summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTian Fang <tfang@fb.com>2015-03-09 22:53:57 -0700
committerTian Fang <tfang@fb.com>2015-03-09 22:53:57 -0700
commit2a51b7c1c2165ddb188c511e192b75f0aa0fbead (patch)
treebb42aeac00a8b986c325cd70d5cca6c13bc0c23a
downloadast2050-yocto-openbmc-2a51b7c1c2165ddb188c511e192b75f0aa0fbead.zip
ast2050-yocto-openbmc-2a51b7c1c2165ddb188c511e192b75f0aa0fbead.tar.gz
Initial open source release of OpenBMC
-rw-r--r--.gitignore0
-rw-r--r--CONTRIBUTING.md37
-rw-r--r--README.md67
-rw-r--r--common/recipes-connectivity/dhcp/dhcp_%.bbappend3
-rw-r--r--common/recipes-connectivity/dhcp/files/dhclient.conf52
-rw-r--r--common/recipes-connectivity/openssh/files/init160
-rw-r--r--common/recipes-connectivity/openssh/openssh_6.5%.bbappend3
-rw-r--r--common/recipes-core/base-files/base-files_%.bbappend30
-rw-r--r--common/recipes-core/i2c-tools/i2c-tools_3.1.1.bb38
-rw-r--r--common/recipes-core/init-ifupdown/files/init92
-rw-r--r--common/recipes-core/init-ifupdown/files/nfsroot2
-rw-r--r--common/recipes-core/init-ifupdown/init-ifupdown_%.bbappend2
-rw-r--r--common/recipes-core/packagegroups/packagegroup-core-tools-debug.bbappend6
-rw-r--r--common/recipes-core/udev/files/init5
-rw-r--r--common/recipes-core/udev/udev_%.bbappend2
-rwxr-xr-xcommon/recipes-core/watchdog-ctrl/watchdog-ctrl/watchdog_ctrl.sh44
-rw-r--r--common/recipes-core/watchdog-ctrl/watchdog-ctrl_0.1.bb33
-rw-r--r--common/recipes-rest/bottle/bottle_0.12.7.bb19
-rw-r--r--conf/layer.conf10
-rw-r--r--meta-aspeed/classes/aspeed_uboot_image.bbclass63
-rw-r--r--meta-aspeed/conf/layer.conf10
-rw-r--r--meta-aspeed/conf/machine/include/ast1250.inc28
-rw-r--r--meta-aspeed/conf/machine/include/ast2400.inc7
-rw-r--r--meta-aspeed/recipes-bsp/u-boot/files/fw_env.config22
-rw-r--r--meta-aspeed/recipes-bsp/u-boot/files/patch-2013.07/0000-u-boot-aspeed-064.patch44658
-rw-r--r--meta-aspeed/recipes-bsp/u-boot/files/patch-2013.07/0001-u-boot-openbmc.patch1580
-rw-r--r--meta-aspeed/recipes-bsp/u-boot/u-boot-fw-utils_2013.07%.bbappend5
-rw-r--r--meta-aspeed/recipes-bsp/u-boot/u-boot_2013.07%.bbappend12
-rw-r--r--meta-aspeed/recipes-core/images/aspeed-dev.inc5
-rw-r--r--meta-aspeed/recipes-core/images/files/aspeed_device_table41
-rw-r--r--meta-aspeed/recipes-kernel/linux/files/patch-2.6.28.9/0000-linux-aspeed-064.patch50917
-rw-r--r--meta-aspeed/recipes-kernel/linux/files/patch-2.6.28.9/0000-linux-openbmc.patch13400
-rw-r--r--meta-aspeed/recipes-kernel/linux/files/patch-2.6.28.9/0001-MTD-fix-m25p80-64-bit-divisions.patch129
-rw-r--r--meta-aspeed/recipes-kernel/linux/files/patch-2.6.28.9/0001-bzip2-lzma-library-support-for-gzip-bzip2-and-lzma-d.patch1876
-rw-r--r--meta-aspeed/recipes-kernel/linux/files/patch-2.6.28.9/0002-bzip2-lzma-config-and-initramfs-support-for-bzip2-lz.patch585
-rw-r--r--meta-aspeed/recipes-kernel/linux/files/patch-2.6.28.9/0005-mtd-Bug-in-m25p80.c-during-whole-chip-erase.patch53
-rw-r--r--meta-aspeed/recipes-kernel/linux/files/patch-2.6.28.9/0006-mtd-fix-timeout-in-M25P80-driver.patch63
-rw-r--r--meta-aspeed/recipes-kernel/linux/files/patch-2.6.28.9/0009-mtd-m25p80-timeout-too-short-for-worst-case-m25p16-d.patch31
-rw-r--r--meta-aspeed/recipes-kernel/linux/files/patch-2.6.28.9/0010-mtd-m25p80-fix-null-pointer-dereference-bug.patch56
-rw-r--r--meta-aspeed/recipes-kernel/linux/files/patch-2.6.28.9/0012-mtd-m25p80-add-support-for-AAI-programming-with-SST-.patch179
-rw-r--r--meta-aspeed/recipes-kernel/linux/files/patch-2.6.28.9/0020-mtd-m25p80-make-command-buffer-DMA-safe.patch56
-rw-r--r--meta-aspeed/recipes-kernel/linux/files/patch-2.6.28.9/0021-mtd-m25p80-Add-support-for-CAT25xxx-serial-EEPROMs.patch327
-rw-r--r--meta-aspeed/recipes-kernel/linux/files/patch-2.6.28.9/0022-mtd-m25p80-Add-support-for-Macronix-MX25L25635E.patch99
-rw-r--r--meta-aspeed/recipes-kernel/linux/files/patch-2.6.28.9/0023-mtd-m25p80-Add-support-for-Macronix-MX25L25655E.patch72
-rw-r--r--meta-aspeed/recipes-kernel/linux/files/patch-2.6.28.9/0024-mtd-m25p80-add-support-for-Micron-N25Q256A.patch35
-rw-r--r--meta-aspeed/recipes-kernel/linux/files/patch-2.6.28.9/0025-mtd-m25p80-add-support-for-Micron-N25Q128.patch28
-rw-r--r--meta-aspeed/recipes-kernel/linux/files/patch-2.6.28.9/0026-mtd-m25p80-modify-info-for-Micron-N25Q128.patch39
-rw-r--r--meta-aspeed/recipes-kernel/linux/files/patch-2.6.28.9/0027-mtd-m25p80-n25q064-is-Micron-not-Intel-Numonyx.patch29
-rw-r--r--meta-aspeed/recipes-kernel/linux/files/patch-2.6.28.9/0028-ipv6-Plug-sk_buff-leak-in-ipv6_rcv-net-ipv6-ip6_inpu.patch52
-rw-r--r--meta-aspeed/recipes-kernel/linux/files/patch-2.6.28.9/README1
-rw-r--r--meta-aspeed/recipes-kernel/linux/linux-aspeed.inc31
-rw-r--r--meta-aspeed/recipes-kernel/linux/linux-aspeed_2.6.28.9.bb39
-rw-r--r--meta-facebook/COPYING340
-rw-r--r--meta-facebook/meta-wedge/conf/bblayers.conf.sample21
-rw-r--r--meta-facebook/meta-wedge/conf/conf-notes.txt2
-rw-r--r--meta-facebook/meta-wedge/conf/layer.conf10
-rw-r--r--meta-facebook/meta-wedge/conf/local.conf.sample140
-rw-r--r--meta-facebook/meta-wedge/conf/machine/wedge.conf7
-rw-r--r--meta-facebook/meta-wedge/recipes-core/busybox/busybox/busybox.cfg18
-rw-r--r--meta-facebook/meta-wedge/recipes-core/busybox/busybox_%.bbappend5
-rw-r--r--meta-facebook/meta-wedge/recipes-core/images/wedge-image.bb1
-rw-r--r--meta-facebook/meta-wedge/recipes-core/images/wedge-image.inc77
-rw-r--r--meta-facebook/meta-wedge/recipes-core/init-ifupdown/files/interfaces11
-rw-r--r--meta-facebook/meta-wedge/recipes-core/init-ifupdown/init-ifupdown_%.bbappend2
-rw-r--r--meta-facebook/meta-wedge/recipes-core/sysvinit/sysvinit-inittab_%.bbappend5
-rw-r--r--meta-facebook/meta-wedge/recipes-kernel/linux/linux-aspeed_2.6%.bbappend5
-rw-r--r--meta-facebook/meta-wedge/recipes-wedge/bitbang/bitbang_0.1.bb22
-rw-r--r--meta-facebook/meta-wedge/recipes-wedge/bitbang/files/src/Makefile13
-rw-r--r--meta-facebook/meta-wedge/recipes-wedge/bitbang/files/src/bitbang.c236
-rw-r--r--meta-facebook/meta-wedge/recipes-wedge/bitbang/files/src/bitbang.h66
-rw-r--r--meta-facebook/meta-wedge/recipes-wedge/bitbang/files/src/gpio.c107
-rw-r--r--meta-facebook/meta-wedge/recipes-wedge/bitbang/files/src/gpio.h42
-rw-r--r--meta-facebook/meta-wedge/recipes-wedge/bitbang/files/src/mdio_bb.c336
-rw-r--r--meta-facebook/meta-wedge/recipes-wedge/bitbang/files/src/spi_bb.c317
-rw-r--r--meta-facebook/meta-wedge/recipes-wedge/fan-ctrl/fan-ctrl/Makefile10
-rw-r--r--meta-facebook/meta-wedge/recipes-wedge/fan-ctrl/fan-ctrl/README5
-rw-r--r--meta-facebook/meta-wedge/recipes-wedge/fan-ctrl/fan-ctrl/fand.cpp851
-rwxr-xr-xmeta-facebook/meta-wedge/recipes-wedge/fan-ctrl/fan-ctrl/get_fan_speed.sh59
-rwxr-xr-xmeta-facebook/meta-wedge/recipes-wedge/fan-ctrl/fan-ctrl/init_pwm.sh71
-rwxr-xr-xmeta-facebook/meta-wedge/recipes-wedge/fan-ctrl/fan-ctrl/set_fan_speed.sh85
-rw-r--r--meta-facebook/meta-wedge/recipes-wedge/fan-ctrl/fan-ctrl/setup-fan.sh23
-rw-r--r--meta-facebook/meta-wedge/recipes-wedge/fan-ctrl/fan-ctrl/watchdog.cpp201
-rw-r--r--meta-facebook/meta-wedge/recipes-wedge/fan-ctrl/fan-ctrl/watchdog.h60
-rw-r--r--meta-facebook/meta-wedge/recipes-wedge/fan-ctrl/fan-ctrl_0.1.bb59
-rw-r--r--meta-facebook/meta-wedge/recipes-wedge/fblibs/files/alert_control/Makefile11
-rw-r--r--meta-facebook/meta-wedge/recipes-wedge/fblibs/files/alert_control/alert_control.c117
-rw-r--r--meta-facebook/meta-wedge/recipes-wedge/fblibs/files/alert_control/alert_control.h64
-rw-r--r--meta-facebook/meta-wedge/recipes-wedge/fblibs/files/ipmi/Makefile11
-rw-r--r--meta-facebook/meta-wedge/recipes-wedge/fblibs/files/ipmi/ipmi.c81
-rw-r--r--meta-facebook/meta-wedge/recipes-wedge/fblibs/files/ipmi/ipmi.h35
-rw-r--r--meta-facebook/meta-wedge/recipes-wedge/fblibs/libalert-control_0.1.bb24
-rw-r--r--meta-facebook/meta-wedge/recipes-wedge/fblibs/libipmi_0.1.bb25
-rw-r--r--meta-facebook/meta-wedge/recipes-wedge/fbutils/fbutils_0.1.bb86
-rw-r--r--meta-facebook/meta-wedge/recipes-wedge/fbutils/files/COPYING340
-rw-r--r--meta-facebook/meta-wedge/recipes-wedge/fbutils/files/ast-functions222
-rw-r--r--meta-facebook/meta-wedge/recipes-wedge/fbutils/files/at93c46.py260
-rwxr-xr-xmeta-facebook/meta-wedge/recipes-wedge/fbutils/files/at93c46_util.py178
-rw-r--r--meta-facebook/meta-wedge/recipes-wedge/fbutils/files/bcm5396.py452
-rw-r--r--meta-facebook/meta-wedge/recipes-wedge/fbutils/files/bcm5396_util.py260
-rw-r--r--meta-facebook/meta-wedge/recipes-wedge/fbutils/files/create_vlan_intf37
-rw-r--r--meta-facebook/meta-wedge/recipes-wedge/fbutils/files/eth0_mac_fixup.sh41
-rwxr-xr-xmeta-facebook/meta-wedge/recipes-wedge/fbutils/files/fcswitcher.sh83
-rwxr-xr-xmeta-facebook/meta-wedge/recipes-wedge/fbutils/files/mdio.py124
-rwxr-xr-xmeta-facebook/meta-wedge/recipes-wedge/fbutils/files/mount_data0.sh61
-rw-r--r--meta-facebook/meta-wedge/recipes-wedge/fbutils/files/post_led.sh105
-rw-r--r--meta-facebook/meta-wedge/recipes-wedge/fbutils/files/power-on.sh72
-rwxr-xr-xmeta-facebook/meta-wedge/recipes-wedge/fbutils/files/power_led.sh49
-rw-r--r--meta-facebook/meta-wedge/recipes-wedge/fbutils/files/rc.early25
-rw-r--r--meta-facebook/meta-wedge/recipes-wedge/fbutils/files/rc.local26
-rw-r--r--meta-facebook/meta-wedge/recipes-wedge/fbutils/files/reset_usb.sh36
-rwxr-xr-xmeta-facebook/meta-wedge/recipes-wedge/fbutils/files/setup-gpio.sh349
-rwxr-xr-xmeta-facebook/meta-wedge/recipes-wedge/fbutils/files/setup_rov.sh99
-rw-r--r--meta-facebook/meta-wedge/recipes-wedge/fbutils/files/setup_switch.py49
-rwxr-xr-xmeta-facebook/meta-wedge/recipes-wedge/fbutils/files/sol.sh37
-rw-r--r--meta-facebook/meta-wedge/recipes-wedge/fbutils/files/src/include/i2c-dev.h362
-rw-r--r--meta-facebook/meta-wedge/recipes-wedge/fbutils/files/src/include/log.h59
-rwxr-xr-xmeta-facebook/meta-wedge/recipes-wedge/fbutils/files/us_console.sh47
-rwxr-xr-xmeta-facebook/meta-wedge/recipes-wedge/fbutils/files/watch-fc.sh34
-rw-r--r--meta-facebook/meta-wedge/recipes-wedge/fbutils/files/wedge_power.sh201
-rw-r--r--meta-facebook/meta-wedge/recipes-wedge/fbutils/files/wedge_us_mac.sh29
-rw-r--r--meta-facebook/meta-wedge/recipes-wedge/ipmid/files/Makefile13
-rw-r--r--meta-facebook/meta-wedge/recipes-wedge/ipmid/files/ipmid.c1490
-rw-r--r--meta-facebook/meta-wedge/recipes-wedge/ipmid/files/platform/fruid.h28
-rw-r--r--meta-facebook/meta-wedge/recipes-wedge/ipmid/files/platform/sdr.c412
-rw-r--r--meta-facebook/meta-wedge/recipes-wedge/ipmid/files/platform/sdr.h132
-rw-r--r--meta-facebook/meta-wedge/recipes-wedge/ipmid/files/platform/sel.c438
-rw-r--r--meta-facebook/meta-wedge/recipes-wedge/ipmid/files/platform/sel.h51
-rw-r--r--meta-facebook/meta-wedge/recipes-wedge/ipmid/files/platform/sensor.h117
-rw-r--r--meta-facebook/meta-wedge/recipes-wedge/ipmid/files/platform/timestamp.c46
-rw-r--r--meta-facebook/meta-wedge/recipes-wedge/ipmid/files/platform/timestamp.h30
-rw-r--r--meta-facebook/meta-wedge/recipes-wedge/ipmid/files/platform/wedge/fruid.c183
-rw-r--r--meta-facebook/meta-wedge/recipes-wedge/ipmid/files/platform/wedge/sensor.c371
-rw-r--r--meta-facebook/meta-wedge/recipes-wedge/ipmid/files/setup-ipmid.sh16
-rw-r--r--meta-facebook/meta-wedge/recipes-wedge/ipmid/ipmid_0.1.bb54
-rw-r--r--meta-facebook/meta-wedge/recipes-wedge/lm_sensors/files/wedge.conf71
-rw-r--r--meta-facebook/meta-wedge/recipes-wedge/lm_sensors/lmsensors_%.bbappend10
-rw-r--r--meta-facebook/meta-wedge/recipes-wedge/oob-nic/oob-nic/src/Makefile13
-rw-r--r--meta-facebook/meta-wedge/recipes-wedge/oob-nic/oob-nic/src/README10
-rw-r--r--meta-facebook/meta-wedge/recipes-wedge/oob-nic/oob-nic/src/etc/oob-nic.sh103
-rw-r--r--meta-facebook/meta-wedge/recipes-wedge/oob-nic/oob-nic/src/hlist.h73
-rw-r--r--meta-facebook/meta-wedge/recipes-wedge/oob-nic/oob-nic/src/i2craw.c245
-rw-r--r--meta-facebook/meta-wedge/recipes-wedge/oob-nic/oob-nic/src/intf.c254
-rw-r--r--meta-facebook/meta-wedge/recipes-wedge/oob-nic/oob-nic/src/intf.h31
-rw-r--r--meta-facebook/meta-wedge/recipes-wedge/oob-nic/oob-nic/src/libnetlink.c717
-rw-r--r--meta-facebook/meta-wedge/recipes-wedge/oob-nic/oob-nic/src/libnetlink.h161
-rw-r--r--meta-facebook/meta-wedge/recipes-wedge/oob-nic/oob-nic/src/ll_map.c225
-rw-r--r--meta-facebook/meta-wedge/recipes-wedge/oob-nic/oob-nic/src/ll_map.h32
-rw-r--r--meta-facebook/meta-wedge/recipes-wedge/oob-nic/oob-nic/src/main.c192
-rw-r--r--meta-facebook/meta-wedge/recipes-wedge/oob-nic/oob-nic/src/nic.c487
-rw-r--r--meta-facebook/meta-wedge/recipes-wedge/oob-nic/oob-nic/src/nic.h44
-rw-r--r--meta-facebook/meta-wedge/recipes-wedge/oob-nic/oob-nic/src/nic_defs.h143
-rw-r--r--meta-facebook/meta-wedge/recipes-wedge/oob-nic/oob-nic_0.1.bb29
-rw-r--r--meta-facebook/meta-wedge/recipes-wedge/po-eeprom/files/Makefile10
-rw-r--r--meta-facebook/meta-wedge/recipes-wedge/po-eeprom/files/po-eeprom.c80
-rw-r--r--meta-facebook/meta-wedge/recipes-wedge/po-eeprom/po-eeprom_0.1.bb25
-rw-r--r--meta-facebook/meta-wedge/recipes-wedge/rackmon/rackmon/Makefile16
-rw-r--r--meta-facebook/meta-wedge/recipes-wedge/rackmon/rackmon/gpiowatch.c93
-rw-r--r--meta-facebook/meta-wedge/recipes-wedge/rackmon/rackmon/modbus.c183
-rw-r--r--meta-facebook/meta-wedge/recipes-wedge/rackmon/rackmon/modbus.h46
-rw-r--r--meta-facebook/meta-wedge/recipes-wedge/rackmon/rackmon/modbuscmd.c163
-rw-r--r--meta-facebook/meta-wedge/recipes-wedge/rackmon/rackmon/modbussim.c183
-rw-r--r--meta-facebook/meta-wedge/recipes-wedge/rackmon/rackmon_0.1.bb48
-rw-r--r--meta-facebook/meta-wedge/recipes-wedge/rest-api/files/rest.py102
-rw-r--r--meta-facebook/meta-wedge/recipes-wedge/rest-api/files/rest_bmc.py67
-rw-r--r--meta-facebook/meta-wedge/recipes-wedge/rest-api/files/rest_fruid.py87
-rw-r--r--meta-facebook/meta-wedge/recipes-wedge/rest-api/files/rest_gpios.py56
-rw-r--r--meta-facebook/meta-wedge/recipes-wedge/rest-api/files/rest_sensors.py50
-rw-r--r--meta-facebook/meta-wedge/recipes-wedge/rest-api/files/rest_server.py68
-rw-r--r--meta-facebook/meta-wedge/recipes-wedge/rest-api/files/setup-rest-api.sh16
-rw-r--r--meta-facebook/meta-wedge/recipes-wedge/rest-api/rest-api_0.1.bb52
-rw-r--r--meta-facebook/meta-wedge/recipes-wedge/sensor-setup/files/sensor-setup.sh52
-rw-r--r--meta-facebook/meta-wedge/recipes-wedge/sensor-setup/sensor-setup_0.1.bb23
-rw-r--r--meta-facebook/meta-wedge/recipes-wedge/sms-kcsd/sms-kcsd/Makefile10
-rw-r--r--meta-facebook/meta-wedge/recipes-wedge/sms-kcsd/sms-kcsd/setup-sms-kcs.sh16
-rw-r--r--meta-facebook/meta-wedge/recipes-wedge/sms-kcsd/sms-kcsd/sms-kcsd.c144
-rw-r--r--meta-facebook/meta-wedge/recipes-wedge/sms-kcsd/sms-kcsd_0.1.bb46
-rwxr-xr-xmeta-facebook/meta-wedge/recipes-wedge/usb-console/files/usbcons.sh80
-rwxr-xr-xmeta-facebook/meta-wedge/recipes-wedge/usb-console/files/usbmon.sh25
-rw-r--r--meta-facebook/meta-wedge/recipes-wedge/usb-console/usb-console_0.1.bb27
-rw-r--r--meta-facebook/meta-wedge/recipes-wedge/wedge-eeprom/files/lib/Makefile11
-rw-r--r--meta-facebook/meta-wedge/recipes-wedge/wedge-eeprom/files/lib/wedge_eeprom.c403
-rw-r--r--meta-facebook/meta-wedge/recipes-wedge/wedge-eeprom/files/lib/wedge_eeprom.h121
-rw-r--r--meta-facebook/meta-wedge/recipes-wedge/wedge-eeprom/files/utils/Makefile10
-rw-r--r--meta-facebook/meta-wedge/recipes-wedge/wedge-eeprom/files/utils/weutil.c74
-rw-r--r--meta-facebook/meta-wedge/recipes-wedge/wedge-eeprom/libwedge-eeprom_0.1.bb26
-rw-r--r--meta-facebook/meta-wedge/recipes-wedge/wedge-eeprom/wedge-eeprom_0.1.bb21
186 files changed, 131086 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/.gitignore
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
new file mode 100644
index 0000000..eb35050
--- /dev/null
+++ b/CONTRIBUTING.md
@@ -0,0 +1,37 @@
+CONTRIBUTING.md
+
+# Contributing to OpenBMC
+We want to make contributing to this project as easy and transparent as
+possible.
+
+## Our Development Process
+We develop on a private branch internally at Facebook. We regularly update
+this github project with the changes from the internal repo. External pull
+requests are cherry-picked into our repo and then pushed back out.
+
+## Pull Requests
+We actively welcome your pull requests.
+1. Fork the repo and create your branch from `master`.
+2. If you've added code that should be tested, add tests
+3. If you've changed APIs, update the documentation.
+4. Ensure the test suite passes.
+5. Make sure your code lints.
+6. If you haven't already, complete the Contributor License Agreement ("CLA").
+
+## Contributor License Agreement ("CLA")
+In order to accept your pull request, we need you to submit a CLA. You only need
+to do this once to work on any of Facebook's open source projects.
+
+Complete your CLA here: <https://code.facebook.com/cla>
+
+## Issues
+We use GitHub issues to track public bugs. Please ensure your description is
+clear and has sufficient instructions to be able to reproduce the issue.
+
+Facebook has a [bounty program](https://www.facebook.com/whitehat/) for the safe
+disclosure of security bugs. In those cases, please go through the process
+outlined on that page and do not file a public issue.
+
+## Coding Style
+* 2 spaces for indentation rather than tabs
+* 80 character line length
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..9740139
--- /dev/null
+++ b/README.md
@@ -0,0 +1,67 @@
+# OpenBMC
+
+OpenBMC is an open software framework to build a complete Linux image for a Board Management Controller (BMC).
+
+OpenBMC uses [Yocto](https://www.yoctoproject.org) as the underlying building framework.
+
+## Contents
+
+This repository includes 3 set of layers:
+
+* **OpenBMC Common Layer** - Common packages and recipes can be used in different types of BMC.
+* **BMC System-on-Chip (SoC) Layer** - SoC specific drivers and tools. This layer includes the bootloader (u-boot) and the Linux kernel. Both the bootloader and Linux kernel shall include the hardware drivers specific for the SoC.
+* **Board Specific Layer** - Board specific drivers, configurations, and tools. This layer defines how to configure the image. It also defines what packages to be installed for an OpenBMC image for this board. Any board specific initialization and tools are also included in this layer.
+
+## File structure
+
+Yocto naming pattern is used in this repository. `meta-layer` is used to name a layer. And `recipe-abc` is used to name a recipe.
+
+The recipes for OpenBMC common layer should be in `meta-openbmc/common`.
+
+BMC SoC layer and board specific layer are grouped together based on the vendor/manufacturer name. For example, all Facebook boards specific code should be in `meta-openbmc/meta-facebook`. And `meta-openbmc/meta-aspeed` includes source code for Aspeed SoCs.
+
+## How to build
+
+* Step 0 - Set up the build environment based on the Yocto project [document](http://www.yoctoproject.org/docs/1.6.1/yocto-project-qs/yocto-project-qs.html).
+
+* Step 1 - Clone Yocto repository.
+```
+$ git clone -b daisy https://git.yoctoproject.org/git/poky
+```
+
+* Step 2 - Clone Openembedded and OpenBMC repositories, in the new created `poky` directory,
+```
+$ cd poky
+$ git clone -b daisy https://github.com/openembedded/meta-openembedded.git
+$ git clone git@github.com:facebook/openbmc.git meta-openbmc
+```
+
+* Step 3 - Initialize a build directory. In `poky` directory,
+
+```
+$ export TEMPLATECONF=meta-openbmc/meta-facebook/meta-wedge/conf
+$ source oe-init-build-env
+```
+
+After this step, you will be dropped into a build directory, `poky/build`.
+
+* Step 4 - Start the build within the build directory, `poky/build`.
+
+```
+$ bitbake wedge-image
+```
+
+The build process automatically fetches all necessary packages and build the complete image. The final build results are in `poky/build/tmp/deploy/images/wedge`.
+
+* u-boot.bin - This is the u-boot image for the board.
+* uImage - This the Linux kernel for the board.
+* wedge-image-wedge.cpio.lzma.u-boot - This is the rootfs for the board
+* flash-wedge - This is the complete flash image including u-boot, kernel, and the rootfs.
+
+# How can I contribute
+
+If you have an application that can be used by different BMCs, you can contribute your application to the OpenBMC common layer.
+
+If you are a BMC SoC vendor, you can contribute your SoC specific drivers to the BMC SoC layer.
+
+If you are a board vendor, you can contribute your board specific configurations and tools to the Board specific layer. If the board uses a new BMC SoC that is not part of the BMC SoC layer, the SoC specific driver contribution to the BMC SoC layer is also required.
diff --git a/common/recipes-connectivity/dhcp/dhcp_%.bbappend b/common/recipes-connectivity/dhcp/dhcp_%.bbappend
new file mode 100644
index 0000000..6dc6962
--- /dev/null
+++ b/common/recipes-connectivity/dhcp/dhcp_%.bbappend
@@ -0,0 +1,3 @@
+FILESEXTRAPATHS_prepend := "${THISDIR}/files:"
+
+SRC_URI += "file://dhclient.conf"
diff --git a/common/recipes-connectivity/dhcp/files/dhclient.conf b/common/recipes-connectivity/dhcp/files/dhclient.conf
new file mode 100644
index 0000000..8dea59b
--- /dev/null
+++ b/common/recipes-connectivity/dhcp/files/dhclient.conf
@@ -0,0 +1,52 @@
+# Configuration file for /sbin/dhclient, which is included in Debian's
+# dhcp3-client package.
+#
+# This is a sample configuration file for dhclient. See dhclient.conf's
+# man page for more information about the syntax of this file
+# and a more comprehensive list of the parameters understood by
+# dhclient.
+#
+# Normally, if the DHCP server provides reasonable information and does
+# not leave anything out (like the domain name, for example), then
+# few changes must be made to this file, if any.
+#
+
+#send host-name "andare.fugue.com";
+#send dhcp-client-identifier 1:0:a0:24:ab:fb:9c;
+#send dhcp-lease-time 3600;
+#supersede domain-name "fugue.com home.vix.com";
+#prepend domain-name-servers 127.0.0.1;
+request subnet-mask, broadcast-address, time-offset, routers,
+ domain-name, domain-name-servers, host-name,
+ netbios-name-servers, netbios-scope;
+#require subnet-mask, domain-name-servers;
+# 25 seconds (default 300s) to get the lease
+timeout 25;
+# if not, retry in 55 seconds (default 5m)
+retry 55;
+#reboot 10;
+#select-timeout 5;
+#initial-interval 2;
+#script "/etc/dhcp3/dhclient-script";
+#media "-link0 -link1 -link2", "link0 link1";
+#reject 192.33.137.209;
+
+#alias {
+# interface "eth0";
+# fixed-address 192.5.5.213;
+# option subnet-mask 255.255.255.255;
+#}
+
+#lease {
+# interface "eth0";
+# fixed-address 192.33.137.200;
+# medium "link0 link1";
+# option host-name "andare.swiftmedia.com";
+# option subnet-mask 255.255.255.0;
+# option broadcast-address 192.33.137.255;
+# option routers 192.33.137.250;
+# option domain-name-servers 127.0.0.1;
+# renew 2 2000/1/12 00:00:01;
+# rebind 2 2000/1/12 00:00:01;
+# expire 2 2000/1/12 00:00:01;
+#}
diff --git a/common/recipes-connectivity/openssh/files/init b/common/recipes-connectivity/openssh/files/init
new file mode 100644
index 0000000..e7484a7
--- /dev/null
+++ b/common/recipes-connectivity/openssh/files/init
@@ -0,0 +1,160 @@
+#! /bin/sh
+set -e
+
+# source function library
+. /etc/init.d/functions
+
+# /etc/init.d/ssh: start and stop the OpenBSD "secure shell" daemon
+
+test -x /usr/sbin/sshd || exit 0
+( /usr/sbin/sshd -\? 2>&1 | grep -q OpenSSH ) 2>/dev/null || exit 0
+
+# /etc/default/ssh may set SYSCONFDIR and SSHD_OPTS
+if test -f /etc/default/ssh; then
+ . /etc/default/ssh
+fi
+
+[ -z "$SYSCONFDIR" ] && SYSCONFDIR=/etc/ssh
+mkdir -p $SYSCONFDIR
+
+HOST_KEY_RSA=$SYSCONFDIR/ssh_host_rsa_key
+HOST_KEY_DSA=$SYSCONFDIR/ssh_host_dsa_key
+HOST_KEY_ECDSA=$SYSCONFDIR/ssh_host_ecdsa_key
+HOST_KEY_ED25519=$SYSCONFDIR/ssh_host_ed25519_key
+
+check_for_no_start() {
+ # forget it if we're trying to start, and /etc/ssh/sshd_not_to_be_run exists
+ if [ -e $SYSCONFDIR/sshd_not_to_be_run ]; then
+ echo "OpenBSD Secure Shell server not in use ($SYSCONFDIR/sshd_not_to_be_run)"
+ exit 0
+ fi
+}
+
+check_privsep_dir() {
+ # Create the PrivSep empty dir if necessary
+ if [ ! -d /var/run/sshd ]; then
+ mkdir /var/run/sshd
+ chmod 0755 /var/run/sshd
+ fi
+}
+
+check_config() {
+ /usr/sbin/sshd -t || exit 1
+}
+
+KEYFILES_DIR="/mnt/data/etc/ssh"
+
+prepare_keyfiles_dir() {
+ if [ ! -d "$KEYFILES_DIR" ]; then
+ # remove it in case someone create a file with the same name
+ rm -rf "$KEYFILES_DIR" > /dev/null 2>&1
+ mkdir -p "$KEYFILES_DIR"
+ fi
+}
+
+get_keyfile() {
+ filename=$(basename $1)
+ if [ -f "$KEYFILES_DIR/$filename" ]; then
+ rm -rf $1 > /dev/null 2>&1
+ ln -s "$KEYFILES_DIR/$filename" $1
+ fi
+}
+
+save_keyfile() {
+ filename=$(basename $1)
+ if [ -d "$KEYFILES_DIR" ]; then
+ mv -f $1 "$KEYFILES_DIR/$filename" > /dev/null 2>&1
+ ln -s "$KEYFILES_DIR/$filename" $1
+ fi
+}
+
+check_keys() {
+ # prepare for the permanent storage
+ prepare_keyfiles_dir
+ # create keys if necessary
+ get_keyfile $HOST_KEY_RSA
+ get_keyfile $HOST_KEY_RSA.pub
+ if [ ! -f $HOST_KEY_RSA ]; then
+ echo " generating ssh RSA key..."
+ ssh-keygen -q -f $HOST_KEY_RSA -N '' -t rsa
+ save_keyfile $HOST_KEY_RSA
+ save_keyfile $HOST_KEY_RSA.pub
+ fi
+
+ get_keyfile $HOST_KEY_ECDSA
+ get_keyfile $HOST_KEY_ECDSA.pub
+ if [ ! -f $HOST_KEY_ECDSA ]; then
+ echo " generating ssh ECDSA key..."
+ ssh-keygen -q -f $HOST_KEY_ECDSA -N '' -t ecdsa
+ save_keyfile $HOST_KEY_ECDSA
+ save_keyfile $HOST_KEY_ECDSA.pub
+ fi
+
+ get_keyfile $HOST_KEY_DSA
+ get_keyfile $HOST_KEY_DSA.pub
+ if [ ! -f $HOST_KEY_DSA ]; then
+ echo " generating ssh DSA key..."
+ ssh-keygen -q -f $HOST_KEY_DSA -N '' -t dsa
+ save_keyfile $HOST_KEY_DSA
+ save_keyfile $HOST_KEY_DSA.pub
+ fi
+
+ get_keyfile $HOST_KEY_ED25519
+ get_keyfile $HOST_KEY_ED25519.pub
+ if [ ! -f $HOST_KEY_ED25519 ]; then
+ echo " generating ssh ED25519 key..."
+ ssh-keygen -q -f $HOST_KEY_ED25519 -N '' -t ed25519
+ save_keyfile $HOST_KEY_ED25519
+ save_keyfile $HOST_KEY_ED25519.pub
+ fi
+}
+
+export PATH="${PATH:+$PATH:}/usr/sbin:/sbin"
+
+case "$1" in
+ start)
+ check_for_no_start
+ echo "Starting OpenBSD Secure Shell server: sshd"
+ check_keys
+ check_privsep_dir
+ start-stop-daemon -S -x /usr/sbin/sshd -- $SSHD_OPTS
+ echo "done."
+ ;;
+ stop)
+ echo -n "Stopping OpenBSD Secure Shell server: sshd"
+ start-stop-daemon -K -x /usr/sbin/sshd
+ echo "."
+ ;;
+
+ reload|force-reload)
+ check_for_no_start
+ check_keys
+ check_config
+ echo -n "Reloading OpenBSD Secure Shell server's configuration"
+ start-stop-daemon -K -s 1 -x /usr/sbin/sshd
+ echo "."
+ ;;
+
+ restart)
+ check_keys
+ check_config
+ echo -n "Restarting OpenBSD Secure Shell server: sshd"
+ start-stop-daemon -K --oknodo -x /usr/sbin/sshd
+ check_for_no_start
+ check_privsep_dir
+ sleep 2
+ start-stop-daemon -S -x /usr/sbin/sshd -- $SSHD_OPTS
+ echo "."
+ ;;
+
+ status)
+ status /usr/sbin/sshd
+ exit $?
+ ;;
+
+ *)
+ echo "Usage: /etc/init.d/ssh {start|stop|status|reload|force-reload|restart}"
+ exit 1
+esac
+
+exit 0
diff --git a/common/recipes-connectivity/openssh/openssh_6.5%.bbappend b/common/recipes-connectivity/openssh/openssh_6.5%.bbappend
new file mode 100644
index 0000000..60b164b
--- /dev/null
+++ b/common/recipes-connectivity/openssh/openssh_6.5%.bbappend
@@ -0,0 +1,3 @@
+FILESEXTRAPATHS_prepend := "${THISDIR}/files:"
+
+SRC_URI += "file://init"
diff --git a/common/recipes-core/base-files/base-files_%.bbappend b/common/recipes-core/base-files/base-files_%.bbappend
new file mode 100644
index 0000000..340ad2c
--- /dev/null
+++ b/common/recipes-core/base-files/base-files_%.bbappend
@@ -0,0 +1,30 @@
+BASEFILESISSUEINSTALL = "do_install_bmc_issue"
+
+DISTRO_HOSTNAME = "bmc"
+
+do_install_bmc_issue () {
+ if [ "${DISTRO_HOSTNAME}" != "" ]; then
+ echo ${DISTRO_HOSTNAME} > ${D}${sysconfdir}/hostname
+ else
+ echo ${MACHINE} > ${D}${sysconfdir}/hostname
+ fi
+
+ # found out the source dir
+ dir=$(pwd)
+ while [ -n "$dir" -a "$dir" != "/" -a ! -d "$dir/meta-openbmc/.git" ]; do
+ dir=$(dirname $dir)
+ done
+
+ if [ -d "$dir/meta-aspeed/.git" ]; then
+ srcdir="$dir/meta-aspeed"
+ srcdir_git="${srcdir}/.git"
+ version=$(git --git-dir=${srcdir_git} --work-tree=${srcdir} describe --dirty 2> /dev/null)
+ else
+ version=""
+ fi
+
+ echo "Open BMC Release ${version} \\n \\l" > ${D}${sysconfdir}/issue
+ echo >> ${D}${sysconfdir}/issue
+ echo "Open BMC Release ${version} %h" > ${D}${sysconfdir}/issue.net
+ echo >> ${D}${sysconfdir}/issue.net
+}
diff --git a/common/recipes-core/i2c-tools/i2c-tools_3.1.1.bb b/common/recipes-core/i2c-tools/i2c-tools_3.1.1.bb
new file mode 100644
index 0000000..6743e3f
--- /dev/null
+++ b/common/recipes-core/i2c-tools/i2c-tools_3.1.1.bb
@@ -0,0 +1,38 @@
+DESCRIPTION = "i2c tools"
+SECTION = "base"
+LICENSE = "GPLv2"
+LIC_FILES_CHKSUM = "file://COPYING;md5=751419260aa954499f7abaabaa882bbe"
+
+SRCREV = "6235"
+SRC_URI = "svn://lm-sensors.org/svn/i2c-tools/branches/;protocol=http;module=i2c-tools-3.1 \
+ "
+
+S = "${WORKDIR}/i2c-tools-3.1"
+
+i2ctools = "i2cdetect \
+ i2cdump \
+ i2cget \
+ i2cset \
+ "
+
+eepromtools = "eepromer \
+ eeprom \
+ eeprog \
+ "
+
+do_compile() {
+ make -C eepromer
+ make
+}
+
+do_install() {
+ mkdir -p ${D}/${bindir}
+ for f in ${i2ctools}; do
+ install -m 755 tools/$f ${D}/${bindir}/$f
+ done
+ for f in ${eepromtools}; do
+ install -m 755 eepromer/$f ${D}/${bindir}/$f
+ done
+}
+
+FILES_${PN} = "${bindir}"
diff --git a/common/recipes-core/init-ifupdown/files/init b/common/recipes-core/init-ifupdown/files/init
new file mode 100644
index 0000000..8e15896
--- /dev/null
+++ b/common/recipes-core/init-ifupdown/files/init
@@ -0,0 +1,92 @@
+#!/bin/sh -e
+### BEGIN INIT INFO
+# Provides: networking
+# Required-Start: mountvirtfs $local_fs
+# Required-Stop: $local_fs
+# Should-Start: ifupdown
+# Should-Stop: ifupdown
+# Default-Start: S
+# Default-Stop: 0 6
+# Short-Description: Raise network interfaces.
+### END INIT INFO
+
+PATH="/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin"
+
+[ -x /sbin/ifup ] || exit 0
+
+check_network_file_systems() {
+ [ -e /proc/mounts ] || return 0
+
+ if [ -e /etc/iscsi/iscsi.initramfs ]; then
+ echo "not deconfiguring network interfaces: iSCSI root is mounted."
+ exit 0
+ fi
+
+ exec 9<&0 < /proc/mounts
+ while read DEV MTPT FSTYPE REST; do
+ case $DEV in
+ /dev/nbd*|/dev/nd[a-z]*|/dev/etherd/e*)
+ echo "not deconfiguring network interfaces: network devices still mounted."
+ exit 0
+ ;;
+ esac
+ case $FSTYPE in
+ nfs|nfs4|smbfs|ncp|ncpfs|cifs|coda|ocfs2|gfs|pvfs|pvfs2|fuse.httpfs|fuse.curlftpfs)
+ echo "not deconfiguring network interfaces: network file systems still mounted."
+ exit 0
+ ;;
+ esac
+ done
+ exec 0<&9 9<&-
+}
+
+check_network_swap() {
+ [ -e /proc/swaps ] || return 0
+
+ exec 9<&0 < /proc/swaps
+ while read DEV MTPT FSTYPE REST; do
+ case $DEV in
+ /dev/nbd*|/dev/nd[a-z]*|/dev/etherd/e*)
+ echo "not deconfiguring network interfaces: network swap still mounted."
+ exit 0
+ ;;
+ esac
+ done
+ exec 0<&9 9<&-
+}
+
+case "$1" in
+start)
+ echo -n "Configuring network interfaces... "
+ sysctl -e -p /etc/sysctl.conf >/dev/null 2>&1
+ ifup -a
+ echo "done."
+ ;;
+
+stop)
+ # tfang, disabled them because 'exec < /proc/mounts' hangs
+ # could be kernel issue as regular file is ok
+ #check_network_file_systems
+ #check_network_swap
+
+ echo -n "Deconfiguring network interfaces... "
+ ifdown -a
+ echo "done."
+ ;;
+
+force-reload|restart)
+ echo "Running $0 $1 is deprecated because it may not enable again some interfaces"
+ echo "Reconfiguring network interfaces... "
+ ifdown -a || true
+ ifup -a
+ echo "done."
+ ;;
+
+*)
+ echo "Usage: /etc/init.d/networking {start|stop}"
+ exit 1
+ ;;
+esac
+
+exit 0
+
diff --git a/common/recipes-core/init-ifupdown/files/nfsroot b/common/recipes-core/init-ifupdown/files/nfsroot
new file mode 100644
index 0000000..b667cbb
--- /dev/null
+++ b/common/recipes-core/init-ifupdown/files/nfsroot
@@ -0,0 +1,2 @@
+exit 0
+
diff --git a/common/recipes-core/init-ifupdown/init-ifupdown_%.bbappend b/common/recipes-core/init-ifupdown/init-ifupdown_%.bbappend
new file mode 100644
index 0000000..7d74521
--- /dev/null
+++ b/common/recipes-core/init-ifupdown/init-ifupdown_%.bbappend
@@ -0,0 +1,2 @@
+
+FILESEXTRAPATHS_prepend := "${THISDIR}/files:"
diff --git a/common/recipes-core/packagegroups/packagegroup-core-tools-debug.bbappend b/common/recipes-core/packagegroups/packagegroup-core-tools-debug.bbappend
new file mode 100644
index 0000000..65f85de
--- /dev/null
+++ b/common/recipes-core/packagegroups/packagegroup-core-tools-debug.bbappend
@@ -0,0 +1,6 @@
+# eglibc-mtrace is a Perl script analyzing the mtrace output data.
+# It is small but depends on perl, which increases image size by 1.35M.
+# Remove it explicitly. When we need to use it, we can always copy the
+# mtrace results out and run mtrace utility outside of BMC.
+MTRACE = ""
+MTRACE_libc-glibc = ""
diff --git a/common/recipes-core/udev/files/init b/common/recipes-core/udev/files/init
new file mode 100644
index 0000000..a428665
--- /dev/null
+++ b/common/recipes-core/udev/files/init
@@ -0,0 +1,5 @@
+#!/bin/sh
+
+echo "UDEV: no devtmpfs support. Skip udev"
+
+exit 0
diff --git a/common/recipes-core/udev/udev_%.bbappend b/common/recipes-core/udev/udev_%.bbappend
new file mode 100644
index 0000000..7d74521
--- /dev/null
+++ b/common/recipes-core/udev/udev_%.bbappend
@@ -0,0 +1,2 @@
+
+FILESEXTRAPATHS_prepend := "${THISDIR}/files:"
diff --git a/common/recipes-core/watchdog-ctrl/watchdog-ctrl/watchdog_ctrl.sh b/common/recipes-core/watchdog-ctrl/watchdog-ctrl/watchdog_ctrl.sh
new file mode 100755
index 0000000..9c4f2cc
--- /dev/null
+++ b/common/recipes-core/watchdog-ctrl/watchdog-ctrl/watchdog_ctrl.sh
@@ -0,0 +1,44 @@
+#!/bin/sh
+#
+# Copyright 2004-present Facebook. All Rights Reserved.
+#
+# This program file is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by the
+# Free Software Foundation; version 2 of the License.
+#
+# This program is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+# for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program in a file named COPYING; if not, write to the
+# Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor,
+# Boston, MA 02110-1301 USA
+#
+usage() {
+ echo "Usage: $0 <on | off>" >&2
+}
+
+set -e
+
+if [ "$#" -ne 1 ]; then
+ usage
+ exit 1
+fi
+
+case "$1" in
+"on")
+ echo "Enabling watchdog. Note: this does not start the watchdog!"
+ echo "x" > /dev/watchdog
+ ;;
+"off")
+ echo "Disabling watchdog."
+ echo "X" > /dev/watchdog
+ ;;
+*)
+ usage
+ exit 1
+ ;;
+esac
diff --git a/common/recipes-core/watchdog-ctrl/watchdog-ctrl_0.1.bb b/common/recipes-core/watchdog-ctrl/watchdog-ctrl_0.1.bb
new file mode 100644
index 0000000..00cf0f9
--- /dev/null
+++ b/common/recipes-core/watchdog-ctrl/watchdog-ctrl_0.1.bb
@@ -0,0 +1,33 @@
+# Copyright 2014-present Facebook. All Rights Reserved.
+SUMMARY = "Watchdog control utilities."
+DESCRIPTION = "The utilities to control system watchdog."
+SECTION = "base"
+PR = "r1"
+LICENSE = "GPLv2"
+LIC_FILES_CHKSUM = "file://watchdog_ctrl.sh;beginline=5;endline=18;md5=0b1ee7d6f844d472fa306b2fee2167e0"
+
+SRC_URI = "file://watchdog_ctrl.sh \
+ "
+
+S = "${WORKDIR}"
+
+binfiles = "watchdog_ctrl.sh"
+
+pkgdir = "watchdog_ctrl"
+
+do_install() {
+ dst="${D}/usr/local/fbpackages/${pkgdir}"
+ bin="${D}/usr/local/bin"
+ install -d $dst
+ install -d $bin
+ for f in ${binfiles}; do
+ install -m 755 $f ${dst}/${f}
+ ln -s ../fbpackages/${pkgdir}/${f} ${bin}/${f}
+ done
+}
+
+FBPACKAGEDIR = "${prefix}/local/fbpackages"
+
+FILES_${PN} = "${FBPACKAGEDIR}/watchdog_ctrl ${prefix}/local/bin ${sysconfdir} "
+INHIBIT_PACKAGE_DEBUG_SPLIT = "1"
+INHIBIT_PACKAGE_STRIP = "1"
diff --git a/common/recipes-rest/bottle/bottle_0.12.7.bb b/common/recipes-rest/bottle/bottle_0.12.7.bb
new file mode 100644
index 0000000..25bd547
--- /dev/null
+++ b/common/recipes-rest/bottle/bottle_0.12.7.bb
@@ -0,0 +1,19 @@
+DESCRIPTION = "Bottle Web Framework"
+SECTION = "base"
+LICENSE = "MIT"
+LIC_FILES_CHKSUM = "file://bottle.py;beginline=1;endline=14;md5=15d806194a048a43e3a7f1d4c7574fe6"
+
+SRC_URI = "https://pypi.python.org/packages/source/b/bottle/${PN}-${PV}.tar.gz"
+SRC_URI[md5sum] = "ed0b83c9dbbdbde784e7c652d61c59f4"
+SRC_URI[sha256sum] = "e3ea2191f06ca51af45bf6ca41ed2d1b2d809ceda0876466879fe205be7b2073"
+
+S = "${WORKDIR}/${PN}-${PV}"
+
+dst="/usr/lib/python2.7"
+
+do_install() {
+ mkdir -p ${D}/${dst}
+ install -m 755 bottle.py ${D}/${dst}
+}
+
+FILES_${PN} = "${dst}"
diff --git a/conf/layer.conf b/conf/layer.conf
new file mode 100644
index 0000000..3084e34
--- /dev/null
+++ b/conf/layer.conf
@@ -0,0 +1,10 @@
+# We have a conf and classes directory, add to BBPATH
+BBPATH .= ":${LAYERDIR}"
+
+# We have common/recipes-* directories, add to BBFILES
+BBFILES += "${LAYERDIR}/common/recipes-*/*/*.bb \
+ ${LAYERDIR}/common/recipes-*/*/*.bbappend"
+
+BBFILE_COLLECTIONS += "openbmc"
+BBFILE_PATTERN_openbmc = "^${LAYERDIR}/"
+BBFILE_PRIORITY_openbmc = "6"
diff --git a/meta-aspeed/classes/aspeed_uboot_image.bbclass b/meta-aspeed/classes/aspeed_uboot_image.bbclass
new file mode 100644
index 0000000..b22b0b8
--- /dev/null
+++ b/meta-aspeed/classes/aspeed_uboot_image.bbclass
@@ -0,0 +1,63 @@
+inherit image_types_uboot
+
+# oe_mkimage() was defined in image_types_uboot. Howver, it does not consider
+# the image load address and entry point. Override it here.
+
+oe_mkimage () {
+ mkimage -A ${UBOOT_ARCH} -O linux -T ramdisk -C $2 -n ${IMAGE_NAME} \
+ -a ${UBOOT_IMAGE_LOADADDRESS} -e ${UBOOT_IMAGE_ENTRYPOINT} \
+ -d ${DEPLOY_DIR_IMAGE}/$1 ${DEPLOY_DIR_IMAGE}/$1.u-boot
+}
+
+UBOOT_IMAGE_ENTRYPOINT ?= "0x42000000"
+UBOOT_IMAGE_LOADADDRESS ?= "${UBOOT_IMAGE_ENTRYPOINT}"
+
+# 24M
+IMAGE_ROOTFS_SIZE = "24576"
+# and don't put overhead behind my back
+IMAGE_OVERHEAD_FACTOR = "1"
+
+IMAGE_PREPROCESS_COMMAND += " generate_data_mount_dir ; "
+IMAGE_POSTPROCESS_COMMAND += " flash_image_generate ; "
+
+FLASH_IMAGE_NAME ?= "flash-${MACHINE}-${DATETIME}"
+FLASH_IMAGE_LINK ?= "flash-${MACHINE}"
+# 16M
+FLASH_SIZE ?= "16384"
+FLASH_UBOOT_OFFSET ?= "0"
+# 512k
+FLASH_KERNEL_OFFSET ?= "512"
+# 3M
+FLASH_ROOTFS_OFFSET ?= "3072"
+
+flash_image_generate() {
+ kernelfile="${DEPLOY_DIR_IMAGE}/${KERNEL_IMAGETYPE}"
+ ubootfile="${DEPLOY_DIR_IMAGE}/u-boot.${UBOOT_SUFFIX}"
+ # rootfs has to match the type defined in IMAGE_FSTYPES"
+ rootfs="${DEPLOY_DIR_IMAGE}/${IMAGE_LINK_NAME}.cpio.lzma.u-boot"
+ if [ ! -f $kernelfile ]; then
+ echo "Kernel file ${kernelfile} does not exist"
+ return 1
+ fi
+ if [ ! -f $ubootfile ]; then
+ echo "U-boot file ${ubootfile} does not exist"
+ return 1
+ fi
+ if [ ! -f $rootfs ]; then
+ echo "Rootfs file ${rootfs} does not exist"
+ return 1
+ fi
+ dst="${DEPLOY_DIR_IMAGE}/${FLASH_IMAGE_NAME}"
+ rm -rf $dst
+ dd if=/dev/zero of=${dst} bs=1k count=${FLASH_SIZE}
+ dd if=${ubootfile} of=${dst} bs=1k seek=${FLASH_UBOOT_OFFSET}
+ dd if=${kernelfile} of=${dst} bs=1k seek=${FLASH_KERNEL_OFFSET}
+ dd if=${rootfs} of=${dst} bs=1k seek=${FLASH_ROOTFS_OFFSET}
+ dstlink="${DEPLOY_DIR_IMAGE}/${FLASH_IMAGE_LINK}"
+ rm -rf $dstlink
+ ln -sf ${FLASH_IMAGE_NAME} $dstlink
+}
+
+generate_data_mount_dir() {
+ mkdir -p "${IMAGE_ROOTFS}/mnt/data"
+}
diff --git a/meta-aspeed/conf/layer.conf b/meta-aspeed/conf/layer.conf
new file mode 100644
index 0000000..2418d8e
--- /dev/null
+++ b/meta-aspeed/conf/layer.conf
@@ -0,0 +1,10 @@
+# We have a conf and classes directory, add to BBPATH
+BBPATH .= ":${LAYERDIR}"
+
+# We have recipes-* directories, add to BBFILES
+BBFILES += "${LAYERDIR}/recipes-*/*/*.bb \
+ ${LAYERDIR}/recipes-*/*/*.bbappend"
+
+BBFILE_COLLECTIONS += "aspeed"
+BBFILE_PATTERN_aspeed = "^${LAYERDIR}/"
+BBFILE_PRIORITY_aspeed = "7"
diff --git a/meta-aspeed/conf/machine/include/ast1250.inc b/meta-aspeed/conf/machine/include/ast1250.inc
new file mode 100644
index 0000000..099fdb0
--- /dev/null
+++ b/meta-aspeed/conf/machine/include/ast1250.inc
@@ -0,0 +1,28 @@
+#@TYPE: Machine
+#@NAME: aspeed ast1250
+#@DESCRIPTION: Machine configuration for aspeed ast1250 SoC
+
+# Ship all kernel modules by default
+MACHINE_EXTRA_RRECOMMENDS = "kernel-modules"
+
+# Allow for MMC booting (required by the NAND-less Beagleboard XM)
+EXTRA_IMAGEDEPENDS += "u-boot"
+
+# Uncomment the following line to enable the hard floating point abi. Note that
+# this breaks some binary libraries and 3D (neither of which ship with
+# meta-yocto). For maximum compatibility, leave this disabled.
+DEFAULTTUNE ?= "arm926ejs"
+require conf/machine/include/tune-arm926ejs.inc
+
+PREFERRED_PROVIDER_virtual/kernel ?= "linux-aspeed"
+PREFERRED_VERSION_linux-aspeed ?= "2.6.28%"
+
+KERNEL_IMAGETYPE ?= "uImage"
+KERNEL_EXTRA_ARGS ?= "UIMAGE_LOADADDR=0x40008000"
+
+UBOOT_SUFFIX ?= "bin"
+UBOOT_ENTRYPOINT ?= "0x40008000"
+UBOOT_LOADADDRESS ?= "0x40008000"
+UBOOT_MACHINE ?= "ast1250_config"
+
+MACHINE_FEATURES = "usbgadget usbhost vfat ext2 serial"
diff --git a/meta-aspeed/conf/machine/include/ast2400.inc b/meta-aspeed/conf/machine/include/ast2400.inc
new file mode 100644
index 0000000..4ea982b
--- /dev/null
+++ b/meta-aspeed/conf/machine/include/ast2400.inc
@@ -0,0 +1,7 @@
+#@TYPE: Machine
+#@NAME: aspeed ast2400
+#@DESCRIPTION: Machine configuration for aspeed ast2400 SoC
+
+UBOOT_MACHINE ?= "ast2400_config"
+
+require conf/machine/include/ast1250.inc \ No newline at end of file
diff --git a/meta-aspeed/recipes-bsp/u-boot/files/fw_env.config b/meta-aspeed/recipes-bsp/u-boot/files/fw_env.config
new file mode 100644
index 0000000..9cb3ad2
--- /dev/null
+++ b/meta-aspeed/recipes-bsp/u-boot/files/fw_env.config
@@ -0,0 +1,22 @@
+# Configuration file for fw_(printenv/setenv) utility.
+# Up to two entries are valid, in this case the redundant
+# environment sector is assumed present.
+# Notice, that the "Number of sectors" is ignored on NOR and SPI-dataflash.
+# Futhermore, if the Flash sector size is ommitted, this value is assumed to
+# be the same as the Environment size, which is valid for NOR and SPI-dataflash
+
+# NOR example
+# MTD device name Device offset Env. size Flash sector size Number of sectors
+/dev/mtd1 0x0000 0x20000 0x20000
+#/dev/mtd2 0x0000 0x4000 0x4000
+
+# MTD SPI-dataflash example
+# MTD device name Device offset Env. size Flash sector size Number of sectors
+#/dev/mtd5 0x4200 0x4200
+#/dev/mtd6 0x4200 0x4200
+
+# NAND example
+#/dev/mtd0 0x4000 0x4000 0x20000 2
+
+# Block device example
+#/dev/mmcblk0 0xc0000 0x20000
diff --git a/meta-aspeed/recipes-bsp/u-boot/files/patch-2013.07/0000-u-boot-aspeed-064.patch b/meta-aspeed/recipes-bsp/u-boot/files/patch-2013.07/0000-u-boot-aspeed-064.patch
new file mode 100644
index 0000000..8ebfb96
--- /dev/null
+++ b/meta-aspeed/recipes-bsp/u-boot/files/patch-2013.07/0000-u-boot-aspeed-064.patch
@@ -0,0 +1,44658 @@
+diff --git a/arch/arm/cpu/arm926ejs/aspeed/COMMINF.H b/arch/arm/cpu/arm926ejs/aspeed/COMMINF.H
+new file mode 100644
+index 0000000..44b7540
+--- /dev/null
++++ b/arch/arm/cpu/arm926ejs/aspeed/COMMINF.H
+@@ -0,0 +1,641 @@
++/*
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++ */
++#ifndef COMMINF_H
++#define COMMINF_H
++
++#include "SWFUNC.H"
++
++#if defined(LinuxAP)
++#endif
++#ifdef SLT_UBOOT
++#endif
++#ifdef SLT_DOS
++ #include <stdio.h>
++ #include <time.h>
++ #include <dos.h> // For delay()
++#endif
++
++#include "TYPEDEF.H"
++#include "LIB.H"
++
++//---------------------------------------------------------
++// Print Message
++//---------------------------------------------------------
++// for function
++#define FP_LOG 0
++#define FP_IO 1
++#define STD_OUT 2
++
++#ifdef SLT_UBOOT
++ #define PRINT printf
++ #define OUT_OBJ
++ #define FILE_VAR
++
++ #define GET_OBJ( i ) \
++ do { \
++ if ( i != STD_OUT ) \
++ return; \
++ } while ( 0 );
++
++#else
++ #define PRINT fprintf
++ #define OUT_OBJ fp,
++ #define FILE_VAR FILE *fp;
++
++ #define GET_OBJ( i ) \
++ switch( i ) { \
++ case FP_LOG: \
++ fp = fp_log; \
++ break; \
++ case FP_IO: \
++ fp = fp_io; \
++ break; \
++ case STD_OUT: \
++ fp = stdout; \
++ break; \
++ default : break; \
++ }
++#endif
++
++//---------------------------------------------------------
++// Function
++//---------------------------------------------------------
++#ifdef SLT_UBOOT
++ #define DELAY( x ) udelay( x * 1000 ) // For Uboot, the unit of udelay() is us.
++ #define GET_CAHR getc
++#endif
++#ifdef SLT_DOS
++ #define DELAY( x ) delay( x ) // For DOS, the unit of delay() is ms.
++ #define GET_CAHR getchar
++#endif
++
++//---------------------------------------------------------
++// Default argument
++//---------------------------------------------------------
++#define DEF_USER_DEF_PACKET_VAL 0x66666666 //0xff00ff00, 0xf0f0f0f0, 0xcccccccc, 0x55aa55aa, 0x5a5a5a5a, 0x66666666
++#define DEF_IOTIMINGBUND 5 //0/1/3/5/7
++#define DEF_PHY_ADR 0
++#define DEF_TESTMODE 0 //[0]0: no burst mode, 1: 0xff, 2: 0x55, 3: random, 4: ARP, 5: ARP, 6: IO timing, 7: IO timing+IO Strength
++#define DEF_LOOP_MAX 1
++#define DEF_MAC_LOOP_BACK 0 //GCtrl bit6
++#define DEF_SKIP_CHECK_PHY 0 //GCtrl bit4
++#define DEF_INIT_PHY 1 //GCtrl bit3
++
++#define SET_1GBPS 0 // 1G bps
++#define SET_100MBPS 1 // 100M bps
++#define SET_10MBPS 2 // 10M bps
++#define SET_1G_100M_10MBPS 3 // 1G and 100M and 10M bps
++#define DEF_SPEED SET_1G_100M_10MBPS
++#define DEF_ARPNUMCNT 0
++
++//---------------------------------------------------------
++// MAC information
++//---------------------------------------------------------
++#if ( AST1010_IOMAP == 1 )
++ // AST1010 only has a MAC
++ #define MAC_BASE1 AST_MAC1_BASE
++ #define MAC_BASE2 AST_MAC1_BASE
++ #define MAC_BASE3 AST_MAC1_BASE
++ #define MAC_BASE4 AST_MAC1_BASE
++#endif
++
++#if ( AST1010_IOMAP == 2 )
++ // AST1010 only has a MAC
++ #define MAC_BASE1 0x0830000
++ #define MAC_BASE2 0x0830000
++ #define MAC_BASE3 0x0830000
++ #define MAC_BASE4 0x0830000
++#endif
++
++#ifndef AST1010_IOMAP
++ #define MAC_BASE1 0x1e660000
++ #define MAC_BASE2 0x1e680000
++ #define MAC_BASE3 0x1e670000
++ #define MAC_BASE4 0x1e690000
++#endif
++
++#define MDC_Thres 0x3f
++#define MAC_PHYWr 0x08000000
++#define MAC_PHYRd 0x04000000
++
++#define MAC_PHYWr_New 0x00009400
++#define MAC_PHYRd_New 0x00009800
++#define MAC_PHYBusy_New 0x00008000
++
++//#define MAC_30h 0x00001010
++//#define MAC_34h 0x00000000
++//#define MAC_38h 0x00d22f00 //default 0x22f00
++//#define MAC_38h 0x00022f00 //default 0x22f00
++
++#define MAC_40h 0x40000000
++
++#ifdef Enable_BufMerge
++ #define MAC_48h 0x007702F1 //default 0xf1
++#else
++ #ifdef AST1010_IOMAP
++ #define MAC_48h 0x000002F1 //default 0xf1
++ #else
++ #define MAC_48h 0x000001F1 //default 0xf1
++ #endif
++#endif
++
++//---------------------------------------------------------
++// Data information
++//---------------------------------------------------------
++#ifdef SelectSimpleBoundary
++ #define ZeroCopy_OFFSET 0
++#else
++ #define ZeroCopy_OFFSET ( (BurstEnable) ? 0 : 2 )
++#endif
++
++// --------------------------------- DRAM_MapAdr = TDES_BASE1
++// | TX descriptor ring #1 |
++// ------------------------- DRAM_MapAdr + 0x040000 = RDES_BASE1
++// | RX descriptor ring #1 |
++// ------------------------- DRAM_MapAdr + 0x080000 = TDES_BASE2
++// | TX descriptor ring #2 |
++// ------------------------- DRAM_MapAdr + 0x0C0000 = RDES_BASE2
++// | RX descriptor ring #2 |
++// --------------------------------- DRAM_MapAdr + 0x100000 = DMA_BASE -------------------------
++// | #1 | \ | #1 Tx |
++// DMA buffer | | DMA_BufSize | LOOP = 0 |
++// ( Tx/Rx ) ------------------------- / --------------------------------------------------
++// | #2 | | #2 Rx | #2 Tx |
++// | | | LOOP = 0 | LOOP = 1 |
++// ------------------------- --------------------------------------------------
++// | #3 | | #3 Rx |
++// | | | LOOP = 1 |
++// ------------------------- -------------------------
++// | #4 | ..........
++// | |
++// -------------------------
++// | #5 |
++// | |
++// -------------------------
++// | #6 |
++// | |
++// -------------------------
++// .
++// .
++// -------------------------
++// | #n, n = DMA_BufNum |
++// | |
++// ---------------------------------
++
++#if ( AST1010_IOMAP == 1 )
++ #define DRAM_MapAdr ( CONFIG_DRAM_SWAP_BASE + 0x00200000 ) // We use 0xA00000 to 0xEFFFFF
++ #define CPU_BUS_ADDR_SDRAM_OFFSET 0x01000000 // In ReMapping function, MAC engine need Bus address
++ // But Coldfire need CPU address, so need to do offset
++#endif
++
++#if ( AST1010_IOMAP == 2 )
++ #define DRAM_MapAdr 0x0A00000 // We use 0xA00000 to 0xEFFFFF
++ #define CPU_BUS_ADDR_SDRAM_OFFSET 0
++#endif
++
++#ifndef AST1010_IOMAP
++ #ifdef AST3200_IOMAP
++ #define DRAM_MapAdr 0x80000000
++ #else
++ #define DRAM_MapAdr 0x44000000
++ #endif
++
++ #define CPU_BUS_ADDR_SDRAM_OFFSET 0
++#endif
++
++ #define TDES_BASE1 ( 0x00000000 + DRAM_MapAdr )
++ #define RDES_BASE1 ( 0x00040000 + DRAM_MapAdr )
++ #define TDES_BASE2 ( 0x00080000 + DRAM_MapAdr )
++ #define RDES_BASE2 ( 0x000C0000 + DRAM_MapAdr )
++
++ #define TDES_IniVal ( 0xb0000000 + FRAME_LEN_Cur )
++ #define RDES_IniVal ( 0x00000fff )
++ #define EOR_IniVal ( 0x40008000 )
++ #define HWOwnTx(dat) ( (dat) & 0x80000000 )
++ #define HWOwnRx(dat) ( !((dat) & 0x80000000) )
++ #define HWEOR(dat) ( dat & 0x40000000 )
++
++//---------------------------------------------------------
++// Error Flag Bits
++//---------------------------------------------------------
++#define Err_MACMode ( 1 << 0 ) // MAC interface mode mismatch
++#define Err_PHY_Type ( 1 << 1 ) // Unidentifiable PHY
++#define Err_MALLOC_FrmSize ( 1 << 2 ) // Malloc fail at frame size buffer
++#define Err_MALLOC_LastWP ( 1 << 3 ) // Malloc fail at last WP buffer
++#define Err_Check_Buf_Data ( 1 << 4 ) // Received data mismatch
++#define Err_Check_Des ( 1 << 5 ) // Descriptor error
++#define Err_NCSI_LinkFail ( 1 << 6 ) // NCSI packet retry number over flows
++#define Err_NCSI_Check_TxOwnTimeOut ( 1 << 7 ) // Time out of checking Tx owner bit in NCSI packet
++#define Err_NCSI_Check_RxOwnTimeOut ( 1 << 8 ) // Time out of checking Rx owner bit in NCSI packet
++#define Err_NCSI_Check_ARPOwnTimeOut ( 1 << 9 ) // Time out of checking ARP owner bit in NCSI packet
++#define Err_NCSI_No_PHY ( 1 << 10 ) // Can not find NCSI PHY
++#define Err_NCSI_Channel_Num ( 1 << 11 ) // NCSI Channel Number Mismatch
++#define Err_NCSI_Package_Num ( 1 << 12 ) // NCSI Package Number Mismatch
++#define Err_PHY_TimeOut ( 1 << 13 ) // Time out of read/write/reset PHY register
++#define Err_RXBUF_UNAVA ( 1 << 14 ) // MAC00h[2]:Receiving buffer unavailable
++#define Err_RPKT_LOST ( 1 << 15 ) // MAC00h[3]:Received packet lost due to RX FIFO full
++#define Err_NPTXBUF_UNAVA ( 1 << 16 ) // MAC00h[6]:Normal priority transmit buffer unavailable
++#define Err_TPKT_LOST ( 1 << 17 ) // MAC00h[7]:Packets transmitted to Ethernet lost
++#define Err_DMABufNum ( 1 << 18 ) // DMA Buffer is not enough
++#define Err_IOMargin ( 1 << 19 ) // IO timing margin is not enough
++#define Err_IOMarginOUF ( 1 << 20 ) // IO timing testing out of boundary
++#define Err_MHCLK_Ratio ( 1 << 21 ) // Error setting of MAC AHB bus clock (SCU08[18:16])
++
++#define Check_Des_TxOwnTimeOut ( 1 << 0 ) // Time out of checking Tx owner bit
++#define Check_Des_RxOwnTimeOut ( 1 << 1 ) // Time out of checking Rx owner bit
++#define Check_Des_RxErr ( 1 << 2 ) // Input signal RxErr
++#define Check_Des_OddNibble ( 1 << 3 ) // Nibble bit happen
++#define Check_Des_CRC ( 1 << 4 ) // CRC error of frame
++#define Check_Des_RxFIFOFull ( 1 << 5 ) // Rx FIFO full
++#define Check_Des_FrameLen ( 1 << 6 ) // Frame length mismatch
++
++#define NCSI_LinkFail_Get_Version_ID ( 1 << 0 ) // Time out when Get Version ID
++#define NCSI_LinkFail_Get_Capabilities ( 1 << 1 ) // Time out when Get Capabilities
++#define NCSI_LinkFail_Select_Active_Package ( 1 << 2 ) // Time out when Select Active Package
++#define NCSI_LinkFail_Enable_Set_MAC_Address ( 1 << 3 ) // Time out when Enable Set MAC Address
++#define NCSI_LinkFail_Enable_Broadcast_Filter ( 1 << 4 ) // Time out when Enable Broadcast Filter
++#define NCSI_LinkFail_Enable_Network_TX ( 1 << 5 ) // Time out when Enable Network TX
++#define NCSI_LinkFail_Enable_Channel ( 1 << 6 ) // Time out when Enable Channel
++#define NCSI_LinkFail_Disable_Network_TX ( 1 << 7 ) // Time out when Disable Network TX
++#define NCSI_LinkFail_Disable_Channel ( 1 << 8 ) // Time out when Disable Channel
++
++//---------------------------------------------------------
++// SCU information
++//---------------------------------------------------------
++#if ( AST1010_IOMAP == 1 )
++ #define SCU_BASE AST_SCU_BASE
++#endif
++#if ( AST1010_IOMAP == 2 )
++ #define SCU_BASE 0x0841000
++#endif
++
++#ifndef AST1010_IOMAP
++ #define SCU_BASE 0x1e6e2000
++#endif
++
++#define SCU_48h_AST1010 0x00000200
++#define SCU_48h_AST2300 0x00222255
++
++//#ifdef SLT_DOS
++// #define SCU_80h 0x00000000
++// #define SCU_88h 0x00000000
++// #define SCU_90h 0x00000000
++// #define SCU_74h 0x00000000
++//#else
++// #define SCU_80h 0x0000000f //AST2300[3:0]MAC1~4 PHYLINK
++// #define SCU_88h 0xc0000000 //AST2300[31]MAC1 MDIO, [30]MAC1 MDC
++// #define SCU_90h 0x00000004 //AST2300[2 ]MAC2 MDC/MDIO
++// #define SCU_74h 0x06300000 //AST3000[20]MAC2 MDC/MDIO, [21]MAC2 MII, [25]MAC1 PHYLINK, [26]MAC2 PHYLINK
++//#endif
++
++//---------------------------------------------------------
++// DMA Buffer information
++//---------------------------------------------------------
++#ifdef FPGA
++ #define DRAM_KByteSize ( 56 * 1024 )
++#else
++ #ifdef AST1010_IOMAP
++ #define DRAM_KByteSize ( 3 * 1024 ) // DATA buffer only use 0xB00000 to 0xE00000
++ #else
++ #define DRAM_KByteSize ( 18 * 1024 )
++ #endif
++#endif
++
++#define DMA_BASE ( 0x00100000 + DRAM_MapAdr )
++
++#ifdef Enable_Jumbo
++ #define DMA_PakSize ( 10 * 1024 )
++#else
++ #define DMA_PakSize ( 2 * 1024 ) // The size of one LAN packet
++#endif
++
++#ifdef SelectSimpleBoundary
++ #define DMA_BufSize ( ( ( ( ( DES_NUMBER + 15 ) * DMA_PakSize ) >> 2 ) << 2 ) ) //vary by DES_NUMBER
++#else
++ #define DMA_BufSize (4 + ( ( ( ( DES_NUMBER + 15 ) * DMA_PakSize ) >> 2 ) << 2 ) ) //vary by DES_NUMBER
++#endif
++
++#define DMA_BufNum ( ( DRAM_KByteSize * 1024 ) / ( DMA_BufSize ) ) //vary by DES_NUMBER
++#define GET_DMA_BASE_SETUP ( DMA_BASE )
++#define GET_DMA_BASE(x) ( DMA_BASE + ( ( ( ( x ) % DMA_BufNum ) + 1 ) * DMA_BufSize ) )//vary by DES_NUMBER
++
++#define SEED_START 8
++#define DATA_SEED(seed) ( ( seed ) | (( seed + 1 ) << 16 ) )
++#define DATA_IncVal 0x00020001
++//#define DATA_IncVal 0x01000001 //fail
++//#define DATA_IncVal 0x10000001 //fail
++//#define DATA_IncVal 0x10000000 //fail
++//#define DATA_IncVal 0x80000000 //fail
++//#define DATA_IncVal 0x00000001 //ok
++//#define DATA_IncVal 0x01000100 //ok
++//#define DATA_IncVal 0x01010000 //ok
++//#define DATA_IncVal 0x01010101 //ok
++//#define DATA_IncVal 0x00000101 //ok
++//#define DATA_IncVal 0x00001111 //fail
++//#define DATA_IncVal 0x00000011 //fail
++//#define DATA_IncVal 0x10100101 //fail
++//#define DATA_IncVal 0xfeff0201
++//#define DATA_IncVal 0x00010001
++#define PktByteSize ( ( ( ( ZeroCopy_OFFSET + FRAME_LEN_Cur - 1 ) >> 2 ) + 1) << 2 )
++
++//---------------------------------------------------------
++// Delay (ms)
++//---------------------------------------------------------
++//#define Delay_DesGap 1000 //off
++//#define Delay_DesGap 700 //off
++
++//#define Delay_ChkRxOwn 10
++//#define Delay_ChkTxOwn 10
++#define Delay_CntMax 100000000
++//#define Delay_CntMax 1000
++//#define Delay_CntMax 8465
++//#define Delay_CntMaxIncVal 50000
++#define Delay_CntMaxIncVal 47500
++
++#define Delay_PHYRst 100
++#define Delay_PHYRd 5
++
++#define Delay_SCU 11
++#define Delay_MACRst 1
++#define Delay_MACDump 100
++
++//#define Delay_DES 1
++
++//---------------------------------------------------------
++// Time Out
++//---------------------------------------------------------
++#define TIME_OUT_Des 10000
++#define TIME_OUT_PHY_RW 10000
++#define TIME_OUT_PHY_Rst 10000
++
++//#define TIME_OUT_NCSI 300000
++#define TIME_OUT_NCSI 30000
++
++
++
++//---------------------------------------------------------
++// Chip memory MAP
++//---------------------------------------------------------
++#define LITTLE_ENDIAN_ADDRESS 0
++#define BIG_ENDIAN_ADDRESS 1
++
++typedef struct {
++ ULONG StartAddr;
++ ULONG EndAddr;
++} LittleEndian_Area;
++
++#if ( AST1010_IOMAP == 1 )
++ static const LittleEndian_Area LittleEndianArea[] = {
++ { AST_IO_BASE, (AST_IO_BASE + 0x000FFFFF) },
++ { 0xFFFFFFFF, 0xFFFFFFFF } // End
++ };
++#else
++ static const LittleEndian_Area LittleEndianArea[] = {
++ { 0xFFFFFFFF, 0xFFFFFFFF } // End
++ };
++#endif
++
++// ========================================================
++// For ncsi.c
++
++#define DEF_PACKAGE2NUM 1 // Default value
++#define DEF_CHANNEL2NUM 2 // Default value
++
++typedef struct {
++ unsigned char Package_ID;
++ unsigned char Channel_ID;
++ unsigned long Capabilities_Flags;
++ unsigned long Broadcast_Packet_Filter_Capabilities;
++ unsigned long Multicast_Packet_Filter_Capabilities;
++ unsigned long Buffering_Capabilities;
++ unsigned long AEN_Control_Support;
++ unsigned long PCI_DID_VID;
++ unsigned long ManufacturerID;
++} NCSI_Capability;
++
++#undef GLOBAL
++#ifdef NCSI_C
++#define GLOBAL
++#else
++#define GLOBAL extern
++#endif
++
++GLOBAL NCSI_Capability NCSI_Cap_SLT;
++GLOBAL BYTE number_chl;
++
++GLOBAL char phy_ncsi (void);
++
++// ========================================================
++// For mactest
++
++#undef GLOBAL
++#ifdef MACTEST_C
++#define GLOBAL
++#else
++#define GLOBAL extern
++#endif
++
++GLOBAL ULONG NCSI_DiSChannel;
++
++//
++#ifdef SLT_UBOOT
++#else
++// SLT_DOS
++GLOBAL FILE *fp_log;
++GLOBAL FILE *fp_io;
++#endif
++
++GLOBAL CHAR dlymap[16][16];
++GLOBAL CHAR PrintNCSIEn;
++GLOBAL ULONG ARPNumCnt;
++GLOBAL CHAR FileNameMain[256];
++GLOBAL CHAR FileName[256];
++GLOBAL CHAR ASTChipName[256];
++GLOBAL CHAR LOOP_Str[256];
++GLOBAL BYTE IOTimingBund;
++GLOBAL BYTE ChannelTolNum;
++GLOBAL BYTE PackageTolNum;
++GLOBAL ULONG IOdly_out_reg;
++GLOBAL BYTE IOdly_out_reg_idx;
++GLOBAL ULONG Dat_ULONG;
++GLOBAL ULONG IOdly_incval;
++GLOBAL ULONG IOdly_in_reg;
++GLOBAL BYTE IOdly_in_reg_idx;
++GLOBAL ULONG *wp_lst;
++GLOBAL ULONG *FRAME_LEN;
++GLOBAL ULONG DES_NUMBER;
++GLOBAL ULONG DES_NUMBER_Org;
++GLOBAL int LOOP_MAX;
++GLOBAL ULONG LOOP_CheckNum;
++GLOBAL int Loop;
++GLOBAL ULONG CheckBuf_MBSize;
++GLOBAL ULONG Err_Flag;
++GLOBAL ULONG SCU_f0h_old;
++#ifdef AST1010_IOMAP
++ GLOBAL ULONG SCU_11Ch_old;
++#endif
++GLOBAL ULONG SCU_04h;
++GLOBAL ULONG SCU_90h_old;
++GLOBAL ULONG SCU_7ch_old;
++GLOBAL ULONG MAC_50h;
++GLOBAL ULONG SCU_ach_old;
++GLOBAL ULONG SCU_70h_old;
++GLOBAL ULONG MAC_50h_Speed;
++GLOBAL ULONG SCU_48h_old;
++GLOBAL ULONG SCU_48h_mix;
++GLOBAL ULONG MAC_08h_old;
++GLOBAL ULONG MAC_0ch_old;
++GLOBAL ULONG MAC_40h_old;
++GLOBAL ULONG SCU_08h_old;
++GLOBAL ULONG MAC_PHYBASE;
++GLOBAL ULONG LOOP_MAX_arg;
++GLOBAL BYTE GRun_Mode;
++GLOBAL ULONG GSpeed_idx;
++GLOBAL CHAR GSpeed_sel[3];
++GLOBAL CHAR PHY_ADR;
++GLOBAL CHAR PHY_ADR_arg;
++GLOBAL CHAR PHYName[256];
++GLOBAL ULONG PHY_ID3;
++GLOBAL ULONG PHY_ID2;
++GLOBAL BYTE number_pak;
++GLOBAL BYTE TestMode;
++GLOBAL ULONG IOStr_i;
++GLOBAL BYTE IOTimingBund_arg;
++GLOBAL BYTE GSpeed;
++GLOBAL BYTE GCtrl;
++GLOBAL ULONG UserDVal;
++GLOBAL ULONG H_MAC_BASE;
++GLOBAL ULONG H_TDES_BASE;
++GLOBAL ULONG H_RDES_BASE;
++GLOBAL CHAR Loop_rl[3];
++GLOBAL CHAR IOTiming;
++GLOBAL CHAR LOOP_INFINI;
++GLOBAL CHAR SelectMAC;
++GLOBAL CHAR Enable_SkipChkPHY;
++GLOBAL CHAR Enable_MAC34;
++GLOBAL CHAR IOStrength;
++GLOBAL CHAR DataDelay;
++GLOBAL CHAR SA[6];
++GLOBAL CHAR RxDataEnable;
++GLOBAL CHAR IEEETesting;
++GLOBAL CHAR BurstEnable;
++GLOBAL CHAR MAC_Mode;
++GLOBAL CHAR Enable_MACLoopback;
++GLOBAL CHAR Enable_InitPHY;
++GLOBAL CHAR MAC1_1GEn;
++GLOBAL CHAR MAC2_RMII;
++GLOBAL CHAR Enable_RMII;
++GLOBAL CHAR MAC2_1GEn;
++GLOBAL CHAR TxDataEnable;
++GLOBAL CHAR AST2300_NewMDIO;
++GLOBAL CHAR ASTChipType;
++GLOBAL CHAR Err_Flag_PrintEn;
++GLOBAL CHAR AST2400;
++GLOBAL CHAR AST2300;
++GLOBAL CHAR AST1100;//Different in phy & dram initiation & dram size & RMII
++GLOBAL CHAR AST3200;
++GLOBAL CHAR AST1010;
++GLOBAL SCHAR IOdly_i_min;
++GLOBAL SCHAR IOdly_j_min;
++GLOBAL SCHAR IOdly_i_max;
++GLOBAL SCHAR IOdly_j_max;
++GLOBAL BYTE IOdly_i;
++GLOBAL BYTE IOdly_j;
++GLOBAL BYTE IOdly_in;
++GLOBAL BYTE IOdly_out;
++GLOBAL SCHAR IOdly_in_str;
++GLOBAL BYTE IOdly_in_end;
++GLOBAL BYTE IOdly_out_end;
++GLOBAL BYTE IOdly_out_shf;
++GLOBAL BYTE IOdly_in_shf;
++GLOBAL SCHAR IOdly_out_str;
++GLOBAL BYTE valary[16];
++
++#define MODE_DEDICATED 0x01
++#define MODE_NSCI 0x02
++GLOBAL CHAR ModeSwitch;
++
++#ifdef SLT_UBOOT
++#else
++ GLOBAL time_t timestart;
++#endif
++
++#ifdef SPI_BUS
++ GLOBAL ULONG mmiobase;
++#else
++ // ( USE_P2A | USE_LPC )
++ GLOBAL UCHAR *mmiobase;
++ GLOBAL ULONG ulPCIBaseAddress;
++ GLOBAL ULONG ulMMIOBaseAddress;
++#endif
++
++
++// ========================================================
++// For mac.c
++#undef GLOBAL
++#ifdef MAC_C
++#define GLOBAL
++#else
++#define GLOBAL extern
++#endif
++
++GLOBAL ULONG ARP_data[16];
++GLOBAL ULONG NCSI_LinkFail_Val;
++static const char version_name[] = VER_NAME;
++
++GLOBAL void Debug_delay (void);
++GLOBAL void read_scu (void);
++GLOBAL void Setting_scu (void);
++GLOBAL void PrintMode (void);
++GLOBAL void PrintPakNUm (void);
++GLOBAL void PrintChlNUm (void);
++GLOBAL void PrintTest (void);
++GLOBAL void PrintIOTimingBund (void);
++GLOBAL void PrintSpeed (void);
++GLOBAL void PrintCtrl (void);
++GLOBAL void PrintLoop (void);
++GLOBAL void PrintPHYAdr (void);
++GLOBAL void Finish_Close (void);
++GLOBAL void Calculate_LOOP_CheckNum (void);
++GLOBAL char Finish_Check (int value);
++GLOBAL void init_scu1 (void);
++GLOBAL void init_scu_macrst (void);
++GLOBAL void setup_arp (void);
++GLOBAL void TestingSetup (void);
++GLOBAL void init_scu2 (void);
++GLOBAL void init_scu3 (void);
++GLOBAL void init_mac (ULONG base, ULONG tdexbase, ULONG rdexbase);
++GLOBAL char TestingLoop (ULONG loop_checknum);
++GLOBAL void PrintIO_Line_LOG (void);
++GLOBAL void init_phy (int loop_phy);
++GLOBAL void recov_phy (int loop_phy);
++GLOBAL int FindErr (int value);
++GLOBAL int FindErr_Des (int value);
++GLOBAL void PrintIO_Header (BYTE option);
++GLOBAL void Print_Header (BYTE option);
++GLOBAL void PrintIO_LineS (BYTE option);
++GLOBAL void PrintIO_Line (BYTE option);
++GLOBAL void FPri_ErrFlag (BYTE option);
++
++#ifdef SUPPORT_PHY_LAN9303
++// ========================================================
++// For LAN9303.c
++#undef GLOBAL
++#ifdef LAN9303_C
++#define GLOBAL
++#else
++#define GLOBAL extern
++#endif
++
++GLOBAL void LAN9303(int num, int phy_adr, int speed, int int_loopback);
++#endif // SUPPORT_PHY_LAN9303
++#endif // End COMMINF_H
++
+diff --git a/arch/arm/cpu/arm926ejs/aspeed/DEF_SPI.H b/arch/arm/cpu/arm926ejs/aspeed/DEF_SPI.H
+new file mode 100644
+index 0000000..02353e7
+--- /dev/null
++++ b/arch/arm/cpu/arm926ejs/aspeed/DEF_SPI.H
+@@ -0,0 +1,35 @@
++/*
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++ */
++#ifndef DEF_SPI_H
++#define DEF_SPI_H
++
++#include "TYPEDEF.H"
++#include "SWFUNC.H"
++
++typedef struct _DEVICE_PCI_INFO
++{
++ USHORT usVendorID;
++ USHORT usDeviceID;
++ ULONG ulPCIConfigurationBaseAddress;
++ ULONG ulPhysicalBaseAddress;
++ ULONG ulMMIOBaseAddress;
++ USHORT usRelocateIO;
++} DEVICE_PCI_INFO;
++
++//VIDEO Engine Info
++typedef struct _VIDEO_ENGINE_INFO {
++ USHORT iEngVersion;
++ DEVICE_PCI_INFO VGAPCIInfo;
++} VIDEO_ENGINE_INFO;
++
++BOOLEAN GetDevicePCIInfo (VIDEO_ENGINE_INFO *VideoEngineInfo);
++
++#endif // DEF_SPI_H
+diff --git a/arch/arm/cpu/arm926ejs/aspeed/DRAM_SPI.c b/arch/arm/cpu/arm926ejs/aspeed/DRAM_SPI.c
+new file mode 100644
+index 0000000..fe2b5cf
+--- /dev/null
++++ b/arch/arm/cpu/arm926ejs/aspeed/DRAM_SPI.c
+@@ -0,0 +1,78 @@
++/*
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++ */
++#define DRAM_SPI_C
++static const char ThisFile[] = "DRAM_SPI.c";
++
++#include "SWFUNC.H"
++
++#ifdef SPI_BUS
++#include <stdio.h>
++#include "DEF_SPI.H"
++#include "LIB_SPI.H"
++
++VOID Set_MMIO_Base(ULONG PCI_BASE, ULONG addr)
++{
++ static ULONG MMIO_BASE = -1;
++
++ if(MMIO_BASE != (addr & 0xffff0000)){
++ if(MMIO_BASE == -1){
++ *(ULONG *)(PCI_BASE + 0xF000) = 1;
++ }
++ *(ULONG *)(PCI_BASE + 0xF004) = addr;
++ MMIO_BASE = addr & 0xffff0000;
++ }
++}
++
++VOID MOutbm(ULONG PCI_BASE, ULONG Offset, BYTE Data)
++{
++ Set_MMIO_Base(PCI_BASE, Offset);
++ *(BYTE *)(PCI_BASE + 0x10000 + (Offset & 0xffff)) = Data;
++}
++
++VOID MOutwm(ULONG PCI_BASE, ULONG Offset, USHORT Data)
++{
++ Set_MMIO_Base(PCI_BASE, Offset);
++ *(USHORT *)(PCI_BASE + 0x10000 + (Offset & 0xffff)) = Data;
++}
++
++VOID MOutdwm(ULONG PCI_BASE, ULONG Offset, ULONG Data)
++{
++ Set_MMIO_Base(PCI_BASE, Offset);
++ *(ULONG *)(PCI_BASE + 0x10000 + (Offset & 0xffff)) = Data;
++}
++
++BYTE MInbm(ULONG PCI_BASE, ULONG Offset)
++{
++ BYTE jData;
++
++ Set_MMIO_Base(PCI_BASE, Offset);
++ jData = *(BYTE *)(PCI_BASE + 0x10000 + (Offset & 0xffff));
++ return(jData);
++}
++
++USHORT MInwm(ULONG PCI_BASE, ULONG Offset)
++{
++ USHORT usData;
++
++ Set_MMIO_Base(PCI_BASE, Offset);
++ usData = *(USHORT *)(PCI_BASE + 0x10000 + (Offset & 0xffff));
++ return(usData);
++}
++
++ULONG MIndwm(ULONG PCI_BASE, ULONG Offset)
++{
++ ULONG ulData;
++
++ Set_MMIO_Base(PCI_BASE, Offset);
++ ulData = *(ULONG *)(PCI_BASE + 0x10000 + (Offset & 0xffff));
++ return(ulData);
++}
++#endif // End SPI_BUS
+diff --git a/arch/arm/cpu/arm926ejs/aspeed/IO.H b/arch/arm/cpu/arm926ejs/aspeed/IO.H
+new file mode 100644
+index 0000000..5fe03f0
+--- /dev/null
++++ b/arch/arm/cpu/arm926ejs/aspeed/IO.H
+@@ -0,0 +1,36 @@
++/*
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++ */
++#ifndef IO_H
++#define IO_H
++
++#include "SWFUNC.H"
++
++//
++// Macro
++//
++#if defined(LinuxAP)
++ #define delay(val) usleep(val*1000)
++ #define ob(p,d) outb(d,p)
++ #define ib(p) inb(p)
++#else
++ #define ob(p,d) outp(p,d)
++ #define ib(p) inp(p)
++#endif
++
++#ifdef USE_LPC
++void open_aspeed_sio_password(void);
++void enable_aspeed_LDU(BYTE jldu_number);
++int findlpcport(BYTE jldu_number);
++#endif
++
++void WriteSOC_DD(ULONG addr, ULONG data);
++ULONG ReadSOC_DD(ULONG addr);
++#endif
+diff --git a/arch/arm/cpu/arm926ejs/aspeed/IO.c b/arch/arm/cpu/arm926ejs/aspeed/IO.c
+new file mode 100644
+index 0000000..86e9918
+--- /dev/null
++++ b/arch/arm/cpu/arm926ejs/aspeed/IO.c
+@@ -0,0 +1,356 @@
++/*
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++ */
++#define IO_C
++static const char ThisFile[] = "IO.c";
++
++#include "SWFUNC.H"
++
++#if defined(LinuxAP)
++ #include <stdio.h>
++ #include <string.h>
++ #include <stdlib.h>
++ #include <stdarg.h>
++ #include <unistd.h>
++ #include <string.h>
++ #include <fcntl.h>
++ #include <pthread.h>
++ #include <sys/mman.h>
++ #include <sys/io.h>
++#endif
++#ifdef SLT_UBOOT
++ #include <common.h>
++ #include <command.h>
++ #include <post.h>
++ #include <malloc.h>
++ #include <net.h>
++ #include <COMMINF.H>
++#endif
++#ifdef SLT_DOS
++ #include <stdlib.h>
++ #include <stdio.h>
++ #include <time.h>
++ #include <conio.h>
++ #include <dos.h>
++ #include <mem.h>
++ #include "TYPEDEF.H"
++ #include "LIB.H"
++ #include "COMMINF.H"
++#endif
++
++#include "TYPEDEF.H"
++#include "IO.H"
++#include "LIB_SPI.H"
++
++#ifdef SPI_BUS
++#endif
++#ifdef USE_LPC
++ USHORT usLPCPort;
++#endif
++#ifdef USE_P2A
++#endif
++
++#ifdef USE_LPC
++//------------------------------------------------------------
++// LPC access
++//------------------------------------------------------------
++void open_aspeed_sio_password(void)
++{
++ ob (usLPCPort, 0xaa);
++
++ ob (usLPCPort, 0xa5);
++ ob (usLPCPort, 0xa5);
++}
++
++//------------------------------------------------------------
++void close_aspeed_sio_password(void)
++{
++ ob (usLPCPort, 0xaa);
++}
++
++//------------------------------------------------------------
++void enable_aspeed_LDU(BYTE jldu_number)
++{
++ ob (usLPCPort, 0x07);
++ ob ((usLPCPort + 1), jldu_number);
++ ob (usLPCPort, 0x30);
++ ob ((usLPCPort + 1), 0x01);
++}
++
++//------------------------------------------------------------
++void disable_aspeed_LDU(BYTE jldu_number)
++{
++ ob (usLPCPort, 0x07);
++ ob ((usLPCPort + 1), jldu_number);
++ ob (usLPCPort, 0x30);
++ ob ((usLPCPort + 1), 0x00);
++}
++
++//------------------------------------------------------------
++/*
++ulAddress = AHB address
++jmode = 0: byte mode
++ 1: word mode
++ 2: dword mode
++*/
++static ULONG lpc_read (ULONG ulAddress, BYTE jmode)
++{
++ ULONG uldata = 0;
++ ULONG ultemp = 0;
++ BYTE jtemp;
++
++ //Write Address
++ ob ( usLPCPort, 0xf0);
++ ob ( (usLPCPort + 1 ), ((ulAddress & 0xff000000) >> 24));
++ ob ( usLPCPort, 0xf1);
++ ob ( (usLPCPort + 1) , ((ulAddress & 0x00ff0000) >> 16));
++ ob ( usLPCPort, 0xf2);
++ ob ( (usLPCPort + 1), ((ulAddress & 0x0000ff00) >> 8));
++ ob ( usLPCPort, 0xf3);
++ ob ( (usLPCPort + 1), ulAddress & 0xff);
++
++ //Write Mode
++ ob (usLPCPort, 0xf8);
++ jtemp = ib ((usLPCPort + 1));
++ ob ((usLPCPort + 1), ((jtemp & 0xfc) | jmode));
++
++ //Fire
++ ob (usLPCPort, 0xfe);
++ jtemp = ib ((usLPCPort + 1));
++
++ //Get Data
++ switch ( jmode )
++ {
++ case 0:
++ ob (usLPCPort, 0xf7);
++ ultemp = ib ((usLPCPort + 1));
++ uldata |= (ultemp);
++ break;
++
++ case 1:
++ ob (usLPCPort, 0xf6);
++ ultemp = ib ((usLPCPort + 1));
++ uldata |= (ultemp << 8);
++ ob (usLPCPort, 0xf7);
++ ultemp = ib ((usLPCPort + 1));
++ uldata |= (ultemp << 0);
++ break;
++
++ case 2:
++ ob (usLPCPort, 0xf4);
++ ultemp = ib ((usLPCPort + 1));
++ uldata |= (ultemp << 24);
++ ob (usLPCPort, 0xf5);
++ ultemp = ib ((usLPCPort + 1));
++ uldata |= (ultemp << 16);
++ ob (usLPCPort, 0xf6);
++ ultemp = ib ((usLPCPort + 1));
++ uldata |= (ultemp << 8);
++ ob (usLPCPort, 0xf7);
++ ultemp = ib ((usLPCPort + 1));
++ uldata |= ultemp;
++ break;
++ } // End switch ( jmode )
++
++ return uldata;
++} // End static ULONG lpc_read (ULONG ulAddress, BYTE jmode)
++
++//------------------------------------------------------------
++static void lpc_write (ULONG ulAddress, ULONG uldata, BYTE jmode)
++{
++ BYTE jtemp;
++
++ //Write Address
++ ob ( usLPCPort, 0xf0);
++ ob ((usLPCPort + 1), ((ulAddress & 0xff000000) >> 24));
++ ob ( usLPCPort, 0xf1);
++ ob ((usLPCPort + 1), ((ulAddress & 0x00ff0000) >> 16));
++ ob ( usLPCPort, 0xf2);
++ ob ((usLPCPort + 1), ((ulAddress & 0x0000ff00) >> 8));
++ ob ( usLPCPort, 0xf3);
++ ob ((usLPCPort + 1), ulAddress & 0xff);
++
++ //Write Data
++ switch ( jmode )
++ {
++ case 0:
++ ob ( usLPCPort, 0xf7);
++ ob ((usLPCPort + 1), (uldata & 0xff));
++ break;
++ case 1:
++ ob ( usLPCPort, 0xf6);
++ ob ((usLPCPort + 1), ((uldata & 0xff00) >> 8));
++ ob ( usLPCPort, 0xf7);
++ ob ((usLPCPort + 1), (uldata & 0x00ff));
++ break;
++ case 2:
++ ob ( usLPCPort, 0xf4);
++ ob ((usLPCPort + 1), ((uldata & 0xff000000) >> 24));
++ ob ( usLPCPort, 0xf5);
++ ob ((usLPCPort + 1), ((uldata & 0x00ff0000) >> 16));
++ ob ( usLPCPort, 0xf6);
++ ob ((usLPCPort + 1), ((uldata & 0x0000ff00) >> 8));
++ ob ( usLPCPort, 0xf7);
++ ob ((usLPCPort + 1), uldata & 0xff);
++ break;
++ } // End switch ( jmode )
++
++ //Write Mode
++ ob (usLPCPort, 0xf8);
++ jtemp = ib ((usLPCPort + 1));
++ ob ((usLPCPort + 1), ((jtemp & 0xfc) | jmode));
++
++ //Fire
++ ob (usLPCPort, 0xfe);
++ ob ((usLPCPort + 1), 0xcf);
++
++} // End static void lpc_write (ULONG ulAddress, ULONG uldata, BYTE jmode)
++
++//------------------------------------------------------------
++static USHORT usLPCPortList[] = {0x2e, 0x4e, 0xff};
++int findlpcport(BYTE jldu_number)
++{
++ USHORT *jLPCPortPtr;
++ ULONG ulData;
++
++ jLPCPortPtr = usLPCPortList;
++ while (*(USHORT *)(jLPCPortPtr) != 0xff )
++ {
++ usLPCPort = *(USHORT *)(jLPCPortPtr++);
++
++ open_aspeed_sio_password();
++ enable_aspeed_LDU(0x0d);
++
++ ulData = lpc_read(0x1e6e207c, 2);
++
++ if ( (ulData != 0x00000000) &&
++ (ulData != 0xFFFFFFFF) )
++ {
++ printf("Find LPC IO port at 0x%2x \n", usLPCPort);
++ return 1;
++ }
++
++ disable_aspeed_LDU(0x0d);
++ close_aspeed_sio_password();
++ }
++
++ //printf("[Error] Fail to find proper LPC IO Port \n");
++ return 0;
++}
++#endif // End ifdef USE_LPC
++
++#ifdef USE_P2A
++//------------------------------------------------------------
++// A2P Access
++//------------------------------------------------------------
++void mm_write (ULONG addr, ULONG data, BYTE jmode)
++{
++ *(ULONG *) (mmiobase + 0xF004) = (ULONG) ((addr) & 0xFFFF0000);
++ *(ULONG *) (mmiobase + 0xF000) = (ULONG) 0x00000001;
++
++ switch ( jmode )
++ {
++ case 0:
++ *(BYTE *) (mmiobase + 0x10000 + ((addr) & 0x0000FFFF)) = (BYTE) data;
++ break;
++ case 1:
++ *(USHORT *) (mmiobase + 0x10000 + ((addr) & 0x0000FFFF)) = (USHORT) data;
++ break;
++ case 2:
++ default:
++ *(ULONG *) (mmiobase + 0x10000 + ((addr) & 0x0000FFFF)) = data;
++ break;
++ } //switch
++}
++
++//------------------------------------------------------------
++ULONG mm_read (ULONG addr, BYTE jmode)
++{
++ *(ULONG *) (mmiobase + 0xF004) = (ULONG) ((addr) & 0xFFFF0000);
++ *(ULONG *) (mmiobase + 0xF000) = (ULONG) 0x00000001;
++ switch (jmode)
++ {
++ case 0:
++ return ( *(BYTE *) (mmiobase + 0x10000 + ((addr) & 0x0000FFFF)) );
++ break;
++ case 1:
++ return ( *(USHORT *) (mmiobase + 0x10000 + ((addr) & 0x0000FFFF)) );
++ break;
++ default:
++ case 2:
++ return ( *(ULONG *) (mmiobase + 0x10000 + ((addr) & 0x0000FFFF)) );
++ break;
++ } //switch
++
++ return 0;
++}
++#endif // End ifdef USE_P2A
++
++//------------------------------------------------------------
++// General Access API
++//------------------------------------------------------------
++#ifdef SLT_UBOOT
++BYTE Check_BEorLN ( ULONG chkaddr )
++{
++ BYTE ret = BIG_ENDIAN_ADDRESS;
++ BYTE i = 0;
++
++ do {
++ if ( LittleEndianArea[i].StartAddr == LittleEndianArea[i].EndAddr )
++ break;
++
++ if ( ( LittleEndianArea[i].StartAddr <= chkaddr ) &&
++ ( LittleEndianArea[i].EndAddr >= chkaddr ) ) {
++ ret = LITTLE_ENDIAN_ADDRESS;
++ break;
++ }
++ i++;
++ } while ( 1 );
++
++ return ret;
++}
++#endif
++
++void WriteSOC_DD(ULONG addr, ULONG data)
++{
++#ifdef SLT_UBOOT
++ if ( Check_BEorLN( addr ) == BIG_ENDIAN_ADDRESS )
++ *(volatile unsigned long *)(addr) = cpu_to_le32(data);
++ else
++ *(volatile unsigned long *)(addr) = data;
++#else
++ #ifdef USE_LPC
++ lpc_write(addr, data, 2);
++ #endif
++ #ifdef USE_P2A
++ mm_write(addr, data, 2);
++ #endif
++#endif
++}
++
++//------------------------------------------------------------
++ULONG ReadSOC_DD(ULONG addr)
++{
++#ifdef SLT_UBOOT
++ if ( Check_BEorLN( addr ) == BIG_ENDIAN_ADDRESS )
++ return le32_to_cpu(*(volatile unsigned long *) (addr));
++ else
++ return (*(volatile unsigned long *) (addr));
++#else
++ #ifdef USE_LPC
++ return (lpc_read(addr, 2));
++ #endif
++ #ifdef USE_P2A
++ return (mm_read(addr, 2));
++ #endif
++#endif
++ return 0;
++}
++
+diff --git a/arch/arm/cpu/arm926ejs/aspeed/LAN9303.c b/arch/arm/cpu/arm926ejs/aspeed/LAN9303.c
+new file mode 100644
+index 0000000..498d4fd
+--- /dev/null
++++ b/arch/arm/cpu/arm926ejs/aspeed/LAN9303.c
+@@ -0,0 +1,525 @@
++/*
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++ */
++#define LAN9303_C
++static const char ThisFile[] = "LAN9303.c";
++
++#include "SWFUNC.H"
++#ifdef SLT_UBOOT
++ #include <COMMINF.H>
++ #include <MAC.H>
++ #include <IO.H>
++#endif
++
++#ifdef SLT_DOS
++ #include "COMMINF.H"
++ #include <stdlib.h>
++ #include "IO.H"
++#endif
++
++#ifdef SUPPORT_PHY_LAN9303
++//#define LAN9303M
++#define I2C_Debug 0
++#define Print_DWRW 0
++#define Print_PHYRW 0
++#define I2C_TIMEOUT 10000000
++
++ULONG devbase;
++ULONG busnum;
++ULONG byte;
++ULONG data_rd;
++
++//------------------------------------------------------------
++// Basic
++//------------------------------------------------------------
++void actime(ULONG ac1, ULONG ac2, ULONG *fact, ULONG *ckh, ULONG *ckl)
++{
++ static int divcnt;
++
++ ac1 = ac1 * 50 + 1;
++ ac2 = ac2 * 50 + 1;
++
++ divcnt = 0;
++ while (ac1 > 8 || ac2 > 8) {
++ divcnt++;
++ ac1 >>= 1;
++ ac2 >>= 1;
++ }
++
++ if (ac1 < 2 ) ac1 = 2;
++ if (ac2 < 2 ) ac2 = 2;
++ if (ac1 > ac2) ac2 = 1;
++ else ac1 += 1;
++
++#ifdef PRINT_MSG
++ printf("Divcnt = %d, ckdiv = %d, ckh = %d, ckl = %d\n",(1<<divcnt)*(ac1+ac2),divcnt,ac1-1,ac2-1);
++ printf("CKH = %d us, CKL = %d us\n",(1<<divcnt)*ac1/50,(1<<divcnt)*ac2/50);
++#endif
++
++ *fact = divcnt;
++ *ckh = ac1 - 1;
++ *ckl = ac2 - 1;
++}
++
++//------------------------------------------------------------
++ULONG PollStatus()
++{
++ static ULONG status;
++ static ULONG cnt = 0;
++
++ do {
++ status = ReadSOC_DD( devbase + 0x14 ) & 0xff;
++
++ if ( ++cnt > I2C_TIMEOUT ) {
++ printf("\nWait1 Timeout at bus %d!\n", busnum);
++ printf("Status 14 = %08x\n", ReadSOC_DD(devbase + 0x14));
++ exit(0);
++ }
++ } while (status != 0);
++
++ cnt = 0;
++ do {
++ status = ReadSOC_DD( devbase + 0x10 );
++ if ( ++cnt > I2C_TIMEOUT ) {
++ printf("\nWait2 Timeout at bus %d!\n", busnum);
++ printf("Status 14 = %08x\n", ReadSOC_DD(devbase + 0x14));
++ exit(0);
++ }
++ } while (status == 0);
++
++ WriteSOC_DD( devbase + 0x10, status );
++
++ return(status);
++}
++
++
++//------------------------------------------------------------
++ULONG writeb(ULONG start, ULONG data, ULONG stop)
++{
++ WriteSOC_DD( devbase + 0x20, data);
++ WriteSOC_DD( devbase + 0x14, 0x02 | start | (stop << 5) );
++ return(PollStatus());
++}
++
++//------------------------------------------------------------
++ULONG readb(ULONG last, ULONG stop)
++{
++ static ULONG data;
++
++ WriteSOC_DD( devbase + 0x14, 0x08 | (last << 4) | (stop << 5) );
++ data = PollStatus();
++
++ if (data & 0x4) {
++ data = ReadSOC_DD( devbase + 0x20 );
++ return(data >> 8);
++ }
++ else {
++ return(-1);
++ }
++}
++
++//------------------------------------------------------------
++void Initial(ULONG base, ULONG ckh, ULONG ckl)
++{
++ static ULONG ackh;
++ static ULONG ackl;
++ static ULONG divx;
++
++ actime(ckh, ckl, &divx, &ackh, &ackl);
++ WriteSOC_DD(base + 0x00, 0x1);
++ if (ReadSOC_DD(base + 0x00) != 0x1) {
++ printf("Controller initial fail : %x\n",base);
++ exit(0);
++ }
++ WriteSOC_DD(base + 0x04, 0x77700360 | (ackh << 16) | (ackl << 12) | divx);
++ WriteSOC_DD(base + 0x08, 0x0);
++ WriteSOC_DD(base + 0x0c, 0x0);
++ WriteSOC_DD(base + 0x10, 0xffffffff);
++ WriteSOC_DD(base + 0x14, 0x00);
++ WriteSOC_DD(base + 0x1C, 0xff0000);
++ WriteSOC_DD(base + 0x20, 0x00);
++}
++
++//------------------------------------------------------------
++void print_status(ULONG status)
++{
++ if ( status & 0x02 ) printf( "Device NAK\n" );
++ if ( status & 0x08 ) printf( "Arbitration Loss\n" );
++ if ( status & 0x10 ) printf( "STOP\n" );
++ if ( status & 0x20 ) printf( "Abnormal STOP\n" );
++ if ( status & 0x40 ) printf( "SCL Low timeout\n" );
++}
++
++//------------------------------------------------------------
++void readme()
++{
++ printf("\nVersion:%s\n", version_name);
++#ifdef LAN9303M
++ printf("LAN9303M [bus] [vir_PHY_adr] [speed] [func]\n");
++#else
++ printf("LAN9303 [bus] [vir_PHY_adr] [speed] [func]\n" );
++#endif
++ printf("[bus] | 1~14: I2C bus number\n" );
++ printf("[vir_PHY_adr] | 0~1: virtual PHY address\n" );
++ printf("[speed] | 1: 100M\n" );
++ printf(" | 2: 10 M\n" );
++ printf("[func] | 0: external loopback\n" );
++ printf(" | 1: internal loopback\n" );
++}
++
++//------------------------------------------------------------
++void quit()
++{
++ WriteSOC_DD( devbase + 0x14, 0x20 );
++ PollStatus();
++ readme();
++}
++
++//------------------------------------------------------------
++// Double-Word Read/Write
++//------------------------------------------------------------
++ULONG I2C_DWRead(ULONG adr)
++{
++ static ULONG status;
++ int i;
++
++ Initial(devbase, 10, 10);
++
++ if ( Print_DWRW )
++ printf("RAdr %02x: ", adr);
++
++ status = writeb( 1, LAN9303_I2C_ADR, 0 );
++ if ( I2C_Debug )
++ printf("R1W[%02x]%02x ", status, LAN9303_I2C_ADR);
++
++ if ( status != 0x1 ) {
++ print_status(status);
++ quit();
++ exit(0);
++ }
++
++ status = writeb(0, adr, 0);
++ if ( I2C_Debug )
++ printf("R2W[%02x]%02x ", status, adr);
++ if ( !(status & 0x1) ) {
++ print_status(status);
++ quit();
++ exit(0);
++ }
++
++ status = writeb(1, LAN9303_I2C_ADR | 0x1, 0);
++ if ( I2C_Debug )
++ printf("R3W[%02x]%02x ", status, LAN9303_I2C_ADR | 0x1);
++ if ( status != 0x1 ) {
++ print_status(status);
++ quit();
++ exit(0);
++ }
++
++ if ( I2C_Debug )
++ printf("R4");
++
++ data_rd = 0;
++ for (i = 24; i >= 0; i-=8) {
++ if (i == 0) byte = readb(1, 1);
++ else byte = readb(0, 0);
++
++ if ( I2C_Debug )
++ printf("%02x ", byte);
++ data_rd = data_rd | (byte << i);
++ }
++
++ if ( Print_DWRW )
++ printf("%08x\n", data_rd);
++
++ return (data_rd);
++} // End ULONG I2C_DWRead(ULONG adr)
++
++//------------------------------------------------------------
++void I2C_DWWrite(ULONG adr, ULONG dwdata)
++{
++ static ULONG status;
++ int i;
++ ULONG endx;
++
++ Initial(devbase, 10, 10);
++ if (Print_DWRW)
++ printf("WAdr %02x: ", adr);
++
++ status = writeb(1, LAN9303_I2C_ADR, 0);
++ if ( I2C_Debug )
++ printf("W1[%02x]%02x ", status, LAN9303_I2C_ADR);
++ if ( status != 0x1 ) {
++ print_status(status);
++ quit();
++ exit(0);
++ }
++ status = writeb(0, adr, 0);
++ if ( I2C_Debug )
++ printf("W2[%02x]%02x ", status, adr);
++ if ( !(status & 0x1) ) {
++ print_status(status);
++ quit();
++ exit(0);
++ }
++
++ if (I2C_Debug)
++ printf("W3");
++ endx = 0;
++ for (i = 24; i >= 0; i-=8) {
++ if (i == 0)
++ endx = 1;
++ byte = (dwdata >> i) & 0xff;
++ status = writeb(0, byte, endx);
++
++ if (I2C_Debug)
++ printf("[%02x]%02x ", status, byte);
++ if (!(status & 0x1)) {
++ print_status(status);
++ quit();
++ exit(0);
++ }
++ }
++
++ if (Print_DWRW) printf("%08x\n", dwdata);
++} // End void I2C_DWWrite(ULONG adr, ULONG dwdata)
++
++//------------------------------------------------------------
++// PHY Read/Write
++//------------------------------------------------------------
++ULONG LAN9303_PHY_Read(ULONG phy_adr, ULONG reg_adr)
++{
++ static ULONG data_rd;
++
++ I2C_DWWrite(0x2a, ((phy_adr & 0x1f) << 11) | ((reg_adr & 0x1f) << 6));//[0A8h]PMI_ACCESS
++ do {
++ data_rd = I2C_DWRead (0x2a);
++ } while(data_rd & 0x00000001);//[0A8h]PMI_ACCESS
++
++ data_rd = I2C_DWRead (0x29);//[0A4h]PMI_DATA
++ if (Print_PHYRW)
++ printf("PHY:%2d, Reg:%2d, Data:%08x\n", phy_adr, reg_adr, data_rd);
++
++ return(data_rd);
++}
++
++//------------------------------------------------------------
++void LAN9303_PHY_Write(ULONG phy_adr, ULONG reg_adr, ULONG data_wr)
++{
++ static ULONG data_rd;
++
++ I2C_DWWrite(0x29, data_wr);//[0A4h]PMI_DATA
++
++ I2C_DWWrite(0x2a, ((phy_adr & 0x1f) << 11) | ((reg_adr & 0x1f) << 6) | 0x2);//[0A8h]PMI_ACCESS
++ do {
++ data_rd = I2C_DWRead (0x2a);
++ } while(data_rd & 0x00000001);//[0A8h]PMI_ACCESS
++}
++
++//------------------------------------------------------------
++ULONG LAN9303_PHY_Read_WD(ULONG data_ctl)
++{
++ static ULONG data_rd;
++
++ I2C_DWWrite(0x2a, data_ctl);//[0A8h]PMI_ACCESS
++ do {
++ data_rd = I2C_DWRead (0x2a);
++ } while(data_rd & 0x00000001);//[0A8h]PMI_ACCESS
++
++ data_rd = I2C_DWRead (0x29);//[0A4h]PMI_DATA
++ if (Print_PHYRW)
++ printf("WD Data:%08x\n", data_ctl);
++
++ return(data_rd);
++}
++
++//------------------------------------------------------------
++void LAN9303_PHY_Write_WD(ULONG data_ctl, ULONG data_wr)
++{
++ static ULONG data_rd;
++
++ I2C_DWWrite( 0x29, data_wr ); //[0A4h]PMI_DATA
++ I2C_DWWrite( 0x2a, data_ctl ); //[0A8h]PMI_ACCESS
++ do {
++ data_rd = I2C_DWRead (0x2a);
++ } while(data_rd & 0x00000001); //[0A8h]PMI_ACCESS
++}
++
++//------------------------------------------------------------
++// Virtual PHY Read/Write
++//------------------------------------------------------------
++ULONG LAN9303_VirPHY_Read(ULONG reg_adr)
++{
++ static ULONG data_rd;
++
++ data_rd = I2C_DWRead (0x70+reg_adr);//[1C0h]
++ if ( Print_PHYRW )
++ printf("VirPHY Reg:%2d, Data:%08x\n", reg_adr, data_rd);
++
++ return(data_rd);
++}
++
++//------------------------------------------------------------
++void LAN9303_VirPHY_Write(ULONG reg_adr, ULONG data_wr)
++{
++ I2C_DWWrite(0x70+reg_adr, data_wr);//[1C0h]
++}
++
++//------------------------------------------------------------
++void LAN9303_VirPHY_RW(ULONG reg_adr, ULONG data_clr, ULONG data_set)
++{
++ I2C_DWWrite(0x70+reg_adr, (LAN9303_VirPHY_Read(reg_adr) & (~data_clr)) | data_set);//[1C0h]
++}
++
++//------------------------------------------------------------
++// PHY Read/Write
++//------------------------------------------------------------
++ULONG LAN9303_Read(ULONG adr)
++{
++ static ULONG data_rd;
++
++ I2C_DWWrite(0x6c, 0xc00f0000 | adr & 0xffff);//[1B0h]SWITCH_CSR_CMD
++ do {
++ data_rd = I2C_DWRead (0x6c);
++ } while(data_rd & 0x80000000);//[1B0h]SWITCH_CSR_CMD
++
++ return(I2C_DWRead (0x6b));//[1ACh]SWITCH_CSR_DATA
++}
++
++//------------------------------------------------------------
++void LAN9303_Write(ULONG adr, ULONG data)
++{
++ static ULONG data_rd;
++
++ I2C_DWWrite(0x6b, data);//[1ACh]SWITCH_CSR_DATA
++ I2C_DWWrite(0x6c, 0x800f0000 | adr & 0xffff);//[1B0h]SWITCH_CSR_CMD
++
++ do {
++ data_rd = I2C_DWRead (0x6c);
++ } while(data_rd & 0x80000000);//[1B0h]SWITCH_CSR_CMD
++}
++
++//------------------------------------------------------------
++void LAN9303(int num, int phy_adr, int speed, int int_loopback)
++{
++ static ULONG data_rd;
++
++ //------------------------------------------------------------
++ // I2C Initial
++ //------------------------------------------------------------
++ busnum = num;
++ if (busnum <= 7) devbase = 0x1E78A000 + ( busnum * 0x40);
++ else devbase = 0x1E78A300 + ((busnum-8) * 0x40);
++ Initial(devbase, 10, 10);
++
++ //------------------------------------------------------------
++ // LAN9303 Register Setting
++ //------------------------------------------------------------
++ printf("----> Start\n");
++ if (int_loopback == 0) {
++ //Force Speed & external loopback
++ if (speed == 1) { //100M
++ LAN9303_VirPHY_RW( 0, 0xffff, 0x2300 ); //adr clr set //VPHY_BASIC_CTRL
++ LAN9303_VirPHY_RW( 11, 0xffff, 0x2300 ); //adr clr set //P1_MII_BASIC_CONTROL
++ LAN9303_PHY_Write( phy_adr + 1, 0, 0x2300 );
++ LAN9303_PHY_Write( phy_adr + 2, 0, 0x2300 );
++ }
++ else {
++ LAN9303_VirPHY_RW( 0, 0xffff, 0x0100 ); //adr clr set //VPHY_BASIC_CTRL
++ LAN9303_VirPHY_RW( 11, 0xffff, 0x0100 ); //adr clr set //P1_MII_BASIC_CONTROL
++ LAN9303_PHY_Write( phy_adr + 1, 0, 0x0100);
++ LAN9303_PHY_Write( phy_adr + 2, 0, 0x0100);
++ }
++
++ LAN9303_Write( 0x180c, 0x00000001 ); // SWE_VLAN_WR_DATA
++ LAN9303_Write( 0x180b, 0x00000010 ); // SWE_VLAN_CMD
++ do {data_rd = LAN9303_Read (0x1810);} while(data_rd & 0x1);
++
++ LAN9303_Write( 0x180c, 0x00000002 ); // SWE_VLAN_WR_DATA
++ LAN9303_Write( 0x180b, 0x00000011 ); // SWE_VLAN_CMD
++ do {data_rd = LAN9303_Read (0x1810);} while(data_rd & 0x1);
++
++ LAN9303_Write( 0x180c, 0x00000003 ); // SWE_VLAN_WR_DATA
++ LAN9303_Write( 0x180b, 0x00000012 ); // SWE_VLAN_CMD
++ do {data_rd = LAN9303_Read (0x1810);} while(data_rd & 0x1);
++
++#ifdef LAN9303M
++ LAN9303_Write( 0x180c, 0x00022001 ); // SWE_VLAN_WR_DATA
++ LAN9303_Write( 0x180b, 0x00000000 ); // SWE_VLAN_CMD
++ do {data_rd = LAN9303_Read (0x1810);} while(data_rd & 0x1);
++
++ LAN9303_Write( 0x180c, 0x00024002 ); // SWE_VLAN_WR_DATA
++ LAN9303_Write( 0x180b, 0x00000001 ); // SWE_VLAN_CMD
++ do {data_rd = LAN9303_Read (0x1810);} while(data_rd & 0x1);
++
++ LAN9303_Write( 0x180c, 0x0002a003 ); // SWE_VLAN_WR_DATA
++ LAN9303_Write( 0x180b, 0x00000002 ); // SWE_VLAN_CMD
++ do {data_rd = LAN9303_Read (0x1810);} while(data_rd & 0x1);
++#else
++ LAN9303_Write( 0x180c, 0x0002a001 ); // SWE_VLAN_WR_DATA
++ LAN9303_Write( 0x180b, 0x00000000 ); // SWE_VLAN_CMD
++ do {data_rd = LAN9303_Read (0x1810);} while(data_rd & 0x1);
++
++ LAN9303_Write( 0x180c, 0x0000a002 ); // SWE_VLAN_WR_DATA
++ LAN9303_Write( 0x180b, 0x00000001 ); // SWE_VLAN_CMD
++ do {data_rd = LAN9303_Read (0x1810);} while(data_rd & 0x1);
++
++ LAN9303_Write( 0x180c, 0x00022003 ); // SWE_VLAN_WR_DATA
++ LAN9303_Write( 0x180b, 0x00000002 ); // SWE_VLAN_CMD
++ do {data_rd = LAN9303_Read (0x1810);} while(data_rd & 0x1);
++#endif
++ LAN9303_Write( 0x1840, 0x00000007);
++ }
++ else if ( int_loopback == 1 ) {
++ //Force Speed & internal loopback
++ if ( speed == 1 ) {
++ //100M
++ LAN9303_VirPHY_RW( 0, 0xffff, 0x6300 ); // adr clr set //VPHY_BASIC_CTRL
++ LAN9303_VirPHY_RW( 11, 0xffff, 0x6300 ); // adr clr set //P1_MII_BASIC_CONTROL
++ LAN9303_PHY_Write( phy_adr + 1, 0, 0x6300 );
++ LAN9303_PHY_Write( phy_adr + 2, 0, 0x6300 );
++ }
++ else {
++ LAN9303_VirPHY_RW( 0, 0xffff, 0x4100 ); // adr clr set //VPHY_BASIC_CTRL
++ LAN9303_VirPHY_RW( 11, 0xffff, 0x4100 ); // adr clr set //P1_MII_BASIC_CONTROL
++ LAN9303_PHY_Write( phy_adr + 1, 0, 0x4100 );
++ LAN9303_PHY_Write( phy_adr + 2, 0, 0x4100 );
++ }
++ }
++ else {
++ //Force Speed
++ if (speed == 1) {
++ //100M
++ LAN9303_VirPHY_RW( 0, 0xffff, 0x2300 ); // adr clr set //VPHY_BASIC_CTRL
++ LAN9303_VirPHY_RW( 11, 0xffff, 0x2300 ); // adr clr set //P1_MII_BASIC_CONTROL
++ LAN9303_PHY_Write( phy_adr + 1, 0, 0x2300 );
++ LAN9303_PHY_Write( phy_adr + 2, 0, 0x2300 );
++ }
++ else {
++ LAN9303_VirPHY_RW( 0, 0xffff, 0x0100 ); // adr clr set //VPHY_BASIC_CTRL
++ LAN9303_VirPHY_RW( 11, 0xffff, 0x0100 ); // adr clr set //P1_MII_BASIC_CONTROL
++ LAN9303_PHY_Write( phy_adr + 1, 0, 0x0100 );
++ LAN9303_PHY_Write( phy_adr + 2, 0, 0x0100 );
++ }
++#ifdef LAN9303M
++#else
++ if (int_loopback == 3) {
++ //[LAN9303]IEEE measurement
++ data_rd = LAN9303_PHY_Read(phy_adr+1, 27);//PHY_SPECIAL_CONTROL_STAT_IND_x
++ LAN9303_PHY_Write(phy_adr+1, 27, (data_rd & 0x9fff) | 0x8000);//PHY_SPECIAL_CONTROL_STAT_IND_x
++
++ data_rd = LAN9303_PHY_Read(phy_adr+2, 27);//PHY_SPECIAL_CONTROL_STAT_IND_x
++ LAN9303_PHY_Write(phy_adr+2, 27, (data_rd & 0x9fff) | 0x8000);//PHY_SPECIAL_CONTROL_STAT_IND_x
++ }
++#endif
++ } // End if (int_loopback == 0)
++} // End void LAN9303(int num, int phy_adr, int speed, int int_loopback)
++#endif // SUPPORT_PHY_LAN9303
++
+diff --git a/arch/arm/cpu/arm926ejs/aspeed/LIB.H b/arch/arm/cpu/arm926ejs/aspeed/LIB.H
+new file mode 100644
+index 0000000..a7c61dd
+--- /dev/null
++++ b/arch/arm/cpu/arm926ejs/aspeed/LIB.H
+@@ -0,0 +1,37 @@
++/*
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++ */
++#ifndef LIB_H
++#define LIB_H
++
++#include "TYPEDEF.H"
++
++//
++// Macro
++//
++#define INTFUNC int386
++
++#define OUTDWPORT outpd
++#define INDWPORT inpd
++#define OUTPUT outp
++#define INPUT inp
++
++//
++// PCI
++//
++ULONG ReadPCIReg (ULONG ulPCIConfigAddress, BYTE jOffest, ULONG ulMask);
++ULONG FindPCIDevice (USHORT usVendorID, USHORT usDeviceID, USHORT usBusType);
++VOID WritePCIReg (ULONG ulPCIConfigAddress, BYTE jOffest, ULONG ulMask, ULONG ulData);
++
++//
++// Map Resource
++//
++ULONG MapPhysicalToLinear (ULONG ulBaseAddress, ULONG ulSize);
++#endif
+diff --git a/arch/arm/cpu/arm926ejs/aspeed/LIB.c b/arch/arm/cpu/arm926ejs/aspeed/LIB.c
+new file mode 100644
+index 0000000..f2a0c54
+--- /dev/null
++++ b/arch/arm/cpu/arm926ejs/aspeed/LIB.c
+@@ -0,0 +1,184 @@
++/*
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++ */
++#define LIB_C
++static const char ThisFile[] = "LIB.c";
++
++#include "SWFUNC.H"
++
++#ifdef SLT_UBOOT
++ #include <common.h>
++ #include <command.h>
++#endif
++#ifdef SLT_DOS
++#include <stdlib.h>
++#include <stdio.h>
++#include <time.h>
++#include <conio.h>
++#include <dos.h>
++#include <mem.h>
++#endif
++
++#include "LIB.H"
++#include "TYPEDEF.H"
++
++#ifdef USE_P2A
++//------------------------------------------------------------
++// PCI
++//------------------------------------------------------------
++ULONG ReadPCIReg (ULONG ulPCIConfigAddress, BYTE jOffest, ULONG ulMask)
++{
++#ifndef Windows
++ OUTDWPORT(0xcf8, ulPCIConfigAddress + jOffest);
++
++ return (((ULONG)INDWPORT(0xcfc)) & ulMask);
++#else
++ WRITE_PORT_ULONG((PULONG)0xcf8, ulPCIConfigAddress + jOffest);
++
++ return (READ_PORT_ULONG((PULONG)0xcfc) & ulMask);
++#endif
++}
++
++//------------------------------------------------------------
++VOID WritePCIReg (ULONG ulPCIConfigAddress, BYTE jOffest, ULONG ulMask, ULONG ulData)
++{
++#ifndef Windows
++ OUTDWPORT(0xcf8, ulPCIConfigAddress + jOffest);
++ OUTDWPORT(0xcfc, (INDWPORT(0xcfc) & ulMask | ulData));
++#else
++ WRITE_PORT_ULONG((PULONG)0xcf8, ulPCIConfigAddress + jOffest);
++ WRITE_PORT_ULONG((PULONG)0xcfc, (READ_PORT_ULONG((PULONG)0xcfc) & ulMask | ulData));
++#endif
++}
++
++//------------------------------------------------------------
++ULONG FindPCIDevice (USHORT usVendorID, USHORT usDeviceID, USHORT usBusType)
++{
++//Return: ulPCIConfigAddress
++//usBusType: ACTIVE/PCI/AGP/PCI-E
++
++ ULONG Base[256];
++ ULONG ebx;
++ USHORT i;
++ USHORT j;
++
++ for (i = 0; i < 256; i++) {
++ Base[i] = 0x80000000 + 0x10000 * i;
++ }
++
++ if (usBusType == PCI)
++ {
++ ebx = 0x80000000;
++ }
++ else if (usBusType == PCIE)
++ {
++ ebx = 0x80020000;
++ }
++ else // AGP and ACTIVE
++ {
++ ebx = 0x80010000;
++ }
++
++ if ( usBusType != ACTIVE ) //AGP, PCI, PCIE
++ {
++ for (i = 0; i < 32; i++)
++ {
++ ebx = ebx + (0x800);
++ if (((USHORT)ReadPCIReg(ebx, 0, 0xffff) == usVendorID) && ((USHORT)(ReadPCIReg(ebx, 0, 0xffff0000) >> 16) == usDeviceID))
++ {
++ return ebx;
++ }
++ }
++ return 0;
++ }
++ else //ACTIVE
++ {
++ for (j = 0; j < 256; j++)
++ {
++ ebx = Base[j];
++ for (i = 0; i < 32; i++)
++ {
++ ebx = ebx + (0x800);
++ if (((USHORT)ReadPCIReg(ebx, 0, 0xffff) == usVendorID) && ((USHORT)(ReadPCIReg(ebx, 0, 0xffff0000) >> 16) == usDeviceID))
++ {
++ return ebx;
++ }
++ }
++ }
++ return 0;
++ }
++} // End ULONG FindPCIDevice (USHORT usVendorID, USHORT usDeviceID, USHORT usBusType)
++#endif
++//------------------------------------------------------------
++// Allocate Resource
++//------------------------------------------------------------
++#ifdef SLT_DOS
++ULONG InitDOS32()
++{
++ union REGS regs ;
++
++ regs.w.ax = 0xee00;
++ INTFUNC(0x31, &regs, &regs) ;
++
++ if(regs.w.ax >= 0x301) // DOS32 version >= 3.01 ?
++ return 1;
++ else
++ return 0;
++}
++
++//------------------------------------------------------------
++USHORT CheckDOS()
++{
++ union REGS regs;
++
++ regs.w.ax = 0xeeff;
++ int386(0x31, &regs, &regs);
++ if (regs.x.eax == 0x504d4457)
++ {
++ return 0;
++ } else {
++ printf("PMODEW Init. fail\n");
++ return 1;
++ }
++}
++
++//------------------------------------------------------------
++ULONG MapPhysicalToLinear (ULONG ulBaseAddress, ULONG ulSize)
++{
++ union REGS regs;
++
++ regs.w.ax = 0x0800; // map physcial memory
++ regs.w.bx = ulBaseAddress >> 16; // bx:cx = physical address
++ regs.w.cx = ulBaseAddress;
++ regs.w.si = ulSize >> 16; // si:di = mapped memory block size
++ regs.w.di = ulSize;
++ INTFUNC(0x31, &regs, &regs); // int386(0x31, &regs, &regs);
++ if (regs.w.cflag == 0)
++ return (ULONG) (regs.w.bx << 16 + regs.w.cx); // Linear Addr = bx:cx
++ else
++ return 0;
++}
++
++//------------------------------------------------------------
++USHORT FreePhysicalMapping(ULONG udwLinAddress)
++{
++ union REGS regs;
++
++ regs.w.ax = 0x0801;
++ regs.w.bx = udwLinAddress >> 16;
++ regs.w.cx = udwLinAddress & 0xFFFF;
++ int386(0x31, &regs, &regs);
++
++ if (regs.x.cflag)
++ return ((USHORT) 0);
++ else return ((USHORT) 1);
++}
++#endif
++
+diff --git a/arch/arm/cpu/arm926ejs/aspeed/LIB_SPI.H b/arch/arm/cpu/arm926ejs/aspeed/LIB_SPI.H
+new file mode 100644
+index 0000000..78c8f1e
+--- /dev/null
++++ b/arch/arm/cpu/arm926ejs/aspeed/LIB_SPI.H
+@@ -0,0 +1,23 @@
++/*
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++ */
++#ifndef LIB_SPI_H
++#define LIB_SPI_H
++
++#ifdef SPI_BUS
++ // MMIO Functions
++ VOID MOutwm (ULONG, ULONG, USHORT);
++ VOID MOutdwm (ULONG, ULONG, ULONG);
++ ULONG MIndwm (ULONG, ULONG);
++
++ void spim_init(int cs);
++#endif
++
++#endif // LIB_SPI_H
+diff --git a/arch/arm/cpu/arm926ejs/aspeed/MAC.H b/arch/arm/cpu/arm926ejs/aspeed/MAC.H
+new file mode 100644
+index 0000000..6732117
+--- /dev/null
++++ b/arch/arm/cpu/arm926ejs/aspeed/MAC.H
+@@ -0,0 +1,157 @@
++/*
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++ */
++#ifndef MAC_H
++#define MAC_H
++
++#ifdef SPI_BUS
++ #include <stdio.h>
++ #include <stdlib.h>
++ #include <time.h>
++ #define SPI_CS 1
++#endif
++// ( USE_P2A | USE_LPC )
++
++#if defined(LinuxAP)
++ #include <stdio.h>
++ #include <stdlib.h>
++ #include <string.h>
++ #include <stdarg.h>
++ #include <unistd.h>
++ #include <string.h>
++ #include <fcntl.h>
++ #include <pthread.h>
++ #include <sys/mman.h>
++ #include <sys/io.h>
++#endif
++#ifdef SLT_UBOOT
++ #include <common.h>
++ #include <command.h>
++#endif
++#ifdef SLT_DOS
++ #include <stdio.h>
++ #include <stdlib.h>
++ #include <time.h>
++ #include <conio.h>
++ #include <dos.h>
++ #include <mem.h>
++#endif
++
++#include "NCSI.H"
++#include "IO.H"
++
++// --------------------------------------------------------------
++// Define
++// --------------------------------------------------------------
++
++//#define Force_Enable_MAC34 //[ON][SLT:off] (Force enable mac34)
++//#define Force_Enable_NewMDIO //[off][SLT:off] (Force enable new MDC/MDIO)
++//#define Enable_Fast_SCU //[off]
++//#define Enable_Old_Style //[off]
++#define ENABLE_DASA //[ON]
++//#define Enable_AST2300_Int125MHz //[off]
++//#define ENABLE_ARP_2_WOL //[off]
++//#define Enable_MAC_SWRst //[off]
++
++#define Enable_Runt
++//#define Enable_Jumbo
++//#define Enable_BufMerge
++//#define Disable_VGA
++
++//#define SelectSimpleBoundary //[off] Using in debug
++//#define SelectSimpleData //[off] Using in debug
++//#define SelectSimpleLength 1512 //[off] 60(0x3c) ~ 1514(0x5ea); 1512(0x5e8)
++//#define SelectDesNumber 8 //[off] 1 ~
++//#define SelectSimpleDA //[off] Using in debug
++//#define SelectSimpleDes //[off]
++//#define SelectLengthInc //[off] Using in debug
++
++#define SimpleData_Fix //[ON] Using in debug
++#define SimpleData_FixNum 12
++#define SimpleData_FixVal00 0x00000000 //[0]no SelectSimpleDA: (60: 0412 8908)(1512: e20d e9da)
++#define SimpleData_FixVal01 0xffffffff //[0]no SelectSimpleDA: (60: f48c f14d)(1512: af05 260c)
++#define SimpleData_FixVal02 0x55555555 //[0]no SelectSimpleDA: (60: 5467 5ecb)(1512: d90a 5368)
++#define SimpleData_FixVal03 0xaaaaaaaa //[0]no SelectSimpleDA: (60: a4f9 268e)(1512: 9402 9cbe)
++#define SimpleData_FixVal04 0x5a5a5a5a //[1]no SelectSimpleDA: (60: 7f01 e22d)(1512: 4fd3 8012)
++#define SimpleData_FixVal05 0xc3c3c3c3 //[1]no SelectSimpleDA: (60: 5916 02d5)(1512: 99f1 6127)
++#define SimpleData_FixVal06 0x96969696 //[1]no SelectSimpleDA: (60: 0963 d516)(1512: a2f6 db95)
++#define SimpleData_FixVal07 0xf0f0f0f0 //[1]no SelectSimpleDA: (60: dfea 4dab)(1512: 39dc f576)
++#define SimpleData_FixVal08 0x5555aaaa //[2]no SelectSimpleDA: (60: b61b 5777)(1512: 4652 ddb0)
++#define SimpleData_FixVal09 0xffff0000 //[2]no SelectSimpleDA: (60: 16f0 f8f1)(1512: 305d a8d4)
++#define SimpleData_FixVal10 0x5a5aa5a5 //[2]no SelectSimpleDA: (60: 9d7d eb91)(1512: d08b 0eca)
++#define SimpleData_FixVal11 0xc3c33c3c //[2]no SelectSimpleDA: (60: bb6a 0b69)(1512: 06a9 efff)
++
++#define SelectSimpleDA_Dat0 0x67052301
++#define SelectSimpleDA_Dat1 0xe0cda089
++#define SelectSimpleDA_Dat2 0x98badcfe
++
++#define SelectWOLDA_DatH 0x206a
++#define SelectWOLDA_DatL 0x8a374d9b
++
++#define MOVE_DATA_MB_SEC 800 // MByte per second to move data
++
++//---------------------------------------------------------
++// Frame size
++//---------------------------------------------------------
++#define ENABLE_RAND_SIZE 0
++#define Rand_Sed 0xffccd
++#define FRAME_Rand_Simple 0
++#define MIN_FRAME_RAND_SIZE 60
++#define MAX_FRAME_RAND_SIZE 1514
++
++#define FRAME_SELH_PERD 7
++#ifdef Enable_Jumbo
++// #define FRAME_LENH 9212 //max:9212
++// #define FRAME_LENL 9211 //max:9212
++ #define FRAME_LENH 9212 //max:9212
++ #define FRAME_LENL 9212 //max:9212
++// #define FRAME_LENH 8120
++// #define FRAME_LENL 8119
++// #define FRAME_LENH 7000
++// #define FRAME_LENL 6999
++// #define FRAME_LENH 4095
++// #define FRAME_LENL 4094
++// #define FRAME_LENH 2040
++// #define FRAME_LENL 2039
++#else
++ #ifdef SelectSimpleLength
++// #define FRAME_LENH ( SelectSimpleLength + 1 )
++// #define FRAME_LENL ( SelectSimpleLength )
++ #define FRAME_LENH SelectSimpleLength
++ #define FRAME_LENL SelectSimpleLength
++ #else
++// #define FRAME_LENH 1514 //max:1514
++// #define FRAME_LENL 1513 //max:1514
++ #define FRAME_LENH 1514 //max:1514
++ #define FRAME_LENL 1514 //max:1514
++ #endif
++#endif
++
++const ULONG ARP_org_data[16] = {
++ 0xffffffff,
++ 0x0000ffff, // SA:00 00
++ 0x12345678, // SA:12 34 56 78
++ 0x01000608, // ARP(0x0806)
++ 0x04060008,
++ 0x00000100, // sender MAC Address: 00 00
++ 0x12345678, // sender MAC Address: 12 34 56 78
++ 0xeb00a8c0, // sender IP Address: 192.168.0.235
++ 0x00000000, // target MAC Address: 00 00 00 00
++ 0xa8c00000, // target MAC Address: 00 00, sender IP Address:192.168
++ 0x00000100, // sender IP Address: 0.1
++// 0x0000de00, // sender IP Address: 0.222
++ 0x00000000,
++ 0x00000000,
++ 0x00000000,
++ 0x00000000,
++ 0xc68e2bd5
++};
++
++#endif // MAC_H
+diff --git a/arch/arm/cpu/arm926ejs/aspeed/MAC.c b/arch/arm/cpu/arm926ejs/aspeed/MAC.c
+new file mode 100644
+index 0000000..829da92
+--- /dev/null
++++ b/arch/arm/cpu/arm926ejs/aspeed/MAC.c
+@@ -0,0 +1,2085 @@
++/*
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++ */
++#define MAC_C
++static const char ThisFile[] = "MAC.c";
++
++#include "SWFUNC.H"
++
++#ifdef SLT_UBOOT
++ #include <common.h>
++ #include <command.h>
++ #include <COMMINF.H>
++ #include "STDUBOOT.H"
++#endif
++#ifdef SLT_DOS
++ #include <stdio.h>
++ #include <stdlib.h>
++ #include <conio.h>
++ #include <string.h>
++ #include "COMMINF.H"
++#endif
++
++#include "MAC.H"
++
++double Avg_frame_len;
++ULONG Check_Des_Val;
++ULONG wp_fir;
++ULONG wp;
++ULONG FRAME_LEN_Cur;
++ULONG gdata;
++ULONG CheckDesFail_DesNum;
++ULONG VGAMode;
++ULONG SCU_1ch_old;
++ULONG SCU_0ch_old;
++ULONG SCU_48h_default;
++ULONG SCU_2ch_old;
++ULONG SCU_80h_old;
++ULONG SCU_74h_old;
++ULONG SCU_a4h_old;
++ULONG SCU_88h_old;
++ULONG WDT_0ch_old;
++ULONG SCU_04h_mix;
++ULONG SCU_04h_old;
++ULONG WDT_2ch_old;
++char SCU_oldvld = 0;
++
++#ifdef SLT_UBOOT
++#else
++ static double timeused;
++#endif
++// -------------------------------------------------------------
++
++void Debug_delay (void) {
++ #ifdef DbgPrn_Enable_Debug_delay
++ GET_CAHR();
++ #endif
++}
++
++
++
++
++void dump_mac_ROreg (void) {
++ DELAY(Delay_MACDump);
++ printf("\n");
++ printf("[MAC-H] ROReg A0h~ACh: %08lx %08lx %08lx %08lx\n", ReadSOC_DD(H_MAC_BASE+0xA0), ReadSOC_DD(H_MAC_BASE+0xA4), ReadSOC_DD(H_MAC_BASE+0xA8), ReadSOC_DD(H_MAC_BASE+0xAC));
++ printf("[MAC-H] ROReg B0h~BCh: %08lx %08lx %08lx %08lx\n", ReadSOC_DD(H_MAC_BASE+0xB0), ReadSOC_DD(H_MAC_BASE+0xB4), ReadSOC_DD(H_MAC_BASE+0xB8), ReadSOC_DD(H_MAC_BASE+0xBC));
++ printf("[MAC-H] ROReg C0h~C8h: %08lx %08lx %08lx \n", ReadSOC_DD(H_MAC_BASE+0xC0), ReadSOC_DD(H_MAC_BASE+0xC4), ReadSOC_DD(H_MAC_BASE+0xC8));
++}
++
++//------------------------------------------------------------
++// SCU
++//------------------------------------------------------------
++void recov_scu (void) {
++ #ifdef DbgPrn_FuncHeader
++ printf ("recov_scu\n");
++ Debug_delay();
++ #endif
++
++ //MAC
++ WriteSOC_DD( H_MAC_BASE + 0x08, MAC_08h_old );
++ WriteSOC_DD( H_MAC_BASE + 0x0c, MAC_0ch_old );
++ WriteSOC_DD( H_MAC_BASE + 0x40, MAC_40h_old );
++
++ //SCU
++ WriteSOC_DD( SCU_BASE + 0x04, SCU_04h_old );
++ WriteSOC_DD( SCU_BASE + 0x08, SCU_08h_old );
++ WriteSOC_DD( SCU_BASE + 0x0c, SCU_0ch_old );
++ WriteSOC_DD( SCU_BASE + 0x1c, SCU_1ch_old );
++ WriteSOC_DD( SCU_BASE + 0x2c, SCU_2ch_old );
++ WriteSOC_DD( SCU_BASE + 0x48, SCU_48h_old );
++// WriteSOC_DD( SCU_BASE + 0x70, SCU_70h_old );
++ WriteSOC_DD( SCU_BASE + 0x74, SCU_74h_old );
++ WriteSOC_DD( SCU_BASE + 0x7c, SCU_7ch_old );
++ WriteSOC_DD( SCU_BASE + 0x80, SCU_80h_old );
++ WriteSOC_DD( SCU_BASE + 0x88, SCU_88h_old );
++ WriteSOC_DD( SCU_BASE + 0x90, SCU_90h_old );
++ WriteSOC_DD( SCU_BASE + 0xa4, SCU_a4h_old );
++ WriteSOC_DD( SCU_BASE + 0xac, SCU_ach_old );
++ #ifdef AST1010_IOMAP
++ WriteSOC_DD( SCU_BASE + 0x11C, SCU_11Ch_old );
++ #endif
++
++ //WDT
++ #ifdef AST1010_IOMAP
++ #else
++ // WriteSOC_DD(0x1e78500c, WDT_0ch_old);
++ // WriteSOC_DD(0x1e78502c, WDT_2ch_old);
++ #endif
++
++ if ( ASTChipType == 3 ) {
++ if ( SCU_f0h_old & 0x01 ) WriteSOC_DD( SCU_BASE + 0xf0, 0xAEED0001 ); //Enable MAC34
++ if ( SCU_f0h_old & 0x02 ) WriteSOC_DD( SCU_BASE + 0xf0, 0x2000DEEA ); //Enable Decode
++ if ( SCU_f0h_old & 0x04 ) WriteSOC_DD( SCU_BASE + 0xf0, 0xA0E0E0D3 ); //Enable I2S
++ if ( SCU_f0h_old & 0x08 ) WriteSOC_DD( SCU_BASE + 0xf0, 0x4D0E0E0A ); //Enable PCI Host
++ if ( SCU_f0h_old & 0x10 ) WriteSOC_DD( SCU_BASE + 0xf0, 0x10ADDEED ); //Enable IR
++ if ( SCU_f0h_old & 0x20 ) WriteSOC_DD( SCU_BASE + 0xf0, 0x66559959 ); //Enabel Buffer Merge
++ if ( SCU_f0h_old & 0x40 ) WriteSOC_DD( SCU_BASE + 0xf0, 0x68961A33 ); //Enable PS2 IO
++ if ( SCU_f0h_old & 0x80 ) WriteSOC_DD( SCU_BASE + 0xf0, 0x68971A33 ); //Enable PS2 IO
++ }
++} // End void recov_scu (void)
++
++void read_scu (void) {
++ #ifdef DbgPrn_FuncHeader
++ printf ("read_scu\n");
++ Debug_delay();
++ #endif
++
++ if (!SCU_oldvld) {
++ //SCU
++ SCU_04h_old = ReadSOC_DD( SCU_BASE + 0x04 );
++ SCU_08h_old = ReadSOC_DD( SCU_BASE + 0x08 );
++ SCU_0ch_old = ReadSOC_DD( SCU_BASE + 0x0c );
++ SCU_1ch_old = ReadSOC_DD( SCU_BASE + 0x1c );
++ SCU_2ch_old = ReadSOC_DD( SCU_BASE + 0x2c );
++ SCU_48h_old = ReadSOC_DD( SCU_BASE + 0x48 );
++ SCU_70h_old = ReadSOC_DD( SCU_BASE + 0x70 );
++ SCU_74h_old = ReadSOC_DD( SCU_BASE + 0x74 );
++ SCU_7ch_old = ReadSOC_DD( SCU_BASE + 0x7c );
++ SCU_80h_old = ReadSOC_DD( SCU_BASE + 0x80 );
++ SCU_88h_old = ReadSOC_DD( SCU_BASE + 0x88 );
++ SCU_90h_old = ReadSOC_DD( SCU_BASE + 0x90 );
++ SCU_a4h_old = ReadSOC_DD( SCU_BASE + 0xa4 );
++ SCU_ach_old = ReadSOC_DD( SCU_BASE + 0xac );
++ SCU_f0h_old = ReadSOC_DD( SCU_BASE + 0xf0 );
++ #ifdef AST1010_IOMAP
++ SCU_11Ch_old = ReadSOC_DD( SCU_BASE + 0x11C );
++ #endif
++
++ //WDT
++ #ifdef AST1010_IOMAP
++ #else
++ WDT_0ch_old = ReadSOC_DD( 0x1e78500c );
++ WDT_2ch_old = ReadSOC_DD( 0x1e78502c );
++ #endif
++
++ SCU_oldvld = 1;
++ } // End if (!SCU_oldvld)
++} // End read_scu()
++
++void Setting_scu (void)
++{
++ //SCU
++ if (AST1010) {
++ do {
++ WriteSOC_DD( SCU_BASE + 0x00 , 0x1688a8a8);
++ #ifndef SLT_UBOOT
++ WriteSOC_DD( SCU_BASE + 0x70 , SCU_70h_old & 0xfffffffe); // Disable CPU
++ #endif
++ } while ( ReadSOC_DD( SCU_BASE + 0x00 ) != 0x1 );
++
++ #if( AST1010_IOMAP == 1)
++ WriteSOC_DD( SCU_BASE + 0x11C, 0x00000000); // Disable Cache functionn
++ #endif
++ }
++ else {
++ do {
++ WriteSOC_DD( SCU_BASE + 0x00, 0x1688a8a8);
++ #ifndef SLT_UBOOT
++ WriteSOC_DD( SCU_BASE + 0x70, SCU_70h_old | 0x3 ); // Disable CPU
++ #endif
++ } while ( ReadSOC_DD( SCU_BASE + 0x00 ) != 0x1 );
++ } // End if (AST1010)
++
++ //WDT
++ #ifdef AST1010_IOMAP
++ #else
++ WriteSOC_DD( 0x1e78500c, WDT_0ch_old & 0xfffffffc );
++ WriteSOC_DD( 0x1e78502c, WDT_2ch_old & 0xfffffffc );
++ #endif
++}
++
++//------------------------------------------------------------
++void init_scu1 (void) {
++ #ifdef DbgPrn_FuncHeader
++ printf ("init_scu1\n");
++ Debug_delay();
++ #endif
++
++ if (AST3200) {
++ WriteSOC_DD( SCU_BASE + 0x0c, (SCU_0ch_old & 0xffefffff) );//Clock Stop Control
++ }
++ else if (AST1010) {
++ WriteSOC_DD( SCU_BASE + 0x0c, ( SCU_0ch_old & 0xffffffbf ) );//Clock Stop Control
++ WriteSOC_DD( SCU_BASE + 0x88, ((SCU_88h_old & 0x003fffff ) | 0xffc00000) );//Multi-function Pin Control
++ }
++ else if (AST2300) {
++#ifdef Enable_BufMerge
++ WriteSOC_DD( SCU_BASE + 0xf0, 0x66559959 );//MAC buffer merge
++#endif
++
++#ifdef Enable_AST2300_Int125MHz
++ SCU_48h_mix = (SCU_48h_old & 0xf0000000) | 0x80000000;
++// WriteSOC_DD( SCU_BASE + 0xf0, 0xa0e0e0d3 );//Enable I2S
++// WriteSOC_DD( SCU_BASE + 0x04, SCU_04h_old & 0xfffdffff );//Rst(Enable I2S)
++//
++//// WriteSOC_DD( 0x1e6e5020, ReadSOC_DD(0x1e6e5020) | 0x00010000 );//P_I2SPLLAdjEnable
++// WriteSOC_DD( 0x1e6e5020, ReadSOC_DD(0x1e6e5020) | 0x00000000 );//P_I2SPLLAdjEnable
++// WriteSOC_DD( 0x1e6e5024, 0x00000175 );//P_I2SPLLAdjCnt
++
++// WriteSOC_DD( SCU_BASE + 0x1c, 0x0000a51a );//124800000(24MHz)
++// WriteSOC_DD( SCU_BASE + 0x1c, 0x0000a92f );//125333333(24MHz)
++// WriteSOC_DD( SCU_BASE + 0x1c, 0x0000587d );//125000000(24MHz)
++ WriteSOC_DD( SCU_BASE + 0x1c, 0x00006c7d );//125000000(24MHz)
++ WriteSOC_DD( SCU_BASE + 0x2c, 0x00300000 | (SCU_2ch_old & 0xffcfffef) );//D-PLL assigned to VGA, D2-PLL assigned to I2S.
++ WriteSOC_DD( SCU_BASE + 0x48, 0x80000000 | SCU_48h_old );//125MHz come from I2SPLL
++#else
++ SCU_48h_mix = (SCU_48h_old & 0xf0000000);
++#endif
++ switch (SelectMAC) {
++ case 0 :
++ WriteSOC_DD( SCU_BASE + 0x88, (SCU_88h_old & 0x3fffffff) | 0xc0000000 );//[31]MAC1 MDIO, [30]MAC1 MDC
++ break;
++ case 1 :
++ WriteSOC_DD( SCU_BASE + 0x90, (SCU_90h_old & 0xfffffffb) | 0x00000004 );//[2 ]MAC2 MDC/MDIO
++ break;
++ case 2 :
++ case 3 :
++ default : break;
++ }
++
++ WriteSOC_DD(SCU_BASE+0x0c, (SCU_0ch_old & 0xff0fffff) );//Clock Stop Control
++// WriteSOC_DD(SCU_BASE+0x80, (SCU_80h_old & 0xfffffff0) | 0x0000000f);//MAC1LINK/MAC2LINK
++ }
++ else {
++ switch (SelectMAC) {
++ case 0 :
++// WriteSOC_DD(SCU_BASE+0x74, (SCU_74h_old & 0xfdffffff) | 0x02000000);//[25]MAC1 PHYLINK
++ break;
++ case 1 :
++ if (MAC2_RMII) {
++// WriteSOC_DD(SCU_BASE+0x74, (SCU_74h_old & 0xfbefffff) | 0x04100000);//[26]MAC2 PHYLINK, [21]MAC2 MII, [20]MAC2 MDC/MDIO
++ WriteSOC_DD(SCU_BASE+0x74, (SCU_74h_old & 0xffefffff) | 0x00100000);//[26]MAC2 PHYLINK, [21]MAC2 MII, [20]MAC2 MDC/MDIO
++ } else {
++// WriteSOC_DD(SCU_BASE+0x74, (SCU_74h_old & 0xfbcfffff) | 0x04300000);//[26]MAC2 PHYLINK, [21]MAC2 MII, [20]MAC2 MDC/MDIO
++ WriteSOC_DD(SCU_BASE+0x74, (SCU_74h_old & 0xffcfffff) | 0x00300000);//[26]MAC2 PHYLINK, [21]MAC2 MII, [20]MAC2 MDC/MDIO
++ }
++ break;
++ default : break;
++ } // End switch (SelectMAC)
++ } // End if (AST3200)
++} // End void init_scu1 (void)
++
++//------------------------------------------------------------
++void init_scu_macrst (void) {
++
++#ifdef Enable_AST2300_Int125MHz
++ if (ASTChipType == 3) {
++ SCU_04h_mix = SCU_04h_old & 0xfffdffff;
++ } else {
++ SCU_04h_mix = SCU_04h_old;
++ }
++#else
++ SCU_04h_mix = SCU_04h_old;
++#endif
++
++ WriteSOC_DD ( SCU_BASE + 0x04, (SCU_04h_mix & ~SCU_04h) | SCU_04h);//Rst
++ DELAY(Delay_SCU);
++ WriteSOC_DD ( SCU_BASE + 0x04, (SCU_04h_mix & ~SCU_04h) );//Enable Engine
++// DELAY(Delay_SCU);
++} // End void init_scu_macrst (void)
++
++//------------------------------------------------------------
++void init_scu2 (void) {
++
++#ifdef SCU_74h
++ #ifdef DbgPrn_FuncHeader
++ printf ("init_scu2\n");
++ Debug_delay();
++ #endif
++
++ WriteSOC_DD( SCU_BASE + 0x74, SCU_74h_old | SCU_74h );//PinMux
++ delay(Delay_SCU);
++#endif
++
++} // End void init_scu2 (void)
++
++//------------------------------------------------------------
++void init_scu3 (void) {
++
++#ifdef SCU_74h
++ #ifdef DbgPrn_FuncHeader
++ printf ("init_scu3\n");
++ Debug_delay();
++ #endif
++
++ WriteSOC_DD( SCU_BASE + 0x74, SCU_74h_old | (SCU_74h & 0xffefffff) );//PinMux
++ delay(Delay_SCU);
++#endif
++
++} // End void init_scu3 (void)
++
++//------------------------------------------------------------
++// MAC
++//------------------------------------------------------------
++void init_mac (ULONG base, ULONG tdexbase, ULONG rdexbase) {
++ #ifdef DbgPrn_FuncHeader
++ printf ("init_mac\n");
++ Debug_delay();
++ #endif
++
++#ifdef Enable_MAC_SWRst
++ WriteSOC_DD( base + 0x50, 0x80000000 | MAC_50h | MAC_50h_Speed);
++// WriteSOC_DD( base + 0x50, 0x80000000);
++
++ while (0x80000000 & ReadSOC_DD(base+0x50)) {
++//printf(".");
++ DELAY(Delay_MACRst);
++ }
++ DELAY(Delay_MACRst);
++#endif
++
++ WriteSOC_DD( base + 0x20, (tdexbase + CPU_BUS_ADDR_SDRAM_OFFSET) ); // 20130730
++ WriteSOC_DD( base + 0x24, (rdexbase + CPU_BUS_ADDR_SDRAM_OFFSET) ); // 20130730
++
++#ifdef MAC_30h
++ WriteSOC_DD( base + 0x30, MAC_30h);//Int Thr/Cnt
++#endif
++
++#ifdef MAC_34h
++ WriteSOC_DD( base + 0x34, MAC_34h);//Poll Cnt
++#endif
++
++#ifdef MAC_38h
++ WriteSOC_DD( base + 0x38, MAC_38h);
++#endif
++
++#ifdef MAC_40h
++ if (Enable_MACLoopback) {
++ if (AST2300_NewMDIO) WriteSOC_DD( base + 0x40, MAC_40h | 0x80000000);
++ else WriteSOC_DD( base + 0x40, MAC_40h);
++ }
++#endif
++
++#ifdef MAC_48h
++ WriteSOC_DD( base + 0x48, MAC_48h);
++#endif
++
++ if ( ModeSwitch == MODE_NSCI )
++ WriteSOC_DD( base + 0x4c, NCSI_RxDMA_PakSize);
++ else
++ WriteSOC_DD( base + 0x4c, DMA_PakSize);
++
++ WriteSOC_DD( base + 0x50, MAC_50h | MAC_50h_Speed | 0xf);
++ DELAY(Delay_MACRst);
++} // End void init_mac (ULONG base, ULONG tdexbase, ULONG rdexbase)
++
++//------------------------------------------------------------
++// Basic
++//------------------------------------------------------------
++void FPri_RegValue (BYTE option) {
++
++#ifdef SLT_UBOOT
++#else
++ time_t timecur;
++#endif
++
++ FILE_VAR
++
++ GET_OBJ( option )
++
++ PRINT(OUT_OBJ "[SCU] 04:%08lx 08:%08lx 0c:%08lx 48:%08lx\n", SCU_04h_old, SCU_08h_old, SCU_0ch_old, SCU_48h_old);
++ PRINT(OUT_OBJ "[SCU] 70:%08lx 74:%08lx 7c:%08lx\n", SCU_70h_old, SCU_74h_old, SCU_7ch_old);
++ PRINT(OUT_OBJ "[SCU] 80:%08lx 88:%08lx 90:%08lx f0:%08lx\n", SCU_80h_old, SCU_88h_old, SCU_90h_old, SCU_f0h_old);
++ PRINT(OUT_OBJ "[SCU] a4:%08lx ac:%08lx\n", SCU_a4h_old, SCU_ach_old);
++ PRINT(OUT_OBJ "[WDT] 0c:%08lx 2c:%08lx\n", WDT_0ch_old, WDT_2ch_old);
++ PRINT(OUT_OBJ "[MAC] 08:%08lx 0c:%08lx\n", MAC_08h_old, MAC_0ch_old);
++ PRINT(OUT_OBJ "[MAC] A0|%08lx %08lx %08lx %08lx\n", ReadSOC_DD( MAC_PHYBASE + 0xa0), ReadSOC_DD( MAC_PHYBASE + 0xa4 ), ReadSOC_DD( MAC_PHYBASE + 0xa8 ), ReadSOC_DD(MAC_PHYBASE + 0xac ) );
++ PRINT(OUT_OBJ "[MAC] B0|%08lx %08lx %08lx %08lx\n", ReadSOC_DD( MAC_PHYBASE + 0xb0), ReadSOC_DD( MAC_PHYBASE + 0xb4 ), ReadSOC_DD( MAC_PHYBASE + 0xb8 ), ReadSOC_DD(MAC_PHYBASE + 0xbc ) );
++ PRINT(OUT_OBJ "[MAC] C0|%08lx %08lx %08lx\n", ReadSOC_DD( MAC_PHYBASE + 0xc0), ReadSOC_DD( MAC_PHYBASE + 0xc4 ), ReadSOC_DD( MAC_PHYBASE + 0xc8 ));
++
++#ifdef SLT_UBOOT
++#else
++ fprintf(fp, "Time: %s", ctime(&timestart));
++ time(&timecur);
++ fprintf(fp, "----> %s", ctime(&timecur));
++#endif
++} // End void FPri_RegValue (BYTE *fp)
++
++//------------------------------------------------------------
++void FPri_End (BYTE option) {
++
++ FILE_VAR
++
++ GET_OBJ( option )
++
++ if ( !RxDataEnable ) {
++ }
++ else if ( Err_Flag ) {
++ PRINT(OUT_OBJ " \n----> fail !!!\n");
++ } else {
++ PRINT(OUT_OBJ " \n----> All Pass !!!\n");
++ }
++
++ if ( ModeSwitch == MODE_DEDICATED ) {
++ if (PHY_ADR_arg != PHY_ADR)
++ PRINT(OUT_OBJ "\n[Warning] PHY Address change from %d to %d !!!\n", PHY_ADR_arg, PHY_ADR);
++ }
++
++ if ( AST1010 ) {
++ Dat_ULONG = (SCU_ach_old >> 12) & 0xf;
++ if (Dat_ULONG) {
++ PRINT(OUT_OBJ "\n[Warning] SCUAC[15:12] == 0x%02lx is not the suggestion value 0.\n", Dat_ULONG);
++ PRINT(OUT_OBJ " This change at this platform must been proven again by the ASPEED.\n");
++ }
++
++ SCU_48h_default = SCU_48h_AST1010 & 0x01000f00;
++ if ((SCU_48h_old != SCU_48h_default)) {
++ PRINT(OUT_OBJ "\n[Warning] SCU48 == 0x%08lx is not the suggestion value 0x%08lx.\n", SCU_48h_old, SCU_48h_default);
++ PRINT(OUT_OBJ " This change at this platform must been proven again by the ASPEED.\n");
++ }
++ }
++ else if ( AST2300 ) {
++ if ( AST2400 ) {
++ Dat_ULONG = (SCU_90h_old >> 8) & 0xf;
++ if (Dat_ULONG) {
++ PRINT(OUT_OBJ "\n[Warning] SCU90[11: 8] == 0x%02lx is not the suggestion value 0.\n", Dat_ULONG);
++ PRINT(OUT_OBJ " This change at this platform must been proven again by the ASPEED.\n");
++ }
++ }
++ else {
++ Dat_ULONG = (SCU_90h_old >> 8) & 0xff;
++ if (Dat_ULONG) {
++ PRINT(OUT_OBJ "\n[Warning] SCU90[15: 8] == 0x%02lx is not the suggestion value 0.\n", Dat_ULONG);
++ PRINT(OUT_OBJ " This change at this platform must been proven again by the ASPEED.\n");
++ }
++ }
++
++ if (Enable_MAC34) SCU_48h_default = SCU_48h_AST2300;
++ else SCU_48h_default = SCU_48h_AST2300 & 0x0300ffff;
++
++ if ((SCU_48h_old != SCU_48h_default)) {
++ PRINT(OUT_OBJ "\n[Warning] SCU48 == 0x%08lx is not the suggestion value 0x%08lx.\n", SCU_48h_old, SCU_48h_default);
++ PRINT(OUT_OBJ " This change at this platform must been proven again by the ASPEED.\n");
++ }
++ } // End if ( AST1010 )
++
++ if ( ModeSwitch == MODE_NSCI ) {
++ PRINT(OUT_OBJ "\n[Arg] %d %d %d %d %d %ld (%s)\n", GRun_Mode, PackageTolNum, ChannelTolNum, TestMode, IOTimingBund, (ARPNumCnt| (ULONG)PrintNCSIEn), ASTChipName);
++
++ switch (NCSI_Cap_SLT.PCI_DID_VID) {
++ case PCI_DID_VID_Intel_82574L : PRINT( OUT_OBJ "[NC]%08lx %08lx: Intel 82574L \n", NCSI_Cap_SLT.ManufacturerID, NCSI_Cap_SLT.PCI_DID_VID ); break;
++ case PCI_DID_VID_Intel_82575_10d6 : PRINT( OUT_OBJ "[NC]%08lx %08lx: Intel 82575 \n", NCSI_Cap_SLT.ManufacturerID, NCSI_Cap_SLT.PCI_DID_VID ); break;
++ case PCI_DID_VID_Intel_82575_10a7 : PRINT( OUT_OBJ "[NC]%08lx %08lx: Intel 82575 \n", NCSI_Cap_SLT.ManufacturerID, NCSI_Cap_SLT.PCI_DID_VID ); break;
++ case PCI_DID_VID_Intel_82575_10a9 : PRINT( OUT_OBJ "[NC]%08lx %08lx: Intel 82575 \n", NCSI_Cap_SLT.ManufacturerID, NCSI_Cap_SLT.PCI_DID_VID ); break;
++ case PCI_DID_VID_Intel_82576_10c9 : PRINT( OUT_OBJ "[NC]%08lx %08lx: Intel 82576 \n", NCSI_Cap_SLT.ManufacturerID, NCSI_Cap_SLT.PCI_DID_VID ); break;
++ case PCI_DID_VID_Intel_82576_10e6 : PRINT( OUT_OBJ "[NC]%08lx %08lx: Intel 82576 \n", NCSI_Cap_SLT.ManufacturerID, NCSI_Cap_SLT.PCI_DID_VID ); break;
++ case PCI_DID_VID_Intel_82576_10e7 : PRINT( OUT_OBJ "[NC]%08lx %08lx: Intel 82576 \n", NCSI_Cap_SLT.ManufacturerID, NCSI_Cap_SLT.PCI_DID_VID ); break;
++ case PCI_DID_VID_Intel_82576_10e8 : PRINT( OUT_OBJ "[NC]%08lx %08lx: Intel 82576 \n", NCSI_Cap_SLT.ManufacturerID, NCSI_Cap_SLT.PCI_DID_VID ); break;
++ case PCI_DID_VID_Intel_82576_1518 : PRINT( OUT_OBJ "[NC]%08lx %08lx: Intel 82576 \n", NCSI_Cap_SLT.ManufacturerID, NCSI_Cap_SLT.PCI_DID_VID ); break;
++ case PCI_DID_VID_Intel_82576_1526 : PRINT( OUT_OBJ "[NC]%08lx %08lx: Intel 82576 \n", NCSI_Cap_SLT.ManufacturerID, NCSI_Cap_SLT.PCI_DID_VID ); break;
++ case PCI_DID_VID_Intel_82576_150a : PRINT( OUT_OBJ "[NC]%08lx %08lx: Intel 82576 \n", NCSI_Cap_SLT.ManufacturerID, NCSI_Cap_SLT.PCI_DID_VID ); break;
++ case PCI_DID_VID_Intel_82576_150d : PRINT( OUT_OBJ "[NC]%08lx %08lx: Intel 82576 \n", NCSI_Cap_SLT.ManufacturerID, NCSI_Cap_SLT.PCI_DID_VID ); break;
++ case PCI_DID_VID_Intel_82599_10fb : PRINT( OUT_OBJ "[NC]%08lx %08lx: Intel 82599 \n", NCSI_Cap_SLT.ManufacturerID, NCSI_Cap_SLT.PCI_DID_VID ); break;
++ case PCI_DID_VID_Intel_82599_1557 : PRINT( OUT_OBJ "[NC]%08lx %08lx: Intel 82599 \n", NCSI_Cap_SLT.ManufacturerID, NCSI_Cap_SLT.PCI_DID_VID ); break;
++ case PCI_DID_VID_Intel_I350_1521 : PRINT( OUT_OBJ "[NC]%08lx %08lx: Intel I350 \n", NCSI_Cap_SLT.ManufacturerID, NCSI_Cap_SLT.PCI_DID_VID ); break;
++ case PCI_DID_VID_Intel_I350_1523 : PRINT( OUT_OBJ "[NC]%08lx %08lx: Intel I350 \n", NCSI_Cap_SLT.ManufacturerID, NCSI_Cap_SLT.PCI_DID_VID ); break;
++ case PCI_DID_VID_Intel_I210 : PRINT( OUT_OBJ "[NC]%08lx %08lx: Intel I210 \n", NCSI_Cap_SLT.ManufacturerID, NCSI_Cap_SLT.PCI_DID_VID ); break;
++ case PCI_DID_VID_Intel_X540 : PRINT( OUT_OBJ "[NC]%08lx %08lx: Intel X540 \n", NCSI_Cap_SLT.ManufacturerID, NCSI_Cap_SLT.PCI_DID_VID ); break;
++ case PCI_DID_VID_Broadcom_BCM5718 : PRINT( OUT_OBJ "[NC]%08lx %08lx: Broadcom BCM5718 \n", NCSI_Cap_SLT.ManufacturerID, NCSI_Cap_SLT.PCI_DID_VID ); break;
++ case PCI_DID_VID_Broadcom_BCM5720 : PRINT( OUT_OBJ "[NC]%08lx %08lx: Broadcom BCM5720 \n", NCSI_Cap_SLT.ManufacturerID, NCSI_Cap_SLT.PCI_DID_VID ); break;
++ case PCI_DID_VID_Broadcom_BCM5725 : PRINT( OUT_OBJ "[NC]%08lx %08lx: Broadcom BCM5725 \n", NCSI_Cap_SLT.ManufacturerID, NCSI_Cap_SLT.PCI_DID_VID ); break;
++// case PCI_DID_VID_Broadcom_BCM57810 : PRINT( OUT_OBJ "[NC]%08x %08x: Broadcom BCM57810 \n", NCSI_Cap_SLT.ManufacturerID, NCSI_Cap_SLT.PCI_DID_VID ); break;
++ case PCI_DID_VID_Mellanox_ConnectX_3 : PRINT( OUT_OBJ "[NC]%08lx %08lx: Mellanox ConnectX-3\n", NCSI_Cap_SLT.ManufacturerID, NCSI_Cap_SLT.PCI_DID_VID ); break;
++ default :
++ switch (NCSI_Cap_SLT.ManufacturerID) {
++ case ManufacturerID_Intel : PRINT( OUT_OBJ "[NC]%08lx %08lx: Intel \n", NCSI_Cap_SLT.ManufacturerID, NCSI_Cap_SLT.PCI_DID_VID ); break;
++ case ManufacturerID_Broadcom : PRINT( OUT_OBJ "[NC]%08lx %08lx: Broadcom\n", NCSI_Cap_SLT.ManufacturerID, NCSI_Cap_SLT.PCI_DID_VID ); break;
++ case ManufacturerID_Mellanox : PRINT( OUT_OBJ "[NC]%08lx %08lx: Mellanox\n", NCSI_Cap_SLT.ManufacturerID, NCSI_Cap_SLT.PCI_DID_VID ); break;
++ default : PRINT(OUT_OBJ "[NC]%08lx %08lx \n", NCSI_Cap_SLT.ManufacturerID, NCSI_Cap_SLT.PCI_DID_VID); break;
++ } // End switch (NCSI_Cap_SLT.ManufacturerID)
++ } // End switch (NCSI_Cap_SLT.PCI_DID_VID)
++ }
++ else {
++ if (LOOP_INFINI) PRINT(OUT_OBJ "\n[Arg] %d %d %d # %d %d %d %lx (%s)[%d %d %d]\n" , GRun_Mode, GSpeed, GCtrl, TestMode, PHY_ADR_arg, IOTimingBund, UserDVal, ASTChipName, Loop_rl[0], Loop_rl[1], Loop_rl[2]);
++ else PRINT(OUT_OBJ "\n[Arg] %d %d %d %ld %d %d %d %lx (%s)[%d %d %d]\n", GRun_Mode, GSpeed, GCtrl, LOOP_MAX_arg, TestMode, PHY_ADR_arg, IOTimingBund, UserDVal, ASTChipName, Loop_rl[0], Loop_rl[1], Loop_rl[2]);
++
++ PRINT(OUT_OBJ "[PHY] Adr:%d ID2:%04lx ID3:%04lx (%s)\n", PHY_ADR, PHY_ID2, PHY_ID3, PHYName);
++ } // End if ( ModeSwitch == MODE_NSCI )
++
++#ifdef SUPPORT_PHY_LAN9303
++ PRINT(OUT_OBJ "[Ver II] %s (for LAN9303 with I2C%d)\n", version_name, LAN9303_I2C_BUSNUM);
++#else
++ PRINT(OUT_OBJ "[Ver II] %s\n", version_name);
++#endif
++} // End void FPri_End (BYTE option)
++
++//------------------------------------------------------------
++void FPri_ErrFlag (BYTE option) {
++
++ FILE_VAR
++
++ GET_OBJ( option )
++
++ if (Err_Flag && Err_Flag_PrintEn) {
++ PRINT(OUT_OBJ "\n\n");
++//fprintf(fp, "Err_Flag: %x\n\n", Err_Flag);
++
++ if ( Err_Flag & Err_PHY_Type ) PRINT( OUT_OBJ "[Err] Unidentifiable PHY \n" );
++ if ( Err_Flag & Err_MALLOC_FrmSize ) PRINT( OUT_OBJ "[Err] Malloc fail at frame size buffer \n" );
++ if ( Err_Flag & Err_MALLOC_LastWP ) PRINT( OUT_OBJ "[Err] Malloc fail at last WP buffer \n" );
++ if ( Err_Flag & Err_Check_Buf_Data ) PRINT( OUT_OBJ "[Err] Received data mismatch \n" );
++ if ( Err_Flag & Err_NCSI_Check_TxOwnTimeOut ) PRINT( OUT_OBJ "[Err] Time out of checking Tx owner bit in NCSI packet \n" );
++ if ( Err_Flag & Err_NCSI_Check_RxOwnTimeOut ) PRINT( OUT_OBJ "[Err] Time out of checking Rx owner bit in NCSI packet \n" );
++ if ( Err_Flag & Err_NCSI_Check_ARPOwnTimeOut) PRINT( OUT_OBJ "[Err] Time out of checking ARP owner bit in NCSI packet \n" );
++ if ( Err_Flag & Err_NCSI_No_PHY ) PRINT( OUT_OBJ "[Err] Can not find NCSI PHY \n" );
++ if ( Err_Flag & Err_NCSI_Channel_Num ) PRINT( OUT_OBJ "[Err] NCSI Channel Number Mismatch \n" );
++ if ( Err_Flag & Err_NCSI_Package_Num ) PRINT( OUT_OBJ "[Err] NCSI Package Number Mismatch \n" );
++ if ( Err_Flag & Err_PHY_TimeOut ) PRINT( OUT_OBJ "[Err] Time out of read/write/reset PHY register \n" );
++ if ( Err_Flag & Err_RXBUF_UNAVA ) PRINT( OUT_OBJ "[Err] MAC00h[2]:Receiving buffer unavailable \n" );
++ if ( Err_Flag & Err_RPKT_LOST ) PRINT( OUT_OBJ "[Err] MAC00h[3]:Received packet lost due to RX FIFO full \n" );
++ if ( Err_Flag & Err_NPTXBUF_UNAVA ) PRINT( OUT_OBJ "[Err] MAC00h[6]:Normal priority transmit buffer unavailable \n" );
++ if ( Err_Flag & Err_TPKT_LOST ) PRINT( OUT_OBJ "[Err] MAC00h[7]:Packets transmitted to Ethernet lost \n" );
++ if ( Err_Flag & Err_DMABufNum ) PRINT( OUT_OBJ "[Err] DMA Buffer is not enough \n" );
++ if ( Err_Flag & Err_IOMargin ) PRINT( OUT_OBJ "[Err] IO timing margin is not enough \n" );
++
++ if ( Err_Flag & Err_MHCLK_Ratio ) {
++ if ( AST1010 ) {
++ PRINT(OUT_OBJ "[Err] Error setting of MAC AHB bus clock (SCU08[13:12]) \n");
++ Dat_ULONG = (SCU_08h_old >> 12) & 0x3;
++ PRINT(OUT_OBJ " SCU08[13:12] == 0x%01lx is not the suggestion value 0.\n", Dat_ULONG);
++ }
++ else {
++ PRINT(OUT_OBJ "[Err] Error setting of MAC AHB bus clock (SCU08[18:16]) \n");
++ Dat_ULONG = (SCU_08h_old >> 16) & 0x7;
++
++ if (MAC1_1GEn | MAC2_1GEn) {
++ PRINT(OUT_OBJ " SCU08[18:16] == 0x%01lx is not the suggestion value 2.\n", Dat_ULONG);
++ }
++ else {
++ PRINT(OUT_OBJ " SCU08[18:16] == 0x%01lx is not the suggestion value 4.\n", Dat_ULONG);
++ }
++ } // end if ( AST1010 )
++ } // End if ( Err_Flag & Err_MHCLK_Ratio )
++
++ if (Err_Flag & Err_IOMarginOUF ) {
++ PRINT(OUT_OBJ "[Err] IO timing testing range out of boundary\n");
++ if (Enable_RMII) {
++#ifdef Enable_Old_Style
++ PRINT(OUT_OBJ " (%d,%d): 1x%d [%d]x[%d:%d]\n", IOdly_out_reg_idx, IOdly_in_reg_idx, IOTimingBund, IOdly_out_reg_idx, IOdly_in_reg_idx - (IOTimingBund>>1), IOdly_in_reg_idx + (IOTimingBund>>1));
++#else
++ PRINT(OUT_OBJ " (%d,%d): %dx1 [%d:%d]x[%d]\n", IOdly_in_reg_idx, IOdly_out_reg_idx, IOTimingBund, IOdly_in_reg_idx - (IOTimingBund>>1), IOdly_in_reg_idx + (IOTimingBund>>1), IOdly_out_reg_idx);
++#endif
++ } else {
++#ifdef Enable_Old_Style
++ PRINT(OUT_OBJ " (%d,%d): %dx%d [%d:%d]x[%d:%d]\n", IOdly_out_reg_idx, IOdly_in_reg_idx, IOTimingBund, IOTimingBund, IOdly_out_reg_idx - (IOTimingBund>>1), IOdly_out_reg_idx + (IOTimingBund>>1), IOdly_in_reg_idx - (IOTimingBund>>1), IOdly_in_reg_idx + (IOTimingBund>>1));
++#else
++ PRINT(OUT_OBJ " (%d,%d): %dx%d [%d:%d]x[%d:%d]\n", IOdly_in_reg_idx, IOdly_out_reg_idx, IOTimingBund, IOTimingBund, IOdly_in_reg_idx - (IOTimingBund>>1), IOdly_in_reg_idx + (IOTimingBund>>1), IOdly_out_reg_idx - (IOTimingBund>>1), IOdly_out_reg_idx + (IOTimingBund>>1));
++#endif
++ }
++ } // End if (Err_Flag & Err_IOMarginOUF )
++
++ if (Err_Flag & Err_Check_Des ) {
++ PRINT(OUT_OBJ "[Err] Descriptor error\n");
++ if ( Check_Des_Val & Check_Des_TxOwnTimeOut ) PRINT( OUT_OBJ "[Des] Time out of checking Tx owner bit\n" );
++ if ( Check_Des_Val & Check_Des_RxOwnTimeOut ) PRINT( OUT_OBJ "[Des] Time out of checking Rx owner bit\n" );
++ if ( Check_Des_Val & Check_Des_RxErr ) PRINT( OUT_OBJ "[Des] Input signal RxErr \n" );
++ if ( Check_Des_Val & Check_Des_OddNibble ) PRINT( OUT_OBJ "[Des] Nibble bit happen \n" );
++ if ( Check_Des_Val & Check_Des_CRC ) PRINT( OUT_OBJ "[Des] CRC error of frame \n" );
++ if ( Check_Des_Val & Check_Des_RxFIFOFull ) PRINT( OUT_OBJ "[Des] Rx FIFO full \n" );
++ if ( Check_Des_Val & Check_Des_FrameLen ) PRINT( OUT_OBJ "[Des] Frame length mismatch \n" );
++ } // End if (Err_Flag & Err_Check_Des )
++
++ if (Err_Flag & Err_MACMode ) {
++ PRINT(OUT_OBJ "[Err] MAC interface mode mismatch\n");
++ if ( AST1010 ) {
++ }
++ else if (AST2300) {
++ switch (MAC_Mode) {
++ case 0 : PRINT( OUT_OBJ " SCU70h[7:6] == 0: [MAC#1] RMII [MAC#2] RMII \n" ); break;
++ case 1 : PRINT( OUT_OBJ " SCU70h[7:6] == 1: [MAC#1] RGMII [MAC#2] RMII \n" ); break;
++ case 2 : PRINT( OUT_OBJ " SCU70h[7:6] == 2: [MAC#1] RMII [MAC#2] RGMII\n" ); break;
++ case 3 : PRINT( OUT_OBJ " SCU70h[7:6] == 3: [MAC#1] RGMII [MAC#2] RGMII\n" ); break;
++ }
++ }
++ else {
++ switch (MAC_Mode) {
++ case 0 : PRINT( OUT_OBJ " SCU70h[8:6] == 000: [MAC#1] GMII \n" ); break;
++ case 1 : PRINT( OUT_OBJ " SCU70h[8:6] == 001: [MAC#1] MII [MAC#2] MII \n" ); break;
++ case 2 : PRINT( OUT_OBJ " SCU70h[8:6] == 010: [MAC#1] RMII [MAC#2] MII \n" ); break;
++ case 3 : PRINT( OUT_OBJ " SCU70h[8:6] == 011: [MAC#1] MII \n" ); break;
++ case 4 : PRINT( OUT_OBJ " SCU70h[8:6] == 100: [MAC#1] RMII \n" ); break;
++ case 5 : PRINT( OUT_OBJ " SCU70h[8:6] == 101: Reserved \n" ); break;
++ case 6 : PRINT( OUT_OBJ " SCU70h[8:6] == 110: [MAC#1] RMII [MAC#2] RMII\n" ); break;
++ case 7 : PRINT( OUT_OBJ " SCU70h[8:6] == 111: Disable MAC \n" ); break;
++ }
++ } // End if ( AST1010 )
++ } // End if (Err_Flag & Err_MACMode )
++
++ if ( ModeSwitch == MODE_NSCI ) {
++ if (Err_Flag & Err_NCSI_LinkFail ) {
++ PRINT(OUT_OBJ "[Err] NCSI packet retry number over flows when find channel\n");
++
++ if (NCSI_LinkFail_Val & NCSI_LinkFail_Get_Version_ID ) PRINT(OUT_OBJ "[NCSI] Time out when Get Version ID \n");
++ if (NCSI_LinkFail_Val & NCSI_LinkFail_Get_Capabilities ) PRINT(OUT_OBJ "[NCSI] Time out when Get Capabilities \n");
++ if (NCSI_LinkFail_Val & NCSI_LinkFail_Select_Active_Package ) PRINT(OUT_OBJ "[NCSI] Time out when Select Active Package \n");
++ if (NCSI_LinkFail_Val & NCSI_LinkFail_Enable_Set_MAC_Address ) PRINT(OUT_OBJ "[NCSI] Time out when Enable Set MAC Address \n");
++ if (NCSI_LinkFail_Val & NCSI_LinkFail_Enable_Broadcast_Filter) PRINT(OUT_OBJ "[NCSI] Time out when Enable Broadcast Filter\n");
++ if (NCSI_LinkFail_Val & NCSI_LinkFail_Enable_Network_TX ) PRINT(OUT_OBJ "[NCSI] Time out when Enable Network TX \n");
++ if (NCSI_LinkFail_Val & NCSI_LinkFail_Enable_Channel ) PRINT(OUT_OBJ "[NCSI] Time out when Enable Channel \n");
++ if (NCSI_LinkFail_Val & NCSI_LinkFail_Disable_Network_TX ) PRINT(OUT_OBJ "[NCSI] Time out when Disable Network TX \n");
++ if (NCSI_LinkFail_Val & NCSI_LinkFail_Disable_Channel ) PRINT(OUT_OBJ "[NCSI] Time out when Disable Channel \n");
++ }
++
++ if (Err_Flag & Err_NCSI_Channel_Num ) PRINT(OUT_OBJ "[NCSI] Channel number expected: %d, real: %d\n", ChannelTolNum, number_chl);
++ if (Err_Flag & Err_NCSI_Package_Num ) PRINT(OUT_OBJ "[NCSI] Peckage number expected: %d, real: %d\n", PackageTolNum, number_pak);
++ } // End if ( ModeSwitch == MODE_NSCI )
++ } // End if (Err_Flag && Err_Flag_PrintEn)
++} // End void FPri_ErrFlag (BYTE option)
++
++//------------------------------------------------------------
++void Finish_Close (void) {
++
++ if (SCU_oldvld)
++ recov_scu();
++
++#ifdef SLT_DOS
++ if (fp_io && IOTiming)
++ fclose(fp_io);
++
++ if (fp_log)
++ fclose(fp_log);
++#endif
++} // End void Finish_Close (void)
++
++//------------------------------------------------------------
++char Finish_Check (int value) {
++ ULONG temp;
++ CHAR i = 0;
++
++#ifdef Disable_VGA
++ if (VGAModeVld) {
++ outp(0x3d4, 0x17);
++ outp(0x3d5, VGAMode);
++ }
++#endif
++ #ifdef DbgPrn_FuncHeader
++ printf ("Finish_Check\n");
++ Debug_delay();
++ #endif
++
++ if ( FRAME_LEN )
++ free(FRAME_LEN);
++
++ if ( wp_lst )
++ free(wp_lst );
++
++ Err_Flag = Err_Flag | value;
++
++ if ( DbgPrn_ErrFlg )
++ printf ("\nErr_Flag: [%08lx]\n", Err_Flag);
++
++ if ( !BurstEnable )
++ FPri_ErrFlag( FP_LOG );
++
++ if ( IOTiming )
++ FPri_ErrFlag( FP_IO );
++
++ FPri_ErrFlag( STD_OUT );
++
++ if ( !BurstEnable )
++ FPri_End( FP_LOG );
++
++ if ( IOTiming )
++ FPri_End( FP_IO );
++
++ FPri_End( STD_OUT );
++
++
++ if ( !BurstEnable ) FPri_RegValue( FP_LOG );
++ if ( IOTiming ) FPri_RegValue( FP_IO );
++
++ Finish_Close();
++
++ // 20140325
++ temp = ReadSOC_DD( 0x1e6e2040 );
++ if ( ModeSwitch == MODE_NSCI )
++ {
++ if ( SelectMAC == 0 )
++ i = 17;
++ else
++ i = 16;
++ }
++ else
++ {
++ if ( SelectMAC == 0 )
++ i = 19;
++ else
++ i = 18;
++ }
++ WriteSOC_DD( 0x1e6e2040, (temp | (1 << i)) );
++
++
++ if ( Err_Flag )
++ {
++ // Fail
++ return( 1 );
++ }
++ else
++ {
++ // Pass
++ return( 0 );
++ }
++} // End char Finish_Check (int value)
++
++//------------------------------------------------------------
++int FindErr (int value) {
++ Err_Flag = Err_Flag | value;
++
++ if ( DbgPrn_ErrFlg )
++ printf ("\nErr_Flag: [%08lx]\n", Err_Flag);
++
++ return(1);
++}
++
++//------------------------------------------------------------
++int FindErr_Des (int value) {
++ Check_Des_Val = Check_Des_Val | value;
++ Err_Flag = Err_Flag | Err_Check_Des;
++ if ( DbgPrn_ErrFlg )
++ printf ("\nErr_Flag: [%08lx] Check_Des_Val: [%08lx]\n", Err_Flag, Check_Des_Val);
++
++ return(1);
++}
++
++//------------------------------------------------------------
++// Get and Check status of Interrupt
++//------------------------------------------------------------
++int check_int ( char *type ) {
++ #ifdef DbgPrn_FuncHeader
++ printf ("check_int : %d\n", Loop);
++ Debug_delay();
++ #endif
++
++ Dat_ULONG = ReadSOC_DD( H_MAC_BASE + 0x00 );//Interrupt Status
++#ifdef SLT_DOS
++#ifdef CheckRxbufUNAVA
++ if ( Dat_ULONG & 0x00000004 ) {
++ fprintf(fp_log, "[%sIntStatus] Receiving buffer unavailable : %08lx [loop:%d]\n", type, Dat_ULONG, Loop);
++ FindErr( Err_RXBUF_UNAVA );
++ }
++#endif
++
++#ifdef CheckRPktLost
++ if ( Dat_ULONG & 0x00000008 ) {
++ fprintf(fp_log, "[%sIntStatus] Received packet lost due to RX FIFO full : %08lx [loop:%d]\n", type, Dat_ULONG, Loop);
++ FindErr( Err_RPKT_LOST );
++ }
++#endif
++
++#ifdef CheckNPTxbufUNAVA
++ if ( Dat_ULONG & 0x00000040 ) {
++ fprintf(fp_log, "[%sIntStatus] Normal priority transmit buffer unavailable: %08lx [loop:%d]\n", type, Dat_ULONG, Loop);
++ FindErr( Err_NPTXBUF_UNAVA );
++ }
++#endif
++
++#ifdef CheckTPktLost
++ if ( Dat_ULONG & 0x00000080 ) {
++ fprintf(fp_log, "[%sIntStatus] Packets transmitted to Ethernet lost : %08lx [loop:%d]\n", type, Dat_ULONG, Loop);
++ FindErr( Err_TPKT_LOST );
++ }
++#endif
++#endif
++ if (Err_Flag)
++ return(1);
++ else
++ return(0);
++} // End int check_int (char *type)
++
++
++//------------------------------------------------------------
++// Buffer
++//------------------------------------------------------------
++void setup_framesize (void) {
++ int i;
++
++ #ifdef DbgPrn_FuncHeader
++ printf ("setup_framesize\n");
++ Debug_delay();
++ #endif
++
++ //------------------------------------------------------------
++ // Fill Frame Size out descriptor area
++ //------------------------------------------------------------
++ #ifdef SLT_UBOOT
++ if (0)
++ #else
++ if ( ENABLE_RAND_SIZE )
++ #endif
++ {
++ for (i = 0; i < DES_NUMBER; i++) {
++ if ( FRAME_Rand_Simple ) {
++ switch(rand() % 5) {
++ case 0 : FRAME_LEN[i] = 0x4e ; break;
++ case 1 : FRAME_LEN[i] = 0x4ba; break;
++ default: FRAME_LEN[i] = 0x5ea; break;
++ }
++ }
++ else {
++ FRAME_LEN_Cur = rand() % (MAX_FRAME_RAND_SIZE + 1);
++
++ if (FRAME_LEN_Cur < MIN_FRAME_RAND_SIZE)
++ FRAME_LEN_Cur = MIN_FRAME_RAND_SIZE;
++
++ FRAME_LEN[i] = FRAME_LEN_Cur;
++ }
++#ifdef SLT_DOS
++ if (DbgPrn_FRAME_LEN)
++ fprintf(fp_log, "[setup_framesize] FRAME_LEN_Cur:%08lx[Des:%d][loop:%d]\n", FRAME_LEN[i], i, Loop);
++#endif
++ }
++ }
++ else {
++ for (i = 0; i < DES_NUMBER; i++) {
++ #ifdef SelectSimpleLength
++ if (i % FRAME_SELH_PERD)
++ FRAME_LEN[i] = FRAME_LENH;
++ else
++ FRAME_LEN[i] = FRAME_LENL;
++ #else
++ if ( BurstEnable ) {
++ if (IEEETesting) {
++ FRAME_LEN[i] = 1514;
++ }
++ else {
++ #ifdef ENABLE_ARP_2_WOL
++ FRAME_LEN[i] = 164;
++ #else
++ FRAME_LEN[i] = 60;
++ #endif
++ }
++ }
++ else {
++ #ifdef SelectLengthInc
++// FRAME_LEN[i] = (i%1455)+60;
++ FRAME_LEN[i] = 1514-( i % 1455 );
++ #else
++ if (i % FRAME_SELH_PERD)
++ FRAME_LEN[i] = FRAME_LENH;
++ else
++ FRAME_LEN[i] = FRAME_LENL;
++ #endif
++ } // End if (BurstEnable)
++ #endif
++/*
++ switch(i % 20) {
++ case 0 : FRAME_LEN[i] = FRAME_LENH; break;
++ case 1 : FRAME_LEN[i] = FRAME_LENH; break;
++ case 2 : FRAME_LEN[i] = FRAME_LENH; break;
++ default: FRAME_LEN[i] = FRAME_LENL; break;
++ }
++*/
++#ifdef SLT_DOS
++ if (DbgPrn_FRAME_LEN)
++ fprintf(fp_log, "[setup_framesize] FRAME_LEN_Cur:%08lx[Des:%d][loop:%d]\n", FRAME_LEN[i], i, Loop);
++#endif
++ } // End for (i = 0; i < DES_NUMBER; i++)
++ } // End if ( ENABLE_RAND_SIZE )
++
++ // Calculate average of frame size
++ Avg_frame_len = 0;
++
++ for ( i = 0; i < DES_NUMBER; i++ ) {
++ Avg_frame_len += FRAME_LEN[i];
++ }
++
++ Avg_frame_len = Avg_frame_len / (double)DES_NUMBER;
++
++ //------------------------------------------------------------
++ // Write Plane
++ //------------------------------------------------------------
++ switch( ZeroCopy_OFFSET & 0x3 ) {
++ case 0: wp_fir = 0xffffffff; break;
++ case 1: wp_fir = 0xffffff00; break;
++ case 2: wp_fir = 0xffff0000; break;
++ case 3: wp_fir = 0xff000000; break;
++ }
++
++ for ( i = 0; i < DES_NUMBER; i++ ) {
++ switch( ( ZeroCopy_OFFSET + FRAME_LEN[i] - 1 ) & 0x3 ) {
++ case 0: wp_lst[i] = 0x000000ff; break;
++ case 1: wp_lst[i] = 0x0000ffff; break;
++ case 2: wp_lst[i] = 0x00ffffff; break;
++ case 3: wp_lst[i] = 0xffffffff; break;
++ }
++ } // End for ( i = 0; i < DES_NUMBER; i++ )
++} // End void setup_framesize (void)
++
++//------------------------------------------------------------
++void setup_arp (void) {
++ int i;
++ for (i = 0; i < 16; i++ )
++ ARP_data[i] = ARP_org_data[i];
++
++ ARP_data[1] = 0x0000ffff | ( SA[0] << 16 )
++ | ( SA[1] << 24 );
++
++ ARP_data[2] = ( SA[2] )
++ | ( SA[3] << 8 )
++ | ( SA[4] << 16 )
++ | ( SA[5] << 24 );
++
++ ARP_data[5] = 0x00000100 | ( SA[0] << 16 )
++ | ( SA[1] << 24 );
++
++ ARP_data[6] = ( SA[2] )
++ | ( SA[3] << 8 )
++ | ( SA[4] << 16 )
++ | ( SA[5] << 24 );
++} // End void setup_arp (void)
++
++//------------------------------------------------------------
++void setup_buf (void) {
++ int i;
++ int j;
++ ULONG adr;
++ ULONG adr_srt;
++ ULONG adr_end;
++ ULONG len;
++ #ifdef SelectSimpleDA
++ int cnt;
++ ULONG Current_framelen;
++ #endif
++
++ #ifdef ENABLE_ARP_2_WOL
++ int DA[3];
++
++ DA[0] = ( ( SelectWOLDA_DatH >> 8 ) & 0x00ff ) |
++ ( ( SelectWOLDA_DatH << 8 ) & 0xff00 );
++
++ DA[1] = ( ( SelectWOLDA_DatL >> 24 ) & 0x00ff ) |
++ ( ( SelectWOLDA_DatL >> 8 ) & 0xff00 );
++
++ DA[2] = ( ( SelectWOLDA_DatL >> 8 ) & 0x00ff ) |
++ ( ( SelectWOLDA_DatL << 8 ) & 0xff00 );
++ #endif
++
++ #ifdef DbgPrn_FuncHeader
++ printf ("setup_buf : %d\n", Loop);
++ Debug_delay();
++ #endif
++
++ // It need be multiple of 4
++ adr_srt = GET_DMA_BASE_SETUP & 0xfffffffc;
++
++ for (j = 0; j < DES_NUMBER; j++) {
++ if ( DbgPrn_BufAdr )
++ printf("[loop:%4d][des:%4d][setup_buf ] %08lx\n", Loop, j, adr_srt);
++
++ if ( BurstEnable ) {
++ if ( IEEETesting ) {
++ #ifdef ENABLE_DASA
++ WriteSOC_DD( adr_srt , 0xffffffff );
++ WriteSOC_DD( adr_srt + 4, ARP_data[1] );
++ WriteSOC_DD( adr_srt + 8, ARP_data[2] );
++
++ for (adr = (adr_srt + 12); adr < (adr_srt + DMA_PakSize); adr += 4 )
++ #else
++ for (adr = adr_srt; adr < (adr_srt + DMA_PakSize); adr += 4 )
++ #endif
++ {
++ switch( TestMode ) {
++ case 1: gdata = 0xffffffff; break;
++ case 2: gdata = 0x55555555; break;
++ case 3: gdata = rand() | (rand() << 16); break;
++ case 5: gdata = UserDVal; break;
++ }
++ WriteSOC_DD(adr, gdata);
++ } // End for()
++ }
++ else {
++ for (i = 0; i < 16; i++) {
++ WriteSOC_DD( adr_srt + ( i << 2 ), ARP_data[i] );
++ }
++
++ #ifdef ENABLE_ARP_2_WOL
++ for (i = 16; i < 40; i += 3) {
++ WriteSOC_DD( adr_srt + ( i << 2 ), ( DA[1] << 16 ) | DA[0] );
++ WriteSOC_DD( adr_srt + ( i << 2 ) + 4, ( DA[0] << 16 ) | DA[2] );
++ WriteSOC_DD( adr_srt + ( i << 2 ) + 8, ( DA[2] << 16 ) | DA[1] );
++ }
++ #endif
++ } // End if ( IEEETesting )
++ }
++ else {
++ // --------------------------------------------
++ #ifdef SelectSimpleData
++ #ifdef SimpleData_Fix
++ switch( j % SimpleData_FixNum ) {
++ case 0 : gdata = SimpleData_FixVal00; break;
++ case 1 : gdata = SimpleData_FixVal01; break;
++ case 2 : gdata = SimpleData_FixVal02; break;
++ case 3 : gdata = SimpleData_FixVal03; break;
++ case 4 : gdata = SimpleData_FixVal04; break;
++ case 5 : gdata = SimpleData_FixVal05; break;
++ case 6 : gdata = SimpleData_FixVal06; break;
++ case 7 : gdata = SimpleData_FixVal07; break;
++ case 8 : gdata = SimpleData_FixVal08; break;
++ case 9 : gdata = SimpleData_FixVal09; break;
++ case 10 : gdata = SimpleData_FixVal10; break;
++ default : gdata = SimpleData_FixVal11; break;
++ }
++ #else
++ gdata = 0x11111111 * ((j + SEED_START) % 256);
++ #endif
++
++ adr_end = adr_srt + DMA_PakSize;
++ for ( adr = adr_srt; adr < adr_end; adr += 4 ) {
++ WriteSOC_DD( adr, gdata );
++ }
++ // --------------------------------------------
++ #elif SelectSimpleDA
++
++ gdata = DATA_SEED(j + SEED_START);
++ Current_framelen = FRAME_LEN[j];
++
++ if ( DbgPrn_FRAME_LEN )
++ fprintf(fp_log, "[setup_buf ] Current_framelen:%08lx[Des:%d][loop:%d]\n", Current_framelen, j, Loop);
++
++ cnt = 0;
++ len = ( ( ( Current_framelen - 14 ) & 0xff ) << 8) |
++ ( ( Current_framelen - 14 ) >> 8 );
++
++ adr_end = adr_srt + DMA_PakSize;
++ for ( adr = adr_srt; adr < adr_end; adr += 4 ) {
++ cnt++;
++ if (cnt == 1 ) WriteSOC_DD( adr, SelectSimpleDA_Dat0 );
++ else if (cnt == 2 ) WriteSOC_DD( adr, SelectSimpleDA_Dat1 );
++ else if (cnt == 3 ) WriteSOC_DD( adr, SelectSimpleDA_Dat2 );
++ else if (cnt == 4 ) WriteSOC_DD( adr, len | (len << 16) );
++ else
++ WriteSOC_DD( adr, gdata );
++
++ gdata += DATA_IncVal;
++ }
++ // --------------------------------------------
++ #else
++
++ gdata = DATA_SEED(j + SEED_START);
++ adr_end = adr_srt + DMA_PakSize;
++ for ( adr = adr_srt; adr < adr_end; adr += 4 ) {
++ WriteSOC_DD( adr, gdata );
++
++ gdata += DATA_IncVal;
++ }
++
++ #endif
++
++ } // End if ( BurstEnable )
++
++ adr_srt += DMA_PakSize;
++ } // End for (j = 0; j < DES_NUMBER; j++)
++} // End void setup_buf (void)
++
++//------------------------------------------------------------
++// Check data of one packet
++//------------------------------------------------------------
++char check_Data (ULONG desadr, LONG number) {
++ int index;
++ int cnt;
++ ULONG rdata;
++ ULONG wp_lst_cur;
++ ULONG adr_las;
++ ULONG adr;
++ ULONG adr_srt;
++ ULONG adr_end;
++ ULONG len;
++ #ifdef SelectSimpleDA
++ ULONG gdata_bak;
++ #endif
++
++ #ifdef DbgPrn_FuncHeader
++ printf ("check_Data : %d\n", Loop);
++ Debug_delay();
++ #endif
++ //printf("[Des:%d][loop:%d]Desadr:%08x\n", number, Loop, desadr);
++
++ wp_lst_cur = wp_lst[number];
++ FRAME_LEN_Cur = FRAME_LEN[number];
++#ifdef SLT_DOS
++ if ( DbgPrn_FRAME_LEN )
++ fprintf(fp_log, "[check_Data ] FRAME_LEN_Cur:%08lx[Des:%d][loop:%d]\n", FRAME_LEN_Cur, number, Loop);
++#endif
++ adr_srt = ReadSOC_DD(desadr) & 0xfffffffc;
++ adr_end = adr_srt + PktByteSize;
++
++ #ifdef SelectSimpleData
++ #ifdef SimpleData_Fix
++ switch( number % SimpleData_FixNum ) {
++ case 0 : gdata = SimpleData_FixVal00; break;
++ case 1 : gdata = SimpleData_FixVal01; break;
++ case 2 : gdata = SimpleData_FixVal02; break;
++ case 3 : gdata = SimpleData_FixVal03; break;
++ case 4 : gdata = SimpleData_FixVal04; break;
++ case 5 : gdata = SimpleData_FixVal05; break;
++ case 6 : gdata = SimpleData_FixVal06; break;
++ case 7 : gdata = SimpleData_FixVal07; break;
++ case 8 : gdata = SimpleData_FixVal08; break;
++ case 9 : gdata = SimpleData_FixVal09; break;
++ case 10 : gdata = SimpleData_FixVal10; break;
++ default : gdata = SimpleData_FixVal11; break;
++ }
++ #else
++ gdata = 0x11111111 * ((number + SEED_START) % 256);
++ #endif
++ #else
++ gdata = DATA_SEED(number + SEED_START);
++ #endif
++
++ wp = wp_fir;
++ adr_las = adr_end - 4;
++
++ cnt = 0;
++ len = (((FRAME_LEN_Cur-14) & 0xff) << 8) | ((FRAME_LEN_Cur-14) >> 8);
++#ifdef SLT_DOS
++ if (DbgPrn_Bufdat)
++ fprintf(fp_log, " Inf:%08lx ~ %08lx(%08lx) %08lx [Des:%d][loop:%d]\n", adr_srt, adr_end, adr_las, gdata, number, Loop);
++#endif
++ for (adr = adr_srt; adr < adr_end; adr+=4) {
++
++ #ifdef SelectSimpleDA
++ cnt++;
++ if ( cnt == 1 ) { gdata_bak = gdata; gdata = SelectSimpleDA_Dat0; }
++ else if ( cnt == 2 ) { gdata_bak = gdata; gdata = SelectSimpleDA_Dat1; }
++ else if ( cnt == 3 ) { gdata_bak = gdata; gdata = SelectSimpleDA_Dat2; }
++ else if ( cnt == 4 ) { gdata_bak = gdata; gdata = len | (len << 16); }
++ #endif
++ rdata = ReadSOC_DD(adr);
++ if (adr == adr_las)
++ wp = wp & wp_lst_cur;
++
++ if ( (rdata & wp) != (gdata & wp) ) {
++#ifdef SLT_DOS
++ fprintf(fp_log, "\nError: Adr:%08lx[%3d] (%08lx) (%08lx:%08lx) [Des:%d][loop:%d]\n", adr, (adr - adr_srt) / 4, rdata, gdata, wp, number, Loop);
++#endif
++ for (index = 0; index < 6; index++) {
++ rdata = ReadSOC_DD(adr);
++#ifdef SLT_DOS
++ fprintf(fp_log, "Rep : Adr:%08lx (%08lx) (%08lx:%08lx) [Des:%d][loop:%d]\n", adr, rdata, gdata, wp, number, Loop);
++#endif
++ }
++
++ if ( DbgPrn_DumpMACCnt )
++ dump_mac_ROreg();
++
++ return( FindErr( Err_Check_Buf_Data ) );
++ } // End if ( (rdata & wp) != (gdata & wp) )
++#ifdef SLT_DOS
++ if ( DbgPrn_BufdatDetail )
++ fprintf(fp_log, " Adr:%08lx[%3d] (%08lx) (%08lx:%08lx) [Des:%d][loop:%d]\n", adr, (adr - adr_srt) / 4, rdata, gdata, wp, number, Loop);
++#endif
++ #ifdef SelectSimpleDA
++ if ( cnt <= 4 )
++ gdata = gdata_bak;
++ #endif
++
++ #ifdef SelectSimpleData
++ #else
++ gdata += DATA_IncVal;
++ #endif
++
++ wp = 0xffffffff;
++ }
++ return(0);
++} // End char check_Data (ULONG desadr, LONG number)
++
++//------------------------------------------------------------
++char check_buf (int loopcnt) {
++ int count;
++ ULONG desadr;
++
++ #ifdef DbgPrn_FuncHeader
++ printf ("check_buf : %d\n", Loop);
++ Debug_delay();
++ #endif
++
++ for ( count = DES_NUMBER - 1; count >= 0; count-- ) {
++ desadr = H_RDES_BASE + ( 16 * count ) + 12;
++ //printf("%d:%08x\n", count, desadr);
++ if (check_Data(desadr, count)) {
++ check_int ("");
++
++ return(1);
++ }
++ }
++ if ( check_int ("") )
++ return(1);
++
++ return(0);
++} // End char check_buf (int loopcnt)
++
++//------------------------------------------------------------
++// Descriptor
++//------------------------------------------------------------
++void setup_txdes (ULONG desadr, ULONG bufbase) {
++ ULONG bufadr;
++ ULONG desval;
++ int count;
++
++ #ifdef DbgPrn_FuncHeader
++ printf ("setup_txdes: %d\n", Loop);
++ Debug_delay();
++ #endif
++
++ bufadr = bufbase + ZeroCopy_OFFSET;
++
++ if (TxDataEnable) {
++ for (count = 0; count < DES_NUMBER; count++) {
++ FRAME_LEN_Cur = FRAME_LEN[count];
++ desval = TDES_IniVal;
++ #ifdef SLT_DOS
++ if (DbgPrn_FRAME_LEN)
++ fprintf(fp_log, "[setup_txdes ] FRAME_LEN_Cur:%08lx[Des:%d][loop:%d]\n", FRAME_LEN_Cur, count, Loop);
++ #endif
++ if (DbgPrn_BufAdr)
++ printf("[loop:%4d][des:%4d][setup_txdes] %08lx\n", Loop, count, bufadr);
++
++ WriteSOC_DD( desadr + 0x04, 0 );
++ WriteSOC_DD( desadr + 0x08, 0 );
++ WriteSOC_DD( desadr + 0x0C, (bufadr + CPU_BUS_ADDR_SDRAM_OFFSET) ); // 20130730
++ if ( count == ( DES_NUMBER - 1 ) )
++ WriteSOC_DD( desadr , desval | EOR_IniVal);
++ else
++ WriteSOC_DD( desadr , desval );
++
++ bufadr += DMA_PakSize;
++ desadr += 16;
++ }
++ }
++ else {
++ WriteSOC_DD( desadr , 0);
++ }
++} // End void setup_txdes (ULONG desadr, ULONG bufbase)
++
++//------------------------------------------------------------
++void setup_rxdes (ULONG desadr, ULONG bufbase) {
++ ULONG bufadr;
++ ULONG desval;
++ int count;
++
++ #ifdef DbgPrn_FuncHeader
++ printf ("setup_rxdes: %d\n", Loop);
++ Debug_delay();
++ #endif
++
++ bufadr = bufbase+ZeroCopy_OFFSET;
++ desval = RDES_IniVal;
++
++ if ( RxDataEnable ) {
++ for (count = 0; count < DES_NUMBER; count++) {
++ if (DbgPrn_BufAdr)
++ printf("[loop:%4d][des:%4d][setup_rxdes] %08lx\n", Loop, count, bufadr);
++ WriteSOC_DD( desadr + 0x04, 0 );
++ WriteSOC_DD( desadr + 0x08, 0 );
++ WriteSOC_DD( desadr + 0x0C, ( bufadr + CPU_BUS_ADDR_SDRAM_OFFSET) ); // 20130730
++ if ( count == ( DES_NUMBER - 1 ) )
++ WriteSOC_DD( desadr , desval | EOR_IniVal );
++ else
++ WriteSOC_DD( desadr , desval );
++
++ desadr += 16;
++ bufadr += DMA_PakSize;
++ }
++ }
++ else {
++ WriteSOC_DD( desadr , 0x80000000 );
++ } // End if ( RxDataEnable )
++} // End void setup_rxdes (ULONG desadr, ULONG bufbase)
++
++//------------------------------------------------------------
++// First setting TX and RX information
++//------------------------------------------------------------
++void setup_des (ULONG bufnum) {
++
++ if ( DbgPrn_BufAdr ) {
++ printf ("setup_rxdes: %ld\n", bufnum);
++ Debug_delay();
++ }
++
++ setup_txdes( H_TDES_BASE, GET_DMA_BASE_SETUP );
++ setup_rxdes( H_RDES_BASE, GET_DMA_BASE(0) );
++
++} // End void setup_des (ULONG bufnum)
++
++//------------------------------------------------------------
++// Move buffer point of TX and RX descriptor to next DMA buffer
++//------------------------------------------------------------
++void setup_des_loop (ULONG bufnum) {
++ int count;
++ ULONG H_rx_desadr;
++ ULONG H_tx_desadr;
++ ULONG H_tx_bufadr;
++ ULONG H_rx_bufadr;
++
++ if ( DbgPrn_BufAdr ) {
++ printf ("setup_rxdes_loop: %ld\n", bufnum);
++ Debug_delay();
++ }
++
++ if (RxDataEnable) {
++ H_rx_bufadr = GET_DMA_BASE( bufnum + 1 ) + ZeroCopy_OFFSET;
++ H_rx_desadr = H_RDES_BASE;
++//printf (" =====>setup_rxdes_loop: %ld [%lX]\n", bufnum, H_rx_bufadr);
++ for (count = 0; count < DES_NUMBER; count++) {
++ WriteSOC_DD(H_rx_desadr + 0x0C, (H_rx_bufadr + CPU_BUS_ADDR_SDRAM_OFFSET) ); // 20130730
++
++ if (count == (DES_NUMBER - 1)) {
++ WriteSOC_DD( H_rx_desadr, RDES_IniVal | EOR_IniVal );
++ }
++ else {
++ WriteSOC_DD( H_rx_desadr, RDES_IniVal );
++ }
++ H_rx_bufadr += DMA_PakSize;
++ H_rx_desadr += 16;
++ }
++ }
++
++ if (TxDataEnable) {
++ if (RxDataEnable) {
++ H_tx_bufadr = GET_DMA_BASE( bufnum ) + ZeroCopy_OFFSET;
++ }
++ else {
++ H_tx_bufadr = GET_DMA_BASE( 0 ) + ZeroCopy_OFFSET;
++ }
++ H_tx_desadr = H_TDES_BASE;
++//printf (" =====>setup_Txdes_loop: %ld [%lX]\n", bufnum, H_tx_bufadr);
++ for (count = 0; count < DES_NUMBER; count++) {
++ FRAME_LEN_Cur = FRAME_LEN[count];
++ WriteSOC_DD( H_tx_desadr + 0x0C, ( H_tx_bufadr + CPU_BUS_ADDR_SDRAM_OFFSET) ); // 20130730
++ if (count == (DES_NUMBER - 1)) {
++ WriteSOC_DD( H_tx_desadr, TDES_IniVal | EOR_IniVal );
++ }
++ else {
++ WriteSOC_DD( H_tx_desadr, TDES_IniVal );
++ }
++ H_tx_bufadr += DMA_PakSize;
++ H_tx_desadr += 16;
++ }
++ }
++
++ WriteSOC_DD( H_MAC_BASE + 0x18, 0x00000000 ); // Tx Poll
++ WriteSOC_DD( H_MAC_BASE + 0x1c, 0x00000000 ); // Rx Poll
++} // End void setup_des_loop (ULONG bufnum)
++
++//------------------------------------------------------------
++char check_des_header_Tx (char *type, ULONG adr, LONG desnum) {
++ int timeout = 0;
++ ULONG dat;
++
++ dat = ReadSOC_DD(adr);
++
++ while ( HWOwnTx(dat) ) {
++ // we will run again, if transfer has not been completed.
++ if ( RxDataEnable && (++timeout > TIME_OUT_Des) ) {
++ #ifdef SLT_DOS
++ fprintf(fp_log, "[%sTxDesOwn] Address %08lx = %08lx [Des:%d][loop:%d]\n", type, adr, dat, desnum, Loop);
++ #endif
++ return(FindErr_Des(Check_Des_TxOwnTimeOut));
++ }
++ WriteSOC_DD(H_MAC_BASE + 0x18, 0x00000000);//Tx Poll
++ WriteSOC_DD(H_MAC_BASE + 0x1c, 0x00000000);//Rx Poll
++
++ #ifdef Delay_ChkTxOwn
++ delay(Delay_ChkTxOwn);
++ #endif
++ dat = ReadSOC_DD(adr);
++ }
++
++ return(0);
++} // End char check_des_header_Tx (char *type, ULONG adr, LONG desnum)
++
++//------------------------------------------------------------
++char check_des_header_Rx (char *type, ULONG adr, LONG desnum) {
++ #ifdef CheckRxOwn
++ int timeout = 0;
++ ULONG dat;
++
++ dat = ReadSOC_DD(adr);
++
++ while ( HWOwnRx( dat ) ) {
++ // we will run again, if transfer has not been completed.
++ if (TxDataEnable && (++timeout > TIME_OUT_Des)) {
++ #ifdef SLT_DOS
++ fprintf(fp_log, "[%sRxDesOwn] Address %08lx = %08lx [Des:%d][loop:%d]\n", type, adr, dat, desnum, Loop);
++ #endif
++ return(FindErr_Des(Check_Des_RxOwnTimeOut));
++ }
++
++ WriteSOC_DD(H_MAC_BASE + 0x18, 0x00000000);//Tx Poll
++ WriteSOC_DD(H_MAC_BASE + 0x1c, 0x00000000);//Rx Poll
++
++ #ifdef Delay_ChkRxOwn
++ delay(Delay_ChkRxOwn);
++ #endif
++ dat = ReadSOC_DD(adr);
++ };
++
++ Dat_ULONG = ReadSOC_DD( adr + 12 );
++
++ #ifdef CheckRxLen
++ #ifdef SLT_DOS
++ if ( DbgPrn_FRAME_LEN )
++ fprintf(fp_log, "[%sRxDes ] FRAME_LEN_Cur:%08lx[Des:%d][loop:%d]\n", type, (FRAME_LEN_Cur + 4), desnum, Loop);
++ #endif
++
++ if ((dat & 0x3fff) != (FRAME_LEN_Cur + 4)) {
++ #ifdef SLT_DOS
++ fprintf(fp_log, "[%sRxDes] Error Frame Length %08lx:%08lx %08lx(%4d/%4d) [Des:%d][loop:%d]\n", type, adr, dat, Dat_ULONG, (dat & 0x3fff), (FRAME_LEN_Cur + 4), desnum, Loop);
++ #endif
++ FindErr_Des(Check_Des_FrameLen);
++ }
++ #endif // End CheckRxLen
++
++ #ifdef CheckRxErr
++ if (dat & 0x00040000) {
++ #ifdef SLT_DOS
++ fprintf(fp_log, "[%sRxDes] Error RxErr %08lx:%08lx %08lx [Des:%d][loop:%d]\n", type, adr, dat, Dat_ULONG, desnum, Loop);
++ #endif
++ FindErr_Des(Check_Des_RxErr);
++ }
++ #endif // End CheckRxErr
++
++ #ifdef CheckOddNibble
++ if (dat & 0x00400000) {
++ #ifdef SLT_DOS
++ fprintf(fp_log, "[%sRxDes] Odd Nibble %08lx:%08lx %08lx [Des:%d][loop:%d]\n", type, adr, dat, Dat_ULONG, desnum, Loop);
++ #endif
++ FindErr_Des(Check_Des_OddNibble);
++ }
++ #endif // End CheckOddNibble
++
++ #ifdef CheckCRC
++ if (dat & 0x00080000) {
++ #ifdef SLT_DOS
++ fprintf(fp_log, "[%sRxDes] Error CRC %08lx:%08lx %08lx [Des:%d][loop:%d]\n", type, adr, dat, Dat_ULONG, desnum, Loop);
++ #endif
++ FindErr_Des(Check_Des_CRC);
++ }
++ #endif // End CheckCRC
++
++ #ifdef CheckRxFIFOFull
++ if (dat & 0x00800000) {
++ #ifdef SLT_DOS
++ fprintf(fp_log, "[%sRxDes] Error Rx FIFO Full %08lx:%08lx %08lx [Des:%d][loop:%d]\n", type, adr, dat, Dat_ULONG, desnum, Loop);
++ #endif
++ FindErr_Des(Check_Des_RxFIFOFull);
++ }
++ #endif // End CheckRxFIFOFull
++
++ // if (check_int ("")) {return(1);}
++ #endif // End CheckRxOwn
++
++ if (Err_Flag)
++ return(1);
++ else
++ return(0);
++} // End char check_des_header_Rx (char *type, ULONG adr, LONG desnum)
++
++//------------------------------------------------------------
++char check_des (ULONG bufnum, int checkpoint) {
++ int desnum;
++ ULONG H_rx_desadr;
++ ULONG H_tx_desadr;
++ ULONG H_tx_bufadr;
++ ULONG H_rx_bufadr;
++
++ #ifdef Delay_DesGap
++ ULONG dly_cnt = 0;
++ ULONG dly_max = Delay_CntMaxIncVal;
++ #endif
++
++ #ifdef DbgPrn_FuncHeader
++ printf ("check_des : %d(%d)\n", Loop, checkpoint);
++ Debug_delay();
++ #endif
++
++ // Fire the engine to send and recvice
++ WriteSOC_DD( H_MAC_BASE + 0x18, 0x00000000 );//Tx Poll
++ WriteSOC_DD( H_MAC_BASE + 0x1c, 0x00000000 );//Rx Poll
++
++ #ifdef SelectSimpleDes
++ #else
++ if ( IEEETesting == 1 ) {
++ // IEEE test mode, there is the same data in every lan packet
++ H_tx_bufadr = GET_DMA_BASE_SETUP;
++ H_rx_bufadr = GET_DMA_BASE(0);
++ }
++ else {
++ H_rx_bufadr = GET_DMA_BASE( bufnum + 1 ) + ZeroCopy_OFFSET;
++
++ if (RxDataEnable) {
++ H_tx_bufadr = GET_DMA_BASE(bufnum ) + ZeroCopy_OFFSET;
++ }
++ else {
++ H_tx_bufadr = GET_DMA_BASE( 0 ) + ZeroCopy_OFFSET;
++ }
++ }
++ #endif
++
++ H_rx_desadr = H_RDES_BASE;
++ H_tx_desadr = H_TDES_BASE;
++
++ #ifdef Delay_DES
++ delay(Delay_DES);
++ #endif
++
++ for (desnum = 0; desnum < DES_NUMBER; desnum++) {
++ if ( DbgPrn_BufAdr )
++ printf( "[loop:%4d][des:%4d][check_des ] %08lx %08lx [%08lx] [%08lx]\n", Loop, desnum, ( H_tx_desadr ), ( H_rx_desadr ), ReadSOC_DD( H_tx_desadr + 12 ), ReadSOC_DD( H_rx_desadr + 12 ) );
++
++ //[Delay]--------------------
++ #ifdef Delay_DesGap
++ if ( dly_cnt++ > 3 ) {
++ switch ( rand() % 12 ) {
++ case 1 : dly_max = 00000; break;
++ case 3 : dly_max = 20000; break;
++ case 5 : dly_max = 40000; break;
++ case 7 : dly_max = 60000; break;
++ defaule: dly_max = 70000; break;
++ }
++
++ dly_max += ( rand() % 4 ) * 14321;
++
++ while (dly_cnt < dly_max) {
++ dly_cnt++;
++ }
++
++ dly_cnt = 0;
++ }
++ else {
++// timeout = 0;
++// while (timeout < 50000) {timeout++;};
++ }
++ #endif // End Delay_DesGap
++
++ //[Check Owner Bit]--------------------
++ FRAME_LEN_Cur = FRAME_LEN[desnum];
++#ifdef SLT_DOS
++ if ( DbgPrn_FRAME_LEN )
++ fprintf(fp_log, "[check_des ] FRAME_LEN_Cur:%08lx[Des:%d][loop:%d]%d\n", FRAME_LEN_Cur, desnum, Loop, checkpoint);
++#endif
++// if (BurstEnable) {
++// if (check_des_header_Tx("", H_tx_desadr, desnum)) {CheckDesFail_DesNum = desnum; return(1);}
++// } else {
++// if (check_des_header_Rx("", H_rx_desadr, desnum)) {CheckDesFail_DesNum = desnum; return(1);}
++// if (check_des_header_Tx("", H_tx_desadr, desnum)) {CheckDesFail_DesNum = desnum; return(1);}
++// }
++
++ // Check the description of Tx and Rx
++ if ( RxDataEnable && check_des_header_Rx("", H_rx_desadr, desnum) ) {
++ CheckDesFail_DesNum = desnum;
++
++ return(1);
++ }
++ if ( TxDataEnable && check_des_header_Tx("", H_tx_desadr, desnum) ) {
++ CheckDesFail_DesNum = desnum;
++
++ return(1);
++ }
++// else {
++// printf(" %d \r", desnum);
++// }
++
++ #ifdef SelectSimpleDes
++ #else
++ if ( !checkpoint ) {
++ // Setting buffer address to description of Tx and Rx on next stage
++
++// if (!BurstEnable) {
++// WriteSOC_DD( H_rx_desadr + 0x0C, (H_rx_bufadr + CPU_BUS_ADDR_SDRAM_OFFSET) );
++// WriteSOC_DD( H_tx_desadr + 0x0C, (H_tx_bufadr + CPU_BUS_ADDR_SDRAM_OFFSET) );
++// }
++//
++// if ( desnum == (DES_NUMBER - 1) ) {
++// WriteSOC_DD( H_rx_desadr, RDES_IniVal | EOR_IniVal );
++// WriteSOC_DD( H_tx_desadr, TDES_IniVal | EOR_IniVal );
++// }
++// else {
++// WriteSOC_DD( H_rx_desadr, RDES_IniVal );
++// WriteSOC_DD( H_tx_desadr, TDES_IniVal );
++// }
++// WriteSOC_DD( H_MAC_BASE+0x18, 0x00000000 ); //Tx Poll
++// WriteSOC_DD( H_MAC_BASE+0x1c, 0x00000000 ); //Rx Poll
++
++ if ( RxDataEnable ) {
++ WriteSOC_DD( H_rx_desadr + 0x0C, (H_rx_bufadr + CPU_BUS_ADDR_SDRAM_OFFSET) ); // 20130730
++
++ if ( desnum == (DES_NUMBER - 1) ) {
++ WriteSOC_DD( H_rx_desadr, RDES_IniVal | EOR_IniVal );
++ } else {
++ WriteSOC_DD( H_rx_desadr, RDES_IniVal );
++ }
++ }
++ if ( TxDataEnable ) {
++ WriteSOC_DD( H_tx_desadr + 0x0C, (H_tx_bufadr + CPU_BUS_ADDR_SDRAM_OFFSET) ); // 20130730
++ if ( desnum == (DES_NUMBER - 1) ) {
++ WriteSOC_DD( H_tx_desadr, TDES_IniVal | EOR_IniVal );
++ }
++ else {
++ WriteSOC_DD( H_tx_desadr, TDES_IniVal );
++ }
++ }
++ WriteSOC_DD( H_MAC_BASE + 0x18, 0x00000000 ); //Tx Poll
++ WriteSOC_DD( H_MAC_BASE + 0x1c, 0x00000000 ); //Rx Poll
++ }
++ H_rx_bufadr += DMA_PakSize;
++ H_tx_bufadr += DMA_PakSize;
++ #endif // End SelectSimpleDes
++
++ H_rx_desadr += 16;
++ H_tx_desadr += 16;
++ } // End for (desnum = 0; desnum < DES_NUMBER; desnum++)
++
++ return(0);
++} // End char check_des (ULONG bufnum, int checkpoint)
++//#endif
++
++//------------------------------------------------------------
++// Print
++//------------------------------------------------------------
++void PrintMode (void) {
++ if (Enable_MAC34) printf ("run_mode[dec] | 0->MAC1 1->MAC2 2->MAC3 3->MAC4\n");
++ else printf ("run_mode[dec] | 0->MAC1 1->MAC2\n");
++}
++
++//------------------------------------------------------------
++void PrintSpeed (void) {
++ printf ("speed[dec] | 0->1G 1->100M 2->10M 3->all speed (default:%3d)\n", DEF_SPEED);
++}
++
++//------------------------------------------------------------
++void PrintCtrl (void) {
++ printf ("ctrl[dec] | bit0~2: Reserved\n");
++ printf ("(default:%3d) | bit3 : 1->Enable PHY init 0->Disable PHY init\n", GCtrl);
++ printf (" | bit4 : 1->Enable PHY int-loop 0->Disable PHY int-loop\n");
++ printf (" | bit5 : 1->Ignore PHY ID 0->Check PHY ID\n");
++ if (AST2400) {
++ printf (" | bit6 : 1->Enable MAC int-loop 0->Disable MAC int-loop\n");
++ }
++}
++
++//------------------------------------------------------------
++void PrintLoop (void) {
++ printf ("loop_max[dec] | 1G : 20 will run 1 sec (default:%3d)\n", DEF_LOOP_MAX * 20);
++ printf (" | 100M: 2 will run 1 sec (default:%3d)\n", DEF_LOOP_MAX * 2);
++ printf (" | 10M : 1 will run 1 sec (default:%3d)\n", DEF_LOOP_MAX);
++}
++
++//------------------------------------------------------------
++void PrintTest (void) {
++ if ( ModeSwitch == MODE_NSCI ) {
++ printf ("test_mode[dec] | 0: NCSI configuration with Disable_Channel request\n");
++ printf ("(default:%3d) | 1: NCSI configuration without Disable_Channel request\n", DEF_TESTMODE);
++ }
++ else {
++ printf ("test_mode[dec] | 0: Tx/Rx frame checking\n");
++ printf ("(default:%3d) | 1: Tx output 0xff frame\n", DEF_TESTMODE);
++ printf (" | 2: Tx output 0x55 frame\n");
++ printf (" | 3: Tx output random frame\n");
++ printf (" | 4: Tx output ARP frame\n");
++ printf (" | 5: Tx output user defined value frame (default:0x%8x)\n", DEF_USER_DEF_PACKET_VAL);
++ } // End if ( ModeSwitch == MODE_NSCI )
++
++ if (AST2300) {
++ printf (" | 6: IO timing testing\n");
++ printf (" | 7: IO timing/strength testing\n");
++ }
++}
++
++//------------------------------------------------------------
++void PrintPHYAdr (void) {
++ printf ("phy_adr[dec] | 0~31: PHY Address (default:%d)\n", DEF_PHY_ADR);
++}
++
++//------------------------------------------------------------
++void PrintIOTimingBund (void) {
++ printf ("IO margin[dec] | 0/1/3/5 (default:%d)\n", DEF_IOTIMINGBUND);
++}
++
++//------------------------------------------------------------
++void PrintPakNUm (void) {
++ printf ("package_num[dec] | 1~ 8: Total Number of NCSI Package (default:%d)\n", DEF_PACKAGE2NUM);
++}
++
++//------------------------------------------------------------
++void PrintChlNUm (void) {
++ printf ("channel_num[dec] | 1~32: Total Number of NCSI Channel (default:%d)\n", DEF_CHANNEL2NUM);
++}
++
++//------------------------------------------------------------
++
++void Print_Header (BYTE option) {
++
++ FILE_VAR
++
++ GET_OBJ( option )
++
++ if (GSpeed_sel[0]) PRINT(OUT_OBJ " 1G ");
++ else if (GSpeed_sel[1]) PRINT(OUT_OBJ " 100M ");
++ else PRINT(OUT_OBJ " 10M ");
++
++ switch (TestMode) {
++ case 0 : PRINT(OUT_OBJ "Tx/Rx frame checking \n" ); break;
++ case 1 : PRINT(OUT_OBJ "Tx output 0xff frame \n" ); break;
++ case 2 : PRINT(OUT_OBJ "Tx output 0x55 frame \n" ); break;
++ case 3 : PRINT(OUT_OBJ "Tx output random frame \n" ); break;
++ case 4 : PRINT(OUT_OBJ "Tx output ARP frame \n" ); break;
++ case 5 : PRINT(OUT_OBJ "Tx output 0x%08lx frame \n", UserDVal); break;
++ case 6 : PRINT(OUT_OBJ "IO delay testing \n" ); break;
++ case 7 : PRINT(OUT_OBJ "IO delay testing(Strength) \n" ); break;
++ case 8 : PRINT(OUT_OBJ "Tx frame \n" ); break;
++ case 9 : PRINT(OUT_OBJ "Rx frame checking \n" ); break;
++ }
++}
++
++//------------------------------------------------------------
++void PrintIO_Header (BYTE option) {
++
++ FILE_VAR
++
++ GET_OBJ( option )
++
++ if ( IOStrength ) {
++ if (GSpeed_sel[0]) PRINT(OUT_OBJ "[Strength %ld][1G ]========================================\n", IOStr_i);
++ else if (GSpeed_sel[1]) PRINT(OUT_OBJ "[Strength %ld][100M]========================================\n", IOStr_i);
++ else PRINT(OUT_OBJ "[Strength %ld][10M ]========================================\n", IOStr_i);
++ } else {
++ if (GSpeed_sel[0]) PRINT(OUT_OBJ "[1G ]========================================\n");
++ else if (GSpeed_sel[1]) PRINT(OUT_OBJ "[100M]========================================\n");
++ else PRINT(OUT_OBJ "[10M ]========================================\n");
++ }
++
++#ifdef Enable_Old_Style
++ if (Enable_RMII) PRINT(OUT_OBJ "Tx:SCU48[ %2d]= ", IOdly_out_shf);
++ else PRINT(OUT_OBJ "Tx:SCU48[%2d:%2d]= ", IOdly_out_shf+3, IOdly_out_shf);
++
++ for (IOdly_j = IOdly_out_str; IOdly_j <= IOdly_out_end; IOdly_j+=IOdly_incval) {
++ IOdly_out = valary[IOdly_j];
++ PRINT(OUT_OBJ "%2x", IOdly_out);
++ }
++
++ PRINT(OUT_OBJ "\n ");
++ for (IOdly_j = IOdly_out_str; IOdly_j <= IOdly_out_end; IOdly_j+=IOdly_incval) {
++ if (IOdly_out_reg_idx == IOdly_j) PRINT(OUT_OBJ " |");
++ else PRINT(OUT_OBJ " ");
++ }
++#else
++ PRINT(OUT_OBJ "Rx:SCU48[%2d:%2d]= ", IOdly_in_shf+3, IOdly_in_shf);
++
++ for (IOdly_i = IOdly_in_str; IOdly_i <= IOdly_in_end; IOdly_i+=IOdly_incval) {
++ IOdly_in = valary[IOdly_i];
++ PRINT(OUT_OBJ "%2x", IOdly_in);
++ }
++
++ PRINT(OUT_OBJ "\n ");
++ for (IOdly_i = IOdly_in_str; IOdly_i <= IOdly_in_end; IOdly_i+=IOdly_incval) {
++ if (IOdly_in_reg_idx == IOdly_i) PRINT(OUT_OBJ " |");
++ else PRINT(OUT_OBJ " ");
++ }
++#endif
++
++ PRINT(OUT_OBJ "\n");
++} // End void PrintIO_Header (BYTE option)
++
++//------------------------------------------------------------
++void PrintIO_LineS (BYTE option) {
++
++ FILE_VAR
++
++ GET_OBJ( option )
++
++
++#ifdef Enable_Old_Style
++ if (IOdly_in_reg == IOdly_in) {
++ PRINT(OUT_OBJ "Rx:SCU48[%2d:%2d]=%01x:-", IOdly_in_shf+3, IOdly_in_shf, IOdly_in);
++ }
++ else {
++ PRINT(OUT_OBJ "Rx:SCU48[%2d:%2d]=%01x: ", IOdly_in_shf+3, IOdly_in_shf, IOdly_in);
++ }
++#else
++ if (Enable_RMII) {
++ if (IOdly_out_reg == IOdly_out) {
++ PRINT(OUT_OBJ "Tx:SCU48[ %2d]=%01x:-", IOdly_out_shf, IOdly_out);
++ }
++ else {
++ PRINT(OUT_OBJ "Tx:SCU48[ %2d]=%01x: ", IOdly_out_shf, IOdly_out);
++ }
++ } else {
++ if (IOdly_out_reg == IOdly_out) {
++ PRINT(OUT_OBJ "Tx:SCU48[%2d:%2d]=%01x:-", IOdly_out_shf+3, IOdly_out_shf, IOdly_out);
++ }
++ else {
++ PRINT(OUT_OBJ "Tx:SCU48[%2d:%2d]=%01x: ", IOdly_out_shf+3, IOdly_out_shf, IOdly_out);
++ }
++ }
++#endif
++} // void PrintIO_LineS (BYTE option)
++
++//------------------------------------------------------------
++void PrintIO_Line (BYTE option) {
++
++ FILE_VAR
++
++ GET_OBJ( option )
++
++ if ( ( IOdly_in_reg == IOdly_in ) && ( IOdly_out_reg == IOdly_out ) ) {
++ if (dlymap[IOdly_i][IOdly_j]) PRINT(OUT_OBJ " X");
++ else PRINT(OUT_OBJ " O");
++ }
++ else {
++ if (dlymap[IOdly_i][IOdly_j]) PRINT(OUT_OBJ " x");
++ else PRINT(OUT_OBJ " o");
++ }
++} // End void PrintIO_Line (BYTE option)
++
++//------------------------------------------------------------
++void PrintIO_Line_LOG (void) {
++#ifndef SLT_UBOOT
++#ifdef Enable_Old_Style
++ if (Enable_RMII) fprintf(fp_log, "\nTx:SCU48[ %2d]=%2x, ", IOdly_out_shf, IOdly_out);
++ else fprintf(fp_log, "\nTx:SCU48[%2d:%2d]=%2x, ", IOdly_out_shf+3, IOdly_out_shf, IOdly_out);
++
++ fprintf(fp_log, "Rx:SCU48[%2d:%2d]=%01x: ", IOdly_in_shf+3, IOdly_in_shf, IOdly_in);
++
++ if (dlymap[IOdly_i][IOdly_j]) fprintf(fp_log, " X\n");
++ else fprintf(fp_log, " O\n");
++#else
++ fprintf(fp_log, "\nRx:SCU48[%2d:%2d]=%2x, ", IOdly_in_shf+3, IOdly_in_shf, IOdly_in);
++
++ if (Enable_RMII) fprintf(fp_log, "Tx:SCU48[ %2d]=%01x: ", IOdly_out_shf, IOdly_out);
++ else fprintf(fp_log, "Tx:SCU48[%2d:%2d]=%01x: ", IOdly_out_shf+3, IOdly_out_shf, IOdly_out);
++
++ if (dlymap[IOdly_i][IOdly_j]) fprintf(fp_log, " X\n");
++ else fprintf(fp_log, " O\n");
++#endif
++#endif
++}
++
++//------------------------------------------------------------
++// main
++//------------------------------------------------------------
++void Calculate_LOOP_CheckNum (void) {
++
++#define ONE_MBYTE 1048576
++
++ #ifdef CheckDataEveryTime
++ LOOP_CheckNum = 1;
++ #else
++ if (IOTiming || IOTimingBund || (GSpeed == SET_1G_100M_10MBPS)) {
++ LOOP_CheckNum = LOOP_MAX;
++ }
++ else {
++ switch ( GSpeed ) {
++ case SET_1GBPS : CheckBuf_MBSize = MOVE_DATA_MB_SEC ; break; // 1G
++ case SET_100MBPS : CheckBuf_MBSize = (MOVE_DATA_MB_SEC >> 3); break; // 100M ~ 1G / 8
++ case SET_10MBPS : CheckBuf_MBSize = (MOVE_DATA_MB_SEC >> 6); break; // 10M ~ 1G / 64
++ }
++ LOOP_CheckNum = ( CheckBuf_MBSize / ( ((DES_NUMBER * DMA_PakSize) / ONE_MBYTE ) + 1) );
++ }
++ #endif
++}
++
++//------------------------------------------------------------
++void TestingSetup (void) {
++ #ifdef DbgPrn_FuncHeader
++ printf ("TestingSetup\n");
++ Debug_delay();
++ #endif
++
++ #ifdef SLT_UBOOT
++ #else
++ #ifdef Rand_Sed
++ srand((unsigned) Rand_Sed);
++ #else
++ srand((unsigned) timestart);
++ #endif
++ #endif
++
++ //[Disable VGA]--------------------
++ #ifdef Disable_VGA
++ if ( LOOP_INFINI & ~(BurstEnable || IOTiming) ) {
++ VGAModeVld = 1;
++ outp(0x3d4, 0x17);
++ VGAMode = inp(0x3d5);
++ outp(0x3d4, 0x17);
++ outp(0x3d5, 0);
++ }
++ #endif
++
++ //[Setup]--------------------
++ setup_framesize();
++ setup_buf();
++}
++
++//------------------------------------------------------------
++// Return 1 ==> fail
++// Return 0 ==> PASS
++//------------------------------------------------------------
++char TestingLoop (ULONG loop_checknum) {
++ char checkprd;
++ char looplast;
++ char checken;
++
++ #ifdef SLT_UBOOT
++ #else
++ clock_t timeold;
++ #endif
++
++ #ifdef DbgPrn_FuncHeader
++ printf ("TestingLoop: %d\n", Loop);
++ Debug_delay();
++ #endif
++
++ if ( DbgPrn_DumpMACCnt )
++ dump_mac_ROreg();
++
++ //[Setup]--------------------
++ Loop = 0;
++ checkprd = 0;
++ checken = 0;
++ looplast = 0;
++
++ setup_des( 0 );
++
++ #ifdef SLT_UBOOT
++ #else
++ timeold = clock();
++ #endif
++
++ while ( (Loop < LOOP_MAX) || LOOP_INFINI ) {
++ looplast = !LOOP_INFINI && (Loop == LOOP_MAX - 1);
++
++ #ifdef CheckRxBuf
++ if (!BurstEnable) {
++ checkprd = ((Loop % loop_checknum) == (loop_checknum - 1));
++ }
++ checken = looplast | checkprd;
++ #endif
++
++ if ( DataDelay & ( Loop == 0 ) ) {
++ printf ("Press any key to start...\n");
++ GET_CAHR();
++ }
++
++#ifdef DbgPrn_FuncHeader
++ if ( DbgPrn_BufAdr ) {
++ printf ("for start ======> %d/%d(%d) looplast:%d checkprd:%d checken:%d\n", Loop, LOOP_MAX, LOOP_INFINI, looplast, checkprd, checken);
++ Debug_delay();
++ }
++#endif
++
++ //[Check DES]--------------------
++ if ( check_des(Loop, checken) ) {
++ //descriptor error
++ #ifdef CheckRxBuf
++ DES_NUMBER = CheckDesFail_DesNum + 1;
++ if ( checkprd ) {
++ check_buf(loop_checknum);
++ }
++ else {
++ check_buf((LOOP_MAX % loop_checknum));
++ }
++ DES_NUMBER = DES_NUMBER_Org;
++ #endif
++
++ if (DbgPrn_DumpMACCnt)
++ dump_mac_ROreg();
++
++ return(1);
++ }
++
++ //[Check Buf]--------------------
++ if ( RxDataEnable && checken ) {
++ #ifdef SLT_UBOOT
++ #else
++ timeused = (clock() - timeold) / (double) CLK_TCK;
++ #endif
++
++ if ( checkprd ) {
++ #ifdef SLT_DOS
++ #else
++ #ifdef SLT_UBOOT
++ #else
++ printf("[run loop:%3d] BandWidth: %7.2f Mbps, %6.2f sec\n", loop_checknum, ((double)loop_checknum * (double)DES_NUMBER * Avg_frame_len * 8.0) / ((double)timeused * 1000000.0), timeused);
++ fprintf(fp_log, "[run loop:%3d] BandWidth: %7.2f Mbps, %6.2f sec\n", loop_checknum, ((double)loop_checknum * (double)DES_NUMBER * Avg_frame_len * 8.0) / ((double)timeused * 1000000.0), timeused);
++ #endif
++ #endif
++
++ #ifdef CheckRxBuf
++ if ( check_buf( loop_checknum ) )
++ return(1);
++ #endif
++ }
++ else {
++ #ifdef SLT_DOS
++ #else
++ #ifdef SLT_UBOOT
++ #else
++ printf("[run loop:%3d] BandWidth: %7.2f Mbps, %6.2f sec\n", (LOOP_MAX % loop_checknum), ((double)(LOOP_MAX % loop_checknum) * (double)DES_NUMBER * Avg_frame_len * 8.0) / ((double)timeused * 1000000.0), timeused);
++ fprintf(fp_log, "[run loop:%3d] BandWidth: %7.2f Mbps, %6.2f sec\n", (LOOP_MAX % loop_checknum), ((double)(LOOP_MAX % loop_checknum) * (double)DES_NUMBER * Avg_frame_len * 8.0) / ((double)timeused * 1000000.0), timeused);
++ #endif
++ #endif
++
++ #ifdef CheckRxBuf
++ if ( check_buf( ( LOOP_MAX % loop_checknum ) ) )
++ return(1);
++ #endif
++ } // End if ( checkprd )
++
++ #ifdef SelectSimpleDes
++ #else
++ if ( !looplast )
++ setup_des_loop( Loop );
++ #endif
++
++ #ifdef SLT_DOS
++ #else
++ #ifdef SLT_UBOOT
++ #else
++ timeold = clock();
++ #endif
++ #endif
++
++ } // End if ( RxDataEnable && checken )
++
++ #ifdef SelectSimpleDes
++ if ( !looplast )
++ setup_des_loop( Loop );
++ #endif
++
++ if ( LOOP_INFINI ) {
++ printf("===============> Loop: %d \r", Loop);
++ }
++ else if (TestMode == 0) {
++ if (!(DbgPrn_BufAdr || IOTimingBund))
++ printf(" %d \r", Loop);
++// switch (Loop % 4) {
++// case 0x00: printf("| %d \r", Loop); break;
++// case 0x01: printf("/ %d \r", Loop); break;
++// case 0x02: printf("- %d \r", Loop); break;
++// default : printf("\ %d \r", Loop); break;
++// }
++ }
++
++ if ( DbgPrn_BufAdr ) {
++ printf ("for end ======> %d/%d(%d)\n", Loop, LOOP_MAX, LOOP_INFINI);
++ Debug_delay();
++ }
++
++ Loop++;
++ } // End while ((Loop < LOOP_MAX) || LOOP_INFINI)
++
++ Loop_rl[GSpeed_idx] = Loop;
++
++ return(0);
++} // End char TestingLoop (ULONG loop_checknum)
++
++
+diff --git a/arch/arm/cpu/arm926ejs/aspeed/Makefile b/arch/arm/cpu/arm926ejs/aspeed/Makefile
+new file mode 100644
+index 0000000..378745e
+--- /dev/null
++++ b/arch/arm/cpu/arm926ejs/aspeed/Makefile
+@@ -0,0 +1,53 @@
++# This program is free software; you can redistribute it and/or
++# modify it under the terms of the GNU General Public License as
++# published by the Free Software Foundation; either version 2 of
++# the License, or (at your option) any later version.
++#
++# This program is distributed in the hope that it will be useful,
++# but WITHOUT ANY WARRANTY; without even the implied warranty of
++# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++# GNU General Public License for more details.
++#
++# You should have received a copy of the GNU General Public License
++# along with this program; if not, write to the Free Software
++# Foundation, Inc., 59 Temple Place, Suite 330, Boston,
++# MA 02111-1307 USA
++#
++
++include $(TOPDIR)/config.mk
++
++LIB = $(obj)lib$(SOC).a
++
++COBJS = timer.o
++COBJS += reset.o
++COBJS += mactest.o
++COBJS += DRAM_SPI.o
++COBJS += IO.o
++COBJS += LIB.o
++COBJS += MAC.o
++COBJS += NCSI.o
++COBJS += PCI_SPI.o
++COBJS += PHY.o
++COBJS += SPIM.o
++COBJS += STDUBOOT.o
++COBJS += PLLTESTU.o
++COBJS += TRAPTEST.o
++COBJS += STRESS.o
++
++SRCS := $(START:.o=.S) $(SOBJS:.o=.S) $(COBJS:.o=.c)
++OBJS := $(addprefix $(obj),$(COBJS) $(SOBJS))
++START := $(addprefix $(obj),$(START))
++
++all: $(obj).depend $(LIB)
++
++$(LIB): $(OBJS)
++ $(AR) $(ARFLAGS) $@ $(OBJS)
++
++#########################################################################
++
++# defines $(obj).depend target
++include $(SRCTREE)/rules.mk
++
++sinclude $(obj).depend
++
++#########################################################################
+diff --git a/arch/arm/cpu/arm926ejs/aspeed/NCSI.H b/arch/arm/cpu/arm926ejs/aspeed/NCSI.H
+new file mode 100644
+index 0000000..a0e448b
+--- /dev/null
++++ b/arch/arm/cpu/arm926ejs/aspeed/NCSI.H
+@@ -0,0 +1,189 @@
++/*
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++ */
++#ifndef NCSI_H
++#define NCSI_H
++
++#include "TYPEDEF.H"
++
++//---------------------------------------------------------
++// Define
++//---------------------------------------------------------
++#define MAX_PACKAGE_NUM 8 // 1 ~ 8
++#define MAX_CHANNEL_NUM 4 // 1 ~ 32
++//#define Enable_NCSI_LOOP_INFINI //[off]
++
++//---------------------------------------------------------
++// Function
++//---------------------------------------------------------
++#define SENT_RETRY_COUNT 1
++#define NCSI_RxDESNum 50
++
++//#define NCSI_Skip_Phase1_DeSelectPackage
++//#define NCSI_Skip_DeSelectPackage
++//#define NCSI_Skip_DiSChannel
++//#define NCSI_EnableDelay_DeSelectPackage
++//#define NCSI_EnableDelay_GetLinkStatus
++//#define NCSI_EnableDelay_EachPackage
++//#define Print_Version_ID
++//#define Print_PackageName
++
++//---------------------------------------------------------
++// PCI DID/VID & Manufacturer ID
++//---------------------------------------------------------
++#define ManufacturerID_Intel 0x00000157 //343
++#define ManufacturerID_Broadcom 0x0000113d //4413
++#define ManufacturerID_Mellanox 0x000002c9 //713
++
++//PCI VID: [163c]intel
++//PCI VID: [8086]Intel Corporation
++//PCI VID: [8087]Intel
++//PCI VID: [14e4]Broadcom Corporation
++//PCI VID: [15b3]Mellanox
++#define PCI_DID_VID_Intel_82574L 0x10d38086 // IntelR 82574L Gigabit Ethernet Controller
++#define PCI_DID_VID_Intel_82575_10d6 0x10d68086 // 82566 DM-2-gigabyte
++#define PCI_DID_VID_Intel_82575_10a7 0x10a78086 // 82575EB Gigabit Network Connection
++#define PCI_DID_VID_Intel_82575_10a9 0x10a98086 // 82575EB Gigabit Network Connection
++#define PCI_DID_VID_Intel_82576_10c9 0x10c98086 //*82576 Gigabit ET Dual Port Server Adapter
++#define PCI_DID_VID_Intel_82576_10e6 0x10e68086 // 82576 Gigabit Network Connection
++#define PCI_DID_VID_Intel_82576_10e7 0x10e78086 // 82576 Gigabit Network Connection
++#define PCI_DID_VID_Intel_82576_10e8 0x10e88086 // E64750-xxx Intel Gigabit ET Quad Port Server Adapter
++#define PCI_DID_VID_Intel_82576_1518 0x15188086 // 82576NS SerDes Gigabit Network Connectio
++#define PCI_DID_VID_Intel_82576_1526 0x15268086 // Intel Gigabit ET2 Quad Port Server Adapter
++#define PCI_DID_VID_Intel_82576_150a 0x150a8086 // 82576NS Gigabit Ethernet Controller
++#define PCI_DID_VID_Intel_82576_150d 0x150d8086 // 82576 Gigabit Backplane Connection
++#define PCI_DID_VID_Intel_82599_10fb 0x10fb8086 // 10 Gb Ethernet controller
++#define PCI_DID_VID_Intel_82599_1557 0x15578086 //
++#define PCI_DID_VID_Intel_I350_1521 0x15218086 //
++#define PCI_DID_VID_Intel_I350_1523 0x15238086 //
++#define PCI_DID_VID_Intel_I210 0x15338086 //
++#define PCI_DID_VID_Intel_X540 0x15288086 //
++#define PCI_DID_VID_Broadcom_BCM5718 0x165614e4 //
++#define PCI_DID_VID_Broadcom_BCM5720 0x165f14e4 //
++#define PCI_DID_VID_Broadcom_BCM5725 0x164314e4 //
++#define PCI_DID_VID_Mellanox_ConnectX_3 0x100315b3 //*
++
++//---------------------------------------------------------
++// Delay (ms)
++//---------------------------------------------------------
++#define Delay_EachPackage 1000
++#define Delay_DeSelectPackage 50
++#define Delay_GetLinkStatus 50
++
++//---------------------------------------------------------
++// NCSI Parameter
++//---------------------------------------------------------
++//Command and Response Type
++#define CLEAR_INITIAL_STATE 0x00 //M
++#define SELECT_PACKAGE 0x01 //M
++#define DESELECT_PACKAGE 0x02 //M
++#define ENABLE_CHANNEL 0x03 //M
++#define DISABLE_CHANNEL 0x04 //M
++#define RESET_CHANNEL 0x05 //M
++#define ENABLE_CHANNEL_NETWORK_TX 0x06 //M
++#define DISABLE_CHANNEL_NETWORK_TX 0x07 //M
++#define AEN_ENABLE 0x08
++#define SET_LINK 0x09 //M
++#define GET_LINK_STATUS 0x0A //M
++#define SET_VLAN_FILTER 0x0B //M
++#define ENABLE_VLAN 0x0C //M
++#define DISABLE_VLAN 0x0D //M
++#define SET_MAC_ADDRESS 0x0E //M
++#define ENABLE_BROADCAST_FILTERING 0x10 //M
++#define DISABLE_BROADCAST_FILTERING 0x11 //M
++#define ENABLE_GLOBAL_MULTICAST_FILTERING 0x12
++#define DISABLE_GLOBAL_MULTICAST_FILTERING 0x13
++#define SET_NCSI_FLOW_CONTROL 0x14
++#define GET_VERSION_ID 0x15 //M
++#define GET_CAPABILITIES 0x16 //M
++#define GET_PARAMETERS 0x17 //M
++#define GET_CONTROLLER_PACKET_STATISTICS 0x18
++#define GET_NCSI_STATISTICS 0x19
++#define GET_NCSI_PASS_THROUGH_STATISTICS 0x1A
++
++//Standard Response Code
++#define COMMAND_COMPLETED 0x00
++#define COMMAND_FAILED 0x01
++#define COMMAND_UNAVAILABLE 0x02
++#define COMMAND_UNSUPPORTED 0x03
++
++//Standard Reason Code
++#define NO_ERROR 0x0000
++#define INTERFACE_INITIALIZATION_REQUIRED 0x0001
++#define PARAMETER_IS_INVALID 0x0002
++#define CHANNEL_NOT_READY 0x0003
++#define PACKAGE_NOT_READY 0x0004
++#define INVALID_PAYLOAD_LENGTH 0x0005
++#define UNKNOWN_COMMAND_TYPE 0x7FFF
++
++//SET_MAC_ADDRESS
++#define UNICAST ( 0x00 << 5 )
++#define MULTICAST ( 0x01 << 5 )
++#define DISABLE_MAC_ADDRESS_FILTER 0x00
++#define ENABLE_MAC_ADDRESS_FILTER 0x01
++
++//GET_LINK_STATUS
++#define LINK_DOWN 0
++#define LINK_UP 1
++
++#define NCSI_RxDMA_PakSize 2048
++#define NCSI_RxDMA_BASE (DMA_BASE+0x00100000)
++
++//---------------------------------------------------------
++// Variable
++//---------------------------------------------------------
++//NC-SI Command Packet
++typedef struct {
++//Ethernet Header
++ unsigned char DA[6]; // Destination Address
++ unsigned char SA[6]; // Source Address
++ unsigned short EtherType; // DMTF NC-SI, it should be 0x88F8
++//NC-SI Control Packet
++ unsigned char MC_ID; // Management Controller should set this field to 0x00
++ unsigned char Header_Revision; // For NC-SI 1.0 spec, this field has to set 0x01
++ unsigned char Reserved_1; // Reserved has to set to 0x00
++ unsigned char IID; // Instance ID
++ unsigned char Command;
++ unsigned char Channel_ID;
++ unsigned short Payload_Length; // Payload Length = 12 bits, 4 bits are reserved
++ unsigned long Reserved_2;
++ unsigned long Reserved_3;
++
++ unsigned short Reserved_4;
++ unsigned short Reserved_5;
++ unsigned short Response_Code;
++ unsigned short Reason_Code;
++ unsigned char Payload_Data[64];
++} NCSI_Command_Packet;
++
++//NC-SI Response Packet
++typedef struct {
++ unsigned char DA[6];
++ unsigned char SA[6];
++ unsigned short EtherType; //DMTF NC-SI
++//NC-SI Control Packet
++ unsigned char MC_ID; //Management Controller should set this field to 0x00
++ unsigned char Header_Revision; //For NC-SI 1.0 spec, this field has to set 0x01
++ unsigned char Reserved_1; //Reserved has to set to 0x00
++ unsigned char IID; //Instance ID
++ unsigned char Command;
++ unsigned char Channel_ID;
++ unsigned short Payload_Length; //Payload Length = 12 bits, 4 bits are reserved
++ unsigned short Reserved_2;
++ unsigned short Reserved_3;
++ unsigned short Reserved_4;
++ unsigned short Reserved_5;
++
++ unsigned short Response_Code;
++ unsigned short Reason_Code;
++ unsigned char Payload_Data[64];
++} NCSI_Response_Packet;
++
++#endif // NCSI_H
+diff --git a/arch/arm/cpu/arm926ejs/aspeed/NCSI.c b/arch/arm/cpu/arm926ejs/aspeed/NCSI.c
+new file mode 100644
+index 0000000..7de06c3
+--- /dev/null
++++ b/arch/arm/cpu/arm926ejs/aspeed/NCSI.c
+@@ -0,0 +1,934 @@
++/*
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++ */
++#define NCSI_C
++static const char ThisFile[] = "NCSI.c";
++
++#include "SWFUNC.H"
++
++#ifdef SLT_UBOOT
++ #include <common.h>
++ #include <command.h>
++ #include <COMMINF.H>
++ #include <NCSI.H>
++ #include <IO.H>
++#endif
++#ifdef SLT_DOS
++ #include <stdio.h>
++ #include <stdlib.h>
++ #include <conio.h>
++ #include <string.h>
++ #include "COMMINF.H"
++ #include "NCSI.H"
++ #include "IO.H"
++#endif
++
++NCSI_Command_Packet NCSI_Request_SLT;
++NCSI_Response_Packet NCSI_Respond_SLT;
++int InstanceID;
++int NCSI_RxTimeOutScale;
++ULONG NCSI_RxDesBase;
++ULONG NCSI_TxDWBUF[512];
++ULONG NCSI_RxDWBUF[512];
++char NCSI_CommandStr[512];
++unsigned char *NCSI_TxByteBUF;
++unsigned char *NCSI_RxByteBUF;
++unsigned char NCSI_Payload_Data[16];
++unsigned long Payload_Checksum_NCSI = 0x00000000;
++ULONG select_flag[MAX_PACKAGE_NUM];
++
++ULONG DWSwap_SLT (ULONG in) {
++ return( ((in & 0xff000000) >> 24)
++ | ((in & 0x00ff0000) >> 8)
++ | ((in & 0x0000ff00) << 8)
++ | ((in & 0x000000ff) << 24)
++ );
++}
++USHORT WDSwap_SLT (USHORT in) {
++ return( ((in & 0xff00) >> 8)
++ | ((in & 0x00ff) << 8)
++ );
++}
++
++//------------------------------------------------------------
++int FindErr_NCSI (int value) {
++ NCSI_LinkFail_Val = NCSI_LinkFail_Val | value;
++ Err_Flag = Err_Flag | Err_NCSI_LinkFail;
++ if ( DbgPrn_ErrFlg )
++ printf ("\nErr_Flag: [%08lx] NCSI_LinkFail_Val: [%08lx]\n", Err_Flag, NCSI_LinkFail_Val);
++
++ return(1);
++}
++
++//------------------------------------------------------------
++// PHY IC(NC-SI)
++//------------------------------------------------------------
++void ncsi_respdump ( NCSI_Response_Packet *in ) {
++ printf ("DA : %02x %02x %02x %02x %02x %02x\n", in->DA[5], in->DA[4], in->DA[3], in->DA[2], in->DA[1], in->DA[0]);
++ printf ("SA : %02x %02x %02x %02x %02x %02x\n", in->SA[5], in->SA[4], in->SA[3], in->SA[2], in->SA[1], in->SA[0]);
++ printf ("EtherType : %04x\n", in->EtherType );//DMTF NC-SI
++ printf ("MC_ID : %02x\n", in->MC_ID );//Management Controller should set this field to 0x00
++ printf ("Header_Revision: %02x\n", in->Header_Revision );//For NC-SI 1.0 spec, this field has to set 0x01
++// printf ("Reserved_1 : %02x\n", in->Reserved_1 ); //Reserved has to set to 0x00
++ printf ("IID : %02x\n", in->IID );//Instance ID
++ printf ("Command : %02x\n", in->Command );
++ printf ("Channel_ID : %02x\n", in->Channel_ID );
++ printf ("Payload_Length : %04x\n", in->Payload_Length );//Payload Length = 12 bits, 4 bits are reserved
++// printf ("Reserved_2 : %04x\n", in->Reserved_2 );
++// printf ("Reserved_3 : %04x\n", in->Reserved_3 );
++// printf ("Reserved_4 : %04x\n", in->Reserved_4 );
++// printf ("Reserved_5 : %04x\n", in->Reserved_5 );
++ printf ("Response_Code : %04x\n", in->Response_Code );
++ printf ("Reason_Code : %04x\n", in->Reason_Code );
++ printf ("Payload_Data : %02x%02x%02x%02x\n", in->Payload_Data[ 3], in->Payload_Data[ 2], in->Payload_Data[ 1], in->Payload_Data[ 0]);
++// printf ("Payload_Data : %02x%02x%02x%02x\n", in->Payload_Data[ 7], in->Payload_Data[ 6], in->Payload_Data[ 5], in->Payload_Data[ 4]);
++// printf ("Payload_Data : %02x%02x%02x%02x\n", in->Payload_Data[11], in->Payload_Data[10], in->Payload_Data[ 9], in->Payload_Data[ 8]);
++// printf ("Payload_Data : %02x%02x%02x%02x\n", in->Payload_Data[15], in->Payload_Data[14], in->Payload_Data[13], in->Payload_Data[12]);
++// printf ("Payload_Data : %02x%02x%02x%02x\n", in->Payload_Data[19], in->Payload_Data[18], in->Payload_Data[17], in->Payload_Data[16]);
++// printf ("Payload_Data : %02x%02x%02x%02x\n", in->Payload_Data[23], in->Payload_Data[22], in->Payload_Data[21], in->Payload_Data[20]);
++}
++
++//------------------------------------------------------------
++void NCSI_Struct_Initialize_SLT (void) {
++ int i;
++
++ ULONG NCSI_RxDatBase;
++
++ InstanceID = 0;
++ NCSI_RxTimeOutScale = 1;
++
++ for (i = 0; i < 6; i++) {
++ NCSI_Request_SLT.DA[i] = 0xFF;
++ }
++
++ for (i = 0; i < 6; i++) {
++// NCSI_Request.SA[i] = i<<2;
++ NCSI_Request_SLT.SA[i] = SA[i];
++ }
++
++ NCSI_Request_SLT.EtherType = WDSwap_SLT(0x88F8); // EtherType = 0x88F8 (DMTF NC-SI) page 50, table 8, NC-SI spec. version 1.0.0
++ NCSI_Request_SLT.MC_ID = 0;
++ NCSI_Request_SLT.Header_Revision = 0x01;
++ NCSI_Request_SLT.Reserved_1 = 0;
++ NCSI_Request_SLT.Reserved_2 = 0;
++ NCSI_Request_SLT.Reserved_3 = 0;
++
++ NCSI_TxByteBUF = (unsigned char *) &NCSI_TxDWBUF[0];
++ NCSI_RxByteBUF = (unsigned char *) &NCSI_RxDWBUF[0];
++
++ NCSI_RxDesBase = H_RDES_BASE;
++ NCSI_RxDatBase = NCSI_RxDMA_BASE;
++
++ for (i = 0; i < NCSI_RxDESNum - 1; i++) {
++ WriteSOC_DD( ( NCSI_RxDesBase + 0 ), 0x00000000 );
++ WriteSOC_DD( ( NCSI_RxDesBase + 4 ), 0x00000000 );
++ WriteSOC_DD( ( NCSI_RxDesBase + 8 ), 0x00000000 );
++ WriteSOC_DD( ( NCSI_RxDesBase + 0x0C ), (NCSI_RxDatBase + CPU_BUS_ADDR_SDRAM_OFFSET) ); // 20130730
++ NCSI_RxDesBase += 16;
++ NCSI_RxDatBase += NCSI_RxDMA_PakSize;
++ }
++ WriteSOC_DD( ( NCSI_RxDesBase + 0 ), EOR_IniVal );
++ WriteSOC_DD( ( NCSI_RxDesBase + 4 ), 0x00000000 );
++ WriteSOC_DD( ( NCSI_RxDesBase + 8 ), 0x00000000 );
++ WriteSOC_DD( ( NCSI_RxDesBase + 0x0C ), (NCSI_RxDatBase + CPU_BUS_ADDR_SDRAM_OFFSET) ); // 20130730
++
++ NCSI_RxDesBase = H_RDES_BASE;
++}
++
++//------------------------------------------------------------
++void Calculate_Checksum_NCSI (unsigned char *buffer_base, int Length) {
++ ULONG CheckSum = 0;
++ ULONG Data;
++ ULONG Data1;
++ int i;
++
++ // Calculate checksum is from byte 14 of ethernet Haeder and Control packet header
++ // Page 50, NC-SI spec. ver. 1.0.0 form DMTF
++ for (i = 14; i < Length; i += 2 ) {
++ Data = buffer_base[i];
++ Data1 = buffer_base[i + 1];
++ CheckSum += ((Data << 8) + Data1);
++ }
++ Payload_Checksum_NCSI = DWSwap_SLT(~(CheckSum) + 1); //2's complement
++}
++
++//------------------------------------------------------------
++// return 0: it is PASS
++// return 1: it is FAIL
++//------------------------------------------------------------
++char NCSI_Rx_SLT (unsigned char command) {
++
++#define NCSI_RX_RETRY_TIME 2
++ int timeout = 0;
++ int bytesize;
++ int dwsize;
++ int i;
++ int retry = 0;
++ char ret = 1;
++
++ ULONG NCSI_RxDatBase;
++ ULONG NCSI_RxDesDat;
++ ULONG NCSI_RxData;
++
++
++ do {
++ WriteSOC_DD( ( H_MAC_BASE + 0x1C ), 0x00000000 );//Rx Poll
++
++ do {
++ NCSI_RxDesDat = ReadSOC_DD(NCSI_RxDesBase);
++ if ( ++timeout > TIME_OUT_NCSI * NCSI_RxTimeOutScale ) {
++ #ifdef SLT_DOS
++ fprintf(fp_log, "[Cmd:%02X][NCSI-RxDesOwn] %08lX \n", command, NCSI_RxDesDat );
++ #endif
++ return( FindErr(Err_NCSI_Check_RxOwnTimeOut) );
++ }
++ } while( HWOwnRx(NCSI_RxDesDat) );
++
++ #ifdef CheckRxErr
++ if (NCSI_RxDesDat & 0x00040000) {
++ #ifdef SLT_DOS
++ fprintf(fp_log, "[RxDes] Error RxErr %08lx\n", NCSI_RxDesDat);
++ #endif
++ FindErr_Des(Check_Des_RxErr);
++ }
++ #endif
++
++ #ifdef CheckOddNibble
++ if (NCSI_RxDesDat & 0x00400000) {
++ #ifdef SLT_DOS
++ fprintf(fp_log, "[RxDes] Odd Nibble %08lx\n", NCSI_RxDesDat);
++ #endif
++ FindErr_Des(Check_Des_OddNibble);
++ }
++ #endif
++
++ #ifdef CheckCRC
++ if (NCSI_RxDesDat & 0x00080000) {
++ #ifdef SLT_DOS
++ fprintf(fp_log, "[RxDes] Error CRC %08lx\n", NCSI_RxDesDat);
++ #endif
++ FindErr_Des(Check_Des_CRC);
++ }
++ #endif
++
++ #ifdef CheckRxFIFOFull
++ if (NCSI_RxDesDat & 0x00800000) {
++ #ifdef SLT_DOS
++ fprintf(fp_log, "[RxDes] Error Rx FIFO Full %08lx\n", NCSI_RxDesDat);
++ #endif
++ FindErr_Des(Check_Des_RxFIFOFull);
++ }
++ #endif
++
++ // Get point of RX DMA buffer
++ NCSI_RxDatBase = ReadSOC_DD( NCSI_RxDesBase + 0x0C );
++ NCSI_RxData = ReadSOC_DD( NCSI_RxDatBase + 0x0C );
++
++ if ( HWEOR( NCSI_RxDesDat ) ) {
++ // it is last the descriptor in the receive Ring
++ WriteSOC_DD( NCSI_RxDesBase , EOR_IniVal );
++ NCSI_RxDesBase = H_RDES_BASE;
++ }
++ else {
++ WriteSOC_DD( NCSI_RxDesBase , 0x00000000 );
++ NCSI_RxDesBase += 16;
++ }
++
++ // Get RX valid data in offset 00h of RXDS#0
++ bytesize = (NCSI_RxDesDat & 0x3fff);
++
++ // Fill up to multiple of 4
++ if ( ( bytesize % 4 ) != 0 )
++ dwsize = ( bytesize >> 2 ) + 1;
++ else
++ dwsize = bytesize >> 2;
++
++ #ifdef SLT_DOS
++ if ( PrintNCSIEn )
++ fprintf(fp_log ,"[Rx] %d bytes(%xh)\n", bytesize, bytesize);
++ #endif
++
++ for (i = 0; i < dwsize; i++) {
++ NCSI_RxDWBUF[i] = ReadSOC_DD(NCSI_RxDatBase + ( i << 2 ));
++ if ( PrintNCSIEn ) {
++ if ( i == ( dwsize - 1 ) ) {
++ switch (bytesize % 4) {
++ case 0 : NCSI_RxDWBUF[i] = NCSI_RxDWBUF[i] & 0xffffffff; break;
++ case 3 : NCSI_RxDWBUF[i] = NCSI_RxDWBUF[i] & 0xffffff ; break;
++ case 2 : NCSI_RxDWBUF[i] = NCSI_RxDWBUF[i] & 0xffff ; break;
++ case 1 : NCSI_RxDWBUF[i] = NCSI_RxDWBUF[i] & 0xff ; break;
++ }
++ #ifdef SLT_DOS
++ switch (bytesize % 4) {
++ case 0 : fprintf(fp_log ,"[Rx%02d]%08lx %08lx\n", i, NCSI_RxDWBUF[i], DWSwap_SLT(NCSI_RxDWBUF[i]) ); break;
++ case 3 : fprintf(fp_log ,"[Rx%02d]--%06lx %06lx--\n", i, NCSI_RxDWBUF[i], DWSwap_SLT(NCSI_RxDWBUF[i]) >> 8 ); break;
++ case 2 : fprintf(fp_log ,"[Rx%02d]----%04lx %04lx----\n", i, NCSI_RxDWBUF[i], DWSwap_SLT(NCSI_RxDWBUF[i]) >> 16 ); break;
++ case 1 : fprintf(fp_log ,"[Rx%02d]------%02lx %02lx------\n", i, NCSI_RxDWBUF[i], DWSwap_SLT(NCSI_RxDWBUF[i]) >> 24 ); break;
++ default : fprintf(fp_log ,"[Rx%02d]error", i); break;
++ }
++ #endif
++ }
++ else {
++ #ifdef SLT_DOS
++ fprintf(fp_log ,"[Rx%02d]%08lx %08lx\n", i, NCSI_RxDWBUF[i], DWSwap_SLT(NCSI_RxDWBUF[i]));
++ #endif
++ }
++ }
++ } // End for (i = 0; i < dwsize; i++)
++
++ // EtherType field of the response packet should be 0x88F8
++ if ((NCSI_RxData & 0xffff) == 0xf888) {
++ memcpy (&NCSI_Respond_SLT, NCSI_RxByteBUF, bytesize);
++
++ #ifdef SLT_DOS
++ if ( PrintNCSIEn )
++ fprintf(fp_log ,"[Rx IID:%2d]\n", NCSI_Respond_SLT.IID);
++ #endif
++
++ NCSI_Respond_SLT.EtherType = WDSwap_SLT( NCSI_Respond_SLT.EtherType );
++ NCSI_Respond_SLT.Payload_Length = WDSwap_SLT( NCSI_Respond_SLT.Payload_Length );
++ NCSI_Respond_SLT.Response_Code = WDSwap_SLT( NCSI_Respond_SLT.Response_Code );
++ NCSI_Respond_SLT.Reason_Code = WDSwap_SLT( NCSI_Respond_SLT.Reason_Code );
++
++ ret = 0;
++ break;
++ }
++ else {
++ #ifdef SLT_DOS
++ if ( PrintNCSIEn )
++ fprintf(fp_log, "[Skip] Not NCSI Response: %08lx\n", NCSI_RxData);
++ #endif
++
++ retry++;
++ }
++ } while ( retry < NCSI_RX_RETRY_TIME );
++
++ return( ret );
++} // End char NCSI_Rx_SLT (void)
++
++//------------------------------------------------------------
++char NCSI_Tx (void) {
++ int bytesize;
++ int dwsize;
++ int i;
++ int timeout = 0;
++ ULONG NCSI_TxDesDat;
++
++ // Header of NC-SI command format is 34 bytes. page 58, NC-SI spec. ver 1.0.0 from DMTF
++ // The minimum size of a NC-SI package is 64 bytes.
++ bytesize = 34 + WDSwap_SLT(NCSI_Request_SLT.Payload_Length);
++ if ( bytesize < 64 ) {
++ memset (NCSI_TxByteBUF + bytesize, 0, 60 - bytesize);
++ bytesize = 64;
++ }
++
++ // Fill up to multiple of 4
++// dwsize = (bytesize + 3) >> 2;
++ if ( ( bytesize % 4 ) != 0 )
++ dwsize = ( bytesize >> 2 ) + 1;
++ else
++ dwsize = bytesize >> 2;
++
++ #ifdef SLT_DOS
++ if ( PrintNCSIEn )
++ fprintf(fp_log ,"[Tx IID:%2d] %d bytes(%xh)\n", NCSI_Request_SLT.IID, bytesize, bytesize);
++ #endif
++
++ // Copy data to DMA buffer
++ for (i = 0; i < dwsize; i++) {
++ WriteSOC_DD( DMA_BASE + (i << 2), NCSI_TxDWBUF[i] );
++ if ( PrintNCSIEn ) {
++ if (i == (dwsize - 1)) {
++ switch (bytesize % 4) {
++ case 0 : NCSI_TxDWBUF[i] = NCSI_TxDWBUF[i] & 0xffffffff; break;
++ case 3 : NCSI_TxDWBUF[i] = NCSI_TxDWBUF[i] & 0x00ffffff; break;
++ case 2 : NCSI_TxDWBUF[i] = NCSI_TxDWBUF[i] & 0x0000ffff; break;
++ case 1 : NCSI_TxDWBUF[i] = NCSI_TxDWBUF[i] & 0x000000ff; break;
++ }
++ #ifdef SLT_DOS
++ switch (bytesize % 4) {
++ case 0 : fprintf(fp_log ,"[Tx%02d]%08x %08x\n", i, NCSI_TxDWBUF[i], DWSwap_SLT( NCSI_TxDWBUF[i]) ); break;
++ case 3 : fprintf(fp_log ,"[Tx%02d]--%06x %06x--\n", i, NCSI_TxDWBUF[i], DWSwap_SLT( NCSI_TxDWBUF[i]) >> 8 ); break;
++ case 2 : fprintf(fp_log ,"[Tx%02d]----%04x %04x----\n", i, NCSI_TxDWBUF[i], DWSwap_SLT( NCSI_TxDWBUF[i]) >> 16 ); break;
++ case 1 : fprintf(fp_log ,"[Tx%02d]------%02x %02x------\n", i, NCSI_TxDWBUF[i], DWSwap_SLT( NCSI_TxDWBUF[i]) >> 24 ); break;
++ default : fprintf(fp_log ,"[Tx%02d]error", i); break;
++ }
++ #endif
++ }
++ else {
++ #ifdef SLT_DOS
++ fprintf( fp_log , "[Tx%02d]%08x %08x\n", i, NCSI_TxDWBUF[i], DWSwap_SLT(NCSI_TxDWBUF[i]) );
++ #endif
++ }
++ }
++ } // End for (i = 0; i < dwsize; i++)
++
++ // Setting one TX descriptor
++ WriteSOC_DD( H_TDES_BASE + 0x04, 0 );
++ WriteSOC_DD( H_TDES_BASE + 0x08, 0 );
++ WriteSOC_DD( H_TDES_BASE + 0x0C, (DMA_BASE + CPU_BUS_ADDR_SDRAM_OFFSET) ); // 20130730
++ WriteSOC_DD( H_TDES_BASE , 0xf0008000 + bytesize );
++ // Fire
++ WriteSOC_DD( H_MAC_BASE + 0x18, 0x00000000 );//Tx Poll
++
++ do {
++ NCSI_TxDesDat = ReadSOC_DD(H_TDES_BASE);
++ if ( ++timeout > TIME_OUT_NCSI ) {
++ #ifdef SLT_DOS
++ fprintf(fp_log, "[NCSI-TxDesOwn] %08lx\n", NCSI_TxDesDat);
++ #endif
++
++ return(FindErr(Err_NCSI_Check_TxOwnTimeOut));
++ }
++ } while ( HWOwnTx(NCSI_TxDesDat) );
++
++ return(0);
++} // End char NCSI_Tx (void)
++
++//------------------------------------------------------------
++char NCSI_ARP (void) {
++ int i;
++ int timeout = 0;
++ ULONG NCSI_TxDesDat;
++
++ if ( ARPNumCnt ) {
++ #ifdef SLT_DOS
++ if ( PrintNCSIEn )
++ fprintf(fp_log ,"[ARP] 60 bytes x%d\n", ARPNumCnt);
++ #endif
++
++ for (i = 0; i < 15; i++) {
++ #ifdef SLT_DOS
++ if ( PrintNCSIEn )
++ fprintf(fp_log ,"[Tx%02d] %08x %08x\n", i, ARP_data[i], DWSwap_SLT(ARP_data[i]));
++ #endif
++ WriteSOC_DD( DMA_BASE + ( i << 2 ), ARP_data[i] );
++ }
++ WriteSOC_DD( H_TDES_BASE + 0x04, 0 );
++ WriteSOC_DD( H_TDES_BASE + 0x08, 0 );
++ WriteSOC_DD( H_TDES_BASE + 0x0C, (DMA_BASE + CPU_BUS_ADDR_SDRAM_OFFSET) ); // 20130730
++ WriteSOC_DD( H_TDES_BASE , 0xf0008000 + 60 );
++
++ for (i = 0; i < ARPNumCnt; i++) {
++ WriteSOC_DD( H_TDES_BASE , 0xf0008000 + 60);
++
++ WriteSOC_DD( H_MAC_BASE + 0x18, 0x00000000 );//Tx Poll
++
++ timeout = 0;
++ do {
++ NCSI_TxDesDat = ReadSOC_DD(H_TDES_BASE);
++
++ if (++timeout > TIME_OUT_NCSI) {
++ #ifdef SLT_DOS
++ fprintf(fp_log, "[ARP-TxDesOwn] %08lx\n", NCSI_TxDesDat);
++ #endif
++
++ return(FindErr(Err_NCSI_Check_ARPOwnTimeOut));
++ }
++ } while (HWOwnTx(NCSI_TxDesDat));
++ }
++ }
++ return(0);
++} // End char NCSI_ARP (void)
++
++//------------------------------------------------------------
++void WrRequest (unsigned char command, unsigned char id, unsigned short length) {
++
++ NCSI_Request_SLT.IID = InstanceID;
++ NCSI_Request_SLT.Command = command;
++ NCSI_Request_SLT.Channel_ID = id;
++ NCSI_Request_SLT.Payload_Length = WDSwap_SLT(length);
++
++ memcpy ( NCSI_TxByteBUF , &NCSI_Request_SLT , 30 );
++ memcpy ((NCSI_TxByteBUF + 30 ), &NCSI_Payload_Data , length);
++ Calculate_Checksum_NCSI(NCSI_TxByteBUF, 30 + length);
++ memcpy ((NCSI_TxByteBUF + 30 + length), &Payload_Checksum_NCSI, 4 );
++}
++
++//------------------------------------------------------------
++void NCSI_PrintCommandStr (unsigned char command, unsigned iid) {
++ switch (command & 0x80) {
++ case 0x80 : sprintf(NCSI_CommandStr, "IID:%3d [%02x][Respond]", iid, command); break;
++ default : sprintf(NCSI_CommandStr, "IID:%3d [%02x][Request]", iid, command); break;
++ }
++ switch (command & 0x7f) {
++ case 0x00 : sprintf(NCSI_CommandStr, "%s[CLEAR_INITIAL_STATE ]", NCSI_CommandStr); break;
++ case 0x01 : sprintf(NCSI_CommandStr, "%s[SELECT_PACKAGE ]", NCSI_CommandStr); break;
++ case 0x02 : sprintf(NCSI_CommandStr, "%s[DESELECT_PACKAGE ]", NCSI_CommandStr); break;
++ case 0x03 : sprintf(NCSI_CommandStr, "%s[ENABLE_CHANNEL ]", NCSI_CommandStr); break;
++ case 0x04 : sprintf(NCSI_CommandStr, "%s[DISABLE_CHANNEL ]", NCSI_CommandStr); break;
++ case 0x05 : sprintf(NCSI_CommandStr, "%s[RESET_CHANNEL ]", NCSI_CommandStr); break;
++ case 0x06 : sprintf(NCSI_CommandStr, "%s[ENABLE_CHANNEL_NETWORK_TX ]", NCSI_CommandStr); break;
++ case 0x07 : sprintf(NCSI_CommandStr, "%s[DISABLE_CHANNEL_NETWORK_TX ]", NCSI_CommandStr); break;
++ case 0x08 : sprintf(NCSI_CommandStr, "%s[AEN_ENABLE ]", NCSI_CommandStr); break;
++ case 0x09 : sprintf(NCSI_CommandStr, "%s[SET_LINK ]", NCSI_CommandStr); break;
++ case 0x0A : sprintf(NCSI_CommandStr, "%s[GET_LINK_STATUS ]", NCSI_CommandStr); break;
++ case 0x0B : sprintf(NCSI_CommandStr, "%s[SET_VLAN_FILTER ]", NCSI_CommandStr); break;
++ case 0x0C : sprintf(NCSI_CommandStr, "%s[ENABLE_VLAN ]", NCSI_CommandStr); break;
++ case 0x0D : sprintf(NCSI_CommandStr, "%s[DISABLE_VLAN ]", NCSI_CommandStr); break;
++ case 0x0E : sprintf(NCSI_CommandStr, "%s[SET_MAC_ADDRESS ]", NCSI_CommandStr); break;
++ case 0x10 : sprintf(NCSI_CommandStr, "%s[ENABLE_BROADCAST_FILTERING ]", NCSI_CommandStr); break;
++ case 0x11 : sprintf(NCSI_CommandStr, "%s[DISABLE_BROADCAST_FILTERING ]", NCSI_CommandStr); break;
++ case 0x12 : sprintf(NCSI_CommandStr, "%s[ENABLE_GLOBAL_MULTICAST_FILTERING ]", NCSI_CommandStr); break;
++ case 0x13 : sprintf(NCSI_CommandStr, "%s[DISABLE_GLOBAL_MULTICAST_FILTERING ]", NCSI_CommandStr); break;
++ case 0x14 : sprintf(NCSI_CommandStr, "%s[SET_NCSI_FLOW_CONTROL ]", NCSI_CommandStr); break;
++ case 0x15 : sprintf(NCSI_CommandStr, "%s[GET_VERSION_ID ]", NCSI_CommandStr); break;
++ case 0x16 : sprintf(NCSI_CommandStr, "%s[GET_CAPABILITIES ]", NCSI_CommandStr); break;
++ case 0x17 : sprintf(NCSI_CommandStr, "%s[GET_PARAMETERS ]", NCSI_CommandStr); break;
++ case 0x18 : sprintf(NCSI_CommandStr, "%s[GET_CONTROLLER_PACKET_STATISTICS ]", NCSI_CommandStr); break;
++ case 0x19 : sprintf(NCSI_CommandStr, "%s[GET_NCSI_STATISTICS ]", NCSI_CommandStr); break;
++ case 0x1A : sprintf(NCSI_CommandStr, "%s[GET_NCSI_PASS_THROUGH_STATISTICS ]", NCSI_CommandStr); break;
++ case 0x50 : sprintf(NCSI_CommandStr, "%s[OEM_COMMAND ]", NCSI_CommandStr); break;
++ default : sprintf(NCSI_CommandStr, "%s Not Support Command", NCSI_CommandStr); break ;
++ }
++} // End void NCSI_PrintCommandStr (unsigned char command, unsigned iid)
++
++//------------------------------------------------------------
++void NCSI_PrintCommandType (unsigned char command, unsigned iid) {
++ NCSI_PrintCommandStr(command, iid);
++ printf ("%s\n", NCSI_CommandStr);
++}
++
++//------------------------------------------------------------
++void NCSI_PrintCommandType2File (unsigned char command, unsigned iid) {
++ NCSI_PrintCommandStr(command, iid);
++ #ifdef SLT_DOS
++ fprintf(fp_log, "%s\n", NCSI_CommandStr);
++ #endif
++}
++
++//------------------------------------------------------------
++char NCSI_SentWaitPacket (unsigned char command, unsigned char id, unsigned short length) {
++ int Retry = 0;
++ char ret;
++
++ do {
++ InstanceID++;
++ WrRequest(command, id, length);
++
++ ret = NCSI_Tx(); if ( ret != 0 )
++ {
++ // printf("======> NCSI_Tx return code = %X\n", ret );
++ return(1);
++ }
++#ifdef Print_PackageName
++ NCSI_PrintCommandType(command, InstanceID);
++#endif
++
++#ifdef NCSI_EnableDelay_EachPackage
++ delay(Delay_EachPackage);
++#endif
++ if ( NCSI_Rx_SLT( command ) )
++ return(2);
++
++ #ifdef SLT_DOS
++ if ( PrintNCSIEn )
++ fprintf(fp_log, "[Request] ETyp:%04x MC_ID:%02x HeadVer:%02x IID:%02x Comm:%02x ChlID:%02x PayLen:%04x\n", WDSwap_SLT(NCSI_Request_SLT.EtherType),
++ NCSI_Request_SLT.MC_ID,
++ NCSI_Request_SLT.Header_Revision,
++ NCSI_Request_SLT.IID,
++ NCSI_Request_SLT.Command,
++ NCSI_Request_SLT.Channel_ID,
++ WDSwap_SLT(NCSI_Request_SLT.Payload_Length) );
++ if ( PrintNCSIEn )
++ fprintf(fp_log, "[Respond] ETyp:%04x MC_ID:%02x HeadVer:%02x IID:%02x Comm:%02x ChlID:%02x PayLen:%04x ResCd:%02x ReaCd:%02x\n",
++ NCSI_Respond_SLT.EtherType,
++ NCSI_Respond_SLT.MC_ID,
++ NCSI_Respond_SLT.Header_Revision,
++ NCSI_Respond_SLT.IID,
++ NCSI_Respond_SLT.Command,
++ NCSI_Respond_SLT.Channel_ID,
++ NCSI_Respond_SLT.Payload_Length,
++ NCSI_Respond_SLT.Response_Code,
++ NCSI_Respond_SLT.Reason_Code);
++ #endif
++
++ if ( (NCSI_Respond_SLT.IID != InstanceID) ||
++ (NCSI_Respond_SLT.Command != (command | 0x80)) ||
++ (NCSI_Respond_SLT.Response_Code != COMMAND_COMPLETED) ) {
++ #ifdef SLT_DOS
++ if ( PrintNCSIEn )
++ fprintf(fp_log, "Retry: Command = %x, Response_Code = %x\n", NCSI_Request_SLT.Command, NCSI_Respond_SLT.Response_Code);
++
++ #endif
++ Retry++;
++ }
++ else {
++ if ( PrintNCSIEn )
++ NCSI_PrintCommandType2File(command, InstanceID);
++
++ return(0);
++ }
++ } while (Retry <= SENT_RETRY_COUNT);
++
++ return( 3 );
++} // End char NCSI_SentWaitPacket (unsigned char command, unsigned char id, unsigned short length)
++
++//------------------------------------------------------------
++char Clear_Initial_State_SLT (int Channel_ID) {//Command:0x00
++ return(NCSI_SentWaitPacket(CLEAR_INITIAL_STATE, (NCSI_Cap_SLT.Package_ID << 5) + Channel_ID, 0));//Internal Channel ID = 0
++}
++
++//------------------------------------------------------------
++char Select_Package_SLT (int Package_ID) {//Command:0x01
++ memset ((void *)NCSI_Payload_Data, 0, 4);
++ NCSI_Payload_Data[3] = 1; //Arbitration Disable
++
++ return(NCSI_SentWaitPacket(SELECT_PACKAGE, (Package_ID << 5) + 0x1F, 4));//Internal Channel ID = 0x1F, 0x1F means all channel
++}
++
++//------------------------------------------------------------
++void Select_Active_Package_SLT (void) {//Command:0x01
++ memset ((void *)NCSI_Payload_Data, 0, 4);
++ NCSI_Payload_Data[3] = 1; //Arbitration Disable
++
++ if (NCSI_SentWaitPacket(SELECT_PACKAGE, (NCSI_Cap_SLT.Package_ID << 5) + 0x1F, 4)) {//Internal Channel ID = 0x1F
++ FindErr_NCSI(NCSI_LinkFail_Select_Active_Package);
++ }
++}
++
++//------------------------------------------------------------
++void DeSelect_Package_SLT (int Package_ID) {//Command:0x02
++ NCSI_SentWaitPacket(DESELECT_PACKAGE, (Package_ID << 5) + 0x1F, 0);//Internal Channel ID = 0x1F, 0x1F means all channel
++
++#ifdef NCSI_EnableDelay_DeSelectPackage
++ delay(Delay_DeSelectPackage);
++#endif
++}
++
++//------------------------------------------------------------
++void Enable_Channel_SLT (void) {//Command:0x03
++ if ( NCSI_SentWaitPacket(ENABLE_CHANNEL, (NCSI_Cap_SLT.Package_ID << 5) + NCSI_Cap_SLT.Channel_ID, 0) ) {
++ FindErr_NCSI(NCSI_LinkFail_Enable_Channel);
++ }
++}
++
++//------------------------------------------------------------
++void Disable_Channel_SLT (void) {//Command:0x04
++ memset ((void *)NCSI_Payload_Data, 0, 4);
++ NCSI_Payload_Data[3] = 0x1; //ALD
++
++ if (NCSI_SentWaitPacket(DISABLE_CHANNEL, (NCSI_Cap_SLT.Package_ID << 5) + NCSI_Cap_SLT.Channel_ID, 4)) {
++ FindErr_NCSI(NCSI_LinkFail_Disable_Channel);
++ }
++}
++void Enable_Network_TX_SLT (void) {//Command:0x06
++ if ( NCSI_SentWaitPacket(ENABLE_CHANNEL_NETWORK_TX, (NCSI_Cap_SLT.Package_ID << 5) + NCSI_Cap_SLT.Channel_ID, 0) ) {
++ FindErr_NCSI(NCSI_LinkFail_Enable_Network_TX);
++ }
++}
++
++//------------------------------------------------------------
++void Disable_Network_TX_SLT (void) {//Command:0x07
++ if ( NCSI_SentWaitPacket(DISABLE_CHANNEL_NETWORK_TX, (NCSI_Cap_SLT.Package_ID << 5) + NCSI_Cap_SLT.Channel_ID, 0) ) {
++ FindErr_NCSI(NCSI_LinkFail_Disable_Network_TX);
++ }
++}
++
++//------------------------------------------------------------
++void Set_Link_SLT (void) {//Command:0x09
++ memset ((void *)NCSI_Payload_Data, 0, 8);
++ NCSI_Payload_Data[2] = 0x02; //full duplex
++// NCSI_Payload_Data[3] = 0x04; //100M, auto-disable
++ NCSI_Payload_Data[3] = 0x05; //100M, auto-enable
++
++ NCSI_SentWaitPacket(SET_LINK, (NCSI_Cap_SLT.Package_ID << 5) + NCSI_Cap_SLT.Channel_ID, 8);
++}
++
++//------------------------------------------------------------
++char Get_Link_Status_SLT (void) {//Command:0x0a
++
++ if (NCSI_SentWaitPacket(GET_LINK_STATUS, (NCSI_Cap_SLT.Package_ID << 5) + NCSI_Cap_SLT.Channel_ID, 0)) {
++ return(0);
++ }
++ else {
++ if (NCSI_Respond_SLT.Payload_Data[3] & 0x20) {
++ if (NCSI_Respond_SLT.Payload_Data[3] & 0x40) {
++ if (NCSI_Respond_SLT.Payload_Data[3] & 0x01)
++ return(1); //Link Up or Not
++ else
++ return(0);
++ } else
++ return(0); //Auto Negotiate did not finish
++ } else {
++ if (NCSI_Respond_SLT.Payload_Data[3] & 0x01)
++ return(1); //Link Up or Not
++ else
++ return(0);
++ }
++ }
++} // End char Get_Link_Status_SLT (void)
++
++//------------------------------------------------------------
++void Enable_Set_MAC_Address_SLT (void) {//Command:0x0e
++ int i;
++
++ for ( i = 0; i < 6; i++ ) {
++ NCSI_Payload_Data[i] = NCSI_Request_SLT.SA[i];
++ }
++ NCSI_Payload_Data[6] = 1; //MAC Address Num = 1 --> address filter 1, fixed in sample code
++ NCSI_Payload_Data[7] = UNICAST + 0 + ENABLE_MAC_ADDRESS_FILTER; //AT + Reserved + E
++
++ if ( NCSI_SentWaitPacket(SET_MAC_ADDRESS, (NCSI_Cap_SLT.Package_ID << 5) + NCSI_Cap_SLT.Channel_ID, 8) ) {
++ FindErr_NCSI(NCSI_LinkFail_Enable_Set_MAC_Address);
++ }
++}
++
++//------------------------------------------------------------
++void Enable_Broadcast_Filter_SLT (void) {//Command:0x10
++ memset ((void *)NCSI_Payload_Data, 0, 4);
++ NCSI_Payload_Data[3] = 0xF; //ARP, DHCP, NetBIOS
++
++ if (NCSI_SentWaitPacket(ENABLE_BROADCAST_FILTERING, (NCSI_Cap_SLT.Package_ID << 5) + NCSI_Cap_SLT.Channel_ID, 4) ) {
++ FindErr_NCSI(NCSI_LinkFail_Enable_Broadcast_Filter);
++ }
++}
++
++//------------------------------------------------------------
++void Get_Version_ID_SLT (void) {//Command:0x15
++
++ if (NCSI_SentWaitPacket(GET_VERSION_ID, (NCSI_Cap_SLT.Package_ID << 5) + NCSI_Cap_SLT.Channel_ID, 0) ) {
++ FindErr_NCSI(NCSI_LinkFail_Get_Version_ID);
++ }
++ else {
++#ifdef Print_Version_ID
++ printf ("NCSI Version : %02x %02x %02x %02x\n", NCSI_Respond_SLT.Payload_Data[ 0], NCSI_Respond_SLT.Payload_Data[ 1], NCSI_Respond_SLT.Payload_Data[ 2], NCSI_Respond_SLT.Payload_Data[ 3]);
++ printf ("NCSI Version : %02x %02x %02x %02x\n", NCSI_Respond_SLT.Payload_Data[ 4], NCSI_Respond_SLT.Payload_Data[ 5], NCSI_Respond_SLT.Payload_Data[ 6], NCSI_Respond_SLT.Payload_Data[ 7]);
++ printf ("Firmware Name String: %02x %02x %02x %02x\n", NCSI_Respond_SLT.Payload_Data[ 8], NCSI_Respond_SLT.Payload_Data[ 9], NCSI_Respond_SLT.Payload_Data[10], NCSI_Respond_SLT.Payload_Data[11]);
++ printf ("Firmware Name String: %02x %02x %02x %02x\n", NCSI_Respond_SLT.Payload_Data[12], NCSI_Respond_SLT.Payload_Data[13], NCSI_Respond_SLT.Payload_Data[14], NCSI_Respond_SLT.Payload_Data[15]);
++ printf ("Firmware Name String: %02x %02x %02x %02x\n", NCSI_Respond_SLT.Payload_Data[16], NCSI_Respond_SLT.Payload_Data[17], NCSI_Respond_SLT.Payload_Data[18], NCSI_Respond_SLT.Payload_Data[19]);
++ printf ("Firmware Version : %02x %02x %02x %02x\n", NCSI_Respond_SLT.Payload_Data[20], NCSI_Respond_SLT.Payload_Data[21], NCSI_Respond_SLT.Payload_Data[22], NCSI_Respond_SLT.Payload_Data[23]);
++ printf ("PCI DID/VID : %02x %02x/%02x %02x\n", NCSI_Respond_SLT.Payload_Data[24], NCSI_Respond_SLT.Payload_Data[25], NCSI_Respond_SLT.Payload_Data[26], NCSI_Respond_SLT.Payload_Data[27]);
++ printf ("PCI SSID/SVID : %02x %02x/%02x %02x\n", NCSI_Respond_SLT.Payload_Data[28], NCSI_Respond_SLT.Payload_Data[29], NCSI_Respond_SLT.Payload_Data[30], NCSI_Respond_SLT.Payload_Data[31]);
++ printf ("Manufacturer ID : %02x %02x %02x %02x\n", NCSI_Respond_SLT.Payload_Data[32], NCSI_Respond_SLT.Payload_Data[33], NCSI_Respond_SLT.Payload_Data[34], NCSI_Respond_SLT.Payload_Data[35]);
++ printf ("Checksum : %02x %02x %02x %02x\n", NCSI_Respond_SLT.Payload_Data[36], NCSI_Respond_SLT.Payload_Data[37], NCSI_Respond_SLT.Payload_Data[38], NCSI_Respond_SLT.Payload_Data[39]);
++#endif
++ NCSI_Cap_SLT.PCI_DID_VID = (NCSI_Respond_SLT.Payload_Data[24]<<24)
++ | (NCSI_Respond_SLT.Payload_Data[25]<<16)
++ | (NCSI_Respond_SLT.Payload_Data[26]<< 8)
++ | (NCSI_Respond_SLT.Payload_Data[27] );
++ NCSI_Cap_SLT.ManufacturerID = (NCSI_Respond_SLT.Payload_Data[32]<<24)
++ | (NCSI_Respond_SLT.Payload_Data[33]<<16)
++ | (NCSI_Respond_SLT.Payload_Data[34]<< 8)
++ | (NCSI_Respond_SLT.Payload_Data[35] );
++ }
++} // End void Get_Version_ID_SLT (void)
++
++//------------------------------------------------------------
++void Get_Capabilities_SLT (void) {//Command:0x16
++
++ if (NCSI_SentWaitPacket(GET_CAPABILITIES, (NCSI_Cap_SLT.Package_ID << 5) + NCSI_Cap_SLT.Channel_ID, 0)) {
++ FindErr_NCSI(NCSI_LinkFail_Get_Capabilities);
++ }
++ else {
++ NCSI_Cap_SLT.Capabilities_Flags = NCSI_Respond_SLT.Payload_Data[0];
++ NCSI_Cap_SLT.Broadcast_Packet_Filter_Capabilities = NCSI_Respond_SLT.Payload_Data[1];
++ NCSI_Cap_SLT.Multicast_Packet_Filter_Capabilities = NCSI_Respond_SLT.Payload_Data[2];
++ NCSI_Cap_SLT.Buffering_Capabilities = NCSI_Respond_SLT.Payload_Data[3];
++ NCSI_Cap_SLT.AEN_Control_Support = NCSI_Respond_SLT.Payload_Data[4];
++ }
++}
++
++//------------------------------------------------------------
++void Get_Controller_Packet_Statistics (void) {//Command:0x18
++
++ NCSI_SentWaitPacket(GET_CONTROLLER_PACKET_STATISTICS, (NCSI_Cap_SLT.Package_ID << 5) + NCSI_Cap_SLT.Channel_ID, 0);
++}
++
++//------------------------------------------------------------
++char phy_ncsi (void) {
++ ULONG Channel_Found = 0;
++ ULONG Package_Found = 0;
++ ULONG Re_Send;
++ ULONG Err_Flag_bak;
++ ULONG pkg_idx;
++ ULONG chl_idx;
++ ULONG Link_Status;
++ ULONG NCSI_LinkFail_Val_bak;
++
++ number_chl = 0;
++ number_pak = 0;
++
++ NCSI_LinkFail_Val = 0;
++ #ifdef SLT_DOS
++ fprintf(fp_log, "\n\n======> Start:\n" );
++ #endif
++ NCSI_Struct_Initialize_SLT();
++
++ #ifdef NCSI_Skip_Phase1_DeSelectPackage
++ #else
++
++ //NCSI Start
++ //Disable Channel then DeSelect Package
++ for (pkg_idx = 0; pkg_idx < MAX_PACKAGE_NUM; pkg_idx++) {
++ // Ignore error flag in the NCSI command
++ Err_Flag_bak = Err_Flag;
++ NCSI_LinkFail_Val_bak = NCSI_LinkFail_Val;
++ select_flag[pkg_idx] = Select_Package_SLT (pkg_idx); // Command:0x01
++ Err_Flag = Err_Flag_bak;
++ NCSI_LinkFail_Val = NCSI_LinkFail_Val_bak;
++
++ if ( select_flag[pkg_idx] == 0 ) {
++ NCSI_Cap_SLT.Package_ID = pkg_idx;
++
++ for ( chl_idx = 0; chl_idx < MAX_CHANNEL_NUM; chl_idx++ ) {
++ NCSI_Cap_SLT.Channel_ID = chl_idx;
++ // Ignore error flag in the NCSI command
++ Err_Flag_bak = Err_Flag;
++ NCSI_LinkFail_Val_bak = NCSI_LinkFail_Val;
++ Disable_Channel_SLT(); // Command: 0x04
++ Err_Flag = Err_Flag_bak;
++ NCSI_LinkFail_Val = NCSI_LinkFail_Val_bak;
++ }
++ #ifdef NCSI_Skip_DeSelectPackage
++ #else
++ DeSelect_Package_SLT (pkg_idx); // Command:0x02
++ #endif
++ } // End if ( select_flag[pkg_idx] == 0 )
++ } // End for (pkg_idx = 0; pkg_idx < MAX_PACKAGE_NUM; pkg_idx++)
++ #endif
++
++ //Select Package
++ for (pkg_idx = 0; pkg_idx < MAX_PACKAGE_NUM; pkg_idx++) {
++ #ifdef NCSI_Skip_Phase1_DeSelectPackage
++ // Ignore error flag in the NCSI command
++ Err_Flag_bak = Err_Flag;
++ NCSI_LinkFail_Val_bak = NCSI_LinkFail_Val;
++ select_flag[pkg_idx] = Select_Package_SLT (pkg_idx);//Command:0x01
++ Err_Flag = Err_Flag_bak;
++ NCSI_LinkFail_Val = NCSI_LinkFail_Val_bak;
++ #endif
++
++ if (select_flag[pkg_idx] == 0) {
++ //NCSI_RxTimeOutScale = 1000;
++ NCSI_RxTimeOutScale = 10;
++ number_pak++;
++ Package_Found = 1;
++ NCSI_Cap_SLT.Package_ID = pkg_idx;
++
++ if ( !(IOTiming||IOTimingBund) )
++ printf ("====Find Package ID: %d\n", NCSI_Cap_SLT.Package_ID);
++ #ifdef SLT_DOS
++ fprintf(fp_log, "====Find Package ID: %d\n", NCSI_Cap_SLT.Package_ID);
++ #endif
++
++ #ifdef NCSI_Skip_Phase1_DeSelectPackage
++ #else
++ Select_Package_SLT (pkg_idx);//Command:0x01
++ #endif
++
++ // Scan all channel in the package
++ for ( chl_idx = 0; chl_idx < MAX_CHANNEL_NUM; chl_idx++ ) {
++ // backup error flag
++ Err_Flag_bak = Err_Flag;
++ NCSI_LinkFail_Val_bak = NCSI_LinkFail_Val;
++ if (Clear_Initial_State_SLT(chl_idx) == 0) { //Command:0x00
++ number_chl++;
++ Channel_Found = 1;
++ NCSI_Cap_SLT.Channel_ID = chl_idx;
++
++ if ( !(IOTiming || IOTimingBund) )
++ printf ("--------Find Channel ID: %d\n", NCSI_Cap_SLT.Channel_ID);
++
++ #ifdef SLT_DOS
++ fprintf(fp_log, "--------Find Channel ID: %d\n", NCSI_Cap_SLT.Channel_ID);
++ #endif
++ // Get Version and Capabilities
++ Get_Version_ID_SLT(); //Command:0x15
++ Get_Capabilities_SLT(); //Command:0x16
++ Select_Active_Package_SLT(); //Command:0x01
++ Enable_Set_MAC_Address_SLT(); //Command:0x0e
++ Enable_Broadcast_Filter_SLT(); //Command:0x10
++
++ // Enable TX
++ Enable_Network_TX_SLT(); //Command:0x06
++
++ // Enable Channel
++ Enable_Channel_SLT(); //Command:0x03
++
++ // Get Link Status
++ Re_Send = 0;
++ do {
++ #ifdef NCSI_EnableDelay_GetLinkStatus
++ if ( Re_Send >= 2 )
++ delay(Delay_GetLinkStatus);
++ #endif
++
++ Link_Status = Get_Link_Status_SLT();//Command:0x0a
++
++ if ( Link_Status == LINK_UP ) {
++ if (!(IOTiming||IOTimingBund))
++ printf (" This Channel is LINK_UP\n");
++
++ #ifdef SLT_DOS
++ fprintf(fp_log, " This Channel is LINK_UP\n");
++ #endif
++
++ NCSI_ARP ();
++
++ break;
++ }
++ else if ( Link_Status == LINK_DOWN ) {
++ if ( Re_Send >= 2 ) {
++ if ( !(IOTiming || IOTimingBund) )
++ printf (" This Channel is LINK_DOWN\n");
++
++ #ifdef SLT_DOS
++ fprintf(fp_log, " This Channel is LINK_DOWN\n");
++ #endif
++
++ break;
++ }
++ } // End if ( Link_Status == LINK_UP )
++ } while ( Re_Send++ <= 2 );
++
++ #ifdef NCSI_Skip_DiSChannel
++ #else
++ if ( NCSI_DiSChannel ) {
++ // Disable TX
++ Disable_Network_TX_SLT(); //Command:0x07
++ // Disable Channel
++ Disable_Channel_SLT(); //Command:0x04
++ }
++ #endif
++ }
++ else {
++ Err_Flag = Err_Flag_bak;
++ NCSI_LinkFail_Val = NCSI_LinkFail_Val_bak;
++ }
++ } // End for ( chl_idx = 0; chl_idx < MAX_CHANNEL_NUM; chl_idx++ )
++
++ #ifdef NCSI_Skip_DeSelectPackage
++ #else
++ DeSelect_Package_SLT (pkg_idx);//Command:0x02
++ #endif
++ NCSI_RxTimeOutScale = 1;
++ }
++ else {
++ if (!(IOTiming||IOTimingBund)) {
++ printf ("====Absence of Package ID: %ld\n", pkg_idx);
++ #ifdef SLT_DOS
++ fprintf(fp_log, "====Absence of Package ID: %ld\n", pkg_idx);
++ #endif
++ }
++ } // End if (select_flag[pkg_idx] == 0)
++ } // End for (pkg_idx = 0; pkg_idx < MAX_PACKAGE_NUM; pkg_idx++)
++
++ if ( !Package_Found ) FindErr( Err_NCSI_No_PHY );
++ if ( ChannelTolNum != number_chl ) FindErr( Err_NCSI_Channel_Num );
++ if ( PackageTolNum != number_pak ) FindErr( Err_NCSI_Package_Num );
++// if ( !Channel_Found) FindErr();
++
++ if ( Err_Flag )
++ return(1);
++ else
++ return(0);
++}
++
+diff --git a/arch/arm/cpu/arm926ejs/aspeed/PCI_SPI.c b/arch/arm/cpu/arm926ejs/aspeed/PCI_SPI.c
+new file mode 100644
+index 0000000..77aac47
+--- /dev/null
++++ b/arch/arm/cpu/arm926ejs/aspeed/PCI_SPI.c
+@@ -0,0 +1,83 @@
++/*
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++ */
++#define PCI_SPI_C
++static const char ThisFile[] = "PCI_SPI.c";
++
++#include "SWFUNC.H"
++
++#ifdef SLT_UBOOT
++ #include <common.h>
++ #include <command.h>
++#endif
++#ifdef SLT_DOS
++ #include <stdio.h>
++ #include <stdlib.h>
++ #include <conio.h>
++ #include <string.h>
++ #include <dos.h>
++#endif
++
++#include "DEF_SPI.H"
++#include "LIB.H"
++#include "TYPEDEF.H"
++
++#ifdef SPI_BUS
++ULONG GetPCIInfo (DEVICE_PCI_INFO *VGAPCIInfo)
++{
++ ULONG ulPCIBaseAddress, MMIOBaseAddress, LinearAddressBase, busnum, data;
++
++ ulPCIBaseAddress = FindPCIDevice (0x1A03, 0x2000, ACTIVE);
++ busnum = 0;
++ while (ulPCIBaseAddress == 0 && busnum < 256) {
++ ulPCIBaseAddress = FindPCIDevice (0x1A03, 0x2000, busnum);
++ if (ulPCIBaseAddress == 0) {
++ ulPCIBaseAddress = FindPCIDevice (0x1688, 0x2000, busnum);
++ }
++ if (ulPCIBaseAddress == 0) {
++ ulPCIBaseAddress = FindPCIDevice (0x1A03, 0x1160, busnum);
++ }
++ if (ulPCIBaseAddress == 0) {
++ ulPCIBaseAddress = FindPCIDevice (0x1A03, 0x1180, busnum);
++ }
++ busnum++;
++ }
++ printf ("ulPCIBaseAddress = %lx\n", ulPCIBaseAddress);
++ if (ulPCIBaseAddress != 0) {
++ VGAPCIInfo->ulPCIConfigurationBaseAddress = ulPCIBaseAddress;
++ VGAPCIInfo->usVendorID = ReadPCIReg(ulPCIBaseAddress, 0, 0xFFFF);
++ VGAPCIInfo->usDeviceID = ReadPCIReg(ulPCIBaseAddress, 0, 0xFFFF0000) >> 16;
++ LinearAddressBase = ReadPCIReg (ulPCIBaseAddress, 0x10, 0xFFFFFFF0);
++ VGAPCIInfo->ulPhysicalBaseAddress = MapPhysicalToLinear (LinearAddressBase, 64 * 1024 * 1024 + 0x200000);
++ MMIOBaseAddress = ReadPCIReg (ulPCIBaseAddress, 0x14, 0xFFFF0000);
++ VGAPCIInfo->ulMMIOBaseAddress = MapPhysicalToLinear (MMIOBaseAddress, 64 * 1024 * 1024);
++ VGAPCIInfo->usRelocateIO = ReadPCIReg (ulPCIBaseAddress, 0x18, 0x0000FF80);
++ OUTDWPORT(0xcf8, ulPCIBaseAddress + 0x4);
++ data = INDWPORT(0xcfc);
++ OUTDWPORT(0xcfc, data | 0x3);
++ return TRUE;
++ }
++ else {
++ return FALSE;
++ }
++} // End ULONG GetPCIInfo (DEVICE_PCI_INFO *VGAPCIInfo)
++
++BOOLEAN GetDevicePCIInfo (VIDEO_ENGINE_INFO *VideoEngineInfo)
++{
++ if (GetPCIInfo (&VideoEngineInfo->VGAPCIInfo) == TRUE) {
++ return TRUE;
++ }
++ else {
++ printf("Can not find PCI device!\n");
++ exit(0);
++ return FALSE;
++ }
++} // End
++#endif // End ifdef SPI_BUS
+diff --git a/arch/arm/cpu/arm926ejs/aspeed/PHY.H b/arch/arm/cpu/arm926ejs/aspeed/PHY.H
+new file mode 100644
+index 0000000..81d9470
+--- /dev/null
++++ b/arch/arm/cpu/arm926ejs/aspeed/PHY.H
+@@ -0,0 +1,56 @@
++/*
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++ */
++#ifndef PHY_H
++#define PHY_H
++
++//
++// Define
++//
++#define Enable_SearchPHYID //[ON] (Search vlid PHY ID)
++#define Enable_CheckZeroPHYID //[ON] (Check PHY ID with value 0)
++
++#ifdef Enable_CheckZeroPHYID
++ #define PHY_IS_VALID( dat ) ( ( (dat & 0xffff) != 0xffff ) && ( ( dat & 0xffff ) != 0x0 ) )
++#else
++ #define PHY_IS_VALID( dat ) ( ( dat & 0xffff) != 0xffff )
++#endif
++
++// Define PHY basic register
++#define PHY_REG_BMCR 0x00 // Basic Mode Control Register
++#define PHY_REG_BMSR 0x01 // Basic Mode Status Register
++#define PHY_REG_ID_1 0x02
++#define PHY_REG_ID_2 0x03
++#define PHY_ANER 0x06 // Auto-negotiation Expansion Register
++#define PHY_GBCR 0x09 // 1000Base-T Control Register
++#define PHY_SR 0x11 // PHY Specific Status Register
++#define PHY_INER 0x12 // Interrupt Enable Register
++
++#define TIME_OUT_PHY_RW 10000
++#define TIME_OUT_PHY_Rst 10000
++
++#define PHYID3_Mask 0xfc00 //0xffc0
++
++/* --- Note for SettingPHY chip ---
++void phy_xxxx (int loop_phy) {
++
++ if ( BurstEnable ) {
++ // IEEE test
++ }
++ else if (loop_phy) {
++ // Internal loop back
++ }
++ else {
++ // external loop back
++ }
++}
++----------------------------------- */
++
++#endif // PHY_H
+diff --git a/arch/arm/cpu/arm926ejs/aspeed/PHY.c b/arch/arm/cpu/arm926ejs/aspeed/PHY.c
+new file mode 100644
+index 0000000..6afed9d
+--- /dev/null
++++ b/arch/arm/cpu/arm926ejs/aspeed/PHY.c
+@@ -0,0 +1,1541 @@
++/*
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++ */
++#define PHY_C
++static const char ThisFile[] = "PHY.c";
++
++#include "SWFUNC.H"
++
++#ifdef SLT_UBOOT
++ #include <common.h>
++ #include <command.h>
++ #include <COMMINF.H>
++ #include "STDUBOOT.H"
++#endif
++#ifdef SLT_DOS
++ #include <stdio.h>
++ #include <stdlib.h>
++ #include <conio.h>
++ #include <string.h>
++ #include "COMMINF.H"
++#endif
++
++#include "PHY.H"
++#include "TYPEDEF.H"
++#include "IO.H"
++
++ULONG PHY_09h;
++ULONG PHY_18h;
++ULONG PHY_1fh;
++ULONG PHY_06hA[7];
++ULONG PHY_11h;
++ULONG PHY_12h;
++ULONG PHY_15h;
++ULONG PHY_06h;
++char PHYID[256];
++ULONG PHY_00h;
++
++//------------------------------------------------------------
++// PHY R/W basic
++//------------------------------------------------------------
++void phy_write (int adr, ULONG data) {
++ int timeout = 0;
++
++ if (AST2300_NewMDIO) {
++ WriteSOC_DD( MAC_PHYBASE + 0x60, ( data << 16 ) | MAC_PHYWr_New | (PHY_ADR<<5) | (adr & 0x1f));
++
++ while ( ReadSOC_DD( MAC_PHYBASE + 0x60 ) & MAC_PHYBusy_New ) {
++ if ( ++timeout > TIME_OUT_PHY_RW ) {
++ if (!BurstEnable)
++#ifdef SLT_DOS
++ fprintf(fp_log, "[PHY-Write] Time out: %08lx\n", ReadSOC_DD( MAC_PHYBASE + 0x60 ) );
++#endif
++ FindErr( Err_PHY_TimeOut );
++ break;
++ }
++ }
++ }
++ else {
++ WriteSOC_DD( MAC_PHYBASE + 0x64, data );
++
++ WriteSOC_DD( MAC_PHYBASE + 0x60, MDC_Thres | MAC_PHYWr | (PHY_ADR<<16) | ((adr & 0x1f) << 21));
++
++ while ( ReadSOC_DD( MAC_PHYBASE + 0x60 ) & MAC_PHYWr ) {
++ if ( ++timeout > TIME_OUT_PHY_RW ) {
++#ifdef SLT_DOS
++ if (!BurstEnable)
++ fprintf(fp_log, "[PHY-Write] Time out: %08lx\n", ReadSOC_DD( MAC_PHYBASE + 0x60 ) );
++#endif
++ FindErr( Err_PHY_TimeOut );
++ break;
++ }
++ }
++ } // End if (AST2300_NewMDIO)
++
++ if ( DbgPrn_PHYRW )
++ printf ("[Wr ]%02d: %04lx\n", adr, data);
++} // End void phy_write (int adr, ULONG data)
++
++//------------------------------------------------------------
++ULONG phy_read (int adr) {
++ int timeout = 0;
++
++ if ( AST2300_NewMDIO ) {
++ WriteSOC_DD( MAC_PHYBASE + 0x60, MAC_PHYRd_New | (PHY_ADR << 5) | ( adr & 0x1f ) );
++
++ while ( ReadSOC_DD( MAC_PHYBASE + 0x60 ) & MAC_PHYBusy_New ) {
++ if ( ++timeout > TIME_OUT_PHY_RW ) {
++ if ( !BurstEnable )
++#ifdef SLT_DOS
++ fprintf(fp_log, "[PHY-Read] Time out: %08lx\n", ReadSOC_DD( MAC_PHYBASE + 0x60 ));
++#endif
++ FindErr( Err_PHY_TimeOut );
++ break;
++ }
++ }
++
++ DELAY(Delay_PHYRd);
++ Dat_ULONG = ReadSOC_DD( MAC_PHYBASE + 0x64 ) & 0xffff;
++ }
++ else {
++ WriteSOC_DD( MAC_PHYBASE + 0x60, MDC_Thres | MAC_PHYRd | (PHY_ADR << 16) | ((adr & 0x1f) << 21) );
++
++ while ( ReadSOC_DD( MAC_PHYBASE + 0x60 ) & MAC_PHYRd ) {
++ if ( ++timeout > TIME_OUT_PHY_RW ) {
++#ifdef SLT_DOS
++ if ( !BurstEnable )
++ fprintf( fp_log, "[PHY-Read] Time out: %08lx\n", ReadSOC_DD( MAC_PHYBASE + 0x60 ) );
++#endif
++ FindErr( Err_PHY_TimeOut );
++ break;
++ }
++ }
++
++ DELAY( Delay_PHYRd );
++ Dat_ULONG = ReadSOC_DD( MAC_PHYBASE + 0x64 ) >> 16;
++ }
++
++ if ( DbgPrn_PHYRW )
++ printf ("[Rd ]%02d: %04lx\n", adr, Dat_ULONG );
++
++ return( Dat_ULONG );
++} // End ULONG phy_read (int adr)
++
++//------------------------------------------------------------
++void phy_Read_Write (int adr, ULONG clr_mask, ULONG set_mask) {
++ if ( DbgPrn_PHYRW )
++ printf ("[RW ]%02d: clr:%04lx: set:%04lx\n", adr, clr_mask, set_mask);
++ phy_write(adr, ((phy_read(adr) & (~clr_mask)) | set_mask));
++}
++
++//------------------------------------------------------------
++void phy_out ( int adr ) {
++ printf ("%02d: %04lx\n", adr, phy_read(adr));
++}
++
++//------------------------------------------------------------
++//void phy_outchg ( int adr ) {
++// ULONG PHY_valold = 0;
++// ULONG PHY_val;
++//
++// while (1) {
++// PHY_val = phy_read(adr);
++// if (PHY_valold != PHY_val) {
++// printf ("%02d: %04lx\n", adr, PHY_val);
++// PHY_valold = PHY_val;
++// }
++// }
++//}
++
++//------------------------------------------------------------
++void phy_dump (char *name) {
++ int index;
++
++ printf ("[%s][%d]----------------\n", name, PHY_ADR);
++ for (index = 0; index < 32; index++) {
++ printf ("%02d: %04lx ", index, phy_read(index));
++
++ if ((index % 8) == 7)
++ printf ("\n");
++ }
++}
++
++//------------------------------------------------------------
++void phy_id (BYTE option) {
++
++ ULONG reg_adr;
++ CHAR PHY_ADR_org;
++ FILE_VAR
++
++ GET_OBJ( option )
++
++ PHY_ADR_org = PHY_ADR;
++ for (PHY_ADR = 0; PHY_ADR < 32; PHY_ADR++) {
++
++ PRINT(OUT_OBJ "[%02d] ", PHY_ADR);
++
++ for (reg_adr = 2; reg_adr <= 3; reg_adr++)
++ PRINT(OUT_OBJ "%ld:%04lx ", reg_adr, phy_read(reg_adr));
++
++ if ((PHY_ADR % 4) == 3)
++ PRINT(OUT_OBJ "\n");
++ }
++ PHY_ADR = PHY_ADR_org;
++}
++
++
++//------------------------------------------------------------
++void phy_delay (int dt) {
++ DELAY( dt );
++}
++
++//------------------------------------------------------------
++// PHY IC
++//------------------------------------------------------------
++void phy_basic_setting (int loop_phy) {
++ phy_Read_Write(0, 0x7140, PHY_00h); //clr set
++ if ( DbgPrn_PHYRW )
++ printf ("[Set]00: %04lx\n", phy_read( PHY_REG_BMCR ));
++}
++
++//------------------------------------------------------------
++void phy_Wait_Reset_Done (void) {
++ int timeout = 0;
++
++ while ( phy_read( PHY_REG_BMCR ) & 0x8000 ) {
++ if (DbgPrn_PHYRW)
++ printf ("00: %04lx\n", phy_read( PHY_REG_BMCR ));
++
++ if (++timeout > TIME_OUT_PHY_Rst) {
++#ifdef SLT_DOS
++ if (!BurstEnable) fprintf(fp_log, "[PHY-Reset] Time out: %08lx\n", ReadSOC_DD(MAC_PHYBASE+0x60));
++#endif
++ FindErr(Err_PHY_TimeOut);
++ break;
++ }
++ }//wait Rst Done
++
++ if (DbgPrn_PHYRW) printf ("[Clr]00: %04lx\n", phy_read( PHY_REG_BMCR ));
++ DELAY(Delay_PHYRst);
++}
++
++//------------------------------------------------------------
++void phy_Reset (int loop_phy) {
++ phy_basic_setting(loop_phy);
++
++ phy_Read_Write(0, 0x0000, 0x8000 | PHY_00h);//clr set//Rst PHY
++ phy_Wait_Reset_Done();
++
++ phy_basic_setting(loop_phy);
++ DELAY(Delay_PHYRst);
++}
++
++//------------------------------------------------------------
++void recov_phy_marvell (int loop_phy) {//88E1111
++ if ( BurstEnable ) {
++ }
++ else if ( loop_phy ) {
++ }
++ else {
++ if (GSpeed_sel[0]) {
++ phy_write(9, PHY_09h);
++
++ phy_Reset(loop_phy);
++
++ phy_write(29, 0x0007);
++ phy_Read_Write(30, 0x0008, 0x0000);//clr set
++ phy_write(29, 0x0010);
++ phy_Read_Write(30, 0x0002, 0x0000);//clr set
++ phy_write(29, 0x0012);
++ phy_Read_Write(30, 0x0001, 0x0000);//clr set
++
++ phy_write(18, PHY_12h);
++ }
++ }
++}
++
++//------------------------------------------------------------
++void phy_marvell (int loop_phy) {//88E1111
++ int Retry;
++
++ if ( DbgPrn_PHYName )
++ printf ("--->(%04lx %04lx)[Marvell] %s\n", PHY_ID2, PHY_ID3, PHYName);
++
++ if ( BurstEnable ) {
++ phy_Reset(loop_phy);
++ }
++ else if ( loop_phy ) {
++ phy_Reset(loop_phy);
++ }
++ else {
++ if ( GSpeed_sel[0] ) {
++ PHY_09h = phy_read( PHY_GBCR );
++ PHY_12h = phy_read( PHY_INER );
++ phy_write ( 18, 0x0000 );
++ phy_Read_Write( 9, 0x0000, 0x1800 );//clr set
++ }
++
++ phy_Reset(loop_phy);
++
++ if (GSpeed_sel[0]) {
++ phy_write ( 29, 0x0007 );
++ phy_Read_Write( 30, 0x0000, 0x0008 );//clr set
++ phy_write ( 29, 0x0010 );
++ phy_Read_Write( 30, 0x0000, 0x0002 );//clr set
++ phy_write ( 29, 0x0012 );
++ phy_Read_Write( 30, 0x0000, 0x0001 );//clr set
++ }
++ }
++
++ Retry = 0;
++ do {
++ PHY_11h = phy_read( PHY_SR );
++ } while ( !( ( PHY_11h & 0x0400 ) | loop_phy | ( Retry++ > 20 ) ) );
++}
++
++//------------------------------------------------------------
++void recov_phy_marvell0 (int loop_phy) {//88E1310
++ if (BurstEnable) {
++ } else if (loop_phy) {
++ } else {
++ if (GSpeed_sel[0]) {
++ phy_write(22, 0x0006);
++ phy_Read_Write(16, 0x0020, 0x0000);//clr set
++ phy_write(22, 0x0000);
++ }
++ }
++}
++
++//------------------------------------------------------------
++void phy_marvell0 (int loop_phy) {//88E1310
++ int Retry;
++
++ if (DbgPrn_PHYName)
++ printf ("--->(%04lx %04lx)[Marvell] %s\n", PHY_ID2, PHY_ID3, PHYName);
++
++ phy_write( 22, 0x0002 );
++
++ PHY_15h = phy_read(21);
++ if (PHY_15h & 0x0030) {
++ printf ("\n\n[Warning] Page2, Register 21, bit 4~5 must be 0 [Reg15_2:%04lx]\n\n", PHY_15h);
++#ifdef SLT_DOS
++ if ( IOTiming )
++ fprintf (fp_io, "\n\n[Warning] Page2, Register 21, bit 4~5 must be 0 [Reg15_2:%04lx]\n\n", PHY_15h);
++ if ( !BurstEnable)
++ fprintf (fp_log, "\n\n[Warning] Page2, Register 21, bit 4~5 must be 0 [Reg15_2:%04lx]\n\n", PHY_15h);
++#endif
++// phy_Read_Write(21, 0x0030, 0x0000);//clr set//[5]Rx Dly, [4]Tx Dly
++ phy_write(21, PHY_15h & 0xffcf); // Set [5]Rx Dly, [4]Tx Dly to 0
++ }
++ phy_write(22, 0x0000);
++
++ if ( BurstEnable ) {
++ phy_Reset(loop_phy);
++ }
++ else if ( loop_phy ) {
++ phy_write( 22, 0x0002 );
++
++ if ( GSpeed_sel[0] ) {
++ phy_Read_Write( 21, 0x6040, 0x0040 );//clr set
++ }
++ else if ( GSpeed_sel[1] ) {
++ phy_Read_Write( 21, 0x6040, 0x2000 );//clr set
++ }
++ else {
++ phy_Read_Write( 21, 0x6040, 0x0000 );//clr set
++ }
++ phy_write( 22, 0x0000 );
++ phy_Reset( loop_phy );
++ }
++ else {
++ if ( GSpeed_sel[0] ) {
++ phy_write( 22, 0x0006 );
++ phy_Read_Write( 16, 0x0000, 0x0020 );//clr set
++ phy_write( 22, 0x0000 );
++ }
++
++ phy_Reset(loop_phy);
++ }
++
++ Retry = 0;
++ do {
++ PHY_11h = phy_read( PHY_SR );
++ } while (!((PHY_11h & 0x0400) | loop_phy | (Retry++ > 20)));
++}
++
++//------------------------------------------------------------
++void recov_phy_marvell1 (int loop_phy) {//88E6176
++ CHAR PHY_ADR_org;
++
++ PHY_ADR_org = PHY_ADR;
++ for ( PHY_ADR = 16; PHY_ADR <= 22; PHY_ADR++ ) {
++ if ( BurstEnable ) {
++ }
++ else {
++ phy_write(6, PHY_06hA[PHY_ADR-16]);//06h[5]P5 loopback, 06h[6]P6 loopback
++ }
++ }
++ for ( PHY_ADR = 21; PHY_ADR <= 22; PHY_ADR++ ) {
++ phy_write(1, 0x3); //01h[1:0]00 = 10 Mbps, 01 = 100 Mbps, 10 = 1000 Mbps, 11 = Speed is not forced.
++ }
++ PHY_ADR = PHY_ADR_org;
++}
++
++//------------------------------------------------------------
++void phy_marvell1 (int loop_phy) {//88E6176
++// ULONG PHY_01h;
++ CHAR PHY_ADR_org;
++
++ if (DbgPrn_PHYName)
++ printf ("--->(%04lx %04lx)[Marvell] %s\n", PHY_ID2, PHY_ID3, PHYName);
++
++ //The 88E6176 is switch with 7 Port(P0~P6) and the PHYAdr will be fixed at 0x10~0x16, and only P5/P6 can be connected to the MAC.
++ //Therefor, the 88E6176 only can run the internal loopback.
++ PHY_ADR_org = PHY_ADR;
++ for ( PHY_ADR = 16; PHY_ADR <= 20; PHY_ADR++ ) {
++ if ( BurstEnable ) {
++ }
++ else {
++ PHY_06hA[PHY_ADR-16] = phy_read( PHY_ANER );
++ phy_write(6, 0x00);//06h[5]P5 loopback, 06h[6]P6 loopback
++ }
++ }
++
++ for ( PHY_ADR = 21; PHY_ADR <= 22; PHY_ADR++ ) {
++// PHY_01h = phy_read( PHY_REG_BMSR );
++// if (GSpeed_sel[0]) phy_write(1, (PHY_01h & 0xfffc) | 0x2);//[1:0]00 = 10 Mbps, 01 = 100 Mbps, 10 = 1000 Mbps, 11 = Speed is not forced.
++// else if (GSpeed_sel[1]) phy_write(1, (PHY_01h & 0xfffc) | 0x1);//[1:0]00 = 10 Mbps, 01 = 100 Mbps, 10 = 1000 Mbps, 11 = Speed is not forced.
++// else phy_write(1, (PHY_01h & 0xfffc) );//[1:0]00 = 10 Mbps, 01 = 100 Mbps, 10 = 1000 Mbps, 11 = Speed is not forced.
++ if (GSpeed_sel[0]) phy_write(1, 0x2);//01h[1:0]00 = 10 Mbps, 01 = 100 Mbps, 10 = 1000 Mbps, 11 = Speed is not forced.
++ else if (GSpeed_sel[1]) phy_write(1, 0x1);//01h[1:0]00 = 10 Mbps, 01 = 100 Mbps, 10 = 1000 Mbps, 11 = Speed is not forced.
++ else phy_write(1, 0x0);//01h[1:0]00 = 10 Mbps, 01 = 100 Mbps, 10 = 1000 Mbps, 11 = Speed is not forced.
++
++ if (BurstEnable) {
++ }
++ else {
++ PHY_06hA[PHY_ADR-16] = phy_read( PHY_ANER );
++ if (PHY_ADR == 21) phy_write(6, 0x20);//06h[5]P5 loopback, 06h[6]P6 loopback
++ else phy_write(6, 0x40);//06h[5]P5 loopback, 06h[6]P6 loopback
++ }
++ }
++ PHY_ADR = PHY_ADR_org;
++}
++
++//------------------------------------------------------------
++void recov_phy_marvell2 (int loop_phy) {//88E1512
++ if (BurstEnable) {
++ }
++ else if (loop_phy) {
++ }
++ else {
++ if (GSpeed_sel[0]) {
++ phy_write(22, 0x0006);
++ phy_Read_Write(18, 0x0008, 0x0000);//clr set
++ phy_write(22, 0x0000);
++ }
++ }
++}
++
++//------------------------------------------------------------
++void phy_marvell2 (int loop_phy) {//88E1512
++ int Retry = 0;
++ ULONG temp_reg;
++
++ if ( DbgPrn_PHYName )
++ printf ("--->(%04lx %04lx)[Marvell] %s\n", PHY_ID2, PHY_ID3, PHYName);
++
++ phy_write(22, 0x0002);
++ PHY_15h = phy_read(21);
++
++ if ( PHY_15h & 0x0030 ) {
++ printf ("\n\n[Warning] Page2, Register 21, bit 4~5 must be 0 [Reg15h_2:%04lx]\n\n", PHY_15h);
++#ifdef SLT_DOS
++ if (IOTiming ) fprintf (fp_io, "\n\n[Warning] Page2, Register 21, bit 4~5 must be 0 [Reg15h_2:%04lx]\n\n", PHY_15h);
++ if (!BurstEnable) fprintf (fp_log, "\n\n[Warning] Page2, Register 21, bit 4~5 must be 0 [Reg15h_2:%04lx]\n\n", PHY_15h);
++#endif
++ // phy_Read_Write(21, 0x0030, 0x0000);//clr set//[5]Rx Dly, [4]Tx Dly
++// phy_write(21, PHY_15h & 0xffcf);
++ }
++ phy_write(22, 0x0000);
++
++ if ( BurstEnable ) {
++ phy_Reset(loop_phy);
++ }
++ else if (loop_phy) {
++ // Internal loopback funciton only support in copper mode
++ // switch page 18
++ phy_write(22, 0x0012);
++ // Change mode to Copper mode
++ phy_write(20, 0x8210);
++ // do software reset
++ do {
++ temp_reg = phy_read( 20 );
++ } while ( ( (temp_reg & 0x8000) == 0x8000 ) & (Retry++ < 20) );
++
++ // switch page 2
++ phy_write(22, 0x0002);
++ if (GSpeed_sel[0]) {
++ phy_Read_Write(21, 0x2040, 0x0040);//clr set
++ }
++ else if (GSpeed_sel[1]) {
++ phy_Read_Write(21, 0x2040, 0x2000);//clr set
++ }
++ else {
++ phy_Read_Write(21, 0x2040, 0x0000);//clr set
++ }
++ phy_write(22, 0x0000);
++
++ phy_Reset(loop_phy);
++ }
++ else {
++ if (GSpeed_sel[0]) {
++ phy_write(22, 0x0006);
++ phy_Read_Write(18, 0x0000, 0x0008);//clr set
++ phy_write(22, 0x0000);
++ }
++
++ phy_Reset(loop_phy);
++ }
++
++ Retry = 0;
++ do {
++ PHY_11h = phy_read( PHY_SR );
++ } while (!((PHY_11h & 0x0400) | loop_phy | (Retry++ > 20)));
++}
++
++//------------------------------------------------------------
++void phy_broadcom (int loop_phy) {//BCM5221
++ if (DbgPrn_PHYName)
++ printf ("--->(%04lx %04lx)[Broadcom] %s\n", PHY_ID2, PHY_ID3, PHYName);
++
++ phy_Reset(loop_phy);
++
++ if (IEEETesting) {
++ if (IOTimingBund_arg == 0) {
++ phy_write(25, 0x1f01);//Force MDI //Measuring from channel A
++ }
++ else {
++ phy_Read_Write(24, 0x0000, 0x4000);//clr set//Force Link
++// phy_write( 0, PHY_00h);
++// phy_write(30, 0x1000);
++ }
++ }
++}
++
++//------------------------------------------------------------
++void recov_phy_broadcom0 (int loop_phy) {//BCM54612
++
++ // Need to do it for AST2400
++ phy_write(0x1C, 0x8C00); // Disable GTXCLK Clock Delay Enable
++ phy_write(0x18, 0xF0E7); // Disable RGMII RXD to RXC Skew
++
++ if (BurstEnable) {
++ }
++ else if (loop_phy) {
++ phy_write( 0, PHY_00h);
++ }
++ else {
++ phy_write(0x00, PHY_00h);
++ phy_write(0x09, PHY_09h);
++ phy_write(0x18, PHY_18h);
++ }
++}
++
++//------------------------------------------------------------
++void phy_broadcom0 (int loop_phy) {//BCM54612
++ if ( DbgPrn_PHYName )
++ printf ("--->(%04lx %04lx)[Broadcom] %s\n", PHY_ID2, PHY_ID3, PHYName);
++
++ // Need to do it for AST2400
++ phy_write(0x1C, 0x8C00); // Disable GTXCLK Clock Delay Enable
++ phy_write(0x18, 0xF0E7); // Disable RGMII RXD to RXC Skew
++
++ // Backup org value
++ // read reg 18H, Page 103, BCM54612EB1KMLG_Spec.pdf
++ phy_write(0x18, 0x7007);
++ PHY_18h = phy_read(0x18);
++
++ PHY_00h = phy_read( PHY_REG_BMCR );
++ PHY_09h = phy_read( PHY_GBCR );
++
++ if ( BurstEnable ) {
++ phy_basic_setting(loop_phy);
++ }
++ else if (loop_phy) {
++ phy_basic_setting(loop_phy);
++
++ // Enable Internal Loopback mode
++ // Page 58, BCM54612EB1KMLG_Spec.pdf
++ phy_write(0x0, 0x5140);
++ DELAY(Delay_PHYRst);
++ /* Only 1G Test is PASS, 100M and 10M is false @20130619 */
++
++// Waiting for BCM FAE's response
++// if (GSpeed_sel[0]) {
++// // Speed 1G
++// // Enable Internal Loopback mode
++// // Page 58, BCM54612EB1KMLG_Spec.pdf
++// phy_write(0x0, 0x5140);
++// }
++// else if (GSpeed_sel[1]) {
++// // Speed 100M
++// // Enable Internal Loopback mode
++// // Page 58, BCM54612EB1KMLG_Spec.pdf
++// phy_write(0x0, 0x7100);
++// phy_write(0x1E, 0x1000);
++// }
++// else if (GSpeed_sel[2]) {
++// // Speed 10M
++// // Enable Internal Loopback mode
++// // Page 58, BCM54612EB1KMLG_Spec.pdf
++// phy_write(0x0, 0x5100);
++// phy_write(0x1E, 0x1000);
++// }
++//
++// DELAY(Delay_PHYRst);
++ }
++ else {
++
++ if (GSpeed_sel[0]) {
++ // Page 60, BCM54612EB1KMLG_Spec.pdf
++ // need to insert loopback plug
++ phy_write( 9, 0x1800);
++ phy_write( 0, 0x0140);
++ phy_write( 0x18, 0x8400); // Enable Transmit test mode
++ } else if (GSpeed_sel[1]) {
++ // Page 60, BCM54612EB1KMLG_Spec.pdf
++ // need to insert loopback plug
++ phy_write( 0, 0x2100);
++ phy_write( 0x18, 0x8400); // Enable Transmit test mode
++ } else {
++ // Page 60, BCM54612EB1KMLG_Spec.pdf
++ // need to insert loopback plug
++ phy_write( 0, 0x0100);
++ phy_write( 0x18, 0x8400); // Enable Transmit test mode
++ }
++ }
++}
++
++//------------------------------------------------------------
++void phy_realtek (int loop_phy) {//RTL8201N
++ if ( DbgPrn_PHYName )
++ printf ("--->(%04lx %04lx)[Realtek] %s\n", PHY_ID2, PHY_ID3, PHYName);
++
++ phy_Reset(loop_phy);
++}
++
++//------------------------------------------------------------
++//internal loop 100M: Don't support
++//internal loop 10M : no loopback stub
++void phy_realtek0 (int loop_phy) {//RTL8201E
++ if ( DbgPrn_PHYName )
++ printf ("--->(%04lx %04lx)[Realtek] %s\n", PHY_ID2, PHY_ID3, PHYName);
++
++ phy_Reset(loop_phy);
++
++// phy_Read_Write(25, 0x2800, 0x0000);//clr set
++// printf("Enable phy output RMII clock\n");
++ if (IEEETesting) {
++ phy_write(31, 0x0001);
++ if (IOTimingBund_arg == 0) {
++ phy_write(25, 0x1f01);//Force MDI //Measuring from channel A
++ }
++ else {
++ phy_write(25, 0x1f00);//Force MDIX //Measuring from channel B
++ }
++ phy_write(31, 0x0000);
++ }
++}
++
++//------------------------------------------------------------
++void recov_phy_realtek1 (int loop_phy) {//RTL8211D
++ if ( BurstEnable ) {
++ if ( IEEETesting ) {
++ if ( GSpeed_sel[0] ) {
++ if (IOTimingBund_arg == 0) {
++ //Test Mode 1
++ phy_write( 31, 0x0002 );
++ phy_write( 2, 0xc203 );
++ phy_write( 31, 0x0000 );
++ phy_write( 9, 0x0000 );
++ }
++ else {
++ //Test Mode 4
++ phy_write( 31, 0x0000 );
++ phy_write( 9, 0x0000 );
++ }
++
++ phy_write( 31, 0x0000 );
++ }
++ else if ( GSpeed_sel[1] ) {
++ phy_write( 23, 0x2100 );
++ phy_write( 16, 0x016e );
++ }
++ else {
++// phy_write( 31, 0x0006 );
++// phy_write( 0, 0x5a00 );
++// phy_write( 31, 0x0000 );
++ }
++ } // End if ( IEEETesting )
++ }
++ else if (loop_phy) {
++ if ( GSpeed_sel[0] ) {
++ phy_write( 31, 0x0000 ); // new in Rev. 1.6
++ phy_write( 0, 0x1140 ); // new in Rev. 1.6
++ phy_write( 20, 0x8040 ); // new in Rev. 1.6
++ }
++ }
++ else {
++ if ( GSpeed_sel[0] ) {
++ phy_write( 31, 0x0001 );
++ phy_write( 3, 0xdf41 );
++ phy_write( 2, 0xdf20 );
++ phy_write( 1, 0x0140 );
++ phy_write( 0, 0x00bb );
++ phy_write( 4, 0xb800 );
++ phy_write( 4, 0xb000 );
++
++ phy_write( 31, 0x0000 );
++// phy_write( 26, 0x0020 ); // Rev. 1.2
++ phy_write( 26, 0x0040 ); // new in Rev. 1.6
++ phy_write( 0, 0x1140 );
++// phy_write( 21, 0x0006 ); // Rev. 1.2
++ phy_write( 21, 0x1006 ); // new in Rev. 1.6
++ phy_write( 23, 0x2100 );
++// } else if ( GSpeed_sel[1] ) {//option
++// phy_write( 31, 0x0000 );
++// phy_write( 9, 0x0200 );
++// phy_write( 0, 0x1200 );
++// } else if ( GSpeed_sel[2] ) {//option
++// phy_write( 31, 0x0000 );
++// phy_write( 9, 0x0200 );
++// phy_write( 4, 0x05e1 );
++// phy_write( 0, 0x1200 );
++ }
++ } // End if ( BurstEnable )
++} // End void recov_phy_realtek1 (int loop_phy)
++
++//------------------------------------------------------------
++//internal loop 1G : no loopback stub
++//internal loop 100M: no loopback stub
++//internal loop 10M : no loopback stub
++void phy_realtek1 (int loop_phy) {//RTL8211D
++ if ( DbgPrn_PHYName )
++ printf ("--->(%04lx %04lx)[Realtek] %s\n", PHY_ID2, PHY_ID3, PHYName);
++
++ if ( BurstEnable ) {
++ if ( IEEETesting ) {
++ if ( GSpeed_sel[0] ) {
++ if (IOTimingBund_arg == 0) {
++ //Test Mode 1
++ phy_write( 31, 0x0002 );
++ phy_write( 2, 0xc22b );
++ phy_write( 31, 0x0000 );
++ phy_write( 9, 0x2000 );
++ }
++ else {
++ //Test Mode 4
++ phy_write( 31, 0x0000 );
++ phy_write( 9, 0x8000 );
++ }
++ phy_write( 31, 0x0000 );
++ }
++ else if ( GSpeed_sel[1] ) {
++ if ( IOTimingBund_arg == 0 ) {
++ //From Channel A
++ phy_write( 23, 0xa102 );
++ phy_write( 16, 0x01ae );//MDI
++ }
++ else {
++ //From Channel B
++ phy_Read_Write( 17, 0x0008, 0x0000 ); // clr set
++ phy_write( 23, 0xa102 ); // MDI
++ phy_write( 16, 0x010e );
++ }
++ } else {
++// if ( IOTimingBund_arg == 0 ) {//Pseudo-random pattern
++// phy_write( 31, 0x0006 );
++// phy_write( 0, 0x5a21 );
++// phy_write( 31, 0x0000 );
++// }
++// else if ( IOTimingBund_arg == 1 ) {//¡§FF¡¨ pattern
++// phy_write( 31, 0x0006 );
++// phy_write( 2, 0x05ee );
++// phy_write( 0, 0xff21 );
++// phy_write( 31, 0x0000 );
++// } else {//¡§00¡¨ pattern
++// phy_write( 31, 0x0006 );
++// phy_write( 2, 0x05ee );
++// phy_write( 0, 0x0021 );
++// phy_write( 31, 0x0000 );
++// }
++ }
++ }
++ else {
++ phy_Reset(loop_phy);
++ }
++ }
++ else if ( loop_phy ) {
++ phy_Reset(loop_phy);
++
++ if ( GSpeed_sel[0] ) {
++ phy_write(20, 0x0042);//new in Rev. 1.6
++ }
++ }
++ else {
++ if ( GSpeed_sel[0] ) {
++ phy_write( 31, 0x0001 );
++ phy_write( 3, 0xff41 );
++ phy_write( 2, 0xd720 );
++ phy_write( 1, 0x0140 );
++ phy_write( 0, 0x00bb );
++ phy_write( 4, 0xb800 );
++ phy_write( 4, 0xb000 );
++
++ phy_write( 31, 0x0007 );
++ phy_write( 30, 0x0040 );
++ phy_write( 24, 0x0008 );
++
++ phy_write( 31, 0x0000 );
++ phy_write( 9, 0x0300 );
++ phy_write( 26, 0x0020 );
++ phy_write( 0, 0x0140 );
++ phy_write( 23, 0xa101 );
++ phy_write( 21, 0x0200 );
++ phy_write( 23, 0xa121 );
++ phy_write( 23, 0xa161 );
++ phy_write( 0, 0x8000 );
++ phy_Wait_Reset_Done();
++ phy_delay(200); // new in Rev. 1.6
++// }
++// else if ( GSpeed_sel[1] ) {//option
++// phy_write( 31, 0x0000 );
++// phy_write( 9, 0x0000 );
++// phy_write( 4, 0x0061 );
++// phy_write( 0, 0x1200 );
++// phy_delay(5000);
++// }
++// else if (GSpeed_sel[2]) {//option
++// phy_write( 31, 0x0000 );
++// phy_write( 9, 0x0000 );
++// phy_write( 4, 0x05e1 );
++// phy_write( 0, 0x1200 );
++// phy_delay(5000);
++ }
++ else {
++ phy_Reset(loop_phy);
++ }
++ }
++} // End void phy_realtek1 (int loop_phy)
++
++//------------------------------------------------------------
++void recov_phy_realtek2 (int loop_phy) {//RTL8211E
++ if ( BurstEnable ) {
++ if ( IEEETesting ) {
++ phy_write( 31, 0x0005 );
++ phy_write( 5, 0x8b86 );
++ phy_write( 6, 0xe201 );
++ phy_write( 31, 0x0007 );
++ phy_write( 30, 0x0020 );
++ phy_write( 21, 0x1108 );
++ phy_write( 31, 0x0000 );
++
++ if ( GSpeed_sel[0] ) {
++ phy_write( 31, 0x0000 );
++ phy_write( 9, 0x0000 );
++ }
++ else if ( GSpeed_sel[1] ) {
++ phy_write( 31, 0x0007 );
++ phy_write( 30, 0x002f );
++ phy_write( 23, 0xd88f );
++ phy_write( 30, 0x002d );
++ phy_write( 24, 0xf050 );
++ phy_write( 31, 0x0000 );
++ phy_write( 16, 0x006e );
++ }
++ else {
++ }
++ }
++ else {
++ }
++ }
++ else if (loop_phy) {
++ }
++ else {
++ if (GSpeed_sel[0]) {
++ //Rev 1.5 //not stable
++// phy_write( 31, 0x0000 );
++// phy_write( 0, 0x8000 );
++// phy_Wait_Reset_Done();
++// phy_delay(30);
++// phy_write( 23, 0x2160 );
++// phy_write( 31, 0x0007 );
++// phy_write( 30, 0x0040 );
++// phy_write( 24, 0x0004 );
++// phy_write( 24, 0x1a24 );
++// phy_write( 25, 0xfd00 );
++// phy_write( 24, 0x0000 );
++// phy_write( 31, 0x0000 );
++// phy_write( 0, 0x1140 );
++// phy_write( 26, 0x0040 );
++// phy_write( 31, 0x0007 );
++// phy_write( 30, 0x002f );
++// phy_write( 23, 0xd88f );
++// phy_write( 30, 0x0023 );
++// phy_write( 22, 0x0300 );
++// phy_write( 31, 0x0000 );
++// phy_write( 21, 0x1006 );
++// phy_write( 23, 0x2100 );
++/**/
++ //Rev 1.6
++ phy_write( 31, 0x0000 );
++ phy_write( 0, 0x8000 );
++ phy_Wait_Reset_Done();
++ phy_delay(30);
++ phy_write( 31, 0x0007 );
++ phy_write( 30, 0x0042 );
++ phy_write( 21, 0x0500 );
++ phy_write( 31, 0x0000 );
++ phy_write( 0, 0x1140 );
++ phy_write( 26, 0x0040 );
++ phy_write( 31, 0x0007 );
++ phy_write( 30, 0x002f );
++ phy_write( 23, 0xd88f );
++ phy_write( 30, 0x0023 );
++ phy_write( 22, 0x0300 );
++ phy_write( 31, 0x0000 );
++ phy_write( 21, 0x1006 );
++ phy_write( 23, 0x2100 );
++/**/
++// } else if (GSpeed_sel[1]) {//option
++// phy_write( 31, 0x0000 );
++// phy_write( 9, 0x0200 );
++// phy_write( 0, 0x1200 );
++// } else if (GSpeed_sel[2]) {//option
++// phy_write( 31, 0x0000 );
++// phy_write( 9, 0x0200 );
++// phy_write( 4, 0x05e1 );
++// phy_write( 0, 0x1200 );
++ }
++ }
++} // End void recov_phy_realtek2 (int loop_phy)
++
++//------------------------------------------------------------
++//internal loop 1G : no loopback stub
++//internal loop 100M: no loopback stub
++//internal loop 10M : no loopback stub
++void phy_realtek2 (int loop_phy) {//RTL8211E
++
++ if ( DbgPrn_PHYName )
++ printf ("--->(%04lx %04lx)[Realtek] %s\n", PHY_ID2, PHY_ID3, PHYName);
++
++ phy_Read_Write( 0, 0x0000, 0x8000 | PHY_00h ); // clr set // Rst PHY
++ phy_Wait_Reset_Done();
++ phy_delay(30);
++
++ if ( BurstEnable ) {
++ if ( IEEETesting ) {
++ phy_write( 31, 0x0005 );
++ phy_write( 5, 0x8b86 );
++ phy_write( 6, 0xe200 );
++ phy_write( 31, 0x0007 );
++ phy_write( 30, 0x0020 );
++ phy_write( 21, 0x0108 );
++ phy_write( 31, 0x0000 );
++
++ if ( GSpeed_sel[0] ) {
++ phy_write( 31, 0x0000 );
++
++ if ( IOTimingBund_arg == 0 ) {
++ phy_write( 9, 0x2000);//Test Mode 1
++ }
++ else {
++ phy_write( 9, 0x8000);//Test Mode 4
++ }
++ }
++ else if ( GSpeed_sel[1] ) {
++ phy_write( 31, 0x0007 );
++ phy_write( 30, 0x002f );
++ phy_write( 23, 0xd818 );
++ phy_write( 30, 0x002d );
++ phy_write( 24, 0xf060 );
++ phy_write( 31, 0x0000 );
++
++ if ( IOTimingBund_arg == 0 ) {
++ phy_write(16, 0x00ae);//From Channel A
++ }
++ else {
++ phy_write(16, 0x008e);//From Channel B
++ }
++ }
++ else {
++ }
++ }
++ else {
++ phy_basic_setting(loop_phy);
++ phy_delay(30);
++ }
++ }
++ else if (loop_phy) {
++ phy_basic_setting(loop_phy);
++
++ phy_Read_Write(0, 0x0000, 0x8000 | PHY_00h);//clr set//Rst PHY
++ phy_Wait_Reset_Done();
++ phy_delay(30);
++
++ phy_basic_setting(loop_phy);
++ phy_delay(30);
++ }
++ else {
++ if ( GSpeed_sel[0] ) {
++ //Rev 1.5 //not stable
++// phy_write( 23, 0x2160 );
++// phy_write( 31, 0x0007 );
++// phy_write( 30, 0x0040 );
++// phy_write( 24, 0x0004 );
++// phy_write( 24, 0x1a24 );
++// phy_write( 25, 0x7d00 );
++// phy_write( 31, 0x0000 );
++// phy_write( 23, 0x2100 );
++// phy_write( 31, 0x0007 );
++// phy_write( 30, 0x0040 );
++// phy_write( 24, 0x0000 );
++// phy_write( 30, 0x0023 );
++// phy_write( 22, 0x0006 );
++// phy_write( 31, 0x0000 );
++// phy_write( 0, 0x0140 );
++// phy_write( 26, 0x0060 );
++// phy_write( 31, 0x0007 );
++// phy_write( 30, 0x002f );
++// phy_write( 23, 0xd820 );
++// phy_write( 31, 0x0000 );
++// phy_write( 21, 0x0206 );
++// phy_write( 23, 0x2120 );
++// phy_write( 23, 0x2160 );
++/**/
++ //Rev 1.6
++ phy_write( 31, 0x0007 );
++ phy_write( 30, 0x0042 );
++ phy_write( 21, 0x2500 );
++ phy_write( 30, 0x0023 );
++ phy_write( 22, 0x0006 );
++ phy_write( 31, 0x0000 );
++ phy_write( 0, 0x0140 );
++ phy_write( 26, 0x0060 );
++ phy_write( 31, 0x0007 );
++ phy_write( 30, 0x002f );
++ phy_write( 23, 0xd820 );
++ phy_write( 31, 0x0000 );
++ phy_write( 21, 0x0206 );
++ phy_write( 23, 0x2120 );
++ phy_write( 23, 0x2160 );
++ phy_delay(300);
++/**/
++// }
++// else if ( GSpeed_sel[1] ) {//option
++// phy_write( 31, 0x0000 );
++// phy_write( 9, 0x0000 );
++// phy_write( 4, 0x0061 );
++// phy_write( 0, 0x1200 );
++// phy_delay(5000);
++// }
++// else if ( GSpeed_sel[2] ) {//option
++// phy_write( 31, 0x0000 );
++// phy_write( 9, 0x0000 );
++// phy_write( 4, 0x05e1 );
++// phy_write( 0, 0x1200 );
++// phy_delay(5000);
++ }
++ else {
++ phy_basic_setting(loop_phy);
++ phy_delay(150);
++ }
++ }
++} // End void phy_realtek2 (int loop_phy)
++
++//------------------------------------------------------------
++void recov_phy_realtek3 (int loop_phy) {//RTL8211C
++ if ( BurstEnable ) {
++ if ( IEEETesting ) {
++ if ( GSpeed_sel[0] ) {
++ phy_write( 9, 0x0000 );
++ }
++ else if ( GSpeed_sel[1] ) {
++ phy_write( 17, PHY_11h );
++ phy_write( 14, 0x0000 );
++ phy_write( 16, 0x00a0 );
++ }
++ else {
++// phy_write( 31, 0x0006 );
++// phy_write( 0, 0x5a00 );
++// phy_write( 31, 0x0000 );
++ }
++ }
++ else {
++ }
++ }
++ else if (loop_phy) {
++ if ( GSpeed_sel[0] ) {
++ phy_write( 11, 0x0000 );
++ }
++ phy_write( 12, 0x1006 );
++ }
++ else {
++ if ( GSpeed_sel[0] ) {
++ phy_write( 31, 0x0001 );
++ phy_write( 4, 0xb000 );
++ phy_write( 3, 0xff41 );
++ phy_write( 2, 0xdf20 );
++ phy_write( 1, 0x0140 );
++ phy_write( 0, 0x00bb );
++ phy_write( 4, 0xb800 );
++ phy_write( 4, 0xb000 );
++
++ phy_write( 31, 0x0000 );
++ phy_write( 25, 0x8c00 );
++ phy_write( 26, 0x0040 );
++ phy_write( 0, 0x1140 );
++ phy_write( 14, 0x0000 );
++ phy_write( 12, 0x1006 );
++ phy_write( 23, 0x2109 );
++ }
++ }
++}
++
++//------------------------------------------------------------
++void phy_realtek3 (int loop_phy) {//RTL8211C
++ if ( DbgPrn_PHYName )
++ printf ("--->(%04lx %04lx)[Realtek] %s\n", PHY_ID2, PHY_ID3, PHYName);
++
++ if ( BurstEnable ) {
++ if ( IEEETesting ) {
++ if ( GSpeed_sel[0] ) {
++ if ( IOTimingBund_arg == 0 ) { //Test Mode 1
++ phy_write( 9, 0x2000);
++ }
++ else if (IOTimingBund_arg == 1) {//Test Mode 2
++ phy_write( 9, 0x4000);
++ }
++ else if (IOTimingBund_arg == 2) {//Test Mode 3
++ phy_write( 9, 0x6000);
++ }
++ else { //Test Mode 4
++ phy_write( 9, 0x8000);
++ }
++ }
++ else if ( GSpeed_sel[1] ) {
++ PHY_11h = phy_read( PHY_SR );
++ phy_write( 17, PHY_11h & 0xfff7 );
++ phy_write( 14, 0x0660 );
++
++ if ( IOTimingBund_arg == 0 ) {
++ phy_write( 16, 0x00a0 );//MDI //From Channel A
++ }
++ else {
++ phy_write( 16, 0x0080 );//MDIX //From Channel B
++ }
++ }
++ else {
++// if (IOTimingBund_arg == 0) {//Pseudo-random pattern
++// phy_write( 31, 0x0006 );
++// phy_write( 0, 0x5a21 );
++// phy_write( 31, 0x0000 );
++// }
++// else if (IOTimingBund_arg == 1) {//¡§FF¡¨ pattern
++// phy_write( 31, 0x0006 );
++// phy_write( 2, 0x05ee );
++// phy_write( 0, 0xff21 );
++// phy_write( 31, 0x0000 );
++// }
++// else {//¡§00¡¨ pattern
++// phy_write( 31, 0x0006 );
++// phy_write( 2, 0x05ee );
++// phy_write( 0, 0x0021 );
++// phy_write( 31, 0x0000 );
++// }
++ }
++ }
++ else {
++ phy_Reset(loop_phy);
++ }
++ }
++ else if (loop_phy) {
++ phy_write( 0, 0x9200);
++ phy_Wait_Reset_Done();
++ phy_delay(30);
++
++ phy_write( 17, 0x401c );
++ phy_write( 12, 0x0006 );
++
++ if ( GSpeed_sel[0] ) {
++ phy_write(11, 0x0002);
++ }
++ else {
++ phy_basic_setting(loop_phy);
++ }
++ }
++ else {
++ if (GSpeed_sel[0]) {
++ phy_write( 31, 0x0001 );
++ phy_write( 4, 0xb000 );
++ phy_write( 3, 0xff41 );
++ phy_write( 2, 0xd720 );
++ phy_write( 1, 0x0140 );
++ phy_write( 0, 0x00bb );
++ phy_write( 4, 0xb800 );
++ phy_write( 4, 0xb000 );
++
++ phy_write( 31, 0x0000 );
++ phy_write( 25, 0x8400 );
++ phy_write( 26, 0x0020 );
++ phy_write( 0, 0x0140 );
++ phy_write( 14, 0x0210 );
++ phy_write( 12, 0x0200 );
++ phy_write( 23, 0x2109 );
++ phy_write( 23, 0x2139 );
++ }
++ else {
++ phy_Reset(loop_phy);
++ }
++ }
++} // End void phy_realtek3 (int loop_phy)
++
++//------------------------------------------------------------
++void phy_realtek4 (int loop_phy) {//RTL8201F
++ if ( DbgPrn_PHYName )
++ printf ("--->(%04lx %04lx)[Realtek] %s\n", PHY_ID2, PHY_ID3, PHYName);
++
++ if ( BurstEnable ) {
++ if ( IEEETesting ) {
++ phy_write( 31, 0x0004 );
++ phy_write( 16, 0x4077 );
++ phy_write( 21, 0xc5a0 );
++ phy_write( 31, 0x0000 );
++
++ if ( GSpeed_sel[1] ) {
++ phy_write( 0, 0x8000 ); // Reset PHY
++ phy_write( 24, 0x0310 ); // Disable ALDPS
++
++ if ( IOTimingBund_arg == 0 ) {
++ phy_write( 28, 0x40c2 ); //Force MDI //From Channel A (RJ45 pair 1, 2)
++ }
++ else {
++ phy_write( 28, 0x40c0 ); //Force MDIX//From Channel B (RJ45 pair 3, 6)
++ }
++ phy_write( 0, 0x2100); //Force 100M/Full Duplex)
++ }
++ } else {
++ phy_Reset(loop_phy);
++ }
++ }
++ else {
++ phy_Reset(loop_phy);
++ }
++}
++
++//------------------------------------------------------------
++void phy_smsc (int loop_phy) {//LAN8700
++ if ( DbgPrn_PHYName )
++ printf ("--->(%04lx %04lx)[SMSC] %s\n", PHY_ID2, PHY_ID3, PHYName);
++
++ phy_Reset(loop_phy);
++}
++
++//------------------------------------------------------------
++void phy_micrel (int loop_phy) {//KSZ8041
++ if ( DbgPrn_PHYName )
++ printf ("--->(%04lx %04lx)[Micrel] %s\n", PHY_ID2, PHY_ID3, PHYName);
++
++ phy_Reset(loop_phy);
++
++// phy_write(24, 0x0600);
++}
++
++//------------------------------------------------------------
++void phy_micrel0 (int loop_phy) {//KSZ8031/KSZ8051
++ if ( DbgPrn_PHYName ) printf ("--->(%04lx %04lx)[Micrel] %s\n", PHY_ID2, PHY_ID3, PHYName);
++
++ //For KSZ8051RNL only
++ //Reg1Fh[7] = 0(default): 25MHz Mode, XI, XO(pin 9, 8) is 25MHz(crystal/oscilator).
++ //Reg1Fh[7] = 1 : 50MHz Mode, XI(pin 9) is 50MHz(oscilator).
++ PHY_1fh = phy_read(31);
++ if (PHY_1fh & 0x0080) sprintf(PHYName, "%s-50MHz Mode", PHYName);
++ else sprintf(PHYName, "%s-25MHz Mode", PHYName);
++
++ if (IEEETesting) {
++ phy_Read_Write( 0, 0x0000, 0x8000 | PHY_00h );//clr set//Rst PHY
++ phy_Wait_Reset_Done();
++
++ phy_Read_Write( 31, 0x0000, 0x2000 );//clr set//1Fh[13] = 1: Disable auto MDI/MDI-X
++ phy_basic_setting(loop_phy);
++ phy_Read_Write( 31, 0x0000, 0x0800 );//clr set//1Fh[11] = 1: Force link pass
++
++// phy_delay(2500);//2.5 sec
++ }
++ else {
++ phy_Reset(loop_phy);
++
++ //Reg16h[6] = 1 : RMII B-to-B override
++ //Reg16h[1] = 1(default): RMII override
++ phy_Read_Write( 22, 0x0000, 0x0042 );//clr set
++ }
++
++ if ( PHY_1fh & 0x0080 )
++ phy_Read_Write( 31, 0x0000, 0x0080 );//clr set//Reset PHY will clear Reg1Fh[7]
++}
++
++//------------------------------------------------------------
++void recov_phy_vitesse (int loop_phy) {//VSC8601
++ if ( BurstEnable ) {
++// if (IEEETesting) {
++// } else {
++// }
++ }
++ else if ( loop_phy ) {
++ }
++ else {
++ if ( GSpeed_sel[0] ) {
++ phy_write( 24, PHY_18h );
++ phy_write( 18, PHY_12h );
++ }
++ }
++}
++
++//------------------------------------------------------------
++void phy_vitesse (int loop_phy) {//VSC8601
++ if ( DbgPrn_PHYName )
++ printf ("--->(%04lx %04lx)[VITESSE] %s\n", PHY_ID2, PHY_ID3, PHYName);
++
++ if ( BurstEnable ) {
++ if ( IEEETesting ) {
++ phy_Reset(loop_phy);
++ }
++ else {
++ phy_Reset(loop_phy);
++ }
++ }
++ else if ( loop_phy ) {
++ phy_Reset(loop_phy);
++ }
++ else {
++ if ( GSpeed_sel[0] ) {
++ PHY_18h = phy_read( 24 );
++ PHY_12h = phy_read( PHY_INER );
++
++ phy_Reset(loop_phy);
++
++ phy_write( 24, PHY_18h | 0x0001 );
++ phy_write( 18, PHY_12h | 0x0020 );
++ }
++ else {
++ phy_Reset(loop_phy);
++ }
++ }
++}
++
++//------------------------------------------------------------
++void phy_default (int loop_phy) {
++ if ( DbgPrn_PHYName )
++ printf ("--->(%04lx %04lx)%s\n", PHY_ID2, PHY_ID3, PHYName);
++
++ phy_Reset(loop_phy);
++}
++
++//------------------------------------------------------------
++// PHY Init
++//------------------------------------------------------------
++BOOLEAN find_phyadr (void) {
++ ULONG PHY_val;
++ BOOLEAN ret = FALSE;
++
++ #ifdef DbgPrn_FuncHeader
++ printf ("find_phyadr\n");
++ Debug_delay();
++ #endif
++
++ do {
++ // Check current PHY address by user setting
++ PHY_val = phy_read( PHY_REG_ID_1 );
++ if ( PHY_IS_VALID(PHY_val) ) {
++ ret = TRUE;
++ break;
++ }
++
++ if ( Enable_SkipChkPHY ) {
++ PHY_val = phy_read( PHY_REG_BMCR );
++
++ if ((PHY_val & 0x8000) & Enable_InitPHY) {
++ // PHY is reseting and need to inital PHY
++ #ifndef Enable_SearchPHYID
++ break;
++ #endif
++ }
++ else {
++ ret = TRUE;
++ break;
++ }
++ }
++
++ #ifdef Enable_SearchPHYID
++ // Scan PHY address from 0 to 31
++ printf("Search PHY address\n");
++ for ( PHY_ADR = 0; PHY_ADR < 32; PHY_ADR++ ) {
++ PHY_val = phy_read( PHY_REG_ID_1 );
++ if ( PHY_IS_VALID(PHY_val) ) {
++ ret = TRUE;
++ break;
++ }
++ }
++ // Don't find PHY address
++ PHY_ADR = PHY_ADR_arg;
++ #endif
++ } while ( 0 );
++
++ if ( ret == TRUE ) {
++ if ( PHY_ADR_arg != PHY_ADR ) {
++
++ if ( !BurstEnable )
++ phy_id( FP_LOG );
++
++ phy_id( STD_OUT );
++ }
++ }
++ else {
++
++ if ( !BurstEnable )
++ phy_id( FP_LOG );
++
++ phy_id( STD_OUT );
++ FindErr( Err_PHY_Type );
++ }
++
++ return ret;
++} // End BOOLEAN find_phyadr (void)
++
++//------------------------------------------------------------
++char phy_chk (ULONG id2, ULONG id3, ULONG id3_mask) {
++ if ((PHY_ID2 == id2) && ((PHY_ID3 & id3_mask) == (id3 & id3_mask)))
++ return(1);
++ else
++ return(0);
++}
++
++//------------------------------------------------------------
++void phy_set00h (int loop_phy) {
++ #ifdef DbgPrn_FuncHeader
++ printf ("phy_set00h\n");
++ Debug_delay();
++ #endif
++
++ if (BurstEnable) {
++ if (IEEETesting) {
++ if (GSpeed_sel[0]) PHY_00h = 0x0140;
++ else if (GSpeed_sel[1]) PHY_00h = 0x2100;
++ else PHY_00h = 0x0100;
++ }
++ else {
++ if (GSpeed_sel[0]) PHY_00h = 0x1140;
++ else if (GSpeed_sel[1]) PHY_00h = 0x3100;
++ else PHY_00h = 0x1100;
++ }
++ }
++ else if (loop_phy) {
++ if (GSpeed_sel[0]) PHY_00h = 0x4140;
++ else if (GSpeed_sel[1]) PHY_00h = 0x6100;
++ else PHY_00h = 0x4100;
++ }
++ else {
++ if (GSpeed_sel[0]) PHY_00h = 0x0140;
++ else if (GSpeed_sel[1]) PHY_00h = 0x2100;
++ else PHY_00h = 0x0100;
++ }
++}
++
++//------------------------------------------------------------
++void phy_sel (int loop_phy) {
++ #ifdef DbgPrn_FuncHeader
++ printf ("phy_sel\n");
++ Debug_delay();
++ #endif
++
++ PHY_ID2 = phy_read( PHY_REG_ID_1 );
++ PHY_ID3 = phy_read( PHY_REG_ID_2 );
++ phy_set00h(loop_phy);
++
++ if ((PHY_ID2 == 0xffff) && (PHY_ID3 == 0xffff) && !Enable_SkipChkPHY) {
++ sprintf(PHYName, "--");
++ FindErr(Err_PHY_Type);
++ }
++#ifdef Enable_CheckZeroPHYID
++ else if ((PHY_ID2 == 0x0000) && (PHY_ID3 == 0x0000) && !Enable_SkipChkPHY) {
++ sprintf(PHYName, "--"); FindErr(Err_PHY_Type);
++ }
++#endif
++
++ if (phy_chk(0x0362, 0x5e6a, 0xfff0 )) {sprintf(PHYName, "BCM54612" ); if (Enable_InitPHY) phy_broadcom0(loop_phy);}//BCM54612 1G/100/10M RGMII
++ else if (phy_chk(0x0362, 0x5d10, 0xfff0 )) {sprintf(PHYName, "BCM54616S" ); if (Enable_InitPHY) phy_broadcom0(loop_phy);}//BCM54616A 1G/100/10M RGMII
++ else if (phy_chk(0x0040, 0x61e0, PHYID3_Mask)) {sprintf(PHYName, "BCM5221" ); if (Enable_InitPHY) phy_broadcom (loop_phy);}//BCM5221 100/10M MII, RMII
++ else if (phy_chk(0x0141, 0x0dd0, 0xfff0 )) {sprintf(PHYName, "88E1512" ); if (Enable_InitPHY) phy_marvell2 (loop_phy);}//88E1512 1G/100/10M RGMII
++ else if (phy_chk(0xff00, 0x1761, 0xffff )) {sprintf(PHYName, "88E6176(IntLoop)"); if (Enable_InitPHY) phy_marvell1 (loop_phy);}//88E6176 1G/100/10M 2 RGMII Switch
++ else if (phy_chk(0x0141, 0x0e90, 0xfff0 )) {sprintf(PHYName, "88E1310" ); if (Enable_InitPHY) phy_marvell0 (loop_phy);}//88E1310 1G/100/10M RGMII
++ else if (phy_chk(0x0141, 0x0cc0, PHYID3_Mask)) {sprintf(PHYName, "88E1111" ); if (Enable_InitPHY) phy_marvell (loop_phy);}//88E1111 1G/100/10M GMII, MII, RGMII
++ else if (phy_chk(0x001c, 0xc816, 0xffff )) {sprintf(PHYName, "RTL8201F" ); if (Enable_InitPHY) phy_realtek4 (loop_phy);}//RTL8201F 100/10M MII, RMII
++ else if (phy_chk(0x001c, 0xc815, 0xfff0 )) {sprintf(PHYName, "RTL8201E" ); if (Enable_InitPHY) phy_realtek0 (loop_phy);}//RTL8201E 100/10M MII, RMII(RTL8201E(L)-VC only)
++ else if (phy_chk(0x001c, 0xc912, 0xffff )) {sprintf(PHYName, "RTL8211C" ); if (Enable_InitPHY) phy_realtek3 (loop_phy);}//RTL8211C 1G/100/10M RGMII
++ else if (phy_chk(0x001c, 0xc914, 0xffff )) {sprintf(PHYName, "RTL8211D" ); if (Enable_InitPHY) phy_realtek1 (loop_phy);}//RTL8211D 1G/100/10M GMII(RTL8211DN/RTL8211DG only), MII(RTL8211DN/RTL8211DG only), RGMII
++ else if (phy_chk(0x001c, 0xc915, 0xffff )) {sprintf(PHYName, "RTL8211E" ); if (Enable_InitPHY) phy_realtek2 (loop_phy);}//RTL8211E 1G/100/10M GMII(RTL8211EG only), RGMII
++ else if (phy_chk(0x0000, 0x8201, PHYID3_Mask)) {sprintf(PHYName, "RTL8201N" ); if (Enable_InitPHY) phy_realtek (loop_phy);}//RTL8201N 100/10M MII, RMII
++ else if (phy_chk(0x0007, 0xc0c4, PHYID3_Mask)) {sprintf(PHYName, "LAN8700" ); if (Enable_InitPHY) phy_smsc (loop_phy);}//LAN8700 100/10M MII, RMII
++ else if (phy_chk(0x0022, 0x1555, 0xfff0 )) {sprintf(PHYName, "KSZ8031/KSZ8051" ); if (Enable_InitPHY) phy_micrel0 (loop_phy);}//KSZ8051/KSZ8031 100/10M RMII
++ else if (phy_chk(0x0022, 0x1560, 0xfff0 )) {sprintf(PHYName, "KSZ8081" ); if (Enable_InitPHY) phy_micrel0 (loop_phy);}//KSZ8081 100/10M RMII
++ else if (phy_chk(0x0022, 0x1512, 0xfff0 )) {sprintf(PHYName, "KSZ8041" ); if (Enable_InitPHY) phy_micrel (loop_phy);}//KSZ8041 100/10M RMII
++ else if (phy_chk(0x0007, 0x0421, 0xfff0 )) {sprintf(PHYName, "VSC8601" ); if (Enable_InitPHY) phy_vitesse (loop_phy);}//VSC8601 1G/100/10M RGMII
++ else {sprintf(PHYName, "default" ); if (Enable_InitPHY) phy_default (loop_phy);}//
++}
++
++//------------------------------------------------------------
++void recov_phy (int loop_phy) {
++ #ifdef DbgPrn_FuncHeader
++ printf ("recov_phy\n");
++ Debug_delay();
++ #endif
++
++ if (phy_chk(0x0362, 0x5e6a, 0xfff0 )) recov_phy_broadcom0(loop_phy);//BCM54612 1G/100/10M RGMII
++ else if (phy_chk(0x0362, 0x5d10, 0xfff0 )) recov_phy_broadcom0(loop_phy);//BCM54616A 1G/100/10M RGMII
++ else if (phy_chk(0x0141, 0x0dd0, 0xfff0 )) recov_phy_marvell2 (loop_phy);//88E1512 1G/100/10M RGMII
++ else if (phy_chk(0xff00, 0x1761, 0xffff )) recov_phy_marvell1 (loop_phy);//88E6176 1G/100/10M 2 RGMII Switch
++ else if (phy_chk(0x0141, 0x0e90, 0xfff0 )) recov_phy_marvell0 (loop_phy);//88E1310 1G/100/10M RGMII
++ else if (phy_chk(0x0141, 0x0cc0, PHYID3_Mask)) recov_phy_marvell (loop_phy);//88E1111 1G/100/10M GMII, MII, RGMII
++ else if (phy_chk(0x001c, 0xc914, 0xffff )) recov_phy_realtek1 (loop_phy);//RTL8211D 1G/100/10M GMII(RTL8211DN/RTL8211DG only), MII(RTL8211DN/RTL8211DG only), RGMII
++ else if (phy_chk(0x001c, 0xc915, 0xffff )) recov_phy_realtek2 (loop_phy);//RTL8211E 1G/100/10M GMII(RTL8211EG only), RGMII
++ else if (phy_chk(0x001c, 0xc912, 0xffff )) recov_phy_realtek3 (loop_phy);//RTL8211C 1G/100/10M RGMII
++ else if (phy_chk(0x0007, 0x0421, 0xfff0 )) recov_phy_vitesse (loop_phy);//VSC8601 1G/100/10M RGMII
++}
++
++//------------------------------------------------------------
++void init_phy (int loop_phy) {
++ #ifdef DbgPrn_FuncHeader
++ printf ("init_phy\n");
++ Debug_delay();
++ #endif
++
++ sprintf( PHYID, "PHY%d", SelectMAC + 1 );
++
++ if ( DbgPrn_PHYInit )
++ phy_dump( PHYID );
++
++ if ( find_phyadr() == TRUE )
++ phy_sel( loop_phy );
++
++ if ( DbgPrn_PHYInit )
++ phy_dump( PHYID );
++}
++
++
+diff --git a/arch/arm/cpu/arm926ejs/aspeed/PLLTESTU.H b/arch/arm/cpu/arm926ejs/aspeed/PLLTESTU.H
+new file mode 100644
+index 0000000..6fa96e6
+--- /dev/null
++++ b/arch/arm/cpu/arm926ejs/aspeed/PLLTESTU.H
+@@ -0,0 +1,50 @@
++/*
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++ */
++#ifndef PLLTESTU_H
++#define PLLTESTU_H
++
++//PLL Mode Definition
++#define NAND_PLLMODE 0x00
++#define DELAY_PLLMODE 0x04
++#define PCI_PLLMODE 0x08
++#define DPLL_PLLMODE 0x2c
++#define MPLL_PLLMODE 0x10
++#define HPLL_PLLMODE 0x14
++#define LPC_PLLMODE 0x18
++#define VIDEOA_PLLMODE 0x1c
++#define D2PLL_PLLMODE 0x0c
++#define VIDEOB_PLLMODE 0x3c
++
++#define PCI_PLLMODE_AST1160 0x10
++#define MPLL_PLLMODE_AST1160 0x14
++#define HPLL_PLLMODE_AST1160 0x14
++#define DPLL_PLLMODE_AST1160 0x1c
++
++#define PCI_PLLMODE_AST2300 0x2c
++#define MPLL_PLLMODE_AST2300 0x10
++#define HPLL_PLLMODE_AST2300 0x30
++#define DPLL_PLLMODE_AST2300 0x08
++#define DEL0_PLLMODE_AST2300 0x00
++
++#define ERR_FATAL 0x00000001
++
++typedef struct _VGAINFO {
++ USHORT usDeviceID;
++ UCHAR jRevision;
++
++ ULONG ulMCLK;
++ ULONG ulDRAMBusWidth;
++
++ ULONG ulCPUCLK;
++ ULONG ulAHBCLK;
++} _VGAInfo;
++
++#endif // End PLLTESTU_H
+diff --git a/arch/arm/cpu/arm926ejs/aspeed/PLLTESTU.c b/arch/arm/cpu/arm926ejs/aspeed/PLLTESTU.c
+new file mode 100644
+index 0000000..95958b0
+--- /dev/null
++++ b/arch/arm/cpu/arm926ejs/aspeed/PLLTESTU.c
+@@ -0,0 +1,411 @@
++/*
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++ */
++#define PLLTEST_C
++static const char ThisFile[] = "PLLTEST.c";
++
++#include "SWFUNC.H"
++
++#include <COMMINF.H>
++#include <STDUBOOT.H>
++#include <TYPEDEF.H>
++#include <IO.H>
++#include <PLLTESTU.H>
++
++/*
++ * static
++ */
++static UCHAR jVersion[] = "v.0.57.00";
++
++void print_usage( void )
++{
++ printf(" PLLTest [pll mode] [err rate]\n");
++ printf(" [pll mode] h-pll: ARM CPU Clock PLL\n");
++ printf(" m-pll: Memory Clock PLL\n");
++ printf(" [err rate] Error Rate: unit %\n");
++ printf(" default is 1%\n");
++}
++
++BOOL CompareToRing(_VGAInfo *VGAInfo, ULONG ulPLLMode, ULONG ulDCLK, ULONG ulErrRate)
++{
++ ULONG ulCounter, ulLowLimit, ulHighLimit;
++ ULONG ulData, ulValue, ulDiv;
++ ULONG ulSCUBase;
++ double del0;
++ ULONG uldel0;
++
++ if ((VGAInfo->usDeviceID == 0x1160) || (VGAInfo->usDeviceID == 0x1180))
++ ulSCUBase = 0x80fc8200;
++ else
++ ulSCUBase = 0x1e6e2000;
++
++ //Fixed AST2300 H-PLL can't Get Correct Value in VGA only mode, ycchen@081711
++ if ( (VGAInfo->jRevision >= 0x20) && (ulPLLMode == HPLL_PLLMODE_AST2300) )
++ {
++ WriteSOC_DD(ulSCUBase, 0x1688a8a8);
++ ulData = ReadSOC_DD(ulSCUBase + 0x08);
++ WriteSOC_DD(ulSCUBase + 0x08, ulData & 0xFFFFFF00);
++ }
++
++ ulCounter = (ulDCLK/1000) * 512 / 24000 - 1;
++ ulLowLimit = ulCounter * (100 - ulErrRate) / 100;
++ ulHighLimit = ulCounter * (100 + ulErrRate) / 100;
++
++ DELAY(10);
++ WriteSOC_DD(ulSCUBase, 0x1688a8a8);
++ WriteSOC_DD(ulSCUBase + 0x28, (ulHighLimit << 16) | ulLowLimit);
++ WriteSOC_DD(ulSCUBase + 0x10, ulPLLMode);
++ WriteSOC_DD(ulSCUBase + 0x10, ulPLLMode | 0x03);
++ DELAY(1);
++ do {
++ ulData = ReadSOC_DD(ulSCUBase + 0x10);
++ } while (!(ulData & 0x40));
++ ulValue = ReadSOC_DD(ulSCUBase + 0x14);
++
++ //Patch for AST1160/1180 DCLK calculate
++ if ( ((VGAInfo->usDeviceID == 0x1160) || (VGAInfo->usDeviceID == 0x1180)) && (ulPLLMode == DPLL_PLLMODE_AST1160) )
++ {
++ ulData = ReadSOC_DD(0x80fc906c);
++ ulDiv = ulData & 0x000c0000;
++ ulDiv >>= 18;
++ ulDiv++;
++ ulValue /= ulDiv;
++ }
++
++ if ( (VGAInfo->jRevision >= 0x20) && (ulPLLMode == DEL0_PLLMODE_AST2300) )
++ {
++ del0 = (double)(24.0 * (ulValue + 1) / 512.0);
++ del0 = 1000/del0/16/8;
++ uldel0 = (ULONG) (del0 * 1000000);
++ if (uldel0 < ulDCLK)
++ {
++ printf( "[PASS][DEL0] Actual DEL0:%f ns, Max. DEL0:%f ns \n", del0, (double)ulDCLK/1000000);
++ ulData |= 0x80;
++ }
++ else
++ {
++ printf( "[ERROR][DEL0] Actual DEL0:%f ns, Max. DEL0:%f ns \n", del0, (double)ulDCLK/1000000);
++ ulData == 0x00;
++ }
++ }
++ else
++ {
++ printf( "[INFO] PLL Predict Count = %x, Actual Count = %x \n", ulCounter, ulValue);
++ }
++
++ WriteSOC_DD(ulSCUBase + 0x10, 0x2C); //disable ring
++
++ if (ulData & 0x80)
++ return (TRUE);
++ else
++ return(FALSE);
++} /* CompareToRing */
++
++VOID GetDRAMInfo(_VGAInfo *VGAInfo)
++{
++ ULONG ulData, ulData2;
++ ULONG ulRefPLL, ulDeNumerator, ulNumerator, ulDivider, ulOD;
++
++ if (VGAInfo->jRevision >= 0x10)
++ {
++ WriteSOC_DD(0x1e6e2000, 0x1688A8A8);
++
++ //Get DRAM Bus Width
++ ulData = ReadSOC_DD(0x1e6e0004);
++ if (ulData & 0x40)
++ VGAInfo->ulDRAMBusWidth = 16;
++ else
++ VGAInfo->ulDRAMBusWidth = 32;
++
++ ulRefPLL = 24000;
++ if (VGAInfo->jRevision >= 0x30) //AST2400
++ {
++ ulData = ReadSOC_DD(0x1e6e2070);
++ if (ulData & 0x00800000) //D[23] = 1
++ ulRefPLL = 25000;
++ }
++
++ ulData = ReadSOC_DD(0x1e6e2020);
++ ulDeNumerator = ulData & 0x0F;
++ ulNumerator = (ulData & 0x07E0) >> 5;
++ ulOD = (ulData & 0x10) ? 1:2;
++
++ ulData = (ulData & 0x7000) >> 12;
++ switch (ulData)
++ {
++ case 0x07:
++ ulDivider = 16;
++ break;
++ case 0x06:
++ ulDivider = 8;
++ break;
++ case 0x05:
++ ulDivider = 4;
++ break;
++ case 0x04:
++ ulDivider = 2;
++ break;
++ default:
++ ulDivider = 0x01;
++ }
++
++ VGAInfo->ulMCLK = ulRefPLL * ulOD * (ulNumerator + 2) / ((ulDeNumerator + 1) * ulDivider * 1000);
++ }
++} // GetDRAMInfo
++
++VOID GetCLKInfo( _VGAInfo *VGAInfo)
++{
++ ULONG ulData, ulCPUTrap, ulAHBTrap;
++ ULONG ulRefPLL, ulDeNumerator, ulNumerator, ulDivider, ulOD;
++
++ if (VGAInfo->jRevision >= 0x30)
++ {
++ WriteSOC_DD(0x1e6e2000, 0x1688a8a8);
++ ulData = ReadSOC_DD(0x1e6e2024);
++ if (ulData & 0x40000) //from H-PLL
++ {
++ ulRefPLL = 24000;
++ ulData = ReadSOC_DD(0x1e6e2070);
++ if (ulData & 0x00800000) //D[23] = 1
++ ulRefPLL = 25000;
++
++ ulData = ReadSOC_DD(0x1e6e2024);
++
++ ulDeNumerator = ulData & 0x0F;
++ ulNumerator = (ulData & 0x07E0) >> 5;
++ ulOD = (ulData & 0x10) ? 1:2;
++
++ VGAInfo->ulCPUCLK = ulRefPLL * ulOD * (ulNumerator + 2) / ((ulDeNumerator + 1) * 1000);
++
++ }
++ else //from trapping
++ {
++ ulRefPLL = 24;
++ ulData = ReadSOC_DD(0x1e6e2070);
++ if (ulData & 0x00800000) //D[23] = 1
++ ulRefPLL = 25;
++
++ ulCPUTrap = ulData & 0x0300;
++ ulCPUTrap >>= 8;
++
++ switch (ulCPUTrap)
++ {
++ case 0x00:
++ VGAInfo->ulCPUCLK = ulRefPLL * 16;
++ break;
++ case 0x01:
++ VGAInfo->ulCPUCLK = ulRefPLL * 15;
++ break;
++ case 0x02:
++ VGAInfo->ulCPUCLK = ulRefPLL * 14;
++ break;
++ case 0x03:
++ VGAInfo->ulCPUCLK = ulRefPLL * 17;
++ break;
++ }
++
++ }
++
++ ulData = ReadSOC_DD(0x1e6e2070);
++ ulAHBTrap = ulData & 0x0c00;
++ ulAHBTrap >>= 10;
++ switch (ulAHBTrap)
++ {
++ case 0x00:
++ VGAInfo->ulAHBCLK = VGAInfo->ulCPUCLK;
++ break;
++ case 0x01:
++ VGAInfo->ulAHBCLK = VGAInfo->ulCPUCLK / 2;
++ break;
++ case 0x02:
++ VGAInfo->ulAHBCLK = VGAInfo->ulCPUCLK / 4;
++ break;
++ case 0x03:
++ VGAInfo->ulAHBCLK = VGAInfo->ulCPUCLK / 3;
++ break;
++ }
++
++ } //AST2400
++ else if (VGAInfo->jRevision >= 0x20)
++ {
++ WriteSOC_DD(0x1e6e2000, 0x1688a8a8);
++ ulData = ReadSOC_DD(0x1e6e2024);
++ if (ulData & 0x40000) //from H-PLL
++ {
++ ulRefPLL = 24000;
++
++ ulData = ReadSOC_DD(0x1e6e2024);
++
++ ulDeNumerator = ulData & 0x0F;
++ ulNumerator = (ulData & 0x07E0) >> 5;
++ ulOD = (ulData & 0x10) ? 1:2;
++
++ VGAInfo->ulCPUCLK = ulRefPLL * ulOD * (ulNumerator + 2) / ((ulDeNumerator + 1) * 1000);
++
++ }
++ else //from trapping
++ {
++ ulData = ReadSOC_DD(0x1e6e2070);
++ ulCPUTrap = ulData & 0x0300;
++ ulCPUTrap >>= 8;
++
++ switch (ulCPUTrap)
++ {
++ case 0x00:
++ VGAInfo->ulCPUCLK = 384;
++ break;
++ case 0x01:
++ VGAInfo->ulCPUCLK = 360;
++ break;
++ case 0x02:
++ VGAInfo->ulCPUCLK = 336;
++ break;
++ case 0x03:
++ VGAInfo->ulCPUCLK = 408;
++ break;
++ }
++
++ }
++
++ ulData = ReadSOC_DD(0x1e6e2070);
++ ulAHBTrap = ulData & 0x0c00;
++ ulAHBTrap >>= 10;
++ switch (ulAHBTrap)
++ {
++ case 0x00:
++ VGAInfo->ulAHBCLK = VGAInfo->ulCPUCLK;
++ break;
++ case 0x01:
++ VGAInfo->ulAHBCLK = VGAInfo->ulCPUCLK / 2;
++ break;
++ case 0x02:
++ VGAInfo->ulAHBCLK = VGAInfo->ulCPUCLK / 4;
++ break;
++ case 0x03:
++ VGAInfo->ulAHBCLK = VGAInfo->ulCPUCLK / 3;
++ break;
++ }
++
++ } //AST2300
++} // GetCLKInfo
++
++int pll_function(int argc, char *argv[])
++{
++ _VGAInfo *pVGAInfo;
++ ULONG ulErrRate = 1;
++ ULONG PLLMode;
++ ULONG RefClk;
++ CHAR *stop_at;
++ CHAR i;
++
++ printf("**************************************************** \n");
++ printf("*** ASPEED Graphics PLL Test %s Log *** \n", jVersion);
++ printf("*** for u-boot *** \n");
++ printf("**************************************************** \n");
++ printf("\n");
++
++ // Check chip type
++ switch ( ReadSOC_DD( 0x1e6e2000 + 0x7c ) ) {
++ case 0x02010303 :
++ case 0x02000303 :
++ printf("The chip is AST2400\n" );
++ pVGAInfo->usDeviceID = 0x2400;
++ pVGAInfo->jRevision = 0x30;
++ break;
++
++ case 0x02010103 :
++ case 0x02000003 :
++ printf("The chip is AST1400\n" );
++ pVGAInfo->usDeviceID = 0x1400;
++ pVGAInfo->jRevision = 0x30;
++ break;
++
++ case 0x01010303 :
++ case 0x01000003 :
++ printf("The chip is AST2300\n" );
++ pVGAInfo->usDeviceID = 0x2300;
++ pVGAInfo->jRevision = 0x20;
++ break;
++
++ case 0x01010203 :
++ printf("The chip is AST1050\n" );
++ pVGAInfo->usDeviceID = 0x1050;
++ pVGAInfo->jRevision = 0x20;
++ break;
++
++ default :
++ printf ("Error Silicon Revision ID(SCU7C) %08lx!!!\n", ReadSOC_DD( 0x1e6e2000 + 0x7c ) );
++ return(1);
++ }
++
++
++ GetDRAMInfo( pVGAInfo );
++ GetCLKInfo( pVGAInfo );
++
++ if ( ( argc <= 1 ) || ( argc >= 4 ) ){
++ print_usage();
++ return (ERR_FATAL);
++ }
++ else {
++ for ( i = 1; i < argc; i++ ) {
++ switch ( i ) {
++ case 1:
++ if (!strcmp(argv[i], "m-pll"))
++ {
++ if (pVGAInfo->jRevision >= 0x20)
++ PLLMode = MPLL_PLLMODE_AST2300;
++ else
++ PLLMode = MPLL_PLLMODE;
++
++ RefClk = pVGAInfo->ulMCLK * 1000000;
++ if (pVGAInfo->jRevision >= 0x20) //dual-edge
++ RefClk /= 2;
++ }
++ else if (!strcmp(argv[i], "h-pll"))
++ {
++ if (pVGAInfo->jRevision >= 0x20)
++ PLLMode = HPLL_PLLMODE_AST2300;
++ else
++ PLLMode = HPLL_PLLMODE;
++
++ //AST2300 only has HCLK ring test mode, ycchen@040512
++ RefClk = pVGAInfo->ulCPUCLK * 1000000; //Other : H-PLL
++ if (pVGAInfo->jRevision >= 0x20) //AST2300: HCLK
++ RefClk = pVGAInfo->ulAHBCLK * 1000000;
++ }
++ else {
++ print_usage();
++ return (ERR_FATAL);
++ }
++ break;
++ case 2:
++ ulErrRate = (ULONG) strtoul(argv[i], &stop_at, 10);
++
++ break;
++ default:
++ break;
++ } // End switch()
++ } // End for
++ }
++
++ /* Compare ring */
++ if (CompareToRing(pVGAInfo, PLLMode, RefClk, ulErrRate ) == TRUE)
++ {
++ printf("[PASS] %s PLL Check Pass!! \n", argv[1]);
++ return 0;
++ }
++ else
++ {
++ printf("[ERROR] %s PLL Check Failed!! \n", argv[1]);
++ return (ERR_FATAL);
++ }
++}
++
++
+diff --git a/arch/arm/cpu/arm926ejs/aspeed/SPIM.c b/arch/arm/cpu/arm926ejs/aspeed/SPIM.c
+new file mode 100644
+index 0000000..e1bdd07
+--- /dev/null
++++ b/arch/arm/cpu/arm926ejs/aspeed/SPIM.c
+@@ -0,0 +1,63 @@
++/*
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++ */
++#define SPIM_C
++static const char ThisFile[] = "SPIM.c";
++
++#include "SWFUNC.H"
++
++#ifdef SPI_BUS
++
++#include <stdio.h>
++#include <stdlib.h>
++#include <conio.h>
++#include <string.h>
++#include "TYPEDEF.H"
++#include "LIB_SPI.H"
++
++#define SPIM_CMD_WHA 0x01
++#define SPIM_CMD_RD 0x0B
++#define SPIM_CMD_DRD 0xBB
++#define SPIM_CMD_WR 0x02
++#define SPIM_CMD_DWR 0xD2
++#define SPIM_CMD_STA 0x05
++#define SPIM_CMD_ENBYTE 0x06
++#define SPIM_CMD_DISBYTE 0x04
++
++ULONG spim_cs;
++ULONG spim_base;
++ULONG spim_hadr;
++
++void spim_end()
++{
++ ULONG data;
++
++ data = MIndwm((ULONG)mmiobase, 0x1E620010 + (spim_cs << 2));
++ MOutdwm( (ULONG)mmiobase, 0x1E620010 + (spim_cs << 2), data | 0x4);
++ MOutdwm( (ULONG)mmiobase, 0x1E620010 + (spim_cs << 2), data);
++}
++
++//------------------------------------------------------------
++void spim_init(int cs)
++{
++ ULONG data;
++
++ spim_cs = cs;
++ MOutdwm( (ULONG)mmiobase, 0x1E620000, (0x2 << (cs << 1)) | (0x10000 << cs));
++ MOutdwm( (ULONG)mmiobase, 0x1E620010 + (cs << 2), 0x00000007);
++ MOutdwm( (ULONG)mmiobase, 0x1E620010 + (cs << 2), 0x00002003);
++ MOutdwm( (ULONG)mmiobase, 0x1E620004, 0x100 << cs);
++ data = MIndwm((ULONG)mmiobase, 0x1E620030 + (cs << 2));
++ spim_base = 0x20000000 | ((data & 0x007f0000) << 7);
++ MOutwm ( (ULONG)mmiobase, spim_base, SPIM_CMD_WHA);
++ spim_end();
++ spim_hadr = 0;
++}
++#endif // End SPI_BUS
+diff --git a/arch/arm/cpu/arm926ejs/aspeed/STDUBOOT.H b/arch/arm/cpu/arm926ejs/aspeed/STDUBOOT.H
+new file mode 100644
+index 0000000..7fbf590
+--- /dev/null
++++ b/arch/arm/cpu/arm926ejs/aspeed/STDUBOOT.H
+@@ -0,0 +1,18 @@
++/*
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++ */
++#ifndef STDUBOOT_H
++#define STDUBOOT_H
++
++unsigned long int strtoul(char *string, char **endPtr, int base);
++int atoi( char s[] );
++int rand(void);
++
++#endif // End STDUBOOT_H
+diff --git a/arch/arm/cpu/arm926ejs/aspeed/STDUBOOT.c b/arch/arm/cpu/arm926ejs/aspeed/STDUBOOT.c
+new file mode 100644
+index 0000000..90e2997
+--- /dev/null
++++ b/arch/arm/cpu/arm926ejs/aspeed/STDUBOOT.c
+@@ -0,0 +1,235 @@
++/*
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++ */
++#define STDUBOOT_C
++static const char ThisFile[] = "STDUBOOT.c";
++
++#include "SWFUNC.H"
++
++#ifdef SLT_UBOOT
++
++int isspace ( char c )
++{
++ if ( ( c == ' ' ) || ( c == 9 ) || ( c == 13 ) )
++ return 1;
++
++ return 0;
++}
++
++/*
++ * strtoul.c --
++ *
++ * Source code for the "strtoul" library procedure.
++ *
++ * Copyright 1988 Regents of the University of California
++ * Permission to use, copy, modify, and distribute this
++ * software and its documentation for any purpose and without
++ * fee is hereby granted, provided that the above copyright
++ * notice appear in all copies. The University of California
++ * makes no representations about the suitability of this
++ * software for any purpose. It is provided "as is" without
++ * express or implied warranty.
++ */
++
++//#include <ctype.h>
++
++/*
++ * The table below is used to convert from ASCII digits to a
++ * numerical equivalent. It maps from '0' through 'z' to integers
++ * (100 for non-digit characters).
++ */
++
++static char cvtIn[] = {
++ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, /* '0' - '9' */
++ 100, 100, 100, 100, 100, 100, 100, /* punctuation */
++ 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, /* 'A' - 'Z' */
++ 20, 21, 22, 23, 24, 25, 26, 27, 28, 29,
++ 30, 31, 32, 33, 34, 35,
++ 100, 100, 100, 100, 100, 100, /* punctuation */
++ 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, /* 'a' - 'z' */
++ 20, 21, 22, 23, 24, 25, 26, 27, 28, 29,
++ 30, 31, 32, 33, 34, 35};
++
++/*
++ *----------------------------------------------------------------------
++ *
++ * strtoul --
++ *
++ * Convert an ASCII string into an integer.
++ *
++ * Results:
++ * The return value is the integer equivalent of string. If endPtr
++ * is non-NULL, then *endPtr is filled in with the character
++ * after the last one that was part of the integer. If string
++ * doesn't contain a valid integer value, then zero is returned
++ * and *endPtr is set to string.
++ *
++ * Side effects:
++ * None.
++ *
++ *----------------------------------------------------------------------
++ */
++
++unsigned long int
++strtoul(char *string, char **endPtr, int base)
++ /* string; String of ASCII digits, possibly
++ * preceded by white space. For bases
++ * greater than 10, either lower- or
++ * upper-case digits may be used.
++ */
++ /* **endPtr; Where to store address of terminating
++ * character, or NULL. */
++ /* base; Base for conversion. Must be less
++ * than 37. If 0, then the base is chosen
++ * from the leading characters of string:
++ * "0x" means hex, "0" means octal, anything
++ * else means decimal.
++ */
++{
++ register char *p;
++ register unsigned long int result = 0;
++ register unsigned digit;
++ int anyDigits = 0;
++
++ /*
++ * Skip any leading blanks.
++ */
++
++ p = string;
++ while (isspace(*p)) {
++ p += 1;
++ }
++
++ /*
++ * If no base was provided, pick one from the leading characters
++ * of the string.
++ */
++
++ if (base == 0)
++ {
++ if (*p == '0') {
++ p += 1;
++ if (*p == 'x') {
++ p += 1;
++ base = 16;
++ } else {
++
++ /*
++ * Must set anyDigits here, otherwise "0" produces a
++ * "no digits" error.
++ */
++
++ anyDigits = 1;
++ base = 8;
++ }
++ }
++ else base = 10;
++ } else if (base == 16) {
++
++ /*
++ * Skip a leading "0x" from hex numbers.
++ */
++
++ if ((p[0] == '0') && (p[1] == 'x')) {
++ p += 2;
++ }
++ }
++
++ /*
++ * Sorry this code is so messy, but speed seems important. Do
++ * different things for base 8, 10, 16, and other.
++ */
++
++ if (base == 8) {
++ for ( ; ; p += 1) {
++ digit = *p - '0';
++ if (digit > 7) {
++ break;
++ }
++ result = (result << 3) + digit;
++ anyDigits = 1;
++ }
++ } else if (base == 10) {
++ for ( ; ; p += 1) {
++ digit = *p - '0';
++ if (digit > 9) {
++ break;
++ }
++ result = (10*result) + digit;
++ anyDigits = 1;
++ }
++ } else if (base == 16) {
++ for ( ; ; p += 1) {
++ digit = *p - '0';
++ if (digit > ('z' - '0')) {
++ break;
++ }
++ digit = cvtIn[digit];
++ if (digit > 15) {
++ break;
++ }
++ result = (result << 4) + digit;
++ anyDigits = 1;
++ }
++ } else {
++ for ( ; ; p += 1) {
++ digit = *p - '0';
++ if (digit > ('z' - '0')) {
++ break;
++ }
++ digit = cvtIn[digit];
++ if (digit >= base) {
++ break;
++ }
++ result = result*base + digit;
++ anyDigits = 1;
++ }
++ }
++
++ /*
++ * See if there were any digits at all.
++ */
++
++ if (!anyDigits) {
++ p = string;
++ }
++
++ if (endPtr != 0) {
++ *endPtr = p;
++ }
++
++ return result;
++}
++
++// -----------------------------------------------------------------------------
++int atoi( char s[] )
++{
++
++ int i;
++ int ans = 0;
++
++ for( i = 0; s[i] >= '0' && s[i] <= '9'; ++i )
++ ans = ( 10 * ans ) + ( s[i] - '0' );
++
++ return ans;
++}
++
++// -----------------------------------------------------------------------------
++/* rand:return pseudo-random integer on 0...32767 */
++int rand(void)
++{
++ static unsigned long int next = 1;
++
++ next = next * 1103515245 + 12345;
++
++ return (unsigned int) ( next / 65536 ) % 32768;
++}
++
++#endif // End SLT_UBOOT
+diff --git a/arch/arm/cpu/arm926ejs/aspeed/STRESS.c b/arch/arm/cpu/arm926ejs/aspeed/STRESS.c
+new file mode 100644
+index 0000000..dffd64f
+--- /dev/null
++++ b/arch/arm/cpu/arm926ejs/aspeed/STRESS.c
+@@ -0,0 +1,145 @@
++/*
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++ */
++#define STRESS_C
++static const char ThisFile[] = "STRESS.c";
++
++#include "SWFUNC.H"
++#include <COMMINF.H>
++#include <IO.H>
++
++#define TIMEOUT_DRAM 5000000
++
++/* ------------------------------------------------------------------------- */
++int MMCTestBurst(unsigned int datagen)
++{
++ unsigned int data;
++ unsigned int timeout = 0;
++
++ WriteSOC_DD( 0x1E6E0070, 0x00000000 );
++ WriteSOC_DD( 0x1E6E0070, (0x000000C1 | (datagen << 3)) );
++
++ do {
++ data = ReadSOC_DD( 0x1E6E0070 ) & 0x3000;
++
++ if( data & 0x2000 )
++ return(0);
++
++ if( ++timeout > TIMEOUT_DRAM ) {
++ printf("Timeout!!\n");
++ WriteSOC_DD( 0x1E6E0070, 0x00000000 );
++
++ return(0);
++ }
++ } while( !data );
++ WriteSOC_DD( 0x1E6E0070, 0x00000000 );
++
++ return(1);
++}
++
++/* ------------------------------------------------------------------------- */
++int MMCTestSingle(unsigned int datagen)
++{
++ unsigned int data;
++ unsigned int timeout = 0;
++
++ WriteSOC_DD( 0x1E6E0070, 0x00000000 );
++ WriteSOC_DD( 0x1E6E0070, (0x00000085 | (datagen << 3)) );
++
++ do {
++ data = ReadSOC_DD( 0x1E6E0070 ) & 0x3000;
++
++ if( data & 0x2000 )
++ return(0);
++
++ if( ++timeout > TIMEOUT_DRAM ){
++ printf("Timeout!!\n");
++ WriteSOC_DD( 0x1E6E0070, 0x00000000 );
++
++ return(0);
++ }
++ } while ( !data );
++ WriteSOC_DD( 0x1E6E0070, 0x00000000 );
++
++ return(1);
++}
++
++/* ------------------------------------------------------------------------- */
++int MMCTest()
++{
++ unsigned int pattern;
++
++ pattern = ReadSOC_DD( 0x1E6E2078 );
++ printf("Pattern = %08X : ",pattern);
++
++ WriteSOC_DD(0x1E6E0074, (DRAM_MapAdr | 0x7fffff) );
++ WriteSOC_DD(0x1E6E007C, pattern );
++
++ if(!MMCTestBurst(0)) return(0);
++ if(!MMCTestBurst(1)) return(0);
++ if(!MMCTestBurst(2)) return(0);
++ if(!MMCTestBurst(3)) return(0);
++ if(!MMCTestBurst(4)) return(0);
++ if(!MMCTestBurst(5)) return(0);
++ if(!MMCTestBurst(6)) return(0);
++ if(!MMCTestBurst(7)) return(0);
++ if(!MMCTestSingle(0)) return(0);
++ if(!MMCTestSingle(1)) return(0);
++ if(!MMCTestSingle(2)) return(0);
++ if(!MMCTestSingle(3)) return(0);
++ if(!MMCTestSingle(4)) return(0);
++ if(!MMCTestSingle(5)) return(0);
++ if(!MMCTestSingle(6)) return(0);
++ if(!MMCTestSingle(7)) return(0);
++
++ return(1);
++}
++
++/* ------------------------------------------------------------------------- */
++int dram_stress_function(int argc, char *argv[])
++{
++ unsigned int Pass;
++ unsigned int PassCnt = 0;
++ unsigned int Testcounter = 0;
++ int ret = 1;
++ char *stop_at;
++
++ printf("**************************************************** \n");
++ printf("*** ASPEED Stress DRAM *** \n");
++ printf("*** 20131107 for u-boot *** \n");
++ printf("**************************************************** \n");
++ printf("\n");
++
++ if ( argc != 2 ){
++ ret = 0;
++ return ( ret );
++ }
++ else {
++ Testcounter = (unsigned int) strtoul(argv[1], &stop_at, 10);
++ }
++
++ WriteSOC_DD(0x1E6E0000, 0xFC600309);
++
++ while( ( Testcounter > PassCnt ) || ( Testcounter == 0 ) ){
++ if( !MMCTest() ) {
++ printf("FAIL...%d/%d\n", PassCnt, Testcounter);
++ ret = 0;
++
++ break;
++ }
++ else {
++ PassCnt++;
++ printf("Pass %d/%d\n", PassCnt, Testcounter);
++ }
++ } // End while()
++
++ return( ret );
++}
++
+diff --git a/arch/arm/cpu/arm926ejs/aspeed/SWFUNC.H b/arch/arm/cpu/arm926ejs/aspeed/SWFUNC.H
+new file mode 100644
+index 0000000..0a03654
+--- /dev/null
++++ b/arch/arm/cpu/arm926ejs/aspeed/SWFUNC.H
+@@ -0,0 +1,137 @@
++/*
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++ */
++#ifndef SWFUNC_H
++#define SWFUNC_H
++
++
++//---------------------------------------------------------
++// Program information
++//---------------------------------------------------------
++#define VER_NAME "Ver 0.34 version @2014/03/25 0932"
++
++/* == Step 1: ====== Support OS system =================== */
++// LinuxAP
++// #define Windows
++#define SLT_UBOOT
++//#define SLT_DOS
++
++/* == Step 2:======== Support interface ================== */
++/* Choose One */
++//#define SPI_BUS
++//#define USE_LPC
++//#define USE_P2A // PCI or PCIe bus to AHB bus
++
++/* == Step 3:========== Support Chip ================== */
++//#define AST1010_CHIP
++//#define AST3200_IOMAP
++//#define FPGA
++
++#ifdef AST1010_CHIP
++ #ifdef SLT_UBOOT
++ #define AST1010_IOMAP 1
++ #endif
++ #ifdef SLT_DOS
++ #define AST1010_IOMAP 2
++
++ // AST1010 only has LPC interface
++ #undef USE_P2A
++ #undef SPI_BUS
++ #define USE_LPC
++ #endif
++#endif
++
++/* == Step 4:========== Select PHY ================== */
++//#define SUPPORT_PHY_LAN9303 // Initial PHY via I2C bus
++#define LAN9303_I2C_BUSNUM 6 // 1-based
++#define LAN9303_I2C_ADR 0x14
++
++/* ====================== Program ======================== */
++// The "PHY_NCSI" option is only for DOS compiler
++#if defined (PHY_NCSI)
++ #ifdef SLT_UBOOT
++ #error Wrong setting......
++ #endif
++#endif
++
++#if defined (PHY_NCSI)
++ #ifdef SUPPORT_PHY_LAN9303
++ #error Wrong setting (Can't support LAN9303)......
++ #endif
++#endif
++
++/* ================= Check setting ===================== */
++#ifdef SLT_UBOOT
++ #ifdef SLT_DOS
++ #error Can NOT support two OS
++ #endif
++#endif
++#ifdef SLT_DOS
++ #ifdef SLT_UBOOT
++ #error Can NOT support two OS
++ #endif
++#endif
++
++#ifdef USE_P2A
++ #ifdef SLT_UBOOT
++ #error Can NOT be set PCI bus in Uboot
++ #endif
++#endif
++#ifdef USE_LPC
++ #ifdef SLT_UBOOT
++ #error Can NOT be set LPC bus in Uboot
++ #endif
++#endif
++#ifdef SPI_BUS
++ #ifdef SLT_UBOOT
++ #error Can NOT be set SPI bus in Uboot
++ #endif
++#endif
++
++/* ======================== Program flow control ======================== */
++#define RUN_STEP 5
++// 0: read_scu
++// 1: parameter setup
++// 2: init_scu1,
++// 3: init_scu_macrst
++// 4: Data Initial
++// 5: ALL
++
++/* ====================== Switch print debug message ====================== */
++#define DbgPrn_Enable_Debug_delay 0
++//#define DbgPrn_FuncHeader 0 //1
++#define DbgPrn_ErrFlg 0
++#define DbgPrn_BufAdr 0 //1
++#define DbgPrn_Bufdat 0
++#define DbgPrn_BufdatDetail 0
++#define DbgPrn_PHYRW 0
++#define DbgPrn_PHYInit 0
++#define DbgPrn_PHYName 0
++#define DbgPrn_DumpMACCnt 0
++#define DbgPrn_Info 0 //1
++#define DbgPrn_FRAME_LEN 0
++
++
++/* ============ Enable or Disable Check item of the descriptor ============ */
++#define CheckRxOwn
++#define CheckRxErr
++//#define CheckOddNibble
++#define CheckCRC
++#define CheckRxFIFOFull
++#define CheckRxLen
++//#define CheckDataEveryTime
++
++//#define CheckRxbufUNAVA
++#define CheckRPktLost
++//#define CheckNPTxbufUNAVA
++#define CheckTPktLost
++#define CheckRxBuf
++
++#endif // SWFUNC_H
+diff --git a/arch/arm/cpu/arm926ejs/aspeed/TRAPTEST.c b/arch/arm/cpu/arm926ejs/aspeed/TRAPTEST.c
+new file mode 100644
+index 0000000..72936c0
+--- /dev/null
++++ b/arch/arm/cpu/arm926ejs/aspeed/TRAPTEST.c
+@@ -0,0 +1,151 @@
++/*
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++ */
++#define PLLTEST_C
++static const char ThisFile[] = "PLLTEST.c";
++
++#include "SWFUNC.H"
++
++#include <COMMINF.H>
++#include <TYPEDEF.H>
++#include <IO.H>
++
++#define ASTCHIP_2400 0
++#define ASTCHIP_2300 1
++#define ASTCHIP_1400 2
++#define ASTCHIP_1300 3
++#define ASTCHIP_1050 4
++
++const UCHAR jVersion[] = "v.0.60.06";
++
++typedef struct _TRAPINFO {
++ USHORT CPU_clk;
++ UCHAR CPU_AHB_ratio;
++} _TrapInfo;
++
++const _TrapInfo AST_default_trap_setting[] = {
++ // CPU_clk, CPU_AHB_ratio
++ { 384, 2 }, // AST2400 or AST1250 ( ASTCHIP_2400 )
++ { 384, 2 }, // AST2300 ( ASTCHIP_2300 )
++ { 384, 0xFF }, // AST1400 ( ASTCHIP_1400 )
++ { 384, 0xFF }, // AST1300 ( ASTCHIP_1300 )
++ { 384, 2 } // AST1050 ( ASTCHIP_1050 )
++};
++
++int trap_function(int argc, char *argv[])
++{
++ UCHAR chiptype;
++ ULONG ulData, ulTemp;
++ UCHAR status = TRUE;
++ USHORT val_trap;
++
++ printf("**************************************************** \n");
++ printf("*** ASPEED Trap Test %s Log *** \n", jVersion);
++ printf("*** for u-boot *** \n");
++ printf("**************************************************** \n");
++ printf("\n");
++
++ // Check chip type
++ switch ( ReadSOC_DD( 0x1e6e2000 + 0x7c ) ) {
++ case 0x02010303 :
++ case 0x02000303 :
++ printf("The chip is AST2400 or AST1250\n" );
++ chiptype = ASTCHIP_2400;
++ break;
++
++ case 0x02010103 :
++ case 0x02000003 :
++ printf("The chip is AST1400\n" );
++ chiptype = ASTCHIP_1400;
++ break;
++
++ case 0x01010303 :
++ case 0x01000003 :
++ printf("The chip is AST2300\n" );
++ chiptype = ASTCHIP_2300;
++ break;
++
++ case 0x01010203 :
++ printf("The chip is AST1050\n" );
++ chiptype = ASTCHIP_1050;
++ break;
++
++ case 0x01010003 :
++ printf("The chip is AST1300\n" );
++ chiptype = ASTCHIP_1300;
++ break;
++
++ default :
++ printf ("Error Silicon Revision ID(SCU7C) %08lx!!!\n", ReadSOC_DD( 0x1e6e2000 + 0x7c ) );
++ return(1);
++ }
++
++ WriteSOC_DD(0x1e6e2000, 0x1688A8A8);
++ ulData = ReadSOC_DD(0x1e6e2070);
++
++ // Check CPU clock
++ ulTemp = ulData;
++ ulTemp &= 0x0300;
++ ulTemp >>= 8;
++
++ switch (ulTemp)
++ {
++ case 0x00:
++ val_trap = 384;
++ break;
++ case 0x01:
++ val_trap = 360;
++ break;
++ case 0x02:
++ val_trap = 336;
++ break;
++ case 0x03:
++ val_trap = 408;
++ break;
++ }
++
++ if (AST_default_trap_setting[chiptype].CPU_clk != val_trap)
++ {
++ printf("[ERROR] CPU CLK: Correct is %d; Real is %d \n", AST_default_trap_setting[chiptype].CPU_clk, val_trap);
++ status = FALSE;
++ }
++
++ // Check cpu_ahb_ratio
++ ulTemp = ulData;
++ ulTemp &= 0x0c00;
++ ulTemp >>= 10;
++
++ switch (ulTemp)
++ {
++ case 0x00:
++ val_trap = 1;
++ break;
++ case 0x01:
++ val_trap = 2;
++ break;
++ case 0x02:
++ val_trap = 4;
++ break;
++ case 0x03:
++ val_trap = 3;
++ break;
++ }
++
++ if (AST_default_trap_setting[chiptype].CPU_AHB_ratio != val_trap)
++ {
++ printf("[ERROR] CPU:AHB: Correct is %x:1; Real is %x:1 \n", AST_default_trap_setting[chiptype].CPU_AHB_ratio, val_trap);
++ status = FALSE;
++ }
++
++ if ( status == TRUE )
++ printf("[PASS] hardware trap for CPU clock and CPU\\AHB ratio.\n");
++
++ return status;
++}
+diff --git a/arch/arm/cpu/arm926ejs/aspeed/TYPEDEF.H b/arch/arm/cpu/arm926ejs/aspeed/TYPEDEF.H
+new file mode 100644
+index 0000000..3053ad7
+--- /dev/null
++++ b/arch/arm/cpu/arm926ejs/aspeed/TYPEDEF.H
+@@ -0,0 +1,74 @@
++/*
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++ */
++#ifndef TYPEDEF_H
++#define TYPEDEF_H
++
++#include "SWFUNC.H"
++
++//
++// Define
++//
++#define PCI 1
++#define PCIE 2
++#define AGP 3
++#define ACTIVE 4
++
++#if defined(LinuxAP)
++ #ifndef FLONG
++ #define FLONG unsigned long
++ #endif
++ #ifndef ULONG
++ #define ULONG unsigned long
++ #endif
++ #ifndef LONG
++ #define LONG long
++ #endif
++ #ifndef USHORT
++ #define USHORT unsigned short
++ #endif
++ #ifndef SHORT
++ #define SHORT short
++ #endif
++ #ifndef UCHAR
++ #define UCHAR unsigned char
++ #endif
++ #ifndef CHAR
++ #define CHAR char
++ #endif
++ #ifndef BYTE
++ #define BYTE unsigned char
++ #endif
++ #ifndef VOID
++ #define VOID void
++ #endif
++ #ifndef SCHAR
++ #define SCHAR signed char
++ #endif
++#else
++/* DOS Program */
++ #define VOID void
++ #define FLONG unsigned long
++ #define ULONG unsigned long
++ #define USHORT unsigned short
++ #define UCHAR unsigned char
++ #define LONG long
++ #define SHORT short
++ #define CHAR char
++ #define BYTE UCHAR
++ #define BOOL SHORT
++ #define BOOLEAN unsigned short
++ #define PULONG ULONG *
++ #define SCHAR signed char
++#endif
++ #define TRUE 1
++ #define FALSE 0
++
++#endif // TYPEDEF_H
+diff --git a/arch/arm/cpu/arm926ejs/aspeed/mactest.c b/arch/arm/cpu/arm926ejs/aspeed/mactest.c
+new file mode 100644
+index 0000000..95bd560
+--- /dev/null
++++ b/arch/arm/cpu/arm926ejs/aspeed/mactest.c
+@@ -0,0 +1,1215 @@
++/*
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++ */
++#define MACTEST_C
++static const char ThisFile[] = "MACTEST.c";
++
++#include "SWFUNC.H"
++
++#ifdef SLT_UBOOT
++ #include <common.h>
++ #include <command.h>
++ #include <post.h>
++ #include <malloc.h>
++ #include <net.h>
++ #include <COMMINF.H>
++ #include <STDUBOOT.H>
++ #include <IO.H>
++#else
++ #include <stdlib.h>
++ #include <string.h>
++ #include "LIB.H"
++ #include "COMMINF.H"
++ #include "IO.H"
++#endif
++
++const BYTE Val_Array[16] = {0,1, 2,3, 4,5, 6,7, 8,9, 10,11, 12,13, 14,15}; // AST2300-A1
++const BYTE Val_Array_A0[16] = {8,1, 10,3, 12,5, 14,7, 0,9, 2,11, 4,13, 6,15}; // AST2300-A0
++
++#ifdef SLT_UBOOT
++int main_function(int argc, char *argv[])
++#endif
++#ifdef SLT_DOS
++int main(int argc, char *argv[])
++#endif
++{
++ CHAR MAC2_Valid;
++ CHAR MAC_1GEn;
++ CHAR MAC1_RMII;
++ CHAR Enable_IntLoopPHY;
++ CHAR Disable_RecovPHY;
++ CHAR Force1G;
++ CHAR Force10M;
++ CHAR Force100M;
++ CHAR *stop_at;
++ ULONG IOStr_val;
++ ULONG IOStr_max;
++ ULONG IOStr_shf;
++ ULONG IOdly_val;
++ ULONG Err_Flag_allapeed;
++ int DES_LowNumber;
++ int index;
++ int i;
++ int j;
++ #ifdef Enable_NCSI_LOOP_INFINI
++ BYTE GSpeed_org[3];
++ #endif
++
++#ifdef SPI_BUS
++ VIDEO_ENGINE_INFO VideoEngineInfo;
++#else
++ // ( USE_P2A | USE_LPC )
++ UCHAR *ulMMIOLinearBaseAddress;
++#endif
++
++ #ifdef SLT_UBOOT
++ #else
++ time(&timestart);
++ #endif
++
++ // For DOS system
++ #if defined(PHY_NCSI)
++ // For DOS compiler OPEN WATCOM
++ ModeSwitch = MODE_NSCI;
++ #else
++ #ifdef SLT_DOS
++ ModeSwitch = MODE_DEDICATED;
++ #endif
++ #endif
++
++//------------------------------------------------------------
++// Argument Initial
++//------------------------------------------------------------
++ Err_Flag_allapeed = 0;
++ Err_Flag = 0;
++ Err_Flag_PrintEn = 1;
++ Loop_rl[0] = 0;
++ Loop_rl[1] = 0;
++ Loop_rl[2] = 0;
++
++//------------------------------------------------------------
++// Bus Initial
++//------------------------------------------------------------
++#if defined(LinuxAP)
++#else
++ //DOS system
++ #ifdef SPI_BUS
++ #endif
++ #ifdef USE_LPC
++
++ if ( findlpcport( 0x0d ) == 0) {
++ printf("Failed to find proper LPC port \n");
++
++ return(1);
++ }
++ open_aspeed_sio_password();
++ enable_aspeed_LDU( 0x0d );
++ #endif
++ #ifdef USE_P2A
++ // PCI bus
++ #ifdef DOS_PMODEW
++ if (CheckDOS()) return 1;
++ #endif
++
++ #ifdef DbgPrn_FuncHeader
++ printf ("Initial-MMIO\n");
++ Debug_delay();
++ #endif
++ ulPCIBaseAddress = FindPCIDevice (0x1A03, 0x2000, ACTIVE);
++ if ( ulPCIBaseAddress == 0 )
++ ulPCIBaseAddress = FindPCIDevice (0x1688, 0x2000, ACTIVE);
++ if ( ulPCIBaseAddress == 0 )
++ ulPCIBaseAddress = FindPCIDevice (0x1A03, 0x0200, ACTIVE);
++ if ( ulPCIBaseAddress == 0 )
++ ulPCIBaseAddress = FindPCIDevice (0x1A03, 0x3000, ACTIVE);
++ if ( ulPCIBaseAddress == 0 )
++ ulPCIBaseAddress = FindPCIDevice (0x1A03, 0x2010, ACTIVE);
++ if ( ulPCIBaseAddress == 0 ) {
++ printf ("Can't find device\n");
++
++ return(1);
++ }
++
++ WritePCIReg (ulPCIBaseAddress, 0x04, 0xFFFFFFFc, 0x3);
++ ulMMIOBaseAddress = ReadPCIReg (ulPCIBaseAddress, 0x14, 0xFFFF0000);
++ ulMMIOLinearBaseAddress = (UCHAR *)MapPhysicalToLinear (ulMMIOBaseAddress, 64 * 1024 * 1024);
++ #endif // #ifdef USE_P2A
++#endif // End defined(LinuxAP)
++
++#ifdef SPI_BUS
++ GetDevicePCIInfo (&VideoEngineInfo);
++ mmiobase = VideoEngineInfo.VGAPCIInfo.ulMMIOBaseAddress;
++ spim_init(SPI_CS);
++#else
++ // ( USE_P2A | USE_LPC )
++ mmiobase = ulMMIOLinearBaseAddress;
++#endif
++
++//------------------------------------------------------------
++// Check Chip Feature
++//------------------------------------------------------------
++ read_scu();
++
++ if (RUN_STEP >= 1) {
++ switch (SCU_7ch_old) {
++// case 0x02000003 : sprintf(ASTChipName, "[ ]AST3200-FPGA" ); ASTChipType = 6; AST1100 = 0; break;
++
++ case 0x03020003 : sprintf(ASTChipName, "[ ]AST1010-A2" ); ASTChipType = 5; AST1100 = 0; break;
++ case 0x03010003 : sprintf(ASTChipName, "[ ]AST1010-A1" ); ASTChipType = 5; AST1100 = 0; break;
++ case 0x03000003 : sprintf(ASTChipName, "[*]AST1010-A0" ); ASTChipType = 5; AST1100 = 0; break;
++
++ case 0x02010303 : sprintf(ASTChipName, "[*]AST2400-A1" ); ASTChipType = 4; AST1100 = 0; break;//AST2400-A1
++ case 0x02000303 : sprintf(ASTChipName, "[ ]AST2400-A0" ); ASTChipType = 4; AST1100 = 0; break;//AST2400-A0
++ case 0x02010103 : sprintf(ASTChipName, "[*]AST1400-A1" ); ASTChipType = 4; AST1100 = 0; break;//AST1400-A1
++ case 0x02000003 : sprintf(ASTChipName, "[ ]AST1400-A0" ); ASTChipType = 4; AST1100 = 0; break;//AST1400-A0
++
++ case 0x01010303 : sprintf(ASTChipName, "[*]AST2300-A1" ); ASTChipType = 3; AST1100 = 0; break;//AST2300-A1
++ case 0x01010203 : sprintf(ASTChipName, "[*]AST1050-A1" ); ASTChipType = 3; AST1100 = 0; break;//AST1050-A1
++ case 0x01010003 : sprintf(ASTChipName, "[*]AST1300-A1" ); ASTChipType = 3; AST1100 = 0; break;//AST1300-A1
++ case 0x01000003 : sprintf(ASTChipName, "[ ]AST2300-A0" ); ASTChipType = 3; AST1100 = 0; break;//AST2300-A0
++// case 0x01860003 : sprintf(ASTChipName, "[ ]AST2300-FPGA" ); ASTChipType = 3; AST1100 = 0; break;
++
++ case 0x00000102 : sprintf(ASTChipName, "[*]AST2200-A1" ); ASTChipType = 2; AST1100 = 0; break;//AST2200-A1/A0
++
++ case 0x00000302 : sprintf(ASTChipName, "[*]AST2100-A3" ); ASTChipType = 1; AST1100 = 0; break;//AST2100-A3/A2
++ case 0x00000301 : sprintf(ASTChipName, "[ ]AST2100-A1" ); ASTChipType = 1; AST1100 = 0; break;//AST2100-A1
++ case 0x00000300 : sprintf(ASTChipName, "[ ]AST2100-A0" ); ASTChipType = 1; AST1100 = 0; break;//AST2100-A0
++ case 0x00000202 : sprintf(ASTChipName, "[*]AST2050/AST1100-A3, AST2150-A1"); ASTChipType = 1; AST1100 = 1; break;//AST2050/AST1100-A3/A2 AST2150-A1/A0
++ case 0x00000201 : sprintf(ASTChipName, "[ ]AST2050/AST1100-A1" ); ASTChipType = 1; AST1100 = 1; break;//AST2050/AST1100-A1
++ case 0x00000200 : sprintf(ASTChipName, "[ ]AST2050/AST1100-A0" ); ASTChipType = 1; AST1100 = 1; break;//AST2050/AST1100-A0
++
++ default :
++ printf ("Error Silicon Revision ID(SCU7C) %08lx!!!\n", SCU_7ch_old);
++ return(1);
++ } // End switch (SCU_7ch_old)
++
++ switch (ASTChipType) {
++ case 6 : AST2300 = 1; AST2400 = 1; AST1010 = 0; AST3200 = 1; break;
++ case 5 : AST2300 = 1; AST2400 = 1; AST1010 = 1; AST3200 = 0; break;
++ case 4 : AST2300 = 1; AST2400 = 1; AST1010 = 0; AST3200 = 0; break;
++ case 3 : AST2300 = 1; AST2400 = 0; AST1010 = 0; AST3200 = 0; break;
++ default : AST2300 = 0; AST2400 = 0; AST1010 = 0; AST3200 = 0; break;
++ } // End switch (ASTChipType)
++
++ if (ASTChipType == 3) {
++#ifdef Force_Enable_MAC34
++ WriteSOC_DD( SCU_BASE + 0xf0, 0xAEED0001 ); //enable mac34
++ Enable_MAC34 = 1;
++#else
++ if (SCU_f0h_old & 0x00000001)
++ Enable_MAC34 = 1;
++ else
++ Enable_MAC34 = 0;
++#endif
++ }
++ else {
++ Enable_MAC34 = 0;
++ } // End if (ASTChipType == 3)
++
++ Setting_scu();
++
++//------------------------------------------------------------
++// Argument Input
++//------------------------------------------------------------
++ // Load default value
++ UserDVal = DEF_USER_DEF_PACKET_VAL;
++ IOTimingBund_arg = DEF_IOTIMINGBUND;
++ PHY_ADR_arg = DEF_PHY_ADR;
++ TestMode = DEF_TESTMODE;
++ LOOP_INFINI = 0;
++ LOOP_MAX_arg = 0;
++ GCtrl = ( DEF_MAC_LOOP_BACK << 6 ) | ( DEF_SKIP_CHECK_PHY << 5 ) | ( DEF_INIT_PHY << 3 );
++ GSpeed = DEF_SPEED;
++
++ // Get setting information by user
++ GRun_Mode = (BYTE)atoi(argv[1]);
++
++ if ( ModeSwitch == MODE_NSCI ) {
++ ARPNumCnt = DEF_ARPNUMCNT;
++ ChannelTolNum = DEF_CHANNEL2NUM;
++ PackageTolNum = DEF_PACKAGE2NUM;
++ GSpeed = SET_100MBPS; // In NCSI mode, we set to 100M bps
++ }
++
++ // Setting user's configuration
++ if (argc > 1) {
++ if ( ModeSwitch == MODE_NSCI )
++ switch (argc) {
++ case 7: ARPNumCnt = (ULONG)atoi(argv[6]);
++ case 6: IOTimingBund_arg = (BYTE)atoi(argv[5]);
++ case 5: TestMode = (BYTE)atoi(argv[4]);
++ case 4: ChannelTolNum = (BYTE)atoi(argv[3]);
++ case 3: PackageTolNum = (BYTE)atoi(argv[2]);
++ default: break;
++ }
++ else
++ switch (argc) {
++ case 9: UserDVal = strtoul (argv[8], &stop_at, 16);
++ case 8: IOTimingBund_arg = (BYTE)atoi(argv[7]);
++ case 7: PHY_ADR_arg = (BYTE)atoi(argv[6]);
++ case 6: TestMode = (BYTE)atoi(argv[5]);
++ case 5: strcpy(LOOP_Str, argv[4]);
++ if (!strcmp(LOOP_Str, "#")) LOOP_INFINI = 1;
++ else LOOP_MAX_arg = (ULONG)atoi(LOOP_Str);
++ case 4: GCtrl = (BYTE)atoi(argv[3]);
++ case 3: GSpeed = (BYTE)atoi(argv[2]);
++ default: break;
++ }
++
++ IOTimingBund = IOTimingBund_arg;
++ PHY_ADR = PHY_ADR_arg;
++ }
++ else {
++ // Wrong parameter
++ if ( ModeSwitch == MODE_NSCI ) {
++ if (AST2300)
++ printf ("\nNCSITEST.exe run_mode <package_num> <channel_num> <test_mode> <IO margin>\n\n");
++ else
++ printf ("\nNCSITEST.exe run_mode <package_num> <channel_num> <test_mode>\n\n");
++ PrintMode ();
++ PrintPakNUm();
++ PrintChlNUm();
++ PrintTest ();
++ if (AST2300)
++ PrintIOTimingBund ();
++ }
++ else {
++ if (AST2300)
++ printf ("\nMACTEST.exe run_mode <speed> <ctrl> <loop_max> <test_mode> <phy_adr> <IO margin>\n\n");
++ else
++ printf ("\nMACTEST.exe run_mode <speed> <ctrl> <loop_max> <test_mode> <phy_adr>\n\n");
++ PrintMode ();
++ PrintSpeed ();
++ PrintCtrl ();
++ PrintLoop ();
++ PrintTest ();
++ PrintPHYAdr ();
++ if (AST2300)
++ PrintIOTimingBund ();
++ }
++ Finish_Close();
++
++ return(1);
++ } // End if (argc > 1)
++
++//------------------------------------------------------------
++// Check Argument
++//------------------------------------------------------------
++ switch ( GRun_Mode ) {
++ case 0: printf ("\n[MAC1]\n"); SelectMAC = 0; H_MAC_BASE = MAC_BASE1; break;
++ case 1: printf ("\n[MAC2]\n"); SelectMAC = 1; H_MAC_BASE = MAC_BASE2; break;
++ case 2: if (Enable_MAC34) {printf ("\n[MAC3]\n"); SelectMAC = 2; H_MAC_BASE = MAC_BASE3; break;}
++ else
++ goto Error_MAC_Mode;
++ case 3: if (Enable_MAC34) {printf ("\n[MAC4]\n"); SelectMAC = 3; H_MAC_BASE = MAC_BASE4; break;}
++ else
++ goto Error_MAC_Mode;
++ default:
++Error_MAC_Mode:
++ printf ("Error run_mode!!!\n");
++ PrintMode ();
++
++ return(1);
++ } // End switch ( GRun_Mode )
++
++ H_TDES_BASE = TDES_BASE1;
++ H_RDES_BASE = RDES_BASE1;
++ MAC_PHYBASE = H_MAC_BASE;
++
++ Force1G = 0;
++ Force10M = 0;
++ Force100M = 0;
++ GSpeed_sel[0] = 0;//1G
++ GSpeed_sel[1] = 0;//100M
++ GSpeed_sel[2] = 0;//10M
++
++ switch ( GSpeed ) {
++ case SET_1GBPS : Force1G = 1; GSpeed_sel[0] = 1; break;
++ case SET_100MBPS : Force100M = 1; GSpeed_sel[1] = 1; break;
++ case SET_10MBPS : Force10M = 1; GSpeed_sel[2] = 1; break;
++ case SET_1G_100M_10MBPS : break;
++ default: printf ("Error speed!!!\n");
++ PrintSpeed ();
++ return(1);
++ } // End switch ( GSpeed )
++
++ if ( ModeSwitch == MODE_NSCI ) {
++ Enable_MACLoopback = 0; // For mactest function
++ Enable_SkipChkPHY = 0; // For mactest function
++ Enable_IntLoopPHY = 0; // For mactest function
++ Enable_InitPHY = 0; // For mactest function
++ Disable_RecovPHY = 0; // For mactest function
++ BurstEnable = 0; // For mactest function
++
++ PrintNCSIEn = (ARPNumCnt & 0x1);
++ ARPNumCnt = ARPNumCnt & 0xfffffffe;
++
++ // Check parameter
++ if ((PackageTolNum < 1) || (PackageTolNum > 8)) {
++ PrintPakNUm();
++ return(1);
++ }
++// if ((ChannelTolNum < 0) || (ChannelTolNum > 32)) {
++ if (ChannelTolNum > 32) {
++ PrintChlNUm();
++ return(1);
++ }
++
++ switch (TestMode) {
++ case 0 : NCSI_DiSChannel = 1; IOTiming = 0; IOStrength = 0; TxDataEnable = 1; RxDataEnable = 1; break;
++ case 1 : NCSI_DiSChannel = 0; IOTiming = 0; IOStrength = 0; TxDataEnable = 1; RxDataEnable = 1; break;
++ case 6 : if (AST2300) {NCSI_DiSChannel = 1; IOTiming = 1; IOStrength = 0; TxDataEnable = 1; RxDataEnable = 1; break;}
++ else
++ goto Error_Test_Mode_NCSI;
++ case 7 : if (AST2300) {NCSI_DiSChannel = 1; IOTiming = 1; IOStrength = 1; TxDataEnable = 1; RxDataEnable = 1; break;}
++ else
++ goto Error_Test_Mode_NCSI;
++ default:
++ // Wrong parameter
++Error_Test_Mode_NCSI:
++ printf ("Error test_mode!!!\n");
++ PrintTest ();
++ return(1);
++ } // End switch (TestMode)
++ }
++ else {
++ if ( GCtrl & 0xffffff83 ) {
++ printf ("Error ctrl!!!\n");
++ PrintCtrl ();
++ return(1);
++ }
++ else {
++ Enable_MACLoopback = ( GCtrl >> 6 ) & 0x1; // ??
++ Enable_SkipChkPHY = ( GCtrl >> 5 ) & 0x1; // ??
++ Enable_IntLoopPHY = ( GCtrl >> 4 ) & 0x1;
++ Enable_InitPHY = ( GCtrl >> 3 ) & 0x1;
++ Disable_RecovPHY = ( GCtrl >> 2 ) & 0x1; // ??
++
++ if (!AST2400 && Enable_MACLoopback) {
++ printf ("Error ctrl!!!\n");
++ PrintCtrl ();
++ return(1);
++ }
++ } // End if ( GCtrl & 0xffffff83 )
++
++ if (!LOOP_MAX_arg) {
++ switch (GSpeed) {
++ case SET_1GBPS : LOOP_MAX_arg = DEF_LOOP_MAX * 200; break; // 20140325
++ case SET_100MBPS : LOOP_MAX_arg = DEF_LOOP_MAX * 20 ; break; // 20140325
++ case SET_10MBPS : LOOP_MAX_arg = DEF_LOOP_MAX * 10 ; break; // 20140325
++ case SET_1G_100M_10MBPS: LOOP_MAX_arg = DEF_LOOP_MAX * 10 ; break; // 20140325
++ }
++ } // End if (!LOOP_MAX_arg)
++
++ LOOP_MAX = LOOP_MAX_arg * 10; // 20140325
++ Calculate_LOOP_CheckNum();
++
++ switch (TestMode) {
++ case 0 : BurstEnable = 0; IEEETesting = 0; IOTiming = 0; IOStrength = 0; TxDataEnable = 1; RxDataEnable = 1; DataDelay = 0; break;
++ case 1 : BurstEnable = 1; IEEETesting = 1; IOTiming = 0; IOStrength = 0; TxDataEnable = 1; RxDataEnable = 0; DataDelay = 0; break;
++ case 2 : BurstEnable = 1; IEEETesting = 1; IOTiming = 0; IOStrength = 0; TxDataEnable = 1; RxDataEnable = 0; DataDelay = 0; break;
++ case 3 : BurstEnable = 1; IEEETesting = 1; IOTiming = 0; IOStrength = 0; TxDataEnable = 1; RxDataEnable = 0; DataDelay = 0; break;
++ case 4 : BurstEnable = 1; IEEETesting = 0; IOTiming = 0; IOStrength = 0; TxDataEnable = 1; RxDataEnable = 0; DataDelay = 0; break; // ??
++ case 5 : BurstEnable = 1; IEEETesting = 1; IOTiming = 0; IOStrength = 0; TxDataEnable = 1; RxDataEnable = 0; DataDelay = 0; break; // ??
++ case 6 : if (AST2300) {BurstEnable = 0; IEEETesting = 0; IOTiming = 1; IOStrength = 0; TxDataEnable = 1; RxDataEnable = 1; DataDelay = 0; break;}
++ else
++ goto Error_Test_Mode;
++ case 7 : if (AST2300) {BurstEnable = 0; IEEETesting = 0; IOTiming = 1; IOStrength = 1; TxDataEnable = 1; RxDataEnable = 1; DataDelay = 0; break;}
++ else
++ goto Error_Test_Mode;
++ case 8 : BurstEnable = 0; IEEETesting = 0; IOTiming = 0; IOStrength = 0; TxDataEnable = 1; RxDataEnable = 0; DataDelay = 0; break; // ??
++ case 9 : BurstEnable = 0; IEEETesting = 0; IOTiming = 0; IOStrength = 0; TxDataEnable = 0; RxDataEnable = 1; DataDelay = 0; break; // ??
++ case 10 : BurstEnable = 0; IEEETesting = 0; IOTiming = 0; IOStrength = 0; TxDataEnable = 1; RxDataEnable = 1; DataDelay = 1; break; // ??
++ default:
++Error_Test_Mode:
++ printf ("Error test_mode!!!\n");
++ PrintTest ();
++ return(1);
++ } // End switch (TestMode)
++
++ if ( PHY_ADR > 31 ) {
++ printf ("Error phy_adr!!!\n");
++ PrintPHYAdr ();
++ return(1);
++ } // End if (PHY_ADR > 31)
++ } // End if ( ModeSwitch == MODE_NSCI )
++
++ if ( BurstEnable ) {
++ IOTimingBund = 0;
++ }
++ else {
++ if ( ~DataDelay && AST2300 ) {
++ if ( !( ( (7 >= IOTimingBund) && (IOTimingBund & 0x1) ) ||
++ ( IOTimingBund == 0 ) ) ) {
++ printf ("Error IO margin!!!\n");
++ PrintIOTimingBund ();
++ return(1);
++ }
++ }
++ else {
++ IOTimingBund = 0;
++ } // End if ( ~DataDelay && AST2300 )
++
++ // Define Output file name
++ if ( ModeSwitch == MODE_NSCI )
++ sprintf(FileNameMain, "%d", SelectMAC+1);
++ else {
++ if (Enable_IntLoopPHY)
++ sprintf(FileNameMain, "%dI", SelectMAC+1);
++ else
++ sprintf(FileNameMain, "%dE", SelectMAC+1);
++ }
++
++ #ifndef SLT_UBOOT
++ if ( IOTiming ) {
++ if ( IOStrength )
++ sprintf(FileName, "MIOD%sS.log", FileNameMain);
++ else
++ sprintf(FileName, "MIOD%s.log", FileNameMain);
++
++ fp_log = fopen(FileName,"w");
++
++ if ( IOStrength )
++ sprintf(FileName, "MIO%sS.log", FileNameMain);
++ else
++ sprintf(FileName, "MIO%s.log", FileNameMain);
++
++ fp_io = fopen(FileName,"w");
++ }
++ else {
++ sprintf(FileName, "MAC%s.log", FileNameMain);
++
++ fp_log = fopen(FileName,"w");
++ }
++ #endif
++ } // End if (BurstEnable)
++
++//------------------------------------------------------------
++// Check Definition
++//------------------------------------------------------------
++ for (i = 0; i < 16; i++)
++ valary[i] = Val_Array[i];
++
++ if ( AST3200 ) {
++ MAC_Mode = (SCU_70h_old >> 6) & 0x1;
++ MAC1_1GEn = (MAC_Mode & 0x1) ? 1 : 0;//1:RGMII, 0:RMII
++ MAC2_1GEn = 0;
++
++ MAC1_RMII = !MAC1_1GEn;
++ MAC2_RMII = 0;
++ MAC2_Valid = 0;
++ }
++ else if ( AST1010 ) {
++ MAC_Mode = 0;
++ MAC1_1GEn = 0;
++ MAC2_1GEn = 0;
++
++ MAC1_RMII = 1;
++ MAC2_RMII = 0;
++ MAC2_Valid = 0;
++ }
++ else if ( AST2300 ) {
++ if (SCU_7ch_old == 0x01000003) {
++ //AST2300-A0
++ for (i = 0; i < 16; i++) {
++ valary[i] = Val_Array_A0[i];
++ }
++ }
++
++ MAC_Mode = (SCU_70h_old >> 6) & 0x3;
++ MAC1_1GEn = (MAC_Mode & 0x1) ? 1 : 0;//1:RGMII, 0:RMII
++ MAC2_1GEn = (MAC_Mode & 0x2) ? 1 : 0;//1:RGMII, 0:RMII
++
++ MAC1_RMII = !MAC1_1GEn;
++ MAC2_RMII = !MAC2_1GEn;
++ MAC2_Valid = 1;
++ }
++ else {
++ MAC_Mode = (SCU_70h_old >> 6) & 0x7;
++ MAC1_1GEn = (MAC_Mode == 0x0) ? 1 : 0;
++ MAC2_1GEn = 0;
++
++ switch ( MAC_Mode ) {
++ case 0 : MAC1_RMII = 0; MAC2_RMII = 0; MAC2_Valid = 0; break; //000: Select GMII(MAC#1) only
++ case 1 : MAC1_RMII = 0; MAC2_RMII = 0; MAC2_Valid = 1; break; //001: Select MII (MAC#1) and MII(MAC#2)
++ case 2 : MAC1_RMII = 1; MAC2_RMII = 0; MAC2_Valid = 1; break; //010: Select RMII(MAC#1) and MII(MAC#2)
++ case 3 : MAC1_RMII = 0; MAC2_RMII = 0; MAC2_Valid = 0; break; //011: Select MII (MAC#1) only
++ case 4 : MAC1_RMII = 1; MAC2_RMII = 0; MAC2_Valid = 0; break; //100: Select RMII(MAC#1) only
++// case 5 : MAC1_RMII = 0; MAC2_RMII = 0; MAC2_Valid = 0; break; //101: Reserved
++ case 6 : MAC1_RMII = 1; MAC2_RMII = 1; MAC2_Valid = 1; break; //110: Select RMII(MAC#1) and RMII(MAC#2)
++// case 7 : MAC1_RMII = 0; MAC2_RMII = 0; MAC2_Valid = 0; break; //111: Disable dual MAC
++ default: return(Finish_Check(Err_MACMode));
++ }
++ } // End if ( AST3200 )
++
++ if ( SelectMAC == 0 ) {
++ Enable_RMII = MAC1_RMII;
++ MAC_1GEn = MAC1_1GEn;
++
++ if ( Force1G & !MAC1_1GEn ) {
++ printf ("\nMAC1 don't support 1Gbps !!!\n");
++ return( Finish_Check(Err_MACMode) );
++ }
++ } else if (SelectMAC == 1) {
++ Enable_RMII = MAC2_RMII;
++ MAC_1GEn = MAC2_1GEn;
++
++ if ( Force1G & !MAC2_1GEn ) {
++ printf ("\nMAC2 don't support 1Gbps !!!\n");
++ return(Finish_Check(Err_MACMode));
++ }
++ if ( !MAC2_Valid ) {
++ printf ("\nMAC2 not valid !!!\n");
++ return(Finish_Check(Err_MACMode));
++ }
++ }
++ else {
++ Enable_RMII = 1;
++ MAC_1GEn = 0;
++
++ if (Force1G) {
++ printf ("\nMAC3/MAC4 don't support 1Gbps !!!\n");
++ return(Finish_Check(Err_MACMode));
++ }
++ } // End if ( SelectMAC == 0 )
++
++ if ( ModeSwitch == MODE_NSCI ) {
++ if (!Enable_RMII) {
++ printf ("\nNCSI must be RMII interface !!!\n");
++ return(Finish_Check(Err_MACMode));
++ }
++ }
++
++ if ( GSpeed == SET_1G_100M_10MBPS ) {
++ GSpeed_sel[0] = MAC_1GEn;
++ GSpeed_sel[1] = 1;
++ GSpeed_sel[2] = 1;
++ }
++
++ if ( AST1010 ) {
++ // Check bit 13:12
++ Dat_ULONG = SCU_08h_old & 0x00003000;
++ if (Dat_ULONG != 0x00000000)
++ return(Finish_Check(Err_MHCLK_Ratio));
++ }
++ else if ( AST2300 ) {
++ Dat_ULONG = (SCU_08h_old >> 16) & 0x7;
++ if (MAC1_1GEn | MAC2_1GEn) {
++ if ( (Dat_ULONG == 0) || (Dat_ULONG > 2) )
++ return(Finish_Check(Err_MHCLK_Ratio));
++ }
++ else {
++ if (Dat_ULONG != 4)
++ return(Finish_Check(Err_MHCLK_Ratio));
++ }
++ } // End if (AST1010)
++
++ //MAC
++ MAC_08h_old = ReadSOC_DD( H_MAC_BASE + 0x08 );
++ MAC_0ch_old = ReadSOC_DD( H_MAC_BASE + 0x0c );
++ MAC_40h_old = ReadSOC_DD( H_MAC_BASE + 0x40 );
++
++ if ( ((MAC_08h_old == 0x0000) && (MAC_0ch_old == 0x00000000))
++ || ((MAC_08h_old == 0xffff) && (MAC_0ch_old == 0xffffffff))
++// || (MAC_0ch_old & 0x1)
++// || (MAC_0ch_old & 0x2)
++ )
++ {
++ // Load default for MAC address
++ SA[0] = 0x00;
++ SA[1] = 0x57;
++ SA[2] = 0x89;
++ SA[3] = 0x56;
++ SA[4] = 0x88;
++ SA[5] = 0x38;
++ }
++ else {
++ SA[0] = (MAC_08h_old >> 8) & 0xff;
++ SA[1] = (MAC_08h_old ) & 0xff;
++ SA[2] = (MAC_0ch_old >> 24) & 0xff;
++ SA[3] = (MAC_0ch_old >> 16) & 0xff;
++ SA[4] = (MAC_0ch_old >> 8) & 0xff;
++ SA[5] = (MAC_0ch_old ) & 0xff;
++ }
++ // printf ("%08x %08x: %02x %02x %02x %02x %02x %02x\n", MAC_08h_old, MAC_0ch_old, SA[0], SA[1], SA[2], SA[3], SA[4], SA[5]);
++
++ if ( AST2300 ) {
++#ifdef Force_Enable_NewMDIO
++ AST2300_NewMDIO = 1;
++ WriteSOC_DD(H_MAC_BASE+0x40, MAC_40h_old | 0x80000000)
++#else
++ AST2300_NewMDIO = (MAC_40h_old & 0x80000000) ? 1 : 0;
++#endif
++ }
++ else {
++ AST2300_NewMDIO = 0;
++ } // End if (AST2300)
++
++//------------------------------------------------------------
++// Parameter Initial
++//------------------------------------------------------------
++ if ( AST3200 ) {
++ SCU_04h = 0x0c000800; //Reset Engine
++ }
++ else if (AST1010) {
++ SCU_04h = 0x00000010; //Reset Engine
++ }
++ else if (AST2300) {
++ SCU_04h = 0x0c001800; //Reset Engine
++ }
++ else {
++ SCU_04h = 0x00001800; //Reset Engine
++ } // End if ( AST3200 )
++
++ if ( ModeSwitch == MODE_NSCI )
++ // Set to 100Mbps and Enable RX broabcast packets and CRC_APD and Full duplex
++ MAC_50h = 0x000a0500;
++ else {
++ // RX_ALLADR and CRC_APD and Full duplex
++ MAC_50h = 0x00004500;
++
++ #ifdef Enable_Runt
++ MAC_50h = MAC_50h | 0x00001000;
++ #endif
++
++ #ifdef Enable_Jumbo
++ MAC_50h = MAC_50h | 0x00002000;
++ #endif
++ } // End if ( ModeSwitch == MODE_NSCI )
++
++//------------------------------------------------------------
++// Descriptor Number
++//------------------------------------------------------------
++ if ( ModeSwitch == MODE_DEDICATED ) {
++
++ #ifdef Enable_Jumbo
++ DES_LowNumber = 1;
++ #else
++ DES_LowNumber = IOTiming;
++ #endif
++ if ( Enable_SkipChkPHY && ( TestMode == 0 ) ) {
++ DES_NUMBER = 114;//for SMSC's LAN9303 issue
++ }
++ else {
++ if ( AST1010 | AST3200 ) {
++ DES_NUMBER = (IOTimingBund) ? 100 : 256;
++ }
++ else {
++ switch ( GSpeed ) {
++ case SET_1GBPS : DES_NUMBER = (IOTimingBund) ? 10 : (DES_LowNumber) ? 50 : 400; break; // 20140325
++ case SET_100MBPS : DES_NUMBER = (IOTimingBund) ? 10 : (DES_LowNumber) ? 50 : 400; break; // 20140325
++ case SET_10MBPS : DES_NUMBER = (IOTimingBund) ? 10 : (DES_LowNumber) ? 10 : 80; break; // 20140325
++ case SET_1G_100M_10MBPS : DES_NUMBER = (IOTimingBund) ? 10 : (DES_LowNumber) ? 10 : 80; break; // 20140325
++ }
++ } // End if ( Enable_SkipChkPHY && ( TestMode == 0 ) )
++ }
++
++ #ifdef SelectDesNumber
++ DES_NUMBER = SelectDesNumber;
++ #endif
++
++ #ifdef USE_LPC
++ DES_NUMBER /= 8;
++ #endif
++
++ #ifdef ENABLE_ARP_2_WOL
++ if ( TestMode == 4 ) {
++ DES_NUMBER = 1;
++ }
++ #endif
++
++ DES_NUMBER_Org = DES_NUMBER;
++
++ if ( DbgPrn_Info ) {
++ printf ("CheckBuf_MBSize : %ld\n", CheckBuf_MBSize);
++ printf ("LOOP_CheckNum : %ld\n", LOOP_CheckNum);
++ printf ("DES_NUMBER : %ld\n", DES_NUMBER);
++ printf ("DMA_BufSize : %ld bytes\n", DMA_BufSize);
++ printf ("DMA_BufNum : %d\n", DMA_BufNum);
++ printf ("\n");
++ }
++// if (3 > DMA_BufNum)
++// return( Finish_Check(Err_DMABufNum) );
++
++ if (2 > DMA_BufNum)
++ return( Finish_Check(Err_DMABufNum) );
++ } // End if ( ModeSwitch == MODE_DEDICATED )
++ } // End if (RUN_STEP >= 1)
++
++//------------------------------------------------------------
++// SCU Initial
++//------------------------------------------------------------
++ if ( RUN_STEP >= 2 ) {
++ init_scu1();
++ }
++
++ if ( RUN_STEP >= 3 ) {
++ init_scu_macrst();
++ }
++
++//------------------------------------------------------------
++// Data Initial
++//------------------------------------------------------------
++ if (RUN_STEP >= 4) {
++ setup_arp();
++ if ( ModeSwitch == MODE_DEDICATED ) {
++
++ FRAME_LEN = (ULONG *)malloc(DES_NUMBER * sizeof( ULONG ));
++ wp_lst = (ULONG *)malloc(DES_NUMBER * sizeof( ULONG ));
++
++ if ( !FRAME_LEN )
++ return( Finish_Check( Err_MALLOC_FrmSize ) );
++
++ if ( !wp_lst )
++ return( Finish_Check( Err_MALLOC_LastWP ));
++
++ // Setup data and length
++ TestingSetup();
++ } // End if ( ModeSwitch == MODE_DEDICATED )
++
++ // Get bit (shift) of IO driving strength register
++ if ( IOStrength ) {
++ if (AST1010) {
++ IOStr_max = 1;//0~1
++ }
++ else if (AST2400) {
++ IOStr_max = 1;//0~1
++ switch (SelectMAC) {
++ case 0 : IOStr_shf = 9; break;
++ case 1 : IOStr_shf = 11; break;
++ }
++ }
++ else {
++ IOStr_max = 3;//0~3
++ switch (SelectMAC) {
++ case 0 : IOStr_shf = 8; break;
++ case 1 : IOStr_shf = 10; break;
++ case 2 : IOStr_shf = 12; break;
++ case 3 : IOStr_shf = 14; break;
++ }
++ }
++ }
++ else {
++ IOStr_max = 0;
++ IOStr_shf = 0;
++ } // End if (IOStrength)
++
++ // Get current clock delay value of TX(out) and RX(in) in the SCU48 register
++ // and setting test range
++ if ( Enable_RMII ) {
++ switch (GRun_Mode) {
++ case 0 : IOdly_out_shf = 24; IOdly_in_shf = 8; break;
++ case 1 : IOdly_out_shf = 25; IOdly_in_shf = 12; break;
++ case 2 : IOdly_out_shf = 26; IOdly_in_shf = 16; break;
++ case 3 : IOdly_out_shf = 27; IOdly_in_shf = 20; break;
++ }
++ IOdly_in_reg = (SCU_48h_old >> IOdly_in_shf ) & 0xf;
++ IOdly_out_reg = (SCU_48h_old >> IOdly_out_shf) & 0x1;
++ }
++ else {
++ switch (GRun_Mode) {
++ case 0 : IOdly_out_shf = 0; IOdly_in_shf = 8; break;
++ case 1 : IOdly_out_shf = 4; IOdly_in_shf = 12; break;
++ }
++ IOdly_in_reg = (SCU_48h_old >> IOdly_in_shf ) & 0xf;
++ IOdly_out_reg = (SCU_48h_old >> IOdly_out_shf) & 0xf;
++ } // End if ( Enable_RMII )
++
++ // Find the coordinate in X-Y axis
++ for ( index = 0; index <= 15; index++ )
++ if ( IOdly_in_reg == valary[index] ) {
++ IOdly_in_reg_idx = index;
++ break;
++ }
++ for ( index = 0; index <= 15; index++ )
++ if ( IOdly_out_reg == valary[index] ) {
++ IOdly_out_reg_idx = index;
++ break;
++ }
++
++ // Get the range for testmargin block
++ if ( IOTiming ) {
++ if ( Enable_RMII ) {
++ IOdly_incval = 1;
++ IOdly_in_str = 0;
++ IOdly_in_end = 15;
++ IOdly_out_str = 0;
++ IOdly_out_end = 1;
++ }
++ else {
++ IOdly_incval = 1;
++ IOdly_in_str = 0;
++ IOdly_in_end = 15;
++ IOdly_out_str = 0;
++ IOdly_out_end = 15;
++ }
++ }
++ else if ( IOTimingBund ) {
++ if ( Enable_RMII ) {
++ IOdly_incval = 1;
++ IOdly_in_str = IOdly_in_reg_idx - ( IOTimingBund >> 1 );
++ IOdly_in_end = IOdly_in_reg_idx + ( IOTimingBund >> 1 );
++ IOdly_out_str = IOdly_out_reg_idx;
++ IOdly_out_end = IOdly_out_reg_idx;
++ }
++ else {
++ IOdly_incval = 1;
++ IOdly_in_str = IOdly_in_reg_idx - ( IOTimingBund >> 1 );
++ IOdly_in_end = IOdly_in_reg_idx + ( IOTimingBund >> 1 );
++ IOdly_out_str = IOdly_out_reg_idx - ( IOTimingBund >> 1 );
++ IOdly_out_end = IOdly_out_reg_idx + ( IOTimingBund >> 1 );
++ }
++ if ((IOdly_in_str < 0) || (IOdly_in_end > 15))
++ return( Finish_Check( Err_IOMarginOUF ) );
++
++ if ((IOdly_out_str < 0) || (IOdly_out_end > 15))
++ return( Finish_Check( Err_IOMarginOUF ) );
++
++// if (IOdly_in_str < 0) IOdly_in_str = 0;
++// if (IOdly_in_end > 15) IOdly_in_end = 15;
++// if (IOdly_out_str < 0) IOdly_out_str = 0;
++// if (IOdly_out_end > 15) IOdly_out_end = 15;
++ }
++ else {
++ IOdly_incval = 1;
++ IOdly_in_str = 0;
++ IOdly_in_end = 0;
++ IOdly_out_str = 0;
++ IOdly_out_end = 0;
++ } // End if (IOTiming)
++ } // End if (RUN_STEP >= 4)
++
++//------------------------------------------------------------
++// main
++//------------------------------------------------------------
++ if (RUN_STEP >= 5) {
++ #ifdef DbgPrn_FuncHeader
++ printf ("GSpeed_sel: %d %d %d\n", GSpeed_sel[0], GSpeed_sel[1], GSpeed_sel[2]);
++ Debug_delay();
++ #endif
++
++ if ( ModeSwitch == MODE_NSCI ) {
++ #ifdef Enable_NCSI_LOOP_INFINI
++ for ( GSpeed_idx = 0; GSpeed_idx < 3; GSpeed_idx++ ) {
++ GSpeed_org[GSpeed_idx] = GSpeed_sel[GSpeed_idx];
++ }
++NCSI_LOOP_INFINI:;
++ for ( GSpeed_idx = 0; GSpeed_idx < 3; GSpeed_idx++ ) {
++ GSpeed_sel[GSpeed_idx] = GSpeed_org[GSpeed_idx];
++ }
++ #endif
++ } // End if ( ModeSwitch == MODE_NSCI )
++
++ for (GSpeed_idx = 0; GSpeed_idx < 3; GSpeed_idx++) {
++ Err_Flag_PrintEn = 1;
++ if ( GSpeed_sel[GSpeed_idx] ) {
++ // Setting the LAN speed
++ if ( ModeSwitch == MODE_DEDICATED ) {
++
++
++ // Test three speed of LAN, we will modify loop number
++ if (GSpeed == SET_1G_100M_10MBPS) {
++ if (GSpeed_sel[0]) LOOP_MAX = LOOP_MAX_arg;
++ else if (GSpeed_sel[1]) LOOP_MAX = LOOP_MAX_arg / 10;
++ else LOOP_MAX = LOOP_MAX_arg / 100;
++
++ if ( !LOOP_MAX )
++ LOOP_MAX = 1;
++
++ Calculate_LOOP_CheckNum();
++ }
++
++ // Setting speed of LAN
++ if (GSpeed_sel[0]) MAC_50h_Speed = 0x00000200;
++ else if (GSpeed_sel[1]) MAC_50h_Speed = 0x00080000;
++ else MAC_50h_Speed = 0x00000000;
++
++ //------------------------------------------------------------
++ // PHY Initial
++ //------------------------------------------------------------
++ if ( AST1100 )
++ init_scu2();
++
++ if ( Enable_InitPHY ) {
++#ifdef SUPPORT_PHY_LAN9303
++ LAN9303(LAN9303_I2C_BUSNUM, PHY_ADR_arg, GSpeed_idx, Enable_IntLoopPHY | (BurstEnable<<1) | IEEETesting);
++#else
++ init_phy( Enable_IntLoopPHY );
++#endif
++ DELAY( Delay_PHYRst * 10 );
++ } // End if (Enable_InitPHY)
++
++ if ( AST1100 )
++ init_scu3();
++
++ if ( Err_Flag )
++ return( Finish_Check( 0 ) );
++ } // End if ( ModeSwitch == MODE_DEDICATED )
++
++ //------------------------------------------------------------
++ // Start
++ //------------------------------------------------------------
++
++ // The loop is for different IO strength
++ for ( IOStr_i = 0; IOStr_i <= IOStr_max; IOStr_i++ ) {
++
++ // Print Header of report to monitor and log file
++ if ( IOTiming || IOTimingBund ) {
++ if ( IOStrength ) {
++ if ( AST1010 ) {
++ IOStr_val = (SCU_ach_old & 0xfff0ffff) | ((IOStr_i) ? 0xf0000 : 0x0);
++ }
++ else {
++ IOStr_val = (SCU_90h_old & 0xffff00ff) | (IOStr_i << IOStr_shf);
++ }
++ //printf("\nIOStrength_val= %08x, ", IOStr_val);
++ //printf("SCU90h: %08x ->", ReadSOC_DD(SCU_BASE+0x90));
++ WriteSOC_DD( SCU_BASE + 0x90, IOStr_val );
++ //printf(" %08x\n", ReadSOC_DD(SCU_BASE+0x90));
++
++ #ifndef SLT_UBOOT
++ if (GSpeed_sel[0]) fprintf(fp_log, "[Strength %d][1G ]========================================\n", IOStr_i);
++ else if (GSpeed_sel[1]) fprintf(fp_log, "[Strength %d][100M]========================================\n", IOStr_i);
++ else fprintf(fp_log, "[Strength %d][10M ]========================================\n", IOStr_i);
++ #endif
++ }
++ else {
++ #ifndef SLT_UBOOT
++ if (GSpeed_sel[0]) fprintf(fp_log, "[1G ]========================================\n");
++ else if (GSpeed_sel[1]) fprintf(fp_log, "[100M]========================================\n");
++ else fprintf(fp_log, "[10M ]========================================\n");
++ #endif
++ }
++
++ if ( IOTimingBund )
++ PrintIO_Header(FP_LOG);
++ if ( IOTiming )
++ PrintIO_Header(FP_IO);
++
++ PrintIO_Header(STD_OUT);
++
++ }
++ else {
++ if ( ModeSwitch == MODE_DEDICATED ) {
++
++ if (!BurstEnable)
++ Print_Header(FP_LOG);
++
++ Print_Header(STD_OUT);
++ }
++ } // End if (IOTiming || IOTimingBund)
++
++#ifdef Enable_Old_Style
++ for (IOdly_i = IOdly_in_str; IOdly_i <= IOdly_in_end; IOdly_i+=IOdly_incval) {
++ IOdly_in = valary[IOdly_i];
++#else
++ for (IOdly_j = IOdly_out_str; IOdly_j <= IOdly_out_end; IOdly_j+=IOdly_incval) {
++ IOdly_out = valary[IOdly_j];
++#endif
++
++ if (IOTiming || IOTimingBund) {
++#ifdef Enable_Fast_SCU
++ #ifdef Enable_Old_Style
++ WriteSOC_DD(SCU_BASE + 0x48, SCU_48h_mix | (IOdly_in << IOdly_in_shf));
++ #else
++ WriteSOC_DD(SCU_BASE + 0x48, SCU_48h_mix | (IOdly_out << IOdly_out_shf));
++ #endif
++#endif
++
++ if ( IOTimingBund )
++ PrintIO_LineS(FP_LOG);
++ if ( IOTiming )
++ PrintIO_LineS(FP_IO);
++
++ PrintIO_LineS(STD_OUT);
++ } // End if (IOTiming || IOTimingBund)
++
++ //------------------------------------------------------------
++ // SCU Initial
++ //------------------------------------------------------------
++#ifdef Enable_Fast_SCU
++ init_scu_macrst();
++#endif
++#ifdef Enable_Old_Style
++ for (IOdly_j = IOdly_out_str; IOdly_j <= IOdly_out_end; IOdly_j+=IOdly_incval) {
++ IOdly_out = valary[IOdly_j];
++#else
++ for (IOdly_i = IOdly_in_str; IOdly_i <= IOdly_in_end; IOdly_i+=IOdly_incval) {
++ IOdly_in = valary[IOdly_i];
++#endif
++ if ( IOTiming || IOTimingBund ) {
++ IOdly_val = (IOdly_in << IOdly_in_shf) | (IOdly_out << IOdly_out_shf);
++
++//printf("\nIOdly_val= %08x, ", IOdly_val);
++//printf("SCU48h: %08x ->", ReadSOC_DD( SCU_BASE + 0x48 ) );
++ WriteSOC_DD( SCU_BASE + 0x48, SCU_48h_mix | IOdly_val );
++//printf(" %08x\n", ReadSOC_DD(SCU_BASE+0x48));
++ } // End if (IOTiming || IOTimingBund)
++
++ //------------------------------------------------------------
++ // SCU Initial
++ //------------------------------------------------------------
++#ifdef Enable_Fast_SCU
++#else
++ init_scu_macrst();
++#endif
++
++ //------------------------------------------------------------
++ // MAC Initial
++ //------------------------------------------------------------
++ init_mac(H_MAC_BASE, H_TDES_BASE, H_RDES_BASE);
++ if ( Err_Flag )
++ return( Finish_Check(0) );
++
++ // Testing
++ if ( ModeSwitch == MODE_NSCI )
++ dlymap[IOdly_i][IOdly_j] = phy_ncsi();
++ else
++ dlymap[IOdly_i][IOdly_j] = TestingLoop(LOOP_CheckNum);
++
++
++ // Display to Log file and monitor
++ if ( IOTiming || IOTimingBund ) {
++
++ if ( IOTimingBund )
++ PrintIO_Line(FP_LOG);
++
++ if ( IOTiming )
++ PrintIO_Line(FP_IO);
++
++ PrintIO_Line(STD_OUT);
++
++ // Find the range of current setting
++ if ( ( IOdly_in_reg == IOdly_in ) && ( IOdly_out_reg == IOdly_out ) ) {
++ IOdly_i_min = IOdly_i - ( IOTimingBund >> 1 );
++ IOdly_i_max = IOdly_i + ( IOTimingBund >> 1 );
++
++ if ( Enable_RMII ) {
++ IOdly_j_min = IOdly_j;
++ IOdly_j_max = IOdly_j;
++ }
++ else {
++ IOdly_j_min = IOdly_j - (IOTimingBund >> 1 );
++ IOdly_j_max = IOdly_j + (IOTimingBund >> 1 );
++ }
++ }
++
++ PrintIO_Line_LOG();
++ FPri_ErrFlag(FP_LOG);
++
++// Err_Flag_allapeed = Err_Flag_allapeed | Err_Flag;
++ Err_Flag = 0;
++ }
++ }// End for (IOdly_j = IOdly_out_str; IOdly_j <= IOdly_out_end; IOdly_j+=IOdly_incval)
++#ifndef SLT_UBOOT
++ if ( IOTiming || IOTimingBund ) {
++ if ( IOTimingBund )
++ fprintf(fp_log, "\n");
++ if (IOTiming )
++ fprintf(fp_io, "\n");
++ }
++#endif
++ printf("\n");
++ } // End for (IOdly_j = IOdly_out_str; IOdly_j <= IOdly_out_end; IOdly_j+=IOdly_incval)
++
++ //------------------------------------------------------------
++ // End
++ //------------------------------------------------------------
++
++ if ( IOTiming || IOTimingBund ) {
++ if ( ( IOdly_i_min < 0 ) || ( IOdly_i_max > 15 ) )
++ FindErr(Err_IOMarginOUF);
++ if ( ( IOdly_j_min < 0 ) || ( IOdly_j_max > 15 ) )
++ FindErr(Err_IOMarginOUF);
++
++ if ( IOdly_i_min < 0 ) IOdly_i_min = 0;
++ if ( IOdly_i_max > 15 ) IOdly_i_max = 15;
++ if ( IOdly_j_min < 0 ) IOdly_j_min = 0;
++ if ( IOdly_j_max > 15 ) IOdly_j_max = 15;
++
++#ifdef Enable_Old_Style
++ for (IOdly_i = IOdly_i_min; IOdly_i <= IOdly_i_max; IOdly_i++)
++ for (IOdly_j = IOdly_j_min; IOdly_j <= IOdly_j_max; IOdly_j++)
++#else
++ for (IOdly_j = IOdly_j_min; IOdly_j <= IOdly_j_max; IOdly_j++)
++ for (IOdly_i = IOdly_i_min; IOdly_i <= IOdly_i_max; IOdly_i++)
++#endif
++ {
++ if ( dlymap[IOdly_i][IOdly_j] ) {
++#ifdef SLT_DOS
++ if ( IOTiming ) {
++#ifdef Enable_Old_Style
++ for (i = IOdly_i_min; i <= IOdly_i_max; i++)
++#else
++ for (j = IOdly_j_min; j <= IOdly_j_max; j++)
++#endif
++ {
++#ifdef Enable_Old_Style
++ for (j = IOdly_j_min; j <= IOdly_j_max; j++)
++#else
++ for (i = IOdly_i_min; i <= IOdly_i_max; i++)
++#endif
++ {
++ if (dlymap[i][j]) fprintf(fp_io, "x ");
++ else fprintf(fp_io, "o ");
++ }
++ fprintf(fp_io, "\n");
++ }
++ } // End if ( IOTiming )
++#endif // End SLT_DOS
++ FindErr(Err_IOMargin);
++ goto Find_Err_IOMargin;
++ } // End if ( dlymap[IOdly_i][IOdly_j] )
++ }
++ } // End if ( IOTiming || IOTimingBund )
++
++Find_Err_IOMargin:;
++ if ( !BurstEnable )
++ FPri_ErrFlag(FP_LOG);
++ if ( IOTiming )
++ FPri_ErrFlag(FP_IO);
++
++ FPri_ErrFlag(STD_OUT);
++
++ Err_Flag_allapeed = Err_Flag_allapeed | Err_Flag;
++ Err_Flag = 0;
++ } // End for (IOStr_i = 0; IOStr_i <= IOStr_max; IOStr_i++)
++
++ if ( ModeSwitch == MODE_DEDICATED ) {
++ if ( Enable_InitPHY & !Disable_RecovPHY )
++ recov_phy(Enable_IntLoopPHY);
++ }
++
++ GSpeed_sel[GSpeed_idx] = 0;
++ } // End if (GSpeed_sel[GSpeed_idx])
++
++ Err_Flag_PrintEn = 0;
++ } // End for (GSpeed_idx = 0; GSpeed_idx < 3; GSpeed_idx++)
++
++ Err_Flag = Err_Flag_allapeed;
++
++ if ( ModeSwitch == MODE_NSCI ) {
++ #ifdef Enable_NCSI_LOOP_INFINI
++ if (Err_Flag == 0) {
++ if (fp_log) {
++ fclose(fp_log);
++ fp_log = fopen(FileName,"w");
++ }
++ goto NCSI_LOOP_INFINI;
++ }
++ #endif
++ }
++
++ } // End if (RUN_STEP >= 5)
++
++ return(Finish_Check(0));
++
++}
++
+diff --git a/arch/arm/cpu/arm926ejs/aspeed/reset.c b/arch/arm/cpu/arm926ejs/aspeed/reset.c
+new file mode 100644
+index 0000000..e0a57f9
+--- /dev/null
++++ b/arch/arm/cpu/arm926ejs/aspeed/reset.c
+@@ -0,0 +1,24 @@
++/*
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++*/
++
++#include <common.h>
++#include <asm/io.h>
++
++#define AST_WDT_BASE 0x1e785000
++void reset_cpu(ulong addr)
++{
++ __raw_writel(0x10 , AST_WDT_BASE+0x04);
++ __raw_writel(0x4755, AST_WDT_BASE+0x08);
++ __raw_writel(0x3, AST_WDT_BASE+0x0c);
++
++ while (1)
++ /*nothing*/;
++}
+diff --git a/arch/arm/cpu/arm926ejs/aspeed/timer.c b/arch/arm/cpu/arm926ejs/aspeed/timer.c
+new file mode 100644
+index 0000000..4bba5c5
+--- /dev/null
++++ b/arch/arm/cpu/arm926ejs/aspeed/timer.c
+@@ -0,0 +1,153 @@
++/*
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License as
++ * published by the Free Software Foundation; either version 2 of
++ * the License, or (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
++ * MA 02111-1307 USA
++ */
++
++#include <common.h>
++#include <arm926ejs.h>
++
++#define TIMER_LOAD_VAL 0xffffffff
++
++/* macro to read the 32 bit timer */
++#define READ_TIMER (*(volatile ulong *)(CONFIG_SYS_TIMERBASE+0))
++
++static ulong timestamp;
++static ulong lastdec;
++
++int timer_init (void)
++{
++ *(volatile ulong *)(CONFIG_SYS_TIMERBASE + 4) = TIMER_LOAD_VAL;
++ *(volatile ulong *)(CONFIG_SYS_TIMERBASE + 0x30) = 0x3; /* enable timer1 */
++
++ /* init the timestamp and lastdec value */
++ reset_timer_masked();
++
++ return 0;
++}
++
++/*
++ * timer without interrupts
++ */
++
++void reset_timer (void)
++{
++ reset_timer_masked ();
++}
++
++ulong get_timer (ulong base)
++{
++ return get_timer_masked () - base;
++}
++
++void set_timer (ulong t)
++{
++ timestamp = t;
++}
++
++/* delay x useconds AND perserve advance timstamp value */
++void udelay (unsigned long usec)
++{
++ ulong tmo, tmp;
++
++ if(usec >= 1000){ /* if "big" number, spread normalization to seconds */
++ tmo = usec / 1000; /* start to normalize for usec to ticks per sec */
++ tmo *= CONFIG_SYS_HZ; /* find number of "ticks" to wait to achieve target */
++ tmo /= 1000; /* finish normalize. */
++ }else{ /* else small number, don't kill it prior to HZ multiply */
++ tmo = usec * CONFIG_SYS_HZ;
++ tmo /= (1000*1000);
++ }
++
++ tmp = get_timer (0); /* get current timestamp */
++ if( (tmo + tmp + 1) < tmp ) /* if setting this fordward will roll time stamp */
++ reset_timer_masked (); /* reset "advancing" timestamp to 0, set lastdec value */
++ else
++ tmo += tmp; /* else, set advancing stamp wake up time */
++
++ while (get_timer_masked () < tmo)/* loop till event */
++ /*NOP*/;
++}
++
++void reset_timer_masked (void)
++{
++ /* reset time */
++ lastdec = READ_TIMER; /* capure current decrementer value time */
++ timestamp = 0; /* start "advancing" time stamp from 0 */
++}
++
++ulong get_timer_masked (void)
++{
++ ulong now = READ_TIMER; /* current tick value */
++
++ if (lastdec >= now) { /* normal mode (non roll) */
++ /* normal mode */
++ timestamp += lastdec - now; /* move stamp fordward with absoulte diff ticks */
++ } else { /* we have overflow of the count down timer */
++ /* nts = ts + ld + (TLV - now)
++ * ts=old stamp, ld=time that passed before passing through -1
++ * (TLV-now) amount of time after passing though -1
++ * nts = new "advancing time stamp"...it could also roll and cause problems.
++ */
++ timestamp += lastdec + TIMER_LOAD_VAL - now;
++ }
++ lastdec = now;
++
++ return timestamp;
++}
++
++/* waits specified delay value and resets timestamp */
++void udelay_masked (unsigned long usec)
++{
++ ulong tmo;
++ ulong endtime;
++ signed long diff;
++
++ if (usec >= 1000) { /* if "big" number, spread normalization to seconds */
++ tmo = usec / 1000; /* start to normalize for usec to ticks per sec */
++ tmo *= CONFIG_SYS_HZ; /* find number of "ticks" to wait to achieve target */
++ tmo /= 1000; /* finish normalize. */
++ } else { /* else small number, don't kill it prior to HZ multiply */
++ tmo = usec * CONFIG_SYS_HZ;
++ tmo /= (1000*1000);
++ }
++
++ endtime = get_timer_masked () + tmo;
++
++ do {
++ ulong now = get_timer_masked ();
++ diff = endtime - now;
++ } while (diff >= 0);
++}
++
++/*
++ * This function is derived from PowerPC code (read timebase as long long).
++ * On ARM it just returns the timer value.
++ */
++unsigned long long get_ticks(void)
++{
++ return get_timer(0);
++}
++
++/*
++ * This function is derived from PowerPC code (timebase clock frequency).
++ * On ARM it returns the number of timer ticks per second.
++ */
++ulong get_tbclk (void)
++{
++ ulong tbclk;
++
++ tbclk = CONFIG_SYS_HZ;
++ return tbclk;
++}
+diff --git a/arch/arm/include/asm/arch-aspeed/aspeed_i2c.h b/arch/arm/include/asm/arch-aspeed/aspeed_i2c.h
+new file mode 100644
+index 0000000..5419fca
+--- /dev/null
++++ b/arch/arm/include/asm/arch-aspeed/aspeed_i2c.h
+@@ -0,0 +1,69 @@
++/*
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++ */
++#if defined(CONFIG_AST1300)
++#define SCU_BASE CONFIG_SCUREG_BASE
++#define I2C_BASE CONFIG_I2CREG_BASE
++#define I2C_CHANNEL CONFIG_I2C_CHANNEL
++#else
++#define SCU_BASE 0x1E6E2000
++#define I2C_BASE 0x1E78A000
++/* Cause U-boot i2c command limitation, it can't assign channel number. Our EEPROM is at channel 3 now*/
++/* AST2200's EEPROM is at channel 4 */
++#if defined(CONFIG_AST2200) || defined(CONFIG_AST2300) || defined(CONFIG_AST2400)
++#define I2C_CHANNEL 4
++#else
++#define I2C_CHANNEL 3
++#endif
++#endif
++
++/* Fix timing for EEPROM 100Khz*/
++#define AC_TIMING 0x77743335
++#define ALL_CLEAR 0xFFFFFFFF
++#define MASTER_ENABLE 0x01
++#define SLAVE_ENABLE 0x02
++#define LOOP_COUNT 0x100000
++#define SCU_RESET_CONTROL 0x04
++#define SCU_MULTIFUNCTION_PIN_CTL5_REG 0x90
++
++/* I2C Register */
++#define I2C_FUNCTION_CONTROL_REGISTER (I2C_BASE + I2C_CHANNEL * 0x40 + 0x00)
++#define I2C_AC_TIMING_REGISTER_1 (I2C_BASE + I2C_CHANNEL * 0x40 + 0x04)
++#define I2C_AC_TIMING_REGISTER_2 (I2C_BASE + I2C_CHANNEL * 0x40 + 0x08)
++#define I2C_INTERRUPT_CONTROL_REGISTER (I2C_BASE + I2C_CHANNEL * 0x40 + 0x0c)
++#define I2C_INTERRUPT_STATUS_REGISTER (I2C_BASE + I2C_CHANNEL * 0x40 + 0x10)
++#define I2C_COMMAND_REGISTER (I2C_BASE + I2C_CHANNEL * 0x40 + 0x14)
++#define I2C_DEVICE_ADDRESS_REGISTER (I2C_BASE + I2C_CHANNEL * 0x40 + 0x18)
++#define I2C_BUFFER_CONTROL_REGISTER (I2C_BASE + I2C_CHANNEL * 0x40 + 0x1c)
++#define I2C_BYTE_BUFFER_REGISTER (I2C_BASE + I2C_CHANNEL * 0x40 + 0x20)
++#define I2C_DMA_CONTROL_REGISTER (I2C_BASE + I2C_CHANNEL * 0x40 + 0x24)
++#define I2C_DMA_STATUS_REGISTER (I2C_BASE + I2C_CHANNEL * 0x40 + 0x28)
++
++/* Command Bit */
++#define MASTER_START_COMMAND (1 << 0)
++#define MASTER_TX_COMMAND (1 << 1)
++#define MASTER_RX_COMMAND (1 << 3)
++#define RX_COMMAND_LIST (1 << 4)
++#define MASTER_STOP_COMMAND (1 << 5)
++
++/* Interrupt Status Bit */
++#define TX_ACK (1 << 0)
++#define TX_NACK (1 << 1)
++#define RX_DONE (1 << 2)
++#define STOP_DONE (1 << 4)
++
++/* Macros to access registers */
++#define outb(v,p) *(volatile u8 *) (p) = v
++#define outw(v,p) *(volatile u16 *) (p) = v
++#define outl(v,p) *(volatile u32 *) (p) = v
++
++#define inb(p) *(volatile u8 *) (p)
++#define inw(p) *(volatile u16 *) (p)
++#define inl(p) *(volatile u32 *) (p)
+diff --git a/arch/arm/include/asm/mach-types.h b/arch/arm/include/asm/mach-types.h
+index 440b041..48fcf2b 100644
+--- a/arch/arm/include/asm/mach-types.h
++++ b/arch/arm/include/asm/mach-types.h
+@@ -175,6 +175,16 @@ extern unsigned int __machine_arch_type;
+ #define MACH_TYPE_PALMTX 885
+ #define MACH_TYPE_S3C2413 887
+ #define MACH_TYPE_WG302V2 890
++#define MACH_TYPE_AST1100 903
++#define MACH_TYPE_AST2000 900
++#define MACH_TYPE_AST2100 902
++#define MACH_TYPE_AST2150 907
++#define MACH_TYPE_AST2200 906
++#define MACH_TYPE_AST2300_FPGA_1 901
++#define MACH_TYPE_AST2300_FPGA_2 901
++#define MACH_TYPE_AST2300 901
++#define MACH_TYPE_AST3100 901
++#define MACH_TYPE_ASPEED 8888
+ #define MACH_TYPE_OMAP_2430SDP 900
+ #define MACH_TYPE_DAVINCI_EVM 901
+ #define MACH_TYPE_PALMZ72 904
+@@ -840,7 +850,6 @@ extern unsigned int __machine_arch_type;
+ #define MACH_TYPE_NV1000 3218
+ #define MACH_TYPE_NUC950TS 3219
+ #define MACH_TYPE_NOKIA_RM680 3220
+-#define MACH_TYPE_AST2200 3221
+ #define MACH_TYPE_LEAD 3222
+ #define MACH_TYPE_UNINO1 3223
+ #define MACH_TYPE_GREECO 3224
+@@ -3063,6 +3072,126 @@ extern unsigned int __machine_arch_type;
+ # define machine_is_wg302v2() (0)
+ #endif
+
++#ifdef CONFIG_MACH_AST1100
++# ifdef machine_arch_type
++# undef machine_arch_type
++# define machine_arch_type __machine_arch_type
++# else
++# define machine_arch_type MACH_TYPE_AST1100
++# endif
++# define machine_is_ast1100() (machine_arch_type == MACH_TYPE_AST1100)
++#else
++# define machine_is_ast1100() (0)
++#endif
++
++#ifdef CONFIG_MACH_AST2000
++# ifdef machine_arch_type
++# undef machine_arch_type
++# define machine_arch_type __machine_arch_type
++# else
++# define machine_arch_type MACH_TYPE_AST2000
++# endif
++# define machine_is_ast2000() (machine_arch_type == MACH_TYPE_AST2000)
++#else
++# define machine_is_ast2000() (0)
++#endif
++
++#ifdef CONFIG_MACH_AST2100
++# ifdef machine_arch_type
++# undef machine_arch_type
++# define machine_arch_type __machine_arch_type
++# else
++# define machine_arch_type MACH_TYPE_AST2100
++# endif
++# define machine_is_ast2100() (machine_arch_type == MACH_TYPE_AST2100)
++#else
++# define machine_is_ast2100() (0)
++#endif
++
++#ifdef CONFIG_MACH_AST2150
++# ifdef machine_arch_type
++# undef machine_arch_type
++# define machine_arch_type __machine_arch_type
++# else
++# define machine_arch_type MACH_TYPE_AST2150
++# endif
++# define machine_is_ast2150() (machine_arch_type == MACH_TYPE_AST2150)
++#else
++# define machine_is_ast2150() (0)
++#endif
++
++#ifdef CONFIG_MACH_AST2200
++# ifdef machine_arch_type
++# undef machine_arch_type
++# define machine_arch_type __machine_arch_type
++# else
++# define machine_arch_type MACH_TYPE_AST2200
++# endif
++# define machine_is_ast2200() (machine_arch_type == MACH_TYPE_AST2200)
++#else
++# define machine_is_ast2200() (0)
++#endif
++
++#ifdef CONFIG_MACH_AST2300_FPGA_1
++# ifdef machine_arch_type
++# undef machine_arch_type
++# define machine_arch_type __machine_arch_type
++# else
++# define machine_arch_type MACH_TYPE_AST2300_FPGA_1
++# endif
++# define machine_is_ast2300_fpga_1() (machine_arch_type == MACH_TYPE_AST2300_FPGA_1)
++#else
++# define machine_is_ast2300_fpga_1() (0)
++#endif
++
++#ifdef CONFIG_MACH_AST2300_FPGA_2
++# ifdef machine_arch_type
++# undef machine_arch_type
++# define machine_arch_type __machine_arch_type
++# else
++# define machine_arch_type MACH_TYPE_AST2300_FPGA_2
++# endif
++# define machine_is_ast2300_fpga_2() (machine_arch_type == MACH_TYPE_AST2300_FPGA_2)
++#else
++# define machine_is_ast2300_fpga_2() (0)
++#endif
++
++#ifdef CONFIG_MACH_AST3100
++# ifdef machine_arch_type
++# undef machine_arch_type
++# define machine_arch_type __machine_arch_type
++# else
++# define machine_arch_type MACH_TYPE_AST3100
++# endif
++# define machine_is_ast3100() (machine_arch_type == MACH_TYPE_AST3100)
++#else
++# define machine_is_ast3100() (0)
++#endif
++
++#ifdef CONFIG_MACH_ASPEED
++# ifdef machine_arch_type
++# undef machine_arch_type
++# define machine_arch_type __machine_arch_type
++# else
++# define machine_arch_type MACH_TYPE_ASPEED
++# endif
++# define machine_is_aspeed() (machine_arch_type == MACH_TYPE_ASPEED)
++#else
++# define machine_is_aspeed() (0)
++#endif
++
++#ifdef CONFIG_MACH_AST2300
++# ifdef machine_arch_type
++# undef machine_arch_type
++# define machine_arch_type __machine_arch_type
++# else
++# define machine_arch_type MACH_TYPE_AST2300
++# endif
++# define machine_is_ast2300() (machine_arch_type == MACH_TYPE_AST2300)
++#else
++# define machine_is_ast2300() (0)
++#endif
++
+ #ifdef CONFIG_MACH_OMAP_2430SDP
+ # ifdef machine_arch_type
+ # undef machine_arch_type
+@@ -11043,18 +11172,6 @@ extern unsigned int __machine_arch_type;
+ # define machine_is_nokia_rm680() (0)
+ #endif
+
+-#ifdef CONFIG_MACH_AST2200
+-# ifdef machine_arch_type
+-# undef machine_arch_type
+-# define machine_arch_type __machine_arch_type
+-# else
+-# define machine_arch_type MACH_TYPE_AST2200
+-# endif
+-# define machine_is_ast2200() (machine_arch_type == MACH_TYPE_AST2200)
+-#else
+-# define machine_is_ast2200() (0)
+-#endif
+-
+ #ifdef CONFIG_MACH_LEAD
+ # ifdef machine_arch_type
+ # undef machine_arch_type
+diff --git a/board/aspeed/ast2300/Makefile b/board/aspeed/ast2300/Makefile
+new file mode 100644
+index 0000000..d5300e6
+--- /dev/null
++++ b/board/aspeed/ast2300/Makefile
+@@ -0,0 +1,42 @@
++# This program is distributed in the hope that it will be useful,
++# but WITHOUT ANY WARRANTY; without even the implied warranty of
++# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++# GNU General Public License for more details.
++#
++# You should have received a copy of the GNU General Public License
++# along with this program; if not, write to the Free Software
++# Foundation, Inc., 59 Temple Place, Suite 330, Boston,
++# MA 02111-1307 USA
++#
++
++include $(TOPDIR)/config.mk
++
++LIB = $(obj)lib$(BOARD).a
++
++COBJS = ast2300.o flash.o flash_spi.o pci.o crc32.o slt.o regtest.o vfun.o vhace.o crt.o videotest.o mactest.o hactest.o mictest.o
++
++ifdef CONFIG_FPGA_ASPEED
++SOBJS := platform_fpga.o
++else
++SOBJS := platform.o
++endif
++
++SRCS := $(SOBJS:.o=.S) $(COBJS:.o=.c)
++OBJS := $(addprefix $(obj),$(COBJS))
++SOBJS := $(addprefix $(obj),$(SOBJS))
++
++$(LIB): $(obj).depend $(OBJS) $(SOBJS)
++ $(AR) $(ARFLAGS) $@ $(OBJS) $(SOBJS)
++
++clean:
++ rm -f $(SOBJS) $(OBJS)
++
++distclean: clean
++ rm -f $(LIB) core *.bak $(obj).depend
++
++# defines $(obj).depend target
++include $(SRCTREE)/rules.mk
++
++sinclude .depend
++
++#########################################################################
+diff --git a/board/aspeed/ast2300/aes.c b/board/aspeed/ast2300/aes.c
+new file mode 100755
+index 0000000..f30ab99
+--- /dev/null
++++ b/board/aspeed/ast2300/aes.c
+@@ -0,0 +1,573 @@
++/*
++ * AES implementation
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++ */
++
++/* uncomment the following line to run the test suite */
++
++/* #define TEST */
++
++/* uncomment the following line to use pre-computed tables */
++/* otherwise the tables will be generated at the first run */
++
++#define FIXED_TABLES
++
++#ifndef FIXED_TABLES
++
++/* forward S-box & tables */
++
++uint32 FSb[256];
++uint32 FT0[256];
++uint32 FT1[256];
++uint32 FT2[256];
++uint32 FT3[256];
++
++/* reverse S-box & tables */
++
++uint32 RSb[256];
++uint32 RT0[256];
++uint32 RT1[256];
++uint32 RT2[256];
++uint32 RT3[256];
++
++/* round constants */
++
++uint32 RCON[10];
++
++/* tables generation flag */
++
++int do_init = 1;
++
++/* tables generation routine */
++
++#define ROTR8(x) ( ( ( x << 24 ) & 0xFFFFFFFF ) | \
++ ( ( x & 0xFFFFFFFF ) >> 8 ) )
++
++#define XTIME(x) ( ( x << 1 ) ^ ( ( x & 0x80 ) ? 0x1B : 0x00 ) )
++#define MUL(x,y) ( ( x && y ) ? pow[(log[x] + log[y]) % 255] : 0 )
++
++void aes_gen_tables( void )
++{
++ int i;
++ uint8 x, y;
++ uint8 pow[256];
++ uint8 log[256];
++
++ /* compute pow and log tables over GF(2^8) */
++
++ for( i = 0, x = 1; i < 256; i++, x ^= XTIME( x ) )
++ {
++ pow[i] = x;
++ log[x] = i;
++ }
++
++ /* calculate the round constants */
++
++ for( i = 0, x = 1; i < 10; i++, x = XTIME( x ) )
++ {
++ RCON[i] = (uint32) x << 24;
++ }
++
++ /* generate the forward and reverse S-boxes */
++
++ FSb[0x00] = 0x63;
++ RSb[0x63] = 0x00;
++
++ for( i = 1; i < 256; i++ )
++ {
++ x = pow[255 - log[i]];
++
++ y = x; y = ( y << 1 ) | ( y >> 7 );
++ x ^= y; y = ( y << 1 ) | ( y >> 7 );
++ x ^= y; y = ( y << 1 ) | ( y >> 7 );
++ x ^= y; y = ( y << 1 ) | ( y >> 7 );
++ x ^= y ^ 0x63;
++
++ FSb[i] = x;
++ RSb[x] = i;
++ }
++
++ /* generate the forward and reverse tables */
++
++ for( i = 0; i < 256; i++ )
++ {
++ x = (unsigned char) FSb[i]; y = XTIME( x );
++
++ FT0[i] = (uint32) ( x ^ y ) ^
++ ( (uint32) x << 8 ) ^
++ ( (uint32) x << 16 ) ^
++ ( (uint32) y << 24 );
++
++ FT0[i] &= 0xFFFFFFFF;
++
++ FT1[i] = ROTR8( FT0[i] );
++ FT2[i] = ROTR8( FT1[i] );
++ FT3[i] = ROTR8( FT2[i] );
++
++ y = (unsigned char) RSb[i];
++
++ RT0[i] = ( (uint32) MUL( 0x0B, y ) ) ^
++ ( (uint32) MUL( 0x0D, y ) << 8 ) ^
++ ( (uint32) MUL( 0x09, y ) << 16 ) ^
++ ( (uint32) MUL( 0x0E, y ) << 24 );
++
++ RT0[i] &= 0xFFFFFFFF;
++
++ RT1[i] = ROTR8( RT0[i] );
++ RT2[i] = ROTR8( RT1[i] );
++ RT3[i] = ROTR8( RT2[i] );
++ }
++}
++
++#else
++
++/* forward S-box */
++
++static const uint32 FSb[256] =
++{
++ 0x63, 0x7C, 0x77, 0x7B, 0xF2, 0x6B, 0x6F, 0xC5,
++ 0x30, 0x01, 0x67, 0x2B, 0xFE, 0xD7, 0xAB, 0x76,
++ 0xCA, 0x82, 0xC9, 0x7D, 0xFA, 0x59, 0x47, 0xF0,
++ 0xAD, 0xD4, 0xA2, 0xAF, 0x9C, 0xA4, 0x72, 0xC0,
++ 0xB7, 0xFD, 0x93, 0x26, 0x36, 0x3F, 0xF7, 0xCC,
++ 0x34, 0xA5, 0xE5, 0xF1, 0x71, 0xD8, 0x31, 0x15,
++ 0x04, 0xC7, 0x23, 0xC3, 0x18, 0x96, 0x05, 0x9A,
++ 0x07, 0x12, 0x80, 0xE2, 0xEB, 0x27, 0xB2, 0x75,
++ 0x09, 0x83, 0x2C, 0x1A, 0x1B, 0x6E, 0x5A, 0xA0,
++ 0x52, 0x3B, 0xD6, 0xB3, 0x29, 0xE3, 0x2F, 0x84,
++ 0x53, 0xD1, 0x00, 0xED, 0x20, 0xFC, 0xB1, 0x5B,
++ 0x6A, 0xCB, 0xBE, 0x39, 0x4A, 0x4C, 0x58, 0xCF,
++ 0xD0, 0xEF, 0xAA, 0xFB, 0x43, 0x4D, 0x33, 0x85,
++ 0x45, 0xF9, 0x02, 0x7F, 0x50, 0x3C, 0x9F, 0xA8,
++ 0x51, 0xA3, 0x40, 0x8F, 0x92, 0x9D, 0x38, 0xF5,
++ 0xBC, 0xB6, 0xDA, 0x21, 0x10, 0xFF, 0xF3, 0xD2,
++ 0xCD, 0x0C, 0x13, 0xEC, 0x5F, 0x97, 0x44, 0x17,
++ 0xC4, 0xA7, 0x7E, 0x3D, 0x64, 0x5D, 0x19, 0x73,
++ 0x60, 0x81, 0x4F, 0xDC, 0x22, 0x2A, 0x90, 0x88,
++ 0x46, 0xEE, 0xB8, 0x14, 0xDE, 0x5E, 0x0B, 0xDB,
++ 0xE0, 0x32, 0x3A, 0x0A, 0x49, 0x06, 0x24, 0x5C,
++ 0xC2, 0xD3, 0xAC, 0x62, 0x91, 0x95, 0xE4, 0x79,
++ 0xE7, 0xC8, 0x37, 0x6D, 0x8D, 0xD5, 0x4E, 0xA9,
++ 0x6C, 0x56, 0xF4, 0xEA, 0x65, 0x7A, 0xAE, 0x08,
++ 0xBA, 0x78, 0x25, 0x2E, 0x1C, 0xA6, 0xB4, 0xC6,
++ 0xE8, 0xDD, 0x74, 0x1F, 0x4B, 0xBD, 0x8B, 0x8A,
++ 0x70, 0x3E, 0xB5, 0x66, 0x48, 0x03, 0xF6, 0x0E,
++ 0x61, 0x35, 0x57, 0xB9, 0x86, 0xC1, 0x1D, 0x9E,
++ 0xE1, 0xF8, 0x98, 0x11, 0x69, 0xD9, 0x8E, 0x94,
++ 0x9B, 0x1E, 0x87, 0xE9, 0xCE, 0x55, 0x28, 0xDF,
++ 0x8C, 0xA1, 0x89, 0x0D, 0xBF, 0xE6, 0x42, 0x68,
++ 0x41, 0x99, 0x2D, 0x0F, 0xB0, 0x54, 0xBB, 0x16
++};
++
++/* forward tables */
++
++#define FT \
++\
++ V(C6,63,63,A5), V(F8,7C,7C,84), V(EE,77,77,99), V(F6,7B,7B,8D), \
++ V(FF,F2,F2,0D), V(D6,6B,6B,BD), V(DE,6F,6F,B1), V(91,C5,C5,54), \
++ V(60,30,30,50), V(02,01,01,03), V(CE,67,67,A9), V(56,2B,2B,7D), \
++ V(E7,FE,FE,19), V(B5,D7,D7,62), V(4D,AB,AB,E6), V(EC,76,76,9A), \
++ V(8F,CA,CA,45), V(1F,82,82,9D), V(89,C9,C9,40), V(FA,7D,7D,87), \
++ V(EF,FA,FA,15), V(B2,59,59,EB), V(8E,47,47,C9), V(FB,F0,F0,0B), \
++ V(41,AD,AD,EC), V(B3,D4,D4,67), V(5F,A2,A2,FD), V(45,AF,AF,EA), \
++ V(23,9C,9C,BF), V(53,A4,A4,F7), V(E4,72,72,96), V(9B,C0,C0,5B), \
++ V(75,B7,B7,C2), V(E1,FD,FD,1C), V(3D,93,93,AE), V(4C,26,26,6A), \
++ V(6C,36,36,5A), V(7E,3F,3F,41), V(F5,F7,F7,02), V(83,CC,CC,4F), \
++ V(68,34,34,5C), V(51,A5,A5,F4), V(D1,E5,E5,34), V(F9,F1,F1,08), \
++ V(E2,71,71,93), V(AB,D8,D8,73), V(62,31,31,53), V(2A,15,15,3F), \
++ V(08,04,04,0C), V(95,C7,C7,52), V(46,23,23,65), V(9D,C3,C3,5E), \
++ V(30,18,18,28), V(37,96,96,A1), V(0A,05,05,0F), V(2F,9A,9A,B5), \
++ V(0E,07,07,09), V(24,12,12,36), V(1B,80,80,9B), V(DF,E2,E2,3D), \
++ V(CD,EB,EB,26), V(4E,27,27,69), V(7F,B2,B2,CD), V(EA,75,75,9F), \
++ V(12,09,09,1B), V(1D,83,83,9E), V(58,2C,2C,74), V(34,1A,1A,2E), \
++ V(36,1B,1B,2D), V(DC,6E,6E,B2), V(B4,5A,5A,EE), V(5B,A0,A0,FB), \
++ V(A4,52,52,F6), V(76,3B,3B,4D), V(B7,D6,D6,61), V(7D,B3,B3,CE), \
++ V(52,29,29,7B), V(DD,E3,E3,3E), V(5E,2F,2F,71), V(13,84,84,97), \
++ V(A6,53,53,F5), V(B9,D1,D1,68), V(00,00,00,00), V(C1,ED,ED,2C), \
++ V(40,20,20,60), V(E3,FC,FC,1F), V(79,B1,B1,C8), V(B6,5B,5B,ED), \
++ V(D4,6A,6A,BE), V(8D,CB,CB,46), V(67,BE,BE,D9), V(72,39,39,4B), \
++ V(94,4A,4A,DE), V(98,4C,4C,D4), V(B0,58,58,E8), V(85,CF,CF,4A), \
++ V(BB,D0,D0,6B), V(C5,EF,EF,2A), V(4F,AA,AA,E5), V(ED,FB,FB,16), \
++ V(86,43,43,C5), V(9A,4D,4D,D7), V(66,33,33,55), V(11,85,85,94), \
++ V(8A,45,45,CF), V(E9,F9,F9,10), V(04,02,02,06), V(FE,7F,7F,81), \
++ V(A0,50,50,F0), V(78,3C,3C,44), V(25,9F,9F,BA), V(4B,A8,A8,E3), \
++ V(A2,51,51,F3), V(5D,A3,A3,FE), V(80,40,40,C0), V(05,8F,8F,8A), \
++ V(3F,92,92,AD), V(21,9D,9D,BC), V(70,38,38,48), V(F1,F5,F5,04), \
++ V(63,BC,BC,DF), V(77,B6,B6,C1), V(AF,DA,DA,75), V(42,21,21,63), \
++ V(20,10,10,30), V(E5,FF,FF,1A), V(FD,F3,F3,0E), V(BF,D2,D2,6D), \
++ V(81,CD,CD,4C), V(18,0C,0C,14), V(26,13,13,35), V(C3,EC,EC,2F), \
++ V(BE,5F,5F,E1), V(35,97,97,A2), V(88,44,44,CC), V(2E,17,17,39), \
++ V(93,C4,C4,57), V(55,A7,A7,F2), V(FC,7E,7E,82), V(7A,3D,3D,47), \
++ V(C8,64,64,AC), V(BA,5D,5D,E7), V(32,19,19,2B), V(E6,73,73,95), \
++ V(C0,60,60,A0), V(19,81,81,98), V(9E,4F,4F,D1), V(A3,DC,DC,7F), \
++ V(44,22,22,66), V(54,2A,2A,7E), V(3B,90,90,AB), V(0B,88,88,83), \
++ V(8C,46,46,CA), V(C7,EE,EE,29), V(6B,B8,B8,D3), V(28,14,14,3C), \
++ V(A7,DE,DE,79), V(BC,5E,5E,E2), V(16,0B,0B,1D), V(AD,DB,DB,76), \
++ V(DB,E0,E0,3B), V(64,32,32,56), V(74,3A,3A,4E), V(14,0A,0A,1E), \
++ V(92,49,49,DB), V(0C,06,06,0A), V(48,24,24,6C), V(B8,5C,5C,E4), \
++ V(9F,C2,C2,5D), V(BD,D3,D3,6E), V(43,AC,AC,EF), V(C4,62,62,A6), \
++ V(39,91,91,A8), V(31,95,95,A4), V(D3,E4,E4,37), V(F2,79,79,8B), \
++ V(D5,E7,E7,32), V(8B,C8,C8,43), V(6E,37,37,59), V(DA,6D,6D,B7), \
++ V(01,8D,8D,8C), V(B1,D5,D5,64), V(9C,4E,4E,D2), V(49,A9,A9,E0), \
++ V(D8,6C,6C,B4), V(AC,56,56,FA), V(F3,F4,F4,07), V(CF,EA,EA,25), \
++ V(CA,65,65,AF), V(F4,7A,7A,8E), V(47,AE,AE,E9), V(10,08,08,18), \
++ V(6F,BA,BA,D5), V(F0,78,78,88), V(4A,25,25,6F), V(5C,2E,2E,72), \
++ V(38,1C,1C,24), V(57,A6,A6,F1), V(73,B4,B4,C7), V(97,C6,C6,51), \
++ V(CB,E8,E8,23), V(A1,DD,DD,7C), V(E8,74,74,9C), V(3E,1F,1F,21), \
++ V(96,4B,4B,DD), V(61,BD,BD,DC), V(0D,8B,8B,86), V(0F,8A,8A,85), \
++ V(E0,70,70,90), V(7C,3E,3E,42), V(71,B5,B5,C4), V(CC,66,66,AA), \
++ V(90,48,48,D8), V(06,03,03,05), V(F7,F6,F6,01), V(1C,0E,0E,12), \
++ V(C2,61,61,A3), V(6A,35,35,5F), V(AE,57,57,F9), V(69,B9,B9,D0), \
++ V(17,86,86,91), V(99,C1,C1,58), V(3A,1D,1D,27), V(27,9E,9E,B9), \
++ V(D9,E1,E1,38), V(EB,F8,F8,13), V(2B,98,98,B3), V(22,11,11,33), \
++ V(D2,69,69,BB), V(A9,D9,D9,70), V(07,8E,8E,89), V(33,94,94,A7), \
++ V(2D,9B,9B,B6), V(3C,1E,1E,22), V(15,87,87,92), V(C9,E9,E9,20), \
++ V(87,CE,CE,49), V(AA,55,55,FF), V(50,28,28,78), V(A5,DF,DF,7A), \
++ V(03,8C,8C,8F), V(59,A1,A1,F8), V(09,89,89,80), V(1A,0D,0D,17), \
++ V(65,BF,BF,DA), V(D7,E6,E6,31), V(84,42,42,C6), V(D0,68,68,B8), \
++ V(82,41,41,C3), V(29,99,99,B0), V(5A,2D,2D,77), V(1E,0F,0F,11), \
++ V(7B,B0,B0,CB), V(A8,54,54,FC), V(6D,BB,BB,D6), V(2C,16,16,3A)
++
++#define V(a,b,c,d) 0x##a##b##c##d
++static const uint32 FT0[256] = { FT };
++#undef V
++
++#define V(a,b,c,d) 0x##d##a##b##c
++static const uint32 FT1[256] = { FT };
++#undef V
++
++#define V(a,b,c,d) 0x##c##d##a##b
++static const uint32 FT2[256] = { FT };
++#undef V
++
++#define V(a,b,c,d) 0x##b##c##d##a
++static const uint32 FT3[256] = { FT };
++#undef V
++
++#undef FT
++
++/* reverse S-box */
++
++static const uint32 RSb[256] =
++{
++ 0x52, 0x09, 0x6A, 0xD5, 0x30, 0x36, 0xA5, 0x38,
++ 0xBF, 0x40, 0xA3, 0x9E, 0x81, 0xF3, 0xD7, 0xFB,
++ 0x7C, 0xE3, 0x39, 0x82, 0x9B, 0x2F, 0xFF, 0x87,
++ 0x34, 0x8E, 0x43, 0x44, 0xC4, 0xDE, 0xE9, 0xCB,
++ 0x54, 0x7B, 0x94, 0x32, 0xA6, 0xC2, 0x23, 0x3D,
++ 0xEE, 0x4C, 0x95, 0x0B, 0x42, 0xFA, 0xC3, 0x4E,
++ 0x08, 0x2E, 0xA1, 0x66, 0x28, 0xD9, 0x24, 0xB2,
++ 0x76, 0x5B, 0xA2, 0x49, 0x6D, 0x8B, 0xD1, 0x25,
++ 0x72, 0xF8, 0xF6, 0x64, 0x86, 0x68, 0x98, 0x16,
++ 0xD4, 0xA4, 0x5C, 0xCC, 0x5D, 0x65, 0xB6, 0x92,
++ 0x6C, 0x70, 0x48, 0x50, 0xFD, 0xED, 0xB9, 0xDA,
++ 0x5E, 0x15, 0x46, 0x57, 0xA7, 0x8D, 0x9D, 0x84,
++ 0x90, 0xD8, 0xAB, 0x00, 0x8C, 0xBC, 0xD3, 0x0A,
++ 0xF7, 0xE4, 0x58, 0x05, 0xB8, 0xB3, 0x45, 0x06,
++ 0xD0, 0x2C, 0x1E, 0x8F, 0xCA, 0x3F, 0x0F, 0x02,
++ 0xC1, 0xAF, 0xBD, 0x03, 0x01, 0x13, 0x8A, 0x6B,
++ 0x3A, 0x91, 0x11, 0x41, 0x4F, 0x67, 0xDC, 0xEA,
++ 0x97, 0xF2, 0xCF, 0xCE, 0xF0, 0xB4, 0xE6, 0x73,
++ 0x96, 0xAC, 0x74, 0x22, 0xE7, 0xAD, 0x35, 0x85,
++ 0xE2, 0xF9, 0x37, 0xE8, 0x1C, 0x75, 0xDF, 0x6E,
++ 0x47, 0xF1, 0x1A, 0x71, 0x1D, 0x29, 0xC5, 0x89,
++ 0x6F, 0xB7, 0x62, 0x0E, 0xAA, 0x18, 0xBE, 0x1B,
++ 0xFC, 0x56, 0x3E, 0x4B, 0xC6, 0xD2, 0x79, 0x20,
++ 0x9A, 0xDB, 0xC0, 0xFE, 0x78, 0xCD, 0x5A, 0xF4,
++ 0x1F, 0xDD, 0xA8, 0x33, 0x88, 0x07, 0xC7, 0x31,
++ 0xB1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xEC, 0x5F,
++ 0x60, 0x51, 0x7F, 0xA9, 0x19, 0xB5, 0x4A, 0x0D,
++ 0x2D, 0xE5, 0x7A, 0x9F, 0x93, 0xC9, 0x9C, 0xEF,
++ 0xA0, 0xE0, 0x3B, 0x4D, 0xAE, 0x2A, 0xF5, 0xB0,
++ 0xC8, 0xEB, 0xBB, 0x3C, 0x83, 0x53, 0x99, 0x61,
++ 0x17, 0x2B, 0x04, 0x7E, 0xBA, 0x77, 0xD6, 0x26,
++ 0xE1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0C, 0x7D
++};
++
++/* reverse tables */
++
++#define RT \
++\
++ V(51,F4,A7,50), V(7E,41,65,53), V(1A,17,A4,C3), V(3A,27,5E,96), \
++ V(3B,AB,6B,CB), V(1F,9D,45,F1), V(AC,FA,58,AB), V(4B,E3,03,93), \
++ V(20,30,FA,55), V(AD,76,6D,F6), V(88,CC,76,91), V(F5,02,4C,25), \
++ V(4F,E5,D7,FC), V(C5,2A,CB,D7), V(26,35,44,80), V(B5,62,A3,8F), \
++ V(DE,B1,5A,49), V(25,BA,1B,67), V(45,EA,0E,98), V(5D,FE,C0,E1), \
++ V(C3,2F,75,02), V(81,4C,F0,12), V(8D,46,97,A3), V(6B,D3,F9,C6), \
++ V(03,8F,5F,E7), V(15,92,9C,95), V(BF,6D,7A,EB), V(95,52,59,DA), \
++ V(D4,BE,83,2D), V(58,74,21,D3), V(49,E0,69,29), V(8E,C9,C8,44), \
++ V(75,C2,89,6A), V(F4,8E,79,78), V(99,58,3E,6B), V(27,B9,71,DD), \
++ V(BE,E1,4F,B6), V(F0,88,AD,17), V(C9,20,AC,66), V(7D,CE,3A,B4), \
++ V(63,DF,4A,18), V(E5,1A,31,82), V(97,51,33,60), V(62,53,7F,45), \
++ V(B1,64,77,E0), V(BB,6B,AE,84), V(FE,81,A0,1C), V(F9,08,2B,94), \
++ V(70,48,68,58), V(8F,45,FD,19), V(94,DE,6C,87), V(52,7B,F8,B7), \
++ V(AB,73,D3,23), V(72,4B,02,E2), V(E3,1F,8F,57), V(66,55,AB,2A), \
++ V(B2,EB,28,07), V(2F,B5,C2,03), V(86,C5,7B,9A), V(D3,37,08,A5), \
++ V(30,28,87,F2), V(23,BF,A5,B2), V(02,03,6A,BA), V(ED,16,82,5C), \
++ V(8A,CF,1C,2B), V(A7,79,B4,92), V(F3,07,F2,F0), V(4E,69,E2,A1), \
++ V(65,DA,F4,CD), V(06,05,BE,D5), V(D1,34,62,1F), V(C4,A6,FE,8A), \
++ V(34,2E,53,9D), V(A2,F3,55,A0), V(05,8A,E1,32), V(A4,F6,EB,75), \
++ V(0B,83,EC,39), V(40,60,EF,AA), V(5E,71,9F,06), V(BD,6E,10,51), \
++ V(3E,21,8A,F9), V(96,DD,06,3D), V(DD,3E,05,AE), V(4D,E6,BD,46), \
++ V(91,54,8D,B5), V(71,C4,5D,05), V(04,06,D4,6F), V(60,50,15,FF), \
++ V(19,98,FB,24), V(D6,BD,E9,97), V(89,40,43,CC), V(67,D9,9E,77), \
++ V(B0,E8,42,BD), V(07,89,8B,88), V(E7,19,5B,38), V(79,C8,EE,DB), \
++ V(A1,7C,0A,47), V(7C,42,0F,E9), V(F8,84,1E,C9), V(00,00,00,00), \
++ V(09,80,86,83), V(32,2B,ED,48), V(1E,11,70,AC), V(6C,5A,72,4E), \
++ V(FD,0E,FF,FB), V(0F,85,38,56), V(3D,AE,D5,1E), V(36,2D,39,27), \
++ V(0A,0F,D9,64), V(68,5C,A6,21), V(9B,5B,54,D1), V(24,36,2E,3A), \
++ V(0C,0A,67,B1), V(93,57,E7,0F), V(B4,EE,96,D2), V(1B,9B,91,9E), \
++ V(80,C0,C5,4F), V(61,DC,20,A2), V(5A,77,4B,69), V(1C,12,1A,16), \
++ V(E2,93,BA,0A), V(C0,A0,2A,E5), V(3C,22,E0,43), V(12,1B,17,1D), \
++ V(0E,09,0D,0B), V(F2,8B,C7,AD), V(2D,B6,A8,B9), V(14,1E,A9,C8), \
++ V(57,F1,19,85), V(AF,75,07,4C), V(EE,99,DD,BB), V(A3,7F,60,FD), \
++ V(F7,01,26,9F), V(5C,72,F5,BC), V(44,66,3B,C5), V(5B,FB,7E,34), \
++ V(8B,43,29,76), V(CB,23,C6,DC), V(B6,ED,FC,68), V(B8,E4,F1,63), \
++ V(D7,31,DC,CA), V(42,63,85,10), V(13,97,22,40), V(84,C6,11,20), \
++ V(85,4A,24,7D), V(D2,BB,3D,F8), V(AE,F9,32,11), V(C7,29,A1,6D), \
++ V(1D,9E,2F,4B), V(DC,B2,30,F3), V(0D,86,52,EC), V(77,C1,E3,D0), \
++ V(2B,B3,16,6C), V(A9,70,B9,99), V(11,94,48,FA), V(47,E9,64,22), \
++ V(A8,FC,8C,C4), V(A0,F0,3F,1A), V(56,7D,2C,D8), V(22,33,90,EF), \
++ V(87,49,4E,C7), V(D9,38,D1,C1), V(8C,CA,A2,FE), V(98,D4,0B,36), \
++ V(A6,F5,81,CF), V(A5,7A,DE,28), V(DA,B7,8E,26), V(3F,AD,BF,A4), \
++ V(2C,3A,9D,E4), V(50,78,92,0D), V(6A,5F,CC,9B), V(54,7E,46,62), \
++ V(F6,8D,13,C2), V(90,D8,B8,E8), V(2E,39,F7,5E), V(82,C3,AF,F5), \
++ V(9F,5D,80,BE), V(69,D0,93,7C), V(6F,D5,2D,A9), V(CF,25,12,B3), \
++ V(C8,AC,99,3B), V(10,18,7D,A7), V(E8,9C,63,6E), V(DB,3B,BB,7B), \
++ V(CD,26,78,09), V(6E,59,18,F4), V(EC,9A,B7,01), V(83,4F,9A,A8), \
++ V(E6,95,6E,65), V(AA,FF,E6,7E), V(21,BC,CF,08), V(EF,15,E8,E6), \
++ V(BA,E7,9B,D9), V(4A,6F,36,CE), V(EA,9F,09,D4), V(29,B0,7C,D6), \
++ V(31,A4,B2,AF), V(2A,3F,23,31), V(C6,A5,94,30), V(35,A2,66,C0), \
++ V(74,4E,BC,37), V(FC,82,CA,A6), V(E0,90,D0,B0), V(33,A7,D8,15), \
++ V(F1,04,98,4A), V(41,EC,DA,F7), V(7F,CD,50,0E), V(17,91,F6,2F), \
++ V(76,4D,D6,8D), V(43,EF,B0,4D), V(CC,AA,4D,54), V(E4,96,04,DF), \
++ V(9E,D1,B5,E3), V(4C,6A,88,1B), V(C1,2C,1F,B8), V(46,65,51,7F), \
++ V(9D,5E,EA,04), V(01,8C,35,5D), V(FA,87,74,73), V(FB,0B,41,2E), \
++ V(B3,67,1D,5A), V(92,DB,D2,52), V(E9,10,56,33), V(6D,D6,47,13), \
++ V(9A,D7,61,8C), V(37,A1,0C,7A), V(59,F8,14,8E), V(EB,13,3C,89), \
++ V(CE,A9,27,EE), V(B7,61,C9,35), V(E1,1C,E5,ED), V(7A,47,B1,3C), \
++ V(9C,D2,DF,59), V(55,F2,73,3F), V(18,14,CE,79), V(73,C7,37,BF), \
++ V(53,F7,CD,EA), V(5F,FD,AA,5B), V(DF,3D,6F,14), V(78,44,DB,86), \
++ V(CA,AF,F3,81), V(B9,68,C4,3E), V(38,24,34,2C), V(C2,A3,40,5F), \
++ V(16,1D,C3,72), V(BC,E2,25,0C), V(28,3C,49,8B), V(FF,0D,95,41), \
++ V(39,A8,01,71), V(08,0C,B3,DE), V(D8,B4,E4,9C), V(64,56,C1,90), \
++ V(7B,CB,84,61), V(D5,32,B6,70), V(48,6C,5C,74), V(D0,B8,57,42)
++
++#define V(a,b,c,d) 0x##a##b##c##d
++static const uint32 RT0[256] = { RT };
++#undef V
++
++#define V(a,b,c,d) 0x##d##a##b##c
++static const uint32 RT1[256] = { RT };
++#undef V
++
++#define V(a,b,c,d) 0x##c##d##a##b
++static const uint32 RT2[256] = { RT };
++#undef V
++
++#define V(a,b,c,d) 0x##b##c##d##a
++static const uint32 RT3[256] = { RT };
++#undef V
++
++#undef RT
++
++/* round constants */
++
++static const uint32 RCON[10] =
++{
++ 0x01000000, 0x02000000, 0x04000000, 0x08000000,
++ 0x10000000, 0x20000000, 0x40000000, 0x80000000,
++ 0x1B000000, 0x36000000
++};
++
++int do_init = 0;
++
++void aes_gen_tables( void )
++{
++}
++
++#endif
++
++/* platform-independant 32-bit integer manipulation macros */
++
++#define GET_UINT32_aes(n,b,i) \
++{ \
++ (n) = ( (uint32) (b)[(i) ] << 24 ) \
++ | ( (uint32) (b)[(i) + 1] << 16 ) \
++ | ( (uint32) (b)[(i) + 2] << 8 ) \
++ | ( (uint32) (b)[(i) + 3] ); \
++}
++
++#define PUT_UINT32_aes(n,b,i) \
++{ \
++ (b)[(i) ] = (uint8) ( (n) >> 24 ); \
++ (b)[(i) + 1] = (uint8) ( (n) >> 16 ); \
++ (b)[(i) + 2] = (uint8) ( (n) >> 8 ); \
++ (b)[(i) + 3] = (uint8) ( (n) ); \
++}
++
++/* decryption key schedule tables */
++
++int KT_init = 1;
++
++uint32 KT0[256];
++uint32 KT1[256];
++uint32 KT2[256];
++uint32 KT3[256];
++
++/* AES key scheduling routine */
++int aes_set_key( aes_context *ctx, uint8 *key, int nbits )
++{
++ int i;
++ uint32 *RK, *SK;
++
++ if( do_init )
++ {
++ aes_gen_tables();
++
++ do_init = 0;
++ }
++
++ switch( nbits )
++ {
++ case 128: ctx->nr = 10; break;
++ case 192: ctx->nr = 12; break;
++ case 256: ctx->nr = 14; break;
++ default : return( 1 );
++ }
++
++ RK = ctx->erk;
++
++ for( i = 0; i < (nbits >> 5); i++ )
++ {
++ GET_UINT32_aes( RK[i], key, i * 4 );
++ }
++
++ /* setup encryption round keys */
++
++ switch( nbits )
++ {
++ case 128:
++
++ for( i = 0; i < 10; i++, RK += 4 )
++ {
++ RK[4] = RK[0] ^ RCON[i] ^
++ ( FSb[ (uint8) ( RK[3] >> 16 ) ] << 24 ) ^
++ ( FSb[ (uint8) ( RK[3] >> 8 ) ] << 16 ) ^
++ ( FSb[ (uint8) ( RK[3] ) ] << 8 ) ^
++ ( FSb[ (uint8) ( RK[3] >> 24 ) ] );
++
++ RK[5] = RK[1] ^ RK[4];
++ RK[6] = RK[2] ^ RK[5];
++ RK[7] = RK[3] ^ RK[6];
++ }
++ break;
++
++ case 192:
++
++ for( i = 0; i < 8; i++, RK += 6 )
++ {
++ RK[6] = RK[0] ^ RCON[i] ^
++ ( FSb[ (uint8) ( RK[5] >> 16 ) ] << 24 ) ^
++ ( FSb[ (uint8) ( RK[5] >> 8 ) ] << 16 ) ^
++ ( FSb[ (uint8) ( RK[5] ) ] << 8 ) ^
++ ( FSb[ (uint8) ( RK[5] >> 24 ) ] );
++
++ RK[7] = RK[1] ^ RK[6];
++ RK[8] = RK[2] ^ RK[7];
++ RK[9] = RK[3] ^ RK[8];
++ RK[10] = RK[4] ^ RK[9];
++ RK[11] = RK[5] ^ RK[10];
++ }
++ break;
++
++ case 256:
++
++ for( i = 0; i < 7; i++, RK += 8 )
++ {
++ RK[8] = RK[0] ^ RCON[i] ^
++ ( FSb[ (uint8) ( RK[7] >> 16 ) ] << 24 ) ^
++ ( FSb[ (uint8) ( RK[7] >> 8 ) ] << 16 ) ^
++ ( FSb[ (uint8) ( RK[7] ) ] << 8 ) ^
++ ( FSb[ (uint8) ( RK[7] >> 24 ) ] );
++
++ RK[9] = RK[1] ^ RK[8];
++ RK[10] = RK[2] ^ RK[9];
++ RK[11] = RK[3] ^ RK[10];
++
++ RK[12] = RK[4] ^
++ ( FSb[ (uint8) ( RK[11] >> 24 ) ] << 24 ) ^
++ ( FSb[ (uint8) ( RK[11] >> 16 ) ] << 16 ) ^
++ ( FSb[ (uint8) ( RK[11] >> 8 ) ] << 8 ) ^
++ ( FSb[ (uint8) ( RK[11] ) ] );
++
++ RK[13] = RK[5] ^ RK[12];
++ RK[14] = RK[6] ^ RK[13];
++ RK[15] = RK[7] ^ RK[14];
++ }
++ break;
++ }
++
++ /* setup decryption round keys */
++
++ if( KT_init )
++ {
++ for( i = 0; i < 256; i++ )
++ {
++ KT0[i] = RT0[ FSb[i] ];
++ KT1[i] = RT1[ FSb[i] ];
++ KT2[i] = RT2[ FSb[i] ];
++ KT3[i] = RT3[ FSb[i] ];
++ }
++
++ KT_init = 0;
++ }
++
++ SK = ctx->drk;
++
++ *SK++ = *RK++;
++ *SK++ = *RK++;
++ *SK++ = *RK++;
++ *SK++ = *RK++;
++
++ for( i = 1; i < ctx->nr; i++ )
++ {
++ RK -= 8;
++
++ *SK++ = KT0[ (uint8) ( *RK >> 24 ) ] ^
++ KT1[ (uint8) ( *RK >> 16 ) ] ^
++ KT2[ (uint8) ( *RK >> 8 ) ] ^
++ KT3[ (uint8) ( *RK ) ]; RK++;
++
++ *SK++ = KT0[ (uint8) ( *RK >> 24 ) ] ^
++ KT1[ (uint8) ( *RK >> 16 ) ] ^
++ KT2[ (uint8) ( *RK >> 8 ) ] ^
++ KT3[ (uint8) ( *RK ) ]; RK++;
++
++ *SK++ = KT0[ (uint8) ( *RK >> 24 ) ] ^
++ KT1[ (uint8) ( *RK >> 16 ) ] ^
++ KT2[ (uint8) ( *RK >> 8 ) ] ^
++ KT3[ (uint8) ( *RK ) ]; RK++;
++
++ *SK++ = KT0[ (uint8) ( *RK >> 24 ) ] ^
++ KT1[ (uint8) ( *RK >> 16 ) ] ^
++ KT2[ (uint8) ( *RK >> 8 ) ] ^
++ KT3[ (uint8) ( *RK ) ]; RK++;
++ }
++
++ RK -= 8;
++
++ *SK++ = *RK++;
++ *SK++ = *RK++;
++ *SK++ = *RK++;
++ *SK++ = *RK++;
++
++ return( 0 );
++}
+diff --git a/board/aspeed/ast2300/ast2300.c b/board/aspeed/ast2300/ast2300.c
+new file mode 100644
+index 0000000..b317786
+--- /dev/null
++++ b/board/aspeed/ast2300/ast2300.c
+@@ -0,0 +1,171 @@
++/*
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++ */
++
++#include <common.h>
++#include <command.h>
++#include <pci.h>
++
++int board_init (void)
++{
++ DECLARE_GLOBAL_DATA_PTR;
++ unsigned char data;
++ unsigned long reg;
++
++ /* AHB Controller */
++ *((volatile ulong*) 0x1E600000) = 0xAEED1A03; /* unlock AHB controller */
++ *((volatile ulong*) 0x1E60008C) |= 0x01; /* map DRAM to 0x00000000 */
++#ifdef CONFIG_PCI
++ *((volatile ulong*) 0x1E60008C) |= 0x30; /* map PCI */
++#endif
++
++ /* Flash Controller */
++#ifdef CONFIG_FLASH_AST2300
++ *((volatile ulong*) 0x1e620000) |= 0x800f0000; /* enable Flash Write */
++#else
++ *((volatile ulong*) 0x16000000) |= 0x00001c00; /* enable Flash Write */
++#endif
++
++ /* SCU */
++ *((volatile ulong*) 0x1e6e2000) = 0x1688A8A8; /* unlock SCU */
++ reg = *((volatile ulong*) 0x1e6e2008);
++ reg &= 0x1c0fffff;
++ reg |= 0x61800000; /* PCLK = HPLL/8 */
++#ifdef CONFIG_AST1070
++ reg |= 0x300000; /* LHCLK = HPLL/8 */
++ reg |= 0x80000; /* LPC Host Clock */
++#endif
++ *((volatile ulong*) 0x1e6e2008) = reg;
++ reg = *((volatile ulong*) 0x1e6e200c); /* enable 2D Clk */
++ *((volatile ulong*) 0x1e6e200c) &= 0xFFFFFFFD;
++/* enable wide screen. If your video driver does not support wide screen, don't
++enable this bit 0x1e6e2040 D[0]*/
++ reg = *((volatile ulong*) 0x1e6e2040);
++ *((volatile ulong*) 0x1e6e2040) |= 0x01;
++#ifdef CONFIG_AST1070
++/*set VPPL1 */
++
++ *((volatile ulong*) 0x1e6e201c) = 0x6420;
++
++// set d2-pll & enable d2-pll D[21:20], D[4]
++ reg = *((volatile ulong*) 0x1e6e202c);
++ reg &= 0xffcfffef;
++ reg |= 0x00200010;
++ *((volatile ulong*) 0x1e6e202c) = reg;
++
++// set OSCCLK = VPLL1
++ *((volatile ulong*) 0x1e6e2010) = 0x8;
++
++// enable OSCCLK
++ reg = *((volatile ulong*) 0x1e6e202c);
++ reg &= 0xfffffffd;
++ reg |= 0x00000002;
++ *((volatile ulong*) 0x1e6e202c) = reg;
++
++// enable AST1050's LPC master
++ reg = *((volatile ulong*) 0x1e7890a0);
++ *((volatile ulong*) 0x1e7890a0) |= 0x11;
++#endif
++ /* arch number */
++ gd->bd->bi_arch_number = MACH_TYPE_ASPEED;
++
++ /* adress of boot parameters */
++ gd->bd->bi_boot_params = 0x40000100;
++
++ return 0;
++}
++
++int dram_init (void)
++{
++ DECLARE_GLOBAL_DATA_PTR;
++
++ gd->bd->bi_dram[0].start = PHYS_SDRAM_1;
++ gd->bd->bi_dram[0].size = PHYS_SDRAM_1_SIZE;
++
++ return 0;
++}
++
++/*
++SCU7C: Silicon Revision ID Register
++D[31:24]: Chip ID
++0: AST2050/AST2100/AST2150/AST2200/AST3000
++1: AST2300
++
++D[23:16] Silicon revision ID for AST2300 generation and later
++0: A0
++1: A1
++2: A2
++.
++.
++.
++FPGA revision starts from 0x80
++
++
++D[11:8] Bounding option
++
++D[7:0] Silicon revision ID for AST2050/AST2100 generation (for software compatible)
++0: A0
++1: A1
++2: A2
++3: A3
++.
++.
++FPGA revision starts from 0x08, 8~10 means A0, 11+ means A1, AST2300 should be assigned to 3
++*/
++int misc_init_r(void)
++{
++ unsigned int reg1, revision, chip_id;
++
++ /* Show H/W Version */
++ reg1 = (unsigned int) (*((ulong*) 0x1e6e207c));
++ chip_id = (reg1 & 0xff000000) >> 24;
++ revision = (reg1 & 0xff0000) >> 16;
++
++ puts ("H/W: ");
++ if (chip_id == 1) {
++ if (revision >= 0x80) {
++ printf("AST2300 series FPGA Rev. %02x \n", revision);
++ }
++ else {
++ printf("AST2300 series chip Rev. %02x \n", revision);
++ }
++ }
++ else if (chip_id == 0) {
++ printf("AST2050/AST2150 series chip\n");
++ }
++
++#ifdef CONFIG_AST1070
++ puts ("C/C: ");
++ revision = (unsigned int) (*((ulong*) 0x60002034));
++ printf("AST1070 ID [%08x] \n", revision);
++#endif
++
++#ifdef CONFIG_PCI
++ pci_init ();
++#endif
++
++ if (getenv ("verify") == NULL) {
++ setenv ("verify", "n");
++ }
++ if (getenv ("eeprom") == NULL) {
++ setenv ("eeprom", "y");
++ }
++}
++
++#ifdef CONFIG_PCI
++static struct pci_controller hose;
++
++extern void aspeed_init_pci (struct pci_controller *hose);
++
++void pci_init_board(void)
++{
++ aspeed_init_pci(&hose);
++}
++#endif
+diff --git a/board/aspeed/ast2300/config.mk b/board/aspeed/ast2300/config.mk
+new file mode 100755
+index 0000000..24ca09b
+--- /dev/null
++++ b/board/aspeed/ast2300/config.mk
+@@ -0,0 +1,18 @@
++# This program is distributed in the hope that it will be useful,
++# but WITHOUT ANY WARRANTY; without even the implied warranty of
++# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++# GNU General Public License for more details.
++#
++# You should have received a copy of the GNU General Public License
++# along with this program; if not, write to the Free Software
++# Foundation, Inc., 59 Temple Place, Suite 330, Boston,
++# MA 02111-1307 USA
++#
++
++# ROM version
++#TEXT_BASE = 0xBFC00000
++
++# RAM version
++TEXT_BASE = 0x40500000
++#TEXT_BASE = 0x00000000
++#TEXT_BASE = 0x00400000
+diff --git a/board/aspeed/ast2300/crc32.c b/board/aspeed/ast2300/crc32.c
+new file mode 100755
+index 0000000..cc8d2ac
+--- /dev/null
++++ b/board/aspeed/ast2300/crc32.c
+@@ -0,0 +1,127 @@
++/*
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++ */
++#include <common.h>
++#include <asm/processor.h>
++#include <asm/byteorder.h>
++#include <environment.h>
++
++#ifdef CONFIG_2SPIFLASH
++
++extern flash_info_t flash_info[CFG_MAX_FLASH_BANKS];
++
++/* ========================================================================
++ * Table of CRC-32's of all single-byte values (made by make_aspeed_crc_table)
++ */
++unsigned long aspeed_crc_table[256] = {
++ 0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL, 0x076dc419L,
++ 0x706af48fL, 0xe963a535L, 0x9e6495a3L, 0x0edb8832L, 0x79dcb8a4L,
++ 0xe0d5e91eL, 0x97d2d988L, 0x09b64c2bL, 0x7eb17cbdL, 0xe7b82d07L,
++ 0x90bf1d91L, 0x1db71064L, 0x6ab020f2L, 0xf3b97148L, 0x84be41deL,
++ 0x1adad47dL, 0x6ddde4ebL, 0xf4d4b551L, 0x83d385c7L, 0x136c9856L,
++ 0x646ba8c0L, 0xfd62f97aL, 0x8a65c9ecL, 0x14015c4fL, 0x63066cd9L,
++ 0xfa0f3d63L, 0x8d080df5L, 0x3b6e20c8L, 0x4c69105eL, 0xd56041e4L,
++ 0xa2677172L, 0x3c03e4d1L, 0x4b04d447L, 0xd20d85fdL, 0xa50ab56bL,
++ 0x35b5a8faL, 0x42b2986cL, 0xdbbbc9d6L, 0xacbcf940L, 0x32d86ce3L,
++ 0x45df5c75L, 0xdcd60dcfL, 0xabd13d59L, 0x26d930acL, 0x51de003aL,
++ 0xc8d75180L, 0xbfd06116L, 0x21b4f4b5L, 0x56b3c423L, 0xcfba9599L,
++ 0xb8bda50fL, 0x2802b89eL, 0x5f058808L, 0xc60cd9b2L, 0xb10be924L,
++ 0x2f6f7c87L, 0x58684c11L, 0xc1611dabL, 0xb6662d3dL, 0x76dc4190L,
++ 0x01db7106L, 0x98d220bcL, 0xefd5102aL, 0x71b18589L, 0x06b6b51fL,
++ 0x9fbfe4a5L, 0xe8b8d433L, 0x7807c9a2L, 0x0f00f934L, 0x9609a88eL,
++ 0xe10e9818L, 0x7f6a0dbbL, 0x086d3d2dL, 0x91646c97L, 0xe6635c01L,
++ 0x6b6b51f4L, 0x1c6c6162L, 0x856530d8L, 0xf262004eL, 0x6c0695edL,
++ 0x1b01a57bL, 0x8208f4c1L, 0xf50fc457L, 0x65b0d9c6L, 0x12b7e950L,
++ 0x8bbeb8eaL, 0xfcb9887cL, 0x62dd1ddfL, 0x15da2d49L, 0x8cd37cf3L,
++ 0xfbd44c65L, 0x4db26158L, 0x3ab551ceL, 0xa3bc0074L, 0xd4bb30e2L,
++ 0x4adfa541L, 0x3dd895d7L, 0xa4d1c46dL, 0xd3d6f4fbL, 0x4369e96aL,
++ 0x346ed9fcL, 0xad678846L, 0xda60b8d0L, 0x44042d73L, 0x33031de5L,
++ 0xaa0a4c5fL, 0xdd0d7cc9L, 0x5005713cL, 0x270241aaL, 0xbe0b1010L,
++ 0xc90c2086L, 0x5768b525L, 0x206f85b3L, 0xb966d409L, 0xce61e49fL,
++ 0x5edef90eL, 0x29d9c998L, 0xb0d09822L, 0xc7d7a8b4L, 0x59b33d17L,
++ 0x2eb40d81L, 0xb7bd5c3bL, 0xc0ba6cadL, 0xedb88320L, 0x9abfb3b6L,
++ 0x03b6e20cL, 0x74b1d29aL, 0xead54739L, 0x9dd277afL, 0x04db2615L,
++ 0x73dc1683L, 0xe3630b12L, 0x94643b84L, 0x0d6d6a3eL, 0x7a6a5aa8L,
++ 0xe40ecf0bL, 0x9309ff9dL, 0x0a00ae27L, 0x7d079eb1L, 0xf00f9344L,
++ 0x8708a3d2L, 0x1e01f268L, 0x6906c2feL, 0xf762575dL, 0x806567cbL,
++ 0x196c3671L, 0x6e6b06e7L, 0xfed41b76L, 0x89d32be0L, 0x10da7a5aL,
++ 0x67dd4accL, 0xf9b9df6fL, 0x8ebeeff9L, 0x17b7be43L, 0x60b08ed5L,
++ 0xd6d6a3e8L, 0xa1d1937eL, 0x38d8c2c4L, 0x4fdff252L, 0xd1bb67f1L,
++ 0xa6bc5767L, 0x3fb506ddL, 0x48b2364bL, 0xd80d2bdaL, 0xaf0a1b4cL,
++ 0x36034af6L, 0x41047a60L, 0xdf60efc3L, 0xa867df55L, 0x316e8eefL,
++ 0x4669be79L, 0xcb61b38cL, 0xbc66831aL, 0x256fd2a0L, 0x5268e236L,
++ 0xcc0c7795L, 0xbb0b4703L, 0x220216b9L, 0x5505262fL, 0xc5ba3bbeL,
++ 0xb2bd0b28L, 0x2bb45a92L, 0x5cb36a04L, 0xc2d7ffa7L, 0xb5d0cf31L,
++ 0x2cd99e8bL, 0x5bdeae1dL, 0x9b64c2b0L, 0xec63f226L, 0x756aa39cL,
++ 0x026d930aL, 0x9c0906a9L, 0xeb0e363fL, 0x72076785L, 0x05005713L,
++ 0x95bf4a82L, 0xe2b87a14L, 0x7bb12baeL, 0x0cb61b38L, 0x92d28e9bL,
++ 0xe5d5be0dL, 0x7cdcefb7L, 0x0bdbdf21L, 0x86d3d2d4L, 0xf1d4e242L,
++ 0x68ddb3f8L, 0x1fda836eL, 0x81be16cdL, 0xf6b9265bL, 0x6fb077e1L,
++ 0x18b74777L, 0x88085ae6L, 0xff0f6a70L, 0x66063bcaL, 0x11010b5cL,
++ 0x8f659effL, 0xf862ae69L, 0x616bffd3L, 0x166ccf45L, 0xa00ae278L,
++ 0xd70dd2eeL, 0x4e048354L, 0x3903b3c2L, 0xa7672661L, 0xd06016f7L,
++ 0x4969474dL, 0x3e6e77dbL, 0xaed16a4aL, 0xd9d65adcL, 0x40df0b66L,
++ 0x37d83bf0L, 0xa9bcae53L, 0xdebb9ec5L, 0x47b2cf7fL, 0x30b5ffe9L,
++ 0xbdbdf21cL, 0xcabac28aL, 0x53b39330L, 0x24b4a3a6L, 0xbad03605L,
++ 0xcdd70693L, 0x54de5729L, 0x23d967bfL, 0xb3667a2eL, 0xc4614ab8L,
++ 0x5d681b02L, 0x2a6f2b94L, 0xb40bbe37L, 0xc30c8ea1L, 0x5a05df1bL,
++ 0x2d02ef8dL
++};
++
++/* ========================================================================= */
++#define ASPEED_DO1(buf) crc = aspeed_crc_table[((int)crc ^ (*buf++)) & 0xff] ^ (crc >> 8);
++#define ASPEED_DO2(buf) ASPEED_DO1(buf); ASPEED_DO1(buf);
++#define ASPEED_DO4(buf) ASPEED_DO2(buf); ASPEED_DO2(buf);
++#define ASPEED_DO8(buf) ASPEED_DO4(buf); ASPEED_DO4(buf);
++
++/* ========================================================================= */
++unsigned long spi2_crc32(crc, buf, len)
++ unsigned long crc;
++ unsigned char *buf;
++ unsigned long len;
++{
++
++ size_t len1, len2;
++ char *s;
++
++ len1 = len2 = 0;
++ if ( (ulong)(buf) <= (flash_info[0].start[0] + flash_info[0].size) )
++ len1 = (flash_info[0].start[0] + flash_info[0].size) - (ulong)(buf);
++
++ len1 = (len < len1) ? len:len1;
++ len2 = (len < len1) ? 0: (len - len1);
++
++ crc = crc ^ 0xffffffffL;
++ while (len1 >= 8)
++ {
++ ASPEED_DO8(buf);
++ len1 -= 8;
++ }
++ if (len1) do {
++ ASPEED_DO1(buf);
++ } while (--len1);
++
++ //s = (char *) flash_info[1].start[0];
++ s= (char *) flash_make_addr (&flash_info[1], 0, 0);
++ while (len2 >= 8)
++ {
++ ASPEED_DO8(s);
++ len2 -= 8;
++ }
++ if (len2) do {
++ ASPEED_DO1(s);
++ } while (--len2);
++
++ return crc ^ 0xffffffffL;
++
++}
++
++#endif /* CONFIG_2SPIFLASH */
++
+diff --git a/board/aspeed/ast2300/crt.c b/board/aspeed/ast2300/crt.c
+new file mode 100755
+index 0000000..b67f669
+--- /dev/null
++++ b/board/aspeed/ast2300/crt.c
+@@ -0,0 +1,322 @@
++/*
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++ */
++#include <common.h>
++#include <command.h>
++
++#include "type.h"
++#include "vesa.h"
++#include "vdef.h"
++#include "vfun.h"
++#include "vreg.h"
++#include "crt.h"
++
++ULONG AST3000DCLKTableV [] = {
++ 0x00046515, /* 00: VCLK25_175 */
++ 0x00047255, /* 01: VCLK28_322 */
++ 0x0004682a, /* 02: VCLK31_5 */
++ 0x0004672a, /* 03: VCLK36 */
++ 0x00046c50, /* 04: VCLK40 */
++ 0x00046842, /* 05: VCLK49_5 */
++ 0x00006c32, /* 06: VCLK50 */
++ 0x00006a2f, /* 07: VCLK56_25 */
++ 0x00006c41, /* 08: VCLK65 */
++ 0x00006832, /* 09: VCLK75 */
++ 0x0000672e, /* 0A: VCLK78_75 */
++ 0x0000683f, /* 0B: VCLK94_5 */
++ 0x00004824, /* 0C: VCLK108 */
++ 0x00004723, /* 0D: VCLK119 */
++ 0x0000482d, /* 0E: VCLK135 */
++ 0x00004B37, /* 0F: VCLK146_25 */
++ 0x0000472e, /* 10: VCLK157_5 */
++ 0x00004836, /* 11: VCLK162 */
++
++};
++
++BOOL CheckDAC(int nCRTIndex)
++{
++ BYTE btValue;
++ BOOL bValue;
++
++ BYTE btDeviceSelect;
++
++ switch (nCRTIndex)
++ {
++ case CRT_1:
++ btDeviceSelect = DEVICE_ADDRESS_CH7301_CRT1;
++ break;
++ case CRT_2:
++ btDeviceSelect = DEVICE_ADDRESS_CH7301_CRT2;
++ break;
++ default:
++ printf("CRTIndex is not 1 or 2");
++ return FALSE;
++ break;
++ }
++
++ //Enable all DAC's and set register 21h[0] = '0'
++ //DVIP and DVIL disable for DAC
++ SetI2CRegClient(0, DEVICE_SELECT_CH7301, btDeviceSelect, CH7301_PM_REG, 0x00);
++
++ btValue = GetI2CRegClient(0, DEVICE_SELECT_CH7301, btDeviceSelect, CH7301_DC_REG);
++ btValue = btValue & 0xFE;
++ SetI2CRegClient(0, DEVICE_SELECT_CH7301, btDeviceSelect, CH7301_DC_REG, btValue);
++
++ //Set SENSE bit to 1
++ btValue = GetI2CRegClient(0, DEVICE_SELECT_CH7301, btDeviceSelect, CH7301_CD_REG);
++ btValue = btValue | 0x01;
++ SetI2CRegClient(0, DEVICE_SELECT_CH7301, btDeviceSelect, CH7301_CD_REG, btValue);
++
++ //Reset SENSE bit to 0
++ btValue = GetI2CRegClient(0, DEVICE_SELECT_CH7301, btDeviceSelect, CH7301_CD_REG);
++ btValue = btValue & 0xFE;
++ SetI2CRegClient(0, DEVICE_SELECT_CH7301, btDeviceSelect, CH7301_CD_REG, btValue);
++
++ bValue = (GetI2CRegClient(0, DEVICE_SELECT_CH7301, btDeviceSelect, CH7301_CD_REG) & CD_DACT) ? TRUE : FALSE;
++
++ return bValue;
++}
++
++VOID SetCH7301C(ULONG MMIOBase,
++ int nCRTIndex,
++ int inFreqRange,
++ int inOperating)
++{
++ BYTE btDeviceSelect;
++ BYTE btValue;
++
++//#ifdef EVB_CLIENT
++ //output RGB doesn't need to set CH7301
++ //if (1 == inOperating)
++ // return;
++//#endif
++
++ switch (nCRTIndex)
++ {
++ case CRT_1:
++ btDeviceSelect = 0xEA;
++
++ break;
++ case CRT_2:
++ btDeviceSelect = 0xEC;
++
++ break;
++ default:
++ printf("CRTIndex is not 1 or 2");
++ return;
++ break;
++ }
++
++ if (inFreqRange <= VCLK65)
++ {
++ printf("ch7301: low f \n");
++ SetI2CRegClient(MMIOBase, 0x3, btDeviceSelect, 0x33, 0x08);
++ SetI2CRegClient(MMIOBase, 0x3, btDeviceSelect, 0x34, 0x16);
++ SetI2CRegClient(MMIOBase, 0x3, btDeviceSelect, 0x36, 0x60);
++ }
++ else
++ {
++ SetI2CRegClient(MMIOBase, 0x3, btDeviceSelect, 0x33, 0x06);
++ SetI2CRegClient(MMIOBase, 0x3, btDeviceSelect, 0x34, 0x26);
++ SetI2CRegClient(MMIOBase, 0x3, btDeviceSelect, 0x36, 0xA0);
++ }
++
++ switch (inOperating)
++ {
++ case 0:
++ //DVI is normal function
++ SetI2CRegClient(MMIOBase, 0x3, btDeviceSelect, 0x49, 0xC0);
++ SetI2CRegClient(MMIOBase, 0x3, btDeviceSelect, 0x1D, 0x47);
++ break;
++ case 1:
++ //RGB
++ SetI2CRegClient(MMIOBase, 0x3, btDeviceSelect, 0x48, 0x18);
++ SetI2CRegClient(MMIOBase, 0x3, btDeviceSelect, 0x49, 0x0);
++ SetI2CRegClient(MMIOBase, 0x3, btDeviceSelect, 0x56, 0x0);
++ SetI2CRegClient(MMIOBase, 0x3, btDeviceSelect, 0x21, 0x9);
++ SetI2CRegClient(MMIOBase, 0x3, btDeviceSelect, 0x1D, 0x48);
++ SetI2CRegClient(MMIOBase, 0x3, btDeviceSelect, 0x1C, 0x00);
++ break;
++ default:
++ break;
++ };
++}
++
++void SetASTModeTiming (ULONG MMIOBase, int nCRTIndex, BYTE ModeIndex, BYTE ColorDepth)
++{
++ ULONG temp, RetraceStart, RetraceEnd, DisplayOffset, TerminalCount, bpp;
++
++// Access CRT Engine
++ // SetPolarity
++ WriteMemoryLongWithMASKClient(SCU_BASE, CRT1_CONTROL_REG + nCRTIndex*0x60, ((vModeTable[ModeIndex].HorPolarity << HOR_SYNC_SELECT_BIT) | (vModeTable[ModeIndex].VerPolarity << VER_SYNC_SELECT_BIT)), (HOR_SYNC_SELECT_MASK|VER_SYNC_SELECT_MASK));
++
++#if CONFIG_AST3000
++ WriteMemoryLongClient(SCU_BASE, CRT1_CONTROL2_REG + nCRTIndex*0x60, 0xc0);
++#else
++ //2100 is single edge
++ WriteMemoryLongClient(SCU_BASE, CRT1_CONTROL2_REG + nCRTIndex*0x60, 0x80);
++#endif
++ // Horizontal Timing
++ temp = 0;
++ temp = ((vModeTable[ModeIndex].HorizontalActive - 1) << HOR_ENABLE_END_BIT) | ((vModeTable[ModeIndex].HorizontalTotal - 1) << HOR_TOTAL_BIT);
++ WriteMemoryLongClient(SCU_BASE, CRT1_HOR_TOTAL_END_REG + nCRTIndex*0x60, temp);
++
++ RetraceStart = vModeTable[ModeIndex].HorizontalTotal - vModeTable[ModeIndex].HBackPorch - vModeTable[ModeIndex].HSyncTime - vModeTable[ModeIndex].HLeftBorder - 1;
++ RetraceEnd = (RetraceStart + vModeTable[ModeIndex].HSyncTime);
++ temp = 0;
++ temp = (RetraceEnd << HOR_RETRACE_END_BIT) | (RetraceStart << HOR_RETRACE_START_BIT);
++ WriteMemoryLongClient(SCU_BASE, CRT1_HOR_RETRACE_REG + nCRTIndex*0x60, temp);
++
++ // Vertical Timing
++ temp = 0;
++ temp = ((vModeTable[ModeIndex].VerticalActive - 1) << VER_ENABLE_END_BIT) | ((vModeTable[ModeIndex].VerticalTotal - 1) << VER_TOTAL_BIT);
++ WriteMemoryLongClient(SCU_BASE, CRT1_VER_TOTAL_END_REG + nCRTIndex*0x60, temp);
++
++ temp = 0;
++ RetraceStart = vModeTable[ModeIndex].VerticalTotal - vModeTable[ModeIndex].VBackPorch - vModeTable[ModeIndex].VSyncTime - vModeTable[ModeIndex].VTopBorder - 1;
++ RetraceEnd = (RetraceStart + vModeTable[ModeIndex].VSyncTime);
++ temp = (RetraceEnd << VER_RETRACE_END_BIT) | (RetraceStart << VER_RETRACE_START_BIT);
++ WriteMemoryLongClient(SCU_BASE, CRT1_VER_RETRACE_REG + nCRTIndex*0x60, temp);
++
++ // Set CRT Display Offset and Terminal Count
++ if (ColorDepth == RGB_565) {
++ bpp = 16;
++ }
++ else {
++ bpp = 32;
++ }
++
++ DisplayOffset = vModeTable[ModeIndex].HorizontalActive * bpp / 8;
++ TerminalCount = vModeTable[ModeIndex].HorizontalActive * bpp / 64;
++ if (ColorDepth == YUV_444) {
++ TerminalCount = TerminalCount * 3 / 4;
++ }
++ if (((vModeTable[ModeIndex].HorizontalActive * bpp) % 64) != 0) {
++ TerminalCount++;
++ }
++
++ WriteMemoryLongClient(SCU_BASE, CRT1_DISPLAY_OFFSET + nCRTIndex*0x60, ((TerminalCount << TERMINAL_COUNT_BIT) | DisplayOffset));
++
++ // Set Color Format
++ WriteMemoryLongWithMASKClient(SCU_BASE, CRT1_CONTROL_REG + nCRTIndex*0x60, (ColorDepth << FORMAT_SELECT_BIT), FORMAT_SELECT_MASK);
++
++ // Set Threshold
++ temp = 0;
++ temp = (CRT_HIGH_THRESHOLD_VALUE << THRES_HIGHT_BIT) | (CRT_LOW_THRESHOLD_VALUE << THRES_LOW_BIT);
++ WriteMemoryLongClient(SCU_BASE, CRT1_THRESHOLD_REG + nCRTIndex*0x60, temp);
++
++ WriteMemoryLongClient(SCU_BASE, CRT1_VIDEO_PLL_REG + nCRTIndex*0x60, AST3000DCLKTableV[vModeTable[ModeIndex].PixelClock]);
++}
++
++void SetASTCenter1024ModeTiming (ULONG MMIOBase, int nCRTIndex, BYTE ModeIndex, BYTE ColorDepth)
++{
++ ULONG temp, RetraceStart, RetraceEnd, DisplayOffset, TerminalCount, bpp;
++
++ // Access CRT Engine
++ // SetPolarity
++ WriteMemoryLongWithMASKClient(SCU_BASE, CRT1_CONTROL_REG + nCRTIndex*0x60, (HOR_NEGATIVE << HOR_SYNC_SELECT_BIT) | (VER_NEGATIVE << VER_SYNC_SELECT_BIT), HOR_SYNC_SELECT_MASK|VER_SYNC_SELECT_MASK);
++
++ WriteMemoryLongClient(SCU_BASE, CRT1_CONTROL2_REG + nCRTIndex*0x60, 0xC0);
++
++ // Horizontal Timing
++ temp = 0;
++ temp = ((vModeTable[ModeIndex].HorizontalActive - 1) << HOR_ENABLE_END_BIT) | ((vModeTable[10].HorizontalTotal - 1) << HOR_TOTAL_BIT);
++ WriteMemoryLongClient(SCU_BASE, CRT1_HOR_TOTAL_END_REG + nCRTIndex*0x60, temp);
++
++ RetraceStart = vModeTable[10].HorizontalTotal - vModeTable[10].HBackPorch - vModeTable[10].HSyncTime - vModeTable[10].HLeftBorder - 1;
++ RetraceStart = RetraceStart - (vModeTable[10].HorizontalActive - vModeTable[ModeIndex].HorizontalActive) / 2 - 1;
++ RetraceEnd = (RetraceStart + vModeTable[10].HSyncTime);
++ temp = 0;
++ temp = (RetraceEnd << HOR_RETRACE_END_BIT) | (RetraceStart << HOR_RETRACE_START_BIT);
++ WriteMemoryLongClient(SCU_BASE, CRT1_HOR_RETRACE_REG + nCRTIndex*0x60, temp);
++
++ // Vertical Timing
++ temp = 0;
++ temp = ((vModeTable[ModeIndex].VerticalActive - 1) << VER_ENABLE_END_BIT) | ((vModeTable[10].VerticalTotal - 1) << VER_TOTAL_BIT);
++ WriteMemoryLongClient(SCU_BASE, CRT1_VER_TOTAL_END_REG + nCRTIndex*0x60, temp);
++
++ RetraceStart = vModeTable[10].VerticalTotal - vModeTable[10].VBackPorch - vModeTable[10].VSyncTime - vModeTable[10].VTopBorder - 1;
++ RetraceStart = RetraceStart - (vModeTable[10].VerticalActive - vModeTable[ModeIndex].VerticalActive) / 2 - 1;
++ RetraceEnd = (RetraceStart + vModeTable[10].VSyncTime);
++ temp = (RetraceEnd << VER_RETRACE_END_BIT) | (RetraceStart << VER_RETRACE_START_BIT);
++ WriteMemoryLongClient(SCU_BASE, CRT1_VER_RETRACE_REG + nCRTIndex*0x60, temp);
++
++ // Set CRT Display Offset and Terminal Count
++ if (ColorDepth == RGB_565) {
++ bpp = 16;
++ }
++ else {
++ bpp = 32;
++ }
++ DisplayOffset = vModeTable[ModeIndex].HorizontalActive * bpp / 8;
++ TerminalCount = vModeTable[ModeIndex].HorizontalActive * bpp / 64;
++ if (ColorDepth == YUV_444) {
++ TerminalCount = TerminalCount * 3 / 4;
++ }
++ if (((vModeTable[ModeIndex].HorizontalActive * bpp) % 64) != 0) {
++ TerminalCount++;
++ }
++
++ WriteMemoryLongClient(SCU_BASE, CRT1_DISPLAY_OFFSET + nCRTIndex*0x60, (TerminalCount << TERMINAL_COUNT_BIT) | DisplayOffset);
++
++ // Set Color Format
++ WriteMemoryLongWithMASKClient(SCU_BASE, CRT1_CONTROL_REG + nCRTIndex*0x60, (ColorDepth << FORMAT_SELECT_BIT), FORMAT_SELECT_MASK);
++
++ // Set Threshold
++ temp = 0;
++ temp = (CRT_HIGH_THRESHOLD_VALUE << THRES_HIGHT_BIT) | (CRT_LOW_THRESHOLD_VALUE << THRES_LOW_BIT);
++ WriteMemoryLongClient(SCU_BASE, CRT1_THRESHOLD_REG + nCRTIndex*0x60, temp);
++
++ // Set DCLK
++ WriteMemoryLongClient(SCU_BASE, CRT1_VIDEO_PLL_REG + nCRTIndex*0x60, AST3000DCLKTableV[vModeTable[ModeIndex].PixelClock]);
++
++}
++
++BOOL ASTSetModeV (ULONG MMIOBase, int nCRTIndex, ULONG VGABaseAddr, USHORT Horizontal, USHORT Vertical, BYTE ColorFormat, BYTE CenterMode)
++{
++ BYTE i, ModeIndex;
++ BOOL bDAC;
++ ULONG ulTemp;
++
++ // Access CRT Engine
++ //Enable CRT1 graph
++ WriteMemoryLongWithMASKClient(SCU_BASE, CRT1_CONTROL_REG + 0x60*nCRTIndex, GRAPH_DISPLAY_ON, GRAPH_DISPLAY_MASK);
++
++ // Set CRT Display Start Address
++ WriteMemoryLongWithMASKClient(SCU_BASE, CRT1_DISPLAY_ADDRESS + 0x60*nCRTIndex, VGABaseAddr, DISPLAY_ADDRESS_MASK);
++
++ for (i = 0; i < Mode60HZCount; i++) {
++ if ((vModeTable[i].HorizontalActive == Horizontal) && (vModeTable[i].VerticalActive == Vertical)) {
++
++ ModeIndex = i;
++
++ if (CenterMode != 1) {
++ SetASTModeTiming(MMIOBase, nCRTIndex, i, ColorFormat);
++ }
++ else {
++ SetASTCenter1024ModeTiming (MMIOBase, nCRTIndex, i, ColorFormat);
++ }
++
++ //use internal video out sigal and don't need use 7301
++ /*
++ bDAC = CheckDAC(nCRTIndex);
++
++ SetCH7301C(0,
++ nCRTIndex,
++ vModeTable[ModeIndex].PixelClock,
++ bDAC); //For RGB
++ */
++ return TRUE;
++ }
++ }
++
++ return FALSE;
++}
++
+diff --git a/board/aspeed/ast2300/crt.h b/board/aspeed/ast2300/crt.h
+new file mode 100755
+index 0000000..e7483be
+--- /dev/null
++++ b/board/aspeed/ast2300/crt.h
+@@ -0,0 +1,121 @@
++/*
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++ */
++#ifndef _CRT_H_
++#define _CRT_H_
++
++#ifdef Watcom
++#define CRT_REMAP_OFFSET 0x10000
++#else
++#define CRT_REMAP_OFFSET 0x0
++#endif
++
++/********************************************************/
++/* CRT register */
++/********************************************************/
++#define CRT_BASE_OFFSET 0x6000+CRT_REMAP_OFFSET
++
++#define CRT1_CONTROL_REG 0x00 + CRT_BASE_OFFSET
++ #define GRAPH_DISPLAY_BIT 0
++ #define GRAPH_DISPLAY_MASK (1<<0)
++ #define GRAPH_DISPLAY_ON 1
++ #define GRAPH_DISPLAY_OFF 0
++ #define FORMAT_SELECT_BIT 8
++ #define FORMAT_SELECT_MASK (3<<8)
++ #define HOR_SYNC_SELECT_BIT 16
++ #define HOR_SYNC_SELECT_MASK (1<<16)
++ #define HOR_NEGATIVE 1
++ #define HOR_POSITIVE 0
++ #define VER_SYNC_SELECT_BIT 17
++ #define VER_SYNC_SELECT_MASK (1<<17)
++ #define VER_NEGATIVE 1
++ #define VER_POSITIVE 0
++
++#define CRT1_CONTROL2_REG 0x04 + CRT_BASE_OFFSET
++
++#define CRT1_VIDEO_PLL_REG 0x0C + CRT_BASE_OFFSET
++ #define POST_DIV_BIT 18
++ #define POST_DIV_MASK 3<<18
++ #define DIV_1_1 0
++ //#define DIV_1_2 1
++ #define DIV_1_2 2
++ #define DIV_1_4 3
++
++#define CRT1_HOR_TOTAL_END_REG 0x10 + CRT_BASE_OFFSET
++ #define HOR_TOTAL_BIT 0
++ #define HOR_ENABLE_END_BIT 16
++
++#define CRT1_HOR_RETRACE_REG 0x14 + CRT_BASE_OFFSET
++ #define HOR_RETRACE_START_BIT 0
++ #define HOR_RETRACE_END_BIT 16
++
++#define CRT1_VER_TOTAL_END_REG 0x18 + CRT_BASE_OFFSET
++ #define VER_TOTAL_BIT 0
++ #define VER_ENABLE_END_BIT 16
++
++#define CRT1_VER_RETRACE_REG 0x1C + CRT_BASE_OFFSET
++ #define VER_RETRACE_START_BIT 0
++ #define VER_RETRACE_END_BIT 16
++
++#define CRT1_DISPLAY_ADDRESS 0x20 + CRT_BASE_OFFSET
++ #define DISPLAY_ADDRESS_MASK 0x0FFFFFFF
++
++#define CRT1_DISPLAY_OFFSET 0x24 + CRT_BASE_OFFSET
++ #define DISPLAY_OFFSET_ALIGN 7 /* 8 byte alignment*/
++ #define TERMINAL_COUNT_BIT 16
++
++#define CRT1_THRESHOLD_REG 0x28 + CRT_BASE_OFFSET
++ #define THRES_LOW_BIT 0
++ #define THRES_HIGHT_BIT 8
++
++#define CURSOR_POSITION 0x30 + OFFSET
++#define CURSOR_OFFSET 0x34 + OFFSET
++#define CURSOR_PATTERN 0x38 + OFFSET
++#define OSD_HORIZONTAL 0x40 + OFFSET
++#define OSD_VERTICAL 0x44 + OFFSET
++#define OSD_PATTERN 0x48 + OFFSET
++#define OSD_OFFSET 0x4C + OFFSET
++#define OSD_THRESHOLD 0x50 + OFFSET
++
++//Ch7301c
++#define DEVICE_ADDRESS_CH7301_CRT1 0xEA
++#define DEVICE_ADDRESS_CH7301_CRT2 0xEC
++
++
++#define DEVICE_SELECT_CH7301 0x3
++
++/* CH7301 Register Definition */
++#define CH7301_CD_REG 0x20
++ #define CD_DACT 0x0E
++ #define CD_DVIT 1 << 5
++#define CH7301_DC_REG 0x21
++#define CH7301_PM_REG 0x49
++
++BOOL CheckHotPlug(int nCRTIndex);
++BOOL CheckDAC(int nCRTIndex);
++
++BOOL ASTSetModeV (ULONG MMIOBase,
++ int nCRTIndex,
++ ULONG VGABaseAddr,
++ USHORT Horizontal,
++ USHORT Vertical,
++ BYTE ColorFormat,
++ BYTE CenterMode);
++
++BOOL SelCRTClock(ULONG MMIOBase,
++ int nCRTIndex,
++ USHORT Horizontal,
++ USHORT Vertical);
++
++void DisableCRT(ULONG MMIOBase, int nCRTIndex);
++void ClearCRTWithBlack(ULONG ulCRTAddr, int iWidth, int iHeight);
++
++#endif /* _CRT_H_ */
++
+diff --git a/board/aspeed/ast2300/flash.c b/board/aspeed/ast2300/flash.c
+new file mode 100755
+index 0000000..d611d0d
+--- /dev/null
++++ b/board/aspeed/ast2300/flash.c
+@@ -0,0 +1,1651 @@
++/*
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
++ * MA 02111-1307 USA
++ *
++ * History
++ * 01/20/2004 - combined variants of original driver.
++ * 01/22/2004 - Write performance enhancements for parallel chips (Tolunay)
++ * 01/23/2004 - Support for x8/x16 chips (Rune Raknerud)
++ * 01/27/2004 - Little endian support Ed Okerson
++ *
++ * Tested Architectures
++ * Port Width Chip Width # of banks Flash Chip Board
++ * 32 16 1 28F128J3 seranoa/eagle
++ * 64 16 1 28F128J3 seranoa/falcon
++ */
++// (Sun) This CFI driver is written for fixed-width flash chips.
++// It was not designed for flexible 8-bit/16-bit chips, which are the norm.
++// When those chips are connected to a bus in 8-bit mode, the address wires
++// right-shifted by 1.
++//FIXME: Fix the driver to auto-detect "16-bit flash wired in 8-bit mode".
++// Left-shift CFI offsets by 1 bit instead of doubling the #define values.
++
++/* The DEBUG define must be before common to enable debugging */
++// (Sun) Changed to DEBUG_FLASH because flash debug()s are too numerous.
++// #define DEBUG
++
++#include <common.h>
++#include <asm/processor.h>
++#include <asm/byteorder.h>
++#include <environment.h>
++#ifdef CONFIG_SYS_FLASH_CFI
++
++/*
++ * This file implements a Common Flash Interface (CFI) driver for U-Boot.
++ * The width of the port and the width of the chips are determined at initialization.
++ * These widths are used to calculate the address for access CFI data structures.
++ * It has been tested on an Intel Strataflash implementation and AMD 29F016D.
++ *
++ * References
++ * JEDEC Standard JESD68 - Common Flash Interface (CFI)
++ * JEDEC Standard JEP137-A Common Flash Interface (CFI) ID Codes
++ * Intel Application Note 646 Common Flash Interface (CFI) and Command Sets
++ * Intel 290667-008 3 Volt Intel StrataFlash Memory datasheet
++ *
++ * TODO
++ *
++ * Use Primary Extended Query table (PRI) and Alternate Algorithm Query
++ * Table (ALT) to determine if protection is available
++ *
++ * Add support for other command sets Use the PRI and ALT to determine command set
++ * Verify erase and program timeouts.
++ */
++
++#ifndef CONFIG_FLASH_BANKS_LIST
++#define CONFIG_FLASH_BANKS_LIST { CONFIG_SYS_FLASH_BASE }
++#endif
++
++#define FLASH_CMD_CFI 0x98
++#define FLASH_CMD_READ_ID 0x90
++#define FLASH_CMD_RESET 0xff
++#define FLASH_CMD_BLOCK_ERASE 0x20
++#define FLASH_CMD_ERASE_CONFIRM 0xD0
++#define FLASH_CMD_WRITE 0x40
++#define FLASH_CMD_PROTECT 0x60
++#define FLASH_CMD_PROTECT_SET 0x01
++#define FLASH_CMD_PROTECT_CLEAR 0xD0
++#define FLASH_CMD_CLEAR_STATUS 0x50
++#define FLASH_CMD_WRITE_TO_BUFFER 0xE8
++#define FLASH_CMD_WRITE_BUFFER_CONFIRM 0xD0
++
++#define FLASH_STATUS_DONE 0x80
++#define FLASH_STATUS_ESS 0x40
++#define FLASH_STATUS_ECLBS 0x20
++#define FLASH_STATUS_PSLBS 0x10
++#define FLASH_STATUS_VPENS 0x08
++#define FLASH_STATUS_PSS 0x04
++#define FLASH_STATUS_DPS 0x02
++#define FLASH_STATUS_R 0x01
++#define FLASH_STATUS_PROTECT 0x01
++
++#define AMD_CMD_RESET 0xF0
++#define AMD_CMD_WRITE 0xA0
++#define AMD_CMD_ERASE_START 0x80
++#define AMD_CMD_ERASE_SECTOR 0x30
++#define AMD_CMD_UNLOCK_START 0xAA
++#define AMD_CMD_UNLOCK_ACK 0x55
++#define AMD_CMD_WRITE_TO_BUFFER 0x25
++#define AMD_CMD_BUFFER_TO_FLASH 0x29
++
++#define AMD_STATUS_TOGGLE 0x40
++#define AMD_STATUS_ERROR 0x20
++//FIXME: These 3 were also changed for 8-bit/16-bit flash chips.
++#define AMD_ADDR_ERASE_START (0xAAA/info->portwidth)
++#define AMD_ADDR_START (0xAAA/info->portwidth)
++#define AMD_ADDR_ACK (0x555/info->portwidth)
++
++//FIXME: Fix the driver to auto-detect "16-bit flash wired in 8-bit mode".
++// Left-shift CFI offsets by 1 bit instead of doubling the #define values.
++#define FLASH_OFFSET_CFI (0xAA/info->portwidth)
++#define FLASH_OFFSET_CFI_RESP (0x20/info->portwidth)
++#define FLASH_OFFSET_CFI_RESP1 (0x22/info->portwidth)
++#define FLASH_OFFSET_CFI_RESP2 (0x24/info->portwidth)
++#define FLASH_OFFSET_PRIMARY_VENDOR (0x26/info->portwidth)
++#define FLASH_OFFSET_WTOUT (0x3E/info->portwidth)
++#define FLASH_OFFSET_WBTOUT (0x40/info->portwidth)
++#define FLASH_OFFSET_ETOUT (0x42/info->portwidth)
++#define FLASH_OFFSET_CETOUT (0x44/info->portwidth)
++#define FLASH_OFFSET_WMAX_TOUT (0x46/info->portwidth)
++#define FLASH_OFFSET_WBMAX_TOUT (0x48/info->portwidth)
++#define FLASH_OFFSET_EMAX_TOUT (0x4A/info->portwidth)
++#define FLASH_OFFSET_CEMAX_TOUT (0x4C/info->portwidth)
++#define FLASH_OFFSET_SIZE (0x4E/info->portwidth)
++#define FLASH_OFFSET_INTERFACE (0x50/info->portwidth)
++#define FLASH_OFFSET_BUFFER_SIZE (0x54/info->portwidth)
++#define FLASH_OFFSET_NUM_ERASE_REGIONS (0x58/info->portwidth)
++#define FLASH_OFFSET_ERASE_REGIONS (0x5A/info->portwidth)
++#define FLASH_OFFSET_PROTECT (0x02/info->portwidth)
++#define FLASH_OFFSET_USER_PROTECTION (0x85/info->portwidth)
++#define FLASH_OFFSET_INTEL_PROTECTION (0x81/info->portwidth)
++
++#define MAX_NUM_ERASE_REGIONS 4
++
++#define FLASH_MAN_CFI 0x01000000
++
++#define CFI_CMDSET_NONE 0
++#define CFI_CMDSET_INTEL_EXTENDED 1
++#define CFI_CMDSET_AMD_STANDARD 2
++#define CFI_CMDSET_INTEL_STANDARD 3
++#define CFI_CMDSET_AMD_EXTENDED 4
++#define CFI_CMDSET_MITSU_STANDARD 256
++#define CFI_CMDSET_MITSU_EXTENDED 257
++#define CFI_CMDSET_SST 258
++
++
++#ifdef CONFIG_SYS_FLASH_CFI_AMD_RESET /* needed for STM_ID_29W320DB on UC100 */
++# undef FLASH_CMD_RESET
++# define FLASH_CMD_RESET AMD_CMD_RESET /* use AMD-Reset instead */
++#endif
++
++
++typedef union {
++ unsigned char c;
++ unsigned short w;
++ unsigned long l;
++ unsigned long long ll;
++} cfiword_t;
++
++typedef union {
++ volatile unsigned char *cp;
++ volatile unsigned short *wp;
++ volatile unsigned long *lp;
++ volatile unsigned long long *llp;
++} cfiptr_t;
++
++/* use CFG_MAX_FLASH_BANKS_DETECT if defined */
++#ifdef CONFIG_SYS_MAX_FLASH_BANKS_DETECT
++static ulong bank_base[CONFIG_SYS_MAX_FLASH_BANKS_DETECT] = CONFIG_FLASH_BANKS_LIST;
++flash_info_t flash_info[CFG_MAX_FLASH_BANKS_DETECT]; /* FLASH chips info */
++#else
++static ulong bank_base[CONFIG_SYS_MAX_FLASH_BANKS] = CONFIG_FLASH_BANKS_LIST;
++flash_info_t flash_info[CONFIG_SYS_MAX_FLASH_BANKS]; /* FLASH chips info */
++#endif
++
++
++/*-----------------------------------------------------------------------
++ * Functions
++ */
++static void flash_add_byte (flash_info_t * info, cfiword_t * cword, uchar c);
++static void flash_make_cmd (flash_info_t * info, uchar cmd, void *cmdbuf);
++static void flash_write_cmd (flash_info_t * info, flash_sect_t sect, uint offset, uchar cmd);
++static void flash_write_cmd_nodbg (flash_info_t * info, flash_sect_t sect, uint offset, uchar cmd);
++static void flash_write_cmd_int (flash_info_t * info, flash_sect_t sect, uint offset, uchar cmd, int noDebug);
++static void flash_unlock_seq (flash_info_t * info, flash_sect_t sect);
++static int flash_isequal (flash_info_t * info, flash_sect_t sect, uint offset, uchar cmd);
++static int flash_isset (flash_info_t * info, flash_sect_t sect, uint offset, uchar cmd);
++static int flash_toggle (flash_info_t * info, flash_sect_t sect, uint offset, uchar cmd);
++static int flash_detect_cfi (flash_info_t * info);
++ulong flash_get_size (ulong base, int banknum);
++static int flash_write_cfiword (flash_info_t * info, ulong dest, cfiword_t cword);
++static int flash_full_status_check (flash_info_t * info, flash_sect_t sector,
++ ulong tout, char *prompt);
++static void write_buffer_abort_reset(flash_info_t * info, flash_sect_t sector);
++#if defined(CFG_ENV_IS_IN_FLASH) || defined(CFG_ENV_ADDR_REDUND) || (CFG_MONITOR_BASE >= CFG_FLASH_BASE)
++static flash_info_t *flash_get_info(ulong base);
++#endif
++#ifdef CONFIG_SYS_FLASH_USE_BUFFER_WRITE
++static int flash_write_cfibuffer (flash_info_t * info, ulong dest, uchar * cp, int len);
++static int flash_write_cfibuffer_amd (flash_info_t * info, ulong dest, uchar * cp, int len);
++#endif
++
++/*-----------------------------------------------------------------------
++ * create an address based on the offset and the port width
++ */
++inline uchar *flash_make_addr (flash_info_t * info, flash_sect_t sect, uint offset)
++{
++ return ((uchar *) (info->start[sect] + (offset * info->portwidth)));
++}
++
++/*-----------------------------------------------------------------------
++ * Debug support
++ */
++#ifdef DEBUG_FLASH
++static void print_longlong (char *str, unsigned long long data)
++{
++ int i;
++ char *cp;
++
++ cp = (unsigned char *) &data;
++ for (i = 0; i < 8; i++)
++ sprintf (&str[i * 2], "%2.2x", *cp++);
++}
++#endif
++
++#if defined(DEBUG_FLASH)
++static void flash_printqry (flash_info_t * info, flash_sect_t sect)
++{
++ cfiptr_t cptr;
++ int x, y;
++
++ for (x = 0; x < 0x40; x += 16U / info->portwidth) {
++ cptr.cp =
++ flash_make_addr (info, sect,
++ x + FLASH_OFFSET_CFI_RESP);
++ debug ("%p : ", cptr.cp);
++ for (y = 0; y < 16; y++) {
++ debug ("%2.2x ", cptr.cp[y]);
++ }
++ debug (" ");
++ for (y = 0; y < 16; y++) {
++ if (cptr.cp[y] >= 0x20 && cptr.cp[y] <= 0x7e) {
++ debug ("%c", cptr.cp[y]);
++ } else {
++ debug (".");
++ }
++ }
++ debug ("\n");
++ }
++}
++#endif
++
++/*-----------------------------------------------------------------------
++ * read a character at a port width address
++ */
++inline uchar flash_read_uchar (flash_info_t * info, uint offset)
++{
++ uchar *cp;
++
++ cp = flash_make_addr (info, 0, offset);
++#if defined(__LITTLE_ENDIAN)
++ return (cp[0]);
++#else
++ return (cp[info->portwidth - 1]);
++#endif
++}
++
++/*-----------------------------------------------------------------------
++ * read a short word by swapping for ppc format.
++ */
++#if 0
++static ushort flash_read_ushort (flash_info_t * info, flash_sect_t sect, uint offset)
++{
++ uchar *addr;
++ ushort retval;
++
++#ifdef DEBUG_FLASH
++ int x;
++#endif
++ addr = flash_make_addr (info, sect, offset);
++
++#ifdef DEBUG_FLASH
++ debug ("ushort addr is at %p info->portwidth = %d\n", addr,
++ info->portwidth);
++ for (x = 0; x < 2 * info->portwidth; x++) {
++ debug ("addr[%x] = 0x%x\n", x, addr[x]);
++ }
++#endif
++#if defined(__LITTLE_ENDIAN)
++ if (info->interface == FLASH_CFI_X8X16) {
++ retval = (addr[0] | (addr[2] << 8));
++ } else {
++ retval = (addr[0] | (addr[(info->portwidth)] << 8));
++ }
++#else
++ retval = ((addr[(2 * info->portwidth) - 1] << 8) |
++ addr[info->portwidth - 1]);
++#endif
++
++ debug ("retval = 0x%x\n", retval);
++ return retval;
++}
++#endif
++
++/*-----------------------------------------------------------------------
++ * read a long word by picking the least significant byte of each maximum
++ * port size word. Swap for ppc format.
++ */
++static ulong flash_read_long (flash_info_t * info, flash_sect_t sect, uint offset)
++{
++ uchar *addr;
++ ulong retval;
++#ifdef DEBUG_FLASH
++ int x;
++#endif
++#if 0
++ switch (info->interface) {
++ case FLASH_CFI_X8:
++ case FLASH_CFI_X16:
++ break;
++ case FLASH_CFI_X8X16:
++ offset <<= 1;
++ }
++#endif
++ // flash_make_addr() multiplies offset by info->portwidth.
++ addr = flash_make_addr (info, sect, offset);
++
++#ifdef DEBUG_FLASH
++ debug ("long addr is at %p info->portwidth = %d\n", addr,
++ info->portwidth);
++ for (x = 0; x < 4 * info->portwidth; x++) {
++ debug ("addr[%x] = 0x%x\n", x, addr[x]);
++ }
++#endif
++#if defined(__LITTLE_ENDIAN)
++ if (info->interface == FLASH_CFI_X8X16) {
++ retval = (addr[0] | (addr[2] << 8) | (addr[4] << 16) | (addr[6] << 24));
++ } else {
++ retval = (addr[0] | (addr[(info->portwidth)] << 8) |
++ (addr[(2 * info->portwidth)] << 16) |
++ (addr[(3 * info->portwidth)] << 24));
++ }
++#else
++ //FIXME: This undocumented code appears to match broken bus wiring.
++ retval = (addr[(2 * info->portwidth) - 1] << 24) |
++ (addr[(info->portwidth) - 1] << 16) |
++ (addr[(4 * info->portwidth) - 1] << 8) |
++ addr[(3 * info->portwidth) - 1];
++#endif
++ return retval;
++}
++
++/*-----------------------------------------------------------------------
++ */
++unsigned long flash_init (void)
++{
++ unsigned long size = 0;
++ int i;
++
++ /* Init: no FLASHes known */
++ for (i = 0; i < CONFIG_SYS_MAX_FLASH_BANKS; ++i) {
++ flash_info[i].flash_id = FLASH_UNKNOWN;
++ size += flash_info[i].size = flash_get_size (bank_base[i], i);
++ if (flash_info[i].flash_id == FLASH_UNKNOWN) {
++#ifndef CFG_FLASH_QUIET_TEST
++ printf ("## Unknown FLASH on Bank %d - Size = 0x%08lx = %ld MB\n",
++ i, flash_info[i].size, flash_info[i].size << 20);
++#endif /* CFG_FLASH_QUIET_TEST */
++ }
++ }
++
++ /* Monitor protection ON by default */
++#if (CONFIG_MONITOR_BASE >= CONFIG_SYS_FLASH_BASE)
++ flash_protect (FLAG_PROTECT_SET,
++ CONFIG_MONITOR_BASE,
++ CONFIG_MONITOR_BASE + monitor_flash_len - 1,
++ flash_get_info(CONFIG_MONITOR_BASE));
++#endif
++
++ /* Environment protection ON by default */
++#ifdef CONFIG_ENV_IS_IN_FLASH
++ flash_protect (FLAG_PROTECT_SET,
++ CONFIG_ENV_ADDR,
++ CONFIG_ENV_ADDR + CONFIG_ENV_SECT_SIZE - 1,
++ flash_get_info(CONFIG_ENV_ADDR));
++#endif
++
++ /* Redundant environment protection ON by default */
++#ifdef CONFIG_ENV_ADDR_REDUND
++ flash_protect (FLAG_PROTECT_SET,
++ CONFIG_ENV_ADDR_REDUND,
++ CONFIG_ENV_ADDR_REDUND + CONFIG_ENV_SIZE_REDUND - 1,
++ flash_get_info(CONFIG_ENV_ADDR_REDUND));
++#endif
++ return (size);
++}
++
++/*-----------------------------------------------------------------------
++ */
++#if defined(CONFIG_ENV_IS_IN_FLASH) || defined(CONFIG_ENV_ADDR_REDUND) || (CONFIG_MONITOR_BASE >= CONFIG_SYS_FLASH_BASE)
++static flash_info_t *flash_get_info(ulong base)
++{
++ int i;
++ flash_info_t * info = 0;
++
++ for (i = 0; i < CONFIG_SYS_MAX_FLASH_BANKS; i ++) {
++ info = & flash_info[i];
++ if (info->size && info->start[0] <= base &&
++ base <= info->start[0] + info->size - 1)
++ break;
++ }
++
++ return i == CONFIG_SYS_MAX_FLASH_BANKS ? 0 : info;
++}
++#endif
++
++/*-----------------------------------------------------------------------
++ */
++int flash_erase (flash_info_t * info, int s_first, int s_last)
++{
++ int rcode = 0;
++ int prot;
++ flash_sect_t sect;
++ uchar ch;
++ uchar *addr;
++
++ if (info->flash_id != FLASH_MAN_CFI) {
++ puts ("Can't erase unknown flash type - aborted\n");
++ return 1;
++ }
++ if ((s_first < 0) || (s_first > s_last)) {
++ puts ("- no sectors to erase\n");
++ return 1;
++ }
++
++ prot = 0;
++ for (sect = s_first; sect <= s_last; ++sect) {
++ if (info->protect[sect]) {
++ prot++;
++ }
++ }
++ if (prot) {
++ printf ("- Warning: %d protected sectors will not be erased!\n", prot);
++ } else {
++ putc ('\n');
++ }
++
++
++ for (sect = s_first; sect <= s_last; sect++) {
++ if (info->protect[sect] == 0) { /* not protected */
++ switch (info->vendor) {
++ case CFI_CMDSET_INTEL_STANDARD:
++ case CFI_CMDSET_INTEL_EXTENDED:
++ flash_write_cmd (info, sect, 0, FLASH_CMD_CLEAR_STATUS);
++ flash_write_cmd (info, sect, 0, FLASH_CMD_BLOCK_ERASE);
++ flash_write_cmd (info, sect, 0, FLASH_CMD_ERASE_CONFIRM);
++ break;
++ case CFI_CMDSET_AMD_STANDARD:
++ case CFI_CMDSET_AMD_EXTENDED:
++ flash_unlock_seq (info, sect);
++ flash_write_cmd (info, sect, AMD_ADDR_ERASE_START,
++ AMD_CMD_ERASE_START);
++ flash_unlock_seq (info, sect);
++ flash_write_cmd (info, sect, 0, AMD_CMD_ERASE_SECTOR);
++
++ /* toggle */
++ addr = flash_make_addr (info, sect, 0);
++ do {
++ ch = *(volatile uchar *)(addr);
++ } while ( ((ch & 0x80) == 0) || (ch != 0xFF) );
++ break;
++ default:
++ debug ("Unkown flash vendor %d\n",
++ info->vendor);
++ break;
++ }
++
++ if (flash_full_status_check
++ (info, sect, info->erase_blk_tout, "erase")) {
++ rcode = 1;
++ } else
++ putc ('.');
++ }
++ }
++ puts (" done\n");
++ return rcode;
++}
++
++/*-----------------------------------------------------------------------
++ */
++void flash_print_info (flash_info_t * info)
++{
++ int i;
++
++ if (info->flash_id != FLASH_MAN_CFI) {
++ puts ("missing or unknown FLASH type\n");
++ return;
++ }
++
++ printf ("CFI conformant FLASH (%d x %d)",
++ (info->portwidth << 3), (info->chipwidth << 3));
++ printf (" Size: %ld MB in %d Sectors\n",
++ info->size >> 20, info->sector_count);
++ printf (" Erase timeout %ld ms, write timeout %ld ms, buffer write timeout %ld ms, buffer size %d\n",
++ info->erase_blk_tout,
++ info->write_tout,
++ info->buffer_write_tout,
++ info->buffer_size);
++
++ puts (" Sector Start Addresses:");
++ for (i = 0; i < info->sector_count; ++i) {
++#ifdef CFG_FLASH_EMPTY_INFO
++ int k;
++ int size;
++ int erased;
++ volatile unsigned long *flash;
++
++ /*
++ * Check if whole sector is erased
++ */
++ if (i != (info->sector_count - 1))
++ size = info->start[i + 1] - info->start[i];
++ else
++ size = info->start[0] + info->size - info->start[i];
++ erased = 1;
++ flash = (volatile unsigned long *) info->start[i];
++ size = size >> 2; /* divide by 4 for longword access */
++ for (k = 0; k < size; k++) {
++ if (*flash++ != 0xffffffff) {
++ erased = 0;
++ break;
++ }
++ }
++
++ if ((i % 5) == 0)
++ printf ("\n");
++ /* print empty and read-only info */
++ printf (" %08lX%s%s",
++ info->start[i],
++ erased ? " E" : " ",
++ info->protect[i] ? "RO " : " ");
++#else /* ! CFG_FLASH_EMPTY_INFO */
++ if ((i % 5) == 0)
++ printf ("\n ");
++ printf (" %08lX%s",
++ info->start[i], info->protect[i] ? " (RO)" : " ");
++#endif
++ }
++ putc ('\n');
++ return;
++}
++
++/*-----------------------------------------------------------------------
++ * Copy memory to flash, returns:
++ * 0 - OK
++ * 1 - write timeout
++ * 2 - Flash not erased
++ */
++int write_buff (flash_info_t * info, uchar * src, ulong addr, ulong cnt)
++{
++ ulong wp;
++ ulong cp;
++ int aln;
++ cfiword_t cword;
++ int i, rc;
++
++#ifdef CONFIG_SYS_FLASH_USE_BUFFER_WRITE
++ unsigned char pat[] = {'|', '-', '/', '\\'};
++ int patcnt = 0;
++ int buffered_size;
++#endif
++ /* get lower aligned address */
++ /* get lower aligned address */
++ wp = (addr & ~(info->portwidth - 1));
++
++ /* handle unaligned start */
++ if ((aln = addr - wp) != 0) {
++ cword.l = 0;
++ cp = wp;
++ for (i = 0; i < aln; ++i, ++cp)
++ flash_add_byte (info, &cword, (*(uchar *) cp));
++
++ for (; (i < info->portwidth) && (cnt > 0); i++) {
++ flash_add_byte (info, &cword, *src++);
++ cnt--;
++ cp++;
++ }
++ for (; (cnt == 0) && (i < info->portwidth); ++i, ++cp)
++ flash_add_byte (info, &cword, (*(uchar *) cp));
++ if ((rc = flash_write_cfiword (info, wp, cword)) != 0)
++ return rc;
++ wp = cp;
++ }
++
++ /* handle the aligned part */
++#ifdef CONFIG_SYS_FLASH_USE_BUFFER_WRITE
++ buffered_size = (info->portwidth / info->chipwidth);
++ buffered_size *= info->buffer_size;
++ while (cnt >= info->portwidth) {
++ /* Show processing */
++ if ((++patcnt % 256) == 0)
++ printf("%c\b", pat[(patcnt / 256) & 0x03]);
++
++ i = buffered_size > cnt ? cnt : buffered_size;
++ if ((rc = flash_write_cfibuffer (info, wp, src, i)) != ERR_OK)
++ return rc;
++ i -= i & (info->portwidth - 1);
++ wp += i;
++ src += i;
++ cnt -= i;
++ }
++#else
++ while (cnt >= info->portwidth) {
++ cword.l = 0;
++ for (i = 0; i < info->portwidth; i++) {
++ flash_add_byte (info, &cword, *src++);
++ }
++ if ((rc = flash_write_cfiword (info, wp, cword)) != 0)
++ return rc;
++ wp += info->portwidth;
++ cnt -= info->portwidth;
++ }
++#endif /* CONFIG_SYS_FLASH_USE_BUFFER_WRITE */
++ if (cnt == 0) {
++ return (0);
++ }
++
++ /*
++ * handle unaligned tail bytes
++ */
++ cword.l = 0;
++ for (i = 0, cp = wp; (i < info->portwidth) && (cnt > 0); ++i, ++cp) {
++ flash_add_byte (info, &cword, *src++);
++ --cnt;
++ }
++ for (; i < info->portwidth; ++i, ++cp) {
++ flash_add_byte (info, &cword, (*(uchar *) cp));
++ }
++
++ return flash_write_cfiword (info, wp, cword);
++}
++
++/*-----------------------------------------------------------------------
++ */
++#ifdef CFG_FLASH_PROTECTION
++
++int flash_real_protect (flash_info_t * info, long sector, int prot)
++{
++ int retcode = 0;
++
++ flash_write_cmd (info, sector, 0, FLASH_CMD_CLEAR_STATUS);
++ flash_write_cmd (info, sector, 0, FLASH_CMD_PROTECT);
++ if (prot)
++ flash_write_cmd (info, sector, 0, FLASH_CMD_PROTECT_SET);
++ else
++ flash_write_cmd (info, sector, 0, FLASH_CMD_PROTECT_CLEAR);
++
++ if ((retcode =
++ flash_full_status_check (info, sector, info->erase_blk_tout,
++ prot ? "protect" : "unprotect")) == 0) {
++
++ info->protect[sector] = prot;
++ /* Intel's unprotect unprotects all locking */
++ if (prot == 0) {
++ flash_sect_t i;
++
++ for (i = 0; i < info->sector_count; i++) {
++ if (info->protect[i])
++ flash_real_protect (info, i, 1);
++ }
++ }
++ }
++ return retcode;
++}
++
++/*-----------------------------------------------------------------------
++ * flash_read_user_serial - read the OneTimeProgramming cells
++ */
++void flash_read_user_serial (flash_info_t * info, void *buffer, int offset,
++ int len)
++{
++ uchar *src;
++ uchar *dst;
++
++ dst = buffer;
++ src = flash_make_addr (info, 0, FLASH_OFFSET_USER_PROTECTION);
++ flash_write_cmd (info, 0, 0, FLASH_CMD_READ_ID);
++ memcpy (dst, src + offset, len);
++ flash_write_cmd (info, 0, 0, info->cmd_reset);
++}
++
++/*
++ * flash_read_factory_serial - read the device Id from the protection area
++ */
++void flash_read_factory_serial (flash_info_t * info, void *buffer, int offset,
++ int len)
++{
++ uchar *src;
++
++ src = flash_make_addr (info, 0, FLASH_OFFSET_INTEL_PROTECTION);
++ flash_write_cmd (info, 0, 0, FLASH_CMD_READ_ID);
++ memcpy (buffer, src + offset, len);
++ flash_write_cmd (info, 0, 0, info->cmd_reset);
++}
++
++#endif /* CFG_FLASH_PROTECTION */
++
++/*
++ * flash_is_busy - check to see if the flash is busy
++ * This routine checks the status of the chip and returns true if the chip is busy
++ */
++static int flash_is_busy (flash_info_t * info, flash_sect_t sect)
++{
++ int retval;
++
++ switch (info->vendor) {
++ case CFI_CMDSET_INTEL_STANDARD:
++ case CFI_CMDSET_INTEL_EXTENDED:
++ retval = !flash_isset (info, sect, 0, FLASH_STATUS_DONE);
++ break;
++ case CFI_CMDSET_AMD_STANDARD:
++ case CFI_CMDSET_AMD_EXTENDED:
++ retval = flash_toggle (info, sect, 0, AMD_STATUS_TOGGLE);
++ break;
++ default:
++ retval = 0;
++ }
++#ifdef DEBUG_FLASH
++ if (retval)
++ debug ("flash_is_busy: %d\n", retval);
++#endif
++ return retval;
++}
++
++/*-----------------------------------------------------------------------
++ * wait for XSR.7 to be set. Time out with an error if it does not.
++ * This routine does not set the flash to read-array mode.
++ */
++static int flash_status_check (flash_info_t * info, flash_sect_t sector,
++ ulong tout, char *prompt)
++{
++ ulong start, now;
++
++ /* Wait for command completion */
++ // (Sun) Fix order of checking time so it works when the CPU is very
++ // slow, e.g., single-stepping or emulation.
++ start = get_timer (0);
++ while (now = get_timer(start),
++ flash_is_busy (info, sector))
++ {
++ if (now > info->erase_blk_tout) {
++ printf ("Flash %s timeout at address %lx data %lx\n",
++ prompt, info->start[sector],
++ flash_read_long (info, sector, 0));
++ flash_write_cmd (info, sector, 0, info->cmd_reset);
++ return ERR_TIMOUT;
++ }
++ }
++ return ERR_OK;
++}
++
++/*-----------------------------------------------------------------------
++ * Wait for XSR.7 to be set, if it times out print an error, otherwise do a full status check.
++ * This routine sets the flash to read-array mode.
++ */
++static int flash_full_status_check (flash_info_t * info, flash_sect_t sector,
++ ulong tout, char *prompt)
++{
++ int retcode;
++
++ retcode = flash_status_check (info, sector, tout, prompt);
++ switch (info->vendor) {
++ case CFI_CMDSET_INTEL_EXTENDED:
++ case CFI_CMDSET_INTEL_STANDARD:
++ if ((retcode != ERR_OK)
++ && !flash_isequal (info, sector, 0, FLASH_STATUS_DONE)) {
++ retcode = ERR_INVAL;
++ printf ("Flash %s error at address %lx\n", prompt,
++ info->start[sector]);
++ if (flash_isset (info, sector, 0, FLASH_STATUS_ECLBS | FLASH_STATUS_PSLBS)) {
++ puts ("Command Sequence Error.\n");
++ } else if (flash_isset (info, sector, 0, FLASH_STATUS_ECLBS)) {
++ puts ("Block Erase Error.\n");
++ retcode = ERR_NOT_ERASED;
++ } else if (flash_isset (info, sector, 0, FLASH_STATUS_PSLBS)) {
++ puts ("Locking Error\n");
++ }
++ if (flash_isset (info, sector, 0, FLASH_STATUS_DPS)) {
++ puts ("Block locked.\n");
++ retcode = ERR_PROTECTED;
++ }
++ if (flash_isset (info, sector, 0, FLASH_STATUS_VPENS))
++ puts ("Vpp Low Error.\n");
++ }
++ flash_write_cmd (info, sector, 0, info->cmd_reset);
++ break;
++ default:
++ break;
++ }
++ return retcode;
++}
++
++static void write_buffer_abort_reset(flash_info_t * info, flash_sect_t sector)
++{
++ flash_write_cmd (info, sector, 0xaaa, 0xaa);
++ flash_write_cmd (info, sector, 0x555, 0x55);
++ flash_write_cmd (info, sector, 0xaaa, 0xf0);
++}
++
++/*-----------------------------------------------------------------------
++ */
++static void flash_add_byte (flash_info_t * info, cfiword_t * cword, uchar c)
++{
++#if defined(__LITTLE_ENDIAN)
++ unsigned short w;
++ unsigned int l;
++ unsigned long long ll;
++#endif
++
++ switch (info->portwidth) {
++ case FLASH_CFI_8BIT:
++ cword->c = c;
++ break;
++ case FLASH_CFI_16BIT:
++#if defined(__LITTLE_ENDIAN)
++ w = c;
++ w <<= 8;
++ cword->w = (cword->w >> 8) | w;
++#else
++ cword->w = (cword->w << 8) | c;
++#endif
++ break;
++ case FLASH_CFI_32BIT:
++#if defined(__LITTLE_ENDIAN)
++ l = c;
++ l <<= 24;
++ cword->l = (cword->l >> 8) | l;
++#else
++ cword->l = (cword->l << 8) | c;
++#endif
++ break;
++ case FLASH_CFI_64BIT:
++#if defined(__LITTLE_ENDIAN)
++ ll = c;
++ ll <<= 56;
++ cword->ll = (cword->ll >> 8) | ll;
++#else
++ cword->ll = (cword->ll << 8) | c;
++#endif
++ break;
++ }
++}
++
++
++/*-----------------------------------------------------------------------
++ * make a proper sized command based on the port and chip widths
++ */
++static void flash_make_cmd (flash_info_t * info, uchar cmd, void *cmdbuf)
++{
++ int i;
++ uchar *cp = (uchar *) cmdbuf;
++
++#if defined(__LITTLE_ENDIAN)
++ for (i = info->portwidth; i > 0; i--)
++#else
++ for (i = 1; i <= info->portwidth; i++)
++#endif
++ *cp++ = (i & (info->chipwidth - 1)) ? '\0' : cmd;
++}
++
++/*
++ * Write a proper sized command to the correct address
++ */
++static void
++flash_write_cmd (flash_info_t * info, flash_sect_t sect, uint offset,
++ uchar cmd)
++{
++#ifdef DEBUG_FLASH
++ const int noDebug = 0;
++#else
++ const int noDebug = 1;
++#endif
++ return flash_write_cmd_int(info, sect, offset, cmd, noDebug);
++}
++static void
++flash_write_cmd_nodbg (flash_info_t * info, flash_sect_t sect, uint offset,
++ uchar cmd)
++{
++ return flash_write_cmd_int(info, sect, offset, cmd, 1);
++}
++
++static void
++flash_write_cmd_int (flash_info_t * info, flash_sect_t sect, uint offset,
++ uchar cmd, int noDebug)
++{
++
++ volatile cfiptr_t addr;
++ cfiword_t cword;
++
++ addr.cp = flash_make_addr (info, sect, offset);
++ flash_make_cmd (info, cmd, &cword);
++ switch (info->portwidth) {
++ case FLASH_CFI_8BIT:
++ if (noDebug == 0)
++ debug ("fwc addr %p cmd %x %x 8bit x %d bit\n", addr.cp, cmd,
++ cword.c, info->chipwidth << CFI_FLASH_SHIFT_WIDTH);
++ *addr.cp = cword.c;
++ break;
++ case FLASH_CFI_16BIT:
++ if (noDebug == 0)
++ debug ("fwc addr %p cmd %x %4.4x 16bit x %d bit\n", addr.wp,
++ cmd, cword.w,
++ info->chipwidth << CFI_FLASH_SHIFT_WIDTH);
++ *addr.wp = cword.w;
++ break;
++ case FLASH_CFI_32BIT:
++ if (noDebug == 0)
++ debug ("fwc addr %p cmd %x %8.8lx 32bit x %d bit\n", addr.lp,
++ cmd, cword.l,
++ info->chipwidth << CFI_FLASH_SHIFT_WIDTH);
++ *addr.lp = cword.l;
++ break;
++ case FLASH_CFI_64BIT:
++#ifdef DEBUG_FLASH
++ if (noDebug == 0)
++ {
++ char str[20];
++
++ print_longlong (str, cword.ll);
++
++ debug ("fwrite addr %p cmd %x %s 64 bit x %d bit\n",
++ addr.llp, cmd, str,
++ info->chipwidth << CFI_FLASH_SHIFT_WIDTH);
++ }
++#endif
++ *addr.llp = cword.ll;
++ break;
++ }
++}
++
++static void flash_unlock_seq (flash_info_t * info, flash_sect_t sect)
++{
++ flash_write_cmd_nodbg (info, sect, AMD_ADDR_START, AMD_CMD_UNLOCK_START);
++ flash_write_cmd_nodbg (info, sect, AMD_ADDR_ACK, AMD_CMD_UNLOCK_ACK);
++}
++
++/*-----------------------------------------------------------------------
++ */
++static int flash_isequal (flash_info_t * info, flash_sect_t sect, uint offset, uchar cmd)
++{
++ cfiptr_t cptr;
++ cfiword_t cword;
++ int retval;
++#ifdef DEBUG_FLASH
++ const int dbg = 1;
++#else
++ const int dbg = 0;
++#endif
++ cptr.cp = flash_make_addr (info, sect, offset);
++ flash_make_cmd (info, cmd, &cword);
++
++ if (dbg)
++ debug ("is= cmd %x(%c) addr %p ", cmd, cmd, cptr.cp);
++ switch (info->portwidth) {
++ case FLASH_CFI_8BIT:
++ if (dbg)
++ debug ("is= %x %x\n", cptr.cp[0], cword.c);
++ retval = (cptr.cp[0] == cword.c);
++ break;
++ case FLASH_CFI_16BIT:
++ if (dbg)
++ debug ("is= %4.4x %4.4x\n", cptr.wp[0], cword.w);
++ retval = (cptr.wp[0] == cword.w);
++ break;
++ case FLASH_CFI_32BIT:
++ if (dbg)
++ debug ("is= %8.8lx %8.8lx\n", cptr.lp[0], cword.l);
++ retval = (cptr.lp[0] == cword.l);
++ break;
++ case FLASH_CFI_64BIT:
++#ifdef DEBUG_FLASH
++ {
++ char str1[20];
++ char str2[20];
++
++ print_longlong (str1, cptr.llp[0]);
++ print_longlong (str2, cword.ll);
++ debug ("is= %s %s\n", str1, str2);
++ }
++#endif
++ retval = (cptr.llp[0] == cword.ll);
++ break;
++ default:
++ retval = 0;
++ break;
++ }
++ return retval;
++}
++
++/*-----------------------------------------------------------------------
++ */
++static int flash_isset (flash_info_t * info, flash_sect_t sect, uint offset, uchar cmd)
++{
++ cfiptr_t cptr;
++ cfiword_t cword;
++ int retval;
++
++ cptr.cp = flash_make_addr (info, sect, offset);
++ flash_make_cmd (info, cmd, &cword);
++ switch (info->portwidth) {
++ case FLASH_CFI_8BIT:
++ retval = ((cptr.cp[0] & cword.c) == cword.c);
++ break;
++ case FLASH_CFI_16BIT:
++ retval = ((cptr.wp[0] & cword.w) == cword.w);
++ break;
++ case FLASH_CFI_32BIT:
++ retval = ((cptr.lp[0] & cword.l) == cword.l);
++ break;
++ case FLASH_CFI_64BIT:
++ retval = ((cptr.llp[0] & cword.ll) == cword.ll);
++ break;
++ default:
++ retval = 0;
++ break;
++ }
++ return retval;
++}
++
++/*-----------------------------------------------------------------------
++ */
++static int flash_toggle (flash_info_t * info, flash_sect_t sect, uint offset, uchar cmd)
++{
++ cfiptr_t cptr;
++ cfiword_t cword;
++ int retval;
++
++ cptr.cp = flash_make_addr (info, sect, offset);
++ flash_make_cmd (info, cmd, &cword);
++ switch (info->portwidth) {
++ case FLASH_CFI_8BIT:
++ retval = ((cptr.cp[0] & cword.c) != (cptr.cp[0] & cword.c));
++ break;
++ case FLASH_CFI_16BIT:
++ retval = ((cptr.wp[0] & cword.w) != (cptr.wp[0] & cword.w));
++ break;
++ case FLASH_CFI_32BIT:
++ retval = ((cptr.lp[0] & cword.l) != (cptr.lp[0] & cword.l));
++ break;
++ case FLASH_CFI_64BIT:
++ retval = ((cptr.llp[0] & cword.ll) !=
++ (cptr.llp[0] & cword.ll));
++ break;
++ default:
++ retval = 0;
++ break;
++ }
++ return retval;
++}
++
++/*-----------------------------------------------------------------------
++ * detect if flash is compatible with the Common Flash Interface (CFI)
++ * http://www.jedec.org/download/search/jesd68.pdf
++ *
++*/
++static int flash_detect_cfi (flash_info_t * info)
++{
++ ulong data;
++
++ debug ("flash_detect_cfi()... ");
++
++#if defined(CONFIG_FLASH_AST2300)
++ data = *(ulong *)(0x1e6e2070); /* hardware traping */
++ if (data & 0x10) /* D[4]: 0/1 (8/16) */
++ info->portwidth = FLASH_CFI_16BIT;
++ else
++ info->portwidth = FLASH_CFI_8BIT;
++#else
++ info->portwidth = FLASH_CFI_8BIT;
++#endif
++
++ {
++ for (info->chipwidth = FLASH_CFI_BY8;
++ info->chipwidth <= info->portwidth;
++ info->chipwidth <<= 1) {
++ flash_write_cmd (info, 0, 0, FLASH_CMD_RESET);
++ flash_write_cmd (info, 0, FLASH_OFFSET_CFI, FLASH_CMD_CFI);
++ if (flash_isequal (info, 0, FLASH_OFFSET_CFI_RESP, 'Q')
++ //FIXME: Next 3 lines were changed for 8-bit/16-bit flash chips.
++ && flash_isequal (info, 0, FLASH_OFFSET_CFI_RESP1, 'R')
++ && flash_isequal (info, 0, FLASH_OFFSET_CFI_RESP2, 'Y')) {
++ info->interface = flash_read_uchar (info, FLASH_OFFSET_INTERFACE);
++ debug ("device interface is %d\n",
++ info->interface);
++ debug ("found port %d chip %d ",
++ info->portwidth, info->chipwidth);
++ debug ("port %d bits chip %d bits\n",
++ info->portwidth << CFI_FLASH_SHIFT_WIDTH,
++ info->chipwidth << CFI_FLASH_SHIFT_WIDTH);
++ return 1;
++ }
++ }
++ }
++ debug ("not found\n");
++ return 0;
++}
++
++/*
++ * The following code cannot be run from FLASH!
++ *
++ */
++ulong flash_get_size (ulong base, int banknum)
++{
++ flash_info_t *info = &flash_info[banknum];
++ int i, j;
++ flash_sect_t sect_cnt;
++ unsigned long sector;
++ unsigned long tmp;
++ int size_ratio;
++ uchar num_erase_regions;
++ int erase_region_size;
++ int erase_region_count;
++
++ info->start[0] = base;
++
++ if (flash_detect_cfi (info)) {
++ info->vendor = flash_read_uchar (info, FLASH_OFFSET_PRIMARY_VENDOR);
++#if defined(DEBUG_FLASH)
++ flash_printqry (info, 0);
++#endif
++ switch (info->vendor) {
++ case CFI_CMDSET_INTEL_STANDARD:
++ case CFI_CMDSET_INTEL_EXTENDED:
++ default:
++ info->cmd_reset = FLASH_CMD_RESET;
++ break;
++ case CFI_CMDSET_AMD_STANDARD:
++ case CFI_CMDSET_AMD_EXTENDED:
++ info->cmd_reset = AMD_CMD_RESET;
++ break;
++ }
++
++ debugX(2, "manufacturer is %d\n", info->vendor);
++ size_ratio = info->portwidth / info->chipwidth;
++ /* if the chip is x8/x16 reduce the ratio by half */
++#if 0
++ if ((info->interface == FLASH_CFI_X8X16)
++ && (info->chipwidth == FLASH_CFI_BY8)) {
++ size_ratio >>= 1;
++ }
++#endif
++ num_erase_regions = flash_read_uchar (info, FLASH_OFFSET_NUM_ERASE_REGIONS);
++ debugX(2, "size_ratio %d port %d bits chip %d bits\n",
++ size_ratio, info->portwidth << CFI_FLASH_SHIFT_WIDTH,
++ info->chipwidth << CFI_FLASH_SHIFT_WIDTH);
++ debugX(2, "found %d erase regions\n", num_erase_regions);
++ sect_cnt = 0;
++ sector = base;
++ for (i = 0; i < num_erase_regions; i++) {
++ if (i > MAX_NUM_ERASE_REGIONS) {
++ printf ("%d erase regions found, only %d used\n",
++ num_erase_regions, MAX_NUM_ERASE_REGIONS);
++ break;
++ }
++ // CFI Erase Block Region Information:
++ // Bits[31:16] = sect_size/256, 0 means 128-byte
++ // Bits[15:0] = num_sectors - 1
++ tmp = flash_read_long(info, 0,
++ FLASH_OFFSET_ERASE_REGIONS + i * 4);
++ debug("CFI erase block region info[%d]: 0x%08x, ",
++ i, tmp);
++ erase_region_count = (tmp & 0xffff) + 1;
++ tmp >>= 16;
++ erase_region_size = (tmp ? tmp * 256 : 128);
++ debug ("erase_region_count=%d erase_region_size=%d\n",
++ erase_region_count, erase_region_size);
++#if 0
++ erase_region_size = CFG_FLASH_SECTOR_SIZE; // Commented out
++ erase_region_count = CFG_FLASH_SECTOR_COUNT; // Commented out
++#endif
++ if (sect_cnt + erase_region_count > CONFIG_SYS_MAX_FLASH_SECT) {
++ printf("Warning: Erase region %d adds too many flash sectors"
++ " %d+%d; reducing to fit total limit of %d\n",
++ i, sect_cnt, erase_region_count, CONFIG_SYS_MAX_FLASH_SECT);
++ erase_region_count = CONFIG_SYS_MAX_FLASH_SECT - sect_cnt;
++ }
++ for (j = 0; j < erase_region_count; j++) {
++ info->start[sect_cnt] = sector;
++ sector += (erase_region_size * size_ratio);
++
++ /*
++ * Only read protection status from supported devices (intel...)
++ */
++ switch (info->vendor) {
++ case CFI_CMDSET_INTEL_EXTENDED:
++ case CFI_CMDSET_INTEL_STANDARD:
++ info->protect[sect_cnt] =
++ flash_isset (info, sect_cnt,
++ FLASH_OFFSET_PROTECT,
++ FLASH_STATUS_PROTECT);
++ break;
++ default:
++ info->protect[sect_cnt] = 0; /* default: not protected */
++ }
++
++ sect_cnt++;
++ }
++ }
++
++ info->sector_count = sect_cnt;
++ /* multiply the size by the number of chips */
++ // info->size = (1 << flash_read_uchar (info, FLASH_OFFSET_SIZE)) * size_ratio;
++ // Use only the sectors that fit within the flash_info array size.
++ info->size = sector - base;
++ printf("Flash bank %d at %08x has 0x%x bytes in %d sectors"
++ " (chipSize 1<<%d, size_ratio %d).\n",
++ banknum, base, info->size, info->sector_count,
++ flash_read_uchar(info, FLASH_OFFSET_SIZE), size_ratio);
++
++ info->buffer_size = (1 << flash_read_uchar (info, FLASH_OFFSET_BUFFER_SIZE));
++ /* Limit the buffer size to 32bytes to meet most of AMD-styles flash's minimum requirement */
++ if (info->buffer_size > 32)
++ info->buffer_size = 32;
++ tmp = 1 << flash_read_uchar (info, FLASH_OFFSET_ETOUT);
++ info->erase_blk_tout = (tmp * (1 << flash_read_uchar (info, FLASH_OFFSET_EMAX_TOUT)));
++ tmp = 1 << flash_read_uchar (info, FLASH_OFFSET_WBTOUT);
++ info->buffer_write_tout = (tmp * (1 << flash_read_uchar (info, FLASH_OFFSET_WBMAX_TOUT)));
++ tmp = 1 << flash_read_uchar (info, FLASH_OFFSET_WTOUT);
++ info->write_tout = (tmp * (1 << flash_read_uchar (info, FLASH_OFFSET_WMAX_TOUT))) / 1000;
++ info->flash_id = FLASH_MAN_CFI;
++#if 0
++ if ((info->interface == FLASH_CFI_X8X16) && (info->chipwidth == FLASH_CFI_BY8)) {
++ info->portwidth >>= 1; /* XXX - Need to test on x8/x16 in parallel. */
++ }
++#endif
++ }
++
++ flash_write_cmd (info, 0, 0, info->cmd_reset);
++ return (info->size);
++}
++
++
++/*-----------------------------------------------------------------------
++ */
++static int flash_write_cfiword (flash_info_t * info, ulong dest,
++ cfiword_t cword)
++{
++
++ cfiptr_t ctladdr;
++ cfiptr_t cptr;
++ int flag;
++
++ ctladdr.cp = flash_make_addr (info, 0, 0);
++ cptr.cp = (uchar *) dest;
++
++
++ /* Check if Flash is (sufficiently) erased */
++ switch (info->portwidth) {
++ case FLASH_CFI_8BIT:
++ flag = ((cptr.cp[0] & cword.c) == cword.c);
++ break;
++ case FLASH_CFI_16BIT:
++ flag = ((cptr.wp[0] & cword.w) == cword.w);
++ break;
++ case FLASH_CFI_32BIT:
++ flag = ((cptr.lp[0] & cword.l) == cword.l);
++ break;
++ case FLASH_CFI_64BIT:
++ flag = ((cptr.llp[0] & cword.ll) == cword.ll);
++ break;
++ default:
++ return 2;
++ }
++ if (!flag)
++ return 2;
++
++ /* Disable interrupts which might cause a timeout here */
++ flag = disable_interrupts ();
++
++ switch (info->vendor) {
++ case CFI_CMDSET_INTEL_EXTENDED:
++ case CFI_CMDSET_INTEL_STANDARD:
++ flash_write_cmd_nodbg (info, 0, 0, FLASH_CMD_CLEAR_STATUS);
++ flash_write_cmd_nodbg (info, 0, 0, FLASH_CMD_WRITE);
++ break;
++ case CFI_CMDSET_AMD_EXTENDED:
++ case CFI_CMDSET_AMD_STANDARD:
++ flash_unlock_seq (info, 0);
++ flash_write_cmd_nodbg (info, 0, AMD_ADDR_START, AMD_CMD_WRITE);
++ break;
++ }
++
++ switch (info->portwidth) {
++ case FLASH_CFI_8BIT:
++ cptr.cp[0] = cword.c;
++ break;
++ case FLASH_CFI_16BIT:
++ cptr.wp[0] = cword.w;
++ break;
++ case FLASH_CFI_32BIT:
++ cptr.lp[0] = cword.l;
++ break;
++ case FLASH_CFI_64BIT:
++ cptr.llp[0] = cword.ll;
++ break;
++ }
++
++ /* re-enable interrupts if necessary */
++ if (flag)
++ enable_interrupts ();
++
++ return flash_full_status_check (info, 0, info->write_tout, "write");
++}
++
++#ifdef CONFIG_SYS_FLASH_USE_BUFFER_WRITE
++
++/* loop through the sectors from the highest address
++ * when the passed address is greater or equal to the sector address
++ * we have a match
++ */
++static flash_sect_t find_sector (flash_info_t * info, ulong addr)
++{
++ flash_sect_t sector;
++
++ for (sector = info->sector_count - 1; sector >= 0; sector--) {
++ if (addr >= info->start[sector])
++ break;
++ }
++ return sector;
++}
++
++static int flash_write_cfibuffer (flash_info_t * info, ulong dest, uchar * cp,
++ int len)
++{
++ flash_sect_t sector;
++ int cnt;
++ int retcode;
++ volatile cfiptr_t src;
++ volatile cfiptr_t dst;
++
++/* Add AMD write buffer mode support, ycchen@102006 */
++#if 0
++ /* buffered writes in the AMD chip set is not supported yet */
++ if((info->vendor == CFI_CMDSET_AMD_STANDARD) ||
++ (info->vendor == CFI_CMDSET_AMD_EXTENDED))
++ return ERR_INVAL;
++#endif
++ if((info->vendor == CFI_CMDSET_AMD_STANDARD) ||
++ (info->vendor == CFI_CMDSET_AMD_EXTENDED))
++ {
++ retcode = flash_write_cfibuffer_amd(info, dest, cp, len);
++ return retcode;
++ }
++
++ src.cp = cp;
++ dst.cp = (uchar *) dest;
++ sector = find_sector (info, dest);
++ flash_write_cmd (info, sector, 0, FLASH_CMD_CLEAR_STATUS);
++ flash_write_cmd (info, sector, 0, FLASH_CMD_WRITE_TO_BUFFER);
++ if ((retcode =
++ flash_status_check (info, sector, info->buffer_write_tout,
++ "write to buffer")) == ERR_OK) {
++ /* reduce the number of loops by the width of the port */
++ switch (info->portwidth) {
++ case FLASH_CFI_8BIT:
++ cnt = len;
++ break;
++ case FLASH_CFI_16BIT:
++ cnt = len >> 1;
++ break;
++ case FLASH_CFI_32BIT:
++ cnt = len >> 2;
++ break;
++ case FLASH_CFI_64BIT:
++ cnt = len >> 3;
++ break;
++ default:
++ return ERR_INVAL;
++ break;
++ }
++ flash_write_cmd (info, sector, 0, (uchar) cnt - 1);
++ while (cnt-- > 0) {
++ switch (info->portwidth) {
++ case FLASH_CFI_8BIT:
++ *dst.cp++ = *src.cp++;
++ break;
++ case FLASH_CFI_16BIT:
++ *dst.wp++ = *src.wp++;
++ break;
++ case FLASH_CFI_32BIT:
++ *dst.lp++ = *src.lp++;
++ break;
++ case FLASH_CFI_64BIT:
++ *dst.llp++ = *src.llp++;
++ break;
++ default:
++ return ERR_INVAL;
++ break;
++ }
++ }
++ flash_write_cmd (info, sector, 0,
++ FLASH_CMD_WRITE_BUFFER_CONFIRM);
++ retcode =
++ flash_full_status_check (info, sector,
++ info->buffer_write_tout,
++ "buffer write");
++ }
++ flash_write_cmd (info, sector, 0, FLASH_CMD_CLEAR_STATUS);
++ return retcode;
++}
++
++
++static int flash_write_cfibuffer_amd (flash_info_t * info, ulong dest, uchar * cp,
++ int len)
++{
++ flash_sect_t sector;
++ int cnt;
++ int retcode;
++ volatile cfiptr_t src;
++ volatile cfiptr_t dst;
++ volatile cfiword_t tmpsrc, tmpdst;
++
++ src.cp = cp;
++ dst.cp = (uchar *) dest;
++ sector = find_sector (info, dest);
++ flash_unlock_seq (info, 0);
++ if ((retcode =
++ flash_status_check (info, sector, info->buffer_write_tout,
++ "write to buffer")) == ERR_OK) {
++ /* reduce the number of loops by the width of the port */
++ switch (info->portwidth) {
++ case FLASH_CFI_8BIT:
++ cnt = len;
++ *dst.cp = (uchar) (AMD_CMD_WRITE_TO_BUFFER);
++ *dst.cp = (uchar) (cnt -1);
++ break;
++ case FLASH_CFI_16BIT:
++ cnt = len >> 1;
++ *dst.wp = (unsigned short) (AMD_CMD_WRITE_TO_BUFFER);
++ *dst.wp = (unsigned short) (cnt -1);
++ break;
++ case FLASH_CFI_32BIT:
++ cnt = len >> 2;
++ *dst.lp = (unsigned long) (AMD_CMD_WRITE_TO_BUFFER);
++ *dst.lp = (unsigned long) (cnt -1);
++ break;
++ case FLASH_CFI_64BIT:
++ cnt = len >> 3;
++ *dst.llp = (unsigned long long) (AMD_CMD_WRITE_TO_BUFFER);
++ *dst.llp = (unsigned long long) (cnt -1);
++ break;
++ default:
++ return ERR_INVAL;
++ break;
++ }
++ while (cnt-- > 0) {
++ switch (info->portwidth) {
++ case FLASH_CFI_8BIT:
++ *dst.cp++ = *src.cp++;
++ break;
++ case FLASH_CFI_16BIT:
++ *dst.wp++ = *src.wp++;
++ break;
++ case FLASH_CFI_32BIT:
++ *dst.lp++ = *src.lp++;
++ break;
++ case FLASH_CFI_64BIT:
++ *dst.llp++ = *src.llp++;
++ break;
++ default:
++ return ERR_INVAL;
++ break;
++ }
++ }
++ switch (info->portwidth) {
++ case FLASH_CFI_8BIT:
++ src.cp--;
++ dst.cp--;
++ *dst.cp = (unsigned char) (AMD_CMD_BUFFER_TO_FLASH);
++ tmpsrc.c = *src.cp & 0x80;
++
++ do {
++ tmpdst.c = *(volatile uchar *)(dst.cp);
++
++ if (tmpdst.c & 0x20) { /* toggle DQ5 */
++ tmpdst.c = *(volatile uchar *)(dst.cp);
++ if ((tmpdst.c & 0x80) != tmpsrc.c)
++ {
++ printf("program error occurred\n");
++ flash_write_cmd (info, sector, 0, info->cmd_reset);
++ return ERR_PROG_ERROR;
++ }
++ }
++ else if (tmpdst.c & 0x02) { /* toggle DQ1 */
++ tmpdst.c = *(volatile uchar *)(dst.cp);
++ if ((tmpdst.c & 0x80) != tmpsrc.c)
++ {
++ printf("write buffer error occurred \n");
++ write_buffer_abort_reset(info, sector);
++ return ERR_PROG_ERROR;
++ }
++ }
++
++ } while ((tmpdst.c & 0x80) != tmpsrc.c);
++
++ break;
++ case FLASH_CFI_16BIT:
++ src.wp--;
++ dst.wp--;
++ *dst.wp = (unsigned short) (AMD_CMD_BUFFER_TO_FLASH);
++ tmpsrc.w = *src.wp & 0x80;
++
++ do {
++ tmpdst.w = *(volatile short *)(dst.wp);
++
++ if (tmpdst.w & 0x20) { /* toggle DQ5 */
++ tmpdst.w = *(volatile ushort *)(dst.wp);
++ if ((tmpdst.w & 0x80) != tmpsrc.w)
++ {
++ printf("program error occurred\n");
++ flash_write_cmd (info, sector, 0, info->cmd_reset);
++ return ERR_PROG_ERROR;
++ }
++ }
++ else if (tmpdst.w & 0x02) { /* toggle DQ1 */
++ tmpdst.w = *(volatile ushort *)(dst.wp);
++ if ((tmpdst.w & 0x80) != tmpsrc.w)
++ {
++ printf("write buffer error occurred \n");
++ write_buffer_abort_reset(info, sector);
++ return ERR_PROG_ERROR;
++ }
++ }
++
++ } while ((tmpdst.w & 0x80) != tmpsrc.w);
++
++ break;
++ case FLASH_CFI_32BIT:
++ src.lp--;
++ dst.lp--;
++ *dst.lp = (unsigned long) (AMD_CMD_BUFFER_TO_FLASH);
++ tmpsrc.l = *src.lp & 0x80;
++
++ do {
++ tmpdst.l = *(volatile ulong *)(dst.lp);
++
++ if (tmpdst.l & 0x20) { /* toggle DQ5 */
++ tmpdst.l = *(volatile ulong *)(dst.lp);
++ if ((tmpdst.l & 0x80) != tmpsrc.l)
++ {
++ printf("program error occurred\n");
++ flash_write_cmd (info, sector, 0, info->cmd_reset);
++ return ERR_PROG_ERROR;
++ }
++ }
++ else if (tmpdst.l & 0x02) { /* toggle DQ1 */
++ tmpdst.l = *(volatile ulong *)(dst.lp);
++ if ((tmpdst.l & 0x80) != tmpsrc.l)
++ {
++ printf("write buffer error occurred \n");
++ write_buffer_abort_reset(info, sector);
++ return ERR_PROG_ERROR;
++ }
++ }
++
++ } while ((tmpdst.l & 0x80) != tmpsrc.l);
++
++ break;
++ case FLASH_CFI_64BIT:
++ src.llp--;
++ dst.llp--;
++ *dst.llp = (unsigned long long) (AMD_CMD_BUFFER_TO_FLASH);
++ tmpsrc.ll = *src.llp & 0x80;
++
++ do {
++ tmpdst.ll = *(volatile unsigned long long *)(dst.llp);
++
++ if (tmpdst.ll & 0x20) { /* toggle DQ5 */
++ tmpdst.ll = *(volatile unsigned long long *)(dst.llp);
++ if ((tmpdst.ll & 0x80) != tmpsrc.ll)
++ {
++ printf("program error occurred\n");
++ flash_write_cmd (info, sector, 0, info->cmd_reset);
++ return ERR_PROG_ERROR;
++ }
++ }
++ else if (tmpdst.ll & 0x02) { /* toggle DQ1 */
++ tmpdst.ll = *(volatile unsigned long long *)(dst.llp);
++ if ((tmpdst.ll & 0x80) != tmpsrc.ll)
++ {
++ printf("write buffer error occurred \n");
++ write_buffer_abort_reset(info, sector);
++ return ERR_PROG_ERROR;
++ }
++ }
++
++ } while ((tmpdst.ll & 0x80) != tmpsrc.ll);
++
++ break;
++ default:
++ return ERR_INVAL;
++ break;
++ }
++
++ retcode =
++ flash_full_status_check (info, sector,
++ info->buffer_write_tout,
++ "buffer write");
++ }
++
++ return retcode;
++}
++#endif /* CONFIG_SYS_FLASH_USE_BUFFER_WRITE */
++
++#ifdef CONFIG_FLASH_AST2300_DMA
++#define STCBaseAddress 0x1e620000
++
++/* for DMA */
++#define REG_FLASH_INTERRUPT_STATUS 0x08
++#define REG_FLASH_DMA_CONTROL 0x80
++#define REG_FLASH_DMA_FLASH_BASE 0x84
++#define REG_FLASH_DMA_DRAM_BASE 0x88
++#define REG_FLASH_DMA_LENGTH 0x8c
++
++#define FLASH_STATUS_DMA_BUSY 0x0000
++#define FLASH_STATUS_DMA_READY 0x0800
++#define FLASH_STATUS_DMA_CLEAR 0x0800
++
++#define FLASH_DMA_ENABLE 0x01
++
++void * memmove_dma(void * dest,const void *src,size_t count)
++{
++ ulong count_align, poll_time, data;
++
++ count_align = (count + 3) & 0xFFFFFFFC; /* 4-bytes align */
++ poll_time = 100; /* set 100 us as default */
++
++ *(ulong *) (STCBaseAddress + REG_FLASH_DMA_CONTROL) = (ulong) (~FLASH_DMA_ENABLE);
++
++ *(ulong *) (STCBaseAddress + REG_FLASH_DMA_FLASH_BASE) = (ulong *) (src);
++ *(ulong *) (STCBaseAddress + REG_FLASH_DMA_DRAM_BASE) = (ulong *) (dest);
++ *(ulong *) (STCBaseAddress + REG_FLASH_DMA_LENGTH) = (ulong) (count_align);
++ udelay(10);
++ *(ulong *) (STCBaseAddress + REG_FLASH_DMA_CONTROL) = (ulong) (FLASH_DMA_ENABLE);
++
++ /* wait poll */
++ do {
++ udelay(poll_time);
++ data = *(ulong *) (STCBaseAddress + REG_FLASH_INTERRUPT_STATUS);
++ } while (!(data & FLASH_STATUS_DMA_READY));
++
++ /* clear status */
++ *(ulong *) (STCBaseAddress + REG_FLASH_INTERRUPT_STATUS) |= FLASH_STATUS_DMA_CLEAR;
++}
++#endif
++#endif /* CFG_FLASH_CFI */
+diff --git a/board/aspeed/ast2300/flash_spi.c b/board/aspeed/ast2300/flash_spi.c
+new file mode 100755
+index 0000000..6660628
+--- /dev/null
++++ b/board/aspeed/ast2300/flash_spi.c
+@@ -0,0 +1,1639 @@
++/*
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License as
++ * published by the Free Software Foundation; either version 2 of
++ * the License, or (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
++ * MA 02111-1307 USA
++ *
++ * History
++ * 01/20/2004 - combined variants of original driver.
++ * 01/22/2004 - Write performance enhancements for parallel chips (Tolunay)
++ * 01/23/2004 - Support for x8/x16 chips (Rune Raknerud)
++ * 01/27/2004 - Little endian support Ed Okerson
++ *
++ * Tested Architectures
++ * Port Width Chip Width # of banks Flash Chip Board
++ * 32 16 1 28F128J3 seranoa/eagle
++ * 64 16 1 28F128J3 seranoa/falcon
++ *
++ */
++
++/* The DEBUG define must be before common to enable debugging */
++/* #define DEBUG */
++
++#include <common.h>
++#include <asm/processor.h>
++#include <asm/byteorder.h>
++#include <environment.h>
++#ifdef CONFIG_FLASH_SPI
++
++/*
++ * This file implements a Common Flash Interface (CFI) driver for U-Boot.
++ * The width of the port and the width of the chips are determined at initialization.
++ * These widths are used to calculate the address for access CFI data structures.
++ * It has been tested on an Intel Strataflash implementation and AMD 29F016D.
++ *
++ * References
++ * JEDEC Standard JESD68 - Common Flash Interface (CFI)
++ * JEDEC Standard JEP137-A Common Flash Interface (CFI) ID Codes
++ * Intel Application Note 646 Common Flash Interface (CFI) and Command Sets
++ * Intel 290667-008 3 Volt Intel StrataFlash Memory datasheet
++ *
++ * TODO
++ *
++ * Use Primary Extended Query table (PRI) and Alternate Algorithm Query
++ * Table (ALT) to determine if protection is available
++ *
++ * Add support for other command sets Use the PRI and ALT to determine command set
++ * Verify erase and program timeouts.
++ */
++
++#ifndef CONFIG_FLASH_BANKS_LIST
++#define CONFIG_FLASH_BANKS_LIST { CONFIG_SYS_FLASH_BASE }
++#endif
++
++/* use CFG_MAX_FLASH_BANKS_DETECT if defined */
++#ifdef CONFIG_SYS_MAX_FLASH_BANKS_DETECT
++static ulong bank_base[CONFIG_SYS_MAX_FLASH_BANKS_DETECT] = CONFIG_FLASH_BANKS_LIST;
++flash_info_t flash_info[CONFIG_SYS_MAX_FLASH_BANKS_DETECT]; /* FLASH chips info */
++#else
++static ulong bank_base[CONFIG_SYS_MAX_FLASH_BANKS] = CONFIG_FLASH_BANKS_LIST;
++flash_info_t flash_info[CONFIG_SYS_MAX_FLASH_BANKS]; /* FLASH chips info */
++#endif
++
++/* Support Flash ID */
++#define STM25P64 0x172020
++#define STM25P128 0x182020
++#define N25Q256 0x19ba20
++#define N25Q512 0x20ba20
++#define S25FL064A 0x160201
++#define S25FL128P 0x182001
++#define S25FL256S 0x190201
++#define W25X16 0x1530ef
++#define W25X64 0x1730ef
++#define W25Q64BV 0x1740ef
++#define W25Q128BV 0x1840ef
++#define W25Q256FV 0x1940ef
++#define MX25L1605D 0x1520C2
++#define MX25L12805D 0x1820C2
++#define MX25L25635E 0x1920C2
++#define SST25VF016B 0x4125bf
++#define SST25VF064C 0x4b25bf
++#define AT25DF161 0x02461F
++#define AT25DF321 0x01471F
++
++/* SPI Define */
++#if defined(CONFIG_FLASH_AST2300) || defined(CONFIG_AST1300)
++#if defined(CONFIG_AST1300)
++#define STCBaseAddress 0x00620000
++#else
++#define STCBaseAddress 0x1e620000
++#endif
++#define SCU_REVISION_REGISTER 0x1e6e207c
++#define SCU_CACHE_CTRL_REGISTER 0x1e6e2118
++
++#define SPICtrlRegOffset 0x10
++#define SPICtrlRegOffset2 0x14
++
++#define SPIMiscCtrlRegOffset 0x54
++
++/* for DMA */
++#define REG_FLASH_INTERRUPT_STATUS 0x08
++#define REG_FLASH_DMA_CONTROL 0x80
++#define REG_FLASH_DMA_FLASH_BASE 0x84
++#define REG_FLASH_DMA_DRAM_BASE 0x88
++#define REG_FLASH_DMA_LENGTH 0x8c
++
++#define FLASH_STATUS_DMA_BUSY 0x0000
++#define FLASH_STATUS_DMA_READY 0x0800
++#define FLASH_STATUS_DMA_CLEAR 0x0800
++
++#define FLASH_DMA_ENABLE 0x01
++#else
++#define STCBaseAddress 0x16000000
++
++#define SPICtrlRegOffset 0x04
++#define SPICtrlRegOffset2 0x0C
++#endif /* CONFIG_FLASH_AST2300 */
++
++#define CMD_MASK 0xFFFFFFF8
++
++#define NORMALREAD 0x00
++#define FASTREAD 0x01
++#define NORMALWRITE 0x02
++#define USERMODE 0x03
++
++#define CE_LOW 0x00
++#define CE_HIGH 0x04
++
++/* AST2300 only */
++#define IOMODEx1 0x00000000
++#define IOMODEx2 0x20000000
++#define IOMODEx2_dummy 0x30000000
++#define IOMODEx4 0x40000000
++#define IOMODEx4_dummy 0x50000000
++
++#define DUMMY_COMMAND_OUT 0x00008000
++/* ~AST2300 only */
++
++/* specificspi */
++#define SpecificSPI_N25Q512 0x00000001
++
++static ulong AST2300_SPICLK_DIV[16] = {0x0F, 0x07, 0x0E, 0x06, 0x0D, 0x05, 0x0C, 0x04, \
++ 0x0B, 0x03, 0x0A, 0x02, 0x09, 0x01, 0x08, 0x00 };
++
++/*-----------------------------------------------------------------------
++ * Functions
++ */
++static void reset_flash (flash_info_t * info);
++static void enable_write (flash_info_t * info);
++static void write_status_register (flash_info_t * info, uchar data);
++static void enable4b (flash_info_t * info);
++static void enable4b_spansion (flash_info_t * info);
++static void enable4b_numonyx (flash_info_t * info);
++static ulong flash_get_size (ulong base, int banknum);
++static int flash_write_buffer (flash_info_t *info, uchar *src, ulong addr, int len);
++#if defined(CFG_ENV_IS_IN_FLASH) || defined(CFG_ENV_ADDR_REDUND) || (CFG_MONITOR_BASE >= CFG_FLASH_BASE)
++static flash_info_t *flash_get_info(ulong base);
++#endif
++
++
++/*-----------------------------------------------------------------------
++ * create an address based on the offset and the port width
++ */
++inline uchar *flash_make_addr (flash_info_t * info, flash_sect_t sect, uint offset)
++{
++#ifdef CONFIG_2SPIFLASH
++ if (info->start[0] >= PHYS_FLASH_2)
++ return ((uchar *) (info->start[sect] + (offset * 1) - (PHYS_FLASH_2 - PHYS_FLASH_2_BASE) ));
++ else
++ return ((uchar *) (info->start[sect] + (offset * 1)));
++#else
++ return ((uchar *) (info->start[sect] + (offset * 1)));
++#endif
++}
++
++/*-----------------------------------------------------------------------
++ * read a character at a port width address
++ */
++inline uchar flash_read_uchar (flash_info_t * info, uint offset)
++{
++ uchar *cp;
++
++ cp = flash_make_addr (info, 0, offset);
++#if defined(__LITTLE_ENDIAN)
++ return (cp[0]);
++#else
++ return (cp[1 - 1]);
++#endif
++}
++
++/*-----------------------------------------------------------------------
++ * read a short word by swapping for ppc format.
++ */
++ushort flash_read_ushort (flash_info_t * info, flash_sect_t sect, uint offset)
++{
++ uchar *addr;
++ ushort retval;
++
++#ifdef DEBUG
++ int x;
++#endif
++ addr = flash_make_addr (info, sect, offset);
++
++#ifdef DEBUG
++ debug ("ushort addr is at %p 1 = %d\n", addr,
++ 1);
++ for (x = 0; x < 2 * 1; x++) {
++ debug ("addr[%x] = 0x%x\n", x, addr[x]);
++ }
++#endif
++#if defined(__LITTLE_ENDIAN)
++ retval = ((addr[(1)] << 8) | addr[0]);
++#else
++ retval = ((addr[(2 * 1) - 1] << 8) |
++ addr[1 - 1]);
++#endif
++
++ debug ("retval = 0x%x\n", retval);
++ return retval;
++}
++
++/*-----------------------------------------------------------------------
++ * read a long word by picking the least significant byte of each maiximum
++ * port size word. Swap for ppc format.
++ */
++ulong flash_read_long (flash_info_t * info, flash_sect_t sect, uint offset)
++{
++ uchar *addr;
++ ulong retval;
++
++#ifdef DEBUG
++ int x;
++#endif
++ addr = flash_make_addr (info, sect, offset);
++
++#ifdef DEBUG
++ debug ("long addr is at %p 1 = %d\n", addr,
++ 1);
++ for (x = 0; x < 4 * 1; x++) {
++ debug ("addr[%x] = 0x%x\n", x, addr[x]);
++ }
++#endif
++#if defined(__LITTLE_ENDIAN)
++ retval = (addr[0] << 16) | (addr[(1)] << 24) |
++ (addr[(2 * 1)]) | (addr[(3 * 1)] << 8);
++#else
++ retval = (addr[(2 * 1) - 1] << 24) |
++ (addr[(1) - 1] << 16) |
++ (addr[(4 * 1) - 1] << 8) |
++ addr[(3 * 1) - 1];
++#endif
++ return retval;
++}
++
++/*-----------------------------------------------------------------------
++ */
++static void disable_cache(void)
++{
++#if defined(AST1300_CPU_CACHE_ENABLE)
++ ulong uldata;
++
++ uldata = *(volatile ulong *) (SCU_CACHE_CTRL_REGISTER);
++ uldata &= 0xfffffffd;
++ *(ulong *) (SCU_CACHE_CTRL_REGISTER) = uldata;
++#endif
++}
++
++static void enable_cache(void)
++{
++#if defined(AST1300_CPU_CACHE_ENABLE)
++ ulong uldata;
++
++ uldata = *(volatile ulong *) (SCU_CACHE_CTRL_REGISTER);
++ uldata |= 0x00000002;
++ *(ulong *) (SCU_CACHE_CTRL_REGISTER) = uldata;
++#endif
++}
++
++static void reset_flash (flash_info_t * info)
++{
++ ulong ulCtrlData, CtrlOffset, MiscCtrlOffset;
++
++ if (info->CE == 2)
++ {
++ CtrlOffset = SPICtrlRegOffset2;
++ }
++ else
++ {
++ CtrlOffset = SPICtrlRegOffset;
++ }
++
++#if defined(CONFIG_FLASH_AST2300) || defined(CONFIG_AST1300)
++ ulCtrlData = info->iomode | (info->readcmd << 16) | (info->tCK_Read << 8) | (info->dummybyte << 6) | FASTREAD;
++#if 0
++ if (info->quadport)
++ {
++ MiscCtrlOffset = SPIMiscCtrlRegOffset;
++ *(ulong *) (STCBaseAddress + MiscCtrlOffset) = info->dummydata;
++ ulCtrlData |= DUMMY_COMMAND_OUT;
++ }
++#endif
++#else
++ ulCtrlData = (info->readcmd << 16) | (info->tCK_Read << 8) | (info->dummybyte << 6) | FASTREAD;
++ if (info->dualport)
++ ulCtrlData |= 0x08;
++#endif
++ *(ulong *) (STCBaseAddress + CtrlOffset) = ulCtrlData;
++
++ enable_cache();
++}
++
++static void enable_write (flash_info_t * info)
++{
++ ulong base;
++ ulong ulCtrlData, CtrlOffset;
++ uchar jReg;
++
++ if (info->CE == 2)
++ {
++ CtrlOffset = SPICtrlRegOffset2;
++ }
++ else
++ {
++ CtrlOffset = SPICtrlRegOffset;
++ }
++
++ //base = info->start[0];
++ base = flash_make_addr (info, 0, 0);
++
++ ulCtrlData = (info->tCK_Write << 8);
++ ulCtrlData |= CE_LOW | USERMODE;
++ *(ulong *) (STCBaseAddress + CtrlOffset) = ulCtrlData;
++ udelay(200);
++ *(uchar *) (base) = (uchar) (0x06);
++ udelay(10);
++ ulCtrlData &= CMD_MASK;
++ ulCtrlData |= CE_HIGH | USERMODE;
++ *(ulong *) (STCBaseAddress + CtrlOffset) = ulCtrlData;
++ udelay(200);
++
++ ulCtrlData &= CMD_MASK;
++ ulCtrlData |= CE_LOW | USERMODE;
++ *(ulong *) (STCBaseAddress + CtrlOffset) = ulCtrlData;
++ udelay(200);
++ *(uchar *) (base) = (uchar) (0x05);
++ udelay(10);
++ do {
++ jReg = *(volatile uchar *) (base);
++ } while (!(jReg & 0x02));
++ ulCtrlData &= CMD_MASK;
++ ulCtrlData |= CE_HIGH | USERMODE;
++ *(ulong *) (STCBaseAddress + CtrlOffset) = ulCtrlData;
++ udelay(200);
++
++}
++
++static void write_status_register (flash_info_t * info, uchar data)
++{
++ ulong base;
++ ulong ulSMMBase, ulCtrlData, CtrlOffset;
++ uchar jReg;
++
++ if (info->CE == 2)
++ {
++ CtrlOffset = SPICtrlRegOffset2;
++ }
++ else
++ {
++ CtrlOffset = SPICtrlRegOffset;
++ }
++
++ //base = info->start[0];
++ base = flash_make_addr (info, 0, 0);
++
++ enable_write (info);
++
++ ulCtrlData = (info->tCK_Write << 8);
++ ulCtrlData |= CE_LOW | USERMODE;
++ *(ulong *) (STCBaseAddress + CtrlOffset) = ulCtrlData;
++ udelay(200);
++ *(uchar *) (base) = (uchar) (0x01);
++ udelay(10);
++ *(uchar *) (base) = (uchar) (data);
++ ulCtrlData &= CMD_MASK;
++ ulCtrlData |= CE_HIGH | USERMODE;
++ *(ulong *) (STCBaseAddress + CtrlOffset) = ulCtrlData;
++ udelay(200);
++
++ ulCtrlData &= CMD_MASK;
++ ulCtrlData |= CE_LOW | USERMODE;
++ *(ulong *) (STCBaseAddress + CtrlOffset) = ulCtrlData;
++ udelay(200);
++ *(uchar *) (base) = (uchar) (0x05);
++ udelay(10);
++ do {
++ jReg = *(volatile uchar *) (base);
++ } while (jReg & 0x01);
++ ulCtrlData &= CMD_MASK;
++ ulCtrlData |= CE_HIGH | USERMODE;
++ *(ulong *) (STCBaseAddress + CtrlOffset) = ulCtrlData;
++ udelay(200);
++
++}
++
++static void enable4b (flash_info_t * info)
++{
++ ulong base;
++ ulong ulSMMBase, ulCtrlData, CtrlOffset;
++ uchar jReg;
++
++ if (info->CE == 2)
++ {
++ CtrlOffset = SPICtrlRegOffset2;
++ }
++ else
++ {
++ CtrlOffset = SPICtrlRegOffset;
++ }
++
++ //base = info->start[0];
++ base = flash_make_addr (info, 0, 0);
++
++ ulCtrlData = (info->tCK_Write << 8);
++ ulCtrlData |= CE_LOW | USERMODE;
++ *(ulong *) (STCBaseAddress + CtrlOffset) = ulCtrlData;
++ udelay(200);
++ *(uchar *) (base) = (uchar) (0xb7);
++ ulCtrlData &= CMD_MASK;
++ ulCtrlData |= CE_HIGH | USERMODE;
++ *(ulong *) (STCBaseAddress + CtrlOffset) = ulCtrlData;
++ udelay(200);
++
++} /* enable4b */
++
++static void enable4b_spansion (flash_info_t * info)
++{
++ ulong base;
++ ulong ulSMMBase, ulCtrlData, CtrlOffset;
++ uchar jReg;
++
++ if (info->CE == 2)
++ {
++ CtrlOffset = SPICtrlRegOffset2;
++ }
++ else
++ {
++ CtrlOffset = SPICtrlRegOffset;
++ }
++
++ //base = info->start[0];
++ base = flash_make_addr (info, 0, 0);
++
++ /* Enable 4B: BAR0 D[7] = 1 */
++ ulCtrlData = (info->tCK_Write << 8);
++ ulCtrlData |= CE_LOW | USERMODE;
++ *(ulong *) (STCBaseAddress + CtrlOffset) = ulCtrlData;
++ udelay(200);
++ *(uchar *) (base) = (uchar) (0x17);
++ udelay(10);
++ *(uchar *) (base) = (uchar) (0x80);
++ ulCtrlData &= CMD_MASK;
++ ulCtrlData |= CE_HIGH | USERMODE;
++ *(ulong *) (STCBaseAddress + CtrlOffset) = ulCtrlData;
++ udelay(200);
++
++ ulCtrlData &= CMD_MASK;
++ ulCtrlData |= CE_LOW | USERMODE;
++ *(ulong *) (STCBaseAddress + CtrlOffset) = ulCtrlData;
++ udelay(200);
++ *(uchar *) (base) = (uchar) (0x16);
++ udelay(10);
++ do {
++ jReg = *(volatile uchar *) (base);
++ } while (!(jReg & 0x80));
++ ulCtrlData &= CMD_MASK;
++ ulCtrlData |= CE_HIGH | USERMODE;
++ *(ulong *) (STCBaseAddress + CtrlOffset) = ulCtrlData;
++ udelay(200);
++
++} /* enable4b_spansion */
++
++static void enable4b_numonyx (flash_info_t * info)
++{
++ ulong base;
++ ulong ulSMMBase, ulCtrlData, CtrlOffset;
++ uchar jReg;
++
++ if (info->CE == 2)
++ {
++ CtrlOffset = SPICtrlRegOffset2;
++ }
++ else
++ {
++ CtrlOffset = SPICtrlRegOffset;
++ }
++
++ //base = info->start[0];
++ base = flash_make_addr (info, 0, 0);
++
++ /* Enable Write */
++ enable_write (info);
++
++ /* Enable 4B: CMD:0xB7 */
++ ulCtrlData = (info->tCK_Write << 8);
++ ulCtrlData |= CE_LOW | USERMODE;
++ *(ulong *) (STCBaseAddress + CtrlOffset) = ulCtrlData;
++ udelay(200);
++ *(uchar *) (base) = (uchar) (0xB7);
++ udelay(10);
++ ulCtrlData &= CMD_MASK;
++ ulCtrlData |= CE_HIGH | USERMODE;
++ *(ulong *) (STCBaseAddress + CtrlOffset) = ulCtrlData;
++ udelay(200);
++
++} /* enable4b_numonyx */
++
++/*
++ *
++ */
++static ulong flash_get_size (ulong base, int banknum)
++{
++ flash_info_t *info = &flash_info[banknum];
++ int j;
++ unsigned long sector;
++ int erase_region_size;
++ ulong ulCtrlData, CtrlOffset;
++ ulong ulID;
++ uchar ch[3];
++ ulong cpuclk, div, reg;
++ ulong WriteClk, EraseClk, ReadClk;
++ ulong vbase;
++ ulong SCURevision;
++
++ ulong ulRefPLL;
++ ulong ulDeNumerator;
++ ulong ulNumerator;
++ ulong ulOD;
++
++ disable_cache();
++
++ info->start[0] = base;
++ vbase = flash_make_addr (info, 0, 0);
++
++#if defined(CONFIG_FLASH_AST2300) || defined(CONFIG_AST1300)
++ CtrlOffset = SPICtrlRegOffset;
++ info->CE = 0;
++#else
++ if (vbase == PHYS_FLASH_1)
++ {
++ CtrlOffset = SPICtrlRegOffset2;
++ info->CE = 2;
++ }
++ else
++ {
++ CtrlOffset = SPICtrlRegOffset;
++ info->CE = 0;
++ }
++#endif
++
++ /* Get Flash ID */
++ ulCtrlData = *(ulong *) (STCBaseAddress + CtrlOffset) & CMD_MASK;
++ ulCtrlData |= CE_LOW | USERMODE;
++ *(ulong *) (STCBaseAddress + CtrlOffset) = ulCtrlData;
++ udelay(200);
++ *(uchar *) (vbase) = (uchar) (0x9F);
++ udelay(10);
++ ch[0] = *(volatile uchar *)(vbase);
++ udelay(10);
++ ch[1] = *(volatile uchar *)(vbase);
++ udelay(10);
++ ch[2] = *(volatile uchar *)(vbase);
++ udelay(10);
++ ulCtrlData = *(ulong *) (STCBaseAddress + CtrlOffset) & CMD_MASK;
++ ulCtrlData |= CE_HIGH | USERMODE;
++ *(ulong *) (STCBaseAddress + CtrlOffset) = ulCtrlData;
++ udelay(200);
++ ulID = ((ulong)ch[0]) | ((ulong)ch[1] << 8) | ((ulong)ch[2] << 16) ;
++ info->flash_id = ulID;
++
++ //printf("SPI Flash ID: %x \n", ulID);
++
++ /* init default */
++ info->iomode = IOMODEx1;
++ info->address32 = 0;
++ info->quadport = 0;
++ info->specificspi = 0;
++
++ switch (info->flash_id)
++ {
++ case STM25P64:
++ info->sector_count = 128;
++ info->size = 0x800000;
++ erase_region_size = 0x10000;
++ info->readcmd = 0x0b;
++ info->dualport = 0;
++ info->dummybyte = 1;
++ info->buffersize = 256;
++ WriteClk = 40;
++ EraseClk = 20;
++ ReadClk = 40;
++ break;
++
++ case STM25P128:
++ info->sector_count = 64;
++ info->size = 0x1000000;
++ erase_region_size = 0x40000;
++ info->readcmd = 0x0b;
++ info->dualport = 0;
++ info->dummybyte = 1;
++ info->buffersize = 256;
++ WriteClk = 50;
++ EraseClk = 20;
++ ReadClk = 50;
++ break;
++
++ case N25Q256:
++ info->sector_count = 256;
++ info->size = 0x1000000;
++ erase_region_size = 0x10000;
++ info->readcmd = 0x0b;
++ info->dualport = 0;
++ info->dummybyte = 1;
++ info->buffersize = 256;
++ WriteClk = 50;
++ EraseClk = 20;
++ ReadClk = 50;
++#if defined(CONFIG_FLASH_AST2300) || defined(CONFIG_AST1300)
++ info->sector_count = 512;
++ info->size = 0x2000000;
++ info->address32 = 1;
++#endif
++ break;
++
++ case N25Q512:
++ info->sector_count = 256;
++ info->size = 0x1000000;
++ erase_region_size = 0x10000;
++ info->readcmd = 0x0b;
++ info->dualport = 0;
++ info->dummybyte = 1;
++ info->buffersize = 256;
++ info->specificspi = SpecificSPI_N25Q512;
++ WriteClk = 50;
++ EraseClk = 20;
++ ReadClk = 50;
++#if defined(CONFIG_FLASH_AST2300) || defined(CONFIG_AST1300)
++ info->sector_count = 1024;
++ info->size = 0x4000000;
++ info->address32 = 1;
++#endif
++ break;
++
++ case W25X16:
++ info->sector_count = 32;
++ info->size = 0x200000;
++ erase_region_size = 0x10000;
++ info->readcmd = 0x3b;
++ info->dualport = 1;
++ info->dummybyte = 1;
++ info->iomode = IOMODEx2;
++ info->buffersize = 256;
++ WriteClk = 50;
++ EraseClk = 25;
++ ReadClk = 50;
++ break;
++
++ case W25X64:
++ info->sector_count = 128;
++ info->size = 0x800000;
++ erase_region_size = 0x10000;
++ info->readcmd = 0x3b;
++ info->dualport = 1;
++ info->dummybyte = 1;
++ info->iomode = IOMODEx2;
++ info->buffersize = 256;
++ WriteClk = 50;
++ EraseClk = 25;
++ ReadClk = 50;
++ break;
++
++ case W25Q64BV:
++ info->sector_count = 128;
++ info->size = 0x800000;
++ erase_region_size = 0x10000;
++ info->readcmd = 0x3b;
++ info->dualport = 1;
++ info->dummybyte = 1;
++ info->iomode = IOMODEx2;
++ info->buffersize = 256;
++ WriteClk = 80;
++ EraseClk = 40;
++ ReadClk = 80;
++ break;
++
++ case W25Q128BV:
++ info->sector_count = 256;
++ info->size = 0x1000000;
++ erase_region_size = 0x10000;
++ info->readcmd = 0x3b;
++ info->dualport = 1;
++ info->dummybyte = 1;
++ info->iomode = IOMODEx2;
++ info->buffersize = 256;
++ WriteClk = 104;
++ EraseClk = 50;
++ ReadClk = 104;
++ break;
++
++ case W25Q256FV:
++ info->sector_count = 256;
++ info->size = 0x1000000;
++ erase_region_size = 0x10000;
++ info->readcmd = 0x0b;
++ info->dualport = 0;
++ info->dummybyte = 1;
++ info->buffersize = 256;
++ WriteClk = 50;
++ EraseClk = 20;
++ ReadClk = 50;
++#if defined(CONFIG_FLASH_AST2300) || defined(CONFIG_AST1300)
++ info->sector_count = 512;
++ info->size = 0x2000000;
++ info->address32 = 1;
++#endif
++ break;
++
++ case S25FL064A:
++ info->sector_count = 128;
++ info->size = 0x800000;
++ erase_region_size = 0x10000;
++ info->readcmd = 0x0b;
++ info->dualport = 0;
++ info->dummybyte = 1;
++ info->buffersize = 256;
++ WriteClk = 50;
++ EraseClk = 25;
++ ReadClk = 50;
++ break;
++
++ case S25FL128P:
++ info->sector_count = 256;
++ info->size = 0x1000000;
++ erase_region_size = 0x10000;
++ info->readcmd = 0x0b;
++ info->dualport = 0;
++ info->dummybyte = 1;
++ info->buffersize = 256;
++ WriteClk = 100;
++ EraseClk = 40;
++ ReadClk = 100;
++ break;
++
++ case S25FL256S:
++ info->sector_count = 256;
++ info->size = 0x1000000;
++ erase_region_size = 0x10000;
++ info->readcmd = 0x0b;
++ info->dualport = 0;
++ info->dummybyte = 1;
++ info->buffersize = 256;
++ WriteClk = 50;
++ EraseClk = 20;
++ ReadClk = 50;
++#if defined(CONFIG_FLASH_AST2300) || defined(CONFIG_AST1300)
++ info->sector_count = 512;
++ info->size = 0x2000000;
++ info->address32 = 1;
++#endif
++ break;
++
++ case MX25L25635E:
++ info->sector_count = 256;
++ info->size = 0x1000000;
++ erase_region_size = 0x10000;
++ info->readcmd = 0x0b;
++ info->dualport = 0;
++ info->dummybyte = 1;
++ info->buffersize = 256;
++ WriteClk = 50;
++ EraseClk = 20;
++ ReadClk = 50;
++#if defined(CONFIG_FLASH_AST2300) || defined(CONFIG_AST1300)
++ info->sector_count = 512;
++ info->size = 0x2000000;
++ info->address32 = 1;
++#if defined(CONFIG_FLASH_SPIx2_Dummy)
++ info->readcmd = 0xbb;
++ info->dummybyte = 1;
++ info->dualport = 1;
++ info->iomode = IOMODEx2_dummy;
++#elif defined(CONFIG_FLASH_SPIx4_Dummy)
++ info->readcmd = 0xeb;
++ info->dummybyte = 3;
++ info->dualport = 0;
++ info->iomode = IOMODEx4_dummy;
++ info->quadport = 1;
++ info->dummydata = 0xaa;
++#endif
++#endif
++ break;
++
++ case MX25L12805D:
++ info->sector_count = 256;
++ info->size = 0x1000000;
++ erase_region_size = 0x10000;
++ info->readcmd = 0x0b;
++ info->dualport = 0;
++ info->dummybyte = 1;
++ info->buffersize = 256;
++/*
++SCU7C: Silicon Revision ID Register
++D[31:24]: Chip ID
++0: AST2050/AST2100/AST2150/AST2200/AST3000
++1: AST2300
++
++D[23:16] Silicon revision ID for AST2300 generation and later
++0: A0
++1: A1
++2: A2
++.
++.
++.
++FPGA revision starts from 0x80
++
++AST2300 A0 SPI can't run faster than 50Mhz
++*/
++ WriteClk = 50;
++ EraseClk = 20;
++ ReadClk = 50;
++
++ SCURevision = *(ulong *) (SCU_REVISION_REGISTER);
++ if (((SCURevision >> 24) & 0xff) == 0x01) { //AST2300
++ if (((SCURevision >> 16) & 0xff) == 0x00) { //A0
++ WriteClk = 25;
++ EraseClk = 20;
++ ReadClk = 25;
++ }
++ }
++#if defined(CONFIG_FLASH_AST2300) || defined(CONFIG_AST1300)
++#if defined(CONFIG_FLASH_SPIx2_Dummy)
++ info->readcmd = 0xbb;
++ info->dummybyte = 1;
++ info->dualport = 1;
++ info->iomode = IOMODEx2_dummy;
++#elif defined(CONFIG_FLASH_SPIx4_Dummy)
++ info->readcmd = 0xeb;
++ info->dummybyte = 3;
++ info->dualport = 0;
++ info->iomode = IOMODEx4_dummy;
++ info->quadport = 1;
++ info->dummydata = 0xaa;
++#endif
++#endif
++ break;
++
++ case MX25L1605D:
++ info->sector_count = 32;
++ info->size = 0x200000;
++ erase_region_size = 0x10000;
++ info->readcmd = 0x0b;
++ info->dualport = 0;
++ info->dummybyte = 1;
++ info->buffersize = 256;
++ WriteClk = 50;
++ EraseClk = 20;
++ ReadClk = 50;
++ break;
++
++ case SST25VF016B:
++ info->sector_count = 32;
++ info->size = 0x200000;
++ erase_region_size = 0x10000;
++ info->readcmd = 0x0b;
++ info->dualport = 0;
++ info->dummybyte = 1;
++ info->buffersize = 1;
++ WriteClk = 50;
++ EraseClk = 25;
++ ReadClk = 50;
++ break;
++
++ case SST25VF064C:
++ info->sector_count = 128;
++ info->size = 0x800000;
++ erase_region_size = 0x10000;
++ info->readcmd = 0x0b;
++ info->dualport = 0;
++ info->dummybyte = 1;
++ info->buffersize = 1;
++ WriteClk = 50;
++ EraseClk = 25;
++ ReadClk = 50;
++ break;
++
++ case AT25DF161:
++ info->sector_count = 32;
++ info->size = 0x200000;
++ erase_region_size = 0x10000;
++ info->readcmd = 0x0b;
++ info->dualport = 0;
++ info->dummybyte = 1;
++ info->buffersize = 1;
++ WriteClk = 50;
++ EraseClk = 25;
++ ReadClk = 50;
++ break;
++
++ case AT25DF321:
++ info->sector_count = 32;
++ info->size = 0x400000;
++ erase_region_size = 0x10000;
++ info->readcmd = 0x0b;
++ info->dualport = 0;
++ info->dummybyte = 1;
++ info->buffersize = 1;
++ WriteClk = 50;
++ EraseClk = 25;
++ ReadClk = 50;
++ break;
++
++ default: /* use JEDEC ID */
++ erase_region_size = 0x10000;
++ info->readcmd = 0x0b;
++ info->dualport = 0;
++ info->dummybyte = 1;
++ info->buffersize = 1;
++ WriteClk = 50;
++ EraseClk = 25;
++ ReadClk = 50;
++ if ((info->flash_id & 0xFF) == 0x1F) /* Atmel */
++ {
++ switch (info->flash_id & 0x001F00)
++ {
++ case 0x000400:
++ info->sector_count = 8;
++ info->size = 0x80000;
++ break;
++ case 0x000500:
++ info->sector_count = 16;
++ info->size = 0x100000;
++ break;
++ case 0x000600:
++ info->sector_count = 32;
++ info->size = 0x200000;
++ break;
++ case 0x000700:
++ info->sector_count = 64;
++ info->size = 0x400000;
++ break;
++ case 0x000800:
++ info->sector_count = 128;
++ info->size = 0x800000;
++ break;
++ case 0x000900:
++ info->sector_count = 256;
++ info->size = 0x1000000;
++ break;
++ default:
++ printf("Can't support this SPI Flash!! \n");
++ return 0;
++ }
++ } /* Atmel JDEC */
++ else /* JDEC */
++ {
++ switch (info->flash_id & 0xFF0000)
++ {
++ case 0x120000:
++ info->sector_count = 4;
++ info->size = 0x40000;
++ break;
++ case 0x130000:
++ info->sector_count = 8;
++ info->size = 0x80000;
++ break;
++ case 0x140000:
++ info->sector_count =16;
++ info->size = 0x100000;
++ break;
++ case 0x150000:
++ info->sector_count =32;
++ info->size = 0x200000;
++ break;
++ case 0x160000:
++ info->sector_count =64;
++ info->size = 0x400000;
++ break;
++ case 0x170000:
++ info->sector_count =128;
++ info->size = 0x800000;
++ break;
++ case 0x180000:
++ info->sector_count =256;
++ info->size = 0x1000000;
++ break;
++ case 0x190000:
++ info->sector_count =256;
++ info->size = 0x1000000;
++#if defined(CONFIG_FLASH_AST2300) || defined(CONFIG_AST1300)
++ info->sector_count = 512;
++ info->size = 0x2000000;
++ info->address32 = 1;
++#if defined(CONFIG_FLASH_SPIx2_Dummy)
++ info->readcmd = 0xbb;
++ info->dummybyte = 1;
++ info->dualport = 1;
++ info->iomode = IOMODEx2_dummy;
++#elif defined(CONFIG_FLASH_SPIx4_Dummy)
++ info->readcmd = 0xeb;
++ info->dummybyte = 3;
++ info->dualport = 0;
++ info->iomode = IOMODEx4_dummy;
++ info->quadport = 1;
++ info->dummydata = 0xaa;
++#endif
++#endif
++ break;
++
++ case 0x200000:
++ info->sector_count =256;
++ info->size = 0x1000000;
++ if ((info->flash_id & 0xFF) == 0x20) /* numonyx */
++ info->specificspi = SpecificSPI_N25Q512;
++#if defined(CONFIG_FLASH_AST2300) || defined(CONFIG_AST1300)
++ info->sector_count = 1024;
++ info->size = 0x4000000;
++ info->address32 = 1;
++#if defined(CONFIG_FLASH_SPIx2_Dummy)
++ info->readcmd = 0xbb;
++ info->dummybyte = 1;
++ info->dualport = 1;
++ info->iomode = IOMODEx2_dummy;
++#elif defined(CONFIG_FLASH_SPIx4_Dummy)
++ info->readcmd = 0xeb;
++ info->dummybyte = 3;
++ info->dualport = 0;
++ info->iomode = IOMODEx4_dummy;
++ info->quadport = 1;
++ info->dummydata = 0xaa;
++#endif
++#endif
++ break;
++
++ default:
++ printf("Can't support this SPI Flash!! \n");
++ return 0;
++ }
++ } /* JDEC */
++ }
++
++ debug ("erase_region_count = %d erase_region_size = %d\n",
++ erase_region_count, erase_region_size);
++
++ sector = base;
++ for (j = 0; j < info->sector_count; j++) {
++
++ info->start[j] = sector;
++ sector += erase_region_size;
++ info->protect[j] = 0; /* default: not protected */
++ }
++
++ /* set SPI flash extended info */
++#if defined(CONFIG_AST1300)
++ if (info->size > 0x200000) /* limit MAX Flash to 2MB for AST1300 */
++ info->size = 0x200000;
++#endif
++#if defined(CONFIG_AST2400) || defined(CONFIG_AST2300) || defined(CONFIG_AST2300_FPGA_1) || defined(CONFIG_AST2300_FPGA_2) || defined(CONFIG_AST1300)
++ reg = *((volatile ulong*) 0x1e6e2024);
++ if (reg & 0x40000)
++ {
++ reg = *((volatile ulong*) 0x1e6e2070);
++
++ ulRefPLL = 24;
++ ulDeNumerator = reg & 0x0F;
++ ulNumerator = (reg & 0x07E0) >> 5;
++ ulOD = (reg & 0x10) ? 1:2;
++
++ cpuclk = ulRefPLL * ulOD * (ulNumerator + 2) / (ulDeNumerator + 1);
++ }
++ else
++ {
++ reg = *((volatile ulong*) 0x1e6e2070);
++#if defined(CONFIG_AST2400)
++ if (reg & 0x00800000) //ref. clk:25MHz
++ {
++ switch (reg & 0x300)
++ {
++ case 0x000:
++ cpuclk = 400;
++ break;
++ case 0x100:
++ cpuclk = 375;
++ break;
++ case 0x200:
++ cpuclk = 350;
++ break;
++ case 0x300:
++ cpuclk = 325;
++ break;
++ }
++ }
++ else
++ {
++ switch (reg & 0x300) //ref. clk:24MHz
++ {
++ case 0x000:
++ cpuclk = 384;
++ break;
++ case 0x100:
++ cpuclk = 360;
++ break;
++ case 0x200:
++ cpuclk = 336;
++ break;
++ case 0x300:
++ cpuclk = 312;
++ break;
++ }
++ }
++#else
++ switch (reg & 0x300)
++ {
++ case 0x000:
++ cpuclk = 384;
++ break;
++ case 0x100:
++ cpuclk = 360;
++ break;
++ case 0x200:
++ cpuclk = 336;
++ break;
++ case 0x300:
++ cpuclk = 408;
++ break;
++ }
++#endif
++ }
++
++ reg = *((volatile ulong*) 0x1e6e2070);
++ switch (reg & 0xc00)
++ {
++ case 0x000:
++ cpuclk /= 1;
++ break;
++ case 0x400:
++ cpuclk /= 2;
++ break;
++ case 0x800:
++ cpuclk /= 4;
++ break;
++ case 0xC00:
++ cpuclk /= 3;
++ break;
++ }
++#else /* AST2100 */
++ reg = *((volatile ulong*) 0x1e6e2070);
++ switch (reg & 0xe00)
++ {
++ case 0x000:
++ cpuclk = 266;
++ break;
++ case 0x200:
++ cpuclk = 233;
++ break;
++ case 0x400:
++ cpuclk = 200;
++ break;
++ case 0x600:
++ cpuclk = 166;
++ break;
++ case 0x800:
++ cpuclk = 133;
++ break;
++ case 0xA00:
++ cpuclk = 100;
++ break;
++ case 0xC00:
++ cpuclk = 300;
++ break;
++ case 0xE00:
++ cpuclk = 24;
++ break;
++ }
++ switch (reg & 0x3000)
++ {
++ case 0x1000:
++ cpuclk /= 2;
++ break;
++ case 0x2000:
++ cpuclk /= 4;
++ break;
++ case 0x3000:
++ cpuclk /= 3;
++ break;
++ }
++#endif
++
++#if defined(CONFIG_AST2400) || defined(CONFIG_AST2300) || defined(CONFIG_AST2300_FPGA_1) || defined(CONFIG_AST2300_FPGA_2) || defined(CONFIG_AST1300)
++
++#if defined(CONFIG_AST2300) || defined(CONFIG_AST1300)
++ /* limit Max SPI CLK to 50MHz (Datasheet v1.2) */
++ if (WriteClk > 50) WriteClk = 50;
++ if (EraseClk > 50) EraseClk = 50;
++ if (ReadClk > 50) ReadClk = 50;
++#endif
++
++ div = 1;
++ while ( ((cpuclk/div) > WriteClk) && (div < 16) )
++ {
++ div++;
++ }
++ info->tCK_Write = AST2300_SPICLK_DIV[div-1];
++
++ div = 1;
++ while ( ((cpuclk/div) > EraseClk) && (div < 16) )
++ {
++ div++;
++ }
++ info->tCK_Erase = AST2300_SPICLK_DIV[div-1];
++
++ div = 1;
++ while ( ((cpuclk/div) > ReadClk) && (div < 16) )
++ {
++ div++;
++ }
++ info->tCK_Read = AST2300_SPICLK_DIV[div-1];
++#else
++ div = 2;
++ info->tCK_Write = 7;
++ while ( (cpuclk/div) > WriteClk )
++ {
++ info->tCK_Write--;
++ div +=2;
++ }
++ div = 2;
++ info->tCK_Erase = 7;
++ while ( (cpuclk/div) > EraseClk )
++ {
++ info->tCK_Erase--;
++ div +=2;
++ }
++ div = 2;
++ info->tCK_Read = 7;
++ while ( (cpuclk/div) > ReadClk )
++ {
++ info->tCK_Read--;
++ div +=2;
++ }
++#endif
++
++ /* unprotect flash */
++ write_status_register(info, 0);
++
++ if (info->quadport)
++ write_status_register(info, 0x40); /* enable QE */
++
++ if (info->address32)
++ {
++ reg = *((volatile ulong*) 0x1e6e2070); /* set H/W Trappings */
++ reg |= 0x10;
++ *((volatile ulong*) 0x1e6e2070) = reg;
++
++ reg = *((volatile ulong*) 0x1e620004); /* enable 32b control bit*/
++ reg |= (0x01 << info->CE);
++ *((volatile ulong*) 0x1e620004) = reg;
++
++ /* set flash chips to 32bits addressing mode */
++ if ((info->flash_id & 0xFF) == 0x01) /* Spansion */
++ enable4b_spansion(info);
++ else if ((info->flash_id & 0xFF) == 0x20) /* Numonyx */
++ enable4b_numonyx(info);
++ else /* MXIC, Winbond */
++ enable4b(info);
++
++ }
++
++ reset_flash(info);
++
++ return (info->size);
++}
++
++
++/*-----------------------------------------------------------------------
++ */
++static int flash_write_buffer (flash_info_t *info, uchar *src, ulong addr, int len)
++{
++ ulong j, base, offset;
++ ulong ulSMMBase, ulCtrlData, CtrlOffset;
++ uchar jReg;
++
++ if (info->CE == 2)
++ {
++ CtrlOffset = SPICtrlRegOffset2;
++ }
++ else
++ {
++ CtrlOffset = SPICtrlRegOffset;
++ }
++
++ base = info->start[0];
++ offset = addr - base;
++ base = flash_make_addr (info, 0, 0);
++
++ enable_write (info);
++
++ ulCtrlData = (info->tCK_Write << 8);
++
++ ulCtrlData &= CMD_MASK;
++ ulCtrlData |= CE_LOW | USERMODE;
++ *(ulong *) (STCBaseAddress + CtrlOffset) = ulCtrlData;
++ udelay(200);
++ *(uchar *) (base) = (uchar) (0x02);
++ udelay(10);
++ if (info->address32)
++ {
++ *(uchar *) (base) = (uchar) ((offset & 0xff000000) >> 24);
++ udelay(10);
++ }
++ *(uchar *) (base) = (uchar) ((offset & 0xff0000) >> 16);
++ udelay(10);
++ *(uchar *) (base) = (uchar) ((offset & 0x00ff00) >> 8);
++ udelay(10);
++ *(uchar *) (base) = (uchar) ((offset & 0x0000ff));
++ udelay(10);
++
++ for (j=0; j<len; j++)
++ {
++ *(uchar *) (base) = *(uchar *) (src++);
++ udelay(10);
++ }
++
++ ulCtrlData &= CMD_MASK;
++ ulCtrlData |= CE_HIGH | USERMODE;
++ *(ulong *) (STCBaseAddress + CtrlOffset) = ulCtrlData;
++ udelay(200);
++
++ ulCtrlData &= CMD_MASK;
++ ulCtrlData |= CE_LOW | USERMODE;
++ *(ulong *) (STCBaseAddress + CtrlOffset) = ulCtrlData;
++ udelay(200);
++ *(uchar *) (base) = (uchar) (0x05);
++ udelay(10);
++ do {
++ jReg = *(volatile uchar *) (base);
++ } while ((jReg & 0x01));
++ ulCtrlData &= CMD_MASK;
++ ulCtrlData |= CE_HIGH | USERMODE;
++ *(ulong *) (STCBaseAddress + CtrlOffset) = ulCtrlData;
++ udelay(200);
++
++ /* RFSR */
++ if (info->specificspi == SpecificSPI_N25Q512)
++ {
++ ulCtrlData &= CMD_MASK;
++ ulCtrlData |= CE_LOW | USERMODE;
++ *(ulong *) (STCBaseAddress + CtrlOffset) = ulCtrlData;
++ udelay(200);
++ *(uchar *) (base) = (uchar) (0x70);
++ udelay(10);
++ do {
++ jReg = *(volatile uchar *) (base);
++ } while (!(jReg & 0x80));
++ ulCtrlData &= CMD_MASK;
++ ulCtrlData |= CE_HIGH | USERMODE;
++ *(ulong *) (STCBaseAddress + CtrlOffset) = ulCtrlData;
++ udelay(200);
++ }
++}
++
++/*-----------------------------------------------------------------------
++ *
++ * export functions
++ *
++ */
++
++/*-----------------------------------------------------------------------
++ *
++ */
++unsigned long flash_init (void)
++{
++ unsigned long size = 0;
++ int i;
++
++ /* Init: no FLASHes known */
++ for (i = 0; i < CONFIG_SYS_MAX_FLASH_BANKS; ++i) {
++ flash_info[i].flash_id = FLASH_UNKNOWN;
++ size += flash_info[i].size = flash_get_size (bank_base[i], i);
++ if (flash_info[i].flash_id == FLASH_UNKNOWN) {
++#ifndef CFG_FLASH_QUIET_TEST
++ printf ("## Unknown FLASH on Bank %d - Size = 0x%08lx = %ld MB\n",
++ i, flash_info[i].size, flash_info[i].size << 20);
++#endif /* CFG_FLASH_QUIET_TEST */
++ }
++ }
++
++ /* Monitor protection ON by default */
++#if (CONFIG_MONITOR_BASE >= CONFIG_SYS_FLASH_BASE)
++ flash_protect (FLAG_PROTECT_SET,
++ CONFIG_MONITOR_BASE,
++ CONFIG_MONITOR_BASE + monitor_flash_len - 1,
++ flash_get_info(CONFIG_MONITOR_BASE));
++#endif
++
++ /* Environment protection ON by default */
++#ifdef CONFIG_ENV_IS_IN_FLASH
++ flash_protect (FLAG_PROTECT_SET,
++ CONFIG_ENV_ADDR,
++ CONFIG_ENV_ADDR + CONFIG_ENV_SECT_SIZE - 1,
++ flash_get_info(CONFIG_ENV_ADDR));
++#endif
++
++ /* Redundant environment protection ON by default */
++#ifdef CONFIG_ENV_ADDR_REDUND
++ flash_protect (FLAG_PROTECT_SET,
++ CONFIG_ENV_ADDR_REDUND,
++ CONFIG_ENV_ADDR_REDUND + CONFIG_ENV_SIZE_REDUND - 1,
++ flash_get_info(CONFIG_ENV_ADDR_REDUND));
++#endif
++ return (size);
++}
++
++/*-----------------------------------------------------------------------
++ */
++#if defined(CONFIG_ENV_IS_IN_FLASH) || defined(CONFIG_ENV_ADDR_REDUND) || (CONFIG_MONITOR_BASE >= CONFIG_SYS_FLASH_BASE)
++static flash_info_t *flash_get_info(ulong base)
++{
++ int i;
++ flash_info_t * info = 0;
++
++ for (i = 0; i < CONFIG_SYS_MAX_FLASH_BANKS; i ++) {
++ info = & flash_info[i];
++ if (info->size && info->start[0] <= base &&
++ base <= info->start[0] + info->size - 1)
++ break;
++ }
++
++ return i == CONFIG_SYS_MAX_FLASH_BANKS ? 0 : info;
++}
++#endif
++
++/*-----------------------------------------------------------------------
++ */
++int flash_erase (flash_info_t * info, int s_first, int s_last)
++{
++ int rcode = 0;
++ int prot;
++ flash_sect_t sect;
++
++ ulong base, offset;
++ ulong ulSMMBase, ulCtrlData, CtrlOffset;
++ uchar jReg;
++
++ disable_cache();
++
++ if (info->CE == 2)
++ {
++ CtrlOffset = SPICtrlRegOffset2;
++ }
++ else
++ {
++ CtrlOffset = SPICtrlRegOffset;
++ }
++
++ if ((s_first < 0) || (s_first > s_last)) {
++ puts ("- no sectors to erase\n");
++ return 1;
++ }
++
++ prot = 0;
++ for (sect = s_first; sect <= s_last; ++sect) {
++ if (info->protect[sect]) {
++ prot++;
++ }
++ }
++ if (prot) {
++ printf ("- Warning: %d protected sectors will not be erased!\n", prot);
++ } else {
++ putc ('\n');
++ }
++
++ ulCtrlData = (info->tCK_Erase << 8);
++ for (sect = s_first; sect <= s_last; sect++) {
++ if (info->protect[sect] == 0) { /* not protected */
++ /* start erasing */
++ enable_write(info);
++
++ base = info->start[0];
++ offset = info->start[sect] - base;
++ base = flash_make_addr (info, 0, 0);
++
++ ulCtrlData &= CMD_MASK;
++ ulCtrlData |= CE_LOW | USERMODE;
++ *(ulong *) (STCBaseAddress + CtrlOffset) = ulCtrlData;
++ udelay(200);
++ *(uchar *) (base) = (uchar) (0xd8);
++ udelay(10);
++ if (info->address32)
++ {
++ *(uchar *) (base) = (uchar) ((offset & 0xff000000) >> 24);
++ udelay(10);
++ }
++ *(uchar *) (base) = (uchar) ((offset & 0xff0000) >> 16);
++ udelay(10);
++ *(uchar *) (base) = (uchar) ((offset & 0x00ff00) >> 8);
++ udelay(10);
++ *(uchar *) (base) = (uchar) ((offset & 0x0000ff));
++ udelay(10);
++
++ ulCtrlData &= CMD_MASK;
++ ulCtrlData |= CE_HIGH | USERMODE;
++ *(ulong *) (STCBaseAddress + CtrlOffset) = ulCtrlData;
++ udelay(200);
++
++ ulCtrlData &= CMD_MASK;
++ ulCtrlData |= CE_LOW | USERMODE;
++ *(ulong *) (STCBaseAddress + CtrlOffset) = ulCtrlData;
++ udelay(200);
++ *(uchar *) (base) = (uchar) (0x05);
++ udelay(10);
++ do {
++ jReg = *(volatile uchar *) (base);
++ } while ((jReg & 0x01));
++ ulCtrlData &= CMD_MASK;
++ ulCtrlData |= CE_HIGH | USERMODE;
++ *(ulong *) (STCBaseAddress + CtrlOffset) = ulCtrlData;
++ udelay(200);
++
++ /* RFSR */
++ if (info->specificspi == SpecificSPI_N25Q512)
++ {
++ ulCtrlData &= CMD_MASK;
++ ulCtrlData |= CE_LOW | USERMODE;
++ *(ulong *) (STCBaseAddress + CtrlOffset) = ulCtrlData;
++ udelay(200);
++ *(uchar *) (base) = (uchar) (0x70);
++ udelay(10);
++ do {
++ jReg = *(volatile uchar *) (base);
++ } while (!(jReg & 0x80));
++ ulCtrlData &= CMD_MASK;
++ ulCtrlData |= CE_HIGH | USERMODE;
++ *(ulong *) (STCBaseAddress + CtrlOffset) = ulCtrlData;
++ udelay(200);
++ }
++
++ putc ('.');
++ }
++ }
++ puts (" done\n");
++
++ reset_flash(info);
++
++ return rcode;
++}
++
++/*-----------------------------------------------------------------------
++ */
++void flash_print_info (flash_info_t * info)
++{
++ putc ('\n');
++ return;
++}
++
++/*-----------------------------------------------------------------------
++ * Copy memory to flash, returns:
++ * 0 - OK
++ * 1 - write timeout
++ * 2 - Flash not erased
++ */
++int write_buff (flash_info_t * info, uchar * src, ulong addr, ulong cnt)
++{
++ int count;
++ unsigned char pat[] = {'|', '-', '/', '\\'};
++ int patcnt;
++
++ disable_cache();
++
++ /* get lower aligned address */
++ if (addr & (info->buffersize - 1))
++ {
++ count = cnt >= info->buffersize ? (info->buffersize - (addr & 0xff)):cnt;
++ flash_write_buffer (info, src, addr, count);
++ addr+= count;
++ src += count;
++ cnt -= count;
++ }
++
++ /* prog */
++ while (cnt > 0) {
++ count = cnt >= info->buffersize ? info->buffersize:cnt;
++ flash_write_buffer (info, src, addr, count);
++ addr+= count;
++ src += count;
++ cnt -= count;
++ printf("%c\b", pat[(patcnt++) & 0x03]);
++ }
++
++ reset_flash(info);
++
++ return (0);
++}
++
++#ifdef CONFIG_FLASH_AST2300_DMA
++void * memmove_dma(void * dest,const void *src,size_t count)
++{
++ ulong count_align, poll_time, data;
++
++ count_align = (count + 3) & 0xFFFFFFFC; /* 4-bytes align */
++ poll_time = 100; /* set 100 us as default */
++
++ /* force end of burst read */
++ *(volatile ulong *) (STCBaseAddress + SPICtrlRegOffset) |= CE_HIGH;
++ *(volatile ulong *) (STCBaseAddress + SPICtrlRegOffset) &= ~CE_HIGH;
++
++ *(ulong *) (STCBaseAddress + REG_FLASH_DMA_CONTROL) = (ulong) (~FLASH_DMA_ENABLE);
++ *(ulong *) (STCBaseAddress + REG_FLASH_DMA_FLASH_BASE) = (ulong *) (src);
++ *(ulong *) (STCBaseAddress + REG_FLASH_DMA_DRAM_BASE) = (ulong *) (dest);
++ *(ulong *) (STCBaseAddress + REG_FLASH_DMA_LENGTH) = (ulong) (count_align);
++ *(ulong *) (STCBaseAddress + REG_FLASH_DMA_CONTROL) = (ulong) (FLASH_DMA_ENABLE);
++
++ /* wait poll */
++ do {
++ udelay(poll_time);
++ data = *(ulong *) (STCBaseAddress + REG_FLASH_INTERRUPT_STATUS);
++ } while (!(data & FLASH_STATUS_DMA_READY));
++
++ /* clear status */
++ *(ulong *) (STCBaseAddress + REG_FLASH_INTERRUPT_STATUS) |= FLASH_STATUS_DMA_CLEAR;
++}
++#endif
++#endif /* CONFIG_FLASH_SPI */
+diff --git a/board/aspeed/ast2300/hactest.c b/board/aspeed/ast2300/hactest.c
+new file mode 100755
+index 0000000..bfa87d5
+--- /dev/null
++++ b/board/aspeed/ast2300/hactest.c
+@@ -0,0 +1,762 @@
++/*
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
++ * MA 02111-1307 USA
++ */
++
++/*
++ * Diagnostics support
++ */
++#include <common.h>
++#include <command.h>
++#include <post.h>
++#include "slt.h"
++
++#if ((CFG_CMD_SLT & CFG_CMD_HACTEST) && defined(CONFIG_SLT))
++#include "hactest.h"
++
++#include "aes.c"
++#include "rc4.c"
++
++static unsigned char crypto_src[CRYPTO_MAX_SRC], crypto_dst[CRYPTO_MAX_DST], crypto_context[CRYPTO_MAX_CONTEXT];
++static unsigned char hash_src[HASH_MAX_SRC], hash_dst[HASH_MAX_DST], hmac_key[HMAC_MAX_KEY];
++
++/*
++ * table
++ */
++static aes_test aestest[] = {
++ { CRYPTOMODE_ECB, 128,
++ {0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6, 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c, '\0'},
++ {0x32, 0x43, 0xf6, 0xa8, 0x88, 0x5a, 0x30, 0x8d, 0x31, 0x31, 0x98, 0xa2, 0xe0, 0x37, 0x07, 0x34, '\0'},
++ {0x39, 0x25, 0x84, 0x1d, 0x02, 0xdc, 0x09, 0xfb, 0xdc, 0x11, 0x85, 0x97, 0x19, 0x6a, 0x0b, 0x32, '\0'} },
++ {0xFF, 0xFF, "", "", ""}, /* End Mark */
++};
++
++static rc4_test rc4test[] = {
++ {{0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, '\0'},
++ {0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, '\0'}},
++ {{0xff}, {0xff}}, /* End Mark */
++};
++
++static hash_test hashtest[] = {
++ {HASHMODE_SHA1, 20,
++ "abc",
++ {0x53, 0x20, 0xb0, 0x8c, 0xa1, 0xf5, 0x74, 0x62, 0x50, 0x71, 0x89, 0x41, 0xc5, 0x0a, 0xdf, 0x4e, 0xbb, 0x55, 0x76, 0x06, '\0'}},
++ {0xFF, 0xFF, "", ""}, /* End Mark */
++};
++
++static hmac_test hmactest[] = {
++ {HASHMODE_SHA1, 64, 20,
++ {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16,0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, '\0' },
++ "Sample #1",
++ {0xbf, 0x39, 0xda, 0xb1, 0x7d, 0xc2, 0xe1, 0x23, 0x0d, 0x28, 0x35, 0x3b, 0x8c, 0xcb, 0x14, 0xb6, 0x22, 0x02, 0x65, 0xb3, '\0'}},
++ {0xFF, 0xFF, 0xFF, "", "", ""}, /* End Mark */
++};
++
++void EnableHMAC(void)
++{
++ unsigned long ulData;
++
++ /* init SCU */
++ *(unsigned long *) (0x1e6e2000) = 0x1688a8a8;
++
++ ulData = *(volatile unsigned long *) (0x1e6e200c);
++ ulData &= 0xfdfff;
++ *(unsigned long *) (0x1e6e200c) = ulData;
++ udelay(100);
++ ulData = *(volatile unsigned long *) (0x1e6e2004);
++ ulData &= 0xfffef;
++ *(unsigned long *) (0x1e6e2004) = ulData;
++
++}
++
++/* AES */
++void aes_enc_ast3000(aes_context *ctx, uint8 *input, uint8 *iv, uint8 *output, uint32 ulMsgLength , uint32 ulAESMode)
++{
++
++ unsigned long i, ulTemp, ulCommand;
++ unsigned char ch;
++ unsigned char *pjsrc, *pjdst, *pjcontext;
++
++ ulCommand = CRYPTO_ENABLE_RW | CRYPTO_ENABLE_CONTEXT_LOAD | CRYPTO_ENABLE_CONTEXT_SAVE | \
++ CRYPTO_AES | CRYPTO_ENCRYPTO | CRYPTO_SYNC_MODE_ASYNC;
++
++ switch (ctx->nr)
++ {
++ case 10:
++ ulCommand |= CRYPTO_AES128;
++ break;
++ case 12:
++ ulCommand |= CRYPTO_AES192;
++ break;
++ case 14:
++ ulCommand |= CRYPTO_AES256;
++ break;
++ }
++
++ switch (ulAESMode)
++ {
++ case CRYPTOMODE_ECB:
++ ulCommand |= CRYPTO_AES_ECB;
++ break;
++ case CRYPTOMODE_CBC:
++ ulCommand |= CRYPTO_AES_CBC;
++ break;
++ case CRYPTOMODE_CFB:
++ ulCommand |= CRYPTO_AES_CFB;
++ break;
++ case CRYPTOMODE_OFB:
++ ulCommand |= CRYPTO_AES_OFB;
++ break;
++ case CRYPTOMODE_CTR:
++ ulCommand |= CRYPTO_AES_CTR;
++ break;
++ }
++
++ pjsrc = (unsigned char *) m16byteAlignment((unsigned long) crypto_src);
++ pjdst = (unsigned char *) m16byteAlignment((unsigned long) crypto_dst);
++ pjcontext = (unsigned char *) m16byteAlignment((unsigned long) crypto_context);
++
++ /* Init HW */
++ *(unsigned long *) (HAC_REG_BASE + REG_CRYPTO_SRC_BASE_OFFSET) = (unsigned long) pjsrc;
++ *(unsigned long *) (HAC_REG_BASE + REG_CRYPTO_DST_BASE_OFFSET) = (unsigned long) pjdst;
++ *(unsigned long *) (HAC_REG_BASE + REG_CRYPTO_CONTEXT_BASE_OFFSET) = (unsigned long) pjcontext;
++ *(unsigned long *) (HAC_REG_BASE + REG_CRYPTO_LEN_OFFSET) = ulMsgLength;
++
++ /* Set source */
++ for (i=0; i< ulMsgLength; i++)
++ {
++ ch = *(uint8 *)(input + i);
++ *(uint8 *) (pjsrc + i) = ch;
++ }
++
++ /* Set Context */
++ /* Set IV */
++ for (i=0; i<16; i++)
++ {
++ ch = *(uint8 *) (iv + i);
++ *(uint8 *) (pjcontext + i) = ch;
++ }
++
++ /* Set Expansion Key */
++ for (i=0; i<(4*(ctx->nr+1)); i++)
++ {
++ ulTemp = ((ctx->erk[i] & 0xFF) << 24) + ((ctx->erk[i] & 0xFF00) << 8) + ((ctx->erk[i] & 0xFF0000) >> 8) + ((ctx->erk[i] & 0xFF000000) >> 24);
++ *(uint32 *) (pjcontext + i*4 + 16) = ulTemp;
++ }
++
++ /* fire cmd */
++ *(unsigned long *) (HAC_REG_BASE + REG_CRYPTO_CMD_BASE_OFFSET) = ulCommand;
++ do {
++ ulTemp = *(volatile unsigned long *) (HAC_REG_BASE + REG_CRYPTO_STATUS_OFFSET);
++ } while (ulTemp & CRYPTO_BUSY);
++
++ /* Output */
++ for (i=0; i<ulMsgLength; i++)
++ {
++ ch = *(uint8 *) (pjdst + i);
++ *(uint8 *) (output + i) = ch;
++ }
++
++} /* aes_enc_ast3000 */
++
++
++void aes_dec_ast3000(aes_context *ctx, uint8 *input, uint8 *iv, uint8 *output, uint32 ulMsgLength , uint32 ulAESMode)
++{
++ unsigned long i, ulTemp, ulCommand;
++ unsigned char ch;
++ unsigned char *pjsrc, *pjdst, *pjcontext;
++
++ ulCommand = CRYPTO_ENABLE_RW | CRYPTO_ENABLE_CONTEXT_LOAD | CRYPTO_ENABLE_CONTEXT_SAVE | \
++ CRYPTO_AES | CRYPTO_DECRYPTO | CRYPTO_SYNC_MODE_ASYNC;
++
++ switch (ctx->nr)
++ {
++ case 10:
++ ulCommand |= CRYPTO_AES128;
++ break;
++ case 12:
++ ulCommand |= CRYPTO_AES192;
++ break;
++ case 14:
++ ulCommand |= CRYPTO_AES256;
++ break;
++ }
++
++ switch (ulAESMode)
++ {
++ case CRYPTOMODE_ECB:
++ ulCommand |= CRYPTO_AES_ECB;
++ break;
++ case CRYPTOMODE_CBC:
++ ulCommand |= CRYPTO_AES_CBC;
++ break;
++ case CRYPTOMODE_CFB:
++ ulCommand |= CRYPTO_AES_CFB;
++ break;
++ case CRYPTOMODE_OFB:
++ ulCommand |= CRYPTO_AES_OFB;
++ break;
++ case CRYPTOMODE_CTR:
++ ulCommand |= CRYPTO_AES_CTR;
++ break;
++ }
++
++ pjsrc = (unsigned char *) m16byteAlignment((unsigned long) crypto_src);
++ pjdst = (unsigned char *) m16byteAlignment((unsigned long) crypto_dst);
++ pjcontext = (unsigned char *) m16byteAlignment((unsigned long) crypto_context);
++
++ /* Init HW */
++ *(unsigned long *) (HAC_REG_BASE + REG_CRYPTO_SRC_BASE_OFFSET) = (unsigned long) pjsrc;
++ *(unsigned long *) (HAC_REG_BASE + REG_CRYPTO_DST_BASE_OFFSET) = (unsigned long) pjdst;
++ *(unsigned long *) (HAC_REG_BASE + REG_CRYPTO_CONTEXT_BASE_OFFSET) = (unsigned long) pjcontext;
++ *(unsigned long *) (HAC_REG_BASE + REG_CRYPTO_LEN_OFFSET) = ulMsgLength;
++
++ /* Set source */
++ for (i=0; i< ulMsgLength; i++)
++ {
++ ch = *(uint8 *)(input + i);
++ *(uint8 *) (pjsrc + i) = ch;
++ }
++
++ /* Set Context */
++ /* Set IV */
++ for (i=0; i<16; i++)
++ {
++ ch = *(uint8 *) (iv + i);
++ *(uint8 *) (pjcontext + i) = ch;
++ }
++
++ /* Set Expansion Key */
++ for (i=0; i<(4*(ctx->nr+1)); i++)
++ {
++ ulTemp = ((ctx->erk[i] & 0xFF) << 24) + ((ctx->erk[i] & 0xFF00) << 8) + ((ctx->erk[i] & 0xFF0000) >> 8) + ((ctx->erk[i] & 0xFF000000) >> 24);
++ *(uint32 *) (pjcontext + i*4 + 16) = ulTemp;
++ }
++
++ /* fire cmd */
++ *(unsigned long *) (HAC_REG_BASE + REG_CRYPTO_CMD_BASE_OFFSET) = ulCommand;
++ do {
++ ulTemp = *(volatile unsigned long *) (HAC_REG_BASE + REG_CRYPTO_STATUS_OFFSET);
++ } while (ulTemp & CRYPTO_BUSY);
++
++ /* Output */
++ for (i=0; i<ulMsgLength; i++)
++ {
++ ch = *(uint8 *) (pjdst + i);
++ *(uint8 *) (output + i) = ch;
++ }
++
++} /* aes_dec_ast3000 */
++
++void rc4_crypt_ast3000(uint8 *data, int ulMsgLength, uint8 *rc4_key, uint32 ulKeyLength)
++{
++ struct rc4_state s;
++ unsigned long i, ulTemp, ulCommand;
++ unsigned char ch;
++ unsigned char *pjsrc, *pjdst, *pjcontext;
++
++ ulCommand = CRYPTO_ENABLE_RW | CRYPTO_ENABLE_CONTEXT_LOAD | CRYPTO_ENABLE_CONTEXT_SAVE | \
++ CRYPTO_RC4 | CRYPTO_SYNC_MODE_ASYNC;
++
++ rc4_setup( &s, rc4_key, ulKeyLength );
++
++ pjsrc = (unsigned char *) m16byteAlignment((unsigned long) crypto_src);
++ pjdst = (unsigned char *) m16byteAlignment((unsigned long) crypto_dst);
++ pjcontext = (unsigned char *) m16byteAlignment((unsigned long) crypto_context);
++
++ /* Init HW */
++ *(uint32 *) (HAC_REG_BASE + REG_CRYPTO_SRC_BASE_OFFSET) = (unsigned long) pjsrc;
++ *(uint32 *) (HAC_REG_BASE + REG_CRYPTO_DST_BASE_OFFSET) = (unsigned long) pjdst;
++ *(uint32 *) (HAC_REG_BASE + REG_CRYPTO_CONTEXT_BASE_OFFSET) = (unsigned long) pjcontext;
++ *(uint32 *) (HAC_REG_BASE + REG_CRYPTO_LEN_OFFSET) = ulMsgLength;
++
++
++ /* Set source */
++ for (i=0; i< ulMsgLength; i++)
++ {
++ ch = *(uint8 *)(data + i);
++ *(uint8 *) (pjsrc + i) = ch;
++ }
++
++ /* Set Context */
++ /* Set i, j */
++ *(uint32 *) (pjcontext + 8) = 0x0001;
++
++ /* Set Expansion Key */
++ for (i=0; i<(256/4); i++)
++ {
++ ulTemp = (s.m[i * 4] & 0xFF) + ((s.m[i * 4 + 1] & 0xFF) << 8) + ((s.m[i * 4 + 2] & 0xFF) << 16) + ((s.m[i * 4+ 3] & 0xFF) << 24);
++ *(uint32 *) (pjcontext + i*4 + 16) = ulTemp;
++ }
++
++ /* fire cmd */
++ *(uint32 *) (HAC_REG_BASE + REG_CRYPTO_CMD_BASE_OFFSET) = ulCommand;
++ do {
++ ulTemp = *(volatile uint32 *) (HAC_REG_BASE + REG_CRYPTO_STATUS_OFFSET);
++ } while (ulTemp & CRYPTO_BUSY);
++
++ /* Output */
++ for (i=0; i<ulMsgLength; i++)
++ {
++ ch = *(volatile uint8 *) (pjdst + i);
++ *(uint8 *) (data + i) = ch;
++ }
++
++} /* rc4_crypt_ast3000 */
++
++/* Hash */
++void hash_ast3000(uint8 *msg, uint32 ulLength, unsigned char *output, uint32 ulHashMode)
++{
++ uint32 i, ulTemp, ulCommand, ulDigestLength, ulMyMsgLength;
++ uint8 ch;
++ unsigned char *pjsrc, *pjdst;
++
++ /* Get Info */
++ switch (ulHashMode)
++ {
++ case HASHMODE_MD5:
++ ulCommand = HASH_ALG_SELECT_MD5;
++ ulDigestLength = 16;
++ break;
++ case HASHMODE_SHA1:
++ ulCommand = HASH_ALG_SELECT_SHA1 | 0x08;
++ ulDigestLength = 20;
++ break;
++ case HASHMODE_SHA256:
++ ulCommand = HASH_ALG_SELECT_SHA256 | 0x08;
++ ulDigestLength = 32;
++ break;
++ case HASHMODE_SHA224:
++ ulCommand = HASH_ALG_SELECT_SHA224 | 0x08;
++ ulDigestLength = 28;
++ break;
++ }
++
++ pjsrc = (unsigned char *) m16byteAlignment((unsigned long) hash_src);
++ pjdst = (unsigned char *) m16byteAlignment((unsigned long) hash_dst);
++
++ /* 16byte alignment */
++ ulMyMsgLength = m16byteAlignment(ulLength);
++
++ /* Init. HW */
++ *(uint32 *) (HAC_REG_BASE + REG_HASH_SRC_BASE_OFFSET) = (unsigned long) pjsrc;
++ *(uint32 *) (HAC_REG_BASE + REG_HASH_DST_BASE_OFFSET) = (unsigned long) pjdst;
++ *(uint32 *) (HAC_REG_BASE + REG_HASH_LEN_OFFSET) = ulMyMsgLength;
++
++ /* write src */
++ for (i=0; i<ulLength; i++)
++ {
++ ch = *(uint8 *)(msg+i);
++ *(uint8 *) (pjsrc + i) = ch;
++ }
++ for (i=ulLength; i<ulMyMsgLength; i++)
++ *(uint8 *) (pjsrc + i) = 0;
++
++ /* fire cmd */
++ *(uint32 *) (HAC_REG_BASE + REG_HASH_CMD_OFFSET) = ulCommand;
++
++ /* get digest */
++ do {
++ ulTemp = *(volatile uint32 *) (HAC_REG_BASE + REG_HASH_STATUS_OFFSET);
++ } while (ulTemp & HASH_BUSY);
++
++ for (i=0; i<ulDigestLength; i++)
++ {
++ ch = *(volatile uint8 *) (pjdst + i);
++ *(uint8 *) (output + i) = ch;
++ }
++
++} /* hash_ast3000 */
++
++/* HMAC */
++void hmackey_ast3000(uint8 *key, uint32 ulKeyLength, uint32 ulHashMode)
++{
++ uint32 i, ulBlkLength, ulDigestLength, ulTemp, ulCommand;
++ uint8 k0[64], sum[32];
++ uint8 ch;
++ unsigned char *pjsrc, *pjdst, *pjkey;
++
++ /* Get Info */
++ switch (ulHashMode)
++ {
++ case HASHMODE_MD5:
++ ulCommand = HASH_ALG_SELECT_MD5;
++ ulDigestLength = 16;
++ break;
++ case HASHMODE_SHA1:
++ ulCommand = HASH_ALG_SELECT_SHA1 | 0x08;
++ ulDigestLength = 20;
++ break;
++ case HASHMODE_SHA256:
++ ulCommand = HASH_ALG_SELECT_SHA256 | 0x08;
++ ulDigestLength = 32;
++ break;
++ case HASHMODE_SHA224:
++ ulCommand = HASH_ALG_SELECT_SHA224 | 0x08;
++ ulDigestLength = 28;
++ break;
++ }
++ ulBlkLength = 64; /* MD5, SHA1/256/224: 64bytes */
++
++ /* Init */
++ memset( (void *) k0, 0, 64); /* reset to zero */
++ memset( (void *) sum, 0, 32); /* reset to zero */
++
++ /* Get k0 */
++ if (ulKeyLength <= ulBlkLength)
++ memcpy( (void *) k0, (void *) key, ulKeyLength );
++ else /* (ulKeyLength > ulBlkLength) */
++ {
++ hash_ast3000(key, ulKeyLength, sum, ulHashMode);
++ memcpy( (void *) k0, (void *) sum, ulDigestLength );
++ }
++
++ pjsrc = (unsigned char *) m16byteAlignment((unsigned long) hash_src);
++ pjdst = (unsigned char *) m16byteAlignment((unsigned long) hash_dst);
++ pjkey = (unsigned char *) m64byteAlignment((unsigned long) hmac_key);
++
++ /* Calculate digest */
++ *(uint32 *) (HAC_REG_BASE + REG_HASH_SRC_BASE_OFFSET) = (unsigned long) pjsrc;
++ *(uint32 *) (HAC_REG_BASE + REG_HASH_DST_BASE_OFFSET) = (unsigned long) pjdst;
++ *(uint32 *) (HAC_REG_BASE + REG_HASH_KEY_BASE_OFFSET) = (unsigned long) pjkey;
++ *(uint32 *) (HAC_REG_BASE + REG_HASH_LEN_OFFSET) = ulBlkLength;
++
++ /* write key to src */
++ for (i=0; i<ulBlkLength; i++)
++ {
++ ch = *(uint8 *)(k0+i);
++ *(uint8 *) (pjsrc + i) = ch;
++ }
++
++ /* fire cmd for calculate */
++ *(uint32 *) (HAC_REG_BASE + REG_HASH_CMD_OFFSET) = ulCommand | HAC_DIGEST_CAL_ENABLE;
++ do {
++ ulTemp = *(volatile uint32 *) (HAC_REG_BASE + REG_HASH_STATUS_OFFSET);
++ } while (ulTemp & HASH_BUSY);
++
++} /* hmackey_ast3000 */
++
++void hmac_ast3000(uint8 *key, uint32 ulKeyLength, uint8 *msg, uint32 ulMsgLength, uint32 ulHashMode, unsigned char *output)
++{
++ uint32 i, ulTemp, ulCommand, ulDigestLength, ulMyMsgLength;;
++ uint8 ch;
++ unsigned char *pjsrc, *pjdst, *pjkey;
++
++ /* Calculate digest */
++ switch (ulHashMode)
++ {
++ case HASHMODE_MD5:
++ ulCommand = HASH_ALG_SELECT_MD5;
++ ulDigestLength = 16;
++ break;
++ case HASHMODE_SHA1:
++ ulCommand = HASH_ALG_SELECT_SHA1 | 0x08;
++ ulDigestLength = 20;
++ break;
++ case HASHMODE_SHA256:
++ ulCommand = HASH_ALG_SELECT_SHA256 | 0x08;
++ ulDigestLength = 32;
++ break;
++ case HASHMODE_SHA224:
++ ulCommand = HASH_ALG_SELECT_SHA224 | 0x08;
++ ulDigestLength = 28;
++ break;
++ }
++
++ pjsrc = (unsigned char *) m16byteAlignment((unsigned long) hash_src);
++ pjdst = (unsigned char *) m16byteAlignment((unsigned long) hash_dst);
++ pjkey = (unsigned char *) m64byteAlignment((unsigned long) hmac_key);
++
++ /* 16byte alignment */
++ ulMyMsgLength = m16byteAlignment(ulMsgLength);
++
++ /* Init. HW */
++ *(uint32 *) (HAC_REG_BASE + REG_HASH_SRC_BASE_OFFSET) = (unsigned long) pjsrc;
++ *(uint32 *) (HAC_REG_BASE + REG_HASH_DST_BASE_OFFSET) = (unsigned long) pjdst;
++ *(uint32 *) (HAC_REG_BASE + REG_HASH_KEY_BASE_OFFSET) = (unsigned long) pjkey;
++ *(uint32 *) (HAC_REG_BASE + REG_HASH_LEN_OFFSET) = ulMyMsgLength;
++
++ /* write Text to src */
++ for (i=0; i<ulMsgLength; i++)
++ {
++ ch = *(uint8 *)(msg+i);
++ *(uint8 *) (pjsrc + i) = ch;
++ }
++ for (i=ulMsgLength; i<ulMyMsgLength; i++)
++ *(uint8 *) (pjsrc + i) = 0;
++
++ /* fire cmd */
++ *(uint32 *) (HAC_REG_BASE + REG_HASH_CMD_OFFSET) = ulCommand | HAC_ENABLE;
++ do {
++ ulTemp = *(volatile uint32 *) (HAC_REG_BASE + REG_HASH_STATUS_OFFSET);
++ } while (ulTemp & HASH_BUSY);
++
++ /* Output Digest */
++ for (i=0; i<ulDigestLength; i++)
++ {
++ ch = *(uint8 *) (pjdst + i);
++ *(uint8 *) (output + i) = ch;
++ }
++
++} /* hmac_ast3000 */
++
++/* main hactest procedure */
++int do_hactest (void)
++{
++ unsigned long i, j, Flags = 0;
++ aes_test *pjaes_test;
++ aes_context aes_ctx;
++ unsigned char AES_Mode[8], aes_output[64];
++ unsigned long ulAESMsgLength;
++
++ rc4_test *pjrc4_test;
++ unsigned char rc4_buf_sw[64], rc4_buf_hw[64];
++ unsigned long ulRC4KeyLength, ulRC4MsgLength;
++
++ hash_test *pjhash_test;
++ unsigned char HASH_Mode[8], hash_out[64];
++
++ hmac_test *pjhmac_test;
++ unsigned char HMAC_Mode[8], hmac_out[64];
++
++ EnableHMAC();
++
++ /* AES Test */
++ pjaes_test = aestest;
++ while (pjaes_test->aes_mode != 0xFF)
++ {
++
++ if (pjaes_test->aes_mode == CRYPTOMODE_CBC)
++ strcpy (AES_Mode, "CBC");
++ else if (pjaes_test->aes_mode == CRYPTOMODE_CFB)
++ strcpy (AES_Mode, "CFB");
++ else if (pjaes_test->aes_mode == CRYPTOMODE_OFB)
++ strcpy (AES_Mode, "OFB");
++ else if (pjaes_test->aes_mode == CRYPTOMODE_CTR)
++ strcpy (AES_Mode, "CTR");
++ else
++ strcpy (AES_Mode, "ECB");
++
++ /* Get Msg. Length */
++ ulAESMsgLength = strlen(pjaes_test->plaintext);
++ j = ( (ulAESMsgLength + 15) >> 4) << 4;
++ for (i=ulAESMsgLength; i<j; i++)
++ pjaes_test->plaintext[i] = 0;
++ ulAESMsgLength = j;
++
++ aes_set_key(&aes_ctx, pjaes_test->key, pjaes_test->key_length);
++
++ /* Encryption Test */
++ aes_enc_ast3000(&aes_ctx, pjaes_test->plaintext, pjaes_test->key, aes_output, ulAESMsgLength, pjaes_test->aes_mode);
++ if (strncmp(aes_output, pjaes_test->ciphertext, ulAESMsgLength))
++ {
++ Flags |= FLAG_AESTEST_FAIL;
++ printf("[INFO] AES%d %s Mode Encryption Failed \n", pjaes_test->key_length, AES_Mode);
++ printf("[DBG] Golden Data Dump .... \n");
++ for (i=0; i< ulAESMsgLength; i++)
++ {
++ printf("%02x ", pjaes_test->ciphertext[i]);
++ if (((i+1) % 8) == 0)
++ printf("\n");
++ }
++ printf("\n [DBG] Error Data Dump .... \n");
++ for (i=0; i< ulAESMsgLength; i++)
++ {
++ printf("%02x ", aes_output[i]);
++ if (((i+1) % 8) == 0)
++ printf("\n");
++ }
++ printf("\n");
++ }
++ else
++ {
++ /*
++ printf("[INFO] AES%d %s Mode Encryption Passed \n", pjaes_test->key_length, AES_Mode);
++ */
++ }
++
++ /* Decryption Test */
++ aes_dec_ast3000(&aes_ctx, pjaes_test->ciphertext, pjaes_test->key, aes_output, ulAESMsgLength, pjaes_test->aes_mode);
++ if (strncmp(aes_output, pjaes_test->plaintext, ulAESMsgLength))
++ {
++ Flags |= FLAG_AESTEST_FAIL;
++ printf("[INFO] AES%d %s Mode Decryption Failed \n", pjaes_test->key_length, AES_Mode);
++ printf("[DBG] Golden Data Dump .... \n");
++ for (i=0; i< ulAESMsgLength; i++)
++ {
++ printf("%02x ", pjaes_test->plaintext[i]);
++ if (((i+1) % 8) == 0)
++ printf("\n");
++ }
++ printf("\n [DBG] Error Data Dump .... \n");
++ for (i=0; i< ulAESMsgLength; i++)
++ {
++ printf("%02x ", aes_output[i]);
++ if (((i+1) % 8) == 0)
++ printf("\n");
++ }
++ printf("\n");
++ }
++ else
++ {
++ /*
++ printf("[INFO] AES%d %s Mode Decryption Passed \n", pjaes_test->key_length, AES_Mode);
++ */
++ }
++
++ pjaes_test++;
++ } /* AES */
++
++ /* RC4 Test */
++ pjrc4_test = rc4test;
++ while ((pjrc4_test->key[0] != 0xff) && (pjrc4_test->data[0] != 0xff))
++ {
++
++ /* Get Info */
++ ulRC4KeyLength = strlen(pjrc4_test->key);
++ ulRC4MsgLength = strlen(pjrc4_test->data);
++ memcpy( (void *) rc4_buf_sw, (void *) pjrc4_test->data, ulRC4MsgLength );
++ memcpy( (void *) rc4_buf_hw, (void *) pjrc4_test->data, ulRC4MsgLength );
++
++ /* Crypto */
++ rc4_crypt_sw(rc4_buf_sw, ulRC4MsgLength, pjrc4_test->key, ulRC4KeyLength);
++ rc4_crypt_ast3000(rc4_buf_hw, ulRC4MsgLength, pjrc4_test->key, ulRC4KeyLength);
++
++ if (strncmp(rc4_buf_hw, rc4_buf_sw, ulRC4MsgLength))
++ {
++ Flags |= FLAG_RC4TEST_FAIL;
++ printf("[INFO] RC4 Encryption Failed \n");
++ printf("[DBG] Golden Data Dump .... \n");
++ for (i=0; i< ulRC4MsgLength; i++)
++ {
++ printf("%02x ", rc4_buf_sw[i]);
++ if (((i+1) % 8) == 0)
++ printf("\n");
++ }
++ printf("\n [DBG] Error Data Dump .... \n");
++ for (i=0; i< ulRC4MsgLength; i++)
++ {
++ printf("%02x ", rc4_buf_hw[i]);
++ if (((i+1) % 8) == 0)
++ printf("\n");
++ }
++ printf("\n");
++ }
++ else
++ {
++ /*
++ printf("[INFO] RC4 Encryption Passed \n");
++ */
++ }
++
++ pjrc4_test++;
++
++ } /* RC4 */
++
++ /* Hash Test */
++ pjhash_test = hashtest;
++ while (pjhash_test->hash_mode != 0xFF)
++ {
++
++ if (pjhash_test->hash_mode == HASHMODE_MD5)
++ strcpy (HASH_Mode, "MD5");
++ else if (pjhash_test->hash_mode == HASHMODE_SHA1)
++ strcpy (HASH_Mode, "SHA1");
++ else if (pjhash_test->hash_mode == HASHMODE_SHA256)
++ strcpy (HASH_Mode, "SHA256");
++ else if (pjhash_test->hash_mode == HASHMODE_SHA224)
++ strcpy (HASH_Mode, "SHA224");
++
++ /* Hash */
++ hash_ast3000(pjhash_test->input, strlen(pjhash_test->input), hash_out, pjhash_test->hash_mode);
++ if (strncmp(hash_out, pjhash_test->digest, pjhash_test->digest_length))
++ {
++ Flags |= FLAG_HASHTEST_FAIL;
++ printf("[INFO] HASH %s Failed \n", HASH_Mode);
++ printf("[DBG] Golden Data Dump .... \n");
++ for (i=0; i< pjhash_test->digest_length; i++)
++ {
++ printf("%02x ",pjhash_test->digest[i]);
++ if (((i+1) % 8) == 0)
++ printf("\n");
++ }
++ printf("\n [DBG] Error Data Dump .... \n");
++ for (i=0; i< pjhash_test->digest_length; i++)
++ {
++ printf("%02x ",hash_out[i]);
++ if (((i+1) % 8) == 0)
++ printf("\n");
++ }
++ printf("\n");
++ }
++ else
++ {
++ /*
++ printf("[INFO] HASH %s Passed \n", HASH_Mode);
++ */
++ }
++
++ pjhash_test++;
++
++ } /* Hash Test */
++
++ /* HMAC Test */
++ pjhmac_test = hmactest;
++ while (pjhmac_test->hash_mode != 0xFF)
++ {
++
++ if (pjhmac_test->hash_mode == HASHMODE_MD5)
++ strcpy (HMAC_Mode, "MD5");
++ else if (pjhmac_test->hash_mode == HASHMODE_SHA1)
++ strcpy (HMAC_Mode, "SHA1");
++ else if (pjhmac_test->hash_mode == HASHMODE_SHA256)
++ strcpy (HMAC_Mode, "SHA256");
++ else if (pjhmac_test->hash_mode == HASHMODE_SHA224)
++ strcpy (HMAC_Mode, "SHA224");
++
++ /* HMAC */
++ hmackey_ast3000(pjhmac_test->key, pjhmac_test->key_length, pjhmac_test->hash_mode);
++ hmac_ast3000(pjhmac_test->key, pjhmac_test->key_length, pjhmac_test->input, strlen(pjhmac_test->input), pjhmac_test->hash_mode, hmac_out);
++ if (strncmp(hmac_out, pjhmac_test->digest, pjhmac_test->digest_length))
++ {
++ Flags |= FLAG_HASHTEST_FAIL;
++ printf("[INFO] HMAC %s Failed \n", HMAC_Mode);
++ printf("[DBG] Golden Data Dump .... \n");
++ for (i=0; i< pjhmac_test->digest_length; i++)
++ {
++ printf("%02x ",pjhmac_test->digest[i]);
++ if (((i+1) % 8) == 0)
++ printf("\n");
++ }
++ printf("\n [DBG] Error Data Dump .... \n");
++ for (i=0; i< pjhmac_test->digest_length; i++)
++ {
++ printf("%02x ",hmac_out[i]);
++ if (((i+1) % 8) == 0)
++ printf("\n");
++ }
++ printf("\n");
++ }
++ else
++ {
++ /*
++ printf("[INFO] HMAC %s Passed \n", HMAC_Mode);
++ */
++ }
++
++ pjhmac_test++;
++
++ } /* HMAC Test */
++
++ return Flags;
++
++}
++
++#endif /* CONFIG_SLT */
+diff --git a/board/aspeed/ast2300/hactest.h b/board/aspeed/ast2300/hactest.h
+new file mode 100755
+index 0000000..fcf2186
+--- /dev/null
++++ b/board/aspeed/ast2300/hactest.h
+@@ -0,0 +1,194 @@
++/*
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++ */
++/* Err Flags */
++#define FLAG_AESTEST_FAIL 0x00000001
++#define FLAG_RC4TEST_FAIL 0x00000002
++#define FLAG_HASHTEST_FAIL 0x00000004
++
++/* Specific */
++/*
++#define DRAM_BASE 0x40000000
++#define CRYPTO_SRC_BASE (DRAM_BASE + 0x100000)
++#define CRYPTO_DST_BASE (DRAM_BASE + 0x200000)
++#define CRYPTO_CONTEXT_BASE (DRAM_BASE + 0x300000)
++
++#define HASH_SRC_BASE (DRAM_BASE + 0x400000)
++#define HASH_DST_BASE (DRAM_BASE + 0x500000)
++#define HMAC_KEY_BASE (DRAM_BASE + 0x600000)
++*/
++#define m08byteAlignment(x) ((x + 0x00000007) & 0xFFFFFFF8)
++#define m16byteAlignment(x) ((x + 0x0000000F) & 0xFFFFFFF0)
++#define m64byteAlignment(x) ((x + 0x0000003F) & 0xFFFFFFC0)
++
++#define CRYPTO_ALIGNMENT 16
++#define CRYPTO_MAX_SRC (100+CRYPTO_ALIGNMENT)
++#define CRYPTO_MAX_DST (100+CRYPTO_ALIGNMENT)
++#define CRYPTO_MAX_CONTEXT (100+CRYPTO_ALIGNMENT)
++
++#define HASH_ALIGNMENT 16
++#define HMAC_KEY_ALIGNMENT 64
++#define HASH_MAX_SRC (100+HASH_ALIGNMENT)
++#define HASH_MAX_DST (32+HASH_ALIGNMENT)
++#define HMAC_MAX_KEY (64+HMAC_KEY_ALIGNMENT)
++
++/* General */
++#define HAC_REG_BASE 0x1e6e3000
++
++#define MAX_KEYLENGTH 100
++#define MAX_TEXTLENGTH 100
++#define MAX_AESTEXTLENGTH 256
++#define MAX_RC4TEXTLENGTH 256
++#define MAX_RC4KEYLENGTH 256
++
++#define CRYPTOMODE_ECB 0x00
++#define CRYPTOMODE_CBC 0x01
++#define CRYPTOMODE_CFB 0x02
++#define CRYPTOMODE_OFB 0x03
++#define CRYPTOMODE_CTR 0x04
++
++#define HASHMODE_MD5 0x00
++#define HASHMODE_SHA1 0x01
++#define HASHMODE_SHA256 0x02
++#define HASHMODE_SHA224 0x03
++
++#define MIXMODE_DISABLE 0x00
++#define MIXMODE_CRYPTO 0x02
++#define MIXMODE_HASH 0x03
++
++#define REG_CRYPTO_SRC_BASE_OFFSET 0x00
++#define REG_CRYPTO_DST_BASE_OFFSET 0x04
++#define REG_CRYPTO_CONTEXT_BASE_OFFSET 0x08
++#define REG_CRYPTO_LEN_OFFSET 0x0C
++#define REG_CRYPTO_CMD_BASE_OFFSET 0x10
++//#define REG_CRYPTO_ENABLE_OFFSET 0x14
++#define REG_CRYPTO_STATUS_OFFSET 0x1C
++
++#define REG_HASH_SRC_BASE_OFFSET 0x20
++#define REG_HASH_DST_BASE_OFFSET 0x24
++#define REG_HASH_KEY_BASE_OFFSET 0x28
++#define REG_HASH_LEN_OFFSET 0x2C
++#define REG_HASH_CMD_OFFSET 0x30
++//#define REG_HASH_ENABLE_OFFSET 0x14
++#define REG_HASH_STATUS_OFFSET 0x1C
++
++#define HASH_BUSY 0x01
++#define CRYPTO_BUSY 0x02
++
++//#define ENABLE_HASH 0x01
++//#define DISABLE_HASH 0x00
++//#define ENABLE_CRYPTO 0x02
++//#define DISABLE_CRYPTO 0x00
++
++#define CRYPTO_SYNC_MODE_MASK 0x03
++#define CRYPTO_SYNC_MODE_ASYNC 0x00
++#define CRYPTO_SYNC_MODE_PASSIVE 0x02
++#define CRYPTO_SYNC_MODE_ACTIVE 0x03
++
++#define CRYPTO_AES128 0x00
++#define CRYPTO_AES192 0x04
++#define CRYPTO_AES256 0x08
++
++#define CRYPTO_AES_ECB 0x00
++#define CRYPTO_AES_CBC 0x10
++#define CRYPTO_AES_CFB 0x20
++#define CRYPTO_AES_OFB 0x30
++#define CRYPTO_AES_CTR 0x40
++
++#define CRYPTO_ENCRYPTO 0x80
++#define CRYPTO_DECRYPTO 0x00
++
++#define CRYPTO_AES 0x000
++#define CRYPTO_RC4 0x100
++
++#define CRYPTO_ENABLE_RW 0x000
++#define CRYPTO_ENABLE_CONTEXT_LOAD 0x000
++#define CRYPTO_ENABLE_CONTEXT_SAVE 0x000
++
++#define HASH_SYNC_MODE_MASK 0x03
++#define HASH_SYNC_MODE_ASYNC 0x00
++#define HASH_SYNC_MODE_PASSIVE 0x02
++#define HASH_SYNC_MODE_ACTIVE 0x03
++
++#define HASH_READ_SWAP_ENABLE 0x04
++#define HMAC_SWAP_CONTROL_ENABLE 0x08
++
++#define HASH_ALG_SELECT_MASK 0x70
++#define HASH_ALG_SELECT_MD5 0x00
++#define HASH_ALG_SELECT_SHA1 0x20
++#define HASH_ALG_SELECT_SHA224 0x40
++#define HASH_ALG_SELECT_SHA256 0x50
++
++#define HAC_ENABLE 0x80
++#define HAC_DIGEST_CAL_ENABLE 0x180
++#define HASH_INT_ENABLE 0x200
++
++/* AES */
++#ifndef uint8
++#define uint8 unsigned char
++#endif
++
++#ifndef uint32
++#define uint32 unsigned long int
++#endif
++
++typedef struct
++{
++ uint32 erk[64]; /* encryption round keys */
++ uint32 drk[64]; /* decryption round keys */
++ int nr; /* number of rounds */
++}
++aes_context;
++
++typedef struct
++{
++ int aes_mode;
++ int key_length;
++
++ uint8 key[32]; /* as iv in CTR mode */
++ uint8 plaintext[64];
++ uint8 ciphertext[64];
++
++}
++aes_test;
++
++/* RC4 */
++typedef struct
++{
++ uint8 key[32];
++ uint8 data[64];
++}
++rc4_test;
++
++/* Hash */
++typedef struct
++{
++ int hash_mode;
++ int digest_length;
++
++ uint8 input[64];
++ uint8 digest[64];
++
++}
++hash_test;
++
++/* HMAC */
++typedef struct
++{
++ int hash_mode;
++ int key_length;
++ int digest_length;
++
++ uint8 key[100];
++ uint8 input[64];
++ uint8 digest[64];
++
++}
++hmac_test;
+diff --git a/board/aspeed/ast2300/mactest.c b/board/aspeed/ast2300/mactest.c
+new file mode 100755
+index 0000000..5566b65
+--- /dev/null
++++ b/board/aspeed/ast2300/mactest.c
+@@ -0,0 +1,504 @@
++/*
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++ */
++/*
++ * (C) Copyright 2007 ASPEED Software
++ * MAC Manufacture Test in ASPEED's SDK version 0.20.01
++ *
++ * Release History
++ * 1. First Release, river@20071130
++ * 2. Fix the endless loop when PHY is not ready, river@20071204
++ *
++ * Test items:
++ * 1. Support MARVELL PHY only in this version
++ * 2. MDC/MDIO
++ * 3. GMAC/Duplex TX/RX Full_Size, Packet_Length Test
++ * 4. 100M/Duplex TX/RX Full_Size, Packet_Length Test
++ *
++ *
++ *
++*/
++
++
++/*
++* Diagnostics support
++*/
++#include <common.h>
++#include <command.h>
++#include <post.h>
++#include <malloc.h>
++#include <net.h>
++#include "slt.h"
++
++#if ((CFG_CMD_SLT & CFG_CMD_MACTEST) && defined(CONFIG_SLT))
++#include "mactest.h"
++
++static int INL(u_long base, u_long addr)
++{
++ return le32_to_cpu(*(volatile u_long *)(addr + base));
++}
++
++static void OUTL(u_long base, int command, u_long addr)
++{
++ *(volatile u_long *)(addr + base) = cpu_to_le32(command);
++}
++
++
++static void SCU_MAC1_Enable (void)
++{
++ unsigned int SCU_Register;
++
++//MAC1 RESET/PHY_LINK in SCU
++ SCU_Register = INL(SCU_BASE, SCU_RESET_CONTROL_REG);
++ OUTL(SCU_BASE, SCU_Register & ~(0x800), SCU_RESET_CONTROL_REG);
++
++}
++
++/*------------------------------------------------------------
++ . Reads a register from the MII Management serial interface
++ .-------------------------------------------------------------*/
++static u16 phy_read_register (u8 PHY_Register, u8 PHY_Address)
++{
++ u32 Data, Status = 0, Loop_Count = 0, PHY_Ready = 1;
++ u16 Return_Data;
++
++ OUTL(MAC1_IO_BASE, (PHY_Register << 21) + (PHY_Address << 16) + MIIRD + MDC_CYCTHR, PHYCR_REG);
++ do {
++ Status = (INL (MAC1_IO_BASE, PHYCR_REG) & MIIRD);
++ Loop_Count++;
++ if (Loop_Count >= PHY_LOOP) {
++ PHY_Ready = 0;
++ break;
++ }
++ } while (Status == MIIRD);
++
++ if (PHY_Ready == 0) {
++ printf ("PHY NOT REDAY\n");
++ return 0;
++ }
++
++ udelay(5*1000);
++ Data = INL (MAC1_IO_BASE, PHYDATA_REG);
++ Return_Data = (Data >> 16);
++
++ return Return_Data;
++}
++
++static void phy_write_register (u8 PHY_Register, u8 PHY_Address, u16 PHY_Data)
++{
++ u32 Status = 0, Loop_Count = 0, PHY_Ready = 1;
++
++ OUTL(MAC1_IO_BASE, PHY_Data, PHYDATA_REG);
++ OUTL(MAC1_IO_BASE, (PHY_Register << 21) + (PHY_Address << 16) + MIIWR + MDC_CYCTHR, PHYCR_REG);
++ do {
++ Status = (INL (MAC1_IO_BASE, PHYCR_REG) & MIIWR);
++ Loop_Count++;
++ if (Loop_Count >= PHY_LOOP) {
++ PHY_Ready = 0;
++ break;
++ }
++ } while (Status == MIIWR);
++ if (PHY_Ready == 0) {
++ printf ("PHY NOT REDAY\n");
++ }
++}
++
++static int wait_link_resolve (void)
++{
++ int resolved_status, Loop_Count = 0, PHY_Ready = 1;
++
++ do {
++ resolved_status = (phy_read_register (0x11, 0) & (PHY_RESOLVED_bit | PHY_LINK_bit));
++ Loop_Count++;
++ if (Loop_Count >= PHY_LOOP) {
++ PHY_Ready = 0;
++ printf ("PHY NOT READY\n");
++ break;
++ }
++ } while (resolved_status != (PHY_RESOLVED_bit | PHY_LINK_bit));
++
++ return PHY_Ready;
++}
++
++static void set_phy_speed (int chip, int speed, int duplex)
++{
++ unsigned short data, status;
++
++
++ if (chip == PHYID_VENDOR_MARVELL) {
++ if ((speed == PHY_SPEED_1G) && (duplex == DUPLEX_FULL)) {
++//Manual Control
++ phy_write_register (18, 0, 0);
++ data = phy_read_register (9, 0);
++ phy_write_register (9, 0, data | 0x1800);
++//PHY Reset
++ phy_write_register (0, 0, 0x0140 | 0x8000);
++ do {
++ status = (phy_read_register (0, 0) & 0x8000);
++ } while (status != 0);
++
++//Force 1G
++ phy_write_register (29, 0, 0x07);
++ data = phy_read_register (30, 0);
++ phy_write_register (30, 0, data | 0x08);
++ phy_write_register (29, 0, 0x10);
++ data = phy_read_register (30, 0);
++ phy_write_register (30, 0, data | 0x02);
++ phy_write_register (29, 0, 0x12);
++ data = phy_read_register (30, 0);
++ phy_write_register (30, 0, data | 0x01);
++
++ printf ("FORCE MARVELL PHY to 1G/DUPLEX DONE\n");
++ }
++ else if ((speed == PHY_SPEED_100M) && (duplex == DUPLEX_FULL)) {
++//PHY Reset
++ phy_write_register (0, 0, 0x2100 | 0x8000);
++ do {
++ status = (phy_read_register (0, 0) & 0x8000);
++ } while (status != 0);
++
++//Force 100M
++ data = phy_read_register (0, 0);
++ phy_write_register (0, 0, data | 0x4000 | 0x8000);
++ do {
++ status = (phy_read_register (0, 0) & 0x8000);
++ } while (status != 0);
++ data = phy_read_register (0, 0);
++
++ printf ("FORCE MARVELL PHY to 100M/DUPLEX DONE\n");
++ }
++ }
++ else if ( (chip == PHYID_VENDOR_RTL8201E) || (chip == PHYID_VENDOR_BROADCOM) ){
++ /* basic setting */
++ data = phy_read_register (0, 0);
++ data &= 0x7140;
++ data |= 0x4000;
++ if (speed == PHY_SPEED_100M)
++ data |= 0x2000;
++ if (duplex == DUPLEX_FULL)
++ data |= 0x0100;
++ phy_write_register (0, 0, data);
++
++ /* reset */
++ phy_write_register (0, 0, data | 0x8000);
++ do {
++ status = (phy_read_register (0, 0) & 0x8000);
++ } while (status != 0);
++ udelay(100*1000);
++
++ /* basic setting */
++ phy_write_register (0, 0, data);
++
++ if (chip == PHYID_VENDOR_RTL8201E)
++ printf ("FORCE RTL8201E PHY to 100M/DUPLEX DONE\n");
++ else if (chip == PHYID_VENDOR_BROADCOM)
++ printf ("FORCE Broadcom PHY to 100M/DUPLEX DONE\n");
++
++ }
++
++}
++
++static void MAC1_reset (void)
++{
++ OUTL(MAC1_IO_BASE, SW_RST_bit, MACCR_REG);
++ for (; (INL(MAC1_IO_BASE, MACCR_REG ) & SW_RST_bit) != 0; ) {udelay(1000);}
++ OUTL(MAC1_IO_BASE, 0, IER_REG );
++}
++
++static int set_mac1_control_register (int Chip_ID)
++{
++ unsigned long MAC_CR_Register = 0;
++ int PHY_Ready = 1;
++ u16 PHY_Status, PHY_Speed, PHY_Duplex, Advertise, Link_Partner;
++
++ MAC_CR_Register = SPEED_100M_MODE_bit | RX_ALLADR_bit | FULLDUP_bit | RXMAC_EN_bit | RXDMA_EN_bit | TXMAC_EN_bit | TXDMA_EN_bit | CRC_APD_bit;
++
++ if ( (Chip_ID == PHYID_VENDOR_BROADCOM) || (Chip_ID == PHYID_VENDOR_RTL8201E)) {
++ Advertise = phy_read_register (0x04, 0);
++ Link_Partner = phy_read_register (0x05, 0);
++ Advertise = (Advertise & PHY_SPEED_DUPLEX_MASK);
++ Link_Partner = (Link_Partner & PHY_SPEED_DUPLEX_MASK);
++ if ((Advertise & Link_Partner) & PHY_100M_DUPLEX) {
++ MAC_CR_Register |= SPEED_100M_MODE_bit;
++ MAC_CR_Register |= FULLDUP_bit;
++ }
++ else if ((Advertise & Link_Partner) & PHY_100M_HALF) {
++ MAC_CR_Register |= SPEED_100M_MODE_bit;
++ MAC_CR_Register &= ~FULLDUP_bit;
++ }
++ else if ((Advertise & Link_Partner) & PHY_10M_DUPLEX) {
++ MAC_CR_Register &= ~SPEED_100M_MODE_bit;
++ MAC_CR_Register |= FULLDUP_bit;
++ }
++ else if ((Advertise & Link_Partner) & PHY_10M_HALF) {
++ MAC_CR_Register &= ~SPEED_100M_MODE_bit;
++ MAC_CR_Register &= ~FULLDUP_bit;
++ }
++ }
++ else if (Chip_ID == PHYID_VENDOR_MARVELL) {
++
++ PHY_Ready = wait_link_resolve ();
++
++ if (PHY_Ready == 1) {
++ PHY_Status = phy_read_register (0x11, 0);
++ PHY_Speed = (PHY_Status & PHY_SPEED_MASK) >> 14;
++ PHY_Duplex = (PHY_Status & PHY_DUPLEX_MASK) >> 13;
++
++ if (PHY_Speed == SPEED_1000M) {
++ MAC_CR_Register |= GMAC_MODE_bit;
++ }
++ else {
++ MAC_CR_Register &= ~GMAC_MODE_bit;
++ if (PHY_Speed == SPEED_10M) {
++ MAC_CR_Register &= ~SPEED_100M_MODE_bit;
++ }
++ }
++ if (PHY_Duplex == DUPLEX_HALF) {
++ MAC_CR_Register &= ~FULLDUP_bit;
++ }
++ }
++ }
++ OUTL(MAC1_IO_BASE, MAC_CR_Register, MACCR_REG);
++
++ return PHY_Ready;
++}
++
++static void ring_buffer_alloc (void)
++{
++ unsigned int i, j;
++
++//Write data into TX buffer
++ for (i = 0; i < NUM_TX; i++) {
++ for (j = 0; j < TX_BUFF_SZ; j++) {
++ tx_buffer[i][j] = i * 4 + j;
++ }
++ }
++//Initialize RX buffer to 0
++ for (i = 0; i < NUM_RX; i++) {
++ for (j = 0; j < RX_BUFF_SZ; j++) {
++ rx_buffer[i][j] = 0;
++ }
++ }
++//Prepare descriptor
++ for (i = 0; i < NUM_RX; i++) {
++ rx_ring[i].status = cpu_to_le32(RXPKT_RDY + RX_BUFF_SZ);
++ rx_ring[i].buf = ((u32) &rx_buffer[i]);
++ rx_ring[i].reserved = 0;
++ }
++ for (i = 0; i < NUM_TX; i++) {
++ tx_ring[i].status = 0;
++ tx_ring[i].des1 = 0;
++ tx_ring[i].buf = ((u32) &tx_buffer[i]);
++ tx_ring[i].reserved = 0;
++ }
++
++ rx_ring[NUM_RX - 1].status |= cpu_to_le32(EDORR);
++ tx_ring[NUM_TX - 1].status |= cpu_to_le32(EDOTR);
++
++ OUTL(MAC1_IO_BASE, ((u32) &tx_ring), TXR_BADR_REG);
++ OUTL(MAC1_IO_BASE, ((u32) &rx_ring), RXR_BADR_REG);
++
++ tx_new = 0;
++ rx_new = 0;
++}
++
++static int packet_test (void)
++{
++ unsigned int rx_status, length, i, Loop_Count = 0;
++
++ tx_ring[tx_new].status |= cpu_to_le32(LTS | FTS | TX_BUFF_SZ);
++ tx_ring[tx_new].status |= cpu_to_le32(TXDMA_OWN);
++ OUTL(MAC1_IO_BASE, POLL_DEMAND, TXPD_REG);
++
++//Compare result
++ do {
++ rx_status = rx_ring[rx_new].status;
++ Loop_Count++;
++ } while (!(rx_status & RXPKT_STATUS) && (Loop_Count < PHY_LOOP));
++ if (rx_status & (RX_ERR | CRC_ERR | FTL | RUNT | RX_ODD_NB)) {
++ /* There was an error.*/
++ printf("RX error status = 0x%08X\n", rx_status);
++ return PACKET_TEST_FAIL;
++ } else {
++ length = (rx_status & BYTE_COUNT_MASK);
++ for (i = 0; i < RX_BUFF_SZ / 4; i++) {
++ if (rx_buffer[rx_new][i] != tx_buffer[tx_new][i]) {
++ printf ("ERROR at packet %d, address %x\n", rx_new, i);
++ printf ("Gold = %8x, Real = %8x\n", tx_buffer[tx_new][i], rx_buffer[rx_new][i]);
++ return PACKET_TEST_FAIL;
++ }
++ }
++ }
++ tx_new = (tx_new + 1) % NUM_TX;
++ rx_new = (rx_new + 1) % NUM_RX;
++
++ return TEST_PASS;
++}
++
++static int packet_length_test (int packet_length)
++{
++ unsigned int rx_status, length, i, Loop_Count = 0;
++
++ tx_ring[tx_new].status &= (~(BYTE_COUNT_MASK));
++ tx_ring[tx_new].status |= cpu_to_le32(LTS | FTS | packet_length);
++ tx_ring[tx_new].status |= cpu_to_le32(TXDMA_OWN);
++ OUTL(MAC1_IO_BASE, POLL_DEMAND, TXPD_REG);
++
++//Compare result
++ do {
++ rx_status = rx_ring[rx_new].status;
++ Loop_Count++;
++ } while (!(rx_status & RXPKT_STATUS) && (Loop_Count < PHY_LOOP));
++ if (rx_status & (RX_ERR | CRC_ERR | FTL | RUNT | RX_ODD_NB)) {
++ /* There was an error.*/
++ printf("RX error status = 0x%08X\n", rx_status);
++ return PACKET_LENGTH_TEST_FAIL;
++ } else {
++ length = (rx_status & BYTE_COUNT_MASK) - 4;
++ if (length != packet_length) {
++ printf ("Received Length ERROR. Gold = %d, Fail = %d\n",packet_length, length);
++ printf ("rx_new = %d, tx_new = %d\n", rx_new, tx_new);
++ return PACKET_LENGTH_TEST_FAIL;
++ }
++ for (i = 0; i < length; i++) {
++ if (rx_buffer[rx_new][i] != tx_buffer[tx_new][i]) {
++ printf ("ERROR at packet %d, address %x\n", rx_new, i);
++ printf ("Gold = %8x, Real = %8x\n", tx_buffer[tx_new][i], rx_buffer[rx_new][i]);
++ return PACKET_LENGTH_TEST_FAIL;
++ }
++ }
++ }
++ rx_ring[rx_new].status &= (~(RXPKT_STATUS));
++ tx_new = (tx_new + 1) % NUM_TX;
++ rx_new = (rx_new + 1) % NUM_RX;
++
++ return TEST_PASS;
++}
++
++static int MAC1_init (int id)
++{
++ int phy_status = 0;
++
++ MAC1_reset ();
++ phy_status = set_mac1_control_register (id);
++ ring_buffer_alloc ();
++
++ return phy_status;
++}
++
++int do_mactest (void)
++{
++ unsigned int phy_id, i;
++ int test_result = 0, phy_status = 0;
++
++ SCU_MAC1_Enable();
++ phy_id = ((phy_read_register (0x02, 0) << 16) + phy_read_register (0x03, 0)) & PHYID_VENDOR_MASK;
++ if (phy_id == PHYID_VENDOR_MARVELL) {
++ printf ("PHY DETECTED ------> MARVELL\n");
++
++ set_phy_speed (phy_id, PHY_SPEED_1G, DUPLEX_FULL);
++ if ((phy_status = MAC1_init (phy_id)) != 0) {
++ for (i = 0; i < NUM_TX; i++) {
++ test_result |= packet_test ();
++ if (test_result != 0)
++ break;
++ }
++ }
++ else if (phy_status == 0) {
++ printf ("PHY FAIL: Please Check If you are using LOOP BACK Connector\n");
++ test_result = 3;
++ return test_result;
++ }
++ if ((phy_status = MAC1_init (phy_id)) != 0) {
++ for (i = 60; i < TX_BUFF_SZ; i++) {
++ test_result |= packet_length_test (i);
++ if (test_result != 0)
++ break;
++ }
++ }
++ else if (phy_status == 0) {
++ printf ("PHY FAIL: Please Check If you are using LOOP BACK Connector\n");
++ test_result = 3;
++ return test_result;
++ }
++ set_phy_speed (phy_id, PHY_SPEED_100M, DUPLEX_FULL);
++ if ((phy_status = MAC1_init (phy_id)) != 0) {
++ for (i = 0; i < NUM_TX; i++) {
++ test_result |= packet_test ();
++ if (test_result != 0)
++ break;
++ }
++ }
++ else if (phy_status == 0) {
++ printf ("PHY FAIL: Please Check If you are using LOOP BACK Connector\n");
++ test_result = 3;
++ return test_result;
++ }
++
++ if ((phy_status = MAC1_init (phy_id)) != 0) {
++ for (i = 60; i < TX_BUFF_SZ; i++) {
++ test_result |= packet_length_test (i);
++ if (test_result != 0)
++ break;
++ }
++ }
++ else if (phy_status == 0) {
++ printf ("PHY FAIL: Please Check If you are using LOOP BACK Connector\n");
++ test_result = 3;
++ return test_result;
++ }
++ }
++ else if ( (phy_id == PHYID_VENDOR_RTL8201E) || (phy_id == PHYID_VENDOR_BROADCOM) ){
++
++ if (phy_id == PHYID_VENDOR_RTL8201E)
++ printf ("PHY DETECTED ------> RTL 8201E \n");
++ else if (phy_id == PHYID_VENDOR_BROADCOM)
++ printf ("PHY DETECTED ------> Broadcom \n");
++
++ set_phy_speed (phy_id, PHY_SPEED_100M, DUPLEX_FULL);
++ if ((phy_status = MAC1_init (phy_id)) != 0) {
++ for (i = 0; i < NUM_TX; i++) {
++ test_result |= packet_test ();
++ if (test_result != 0)
++ break;
++ }
++ }
++ else if (phy_status == 0) {
++ printf ("PHY FAIL: Please Check If you are using LOOP BACK Connector\n");
++ test_result = 3;
++ return test_result;
++ }
++
++ if ((phy_status = MAC1_init (phy_id)) != 0) {
++ for (i = 60; i < TX_BUFF_SZ; i++) {
++ test_result |= packet_length_test (i);
++ if (test_result != 0)
++ break;
++ }
++ }
++ else if (phy_status == 0) {
++ printf ("PHY FAIL: Please Check If you are using LOOP BACK Connector\n");
++ test_result = 3;
++ return test_result;
++ }
++ }
++
++ if ((phy_status == 0) && (test_result & PACKET_TEST_FAIL)) {
++ printf ("Packet Test FAIL !\n");
++ }
++ else if ((phy_status == 0) && (test_result & PACKET_LENGTH_TEST_FAIL)) {
++ printf ("Packet Length Test FAIL !\n");
++ }
++
++ return test_result;
++
++}
++
++#endif /* CONFIG_SLT */
+diff --git a/board/aspeed/ast2300/mactest.h b/board/aspeed/ast2300/mactest.h
+new file mode 100755
+index 0000000..e75b7bb
+--- /dev/null
++++ b/board/aspeed/ast2300/mactest.h
+@@ -0,0 +1,215 @@
++/*
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++ */
++/* MACTest.h */
++
++// --------------------------------------------------------------------
++// General Definition
++// --------------------------------------------------------------------
++#define MAC1_IO_BASE 0x1E660000
++#define PHY_LOOP 100000
++#define NUM_RX 48
++#define NUM_TX 48
++#define RX_BUFF_SZ 1514
++#define TX_BUFF_SZ 1514
++#define TOUT_LOOP 1000000
++#define ETH_ALEN 6
++#define POLL_DEMAND 1
++
++
++// --------------------------------------------------------------------
++// MAC Register Index
++// --------------------------------------------------------------------
++#define ISR_REG 0x00 // interrups status register
++#define IER_REG 0x04 // interrupt maks register
++#define MAC_MADR_REG 0x08 // MAC address (Most significant)
++#define MAC_LADR_REG 0x0c // MAC address (Least significant)
++#define MAHT0_REG 0x10 // Multicast Address Hash Table 0 register
++#define MAHT1_REG 0x14 // Multicast Address Hash Table 1 register
++#define TXPD_REG 0x18 // Transmit Poll Demand register
++#define RXPD_REG 0x1c // Receive Poll Demand register
++#define TXR_BADR_REG 0x20 // Transmit Ring Base Address register
++#define RXR_BADR_REG 0x24 // Receive Ring Base Address register
++#define HPTXPD_REG 0x28
++#define HPTXR_BADR_REG 0x2c
++#define ITC_REG 0x30 // interrupt timer control register
++#define APTC_REG 0x34 // Automatic Polling Timer control register
++#define DBLAC_REG 0x38 // DMA Burst Length and Arbitration control register
++#define DMAFIFOS_REG 0x3c
++#define FEAR_REG 0x44
++#define TPAFCR_REG 0x48
++#define RBSR_REG 0x4c
++#define MACCR_REG 0x50 // MAC control register
++#define MACSR_REG 0x54 // MAC status register
++#define PHYCR_REG 0x60 // PHY control register
++#define PHYDATA_REG 0x64 // PHY Write Data register
++
++// --------------------------------------------------------------------
++// PHYCR_REG
++// --------------------------------------------------------------------
++#define PHY_RE_AUTO_bit (1UL<<9)
++#define PHY_READ_bit (1UL<<26)
++#define PHY_WRITE_bit (1UL<<27)
++// --------------------------------------------------------------------
++// PHYCR_REG
++// --------------------------------------------------------------------
++#define PHY_AUTO_OK_bit (1UL<<5)
++// --------------------------------------------------------------------
++// PHY INT_STAT_REG
++// --------------------------------------------------------------------
++#define PHY_SPEED_CHG_bit (1UL<<14)
++#define PHY_DUPLEX_CHG_bit (1UL<<13)
++#define PHY_LINK_CHG_bit (1UL<<10)
++#define PHY_AUTO_COMP_bit (1UL<<11)
++// --------------------------------------------------------------------
++// PHY SPE_STAT_REG
++// --------------------------------------------------------------------
++#define PHY_RESOLVED_bit (1UL<<11)
++#define PHY_LINK_bit (1UL<<10)
++#define PHY_SPEED_mask 0xC000
++#define PHY_SPEED_10M 0x0
++#define PHY_SPEED_100M 0x1
++#define PHY_SPEED_1G 0x2
++#define PHY_DUPLEX_mask 0x2000
++#define PHY_SPEED_DUPLEX_MASK 0x01E0
++#define PHY_100M_DUPLEX 0x0100
++#define PHY_100M_HALF 0x0080
++#define PHY_10M_DUPLEX 0x0040
++#define PHY_10M_HALF 0x0020
++#define LINK_STATUS 0x04
++#define PHYID_VENDOR_MASK 0xfffffc00
++#define PHYID_VENDOR_MARVELL 0x01410c00
++#define PHYID_VENDOR_BROADCOM 0x00406000
++#define PHYID_VENDOR_RTL8201E 0x001cc800
++#define DUPLEX_FULL 0x01
++#define DUPLEX_HALF 0x00
++
++
++
++// --------------------------------------------------------------------
++// MACCR_REG
++// --------------------------------------------------------------------
++
++#define SW_RST_bit (1UL<<31) // software reset/
++#define DIRPATH_bit (1UL<<21)
++#define RX_IPCS_FAIL_bit (1UL<<20)
++#define SPEED_100M_MODE_bit (1UL<<19)
++#define RX_UDPCS_FAIL_bit (1UL<<18)
++#define RX_BROADPKT_bit (1UL<<17) // Receiving broadcast packet
++#define RX_MULTIPKT_bit (1UL<<16) // receiving multicast packet
++#define RX_HT_EN_bit (1UL<<15)
++#define RX_ALLADR_bit (1UL<<14) // not check incoming packet's destination address
++#define JUMBO_LF_bit (1UL<<13)
++#define RX_RUNT_bit (1UL<<12) // Store incoming packet even its length is les than 64 byte
++#define CRC_CHK_bit (1UL<<11)
++#define CRC_APD_bit (1UL<<10) // append crc to transmit packet
++#define GMAC_MODE_bit (1UL<<9)
++#define FULLDUP_bit (1UL<<8) // full duplex
++#define ENRX_IN_HALFTX_bit (1UL<<7)
++#define LOOP_EN_bit (1UL<<6) // Internal loop-back
++#define HPTXR_EN_bit (1UL<<5)
++#define REMOVE_VLAN_bit (1UL<<4)
++#define RXMAC_EN_bit (1UL<<3) // receiver enable
++#define TXMAC_EN_bit (1UL<<2) // transmitter enable
++#define RXDMA_EN_bit (1UL<<1) // enable DMA receiving channel
++#define TXDMA_EN_bit (1UL<<0) // enable DMA transmitting channel
++
++
++// --------------------------------------------------------------------
++// SCU_REG
++// --------------------------------------------------------------------
++#define SCU_BASE 0x1E6E2000
++#define SCU_PROTECT_KEY_REG 0x0
++#define SCU_PROT_KEY_MAGIC 0x1688a8a8
++#define SCU_RESET_CONTROL_REG 0x04
++#define SCU_RESET_MAC1 (1u << 11)
++#define SCU_RESET_MAC2 (1u << 12)
++#define SCU_HARDWARE_TRAPPING_REG 0x70
++#define SCU_HT_MAC_INTF_LSBIT 6
++#define SCU_HT_MAC_INTERFACE (0x7u << SCU_HT_MAC_INTF_LSBIT)
++#define MAC_INTF_SINGLE_PORT_MODES (1u<<0/*GMII*/ | 1u<<3/*MII_ONLY*/ | 1u<<4/*RMII_ONLY*/)
++#define SCU_HT_MAC_GMII 0x0u
++// MII and MII mode
++#define SCU_HT_MAC_MII_MII 0x1u
++#define SCU_HT_MAC_MII_ONLY 0x3u
++#define SCU_HT_MAC_RMII_ONLY 0x4u
++#define SCU_MULTIFUNCTION_PIN_REG 0x74
++#define SCU_MFP_MAC2_PHYLINK (1u << 26)
++#define SCU_MFP_MAC1_PHYLINK (1u << 25)
++#define SCU_MFP_MAC2_MII_INTF (1u << 21)
++#define SCU_MFP_MAC2_MDC_MDIO (1u << 20)
++#define SCU_SILICON_REVISION_REG 0x7C
++
++//---------------------------------------------------
++// PHY R/W Register Bit
++//---------------------------------------------------
++#define MIIWR (1UL<<27)
++#define MIIRD (1UL<<26)
++#define MDC_CYCTHR 0x34
++#define PHY_SPEED_MASK 0xC000
++#define PHY_DUPLEX_MASK 0x2000
++#define SPEED_1000M 0x02
++#define SPEED_100M 0x01
++#define SPEED_10M 0x00
++#define DUPLEX_FULL 0x01
++#define DUPLEX_HALF 0x00
++#define RESOLVED_BIT 0x800
++
++#define PHY_SPEED_DUPLEX_MASK 0x01E0
++#define PHY_100M_DUPLEX 0x0100
++#define PHY_100M_HALF 0x0080
++#define PHY_10M_DUPLEX 0x0040
++#define PHY_10M_HALF 0x0020
++
++//---------------------------------------------------
++// Descriptor bits.
++//---------------------------------------------------
++#define TXDMA_OWN 0x80000000 /* Own Bit */
++#define RXPKT_RDY 0x00000000
++#define RXPKT_STATUS 0x80000000
++#define EDORR 0x40000000 /* Receive End Of Ring */
++#define LRS 0x10000000 /* Last Descriptor */
++#define RD_ES 0x00008000 /* Error Summary */
++#define EDOTR 0x40000000 /* Transmit End Of Ring */
++#define T_OWN 0x80000000 /* Own Bit */
++#define LTS 0x10000000 /* Last Segment */
++#define FTS 0x20000000 /* First Segment */
++#define CRC_ERR 0x00080000
++#define TD_ES 0x00008000 /* Error Summary */
++#define TD_SET 0x08000000 /* Setup Packet */
++#define RX_ERR 0x00040000
++#define FTL 0x00100000
++#define RUNT 0x00200000
++#define RX_ODD_NB 0x00400000
++#define BYTE_COUNT_MASK 0x00003FFF
++
++//---------------------------------------------------
++// SPEED/DUPLEX Parameters
++//---------------------------------------------------
++
++//---------------------------------------------------
++// Return Status
++//---------------------------------------------------
++#define TEST_PASS 0
++#define PACKET_TEST_FAIL 1
++#define PACKET_LENGTH_TEST_FAIL 2
++
++struct mac_desc {
++ volatile s32 status;
++ u32 des1;
++ u32 reserved;
++ u32 buf;
++};
++static struct mac_desc rx_ring[NUM_RX] __attribute__ ((aligned(32))); /* RX descriptor ring */
++static struct mac_desc tx_ring[NUM_TX] __attribute__ ((aligned(32))); /* TX descriptor ring */
++static int rx_new; /* RX descriptor ring pointer */
++static int tx_new; /* TX descriptor ring pointer */
++static volatile unsigned char rx_buffer[NUM_RX][RX_BUFF_SZ] __attribute__ ((aligned(32))); /* RX buffer */
++static volatile unsigned char tx_buffer[NUM_TX][TX_BUFF_SZ] __attribute__ ((aligned(32))); /* TX buffer */
+diff --git a/board/aspeed/ast2300/mictest.c b/board/aspeed/ast2300/mictest.c
+new file mode 100755
+index 0000000..1b2b342
+--- /dev/null
++++ b/board/aspeed/ast2300/mictest.c
+@@ -0,0 +1,146 @@
++/*
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
++ * MA 02111-1307 USA
++ */
++
++/*
++ * Diagnostics support
++ */
++#include <common.h>
++#include <command.h>
++#include <post.h>
++#include "slt.h"
++
++#if ((CFG_CMD_SLT & CFG_CMD_MICTEST) && defined(CONFIG_SLT))
++#include "mictest.h"
++
++static unsigned char ctrlbuf[MIC_MAX_CTRL];
++static unsigned char chksumbuf[MIC_MAX_CHKSUM];
++
++void vInitSCU(void)
++{
++ unsigned long ulData;
++
++ *(unsigned long *) (0x1e6e2000) = 0x1688A8A8;
++
++ udelay(100);
++
++ ulData = *(unsigned long *) (0x1e6e2004);
++ ulData &= 0xbffff;
++ *(unsigned long *) (0x1e6e2004) = ulData;
++
++}
++
++void vInitMIC(void)
++{
++ unsigned long i, j, ulPageNumber;
++ unsigned char *pjctrl, *pjsum;
++
++ ulPageNumber = DRAMSIZE >> 12;
++
++ pjctrl = (unsigned char *)(m16byteAlignment((unsigned long) ctrlbuf));
++ pjsum = (unsigned char *)(m16byteAlignment((unsigned long) chksumbuf));
++
++ /* init ctrl buffer (2bits for one page) */
++ for (i=0; i< (ulPageNumber/4); i++)
++ *(unsigned char *) (pjctrl + i) = DEFAULT_CTRL;
++
++ /* init chksum buf (4bytes for one page) */
++ for (i=0; i<ulPageNumber; i++)
++ *(unsigned long *) (pjsum + i*4) = DEFAULT_CHKSUM;
++
++ *(unsigned long *) (MIC_BASE + MIC_CTRLBUFF_REG) = (unsigned long) pjctrl;
++ *(unsigned long *) (MIC_BASE + MIC_CHKSUMBUF_REG) = (unsigned long) pjsum;
++ *(unsigned long *) (MIC_BASE + MIC_RATECTRL_REG) = (unsigned long) DEFAULT_RATE;
++ *(unsigned long *) (MIC_BASE + MIC_ENGINECTRL_REG) = MIC_ENABLE_MIC | (DRAMSIZE - 0x1000);
++
++}
++
++void vDisableMIC(void)
++{
++ *(unsigned long *) (MIC_BASE + MIC_ENGINECTRL_REG) = MIC_RESET_MIC;
++
++}
++
++int do_chksum(void)
++{
++ unsigned long i, j, k, ulPageNumber;
++ int Status = 0;
++ unsigned short tmp;
++ volatile unsigned long sum1, sum2;
++ unsigned long goldensum, chksum;
++ unsigned long len, tlen;
++ unsigned char *pjsum;
++
++ ulPageNumber = DRAMSIZE >> 12;
++ pjsum = (unsigned char *)(m16byteAlignment((unsigned long) chksumbuf));
++
++ /* start test */
++ for (i=0; i<ulPageNumber; i++)
++ {
++
++ sum1 = 0xffff, sum2 = 0xffff;
++ len = 0x0800;
++ j = 0;
++
++ while (len)
++ {
++ tlen = len > 360 ? 360 : len;
++ len -= tlen;
++ do {
++ tmp = *(unsigned short *) (DRAM_BASE + ((i << 12) + j));
++ sum1 += (unsigned long) tmp;
++ sum2 += sum1;
++ j+=2;
++ } while (--tlen);
++ sum1 = (sum1 & 0xffff) + (sum1 >> 16);
++ sum2 = (sum2 & 0xffff) + (sum2 >> 16);
++ }
++
++ sum1 = (sum1 & 0xffff) + (sum1 >> 16);
++ sum2 = (sum2 & 0xffff) + (sum2 >> 16);
++
++ goldensum = (sum2 << 16) | sum1;
++ k= 0;
++ do {
++ chksum = *(unsigned long *) (pjsum + i*4);
++ udelay(100);
++ k++;
++ } while ((chksum == 0) && (k<1000));
++
++ if (chksum != goldensum)
++ {
++ Status = 1;
++ printf("[FAIL] MIC Chksum Failed at Page %x \n", i);
++ }
++
++ } /* end of i loop */
++
++ return (Status);
++
++}
++
++int do_mictest (void)
++{
++ unsigned long Flags = 0;
++
++ vInitSCU();
++ vInitMIC();
++
++ if (do_chksum())
++ Flags = 1;
++
++ vDisableMIC();
++
++ return Flags;
++
++}
++
++#endif /* CONFIG_SLT */
+diff --git a/board/aspeed/ast2300/mictest.h b/board/aspeed/ast2300/mictest.h
+new file mode 100755
+index 0000000..e14bb41
+--- /dev/null
++++ b/board/aspeed/ast2300/mictest.h
+@@ -0,0 +1,55 @@
++/*
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++ */
++/* Macro */
++#define m08byteAlignment(x) ((x + 0x00000007) & 0xFFFFFFF8)
++#define m16byteAlignment(x) ((x + 0x0000000F) & 0xFFFFFFF0)
++#define m64byteAlignment(x) ((x + 0x0000003F) & 0xFFFFFFC0)
++
++/* Options */
++#define MIC_TEST_PAGE 32
++#define DRAMSIZE (MIC_TEST_PAGE * 0x1000)
++#define MIC_MAX_CTRL (MIC_TEST_PAGE / 4 + 16)
++#define MIC_MAX_CHKSUM (MIC_TEST_PAGE * 4 + 16)
++
++/* Default Setting */
++#define DEFAULT_RATE 0x00000000
++#define DEFAULT_CTRL 0xFF
++#define DEFAULT_CHKSUM 0x00000000
++#define DEFAULT_WRITEBACK 0x08880000
++
++/* Reg. Definition */
++#define DRAM_BASE 0x40000000
++#define MIC_BASE 0x1e640000
++#define MIC_CTRLBUFF_REG 0x00
++#define MIC_CHKSUMBUF_REG 0x04
++#define MIC_RATECTRL_REG 0x08
++#define MIC_ENGINECTRL_REG 0x0C
++#define MIC_STOPPAGE_REG 0x10
++#define MIC_STATUS_REG 0x14
++#define MIC_STATUS1_REG 0x18
++#define MIC_STATUS2_REG 0x1C
++
++#define MIC_RESET_MIC 0x00000000
++#define MIC_ENABLE_MIC 0x10000000
++#define MIC_MAXPAGE_MASK 0x0FFFF000
++#define MIC_WRITEBACK_MASK 0xFFFF0000
++#define MIC_STOPPAGE_MASK 0x0000FFFF
++#define MIC_PAGEERROR 0x40000000
++#define MIC_PAGE1ERROR 0x10000000
++#define MIC_PAGE2ERROR 0x20000000
++#define MIC_INTMASK 0x00060000
++#define MIC_ERRPAGENO_MASK 0x0000FFFF
++
++#define MIC_CTRL_MASK 0x03
++#define MIC_CTRL_SKIP 0x00
++#define MIC_CTRL_CHK1 0x01
++#define MIC_CTRL_CHK2 0x02
++#define MIC_CTRL_CHK3 0x03
+diff --git a/board/aspeed/ast2300/pci.c b/board/aspeed/ast2300/pci.c
+new file mode 100755
+index 0000000..5b17466
+--- /dev/null
++++ b/board/aspeed/ast2300/pci.c
+@@ -0,0 +1,243 @@
++/*
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License as
++ * published by the Free Software Foundation; either version 2, or (at
++ * your option) any later version.
++ */
++
++#include <common.h>
++#include <pci.h>
++
++#ifdef CONFIG_PCI
++
++#define PCI_CSR_BASE 0x60000000
++#define ASPEED_PCI_IO_BASE 0x00000000
++#define ASPEED_PCI_IO_SIZE 0x00010000
++#define ASPEED_PCI_MEM_BASE 0x68000000
++#define ASPEED_PCI_MEM_SIZE 0x18000000
++
++#define CSR_CRP_CMD_OFFSET 0x00
++#define CSR_CRP_WRITE_OFFSET 0x04
++#define CSR_CRP_READ_OFFSET 0x08
++#define CSR_PCI_ADDR_OFFSET 0x0C
++#define CSR_PCI_CMD_OFFSET 0x10
++#define CSR_PCI_WRITE_OFFSET 0x14
++#define CSR_PCI_READ_OFFSET 0x18
++#define CSR_PCI_STATUS_OFFSET 0x1C
++
++#define CRP_ADDR_REG (volatile ulong*) (PCI_CSR_BASE + CSR_CRP_CMD_OFFSET)
++#define CRP_WRITE_REG (volatile ulong*) (PCI_CSR_BASE + CSR_CRP_WRITE_OFFSET)
++#define CRP_READ_REG (volatile ulong*) (PCI_CSR_BASE + CSR_CRP_READ_OFFSET)
++#define PCI_ADDR_REG (volatile ulong*) (PCI_CSR_BASE + CSR_PCI_ADDR_OFFSET)
++#define PCI_CMD_REG (volatile ulong*) (PCI_CSR_BASE + CSR_PCI_CMD_OFFSET)
++#define PCI_WRITE_REG (volatile ulong*) (PCI_CSR_BASE + CSR_PCI_WRITE_OFFSET)
++#define PCI_READ_REG (volatile ulong*) (PCI_CSR_BASE + CSR_PCI_READ_OFFSET)
++
++#define PCI_CMD_READ 0x0A
++#define PCI_CMD_WRITE 0x0B
++
++#define RESET_PCI_STATUS *(volatile ulong*) (PCI_CSR_BASE + CSR_PCI_STATUS_OFFSET) = 0x01
++#define CHK_PCI_STATUS (*(volatile ulong*) (PCI_CSR_BASE + CSR_PCI_STATUS_OFFSET) & 0x03)
++
++static int pci_config_access (u8 access_type, u32 dev, u32 reg, u32 * data)
++{
++ u32 bus;
++ u32 device;
++ u32 function;
++
++ bus = ((dev & 0xff0000) >> 16);
++ device = ((dev & 0xf800) >> 11);
++ function = (dev & 0x0700);
++
++ if (bus == 0) {
++ // Type 0 Configuration
++ *PCI_ADDR_REG = (u32) (1UL << device | function | (reg & 0xfc));
++ } else {
++ // Type 1 Configuration
++ *PCI_ADDR_REG = (u32) (dev | ((reg / 4) << 2) | 1);
++ }
++
++ RESET_PCI_STATUS;
++
++ if (access_type == PCI_CMD_WRITE) {
++ *PCI_CMD_REG = (ulong) PCI_CMD_WRITE;
++ *PCI_WRITE_REG = *data;
++ } else {
++ *PCI_CMD_REG = (ulong) PCI_CMD_READ;
++ *data = *PCI_READ_REG;
++ }
++
++ return (CHK_PCI_STATUS);
++}
++
++static int aspeed_pci_read_config_byte (u32 hose, u32 dev, u32 reg, u8 * val)
++{
++ u32 data;
++
++ if (pci_config_access (PCI_CMD_READ, dev, reg, &data)) {
++ *val = 0;
++ return -1;
++ }
++
++ *val = (data >> ((reg & 3) << 3)) & 0xff;
++
++ return 0;
++}
++
++
++static int aspeed_pci_read_config_word (u32 hose, u32 dev, u32 reg, u16 * val)
++{
++ u32 data;
++
++ if (reg & 1)
++ return -1;
++
++ if (pci_config_access (PCI_CMD_READ, dev, reg, &data)) {
++ *val = 0;
++ return -1;
++ }
++
++ *val = (data >> ((reg & 3) << 3)) & 0xffff;
++
++ return 0;
++}
++
++
++static int aspeed_pci_read_config_dword (u32 hose, u32 dev, u32 reg,
++ u32 * val)
++{
++ u32 data = 0;
++
++ if (reg & 3)
++ return -1;
++
++ if (pci_config_access (PCI_CMD_READ, dev, reg, &data)) {
++ *val = 0;
++ return -1;
++ }
++
++ *val = data;
++
++ return (0);
++}
++
++static int aspeed_pci_write_config_byte (u32 hose, u32 dev, u32 reg, u8 val)
++{
++ u32 data = 0;
++
++ if (pci_config_access (PCI_CMD_READ, dev, reg, &data))
++ return -1;
++
++ data = (data & ~(0xff << ((reg & 3) << 3))) | (val <<
++ ((reg & 3) << 3));
++
++ if (pci_config_access (PCI_CMD_WRITE, dev, reg, &data))
++ return -1;
++
++ return 0;
++}
++
++
++static int aspeed_pci_write_config_word (u32 hose, u32 dev, u32 reg, u16 val)
++{
++ u32 data = 0;
++
++ if (reg & 1)
++ return -1;
++
++ if (pci_config_access (PCI_CMD_READ, dev, reg, &data))
++ return -1;
++
++ data = (data & ~(0xffff << ((reg & 3) << 3))) | (val <<
++ ((reg & 3) << 3));
++
++ if (pci_config_access (PCI_CMD_WRITE, dev, reg, &data))
++ return -1;
++
++ return 0;
++}
++
++static int aspeed_pci_write_config_dword (u32 hose, u32 dev, u32 reg, u32 val)
++{
++ u32 data;
++
++ if (reg & 3) {
++ return -1;
++ }
++
++ data = val;
++
++ if (pci_config_access (PCI_CMD_WRITE, dev, reg, &data))
++ return -1;
++
++ return (0);
++}
++
++/*
++ * Initialize PCIU
++ */
++aspeed_pciu_init ()
++{
++
++ unsigned long reg;
++
++ /* Reset PCI Host */
++ reg = *((volatile ulong*) 0x1e6e2004);
++ *((volatile ulong*) 0x1e6e2004) = reg | 0x00280000;
++
++ reg = *((volatile ulong*) 0x1e6e2074); /* REQ2 */
++ *((volatile ulong*) 0x1e6e2074) = reg | 0x00000010;
++
++ *((volatile ulong*) 0x1e6e2008) |= 0x00080000;
++ reg = *((volatile ulong*) 0x1e6e200c);
++ *((volatile ulong*) 0x1e6e200c) = reg & 0xfff7ffff;
++ udelay(1);
++ *((volatile ulong*) 0x1e6e2004) &= 0xfff7ffff;
++
++ /* Initial PCI Host */
++ RESET_PCI_STATUS;
++
++ *CRP_ADDR_REG = ((ulong)(PCI_CMD_READ) << 16) | 0x04;
++ reg = *CRP_READ_REG;
++
++ *CRP_ADDR_REG = ((ulong)(PCI_CMD_WRITE) << 16) | 0x04;
++ *CRP_WRITE_REG = reg | 0x07;
++
++}
++
++/*
++ * Initialize Module
++ */
++
++void aspeed_init_pci (struct pci_controller *hose)
++{
++ hose->first_busno = 0;
++ hose->last_busno = 0xff;
++
++ aspeed_pciu_init (); /* Initialize PCIU */
++
++ /* PCI memory space #1 */
++ pci_set_region (hose->regions + 0,
++ ASPEED_PCI_MEM_BASE, ASPEED_PCI_MEM_BASE, ASPEED_PCI_MEM_SIZE, PCI_REGION_MEM);
++
++ /* PCI I/O space */
++ pci_set_region (hose->regions + 1,
++ ASPEED_PCI_IO_BASE, ASPEED_PCI_IO_BASE, ASPEED_PCI_IO_SIZE, PCI_REGION_IO);
++
++ hose->region_count = 2;
++
++ hose->read_byte = aspeed_pci_read_config_byte;
++ hose->read_word = aspeed_pci_read_config_word;
++ hose->read_dword = aspeed_pci_read_config_dword;
++ hose->write_byte = aspeed_pci_write_config_byte;
++ hose->write_word = aspeed_pci_write_config_word;
++ hose->write_dword = aspeed_pci_write_config_dword;
++
++ pci_register_hose (hose);
++
++ hose->last_busno = pci_hose_scan (hose);
++
++ return;
++}
++#endif /* CONFIG_PCI */
++
+diff --git a/board/aspeed/ast2300/platform.S b/board/aspeed/ast2300/platform.S
+new file mode 100644
+index 0000000..27e8f26
+--- /dev/null
++++ b/board/aspeed/ast2300/platform.S
+@@ -0,0 +1,3089 @@
++/*
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++ */
++/*
++ * Board specific setup info
++ *
++ ******************************************************************************
++ * ASPEED Technology Inc.
++ * AST2300/AST2400 DDR2/DDR3 SDRAM controller initialization and calibration sequence
++ *
++ * Gary Hsu, <gary_hsu@aspeedtech.com>
++ *
++ * Release date: 2014.12.29 formal release for SDK0.60
++ *
++ * Modified list from v0.23
++ * EC1. Modify DQIDLY and DQSI-MCLK2X calibration algorithm
++ * EC2. Remove pass 2 DQIDLY finetune process
++ * EC3. Modify ECC code
++ * EC4. Add AST2400 supporting
++ * EC5. Add SPI timing calibration for AST2400
++ * EC6. Remove AST2300-A0 PCI-e workaround
++ * EC7. Add CK duty calibration for AST2400
++ * EC8. Remove #define CONFIG_DRAM_UART_OUT, default has message output to UART5
++ * EC9. Add DRAM size auto-detection
++ * EC10. Add GPIO register clear when watchdog reboot (only for AST2400)
++ * EC11. Move the "Solve ASPM" code position of AST2300 to avoid watchdog reset
++ *
++ * Modified list from v0.53
++ * EC1. Add solution of LPC lock issue due to watchdog reset. (AP note A2300-11)
++ *
++ * Modified list from v0.56
++ * EC1. Fix read DQS input mask window too late issue if DRAM's t_DQSCK is earlier too much
++ * (ex. Nanya NT5CB64M16FP)
++ * 1. Change init value of MCR18[4] from '1' to '0'
++ * 2. Add CBR4 code to finetune MCR18[4]
++ *
++ * Modified list from v0.59
++ * EC1. Add DQS input gating window delay tuning (1/2 T) when CBR retry
++ * EC2. Modify DLL1 MAdj = 0x4C
++ *
++ * Optional define variable
++ * 1. DRAM Speed //
++ * CONFIG_DRAM_336 // 336MHz (DDR-667)
++ * CONFIG_DRAM_408 // 408MHz (DDR-800) (default)
++ * 2. ECC Function enable
++ * CONFIG_DRAM_ECC // define to enable ECC function
++ * // when enabled, must define the ECC protected memory size at 0x1e6e0054
++ * 3. UART5 message output //
++ * CONFIG_DRAM_UART_38400 // set the UART baud rate to 38400, default is 115200
++ ******************************************************************************
++ */
++
++#include <config.h>
++#include <version.h>
++/******************************************************************************
++ Calibration Macro Start
++ Usable registers:
++ r0, r1, r2, r3, r5, r6, r7, r8, r9, r10, r11
++ ******************************************************************************/
++/* PATTERN_TABLE,
++ init_delay_timer,
++ check_delay_timer,
++ clear_delay_timer,
++ record_dll2_pass_range,
++ record_dll2_pass_range_h,
++ are for DRAM calibration */
++
++PATTERN_TABLE:
++ .word 0xff00ff00
++ .word 0xcc33cc33
++ .word 0xaa55aa55
++ .word 0x88778877
++ .word 0x92cc4d6e @ 5
++ .word 0x543d3cde
++ .word 0xf1e843c7
++ .word 0x7c61d253
++ .word 0x00000000 @ 8
++
++ .macro init_delay_timer
++ ldr r0, =0x1e782024 @ Set Timer3 Reload
++ str r2, [r0]
++
++ ldr r0, =0x1e6c0038 @ Clear Timer3 ISR
++ ldr r1, =0x00040000
++ str r1, [r0]
++
++ ldr r0, =0x1e782030 @ Enable Timer3
++ ldr r1, [r0]
++ mov r2, #7
++ orr r1, r1, r2, lsl #8
++ str r1, [r0]
++
++ ldr r0, =0x1e6c0090 @ Check ISR for Timer3 timeout
++ .endm
++
++ .macro check_delay_timer
++ ldr r1, [r0]
++ bic r1, r1, #0xFFFBFFFF
++ mov r2, r1, lsr #18
++ cmp r2, #0x01
++ .endm
++
++ .macro clear_delay_timer
++ ldr r0, =0x1e782030 @ Disable Timer3
++ ldr r1, [r0]
++ bic r1, r1, #0x00000F00
++ str r1, [r0]
++
++ ldr r0, =0x1e6c0038 @ Clear Timer3 ISR
++ ldr r1, =0x00040000
++ str r1, [r0]
++ .endm
++
++ .macro record_dll2_pass_range
++ ldr r1, [r0]
++ bic r2, r1, #0xFFFFFF00
++ cmp r2, r3 @ record min
++ bicgt r1, r1, #0x000000FF
++ orrgt r1, r1, r3
++ bic r2, r1, #0xFFFF00FF
++ cmp r3, r2, lsr #8 @ record max
++ bicgt r1, r1, #0x0000FF00
++ orrgt r1, r1, r3, lsl #8
++ str r1, [r0]
++ .endm
++
++ .macro record_dll2_pass_range_h
++ ldr r1, [r0]
++ bic r2, r1, #0xFF00FFFF
++ mov r2, r2, lsr #16
++ cmp r2, r3 @ record min
++ bicgt r1, r1, #0x00FF0000
++ orrgt r1, r1, r3, lsl #16
++ bic r2, r1, #0x00FFFFFF
++ cmp r3, r2, lsr #24 @ record max
++ bicgt r1, r1, #0xFF000000
++ orrgt r1, r1, r3, lsl #24
++ str r1, [r0]
++ .endm
++
++ .macro init_spi_checksum
++ ldr r0, =0x1e620084
++ ldr r1, =0x20010000
++ str r1, [r0]
++ ldr r0, =0x1e62008C
++ ldr r1, =0x20000200
++ str r1, [r0]
++ ldr r0, =0x1e620080
++ ldr r1, =0x0000000D
++ orr r2, r2, r7
++ orr r1, r1, r2, lsl #8
++ and r2, r6, #0xF
++ orr r1, r1, r2, lsl #4
++ str r1, [r0]
++ ldr r0, =0x1e620008
++ ldr r2, =0x00000800
++ .endm
++
++/******************************************************************************
++ Calibration Macro End
++ ******************************************************************************/
++LPC_Patch: @ load to SRAM base 0x1e720400
++ str r1, [r0]
++ str r3, [r2]
++ bic r1, r1, #0xFF
++LPC_Patch_S1:
++ subs r5, r5, #0x01
++ moveq pc, r8
++ ldr r3, [r2]
++ tst r3, #0x01
++ movne pc, r8
++ mov pc, r7
++LPC_Patch_S2: @ load to SRAM base 0x1e720480
++ str r1, [r0]
++ mov pc, r9
++LPC_Patch_E:
++
++.globl lowlevel_init
++lowlevel_init:
++
++init_dram:
++ /* save lr */
++ mov r4, lr
++/* Test - DRAM initial time */
++ ldr r0, =0x1e782044
++ ldr r1, =0xFFFFFFFF
++ str r1, [r0]
++
++ ldr r0, =0x1e782030
++ ldr r1, [r0]
++ bic r1, r1, #0x0000F000
++ str r1, [r0]
++ mov r2, #3
++ orr r1, r1, r2, lsl #12
++ str r1, [r0]
++/* Test - DRAM initial time */
++
++ /*Set Scratch register Bit 7 before initialize*/
++ ldr r0, =0x1e6e2000
++ ldr r1, =0x1688a8a8
++ str r1, [r0]
++
++ ldr r0, =0x1e6e2040
++ ldr r1, [r0]
++ orr r1, r1, #0x80
++ str r1, [r0]
++
++ /* Fix LPC lock issue for AST2300 */
++ ldr r0, =0x1e6e207c @ Check AST2300
++ ldr r1, [r0]
++ mov r1, r1, lsr #24
++ cmp r1, #0x01
++ bne lpc_recover_end @ not match AST2300
++
++ mov r3, #0x0
++lpc_recover_check:
++ ldr r0, =0x1e78900c @ check HICR3[4]=0x1
++ ldr r1, [r0]
++ tst r1, #0x10
++ beq lpc_recover_end
++ ldr r0, =0x1e789004 @ check HICR1[7]=0x1
++ ldr r1, [r0]
++ tst r1, #0x80
++ beq lpc_recover_end
++ ldr r0, =0x1e7890a0 @ check LHCR0[27:24]=0x6
++ ldr r1, [r0]
++ mov r1, r1, lsr #24
++ and r1, r1, #0xF
++ cmp r1, #0x06
++ bne lpc_recover_end
++ add r3, r3, #0x01
++ cmp r3, #0x5 @ repeat 5 times
++ ble lpc_recover_check
++
++ mov r3, #0x0
++lpc_recover_init:
++ ldr r0, =0x1e7890a4 @ set LHCR1[1:0]=0x0
++ ldr r1, =0x00000000
++ str r1, [r0]
++ add r3, r3, #0x01
++ cmp r3, #0x20
++ bge lpc_recover_end
++ ldr r1, [r0]
++ tst r1, #0x01
++ bne lpc_recover_init
++
++ ldr r0, =0x1e7890b0 @ set LHCR4[7:0]=0xFF
++ ldr r1, =0x000000FF
++ str r1, [r0]
++ ldr r0, =0x1e7890b4 @ set LHCR5[31:0]=0xFFFFFFFF
++ ldr r1, =0xFFFFFFFF
++ str r1, [r0]
++ ldr r0, =0x1e7890b8 @ set LHCR6[31:0]=0xFFFFFFFF
++ str r1, [r0]
++
++ adr r6, LPC_Patch
++ adr r7, LPC_Patch_S2
++ ldr r0, =0x1e720400
++copy_lpc_patch_1:
++ ldr r1, [r6]
++ str r1, [r0]
++ add r6, r6, #0x4
++ add r0, r0, #0x4
++ cmp r6, r7
++ bne copy_lpc_patch_1
++
++ adr r6, LPC_Patch_S2
++ adr r7, LPC_Patch_E
++ ldr r0, =0x1e720480
++copy_lpc_patch_2:
++ ldr r1, [r6]
++ str r1, [r0]
++ add r6, r6, #0x4
++ add r0, r0, #0x4
++ cmp r6, r7
++ bne copy_lpc_patch_2
++
++ ldr r0, =0x1e7890a0 @ set LHCR0[31:0]=0xFFFFFF01
++ ldr r1, =0xFFFFFF01
++ add r2, r0, #0x4
++ mov r3, #0x01
++ mov r5, #0x10
++ adr r9, lpc_recover_end
++ adr r6, LPC_Patch
++ adr r7, LPC_Patch_S1
++ sub r6, r7, r6
++ ldr r7, =0x1e720400
++ add r7, r7, r6
++ ldr r8, =0x1e720480
++ ldr pc, =0x1e720400
++
++lpc_recover_end:
++ ldr r0, =0x1e7890a0 @ set LHCR0[31:0]=0xFFFFFF00
++ ldr r1, =0xFFFFFF00
++ str r1, [r0]
++ /* <END> Fix LPC lock issue for AST2300 */
++
++ /* Check Scratch Register Bit 6 */
++ ldr r0, =0x1e6e2040
++ ldr r1, [r0]
++ bic r1, r1, #0xFFFFFFBF
++ mov r2, r1, lsr #6
++ cmp r2, #0x01
++ beq platform_exit
++
++ ldr r2, =0x033103F1 @ load PLL parameter for 24Mhz CLKIN (396:324)
++/* ldr r2, =0x019001F0 @ load PLL parameter for 24Mhz CLKIN (408:336) */
++ ldr r0, =0x1e6e207c @ Check Revision ID
++ ldr r1, [r0]
++ mov r1, r1, lsr #24
++ cmp r1, #0x02
++ bne set_MPLL @ not match AST2400
++
++ ldr r0, =0x1e6e2070 @ Check CLKIN freq
++ ldr r1, [r0]
++ mov r1, r1, lsr #23
++ tst r1, #0x01
++ ldrne r2, =0x017001D0 @ load PLL parameter for 25Mhz CLKIN (400:325)
++
++set_MPLL:
++ ldr r0, =0x1e6e2020 @ M-PLL (DDR SDRAM) Frequency
++ ldr r1, =0xFFFF
++#if defined(CONFIG_DRAM_336)
++ mov r2, r2, lsr #16
++#endif
++ and r1, r2, r1
++ str r1, [r0]
++
++/* Debug - UART console message */
++ ldr r0, =0x1e78400c
++ mov r1, #0x83
++ str r1, [r0]
++
++ ldr r0, =0x1e6e202c
++ ldr r2, [r0]
++ mov r2, r2, lsr #12
++ tst r2, #0x01
++ ldr r0, =0x1e784000
++ moveq r1, #0x0D @ Baudrate 115200
++ movne r1, #0x01 @ Baudrate 115200, div13
++#if defined(CONFIG_DRAM_UART_38400)
++ moveq r1, #0x27 @ Baudrate 38400
++ movne r1, #0x03 @ Baudrate 38400 , div13
++#endif
++ str r1, [r0]
++
++ ldr r0, =0x1e784004
++ mov r1, #0x00
++ str r1, [r0]
++
++ ldr r0, =0x1e78400c
++ mov r1, #0x03
++ str r1, [r0]
++
++ ldr r0, =0x1e784008
++ mov r1, #0x07
++ str r1, [r0]
++
++ ldr r0, =0x1e784000
++ mov r1, #0x0D @ '\r'
++ str r1, [r0]
++ mov r1, #0x0A @ '\n'
++ str r1, [r0]
++ mov r1, #0x44 @ 'D'
++ str r1, [r0]
++ mov r1, #0x52 @ 'R'
++ str r1, [r0]
++ mov r1, #0x41 @ 'A'
++ str r1, [r0]
++ mov r1, #0x4D @ 'M'
++ str r1, [r0]
++ mov r1, #0x20 @ ' '
++ str r1, [r0]
++ mov r1, #0x49 @ 'I'
++ str r1, [r0]
++ mov r1, #0x6E @ 'n'
++ str r1, [r0]
++ mov r1, #0x69 @ 'i'
++ str r1, [r0]
++ mov r1, #0x74 @ 't'
++ str r1, [r0]
++ mov r1, #0x2D @ '-'
++ str r1, [r0]
++ mov r1, #0x44 @ 'D'
++ str r1, [r0]
++ mov r1, #0x44 @ 'D'
++ str r1, [r0]
++ mov r1, #0x52 @ 'R'
++ str r1, [r0]
++/* Debug - UART console message */
++
++ /* Delay about 100us */
++ ldr r0, =0x1e782030 @ Init Timer3 Control
++ ldr r1, [r0]
++ bic r1, r1, #0x00000F00
++ str r1, [r0]
++
++ ldr r2, =0x00000064 @ Set Timer3 Reload = 100 us
++ init_delay_timer
++delay_0:
++ check_delay_timer
++ bne delay_0
++ clear_delay_timer
++ /* end delay 100us */
++
++/******************************************************************************
++ Init DRAM common registers
++ ******************************************************************************/
++ ldr r0, =0x1e6e0000
++ ldr r1, =0xfc600309
++ str r1, [r0]
++
++ /* Reset MMC */
++ ldr r1, =0x00000000
++ ldr r0, =0x1e6e0034
++ str r1, [r0]
++ ldr r0, =0x1e6e0018
++ str r1, [r0]
++ ldr r0, =0x1e6e0024
++ str r1, [r0]
++ ldr r0, =0x1e6e0064 @ REG_MADJ, power down DLL
++ str r1, [r0]
++
++ ldr r1, =0x00034C4C @ REG_MADJ, reset DLL
++ str r1, [r0]
++
++ ldr r0, =0x1e6e0068 @ REG_SADJ
++ ldr r1, =0x00001800
++ str r1, [r0]
++
++ /* Delay about 10us */
++ ldr r2, =0x0000000B @ Set Timer3 Reload = 10 us
++ init_delay_timer
++delay_1:
++ check_delay_timer
++ bne delay_1
++ clear_delay_timer
++ /* end delay 10us */
++
++ ldr r0, =0x1e6e0064 @ REG_MADJ | 0xC0000, enable DLL
++ ldr r1, [r0]
++ ldr r2, =0xC0000
++ orr r1, r1, r2
++ str r1, [r0]
++
++ ldr r0, =0x1e6e0008
++ ldr r1, =0x0090040f /* VGA */
++ str r1, [r0]
++
++ ldr r0, =0x1e6e0018
++ ldr r1, =0x4000A120
++ str r1, [r0]
++
++ ldr r0, =0x1e6e0018
++ ldr r1, =0x00000120
++ str r1, [r0]
++
++ ldr r0, =0x1e6e0038
++ ldr r1, =0x00000000
++ str r1, [r0]
++
++ ldr r0, =0x1e6e0040
++ ldr r1, =0xFF444444
++ str r1, [r0]
++
++ ldr r0, =0x1e6e0044
++ ldr r1, =0x22222222
++ str r1, [r0]
++
++ ldr r0, =0x1e6e0048
++ ldr r1, =0x22222222
++ str r1, [r0]
++
++ ldr r0, =0x1e6e004c
++ ldr r1, =0x22222222
++ str r1, [r0]
++
++ ldr r0, =0x1e6e0050
++ ldr r1, =0x80000000
++ str r1, [r0]
++
++ ldr r0, =0x1e6e0050
++ ldr r1, =0x00000000
++ str r1, [r0]
++
++ ldr r0, =0x1e6e0054
++ ldr r1, =0x00000000
++ str r1, [r0]
++
++ ldr r0, =0x1e6e0060 @ REG_DRV
++ ldr r1, =0x000000FA @ 408 MHz
++#if defined(CONFIG_DRAM_336)
++ ldr r1, =0x000000FA
++#endif
++ str r1, [r0]
++
++ ldr r0, =0x1e6e0070
++ ldr r1, =0x00000000
++ str r1, [r0]
++
++ ldr r0, =0x1e6e0074
++ ldr r1, =0x00000000
++ str r1, [r0]
++
++ ldr r0, =0x1e6e0078
++ ldr r1, =0x00000000
++ str r1, [r0]
++
++ ldr r0, =0x1e6e007c
++ ldr r1, =0x00000000
++ str r1, [r0]
++
++ ldr r0, =0x1e6e0080
++ ldr r1, =0x00000000
++ str r1, [r0]
++
++ ldr r0, =0x1e6e0084
++ ldr r1, =0x00FFFFFF
++ str r1, [r0]
++
++ ldr r0, =0x1e6e0088 @ REG_DQIDLY
++ ldr r1, =0x00000089 @ 408 MHz
++#if defined(CONFIG_DRAM_336)
++ ldr r1, =0x00000074
++#endif
++ str r1, [r0]
++
++ ldr r0, =0x1e6e0020 @ REG_DQSIC
++ ldr r1, =0x000000E2 @ 408 MHz
++#if defined(CONFIG_DRAM_336)
++ ldr r1, =0x000000BA
++#endif
++ str r1, [r0]
++
++ /* Delay about 10us */
++ ldr r2, =0x0000000B @ Set Timer3 Reload = 10 us
++ init_delay_timer
++delay_2:
++ check_delay_timer
++ bne delay_2
++ clear_delay_timer
++ /* end delay 10us */
++
++ /* Check DRAM Type by H/W Trapping */
++ ldr r0, =0x1e6e2070
++ ldr r1, [r0]
++ bic r1, r1, #0xFEFFFFFF @ bit[24]=1 => DDR2
++ mov r2, r1, lsr #24
++ cmp r2, #0x01
++ beq ddr2_init
++ b ddr3_init
++.LTORG
++
++/******************************************************************************
++ DDR3 Init
++
++ tRCD = 15 ns
++ tRAS = 37.5 ns
++ tRRD = max(4 CK,10 ns)
++ tRP = 15 ns
++ tRFC = 110ns/1Gbit, 160ns/2Gbit, 300ns/4Gbit
++ tRTP = max(4 CK,7.5 ns)
++ tWR = 15 ns
++ tXSNR = max(10 CK,200 ns)
++ tWTR = max(4 CK,7.5 ns)
++ tFAW = 50 ns
++ tMRD = max(15 CK,20 ns)
++ ******************************************************************************/
++ddr3_init:
++/* Debug - UART console message */
++ ldr r0, =0x1e784000
++ mov r1, #0x33 @ '3'
++ str r1, [r0]
++ mov r1, #0x0D @ '\r'
++ str r1, [r0]
++ mov r1, #0x0A @ '\n'
++ str r1, [r0]
++/* Debug - UART console message */
++
++ ldr r0, =0x1e6e0004
++ ldr r1, =0x00000531 @ Default set to 1Gbit
++ str r1, [r0]
++
++ ldr r0, =0x1e6e0010 @ REG_AC1
++ ldr r1, =0x33302825 @ 408 MHz
++#if defined(CONFIG_DRAM_336)
++ ldr r1, =0x22202725
++#endif
++ str r1, [r0]
++
++ /* Check DRAM CL Timing by H/W Trapping */
++ ldr r0, =0x1e6e2070
++ ldr r1, [r0]
++ bic r1, r1, #0xF9FFFFFF
++ mov r2, r1, lsr #9 @ Set CL
++ ldr r1, =0x00020000
++ add r2, r2, r1
++ ldr r1, [r0]
++ bic r1, r1, #0xFBFFFFFF
++ mov r1, r1, lsr #6 @ Set CWL
++ orr r2, r2, r1
++ ldr r1, =0x00300000
++ add r2, r2, r1
++
++ ldr r0, =0x1e6e0014 @ REG_AC2
++ ldr r1, =0xCC00963F @ 408 MHz
++#if defined(CONFIG_DRAM_336)
++ ldr r1, =0xAA007636
++#endif
++ orr r1, r1, r2
++ str r1, [r0]
++
++ ldr r0, =0x1e6e0004 @ check 2400 mode
++ ldr r2, [r0]
++ mov r2, r2, lsr #10
++
++ ldr r0, =0x1e6e006c @ REG_IOZ
++ ldr r1, =0x00002312 @ 408 MHz
++#if defined(CONFIG_DRAM_336)
++ ldr r1, =0x00002312
++#endif
++ tst r2, #0x01
++ moveq r1, r1, lsr #8
++ str r1, [r0]
++
++ ldr r0, =0x1e6e0120
++ mov r1, #0
++ str r1, [r0]
++ tst r2, #0x01 @ check AST2300
++ beq CBRDLL1_2300_Start
++ ldr r0, =0x1e6e207c @ check AST2400 revision A0
++ ldr r1, [r0]
++ mov r1, r1, lsr #16
++ and r1, r1, #0xFF
++ cmp r1, #0x0
++ beq CBRDLL1_2300_Start
++ b CBRDLL1_2400_Start
++MCLK2X_Phase_CBR_Done_DDR3:
++ ldr r0, =0x1e6e0018
++ ldr r1, [r0]
++ orr r1, r1, #0x40
++ str r1, [r0]
++
++ ldr r0, =0x1e6e0034
++ ldr r1, =0x00000001
++ str r1, [r0]
++
++ ldr r0, =0x1e6e000c
++ ldr r1, =0x00000040
++ str r1, [r0]
++
++ /* Delay about 400us */
++ ldr r2, =0x00000190 @ Set Timer3 Reload = 400 us
++ init_delay_timer
++delay3_4:
++ check_delay_timer
++ bne delay3_4
++ clear_delay_timer
++ /* end delay 400us */
++
++ /* Check DRAM CL Timing by H/W Trapping */
++ ldr r0, =0x1e6e2070
++ ldr r1, [r0]
++ bic r1, r1, #0xF9FFFFFF
++ mov r2, r1, lsr #21 @ Set CL
++ ldr r1, =0x00000010
++ add r2, r2, r1
++ ldr r1, [r0]
++ bic r1, r1, #0xFBFFFFFF
++ mov r1, r1, lsr #7 @ Set CWL
++ orr r2, r2, r1
++
++ ldr r0, =0x1e6e002c @ REG_MRS
++ ldr r1, =0x04001700 @ 408 MHz
++#if defined(CONFIG_DRAM_336)
++ ldr r1, =0x04001500
++#endif
++ orr r1, r1, r2
++ str r1, [r0]
++
++ ldr r0, =0x1e6e0030 @ REG_EMRS
++ ldr r1, =0x00000000 @ 408 MHz
++#if defined(CONFIG_DRAM_336)
++ ldr r1, =0x00000000
++#endif
++ str r1, [r0]
++
++ ldr r0, =0x1e6e0028 @ Set EMRS2
++ ldr r1, =0x00000005
++ str r1, [r0]
++
++ ldr r0, =0x1e6e0028 @ Set EMRS3
++ ldr r1, =0x00000007
++ str r1, [r0]
++
++ ldr r0, =0x1e6e0028 @ Set EMRS
++ ldr r1, =0x00000003
++ str r1, [r0]
++
++ ldr r0, =0x1e6e0028 @ Set MRS
++ ldr r1, =0x00000001
++ str r1, [r0]
++
++ ldr r0, =0x1e6e002c @ REG_MRS
++ ldr r1, =0x04001600 @ 408 MHz
++#if defined(CONFIG_DRAM_336)
++ ldr r1, =0x04001400
++#endif
++ orr r1, r1, r2
++ str r1, [r0]
++
++ ldr r0, =0x1e6e000c @ Refresh 8 times
++ ldr r1, =0x00005C48
++ str r1, [r0]
++
++ ldr r0, =0x1e6e0028 @ Set MRS
++ ldr r1, =0x00000001
++ str r1, [r0]
++
++ ldr r0, =0x1e6e000c @ Set refresh cycle
++ ldr r1, =0x00002001
++ str r1, [r0]
++
++ ldr r0, =0x1e6e0014
++ ldr r1, [r0]
++ bic r1, r1, #0xFFF9FFFF
++ mov r2, r1, lsr #3 @ get CL
++
++ ldr r0, =0x1e6e0034 @ REG_PWC
++ ldr r1, =0x00000303 @ 408 MHz
++#if defined(CONFIG_DRAM_336)
++ ldr r1, =0x00000303
++#endif
++ orr r1, r1, r2
++ str r1, [r0]
++
++ b Calibration_Start
++.LTORG
++/******************************************************************************
++ End DDR3 Init
++ ******************************************************************************/
++
++/******************************************************************************
++ DDR2 Init
++
++ tRCD = 15 ns
++ tRAS = 45 ns
++ tRRD = 10 ns
++ tRP = 15 ns
++ tRFC = 105ns/512Mbit, 127.5ns/1Gbit, 197.5ns/2Gbit, 327.5ns/4Gbit
++ tRTP = 7.5 ns
++ tWR = 15 ns
++ tXSNR = 200 ns
++ tWTR = 7.5 ns
++ tFAW = 50 ns
++ tMRD = 4 CK
++ ******************************************************************************/
++ddr2_init:
++/* Debug - UART console message */
++ ldr r0, =0x1e784000
++ mov r1, #0x32 @ '2'
++ str r1, [r0]
++ mov r1, #0x0D @ '\r'
++ str r1, [r0]
++ mov r1, #0x0A @ '\n'
++ str r1, [r0]
++/* Debug - UART console message */
++
++ ldr r0, =0x1e6e0004
++ ldr r1, =0x00000510 @ Default set to 512Mbit
++ str r1, [r0]
++
++ ldr r0, =0x1e6e0010 @ REG_AC1
++ ldr r1, =0x33302714 @ 408 MHz
++#if defined(CONFIG_DRAM_336)
++ ldr r1, =0x22201613
++#endif
++ str r1, [r0]
++
++ /* Check DRAM CL Timing by H/W Trapping */
++ ldr r0, =0x1e6e2070
++ ldr r1, [r0]
++ bic r1, r1, #0xF9FFFFFF
++ mov r2, r1, lsr #5 @ Set CL
++ mov r1, r2, lsr #4 @ Set CWL
++ orr r2, r2, r1
++ ldr r1, =0x00110000
++ add r2, r2, r1
++
++ ldr r0, =0x1e6e0014 @ REG_AC2
++ ldr r1, =0xCC00B03F @ 408 MHz
++#if defined(CONFIG_DRAM_336)
++ ldr r1, =0xAA00903B
++#endif
++ orr r1, r1, r2
++ str r1, [r0]
++
++ ldr r0, =0x1e6e0004 @ check 2400 mode
++ ldr r2, [r0]
++ mov r2, r2, lsr #10
++
++ ldr r0, =0x1e6e006c @ REG_IOZ
++ ldr r1, =0x00002312 @ 408 MHz
++#if defined(CONFIG_DRAM_336)
++ ldr r1, =0x00002312
++#endif
++ tst r2, #0x01
++ moveq r1, r1, lsr #8
++ str r1, [r0]
++
++ ldr r0, =0x1e6e0120
++ mov r1, #1
++ str r1, [r0]
++ tst r2, #0x01 @ check AST2300
++ beq CBRDLL1_2300_Start
++ ldr r0, =0x1e6e207c @ check AST2400 revision A0
++ ldr r1, [r0]
++ mov r1, r1, lsr #16
++ and r1, r1, #0xFF
++ cmp r1, #0x0
++ beq CBRDLL1_2300_Start
++ b CBRDLL1_2400_Start
++MCLK2X_Phase_CBR_Done_DDR2:
++
++ ldr r0, =0x1e6e0034
++ ldr r1, =0x00000001
++ str r1, [r0]
++
++ ldr r0, =0x1e6e000c
++ ldr r1, =0x00000000
++ str r1, [r0]
++
++ /* Delay about 400us */
++ ldr r2, =0x00000190 @ Set Timer3 Reload = 400 us
++ init_delay_timer
++delay2_4:
++ check_delay_timer
++ bne delay2_4
++ clear_delay_timer
++ /* end delay 400us */
++
++ /* Check DRAM CL Timing by H/W Trapping */
++ ldr r0, =0x1e6e2070
++ ldr r1, [r0]
++ bic r1, r1, #0xF9FFFFFF
++ mov r2, r1, lsr #21 @ Set CL
++ ldr r1, =0x00000040
++ orr r2, r2, r1
++
++ ldr r0, =0x1e6e002c @ REG_MRS
++ ldr r1, =0x00000D03 @ 408 MHz
++#if defined(CONFIG_DRAM_336)
++ ldr r1, =0x00000B03
++#endif
++ orr r1, r1, r2
++ str r1, [r0]
++
++ ldr r0, =0x1e6e0030 @ REG_EMRS
++ ldr r1, =0x00000040 @ 408 MHz
++#if defined(CONFIG_DRAM_336)
++ ldr r1, =0x00000040
++#endif
++ str r1, [r0]
++
++ ldr r0, =0x1e6e0028 @ Set EMRS2
++ ldr r1, =0x00000005
++ str r1, [r0]
++
++ ldr r0, =0x1e6e0028 @ Set EMRS3
++ ldr r1, =0x00000007
++ str r1, [r0]
++
++ ldr r0, =0x1e6e0028 @ Set EMRS
++ ldr r1, =0x00000003
++ str r1, [r0]
++
++ ldr r0, =0x1e6e0028 @ Set MRS
++ ldr r1, =0x00000001
++ str r1, [r0]
++
++ ldr r0, =0x1e6e000c @ Refresh 8 times
++ ldr r1, =0x00005C08
++ str r1, [r0]
++
++ ldr r0, =0x1e6e002c @ REG_MRS
++ ldr r1, =0x00000C03 @ 408 MHz
++#if defined(CONFIG_DRAM_336)
++ ldr r1, =0x00000A03
++#endif
++ orr r1, r1, r2
++ str r1, [r0]
++
++ ldr r0, =0x1e6e0028 @ Set MRS
++ ldr r1, =0x00000001
++ str r1, [r0]
++
++ ldr r0, =0x1e6e0030 @ REG_EMRS
++ ldr r1, =0x000003C0 @ 408 MHz
++#if defined(CONFIG_DRAM_336)
++ ldr r1, =0x000003C0
++#endif
++ str r1, [r0]
++
++ ldr r0, =0x1e6e0028 @ Set EMRS
++ ldr r1, =0x00000003
++ str r1, [r0]
++
++ ldr r0, =0x1e6e0030 @ REG_EMRS
++ ldr r1, =0x00000040 @ 408 MHz
++#if defined(CONFIG_DRAM_336)
++ ldr r1, =0x00000040
++#endif
++ str r1, [r0]
++
++ ldr r0, =0x1e6e0028 @ Set EMRS
++ ldr r1, =0x00000003
++ str r1, [r0]
++
++ ldr r0, =0x1e6e000c @ Set refresh cycle
++ ldr r1, =0x00002001
++ str r1, [r0]
++
++ ldr r0, =0x1e6e0014
++ ldr r1, [r0]
++ bic r1, r1, #0xFFF9FFFF
++ mov r2, r1, lsr #3 @ get CL
++
++ ldr r0, =0x1e6e0034 @ REG_PWC
++ ldr r1, =0x00000503 @ 408 MHz
++#if defined(CONFIG_DRAM_336)
++ ldr r1, =0x00000503
++#endif
++ orr r1, r1, r2
++ str r1, [r0]
++
++ b Calibration_Start
++.LTORG
++/******************************************************************************
++ End DDR2 Init
++ ******************************************************************************/
++/******************************************************************************
++ DDR CK duty finetune program
++ SRAM buffer definition
++ 0x1E720204 : gdll golden DLL1 record
++ 0x1E720208 : gduty golden duty setting record
++ 0x1E72020C : gdutysum golden duty data record
++ 0x1E720210 : duty record of delay 0 invert
++ 0x1E720214 : duty record of delay 1 invert
++ ....
++ 0x1E72024C : duty record of delay 15 invert
++ 0x1E720250 : duty record of delay 0
++ 0x1E720254 : duty record of delay 1
++ ....
++ 0x1E72028C : duty record of delay 15
++
++ Register usage
++ r0 - r3 = free
++ r4 = record the return pc value, do not use
++ r5 = free
++ r6 = free
++ r7 = duty count
++ r8 = gdll
++ r9 = gduty
++ r10 = gdutysum
++ ******************************************************************************/
++CBRDLL1_2400_Start:
++ ldr r0, =0x1e6e0120
++ ldr r1, [r0]
++ orr r1, r1, #0x02
++ str r1, [r0]
++
++ ldr r1, =0x00000000
++ ldr r0, =0x1e720204
++ ldr r2, =0x1e7202a0
++init_sram_start0:
++ str r1, [r0]
++ add r0, r0, #4
++ cmp r0, r2
++ blt init_sram_start0
++
++ ldr r0, =0x1e6e0034
++ mov r1, #0x20
++ str r1, [r0]
++
++ ldr r0, =0x1e6e0060
++ ldr r1, [r0]
++ mov r2, #0x01
++ orr r1, r1, r2, lsl #13
++ str r1, [r0]
++
++ mov r7, #0x0 @ init duty count
++ mov r8, #0x0 @ init gdll
++ mov r9, #0x0 @ init gduty
++ mov r10, #0x0 @ init gdutysum
++cbrdll1_duty_start:
++ cmp r7, #32
++ bge cbrdll1_duty_end
++
++ ldr r0, =0x1e6e0018
++ ldr r1, =0x00008120
++ str r1, [r0]
++
++ ldr r0, =0x1e6e0060
++ ldr r1, [r0]
++ bic r1, r1, #0x00001F00
++ orr r1, r1, r7, lsl #8
++ mov r2, #0x10
++ eor r1, r1, r2, lsl #8
++ str r1, [r0]
++
++ ldr r0, =0x1e6e0000 @ dummy read
++ ldr r1, [r0]
++
++ b CBRDLL1_2300_Start
++CBRDLL1_2400_Call:
++
++ mov r5, #0x01 @ init dqidly count
++ mov r6, #0x00 @ init duty sum
++cbrdll1_duty_cal_start:
++ cmp r5, #0x05
++ bge cbrdll1_duty_cal_end
++
++ ldr r0, =0x1e6e0018
++ ldr r1, =0x00200120
++ orr r1, r1, r5, lsl #16
++ str r1, [r0]
++
++ ldr r0, =0x1e6e0000
++ ldr r1, [r0]
++
++ ldr r0, =0x1e6e0018
++ ldr r1, [r0]
++ mov r2, #0x10
++ orr r1, r1, r2, lsl #24
++ str r1, [r0]
++
++ ldr r0, =0x1e6e0080
++ ldr r1, =0x80000000 @ init duty cal waiting
++cbrdll1_duty_cal_wait:
++ ldr r2, [r0]
++ tst r2, r1
++ beq cbrdll1_duty_cal_wait
++
++ ldr r0, =0x1e6e008c
++ ldr r2, [r0]
++
++ ldr r0, =0x1e720210
++ add r0, r0, r7, lsl #2
++ str r2, [r0]
++
++ ldr r1, =0xFFFF
++ and r3, r1, r2
++ cmp r3, r1
++ moveq r2, r2, lsr #16
++ and r3, r1, r2
++ add r6, r6, r3
++ ldr r1, =0xF000
++ cmp r3, r1
++ blt cbrdll1_duty_cal_end
++ add r5, r5, #0x01
++ b cbrdll1_duty_cal_start
++
++cbrdll1_duty_cal_end:
++ mov r6, r6, lsr #2 @ get dutysum
++ cmp r6, r10 @ check dutysum > gdutysum
++ ble cbrdll1_duty_next
++ ldr r0, =0x1e6e0068
++ ldr r8, [r0]
++ eor r9, r7, #0x10
++ mov r10, r6
++
++cbrdll1_duty_next:
++ add r7, r7, #0x01
++ cmp r7, #16 @ check duty >= 15
++ blt cbrdll1_duty_start
++ ldr r0, =0xFA00 @ check gdutysum > 0xFA00
++ cmp r10, r0
++ blt cbrdll1_duty_start
++
++cbrdll1_duty_end:
++ ldr r0, =0x1e6e0060
++ ldr r1, [r0]
++ bic r1, r1, #0x00001F00
++ orr r1, r1, r9, lsl #8
++ str r1, [r0]
++
++ ldr r0, =0x1e6e0068
++ bic r8, r8, #0xFF000000
++ bic r8, r8, #0x00FF0000
++ str r8, [r0]
++
++ ldr r0, =0x1e720204 @ record result
++ str r8, [r0]
++ add r0, r0, #0x04
++ str r9, [r0]
++ add r0, r0, #0x04
++ str r10, [r0]
++
++ ldr r0, =0x1e6e0018
++ ldr r1, =0x00008120
++ str r1, [r0]
++ ldr r0, =0x1e6e0000 @ dummy read
++ ldr r1, [r0]
++ ldr r0, =0x1e6e0018
++ ldr r1, =0x00000120
++ str r1, [r0]
++
++ ldr r0, =0x1e6e0120
++ ldr r1, [r0]
++ cmp r1, #0x3
++ beq MCLK2X_Phase_CBR_Done_DDR2
++ b MCLK2X_Phase_CBR_Done_DDR3
++
++/******************************************************************************
++ MCLK2X lock to MCLK program
++ r0 - r3 = free
++ r5 = madjmax
++ r6 = dllend
++ 0x1E720200 = 0x96cnt:failcnt:dllmax:dllmin
++ ******************************************************************************/
++CBRDLL1_2300_Start:
++ ldr r0, =0x1e6e0064
++ ldr r5, [r0]
++ and r5, r5, #0xFF @ init madjmax
++ mov r6, r5 @ init dllend
++
++ ldr r1, =0x000000ff
++ ldr r0, =0x1e720200
++ str r1, [r0] @ init dllcnt2:dllmax:dllmin
++
++ mov r3, #0x0 @ init loop count
++cbrdll1_scan_start:
++ cmp r3, r6
++ bge cbrdll1_scan_end
++
++ ldr r0, =0x1e6e0018
++ ldr r1, =0x00008120
++ str r1, [r0]
++
++ ldr r0, =0x1e6e0068
++ mov r1, r3
++ cmp r1, r5
++ subge r1, r1, r5
++ str r1, [r0]
++
++ ldr r0, =0x1e6e0000 @ dummy read
++ ldr r1, [r0]
++
++ ldr r0, =0x1e6e0018
++ ldr r1, =0x00000120
++ str r1, [r0]
++
++ ldr r0, =0x1e6e0000 @ dummy read
++ ldr r1, [r0]
++ ldr r0, =0x1e6e0000 @ dummy read
++ ldr r1, [r0]
++
++ ldr r0, =0x1e6e001c
++ ldr r1, [r0]
++ mov r1, r1, lsr #16
++ and r1, r1, #0xFF
++
++ and r2, r1, #0x96
++ cmp r2, #0x96
++ beq cbrdll1_scan_pass @ if (mclk2x_phase & 0x96) == 0x96
++ ldr r0, =0x1e720200
++ ldr r1, [r0]
++ mov r2, r1, lsr #8
++ ands r2, r2, #0xFF @ get dllmax
++ beq cbrdll1_scan_next @ if dllmax == 0
++ mov r2, r1, lsr #16
++ and r2, r2, #0xFF
++ add r2, r2, #0x01
++ cmp r2, #0x02
++ movge r6, r3
++ bic r1, r1, #0x00FF0000
++ orr r1, r1, r2, lsl #16
++ str r1, [r0]
++ b cbrdll1_scan_next
++
++cbrdll1_scan_pass:
++ cmp r3, #0x0 @ if dll = 0
++ moveq r3, #0x0F
++ addeq r6, r6, #0x10
++ beq cbrdll1_scan_next
++ ldr r0, =0x1e720200
++ ldr r2, [r0]
++ cmp r1, #0x96
++ bne cbrdll1_scan_pass2
++ mov r1, r2, lsr #24
++ add r1, r1, #0x01
++ bic r2, r2, #0xFF000000
++ orr r2, r2, r1, lsl #24
++ cmp r1, #0x03 @ check (phase == 0x96) count == 3
++ bicge r2, r2, #0x0000FF00
++ bicge r2, r2, #0x000000FF
++ orrge r2, r2, r3, lsl #8
++ orrge r2, r2, r3
++ str r2, [r0]
++ bge cbrdll1_scan_end
++
++cbrdll1_scan_pass2:
++ and r1, r2, #0xFF @ if(dllmin > dll)
++ cmp r1, r3
++ bicgt r2, r2, #0x000000FF
++ orrgt r2, r2, r3
++
++ mov r1, r2, lsr #8 @ if(dllmax < dll)
++ and r1, r1, #0xFF
++ cmp r1, r3
++ biclt r2, r2, #0x0000FF00
++ orrlt r2, r2, r3, lsl #8
++
++ bic r2, r2, #0x00FF0000
++ str r2, [r0]
++
++cbrdll1_scan_next:
++ add r3, r3, #0x01
++ b cbrdll1_scan_start
++
++cbrdll1_scan_end:
++ ldr r0, =0x1e720200
++ ldr r1, [r0]
++ mov r2, r1, lsr #8 @ get dllmax
++ ands r2, r2, #0xFF
++ bne cbrdll1_scan_done @ if(dllmax != 0)
++ ldr r0, =0x1e6e0064
++ ldr r3, [r0]
++ bic r1, r3, #0x000C0000
++ str r1, [r0]
++ add r0, r0, #0x04
++ mov r1, #0x0
++ str r1, [r0]
++
++ /* Delay about 10us */
++ ldr r2, =0x0000000A @ Set Timer3 Reload = 10 us
++ init_delay_timer
++delay0_1:
++ check_delay_timer
++ bne delay0_1
++ clear_delay_timer
++ /* end delay 10us */
++
++ ldr r0, =0x1e6e0064
++ str r3, [r0]
++
++ /* Delay about 10us */
++ ldr r2, =0x0000000A @ Set Timer3 Reload = 10 us
++ init_delay_timer
++delay0_2:
++ check_delay_timer
++ bne delay0_2
++ clear_delay_timer
++ /* end delay 10us */
++
++ b CBRDLL1_2300_Start
++
++cbrdll1_scan_done:
++ and r1, r1, #0xFF
++ add r1, r1, r2
++ mov r6, r1, lsr #1 @ dll1.0 = (dllmin + dllmax) >> 1
++ cmp r6, r5
++ subge r6, r6, r5
++ add r3, r6, r5, lsr #2 @ dll1.1 = dll1.0 + (MADJ >> 2)
++
++ ldr r0, =0x1e6e0004
++ ldr r1, [r0]
++ mov r1, r1, lsr #10
++ tst r1, #0x1
++ bne cbrdll1_scan_set_2400
++ cmp r3, r5
++ subge r3, r3, r5
++ mov r2, #0x0
++ tst r3, #0x08
++ beq cbrdll1_scan_set_2300_2 @ if !(dll & 8)
++cbrdll1_scan_set_2300_1: @ if (dll & 8)
++ mov r1, #0x0
++ tst r3, #0x08
++ addeq r1, r1, #0x01
++ cmp r2, #0x05
++ addge r1, r1, #0x01
++ cmp r1, #0x02
++ beq cbrdll1_scan_set
++ add r2, r2, #0x01
++ add r3, r3, #0x01
++ cmp r3, r5
++ subge r3, r3, r5
++ b cbrdll1_scan_set_2300_1
++
++cbrdll1_scan_set_2300_2:
++ and r1, r3, #0x07
++ cmp r1, #0x07
++ beq cbrdll1_scan_set
++ cmp r2, #0x05
++ bge cbrdll1_scan_set
++ add r2, r2, #0x01
++ add r3, r3, #0x01
++ cmp r3, r5
++ subge r3, r3, r5
++ b cbrdll1_scan_set_2300_2
++
++cbrdll1_scan_set_2400:
++ add r3, r3, #0x05 @ dll1.1 = dll1.0 + (MADJ >> 2) + 5
++ cmp r3, r5
++ subge r3, r3, r5
++
++cbrdll1_scan_set:
++ orr r1, r6, r3, lsl #8
++ ldr r0, =0x1e6e0068
++ str r1, [r0]
++
++ ldr r0, =0x1e6e0120
++ ldr r1, [r0]
++ cmp r1, #0x0
++ beq MCLK2X_Phase_CBR_Done_DDR3
++ cmp r1, #0x1
++ beq MCLK2X_Phase_CBR_Done_DDR2
++ b CBRDLL1_2400_Call
++
++.LTORG
++
++/******************************************************************************
++ Calibration Code Start
++ SRAM buffer definition
++ 0x1E720000 : Pass 1, DLLI MIN value range
++ 0x1E720008 : DQS0 DLL valid range, 2nd time CBR
++ 0x1E72000C : DQS1 DLL valid range, 2nd time CBR
++ 0x1E720010 : DQ0 DLL valid range, Pass 1
++ 0x1E720014 : DQ1 DLL valid range, Pass 1
++ ....
++ 0x1E720048 : DQ14 DLL valid range, Pass 1
++ 0x1E72004C : DQ15 DLL valid range, Pass 1
++ 0x1E720090 : DLL1 SAdj record
++ 0x1E720094 : DQL Pass1 finetune result
++ 0x1E720098 : DQH Pass1 finetune result
++ 0x1E72009C : DRAM initial time, (us)
++ 0x1E7200A0 : CBR3 retry counter
++ 0x1E7200A4 : DRAM initial time, (us)
++ 0x1E7200A8 : Released date
++ 0x1E7200AC : Released SDK version
++ 0x1E7200B0 : DQS input mask window for MCR18[4] = 0
++ 0x1E7200B4 : DQS input mask window for MCR18[4] = 1
++ 0x1E720100 : DQIDLY=00, DLL valid range
++ 0x1E720104 : DQIDLY=01, DLL valid range
++ ....
++ 0x1E720178 : DQIDLY=30, DLL valid range
++ 0x1E72017C : DQIDLY=31, DLL valid range
++ 0x1E720180 : DQSI-MCLK2X P-phase pass record DLL2= 0-31
++ 0x1E720184 : DQSI-MCLK2X P-phase pass record DLL2=32-63
++ 0x1E720188 : DQSI-MCLK2X N-phase pass record DLL2= 0-31
++ 0x1E72018C : DQSI-MCLK2X N-phase pass record DLL2=32-63
++ ******************************************************************************/
++Calibration_Start_pre: @ Toggle DQSI mask delay
++ ldr r0, =0x1e6e0018
++ ldr r1, [r0]
++ eor r1, r1, #0x10
++ str r1, [r0]
++
++Calibration_Start:
++/* Init SRAM buffer */
++ ldr r1, =0x000000ff
++ ldr r0, =0x1e720000
++ ldr r2, =0x1e720100
++init_sram_start:
++ str r1, [r0]
++ add r0, r0, #4
++ cmp r0, r2
++ blt init_sram_start
++
++ ldr r1, =0x00ff00ff
++ ldr r0, =0x1e720100
++ ldr r2, =0x1e720180
++init_sram_start2:
++ str r1, [r0]
++ add r0, r0, #4
++ cmp r0, r2
++ blt init_sram_start2
++
++ ldr r1, =0x00000000
++ ldr r0, =0x1e720180
++ ldr r2, =0x1e720200
++init_sram_start3:
++ str r1, [r0]
++ add r0, r0, #4
++ cmp r0, r2
++ blt init_sram_start3
++
++ ldr r0, =0x1e6e0068 @ save the DLL1 SAdj initial value
++ ldr r1, [r0]
++ ldr r0, =0x1e720090
++ str r1, [r0]
++
++/* Start
++ r0 = free
++ r1 = free
++ r2 = free
++ r3 = free
++ r4 = record the return pc value, do not use
++ r5 = pattern table index
++ r6 = pass count
++ r7 = dram DLL2 parameter index (0x1e6e0068), max is 0x4C
++*/
++/******************************************************************************
++ Fine DQI delay and DQSI-MCLK phase
++ r8 = DQIDLY count
++ r9 = DQSI-MCLK2X phase count
++ r10 = pattern fail retry counter, initialize to 2 (fail 2 times)
++ r11 = passcnt accumulator for each DQIDLY
++ *****************************************************************************/
++CBR0_START:
++/* Debug - UART console message */
++ ldr r0, =0x1e784000
++ mov r1, #0x43 @ 'C'
++ str r1, [r0]
++ mov r1, #0x42 @ 'B'
++ str r1, [r0]
++ mov r1, #0x52 @ 'R'
++ str r1, [r0]
++ mov r1, #0x30 @ '0'
++ str r1, [r0]
++ mov r1, #0x2D @ '-'
++ str r1, [r0]
++/* Debug - UART console message */
++
++ ldr r0, =0x1e6e0018
++ ldr r1, [r0]
++ bic r1, r1, #0xFF000000
++ bic r1, r1, #0x00FF0000
++ str r1, [r0]
++
++ ldr r0, =0x1e6e0074 @ set the testing DRAM size = 1KB
++ ldr r1, =0x000003FF
++ str r1, [r0]
++
++ mov r8, #0x00 @ init DQIDLY
++ mov r9, #0x00 @ init DQSI-MCLK2X phase
++ mov r11, #0x01 @ init passcnt accumulator
++
++cbr0_next_dqidly:
++ cmp r9, #0x00
++ bne cbr0_next_dqsiphase
++ cmp r11, #0x00
++ addeq r8, r8, #0x01 @ jump 1 stage if no pass at previous stage
++ mov r11, #0x00
++ add r8, r8, #0x01
++ cmp r8, #0x1F @ max DQIDLY = 31
++ bgt CBR0_END
++
++/* Debug - UART console message */
++ ldr r0, =0x1e784000
++ and r1, r8, #0x07
++ add r1, r1, #0x30 @ '0-7'
++ str r1, [r0]
++/* Debug - UART console message */
++
++ ldr r0, =0x1e6e0018
++ ldr r1, [r0]
++ bic r1, r1, #0x00FF0000
++ orr r1, r1, r8, lsl #16
++ str r1, [r0]
++ mov r9, #0x01 @ '1':p_phase, '0':n_phase
++
++ /* Delay about 3us */ @ wait DQIDLY load
++ ldr r2, =0x00000003 @ Set Timer4 Reload = 3 us
++ init_delay_timer
++delay_4:
++ check_delay_timer
++ bne delay_4
++ clear_delay_timer
++ /* end delay 3us */
++
++ b cbr0_dll2_scan_start
++
++cbr0_next_dqsiphase:
++ ldr r0, =0x1e6e0018
++ ldr r1, [r0]
++ orr r1, r1, r9, lsl #23 @ set DQSI-MCLK2X phase
++ str r1, [r0]
++ mov r9, #0x00
++
++cbr0_dll2_scan_start:
++ mov r6, #0x00 @ init pass count
++ mov r7, #0x00 @ init DLL2 parameter index
++
++/****************************
++ DLL2 delay margin test loop
++ ***************************/
++cbr0_next_dll2_parameter:
++ ldr r0, =0x1e6e0068 @ load DLL2 parameter
++ ldr r1, [r0]
++ bic r1, r1, #0x00FF0000
++ bic r1, r1, #0xFF000000
++ orr r1, r1, r7, lsl #16
++ str r1, [r0]
++ ldr r2, =0x40404040 @ DLL2 max is 0x40404040
++ cmp r7, r2
++ bge cbr0_next_dqidly
++ ldr r2, =0x01010101
++ add r7, r7, r2
++
++/* CBRScan3() start */
++ adrl r5, PATTERN_TABLE @ init pattern table index
++/****************************
++ Test pattern iteration loop
++ ***************************/
++cbr0_next_test_pattern:
++ mov r10, #2 @ set the retry loop = 2 of each pattern
++ ldr r1, [r5] @ load test pattern
++ ldr r0, =0x1e6e007c
++ str r1, [r0]
++ cmp r1, #0x00 @ the last data in pattern is 0x00
++ bne cbr0_test_burst
++
++ and r3, r7, #0xFF
++ sub r3, r3, #0x01 @ we add 1 after loop check so we need to decrease 1
++ cmp r3, #0x00
++ beq cbr0_next_dqidly @ pass at dlli = 0, invalid
++ add r6, r6, #0x01 @ increment pass count
++ add r11, r11, #0x01 @ increment pass count
++
++ ldr r0, =0x1e720180 @ record DLL2 pass window
++ cmp r9, #0x00 @ DQSI-MCLK2X phase check
++ addeq r0, r0, #0x08
++ cmp r3, #32
++ addge r0, r0, #0x4
++ and r1, r3, #0x1F
++ mov r2, #0x1
++ mov r2, r2, lsl r1
++ ldr r1, [r0]
++ orr r1, r1, r2
++ str r1, [r0]
++
++ ldr r0, =0x1e720100 @ record DLL2 min:max value for each DQIDLY
++ add r0, r0, r8, lsl #2
++ cmp r9, #0x00 @ DQSI-MCLK2X phase check
++ beq cbr0_test_pass_dqsin
++ record_dll2_pass_range
++ b cbr0_next_dll2_parameter
++
++cbr0_test_pass_dqsin:
++ record_dll2_pass_range_h
++ b cbr0_next_dll2_parameter
++
++cbr0_test_pattern_fail:
++ cmp r6, #5 @ passcnt >= 5
++ bge cbr0_next_dqidly
++ ldr r0, =0x1e720100 @ reset DLL2 min:max value
++ add r0, r0, r8, lsl #2
++ ldr r1, [r0]
++ ldr r2, =0xFFFF0000
++ ldr r3, =0x000000FF
++ cmp r9, #0x00
++ moveq r2, r2, lsr #16
++ moveq r3, r3, lsl #16
++ and r1, r1, r2
++ orr r1, r1, r3
++ str r1, [r0]
++ b cbr0_next_dll2_parameter @ CBRScan3() end and test result fail, go to next step
++
++/****************************
++ Test fail retry loop
++ ***************************/
++cbr0_pattern_fail_retry:
++
++/* CBRTest3() start */
++cbr0_test_burst:
++ ldr r0, =0x1e6e0070
++ ldr r1, =0x00000000
++ str r1, [r0]
++ ldr r1, =0x000000C1
++ str r1, [r0]
++ ldr r3, =0x3000
++cbr0_wait_engine_idle_0:
++ ldr r2, [r0]
++ tst r2, r3 @ D[12] = idle bit
++ beq cbr0_wait_engine_idle_0
++
++ ldr r2, [r0] @ read fail bit status
++ mov r1, #0x0
++ str r1, [r0]
++ mov r2, r2, lsr #13 @ D[13] = fail bit
++ cmp r2, #0x00
++ bne cbr0_test_fail
++
++cbr0_test_single:
++ ldr r0, =0x1e6e0070
++ ldr r1, =0x00000000
++ str r1, [r0]
++ ldr r1, =0x00000085
++ str r1, [r0]
++ ldr r3, =0x3000
++cbr0_wait_engine_idle_1:
++ ldr r2, [r0]
++ tst r2, r3 @ D[12] = idle bit
++ beq cbr0_wait_engine_idle_1
++
++ ldr r2, [r0] @ read fail bit status
++ mov r1, #0x0
++ str r1, [r0]
++ mov r2, r2, lsr #13 @ D[13] = fail bit
++ cmp r2, #0x00
++ beq cbr0_test_pass
++
++/* CBRTest3() end */
++
++cbr0_test_fail:
++ subs r10, r10, #1
++ bne cbr0_pattern_fail_retry
++ b cbr0_test_pattern_fail @ CBRScan3() return(0)
++
++cbr0_test_pass:
++ add r5, r5, #0x04 @ increase the test pattern index
++ b cbr0_next_test_pattern
++
++CBR0_END:
++ mov r5, #0x0 @ init DQIDLY search count
++ mov r6, #0x0 @ init max_margin:g_margin
++ mov r8, #0x0 @ init g_side
++ mov r7, #0x0 @ init maximum margin DQIDLY,DQSI-MCLK2X phase
++cbr0_search_dll_margin_s:
++ ldr r0, =0x1e720100
++ add r0, r0, r5, lsl #2
++ ldr r1, [r0]
++ and r2, r1, #0xFF @ get dllmin_p
++ mov r1, r1, lsr #8
++ and r3, r1, #0xFF @ get dllmax_p
++ subs r2, r3, r2 @ get margin-P
++ movmi r2, #0x0
++ mov r1, r1, lsr #8
++ and r3, r1, #0xFF @ get dllmin_n
++ mov r1, r1, lsr #8
++ and r1, r1, #0xFF @ get dllmax_n
++ subs r3, r1, r3 @ get margin-N
++ movmi r3, #0x0
++ add r1, r2, r3
++ cmp r1, #0x0
++ beq cbr0_search_dll_margin_e @ if margin-P = 0 && margin-N = 0
++
++ ldr r9, [r0]
++ ldr r0, =0x1e720180
++ cmp r2, r3
++ orrlt r5, r5, #0x80 @ margin-N > margin-P
++ addlt r0, r0, #0x08
++ movlt r9, r9, lsr #16
++ movge r3, r2 @ max(margin-P/N)
++ add r2, r3, #0x2 @ define +/- 2 steps of variation
++ mov r1, r6, lsr #16
++ cmp r2, r1
++ blt cbr0_search_dll_margin_e @ if max(margin-P/N) + 2 < max_margin
++
++ and r1, r9, #0xFF @ r1 = dlli counter
++ cmp r1, #32
++ ldrge r2, [r0, #0x4] @ load pass window
++ ldrlt r2, [r0]
++ and r1, r1, #0x1F
++ mov r10, #0x1 @ init test bit mask
++ mov r10, r10, lsl r1
++ and r1, r9, #0xFF
++cbr0_search_dllmin_margin_s:
++ tst r2, r10
++ beq cbr0_search_dllmin_margin_e
++ mov r10, r10, lsr #1
++ cmp r1, #32
++ ldreq r2, [r0]
++ ldreq r10, =0x80000000
++ subs r1, r1, #0x1
++ bne cbr0_search_dllmin_margin_s
++
++cbr0_search_dllmin_margin_e:
++ and r2, r9, #0xFF
++ sub r11, r2, r1 @ get dllmin side margin
++
++ mov r9, r9, lsr #8
++ and r1, r9, #0xFF @ r1 = dlli counter
++ cmp r1, #32
++ ldrge r2, [r0, #0x4] @ load pass window
++ ldrlt r2, [r0]
++ and r1, r1, #0x1F
++ mov r10, #0x1 @ init test bit mask
++ mov r10, r10, lsl r1
++ and r1, r9, #0xFF
++cbr0_search_dllmax_margin_s:
++ tst r2, r10
++ beq cbr0_search_dllmax_margin_e
++ mov r10, r10, lsl #1
++ cmp r1, #31
++ ldreq r2, [r0, #0x4]
++ ldreq r10, =0x00000001
++ add r1, r1, #0x1
++ cmp r1, #64
++ bne cbr0_search_dllmax_margin_s
++
++cbr0_search_dllmax_margin_e:
++ and r2, r9, #0xFF
++ sub r1, r1, r2 @ get dllmax side margin
++ cmp r1, r11
++ movlt r11, r1 @ get side_margin
++
++cbr0_check_dll_margin: @ if max(margin-P/N) > g_margin && side_margin >= g_side && dqidly <= 20
++ cmp r5, #20
++ bgt cbr0_check_dll_margin2
++ and r1, r6, #0xFF
++ cmp r3, r1
++ ble cbr0_check_dll_margin3
++ cmp r11, r8
++ bge cbr0_set_dll_margin
++
++cbr0_check_dll_margin2: @ if max(margin-P/N) > g_margin+1 && side_margin >= g_side)
++ and r1, r6, #0xFF
++ add r2, r1, #0x1
++ cmp r3, r2
++ ble cbr0_check_dll_margin3
++ cmp r11, r8
++ bge cbr0_set_dll_margin
++
++cbr0_check_dll_margin3: @ if side_margin > g_side && g_side < 8
++ cmp r8, #8
++ bge cbr0_search_dll_margin_e
++ cmp r11, r8
++ ble cbr0_search_dll_margin_e
++
++cbr0_set_dll_margin:
++ mov r1, r6, lsr #16
++ cmp r3, r1
++ bicgt r6, r6, #0x00FF0000
++ orrgt r6, r6, r3, lsl #16
++ bic r6, r6, #0x000000FF
++ orr r6, r6, r3
++ mov r7, r5
++ mov r8, r11
++
++cbr0_search_dll_margin_e:
++ and r5, r5, #0x7F
++ add r5, r5, #0x01
++ cmp r5, #0x20 @ last DQIDLY
++ blt cbr0_search_dll_margin_s
++
++ ldr r0, =0x1e6e0018
++ ldr r1, [r0]
++ bic r1, r1, #0x00FF0000
++ orr r1, r1, r7, lsl #16
++ str r1, [r0]
++
++ ldr r0, =0x1e6e0068
++ ldr r1, [r0]
++ bic r1, r1, #0x00FF0000
++ bic r1, r1, #0xFF000000
++ str r1, [r0]
++
++ /* Delay about 5us */
++ ldr r2, =0x00000005 @ Set Timer5 Reload = 5 us
++ init_delay_timer
++delay_5:
++ check_delay_timer
++ bne delay_5
++ clear_delay_timer
++ /* end delay 5us */
++
++ ldr r0, =0x1e6e000c @ Set refresh cycle
++ ldr r1, =0x00005C01
++ str r1, [r0]
++
++/******************************************************************************
++ Fine tune per bit DQ input delay -- Pass 1, left edge align
++ r8 = free
++ r9 = DQ fail bit accumulator
++ r10 = pattern fail counter, initialize to 5 (fail 5 times)
++ r11 = free
++ *****************************************************************************/
++CBR1_START:
++/* Debug - UART console message */
++ ldr r0, =0x1e784000
++ mov r1, #0x0D @ '\r'
++ str r1, [r0]
++ mov r1, #0x0A @ '\n'
++ str r1, [r0]
++ mov r1, #0x43 @ 'C'
++ str r1, [r0]
++ mov r1, #0x42 @ 'B'
++ str r1, [r0]
++ mov r1, #0x52 @ 'R'
++ str r1, [r0]
++ mov r1, #0x31 @ '1'
++ str r1, [r0]
++/* Debug - UART console message */
++
++ mov r6, #0x00 @ init pass count
++ mov r7, #0x00 @ init DLL2 parameter index
++
++/****************************
++ DLL2 delay margin test loop
++ ***************************/
++cbr1_next_dll2_parameter:
++ ldr r0, =0x1e6e0068 @ load DLL2 parameter
++ ldr r1, [r0]
++ bic r1, r1, #0x00FF0000
++ bic r1, r1, #0xFF000000
++ orr r1, r1, r7, lsl #16
++ str r1, [r0]
++ ldr r2, =0x40404040 @ parameter's max is to 0x40404040
++ cmp r7, r2
++ bge CBR1_END
++ ldr r2, =0x01010101
++ add r7, r7, r2
++
++ ldr r0, =0x1e6e0074 @ set the testing DRAM size = 4KB
++ ldr r1, =0x00000FFF
++ str r1, [r0]
++
++/* CBRScan2() start */
++ ldr r9, =0xFFFF @ init test status
++ adrl r5, PATTERN_TABLE @ init pattern table index
++/****************************
++ Test pattern iteration loop
++ ***************************/
++cbr1_next_test_pattern:
++ mov r10, #5 @ set the retry loop of each pattern
++ ldr r1, [r5] @ load test pattern
++ ldr r0, =0x1e6e007c
++ str r1, [r0]
++ cmp r1, #0x00 @ the last data in pattern is 0x00
++ bne cbr1_test_single
++
++cbr1_test_pattern_end:
++ cmp r9, #0x00
++ bne cbr1_test_pass_dqi
++ cmp r6, #10
++ bge CBR1_END
++ b cbr1_next_dll2_parameter @ CBRScan2() end and test result fail, go to next step
++
++cbr1_test_pass_dqi:
++ and r3, r7, #0xFF
++ sub r3, r3, #0x01 @ we add 1 after loop check so we need to decrease 1
++ add r6, r6, #0x01 @ increment pass count
++ ldr r0, =0x1e720010
++ mov r8, #0x01
++cbr1_test_pass_dqi_loop_s:
++ tst r9, r8
++ beq cbr1_test_pass_dqi_loop_e
++ record_dll2_pass_range
++
++cbr1_test_pass_dqi_loop_e:
++ add r0, r0, #0x04
++ mov r8, r8, lsl #1
++ ldr r1, =0xFFFF
++ tst r8, r1
++ bne cbr1_test_pass_dqi_loop_s
++ b cbr1_next_dll2_parameter
++
++/****************************
++ Test fail retry loop
++ ***************************/
++cbr1_pattern_fail_retry:
++
++/* CBRTest2() start */
++cbr1_test_single:
++ ldr r0, =0x1e6e0070
++ ldr r1, =0x00000000
++ str r1, [r0]
++ ldr r1, =0x00000005
++ str r1, [r0]
++ ldr r3, =0x1000
++ ldr r1, =0x1000
++cbr1_wait_engine_idle_0:
++ subs r1, r1, #1
++ beq cbr1_test_single_end
++ ldr r2, [r0]
++ tst r2, r3 @ D[12] = idle bit
++ beq cbr1_wait_engine_idle_0
++
++cbr1_test_single_end:
++ ldr r0, =0x1e6e0078 @ read fail bit status
++ ldr r11, [r0]
++ orr r11, r11, r11, lsr #16
++ bic r11, r11, #0xFF000000
++ bic r11, r11, #0x00FF0000
++
++ ldr r1, =0xFFFF
++ cmp r11, r1
++ beq cbr1_test_fail
++
++cbr1_test_burst:
++ ldr r0, =0x1e6e0070
++ ldr r2, =0x00000000
++ str r2, [r0]
++ ldr r2, =0x00000041
++ str r2, [r0]
++ ldr r3, =0x1000
++ ldr r1, =0x1000
++cbr1_wait_engine_idle_1:
++ subs r1, r1, #1
++ beq cbr1_test_burst_end
++ ldr r2, [r0]
++ tst r2, r3 @ D[12] = idle bit
++ beq cbr1_wait_engine_idle_1
++
++cbr1_test_burst_end:
++ ldr r0, =0x1e6e0078 @ read fail bit status
++ ldr r2, [r0]
++ orr r2, r2, r2, lsr #16
++ bic r2, r2, #0xFF000000
++ bic r2, r2, #0x00FF0000
++ orr r11, r11, r2
++
++ ldr r2, =0xFFFF
++ cmp r11, r2
++ bne cbr1_test_pass
++/* CBRTest2() end */
++
++cbr1_test_fail:
++ subs r10, r10, #1
++ bne cbr1_pattern_fail_retry
++ mov r9, #0x00
++ b cbr1_test_pattern_end @ CBRScan2() return(0)
++
++cbr1_test_pass:
++ ldr r1, =0xFFFF @ record the pass bit
++ eor r11, r11, r1
++ and r9, r9, r11 @ DQ pass bit
++ cmp r9, #0x00
++ beq cbr1_test_pattern_end @ CBRScan2() return(0)
++
++ add r5, r5, #0x04 @ increase the test pattern index
++ b cbr1_next_test_pattern
++
++CBR1_END:
++ mov r5, #0x0 @ init DQ DLL_min sum
++ mov r6, #0x0 @ init DQ DLL_min valid count
++ ldr r0, =0x1e72000c
++ ldr r3, =0x1e720050
++cbr1_search_dllmin_s:
++ add r0, r0, #0x04
++ cmp r0, r3
++ beq cbr1_search_dllmin_e
++ ldr r1, [r0]
++ mov r2, r1, lsr #8
++ and r2, r2, #0xFF @ get dllmax
++ and r1, r1, #0xFF @ get dllmin
++ subs r2, r2, r1 @ dllmax - dllmin
++ bmi cbr1_search_dllmin_s @ no valid margin found, bypass fine tune
++ cmp r2, #10 @ (dllmax - dllmin) < 10
++ blt cbr1_search_dllmin_s @ no enough margin found, bypass fine tune
++ add r5, r5, r1
++ add r6, r6, #1
++ b cbr1_search_dllmin_s
++
++cbr1_search_dllmin_e:
++ cmp r6, #16
++ bne Calibration_Start_pre @ not all bits valid, retry again
++
++ mov r5, r5, lsr #4
++ ldr r0, =0x1e720000
++ str r5, [r0]
++
++ mov r6, #0x00 @ init DQL CBR value
++ ldr r0, =0x1e720030
++ ldr r7, =0x1e72000c
++cbr1_set_result_dql:
++ sub r0, r0, #4
++ cmp r0, r7
++ beq cbr1_set_result_next
++ mov r6, r6, lsl #3
++ ldr r1, [r0]
++ mov r2, r1, lsr #8
++ and r2, r2, #0xFF @ get dllmax
++ and r1, r1, #0xFF @ get dllmin
++ mov r3, r1 @ dll = dllmin
++ cmp r5, r3
++ blt cbr1_set_result_dql_neg
++ sub r1, r5, r3
++ mov r2, #19
++ mul r1, r2, r1
++ mov r1, r1, lsr #5 @ dqi_tune = ((gold_dll - dll) * 19) >> 5
++ cmp r1, #2 @ dqi_tune max = 2
++ movgt r1, #2
++ orr r6, r6, r1
++ b cbr1_set_result_dql
++
++cbr1_set_result_dql_neg:
++ sub r1, r3, r5
++ mov r2, #19
++ mul r1, r2, r1
++ mov r1, r1, lsr #5 @ dqi_tune = ((gold_dll - dll) * 19) >> 5
++ cmp r1, #2 @ dqi_tune max = -2
++ movgt r1, #2
++ mov r2, #8
++ sub r1, r2, r1
++ and r1, r1, #7
++ orr r6, r6, r1
++ b cbr1_set_result_dql
++
++cbr1_set_result_next:
++ ldr r0, =0x1e6e0080 @ save DQL fine tune result
++ str r6, [r0]
++ ldr r0, =0x1e720094
++ str r6, [r0]
++
++ mov r6, #0x00 @ init DQH CBR value
++ ldr r0, =0x1e720050
++ ldr r7, =0x1e72002c
++cbr1_set_result_dqh:
++ sub r0, r0, #4
++ cmp r0, r7
++ beq cbr1_set_result_end
++ mov r6, r6, lsl #3
++ ldr r1, [r0]
++ mov r2, r1, lsr #8
++ and r2, r2, #0xFF @ get dllmax
++ and r1, r1, #0xFF @ get dllmin
++ mov r3, r1 @ dll = dllmin
++ cmp r5, r3
++ blt cbr1_set_result_dqh_neg
++ sub r1, r5, r3
++ mov r2, #19
++ mul r1, r2, r1
++ mov r1, r1, lsr #5 @ dqi_tune = ((gold_dll - dll) * 19) >> 5
++ cmp r1, #3 @ dqi_tune max = 2
++ movgt r1, #3
++ subs r1, r1, #1
++ movmi r1, #7
++ orr r6, r6, r1
++ b cbr1_set_result_dqh
++
++cbr1_set_result_dqh_neg:
++ sub r1, r3, r5
++ mov r2, #19
++ mul r1, r2, r1
++ mov r1, r1, lsr #5 @ dqi_tune = ((gold_dll - dll) * 19) >> 5
++ add r1, r1, #1
++ cmp r1, #2 @ dqi_tune max = -2
++ movgt r1, #2
++ mov r2, #8
++ sub r1, r2, r1
++ and r1, r1, #7
++ orr r6, r6, r1
++ b cbr1_set_result_dqh
++
++cbr1_set_result_end:
++ ldr r0, =0x1e6e0084 @ save DQH fine tune result
++ str r6, [r0]
++ ldr r0, =0x1e720098
++ str r6, [r0]
++
++/******************************************************************************
++ Search the DLL2 detail margin
++ *****************************************************************************/
++ ldr r0, =0x1e7200a0
++ mov r1, #0
++ str r1, [r0]
++
++CBR3_START:
++/* Debug - UART console message */
++ ldr r0, =0x1e784000
++ mov r1, #0x33 @ '3'
++ str r1, [r0]
++/* Debug - UART console message */
++
++ mov r6, #0x00 @ init pass count
++ mov r7, #0x00 @ init DLL2 parameter index
++ ldr r1, =0x000000ff
++ ldr r0, =0x1e720008 @ init DQL dllmax,dllmin
++ str r1, [r0]
++ ldr r0, =0x1e72000c @ init DQH dllmax,dllmin
++ str r1, [r0]
++
++ ldr r0, =0x1e7200a0 @ CBR3 iteration counter
++ ldr r1, [r0]
++ add r1, r1, #1
++ str r1, [r0]
++
++/****************************
++ DLL2 delay margin test loop
++ ***************************/
++cbr3_next_dll2_parameter:
++ ldr r0, =0x1e6e0068 @ load DLL2 parameter
++ ldr r1, [r0]
++ bic r1, r1, #0x00FF0000
++ bic r1, r1, #0xFF000000
++ orr r1, r1, r7, lsl #16
++ str r1, [r0]
++ ldr r2, =0x40404040 @ parameter's max is to 0x40404040
++ cmp r7, r2
++ bge CBR3_END
++ ldr r2, =0x01010101
++ add r7, r7, r2
++
++ ldr r0, =0x1e6e0074 @ set the testing DRAM size = 64KB
++ ldr r1, =0x0000FFFF
++ str r1, [r0]
++
++/* CBRScan() start */
++ mov r9, #0x03 @ init test status
++ adrl r5, PATTERN_TABLE @ init pattern table index
++/****************************
++ Test pattern iteration loop
++ ***************************/
++cbr3_next_test_pattern:
++ mov r10, #5 @ set the retry loop of each pattern
++ ldr r1, [r5] @ load test pattern
++ ldr r0, =0x1e6e007c
++ str r1, [r0]
++ cmp r1, #0x00 @ the last data in pattern is 0x00
++ bne cbr3_test_single
++
++cbr3_test_pattern_end:
++ cmp r9, #0x00
++ bne cbr3_test_pass_dql
++ cmp r6, #10
++ bge CBR3_END
++ b cbr3_next_dll2_parameter @ CBRScan() end and test result fail, go to next step
++
++cbr3_test_pass_dql:
++ and r3, r7, #0xFF
++ sub r3, r3, #0x01 @ we add one after loop check so we need to decrease 1
++ add r6, r6, #0x01 @ increment pass count
++ tst r9, #0x01
++ beq cbr3_test_pass_dqh
++
++ ldr r0, =0x1E720008
++ record_dll2_pass_range
++
++cbr3_test_pass_dqh:
++ tst r9, #0x02
++ beq cbr3_next_dll2_parameter
++ ldr r0, =0x1E72000c
++ record_dll2_pass_range
++ b cbr3_next_dll2_parameter
++
++/****************************
++ Test fail retry loop
++ ***************************/
++cbr3_pattern_fail_retry:
++
++/* CBRTest() start */
++cbr3_test_single:
++ ldr r0, =0x1e6e0070
++ ldr r1, =0x00000000
++ str r1, [r0]
++ ldr r1, =0x00000005
++ str r1, [r0]
++ ldr r3, =0x1000
++ ldr r8, =0x10000
++cbr3_wait_engine_idle_0:
++ subs r8, r8, #1
++ beq cbr3_test_single_end
++ ldr r2, [r0]
++ tst r2, r3 @ D[12] = idle bit
++ beq cbr3_wait_engine_idle_0
++
++cbr3_test_single_end:
++ ldr r0, =0x1e6e0078 @ read fail bit status
++ ldr r11, [r0]
++ orr r11, r11, r11, lsr #16
++ bic r11, r11, #0xFF000000
++ bic r11, r11, #0x00FF0000
++
++ ldr r1, =0xFF
++ tst r11, r1
++ beq cbr3_test_burst
++ tst r11, r1, lsl #8
++ bne cbr3_test_fail
++
++cbr3_test_burst:
++ mov r1, #0x00 @ initialize loop index, r1 is loop's index
++cbr3_test_burst_loop:
++ ldr r0, =0x1e6e0070
++ ldr r2, =0x00000000
++ str r2, [r0]
++ mov r2, r1, lsl #3
++ orr r2, r2, #0x41 @ test command = 0x41 | (datagen << 3)
++ str r2, [r0]
++ ldr r3, =0x1000
++ ldr r8, =0x10000
++cbr3_wait_engine_idle_1:
++ subs r8, r8, #1
++ beq cbr3_test_burst_end
++ ldr r2, [r0]
++ tst r2, r3 @ D[12] = idle bit
++ beq cbr3_wait_engine_idle_1
++
++cbr3_test_burst_end:
++ ldr r0, =0x1e6e0078 @ read fail bit status
++ ldr r2, [r0]
++ orr r2, r2, r2, lsr #16
++ bic r2, r2, #0xFF000000
++ bic r2, r2, #0x00FF0000
++ orr r11, r11, r2
++
++ ldr r2, =0xFF
++ tst r11, r2
++ beq cbr3_next_test_burst_mode
++ tst r11, r2, lsl #8
++ beq cbr3_next_test_burst_mode
++/* CBRTest() end */
++
++cbr3_test_fail:
++ subs r10, r10, #1
++ bne cbr3_pattern_fail_retry
++ mov r9, #0x00
++ b cbr3_test_pattern_end @ CBRScan() return(0)
++
++cbr3_next_test_burst_mode:
++ add r1, r1, #1 @ increase the test mode index
++ cmp r1, #0x08 @ there are 8 modes
++ bne cbr3_test_burst_loop
++
++ ldr r1, =0xFF @ record the pass byte
++ tst r11, r1
++ andne r9, r9, #0x02 @ DQL fail
++ tst r11, r1, lsl #8
++ andne r9, r9, #0x01 @ DQH fail
++ cmp r9, #0x00
++ beq cbr3_test_pattern_end @ CBRScan() return(0)
++
++ add r5, r5, #0x04 @ increase the test pattern index
++ b cbr3_next_test_pattern
++
++CBR3_END:
++ ldr r0, =0x1e72000c @ check DQH margin
++ ldr r1, [r0]
++ mov r2, r1, lsr #8
++ and r2, r2, #0xFF @ get dllmax
++ and r1, r1, #0xFF @ get dllmin
++ subs r5, r2, r1 @ dllmax - dllmin
++ bmi CBR3_START @ no valid margin found, retry again
++ cmp r5, #10 @ (dllmax - dllmin) < 10
++ blt CBR3_START @ no enough margin found, retry again
++ add r2, r1, r2 @ (dllmin[1] + dllmax[1] + 1) >> 1
++ add r2, r2, #0x01
++ mov r1, r2, lsr #1
++ mov r3, r1, lsl #8
++ ldr r1, [r0] @ store the dll search result
++ bic r1, r1, #0xFF000000
++ bic r1, r1, #0x00FF0000
++ orr r1, r1, r3, lsl #8
++ str r1, [r0]
++
++ ldr r0, =0x1e720008 @ check DQL margin
++ ldr r1, [r0]
++ mov r2, r1, lsr #8
++ and r2, r2, #0xFF @ get dllmax
++ and r1, r1, #0xFF @ get dllmin
++ subs r5, r2, r1 @ dllmax - dllmin
++ bmi CBR3_START @ no valid margin found, retry again
++ cmp r5, #10 @ (dllmax - dllmin) < 10
++ blt CBR3_START @ no enough margin found, retry again
++ add r2, r1, r2 @ (dllmin[0] + dllmax[0] + 1) >> 1
++ add r2, r2, #0x01
++ mov r1, r2, lsr #1
++ ldr r2, [r0] @ store the dll search result
++ bic r2, r2, #0xFF000000
++ bic r2, r2, #0x00FF0000
++ orr r2, r2, r1, lsl #16
++ str r2, [r0]
++ orr r3, r3, r1
++
++ ldr r0, =0x1e6e0068 @ save the result dll value
++ ldr r1, [r0]
++ bic r1, r1, #0xFF000000
++ bic r1, r1, #0x00FF0000
++ orr r1, r1, r3, lsl #16
++ str r1, [r0]
++ b CBR4_START
++
++.LTORG
++
++/******************************************************************************
++ Search the DQS input mask margin
++ *****************************************************************************/
++CBR4_START:
++/* Debug - UART console message */
++ ldr r0, =0x1e784000
++ mov r1, #0x34 @ '4'
++ str r1, [r0]
++/* Debug - UART console message */
++
++ ldr r0, =0x1e6e0074 @ set the testing DRAM size = 4KB
++ ldr r1, =0x00000FFF
++ str r1, [r0]
++
++ mov r8, #0x00 @ init MCR18[4]
++ ldr r1, =0x000000ff
++ ldr r0, =0x1e7200b0 @ init MCR18[4]=0 max,min
++ str r1, [r0]
++ ldr r0, =0x1e7200b4 @ init MCR18[4]=1 max,min
++ str r1, [r0]
++
++ ldr r0, =0x1e6e0018
++ ldr r1, [r0]
++ bic r1, r1, #0x0000001F
++ str r1, [r0]
++
++ b cbr4_scan_start
++
++cbr4_next_maskdly:
++ add r8, r8, #0x01
++ and r2, r8, #0x01
++ ldr r0, =0x1e6e0018
++ ldr r1, [r0]
++ bic r1, r1, #0x0000001F
++ orr r1, r1, r2, lsl #4
++ str r1, [r0]
++ cmp r8, #0x02
++ bge CBR4_END
++
++cbr4_scan_start:
++ mov r6, #0x00 @ init pass count
++ mov r7, #0x00 @ init mask delay
++
++/****************************
++ DQS Mask delay margin test loop
++ ***************************/
++cbr4_next_parameter:
++ cmp r7, #0x10 @ max delay = 0xF
++ bge cbr4_next_maskdly
++ ldr r0, =0x1e6e0018 @ load MCR18 parameter
++ ldr r1, [r0]
++ bic r1, r1, #0x0000000F
++ orr r1, r1, r7
++ str r1, [r0]
++ add r7, r7, #0x01
++
++/* CBRScan3() start */
++ adrl r5, PATTERN_TABLE @ init pattern table index
++/****************************
++ Test pattern iteration loop
++ ***************************/
++cbr4_next_test_pattern:
++ mov r10, #2 @ set the retry loop = 2 of each pattern
++ ldr r1, [r5] @ load test pattern
++ ldr r0, =0x1e6e007c
++ str r1, [r0]
++ cmp r1, #0x00 @ the last data in pattern is 0x00
++ bne cbr4_test_burst
++
++ and r3, r7, #0xFF
++ sub r3, r3, #0x01 @ we add 1 after loop check so we need to decrease 1
++ add r6, r6, #0x01 @ increment pass count
++
++ ldr r0, =0x1e7200b0 @ record pass window
++ add r0, r0, r8, lsl #2
++ record_dll2_pass_range
++ mov r2, #0x01
++ add r1, r1, r2, lsl #16
++ str r1, [r0]
++ b cbr4_next_parameter
++
++cbr4_test_pattern_fail:
++ cmp r6, #5 @ passcnt >= 5
++ bge cbr4_next_maskdly
++ b cbr4_next_parameter
++
++/****************************
++ Test fail retry loop
++ ***************************/
++cbr4_pattern_fail_retry:
++
++/* CBRTest3() start */
++cbr4_test_burst:
++ ldr r0, =0x1e6e0070
++ ldr r1, =0x00000000
++ str r1, [r0]
++ ldr r1, =0x000000C1
++ str r1, [r0]
++ ldr r3, =0x3000
++cbr4_wait_engine_idle_0:
++ ldr r2, [r0]
++ tst r2, r3 @ D[12] = idle bit
++ beq cbr4_wait_engine_idle_0
++
++ ldr r2, [r0] @ read fail bit status
++ mov r1, #0x0
++ str r1, [r0]
++ mov r2, r2, lsr #13 @ D[13] = fail bit
++ cmp r2, #0x00
++ bne cbr4_test_fail
++
++cbr4_test_single:
++ ldr r0, =0x1e6e0070
++ ldr r1, =0x00000000
++ str r1, [r0]
++ ldr r1, =0x00000085
++ str r1, [r0]
++ ldr r3, =0x3000
++cbr4_wait_engine_idle_1:
++ ldr r2, [r0]
++ tst r2, r3 @ D[12] = idle bit
++ beq cbr4_wait_engine_idle_1
++
++ ldr r2, [r0] @ read fail bit status
++ mov r1, #0x0
++ str r1, [r0]
++ mov r2, r2, lsr #13 @ D[13] = fail bit
++ cmp r2, #0x00
++ beq cbr4_test_pass
++
++/* CBRTest3() end */
++
++cbr4_test_fail:
++ subs r10, r10, #1
++ bne cbr4_pattern_fail_retry
++ b cbr4_test_pattern_fail @ CBRScan3() return(0)
++
++cbr4_test_pass:
++ add r5, r5, #0x04 @ increase the test pattern index
++ b cbr4_next_test_pattern
++
++CBR4_END:
++ ldr r0, =0x1e7200b0 @ check mask margin
++ ldr r1, [r0]
++ add r0, r0, #0x04
++ ldr r2, [r0]
++ ands r6, r2, #0xFF @ get min of MCR18[4] = 1
++ bne cbr4_noset_delay
++ ands r5, r1, #0xFF @ get min of MCR18[4] = 0
++ bne cbr4_set_delay
++ mov r1, r1, lsr #8 @ get max of MCR18[4] = 0
++ and r1, r1, #0xFF
++ mov r2, r2, lsr #8 @ get max of MCR18[4] = 1
++ and r2, r2, #0xFF
++ sub r1, r1, r5
++ sub r2, r2, r6
++ cmp r1, r2
++ bge cbr4_noset_delay
++
++cbr4_set_delay:
++ ldr r0, =0x1e6e0018
++ ldr r1, [r0]
++ orr r1, r1, #0x10
++ str r1, [r0]
++
++cbr4_noset_delay:
++ ldr r0, =0x1e6e0070
++ ldr r1, =0x00000000
++ str r1, [r0]
++
++/******************************************************************************
++ CBR Finish
++ *****************************************************************************/
++/******************************************************************************
++ Check DRAM Size
++ *****************************************************************************/
++ ldr r0, =0x1e6e2070
++ ldr r1, [r0]
++ bic r1, r1, #0xFEFFFFFF @ bit[24]=1 => DDR2
++ mov r2, r1, lsr #24
++ cmp r2, #0x01
++ beq check_ddr2_size
++
++ ldr r0, =0x1e6e0004
++ ldr r5, [r0]
++ bic r5, r5, #0x00000003 @ record MCR04
++ orr r1, r5, #0x3
++ str r1, [r0] @ set to 4Gbit
++ ldr r6, =0x003F2217
++#if defined(CONFIG_DRAM_336)
++ ldr r6, =0x00361C13
++#endif
++ b check_dram_size
++
++check_ddr2_size:
++ ldr r0, =0x1e6e0004
++ ldr r5, [r0]
++ bic r5, r5, #0x00000023 @ record MCR04
++ orr r1, r5, #0x23
++ str r1, [r0] @ set to 4Gbit
++ ldr r6, =0x3F2B1B16
++#if defined(CONFIG_DRAM_336)
++ ldr r6, =0x3B231612
++#endif
++
++ ldr r0, =0x40000000
++ ldr r1, =0x1817191A
++ str r1, [r0]
++ ldr r0, =0x40002000
++ ldr r1, =0x73616532
++ str r1, [r0]
++ ldr r0, =0x40000000
++ ldr r1, =0x1817191A
++ ldr r2, [r0]
++ cmp r1, r2
++ bne check_dram_size_end @ == 512Mbit
++ orr r5, r5, #0x20 @ >= 1Gbit
++ mov r6, r6, lsr #8
++
++check_dram_size:
++ ldr r0, =0x50100000
++ ldr r1, =0x41424344
++ str r1, [r0]
++ ldr r0, =0x48100000
++ ldr r1, =0x25262728
++ str r1, [r0]
++ ldr r0, =0x40100000
++ ldr r1, =0x191A1B1C
++ str r1, [r0]
++ ldr r0, =0x50100000
++ ldr r1, =0x41424344
++ ldr r2, [r0]
++ cmp r2, r1 @ == 4Gbit
++ orreq r5, r5, #0x03
++ moveq r6, r6, lsr #16
++ beq check_dram_size_end
++ ldr r0, =0x48100000
++ ldr r1, =0x25262728
++ ldr r2, [r0]
++ cmp r2, r1 @ == 2Gbit
++ orreq r5, r5, #0x02
++ moveq r6, r6, lsr #8
++ beq check_dram_size_end
++ orr r5, r5, #0x01 @ == 1Gbit
++
++check_dram_size_end:
++ ldr r0, =0x1e6e0004
++ str r5, [r0]
++ ldr r0, =0x1e6e0014
++ ldr r1, [r0]
++ bic r1, r1, #0x000000FF
++ and r6, r6, #0xFF
++ orr r1, r1, r6
++ str r1, [r0]
++
++ ldr r0, =0x1e6e0120 @ VGA Compatible Mode
++ ldr r1, =0x000050C0 @ 408 MHz
++#if defined(CONFIG_DRAM_336)
++ ldr r1, =0x00004DC0
++#endif
++ str r1, [r0]
++
++/******************************************************************************
++ Version Number
++ *****************************************************************************/
++ ldr r0, =0x1e7200a8
++ ldr r1, =0x20141229 @ released date
++ str r1, [r0]
++
++ add r0, r0, #4
++ ldr r1, =0x00000060 @ released SDK version
++ str r1, [r0]
++
++/******************************************************************************
++ Calibration Code End
++ ******************************************************************************/
++
++set_scratch:
++ /*Set Scratch register Bit 6 after ddr initial finished */
++ ldr r0, =0x1e6e2040
++ ldr r1, [r0]
++ orr r1, r1, #0x40
++ str r1, [r0]
++
++/* Debug - UART console message */
++ ldr r0, =0x1e784000
++ mov r1, #0x44 @ 'D'
++ str r1, [r0]
++ mov r1, #0x6F @ 'o'
++ str r1, [r0]
++ mov r1, #0x6E @ 'n'
++ str r1, [r0]
++ mov r1, #0x65 @ 'e'
++ str r1, [r0]
++ mov r1, #0x0D @ '\r'
++ str r1, [r0]
++ mov r1, #0x0A @ '\n'
++ str r1, [r0]
++/* Debug - UART console message */
++
++/******************************************************************************
++ Solve PCIe ASPM issue, only applied to AST2300 series
++ ******************************************************************************/
++ ldr r0, =0x1e6e207c @ Check bounding for AST1150 existence
++ ldr r1, [r0]
++ mov r2, r1, lsr #24
++ cmp r2, #0x01
++ bne platform_exit @ not match AST2300
++ bic r1, r1, #0xFFFFFCFF
++ mov r1, r1, lsr #8
++ cmp r1, #0x02
++ beq platform_exit @ match AST1050
++
++ ldr r0, =0x1e6e2004 @ Disable I2C controller reset
++ ldr r1, [r0]
++ orr r1, r1, #0x04
++ str r1, [r0]
++ bic r1, r1, #0x04
++ str r1, [r0]
++
++ ldr r0, =0x1e78a054 @ Check I2C bus state, if busy then quit
++ ldr r1, [r0]
++ mov r1, r1, lsr #17
++ and r1, r1, #0x03
++ cmp r1, #0x03
++ bne platform_exit
++
++ ldr r0, =0x1e78a040 @ Init I2C1 controller
++ mov r1, #0x01
++ orr r1, r1, r1, lsl #16
++ str r1, [r0]
++
++ ldr r0, =0x1e78a044
++ ldr r1, =0x77776704
++ str r1, [r0]
++
++ mov r1, #0x0
++ ldr r0, =0x1e78a048
++ str r1, [r0]
++ ldr r0, =0x1e78a04c
++ str r1, [r0]
++
++ ldr r0, =0x1e78a050
++ ldr r1, =0xFFFFFFFF
++ str r1, [r0]
++
++ ldr r0, =0x1e78a200 @ Set AST1150 I2C password
++ ldr r1, =0x00A88FA8
++ str r1, [r0]
++
++ ldr r0, =0x1e78a05c
++ ldr r1, =0x00000200 @ Enable buffer mode transfering 3 bytes
++ str r1, [r0]
++
++ ldr r0, =0x1e78a054
++ ldr r1, =0x00000063 @ Fire commmand
++ str r1, [r0]
++
++ ldr r0, =0x1e78a050
++i2c_wait_cmddone_1:
++ ldr r1, [r0]
++ tst r1, #0x38
++ beq i2c_wait_cmddone_1
++ tst r1, #0x2A @ transmit error
++ bne platform_exit2
++ ldr r1, =0xFFFFFFFF
++ str r1, [r0]
++
++ ldr r0, =0x1e78a200 @ Disable ASPM capability
++ ldr r1, =0x04005DA8
++ str r1, [r0]
++
++ ldr r0, =0x1e78a204
++ ldr r1, =0x00000024
++ str r1, [r0]
++
++ ldr r0, =0x1e78a05c
++ ldr r1, =0x00000200 @ Enable buffer mode transfering 3 bytes
++ str r1, [r0]
++
++ ldr r0, =0x1e78a054
++ ldr r1, =0x00000063 @ Fire commmand
++ str r1, [r0]
++
++ ldr r0, =0x1e78a050
++i2c_wait_cmddone_2:
++ ldr r1, [r0]
++ tst r1, #0x38
++ beq i2c_wait_cmddone_2
++ tst r1, #0x2A @ transmit error
++ bne platform_exit2
++ ldr r1, =0xFFFFFFFF
++ str r1, [r0]
++
++platform_exit2:
++ ldr r0, =0x1e78a040 @ Disable I2C1 controller
++ mov r1, #0x00
++ str r1, [r0]
++
++ b platform_exit
++.LTORG
++
++platform_exit:
++#ifdef CONFIG_DRAM_ECC
++ ldr r0, =0x1e6e0004
++ ldr r1, [r0]
++ orr r1, r1, #0x80
++ str r1, [r0]
++
++ ldr r0, =0x1e6e0054
++ ldr r1, =0x05000000 /* ECC protected memory size, default set at 80M */
++ str r1, [r0]
++
++ ldr r0, =0x1e6e007C
++ ldr r1, =0x00000000
++ str r1, [r0]
++ ldr r0, =0x1e6e0074
++ str r1, [r0]
++
++ ldr r0, =0x1e6e0070
++ ldr r1, =0x00000221
++ str r1, [r0]
++
++ ldr r0, =0x1e6e0070
++ ldr r2, =0x00001000
++ECC_Init_Flag:
++ ldr r1, [r0]
++ tst r1, r2 @ D[12] = 1, Done
++ beq ECC_Init_Flag
++
++ ldr r0, =0x1e6e0070
++ ldr r1, =0x00000000
++ str r1, [r0]
++
++ ldr r0, =0x1e6e0050
++ ldr r1, =0x80000000
++ str r1, [r0]
++
++ ldr r0, =0x1e6e0050
++ ldr r1, =0x00000000
++ str r1, [r0]
++
++ ldr r0, =0x1e6e0070
++ ldr r1, =0x00000400
++ str r1, [r0]
++#endif
++ ldr r0, =0x1e6e2008 @ Set Video ECLK phase
++ ldr r1, [r0]
++ ldr r2, =0xfffffff3
++ and r1, r1, r2
++ orr r1, r1, #0x08
++ str r1, [r0]
++
++ ldr r0, =0x1e6e2004
++ ldr r1, [r0]
++ ldr r2, =0xFFBFFFFF @ Enable JTAG Master, solve ARM stucked by JTAG issue
++ and r1, r1, r2
++ str r1, [r0]
++
++ ldr r0, =0x1e6e2048 @ Set MAC interface delay timing
++ ldr r1, =0x2255
++ str r1, [r0]
++
++ ldr r0, =0x1e6e2070 @ Set MAC AHB bus clock
++ ldr r1, [r0]
++ mov r2, #0x04 @ Default RMII, set MHCLK = HPLL/10
++ tst r1, #0xC0
++ movne r2, #0x02 @ if RGMII, set MHCLK = HPLL/6
++ ldr r0, =0x1e6e2008
++ ldr r1, [r0]
++ bic r1, r1, #0x00070000
++ orr r1, r1, r2, lsl #16
++ str r1, [r0]
++
++/* Test - DRAM initial time */
++ ldr r0, =0x1e782040
++ ldr r1, [r0]
++ ldr r0, =0xFFFFFFFF
++ sub r1, r0, r1
++ ldr r0, =0x1e72009c
++ str r1, [r0]
++ ldr r0, =0x1e7200a4
++ str r1, [r0]
++ ldr r0, =0x1e782030
++ ldr r1, [r0]
++ bic r1, r1, #0x0000F000
++ str r1, [r0]
++/* Test - DRAM initial time */
++
++/******************************************************************************
++ Reset GPIO registers when watchdog reset
++ ******************************************************************************/
++ ldr r0, =0x1e6e207c @ Check Revision ID
++ ldr r1, [r0]
++ mov r1, r1, lsr #24
++ cmp r1, #0x02
++ bne platform_exit3 @ not match AST2400
++
++ ldr r0, =0x1e6e203c @ Check watchdog reset event
++ ldr r1, [r0]
++ and r1, r1, #0x06
++ cmp r1, #0x0
++ beq platform_exit3 @ no watchdog reset event
++
++ ldr r0, =0x1e6e209c @ Check watchdog GPIO selection
++ ldr r1, [r0]
++ mov r1, r1, lsr #21
++ tst r1, #0x01
++ beq platform_exit3 @ no watchdog reset selection
++
++ ldr r1, =0x00000000 @ clear GPIO register reset by PRST_N
++ ldr r2, =0xFFFFFFFF
++ ldr r0, =0x1e780008
++ str r1, [r0]
++ ldr r0, =0x1e78000c
++ str r1, [r0]
++ ldr r0, =0x1e780010
++ str r1, [r0]
++ ldr r0, =0x1e780014
++ str r1, [r0]
++ ldr r0, =0x1e780018
++ str r2, [r0]
++ ldr r0, =0x1e780028
++ str r1, [r0]
++ ldr r0, =0x1e78002c
++ str r1, [r0]
++ ldr r0, =0x1e780030
++ str r1, [r0]
++ ldr r0, =0x1e780034
++ str r1, [r0]
++ ldr r0, =0x1e780038
++ str r2, [r0]
++ ldr r0, =0x1e780040
++ str r1, [r0]
++ ldr r0, =0x1e780044
++ str r1, [r0]
++ ldr r0, =0x1e780048
++ str r1, [r0]
++ ldr r0, =0x1e78004c
++ str r1, [r0]
++ ldr r0, =0x1e780050
++ str r1, [r0]
++ ldr r0, =0x1e780054
++ str r1, [r0]
++ ldr r0, =0x1e780058
++ str r1, [r0]
++ ldr r0, =0x1e780060
++ str r1, [r0]
++ ldr r0, =0x1e780064
++ str r1, [r0]
++ ldr r0, =0x1e780068
++ str r1, [r0]
++ ldr r0, =0x1e78006c
++ str r1, [r0]
++ ldr r0, =0x1e780090
++ str r1, [r0]
++ ldr r0, =0x1e780094
++ str r1, [r0]
++ ldr r0, =0x1e780098
++ str r1, [r0]
++ ldr r0, =0x1e78009c
++ str r1, [r0]
++ ldr r0, =0x1e7800a0
++ str r1, [r0]
++ ldr r0, =0x1e7800a4
++ str r1, [r0]
++ ldr r0, =0x1e7800a8
++ str r2, [r0]
++ ldr r0, =0x1e7800b0
++ str r1, [r0]
++ ldr r0, =0x1e7800b4
++ str r1, [r0]
++ ldr r0, =0x1e7800b8
++ str r1, [r0]
++ ldr r0, =0x1e7800e0
++ str r1, [r0]
++ ldr r0, =0x1e7800e4
++ str r1, [r0]
++ ldr r0, =0x1e7800e8
++ str r1, [r0]
++ ldr r0, =0x1e7800ec
++ str r1, [r0]
++ ldr r0, =0x1e7800f0
++ str r1, [r0]
++ ldr r0, =0x1e7800f4
++ str r1, [r0]
++ ldr r0, =0x1e7800f8
++ str r2, [r0]
++ ldr r0, =0x1e780100
++ str r1, [r0]
++ ldr r0, =0x1e780104
++ str r1, [r0]
++ ldr r0, =0x1e780108
++ str r1, [r0]
++ ldr r0, =0x1e780110
++ str r1, [r0]
++ ldr r0, =0x1e780114
++ str r1, [r0]
++ ldr r0, =0x1e780118
++ str r1, [r0]
++ ldr r0, =0x1e78011c
++ str r1, [r0]
++ ldr r0, =0x1e780120
++ str r1, [r0]
++ ldr r0, =0x1e780124
++ str r1, [r0]
++ ldr r0, =0x1e780128
++ str r2, [r0]
++ ldr r0, =0x1e780130
++ str r1, [r0]
++ ldr r0, =0x1e780134
++ str r1, [r0]
++ ldr r0, =0x1e780138
++ str r1, [r0]
++ ldr r0, =0x1e780140
++ str r1, [r0]
++ ldr r0, =0x1e780144
++ str r1, [r0]
++ ldr r0, =0x1e780148
++ str r1, [r0]
++ ldr r0, =0x1e78014c
++ str r1, [r0]
++ ldr r0, =0x1e780150
++ str r1, [r0]
++ ldr r0, =0x1e780154
++ str r1, [r0]
++ ldr r0, =0x1e780158
++ str r2, [r0]
++ ldr r0, =0x1e780160
++ str r1, [r0]
++ ldr r0, =0x1e780164
++ str r1, [r0]
++ ldr r0, =0x1e780168
++ str r1, [r0]
++ ldr r0, =0x1e780170
++ str r1, [r0]
++ ldr r0, =0x1e780174
++ str r1, [r0]
++ ldr r0, =0x1e780178
++ str r1, [r0]
++ ldr r0, =0x1e78017c
++ str r1, [r0]
++ ldr r0, =0x1e780180
++ str r1, [r0]
++ ldr r0, =0x1e780184
++ str r1, [r0]
++ ldr r0, =0x1e780188
++ str r2, [r0]
++ ldr r0, =0x1e780190
++ str r1, [r0]
++ ldr r0, =0x1e780194
++ str r1, [r0]
++ ldr r0, =0x1e780198
++ str r1, [r0]
++ ldr r0, =0x1e7801d0
++ str r1, [r0]
++ ldr r0, =0x1e7801d4
++ str r1, [r0]
++
++ ldr r0, =0x1e780204 @ clear SGPIOM register reset by PRST_N
++ str r1, [r0]
++ ldr r0, =0x1e780208
++ str r1, [r0]
++ ldr r0, =0x1e78020c
++ str r1, [r0]
++ ldr r0, =0x1e780210
++ str r1, [r0]
++ ldr r0, =0x1e780214
++ str r2, [r0]
++ ldr r0, =0x1e780220
++ str r1, [r0]
++ ldr r0, =0x1e780224
++ str r1, [r0]
++ ldr r0, =0x1e780228
++ str r1, [r0]
++ ldr r0, =0x1e78022c
++ str r1, [r0]
++ ldr r0, =0x1e780230
++ str r2, [r0]
++ ldr r0, =0x1e78023c
++ str r1, [r0]
++ ldr r0, =0x1e780240
++ str r1, [r0]
++ ldr r0, =0x1e780244
++ str r1, [r0]
++ ldr r0, =0x1e780248
++ str r1, [r0]
++ ldr r0, =0x1e78024c
++ str r2, [r0]
++ ldr r0, =0x1e780254
++ ldr r3, =0x01000040
++ str r3, [r0]
++ ldr r0, =0x1e780258
++ str r1, [r0]
++ ldr r0, =0x1e78025c
++ str r1, [r0]
++ ldr r0, =0x1e780260
++ str r1, [r0]
++
++ ldr r0, =0x1e780300 @ clear SGPIOS register reset by PRST_N
++ str r1, [r0]
++ ldr r0, =0x1e780304
++ str r1, [r0]
++ ldr r0, =0x1e780308
++ str r1, [r0]
++ ldr r0, =0x1e78030c
++ str r1, [r0]
++ ldr r0, =0x1e780310
++ str r1, [r0]
++ ldr r0, =0x1e780314
++ str r1, [r0]
++ ldr r0, =0x1e780318
++ str r2, [r0]
++ ldr r0, =0x1e78031c
++ str r2, [r0]
++ ldr r0, =0x1e780320
++ str r2, [r0]
++
++platform_exit3:
++
++/******************************************************************************
++ SPI Timing Calibration, not applicable to AST2300 series
++ ******************************************************************************/
++ ldr r0, =0x1e6e207c @ Check Revision ID
++ ldr r1, [r0]
++ mov r1, r1, lsr #24
++ cmp r1, #0x02
++ blt platform_exit4 @ not match AST2400 or later
++
++ ldr r0, =0x1e6e2070 @ Check SPI flash
++ ldr r1, [r0]
++ and r1, r1, #0x03
++ cmp r1, #0x02
++ bne platform_exit4
++
++ mov r2, #0x0
++ mov r6, #0x0
++ mov r7, #0x0
++ init_spi_checksum
++spi_checksum_wait_0:
++ ldr r1, [r0]
++ tst r1, r2
++ beq spi_checksum_wait_0
++ ldr r0, =0x1e620090
++ ldr r5, [r0] @ record golden checksum
++ ldr r0, =0x1e620080
++ mov r1, #0x0
++ str r1, [r0]
++
++ ldr r0, =0x1e620010 @ set to fast read mode
++ ldr r1, =0x000B0041
++ str r1, [r0]
++
++ ldr r6, =0x00F7E6D0 @ Init spiclk loop
++ mov r8, #0x0 @ Init delay record
++
++spi_cbr_next_clkrate:
++ mov r6, r6, lsr #0x4
++ cmp r6, #0x0
++ beq spi_cbr_end
++
++ mov r7, #0x0 @ Init delay loop
++ mov r8, r8, lsl #4
++
++spi_cbr_next_delay_s:
++ mov r2, #0x8
++ init_spi_checksum
++spi_checksum_wait_1:
++ ldr r1, [r0]
++ tst r1, r2
++ beq spi_checksum_wait_1
++ ldr r0, =0x1e620090
++ ldr r2, [r0] @ read checksum
++ ldr r0, =0x1e620080
++ mov r1, #0x0
++ str r1, [r0]
++ cmp r2, r5
++ bne spi_cbr_next_delay_e
++
++ mov r2, #0x0
++ init_spi_checksum
++spi_checksum_wait_2:
++ ldr r1, [r0]
++ tst r1, r2
++ beq spi_checksum_wait_2
++ ldr r0, =0x1e620090
++ ldr r2, [r0] @ read checksum
++ ldr r0, =0x1e620080
++ mov r1, #0x0
++ str r1, [r0]
++ cmp r2, r5
++ bne spi_cbr_next_delay_e
++
++ orr r8, r8, r7 @ record passed delay
++ b spi_cbr_next_clkrate
++
++spi_cbr_next_delay_e:
++ add r7, r7, #0x1
++ cmp r7, #0x6
++ blt spi_cbr_next_delay_s
++ b spi_cbr_next_clkrate
++
++spi_cbr_end:
++ ldr r0, =0x1e620094
++ str r8, [r0]
++ ldr r0, =0x1e620010
++ mov r1, #0x0
++ str r1, [r0]
++
++platform_exit4:
++
++ /* restore lr */
++ mov lr, r4
++
++ /* back to arch calling code */
++ mov pc, lr
+diff --git a/board/aspeed/ast2300/rc4.c b/board/aspeed/ast2300/rc4.c
+new file mode 100755
+index 0000000..32e0ffa
+--- /dev/null
++++ b/board/aspeed/ast2300/rc4.c
+@@ -0,0 +1,68 @@
++/*
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++ */
++struct rc4_state
++{
++ int x, y, m[256];
++};
++
++void rc4_setup( struct rc4_state *s, unsigned char *key, int length )
++{
++ int i, j, k, *m, a;
++
++ s->x = 0;
++ s->y = 0;
++ m = s->m;
++
++ for( i = 0; i < 256; i++ )
++ {
++ m[i] = i;
++ }
++
++ j = k = 0;
++
++ for( i = 0; i < 256; i++ )
++ {
++ a = m[i];
++ j = (unsigned char) ( j + a + key[k] );
++ m[i] = m[j]; m[j] = a;
++ if( ++k >= length ) k = 0;
++ }
++}
++
++void rc4_crypt( struct rc4_state *s, unsigned char *data, int length )
++{
++ int i, x, y, *m, a, b;
++
++ x = s->x;
++ y = s->y;
++ m = s->m;
++
++ for( i = 0; i < length; i++ )
++ {
++ x = (unsigned char) ( x + 1 ); a = m[x];
++ y = (unsigned char) ( y + a );
++ m[x] = b = m[y];
++ m[y] = a;
++ data[i] ^= m[(unsigned char) ( a + b )];
++ }
++
++ s->x = x;
++ s->y = y;
++}
++
++void rc4_crypt_sw(unsigned char *data, int ulMsgLength, unsigned char *rc4_key, unsigned long ulKeyLength )
++{
++ struct rc4_state s;
++
++ rc4_setup( &s, rc4_key, ulKeyLength );
++
++ rc4_crypt( &s, data, ulMsgLength );
++}
+diff --git a/board/aspeed/ast2300/regtest.c b/board/aspeed/ast2300/regtest.c
+new file mode 100755
+index 0000000..1cd75ae
+--- /dev/null
++++ b/board/aspeed/ast2300/regtest.c
+@@ -0,0 +1,91 @@
++/*
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
++ * MA 02111-1307 USA
++ */
++
++/*
++ * Diagnostics support
++ */
++#include <common.h>
++#include <command.h>
++#include <post.h>
++#include "slt.h"
++
++#if ((CFG_CMD_SLT & CFG_CMD_REGTEST) && defined(CONFIG_SLT))
++#include "regtest.h"
++
++int do_regtest (void)
++{
++ _SOCRegTestInfo *pjSOCRegInfo;
++ _SOCRegTestTbl *pjRegTable;
++ unsigned long ulRegBase;
++ unsigned long ulIndex, ulBack, ulAND, ulMask, ulData, ulTemp;
++ unsigned long Flags = 0;
++
++ /* unlock reg */
++ *(unsigned long *) (0x1e600000) = 0xaeed1a03; /* AHBC */
++ *(unsigned long *) (0x1e6e0000) = 0xfc600309; /* MMC */
++ *(unsigned long *) (0x1e6e2000) = 0x1688a8a8; /* SCU */
++
++ /* SCU */
++
++ /* do test */
++ pjSOCRegInfo = SOCRegTestInfo;
++ while (strcmp(pjSOCRegInfo->jName, "END"))
++ {
++ /* Reg. Test Start */
++ ulRegBase = pjSOCRegInfo->ulRegOffset;
++ pjRegTable = pjSOCRegInfo->pjTblIndex;
++
++ while (pjRegTable->ulIndex != 0xFFFFFFFF)
++ {
++ ulIndex = ulRegBase + pjRegTable->ulIndex;
++
++ ulBack = *(unsigned long *) (ulIndex);
++
++ ulMask = pjRegTable->ulMask;
++ ulAND = ~pjRegTable->ulMask;
++
++ ulData = 0xFFFFFFFF & pjRegTable->ulMask;
++ *(unsigned long *) (ulIndex) = ulData;
++ ulTemp = *(volatile unsigned long *) (ulIndex) & pjRegTable->ulMask;
++ if (ulData != ulTemp)
++ {
++ Flags |= pjSOCRegInfo->ulFlags;
++ printf("[DBG] RegTest: Failed Index:%x, Data:%x, Temp:%x \n", ulIndex, ulData, ulTemp);
++ }
++
++ ulData = 0x00000000 & pjRegTable->ulMask;
++ *(unsigned long *) (ulIndex) = ulData;
++ ulTemp = *(volatile unsigned long *) (ulIndex) & pjRegTable->ulMask;
++ if (ulData != ulTemp)
++ {
++ Flags |= pjSOCRegInfo->ulFlags;
++ printf("[DBG] RegTest: Failed Index:%x, Data:%x, Temp:%x \n", ulIndex, ulData, ulTemp);
++ }
++
++ *(unsigned long *) (ulIndex) = ulBack;
++
++ pjRegTable++;
++
++ } /* Individual Reg. Test */
++
++ if (Flags & pjSOCRegInfo->ulFlags)
++ printf("[INFO] RegTest: %s Failed \n", pjSOCRegInfo->jName);
++
++ pjSOCRegInfo++;
++
++ } /* Reg. Test */
++
++ return Flags;
++
++}
++
++#endif /* CONFIG_SLT */
+diff --git a/board/aspeed/ast2300/regtest.h b/board/aspeed/ast2300/regtest.h
+new file mode 100755
+index 0000000..49a360e
+--- /dev/null
++++ b/board/aspeed/ast2300/regtest.h
+@@ -0,0 +1,255 @@
++/*
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++ */
++typedef struct {
++ unsigned long ulIndex;
++ unsigned long ulMask;
++} _SOCRegTestTbl;
++
++typedef struct {
++ unsigned char jName[10];
++ unsigned long ulRegOffset;
++ _SOCRegTestTbl *pjTblIndex;
++ unsigned long ulFlags;
++} _SOCRegTestInfo;
++
++_SOCRegTestTbl SMCRegTestTbl[] = {
++ {0x00000000, 0x00001FF3},
++ {0x00000004, 0xFFFFFFFF},
++ {0x00000008, 0x0FFF17FF},
++ {0x0000000C, 0xFFFFFFFF},
++ {0x00000010, 0xFF5FFFF3},
++ {0x00000018, 0x0FFFFFFF},
++ {0xFFFFFFFF, 0xFFFFFFFF},
++};
++
++_SOCRegTestTbl AHBCRegTestTbl[] = {
++ {0x00000080, 0x0000FFFE},
++ {0x00000088, 0x01000000},
++ {0x0000008c, 0x00000031},
++ {0xFFFFFFFF, 0xFFFFFFFF},
++};
++
++_SOCRegTestTbl MICRegTestTbl[] = {
++/*
++ {0x00000000, 0x0FFFFFF8},
++ {0x00000004, 0x0FFFFFF8},
++ {0x00000008, 0x0000FFFF},
++ {0x0000000C, 0x0FFFF000},
++ {0x00000010, 0xFFFFFFFF},
++*/
++ {0xFFFFFFFF, 0xFFFFFFFF},
++};
++
++_SOCRegTestTbl MAC1RegTestTbl[] = {
++ {0xFFFFFFFF, 0xFFFFFFFF},
++};
++
++_SOCRegTestTbl MAC2RegTestTbl[] = {
++ {0xFFFFFFFF, 0xFFFFFFFF},
++};
++
++_SOCRegTestTbl USB2RegTestTbl[] = {
++ {0xFFFFFFFF, 0xFFFFFFFF},
++};
++
++_SOCRegTestTbl VICRegTestTbl[] = {
++ {0x0000000C, 0xFFFFFFFF},
++ {0x00000024, 0xFFFFFFFF},
++ {0x00000028, 0xFFFFFFFF},
++ {0x0000002C, 0xFFFFFFFF},
++ {0xFFFFFFFF, 0xFFFFFFFF},
++};
++
++_SOCRegTestTbl MMCRegTestTbl[] = {
++ {0xFFFFFFFF, 0xFFFFFFFF},
++};
++
++_SOCRegTestTbl USB11RegTestTbl[] = {
++ {0xFFFFFFFF, 0xFFFFFFFF},
++};
++
++_SOCRegTestTbl SCURegTestTbl[] = {
++ {0xFFFFFFFF, 0xFFFFFFFF},
++};
++
++_SOCRegTestTbl HASERegTestTbl[] = {
++ {0x00000000, 0x0FFFFFF8},
++ {0x00000004, 0x0FFFFFF8},
++ {0x00000008, 0x0FFFFFF8},
++ {0x0000000C, 0x0FFFFFF8},
++ //{0x00000010, 0x00001FFF},
++ {0x00000020, 0x0FFFFFF8},
++ {0x00000024, 0x0FFFFFF8},
++ {0x00000028, 0x0FFFFFc0},
++ {0x0000002C, 0x0FFFFFFF},
++ //{0x00000030, 0x000003FF},
++ {0xFFFFFFFF, 0xFFFFFFFF},
++};
++
++_SOCRegTestTbl I2SRegTestTbl[] = {
++ {0xFFFFFFFF, 0xFFFFFFFF},
++};
++
++_SOCRegTestTbl CRTRegTestTbl[] = {
++/*
++ {0x00000000, 0x001F3703},
++ {0x00000004, 0x0000FFC1},
++*/
++ {0x00000010, 0x0FFF0FFF},
++ {0x00000014, 0x0FFF0FFF},
++ {0x00000018, 0x07FF07FF},
++ {0x0000001C, 0x07FF07FF},
++ {0x00000020, 0x0FFFFFF8},
++ {0x00000024, 0x07FF3FF8},
++/*
++ {0x00000028, 0x003F003F},
++ {0x00000030, 0x003F003F},
++ {0x00000034, 0x0FFF0FFF},
++ {0x00000038, 0x0FFFFFF8},
++*/
++ {0x00000040, 0x0FFF0FFF},
++ {0x00000044, 0x07FF07FF},
++ {0x00000048, 0x0FFFFFF8},
++ {0x0000004C, 0x00FF07F8},
++ {0x00000050, 0x000F0F0F},
++/*
++ {0x00000060, 0x001F3703},
++ {0x00000064, 0x0000FFC1},
++*/
++ {0x00000070, 0x0FFF0FFF},
++ {0x00000074, 0x0FFF0FFF},
++ {0x00000078, 0x07FF07FF},
++ {0x0000007C, 0x07FF07FF},
++ {0x00000080, 0x0FFFFFF8},
++ {0x00000084, 0x07FF3FF8},
++/*
++ {0x00000088, 0x003F003F},
++ {0x00000090, 0x003F003F},
++ {0x00000094, 0x0FFF0FFF},
++ {0x00000098, 0x0FFFFFF8},
++*/
++ {0x000000A0, 0x0FFF0FFF},
++ {0x000000A4, 0x07FF07FF},
++ {0x000000A8, 0x0FFFFFF8},
++ {0x000000AC, 0x00FF07F8},
++ {0x000000B0, 0x000F0F0F},
++ {0xFFFFFFFF, 0xFFFFFFFF},
++};
++
++_SOCRegTestTbl VIDEORegTestTbl[] = {
++ {0xFFFFFFFF, 0xFFFFFFFF},
++};
++
++_SOCRegTestTbl A2PRegTestTbl[] = {
++ {0xFFFFFFFF, 0xFFFFFFFF},
++};
++
++_SOCRegTestTbl MDMARegTestTbl[] = {
++ {0xFFFFFFFF, 0xFFFFFFFF},
++};
++
++_SOCRegTestTbl M2DRegTestTbl[] = {
++ {0xFFFFFFFF, 0xFFFFFFFF},
++};
++
++_SOCRegTestTbl GPIORegTestTbl[] = {
++ {0xFFFFFFFF, 0xFFFFFFFF},
++};
++
++_SOCRegTestTbl RTCRegTestTbl[] = {
++ {0xFFFFFFFF, 0xFFFFFFFF},
++};
++
++_SOCRegTestTbl TIMERRegTestTbl[] = {
++ {0xFFFFFFFF, 0xFFFFFFFF},
++};
++
++_SOCRegTestTbl UART1RegTestTbl[] = {
++ {0xFFFFFFFF, 0xFFFFFFFF},
++};
++
++_SOCRegTestTbl UART2RegTestTbl[] = {
++ {0xFFFFFFFF, 0xFFFFFFFF},
++};
++
++_SOCRegTestTbl WDTRegTestTbl[] = {
++ {0xFFFFFFFF, 0xFFFFFFFF},
++};
++
++_SOCRegTestTbl PWMRegTestTbl[] = {
++ {0xFFFFFFFF, 0xFFFFFFFF},
++};
++
++_SOCRegTestTbl VUART1RegTestTbl[] = {
++ {0xFFFFFFFF, 0xFFFFFFFF},
++};
++
++_SOCRegTestTbl VUART2RegTestTbl[] = {
++ {0xFFFFFFFF, 0xFFFFFFFF},
++};
++
++_SOCRegTestTbl LPCRegTestTbl[] = {
++ {0xFFFFFFFF, 0xFFFFFFFF},
++};
++
++_SOCRegTestTbl I2CRegTestTbl[] = {
++ {0xFFFFFFFF, 0xFFFFFFFF},
++};
++
++_SOCRegTestTbl PECIRegTestTbl[] = {
++ {0xFFFFFFFF, 0xFFFFFFFF},
++};
++
++_SOCRegTestTbl PCIARegTestTbl[] = {
++ {0xFFFFFFFF, 0xFFFFFFFF},
++};
++
++_SOCRegTestTbl PCIRegTestTbl[] = {
++ {0xFFFFFFFF, 0xFFFFFFFF},
++};
++
++
++/* Test List */
++_SOCRegTestInfo SOCRegTestInfo[] = {
++ /* Test Name, Reg. Offset, Test Table, Error Code */
++ { "SMCREG", 0x16000000, SMCRegTestTbl, 0x00000001},
++ { "AHBCREG", 0x1e600000, AHBCRegTestTbl, 0x00000002},
++ { "MICREG", 0x1e640000, MICRegTestTbl, 0x00000004},
++ { "MAC1REG", 0x1e660000, MAC1RegTestTbl, 0x00000008},
++ { "MAC2REG", 0x1e680000, MAC2RegTestTbl, 0x00000010},
++ { "USB2REG", 0x1e6a0000, USB2RegTestTbl, 0x00000020},
++ { "VICREG", 0x1e6c0000, VICRegTestTbl, 0x00000040},
++ { "MMCREG", 0x1e6e0000, MMCRegTestTbl, 0x00000080},
++ { "USB11REG", 0x1e6e1000, USB11RegTestTbl, 0x00000100},
++ { "SCUREG", 0x1e6e2000, SCURegTestTbl, 0x00000200},
++ { "HASEREG", 0x1e6e3000, HASERegTestTbl, 0x00000400},
++ { "I2SREG", 0x1e6e5000, I2SRegTestTbl, 0x00000800},
++ { "CRTREG", 0x1e6e6000, CRTRegTestTbl, 0x00001000},
++ { "VIDEOREG", 0x1e700000, VIDEORegTestTbl, 0x00002000},
++ { "A2PREG", 0x1e720000, A2PRegTestTbl, 0x00004000},
++ { "MDMAREG", 0x1e740000, MDMARegTestTbl, 0x00008000},
++ { "2DREG", 0x1e760000, M2DRegTestTbl, 0x00010000},
++ { "GPIOREG", 0x1e780000, GPIORegTestTbl, 0x00020000},
++ { "RTCREG", 0x1e781000, RTCRegTestTbl, 0x00040000},
++ { "TIMERREG", 0x1e782000, TIMERRegTestTbl, 0x00080000},
++ { "UART1REG", 0x1e783000, UART1RegTestTbl, 0x00100000},
++ { "UART2REG", 0x1e784000, UART2RegTestTbl, 0x00200000},
++ { "WDTREG", 0x1e785000, WDTRegTestTbl, 0x00400000},
++ { "PWMREG", 0x1e786000, PWMRegTestTbl, 0x00800000},
++ {"VUART1REG", 0x1e787000, VUART1RegTestTbl, 0x01000000},
++ {"VUART2REG", 0x1e788000, VUART2RegTestTbl, 0x02000000},
++ { "LPCREG", 0x1e789000, LPCRegTestTbl, 0x04000000},
++ { "I2CREG", 0x1e78A000, I2CRegTestTbl, 0x08000000},
++ { "PECIREG", 0x1e78B000, PECIRegTestTbl, 0x10000000},
++ { "PCIAREG", 0x1e78C000, PCIARegTestTbl, 0x20000000},
++ { "PCIREG", 0x60000000, PCIRegTestTbl, 0x40000000},
++ { "END", 0xffffffff, NULL, 0xffffffff}
++};
+diff --git a/board/aspeed/ast2300/slt.c b/board/aspeed/ast2300/slt.c
+new file mode 100755
+index 0000000..3283d34
+--- /dev/null
++++ b/board/aspeed/ast2300/slt.c
+@@ -0,0 +1,105 @@
++/*
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
++ * MA 02111-1307 USA
++ */
++
++/*
++ * Diagnostics support
++ */
++#include <common.h>
++#include <command.h>
++#include <post.h>
++#include "slt.h"
++
++#if defined (CONFIG_SLT)
++
++int do_slt (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])
++{
++ int flags = 0;
++ int loop = 1;
++
++ if (argc > 1) {
++ loop = simple_strtoul(argv[1], NULL, 10);
++ }
++
++ do {
++
++do_slt_start:
++ /* Reg. Test */
++#if (CFG_CMD_SLT & CFG_CMD_REGTEST)
++ if (do_regtest())
++ {
++ flags |= FLAG_REGTEST_FAIL;
++ printf("[INFO] RegTest Failed \n");
++ }
++ else
++ printf("[INFO] RegTest Passed \n");
++#endif
++#if (CFG_CMD_SLT & CFG_CMD_MACTEST)
++ if (do_mactest())
++ {
++ flags |= FLAG_MACTEST_FAIL;
++ printf("[INFO] MACTest Failed \n");
++ }
++ else
++ printf("[INFO] MACTest Passed \n");
++#endif
++#if (CFG_CMD_SLT & CFG_CMD_VIDEOTEST)
++ if (do_videotest())
++ {
++ flags |= FLAG_VIDEOTEST_FAIL;
++ printf("[INFO] VideoTest Failed \n");
++ }
++ else
++ printf("[INFO] VideoTest Passed \n");
++#endif
++#if (CFG_CMD_SLT & CFG_CMD_HACTEST)
++ if (do_hactest())
++ {
++ flags |= FLAG_HACTEST_FAIL;
++ printf("[INFO] HACTest Failed \n");
++ }
++ else
++ printf("[INFO] HACTest Passed \n");
++#endif
++#if (CFG_CMD_SLT & CFG_CMD_MICTEST)
++ if (do_mictest())
++ {
++ flags |= FLAG_MICTEST_FAIL;
++ printf("[INFO] MICTest Failed \n");
++ }
++ else
++ printf("[INFO] MICTest Passed \n");
++#endif
++
++ /* Summary */
++ if (flags)
++ printf ("[INFO] SLT Test Failed!! \n");
++ else
++ printf ("[INFO] SLT Test Passed!! \n");
++
++ if (loop == 0) /* infinite */
++ goto do_slt_start;
++ else
++ loop--;
++
++ } while (loop);
++
++ return 0;
++}
++/***************************************************/
++
++U_BOOT_CMD(
++ slt, CONFIG_SYS_MAXARGS, 0, do_slt,
++ "slt - slt test program \n",
++ NULL
++);
++
++#endif /* CONFIG_SLT */
+diff --git a/board/aspeed/ast2300/slt.h b/board/aspeed/ast2300/slt.h
+new file mode 100755
+index 0000000..4e650bc
+--- /dev/null
++++ b/board/aspeed/ast2300/slt.h
+@@ -0,0 +1,29 @@
++/*
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++ */
++#define CFG_CMD_REGTEST 0x00000001
++#define CFG_CMD_MACTEST 0x00000002
++#define CFG_CMD_VIDEOTEST 0x00000004
++#define CFG_CMD_HACTEST 0x00000008
++#define CFG_CMD_MICTEST 0x00000010
++#define CFG_CMD_OSDTEST 0x00000020
++#define CFG_CMD_2DTEST 0x00000040
++#define CFG_CMD_HWCTEST 0x00000080
++
++#define FLAG_REGTEST_FAIL 0x00000001
++#define FLAG_MACTEST_FAIL 0x00000002
++#define FLAG_VIDEOTEST_FAIL 0x00000004
++#define FLAG_HACTEST_FAIL 0x00000008
++#define FLAG_MICTEST_FAIL 0x00000010
++#define FLAG_OSDTEST_FAIL 0x00000020
++#define FLAG_2DTEST_FAIL 0x00000040
++#define FLAG_HWCTEST_FAIL 0x00000080
++
++
+diff --git a/board/aspeed/ast2300/type.h b/board/aspeed/ast2300/type.h
+new file mode 100755
+index 0000000..f57ee5a
+--- /dev/null
++++ b/board/aspeed/ast2300/type.h
+@@ -0,0 +1,116 @@
++/*
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++ */
++#ifndef _TYPE_H_
++#define _TYPE_H_
++
++ typedef unsigned char BOOL;
++ typedef unsigned char UINT8;
++ typedef unsigned short UINT16;
++ typedef unsigned int UINT32;
++
++ #define FLONG unsigned long
++ #define BYTE unsigned char
++ #define INT int
++ #define VOID void
++ #define BOOLEAN unsigned short
++ #define ULONG unsigned long
++ #define USHORT unsigned short
++ #define UCHAR unsigned char
++ #define CHAR char
++ #define LONG long
++ #define PUCHAR UCHAR *
++ #define PULONG ULONG *
++
++ #define FAIL 1
++
++ #define intfunc int386
++
++ #define outdwport outpd
++ #define indwport inpd
++ #define outport outp
++ #define inport inp
++
++ //#define NULL ((void *)0)
++ #define FALSE 0
++ #define TRUE 1
++
++ #define ReadMemoryBYTE(baseaddress,offset) *(BYTE *)((ULONG)(baseaddress)+(ULONG)(offset))
++ #define ReadMemoryLong(baseaddress,offset) *(ULONG *)((ULONG)(baseaddress)+(ULONG)(offset))
++ #define ReadMemoryShort(baseaddress,offset) *(USHORT *)((ULONG)(baseaddress)+(ULONG)(offset))
++ #define WriteMemoryBYTE(baseaddress,offset,data) *(BYTE *)((ULONG)(baseaddress)+(ULONG)(offset)) = (BYTE)(data)
++ #define WriteMemoryLong(baseaddress,offset,data) *(ULONG *)((ULONG)(baseaddress)+(ULONG)(offset))=(ULONG)(data)
++ #define WriteMemoryShort(baseaddress,offset,data) *(USHORT *)((ULONG)(baseaddress)+(ULONG)(offset))=(USHORT)(data)
++ #define WriteMemoryLongWithANDData(baseaddress, offset, anddata, data) *(ULONG *)((ULONG)(baseaddress)+(ULONG)(offset)) = *(ULONG *)((ULONG)(baseaddress)+(ULONG)(offset)) & (ULONG)(anddata) | (ULONG)(data)
++
++ #define WriteMemoryLongWithMASK(baseaddress, offset, data, mask) \
++ *(volatile ULONG *)((ULONG)(baseaddress)+(ULONG)(offset)) = *(volatile ULONG *)(((ULONG)(baseaddress)+(ULONG)(offset)) & (ULONG)(~(mask))) | ((ULONG)(data) & (ULONG)(mask))
++
++ #define ReadMemoryLongHost(baseaddress,offset) *(volatile ULONG *)((ULONG)(baseaddress)+(ULONG)(offset))
++ #define WriteMemoryLongHost(baseaddress,offset,data) *(volatile ULONG *)((ULONG)(baseaddress)+(ULONG)(offset))=(ULONG)(data)
++ #define WriteMemoryBYTEHost(baseaddress,offset,data) *(volatile BYTE *)((ULONG)(baseaddress)+(ULONG)(offset)) = (BYTE)(data)
++#define WriteMemoryLongWithMASKHost(baseaddress, offset, data, mask) *(volatile ULONG *)((ULONG)(baseaddress)+(ULONG)(offset)) = (((*(volatile ULONG *)((ULONG)(baseaddress)+(ULONG)(offset)))&(~mask)) | (ULONG)((data)&(mask)))
++
++ #define ReadMemoryLongClient(baseaddress,offset) *(volatile ULONG *)((ULONG)(baseaddress)+(ULONG)(offset))
++ #define WriteMemoryLongClient(baseaddress,offset,data) *(volatile ULONG *)((ULONG)(baseaddress)+(ULONG)(offset))=(ULONG)(data)
++ #define WriteMemoryBYTEClient(baseaddress,offset,data) *(volatile BYTE *)((ULONG)(baseaddress)+(ULONG)(offset)) = (BYTE)(data)
++#define WriteMemoryLongWithMASKClient(baseaddress, offset, data, mask) *(volatile ULONG *)((ULONG)(baseaddress)+(ULONG)(offset)) = (((*(volatile ULONG *)((ULONG)(baseaddress)+(ULONG)(offset)))&(~mask)) | (ULONG)((data)&(mask)))
++
++#ifdef BUF_GLOBALS
++#define BUF_EXT
++#else
++#define BUF_EXT extern
++#endif
++
++BUF_EXT ULONG g_CAPTURE_VIDEO1_BUF1_ADDR; /* VIDEO1_BUF_1_ADDR*/
++BUF_EXT ULONG g_CAPTURE_VIDEO1_BUF2_ADDR; /* VIDEO1_BUF_2_ADDR*/
++BUF_EXT ULONG g_VIDEO1_COMPRESS_BUF_ADDR; /* Encode destination address */
++BUF_EXT ULONG g_VIDEO1_CRC_BUF_ADDR;
++BUF_EXT ULONG g_VIDEO1_FLAG_BUF_ADDR;
++BUF_EXT ULONG g_VIDEO1_RC4_BUF_ADDR;
++
++
++BUF_EXT ULONG g_CAPTURE_VIDEO2_BUF1_ADDR;
++BUF_EXT ULONG g_CAPTURE_VIDEO2_BUF2_ADDR;
++BUF_EXT ULONG g_VIDEO2_COMPRESS_BUF_ADDR;
++BUF_EXT ULONG g_VIDEO2_CRC_BUF_ADDR;
++BUF_EXT ULONG g_VIDEO2_FLAG_BUF_ADDR;
++BUF_EXT ULONG g_VIDEO2_RC4_BUF_ADDR;
++
++BUF_EXT ULONG g_VIDEO1_DECODE_BUF_1_ADDR;
++BUF_EXT ULONG g_VIDEO1_DECODE_BUF_2_ADDR;
++BUF_EXT ULONG g_VIDEO1_DECOMPRESS_BUF_ADDR;
++BUF_EXT ULONG g_VIDEO1_DECODE_RC4_BUF_ADDR;
++
++BUF_EXT ULONG g_VIDEO2_DECODE_BUF_1_ADDR;
++BUF_EXT ULONG g_VIDEO2_DECODE_BUF_2_ADDR;
++BUF_EXT ULONG g_VIDEO2_DECOMPRESS_BUF_ADDR;
++BUF_EXT ULONG g_VIDEO2_DECODE_RC4_BUF_ADDR;
++
++BUF_EXT ULONG g_CAPTURE_VIDEOM_BUF1_ADDR;
++BUF_EXT ULONG g_CAPTURE_VIDEOM_BUF2_ADDR;
++BUF_EXT ULONG g_VIDEOM_COMPRESS_BUF_ADDR;
++BUF_EXT ULONG g_VIDEOM_FLAG_BUF_ADDR;
++BUF_EXT ULONG g_VIDEOM_RC4_BUF_ADDR;
++
++BUF_EXT ULONG g_VIDEOM_DECODE_BUF_1_ADDR;
++BUF_EXT ULONG g_VIDEOM_DECODE_BUF_2_ADDR;
++BUF_EXT ULONG g_VIDEOM_DECOMPRESS_BUF_ADDR;
++BUF_EXT ULONG g_VIDEOM_DECODE_RC4_BUF_ADDR;
++
++#ifdef WIN_GLOBALS
++#define WIN_EXT
++#else
++#define WIN_EXT extern
++#endif
++
++WIN_EXT USHORT g_DefWidth, g_DefHeight;
++
++#endif
+diff --git a/board/aspeed/ast2300/u-boot.lds b/board/aspeed/ast2300/u-boot.lds
+new file mode 100755
+index 0000000..b5a90ef
+--- /dev/null
++++ b/board/aspeed/ast2300/u-boot.lds
+@@ -0,0 +1,45 @@
++/*
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
++ * MA 02111-1307 USA
++ */
++
++OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm")
++/*OUTPUT_FORMAT("elf32-arm", "elf32-arm", "elf32-arm")*/
++OUTPUT_ARCH(arm)
++ENTRY(_start)
++SECTIONS
++{
++ . = 0x00000000;
++
++ . = ALIGN(4);
++ .text :
++ {
++ cpu/arm926ejs/start.o (.text)
++ *(.text)
++ }
++
++ . = ALIGN(4);
++ .rodata : { *(.rodata) }
++
++ . = ALIGN(4);
++ .data : { *(.data) }
++
++ . = ALIGN(4);
++ .got : { *(.got) }
++
++ __u_boot_cmd_start = .;
++ .u_boot_cmd : { *(.u_boot_cmd) }
++ __u_boot_cmd_end = .;
++
++ . = ALIGN(4);
++ __bss_start = .;
++ .bss : { *(.bss) }
++ _end = .;
++}
+diff --git a/board/aspeed/ast2300/vdef.h b/board/aspeed/ast2300/vdef.h
+new file mode 100755
+index 0000000..3c99b7e
+--- /dev/null
++++ b/board/aspeed/ast2300/vdef.h
+@@ -0,0 +1,500 @@
++/*
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++ */
++#ifndef _VDEF_H_
++#define _VDEF_H_
++
++#define VIDEO1 0
++#define VIDEO1_ON 0x01
++#define VIDEO2 1
++#define VIDEO2_ON 0x02
++
++#define VIDEOM_ON 0x04
++#define VIDEOM 2
++
++#define CRT_1 0
++#define CRT_1_ON 0x01
++#define CRT_2 1
++#define CRT_2_ON 0x02
++
++#define SINGLE_CODEC_SINGLE_CAPTURE 0
++#define AUTO_CODEC_SINGLE_CAPTURE 2
++#define AUTO_CODEC_AUTO_CAPTURE 3
++
++#define MAC1_BASE 0x1E660000
++#define APB_BRIDGE_1_BASE 0x1E6E0000
++#define VIDEO_REG_BASE 0x1E700000
++#define APB_BRIDGE_2_BASE 0x1E780000
++
++#define DRAM_INIT_BASE 0x1E6E0000
++
++#define SDRAM_PROTECT_REG 0x00
++ #define SDRAM_WRITE_DISABLE 0
++ #define SDRAM_WRITE_ENABLE 1
++
++#define SCU_BASE 0x1E6E0000
++#define SCU_OFFSET 0x2000
++
++#define VIC_BASE 0x1E6C0000
++ #define VIDEO_INT_BIT 7
++
++#define IRQ_STATUS_REG 0x00
++#define RAW_INT_STATUS_REG 0x08
++#define INT_SEL_REG 0x0C
++ #define FIQ_INT 1
++ #define IRQ_INT 0
++#define INT_EN_REG 0x10
++#define INT_EN_CLEAR_REG 0x14
++#define INT_SOFT_REG 0x18
++#define INT_SOFT_CLEAR_REG 0x1C
++#define INT_SENSE_REG 0x24
++ #define LEVEL_SENSE 1
++ #define EDGE_SENSE 0
++#define INT_EVENT_REG 0x2C
++ #define HIGH_LEVEL_SENSE 1
++ #define LOW_LEVEL_SENSE 0
++
++#define SCU_HW_TRAPPING_REG 0x70 + SCU_OFFSET
++ #define CLIENT_MODE_EN_BIT 18
++ #define CLIENT_MODE_EN_MASK 0x00040000
++ #define BE_HOST_CHIP 0
++ #define BE_CLIENT_CHIP 1
++
++#define SCU_ULOCK_KEY 0x1688A8A8
++
++#define SCU_PROTECT_REG 0x00 + SCU_OFFSET
++ #define SCU_WRITE_DISABLE 0
++ #define SCU_WRITE_ENABLE 1
++
++#define SCU_CONTROL_REG 0x04 + SCU_OFFSET
++ #define VIDEO_ENGINE_RESET 0x00000040
++ #define VIDEO_ENGINE_RESET_BIT 6
++ #define VIDEO_ENGINE_RESET_MASK 0x00000040
++ #define VIDEO_RESET_EN 1
++ #define VIDEO_RESET_OFF 0
++
++#define SCU_CLOCK_SELECTION_REG 0x08 + SCU_OFFSET
++ #define PORTA_CLOCK_DELAY_MASK 7 << 8 //Video port A output clcok selection
++ #define PORTA_CLOCK_INV_DELAY_1NS 5 << 8 //Clock inversed and delay ~ 2ns
++ #define PORTA_CLOCK_INV_DELAY_2NS 6 << 8 //Clock inversed and delay ~ 3ns
++ #define PORTB_CLOCK_DELAY_MASK 7 << 12 //Video port B output clock delay
++ #define PORTB_CLOCK_INV_DELAY_1NS 5 << 12 //Clock inversed and delay ~ 3ns
++ #define PORTB_CLOCK_INV_DELAY_2NS 6 << 12 //Clock inversed and delay ~ 3ns
++ #define PORTB_CLOCK_SEL 1 << 15 //Video port B clock selection
++ #define PORTB_FROM_D1CLK 0 << 15
++ #define PORTB_FROM_D2CLK 1 << 15
++ #define ECLK_CLK_SEL_MASK (3 << 2)
++ #define ECLK_FROM_HPLL (1 << 2)
++
++ #define D2CLK_CLOCK_SELECTION 0x00020000
++ #define D2CLK_CLOCK_SELECTION_BIT 17
++ #define D2CLK_CLOCK_SELECTION_MASK 0x00060000
++ #define NORMAL_CRT1 0
++ #define V1CLK_VIDEO1 2
++ #define V1CLK_VIDEO2 3
++
++#define SCU_CLOCK_STOP_REG 0x0C + SCU_OFFSET
++ #define EN_ECLK 0 << 0 //Enable ECLK (For Video Engine)
++ #define STOP_ECLK_BIT 0
++ #define STOP_ECLK_MASK 1 << 0
++ #define EN_V1CLK 0 << 3 //Enable V1CLK (For Video Capture #1)
++ #define STOP_V1CLK_BIT 3
++ #define STOP_V1CLK_MASK 1 << 3
++ #define EN_D1CLK 0 << 10 //Enable D1CLK (For CRT1)
++ #define STOP_D1CLK_BIT 10
++ #define STOP_D1CLK_MASK 1 << 10
++ #define EN_D2CLK 0 << 11 //Stop D2CLK (For CRT2)
++ #define STOP_D2CLK (1 << 11)
++ #define STOP_D2CLK_BIT 11
++ #define STOP_D2CLK_MASK 1 << 11
++ #define EN_V2CLK 0 << 12 //Stop V2CLK (For Video Capture #2)
++ #define STOP_V2CLK_BIT 12
++ #define STOP_V2CLK_MASK 1 << 12
++ #define STOP_HACE_BIT 13
++ #define EN_HACE (0 << 13)
++ #define STOP_HACE_MASK (1 << 13)
++ #define EN_I2SCLK 0 << 18
++ #define STOP_I2SCLK_MASK 1 << 18
++
++#define SCU_PIN_CTRL1_REG 0x74 + SCU_OFFSET
++ #define I2C_5_PIN_EN 1 << 12 //Enable I2C #5 PIN
++ #define I2C_5_PIN_OFF 0 << 12 //Disable I2C #5 PIN
++ #define I2C_5_PIN_MASK 1 << 12
++ #define VGA_PIN_OFF 0 << 15 //Enable VGA pins
++ #define VGA_PIN_MASK 1 << 15
++ #define VIDEO_PORTA_EN 1 << 16 //Enable Video port A control pins
++ #define VIDEO_PORTA_MASK 1 << 16
++ #define VIDEO_PORTB_EN 1 << 17 //Enable Video port B control pins
++ #define VIDEO_PORTB_MASK 1 << 17
++ #define VIDEO_VP1_EN 1 << 22 //Enable VP[11:0]
++ #define VIDEO_VP1_MASK 1 << 22
++ #define VIDEO_VP2_EN 1 << 23 //Enable VP[23:12]
++ #define VIDEO_VP2_MASK 1 << 23
++ #define I2S_PIN_EN 1 << 29 //Enable I2S function pins
++ #define I2S_PIN_MASK 1 << 29
++
++#define SCU_PIN_CTRL2_REG 0x78 + SCU_OFFSET
++ #define VIDEO_PORTA_SINGLE_EDGE_MASK 1 << 0
++ #define VIDEO_PORTA_SINGLE_EDGE 1 << 0 //Enable Video port A single mode
++ #define VIDEO_PORTA_DUAL_EDGE 0 << 0
++ #define VIDEO_PORTB_SINGLE_EDGE_MASK 1 << 1
++ #define VIDEO_PORTB_DUAL_EDGE 0 << 1
++ #define VIDEO_PORTB_SINGLE_EDGE 1 << 1 //Enable Video port B single mode
++
++#define SCU_M_PLL_PARAM_REG 0x20 + SCU_OFFSET
++
++#define DRAM_BASE 0x40000000
++
++#define INPUT_BITCOUNT_YUV444 4
++#define INPUT_BITCOUNT_YUV420 2
++
++/* HW comment value */
++//PASSWORD
++#define VIDEO_UNLOCK_KEY 0x1A038AA8
++#define SCU_UNLOCK_KEY 0x1688A8A8
++#define SDRAM_UNLOCK_KEY 0xFC600309
++
++
++//#define SAMPLE_RATE 12000000.0
++#ifdef OSC_NEW
++ #define SAMPLE_RATE 24576000.0
++#else
++ #define SAMPLE_RATE 24000000.0
++#endif
++
++#define MODEDETECTION_VERTICAL_STABLE_MAXIMUM 0x4
++#define MODEDETECTION_HORIZONTAL_STABLE_MAXIMUM 0x4
++#define MODEDETECTION_VERTICAL_STABLE_THRESHOLD 0x4
++#define MODEDETECTION_HORIZONTAL_STABLE_THRESHOLD 0x8
++
++#define MODEDETECTION_EDGE_PIXEL_THRES_DIGITAL 2
++#define MODEDETECTION_EDGE_PIXEL_THRES_ANALOGE 0x0A
++
++#define MODEDETECTION_OK 0
++#define MODEDETECTION_ERROR 1
++#define JUDGE_MODE_ERROR 2
++
++//I2C Loop Count
++#define LOOP_COUNT 1000
++#define CAN_NOT_FIND_DEVICE 1
++#define SET_I2C_DONE 0
++#define I2C_BASE 0xA000
++#define AC_TIMING 0x77743355
++
++//I2C channel and Devices
++#define I2C_VIDEO1_EEPROM 0x2
++#define I2C_VIDEO2_EEPROM 0x5
++#define I2C_VIDEO2_9883 0x4
++/*
++ULONG CAPTURE1_ADDRESS = 0x1000000;
++ULONG CAPTURE2_ADDRESS = 0x3000000;
++ULONG PASS1_ENCODE_SOURCE_ADDRESS = 0x1000000;
++ULONG PASS1_ENCODE_DESTINATION_ADDRESS = 0x2000000;
++ULONG Buffer1_DECODE_SOURCE_ADDRESS = 0x1000000;
++ULONG Buffer2_DECODE_SOURCE_ADDRESS = 0x1400000;
++ULONG PASS1_DECODE_DESTINATION_ADDRESS = 0x600000;
++ULONG CAPTURE_2ND_ADDRESS = 0x1800000;
++ULONG PASS1_2ND_ENCODE_SOURCE_ADDRESS = 0x1800000;
++ULONG PASS1_2ND_ENCODE_DESTINATION_ADDRESS = 0x2800000;
++ULONG PASS1_2ND_DECODE_SOURCE_ADDRESS = 0x1000000;
++ULONG PASS1_2ND_DECODE_DESTINATION_ADDRESS = 0x600000;
++ULONG PASS2_ENCODE_SOURCE_ADDRESS = 0x000000;
++ULONG PASS2_ENCODE_DESTINATION_ADDRESS = 0xC00000;
++ULONG PASS2_DECODE_SOURCE_ADDRESS = 0xC00000;
++ULONG PASS2_DECODE_DESTINATION_ADDRESS = 0x600000;
++ULNG PASS2_DECODE_REFERENCE_ADDRESS = 0x600000;
++*/
++
++typedef struct _CTL_REG_G {
++ ULONG CompressMode:1;
++ ULONG SkipEmptyFrame:1;
++ ULONG MemBurstLen:2;
++ ULONG LineBufEn:2;
++ ULONG Unused:26;
++} CTL_REG_G;
++
++
++typedef union _U_CTL_G {
++ ULONG Value;
++ CTL_REG_G CtlReg;
++} U_CTL_G;
++
++typedef struct _MODE_DETECTION_PARAM_REG {
++ ULONG Unused1:8;
++ ULONG EdgePixelThres:8;
++ ULONG VerStableMax:4;
++ ULONG HorStableMax:4;
++ ULONG VerDiffMax:4;
++ ULONG HorDiffMax:4;
++} MODE_DETECTION_PARAM_REG;
++
++typedef struct _CRC_PRI_PARAM_REG {
++ ULONG Enable:1;
++ ULONG HighBitOnly:1;
++ ULONG SkipCountMax:6;
++ ULONG PolyLow:8;
++ ULONG PolyHigh:16;
++} CRC_PRI_PARAM_REG;
++
++typedef union _U_CRC_PRI_PARAM {
++ ULONG Value;
++ CRC_PRI_PARAM_REG CRCPriParam;
++} U_CRC_PRI_PARAM;
++
++typedef struct _CRC_SEC_PARAM_REG {
++ ULONG Unused1:8;
++ ULONG PolyLow:8;
++ ULONG PolyHigh:16;
++} CRC_SEC_PARAM_REG;
++
++typedef union _U_CRC_SEC_PARAM {
++ ULONG Value;
++ CRC_SEC_PARAM_REG CRCSecParam;
++} U_CRC_SEC_PARAM;
++
++typedef struct _GENERAL_INFO {
++ BYTE EnableVideoM;
++ BYTE CenterMode;
++ BYTE RC4NoResetFrame;
++ BYTE RC4TestMode;
++ U_CTL_G uCtlReg;
++ U_CRC_PRI_PARAM uCRCPriParam;
++ U_CRC_SEC_PARAM uCRCSecParam;
++} GENERAL_INFO, *PGENERAL_INFO;
++
++typedef struct _SEQ_CTL_REG {
++ ULONG Unused1:1;
++ ULONG Unused2:1;
++ ULONG Unused3:1;
++ ULONG CaptureAutoMode:1;
++ ULONG Unused4:1;
++ ULONG CodecAutoMode:1;
++ ULONG Unused5:1;
++ ULONG WatchDog:1;
++ ULONG CRTSel:1;
++ ULONG AntiTearing:1;
++ ULONG DataType:2;
++ ULONG Unused6:20;
++} SEQ_CTL_REG;
++
++typedef union _U_SEQ_CTL {
++ ULONG Value;
++ SEQ_CTL_REG SeqCtlReg;
++} U_SEQ_CTL;
++
++typedef struct _CTL_REG {
++ ULONG SrcHsync:1;
++ ULONG SrcVsync:1;
++ ULONG ExtSrc:1;
++ ULONG AnalongExtSrc:1;
++ ULONG IntTimingGen:1;
++ ULONG IntDataFrom:1;
++ ULONG WriteFmt:2;
++ ULONG VGACursor:1;
++ ULONG LinearMode:1;
++ ULONG ClockDelay:2;
++ ULONG CCIR656Src:1;
++ ULONG PortClock:1;
++ ULONG ExtPort:1;
++ ULONG Unused1:1;
++ ULONG FrameRate:8;
++ ULONG Unused2:8;
++} CTL_REG;
++
++typedef union _U_CTL {
++ ULONG Value;
++ CTL_REG CtlReg;
++} U_CTL_REG;
++
++typedef struct _TIMING_GEN_SETTING_H {
++ ULONG HDEEnd:13;
++ ULONG Unused1:3;
++ ULONG HDEStart:13;
++ ULONG Unused2:3;
++} TIMING_GEN_SETTING_H;
++
++typedef struct _TIMING_GEN_SETTING_V {
++ ULONG VDEEnd:13;
++ ULONG Unused1:3;
++ ULONG VDEStart:13;
++ ULONG Unused2:3;
++} TIMING_GEN_SETTING_V;
++
++typedef struct _BCD_CTL_REG {
++ ULONG Enable:1;
++ ULONG Unused1:15;
++ ULONG Tolerance:8;
++ ULONG Unused2:8;
++} BCD_CTL_REG;
++
++typedef union _U_BCD_CTL {
++ ULONG Value;
++ BCD_CTL_REG BCDCtlReg;
++} U_BCD_CTL;
++
++typedef struct _COMPRESS_WINDOW_REG {
++ ULONG VerLine:13;
++ ULONG Unused1:3;
++ ULONG HorPixel:13;
++ ULONG Unused2:3;
++} COMPRESS_WINDOW_REG;
++
++typedef struct _STREAM_BUF_SIZE {
++ ULONG PacketSize:3;
++ ULONG RingBufNum:2;
++ ULONG Unused1:11;
++ ULONG SkipHighMBThres:7;
++ ULONG SkipTestMode:2;
++ ULONG Unused2:7;
++} STREAM_BUF_SIZE;
++
++typedef union _U_STREAM_BUF {
++ ULONG Value;
++ STREAM_BUF_SIZE StreamBufSize;
++} U_STREAM_BUF;
++
++
++typedef struct _COMPRESS_CTL_REG {
++ ULONG JPEGOnly:1; /* True: Jpeg Only mode(Disable VQ), False:Jpeg and VQ mix mode */
++ ULONG En4VQ:1; /* True: 1, 2, 4 color mode, False: 1,2 color mode */
++ ULONG CodecMode:1; /* High and best Quantization encoding/decoding setting*/
++ ULONG DualQuality:1;
++ ULONG EnBest:1;
++ ULONG EnRC4:1;
++ ULONG NorChromaDCTTable:5;
++ ULONG NorLumaDCTTable:5;
++ ULONG EnHigh:1;
++ ULONG TestCtl:2;
++ ULONG UVFmt:1;
++ ULONG HufTable:2;
++ ULONG AlterValue1:5;
++ ULONG AlterValue2:5;
++} COMPRESS_CTL_REG;
++
++typedef union _U_COMPRESS_CTL {
++ ULONG Value;
++ COMPRESS_CTL_REG CompressCtlReg;
++} U_COMPRESS_CTL;
++
++typedef struct _QUANTI_TABLE_LOW_REG {
++ ULONG ChromaTable:5;
++ ULONG LumaTable:5;
++ ULONG Unused1:22;
++} QUANTI_TABLE_LOW_REG;
++
++typedef union _U_CQUANTI_TABLE_LOW {
++ ULONG Value;
++ QUANTI_TABLE_LOW_REG QTableLowReg;
++} U_QUANTI_TABLE_LOW;
++
++typedef struct _QUANTI_VALUE_REG {
++ ULONG High:15;
++ ULONG Unused1:1;
++ ULONG Best:15;
++ ULONG Unused2:1;
++} QUANTI_VALUE_REG;
++
++typedef union _U_QUANTI_VALUE {
++ ULONG Value;
++ QUANTI_VALUE_REG QValueReg;
++} U_QUANTI_VALUE;
++
++typedef struct _BSD_PARAM_REG {
++ ULONG HighThres:8;
++ ULONG LowThres:8;
++ ULONG HighCount:6;
++ ULONG Unused1:2;
++ ULONG LowCount:6;
++ ULONG Unused2:2;
++} BSD_PARAM_REG;
++
++typedef union _U_BSD_PARAM {
++ ULONG Value;
++ BSD_PARAM_REG BSDParamReg;
++} U_BSD_PARAM;
++
++typedef struct _VIDEO_INFO {
++ BYTE ExtADCAct; /* read from modection register */
++ BYTE EnableRC4;
++ BYTE DownScalingMethod;
++ USHORT AnalogDifferentialThreshold; /* BCD tolerance */
++ USHORT DigitalDifferentialThreshold; /* BCD tolerance */
++ USHORT DstWidth;
++ USHORT DstHeight;
++ USHORT SrcWidth;
++ USHORT SrcHeight;
++ BYTE HighLumaTable; /* if High and best Jpeg codec enable, use HighLumaTable and HighChromaTable, otherwise HighDeQuantiValue and BestDequantiValue*/
++ BYTE HighChromaTable;
++ BYTE HighDeQuantiValue;
++ BYTE BestDequantiValue;
++ U_SEQ_CTL uSeqCtlReg;
++ U_CTL_REG uCtlReg;
++ U_BCD_CTL uBCDCtlReg;
++ U_STREAM_BUF uStreamBufSize;
++ U_COMPRESS_CTL uCompressCtlReg;
++ U_QUANTI_TABLE_LOW uQTableLowReg;
++ U_QUANTI_VALUE uQValueReg;
++ U_BSD_PARAM uBSDParamReg;
++} VIDEO_INFO, *PVIDEO_INFO ;
++
++typedef struct _VIDEOM_SEQ_CTL_REG {
++ ULONG Unused1:1; //Bit 0
++ ULONG Unused2:1; //Bit 1
++ ULONG Unused3:1; //Bit 2
++ ULONG StreamMode:1; //Bit 3
++ ULONG Unused4:1; //Bit 4
++ ULONG CodecAutoMode:1; //Bit 5
++ ULONG Unused6:1; //Bit 6
++ ULONG Unused7:1; //Bit 7
++ ULONG SrcSel:1; //Bit 8
++ ULONG Unused9:1; //Bit 9
++ ULONG DataType:2; //Bit[11:10]
++ ULONG Unused12:20;
++} VIDEOM_SEQ_CTL_REG;
++
++typedef union _U_VIDEOM_SEQ_CTL {
++ ULONG Value;
++ VIDEOM_SEQ_CTL_REG SeqCtlReg;
++} U_VIDEOM_SEQ_CTL;
++
++typedef struct _VIDEOM_INFO {
++ BYTE DownScalingMethod;
++ USHORT AnalogDifferentialThreshold; /* BCD tolerance */
++ USHORT DigitalDifferentialThreshold; /* BCD tolerance */
++ USHORT DstWidth;
++ USHORT DstHeight;
++ USHORT SrcWidth;
++ USHORT SrcHeight;
++ BYTE HighLumaTable; /* if High and best Jpeg codec enable, use HighLumaTable and HighChromaTable, otherwise HighDeQuantiValue and BestDequantiValue*/
++ BYTE HighChromaTable;
++ BYTE HighDeQuantiValue;
++ BYTE BestDequantiValue;
++ BYTE PacketSize; //the same as video1 & video2
++ BYTE RingBufNum;
++ BYTE EnableRC4;
++ U_VIDEOM_SEQ_CTL uSeqCtlReg;
++ U_BCD_CTL uBCDCtlReg;
++ U_COMPRESS_CTL uCompressCtlReg;
++ U_QUANTI_TABLE_LOW uQTableLowReg;
++ U_QUANTI_VALUE uQValueReg;
++ U_BSD_PARAM uBSDParamReg;
++} VIDEOM_INFO, *PVIDEOM_INFO ;
++
++typedef struct _VIDEO_MODE_INFO
++{
++ USHORT X;
++ USHORT Y;
++ USHORT ColorDepth;
++ USHORT RefreshRate;
++ BYTE ModeIndex;
++} VIDEO_MODE_INFO, *PVIDEO_MODE_INFO;
++
++#endif
++
+diff --git a/board/aspeed/ast2300/vesa.h b/board/aspeed/ast2300/vesa.h
+new file mode 100755
+index 0000000..69aba90
+--- /dev/null
++++ b/board/aspeed/ast2300/vesa.h
+@@ -0,0 +1,163 @@
++/*
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++ */
++#ifndef _VESA_H_
++#define _VESA_H_
++
++typedef enum
++{
++ VCLK25_175 = 0x00,
++ VCLK28_322 = 0x01,
++ VCLK31_5 = 0x02,
++ VCLK31_574 = 0x03,
++ VCLK32_76 = 0x04,
++ VCLK33_154 = 0x05,
++ VCLK36 = 0x06,
++ VCLK40 = 0x07,
++ VCLK45_978 = 0x08,
++ VCLK49_5 = 0x09,
++ VCLK50 = 0x0A,
++ VCLK52_95 = 0x0B,
++ VCLK56_25 = 0x0C,
++ VCLK65 = 0x0D,
++ VCLK74_48 = 0x0E,
++ VCLK75 = 0x0F,
++ VCLK78_75 = 0x10,
++ VCLK79_373 = 0x11,
++ VCLK81_624 = 0x12,
++ VCLK83_462 = 0x13,
++ VCLK84_715 = 0x14,
++ VCLK94_5 = 0x15,
++ VCLK106_5 = 0x16,
++ VCLK108 = 0x17,
++ VCLK119 = 0x18,
++ VCLK135 = 0x19,
++ VCLK136_358 = 0x1A,
++ VCLK146_25 = 0x1B,
++ VCLK154 = 0x1C,
++ VCLK157_5 = 0x1D,
++ VCLK162 = 0x1E
++} ePIXEL_CLOCK;
++
++typedef struct {
++ USHORT HorizontalTotal;
++ USHORT VerticalTotal;
++ USHORT HorizontalActive;
++ USHORT VerticalActive;
++ BYTE RefreshRate;
++ double HorizontalFrequency;
++ USHORT HSyncTime;
++ USHORT HBackPorch;
++ USHORT VSyncTime;
++ USHORT VBackPorch;
++ USHORT HLeftBorder;
++ USHORT HRightBorder;
++ USHORT VBottomBorder;
++ USHORT VTopBorder;
++ USHORT PixelClock;
++ BOOL HorPolarity;
++ BOOL VerPolarity;
++ BYTE ADCIndex1;
++ BYTE ADCIndex2;
++ BYTE ADCIndex3;
++ BYTE ADCIndex5;
++ BYTE ADCIndex6;
++ BYTE ADCIndex7;
++ BYTE ADCIndex8;
++ BYTE ADCIndex9;
++ BYTE ADCIndexA;
++ BYTE ADCIndexF;
++ BYTE ADCIndex15;
++ int HorizontalShift;
++ int VerticalShift;
++} VESA_MODE;
++
++#define HOR_POSITIVE 0
++#define HOR_NEGATIVE 1
++#define VER_POSITIVE 0
++#define VER_NEGATIVE 1
++
++#ifdef VESA_GLOBALS
++
++// Note: Modified for modes which have border issue
++VESA_MODE vModeTable[] = {
++////////////////////////// 60Hz mode
++// 720x480 done
++ {1056, 497, 720, 480, 60, 29.900, 88, 104, 3, 13, 0, 0, 0, 0, VCLK31_574, HOR_NEGATIVE, VER_NEGATIVE, 0x41, 0xF0, 0x48, 0x05, 0x20, 0x58, 0x60, 0x60, 0x60, 0x5E, 0xFE, 6, 2},
++// 848x480 done
++ {1064, 517, 848, 480, 60, 31.160, 88, 91, 3, 26, 0, 0, 0, 0, VCLK33_154, HOR_NEGATIVE, VER_NEGATIVE, 0x42, 0x70, 0x48, 0x05, 0x20, 0x58, 0x60, 0x60, 0x60, 0x5E, 0xFE, 6, 2},
++ {800, 525, 640, 480, 60, 31.469, 96, 40, 2, 25, 1, 1, 8, 8, VCLK25_175, HOR_NEGATIVE, VER_NEGATIVE, 0x31, 0xF0, 0x48, 0x05, 0x20, 0x60, 0x60, 0x60, 0x60, 0x5E, 0xFE, 6, 2},
++// 720x576
++ {912, 597, 720, 576, 60, 35.920, 72, 88, 3, 17, 0, 0, 0, 0, VCLK32_76, HOR_NEGATIVE, VER_NEGATIVE, 0x38, 0xF0, 0x48, 0x05, 0x20, 0x48, 0x60, 0x60, 0x60, 0x5E, 0xFE, 6, 2},
++// 960x600 GTF done
++ {1232, 622, 960, 600, 60, 37.320, 96, 136, 3, 18, 0, 0, 0, 0, VCLK45_978, HOR_NEGATIVE, VER_NEGATIVE, 0x4C, 0xF0, 0x60, 0x05, 0x20, 0x60, 0x60, 0x60, 0x60, 0x5E, 0xFE, -1, 0},
++ {1056, 628, 800, 600, 60, 37.879, 128, 88, 4, 23, 0, 0, 0, 0, VCLK40, HOR_POSITIVE, VER_POSITIVE, 0x41, 0xF0, 0x60, 0x05, 0x20, 0x80, 0x60, 0x60, 0x60, 0x5E, 0xFE, -1, 0},
++// 1088x612 GTF done
++ {1392, 634, 1088, 612, 60, 38.04, 112, 152, 3, 18, 0, 0, 0, 0, VCLK52_95, HOR_NEGATIVE, VER_NEGATIVE, 0x56, 0xF0, 0x60, 0x05, 0x20, 0x70, 0x60, 0x60, 0x60, 0x5E, 0xFE, -1, 0},
++// 1280x720 GTF done
++ {1664, 746, 1280, 720, 60, 44.760, 136, 192, 3, 22, 0, 0, 0, 0, VCLK74_48, HOR_NEGATIVE, VER_NEGATIVE, 0x67, 0xF0, 0xA8, 0x05, 0x20, 0x88, 0x60, 0x60, 0x60, 0x5E, 0xFE, -1, 0},
++// 1360x768 GTF done
++ {1776, 795, 1360, 768, 60, 47.700, 144, 208, 3, 23, 0, 0, 0, 0, VCLK84_715, HOR_NEGATIVE, VER_NEGATIVE, 0x6E, 0xF0, 0xA8, 0x05, 0x20, 0x90, 0x60, 0x60, 0x60, 0x5E, 0xFE, 7, 1},
++// 1280x768 done
++ {1664, 798, 1280, 768, 60, 47.700, 128, 184, 7, 20, 0, 0, 0, 0, VCLK79_373, HOR_NEGATIVE, VER_NEGATIVE, 0x67, 0xF0, 0xA8, 0x05, 0x20, 0x80, 0x60, 0x60, 0x60, 0x5E, 0xFE, 7, 1},
++ {1344, 806, 1024, 768, 60, 48.363, 136, 160, 6, 29, 0, 0, 0, 0, VCLK65, HOR_NEGATIVE, VER_NEGATIVE, 0x53, 0xF0, 0xA8, 0x05, 0x20, 0x88, 0x60, 0x60, 0x60, 0x5E, 0xFE, -1, 7},
++// 1280x800 GTF done
++ {1680, 828, 1280, 800, 60, 49.680, 136, 200, 3, 24, 0, 0, 0, 0, VCLK83_462, HOR_NEGATIVE, VER_NEGATIVE, 0x68, 0xF0, 0xA8, 0x05, 0x20, 0x88, 0x60, 0x60, 0x60, 0x5E, 0xFE, -1, 0},
++// 1152x864 GTF done
++ {1520, 895, 1152, 864, 60, 53.700, 120, 184, 3, 27, 0, 0, 0, 0, VCLK81_624, HOR_NEGATIVE, VER_NEGATIVE, 0x5E, 0xF0, 0xA8, 0x05, 0x20, 0x78, 0x60, 0x60, 0x60, 0x5E, 0xFE, -1, 0},
++// 1600x900 GTF done
++ {2128, 932, 1600, 900, 60, 55.920, 168, 264, 3, 28, 0, 0, 0, 0, VCLK119, HOR_NEGATIVE, VER_NEGATIVE, 0x84, 0xF0, 0xA8, 0x05, 0x20, 0xA8, 0x60, 0x60, 0x60, 0x5E, 0xFE, -1, 0},
++// 1440X900 CVT done
++ {1904, 933, 1440, 900, 60, 55.935, 152, 232, 6, 25, 0, 0, 0, 0, VCLK106_5, HOR_NEGATIVE, VER_POSITIVE, 0x76, 0xF0, 0xA8, 0x05, 0x20, 0x96, 0x60, 0x60, 0x60, 0x5E, 0xFE, -1, 0},
++ {1800, 1000, 1280, 960, 60, 60.000, 112, 312, 3, 36, 0, 0, 0, 0, VCLK108, HOR_POSITIVE, VER_POSITIVE, 0x70, 0x70, 0xA8, 0x05, 0x20, 0x70, 0x60, 0x60, 0x60, 0x5E, 0xFE, -1, 0},
++// 1600x1024 GTF done
++ {2144, 1060, 1600, 1024, 60, 63.600, 168, 272, 3, 32, 0, 0, 0, 0, VCLK136_358, HOR_NEGATIVE, VER_NEGATIVE, 0x85, 0xF0, 0xE8, 0x05, 0x20, 0xA8, 0x60, 0x60, 0x60, 0x5E, 0xFE, -1, 0},
++ {1688, 1066, 1280, 1024, 60, 63.981, 112, 248, 3, 38, 0, 0, 0, 0, VCLK108, HOR_POSITIVE, VER_POSITIVE, 0x69, 0x70, 0xA8, 0x05, 0x20, 0x70, 0x60, 0x60, 0x60, 0x5E, 0xFE, -1, 0},
++// 1680X1050 CVT done Reduced Blanking
++ {1840, 1080, 1680, 1050, 60, 64.674, 32, 80, 6, 21, 0, 0, 0, 0, VCLK119, HOR_POSITIVE, VER_NEGATIVE, 0x72, 0xF0, 0xA8, 0x05, 0x20, 0x20, 0x60, 0x60, 0x60, 0x5E, 0xFE, -1, 0},
++// 1920X1200 CVT done Reduced Blanking
++ {2080, 1235, 1920, 1200, 60, 74.038, 32, 80, 6, 26, 0, 0, 0, 0, VCLK154, HOR_POSITIVE, VER_NEGATIVE, 0x81, 0xF0, 0xA8, 0x05, 0x20, 0x20, 0x60, 0x60, 0x60, 0x5E, 0xFE, -1, 0},
++ //{2160, 1250, 1600, 1200, 60,75.000, 192, 304, 3, 46, 0, 0, 0, 0, VCLK162, HOR_POSITIVE, VER_POSITIVE},
++ {2160, 1248, 1600, 1200, 60, 75.000, 192, 304, 3, 46, 0, 0, 0, 0, VCLK162, HOR_POSITIVE, VER_POSITIVE, 0x86, 0xF0, 0xE8, 0x05, 0x20, 0xC0, 0x60, 0x60, 0x60, 0x5E, 0xFE, -1, 0},
++
++////////////////////// Not 60Hz mode
++ {900, 449, 720, 400, 70, 31.469, 108, 45, 2, 25, 1, 1, 8, 8, 0, HOR_NEGATIVE, VER_NEGATIVE, 0x38, 0x30, 0x48, 0x05, 0x20, 0x6C, 0x60, 0x60, 0x60, 0x5E, 0xFE, 6, 1},
++ {832, 520, 640, 480, 72, 37.861, 40, 120, 3, 20, 1, 1, 8, 8, 0, HOR_NEGATIVE, VER_NEGATIVE, 0x33, 0xF0, 0x48, 0x05, 0x20, 0x28, 0x60, 0x60, 0x60, 0x5E, 0xFE, 6, 3},
++ {840, 500, 640, 480, 75, 37.500, 64, 120, 3, 16, 0, 0, 0, 0, 0, HOR_NEGATIVE, VER_NEGATIVE, 0x34, 0x70, 0x48, 0x05, 0x20, 0x40, 0x60, 0x60, 0x60, 0x5E, 0xFE, -1, 3},
++ {832, 509, 640, 480, 85, 43.269, 56, 80, 3, 25, 0, 0, 0, 0, 0, HOR_NEGATIVE, VER_NEGATIVE, 0x33, 0xF0, 0x48, 0x05, 0x20, 0x38, 0x60, 0x60, 0x60, 0x5E, 0xFE, -1, 3},
++ {1024, 625, 800, 600, 56, 35.156, 72, 128, 2, 22, 0, 0, 0, 0, 0, HOR_POSITIVE, VER_POSITIVE, 0x3F, 0xF0, 0x60, 0x05, 0x20, 0x48, 0x60, 0x60, 0x60, 0x5E, 0xFE, -1, 0},
++ {1040, 666, 800, 600, 72, 48.077, 120, 64, 6, 23, 0, 0, 0, 0, 0, HOR_POSITIVE, VER_POSITIVE, 0x40, 0xF0, 0x60, 0x05, 0x20, 0x78, 0x60, 0x60, 0x60, 0x5E, 0xFE, -1, 0},
++ {1056, 625, 800, 600, 75, 46.875, 80, 160, 3, 21, 0, 0, 0, 0, 0, HOR_POSITIVE, VER_POSITIVE, 0x41, 0xF0, 0x60, 0x05, 0x20, 0x50, 0x60, 0x60, 0x60, 0x5E, 0xFE, -1, 0},
++ {1048, 631, 800, 600, 85, 53.674, 64, 152, 3, 27, 0, 0, 0, 0, 0, HOR_POSITIVE, VER_POSITIVE, 0x41, 0x70, 0x60, 0x05, 0x20, 0x40, 0x60, 0x60, 0x60, 0x5E, 0xFE, -1, 0},
++ {1328, 806, 1024, 768, 70, 56.476, 136, 144, 6, 29, 0, 0, 0, 0, 0, HOR_NEGATIVE, VER_NEGATIVE, 0x52, 0xF0, 0xA8, 0x05, 0x20, 0x88, 0x60, 0x60, 0x60, 0x5E, 0xFE, -1, 7},
++ {1312, 800, 1024, 768, 75, 60.023, 96, 176, 3, 28, 0, 0, 0, 0, 0, HOR_POSITIVE, VER_POSITIVE, 0x51, 0xF0, 0xA8, 0x05, 0x20, 0x60, 0x60, 0x60, 0x60, 0x5E, 0xFE, -1, 1},
++ {1376, 808, 1024, 768, 85, 68.677, 96, 208, 3, 36, 0, 0, 0, 0, 0, HOR_POSITIVE, VER_POSITIVE, 0x55, 0xF0, 0xA8, 0x05, 0x20, 0x60, 0x60, 0x60, 0x60, 0x5E, 0xFE, -1, 1},
++ {1600, 900, 1152, 864, 75, 67.500, 128, 256, 3, 32, 0, 0, 0, 0, 0, HOR_POSITIVE, VER_POSITIVE, 0x63, 0xF0, 0xA8, 0x05, 0x20, 0x80, 0x60, 0x60, 0x60, 0x5E, 0xFE, -1, 0},
++ {1728, 1011, 1280, 960, 85, 85.938, 160, 224, 3, 47, 0, 0, 0, 0, 0, HOR_POSITIVE, VER_POSITIVE, 0x6B, 0xF0, 0xA8, 0x05, 0x20, 0xA0, 0x60, 0x60, 0x60, 0x5E, 0xFE, -1, 0},
++ {1688, 1066, 1280, 1024, 75, 79.976, 144, 248, 3, 38, 0, 0, 0, 0, 0, HOR_POSITIVE, VER_POSITIVE, 0x69, 0x70, 0xE8, 0x05, 0x20, 0x90, 0x60, 0x60, 0x60, 0x5E, 0xFE, -1, 0},
++ {1728, 1072, 1280, 1024, 85, 91.146, 160, 224, 3, 44, 0, 0, 0, 0, 0, HOR_POSITIVE, VER_POSITIVE, 0x6B, 0xF0, 0xA8, 0x05, 0x20, 0xA0, 0x60, 0x60, 0x60, 0x5E, 0xFE, -1, 0},
++ {2160, 1250, 1600, 1200, 65, 81.250, 192, 304, 3, 46, 0, 0, 0, 0, 0, HOR_POSITIVE, VER_POSITIVE, 0x86, 0xF0, 0xA8, 0x05, 0x20, 0xC0, 0x60, 0x60, 0x60, 0x5E, 0xFE, -1, 0},
++ {2160, 1250, 1600, 1200, 70, 87.500, 192, 304, 3, 46, 0, 0, 0, 0, 0, HOR_POSITIVE, VER_POSITIVE, 0x86, 0xF0, 0xA8, 0x05, 0x20, 0xC0, 0x60, 0x60, 0x60, 0x5E, 0xFE, -1, 0},
++ {2160, 1250, 1600, 1200, 75, 93.750, 192, 304, 3, 46, 0, 0, 0, 0, 0, HOR_POSITIVE, VER_POSITIVE, 0x86, 0xF0, 0xA8, 0x05, 0x20, 0xC0, 0x60, 0x60, 0x60, 0x5E, 0xFE, -1, 0},
++ {2160, 1250, 1600, 1200, 85, 106.250,192, 304, 3, 46, 0, 0, 0, 0, 0, HOR_POSITIVE, VER_POSITIVE, 0x86, 0xF0, 0xA8, 0x05, 0x20, 0xC0, 0x60, 0x60, 0x60, 0x5E, 0xFE, -1, 0}
++};
++
++USHORT ModeNumberCount = sizeof (vModeTable) / sizeof (VESA_MODE);
++USHORT Mode60HZCount = 21;
++
++#else /* NOT VESA_GLOBALS */
++extern VESA_MODE vModeTable[];
++extern USHORT ModeNumberCount;
++extern USHORT Mode60HZCount;
++#endif
++
++#endif /* _VESA_H_ */
++
++
+diff --git a/board/aspeed/ast2300/vfun.c b/board/aspeed/ast2300/vfun.c
+new file mode 100755
+index 0000000..f707e80
+--- /dev/null
++++ b/board/aspeed/ast2300/vfun.c
+@@ -0,0 +1,545 @@
++/*
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++ */
++#define BUF_GLOBALS
++#include "type.h"
++#include "vdef.h"
++#include "vreg.h"
++#include "crt.h"
++#include "vfun.h"
++
++ULONG UnlockSCURegHost(ULONG MMIOBase, ULONG Key)
++{
++ WriteMemoryLongHost(SCU_BASE, SCU_PROTECT_REG, Key);
++ return ReadMemoryLongHost(SCU_BASE,SCU_PROTECT_REG);
++}
++
++void ResetVideoHost(void)
++{
++ WriteMemoryLongWithMASKHost(SCU_BASE, SCU_CONTROL_REG, VIDEO_RESET_EN << VIDEO_ENGINE_RESET_BIT, VIDEO_ENGINE_RESET_MASK);
++ WriteMemoryLongWithMASKHost(SCU_BASE, SCU_CONTROL_REG, VIDEO_RESET_OFF << VIDEO_ENGINE_RESET_BIT, VIDEO_ENGINE_RESET_MASK);
++}
++
++void StartModeDetectionTriggerHost(ULONG MMIOBase, ULONG offset)
++{
++ WriteMemoryLongWithMASKHost(VIDEO_REG_BASE, offset, 0, MODE_DETECTION_TRIGGER);
++ WriteMemoryLongWithMASKHost(VIDEO_REG_BASE, offset, MODE_DETECTION_TRIGGER, MODE_DETECTION_TRIGGER);
++}
++
++BOOL ReadVideoInterruptHost(ULONG MMIOBase, ULONG value)
++{
++ return ((ReadMemoryLongHost(VIDEO_REG_BASE, VIDEO_INT_CONTROL_READ_REG) & value) ? TRUE : FALSE);
++}
++
++ULONG UnlockVideoRegHost(ULONG MMIOBase, ULONG Key)
++{
++ WriteMemoryLongHost(VIDEO_REG_BASE, KEY_CONTROL_REG, Key);
++ return ReadMemoryLongHost(VIDEO_REG_BASE,KEY_CONTROL_REG);
++}
++
++void StartVideoCaptureTriggerHost(ULONG MMIOBase, ULONG offset)
++{
++ WriteMemoryLongWithMASKHost(VIDEO_REG_BASE, offset, 0, VIDEO_CAPTURE_TRIGGER);
++ WriteMemoryLongWithMASKHost(VIDEO_REG_BASE, offset, VIDEO_CAPTURE_TRIGGER, VIDEO_CAPTURE_TRIGGER);
++}
++
++void StartVideoCodecTriggerHost(ULONG MMIOBase, ULONG offset)
++{
++ WriteMemoryLongWithMASKHost(VIDEO_REG_BASE, offset, 0, VIDEO_CODEC_TRIGGER);
++ WriteMemoryLongWithMASKHost(VIDEO_REG_BASE, offset, VIDEO_CODEC_TRIGGER, VIDEO_CODEC_TRIGGER);
++}
++
++void StopModeDetectionTriggerHost(ULONG MMIOBase, ULONG offset)
++{
++ WriteMemoryLongWithMASKHost(VIDEO_REG_BASE, offset, 0, MODE_DETECTION_TRIGGER);
++}
++
++void ClearVideoInterruptHost(ULONG MMIOBase, ULONG value)
++{
++ //WriteMemoryLongWithMASKHost(VIDEO_REG_BASE, VIDEO_INT_CONTROL_CLEAR_REG, value, value);
++ WriteMemoryLongHost(VIDEO_REG_BASE, VIDEO_INT_CONTROL_CLEAR_REG, value);
++}
++
++/* UnLock SCU Host and Reset Engine */
++BOOL CheckOnStartHost(void)
++{
++ int i=0, dwValue=0;
++
++ do
++ {
++ dwValue = UnlockSCURegHost(0, SCU_UNLOCK_KEY);
++ i++;
++ }
++ while ((SCU_WRITE_ENABLE != dwValue) && (i<10));
++
++ //Clear SCU Reset Register
++ WriteMemoryLongHost(SCU_BASE, SCU_CONTROL_REG, 0);
++
++ WriteMemoryLongWithMASKHost(SCU_BASE, SCU_CLOCK_STOP_REG, (EN_ECLK | EN_V1CLK | EN_V2CLK), (STOP_ECLK_MASK | STOP_V1CLK_MASK | STOP_V2CLK_MASK));
++
++#if defined(CONFIG_AST2300)
++ WriteMemoryLongWithMASKHost(SCU_BASE, (0x90 + SCU_OFFSET), 0x00000020, 0x00000030); //enable 24bits
++ WriteMemoryLongWithMASKHost(SCU_BASE, (0x88 + SCU_OFFSET), 0x000fff00, 0x000fff00); //enable video multi-pins
++#else //AST2100
++ //WriteMemoryLongWithMASKHost(SCU_BASE, SCU_PIN_CTRL1_REG, (VIDEO_PORTA_EN | VIDEO_PORTB_EN | VIDEO_VP1_EN | VIDEO_VP2_EN) ,
++ // (VIDEO_PORTA_MASK | VIDEO_PORTB_MASK | VIDEO_VP1_MASK | VIDEO_VP2_MASK));
++ WriteMemoryLongWithMASKHost(SCU_BASE, SCU_PIN_CTRL2_REG, (VIDEO_PORTA_SINGLE_EDGE | VIDEO_PORTB_SINGLE_EDGE) ,
++ (VIDEO_PORTA_SINGLE_EDGE_MASK | VIDEO_PORTB_SINGLE_EDGE_MASK));
++#endif
++
++ ResetVideoHost();
++
++ return TRUE;
++}
++
++BOOL CheckOnStartClient(void)
++{
++ int i=0, dwValue=0;
++
++ do
++ {
++ dwValue = UnlockSCURegHost(0, SCU_UNLOCK_KEY);
++ i++;
++ }
++ while ((SCU_WRITE_ENABLE != dwValue) && (i<10));
++
++ //Clear SCU Reset Register
++ WriteMemoryLongClient(SCU_BASE, SCU_CONTROL_REG, 0);
++
++ WriteMemoryLongWithMASKClient(SCU_BASE, SCU_CLOCK_STOP_REG, (EN_ECLK | EN_V1CLK | EN_D1CLK | EN_D2CLK | EN_V2CLK),
++ (STOP_ECLK_MASK | STOP_D1CLK_MASK | STOP_D2CLK_MASK | STOP_V1CLK_MASK | STOP_V2CLK_MASK));
++
++ //WriteMemoryLongWithMASKClient(SCU_BASE, SCU_CLOCK_SELECTION_REG, PORTB_FROM_D2CLK | PORTB_CLOCK_INV_DELAY_3NS | PORTA_CLOCK_INV_DELAY_3NS, PORTB_CLOCK_SEL | PORTB_CLOCK_DELAY_MASK | PORTA_CLOCK_DELAY_MASK);
++ //A1EVA
++ WriteMemoryLongWithMASKClient(SCU_BASE, SCU_CLOCK_SELECTION_REG, (PORTB_FROM_D2CLK | PORTB_CLOCK_INV_DELAY_1NS | PORTA_CLOCK_INV_DELAY_1NS), (PORTB_CLOCK_SEL | PORTB_CLOCK_DELAY_MASK | PORTA_CLOCK_DELAY_MASK));
++ WriteMemoryLongWithMASKClient(SCU_BASE, 0x202C, (0x03<<9), (0x03<<9));
++
++ WriteMemoryLongWithMASKClient(SCU_BASE, SCU_PIN_CTRL1_REG, (VIDEO_PORTA_EN | VIDEO_PORTB_EN | VIDEO_VP1_EN | VIDEO_VP2_EN),
++ (VIDEO_PORTA_MASK | VIDEO_PORTB_MASK | VIDEO_VP1_MASK | VIDEO_VP2_MASK));
++
++#if CONFIG_AST3000
++ WriteMemoryLongWithMASKClient(SCU_BASE, SCU_PIN_CTRL2_REG, (VIDEO_PORTA_DUAL_EDGE | VIDEO_PORTB_DUAL_EDGE),
++ (VIDEO_PORTA_SINGLE_EDGE_MASK | VIDEO_PORTB_SINGLE_EDGE_MASK));
++#else
++ //2100 is single edge
++ WriteMemoryLongWithMASKClient(SCU_BASE, SCU_PIN_CTRL2_REG, (VIDEO_PORTA_SINGLE_EDGE | VIDEO_PORTB_SINGLE_EDGE),
++ (VIDEO_PORTA_SINGLE_EDGE_MASK | VIDEO_PORTB_SINGLE_EDGE_MASK));
++#endif
++
++ WriteMemoryLongWithMASKClient(SCU_BASE, SCU_CLOCK_STOP_REG, (EN_D1CLK | EN_D2CLK), (STOP_D1CLK_MASK | STOP_D2CLK_MASK));
++ WriteMemoryLongWithMASKClient(SCU_BASE, SCU_PIN_CTRL1_REG, VGA_PIN_OFF, VGA_PIN_MASK);
++
++ //ResetVideoHost();
++
++ return TRUE;
++}
++
++ULONG InitializeVideoEngineHost (ULONG MMIOBase,
++ int nVideo,
++ BOOL HorPolarity,
++ BOOL VerPolarity)
++{
++ //ULONG temp, temp1, temp2;
++ ULONG dwRegOffset = nVideo * 0x100;
++ ULONG dwValue;
++ int i;
++
++
++ /* General Video Control */
++ //LineBufEn 0
++ //dwValue = (COMPRESS_MODE << CODEC_DECOMPRESS_MODE_BIT) | DELAY_VSYNC_EN;
++ dwValue = 0;
++ WriteMemoryLongHost(VIDEO_REG_BASE, VIDEO_CONTROL_REG, dwValue);
++ //Video Data Truncation Register
++ WriteMemoryLongHost(VIDEO_REG_BASE, 0x328, 0);
++
++ //D2CLK clock must config according to video's line buffer
++ if (VIDEO1 == nVideo)
++ dwValue = LINE_BUFFER_VIDEO1;
++ else
++ dwValue = LINE_BUFFER_VIDEO2;
++
++ //D2CLK clock must config according to video's line buffer
++ switch (dwValue)
++ {
++ case LINE_BUFFER_OFF:
++ WriteMemoryLongWithMASKHost(SCU_BASE, SCU_CLOCK_SELECTION_REG, NORMAL_CRT1, D2CLK_CLOCK_SELECTION_MASK);
++ WriteMemoryLongWithMASKHost(SCU_BASE, SCU_CLOCK_STOP_REG, STOP_D2CLK, STOP_D2CLK_MASK);
++ break;
++ case LINE_BUFFER_VIDEO1:
++ WriteMemoryLongWithMASKHost(SCU_BASE, SCU_CLOCK_SELECTION_REG, V1CLK_VIDEO1 << D2CLK_CLOCK_SELECTION_BIT, D2CLK_CLOCK_SELECTION_MASK);
++ WriteMemoryLongWithMASKHost(SCU_BASE, SCU_CLOCK_STOP_REG, EN_D2CLK, STOP_D2CLK_MASK);
++ break;
++ case LINE_BUFFER_VIDEO2:
++ WriteMemoryLongWithMASKHost(SCU_BASE, SCU_CLOCK_SELECTION_REG, V1CLK_VIDEO2 << D2CLK_CLOCK_SELECTION_BIT, D2CLK_CLOCK_SELECTION_MASK);
++ WriteMemoryLongWithMASKHost(SCU_BASE, SCU_CLOCK_STOP_REG, EN_D2CLK, STOP_D2CLK_MASK);
++ break;
++ case LINE_BUFFER_VIDEOM:
++ //If select this option, it will config at videoM INIT
++ break;
++ default:
++ break;
++ }
++
++ dwValue = 0;
++ //VR30 now is capture window in the compression
++ dwValue = g_DefHeight << CAPTURE_VER_LINE_BIT |
++ g_DefWidth << CAPTURE_HOR_PIXEL_BIT;
++ WriteMemoryLongHost(VIDEO_REG_BASE, VIDEO1_CAPTURE_WINDOWS_REG + dwRegOffset, dwValue);
++
++ dwValue = 0;
++ //VR34 now is destionation window in the compression
++ dwValue = g_DefHeight << COMPRESS_VER_LINE_BIT |
++ g_DefWidth << COMPRESS_HOR_PIXEL_BIT;
++
++ WriteMemoryLongHost(VIDEO_REG_BASE, VIDEO1_COMPRESS_WINDOWS_REG + dwRegOffset, dwValue);
++
++ //BitCOUNT according compress data format
++ dwValue = YUV444_MODE;
++ if (YUV444_MODE == dwValue)
++ WriteMemoryLongWithMASKHost(VIDEO_REG_BASE, VIDEO1_BUF_LINE_OFFSET_REG + dwRegOffset, g_DefWidth * INPUT_BITCOUNT_YUV444, BUF_LINE_OFFSET_MASK);
++ else
++ WriteMemoryLongWithMASKHost(VIDEO_REG_BASE, VIDEO1_BUF_LINE_OFFSET_REG + dwRegOffset, g_DefWidth * INPUT_BITCOUNT_YUV420, BUF_LINE_OFFSET_MASK);
++
++ // CRC
++ //Disable
++ WriteMemoryLongHost(VIDEO_REG_BASE, VIDEO_CRC_PRIMARY_REG, 0x0);
++ WriteMemoryLongHost(VIDEO_REG_BASE, VIDEO_CRC_SECOND_REG, 0x0);
++
++ /* Sequence Control register */
++ //Oonly Encoder need to set
++ /* Engine Sequence Contol Register */
++ dwValue = (WATCH_DOG_EN << WATCH_DOG_ENABLE_BIT) |
++ VIDEO_CAPTURE_AUTO_MODE |
++ VIDEO_CODEC_AUTO_MODE;
++
++ WriteMemoryLongHost(VIDEO_REG_BASE, VIDEO1_ENGINE_SEQUENCE_CONTROL_REG + dwRegOffset, dwValue);
++
++ /* Control register */
++ dwValue = (HOR_NEGATIVE == HorPolarity) ? NO_INVERSE_POL : INVERSE_POL;
++ dwValue = (((VER_NEGATIVE == VerPolarity) ? NO_INVERSE_POL : INVERSE_POL) << VIDEO_VSYNC_POLARITY_BIT) | dwValue;
++
++ /* HW Recommand*/
++ //dwValue = (TILE_MODE << 9) | dwValue;
++ dwValue = (EXTERNAL_VGA_SOURCE << EXTERNAL_SOURCE_BIT) | dwValue;
++
++ WriteMemoryLongHost(VIDEO_REG_BASE, VIDEO1_CONTROL_REG + dwRegOffset, dwValue);
++
++ /* BCD register */
++ //NO BCD
++ dwValue = 0;
++ WriteMemoryLongHost(VIDEO_REG_BASE, VIDEO1_BCD_CONTROL_REG + dwRegOffset, dwValue);
++
++ /* Stream Buffer Size register */
++ dwValue = (YUV_TEST << SKIP_TEST_MODE_BIT) |
++ (PACKET_SIZE_32KB << STREAM_PACKET_SIZE_BIT) |
++ (PACKETS_8 << RING_BUF_PACKET_NUM_BIT);
++ /* the same with Video1, Video2, and VideoM*/
++ WriteMemoryLongHost(VIDEO_REG_BASE, VIDEO1_STREAM_BUF_SIZE, dwValue);
++
++ /* Comression control register */
++ dwValue = (USE_UV_CIR656 << UV_CIR656_FORMAT_BIT)|
++ (JPEG_MIX_MODE << JPEG_ONLY_BIT)|
++ (VQ_4_COLOR_MODE << VQ_4_COLOR_BIT)|
++ (QUANTI_CODEC_MODE << QUALITY_CODEC_SETTING_BIT)|
++ (7 << NORMAL_QUANTI_CHROMI_TABLE_BIT) |
++ (23 << NORMAL_QUANTI_LUMI_TABLE_BIT);
++
++ //Video2 have same value as video1
++ WriteMemoryLongHost(VIDEO_REG_BASE, VIDEO1_COMPRESS_CONTROL_REG, dwValue);
++
++ /* JPEG Quantization Table register */
++ dwValue = 0;
++ WriteMemoryLongHost(VIDEO_REG_BASE, VIDEO1_QUANTI_TABLE_LOW_REG, dwValue);
++
++ /* Quantization value register */
++ //Video2 have same value as video1
++ dwValue = 0;
++ WriteMemoryLongHost(VIDEO_REG_BASE, VIDEO1_QUANTI_VALUE_REG, dwValue);
++
++ //Video BSD Parameter Register
++ //Video2 have same value as video1
++ dwValue = 0;
++ WriteMemoryLongHost(VIDEO_REG_BASE, VIDEO1_BSD_PARA_REG, dwValue);
++
++ //no scale
++ WriteMemoryLongHost(VIDEO_REG_BASE, VIDEO1_SCALE_FACTOR_REG, 0x10001000);
++ WriteMemoryLongHost(VIDEO_REG_BASE, VIDEO1_SCALE_FACTOR_PARAMETER0_REG, 0x00200000);
++ WriteMemoryLongHost(VIDEO_REG_BASE, VIDEO1_SCALE_FACTOR_PARAMETER1_REG, 0x00200000);
++ WriteMemoryLongHost(VIDEO_REG_BASE, VIDEO1_SCALE_FACTOR_PARAMETER2_REG, 0x00200000);
++ WriteMemoryLongHost(VIDEO_REG_BASE, VIDEO1_SCALE_FACTOR_PARAMETER3_REG, 0x00200000);
++ return TRUE;
++}
++
++ULONG InitializeVideoEngineClient (ULONG MMIOBase,
++ int nVideo)
++{
++ //ULONG temp, temp1, temp2;
++ ULONG dwRegOffset = nVideo * 0x100;
++ ULONG dwValue;
++ int i;
++
++
++ /* General Video Control */
++ //LineBufEn 0
++ dwValue = (DECOMPRESS_MODE << CODEC_DECOMPRESS_MODE_BIT);
++ WriteMemoryLongHost(VIDEO_REG_BASE, VIDEO_CONTROL_REG, dwValue);
++ //Video Data Truncation Register
++ WriteMemoryLongHost(VIDEO_REG_BASE, 0x328, 0);
++
++ //VR30 now is capture window in the compression
++ dwValue = g_DefHeight << CAPTURE_VER_LINE_BIT |
++ g_DefWidth << CAPTURE_HOR_PIXEL_BIT;
++ WriteMemoryLongWithMASKHost(VIDEO_REG_BASE, VIDEO1_CAPTURE_WINDOWS_REG + dwRegOffset, dwValue, CAPTURE_VER_LINE_MASK | CAPTURE_HOR_PIXEL_MASK);
++
++ //VR34 now is destionation window in the compression
++ dwValue = g_DefHeight << COMPRESS_VER_LINE_BIT |
++ g_DefWidth << COMPRESS_HOR_PIXEL_BIT;
++
++ WriteMemoryLongWithMASKHost(VIDEO_REG_BASE, VIDEO1_COMPRESS_WINDOWS_REG + dwRegOffset, dwValue, COMPRESS_VER_LINE_MASK | COMPRESS_HOR_PIXEL_MASK);
++
++ //BitCOUNT according compress data format
++ dwValue = YUV444_MODE;
++ if (YUV444_MODE == dwValue)
++ WriteMemoryLongWithMASKHost(VIDEO_REG_BASE, VIDEO1_BUF_LINE_OFFSET_REG + dwRegOffset, g_DefWidth * INPUT_BITCOUNT_YUV444, BUF_LINE_OFFSET_MASK);
++ else
++ WriteMemoryLongWithMASKHost(VIDEO_REG_BASE, VIDEO1_BUF_LINE_OFFSET_REG + dwRegOffset, g_DefWidth * INPUT_BITCOUNT_YUV420, BUF_LINE_OFFSET_MASK);
++
++ // CRC
++ //Disable
++ WriteMemoryLongHost(VIDEO_REG_BASE, VIDEO_CRC_PRIMARY_REG, 0x0);
++ WriteMemoryLongHost(VIDEO_REG_BASE, VIDEO_CRC_SECOND_REG, 0x0);
++
++ /* Sequence Control register */
++ //Oonly Encoder need to set
++ /* Engine Sequence Contol Register */
++ dwValue = VIDEO_CAPTURE_AUTO_MODE |
++ VIDEO_CODEC_AUTO_MODE;
++
++ WriteMemoryLongHost(VIDEO_REG_BASE, VIDEO1_ENGINE_SEQUENCE_CONTROL_REG + dwRegOffset, dwValue);
++
++ /* Control register */
++ /* HW Recommand*/
++ dwValue = (TILE_MODE << 9);
++
++ WriteMemoryLongHost(VIDEO_REG_BASE, VIDEO1_CONTROL_REG + dwRegOffset, dwValue);
++
++ /* BCD register */
++ //NO BCD
++ dwValue = 0;
++ WriteMemoryLongHost(VIDEO_REG_BASE, VIDEO1_BCD_CONTROL_REG + dwRegOffset, dwValue);
++
++ /* Stream Buffer Size register */
++ dwValue = (YUV_TEST << SKIP_TEST_MODE_BIT) |
++ (PACKET_SIZE_32KB << STREAM_PACKET_SIZE_BIT) |
++ (PACKETS_8 << RING_BUF_PACKET_NUM_BIT);
++ /* the same with Video1, Video2, and VideoM*/
++ WriteMemoryLongHost(VIDEO_REG_BASE, VIDEO1_STREAM_BUF_SIZE, dwValue);
++
++
++ /* Comression control register */
++ dwValue = (USE_UV_CIR656 << UV_CIR656_FORMAT_BIT)|
++ (JPEG_MIX_MODE << JPEG_ONLY_BIT)|
++ (VQ_4_COLOR_MODE << VQ_4_COLOR_BIT)|
++ (QUANTI_CODEC_MODE << QUALITY_CODEC_SETTING_BIT)|
++ (7 << NORMAL_QUANTI_CHROMI_TABLE_BIT) |
++ (23 << NORMAL_QUANTI_LUMI_TABLE_BIT);
++
++ //Video2 have same value as video1
++ if (VIDEO1 == nVideo)
++ {
++ WriteMemoryLongHost(VIDEO_REG_BASE, VIDEO1_COMPRESS_CONTROL_REG, dwValue);
++ }
++ else
++ {
++ WriteMemoryLongHost(VIDEO_REG_BASE, VIDEOM_COMPRESS_CONTROL_REG, dwValue);
++ }
++
++ /* JPEG Quantization Table register */
++ dwValue = 0;
++ WriteMemoryLongHost(VIDEO_REG_BASE, VIDEO1_QUANTI_TABLE_LOW_REG, dwValue);
++
++ /* Quantization value register */
++ //Video2 have same value as video1
++ dwValue = 0;
++ WriteMemoryLongHost(VIDEO_REG_BASE, VIDEO1_QUANTI_VALUE_REG, dwValue);
++
++ //Video BSD Parameter Register
++ //Video2 have same value as video1
++ dwValue = 0;
++ WriteMemoryLongHost(VIDEO_REG_BASE, VIDEO1_BSD_PARA_REG, dwValue);
++
++ return TRUE;
++}
++
++BYTE GetI2CRegClient(ULONG MMIOBase,
++ BYTE DeviceSelect,
++ BYTE DeviceAddress,
++ BYTE RegisterIndex)
++{
++ BYTE Data;
++ ULONG Status;
++
++// Reset
++ WriteMemoryLongClient(APB_BRIDGE_2_BASE, I2C_BASE + DeviceSelect * 0x40 + 0x00, 0);
++// Set AC Timing and Speed
++ WriteMemoryLongClient(APB_BRIDGE_2_BASE, I2C_BASE + DeviceSelect * 0x40 + 0x04, AC_TIMING);
++// Lower Speed
++// WriteMemoryLongWithANDData (VideoEngineInfo->VGAPCIInfo.ulMMIOBaseAddress, I2C_BASE + DeviceSelect * 0x40 + 0x04, 0, 0x33317805);
++ WriteMemoryLongClient(APB_BRIDGE_2_BASE, I2C_BASE + DeviceSelect * 0x40 + 0x08, 0);
++// Clear Interrupt
++ WriteMemoryLongClient(APB_BRIDGE_2_BASE, I2C_BASE + DeviceSelect * 0x40 + 0x10, 0xFFFFFFFF);
++// Enable Master Mode
++ WriteMemoryLongClient(APB_BRIDGE_2_BASE, I2C_BASE + DeviceSelect * 0x40 + 0x00, 1);
++// Enable Interrupt
++ WriteMemoryLongClient(APB_BRIDGE_2_BASE, I2C_BASE + DeviceSelect * 0x40 + 0x0C, 0xAF);
++// BYTE I2C Mode
++// Start and Send Device Address
++ WriteMemoryLongClient(APB_BRIDGE_2_BASE, I2C_BASE + DeviceSelect * 0x40 + 0x20, DeviceAddress);
++ WriteMemoryLongClient(APB_BRIDGE_2_BASE, I2C_BASE + DeviceSelect * 0x40 + 0x14, 0x3);
++// Wait TX ACK
++ do {
++ Status = ReadMemoryLongClient(APB_BRIDGE_2_BASE, I2C_BASE + DeviceSelect * 0x40 + 0x10) & 0x03;
++ } while (Status != 1);
++// Clear Interrupt
++ WriteMemoryLongClient(APB_BRIDGE_2_BASE, I2C_BASE + DeviceSelect * 0x40 + 0x10, 0xFFFFFFFF);
++// Send Device Register Index
++ WriteMemoryLongClient(APB_BRIDGE_2_BASE, I2C_BASE + DeviceSelect * 0x40 + 0x20, RegisterIndex);
++ WriteMemoryLongClient(APB_BRIDGE_2_BASE, I2C_BASE + DeviceSelect * 0x40 + 0x14, 0x2);
++// Wait Tx ACK
++ do {
++ Status = ReadMemoryLongClient(APB_BRIDGE_2_BASE, I2C_BASE + DeviceSelect * 0x40 + 0x10) & 0x03;
++ } while (Status != 1);
++// Clear Interrupt
++ WriteMemoryLongClient(APB_BRIDGE_2_BASE, I2C_BASE + DeviceSelect * 0x40 + 0x10, 0xFFFFFFFF);
++// Start, Send Device Address + 1(Read Mode), Receive Data
++ WriteMemoryLongClient(APB_BRIDGE_2_BASE, I2C_BASE + DeviceSelect * 0x40 + 0x20, DeviceAddress + 1);
++ WriteMemoryLongClient(APB_BRIDGE_2_BASE, I2C_BASE + DeviceSelect * 0x40 + 0x14, 0x1B);
++// Wait Rx Done
++ do {
++ Status = (ReadMemoryLongClient(APB_BRIDGE_2_BASE, I2C_BASE + DeviceSelect * 0x40 + 0x10) & 0x04) >> 2;
++ } while (Status != 1);
++// Clear Interrupt
++ WriteMemoryLongClient(APB_BRIDGE_2_BASE, I2C_BASE + DeviceSelect * 0x40 + 0x10, 0xFFFFFFFF);
++
++// Enable STOP Interrupt
++ WriteMemoryLongWithMASKClient(APB_BRIDGE_2_BASE, I2C_BASE + DeviceSelect * 0x40 + 0x0C, 0x10, 0x10);
++// Issue STOP Command
++ WriteMemoryLongClient(APB_BRIDGE_2_BASE, I2C_BASE + DeviceSelect * 0x40 + 0x14, 0x20);
++// Wait STOP
++ do {
++ Status = (ReadMemoryLongClient(APB_BRIDGE_2_BASE, I2C_BASE + DeviceSelect * 0x40 + 0x10) & 0x10) >> 4;
++ } while (Status != 1);
++// Disable STOP Interrupt
++ WriteMemoryLongClient(APB_BRIDGE_2_BASE, I2C_BASE + DeviceSelect * 0x40 + 0x0C, 0x10);
++// Clear Interrupt
++ WriteMemoryLongClient(APB_BRIDGE_2_BASE, I2C_BASE + DeviceSelect * 0x40 + 0x10, 0xFFFFFFFF);
++// Read Received Data
++ Data = (BYTE)((ReadMemoryLongClient(APB_BRIDGE_2_BASE, I2C_BASE + DeviceSelect * 0x40 + 0x20) & 0xFF00) >> 8);
++
++ return Data;
++}
++
++ULONG SetI2CRegClient(ULONG MMIOBase,
++ BYTE DeviceSelect,
++ BYTE DeviceAddress,
++ BYTE RegisterIndex,
++ BYTE RegisterValue)
++{
++ ULONG Status;
++ ULONG Count = 0;
++
++// Reset
++ WriteMemoryLongClient(APB_BRIDGE_2_BASE, I2C_BASE + DeviceSelect * 0x40 + 0x00, 0);
++// Set Speed
++ WriteMemoryLongClient(APB_BRIDGE_2_BASE, I2C_BASE + DeviceSelect * 0x40 + 0x04, AC_TIMING);
++// Lower Speed
++// WriteMemoryLongWithANDData (VideoEngineInfo->VGAPCIInfo.ulMMIOBaseAddress, I2C_BASE + DeviceSelect * 0x40 + 0x04, 0, 0x33317805);
++ WriteMemoryLongClient(APB_BRIDGE_2_BASE, I2C_BASE + DeviceSelect * 0x40 + 0x08, 0);
++// Clear Interrupt
++ WriteMemoryLongClient(APB_BRIDGE_2_BASE, I2C_BASE + DeviceSelect * 0x40 + 0x10, 0xFFFFFFFF);
++// Enable Master Mode
++ WriteMemoryLongClient(APB_BRIDGE_2_BASE, I2C_BASE + DeviceSelect * 0x40 + 0x00, 1);
++// Enable Interrupt
++ WriteMemoryLongClient(APB_BRIDGE_2_BASE, I2C_BASE + DeviceSelect * 0x40 + 0x0C, 0xAF);
++// BYTE I2C Mode
++// Start and Send Device Address
++ WriteMemoryLongClient(APB_BRIDGE_2_BASE, I2C_BASE + DeviceSelect * 0x40 + 0x20, DeviceAddress);
++ WriteMemoryLongClient(APB_BRIDGE_2_BASE, I2C_BASE + DeviceSelect * 0x40 + 0x14, 0x3);
++// Wait Tx ACK
++ do {
++ Count++;
++ Status = ReadMemoryLongClient(APB_BRIDGE_2_BASE, I2C_BASE + DeviceSelect * 0x40 + 0x10) & 0x03;
++
++ if (2 == Status)
++ {
++ //Clear Interrupt
++ WriteMemoryLongClient(APB_BRIDGE_2_BASE, I2C_BASE + DeviceSelect * 0x40 + 0x10, 0xFFFFFFFF);
++ //Re-Send Start and Send Device Address while NACK return
++ WriteMemoryLongClient(APB_BRIDGE_2_BASE, I2C_BASE + DeviceSelect * 0x40 + 0x20, DeviceAddress);
++ WriteMemoryLongClient(APB_BRIDGE_2_BASE, I2C_BASE + DeviceSelect * 0x40 + 0x14, 0x3);
++ }
++ //else
++ {
++ if (Count > LOOP_COUNT) {
++ return CAN_NOT_FIND_DEVICE;
++ }
++ }
++ } while (Status != 1);
++ Count = 0;
++// Clear Interrupt
++ WriteMemoryLongClient(APB_BRIDGE_2_BASE, I2C_BASE + DeviceSelect * 0x40 + 0x10, 0xFFFFFFFF);
++// Send Device Register Index
++ WriteMemoryLongClient(APB_BRIDGE_2_BASE, I2C_BASE + DeviceSelect * 0x40 + 0x20, RegisterIndex);
++ WriteMemoryLongClient(APB_BRIDGE_2_BASE, I2C_BASE + DeviceSelect * 0x40 + 0x14, 0x2);
++// Wait Tx ACK
++ do {
++ Count++;
++ Status = ReadMemoryLongClient(APB_BRIDGE_2_BASE, I2C_BASE + DeviceSelect * 0x40 + 0x10) & 0x03;
++ if (Count > LOOP_COUNT) {
++ return CAN_NOT_FIND_DEVICE;
++ }
++ } while (Status != 1);
++ Count = 0;
++// Clear Interrupt
++ WriteMemoryLongClient(APB_BRIDGE_2_BASE, I2C_BASE + DeviceSelect * 0x40 + 0x10, 0xFFFFFFFF);
++// Send Device Register Value and Stop
++ WriteMemoryLongClient(APB_BRIDGE_2_BASE, I2C_BASE + DeviceSelect * 0x40 + 0x20, RegisterValue);
++ WriteMemoryLongClient(APB_BRIDGE_2_BASE, I2C_BASE + DeviceSelect * 0x40 + 0x14, 0x2);
++// Wait Tx ACK
++ do {
++ Count++;
++ Status = ReadMemoryLongClient(APB_BRIDGE_2_BASE, I2C_BASE + DeviceSelect * 0x40 + 0x10) & 0x03;
++ if (Count > LOOP_COUNT) {
++ return CAN_NOT_FIND_DEVICE;
++ }
++ } while (Status != 1);
++ Count = 0;
++// Clear Interrupt
++ WriteMemoryLongClient(APB_BRIDGE_2_BASE, I2C_BASE + DeviceSelect * 0x40 + 0x10, 0xFFFFFFFF);
++// Enable STOP Interrupt
++ WriteMemoryLongWithMASKClient(APB_BRIDGE_2_BASE, I2C_BASE + DeviceSelect * 0x40 + 0x0C, 0x10, 0x10);
++// Issue STOP Command
++ WriteMemoryLongClient(APB_BRIDGE_2_BASE, I2C_BASE + DeviceSelect * 0x40 + 0x14, 0x20);
++// Wait STOP
++ do {
++ Count++;
++ Status = (ReadMemoryLongClient(APB_BRIDGE_2_BASE, I2C_BASE + DeviceSelect * 0x40 + 0x10) & 0x10) >> 4;
++ if (Count > LOOP_COUNT) {
++ return CAN_NOT_FIND_DEVICE;
++ }
++ } while (Status != 1);
++// Disable STOP Interrupt
++ WriteMemoryLongWithMASKClient(APB_BRIDGE_2_BASE, I2C_BASE + DeviceSelect * 0x40 + 0x0C, 0, 0x10);
++// Clear Interrupt
++ WriteMemoryLongClient(APB_BRIDGE_2_BASE, I2C_BASE + DeviceSelect * 0x40 + 0x10, 0xFFFFFFFF);
++
++ return SET_I2C_DONE;
++}
+diff --git a/board/aspeed/ast2300/vfun.h b/board/aspeed/ast2300/vfun.h
+new file mode 100755
+index 0000000..90f9ec4
+--- /dev/null
++++ b/board/aspeed/ast2300/vfun.h
+@@ -0,0 +1,79 @@
++/*
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++ */
++#ifndef _VFUN_H_
++#define _VFUN_H_
++
++//#define vBufAlign(x) ((x + 0x0000007F) & 0xFFFFFF80) //128 byte alignment
++#define vBufAlign(x) ((x + 0x000003FF) & 0xFFFFFC00) //128 byte alignment
++#define vBufAlign2(x) ((x + 0x0000FFFF) & 0xFFFF0000) //128 byte alignment
++#define v16byteAlign(x) ((x + 0x0000000F) & 0xFFFFFFF0)
++#define vBuf_ALIGNMENT 128
++
++#define HOST_TOTAL_SIZE 0x8000000 /* 128M */
++#define STATION_TOTAL_SIZE 0xF800000 /* 120M */
++
++#define VIDEO_SOURCE_SIZE 0x200000 /* 800X600X4 = 0x1D4C00 */
++#define VIDEO_MAX_STREAM_SIZE 0x400000 /* 32X128K = 0x400000 */
++#define VIDEO_FLAG_SIZE 0x5000 /* 1920X1200/128 = 0x4650*/
++#define VIDEO_CRC_SIZE 0x50000 /* 1920/64X1200X8 = 0x46500*/
++
++#define VIDEO1_EN_TOTAL_SIZE (VIDEO_SOURCE_SIZE*2+VIDEO_MAX_STREAM_SIZE+VIDEO_FLAG_SIZE+VIDEO_CRC_SIZE) /* 0x1655000 = about 23M*/
++#define VIDEO2_EN_TOTAL_SIZE VIDEO1_EN_TOTAL_SIZE
++//#define VIDEOM_EN_TOTAL_SIZE (VIDEO_SOURCE_SIZE*2+VIDEO_MAX_STREAM_SIZE+VIDEO_FLAG_SIZE) /* 0x1605000 = about 22.7M */
++//#define VIDEO_HOST_SIZE (VIDEO1_EN_TOTAL_SIZE + VIDEO2_EN_TOTAL_SIZE + VIDEOM_EN_TOTAL_SIZE) /* 0x69922816 = about 70M */
++#define VIDEO_HOST_SIZE (VIDEO1_EN_TOTAL_SIZE + VIDEO2_EN_TOTAL_SIZE) /* NOT NEED VIDEOM */
++
++#define VIDEO1_EN_BASE 0x100000
++#define VIDEO2_EN_BASE (VIDEO1_EN_BASE + VIDEO1_EN_TOTAL_SIZE)
++#define VIDEOM_EN_BASE (VIDEO2_EN_BASE + VIDEO2_EN_TOTAL_SIZE)
++
++#define VIDEO1_DE_TOTAL_SIZE (VIDEO_MAX_STREAM_SIZE + VIDEO_SOURCE_SIZE) /* 0xD00000 = 13M*/
++#define VIDEO2_DE_TOTAL_SIZE (VIDEO1_DE_TOTAL_SIZE)
++#define VIDEO_STATION_SIZE (VIDEO1_DE_TOTAL_SIZE + VIDEO2_DE_TOTAL_SIZE) /* 26M */
++
++#define VIDEO1_DE_BASE VIDEO_HOST_SIZE
++#define VIDEO2_DE_BASE (VIDEO1_DE_BASE + VIDEO1_DE_TOTAL_SIZE)
++#define VIDEO_ALL_SIZE (VIDEO_HOST_SIZE + VIDEO_STATION_SIZE) //Host and Station
++
++#define OutdwmBankModeHost(offset,data) WriteMemoryLongHost(DRAM_BASE,offset,data)
++#define IndwmBankModeHost(offset) ReadMemoryLongHost(DRAM_BASE,offset)
++
++ULONG UnlockVideoRegHost(ULONG MMIOBase, ULONG Key);
++BOOL CheckOnStartHost(void);
++BOOL CheckOnStartClient(void);
++void StartVideoCaptureTriggerHost(ULONG MMIOBase, ULONG offset);
++void StartVideoCaptureTriggerHost(ULONG MMIOBase, ULONG offset);
++void StartVideoCodecTriggerHost(ULONG MMIOBase, ULONG offset);
++ULONG UnlockSCURegHost(ULONG MMIOBase, ULONG Key);
++ULONG UnlockSCURegHost(ULONG MMIOBase, ULONG Key);
++void StartModeDetectionTriggerHost(ULONG MMIOBase, ULONG offset);
++void ClearVideoInterruptHost(ULONG MMIOBase, ULONG value);
++BOOL ReadVideoInterruptHost(ULONG MMIOBase, ULONG value);
++void StopModeDetectionTriggerHost(ULONG MMIOBase, ULONG offset);
++void ResetVideoHost(void);
++ULONG InitializeVideoEngineHost (ULONG MMIOBase,
++ int nVideo,
++ BOOL HorPolarity,
++ BOOL VerPolarity);
++ULONG InitializeVideoEngineClient (ULONG MMIOBase,
++ int nVideo);
++BYTE GetI2CRegClient(ULONG MMIOBase,
++ BYTE DeviceSelect,
++ BYTE DeviceAddress,
++ BYTE RegisterIndex);
++
++ULONG SetI2CRegClient(ULONG MMIOBase,
++ BYTE DeviceSelect,
++ BYTE DeviceAddress,
++ BYTE RegisterIndex,
++ BYTE RegisterValue);
++#endif //_VFUN_H_
++
+diff --git a/board/aspeed/ast2300/vgahw.h b/board/aspeed/ast2300/vgahw.h
+new file mode 100755
+index 0000000..7cbba0d
+--- /dev/null
++++ b/board/aspeed/ast2300/vgahw.h
+@@ -0,0 +1,175 @@
++/*
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++ */
++/******************************************************************************
++ * Mode Stuff
++ ******************************************************************************/
++/* Default Settings */
++#define CRT_LOW_THRESHOLD_VALUE 0x12
++#define CRT_HIGH_THRESHOLD_VALUE 0x1E
++
++/* Output Selection */
++#define CRT1 0x00
++#define CRT2 0x01
++#define DVI1 0x10
++#define DVI2 0x11
++#define LVDS1 0x20
++#define LVDS2 0x21
++
++/* Mode Limitation */
++#define MAX_HResolution 1600
++#define MAX_VResolution 1200
++
++/* Std. Table Index Definition */
++#define TextModeIndex 0
++#define EGAModeIndex 1
++#define VGAModeIndex 2
++#define HiCModeIndex 3
++#define TrueCModeIndex 4
++
++/* DCLK Index */
++#define VCLK25_175 0x00
++#define VCLK28_322 0x01
++#define VCLK31_5 0x02
++#define VCLK36 0x03
++#define VCLK40 0x04
++#define VCLK49_5 0x05
++#define VCLK50 0x06
++#define VCLK56_25 0x07
++#define VCLK65 0x08
++#define VCLK75 0x09
++#define VCLK78_75 0x0A
++#define VCLK94_5 0x0B
++#define VCLK108 0x0C
++#define VCLK135 0x0D
++#define VCLK157_5 0x0E
++#define VCLK162 0x0F
++#define VCLK119 0x10
++
++/* Flags Definition */
++#define Charx8Dot 0x00000001
++#define HalfDCLK 0x00000002
++#define DoubleScanMode 0x00000004
++#define LineCompareOff 0x00000008
++#define SyncPP 0x00000000
++#define SyncPN 0x00000040
++#define SyncNP 0x00000080
++#define SyncNN 0x000000C0
++#define HBorder 0x00000020
++#define VBorder 0x00000010
++#define COLORINDEX 0x00000000
++#define MONOINDEX 0x00000100
++
++/* DAC Definition */
++#define DAC_NUM_TEXT 64
++#define DAC_NUM_EGA 64
++#define DAC_NUM_VGA 256
++
++/* AST3000 Reg. Definition */
++#define AST3000_VGAREG_BASE 0x1e6e6000
++#define AST3000_VGA1_CTLREG 0x00
++#define AST3000_VGA1_CTLREG2 0x04
++#define AST3000_VGA1_STATUSREG 0x08
++#define AST3000_VGA1_PLL 0x0C
++#define AST3000_VGA1_HTREG 0x10
++#define AST3000_VGA1_HRREG 0x14
++#define AST3000_VGA1_VTREG 0x18
++#define AST3000_VGA1_VRREG 0x1C
++#define AST3000_VGA1_STARTADDR 0x20
++#define AST3000_VGA1_OFFSETREG 0x24
++#define AST3000_VGA1_THRESHOLD 0x28
++#define AST3000_HWC1_OFFSET 0x30
++#define AST3000_HWC1_XY 0x34
++#define AST3000_HWC1_PBase 0x38
++#define AST3000_OSD1_H 0x40
++#define AST3000_OSD1_V 0x44
++#define AST3000_OSD1_PBase 0x48
++#define AST3000_OSD1_Offset 0x4C
++#define AST3000_OSD1_THRESHOLD 0x50
++
++#define AST3000_VGA2_CTLREG 0x60
++#define AST3000_VGA2_CTLREG2 0x64
++#define AST3000_VGA2_STATUSREG 0x68
++#define AST3000_VGA2_PLL 0x6C
++#define AST3000_VGA2_HTREG 0x70
++#define AST3000_VGA2_HRREG 0x74
++#define AST3000_VGA2_VTREG 0x78
++#define AST3000_VGA2_VRREG 0x7C
++#define AST3000_VGA2_STARTADDR 0x80
++#define AST3000_VGA2_OFFSETREG 0x84
++#define AST3000_VGA2_THRESHOLD 0x88
++#define AST3000_HWC2_OFFSET 0x90
++#define AST3000_HWC2_XY 0x94
++#define AST3000_HWC2_PBase 0x98
++#define AST3000_OSD2_H 0xA0
++#define AST3000_OSD2_V 0xA4
++#define AST3000_OSD2_PBase 0xA8
++#define AST3000_OSD2_Offset 0xAC
++#define AST3000_OSD2_THRESHOLD 0xB0
++
++/* Data Structure */
++typedef struct {
++ UCHAR ModeName[20];
++ USHORT usModeIndex;
++ USHORT usModeID;
++ USHORT usColorIndex;
++ USHORT usRefreshRateIndex;
++ USHORT usWidth;
++ USHORT usHeight;
++ USHORT usBitsPerPlane;
++ USHORT usRefreshRate;
++} ModeInfoStruct;
++
++typedef struct {
++
++ UCHAR MISC;
++ UCHAR SEQ[4];
++ UCHAR CRTC[25];
++ UCHAR AR[20];
++ UCHAR GR[9];
++
++} VBIOS_STDTABLE_STRUCT, *PVBIOS_STDTABLE_STRUCT;
++
++typedef struct {
++
++ ULONG HT;
++ ULONG HDE;
++ ULONG HFP;
++ ULONG HSYNC;
++ ULONG VT;
++ ULONG VDE;
++ ULONG VFP;
++ ULONG VSYNC;
++ ULONG DCLKIndex;
++ ULONG Flags;
++
++ ULONG ulRefreshRate;
++ ULONG ulRefreshRateIndex;
++ ULONG ulModeID;
++
++} VBIOS_ENHTABLE_STRUCT, *PVBIOS_ENHTABLE_STRUCT;
++
++typedef struct {
++ UCHAR Param1;
++ UCHAR Param2;
++ UCHAR Param3;
++} VBIOS_DCLK_INFO, *PVBIOS_DCLK_INFO;
++
++typedef struct {
++ UCHAR DACR;
++ UCHAR DACG;
++ UCHAR DACB;
++} VBIOS_DAC_INFO, *PVBIOS_DAC_INFO;
++
++typedef struct {
++ PVBIOS_STDTABLE_STRUCT pStdTableEntry;
++ PVBIOS_ENHTABLE_STRUCT pEnhTableEntry;
++
++} VBIOS_MODE_INFO, *PVBIOS_MODE_INFO;
+diff --git a/board/aspeed/ast2300/vhace.c b/board/aspeed/ast2300/vhace.c
+new file mode 100755
+index 0000000..d045cbd
+--- /dev/null
++++ b/board/aspeed/ast2300/vhace.c
+@@ -0,0 +1,66 @@
++/*
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++ */
++#define HASH_GLOBALS
++#include "type.h"
++#include "vdef.h"
++#include "vhace.h"
++#include "vfun.h"
++
++void HashAst3000(ULONG ulLength, ULONG *output, ULONG ulHashMode)
++{
++ ULONG i, ulTemp, ulCommand, ulDigestLength;
++ ULONG ulValue;
++
++ /* Get Info */
++ switch (ulHashMode)
++ {
++ case VHASHMODE_MD5:
++ ulCommand = VHASH_ALG_SELECT_MD5;
++ ulDigestLength = 16;
++ break;
++ case VHASHMODE_SHA1:
++ ulCommand = VHASH_ALG_SELECT_SHA1;
++ ulDigestLength = 20;
++ break;
++ case VHASHMODE_SHA256:
++ ulCommand = VHASH_ALG_SELECT_SHA256;
++ ulDigestLength = 32;
++ break;
++ case VHASHMODE_SHA224:
++ ulCommand = VHASH_ALG_SELECT_SHA224;
++ ulDigestLength = 28;
++ break;
++ }
++
++ /* Init. HW */
++ WriteMemoryLongHost(VHAC_REG_BASE, VREG_HASH_SRC_BASE_OFFSET, g_HashSrcBuffer);
++ WriteMemoryLongHost(VHAC_REG_BASE, VREG_HASH_DST_BASE_OFFSET, g_HashDstBuffer);
++ WriteMemoryLongHost(VHAC_REG_BASE, VREG_HASH_LEN_OFFSET, ulLength);
++
++ /* write src */
++ //already fill in g_VIDEO1_COMPRESS_BUF_ADDR
++
++ /* fire cmd */
++ WriteMemoryLongHost(VHAC_REG_BASE, VREG_HASH_CMD_OFFSET, ulCommand);
++
++ /* get digest */
++ do {
++ ulTemp = ReadMemoryLongHost(VHAC_REG_BASE, VREG_HASH_STATUS_OFFSET);
++ } while (ulTemp & VHASH_BUSY);
++
++ for (i=0; i<ulDigestLength/4; i++)
++ {
++ ulValue = *(((ULONG *)g_HashDstBuffer) + i);
++
++ //output is ULONG pointer
++ *(output + i) = ulValue;
++ }
++}
+diff --git a/board/aspeed/ast2300/vhace.h b/board/aspeed/ast2300/vhace.h
+new file mode 100755
+index 0000000..460989b
+--- /dev/null
++++ b/board/aspeed/ast2300/vhace.h
+@@ -0,0 +1,58 @@
++/*
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++ */
++#ifndef _VHACE_H_
++#define _VHACE_H_
++
++#define VHASHMODE_MD5 0x00
++#define VHASHMODE_SHA1 0x01
++#define VHASHMODE_SHA256 0x02
++#define VHASHMODE_SHA224 0x03
++
++#define VHASH_ALG_SELECT_MASK 0x70
++#define VHASH_ALG_SELECT_MD5 0x00
++#define VHASH_ALG_SELECT_SHA1 0x20
++#define VHASH_ALG_SELECT_SHA224 0x40
++#define VHASH_ALG_SELECT_SHA256 0x50
++
++#define VHASH_BUSY 0x01
++
++#define VHAC_REG_BASE 0x1e6e0000
++#define VHAC_REG_OFFSET 0x3000
++
++#define VREG_HASH_SRC_BASE_OFFSET (0x20+VHAC_REG_OFFSET)
++#define VREG_HASH_DST_BASE_OFFSET (0x24+VHAC_REG_OFFSET)
++#define VREG_HASH_KEY_BASE_OFFSET (0x28+VHAC_REG_OFFSET)
++#define VREG_HASH_LEN_OFFSET (0x2C+VHAC_REG_OFFSET)
++#define VREG_HASH_CMD_OFFSET (0x30+VHAC_REG_OFFSET)
++
++#define VREG_HASH_STATUS_OFFSET (0x1C+VHAC_REG_OFFSET)
++
++typedef struct
++{
++ int HashMode;
++ int DigestLen;
++} HASH_METHOD;
++
++
++#ifdef HASH_GLOBALS
++#define HASH_EXT
++#else
++#define HASH_EXT extern
++#endif
++
++HASH_EXT HASH_METHOD g_HashMethod;
++HASH_EXT BYTE g_DigestBuf[32];
++HASH_EXT ULONG g_HashSrcBuffer;
++HASH_EXT ULONG g_HashDstBuffer;
++
++void HashAst3000(ULONG ulLength, ULONG *output, ULONG ulHashMode);
++#endif
++
+diff --git a/board/aspeed/ast2300/videotest.c b/board/aspeed/ast2300/videotest.c
+new file mode 100755
+index 0000000..f2e4953
+--- /dev/null
++++ b/board/aspeed/ast2300/videotest.c
+@@ -0,0 +1,779 @@
++/*
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
++ * MA 02111-1307 USA
++ */
++
++/*
++ * Diagnostics support
++ */
++#include <common.h>
++#include <command.h>
++#include <malloc.h>
++#include <post.h>
++
++#include "slt.h"
++#define WIN_GLOBALS
++#include "type.h"
++#include "vreg.h"
++#define VESA_GLOBALS
++#include "vesa.h"
++#include "vfun.h"
++#include "vdef.h"
++#include "vhace.h"
++#include "crt.h"
++#include "videotest.h"
++
++#define VHASH_ALIGNMENT 16
++#define VHASH_MAX_DST (32+VHASH_ALIGNMENT)
++
++
++#if ((CFG_CMD_SLT & CFG_CMD_VIDEOTEST) && defined(CONFIG_SLT))
++#include "videotest.h"
++
++#define RAND_MAX 32767 //2^16-1
++
++ULONG randSeed = 1;
++
++void srand(ULONG seed)
++{
++ randSeed = seed;
++}
++
++int rand(void)
++{
++ randSeed = randSeed * 214013 + 2531011;
++ return (int)(randSeed >> 17); //32 -15 = 17
++}
++
++//static unsigned char CaptureVideo1Buf1Addr[VIDEO_SOURCE_SIZE], CaptureVideo1Buf2Addr[VIDEO_SOURCE_SIZE], Video1CompressBufAddr[CRYPTO_MAX_CONTEXT];
++ULONG pCaptureVideo1Buf1Addr[VIDEO_SOURCE_SIZE/4], pCaptureVideo1Buf2Addr[VIDEO_SOURCE_SIZE/4], pVideo1CompressBufAddr[VIDEO_MAX_STREAM_SIZE/4], pVideo1FlagBufAddr[VIDEO_FLAG_SIZE];
++ULONG pCaptureVideo2Buf1Addr[VIDEO_SOURCE_SIZE/4], pCaptureVideo2Buf2Addr[VIDEO_SOURCE_SIZE/4], pVideo2CompressBufAddr[VIDEO_MAX_STREAM_SIZE/4], pVideo2FlagBufAddr[VIDEO_FLAG_SIZE];
++
++ULONG pVHashDstBuffer[VHASH_MAX_DST/4];
++
++ULONG pVideo1DecAddr[VIDEO_SOURCE_SIZE/4];
++ULONG pCrt1Addr[VIDEO_SOURCE_SIZE/4];
++//ULONG pCap1Addr[VIDEO_SOURCE_SIZE/4];
++
++BOOL AllocateEncodeBufHost(ULONG MMIOBase, int nVideo)
++{
++ //ULONG Addr;
++ //ULONG dwRegOffset = nVideo * 0x100;
++
++ if (VIDEO1 == nVideo)
++ {
++
++ //Addr = (ULONG)malloc(pVideoInfo->SrcWidth * pVideoInfo->SrcHeight * 4);
++ //pCaptureVideo1Buf1Addr = malloc(VIDEO_SOURCE_SIZE);
++
++ g_CAPTURE_VIDEO1_BUF1_ADDR = vBufAlign((ULONG)pCaptureVideo1Buf1Addr);
++ WriteMemoryLongWithMASKHost(VIDEO_REG_BASE, VIDEO1_BUF_1_ADDR_REG, g_CAPTURE_VIDEO1_BUF1_ADDR, BUF_1_ADDR_MASK);
++
++ //Addr = (ULONG)malloc(pVideoInfo->SrcWidth * pVideoInfo->SrcHeight * 4);
++ //pCaptureVideo1Buf2Addr = malloc(VIDEO_SOURCE_SIZE);
++
++ g_CAPTURE_VIDEO1_BUF2_ADDR = vBufAlign((ULONG)pCaptureVideo1Buf2Addr);
++ WriteMemoryLongWithMASKHost(VIDEO_REG_BASE, VIDEO1_BUF_2_ADDR_REG, g_CAPTURE_VIDEO1_BUF2_ADDR, BUF_2_ADDR_MASK);
++
++ //Addr = (ULONG)malloc(pVideoInfo->uStreamBufSize.StreamBufSize.RingBufNum * pVideoInfo->uStreamBufSize.StreamBufSize.PacketSize)
++ //pVideo1CompressBufAddr = malloc(VIDEO_MAX_STREAM_SIZE);
++ g_VIDEO1_COMPRESS_BUF_ADDR = vBufAlign((ULONG)pVideo1CompressBufAddr);
++ WriteMemoryLongWithMASKHost(VIDEO_REG_BASE, VIDEO1_COMPRESS_BUF_ADDR_REG, g_VIDEO1_COMPRESS_BUF_ADDR, BUF_2_ADDR_MASK);
++
++ //Addr = (ULONG)malloc((pVideoInfo->SrcHeigh/64) * pVideoInfo->SrcWidth * 8);
++ //g_VIDEO1_CRC_BUF_ADDR = vBufAlign((ULONG)malloc(VIDEO_MAX_STREAM_SIZE));
++ //WriteMemoryLongWithMASKHost(VIDEO_REG_BASE, VIDEO1_CRC_BUF_ADDR_REG, g_VIDEO1_CRC_BUF_ADDR, BUF_2_ADDR_MASK);
++
++
++ //Addr = (ULONG)malloc(pVideoInfo->SrcHeigh * pVideoInfo->SrcWidth / 128 (/64*4/8));
++ //pVideo1FlagBufAddr = malloc(VIDEO_FLAG_SIZE);
++ g_VIDEO1_FLAG_BUF_ADDR = vBufAlign((ULONG)pVideo1FlagBufAddr);
++ WriteMemoryLongWithMASKHost(VIDEO_REG_BASE, VIDEO1_FLAG_BUF_ADDR_REG, g_VIDEO1_FLAG_BUF_ADDR, BUF_2_ADDR_MASK);
++ }
++ else if (VIDEO2 == nVideo)
++ {
++ //Addr = (ULONG)malloc(pVideoInfo->SrcWidth * pVideoInfo->SrcHeight * 4);
++ //pCaptureVideo2Buf1Addr = malloc(VIDEO_SOURCE_SIZE);
++ g_CAPTURE_VIDEO2_BUF1_ADDR = vBufAlign((ULONG)pCaptureVideo2Buf1Addr);
++ WriteMemoryLongWithMASKHost(VIDEO_REG_BASE, VIDEO2_BUF_1_ADDR_REG, g_CAPTURE_VIDEO2_BUF1_ADDR, BUF_1_ADDR_MASK);
++
++ //Addr = (ULONG)malloc(pVideoInfo->SrcWidth * pVideoInfo->SrcHeight * 4);
++ //pCaptureVideo2Buf2Addr = malloc(VIDEO_SOURCE_SIZE);
++ g_CAPTURE_VIDEO2_BUF2_ADDR = vBufAlign((ULONG)pCaptureVideo2Buf2Addr);
++ WriteMemoryLongWithMASKHost(VIDEO_REG_BASE, VIDEO2_BUF_2_ADDR_REG, g_CAPTURE_VIDEO2_BUF2_ADDR, BUF_2_ADDR_MASK);
++
++ //Addr = (ULONG)malloc(pVideoInfo->uStreamBufSize.StreamBufSize.RingBufNum * pVideoInfo->uStreamBufSize.StreamBufSize.PacketSize)
++ //pVideo2CompressBufAddr = malloc(VIDEO_MAX_STREAM_SIZE);
++ g_VIDEO2_COMPRESS_BUF_ADDR = vBufAlign((ULONG)pVideo2CompressBufAddr);
++ WriteMemoryLongWithMASKHost(VIDEO_REG_BASE, VIDEO2_COMPRESS_BUF_ADDR_REG, g_VIDEO2_COMPRESS_BUF_ADDR, BUF_2_ADDR_MASK);
++
++ //Addr = (ULONG)malloc((pVideoInfo->SrcHeigh/64) * pVideoInfo->SrcWidth * 8);
++ //g_VIDEO1_CRC_BUF_ADDR = vBufAlign((ULONG)malloc(VIDEO_MAX_STREAM_SIZE));
++ //WriteMemoryLongWithMASKHost(VIDEO_REG_BASE, VIDEO1_CRC_BUF_ADDR_REG, g_VIDEO1_CRC_BUF_ADDR, BUF_2_ADDR_MASK);
++
++
++ //Addr = (ULONG)malloc(pVideoInfo->SrcHeigh * pVideoInfo->SrcWidth / 128 (/64*4/8));
++ //pVideo2FlagBufAddr = malloc(VIDEO_FLAG_SIZE);
++ g_VIDEO2_FLAG_BUF_ADDR = vBufAlign((ULONG)pVideo2FlagBufAddr);
++ WriteMemoryLongWithMASKHost(VIDEO_REG_BASE, VIDEO2_FLAG_BUF_ADDR_REG, g_VIDEO2_FLAG_BUF_ADDR, BUF_2_ADDR_MASK);
++ }
++
++}
++
++/********************************************************/
++/* 1. product random data to encode */
++/* 2. use hash to verify encode function */
++/* 3. use encode stream to decompress original data */
++/********************************************************/
++int CodecTest(void)
++{
++ int num, i=0, j=0;
++ ULONG ulTemp = 0, ulTemp2;
++ int dwValue;
++ ULONG ulHWWp;
++ ULONG ulHWPt;
++
++ //max size
++ ULONG tArray[32/4];
++
++ //mode detection
++ BOOL bExternal = TRUE;
++ BOOL bAnalog = TRUE;
++ ULONG Status;
++
++#if defined(CONFIG_AST2300)
++ ULONG ulHashSha1[5] = {0x3f0c2ad6,0xc8eb7074,0xa9929352,0xfcd5b8b0,0x76fa8461};
++ ULONG aHashDecode[5] = {0xb23b62bb,0xd22a602b,0x113038a0,0x7217c6ab,0xcb156f06};
++#else
++ ULONG ulHashSha1[5] = {0x2a19e99f,0x99b1bb2d,0x9ac82862,0x49205e43,0x6bc4b4d7};
++ ULONG aHashDecode[5] = {0x2907a827,0xaf337079,0x47817f1f,0xb0b7cd68,0x8d33bd2};
++#endif
++
++ //Load pattern to src1 & src2 buffer
++ srand(1);
++
++ //Total size : DefWidth*DeHeight*4
++ //rand function: 16 bits one time is equal to 2 bytes
++ //OutdwmBankMode: 32 bits one time is equal to 4 bytes
++ for (i=0; i<g_DefWidth*g_DefHeight*2; i++)
++ {
++ if (i%2)
++ {
++ ulTemp2 = rand();
++ ulTemp = (ulTemp2 << 16) | ulTemp;
++ //WriteMemoryLongHost(DRAM_BASE, g_CAPTURE_VIDEO1_BUF1_ADDR + ((i-1)/2)*4, ulTemp);
++ *(((ULONG *)g_CAPTURE_VIDEO1_BUF1_ADDR) + (i-1)/2) = ulTemp;
++ ulTemp = 0;
++ }
++ else
++ {
++ ulTemp = rand();
++ }
++ }
++
++ /* init encoder engine */
++ InitializeVideoEngineHost (0,
++ VIDEO1,
++ vModeTable[2].HorPolarity,
++ vModeTable[2].VerPolarity);
++
++ /* reset offset pointer register*/
++ WriteMemoryLongWithMASKHost(VIDEO_REG_BASE, VIDEO1_ENGINE_SEQUENCE_CONTROL_REG, 0, VIDEO_CODEC_TRIGGER | VIDEO_CAPTURE_TRIGGER);
++
++ WriteMemoryLongWithMASKHost(VIDEO_REG_BASE, VIDEO1_COMPRESS_BUF_READ_OFFSET_REG, 0, COMPRESS_BUF_READ_OFFSET_MASK);
++ WriteMemoryLongWithMASKHost(VIDEO_REG_BASE, VIDEO1_BUF_CODEC_OFFSET_READ, 0, BUF_CODEC_OFFSET_MASK);
++ WriteMemoryLongWithMASKHost(VIDEO_REG_BASE, VIDEO1_COMPRESS_BUF_PROCESS_OFFSET_REG, 0, COMPRESS_BUF_PROCESS_OFFSET_MASK);
++ WriteMemoryLongWithMASKHost(VIDEO_REG_BASE, VIDEO1_COMPRESS_FRAME_END_READ, 0, COMPRESS_FRAME_END_READ_MASK);
++
++ /* start compress stream */
++ WriteMemoryLongWithMASKHost(VIDEO_REG_BASE, VIDEO1_ENGINE_SEQUENCE_CONTROL_REG, MODE_DETECTION_TRIGGER, MODE_DETECTION_TRIGGER);
++ //Stream mode: set CODEC trigger first
++ WriteMemoryLongWithMASKHost(VIDEO_REG_BASE, VIDEO1_ENGINE_SEQUENCE_CONTROL_REG, VIDEO_CODEC_TRIGGER, VIDEO_CODEC_TRIGGER);
++
++ //Stream mode: start trigger (only trigger capture bit)
++ StartVideoCaptureTriggerHost(0, VIDEO1_ENGINE_SEQUENCE_CONTROL_REG);
++
++ //stop engine
++ WriteMemoryLongWithMASKHost(VIDEO_REG_BASE, VIDEO1_ENGINE_SEQUENCE_CONTROL_REG, 0, 0xFF);
++#if defined(CONFIG_AST2300)
++ do { /* wait compress engine idle */
++ ulTemp = ReadMemoryLongHost(VIDEO_REG_BASE, VIDEO1_ENGINE_SEQUENCE_CONTROL_REG);
++ } while (!(ulTemp & 0x40000));
++#endif
++
++ //read 30 times to get HW write pointer
++ for (i=0; i<30000; i++)
++ ulHWWp = ReadMemoryLongHost(VIDEO_REG_BASE, VIDEO1_BUF_CODEC_OFFSET_READ);
++
++ g_HashSrcBuffer = g_VIDEO1_COMPRESS_BUF_ADDR + 128; //skip encode data 128 byte
++ g_HashDstBuffer = v16byteAlign((unsigned long)pVHashDstBuffer);
++ ulTemp = 300;
++
++ //Enable hash clock
++ WriteMemoryLongWithMASKHost(SCU_BASE, SCU_CLOCK_STOP_REG, EN_HACE, STOP_HACE_MASK);
++ g_HashMethod.HashMode = VHASHMODE_SHA1;
++ g_HashMethod.DigestLen = 20;
++ HashAst3000(ulTemp, tArray, g_HashMethod.HashMode);
++
++ if (strncmp((const char *)tArray, (const char *)ulHashSha1, g_HashMethod.DigestLen))
++ {
++ printf("[VIDEO] Encoder Test: Wrong\n");
++ //ExitVideoTest();
++ return VIDEO_ENCODE_FAIL;
++ }
++ else
++ {
++ printf("[VIDEO] Encoder Test: Pass\n");
++ }
++
++#if 0
++ /******** prepare for next decoding test at the same chip ***********/
++ ResetVideoHost();
++
++ dwValue=0;
++
++ do
++ {
++ dwValue = UnlockVideoRegHost(0, VIDEO_UNLOCK_KEY);
++ i++;
++ }
++ while ((VIDEO_UNLOCK != dwValue) && (i<10));
++
++ if (VIDEO_UNLOCK != dwValue)
++ {
++ printf("[VIDEO] Video register is locked");
++ return VIDEO_UNLOCK_FAIL;
++ }
++
++ // allocate decoding buffer
++ //Use Compress buffer last time, and Don't need to allocate
++ g_VIDEO1_DECODE_BUF_1_ADDR = g_VIDEO1_COMPRESS_BUF_ADDR;
++ WriteMemoryLongWithMASKHost(VIDEO_REG_BASE, VIDEO1_BUF_1_ADDR_REG, g_VIDEO1_DECODE_BUF_1_ADDR, BUF_1_ADDR_MASK);
++
++ // pVideo1DecAddr = malloc(VIDEO_SOURCE_SIZE);
++ g_VIDEO1_DECOMPRESS_BUF_ADDR = vBufAlign((unsigned long)pVideo1DecAddr);
++ WriteMemoryLongWithMASKHost(VIDEO_REG_BASE, VIDEO1_COMPRESS_BUF_ADDR_REG, g_VIDEO1_DECOMPRESS_BUF_ADDR, COMPRESS_BUF_ADDR_MASK);
++
++ //Addr = (ULONG)malloc(256);
++ //g_VIDEO1_RC4_BUF_ADDR = Addr;
++ //g_VIDEO1_DECODE_RC4_BUF_ADDR = g_VIDEO1_DECOMPRESS_BUF_ADDR + 0x800000; //assume video size is 8MB for umcompressed buf;
++ //WriteMemoryLongWithMASKClient(VIDEO_REG_BASE, VIDEO1_RC4_TABLE_ADDR, g_VIDEO1_DECODE_RC4_BUF_ADDR, RC4_TABLE_ADDR_MASK);
++
++ //HW recommanded value
++ WriteMemoryLongWithMASKHost(VIDEO_REG_BASE, VIDEO1_BUF_2_ADDR_REG, g_VIDEO1_DECOMPRESS_BUF_ADDR, BUF_2_ADDR_MASK);
++ //WriteMemoryLongWithMASKClient(VIDEO_REG_BASE, VIDEO1_BUF_2_ADDR_REG, 0, BUF_2_ADDR_MASK);
++ WriteMemoryLongWithMASKHost(VIDEO_REG_BASE, VIDEO1_CRC_BUF_ADDR_REG, 0, BUF_2_ADDR_MASK);
++
++ /* init encoder engine */
++ InitializeVideoEngineClient (0, VIDEO1);
++
++ /* reset offset pointer register*/
++ WriteMemoryLongWithMASKHost(VIDEO_REG_BASE, VIDEO1_ENGINE_SEQUENCE_CONTROL_REG, 0, VIDEO_CODEC_TRIGGER | VIDEO_CAPTURE_TRIGGER);
++
++ WriteMemoryLongWithMASKHost(VIDEO_REG_BASE, VIDEO1_COMPRESS_BUF_READ_OFFSET_REG, 0, COMPRESS_BUF_READ_OFFSET_MASK);
++ WriteMemoryLongWithMASKHost(VIDEO_REG_BASE, VIDEO1_BUF_CODEC_OFFSET_READ, 0, BUF_CODEC_OFFSET_MASK);
++ WriteMemoryLongWithMASKHost(VIDEO_REG_BASE, VIDEO1_COMPRESS_BUF_PROCESS_OFFSET_REG, 0, COMPRESS_BUF_PROCESS_OFFSET_MASK);
++ WriteMemoryLongWithMASKHost(VIDEO_REG_BASE, VIDEO1_COMPRESS_FRAME_END_READ, 0, COMPRESS_FRAME_END_READ_MASK);
++
++ StartVideoCodecTriggerHost(0, VIDEO1_ENGINE_SEQUENCE_CONTROL_REG);
++
++ //wrtie SW write pointer
++ WriteMemoryLongWithMASKHost(VIDEO_REG_BASE, VIDEO1_DECOMPRESS_BUF_PROCESS_OFFSET_REG, ulHWWp, COMPRESS_BUF_READ_OFFSET_MASK);
++ WriteMemoryLongWithMASKHost(VIDEO_REG_BASE, VIDEO1_DECOMPRESS_BUF_WRITE_OFFSET_REG, ulHWWp, COMPRESS_BUF_READ_OFFSET_MASK);
++
++ i = 0;
++
++ do
++ {
++ ulHWPt = ReadMemoryLongHost(VIDEO_REG_BASE, VIDEO1_BUF_CODEC_OFFSET_READ);
++ i++;
++ }while((ulHWPt != ulHWWp) && (i<10000));
++
++ if (10000 > i)
++ {
++ printf("[VIDEO] Decoder Pointer cannot move!!! /n");
++ //ExitVideoTest();
++ return VIDEO_DECODE_FAIL;
++ }
++
++ //8*8 YUVA block
++ for (i=24; i<g_DefWidth*g_DefHeight; i=i+32)
++ {
++ *(((ULONG *)g_VIDEO1_DECOMPRESS_BUF_ADDR) + i) = 0x0;
++ *(((ULONG *)g_VIDEO1_DECOMPRESS_BUF_ADDR) + i+1) = 0x0;
++ }
++
++ g_HashSrcBuffer = g_VIDEO1_DECOMPRESS_BUF_ADDR;
++ //g_HashDstBuffer = VIDEO1_EN_BASE + VIDEO_ALL_SIZE; //config forward
++
++ ulTemp = 300;
++
++ //Enable hash clock
++ WriteMemoryLongWithMASKHost(SCU_BASE, SCU_CLOCK_STOP_REG, EN_HACE, STOP_HACE_MASK);
++ g_HashMethod.HashMode = VHASHMODE_SHA1;
++ g_HashMethod.DigestLen = 20;
++ HashAst3000(ulTemp, tArray, g_HashMethod.HashMode);
++
++ if (strncmp((const char *)tArray, (const char *)aHashDecode, g_HashMethod.DigestLen))
++ {
++ printf("[VIDEO] Decoder Test: Wrong\n");
++ //ExitVideoTest();
++ return VIDEO_DECODE_FAIL;
++ }
++ else
++ {
++ printf("[VIDEO] Decoder Test: Pass\n");
++ }
++#endif
++
++ return VIDEO_TEST_OK;
++}
++
++/********************************************************/
++/* Only used in the host */
++/* test function: Mode detection and Capture pattern */
++/********************************************************/
++int CapTest(void)
++{
++ ULONG dwValue, Status;
++ int i;
++ BOOL bAnalog;
++ ULONG HStart, HEnd, VStart, VEnd;
++ USHORT usCRTHor, usCRTVer;
++ ULONG ulHor, ulVer;
++ ULONG ulVGABaseAddr, ulCapAddr;
++ ULONG ulFlag;
++
++ printf("\n --------- Mode Detection Test --------- \n");
++ //clear clear register
++ WriteMemoryLongHost(VIDEO_REG_BASE, VIDEO1_CONTROL_REG, 0);
++ dwValue = ReadMemoryLongHost(VIDEO_REG_BASE, VIDEO1_CONTROL_REG);
++
++ // Note: Current mode detection procedure has to set signal input 1st
++ //Note: Clear and enable interrupt Encode
++ ClearVideoInterruptHost(0, VIDEO1_MODE_DETECTION_READY_CLEAR);
++ WriteMemoryLongWithMASKHost(VIDEO_REG_BASE, VIDEO_INT_CONTROL_EN_REG, VIDEO1_MODE_DETECTION_READY_INT_EN, VIDEO1_MODE_DETECTION_READY_INT_EN);
++ // Set input signal
++ dwValue |= EXTERNAL_VGA_SOURCE;
++
++ WriteMemoryLongWithMASKHost(VIDEO_REG_BASE, VIDEO1_CONTROL_REG, (dwValue <<EXTERNAL_SOURCE_BIT), EXTERNAL_SOURCE_MASK);
++
++// Set H/V stable maximum
++ WriteMemoryLongWithMASKHost(VIDEO_REG_BASE, VIDEO_MODE_DETECTION_PARAM_REG, (MODEDETECTION_VERTICAL_STABLE_MAXIMUM << VER_STABLE_MAX_BIT), 0x000F0000);
++ WriteMemoryLongWithMASKHost(VIDEO_REG_BASE, VIDEO_MODE_DETECTION_PARAM_REG, (MODEDETECTION_HORIZONTAL_STABLE_MAXIMUM << HOR_STABLE_MAX_BIT), HOR_STABLE_MAX_BIT_MASK);
++// Set H/V stable threshold
++ WriteMemoryLongWithMASKHost(VIDEO_REG_BASE, VIDEO_MODE_DETECTION_PARAM_REG, (MODEDETECTION_VERTICAL_STABLE_THRESHOLD << VER_STABLE_THRES_BIT), VER_STABLE_THRES_BIT_MASK);
++ WriteMemoryLongWithMASKHost(VIDEO_REG_BASE, VIDEO_MODE_DETECTION_PARAM_REG, (MODEDETECTION_HORIZONTAL_STABLE_THRESHOLD << HOR_STABLE_THRES_BIT), HOR_STABLE_THRES_BIT_MASK);
++
++ //Trigger mode detection
++ // turn off WATCH_DOG first
++ WriteMemoryLongWithMASKHost(VIDEO_REG_BASE, VIDEO1_ENGINE_SEQUENCE_CONTROL_REG, (WATCH_DOG_OFF << WATCH_DOG_ENABLE_BIT), WATCH_DOG_EN_MASK);
++
++ // Note: Clear mode detection ready interrupt
++ //ClearVideoInterrupt(MMIOBase, MODE_DETECTION_READY_CLEAR);
++ StartModeDetectionTriggerHost(0, VIDEO1_ENGINE_SEQUENCE_CONTROL_REG);
++
++
++// Note: Polling mode detection ready interrupt
++ //it sometime take a long time, especially during change mode,
++ //so the loop count must be big, or you can't pull it by timer
++ i = 0;
++ do {
++
++ Status = ReadVideoInterruptHost(0, VIDEO1_MODE_DETECTION_READY_READ);
++ i++;
++ } while ((!Status) & (i<500000));
++
++ if (!Status)
++ {
++ printf("[VIDEO] Mode detection error\n");
++ //ExitVideoTest();
++ return VIDEO_TEST_FAIL;
++ }
++
++ HStart = (ReadMemoryLongHost(VIDEO_REG_BASE, VIDE1_MODE_DETECTION_EDGE_H_REG) & LEFT_EDGE_LOCATION_MASK) >> LEFT_EDGE_LOCATION_BIT;
++ HEnd = (ReadMemoryLongHost(VIDEO_REG_BASE, VIDE1_MODE_DETECTION_EDGE_H_REG) & RIGHT_EDGE_LOCATION_MASK) >> RIGHT_EDGE_LOCATION_BIT;
++
++ VStart = (ReadMemoryLongHost(VIDEO_REG_BASE, VIDE1_MODE_DETECTION_EDGE_V_REG) & TOP_EDGE_LOCATION_MASK) >> TOP_EDGE_LOCATION_BIT;
++ VEnd = (ReadMemoryLongHost(VIDEO_REG_BASE, VIDE1_MODE_DETECTION_EDGE_V_REG) & BOTTOM_EDGE_LOCATION_MASK) >> BOTTOM_EDGE_LOCATION_BIT;
++
++ ulHor = HEnd-HStart+1;
++ ulVer = VEnd-VStart+1;
++
++ printf("[VIDEO] Resolution: H[%d] * V[%d]\n", ulHor, ulVer);
++
++ if ((g_DefWidth == ulHor) & (g_DefHeight == ulVer))
++ {
++ printf("[VIDEO] Mode detection PASS\n");
++ }
++ else
++ {
++ printf("[VIDEO] Mode detection FAIL\n");
++ return VIDEO_TEST_FAIL;
++ }
++
++ if(!((ReadMemoryLongHost(VIDEO_REG_BASE, VIDEO1_MODE_DETECTION_STATUS_READ_REG) & ANALONG_DIGITAL_READ) >> ANALONG_DIGITAL_READ_BIT))
++ bAnalog = FALSE;
++ else
++ bAnalog = TRUE;
++
++ // Note: Clear mode detection ready interrupt
++ ClearVideoInterruptHost(0, VIDEO1_MODE_DETECTION_READY_CLEAR);
++
++ printf("\n --------- Capture Test --------- \n");
++
++ //capture engine
++ WriteMemoryLongWithMASKHost(VIDEO_REG_BASE, VIDEO1_TIMEING_GEN_HOR_REG, (HEnd << VIDEO_HDE_END_BIT), VIDEO_HDE_END_MASK);
++ WriteMemoryLongWithMASKHost(VIDEO_REG_BASE, VIDEO1_TIMEING_GEN_HOR_REG, (HStart << VIDEO_HDE_START_BIT), VIDEO_HDE_START_MASK);
++ WriteMemoryLongWithMASKHost(VIDEO_REG_BASE, VIDEO1_TIMEING_GEN_V_REG, (VEnd << VIDEO_VDE_END_BIT), VIDEO_VDE_END_MASK);
++ WriteMemoryLongWithMASKHost(VIDEO_REG_BASE, VIDEO1_TIMEING_GEN_V_REG, (VStart << VIDEO_VDE_START_BIT), VIDEO_VDE_START_MASK);
++
++ ulCapAddr = vBufAlign2((ULONG)pCaptureVideo1Buf1Addr);
++ WriteMemoryLongWithMASKHost(VIDEO_REG_BASE, VIDEO1_BUF_1_ADDR_REG, ulCapAddr, BUF_1_ADDR_MASK);
++
++ WriteMemoryLongWithMASKHost(VIDEO_REG_BASE, VIDEO1_BUF_2_ADDR_REG, 0, BUF_2_ADDR_MASK);
++
++ InitializeVideoEngineHost (0,
++ VIDEO1,
++ vModeTable[2].HorPolarity,
++ vModeTable[2].VerPolarity);
++
++ WriteMemoryLongHost(VIDEO_REG_BASE, 0x04, 0x01);
++ WriteMemoryLongHost(VIDEO_REG_BASE, 0x300, 0x0);
++#if defined(CONFIG_AST2300)
++ WriteMemoryLongWithMASKHost(VIDEO_REG_BASE, 0x8, 0x0880, 0x0ec0);
++#elif defined(CONFIG_AST3000)
++ WriteMemoryLongWithMASKHost(VIDEO_REG_BASE, 0x8, 0x2800, 0x2800);
++#else
++ WriteMemoryLongWithMASKHost(VIDEO_REG_BASE, 0x8, 0xa00, 0x2a80); //tile mode
++#endif
++
++ WriteMemoryLongWithMASKHost(VIDEO_REG_BASE, VIDEO1_TIMEING_GEN_HOR_REG, 0xa0000000, 0xa0000000);
++
++ //only trigger capture, in source buffer (vr44), the front of data is correct.
++ //StartVideoCaptureTriggerHost(0, VIDEO1_ENGINE_SEQUENCE_CONTROL_REG);
++ WriteMemoryLongHost(VIDEO_REG_BASE, VIDEO1_ENGINE_SEQUENCE_CONTROL_REG, VIDEO_CAPTURE_TRIGGER);
++
++ i = 0;
++ do {
++ Status = ReadMemoryLongHost(VIDEO_REG_BASE, VIDEO1_ENGINE_SEQUENCE_CONTROL_REG) & CAPTURE_READY_MASK;
++ i++;
++ } while ((!Status) & (i<500000));
++
++ if (!Status)
++ {
++ printf("[VIDEO] Capture is not READY\n");
++ return VIDEO_TEST_FAIL;
++ }
++
++#if !defined(CONFIG_AST2300)
++ ulVGABaseAddr = ulCapAddr + 0x1000;
++
++ /* check pattern */
++ ulFlag = 0; //no 0 is error
++
++ for (i=0; i<100; i++)
++ {
++ dwValue = *(ULONG *)(ulVGABaseAddr + i*32);
++ if (0x32323232 != dwValue)
++ {
++ printf("[VIDEO] Capture Test fail -- capture data doesn't match source \n");
++ printf("[VIDEO]1 i=%d value=%x\n", i, dwValue);
++ ulFlag = 1;
++ break;
++ }
++
++ dwValue = *(ULONG *)(ulVGABaseAddr + i*32 + 4);
++ if (0x32323232 != dwValue)
++ {
++ printf("[VIDEO] Capture Test fail -- capture data doesn't match source \n");
++ printf("[VIDEO]2 i=%d value=%x\n", i, dwValue);
++ ulFlag = 1;
++ break;
++ }
++
++ dwValue = *(ULONG *)(ulVGABaseAddr + i*32 + 8);
++ if (0x80808080 != dwValue)
++ {
++ printf("[VIDEO] Capture Test fail -- capture data doesn't match source \n");
++ printf("[VIDEO]3 i=%d value=%x\n", i, dwValue);
++ ulFlag = 1;
++ break;
++ }
++
++ dwValue = *(ULONG *)(ulVGABaseAddr + i*32 + 12);
++ if (0x80808080 != dwValue)
++ {
++ printf("[VIDEO] Capture Test fail -- capture data doesn't match source \n");
++ printf("4 i=%d value=%x\n", i, dwValue);
++ ulFlag = 1;
++ break;
++ }
++
++ dwValue = *(ULONG *)(ulVGABaseAddr + i*32 + 16);
++ if (0x80808080 != dwValue)
++ {
++ printf("[VIDEO] Capture Test fail -- capture data doesn't match source \n");
++ printf("5 i=%d value=%x\n", i, dwValue);
++ ulFlag = 1;
++ break;
++ }
++
++ dwValue = *(ULONG *)(ulVGABaseAddr + i*32 + 20);
++ if (0x80808080 != dwValue)
++ {
++ printf("[VIDEO] Capture Test fail -- capture data doesn't match source \n");
++ printf("6 i=%d value=%x\n", i, dwValue);
++ ulFlag = 1;
++ break;
++ }
++ }
++#endif
++
++ if (!ulFlag)
++ {
++ printf("[VIDEO] Capture Test OK\n");
++ }
++ else
++ {
++ printf("[VIDEO] Capture Test FAIL\n");
++ return VIDEO_TEST_FAIL;
++ }
++
++ return VIDEO_TEST_OK;
++}
++
++/********************************************************/
++/* Only used in the station */
++/********************************************************/
++int CRTTest(void)
++{
++ ULONG ulVGABaseAddr;
++ BYTE btCRTCenterMode, btCRTColorFmt;
++ USHORT usCRTHor, usCRTVer;
++ ULONG ulData;
++
++ int i,j;
++
++ //printf("\n --------- Turn on CRT --------- \n");
++
++ //Enable CRT1 first
++ ulVGABaseAddr = vBufAlign((unsigned long)pCrt1Addr);
++
++ btCRTCenterMode = 0;
++ btCRTColorFmt = YUV_444;
++ usCRTHor = g_DefWidth;
++ usCRTVer = g_DefHeight;
++
++ CheckOnStartClient();
++
++ /* Fill Pattern */
++ for (i=0; i<usCRTHor; i++)
++ {
++ for (j=0; j<usCRTVer/8; j++)
++ {
++ //Y
++ //ulData = 0x10101010;
++ ulData = 0x32323232;
++ *(ULONG *)(ulVGABaseAddr + (i*usCRTVer*4+j*32)) = ulData;
++ //ulData = 0x10101010;
++ ulData = 0x32323232;
++ *(ULONG *)(ulVGABaseAddr + (i*usCRTVer*4+j*32) +4) = ulData;
++ //U
++ ulData = 0x80808080;
++ //ulData = 0x77777777;
++ *(ULONG *)(ulVGABaseAddr + (i*usCRTVer*4+j*32) +8) = ulData;
++ ulData = 0x80808080;
++ //ulData = 0x77777777;
++ *(ULONG *)(ulVGABaseAddr + (i*usCRTVer*4+j*32) +12) = ulData;
++ //V
++ ulData = 0x80808080;
++ //ulData = 0x11111111;
++ *(ULONG *)(ulVGABaseAddr + (i*usCRTVer*4+j*32) +16) = ulData;
++ ulData = 0x80808080;
++ //ulData = 0x11111111;
++ *(ULONG *)(ulVGABaseAddr + (i*usCRTVer*4+j*32) +20) = ulData;
++ //A
++ ulData = 0xFFFFFFFFF;
++ *(ULONG *)(ulVGABaseAddr + (i*usCRTVer*4+j*32) +24) = ulData;
++ ulData = 0xFFFFFFFFF;
++ *(ULONG *)(ulVGABaseAddr + (i*usCRTVer*4+j*32) +28) = ulData;
++ }
++ } /* ~Fill Pattern */
++
++#if defined(CONFIG_AST2300)
++ if(!ASTSetModeV (0, CRT_2, ulVGABaseAddr, usCRTHor, usCRTVer, btCRTColorFmt, btCRTCenterMode))
++#else
++ if(!ASTSetModeV (0, CRT_1, ulVGABaseAddr, usCRTHor, usCRTVer, btCRTColorFmt, btCRTCenterMode))
++#endif
++ {
++ printf("[VIDEO] The resolution is not in mode table list\n");
++ return CRT_FAIL;
++ }
++
++ //printf("[VIDEO] CRT turn on\n");
++
++ return VIDEO_TEST_OK;
++}
++
++int do_videotest (void)
++{
++ int dwValue=0;
++ int i = 0;
++ int iRet;
++ ULONG ulRestore1, ulTemp;
++ BOOL bClient;
++
++
++ //InitVideoTest();
++ g_DefWidth = 640;
++ g_DefHeight= 480;
++
++ printf("\n --------- Codec Test --------- \n");
++
++#if defined(CONFIG_AST2300)
++ WriteMemoryLongWithMASKHost(SCU_BASE, SCU_CONTROL_REG, 0x00002000, 0x00002000);
++#endif
++
++ CheckOnStartHost();
++
++ do
++ {
++ dwValue = UnlockVideoRegHost(0, VIDEO_UNLOCK_KEY);
++ i++;
++ }
++ while ((VIDEO_UNLOCK != dwValue) && (i<1000));
++
++ if (VIDEO_UNLOCK != dwValue)
++ {
++ printf("[VIDEO] Video register is locked \n");
++ return VIDEO_TEST_FAIL;
++ }
++ AllocateEncodeBufHost(0, VIDEO1);
++
++ iRet = CodecTest();
++ if (iRet)
++ return VIDEO_TEST_FAIL;
++
++#if defined(CONFIG_AST2300)
++ /* Init SCU */
++ WriteMemoryLongWithMASKHost(SCU_BASE, (0x2c + SCU_OFFSET), 0x00040000, 0x00040010); /* Enable D2-PLL */
++ WriteMemoryLongWithMASKHost(SCU_BASE, SCU_CLOCK_STOP_REG, 0, 0x00000400); /* Enable D2CLK */
++ udelay(10);
++ WriteMemoryLongWithMASKHost(SCU_BASE, SCU_CONTROL_REG, 0, 0x00002000);
++
++ WriteMemoryLongWithMASKHost(SCU_BASE, (0x90 + SCU_OFFSET), 0x20, 0x00000030); /* enable video mode single edge */
++ WriteMemoryLongWithMASKHost(SCU_BASE, (0x84 + SCU_OFFSET), 0xfffe0000, 0xfffe0000); /* multi-pins */
++ WriteMemoryLongWithMASKHost(SCU_BASE, (0x88 + SCU_OFFSET), 0x000fffff, 0x000fffff); /* multi-pins */
++
++ iRet = CRTTest();
++ if (iRet)
++ {
++ printf("[VIDEO] CRT Test Failed \n");
++ return VIDEO_TEST_FAIL;
++ }
++
++ iRet = CapTest();
++ if (iRet)
++ {
++ printf("[VIDEO] Capture Test Failed \n");
++ return VIDEO_TEST_FAIL;
++ }
++#else
++ //Host or Client
++ bClient = ((ReadMemoryLong(SCU_BASE, SCU_HW_TRAPPING_REG) & CLIENT_MODE_EN_MASK)?TRUE:FALSE);
++ //reset video for another testing
++ ResetVideoHost();
++ dwValue=0;
++ i = 0;
++ do
++ {
++ dwValue = UnlockVideoRegHost(0, VIDEO_UNLOCK_KEY);
++ i++;
++ }
++ while ((VIDEO_UNLOCK != dwValue) && (i<10));
++
++ if (VIDEO_UNLOCK != dwValue)
++ {
++ printf("[VIDEO] Video register is locked");
++ return VIDEO_UNLOCK_FAIL;
++ }
++
++ //check if 1e6e0008[3,0] is 0
++ ulRestore1 = ReadMemoryLongHost(0x1e6e0000, 8);
++ dwValue = ReadMemoryLongHost(0x1e6e0000, 8)&0xF;
++
++ //set 1e6e0008[3,0] to 0
++ if (dwValue)
++ {
++ WriteMemoryLongHost(0x1e6e0000, 0, 0xfc600309);
++
++ i=0;
++ do
++ {
++ i++;
++ dwValue = ReadMemoryLongHost(0x1e6e0000,0);
++ }while((1 != dwValue)&& (i<10));
++
++ if (1 != dwValue)
++ {
++ printf("0x1e6e0000 is locked");
++ return VIDEO_UNLOCK_FAIL;
++ }
++ }
++
++ //only clear 1e6e0008[3,0]
++ WriteMemoryLongWithMASKHost(0x1e6e0000, 8, 0, 0xf);
++
++ bClient = 0;
++ if (!bClient)
++ {
++ //To turn on crt, must be the client mode
++ WriteMemoryLongWithMASKHost(SCU_BASE, SCU_HW_TRAPPING_REG, (BE_CLIENT_CHIP << CLIENT_MODE_EN_BIT), CLIENT_MODE_EN_MASK);
++
++ iRet = CRTTest();
++
++ if (iRet)
++ {
++ //trapping to host, the Vsync of CRT can't output and the host doesn't have video sync input
++ WriteMemoryLongWithMASKHost(SCU_BASE, SCU_HW_TRAPPING_REG, (BE_HOST_CHIP << CLIENT_MODE_EN_BIT), CLIENT_MODE_EN_MASK);
++ //restore value
++ WriteMemoryLongHost(0x1e6e0000, 8, ulRestore1);
++ //lock register
++ WriteMemoryLongHost(0x1e6e0000, 0, 0x12345678);
++ return VIDEO_TEST_FAIL;
++ }
++
++ iRet = CapTest();
++
++ if (iRet)
++ {
++ //trapping to host, the Vsync of CRT can't output and the host doesn't have video sync input
++ WriteMemoryLongWithMASKHost(SCU_BASE, SCU_HW_TRAPPING_REG, (BE_HOST_CHIP << CLIENT_MODE_EN_BIT), CLIENT_MODE_EN_MASK);
++ //restore value
++ WriteMemoryLongHost(0x1e6e0000, 8, ulRestore1);
++ //lock register
++ WriteMemoryLongHost(0x1e6e0000, 0, 0x12345678);
++
++ return VIDEO_TEST_FAIL;
++ }
++ //WriteMemoryLongWithMASKHost(SCU_BASE, SCU_HW_TRAPPING_REG, (BE_HOST_CHIP << CLIENT_MODE_EN_BIT), CLIENT_MODE_EN_MASK);
++ }
++ //trapping to host, the Vsync of CRT can't output and the host doesn't have video sync input
++ WriteMemoryLongWithMASKHost(SCU_BASE, SCU_HW_TRAPPING_REG, (BE_HOST_CHIP << CLIENT_MODE_EN_BIT), CLIENT_MODE_EN_MASK);
++ //restore value
++ WriteMemoryLongHost(0x1e6e0000, 8, ulRestore1);
++ //lock register
++ WriteMemoryLongHost(0x1e6e0000, 0, 0x12345678);
++#endif
++
++ return VIDEO_TEST_OK;
++}
++#endif /* CONFIG_SLT */
+diff --git a/board/aspeed/ast2300/videotest.h b/board/aspeed/ast2300/videotest.h
+new file mode 100755
+index 0000000..79b8dd9
+--- /dev/null
++++ b/board/aspeed/ast2300/videotest.h
+@@ -0,0 +1,24 @@
++/*
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++ */
++/* VideoTest.h */
++#ifndef _VIDEOTEST_H_
++#define _VIDEOTEST_H_
++
++#define VIDEO_TEST_OK 0
++#define VIDEO_TEST_FAIL 1
++
++#define VIDEO_UNLOCK_FAIL 1
++#define VIDEO_ENCODE_FAIL 2
++#define VIDEO_DECODE_FAIL 3
++#define CRT_FAIL 4
++
++#endif /* _VIDEOTEST_H_ */
++
+diff --git a/board/aspeed/ast2300/vreg.h b/board/aspeed/ast2300/vreg.h
+new file mode 100755
+index 0000000..9738548
+--- /dev/null
++++ b/board/aspeed/ast2300/vreg.h
+@@ -0,0 +1,845 @@
++/*
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++ */
++#ifndef _VREG_H_
++#define _VREG_H_
++
++/********************************************************/
++/* CRT register */
++/********************************************************/
++#define CRT_BASE_ADDRESS 0x000400
++#define VGA_GRAPH_BASE_ADDRESS 0x600000
++#define VGA_CURSOR_BASE_ADDRESS 0x300000
++#define VGA_OSD_BASE_ADDRESS 0x300000
++#define RGB_565 0x0
++#define RGB_888 0x1
++#define YUV_444 0x2
++#define NO_SUPPORTED_CRT_FMT 0x3
++#define CRT_LOW_THRESHOLD_VALUE 0x12
++#define CRT_HIGH_THRESHOLD_VALUE 0x1E
++
++// AST3000's Registers
++#ifdef Watcom
++#define VIDEOBASE_OFFSET 0x10000
++#else
++#define VIDEOBASE_OFFSET 0x0
++#endif
++
++#define KEY_CONTROL_REG 0x00 + VIDEOBASE_OFFSET
++ #define VIDEO_LOCKED 0
++ #define VIDEO_UNLOCK 1
++
++// Registers for video1 and video2
++#define VIDEO1_ENGINE_SEQUENCE_CONTROL_REG 0x04 + VIDEOBASE_OFFSET
++#define VIDEO2_ENGINE_SEQUENCE_CONTROL_REG 0x104 + VIDEOBASE_OFFSET
++ #define MODE_DETECTION_TRIGGER 0x00000001 //Bit[0] trigger HW auto mode detection
++ #define VIDEO_CAPTURE_TRIGGER 0x00000002 //Bit[1] trigger HW to capture video
++ #define FORCE_HW_IDLE_MASK (1<<2) //Bit[2] Force engine into ready(idle) state
++ #define ENGINE_RESET (0<<2)
++ #define ENGINE_IDLE (1<<2)
++ #define VIDEO_CAPTURE_AUTO_MODE 0x00000008 //Bit[3]
++ #define CAPTURE_FRAME_MODE 0
++ #define CAPTURE_AUTO_MODE 1
++ #define CAPTURE_AUTO_MODE_BIT 3
++ #define CAPTURE_AUTO_MODE_MASK 0x00000008
++ #define VIDEO_CODEC_TRIGGER 0x00000010 //Bit[4] trigger HW to compress or decompress video
++ #define CODEC_TRIGGER_BIT 4
++ #define CODEC_TRIGGER_MASK 0x00000010
++ #define CLEAR_CODEC_TRIGGER 0
++ #define EN_CODEC_TRIGGER 1
++ #define VIDEO_CODEC_AUTO_MODE 0x00000020 //Bit[5]
++ #define CODEC_FRAME_MODE 0
++ #define CODEC_AUTO_MODE 1
++ #define CODEC_AUTO_MODE_BIT 5
++ #define CODEC_AUTO_MODE_MASK 0x00000020
++ #define INSERT_FULL_FRAME_MASK (1<<6) //Bit[6] Insert full frame compression
++ #define INSERT_FULL_FRAME_EN (1<<6)
++ #define INSERT_FULL_FRAME_OFF (0<<6)
++ #define WATCH_DOG_ENABLE 0x00000080 //Bit[7] Video Enable watch dog for mode change detection
++ #define WATCH_DOG_ENABLE_BIT 7
++ #define WATCH_DOG_OFF 0
++ #define WATCH_DOG_EN 1
++ #define WATCH_DOG_EN_MASK 0x00000080
++ #define VIDEO_CRT_SELECTION 0x00000100 //Bit[8]
++ #define CRT1 0
++ #define CRT2 1
++ #define ANTI_TEARING_ENABLE 0x00000200 //Bit[9] Anti-tearing mode enable for decoding
++ #define ANTI_TEARING_EN 1
++ #define STREAM_DATA_MODE 0x00000400 //Bit[11:10] Buffer and Stream Data type
++ #define STREAM_DATA_MODE_BIT 10
++ #define STREAM_DATA_MODE_MASK 0x00000C00
++ #define YUV444_MODE 0
++ #define YUV420_MODE 1
++ #define YUV420_MODE_WITH_AST2000 2 //AST2000 compatible
++ #define VIDEO_CAPTURE_READY 0x00010000 //Bit[16] Video capture ready status read back(read only)
++ #define CAPTURE_READY_MASK 0x00010000
++ #define HW_BUSY 0
++ #define HW_IDLE 1
++ #define VIDEO_CODEC_READY 0x00040000 //Bit[18] Video codec ready status read back(read only)
++ #define CODEC_READY_MASK 0x00040000
++ //#define HW_BUSY 0
++ //#define HW_IDLE 1
++
++#define VIDEO1_CONTROL_REG 0x08 + VIDEOBASE_OFFSET
++#define VIDEO2_CONTROL_REG 0x108 + VIDEOBASE_OFFSET
++ #define VIDEO_HSYNC_POLARITY 0x00000001 //Bit[0] Video source hsync polarity
++ #define VIDEO_HSYNC_POLARITY_BIT 0
++ #define NO_INVERSE_POL 0
++ #define INVERSE_POL 1
++ #define VIDEO_VSYNC_POLARITY 0x00000002 //Bit[1] Video source vsync polarity
++ #define VIDEO_VSYNC_POLARITY_BIT 1
++ //Setting defination the same as VIDEO_HSYNC_POLARITY
++ #define VIDEO_EXTERNAL_SOURCE 0x00000004 //Bit[2] Video external source
++ #define EXTERNAL_SOURCE_BIT 2
++ #define INTERNAL_VGA_SOURCE 0
++ #define EXTERNAL_VGA_SOURCE 1
++ #define EXTERNAL_SOURCE_MASK 0x00000004
++ #define VIDEO_ANALONG_EXTERNAL_SOURCE 0x00000008 //Bit[3] Video Analog external source
++ #define ANALONG_EXTERNAL_SOURCE_BIT 3
++ #define DVI_SOURCE 0
++ #define ANALOG_RGB_SOURCE 1
++ #define VIDEO_INTERNAL_TIMING_GEN 0x00000010 //Bit[4] Video Use internal timing generator
++ #define INTERNAL_TIMING_GEN_BIT 4
++ #define EXTERNAL_DE_SIGNAL 0 //DVI only
++ #define VR0C_VR10_DE_SINGAL 1 //use VR0C and VR10 for generate VDE signal
++ /****** Video2 Only from DAC ******/
++ #define VIDEO1_CAPTURE_FROM 0x00000020 //Bit[5] Video1 capture data direct from VGA frame buffer(internal VGA only)
++ #define FROM_DAC_PORT 0
++ #define FROM_FRAME_BUFFER 1
++ #define WRITE_DATA_FORMAT 0x00000040 //Bit[7:6] Write data format
++ #define WRITE_DATA_FORMAT_BIT 6
++ #define WRTIE_DATA_FORMAT_MASK 0x000000C0
++ #define CCIR601_2_YUV_FORMAT 0
++ #define FULL_YUV_FORMAT 1
++ #define RGB_FORMAT 2
++ #define VGA_CURSOR_DISABLE 0x00000100 //Bit[8] External video port slection
++ #define VGA_CURSOR_NORMAL 0
++ #define VGA_CURSOR_OFF 1
++ #define VIDEO_CAPTURE_LINEAR_MODE 0x00000200 //Bit[9] VIDEO_CAPTURE_LINEAR_MODE
++ #define LINEAR_MODE 0
++ #define TILE_MODE 1
++ #define VIDEO_CLOCK_DELAY 0x00000400 //Bit[11:10] Video clock delay control
++ #define VIDEO_CLOCK_DELAY_BIT 10
++ #define VIDEO_CLOCK_DELAY_MASK 0x00000C00
++ #define DELAY_0_NS 0
++ #define DELAY_1_NS 1
++ #define INV_AND_DELAY_0_NS 2
++ #define INV_AND_DELAY_1_NS 3
++ #define VIDEO_CCIR656_SOURCE_MODE 0x00001000 //Bit[12] Video CCIR656 source mode
++ #define RGB_SOURCE_MODE 0
++ #define CCIR656_SOURCE_MODE 1
++ #define SOURCE_PORT_CLOCK_MODE 0x00002000 //Bit[13] Video Source port clock mode
++ #define SINGLE_EDGE_MODE 0
++ #define DUAL_EDGE_MODE 1
++ #define EXTERNAL_PORT_SELECTION 0x00004000 //Bit[14] External video port slection
++ #define VIDEO_PORT_A 0
++ #define VIDEO_PORT_B 1
++ #define VIDEO_CAPTURE_FRAME_RATE 0x00010000 //Bit[23:16] Video capture frame rate control
++ #define VIDEO_CAPTURE_FRAME_RATE_BIT 16
++ #define VIDEO_CAPTURE_FRAME_RATE_MASK 0x00FF0000 //Maximum frame rate = XX * SourceFPS / 60
++
++#define VIDEO1_TIMEING_GEN_HOR_REG 0x0C + VIDEOBASE_OFFSET
++#define VIDEO2_TIMEING_GEN_HOR_REG 0x10C + VIDEOBASE_OFFSET
++ #define VIDEO_HDE_END 0x00000000 //Bit[12:0] Video HDE End timing generator
++ #define VIDEO_HDE_END_BIT 0 //Number of pixels from rising edge of Hsync for first active pixel
++ #define VIDEO_HDE_END_MASK 0x00001FFF
++ #define VIDEO_HDE_START 0x00010000 //Bit[28:16] Video HDE Start timing generator
++ #define VIDEO_HDE_START_BIT 16 //Number of pixels from rising edge of Hsync for last active pixel
++ #define VIDEO_HDE_START_MASK 0x1FFF0000
++ #define FRAME_RATE_OFF 0
++
++#define VIDEO1_TIMEING_GEN_V_REG 0x10 + VIDEOBASE_OFFSET
++#define VIDEO2_TIMEING_GEN_V_REG 0x110 + VIDEOBASE_OFFSET
++ #define VIDEO_VDE_END 0x00000001 //Bit[11:0] Video VDE End timing generator
++ #define VIDEO_VDE_END_BIT 0 //Number of pixels from rising edge of Vsync for first active pixel
++ #define VIDEO_VDE_END_MASK 0x00000FFF
++ #define VIDEO_VDE_START 0x00010000 //Bit[27:16] Video VDE Start timing generator
++ #define VIDEO_VDE_START_BIT 16 //Number of pixels from rising edge of Vsync for last active pixel
++ #define VIDEO_VDE_START_MASK 0x0FFF0000
++
++#define VIDEO1_SCALE_FACTOR_REG 0x14 + VIDEOBASE_OFFSET
++#define VIDEO2_SCALE_FACTOR_REG 0x114 + VIDEOBASE_OFFSET
++ #define HOR_SCALING_FACTOR 0x00000001 //Bit[15:0] Video Horizontal scaling factor
++ #define HOR_SCALING_FACTOR_BIT 0 //The formula=4096/(Horizontal scaling facotr)
++ #define HOR_SCALING_FACTOR_MASK 0x0000FFFF
++ #define VER_SCALING_FACTOR 0x00000000 //Bit[31:16] Video Vertical scaling factor
++ #define VER_SCALING_FACTOR_BIT 16 //The formula=4096/(Vertical scaling facotr)
++ #define VER_SCALING_FACTOR_MASK 0xFFFF0000
++
++#define VIDEO1_SCALE_FACTOR_PARAMETER0_REG 0x18 + VIDEOBASE_OFFSET //Scaling Parameters F00, F01, F02, F03
++#define VIDEO2_SCALE_FACTOR_PARAMETER0_REG 0x118 + VIDEOBASE_OFFSET
++
++#define VIDEO1_SCALE_FACTOR_PARAMETER1_REG 0x1C + VIDEOBASE_OFFSET //Scaling Parameters F10, F11, F12, F13
++#define VIDEO2_SCALE_FACTOR_PARAMETER1_REG 0x11C + VIDEOBASE_OFFSET
++
++#define VIDEO1_SCALE_FACTOR_PARAMETER2_REG 0x20 + VIDEOBASE_OFFSET //Scaling Parameters F20, F21, F22, F23
++#define VIDEO2_SCALE_FACTOR_PARAMETER2_REG 0x120 + VIDEOBASE_OFFSET
++
++#define VIDEO1_SCALE_FACTOR_PARAMETER3_REG 0x24 + VIDEOBASE_OFFSET //Scaling Parameters F30, F31, F32, F33
++#define VIDEO2_SCALE_FACTOR_PARAMETER3_REG 0x124 + VIDEOBASE_OFFSET
++
++#define VIDEO1_BCD_CONTROL_REG 0x2C + VIDEOBASE_OFFSET
++#define VIDEO2_BCD_CONTROL_REG 0x12C + VIDEOBASE_OFFSET
++ #define BCD_ENABLE 0x00000001 //Bit[0] Enable block change detection(BCD)
++ #define BCD_ENABLE_BIT 0
++ #define BCD_ENABLE_MASK 0x00000001
++ #define BCD_TOLERANCE 0x00010000 //Bit[23:16]
++ #define BCD_TOLERANCE_BIT 16 //flag as changed block when the video data difference greater
++ #define BCD_TOLERANCE_MASK 0x00FF0000
++
++#define VIDEO1_CAPTURE_WINDOWS_REG 0x30 + VIDEOBASE_OFFSET
++#define VIDEO2_CAPTURE_WINDOWS_REG 0x130 + VIDEOBASE_OFFSET
++ #define CAPTURE_VER_LINE 0x00000001 //Bit[10:0] Video compression vertical line total
++ #define CAPTURE_VER_LINE_BIT 0
++ #define CAPTURE_VER_LINE_MASK 0x000007FF
++ #define CAPTURE_HOR_PIXEL 0x00010000 //Bit[26:16] Video compression vertical line total
++ #define CAPTURE_HOR_PIXEL_BIT 16
++ #define CAPTURE_HOR_PIXEL_MASK 0x07FF0000
++
++#define VIDEO1_COMPRESS_WINDOWS_REG 0x34 + VIDEOBASE_OFFSET
++#define VIDEO2_COMPRESS_WINDOWS_REG 0x134 + VIDEOBASE_OFFSET
++ #define COMPRESS_VER_LINE 0x00000001 //Bit[10:0] Video compression vertical line total
++ #define COMPRESS_VER_LINE_BIT 0
++ #define COMPRESS_VER_LINE_MASK 0x000007FF
++ #define COMPRESS_HOR_PIXEL 0x00010000 //Bit[26:16] Video compression vertical line total
++ #define COMPRESS_HOR_PIXEL_BIT 16
++ #define COMPRESS_HOR_PIXEL_MASK 0x07FF0000
++
++#define VIDEO1_COMPRESS_BUF_PROCESS_OFFSET_REG 0x38
++#define VIDEO2_COMPRESS_BUF_PROCESS_OFFSET_REG 0x138
++ #define COMPRESS_BUF_PROCESS_OFFSET_ALIGN 127 //128 byte alignment
++ #define COMPRESS_BUF_PROCESS_OFFSET_MASK 0xFFFFFF
++
++#define VIDEO1_DECOMPRESS_BUF_PROCESS_OFFSET_REG 0x38
++#define VIDEO2_DECOMPRESS_BUF_PROCESS_OFFSET_REG 0x138
++ #define DECOMPRESS_BUF_PROCESS_OFFSET_ALIGN 127 //128 byte alignment
++ #define DECOMPRESS_BUF_PROCESS_OFFSET_MASK 0xFFFFFF
++
++
++//For Compression
++#define VIDEO1_COMPRESS_BUF_READ_OFFSET_REG 0x3C + VIDEOBASE_OFFSET //For stream mode
++#define VIDEO2_COMPRESS_BUF_READ_OFFSET_REG 0x13C + VIDEOBASE_OFFSET
++ #define COMPRESS_BUF_READ_OFFSET_ALIGN 127 //128 byte alignment
++ #define COMPRESS_BUF_READ_OFFSET_MASK 0x00FFFFFF
++//For Decompression
++#define VIDEO1_DECOMPRESS_BUF_WRITE_OFFSET_REG 0x3C + VIDEOBASE_OFFSET //For stream mode
++#define VIDEO2_DECOMPRESS_BUF_WRITE_OFFSET_REG 0x13C + VIDEOBASE_OFFSET
++ #define DECOMPRESS_BUF_WRITE_OFFSET_ALIGN 127 //128 byte alignment
++ #define DECOMPRESS_BUF_WRITE_OFFSET_MASK 0x00FFFFFF
++
++#define VIDEO1_CRC_BUF_ADDR_REG 0x40 + VIDEOBASE_OFFSET
++#define VIDEO2_CRC_BUF_ADDR_REG 0x140 + VIDEOBASE_OFFSET
++ #define CRC_BUF_ADDR_ALIGN 7 //8 byte alignment
++ #define CRC_BUF_ADDR_MASK 0x0FFFFFFF
++
++#define VIDEO1_BUF_1_ADDR_REG 0x44 + VIDEOBASE_OFFSET //For Source Buffer in frame mode
++#define VIDEO2_BUF_1_ADDR_REG 0x144 + VIDEOBASE_OFFSET
++ #define BUF_1_ADDR_ALIGN 255 //256 byte alignment
++ #define BUF_1_ADDR_MASK 0x1FFFFFFF
++
++#define VIDEO1_BUF_LINE_OFFSET_REG 0x48 + VIDEOBASE_OFFSET //Must set both in Frame/Stream mode
++#define VIDEO2_BUF_LINE_OFFSET_REG 0x148 + VIDEOBASE_OFFSET
++ #define BUF_LINE_OFFSET_ALIGN 7 //8 byte alignment
++ #define BUF_LINE_OFFSET_MASK 0x00003FFF
++
++#define VIDEO1_BUF_2_ADDR_REG 0x4C + VIDEOBASE_OFFSET //For BCD Buffer in frame mode
++#define VIDEO2_BUF_2_ADDR_REG 0x14C + VIDEOBASE_OFFSET
++ #define BUF_2_ADDR_ALIGN 255 //256 byte alignment
++ #define BUF_2_ADDR_MASK 0x1FFFFFFF
++
++#define VIDEO1_FLAG_BUF_ADDR_REG 0x50 + VIDEOBASE_OFFSET //For block change flag buffer
++#define VIDEO2_FLAG_BUF_ADDR_REG 0x150 + VIDEOBASE_OFFSET
++ #define FLAG_BUF_ADDR_ALIGN 7 //8 byte alignment
++ #define FLAG_BUF_ADDR_MASK 0x1FFFFFFF
++
++#define VIDEO1_COMPRESS_BUF_ADDR_REG 0x54 + VIDEOBASE_OFFSET //For stream mode
++#define VIDEO2_COMPRESS_BUF_ADDR_REG 0x154 + VIDEOBASE_OFFSET
++ #define COMPRESS_BUF_ADDR_ALIGN 127 //128 byte alignment
++ #define COMPRESS_BUF_ADDR_MASK 0x1FFFFFFF
++
++#define VIDEO1_STREAM_BUF_SIZE 0x58 + VIDEOBASE_OFFSET //For stream mode
++#define VIDEO2_STREAM_BUF_SIZE 0x158 + VIDEOBASE_OFFSET
++ #define STREAM_PACKET_SIZE 0x00000001
++ #define STREAM_PACKET_SIZE_BIT 0
++ #define STREAM_PACKET_SIZE_MASK 0x00000007
++ #define PACKET_SIZE_1KB 0
++ #define PACKET_SIZE_2KB 1
++ #define PACKET_SIZE_4KB 2
++ #define PACKET_SIZE_8KB 3
++ #define PACKET_SIZE_16KB 4
++ #define PACKET_SIZE_32KB 5
++ #define PACKET_SIZE_64KB 6
++ #define PACKET_SIZE_128KB 7
++ #define RING_BUF_PACKET_NUM 0x00000008
++ #define RING_BUF_PACKET_NUM_BIT 3
++ #define RING_BUF_PACKET_NUM_MASK 0x00000018
++ #define PACKETS_4 0
++ #define PACKETS_8 1
++ #define PACKETS_16 2
++ #define PACKETS_32 3
++ #define SKIP_HIGH_MB_THRES 0x00010000 //Bit[22:16] Skip high quality macro block threshold
++ #define SKIP_HIGH_MB_THRES_BIT 16
++ #define SKIP_HIGH_MB_THRES_MASK 0x007F0000
++ #define SKIP_TEST_MODE 0x00800000 //Bit[24:23] Skip test mode
++ #define SKIP_TEST_MODE_BIT 23
++ #define SKIP_TEST_MODE_MASK 0x01800000
++ #define YUV_TEST 2 //recommend
++
++#define VIDEO1_BUF_CODEC_OFFSET_READ 0x5C + VIDEOBASE_OFFSET //For stream mode,
++#define VIDEO2_BUF_CODEC_OFFSET_READ 0x15C + VIDEOBASE_OFFSET //Video stream buffer offset read back(HW)
++ #define BUF_CODEC_OFFSET_ALIGN 255 //256 byte alignment
++ #define BUF_CODEC_OFFSET_MASK 0x00FFFFFF
++
++#define VIDEO1_COMPRESS_CONTROL_REG 0x60 + VIDEOBASE_OFFSET
++#define VIDEO2_COMPRESS_CONTROL_REG 0x160 + VIDEOBASE_OFFSET
++ #define JPEG_ONLY_ENCODE 0x00000001 //Bit[0] JPEG only encoding
++ #define JPEG_ONLY_BIT 0
++ #define JPEG_MIX_MODE 0 //Enable JPEG/VQ mix mode encoding
++ #define JPEG_ONLY_MODE 1 //JPEG encoding mode only
++ #define VQ_4_COLOR_ENCODE 0x00000002 //Bit[1] Enable 4 color VQ encoding
++ #define VQ_4_COLOR_BIT 1
++ #define VQ_1_2_COLOR_MODE 0 //1 and 2 color mode VQ encoding
++ #define VQ_4_COLOR_MODE 1 //1, 2 and 4 color VQ encoding
++ #define QUALITY_CODEC_SETTING 0x00000004 //Bit[2] High and best video quality codec mode setting
++ #define QUALITY_CODEC_SETTING_BIT 2
++ #define JPEG_CODEC_MODE 0 //not supported in best video quality mode
++ #define QUANTI_CODEC_MODE 1
++ #define JPEG_DUAL_QUALITY_EN 0x00000008 //Bit[3] JPEG dual quality mode
++ #define EN_JPEG_DUAL_QUALITY 1 //enable(only for normal video quality mode)
++ #define BEST_QUALITY_EN 0x00000010 //Bit[4] Best quality video mode enable
++ #define BEST_QUALITY_EN_BIT 4
++ #define EN_BEST_QUALITY 1 //enable(only for quantization codec mode)
++ #define RC4_CRYPT_EN 0x00000020 //Bit[5] Enable RC4 encryption/decryption
++ #define RC4_CRYPT_EN_BIT 5
++ #define RC4_CRYPT_EN_MASK 0x00000020
++ #define RC4_CRYPT_ON 1 //enable
++ #define NORMAL_QUANTI_CHROMI_TABLE 0x00000040 //Bit[10:6] Normal video quality mode JPEG DCT chromi quantination table
++ #define NORMAL_QUANTI_CHROMI_TABLE_BIT 6
++ #define NORMAL_QUANTI_CHROMI_TABLE_MASK 0x000007C0
++ #define NORMAL_QUANTI_LUMI_TABLE 0x00000800 //Bit[15:11] Normal video quality mode JPEG DCT lumi quantination table
++ #define NORMAL_QUANTI_LUMI_TABLE_BIT 11
++ #define NORMAL_QUANTI_LUMI_TABLE_MASK 0x0000F800
++ #define HIGH_QUALITY_EN 0x00010000 //Bit[16] High video quality mode enable
++ #define HIGH_QUALITY_EN_BIT 16
++ #define EN_HIGH_QUALITY 1 //Enable
++ #define UV_CIR656_FORMAT 0x00080000 //Bit[19] UV fromat
++ #define UV_CIR656_FORMAT_BIT 19
++ #define USE_UV_CIR656 1 //recommand
++ #define HUFFMAN_TABLE_SELECT 0x00100000 //Bit[20] JPEG Huffman table combination
++ #define DUAL_TABLE 0 //Dual Y, UV table
++ #define SINGLE_TABLE 1 //Single Y table
++ #define SINGLE_UV_TABLE 0x00200000 //1x: Single UV table
++ #define HIGH_QUANTI_CHROMI_TABLE 0x00400000 //Bit[26:22] High quality JPEG DCT chromi quantization table
++ #define HIGH_QUANTI_CHROMI_TABLE_BIT 22
++ #define HIGH_QUANTI_CHROMI_TABLE_MASK 0x07C00000
++ #define HIGH_DEQUANTI_VALUE 0x00400000 //Bit[26:22] High quality de-quantization value
++ #define HIGH_DEQUANTI_VALUE_BIT 22
++ #define HIGH_DEQUANTI_VALUE_MASK 0x07C00000
++ #define HIGH_QUANTI_LUMI_TABLE 0x08000000 //Bit[31:27] High quality JPEG DCT lumi quantization table
++ #define HIGH_QUANTI_LUMI_TABLE_BIT 27
++ #define HIGH_QUANTI_LUMI_TABLE_MASK 0xF8000000
++ #define BEST_DEQUANTI_VALUE 0x08000000 //Bit[31:27] Best quality de-quantization value
++ #define BEST_DEQUANTI_VALUE_BIT 27
++ #define BEST_DEQUANTI_VALUE_MASK 0xF8000000
++
++
++#define VIDEO1_QUANTI_TABLE_LOW_REG 0x64 + VIDEOBASE_OFFSET //Match with 0x60 Bit[10:6], Bit[15:11]
++#define VIDEO2_QUANTI_TABLE_LOW_REG 0x164 + VIDEOBASE_OFFSET
++ #define QUANTI_CHROMI_TABLE_LOW 0x00000001 //Bit[4:0] Normal video low quality block chromi quantization table
++ #define QUANTI_CHROMI_TABLE_LOW_BIT 0
++ #define QUANTI_CHROMI_TABLE_LOW_MASK 0x0000001F
++ #define QUANTI_LUMI_TABLE_LOW 0x00000020 //Bit[9:5] Normal video low quality block lumi quantization table
++ #define QUANTI_LUMI_TABLE_LOW_BIT 5
++ #define QUANTI_LUMI_TABLE_LOW_MASK 0x000003E0
++
++#define VIDEO1_QUANTI_VALUE_REG 0x68 + VIDEOBASE_OFFSET //Match with 0x60 Bit[26:22],Bit[31:27]
++#define VIDEO2_QUANTI_VALUE_REG 0x168 + VIDEOBASE_OFFSET
++ #define HIGH_QUANTI_VALUE 0x00000001 //Bit[14:0] High quality quantization value. Format is 1.14
++ #define HIGH_QUANTI_VALUE_BIT 0
++ #define HIGH_QUANTI_VALUE_MASK 0x00007FFF
++ #define BEST_QUANTI_VALUE 0x00010000 //Bit[30:16] Best quality quantization value. Format is 1.14
++ #define BEST_QUANTI_VALUE_BIT 16
++ #define BEST_QUANTI_VALUE_MASK 0x7FFF0000
++
++#define VIDEO1_BSD_PARA_REG 0x6C + VIDEOBASE_OFFSET //Video BSD Parameters Register
++#define VIDEO2_BSD_PARA_REG 0x16C + VIDEOBASE_OFFSET
++ #define BSD_HIGH_THRES 0x00000001 //Bit[7:0] Block sharpness detection high threshold
++ #define BSD_HIGH_THRES_BIT 0
++ #define BSD_HIGH_THRES_MASK 0x000000FF
++ #define BSD_LOW_THRES 0x00000100 //Bit[15:8] Block shaprpness detection low threshold
++ #define BSD_LOW_THRES_BIT 8
++ #define BSD_LOW_THRES_MASK 0x0000FF00
++ #define BSD_HIGH_COUNTS 0x00010000 //Bit[21:16] Block sharpness detection high counts threshold
++ #define BSD_HIGH_COUNTS_BIT 16
++ #define BSD_HIGH_COUNTS_MASK 0x003F0000
++ #define BSD_LOW_COUNTS 0x00400000 //Bit[27:22] Block sharpness detection low counts threshold
++ #define BSD_LOW_COUNTS_BIT 22
++ #define BSD_LOW_COUNTS_MASK 0x0FC00000
++
++#define VIDEO1_COMPRESS_FRAME_SIZE_REG 0x70 + VIDEOBASE_OFFSET
++#define VIDEO2_COMPRESS_FRAME_SIZE_REG 0x170 + VIDEOBASE_OFFSET
++ #define COMPRESS_FRAME_SIZE_READ 0x00000001 //Bit[19:0] Video compression frame size read back(number of DW)
++ #define COMPRESS_FRAME_SIZE_READ_BIT 0
++ #define COMPRESS_FRAME_SIZE_READ_MASK 0x003FFFFF
++
++#define VIDEO1_COMPRESS_BLOCK_COUNT_REG 0x74 + VIDEOBASE_OFFSET
++#define VIDEO2_COMPRESS_BLOCK_COUNT_REG 0x174 + VIDEOBASE_OFFSET
++ #define PROCESS_BLOCK_COUNT_READ_BIT 0
++ #define PROCESS_BLOCK_COUNT_READ_MASK 0x00003FFF //Bit[13:0] Video processed total block counter read back(number of blocks)
++ #define COMPRESS_BLOCK_COUNT_READ_BIT 16
++ #define COMPRESS_BLOCK_COUNT_READ_MASK 0xFFFF0000 //Bit[29:16] Video processed total block counter read back(number of blocks)
++
++#define VIDEO1_COMPRESS_FRAME_END_READ 0x78 + VIDEOBASE_OFFSET //Video compression stream frame end pointer
++#define VIDEO2_COMPRESS_FRAME_END_READ 0x178 + VIDEOBASE_OFFSET
++ #define COMPRESS_FRAME_END_READ_ALIGN 7
++ #define COMPRESS_FRAME_END_READ_MASK 0x00FFFFFF
++
++#define VIDEO1_COMPRESS_FRAME_COUNT_READ 0x7C + VIDEOBASE_OFFSET
++#define VIDEO2_COMPRESS_FRAME_COUNT_READ 0x17C + VIDEOBASE_OFFSET
++ #define COMPRESS_FRAME_COUNT_READ 0x00000001 //Bit[15:0] Video compression frame count read back(number of frame)
++ #define COMPRESS_FRAME_COUNT_READ_BIT 0
++ #define COMPRESS_FRAME_COUNT_READ_MASK 0xFFFFFFFF
++
++#define VIDEO1_USER_DEFINE_HEADER 0x80 + VIDEOBASE_OFFSET
++#define VIDEO2_USER_DEFINE_HEADER 0x180 + VIDEOBASE_OFFSET
++ #define USER_DEFINE_HEADER 0x00000001 //Bit[15:0] Video user defined header parameter
++ #define USER_DEFINE_HEADER_BIT 0
++ #define USER_DEFINE_HEADER_MASK 0x0000FFFF
++
++#define VIDE1_MODE_DETECTION_EDGE_H_REG 0x90 + VIDEOBASE_OFFSET
++#define VIDE2_MODE_DETECTION_EDGE_H_REG 0x190 + VIDEOBASE_OFFSET
++ #define LEFT_EDGE_LOCATION 0x00000001 //Bit[11:0] Video source left edge location from sync rising edge
++ #define LEFT_EDGE_LOCATION_BIT 0
++ #define LEFT_EDGE_LOCATION_MASK 0x00000FFF
++ #define NO_VER_SYNC (1 << 12) //Bit[12] No Vertical sync detected
++ #define NO_HOR_SYNC (1 << 13) //Bit[13] No horizontal sync detected
++ #define NO_ACTIVE_DISP (1 << 14) //Bit[14] No active display detected
++ #define NO_DISP_CLOCK (1 << 15)
++ #define RIGHT_EDGE_LOCATION 0x00010000 //Bit[27:16] Video source right edge location from sync rising edge
++ #define RIGHT_EDGE_LOCATION_BIT 16
++ #define RIGHT_EDGE_LOCATION_MASK 0x0FFF0000
++
++#define VIDE1_MODE_DETECTION_EDGE_V_REG 0x94 + VIDEOBASE_OFFSET
++#define VIDE2_MODE_DETECTION_EDGE_V_REG 0x194 + VIDEOBASE_OFFSET
++ #define TOP_EDGE_LOCATION 0x00000001 //Bit[11:0] Video source top edge location from sync rising edge
++ #define TOP_EDGE_LOCATION_BIT 0
++ #define TOP_EDGE_LOCATION_MASK 0x00000FFF
++ #define BOTTOM_EDGE_LOCATION 0x00010000 //Bit[27:16] Video source bottom edge location from sync rising edge
++ #define BOTTOM_EDGE_LOCATION_BIT 16
++ #define BOTTOM_EDGE_LOCATION_MASK 0x0FFF0000
++
++#define VIDEO1_MODE_DETECTION_STATUS_READ_REG 0x98 + VIDEOBASE_OFFSET
++#define VIDEO2_MODE_DETECTION_STATUS_READ_REG 0x198 + VIDEOBASE_OFFSET
++ #define MODE_DETECTION_HOR_TIME_READ 0x00000001 //Bit[11:0] Mode detection Horizontal time read back (read only)
++ #define MODE_DETECTION_HOR_TIME_READ_BIT 0
++ #define MODE_DETECTION_HOR_TIME_READ_MASK 0x00000FFF
++ #define ANALONG_DIGITAL_READ 0x00001000 //Bit[12] Auto detection for external analog or digital source read back
++ #define ANALONG_DIGITAL_READ_BIT 12
++ #define DVI_SIGNAL 0
++ #define ADC_SIGNAL 1
++ #define MODE_DETECTION_HOR_STABLE_READ 0x00002000 //Bit[13] Mode detection horizontal stable read back
++ #define HOR_STABLE 1
++ #define MODE_DETECTION_VER_STABLE_READ 0x00004000 //Bit[14] Mode detection vertical stable read back
++ #define VER_STABLE 1
++ #define OUT_LOCK_READ 0x00008000 //Bit[15] Mode detection out of lock read back
++ #define SIGNAL_OUT_LOCK 1
++ #define MODE_DETECTION_VER_LINE_READ 0x00010000 //Bit[27:16] Mode detection Vertical lines read back
++ #define MODE_DETECTION_VER_LINE_READ_BIT 16
++ #define MODE_DETECTION_VER_LINE_READ_MASK 0x0FFF0000
++ #define VSYNC_POLARITY_READ 0x10000000 //Bit[28] Vsync polarity read back
++ #define HSYNC_POLARITY_READ 0x20000000 //Bit[29] Hsync polarity read back
++ #define MODE_DETECTION_VSYNC_READY 0x40000000 //Bit[30] Mode detection Vsync ready
++ #define MODE_DETECTION_HSYNC_READY 0x80000000 //Bit[31] Mode detection Hsync ready
++
++/****** VIDEO MEMAGER SETTING ******/
++#define VIDEOM_ENGINE_SEQUENCE_CONTROL_REG 0x204 + VIDEOBASE_OFFSET
++ #define VIDEOM_CAPTURE_TRIGGER 0x00000002 //Bit[1] trigger HW to capture video
++ #define VIDEOM_AUTO_MODE 0x00000008 //Bit[3]
++ #define DISABLE_AUTO_MODE 0
++ #define AUTO_COMPRESS 1
++ #define VIDEOM_CODEC_TRIGGER 0x00000010 //Bit[4] trigger HW to compress or decompress video
++ #define VIDEOM_SOURCE_SELECTION 0x00000100 //Bit[8]
++ #define VIDEO1 0
++ #define VIDEO2 1
++ //#define STREAM_DATA_MODE 0x00000400 //Bit[11:10] Buffer and Stream Data type
++ // #define STREAM_DATA_MODE_BIT 10
++ // #define STREAM_DATA_MODE_MASK 0x00000C00
++ // #define YUV444_MODE 0
++ // #define YUV420_MODE 1
++ // #define YUV420_MODE_WITH_AST2000 2 //AST2000 compatible
++ #define VIDEOM_CAPTURE_READY 0x00010000 //Bit[16] Video capture ready status read back(read only)
++ //#define HW_BUSY 0
++ //#define HW_IDLE 1
++ #define VIDEOM_CODEC_READY 0x00040000 //Bit[18] Video codec ready status read back(read only)
++ //#define HW_BUSY 0
++ //#define HW_IDLE 1
++
++#define VIDEOM_SCALE_FACTOR_REG 0x214 + VIDEOBASE_OFFSET
++// #define HOR_SCALING_FACTOR 0x00000001 //Bit[15:0] Video Horizontal scaling factor
++// #define HOR_SCALING_FACTOR_BIT 0 //The formula=4096/(Horizontal scaling facotr)
++// #define HOR_SCALING_FACTOR_MASK 0x0000FFFF
++// #define VER_SCALING_FACTOR 0x00000000 //Bit[31:16] Video Vertical scaling factor
++// #define VER_SCALING_FACTOR_BIT 16 //The formula=4096/(Vertical scaling facotr)
++// #define VER_SCALING_FACTOR_MASK 0xFFFF0000
++
++#define VIDEOM_SCALE_FACTOR_PARAMETER0_REG 0x218 + VIDEOBASE_OFFSET //Scaling Parameters F00, F01, F02, F03
++
++#define VIDEOM_SCALE_FACTOR_PARAMETER1_REG 0x21C + VIDEOBASE_OFFSET //Scaling Parameters F10, F11, F12, F13
++
++#define VIDEOM_SCALE_FACTOR_PARAMETER2_REG 0x220 + VIDEOBASE_OFFSET //Scaling Parameters F20, F21, F22, F23
++
++#define VIDEOM_SCALE_FACTOR_PARAMETER3_REG 0x224 + VIDEOBASE_OFFSET //Scaling Parameters F30, F31, F32, F33
++
++#define VIDEOM_BCD_CONTROL_REG 0x22C + VIDEOBASE_OFFSET
++ //#define BCD_ENABLE 0x00000001 //Bit[0] Enable block change detection(BCD)
++ //#define BCD_TOLERANCE 0x00010000 //Bit[23:16]
++ // #define BCD_TOLERANCE_BIT 16 //flag as changed block when the video data difference greater
++ // #define BCD_TOLERANCE_MASK 0x00FF0000
++
++#define VIDEOM_CAPTURE_WINDOWS_REG 0x230 + VIDEOBASE_OFFSET
++ //#define RC4_TABLE_ADDR_ALIGN 7 //8 byte alignment
++ //#define RC4_TABLE_ADDR_MASK 0x0FFFFFFF
++
++#define VIDEOM_COMPRESS_WINDOWS_REG 0x234 + VIDEOBASE_OFFSET
++ //#define COMPRESS_VER_LINE 0x00000001 //Bit[12:0] Video compression vertical line total
++ //#define COMPRESS_VER_LINE_BIT 0
++ //#define COMPRESS_VER_LINE_MASK 0x00001FFF
++ //#define COMPRESS_HOR_PIXEL 0x00010000 //Bit[12:0] Video compression vertical line total
++ //#define COMPRESS_HOR_PIXEL_BIT 16
++ //#define COMPRESS_HOR_PIXEL_MASK 0x1FFF0000
++
++#define VIDEOM_COMPRESS_BUF_PROCESS_OFFSET_REG 0x238
++ //#define COMPRESS_BUF_PROCESS_OFFSET_ALIGN 127 //128 byte alignment
++ //#define COMPRESS_BUF_PROCESS_OFFSET_MASK 0x3FFFFF
++
++
++//For Compression
++#define VIDEOM_COMPRESS_BUF_READ_OFFSET_REG 0x23C + VIDEOBASE_OFFSET //For stream mode
++ //#define COMPRESS_BUF_READ_OFFSET_ALIGN 127 //128 byte alignment
++ //#define COMPRESS_BUF_READ_OFFSET_MASK 0x003FFFFF
++//For Decompression
++#define VIDEOM_DECOMPRESS_BUF_WRITE_OFFSET_REG 0x23C + VIDEOBASE_OFFSET //For stream mode
++ //#define DECOMPRESS_BUF_WRITE_OFFSET_ALIGN 127 //128 byte alignment
++ //#define DECOMPRESS_BUF_WRITE_OFFSET_MASK 0x003FFFFF
++
++#define VIDEOM_BUF_1_ADDR_REG 0x244 + VIDEOBASE_OFFSET //For Source Buffer in frame mode
++ //#define BUF_1_ADDR_ALIGN 255 //256 byte alignment
++ //#define BUF_1_ADDR_MASK 0x0FFFFFFF
++
++#define VIDEOM_BUF_LINE_OFFSET_REG 0x248 + VIDEOBASE_OFFSET //Must set both in Frame/Stream mode
++ //#define BUF_LINE_OFFSET_ALIGN 7 //8 byte alignment
++ //#define BUF_LINE_OFFSET_MASK 0x00003FFF
++
++#define VIDEOM_BUF_2_ADDR_REG 0x24C + VIDEOBASE_OFFSET //For BCD Buffer in frame mode
++ //#define BUF_2_ADDR_ALIGN 255 //256 byte alignment
++ //#define BUF_2_ADDR_MASK 0x0FFFFFFF
++
++#define VIDEOM_FLAG_BUF_ADDR_REG 0x250 + VIDEOBASE_OFFSET //For block change flag buffer
++ //#define FLAG_BUF_ADDR_ALIGN 7 //8 byte alignment
++ //#define FLAG_BUF_ADDR_MASK 0x0FFFFFFF
++
++#define VIDEOM_COMPRESS_BUF_ADDR_REG 0x254 + VIDEOBASE_OFFSET //For stream mode
++ //#define FLAG_BUF_ADDR_ALIGN 7 //8 byte alignment
++ //#define FLAG_BUF_ADDR_MASK 0x0FFFFFFF
++
++#define VIDEOM_BUF_CODEC_OFFSET_READ 0x25C + VIDEOBASE_OFFSET //For stream mode,
++ //#define BUF_CODEC_OFFSET_ALIGN 255 //256 byte alignment
++ //#define BUF_CODEC_OFFSET_MASK 0x003FFFFF
++
++#define VIDEOM_COMPRESS_CONTROL_REG 0x260 + VIDEOBASE_OFFSET
++ //#define JPEG_ONLY_ENCODE 0x00000001 //Bit[0] JPEG only encoding
++ // #define JPEG_MIX_MODE 0 //Enable JPEG/VQ mix mode encoding
++ // #define JPEG_ONLY_MODE 1 //JPEG encoding mode only
++ //#define VQ_4_COLOR_ENCODE 0x00000002 //Bit[1] Enable 4 color VQ encoding
++ // #define VQ_1_2_COLOR_MODE 0 //1 and 2 color mode VQ encoding
++ // #define VQ_4_COLOR_MODE 1 //1, 2 and 4 color VQ encoding
++ //#define QUALITY_CODEC_SETTING 0x00000004 //Bit[2] High and best video quality codec mode setting
++ // #define JPEG_CODEC_MODE 0 //not supported in best video quality mode
++ // #define QUANTI_CODEC_MODE 1
++ //#define JPEG_DUAL_QUALITY_EN 0x00000008 //Bit[3] JPEG dual quality mode
++ // #define EN_JPEG_DUAL_QUALITY 1 //enable(only for normal video quality mode)
++ //#define BEST_QUALITY_EN 0x00000010 //Bit[4] Best quality video mode enable
++ // #define EN_BEST_QUALITY 1 //enable(only for quantization codec mode)
++ //#define RC4_CRYPT_EN 0x00000020 //Bit[5] Enable RC4 encryption/decryption
++ // #define EN_RC4_CRYPT 1 //enable
++ //#define NORMAL_QUANTI_CHROMI_TABLE 0x00000040 //Bit[10:6] Normal video quality mode JPEG DCT chromi quantination table
++ // #define NORMAL_QUANTI_CHROMI_TABLE_BIT 6
++ // #define NORMAL_QUANTI_CHROMI_TABLE_MASK 0x000007C0
++ //#define NORMAL_QUANTI_LUMI_TABLE 0x00000800 //Bit[15:11] Normal video quality mode JPEG DCT lumi quantination table
++ // #define NORMAL_QUANTI_LUMI_TABLE_BIT 11
++ // #define NORMAL_QUANTI_LUMI_TABLE_MASK 0x0000F800
++ //#define HIGH_QUALITY_EN 0x00010000 //Bit[16] High video quality mode enable
++ // #define EN_HIGH_QUALITY 1 //Enable
++ //#define UV_CIR656_FORMAT 0x00080000 //Bit[19] UV fromat
++ // #define USE_UV_CIR656 1 //recommand
++ //#define HUFFMAN_TABLE_SELECT 0x00100000 //Bit[20] JPEG Huffman table combination
++ // #define DUAL_TABLE 0 //Dual Y, UV table
++ // #define SINGLE_TABLE 1 //Single Y table
++ // #define SINGLE_UV_TABLE 0x00200000 //1x: Single UV table
++ //#define HIGH_QUANTI_CHROMI_TABLE 0x00400000 //Bit[26:22] High quality JPEG DCT chromi quantization table
++ // #define HIGH_QUANTI_CHROMI_TABLE_BIT 22
++ // #define HIGH_QUANTI_CHROMI_TABLE_MASK 0x07C00000
++ //#define HIGH_DEQUANTI_VALUE 0x00400000 //Bit[26:22] High quality de-quantization value
++ // #define HIGH_DEQUANTI_VALUE_BIT 22
++ // #define HIGH_DEQUANTI_VALUE_MASK 0x07C00000
++ //#define HIGH_QUANTI_LUMI_TABLE 0x08000000 //Bit[31:27] High quality JPEG DCT lumi quantization table
++ // #define HIGH_QUANTI_LUMI_TABLE_BIT 27
++ // #define HIGH_QUANTI_LUMI_TABLE_MASK 0xF8000000
++ //#define BEST_DEQUANTI_VALUE 0x08000000 //Bit[31:27] Best quality de-quantization value
++ // #define BEST_QUANTI_VALUE_BIT 27
++ // #define BEST_QUANTI_VALUE_MASK 0xF8000000
++
++#define VIDEOM_QUANTI_TABLE_LOW_REG 0x264 + VIDEOBASE_OFFSET //Match with 0x60 Bit[10:6], Bit[15:11]
++// #define QUANTI_CHROMI_TABLE_LOW 0x00000001 //Bit[4:0] Normal video low quality block chromi quantization table
++// #define QUANTI_CHROMI_TABLE_LOW_BIT 0
++// #define QUANTI_CHROMI_TABLE_LOW_MASK 0x0000001F
++// #define QUANTI_LUMI_TABLE_LOW 0x00000020 //Bit[9:5] Normal video low quality block lumi quantization table
++// #define QUANTI_CHROMI_TABLE_LOW_BIT 5
++// #define QUANTI_CHROMI_TABLE_LOW_MASK 0x000003E0
++
++#define VIDEOM_QUANTI_VALUE_REG 0x268 + VIDEOBASE_OFFSET //Match with 0x60 Bit[26:22],Bit[31:27]
++// #define HIGH_QUANTI_VALUE 0x00000001 //Bit[14:0] High quality quantization value. Format is 1.14
++// #define HIGH_QUANTI_VALUE_BIT 0
++// #define HIGH_QUANTI_VALUE_MASK 0x00007FFF
++// #define BEST_QUANTI_VALUE 0x00010000 //Bit[30:16] Best quality quantization value. Format is 1.14
++// #define BEST_QUANTI_VALUE_BIT 16
++// #define BEST_QUANTI_VALUE_MASK 0x7FFF0000
++
++#define VIDEOM_BSD_PARA_REG 0x26C + VIDEOBASE_OFFSET //Video BSD Parameters Register
++// #define BSD_HIGH_THRES 0x00000001 //Bit[7:0] Block sharpness detection high threshold
++// #define BSD_HIGH_THRES_BIT 0
++// #define BSD_HIGH_THRES_MASK 0x000000FF
++// #define BSD_LOW_THRES 0x00000100 //Bit[15:8] Block shaprpness detection low threshold
++// #define BSD_LOW_THRES_BIT 8
++// #define BSD_LOW_THRES_MASK 0x0000FF00
++// #define BSD_HIGH_COUNTS 0x00010000 //Bit[21:16] Block sharpness detection high counts threshold
++// #define BSD_HIGH_COUNTS_BIT 16
++// #define BSD_HIGH_COUNTS_MASK 0x003F0000
++// #define BSD_LOW_COUNTS 0x01000000 //Bit[27:24] Block sharpness detection low counts threshold
++// #define BSD_LOW_COUNTS_BIT 24
++// #define BSD_LOW_COUNTS_MASK 0x3F000000
++
++#define VIDEOM_COMPRESS_FRAME_SIZE_REG 0x270 + VIDEOBASE_OFFSET
++// #define COMPRESS_FRAME_SIZE_READ 0x00000001 //Bit[19:0] Video compression frame size read back(number of DW)
++// #define COMPRESS_FRAME_SIZE_READ_BIT 0
++// #define COMPRESS_FRAME_SIZE_READ_MASK 0x000FFFFF
++
++#define VIDEOM_COMPRESS_BLOCK_COUNT_REG 0x274 + VIDEOBASE_OFFSET
++// #define COMPRESS_BLOCK_COUNT_READ 0x00000001 //Bit[15:0] Video compress block counter read back(number of blocks)
++// #define COMPRESS_BLOCK_COUNT_READ_BIT 0
++// #define COMPRESS_BLOCK_COUNT_READ_MASK 0x0000FFFF
++
++#define VIDEOM_COMPRESS_FRAME_END_READ 0x278 + VIDEOBASE_OFFSET //Video compression stream frame end pointer
++ //#define COMPRESS_FRAME_END_READ_ALIGN 7
++ //#define COMPRESS_FRAME_END_READ_MASK 0x003FFFFF
++
++#define VIDEOM_USER_DEFINE_HEADER_REG 0x280 + VIDEOBASE_OFFSET
++// #define USER_DEFINE_HEADER 0x00000001 //Bit[15:0] Video user defined header parameter
++// #define USER_DEFINE_HEADER_BIT 0
++// #define USER_DEFINE_HEADER_MASK 0x0000FFFF
++
++/****** VR300-VR3FC: General Control registers *****/
++#define VIDEO_CONTROL_REG 0x300 + VIDEOBASE_OFFSET
++ #define CODEC_DECOMPRESS_MODE 0x00000001 //Bit[0] Codec in de-compression mode
++ #define CODEC_DECOMPRESS_MODE_BIT 0
++ #define CODEC_DECOMPRESS_MODE_MASK 0x00000001
++ #define COMPRESS_MODE 0
++ #define DECOMPRESS_MODE 1
++ #define VIDEO_SAFE_MODE 0x00000002 //Bit[1] VIDEO SAFE MODE
++ #define VIDEO_SAFE_MODE_BIT 1
++ #define VIDEO_SAFE_MODE_OFF 0
++ #define VIDEO_SAFE_MODE_ON 1
++ #define DELAY_VSYNC 0x00000004 //Bit[2] Delay Internal VSYNC
++ #define DELAY_VSYNC_BIT 2
++ #define DELAY_VSYNC_MASK (1<<2)
++ #define DELAY_VSYNC_OFF (0<<2)
++ #define DELAY_VSYNC_EN (1<<2)
++ #define VER_DOWNSCALING_LINE_BUFFER_EN 0x00000010 //Bit[5:4] Video vertical downscaling line buffer enable
++ #define VER_LINE_BUFFER_MASK (3<<4)
++ #define LINE_BUFFER_OFF (0<<4)
++ #define LINE_BUFFER_VIDEO1 1
++ #define LINE_BUFFER_VIDEO2 2
++ #define LINE_BUFFER_VIDEOM 3
++ #define RC4_KEY_BUFFER_SELECTION (1UL<<6) //Bit[7:6] RC4 Key Buffer Selection
++ #define RC4_KEY_BUFFER_SELECTION_BIT 6
++ #define RC4_KEY_BUFFER_SELECTION_MASK (3UL<<6)
++ #define RC4_KEY_BUFFER_VIDEO1 0
++ #define RC4_KEY_BUFFER_VIDEO2 1
++ #define RC4_KEY_BUFFER_VIDEOM 2
++ #define RC4_INIT_RESET (1UL<<8) //Bit[8] RC4 initial reset
++ #define RC4_INIT_RESET_BIT 8
++ #define RC4_INIT_RESET_MASK (1UL<<8)
++ #define RC4_NORMAL_MODE 0
++ #define RC4_RESET_COUNTER 1
++ #define RC4_TEST_MODE (1UL<<9) //Bit[9] RC4 test mode
++ #define RC4_TEST_MODE_BIT 9
++ #define RC4_TEST_OFF 0
++ #define RC4_TEST_ON 1
++ #define RC4_SAVE_MODE (1UL<<14) //Bit[14] RC4 save mode
++ #define RC4_SAVE_MODE_BIT 14
++ #define RC4_SAVE_MODE_MASK (1UL<<14)
++ #define RC4_SAVE_MODE_OFF 0
++ #define RC4_SAVE_MODE_ON 1
++ #define RC4_NO_RESET_FRAME (1UL<<15) //Bit[15] RC4 no reset when frame completed
++ #define RC4_NO_RESET_FRAME_BIT 15
++ #define RC4_NO_RESET_FRAME_MASK (1UL<<15)
++ #define RC4_NO_RESET_FRAME_OFF 0 //Always reset
++ #define RC4_NO_RESET_FRAME_ON 1
++
++#define VIDEO_INT_CONTROL_EN_REG 0x304 + VIDEOBASE_OFFSET
++ #define VIDEO1_WATCH_DOG_INT_EN 0x00000001 //Bit[0] Enable Video1 mode detection watch dog out of lock interrupt
++ #define VIDEO1_INPUT_COMPLETE_INT_EN 0x00000002 //Bit[1] Enable Video1 video input complete interrupt (frame complete only for frame mode)
++ #define VIDEO1_PACKET_READY_INT_EN 0x00000004 //Bit[2] Enable Video1 packet ready interrupt
++ #define VIDEO1_COMPRESS_COMPLETE_INT_EN 0x00000008 //Bit[3] Enable Video1 compression complete interrupt
++ #define VIDEO1_MODE_DETECTION_READY_INT_EN 0x00000010 //Bit[4] Enable video1 mode detection ready interrupt
++ #define VIDEO1_FRAME_COMPLETE_INT_EN 0x00000020 //Bit[5] Enable Video1 frame complete interrupt (only for stream mode)
++ #define VIDEO1_STREAM_ERR_INT_EN 0x00000040 //Bit[6] Enable Video1 decode stream error interrupt
++ #define VIDEO2_WATCH_DOG_INT_EN 0x00000100 //Bit[8] Enable Video2 mode detection watch dog out of lock interrupt
++ #define VIDEO2_INPUT_COMPLETE_INT_EN 0x00000200 //Bit[9] Enable Video2 video input complete interrupt (frame complete only for frame mode)
++ #define VIDEO2_PACKET_READY_INT_EN 0x00000400 //Bit[10] Enable Video2 packet ready interrupt
++ #define VIDEO2_COMPRESS_COMPLETE_INT_EN 0x00000800 //Bit[11] Enable Video2 compression complete interrupt
++ #define VIDEO2_MODE_DETECTION_READY_INT_EN 0x00001000 //Bit[12] Enable video2 mode detection ready interrupt
++ #define VIDEO2_FRAME_COMPLETE_INT_EN 0x00002000 //Bit[13] Enable Video2 frame complete interrupt (only for stream mode)
++ #define VIDEO2_STREAM_ERR_INT_EN 0x00004000 //Bit[14] Enable Video2 decode stream error interrupt
++ #define VIDEOM_INPUT_COMPLETE_INT_EN 0x00010000 //Bit[16] Enable VideoM video input complete interrupt
++ #define VIDEOM_COMPRESS_COMPLETE_INT_EN 0x00020000 //Bit[17] Enable VideoM compression complete interrupt
++ #define VIDEOM_PACKET_READY_INT_EN 0x00040000 //Bit[18] Enable VideoM packet ready interrupt
++ #define VIDEOM_FRAME_COMPLETE_INT_EN 0x00080000 //Bit[19] Enable VideoM frame complete interrupt (only for stream mode)
++
++#define VIDEO_INT_CONTROL_READ_REG 0x308 + VIDEOBASE_OFFSET //Clear when write 1
++ #define VIDEO1_WATCH_DOG_READ 0x00000001 //Bit[0] Video1 mode detection watch dog out of lock interrupt status read back
++ #define VIDEO1_WATCH_DOG_BIT 0
++ #define VIDEO1_WATCH_DOG_MASK 0x00000001
++ #define VIDEO1_INPUT_COMPLETE_READ 0x00000002 //Bit[1] Video1 video input complete interrupt status read back (frame complete only for frame mode)
++ #define VIDEO1_INPUT_COMPLETE_BIT 1
++ #define VIDEO1_INPUT_COMPLETE_MASK 0x00000002
++ #define VIDEO1_PACKET_READY_READ 0x00000004 //Bit[2] Video1 packet ready interrupt status read back
++ #define VIDEO1_PACKET_READY_BIT 2
++ #define VIDEO1_PACKET_READY_MASK 0x00000004
++ #define VIDEO1_COMPRESS_COMPLETE_READ 0x00000008 //Bit[3] Video1 compression complete interrupt status read back
++ #define VIDEO1_COMPRESS_COMPLETE_BIT 3
++ #define VIDEO1_COMPRESS_COMPLETE_MASK 0x00000008
++ #define VIDEO1_MODE_DETECTION_READY_READ 0x00000010 //Bit[4] Video1 mode detection ready interrupt status read back
++ #define VIDEO1_MODE_DETECTION_READY_BIT 4
++ #define VIDEO1_FRAME_COMPLETE_READ 0x00000020 //Bit[5] Video1 frame complete interrupt status read back
++ #define VIDEO1_FRAME_COMPLETE_BIT 5
++ #define VIDEO1_FRAME_COMPLETE_MASK 0x00000020
++ #define VIDEO1_STREAM_ERR_READ 0x00000040 //Bit[6] Video1 decode stream error interrupt status read back
++ #define VIDEO1_STREAM_ERR_BIT 6
++ #define VIDEO1_STREAM_ERR_MASK 0x00000040
++ #define VIDEO2_WATCH_DOG_READ 0x00000100 //Bit[8] Video2 mode detection watch dog out of lock interrupt status read back
++ #define VIDEO2_WATCH_DOG_BIT 8
++ #define VIDEO2_WATCH_DOG_MASK 0x00000100
++ #define VIDEO2_INPUT_COMPLETE_READ 0x00000200 //Bit[9] Video2 video input complete interrupt status read back (frame complete only for frame mode)
++ #define VIDEO2_INPUT_COMPLETE_BIT 9
++ #define VIDEO2_INPUT_COMPLETE_MASK 0x00000200
++ #define VIDEO2_PACKET_READY_READ 0x00000400 //Bit[10] Video2 packet ready interrupt status read back
++ #define VIDEO2_PACKET_READY_BIT 10
++ #define VIDEO2_PACKET_READY_MASK 0x00000400
++ #define VIDEO2_COMPRESS_COMPLETE_READ 0x00000800 //Bit[11] Video2 compression complete interrupt status read back
++ #define VIDEO2_COMPRESS_COMPLETE_BIT 11
++ #define VIDEO2_COMPRESS_COMPLETE_MASK 0x00000800
++ #define VIDEO2_MODE_DETECTION_READY_READ 0x00001000 //Bit[12] Video2 mode detection ready interrupt status read back
++ #define VIDEO2_MODE_DETECTION_READY_BIT 12
++ #define VIDEO2_FRAME_COMPLETE_READ 0x00002000 //Bit[13] Video2 frame complete interrupt status read back
++ #define VIDEO2_FRAME_COMPLETE_BIT 13
++ #define VIDEO2_FRAME_COMPLETE_MASK 0x00002000
++ #define VIDEO2_STREAM_ERR_READ 0x00004000 //Bit[14] Video2 decode stream error interrupt status read back
++ #define VIDEO2_STREAM_ERR_BIT 14
++ #define VIDEO2_STREAM_ERR_MASK 0x00004000
++ //need check spec
++ #define VIDEOM_INPUT_COMPLETE_READ 0x00010000 //Bit[16] VideoM video input complete interrupt status read back
++ #define VIDEOM_INPUT_COMPLETE_BIT 16
++ #define VIDEOM_INPUT_COMPLETE_MASK 0x00010000
++ #define VIDEOM_COMPRESS_COMPLETE_READ 0x00020000 //Bit[17] VideoM compression complete interrupt status read back
++ #define VIDEOM_COMPRESS_COMPLETE_BIT 17
++ #define VIDEOM_COMPRESS_COMPLETE_MASK 0x00020000
++ #define VIDEOM_PACKET_READY_READ 0x00040000 //Bit[18] Clear Packet ready interrupt when write 1
++ #define VIDEOM_PACKET_READY_BIT 18
++ #define VIDEOM_PACKET_READY_MASK 0x00040000
++ #define VIDEOM_FRAME_COMPLETE_READ 0x00080000 //Bit[19] Clear Frame complete interrupt when write 1
++ #define VIDEOM_FRAME_COMPLETE_BIT 19
++ #define VIDEOM_FRAME_COMPLETE_MASK 0x00080000
++
++#define VIDEO_INT_CONTROL_CLEAR_REG 0x308 + VIDEOBASE_OFFSET //Clear when write 1
++ //Clear when write 1
++ #define VIDEO1_WATCH_DOG_CLEAR 0x00000001 //Bit[0] Clear mode detection watch dog out of lock interrupt when write 1
++ #define VIDEO1_INPUT_COMPLETE_CLEAR 0x00000002 //Bit[1] Clear video input complete interrupt when write 1 (frame complete only for frame mode)
++ #define VIDEO1_PACKET_READY_CLEAR 0x00000004 //Bit[2] Clear Packet ready interrupt when write 1
++ #define VIDEO1_PACKET_READY_CLEAR_BIT 2
++ #define VIDEO1_PACKET_READY_CLEAR_MASK 0x00000004
++ #define VIDEO1_COMPRESS_COMPLETE_CLEAR 0x00000008 //Bit[3] Clear video compression interrupt when write 1
++ #define VIDEO1_MODE_DETECTION_READY_CLEAR 0x00000010 //Bit[4] Clear Video1 Mode detection ready interrupt when write 1
++ #define VIDEO1_FRAME_COMPLETE_CLEAR 0x00000020 //Bit[5] Clear Frame complete interrupt when write 1
++ #define VIDEO1_FRAME_COMPLETE_CLEAR_BIT 5
++ #define VIDEO1_FRAME_COMPLETE_CLEAR_MASK 0x00000020
++ #define VIDEO1_STREAM_ERR_CLEAR 0x00000040 //Bit[6] Clear decode stream error interrupt when write 1
++ #define VIDEO2_WATCH_DOG_CLEAR 0x00000100 //Bit[8] Clear Mode detection interrupt when write 1
++ #define VIDEO2_INPUT_COMPLETE_CLEAR 0x00000200 //Bit[9] Clear video input complete interrupt when write 1
++ #define VIDEO2_PACKET_READY_CLEAR 0x00000400 //Bit[10] Clear packet ready interrupt when write 1
++ #define VIDEO2_COMPRESS_COMPLETE_CLEAR 0x00000800 //Bit[11] Clear video compression complete interrupt when write 1
++ #define VIDEO2_MODE_DETECTION_READY_CLEAR 0x00001000 //Bit[12] Clear Video2 Mode detection ready interrupt when write 1
++ #define VIDEO2_FRAME_COMPLETE_CLEAR 0x00002000 //Bit[13] Clear Frame complete interrupt when write 1 (frame complete only for frame mode)
++ #define VIDEO2_STREAM_ERR_CLEAR 0x00004000 //Bit[14] Clear Decode stream error interrupt when write 1
++ //need check spec
++ #define VIDEOM_INPUT_COMPLETE_CLEAR 0x00010000 //Bit[16] Clear video input complete interrupt when write 1
++ #define VIDEOM_COMPRESS_COMPLETE_CLEAR 0x00020000 //Bit[17] Clear compression complete interrupt when write 1
++ #define VIDEOM_COMPRESS_COMPLETE_CLEAR_BIT 17
++ #define VIDEOM_COMPRESS_COMPLETE_CLEAR_MASK 0x00020000
++ #define VIDEOM_PACKET_READY_CLEAR 0x00040000 //Bit[18] Clear compression complete interrupt when write 1
++ #define VIDEOM_PACKET_READY_CLEAR_BIT 18
++ #define VIDEOM_PACKET_READY_CLEAR_MASK 0x00040000
++ #define VIDEOM_FRAME_COMPLETE_CLEAR 0x00100000 //Bit[20] Clear Frame complete interrupt when write 1
++ #define VIDEOM_FRAME_COMPLETE_CLEAR_BIT 20
++ #define VIDEOM_FRAME_COMPLETE_CLEAR_MASK 0x00100000
++ #define VIDEOM_STREAM_ERR_CLEAR 0x00200000 //Bit[21] Clear decode stream error interrupt when write 1
++
++#define VIDEO_MODE_DETECTION_PARAM_REG 0x30C + VIDEOBASE_OFFSET
++ #define EDGE_PIXEL_THRES_BIT 8 //Bit[15:8] Mode detection edge pixel threshold
++ #define EDGE_PIXEL_THRES_MASK 0x0000FF00
++ #define VER_STABLE_MAX_BIT 16 //Bit[19:16] Mode detection vertical stable maximum
++ #define VER_STABLE_MAX_BIT_MASK 0x000F0000
++ #define HOR_STABLE_MAX_BIT 20 //Bit[23:20] Mode detection horizontal stable maximum
++ #define HOR_STABLE_MAX_BIT_MASK 0x00F00000
++ #define VER_STABLE_THRES_BIT 24 //Bit[27:24] Mode detection vertical stable threshold
++ #define VER_STABLE_THRES_BIT_MASK 0x0F000000
++ #define HOR_STABLE_THRES_BIT 28 //Bit[31:28] Mode detection horizontal stable threshold
++ #define HOR_STABLE_THRES_BIT_MASK 0xF0000000
++
++#define VIDEO_CRC_PRIMARY_REG 0x320 + VIDEOBASE_OFFSET
++ #define CRC_CHECK_EN 0x00000001 //Bit[0] Video port 1/2 Enable video capture write CRC check
++ #define CRC_CHECK_EN_BIT 0
++ #define CRC_CHECK_HIGH 0x00000002 //Bit[1] Video port 1/2 CRC check high bit only
++ #define CRC_CHECK_HIGH_BIT 1
++ #define SKIP_COUNT_MAX 0x00000004 //Bit[7:2] Video port 1/2 Max capture write skip count
++ #define SKIP_COUNT_MAX_BIT 2
++ #define SKIP_COUNT_MAX_MASK 0x000000FC
++ #define CRC_PRIMARY_POLY_LOW 0x00000100 //Bit[15:8] Primary CRC low 8-bit polynomial
++ #define CRC_RIMARY_POLY_LOW_BIT 8
++ #define CRC_RIMARY_POLY_LOW_MASK 0x0000FF00
++ #define CRC_PRIMARY_POLY_HIGH 0x00010000 //Bit[31:16] Primary CRC high 8-bit polynomial
++ #define CRC_RIMARY_POLY_HIGH_BIT 16
++ #define CRC_RIMARY_POLY_HIGH_MASK 0xFFFF0000
++
++
++#define VIDEO_CRC_SECOND_REG 0x324 + VIDEOBASE_OFFSET
++ #define CRC_SECOND_POLY_LOW 0x00000100 //Bit[15:8] Secondary CRC low 8-bit polynomial
++ #define CRC_SECOND_POLY_LOW_BIT 8
++ #define CRC_SECOND_POLY_LOW_MASK 0x0000FF00
++ #define CRC_SECOND_POLY_HIGH 0x00010000 //Bit[31:16] Secondary CRC high 8-bit polynomial
++ #define CRC_SECOND_POLY_HIGH_BIT 16
++ #define CRC_SECOND_POLY_HIGH_MASK 0xFFFF0000
++
++#define VIDEO1_RC4_KEYS_REG 0x400 + VIDEOBASE_OFFSET //Total Video1 RC4 Keys
++#define VIDEO2_RC4_KEYS_REG 0x500 + VIDEOBASE_OFFSET //Total Video2 RC4 Keys
++#define VIDEOM_RC4_KEYS_REG 0x600 + VIDEOBASE_OFFSET //Total VideoM RC4 Keys
++
++#endif /* end of _VREG_H_ */
++
+diff --git a/board/aspeed/ast2400/Makefile b/board/aspeed/ast2400/Makefile
+new file mode 100644
+index 0000000..1970ea1
+--- /dev/null
++++ b/board/aspeed/ast2400/Makefile
+@@ -0,0 +1,44 @@
++# This program is distributed in the hope that it will be useful,
++# but WITHOUT ANY WARRANTY; without even the implied warranty of
++# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++# GNU General Public License for more details.
++#
++# You should have received a copy of the GNU General Public License
++# along with this program; if not, write to the Free Software
++# Foundation, Inc., 59 Temple Place, Suite 330, Boston,
++# MA 02111-1307 USA
++#
++
++include $(TOPDIR)/config.mk
++
++LIB = $(obj)lib$(BOARD).a
++
++COBJS := ast2400.o flash.o flash_spi.o pci.o crc32.o slt.o regtest.o vfun.o vhace.o crt.o videotest.o mactest.o hactest.o mictest.o
++
++ifeq ($(CONFIG_FPGA_ASPEED),y)
++SOBJS := platform_fpga.o
++else ifeq ($(CONFIG_SLT_ASPEED),y)
++SOBJS := platform_slt.o
++else
++SOBJS := platform.o
++endif
++
++SRCS := $(SOBJS:.o=.S) $(COBJS:.o=.c)
++OBJS := $(addprefix $(obj),$(COBJS))
++SOBJS := $(addprefix $(obj),$(SOBJS))
++
++$(LIB): $(obj).depend $(OBJS) $(SOBJS)
++ $(AR) $(ARFLAGS) $@ $(OBJS) $(SOBJS)
++
++clean:
++ rm -f $(SOBJS) $(OBJS)
++
++distclean: clean
++ rm -f $(LIB) core *.bak $(obj).depend
++
++# defines $(obj).depend target
++include $(SRCTREE)/rules.mk
++
++sinclude .depend
++
++#########################################################################
+diff --git a/board/aspeed/ast2400/aes.c b/board/aspeed/ast2400/aes.c
+new file mode 100755
+index 0000000..76262e7
+--- /dev/null
++++ b/board/aspeed/ast2400/aes.c
+@@ -0,0 +1,579 @@
++/*
++ * AES implementation
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++ */
++
++/* uncomment the following line to run the test suite */
++
++/* #define TEST */
++
++/* uncomment the following line to use pre-computed tables */
++/* otherwise the tables will be generated at the first run */
++
++#define FIXED_TABLES
++
++#ifndef FIXED_TABLES
++
++/* forward S-box & tables */
++
++uint32 FSb[256];
++uint32 FT0[256];
++uint32 FT1[256];
++uint32 FT2[256];
++uint32 FT3[256];
++
++/* reverse S-box & tables */
++
++uint32 RSb[256];
++uint32 RT0[256];
++uint32 RT1[256];
++uint32 RT2[256];
++uint32 RT3[256];
++
++/* round constants */
++
++uint32 RCON[10];
++
++/* tables generation flag */
++
++int do_init = 1;
++
++/* tables generation routine */
++
++#define ROTR8(x) ( ( ( x << 24 ) & 0xFFFFFFFF ) | \
++ ( ( x & 0xFFFFFFFF ) >> 8 ) )
++
++#define XTIME(x) ( ( x << 1 ) ^ ( ( x & 0x80 ) ? 0x1B : 0x00 ) )
++#define MUL(x,y) ( ( x && y ) ? pow[(log[x] + log[y]) % 255] : 0 )
++
++void aes_gen_tables( void )
++{
++ int i;
++ uint8 x, y;
++ uint8 pow[256];
++ uint8 log[256];
++
++ /* compute pow and log tables over GF(2^8) */
++
++ for( i = 0, x = 1; i < 256; i++, x ^= XTIME( x ) )
++ {
++ pow[i] = x;
++ log[x] = i;
++ }
++
++ /* calculate the round constants */
++
++ for( i = 0, x = 1; i < 10; i++, x = XTIME( x ) )
++ {
++ RCON[i] = (uint32) x << 24;
++ }
++
++ /* generate the forward and reverse S-boxes */
++
++ FSb[0x00] = 0x63;
++ RSb[0x63] = 0x00;
++
++ for( i = 1; i < 256; i++ )
++ {
++ x = pow[255 - log[i]];
++
++ y = x; y = ( y << 1 ) | ( y >> 7 );
++ x ^= y; y = ( y << 1 ) | ( y >> 7 );
++ x ^= y; y = ( y << 1 ) | ( y >> 7 );
++ x ^= y; y = ( y << 1 ) | ( y >> 7 );
++ x ^= y ^ 0x63;
++
++ FSb[i] = x;
++ RSb[x] = i;
++ }
++
++ /* generate the forward and reverse tables */
++
++ for( i = 0; i < 256; i++ )
++ {
++ x = (unsigned char) FSb[i]; y = XTIME( x );
++
++ FT0[i] = (uint32) ( x ^ y ) ^
++ ( (uint32) x << 8 ) ^
++ ( (uint32) x << 16 ) ^
++ ( (uint32) y << 24 );
++
++ FT0[i] &= 0xFFFFFFFF;
++
++ FT1[i] = ROTR8( FT0[i] );
++ FT2[i] = ROTR8( FT1[i] );
++ FT3[i] = ROTR8( FT2[i] );
++
++ y = (unsigned char) RSb[i];
++
++ RT0[i] = ( (uint32) MUL( 0x0B, y ) ) ^
++ ( (uint32) MUL( 0x0D, y ) << 8 ) ^
++ ( (uint32) MUL( 0x09, y ) << 16 ) ^
++ ( (uint32) MUL( 0x0E, y ) << 24 );
++
++ RT0[i] &= 0xFFFFFFFF;
++
++ RT1[i] = ROTR8( RT0[i] );
++ RT2[i] = ROTR8( RT1[i] );
++ RT3[i] = ROTR8( RT2[i] );
++ }
++}
++
++#else
++
++/* forward S-box */
++
++static const uint32 FSb[256] =
++{
++ 0x63, 0x7C, 0x77, 0x7B, 0xF2, 0x6B, 0x6F, 0xC5,
++ 0x30, 0x01, 0x67, 0x2B, 0xFE, 0xD7, 0xAB, 0x76,
++ 0xCA, 0x82, 0xC9, 0x7D, 0xFA, 0x59, 0x47, 0xF0,
++ 0xAD, 0xD4, 0xA2, 0xAF, 0x9C, 0xA4, 0x72, 0xC0,
++ 0xB7, 0xFD, 0x93, 0x26, 0x36, 0x3F, 0xF7, 0xCC,
++ 0x34, 0xA5, 0xE5, 0xF1, 0x71, 0xD8, 0x31, 0x15,
++ 0x04, 0xC7, 0x23, 0xC3, 0x18, 0x96, 0x05, 0x9A,
++ 0x07, 0x12, 0x80, 0xE2, 0xEB, 0x27, 0xB2, 0x75,
++ 0x09, 0x83, 0x2C, 0x1A, 0x1B, 0x6E, 0x5A, 0xA0,
++ 0x52, 0x3B, 0xD6, 0xB3, 0x29, 0xE3, 0x2F, 0x84,
++ 0x53, 0xD1, 0x00, 0xED, 0x20, 0xFC, 0xB1, 0x5B,
++ 0x6A, 0xCB, 0xBE, 0x39, 0x4A, 0x4C, 0x58, 0xCF,
++ 0xD0, 0xEF, 0xAA, 0xFB, 0x43, 0x4D, 0x33, 0x85,
++ 0x45, 0xF9, 0x02, 0x7F, 0x50, 0x3C, 0x9F, 0xA8,
++ 0x51, 0xA3, 0x40, 0x8F, 0x92, 0x9D, 0x38, 0xF5,
++ 0xBC, 0xB6, 0xDA, 0x21, 0x10, 0xFF, 0xF3, 0xD2,
++ 0xCD, 0x0C, 0x13, 0xEC, 0x5F, 0x97, 0x44, 0x17,
++ 0xC4, 0xA7, 0x7E, 0x3D, 0x64, 0x5D, 0x19, 0x73,
++ 0x60, 0x81, 0x4F, 0xDC, 0x22, 0x2A, 0x90, 0x88,
++ 0x46, 0xEE, 0xB8, 0x14, 0xDE, 0x5E, 0x0B, 0xDB,
++ 0xE0, 0x32, 0x3A, 0x0A, 0x49, 0x06, 0x24, 0x5C,
++ 0xC2, 0xD3, 0xAC, 0x62, 0x91, 0x95, 0xE4, 0x79,
++ 0xE7, 0xC8, 0x37, 0x6D, 0x8D, 0xD5, 0x4E, 0xA9,
++ 0x6C, 0x56, 0xF4, 0xEA, 0x65, 0x7A, 0xAE, 0x08,
++ 0xBA, 0x78, 0x25, 0x2E, 0x1C, 0xA6, 0xB4, 0xC6,
++ 0xE8, 0xDD, 0x74, 0x1F, 0x4B, 0xBD, 0x8B, 0x8A,
++ 0x70, 0x3E, 0xB5, 0x66, 0x48, 0x03, 0xF6, 0x0E,
++ 0x61, 0x35, 0x57, 0xB9, 0x86, 0xC1, 0x1D, 0x9E,
++ 0xE1, 0xF8, 0x98, 0x11, 0x69, 0xD9, 0x8E, 0x94,
++ 0x9B, 0x1E, 0x87, 0xE9, 0xCE, 0x55, 0x28, 0xDF,
++ 0x8C, 0xA1, 0x89, 0x0D, 0xBF, 0xE6, 0x42, 0x68,
++ 0x41, 0x99, 0x2D, 0x0F, 0xB0, 0x54, 0xBB, 0x16
++};
++
++/* forward tables */
++
++#define FT \
++\
++ V(C6,63,63,A5), V(F8,7C,7C,84), V(EE,77,77,99), V(F6,7B,7B,8D), \
++ V(FF,F2,F2,0D), V(D6,6B,6B,BD), V(DE,6F,6F,B1), V(91,C5,C5,54), \
++ V(60,30,30,50), V(02,01,01,03), V(CE,67,67,A9), V(56,2B,2B,7D), \
++ V(E7,FE,FE,19), V(B5,D7,D7,62), V(4D,AB,AB,E6), V(EC,76,76,9A), \
++ V(8F,CA,CA,45), V(1F,82,82,9D), V(89,C9,C9,40), V(FA,7D,7D,87), \
++ V(EF,FA,FA,15), V(B2,59,59,EB), V(8E,47,47,C9), V(FB,F0,F0,0B), \
++ V(41,AD,AD,EC), V(B3,D4,D4,67), V(5F,A2,A2,FD), V(45,AF,AF,EA), \
++ V(23,9C,9C,BF), V(53,A4,A4,F7), V(E4,72,72,96), V(9B,C0,C0,5B), \
++ V(75,B7,B7,C2), V(E1,FD,FD,1C), V(3D,93,93,AE), V(4C,26,26,6A), \
++ V(6C,36,36,5A), V(7E,3F,3F,41), V(F5,F7,F7,02), V(83,CC,CC,4F), \
++ V(68,34,34,5C), V(51,A5,A5,F4), V(D1,E5,E5,34), V(F9,F1,F1,08), \
++ V(E2,71,71,93), V(AB,D8,D8,73), V(62,31,31,53), V(2A,15,15,3F), \
++ V(08,04,04,0C), V(95,C7,C7,52), V(46,23,23,65), V(9D,C3,C3,5E), \
++ V(30,18,18,28), V(37,96,96,A1), V(0A,05,05,0F), V(2F,9A,9A,B5), \
++ V(0E,07,07,09), V(24,12,12,36), V(1B,80,80,9B), V(DF,E2,E2,3D), \
++ V(CD,EB,EB,26), V(4E,27,27,69), V(7F,B2,B2,CD), V(EA,75,75,9F), \
++ V(12,09,09,1B), V(1D,83,83,9E), V(58,2C,2C,74), V(34,1A,1A,2E), \
++ V(36,1B,1B,2D), V(DC,6E,6E,B2), V(B4,5A,5A,EE), V(5B,A0,A0,FB), \
++ V(A4,52,52,F6), V(76,3B,3B,4D), V(B7,D6,D6,61), V(7D,B3,B3,CE), \
++ V(52,29,29,7B), V(DD,E3,E3,3E), V(5E,2F,2F,71), V(13,84,84,97), \
++ V(A6,53,53,F5), V(B9,D1,D1,68), V(00,00,00,00), V(C1,ED,ED,2C), \
++ V(40,20,20,60), V(E3,FC,FC,1F), V(79,B1,B1,C8), V(B6,5B,5B,ED), \
++ V(D4,6A,6A,BE), V(8D,CB,CB,46), V(67,BE,BE,D9), V(72,39,39,4B), \
++ V(94,4A,4A,DE), V(98,4C,4C,D4), V(B0,58,58,E8), V(85,CF,CF,4A), \
++ V(BB,D0,D0,6B), V(C5,EF,EF,2A), V(4F,AA,AA,E5), V(ED,FB,FB,16), \
++ V(86,43,43,C5), V(9A,4D,4D,D7), V(66,33,33,55), V(11,85,85,94), \
++ V(8A,45,45,CF), V(E9,F9,F9,10), V(04,02,02,06), V(FE,7F,7F,81), \
++ V(A0,50,50,F0), V(78,3C,3C,44), V(25,9F,9F,BA), V(4B,A8,A8,E3), \
++ V(A2,51,51,F3), V(5D,A3,A3,FE), V(80,40,40,C0), V(05,8F,8F,8A), \
++ V(3F,92,92,AD), V(21,9D,9D,BC), V(70,38,38,48), V(F1,F5,F5,04), \
++ V(63,BC,BC,DF), V(77,B6,B6,C1), V(AF,DA,DA,75), V(42,21,21,63), \
++ V(20,10,10,30), V(E5,FF,FF,1A), V(FD,F3,F3,0E), V(BF,D2,D2,6D), \
++ V(81,CD,CD,4C), V(18,0C,0C,14), V(26,13,13,35), V(C3,EC,EC,2F), \
++ V(BE,5F,5F,E1), V(35,97,97,A2), V(88,44,44,CC), V(2E,17,17,39), \
++ V(93,C4,C4,57), V(55,A7,A7,F2), V(FC,7E,7E,82), V(7A,3D,3D,47), \
++ V(C8,64,64,AC), V(BA,5D,5D,E7), V(32,19,19,2B), V(E6,73,73,95), \
++ V(C0,60,60,A0), V(19,81,81,98), V(9E,4F,4F,D1), V(A3,DC,DC,7F), \
++ V(44,22,22,66), V(54,2A,2A,7E), V(3B,90,90,AB), V(0B,88,88,83), \
++ V(8C,46,46,CA), V(C7,EE,EE,29), V(6B,B8,B8,D3), V(28,14,14,3C), \
++ V(A7,DE,DE,79), V(BC,5E,5E,E2), V(16,0B,0B,1D), V(AD,DB,DB,76), \
++ V(DB,E0,E0,3B), V(64,32,32,56), V(74,3A,3A,4E), V(14,0A,0A,1E), \
++ V(92,49,49,DB), V(0C,06,06,0A), V(48,24,24,6C), V(B8,5C,5C,E4), \
++ V(9F,C2,C2,5D), V(BD,D3,D3,6E), V(43,AC,AC,EF), V(C4,62,62,A6), \
++ V(39,91,91,A8), V(31,95,95,A4), V(D3,E4,E4,37), V(F2,79,79,8B), \
++ V(D5,E7,E7,32), V(8B,C8,C8,43), V(6E,37,37,59), V(DA,6D,6D,B7), \
++ V(01,8D,8D,8C), V(B1,D5,D5,64), V(9C,4E,4E,D2), V(49,A9,A9,E0), \
++ V(D8,6C,6C,B4), V(AC,56,56,FA), V(F3,F4,F4,07), V(CF,EA,EA,25), \
++ V(CA,65,65,AF), V(F4,7A,7A,8E), V(47,AE,AE,E9), V(10,08,08,18), \
++ V(6F,BA,BA,D5), V(F0,78,78,88), V(4A,25,25,6F), V(5C,2E,2E,72), \
++ V(38,1C,1C,24), V(57,A6,A6,F1), V(73,B4,B4,C7), V(97,C6,C6,51), \
++ V(CB,E8,E8,23), V(A1,DD,DD,7C), V(E8,74,74,9C), V(3E,1F,1F,21), \
++ V(96,4B,4B,DD), V(61,BD,BD,DC), V(0D,8B,8B,86), V(0F,8A,8A,85), \
++ V(E0,70,70,90), V(7C,3E,3E,42), V(71,B5,B5,C4), V(CC,66,66,AA), \
++ V(90,48,48,D8), V(06,03,03,05), V(F7,F6,F6,01), V(1C,0E,0E,12), \
++ V(C2,61,61,A3), V(6A,35,35,5F), V(AE,57,57,F9), V(69,B9,B9,D0), \
++ V(17,86,86,91), V(99,C1,C1,58), V(3A,1D,1D,27), V(27,9E,9E,B9), \
++ V(D9,E1,E1,38), V(EB,F8,F8,13), V(2B,98,98,B3), V(22,11,11,33), \
++ V(D2,69,69,BB), V(A9,D9,D9,70), V(07,8E,8E,89), V(33,94,94,A7), \
++ V(2D,9B,9B,B6), V(3C,1E,1E,22), V(15,87,87,92), V(C9,E9,E9,20), \
++ V(87,CE,CE,49), V(AA,55,55,FF), V(50,28,28,78), V(A5,DF,DF,7A), \
++ V(03,8C,8C,8F), V(59,A1,A1,F8), V(09,89,89,80), V(1A,0D,0D,17), \
++ V(65,BF,BF,DA), V(D7,E6,E6,31), V(84,42,42,C6), V(D0,68,68,B8), \
++ V(82,41,41,C3), V(29,99,99,B0), V(5A,2D,2D,77), V(1E,0F,0F,11), \
++ V(7B,B0,B0,CB), V(A8,54,54,FC), V(6D,BB,BB,D6), V(2C,16,16,3A)
++
++#define V(a,b,c,d) 0x##a##b##c##d
++static const uint32 FT0[256] = { FT };
++#undef V
++
++#define V(a,b,c,d) 0x##d##a##b##c
++static const uint32 FT1[256] = { FT };
++#undef V
++
++#define V(a,b,c,d) 0x##c##d##a##b
++static const uint32 FT2[256] = { FT };
++#undef V
++
++#define V(a,b,c,d) 0x##b##c##d##a
++static const uint32 FT3[256] = { FT };
++#undef V
++
++#undef FT
++
++/* reverse S-box */
++
++static const uint32 RSb[256] =
++{
++ 0x52, 0x09, 0x6A, 0xD5, 0x30, 0x36, 0xA5, 0x38,
++ 0xBF, 0x40, 0xA3, 0x9E, 0x81, 0xF3, 0xD7, 0xFB,
++ 0x7C, 0xE3, 0x39, 0x82, 0x9B, 0x2F, 0xFF, 0x87,
++ 0x34, 0x8E, 0x43, 0x44, 0xC4, 0xDE, 0xE9, 0xCB,
++ 0x54, 0x7B, 0x94, 0x32, 0xA6, 0xC2, 0x23, 0x3D,
++ 0xEE, 0x4C, 0x95, 0x0B, 0x42, 0xFA, 0xC3, 0x4E,
++ 0x08, 0x2E, 0xA1, 0x66, 0x28, 0xD9, 0x24, 0xB2,
++ 0x76, 0x5B, 0xA2, 0x49, 0x6D, 0x8B, 0xD1, 0x25,
++ 0x72, 0xF8, 0xF6, 0x64, 0x86, 0x68, 0x98, 0x16,
++ 0xD4, 0xA4, 0x5C, 0xCC, 0x5D, 0x65, 0xB6, 0x92,
++ 0x6C, 0x70, 0x48, 0x50, 0xFD, 0xED, 0xB9, 0xDA,
++ 0x5E, 0x15, 0x46, 0x57, 0xA7, 0x8D, 0x9D, 0x84,
++ 0x90, 0xD8, 0xAB, 0x00, 0x8C, 0xBC, 0xD3, 0x0A,
++ 0xF7, 0xE4, 0x58, 0x05, 0xB8, 0xB3, 0x45, 0x06,
++ 0xD0, 0x2C, 0x1E, 0x8F, 0xCA, 0x3F, 0x0F, 0x02,
++ 0xC1, 0xAF, 0xBD, 0x03, 0x01, 0x13, 0x8A, 0x6B,
++ 0x3A, 0x91, 0x11, 0x41, 0x4F, 0x67, 0xDC, 0xEA,
++ 0x97, 0xF2, 0xCF, 0xCE, 0xF0, 0xB4, 0xE6, 0x73,
++ 0x96, 0xAC, 0x74, 0x22, 0xE7, 0xAD, 0x35, 0x85,
++ 0xE2, 0xF9, 0x37, 0xE8, 0x1C, 0x75, 0xDF, 0x6E,
++ 0x47, 0xF1, 0x1A, 0x71, 0x1D, 0x29, 0xC5, 0x89,
++ 0x6F, 0xB7, 0x62, 0x0E, 0xAA, 0x18, 0xBE, 0x1B,
++ 0xFC, 0x56, 0x3E, 0x4B, 0xC6, 0xD2, 0x79, 0x20,
++ 0x9A, 0xDB, 0xC0, 0xFE, 0x78, 0xCD, 0x5A, 0xF4,
++ 0x1F, 0xDD, 0xA8, 0x33, 0x88, 0x07, 0xC7, 0x31,
++ 0xB1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xEC, 0x5F,
++ 0x60, 0x51, 0x7F, 0xA9, 0x19, 0xB5, 0x4A, 0x0D,
++ 0x2D, 0xE5, 0x7A, 0x9F, 0x93, 0xC9, 0x9C, 0xEF,
++ 0xA0, 0xE0, 0x3B, 0x4D, 0xAE, 0x2A, 0xF5, 0xB0,
++ 0xC8, 0xEB, 0xBB, 0x3C, 0x83, 0x53, 0x99, 0x61,
++ 0x17, 0x2B, 0x04, 0x7E, 0xBA, 0x77, 0xD6, 0x26,
++ 0xE1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0C, 0x7D
++};
++
++/* reverse tables */
++
++#define RT \
++\
++ V(51,F4,A7,50), V(7E,41,65,53), V(1A,17,A4,C3), V(3A,27,5E,96), \
++ V(3B,AB,6B,CB), V(1F,9D,45,F1), V(AC,FA,58,AB), V(4B,E3,03,93), \
++ V(20,30,FA,55), V(AD,76,6D,F6), V(88,CC,76,91), V(F5,02,4C,25), \
++ V(4F,E5,D7,FC), V(C5,2A,CB,D7), V(26,35,44,80), V(B5,62,A3,8F), \
++ V(DE,B1,5A,49), V(25,BA,1B,67), V(45,EA,0E,98), V(5D,FE,C0,E1), \
++ V(C3,2F,75,02), V(81,4C,F0,12), V(8D,46,97,A3), V(6B,D3,F9,C6), \
++ V(03,8F,5F,E7), V(15,92,9C,95), V(BF,6D,7A,EB), V(95,52,59,DA), \
++ V(D4,BE,83,2D), V(58,74,21,D3), V(49,E0,69,29), V(8E,C9,C8,44), \
++ V(75,C2,89,6A), V(F4,8E,79,78), V(99,58,3E,6B), V(27,B9,71,DD), \
++ V(BE,E1,4F,B6), V(F0,88,AD,17), V(C9,20,AC,66), V(7D,CE,3A,B4), \
++ V(63,DF,4A,18), V(E5,1A,31,82), V(97,51,33,60), V(62,53,7F,45), \
++ V(B1,64,77,E0), V(BB,6B,AE,84), V(FE,81,A0,1C), V(F9,08,2B,94), \
++ V(70,48,68,58), V(8F,45,FD,19), V(94,DE,6C,87), V(52,7B,F8,B7), \
++ V(AB,73,D3,23), V(72,4B,02,E2), V(E3,1F,8F,57), V(66,55,AB,2A), \
++ V(B2,EB,28,07), V(2F,B5,C2,03), V(86,C5,7B,9A), V(D3,37,08,A5), \
++ V(30,28,87,F2), V(23,BF,A5,B2), V(02,03,6A,BA), V(ED,16,82,5C), \
++ V(8A,CF,1C,2B), V(A7,79,B4,92), V(F3,07,F2,F0), V(4E,69,E2,A1), \
++ V(65,DA,F4,CD), V(06,05,BE,D5), V(D1,34,62,1F), V(C4,A6,FE,8A), \
++ V(34,2E,53,9D), V(A2,F3,55,A0), V(05,8A,E1,32), V(A4,F6,EB,75), \
++ V(0B,83,EC,39), V(40,60,EF,AA), V(5E,71,9F,06), V(BD,6E,10,51), \
++ V(3E,21,8A,F9), V(96,DD,06,3D), V(DD,3E,05,AE), V(4D,E6,BD,46), \
++ V(91,54,8D,B5), V(71,C4,5D,05), V(04,06,D4,6F), V(60,50,15,FF), \
++ V(19,98,FB,24), V(D6,BD,E9,97), V(89,40,43,CC), V(67,D9,9E,77), \
++ V(B0,E8,42,BD), V(07,89,8B,88), V(E7,19,5B,38), V(79,C8,EE,DB), \
++ V(A1,7C,0A,47), V(7C,42,0F,E9), V(F8,84,1E,C9), V(00,00,00,00), \
++ V(09,80,86,83), V(32,2B,ED,48), V(1E,11,70,AC), V(6C,5A,72,4E), \
++ V(FD,0E,FF,FB), V(0F,85,38,56), V(3D,AE,D5,1E), V(36,2D,39,27), \
++ V(0A,0F,D9,64), V(68,5C,A6,21), V(9B,5B,54,D1), V(24,36,2E,3A), \
++ V(0C,0A,67,B1), V(93,57,E7,0F), V(B4,EE,96,D2), V(1B,9B,91,9E), \
++ V(80,C0,C5,4F), V(61,DC,20,A2), V(5A,77,4B,69), V(1C,12,1A,16), \
++ V(E2,93,BA,0A), V(C0,A0,2A,E5), V(3C,22,E0,43), V(12,1B,17,1D), \
++ V(0E,09,0D,0B), V(F2,8B,C7,AD), V(2D,B6,A8,B9), V(14,1E,A9,C8), \
++ V(57,F1,19,85), V(AF,75,07,4C), V(EE,99,DD,BB), V(A3,7F,60,FD), \
++ V(F7,01,26,9F), V(5C,72,F5,BC), V(44,66,3B,C5), V(5B,FB,7E,34), \
++ V(8B,43,29,76), V(CB,23,C6,DC), V(B6,ED,FC,68), V(B8,E4,F1,63), \
++ V(D7,31,DC,CA), V(42,63,85,10), V(13,97,22,40), V(84,C6,11,20), \
++ V(85,4A,24,7D), V(D2,BB,3D,F8), V(AE,F9,32,11), V(C7,29,A1,6D), \
++ V(1D,9E,2F,4B), V(DC,B2,30,F3), V(0D,86,52,EC), V(77,C1,E3,D0), \
++ V(2B,B3,16,6C), V(A9,70,B9,99), V(11,94,48,FA), V(47,E9,64,22), \
++ V(A8,FC,8C,C4), V(A0,F0,3F,1A), V(56,7D,2C,D8), V(22,33,90,EF), \
++ V(87,49,4E,C7), V(D9,38,D1,C1), V(8C,CA,A2,FE), V(98,D4,0B,36), \
++ V(A6,F5,81,CF), V(A5,7A,DE,28), V(DA,B7,8E,26), V(3F,AD,BF,A4), \
++ V(2C,3A,9D,E4), V(50,78,92,0D), V(6A,5F,CC,9B), V(54,7E,46,62), \
++ V(F6,8D,13,C2), V(90,D8,B8,E8), V(2E,39,F7,5E), V(82,C3,AF,F5), \
++ V(9F,5D,80,BE), V(69,D0,93,7C), V(6F,D5,2D,A9), V(CF,25,12,B3), \
++ V(C8,AC,99,3B), V(10,18,7D,A7), V(E8,9C,63,6E), V(DB,3B,BB,7B), \
++ V(CD,26,78,09), V(6E,59,18,F4), V(EC,9A,B7,01), V(83,4F,9A,A8), \
++ V(E6,95,6E,65), V(AA,FF,E6,7E), V(21,BC,CF,08), V(EF,15,E8,E6), \
++ V(BA,E7,9B,D9), V(4A,6F,36,CE), V(EA,9F,09,D4), V(29,B0,7C,D6), \
++ V(31,A4,B2,AF), V(2A,3F,23,31), V(C6,A5,94,30), V(35,A2,66,C0), \
++ V(74,4E,BC,37), V(FC,82,CA,A6), V(E0,90,D0,B0), V(33,A7,D8,15), \
++ V(F1,04,98,4A), V(41,EC,DA,F7), V(7F,CD,50,0E), V(17,91,F6,2F), \
++ V(76,4D,D6,8D), V(43,EF,B0,4D), V(CC,AA,4D,54), V(E4,96,04,DF), \
++ V(9E,D1,B5,E3), V(4C,6A,88,1B), V(C1,2C,1F,B8), V(46,65,51,7F), \
++ V(9D,5E,EA,04), V(01,8C,35,5D), V(FA,87,74,73), V(FB,0B,41,2E), \
++ V(B3,67,1D,5A), V(92,DB,D2,52), V(E9,10,56,33), V(6D,D6,47,13), \
++ V(9A,D7,61,8C), V(37,A1,0C,7A), V(59,F8,14,8E), V(EB,13,3C,89), \
++ V(CE,A9,27,EE), V(B7,61,C9,35), V(E1,1C,E5,ED), V(7A,47,B1,3C), \
++ V(9C,D2,DF,59), V(55,F2,73,3F), V(18,14,CE,79), V(73,C7,37,BF), \
++ V(53,F7,CD,EA), V(5F,FD,AA,5B), V(DF,3D,6F,14), V(78,44,DB,86), \
++ V(CA,AF,F3,81), V(B9,68,C4,3E), V(38,24,34,2C), V(C2,A3,40,5F), \
++ V(16,1D,C3,72), V(BC,E2,25,0C), V(28,3C,49,8B), V(FF,0D,95,41), \
++ V(39,A8,01,71), V(08,0C,B3,DE), V(D8,B4,E4,9C), V(64,56,C1,90), \
++ V(7B,CB,84,61), V(D5,32,B6,70), V(48,6C,5C,74), V(D0,B8,57,42)
++
++#define V(a,b,c,d) 0x##a##b##c##d
++static const uint32 RT0[256] = { RT };
++#undef V
++
++#define V(a,b,c,d) 0x##d##a##b##c
++static const uint32 RT1[256] = { RT };
++#undef V
++
++#define V(a,b,c,d) 0x##c##d##a##b
++static const uint32 RT2[256] = { RT };
++#undef V
++
++#define V(a,b,c,d) 0x##b##c##d##a
++static const uint32 RT3[256] = { RT };
++#undef V
++
++#undef RT
++
++/* round constants */
++
++static const uint32 RCON[10] =
++{
++ 0x01000000, 0x02000000, 0x04000000, 0x08000000,
++ 0x10000000, 0x20000000, 0x40000000, 0x80000000,
++ 0x1B000000, 0x36000000
++};
++
++int do_init = 0;
++
++void aes_gen_tables( void )
++{
++}
++
++#endif
++
++/* platform-independant 32-bit integer manipulation macros */
++
++#define GET_UINT32_aes(n,b,i) \
++{ \
++ (n) = ( (uint32) (b)[(i) ] << 24 ) \
++ | ( (uint32) (b)[(i) + 1] << 16 ) \
++ | ( (uint32) (b)[(i) + 2] << 8 ) \
++ | ( (uint32) (b)[(i) + 3] ); \
++}
++
++#define PUT_UINT32_aes(n,b,i) \
++{ \
++ (b)[(i) ] = (uint8) ( (n) >> 24 ); \
++ (b)[(i) + 1] = (uint8) ( (n) >> 16 ); \
++ (b)[(i) + 2] = (uint8) ( (n) >> 8 ); \
++ (b)[(i) + 3] = (uint8) ( (n) ); \
++}
++
++/* decryption key schedule tables */
++
++int KT_init = 1;
++
++uint32 KT0[256];
++uint32 KT1[256];
++uint32 KT2[256];
++uint32 KT3[256];
++
++/* AES key scheduling routine */
++int aes_set_key( aes_context *ctx, uint8 *key, int nbits )
++{
++ int i;
++ uint32 *RK, *SK;
++
++ if( do_init )
++ {
++ aes_gen_tables();
++
++ do_init = 0;
++ }
++
++ switch( nbits )
++ {
++ case 128: ctx->nr = 10; break;
++ case 192: ctx->nr = 12; break;
++ case 256: ctx->nr = 14; break;
++ default : return( 1 );
++ }
++
++ RK = ctx->erk;
++
++ for( i = 0; i < (nbits >> 5); i++ )
++ {
++ GET_UINT32_aes( RK[i], key, i * 4 );
++ }
++
++ /* setup encryption round keys */
++
++ switch( nbits )
++ {
++ case 128:
++
++ for( i = 0; i < 10; i++, RK += 4 )
++ {
++ RK[4] = RK[0] ^ RCON[i] ^
++ ( FSb[ (uint8) ( RK[3] >> 16 ) ] << 24 ) ^
++ ( FSb[ (uint8) ( RK[3] >> 8 ) ] << 16 ) ^
++ ( FSb[ (uint8) ( RK[3] ) ] << 8 ) ^
++ ( FSb[ (uint8) ( RK[3] >> 24 ) ] );
++
++ RK[5] = RK[1] ^ RK[4];
++ RK[6] = RK[2] ^ RK[5];
++ RK[7] = RK[3] ^ RK[6];
++ }
++ break;
++
++ case 192:
++
++ for( i = 0; i < 8; i++, RK += 6 )
++ {
++ RK[6] = RK[0] ^ RCON[i] ^
++ ( FSb[ (uint8) ( RK[5] >> 16 ) ] << 24 ) ^
++ ( FSb[ (uint8) ( RK[5] >> 8 ) ] << 16 ) ^
++ ( FSb[ (uint8) ( RK[5] ) ] << 8 ) ^
++ ( FSb[ (uint8) ( RK[5] >> 24 ) ] );
++
++ RK[7] = RK[1] ^ RK[6];
++ RK[8] = RK[2] ^ RK[7];
++ RK[9] = RK[3] ^ RK[8];
++ RK[10] = RK[4] ^ RK[9];
++ RK[11] = RK[5] ^ RK[10];
++ }
++ break;
++
++ case 256:
++
++ for( i = 0; i < 7; i++, RK += 8 )
++ {
++ RK[8] = RK[0] ^ RCON[i] ^
++ ( FSb[ (uint8) ( RK[7] >> 16 ) ] << 24 ) ^
++ ( FSb[ (uint8) ( RK[7] >> 8 ) ] << 16 ) ^
++ ( FSb[ (uint8) ( RK[7] ) ] << 8 ) ^
++ ( FSb[ (uint8) ( RK[7] >> 24 ) ] );
++
++ RK[9] = RK[1] ^ RK[8];
++ RK[10] = RK[2] ^ RK[9];
++ RK[11] = RK[3] ^ RK[10];
++
++ RK[12] = RK[4] ^
++ ( FSb[ (uint8) ( RK[11] >> 24 ) ] << 24 ) ^
++ ( FSb[ (uint8) ( RK[11] >> 16 ) ] << 16 ) ^
++ ( FSb[ (uint8) ( RK[11] >> 8 ) ] << 8 ) ^
++ ( FSb[ (uint8) ( RK[11] ) ] );
++
++ RK[13] = RK[5] ^ RK[12];
++ RK[14] = RK[6] ^ RK[13];
++ RK[15] = RK[7] ^ RK[14];
++ }
++ break;
++ }
++
++ /* setup decryption round keys */
++
++ if( KT_init )
++ {
++ for( i = 0; i < 256; i++ )
++ {
++ KT0[i] = RT0[ FSb[i] ];
++ KT1[i] = RT1[ FSb[i] ];
++ KT2[i] = RT2[ FSb[i] ];
++ KT3[i] = RT3[ FSb[i] ];
++ }
++
++ KT_init = 0;
++ }
++
++ SK = ctx->drk;
++
++ *SK++ = *RK++;
++ *SK++ = *RK++;
++ *SK++ = *RK++;
++ *SK++ = *RK++;
++
++ for( i = 1; i < ctx->nr; i++ )
++ {
++ RK -= 8;
++
++ *SK++ = KT0[ (uint8) ( *RK >> 24 ) ] ^
++ KT1[ (uint8) ( *RK >> 16 ) ] ^
++ KT2[ (uint8) ( *RK >> 8 ) ] ^
++ KT3[ (uint8) ( *RK ) ]; RK++;
++
++ *SK++ = KT0[ (uint8) ( *RK >> 24 ) ] ^
++ KT1[ (uint8) ( *RK >> 16 ) ] ^
++ KT2[ (uint8) ( *RK >> 8 ) ] ^
++ KT3[ (uint8) ( *RK ) ]; RK++;
++
++ *SK++ = KT0[ (uint8) ( *RK >> 24 ) ] ^
++ KT1[ (uint8) ( *RK >> 16 ) ] ^
++ KT2[ (uint8) ( *RK >> 8 ) ] ^
++ KT3[ (uint8) ( *RK ) ]; RK++;
++
++ *SK++ = KT0[ (uint8) ( *RK >> 24 ) ] ^
++ KT1[ (uint8) ( *RK >> 16 ) ] ^
++ KT2[ (uint8) ( *RK >> 8 ) ] ^
++ KT3[ (uint8) ( *RK ) ]; RK++;
++ }
++
++ RK -= 8;
++
++ *SK++ = *RK++;
++ *SK++ = *RK++;
++ *SK++ = *RK++;
++ *SK++ = *RK++;
++
++ return( 0 );
++}
+diff --git a/board/aspeed/ast2400/ast2400.c b/board/aspeed/ast2400/ast2400.c
+new file mode 100644
+index 0000000..65bccbe
+--- /dev/null
++++ b/board/aspeed/ast2400/ast2400.c
+@@ -0,0 +1,304 @@
++/*
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++ */
++
++#include <common.h>
++#include <command.h>
++#include <pci.h>
++
++int board_init (void)
++{
++ DECLARE_GLOBAL_DATA_PTR;
++ unsigned char data;
++ unsigned long gpio;
++ unsigned long reg;
++
++ /* AHB Controller */
++ *((volatile ulong*) 0x1E600000) = 0xAEED1A03; /* unlock AHB controller */
++ *((volatile ulong*) 0x1E60008C) |= 0x01; /* map DRAM to 0x00000000 */
++
++ /* Flash Controller */
++#ifdef CONFIG_FLASH_AST2300
++ *((volatile ulong*) 0x1e620000) |= 0x800f0000; /* enable Flash Write */
++#else
++ *((volatile ulong*) 0x16000000) |= 0x00001c00; /* enable Flash Write */
++#endif
++
++ /* SCU */
++ *((volatile ulong*) 0x1e6e2000) = 0x1688A8A8; /* unlock SCU */
++ reg = *((volatile ulong*) 0x1e6e2008);
++ reg &= 0x1c0fffff;
++ reg |= 0x61800000; /* PCLK = HPLL/8 */
++#ifdef CONFIG_AST1070
++ //check lpc or lpc+ mode
++////////////////////////////////////////////////////////////////////////
++ gpio = *((volatile ulong*) 0x1e780070); /* mode check */
++ if(gpio & 0x2)
++ reg |= 0x100000; /* LHCLK = HPLL/4 */
++ else
++ reg |= 0x300000; /* LHCLK = HPLL/8 */
++
++ reg |= 0x80000; /* enable LPC Host Clock */
++
++ *((volatile ulong*) 0x1e6e2008) = reg;
++
++ reg = *((volatile ulong*) 0x1e6e200c); /* enable LPC clock */
++ *((volatile ulong*) 0x1e6e200c) &= ~(1 << 28);
++
++ if(gpio & 0x2) {
++
++ //use LPC+ for sys clk
++ // set OSCCLK = VPLL1
++ *((volatile ulong*) 0x1e6e2010) = 0x18;
++
++ // enable OSCCLK
++ reg = *((volatile ulong*) 0x1e6e202c);
++ reg |= 0x00000002;
++ *((volatile ulong*) 0x1e6e202c) = reg;
++ } else {
++ // USE LPC use D2 clk
++ /*set VPPL1 */
++ *((volatile ulong*) 0x1e6e201c) = 0x6420;
++
++ // set d2-pll & enable d2-pll D[21:20], D[4]
++ reg = *((volatile ulong*) 0x1e6e202c);
++ reg &= 0xffcfffef;
++ reg |= 0x00200010;
++ *((volatile ulong*) 0x1e6e202c) = reg;
++
++ // set OSCCLK = VPLL1
++ *((volatile ulong*) 0x1e6e2010) = 0x8;
++
++ // enable OSCCLK
++ reg = *((volatile ulong*) 0x1e6e202c);
++ reg &= 0xfffffffd;
++ reg |= 0x00000002;
++ *((volatile ulong*) 0x1e6e202c) = reg;
++ }
++#else
++ *((volatile ulong*) 0x1e6e2008) = reg;
++#endif
++ reg = *((volatile ulong*) 0x1e6e200c); /* enable 2D Clk */
++ *((volatile ulong*) 0x1e6e200c) &= 0xFFFFFFFD;
++/* enable wide screen. If your video driver does not support wide screen, don't
++enable this bit 0x1e6e2040 D[0]*/
++ reg = *((volatile ulong*) 0x1e6e2040);
++ *((volatile ulong*) 0x1e6e2040) |= 0x01;
++
++ /* arch number */
++ gd->bd->bi_arch_number = MACH_TYPE_ASPEED;
++
++ /* adress of boot parameters */
++ gd->bd->bi_boot_params = 0x40000100;
++
++ return 0;
++}
++
++int dram_init (void)
++{
++ DECLARE_GLOBAL_DATA_PTR;
++
++ gd->bd->bi_dram[0].start = PHYS_SDRAM_1;
++ gd->bd->bi_dram[0].size = PHYS_SDRAM_1_SIZE;
++
++ return 0;
++}
++
++/*
++SCU7C: Silicon Revision ID Register
++D[31:24]: Chip ID
++0: AST2050/AST2100/AST2150/AST2200/AST3000
++1: AST2300
++
++D[23:16] Silicon revision ID for AST2300 generation and later
++0: A0
++1: A1
++2: A2
++.
++.
++.
++FPGA revision starts from 0x80
++
++
++D[11:8] Bounding option
++
++D[7:0] Silicon revision ID for AST2050/AST2100 generation (for software compatible)
++0: A0
++1: A1
++2: A2
++3: A3
++.
++.
++FPGA revision starts from 0x08, 8~10 means A0, 11+ means A1, AST2300 should be assigned to 3
++*/
++int wait_calibration_done()
++{
++ DECLARE_GLOBAL_DATA_PTR;
++ unsigned char data;
++ unsigned long reg, count = 0;
++
++ do {
++ udelay(1000);
++ count++;
++ if (count >= 1000) {
++
++ return 1;
++ }
++ } while ((*(volatile ulong*) 0x1e6ec000) & 0xf00);
++
++// printf ("count = %d\n", count);
++
++ return 0;
++}
++
++/* AST1070 Calibration
++Program 0x101 to 0x1e6ec000
++Wait till 1e6ec000 [8] = 0
++Check 0x1e6ec004 = 0x5a5a5a5a
++*/
++int ast1070_calibration()
++{
++ DECLARE_GLOBAL_DATA_PTR;
++ unsigned char data;
++ unsigned long reg, i, j;
++
++ //only for 2 chip
++ for (i = 0; i < 2; i++) {
++ for (j = 0; j < 4; j++) {
++// printf ("chip = %d, delay = %d\n", i, j);
++ *((volatile ulong*) 0x1e6ec000) = (j << (12 + i * 2)) + (1 << (8 + i)) + 0x01;
++// printf ("1e6ec000 = %x\n", *(volatile ulong*)0x1e6ec000);
++ if (!wait_calibration_done()) {
++ if ((*(volatile ulong*) 0x1e6ec004) == 0x5a5a5a5a) {
++// printf ("calibration result: chip %d pass, timing = %d\n", i, j);
++ break;
++ }
++ else {
++// printf ("calibration result: chip %d fail, timing = %d\n", i, j);
++ }
++ }
++ }
++ }
++
++ return 0;
++}
++
++int misc_init_r(void)
++{
++ unsigned int reg, reg1, revision, chip_id, lpc_plus;
++
++#ifdef CONFIG_AST1070
++ //Reset AST1070 and AST2400 engine [bit 23:15]
++ reg = *((volatile ulong*) 0x1e7890a0);
++ reg &= ~0x808000;
++ *((volatile ulong*) 0x1e7890a0) = reg;
++
++ udelay(5000);
++
++ lpc_plus = (*((volatile ulong*) 0x1e780070)) & 0x2;
++
++ reg = *((volatile ulong*) 0x1e7890a0);
++ reg |= 0x800000;
++ *((volatile ulong*) 0x1e7890a0) = reg;
++
++ udelay(1000);
++
++ reg = *((volatile ulong*) 0x1e7890a0);
++ reg |= 0x008000;
++ *((volatile ulong*) 0x1e7890a0) = reg;
++
++
++ if(lpc_plus) {
++ *((volatile ulong*) 0x1E60008C) |= 0x011; /* map DRAM to 0x00000000 and LPC+ 0x70000000*/
++
++ //SCU multi-Function pin
++ reg = *((volatile ulong*) 0x1e6e2090);
++ reg |= (1 << 30);
++ *((volatile ulong*) 0x1e6e2090) = reg;
++ //LPC+ Engine Enable
++ reg = *((volatile ulong*) 0x1e6ec000);
++ reg |= 1;
++ *((volatile ulong*) 0x1e6ec000) = reg;
++
++ ast1070_calibration();
++
++ } else {
++ // enable AST1050's LPC master
++ reg = *((volatile ulong*) 0x1e7890a0);
++ *((volatile ulong*) 0x1e7890a0) |= 0x11;
++
++ }
++
++#endif
++ /* Show H/W Version */
++ reg1 = (unsigned int) (*((ulong*) 0x1e6e207c));
++ chip_id = (reg1 & 0xff000000) >> 24;
++ revision = (reg1 & 0xff0000) >> 16;
++
++ puts ("H/W: ");
++ if (chip_id == 1) {
++ if (revision >= 0x80) {
++ printf("AST2300 series FPGA Rev. %02x \n", revision);
++ }
++ else {
++ printf("AST2300 series chip Rev. %02x \n", revision);
++ }
++ }
++ else if (chip_id == 2) {
++ printf("AST2400 series chip Rev. %02x \n", revision);
++ }
++ else if (chip_id == 0) {
++ printf("AST2050/AST2150 series chip\n");
++ }
++
++#ifdef CONFIG_AST1070
++ if(lpc_plus) {
++ puts ("C/C: LPC+ :");
++ revision = (unsigned int) (*((ulong*) 0x70002034));
++ printf("AST1070 ID [%08x] ", revision);
++
++ if((*((volatile ulong*) 0x1e780070)) & 0x4) {
++ if((unsigned int) (*((ulong*) 0x70012034)) == 0x10700001)
++ printf(", 2nd : AST1070 ID [%08x] \n", (unsigned int) (*((ulong*) 0x70012034)));
++ else
++ printf("\n");
++ } else {
++ printf("\n");
++ }
++ } else {
++ puts ("C/C: LPC :");
++ revision = (unsigned int) (*((ulong*) 0x60002034));
++ printf("LPC : AST1070 ID [%08x] \n", revision);
++
++ }
++#endif
++
++#ifdef CONFIG_PCI
++ pci_init ();
++#endif
++
++ if (getenv ("verify") == NULL) {
++ setenv ("verify", "n");
++ }
++ if (getenv ("eeprom") == NULL) {
++ setenv ("eeprom", "y");
++ }
++}
++
++#ifdef CONFIG_PCI
++static struct pci_controller hose;
++
++extern void aspeed_init_pci (struct pci_controller *hose);
++
++void pci_init_board(void)
++{
++ aspeed_init_pci(&hose);
++}
++#endif
+diff --git a/board/aspeed/ast2400/config.mk b/board/aspeed/ast2400/config.mk
+new file mode 100755
+index 0000000..24ca09b
+--- /dev/null
++++ b/board/aspeed/ast2400/config.mk
+@@ -0,0 +1,18 @@
++# This program is distributed in the hope that it will be useful,
++# but WITHOUT ANY WARRANTY; without even the implied warranty of
++# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++# GNU General Public License for more details.
++#
++# You should have received a copy of the GNU General Public License
++# along with this program; if not, write to the Free Software
++# Foundation, Inc., 59 Temple Place, Suite 330, Boston,
++# MA 02111-1307 USA
++#
++
++# ROM version
++#TEXT_BASE = 0xBFC00000
++
++# RAM version
++TEXT_BASE = 0x40500000
++#TEXT_BASE = 0x00000000
++#TEXT_BASE = 0x00400000
+diff --git a/board/aspeed/ast2400/crc32.c b/board/aspeed/ast2400/crc32.c
+new file mode 100755
+index 0000000..cc8d2ac
+--- /dev/null
++++ b/board/aspeed/ast2400/crc32.c
+@@ -0,0 +1,127 @@
++/*
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++ */
++#include <common.h>
++#include <asm/processor.h>
++#include <asm/byteorder.h>
++#include <environment.h>
++
++#ifdef CONFIG_2SPIFLASH
++
++extern flash_info_t flash_info[CFG_MAX_FLASH_BANKS];
++
++/* ========================================================================
++ * Table of CRC-32's of all single-byte values (made by make_aspeed_crc_table)
++ */
++unsigned long aspeed_crc_table[256] = {
++ 0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL, 0x076dc419L,
++ 0x706af48fL, 0xe963a535L, 0x9e6495a3L, 0x0edb8832L, 0x79dcb8a4L,
++ 0xe0d5e91eL, 0x97d2d988L, 0x09b64c2bL, 0x7eb17cbdL, 0xe7b82d07L,
++ 0x90bf1d91L, 0x1db71064L, 0x6ab020f2L, 0xf3b97148L, 0x84be41deL,
++ 0x1adad47dL, 0x6ddde4ebL, 0xf4d4b551L, 0x83d385c7L, 0x136c9856L,
++ 0x646ba8c0L, 0xfd62f97aL, 0x8a65c9ecL, 0x14015c4fL, 0x63066cd9L,
++ 0xfa0f3d63L, 0x8d080df5L, 0x3b6e20c8L, 0x4c69105eL, 0xd56041e4L,
++ 0xa2677172L, 0x3c03e4d1L, 0x4b04d447L, 0xd20d85fdL, 0xa50ab56bL,
++ 0x35b5a8faL, 0x42b2986cL, 0xdbbbc9d6L, 0xacbcf940L, 0x32d86ce3L,
++ 0x45df5c75L, 0xdcd60dcfL, 0xabd13d59L, 0x26d930acL, 0x51de003aL,
++ 0xc8d75180L, 0xbfd06116L, 0x21b4f4b5L, 0x56b3c423L, 0xcfba9599L,
++ 0xb8bda50fL, 0x2802b89eL, 0x5f058808L, 0xc60cd9b2L, 0xb10be924L,
++ 0x2f6f7c87L, 0x58684c11L, 0xc1611dabL, 0xb6662d3dL, 0x76dc4190L,
++ 0x01db7106L, 0x98d220bcL, 0xefd5102aL, 0x71b18589L, 0x06b6b51fL,
++ 0x9fbfe4a5L, 0xe8b8d433L, 0x7807c9a2L, 0x0f00f934L, 0x9609a88eL,
++ 0xe10e9818L, 0x7f6a0dbbL, 0x086d3d2dL, 0x91646c97L, 0xe6635c01L,
++ 0x6b6b51f4L, 0x1c6c6162L, 0x856530d8L, 0xf262004eL, 0x6c0695edL,
++ 0x1b01a57bL, 0x8208f4c1L, 0xf50fc457L, 0x65b0d9c6L, 0x12b7e950L,
++ 0x8bbeb8eaL, 0xfcb9887cL, 0x62dd1ddfL, 0x15da2d49L, 0x8cd37cf3L,
++ 0xfbd44c65L, 0x4db26158L, 0x3ab551ceL, 0xa3bc0074L, 0xd4bb30e2L,
++ 0x4adfa541L, 0x3dd895d7L, 0xa4d1c46dL, 0xd3d6f4fbL, 0x4369e96aL,
++ 0x346ed9fcL, 0xad678846L, 0xda60b8d0L, 0x44042d73L, 0x33031de5L,
++ 0xaa0a4c5fL, 0xdd0d7cc9L, 0x5005713cL, 0x270241aaL, 0xbe0b1010L,
++ 0xc90c2086L, 0x5768b525L, 0x206f85b3L, 0xb966d409L, 0xce61e49fL,
++ 0x5edef90eL, 0x29d9c998L, 0xb0d09822L, 0xc7d7a8b4L, 0x59b33d17L,
++ 0x2eb40d81L, 0xb7bd5c3bL, 0xc0ba6cadL, 0xedb88320L, 0x9abfb3b6L,
++ 0x03b6e20cL, 0x74b1d29aL, 0xead54739L, 0x9dd277afL, 0x04db2615L,
++ 0x73dc1683L, 0xe3630b12L, 0x94643b84L, 0x0d6d6a3eL, 0x7a6a5aa8L,
++ 0xe40ecf0bL, 0x9309ff9dL, 0x0a00ae27L, 0x7d079eb1L, 0xf00f9344L,
++ 0x8708a3d2L, 0x1e01f268L, 0x6906c2feL, 0xf762575dL, 0x806567cbL,
++ 0x196c3671L, 0x6e6b06e7L, 0xfed41b76L, 0x89d32be0L, 0x10da7a5aL,
++ 0x67dd4accL, 0xf9b9df6fL, 0x8ebeeff9L, 0x17b7be43L, 0x60b08ed5L,
++ 0xd6d6a3e8L, 0xa1d1937eL, 0x38d8c2c4L, 0x4fdff252L, 0xd1bb67f1L,
++ 0xa6bc5767L, 0x3fb506ddL, 0x48b2364bL, 0xd80d2bdaL, 0xaf0a1b4cL,
++ 0x36034af6L, 0x41047a60L, 0xdf60efc3L, 0xa867df55L, 0x316e8eefL,
++ 0x4669be79L, 0xcb61b38cL, 0xbc66831aL, 0x256fd2a0L, 0x5268e236L,
++ 0xcc0c7795L, 0xbb0b4703L, 0x220216b9L, 0x5505262fL, 0xc5ba3bbeL,
++ 0xb2bd0b28L, 0x2bb45a92L, 0x5cb36a04L, 0xc2d7ffa7L, 0xb5d0cf31L,
++ 0x2cd99e8bL, 0x5bdeae1dL, 0x9b64c2b0L, 0xec63f226L, 0x756aa39cL,
++ 0x026d930aL, 0x9c0906a9L, 0xeb0e363fL, 0x72076785L, 0x05005713L,
++ 0x95bf4a82L, 0xe2b87a14L, 0x7bb12baeL, 0x0cb61b38L, 0x92d28e9bL,
++ 0xe5d5be0dL, 0x7cdcefb7L, 0x0bdbdf21L, 0x86d3d2d4L, 0xf1d4e242L,
++ 0x68ddb3f8L, 0x1fda836eL, 0x81be16cdL, 0xf6b9265bL, 0x6fb077e1L,
++ 0x18b74777L, 0x88085ae6L, 0xff0f6a70L, 0x66063bcaL, 0x11010b5cL,
++ 0x8f659effL, 0xf862ae69L, 0x616bffd3L, 0x166ccf45L, 0xa00ae278L,
++ 0xd70dd2eeL, 0x4e048354L, 0x3903b3c2L, 0xa7672661L, 0xd06016f7L,
++ 0x4969474dL, 0x3e6e77dbL, 0xaed16a4aL, 0xd9d65adcL, 0x40df0b66L,
++ 0x37d83bf0L, 0xa9bcae53L, 0xdebb9ec5L, 0x47b2cf7fL, 0x30b5ffe9L,
++ 0xbdbdf21cL, 0xcabac28aL, 0x53b39330L, 0x24b4a3a6L, 0xbad03605L,
++ 0xcdd70693L, 0x54de5729L, 0x23d967bfL, 0xb3667a2eL, 0xc4614ab8L,
++ 0x5d681b02L, 0x2a6f2b94L, 0xb40bbe37L, 0xc30c8ea1L, 0x5a05df1bL,
++ 0x2d02ef8dL
++};
++
++/* ========================================================================= */
++#define ASPEED_DO1(buf) crc = aspeed_crc_table[((int)crc ^ (*buf++)) & 0xff] ^ (crc >> 8);
++#define ASPEED_DO2(buf) ASPEED_DO1(buf); ASPEED_DO1(buf);
++#define ASPEED_DO4(buf) ASPEED_DO2(buf); ASPEED_DO2(buf);
++#define ASPEED_DO8(buf) ASPEED_DO4(buf); ASPEED_DO4(buf);
++
++/* ========================================================================= */
++unsigned long spi2_crc32(crc, buf, len)
++ unsigned long crc;
++ unsigned char *buf;
++ unsigned long len;
++{
++
++ size_t len1, len2;
++ char *s;
++
++ len1 = len2 = 0;
++ if ( (ulong)(buf) <= (flash_info[0].start[0] + flash_info[0].size) )
++ len1 = (flash_info[0].start[0] + flash_info[0].size) - (ulong)(buf);
++
++ len1 = (len < len1) ? len:len1;
++ len2 = (len < len1) ? 0: (len - len1);
++
++ crc = crc ^ 0xffffffffL;
++ while (len1 >= 8)
++ {
++ ASPEED_DO8(buf);
++ len1 -= 8;
++ }
++ if (len1) do {
++ ASPEED_DO1(buf);
++ } while (--len1);
++
++ //s = (char *) flash_info[1].start[0];
++ s= (char *) flash_make_addr (&flash_info[1], 0, 0);
++ while (len2 >= 8)
++ {
++ ASPEED_DO8(s);
++ len2 -= 8;
++ }
++ if (len2) do {
++ ASPEED_DO1(s);
++ } while (--len2);
++
++ return crc ^ 0xffffffffL;
++
++}
++
++#endif /* CONFIG_2SPIFLASH */
++
+diff --git a/board/aspeed/ast2400/crt.c b/board/aspeed/ast2400/crt.c
+new file mode 100755
+index 0000000..b67f669
+--- /dev/null
++++ b/board/aspeed/ast2400/crt.c
+@@ -0,0 +1,322 @@
++/*
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++ */
++#include <common.h>
++#include <command.h>
++
++#include "type.h"
++#include "vesa.h"
++#include "vdef.h"
++#include "vfun.h"
++#include "vreg.h"
++#include "crt.h"
++
++ULONG AST3000DCLKTableV [] = {
++ 0x00046515, /* 00: VCLK25_175 */
++ 0x00047255, /* 01: VCLK28_322 */
++ 0x0004682a, /* 02: VCLK31_5 */
++ 0x0004672a, /* 03: VCLK36 */
++ 0x00046c50, /* 04: VCLK40 */
++ 0x00046842, /* 05: VCLK49_5 */
++ 0x00006c32, /* 06: VCLK50 */
++ 0x00006a2f, /* 07: VCLK56_25 */
++ 0x00006c41, /* 08: VCLK65 */
++ 0x00006832, /* 09: VCLK75 */
++ 0x0000672e, /* 0A: VCLK78_75 */
++ 0x0000683f, /* 0B: VCLK94_5 */
++ 0x00004824, /* 0C: VCLK108 */
++ 0x00004723, /* 0D: VCLK119 */
++ 0x0000482d, /* 0E: VCLK135 */
++ 0x00004B37, /* 0F: VCLK146_25 */
++ 0x0000472e, /* 10: VCLK157_5 */
++ 0x00004836, /* 11: VCLK162 */
++
++};
++
++BOOL CheckDAC(int nCRTIndex)
++{
++ BYTE btValue;
++ BOOL bValue;
++
++ BYTE btDeviceSelect;
++
++ switch (nCRTIndex)
++ {
++ case CRT_1:
++ btDeviceSelect = DEVICE_ADDRESS_CH7301_CRT1;
++ break;
++ case CRT_2:
++ btDeviceSelect = DEVICE_ADDRESS_CH7301_CRT2;
++ break;
++ default:
++ printf("CRTIndex is not 1 or 2");
++ return FALSE;
++ break;
++ }
++
++ //Enable all DAC's and set register 21h[0] = '0'
++ //DVIP and DVIL disable for DAC
++ SetI2CRegClient(0, DEVICE_SELECT_CH7301, btDeviceSelect, CH7301_PM_REG, 0x00);
++
++ btValue = GetI2CRegClient(0, DEVICE_SELECT_CH7301, btDeviceSelect, CH7301_DC_REG);
++ btValue = btValue & 0xFE;
++ SetI2CRegClient(0, DEVICE_SELECT_CH7301, btDeviceSelect, CH7301_DC_REG, btValue);
++
++ //Set SENSE bit to 1
++ btValue = GetI2CRegClient(0, DEVICE_SELECT_CH7301, btDeviceSelect, CH7301_CD_REG);
++ btValue = btValue | 0x01;
++ SetI2CRegClient(0, DEVICE_SELECT_CH7301, btDeviceSelect, CH7301_CD_REG, btValue);
++
++ //Reset SENSE bit to 0
++ btValue = GetI2CRegClient(0, DEVICE_SELECT_CH7301, btDeviceSelect, CH7301_CD_REG);
++ btValue = btValue & 0xFE;
++ SetI2CRegClient(0, DEVICE_SELECT_CH7301, btDeviceSelect, CH7301_CD_REG, btValue);
++
++ bValue = (GetI2CRegClient(0, DEVICE_SELECT_CH7301, btDeviceSelect, CH7301_CD_REG) & CD_DACT) ? TRUE : FALSE;
++
++ return bValue;
++}
++
++VOID SetCH7301C(ULONG MMIOBase,
++ int nCRTIndex,
++ int inFreqRange,
++ int inOperating)
++{
++ BYTE btDeviceSelect;
++ BYTE btValue;
++
++//#ifdef EVB_CLIENT
++ //output RGB doesn't need to set CH7301
++ //if (1 == inOperating)
++ // return;
++//#endif
++
++ switch (nCRTIndex)
++ {
++ case CRT_1:
++ btDeviceSelect = 0xEA;
++
++ break;
++ case CRT_2:
++ btDeviceSelect = 0xEC;
++
++ break;
++ default:
++ printf("CRTIndex is not 1 or 2");
++ return;
++ break;
++ }
++
++ if (inFreqRange <= VCLK65)
++ {
++ printf("ch7301: low f \n");
++ SetI2CRegClient(MMIOBase, 0x3, btDeviceSelect, 0x33, 0x08);
++ SetI2CRegClient(MMIOBase, 0x3, btDeviceSelect, 0x34, 0x16);
++ SetI2CRegClient(MMIOBase, 0x3, btDeviceSelect, 0x36, 0x60);
++ }
++ else
++ {
++ SetI2CRegClient(MMIOBase, 0x3, btDeviceSelect, 0x33, 0x06);
++ SetI2CRegClient(MMIOBase, 0x3, btDeviceSelect, 0x34, 0x26);
++ SetI2CRegClient(MMIOBase, 0x3, btDeviceSelect, 0x36, 0xA0);
++ }
++
++ switch (inOperating)
++ {
++ case 0:
++ //DVI is normal function
++ SetI2CRegClient(MMIOBase, 0x3, btDeviceSelect, 0x49, 0xC0);
++ SetI2CRegClient(MMIOBase, 0x3, btDeviceSelect, 0x1D, 0x47);
++ break;
++ case 1:
++ //RGB
++ SetI2CRegClient(MMIOBase, 0x3, btDeviceSelect, 0x48, 0x18);
++ SetI2CRegClient(MMIOBase, 0x3, btDeviceSelect, 0x49, 0x0);
++ SetI2CRegClient(MMIOBase, 0x3, btDeviceSelect, 0x56, 0x0);
++ SetI2CRegClient(MMIOBase, 0x3, btDeviceSelect, 0x21, 0x9);
++ SetI2CRegClient(MMIOBase, 0x3, btDeviceSelect, 0x1D, 0x48);
++ SetI2CRegClient(MMIOBase, 0x3, btDeviceSelect, 0x1C, 0x00);
++ break;
++ default:
++ break;
++ };
++}
++
++void SetASTModeTiming (ULONG MMIOBase, int nCRTIndex, BYTE ModeIndex, BYTE ColorDepth)
++{
++ ULONG temp, RetraceStart, RetraceEnd, DisplayOffset, TerminalCount, bpp;
++
++// Access CRT Engine
++ // SetPolarity
++ WriteMemoryLongWithMASKClient(SCU_BASE, CRT1_CONTROL_REG + nCRTIndex*0x60, ((vModeTable[ModeIndex].HorPolarity << HOR_SYNC_SELECT_BIT) | (vModeTable[ModeIndex].VerPolarity << VER_SYNC_SELECT_BIT)), (HOR_SYNC_SELECT_MASK|VER_SYNC_SELECT_MASK));
++
++#if CONFIG_AST3000
++ WriteMemoryLongClient(SCU_BASE, CRT1_CONTROL2_REG + nCRTIndex*0x60, 0xc0);
++#else
++ //2100 is single edge
++ WriteMemoryLongClient(SCU_BASE, CRT1_CONTROL2_REG + nCRTIndex*0x60, 0x80);
++#endif
++ // Horizontal Timing
++ temp = 0;
++ temp = ((vModeTable[ModeIndex].HorizontalActive - 1) << HOR_ENABLE_END_BIT) | ((vModeTable[ModeIndex].HorizontalTotal - 1) << HOR_TOTAL_BIT);
++ WriteMemoryLongClient(SCU_BASE, CRT1_HOR_TOTAL_END_REG + nCRTIndex*0x60, temp);
++
++ RetraceStart = vModeTable[ModeIndex].HorizontalTotal - vModeTable[ModeIndex].HBackPorch - vModeTable[ModeIndex].HSyncTime - vModeTable[ModeIndex].HLeftBorder - 1;
++ RetraceEnd = (RetraceStart + vModeTable[ModeIndex].HSyncTime);
++ temp = 0;
++ temp = (RetraceEnd << HOR_RETRACE_END_BIT) | (RetraceStart << HOR_RETRACE_START_BIT);
++ WriteMemoryLongClient(SCU_BASE, CRT1_HOR_RETRACE_REG + nCRTIndex*0x60, temp);
++
++ // Vertical Timing
++ temp = 0;
++ temp = ((vModeTable[ModeIndex].VerticalActive - 1) << VER_ENABLE_END_BIT) | ((vModeTable[ModeIndex].VerticalTotal - 1) << VER_TOTAL_BIT);
++ WriteMemoryLongClient(SCU_BASE, CRT1_VER_TOTAL_END_REG + nCRTIndex*0x60, temp);
++
++ temp = 0;
++ RetraceStart = vModeTable[ModeIndex].VerticalTotal - vModeTable[ModeIndex].VBackPorch - vModeTable[ModeIndex].VSyncTime - vModeTable[ModeIndex].VTopBorder - 1;
++ RetraceEnd = (RetraceStart + vModeTable[ModeIndex].VSyncTime);
++ temp = (RetraceEnd << VER_RETRACE_END_BIT) | (RetraceStart << VER_RETRACE_START_BIT);
++ WriteMemoryLongClient(SCU_BASE, CRT1_VER_RETRACE_REG + nCRTIndex*0x60, temp);
++
++ // Set CRT Display Offset and Terminal Count
++ if (ColorDepth == RGB_565) {
++ bpp = 16;
++ }
++ else {
++ bpp = 32;
++ }
++
++ DisplayOffset = vModeTable[ModeIndex].HorizontalActive * bpp / 8;
++ TerminalCount = vModeTable[ModeIndex].HorizontalActive * bpp / 64;
++ if (ColorDepth == YUV_444) {
++ TerminalCount = TerminalCount * 3 / 4;
++ }
++ if (((vModeTable[ModeIndex].HorizontalActive * bpp) % 64) != 0) {
++ TerminalCount++;
++ }
++
++ WriteMemoryLongClient(SCU_BASE, CRT1_DISPLAY_OFFSET + nCRTIndex*0x60, ((TerminalCount << TERMINAL_COUNT_BIT) | DisplayOffset));
++
++ // Set Color Format
++ WriteMemoryLongWithMASKClient(SCU_BASE, CRT1_CONTROL_REG + nCRTIndex*0x60, (ColorDepth << FORMAT_SELECT_BIT), FORMAT_SELECT_MASK);
++
++ // Set Threshold
++ temp = 0;
++ temp = (CRT_HIGH_THRESHOLD_VALUE << THRES_HIGHT_BIT) | (CRT_LOW_THRESHOLD_VALUE << THRES_LOW_BIT);
++ WriteMemoryLongClient(SCU_BASE, CRT1_THRESHOLD_REG + nCRTIndex*0x60, temp);
++
++ WriteMemoryLongClient(SCU_BASE, CRT1_VIDEO_PLL_REG + nCRTIndex*0x60, AST3000DCLKTableV[vModeTable[ModeIndex].PixelClock]);
++}
++
++void SetASTCenter1024ModeTiming (ULONG MMIOBase, int nCRTIndex, BYTE ModeIndex, BYTE ColorDepth)
++{
++ ULONG temp, RetraceStart, RetraceEnd, DisplayOffset, TerminalCount, bpp;
++
++ // Access CRT Engine
++ // SetPolarity
++ WriteMemoryLongWithMASKClient(SCU_BASE, CRT1_CONTROL_REG + nCRTIndex*0x60, (HOR_NEGATIVE << HOR_SYNC_SELECT_BIT) | (VER_NEGATIVE << VER_SYNC_SELECT_BIT), HOR_SYNC_SELECT_MASK|VER_SYNC_SELECT_MASK);
++
++ WriteMemoryLongClient(SCU_BASE, CRT1_CONTROL2_REG + nCRTIndex*0x60, 0xC0);
++
++ // Horizontal Timing
++ temp = 0;
++ temp = ((vModeTable[ModeIndex].HorizontalActive - 1) << HOR_ENABLE_END_BIT) | ((vModeTable[10].HorizontalTotal - 1) << HOR_TOTAL_BIT);
++ WriteMemoryLongClient(SCU_BASE, CRT1_HOR_TOTAL_END_REG + nCRTIndex*0x60, temp);
++
++ RetraceStart = vModeTable[10].HorizontalTotal - vModeTable[10].HBackPorch - vModeTable[10].HSyncTime - vModeTable[10].HLeftBorder - 1;
++ RetraceStart = RetraceStart - (vModeTable[10].HorizontalActive - vModeTable[ModeIndex].HorizontalActive) / 2 - 1;
++ RetraceEnd = (RetraceStart + vModeTable[10].HSyncTime);
++ temp = 0;
++ temp = (RetraceEnd << HOR_RETRACE_END_BIT) | (RetraceStart << HOR_RETRACE_START_BIT);
++ WriteMemoryLongClient(SCU_BASE, CRT1_HOR_RETRACE_REG + nCRTIndex*0x60, temp);
++
++ // Vertical Timing
++ temp = 0;
++ temp = ((vModeTable[ModeIndex].VerticalActive - 1) << VER_ENABLE_END_BIT) | ((vModeTable[10].VerticalTotal - 1) << VER_TOTAL_BIT);
++ WriteMemoryLongClient(SCU_BASE, CRT1_VER_TOTAL_END_REG + nCRTIndex*0x60, temp);
++
++ RetraceStart = vModeTable[10].VerticalTotal - vModeTable[10].VBackPorch - vModeTable[10].VSyncTime - vModeTable[10].VTopBorder - 1;
++ RetraceStart = RetraceStart - (vModeTable[10].VerticalActive - vModeTable[ModeIndex].VerticalActive) / 2 - 1;
++ RetraceEnd = (RetraceStart + vModeTable[10].VSyncTime);
++ temp = (RetraceEnd << VER_RETRACE_END_BIT) | (RetraceStart << VER_RETRACE_START_BIT);
++ WriteMemoryLongClient(SCU_BASE, CRT1_VER_RETRACE_REG + nCRTIndex*0x60, temp);
++
++ // Set CRT Display Offset and Terminal Count
++ if (ColorDepth == RGB_565) {
++ bpp = 16;
++ }
++ else {
++ bpp = 32;
++ }
++ DisplayOffset = vModeTable[ModeIndex].HorizontalActive * bpp / 8;
++ TerminalCount = vModeTable[ModeIndex].HorizontalActive * bpp / 64;
++ if (ColorDepth == YUV_444) {
++ TerminalCount = TerminalCount * 3 / 4;
++ }
++ if (((vModeTable[ModeIndex].HorizontalActive * bpp) % 64) != 0) {
++ TerminalCount++;
++ }
++
++ WriteMemoryLongClient(SCU_BASE, CRT1_DISPLAY_OFFSET + nCRTIndex*0x60, (TerminalCount << TERMINAL_COUNT_BIT) | DisplayOffset);
++
++ // Set Color Format
++ WriteMemoryLongWithMASKClient(SCU_BASE, CRT1_CONTROL_REG + nCRTIndex*0x60, (ColorDepth << FORMAT_SELECT_BIT), FORMAT_SELECT_MASK);
++
++ // Set Threshold
++ temp = 0;
++ temp = (CRT_HIGH_THRESHOLD_VALUE << THRES_HIGHT_BIT) | (CRT_LOW_THRESHOLD_VALUE << THRES_LOW_BIT);
++ WriteMemoryLongClient(SCU_BASE, CRT1_THRESHOLD_REG + nCRTIndex*0x60, temp);
++
++ // Set DCLK
++ WriteMemoryLongClient(SCU_BASE, CRT1_VIDEO_PLL_REG + nCRTIndex*0x60, AST3000DCLKTableV[vModeTable[ModeIndex].PixelClock]);
++
++}
++
++BOOL ASTSetModeV (ULONG MMIOBase, int nCRTIndex, ULONG VGABaseAddr, USHORT Horizontal, USHORT Vertical, BYTE ColorFormat, BYTE CenterMode)
++{
++ BYTE i, ModeIndex;
++ BOOL bDAC;
++ ULONG ulTemp;
++
++ // Access CRT Engine
++ //Enable CRT1 graph
++ WriteMemoryLongWithMASKClient(SCU_BASE, CRT1_CONTROL_REG + 0x60*nCRTIndex, GRAPH_DISPLAY_ON, GRAPH_DISPLAY_MASK);
++
++ // Set CRT Display Start Address
++ WriteMemoryLongWithMASKClient(SCU_BASE, CRT1_DISPLAY_ADDRESS + 0x60*nCRTIndex, VGABaseAddr, DISPLAY_ADDRESS_MASK);
++
++ for (i = 0; i < Mode60HZCount; i++) {
++ if ((vModeTable[i].HorizontalActive == Horizontal) && (vModeTable[i].VerticalActive == Vertical)) {
++
++ ModeIndex = i;
++
++ if (CenterMode != 1) {
++ SetASTModeTiming(MMIOBase, nCRTIndex, i, ColorFormat);
++ }
++ else {
++ SetASTCenter1024ModeTiming (MMIOBase, nCRTIndex, i, ColorFormat);
++ }
++
++ //use internal video out sigal and don't need use 7301
++ /*
++ bDAC = CheckDAC(nCRTIndex);
++
++ SetCH7301C(0,
++ nCRTIndex,
++ vModeTable[ModeIndex].PixelClock,
++ bDAC); //For RGB
++ */
++ return TRUE;
++ }
++ }
++
++ return FALSE;
++}
++
+diff --git a/board/aspeed/ast2400/crt.h b/board/aspeed/ast2400/crt.h
+new file mode 100755
+index 0000000..e7483be
+--- /dev/null
++++ b/board/aspeed/ast2400/crt.h
+@@ -0,0 +1,121 @@
++/*
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++ */
++#ifndef _CRT_H_
++#define _CRT_H_
++
++#ifdef Watcom
++#define CRT_REMAP_OFFSET 0x10000
++#else
++#define CRT_REMAP_OFFSET 0x0
++#endif
++
++/********************************************************/
++/* CRT register */
++/********************************************************/
++#define CRT_BASE_OFFSET 0x6000+CRT_REMAP_OFFSET
++
++#define CRT1_CONTROL_REG 0x00 + CRT_BASE_OFFSET
++ #define GRAPH_DISPLAY_BIT 0
++ #define GRAPH_DISPLAY_MASK (1<<0)
++ #define GRAPH_DISPLAY_ON 1
++ #define GRAPH_DISPLAY_OFF 0
++ #define FORMAT_SELECT_BIT 8
++ #define FORMAT_SELECT_MASK (3<<8)
++ #define HOR_SYNC_SELECT_BIT 16
++ #define HOR_SYNC_SELECT_MASK (1<<16)
++ #define HOR_NEGATIVE 1
++ #define HOR_POSITIVE 0
++ #define VER_SYNC_SELECT_BIT 17
++ #define VER_SYNC_SELECT_MASK (1<<17)
++ #define VER_NEGATIVE 1
++ #define VER_POSITIVE 0
++
++#define CRT1_CONTROL2_REG 0x04 + CRT_BASE_OFFSET
++
++#define CRT1_VIDEO_PLL_REG 0x0C + CRT_BASE_OFFSET
++ #define POST_DIV_BIT 18
++ #define POST_DIV_MASK 3<<18
++ #define DIV_1_1 0
++ //#define DIV_1_2 1
++ #define DIV_1_2 2
++ #define DIV_1_4 3
++
++#define CRT1_HOR_TOTAL_END_REG 0x10 + CRT_BASE_OFFSET
++ #define HOR_TOTAL_BIT 0
++ #define HOR_ENABLE_END_BIT 16
++
++#define CRT1_HOR_RETRACE_REG 0x14 + CRT_BASE_OFFSET
++ #define HOR_RETRACE_START_BIT 0
++ #define HOR_RETRACE_END_BIT 16
++
++#define CRT1_VER_TOTAL_END_REG 0x18 + CRT_BASE_OFFSET
++ #define VER_TOTAL_BIT 0
++ #define VER_ENABLE_END_BIT 16
++
++#define CRT1_VER_RETRACE_REG 0x1C + CRT_BASE_OFFSET
++ #define VER_RETRACE_START_BIT 0
++ #define VER_RETRACE_END_BIT 16
++
++#define CRT1_DISPLAY_ADDRESS 0x20 + CRT_BASE_OFFSET
++ #define DISPLAY_ADDRESS_MASK 0x0FFFFFFF
++
++#define CRT1_DISPLAY_OFFSET 0x24 + CRT_BASE_OFFSET
++ #define DISPLAY_OFFSET_ALIGN 7 /* 8 byte alignment*/
++ #define TERMINAL_COUNT_BIT 16
++
++#define CRT1_THRESHOLD_REG 0x28 + CRT_BASE_OFFSET
++ #define THRES_LOW_BIT 0
++ #define THRES_HIGHT_BIT 8
++
++#define CURSOR_POSITION 0x30 + OFFSET
++#define CURSOR_OFFSET 0x34 + OFFSET
++#define CURSOR_PATTERN 0x38 + OFFSET
++#define OSD_HORIZONTAL 0x40 + OFFSET
++#define OSD_VERTICAL 0x44 + OFFSET
++#define OSD_PATTERN 0x48 + OFFSET
++#define OSD_OFFSET 0x4C + OFFSET
++#define OSD_THRESHOLD 0x50 + OFFSET
++
++//Ch7301c
++#define DEVICE_ADDRESS_CH7301_CRT1 0xEA
++#define DEVICE_ADDRESS_CH7301_CRT2 0xEC
++
++
++#define DEVICE_SELECT_CH7301 0x3
++
++/* CH7301 Register Definition */
++#define CH7301_CD_REG 0x20
++ #define CD_DACT 0x0E
++ #define CD_DVIT 1 << 5
++#define CH7301_DC_REG 0x21
++#define CH7301_PM_REG 0x49
++
++BOOL CheckHotPlug(int nCRTIndex);
++BOOL CheckDAC(int nCRTIndex);
++
++BOOL ASTSetModeV (ULONG MMIOBase,
++ int nCRTIndex,
++ ULONG VGABaseAddr,
++ USHORT Horizontal,
++ USHORT Vertical,
++ BYTE ColorFormat,
++ BYTE CenterMode);
++
++BOOL SelCRTClock(ULONG MMIOBase,
++ int nCRTIndex,
++ USHORT Horizontal,
++ USHORT Vertical);
++
++void DisableCRT(ULONG MMIOBase, int nCRTIndex);
++void ClearCRTWithBlack(ULONG ulCRTAddr, int iWidth, int iHeight);
++
++#endif /* _CRT_H_ */
++
+diff --git a/board/aspeed/ast2400/flash.c b/board/aspeed/ast2400/flash.c
+new file mode 100755
+index 0000000..d611d0d
+--- /dev/null
++++ b/board/aspeed/ast2400/flash.c
+@@ -0,0 +1,1651 @@
++/*
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
++ * MA 02111-1307 USA
++ *
++ * History
++ * 01/20/2004 - combined variants of original driver.
++ * 01/22/2004 - Write performance enhancements for parallel chips (Tolunay)
++ * 01/23/2004 - Support for x8/x16 chips (Rune Raknerud)
++ * 01/27/2004 - Little endian support Ed Okerson
++ *
++ * Tested Architectures
++ * Port Width Chip Width # of banks Flash Chip Board
++ * 32 16 1 28F128J3 seranoa/eagle
++ * 64 16 1 28F128J3 seranoa/falcon
++ */
++// (Sun) This CFI driver is written for fixed-width flash chips.
++// It was not designed for flexible 8-bit/16-bit chips, which are the norm.
++// When those chips are connected to a bus in 8-bit mode, the address wires
++// right-shifted by 1.
++//FIXME: Fix the driver to auto-detect "16-bit flash wired in 8-bit mode".
++// Left-shift CFI offsets by 1 bit instead of doubling the #define values.
++
++/* The DEBUG define must be before common to enable debugging */
++// (Sun) Changed to DEBUG_FLASH because flash debug()s are too numerous.
++// #define DEBUG
++
++#include <common.h>
++#include <asm/processor.h>
++#include <asm/byteorder.h>
++#include <environment.h>
++#ifdef CONFIG_SYS_FLASH_CFI
++
++/*
++ * This file implements a Common Flash Interface (CFI) driver for U-Boot.
++ * The width of the port and the width of the chips are determined at initialization.
++ * These widths are used to calculate the address for access CFI data structures.
++ * It has been tested on an Intel Strataflash implementation and AMD 29F016D.
++ *
++ * References
++ * JEDEC Standard JESD68 - Common Flash Interface (CFI)
++ * JEDEC Standard JEP137-A Common Flash Interface (CFI) ID Codes
++ * Intel Application Note 646 Common Flash Interface (CFI) and Command Sets
++ * Intel 290667-008 3 Volt Intel StrataFlash Memory datasheet
++ *
++ * TODO
++ *
++ * Use Primary Extended Query table (PRI) and Alternate Algorithm Query
++ * Table (ALT) to determine if protection is available
++ *
++ * Add support for other command sets Use the PRI and ALT to determine command set
++ * Verify erase and program timeouts.
++ */
++
++#ifndef CONFIG_FLASH_BANKS_LIST
++#define CONFIG_FLASH_BANKS_LIST { CONFIG_SYS_FLASH_BASE }
++#endif
++
++#define FLASH_CMD_CFI 0x98
++#define FLASH_CMD_READ_ID 0x90
++#define FLASH_CMD_RESET 0xff
++#define FLASH_CMD_BLOCK_ERASE 0x20
++#define FLASH_CMD_ERASE_CONFIRM 0xD0
++#define FLASH_CMD_WRITE 0x40
++#define FLASH_CMD_PROTECT 0x60
++#define FLASH_CMD_PROTECT_SET 0x01
++#define FLASH_CMD_PROTECT_CLEAR 0xD0
++#define FLASH_CMD_CLEAR_STATUS 0x50
++#define FLASH_CMD_WRITE_TO_BUFFER 0xE8
++#define FLASH_CMD_WRITE_BUFFER_CONFIRM 0xD0
++
++#define FLASH_STATUS_DONE 0x80
++#define FLASH_STATUS_ESS 0x40
++#define FLASH_STATUS_ECLBS 0x20
++#define FLASH_STATUS_PSLBS 0x10
++#define FLASH_STATUS_VPENS 0x08
++#define FLASH_STATUS_PSS 0x04
++#define FLASH_STATUS_DPS 0x02
++#define FLASH_STATUS_R 0x01
++#define FLASH_STATUS_PROTECT 0x01
++
++#define AMD_CMD_RESET 0xF0
++#define AMD_CMD_WRITE 0xA0
++#define AMD_CMD_ERASE_START 0x80
++#define AMD_CMD_ERASE_SECTOR 0x30
++#define AMD_CMD_UNLOCK_START 0xAA
++#define AMD_CMD_UNLOCK_ACK 0x55
++#define AMD_CMD_WRITE_TO_BUFFER 0x25
++#define AMD_CMD_BUFFER_TO_FLASH 0x29
++
++#define AMD_STATUS_TOGGLE 0x40
++#define AMD_STATUS_ERROR 0x20
++//FIXME: These 3 were also changed for 8-bit/16-bit flash chips.
++#define AMD_ADDR_ERASE_START (0xAAA/info->portwidth)
++#define AMD_ADDR_START (0xAAA/info->portwidth)
++#define AMD_ADDR_ACK (0x555/info->portwidth)
++
++//FIXME: Fix the driver to auto-detect "16-bit flash wired in 8-bit mode".
++// Left-shift CFI offsets by 1 bit instead of doubling the #define values.
++#define FLASH_OFFSET_CFI (0xAA/info->portwidth)
++#define FLASH_OFFSET_CFI_RESP (0x20/info->portwidth)
++#define FLASH_OFFSET_CFI_RESP1 (0x22/info->portwidth)
++#define FLASH_OFFSET_CFI_RESP2 (0x24/info->portwidth)
++#define FLASH_OFFSET_PRIMARY_VENDOR (0x26/info->portwidth)
++#define FLASH_OFFSET_WTOUT (0x3E/info->portwidth)
++#define FLASH_OFFSET_WBTOUT (0x40/info->portwidth)
++#define FLASH_OFFSET_ETOUT (0x42/info->portwidth)
++#define FLASH_OFFSET_CETOUT (0x44/info->portwidth)
++#define FLASH_OFFSET_WMAX_TOUT (0x46/info->portwidth)
++#define FLASH_OFFSET_WBMAX_TOUT (0x48/info->portwidth)
++#define FLASH_OFFSET_EMAX_TOUT (0x4A/info->portwidth)
++#define FLASH_OFFSET_CEMAX_TOUT (0x4C/info->portwidth)
++#define FLASH_OFFSET_SIZE (0x4E/info->portwidth)
++#define FLASH_OFFSET_INTERFACE (0x50/info->portwidth)
++#define FLASH_OFFSET_BUFFER_SIZE (0x54/info->portwidth)
++#define FLASH_OFFSET_NUM_ERASE_REGIONS (0x58/info->portwidth)
++#define FLASH_OFFSET_ERASE_REGIONS (0x5A/info->portwidth)
++#define FLASH_OFFSET_PROTECT (0x02/info->portwidth)
++#define FLASH_OFFSET_USER_PROTECTION (0x85/info->portwidth)
++#define FLASH_OFFSET_INTEL_PROTECTION (0x81/info->portwidth)
++
++#define MAX_NUM_ERASE_REGIONS 4
++
++#define FLASH_MAN_CFI 0x01000000
++
++#define CFI_CMDSET_NONE 0
++#define CFI_CMDSET_INTEL_EXTENDED 1
++#define CFI_CMDSET_AMD_STANDARD 2
++#define CFI_CMDSET_INTEL_STANDARD 3
++#define CFI_CMDSET_AMD_EXTENDED 4
++#define CFI_CMDSET_MITSU_STANDARD 256
++#define CFI_CMDSET_MITSU_EXTENDED 257
++#define CFI_CMDSET_SST 258
++
++
++#ifdef CONFIG_SYS_FLASH_CFI_AMD_RESET /* needed for STM_ID_29W320DB on UC100 */
++# undef FLASH_CMD_RESET
++# define FLASH_CMD_RESET AMD_CMD_RESET /* use AMD-Reset instead */
++#endif
++
++
++typedef union {
++ unsigned char c;
++ unsigned short w;
++ unsigned long l;
++ unsigned long long ll;
++} cfiword_t;
++
++typedef union {
++ volatile unsigned char *cp;
++ volatile unsigned short *wp;
++ volatile unsigned long *lp;
++ volatile unsigned long long *llp;
++} cfiptr_t;
++
++/* use CFG_MAX_FLASH_BANKS_DETECT if defined */
++#ifdef CONFIG_SYS_MAX_FLASH_BANKS_DETECT
++static ulong bank_base[CONFIG_SYS_MAX_FLASH_BANKS_DETECT] = CONFIG_FLASH_BANKS_LIST;
++flash_info_t flash_info[CFG_MAX_FLASH_BANKS_DETECT]; /* FLASH chips info */
++#else
++static ulong bank_base[CONFIG_SYS_MAX_FLASH_BANKS] = CONFIG_FLASH_BANKS_LIST;
++flash_info_t flash_info[CONFIG_SYS_MAX_FLASH_BANKS]; /* FLASH chips info */
++#endif
++
++
++/*-----------------------------------------------------------------------
++ * Functions
++ */
++static void flash_add_byte (flash_info_t * info, cfiword_t * cword, uchar c);
++static void flash_make_cmd (flash_info_t * info, uchar cmd, void *cmdbuf);
++static void flash_write_cmd (flash_info_t * info, flash_sect_t sect, uint offset, uchar cmd);
++static void flash_write_cmd_nodbg (flash_info_t * info, flash_sect_t sect, uint offset, uchar cmd);
++static void flash_write_cmd_int (flash_info_t * info, flash_sect_t sect, uint offset, uchar cmd, int noDebug);
++static void flash_unlock_seq (flash_info_t * info, flash_sect_t sect);
++static int flash_isequal (flash_info_t * info, flash_sect_t sect, uint offset, uchar cmd);
++static int flash_isset (flash_info_t * info, flash_sect_t sect, uint offset, uchar cmd);
++static int flash_toggle (flash_info_t * info, flash_sect_t sect, uint offset, uchar cmd);
++static int flash_detect_cfi (flash_info_t * info);
++ulong flash_get_size (ulong base, int banknum);
++static int flash_write_cfiword (flash_info_t * info, ulong dest, cfiword_t cword);
++static int flash_full_status_check (flash_info_t * info, flash_sect_t sector,
++ ulong tout, char *prompt);
++static void write_buffer_abort_reset(flash_info_t * info, flash_sect_t sector);
++#if defined(CFG_ENV_IS_IN_FLASH) || defined(CFG_ENV_ADDR_REDUND) || (CFG_MONITOR_BASE >= CFG_FLASH_BASE)
++static flash_info_t *flash_get_info(ulong base);
++#endif
++#ifdef CONFIG_SYS_FLASH_USE_BUFFER_WRITE
++static int flash_write_cfibuffer (flash_info_t * info, ulong dest, uchar * cp, int len);
++static int flash_write_cfibuffer_amd (flash_info_t * info, ulong dest, uchar * cp, int len);
++#endif
++
++/*-----------------------------------------------------------------------
++ * create an address based on the offset and the port width
++ */
++inline uchar *flash_make_addr (flash_info_t * info, flash_sect_t sect, uint offset)
++{
++ return ((uchar *) (info->start[sect] + (offset * info->portwidth)));
++}
++
++/*-----------------------------------------------------------------------
++ * Debug support
++ */
++#ifdef DEBUG_FLASH
++static void print_longlong (char *str, unsigned long long data)
++{
++ int i;
++ char *cp;
++
++ cp = (unsigned char *) &data;
++ for (i = 0; i < 8; i++)
++ sprintf (&str[i * 2], "%2.2x", *cp++);
++}
++#endif
++
++#if defined(DEBUG_FLASH)
++static void flash_printqry (flash_info_t * info, flash_sect_t sect)
++{
++ cfiptr_t cptr;
++ int x, y;
++
++ for (x = 0; x < 0x40; x += 16U / info->portwidth) {
++ cptr.cp =
++ flash_make_addr (info, sect,
++ x + FLASH_OFFSET_CFI_RESP);
++ debug ("%p : ", cptr.cp);
++ for (y = 0; y < 16; y++) {
++ debug ("%2.2x ", cptr.cp[y]);
++ }
++ debug (" ");
++ for (y = 0; y < 16; y++) {
++ if (cptr.cp[y] >= 0x20 && cptr.cp[y] <= 0x7e) {
++ debug ("%c", cptr.cp[y]);
++ } else {
++ debug (".");
++ }
++ }
++ debug ("\n");
++ }
++}
++#endif
++
++/*-----------------------------------------------------------------------
++ * read a character at a port width address
++ */
++inline uchar flash_read_uchar (flash_info_t * info, uint offset)
++{
++ uchar *cp;
++
++ cp = flash_make_addr (info, 0, offset);
++#if defined(__LITTLE_ENDIAN)
++ return (cp[0]);
++#else
++ return (cp[info->portwidth - 1]);
++#endif
++}
++
++/*-----------------------------------------------------------------------
++ * read a short word by swapping for ppc format.
++ */
++#if 0
++static ushort flash_read_ushort (flash_info_t * info, flash_sect_t sect, uint offset)
++{
++ uchar *addr;
++ ushort retval;
++
++#ifdef DEBUG_FLASH
++ int x;
++#endif
++ addr = flash_make_addr (info, sect, offset);
++
++#ifdef DEBUG_FLASH
++ debug ("ushort addr is at %p info->portwidth = %d\n", addr,
++ info->portwidth);
++ for (x = 0; x < 2 * info->portwidth; x++) {
++ debug ("addr[%x] = 0x%x\n", x, addr[x]);
++ }
++#endif
++#if defined(__LITTLE_ENDIAN)
++ if (info->interface == FLASH_CFI_X8X16) {
++ retval = (addr[0] | (addr[2] << 8));
++ } else {
++ retval = (addr[0] | (addr[(info->portwidth)] << 8));
++ }
++#else
++ retval = ((addr[(2 * info->portwidth) - 1] << 8) |
++ addr[info->portwidth - 1]);
++#endif
++
++ debug ("retval = 0x%x\n", retval);
++ return retval;
++}
++#endif
++
++/*-----------------------------------------------------------------------
++ * read a long word by picking the least significant byte of each maximum
++ * port size word. Swap for ppc format.
++ */
++static ulong flash_read_long (flash_info_t * info, flash_sect_t sect, uint offset)
++{
++ uchar *addr;
++ ulong retval;
++#ifdef DEBUG_FLASH
++ int x;
++#endif
++#if 0
++ switch (info->interface) {
++ case FLASH_CFI_X8:
++ case FLASH_CFI_X16:
++ break;
++ case FLASH_CFI_X8X16:
++ offset <<= 1;
++ }
++#endif
++ // flash_make_addr() multiplies offset by info->portwidth.
++ addr = flash_make_addr (info, sect, offset);
++
++#ifdef DEBUG_FLASH
++ debug ("long addr is at %p info->portwidth = %d\n", addr,
++ info->portwidth);
++ for (x = 0; x < 4 * info->portwidth; x++) {
++ debug ("addr[%x] = 0x%x\n", x, addr[x]);
++ }
++#endif
++#if defined(__LITTLE_ENDIAN)
++ if (info->interface == FLASH_CFI_X8X16) {
++ retval = (addr[0] | (addr[2] << 8) | (addr[4] << 16) | (addr[6] << 24));
++ } else {
++ retval = (addr[0] | (addr[(info->portwidth)] << 8) |
++ (addr[(2 * info->portwidth)] << 16) |
++ (addr[(3 * info->portwidth)] << 24));
++ }
++#else
++ //FIXME: This undocumented code appears to match broken bus wiring.
++ retval = (addr[(2 * info->portwidth) - 1] << 24) |
++ (addr[(info->portwidth) - 1] << 16) |
++ (addr[(4 * info->portwidth) - 1] << 8) |
++ addr[(3 * info->portwidth) - 1];
++#endif
++ return retval;
++}
++
++/*-----------------------------------------------------------------------
++ */
++unsigned long flash_init (void)
++{
++ unsigned long size = 0;
++ int i;
++
++ /* Init: no FLASHes known */
++ for (i = 0; i < CONFIG_SYS_MAX_FLASH_BANKS; ++i) {
++ flash_info[i].flash_id = FLASH_UNKNOWN;
++ size += flash_info[i].size = flash_get_size (bank_base[i], i);
++ if (flash_info[i].flash_id == FLASH_UNKNOWN) {
++#ifndef CFG_FLASH_QUIET_TEST
++ printf ("## Unknown FLASH on Bank %d - Size = 0x%08lx = %ld MB\n",
++ i, flash_info[i].size, flash_info[i].size << 20);
++#endif /* CFG_FLASH_QUIET_TEST */
++ }
++ }
++
++ /* Monitor protection ON by default */
++#if (CONFIG_MONITOR_BASE >= CONFIG_SYS_FLASH_BASE)
++ flash_protect (FLAG_PROTECT_SET,
++ CONFIG_MONITOR_BASE,
++ CONFIG_MONITOR_BASE + monitor_flash_len - 1,
++ flash_get_info(CONFIG_MONITOR_BASE));
++#endif
++
++ /* Environment protection ON by default */
++#ifdef CONFIG_ENV_IS_IN_FLASH
++ flash_protect (FLAG_PROTECT_SET,
++ CONFIG_ENV_ADDR,
++ CONFIG_ENV_ADDR + CONFIG_ENV_SECT_SIZE - 1,
++ flash_get_info(CONFIG_ENV_ADDR));
++#endif
++
++ /* Redundant environment protection ON by default */
++#ifdef CONFIG_ENV_ADDR_REDUND
++ flash_protect (FLAG_PROTECT_SET,
++ CONFIG_ENV_ADDR_REDUND,
++ CONFIG_ENV_ADDR_REDUND + CONFIG_ENV_SIZE_REDUND - 1,
++ flash_get_info(CONFIG_ENV_ADDR_REDUND));
++#endif
++ return (size);
++}
++
++/*-----------------------------------------------------------------------
++ */
++#if defined(CONFIG_ENV_IS_IN_FLASH) || defined(CONFIG_ENV_ADDR_REDUND) || (CONFIG_MONITOR_BASE >= CONFIG_SYS_FLASH_BASE)
++static flash_info_t *flash_get_info(ulong base)
++{
++ int i;
++ flash_info_t * info = 0;
++
++ for (i = 0; i < CONFIG_SYS_MAX_FLASH_BANKS; i ++) {
++ info = & flash_info[i];
++ if (info->size && info->start[0] <= base &&
++ base <= info->start[0] + info->size - 1)
++ break;
++ }
++
++ return i == CONFIG_SYS_MAX_FLASH_BANKS ? 0 : info;
++}
++#endif
++
++/*-----------------------------------------------------------------------
++ */
++int flash_erase (flash_info_t * info, int s_first, int s_last)
++{
++ int rcode = 0;
++ int prot;
++ flash_sect_t sect;
++ uchar ch;
++ uchar *addr;
++
++ if (info->flash_id != FLASH_MAN_CFI) {
++ puts ("Can't erase unknown flash type - aborted\n");
++ return 1;
++ }
++ if ((s_first < 0) || (s_first > s_last)) {
++ puts ("- no sectors to erase\n");
++ return 1;
++ }
++
++ prot = 0;
++ for (sect = s_first; sect <= s_last; ++sect) {
++ if (info->protect[sect]) {
++ prot++;
++ }
++ }
++ if (prot) {
++ printf ("- Warning: %d protected sectors will not be erased!\n", prot);
++ } else {
++ putc ('\n');
++ }
++
++
++ for (sect = s_first; sect <= s_last; sect++) {
++ if (info->protect[sect] == 0) { /* not protected */
++ switch (info->vendor) {
++ case CFI_CMDSET_INTEL_STANDARD:
++ case CFI_CMDSET_INTEL_EXTENDED:
++ flash_write_cmd (info, sect, 0, FLASH_CMD_CLEAR_STATUS);
++ flash_write_cmd (info, sect, 0, FLASH_CMD_BLOCK_ERASE);
++ flash_write_cmd (info, sect, 0, FLASH_CMD_ERASE_CONFIRM);
++ break;
++ case CFI_CMDSET_AMD_STANDARD:
++ case CFI_CMDSET_AMD_EXTENDED:
++ flash_unlock_seq (info, sect);
++ flash_write_cmd (info, sect, AMD_ADDR_ERASE_START,
++ AMD_CMD_ERASE_START);
++ flash_unlock_seq (info, sect);
++ flash_write_cmd (info, sect, 0, AMD_CMD_ERASE_SECTOR);
++
++ /* toggle */
++ addr = flash_make_addr (info, sect, 0);
++ do {
++ ch = *(volatile uchar *)(addr);
++ } while ( ((ch & 0x80) == 0) || (ch != 0xFF) );
++ break;
++ default:
++ debug ("Unkown flash vendor %d\n",
++ info->vendor);
++ break;
++ }
++
++ if (flash_full_status_check
++ (info, sect, info->erase_blk_tout, "erase")) {
++ rcode = 1;
++ } else
++ putc ('.');
++ }
++ }
++ puts (" done\n");
++ return rcode;
++}
++
++/*-----------------------------------------------------------------------
++ */
++void flash_print_info (flash_info_t * info)
++{
++ int i;
++
++ if (info->flash_id != FLASH_MAN_CFI) {
++ puts ("missing or unknown FLASH type\n");
++ return;
++ }
++
++ printf ("CFI conformant FLASH (%d x %d)",
++ (info->portwidth << 3), (info->chipwidth << 3));
++ printf (" Size: %ld MB in %d Sectors\n",
++ info->size >> 20, info->sector_count);
++ printf (" Erase timeout %ld ms, write timeout %ld ms, buffer write timeout %ld ms, buffer size %d\n",
++ info->erase_blk_tout,
++ info->write_tout,
++ info->buffer_write_tout,
++ info->buffer_size);
++
++ puts (" Sector Start Addresses:");
++ for (i = 0; i < info->sector_count; ++i) {
++#ifdef CFG_FLASH_EMPTY_INFO
++ int k;
++ int size;
++ int erased;
++ volatile unsigned long *flash;
++
++ /*
++ * Check if whole sector is erased
++ */
++ if (i != (info->sector_count - 1))
++ size = info->start[i + 1] - info->start[i];
++ else
++ size = info->start[0] + info->size - info->start[i];
++ erased = 1;
++ flash = (volatile unsigned long *) info->start[i];
++ size = size >> 2; /* divide by 4 for longword access */
++ for (k = 0; k < size; k++) {
++ if (*flash++ != 0xffffffff) {
++ erased = 0;
++ break;
++ }
++ }
++
++ if ((i % 5) == 0)
++ printf ("\n");
++ /* print empty and read-only info */
++ printf (" %08lX%s%s",
++ info->start[i],
++ erased ? " E" : " ",
++ info->protect[i] ? "RO " : " ");
++#else /* ! CFG_FLASH_EMPTY_INFO */
++ if ((i % 5) == 0)
++ printf ("\n ");
++ printf (" %08lX%s",
++ info->start[i], info->protect[i] ? " (RO)" : " ");
++#endif
++ }
++ putc ('\n');
++ return;
++}
++
++/*-----------------------------------------------------------------------
++ * Copy memory to flash, returns:
++ * 0 - OK
++ * 1 - write timeout
++ * 2 - Flash not erased
++ */
++int write_buff (flash_info_t * info, uchar * src, ulong addr, ulong cnt)
++{
++ ulong wp;
++ ulong cp;
++ int aln;
++ cfiword_t cword;
++ int i, rc;
++
++#ifdef CONFIG_SYS_FLASH_USE_BUFFER_WRITE
++ unsigned char pat[] = {'|', '-', '/', '\\'};
++ int patcnt = 0;
++ int buffered_size;
++#endif
++ /* get lower aligned address */
++ /* get lower aligned address */
++ wp = (addr & ~(info->portwidth - 1));
++
++ /* handle unaligned start */
++ if ((aln = addr - wp) != 0) {
++ cword.l = 0;
++ cp = wp;
++ for (i = 0; i < aln; ++i, ++cp)
++ flash_add_byte (info, &cword, (*(uchar *) cp));
++
++ for (; (i < info->portwidth) && (cnt > 0); i++) {
++ flash_add_byte (info, &cword, *src++);
++ cnt--;
++ cp++;
++ }
++ for (; (cnt == 0) && (i < info->portwidth); ++i, ++cp)
++ flash_add_byte (info, &cword, (*(uchar *) cp));
++ if ((rc = flash_write_cfiword (info, wp, cword)) != 0)
++ return rc;
++ wp = cp;
++ }
++
++ /* handle the aligned part */
++#ifdef CONFIG_SYS_FLASH_USE_BUFFER_WRITE
++ buffered_size = (info->portwidth / info->chipwidth);
++ buffered_size *= info->buffer_size;
++ while (cnt >= info->portwidth) {
++ /* Show processing */
++ if ((++patcnt % 256) == 0)
++ printf("%c\b", pat[(patcnt / 256) & 0x03]);
++
++ i = buffered_size > cnt ? cnt : buffered_size;
++ if ((rc = flash_write_cfibuffer (info, wp, src, i)) != ERR_OK)
++ return rc;
++ i -= i & (info->portwidth - 1);
++ wp += i;
++ src += i;
++ cnt -= i;
++ }
++#else
++ while (cnt >= info->portwidth) {
++ cword.l = 0;
++ for (i = 0; i < info->portwidth; i++) {
++ flash_add_byte (info, &cword, *src++);
++ }
++ if ((rc = flash_write_cfiword (info, wp, cword)) != 0)
++ return rc;
++ wp += info->portwidth;
++ cnt -= info->portwidth;
++ }
++#endif /* CONFIG_SYS_FLASH_USE_BUFFER_WRITE */
++ if (cnt == 0) {
++ return (0);
++ }
++
++ /*
++ * handle unaligned tail bytes
++ */
++ cword.l = 0;
++ for (i = 0, cp = wp; (i < info->portwidth) && (cnt > 0); ++i, ++cp) {
++ flash_add_byte (info, &cword, *src++);
++ --cnt;
++ }
++ for (; i < info->portwidth; ++i, ++cp) {
++ flash_add_byte (info, &cword, (*(uchar *) cp));
++ }
++
++ return flash_write_cfiword (info, wp, cword);
++}
++
++/*-----------------------------------------------------------------------
++ */
++#ifdef CFG_FLASH_PROTECTION
++
++int flash_real_protect (flash_info_t * info, long sector, int prot)
++{
++ int retcode = 0;
++
++ flash_write_cmd (info, sector, 0, FLASH_CMD_CLEAR_STATUS);
++ flash_write_cmd (info, sector, 0, FLASH_CMD_PROTECT);
++ if (prot)
++ flash_write_cmd (info, sector, 0, FLASH_CMD_PROTECT_SET);
++ else
++ flash_write_cmd (info, sector, 0, FLASH_CMD_PROTECT_CLEAR);
++
++ if ((retcode =
++ flash_full_status_check (info, sector, info->erase_blk_tout,
++ prot ? "protect" : "unprotect")) == 0) {
++
++ info->protect[sector] = prot;
++ /* Intel's unprotect unprotects all locking */
++ if (prot == 0) {
++ flash_sect_t i;
++
++ for (i = 0; i < info->sector_count; i++) {
++ if (info->protect[i])
++ flash_real_protect (info, i, 1);
++ }
++ }
++ }
++ return retcode;
++}
++
++/*-----------------------------------------------------------------------
++ * flash_read_user_serial - read the OneTimeProgramming cells
++ */
++void flash_read_user_serial (flash_info_t * info, void *buffer, int offset,
++ int len)
++{
++ uchar *src;
++ uchar *dst;
++
++ dst = buffer;
++ src = flash_make_addr (info, 0, FLASH_OFFSET_USER_PROTECTION);
++ flash_write_cmd (info, 0, 0, FLASH_CMD_READ_ID);
++ memcpy (dst, src + offset, len);
++ flash_write_cmd (info, 0, 0, info->cmd_reset);
++}
++
++/*
++ * flash_read_factory_serial - read the device Id from the protection area
++ */
++void flash_read_factory_serial (flash_info_t * info, void *buffer, int offset,
++ int len)
++{
++ uchar *src;
++
++ src = flash_make_addr (info, 0, FLASH_OFFSET_INTEL_PROTECTION);
++ flash_write_cmd (info, 0, 0, FLASH_CMD_READ_ID);
++ memcpy (buffer, src + offset, len);
++ flash_write_cmd (info, 0, 0, info->cmd_reset);
++}
++
++#endif /* CFG_FLASH_PROTECTION */
++
++/*
++ * flash_is_busy - check to see if the flash is busy
++ * This routine checks the status of the chip and returns true if the chip is busy
++ */
++static int flash_is_busy (flash_info_t * info, flash_sect_t sect)
++{
++ int retval;
++
++ switch (info->vendor) {
++ case CFI_CMDSET_INTEL_STANDARD:
++ case CFI_CMDSET_INTEL_EXTENDED:
++ retval = !flash_isset (info, sect, 0, FLASH_STATUS_DONE);
++ break;
++ case CFI_CMDSET_AMD_STANDARD:
++ case CFI_CMDSET_AMD_EXTENDED:
++ retval = flash_toggle (info, sect, 0, AMD_STATUS_TOGGLE);
++ break;
++ default:
++ retval = 0;
++ }
++#ifdef DEBUG_FLASH
++ if (retval)
++ debug ("flash_is_busy: %d\n", retval);
++#endif
++ return retval;
++}
++
++/*-----------------------------------------------------------------------
++ * wait for XSR.7 to be set. Time out with an error if it does not.
++ * This routine does not set the flash to read-array mode.
++ */
++static int flash_status_check (flash_info_t * info, flash_sect_t sector,
++ ulong tout, char *prompt)
++{
++ ulong start, now;
++
++ /* Wait for command completion */
++ // (Sun) Fix order of checking time so it works when the CPU is very
++ // slow, e.g., single-stepping or emulation.
++ start = get_timer (0);
++ while (now = get_timer(start),
++ flash_is_busy (info, sector))
++ {
++ if (now > info->erase_blk_tout) {
++ printf ("Flash %s timeout at address %lx data %lx\n",
++ prompt, info->start[sector],
++ flash_read_long (info, sector, 0));
++ flash_write_cmd (info, sector, 0, info->cmd_reset);
++ return ERR_TIMOUT;
++ }
++ }
++ return ERR_OK;
++}
++
++/*-----------------------------------------------------------------------
++ * Wait for XSR.7 to be set, if it times out print an error, otherwise do a full status check.
++ * This routine sets the flash to read-array mode.
++ */
++static int flash_full_status_check (flash_info_t * info, flash_sect_t sector,
++ ulong tout, char *prompt)
++{
++ int retcode;
++
++ retcode = flash_status_check (info, sector, tout, prompt);
++ switch (info->vendor) {
++ case CFI_CMDSET_INTEL_EXTENDED:
++ case CFI_CMDSET_INTEL_STANDARD:
++ if ((retcode != ERR_OK)
++ && !flash_isequal (info, sector, 0, FLASH_STATUS_DONE)) {
++ retcode = ERR_INVAL;
++ printf ("Flash %s error at address %lx\n", prompt,
++ info->start[sector]);
++ if (flash_isset (info, sector, 0, FLASH_STATUS_ECLBS | FLASH_STATUS_PSLBS)) {
++ puts ("Command Sequence Error.\n");
++ } else if (flash_isset (info, sector, 0, FLASH_STATUS_ECLBS)) {
++ puts ("Block Erase Error.\n");
++ retcode = ERR_NOT_ERASED;
++ } else if (flash_isset (info, sector, 0, FLASH_STATUS_PSLBS)) {
++ puts ("Locking Error\n");
++ }
++ if (flash_isset (info, sector, 0, FLASH_STATUS_DPS)) {
++ puts ("Block locked.\n");
++ retcode = ERR_PROTECTED;
++ }
++ if (flash_isset (info, sector, 0, FLASH_STATUS_VPENS))
++ puts ("Vpp Low Error.\n");
++ }
++ flash_write_cmd (info, sector, 0, info->cmd_reset);
++ break;
++ default:
++ break;
++ }
++ return retcode;
++}
++
++static void write_buffer_abort_reset(flash_info_t * info, flash_sect_t sector)
++{
++ flash_write_cmd (info, sector, 0xaaa, 0xaa);
++ flash_write_cmd (info, sector, 0x555, 0x55);
++ flash_write_cmd (info, sector, 0xaaa, 0xf0);
++}
++
++/*-----------------------------------------------------------------------
++ */
++static void flash_add_byte (flash_info_t * info, cfiword_t * cword, uchar c)
++{
++#if defined(__LITTLE_ENDIAN)
++ unsigned short w;
++ unsigned int l;
++ unsigned long long ll;
++#endif
++
++ switch (info->portwidth) {
++ case FLASH_CFI_8BIT:
++ cword->c = c;
++ break;
++ case FLASH_CFI_16BIT:
++#if defined(__LITTLE_ENDIAN)
++ w = c;
++ w <<= 8;
++ cword->w = (cword->w >> 8) | w;
++#else
++ cword->w = (cword->w << 8) | c;
++#endif
++ break;
++ case FLASH_CFI_32BIT:
++#if defined(__LITTLE_ENDIAN)
++ l = c;
++ l <<= 24;
++ cword->l = (cword->l >> 8) | l;
++#else
++ cword->l = (cword->l << 8) | c;
++#endif
++ break;
++ case FLASH_CFI_64BIT:
++#if defined(__LITTLE_ENDIAN)
++ ll = c;
++ ll <<= 56;
++ cword->ll = (cword->ll >> 8) | ll;
++#else
++ cword->ll = (cword->ll << 8) | c;
++#endif
++ break;
++ }
++}
++
++
++/*-----------------------------------------------------------------------
++ * make a proper sized command based on the port and chip widths
++ */
++static void flash_make_cmd (flash_info_t * info, uchar cmd, void *cmdbuf)
++{
++ int i;
++ uchar *cp = (uchar *) cmdbuf;
++
++#if defined(__LITTLE_ENDIAN)
++ for (i = info->portwidth; i > 0; i--)
++#else
++ for (i = 1; i <= info->portwidth; i++)
++#endif
++ *cp++ = (i & (info->chipwidth - 1)) ? '\0' : cmd;
++}
++
++/*
++ * Write a proper sized command to the correct address
++ */
++static void
++flash_write_cmd (flash_info_t * info, flash_sect_t sect, uint offset,
++ uchar cmd)
++{
++#ifdef DEBUG_FLASH
++ const int noDebug = 0;
++#else
++ const int noDebug = 1;
++#endif
++ return flash_write_cmd_int(info, sect, offset, cmd, noDebug);
++}
++static void
++flash_write_cmd_nodbg (flash_info_t * info, flash_sect_t sect, uint offset,
++ uchar cmd)
++{
++ return flash_write_cmd_int(info, sect, offset, cmd, 1);
++}
++
++static void
++flash_write_cmd_int (flash_info_t * info, flash_sect_t sect, uint offset,
++ uchar cmd, int noDebug)
++{
++
++ volatile cfiptr_t addr;
++ cfiword_t cword;
++
++ addr.cp = flash_make_addr (info, sect, offset);
++ flash_make_cmd (info, cmd, &cword);
++ switch (info->portwidth) {
++ case FLASH_CFI_8BIT:
++ if (noDebug == 0)
++ debug ("fwc addr %p cmd %x %x 8bit x %d bit\n", addr.cp, cmd,
++ cword.c, info->chipwidth << CFI_FLASH_SHIFT_WIDTH);
++ *addr.cp = cword.c;
++ break;
++ case FLASH_CFI_16BIT:
++ if (noDebug == 0)
++ debug ("fwc addr %p cmd %x %4.4x 16bit x %d bit\n", addr.wp,
++ cmd, cword.w,
++ info->chipwidth << CFI_FLASH_SHIFT_WIDTH);
++ *addr.wp = cword.w;
++ break;
++ case FLASH_CFI_32BIT:
++ if (noDebug == 0)
++ debug ("fwc addr %p cmd %x %8.8lx 32bit x %d bit\n", addr.lp,
++ cmd, cword.l,
++ info->chipwidth << CFI_FLASH_SHIFT_WIDTH);
++ *addr.lp = cword.l;
++ break;
++ case FLASH_CFI_64BIT:
++#ifdef DEBUG_FLASH
++ if (noDebug == 0)
++ {
++ char str[20];
++
++ print_longlong (str, cword.ll);
++
++ debug ("fwrite addr %p cmd %x %s 64 bit x %d bit\n",
++ addr.llp, cmd, str,
++ info->chipwidth << CFI_FLASH_SHIFT_WIDTH);
++ }
++#endif
++ *addr.llp = cword.ll;
++ break;
++ }
++}
++
++static void flash_unlock_seq (flash_info_t * info, flash_sect_t sect)
++{
++ flash_write_cmd_nodbg (info, sect, AMD_ADDR_START, AMD_CMD_UNLOCK_START);
++ flash_write_cmd_nodbg (info, sect, AMD_ADDR_ACK, AMD_CMD_UNLOCK_ACK);
++}
++
++/*-----------------------------------------------------------------------
++ */
++static int flash_isequal (flash_info_t * info, flash_sect_t sect, uint offset, uchar cmd)
++{
++ cfiptr_t cptr;
++ cfiword_t cword;
++ int retval;
++#ifdef DEBUG_FLASH
++ const int dbg = 1;
++#else
++ const int dbg = 0;
++#endif
++ cptr.cp = flash_make_addr (info, sect, offset);
++ flash_make_cmd (info, cmd, &cword);
++
++ if (dbg)
++ debug ("is= cmd %x(%c) addr %p ", cmd, cmd, cptr.cp);
++ switch (info->portwidth) {
++ case FLASH_CFI_8BIT:
++ if (dbg)
++ debug ("is= %x %x\n", cptr.cp[0], cword.c);
++ retval = (cptr.cp[0] == cword.c);
++ break;
++ case FLASH_CFI_16BIT:
++ if (dbg)
++ debug ("is= %4.4x %4.4x\n", cptr.wp[0], cword.w);
++ retval = (cptr.wp[0] == cword.w);
++ break;
++ case FLASH_CFI_32BIT:
++ if (dbg)
++ debug ("is= %8.8lx %8.8lx\n", cptr.lp[0], cword.l);
++ retval = (cptr.lp[0] == cword.l);
++ break;
++ case FLASH_CFI_64BIT:
++#ifdef DEBUG_FLASH
++ {
++ char str1[20];
++ char str2[20];
++
++ print_longlong (str1, cptr.llp[0]);
++ print_longlong (str2, cword.ll);
++ debug ("is= %s %s\n", str1, str2);
++ }
++#endif
++ retval = (cptr.llp[0] == cword.ll);
++ break;
++ default:
++ retval = 0;
++ break;
++ }
++ return retval;
++}
++
++/*-----------------------------------------------------------------------
++ */
++static int flash_isset (flash_info_t * info, flash_sect_t sect, uint offset, uchar cmd)
++{
++ cfiptr_t cptr;
++ cfiword_t cword;
++ int retval;
++
++ cptr.cp = flash_make_addr (info, sect, offset);
++ flash_make_cmd (info, cmd, &cword);
++ switch (info->portwidth) {
++ case FLASH_CFI_8BIT:
++ retval = ((cptr.cp[0] & cword.c) == cword.c);
++ break;
++ case FLASH_CFI_16BIT:
++ retval = ((cptr.wp[0] & cword.w) == cword.w);
++ break;
++ case FLASH_CFI_32BIT:
++ retval = ((cptr.lp[0] & cword.l) == cword.l);
++ break;
++ case FLASH_CFI_64BIT:
++ retval = ((cptr.llp[0] & cword.ll) == cword.ll);
++ break;
++ default:
++ retval = 0;
++ break;
++ }
++ return retval;
++}
++
++/*-----------------------------------------------------------------------
++ */
++static int flash_toggle (flash_info_t * info, flash_sect_t sect, uint offset, uchar cmd)
++{
++ cfiptr_t cptr;
++ cfiword_t cword;
++ int retval;
++
++ cptr.cp = flash_make_addr (info, sect, offset);
++ flash_make_cmd (info, cmd, &cword);
++ switch (info->portwidth) {
++ case FLASH_CFI_8BIT:
++ retval = ((cptr.cp[0] & cword.c) != (cptr.cp[0] & cword.c));
++ break;
++ case FLASH_CFI_16BIT:
++ retval = ((cptr.wp[0] & cword.w) != (cptr.wp[0] & cword.w));
++ break;
++ case FLASH_CFI_32BIT:
++ retval = ((cptr.lp[0] & cword.l) != (cptr.lp[0] & cword.l));
++ break;
++ case FLASH_CFI_64BIT:
++ retval = ((cptr.llp[0] & cword.ll) !=
++ (cptr.llp[0] & cword.ll));
++ break;
++ default:
++ retval = 0;
++ break;
++ }
++ return retval;
++}
++
++/*-----------------------------------------------------------------------
++ * detect if flash is compatible with the Common Flash Interface (CFI)
++ * http://www.jedec.org/download/search/jesd68.pdf
++ *
++*/
++static int flash_detect_cfi (flash_info_t * info)
++{
++ ulong data;
++
++ debug ("flash_detect_cfi()... ");
++
++#if defined(CONFIG_FLASH_AST2300)
++ data = *(ulong *)(0x1e6e2070); /* hardware traping */
++ if (data & 0x10) /* D[4]: 0/1 (8/16) */
++ info->portwidth = FLASH_CFI_16BIT;
++ else
++ info->portwidth = FLASH_CFI_8BIT;
++#else
++ info->portwidth = FLASH_CFI_8BIT;
++#endif
++
++ {
++ for (info->chipwidth = FLASH_CFI_BY8;
++ info->chipwidth <= info->portwidth;
++ info->chipwidth <<= 1) {
++ flash_write_cmd (info, 0, 0, FLASH_CMD_RESET);
++ flash_write_cmd (info, 0, FLASH_OFFSET_CFI, FLASH_CMD_CFI);
++ if (flash_isequal (info, 0, FLASH_OFFSET_CFI_RESP, 'Q')
++ //FIXME: Next 3 lines were changed for 8-bit/16-bit flash chips.
++ && flash_isequal (info, 0, FLASH_OFFSET_CFI_RESP1, 'R')
++ && flash_isequal (info, 0, FLASH_OFFSET_CFI_RESP2, 'Y')) {
++ info->interface = flash_read_uchar (info, FLASH_OFFSET_INTERFACE);
++ debug ("device interface is %d\n",
++ info->interface);
++ debug ("found port %d chip %d ",
++ info->portwidth, info->chipwidth);
++ debug ("port %d bits chip %d bits\n",
++ info->portwidth << CFI_FLASH_SHIFT_WIDTH,
++ info->chipwidth << CFI_FLASH_SHIFT_WIDTH);
++ return 1;
++ }
++ }
++ }
++ debug ("not found\n");
++ return 0;
++}
++
++/*
++ * The following code cannot be run from FLASH!
++ *
++ */
++ulong flash_get_size (ulong base, int banknum)
++{
++ flash_info_t *info = &flash_info[banknum];
++ int i, j;
++ flash_sect_t sect_cnt;
++ unsigned long sector;
++ unsigned long tmp;
++ int size_ratio;
++ uchar num_erase_regions;
++ int erase_region_size;
++ int erase_region_count;
++
++ info->start[0] = base;
++
++ if (flash_detect_cfi (info)) {
++ info->vendor = flash_read_uchar (info, FLASH_OFFSET_PRIMARY_VENDOR);
++#if defined(DEBUG_FLASH)
++ flash_printqry (info, 0);
++#endif
++ switch (info->vendor) {
++ case CFI_CMDSET_INTEL_STANDARD:
++ case CFI_CMDSET_INTEL_EXTENDED:
++ default:
++ info->cmd_reset = FLASH_CMD_RESET;
++ break;
++ case CFI_CMDSET_AMD_STANDARD:
++ case CFI_CMDSET_AMD_EXTENDED:
++ info->cmd_reset = AMD_CMD_RESET;
++ break;
++ }
++
++ debugX(2, "manufacturer is %d\n", info->vendor);
++ size_ratio = info->portwidth / info->chipwidth;
++ /* if the chip is x8/x16 reduce the ratio by half */
++#if 0
++ if ((info->interface == FLASH_CFI_X8X16)
++ && (info->chipwidth == FLASH_CFI_BY8)) {
++ size_ratio >>= 1;
++ }
++#endif
++ num_erase_regions = flash_read_uchar (info, FLASH_OFFSET_NUM_ERASE_REGIONS);
++ debugX(2, "size_ratio %d port %d bits chip %d bits\n",
++ size_ratio, info->portwidth << CFI_FLASH_SHIFT_WIDTH,
++ info->chipwidth << CFI_FLASH_SHIFT_WIDTH);
++ debugX(2, "found %d erase regions\n", num_erase_regions);
++ sect_cnt = 0;
++ sector = base;
++ for (i = 0; i < num_erase_regions; i++) {
++ if (i > MAX_NUM_ERASE_REGIONS) {
++ printf ("%d erase regions found, only %d used\n",
++ num_erase_regions, MAX_NUM_ERASE_REGIONS);
++ break;
++ }
++ // CFI Erase Block Region Information:
++ // Bits[31:16] = sect_size/256, 0 means 128-byte
++ // Bits[15:0] = num_sectors - 1
++ tmp = flash_read_long(info, 0,
++ FLASH_OFFSET_ERASE_REGIONS + i * 4);
++ debug("CFI erase block region info[%d]: 0x%08x, ",
++ i, tmp);
++ erase_region_count = (tmp & 0xffff) + 1;
++ tmp >>= 16;
++ erase_region_size = (tmp ? tmp * 256 : 128);
++ debug ("erase_region_count=%d erase_region_size=%d\n",
++ erase_region_count, erase_region_size);
++#if 0
++ erase_region_size = CFG_FLASH_SECTOR_SIZE; // Commented out
++ erase_region_count = CFG_FLASH_SECTOR_COUNT; // Commented out
++#endif
++ if (sect_cnt + erase_region_count > CONFIG_SYS_MAX_FLASH_SECT) {
++ printf("Warning: Erase region %d adds too many flash sectors"
++ " %d+%d; reducing to fit total limit of %d\n",
++ i, sect_cnt, erase_region_count, CONFIG_SYS_MAX_FLASH_SECT);
++ erase_region_count = CONFIG_SYS_MAX_FLASH_SECT - sect_cnt;
++ }
++ for (j = 0; j < erase_region_count; j++) {
++ info->start[sect_cnt] = sector;
++ sector += (erase_region_size * size_ratio);
++
++ /*
++ * Only read protection status from supported devices (intel...)
++ */
++ switch (info->vendor) {
++ case CFI_CMDSET_INTEL_EXTENDED:
++ case CFI_CMDSET_INTEL_STANDARD:
++ info->protect[sect_cnt] =
++ flash_isset (info, sect_cnt,
++ FLASH_OFFSET_PROTECT,
++ FLASH_STATUS_PROTECT);
++ break;
++ default:
++ info->protect[sect_cnt] = 0; /* default: not protected */
++ }
++
++ sect_cnt++;
++ }
++ }
++
++ info->sector_count = sect_cnt;
++ /* multiply the size by the number of chips */
++ // info->size = (1 << flash_read_uchar (info, FLASH_OFFSET_SIZE)) * size_ratio;
++ // Use only the sectors that fit within the flash_info array size.
++ info->size = sector - base;
++ printf("Flash bank %d at %08x has 0x%x bytes in %d sectors"
++ " (chipSize 1<<%d, size_ratio %d).\n",
++ banknum, base, info->size, info->sector_count,
++ flash_read_uchar(info, FLASH_OFFSET_SIZE), size_ratio);
++
++ info->buffer_size = (1 << flash_read_uchar (info, FLASH_OFFSET_BUFFER_SIZE));
++ /* Limit the buffer size to 32bytes to meet most of AMD-styles flash's minimum requirement */
++ if (info->buffer_size > 32)
++ info->buffer_size = 32;
++ tmp = 1 << flash_read_uchar (info, FLASH_OFFSET_ETOUT);
++ info->erase_blk_tout = (tmp * (1 << flash_read_uchar (info, FLASH_OFFSET_EMAX_TOUT)));
++ tmp = 1 << flash_read_uchar (info, FLASH_OFFSET_WBTOUT);
++ info->buffer_write_tout = (tmp * (1 << flash_read_uchar (info, FLASH_OFFSET_WBMAX_TOUT)));
++ tmp = 1 << flash_read_uchar (info, FLASH_OFFSET_WTOUT);
++ info->write_tout = (tmp * (1 << flash_read_uchar (info, FLASH_OFFSET_WMAX_TOUT))) / 1000;
++ info->flash_id = FLASH_MAN_CFI;
++#if 0
++ if ((info->interface == FLASH_CFI_X8X16) && (info->chipwidth == FLASH_CFI_BY8)) {
++ info->portwidth >>= 1; /* XXX - Need to test on x8/x16 in parallel. */
++ }
++#endif
++ }
++
++ flash_write_cmd (info, 0, 0, info->cmd_reset);
++ return (info->size);
++}
++
++
++/*-----------------------------------------------------------------------
++ */
++static int flash_write_cfiword (flash_info_t * info, ulong dest,
++ cfiword_t cword)
++{
++
++ cfiptr_t ctladdr;
++ cfiptr_t cptr;
++ int flag;
++
++ ctladdr.cp = flash_make_addr (info, 0, 0);
++ cptr.cp = (uchar *) dest;
++
++
++ /* Check if Flash is (sufficiently) erased */
++ switch (info->portwidth) {
++ case FLASH_CFI_8BIT:
++ flag = ((cptr.cp[0] & cword.c) == cword.c);
++ break;
++ case FLASH_CFI_16BIT:
++ flag = ((cptr.wp[0] & cword.w) == cword.w);
++ break;
++ case FLASH_CFI_32BIT:
++ flag = ((cptr.lp[0] & cword.l) == cword.l);
++ break;
++ case FLASH_CFI_64BIT:
++ flag = ((cptr.llp[0] & cword.ll) == cword.ll);
++ break;
++ default:
++ return 2;
++ }
++ if (!flag)
++ return 2;
++
++ /* Disable interrupts which might cause a timeout here */
++ flag = disable_interrupts ();
++
++ switch (info->vendor) {
++ case CFI_CMDSET_INTEL_EXTENDED:
++ case CFI_CMDSET_INTEL_STANDARD:
++ flash_write_cmd_nodbg (info, 0, 0, FLASH_CMD_CLEAR_STATUS);
++ flash_write_cmd_nodbg (info, 0, 0, FLASH_CMD_WRITE);
++ break;
++ case CFI_CMDSET_AMD_EXTENDED:
++ case CFI_CMDSET_AMD_STANDARD:
++ flash_unlock_seq (info, 0);
++ flash_write_cmd_nodbg (info, 0, AMD_ADDR_START, AMD_CMD_WRITE);
++ break;
++ }
++
++ switch (info->portwidth) {
++ case FLASH_CFI_8BIT:
++ cptr.cp[0] = cword.c;
++ break;
++ case FLASH_CFI_16BIT:
++ cptr.wp[0] = cword.w;
++ break;
++ case FLASH_CFI_32BIT:
++ cptr.lp[0] = cword.l;
++ break;
++ case FLASH_CFI_64BIT:
++ cptr.llp[0] = cword.ll;
++ break;
++ }
++
++ /* re-enable interrupts if necessary */
++ if (flag)
++ enable_interrupts ();
++
++ return flash_full_status_check (info, 0, info->write_tout, "write");
++}
++
++#ifdef CONFIG_SYS_FLASH_USE_BUFFER_WRITE
++
++/* loop through the sectors from the highest address
++ * when the passed address is greater or equal to the sector address
++ * we have a match
++ */
++static flash_sect_t find_sector (flash_info_t * info, ulong addr)
++{
++ flash_sect_t sector;
++
++ for (sector = info->sector_count - 1; sector >= 0; sector--) {
++ if (addr >= info->start[sector])
++ break;
++ }
++ return sector;
++}
++
++static int flash_write_cfibuffer (flash_info_t * info, ulong dest, uchar * cp,
++ int len)
++{
++ flash_sect_t sector;
++ int cnt;
++ int retcode;
++ volatile cfiptr_t src;
++ volatile cfiptr_t dst;
++
++/* Add AMD write buffer mode support, ycchen@102006 */
++#if 0
++ /* buffered writes in the AMD chip set is not supported yet */
++ if((info->vendor == CFI_CMDSET_AMD_STANDARD) ||
++ (info->vendor == CFI_CMDSET_AMD_EXTENDED))
++ return ERR_INVAL;
++#endif
++ if((info->vendor == CFI_CMDSET_AMD_STANDARD) ||
++ (info->vendor == CFI_CMDSET_AMD_EXTENDED))
++ {
++ retcode = flash_write_cfibuffer_amd(info, dest, cp, len);
++ return retcode;
++ }
++
++ src.cp = cp;
++ dst.cp = (uchar *) dest;
++ sector = find_sector (info, dest);
++ flash_write_cmd (info, sector, 0, FLASH_CMD_CLEAR_STATUS);
++ flash_write_cmd (info, sector, 0, FLASH_CMD_WRITE_TO_BUFFER);
++ if ((retcode =
++ flash_status_check (info, sector, info->buffer_write_tout,
++ "write to buffer")) == ERR_OK) {
++ /* reduce the number of loops by the width of the port */
++ switch (info->portwidth) {
++ case FLASH_CFI_8BIT:
++ cnt = len;
++ break;
++ case FLASH_CFI_16BIT:
++ cnt = len >> 1;
++ break;
++ case FLASH_CFI_32BIT:
++ cnt = len >> 2;
++ break;
++ case FLASH_CFI_64BIT:
++ cnt = len >> 3;
++ break;
++ default:
++ return ERR_INVAL;
++ break;
++ }
++ flash_write_cmd (info, sector, 0, (uchar) cnt - 1);
++ while (cnt-- > 0) {
++ switch (info->portwidth) {
++ case FLASH_CFI_8BIT:
++ *dst.cp++ = *src.cp++;
++ break;
++ case FLASH_CFI_16BIT:
++ *dst.wp++ = *src.wp++;
++ break;
++ case FLASH_CFI_32BIT:
++ *dst.lp++ = *src.lp++;
++ break;
++ case FLASH_CFI_64BIT:
++ *dst.llp++ = *src.llp++;
++ break;
++ default:
++ return ERR_INVAL;
++ break;
++ }
++ }
++ flash_write_cmd (info, sector, 0,
++ FLASH_CMD_WRITE_BUFFER_CONFIRM);
++ retcode =
++ flash_full_status_check (info, sector,
++ info->buffer_write_tout,
++ "buffer write");
++ }
++ flash_write_cmd (info, sector, 0, FLASH_CMD_CLEAR_STATUS);
++ return retcode;
++}
++
++
++static int flash_write_cfibuffer_amd (flash_info_t * info, ulong dest, uchar * cp,
++ int len)
++{
++ flash_sect_t sector;
++ int cnt;
++ int retcode;
++ volatile cfiptr_t src;
++ volatile cfiptr_t dst;
++ volatile cfiword_t tmpsrc, tmpdst;
++
++ src.cp = cp;
++ dst.cp = (uchar *) dest;
++ sector = find_sector (info, dest);
++ flash_unlock_seq (info, 0);
++ if ((retcode =
++ flash_status_check (info, sector, info->buffer_write_tout,
++ "write to buffer")) == ERR_OK) {
++ /* reduce the number of loops by the width of the port */
++ switch (info->portwidth) {
++ case FLASH_CFI_8BIT:
++ cnt = len;
++ *dst.cp = (uchar) (AMD_CMD_WRITE_TO_BUFFER);
++ *dst.cp = (uchar) (cnt -1);
++ break;
++ case FLASH_CFI_16BIT:
++ cnt = len >> 1;
++ *dst.wp = (unsigned short) (AMD_CMD_WRITE_TO_BUFFER);
++ *dst.wp = (unsigned short) (cnt -1);
++ break;
++ case FLASH_CFI_32BIT:
++ cnt = len >> 2;
++ *dst.lp = (unsigned long) (AMD_CMD_WRITE_TO_BUFFER);
++ *dst.lp = (unsigned long) (cnt -1);
++ break;
++ case FLASH_CFI_64BIT:
++ cnt = len >> 3;
++ *dst.llp = (unsigned long long) (AMD_CMD_WRITE_TO_BUFFER);
++ *dst.llp = (unsigned long long) (cnt -1);
++ break;
++ default:
++ return ERR_INVAL;
++ break;
++ }
++ while (cnt-- > 0) {
++ switch (info->portwidth) {
++ case FLASH_CFI_8BIT:
++ *dst.cp++ = *src.cp++;
++ break;
++ case FLASH_CFI_16BIT:
++ *dst.wp++ = *src.wp++;
++ break;
++ case FLASH_CFI_32BIT:
++ *dst.lp++ = *src.lp++;
++ break;
++ case FLASH_CFI_64BIT:
++ *dst.llp++ = *src.llp++;
++ break;
++ default:
++ return ERR_INVAL;
++ break;
++ }
++ }
++ switch (info->portwidth) {
++ case FLASH_CFI_8BIT:
++ src.cp--;
++ dst.cp--;
++ *dst.cp = (unsigned char) (AMD_CMD_BUFFER_TO_FLASH);
++ tmpsrc.c = *src.cp & 0x80;
++
++ do {
++ tmpdst.c = *(volatile uchar *)(dst.cp);
++
++ if (tmpdst.c & 0x20) { /* toggle DQ5 */
++ tmpdst.c = *(volatile uchar *)(dst.cp);
++ if ((tmpdst.c & 0x80) != tmpsrc.c)
++ {
++ printf("program error occurred\n");
++ flash_write_cmd (info, sector, 0, info->cmd_reset);
++ return ERR_PROG_ERROR;
++ }
++ }
++ else if (tmpdst.c & 0x02) { /* toggle DQ1 */
++ tmpdst.c = *(volatile uchar *)(dst.cp);
++ if ((tmpdst.c & 0x80) != tmpsrc.c)
++ {
++ printf("write buffer error occurred \n");
++ write_buffer_abort_reset(info, sector);
++ return ERR_PROG_ERROR;
++ }
++ }
++
++ } while ((tmpdst.c & 0x80) != tmpsrc.c);
++
++ break;
++ case FLASH_CFI_16BIT:
++ src.wp--;
++ dst.wp--;
++ *dst.wp = (unsigned short) (AMD_CMD_BUFFER_TO_FLASH);
++ tmpsrc.w = *src.wp & 0x80;
++
++ do {
++ tmpdst.w = *(volatile short *)(dst.wp);
++
++ if (tmpdst.w & 0x20) { /* toggle DQ5 */
++ tmpdst.w = *(volatile ushort *)(dst.wp);
++ if ((tmpdst.w & 0x80) != tmpsrc.w)
++ {
++ printf("program error occurred\n");
++ flash_write_cmd (info, sector, 0, info->cmd_reset);
++ return ERR_PROG_ERROR;
++ }
++ }
++ else if (tmpdst.w & 0x02) { /* toggle DQ1 */
++ tmpdst.w = *(volatile ushort *)(dst.wp);
++ if ((tmpdst.w & 0x80) != tmpsrc.w)
++ {
++ printf("write buffer error occurred \n");
++ write_buffer_abort_reset(info, sector);
++ return ERR_PROG_ERROR;
++ }
++ }
++
++ } while ((tmpdst.w & 0x80) != tmpsrc.w);
++
++ break;
++ case FLASH_CFI_32BIT:
++ src.lp--;
++ dst.lp--;
++ *dst.lp = (unsigned long) (AMD_CMD_BUFFER_TO_FLASH);
++ tmpsrc.l = *src.lp & 0x80;
++
++ do {
++ tmpdst.l = *(volatile ulong *)(dst.lp);
++
++ if (tmpdst.l & 0x20) { /* toggle DQ5 */
++ tmpdst.l = *(volatile ulong *)(dst.lp);
++ if ((tmpdst.l & 0x80) != tmpsrc.l)
++ {
++ printf("program error occurred\n");
++ flash_write_cmd (info, sector, 0, info->cmd_reset);
++ return ERR_PROG_ERROR;
++ }
++ }
++ else if (tmpdst.l & 0x02) { /* toggle DQ1 */
++ tmpdst.l = *(volatile ulong *)(dst.lp);
++ if ((tmpdst.l & 0x80) != tmpsrc.l)
++ {
++ printf("write buffer error occurred \n");
++ write_buffer_abort_reset(info, sector);
++ return ERR_PROG_ERROR;
++ }
++ }
++
++ } while ((tmpdst.l & 0x80) != tmpsrc.l);
++
++ break;
++ case FLASH_CFI_64BIT:
++ src.llp--;
++ dst.llp--;
++ *dst.llp = (unsigned long long) (AMD_CMD_BUFFER_TO_FLASH);
++ tmpsrc.ll = *src.llp & 0x80;
++
++ do {
++ tmpdst.ll = *(volatile unsigned long long *)(dst.llp);
++
++ if (tmpdst.ll & 0x20) { /* toggle DQ5 */
++ tmpdst.ll = *(volatile unsigned long long *)(dst.llp);
++ if ((tmpdst.ll & 0x80) != tmpsrc.ll)
++ {
++ printf("program error occurred\n");
++ flash_write_cmd (info, sector, 0, info->cmd_reset);
++ return ERR_PROG_ERROR;
++ }
++ }
++ else if (tmpdst.ll & 0x02) { /* toggle DQ1 */
++ tmpdst.ll = *(volatile unsigned long long *)(dst.llp);
++ if ((tmpdst.ll & 0x80) != tmpsrc.ll)
++ {
++ printf("write buffer error occurred \n");
++ write_buffer_abort_reset(info, sector);
++ return ERR_PROG_ERROR;
++ }
++ }
++
++ } while ((tmpdst.ll & 0x80) != tmpsrc.ll);
++
++ break;
++ default:
++ return ERR_INVAL;
++ break;
++ }
++
++ retcode =
++ flash_full_status_check (info, sector,
++ info->buffer_write_tout,
++ "buffer write");
++ }
++
++ return retcode;
++}
++#endif /* CONFIG_SYS_FLASH_USE_BUFFER_WRITE */
++
++#ifdef CONFIG_FLASH_AST2300_DMA
++#define STCBaseAddress 0x1e620000
++
++/* for DMA */
++#define REG_FLASH_INTERRUPT_STATUS 0x08
++#define REG_FLASH_DMA_CONTROL 0x80
++#define REG_FLASH_DMA_FLASH_BASE 0x84
++#define REG_FLASH_DMA_DRAM_BASE 0x88
++#define REG_FLASH_DMA_LENGTH 0x8c
++
++#define FLASH_STATUS_DMA_BUSY 0x0000
++#define FLASH_STATUS_DMA_READY 0x0800
++#define FLASH_STATUS_DMA_CLEAR 0x0800
++
++#define FLASH_DMA_ENABLE 0x01
++
++void * memmove_dma(void * dest,const void *src,size_t count)
++{
++ ulong count_align, poll_time, data;
++
++ count_align = (count + 3) & 0xFFFFFFFC; /* 4-bytes align */
++ poll_time = 100; /* set 100 us as default */
++
++ *(ulong *) (STCBaseAddress + REG_FLASH_DMA_CONTROL) = (ulong) (~FLASH_DMA_ENABLE);
++
++ *(ulong *) (STCBaseAddress + REG_FLASH_DMA_FLASH_BASE) = (ulong *) (src);
++ *(ulong *) (STCBaseAddress + REG_FLASH_DMA_DRAM_BASE) = (ulong *) (dest);
++ *(ulong *) (STCBaseAddress + REG_FLASH_DMA_LENGTH) = (ulong) (count_align);
++ udelay(10);
++ *(ulong *) (STCBaseAddress + REG_FLASH_DMA_CONTROL) = (ulong) (FLASH_DMA_ENABLE);
++
++ /* wait poll */
++ do {
++ udelay(poll_time);
++ data = *(ulong *) (STCBaseAddress + REG_FLASH_INTERRUPT_STATUS);
++ } while (!(data & FLASH_STATUS_DMA_READY));
++
++ /* clear status */
++ *(ulong *) (STCBaseAddress + REG_FLASH_INTERRUPT_STATUS) |= FLASH_STATUS_DMA_CLEAR;
++}
++#endif
++#endif /* CFG_FLASH_CFI */
+diff --git a/board/aspeed/ast2400/flash_spi.c b/board/aspeed/ast2400/flash_spi.c
+new file mode 100755
+index 0000000..ad89254
+--- /dev/null
++++ b/board/aspeed/ast2400/flash_spi.c
+@@ -0,0 +1,1634 @@
++/*
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
++ * MA 02111-1307 USA
++ *
++ * History
++ * 01/20/2004 - combined variants of original driver.
++ * 01/22/2004 - Write performance enhancements for parallel chips (Tolunay)
++ * 01/23/2004 - Support for x8/x16 chips (Rune Raknerud)
++ * 01/27/2004 - Little endian support Ed Okerson
++ *
++ * Tested Architectures
++ * Port Width Chip Width # of banks Flash Chip Board
++ * 32 16 1 28F128J3 seranoa/eagle
++ * 64 16 1 28F128J3 seranoa/falcon
++ *
++ */
++
++/* The DEBUG define must be before common to enable debugging */
++/* #define DEBUG */
++
++#include <common.h>
++#include <asm/processor.h>
++#include <asm/byteorder.h>
++#include <environment.h>
++#ifdef CONFIG_FLASH_SPI
++
++/*
++ * This file implements a Common Flash Interface (CFI) driver for U-Boot.
++ * The width of the port and the width of the chips are determined at initialization.
++ * These widths are used to calculate the address for access CFI data structures.
++ * It has been tested on an Intel Strataflash implementation and AMD 29F016D.
++ *
++ * References
++ * JEDEC Standard JESD68 - Common Flash Interface (CFI)
++ * JEDEC Standard JEP137-A Common Flash Interface (CFI) ID Codes
++ * Intel Application Note 646 Common Flash Interface (CFI) and Command Sets
++ * Intel 290667-008 3 Volt Intel StrataFlash Memory datasheet
++ *
++ * TODO
++ *
++ * Use Primary Extended Query table (PRI) and Alternate Algorithm Query
++ * Table (ALT) to determine if protection is available
++ *
++ * Add support for other command sets Use the PRI and ALT to determine command set
++ * Verify erase and program timeouts.
++ */
++
++#ifndef CONFIG_FLASH_BANKS_LIST
++#define CONFIG_FLASH_BANKS_LIST { CONFIG_SYS_FLASH_BASE }
++#endif
++
++/* use CFG_MAX_FLASH_BANKS_DETECT if defined */
++#ifdef CONFIG_SYS_MAX_FLASH_BANKS_DETECT
++static ulong bank_base[CONFIG_SYS_MAX_FLASH_BANKS_DETECT] = CONFIG_FLASH_BANKS_LIST;
++flash_info_t flash_info[CONFIG_SYS_MAX_FLASH_BANKS_DETECT]; /* FLASH chips info */
++#else
++static ulong bank_base[CONFIG_SYS_MAX_FLASH_BANKS] = CONFIG_FLASH_BANKS_LIST;
++flash_info_t flash_info[CONFIG_SYS_MAX_FLASH_BANKS]; /* FLASH chips info */
++#endif
++
++/* Support Flash ID */
++#define STM25P64 0x172020
++#define STM25P128 0x182020
++#define N25Q256 0x19ba20
++#define N25Q512 0x20ba20
++#define S25FL064A 0x160201
++#define S25FL128P 0x182001
++#define S25FL256S 0x190201
++#define W25X16 0x1530ef
++#define W25X64 0x1730ef
++#define W25Q64BV 0x1740ef
++#define W25Q128BV 0x1840ef
++#define W25Q256FV 0x1940ef
++#define MX25L1605D 0x1520C2
++#define MX25L12805D 0x1820C2
++#define MX25L25635E 0x1920C2
++#define SST25VF016B 0x4125bf
++#define SST25VF064C 0x4b25bf
++#define AT25DF161 0x02461F
++#define AT25DF321 0x01471F
++
++/* SPI Define */
++#if defined(CONFIG_FLASH_AST2300) || defined(CONFIG_AST1300)
++#if defined(CONFIG_AST1300)
++#define STCBaseAddress 0x00620000
++#else
++#define STCBaseAddress 0x1e620000
++#endif
++#define SCU_REVISION_REGISTER 0x1e6e207c
++#define SCU_CACHE_CTRL_REGISTER 0x1e6e2118
++
++#define SPICtrlRegOffset 0x10
++#define SPICtrlRegOffset2 0x14
++
++#define SPIMiscCtrlRegOffset 0x54
++
++/* for DMA */
++#define REG_FLASH_INTERRUPT_STATUS 0x08
++#define REG_FLASH_DMA_CONTROL 0x80
++#define REG_FLASH_DMA_FLASH_BASE 0x84
++#define REG_FLASH_DMA_DRAM_BASE 0x88
++#define REG_FLASH_DMA_LENGTH 0x8c
++
++#define FLASH_STATUS_DMA_BUSY 0x0000
++#define FLASH_STATUS_DMA_READY 0x0800
++#define FLASH_STATUS_DMA_CLEAR 0x0800
++
++#define FLASH_DMA_ENABLE 0x01
++#else
++#define STCBaseAddress 0x16000000
++
++#define SPICtrlRegOffset 0x04
++#define SPICtrlRegOffset2 0x0C
++#endif /* CONFIG_FLASH_AST2300 */
++
++#define CMD_MASK 0xFFFFFFF8
++
++#define NORMALREAD 0x00
++#define FASTREAD 0x01
++#define NORMALWRITE 0x02
++#define USERMODE 0x03
++
++#define CE_LOW 0x00
++#define CE_HIGH 0x04
++
++/* AST2300 only */
++#define IOMODEx1 0x00000000
++#define IOMODEx2 0x20000000
++#define IOMODEx2_dummy 0x30000000
++#define IOMODEx4 0x40000000
++#define IOMODEx4_dummy 0x50000000
++
++#define DUMMY_COMMAND_OUT 0x00008000
++/* ~AST2300 only */
++
++/* specificspi */
++#define SpecificSPI_N25Q512 0x00000001
++
++static ulong AST2300_SPICLK_DIV[16] = {0x0F, 0x07, 0x0E, 0x06, 0x0D, 0x05, 0x0C, 0x04, \
++ 0x0B, 0x03, 0x0A, 0x02, 0x09, 0x01, 0x08, 0x00 };
++
++/*-----------------------------------------------------------------------
++ * Functions
++ */
++static void reset_flash (flash_info_t * info);
++static void enable_write (flash_info_t * info);
++static void write_status_register (flash_info_t * info, uchar data);
++static void enable4b (flash_info_t * info);
++static void enable4b_spansion (flash_info_t * info);
++static void enable4b_numonyx (flash_info_t * info);
++static ulong flash_get_size (ulong base, int banknum);
++static int flash_write_buffer (flash_info_t *info, uchar *src, ulong addr, int len);
++#if defined(CFG_ENV_IS_IN_FLASH) || defined(CFG_ENV_ADDR_REDUND) || (CFG_MONITOR_BASE >= CFG_FLASH_BASE)
++static flash_info_t *flash_get_info(ulong base);
++#endif
++
++
++/*-----------------------------------------------------------------------
++ * create an address based on the offset and the port width
++ */
++inline uchar *flash_make_addr (flash_info_t * info, flash_sect_t sect, uint offset)
++{
++#ifdef CONFIG_2SPIFLASH
++ if (info->start[0] >= PHYS_FLASH_2)
++ return ((uchar *) (info->start[sect] + (offset * 1) - (PHYS_FLASH_2 - PHYS_FLASH_2_BASE) ));
++ else
++ return ((uchar *) (info->start[sect] + (offset * 1)));
++#else
++ return ((uchar *) (info->start[sect] + (offset * 1)));
++#endif
++}
++
++/*-----------------------------------------------------------------------
++ * read a character at a port width address
++ */
++inline uchar flash_read_uchar (flash_info_t * info, uint offset)
++{
++ uchar *cp;
++
++ cp = flash_make_addr (info, 0, offset);
++#if defined(__LITTLE_ENDIAN)
++ return (cp[0]);
++#else
++ return (cp[1 - 1]);
++#endif
++}
++
++/*-----------------------------------------------------------------------
++ * read a short word by swapping for ppc format.
++ */
++ushort flash_read_ushort (flash_info_t * info, flash_sect_t sect, uint offset)
++{
++ uchar *addr;
++ ushort retval;
++
++#ifdef DEBUG
++ int x;
++#endif
++ addr = flash_make_addr (info, sect, offset);
++
++#ifdef DEBUG
++ debug ("ushort addr is at %p 1 = %d\n", addr,
++ 1);
++ for (x = 0; x < 2 * 1; x++) {
++ debug ("addr[%x] = 0x%x\n", x, addr[x]);
++ }
++#endif
++#if defined(__LITTLE_ENDIAN)
++ retval = ((addr[(1)] << 8) | addr[0]);
++#else
++ retval = ((addr[(2 * 1) - 1] << 8) |
++ addr[1 - 1]);
++#endif
++
++ debug ("retval = 0x%x\n", retval);
++ return retval;
++}
++
++/*-----------------------------------------------------------------------
++ * read a long word by picking the least significant byte of each maiximum
++ * port size word. Swap for ppc format.
++ */
++ulong flash_read_long (flash_info_t * info, flash_sect_t sect, uint offset)
++{
++ uchar *addr;
++ ulong retval;
++
++#ifdef DEBUG
++ int x;
++#endif
++ addr = flash_make_addr (info, sect, offset);
++
++#ifdef DEBUG
++ debug ("long addr is at %p 1 = %d\n", addr,
++ 1);
++ for (x = 0; x < 4 * 1; x++) {
++ debug ("addr[%x] = 0x%x\n", x, addr[x]);
++ }
++#endif
++#if defined(__LITTLE_ENDIAN)
++ retval = (addr[0] << 16) | (addr[(1)] << 24) |
++ (addr[(2 * 1)]) | (addr[(3 * 1)] << 8);
++#else
++ retval = (addr[(2 * 1) - 1] << 24) |
++ (addr[(1) - 1] << 16) |
++ (addr[(4 * 1) - 1] << 8) |
++ addr[(3 * 1) - 1];
++#endif
++ return retval;
++}
++
++/*-----------------------------------------------------------------------
++ */
++static void disable_cache(void)
++{
++#if defined(AST1300_CPU_CACHE_ENABLE)
++ ulong uldata;
++
++ uldata = *(volatile ulong *) (SCU_CACHE_CTRL_REGISTER);
++ uldata &= 0xfffffffd;
++ *(ulong *) (SCU_CACHE_CTRL_REGISTER) = uldata;
++#endif
++}
++
++static void enable_cache(void)
++{
++#if defined(AST1300_CPU_CACHE_ENABLE)
++ ulong uldata;
++
++ uldata = *(volatile ulong *) (SCU_CACHE_CTRL_REGISTER);
++ uldata |= 0x00000002;
++ *(ulong *) (SCU_CACHE_CTRL_REGISTER) = uldata;
++#endif
++}
++
++static void reset_flash (flash_info_t * info)
++{
++ ulong ulCtrlData, CtrlOffset, MiscCtrlOffset;
++
++ if (info->CE == 2)
++ {
++ CtrlOffset = SPICtrlRegOffset2;
++ }
++ else
++ {
++ CtrlOffset = SPICtrlRegOffset;
++ }
++
++#if defined(CONFIG_FLASH_AST2300) || defined(CONFIG_AST1300)
++ ulCtrlData = info->iomode | (info->readcmd << 16) | (info->tCK_Read << 8) | (info->dummybyte << 6) | FASTREAD;
++#if 0
++ if (info->quadport)
++ {
++ MiscCtrlOffset = SPIMiscCtrlRegOffset;
++ *(ulong *) (STCBaseAddress + MiscCtrlOffset) = info->dummydata;
++ ulCtrlData |= DUMMY_COMMAND_OUT;
++ }
++#endif
++#else
++ ulCtrlData = (info->readcmd << 16) | (info->tCK_Read << 8) | (info->dummybyte << 6) | FASTREAD;
++ if (info->dualport)
++ ulCtrlData |= 0x08;
++#endif
++ *(ulong *) (STCBaseAddress + CtrlOffset) = ulCtrlData;
++
++ enable_cache();
++}
++
++static void enable_write (flash_info_t * info)
++{
++ ulong base;
++ ulong ulCtrlData, CtrlOffset;
++ uchar jReg;
++
++ if (info->CE == 2)
++ {
++ CtrlOffset = SPICtrlRegOffset2;
++ }
++ else
++ {
++ CtrlOffset = SPICtrlRegOffset;
++ }
++
++ //base = info->start[0];
++ base = flash_make_addr (info, 0, 0);
++
++ ulCtrlData = (info->tCK_Write << 8);
++ ulCtrlData |= CE_LOW | USERMODE;
++ *(ulong *) (STCBaseAddress + CtrlOffset) = ulCtrlData;
++ udelay(200);
++ *(uchar *) (base) = (uchar) (0x06);
++ udelay(10);
++ ulCtrlData &= CMD_MASK;
++ ulCtrlData |= CE_HIGH | USERMODE;
++ *(ulong *) (STCBaseAddress + CtrlOffset) = ulCtrlData;
++ udelay(200);
++
++ ulCtrlData &= CMD_MASK;
++ ulCtrlData |= CE_LOW | USERMODE;
++ *(ulong *) (STCBaseAddress + CtrlOffset) = ulCtrlData;
++ udelay(200);
++ *(uchar *) (base) = (uchar) (0x05);
++ udelay(10);
++ do {
++ jReg = *(volatile uchar *) (base);
++ } while (!(jReg & 0x02));
++ ulCtrlData &= CMD_MASK;
++ ulCtrlData |= CE_HIGH | USERMODE;
++ *(ulong *) (STCBaseAddress + CtrlOffset) = ulCtrlData;
++ udelay(200);
++
++}
++
++static void write_status_register (flash_info_t * info, uchar data)
++{
++ ulong base;
++ ulong ulSMMBase, ulCtrlData, CtrlOffset;
++ uchar jReg;
++
++ if (info->CE == 2)
++ {
++ CtrlOffset = SPICtrlRegOffset2;
++ }
++ else
++ {
++ CtrlOffset = SPICtrlRegOffset;
++ }
++
++ //base = info->start[0];
++ base = flash_make_addr (info, 0, 0);
++
++ enable_write (info);
++
++ ulCtrlData = (info->tCK_Write << 8);
++ ulCtrlData |= CE_LOW | USERMODE;
++ *(ulong *) (STCBaseAddress + CtrlOffset) = ulCtrlData;
++ udelay(200);
++ *(uchar *) (base) = (uchar) (0x01);
++ udelay(10);
++ *(uchar *) (base) = (uchar) (data);
++ ulCtrlData &= CMD_MASK;
++ ulCtrlData |= CE_HIGH | USERMODE;
++ *(ulong *) (STCBaseAddress + CtrlOffset) = ulCtrlData;
++ udelay(200);
++
++ ulCtrlData &= CMD_MASK;
++ ulCtrlData |= CE_LOW | USERMODE;
++ *(ulong *) (STCBaseAddress + CtrlOffset) = ulCtrlData;
++ udelay(200);
++ *(uchar *) (base) = (uchar) (0x05);
++ udelay(10);
++ do {
++ jReg = *(volatile uchar *) (base);
++ } while (jReg & 0x01);
++ ulCtrlData &= CMD_MASK;
++ ulCtrlData |= CE_HIGH | USERMODE;
++ *(ulong *) (STCBaseAddress + CtrlOffset) = ulCtrlData;
++ udelay(200);
++
++}
++
++static void enable4b (flash_info_t * info)
++{
++ ulong base;
++ ulong ulSMMBase, ulCtrlData, CtrlOffset;
++ uchar jReg;
++
++ if (info->CE == 2)
++ {
++ CtrlOffset = SPICtrlRegOffset2;
++ }
++ else
++ {
++ CtrlOffset = SPICtrlRegOffset;
++ }
++
++ //base = info->start[0];
++ base = flash_make_addr (info, 0, 0);
++
++ ulCtrlData = (info->tCK_Write << 8);
++ ulCtrlData |= CE_LOW | USERMODE;
++ *(ulong *) (STCBaseAddress + CtrlOffset) = ulCtrlData;
++ udelay(200);
++ *(uchar *) (base) = (uchar) (0xb7);
++ ulCtrlData &= CMD_MASK;
++ ulCtrlData |= CE_HIGH | USERMODE;
++ *(ulong *) (STCBaseAddress + CtrlOffset) = ulCtrlData;
++ udelay(200);
++
++} /* enable4b */
++
++static void enable4b_spansion (flash_info_t * info)
++{
++ ulong base;
++ ulong ulSMMBase, ulCtrlData, CtrlOffset;
++ uchar jReg;
++
++ if (info->CE == 2)
++ {
++ CtrlOffset = SPICtrlRegOffset2;
++ }
++ else
++ {
++ CtrlOffset = SPICtrlRegOffset;
++ }
++
++ //base = info->start[0];
++ base = flash_make_addr (info, 0, 0);
++
++ /* Enable 4B: BAR0 D[7] = 1 */
++ ulCtrlData = (info->tCK_Write << 8);
++ ulCtrlData |= CE_LOW | USERMODE;
++ *(ulong *) (STCBaseAddress + CtrlOffset) = ulCtrlData;
++ udelay(200);
++ *(uchar *) (base) = (uchar) (0x17);
++ udelay(10);
++ *(uchar *) (base) = (uchar) (0x80);
++ ulCtrlData &= CMD_MASK;
++ ulCtrlData |= CE_HIGH | USERMODE;
++ *(ulong *) (STCBaseAddress + CtrlOffset) = ulCtrlData;
++ udelay(200);
++
++ ulCtrlData &= CMD_MASK;
++ ulCtrlData |= CE_LOW | USERMODE;
++ *(ulong *) (STCBaseAddress + CtrlOffset) = ulCtrlData;
++ udelay(200);
++ *(uchar *) (base) = (uchar) (0x16);
++ udelay(10);
++ do {
++ jReg = *(volatile uchar *) (base);
++ } while (!(jReg & 0x80));
++ ulCtrlData &= CMD_MASK;
++ ulCtrlData |= CE_HIGH | USERMODE;
++ *(ulong *) (STCBaseAddress + CtrlOffset) = ulCtrlData;
++ udelay(200);
++
++} /* enable4b_spansion */
++
++static void enable4b_numonyx (flash_info_t * info)
++{
++ ulong base;
++ ulong ulSMMBase, ulCtrlData, CtrlOffset;
++ uchar jReg;
++
++ if (info->CE == 2)
++ {
++ CtrlOffset = SPICtrlRegOffset2;
++ }
++ else
++ {
++ CtrlOffset = SPICtrlRegOffset;
++ }
++
++ //base = info->start[0];
++ base = flash_make_addr (info, 0, 0);
++
++ /* Enable Write */
++ enable_write (info);
++
++ /* Enable 4B: CMD:0xB7 */
++ ulCtrlData = (info->tCK_Write << 8);
++ ulCtrlData |= CE_LOW | USERMODE;
++ *(ulong *) (STCBaseAddress + CtrlOffset) = ulCtrlData;
++ udelay(200);
++ *(uchar *) (base) = (uchar) (0xB7);
++ udelay(10);
++ ulCtrlData &= CMD_MASK;
++ ulCtrlData |= CE_HIGH | USERMODE;
++ *(ulong *) (STCBaseAddress + CtrlOffset) = ulCtrlData;
++ udelay(200);
++
++} /* enable4b_numonyx */
++
++/*
++ *
++ */
++static ulong flash_get_size (ulong base, int banknum)
++{
++ flash_info_t *info = &flash_info[banknum];
++ int j;
++ unsigned long sector;
++ int erase_region_size;
++ ulong ulCtrlData, CtrlOffset;
++ ulong ulID;
++ uchar ch[3];
++ ulong cpuclk, div, reg;
++ ulong WriteClk, EraseClk, ReadClk;
++ ulong vbase;
++ ulong SCURevision;
++
++ ulong ulRefPLL;
++ ulong ulDeNumerator;
++ ulong ulNumerator;
++ ulong ulOD;
++
++ disable_cache();
++
++ info->start[0] = base;
++ vbase = flash_make_addr (info, 0, 0);
++
++#if defined(CONFIG_FLASH_AST2300) || defined(CONFIG_AST1300)
++ CtrlOffset = SPICtrlRegOffset;
++ info->CE = 0;
++#else
++ if (vbase == PHYS_FLASH_1)
++ {
++ CtrlOffset = SPICtrlRegOffset2;
++ info->CE = 2;
++ }
++ else
++ {
++ CtrlOffset = SPICtrlRegOffset;
++ info->CE = 0;
++ }
++#endif
++
++ /* Get Flash ID */
++ ulCtrlData = *(ulong *) (STCBaseAddress + CtrlOffset) & CMD_MASK;
++ ulCtrlData |= CE_LOW | USERMODE;
++ *(ulong *) (STCBaseAddress + CtrlOffset) = ulCtrlData;
++ udelay(200);
++ *(uchar *) (vbase) = (uchar) (0x9F);
++ udelay(10);
++ ch[0] = *(volatile uchar *)(vbase);
++ udelay(10);
++ ch[1] = *(volatile uchar *)(vbase);
++ udelay(10);
++ ch[2] = *(volatile uchar *)(vbase);
++ udelay(10);
++ ulCtrlData = *(ulong *) (STCBaseAddress + CtrlOffset) & CMD_MASK;
++ ulCtrlData |= CE_HIGH | USERMODE;
++ *(ulong *) (STCBaseAddress + CtrlOffset) = ulCtrlData;
++ udelay(200);
++ ulID = ((ulong)ch[0]) | ((ulong)ch[1] << 8) | ((ulong)ch[2] << 16) ;
++ info->flash_id = ulID;
++
++ //printf("SPI Flash ID: %x \n", ulID);
++
++ /* init default */
++ info->iomode = IOMODEx1;
++ info->address32 = 0;
++ info->quadport = 0;
++ info->specificspi = 0;
++
++ switch (info->flash_id)
++ {
++ case STM25P64:
++ info->sector_count = 128;
++ info->size = 0x800000;
++ erase_region_size = 0x10000;
++ info->readcmd = 0x0b;
++ info->dualport = 0;
++ info->dummybyte = 1;
++ info->buffersize = 256;
++ WriteClk = 40;
++ EraseClk = 20;
++ ReadClk = 40;
++ break;
++
++ case STM25P128:
++ info->sector_count = 64;
++ info->size = 0x1000000;
++ erase_region_size = 0x40000;
++ info->readcmd = 0x0b;
++ info->dualport = 0;
++ info->dummybyte = 1;
++ info->buffersize = 256;
++ WriteClk = 50;
++ EraseClk = 20;
++ ReadClk = 50;
++ break;
++
++ case N25Q256:
++ info->sector_count = 256;
++ info->size = 0x1000000;
++ erase_region_size = 0x10000;
++ info->readcmd = 0x0b;
++ info->dualport = 0;
++ info->dummybyte = 1;
++ info->buffersize = 256;
++ WriteClk = 50;
++ EraseClk = 20;
++ ReadClk = 50;
++#if defined(CONFIG_FLASH_AST2300) || defined(CONFIG_AST1300)
++ info->sector_count = 512;
++ info->size = 0x2000000;
++ info->address32 = 1;
++#endif
++ break;
++
++ case N25Q512:
++ info->sector_count = 256;
++ info->size = 0x1000000;
++ erase_region_size = 0x10000;
++ info->readcmd = 0x0b;
++ info->dualport = 0;
++ info->dummybyte = 1;
++ info->buffersize = 256;
++ info->specificspi = SpecificSPI_N25Q512;
++ WriteClk = 50;
++ EraseClk = 20;
++ ReadClk = 50;
++#if defined(CONFIG_FLASH_AST2300) || defined(CONFIG_AST1300)
++ info->sector_count = 1024;
++ info->size = 0x4000000;
++ info->address32 = 1;
++#endif
++ break;
++
++ case W25X16:
++ info->sector_count = 32;
++ info->size = 0x200000;
++ erase_region_size = 0x10000;
++ info->readcmd = 0x3b;
++ info->dualport = 1;
++ info->dummybyte = 1;
++ info->iomode = IOMODEx2;
++ info->buffersize = 256;
++ WriteClk = 50;
++ EraseClk = 25;
++ ReadClk = 50;
++ break;
++
++ case W25X64:
++ info->sector_count = 128;
++ info->size = 0x800000;
++ erase_region_size = 0x10000;
++ info->readcmd = 0x3b;
++ info->dualport = 1;
++ info->dummybyte = 1;
++ info->iomode = IOMODEx2;
++ info->buffersize = 256;
++ WriteClk = 50;
++ EraseClk = 25;
++ ReadClk = 50;
++ break;
++
++ case W25Q64BV:
++ info->sector_count = 128;
++ info->size = 0x800000;
++ erase_region_size = 0x10000;
++ info->readcmd = 0x3b;
++ info->dualport = 1;
++ info->dummybyte = 1;
++ info->iomode = IOMODEx2;
++ info->buffersize = 256;
++ WriteClk = 80;
++ EraseClk = 40;
++ ReadClk = 80;
++ break;
++
++ case W25Q128BV:
++ info->sector_count = 256;
++ info->size = 0x1000000;
++ erase_region_size = 0x10000;
++ info->readcmd = 0x3b;
++ info->dualport = 1;
++ info->dummybyte = 1;
++ info->iomode = IOMODEx2;
++ info->buffersize = 256;
++ WriteClk = 104;
++ EraseClk = 50;
++ ReadClk = 104;
++ break;
++
++ case W25Q256FV:
++ info->sector_count = 256;
++ info->size = 0x1000000;
++ erase_region_size = 0x10000;
++ info->readcmd = 0x0b;
++ info->dualport = 0;
++ info->dummybyte = 1;
++ info->buffersize = 256;
++ WriteClk = 50;
++ EraseClk = 20;
++ ReadClk = 50;
++#if defined(CONFIG_FLASH_AST2300) || defined(CONFIG_AST1300)
++ info->sector_count = 512;
++ info->size = 0x2000000;
++ info->address32 = 1;
++#endif
++ break;
++
++ case S25FL064A:
++ info->sector_count = 128;
++ info->size = 0x800000;
++ erase_region_size = 0x10000;
++ info->readcmd = 0x0b;
++ info->dualport = 0;
++ info->dummybyte = 1;
++ info->buffersize = 256;
++ WriteClk = 50;
++ EraseClk = 25;
++ ReadClk = 50;
++ break;
++
++ case S25FL128P:
++ info->sector_count = 256;
++ info->size = 0x1000000;
++ erase_region_size = 0x10000;
++ info->readcmd = 0x0b;
++ info->dualport = 0;
++ info->dummybyte = 1;
++ info->buffersize = 256;
++ WriteClk = 100;
++ EraseClk = 40;
++ ReadClk = 100;
++ break;
++
++ case S25FL256S:
++ info->sector_count = 256;
++ info->size = 0x1000000;
++ erase_region_size = 0x10000;
++ info->readcmd = 0x0b;
++ info->dualport = 0;
++ info->dummybyte = 1;
++ info->buffersize = 256;
++ WriteClk = 50;
++ EraseClk = 20;
++ ReadClk = 50;
++#if defined(CONFIG_FLASH_AST2300) || defined(CONFIG_AST1300)
++ info->sector_count = 512;
++ info->size = 0x2000000;
++ info->address32 = 1;
++#endif
++ break;
++
++ case MX25L25635E:
++ info->sector_count = 256;
++ info->size = 0x1000000;
++ erase_region_size = 0x10000;
++ info->readcmd = 0x0b;
++ info->dualport = 0;
++ info->dummybyte = 1;
++ info->buffersize = 256;
++ WriteClk = 50;
++ EraseClk = 20;
++ ReadClk = 50;
++#if defined(CONFIG_FLASH_AST2300) || defined(CONFIG_AST1300)
++ info->sector_count = 512;
++ info->size = 0x2000000;
++ info->address32 = 1;
++#if defined(CONFIG_FLASH_SPIx2_Dummy)
++ info->readcmd = 0xbb;
++ info->dummybyte = 1;
++ info->dualport = 1;
++ info->iomode = IOMODEx2_dummy;
++#elif defined(CONFIG_FLASH_SPIx4_Dummy)
++ info->readcmd = 0xeb;
++ info->dummybyte = 3;
++ info->dualport = 0;
++ info->iomode = IOMODEx4_dummy;
++ info->quadport = 1;
++ info->dummydata = 0xaa;
++#endif
++#endif
++ break;
++
++ case MX25L12805D:
++ info->sector_count = 256;
++ info->size = 0x1000000;
++ erase_region_size = 0x10000;
++ info->readcmd = 0x0b;
++ info->dualport = 0;
++ info->dummybyte = 1;
++ info->buffersize = 256;
++/*
++SCU7C: Silicon Revision ID Register
++D[31:24]: Chip ID
++0: AST2050/AST2100/AST2150/AST2200/AST3000
++1: AST2300
++
++D[23:16] Silicon revision ID for AST2300 generation and later
++0: A0
++1: A1
++2: A2
++.
++.
++.
++FPGA revision starts from 0x80
++
++AST2300 A0 SPI can't run faster than 50Mhz
++*/
++ WriteClk = 50;
++ EraseClk = 20;
++ ReadClk = 50;
++
++ SCURevision = *(ulong *) (SCU_REVISION_REGISTER);
++ if (((SCURevision >> 24) & 0xff) == 0x01) { //AST2300
++ if (((SCURevision >> 16) & 0xff) == 0x00) { //A0
++ WriteClk = 25;
++ EraseClk = 20;
++ ReadClk = 25;
++ }
++ }
++#if defined(CONFIG_FLASH_AST2300) || defined(CONFIG_AST1300)
++#if defined(CONFIG_FLASH_SPIx2_Dummy)
++ info->readcmd = 0xbb;
++ info->dummybyte = 1;
++ info->dualport = 1;
++ info->iomode = IOMODEx2_dummy;
++#elif defined(CONFIG_FLASH_SPIx4_Dummy)
++ info->readcmd = 0xeb;
++ info->dummybyte = 3;
++ info->dualport = 0;
++ info->iomode = IOMODEx4_dummy;
++ info->quadport = 1;
++ info->dummydata = 0xaa;
++#endif
++#endif
++ break;
++
++ case MX25L1605D:
++ info->sector_count = 32;
++ info->size = 0x200000;
++ erase_region_size = 0x10000;
++ info->readcmd = 0x0b;
++ info->dualport = 0;
++ info->dummybyte = 1;
++ info->buffersize = 256;
++ WriteClk = 50;
++ EraseClk = 20;
++ ReadClk = 50;
++ break;
++
++ case SST25VF016B:
++ info->sector_count = 32;
++ info->size = 0x200000;
++ erase_region_size = 0x10000;
++ info->readcmd = 0x0b;
++ info->dualport = 0;
++ info->dummybyte = 1;
++ info->buffersize = 1;
++ WriteClk = 50;
++ EraseClk = 25;
++ ReadClk = 50;
++ break;
++
++ case SST25VF064C:
++ info->sector_count = 128;
++ info->size = 0x800000;
++ erase_region_size = 0x10000;
++ info->readcmd = 0x0b;
++ info->dualport = 0;
++ info->dummybyte = 1;
++ info->buffersize = 1;
++ WriteClk = 50;
++ EraseClk = 25;
++ ReadClk = 50;
++ break;
++
++ case AT25DF161:
++ info->sector_count = 32;
++ info->size = 0x200000;
++ erase_region_size = 0x10000;
++ info->readcmd = 0x0b;
++ info->dualport = 0;
++ info->dummybyte = 1;
++ info->buffersize = 1;
++ WriteClk = 50;
++ EraseClk = 25;
++ ReadClk = 50;
++ break;
++
++ case AT25DF321:
++ info->sector_count = 32;
++ info->size = 0x400000;
++ erase_region_size = 0x10000;
++ info->readcmd = 0x0b;
++ info->dualport = 0;
++ info->dummybyte = 1;
++ info->buffersize = 1;
++ WriteClk = 50;
++ EraseClk = 25;
++ ReadClk = 50;
++ break;
++
++ default: /* use JEDEC ID */
++ erase_region_size = 0x10000;
++ info->readcmd = 0x0b;
++ info->dualport = 0;
++ info->dummybyte = 1;
++ info->buffersize = 1;
++ WriteClk = 50;
++ EraseClk = 25;
++ ReadClk = 50;
++ if ((info->flash_id & 0xFF) == 0x1F) /* Atmel */
++ {
++ switch (info->flash_id & 0x001F00)
++ {
++ case 0x000400:
++ info->sector_count = 8;
++ info->size = 0x80000;
++ break;
++ case 0x000500:
++ info->sector_count = 16;
++ info->size = 0x100000;
++ break;
++ case 0x000600:
++ info->sector_count = 32;
++ info->size = 0x200000;
++ break;
++ case 0x000700:
++ info->sector_count = 64;
++ info->size = 0x400000;
++ break;
++ case 0x000800:
++ info->sector_count = 128;
++ info->size = 0x800000;
++ break;
++ case 0x000900:
++ info->sector_count = 256;
++ info->size = 0x1000000;
++ break;
++ default:
++ printf("Can't support this SPI Flash!! \n");
++ return 0;
++ }
++ } /* Atmel JDEC */
++ else /* JDEC */
++ {
++ switch (info->flash_id & 0xFF0000)
++ {
++ case 0x120000:
++ info->sector_count = 4;
++ info->size = 0x40000;
++ break;
++ case 0x130000:
++ info->sector_count = 8;
++ info->size = 0x80000;
++ break;
++ case 0x140000:
++ info->sector_count =16;
++ info->size = 0x100000;
++ break;
++ case 0x150000:
++ info->sector_count =32;
++ info->size = 0x200000;
++ break;
++ case 0x160000:
++ info->sector_count =64;
++ info->size = 0x400000;
++ break;
++ case 0x170000:
++ info->sector_count =128;
++ info->size = 0x800000;
++ break;
++ case 0x180000:
++ info->sector_count =256;
++ info->size = 0x1000000;
++ break;
++ case 0x190000:
++ info->sector_count =256;
++ info->size = 0x1000000;
++#if defined(CONFIG_FLASH_AST2300) || defined(CONFIG_AST1300)
++ info->sector_count = 512;
++ info->size = 0x2000000;
++ info->address32 = 1;
++#if defined(CONFIG_FLASH_SPIx2_Dummy)
++ info->readcmd = 0xbb;
++ info->dummybyte = 1;
++ info->dualport = 1;
++ info->iomode = IOMODEx2_dummy;
++#elif defined(CONFIG_FLASH_SPIx4_Dummy)
++ info->readcmd = 0xeb;
++ info->dummybyte = 3;
++ info->dualport = 0;
++ info->iomode = IOMODEx4_dummy;
++ info->quadport = 1;
++ info->dummydata = 0xaa;
++#endif
++#endif
++ break;
++
++ case 0x200000:
++ info->sector_count =256;
++ info->size = 0x1000000;
++ if ((info->flash_id & 0xFF) == 0x20) /* numonyx */
++ info->specificspi = SpecificSPI_N25Q512;
++#if defined(CONFIG_FLASH_AST2300) || defined(CONFIG_AST1300)
++ info->sector_count = 1024;
++ info->size = 0x4000000;
++ info->address32 = 1;
++#if defined(CONFIG_FLASH_SPIx2_Dummy)
++ info->readcmd = 0xbb;
++ info->dummybyte = 1;
++ info->dualport = 1;
++ info->iomode = IOMODEx2_dummy;
++#elif defined(CONFIG_FLASH_SPIx4_Dummy)
++ info->readcmd = 0xeb;
++ info->dummybyte = 3;
++ info->dualport = 0;
++ info->iomode = IOMODEx4_dummy;
++ info->quadport = 1;
++ info->dummydata = 0xaa;
++#endif
++#endif
++ break;
++
++ default:
++ printf("Can't support this SPI Flash!! \n");
++ return 0;
++ }
++ } /* JDEC */
++ }
++
++ debug ("erase_region_count = %d erase_region_size = %d\n",
++ erase_region_count, erase_region_size);
++
++ sector = base;
++ for (j = 0; j < info->sector_count; j++) {
++
++ info->start[j] = sector;
++ sector += erase_region_size;
++ info->protect[j] = 0; /* default: not protected */
++ }
++
++ /* set SPI flash extended info */
++#if defined(CONFIG_AST1300)
++ if (info->size > 0x200000) /* limit MAX Flash to 2MB for AST1300 */
++ info->size = 0x200000;
++#endif
++#if defined(CONFIG_AST2400) || defined(CONFIG_AST2300) || defined(CONFIG_AST2300_FPGA_1) || defined(CONFIG_AST2300_FPGA_2) || defined(CONFIG_AST1300)
++ reg = *((volatile ulong*) 0x1e6e2024);
++ if (reg & 0x40000)
++ {
++ reg = *((volatile ulong*) 0x1e6e2070);
++
++ ulRefPLL = 24;
++ ulDeNumerator = reg & 0x0F;
++ ulNumerator = (reg & 0x07E0) >> 5;
++ ulOD = (reg & 0x10) ? 1:2;
++
++ cpuclk = ulRefPLL * ulOD * (ulNumerator + 2) / (ulDeNumerator + 1);
++ }
++ else
++ {
++ reg = *((volatile ulong*) 0x1e6e2070);
++#if defined(CONFIG_AST2400)
++ if (reg & 0x00800000) //ref. clk:25MHz
++ {
++ switch (reg & 0x300)
++ {
++ case 0x000:
++ cpuclk = 400;
++ break;
++ case 0x100:
++ cpuclk = 375;
++ break;
++ case 0x200:
++ cpuclk = 350;
++ break;
++ case 0x300:
++ cpuclk = 325;
++ break;
++ }
++ }
++ else
++ {
++ switch (reg & 0x300) //ref. clk:24MHz
++ {
++ case 0x000:
++ cpuclk = 384;
++ break;
++ case 0x100:
++ cpuclk = 360;
++ break;
++ case 0x200:
++ cpuclk = 336;
++ break;
++ case 0x300:
++ cpuclk = 312;
++ break;
++ }
++ }
++#else
++ switch (reg & 0x300)
++ {
++ case 0x000:
++ cpuclk = 384;
++ break;
++ case 0x100:
++ cpuclk = 360;
++ break;
++ case 0x200:
++ cpuclk = 336;
++ break;
++ case 0x300:
++ cpuclk = 408;
++ break;
++ }
++#endif
++ }
++
++ reg = *((volatile ulong*) 0x1e6e2070);
++ switch (reg & 0xc00)
++ {
++ case 0x000:
++ cpuclk /= 1;
++ break;
++ case 0x400:
++ cpuclk /= 2;
++ break;
++ case 0x800:
++ cpuclk /= 4;
++ break;
++ case 0xC00:
++ cpuclk /= 3;
++ break;
++ }
++#else /* AST2100 */
++ reg = *((volatile ulong*) 0x1e6e2070);
++ switch (reg & 0xe00)
++ {
++ case 0x000:
++ cpuclk = 266;
++ break;
++ case 0x200:
++ cpuclk = 233;
++ break;
++ case 0x400:
++ cpuclk = 200;
++ break;
++ case 0x600:
++ cpuclk = 166;
++ break;
++ case 0x800:
++ cpuclk = 133;
++ break;
++ case 0xA00:
++ cpuclk = 100;
++ break;
++ case 0xC00:
++ cpuclk = 300;
++ break;
++ case 0xE00:
++ cpuclk = 24;
++ break;
++ }
++ switch (reg & 0x3000)
++ {
++ case 0x1000:
++ cpuclk /= 2;
++ break;
++ case 0x2000:
++ cpuclk /= 4;
++ break;
++ case 0x3000:
++ cpuclk /= 3;
++ break;
++ }
++#endif
++
++#if defined(CONFIG_AST2400) || defined(CONFIG_AST2300) || defined(CONFIG_AST2300_FPGA_1) || defined(CONFIG_AST2300_FPGA_2) || defined(CONFIG_AST1300)
++
++#if defined(CONFIG_AST2300) || defined(CONFIG_AST1300)
++ /* limit Max SPI CLK to 50MHz (Datasheet v1.2) */
++ if (WriteClk > 50) WriteClk = 50;
++ if (EraseClk > 50) EraseClk = 50;
++ if (ReadClk > 50) ReadClk = 50;
++#endif
++
++ div = 1;
++ while ( ((cpuclk/div) > WriteClk) && (div < 16) )
++ {
++ div++;
++ }
++ info->tCK_Write = AST2300_SPICLK_DIV[div-1];
++
++ div = 1;
++ while ( ((cpuclk/div) > EraseClk) && (div < 16) )
++ {
++ div++;
++ }
++ info->tCK_Erase = AST2300_SPICLK_DIV[div-1];
++
++ div = 1;
++ while ( ((cpuclk/div) > ReadClk) && (div < 16) )
++ {
++ div++;
++ }
++ info->tCK_Read = AST2300_SPICLK_DIV[div-1];
++#else
++ div = 2;
++ info->tCK_Write = 7;
++ while ( (cpuclk/div) > WriteClk )
++ {
++ info->tCK_Write--;
++ div +=2;
++ }
++ div = 2;
++ info->tCK_Erase = 7;
++ while ( (cpuclk/div) > EraseClk )
++ {
++ info->tCK_Erase--;
++ div +=2;
++ }
++ div = 2;
++ info->tCK_Read = 7;
++ while ( (cpuclk/div) > ReadClk )
++ {
++ info->tCK_Read--;
++ div +=2;
++ }
++#endif
++
++ /* unprotect flash */
++ write_status_register(info, 0);
++
++ if (info->quadport)
++ write_status_register(info, 0x40); /* enable QE */
++
++ if (info->address32)
++ {
++ reg = *((volatile ulong*) 0x1e6e2070); /* set H/W Trappings */
++ reg |= 0x10;
++ *((volatile ulong*) 0x1e6e2070) = reg;
++
++ reg = *((volatile ulong*) 0x1e620004); /* enable 32b control bit*/
++ reg |= (0x01 << info->CE);
++ *((volatile ulong*) 0x1e620004) = reg;
++
++ /* set flash chips to 32bits addressing mode */
++ if ((info->flash_id & 0xFF) == 0x01) /* Spansion */
++ enable4b_spansion(info);
++ else if ((info->flash_id & 0xFF) == 0x20) /* Numonyx */
++ enable4b_numonyx(info);
++ else /* MXIC, Winbond */
++ enable4b(info);
++
++ }
++
++ reset_flash(info);
++
++ return (info->size);
++}
++
++
++/*-----------------------------------------------------------------------
++ */
++static int flash_write_buffer (flash_info_t *info, uchar *src, ulong addr, int len)
++{
++ ulong j, base, offset;
++ ulong ulSMMBase, ulCtrlData, CtrlOffset;
++ uchar jReg;
++
++ if (info->CE == 2)
++ {
++ CtrlOffset = SPICtrlRegOffset2;
++ }
++ else
++ {
++ CtrlOffset = SPICtrlRegOffset;
++ }
++
++ base = info->start[0];
++ offset = addr - base;
++ base = flash_make_addr (info, 0, 0);
++
++ enable_write (info);
++
++ ulCtrlData = (info->tCK_Write << 8);
++
++ ulCtrlData &= CMD_MASK;
++ ulCtrlData |= CE_LOW | USERMODE;
++ *(ulong *) (STCBaseAddress + CtrlOffset) = ulCtrlData;
++ udelay(200);
++ *(uchar *) (base) = (uchar) (0x02);
++ udelay(10);
++ if (info->address32)
++ {
++ *(uchar *) (base) = (uchar) ((offset & 0xff000000) >> 24);
++ udelay(10);
++ }
++ *(uchar *) (base) = (uchar) ((offset & 0xff0000) >> 16);
++ udelay(10);
++ *(uchar *) (base) = (uchar) ((offset & 0x00ff00) >> 8);
++ udelay(10);
++ *(uchar *) (base) = (uchar) ((offset & 0x0000ff));
++ udelay(10);
++
++ for (j=0; j<len; j++)
++ {
++ *(uchar *) (base) = *(uchar *) (src++);
++ udelay(10);
++ }
++
++ ulCtrlData &= CMD_MASK;
++ ulCtrlData |= CE_HIGH | USERMODE;
++ *(ulong *) (STCBaseAddress + CtrlOffset) = ulCtrlData;
++ udelay(200);
++
++ ulCtrlData &= CMD_MASK;
++ ulCtrlData |= CE_LOW | USERMODE;
++ *(ulong *) (STCBaseAddress + CtrlOffset) = ulCtrlData;
++ udelay(200);
++ *(uchar *) (base) = (uchar) (0x05);
++ udelay(10);
++ do {
++ jReg = *(volatile uchar *) (base);
++ } while ((jReg & 0x01));
++ ulCtrlData &= CMD_MASK;
++ ulCtrlData |= CE_HIGH | USERMODE;
++ *(ulong *) (STCBaseAddress + CtrlOffset) = ulCtrlData;
++ udelay(200);
++
++ /* RFSR */
++ if (info->specificspi == SpecificSPI_N25Q512)
++ {
++ ulCtrlData &= CMD_MASK;
++ ulCtrlData |= CE_LOW | USERMODE;
++ *(ulong *) (STCBaseAddress + CtrlOffset) = ulCtrlData;
++ udelay(200);
++ *(uchar *) (base) = (uchar) (0x70);
++ udelay(10);
++ do {
++ jReg = *(volatile uchar *) (base);
++ } while (!(jReg & 0x80));
++ ulCtrlData &= CMD_MASK;
++ ulCtrlData |= CE_HIGH | USERMODE;
++ *(ulong *) (STCBaseAddress + CtrlOffset) = ulCtrlData;
++ udelay(200);
++ }
++}
++
++/*-----------------------------------------------------------------------
++ *
++ * export functions
++ *
++ */
++
++/*-----------------------------------------------------------------------
++ *
++ */
++unsigned long flash_init (void)
++{
++ unsigned long size = 0;
++ int i;
++
++ /* Init: no FLASHes known */
++ for (i = 0; i < CONFIG_SYS_MAX_FLASH_BANKS; ++i) {
++ flash_info[i].flash_id = FLASH_UNKNOWN;
++ size += flash_info[i].size = flash_get_size (bank_base[i], i);
++ if (flash_info[i].flash_id == FLASH_UNKNOWN) {
++#ifndef CFG_FLASH_QUIET_TEST
++ printf ("## Unknown FLASH on Bank %d - Size = 0x%08lx = %ld MB\n",
++ i, flash_info[i].size, flash_info[i].size << 20);
++#endif /* CFG_FLASH_QUIET_TEST */
++ }
++ }
++
++ /* Monitor protection ON by default */
++#if (CONFIG_MONITOR_BASE >= CONFIG_SYS_FLASH_BASE)
++ flash_protect (FLAG_PROTECT_SET,
++ CONFIG_MONITOR_BASE,
++ CONFIG_MONITOR_BASE + monitor_flash_len - 1,
++ flash_get_info(CONFIG_MONITOR_BASE));
++#endif
++
++ /* Environment protection ON by default */
++#ifdef CONFIG_ENV_IS_IN_FLASH
++ flash_protect (FLAG_PROTECT_SET,
++ CONFIG_ENV_ADDR,
++ CONFIG_ENV_ADDR + CONFIG_ENV_SECT_SIZE - 1,
++ flash_get_info(CONFIG_ENV_ADDR));
++#endif
++
++ /* Redundant environment protection ON by default */
++#ifdef CONFIG_ENV_ADDR_REDUND
++ flash_protect (FLAG_PROTECT_SET,
++ CONFIG_ENV_ADDR_REDUND,
++ CONFIG_ENV_ADDR_REDUND + CONFIG_ENV_SIZE_REDUND - 1,
++ flash_get_info(CONFIG_ENV_ADDR_REDUND));
++#endif
++ return (size);
++}
++
++/*-----------------------------------------------------------------------
++ */
++#if defined(CONFIG_ENV_IS_IN_FLASH) || defined(CONFIG_ENV_ADDR_REDUND) || (CONFIG_MONITOR_BASE >= CONFIG_SYS_FLASH_BASE)
++static flash_info_t *flash_get_info(ulong base)
++{
++ int i;
++ flash_info_t * info = 0;
++
++ for (i = 0; i < CONFIG_SYS_MAX_FLASH_BANKS; i ++) {
++ info = & flash_info[i];
++ if (info->size && info->start[0] <= base &&
++ base <= info->start[0] + info->size - 1)
++ break;
++ }
++
++ return i == CONFIG_SYS_MAX_FLASH_BANKS ? 0 : info;
++}
++#endif
++
++/*-----------------------------------------------------------------------
++ */
++int flash_erase (flash_info_t * info, int s_first, int s_last)
++{
++ int rcode = 0;
++ int prot;
++ flash_sect_t sect;
++
++ ulong base, offset;
++ ulong ulSMMBase, ulCtrlData, CtrlOffset;
++ uchar jReg;
++
++ disable_cache();
++
++ if (info->CE == 2)
++ {
++ CtrlOffset = SPICtrlRegOffset2;
++ }
++ else
++ {
++ CtrlOffset = SPICtrlRegOffset;
++ }
++
++ if ((s_first < 0) || (s_first > s_last)) {
++ puts ("- no sectors to erase\n");
++ return 1;
++ }
++
++ prot = 0;
++ for (sect = s_first; sect <= s_last; ++sect) {
++ if (info->protect[sect]) {
++ prot++;
++ }
++ }
++ if (prot) {
++ printf ("- Warning: %d protected sectors will not be erased!\n", prot);
++ } else {
++ putc ('\n');
++ }
++
++ ulCtrlData = (info->tCK_Erase << 8);
++ for (sect = s_first; sect <= s_last; sect++) {
++ if (info->protect[sect] == 0) { /* not protected */
++ /* start erasing */
++ enable_write(info);
++
++ base = info->start[0];
++ offset = info->start[sect] - base;
++ base = flash_make_addr (info, 0, 0);
++
++ ulCtrlData &= CMD_MASK;
++ ulCtrlData |= CE_LOW | USERMODE;
++ *(ulong *) (STCBaseAddress + CtrlOffset) = ulCtrlData;
++ udelay(200);
++ *(uchar *) (base) = (uchar) (0xd8);
++ udelay(10);
++ if (info->address32)
++ {
++ *(uchar *) (base) = (uchar) ((offset & 0xff000000) >> 24);
++ udelay(10);
++ }
++ *(uchar *) (base) = (uchar) ((offset & 0xff0000) >> 16);
++ udelay(10);
++ *(uchar *) (base) = (uchar) ((offset & 0x00ff00) >> 8);
++ udelay(10);
++ *(uchar *) (base) = (uchar) ((offset & 0x0000ff));
++ udelay(10);
++
++ ulCtrlData &= CMD_MASK;
++ ulCtrlData |= CE_HIGH | USERMODE;
++ *(ulong *) (STCBaseAddress + CtrlOffset) = ulCtrlData;
++ udelay(200);
++
++ ulCtrlData &= CMD_MASK;
++ ulCtrlData |= CE_LOW | USERMODE;
++ *(ulong *) (STCBaseAddress + CtrlOffset) = ulCtrlData;
++ udelay(200);
++ *(uchar *) (base) = (uchar) (0x05);
++ udelay(10);
++ do {
++ jReg = *(volatile uchar *) (base);
++ } while ((jReg & 0x01));
++ ulCtrlData &= CMD_MASK;
++ ulCtrlData |= CE_HIGH | USERMODE;
++ *(ulong *) (STCBaseAddress + CtrlOffset) = ulCtrlData;
++ udelay(200);
++
++ /* RFSR */
++ if (info->specificspi == SpecificSPI_N25Q512)
++ {
++ ulCtrlData &= CMD_MASK;
++ ulCtrlData |= CE_LOW | USERMODE;
++ *(ulong *) (STCBaseAddress + CtrlOffset) = ulCtrlData;
++ udelay(200);
++ *(uchar *) (base) = (uchar) (0x70);
++ udelay(10);
++ do {
++ jReg = *(volatile uchar *) (base);
++ } while (!(jReg & 0x80));
++ ulCtrlData &= CMD_MASK;
++ ulCtrlData |= CE_HIGH | USERMODE;
++ *(ulong *) (STCBaseAddress + CtrlOffset) = ulCtrlData;
++ udelay(200);
++ }
++
++ putc ('.');
++ }
++ }
++ puts (" done\n");
++
++ reset_flash(info);
++
++ return rcode;
++}
++
++/*-----------------------------------------------------------------------
++ */
++void flash_print_info (flash_info_t * info)
++{
++ putc ('\n');
++ return;
++}
++
++/*-----------------------------------------------------------------------
++ * Copy memory to flash, returns:
++ * 0 - OK
++ * 1 - write timeout
++ * 2 - Flash not erased
++ */
++int write_buff (flash_info_t * info, uchar * src, ulong addr, ulong cnt)
++{
++ int count;
++ unsigned char pat[] = {'|', '-', '/', '\\'};
++ int patcnt;
++
++ disable_cache();
++
++ /* get lower aligned address */
++ if (addr & (info->buffersize - 1))
++ {
++ count = cnt >= info->buffersize ? (info->buffersize - (addr & 0xff)):cnt;
++ flash_write_buffer (info, src, addr, count);
++ addr+= count;
++ src += count;
++ cnt -= count;
++ }
++
++ /* prog */
++ while (cnt > 0) {
++ count = cnt >= info->buffersize ? info->buffersize:cnt;
++ flash_write_buffer (info, src, addr, count);
++ addr+= count;
++ src += count;
++ cnt -= count;
++ printf("%c\b", pat[(patcnt++) & 0x03]);
++ }
++
++ reset_flash(info);
++
++ return (0);
++}
++
++#ifdef CONFIG_FLASH_AST2300_DMA
++void * memmove_dma(void * dest,const void *src,size_t count)
++{
++ ulong count_align, poll_time, data;
++
++ count_align = (count + 3) & 0xFFFFFFFC; /* 4-bytes align */
++ poll_time = 100; /* set 100 us as default */
++
++ /* force end of burst read */
++ *(volatile ulong *) (STCBaseAddress + SPICtrlRegOffset) |= CE_HIGH;
++ *(volatile ulong *) (STCBaseAddress + SPICtrlRegOffset) &= ~CE_HIGH;
++
++ *(ulong *) (STCBaseAddress + REG_FLASH_DMA_CONTROL) = (ulong) (~FLASH_DMA_ENABLE);
++ *(ulong *) (STCBaseAddress + REG_FLASH_DMA_FLASH_BASE) = (ulong *) (src);
++ *(ulong *) (STCBaseAddress + REG_FLASH_DMA_DRAM_BASE) = (ulong *) (dest);
++ *(ulong *) (STCBaseAddress + REG_FLASH_DMA_LENGTH) = (ulong) (count_align);
++ *(ulong *) (STCBaseAddress + REG_FLASH_DMA_CONTROL) = (ulong) (FLASH_DMA_ENABLE);
++
++ /* wait poll */
++ do {
++ udelay(poll_time);
++ data = *(ulong *) (STCBaseAddress + REG_FLASH_INTERRUPT_STATUS);
++ } while (!(data & FLASH_STATUS_DMA_READY));
++
++ /* clear status */
++ *(ulong *) (STCBaseAddress + REG_FLASH_INTERRUPT_STATUS) |= FLASH_STATUS_DMA_CLEAR;
++}
++#endif
++#endif /* CONFIG_FLASH_SPI */
+diff --git a/board/aspeed/ast2400/hactest.c b/board/aspeed/ast2400/hactest.c
+new file mode 100755
+index 0000000..bfa87d5
+--- /dev/null
++++ b/board/aspeed/ast2400/hactest.c
+@@ -0,0 +1,762 @@
++/*
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
++ * MA 02111-1307 USA
++ */
++
++/*
++ * Diagnostics support
++ */
++#include <common.h>
++#include <command.h>
++#include <post.h>
++#include "slt.h"
++
++#if ((CFG_CMD_SLT & CFG_CMD_HACTEST) && defined(CONFIG_SLT))
++#include "hactest.h"
++
++#include "aes.c"
++#include "rc4.c"
++
++static unsigned char crypto_src[CRYPTO_MAX_SRC], crypto_dst[CRYPTO_MAX_DST], crypto_context[CRYPTO_MAX_CONTEXT];
++static unsigned char hash_src[HASH_MAX_SRC], hash_dst[HASH_MAX_DST], hmac_key[HMAC_MAX_KEY];
++
++/*
++ * table
++ */
++static aes_test aestest[] = {
++ { CRYPTOMODE_ECB, 128,
++ {0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6, 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c, '\0'},
++ {0x32, 0x43, 0xf6, 0xa8, 0x88, 0x5a, 0x30, 0x8d, 0x31, 0x31, 0x98, 0xa2, 0xe0, 0x37, 0x07, 0x34, '\0'},
++ {0x39, 0x25, 0x84, 0x1d, 0x02, 0xdc, 0x09, 0xfb, 0xdc, 0x11, 0x85, 0x97, 0x19, 0x6a, 0x0b, 0x32, '\0'} },
++ {0xFF, 0xFF, "", "", ""}, /* End Mark */
++};
++
++static rc4_test rc4test[] = {
++ {{0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, '\0'},
++ {0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, '\0'}},
++ {{0xff}, {0xff}}, /* End Mark */
++};
++
++static hash_test hashtest[] = {
++ {HASHMODE_SHA1, 20,
++ "abc",
++ {0x53, 0x20, 0xb0, 0x8c, 0xa1, 0xf5, 0x74, 0x62, 0x50, 0x71, 0x89, 0x41, 0xc5, 0x0a, 0xdf, 0x4e, 0xbb, 0x55, 0x76, 0x06, '\0'}},
++ {0xFF, 0xFF, "", ""}, /* End Mark */
++};
++
++static hmac_test hmactest[] = {
++ {HASHMODE_SHA1, 64, 20,
++ {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16,0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, '\0' },
++ "Sample #1",
++ {0xbf, 0x39, 0xda, 0xb1, 0x7d, 0xc2, 0xe1, 0x23, 0x0d, 0x28, 0x35, 0x3b, 0x8c, 0xcb, 0x14, 0xb6, 0x22, 0x02, 0x65, 0xb3, '\0'}},
++ {0xFF, 0xFF, 0xFF, "", "", ""}, /* End Mark */
++};
++
++void EnableHMAC(void)
++{
++ unsigned long ulData;
++
++ /* init SCU */
++ *(unsigned long *) (0x1e6e2000) = 0x1688a8a8;
++
++ ulData = *(volatile unsigned long *) (0x1e6e200c);
++ ulData &= 0xfdfff;
++ *(unsigned long *) (0x1e6e200c) = ulData;
++ udelay(100);
++ ulData = *(volatile unsigned long *) (0x1e6e2004);
++ ulData &= 0xfffef;
++ *(unsigned long *) (0x1e6e2004) = ulData;
++
++}
++
++/* AES */
++void aes_enc_ast3000(aes_context *ctx, uint8 *input, uint8 *iv, uint8 *output, uint32 ulMsgLength , uint32 ulAESMode)
++{
++
++ unsigned long i, ulTemp, ulCommand;
++ unsigned char ch;
++ unsigned char *pjsrc, *pjdst, *pjcontext;
++
++ ulCommand = CRYPTO_ENABLE_RW | CRYPTO_ENABLE_CONTEXT_LOAD | CRYPTO_ENABLE_CONTEXT_SAVE | \
++ CRYPTO_AES | CRYPTO_ENCRYPTO | CRYPTO_SYNC_MODE_ASYNC;
++
++ switch (ctx->nr)
++ {
++ case 10:
++ ulCommand |= CRYPTO_AES128;
++ break;
++ case 12:
++ ulCommand |= CRYPTO_AES192;
++ break;
++ case 14:
++ ulCommand |= CRYPTO_AES256;
++ break;
++ }
++
++ switch (ulAESMode)
++ {
++ case CRYPTOMODE_ECB:
++ ulCommand |= CRYPTO_AES_ECB;
++ break;
++ case CRYPTOMODE_CBC:
++ ulCommand |= CRYPTO_AES_CBC;
++ break;
++ case CRYPTOMODE_CFB:
++ ulCommand |= CRYPTO_AES_CFB;
++ break;
++ case CRYPTOMODE_OFB:
++ ulCommand |= CRYPTO_AES_OFB;
++ break;
++ case CRYPTOMODE_CTR:
++ ulCommand |= CRYPTO_AES_CTR;
++ break;
++ }
++
++ pjsrc = (unsigned char *) m16byteAlignment((unsigned long) crypto_src);
++ pjdst = (unsigned char *) m16byteAlignment((unsigned long) crypto_dst);
++ pjcontext = (unsigned char *) m16byteAlignment((unsigned long) crypto_context);
++
++ /* Init HW */
++ *(unsigned long *) (HAC_REG_BASE + REG_CRYPTO_SRC_BASE_OFFSET) = (unsigned long) pjsrc;
++ *(unsigned long *) (HAC_REG_BASE + REG_CRYPTO_DST_BASE_OFFSET) = (unsigned long) pjdst;
++ *(unsigned long *) (HAC_REG_BASE + REG_CRYPTO_CONTEXT_BASE_OFFSET) = (unsigned long) pjcontext;
++ *(unsigned long *) (HAC_REG_BASE + REG_CRYPTO_LEN_OFFSET) = ulMsgLength;
++
++ /* Set source */
++ for (i=0; i< ulMsgLength; i++)
++ {
++ ch = *(uint8 *)(input + i);
++ *(uint8 *) (pjsrc + i) = ch;
++ }
++
++ /* Set Context */
++ /* Set IV */
++ for (i=0; i<16; i++)
++ {
++ ch = *(uint8 *) (iv + i);
++ *(uint8 *) (pjcontext + i) = ch;
++ }
++
++ /* Set Expansion Key */
++ for (i=0; i<(4*(ctx->nr+1)); i++)
++ {
++ ulTemp = ((ctx->erk[i] & 0xFF) << 24) + ((ctx->erk[i] & 0xFF00) << 8) + ((ctx->erk[i] & 0xFF0000) >> 8) + ((ctx->erk[i] & 0xFF000000) >> 24);
++ *(uint32 *) (pjcontext + i*4 + 16) = ulTemp;
++ }
++
++ /* fire cmd */
++ *(unsigned long *) (HAC_REG_BASE + REG_CRYPTO_CMD_BASE_OFFSET) = ulCommand;
++ do {
++ ulTemp = *(volatile unsigned long *) (HAC_REG_BASE + REG_CRYPTO_STATUS_OFFSET);
++ } while (ulTemp & CRYPTO_BUSY);
++
++ /* Output */
++ for (i=0; i<ulMsgLength; i++)
++ {
++ ch = *(uint8 *) (pjdst + i);
++ *(uint8 *) (output + i) = ch;
++ }
++
++} /* aes_enc_ast3000 */
++
++
++void aes_dec_ast3000(aes_context *ctx, uint8 *input, uint8 *iv, uint8 *output, uint32 ulMsgLength , uint32 ulAESMode)
++{
++ unsigned long i, ulTemp, ulCommand;
++ unsigned char ch;
++ unsigned char *pjsrc, *pjdst, *pjcontext;
++
++ ulCommand = CRYPTO_ENABLE_RW | CRYPTO_ENABLE_CONTEXT_LOAD | CRYPTO_ENABLE_CONTEXT_SAVE | \
++ CRYPTO_AES | CRYPTO_DECRYPTO | CRYPTO_SYNC_MODE_ASYNC;
++
++ switch (ctx->nr)
++ {
++ case 10:
++ ulCommand |= CRYPTO_AES128;
++ break;
++ case 12:
++ ulCommand |= CRYPTO_AES192;
++ break;
++ case 14:
++ ulCommand |= CRYPTO_AES256;
++ break;
++ }
++
++ switch (ulAESMode)
++ {
++ case CRYPTOMODE_ECB:
++ ulCommand |= CRYPTO_AES_ECB;
++ break;
++ case CRYPTOMODE_CBC:
++ ulCommand |= CRYPTO_AES_CBC;
++ break;
++ case CRYPTOMODE_CFB:
++ ulCommand |= CRYPTO_AES_CFB;
++ break;
++ case CRYPTOMODE_OFB:
++ ulCommand |= CRYPTO_AES_OFB;
++ break;
++ case CRYPTOMODE_CTR:
++ ulCommand |= CRYPTO_AES_CTR;
++ break;
++ }
++
++ pjsrc = (unsigned char *) m16byteAlignment((unsigned long) crypto_src);
++ pjdst = (unsigned char *) m16byteAlignment((unsigned long) crypto_dst);
++ pjcontext = (unsigned char *) m16byteAlignment((unsigned long) crypto_context);
++
++ /* Init HW */
++ *(unsigned long *) (HAC_REG_BASE + REG_CRYPTO_SRC_BASE_OFFSET) = (unsigned long) pjsrc;
++ *(unsigned long *) (HAC_REG_BASE + REG_CRYPTO_DST_BASE_OFFSET) = (unsigned long) pjdst;
++ *(unsigned long *) (HAC_REG_BASE + REG_CRYPTO_CONTEXT_BASE_OFFSET) = (unsigned long) pjcontext;
++ *(unsigned long *) (HAC_REG_BASE + REG_CRYPTO_LEN_OFFSET) = ulMsgLength;
++
++ /* Set source */
++ for (i=0; i< ulMsgLength; i++)
++ {
++ ch = *(uint8 *)(input + i);
++ *(uint8 *) (pjsrc + i) = ch;
++ }
++
++ /* Set Context */
++ /* Set IV */
++ for (i=0; i<16; i++)
++ {
++ ch = *(uint8 *) (iv + i);
++ *(uint8 *) (pjcontext + i) = ch;
++ }
++
++ /* Set Expansion Key */
++ for (i=0; i<(4*(ctx->nr+1)); i++)
++ {
++ ulTemp = ((ctx->erk[i] & 0xFF) << 24) + ((ctx->erk[i] & 0xFF00) << 8) + ((ctx->erk[i] & 0xFF0000) >> 8) + ((ctx->erk[i] & 0xFF000000) >> 24);
++ *(uint32 *) (pjcontext + i*4 + 16) = ulTemp;
++ }
++
++ /* fire cmd */
++ *(unsigned long *) (HAC_REG_BASE + REG_CRYPTO_CMD_BASE_OFFSET) = ulCommand;
++ do {
++ ulTemp = *(volatile unsigned long *) (HAC_REG_BASE + REG_CRYPTO_STATUS_OFFSET);
++ } while (ulTemp & CRYPTO_BUSY);
++
++ /* Output */
++ for (i=0; i<ulMsgLength; i++)
++ {
++ ch = *(uint8 *) (pjdst + i);
++ *(uint8 *) (output + i) = ch;
++ }
++
++} /* aes_dec_ast3000 */
++
++void rc4_crypt_ast3000(uint8 *data, int ulMsgLength, uint8 *rc4_key, uint32 ulKeyLength)
++{
++ struct rc4_state s;
++ unsigned long i, ulTemp, ulCommand;
++ unsigned char ch;
++ unsigned char *pjsrc, *pjdst, *pjcontext;
++
++ ulCommand = CRYPTO_ENABLE_RW | CRYPTO_ENABLE_CONTEXT_LOAD | CRYPTO_ENABLE_CONTEXT_SAVE | \
++ CRYPTO_RC4 | CRYPTO_SYNC_MODE_ASYNC;
++
++ rc4_setup( &s, rc4_key, ulKeyLength );
++
++ pjsrc = (unsigned char *) m16byteAlignment((unsigned long) crypto_src);
++ pjdst = (unsigned char *) m16byteAlignment((unsigned long) crypto_dst);
++ pjcontext = (unsigned char *) m16byteAlignment((unsigned long) crypto_context);
++
++ /* Init HW */
++ *(uint32 *) (HAC_REG_BASE + REG_CRYPTO_SRC_BASE_OFFSET) = (unsigned long) pjsrc;
++ *(uint32 *) (HAC_REG_BASE + REG_CRYPTO_DST_BASE_OFFSET) = (unsigned long) pjdst;
++ *(uint32 *) (HAC_REG_BASE + REG_CRYPTO_CONTEXT_BASE_OFFSET) = (unsigned long) pjcontext;
++ *(uint32 *) (HAC_REG_BASE + REG_CRYPTO_LEN_OFFSET) = ulMsgLength;
++
++
++ /* Set source */
++ for (i=0; i< ulMsgLength; i++)
++ {
++ ch = *(uint8 *)(data + i);
++ *(uint8 *) (pjsrc + i) = ch;
++ }
++
++ /* Set Context */
++ /* Set i, j */
++ *(uint32 *) (pjcontext + 8) = 0x0001;
++
++ /* Set Expansion Key */
++ for (i=0; i<(256/4); i++)
++ {
++ ulTemp = (s.m[i * 4] & 0xFF) + ((s.m[i * 4 + 1] & 0xFF) << 8) + ((s.m[i * 4 + 2] & 0xFF) << 16) + ((s.m[i * 4+ 3] & 0xFF) << 24);
++ *(uint32 *) (pjcontext + i*4 + 16) = ulTemp;
++ }
++
++ /* fire cmd */
++ *(uint32 *) (HAC_REG_BASE + REG_CRYPTO_CMD_BASE_OFFSET) = ulCommand;
++ do {
++ ulTemp = *(volatile uint32 *) (HAC_REG_BASE + REG_CRYPTO_STATUS_OFFSET);
++ } while (ulTemp & CRYPTO_BUSY);
++
++ /* Output */
++ for (i=0; i<ulMsgLength; i++)
++ {
++ ch = *(volatile uint8 *) (pjdst + i);
++ *(uint8 *) (data + i) = ch;
++ }
++
++} /* rc4_crypt_ast3000 */
++
++/* Hash */
++void hash_ast3000(uint8 *msg, uint32 ulLength, unsigned char *output, uint32 ulHashMode)
++{
++ uint32 i, ulTemp, ulCommand, ulDigestLength, ulMyMsgLength;
++ uint8 ch;
++ unsigned char *pjsrc, *pjdst;
++
++ /* Get Info */
++ switch (ulHashMode)
++ {
++ case HASHMODE_MD5:
++ ulCommand = HASH_ALG_SELECT_MD5;
++ ulDigestLength = 16;
++ break;
++ case HASHMODE_SHA1:
++ ulCommand = HASH_ALG_SELECT_SHA1 | 0x08;
++ ulDigestLength = 20;
++ break;
++ case HASHMODE_SHA256:
++ ulCommand = HASH_ALG_SELECT_SHA256 | 0x08;
++ ulDigestLength = 32;
++ break;
++ case HASHMODE_SHA224:
++ ulCommand = HASH_ALG_SELECT_SHA224 | 0x08;
++ ulDigestLength = 28;
++ break;
++ }
++
++ pjsrc = (unsigned char *) m16byteAlignment((unsigned long) hash_src);
++ pjdst = (unsigned char *) m16byteAlignment((unsigned long) hash_dst);
++
++ /* 16byte alignment */
++ ulMyMsgLength = m16byteAlignment(ulLength);
++
++ /* Init. HW */
++ *(uint32 *) (HAC_REG_BASE + REG_HASH_SRC_BASE_OFFSET) = (unsigned long) pjsrc;
++ *(uint32 *) (HAC_REG_BASE + REG_HASH_DST_BASE_OFFSET) = (unsigned long) pjdst;
++ *(uint32 *) (HAC_REG_BASE + REG_HASH_LEN_OFFSET) = ulMyMsgLength;
++
++ /* write src */
++ for (i=0; i<ulLength; i++)
++ {
++ ch = *(uint8 *)(msg+i);
++ *(uint8 *) (pjsrc + i) = ch;
++ }
++ for (i=ulLength; i<ulMyMsgLength; i++)
++ *(uint8 *) (pjsrc + i) = 0;
++
++ /* fire cmd */
++ *(uint32 *) (HAC_REG_BASE + REG_HASH_CMD_OFFSET) = ulCommand;
++
++ /* get digest */
++ do {
++ ulTemp = *(volatile uint32 *) (HAC_REG_BASE + REG_HASH_STATUS_OFFSET);
++ } while (ulTemp & HASH_BUSY);
++
++ for (i=0; i<ulDigestLength; i++)
++ {
++ ch = *(volatile uint8 *) (pjdst + i);
++ *(uint8 *) (output + i) = ch;
++ }
++
++} /* hash_ast3000 */
++
++/* HMAC */
++void hmackey_ast3000(uint8 *key, uint32 ulKeyLength, uint32 ulHashMode)
++{
++ uint32 i, ulBlkLength, ulDigestLength, ulTemp, ulCommand;
++ uint8 k0[64], sum[32];
++ uint8 ch;
++ unsigned char *pjsrc, *pjdst, *pjkey;
++
++ /* Get Info */
++ switch (ulHashMode)
++ {
++ case HASHMODE_MD5:
++ ulCommand = HASH_ALG_SELECT_MD5;
++ ulDigestLength = 16;
++ break;
++ case HASHMODE_SHA1:
++ ulCommand = HASH_ALG_SELECT_SHA1 | 0x08;
++ ulDigestLength = 20;
++ break;
++ case HASHMODE_SHA256:
++ ulCommand = HASH_ALG_SELECT_SHA256 | 0x08;
++ ulDigestLength = 32;
++ break;
++ case HASHMODE_SHA224:
++ ulCommand = HASH_ALG_SELECT_SHA224 | 0x08;
++ ulDigestLength = 28;
++ break;
++ }
++ ulBlkLength = 64; /* MD5, SHA1/256/224: 64bytes */
++
++ /* Init */
++ memset( (void *) k0, 0, 64); /* reset to zero */
++ memset( (void *) sum, 0, 32); /* reset to zero */
++
++ /* Get k0 */
++ if (ulKeyLength <= ulBlkLength)
++ memcpy( (void *) k0, (void *) key, ulKeyLength );
++ else /* (ulKeyLength > ulBlkLength) */
++ {
++ hash_ast3000(key, ulKeyLength, sum, ulHashMode);
++ memcpy( (void *) k0, (void *) sum, ulDigestLength );
++ }
++
++ pjsrc = (unsigned char *) m16byteAlignment((unsigned long) hash_src);
++ pjdst = (unsigned char *) m16byteAlignment((unsigned long) hash_dst);
++ pjkey = (unsigned char *) m64byteAlignment((unsigned long) hmac_key);
++
++ /* Calculate digest */
++ *(uint32 *) (HAC_REG_BASE + REG_HASH_SRC_BASE_OFFSET) = (unsigned long) pjsrc;
++ *(uint32 *) (HAC_REG_BASE + REG_HASH_DST_BASE_OFFSET) = (unsigned long) pjdst;
++ *(uint32 *) (HAC_REG_BASE + REG_HASH_KEY_BASE_OFFSET) = (unsigned long) pjkey;
++ *(uint32 *) (HAC_REG_BASE + REG_HASH_LEN_OFFSET) = ulBlkLength;
++
++ /* write key to src */
++ for (i=0; i<ulBlkLength; i++)
++ {
++ ch = *(uint8 *)(k0+i);
++ *(uint8 *) (pjsrc + i) = ch;
++ }
++
++ /* fire cmd for calculate */
++ *(uint32 *) (HAC_REG_BASE + REG_HASH_CMD_OFFSET) = ulCommand | HAC_DIGEST_CAL_ENABLE;
++ do {
++ ulTemp = *(volatile uint32 *) (HAC_REG_BASE + REG_HASH_STATUS_OFFSET);
++ } while (ulTemp & HASH_BUSY);
++
++} /* hmackey_ast3000 */
++
++void hmac_ast3000(uint8 *key, uint32 ulKeyLength, uint8 *msg, uint32 ulMsgLength, uint32 ulHashMode, unsigned char *output)
++{
++ uint32 i, ulTemp, ulCommand, ulDigestLength, ulMyMsgLength;;
++ uint8 ch;
++ unsigned char *pjsrc, *pjdst, *pjkey;
++
++ /* Calculate digest */
++ switch (ulHashMode)
++ {
++ case HASHMODE_MD5:
++ ulCommand = HASH_ALG_SELECT_MD5;
++ ulDigestLength = 16;
++ break;
++ case HASHMODE_SHA1:
++ ulCommand = HASH_ALG_SELECT_SHA1 | 0x08;
++ ulDigestLength = 20;
++ break;
++ case HASHMODE_SHA256:
++ ulCommand = HASH_ALG_SELECT_SHA256 | 0x08;
++ ulDigestLength = 32;
++ break;
++ case HASHMODE_SHA224:
++ ulCommand = HASH_ALG_SELECT_SHA224 | 0x08;
++ ulDigestLength = 28;
++ break;
++ }
++
++ pjsrc = (unsigned char *) m16byteAlignment((unsigned long) hash_src);
++ pjdst = (unsigned char *) m16byteAlignment((unsigned long) hash_dst);
++ pjkey = (unsigned char *) m64byteAlignment((unsigned long) hmac_key);
++
++ /* 16byte alignment */
++ ulMyMsgLength = m16byteAlignment(ulMsgLength);
++
++ /* Init. HW */
++ *(uint32 *) (HAC_REG_BASE + REG_HASH_SRC_BASE_OFFSET) = (unsigned long) pjsrc;
++ *(uint32 *) (HAC_REG_BASE + REG_HASH_DST_BASE_OFFSET) = (unsigned long) pjdst;
++ *(uint32 *) (HAC_REG_BASE + REG_HASH_KEY_BASE_OFFSET) = (unsigned long) pjkey;
++ *(uint32 *) (HAC_REG_BASE + REG_HASH_LEN_OFFSET) = ulMyMsgLength;
++
++ /* write Text to src */
++ for (i=0; i<ulMsgLength; i++)
++ {
++ ch = *(uint8 *)(msg+i);
++ *(uint8 *) (pjsrc + i) = ch;
++ }
++ for (i=ulMsgLength; i<ulMyMsgLength; i++)
++ *(uint8 *) (pjsrc + i) = 0;
++
++ /* fire cmd */
++ *(uint32 *) (HAC_REG_BASE + REG_HASH_CMD_OFFSET) = ulCommand | HAC_ENABLE;
++ do {
++ ulTemp = *(volatile uint32 *) (HAC_REG_BASE + REG_HASH_STATUS_OFFSET);
++ } while (ulTemp & HASH_BUSY);
++
++ /* Output Digest */
++ for (i=0; i<ulDigestLength; i++)
++ {
++ ch = *(uint8 *) (pjdst + i);
++ *(uint8 *) (output + i) = ch;
++ }
++
++} /* hmac_ast3000 */
++
++/* main hactest procedure */
++int do_hactest (void)
++{
++ unsigned long i, j, Flags = 0;
++ aes_test *pjaes_test;
++ aes_context aes_ctx;
++ unsigned char AES_Mode[8], aes_output[64];
++ unsigned long ulAESMsgLength;
++
++ rc4_test *pjrc4_test;
++ unsigned char rc4_buf_sw[64], rc4_buf_hw[64];
++ unsigned long ulRC4KeyLength, ulRC4MsgLength;
++
++ hash_test *pjhash_test;
++ unsigned char HASH_Mode[8], hash_out[64];
++
++ hmac_test *pjhmac_test;
++ unsigned char HMAC_Mode[8], hmac_out[64];
++
++ EnableHMAC();
++
++ /* AES Test */
++ pjaes_test = aestest;
++ while (pjaes_test->aes_mode != 0xFF)
++ {
++
++ if (pjaes_test->aes_mode == CRYPTOMODE_CBC)
++ strcpy (AES_Mode, "CBC");
++ else if (pjaes_test->aes_mode == CRYPTOMODE_CFB)
++ strcpy (AES_Mode, "CFB");
++ else if (pjaes_test->aes_mode == CRYPTOMODE_OFB)
++ strcpy (AES_Mode, "OFB");
++ else if (pjaes_test->aes_mode == CRYPTOMODE_CTR)
++ strcpy (AES_Mode, "CTR");
++ else
++ strcpy (AES_Mode, "ECB");
++
++ /* Get Msg. Length */
++ ulAESMsgLength = strlen(pjaes_test->plaintext);
++ j = ( (ulAESMsgLength + 15) >> 4) << 4;
++ for (i=ulAESMsgLength; i<j; i++)
++ pjaes_test->plaintext[i] = 0;
++ ulAESMsgLength = j;
++
++ aes_set_key(&aes_ctx, pjaes_test->key, pjaes_test->key_length);
++
++ /* Encryption Test */
++ aes_enc_ast3000(&aes_ctx, pjaes_test->plaintext, pjaes_test->key, aes_output, ulAESMsgLength, pjaes_test->aes_mode);
++ if (strncmp(aes_output, pjaes_test->ciphertext, ulAESMsgLength))
++ {
++ Flags |= FLAG_AESTEST_FAIL;
++ printf("[INFO] AES%d %s Mode Encryption Failed \n", pjaes_test->key_length, AES_Mode);
++ printf("[DBG] Golden Data Dump .... \n");
++ for (i=0; i< ulAESMsgLength; i++)
++ {
++ printf("%02x ", pjaes_test->ciphertext[i]);
++ if (((i+1) % 8) == 0)
++ printf("\n");
++ }
++ printf("\n [DBG] Error Data Dump .... \n");
++ for (i=0; i< ulAESMsgLength; i++)
++ {
++ printf("%02x ", aes_output[i]);
++ if (((i+1) % 8) == 0)
++ printf("\n");
++ }
++ printf("\n");
++ }
++ else
++ {
++ /*
++ printf("[INFO] AES%d %s Mode Encryption Passed \n", pjaes_test->key_length, AES_Mode);
++ */
++ }
++
++ /* Decryption Test */
++ aes_dec_ast3000(&aes_ctx, pjaes_test->ciphertext, pjaes_test->key, aes_output, ulAESMsgLength, pjaes_test->aes_mode);
++ if (strncmp(aes_output, pjaes_test->plaintext, ulAESMsgLength))
++ {
++ Flags |= FLAG_AESTEST_FAIL;
++ printf("[INFO] AES%d %s Mode Decryption Failed \n", pjaes_test->key_length, AES_Mode);
++ printf("[DBG] Golden Data Dump .... \n");
++ for (i=0; i< ulAESMsgLength; i++)
++ {
++ printf("%02x ", pjaes_test->plaintext[i]);
++ if (((i+1) % 8) == 0)
++ printf("\n");
++ }
++ printf("\n [DBG] Error Data Dump .... \n");
++ for (i=0; i< ulAESMsgLength; i++)
++ {
++ printf("%02x ", aes_output[i]);
++ if (((i+1) % 8) == 0)
++ printf("\n");
++ }
++ printf("\n");
++ }
++ else
++ {
++ /*
++ printf("[INFO] AES%d %s Mode Decryption Passed \n", pjaes_test->key_length, AES_Mode);
++ */
++ }
++
++ pjaes_test++;
++ } /* AES */
++
++ /* RC4 Test */
++ pjrc4_test = rc4test;
++ while ((pjrc4_test->key[0] != 0xff) && (pjrc4_test->data[0] != 0xff))
++ {
++
++ /* Get Info */
++ ulRC4KeyLength = strlen(pjrc4_test->key);
++ ulRC4MsgLength = strlen(pjrc4_test->data);
++ memcpy( (void *) rc4_buf_sw, (void *) pjrc4_test->data, ulRC4MsgLength );
++ memcpy( (void *) rc4_buf_hw, (void *) pjrc4_test->data, ulRC4MsgLength );
++
++ /* Crypto */
++ rc4_crypt_sw(rc4_buf_sw, ulRC4MsgLength, pjrc4_test->key, ulRC4KeyLength);
++ rc4_crypt_ast3000(rc4_buf_hw, ulRC4MsgLength, pjrc4_test->key, ulRC4KeyLength);
++
++ if (strncmp(rc4_buf_hw, rc4_buf_sw, ulRC4MsgLength))
++ {
++ Flags |= FLAG_RC4TEST_FAIL;
++ printf("[INFO] RC4 Encryption Failed \n");
++ printf("[DBG] Golden Data Dump .... \n");
++ for (i=0; i< ulRC4MsgLength; i++)
++ {
++ printf("%02x ", rc4_buf_sw[i]);
++ if (((i+1) % 8) == 0)
++ printf("\n");
++ }
++ printf("\n [DBG] Error Data Dump .... \n");
++ for (i=0; i< ulRC4MsgLength; i++)
++ {
++ printf("%02x ", rc4_buf_hw[i]);
++ if (((i+1) % 8) == 0)
++ printf("\n");
++ }
++ printf("\n");
++ }
++ else
++ {
++ /*
++ printf("[INFO] RC4 Encryption Passed \n");
++ */
++ }
++
++ pjrc4_test++;
++
++ } /* RC4 */
++
++ /* Hash Test */
++ pjhash_test = hashtest;
++ while (pjhash_test->hash_mode != 0xFF)
++ {
++
++ if (pjhash_test->hash_mode == HASHMODE_MD5)
++ strcpy (HASH_Mode, "MD5");
++ else if (pjhash_test->hash_mode == HASHMODE_SHA1)
++ strcpy (HASH_Mode, "SHA1");
++ else if (pjhash_test->hash_mode == HASHMODE_SHA256)
++ strcpy (HASH_Mode, "SHA256");
++ else if (pjhash_test->hash_mode == HASHMODE_SHA224)
++ strcpy (HASH_Mode, "SHA224");
++
++ /* Hash */
++ hash_ast3000(pjhash_test->input, strlen(pjhash_test->input), hash_out, pjhash_test->hash_mode);
++ if (strncmp(hash_out, pjhash_test->digest, pjhash_test->digest_length))
++ {
++ Flags |= FLAG_HASHTEST_FAIL;
++ printf("[INFO] HASH %s Failed \n", HASH_Mode);
++ printf("[DBG] Golden Data Dump .... \n");
++ for (i=0; i< pjhash_test->digest_length; i++)
++ {
++ printf("%02x ",pjhash_test->digest[i]);
++ if (((i+1) % 8) == 0)
++ printf("\n");
++ }
++ printf("\n [DBG] Error Data Dump .... \n");
++ for (i=0; i< pjhash_test->digest_length; i++)
++ {
++ printf("%02x ",hash_out[i]);
++ if (((i+1) % 8) == 0)
++ printf("\n");
++ }
++ printf("\n");
++ }
++ else
++ {
++ /*
++ printf("[INFO] HASH %s Passed \n", HASH_Mode);
++ */
++ }
++
++ pjhash_test++;
++
++ } /* Hash Test */
++
++ /* HMAC Test */
++ pjhmac_test = hmactest;
++ while (pjhmac_test->hash_mode != 0xFF)
++ {
++
++ if (pjhmac_test->hash_mode == HASHMODE_MD5)
++ strcpy (HMAC_Mode, "MD5");
++ else if (pjhmac_test->hash_mode == HASHMODE_SHA1)
++ strcpy (HMAC_Mode, "SHA1");
++ else if (pjhmac_test->hash_mode == HASHMODE_SHA256)
++ strcpy (HMAC_Mode, "SHA256");
++ else if (pjhmac_test->hash_mode == HASHMODE_SHA224)
++ strcpy (HMAC_Mode, "SHA224");
++
++ /* HMAC */
++ hmackey_ast3000(pjhmac_test->key, pjhmac_test->key_length, pjhmac_test->hash_mode);
++ hmac_ast3000(pjhmac_test->key, pjhmac_test->key_length, pjhmac_test->input, strlen(pjhmac_test->input), pjhmac_test->hash_mode, hmac_out);
++ if (strncmp(hmac_out, pjhmac_test->digest, pjhmac_test->digest_length))
++ {
++ Flags |= FLAG_HASHTEST_FAIL;
++ printf("[INFO] HMAC %s Failed \n", HMAC_Mode);
++ printf("[DBG] Golden Data Dump .... \n");
++ for (i=0; i< pjhmac_test->digest_length; i++)
++ {
++ printf("%02x ",pjhmac_test->digest[i]);
++ if (((i+1) % 8) == 0)
++ printf("\n");
++ }
++ printf("\n [DBG] Error Data Dump .... \n");
++ for (i=0; i< pjhmac_test->digest_length; i++)
++ {
++ printf("%02x ",hmac_out[i]);
++ if (((i+1) % 8) == 0)
++ printf("\n");
++ }
++ printf("\n");
++ }
++ else
++ {
++ /*
++ printf("[INFO] HMAC %s Passed \n", HMAC_Mode);
++ */
++ }
++
++ pjhmac_test++;
++
++ } /* HMAC Test */
++
++ return Flags;
++
++}
++
++#endif /* CONFIG_SLT */
+diff --git a/board/aspeed/ast2400/hactest.h b/board/aspeed/ast2400/hactest.h
+new file mode 100755
+index 0000000..fcf2186
+--- /dev/null
++++ b/board/aspeed/ast2400/hactest.h
+@@ -0,0 +1,194 @@
++/*
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++ */
++/* Err Flags */
++#define FLAG_AESTEST_FAIL 0x00000001
++#define FLAG_RC4TEST_FAIL 0x00000002
++#define FLAG_HASHTEST_FAIL 0x00000004
++
++/* Specific */
++/*
++#define DRAM_BASE 0x40000000
++#define CRYPTO_SRC_BASE (DRAM_BASE + 0x100000)
++#define CRYPTO_DST_BASE (DRAM_BASE + 0x200000)
++#define CRYPTO_CONTEXT_BASE (DRAM_BASE + 0x300000)
++
++#define HASH_SRC_BASE (DRAM_BASE + 0x400000)
++#define HASH_DST_BASE (DRAM_BASE + 0x500000)
++#define HMAC_KEY_BASE (DRAM_BASE + 0x600000)
++*/
++#define m08byteAlignment(x) ((x + 0x00000007) & 0xFFFFFFF8)
++#define m16byteAlignment(x) ((x + 0x0000000F) & 0xFFFFFFF0)
++#define m64byteAlignment(x) ((x + 0x0000003F) & 0xFFFFFFC0)
++
++#define CRYPTO_ALIGNMENT 16
++#define CRYPTO_MAX_SRC (100+CRYPTO_ALIGNMENT)
++#define CRYPTO_MAX_DST (100+CRYPTO_ALIGNMENT)
++#define CRYPTO_MAX_CONTEXT (100+CRYPTO_ALIGNMENT)
++
++#define HASH_ALIGNMENT 16
++#define HMAC_KEY_ALIGNMENT 64
++#define HASH_MAX_SRC (100+HASH_ALIGNMENT)
++#define HASH_MAX_DST (32+HASH_ALIGNMENT)
++#define HMAC_MAX_KEY (64+HMAC_KEY_ALIGNMENT)
++
++/* General */
++#define HAC_REG_BASE 0x1e6e3000
++
++#define MAX_KEYLENGTH 100
++#define MAX_TEXTLENGTH 100
++#define MAX_AESTEXTLENGTH 256
++#define MAX_RC4TEXTLENGTH 256
++#define MAX_RC4KEYLENGTH 256
++
++#define CRYPTOMODE_ECB 0x00
++#define CRYPTOMODE_CBC 0x01
++#define CRYPTOMODE_CFB 0x02
++#define CRYPTOMODE_OFB 0x03
++#define CRYPTOMODE_CTR 0x04
++
++#define HASHMODE_MD5 0x00
++#define HASHMODE_SHA1 0x01
++#define HASHMODE_SHA256 0x02
++#define HASHMODE_SHA224 0x03
++
++#define MIXMODE_DISABLE 0x00
++#define MIXMODE_CRYPTO 0x02
++#define MIXMODE_HASH 0x03
++
++#define REG_CRYPTO_SRC_BASE_OFFSET 0x00
++#define REG_CRYPTO_DST_BASE_OFFSET 0x04
++#define REG_CRYPTO_CONTEXT_BASE_OFFSET 0x08
++#define REG_CRYPTO_LEN_OFFSET 0x0C
++#define REG_CRYPTO_CMD_BASE_OFFSET 0x10
++//#define REG_CRYPTO_ENABLE_OFFSET 0x14
++#define REG_CRYPTO_STATUS_OFFSET 0x1C
++
++#define REG_HASH_SRC_BASE_OFFSET 0x20
++#define REG_HASH_DST_BASE_OFFSET 0x24
++#define REG_HASH_KEY_BASE_OFFSET 0x28
++#define REG_HASH_LEN_OFFSET 0x2C
++#define REG_HASH_CMD_OFFSET 0x30
++//#define REG_HASH_ENABLE_OFFSET 0x14
++#define REG_HASH_STATUS_OFFSET 0x1C
++
++#define HASH_BUSY 0x01
++#define CRYPTO_BUSY 0x02
++
++//#define ENABLE_HASH 0x01
++//#define DISABLE_HASH 0x00
++//#define ENABLE_CRYPTO 0x02
++//#define DISABLE_CRYPTO 0x00
++
++#define CRYPTO_SYNC_MODE_MASK 0x03
++#define CRYPTO_SYNC_MODE_ASYNC 0x00
++#define CRYPTO_SYNC_MODE_PASSIVE 0x02
++#define CRYPTO_SYNC_MODE_ACTIVE 0x03
++
++#define CRYPTO_AES128 0x00
++#define CRYPTO_AES192 0x04
++#define CRYPTO_AES256 0x08
++
++#define CRYPTO_AES_ECB 0x00
++#define CRYPTO_AES_CBC 0x10
++#define CRYPTO_AES_CFB 0x20
++#define CRYPTO_AES_OFB 0x30
++#define CRYPTO_AES_CTR 0x40
++
++#define CRYPTO_ENCRYPTO 0x80
++#define CRYPTO_DECRYPTO 0x00
++
++#define CRYPTO_AES 0x000
++#define CRYPTO_RC4 0x100
++
++#define CRYPTO_ENABLE_RW 0x000
++#define CRYPTO_ENABLE_CONTEXT_LOAD 0x000
++#define CRYPTO_ENABLE_CONTEXT_SAVE 0x000
++
++#define HASH_SYNC_MODE_MASK 0x03
++#define HASH_SYNC_MODE_ASYNC 0x00
++#define HASH_SYNC_MODE_PASSIVE 0x02
++#define HASH_SYNC_MODE_ACTIVE 0x03
++
++#define HASH_READ_SWAP_ENABLE 0x04
++#define HMAC_SWAP_CONTROL_ENABLE 0x08
++
++#define HASH_ALG_SELECT_MASK 0x70
++#define HASH_ALG_SELECT_MD5 0x00
++#define HASH_ALG_SELECT_SHA1 0x20
++#define HASH_ALG_SELECT_SHA224 0x40
++#define HASH_ALG_SELECT_SHA256 0x50
++
++#define HAC_ENABLE 0x80
++#define HAC_DIGEST_CAL_ENABLE 0x180
++#define HASH_INT_ENABLE 0x200
++
++/* AES */
++#ifndef uint8
++#define uint8 unsigned char
++#endif
++
++#ifndef uint32
++#define uint32 unsigned long int
++#endif
++
++typedef struct
++{
++ uint32 erk[64]; /* encryption round keys */
++ uint32 drk[64]; /* decryption round keys */
++ int nr; /* number of rounds */
++}
++aes_context;
++
++typedef struct
++{
++ int aes_mode;
++ int key_length;
++
++ uint8 key[32]; /* as iv in CTR mode */
++ uint8 plaintext[64];
++ uint8 ciphertext[64];
++
++}
++aes_test;
++
++/* RC4 */
++typedef struct
++{
++ uint8 key[32];
++ uint8 data[64];
++}
++rc4_test;
++
++/* Hash */
++typedef struct
++{
++ int hash_mode;
++ int digest_length;
++
++ uint8 input[64];
++ uint8 digest[64];
++
++}
++hash_test;
++
++/* HMAC */
++typedef struct
++{
++ int hash_mode;
++ int key_length;
++ int digest_length;
++
++ uint8 key[100];
++ uint8 input[64];
++ uint8 digest[64];
++
++}
++hmac_test;
+diff --git a/board/aspeed/ast2400/mactest.c b/board/aspeed/ast2400/mactest.c
+new file mode 100755
+index 0000000..22054b9
+--- /dev/null
++++ b/board/aspeed/ast2400/mactest.c
+@@ -0,0 +1,510 @@
++/*
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++ */
++/*
++ * (C) Copyright 2007 ASPEED Software
++ * MAC Manufacture Test in ASPEED's SDK version 0.20.01
++ *
++ * Release History
++ * 1. First Release, river@20071130
++ * 2. Fix the endless loop when PHY is not ready, river@20071204
++ *
++ * Test items:
++ * 1. Support MARVELL PHY only in this version
++ * 2. MDC/MDIO
++ * 3. GMAC/Duplex TX/RX Full_Size, Packet_Length Test
++ * 4. 100M/Duplex TX/RX Full_Size, Packet_Length Test
++ *
++ *
++ *
++*/
++
++
++/*
++* Diagnostics support
++*/
++#include <common.h>
++#include <command.h>
++#include <post.h>
++#include <malloc.h>
++#include <net.h>
++#include "slt.h"
++
++#if ((CFG_CMD_SLT & CFG_CMD_MACTEST) && defined(CONFIG_SLT))
++#include "mactest.h"
++
++static int INL(u_long base, u_long addr)
++{
++ return le32_to_cpu(*(volatile u_long *)(addr + base));
++}
++
++static void OUTL(u_long base, int command, u_long addr)
++{
++ *(volatile u_long *)(addr + base) = cpu_to_le32(command);
++}
++
++
++static void SCU_MAC1_Enable (u8 enable)
++{
++ unsigned int SCU_Register;
++
++ if(enable) {
++//MAC1 RESET/PHY_LINK in SCU
++ SCU_Register = INL(SCU_BASE, SCU_RESET_CONTROL_REG);
++ OUTL(SCU_BASE, SCU_Register & ~(0x800), SCU_RESET_CONTROL_REG);
++ } else {
++ SCU_Register = INL(SCU_BASE, SCU_RESET_CONTROL_REG);
++ OUTL(SCU_BASE, SCU_Register |(0x800), SCU_RESET_CONTROL_REG);
++
++}
++}
++
++/*------------------------------------------------------------
++ . Reads a register from the MII Management serial interface
++ .-------------------------------------------------------------*/
++static u16 phy_read_register (u8 PHY_Register, u8 PHY_Address)
++{
++ u32 Data, Status = 0, Loop_Count = 0, PHY_Ready = 1;
++ u16 Return_Data;
++
++ OUTL(MAC1_IO_BASE, (PHY_Register << 21) + (PHY_Address << 16) + MIIRD + MDC_CYCTHR, PHYCR_REG);
++ do {
++ Status = (INL (MAC1_IO_BASE, PHYCR_REG) & MIIRD);
++ Loop_Count++;
++ if (Loop_Count >= PHY_LOOP) {
++ PHY_Ready = 0;
++ break;
++ }
++ } while (Status == MIIRD);
++
++ if (PHY_Ready == 0) {
++ printf ("PHY NOT REDAY\n");
++ return 0;
++ }
++
++ udelay(5*1000);
++ Data = INL (MAC1_IO_BASE, PHYDATA_REG);
++ Return_Data = (Data >> 16);
++
++ return Return_Data;
++}
++
++static void phy_write_register (u8 PHY_Register, u8 PHY_Address, u16 PHY_Data)
++{
++ u32 Status = 0, Loop_Count = 0, PHY_Ready = 1;
++
++ OUTL(MAC1_IO_BASE, PHY_Data, PHYDATA_REG);
++ OUTL(MAC1_IO_BASE, (PHY_Register << 21) + (PHY_Address << 16) + MIIWR + MDC_CYCTHR, PHYCR_REG);
++ do {
++ Status = (INL (MAC1_IO_BASE, PHYCR_REG) & MIIWR);
++ Loop_Count++;
++ if (Loop_Count >= PHY_LOOP) {
++ PHY_Ready = 0;
++ break;
++ }
++ } while (Status == MIIWR);
++ if (PHY_Ready == 0) {
++ printf ("PHY NOT REDAY\n");
++ }
++}
++
++static int wait_link_resolve (void)
++{
++ int resolved_status, Loop_Count = 0, PHY_Ready = 1;
++
++ do {
++ resolved_status = (phy_read_register (0x11, 0) & (PHY_RESOLVED_bit | PHY_LINK_bit));
++ Loop_Count++;
++ if (Loop_Count >= PHY_LOOP) {
++ PHY_Ready = 0;
++ printf ("PHY NOT READY\n");
++ break;
++ }
++ } while (resolved_status != (PHY_RESOLVED_bit | PHY_LINK_bit));
++
++ return PHY_Ready;
++}
++
++static void set_phy_speed (int chip, int speed, int duplex)
++{
++ unsigned short data, status;
++
++
++ if (chip == PHYID_VENDOR_MARVELL) {
++ if ((speed == PHY_SPEED_1G) && (duplex == DUPLEX_FULL)) {
++//Manual Control
++ phy_write_register (18, 0, 0);
++ data = phy_read_register (9, 0);
++ phy_write_register (9, 0, data | 0x1800);
++//PHY Reset
++ phy_write_register (0, 0, 0x0140 | 0x8000);
++ do {
++ status = (phy_read_register (0, 0) & 0x8000);
++ } while (status != 0);
++
++//Force 1G
++ phy_write_register (29, 0, 0x07);
++ data = phy_read_register (30, 0);
++ phy_write_register (30, 0, data | 0x08);
++ phy_write_register (29, 0, 0x10);
++ data = phy_read_register (30, 0);
++ phy_write_register (30, 0, data | 0x02);
++ phy_write_register (29, 0, 0x12);
++ data = phy_read_register (30, 0);
++ phy_write_register (30, 0, data | 0x01);
++
++ printf ("FORCE MARVELL PHY to 1G/DUPLEX DONE\n");
++ }
++ else if ((speed == PHY_SPEED_100M) && (duplex == DUPLEX_FULL)) {
++//PHY Reset
++ phy_write_register (0, 0, 0x2100 | 0x8000);
++ do {
++ status = (phy_read_register (0, 0) & 0x8000);
++ } while (status != 0);
++
++//Force 100M
++ data = phy_read_register (0, 0);
++ phy_write_register (0, 0, data | 0x4000 | 0x8000);
++ do {
++ status = (phy_read_register (0, 0) & 0x8000);
++ } while (status != 0);
++ data = phy_read_register (0, 0);
++
++ printf ("FORCE MARVELL PHY to 100M/DUPLEX DONE\n");
++ }
++ }
++ else if ( (chip == PHYID_VENDOR_RTL8201E) || (chip == PHYID_VENDOR_BROADCOM) ){
++ /* basic setting */
++ data = phy_read_register (0, 0);
++ data &= 0x7140;
++ data |= 0x4000;
++ if (speed == PHY_SPEED_100M)
++ data |= 0x2000;
++ if (duplex == DUPLEX_FULL)
++ data |= 0x0100;
++ phy_write_register (0, 0, data);
++
++ /* reset */
++ phy_write_register (0, 0, data | 0x8000);
++ do {
++ status = (phy_read_register (0, 0) & 0x8000);
++ } while (status != 0);
++ udelay(100*1000);
++
++ /* basic setting */
++ phy_write_register (0, 0, data);
++
++ if (chip == PHYID_VENDOR_RTL8201E)
++ printf ("FORCE RTL8201E PHY to 100M/DUPLEX DONE\n");
++ else if (chip == PHYID_VENDOR_BROADCOM)
++ printf ("FORCE Broadcom PHY to 100M/DUPLEX DONE\n");
++
++ }
++
++}
++
++static void MAC1_reset (void)
++{
++ OUTL(MAC1_IO_BASE, SW_RST_bit, MACCR_REG);
++ for (; (INL(MAC1_IO_BASE, MACCR_REG ) & SW_RST_bit) != 0; ) {udelay(1000);}
++ OUTL(MAC1_IO_BASE, 0, IER_REG );
++}
++
++static int set_mac1_control_register (int Chip_ID)
++{
++ unsigned long MAC_CR_Register = 0;
++ int PHY_Ready = 1;
++ u16 PHY_Status, PHY_Speed, PHY_Duplex, Advertise, Link_Partner;
++
++ MAC_CR_Register = SPEED_100M_MODE_bit | RX_ALLADR_bit | FULLDUP_bit | RXMAC_EN_bit | RXDMA_EN_bit | TXMAC_EN_bit | TXDMA_EN_bit | CRC_APD_bit;
++
++ if ( (Chip_ID == PHYID_VENDOR_BROADCOM) || (Chip_ID == PHYID_VENDOR_RTL8201E)) {
++ Advertise = phy_read_register (0x04, 0);
++ Link_Partner = phy_read_register (0x05, 0);
++ Advertise = (Advertise & PHY_SPEED_DUPLEX_MASK);
++ Link_Partner = (Link_Partner & PHY_SPEED_DUPLEX_MASK);
++ if ((Advertise & Link_Partner) & PHY_100M_DUPLEX) {
++ MAC_CR_Register |= SPEED_100M_MODE_bit;
++ MAC_CR_Register |= FULLDUP_bit;
++ }
++ else if ((Advertise & Link_Partner) & PHY_100M_HALF) {
++ MAC_CR_Register |= SPEED_100M_MODE_bit;
++ MAC_CR_Register &= ~FULLDUP_bit;
++ }
++ else if ((Advertise & Link_Partner) & PHY_10M_DUPLEX) {
++ MAC_CR_Register &= ~SPEED_100M_MODE_bit;
++ MAC_CR_Register |= FULLDUP_bit;
++ }
++ else if ((Advertise & Link_Partner) & PHY_10M_HALF) {
++ MAC_CR_Register &= ~SPEED_100M_MODE_bit;
++ MAC_CR_Register &= ~FULLDUP_bit;
++ }
++ }
++ else if (Chip_ID == PHYID_VENDOR_MARVELL) {
++
++ PHY_Ready = wait_link_resolve ();
++
++ if (PHY_Ready == 1) {
++ PHY_Status = phy_read_register (0x11, 0);
++ PHY_Speed = (PHY_Status & PHY_SPEED_MASK) >> 14;
++ PHY_Duplex = (PHY_Status & PHY_DUPLEX_MASK) >> 13;
++
++ if (PHY_Speed == SPEED_1000M) {
++ MAC_CR_Register |= GMAC_MODE_bit;
++ }
++ else {
++ MAC_CR_Register &= ~GMAC_MODE_bit;
++ if (PHY_Speed == SPEED_10M) {
++ MAC_CR_Register &= ~SPEED_100M_MODE_bit;
++ }
++ }
++ if (PHY_Duplex == DUPLEX_HALF) {
++ MAC_CR_Register &= ~FULLDUP_bit;
++ }
++ }
++ }
++ OUTL(MAC1_IO_BASE, MAC_CR_Register, MACCR_REG);
++
++ return PHY_Ready;
++}
++
++static void ring_buffer_alloc (void)
++{
++ unsigned int i, j;
++
++//Write data into TX buffer
++ for (i = 0; i < NUM_TX; i++) {
++ for (j = 0; j < TX_BUFF_SZ; j++) {
++ tx_buffer[i][j] = i * 4 + j;
++ }
++ }
++//Initialize RX buffer to 0
++ for (i = 0; i < NUM_RX; i++) {
++ for (j = 0; j < RX_BUFF_SZ; j++) {
++ rx_buffer[i][j] = 0;
++ }
++ }
++//Prepare descriptor
++ for (i = 0; i < NUM_RX; i++) {
++ rx_ring[i].status = cpu_to_le32(RXPKT_RDY + RX_BUFF_SZ);
++ rx_ring[i].buf = ((u32) &rx_buffer[i]);
++ rx_ring[i].reserved = 0;
++ }
++ for (i = 0; i < NUM_TX; i++) {
++ tx_ring[i].status = 0;
++ tx_ring[i].des1 = 0;
++ tx_ring[i].buf = ((u32) &tx_buffer[i]);
++ tx_ring[i].reserved = 0;
++ }
++
++ rx_ring[NUM_RX - 1].status |= cpu_to_le32(EDORR);
++ tx_ring[NUM_TX - 1].status |= cpu_to_le32(EDOTR);
++
++ OUTL(MAC1_IO_BASE, ((u32) &tx_ring), TXR_BADR_REG);
++ OUTL(MAC1_IO_BASE, ((u32) &rx_ring), RXR_BADR_REG);
++
++ tx_new = 0;
++ rx_new = 0;
++}
++
++static int packet_test (void)
++{
++ unsigned int rx_status, length, i, Loop_Count = 0;
++
++ tx_ring[tx_new].status |= cpu_to_le32(LTS | FTS | TX_BUFF_SZ);
++ tx_ring[tx_new].status |= cpu_to_le32(TXDMA_OWN);
++ OUTL(MAC1_IO_BASE, POLL_DEMAND, TXPD_REG);
++
++//Compare result
++ do {
++ rx_status = rx_ring[rx_new].status;
++ Loop_Count++;
++ } while (!(rx_status & RXPKT_STATUS) && (Loop_Count < PHY_LOOP));
++ if (rx_status & (RX_ERR | CRC_ERR | FTL | RUNT | RX_ODD_NB)) {
++ /* There was an error.*/
++ printf("RX error status = 0x%08X\n", rx_status);
++ return PACKET_TEST_FAIL;
++ } else {
++ length = (rx_status & BYTE_COUNT_MASK);
++ for (i = 0; i < RX_BUFF_SZ / 4; i++) {
++ if (rx_buffer[rx_new][i] != tx_buffer[tx_new][i]) {
++ printf ("ERROR at packet %d, address %x\n", rx_new, i);
++ printf ("Gold = %8x, Real = %8x\n", tx_buffer[tx_new][i], rx_buffer[rx_new][i]);
++ return PACKET_TEST_FAIL;
++ }
++ }
++ }
++ tx_new = (tx_new + 1) % NUM_TX;
++ rx_new = (rx_new + 1) % NUM_RX;
++
++ return TEST_PASS;
++}
++
++static int packet_length_test (int packet_length)
++{
++ unsigned int rx_status, length, i, Loop_Count = 0;
++
++ tx_ring[tx_new].status &= (~(BYTE_COUNT_MASK));
++ tx_ring[tx_new].status |= cpu_to_le32(LTS | FTS | packet_length);
++ tx_ring[tx_new].status |= cpu_to_le32(TXDMA_OWN);
++ OUTL(MAC1_IO_BASE, POLL_DEMAND, TXPD_REG);
++
++//Compare result
++ do {
++ rx_status = rx_ring[rx_new].status;
++ Loop_Count++;
++ } while (!(rx_status & RXPKT_STATUS) && (Loop_Count < PHY_LOOP));
++ if (rx_status & (RX_ERR | CRC_ERR | FTL | RUNT | RX_ODD_NB)) {
++ /* There was an error.*/
++ printf("RX error status = 0x%08X\n", rx_status);
++ return PACKET_LENGTH_TEST_FAIL;
++ } else {
++ length = (rx_status & BYTE_COUNT_MASK) - 4;
++ if (length != packet_length) {
++ printf ("Received Length ERROR. Gold = %d, Fail = %d\n",packet_length, length);
++ printf ("rx_new = %d, tx_new = %d\n", rx_new, tx_new);
++ return PACKET_LENGTH_TEST_FAIL;
++ }
++ for (i = 0; i < length; i++) {
++ if (rx_buffer[rx_new][i] != tx_buffer[tx_new][i]) {
++ printf ("ERROR at packet %d, address %x\n", rx_new, i);
++ printf ("Gold = %8x, Real = %8x\n", tx_buffer[tx_new][i], rx_buffer[rx_new][i]);
++ return PACKET_LENGTH_TEST_FAIL;
++ }
++ }
++ }
++ rx_ring[rx_new].status &= (~(RXPKT_STATUS));
++ tx_new = (tx_new + 1) % NUM_TX;
++ rx_new = (rx_new + 1) % NUM_RX;
++
++ return TEST_PASS;
++}
++
++static int MAC1_init (int id)
++{
++ int phy_status = 0;
++
++ MAC1_reset ();
++ phy_status = set_mac1_control_register (id);
++ ring_buffer_alloc ();
++
++ return phy_status;
++}
++
++int do_mactest (void)
++{
++ unsigned int phy_id, i;
++ int test_result = 0, phy_status = 0;
++
++ SCU_MAC1_Enable(1);
++ phy_id = ((phy_read_register (0x02, 0) << 16) + phy_read_register (0x03, 0)) & PHYID_VENDOR_MASK;
++ if (phy_id == PHYID_VENDOR_MARVELL) {
++ printf ("PHY DETECTED ------> MARVELL\n");
++
++ set_phy_speed (phy_id, PHY_SPEED_1G, DUPLEX_FULL);
++ if ((phy_status = MAC1_init (phy_id)) != 0) {
++ for (i = 0; i < NUM_TX; i++) {
++ test_result |= packet_test ();
++ if (test_result != 0)
++ break;
++ }
++ }
++ else if (phy_status == 0) {
++ printf ("PHY FAIL: Please Check If you are using LOOP BACK Connector\n");
++ test_result = 3;
++ return test_result;
++ }
++ if ((phy_status = MAC1_init (phy_id)) != 0) {
++ for (i = 60; i < TX_BUFF_SZ; i++) {
++ test_result |= packet_length_test (i);
++ if (test_result != 0)
++ break;
++ }
++ }
++ else if (phy_status == 0) {
++ printf ("PHY FAIL: Please Check If you are using LOOP BACK Connector\n");
++ test_result = 3;
++ return test_result;
++ }
++ set_phy_speed (phy_id, PHY_SPEED_100M, DUPLEX_FULL);
++ if ((phy_status = MAC1_init (phy_id)) != 0) {
++ for (i = 0; i < NUM_TX; i++) {
++ test_result |= packet_test ();
++ if (test_result != 0)
++ break;
++ }
++ }
++ else if (phy_status == 0) {
++ printf ("PHY FAIL: Please Check If you are using LOOP BACK Connector\n");
++ test_result = 3;
++ return test_result;
++ }
++
++ if ((phy_status = MAC1_init (phy_id)) != 0) {
++ for (i = 60; i < TX_BUFF_SZ; i++) {
++ test_result |= packet_length_test (i);
++ if (test_result != 0)
++ break;
++ }
++ }
++ else if (phy_status == 0) {
++ printf ("PHY FAIL: Please Check If you are using LOOP BACK Connector\n");
++ test_result = 3;
++ return test_result;
++ }
++ }
++ else if ( (phy_id == PHYID_VENDOR_RTL8201E) || (phy_id == PHYID_VENDOR_BROADCOM) ){
++
++ if (phy_id == PHYID_VENDOR_RTL8201E)
++ printf ("PHY DETECTED ------> RTL 8201E \n");
++ else if (phy_id == PHYID_VENDOR_BROADCOM)
++ printf ("PHY DETECTED ------> Broadcom \n");
++
++ set_phy_speed (phy_id, PHY_SPEED_100M, DUPLEX_FULL);
++ if ((phy_status = MAC1_init (phy_id)) != 0) {
++ for (i = 0; i < NUM_TX; i++) {
++ test_result |= packet_test ();
++ if (test_result != 0)
++ break;
++ }
++ }
++ else if (phy_status == 0) {
++ printf ("PHY FAIL: Please Check If you are using LOOP BACK Connector\n");
++ test_result = 3;
++ return test_result;
++ }
++
++ if ((phy_status = MAC1_init (phy_id)) != 0) {
++ for (i = 60; i < TX_BUFF_SZ; i++) {
++ test_result |= packet_length_test (i);
++ if (test_result != 0)
++ break;
++ }
++ }
++ else if (phy_status == 0) {
++ printf ("PHY FAIL: Please Check If you are using LOOP BACK Connector\n");
++ test_result = 3;
++ return test_result;
++ }
++ }
++
++ if ((phy_status == 0) && (test_result & PACKET_TEST_FAIL)) {
++ printf ("Packet Test FAIL !\n");
++ }
++ else if ((phy_status == 0) && (test_result & PACKET_LENGTH_TEST_FAIL)) {
++ printf ("Packet Length Test FAIL !\n");
++ }
++
++ SCU_MAC1_Enable(0);
++ return test_result;
++
++}
++
++#endif /* CONFIG_SLT */
+diff --git a/board/aspeed/ast2400/mactest.h b/board/aspeed/ast2400/mactest.h
+new file mode 100755
+index 0000000..e75b7bb
+--- /dev/null
++++ b/board/aspeed/ast2400/mactest.h
+@@ -0,0 +1,215 @@
++/*
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++ */
++/* MACTest.h */
++
++// --------------------------------------------------------------------
++// General Definition
++// --------------------------------------------------------------------
++#define MAC1_IO_BASE 0x1E660000
++#define PHY_LOOP 100000
++#define NUM_RX 48
++#define NUM_TX 48
++#define RX_BUFF_SZ 1514
++#define TX_BUFF_SZ 1514
++#define TOUT_LOOP 1000000
++#define ETH_ALEN 6
++#define POLL_DEMAND 1
++
++
++// --------------------------------------------------------------------
++// MAC Register Index
++// --------------------------------------------------------------------
++#define ISR_REG 0x00 // interrups status register
++#define IER_REG 0x04 // interrupt maks register
++#define MAC_MADR_REG 0x08 // MAC address (Most significant)
++#define MAC_LADR_REG 0x0c // MAC address (Least significant)
++#define MAHT0_REG 0x10 // Multicast Address Hash Table 0 register
++#define MAHT1_REG 0x14 // Multicast Address Hash Table 1 register
++#define TXPD_REG 0x18 // Transmit Poll Demand register
++#define RXPD_REG 0x1c // Receive Poll Demand register
++#define TXR_BADR_REG 0x20 // Transmit Ring Base Address register
++#define RXR_BADR_REG 0x24 // Receive Ring Base Address register
++#define HPTXPD_REG 0x28
++#define HPTXR_BADR_REG 0x2c
++#define ITC_REG 0x30 // interrupt timer control register
++#define APTC_REG 0x34 // Automatic Polling Timer control register
++#define DBLAC_REG 0x38 // DMA Burst Length and Arbitration control register
++#define DMAFIFOS_REG 0x3c
++#define FEAR_REG 0x44
++#define TPAFCR_REG 0x48
++#define RBSR_REG 0x4c
++#define MACCR_REG 0x50 // MAC control register
++#define MACSR_REG 0x54 // MAC status register
++#define PHYCR_REG 0x60 // PHY control register
++#define PHYDATA_REG 0x64 // PHY Write Data register
++
++// --------------------------------------------------------------------
++// PHYCR_REG
++// --------------------------------------------------------------------
++#define PHY_RE_AUTO_bit (1UL<<9)
++#define PHY_READ_bit (1UL<<26)
++#define PHY_WRITE_bit (1UL<<27)
++// --------------------------------------------------------------------
++// PHYCR_REG
++// --------------------------------------------------------------------
++#define PHY_AUTO_OK_bit (1UL<<5)
++// --------------------------------------------------------------------
++// PHY INT_STAT_REG
++// --------------------------------------------------------------------
++#define PHY_SPEED_CHG_bit (1UL<<14)
++#define PHY_DUPLEX_CHG_bit (1UL<<13)
++#define PHY_LINK_CHG_bit (1UL<<10)
++#define PHY_AUTO_COMP_bit (1UL<<11)
++// --------------------------------------------------------------------
++// PHY SPE_STAT_REG
++// --------------------------------------------------------------------
++#define PHY_RESOLVED_bit (1UL<<11)
++#define PHY_LINK_bit (1UL<<10)
++#define PHY_SPEED_mask 0xC000
++#define PHY_SPEED_10M 0x0
++#define PHY_SPEED_100M 0x1
++#define PHY_SPEED_1G 0x2
++#define PHY_DUPLEX_mask 0x2000
++#define PHY_SPEED_DUPLEX_MASK 0x01E0
++#define PHY_100M_DUPLEX 0x0100
++#define PHY_100M_HALF 0x0080
++#define PHY_10M_DUPLEX 0x0040
++#define PHY_10M_HALF 0x0020
++#define LINK_STATUS 0x04
++#define PHYID_VENDOR_MASK 0xfffffc00
++#define PHYID_VENDOR_MARVELL 0x01410c00
++#define PHYID_VENDOR_BROADCOM 0x00406000
++#define PHYID_VENDOR_RTL8201E 0x001cc800
++#define DUPLEX_FULL 0x01
++#define DUPLEX_HALF 0x00
++
++
++
++// --------------------------------------------------------------------
++// MACCR_REG
++// --------------------------------------------------------------------
++
++#define SW_RST_bit (1UL<<31) // software reset/
++#define DIRPATH_bit (1UL<<21)
++#define RX_IPCS_FAIL_bit (1UL<<20)
++#define SPEED_100M_MODE_bit (1UL<<19)
++#define RX_UDPCS_FAIL_bit (1UL<<18)
++#define RX_BROADPKT_bit (1UL<<17) // Receiving broadcast packet
++#define RX_MULTIPKT_bit (1UL<<16) // receiving multicast packet
++#define RX_HT_EN_bit (1UL<<15)
++#define RX_ALLADR_bit (1UL<<14) // not check incoming packet's destination address
++#define JUMBO_LF_bit (1UL<<13)
++#define RX_RUNT_bit (1UL<<12) // Store incoming packet even its length is les than 64 byte
++#define CRC_CHK_bit (1UL<<11)
++#define CRC_APD_bit (1UL<<10) // append crc to transmit packet
++#define GMAC_MODE_bit (1UL<<9)
++#define FULLDUP_bit (1UL<<8) // full duplex
++#define ENRX_IN_HALFTX_bit (1UL<<7)
++#define LOOP_EN_bit (1UL<<6) // Internal loop-back
++#define HPTXR_EN_bit (1UL<<5)
++#define REMOVE_VLAN_bit (1UL<<4)
++#define RXMAC_EN_bit (1UL<<3) // receiver enable
++#define TXMAC_EN_bit (1UL<<2) // transmitter enable
++#define RXDMA_EN_bit (1UL<<1) // enable DMA receiving channel
++#define TXDMA_EN_bit (1UL<<0) // enable DMA transmitting channel
++
++
++// --------------------------------------------------------------------
++// SCU_REG
++// --------------------------------------------------------------------
++#define SCU_BASE 0x1E6E2000
++#define SCU_PROTECT_KEY_REG 0x0
++#define SCU_PROT_KEY_MAGIC 0x1688a8a8
++#define SCU_RESET_CONTROL_REG 0x04
++#define SCU_RESET_MAC1 (1u << 11)
++#define SCU_RESET_MAC2 (1u << 12)
++#define SCU_HARDWARE_TRAPPING_REG 0x70
++#define SCU_HT_MAC_INTF_LSBIT 6
++#define SCU_HT_MAC_INTERFACE (0x7u << SCU_HT_MAC_INTF_LSBIT)
++#define MAC_INTF_SINGLE_PORT_MODES (1u<<0/*GMII*/ | 1u<<3/*MII_ONLY*/ | 1u<<4/*RMII_ONLY*/)
++#define SCU_HT_MAC_GMII 0x0u
++// MII and MII mode
++#define SCU_HT_MAC_MII_MII 0x1u
++#define SCU_HT_MAC_MII_ONLY 0x3u
++#define SCU_HT_MAC_RMII_ONLY 0x4u
++#define SCU_MULTIFUNCTION_PIN_REG 0x74
++#define SCU_MFP_MAC2_PHYLINK (1u << 26)
++#define SCU_MFP_MAC1_PHYLINK (1u << 25)
++#define SCU_MFP_MAC2_MII_INTF (1u << 21)
++#define SCU_MFP_MAC2_MDC_MDIO (1u << 20)
++#define SCU_SILICON_REVISION_REG 0x7C
++
++//---------------------------------------------------
++// PHY R/W Register Bit
++//---------------------------------------------------
++#define MIIWR (1UL<<27)
++#define MIIRD (1UL<<26)
++#define MDC_CYCTHR 0x34
++#define PHY_SPEED_MASK 0xC000
++#define PHY_DUPLEX_MASK 0x2000
++#define SPEED_1000M 0x02
++#define SPEED_100M 0x01
++#define SPEED_10M 0x00
++#define DUPLEX_FULL 0x01
++#define DUPLEX_HALF 0x00
++#define RESOLVED_BIT 0x800
++
++#define PHY_SPEED_DUPLEX_MASK 0x01E0
++#define PHY_100M_DUPLEX 0x0100
++#define PHY_100M_HALF 0x0080
++#define PHY_10M_DUPLEX 0x0040
++#define PHY_10M_HALF 0x0020
++
++//---------------------------------------------------
++// Descriptor bits.
++//---------------------------------------------------
++#define TXDMA_OWN 0x80000000 /* Own Bit */
++#define RXPKT_RDY 0x00000000
++#define RXPKT_STATUS 0x80000000
++#define EDORR 0x40000000 /* Receive End Of Ring */
++#define LRS 0x10000000 /* Last Descriptor */
++#define RD_ES 0x00008000 /* Error Summary */
++#define EDOTR 0x40000000 /* Transmit End Of Ring */
++#define T_OWN 0x80000000 /* Own Bit */
++#define LTS 0x10000000 /* Last Segment */
++#define FTS 0x20000000 /* First Segment */
++#define CRC_ERR 0x00080000
++#define TD_ES 0x00008000 /* Error Summary */
++#define TD_SET 0x08000000 /* Setup Packet */
++#define RX_ERR 0x00040000
++#define FTL 0x00100000
++#define RUNT 0x00200000
++#define RX_ODD_NB 0x00400000
++#define BYTE_COUNT_MASK 0x00003FFF
++
++//---------------------------------------------------
++// SPEED/DUPLEX Parameters
++//---------------------------------------------------
++
++//---------------------------------------------------
++// Return Status
++//---------------------------------------------------
++#define TEST_PASS 0
++#define PACKET_TEST_FAIL 1
++#define PACKET_LENGTH_TEST_FAIL 2
++
++struct mac_desc {
++ volatile s32 status;
++ u32 des1;
++ u32 reserved;
++ u32 buf;
++};
++static struct mac_desc rx_ring[NUM_RX] __attribute__ ((aligned(32))); /* RX descriptor ring */
++static struct mac_desc tx_ring[NUM_TX] __attribute__ ((aligned(32))); /* TX descriptor ring */
++static int rx_new; /* RX descriptor ring pointer */
++static int tx_new; /* TX descriptor ring pointer */
++static volatile unsigned char rx_buffer[NUM_RX][RX_BUFF_SZ] __attribute__ ((aligned(32))); /* RX buffer */
++static volatile unsigned char tx_buffer[NUM_TX][TX_BUFF_SZ] __attribute__ ((aligned(32))); /* TX buffer */
+diff --git a/board/aspeed/ast2400/mictest.c b/board/aspeed/ast2400/mictest.c
+new file mode 100755
+index 0000000..1b2b342
+--- /dev/null
++++ b/board/aspeed/ast2400/mictest.c
+@@ -0,0 +1,146 @@
++/*
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
++ * MA 02111-1307 USA
++ */
++
++/*
++ * Diagnostics support
++ */
++#include <common.h>
++#include <command.h>
++#include <post.h>
++#include "slt.h"
++
++#if ((CFG_CMD_SLT & CFG_CMD_MICTEST) && defined(CONFIG_SLT))
++#include "mictest.h"
++
++static unsigned char ctrlbuf[MIC_MAX_CTRL];
++static unsigned char chksumbuf[MIC_MAX_CHKSUM];
++
++void vInitSCU(void)
++{
++ unsigned long ulData;
++
++ *(unsigned long *) (0x1e6e2000) = 0x1688A8A8;
++
++ udelay(100);
++
++ ulData = *(unsigned long *) (0x1e6e2004);
++ ulData &= 0xbffff;
++ *(unsigned long *) (0x1e6e2004) = ulData;
++
++}
++
++void vInitMIC(void)
++{
++ unsigned long i, j, ulPageNumber;
++ unsigned char *pjctrl, *pjsum;
++
++ ulPageNumber = DRAMSIZE >> 12;
++
++ pjctrl = (unsigned char *)(m16byteAlignment((unsigned long) ctrlbuf));
++ pjsum = (unsigned char *)(m16byteAlignment((unsigned long) chksumbuf));
++
++ /* init ctrl buffer (2bits for one page) */
++ for (i=0; i< (ulPageNumber/4); i++)
++ *(unsigned char *) (pjctrl + i) = DEFAULT_CTRL;
++
++ /* init chksum buf (4bytes for one page) */
++ for (i=0; i<ulPageNumber; i++)
++ *(unsigned long *) (pjsum + i*4) = DEFAULT_CHKSUM;
++
++ *(unsigned long *) (MIC_BASE + MIC_CTRLBUFF_REG) = (unsigned long) pjctrl;
++ *(unsigned long *) (MIC_BASE + MIC_CHKSUMBUF_REG) = (unsigned long) pjsum;
++ *(unsigned long *) (MIC_BASE + MIC_RATECTRL_REG) = (unsigned long) DEFAULT_RATE;
++ *(unsigned long *) (MIC_BASE + MIC_ENGINECTRL_REG) = MIC_ENABLE_MIC | (DRAMSIZE - 0x1000);
++
++}
++
++void vDisableMIC(void)
++{
++ *(unsigned long *) (MIC_BASE + MIC_ENGINECTRL_REG) = MIC_RESET_MIC;
++
++}
++
++int do_chksum(void)
++{
++ unsigned long i, j, k, ulPageNumber;
++ int Status = 0;
++ unsigned short tmp;
++ volatile unsigned long sum1, sum2;
++ unsigned long goldensum, chksum;
++ unsigned long len, tlen;
++ unsigned char *pjsum;
++
++ ulPageNumber = DRAMSIZE >> 12;
++ pjsum = (unsigned char *)(m16byteAlignment((unsigned long) chksumbuf));
++
++ /* start test */
++ for (i=0; i<ulPageNumber; i++)
++ {
++
++ sum1 = 0xffff, sum2 = 0xffff;
++ len = 0x0800;
++ j = 0;
++
++ while (len)
++ {
++ tlen = len > 360 ? 360 : len;
++ len -= tlen;
++ do {
++ tmp = *(unsigned short *) (DRAM_BASE + ((i << 12) + j));
++ sum1 += (unsigned long) tmp;
++ sum2 += sum1;
++ j+=2;
++ } while (--tlen);
++ sum1 = (sum1 & 0xffff) + (sum1 >> 16);
++ sum2 = (sum2 & 0xffff) + (sum2 >> 16);
++ }
++
++ sum1 = (sum1 & 0xffff) + (sum1 >> 16);
++ sum2 = (sum2 & 0xffff) + (sum2 >> 16);
++
++ goldensum = (sum2 << 16) | sum1;
++ k= 0;
++ do {
++ chksum = *(unsigned long *) (pjsum + i*4);
++ udelay(100);
++ k++;
++ } while ((chksum == 0) && (k<1000));
++
++ if (chksum != goldensum)
++ {
++ Status = 1;
++ printf("[FAIL] MIC Chksum Failed at Page %x \n", i);
++ }
++
++ } /* end of i loop */
++
++ return (Status);
++
++}
++
++int do_mictest (void)
++{
++ unsigned long Flags = 0;
++
++ vInitSCU();
++ vInitMIC();
++
++ if (do_chksum())
++ Flags = 1;
++
++ vDisableMIC();
++
++ return Flags;
++
++}
++
++#endif /* CONFIG_SLT */
+diff --git a/board/aspeed/ast2400/mictest.h b/board/aspeed/ast2400/mictest.h
+new file mode 100755
+index 0000000..e14bb41
+--- /dev/null
++++ b/board/aspeed/ast2400/mictest.h
+@@ -0,0 +1,55 @@
++/*
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++ */
++/* Macro */
++#define m08byteAlignment(x) ((x + 0x00000007) & 0xFFFFFFF8)
++#define m16byteAlignment(x) ((x + 0x0000000F) & 0xFFFFFFF0)
++#define m64byteAlignment(x) ((x + 0x0000003F) & 0xFFFFFFC0)
++
++/* Options */
++#define MIC_TEST_PAGE 32
++#define DRAMSIZE (MIC_TEST_PAGE * 0x1000)
++#define MIC_MAX_CTRL (MIC_TEST_PAGE / 4 + 16)
++#define MIC_MAX_CHKSUM (MIC_TEST_PAGE * 4 + 16)
++
++/* Default Setting */
++#define DEFAULT_RATE 0x00000000
++#define DEFAULT_CTRL 0xFF
++#define DEFAULT_CHKSUM 0x00000000
++#define DEFAULT_WRITEBACK 0x08880000
++
++/* Reg. Definition */
++#define DRAM_BASE 0x40000000
++#define MIC_BASE 0x1e640000
++#define MIC_CTRLBUFF_REG 0x00
++#define MIC_CHKSUMBUF_REG 0x04
++#define MIC_RATECTRL_REG 0x08
++#define MIC_ENGINECTRL_REG 0x0C
++#define MIC_STOPPAGE_REG 0x10
++#define MIC_STATUS_REG 0x14
++#define MIC_STATUS1_REG 0x18
++#define MIC_STATUS2_REG 0x1C
++
++#define MIC_RESET_MIC 0x00000000
++#define MIC_ENABLE_MIC 0x10000000
++#define MIC_MAXPAGE_MASK 0x0FFFF000
++#define MIC_WRITEBACK_MASK 0xFFFF0000
++#define MIC_STOPPAGE_MASK 0x0000FFFF
++#define MIC_PAGEERROR 0x40000000
++#define MIC_PAGE1ERROR 0x10000000
++#define MIC_PAGE2ERROR 0x20000000
++#define MIC_INTMASK 0x00060000
++#define MIC_ERRPAGENO_MASK 0x0000FFFF
++
++#define MIC_CTRL_MASK 0x03
++#define MIC_CTRL_SKIP 0x00
++#define MIC_CTRL_CHK1 0x01
++#define MIC_CTRL_CHK2 0x02
++#define MIC_CTRL_CHK3 0x03
+diff --git a/board/aspeed/ast2400/pci.c b/board/aspeed/ast2400/pci.c
+new file mode 100755
+index 0000000..5b17466
+--- /dev/null
++++ b/board/aspeed/ast2400/pci.c
+@@ -0,0 +1,243 @@
++/*
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License as
++ * published by the Free Software Foundation; either version 2, or (at
++ * your option) any later version.
++ */
++
++#include <common.h>
++#include <pci.h>
++
++#ifdef CONFIG_PCI
++
++#define PCI_CSR_BASE 0x60000000
++#define ASPEED_PCI_IO_BASE 0x00000000
++#define ASPEED_PCI_IO_SIZE 0x00010000
++#define ASPEED_PCI_MEM_BASE 0x68000000
++#define ASPEED_PCI_MEM_SIZE 0x18000000
++
++#define CSR_CRP_CMD_OFFSET 0x00
++#define CSR_CRP_WRITE_OFFSET 0x04
++#define CSR_CRP_READ_OFFSET 0x08
++#define CSR_PCI_ADDR_OFFSET 0x0C
++#define CSR_PCI_CMD_OFFSET 0x10
++#define CSR_PCI_WRITE_OFFSET 0x14
++#define CSR_PCI_READ_OFFSET 0x18
++#define CSR_PCI_STATUS_OFFSET 0x1C
++
++#define CRP_ADDR_REG (volatile ulong*) (PCI_CSR_BASE + CSR_CRP_CMD_OFFSET)
++#define CRP_WRITE_REG (volatile ulong*) (PCI_CSR_BASE + CSR_CRP_WRITE_OFFSET)
++#define CRP_READ_REG (volatile ulong*) (PCI_CSR_BASE + CSR_CRP_READ_OFFSET)
++#define PCI_ADDR_REG (volatile ulong*) (PCI_CSR_BASE + CSR_PCI_ADDR_OFFSET)
++#define PCI_CMD_REG (volatile ulong*) (PCI_CSR_BASE + CSR_PCI_CMD_OFFSET)
++#define PCI_WRITE_REG (volatile ulong*) (PCI_CSR_BASE + CSR_PCI_WRITE_OFFSET)
++#define PCI_READ_REG (volatile ulong*) (PCI_CSR_BASE + CSR_PCI_READ_OFFSET)
++
++#define PCI_CMD_READ 0x0A
++#define PCI_CMD_WRITE 0x0B
++
++#define RESET_PCI_STATUS *(volatile ulong*) (PCI_CSR_BASE + CSR_PCI_STATUS_OFFSET) = 0x01
++#define CHK_PCI_STATUS (*(volatile ulong*) (PCI_CSR_BASE + CSR_PCI_STATUS_OFFSET) & 0x03)
++
++static int pci_config_access (u8 access_type, u32 dev, u32 reg, u32 * data)
++{
++ u32 bus;
++ u32 device;
++ u32 function;
++
++ bus = ((dev & 0xff0000) >> 16);
++ device = ((dev & 0xf800) >> 11);
++ function = (dev & 0x0700);
++
++ if (bus == 0) {
++ // Type 0 Configuration
++ *PCI_ADDR_REG = (u32) (1UL << device | function | (reg & 0xfc));
++ } else {
++ // Type 1 Configuration
++ *PCI_ADDR_REG = (u32) (dev | ((reg / 4) << 2) | 1);
++ }
++
++ RESET_PCI_STATUS;
++
++ if (access_type == PCI_CMD_WRITE) {
++ *PCI_CMD_REG = (ulong) PCI_CMD_WRITE;
++ *PCI_WRITE_REG = *data;
++ } else {
++ *PCI_CMD_REG = (ulong) PCI_CMD_READ;
++ *data = *PCI_READ_REG;
++ }
++
++ return (CHK_PCI_STATUS);
++}
++
++static int aspeed_pci_read_config_byte (u32 hose, u32 dev, u32 reg, u8 * val)
++{
++ u32 data;
++
++ if (pci_config_access (PCI_CMD_READ, dev, reg, &data)) {
++ *val = 0;
++ return -1;
++ }
++
++ *val = (data >> ((reg & 3) << 3)) & 0xff;
++
++ return 0;
++}
++
++
++static int aspeed_pci_read_config_word (u32 hose, u32 dev, u32 reg, u16 * val)
++{
++ u32 data;
++
++ if (reg & 1)
++ return -1;
++
++ if (pci_config_access (PCI_CMD_READ, dev, reg, &data)) {
++ *val = 0;
++ return -1;
++ }
++
++ *val = (data >> ((reg & 3) << 3)) & 0xffff;
++
++ return 0;
++}
++
++
++static int aspeed_pci_read_config_dword (u32 hose, u32 dev, u32 reg,
++ u32 * val)
++{
++ u32 data = 0;
++
++ if (reg & 3)
++ return -1;
++
++ if (pci_config_access (PCI_CMD_READ, dev, reg, &data)) {
++ *val = 0;
++ return -1;
++ }
++
++ *val = data;
++
++ return (0);
++}
++
++static int aspeed_pci_write_config_byte (u32 hose, u32 dev, u32 reg, u8 val)
++{
++ u32 data = 0;
++
++ if (pci_config_access (PCI_CMD_READ, dev, reg, &data))
++ return -1;
++
++ data = (data & ~(0xff << ((reg & 3) << 3))) | (val <<
++ ((reg & 3) << 3));
++
++ if (pci_config_access (PCI_CMD_WRITE, dev, reg, &data))
++ return -1;
++
++ return 0;
++}
++
++
++static int aspeed_pci_write_config_word (u32 hose, u32 dev, u32 reg, u16 val)
++{
++ u32 data = 0;
++
++ if (reg & 1)
++ return -1;
++
++ if (pci_config_access (PCI_CMD_READ, dev, reg, &data))
++ return -1;
++
++ data = (data & ~(0xffff << ((reg & 3) << 3))) | (val <<
++ ((reg & 3) << 3));
++
++ if (pci_config_access (PCI_CMD_WRITE, dev, reg, &data))
++ return -1;
++
++ return 0;
++}
++
++static int aspeed_pci_write_config_dword (u32 hose, u32 dev, u32 reg, u32 val)
++{
++ u32 data;
++
++ if (reg & 3) {
++ return -1;
++ }
++
++ data = val;
++
++ if (pci_config_access (PCI_CMD_WRITE, dev, reg, &data))
++ return -1;
++
++ return (0);
++}
++
++/*
++ * Initialize PCIU
++ */
++aspeed_pciu_init ()
++{
++
++ unsigned long reg;
++
++ /* Reset PCI Host */
++ reg = *((volatile ulong*) 0x1e6e2004);
++ *((volatile ulong*) 0x1e6e2004) = reg | 0x00280000;
++
++ reg = *((volatile ulong*) 0x1e6e2074); /* REQ2 */
++ *((volatile ulong*) 0x1e6e2074) = reg | 0x00000010;
++
++ *((volatile ulong*) 0x1e6e2008) |= 0x00080000;
++ reg = *((volatile ulong*) 0x1e6e200c);
++ *((volatile ulong*) 0x1e6e200c) = reg & 0xfff7ffff;
++ udelay(1);
++ *((volatile ulong*) 0x1e6e2004) &= 0xfff7ffff;
++
++ /* Initial PCI Host */
++ RESET_PCI_STATUS;
++
++ *CRP_ADDR_REG = ((ulong)(PCI_CMD_READ) << 16) | 0x04;
++ reg = *CRP_READ_REG;
++
++ *CRP_ADDR_REG = ((ulong)(PCI_CMD_WRITE) << 16) | 0x04;
++ *CRP_WRITE_REG = reg | 0x07;
++
++}
++
++/*
++ * Initialize Module
++ */
++
++void aspeed_init_pci (struct pci_controller *hose)
++{
++ hose->first_busno = 0;
++ hose->last_busno = 0xff;
++
++ aspeed_pciu_init (); /* Initialize PCIU */
++
++ /* PCI memory space #1 */
++ pci_set_region (hose->regions + 0,
++ ASPEED_PCI_MEM_BASE, ASPEED_PCI_MEM_BASE, ASPEED_PCI_MEM_SIZE, PCI_REGION_MEM);
++
++ /* PCI I/O space */
++ pci_set_region (hose->regions + 1,
++ ASPEED_PCI_IO_BASE, ASPEED_PCI_IO_BASE, ASPEED_PCI_IO_SIZE, PCI_REGION_IO);
++
++ hose->region_count = 2;
++
++ hose->read_byte = aspeed_pci_read_config_byte;
++ hose->read_word = aspeed_pci_read_config_word;
++ hose->read_dword = aspeed_pci_read_config_dword;
++ hose->write_byte = aspeed_pci_write_config_byte;
++ hose->write_word = aspeed_pci_write_config_word;
++ hose->write_dword = aspeed_pci_write_config_dword;
++
++ pci_register_hose (hose);
++
++ hose->last_busno = pci_hose_scan (hose);
++
++ return;
++}
++#endif /* CONFIG_PCI */
++
+diff --git a/board/aspeed/ast2400/platform.S b/board/aspeed/ast2400/platform.S
+new file mode 100644
+index 0000000..27e8f26
+--- /dev/null
++++ b/board/aspeed/ast2400/platform.S
+@@ -0,0 +1,3089 @@
++/*
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++ */
++/*
++ * Board specific setup info
++ *
++ ******************************************************************************
++ * ASPEED Technology Inc.
++ * AST2300/AST2400 DDR2/DDR3 SDRAM controller initialization and calibration sequence
++ *
++ * Gary Hsu, <gary_hsu@aspeedtech.com>
++ *
++ * Release date: 2014.12.29 formal release for SDK0.60
++ *
++ * Modified list from v0.23
++ * EC1. Modify DQIDLY and DQSI-MCLK2X calibration algorithm
++ * EC2. Remove pass 2 DQIDLY finetune process
++ * EC3. Modify ECC code
++ * EC4. Add AST2400 supporting
++ * EC5. Add SPI timing calibration for AST2400
++ * EC6. Remove AST2300-A0 PCI-e workaround
++ * EC7. Add CK duty calibration for AST2400
++ * EC8. Remove #define CONFIG_DRAM_UART_OUT, default has message output to UART5
++ * EC9. Add DRAM size auto-detection
++ * EC10. Add GPIO register clear when watchdog reboot (only for AST2400)
++ * EC11. Move the "Solve ASPM" code position of AST2300 to avoid watchdog reset
++ *
++ * Modified list from v0.53
++ * EC1. Add solution of LPC lock issue due to watchdog reset. (AP note A2300-11)
++ *
++ * Modified list from v0.56
++ * EC1. Fix read DQS input mask window too late issue if DRAM's t_DQSCK is earlier too much
++ * (ex. Nanya NT5CB64M16FP)
++ * 1. Change init value of MCR18[4] from '1' to '0'
++ * 2. Add CBR4 code to finetune MCR18[4]
++ *
++ * Modified list from v0.59
++ * EC1. Add DQS input gating window delay tuning (1/2 T) when CBR retry
++ * EC2. Modify DLL1 MAdj = 0x4C
++ *
++ * Optional define variable
++ * 1. DRAM Speed //
++ * CONFIG_DRAM_336 // 336MHz (DDR-667)
++ * CONFIG_DRAM_408 // 408MHz (DDR-800) (default)
++ * 2. ECC Function enable
++ * CONFIG_DRAM_ECC // define to enable ECC function
++ * // when enabled, must define the ECC protected memory size at 0x1e6e0054
++ * 3. UART5 message output //
++ * CONFIG_DRAM_UART_38400 // set the UART baud rate to 38400, default is 115200
++ ******************************************************************************
++ */
++
++#include <config.h>
++#include <version.h>
++/******************************************************************************
++ Calibration Macro Start
++ Usable registers:
++ r0, r1, r2, r3, r5, r6, r7, r8, r9, r10, r11
++ ******************************************************************************/
++/* PATTERN_TABLE,
++ init_delay_timer,
++ check_delay_timer,
++ clear_delay_timer,
++ record_dll2_pass_range,
++ record_dll2_pass_range_h,
++ are for DRAM calibration */
++
++PATTERN_TABLE:
++ .word 0xff00ff00
++ .word 0xcc33cc33
++ .word 0xaa55aa55
++ .word 0x88778877
++ .word 0x92cc4d6e @ 5
++ .word 0x543d3cde
++ .word 0xf1e843c7
++ .word 0x7c61d253
++ .word 0x00000000 @ 8
++
++ .macro init_delay_timer
++ ldr r0, =0x1e782024 @ Set Timer3 Reload
++ str r2, [r0]
++
++ ldr r0, =0x1e6c0038 @ Clear Timer3 ISR
++ ldr r1, =0x00040000
++ str r1, [r0]
++
++ ldr r0, =0x1e782030 @ Enable Timer3
++ ldr r1, [r0]
++ mov r2, #7
++ orr r1, r1, r2, lsl #8
++ str r1, [r0]
++
++ ldr r0, =0x1e6c0090 @ Check ISR for Timer3 timeout
++ .endm
++
++ .macro check_delay_timer
++ ldr r1, [r0]
++ bic r1, r1, #0xFFFBFFFF
++ mov r2, r1, lsr #18
++ cmp r2, #0x01
++ .endm
++
++ .macro clear_delay_timer
++ ldr r0, =0x1e782030 @ Disable Timer3
++ ldr r1, [r0]
++ bic r1, r1, #0x00000F00
++ str r1, [r0]
++
++ ldr r0, =0x1e6c0038 @ Clear Timer3 ISR
++ ldr r1, =0x00040000
++ str r1, [r0]
++ .endm
++
++ .macro record_dll2_pass_range
++ ldr r1, [r0]
++ bic r2, r1, #0xFFFFFF00
++ cmp r2, r3 @ record min
++ bicgt r1, r1, #0x000000FF
++ orrgt r1, r1, r3
++ bic r2, r1, #0xFFFF00FF
++ cmp r3, r2, lsr #8 @ record max
++ bicgt r1, r1, #0x0000FF00
++ orrgt r1, r1, r3, lsl #8
++ str r1, [r0]
++ .endm
++
++ .macro record_dll2_pass_range_h
++ ldr r1, [r0]
++ bic r2, r1, #0xFF00FFFF
++ mov r2, r2, lsr #16
++ cmp r2, r3 @ record min
++ bicgt r1, r1, #0x00FF0000
++ orrgt r1, r1, r3, lsl #16
++ bic r2, r1, #0x00FFFFFF
++ cmp r3, r2, lsr #24 @ record max
++ bicgt r1, r1, #0xFF000000
++ orrgt r1, r1, r3, lsl #24
++ str r1, [r0]
++ .endm
++
++ .macro init_spi_checksum
++ ldr r0, =0x1e620084
++ ldr r1, =0x20010000
++ str r1, [r0]
++ ldr r0, =0x1e62008C
++ ldr r1, =0x20000200
++ str r1, [r0]
++ ldr r0, =0x1e620080
++ ldr r1, =0x0000000D
++ orr r2, r2, r7
++ orr r1, r1, r2, lsl #8
++ and r2, r6, #0xF
++ orr r1, r1, r2, lsl #4
++ str r1, [r0]
++ ldr r0, =0x1e620008
++ ldr r2, =0x00000800
++ .endm
++
++/******************************************************************************
++ Calibration Macro End
++ ******************************************************************************/
++LPC_Patch: @ load to SRAM base 0x1e720400
++ str r1, [r0]
++ str r3, [r2]
++ bic r1, r1, #0xFF
++LPC_Patch_S1:
++ subs r5, r5, #0x01
++ moveq pc, r8
++ ldr r3, [r2]
++ tst r3, #0x01
++ movne pc, r8
++ mov pc, r7
++LPC_Patch_S2: @ load to SRAM base 0x1e720480
++ str r1, [r0]
++ mov pc, r9
++LPC_Patch_E:
++
++.globl lowlevel_init
++lowlevel_init:
++
++init_dram:
++ /* save lr */
++ mov r4, lr
++/* Test - DRAM initial time */
++ ldr r0, =0x1e782044
++ ldr r1, =0xFFFFFFFF
++ str r1, [r0]
++
++ ldr r0, =0x1e782030
++ ldr r1, [r0]
++ bic r1, r1, #0x0000F000
++ str r1, [r0]
++ mov r2, #3
++ orr r1, r1, r2, lsl #12
++ str r1, [r0]
++/* Test - DRAM initial time */
++
++ /*Set Scratch register Bit 7 before initialize*/
++ ldr r0, =0x1e6e2000
++ ldr r1, =0x1688a8a8
++ str r1, [r0]
++
++ ldr r0, =0x1e6e2040
++ ldr r1, [r0]
++ orr r1, r1, #0x80
++ str r1, [r0]
++
++ /* Fix LPC lock issue for AST2300 */
++ ldr r0, =0x1e6e207c @ Check AST2300
++ ldr r1, [r0]
++ mov r1, r1, lsr #24
++ cmp r1, #0x01
++ bne lpc_recover_end @ not match AST2300
++
++ mov r3, #0x0
++lpc_recover_check:
++ ldr r0, =0x1e78900c @ check HICR3[4]=0x1
++ ldr r1, [r0]
++ tst r1, #0x10
++ beq lpc_recover_end
++ ldr r0, =0x1e789004 @ check HICR1[7]=0x1
++ ldr r1, [r0]
++ tst r1, #0x80
++ beq lpc_recover_end
++ ldr r0, =0x1e7890a0 @ check LHCR0[27:24]=0x6
++ ldr r1, [r0]
++ mov r1, r1, lsr #24
++ and r1, r1, #0xF
++ cmp r1, #0x06
++ bne lpc_recover_end
++ add r3, r3, #0x01
++ cmp r3, #0x5 @ repeat 5 times
++ ble lpc_recover_check
++
++ mov r3, #0x0
++lpc_recover_init:
++ ldr r0, =0x1e7890a4 @ set LHCR1[1:0]=0x0
++ ldr r1, =0x00000000
++ str r1, [r0]
++ add r3, r3, #0x01
++ cmp r3, #0x20
++ bge lpc_recover_end
++ ldr r1, [r0]
++ tst r1, #0x01
++ bne lpc_recover_init
++
++ ldr r0, =0x1e7890b0 @ set LHCR4[7:0]=0xFF
++ ldr r1, =0x000000FF
++ str r1, [r0]
++ ldr r0, =0x1e7890b4 @ set LHCR5[31:0]=0xFFFFFFFF
++ ldr r1, =0xFFFFFFFF
++ str r1, [r0]
++ ldr r0, =0x1e7890b8 @ set LHCR6[31:0]=0xFFFFFFFF
++ str r1, [r0]
++
++ adr r6, LPC_Patch
++ adr r7, LPC_Patch_S2
++ ldr r0, =0x1e720400
++copy_lpc_patch_1:
++ ldr r1, [r6]
++ str r1, [r0]
++ add r6, r6, #0x4
++ add r0, r0, #0x4
++ cmp r6, r7
++ bne copy_lpc_patch_1
++
++ adr r6, LPC_Patch_S2
++ adr r7, LPC_Patch_E
++ ldr r0, =0x1e720480
++copy_lpc_patch_2:
++ ldr r1, [r6]
++ str r1, [r0]
++ add r6, r6, #0x4
++ add r0, r0, #0x4
++ cmp r6, r7
++ bne copy_lpc_patch_2
++
++ ldr r0, =0x1e7890a0 @ set LHCR0[31:0]=0xFFFFFF01
++ ldr r1, =0xFFFFFF01
++ add r2, r0, #0x4
++ mov r3, #0x01
++ mov r5, #0x10
++ adr r9, lpc_recover_end
++ adr r6, LPC_Patch
++ adr r7, LPC_Patch_S1
++ sub r6, r7, r6
++ ldr r7, =0x1e720400
++ add r7, r7, r6
++ ldr r8, =0x1e720480
++ ldr pc, =0x1e720400
++
++lpc_recover_end:
++ ldr r0, =0x1e7890a0 @ set LHCR0[31:0]=0xFFFFFF00
++ ldr r1, =0xFFFFFF00
++ str r1, [r0]
++ /* <END> Fix LPC lock issue for AST2300 */
++
++ /* Check Scratch Register Bit 6 */
++ ldr r0, =0x1e6e2040
++ ldr r1, [r0]
++ bic r1, r1, #0xFFFFFFBF
++ mov r2, r1, lsr #6
++ cmp r2, #0x01
++ beq platform_exit
++
++ ldr r2, =0x033103F1 @ load PLL parameter for 24Mhz CLKIN (396:324)
++/* ldr r2, =0x019001F0 @ load PLL parameter for 24Mhz CLKIN (408:336) */
++ ldr r0, =0x1e6e207c @ Check Revision ID
++ ldr r1, [r0]
++ mov r1, r1, lsr #24
++ cmp r1, #0x02
++ bne set_MPLL @ not match AST2400
++
++ ldr r0, =0x1e6e2070 @ Check CLKIN freq
++ ldr r1, [r0]
++ mov r1, r1, lsr #23
++ tst r1, #0x01
++ ldrne r2, =0x017001D0 @ load PLL parameter for 25Mhz CLKIN (400:325)
++
++set_MPLL:
++ ldr r0, =0x1e6e2020 @ M-PLL (DDR SDRAM) Frequency
++ ldr r1, =0xFFFF
++#if defined(CONFIG_DRAM_336)
++ mov r2, r2, lsr #16
++#endif
++ and r1, r2, r1
++ str r1, [r0]
++
++/* Debug - UART console message */
++ ldr r0, =0x1e78400c
++ mov r1, #0x83
++ str r1, [r0]
++
++ ldr r0, =0x1e6e202c
++ ldr r2, [r0]
++ mov r2, r2, lsr #12
++ tst r2, #0x01
++ ldr r0, =0x1e784000
++ moveq r1, #0x0D @ Baudrate 115200
++ movne r1, #0x01 @ Baudrate 115200, div13
++#if defined(CONFIG_DRAM_UART_38400)
++ moveq r1, #0x27 @ Baudrate 38400
++ movne r1, #0x03 @ Baudrate 38400 , div13
++#endif
++ str r1, [r0]
++
++ ldr r0, =0x1e784004
++ mov r1, #0x00
++ str r1, [r0]
++
++ ldr r0, =0x1e78400c
++ mov r1, #0x03
++ str r1, [r0]
++
++ ldr r0, =0x1e784008
++ mov r1, #0x07
++ str r1, [r0]
++
++ ldr r0, =0x1e784000
++ mov r1, #0x0D @ '\r'
++ str r1, [r0]
++ mov r1, #0x0A @ '\n'
++ str r1, [r0]
++ mov r1, #0x44 @ 'D'
++ str r1, [r0]
++ mov r1, #0x52 @ 'R'
++ str r1, [r0]
++ mov r1, #0x41 @ 'A'
++ str r1, [r0]
++ mov r1, #0x4D @ 'M'
++ str r1, [r0]
++ mov r1, #0x20 @ ' '
++ str r1, [r0]
++ mov r1, #0x49 @ 'I'
++ str r1, [r0]
++ mov r1, #0x6E @ 'n'
++ str r1, [r0]
++ mov r1, #0x69 @ 'i'
++ str r1, [r0]
++ mov r1, #0x74 @ 't'
++ str r1, [r0]
++ mov r1, #0x2D @ '-'
++ str r1, [r0]
++ mov r1, #0x44 @ 'D'
++ str r1, [r0]
++ mov r1, #0x44 @ 'D'
++ str r1, [r0]
++ mov r1, #0x52 @ 'R'
++ str r1, [r0]
++/* Debug - UART console message */
++
++ /* Delay about 100us */
++ ldr r0, =0x1e782030 @ Init Timer3 Control
++ ldr r1, [r0]
++ bic r1, r1, #0x00000F00
++ str r1, [r0]
++
++ ldr r2, =0x00000064 @ Set Timer3 Reload = 100 us
++ init_delay_timer
++delay_0:
++ check_delay_timer
++ bne delay_0
++ clear_delay_timer
++ /* end delay 100us */
++
++/******************************************************************************
++ Init DRAM common registers
++ ******************************************************************************/
++ ldr r0, =0x1e6e0000
++ ldr r1, =0xfc600309
++ str r1, [r0]
++
++ /* Reset MMC */
++ ldr r1, =0x00000000
++ ldr r0, =0x1e6e0034
++ str r1, [r0]
++ ldr r0, =0x1e6e0018
++ str r1, [r0]
++ ldr r0, =0x1e6e0024
++ str r1, [r0]
++ ldr r0, =0x1e6e0064 @ REG_MADJ, power down DLL
++ str r1, [r0]
++
++ ldr r1, =0x00034C4C @ REG_MADJ, reset DLL
++ str r1, [r0]
++
++ ldr r0, =0x1e6e0068 @ REG_SADJ
++ ldr r1, =0x00001800
++ str r1, [r0]
++
++ /* Delay about 10us */
++ ldr r2, =0x0000000B @ Set Timer3 Reload = 10 us
++ init_delay_timer
++delay_1:
++ check_delay_timer
++ bne delay_1
++ clear_delay_timer
++ /* end delay 10us */
++
++ ldr r0, =0x1e6e0064 @ REG_MADJ | 0xC0000, enable DLL
++ ldr r1, [r0]
++ ldr r2, =0xC0000
++ orr r1, r1, r2
++ str r1, [r0]
++
++ ldr r0, =0x1e6e0008
++ ldr r1, =0x0090040f /* VGA */
++ str r1, [r0]
++
++ ldr r0, =0x1e6e0018
++ ldr r1, =0x4000A120
++ str r1, [r0]
++
++ ldr r0, =0x1e6e0018
++ ldr r1, =0x00000120
++ str r1, [r0]
++
++ ldr r0, =0x1e6e0038
++ ldr r1, =0x00000000
++ str r1, [r0]
++
++ ldr r0, =0x1e6e0040
++ ldr r1, =0xFF444444
++ str r1, [r0]
++
++ ldr r0, =0x1e6e0044
++ ldr r1, =0x22222222
++ str r1, [r0]
++
++ ldr r0, =0x1e6e0048
++ ldr r1, =0x22222222
++ str r1, [r0]
++
++ ldr r0, =0x1e6e004c
++ ldr r1, =0x22222222
++ str r1, [r0]
++
++ ldr r0, =0x1e6e0050
++ ldr r1, =0x80000000
++ str r1, [r0]
++
++ ldr r0, =0x1e6e0050
++ ldr r1, =0x00000000
++ str r1, [r0]
++
++ ldr r0, =0x1e6e0054
++ ldr r1, =0x00000000
++ str r1, [r0]
++
++ ldr r0, =0x1e6e0060 @ REG_DRV
++ ldr r1, =0x000000FA @ 408 MHz
++#if defined(CONFIG_DRAM_336)
++ ldr r1, =0x000000FA
++#endif
++ str r1, [r0]
++
++ ldr r0, =0x1e6e0070
++ ldr r1, =0x00000000
++ str r1, [r0]
++
++ ldr r0, =0x1e6e0074
++ ldr r1, =0x00000000
++ str r1, [r0]
++
++ ldr r0, =0x1e6e0078
++ ldr r1, =0x00000000
++ str r1, [r0]
++
++ ldr r0, =0x1e6e007c
++ ldr r1, =0x00000000
++ str r1, [r0]
++
++ ldr r0, =0x1e6e0080
++ ldr r1, =0x00000000
++ str r1, [r0]
++
++ ldr r0, =0x1e6e0084
++ ldr r1, =0x00FFFFFF
++ str r1, [r0]
++
++ ldr r0, =0x1e6e0088 @ REG_DQIDLY
++ ldr r1, =0x00000089 @ 408 MHz
++#if defined(CONFIG_DRAM_336)
++ ldr r1, =0x00000074
++#endif
++ str r1, [r0]
++
++ ldr r0, =0x1e6e0020 @ REG_DQSIC
++ ldr r1, =0x000000E2 @ 408 MHz
++#if defined(CONFIG_DRAM_336)
++ ldr r1, =0x000000BA
++#endif
++ str r1, [r0]
++
++ /* Delay about 10us */
++ ldr r2, =0x0000000B @ Set Timer3 Reload = 10 us
++ init_delay_timer
++delay_2:
++ check_delay_timer
++ bne delay_2
++ clear_delay_timer
++ /* end delay 10us */
++
++ /* Check DRAM Type by H/W Trapping */
++ ldr r0, =0x1e6e2070
++ ldr r1, [r0]
++ bic r1, r1, #0xFEFFFFFF @ bit[24]=1 => DDR2
++ mov r2, r1, lsr #24
++ cmp r2, #0x01
++ beq ddr2_init
++ b ddr3_init
++.LTORG
++
++/******************************************************************************
++ DDR3 Init
++
++ tRCD = 15 ns
++ tRAS = 37.5 ns
++ tRRD = max(4 CK,10 ns)
++ tRP = 15 ns
++ tRFC = 110ns/1Gbit, 160ns/2Gbit, 300ns/4Gbit
++ tRTP = max(4 CK,7.5 ns)
++ tWR = 15 ns
++ tXSNR = max(10 CK,200 ns)
++ tWTR = max(4 CK,7.5 ns)
++ tFAW = 50 ns
++ tMRD = max(15 CK,20 ns)
++ ******************************************************************************/
++ddr3_init:
++/* Debug - UART console message */
++ ldr r0, =0x1e784000
++ mov r1, #0x33 @ '3'
++ str r1, [r0]
++ mov r1, #0x0D @ '\r'
++ str r1, [r0]
++ mov r1, #0x0A @ '\n'
++ str r1, [r0]
++/* Debug - UART console message */
++
++ ldr r0, =0x1e6e0004
++ ldr r1, =0x00000531 @ Default set to 1Gbit
++ str r1, [r0]
++
++ ldr r0, =0x1e6e0010 @ REG_AC1
++ ldr r1, =0x33302825 @ 408 MHz
++#if defined(CONFIG_DRAM_336)
++ ldr r1, =0x22202725
++#endif
++ str r1, [r0]
++
++ /* Check DRAM CL Timing by H/W Trapping */
++ ldr r0, =0x1e6e2070
++ ldr r1, [r0]
++ bic r1, r1, #0xF9FFFFFF
++ mov r2, r1, lsr #9 @ Set CL
++ ldr r1, =0x00020000
++ add r2, r2, r1
++ ldr r1, [r0]
++ bic r1, r1, #0xFBFFFFFF
++ mov r1, r1, lsr #6 @ Set CWL
++ orr r2, r2, r1
++ ldr r1, =0x00300000
++ add r2, r2, r1
++
++ ldr r0, =0x1e6e0014 @ REG_AC2
++ ldr r1, =0xCC00963F @ 408 MHz
++#if defined(CONFIG_DRAM_336)
++ ldr r1, =0xAA007636
++#endif
++ orr r1, r1, r2
++ str r1, [r0]
++
++ ldr r0, =0x1e6e0004 @ check 2400 mode
++ ldr r2, [r0]
++ mov r2, r2, lsr #10
++
++ ldr r0, =0x1e6e006c @ REG_IOZ
++ ldr r1, =0x00002312 @ 408 MHz
++#if defined(CONFIG_DRAM_336)
++ ldr r1, =0x00002312
++#endif
++ tst r2, #0x01
++ moveq r1, r1, lsr #8
++ str r1, [r0]
++
++ ldr r0, =0x1e6e0120
++ mov r1, #0
++ str r1, [r0]
++ tst r2, #0x01 @ check AST2300
++ beq CBRDLL1_2300_Start
++ ldr r0, =0x1e6e207c @ check AST2400 revision A0
++ ldr r1, [r0]
++ mov r1, r1, lsr #16
++ and r1, r1, #0xFF
++ cmp r1, #0x0
++ beq CBRDLL1_2300_Start
++ b CBRDLL1_2400_Start
++MCLK2X_Phase_CBR_Done_DDR3:
++ ldr r0, =0x1e6e0018
++ ldr r1, [r0]
++ orr r1, r1, #0x40
++ str r1, [r0]
++
++ ldr r0, =0x1e6e0034
++ ldr r1, =0x00000001
++ str r1, [r0]
++
++ ldr r0, =0x1e6e000c
++ ldr r1, =0x00000040
++ str r1, [r0]
++
++ /* Delay about 400us */
++ ldr r2, =0x00000190 @ Set Timer3 Reload = 400 us
++ init_delay_timer
++delay3_4:
++ check_delay_timer
++ bne delay3_4
++ clear_delay_timer
++ /* end delay 400us */
++
++ /* Check DRAM CL Timing by H/W Trapping */
++ ldr r0, =0x1e6e2070
++ ldr r1, [r0]
++ bic r1, r1, #0xF9FFFFFF
++ mov r2, r1, lsr #21 @ Set CL
++ ldr r1, =0x00000010
++ add r2, r2, r1
++ ldr r1, [r0]
++ bic r1, r1, #0xFBFFFFFF
++ mov r1, r1, lsr #7 @ Set CWL
++ orr r2, r2, r1
++
++ ldr r0, =0x1e6e002c @ REG_MRS
++ ldr r1, =0x04001700 @ 408 MHz
++#if defined(CONFIG_DRAM_336)
++ ldr r1, =0x04001500
++#endif
++ orr r1, r1, r2
++ str r1, [r0]
++
++ ldr r0, =0x1e6e0030 @ REG_EMRS
++ ldr r1, =0x00000000 @ 408 MHz
++#if defined(CONFIG_DRAM_336)
++ ldr r1, =0x00000000
++#endif
++ str r1, [r0]
++
++ ldr r0, =0x1e6e0028 @ Set EMRS2
++ ldr r1, =0x00000005
++ str r1, [r0]
++
++ ldr r0, =0x1e6e0028 @ Set EMRS3
++ ldr r1, =0x00000007
++ str r1, [r0]
++
++ ldr r0, =0x1e6e0028 @ Set EMRS
++ ldr r1, =0x00000003
++ str r1, [r0]
++
++ ldr r0, =0x1e6e0028 @ Set MRS
++ ldr r1, =0x00000001
++ str r1, [r0]
++
++ ldr r0, =0x1e6e002c @ REG_MRS
++ ldr r1, =0x04001600 @ 408 MHz
++#if defined(CONFIG_DRAM_336)
++ ldr r1, =0x04001400
++#endif
++ orr r1, r1, r2
++ str r1, [r0]
++
++ ldr r0, =0x1e6e000c @ Refresh 8 times
++ ldr r1, =0x00005C48
++ str r1, [r0]
++
++ ldr r0, =0x1e6e0028 @ Set MRS
++ ldr r1, =0x00000001
++ str r1, [r0]
++
++ ldr r0, =0x1e6e000c @ Set refresh cycle
++ ldr r1, =0x00002001
++ str r1, [r0]
++
++ ldr r0, =0x1e6e0014
++ ldr r1, [r0]
++ bic r1, r1, #0xFFF9FFFF
++ mov r2, r1, lsr #3 @ get CL
++
++ ldr r0, =0x1e6e0034 @ REG_PWC
++ ldr r1, =0x00000303 @ 408 MHz
++#if defined(CONFIG_DRAM_336)
++ ldr r1, =0x00000303
++#endif
++ orr r1, r1, r2
++ str r1, [r0]
++
++ b Calibration_Start
++.LTORG
++/******************************************************************************
++ End DDR3 Init
++ ******************************************************************************/
++
++/******************************************************************************
++ DDR2 Init
++
++ tRCD = 15 ns
++ tRAS = 45 ns
++ tRRD = 10 ns
++ tRP = 15 ns
++ tRFC = 105ns/512Mbit, 127.5ns/1Gbit, 197.5ns/2Gbit, 327.5ns/4Gbit
++ tRTP = 7.5 ns
++ tWR = 15 ns
++ tXSNR = 200 ns
++ tWTR = 7.5 ns
++ tFAW = 50 ns
++ tMRD = 4 CK
++ ******************************************************************************/
++ddr2_init:
++/* Debug - UART console message */
++ ldr r0, =0x1e784000
++ mov r1, #0x32 @ '2'
++ str r1, [r0]
++ mov r1, #0x0D @ '\r'
++ str r1, [r0]
++ mov r1, #0x0A @ '\n'
++ str r1, [r0]
++/* Debug - UART console message */
++
++ ldr r0, =0x1e6e0004
++ ldr r1, =0x00000510 @ Default set to 512Mbit
++ str r1, [r0]
++
++ ldr r0, =0x1e6e0010 @ REG_AC1
++ ldr r1, =0x33302714 @ 408 MHz
++#if defined(CONFIG_DRAM_336)
++ ldr r1, =0x22201613
++#endif
++ str r1, [r0]
++
++ /* Check DRAM CL Timing by H/W Trapping */
++ ldr r0, =0x1e6e2070
++ ldr r1, [r0]
++ bic r1, r1, #0xF9FFFFFF
++ mov r2, r1, lsr #5 @ Set CL
++ mov r1, r2, lsr #4 @ Set CWL
++ orr r2, r2, r1
++ ldr r1, =0x00110000
++ add r2, r2, r1
++
++ ldr r0, =0x1e6e0014 @ REG_AC2
++ ldr r1, =0xCC00B03F @ 408 MHz
++#if defined(CONFIG_DRAM_336)
++ ldr r1, =0xAA00903B
++#endif
++ orr r1, r1, r2
++ str r1, [r0]
++
++ ldr r0, =0x1e6e0004 @ check 2400 mode
++ ldr r2, [r0]
++ mov r2, r2, lsr #10
++
++ ldr r0, =0x1e6e006c @ REG_IOZ
++ ldr r1, =0x00002312 @ 408 MHz
++#if defined(CONFIG_DRAM_336)
++ ldr r1, =0x00002312
++#endif
++ tst r2, #0x01
++ moveq r1, r1, lsr #8
++ str r1, [r0]
++
++ ldr r0, =0x1e6e0120
++ mov r1, #1
++ str r1, [r0]
++ tst r2, #0x01 @ check AST2300
++ beq CBRDLL1_2300_Start
++ ldr r0, =0x1e6e207c @ check AST2400 revision A0
++ ldr r1, [r0]
++ mov r1, r1, lsr #16
++ and r1, r1, #0xFF
++ cmp r1, #0x0
++ beq CBRDLL1_2300_Start
++ b CBRDLL1_2400_Start
++MCLK2X_Phase_CBR_Done_DDR2:
++
++ ldr r0, =0x1e6e0034
++ ldr r1, =0x00000001
++ str r1, [r0]
++
++ ldr r0, =0x1e6e000c
++ ldr r1, =0x00000000
++ str r1, [r0]
++
++ /* Delay about 400us */
++ ldr r2, =0x00000190 @ Set Timer3 Reload = 400 us
++ init_delay_timer
++delay2_4:
++ check_delay_timer
++ bne delay2_4
++ clear_delay_timer
++ /* end delay 400us */
++
++ /* Check DRAM CL Timing by H/W Trapping */
++ ldr r0, =0x1e6e2070
++ ldr r1, [r0]
++ bic r1, r1, #0xF9FFFFFF
++ mov r2, r1, lsr #21 @ Set CL
++ ldr r1, =0x00000040
++ orr r2, r2, r1
++
++ ldr r0, =0x1e6e002c @ REG_MRS
++ ldr r1, =0x00000D03 @ 408 MHz
++#if defined(CONFIG_DRAM_336)
++ ldr r1, =0x00000B03
++#endif
++ orr r1, r1, r2
++ str r1, [r0]
++
++ ldr r0, =0x1e6e0030 @ REG_EMRS
++ ldr r1, =0x00000040 @ 408 MHz
++#if defined(CONFIG_DRAM_336)
++ ldr r1, =0x00000040
++#endif
++ str r1, [r0]
++
++ ldr r0, =0x1e6e0028 @ Set EMRS2
++ ldr r1, =0x00000005
++ str r1, [r0]
++
++ ldr r0, =0x1e6e0028 @ Set EMRS3
++ ldr r1, =0x00000007
++ str r1, [r0]
++
++ ldr r0, =0x1e6e0028 @ Set EMRS
++ ldr r1, =0x00000003
++ str r1, [r0]
++
++ ldr r0, =0x1e6e0028 @ Set MRS
++ ldr r1, =0x00000001
++ str r1, [r0]
++
++ ldr r0, =0x1e6e000c @ Refresh 8 times
++ ldr r1, =0x00005C08
++ str r1, [r0]
++
++ ldr r0, =0x1e6e002c @ REG_MRS
++ ldr r1, =0x00000C03 @ 408 MHz
++#if defined(CONFIG_DRAM_336)
++ ldr r1, =0x00000A03
++#endif
++ orr r1, r1, r2
++ str r1, [r0]
++
++ ldr r0, =0x1e6e0028 @ Set MRS
++ ldr r1, =0x00000001
++ str r1, [r0]
++
++ ldr r0, =0x1e6e0030 @ REG_EMRS
++ ldr r1, =0x000003C0 @ 408 MHz
++#if defined(CONFIG_DRAM_336)
++ ldr r1, =0x000003C0
++#endif
++ str r1, [r0]
++
++ ldr r0, =0x1e6e0028 @ Set EMRS
++ ldr r1, =0x00000003
++ str r1, [r0]
++
++ ldr r0, =0x1e6e0030 @ REG_EMRS
++ ldr r1, =0x00000040 @ 408 MHz
++#if defined(CONFIG_DRAM_336)
++ ldr r1, =0x00000040
++#endif
++ str r1, [r0]
++
++ ldr r0, =0x1e6e0028 @ Set EMRS
++ ldr r1, =0x00000003
++ str r1, [r0]
++
++ ldr r0, =0x1e6e000c @ Set refresh cycle
++ ldr r1, =0x00002001
++ str r1, [r0]
++
++ ldr r0, =0x1e6e0014
++ ldr r1, [r0]
++ bic r1, r1, #0xFFF9FFFF
++ mov r2, r1, lsr #3 @ get CL
++
++ ldr r0, =0x1e6e0034 @ REG_PWC
++ ldr r1, =0x00000503 @ 408 MHz
++#if defined(CONFIG_DRAM_336)
++ ldr r1, =0x00000503
++#endif
++ orr r1, r1, r2
++ str r1, [r0]
++
++ b Calibration_Start
++.LTORG
++/******************************************************************************
++ End DDR2 Init
++ ******************************************************************************/
++/******************************************************************************
++ DDR CK duty finetune program
++ SRAM buffer definition
++ 0x1E720204 : gdll golden DLL1 record
++ 0x1E720208 : gduty golden duty setting record
++ 0x1E72020C : gdutysum golden duty data record
++ 0x1E720210 : duty record of delay 0 invert
++ 0x1E720214 : duty record of delay 1 invert
++ ....
++ 0x1E72024C : duty record of delay 15 invert
++ 0x1E720250 : duty record of delay 0
++ 0x1E720254 : duty record of delay 1
++ ....
++ 0x1E72028C : duty record of delay 15
++
++ Register usage
++ r0 - r3 = free
++ r4 = record the return pc value, do not use
++ r5 = free
++ r6 = free
++ r7 = duty count
++ r8 = gdll
++ r9 = gduty
++ r10 = gdutysum
++ ******************************************************************************/
++CBRDLL1_2400_Start:
++ ldr r0, =0x1e6e0120
++ ldr r1, [r0]
++ orr r1, r1, #0x02
++ str r1, [r0]
++
++ ldr r1, =0x00000000
++ ldr r0, =0x1e720204
++ ldr r2, =0x1e7202a0
++init_sram_start0:
++ str r1, [r0]
++ add r0, r0, #4
++ cmp r0, r2
++ blt init_sram_start0
++
++ ldr r0, =0x1e6e0034
++ mov r1, #0x20
++ str r1, [r0]
++
++ ldr r0, =0x1e6e0060
++ ldr r1, [r0]
++ mov r2, #0x01
++ orr r1, r1, r2, lsl #13
++ str r1, [r0]
++
++ mov r7, #0x0 @ init duty count
++ mov r8, #0x0 @ init gdll
++ mov r9, #0x0 @ init gduty
++ mov r10, #0x0 @ init gdutysum
++cbrdll1_duty_start:
++ cmp r7, #32
++ bge cbrdll1_duty_end
++
++ ldr r0, =0x1e6e0018
++ ldr r1, =0x00008120
++ str r1, [r0]
++
++ ldr r0, =0x1e6e0060
++ ldr r1, [r0]
++ bic r1, r1, #0x00001F00
++ orr r1, r1, r7, lsl #8
++ mov r2, #0x10
++ eor r1, r1, r2, lsl #8
++ str r1, [r0]
++
++ ldr r0, =0x1e6e0000 @ dummy read
++ ldr r1, [r0]
++
++ b CBRDLL1_2300_Start
++CBRDLL1_2400_Call:
++
++ mov r5, #0x01 @ init dqidly count
++ mov r6, #0x00 @ init duty sum
++cbrdll1_duty_cal_start:
++ cmp r5, #0x05
++ bge cbrdll1_duty_cal_end
++
++ ldr r0, =0x1e6e0018
++ ldr r1, =0x00200120
++ orr r1, r1, r5, lsl #16
++ str r1, [r0]
++
++ ldr r0, =0x1e6e0000
++ ldr r1, [r0]
++
++ ldr r0, =0x1e6e0018
++ ldr r1, [r0]
++ mov r2, #0x10
++ orr r1, r1, r2, lsl #24
++ str r1, [r0]
++
++ ldr r0, =0x1e6e0080
++ ldr r1, =0x80000000 @ init duty cal waiting
++cbrdll1_duty_cal_wait:
++ ldr r2, [r0]
++ tst r2, r1
++ beq cbrdll1_duty_cal_wait
++
++ ldr r0, =0x1e6e008c
++ ldr r2, [r0]
++
++ ldr r0, =0x1e720210
++ add r0, r0, r7, lsl #2
++ str r2, [r0]
++
++ ldr r1, =0xFFFF
++ and r3, r1, r2
++ cmp r3, r1
++ moveq r2, r2, lsr #16
++ and r3, r1, r2
++ add r6, r6, r3
++ ldr r1, =0xF000
++ cmp r3, r1
++ blt cbrdll1_duty_cal_end
++ add r5, r5, #0x01
++ b cbrdll1_duty_cal_start
++
++cbrdll1_duty_cal_end:
++ mov r6, r6, lsr #2 @ get dutysum
++ cmp r6, r10 @ check dutysum > gdutysum
++ ble cbrdll1_duty_next
++ ldr r0, =0x1e6e0068
++ ldr r8, [r0]
++ eor r9, r7, #0x10
++ mov r10, r6
++
++cbrdll1_duty_next:
++ add r7, r7, #0x01
++ cmp r7, #16 @ check duty >= 15
++ blt cbrdll1_duty_start
++ ldr r0, =0xFA00 @ check gdutysum > 0xFA00
++ cmp r10, r0
++ blt cbrdll1_duty_start
++
++cbrdll1_duty_end:
++ ldr r0, =0x1e6e0060
++ ldr r1, [r0]
++ bic r1, r1, #0x00001F00
++ orr r1, r1, r9, lsl #8
++ str r1, [r0]
++
++ ldr r0, =0x1e6e0068
++ bic r8, r8, #0xFF000000
++ bic r8, r8, #0x00FF0000
++ str r8, [r0]
++
++ ldr r0, =0x1e720204 @ record result
++ str r8, [r0]
++ add r0, r0, #0x04
++ str r9, [r0]
++ add r0, r0, #0x04
++ str r10, [r0]
++
++ ldr r0, =0x1e6e0018
++ ldr r1, =0x00008120
++ str r1, [r0]
++ ldr r0, =0x1e6e0000 @ dummy read
++ ldr r1, [r0]
++ ldr r0, =0x1e6e0018
++ ldr r1, =0x00000120
++ str r1, [r0]
++
++ ldr r0, =0x1e6e0120
++ ldr r1, [r0]
++ cmp r1, #0x3
++ beq MCLK2X_Phase_CBR_Done_DDR2
++ b MCLK2X_Phase_CBR_Done_DDR3
++
++/******************************************************************************
++ MCLK2X lock to MCLK program
++ r0 - r3 = free
++ r5 = madjmax
++ r6 = dllend
++ 0x1E720200 = 0x96cnt:failcnt:dllmax:dllmin
++ ******************************************************************************/
++CBRDLL1_2300_Start:
++ ldr r0, =0x1e6e0064
++ ldr r5, [r0]
++ and r5, r5, #0xFF @ init madjmax
++ mov r6, r5 @ init dllend
++
++ ldr r1, =0x000000ff
++ ldr r0, =0x1e720200
++ str r1, [r0] @ init dllcnt2:dllmax:dllmin
++
++ mov r3, #0x0 @ init loop count
++cbrdll1_scan_start:
++ cmp r3, r6
++ bge cbrdll1_scan_end
++
++ ldr r0, =0x1e6e0018
++ ldr r1, =0x00008120
++ str r1, [r0]
++
++ ldr r0, =0x1e6e0068
++ mov r1, r3
++ cmp r1, r5
++ subge r1, r1, r5
++ str r1, [r0]
++
++ ldr r0, =0x1e6e0000 @ dummy read
++ ldr r1, [r0]
++
++ ldr r0, =0x1e6e0018
++ ldr r1, =0x00000120
++ str r1, [r0]
++
++ ldr r0, =0x1e6e0000 @ dummy read
++ ldr r1, [r0]
++ ldr r0, =0x1e6e0000 @ dummy read
++ ldr r1, [r0]
++
++ ldr r0, =0x1e6e001c
++ ldr r1, [r0]
++ mov r1, r1, lsr #16
++ and r1, r1, #0xFF
++
++ and r2, r1, #0x96
++ cmp r2, #0x96
++ beq cbrdll1_scan_pass @ if (mclk2x_phase & 0x96) == 0x96
++ ldr r0, =0x1e720200
++ ldr r1, [r0]
++ mov r2, r1, lsr #8
++ ands r2, r2, #0xFF @ get dllmax
++ beq cbrdll1_scan_next @ if dllmax == 0
++ mov r2, r1, lsr #16
++ and r2, r2, #0xFF
++ add r2, r2, #0x01
++ cmp r2, #0x02
++ movge r6, r3
++ bic r1, r1, #0x00FF0000
++ orr r1, r1, r2, lsl #16
++ str r1, [r0]
++ b cbrdll1_scan_next
++
++cbrdll1_scan_pass:
++ cmp r3, #0x0 @ if dll = 0
++ moveq r3, #0x0F
++ addeq r6, r6, #0x10
++ beq cbrdll1_scan_next
++ ldr r0, =0x1e720200
++ ldr r2, [r0]
++ cmp r1, #0x96
++ bne cbrdll1_scan_pass2
++ mov r1, r2, lsr #24
++ add r1, r1, #0x01
++ bic r2, r2, #0xFF000000
++ orr r2, r2, r1, lsl #24
++ cmp r1, #0x03 @ check (phase == 0x96) count == 3
++ bicge r2, r2, #0x0000FF00
++ bicge r2, r2, #0x000000FF
++ orrge r2, r2, r3, lsl #8
++ orrge r2, r2, r3
++ str r2, [r0]
++ bge cbrdll1_scan_end
++
++cbrdll1_scan_pass2:
++ and r1, r2, #0xFF @ if(dllmin > dll)
++ cmp r1, r3
++ bicgt r2, r2, #0x000000FF
++ orrgt r2, r2, r3
++
++ mov r1, r2, lsr #8 @ if(dllmax < dll)
++ and r1, r1, #0xFF
++ cmp r1, r3
++ biclt r2, r2, #0x0000FF00
++ orrlt r2, r2, r3, lsl #8
++
++ bic r2, r2, #0x00FF0000
++ str r2, [r0]
++
++cbrdll1_scan_next:
++ add r3, r3, #0x01
++ b cbrdll1_scan_start
++
++cbrdll1_scan_end:
++ ldr r0, =0x1e720200
++ ldr r1, [r0]
++ mov r2, r1, lsr #8 @ get dllmax
++ ands r2, r2, #0xFF
++ bne cbrdll1_scan_done @ if(dllmax != 0)
++ ldr r0, =0x1e6e0064
++ ldr r3, [r0]
++ bic r1, r3, #0x000C0000
++ str r1, [r0]
++ add r0, r0, #0x04
++ mov r1, #0x0
++ str r1, [r0]
++
++ /* Delay about 10us */
++ ldr r2, =0x0000000A @ Set Timer3 Reload = 10 us
++ init_delay_timer
++delay0_1:
++ check_delay_timer
++ bne delay0_1
++ clear_delay_timer
++ /* end delay 10us */
++
++ ldr r0, =0x1e6e0064
++ str r3, [r0]
++
++ /* Delay about 10us */
++ ldr r2, =0x0000000A @ Set Timer3 Reload = 10 us
++ init_delay_timer
++delay0_2:
++ check_delay_timer
++ bne delay0_2
++ clear_delay_timer
++ /* end delay 10us */
++
++ b CBRDLL1_2300_Start
++
++cbrdll1_scan_done:
++ and r1, r1, #0xFF
++ add r1, r1, r2
++ mov r6, r1, lsr #1 @ dll1.0 = (dllmin + dllmax) >> 1
++ cmp r6, r5
++ subge r6, r6, r5
++ add r3, r6, r5, lsr #2 @ dll1.1 = dll1.0 + (MADJ >> 2)
++
++ ldr r0, =0x1e6e0004
++ ldr r1, [r0]
++ mov r1, r1, lsr #10
++ tst r1, #0x1
++ bne cbrdll1_scan_set_2400
++ cmp r3, r5
++ subge r3, r3, r5
++ mov r2, #0x0
++ tst r3, #0x08
++ beq cbrdll1_scan_set_2300_2 @ if !(dll & 8)
++cbrdll1_scan_set_2300_1: @ if (dll & 8)
++ mov r1, #0x0
++ tst r3, #0x08
++ addeq r1, r1, #0x01
++ cmp r2, #0x05
++ addge r1, r1, #0x01
++ cmp r1, #0x02
++ beq cbrdll1_scan_set
++ add r2, r2, #0x01
++ add r3, r3, #0x01
++ cmp r3, r5
++ subge r3, r3, r5
++ b cbrdll1_scan_set_2300_1
++
++cbrdll1_scan_set_2300_2:
++ and r1, r3, #0x07
++ cmp r1, #0x07
++ beq cbrdll1_scan_set
++ cmp r2, #0x05
++ bge cbrdll1_scan_set
++ add r2, r2, #0x01
++ add r3, r3, #0x01
++ cmp r3, r5
++ subge r3, r3, r5
++ b cbrdll1_scan_set_2300_2
++
++cbrdll1_scan_set_2400:
++ add r3, r3, #0x05 @ dll1.1 = dll1.0 + (MADJ >> 2) + 5
++ cmp r3, r5
++ subge r3, r3, r5
++
++cbrdll1_scan_set:
++ orr r1, r6, r3, lsl #8
++ ldr r0, =0x1e6e0068
++ str r1, [r0]
++
++ ldr r0, =0x1e6e0120
++ ldr r1, [r0]
++ cmp r1, #0x0
++ beq MCLK2X_Phase_CBR_Done_DDR3
++ cmp r1, #0x1
++ beq MCLK2X_Phase_CBR_Done_DDR2
++ b CBRDLL1_2400_Call
++
++.LTORG
++
++/******************************************************************************
++ Calibration Code Start
++ SRAM buffer definition
++ 0x1E720000 : Pass 1, DLLI MIN value range
++ 0x1E720008 : DQS0 DLL valid range, 2nd time CBR
++ 0x1E72000C : DQS1 DLL valid range, 2nd time CBR
++ 0x1E720010 : DQ0 DLL valid range, Pass 1
++ 0x1E720014 : DQ1 DLL valid range, Pass 1
++ ....
++ 0x1E720048 : DQ14 DLL valid range, Pass 1
++ 0x1E72004C : DQ15 DLL valid range, Pass 1
++ 0x1E720090 : DLL1 SAdj record
++ 0x1E720094 : DQL Pass1 finetune result
++ 0x1E720098 : DQH Pass1 finetune result
++ 0x1E72009C : DRAM initial time, (us)
++ 0x1E7200A0 : CBR3 retry counter
++ 0x1E7200A4 : DRAM initial time, (us)
++ 0x1E7200A8 : Released date
++ 0x1E7200AC : Released SDK version
++ 0x1E7200B0 : DQS input mask window for MCR18[4] = 0
++ 0x1E7200B4 : DQS input mask window for MCR18[4] = 1
++ 0x1E720100 : DQIDLY=00, DLL valid range
++ 0x1E720104 : DQIDLY=01, DLL valid range
++ ....
++ 0x1E720178 : DQIDLY=30, DLL valid range
++ 0x1E72017C : DQIDLY=31, DLL valid range
++ 0x1E720180 : DQSI-MCLK2X P-phase pass record DLL2= 0-31
++ 0x1E720184 : DQSI-MCLK2X P-phase pass record DLL2=32-63
++ 0x1E720188 : DQSI-MCLK2X N-phase pass record DLL2= 0-31
++ 0x1E72018C : DQSI-MCLK2X N-phase pass record DLL2=32-63
++ ******************************************************************************/
++Calibration_Start_pre: @ Toggle DQSI mask delay
++ ldr r0, =0x1e6e0018
++ ldr r1, [r0]
++ eor r1, r1, #0x10
++ str r1, [r0]
++
++Calibration_Start:
++/* Init SRAM buffer */
++ ldr r1, =0x000000ff
++ ldr r0, =0x1e720000
++ ldr r2, =0x1e720100
++init_sram_start:
++ str r1, [r0]
++ add r0, r0, #4
++ cmp r0, r2
++ blt init_sram_start
++
++ ldr r1, =0x00ff00ff
++ ldr r0, =0x1e720100
++ ldr r2, =0x1e720180
++init_sram_start2:
++ str r1, [r0]
++ add r0, r0, #4
++ cmp r0, r2
++ blt init_sram_start2
++
++ ldr r1, =0x00000000
++ ldr r0, =0x1e720180
++ ldr r2, =0x1e720200
++init_sram_start3:
++ str r1, [r0]
++ add r0, r0, #4
++ cmp r0, r2
++ blt init_sram_start3
++
++ ldr r0, =0x1e6e0068 @ save the DLL1 SAdj initial value
++ ldr r1, [r0]
++ ldr r0, =0x1e720090
++ str r1, [r0]
++
++/* Start
++ r0 = free
++ r1 = free
++ r2 = free
++ r3 = free
++ r4 = record the return pc value, do not use
++ r5 = pattern table index
++ r6 = pass count
++ r7 = dram DLL2 parameter index (0x1e6e0068), max is 0x4C
++*/
++/******************************************************************************
++ Fine DQI delay and DQSI-MCLK phase
++ r8 = DQIDLY count
++ r9 = DQSI-MCLK2X phase count
++ r10 = pattern fail retry counter, initialize to 2 (fail 2 times)
++ r11 = passcnt accumulator for each DQIDLY
++ *****************************************************************************/
++CBR0_START:
++/* Debug - UART console message */
++ ldr r0, =0x1e784000
++ mov r1, #0x43 @ 'C'
++ str r1, [r0]
++ mov r1, #0x42 @ 'B'
++ str r1, [r0]
++ mov r1, #0x52 @ 'R'
++ str r1, [r0]
++ mov r1, #0x30 @ '0'
++ str r1, [r0]
++ mov r1, #0x2D @ '-'
++ str r1, [r0]
++/* Debug - UART console message */
++
++ ldr r0, =0x1e6e0018
++ ldr r1, [r0]
++ bic r1, r1, #0xFF000000
++ bic r1, r1, #0x00FF0000
++ str r1, [r0]
++
++ ldr r0, =0x1e6e0074 @ set the testing DRAM size = 1KB
++ ldr r1, =0x000003FF
++ str r1, [r0]
++
++ mov r8, #0x00 @ init DQIDLY
++ mov r9, #0x00 @ init DQSI-MCLK2X phase
++ mov r11, #0x01 @ init passcnt accumulator
++
++cbr0_next_dqidly:
++ cmp r9, #0x00
++ bne cbr0_next_dqsiphase
++ cmp r11, #0x00
++ addeq r8, r8, #0x01 @ jump 1 stage if no pass at previous stage
++ mov r11, #0x00
++ add r8, r8, #0x01
++ cmp r8, #0x1F @ max DQIDLY = 31
++ bgt CBR0_END
++
++/* Debug - UART console message */
++ ldr r0, =0x1e784000
++ and r1, r8, #0x07
++ add r1, r1, #0x30 @ '0-7'
++ str r1, [r0]
++/* Debug - UART console message */
++
++ ldr r0, =0x1e6e0018
++ ldr r1, [r0]
++ bic r1, r1, #0x00FF0000
++ orr r1, r1, r8, lsl #16
++ str r1, [r0]
++ mov r9, #0x01 @ '1':p_phase, '0':n_phase
++
++ /* Delay about 3us */ @ wait DQIDLY load
++ ldr r2, =0x00000003 @ Set Timer4 Reload = 3 us
++ init_delay_timer
++delay_4:
++ check_delay_timer
++ bne delay_4
++ clear_delay_timer
++ /* end delay 3us */
++
++ b cbr0_dll2_scan_start
++
++cbr0_next_dqsiphase:
++ ldr r0, =0x1e6e0018
++ ldr r1, [r0]
++ orr r1, r1, r9, lsl #23 @ set DQSI-MCLK2X phase
++ str r1, [r0]
++ mov r9, #0x00
++
++cbr0_dll2_scan_start:
++ mov r6, #0x00 @ init pass count
++ mov r7, #0x00 @ init DLL2 parameter index
++
++/****************************
++ DLL2 delay margin test loop
++ ***************************/
++cbr0_next_dll2_parameter:
++ ldr r0, =0x1e6e0068 @ load DLL2 parameter
++ ldr r1, [r0]
++ bic r1, r1, #0x00FF0000
++ bic r1, r1, #0xFF000000
++ orr r1, r1, r7, lsl #16
++ str r1, [r0]
++ ldr r2, =0x40404040 @ DLL2 max is 0x40404040
++ cmp r7, r2
++ bge cbr0_next_dqidly
++ ldr r2, =0x01010101
++ add r7, r7, r2
++
++/* CBRScan3() start */
++ adrl r5, PATTERN_TABLE @ init pattern table index
++/****************************
++ Test pattern iteration loop
++ ***************************/
++cbr0_next_test_pattern:
++ mov r10, #2 @ set the retry loop = 2 of each pattern
++ ldr r1, [r5] @ load test pattern
++ ldr r0, =0x1e6e007c
++ str r1, [r0]
++ cmp r1, #0x00 @ the last data in pattern is 0x00
++ bne cbr0_test_burst
++
++ and r3, r7, #0xFF
++ sub r3, r3, #0x01 @ we add 1 after loop check so we need to decrease 1
++ cmp r3, #0x00
++ beq cbr0_next_dqidly @ pass at dlli = 0, invalid
++ add r6, r6, #0x01 @ increment pass count
++ add r11, r11, #0x01 @ increment pass count
++
++ ldr r0, =0x1e720180 @ record DLL2 pass window
++ cmp r9, #0x00 @ DQSI-MCLK2X phase check
++ addeq r0, r0, #0x08
++ cmp r3, #32
++ addge r0, r0, #0x4
++ and r1, r3, #0x1F
++ mov r2, #0x1
++ mov r2, r2, lsl r1
++ ldr r1, [r0]
++ orr r1, r1, r2
++ str r1, [r0]
++
++ ldr r0, =0x1e720100 @ record DLL2 min:max value for each DQIDLY
++ add r0, r0, r8, lsl #2
++ cmp r9, #0x00 @ DQSI-MCLK2X phase check
++ beq cbr0_test_pass_dqsin
++ record_dll2_pass_range
++ b cbr0_next_dll2_parameter
++
++cbr0_test_pass_dqsin:
++ record_dll2_pass_range_h
++ b cbr0_next_dll2_parameter
++
++cbr0_test_pattern_fail:
++ cmp r6, #5 @ passcnt >= 5
++ bge cbr0_next_dqidly
++ ldr r0, =0x1e720100 @ reset DLL2 min:max value
++ add r0, r0, r8, lsl #2
++ ldr r1, [r0]
++ ldr r2, =0xFFFF0000
++ ldr r3, =0x000000FF
++ cmp r9, #0x00
++ moveq r2, r2, lsr #16
++ moveq r3, r3, lsl #16
++ and r1, r1, r2
++ orr r1, r1, r3
++ str r1, [r0]
++ b cbr0_next_dll2_parameter @ CBRScan3() end and test result fail, go to next step
++
++/****************************
++ Test fail retry loop
++ ***************************/
++cbr0_pattern_fail_retry:
++
++/* CBRTest3() start */
++cbr0_test_burst:
++ ldr r0, =0x1e6e0070
++ ldr r1, =0x00000000
++ str r1, [r0]
++ ldr r1, =0x000000C1
++ str r1, [r0]
++ ldr r3, =0x3000
++cbr0_wait_engine_idle_0:
++ ldr r2, [r0]
++ tst r2, r3 @ D[12] = idle bit
++ beq cbr0_wait_engine_idle_0
++
++ ldr r2, [r0] @ read fail bit status
++ mov r1, #0x0
++ str r1, [r0]
++ mov r2, r2, lsr #13 @ D[13] = fail bit
++ cmp r2, #0x00
++ bne cbr0_test_fail
++
++cbr0_test_single:
++ ldr r0, =0x1e6e0070
++ ldr r1, =0x00000000
++ str r1, [r0]
++ ldr r1, =0x00000085
++ str r1, [r0]
++ ldr r3, =0x3000
++cbr0_wait_engine_idle_1:
++ ldr r2, [r0]
++ tst r2, r3 @ D[12] = idle bit
++ beq cbr0_wait_engine_idle_1
++
++ ldr r2, [r0] @ read fail bit status
++ mov r1, #0x0
++ str r1, [r0]
++ mov r2, r2, lsr #13 @ D[13] = fail bit
++ cmp r2, #0x00
++ beq cbr0_test_pass
++
++/* CBRTest3() end */
++
++cbr0_test_fail:
++ subs r10, r10, #1
++ bne cbr0_pattern_fail_retry
++ b cbr0_test_pattern_fail @ CBRScan3() return(0)
++
++cbr0_test_pass:
++ add r5, r5, #0x04 @ increase the test pattern index
++ b cbr0_next_test_pattern
++
++CBR0_END:
++ mov r5, #0x0 @ init DQIDLY search count
++ mov r6, #0x0 @ init max_margin:g_margin
++ mov r8, #0x0 @ init g_side
++ mov r7, #0x0 @ init maximum margin DQIDLY,DQSI-MCLK2X phase
++cbr0_search_dll_margin_s:
++ ldr r0, =0x1e720100
++ add r0, r0, r5, lsl #2
++ ldr r1, [r0]
++ and r2, r1, #0xFF @ get dllmin_p
++ mov r1, r1, lsr #8
++ and r3, r1, #0xFF @ get dllmax_p
++ subs r2, r3, r2 @ get margin-P
++ movmi r2, #0x0
++ mov r1, r1, lsr #8
++ and r3, r1, #0xFF @ get dllmin_n
++ mov r1, r1, lsr #8
++ and r1, r1, #0xFF @ get dllmax_n
++ subs r3, r1, r3 @ get margin-N
++ movmi r3, #0x0
++ add r1, r2, r3
++ cmp r1, #0x0
++ beq cbr0_search_dll_margin_e @ if margin-P = 0 && margin-N = 0
++
++ ldr r9, [r0]
++ ldr r0, =0x1e720180
++ cmp r2, r3
++ orrlt r5, r5, #0x80 @ margin-N > margin-P
++ addlt r0, r0, #0x08
++ movlt r9, r9, lsr #16
++ movge r3, r2 @ max(margin-P/N)
++ add r2, r3, #0x2 @ define +/- 2 steps of variation
++ mov r1, r6, lsr #16
++ cmp r2, r1
++ blt cbr0_search_dll_margin_e @ if max(margin-P/N) + 2 < max_margin
++
++ and r1, r9, #0xFF @ r1 = dlli counter
++ cmp r1, #32
++ ldrge r2, [r0, #0x4] @ load pass window
++ ldrlt r2, [r0]
++ and r1, r1, #0x1F
++ mov r10, #0x1 @ init test bit mask
++ mov r10, r10, lsl r1
++ and r1, r9, #0xFF
++cbr0_search_dllmin_margin_s:
++ tst r2, r10
++ beq cbr0_search_dllmin_margin_e
++ mov r10, r10, lsr #1
++ cmp r1, #32
++ ldreq r2, [r0]
++ ldreq r10, =0x80000000
++ subs r1, r1, #0x1
++ bne cbr0_search_dllmin_margin_s
++
++cbr0_search_dllmin_margin_e:
++ and r2, r9, #0xFF
++ sub r11, r2, r1 @ get dllmin side margin
++
++ mov r9, r9, lsr #8
++ and r1, r9, #0xFF @ r1 = dlli counter
++ cmp r1, #32
++ ldrge r2, [r0, #0x4] @ load pass window
++ ldrlt r2, [r0]
++ and r1, r1, #0x1F
++ mov r10, #0x1 @ init test bit mask
++ mov r10, r10, lsl r1
++ and r1, r9, #0xFF
++cbr0_search_dllmax_margin_s:
++ tst r2, r10
++ beq cbr0_search_dllmax_margin_e
++ mov r10, r10, lsl #1
++ cmp r1, #31
++ ldreq r2, [r0, #0x4]
++ ldreq r10, =0x00000001
++ add r1, r1, #0x1
++ cmp r1, #64
++ bne cbr0_search_dllmax_margin_s
++
++cbr0_search_dllmax_margin_e:
++ and r2, r9, #0xFF
++ sub r1, r1, r2 @ get dllmax side margin
++ cmp r1, r11
++ movlt r11, r1 @ get side_margin
++
++cbr0_check_dll_margin: @ if max(margin-P/N) > g_margin && side_margin >= g_side && dqidly <= 20
++ cmp r5, #20
++ bgt cbr0_check_dll_margin2
++ and r1, r6, #0xFF
++ cmp r3, r1
++ ble cbr0_check_dll_margin3
++ cmp r11, r8
++ bge cbr0_set_dll_margin
++
++cbr0_check_dll_margin2: @ if max(margin-P/N) > g_margin+1 && side_margin >= g_side)
++ and r1, r6, #0xFF
++ add r2, r1, #0x1
++ cmp r3, r2
++ ble cbr0_check_dll_margin3
++ cmp r11, r8
++ bge cbr0_set_dll_margin
++
++cbr0_check_dll_margin3: @ if side_margin > g_side && g_side < 8
++ cmp r8, #8
++ bge cbr0_search_dll_margin_e
++ cmp r11, r8
++ ble cbr0_search_dll_margin_e
++
++cbr0_set_dll_margin:
++ mov r1, r6, lsr #16
++ cmp r3, r1
++ bicgt r6, r6, #0x00FF0000
++ orrgt r6, r6, r3, lsl #16
++ bic r6, r6, #0x000000FF
++ orr r6, r6, r3
++ mov r7, r5
++ mov r8, r11
++
++cbr0_search_dll_margin_e:
++ and r5, r5, #0x7F
++ add r5, r5, #0x01
++ cmp r5, #0x20 @ last DQIDLY
++ blt cbr0_search_dll_margin_s
++
++ ldr r0, =0x1e6e0018
++ ldr r1, [r0]
++ bic r1, r1, #0x00FF0000
++ orr r1, r1, r7, lsl #16
++ str r1, [r0]
++
++ ldr r0, =0x1e6e0068
++ ldr r1, [r0]
++ bic r1, r1, #0x00FF0000
++ bic r1, r1, #0xFF000000
++ str r1, [r0]
++
++ /* Delay about 5us */
++ ldr r2, =0x00000005 @ Set Timer5 Reload = 5 us
++ init_delay_timer
++delay_5:
++ check_delay_timer
++ bne delay_5
++ clear_delay_timer
++ /* end delay 5us */
++
++ ldr r0, =0x1e6e000c @ Set refresh cycle
++ ldr r1, =0x00005C01
++ str r1, [r0]
++
++/******************************************************************************
++ Fine tune per bit DQ input delay -- Pass 1, left edge align
++ r8 = free
++ r9 = DQ fail bit accumulator
++ r10 = pattern fail counter, initialize to 5 (fail 5 times)
++ r11 = free
++ *****************************************************************************/
++CBR1_START:
++/* Debug - UART console message */
++ ldr r0, =0x1e784000
++ mov r1, #0x0D @ '\r'
++ str r1, [r0]
++ mov r1, #0x0A @ '\n'
++ str r1, [r0]
++ mov r1, #0x43 @ 'C'
++ str r1, [r0]
++ mov r1, #0x42 @ 'B'
++ str r1, [r0]
++ mov r1, #0x52 @ 'R'
++ str r1, [r0]
++ mov r1, #0x31 @ '1'
++ str r1, [r0]
++/* Debug - UART console message */
++
++ mov r6, #0x00 @ init pass count
++ mov r7, #0x00 @ init DLL2 parameter index
++
++/****************************
++ DLL2 delay margin test loop
++ ***************************/
++cbr1_next_dll2_parameter:
++ ldr r0, =0x1e6e0068 @ load DLL2 parameter
++ ldr r1, [r0]
++ bic r1, r1, #0x00FF0000
++ bic r1, r1, #0xFF000000
++ orr r1, r1, r7, lsl #16
++ str r1, [r0]
++ ldr r2, =0x40404040 @ parameter's max is to 0x40404040
++ cmp r7, r2
++ bge CBR1_END
++ ldr r2, =0x01010101
++ add r7, r7, r2
++
++ ldr r0, =0x1e6e0074 @ set the testing DRAM size = 4KB
++ ldr r1, =0x00000FFF
++ str r1, [r0]
++
++/* CBRScan2() start */
++ ldr r9, =0xFFFF @ init test status
++ adrl r5, PATTERN_TABLE @ init pattern table index
++/****************************
++ Test pattern iteration loop
++ ***************************/
++cbr1_next_test_pattern:
++ mov r10, #5 @ set the retry loop of each pattern
++ ldr r1, [r5] @ load test pattern
++ ldr r0, =0x1e6e007c
++ str r1, [r0]
++ cmp r1, #0x00 @ the last data in pattern is 0x00
++ bne cbr1_test_single
++
++cbr1_test_pattern_end:
++ cmp r9, #0x00
++ bne cbr1_test_pass_dqi
++ cmp r6, #10
++ bge CBR1_END
++ b cbr1_next_dll2_parameter @ CBRScan2() end and test result fail, go to next step
++
++cbr1_test_pass_dqi:
++ and r3, r7, #0xFF
++ sub r3, r3, #0x01 @ we add 1 after loop check so we need to decrease 1
++ add r6, r6, #0x01 @ increment pass count
++ ldr r0, =0x1e720010
++ mov r8, #0x01
++cbr1_test_pass_dqi_loop_s:
++ tst r9, r8
++ beq cbr1_test_pass_dqi_loop_e
++ record_dll2_pass_range
++
++cbr1_test_pass_dqi_loop_e:
++ add r0, r0, #0x04
++ mov r8, r8, lsl #1
++ ldr r1, =0xFFFF
++ tst r8, r1
++ bne cbr1_test_pass_dqi_loop_s
++ b cbr1_next_dll2_parameter
++
++/****************************
++ Test fail retry loop
++ ***************************/
++cbr1_pattern_fail_retry:
++
++/* CBRTest2() start */
++cbr1_test_single:
++ ldr r0, =0x1e6e0070
++ ldr r1, =0x00000000
++ str r1, [r0]
++ ldr r1, =0x00000005
++ str r1, [r0]
++ ldr r3, =0x1000
++ ldr r1, =0x1000
++cbr1_wait_engine_idle_0:
++ subs r1, r1, #1
++ beq cbr1_test_single_end
++ ldr r2, [r0]
++ tst r2, r3 @ D[12] = idle bit
++ beq cbr1_wait_engine_idle_0
++
++cbr1_test_single_end:
++ ldr r0, =0x1e6e0078 @ read fail bit status
++ ldr r11, [r0]
++ orr r11, r11, r11, lsr #16
++ bic r11, r11, #0xFF000000
++ bic r11, r11, #0x00FF0000
++
++ ldr r1, =0xFFFF
++ cmp r11, r1
++ beq cbr1_test_fail
++
++cbr1_test_burst:
++ ldr r0, =0x1e6e0070
++ ldr r2, =0x00000000
++ str r2, [r0]
++ ldr r2, =0x00000041
++ str r2, [r0]
++ ldr r3, =0x1000
++ ldr r1, =0x1000
++cbr1_wait_engine_idle_1:
++ subs r1, r1, #1
++ beq cbr1_test_burst_end
++ ldr r2, [r0]
++ tst r2, r3 @ D[12] = idle bit
++ beq cbr1_wait_engine_idle_1
++
++cbr1_test_burst_end:
++ ldr r0, =0x1e6e0078 @ read fail bit status
++ ldr r2, [r0]
++ orr r2, r2, r2, lsr #16
++ bic r2, r2, #0xFF000000
++ bic r2, r2, #0x00FF0000
++ orr r11, r11, r2
++
++ ldr r2, =0xFFFF
++ cmp r11, r2
++ bne cbr1_test_pass
++/* CBRTest2() end */
++
++cbr1_test_fail:
++ subs r10, r10, #1
++ bne cbr1_pattern_fail_retry
++ mov r9, #0x00
++ b cbr1_test_pattern_end @ CBRScan2() return(0)
++
++cbr1_test_pass:
++ ldr r1, =0xFFFF @ record the pass bit
++ eor r11, r11, r1
++ and r9, r9, r11 @ DQ pass bit
++ cmp r9, #0x00
++ beq cbr1_test_pattern_end @ CBRScan2() return(0)
++
++ add r5, r5, #0x04 @ increase the test pattern index
++ b cbr1_next_test_pattern
++
++CBR1_END:
++ mov r5, #0x0 @ init DQ DLL_min sum
++ mov r6, #0x0 @ init DQ DLL_min valid count
++ ldr r0, =0x1e72000c
++ ldr r3, =0x1e720050
++cbr1_search_dllmin_s:
++ add r0, r0, #0x04
++ cmp r0, r3
++ beq cbr1_search_dllmin_e
++ ldr r1, [r0]
++ mov r2, r1, lsr #8
++ and r2, r2, #0xFF @ get dllmax
++ and r1, r1, #0xFF @ get dllmin
++ subs r2, r2, r1 @ dllmax - dllmin
++ bmi cbr1_search_dllmin_s @ no valid margin found, bypass fine tune
++ cmp r2, #10 @ (dllmax - dllmin) < 10
++ blt cbr1_search_dllmin_s @ no enough margin found, bypass fine tune
++ add r5, r5, r1
++ add r6, r6, #1
++ b cbr1_search_dllmin_s
++
++cbr1_search_dllmin_e:
++ cmp r6, #16
++ bne Calibration_Start_pre @ not all bits valid, retry again
++
++ mov r5, r5, lsr #4
++ ldr r0, =0x1e720000
++ str r5, [r0]
++
++ mov r6, #0x00 @ init DQL CBR value
++ ldr r0, =0x1e720030
++ ldr r7, =0x1e72000c
++cbr1_set_result_dql:
++ sub r0, r0, #4
++ cmp r0, r7
++ beq cbr1_set_result_next
++ mov r6, r6, lsl #3
++ ldr r1, [r0]
++ mov r2, r1, lsr #8
++ and r2, r2, #0xFF @ get dllmax
++ and r1, r1, #0xFF @ get dllmin
++ mov r3, r1 @ dll = dllmin
++ cmp r5, r3
++ blt cbr1_set_result_dql_neg
++ sub r1, r5, r3
++ mov r2, #19
++ mul r1, r2, r1
++ mov r1, r1, lsr #5 @ dqi_tune = ((gold_dll - dll) * 19) >> 5
++ cmp r1, #2 @ dqi_tune max = 2
++ movgt r1, #2
++ orr r6, r6, r1
++ b cbr1_set_result_dql
++
++cbr1_set_result_dql_neg:
++ sub r1, r3, r5
++ mov r2, #19
++ mul r1, r2, r1
++ mov r1, r1, lsr #5 @ dqi_tune = ((gold_dll - dll) * 19) >> 5
++ cmp r1, #2 @ dqi_tune max = -2
++ movgt r1, #2
++ mov r2, #8
++ sub r1, r2, r1
++ and r1, r1, #7
++ orr r6, r6, r1
++ b cbr1_set_result_dql
++
++cbr1_set_result_next:
++ ldr r0, =0x1e6e0080 @ save DQL fine tune result
++ str r6, [r0]
++ ldr r0, =0x1e720094
++ str r6, [r0]
++
++ mov r6, #0x00 @ init DQH CBR value
++ ldr r0, =0x1e720050
++ ldr r7, =0x1e72002c
++cbr1_set_result_dqh:
++ sub r0, r0, #4
++ cmp r0, r7
++ beq cbr1_set_result_end
++ mov r6, r6, lsl #3
++ ldr r1, [r0]
++ mov r2, r1, lsr #8
++ and r2, r2, #0xFF @ get dllmax
++ and r1, r1, #0xFF @ get dllmin
++ mov r3, r1 @ dll = dllmin
++ cmp r5, r3
++ blt cbr1_set_result_dqh_neg
++ sub r1, r5, r3
++ mov r2, #19
++ mul r1, r2, r1
++ mov r1, r1, lsr #5 @ dqi_tune = ((gold_dll - dll) * 19) >> 5
++ cmp r1, #3 @ dqi_tune max = 2
++ movgt r1, #3
++ subs r1, r1, #1
++ movmi r1, #7
++ orr r6, r6, r1
++ b cbr1_set_result_dqh
++
++cbr1_set_result_dqh_neg:
++ sub r1, r3, r5
++ mov r2, #19
++ mul r1, r2, r1
++ mov r1, r1, lsr #5 @ dqi_tune = ((gold_dll - dll) * 19) >> 5
++ add r1, r1, #1
++ cmp r1, #2 @ dqi_tune max = -2
++ movgt r1, #2
++ mov r2, #8
++ sub r1, r2, r1
++ and r1, r1, #7
++ orr r6, r6, r1
++ b cbr1_set_result_dqh
++
++cbr1_set_result_end:
++ ldr r0, =0x1e6e0084 @ save DQH fine tune result
++ str r6, [r0]
++ ldr r0, =0x1e720098
++ str r6, [r0]
++
++/******************************************************************************
++ Search the DLL2 detail margin
++ *****************************************************************************/
++ ldr r0, =0x1e7200a0
++ mov r1, #0
++ str r1, [r0]
++
++CBR3_START:
++/* Debug - UART console message */
++ ldr r0, =0x1e784000
++ mov r1, #0x33 @ '3'
++ str r1, [r0]
++/* Debug - UART console message */
++
++ mov r6, #0x00 @ init pass count
++ mov r7, #0x00 @ init DLL2 parameter index
++ ldr r1, =0x000000ff
++ ldr r0, =0x1e720008 @ init DQL dllmax,dllmin
++ str r1, [r0]
++ ldr r0, =0x1e72000c @ init DQH dllmax,dllmin
++ str r1, [r0]
++
++ ldr r0, =0x1e7200a0 @ CBR3 iteration counter
++ ldr r1, [r0]
++ add r1, r1, #1
++ str r1, [r0]
++
++/****************************
++ DLL2 delay margin test loop
++ ***************************/
++cbr3_next_dll2_parameter:
++ ldr r0, =0x1e6e0068 @ load DLL2 parameter
++ ldr r1, [r0]
++ bic r1, r1, #0x00FF0000
++ bic r1, r1, #0xFF000000
++ orr r1, r1, r7, lsl #16
++ str r1, [r0]
++ ldr r2, =0x40404040 @ parameter's max is to 0x40404040
++ cmp r7, r2
++ bge CBR3_END
++ ldr r2, =0x01010101
++ add r7, r7, r2
++
++ ldr r0, =0x1e6e0074 @ set the testing DRAM size = 64KB
++ ldr r1, =0x0000FFFF
++ str r1, [r0]
++
++/* CBRScan() start */
++ mov r9, #0x03 @ init test status
++ adrl r5, PATTERN_TABLE @ init pattern table index
++/****************************
++ Test pattern iteration loop
++ ***************************/
++cbr3_next_test_pattern:
++ mov r10, #5 @ set the retry loop of each pattern
++ ldr r1, [r5] @ load test pattern
++ ldr r0, =0x1e6e007c
++ str r1, [r0]
++ cmp r1, #0x00 @ the last data in pattern is 0x00
++ bne cbr3_test_single
++
++cbr3_test_pattern_end:
++ cmp r9, #0x00
++ bne cbr3_test_pass_dql
++ cmp r6, #10
++ bge CBR3_END
++ b cbr3_next_dll2_parameter @ CBRScan() end and test result fail, go to next step
++
++cbr3_test_pass_dql:
++ and r3, r7, #0xFF
++ sub r3, r3, #0x01 @ we add one after loop check so we need to decrease 1
++ add r6, r6, #0x01 @ increment pass count
++ tst r9, #0x01
++ beq cbr3_test_pass_dqh
++
++ ldr r0, =0x1E720008
++ record_dll2_pass_range
++
++cbr3_test_pass_dqh:
++ tst r9, #0x02
++ beq cbr3_next_dll2_parameter
++ ldr r0, =0x1E72000c
++ record_dll2_pass_range
++ b cbr3_next_dll2_parameter
++
++/****************************
++ Test fail retry loop
++ ***************************/
++cbr3_pattern_fail_retry:
++
++/* CBRTest() start */
++cbr3_test_single:
++ ldr r0, =0x1e6e0070
++ ldr r1, =0x00000000
++ str r1, [r0]
++ ldr r1, =0x00000005
++ str r1, [r0]
++ ldr r3, =0x1000
++ ldr r8, =0x10000
++cbr3_wait_engine_idle_0:
++ subs r8, r8, #1
++ beq cbr3_test_single_end
++ ldr r2, [r0]
++ tst r2, r3 @ D[12] = idle bit
++ beq cbr3_wait_engine_idle_0
++
++cbr3_test_single_end:
++ ldr r0, =0x1e6e0078 @ read fail bit status
++ ldr r11, [r0]
++ orr r11, r11, r11, lsr #16
++ bic r11, r11, #0xFF000000
++ bic r11, r11, #0x00FF0000
++
++ ldr r1, =0xFF
++ tst r11, r1
++ beq cbr3_test_burst
++ tst r11, r1, lsl #8
++ bne cbr3_test_fail
++
++cbr3_test_burst:
++ mov r1, #0x00 @ initialize loop index, r1 is loop's index
++cbr3_test_burst_loop:
++ ldr r0, =0x1e6e0070
++ ldr r2, =0x00000000
++ str r2, [r0]
++ mov r2, r1, lsl #3
++ orr r2, r2, #0x41 @ test command = 0x41 | (datagen << 3)
++ str r2, [r0]
++ ldr r3, =0x1000
++ ldr r8, =0x10000
++cbr3_wait_engine_idle_1:
++ subs r8, r8, #1
++ beq cbr3_test_burst_end
++ ldr r2, [r0]
++ tst r2, r3 @ D[12] = idle bit
++ beq cbr3_wait_engine_idle_1
++
++cbr3_test_burst_end:
++ ldr r0, =0x1e6e0078 @ read fail bit status
++ ldr r2, [r0]
++ orr r2, r2, r2, lsr #16
++ bic r2, r2, #0xFF000000
++ bic r2, r2, #0x00FF0000
++ orr r11, r11, r2
++
++ ldr r2, =0xFF
++ tst r11, r2
++ beq cbr3_next_test_burst_mode
++ tst r11, r2, lsl #8
++ beq cbr3_next_test_burst_mode
++/* CBRTest() end */
++
++cbr3_test_fail:
++ subs r10, r10, #1
++ bne cbr3_pattern_fail_retry
++ mov r9, #0x00
++ b cbr3_test_pattern_end @ CBRScan() return(0)
++
++cbr3_next_test_burst_mode:
++ add r1, r1, #1 @ increase the test mode index
++ cmp r1, #0x08 @ there are 8 modes
++ bne cbr3_test_burst_loop
++
++ ldr r1, =0xFF @ record the pass byte
++ tst r11, r1
++ andne r9, r9, #0x02 @ DQL fail
++ tst r11, r1, lsl #8
++ andne r9, r9, #0x01 @ DQH fail
++ cmp r9, #0x00
++ beq cbr3_test_pattern_end @ CBRScan() return(0)
++
++ add r5, r5, #0x04 @ increase the test pattern index
++ b cbr3_next_test_pattern
++
++CBR3_END:
++ ldr r0, =0x1e72000c @ check DQH margin
++ ldr r1, [r0]
++ mov r2, r1, lsr #8
++ and r2, r2, #0xFF @ get dllmax
++ and r1, r1, #0xFF @ get dllmin
++ subs r5, r2, r1 @ dllmax - dllmin
++ bmi CBR3_START @ no valid margin found, retry again
++ cmp r5, #10 @ (dllmax - dllmin) < 10
++ blt CBR3_START @ no enough margin found, retry again
++ add r2, r1, r2 @ (dllmin[1] + dllmax[1] + 1) >> 1
++ add r2, r2, #0x01
++ mov r1, r2, lsr #1
++ mov r3, r1, lsl #8
++ ldr r1, [r0] @ store the dll search result
++ bic r1, r1, #0xFF000000
++ bic r1, r1, #0x00FF0000
++ orr r1, r1, r3, lsl #8
++ str r1, [r0]
++
++ ldr r0, =0x1e720008 @ check DQL margin
++ ldr r1, [r0]
++ mov r2, r1, lsr #8
++ and r2, r2, #0xFF @ get dllmax
++ and r1, r1, #0xFF @ get dllmin
++ subs r5, r2, r1 @ dllmax - dllmin
++ bmi CBR3_START @ no valid margin found, retry again
++ cmp r5, #10 @ (dllmax - dllmin) < 10
++ blt CBR3_START @ no enough margin found, retry again
++ add r2, r1, r2 @ (dllmin[0] + dllmax[0] + 1) >> 1
++ add r2, r2, #0x01
++ mov r1, r2, lsr #1
++ ldr r2, [r0] @ store the dll search result
++ bic r2, r2, #0xFF000000
++ bic r2, r2, #0x00FF0000
++ orr r2, r2, r1, lsl #16
++ str r2, [r0]
++ orr r3, r3, r1
++
++ ldr r0, =0x1e6e0068 @ save the result dll value
++ ldr r1, [r0]
++ bic r1, r1, #0xFF000000
++ bic r1, r1, #0x00FF0000
++ orr r1, r1, r3, lsl #16
++ str r1, [r0]
++ b CBR4_START
++
++.LTORG
++
++/******************************************************************************
++ Search the DQS input mask margin
++ *****************************************************************************/
++CBR4_START:
++/* Debug - UART console message */
++ ldr r0, =0x1e784000
++ mov r1, #0x34 @ '4'
++ str r1, [r0]
++/* Debug - UART console message */
++
++ ldr r0, =0x1e6e0074 @ set the testing DRAM size = 4KB
++ ldr r1, =0x00000FFF
++ str r1, [r0]
++
++ mov r8, #0x00 @ init MCR18[4]
++ ldr r1, =0x000000ff
++ ldr r0, =0x1e7200b0 @ init MCR18[4]=0 max,min
++ str r1, [r0]
++ ldr r0, =0x1e7200b4 @ init MCR18[4]=1 max,min
++ str r1, [r0]
++
++ ldr r0, =0x1e6e0018
++ ldr r1, [r0]
++ bic r1, r1, #0x0000001F
++ str r1, [r0]
++
++ b cbr4_scan_start
++
++cbr4_next_maskdly:
++ add r8, r8, #0x01
++ and r2, r8, #0x01
++ ldr r0, =0x1e6e0018
++ ldr r1, [r0]
++ bic r1, r1, #0x0000001F
++ orr r1, r1, r2, lsl #4
++ str r1, [r0]
++ cmp r8, #0x02
++ bge CBR4_END
++
++cbr4_scan_start:
++ mov r6, #0x00 @ init pass count
++ mov r7, #0x00 @ init mask delay
++
++/****************************
++ DQS Mask delay margin test loop
++ ***************************/
++cbr4_next_parameter:
++ cmp r7, #0x10 @ max delay = 0xF
++ bge cbr4_next_maskdly
++ ldr r0, =0x1e6e0018 @ load MCR18 parameter
++ ldr r1, [r0]
++ bic r1, r1, #0x0000000F
++ orr r1, r1, r7
++ str r1, [r0]
++ add r7, r7, #0x01
++
++/* CBRScan3() start */
++ adrl r5, PATTERN_TABLE @ init pattern table index
++/****************************
++ Test pattern iteration loop
++ ***************************/
++cbr4_next_test_pattern:
++ mov r10, #2 @ set the retry loop = 2 of each pattern
++ ldr r1, [r5] @ load test pattern
++ ldr r0, =0x1e6e007c
++ str r1, [r0]
++ cmp r1, #0x00 @ the last data in pattern is 0x00
++ bne cbr4_test_burst
++
++ and r3, r7, #0xFF
++ sub r3, r3, #0x01 @ we add 1 after loop check so we need to decrease 1
++ add r6, r6, #0x01 @ increment pass count
++
++ ldr r0, =0x1e7200b0 @ record pass window
++ add r0, r0, r8, lsl #2
++ record_dll2_pass_range
++ mov r2, #0x01
++ add r1, r1, r2, lsl #16
++ str r1, [r0]
++ b cbr4_next_parameter
++
++cbr4_test_pattern_fail:
++ cmp r6, #5 @ passcnt >= 5
++ bge cbr4_next_maskdly
++ b cbr4_next_parameter
++
++/****************************
++ Test fail retry loop
++ ***************************/
++cbr4_pattern_fail_retry:
++
++/* CBRTest3() start */
++cbr4_test_burst:
++ ldr r0, =0x1e6e0070
++ ldr r1, =0x00000000
++ str r1, [r0]
++ ldr r1, =0x000000C1
++ str r1, [r0]
++ ldr r3, =0x3000
++cbr4_wait_engine_idle_0:
++ ldr r2, [r0]
++ tst r2, r3 @ D[12] = idle bit
++ beq cbr4_wait_engine_idle_0
++
++ ldr r2, [r0] @ read fail bit status
++ mov r1, #0x0
++ str r1, [r0]
++ mov r2, r2, lsr #13 @ D[13] = fail bit
++ cmp r2, #0x00
++ bne cbr4_test_fail
++
++cbr4_test_single:
++ ldr r0, =0x1e6e0070
++ ldr r1, =0x00000000
++ str r1, [r0]
++ ldr r1, =0x00000085
++ str r1, [r0]
++ ldr r3, =0x3000
++cbr4_wait_engine_idle_1:
++ ldr r2, [r0]
++ tst r2, r3 @ D[12] = idle bit
++ beq cbr4_wait_engine_idle_1
++
++ ldr r2, [r0] @ read fail bit status
++ mov r1, #0x0
++ str r1, [r0]
++ mov r2, r2, lsr #13 @ D[13] = fail bit
++ cmp r2, #0x00
++ beq cbr4_test_pass
++
++/* CBRTest3() end */
++
++cbr4_test_fail:
++ subs r10, r10, #1
++ bne cbr4_pattern_fail_retry
++ b cbr4_test_pattern_fail @ CBRScan3() return(0)
++
++cbr4_test_pass:
++ add r5, r5, #0x04 @ increase the test pattern index
++ b cbr4_next_test_pattern
++
++CBR4_END:
++ ldr r0, =0x1e7200b0 @ check mask margin
++ ldr r1, [r0]
++ add r0, r0, #0x04
++ ldr r2, [r0]
++ ands r6, r2, #0xFF @ get min of MCR18[4] = 1
++ bne cbr4_noset_delay
++ ands r5, r1, #0xFF @ get min of MCR18[4] = 0
++ bne cbr4_set_delay
++ mov r1, r1, lsr #8 @ get max of MCR18[4] = 0
++ and r1, r1, #0xFF
++ mov r2, r2, lsr #8 @ get max of MCR18[4] = 1
++ and r2, r2, #0xFF
++ sub r1, r1, r5
++ sub r2, r2, r6
++ cmp r1, r2
++ bge cbr4_noset_delay
++
++cbr4_set_delay:
++ ldr r0, =0x1e6e0018
++ ldr r1, [r0]
++ orr r1, r1, #0x10
++ str r1, [r0]
++
++cbr4_noset_delay:
++ ldr r0, =0x1e6e0070
++ ldr r1, =0x00000000
++ str r1, [r0]
++
++/******************************************************************************
++ CBR Finish
++ *****************************************************************************/
++/******************************************************************************
++ Check DRAM Size
++ *****************************************************************************/
++ ldr r0, =0x1e6e2070
++ ldr r1, [r0]
++ bic r1, r1, #0xFEFFFFFF @ bit[24]=1 => DDR2
++ mov r2, r1, lsr #24
++ cmp r2, #0x01
++ beq check_ddr2_size
++
++ ldr r0, =0x1e6e0004
++ ldr r5, [r0]
++ bic r5, r5, #0x00000003 @ record MCR04
++ orr r1, r5, #0x3
++ str r1, [r0] @ set to 4Gbit
++ ldr r6, =0x003F2217
++#if defined(CONFIG_DRAM_336)
++ ldr r6, =0x00361C13
++#endif
++ b check_dram_size
++
++check_ddr2_size:
++ ldr r0, =0x1e6e0004
++ ldr r5, [r0]
++ bic r5, r5, #0x00000023 @ record MCR04
++ orr r1, r5, #0x23
++ str r1, [r0] @ set to 4Gbit
++ ldr r6, =0x3F2B1B16
++#if defined(CONFIG_DRAM_336)
++ ldr r6, =0x3B231612
++#endif
++
++ ldr r0, =0x40000000
++ ldr r1, =0x1817191A
++ str r1, [r0]
++ ldr r0, =0x40002000
++ ldr r1, =0x73616532
++ str r1, [r0]
++ ldr r0, =0x40000000
++ ldr r1, =0x1817191A
++ ldr r2, [r0]
++ cmp r1, r2
++ bne check_dram_size_end @ == 512Mbit
++ orr r5, r5, #0x20 @ >= 1Gbit
++ mov r6, r6, lsr #8
++
++check_dram_size:
++ ldr r0, =0x50100000
++ ldr r1, =0x41424344
++ str r1, [r0]
++ ldr r0, =0x48100000
++ ldr r1, =0x25262728
++ str r1, [r0]
++ ldr r0, =0x40100000
++ ldr r1, =0x191A1B1C
++ str r1, [r0]
++ ldr r0, =0x50100000
++ ldr r1, =0x41424344
++ ldr r2, [r0]
++ cmp r2, r1 @ == 4Gbit
++ orreq r5, r5, #0x03
++ moveq r6, r6, lsr #16
++ beq check_dram_size_end
++ ldr r0, =0x48100000
++ ldr r1, =0x25262728
++ ldr r2, [r0]
++ cmp r2, r1 @ == 2Gbit
++ orreq r5, r5, #0x02
++ moveq r6, r6, lsr #8
++ beq check_dram_size_end
++ orr r5, r5, #0x01 @ == 1Gbit
++
++check_dram_size_end:
++ ldr r0, =0x1e6e0004
++ str r5, [r0]
++ ldr r0, =0x1e6e0014
++ ldr r1, [r0]
++ bic r1, r1, #0x000000FF
++ and r6, r6, #0xFF
++ orr r1, r1, r6
++ str r1, [r0]
++
++ ldr r0, =0x1e6e0120 @ VGA Compatible Mode
++ ldr r1, =0x000050C0 @ 408 MHz
++#if defined(CONFIG_DRAM_336)
++ ldr r1, =0x00004DC0
++#endif
++ str r1, [r0]
++
++/******************************************************************************
++ Version Number
++ *****************************************************************************/
++ ldr r0, =0x1e7200a8
++ ldr r1, =0x20141229 @ released date
++ str r1, [r0]
++
++ add r0, r0, #4
++ ldr r1, =0x00000060 @ released SDK version
++ str r1, [r0]
++
++/******************************************************************************
++ Calibration Code End
++ ******************************************************************************/
++
++set_scratch:
++ /*Set Scratch register Bit 6 after ddr initial finished */
++ ldr r0, =0x1e6e2040
++ ldr r1, [r0]
++ orr r1, r1, #0x40
++ str r1, [r0]
++
++/* Debug - UART console message */
++ ldr r0, =0x1e784000
++ mov r1, #0x44 @ 'D'
++ str r1, [r0]
++ mov r1, #0x6F @ 'o'
++ str r1, [r0]
++ mov r1, #0x6E @ 'n'
++ str r1, [r0]
++ mov r1, #0x65 @ 'e'
++ str r1, [r0]
++ mov r1, #0x0D @ '\r'
++ str r1, [r0]
++ mov r1, #0x0A @ '\n'
++ str r1, [r0]
++/* Debug - UART console message */
++
++/******************************************************************************
++ Solve PCIe ASPM issue, only applied to AST2300 series
++ ******************************************************************************/
++ ldr r0, =0x1e6e207c @ Check bounding for AST1150 existence
++ ldr r1, [r0]
++ mov r2, r1, lsr #24
++ cmp r2, #0x01
++ bne platform_exit @ not match AST2300
++ bic r1, r1, #0xFFFFFCFF
++ mov r1, r1, lsr #8
++ cmp r1, #0x02
++ beq platform_exit @ match AST1050
++
++ ldr r0, =0x1e6e2004 @ Disable I2C controller reset
++ ldr r1, [r0]
++ orr r1, r1, #0x04
++ str r1, [r0]
++ bic r1, r1, #0x04
++ str r1, [r0]
++
++ ldr r0, =0x1e78a054 @ Check I2C bus state, if busy then quit
++ ldr r1, [r0]
++ mov r1, r1, lsr #17
++ and r1, r1, #0x03
++ cmp r1, #0x03
++ bne platform_exit
++
++ ldr r0, =0x1e78a040 @ Init I2C1 controller
++ mov r1, #0x01
++ orr r1, r1, r1, lsl #16
++ str r1, [r0]
++
++ ldr r0, =0x1e78a044
++ ldr r1, =0x77776704
++ str r1, [r0]
++
++ mov r1, #0x0
++ ldr r0, =0x1e78a048
++ str r1, [r0]
++ ldr r0, =0x1e78a04c
++ str r1, [r0]
++
++ ldr r0, =0x1e78a050
++ ldr r1, =0xFFFFFFFF
++ str r1, [r0]
++
++ ldr r0, =0x1e78a200 @ Set AST1150 I2C password
++ ldr r1, =0x00A88FA8
++ str r1, [r0]
++
++ ldr r0, =0x1e78a05c
++ ldr r1, =0x00000200 @ Enable buffer mode transfering 3 bytes
++ str r1, [r0]
++
++ ldr r0, =0x1e78a054
++ ldr r1, =0x00000063 @ Fire commmand
++ str r1, [r0]
++
++ ldr r0, =0x1e78a050
++i2c_wait_cmddone_1:
++ ldr r1, [r0]
++ tst r1, #0x38
++ beq i2c_wait_cmddone_1
++ tst r1, #0x2A @ transmit error
++ bne platform_exit2
++ ldr r1, =0xFFFFFFFF
++ str r1, [r0]
++
++ ldr r0, =0x1e78a200 @ Disable ASPM capability
++ ldr r1, =0x04005DA8
++ str r1, [r0]
++
++ ldr r0, =0x1e78a204
++ ldr r1, =0x00000024
++ str r1, [r0]
++
++ ldr r0, =0x1e78a05c
++ ldr r1, =0x00000200 @ Enable buffer mode transfering 3 bytes
++ str r1, [r0]
++
++ ldr r0, =0x1e78a054
++ ldr r1, =0x00000063 @ Fire commmand
++ str r1, [r0]
++
++ ldr r0, =0x1e78a050
++i2c_wait_cmddone_2:
++ ldr r1, [r0]
++ tst r1, #0x38
++ beq i2c_wait_cmddone_2
++ tst r1, #0x2A @ transmit error
++ bne platform_exit2
++ ldr r1, =0xFFFFFFFF
++ str r1, [r0]
++
++platform_exit2:
++ ldr r0, =0x1e78a040 @ Disable I2C1 controller
++ mov r1, #0x00
++ str r1, [r0]
++
++ b platform_exit
++.LTORG
++
++platform_exit:
++#ifdef CONFIG_DRAM_ECC
++ ldr r0, =0x1e6e0004
++ ldr r1, [r0]
++ orr r1, r1, #0x80
++ str r1, [r0]
++
++ ldr r0, =0x1e6e0054
++ ldr r1, =0x05000000 /* ECC protected memory size, default set at 80M */
++ str r1, [r0]
++
++ ldr r0, =0x1e6e007C
++ ldr r1, =0x00000000
++ str r1, [r0]
++ ldr r0, =0x1e6e0074
++ str r1, [r0]
++
++ ldr r0, =0x1e6e0070
++ ldr r1, =0x00000221
++ str r1, [r0]
++
++ ldr r0, =0x1e6e0070
++ ldr r2, =0x00001000
++ECC_Init_Flag:
++ ldr r1, [r0]
++ tst r1, r2 @ D[12] = 1, Done
++ beq ECC_Init_Flag
++
++ ldr r0, =0x1e6e0070
++ ldr r1, =0x00000000
++ str r1, [r0]
++
++ ldr r0, =0x1e6e0050
++ ldr r1, =0x80000000
++ str r1, [r0]
++
++ ldr r0, =0x1e6e0050
++ ldr r1, =0x00000000
++ str r1, [r0]
++
++ ldr r0, =0x1e6e0070
++ ldr r1, =0x00000400
++ str r1, [r0]
++#endif
++ ldr r0, =0x1e6e2008 @ Set Video ECLK phase
++ ldr r1, [r0]
++ ldr r2, =0xfffffff3
++ and r1, r1, r2
++ orr r1, r1, #0x08
++ str r1, [r0]
++
++ ldr r0, =0x1e6e2004
++ ldr r1, [r0]
++ ldr r2, =0xFFBFFFFF @ Enable JTAG Master, solve ARM stucked by JTAG issue
++ and r1, r1, r2
++ str r1, [r0]
++
++ ldr r0, =0x1e6e2048 @ Set MAC interface delay timing
++ ldr r1, =0x2255
++ str r1, [r0]
++
++ ldr r0, =0x1e6e2070 @ Set MAC AHB bus clock
++ ldr r1, [r0]
++ mov r2, #0x04 @ Default RMII, set MHCLK = HPLL/10
++ tst r1, #0xC0
++ movne r2, #0x02 @ if RGMII, set MHCLK = HPLL/6
++ ldr r0, =0x1e6e2008
++ ldr r1, [r0]
++ bic r1, r1, #0x00070000
++ orr r1, r1, r2, lsl #16
++ str r1, [r0]
++
++/* Test - DRAM initial time */
++ ldr r0, =0x1e782040
++ ldr r1, [r0]
++ ldr r0, =0xFFFFFFFF
++ sub r1, r0, r1
++ ldr r0, =0x1e72009c
++ str r1, [r0]
++ ldr r0, =0x1e7200a4
++ str r1, [r0]
++ ldr r0, =0x1e782030
++ ldr r1, [r0]
++ bic r1, r1, #0x0000F000
++ str r1, [r0]
++/* Test - DRAM initial time */
++
++/******************************************************************************
++ Reset GPIO registers when watchdog reset
++ ******************************************************************************/
++ ldr r0, =0x1e6e207c @ Check Revision ID
++ ldr r1, [r0]
++ mov r1, r1, lsr #24
++ cmp r1, #0x02
++ bne platform_exit3 @ not match AST2400
++
++ ldr r0, =0x1e6e203c @ Check watchdog reset event
++ ldr r1, [r0]
++ and r1, r1, #0x06
++ cmp r1, #0x0
++ beq platform_exit3 @ no watchdog reset event
++
++ ldr r0, =0x1e6e209c @ Check watchdog GPIO selection
++ ldr r1, [r0]
++ mov r1, r1, lsr #21
++ tst r1, #0x01
++ beq platform_exit3 @ no watchdog reset selection
++
++ ldr r1, =0x00000000 @ clear GPIO register reset by PRST_N
++ ldr r2, =0xFFFFFFFF
++ ldr r0, =0x1e780008
++ str r1, [r0]
++ ldr r0, =0x1e78000c
++ str r1, [r0]
++ ldr r0, =0x1e780010
++ str r1, [r0]
++ ldr r0, =0x1e780014
++ str r1, [r0]
++ ldr r0, =0x1e780018
++ str r2, [r0]
++ ldr r0, =0x1e780028
++ str r1, [r0]
++ ldr r0, =0x1e78002c
++ str r1, [r0]
++ ldr r0, =0x1e780030
++ str r1, [r0]
++ ldr r0, =0x1e780034
++ str r1, [r0]
++ ldr r0, =0x1e780038
++ str r2, [r0]
++ ldr r0, =0x1e780040
++ str r1, [r0]
++ ldr r0, =0x1e780044
++ str r1, [r0]
++ ldr r0, =0x1e780048
++ str r1, [r0]
++ ldr r0, =0x1e78004c
++ str r1, [r0]
++ ldr r0, =0x1e780050
++ str r1, [r0]
++ ldr r0, =0x1e780054
++ str r1, [r0]
++ ldr r0, =0x1e780058
++ str r1, [r0]
++ ldr r0, =0x1e780060
++ str r1, [r0]
++ ldr r0, =0x1e780064
++ str r1, [r0]
++ ldr r0, =0x1e780068
++ str r1, [r0]
++ ldr r0, =0x1e78006c
++ str r1, [r0]
++ ldr r0, =0x1e780090
++ str r1, [r0]
++ ldr r0, =0x1e780094
++ str r1, [r0]
++ ldr r0, =0x1e780098
++ str r1, [r0]
++ ldr r0, =0x1e78009c
++ str r1, [r0]
++ ldr r0, =0x1e7800a0
++ str r1, [r0]
++ ldr r0, =0x1e7800a4
++ str r1, [r0]
++ ldr r0, =0x1e7800a8
++ str r2, [r0]
++ ldr r0, =0x1e7800b0
++ str r1, [r0]
++ ldr r0, =0x1e7800b4
++ str r1, [r0]
++ ldr r0, =0x1e7800b8
++ str r1, [r0]
++ ldr r0, =0x1e7800e0
++ str r1, [r0]
++ ldr r0, =0x1e7800e4
++ str r1, [r0]
++ ldr r0, =0x1e7800e8
++ str r1, [r0]
++ ldr r0, =0x1e7800ec
++ str r1, [r0]
++ ldr r0, =0x1e7800f0
++ str r1, [r0]
++ ldr r0, =0x1e7800f4
++ str r1, [r0]
++ ldr r0, =0x1e7800f8
++ str r2, [r0]
++ ldr r0, =0x1e780100
++ str r1, [r0]
++ ldr r0, =0x1e780104
++ str r1, [r0]
++ ldr r0, =0x1e780108
++ str r1, [r0]
++ ldr r0, =0x1e780110
++ str r1, [r0]
++ ldr r0, =0x1e780114
++ str r1, [r0]
++ ldr r0, =0x1e780118
++ str r1, [r0]
++ ldr r0, =0x1e78011c
++ str r1, [r0]
++ ldr r0, =0x1e780120
++ str r1, [r0]
++ ldr r0, =0x1e780124
++ str r1, [r0]
++ ldr r0, =0x1e780128
++ str r2, [r0]
++ ldr r0, =0x1e780130
++ str r1, [r0]
++ ldr r0, =0x1e780134
++ str r1, [r0]
++ ldr r0, =0x1e780138
++ str r1, [r0]
++ ldr r0, =0x1e780140
++ str r1, [r0]
++ ldr r0, =0x1e780144
++ str r1, [r0]
++ ldr r0, =0x1e780148
++ str r1, [r0]
++ ldr r0, =0x1e78014c
++ str r1, [r0]
++ ldr r0, =0x1e780150
++ str r1, [r0]
++ ldr r0, =0x1e780154
++ str r1, [r0]
++ ldr r0, =0x1e780158
++ str r2, [r0]
++ ldr r0, =0x1e780160
++ str r1, [r0]
++ ldr r0, =0x1e780164
++ str r1, [r0]
++ ldr r0, =0x1e780168
++ str r1, [r0]
++ ldr r0, =0x1e780170
++ str r1, [r0]
++ ldr r0, =0x1e780174
++ str r1, [r0]
++ ldr r0, =0x1e780178
++ str r1, [r0]
++ ldr r0, =0x1e78017c
++ str r1, [r0]
++ ldr r0, =0x1e780180
++ str r1, [r0]
++ ldr r0, =0x1e780184
++ str r1, [r0]
++ ldr r0, =0x1e780188
++ str r2, [r0]
++ ldr r0, =0x1e780190
++ str r1, [r0]
++ ldr r0, =0x1e780194
++ str r1, [r0]
++ ldr r0, =0x1e780198
++ str r1, [r0]
++ ldr r0, =0x1e7801d0
++ str r1, [r0]
++ ldr r0, =0x1e7801d4
++ str r1, [r0]
++
++ ldr r0, =0x1e780204 @ clear SGPIOM register reset by PRST_N
++ str r1, [r0]
++ ldr r0, =0x1e780208
++ str r1, [r0]
++ ldr r0, =0x1e78020c
++ str r1, [r0]
++ ldr r0, =0x1e780210
++ str r1, [r0]
++ ldr r0, =0x1e780214
++ str r2, [r0]
++ ldr r0, =0x1e780220
++ str r1, [r0]
++ ldr r0, =0x1e780224
++ str r1, [r0]
++ ldr r0, =0x1e780228
++ str r1, [r0]
++ ldr r0, =0x1e78022c
++ str r1, [r0]
++ ldr r0, =0x1e780230
++ str r2, [r0]
++ ldr r0, =0x1e78023c
++ str r1, [r0]
++ ldr r0, =0x1e780240
++ str r1, [r0]
++ ldr r0, =0x1e780244
++ str r1, [r0]
++ ldr r0, =0x1e780248
++ str r1, [r0]
++ ldr r0, =0x1e78024c
++ str r2, [r0]
++ ldr r0, =0x1e780254
++ ldr r3, =0x01000040
++ str r3, [r0]
++ ldr r0, =0x1e780258
++ str r1, [r0]
++ ldr r0, =0x1e78025c
++ str r1, [r0]
++ ldr r0, =0x1e780260
++ str r1, [r0]
++
++ ldr r0, =0x1e780300 @ clear SGPIOS register reset by PRST_N
++ str r1, [r0]
++ ldr r0, =0x1e780304
++ str r1, [r0]
++ ldr r0, =0x1e780308
++ str r1, [r0]
++ ldr r0, =0x1e78030c
++ str r1, [r0]
++ ldr r0, =0x1e780310
++ str r1, [r0]
++ ldr r0, =0x1e780314
++ str r1, [r0]
++ ldr r0, =0x1e780318
++ str r2, [r0]
++ ldr r0, =0x1e78031c
++ str r2, [r0]
++ ldr r0, =0x1e780320
++ str r2, [r0]
++
++platform_exit3:
++
++/******************************************************************************
++ SPI Timing Calibration, not applicable to AST2300 series
++ ******************************************************************************/
++ ldr r0, =0x1e6e207c @ Check Revision ID
++ ldr r1, [r0]
++ mov r1, r1, lsr #24
++ cmp r1, #0x02
++ blt platform_exit4 @ not match AST2400 or later
++
++ ldr r0, =0x1e6e2070 @ Check SPI flash
++ ldr r1, [r0]
++ and r1, r1, #0x03
++ cmp r1, #0x02
++ bne platform_exit4
++
++ mov r2, #0x0
++ mov r6, #0x0
++ mov r7, #0x0
++ init_spi_checksum
++spi_checksum_wait_0:
++ ldr r1, [r0]
++ tst r1, r2
++ beq spi_checksum_wait_0
++ ldr r0, =0x1e620090
++ ldr r5, [r0] @ record golden checksum
++ ldr r0, =0x1e620080
++ mov r1, #0x0
++ str r1, [r0]
++
++ ldr r0, =0x1e620010 @ set to fast read mode
++ ldr r1, =0x000B0041
++ str r1, [r0]
++
++ ldr r6, =0x00F7E6D0 @ Init spiclk loop
++ mov r8, #0x0 @ Init delay record
++
++spi_cbr_next_clkrate:
++ mov r6, r6, lsr #0x4
++ cmp r6, #0x0
++ beq spi_cbr_end
++
++ mov r7, #0x0 @ Init delay loop
++ mov r8, r8, lsl #4
++
++spi_cbr_next_delay_s:
++ mov r2, #0x8
++ init_spi_checksum
++spi_checksum_wait_1:
++ ldr r1, [r0]
++ tst r1, r2
++ beq spi_checksum_wait_1
++ ldr r0, =0x1e620090
++ ldr r2, [r0] @ read checksum
++ ldr r0, =0x1e620080
++ mov r1, #0x0
++ str r1, [r0]
++ cmp r2, r5
++ bne spi_cbr_next_delay_e
++
++ mov r2, #0x0
++ init_spi_checksum
++spi_checksum_wait_2:
++ ldr r1, [r0]
++ tst r1, r2
++ beq spi_checksum_wait_2
++ ldr r0, =0x1e620090
++ ldr r2, [r0] @ read checksum
++ ldr r0, =0x1e620080
++ mov r1, #0x0
++ str r1, [r0]
++ cmp r2, r5
++ bne spi_cbr_next_delay_e
++
++ orr r8, r8, r7 @ record passed delay
++ b spi_cbr_next_clkrate
++
++spi_cbr_next_delay_e:
++ add r7, r7, #0x1
++ cmp r7, #0x6
++ blt spi_cbr_next_delay_s
++ b spi_cbr_next_clkrate
++
++spi_cbr_end:
++ ldr r0, =0x1e620094
++ str r8, [r0]
++ ldr r0, =0x1e620010
++ mov r1, #0x0
++ str r1, [r0]
++
++platform_exit4:
++
++ /* restore lr */
++ mov lr, r4
++
++ /* back to arch calling code */
++ mov pc, lr
+diff --git a/board/aspeed/ast2400/rc4.c b/board/aspeed/ast2400/rc4.c
+new file mode 100755
+index 0000000..32e0ffa
+--- /dev/null
++++ b/board/aspeed/ast2400/rc4.c
+@@ -0,0 +1,68 @@
++/*
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++ */
++struct rc4_state
++{
++ int x, y, m[256];
++};
++
++void rc4_setup( struct rc4_state *s, unsigned char *key, int length )
++{
++ int i, j, k, *m, a;
++
++ s->x = 0;
++ s->y = 0;
++ m = s->m;
++
++ for( i = 0; i < 256; i++ )
++ {
++ m[i] = i;
++ }
++
++ j = k = 0;
++
++ for( i = 0; i < 256; i++ )
++ {
++ a = m[i];
++ j = (unsigned char) ( j + a + key[k] );
++ m[i] = m[j]; m[j] = a;
++ if( ++k >= length ) k = 0;
++ }
++}
++
++void rc4_crypt( struct rc4_state *s, unsigned char *data, int length )
++{
++ int i, x, y, *m, a, b;
++
++ x = s->x;
++ y = s->y;
++ m = s->m;
++
++ for( i = 0; i < length; i++ )
++ {
++ x = (unsigned char) ( x + 1 ); a = m[x];
++ y = (unsigned char) ( y + a );
++ m[x] = b = m[y];
++ m[y] = a;
++ data[i] ^= m[(unsigned char) ( a + b )];
++ }
++
++ s->x = x;
++ s->y = y;
++}
++
++void rc4_crypt_sw(unsigned char *data, int ulMsgLength, unsigned char *rc4_key, unsigned long ulKeyLength )
++{
++ struct rc4_state s;
++
++ rc4_setup( &s, rc4_key, ulKeyLength );
++
++ rc4_crypt( &s, data, ulMsgLength );
++}
+diff --git a/board/aspeed/ast2400/regtest.c b/board/aspeed/ast2400/regtest.c
+new file mode 100755
+index 0000000..1cd75ae
+--- /dev/null
++++ b/board/aspeed/ast2400/regtest.c
+@@ -0,0 +1,91 @@
++/*
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
++ * MA 02111-1307 USA
++ */
++
++/*
++ * Diagnostics support
++ */
++#include <common.h>
++#include <command.h>
++#include <post.h>
++#include "slt.h"
++
++#if ((CFG_CMD_SLT & CFG_CMD_REGTEST) && defined(CONFIG_SLT))
++#include "regtest.h"
++
++int do_regtest (void)
++{
++ _SOCRegTestInfo *pjSOCRegInfo;
++ _SOCRegTestTbl *pjRegTable;
++ unsigned long ulRegBase;
++ unsigned long ulIndex, ulBack, ulAND, ulMask, ulData, ulTemp;
++ unsigned long Flags = 0;
++
++ /* unlock reg */
++ *(unsigned long *) (0x1e600000) = 0xaeed1a03; /* AHBC */
++ *(unsigned long *) (0x1e6e0000) = 0xfc600309; /* MMC */
++ *(unsigned long *) (0x1e6e2000) = 0x1688a8a8; /* SCU */
++
++ /* SCU */
++
++ /* do test */
++ pjSOCRegInfo = SOCRegTestInfo;
++ while (strcmp(pjSOCRegInfo->jName, "END"))
++ {
++ /* Reg. Test Start */
++ ulRegBase = pjSOCRegInfo->ulRegOffset;
++ pjRegTable = pjSOCRegInfo->pjTblIndex;
++
++ while (pjRegTable->ulIndex != 0xFFFFFFFF)
++ {
++ ulIndex = ulRegBase + pjRegTable->ulIndex;
++
++ ulBack = *(unsigned long *) (ulIndex);
++
++ ulMask = pjRegTable->ulMask;
++ ulAND = ~pjRegTable->ulMask;
++
++ ulData = 0xFFFFFFFF & pjRegTable->ulMask;
++ *(unsigned long *) (ulIndex) = ulData;
++ ulTemp = *(volatile unsigned long *) (ulIndex) & pjRegTable->ulMask;
++ if (ulData != ulTemp)
++ {
++ Flags |= pjSOCRegInfo->ulFlags;
++ printf("[DBG] RegTest: Failed Index:%x, Data:%x, Temp:%x \n", ulIndex, ulData, ulTemp);
++ }
++
++ ulData = 0x00000000 & pjRegTable->ulMask;
++ *(unsigned long *) (ulIndex) = ulData;
++ ulTemp = *(volatile unsigned long *) (ulIndex) & pjRegTable->ulMask;
++ if (ulData != ulTemp)
++ {
++ Flags |= pjSOCRegInfo->ulFlags;
++ printf("[DBG] RegTest: Failed Index:%x, Data:%x, Temp:%x \n", ulIndex, ulData, ulTemp);
++ }
++
++ *(unsigned long *) (ulIndex) = ulBack;
++
++ pjRegTable++;
++
++ } /* Individual Reg. Test */
++
++ if (Flags & pjSOCRegInfo->ulFlags)
++ printf("[INFO] RegTest: %s Failed \n", pjSOCRegInfo->jName);
++
++ pjSOCRegInfo++;
++
++ } /* Reg. Test */
++
++ return Flags;
++
++}
++
++#endif /* CONFIG_SLT */
+diff --git a/board/aspeed/ast2400/regtest.h b/board/aspeed/ast2400/regtest.h
+new file mode 100755
+index 0000000..49a360e
+--- /dev/null
++++ b/board/aspeed/ast2400/regtest.h
+@@ -0,0 +1,255 @@
++/*
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++ */
++typedef struct {
++ unsigned long ulIndex;
++ unsigned long ulMask;
++} _SOCRegTestTbl;
++
++typedef struct {
++ unsigned char jName[10];
++ unsigned long ulRegOffset;
++ _SOCRegTestTbl *pjTblIndex;
++ unsigned long ulFlags;
++} _SOCRegTestInfo;
++
++_SOCRegTestTbl SMCRegTestTbl[] = {
++ {0x00000000, 0x00001FF3},
++ {0x00000004, 0xFFFFFFFF},
++ {0x00000008, 0x0FFF17FF},
++ {0x0000000C, 0xFFFFFFFF},
++ {0x00000010, 0xFF5FFFF3},
++ {0x00000018, 0x0FFFFFFF},
++ {0xFFFFFFFF, 0xFFFFFFFF},
++};
++
++_SOCRegTestTbl AHBCRegTestTbl[] = {
++ {0x00000080, 0x0000FFFE},
++ {0x00000088, 0x01000000},
++ {0x0000008c, 0x00000031},
++ {0xFFFFFFFF, 0xFFFFFFFF},
++};
++
++_SOCRegTestTbl MICRegTestTbl[] = {
++/*
++ {0x00000000, 0x0FFFFFF8},
++ {0x00000004, 0x0FFFFFF8},
++ {0x00000008, 0x0000FFFF},
++ {0x0000000C, 0x0FFFF000},
++ {0x00000010, 0xFFFFFFFF},
++*/
++ {0xFFFFFFFF, 0xFFFFFFFF},
++};
++
++_SOCRegTestTbl MAC1RegTestTbl[] = {
++ {0xFFFFFFFF, 0xFFFFFFFF},
++};
++
++_SOCRegTestTbl MAC2RegTestTbl[] = {
++ {0xFFFFFFFF, 0xFFFFFFFF},
++};
++
++_SOCRegTestTbl USB2RegTestTbl[] = {
++ {0xFFFFFFFF, 0xFFFFFFFF},
++};
++
++_SOCRegTestTbl VICRegTestTbl[] = {
++ {0x0000000C, 0xFFFFFFFF},
++ {0x00000024, 0xFFFFFFFF},
++ {0x00000028, 0xFFFFFFFF},
++ {0x0000002C, 0xFFFFFFFF},
++ {0xFFFFFFFF, 0xFFFFFFFF},
++};
++
++_SOCRegTestTbl MMCRegTestTbl[] = {
++ {0xFFFFFFFF, 0xFFFFFFFF},
++};
++
++_SOCRegTestTbl USB11RegTestTbl[] = {
++ {0xFFFFFFFF, 0xFFFFFFFF},
++};
++
++_SOCRegTestTbl SCURegTestTbl[] = {
++ {0xFFFFFFFF, 0xFFFFFFFF},
++};
++
++_SOCRegTestTbl HASERegTestTbl[] = {
++ {0x00000000, 0x0FFFFFF8},
++ {0x00000004, 0x0FFFFFF8},
++ {0x00000008, 0x0FFFFFF8},
++ {0x0000000C, 0x0FFFFFF8},
++ //{0x00000010, 0x00001FFF},
++ {0x00000020, 0x0FFFFFF8},
++ {0x00000024, 0x0FFFFFF8},
++ {0x00000028, 0x0FFFFFc0},
++ {0x0000002C, 0x0FFFFFFF},
++ //{0x00000030, 0x000003FF},
++ {0xFFFFFFFF, 0xFFFFFFFF},
++};
++
++_SOCRegTestTbl I2SRegTestTbl[] = {
++ {0xFFFFFFFF, 0xFFFFFFFF},
++};
++
++_SOCRegTestTbl CRTRegTestTbl[] = {
++/*
++ {0x00000000, 0x001F3703},
++ {0x00000004, 0x0000FFC1},
++*/
++ {0x00000010, 0x0FFF0FFF},
++ {0x00000014, 0x0FFF0FFF},
++ {0x00000018, 0x07FF07FF},
++ {0x0000001C, 0x07FF07FF},
++ {0x00000020, 0x0FFFFFF8},
++ {0x00000024, 0x07FF3FF8},
++/*
++ {0x00000028, 0x003F003F},
++ {0x00000030, 0x003F003F},
++ {0x00000034, 0x0FFF0FFF},
++ {0x00000038, 0x0FFFFFF8},
++*/
++ {0x00000040, 0x0FFF0FFF},
++ {0x00000044, 0x07FF07FF},
++ {0x00000048, 0x0FFFFFF8},
++ {0x0000004C, 0x00FF07F8},
++ {0x00000050, 0x000F0F0F},
++/*
++ {0x00000060, 0x001F3703},
++ {0x00000064, 0x0000FFC1},
++*/
++ {0x00000070, 0x0FFF0FFF},
++ {0x00000074, 0x0FFF0FFF},
++ {0x00000078, 0x07FF07FF},
++ {0x0000007C, 0x07FF07FF},
++ {0x00000080, 0x0FFFFFF8},
++ {0x00000084, 0x07FF3FF8},
++/*
++ {0x00000088, 0x003F003F},
++ {0x00000090, 0x003F003F},
++ {0x00000094, 0x0FFF0FFF},
++ {0x00000098, 0x0FFFFFF8},
++*/
++ {0x000000A0, 0x0FFF0FFF},
++ {0x000000A4, 0x07FF07FF},
++ {0x000000A8, 0x0FFFFFF8},
++ {0x000000AC, 0x00FF07F8},
++ {0x000000B0, 0x000F0F0F},
++ {0xFFFFFFFF, 0xFFFFFFFF},
++};
++
++_SOCRegTestTbl VIDEORegTestTbl[] = {
++ {0xFFFFFFFF, 0xFFFFFFFF},
++};
++
++_SOCRegTestTbl A2PRegTestTbl[] = {
++ {0xFFFFFFFF, 0xFFFFFFFF},
++};
++
++_SOCRegTestTbl MDMARegTestTbl[] = {
++ {0xFFFFFFFF, 0xFFFFFFFF},
++};
++
++_SOCRegTestTbl M2DRegTestTbl[] = {
++ {0xFFFFFFFF, 0xFFFFFFFF},
++};
++
++_SOCRegTestTbl GPIORegTestTbl[] = {
++ {0xFFFFFFFF, 0xFFFFFFFF},
++};
++
++_SOCRegTestTbl RTCRegTestTbl[] = {
++ {0xFFFFFFFF, 0xFFFFFFFF},
++};
++
++_SOCRegTestTbl TIMERRegTestTbl[] = {
++ {0xFFFFFFFF, 0xFFFFFFFF},
++};
++
++_SOCRegTestTbl UART1RegTestTbl[] = {
++ {0xFFFFFFFF, 0xFFFFFFFF},
++};
++
++_SOCRegTestTbl UART2RegTestTbl[] = {
++ {0xFFFFFFFF, 0xFFFFFFFF},
++};
++
++_SOCRegTestTbl WDTRegTestTbl[] = {
++ {0xFFFFFFFF, 0xFFFFFFFF},
++};
++
++_SOCRegTestTbl PWMRegTestTbl[] = {
++ {0xFFFFFFFF, 0xFFFFFFFF},
++};
++
++_SOCRegTestTbl VUART1RegTestTbl[] = {
++ {0xFFFFFFFF, 0xFFFFFFFF},
++};
++
++_SOCRegTestTbl VUART2RegTestTbl[] = {
++ {0xFFFFFFFF, 0xFFFFFFFF},
++};
++
++_SOCRegTestTbl LPCRegTestTbl[] = {
++ {0xFFFFFFFF, 0xFFFFFFFF},
++};
++
++_SOCRegTestTbl I2CRegTestTbl[] = {
++ {0xFFFFFFFF, 0xFFFFFFFF},
++};
++
++_SOCRegTestTbl PECIRegTestTbl[] = {
++ {0xFFFFFFFF, 0xFFFFFFFF},
++};
++
++_SOCRegTestTbl PCIARegTestTbl[] = {
++ {0xFFFFFFFF, 0xFFFFFFFF},
++};
++
++_SOCRegTestTbl PCIRegTestTbl[] = {
++ {0xFFFFFFFF, 0xFFFFFFFF},
++};
++
++
++/* Test List */
++_SOCRegTestInfo SOCRegTestInfo[] = {
++ /* Test Name, Reg. Offset, Test Table, Error Code */
++ { "SMCREG", 0x16000000, SMCRegTestTbl, 0x00000001},
++ { "AHBCREG", 0x1e600000, AHBCRegTestTbl, 0x00000002},
++ { "MICREG", 0x1e640000, MICRegTestTbl, 0x00000004},
++ { "MAC1REG", 0x1e660000, MAC1RegTestTbl, 0x00000008},
++ { "MAC2REG", 0x1e680000, MAC2RegTestTbl, 0x00000010},
++ { "USB2REG", 0x1e6a0000, USB2RegTestTbl, 0x00000020},
++ { "VICREG", 0x1e6c0000, VICRegTestTbl, 0x00000040},
++ { "MMCREG", 0x1e6e0000, MMCRegTestTbl, 0x00000080},
++ { "USB11REG", 0x1e6e1000, USB11RegTestTbl, 0x00000100},
++ { "SCUREG", 0x1e6e2000, SCURegTestTbl, 0x00000200},
++ { "HASEREG", 0x1e6e3000, HASERegTestTbl, 0x00000400},
++ { "I2SREG", 0x1e6e5000, I2SRegTestTbl, 0x00000800},
++ { "CRTREG", 0x1e6e6000, CRTRegTestTbl, 0x00001000},
++ { "VIDEOREG", 0x1e700000, VIDEORegTestTbl, 0x00002000},
++ { "A2PREG", 0x1e720000, A2PRegTestTbl, 0x00004000},
++ { "MDMAREG", 0x1e740000, MDMARegTestTbl, 0x00008000},
++ { "2DREG", 0x1e760000, M2DRegTestTbl, 0x00010000},
++ { "GPIOREG", 0x1e780000, GPIORegTestTbl, 0x00020000},
++ { "RTCREG", 0x1e781000, RTCRegTestTbl, 0x00040000},
++ { "TIMERREG", 0x1e782000, TIMERRegTestTbl, 0x00080000},
++ { "UART1REG", 0x1e783000, UART1RegTestTbl, 0x00100000},
++ { "UART2REG", 0x1e784000, UART2RegTestTbl, 0x00200000},
++ { "WDTREG", 0x1e785000, WDTRegTestTbl, 0x00400000},
++ { "PWMREG", 0x1e786000, PWMRegTestTbl, 0x00800000},
++ {"VUART1REG", 0x1e787000, VUART1RegTestTbl, 0x01000000},
++ {"VUART2REG", 0x1e788000, VUART2RegTestTbl, 0x02000000},
++ { "LPCREG", 0x1e789000, LPCRegTestTbl, 0x04000000},
++ { "I2CREG", 0x1e78A000, I2CRegTestTbl, 0x08000000},
++ { "PECIREG", 0x1e78B000, PECIRegTestTbl, 0x10000000},
++ { "PCIAREG", 0x1e78C000, PCIARegTestTbl, 0x20000000},
++ { "PCIREG", 0x60000000, PCIRegTestTbl, 0x40000000},
++ { "END", 0xffffffff, NULL, 0xffffffff}
++};
+diff --git a/board/aspeed/ast2400/slt.c b/board/aspeed/ast2400/slt.c
+new file mode 100755
+index 0000000..3283d34
+--- /dev/null
++++ b/board/aspeed/ast2400/slt.c
+@@ -0,0 +1,105 @@
++/*
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
++ * MA 02111-1307 USA
++ */
++
++/*
++ * Diagnostics support
++ */
++#include <common.h>
++#include <command.h>
++#include <post.h>
++#include "slt.h"
++
++#if defined (CONFIG_SLT)
++
++int do_slt (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])
++{
++ int flags = 0;
++ int loop = 1;
++
++ if (argc > 1) {
++ loop = simple_strtoul(argv[1], NULL, 10);
++ }
++
++ do {
++
++do_slt_start:
++ /* Reg. Test */
++#if (CFG_CMD_SLT & CFG_CMD_REGTEST)
++ if (do_regtest())
++ {
++ flags |= FLAG_REGTEST_FAIL;
++ printf("[INFO] RegTest Failed \n");
++ }
++ else
++ printf("[INFO] RegTest Passed \n");
++#endif
++#if (CFG_CMD_SLT & CFG_CMD_MACTEST)
++ if (do_mactest())
++ {
++ flags |= FLAG_MACTEST_FAIL;
++ printf("[INFO] MACTest Failed \n");
++ }
++ else
++ printf("[INFO] MACTest Passed \n");
++#endif
++#if (CFG_CMD_SLT & CFG_CMD_VIDEOTEST)
++ if (do_videotest())
++ {
++ flags |= FLAG_VIDEOTEST_FAIL;
++ printf("[INFO] VideoTest Failed \n");
++ }
++ else
++ printf("[INFO] VideoTest Passed \n");
++#endif
++#if (CFG_CMD_SLT & CFG_CMD_HACTEST)
++ if (do_hactest())
++ {
++ flags |= FLAG_HACTEST_FAIL;
++ printf("[INFO] HACTest Failed \n");
++ }
++ else
++ printf("[INFO] HACTest Passed \n");
++#endif
++#if (CFG_CMD_SLT & CFG_CMD_MICTEST)
++ if (do_mictest())
++ {
++ flags |= FLAG_MICTEST_FAIL;
++ printf("[INFO] MICTest Failed \n");
++ }
++ else
++ printf("[INFO] MICTest Passed \n");
++#endif
++
++ /* Summary */
++ if (flags)
++ printf ("[INFO] SLT Test Failed!! \n");
++ else
++ printf ("[INFO] SLT Test Passed!! \n");
++
++ if (loop == 0) /* infinite */
++ goto do_slt_start;
++ else
++ loop--;
++
++ } while (loop);
++
++ return 0;
++}
++/***************************************************/
++
++U_BOOT_CMD(
++ slt, CONFIG_SYS_MAXARGS, 0, do_slt,
++ "slt - slt test program \n",
++ NULL
++);
++
++#endif /* CONFIG_SLT */
+diff --git a/board/aspeed/ast2400/slt.h b/board/aspeed/ast2400/slt.h
+new file mode 100755
+index 0000000..4e650bc
+--- /dev/null
++++ b/board/aspeed/ast2400/slt.h
+@@ -0,0 +1,29 @@
++/*
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++ */
++#define CFG_CMD_REGTEST 0x00000001
++#define CFG_CMD_MACTEST 0x00000002
++#define CFG_CMD_VIDEOTEST 0x00000004
++#define CFG_CMD_HACTEST 0x00000008
++#define CFG_CMD_MICTEST 0x00000010
++#define CFG_CMD_OSDTEST 0x00000020
++#define CFG_CMD_2DTEST 0x00000040
++#define CFG_CMD_HWCTEST 0x00000080
++
++#define FLAG_REGTEST_FAIL 0x00000001
++#define FLAG_MACTEST_FAIL 0x00000002
++#define FLAG_VIDEOTEST_FAIL 0x00000004
++#define FLAG_HACTEST_FAIL 0x00000008
++#define FLAG_MICTEST_FAIL 0x00000010
++#define FLAG_OSDTEST_FAIL 0x00000020
++#define FLAG_2DTEST_FAIL 0x00000040
++#define FLAG_HWCTEST_FAIL 0x00000080
++
++
+diff --git a/board/aspeed/ast2400/type.h b/board/aspeed/ast2400/type.h
+new file mode 100755
+index 0000000..f57ee5a
+--- /dev/null
++++ b/board/aspeed/ast2400/type.h
+@@ -0,0 +1,116 @@
++/*
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++ */
++#ifndef _TYPE_H_
++#define _TYPE_H_
++
++ typedef unsigned char BOOL;
++ typedef unsigned char UINT8;
++ typedef unsigned short UINT16;
++ typedef unsigned int UINT32;
++
++ #define FLONG unsigned long
++ #define BYTE unsigned char
++ #define INT int
++ #define VOID void
++ #define BOOLEAN unsigned short
++ #define ULONG unsigned long
++ #define USHORT unsigned short
++ #define UCHAR unsigned char
++ #define CHAR char
++ #define LONG long
++ #define PUCHAR UCHAR *
++ #define PULONG ULONG *
++
++ #define FAIL 1
++
++ #define intfunc int386
++
++ #define outdwport outpd
++ #define indwport inpd
++ #define outport outp
++ #define inport inp
++
++ //#define NULL ((void *)0)
++ #define FALSE 0
++ #define TRUE 1
++
++ #define ReadMemoryBYTE(baseaddress,offset) *(BYTE *)((ULONG)(baseaddress)+(ULONG)(offset))
++ #define ReadMemoryLong(baseaddress,offset) *(ULONG *)((ULONG)(baseaddress)+(ULONG)(offset))
++ #define ReadMemoryShort(baseaddress,offset) *(USHORT *)((ULONG)(baseaddress)+(ULONG)(offset))
++ #define WriteMemoryBYTE(baseaddress,offset,data) *(BYTE *)((ULONG)(baseaddress)+(ULONG)(offset)) = (BYTE)(data)
++ #define WriteMemoryLong(baseaddress,offset,data) *(ULONG *)((ULONG)(baseaddress)+(ULONG)(offset))=(ULONG)(data)
++ #define WriteMemoryShort(baseaddress,offset,data) *(USHORT *)((ULONG)(baseaddress)+(ULONG)(offset))=(USHORT)(data)
++ #define WriteMemoryLongWithANDData(baseaddress, offset, anddata, data) *(ULONG *)((ULONG)(baseaddress)+(ULONG)(offset)) = *(ULONG *)((ULONG)(baseaddress)+(ULONG)(offset)) & (ULONG)(anddata) | (ULONG)(data)
++
++ #define WriteMemoryLongWithMASK(baseaddress, offset, data, mask) \
++ *(volatile ULONG *)((ULONG)(baseaddress)+(ULONG)(offset)) = *(volatile ULONG *)(((ULONG)(baseaddress)+(ULONG)(offset)) & (ULONG)(~(mask))) | ((ULONG)(data) & (ULONG)(mask))
++
++ #define ReadMemoryLongHost(baseaddress,offset) *(volatile ULONG *)((ULONG)(baseaddress)+(ULONG)(offset))
++ #define WriteMemoryLongHost(baseaddress,offset,data) *(volatile ULONG *)((ULONG)(baseaddress)+(ULONG)(offset))=(ULONG)(data)
++ #define WriteMemoryBYTEHost(baseaddress,offset,data) *(volatile BYTE *)((ULONG)(baseaddress)+(ULONG)(offset)) = (BYTE)(data)
++#define WriteMemoryLongWithMASKHost(baseaddress, offset, data, mask) *(volatile ULONG *)((ULONG)(baseaddress)+(ULONG)(offset)) = (((*(volatile ULONG *)((ULONG)(baseaddress)+(ULONG)(offset)))&(~mask)) | (ULONG)((data)&(mask)))
++
++ #define ReadMemoryLongClient(baseaddress,offset) *(volatile ULONG *)((ULONG)(baseaddress)+(ULONG)(offset))
++ #define WriteMemoryLongClient(baseaddress,offset,data) *(volatile ULONG *)((ULONG)(baseaddress)+(ULONG)(offset))=(ULONG)(data)
++ #define WriteMemoryBYTEClient(baseaddress,offset,data) *(volatile BYTE *)((ULONG)(baseaddress)+(ULONG)(offset)) = (BYTE)(data)
++#define WriteMemoryLongWithMASKClient(baseaddress, offset, data, mask) *(volatile ULONG *)((ULONG)(baseaddress)+(ULONG)(offset)) = (((*(volatile ULONG *)((ULONG)(baseaddress)+(ULONG)(offset)))&(~mask)) | (ULONG)((data)&(mask)))
++
++#ifdef BUF_GLOBALS
++#define BUF_EXT
++#else
++#define BUF_EXT extern
++#endif
++
++BUF_EXT ULONG g_CAPTURE_VIDEO1_BUF1_ADDR; /* VIDEO1_BUF_1_ADDR*/
++BUF_EXT ULONG g_CAPTURE_VIDEO1_BUF2_ADDR; /* VIDEO1_BUF_2_ADDR*/
++BUF_EXT ULONG g_VIDEO1_COMPRESS_BUF_ADDR; /* Encode destination address */
++BUF_EXT ULONG g_VIDEO1_CRC_BUF_ADDR;
++BUF_EXT ULONG g_VIDEO1_FLAG_BUF_ADDR;
++BUF_EXT ULONG g_VIDEO1_RC4_BUF_ADDR;
++
++
++BUF_EXT ULONG g_CAPTURE_VIDEO2_BUF1_ADDR;
++BUF_EXT ULONG g_CAPTURE_VIDEO2_BUF2_ADDR;
++BUF_EXT ULONG g_VIDEO2_COMPRESS_BUF_ADDR;
++BUF_EXT ULONG g_VIDEO2_CRC_BUF_ADDR;
++BUF_EXT ULONG g_VIDEO2_FLAG_BUF_ADDR;
++BUF_EXT ULONG g_VIDEO2_RC4_BUF_ADDR;
++
++BUF_EXT ULONG g_VIDEO1_DECODE_BUF_1_ADDR;
++BUF_EXT ULONG g_VIDEO1_DECODE_BUF_2_ADDR;
++BUF_EXT ULONG g_VIDEO1_DECOMPRESS_BUF_ADDR;
++BUF_EXT ULONG g_VIDEO1_DECODE_RC4_BUF_ADDR;
++
++BUF_EXT ULONG g_VIDEO2_DECODE_BUF_1_ADDR;
++BUF_EXT ULONG g_VIDEO2_DECODE_BUF_2_ADDR;
++BUF_EXT ULONG g_VIDEO2_DECOMPRESS_BUF_ADDR;
++BUF_EXT ULONG g_VIDEO2_DECODE_RC4_BUF_ADDR;
++
++BUF_EXT ULONG g_CAPTURE_VIDEOM_BUF1_ADDR;
++BUF_EXT ULONG g_CAPTURE_VIDEOM_BUF2_ADDR;
++BUF_EXT ULONG g_VIDEOM_COMPRESS_BUF_ADDR;
++BUF_EXT ULONG g_VIDEOM_FLAG_BUF_ADDR;
++BUF_EXT ULONG g_VIDEOM_RC4_BUF_ADDR;
++
++BUF_EXT ULONG g_VIDEOM_DECODE_BUF_1_ADDR;
++BUF_EXT ULONG g_VIDEOM_DECODE_BUF_2_ADDR;
++BUF_EXT ULONG g_VIDEOM_DECOMPRESS_BUF_ADDR;
++BUF_EXT ULONG g_VIDEOM_DECODE_RC4_BUF_ADDR;
++
++#ifdef WIN_GLOBALS
++#define WIN_EXT
++#else
++#define WIN_EXT extern
++#endif
++
++WIN_EXT USHORT g_DefWidth, g_DefHeight;
++
++#endif
+diff --git a/board/aspeed/ast2400/u-boot.lds b/board/aspeed/ast2400/u-boot.lds
+new file mode 100755
+index 0000000..ff0fe22
+--- /dev/null
++++ b/board/aspeed/ast2400/u-boot.lds
+@@ -0,0 +1,56 @@
++/*
++ * (C) Copyright 2004
++ * Wolfgang Denk, DENX Software Engineering, <wg@denx.de>
++ *
++ * See file CREDITS for list of people who contributed to this
++ * project.
++ *
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License as
++ * published by the Free Software Foundation; either version 2 of
++ * the License, or (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
++ * MA 02111-1307 USA
++ */
++
++OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm")
++/*OUTPUT_FORMAT("elf32-arm", "elf32-arm", "elf32-arm")*/
++OUTPUT_ARCH(arm)
++ENTRY(_start)
++SECTIONS
++{
++ . = 0x00000000;
++
++ . = ALIGN(4);
++ .text :
++ {
++ cpu/arm926ejs/start.o (.text)
++ *(.text)
++ }
++
++ . = ALIGN(4);
++ .rodata : { *(.rodata) }
++
++ . = ALIGN(4);
++ .data : { *(.data) }
++
++ . = ALIGN(4);
++ .got : { *(.got) }
++
++ __u_boot_cmd_start = .;
++ .u_boot_cmd : { *(.u_boot_cmd) }
++ __u_boot_cmd_end = .;
++
++ . = ALIGN(4);
++ __bss_start = .;
++ .bss : { *(.bss) }
++ _end = .;
++}
+diff --git a/board/aspeed/ast2400/vdef.h b/board/aspeed/ast2400/vdef.h
+new file mode 100755
+index 0000000..3c99b7e
+--- /dev/null
++++ b/board/aspeed/ast2400/vdef.h
+@@ -0,0 +1,500 @@
++/*
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++ */
++#ifndef _VDEF_H_
++#define _VDEF_H_
++
++#define VIDEO1 0
++#define VIDEO1_ON 0x01
++#define VIDEO2 1
++#define VIDEO2_ON 0x02
++
++#define VIDEOM_ON 0x04
++#define VIDEOM 2
++
++#define CRT_1 0
++#define CRT_1_ON 0x01
++#define CRT_2 1
++#define CRT_2_ON 0x02
++
++#define SINGLE_CODEC_SINGLE_CAPTURE 0
++#define AUTO_CODEC_SINGLE_CAPTURE 2
++#define AUTO_CODEC_AUTO_CAPTURE 3
++
++#define MAC1_BASE 0x1E660000
++#define APB_BRIDGE_1_BASE 0x1E6E0000
++#define VIDEO_REG_BASE 0x1E700000
++#define APB_BRIDGE_2_BASE 0x1E780000
++
++#define DRAM_INIT_BASE 0x1E6E0000
++
++#define SDRAM_PROTECT_REG 0x00
++ #define SDRAM_WRITE_DISABLE 0
++ #define SDRAM_WRITE_ENABLE 1
++
++#define SCU_BASE 0x1E6E0000
++#define SCU_OFFSET 0x2000
++
++#define VIC_BASE 0x1E6C0000
++ #define VIDEO_INT_BIT 7
++
++#define IRQ_STATUS_REG 0x00
++#define RAW_INT_STATUS_REG 0x08
++#define INT_SEL_REG 0x0C
++ #define FIQ_INT 1
++ #define IRQ_INT 0
++#define INT_EN_REG 0x10
++#define INT_EN_CLEAR_REG 0x14
++#define INT_SOFT_REG 0x18
++#define INT_SOFT_CLEAR_REG 0x1C
++#define INT_SENSE_REG 0x24
++ #define LEVEL_SENSE 1
++ #define EDGE_SENSE 0
++#define INT_EVENT_REG 0x2C
++ #define HIGH_LEVEL_SENSE 1
++ #define LOW_LEVEL_SENSE 0
++
++#define SCU_HW_TRAPPING_REG 0x70 + SCU_OFFSET
++ #define CLIENT_MODE_EN_BIT 18
++ #define CLIENT_MODE_EN_MASK 0x00040000
++ #define BE_HOST_CHIP 0
++ #define BE_CLIENT_CHIP 1
++
++#define SCU_ULOCK_KEY 0x1688A8A8
++
++#define SCU_PROTECT_REG 0x00 + SCU_OFFSET
++ #define SCU_WRITE_DISABLE 0
++ #define SCU_WRITE_ENABLE 1
++
++#define SCU_CONTROL_REG 0x04 + SCU_OFFSET
++ #define VIDEO_ENGINE_RESET 0x00000040
++ #define VIDEO_ENGINE_RESET_BIT 6
++ #define VIDEO_ENGINE_RESET_MASK 0x00000040
++ #define VIDEO_RESET_EN 1
++ #define VIDEO_RESET_OFF 0
++
++#define SCU_CLOCK_SELECTION_REG 0x08 + SCU_OFFSET
++ #define PORTA_CLOCK_DELAY_MASK 7 << 8 //Video port A output clcok selection
++ #define PORTA_CLOCK_INV_DELAY_1NS 5 << 8 //Clock inversed and delay ~ 2ns
++ #define PORTA_CLOCK_INV_DELAY_2NS 6 << 8 //Clock inversed and delay ~ 3ns
++ #define PORTB_CLOCK_DELAY_MASK 7 << 12 //Video port B output clock delay
++ #define PORTB_CLOCK_INV_DELAY_1NS 5 << 12 //Clock inversed and delay ~ 3ns
++ #define PORTB_CLOCK_INV_DELAY_2NS 6 << 12 //Clock inversed and delay ~ 3ns
++ #define PORTB_CLOCK_SEL 1 << 15 //Video port B clock selection
++ #define PORTB_FROM_D1CLK 0 << 15
++ #define PORTB_FROM_D2CLK 1 << 15
++ #define ECLK_CLK_SEL_MASK (3 << 2)
++ #define ECLK_FROM_HPLL (1 << 2)
++
++ #define D2CLK_CLOCK_SELECTION 0x00020000
++ #define D2CLK_CLOCK_SELECTION_BIT 17
++ #define D2CLK_CLOCK_SELECTION_MASK 0x00060000
++ #define NORMAL_CRT1 0
++ #define V1CLK_VIDEO1 2
++ #define V1CLK_VIDEO2 3
++
++#define SCU_CLOCK_STOP_REG 0x0C + SCU_OFFSET
++ #define EN_ECLK 0 << 0 //Enable ECLK (For Video Engine)
++ #define STOP_ECLK_BIT 0
++ #define STOP_ECLK_MASK 1 << 0
++ #define EN_V1CLK 0 << 3 //Enable V1CLK (For Video Capture #1)
++ #define STOP_V1CLK_BIT 3
++ #define STOP_V1CLK_MASK 1 << 3
++ #define EN_D1CLK 0 << 10 //Enable D1CLK (For CRT1)
++ #define STOP_D1CLK_BIT 10
++ #define STOP_D1CLK_MASK 1 << 10
++ #define EN_D2CLK 0 << 11 //Stop D2CLK (For CRT2)
++ #define STOP_D2CLK (1 << 11)
++ #define STOP_D2CLK_BIT 11
++ #define STOP_D2CLK_MASK 1 << 11
++ #define EN_V2CLK 0 << 12 //Stop V2CLK (For Video Capture #2)
++ #define STOP_V2CLK_BIT 12
++ #define STOP_V2CLK_MASK 1 << 12
++ #define STOP_HACE_BIT 13
++ #define EN_HACE (0 << 13)
++ #define STOP_HACE_MASK (1 << 13)
++ #define EN_I2SCLK 0 << 18
++ #define STOP_I2SCLK_MASK 1 << 18
++
++#define SCU_PIN_CTRL1_REG 0x74 + SCU_OFFSET
++ #define I2C_5_PIN_EN 1 << 12 //Enable I2C #5 PIN
++ #define I2C_5_PIN_OFF 0 << 12 //Disable I2C #5 PIN
++ #define I2C_5_PIN_MASK 1 << 12
++ #define VGA_PIN_OFF 0 << 15 //Enable VGA pins
++ #define VGA_PIN_MASK 1 << 15
++ #define VIDEO_PORTA_EN 1 << 16 //Enable Video port A control pins
++ #define VIDEO_PORTA_MASK 1 << 16
++ #define VIDEO_PORTB_EN 1 << 17 //Enable Video port B control pins
++ #define VIDEO_PORTB_MASK 1 << 17
++ #define VIDEO_VP1_EN 1 << 22 //Enable VP[11:0]
++ #define VIDEO_VP1_MASK 1 << 22
++ #define VIDEO_VP2_EN 1 << 23 //Enable VP[23:12]
++ #define VIDEO_VP2_MASK 1 << 23
++ #define I2S_PIN_EN 1 << 29 //Enable I2S function pins
++ #define I2S_PIN_MASK 1 << 29
++
++#define SCU_PIN_CTRL2_REG 0x78 + SCU_OFFSET
++ #define VIDEO_PORTA_SINGLE_EDGE_MASK 1 << 0
++ #define VIDEO_PORTA_SINGLE_EDGE 1 << 0 //Enable Video port A single mode
++ #define VIDEO_PORTA_DUAL_EDGE 0 << 0
++ #define VIDEO_PORTB_SINGLE_EDGE_MASK 1 << 1
++ #define VIDEO_PORTB_DUAL_EDGE 0 << 1
++ #define VIDEO_PORTB_SINGLE_EDGE 1 << 1 //Enable Video port B single mode
++
++#define SCU_M_PLL_PARAM_REG 0x20 + SCU_OFFSET
++
++#define DRAM_BASE 0x40000000
++
++#define INPUT_BITCOUNT_YUV444 4
++#define INPUT_BITCOUNT_YUV420 2
++
++/* HW comment value */
++//PASSWORD
++#define VIDEO_UNLOCK_KEY 0x1A038AA8
++#define SCU_UNLOCK_KEY 0x1688A8A8
++#define SDRAM_UNLOCK_KEY 0xFC600309
++
++
++//#define SAMPLE_RATE 12000000.0
++#ifdef OSC_NEW
++ #define SAMPLE_RATE 24576000.0
++#else
++ #define SAMPLE_RATE 24000000.0
++#endif
++
++#define MODEDETECTION_VERTICAL_STABLE_MAXIMUM 0x4
++#define MODEDETECTION_HORIZONTAL_STABLE_MAXIMUM 0x4
++#define MODEDETECTION_VERTICAL_STABLE_THRESHOLD 0x4
++#define MODEDETECTION_HORIZONTAL_STABLE_THRESHOLD 0x8
++
++#define MODEDETECTION_EDGE_PIXEL_THRES_DIGITAL 2
++#define MODEDETECTION_EDGE_PIXEL_THRES_ANALOGE 0x0A
++
++#define MODEDETECTION_OK 0
++#define MODEDETECTION_ERROR 1
++#define JUDGE_MODE_ERROR 2
++
++//I2C Loop Count
++#define LOOP_COUNT 1000
++#define CAN_NOT_FIND_DEVICE 1
++#define SET_I2C_DONE 0
++#define I2C_BASE 0xA000
++#define AC_TIMING 0x77743355
++
++//I2C channel and Devices
++#define I2C_VIDEO1_EEPROM 0x2
++#define I2C_VIDEO2_EEPROM 0x5
++#define I2C_VIDEO2_9883 0x4
++/*
++ULONG CAPTURE1_ADDRESS = 0x1000000;
++ULONG CAPTURE2_ADDRESS = 0x3000000;
++ULONG PASS1_ENCODE_SOURCE_ADDRESS = 0x1000000;
++ULONG PASS1_ENCODE_DESTINATION_ADDRESS = 0x2000000;
++ULONG Buffer1_DECODE_SOURCE_ADDRESS = 0x1000000;
++ULONG Buffer2_DECODE_SOURCE_ADDRESS = 0x1400000;
++ULONG PASS1_DECODE_DESTINATION_ADDRESS = 0x600000;
++ULONG CAPTURE_2ND_ADDRESS = 0x1800000;
++ULONG PASS1_2ND_ENCODE_SOURCE_ADDRESS = 0x1800000;
++ULONG PASS1_2ND_ENCODE_DESTINATION_ADDRESS = 0x2800000;
++ULONG PASS1_2ND_DECODE_SOURCE_ADDRESS = 0x1000000;
++ULONG PASS1_2ND_DECODE_DESTINATION_ADDRESS = 0x600000;
++ULONG PASS2_ENCODE_SOURCE_ADDRESS = 0x000000;
++ULONG PASS2_ENCODE_DESTINATION_ADDRESS = 0xC00000;
++ULONG PASS2_DECODE_SOURCE_ADDRESS = 0xC00000;
++ULONG PASS2_DECODE_DESTINATION_ADDRESS = 0x600000;
++ULNG PASS2_DECODE_REFERENCE_ADDRESS = 0x600000;
++*/
++
++typedef struct _CTL_REG_G {
++ ULONG CompressMode:1;
++ ULONG SkipEmptyFrame:1;
++ ULONG MemBurstLen:2;
++ ULONG LineBufEn:2;
++ ULONG Unused:26;
++} CTL_REG_G;
++
++
++typedef union _U_CTL_G {
++ ULONG Value;
++ CTL_REG_G CtlReg;
++} U_CTL_G;
++
++typedef struct _MODE_DETECTION_PARAM_REG {
++ ULONG Unused1:8;
++ ULONG EdgePixelThres:8;
++ ULONG VerStableMax:4;
++ ULONG HorStableMax:4;
++ ULONG VerDiffMax:4;
++ ULONG HorDiffMax:4;
++} MODE_DETECTION_PARAM_REG;
++
++typedef struct _CRC_PRI_PARAM_REG {
++ ULONG Enable:1;
++ ULONG HighBitOnly:1;
++ ULONG SkipCountMax:6;
++ ULONG PolyLow:8;
++ ULONG PolyHigh:16;
++} CRC_PRI_PARAM_REG;
++
++typedef union _U_CRC_PRI_PARAM {
++ ULONG Value;
++ CRC_PRI_PARAM_REG CRCPriParam;
++} U_CRC_PRI_PARAM;
++
++typedef struct _CRC_SEC_PARAM_REG {
++ ULONG Unused1:8;
++ ULONG PolyLow:8;
++ ULONG PolyHigh:16;
++} CRC_SEC_PARAM_REG;
++
++typedef union _U_CRC_SEC_PARAM {
++ ULONG Value;
++ CRC_SEC_PARAM_REG CRCSecParam;
++} U_CRC_SEC_PARAM;
++
++typedef struct _GENERAL_INFO {
++ BYTE EnableVideoM;
++ BYTE CenterMode;
++ BYTE RC4NoResetFrame;
++ BYTE RC4TestMode;
++ U_CTL_G uCtlReg;
++ U_CRC_PRI_PARAM uCRCPriParam;
++ U_CRC_SEC_PARAM uCRCSecParam;
++} GENERAL_INFO, *PGENERAL_INFO;
++
++typedef struct _SEQ_CTL_REG {
++ ULONG Unused1:1;
++ ULONG Unused2:1;
++ ULONG Unused3:1;
++ ULONG CaptureAutoMode:1;
++ ULONG Unused4:1;
++ ULONG CodecAutoMode:1;
++ ULONG Unused5:1;
++ ULONG WatchDog:1;
++ ULONG CRTSel:1;
++ ULONG AntiTearing:1;
++ ULONG DataType:2;
++ ULONG Unused6:20;
++} SEQ_CTL_REG;
++
++typedef union _U_SEQ_CTL {
++ ULONG Value;
++ SEQ_CTL_REG SeqCtlReg;
++} U_SEQ_CTL;
++
++typedef struct _CTL_REG {
++ ULONG SrcHsync:1;
++ ULONG SrcVsync:1;
++ ULONG ExtSrc:1;
++ ULONG AnalongExtSrc:1;
++ ULONG IntTimingGen:1;
++ ULONG IntDataFrom:1;
++ ULONG WriteFmt:2;
++ ULONG VGACursor:1;
++ ULONG LinearMode:1;
++ ULONG ClockDelay:2;
++ ULONG CCIR656Src:1;
++ ULONG PortClock:1;
++ ULONG ExtPort:1;
++ ULONG Unused1:1;
++ ULONG FrameRate:8;
++ ULONG Unused2:8;
++} CTL_REG;
++
++typedef union _U_CTL {
++ ULONG Value;
++ CTL_REG CtlReg;
++} U_CTL_REG;
++
++typedef struct _TIMING_GEN_SETTING_H {
++ ULONG HDEEnd:13;
++ ULONG Unused1:3;
++ ULONG HDEStart:13;
++ ULONG Unused2:3;
++} TIMING_GEN_SETTING_H;
++
++typedef struct _TIMING_GEN_SETTING_V {
++ ULONG VDEEnd:13;
++ ULONG Unused1:3;
++ ULONG VDEStart:13;
++ ULONG Unused2:3;
++} TIMING_GEN_SETTING_V;
++
++typedef struct _BCD_CTL_REG {
++ ULONG Enable:1;
++ ULONG Unused1:15;
++ ULONG Tolerance:8;
++ ULONG Unused2:8;
++} BCD_CTL_REG;
++
++typedef union _U_BCD_CTL {
++ ULONG Value;
++ BCD_CTL_REG BCDCtlReg;
++} U_BCD_CTL;
++
++typedef struct _COMPRESS_WINDOW_REG {
++ ULONG VerLine:13;
++ ULONG Unused1:3;
++ ULONG HorPixel:13;
++ ULONG Unused2:3;
++} COMPRESS_WINDOW_REG;
++
++typedef struct _STREAM_BUF_SIZE {
++ ULONG PacketSize:3;
++ ULONG RingBufNum:2;
++ ULONG Unused1:11;
++ ULONG SkipHighMBThres:7;
++ ULONG SkipTestMode:2;
++ ULONG Unused2:7;
++} STREAM_BUF_SIZE;
++
++typedef union _U_STREAM_BUF {
++ ULONG Value;
++ STREAM_BUF_SIZE StreamBufSize;
++} U_STREAM_BUF;
++
++
++typedef struct _COMPRESS_CTL_REG {
++ ULONG JPEGOnly:1; /* True: Jpeg Only mode(Disable VQ), False:Jpeg and VQ mix mode */
++ ULONG En4VQ:1; /* True: 1, 2, 4 color mode, False: 1,2 color mode */
++ ULONG CodecMode:1; /* High and best Quantization encoding/decoding setting*/
++ ULONG DualQuality:1;
++ ULONG EnBest:1;
++ ULONG EnRC4:1;
++ ULONG NorChromaDCTTable:5;
++ ULONG NorLumaDCTTable:5;
++ ULONG EnHigh:1;
++ ULONG TestCtl:2;
++ ULONG UVFmt:1;
++ ULONG HufTable:2;
++ ULONG AlterValue1:5;
++ ULONG AlterValue2:5;
++} COMPRESS_CTL_REG;
++
++typedef union _U_COMPRESS_CTL {
++ ULONG Value;
++ COMPRESS_CTL_REG CompressCtlReg;
++} U_COMPRESS_CTL;
++
++typedef struct _QUANTI_TABLE_LOW_REG {
++ ULONG ChromaTable:5;
++ ULONG LumaTable:5;
++ ULONG Unused1:22;
++} QUANTI_TABLE_LOW_REG;
++
++typedef union _U_CQUANTI_TABLE_LOW {
++ ULONG Value;
++ QUANTI_TABLE_LOW_REG QTableLowReg;
++} U_QUANTI_TABLE_LOW;
++
++typedef struct _QUANTI_VALUE_REG {
++ ULONG High:15;
++ ULONG Unused1:1;
++ ULONG Best:15;
++ ULONG Unused2:1;
++} QUANTI_VALUE_REG;
++
++typedef union _U_QUANTI_VALUE {
++ ULONG Value;
++ QUANTI_VALUE_REG QValueReg;
++} U_QUANTI_VALUE;
++
++typedef struct _BSD_PARAM_REG {
++ ULONG HighThres:8;
++ ULONG LowThres:8;
++ ULONG HighCount:6;
++ ULONG Unused1:2;
++ ULONG LowCount:6;
++ ULONG Unused2:2;
++} BSD_PARAM_REG;
++
++typedef union _U_BSD_PARAM {
++ ULONG Value;
++ BSD_PARAM_REG BSDParamReg;
++} U_BSD_PARAM;
++
++typedef struct _VIDEO_INFO {
++ BYTE ExtADCAct; /* read from modection register */
++ BYTE EnableRC4;
++ BYTE DownScalingMethod;
++ USHORT AnalogDifferentialThreshold; /* BCD tolerance */
++ USHORT DigitalDifferentialThreshold; /* BCD tolerance */
++ USHORT DstWidth;
++ USHORT DstHeight;
++ USHORT SrcWidth;
++ USHORT SrcHeight;
++ BYTE HighLumaTable; /* if High and best Jpeg codec enable, use HighLumaTable and HighChromaTable, otherwise HighDeQuantiValue and BestDequantiValue*/
++ BYTE HighChromaTable;
++ BYTE HighDeQuantiValue;
++ BYTE BestDequantiValue;
++ U_SEQ_CTL uSeqCtlReg;
++ U_CTL_REG uCtlReg;
++ U_BCD_CTL uBCDCtlReg;
++ U_STREAM_BUF uStreamBufSize;
++ U_COMPRESS_CTL uCompressCtlReg;
++ U_QUANTI_TABLE_LOW uQTableLowReg;
++ U_QUANTI_VALUE uQValueReg;
++ U_BSD_PARAM uBSDParamReg;
++} VIDEO_INFO, *PVIDEO_INFO ;
++
++typedef struct _VIDEOM_SEQ_CTL_REG {
++ ULONG Unused1:1; //Bit 0
++ ULONG Unused2:1; //Bit 1
++ ULONG Unused3:1; //Bit 2
++ ULONG StreamMode:1; //Bit 3
++ ULONG Unused4:1; //Bit 4
++ ULONG CodecAutoMode:1; //Bit 5
++ ULONG Unused6:1; //Bit 6
++ ULONG Unused7:1; //Bit 7
++ ULONG SrcSel:1; //Bit 8
++ ULONG Unused9:1; //Bit 9
++ ULONG DataType:2; //Bit[11:10]
++ ULONG Unused12:20;
++} VIDEOM_SEQ_CTL_REG;
++
++typedef union _U_VIDEOM_SEQ_CTL {
++ ULONG Value;
++ VIDEOM_SEQ_CTL_REG SeqCtlReg;
++} U_VIDEOM_SEQ_CTL;
++
++typedef struct _VIDEOM_INFO {
++ BYTE DownScalingMethod;
++ USHORT AnalogDifferentialThreshold; /* BCD tolerance */
++ USHORT DigitalDifferentialThreshold; /* BCD tolerance */
++ USHORT DstWidth;
++ USHORT DstHeight;
++ USHORT SrcWidth;
++ USHORT SrcHeight;
++ BYTE HighLumaTable; /* if High and best Jpeg codec enable, use HighLumaTable and HighChromaTable, otherwise HighDeQuantiValue and BestDequantiValue*/
++ BYTE HighChromaTable;
++ BYTE HighDeQuantiValue;
++ BYTE BestDequantiValue;
++ BYTE PacketSize; //the same as video1 & video2
++ BYTE RingBufNum;
++ BYTE EnableRC4;
++ U_VIDEOM_SEQ_CTL uSeqCtlReg;
++ U_BCD_CTL uBCDCtlReg;
++ U_COMPRESS_CTL uCompressCtlReg;
++ U_QUANTI_TABLE_LOW uQTableLowReg;
++ U_QUANTI_VALUE uQValueReg;
++ U_BSD_PARAM uBSDParamReg;
++} VIDEOM_INFO, *PVIDEOM_INFO ;
++
++typedef struct _VIDEO_MODE_INFO
++{
++ USHORT X;
++ USHORT Y;
++ USHORT ColorDepth;
++ USHORT RefreshRate;
++ BYTE ModeIndex;
++} VIDEO_MODE_INFO, *PVIDEO_MODE_INFO;
++
++#endif
++
+diff --git a/board/aspeed/ast2400/vesa.h b/board/aspeed/ast2400/vesa.h
+new file mode 100755
+index 0000000..69aba90
+--- /dev/null
++++ b/board/aspeed/ast2400/vesa.h
+@@ -0,0 +1,163 @@
++/*
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++ */
++#ifndef _VESA_H_
++#define _VESA_H_
++
++typedef enum
++{
++ VCLK25_175 = 0x00,
++ VCLK28_322 = 0x01,
++ VCLK31_5 = 0x02,
++ VCLK31_574 = 0x03,
++ VCLK32_76 = 0x04,
++ VCLK33_154 = 0x05,
++ VCLK36 = 0x06,
++ VCLK40 = 0x07,
++ VCLK45_978 = 0x08,
++ VCLK49_5 = 0x09,
++ VCLK50 = 0x0A,
++ VCLK52_95 = 0x0B,
++ VCLK56_25 = 0x0C,
++ VCLK65 = 0x0D,
++ VCLK74_48 = 0x0E,
++ VCLK75 = 0x0F,
++ VCLK78_75 = 0x10,
++ VCLK79_373 = 0x11,
++ VCLK81_624 = 0x12,
++ VCLK83_462 = 0x13,
++ VCLK84_715 = 0x14,
++ VCLK94_5 = 0x15,
++ VCLK106_5 = 0x16,
++ VCLK108 = 0x17,
++ VCLK119 = 0x18,
++ VCLK135 = 0x19,
++ VCLK136_358 = 0x1A,
++ VCLK146_25 = 0x1B,
++ VCLK154 = 0x1C,
++ VCLK157_5 = 0x1D,
++ VCLK162 = 0x1E
++} ePIXEL_CLOCK;
++
++typedef struct {
++ USHORT HorizontalTotal;
++ USHORT VerticalTotal;
++ USHORT HorizontalActive;
++ USHORT VerticalActive;
++ BYTE RefreshRate;
++ double HorizontalFrequency;
++ USHORT HSyncTime;
++ USHORT HBackPorch;
++ USHORT VSyncTime;
++ USHORT VBackPorch;
++ USHORT HLeftBorder;
++ USHORT HRightBorder;
++ USHORT VBottomBorder;
++ USHORT VTopBorder;
++ USHORT PixelClock;
++ BOOL HorPolarity;
++ BOOL VerPolarity;
++ BYTE ADCIndex1;
++ BYTE ADCIndex2;
++ BYTE ADCIndex3;
++ BYTE ADCIndex5;
++ BYTE ADCIndex6;
++ BYTE ADCIndex7;
++ BYTE ADCIndex8;
++ BYTE ADCIndex9;
++ BYTE ADCIndexA;
++ BYTE ADCIndexF;
++ BYTE ADCIndex15;
++ int HorizontalShift;
++ int VerticalShift;
++} VESA_MODE;
++
++#define HOR_POSITIVE 0
++#define HOR_NEGATIVE 1
++#define VER_POSITIVE 0
++#define VER_NEGATIVE 1
++
++#ifdef VESA_GLOBALS
++
++// Note: Modified for modes which have border issue
++VESA_MODE vModeTable[] = {
++////////////////////////// 60Hz mode
++// 720x480 done
++ {1056, 497, 720, 480, 60, 29.900, 88, 104, 3, 13, 0, 0, 0, 0, VCLK31_574, HOR_NEGATIVE, VER_NEGATIVE, 0x41, 0xF0, 0x48, 0x05, 0x20, 0x58, 0x60, 0x60, 0x60, 0x5E, 0xFE, 6, 2},
++// 848x480 done
++ {1064, 517, 848, 480, 60, 31.160, 88, 91, 3, 26, 0, 0, 0, 0, VCLK33_154, HOR_NEGATIVE, VER_NEGATIVE, 0x42, 0x70, 0x48, 0x05, 0x20, 0x58, 0x60, 0x60, 0x60, 0x5E, 0xFE, 6, 2},
++ {800, 525, 640, 480, 60, 31.469, 96, 40, 2, 25, 1, 1, 8, 8, VCLK25_175, HOR_NEGATIVE, VER_NEGATIVE, 0x31, 0xF0, 0x48, 0x05, 0x20, 0x60, 0x60, 0x60, 0x60, 0x5E, 0xFE, 6, 2},
++// 720x576
++ {912, 597, 720, 576, 60, 35.920, 72, 88, 3, 17, 0, 0, 0, 0, VCLK32_76, HOR_NEGATIVE, VER_NEGATIVE, 0x38, 0xF0, 0x48, 0x05, 0x20, 0x48, 0x60, 0x60, 0x60, 0x5E, 0xFE, 6, 2},
++// 960x600 GTF done
++ {1232, 622, 960, 600, 60, 37.320, 96, 136, 3, 18, 0, 0, 0, 0, VCLK45_978, HOR_NEGATIVE, VER_NEGATIVE, 0x4C, 0xF0, 0x60, 0x05, 0x20, 0x60, 0x60, 0x60, 0x60, 0x5E, 0xFE, -1, 0},
++ {1056, 628, 800, 600, 60, 37.879, 128, 88, 4, 23, 0, 0, 0, 0, VCLK40, HOR_POSITIVE, VER_POSITIVE, 0x41, 0xF0, 0x60, 0x05, 0x20, 0x80, 0x60, 0x60, 0x60, 0x5E, 0xFE, -1, 0},
++// 1088x612 GTF done
++ {1392, 634, 1088, 612, 60, 38.04, 112, 152, 3, 18, 0, 0, 0, 0, VCLK52_95, HOR_NEGATIVE, VER_NEGATIVE, 0x56, 0xF0, 0x60, 0x05, 0x20, 0x70, 0x60, 0x60, 0x60, 0x5E, 0xFE, -1, 0},
++// 1280x720 GTF done
++ {1664, 746, 1280, 720, 60, 44.760, 136, 192, 3, 22, 0, 0, 0, 0, VCLK74_48, HOR_NEGATIVE, VER_NEGATIVE, 0x67, 0xF0, 0xA8, 0x05, 0x20, 0x88, 0x60, 0x60, 0x60, 0x5E, 0xFE, -1, 0},
++// 1360x768 GTF done
++ {1776, 795, 1360, 768, 60, 47.700, 144, 208, 3, 23, 0, 0, 0, 0, VCLK84_715, HOR_NEGATIVE, VER_NEGATIVE, 0x6E, 0xF0, 0xA8, 0x05, 0x20, 0x90, 0x60, 0x60, 0x60, 0x5E, 0xFE, 7, 1},
++// 1280x768 done
++ {1664, 798, 1280, 768, 60, 47.700, 128, 184, 7, 20, 0, 0, 0, 0, VCLK79_373, HOR_NEGATIVE, VER_NEGATIVE, 0x67, 0xF0, 0xA8, 0x05, 0x20, 0x80, 0x60, 0x60, 0x60, 0x5E, 0xFE, 7, 1},
++ {1344, 806, 1024, 768, 60, 48.363, 136, 160, 6, 29, 0, 0, 0, 0, VCLK65, HOR_NEGATIVE, VER_NEGATIVE, 0x53, 0xF0, 0xA8, 0x05, 0x20, 0x88, 0x60, 0x60, 0x60, 0x5E, 0xFE, -1, 7},
++// 1280x800 GTF done
++ {1680, 828, 1280, 800, 60, 49.680, 136, 200, 3, 24, 0, 0, 0, 0, VCLK83_462, HOR_NEGATIVE, VER_NEGATIVE, 0x68, 0xF0, 0xA8, 0x05, 0x20, 0x88, 0x60, 0x60, 0x60, 0x5E, 0xFE, -1, 0},
++// 1152x864 GTF done
++ {1520, 895, 1152, 864, 60, 53.700, 120, 184, 3, 27, 0, 0, 0, 0, VCLK81_624, HOR_NEGATIVE, VER_NEGATIVE, 0x5E, 0xF0, 0xA8, 0x05, 0x20, 0x78, 0x60, 0x60, 0x60, 0x5E, 0xFE, -1, 0},
++// 1600x900 GTF done
++ {2128, 932, 1600, 900, 60, 55.920, 168, 264, 3, 28, 0, 0, 0, 0, VCLK119, HOR_NEGATIVE, VER_NEGATIVE, 0x84, 0xF0, 0xA8, 0x05, 0x20, 0xA8, 0x60, 0x60, 0x60, 0x5E, 0xFE, -1, 0},
++// 1440X900 CVT done
++ {1904, 933, 1440, 900, 60, 55.935, 152, 232, 6, 25, 0, 0, 0, 0, VCLK106_5, HOR_NEGATIVE, VER_POSITIVE, 0x76, 0xF0, 0xA8, 0x05, 0x20, 0x96, 0x60, 0x60, 0x60, 0x5E, 0xFE, -1, 0},
++ {1800, 1000, 1280, 960, 60, 60.000, 112, 312, 3, 36, 0, 0, 0, 0, VCLK108, HOR_POSITIVE, VER_POSITIVE, 0x70, 0x70, 0xA8, 0x05, 0x20, 0x70, 0x60, 0x60, 0x60, 0x5E, 0xFE, -1, 0},
++// 1600x1024 GTF done
++ {2144, 1060, 1600, 1024, 60, 63.600, 168, 272, 3, 32, 0, 0, 0, 0, VCLK136_358, HOR_NEGATIVE, VER_NEGATIVE, 0x85, 0xF0, 0xE8, 0x05, 0x20, 0xA8, 0x60, 0x60, 0x60, 0x5E, 0xFE, -1, 0},
++ {1688, 1066, 1280, 1024, 60, 63.981, 112, 248, 3, 38, 0, 0, 0, 0, VCLK108, HOR_POSITIVE, VER_POSITIVE, 0x69, 0x70, 0xA8, 0x05, 0x20, 0x70, 0x60, 0x60, 0x60, 0x5E, 0xFE, -1, 0},
++// 1680X1050 CVT done Reduced Blanking
++ {1840, 1080, 1680, 1050, 60, 64.674, 32, 80, 6, 21, 0, 0, 0, 0, VCLK119, HOR_POSITIVE, VER_NEGATIVE, 0x72, 0xF0, 0xA8, 0x05, 0x20, 0x20, 0x60, 0x60, 0x60, 0x5E, 0xFE, -1, 0},
++// 1920X1200 CVT done Reduced Blanking
++ {2080, 1235, 1920, 1200, 60, 74.038, 32, 80, 6, 26, 0, 0, 0, 0, VCLK154, HOR_POSITIVE, VER_NEGATIVE, 0x81, 0xF0, 0xA8, 0x05, 0x20, 0x20, 0x60, 0x60, 0x60, 0x5E, 0xFE, -1, 0},
++ //{2160, 1250, 1600, 1200, 60,75.000, 192, 304, 3, 46, 0, 0, 0, 0, VCLK162, HOR_POSITIVE, VER_POSITIVE},
++ {2160, 1248, 1600, 1200, 60, 75.000, 192, 304, 3, 46, 0, 0, 0, 0, VCLK162, HOR_POSITIVE, VER_POSITIVE, 0x86, 0xF0, 0xE8, 0x05, 0x20, 0xC0, 0x60, 0x60, 0x60, 0x5E, 0xFE, -1, 0},
++
++////////////////////// Not 60Hz mode
++ {900, 449, 720, 400, 70, 31.469, 108, 45, 2, 25, 1, 1, 8, 8, 0, HOR_NEGATIVE, VER_NEGATIVE, 0x38, 0x30, 0x48, 0x05, 0x20, 0x6C, 0x60, 0x60, 0x60, 0x5E, 0xFE, 6, 1},
++ {832, 520, 640, 480, 72, 37.861, 40, 120, 3, 20, 1, 1, 8, 8, 0, HOR_NEGATIVE, VER_NEGATIVE, 0x33, 0xF0, 0x48, 0x05, 0x20, 0x28, 0x60, 0x60, 0x60, 0x5E, 0xFE, 6, 3},
++ {840, 500, 640, 480, 75, 37.500, 64, 120, 3, 16, 0, 0, 0, 0, 0, HOR_NEGATIVE, VER_NEGATIVE, 0x34, 0x70, 0x48, 0x05, 0x20, 0x40, 0x60, 0x60, 0x60, 0x5E, 0xFE, -1, 3},
++ {832, 509, 640, 480, 85, 43.269, 56, 80, 3, 25, 0, 0, 0, 0, 0, HOR_NEGATIVE, VER_NEGATIVE, 0x33, 0xF0, 0x48, 0x05, 0x20, 0x38, 0x60, 0x60, 0x60, 0x5E, 0xFE, -1, 3},
++ {1024, 625, 800, 600, 56, 35.156, 72, 128, 2, 22, 0, 0, 0, 0, 0, HOR_POSITIVE, VER_POSITIVE, 0x3F, 0xF0, 0x60, 0x05, 0x20, 0x48, 0x60, 0x60, 0x60, 0x5E, 0xFE, -1, 0},
++ {1040, 666, 800, 600, 72, 48.077, 120, 64, 6, 23, 0, 0, 0, 0, 0, HOR_POSITIVE, VER_POSITIVE, 0x40, 0xF0, 0x60, 0x05, 0x20, 0x78, 0x60, 0x60, 0x60, 0x5E, 0xFE, -1, 0},
++ {1056, 625, 800, 600, 75, 46.875, 80, 160, 3, 21, 0, 0, 0, 0, 0, HOR_POSITIVE, VER_POSITIVE, 0x41, 0xF0, 0x60, 0x05, 0x20, 0x50, 0x60, 0x60, 0x60, 0x5E, 0xFE, -1, 0},
++ {1048, 631, 800, 600, 85, 53.674, 64, 152, 3, 27, 0, 0, 0, 0, 0, HOR_POSITIVE, VER_POSITIVE, 0x41, 0x70, 0x60, 0x05, 0x20, 0x40, 0x60, 0x60, 0x60, 0x5E, 0xFE, -1, 0},
++ {1328, 806, 1024, 768, 70, 56.476, 136, 144, 6, 29, 0, 0, 0, 0, 0, HOR_NEGATIVE, VER_NEGATIVE, 0x52, 0xF0, 0xA8, 0x05, 0x20, 0x88, 0x60, 0x60, 0x60, 0x5E, 0xFE, -1, 7},
++ {1312, 800, 1024, 768, 75, 60.023, 96, 176, 3, 28, 0, 0, 0, 0, 0, HOR_POSITIVE, VER_POSITIVE, 0x51, 0xF0, 0xA8, 0x05, 0x20, 0x60, 0x60, 0x60, 0x60, 0x5E, 0xFE, -1, 1},
++ {1376, 808, 1024, 768, 85, 68.677, 96, 208, 3, 36, 0, 0, 0, 0, 0, HOR_POSITIVE, VER_POSITIVE, 0x55, 0xF0, 0xA8, 0x05, 0x20, 0x60, 0x60, 0x60, 0x60, 0x5E, 0xFE, -1, 1},
++ {1600, 900, 1152, 864, 75, 67.500, 128, 256, 3, 32, 0, 0, 0, 0, 0, HOR_POSITIVE, VER_POSITIVE, 0x63, 0xF0, 0xA8, 0x05, 0x20, 0x80, 0x60, 0x60, 0x60, 0x5E, 0xFE, -1, 0},
++ {1728, 1011, 1280, 960, 85, 85.938, 160, 224, 3, 47, 0, 0, 0, 0, 0, HOR_POSITIVE, VER_POSITIVE, 0x6B, 0xF0, 0xA8, 0x05, 0x20, 0xA0, 0x60, 0x60, 0x60, 0x5E, 0xFE, -1, 0},
++ {1688, 1066, 1280, 1024, 75, 79.976, 144, 248, 3, 38, 0, 0, 0, 0, 0, HOR_POSITIVE, VER_POSITIVE, 0x69, 0x70, 0xE8, 0x05, 0x20, 0x90, 0x60, 0x60, 0x60, 0x5E, 0xFE, -1, 0},
++ {1728, 1072, 1280, 1024, 85, 91.146, 160, 224, 3, 44, 0, 0, 0, 0, 0, HOR_POSITIVE, VER_POSITIVE, 0x6B, 0xF0, 0xA8, 0x05, 0x20, 0xA0, 0x60, 0x60, 0x60, 0x5E, 0xFE, -1, 0},
++ {2160, 1250, 1600, 1200, 65, 81.250, 192, 304, 3, 46, 0, 0, 0, 0, 0, HOR_POSITIVE, VER_POSITIVE, 0x86, 0xF0, 0xA8, 0x05, 0x20, 0xC0, 0x60, 0x60, 0x60, 0x5E, 0xFE, -1, 0},
++ {2160, 1250, 1600, 1200, 70, 87.500, 192, 304, 3, 46, 0, 0, 0, 0, 0, HOR_POSITIVE, VER_POSITIVE, 0x86, 0xF0, 0xA8, 0x05, 0x20, 0xC0, 0x60, 0x60, 0x60, 0x5E, 0xFE, -1, 0},
++ {2160, 1250, 1600, 1200, 75, 93.750, 192, 304, 3, 46, 0, 0, 0, 0, 0, HOR_POSITIVE, VER_POSITIVE, 0x86, 0xF0, 0xA8, 0x05, 0x20, 0xC0, 0x60, 0x60, 0x60, 0x5E, 0xFE, -1, 0},
++ {2160, 1250, 1600, 1200, 85, 106.250,192, 304, 3, 46, 0, 0, 0, 0, 0, HOR_POSITIVE, VER_POSITIVE, 0x86, 0xF0, 0xA8, 0x05, 0x20, 0xC0, 0x60, 0x60, 0x60, 0x5E, 0xFE, -1, 0}
++};
++
++USHORT ModeNumberCount = sizeof (vModeTable) / sizeof (VESA_MODE);
++USHORT Mode60HZCount = 21;
++
++#else /* NOT VESA_GLOBALS */
++extern VESA_MODE vModeTable[];
++extern USHORT ModeNumberCount;
++extern USHORT Mode60HZCount;
++#endif
++
++#endif /* _VESA_H_ */
++
++
+diff --git a/board/aspeed/ast2400/vfun.c b/board/aspeed/ast2400/vfun.c
+new file mode 100755
+index 0000000..f707e80
+--- /dev/null
++++ b/board/aspeed/ast2400/vfun.c
+@@ -0,0 +1,545 @@
++/*
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++ */
++#define BUF_GLOBALS
++#include "type.h"
++#include "vdef.h"
++#include "vreg.h"
++#include "crt.h"
++#include "vfun.h"
++
++ULONG UnlockSCURegHost(ULONG MMIOBase, ULONG Key)
++{
++ WriteMemoryLongHost(SCU_BASE, SCU_PROTECT_REG, Key);
++ return ReadMemoryLongHost(SCU_BASE,SCU_PROTECT_REG);
++}
++
++void ResetVideoHost(void)
++{
++ WriteMemoryLongWithMASKHost(SCU_BASE, SCU_CONTROL_REG, VIDEO_RESET_EN << VIDEO_ENGINE_RESET_BIT, VIDEO_ENGINE_RESET_MASK);
++ WriteMemoryLongWithMASKHost(SCU_BASE, SCU_CONTROL_REG, VIDEO_RESET_OFF << VIDEO_ENGINE_RESET_BIT, VIDEO_ENGINE_RESET_MASK);
++}
++
++void StartModeDetectionTriggerHost(ULONG MMIOBase, ULONG offset)
++{
++ WriteMemoryLongWithMASKHost(VIDEO_REG_BASE, offset, 0, MODE_DETECTION_TRIGGER);
++ WriteMemoryLongWithMASKHost(VIDEO_REG_BASE, offset, MODE_DETECTION_TRIGGER, MODE_DETECTION_TRIGGER);
++}
++
++BOOL ReadVideoInterruptHost(ULONG MMIOBase, ULONG value)
++{
++ return ((ReadMemoryLongHost(VIDEO_REG_BASE, VIDEO_INT_CONTROL_READ_REG) & value) ? TRUE : FALSE);
++}
++
++ULONG UnlockVideoRegHost(ULONG MMIOBase, ULONG Key)
++{
++ WriteMemoryLongHost(VIDEO_REG_BASE, KEY_CONTROL_REG, Key);
++ return ReadMemoryLongHost(VIDEO_REG_BASE,KEY_CONTROL_REG);
++}
++
++void StartVideoCaptureTriggerHost(ULONG MMIOBase, ULONG offset)
++{
++ WriteMemoryLongWithMASKHost(VIDEO_REG_BASE, offset, 0, VIDEO_CAPTURE_TRIGGER);
++ WriteMemoryLongWithMASKHost(VIDEO_REG_BASE, offset, VIDEO_CAPTURE_TRIGGER, VIDEO_CAPTURE_TRIGGER);
++}
++
++void StartVideoCodecTriggerHost(ULONG MMIOBase, ULONG offset)
++{
++ WriteMemoryLongWithMASKHost(VIDEO_REG_BASE, offset, 0, VIDEO_CODEC_TRIGGER);
++ WriteMemoryLongWithMASKHost(VIDEO_REG_BASE, offset, VIDEO_CODEC_TRIGGER, VIDEO_CODEC_TRIGGER);
++}
++
++void StopModeDetectionTriggerHost(ULONG MMIOBase, ULONG offset)
++{
++ WriteMemoryLongWithMASKHost(VIDEO_REG_BASE, offset, 0, MODE_DETECTION_TRIGGER);
++}
++
++void ClearVideoInterruptHost(ULONG MMIOBase, ULONG value)
++{
++ //WriteMemoryLongWithMASKHost(VIDEO_REG_BASE, VIDEO_INT_CONTROL_CLEAR_REG, value, value);
++ WriteMemoryLongHost(VIDEO_REG_BASE, VIDEO_INT_CONTROL_CLEAR_REG, value);
++}
++
++/* UnLock SCU Host and Reset Engine */
++BOOL CheckOnStartHost(void)
++{
++ int i=0, dwValue=0;
++
++ do
++ {
++ dwValue = UnlockSCURegHost(0, SCU_UNLOCK_KEY);
++ i++;
++ }
++ while ((SCU_WRITE_ENABLE != dwValue) && (i<10));
++
++ //Clear SCU Reset Register
++ WriteMemoryLongHost(SCU_BASE, SCU_CONTROL_REG, 0);
++
++ WriteMemoryLongWithMASKHost(SCU_BASE, SCU_CLOCK_STOP_REG, (EN_ECLK | EN_V1CLK | EN_V2CLK), (STOP_ECLK_MASK | STOP_V1CLK_MASK | STOP_V2CLK_MASK));
++
++#if defined(CONFIG_AST2300)
++ WriteMemoryLongWithMASKHost(SCU_BASE, (0x90 + SCU_OFFSET), 0x00000020, 0x00000030); //enable 24bits
++ WriteMemoryLongWithMASKHost(SCU_BASE, (0x88 + SCU_OFFSET), 0x000fff00, 0x000fff00); //enable video multi-pins
++#else //AST2100
++ //WriteMemoryLongWithMASKHost(SCU_BASE, SCU_PIN_CTRL1_REG, (VIDEO_PORTA_EN | VIDEO_PORTB_EN | VIDEO_VP1_EN | VIDEO_VP2_EN) ,
++ // (VIDEO_PORTA_MASK | VIDEO_PORTB_MASK | VIDEO_VP1_MASK | VIDEO_VP2_MASK));
++ WriteMemoryLongWithMASKHost(SCU_BASE, SCU_PIN_CTRL2_REG, (VIDEO_PORTA_SINGLE_EDGE | VIDEO_PORTB_SINGLE_EDGE) ,
++ (VIDEO_PORTA_SINGLE_EDGE_MASK | VIDEO_PORTB_SINGLE_EDGE_MASK));
++#endif
++
++ ResetVideoHost();
++
++ return TRUE;
++}
++
++BOOL CheckOnStartClient(void)
++{
++ int i=0, dwValue=0;
++
++ do
++ {
++ dwValue = UnlockSCURegHost(0, SCU_UNLOCK_KEY);
++ i++;
++ }
++ while ((SCU_WRITE_ENABLE != dwValue) && (i<10));
++
++ //Clear SCU Reset Register
++ WriteMemoryLongClient(SCU_BASE, SCU_CONTROL_REG, 0);
++
++ WriteMemoryLongWithMASKClient(SCU_BASE, SCU_CLOCK_STOP_REG, (EN_ECLK | EN_V1CLK | EN_D1CLK | EN_D2CLK | EN_V2CLK),
++ (STOP_ECLK_MASK | STOP_D1CLK_MASK | STOP_D2CLK_MASK | STOP_V1CLK_MASK | STOP_V2CLK_MASK));
++
++ //WriteMemoryLongWithMASKClient(SCU_BASE, SCU_CLOCK_SELECTION_REG, PORTB_FROM_D2CLK | PORTB_CLOCK_INV_DELAY_3NS | PORTA_CLOCK_INV_DELAY_3NS, PORTB_CLOCK_SEL | PORTB_CLOCK_DELAY_MASK | PORTA_CLOCK_DELAY_MASK);
++ //A1EVA
++ WriteMemoryLongWithMASKClient(SCU_BASE, SCU_CLOCK_SELECTION_REG, (PORTB_FROM_D2CLK | PORTB_CLOCK_INV_DELAY_1NS | PORTA_CLOCK_INV_DELAY_1NS), (PORTB_CLOCK_SEL | PORTB_CLOCK_DELAY_MASK | PORTA_CLOCK_DELAY_MASK));
++ WriteMemoryLongWithMASKClient(SCU_BASE, 0x202C, (0x03<<9), (0x03<<9));
++
++ WriteMemoryLongWithMASKClient(SCU_BASE, SCU_PIN_CTRL1_REG, (VIDEO_PORTA_EN | VIDEO_PORTB_EN | VIDEO_VP1_EN | VIDEO_VP2_EN),
++ (VIDEO_PORTA_MASK | VIDEO_PORTB_MASK | VIDEO_VP1_MASK | VIDEO_VP2_MASK));
++
++#if CONFIG_AST3000
++ WriteMemoryLongWithMASKClient(SCU_BASE, SCU_PIN_CTRL2_REG, (VIDEO_PORTA_DUAL_EDGE | VIDEO_PORTB_DUAL_EDGE),
++ (VIDEO_PORTA_SINGLE_EDGE_MASK | VIDEO_PORTB_SINGLE_EDGE_MASK));
++#else
++ //2100 is single edge
++ WriteMemoryLongWithMASKClient(SCU_BASE, SCU_PIN_CTRL2_REG, (VIDEO_PORTA_SINGLE_EDGE | VIDEO_PORTB_SINGLE_EDGE),
++ (VIDEO_PORTA_SINGLE_EDGE_MASK | VIDEO_PORTB_SINGLE_EDGE_MASK));
++#endif
++
++ WriteMemoryLongWithMASKClient(SCU_BASE, SCU_CLOCK_STOP_REG, (EN_D1CLK | EN_D2CLK), (STOP_D1CLK_MASK | STOP_D2CLK_MASK));
++ WriteMemoryLongWithMASKClient(SCU_BASE, SCU_PIN_CTRL1_REG, VGA_PIN_OFF, VGA_PIN_MASK);
++
++ //ResetVideoHost();
++
++ return TRUE;
++}
++
++ULONG InitializeVideoEngineHost (ULONG MMIOBase,
++ int nVideo,
++ BOOL HorPolarity,
++ BOOL VerPolarity)
++{
++ //ULONG temp, temp1, temp2;
++ ULONG dwRegOffset = nVideo * 0x100;
++ ULONG dwValue;
++ int i;
++
++
++ /* General Video Control */
++ //LineBufEn 0
++ //dwValue = (COMPRESS_MODE << CODEC_DECOMPRESS_MODE_BIT) | DELAY_VSYNC_EN;
++ dwValue = 0;
++ WriteMemoryLongHost(VIDEO_REG_BASE, VIDEO_CONTROL_REG, dwValue);
++ //Video Data Truncation Register
++ WriteMemoryLongHost(VIDEO_REG_BASE, 0x328, 0);
++
++ //D2CLK clock must config according to video's line buffer
++ if (VIDEO1 == nVideo)
++ dwValue = LINE_BUFFER_VIDEO1;
++ else
++ dwValue = LINE_BUFFER_VIDEO2;
++
++ //D2CLK clock must config according to video's line buffer
++ switch (dwValue)
++ {
++ case LINE_BUFFER_OFF:
++ WriteMemoryLongWithMASKHost(SCU_BASE, SCU_CLOCK_SELECTION_REG, NORMAL_CRT1, D2CLK_CLOCK_SELECTION_MASK);
++ WriteMemoryLongWithMASKHost(SCU_BASE, SCU_CLOCK_STOP_REG, STOP_D2CLK, STOP_D2CLK_MASK);
++ break;
++ case LINE_BUFFER_VIDEO1:
++ WriteMemoryLongWithMASKHost(SCU_BASE, SCU_CLOCK_SELECTION_REG, V1CLK_VIDEO1 << D2CLK_CLOCK_SELECTION_BIT, D2CLK_CLOCK_SELECTION_MASK);
++ WriteMemoryLongWithMASKHost(SCU_BASE, SCU_CLOCK_STOP_REG, EN_D2CLK, STOP_D2CLK_MASK);
++ break;
++ case LINE_BUFFER_VIDEO2:
++ WriteMemoryLongWithMASKHost(SCU_BASE, SCU_CLOCK_SELECTION_REG, V1CLK_VIDEO2 << D2CLK_CLOCK_SELECTION_BIT, D2CLK_CLOCK_SELECTION_MASK);
++ WriteMemoryLongWithMASKHost(SCU_BASE, SCU_CLOCK_STOP_REG, EN_D2CLK, STOP_D2CLK_MASK);
++ break;
++ case LINE_BUFFER_VIDEOM:
++ //If select this option, it will config at videoM INIT
++ break;
++ default:
++ break;
++ }
++
++ dwValue = 0;
++ //VR30 now is capture window in the compression
++ dwValue = g_DefHeight << CAPTURE_VER_LINE_BIT |
++ g_DefWidth << CAPTURE_HOR_PIXEL_BIT;
++ WriteMemoryLongHost(VIDEO_REG_BASE, VIDEO1_CAPTURE_WINDOWS_REG + dwRegOffset, dwValue);
++
++ dwValue = 0;
++ //VR34 now is destionation window in the compression
++ dwValue = g_DefHeight << COMPRESS_VER_LINE_BIT |
++ g_DefWidth << COMPRESS_HOR_PIXEL_BIT;
++
++ WriteMemoryLongHost(VIDEO_REG_BASE, VIDEO1_COMPRESS_WINDOWS_REG + dwRegOffset, dwValue);
++
++ //BitCOUNT according compress data format
++ dwValue = YUV444_MODE;
++ if (YUV444_MODE == dwValue)
++ WriteMemoryLongWithMASKHost(VIDEO_REG_BASE, VIDEO1_BUF_LINE_OFFSET_REG + dwRegOffset, g_DefWidth * INPUT_BITCOUNT_YUV444, BUF_LINE_OFFSET_MASK);
++ else
++ WriteMemoryLongWithMASKHost(VIDEO_REG_BASE, VIDEO1_BUF_LINE_OFFSET_REG + dwRegOffset, g_DefWidth * INPUT_BITCOUNT_YUV420, BUF_LINE_OFFSET_MASK);
++
++ // CRC
++ //Disable
++ WriteMemoryLongHost(VIDEO_REG_BASE, VIDEO_CRC_PRIMARY_REG, 0x0);
++ WriteMemoryLongHost(VIDEO_REG_BASE, VIDEO_CRC_SECOND_REG, 0x0);
++
++ /* Sequence Control register */
++ //Oonly Encoder need to set
++ /* Engine Sequence Contol Register */
++ dwValue = (WATCH_DOG_EN << WATCH_DOG_ENABLE_BIT) |
++ VIDEO_CAPTURE_AUTO_MODE |
++ VIDEO_CODEC_AUTO_MODE;
++
++ WriteMemoryLongHost(VIDEO_REG_BASE, VIDEO1_ENGINE_SEQUENCE_CONTROL_REG + dwRegOffset, dwValue);
++
++ /* Control register */
++ dwValue = (HOR_NEGATIVE == HorPolarity) ? NO_INVERSE_POL : INVERSE_POL;
++ dwValue = (((VER_NEGATIVE == VerPolarity) ? NO_INVERSE_POL : INVERSE_POL) << VIDEO_VSYNC_POLARITY_BIT) | dwValue;
++
++ /* HW Recommand*/
++ //dwValue = (TILE_MODE << 9) | dwValue;
++ dwValue = (EXTERNAL_VGA_SOURCE << EXTERNAL_SOURCE_BIT) | dwValue;
++
++ WriteMemoryLongHost(VIDEO_REG_BASE, VIDEO1_CONTROL_REG + dwRegOffset, dwValue);
++
++ /* BCD register */
++ //NO BCD
++ dwValue = 0;
++ WriteMemoryLongHost(VIDEO_REG_BASE, VIDEO1_BCD_CONTROL_REG + dwRegOffset, dwValue);
++
++ /* Stream Buffer Size register */
++ dwValue = (YUV_TEST << SKIP_TEST_MODE_BIT) |
++ (PACKET_SIZE_32KB << STREAM_PACKET_SIZE_BIT) |
++ (PACKETS_8 << RING_BUF_PACKET_NUM_BIT);
++ /* the same with Video1, Video2, and VideoM*/
++ WriteMemoryLongHost(VIDEO_REG_BASE, VIDEO1_STREAM_BUF_SIZE, dwValue);
++
++ /* Comression control register */
++ dwValue = (USE_UV_CIR656 << UV_CIR656_FORMAT_BIT)|
++ (JPEG_MIX_MODE << JPEG_ONLY_BIT)|
++ (VQ_4_COLOR_MODE << VQ_4_COLOR_BIT)|
++ (QUANTI_CODEC_MODE << QUALITY_CODEC_SETTING_BIT)|
++ (7 << NORMAL_QUANTI_CHROMI_TABLE_BIT) |
++ (23 << NORMAL_QUANTI_LUMI_TABLE_BIT);
++
++ //Video2 have same value as video1
++ WriteMemoryLongHost(VIDEO_REG_BASE, VIDEO1_COMPRESS_CONTROL_REG, dwValue);
++
++ /* JPEG Quantization Table register */
++ dwValue = 0;
++ WriteMemoryLongHost(VIDEO_REG_BASE, VIDEO1_QUANTI_TABLE_LOW_REG, dwValue);
++
++ /* Quantization value register */
++ //Video2 have same value as video1
++ dwValue = 0;
++ WriteMemoryLongHost(VIDEO_REG_BASE, VIDEO1_QUANTI_VALUE_REG, dwValue);
++
++ //Video BSD Parameter Register
++ //Video2 have same value as video1
++ dwValue = 0;
++ WriteMemoryLongHost(VIDEO_REG_BASE, VIDEO1_BSD_PARA_REG, dwValue);
++
++ //no scale
++ WriteMemoryLongHost(VIDEO_REG_BASE, VIDEO1_SCALE_FACTOR_REG, 0x10001000);
++ WriteMemoryLongHost(VIDEO_REG_BASE, VIDEO1_SCALE_FACTOR_PARAMETER0_REG, 0x00200000);
++ WriteMemoryLongHost(VIDEO_REG_BASE, VIDEO1_SCALE_FACTOR_PARAMETER1_REG, 0x00200000);
++ WriteMemoryLongHost(VIDEO_REG_BASE, VIDEO1_SCALE_FACTOR_PARAMETER2_REG, 0x00200000);
++ WriteMemoryLongHost(VIDEO_REG_BASE, VIDEO1_SCALE_FACTOR_PARAMETER3_REG, 0x00200000);
++ return TRUE;
++}
++
++ULONG InitializeVideoEngineClient (ULONG MMIOBase,
++ int nVideo)
++{
++ //ULONG temp, temp1, temp2;
++ ULONG dwRegOffset = nVideo * 0x100;
++ ULONG dwValue;
++ int i;
++
++
++ /* General Video Control */
++ //LineBufEn 0
++ dwValue = (DECOMPRESS_MODE << CODEC_DECOMPRESS_MODE_BIT);
++ WriteMemoryLongHost(VIDEO_REG_BASE, VIDEO_CONTROL_REG, dwValue);
++ //Video Data Truncation Register
++ WriteMemoryLongHost(VIDEO_REG_BASE, 0x328, 0);
++
++ //VR30 now is capture window in the compression
++ dwValue = g_DefHeight << CAPTURE_VER_LINE_BIT |
++ g_DefWidth << CAPTURE_HOR_PIXEL_BIT;
++ WriteMemoryLongWithMASKHost(VIDEO_REG_BASE, VIDEO1_CAPTURE_WINDOWS_REG + dwRegOffset, dwValue, CAPTURE_VER_LINE_MASK | CAPTURE_HOR_PIXEL_MASK);
++
++ //VR34 now is destionation window in the compression
++ dwValue = g_DefHeight << COMPRESS_VER_LINE_BIT |
++ g_DefWidth << COMPRESS_HOR_PIXEL_BIT;
++
++ WriteMemoryLongWithMASKHost(VIDEO_REG_BASE, VIDEO1_COMPRESS_WINDOWS_REG + dwRegOffset, dwValue, COMPRESS_VER_LINE_MASK | COMPRESS_HOR_PIXEL_MASK);
++
++ //BitCOUNT according compress data format
++ dwValue = YUV444_MODE;
++ if (YUV444_MODE == dwValue)
++ WriteMemoryLongWithMASKHost(VIDEO_REG_BASE, VIDEO1_BUF_LINE_OFFSET_REG + dwRegOffset, g_DefWidth * INPUT_BITCOUNT_YUV444, BUF_LINE_OFFSET_MASK);
++ else
++ WriteMemoryLongWithMASKHost(VIDEO_REG_BASE, VIDEO1_BUF_LINE_OFFSET_REG + dwRegOffset, g_DefWidth * INPUT_BITCOUNT_YUV420, BUF_LINE_OFFSET_MASK);
++
++ // CRC
++ //Disable
++ WriteMemoryLongHost(VIDEO_REG_BASE, VIDEO_CRC_PRIMARY_REG, 0x0);
++ WriteMemoryLongHost(VIDEO_REG_BASE, VIDEO_CRC_SECOND_REG, 0x0);
++
++ /* Sequence Control register */
++ //Oonly Encoder need to set
++ /* Engine Sequence Contol Register */
++ dwValue = VIDEO_CAPTURE_AUTO_MODE |
++ VIDEO_CODEC_AUTO_MODE;
++
++ WriteMemoryLongHost(VIDEO_REG_BASE, VIDEO1_ENGINE_SEQUENCE_CONTROL_REG + dwRegOffset, dwValue);
++
++ /* Control register */
++ /* HW Recommand*/
++ dwValue = (TILE_MODE << 9);
++
++ WriteMemoryLongHost(VIDEO_REG_BASE, VIDEO1_CONTROL_REG + dwRegOffset, dwValue);
++
++ /* BCD register */
++ //NO BCD
++ dwValue = 0;
++ WriteMemoryLongHost(VIDEO_REG_BASE, VIDEO1_BCD_CONTROL_REG + dwRegOffset, dwValue);
++
++ /* Stream Buffer Size register */
++ dwValue = (YUV_TEST << SKIP_TEST_MODE_BIT) |
++ (PACKET_SIZE_32KB << STREAM_PACKET_SIZE_BIT) |
++ (PACKETS_8 << RING_BUF_PACKET_NUM_BIT);
++ /* the same with Video1, Video2, and VideoM*/
++ WriteMemoryLongHost(VIDEO_REG_BASE, VIDEO1_STREAM_BUF_SIZE, dwValue);
++
++
++ /* Comression control register */
++ dwValue = (USE_UV_CIR656 << UV_CIR656_FORMAT_BIT)|
++ (JPEG_MIX_MODE << JPEG_ONLY_BIT)|
++ (VQ_4_COLOR_MODE << VQ_4_COLOR_BIT)|
++ (QUANTI_CODEC_MODE << QUALITY_CODEC_SETTING_BIT)|
++ (7 << NORMAL_QUANTI_CHROMI_TABLE_BIT) |
++ (23 << NORMAL_QUANTI_LUMI_TABLE_BIT);
++
++ //Video2 have same value as video1
++ if (VIDEO1 == nVideo)
++ {
++ WriteMemoryLongHost(VIDEO_REG_BASE, VIDEO1_COMPRESS_CONTROL_REG, dwValue);
++ }
++ else
++ {
++ WriteMemoryLongHost(VIDEO_REG_BASE, VIDEOM_COMPRESS_CONTROL_REG, dwValue);
++ }
++
++ /* JPEG Quantization Table register */
++ dwValue = 0;
++ WriteMemoryLongHost(VIDEO_REG_BASE, VIDEO1_QUANTI_TABLE_LOW_REG, dwValue);
++
++ /* Quantization value register */
++ //Video2 have same value as video1
++ dwValue = 0;
++ WriteMemoryLongHost(VIDEO_REG_BASE, VIDEO1_QUANTI_VALUE_REG, dwValue);
++
++ //Video BSD Parameter Register
++ //Video2 have same value as video1
++ dwValue = 0;
++ WriteMemoryLongHost(VIDEO_REG_BASE, VIDEO1_BSD_PARA_REG, dwValue);
++
++ return TRUE;
++}
++
++BYTE GetI2CRegClient(ULONG MMIOBase,
++ BYTE DeviceSelect,
++ BYTE DeviceAddress,
++ BYTE RegisterIndex)
++{
++ BYTE Data;
++ ULONG Status;
++
++// Reset
++ WriteMemoryLongClient(APB_BRIDGE_2_BASE, I2C_BASE + DeviceSelect * 0x40 + 0x00, 0);
++// Set AC Timing and Speed
++ WriteMemoryLongClient(APB_BRIDGE_2_BASE, I2C_BASE + DeviceSelect * 0x40 + 0x04, AC_TIMING);
++// Lower Speed
++// WriteMemoryLongWithANDData (VideoEngineInfo->VGAPCIInfo.ulMMIOBaseAddress, I2C_BASE + DeviceSelect * 0x40 + 0x04, 0, 0x33317805);
++ WriteMemoryLongClient(APB_BRIDGE_2_BASE, I2C_BASE + DeviceSelect * 0x40 + 0x08, 0);
++// Clear Interrupt
++ WriteMemoryLongClient(APB_BRIDGE_2_BASE, I2C_BASE + DeviceSelect * 0x40 + 0x10, 0xFFFFFFFF);
++// Enable Master Mode
++ WriteMemoryLongClient(APB_BRIDGE_2_BASE, I2C_BASE + DeviceSelect * 0x40 + 0x00, 1);
++// Enable Interrupt
++ WriteMemoryLongClient(APB_BRIDGE_2_BASE, I2C_BASE + DeviceSelect * 0x40 + 0x0C, 0xAF);
++// BYTE I2C Mode
++// Start and Send Device Address
++ WriteMemoryLongClient(APB_BRIDGE_2_BASE, I2C_BASE + DeviceSelect * 0x40 + 0x20, DeviceAddress);
++ WriteMemoryLongClient(APB_BRIDGE_2_BASE, I2C_BASE + DeviceSelect * 0x40 + 0x14, 0x3);
++// Wait TX ACK
++ do {
++ Status = ReadMemoryLongClient(APB_BRIDGE_2_BASE, I2C_BASE + DeviceSelect * 0x40 + 0x10) & 0x03;
++ } while (Status != 1);
++// Clear Interrupt
++ WriteMemoryLongClient(APB_BRIDGE_2_BASE, I2C_BASE + DeviceSelect * 0x40 + 0x10, 0xFFFFFFFF);
++// Send Device Register Index
++ WriteMemoryLongClient(APB_BRIDGE_2_BASE, I2C_BASE + DeviceSelect * 0x40 + 0x20, RegisterIndex);
++ WriteMemoryLongClient(APB_BRIDGE_2_BASE, I2C_BASE + DeviceSelect * 0x40 + 0x14, 0x2);
++// Wait Tx ACK
++ do {
++ Status = ReadMemoryLongClient(APB_BRIDGE_2_BASE, I2C_BASE + DeviceSelect * 0x40 + 0x10) & 0x03;
++ } while (Status != 1);
++// Clear Interrupt
++ WriteMemoryLongClient(APB_BRIDGE_2_BASE, I2C_BASE + DeviceSelect * 0x40 + 0x10, 0xFFFFFFFF);
++// Start, Send Device Address + 1(Read Mode), Receive Data
++ WriteMemoryLongClient(APB_BRIDGE_2_BASE, I2C_BASE + DeviceSelect * 0x40 + 0x20, DeviceAddress + 1);
++ WriteMemoryLongClient(APB_BRIDGE_2_BASE, I2C_BASE + DeviceSelect * 0x40 + 0x14, 0x1B);
++// Wait Rx Done
++ do {
++ Status = (ReadMemoryLongClient(APB_BRIDGE_2_BASE, I2C_BASE + DeviceSelect * 0x40 + 0x10) & 0x04) >> 2;
++ } while (Status != 1);
++// Clear Interrupt
++ WriteMemoryLongClient(APB_BRIDGE_2_BASE, I2C_BASE + DeviceSelect * 0x40 + 0x10, 0xFFFFFFFF);
++
++// Enable STOP Interrupt
++ WriteMemoryLongWithMASKClient(APB_BRIDGE_2_BASE, I2C_BASE + DeviceSelect * 0x40 + 0x0C, 0x10, 0x10);
++// Issue STOP Command
++ WriteMemoryLongClient(APB_BRIDGE_2_BASE, I2C_BASE + DeviceSelect * 0x40 + 0x14, 0x20);
++// Wait STOP
++ do {
++ Status = (ReadMemoryLongClient(APB_BRIDGE_2_BASE, I2C_BASE + DeviceSelect * 0x40 + 0x10) & 0x10) >> 4;
++ } while (Status != 1);
++// Disable STOP Interrupt
++ WriteMemoryLongClient(APB_BRIDGE_2_BASE, I2C_BASE + DeviceSelect * 0x40 + 0x0C, 0x10);
++// Clear Interrupt
++ WriteMemoryLongClient(APB_BRIDGE_2_BASE, I2C_BASE + DeviceSelect * 0x40 + 0x10, 0xFFFFFFFF);
++// Read Received Data
++ Data = (BYTE)((ReadMemoryLongClient(APB_BRIDGE_2_BASE, I2C_BASE + DeviceSelect * 0x40 + 0x20) & 0xFF00) >> 8);
++
++ return Data;
++}
++
++ULONG SetI2CRegClient(ULONG MMIOBase,
++ BYTE DeviceSelect,
++ BYTE DeviceAddress,
++ BYTE RegisterIndex,
++ BYTE RegisterValue)
++{
++ ULONG Status;
++ ULONG Count = 0;
++
++// Reset
++ WriteMemoryLongClient(APB_BRIDGE_2_BASE, I2C_BASE + DeviceSelect * 0x40 + 0x00, 0);
++// Set Speed
++ WriteMemoryLongClient(APB_BRIDGE_2_BASE, I2C_BASE + DeviceSelect * 0x40 + 0x04, AC_TIMING);
++// Lower Speed
++// WriteMemoryLongWithANDData (VideoEngineInfo->VGAPCIInfo.ulMMIOBaseAddress, I2C_BASE + DeviceSelect * 0x40 + 0x04, 0, 0x33317805);
++ WriteMemoryLongClient(APB_BRIDGE_2_BASE, I2C_BASE + DeviceSelect * 0x40 + 0x08, 0);
++// Clear Interrupt
++ WriteMemoryLongClient(APB_BRIDGE_2_BASE, I2C_BASE + DeviceSelect * 0x40 + 0x10, 0xFFFFFFFF);
++// Enable Master Mode
++ WriteMemoryLongClient(APB_BRIDGE_2_BASE, I2C_BASE + DeviceSelect * 0x40 + 0x00, 1);
++// Enable Interrupt
++ WriteMemoryLongClient(APB_BRIDGE_2_BASE, I2C_BASE + DeviceSelect * 0x40 + 0x0C, 0xAF);
++// BYTE I2C Mode
++// Start and Send Device Address
++ WriteMemoryLongClient(APB_BRIDGE_2_BASE, I2C_BASE + DeviceSelect * 0x40 + 0x20, DeviceAddress);
++ WriteMemoryLongClient(APB_BRIDGE_2_BASE, I2C_BASE + DeviceSelect * 0x40 + 0x14, 0x3);
++// Wait Tx ACK
++ do {
++ Count++;
++ Status = ReadMemoryLongClient(APB_BRIDGE_2_BASE, I2C_BASE + DeviceSelect * 0x40 + 0x10) & 0x03;
++
++ if (2 == Status)
++ {
++ //Clear Interrupt
++ WriteMemoryLongClient(APB_BRIDGE_2_BASE, I2C_BASE + DeviceSelect * 0x40 + 0x10, 0xFFFFFFFF);
++ //Re-Send Start and Send Device Address while NACK return
++ WriteMemoryLongClient(APB_BRIDGE_2_BASE, I2C_BASE + DeviceSelect * 0x40 + 0x20, DeviceAddress);
++ WriteMemoryLongClient(APB_BRIDGE_2_BASE, I2C_BASE + DeviceSelect * 0x40 + 0x14, 0x3);
++ }
++ //else
++ {
++ if (Count > LOOP_COUNT) {
++ return CAN_NOT_FIND_DEVICE;
++ }
++ }
++ } while (Status != 1);
++ Count = 0;
++// Clear Interrupt
++ WriteMemoryLongClient(APB_BRIDGE_2_BASE, I2C_BASE + DeviceSelect * 0x40 + 0x10, 0xFFFFFFFF);
++// Send Device Register Index
++ WriteMemoryLongClient(APB_BRIDGE_2_BASE, I2C_BASE + DeviceSelect * 0x40 + 0x20, RegisterIndex);
++ WriteMemoryLongClient(APB_BRIDGE_2_BASE, I2C_BASE + DeviceSelect * 0x40 + 0x14, 0x2);
++// Wait Tx ACK
++ do {
++ Count++;
++ Status = ReadMemoryLongClient(APB_BRIDGE_2_BASE, I2C_BASE + DeviceSelect * 0x40 + 0x10) & 0x03;
++ if (Count > LOOP_COUNT) {
++ return CAN_NOT_FIND_DEVICE;
++ }
++ } while (Status != 1);
++ Count = 0;
++// Clear Interrupt
++ WriteMemoryLongClient(APB_BRIDGE_2_BASE, I2C_BASE + DeviceSelect * 0x40 + 0x10, 0xFFFFFFFF);
++// Send Device Register Value and Stop
++ WriteMemoryLongClient(APB_BRIDGE_2_BASE, I2C_BASE + DeviceSelect * 0x40 + 0x20, RegisterValue);
++ WriteMemoryLongClient(APB_BRIDGE_2_BASE, I2C_BASE + DeviceSelect * 0x40 + 0x14, 0x2);
++// Wait Tx ACK
++ do {
++ Count++;
++ Status = ReadMemoryLongClient(APB_BRIDGE_2_BASE, I2C_BASE + DeviceSelect * 0x40 + 0x10) & 0x03;
++ if (Count > LOOP_COUNT) {
++ return CAN_NOT_FIND_DEVICE;
++ }
++ } while (Status != 1);
++ Count = 0;
++// Clear Interrupt
++ WriteMemoryLongClient(APB_BRIDGE_2_BASE, I2C_BASE + DeviceSelect * 0x40 + 0x10, 0xFFFFFFFF);
++// Enable STOP Interrupt
++ WriteMemoryLongWithMASKClient(APB_BRIDGE_2_BASE, I2C_BASE + DeviceSelect * 0x40 + 0x0C, 0x10, 0x10);
++// Issue STOP Command
++ WriteMemoryLongClient(APB_BRIDGE_2_BASE, I2C_BASE + DeviceSelect * 0x40 + 0x14, 0x20);
++// Wait STOP
++ do {
++ Count++;
++ Status = (ReadMemoryLongClient(APB_BRIDGE_2_BASE, I2C_BASE + DeviceSelect * 0x40 + 0x10) & 0x10) >> 4;
++ if (Count > LOOP_COUNT) {
++ return CAN_NOT_FIND_DEVICE;
++ }
++ } while (Status != 1);
++// Disable STOP Interrupt
++ WriteMemoryLongWithMASKClient(APB_BRIDGE_2_BASE, I2C_BASE + DeviceSelect * 0x40 + 0x0C, 0, 0x10);
++// Clear Interrupt
++ WriteMemoryLongClient(APB_BRIDGE_2_BASE, I2C_BASE + DeviceSelect * 0x40 + 0x10, 0xFFFFFFFF);
++
++ return SET_I2C_DONE;
++}
+diff --git a/board/aspeed/ast2400/vfun.h b/board/aspeed/ast2400/vfun.h
+new file mode 100755
+index 0000000..90f9ec4
+--- /dev/null
++++ b/board/aspeed/ast2400/vfun.h
+@@ -0,0 +1,79 @@
++/*
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++ */
++#ifndef _VFUN_H_
++#define _VFUN_H_
++
++//#define vBufAlign(x) ((x + 0x0000007F) & 0xFFFFFF80) //128 byte alignment
++#define vBufAlign(x) ((x + 0x000003FF) & 0xFFFFFC00) //128 byte alignment
++#define vBufAlign2(x) ((x + 0x0000FFFF) & 0xFFFF0000) //128 byte alignment
++#define v16byteAlign(x) ((x + 0x0000000F) & 0xFFFFFFF0)
++#define vBuf_ALIGNMENT 128
++
++#define HOST_TOTAL_SIZE 0x8000000 /* 128M */
++#define STATION_TOTAL_SIZE 0xF800000 /* 120M */
++
++#define VIDEO_SOURCE_SIZE 0x200000 /* 800X600X4 = 0x1D4C00 */
++#define VIDEO_MAX_STREAM_SIZE 0x400000 /* 32X128K = 0x400000 */
++#define VIDEO_FLAG_SIZE 0x5000 /* 1920X1200/128 = 0x4650*/
++#define VIDEO_CRC_SIZE 0x50000 /* 1920/64X1200X8 = 0x46500*/
++
++#define VIDEO1_EN_TOTAL_SIZE (VIDEO_SOURCE_SIZE*2+VIDEO_MAX_STREAM_SIZE+VIDEO_FLAG_SIZE+VIDEO_CRC_SIZE) /* 0x1655000 = about 23M*/
++#define VIDEO2_EN_TOTAL_SIZE VIDEO1_EN_TOTAL_SIZE
++//#define VIDEOM_EN_TOTAL_SIZE (VIDEO_SOURCE_SIZE*2+VIDEO_MAX_STREAM_SIZE+VIDEO_FLAG_SIZE) /* 0x1605000 = about 22.7M */
++//#define VIDEO_HOST_SIZE (VIDEO1_EN_TOTAL_SIZE + VIDEO2_EN_TOTAL_SIZE + VIDEOM_EN_TOTAL_SIZE) /* 0x69922816 = about 70M */
++#define VIDEO_HOST_SIZE (VIDEO1_EN_TOTAL_SIZE + VIDEO2_EN_TOTAL_SIZE) /* NOT NEED VIDEOM */
++
++#define VIDEO1_EN_BASE 0x100000
++#define VIDEO2_EN_BASE (VIDEO1_EN_BASE + VIDEO1_EN_TOTAL_SIZE)
++#define VIDEOM_EN_BASE (VIDEO2_EN_BASE + VIDEO2_EN_TOTAL_SIZE)
++
++#define VIDEO1_DE_TOTAL_SIZE (VIDEO_MAX_STREAM_SIZE + VIDEO_SOURCE_SIZE) /* 0xD00000 = 13M*/
++#define VIDEO2_DE_TOTAL_SIZE (VIDEO1_DE_TOTAL_SIZE)
++#define VIDEO_STATION_SIZE (VIDEO1_DE_TOTAL_SIZE + VIDEO2_DE_TOTAL_SIZE) /* 26M */
++
++#define VIDEO1_DE_BASE VIDEO_HOST_SIZE
++#define VIDEO2_DE_BASE (VIDEO1_DE_BASE + VIDEO1_DE_TOTAL_SIZE)
++#define VIDEO_ALL_SIZE (VIDEO_HOST_SIZE + VIDEO_STATION_SIZE) //Host and Station
++
++#define OutdwmBankModeHost(offset,data) WriteMemoryLongHost(DRAM_BASE,offset,data)
++#define IndwmBankModeHost(offset) ReadMemoryLongHost(DRAM_BASE,offset)
++
++ULONG UnlockVideoRegHost(ULONG MMIOBase, ULONG Key);
++BOOL CheckOnStartHost(void);
++BOOL CheckOnStartClient(void);
++void StartVideoCaptureTriggerHost(ULONG MMIOBase, ULONG offset);
++void StartVideoCaptureTriggerHost(ULONG MMIOBase, ULONG offset);
++void StartVideoCodecTriggerHost(ULONG MMIOBase, ULONG offset);
++ULONG UnlockSCURegHost(ULONG MMIOBase, ULONG Key);
++ULONG UnlockSCURegHost(ULONG MMIOBase, ULONG Key);
++void StartModeDetectionTriggerHost(ULONG MMIOBase, ULONG offset);
++void ClearVideoInterruptHost(ULONG MMIOBase, ULONG value);
++BOOL ReadVideoInterruptHost(ULONG MMIOBase, ULONG value);
++void StopModeDetectionTriggerHost(ULONG MMIOBase, ULONG offset);
++void ResetVideoHost(void);
++ULONG InitializeVideoEngineHost (ULONG MMIOBase,
++ int nVideo,
++ BOOL HorPolarity,
++ BOOL VerPolarity);
++ULONG InitializeVideoEngineClient (ULONG MMIOBase,
++ int nVideo);
++BYTE GetI2CRegClient(ULONG MMIOBase,
++ BYTE DeviceSelect,
++ BYTE DeviceAddress,
++ BYTE RegisterIndex);
++
++ULONG SetI2CRegClient(ULONG MMIOBase,
++ BYTE DeviceSelect,
++ BYTE DeviceAddress,
++ BYTE RegisterIndex,
++ BYTE RegisterValue);
++#endif //_VFUN_H_
++
+diff --git a/board/aspeed/ast2400/vgahw.h b/board/aspeed/ast2400/vgahw.h
+new file mode 100755
+index 0000000..7cbba0d
+--- /dev/null
++++ b/board/aspeed/ast2400/vgahw.h
+@@ -0,0 +1,175 @@
++/*
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++ */
++/******************************************************************************
++ * Mode Stuff
++ ******************************************************************************/
++/* Default Settings */
++#define CRT_LOW_THRESHOLD_VALUE 0x12
++#define CRT_HIGH_THRESHOLD_VALUE 0x1E
++
++/* Output Selection */
++#define CRT1 0x00
++#define CRT2 0x01
++#define DVI1 0x10
++#define DVI2 0x11
++#define LVDS1 0x20
++#define LVDS2 0x21
++
++/* Mode Limitation */
++#define MAX_HResolution 1600
++#define MAX_VResolution 1200
++
++/* Std. Table Index Definition */
++#define TextModeIndex 0
++#define EGAModeIndex 1
++#define VGAModeIndex 2
++#define HiCModeIndex 3
++#define TrueCModeIndex 4
++
++/* DCLK Index */
++#define VCLK25_175 0x00
++#define VCLK28_322 0x01
++#define VCLK31_5 0x02
++#define VCLK36 0x03
++#define VCLK40 0x04
++#define VCLK49_5 0x05
++#define VCLK50 0x06
++#define VCLK56_25 0x07
++#define VCLK65 0x08
++#define VCLK75 0x09
++#define VCLK78_75 0x0A
++#define VCLK94_5 0x0B
++#define VCLK108 0x0C
++#define VCLK135 0x0D
++#define VCLK157_5 0x0E
++#define VCLK162 0x0F
++#define VCLK119 0x10
++
++/* Flags Definition */
++#define Charx8Dot 0x00000001
++#define HalfDCLK 0x00000002
++#define DoubleScanMode 0x00000004
++#define LineCompareOff 0x00000008
++#define SyncPP 0x00000000
++#define SyncPN 0x00000040
++#define SyncNP 0x00000080
++#define SyncNN 0x000000C0
++#define HBorder 0x00000020
++#define VBorder 0x00000010
++#define COLORINDEX 0x00000000
++#define MONOINDEX 0x00000100
++
++/* DAC Definition */
++#define DAC_NUM_TEXT 64
++#define DAC_NUM_EGA 64
++#define DAC_NUM_VGA 256
++
++/* AST3000 Reg. Definition */
++#define AST3000_VGAREG_BASE 0x1e6e6000
++#define AST3000_VGA1_CTLREG 0x00
++#define AST3000_VGA1_CTLREG2 0x04
++#define AST3000_VGA1_STATUSREG 0x08
++#define AST3000_VGA1_PLL 0x0C
++#define AST3000_VGA1_HTREG 0x10
++#define AST3000_VGA1_HRREG 0x14
++#define AST3000_VGA1_VTREG 0x18
++#define AST3000_VGA1_VRREG 0x1C
++#define AST3000_VGA1_STARTADDR 0x20
++#define AST3000_VGA1_OFFSETREG 0x24
++#define AST3000_VGA1_THRESHOLD 0x28
++#define AST3000_HWC1_OFFSET 0x30
++#define AST3000_HWC1_XY 0x34
++#define AST3000_HWC1_PBase 0x38
++#define AST3000_OSD1_H 0x40
++#define AST3000_OSD1_V 0x44
++#define AST3000_OSD1_PBase 0x48
++#define AST3000_OSD1_Offset 0x4C
++#define AST3000_OSD1_THRESHOLD 0x50
++
++#define AST3000_VGA2_CTLREG 0x60
++#define AST3000_VGA2_CTLREG2 0x64
++#define AST3000_VGA2_STATUSREG 0x68
++#define AST3000_VGA2_PLL 0x6C
++#define AST3000_VGA2_HTREG 0x70
++#define AST3000_VGA2_HRREG 0x74
++#define AST3000_VGA2_VTREG 0x78
++#define AST3000_VGA2_VRREG 0x7C
++#define AST3000_VGA2_STARTADDR 0x80
++#define AST3000_VGA2_OFFSETREG 0x84
++#define AST3000_VGA2_THRESHOLD 0x88
++#define AST3000_HWC2_OFFSET 0x90
++#define AST3000_HWC2_XY 0x94
++#define AST3000_HWC2_PBase 0x98
++#define AST3000_OSD2_H 0xA0
++#define AST3000_OSD2_V 0xA4
++#define AST3000_OSD2_PBase 0xA8
++#define AST3000_OSD2_Offset 0xAC
++#define AST3000_OSD2_THRESHOLD 0xB0
++
++/* Data Structure */
++typedef struct {
++ UCHAR ModeName[20];
++ USHORT usModeIndex;
++ USHORT usModeID;
++ USHORT usColorIndex;
++ USHORT usRefreshRateIndex;
++ USHORT usWidth;
++ USHORT usHeight;
++ USHORT usBitsPerPlane;
++ USHORT usRefreshRate;
++} ModeInfoStruct;
++
++typedef struct {
++
++ UCHAR MISC;
++ UCHAR SEQ[4];
++ UCHAR CRTC[25];
++ UCHAR AR[20];
++ UCHAR GR[9];
++
++} VBIOS_STDTABLE_STRUCT, *PVBIOS_STDTABLE_STRUCT;
++
++typedef struct {
++
++ ULONG HT;
++ ULONG HDE;
++ ULONG HFP;
++ ULONG HSYNC;
++ ULONG VT;
++ ULONG VDE;
++ ULONG VFP;
++ ULONG VSYNC;
++ ULONG DCLKIndex;
++ ULONG Flags;
++
++ ULONG ulRefreshRate;
++ ULONG ulRefreshRateIndex;
++ ULONG ulModeID;
++
++} VBIOS_ENHTABLE_STRUCT, *PVBIOS_ENHTABLE_STRUCT;
++
++typedef struct {
++ UCHAR Param1;
++ UCHAR Param2;
++ UCHAR Param3;
++} VBIOS_DCLK_INFO, *PVBIOS_DCLK_INFO;
++
++typedef struct {
++ UCHAR DACR;
++ UCHAR DACG;
++ UCHAR DACB;
++} VBIOS_DAC_INFO, *PVBIOS_DAC_INFO;
++
++typedef struct {
++ PVBIOS_STDTABLE_STRUCT pStdTableEntry;
++ PVBIOS_ENHTABLE_STRUCT pEnhTableEntry;
++
++} VBIOS_MODE_INFO, *PVBIOS_MODE_INFO;
+diff --git a/board/aspeed/ast2400/vhace.c b/board/aspeed/ast2400/vhace.c
+new file mode 100755
+index 0000000..d045cbd
+--- /dev/null
++++ b/board/aspeed/ast2400/vhace.c
+@@ -0,0 +1,66 @@
++/*
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++ */
++#define HASH_GLOBALS
++#include "type.h"
++#include "vdef.h"
++#include "vhace.h"
++#include "vfun.h"
++
++void HashAst3000(ULONG ulLength, ULONG *output, ULONG ulHashMode)
++{
++ ULONG i, ulTemp, ulCommand, ulDigestLength;
++ ULONG ulValue;
++
++ /* Get Info */
++ switch (ulHashMode)
++ {
++ case VHASHMODE_MD5:
++ ulCommand = VHASH_ALG_SELECT_MD5;
++ ulDigestLength = 16;
++ break;
++ case VHASHMODE_SHA1:
++ ulCommand = VHASH_ALG_SELECT_SHA1;
++ ulDigestLength = 20;
++ break;
++ case VHASHMODE_SHA256:
++ ulCommand = VHASH_ALG_SELECT_SHA256;
++ ulDigestLength = 32;
++ break;
++ case VHASHMODE_SHA224:
++ ulCommand = VHASH_ALG_SELECT_SHA224;
++ ulDigestLength = 28;
++ break;
++ }
++
++ /* Init. HW */
++ WriteMemoryLongHost(VHAC_REG_BASE, VREG_HASH_SRC_BASE_OFFSET, g_HashSrcBuffer);
++ WriteMemoryLongHost(VHAC_REG_BASE, VREG_HASH_DST_BASE_OFFSET, g_HashDstBuffer);
++ WriteMemoryLongHost(VHAC_REG_BASE, VREG_HASH_LEN_OFFSET, ulLength);
++
++ /* write src */
++ //already fill in g_VIDEO1_COMPRESS_BUF_ADDR
++
++ /* fire cmd */
++ WriteMemoryLongHost(VHAC_REG_BASE, VREG_HASH_CMD_OFFSET, ulCommand);
++
++ /* get digest */
++ do {
++ ulTemp = ReadMemoryLongHost(VHAC_REG_BASE, VREG_HASH_STATUS_OFFSET);
++ } while (ulTemp & VHASH_BUSY);
++
++ for (i=0; i<ulDigestLength/4; i++)
++ {
++ ulValue = *(((ULONG *)g_HashDstBuffer) + i);
++
++ //output is ULONG pointer
++ *(output + i) = ulValue;
++ }
++}
+diff --git a/board/aspeed/ast2400/vhace.h b/board/aspeed/ast2400/vhace.h
+new file mode 100755
+index 0000000..460989b
+--- /dev/null
++++ b/board/aspeed/ast2400/vhace.h
+@@ -0,0 +1,58 @@
++/*
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++ */
++#ifndef _VHACE_H_
++#define _VHACE_H_
++
++#define VHASHMODE_MD5 0x00
++#define VHASHMODE_SHA1 0x01
++#define VHASHMODE_SHA256 0x02
++#define VHASHMODE_SHA224 0x03
++
++#define VHASH_ALG_SELECT_MASK 0x70
++#define VHASH_ALG_SELECT_MD5 0x00
++#define VHASH_ALG_SELECT_SHA1 0x20
++#define VHASH_ALG_SELECT_SHA224 0x40
++#define VHASH_ALG_SELECT_SHA256 0x50
++
++#define VHASH_BUSY 0x01
++
++#define VHAC_REG_BASE 0x1e6e0000
++#define VHAC_REG_OFFSET 0x3000
++
++#define VREG_HASH_SRC_BASE_OFFSET (0x20+VHAC_REG_OFFSET)
++#define VREG_HASH_DST_BASE_OFFSET (0x24+VHAC_REG_OFFSET)
++#define VREG_HASH_KEY_BASE_OFFSET (0x28+VHAC_REG_OFFSET)
++#define VREG_HASH_LEN_OFFSET (0x2C+VHAC_REG_OFFSET)
++#define VREG_HASH_CMD_OFFSET (0x30+VHAC_REG_OFFSET)
++
++#define VREG_HASH_STATUS_OFFSET (0x1C+VHAC_REG_OFFSET)
++
++typedef struct
++{
++ int HashMode;
++ int DigestLen;
++} HASH_METHOD;
++
++
++#ifdef HASH_GLOBALS
++#define HASH_EXT
++#else
++#define HASH_EXT extern
++#endif
++
++HASH_EXT HASH_METHOD g_HashMethod;
++HASH_EXT BYTE g_DigestBuf[32];
++HASH_EXT ULONG g_HashSrcBuffer;
++HASH_EXT ULONG g_HashDstBuffer;
++
++void HashAst3000(ULONG ulLength, ULONG *output, ULONG ulHashMode);
++#endif
++
+diff --git a/board/aspeed/ast2400/videotest.c b/board/aspeed/ast2400/videotest.c
+new file mode 100755
+index 0000000..f2e4953
+--- /dev/null
++++ b/board/aspeed/ast2400/videotest.c
+@@ -0,0 +1,779 @@
++/*
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
++ * MA 02111-1307 USA
++ */
++
++/*
++ * Diagnostics support
++ */
++#include <common.h>
++#include <command.h>
++#include <malloc.h>
++#include <post.h>
++
++#include "slt.h"
++#define WIN_GLOBALS
++#include "type.h"
++#include "vreg.h"
++#define VESA_GLOBALS
++#include "vesa.h"
++#include "vfun.h"
++#include "vdef.h"
++#include "vhace.h"
++#include "crt.h"
++#include "videotest.h"
++
++#define VHASH_ALIGNMENT 16
++#define VHASH_MAX_DST (32+VHASH_ALIGNMENT)
++
++
++#if ((CFG_CMD_SLT & CFG_CMD_VIDEOTEST) && defined(CONFIG_SLT))
++#include "videotest.h"
++
++#define RAND_MAX 32767 //2^16-1
++
++ULONG randSeed = 1;
++
++void srand(ULONG seed)
++{
++ randSeed = seed;
++}
++
++int rand(void)
++{
++ randSeed = randSeed * 214013 + 2531011;
++ return (int)(randSeed >> 17); //32 -15 = 17
++}
++
++//static unsigned char CaptureVideo1Buf1Addr[VIDEO_SOURCE_SIZE], CaptureVideo1Buf2Addr[VIDEO_SOURCE_SIZE], Video1CompressBufAddr[CRYPTO_MAX_CONTEXT];
++ULONG pCaptureVideo1Buf1Addr[VIDEO_SOURCE_SIZE/4], pCaptureVideo1Buf2Addr[VIDEO_SOURCE_SIZE/4], pVideo1CompressBufAddr[VIDEO_MAX_STREAM_SIZE/4], pVideo1FlagBufAddr[VIDEO_FLAG_SIZE];
++ULONG pCaptureVideo2Buf1Addr[VIDEO_SOURCE_SIZE/4], pCaptureVideo2Buf2Addr[VIDEO_SOURCE_SIZE/4], pVideo2CompressBufAddr[VIDEO_MAX_STREAM_SIZE/4], pVideo2FlagBufAddr[VIDEO_FLAG_SIZE];
++
++ULONG pVHashDstBuffer[VHASH_MAX_DST/4];
++
++ULONG pVideo1DecAddr[VIDEO_SOURCE_SIZE/4];
++ULONG pCrt1Addr[VIDEO_SOURCE_SIZE/4];
++//ULONG pCap1Addr[VIDEO_SOURCE_SIZE/4];
++
++BOOL AllocateEncodeBufHost(ULONG MMIOBase, int nVideo)
++{
++ //ULONG Addr;
++ //ULONG dwRegOffset = nVideo * 0x100;
++
++ if (VIDEO1 == nVideo)
++ {
++
++ //Addr = (ULONG)malloc(pVideoInfo->SrcWidth * pVideoInfo->SrcHeight * 4);
++ //pCaptureVideo1Buf1Addr = malloc(VIDEO_SOURCE_SIZE);
++
++ g_CAPTURE_VIDEO1_BUF1_ADDR = vBufAlign((ULONG)pCaptureVideo1Buf1Addr);
++ WriteMemoryLongWithMASKHost(VIDEO_REG_BASE, VIDEO1_BUF_1_ADDR_REG, g_CAPTURE_VIDEO1_BUF1_ADDR, BUF_1_ADDR_MASK);
++
++ //Addr = (ULONG)malloc(pVideoInfo->SrcWidth * pVideoInfo->SrcHeight * 4);
++ //pCaptureVideo1Buf2Addr = malloc(VIDEO_SOURCE_SIZE);
++
++ g_CAPTURE_VIDEO1_BUF2_ADDR = vBufAlign((ULONG)pCaptureVideo1Buf2Addr);
++ WriteMemoryLongWithMASKHost(VIDEO_REG_BASE, VIDEO1_BUF_2_ADDR_REG, g_CAPTURE_VIDEO1_BUF2_ADDR, BUF_2_ADDR_MASK);
++
++ //Addr = (ULONG)malloc(pVideoInfo->uStreamBufSize.StreamBufSize.RingBufNum * pVideoInfo->uStreamBufSize.StreamBufSize.PacketSize)
++ //pVideo1CompressBufAddr = malloc(VIDEO_MAX_STREAM_SIZE);
++ g_VIDEO1_COMPRESS_BUF_ADDR = vBufAlign((ULONG)pVideo1CompressBufAddr);
++ WriteMemoryLongWithMASKHost(VIDEO_REG_BASE, VIDEO1_COMPRESS_BUF_ADDR_REG, g_VIDEO1_COMPRESS_BUF_ADDR, BUF_2_ADDR_MASK);
++
++ //Addr = (ULONG)malloc((pVideoInfo->SrcHeigh/64) * pVideoInfo->SrcWidth * 8);
++ //g_VIDEO1_CRC_BUF_ADDR = vBufAlign((ULONG)malloc(VIDEO_MAX_STREAM_SIZE));
++ //WriteMemoryLongWithMASKHost(VIDEO_REG_BASE, VIDEO1_CRC_BUF_ADDR_REG, g_VIDEO1_CRC_BUF_ADDR, BUF_2_ADDR_MASK);
++
++
++ //Addr = (ULONG)malloc(pVideoInfo->SrcHeigh * pVideoInfo->SrcWidth / 128 (/64*4/8));
++ //pVideo1FlagBufAddr = malloc(VIDEO_FLAG_SIZE);
++ g_VIDEO1_FLAG_BUF_ADDR = vBufAlign((ULONG)pVideo1FlagBufAddr);
++ WriteMemoryLongWithMASKHost(VIDEO_REG_BASE, VIDEO1_FLAG_BUF_ADDR_REG, g_VIDEO1_FLAG_BUF_ADDR, BUF_2_ADDR_MASK);
++ }
++ else if (VIDEO2 == nVideo)
++ {
++ //Addr = (ULONG)malloc(pVideoInfo->SrcWidth * pVideoInfo->SrcHeight * 4);
++ //pCaptureVideo2Buf1Addr = malloc(VIDEO_SOURCE_SIZE);
++ g_CAPTURE_VIDEO2_BUF1_ADDR = vBufAlign((ULONG)pCaptureVideo2Buf1Addr);
++ WriteMemoryLongWithMASKHost(VIDEO_REG_BASE, VIDEO2_BUF_1_ADDR_REG, g_CAPTURE_VIDEO2_BUF1_ADDR, BUF_1_ADDR_MASK);
++
++ //Addr = (ULONG)malloc(pVideoInfo->SrcWidth * pVideoInfo->SrcHeight * 4);
++ //pCaptureVideo2Buf2Addr = malloc(VIDEO_SOURCE_SIZE);
++ g_CAPTURE_VIDEO2_BUF2_ADDR = vBufAlign((ULONG)pCaptureVideo2Buf2Addr);
++ WriteMemoryLongWithMASKHost(VIDEO_REG_BASE, VIDEO2_BUF_2_ADDR_REG, g_CAPTURE_VIDEO2_BUF2_ADDR, BUF_2_ADDR_MASK);
++
++ //Addr = (ULONG)malloc(pVideoInfo->uStreamBufSize.StreamBufSize.RingBufNum * pVideoInfo->uStreamBufSize.StreamBufSize.PacketSize)
++ //pVideo2CompressBufAddr = malloc(VIDEO_MAX_STREAM_SIZE);
++ g_VIDEO2_COMPRESS_BUF_ADDR = vBufAlign((ULONG)pVideo2CompressBufAddr);
++ WriteMemoryLongWithMASKHost(VIDEO_REG_BASE, VIDEO2_COMPRESS_BUF_ADDR_REG, g_VIDEO2_COMPRESS_BUF_ADDR, BUF_2_ADDR_MASK);
++
++ //Addr = (ULONG)malloc((pVideoInfo->SrcHeigh/64) * pVideoInfo->SrcWidth * 8);
++ //g_VIDEO1_CRC_BUF_ADDR = vBufAlign((ULONG)malloc(VIDEO_MAX_STREAM_SIZE));
++ //WriteMemoryLongWithMASKHost(VIDEO_REG_BASE, VIDEO1_CRC_BUF_ADDR_REG, g_VIDEO1_CRC_BUF_ADDR, BUF_2_ADDR_MASK);
++
++
++ //Addr = (ULONG)malloc(pVideoInfo->SrcHeigh * pVideoInfo->SrcWidth / 128 (/64*4/8));
++ //pVideo2FlagBufAddr = malloc(VIDEO_FLAG_SIZE);
++ g_VIDEO2_FLAG_BUF_ADDR = vBufAlign((ULONG)pVideo2FlagBufAddr);
++ WriteMemoryLongWithMASKHost(VIDEO_REG_BASE, VIDEO2_FLAG_BUF_ADDR_REG, g_VIDEO2_FLAG_BUF_ADDR, BUF_2_ADDR_MASK);
++ }
++
++}
++
++/********************************************************/
++/* 1. product random data to encode */
++/* 2. use hash to verify encode function */
++/* 3. use encode stream to decompress original data */
++/********************************************************/
++int CodecTest(void)
++{
++ int num, i=0, j=0;
++ ULONG ulTemp = 0, ulTemp2;
++ int dwValue;
++ ULONG ulHWWp;
++ ULONG ulHWPt;
++
++ //max size
++ ULONG tArray[32/4];
++
++ //mode detection
++ BOOL bExternal = TRUE;
++ BOOL bAnalog = TRUE;
++ ULONG Status;
++
++#if defined(CONFIG_AST2300)
++ ULONG ulHashSha1[5] = {0x3f0c2ad6,0xc8eb7074,0xa9929352,0xfcd5b8b0,0x76fa8461};
++ ULONG aHashDecode[5] = {0xb23b62bb,0xd22a602b,0x113038a0,0x7217c6ab,0xcb156f06};
++#else
++ ULONG ulHashSha1[5] = {0x2a19e99f,0x99b1bb2d,0x9ac82862,0x49205e43,0x6bc4b4d7};
++ ULONG aHashDecode[5] = {0x2907a827,0xaf337079,0x47817f1f,0xb0b7cd68,0x8d33bd2};
++#endif
++
++ //Load pattern to src1 & src2 buffer
++ srand(1);
++
++ //Total size : DefWidth*DeHeight*4
++ //rand function: 16 bits one time is equal to 2 bytes
++ //OutdwmBankMode: 32 bits one time is equal to 4 bytes
++ for (i=0; i<g_DefWidth*g_DefHeight*2; i++)
++ {
++ if (i%2)
++ {
++ ulTemp2 = rand();
++ ulTemp = (ulTemp2 << 16) | ulTemp;
++ //WriteMemoryLongHost(DRAM_BASE, g_CAPTURE_VIDEO1_BUF1_ADDR + ((i-1)/2)*4, ulTemp);
++ *(((ULONG *)g_CAPTURE_VIDEO1_BUF1_ADDR) + (i-1)/2) = ulTemp;
++ ulTemp = 0;
++ }
++ else
++ {
++ ulTemp = rand();
++ }
++ }
++
++ /* init encoder engine */
++ InitializeVideoEngineHost (0,
++ VIDEO1,
++ vModeTable[2].HorPolarity,
++ vModeTable[2].VerPolarity);
++
++ /* reset offset pointer register*/
++ WriteMemoryLongWithMASKHost(VIDEO_REG_BASE, VIDEO1_ENGINE_SEQUENCE_CONTROL_REG, 0, VIDEO_CODEC_TRIGGER | VIDEO_CAPTURE_TRIGGER);
++
++ WriteMemoryLongWithMASKHost(VIDEO_REG_BASE, VIDEO1_COMPRESS_BUF_READ_OFFSET_REG, 0, COMPRESS_BUF_READ_OFFSET_MASK);
++ WriteMemoryLongWithMASKHost(VIDEO_REG_BASE, VIDEO1_BUF_CODEC_OFFSET_READ, 0, BUF_CODEC_OFFSET_MASK);
++ WriteMemoryLongWithMASKHost(VIDEO_REG_BASE, VIDEO1_COMPRESS_BUF_PROCESS_OFFSET_REG, 0, COMPRESS_BUF_PROCESS_OFFSET_MASK);
++ WriteMemoryLongWithMASKHost(VIDEO_REG_BASE, VIDEO1_COMPRESS_FRAME_END_READ, 0, COMPRESS_FRAME_END_READ_MASK);
++
++ /* start compress stream */
++ WriteMemoryLongWithMASKHost(VIDEO_REG_BASE, VIDEO1_ENGINE_SEQUENCE_CONTROL_REG, MODE_DETECTION_TRIGGER, MODE_DETECTION_TRIGGER);
++ //Stream mode: set CODEC trigger first
++ WriteMemoryLongWithMASKHost(VIDEO_REG_BASE, VIDEO1_ENGINE_SEQUENCE_CONTROL_REG, VIDEO_CODEC_TRIGGER, VIDEO_CODEC_TRIGGER);
++
++ //Stream mode: start trigger (only trigger capture bit)
++ StartVideoCaptureTriggerHost(0, VIDEO1_ENGINE_SEQUENCE_CONTROL_REG);
++
++ //stop engine
++ WriteMemoryLongWithMASKHost(VIDEO_REG_BASE, VIDEO1_ENGINE_SEQUENCE_CONTROL_REG, 0, 0xFF);
++#if defined(CONFIG_AST2300)
++ do { /* wait compress engine idle */
++ ulTemp = ReadMemoryLongHost(VIDEO_REG_BASE, VIDEO1_ENGINE_SEQUENCE_CONTROL_REG);
++ } while (!(ulTemp & 0x40000));
++#endif
++
++ //read 30 times to get HW write pointer
++ for (i=0; i<30000; i++)
++ ulHWWp = ReadMemoryLongHost(VIDEO_REG_BASE, VIDEO1_BUF_CODEC_OFFSET_READ);
++
++ g_HashSrcBuffer = g_VIDEO1_COMPRESS_BUF_ADDR + 128; //skip encode data 128 byte
++ g_HashDstBuffer = v16byteAlign((unsigned long)pVHashDstBuffer);
++ ulTemp = 300;
++
++ //Enable hash clock
++ WriteMemoryLongWithMASKHost(SCU_BASE, SCU_CLOCK_STOP_REG, EN_HACE, STOP_HACE_MASK);
++ g_HashMethod.HashMode = VHASHMODE_SHA1;
++ g_HashMethod.DigestLen = 20;
++ HashAst3000(ulTemp, tArray, g_HashMethod.HashMode);
++
++ if (strncmp((const char *)tArray, (const char *)ulHashSha1, g_HashMethod.DigestLen))
++ {
++ printf("[VIDEO] Encoder Test: Wrong\n");
++ //ExitVideoTest();
++ return VIDEO_ENCODE_FAIL;
++ }
++ else
++ {
++ printf("[VIDEO] Encoder Test: Pass\n");
++ }
++
++#if 0
++ /******** prepare for next decoding test at the same chip ***********/
++ ResetVideoHost();
++
++ dwValue=0;
++
++ do
++ {
++ dwValue = UnlockVideoRegHost(0, VIDEO_UNLOCK_KEY);
++ i++;
++ }
++ while ((VIDEO_UNLOCK != dwValue) && (i<10));
++
++ if (VIDEO_UNLOCK != dwValue)
++ {
++ printf("[VIDEO] Video register is locked");
++ return VIDEO_UNLOCK_FAIL;
++ }
++
++ // allocate decoding buffer
++ //Use Compress buffer last time, and Don't need to allocate
++ g_VIDEO1_DECODE_BUF_1_ADDR = g_VIDEO1_COMPRESS_BUF_ADDR;
++ WriteMemoryLongWithMASKHost(VIDEO_REG_BASE, VIDEO1_BUF_1_ADDR_REG, g_VIDEO1_DECODE_BUF_1_ADDR, BUF_1_ADDR_MASK);
++
++ // pVideo1DecAddr = malloc(VIDEO_SOURCE_SIZE);
++ g_VIDEO1_DECOMPRESS_BUF_ADDR = vBufAlign((unsigned long)pVideo1DecAddr);
++ WriteMemoryLongWithMASKHost(VIDEO_REG_BASE, VIDEO1_COMPRESS_BUF_ADDR_REG, g_VIDEO1_DECOMPRESS_BUF_ADDR, COMPRESS_BUF_ADDR_MASK);
++
++ //Addr = (ULONG)malloc(256);
++ //g_VIDEO1_RC4_BUF_ADDR = Addr;
++ //g_VIDEO1_DECODE_RC4_BUF_ADDR = g_VIDEO1_DECOMPRESS_BUF_ADDR + 0x800000; //assume video size is 8MB for umcompressed buf;
++ //WriteMemoryLongWithMASKClient(VIDEO_REG_BASE, VIDEO1_RC4_TABLE_ADDR, g_VIDEO1_DECODE_RC4_BUF_ADDR, RC4_TABLE_ADDR_MASK);
++
++ //HW recommanded value
++ WriteMemoryLongWithMASKHost(VIDEO_REG_BASE, VIDEO1_BUF_2_ADDR_REG, g_VIDEO1_DECOMPRESS_BUF_ADDR, BUF_2_ADDR_MASK);
++ //WriteMemoryLongWithMASKClient(VIDEO_REG_BASE, VIDEO1_BUF_2_ADDR_REG, 0, BUF_2_ADDR_MASK);
++ WriteMemoryLongWithMASKHost(VIDEO_REG_BASE, VIDEO1_CRC_BUF_ADDR_REG, 0, BUF_2_ADDR_MASK);
++
++ /* init encoder engine */
++ InitializeVideoEngineClient (0, VIDEO1);
++
++ /* reset offset pointer register*/
++ WriteMemoryLongWithMASKHost(VIDEO_REG_BASE, VIDEO1_ENGINE_SEQUENCE_CONTROL_REG, 0, VIDEO_CODEC_TRIGGER | VIDEO_CAPTURE_TRIGGER);
++
++ WriteMemoryLongWithMASKHost(VIDEO_REG_BASE, VIDEO1_COMPRESS_BUF_READ_OFFSET_REG, 0, COMPRESS_BUF_READ_OFFSET_MASK);
++ WriteMemoryLongWithMASKHost(VIDEO_REG_BASE, VIDEO1_BUF_CODEC_OFFSET_READ, 0, BUF_CODEC_OFFSET_MASK);
++ WriteMemoryLongWithMASKHost(VIDEO_REG_BASE, VIDEO1_COMPRESS_BUF_PROCESS_OFFSET_REG, 0, COMPRESS_BUF_PROCESS_OFFSET_MASK);
++ WriteMemoryLongWithMASKHost(VIDEO_REG_BASE, VIDEO1_COMPRESS_FRAME_END_READ, 0, COMPRESS_FRAME_END_READ_MASK);
++
++ StartVideoCodecTriggerHost(0, VIDEO1_ENGINE_SEQUENCE_CONTROL_REG);
++
++ //wrtie SW write pointer
++ WriteMemoryLongWithMASKHost(VIDEO_REG_BASE, VIDEO1_DECOMPRESS_BUF_PROCESS_OFFSET_REG, ulHWWp, COMPRESS_BUF_READ_OFFSET_MASK);
++ WriteMemoryLongWithMASKHost(VIDEO_REG_BASE, VIDEO1_DECOMPRESS_BUF_WRITE_OFFSET_REG, ulHWWp, COMPRESS_BUF_READ_OFFSET_MASK);
++
++ i = 0;
++
++ do
++ {
++ ulHWPt = ReadMemoryLongHost(VIDEO_REG_BASE, VIDEO1_BUF_CODEC_OFFSET_READ);
++ i++;
++ }while((ulHWPt != ulHWWp) && (i<10000));
++
++ if (10000 > i)
++ {
++ printf("[VIDEO] Decoder Pointer cannot move!!! /n");
++ //ExitVideoTest();
++ return VIDEO_DECODE_FAIL;
++ }
++
++ //8*8 YUVA block
++ for (i=24; i<g_DefWidth*g_DefHeight; i=i+32)
++ {
++ *(((ULONG *)g_VIDEO1_DECOMPRESS_BUF_ADDR) + i) = 0x0;
++ *(((ULONG *)g_VIDEO1_DECOMPRESS_BUF_ADDR) + i+1) = 0x0;
++ }
++
++ g_HashSrcBuffer = g_VIDEO1_DECOMPRESS_BUF_ADDR;
++ //g_HashDstBuffer = VIDEO1_EN_BASE + VIDEO_ALL_SIZE; //config forward
++
++ ulTemp = 300;
++
++ //Enable hash clock
++ WriteMemoryLongWithMASKHost(SCU_BASE, SCU_CLOCK_STOP_REG, EN_HACE, STOP_HACE_MASK);
++ g_HashMethod.HashMode = VHASHMODE_SHA1;
++ g_HashMethod.DigestLen = 20;
++ HashAst3000(ulTemp, tArray, g_HashMethod.HashMode);
++
++ if (strncmp((const char *)tArray, (const char *)aHashDecode, g_HashMethod.DigestLen))
++ {
++ printf("[VIDEO] Decoder Test: Wrong\n");
++ //ExitVideoTest();
++ return VIDEO_DECODE_FAIL;
++ }
++ else
++ {
++ printf("[VIDEO] Decoder Test: Pass\n");
++ }
++#endif
++
++ return VIDEO_TEST_OK;
++}
++
++/********************************************************/
++/* Only used in the host */
++/* test function: Mode detection and Capture pattern */
++/********************************************************/
++int CapTest(void)
++{
++ ULONG dwValue, Status;
++ int i;
++ BOOL bAnalog;
++ ULONG HStart, HEnd, VStart, VEnd;
++ USHORT usCRTHor, usCRTVer;
++ ULONG ulHor, ulVer;
++ ULONG ulVGABaseAddr, ulCapAddr;
++ ULONG ulFlag;
++
++ printf("\n --------- Mode Detection Test --------- \n");
++ //clear clear register
++ WriteMemoryLongHost(VIDEO_REG_BASE, VIDEO1_CONTROL_REG, 0);
++ dwValue = ReadMemoryLongHost(VIDEO_REG_BASE, VIDEO1_CONTROL_REG);
++
++ // Note: Current mode detection procedure has to set signal input 1st
++ //Note: Clear and enable interrupt Encode
++ ClearVideoInterruptHost(0, VIDEO1_MODE_DETECTION_READY_CLEAR);
++ WriteMemoryLongWithMASKHost(VIDEO_REG_BASE, VIDEO_INT_CONTROL_EN_REG, VIDEO1_MODE_DETECTION_READY_INT_EN, VIDEO1_MODE_DETECTION_READY_INT_EN);
++ // Set input signal
++ dwValue |= EXTERNAL_VGA_SOURCE;
++
++ WriteMemoryLongWithMASKHost(VIDEO_REG_BASE, VIDEO1_CONTROL_REG, (dwValue <<EXTERNAL_SOURCE_BIT), EXTERNAL_SOURCE_MASK);
++
++// Set H/V stable maximum
++ WriteMemoryLongWithMASKHost(VIDEO_REG_BASE, VIDEO_MODE_DETECTION_PARAM_REG, (MODEDETECTION_VERTICAL_STABLE_MAXIMUM << VER_STABLE_MAX_BIT), 0x000F0000);
++ WriteMemoryLongWithMASKHost(VIDEO_REG_BASE, VIDEO_MODE_DETECTION_PARAM_REG, (MODEDETECTION_HORIZONTAL_STABLE_MAXIMUM << HOR_STABLE_MAX_BIT), HOR_STABLE_MAX_BIT_MASK);
++// Set H/V stable threshold
++ WriteMemoryLongWithMASKHost(VIDEO_REG_BASE, VIDEO_MODE_DETECTION_PARAM_REG, (MODEDETECTION_VERTICAL_STABLE_THRESHOLD << VER_STABLE_THRES_BIT), VER_STABLE_THRES_BIT_MASK);
++ WriteMemoryLongWithMASKHost(VIDEO_REG_BASE, VIDEO_MODE_DETECTION_PARAM_REG, (MODEDETECTION_HORIZONTAL_STABLE_THRESHOLD << HOR_STABLE_THRES_BIT), HOR_STABLE_THRES_BIT_MASK);
++
++ //Trigger mode detection
++ // turn off WATCH_DOG first
++ WriteMemoryLongWithMASKHost(VIDEO_REG_BASE, VIDEO1_ENGINE_SEQUENCE_CONTROL_REG, (WATCH_DOG_OFF << WATCH_DOG_ENABLE_BIT), WATCH_DOG_EN_MASK);
++
++ // Note: Clear mode detection ready interrupt
++ //ClearVideoInterrupt(MMIOBase, MODE_DETECTION_READY_CLEAR);
++ StartModeDetectionTriggerHost(0, VIDEO1_ENGINE_SEQUENCE_CONTROL_REG);
++
++
++// Note: Polling mode detection ready interrupt
++ //it sometime take a long time, especially during change mode,
++ //so the loop count must be big, or you can't pull it by timer
++ i = 0;
++ do {
++
++ Status = ReadVideoInterruptHost(0, VIDEO1_MODE_DETECTION_READY_READ);
++ i++;
++ } while ((!Status) & (i<500000));
++
++ if (!Status)
++ {
++ printf("[VIDEO] Mode detection error\n");
++ //ExitVideoTest();
++ return VIDEO_TEST_FAIL;
++ }
++
++ HStart = (ReadMemoryLongHost(VIDEO_REG_BASE, VIDE1_MODE_DETECTION_EDGE_H_REG) & LEFT_EDGE_LOCATION_MASK) >> LEFT_EDGE_LOCATION_BIT;
++ HEnd = (ReadMemoryLongHost(VIDEO_REG_BASE, VIDE1_MODE_DETECTION_EDGE_H_REG) & RIGHT_EDGE_LOCATION_MASK) >> RIGHT_EDGE_LOCATION_BIT;
++
++ VStart = (ReadMemoryLongHost(VIDEO_REG_BASE, VIDE1_MODE_DETECTION_EDGE_V_REG) & TOP_EDGE_LOCATION_MASK) >> TOP_EDGE_LOCATION_BIT;
++ VEnd = (ReadMemoryLongHost(VIDEO_REG_BASE, VIDE1_MODE_DETECTION_EDGE_V_REG) & BOTTOM_EDGE_LOCATION_MASK) >> BOTTOM_EDGE_LOCATION_BIT;
++
++ ulHor = HEnd-HStart+1;
++ ulVer = VEnd-VStart+1;
++
++ printf("[VIDEO] Resolution: H[%d] * V[%d]\n", ulHor, ulVer);
++
++ if ((g_DefWidth == ulHor) & (g_DefHeight == ulVer))
++ {
++ printf("[VIDEO] Mode detection PASS\n");
++ }
++ else
++ {
++ printf("[VIDEO] Mode detection FAIL\n");
++ return VIDEO_TEST_FAIL;
++ }
++
++ if(!((ReadMemoryLongHost(VIDEO_REG_BASE, VIDEO1_MODE_DETECTION_STATUS_READ_REG) & ANALONG_DIGITAL_READ) >> ANALONG_DIGITAL_READ_BIT))
++ bAnalog = FALSE;
++ else
++ bAnalog = TRUE;
++
++ // Note: Clear mode detection ready interrupt
++ ClearVideoInterruptHost(0, VIDEO1_MODE_DETECTION_READY_CLEAR);
++
++ printf("\n --------- Capture Test --------- \n");
++
++ //capture engine
++ WriteMemoryLongWithMASKHost(VIDEO_REG_BASE, VIDEO1_TIMEING_GEN_HOR_REG, (HEnd << VIDEO_HDE_END_BIT), VIDEO_HDE_END_MASK);
++ WriteMemoryLongWithMASKHost(VIDEO_REG_BASE, VIDEO1_TIMEING_GEN_HOR_REG, (HStart << VIDEO_HDE_START_BIT), VIDEO_HDE_START_MASK);
++ WriteMemoryLongWithMASKHost(VIDEO_REG_BASE, VIDEO1_TIMEING_GEN_V_REG, (VEnd << VIDEO_VDE_END_BIT), VIDEO_VDE_END_MASK);
++ WriteMemoryLongWithMASKHost(VIDEO_REG_BASE, VIDEO1_TIMEING_GEN_V_REG, (VStart << VIDEO_VDE_START_BIT), VIDEO_VDE_START_MASK);
++
++ ulCapAddr = vBufAlign2((ULONG)pCaptureVideo1Buf1Addr);
++ WriteMemoryLongWithMASKHost(VIDEO_REG_BASE, VIDEO1_BUF_1_ADDR_REG, ulCapAddr, BUF_1_ADDR_MASK);
++
++ WriteMemoryLongWithMASKHost(VIDEO_REG_BASE, VIDEO1_BUF_2_ADDR_REG, 0, BUF_2_ADDR_MASK);
++
++ InitializeVideoEngineHost (0,
++ VIDEO1,
++ vModeTable[2].HorPolarity,
++ vModeTable[2].VerPolarity);
++
++ WriteMemoryLongHost(VIDEO_REG_BASE, 0x04, 0x01);
++ WriteMemoryLongHost(VIDEO_REG_BASE, 0x300, 0x0);
++#if defined(CONFIG_AST2300)
++ WriteMemoryLongWithMASKHost(VIDEO_REG_BASE, 0x8, 0x0880, 0x0ec0);
++#elif defined(CONFIG_AST3000)
++ WriteMemoryLongWithMASKHost(VIDEO_REG_BASE, 0x8, 0x2800, 0x2800);
++#else
++ WriteMemoryLongWithMASKHost(VIDEO_REG_BASE, 0x8, 0xa00, 0x2a80); //tile mode
++#endif
++
++ WriteMemoryLongWithMASKHost(VIDEO_REG_BASE, VIDEO1_TIMEING_GEN_HOR_REG, 0xa0000000, 0xa0000000);
++
++ //only trigger capture, in source buffer (vr44), the front of data is correct.
++ //StartVideoCaptureTriggerHost(0, VIDEO1_ENGINE_SEQUENCE_CONTROL_REG);
++ WriteMemoryLongHost(VIDEO_REG_BASE, VIDEO1_ENGINE_SEQUENCE_CONTROL_REG, VIDEO_CAPTURE_TRIGGER);
++
++ i = 0;
++ do {
++ Status = ReadMemoryLongHost(VIDEO_REG_BASE, VIDEO1_ENGINE_SEQUENCE_CONTROL_REG) & CAPTURE_READY_MASK;
++ i++;
++ } while ((!Status) & (i<500000));
++
++ if (!Status)
++ {
++ printf("[VIDEO] Capture is not READY\n");
++ return VIDEO_TEST_FAIL;
++ }
++
++#if !defined(CONFIG_AST2300)
++ ulVGABaseAddr = ulCapAddr + 0x1000;
++
++ /* check pattern */
++ ulFlag = 0; //no 0 is error
++
++ for (i=0; i<100; i++)
++ {
++ dwValue = *(ULONG *)(ulVGABaseAddr + i*32);
++ if (0x32323232 != dwValue)
++ {
++ printf("[VIDEO] Capture Test fail -- capture data doesn't match source \n");
++ printf("[VIDEO]1 i=%d value=%x\n", i, dwValue);
++ ulFlag = 1;
++ break;
++ }
++
++ dwValue = *(ULONG *)(ulVGABaseAddr + i*32 + 4);
++ if (0x32323232 != dwValue)
++ {
++ printf("[VIDEO] Capture Test fail -- capture data doesn't match source \n");
++ printf("[VIDEO]2 i=%d value=%x\n", i, dwValue);
++ ulFlag = 1;
++ break;
++ }
++
++ dwValue = *(ULONG *)(ulVGABaseAddr + i*32 + 8);
++ if (0x80808080 != dwValue)
++ {
++ printf("[VIDEO] Capture Test fail -- capture data doesn't match source \n");
++ printf("[VIDEO]3 i=%d value=%x\n", i, dwValue);
++ ulFlag = 1;
++ break;
++ }
++
++ dwValue = *(ULONG *)(ulVGABaseAddr + i*32 + 12);
++ if (0x80808080 != dwValue)
++ {
++ printf("[VIDEO] Capture Test fail -- capture data doesn't match source \n");
++ printf("4 i=%d value=%x\n", i, dwValue);
++ ulFlag = 1;
++ break;
++ }
++
++ dwValue = *(ULONG *)(ulVGABaseAddr + i*32 + 16);
++ if (0x80808080 != dwValue)
++ {
++ printf("[VIDEO] Capture Test fail -- capture data doesn't match source \n");
++ printf("5 i=%d value=%x\n", i, dwValue);
++ ulFlag = 1;
++ break;
++ }
++
++ dwValue = *(ULONG *)(ulVGABaseAddr + i*32 + 20);
++ if (0x80808080 != dwValue)
++ {
++ printf("[VIDEO] Capture Test fail -- capture data doesn't match source \n");
++ printf("6 i=%d value=%x\n", i, dwValue);
++ ulFlag = 1;
++ break;
++ }
++ }
++#endif
++
++ if (!ulFlag)
++ {
++ printf("[VIDEO] Capture Test OK\n");
++ }
++ else
++ {
++ printf("[VIDEO] Capture Test FAIL\n");
++ return VIDEO_TEST_FAIL;
++ }
++
++ return VIDEO_TEST_OK;
++}
++
++/********************************************************/
++/* Only used in the station */
++/********************************************************/
++int CRTTest(void)
++{
++ ULONG ulVGABaseAddr;
++ BYTE btCRTCenterMode, btCRTColorFmt;
++ USHORT usCRTHor, usCRTVer;
++ ULONG ulData;
++
++ int i,j;
++
++ //printf("\n --------- Turn on CRT --------- \n");
++
++ //Enable CRT1 first
++ ulVGABaseAddr = vBufAlign((unsigned long)pCrt1Addr);
++
++ btCRTCenterMode = 0;
++ btCRTColorFmt = YUV_444;
++ usCRTHor = g_DefWidth;
++ usCRTVer = g_DefHeight;
++
++ CheckOnStartClient();
++
++ /* Fill Pattern */
++ for (i=0; i<usCRTHor; i++)
++ {
++ for (j=0; j<usCRTVer/8; j++)
++ {
++ //Y
++ //ulData = 0x10101010;
++ ulData = 0x32323232;
++ *(ULONG *)(ulVGABaseAddr + (i*usCRTVer*4+j*32)) = ulData;
++ //ulData = 0x10101010;
++ ulData = 0x32323232;
++ *(ULONG *)(ulVGABaseAddr + (i*usCRTVer*4+j*32) +4) = ulData;
++ //U
++ ulData = 0x80808080;
++ //ulData = 0x77777777;
++ *(ULONG *)(ulVGABaseAddr + (i*usCRTVer*4+j*32) +8) = ulData;
++ ulData = 0x80808080;
++ //ulData = 0x77777777;
++ *(ULONG *)(ulVGABaseAddr + (i*usCRTVer*4+j*32) +12) = ulData;
++ //V
++ ulData = 0x80808080;
++ //ulData = 0x11111111;
++ *(ULONG *)(ulVGABaseAddr + (i*usCRTVer*4+j*32) +16) = ulData;
++ ulData = 0x80808080;
++ //ulData = 0x11111111;
++ *(ULONG *)(ulVGABaseAddr + (i*usCRTVer*4+j*32) +20) = ulData;
++ //A
++ ulData = 0xFFFFFFFFF;
++ *(ULONG *)(ulVGABaseAddr + (i*usCRTVer*4+j*32) +24) = ulData;
++ ulData = 0xFFFFFFFFF;
++ *(ULONG *)(ulVGABaseAddr + (i*usCRTVer*4+j*32) +28) = ulData;
++ }
++ } /* ~Fill Pattern */
++
++#if defined(CONFIG_AST2300)
++ if(!ASTSetModeV (0, CRT_2, ulVGABaseAddr, usCRTHor, usCRTVer, btCRTColorFmt, btCRTCenterMode))
++#else
++ if(!ASTSetModeV (0, CRT_1, ulVGABaseAddr, usCRTHor, usCRTVer, btCRTColorFmt, btCRTCenterMode))
++#endif
++ {
++ printf("[VIDEO] The resolution is not in mode table list\n");
++ return CRT_FAIL;
++ }
++
++ //printf("[VIDEO] CRT turn on\n");
++
++ return VIDEO_TEST_OK;
++}
++
++int do_videotest (void)
++{
++ int dwValue=0;
++ int i = 0;
++ int iRet;
++ ULONG ulRestore1, ulTemp;
++ BOOL bClient;
++
++
++ //InitVideoTest();
++ g_DefWidth = 640;
++ g_DefHeight= 480;
++
++ printf("\n --------- Codec Test --------- \n");
++
++#if defined(CONFIG_AST2300)
++ WriteMemoryLongWithMASKHost(SCU_BASE, SCU_CONTROL_REG, 0x00002000, 0x00002000);
++#endif
++
++ CheckOnStartHost();
++
++ do
++ {
++ dwValue = UnlockVideoRegHost(0, VIDEO_UNLOCK_KEY);
++ i++;
++ }
++ while ((VIDEO_UNLOCK != dwValue) && (i<1000));
++
++ if (VIDEO_UNLOCK != dwValue)
++ {
++ printf("[VIDEO] Video register is locked \n");
++ return VIDEO_TEST_FAIL;
++ }
++ AllocateEncodeBufHost(0, VIDEO1);
++
++ iRet = CodecTest();
++ if (iRet)
++ return VIDEO_TEST_FAIL;
++
++#if defined(CONFIG_AST2300)
++ /* Init SCU */
++ WriteMemoryLongWithMASKHost(SCU_BASE, (0x2c + SCU_OFFSET), 0x00040000, 0x00040010); /* Enable D2-PLL */
++ WriteMemoryLongWithMASKHost(SCU_BASE, SCU_CLOCK_STOP_REG, 0, 0x00000400); /* Enable D2CLK */
++ udelay(10);
++ WriteMemoryLongWithMASKHost(SCU_BASE, SCU_CONTROL_REG, 0, 0x00002000);
++
++ WriteMemoryLongWithMASKHost(SCU_BASE, (0x90 + SCU_OFFSET), 0x20, 0x00000030); /* enable video mode single edge */
++ WriteMemoryLongWithMASKHost(SCU_BASE, (0x84 + SCU_OFFSET), 0xfffe0000, 0xfffe0000); /* multi-pins */
++ WriteMemoryLongWithMASKHost(SCU_BASE, (0x88 + SCU_OFFSET), 0x000fffff, 0x000fffff); /* multi-pins */
++
++ iRet = CRTTest();
++ if (iRet)
++ {
++ printf("[VIDEO] CRT Test Failed \n");
++ return VIDEO_TEST_FAIL;
++ }
++
++ iRet = CapTest();
++ if (iRet)
++ {
++ printf("[VIDEO] Capture Test Failed \n");
++ return VIDEO_TEST_FAIL;
++ }
++#else
++ //Host or Client
++ bClient = ((ReadMemoryLong(SCU_BASE, SCU_HW_TRAPPING_REG) & CLIENT_MODE_EN_MASK)?TRUE:FALSE);
++ //reset video for another testing
++ ResetVideoHost();
++ dwValue=0;
++ i = 0;
++ do
++ {
++ dwValue = UnlockVideoRegHost(0, VIDEO_UNLOCK_KEY);
++ i++;
++ }
++ while ((VIDEO_UNLOCK != dwValue) && (i<10));
++
++ if (VIDEO_UNLOCK != dwValue)
++ {
++ printf("[VIDEO] Video register is locked");
++ return VIDEO_UNLOCK_FAIL;
++ }
++
++ //check if 1e6e0008[3,0] is 0
++ ulRestore1 = ReadMemoryLongHost(0x1e6e0000, 8);
++ dwValue = ReadMemoryLongHost(0x1e6e0000, 8)&0xF;
++
++ //set 1e6e0008[3,0] to 0
++ if (dwValue)
++ {
++ WriteMemoryLongHost(0x1e6e0000, 0, 0xfc600309);
++
++ i=0;
++ do
++ {
++ i++;
++ dwValue = ReadMemoryLongHost(0x1e6e0000,0);
++ }while((1 != dwValue)&& (i<10));
++
++ if (1 != dwValue)
++ {
++ printf("0x1e6e0000 is locked");
++ return VIDEO_UNLOCK_FAIL;
++ }
++ }
++
++ //only clear 1e6e0008[3,0]
++ WriteMemoryLongWithMASKHost(0x1e6e0000, 8, 0, 0xf);
++
++ bClient = 0;
++ if (!bClient)
++ {
++ //To turn on crt, must be the client mode
++ WriteMemoryLongWithMASKHost(SCU_BASE, SCU_HW_TRAPPING_REG, (BE_CLIENT_CHIP << CLIENT_MODE_EN_BIT), CLIENT_MODE_EN_MASK);
++
++ iRet = CRTTest();
++
++ if (iRet)
++ {
++ //trapping to host, the Vsync of CRT can't output and the host doesn't have video sync input
++ WriteMemoryLongWithMASKHost(SCU_BASE, SCU_HW_TRAPPING_REG, (BE_HOST_CHIP << CLIENT_MODE_EN_BIT), CLIENT_MODE_EN_MASK);
++ //restore value
++ WriteMemoryLongHost(0x1e6e0000, 8, ulRestore1);
++ //lock register
++ WriteMemoryLongHost(0x1e6e0000, 0, 0x12345678);
++ return VIDEO_TEST_FAIL;
++ }
++
++ iRet = CapTest();
++
++ if (iRet)
++ {
++ //trapping to host, the Vsync of CRT can't output and the host doesn't have video sync input
++ WriteMemoryLongWithMASKHost(SCU_BASE, SCU_HW_TRAPPING_REG, (BE_HOST_CHIP << CLIENT_MODE_EN_BIT), CLIENT_MODE_EN_MASK);
++ //restore value
++ WriteMemoryLongHost(0x1e6e0000, 8, ulRestore1);
++ //lock register
++ WriteMemoryLongHost(0x1e6e0000, 0, 0x12345678);
++
++ return VIDEO_TEST_FAIL;
++ }
++ //WriteMemoryLongWithMASKHost(SCU_BASE, SCU_HW_TRAPPING_REG, (BE_HOST_CHIP << CLIENT_MODE_EN_BIT), CLIENT_MODE_EN_MASK);
++ }
++ //trapping to host, the Vsync of CRT can't output and the host doesn't have video sync input
++ WriteMemoryLongWithMASKHost(SCU_BASE, SCU_HW_TRAPPING_REG, (BE_HOST_CHIP << CLIENT_MODE_EN_BIT), CLIENT_MODE_EN_MASK);
++ //restore value
++ WriteMemoryLongHost(0x1e6e0000, 8, ulRestore1);
++ //lock register
++ WriteMemoryLongHost(0x1e6e0000, 0, 0x12345678);
++#endif
++
++ return VIDEO_TEST_OK;
++}
++#endif /* CONFIG_SLT */
+diff --git a/board/aspeed/ast2400/videotest.h b/board/aspeed/ast2400/videotest.h
+new file mode 100755
+index 0000000..79b8dd9
+--- /dev/null
++++ b/board/aspeed/ast2400/videotest.h
+@@ -0,0 +1,24 @@
++/*
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++ */
++/* VideoTest.h */
++#ifndef _VIDEOTEST_H_
++#define _VIDEOTEST_H_
++
++#define VIDEO_TEST_OK 0
++#define VIDEO_TEST_FAIL 1
++
++#define VIDEO_UNLOCK_FAIL 1
++#define VIDEO_ENCODE_FAIL 2
++#define VIDEO_DECODE_FAIL 3
++#define CRT_FAIL 4
++
++#endif /* _VIDEOTEST_H_ */
++
+diff --git a/board/aspeed/ast2400/vreg.h b/board/aspeed/ast2400/vreg.h
+new file mode 100755
+index 0000000..9738548
+--- /dev/null
++++ b/board/aspeed/ast2400/vreg.h
+@@ -0,0 +1,845 @@
++/*
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++ */
++#ifndef _VREG_H_
++#define _VREG_H_
++
++/********************************************************/
++/* CRT register */
++/********************************************************/
++#define CRT_BASE_ADDRESS 0x000400
++#define VGA_GRAPH_BASE_ADDRESS 0x600000
++#define VGA_CURSOR_BASE_ADDRESS 0x300000
++#define VGA_OSD_BASE_ADDRESS 0x300000
++#define RGB_565 0x0
++#define RGB_888 0x1
++#define YUV_444 0x2
++#define NO_SUPPORTED_CRT_FMT 0x3
++#define CRT_LOW_THRESHOLD_VALUE 0x12
++#define CRT_HIGH_THRESHOLD_VALUE 0x1E
++
++// AST3000's Registers
++#ifdef Watcom
++#define VIDEOBASE_OFFSET 0x10000
++#else
++#define VIDEOBASE_OFFSET 0x0
++#endif
++
++#define KEY_CONTROL_REG 0x00 + VIDEOBASE_OFFSET
++ #define VIDEO_LOCKED 0
++ #define VIDEO_UNLOCK 1
++
++// Registers for video1 and video2
++#define VIDEO1_ENGINE_SEQUENCE_CONTROL_REG 0x04 + VIDEOBASE_OFFSET
++#define VIDEO2_ENGINE_SEQUENCE_CONTROL_REG 0x104 + VIDEOBASE_OFFSET
++ #define MODE_DETECTION_TRIGGER 0x00000001 //Bit[0] trigger HW auto mode detection
++ #define VIDEO_CAPTURE_TRIGGER 0x00000002 //Bit[1] trigger HW to capture video
++ #define FORCE_HW_IDLE_MASK (1<<2) //Bit[2] Force engine into ready(idle) state
++ #define ENGINE_RESET (0<<2)
++ #define ENGINE_IDLE (1<<2)
++ #define VIDEO_CAPTURE_AUTO_MODE 0x00000008 //Bit[3]
++ #define CAPTURE_FRAME_MODE 0
++ #define CAPTURE_AUTO_MODE 1
++ #define CAPTURE_AUTO_MODE_BIT 3
++ #define CAPTURE_AUTO_MODE_MASK 0x00000008
++ #define VIDEO_CODEC_TRIGGER 0x00000010 //Bit[4] trigger HW to compress or decompress video
++ #define CODEC_TRIGGER_BIT 4
++ #define CODEC_TRIGGER_MASK 0x00000010
++ #define CLEAR_CODEC_TRIGGER 0
++ #define EN_CODEC_TRIGGER 1
++ #define VIDEO_CODEC_AUTO_MODE 0x00000020 //Bit[5]
++ #define CODEC_FRAME_MODE 0
++ #define CODEC_AUTO_MODE 1
++ #define CODEC_AUTO_MODE_BIT 5
++ #define CODEC_AUTO_MODE_MASK 0x00000020
++ #define INSERT_FULL_FRAME_MASK (1<<6) //Bit[6] Insert full frame compression
++ #define INSERT_FULL_FRAME_EN (1<<6)
++ #define INSERT_FULL_FRAME_OFF (0<<6)
++ #define WATCH_DOG_ENABLE 0x00000080 //Bit[7] Video Enable watch dog for mode change detection
++ #define WATCH_DOG_ENABLE_BIT 7
++ #define WATCH_DOG_OFF 0
++ #define WATCH_DOG_EN 1
++ #define WATCH_DOG_EN_MASK 0x00000080
++ #define VIDEO_CRT_SELECTION 0x00000100 //Bit[8]
++ #define CRT1 0
++ #define CRT2 1
++ #define ANTI_TEARING_ENABLE 0x00000200 //Bit[9] Anti-tearing mode enable for decoding
++ #define ANTI_TEARING_EN 1
++ #define STREAM_DATA_MODE 0x00000400 //Bit[11:10] Buffer and Stream Data type
++ #define STREAM_DATA_MODE_BIT 10
++ #define STREAM_DATA_MODE_MASK 0x00000C00
++ #define YUV444_MODE 0
++ #define YUV420_MODE 1
++ #define YUV420_MODE_WITH_AST2000 2 //AST2000 compatible
++ #define VIDEO_CAPTURE_READY 0x00010000 //Bit[16] Video capture ready status read back(read only)
++ #define CAPTURE_READY_MASK 0x00010000
++ #define HW_BUSY 0
++ #define HW_IDLE 1
++ #define VIDEO_CODEC_READY 0x00040000 //Bit[18] Video codec ready status read back(read only)
++ #define CODEC_READY_MASK 0x00040000
++ //#define HW_BUSY 0
++ //#define HW_IDLE 1
++
++#define VIDEO1_CONTROL_REG 0x08 + VIDEOBASE_OFFSET
++#define VIDEO2_CONTROL_REG 0x108 + VIDEOBASE_OFFSET
++ #define VIDEO_HSYNC_POLARITY 0x00000001 //Bit[0] Video source hsync polarity
++ #define VIDEO_HSYNC_POLARITY_BIT 0
++ #define NO_INVERSE_POL 0
++ #define INVERSE_POL 1
++ #define VIDEO_VSYNC_POLARITY 0x00000002 //Bit[1] Video source vsync polarity
++ #define VIDEO_VSYNC_POLARITY_BIT 1
++ //Setting defination the same as VIDEO_HSYNC_POLARITY
++ #define VIDEO_EXTERNAL_SOURCE 0x00000004 //Bit[2] Video external source
++ #define EXTERNAL_SOURCE_BIT 2
++ #define INTERNAL_VGA_SOURCE 0
++ #define EXTERNAL_VGA_SOURCE 1
++ #define EXTERNAL_SOURCE_MASK 0x00000004
++ #define VIDEO_ANALONG_EXTERNAL_SOURCE 0x00000008 //Bit[3] Video Analog external source
++ #define ANALONG_EXTERNAL_SOURCE_BIT 3
++ #define DVI_SOURCE 0
++ #define ANALOG_RGB_SOURCE 1
++ #define VIDEO_INTERNAL_TIMING_GEN 0x00000010 //Bit[4] Video Use internal timing generator
++ #define INTERNAL_TIMING_GEN_BIT 4
++ #define EXTERNAL_DE_SIGNAL 0 //DVI only
++ #define VR0C_VR10_DE_SINGAL 1 //use VR0C and VR10 for generate VDE signal
++ /****** Video2 Only from DAC ******/
++ #define VIDEO1_CAPTURE_FROM 0x00000020 //Bit[5] Video1 capture data direct from VGA frame buffer(internal VGA only)
++ #define FROM_DAC_PORT 0
++ #define FROM_FRAME_BUFFER 1
++ #define WRITE_DATA_FORMAT 0x00000040 //Bit[7:6] Write data format
++ #define WRITE_DATA_FORMAT_BIT 6
++ #define WRTIE_DATA_FORMAT_MASK 0x000000C0
++ #define CCIR601_2_YUV_FORMAT 0
++ #define FULL_YUV_FORMAT 1
++ #define RGB_FORMAT 2
++ #define VGA_CURSOR_DISABLE 0x00000100 //Bit[8] External video port slection
++ #define VGA_CURSOR_NORMAL 0
++ #define VGA_CURSOR_OFF 1
++ #define VIDEO_CAPTURE_LINEAR_MODE 0x00000200 //Bit[9] VIDEO_CAPTURE_LINEAR_MODE
++ #define LINEAR_MODE 0
++ #define TILE_MODE 1
++ #define VIDEO_CLOCK_DELAY 0x00000400 //Bit[11:10] Video clock delay control
++ #define VIDEO_CLOCK_DELAY_BIT 10
++ #define VIDEO_CLOCK_DELAY_MASK 0x00000C00
++ #define DELAY_0_NS 0
++ #define DELAY_1_NS 1
++ #define INV_AND_DELAY_0_NS 2
++ #define INV_AND_DELAY_1_NS 3
++ #define VIDEO_CCIR656_SOURCE_MODE 0x00001000 //Bit[12] Video CCIR656 source mode
++ #define RGB_SOURCE_MODE 0
++ #define CCIR656_SOURCE_MODE 1
++ #define SOURCE_PORT_CLOCK_MODE 0x00002000 //Bit[13] Video Source port clock mode
++ #define SINGLE_EDGE_MODE 0
++ #define DUAL_EDGE_MODE 1
++ #define EXTERNAL_PORT_SELECTION 0x00004000 //Bit[14] External video port slection
++ #define VIDEO_PORT_A 0
++ #define VIDEO_PORT_B 1
++ #define VIDEO_CAPTURE_FRAME_RATE 0x00010000 //Bit[23:16] Video capture frame rate control
++ #define VIDEO_CAPTURE_FRAME_RATE_BIT 16
++ #define VIDEO_CAPTURE_FRAME_RATE_MASK 0x00FF0000 //Maximum frame rate = XX * SourceFPS / 60
++
++#define VIDEO1_TIMEING_GEN_HOR_REG 0x0C + VIDEOBASE_OFFSET
++#define VIDEO2_TIMEING_GEN_HOR_REG 0x10C + VIDEOBASE_OFFSET
++ #define VIDEO_HDE_END 0x00000000 //Bit[12:0] Video HDE End timing generator
++ #define VIDEO_HDE_END_BIT 0 //Number of pixels from rising edge of Hsync for first active pixel
++ #define VIDEO_HDE_END_MASK 0x00001FFF
++ #define VIDEO_HDE_START 0x00010000 //Bit[28:16] Video HDE Start timing generator
++ #define VIDEO_HDE_START_BIT 16 //Number of pixels from rising edge of Hsync for last active pixel
++ #define VIDEO_HDE_START_MASK 0x1FFF0000
++ #define FRAME_RATE_OFF 0
++
++#define VIDEO1_TIMEING_GEN_V_REG 0x10 + VIDEOBASE_OFFSET
++#define VIDEO2_TIMEING_GEN_V_REG 0x110 + VIDEOBASE_OFFSET
++ #define VIDEO_VDE_END 0x00000001 //Bit[11:0] Video VDE End timing generator
++ #define VIDEO_VDE_END_BIT 0 //Number of pixels from rising edge of Vsync for first active pixel
++ #define VIDEO_VDE_END_MASK 0x00000FFF
++ #define VIDEO_VDE_START 0x00010000 //Bit[27:16] Video VDE Start timing generator
++ #define VIDEO_VDE_START_BIT 16 //Number of pixels from rising edge of Vsync for last active pixel
++ #define VIDEO_VDE_START_MASK 0x0FFF0000
++
++#define VIDEO1_SCALE_FACTOR_REG 0x14 + VIDEOBASE_OFFSET
++#define VIDEO2_SCALE_FACTOR_REG 0x114 + VIDEOBASE_OFFSET
++ #define HOR_SCALING_FACTOR 0x00000001 //Bit[15:0] Video Horizontal scaling factor
++ #define HOR_SCALING_FACTOR_BIT 0 //The formula=4096/(Horizontal scaling facotr)
++ #define HOR_SCALING_FACTOR_MASK 0x0000FFFF
++ #define VER_SCALING_FACTOR 0x00000000 //Bit[31:16] Video Vertical scaling factor
++ #define VER_SCALING_FACTOR_BIT 16 //The formula=4096/(Vertical scaling facotr)
++ #define VER_SCALING_FACTOR_MASK 0xFFFF0000
++
++#define VIDEO1_SCALE_FACTOR_PARAMETER0_REG 0x18 + VIDEOBASE_OFFSET //Scaling Parameters F00, F01, F02, F03
++#define VIDEO2_SCALE_FACTOR_PARAMETER0_REG 0x118 + VIDEOBASE_OFFSET
++
++#define VIDEO1_SCALE_FACTOR_PARAMETER1_REG 0x1C + VIDEOBASE_OFFSET //Scaling Parameters F10, F11, F12, F13
++#define VIDEO2_SCALE_FACTOR_PARAMETER1_REG 0x11C + VIDEOBASE_OFFSET
++
++#define VIDEO1_SCALE_FACTOR_PARAMETER2_REG 0x20 + VIDEOBASE_OFFSET //Scaling Parameters F20, F21, F22, F23
++#define VIDEO2_SCALE_FACTOR_PARAMETER2_REG 0x120 + VIDEOBASE_OFFSET
++
++#define VIDEO1_SCALE_FACTOR_PARAMETER3_REG 0x24 + VIDEOBASE_OFFSET //Scaling Parameters F30, F31, F32, F33
++#define VIDEO2_SCALE_FACTOR_PARAMETER3_REG 0x124 + VIDEOBASE_OFFSET
++
++#define VIDEO1_BCD_CONTROL_REG 0x2C + VIDEOBASE_OFFSET
++#define VIDEO2_BCD_CONTROL_REG 0x12C + VIDEOBASE_OFFSET
++ #define BCD_ENABLE 0x00000001 //Bit[0] Enable block change detection(BCD)
++ #define BCD_ENABLE_BIT 0
++ #define BCD_ENABLE_MASK 0x00000001
++ #define BCD_TOLERANCE 0x00010000 //Bit[23:16]
++ #define BCD_TOLERANCE_BIT 16 //flag as changed block when the video data difference greater
++ #define BCD_TOLERANCE_MASK 0x00FF0000
++
++#define VIDEO1_CAPTURE_WINDOWS_REG 0x30 + VIDEOBASE_OFFSET
++#define VIDEO2_CAPTURE_WINDOWS_REG 0x130 + VIDEOBASE_OFFSET
++ #define CAPTURE_VER_LINE 0x00000001 //Bit[10:0] Video compression vertical line total
++ #define CAPTURE_VER_LINE_BIT 0
++ #define CAPTURE_VER_LINE_MASK 0x000007FF
++ #define CAPTURE_HOR_PIXEL 0x00010000 //Bit[26:16] Video compression vertical line total
++ #define CAPTURE_HOR_PIXEL_BIT 16
++ #define CAPTURE_HOR_PIXEL_MASK 0x07FF0000
++
++#define VIDEO1_COMPRESS_WINDOWS_REG 0x34 + VIDEOBASE_OFFSET
++#define VIDEO2_COMPRESS_WINDOWS_REG 0x134 + VIDEOBASE_OFFSET
++ #define COMPRESS_VER_LINE 0x00000001 //Bit[10:0] Video compression vertical line total
++ #define COMPRESS_VER_LINE_BIT 0
++ #define COMPRESS_VER_LINE_MASK 0x000007FF
++ #define COMPRESS_HOR_PIXEL 0x00010000 //Bit[26:16] Video compression vertical line total
++ #define COMPRESS_HOR_PIXEL_BIT 16
++ #define COMPRESS_HOR_PIXEL_MASK 0x07FF0000
++
++#define VIDEO1_COMPRESS_BUF_PROCESS_OFFSET_REG 0x38
++#define VIDEO2_COMPRESS_BUF_PROCESS_OFFSET_REG 0x138
++ #define COMPRESS_BUF_PROCESS_OFFSET_ALIGN 127 //128 byte alignment
++ #define COMPRESS_BUF_PROCESS_OFFSET_MASK 0xFFFFFF
++
++#define VIDEO1_DECOMPRESS_BUF_PROCESS_OFFSET_REG 0x38
++#define VIDEO2_DECOMPRESS_BUF_PROCESS_OFFSET_REG 0x138
++ #define DECOMPRESS_BUF_PROCESS_OFFSET_ALIGN 127 //128 byte alignment
++ #define DECOMPRESS_BUF_PROCESS_OFFSET_MASK 0xFFFFFF
++
++
++//For Compression
++#define VIDEO1_COMPRESS_BUF_READ_OFFSET_REG 0x3C + VIDEOBASE_OFFSET //For stream mode
++#define VIDEO2_COMPRESS_BUF_READ_OFFSET_REG 0x13C + VIDEOBASE_OFFSET
++ #define COMPRESS_BUF_READ_OFFSET_ALIGN 127 //128 byte alignment
++ #define COMPRESS_BUF_READ_OFFSET_MASK 0x00FFFFFF
++//For Decompression
++#define VIDEO1_DECOMPRESS_BUF_WRITE_OFFSET_REG 0x3C + VIDEOBASE_OFFSET //For stream mode
++#define VIDEO2_DECOMPRESS_BUF_WRITE_OFFSET_REG 0x13C + VIDEOBASE_OFFSET
++ #define DECOMPRESS_BUF_WRITE_OFFSET_ALIGN 127 //128 byte alignment
++ #define DECOMPRESS_BUF_WRITE_OFFSET_MASK 0x00FFFFFF
++
++#define VIDEO1_CRC_BUF_ADDR_REG 0x40 + VIDEOBASE_OFFSET
++#define VIDEO2_CRC_BUF_ADDR_REG 0x140 + VIDEOBASE_OFFSET
++ #define CRC_BUF_ADDR_ALIGN 7 //8 byte alignment
++ #define CRC_BUF_ADDR_MASK 0x0FFFFFFF
++
++#define VIDEO1_BUF_1_ADDR_REG 0x44 + VIDEOBASE_OFFSET //For Source Buffer in frame mode
++#define VIDEO2_BUF_1_ADDR_REG 0x144 + VIDEOBASE_OFFSET
++ #define BUF_1_ADDR_ALIGN 255 //256 byte alignment
++ #define BUF_1_ADDR_MASK 0x1FFFFFFF
++
++#define VIDEO1_BUF_LINE_OFFSET_REG 0x48 + VIDEOBASE_OFFSET //Must set both in Frame/Stream mode
++#define VIDEO2_BUF_LINE_OFFSET_REG 0x148 + VIDEOBASE_OFFSET
++ #define BUF_LINE_OFFSET_ALIGN 7 //8 byte alignment
++ #define BUF_LINE_OFFSET_MASK 0x00003FFF
++
++#define VIDEO1_BUF_2_ADDR_REG 0x4C + VIDEOBASE_OFFSET //For BCD Buffer in frame mode
++#define VIDEO2_BUF_2_ADDR_REG 0x14C + VIDEOBASE_OFFSET
++ #define BUF_2_ADDR_ALIGN 255 //256 byte alignment
++ #define BUF_2_ADDR_MASK 0x1FFFFFFF
++
++#define VIDEO1_FLAG_BUF_ADDR_REG 0x50 + VIDEOBASE_OFFSET //For block change flag buffer
++#define VIDEO2_FLAG_BUF_ADDR_REG 0x150 + VIDEOBASE_OFFSET
++ #define FLAG_BUF_ADDR_ALIGN 7 //8 byte alignment
++ #define FLAG_BUF_ADDR_MASK 0x1FFFFFFF
++
++#define VIDEO1_COMPRESS_BUF_ADDR_REG 0x54 + VIDEOBASE_OFFSET //For stream mode
++#define VIDEO2_COMPRESS_BUF_ADDR_REG 0x154 + VIDEOBASE_OFFSET
++ #define COMPRESS_BUF_ADDR_ALIGN 127 //128 byte alignment
++ #define COMPRESS_BUF_ADDR_MASK 0x1FFFFFFF
++
++#define VIDEO1_STREAM_BUF_SIZE 0x58 + VIDEOBASE_OFFSET //For stream mode
++#define VIDEO2_STREAM_BUF_SIZE 0x158 + VIDEOBASE_OFFSET
++ #define STREAM_PACKET_SIZE 0x00000001
++ #define STREAM_PACKET_SIZE_BIT 0
++ #define STREAM_PACKET_SIZE_MASK 0x00000007
++ #define PACKET_SIZE_1KB 0
++ #define PACKET_SIZE_2KB 1
++ #define PACKET_SIZE_4KB 2
++ #define PACKET_SIZE_8KB 3
++ #define PACKET_SIZE_16KB 4
++ #define PACKET_SIZE_32KB 5
++ #define PACKET_SIZE_64KB 6
++ #define PACKET_SIZE_128KB 7
++ #define RING_BUF_PACKET_NUM 0x00000008
++ #define RING_BUF_PACKET_NUM_BIT 3
++ #define RING_BUF_PACKET_NUM_MASK 0x00000018
++ #define PACKETS_4 0
++ #define PACKETS_8 1
++ #define PACKETS_16 2
++ #define PACKETS_32 3
++ #define SKIP_HIGH_MB_THRES 0x00010000 //Bit[22:16] Skip high quality macro block threshold
++ #define SKIP_HIGH_MB_THRES_BIT 16
++ #define SKIP_HIGH_MB_THRES_MASK 0x007F0000
++ #define SKIP_TEST_MODE 0x00800000 //Bit[24:23] Skip test mode
++ #define SKIP_TEST_MODE_BIT 23
++ #define SKIP_TEST_MODE_MASK 0x01800000
++ #define YUV_TEST 2 //recommend
++
++#define VIDEO1_BUF_CODEC_OFFSET_READ 0x5C + VIDEOBASE_OFFSET //For stream mode,
++#define VIDEO2_BUF_CODEC_OFFSET_READ 0x15C + VIDEOBASE_OFFSET //Video stream buffer offset read back(HW)
++ #define BUF_CODEC_OFFSET_ALIGN 255 //256 byte alignment
++ #define BUF_CODEC_OFFSET_MASK 0x00FFFFFF
++
++#define VIDEO1_COMPRESS_CONTROL_REG 0x60 + VIDEOBASE_OFFSET
++#define VIDEO2_COMPRESS_CONTROL_REG 0x160 + VIDEOBASE_OFFSET
++ #define JPEG_ONLY_ENCODE 0x00000001 //Bit[0] JPEG only encoding
++ #define JPEG_ONLY_BIT 0
++ #define JPEG_MIX_MODE 0 //Enable JPEG/VQ mix mode encoding
++ #define JPEG_ONLY_MODE 1 //JPEG encoding mode only
++ #define VQ_4_COLOR_ENCODE 0x00000002 //Bit[1] Enable 4 color VQ encoding
++ #define VQ_4_COLOR_BIT 1
++ #define VQ_1_2_COLOR_MODE 0 //1 and 2 color mode VQ encoding
++ #define VQ_4_COLOR_MODE 1 //1, 2 and 4 color VQ encoding
++ #define QUALITY_CODEC_SETTING 0x00000004 //Bit[2] High and best video quality codec mode setting
++ #define QUALITY_CODEC_SETTING_BIT 2
++ #define JPEG_CODEC_MODE 0 //not supported in best video quality mode
++ #define QUANTI_CODEC_MODE 1
++ #define JPEG_DUAL_QUALITY_EN 0x00000008 //Bit[3] JPEG dual quality mode
++ #define EN_JPEG_DUAL_QUALITY 1 //enable(only for normal video quality mode)
++ #define BEST_QUALITY_EN 0x00000010 //Bit[4] Best quality video mode enable
++ #define BEST_QUALITY_EN_BIT 4
++ #define EN_BEST_QUALITY 1 //enable(only for quantization codec mode)
++ #define RC4_CRYPT_EN 0x00000020 //Bit[5] Enable RC4 encryption/decryption
++ #define RC4_CRYPT_EN_BIT 5
++ #define RC4_CRYPT_EN_MASK 0x00000020
++ #define RC4_CRYPT_ON 1 //enable
++ #define NORMAL_QUANTI_CHROMI_TABLE 0x00000040 //Bit[10:6] Normal video quality mode JPEG DCT chromi quantination table
++ #define NORMAL_QUANTI_CHROMI_TABLE_BIT 6
++ #define NORMAL_QUANTI_CHROMI_TABLE_MASK 0x000007C0
++ #define NORMAL_QUANTI_LUMI_TABLE 0x00000800 //Bit[15:11] Normal video quality mode JPEG DCT lumi quantination table
++ #define NORMAL_QUANTI_LUMI_TABLE_BIT 11
++ #define NORMAL_QUANTI_LUMI_TABLE_MASK 0x0000F800
++ #define HIGH_QUALITY_EN 0x00010000 //Bit[16] High video quality mode enable
++ #define HIGH_QUALITY_EN_BIT 16
++ #define EN_HIGH_QUALITY 1 //Enable
++ #define UV_CIR656_FORMAT 0x00080000 //Bit[19] UV fromat
++ #define UV_CIR656_FORMAT_BIT 19
++ #define USE_UV_CIR656 1 //recommand
++ #define HUFFMAN_TABLE_SELECT 0x00100000 //Bit[20] JPEG Huffman table combination
++ #define DUAL_TABLE 0 //Dual Y, UV table
++ #define SINGLE_TABLE 1 //Single Y table
++ #define SINGLE_UV_TABLE 0x00200000 //1x: Single UV table
++ #define HIGH_QUANTI_CHROMI_TABLE 0x00400000 //Bit[26:22] High quality JPEG DCT chromi quantization table
++ #define HIGH_QUANTI_CHROMI_TABLE_BIT 22
++ #define HIGH_QUANTI_CHROMI_TABLE_MASK 0x07C00000
++ #define HIGH_DEQUANTI_VALUE 0x00400000 //Bit[26:22] High quality de-quantization value
++ #define HIGH_DEQUANTI_VALUE_BIT 22
++ #define HIGH_DEQUANTI_VALUE_MASK 0x07C00000
++ #define HIGH_QUANTI_LUMI_TABLE 0x08000000 //Bit[31:27] High quality JPEG DCT lumi quantization table
++ #define HIGH_QUANTI_LUMI_TABLE_BIT 27
++ #define HIGH_QUANTI_LUMI_TABLE_MASK 0xF8000000
++ #define BEST_DEQUANTI_VALUE 0x08000000 //Bit[31:27] Best quality de-quantization value
++ #define BEST_DEQUANTI_VALUE_BIT 27
++ #define BEST_DEQUANTI_VALUE_MASK 0xF8000000
++
++
++#define VIDEO1_QUANTI_TABLE_LOW_REG 0x64 + VIDEOBASE_OFFSET //Match with 0x60 Bit[10:6], Bit[15:11]
++#define VIDEO2_QUANTI_TABLE_LOW_REG 0x164 + VIDEOBASE_OFFSET
++ #define QUANTI_CHROMI_TABLE_LOW 0x00000001 //Bit[4:0] Normal video low quality block chromi quantization table
++ #define QUANTI_CHROMI_TABLE_LOW_BIT 0
++ #define QUANTI_CHROMI_TABLE_LOW_MASK 0x0000001F
++ #define QUANTI_LUMI_TABLE_LOW 0x00000020 //Bit[9:5] Normal video low quality block lumi quantization table
++ #define QUANTI_LUMI_TABLE_LOW_BIT 5
++ #define QUANTI_LUMI_TABLE_LOW_MASK 0x000003E0
++
++#define VIDEO1_QUANTI_VALUE_REG 0x68 + VIDEOBASE_OFFSET //Match with 0x60 Bit[26:22],Bit[31:27]
++#define VIDEO2_QUANTI_VALUE_REG 0x168 + VIDEOBASE_OFFSET
++ #define HIGH_QUANTI_VALUE 0x00000001 //Bit[14:0] High quality quantization value. Format is 1.14
++ #define HIGH_QUANTI_VALUE_BIT 0
++ #define HIGH_QUANTI_VALUE_MASK 0x00007FFF
++ #define BEST_QUANTI_VALUE 0x00010000 //Bit[30:16] Best quality quantization value. Format is 1.14
++ #define BEST_QUANTI_VALUE_BIT 16
++ #define BEST_QUANTI_VALUE_MASK 0x7FFF0000
++
++#define VIDEO1_BSD_PARA_REG 0x6C + VIDEOBASE_OFFSET //Video BSD Parameters Register
++#define VIDEO2_BSD_PARA_REG 0x16C + VIDEOBASE_OFFSET
++ #define BSD_HIGH_THRES 0x00000001 //Bit[7:0] Block sharpness detection high threshold
++ #define BSD_HIGH_THRES_BIT 0
++ #define BSD_HIGH_THRES_MASK 0x000000FF
++ #define BSD_LOW_THRES 0x00000100 //Bit[15:8] Block shaprpness detection low threshold
++ #define BSD_LOW_THRES_BIT 8
++ #define BSD_LOW_THRES_MASK 0x0000FF00
++ #define BSD_HIGH_COUNTS 0x00010000 //Bit[21:16] Block sharpness detection high counts threshold
++ #define BSD_HIGH_COUNTS_BIT 16
++ #define BSD_HIGH_COUNTS_MASK 0x003F0000
++ #define BSD_LOW_COUNTS 0x00400000 //Bit[27:22] Block sharpness detection low counts threshold
++ #define BSD_LOW_COUNTS_BIT 22
++ #define BSD_LOW_COUNTS_MASK 0x0FC00000
++
++#define VIDEO1_COMPRESS_FRAME_SIZE_REG 0x70 + VIDEOBASE_OFFSET
++#define VIDEO2_COMPRESS_FRAME_SIZE_REG 0x170 + VIDEOBASE_OFFSET
++ #define COMPRESS_FRAME_SIZE_READ 0x00000001 //Bit[19:0] Video compression frame size read back(number of DW)
++ #define COMPRESS_FRAME_SIZE_READ_BIT 0
++ #define COMPRESS_FRAME_SIZE_READ_MASK 0x003FFFFF
++
++#define VIDEO1_COMPRESS_BLOCK_COUNT_REG 0x74 + VIDEOBASE_OFFSET
++#define VIDEO2_COMPRESS_BLOCK_COUNT_REG 0x174 + VIDEOBASE_OFFSET
++ #define PROCESS_BLOCK_COUNT_READ_BIT 0
++ #define PROCESS_BLOCK_COUNT_READ_MASK 0x00003FFF //Bit[13:0] Video processed total block counter read back(number of blocks)
++ #define COMPRESS_BLOCK_COUNT_READ_BIT 16
++ #define COMPRESS_BLOCK_COUNT_READ_MASK 0xFFFF0000 //Bit[29:16] Video processed total block counter read back(number of blocks)
++
++#define VIDEO1_COMPRESS_FRAME_END_READ 0x78 + VIDEOBASE_OFFSET //Video compression stream frame end pointer
++#define VIDEO2_COMPRESS_FRAME_END_READ 0x178 + VIDEOBASE_OFFSET
++ #define COMPRESS_FRAME_END_READ_ALIGN 7
++ #define COMPRESS_FRAME_END_READ_MASK 0x00FFFFFF
++
++#define VIDEO1_COMPRESS_FRAME_COUNT_READ 0x7C + VIDEOBASE_OFFSET
++#define VIDEO2_COMPRESS_FRAME_COUNT_READ 0x17C + VIDEOBASE_OFFSET
++ #define COMPRESS_FRAME_COUNT_READ 0x00000001 //Bit[15:0] Video compression frame count read back(number of frame)
++ #define COMPRESS_FRAME_COUNT_READ_BIT 0
++ #define COMPRESS_FRAME_COUNT_READ_MASK 0xFFFFFFFF
++
++#define VIDEO1_USER_DEFINE_HEADER 0x80 + VIDEOBASE_OFFSET
++#define VIDEO2_USER_DEFINE_HEADER 0x180 + VIDEOBASE_OFFSET
++ #define USER_DEFINE_HEADER 0x00000001 //Bit[15:0] Video user defined header parameter
++ #define USER_DEFINE_HEADER_BIT 0
++ #define USER_DEFINE_HEADER_MASK 0x0000FFFF
++
++#define VIDE1_MODE_DETECTION_EDGE_H_REG 0x90 + VIDEOBASE_OFFSET
++#define VIDE2_MODE_DETECTION_EDGE_H_REG 0x190 + VIDEOBASE_OFFSET
++ #define LEFT_EDGE_LOCATION 0x00000001 //Bit[11:0] Video source left edge location from sync rising edge
++ #define LEFT_EDGE_LOCATION_BIT 0
++ #define LEFT_EDGE_LOCATION_MASK 0x00000FFF
++ #define NO_VER_SYNC (1 << 12) //Bit[12] No Vertical sync detected
++ #define NO_HOR_SYNC (1 << 13) //Bit[13] No horizontal sync detected
++ #define NO_ACTIVE_DISP (1 << 14) //Bit[14] No active display detected
++ #define NO_DISP_CLOCK (1 << 15)
++ #define RIGHT_EDGE_LOCATION 0x00010000 //Bit[27:16] Video source right edge location from sync rising edge
++ #define RIGHT_EDGE_LOCATION_BIT 16
++ #define RIGHT_EDGE_LOCATION_MASK 0x0FFF0000
++
++#define VIDE1_MODE_DETECTION_EDGE_V_REG 0x94 + VIDEOBASE_OFFSET
++#define VIDE2_MODE_DETECTION_EDGE_V_REG 0x194 + VIDEOBASE_OFFSET
++ #define TOP_EDGE_LOCATION 0x00000001 //Bit[11:0] Video source top edge location from sync rising edge
++ #define TOP_EDGE_LOCATION_BIT 0
++ #define TOP_EDGE_LOCATION_MASK 0x00000FFF
++ #define BOTTOM_EDGE_LOCATION 0x00010000 //Bit[27:16] Video source bottom edge location from sync rising edge
++ #define BOTTOM_EDGE_LOCATION_BIT 16
++ #define BOTTOM_EDGE_LOCATION_MASK 0x0FFF0000
++
++#define VIDEO1_MODE_DETECTION_STATUS_READ_REG 0x98 + VIDEOBASE_OFFSET
++#define VIDEO2_MODE_DETECTION_STATUS_READ_REG 0x198 + VIDEOBASE_OFFSET
++ #define MODE_DETECTION_HOR_TIME_READ 0x00000001 //Bit[11:0] Mode detection Horizontal time read back (read only)
++ #define MODE_DETECTION_HOR_TIME_READ_BIT 0
++ #define MODE_DETECTION_HOR_TIME_READ_MASK 0x00000FFF
++ #define ANALONG_DIGITAL_READ 0x00001000 //Bit[12] Auto detection for external analog or digital source read back
++ #define ANALONG_DIGITAL_READ_BIT 12
++ #define DVI_SIGNAL 0
++ #define ADC_SIGNAL 1
++ #define MODE_DETECTION_HOR_STABLE_READ 0x00002000 //Bit[13] Mode detection horizontal stable read back
++ #define HOR_STABLE 1
++ #define MODE_DETECTION_VER_STABLE_READ 0x00004000 //Bit[14] Mode detection vertical stable read back
++ #define VER_STABLE 1
++ #define OUT_LOCK_READ 0x00008000 //Bit[15] Mode detection out of lock read back
++ #define SIGNAL_OUT_LOCK 1
++ #define MODE_DETECTION_VER_LINE_READ 0x00010000 //Bit[27:16] Mode detection Vertical lines read back
++ #define MODE_DETECTION_VER_LINE_READ_BIT 16
++ #define MODE_DETECTION_VER_LINE_READ_MASK 0x0FFF0000
++ #define VSYNC_POLARITY_READ 0x10000000 //Bit[28] Vsync polarity read back
++ #define HSYNC_POLARITY_READ 0x20000000 //Bit[29] Hsync polarity read back
++ #define MODE_DETECTION_VSYNC_READY 0x40000000 //Bit[30] Mode detection Vsync ready
++ #define MODE_DETECTION_HSYNC_READY 0x80000000 //Bit[31] Mode detection Hsync ready
++
++/****** VIDEO MEMAGER SETTING ******/
++#define VIDEOM_ENGINE_SEQUENCE_CONTROL_REG 0x204 + VIDEOBASE_OFFSET
++ #define VIDEOM_CAPTURE_TRIGGER 0x00000002 //Bit[1] trigger HW to capture video
++ #define VIDEOM_AUTO_MODE 0x00000008 //Bit[3]
++ #define DISABLE_AUTO_MODE 0
++ #define AUTO_COMPRESS 1
++ #define VIDEOM_CODEC_TRIGGER 0x00000010 //Bit[4] trigger HW to compress or decompress video
++ #define VIDEOM_SOURCE_SELECTION 0x00000100 //Bit[8]
++ #define VIDEO1 0
++ #define VIDEO2 1
++ //#define STREAM_DATA_MODE 0x00000400 //Bit[11:10] Buffer and Stream Data type
++ // #define STREAM_DATA_MODE_BIT 10
++ // #define STREAM_DATA_MODE_MASK 0x00000C00
++ // #define YUV444_MODE 0
++ // #define YUV420_MODE 1
++ // #define YUV420_MODE_WITH_AST2000 2 //AST2000 compatible
++ #define VIDEOM_CAPTURE_READY 0x00010000 //Bit[16] Video capture ready status read back(read only)
++ //#define HW_BUSY 0
++ //#define HW_IDLE 1
++ #define VIDEOM_CODEC_READY 0x00040000 //Bit[18] Video codec ready status read back(read only)
++ //#define HW_BUSY 0
++ //#define HW_IDLE 1
++
++#define VIDEOM_SCALE_FACTOR_REG 0x214 + VIDEOBASE_OFFSET
++// #define HOR_SCALING_FACTOR 0x00000001 //Bit[15:0] Video Horizontal scaling factor
++// #define HOR_SCALING_FACTOR_BIT 0 //The formula=4096/(Horizontal scaling facotr)
++// #define HOR_SCALING_FACTOR_MASK 0x0000FFFF
++// #define VER_SCALING_FACTOR 0x00000000 //Bit[31:16] Video Vertical scaling factor
++// #define VER_SCALING_FACTOR_BIT 16 //The formula=4096/(Vertical scaling facotr)
++// #define VER_SCALING_FACTOR_MASK 0xFFFF0000
++
++#define VIDEOM_SCALE_FACTOR_PARAMETER0_REG 0x218 + VIDEOBASE_OFFSET //Scaling Parameters F00, F01, F02, F03
++
++#define VIDEOM_SCALE_FACTOR_PARAMETER1_REG 0x21C + VIDEOBASE_OFFSET //Scaling Parameters F10, F11, F12, F13
++
++#define VIDEOM_SCALE_FACTOR_PARAMETER2_REG 0x220 + VIDEOBASE_OFFSET //Scaling Parameters F20, F21, F22, F23
++
++#define VIDEOM_SCALE_FACTOR_PARAMETER3_REG 0x224 + VIDEOBASE_OFFSET //Scaling Parameters F30, F31, F32, F33
++
++#define VIDEOM_BCD_CONTROL_REG 0x22C + VIDEOBASE_OFFSET
++ //#define BCD_ENABLE 0x00000001 //Bit[0] Enable block change detection(BCD)
++ //#define BCD_TOLERANCE 0x00010000 //Bit[23:16]
++ // #define BCD_TOLERANCE_BIT 16 //flag as changed block when the video data difference greater
++ // #define BCD_TOLERANCE_MASK 0x00FF0000
++
++#define VIDEOM_CAPTURE_WINDOWS_REG 0x230 + VIDEOBASE_OFFSET
++ //#define RC4_TABLE_ADDR_ALIGN 7 //8 byte alignment
++ //#define RC4_TABLE_ADDR_MASK 0x0FFFFFFF
++
++#define VIDEOM_COMPRESS_WINDOWS_REG 0x234 + VIDEOBASE_OFFSET
++ //#define COMPRESS_VER_LINE 0x00000001 //Bit[12:0] Video compression vertical line total
++ //#define COMPRESS_VER_LINE_BIT 0
++ //#define COMPRESS_VER_LINE_MASK 0x00001FFF
++ //#define COMPRESS_HOR_PIXEL 0x00010000 //Bit[12:0] Video compression vertical line total
++ //#define COMPRESS_HOR_PIXEL_BIT 16
++ //#define COMPRESS_HOR_PIXEL_MASK 0x1FFF0000
++
++#define VIDEOM_COMPRESS_BUF_PROCESS_OFFSET_REG 0x238
++ //#define COMPRESS_BUF_PROCESS_OFFSET_ALIGN 127 //128 byte alignment
++ //#define COMPRESS_BUF_PROCESS_OFFSET_MASK 0x3FFFFF
++
++
++//For Compression
++#define VIDEOM_COMPRESS_BUF_READ_OFFSET_REG 0x23C + VIDEOBASE_OFFSET //For stream mode
++ //#define COMPRESS_BUF_READ_OFFSET_ALIGN 127 //128 byte alignment
++ //#define COMPRESS_BUF_READ_OFFSET_MASK 0x003FFFFF
++//For Decompression
++#define VIDEOM_DECOMPRESS_BUF_WRITE_OFFSET_REG 0x23C + VIDEOBASE_OFFSET //For stream mode
++ //#define DECOMPRESS_BUF_WRITE_OFFSET_ALIGN 127 //128 byte alignment
++ //#define DECOMPRESS_BUF_WRITE_OFFSET_MASK 0x003FFFFF
++
++#define VIDEOM_BUF_1_ADDR_REG 0x244 + VIDEOBASE_OFFSET //For Source Buffer in frame mode
++ //#define BUF_1_ADDR_ALIGN 255 //256 byte alignment
++ //#define BUF_1_ADDR_MASK 0x0FFFFFFF
++
++#define VIDEOM_BUF_LINE_OFFSET_REG 0x248 + VIDEOBASE_OFFSET //Must set both in Frame/Stream mode
++ //#define BUF_LINE_OFFSET_ALIGN 7 //8 byte alignment
++ //#define BUF_LINE_OFFSET_MASK 0x00003FFF
++
++#define VIDEOM_BUF_2_ADDR_REG 0x24C + VIDEOBASE_OFFSET //For BCD Buffer in frame mode
++ //#define BUF_2_ADDR_ALIGN 255 //256 byte alignment
++ //#define BUF_2_ADDR_MASK 0x0FFFFFFF
++
++#define VIDEOM_FLAG_BUF_ADDR_REG 0x250 + VIDEOBASE_OFFSET //For block change flag buffer
++ //#define FLAG_BUF_ADDR_ALIGN 7 //8 byte alignment
++ //#define FLAG_BUF_ADDR_MASK 0x0FFFFFFF
++
++#define VIDEOM_COMPRESS_BUF_ADDR_REG 0x254 + VIDEOBASE_OFFSET //For stream mode
++ //#define FLAG_BUF_ADDR_ALIGN 7 //8 byte alignment
++ //#define FLAG_BUF_ADDR_MASK 0x0FFFFFFF
++
++#define VIDEOM_BUF_CODEC_OFFSET_READ 0x25C + VIDEOBASE_OFFSET //For stream mode,
++ //#define BUF_CODEC_OFFSET_ALIGN 255 //256 byte alignment
++ //#define BUF_CODEC_OFFSET_MASK 0x003FFFFF
++
++#define VIDEOM_COMPRESS_CONTROL_REG 0x260 + VIDEOBASE_OFFSET
++ //#define JPEG_ONLY_ENCODE 0x00000001 //Bit[0] JPEG only encoding
++ // #define JPEG_MIX_MODE 0 //Enable JPEG/VQ mix mode encoding
++ // #define JPEG_ONLY_MODE 1 //JPEG encoding mode only
++ //#define VQ_4_COLOR_ENCODE 0x00000002 //Bit[1] Enable 4 color VQ encoding
++ // #define VQ_1_2_COLOR_MODE 0 //1 and 2 color mode VQ encoding
++ // #define VQ_4_COLOR_MODE 1 //1, 2 and 4 color VQ encoding
++ //#define QUALITY_CODEC_SETTING 0x00000004 //Bit[2] High and best video quality codec mode setting
++ // #define JPEG_CODEC_MODE 0 //not supported in best video quality mode
++ // #define QUANTI_CODEC_MODE 1
++ //#define JPEG_DUAL_QUALITY_EN 0x00000008 //Bit[3] JPEG dual quality mode
++ // #define EN_JPEG_DUAL_QUALITY 1 //enable(only for normal video quality mode)
++ //#define BEST_QUALITY_EN 0x00000010 //Bit[4] Best quality video mode enable
++ // #define EN_BEST_QUALITY 1 //enable(only for quantization codec mode)
++ //#define RC4_CRYPT_EN 0x00000020 //Bit[5] Enable RC4 encryption/decryption
++ // #define EN_RC4_CRYPT 1 //enable
++ //#define NORMAL_QUANTI_CHROMI_TABLE 0x00000040 //Bit[10:6] Normal video quality mode JPEG DCT chromi quantination table
++ // #define NORMAL_QUANTI_CHROMI_TABLE_BIT 6
++ // #define NORMAL_QUANTI_CHROMI_TABLE_MASK 0x000007C0
++ //#define NORMAL_QUANTI_LUMI_TABLE 0x00000800 //Bit[15:11] Normal video quality mode JPEG DCT lumi quantination table
++ // #define NORMAL_QUANTI_LUMI_TABLE_BIT 11
++ // #define NORMAL_QUANTI_LUMI_TABLE_MASK 0x0000F800
++ //#define HIGH_QUALITY_EN 0x00010000 //Bit[16] High video quality mode enable
++ // #define EN_HIGH_QUALITY 1 //Enable
++ //#define UV_CIR656_FORMAT 0x00080000 //Bit[19] UV fromat
++ // #define USE_UV_CIR656 1 //recommand
++ //#define HUFFMAN_TABLE_SELECT 0x00100000 //Bit[20] JPEG Huffman table combination
++ // #define DUAL_TABLE 0 //Dual Y, UV table
++ // #define SINGLE_TABLE 1 //Single Y table
++ // #define SINGLE_UV_TABLE 0x00200000 //1x: Single UV table
++ //#define HIGH_QUANTI_CHROMI_TABLE 0x00400000 //Bit[26:22] High quality JPEG DCT chromi quantization table
++ // #define HIGH_QUANTI_CHROMI_TABLE_BIT 22
++ // #define HIGH_QUANTI_CHROMI_TABLE_MASK 0x07C00000
++ //#define HIGH_DEQUANTI_VALUE 0x00400000 //Bit[26:22] High quality de-quantization value
++ // #define HIGH_DEQUANTI_VALUE_BIT 22
++ // #define HIGH_DEQUANTI_VALUE_MASK 0x07C00000
++ //#define HIGH_QUANTI_LUMI_TABLE 0x08000000 //Bit[31:27] High quality JPEG DCT lumi quantization table
++ // #define HIGH_QUANTI_LUMI_TABLE_BIT 27
++ // #define HIGH_QUANTI_LUMI_TABLE_MASK 0xF8000000
++ //#define BEST_DEQUANTI_VALUE 0x08000000 //Bit[31:27] Best quality de-quantization value
++ // #define BEST_QUANTI_VALUE_BIT 27
++ // #define BEST_QUANTI_VALUE_MASK 0xF8000000
++
++#define VIDEOM_QUANTI_TABLE_LOW_REG 0x264 + VIDEOBASE_OFFSET //Match with 0x60 Bit[10:6], Bit[15:11]
++// #define QUANTI_CHROMI_TABLE_LOW 0x00000001 //Bit[4:0] Normal video low quality block chromi quantization table
++// #define QUANTI_CHROMI_TABLE_LOW_BIT 0
++// #define QUANTI_CHROMI_TABLE_LOW_MASK 0x0000001F
++// #define QUANTI_LUMI_TABLE_LOW 0x00000020 //Bit[9:5] Normal video low quality block lumi quantization table
++// #define QUANTI_CHROMI_TABLE_LOW_BIT 5
++// #define QUANTI_CHROMI_TABLE_LOW_MASK 0x000003E0
++
++#define VIDEOM_QUANTI_VALUE_REG 0x268 + VIDEOBASE_OFFSET //Match with 0x60 Bit[26:22],Bit[31:27]
++// #define HIGH_QUANTI_VALUE 0x00000001 //Bit[14:0] High quality quantization value. Format is 1.14
++// #define HIGH_QUANTI_VALUE_BIT 0
++// #define HIGH_QUANTI_VALUE_MASK 0x00007FFF
++// #define BEST_QUANTI_VALUE 0x00010000 //Bit[30:16] Best quality quantization value. Format is 1.14
++// #define BEST_QUANTI_VALUE_BIT 16
++// #define BEST_QUANTI_VALUE_MASK 0x7FFF0000
++
++#define VIDEOM_BSD_PARA_REG 0x26C + VIDEOBASE_OFFSET //Video BSD Parameters Register
++// #define BSD_HIGH_THRES 0x00000001 //Bit[7:0] Block sharpness detection high threshold
++// #define BSD_HIGH_THRES_BIT 0
++// #define BSD_HIGH_THRES_MASK 0x000000FF
++// #define BSD_LOW_THRES 0x00000100 //Bit[15:8] Block shaprpness detection low threshold
++// #define BSD_LOW_THRES_BIT 8
++// #define BSD_LOW_THRES_MASK 0x0000FF00
++// #define BSD_HIGH_COUNTS 0x00010000 //Bit[21:16] Block sharpness detection high counts threshold
++// #define BSD_HIGH_COUNTS_BIT 16
++// #define BSD_HIGH_COUNTS_MASK 0x003F0000
++// #define BSD_LOW_COUNTS 0x01000000 //Bit[27:24] Block sharpness detection low counts threshold
++// #define BSD_LOW_COUNTS_BIT 24
++// #define BSD_LOW_COUNTS_MASK 0x3F000000
++
++#define VIDEOM_COMPRESS_FRAME_SIZE_REG 0x270 + VIDEOBASE_OFFSET
++// #define COMPRESS_FRAME_SIZE_READ 0x00000001 //Bit[19:0] Video compression frame size read back(number of DW)
++// #define COMPRESS_FRAME_SIZE_READ_BIT 0
++// #define COMPRESS_FRAME_SIZE_READ_MASK 0x000FFFFF
++
++#define VIDEOM_COMPRESS_BLOCK_COUNT_REG 0x274 + VIDEOBASE_OFFSET
++// #define COMPRESS_BLOCK_COUNT_READ 0x00000001 //Bit[15:0] Video compress block counter read back(number of blocks)
++// #define COMPRESS_BLOCK_COUNT_READ_BIT 0
++// #define COMPRESS_BLOCK_COUNT_READ_MASK 0x0000FFFF
++
++#define VIDEOM_COMPRESS_FRAME_END_READ 0x278 + VIDEOBASE_OFFSET //Video compression stream frame end pointer
++ //#define COMPRESS_FRAME_END_READ_ALIGN 7
++ //#define COMPRESS_FRAME_END_READ_MASK 0x003FFFFF
++
++#define VIDEOM_USER_DEFINE_HEADER_REG 0x280 + VIDEOBASE_OFFSET
++// #define USER_DEFINE_HEADER 0x00000001 //Bit[15:0] Video user defined header parameter
++// #define USER_DEFINE_HEADER_BIT 0
++// #define USER_DEFINE_HEADER_MASK 0x0000FFFF
++
++/****** VR300-VR3FC: General Control registers *****/
++#define VIDEO_CONTROL_REG 0x300 + VIDEOBASE_OFFSET
++ #define CODEC_DECOMPRESS_MODE 0x00000001 //Bit[0] Codec in de-compression mode
++ #define CODEC_DECOMPRESS_MODE_BIT 0
++ #define CODEC_DECOMPRESS_MODE_MASK 0x00000001
++ #define COMPRESS_MODE 0
++ #define DECOMPRESS_MODE 1
++ #define VIDEO_SAFE_MODE 0x00000002 //Bit[1] VIDEO SAFE MODE
++ #define VIDEO_SAFE_MODE_BIT 1
++ #define VIDEO_SAFE_MODE_OFF 0
++ #define VIDEO_SAFE_MODE_ON 1
++ #define DELAY_VSYNC 0x00000004 //Bit[2] Delay Internal VSYNC
++ #define DELAY_VSYNC_BIT 2
++ #define DELAY_VSYNC_MASK (1<<2)
++ #define DELAY_VSYNC_OFF (0<<2)
++ #define DELAY_VSYNC_EN (1<<2)
++ #define VER_DOWNSCALING_LINE_BUFFER_EN 0x00000010 //Bit[5:4] Video vertical downscaling line buffer enable
++ #define VER_LINE_BUFFER_MASK (3<<4)
++ #define LINE_BUFFER_OFF (0<<4)
++ #define LINE_BUFFER_VIDEO1 1
++ #define LINE_BUFFER_VIDEO2 2
++ #define LINE_BUFFER_VIDEOM 3
++ #define RC4_KEY_BUFFER_SELECTION (1UL<<6) //Bit[7:6] RC4 Key Buffer Selection
++ #define RC4_KEY_BUFFER_SELECTION_BIT 6
++ #define RC4_KEY_BUFFER_SELECTION_MASK (3UL<<6)
++ #define RC4_KEY_BUFFER_VIDEO1 0
++ #define RC4_KEY_BUFFER_VIDEO2 1
++ #define RC4_KEY_BUFFER_VIDEOM 2
++ #define RC4_INIT_RESET (1UL<<8) //Bit[8] RC4 initial reset
++ #define RC4_INIT_RESET_BIT 8
++ #define RC4_INIT_RESET_MASK (1UL<<8)
++ #define RC4_NORMAL_MODE 0
++ #define RC4_RESET_COUNTER 1
++ #define RC4_TEST_MODE (1UL<<9) //Bit[9] RC4 test mode
++ #define RC4_TEST_MODE_BIT 9
++ #define RC4_TEST_OFF 0
++ #define RC4_TEST_ON 1
++ #define RC4_SAVE_MODE (1UL<<14) //Bit[14] RC4 save mode
++ #define RC4_SAVE_MODE_BIT 14
++ #define RC4_SAVE_MODE_MASK (1UL<<14)
++ #define RC4_SAVE_MODE_OFF 0
++ #define RC4_SAVE_MODE_ON 1
++ #define RC4_NO_RESET_FRAME (1UL<<15) //Bit[15] RC4 no reset when frame completed
++ #define RC4_NO_RESET_FRAME_BIT 15
++ #define RC4_NO_RESET_FRAME_MASK (1UL<<15)
++ #define RC4_NO_RESET_FRAME_OFF 0 //Always reset
++ #define RC4_NO_RESET_FRAME_ON 1
++
++#define VIDEO_INT_CONTROL_EN_REG 0x304 + VIDEOBASE_OFFSET
++ #define VIDEO1_WATCH_DOG_INT_EN 0x00000001 //Bit[0] Enable Video1 mode detection watch dog out of lock interrupt
++ #define VIDEO1_INPUT_COMPLETE_INT_EN 0x00000002 //Bit[1] Enable Video1 video input complete interrupt (frame complete only for frame mode)
++ #define VIDEO1_PACKET_READY_INT_EN 0x00000004 //Bit[2] Enable Video1 packet ready interrupt
++ #define VIDEO1_COMPRESS_COMPLETE_INT_EN 0x00000008 //Bit[3] Enable Video1 compression complete interrupt
++ #define VIDEO1_MODE_DETECTION_READY_INT_EN 0x00000010 //Bit[4] Enable video1 mode detection ready interrupt
++ #define VIDEO1_FRAME_COMPLETE_INT_EN 0x00000020 //Bit[5] Enable Video1 frame complete interrupt (only for stream mode)
++ #define VIDEO1_STREAM_ERR_INT_EN 0x00000040 //Bit[6] Enable Video1 decode stream error interrupt
++ #define VIDEO2_WATCH_DOG_INT_EN 0x00000100 //Bit[8] Enable Video2 mode detection watch dog out of lock interrupt
++ #define VIDEO2_INPUT_COMPLETE_INT_EN 0x00000200 //Bit[9] Enable Video2 video input complete interrupt (frame complete only for frame mode)
++ #define VIDEO2_PACKET_READY_INT_EN 0x00000400 //Bit[10] Enable Video2 packet ready interrupt
++ #define VIDEO2_COMPRESS_COMPLETE_INT_EN 0x00000800 //Bit[11] Enable Video2 compression complete interrupt
++ #define VIDEO2_MODE_DETECTION_READY_INT_EN 0x00001000 //Bit[12] Enable video2 mode detection ready interrupt
++ #define VIDEO2_FRAME_COMPLETE_INT_EN 0x00002000 //Bit[13] Enable Video2 frame complete interrupt (only for stream mode)
++ #define VIDEO2_STREAM_ERR_INT_EN 0x00004000 //Bit[14] Enable Video2 decode stream error interrupt
++ #define VIDEOM_INPUT_COMPLETE_INT_EN 0x00010000 //Bit[16] Enable VideoM video input complete interrupt
++ #define VIDEOM_COMPRESS_COMPLETE_INT_EN 0x00020000 //Bit[17] Enable VideoM compression complete interrupt
++ #define VIDEOM_PACKET_READY_INT_EN 0x00040000 //Bit[18] Enable VideoM packet ready interrupt
++ #define VIDEOM_FRAME_COMPLETE_INT_EN 0x00080000 //Bit[19] Enable VideoM frame complete interrupt (only for stream mode)
++
++#define VIDEO_INT_CONTROL_READ_REG 0x308 + VIDEOBASE_OFFSET //Clear when write 1
++ #define VIDEO1_WATCH_DOG_READ 0x00000001 //Bit[0] Video1 mode detection watch dog out of lock interrupt status read back
++ #define VIDEO1_WATCH_DOG_BIT 0
++ #define VIDEO1_WATCH_DOG_MASK 0x00000001
++ #define VIDEO1_INPUT_COMPLETE_READ 0x00000002 //Bit[1] Video1 video input complete interrupt status read back (frame complete only for frame mode)
++ #define VIDEO1_INPUT_COMPLETE_BIT 1
++ #define VIDEO1_INPUT_COMPLETE_MASK 0x00000002
++ #define VIDEO1_PACKET_READY_READ 0x00000004 //Bit[2] Video1 packet ready interrupt status read back
++ #define VIDEO1_PACKET_READY_BIT 2
++ #define VIDEO1_PACKET_READY_MASK 0x00000004
++ #define VIDEO1_COMPRESS_COMPLETE_READ 0x00000008 //Bit[3] Video1 compression complete interrupt status read back
++ #define VIDEO1_COMPRESS_COMPLETE_BIT 3
++ #define VIDEO1_COMPRESS_COMPLETE_MASK 0x00000008
++ #define VIDEO1_MODE_DETECTION_READY_READ 0x00000010 //Bit[4] Video1 mode detection ready interrupt status read back
++ #define VIDEO1_MODE_DETECTION_READY_BIT 4
++ #define VIDEO1_FRAME_COMPLETE_READ 0x00000020 //Bit[5] Video1 frame complete interrupt status read back
++ #define VIDEO1_FRAME_COMPLETE_BIT 5
++ #define VIDEO1_FRAME_COMPLETE_MASK 0x00000020
++ #define VIDEO1_STREAM_ERR_READ 0x00000040 //Bit[6] Video1 decode stream error interrupt status read back
++ #define VIDEO1_STREAM_ERR_BIT 6
++ #define VIDEO1_STREAM_ERR_MASK 0x00000040
++ #define VIDEO2_WATCH_DOG_READ 0x00000100 //Bit[8] Video2 mode detection watch dog out of lock interrupt status read back
++ #define VIDEO2_WATCH_DOG_BIT 8
++ #define VIDEO2_WATCH_DOG_MASK 0x00000100
++ #define VIDEO2_INPUT_COMPLETE_READ 0x00000200 //Bit[9] Video2 video input complete interrupt status read back (frame complete only for frame mode)
++ #define VIDEO2_INPUT_COMPLETE_BIT 9
++ #define VIDEO2_INPUT_COMPLETE_MASK 0x00000200
++ #define VIDEO2_PACKET_READY_READ 0x00000400 //Bit[10] Video2 packet ready interrupt status read back
++ #define VIDEO2_PACKET_READY_BIT 10
++ #define VIDEO2_PACKET_READY_MASK 0x00000400
++ #define VIDEO2_COMPRESS_COMPLETE_READ 0x00000800 //Bit[11] Video2 compression complete interrupt status read back
++ #define VIDEO2_COMPRESS_COMPLETE_BIT 11
++ #define VIDEO2_COMPRESS_COMPLETE_MASK 0x00000800
++ #define VIDEO2_MODE_DETECTION_READY_READ 0x00001000 //Bit[12] Video2 mode detection ready interrupt status read back
++ #define VIDEO2_MODE_DETECTION_READY_BIT 12
++ #define VIDEO2_FRAME_COMPLETE_READ 0x00002000 //Bit[13] Video2 frame complete interrupt status read back
++ #define VIDEO2_FRAME_COMPLETE_BIT 13
++ #define VIDEO2_FRAME_COMPLETE_MASK 0x00002000
++ #define VIDEO2_STREAM_ERR_READ 0x00004000 //Bit[14] Video2 decode stream error interrupt status read back
++ #define VIDEO2_STREAM_ERR_BIT 14
++ #define VIDEO2_STREAM_ERR_MASK 0x00004000
++ //need check spec
++ #define VIDEOM_INPUT_COMPLETE_READ 0x00010000 //Bit[16] VideoM video input complete interrupt status read back
++ #define VIDEOM_INPUT_COMPLETE_BIT 16
++ #define VIDEOM_INPUT_COMPLETE_MASK 0x00010000
++ #define VIDEOM_COMPRESS_COMPLETE_READ 0x00020000 //Bit[17] VideoM compression complete interrupt status read back
++ #define VIDEOM_COMPRESS_COMPLETE_BIT 17
++ #define VIDEOM_COMPRESS_COMPLETE_MASK 0x00020000
++ #define VIDEOM_PACKET_READY_READ 0x00040000 //Bit[18] Clear Packet ready interrupt when write 1
++ #define VIDEOM_PACKET_READY_BIT 18
++ #define VIDEOM_PACKET_READY_MASK 0x00040000
++ #define VIDEOM_FRAME_COMPLETE_READ 0x00080000 //Bit[19] Clear Frame complete interrupt when write 1
++ #define VIDEOM_FRAME_COMPLETE_BIT 19
++ #define VIDEOM_FRAME_COMPLETE_MASK 0x00080000
++
++#define VIDEO_INT_CONTROL_CLEAR_REG 0x308 + VIDEOBASE_OFFSET //Clear when write 1
++ //Clear when write 1
++ #define VIDEO1_WATCH_DOG_CLEAR 0x00000001 //Bit[0] Clear mode detection watch dog out of lock interrupt when write 1
++ #define VIDEO1_INPUT_COMPLETE_CLEAR 0x00000002 //Bit[1] Clear video input complete interrupt when write 1 (frame complete only for frame mode)
++ #define VIDEO1_PACKET_READY_CLEAR 0x00000004 //Bit[2] Clear Packet ready interrupt when write 1
++ #define VIDEO1_PACKET_READY_CLEAR_BIT 2
++ #define VIDEO1_PACKET_READY_CLEAR_MASK 0x00000004
++ #define VIDEO1_COMPRESS_COMPLETE_CLEAR 0x00000008 //Bit[3] Clear video compression interrupt when write 1
++ #define VIDEO1_MODE_DETECTION_READY_CLEAR 0x00000010 //Bit[4] Clear Video1 Mode detection ready interrupt when write 1
++ #define VIDEO1_FRAME_COMPLETE_CLEAR 0x00000020 //Bit[5] Clear Frame complete interrupt when write 1
++ #define VIDEO1_FRAME_COMPLETE_CLEAR_BIT 5
++ #define VIDEO1_FRAME_COMPLETE_CLEAR_MASK 0x00000020
++ #define VIDEO1_STREAM_ERR_CLEAR 0x00000040 //Bit[6] Clear decode stream error interrupt when write 1
++ #define VIDEO2_WATCH_DOG_CLEAR 0x00000100 //Bit[8] Clear Mode detection interrupt when write 1
++ #define VIDEO2_INPUT_COMPLETE_CLEAR 0x00000200 //Bit[9] Clear video input complete interrupt when write 1
++ #define VIDEO2_PACKET_READY_CLEAR 0x00000400 //Bit[10] Clear packet ready interrupt when write 1
++ #define VIDEO2_COMPRESS_COMPLETE_CLEAR 0x00000800 //Bit[11] Clear video compression complete interrupt when write 1
++ #define VIDEO2_MODE_DETECTION_READY_CLEAR 0x00001000 //Bit[12] Clear Video2 Mode detection ready interrupt when write 1
++ #define VIDEO2_FRAME_COMPLETE_CLEAR 0x00002000 //Bit[13] Clear Frame complete interrupt when write 1 (frame complete only for frame mode)
++ #define VIDEO2_STREAM_ERR_CLEAR 0x00004000 //Bit[14] Clear Decode stream error interrupt when write 1
++ //need check spec
++ #define VIDEOM_INPUT_COMPLETE_CLEAR 0x00010000 //Bit[16] Clear video input complete interrupt when write 1
++ #define VIDEOM_COMPRESS_COMPLETE_CLEAR 0x00020000 //Bit[17] Clear compression complete interrupt when write 1
++ #define VIDEOM_COMPRESS_COMPLETE_CLEAR_BIT 17
++ #define VIDEOM_COMPRESS_COMPLETE_CLEAR_MASK 0x00020000
++ #define VIDEOM_PACKET_READY_CLEAR 0x00040000 //Bit[18] Clear compression complete interrupt when write 1
++ #define VIDEOM_PACKET_READY_CLEAR_BIT 18
++ #define VIDEOM_PACKET_READY_CLEAR_MASK 0x00040000
++ #define VIDEOM_FRAME_COMPLETE_CLEAR 0x00100000 //Bit[20] Clear Frame complete interrupt when write 1
++ #define VIDEOM_FRAME_COMPLETE_CLEAR_BIT 20
++ #define VIDEOM_FRAME_COMPLETE_CLEAR_MASK 0x00100000
++ #define VIDEOM_STREAM_ERR_CLEAR 0x00200000 //Bit[21] Clear decode stream error interrupt when write 1
++
++#define VIDEO_MODE_DETECTION_PARAM_REG 0x30C + VIDEOBASE_OFFSET
++ #define EDGE_PIXEL_THRES_BIT 8 //Bit[15:8] Mode detection edge pixel threshold
++ #define EDGE_PIXEL_THRES_MASK 0x0000FF00
++ #define VER_STABLE_MAX_BIT 16 //Bit[19:16] Mode detection vertical stable maximum
++ #define VER_STABLE_MAX_BIT_MASK 0x000F0000
++ #define HOR_STABLE_MAX_BIT 20 //Bit[23:20] Mode detection horizontal stable maximum
++ #define HOR_STABLE_MAX_BIT_MASK 0x00F00000
++ #define VER_STABLE_THRES_BIT 24 //Bit[27:24] Mode detection vertical stable threshold
++ #define VER_STABLE_THRES_BIT_MASK 0x0F000000
++ #define HOR_STABLE_THRES_BIT 28 //Bit[31:28] Mode detection horizontal stable threshold
++ #define HOR_STABLE_THRES_BIT_MASK 0xF0000000
++
++#define VIDEO_CRC_PRIMARY_REG 0x320 + VIDEOBASE_OFFSET
++ #define CRC_CHECK_EN 0x00000001 //Bit[0] Video port 1/2 Enable video capture write CRC check
++ #define CRC_CHECK_EN_BIT 0
++ #define CRC_CHECK_HIGH 0x00000002 //Bit[1] Video port 1/2 CRC check high bit only
++ #define CRC_CHECK_HIGH_BIT 1
++ #define SKIP_COUNT_MAX 0x00000004 //Bit[7:2] Video port 1/2 Max capture write skip count
++ #define SKIP_COUNT_MAX_BIT 2
++ #define SKIP_COUNT_MAX_MASK 0x000000FC
++ #define CRC_PRIMARY_POLY_LOW 0x00000100 //Bit[15:8] Primary CRC low 8-bit polynomial
++ #define CRC_RIMARY_POLY_LOW_BIT 8
++ #define CRC_RIMARY_POLY_LOW_MASK 0x0000FF00
++ #define CRC_PRIMARY_POLY_HIGH 0x00010000 //Bit[31:16] Primary CRC high 8-bit polynomial
++ #define CRC_RIMARY_POLY_HIGH_BIT 16
++ #define CRC_RIMARY_POLY_HIGH_MASK 0xFFFF0000
++
++
++#define VIDEO_CRC_SECOND_REG 0x324 + VIDEOBASE_OFFSET
++ #define CRC_SECOND_POLY_LOW 0x00000100 //Bit[15:8] Secondary CRC low 8-bit polynomial
++ #define CRC_SECOND_POLY_LOW_BIT 8
++ #define CRC_SECOND_POLY_LOW_MASK 0x0000FF00
++ #define CRC_SECOND_POLY_HIGH 0x00010000 //Bit[31:16] Secondary CRC high 8-bit polynomial
++ #define CRC_SECOND_POLY_HIGH_BIT 16
++ #define CRC_SECOND_POLY_HIGH_MASK 0xFFFF0000
++
++#define VIDEO1_RC4_KEYS_REG 0x400 + VIDEOBASE_OFFSET //Total Video1 RC4 Keys
++#define VIDEO2_RC4_KEYS_REG 0x500 + VIDEOBASE_OFFSET //Total Video2 RC4 Keys
++#define VIDEOM_RC4_KEYS_REG 0x600 + VIDEOBASE_OFFSET //Total VideoM RC4 Keys
++
++#endif /* end of _VREG_H_ */
++
+diff --git a/boards.cfg b/boards.cfg
+index 6a368de..674896b 100644
+--- a/boards.cfg
++++ b/boards.cfg
+@@ -72,6 +72,7 @@ mini2440 arm arm920t mini2440 friendl
+ VCMA9 arm arm920t vcma9 mpl s3c24x0
+ smdk2410 arm arm920t - samsung s3c24x0
+ omap1510inn arm arm925t - ti
++ast2400 arm arm926ejs ast2400 aspeed aspeed
+ integratorap_cm926ejs arm arm926ejs integrator armltd - integratorap:CM926EJ_S
+ integratorcp_cm926ejs arm arm926ejs integrator armltd - integratorcp:CM924EJ_S
+ aspenite arm arm926ejs - Marvell armada100
+diff --git a/common/Makefile b/common/Makefile
+index 53c92ef..6ba5f38 100644
+--- a/common/Makefile
++++ b/common/Makefile
+@@ -190,6 +190,8 @@ COBJS-$(CONFIG_CMD_ZIP) += cmd_zip.o
+ COBJS-$(CONFIG_CMD_ZFS) += cmd_zfs.o
+
+ # others
++OBJS-$(CONFIG_CMD_NETTEST) += cmd_nettest.o
++COBJS-$(CONFIG_CMD_SLT) += cmd_slt.o
+ COBJS-$(CONFIG_BOOTSTAGE) += bootstage.o
+ COBJS-$(CONFIG_CONSOLE_MUX) += iomux.o
+ COBJS-y += flash.o
+diff --git a/common/cmd_nettest.c b/common/cmd_nettest.c
+new file mode 100644
+index 0000000..249d7b6
+--- /dev/null
++++ b/common/cmd_nettest.c
+@@ -0,0 +1,214 @@
++/*
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++*/
++
++#include <common.h>
++#include <command.h>
++#include <COMMINF.H>
++
++#ifdef SLT_UBOOT
++extern int main_function(int argc, char *argv[]);
++
++int do_mactest (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])
++{
++ ModeSwitch = MODE_DEDICATED;
++ return main_function( argc, argv);
++}
++
++int do_ncsitest (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])
++{
++ ModeSwitch = MODE_NSCI;
++ return main_function( argc, argv);
++}
++
++U_BOOT_CMD(
++ mactest, CONFIG_SYS_MAXARGS, 0, do_mactest,
++ "mactest - Dedicated LAN test program \n",
++ NULL
++);
++U_BOOT_CMD(
++ ncsitest, CONFIG_SYS_MAXARGS, 0, do_ncsitest,
++ "ncsitest- Share LAN (NC-SI) test program \n",
++ NULL
++);
++
++// ------------------------------------------------------------------------------
++int do_phyread (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])
++{
++ int MACnum;
++ int PHYreg;
++ ULONG result_data;
++ int ret = 0;
++ int PHYaddr;
++ int timeout = 0;
++
++ do {
++ if ( argc != 4 ) {
++ printf(" Wrong parameter number.\n" );
++ printf(" phyr mac addr reg\n" );
++ printf(" mac : 0 or 1. [hex]\n" );
++ printf(" PHY addr: 0 to 31. [hex]\n" );
++ printf(" register: 0 to 0xFF.[hex]\n" );
++ printf(" example: phyr 0 0 1\n" );
++ ret = -1;
++ break;
++ }
++
++ MACnum = strtoul(argv[1], NULL, 16);
++ PHYaddr = strtoul(argv[2], NULL, 16);
++ PHYreg = strtoul(argv[3], NULL, 16);
++
++ if ( MACnum == 0 ) {
++ // Set MAC 0
++ H_MAC_BASE = MAC_BASE1;
++ }
++ else if ( MACnum == 1 ) {
++ // Set MAC 1
++ H_MAC_BASE = MAC_BASE2;
++ }
++ else {
++ printf("wrong parameter (mac number)\n");
++ ret = -1;
++ break;
++ }
++ MAC_PHYBASE = H_MAC_BASE;
++
++ if ( ( PHYaddr < 0 ) || ( PHYaddr > 31 ) ) {
++ printf("wrong parameter (PHY address)\n");
++ ret = -1;
++ break;
++ }
++
++ MAC_40h_old = ReadSOC_DD( H_MAC_BASE + 0x40 );
++ AST2300_NewMDIO = (MAC_40h_old & 0x80000000) ? 1 : 0;
++
++ if ( AST2300_NewMDIO ) {
++ WriteSOC_DD( MAC_PHYBASE + 0x60, MAC_PHYRd_New | (PHYaddr << 5) | ( PHYreg & 0x1f ) );
++ while ( ReadSOC_DD( MAC_PHYBASE + 0x60 ) & MAC_PHYBusy_New ) {
++ if ( ++timeout > TIME_OUT_PHY_RW ) {
++ ret = -1;
++ break;
++ }
++ }
++ DELAY(Delay_PHYRd);
++ result_data = ReadSOC_DD( MAC_PHYBASE + 0x64 ) & 0xffff;
++ }
++ else {
++ WriteSOC_DD( MAC_PHYBASE + 0x60, MDC_Thres | MAC_PHYRd | (PHYaddr << 16) | ((PHYreg & 0x1f) << 21) );
++ while ( ReadSOC_DD( MAC_PHYBASE + 0x60 ) & MAC_PHYRd ) {
++ if ( ++timeout > TIME_OUT_PHY_RW ) {
++ ret = -1;
++ break;
++ }
++ }
++ DELAY( Delay_PHYRd );
++ result_data = ReadSOC_DD( MAC_PHYBASE + 0x64 ) >> 16;
++ }
++ printf(" PHY[%d] reg[%2X] = %08lX\n", PHYaddr, PHYreg, result_data );
++ } while ( 0 );
++
++ return ret;
++}
++
++
++int do_phywrite (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])
++{
++ int MACnum;
++ int PHYreg;
++ int PHYaddr;
++ ULONG reg_data;
++ int ret = 0;
++ int timeout = 0;
++
++ do {
++ if ( argc != 5 )
++ {
++ printf(" Wrong parameter number.\n" );
++ printf(" phyw mac addr reg data\n" );
++ printf(" mac : 0 or 1. [hex]\n" );
++ printf(" PHY addr: 0 to 31. [hex]\n" );
++ printf(" register: 0 to 0xFF. [hex]\n" );
++ printf(" data : 0 to 0xFFFF.[hex]\n" );
++ printf(" example: phyw 0 0 0 610\n" );
++ ret = -1;
++ break;
++ }
++
++ MACnum = strtoul(argv[1], NULL, 16);
++ PHYaddr = strtoul(argv[2], NULL, 16);
++ PHYreg = strtoul(argv[3], NULL, 16);
++ reg_data = strtoul(argv[4], NULL, 16);
++
++ if ( MACnum == 0 ) {
++ // Set MAC 0
++ H_MAC_BASE = MAC_BASE1;
++ }
++ else if ( MACnum == 1 ) {
++ // Set MAC 1
++ H_MAC_BASE = MAC_BASE2;
++ }
++ else {
++ printf("wrong parameter (mac number)\n");
++ ret = -1;
++ break;
++ }
++ MAC_PHYBASE = H_MAC_BASE;
++
++ if ( ( PHYaddr < 0 ) || ( PHYaddr > 31 ) ) {
++ printf("wrong parameter (PHY address)\n");
++ ret = -1;
++ break;
++ }
++
++ MAC_40h_old = ReadSOC_DD( H_MAC_BASE + 0x40 );
++ AST2300_NewMDIO = (MAC_40h_old & 0x80000000) ? 1 : 0;
++
++ if (AST2300_NewMDIO) {
++ WriteSOC_DD( MAC_PHYBASE + 0x60, ( reg_data << 16 ) | MAC_PHYWr_New | (PHYaddr<<5) | (PHYreg & 0x1f));
++
++ while ( ReadSOC_DD( MAC_PHYBASE + 0x60 ) & MAC_PHYBusy_New ) {
++ if ( ++timeout > TIME_OUT_PHY_RW ) {
++ ret = -1;
++ break;
++ }
++ }
++ }
++ else {
++ WriteSOC_DD( MAC_PHYBASE + 0x64, reg_data );
++ WriteSOC_DD( MAC_PHYBASE + 0x60, MDC_Thres | MAC_PHYWr | (PHYaddr<<16) | ((PHYreg & 0x1f) << 21));
++
++ while ( ReadSOC_DD( MAC_PHYBASE + 0x60 ) & MAC_PHYWr ) {
++ if ( ++timeout > TIME_OUT_PHY_RW ) {
++ ret = -1;
++ break;
++ }
++ }
++ } // End if (AST2300_NewMDIO)
++
++ printf("Write: PHY[%d] reg[%2X] = %08lX\n", PHYaddr, PHYreg, reg_data );
++ } while ( 0 );
++
++ return ret;
++}
++
++U_BOOT_CMD(
++ phyr, CONFIG_SYS_MAXARGS, 0, do_phyread,
++ "phyr - Read PHY register. (phyr mac addr reg)\n",
++ NULL
++);
++
++U_BOOT_CMD(
++ phyw, CONFIG_SYS_MAXARGS, 0, do_phywrite,
++ "phyw - Write PHY register. (phyw mac addr reg data)\n",
++ NULL
++);
++
++#endif // End SLT_UBOOT
++
+diff --git a/common/cmd_slt.c b/common/cmd_slt.c
+new file mode 100644
+index 0000000..9763692
+--- /dev/null
++++ b/common/cmd_slt.c
+@@ -0,0 +1,49 @@
++/*
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++*/
++
++#include <command.h>
++
++extern int pll_function(int argc, char *argv[]);
++extern int trap_function(int argc, char *argv[]);
++extern int dram_stress_function(int argc, char *argv[]);
++
++int do_plltest (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])
++{
++ return pll_function( argc, argv);
++}
++
++U_BOOT_CMD(
++ plltest, CONFIG_SYS_MAXARGS, 0, do_plltest,
++ "plltest - PLLTest [pll mode] [err rate] \n",
++ NULL
++);
++
++int do_traptest (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])
++{
++ return trap_function( argc, argv);
++}
++
++U_BOOT_CMD(
++ traptest, CONFIG_SYS_MAXARGS, 0, do_traptest,
++ "traptest- Check hardware trap for CPU clock and CPU\\AHB ratio.\n",
++ NULL
++);
++
++int do_dramtest (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])
++{
++ return dram_stress_function( argc, argv);
++}
++
++U_BOOT_CMD(
++ dramtest, CONFIG_SYS_MAXARGS, 0, do_dramtest,
++ "dramtest- Stress DRAM.\n",
++ NULL
++);
+diff --git a/drivers/i2c/Makefile b/drivers/i2c/Makefile
+index 72e85a3..2b35587 100644
+--- a/drivers/i2c/Makefile
++++ b/drivers/i2c/Makefile
+@@ -43,6 +43,7 @@ COBJS-$(CONFIG_S3C44B0_I2C) += s3c44b0_i2c.o
+ COBJS-$(CONFIG_SOFT_I2C) += soft_i2c.o
+ COBJS-$(CONFIG_TEGRA_I2C) += tegra_i2c.o
+ COBJS-$(CONFIG_TSI108_I2C) += tsi108_i2c.o
++COBJS-$(CONFIG_DRIVER_ASPEED_I2C) += aspeed_i2c.o
+ COBJS-$(CONFIG_U8500_I2C) += u8500_i2c.o
+ COBJS-$(CONFIG_SH_I2C) += sh_i2c.o
+ COBJS-$(CONFIG_SH_SH7734_I2C) += sh_sh7734_i2c.o
+diff --git a/drivers/i2c/aspeed_i2c.c b/drivers/i2c/aspeed_i2c.c
+new file mode 100755
+index 0000000..ff6c756
+--- /dev/null
++++ b/drivers/i2c/aspeed_i2c.c
+@@ -0,0 +1,286 @@
++/*
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++ */
++
++#include <common.h>
++#include <asm/arch/aspeed_i2c.h>
++
++#ifdef CONFIG_DRIVER_ASPEED_I2C
++
++void i2c_init (int speed, int slaveadd)
++{
++ unsigned long SCURegister;
++//I2C Reset
++ SCURegister = inl (SCU_BASE + SCU_RESET_CONTROL);
++ outl (SCURegister & ~(0x04), SCU_BASE + SCU_RESET_CONTROL);
++//I2C Multi-Pin
++ SCURegister = inl (SCU_BASE + SCU_MULTIFUNCTION_PIN_CTL5_REG);
++ outl ((SCURegister | 0x30000), SCU_BASE + SCU_MULTIFUNCTION_PIN_CTL5_REG);
++//Reset
++ outl (0, I2C_FUNCTION_CONTROL_REGISTER);
++//Set AC Timing, we use fix AC timing for eeprom in u-boot
++ outl (AC_TIMING, I2C_AC_TIMING_REGISTER_1);
++ outl (0, I2C_AC_TIMING_REGISTER_2);
++//Clear Interrupt
++ outl (ALL_CLEAR, I2C_INTERRUPT_STATUS_REGISTER);
++//Enable Master Mode
++ outl (MASTER_ENABLE, I2C_FUNCTION_CONTROL_REGISTER);
++//Enable Interrupt, STOP Interrupt has bug in AST2000
++ outl (0xAF, I2C_INTERRUPT_CONTROL_REGISTER);
++//Set Slave address, should not use for eeprom
++ outl (slaveadd, I2C_DEVICE_ADDRESS_REGISTER);
++}
++
++static int i2c_read_byte (u8 devaddr, u16 regoffset, u8 * value, int alen)
++{
++ int i2c_error = 0;
++ u32 status, count = 0;
++
++//Start and Send Device Address
++ outl (devaddr, I2C_BYTE_BUFFER_REGISTER);
++ outl (MASTER_START_COMMAND | MASTER_TX_COMMAND, I2C_COMMAND_REGISTER);
++//Wait Tx ACK
++ do {
++ status = (inl (I2C_INTERRUPT_STATUS_REGISTER) & (TX_ACK | TX_NACK));
++ count++;
++ if (count == LOOP_COUNT) {
++ i2c_error = 1;
++ printf ("Start and Send Device Address can't get ACK back\n");
++ return i2c_error;
++ }
++ } while (status != TX_ACK);
++ count = 0;
++//Clear Interrupt
++ outl (ALL_CLEAR, I2C_INTERRUPT_STATUS_REGISTER);
++//Check if address length equals to 16bits
++ if (alen != 1) {
++//Send Device Register Offset (HIGH BYTE)
++ outl ((regoffset & 0xFF00) >> 8, I2C_BYTE_BUFFER_REGISTER);
++ outl (MASTER_TX_COMMAND, I2C_COMMAND_REGISTER);
++//Wait Tx ACK
++ do {
++ status = (inl (I2C_INTERRUPT_STATUS_REGISTER) & (TX_ACK | TX_NACK));
++ count++;
++ if (count == LOOP_COUNT) {
++ i2c_error = 1;
++ printf ("Send Device Register Offset can't get ACK back\n");
++ return i2c_error;
++ }
++ } while (status != TX_ACK);
++ count = 0;
++//Clear Interrupt
++ outl (ALL_CLEAR, I2C_INTERRUPT_STATUS_REGISTER);
++ }
++//Send Device Register Offset(LOW)
++ outl (regoffset & 0xFF, I2C_BYTE_BUFFER_REGISTER);
++ outl (MASTER_TX_COMMAND, I2C_COMMAND_REGISTER);
++//Wait Tx ACK
++ do {
++ status = (inl (I2C_INTERRUPT_STATUS_REGISTER) & (TX_ACK | TX_NACK));
++ count++;
++ if (count == LOOP_COUNT) {
++ i2c_error = 1;
++ printf ("Send Device Register Offset can't get ACK back\n");
++ return i2c_error;
++ }
++ } while (status != TX_ACK);
++ count = 0;
++//Clear Interrupt
++ outl (ALL_CLEAR, I2C_INTERRUPT_STATUS_REGISTER);
++//Start, Send Device Address + 1 (Read Mode), Receive Data
++ outl (devaddr + 1, I2C_BYTE_BUFFER_REGISTER);
++ outl (MASTER_START_COMMAND | MASTER_TX_COMMAND | MASTER_RX_COMMAND | RX_COMMAND_LIST, I2C_COMMAND_REGISTER);
++//Wait Rx Done
++ do {
++ status = (inl (I2C_INTERRUPT_STATUS_REGISTER) & RX_DONE);
++ count++;
++ if (count == LOOP_COUNT) {
++ i2c_error = 1;
++ printf ("Can't get RX_DONE back\n");
++ return i2c_error;
++ }
++ } while (status != RX_DONE);
++ count = 0;
++//Clear Interrupt
++ outl (ALL_CLEAR, I2C_INTERRUPT_STATUS_REGISTER);
++//Enable Interrupt + Stop Interrupt
++ outl (0xBF, I2C_INTERRUPT_CONTROL_REGISTER);
++//Issue Stop Command
++ outl (MASTER_STOP_COMMAND, I2C_COMMAND_REGISTER);
++//Wait Stop
++ do {
++ status = (inl (I2C_INTERRUPT_STATUS_REGISTER) & STOP_DONE);
++ count++;
++ if (count == LOOP_COUNT) {
++ i2c_error = 1;
++ printf ("Can't get STOP back\n");
++ return i2c_error;
++ }
++ } while (status != STOP_DONE);
++//Disable Stop Interrupt
++ outl (0xAF, I2C_INTERRUPT_CONTROL_REGISTER);
++//Clear Interrupt
++ outl (ALL_CLEAR, I2C_INTERRUPT_STATUS_REGISTER);
++//Read Received Data
++ *value = ((inl (I2C_BYTE_BUFFER_REGISTER) & 0xFF00) >> 8);
++
++ return i2c_error;
++}
++
++static int i2c_write_byte (u8 devaddr, u16 regoffset, u8 value, int alen)
++{
++ int i2c_error = 0;
++ u32 status, count = 0;
++
++//Start and Send Device Address
++ outl (devaddr, I2C_BYTE_BUFFER_REGISTER);
++ outl (MASTER_START_COMMAND | MASTER_TX_COMMAND, I2C_COMMAND_REGISTER);
++//Wait Tx ACK
++ do {
++ status = (inl (I2C_INTERRUPT_STATUS_REGISTER) & (TX_ACK | TX_NACK));
++ count++;
++ if (status == TX_NACK) {
++//Clear Interrupt
++ outl (ALL_CLEAR, I2C_INTERRUPT_STATUS_REGISTER);
++//Re-send Start and Send Device Address while NACK return
++ outl (devaddr, I2C_BYTE_BUFFER_REGISTER);
++ outl (MASTER_START_COMMAND | MASTER_TX_COMMAND, I2C_COMMAND_REGISTER);
++ }
++ else {
++ if (count == LOOP_COUNT) {
++ i2c_error = 1;
++ printf ("Start and Send Device Address can't get ACK back\n");
++ return i2c_error;
++ }
++ }
++ } while (status != TX_ACK);
++ count = 0;
++//Clear Interrupt
++ outl (ALL_CLEAR, I2C_INTERRUPT_STATUS_REGISTER);
++//Check if address length equals to 16bits
++ if (alen != 1) {
++//Send Device Register Offset (HIGH BYTE)
++ outl ((regoffset & 0xFF00) >> 8, I2C_BYTE_BUFFER_REGISTER);
++ outl (MASTER_TX_COMMAND, I2C_COMMAND_REGISTER);
++//Wait Tx ACK
++ do {
++ status = (inl (I2C_INTERRUPT_STATUS_REGISTER) & (TX_ACK | TX_NACK));
++ count++;
++ if (count == LOOP_COUNT) {
++ i2c_error = 1;
++ printf ("Send Device Register Offset can't get ACK back\n");
++ return i2c_error;
++ }
++ } while (status != TX_ACK);
++ count = 0;
++//Clear Interrupt
++ outl (ALL_CLEAR, I2C_INTERRUPT_STATUS_REGISTER);
++ }
++//Send Device Register Offset
++ outl (regoffset & 0xFF, I2C_BYTE_BUFFER_REGISTER);
++ outl (MASTER_TX_COMMAND, I2C_COMMAND_REGISTER);
++//Wait Tx ACK
++ do {
++ status = (inl (I2C_INTERRUPT_STATUS_REGISTER) & (TX_ACK | TX_NACK));
++ count++;
++ if (count == LOOP_COUNT) {
++ i2c_error = 1;
++ printf ("Send Device Register Offset can't get ACK back\n");
++ return i2c_error;
++ }
++ } while (status != TX_ACK);
++ count = 0;
++//Clear Interrupt
++ outl (ALL_CLEAR, I2C_INTERRUPT_STATUS_REGISTER);
++//Send Device Register Value
++ outl (value, I2C_BYTE_BUFFER_REGISTER);
++ outl (MASTER_TX_COMMAND, I2C_COMMAND_REGISTER);
++//Wait Tx ACK
++ do {
++ status = (inl (I2C_INTERRUPT_STATUS_REGISTER) & (TX_ACK | TX_NACK));
++ count++;
++ if (count == LOOP_COUNT) {
++ i2c_error = 1;
++ printf ("Send Device Register Value can't get ACK back\n");
++ return i2c_error;
++ }
++ } while (status != TX_ACK);
++ count = 0;
++//Clear Interrupt
++ outl (ALL_CLEAR, I2C_INTERRUPT_STATUS_REGISTER);
++//Enable Interrupt + Stop Interrupt
++ outl (0xBF, I2C_INTERRUPT_CONTROL_REGISTER);
++//Issue Stop Command
++ outl (MASTER_STOP_COMMAND, I2C_COMMAND_REGISTER);
++//Wait Stop
++ do {
++ status = (inl (I2C_INTERRUPT_STATUS_REGISTER) & STOP_DONE);
++ count++;
++ if (count == LOOP_COUNT) {
++ i2c_error = 1;
++ printf ("Can't get STOP back\n");
++ return i2c_error;
++ }
++ } while (status != STOP_DONE);
++//Disable Stop Interrupt
++ outl (0xAF, I2C_INTERRUPT_CONTROL_REGISTER);
++//Clear Interrupt
++ outl (ALL_CLEAR, I2C_INTERRUPT_STATUS_REGISTER);
++
++ return i2c_error;
++}
++
++int i2c_probe (uchar chip)
++{
++//Suppose IP is always on chip
++ int res = 0;
++
++ return res;
++}
++
++int i2c_read (uchar device_addr, uint register_offset, int alen, uchar * buffer, int len)
++{
++ int i;
++
++ if ((alen == 1) && ((register_offset + len) > 256)) {
++ printf ("Register index overflow\n");
++ }
++
++ for (i = 0; i < len; i++) {
++ if (i2c_read_byte (device_addr, register_offset + i, &buffer[i], alen)) {
++ printf ("I2C read: I/O error\n");
++ i2c_init (CONFIG_SYS_I2C_SPEED, CONFIG_SYS_I2C_SLAVE);
++ return 1;
++ }
++ }
++
++ return 0;
++}
++
++int i2c_write (uchar device_addr, uint register_offset, int alen, uchar * buffer, int len)
++{
++ int i;
++
++ if ((alen == 1) && ((register_offset + len) > 256)) {
++ printf ("Register index overflow\n");
++ }
++
++ for (i = 0; i < len; i++) {
++ if (i2c_write_byte (device_addr, register_offset + i, buffer[i], alen)) {
++ printf ("I2C read: I/O error\n");
++ i2c_init (CONFIG_SYS_I2C_SPEED, CONFIG_SYS_I2C_SLAVE);
++ return 1;
++ }
++ }
++
++ return 0;
++}
++
++#endif /* CONFIG_DRIVER_ASPEED_I2C */
+diff --git a/drivers/net/Makefile b/drivers/net/Makefile
+index 9cf2983..a1d19ca 100644
+--- a/drivers/net/Makefile
++++ b/drivers/net/Makefile
+@@ -68,6 +68,7 @@ COBJS-$(CONFIG_PLB2800_ETHER) += plb2800_eth.o
+ COBJS-$(CONFIG_RTL8139) += rtl8139.o
+ COBJS-$(CONFIG_RTL8169) += rtl8169.o
+ COBJS-$(CONFIG_SH_ETHER) += sh_eth.o
++COBJS-$(CONFIG_ASPEEDNIC) += aspeednic.o
+ COBJS-$(CONFIG_SMC91111) += smc91111.o
+ COBJS-$(CONFIG_SMC911X) += smc911x.o
+ COBJS-$(CONFIG_SUNXI_WEMAC) += sunxi_wemac.o
+diff --git a/drivers/net/aspeednic.c b/drivers/net/aspeednic.c
+new file mode 100644
+index 0000000..6b1ce05
+--- /dev/null
++++ b/drivers/net/aspeednic.c
+@@ -0,0 +1,1528 @@
++/*
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++ */
++
++#include <common.h>
++
++#if defined(CONFIG_CMD_NET) && defined(CONFIG_NET_MULTI) && defined(CONFIG_ASPEEDNIC)
++
++#include <malloc.h>
++#include <net.h>
++#include <pci.h>
++
++
++/*
++ SCU88 D[31]: MAC1 MDIO
++ SCU88 D[30]: MAC1 MDC
++ SCU90 D[2]: MAC2 MDC/MDIO
++ SCU80 D[0]: MAC1 Link
++ SCU80 D[1]: MAC2 Link
++*/
++#define pci_find_devices NULL
++#define pci_read_config_dword NULL
++#if defined(CONFIG_AST1300)
++#define SCU_BASE CONFIG_SCUREG_BASE
++#else
++#define SCU_BASE 0x1E6E2000
++#endif
++#define SCU_RESET_CONTROL 0x04
++#define SCU_CLOCK_SELECTION 0x08
++#define SCU_CLOCK_CONTROL 0x0C
++#define SCU_MAC_CLOCK_DELAY 0x48
++#define SCU_SCRATCH_REGISTER 0x40
++#define SCU_HARDWARE_TRAPPING 0x70
++#define SCU_PIN_MUX 0x74
++#define SCU_MULTIFUNCTION_PIN_CTL1_REG 0x80
++#define SCU_MULTIFUNCTION_PIN_CTL3_REG 0x88
++#define SCU_MULTIFUNCTION_PIN_CTL5_REG 0x90
++#define MAC_INTERFACE 0x1C0
++#define GMII 0x0
++#define MII 0x40
++#define MAC1_CLOCK_ENABLE (1 << 20)
++#define MAC2_CLOCK_ENABLE (1 << 21)
++#define MAC_AHB_CLOCK_DIVIDER (0x07 << 16)
++#if defined(CONFIG_AST2300_FPGA_2) || defined(CONFIG_AST2300) || defined(CONFIG_AST3100) || defined(CONFIG_AST2400)
++#define MAC1_MDIO (1 << 31)
++#define MAC1_MDC (1 << 30)
++#define MAC1_PHY_LINK (1 << 0)
++#define MAC2_MDC_MDIO (1 << 2)
++#define MAC1_PHY_LINK (1 << 0)
++#define MAC2_PHY_LINK (1 << 1)
++#else
++#define MAC2_MDC_MDIO (1 << 20)
++#define MAC2_MII (1 << 21)
++#define MAC1_PHY_LINK (1 << 25)
++#define MAC2_PHY_LINK (1 << 26)
++#endif
++
++#if defined(CONFIG_AST1300)
++unsigned int aspeednic_iobase[1] = {CONFIG_MACREG_BASE};
++#else
++unsigned int aspeednic_iobase[CONFIG_ASPEED_MAC_NUMBER] = {
++ 0x1E660000, 0x1E680000};
++#endif
++
++#undef DEBUG_SROM
++#undef DEBUG_SROM2
++
++#undef UPDATE_SROM
++
++/* PCI Registers.
++ */
++#define PCI_CFDA_PSM 0x43
++
++#define CFRV_RN 0x000000f0 /* Revision Number */
++
++#define WAKEUP 0x00 /* Power Saving Wakeup */
++#define SLEEP 0x80 /* Power Saving Sleep Mode */
++
++#define DC2114x_BRK 0x0020 /* CFRV break between DC21142 & DC21143 */
++
++/* MAC chip register */
++#define ISR_REG 0x00 // interrups status register
++#define IER_REG 0x04 // interrupt maks register
++#define MAC_MADR_REG 0x08 // MAC address (Most significant)
++#define MAC_LADR_REG 0x0c // MAC address (Least significant)
++
++#define MAHT0_REG 0x10 // Multicast Address Hash Table 0 register
++#define MAHT1_REG 0x14 // Multicast Address Hash Table 1 register
++#define TXPD_REG 0x18 // Transmit Poll Demand register
++#define RXPD_REG 0x1c // Receive Poll Demand register
++#define TXR_BADR_REG 0x20 // Transmit Ring Base Address register
++#define RXR_BADR_REG 0x24 // Receive Ring Base Address register
++
++#define HPTXPD_REG 0x28 //
++#define HPTXR_BADR_REG 0x2c //
++
++#define ITC_REG 0x30 // interrupt timer control register
++#define APTC_REG 0x34 // Automatic Polling Timer control register
++#define DBLAC_REG 0x38 // DMA Burst Length and Arbitration control register
++
++#define DMAFIFOS_REG 0x3c //
++#define FEAR_REG 0x44 //
++#define TPAFCR_REG 0x48 //
++#define RBSR_REG 0x4c //for NC Body
++#define MACCR_REG 0x50 // MAC control register
++#define MACSR_REG 0x54 // MAC status register
++#define PHYCR_REG 0x60 // PHY control register
++#define PHYDATA_REG 0x64 // PHY Write Data register
++#define FCR_REG 0x68 // Flow Control register
++#define BPR_REG 0x6c // back pressure register
++#define WOLCR_REG 0x70 // Wake-On-Lan control register
++#define WOLSR_REG 0x74 // Wake-On-Lan status register
++#define WFCRC_REG 0x78 // Wake-up Frame CRC register
++#define WFBM1_REG 0x80 // wake-up frame byte mask 1st double word register
++#define WFBM2_REG 0x84 // wake-up frame byte mask 2nd double word register
++#define WFBM3_REG 0x88 // wake-up frame byte mask 3rd double word register
++#define WFBM4_REG 0x8c // wake-up frame byte mask 4th double word register
++
++
++// --------------------------------------------------------------------
++// MACCR_REG
++// --------------------------------------------------------------------
++
++#define SW_RST_bit (1UL<<31) // software reset/
++#define DIRPATH_bit (1UL<<21)
++#define RX_IPCS_FAIL_bit (1UL<<20) //
++#define RX_TCPCS_FAIL_bit (1UL<<19) //
++#define SPEED_100M_MODE_bit (1UL<<19)
++#define RX_UDPCS_FAIL_bit (1UL<<18) //
++#define RX_BROADPKT_bit (1UL<<17) // Receiving broadcast packet
++#define RX_MULTIPKT_bit (1UL<<16) // receiving multicast packet
++#define RX_HT_EN_bit (1UL<<15)
++#define RX_ALLADR_bit (1UL<<14) // not check incoming packet's destination address
++#define JUMBO_LF_bit (1UL<<13) //
++#define RX_RUNT_bit (1UL<<12) // Store incoming packet even its length is les than 64 byte
++#define CRC_CHK_bit (1UL<<11) //
++#define CRC_APD_bit (1UL<<10) // append crc to transmit packet
++#define GMAC_MODE_bit (1UL<<9) //
++#define FULLDUP_bit (1UL<<8) // full duplex
++#define ENRX_IN_HALFTX_bit (1UL<<7) //
++#define LOOP_EN_bit (1UL<<6) // Internal loop-back
++#define HPTXR_EN_bit (1UL<<5) //
++#define REMOVE_VLAN_bit (1UL<<4) //
++#define RXMAC_EN_bit (1UL<<3) // receiver enable
++#define TXMAC_EN_bit (1UL<<2) // transmitter enable
++#define RXDMA_EN_bit (1UL<<1) // enable DMA receiving channel
++#define TXDMA_EN_bit (1UL<<0) // enable DMA transmitting channel
++
++//---------------------------------------------------
++// PHY R/W Register Bit
++//---------------------------------------------------
++#define MIIWR (1UL<<27)
++#define MIIRD (1UL<<26)
++#define MDC_CYCTHR 0x34
++#define PHY_SPEED_MASK 0xC000
++#define PHY_DUPLEX_MASK 0x2000
++#define SPEED_1000M 0x02
++#define SPEED_100M 0x01
++#define SPEED_10M 0x00
++#define DUPLEX_FULL 0x01
++#define DUPLEX_HALF 0x00
++#define RESOLVED_BIT 0x800
++
++#define PHY_SPEED_DUPLEX_MASK 0x01E0
++#define PHY_100M_DUPLEX 0x0100
++#define PHY_100M_HALF 0x0080
++#define PHY_10M_DUPLEX 0x0040
++#define PHY_10M_HALF 0x0020
++
++
++
++/* Descriptor bits.
++ */
++#define TXDMA_OWN 0x80000000 /* Own Bit */
++#define RXPKT_RDY 0x00000000
++#define RXPKT_STATUS 0x80000000
++//#define EDORR 0x00008000 /* Receive End Of Ring */
++#define EDORR 0x40000000 /* Receive End Of Ring */
++#define LRS 0x10000000 /* Last Descriptor */
++#define RD_ES 0x00008000 /* Error Summary */
++//#define EDOTR 0x00008000 /* Transmit End Of Ring */
++#define EDOTR 0x40000000 /* Transmit End Of Ring */
++#define T_OWN 0x80000000 /* Own Bit */
++#define LTS 0x10000000 /* Last Segment */
++#define FTS 0x20000000 /* First Segment */
++#define CRC_ERR 0x00080000
++#define TD_ES 0x00008000 /* Error Summary */
++#define TD_SET 0x08000000 /* Setup Packet */
++#define RX_ERR 0x00040000
++#define FTL 0x00100000
++#define RUNT 0x00200000
++#define RX_ODD_NB 0x00400000
++
++#define POLL_DEMAND 1
++#define RESET_DE4X5(dev) { \
++ int i; \
++ i=INL(dev, MACCR_REG); \
++ udelay(1000); \
++ OUTL(dev, i | SW_RST_bit, MACCR_REG); \
++ for (; (INL(dev, MACCR_REG ) & SW_RST_bit) != 0; ) {udelay(1000);} \
++ OUTL(dev, 0, IER_REG ); \
++ }
++
++#define START_MAC(dev) { \
++ s32 omr; \
++ omr = INL(dev, MACCR_REG); \
++ omr |= RXMAC_EN_bit | TXMAC_EN_bit | RXDMA_EN_bit | TXDMA_EN_bit; \
++ OUTL(dev, omr, MACCR_REG); /* Enable the TX and/or RX */ \
++ }
++
++#define STOP_MAC(dev) { \
++ s32 omr; \
++ omr = INL(dev, MACCR_REG); \
++ omr &= ~(RXMAC_EN_bit | TXMAC_EN_bit | RXDMA_EN_bit | TXDMA_EN_bit); \
++ OUTL(dev, omr, MACCR_REG); /* Disable the TX and/or RX */ \
++ }
++
++#define NUM_RX_DESC PKTBUFSRX
++#define NUM_TX_DESC 1 /* Number of TX descriptors */
++#define RX_BUFF_SZ PKTSIZE_ALIGN
++#define TX_BUFF_SZ 1514
++
++#define TOUT_LOOP 1000000
++#define PHY_LOOP 250
++#define ETH_ALEN 6
++#define NCSI_LOOP 1500000
++#define RETRY_COUNT 1
++
++struct de4x5_desc {
++ volatile s32 status;
++ u32 des1;
++ u32 reserved;
++ u32 buf;
++};
++
++//PHY Information
++#define PHYID_VENDOR_MASK 0xfffffc00
++#define PHYID_VENDOR_MODEL_MASK 0xfffffff0
++#define PHYID_VENDOR_MARVELL 0x01410c00
++#define PHYID_VENDOR_BROADCOM 0x00406000
++#define PHYID_VENDOR_REALTEK 0x001cc800
++#define PHYID_RTL8201EL 0x001cc810
++#define PHYID_RTL8211 0x001cc910
++#define PHYID_BCM54612E 0x03625E6A
++
++//NCSI define & structure
++//NC-SI Command Packet
++typedef struct {
++//Ethernet Header
++ unsigned char DA[6];
++ unsigned char SA[6];
++ unsigned short EtherType; //DMTF NC-SI
++//NC-SI Control Packet
++ unsigned char MC_ID; //Management Controller should set this field to 0x00
++ unsigned char Header_Revision; //For NC-SI 1.0 spec, this field has to set 0x01
++ unsigned char Reserved_1; //Reserved has to set to 0x00
++ unsigned char IID; //Instance ID
++ unsigned char Command;
++ unsigned char Channel_ID;
++ unsigned short Payload_Length; //Payload Length = 12 bits, 4 bits are reserved
++ unsigned long Reserved_2;
++ unsigned long Reserved_3;
++} NCSI_Command_Packet;
++
++unsigned char Payload_Data[16];
++unsigned char Payload_Pad[4] = {0x00, 0x00, 0x00, 0x00};
++unsigned long Payload_Checksum = 0x00000000;
++
++
++//Command and Response Type
++#define CLEAR_INITIAL_STATE 0x00 //M
++#define SELECT_PACKAGE 0x01 //M
++#define DESELECT_PACKAGE 0x02 //M
++#define ENABLE_CHANNEL 0x03 //M
++#define DISABLE_CHANNEL 0x04 //M
++#define RESET_CHANNEL 0x05 //M
++#define ENABLE_CHANNEL_NETWORK_TX 0x06 //M
++#define DISABLE_CHANNEL_NETWORK_TX 0x07 //M
++#define AEN_ENABLE 0x08
++#define SET_LINK 0x09 //M
++#define GET_LINK_STATUS 0x0A //M
++#define SET_VLAN_FILTER 0x0B //M
++#define ENABLE_VLAN 0x0C //M
++#define DISABLE_VLAN 0x0D //M
++#define SET_MAC_ADDRESS 0x0E //M
++#define ENABLE_BROADCAST_FILTERING 0x10 //M
++#define DISABLE_BROADCAST_FILTERING 0x11 //M
++#define ENABLE_GLOBAL_MULTICAST_FILTERING 0x12
++#define DISABLE_GLOBAL_MULTICAST_FILTERING 0x13
++#define SET_NCSI_FLOW_CONTROL 0x14
++#define GET_VERSION_ID 0x15 //M
++#define GET_CAPABILITIES 0x16 //M
++#define GET_PARAMETERS 0x17 //M
++#define GET_CONTROLLER_PACKET_STATISTICS 0x18
++#define GET_NCSI_STATISTICS 0x19
++#define GET_NCSI_PASS_THROUGH_STATISTICS 0x1A
++
++//NC-SI Response Packet
++typedef struct {
++ unsigned char DA[6];
++ unsigned char SA[6];
++ unsigned short EtherType; //DMTF NC-SI
++//NC-SI Control Packet
++ unsigned char MC_ID; //Management Controller should set this field to 0x00
++ unsigned char Header_Revision; //For NC-SI 1.0 spec, this field has to set 0x01
++ unsigned char Reserved_1; //Reserved has to set to 0x00
++ unsigned char IID; //Instance ID
++ unsigned char Command;
++ unsigned char Channel_ID;
++ unsigned short Payload_Length; //Payload Length = 12 bits, 4 bits are reserved
++ unsigned short Reserved_2;
++ unsigned short Reserved_3;
++ unsigned short Reserved_4;
++ unsigned short Reserved_5;
++ unsigned short Response_Code;
++ unsigned short Reason_Code;
++ unsigned char Payload_Data[64];
++} NCSI_Response_Packet;
++
++NCSI_Command_Packet NCSI_Request;
++NCSI_Response_Packet NCSI_Respond;
++
++//Standard Response Code
++#define COMMAND_COMPLETED 0x00
++#define COMMAND_FAILED 0x01
++#define COMMAND_UNAVAILABLE 0x02
++#define COMMAND_UNSUPPORTED 0x03
++
++//Standard Reason Code
++#define NO_ERROR 0x0000
++#define INTERFACE_INITIALIZATION_REQUIRED 0x0001
++#define PARAMETER_IS_INVALID 0x0002
++#define CHANNEL_NOT_READY 0x0003
++#define PACKAGE_NOT_READY 0x0004
++#define INVALID_PAYLOAD_LENGTH 0x0005
++#define UNKNOWN_COMMAND_TYPE 0x7FFF
++
++
++struct AEN_Packet {
++//Ethernet Header
++ unsigned char DA[6];
++ unsigned char SA[6]; //Network Controller SA = FF:FF:FF:FF:FF:FF
++ unsigned short EtherType; //DMTF NC-SI
++//AEN Packet Format
++ unsigned char MC_ID; //Network Controller should set this field to 0x00
++ unsigned char Header_Revision; //For NC-SI 1.0 spec, this field has to set 0x01
++ unsigned char Reserved_1; //Reserved has to set to 0x00
++// unsigned char IID = 0x00; //Instance ID = 0 in Network Controller
++// unsigned char Command = 0xFF; //AEN = 0xFF
++ unsigned char Channel_ID;
++// unsigned short Payload_Length = 0x04; //Payload Length = 4 in Network Controller AEN Packet
++ unsigned long Reserved_2;
++ unsigned long Reserved_3;
++ unsigned char AEN_Type;
++// unsigned char Reserved_4[3] = {0x00, 0x00, 0x00};
++ unsigned long Optional_AEN_Data;
++ unsigned long Payload_Checksum;
++};
++
++//AEN Type
++#define LINK_STATUS_CHANGE 0x0
++#define CONFIGURATION_REQUIRED 0x1
++#define HOST_NC_DRIVER_STATUS_CHANGE 0x2
++
++typedef struct {
++ unsigned char Package_ID;
++ unsigned char Channel_ID;
++ unsigned long Capabilities_Flags;
++ unsigned long Broadcast_Packet_Filter_Capabilities;
++ unsigned long Multicast_Packet_Filter_Capabilities;
++ unsigned long Buffering_Capabilities;
++ unsigned long AEN_Control_Support;
++} NCSI_Capability;
++NCSI_Capability NCSI_Cap;
++
++//SET_MAC_ADDRESS
++#define UNICAST (0x00 << 5)
++#define MULTICAST (0x01 << 5)
++#define DISABLE_MAC_ADDRESS_FILTER 0x00
++#define ENABLE_MAC_ADDRESS_FILTER 0x01
++
++//GET_LINK_STATUS
++#define LINK_DOWN 0
++#define LINK_UP 1
++
++static struct de4x5_desc rx_ring[NUM_RX_DESC] __attribute__ ((aligned(32))); /* RX descriptor ring */
++static struct de4x5_desc tx_ring[NUM_TX_DESC] __attribute__ ((aligned(32))); /* TX descriptor ring */
++static int rx_new; /* RX descriptor ring pointer */
++static int tx_new; /* TX descriptor ring pointer */
++static unsigned char tx_buffer[NUM_TX_DESC][TX_BUFF_SZ] __attribute__ ((aligned(32)));
++static unsigned char rx_buffer[NUM_RX_DESC][RX_BUFF_SZ] __attribute__ ((aligned(32)));
++
++
++static char rxRingSize;
++static char txRingSize;
++static unsigned int InstanceID = 0;
++static int Retry = 0;
++
++static int aspeednic_init(struct eth_device* dev, bd_t* bis);
++static int aspeednic_send(struct eth_device* dev, volatile void *packet, int length);
++static int aspeednic_recv(struct eth_device* dev);
++static void aspeednic_halt(struct eth_device* dev);
++static void set_mac_address (struct eth_device* dev, bd_t* bis);
++static void phy_write_register (struct eth_device* dev, u8 PHY_Register, u8 PHY_Address, u16 PHY_Data);
++static u16 phy_read_register (struct eth_device* dev, u8 PHY_Register, u8 PHY_Address);
++static void set_mac_control_register(struct eth_device* dev);
++
++#if defined(CONFIG_E500)
++#define phys_to_bus(a) (a)
++#else
++#define phys_to_bus(a) pci_phys_to_mem((pci_dev_t)dev->priv, a)
++#endif
++
++static int INL(struct eth_device* dev, u_long addr)
++{
++ return le32_to_cpu(*(volatile u_long *)(addr + dev->iobase));
++}
++
++static void OUTL(struct eth_device* dev, int command, u_long addr)
++{
++ *(volatile u_long *)(addr + dev->iobase) = cpu_to_le32(command);
++}
++
++
++struct eth_device aspeednic_device[CONFIG_ASPEED_MAC_NUMBER];
++
++void NCSI_Struct_Initialize(void)
++{
++ unsigned long i;
++
++ for (i = 0; i < 6; i++) {
++ NCSI_Request.DA[i] = 0xFF;
++ NCSI_Respond.DA[i] = 0xFF;
++ NCSI_Respond.SA[i] = 0xFF;
++ }
++ NCSI_Request.EtherType = 0xF888;
++ NCSI_Request.MC_ID = 0;
++ NCSI_Request.Header_Revision = 0x01;
++ NCSI_Request.Reserved_1 = 0;
++ NCSI_Request.Reserved_2 = 0;
++ NCSI_Request.Reserved_3 = 0;
++ NCSI_Respond.EtherType = 0xF888;
++ NCSI_Respond.MC_ID = 0;
++ NCSI_Respond.Header_Revision = 0x01;
++ NCSI_Respond.Reserved_1 = 0;
++ NCSI_Respond.Reserved_2 = 0;
++ NCSI_Respond.Reserved_3 = 0;
++}
++
++int aspeednic_initialize(bd_t *bis)
++{
++ int card_number = 0;
++ unsigned int iobase, SCURegister;
++ struct eth_device* dev;
++
++#if defined(CONFIG_AST2300_FPGA_2) || defined(CONFIG_AST2300) || defined(CONFIG_AST3100) || defined(CONFIG_AST2400)
++//AST2300
++//MAC1 CLOCK/RESET/PHY_LINK/MDC_MDIO in SCU
++ SCURegister = le32_to_cpu(*(volatile u_long *)(SCU_BASE + SCU_RESET_CONTROL));
++ *(volatile u_long *)(SCU_BASE + SCU_RESET_CONTROL) = cpu_to_le32(SCURegister | 0x800);
++ udelay(100);
++ SCURegister = le32_to_cpu(*(volatile u_long *)(SCU_BASE + SCU_CLOCK_CONTROL));
++ *(volatile u_long *)(SCU_BASE + SCU_CLOCK_CONTROL) = cpu_to_le32(SCURegister & ~(MAC1_CLOCK_ENABLE));
++ udelay(10000);
++//Add Clock Selection in AST2300 A1, Please check the datasheet for more detail
++//The current sample code uses 0: H-PLL/2 because all EVBs have RGMII interface
++// SCURegister = le32_to_cpu(*(volatile u_long *)(SCU_BASE + SCU_CLOCK_SELECTION));
++// *(volatile u_long *)(SCU_BASE + SCU_CLOCK_SELECTION) = cpu_to_le32(SCURegister & ~(MAC_AHB_CLOCK_DIVIDER));
++ SCURegister = le32_to_cpu(*(volatile u_long *)(SCU_BASE + SCU_RESET_CONTROL));
++ *(volatile u_long *)(SCU_BASE + SCU_RESET_CONTROL) = cpu_to_le32(SCURegister & ~(0x800));
++ SCURegister = le32_to_cpu(*(volatile u_long *)(SCU_BASE + SCU_MULTIFUNCTION_PIN_CTL3_REG));
++ *(volatile u_long *)(SCU_BASE + SCU_MULTIFUNCTION_PIN_CTL3_REG) = cpu_to_le32(SCURegister | (MAC1_MDIO | MAC1_MDC));
++// SCURegister = le32_to_cpu(*(volatile u_long *)(SCU_BASE + SCU_MAC_CLOCK_DELAY));
++//Currently we use fix value in MAC timing on EVB
++// *(volatile u_long *)(SCU_BASE + SCU_MAC_CLOCK_DELAY) = CONFIG_MAC_INTERFACE_CLOCK_DELAY;
++#ifdef CONFIG_MAC1_PHY_LINK_INTERRUPT
++ SCURegister = le32_to_cpu(*(volatile u_long *)(SCU_BASE + SCU_MULTIFUNCTION_PIN_CTL1_REG));
++ *(volatile u_long *)(SCU_BASE + SCU_MULTIFUNCTION_PIN_CTL1_REG) = cpu_to_le32(SCURegister | (MAC1_PHY_LINK));
++#endif
++
++//MAC2 CLOCK/RESET/PHY_LINK/MDC_MDIO
++#ifdef CONFIG_MAC2_ENABLE
++ SCURegister = le32_to_cpu(*(volatile u_long *)(SCU_BASE + SCU_RESET_CONTROL));
++ *(volatile u_long *)(SCU_BASE + SCU_RESET_CONTROL) = cpu_to_le32(SCURegister | 0x1000);
++ udelay(10);
++ SCURegister = le32_to_cpu(*(volatile u_long *)(SCU_BASE + SCU_CLOCK_CONTROL));
++ *(volatile u_long *)(SCU_BASE + SCU_CLOCK_CONTROL) = cpu_to_le32(SCURegister & ~(MAC2_CLOCK_ENABLE));
++ udelay(10000);
++ SCURegister = le32_to_cpu(*(volatile u_long *)(SCU_BASE + SCU_RESET_CONTROL));
++ *(volatile u_long *)(SCU_BASE + SCU_RESET_CONTROL) = cpu_to_le32(SCURegister & ~(0x1000));
++ SCURegister = le32_to_cpu(*(volatile u_long *)(SCU_BASE + SCU_MULTIFUNCTION_PIN_CTL5_REG));
++ *(volatile u_long *)(SCU_BASE + SCU_MULTIFUNCTION_PIN_CTL5_REG) = cpu_to_le32(SCURegister | (MAC2_MDC_MDIO));
++#endif
++#ifdef CONFIG_MAC2_PHY_LINK_INTERRUPT
++ SCURegister = le32_to_cpu(*(volatile u_long *)(SCU_BASE + SCU_MULTIFUNCTION_PIN_CTL1_REG));
++ *(volatile u_long *)(SCU_BASE + SCU_MULTIFUNCTION_PIN_CTL1_REG) = cpu_to_le32(SCURegister | (MAC2_PHY_LINK));
++#endif
++#else
++//AST1100/AST2050/AST2100
++//MAC1 RESET/PHY_LINK in SCU
++ SCURegister = le32_to_cpu(*(volatile u_long *)(SCU_BASE + SCU_RESET_CONTROL));
++ *(volatile u_long *)(SCU_BASE + SCU_RESET_CONTROL) = cpu_to_le32(SCURegister & ~(0x800));
++#ifdef CONFIG_MAC1_PHY_LINK_INTERRUPT
++ SCURegister = le32_to_cpu(*(volatile u_long *)(SCU_BASE + SCU_PIN_MUX));
++ *(volatile u_long *)(SCU_BASE + SCU_PIN_MUX) = cpu_to_le32(SCURegister | (MAC1_PHY_LINK));
++#endif
++
++//MAC2
++#ifdef CONFIG_MAC2_ENABLE
++ SCURegister = le32_to_cpu(*(volatile u_long *)(SCU_BASE + SCU_RESET_CONTROL));
++ *(volatile u_long *)(SCU_BASE + SCU_RESET_CONTROL) = cpu_to_le32(SCURegister & ~(0x1000));
++ SCURegister = le32_to_cpu(*(volatile u_long *)(SCU_BASE + SCU_PIN_MUX));
++ *(volatile u_long *)(SCU_BASE + SCU_PIN_MUX) = cpu_to_le32(SCURegister | (MAC2_MDC_MDIO));
++#endif
++#ifdef CONFIG_MAC2_MII_ENABLE
++ SCURegister = le32_to_cpu(*(volatile u_long *)(SCU_BASE + SCU_PIN_MUX));
++ *(volatile u_long *)(SCU_BASE + SCU_PIN_MUX) = cpu_to_le32(SCURegister | (MAC2_MII));
++#endif
++#ifdef CONFIG_MAC2_PHY_LINK_INTERRUPT
++ SCURegister = le32_to_cpu(*(volatile u_long *)(SCU_BASE + SCU_PIN_MUX));
++ *(volatile u_long *)(SCU_BASE + SCU_PIN_MUX) = cpu_to_le32(SCURegister | (MAC2_PHY_LINK));
++#endif
++#endif
++
++ iobase = aspeednic_iobase[card_number];
++
++ dev = &aspeednic_device[card_number];
++
++
++ sprintf(dev->name, "aspeednic#%d", card_number);
++
++ dev->iobase = iobase;
++
++ if (CONFIG_MAC1_PHY_SETTING >= 1) {
++//NCSI Struct Initialize
++ NCSI_Struct_Initialize();
++ }
++//Set Scratch register (0x1E6E2040 D[15:14])(0x1E6E2041 D[7:6]) to inform kernel MAC1 driver
++ SCURegister = le32_to_cpu(*(volatile u_long *)(SCU_BASE + SCU_SCRATCH_REGISTER));
++ *(volatile u_long *)(SCU_BASE + SCU_SCRATCH_REGISTER) = cpu_to_le32((SCURegister & ~(0xc000)) | (CONFIG_MAC1_PHY_SETTING << 14));
++//Set Scratch register (0x1E6E2040 D[13:12])(0x1E6E2041 D[5:4]) to inform kernel MAC2 driver
++ SCURegister = le32_to_cpu(*(volatile u_long *)(SCU_BASE + SCU_SCRATCH_REGISTER));
++ *(volatile u_long *)(SCU_BASE + SCU_SCRATCH_REGISTER) = cpu_to_le32((SCURegister & ~(0x3000)) | (CONFIG_MAC2_PHY_SETTING << 12));
++
++
++ dev->init = aspeednic_init;
++ dev->halt = aspeednic_halt;
++ dev->send = aspeednic_send;
++ dev->recv = aspeednic_recv;
++
++ /* Ensure we're not sleeping. */
++ if (CONFIG_MAC1_PHY_SETTING >= 1) {
++ udelay(2000000); //2.0 sec
++ }
++ else {
++ udelay(10 * 1000);
++ }
++
++
++ dev->init(dev, bis);
++
++ eth_register(dev);
++
++
++ return card_number;
++}
++
++void Calculate_Checksum(unsigned char *buffer_base, int Length)
++{
++ unsigned int i, CheckSum = 0;
++ unsigned int Data, Data1;
++
++ for (i = 0; i < ((Length - 14) / 2); i++) {
++ Data = buffer_base[i * 2];
++ Data1 = buffer_base[i * 2 + 1];
++ CheckSum += ((Data << 8) + Data1);
++ }
++ Payload_Checksum = (~(CheckSum) + 1); //2's complement
++//Inverse for insert into buffer
++ Data = (Payload_Checksum & 0xFF000000) >> 24;
++ Data1 = (Payload_Checksum & 0x000000FF) << 24;
++ Payload_Checksum = (Payload_Checksum & 0x00FFFF00) + Data + Data1;
++ Data = (Payload_Checksum & 0x00FF0000) >> 8;
++ Data1 = (Payload_Checksum & 0x0000FF00) << 8;
++ Payload_Checksum = (Payload_Checksum & 0xFF0000FF) + Data + Data1;
++}
++
++void copy_data (int Length)
++{
++ memcpy ((unsigned char *)(tx_ring[tx_new].buf + 30), &Payload_Data, Length);
++ Calculate_Checksum((unsigned char *)(tx_ring[tx_new].buf + 14), 30 + Length);
++ memcpy ((unsigned char *)(tx_ring[tx_new].buf + 30 + Length), &Payload_Checksum, 4);
++}
++
++void NCSI_Rx (void)
++{
++ unsigned long status, length, i = 0;
++
++ do {
++ status = (s32)le32_to_cpu(rx_ring[rx_new].status);
++ i++;
++ } while (!(((status & RXPKT_STATUS) != 0) || (i >= NCSI_LOOP)));
++
++ if (i < NCSI_LOOP) {
++ if (status & LRS) {
++ length = (le32_to_cpu(rx_ring[rx_new].status) & 0x3FFF);
++ memcpy (&NCSI_Respond, (unsigned char *)rx_ring[rx_new].buf, length);
++ }
++ rx_ring[rx_new].status &= cpu_to_le32(0x7FFFFFFF);
++ rx_new = (rx_new + 1) % rxRingSize;
++ }
++}
++
++void DeSelect_Package (struct eth_device* dev, int Package_ID)
++{
++ unsigned long Combined_Channel_ID;
++
++//TX
++ do {
++ InstanceID++;
++ NCSI_Request.IID = InstanceID;
++ NCSI_Request.Command = DESELECT_PACKAGE;
++ Combined_Channel_ID = (Package_ID << 5) + 0x1F; //Internal Channel ID = 0x1F, 0x1F means all channel
++ NCSI_Request.Channel_ID = Combined_Channel_ID;
++ NCSI_Request.Payload_Length = 0;
++ memcpy ((unsigned char *)tx_ring[tx_new].buf, &NCSI_Request, 30);
++ copy_data (NCSI_Request.Payload_Length);
++ aspeednic_send (dev, (void *)tx_ring[tx_new].buf, 30 + NCSI_Request.Payload_Length + 4);
++//RX
++ NCSI_Rx();
++ if ((NCSI_Respond.IID != InstanceID) || (NCSI_Respond.Command != (DESELECT_PACKAGE | 0x80)) || (NCSI_Respond.Response_Code != COMMAND_COMPLETED)) {
++ printf ("Retry: Command = %x, Response_Code = %x\n", NCSI_Request.Command, NCSI_Respond.Response_Code);
++ Retry++;
++ InstanceID--;
++ }
++ else {
++ Retry = 0;
++ }
++ } while ((Retry != 0) && (Retry <= RETRY_COUNT));
++ Retry = 0;
++}
++
++int Select_Package (struct eth_device* dev, int Package_ID)
++{
++ unsigned long Combined_Channel_ID, Found = 0;
++
++//TX
++ do {
++ InstanceID++;
++ NCSI_Request.IID = InstanceID;
++ NCSI_Request.Command = SELECT_PACKAGE;
++ Combined_Channel_ID = (Package_ID << 5) + 0x1F; //Internal Channel ID = 0x1F
++ NCSI_Request.Channel_ID = Combined_Channel_ID;
++ NCSI_Request.Payload_Length = (4 << 8);
++ memcpy ((unsigned char *)tx_ring[tx_new].buf, &NCSI_Request, 30);
++ NCSI_Request.Payload_Length = 4;
++ memset ((void *)Payload_Data, 0, 4);
++ Payload_Data[3] = 1; //Arbitration Disable
++ copy_data (NCSI_Request.Payload_Length);
++ aspeednic_send (dev, (void *)tx_ring[tx_new].buf, 30 + NCSI_Request.Payload_Length + 4);
++//RX
++ NCSI_Rx();
++ if ((NCSI_Respond.IID != InstanceID) || (NCSI_Respond.Command != (SELECT_PACKAGE | 0x80)) || (NCSI_Respond.Response_Code != COMMAND_COMPLETED)) {
++ printf ("Retry: Command = %x, Response_Code = %x\n", NCSI_Request.Command, NCSI_Respond.Response_Code);
++ Retry++;
++ Found = 0;
++ InstanceID--;
++ }
++ else {
++ Retry = 0;
++ Found = 1;
++ }
++ } while ((Retry != 0) && (Retry <= RETRY_COUNT));
++ Retry = 0;
++
++ return Found;
++}
++
++void DeSelect_Active_Package (struct eth_device* dev)
++{
++ unsigned long Combined_Channel_ID;
++//TX
++ do {
++ InstanceID++;
++ NCSI_Request.IID = InstanceID;
++ NCSI_Request.Command = DESELECT_PACKAGE;
++ Combined_Channel_ID = (NCSI_Cap.Package_ID << 5) + 0x1F; //Internal Channel ID = 0x1F, 0x1F means all channel
++ NCSI_Request.Channel_ID = Combined_Channel_ID;
++ NCSI_Request.Payload_Length = 0;
++ memcpy ((unsigned char *)tx_ring[tx_new].buf, &NCSI_Request, 30);
++ copy_data (NCSI_Request.Payload_Length);
++ aspeednic_send (dev, (void *)tx_ring[tx_new].buf, 30 + NCSI_Request.Payload_Length + 4);
++//RX
++ NCSI_Rx();
++ if ((NCSI_Respond.IID != InstanceID) || (NCSI_Respond.Command != (DESELECT_PACKAGE | 0x80)) || (NCSI_Respond.Response_Code != COMMAND_COMPLETED)) {
++ printf ("Retry: Command = %x, Response_Code = %x\n", NCSI_Request.Command, NCSI_Respond.Response_Code);
++ Retry++;
++ InstanceID--;
++ }
++ else {
++ Retry = 0;
++ }
++ } while ((Retry != 0) && (Retry <= RETRY_COUNT));
++ Retry = 0;
++}
++
++int Select_Active_Package (struct eth_device* dev)
++{
++ unsigned long Combined_Channel_ID, Found = 0;
++//TX
++ do {
++ InstanceID++;
++ NCSI_Request.IID = InstanceID;
++ NCSI_Request.Command = SELECT_PACKAGE;
++ Combined_Channel_ID = (NCSI_Cap.Package_ID << 5) + 0x1F; //Internal Channel ID = 0x1F
++ NCSI_Request.Channel_ID = Combined_Channel_ID;
++ NCSI_Request.Payload_Length = (4 << 8);
++ memcpy ((unsigned char *)tx_ring[tx_new].buf, &NCSI_Request, 30);
++ NCSI_Request.Payload_Length = 4;
++ memset ((void *)Payload_Data, 0, 4);
++ Payload_Data[3] = 1; //Arbitration Disable
++ copy_data (NCSI_Request.Payload_Length);
++ aspeednic_send (dev, (void *)tx_ring[tx_new].buf, 30 + NCSI_Request.Payload_Length + 4);
++//RX
++ NCSI_Rx();
++ if ((NCSI_Respond.IID != InstanceID) || (NCSI_Respond.Command != (SELECT_PACKAGE | 0x80)) || (NCSI_Respond.Response_Code != COMMAND_COMPLETED)) {
++ printf ("Retry: Command = %x, Response_Code = %x\n", NCSI_Request.Command, NCSI_Respond.Response_Code);
++ Retry++;
++ Found = 0;
++ InstanceID--;
++ }
++ else {
++ Retry = 0;
++ Found = 1;
++ }
++ } while ((Retry != 0) && (Retry <= RETRY_COUNT));
++ Retry = 0;
++
++ return Found;
++}
++
++int Clear_Initial_State (struct eth_device* dev, int Channel_ID)
++{
++ unsigned long Combined_Channel_ID, Found = 0;
++//TX
++ do {
++ InstanceID++;
++ NCSI_Request.IID = InstanceID;
++ NCSI_Request.Command = CLEAR_INITIAL_STATE;
++ Combined_Channel_ID = (NCSI_Cap.Package_ID << 5) + Channel_ID; //Internal Channel ID = 0
++ NCSI_Request.Channel_ID = Combined_Channel_ID;
++ NCSI_Request.Payload_Length = 0;
++ memcpy ((unsigned char *)tx_ring[tx_new].buf, &NCSI_Request, 30);
++ copy_data (NCSI_Request.Payload_Length);
++ aspeednic_send (dev, (void *)tx_ring[tx_new].buf, 30 + NCSI_Request.Payload_Length + 4);
++//RX
++ NCSI_Rx();
++ if ((NCSI_Respond.IID != InstanceID) || (NCSI_Respond.Command != (CLEAR_INITIAL_STATE | 0x80)) || (NCSI_Respond.Response_Code != COMMAND_COMPLETED)) {
++ printf ("Retry: Command = %x, Response_Code = %x\n", NCSI_Request.Command, NCSI_Respond.Response_Code);
++ Retry++;
++ Found = 0;
++ InstanceID--;
++ }
++ else {
++ Retry = 0;
++ Found = 1;
++ }
++ } while ((Retry != 0) && (Retry <= RETRY_COUNT));
++ Retry = 0;
++
++ return Found;
++}
++
++void Get_Version_ID (struct eth_device* dev)
++{
++ unsigned long Combined_Channel_ID;
++//TX
++ do {
++ InstanceID++;
++ NCSI_Request.IID = InstanceID;
++ NCSI_Request.Command = GET_VERSION_ID;
++ Combined_Channel_ID = (NCSI_Cap.Package_ID << 5) + NCSI_Cap.Channel_ID;
++ NCSI_Request.Channel_ID = Combined_Channel_ID;
++ NCSI_Request.Payload_Length = 0;
++ memcpy ((unsigned char *)tx_ring[tx_new].buf, &NCSI_Request, 30);
++ copy_data (NCSI_Request.Payload_Length);
++ aspeednic_send (dev, (void *)tx_ring[tx_new].buf, 30 + NCSI_Request.Payload_Length + 4);
++//RX
++ NCSI_Rx();
++ if ((NCSI_Respond.IID != InstanceID) || (NCSI_Respond.Command != (GET_VERSION_ID | 0x80)) || (NCSI_Respond.Response_Code != COMMAND_COMPLETED)) {
++ printf ("Retry: Command = %x, Response_Code = %x\n", NCSI_Request.Command, NCSI_Respond.Response_Code);
++ Retry++;
++ InstanceID--;
++ }
++ else {
++ Retry = 0;
++ }
++ } while ((Retry != 0) && (Retry <= RETRY_COUNT));
++ Retry = 0;
++}
++
++void Get_Capabilities (struct eth_device* dev)
++{
++ unsigned long Combined_Channel_ID;
++//TX
++ do {
++ InstanceID++;
++ NCSI_Request.IID = InstanceID;
++ NCSI_Request.Command = GET_CAPABILITIES;
++ Combined_Channel_ID = (NCSI_Cap.Package_ID << 5) + NCSI_Cap.Channel_ID;
++ NCSI_Request.Channel_ID = Combined_Channel_ID;
++ NCSI_Request.Payload_Length = 0;
++ memcpy ((unsigned char *)tx_ring[tx_new].buf, &NCSI_Request, 30);
++ copy_data (NCSI_Request.Payload_Length);
++ aspeednic_send (dev, (void *)tx_ring[tx_new].buf, 30 + NCSI_Request.Payload_Length + 4);
++//RX
++ NCSI_Rx();
++ if ((NCSI_Respond.IID != InstanceID) || (NCSI_Respond.Command != (GET_CAPABILITIES | 0x80)) || (NCSI_Respond.Response_Code != COMMAND_COMPLETED)) {
++ printf ("Retry: Command = %x, Response_Code = %x\n", NCSI_Request.Command, NCSI_Respond.Response_Code);
++ Retry++;
++ InstanceID--;
++ }
++ else {
++ Retry = 0;
++ NCSI_Cap.Capabilities_Flags = NCSI_Respond.Payload_Data[0];
++ NCSI_Cap.Broadcast_Packet_Filter_Capabilities = NCSI_Respond.Payload_Data[1];
++ NCSI_Cap.Multicast_Packet_Filter_Capabilities = NCSI_Respond.Payload_Data[2];
++ NCSI_Cap.Buffering_Capabilities = NCSI_Respond.Payload_Data[3];
++ NCSI_Cap.AEN_Control_Support = NCSI_Respond.Payload_Data[4];
++ }
++ } while ((Retry != 0) && (Retry <= RETRY_COUNT));
++ Retry = 0;
++}
++
++void Enable_Set_MAC_Address (struct eth_device* dev)
++{
++ unsigned long Combined_Channel_ID, i;
++//TX
++ do {
++ InstanceID++;
++ NCSI_Request.IID = InstanceID;
++ NCSI_Request.Command = SET_MAC_ADDRESS;
++ Combined_Channel_ID = (NCSI_Cap.Package_ID << 5) + NCSI_Cap.Channel_ID;
++ NCSI_Request.Channel_ID = Combined_Channel_ID;
++ NCSI_Request.Payload_Length = (8 << 8);
++ memcpy ((unsigned char *)tx_ring[tx_new].buf, &NCSI_Request, 30);
++ NCSI_Request.Payload_Length = 8;
++ for (i = 0; i < 6; i++) {
++ Payload_Data[i] = NCSI_Request.SA[i];
++ }
++ Payload_Data[6] = 1; //MAC Address Num = 1 --> address filter 1, fixed in sample code
++ Payload_Data[7] = UNICAST + 0 + ENABLE_MAC_ADDRESS_FILTER; //AT + Reserved + E
++ copy_data (NCSI_Request.Payload_Length);
++ aspeednic_send (dev, (void *)tx_ring[tx_new].buf, 30 + NCSI_Request.Payload_Length + 4);
++//RX
++ NCSI_Rx();
++ if ((NCSI_Respond.IID != InstanceID) || (NCSI_Respond.Command != (SET_MAC_ADDRESS | 0x80)) || (NCSI_Respond.Response_Code != COMMAND_COMPLETED)) {
++ printf ("Retry: Command = %x, Response_Code = %x\n", NCSI_Request.Command, NCSI_Respond.Response_Code);
++ Retry++;
++ InstanceID--;
++ }
++ } while ((Retry != 0) && (Retry <= RETRY_COUNT));
++ Retry = 0;
++}
++
++void Enable_Broadcast_Filter (struct eth_device* dev)
++{
++ unsigned long Combined_Channel_ID;
++//TX
++ do {
++ InstanceID++;
++ NCSI_Request.IID = InstanceID;
++ NCSI_Request.Command = ENABLE_BROADCAST_FILTERING;
++ Combined_Channel_ID = (NCSI_Cap.Package_ID << 5) + NCSI_Cap.Channel_ID;
++ NCSI_Request.Channel_ID = Combined_Channel_ID;
++ NCSI_Request.Payload_Length = (4 << 8);
++ memcpy ((unsigned char *)tx_ring[tx_new].buf, &NCSI_Request, 30);
++ NCSI_Request.Payload_Length = 4;
++ memset ((void *)Payload_Data, 0, 4);
++ Payload_Data[3] = 0xF; //ARP, DHCP, NetBIOS
++ copy_data (NCSI_Request.Payload_Length);
++ aspeednic_send (dev, (void *)tx_ring[tx_new].buf, 30 + NCSI_Request.Payload_Length + 4);
++//RX
++ NCSI_Rx();
++ if ((NCSI_Respond.IID != InstanceID) || (NCSI_Respond.Command != (ENABLE_BROADCAST_FILTERING | 0x80)) || (NCSI_Respond.Response_Code != COMMAND_COMPLETED)) {
++ printf ("Retry: Command = %x, Response_Code = %x\n", NCSI_Request.Command, NCSI_Respond.Response_Code);
++ Retry++;
++ InstanceID--;
++ }
++ else {
++ Retry = 0;
++ }
++ } while ((Retry != 0) && (Retry <= RETRY_COUNT));
++ Retry = 0;
++}
++
++void Enable_AEN (struct eth_device* dev)
++{
++ unsigned long Combined_Channel_ID;
++//TX
++ do {
++ InstanceID++;
++ NCSI_Request.IID = InstanceID;
++ NCSI_Request.Command = AEN_ENABLE;
++ Combined_Channel_ID = (NCSI_Cap.Package_ID << 5) + NCSI_Cap.Channel_ID;
++ NCSI_Request.Channel_ID = Combined_Channel_ID;
++ NCSI_Request.Payload_Length = (8 << 8);
++ memcpy ((unsigned char *)tx_ring[tx_new].buf, &NCSI_Request, 30);
++ NCSI_Request.Payload_Length = 8;
++ memset ((void *)Payload_Data, 0, 8);
++ Payload_Data[3] = 0x00; //MC ID
++ Payload_Data[7] = 0x01; //Link Status only
++ copy_data (NCSI_Request.Payload_Length);
++ aspeednic_send (dev, (void *)tx_ring[tx_new].buf, 30 + NCSI_Request.Payload_Length + 4);
++//RX
++ NCSI_Rx();
++ if ((NCSI_Respond.IID != InstanceID) || (NCSI_Respond.Command != (AEN_ENABLE | 0x80)) || (NCSI_Respond.Response_Code != COMMAND_COMPLETED)) {
++ printf ("Retry: Command = %x, Response_Code = %x\n", NCSI_Request.Command, NCSI_Respond.Response_Code);
++ Retry++;
++ InstanceID--;
++ }
++ else {
++ Retry = 0;
++ }
++ } while ((Retry != 0) && (Retry <= RETRY_COUNT));
++ Retry = 0;
++}
++
++void Enable_Network_TX (struct eth_device* dev)
++{
++ unsigned long Combined_Channel_ID;
++//TX
++ do {
++ InstanceID++;
++ NCSI_Request.IID = InstanceID;
++ NCSI_Request.Command = ENABLE_CHANNEL_NETWORK_TX;
++ Combined_Channel_ID = (NCSI_Cap.Package_ID << 5) + NCSI_Cap.Channel_ID;
++ NCSI_Request.Channel_ID = Combined_Channel_ID;
++ NCSI_Request.Payload_Length = 0;
++ memcpy ((unsigned char *)tx_ring[tx_new].buf, &NCSI_Request, 30);
++ copy_data (NCSI_Request.Payload_Length);
++ aspeednic_send (dev, (void *)tx_ring[tx_new].buf, 30 + NCSI_Request.Payload_Length + 4);
++//RX
++ NCSI_Rx();
++ if ((NCSI_Respond.IID != InstanceID) || (NCSI_Respond.Command != (ENABLE_CHANNEL_NETWORK_TX | 0x80)) || (NCSI_Respond.Response_Code != COMMAND_COMPLETED)) {
++ printf ("Retry: Command = %x, Response_Code = %x\n", NCSI_Request.Command, NCSI_Respond.Response_Code);
++ Retry++;
++ InstanceID--;
++ }
++ else {
++ Retry = 0;
++ }
++ } while ((Retry != 0) && (Retry <= RETRY_COUNT));
++ Retry = 0;
++}
++
++void Disable_Network_TX (struct eth_device* dev)
++{
++ unsigned long Combined_Channel_ID;
++//TX
++ do {
++ InstanceID++;
++ NCSI_Request.IID = InstanceID;
++ NCSI_Request.Command = DISABLE_CHANNEL_NETWORK_TX;
++ Combined_Channel_ID = (NCSI_Cap.Package_ID << 5) + NCSI_Cap.Channel_ID;
++ NCSI_Request.Channel_ID = Combined_Channel_ID;
++ NCSI_Request.Payload_Length = 0;
++ memcpy ((unsigned char *)tx_ring[tx_new].buf, &NCSI_Request, 30);
++ copy_data (NCSI_Request.Payload_Length);
++ aspeednic_send (dev, (void *)tx_ring[tx_new].buf, 30 + NCSI_Request.Payload_Length + 4);
++//RX
++ NCSI_Rx();
++ if ((NCSI_Respond.IID != InstanceID) || (NCSI_Respond.Command != (DISABLE_CHANNEL_NETWORK_TX | 0x80)) || (NCSI_Respond.Response_Code != COMMAND_COMPLETED)) {
++ printf ("Retry: Command = %x, Response_Code = %x\n", NCSI_Request.Command, NCSI_Respond.Response_Code);
++ Retry++;
++ InstanceID--;
++ }
++ else {
++ Retry = 0;
++ }
++ } while ((Retry != 0) && (Retry <= RETRY_COUNT));
++ Retry = 0;
++}
++
++void Enable_Channel (struct eth_device* dev)
++{
++ unsigned long Combined_Channel_ID;
++//TX
++ do {
++ InstanceID++;
++ NCSI_Request.IID = InstanceID;
++ NCSI_Request.Command = ENABLE_CHANNEL;
++ Combined_Channel_ID = (NCSI_Cap.Package_ID << 5) + NCSI_Cap.Channel_ID;
++ NCSI_Request.Channel_ID = Combined_Channel_ID;
++ NCSI_Request.Payload_Length = 0;
++ memcpy ((unsigned char *)tx_ring[tx_new].buf, &NCSI_Request, 30);
++ copy_data (NCSI_Request.Payload_Length);
++ aspeednic_send (dev, (void *)tx_ring[tx_new].buf, 30 + NCSI_Request.Payload_Length + 4);
++//RX
++ NCSI_Rx();
++ if ((NCSI_Respond.IID != InstanceID) || (NCSI_Respond.Command != (ENABLE_CHANNEL | 0x80)) || (NCSI_Respond.Response_Code != COMMAND_COMPLETED)) {
++ printf ("Retry: Command = %x, Response_Code = %x\n", NCSI_Request.Command, NCSI_Respond.Response_Code);
++ Retry++;
++ InstanceID--;
++ }
++ else {
++ Retry = 0;
++ }
++ } while ((Retry != 0) && (Retry <= RETRY_COUNT));
++ Retry = 0;
++}
++
++void Disable_Channel (struct eth_device* dev)
++{
++ unsigned long Combined_Channel_ID;
++//TX
++ do {
++ InstanceID++;
++ NCSI_Request.IID = InstanceID;
++ NCSI_Request.Command = DISABLE_CHANNEL;
++ Combined_Channel_ID = (NCSI_Cap.Package_ID << 5) + NCSI_Cap.Channel_ID;
++ NCSI_Request.Channel_ID = Combined_Channel_ID;
++ NCSI_Request.Payload_Length = (4 << 8);
++ memcpy ((unsigned char *)tx_ring[tx_new].buf, &NCSI_Request, 30);
++ NCSI_Request.Payload_Length = 4;
++ memset ((void *)Payload_Data, 0, 4);
++ Payload_Data[3] = 0x1; //ALD
++ copy_data (NCSI_Request.Payload_Length);
++ aspeednic_send (dev, (void *)tx_ring[tx_new].buf, 30 + NCSI_Request.Payload_Length + 4);
++//RX
++ NCSI_Rx();
++ if ((NCSI_Respond.IID != InstanceID) || (NCSI_Respond.Command != (DISABLE_CHANNEL | 0x80)) || (NCSI_Respond.Response_Code != COMMAND_COMPLETED)) {
++ printf ("Retry: Command = %x, Response_Code = %x\n", NCSI_Request.Command, NCSI_Respond.Response_Code);
++ Retry++;
++ InstanceID--;
++ }
++ else {
++ Retry = 0;
++ }
++ } while ((Retry != 0) && (Retry <= RETRY_COUNT));
++ Retry = 0;
++}
++
++int Get_Link_Status (struct eth_device* dev)
++{
++ unsigned long Combined_Channel_ID;
++//TX
++ do {
++ InstanceID++;
++ NCSI_Request.IID = InstanceID;
++ NCSI_Request.Command = GET_LINK_STATUS;
++ Combined_Channel_ID = (NCSI_Cap.Package_ID << 5) + NCSI_Cap.Channel_ID;
++ NCSI_Request.Channel_ID = Combined_Channel_ID;
++ NCSI_Request.Payload_Length = 0;
++ memcpy ((unsigned char *)tx_ring[tx_new].buf, &NCSI_Request, 30);
++ copy_data (NCSI_Request.Payload_Length);
++ aspeednic_send (dev, (void *)tx_ring[tx_new].buf, 30 + NCSI_Request.Payload_Length + 4);
++//RX
++ NCSI_Rx();
++ if ((NCSI_Respond.IID != InstanceID) || (NCSI_Respond.Command != (GET_LINK_STATUS | 0x80)) || (NCSI_Respond.Response_Code != COMMAND_COMPLETED)) {
++ printf ("Retry: Command = %x, Response_Code = %x\n", NCSI_Request.Command, NCSI_Respond.Response_Code);
++ Retry++;
++ InstanceID--;
++ }
++ else {
++ Retry = 0;
++ }
++ } while ((Retry != 0) && (Retry <= RETRY_COUNT));
++ Retry = 0;
++ if (NCSI_Respond.Payload_Data[3] & 0x40) {
++ return (NCSI_Respond.Payload_Data[3] & 0x01); //Link Up or Not
++ }
++ else {
++ return 0; //Auto Negotiate did not finish
++ }
++}
++
++void Set_Link (struct eth_device* dev)
++{
++ unsigned long Combined_Channel_ID;
++//TX
++ do {
++ InstanceID++;
++ NCSI_Request.IID = InstanceID;
++ NCSI_Request.Command = SET_LINK;
++ Combined_Channel_ID = (NCSI_Cap.Package_ID << 5) + NCSI_Cap.Channel_ID;
++ NCSI_Request.Channel_ID = Combined_Channel_ID;
++ NCSI_Request.Payload_Length = (8 << 8);
++ memcpy ((unsigned char *)tx_ring[tx_new].buf, &NCSI_Request, 30);
++ NCSI_Request.Payload_Length = 8;
++ memset ((void *)Payload_Data, 0, 8);
++ Payload_Data[2] = 0x02; //full duplex
++ Payload_Data[3] = 0x04; //100M, auto-disable
++ copy_data (NCSI_Request.Payload_Length);
++ aspeednic_send (dev, (void *)tx_ring[tx_new].buf, 30 + NCSI_Request.Payload_Length + 4);
++//RX
++ NCSI_Rx();
++ if ((NCSI_Respond.IID != InstanceID) || (NCSI_Respond.Command != (SET_LINK | 0x80)) || (NCSI_Respond.Response_Code != COMMAND_COMPLETED)) {
++ printf ("Retry: Command = %x, Response_Code = %x\n", NCSI_Request.Command, NCSI_Respond.Response_Code);
++ Retry++;
++ InstanceID--;
++ }
++ else {
++ Retry = 0;
++ }
++ } while ((Retry != 0) && (Retry <= RETRY_COUNT));
++ Retry = 0;
++}
++
++static int aspeednic_init(struct eth_device* dev, bd_t* bis)
++{
++ unsigned long i, Package_Found = 0, Channel_Found = 0, Re_Send = 0, Link_Status;
++
++ RESET_DE4X5(dev);
++ set_mac_address (dev, bis);
++ set_mac_control_register (dev);
++
++ for (i = 0; i < NUM_RX_DESC; i++) {
++ rx_ring[i].status = cpu_to_le32(RXPKT_RDY + RX_BUFF_SZ);
++ rx_ring[i].buf = (u32)(&rx_buffer[i]);
++ rx_ring[i].reserved = 0;
++ }
++
++ for (i=0; i < NUM_TX_DESC; i++) {
++ tx_ring[i].status = 0;
++ tx_ring[i].des1 = 0;
++ tx_ring[i].buf = (u32)(&tx_buffer[i]);
++ tx_ring[i].reserved = 0;
++ }
++
++ rxRingSize = NUM_RX_DESC;
++ txRingSize = NUM_TX_DESC;
++
++ rx_ring[rxRingSize - 1].status |= cpu_to_le32(EDORR);
++ tx_ring[txRingSize - 1].status |= cpu_to_le32(EDOTR);
++
++ OUTL(dev, ((u32) &tx_ring), TXR_BADR_REG);
++ OUTL(dev, ((u32) &rx_ring), RXR_BADR_REG);
++
++ START_MAC(dev);
++
++ tx_new = 0;
++ rx_new = 0;
++
++ if (CONFIG_MAC1_PHY_SETTING >= 1) {
++//NCSI Start
++//DeSelect Package/ Select Package
++ for (i = 0; i < 4; i++) {
++ DeSelect_Package (dev, i);
++ Package_Found = Select_Package (dev, i);
++ if (Package_Found == 1) {
++//AST2100/AST2050/AST1100 supports 1 package only in current firmware version
++ NCSI_Cap.Package_ID = i;
++// Package_Found = 0;
++ break;
++ }
++ }
++ if (Package_Found != 0) {
++//Initiali State
++ for (i = 0; i < 2; i++) { //Suppose 2 channels in current version, You could modify it to 0x1F to support 31 channels
++ Channel_Found = Clear_Initial_State(dev, i);
++ if (Channel_Found == 1) {
++ NCSI_Cap.Channel_ID = i;
++ printf ("Found NCSI Network Controller at (%d, %d)\n", NCSI_Cap.Package_ID, NCSI_Cap.Channel_ID);
++//Get Version and Capabilities
++ Get_Version_ID(dev);
++ Get_Capabilities(dev);
++ Select_Active_Package(dev);
++//Configuration
++ Enable_Set_MAC_Address(dev);
++ Enable_Broadcast_Filter(dev);
++//Enable TX
++ Enable_Network_TX(dev);
++//Enable Channel
++ Enable_Channel(dev);
++//Get Link Status
++ Re_Get_Link_Status:
++ Link_Status = Get_Link_Status(dev);
++ if (Link_Status == LINK_UP) {
++ printf ("Using NCSI Network Controller (%d, %d)\n", NCSI_Cap.Package_ID, NCSI_Cap.Channel_ID);
++ break;
++ }
++ else if ((Link_Status == LINK_DOWN) && (Re_Send < 2)) {
++ Re_Send++;
++ goto Re_Get_Link_Status;
++ }
++//Disable TX
++ Disable_Network_TX(dev);
++//Disable Channel
++// Disable_Channel(dev);
++ Re_Send = 0;
++ Channel_Found = 0;
++ }
++ }
++ }
++ }
++ return 1;
++}
++
++static int aspeednic_send(struct eth_device* dev, volatile void *packet, int length)
++{
++ int status = -1, oldlength = 0, fail = 0;
++ int i;
++
++ if (length <= 0) {
++ printf("%s: bad packet size: %d\n", dev->name, length);
++ goto Done;
++ }
++
++
++ for(i = 0; (tx_ring[tx_new].status & cpu_to_le32(TXDMA_OWN)) == 0x80000000; i++) {
++ if (i >= TOUT_LOOP) {
++ printf("%s: tx error buffer not ready\n", dev->name);
++ fail = 1;
++ goto Done;
++ }
++ }
++
++
++ if (length < 60) {
++ oldlength = length;
++// memset ((void *)cpu_to_le32((u32) (packet + length)), 0, 60 - length);
++ length = 60;
++ }
++ tx_ring[tx_new].buf = cpu_to_le32(((u32) packet));
++ tx_ring[tx_new].status &= (~(0x3FFF));
++ tx_ring[tx_new].status |= cpu_to_le32(LTS | FTS | length);
++ tx_ring[tx_new].status |= cpu_to_le32(TXDMA_OWN);
++
++ OUTL(dev, POLL_DEMAND, TXPD_REG);
++
++ for (i = 0; (tx_ring[tx_new].status & cpu_to_le32(TXDMA_OWN)) == 0x80000000; i++)
++ {
++ if (i >= TOUT_LOOP)
++ {
++ printf(".%s: tx buffer not ready\n", dev->name);
++ fail = 1;
++ goto Done;
++ }
++ }
++
++ if (fail != 1) {
++ status = oldlength;
++ }
++
++ Done:
++ tx_new = (tx_new+1) % NUM_TX_DESC;
++
++ return status;
++}
++
++static int aspeednic_recv(struct eth_device* dev)
++{
++ s32 status;
++ int length = 0;
++
++ for ( ; ; )
++ {
++ status = (s32)le32_to_cpu(rx_ring[rx_new].status);
++
++ if ((status & RXPKT_STATUS) == 0) {
++ break;
++ }
++
++ if (status & LRS) {
++ /* Valid frame status.
++ */
++ if (status & (RX_ERR | CRC_ERR | FTL | RUNT | RX_ODD_NB)) {
++
++ /* There was an error.
++ */
++ printf("RX error status = 0x%08X\n", status);
++ } else {
++ /* A valid frame received.
++ */
++ length = (le32_to_cpu(rx_ring[rx_new].status) & 0x3FFF);
++ debug("%s(): RX buffer %d, %x received\n",
++ __func__, rx_new, length);
++
++
++ /* Pass the packet up to the protocol
++ * layers.
++ */
++ NetReceive(rx_buffer[rx_new], length - 4);
++ }
++
++ /* Change buffer ownership for this frame, back
++ * to the adapter.
++ */
++ rx_ring[rx_new].status &= cpu_to_le32(0x7FFFFFFF);
++// rx_ring[rx_new].status = cpu_to_le32(RXPKT_RDY);
++ }
++
++ /* Update entry information.
++ */
++ rx_new = (rx_new + 1) % rxRingSize;
++ }
++
++ return length;
++}
++
++static void aspeednic_halt(struct eth_device* dev)
++{
++ STOP_MAC(dev);
++}
++
++static void set_mac_address (struct eth_device* dev, bd_t* bis)
++{
++ unsigned char mac_address[6]; // 6 bytes mac address
++ unsigned char ethaddress[20]; // string for setenv function
++ char *s;
++ int i, env; // env variable 0: eeprom, 1: environment parameters
++
++ s = getenv ("eeprom");
++ env = (s && (*s == 'y')) ? 0 : 1;
++
++ if (env == 0) {
++ env = 1;
++ eeprom_init ();
++ eeprom_read (0xA0, 0, mac_address, 6);
++
++ for (i = 0; i < 6; i++) {
++ if (mac_address[i] != 0xFF) {
++ env = 0; //Suppose not all 0xFF is valid
++ }
++ }
++ }
++
++ if (env == 0) { // EEPROM
++ sprintf (ethaddress, "%02X:%02X:%02X:%02X:%02X:%02X", mac_address[0], mac_address[1], mac_address[2], mac_address[3], mac_address[4], mac_address[5]);
++ setenv ("ethaddr", ethaddress);
++ OUTL(dev, ((mac_address[2] << 24) | (mac_address[3] << 16) | (mac_address[4] << 8) | mac_address[5]), MAC_LADR_REG);
++ OUTL(dev, ((mac_address[0] << 8) | mac_address[1]), MAC_MADR_REG);
++ if (CONFIG_MAC1_PHY_SETTING >= 1) {
++ for (i = 0; i < 6; i++) {
++ NCSI_Request.SA[i] = mac_address[i];
++ }
++ }
++ }
++ else { // Environment Parameters
++ OUTL(dev, ((bis->bi_enetaddr[2] << 24) | (bis->bi_enetaddr[3] << 16) | (bis->bi_enetaddr[4] << 8) | bis->bi_enetaddr[5]), MAC_LADR_REG);
++ OUTL(dev, ((bis->bi_enetaddr[0] << 8) | bis->bi_enetaddr[1]), MAC_MADR_REG);
++ if (CONFIG_MAC1_PHY_SETTING >= 1) {
++ for (i = 0; i < 6; i++) {
++ NCSI_Request.SA[i] = bis->bi_enetaddr[i];
++ }
++ }
++ }
++
++}
++
++
++static u16 phy_read_register (struct eth_device* dev, u8 PHY_Register, u8 PHY_Address)
++{
++ u32 Data, Status = 0, Loop_Count = 0, PHY_Ready = 1;
++ u16 Return_Data;
++
++#ifdef REALTEK_PHY_SUPPORT
++ PHY_Address = 0x01;
++#endif
++//20us * 100 = 2ms > (1 / 2.5Mhz) * 0x34
++ OUTL(dev, (PHY_Register << 21) + (PHY_Address << 16) + MIIRD + MDC_CYCTHR, PHYCR_REG);
++ do {
++ udelay(20);
++ Status = (INL (dev, PHYCR_REG) & MIIRD);
++ Loop_Count++;
++ if (Loop_Count >= 100) {
++ PHY_Ready = 0;
++ break;
++ }
++ } while (Status == MIIRD);
++
++ if (PHY_Ready == 0) {
++ printf ("PHY NOT REDAY ");
++ return 0;
++ }
++ Data = INL (dev, PHYDATA_REG);
++ Return_Data = (Data >> 16);
++
++ return Return_Data;
++}
++
++
++static void phy_write_register (struct eth_device* dev, u8 PHY_Register, u8 PHY_Address, u16 PHY_Data)
++{
++ u32 Status = 0, Loop_Count = 0, PHY_Ready = 1;
++
++#ifdef REALTEK_PHY_SUPPORT
++ PHY_Address = 0x01;
++#endif
++//20us * 100 = 2ms > (1 / 2.5Mhz) * 0x34
++ OUTL(dev, PHY_Data, PHYDATA_REG);
++ OUTL(dev, (PHY_Register << 21) + (PHY_Address << 16) + MIIWR + MDC_CYCTHR, PHYCR_REG);
++ do {
++ udelay(20);
++ Status = (INL (dev, PHYCR_REG) & MIIWR);
++ Loop_Count++;
++ if (Loop_Count >= 100) {
++ PHY_Ready = 0;
++ break;
++ }
++ } while (Status == MIIWR);
++ if (PHY_Ready == 0) {
++ printf ("PHY NOT REDAY ");
++ }
++}
++
++static void set_mac_control_register (struct eth_device* dev)
++{
++ unsigned long MAC_CR_Register = 0;
++ unsigned long Loop_Count = 0, PHY_Ready = 1, Chip_ID;
++ u16 PHY_Status, PHY_Speed, PHY_Duplex, Resolved_Status = 0, Advertise, Link_Partner;
++
++ if (CONFIG_MAC1_PHY_SETTING >= 1) {
++ MAC_CR_Register = SPEED_100M_MODE_bit | RX_BROADPKT_bit | FULLDUP_bit | RXMAC_EN_bit | RXDMA_EN_bit | TXMAC_EN_bit | TXDMA_EN_bit | CRC_APD_bit;
++ }
++ else {
++ MAC_CR_Register = SPEED_100M_MODE_bit | FULLDUP_bit | RXMAC_EN_bit | RXDMA_EN_bit | TXMAC_EN_bit | TXDMA_EN_bit | CRC_APD_bit;
++ }
++
++ if (CONFIG_MAC1_PHY_SETTING != 2) {
++ Chip_ID = ((phy_read_register (dev, 0x02, 0)) << 16);
++ Chip_ID |= (phy_read_register (dev, 0x03, 0) & 0xffff);
++ if (((Chip_ID & PHYID_VENDOR_MASK) == PHYID_VENDOR_BROADCOM) ||
++ ((Chip_ID & PHYID_VENDOR_MODEL_MASK) == PHYID_RTL8201EL)) {
++ Advertise = phy_read_register (dev, 0x04, 0);
++ Link_Partner = phy_read_register (dev, 0x05, 0);
++ Advertise = (Advertise & PHY_SPEED_DUPLEX_MASK);
++ Link_Partner = (Link_Partner & PHY_SPEED_DUPLEX_MASK);
++ if ((Advertise & Link_Partner) & PHY_100M_DUPLEX) {
++ MAC_CR_Register |= SPEED_100M_MODE_bit;
++ MAC_CR_Register |= FULLDUP_bit;
++ }
++ else if ((Advertise & Link_Partner) & PHY_100M_HALF) {
++ MAC_CR_Register |= SPEED_100M_MODE_bit;
++ MAC_CR_Register &= ~FULLDUP_bit;
++ }
++ else if ((Advertise & Link_Partner) & PHY_10M_DUPLEX) {
++ MAC_CR_Register &= ~SPEED_100M_MODE_bit;
++ MAC_CR_Register |= FULLDUP_bit;
++ }
++ else if ((Advertise & Link_Partner) & PHY_10M_HALF) {
++ MAC_CR_Register &= ~SPEED_100M_MODE_bit;
++ MAC_CR_Register &= ~FULLDUP_bit;
++ }
++ }
++ else if (((Chip_ID & PHYID_VENDOR_MASK) == PHYID_VENDOR_MARVELL) ||
++ ((Chip_ID & PHYID_VENDOR_MODEL_MASK) == PHYID_RTL8211)) {
++//Max waiting time = (20 + 2)ms * 250(PHY_LOOP) = 5.5s
++ do {
++ udelay (20000);
++ Resolved_Status = (phy_read_register (dev, 0x11, 0) & RESOLVED_BIT);
++ Loop_Count++;
++ if (Loop_Count >= PHY_LOOP) {
++ PHY_Ready = 0;
++ printf ("PHY NOT READY ");
++ break;
++ }
++ } while (Resolved_Status != RESOLVED_BIT);
++
++ if (PHY_Ready == 1) {
++ PHY_Status = phy_read_register (dev, 0x11, 0);
++ PHY_Speed = (PHY_Status & PHY_SPEED_MASK) >> 14;
++ PHY_Duplex = (PHY_Status & PHY_DUPLEX_MASK) >> 13;
++
++ if (PHY_Speed == SPEED_1000M) {
++ MAC_CR_Register |= GMAC_MODE_bit;
++ }
++ else {
++ MAC_CR_Register &= ~GMAC_MODE_bit;
++ if (PHY_Speed == SPEED_10M) {
++ MAC_CR_Register &= ~SPEED_100M_MODE_bit;
++ }
++ }
++ if (PHY_Duplex == DUPLEX_HALF) {
++ MAC_CR_Register &= ~FULLDUP_bit;
++ }
++ }
++//LED Control
++// if (Chip_ID == 0x1C) {
++// PHY_Status = phy_read_register (dev, 0x18, 0);
++// phy_write_register (dev, 0x18, 0, (PHY_Status | 0x09));
++// }
++//LED Control D[0], D[6]
++// if (Chip_ID == 0x141) {
++// PHY_Status = phy_read_register (dev, 0x18, 0);
++// phy_write_register (dev, 0x18, 0, ((PHY_Status & ~(0x41)) | 0x01));
++// }
++ }
++ else if (Chip_ID == PHYID_BCM54612E ) {
++ phy_write_register ( dev, 0x1C, 1, 0x8C00 ); // Disable GTXCLK Clock Delay Enable
++ phy_write_register ( dev, 0x18, 1, 0xF0E7 ); // Disable RGMII RXD to RXC Skew
++
++ Advertise = phy_read_register (dev, 0x04, 1);
++ Link_Partner = phy_read_register (dev, 0x05, 1);
++ Advertise = (Advertise & PHY_SPEED_DUPLEX_MASK);
++ Link_Partner = (Link_Partner & PHY_SPEED_DUPLEX_MASK);
++ if ((Advertise & Link_Partner) & PHY_100M_DUPLEX) {
++ MAC_CR_Register |= SPEED_100M_MODE_bit;
++ MAC_CR_Register |= FULLDUP_bit;
++ }
++ else if ((Advertise & Link_Partner) & PHY_100M_HALF) {
++ MAC_CR_Register |= SPEED_100M_MODE_bit;
++ MAC_CR_Register &= ~FULLDUP_bit;
++ }
++ else if ((Advertise & Link_Partner) & PHY_10M_DUPLEX) {
++ MAC_CR_Register &= ~SPEED_100M_MODE_bit;
++ MAC_CR_Register |= FULLDUP_bit;
++ }
++ else if ((Advertise & Link_Partner) & PHY_10M_HALF) {
++ MAC_CR_Register &= ~SPEED_100M_MODE_bit;
++ MAC_CR_Register &= ~FULLDUP_bit;
++ }
++ }else {
++ printf("Unknow Chip_ID %x\n",Chip_ID);
++ }
++ }
++ OUTL(dev, MAC_CR_Register, MACCR_REG);
++}
++
++#endif /* CFG_CMD_NET && CONFIG_NET_MULTI && CONFIG_ASPEEDMAC */
+diff --git a/include/configs/ast1100.h b/include/configs/ast1100.h
+new file mode 100755
+index 0000000..dbd656e
+--- /dev/null
++++ b/include/configs/ast1100.h
+@@ -0,0 +1,257 @@
++/*
++ * (C) Copyright 2004
++ * Peter Chen <peterc@socle-tech.com.tw>
++ *
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License as
++ * published by the Free Software Foundation; either version 2 of
++ * the License, or (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
++ * MA 02111-1307 USA
++ */
++
++#ifndef __CONFIG_H
++#define __CONFIG_H
++
++/*
++ * Version Identity
++ */
++#define CONFIG_IDENT_STRING " ASPEED (v.0.12) "
++
++/*
++ * High Level Configuration Options
++ * (easy to change)
++ */
++//#define CONFIG_INIT_CRITICAL /* define for U-BOOT 1.1.1 */
++#undef CONFIG_INIT_CRITICAL /* undef for U-BOOT 1.1.4 */
++#define CONFIG_ARM926EJS 1 /* This is an arm926ejs CPU */
++#define CONFIG_ASPEED 1
++#define CONFIG_AST1100 1
++//#define CONFIG_AST1100_FPGA
++#undef CONFIG_AST1100_FPGA /* undef if real chip */
++//#define CONFIG_AST1100A2_PATCH
++#undef CONFIG_AST1100A2_PATCH
++//#define CONFIG_2SPIFLASH /* Boot SPI: CS2, 2nd SPI: CS0 */ /* Not ready */
++#undef CONFIG_2SPIFLASH
++#undef CONFIG_DDR512_200
++#define CONFIG_DDRII1G_200 1
++#undef CONFIG_ASPEED_SLT
++
++//#define CONFIG_USE_IRQ /* we don't need IRQ/FIQ stuff */
++#define CONFIG_MISC_INIT_R
++
++/*
++ * Environment Config
++ */
++#define CONFIG_CMDLINE_TAG 1 /* enable passing of ATAGs */
++#define CONFIG_SETUP_MEMORY_TAGS 1
++#define CONFIG_INITRD_TAG 1
++#define CONFIG_BOOTARGS "debug console=ttyS1,115200n8 ramdisk_size=16384 root=/dev/ram rw init=/linuxrc mem=80M"
++#ifdef CONFIG_ASPEED_SLT
++#define CONFIG_BOOTDELAY 1 /* autoboot after 3 seconds */
++#else
++#define CONFIG_BOOTDELAY 3 /* autoboot after 3 seconds */
++#endif
++#define CONFIG_BOOTCOMMAND "bootm 14080000 14300000"
++#define CONFIG_BOOTFILE "all.bin"
++#define CONFIG_ENV_OVERWRITE
++
++/*
++ * Command line configuration.
++ */
++#include <config_cmd_default.h>
++
++#define CONFIG_CMD_DFL
++#define CONFIG_CMD_ENV
++#define CONFIG_CMD_FLASH
++#define CONFIG_CMD_NET
++#define CONFIG_CMD_PING
++#define CONFIG_CMD_I2C
++#define CONFIG_CMD_EEPROM
++
++/*
++ * CPU Setting
++ */
++#define CPU_CLOCK_RATE 18000000 /* 16.5 MHz clock for the ARM core */
++
++/*
++ * Size of malloc() pool
++ */
++#define CONFIG_SYS_MALLOC_LEN (CONFIG_ENV_SIZE + 128*1024)
++#define CONFIG_SYS_GBL_DATA_SIZE 128 /* size in bytes reserved for initial data */
++
++/*
++ * Stack sizes, The stack sizes are set up in start.S using the settings below
++ */
++#define CONFIG_STACKSIZE (128*1024) /* regular stack */
++#define CONFIG_STACKSIZE_IRQ (4*1024) /* IRQ stack */
++#define CONFIG_STACKSIZE_FIQ (4*1024) /* FIQ stack */
++
++/*
++ * Memory Configuration
++ */
++#define CONFIG_NR_DRAM_BANKS 1 /* we have 1 bank of DRAM */
++#define PHYS_SDRAM_1 0x40000000 /* SDRAM Bank #1 */
++#define PHYS_SDRAM_1_SIZE 0x4000000 /* 64 MB */
++
++#define CONFIG_SYS_SDRAM_BASE 0x40000000
++
++/*
++ * FLASH Configuration
++ */
++#define PHYS_FLASH_1 0x14000000 /* Flash Bank #1 */
++#define PHYS_FLASH_2 0x14800000 /* Flash Bank #2 */
++#define PHYS_FLASH_2_BASE 0x10000000
++
++#ifdef CONFIG_2SPIFLASH
++#define CONFIG_SYS_FLASH_BASE PHYS_FLASH_2_BASE
++#define CONFIG_FLASH_BANKS_LIST { PHYS_FLASH_1, PHYS_FLASH_2 }
++#define CONFIG_SYS_MAX_FLASH_BANKS 2
++#define CONFIG_SYS_MAX_FLASH_SECT (256) /* max number of sectors on one chip */
++
++#define CONFIG_ENV_IS_IN_FLASH 1
++#define CONFIG_ENV_OFFSET 0x7F0000 /* environment starts here */
++#define CONFIG_ENV_SIZE 0x010000 /* Total Size of Environment Sector */
++#else
++#define CONFIG_SYS_FLASH_BASE PHYS_FLASH_1
++#define CONFIG_FLASH_BANKS_LIST { PHYS_FLASH_1 }
++#define CONFIG_SYS_MAX_FLASH_BANKS 1
++#define CONFIG_SYS_MAX_FLASH_SECT (256) /* max number of sectors on one chip */
++
++#define CONFIG_ENV_IS_IN_FLASH 1
++#define CONFIG_ENV_OFFSET 0x7F0000 /* environment starts here */
++#define CONFIG_ENV_SIZE 0x010000 /* Total Size of Environment Sector */
++#endif
++
++#define __LITTLE_ENDIAN
++#define CONFIG_FLASH_SPI
++
++#define CONFIG_MONITOR_BASE TEXT_BASE
++#define CONFIG_MONITOR_LEN (192 << 10)
++
++/* timeout values are in ticks */
++#define CONFIG_SYS_FLASH_ERASE_TOUT (20*CONFIG_SYS_HZ) /* Timeout for Flash Erase */
++#define CONFIG_SYS_FLASH_WRITE_TOUT (20*CONFIG_SYS_HZ) /* Timeout for Flash Write */
++
++/*
++ * Miscellaneous configurable options
++ */
++#define CONFIG_SYS_LONGHELP /* undef to save memory */
++
++#define CONFIG_SYS_PROMPT "boot# " /* Monitor Command Prompt */
++#define CONFIG_SYS_CBSIZE 256 /* Console I/O Buffer Size */
++#define CONFIG_SYS_PBSIZE (CONFIG_SYS_CBSIZE+sizeof(CONFIG_SYS_PROMPT)+16) /* Print Buffer Size */
++#define CONFIG_SYS_MAXARGS 16 /* max number of command args */
++#define CONFIG_SYS_BARGSIZE CONFIG_SYS_CBSIZE /* Boot Argument Buffer Size */
++
++#define CONFIG_SYS_MEMTEST_START 0x40000000 /* memtest works on */
++#define CONFIG_SYS_MEMTEST_END 0x44FFFFFF /* 256 MB in DRAM */
++
++#define CONFIG_SYS_CLKS_IN_HZ /* everything, incl board info, in Hz */
++#undef CONFIG_SYS_CLKS_IN_HZ /* everything, incl board info, in Hz */
++
++#define CONFIG_SYS_LOAD_ADDR 0x43000000 /* default load address */
++
++#define CONFIG_SYS_TIMERBASE 0x1E782000 /* use timer 1 */
++#define CONFIG_SYS_HZ (1*1000*1000) /* use external clk (1M) */
++
++/*
++ * Serial Configuration
++ */
++#define CONFIG_SYS_NS16550
++#define CONFIG_SYS_NS16550_SERIAL
++#define CONFIG_SYS_NS16550_REG_SIZE 4
++#define CONFIG_SYS_NS16550_CLK 24000000
++#define CONFIG_SYS_NS16550_COM1 0x1e783000
++#define CONFIG_SYS_NS16550_COM2 0x1e784000
++#define CONFIG_SYS_LOADS_BAUD_CHANGE
++#define CONFIG_SERIAL1 1
++#define CONFIG_CONS_INDEX 2
++#define CONFIG_BAUDRATE 115200
++#define CONFIG_SYS_BAUDRATE_TABLE { 9600, 19200, 38400, 57600, 115200 }
++
++/*
++ * USB device configuration
++ */
++/*
++#define CONFIG_USB_DEVICE 1
++#define CONFIG_USB_TTY 1
++
++#define CONFIG_USBD_VENDORID 0x1234
++#define CONFIG_USBD_PRODUCTID 0x5678
++#define CONFIG_USBD_MANUFACTURER "Siemens"
++#define CONFIG_USBD_PRODUCT_NAME "SX1"
++*/
++
++/*
++ * I2C configuration
++ */
++#define CONFIG_HARD_I2C
++#define CONFIG_SYS_I2C_SPEED 100000
++#define CONFIG_SYS_I2C_SLAVE 1
++#define CONFIG_DRIVER_ASPEED_I2C
++
++/*
++* EEPROM configuration
++*/
++#define CONFIG_SYS_I2C_EEPROM_ADDR_LEN 2
++#define CONFIG_SYS_I2C_EEPROM_ADDR 0xa0
++
++/*
++ * NIC configuration
++ */
++#define __BYTE_ORDER __LITTLE_ENDIAN
++#define __LITTLE_ENDIAN_BITFIELD
++#define CONFIG_MAC_PARTITION
++#define CONFIG_ASPEEDNIC
++//#define CONFIG_MAC1_PHY_LINK_INTERRUPT
++//#define CONFIG_MAC2_ENABLE
++//#define CONFIG_MAC2_MII_ENABLE
++//#define CONFIG_MAC2_PHY_LINK_INTERRUPT
++
++/*
++*-------------------------------------------------------------------------------
++* NOTICE: MAC1 and MAC2 now have their own seperate PHY configuration.
++* We use 2 bits for each MAC in the scratch register(D[15:11] in 0x1E6E2040) to
++* inform kernel driver.
++* The meanings of the 2 bits are:
++* 00(0): Dedicated PHY
++* 01(1): ASPEED's EVA + INTEL's NC-SI PHY chip EVA
++* 10(2): ASPEED's MAC is connected to NC-SI PHY chip directly
++* 11: Reserved
++*
++* We use CONFIG_MAC1_PHY_SETTING and CONFIG_MAC2_PHY_SETTING in U-Boot
++* 0: Dedicated PHY
++* 1: ASPEED's EVA + INTEL's NC-SI PHY chip EVA
++* 2: ASPEED's MAC is connected to NC-SI PHY chip directly
++* 3: Reserved
++*-------------------------------------------------------------------------------
++*/
++#define CONFIG_MAC1_PHY_SETTING 0
++#define CONFIG_MAC2_PHY_SETTING 0
++#define CONFIG_NET_MULTI
++#define CONFIG_ETHACT aspeednic#0
++#define CONFIG_GATEWAYIP 192.168.0.1
++#define CONFIG_NETMASK 255.255.255.0
++#define CONFIG_IPADDR 192.168.0.188
++#define CONFIG_SERVERIP 192.168.0.126
++#define CONFIG_ETHADDR 00:C0:A8:12:34:56
++#define CONFIG_ETH1ADDR 00:C0:A8:12:34:57
++
++/*
++ * SLT
++ */
++/*
++#define CONFIG_SLT
++#define CFG_CMD_SLT (CFG_CMD_REGTEST | CFG_CMD_MACTEST | CFG_CMD_VIDEOTEST | CFG_CMD_HACTEST | CFG_CMD_MICTEST)
++*/
++
++#endif /* __CONFIG_H */
+diff --git a/include/configs/ast2100.h b/include/configs/ast2100.h
+new file mode 100644
+index 0000000..07733b9
+--- /dev/null
++++ b/include/configs/ast2100.h
+@@ -0,0 +1,272 @@
++/*
++ * (C) Copyright 2004
++ * Peter Chen <peterc@socle-tech.com.tw>
++ *
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License as
++ * published by the Free Software Foundation; either version 2 of
++ * the License, or (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
++ * MA 02111-1307 USA
++ */
++
++#ifndef __CONFIG_H
++#define __CONFIG_H
++
++/*
++ * High Level Configuration Options
++ * (easy to change)
++ */
++//#define CONFIG_INIT_CRITICAL /* define for U-BOOT 1.1.1 */
++#undef CONFIG_INIT_CRITICAL /* undef for U-BOOT 1.1.4 */
++#define CONFIG_ARM926EJS 1 /* This is an arm926ejs CPU */
++#define CONFIG_ASPEED 1
++#define CONFIG_AST2100 1
++//#define CONFIG_AST2100_FPGA
++#undef CONFIG_AST2100_FPGA /* undef if real chip */
++//#define CONFIG_AST2100A2_PATCH
++#undef CONFIG_AST2100A2_PATCH
++#define CONFIG_SYS_FLASH_CFI /* CONFIG_FLASH_CFI, CONFIG_FLASH_SPI is exclusive*/
++//#define CONFIG_FLASH_SPI
++//#define CONFIG_2SPIFLASH /* Boot SPI: CS2, 2nd SPI: CS0 */
++#undef CONFIG_DDRII1G_266
++#undef CONFIG_2SPIFLASH
++#undef CONFIG_ASPEED_SLT
++
++//#define CONFIG_USE_IRQ /* we don't need IRQ/FIQ stuff */
++#define CONFIG_MISC_INIT_R
++
++/*
++ * Environment Config
++ */
++#define CONFIG_CMDLINE_TAG 1 /* enable passing of ATAGs */
++#define CONFIG_SETUP_MEMORY_TAGS 1
++#define CONFIG_INITRD_TAG 1
++#define CONFIG_BOOTARGS "debug console=ttyS1,115200n8 ramdisk_size=16384 root=/dev/ram rw init=/linuxrc mem=80M"
++#define CONFIG_BOOTDELAY 3 /* autoboot after 3 seconds */
++#ifdef CONFIG_SYS_FLASH_CFI
++#define CONFIG_BOOTCOMMAND "bootm 10080000 10300000"
++#else
++#define CONFIG_BOOTCOMMAND "bootm 14080000 14300000"
++#endif
++#define CONFIG_BOOTFILE "all.bin"
++#define CONFIG_ENV_OVERWRITE
++
++/*
++ * Command line configuration.
++ */
++#include <config_cmd_default.h>
++
++#define CONFIG_CMD_DFL
++#define CONFIG_CMD_ENV
++#define CONFIG_CMD_FLASH
++#define CONFIG_CMD_NET
++#define CONFIG_CMD_PING
++#define CONFIG_CMD_I2C
++#define CONFIG_CMD_EEPROM
++
++/*
++ * CPU Setting
++ */
++#define CPU_CLOCK_RATE 18000000 /* 16.5 MHz clock for the ARM core */
++
++/*
++ * Size of malloc() pool
++ */
++#define CONFIG_SYS_MALLOC_LEN (CONFIG_ENV_SIZE + 128*1024)
++#define CONFIG_SYS_GBL_DATA_SIZE 128 /* size in bytes reserved for initial data */
++
++/*
++ * Stack sizes, The stack sizes are set up in start.S using the settings below
++ */
++#define CONFIG_STACKSIZE (128*1024) /* regular stack */
++#define CONFIG_STACKSIZE_IRQ (4*1024) /* IRQ stack */
++#define CONFIG_STACKSIZE_FIQ (4*1024) /* FIQ stack */
++
++/*
++ * Memory Configuration
++ */
++#define CONFIG_NR_DRAM_BANKS 1 /* we have 1 bank of DRAM */
++#define PHYS_SDRAM_1 0x40000000 /* SDRAM Bank #1 */
++#define PHYS_SDRAM_1_SIZE 0x4000000 /* 64 MB */
++
++#define CONFIG_SYS_SDRAM_BASE 0x40000000
++
++/*
++ * FLASH Configuration
++ */
++#ifdef CONFIG_SYS_FLASH_CFI /* NOR Flash */
++
++#define PHYS_FLASH_1 0x10000000 /* Flash Bank #1 */
++
++#define CONFIG_SYS_FLASH_BASE PHYS_FLASH_1
++#define CONFIG_FLASH_BANKS_LIST { PHYS_FLASH_1 }
++
++#define CONFIG_SYS_MAX_FLASH_BANKS 1
++#define CONFIG_SYS_MAX_FLASH_SECT (256) /* max number of sectors on one chip */
++
++#define CONFIG_ENV_IS_IN_FLASH 1
++#define CONFIG_ENV_OFFSET 0x60000 /* environment starts here */
++#define CONFIG_ENV_SIZE 0x20000 /* Total Size of Environment Sector */
++
++#define CONFIG_SYS_FLASH_CFI_AMD_RESET
++#define CONFIG_SYS_FLASH_USE_BUFFER_WRITE
++
++#else /* SPI Flash */
++
++#define PHYS_FLASH_1 0x14000000 /* Flash Bank #1 */
++#define PHYS_FLASH_2 0x14800000 /* Flash Bank #2 */
++#define PHYS_FLASH_2_BASE 0x10000000
++
++#ifdef CONFIG_2SPIFLASH
++#define CONFIG_SYS_FLASH_BASE PHYS_FLASH_2_BASE
++#define CONFIG_FLASH_BANKS_LIST { PHYS_FLASH_1, PHYS_FLASH_2 }
++#define CONFIG_SYS_MAX_FLASH_BANKS 2
++#define CONFIG_SYS_MAX_FLASH_SECT (256) /* max number of sectors on one chip */
++
++#define CONFIG_ENV_IS_IN_FLASH 1
++#define CONFIG_ENV_OFFSET 0x7F0000 /* environment starts here */
++#define CONFIG_ENV_SIZE 0x010000 /* Total Size of Environment Sector */
++#else
++#define CONFIG_SYS_FLASH_BASE PHYS_FLASH_1
++#define CONFIG_FLASH_BANKS_LIST { PHYS_FLASH_1 }
++#define CONFIG_SYS_MAX_FLASH_BANKS 1
++#define CONFIG_SYS_MAX_FLASH_SECT (256) /* max number of sectors on one chip */
++
++#define CONFIG_ENV_IS_IN_FLASH 1
++#define CONFIG_ENV_OFFSET 0x7F0000 /* environment starts here */
++#define CONFIG_ENV_SIZE 0x010000 /* Total Size of Environment Sector */
++#endif
++
++#endif
++
++#define __LITTLE_ENDIAN
++
++#define CONFIG_MONITOR_BASE TEXT_BASE
++#define CONFIG_MONITOR_LEN (192 << 10)
++
++/* timeout values are in ticks */
++#define CONFIG_SYS_FLASH_ERASE_TOUT (20*CONFIG_SYS_HZ) /* Timeout for Flash Erase */
++#define CONFIG_SYS_FLASH_WRITE_TOUT (20*CONFIG_SYS_HZ) /* Timeout for Flash Write */
++
++/*
++ * Miscellaneous configurable options
++ */
++#define CONFIG_SYS_LONGHELP /* undef to save memory */
++
++#define CONFIG_SYS_PROMPT "boot# " /* Monitor Command Prompt */
++#define CONFIG_SYS_CBSIZE 256 /* Console I/O Buffer Size */
++#define CONFIG_SYS_PBSIZE (CONFIG_SYS_CBSIZE+sizeof(CONFIG_SYS_PROMPT)+16) /* Print Buffer Size */
++#define CONFIG_SYS_MAXARGS 16 /* max number of command args */
++#define CONFIG_SYS_BARGSIZE CONFIG_SYS_CBSIZE /* Boot Argument Buffer Size */
++
++#define CONFIG_SYS_MEMTEST_START 0x40000000 /* memtest works on */
++#define CONFIG_SYS_MEMTEST_END 0x44FFFFFF /* 256 MB in DRAM */
++
++#define CONFIG_SYS_CLKS_IN_HZ /* everything, incl board info, in Hz */
++#undef CONFIG_SYS_CLKS_IN_HZ /* everything, incl board info, in Hz */
++
++#define CONFIG_SYS_LOAD_ADDR 0x43000000 /* default load address */
++
++#define CONFIG_SYS_TIMERBASE 0x1E782000 /* use timer 1 */
++#define CONFIG_SYS_HZ (1*1000*1000) /* use external clk (1M) */
++
++/*
++ * Serial Configuration
++ */
++#define CONFIG_SYS_NS16550
++#define CONFIG_SYS_NS16550_SERIAL
++#define CONFIG_SYS_NS16550_REG_SIZE 4
++#define CONFIG_SYS_NS16550_CLK 24000000
++#define CONFIG_SYS_NS16550_COM1 0x1e783000
++#define CONFIG_SYS_NS16550_COM2 0x1e784000
++#define CONFIG_SYS_LOADS_BAUD_CHANGE
++#define CONFIG_SERIAL1 1
++#define CONFIG_CONS_INDEX 2
++#define CONFIG_BAUDRATE 115200
++#define CONFIG_SYS_BAUDRATE_TABLE { 9600, 19200, 38400, 57600, 115200 }
++
++/*
++ * USB device configuration
++ */
++/*
++#define CONFIG_USB_DEVICE 1
++#define CONFIG_USB_TTY 1
++
++#define CONFIG_USBD_VENDORID 0x1234
++#define CONFIG_USBD_PRODUCTID 0x5678
++#define CONFIG_USBD_MANUFACTURER "Siemens"
++#define CONFIG_USBD_PRODUCT_NAME "SX1"
++*/
++
++/*
++ * I2C configuration
++ */
++#define CONFIG_HARD_I2C
++#define CONFIG_SYS_I2C_SPEED 100000
++#define CONFIG_SYS_I2C_SLAVE 1
++#define CONFIG_DRIVER_ASPEED_I2C
++
++/*
++* EEPROM configuration
++*/
++#define CONFIG_SYS_I2C_EEPROM_ADDR_LEN 2
++#define CONFIG_SYS_I2C_EEPROM_ADDR 0xa0
++
++/*
++ * NIC configuration
++ */
++#define __BYTE_ORDER __LITTLE_ENDIAN
++#define __LITTLE_ENDIAN_BITFIELD
++#define CONFIG_MAC_PARTITION
++#define CONFIG_ASPEEDNIC
++#define CONFIG_MAC1_PHY_LINK_INTERRUPT
++#define CONFIG_MAC2_ENABLE
++#define CONFIG_MAC2_MII_ENABLE
++//#define CONFIG_MAC2_PHY_LINK_INTERRUPT
++/*
++*-------------------------------------------------------------------------------
++* NOTICE: MAC1 and MAC2 now have their own seperate PHY configuration.
++* We use 2 bits for each MAC in the scratch register(D[15:11] in 0x1E6E2040) to
++* inform kernel driver.
++* The meanings of the 2 bits are:
++* 00(0): Dedicated PHY
++* 01(1): ASPEED's EVA + INTEL's NC-SI PHY chip EVA
++* 10(2): ASPEED's MAC is connected to NC-SI PHY chip directly
++* 11: Reserved
++*
++* We use CONFIG_MAC1_PHY_SETTING and CONFIG_MAC2_PHY_SETTING in U-Boot
++* 0: Dedicated PHY
++* 1: ASPEED's EVA + INTEL's NC-SI PHY chip EVA
++* 2: ASPEED's MAC is connected to NC-SI PHY chip directly
++* 3: Reserved
++*-------------------------------------------------------------------------------
++*/
++#define CONFIG_MAC1_PHY_SETTING 0
++#define CONFIG_MAC2_PHY_SETTING 0
++#define CONFIG_NET_MULTI
++#define CONFIG_ETHACT aspeednic#0
++#define CONFIG_GATEWAYIP 192.168.0.1
++#define CONFIG_NETMASK 255.255.255.0
++#define CONFIG_IPADDR 192.168.0.188
++#define CONFIG_SERVERIP 192.168.0.106
++#define CONFIG_ETHADDR 00:C0:A8:12:34:56
++#define CONFIG_ETH1ADDR 00:C0:A8:12:34:57
++
++/*
++ * SLT
++ */
++/*
++#define CONFIG_SLT
++#define CONFIG_CMD_SLT (CONFIG_CMD_REGTEST | CONFIG_CMD_MACTEST | CONFIG_CMD_VIDEOTEST | CONFIG_CMD_HACTEST | CONFIG_CMD_MICTEST)
++*/
++
++#endif /* __CONFIG_H */
+diff --git a/include/configs/ast2300.h b/include/configs/ast2300.h
+new file mode 100644
+index 0000000..678e7c3
+--- /dev/null
++++ b/include/configs/ast2300.h
+@@ -0,0 +1,325 @@
++/*
++ * (C) Copyright 2004
++ * Peter Chen <peterc@socle-tech.com.tw>
++ *
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License as
++ * published by the Free Software Foundation; either version 2 of
++ * the License, or (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
++ * MA 02111-1307 USA
++ */
++
++#ifndef __CONFIG_H
++#define __CONFIG_H
++
++/*
++ * High Level Configuration Options
++ * (easy to change)
++ */
++//#define CONFIG_INIT_CRITICAL /* define for U-BOOT 1.1.1 */
++#undef CONFIG_INIT_CRITICAL /* undef for U-BOOT 1.1.4 */
++#define CONFIG_ARM926EJS 1 /* This is an arm926ejs CPU */
++#define CONFIG_ASPEED 1
++#define CONFIG_AST2300 1
++//#define CONFIG_AST1070 1
++//#define CONFIG_SYS_FLASH_CFI /* CONFIG_FLASH_CFI, CONFIG_FLASH_SPI is exclusive*/
++#define CONFIG_FLASH_SPI
++//#define CONFIG_2SPIFLASH /* Boot SPI: CS2, 2nd SPI: CS0 */
++#undef CONFIG_2SPIFLASH
++#undef CONFIG_ASPEED_SLT
++#define CONFIG_FLASH_AST2300
++#define CONFIG_FLASH_AST2300_DMA
++//#define CONFIG_FLASH_SPIx2_Dummy
++//#define CONFIG_FLASH_SPIx4_Dummy
++#define CONFIG_CRT_DISPLAY 1 /* undef if not support CRT */
++
++//#define CONFIG_USE_IRQ /* we don't need IRQ/FIQ stuff */
++#define CONFIG_MISC_INIT_R
++
++/*
++ * DRAM Config
++ *
++ * 1. DRAM Size //
++ * CONFIG_DRAM_512MBIT // 512M bit
++ * CONFIG_DRAM_1GBIT // 1G bit (default)
++ * CONFIG_DRAM_2GBIT // 2G bit
++ * CONFIG_DRAM_4GBIT // 4G bit
++ * 2. DRAM Speed //
++ * CONFIG_DRAM_336 // 336MHz (DDR-667)
++ * CONFIG_DRAM_408 // 408MHz (DDR-800) (default)
++ * 3. VGA Mode
++ * CONFIG_CRT_DISPLAY // define to disable VGA function
++ * 4. ECC Function enable
++ * CONFIG_DRAM_ECC // define to enable ECC function
++ * 5. UART Debug Message
++ * CONFIG_DRAM_UART_OUT // enable output message at UART5
++ * CONFIG_DRAM_UART_38400 // set the UART baud rate to 38400, default is 115200
++ */
++
++//1. DRAM Size
++//#define CONFIG_DRAM_512MBIT
++#define CONFIG_DRAM_1GBIT
++//#define CONFIG_DRAM_2GBIT
++//#define CONFIG_DRAM_4GBIT
++//2. DRAM Speed
++//#define CONFIG_DRAM_336
++#define CONFIG_DRAM_408
++//3. VGA Mode
++//#define CONFIG_CRT_DISPLAY
++//4. ECC Function enable
++//#define CONFIG_DRAM_ECC
++//5. UART Debug Message
++#define CONFIG_DRAM_UART_OUT
++//#define CONFIG_DRAM_UART_38400
++
++
++
++/*
++ * Environment Config
++ */
++#define CONFIG_CMDLINE_TAG 1 /* enable passing of ATAGs */
++#define CONFIG_SETUP_MEMORY_TAGS 1
++#define CONFIG_INITRD_TAG 1
++#define CONFIG_BOOTARGS "debug console=ttyS0,115200n8 ramdisk_size=16384 root=/dev/ram rw init=/linuxrc mem=80M"
++#define CONFIG_UPDATE "tftp 40800000 ast2300.scr; so 40800000'"
++
++#define CONFIG_BOOTDELAY 3 /* autoboot after 3 seconds */
++#ifdef CONFIG_FLASH_AST2300
++#define CONFIG_BOOTCOMMAND "bootm 20080000 20300000"
++#else
++#ifdef CONFIG_SYS_FLASH_CFI
++#define CONFIG_BOOTCOMMAND "bootm 10080000 10300000"
++#else
++#define CONFIG_BOOTCOMMAND "bootm 14080000 14300000"
++#endif
++#endif
++#define CONFIG_BOOTFILE "all.bin"
++#define CONFIG_ENV_OVERWRITE
++
++/*
++ * Command line configuration.
++ */
++#include <config_cmd_default.h>
++
++#define CONFIG_CMD_DFL
++#define CONFIG_CMD_ENV
++#define CONFIG_CMD_FLASH
++#define CONFIG_CMD_NET
++#define CONFIG_CMD_PING
++#define CONFIG_CMD_I2C
++#define CONFIG_CMD_EEPROM
++
++/*
++ * CPU Setting
++ */
++#define CPU_CLOCK_RATE 18000000 /* 16.5 MHz clock for the ARM core */
++
++/*
++ * Size of malloc() pool
++ */
++#define CONFIG_SYS_MALLOC_LEN (CONFIG_ENV_SIZE + 768*1024)
++#define CONFIG_SYS_GBL_DATA_SIZE 128 /* size in bytes reserved for initial data */
++
++/*
++ * Stack sizes, The stack sizes are set up in start.S using the settings below
++ */
++#define CONFIG_STACKSIZE (128*1024) /* regular stack */
++#define CONFIG_STACKSIZE_IRQ (4*1024) /* IRQ stack */
++#define CONFIG_STACKSIZE_FIQ (4*1024) /* FIQ stack */
++
++/*
++ * Memory Configuration
++ */
++#define CONFIG_NR_DRAM_BANKS 1 /* we have 1 bank of DRAM */
++#define PHYS_SDRAM_1 0x40000000 /* SDRAM Bank #1 */
++#define PHYS_SDRAM_1_SIZE 0x4000000 /* 64 MB */
++
++#define CONFIG_SYS_SDRAM_BASE 0x40000000
++
++/*
++ * FLASH Configuration
++ */
++#ifdef CONFIG_SYS_FLASH_CFI /* NOR Flash */
++
++#ifdef CONFIG_FLASH_AST2300
++#define PHYS_FLASH_1 0x20000000 /* Flash Bank #1 */
++#else
++#define PHYS_FLASH_1 0x10000000 /* Flash Bank #1 */
++#endif
++
++#define CONFIG_SYS_FLASH_BASE PHYS_FLASH_1
++#define CONFIG_FLASH_BANKS_LIST { PHYS_FLASH_1 }
++
++#define CONFIG_SYS_MAX_FLASH_BANKS 1
++#define CONFIG_SYS_MAX_FLASH_SECT (256) /* max number of sectors on one chip */
++
++#define CONFIG_ENV_IS_IN_FLASH 1
++#define CONFIG_ENV_OFFSET 0x60000 /* environment starts here */
++#define CONFIG_ENV_SIZE 0x20000 /* Total Size of Environment Sector */
++
++#define CONFIG_SYS_FLASH_CFI_AMD_RESET
++#define CONFIG_SYS_FLASH_USE_BUFFER_WRITE
++
++#else /* SPI Flash */
++
++#ifdef CONFIG_FLASH_AST2300
++#define PHYS_FLASH_1 0x20000000 /* Flash Bank #1 */
++#else
++#define PHYS_FLASH_1 0x14000000 /* Flash Bank #1 */
++#define PHYS_FLASH_2 0x14800000 /* Flash Bank #2 */
++#define PHYS_FLASH_2_BASE 0x10000000
++#endif
++
++#ifdef CONFIG_2SPIFLASH
++#define CONFIG_SYS_FLASH_BASE PHYS_FLASH_2_BASE
++#define CONFIG_FLASH_BANKS_LIST { PHYS_FLASH_1, PHYS_FLASH_2 }
++#define CONFIG_SYS_MAX_FLASH_BANKS 2
++#define CONFIG_SYS_MAX_FLASH_SECT (1024) /* max number of sectors on one chip */
++
++#define CONFIG_ENV_IS_IN_FLASH 1
++#define CONFIG_ENV_OFFSET 0x7F0000 /* environment starts here */
++#define CONFIG_ENV_SIZE 0x010000 /* Total Size of Environment Sector */
++#else
++#define CONFIG_SYS_FLASH_BASE PHYS_FLASH_1
++#define CONFIG_FLASH_BANKS_LIST { PHYS_FLASH_1 }
++#define CONFIG_SYS_MAX_FLASH_BANKS 1
++#define CONFIG_SYS_MAX_FLASH_SECT (1024) /* max number of sectors on one chip */
++
++#define CONFIG_ENV_IS_IN_FLASH 1
++#define CONFIG_ENV_OFFSET 0x7F0000 /* environment starts here */
++#define CONFIG_ENV_SIZE 0x010000 /* Total Size of Environment Sector */
++#endif
++
++#endif
++
++#define __LITTLE_ENDIAN
++
++#define CONFIG_MONITOR_BASE TEXT_BASE
++#define CONFIG_MONITOR_LEN (192 << 10)
++
++/* timeout values are in ticks */
++#define CONFIG_SYS_FLASH_ERASE_TOUT (20*CONFIG_SYS_HZ) /* Timeout for Flash Erase */
++#define CONFIG_SYS_FLASH_WRITE_TOUT (20*CONFIG_SYS_HZ) /* Timeout for Flash Write */
++
++/*
++ * Miscellaneous configurable options
++ */
++#define CONFIG_SYS_LONGHELP /* undef to save memory */
++
++#define CONFIG_SYS_PROMPT "boot# " /* Monitor Command Prompt */
++#define CONFIG_SYS_CBSIZE 256 /* Console I/O Buffer Size */
++#define CONFIG_SYS_PBSIZE (CONFIG_SYS_CBSIZE+sizeof(CONFIG_SYS_PROMPT)+16) /* Print Buffer Size */
++#define CONFIG_SYS_MAXARGS 16 /* max number of command args */
++#define CONFIG_SYS_BARGSIZE CONFIG_SYS_CBSIZE /* Boot Argument Buffer Size */
++
++#define CONFIG_SYS_MEMTEST_START 0x40000000 /* memtest works on */
++#define CONFIG_SYS_MEMTEST_END 0x44FFFFFF /* 256 MB in DRAM */
++
++#define CONFIG_SYS_CLKS_IN_HZ /* everything, incl board info, in Hz */
++#undef CONFIG_SYS_CLKS_IN_HZ /* everything, incl board info, in Hz */
++
++#define CONFIG_SYS_LOAD_ADDR 0x43000000 /* default load address */
++
++#define CONFIG_SYS_TIMERBASE 0x1E782000 /* use timer 1 */
++#define CONFIG_SYS_HZ (1*1000*1000) /* use external clk (1M) */
++
++/*
++ * Serial Configuration
++ */
++#define CONFIG_SYS_NS16550
++#define CONFIG_SYS_NS16550_SERIAL
++#define CONFIG_SYS_NS16550_REG_SIZE 4
++#define CONFIG_SYS_NS16550_CLK 24000000
++#define CONFIG_SYS_NS16550_COM1 0x1e783000
++#define CONFIG_SYS_NS16550_COM2 0x1e784000
++#define CONFIG_SYS_LOADS_BAUD_CHANGE
++#define CONFIG_SERIAL1 1
++#define CONFIG_CONS_INDEX 2
++#define CONFIG_BAUDRATE 115200
++#define CONFIG_SYS_BAUDRATE_TABLE { 9600, 19200, 38400, 57600, 115200 }
++
++/*
++ * USB device configuration
++ */
++/*
++#define CONFIG_USB_DEVICE 1
++#define CONFIG_USB_TTY 1
++
++#define CONFIG_USBD_VENDORID 0x1234
++#define CONFIG_USBD_PRODUCTID 0x5678
++#define CONFIG_USBD_MANUFACTURER "Siemens"
++#define CONFIG_USBD_PRODUCT_NAME "SX1"
++*/
++
++/*
++ * I2C configuration
++ */
++#define CONFIG_HARD_I2C
++#define CONFIG_SYS_I2C_SPEED 100000
++#define CONFIG_SYS_I2C_SLAVE 1
++#define CONFIG_DRIVER_ASPEED_I2C
++
++/*
++* EEPROM configuration
++*/
++#define CONFIG_SYS_I2C_EEPROM_ADDR_LEN 2
++#define CONFIG_SYS_I2C_EEPROM_ADDR 0xa0
++
++/*
++ * NIC configuration
++ */
++#define __BYTE_ORDER __LITTLE_ENDIAN
++#define __LITTLE_ENDIAN_BITFIELD
++#define CONFIG_MAC_PARTITION
++#define CONFIG_ASPEEDNIC
++//#define CONFIG_MAC1_PHY_LINK_INTERRUPT
++#define CONFIG_MAC2_ENABLE
++#define CONFIG_MAC2_PHY_LINK_INTERRUPT
++/*
++*-------------------------------------------------------------------------------
++* NOTICE: MAC1 and MAC2 now have their own seperate PHY configuration.
++* We use 2 bits for each MAC in the scratch register(D[15:11] in 0x1E6E2040) to
++* inform kernel driver.
++* The meanings of the 2 bits are:
++* 00(0): Dedicated PHY
++* 01(1): ASPEED's EVA + INTEL's NC-SI PHY chip EVA
++* 10(2): ASPEED's MAC is connected to NC-SI PHY chip directly
++* 11: Reserved
++*
++* We use CONFIG_MAC1_PHY_SETTING and CONFIG_MAC2_PHY_SETTING in U-Boot
++* 0: Dedicated PHY
++* 1: ASPEED's EVA + INTEL's NC-SI PHY chip EVA
++* 2: ASPEED's MAC is connected to NC-SI PHY chip directly
++* 3: Reserved
++*-------------------------------------------------------------------------------
++*/
++#define CONFIG_MAC1_PHY_SETTING 0
++#define CONFIG_MAC2_PHY_SETTING 0
++#define CONFIG_MAC_INTERFACE_CLOCK_DELAY 0x2255
++#define CONFIG_NET_MULTI
++#define CONFIG_ETHACT aspeednic#0
++#define CONFIG_GATEWAYIP 192.168.0.1
++#define CONFIG_NETMASK 255.255.255.0
++#define CONFIG_IPADDR 192.168.0.45
++#define CONFIG_SERVERIP 192.168.0.81
++#define CONFIG_ETHADDR 00:C0:A8:12:34:56
++#define CONFIG_ETH1ADDR 00:C0:A8:12:34:57
++
++/*
++ * SLT
++ */
++/*
++#define CONFIG_SLT
++#define CFG_CMD_SLT (CFG_CMD_VIDEOTEST | CFG_CMD_MACTEST | CFG_CMD_HACTEST | CFG_CMD_MICTEST)
++*/
++
++#endif /* __CONFIG_H */
+diff --git a/include/configs/ast2300_ast1070.h b/include/configs/ast2300_ast1070.h
+new file mode 100644
+index 0000000..a7abdf5
+--- /dev/null
++++ b/include/configs/ast2300_ast1070.h
+@@ -0,0 +1,323 @@
++/*
++ * (C) Copyright 2004
++ * Peter Chen <peterc@socle-tech.com.tw>
++ *
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License as
++ * published by the Free Software Foundation; either version 2 of
++ * the License, or (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
++ * MA 02111-1307 USA
++ */
++
++#ifndef __CONFIG_H
++#define __CONFIG_H
++
++/*
++ * High Level Configuration Options
++ * (easy to change)
++ */
++//#define CONFIG_INIT_CRITICAL /* define for U-BOOT 1.1.1 */
++#undef CONFIG_INIT_CRITICAL /* undef for U-BOOT 1.1.4 */
++#define CONFIG_ARM926EJS 1 /* This is an arm926ejs CPU */
++#define CONFIG_ASPEED 1
++#define CONFIG_AST2300 1
++#define CONFIG_AST1070 1
++//#define CONFIG_SYS_FLASH_CFI /* CONFIG_FLASH_CFI, CONFIG_FLASH_SPI is exclusive*/
++#define CONFIG_FLASH_SPI
++//#define CONFIG_2SPIFLASH /* Boot SPI: CS2, 2nd SPI: CS0 */
++#undef CONFIG_2SPIFLASH
++#undef CONFIG_ASPEED_SLT
++#define CONFIG_FLASH_AST2300
++#define CONFIG_FLASH_AST2300_DMA
++//#define CONFIG_FLASH_SPIx2_Dummy
++//#define CONFIG_FLASH_SPIx4_Dummy
++#define CONFIG_CRT_DISPLAY 1 /* undef if not support CRT */
++
++//#define CONFIG_USE_IRQ /* we don't need IRQ/FIQ stuff */
++#define CONFIG_MISC_INIT_R
++
++/*
++ * DRAM Config
++ *
++ * 1. DRAM Size //
++ * CONFIG_DRAM_512MBIT // 512M bit
++ * CONFIG_DRAM_1GBIT // 1G bit (default)
++ * CONFIG_DRAM_2GBIT // 2G bit
++ * CONFIG_DRAM_4GBIT // 4G bit
++ * 2. DRAM Speed //
++ * CONFIG_DRAM_336 // 336MHz (DDR-667)
++ * CONFIG_DRAM_408 // 408MHz (DDR-800) (default)
++ * 3. VGA Mode
++ * CONFIG_CRT_DISPLAY // define to disable VGA function
++ * 4. ECC Function enable
++ * CONFIG_DRAM_ECC // define to enable ECC function
++ * 5. UART Debug Message
++ * CONFIG_DRAM_UART_OUT // enable output message at UART5
++ * CONFIG_DRAM_UART_38400 // set the UART baud rate to 38400, default is 115200
++ */
++
++//1. DRAM Size
++//#define CONFIG_DRAM_512MBIT
++#define CONFIG_DRAM_1GBIT
++//#define CONFIG_DRAM_2GBIT
++//#define CONFIG_DRAM_4GBIT
++//2. DRAM Speed
++//#define CONFIG_DRAM_336
++#define CONFIG_DRAM_408
++//3. VGA Mode
++//#define CONFIG_CRT_DISPLAY
++//4. ECC Function enable
++//#define CONFIG_DRAM_ECC
++//5. UART Debug Message
++#define CONFIG_DRAM_UART_OUT
++//#define CONFIG_DRAM_UART_38400
++
++
++
++/*
++ * Environment Config
++ */
++#define CONFIG_CMDLINE_TAG 1 /* enable passing of ATAGs */
++#define CONFIG_SETUP_MEMORY_TAGS 1
++#define CONFIG_INITRD_TAG 1
++#define CONFIG_BOOTARGS "debug console=ttyS0,115200n8 ramdisk_size=16384 root=/dev/ram rw init=/linuxrc mem=80M"
++#define CONFIG_BOOTDELAY 3 /* autoboot after 3 seconds */
++#ifdef CONFIG_FLASH_AST2300
++#define CONFIG_BOOTCOMMAND "bootm 20080000 20300000"
++#else
++#ifdef CONFIG_SYS_FLASH_CFI
++#define CONFIG_BOOTCOMMAND "bootm 10080000 10300000"
++#else
++#define CONFIG_BOOTCOMMAND "bootm 14080000 14300000"
++#endif
++#endif
++#define CONFIG_BOOTFILE "all.bin"
++#define CONFIG_ENV_OVERWRITE
++
++/*
++ * Command line configuration.
++ */
++#include <config_cmd_default.h>
++
++#define CONFIG_CMD_DFL
++#define CONFIG_CMD_ENV
++#define CONFIG_CMD_FLASH
++#define CONFIG_CMD_NET
++#define CONFIG_CMD_PING
++#define CONFIG_CMD_I2C
++#define CONFIG_CMD_EEPROM
++
++/*
++ * CPU Setting
++ */
++#define CPU_CLOCK_RATE 18000000 /* 16.5 MHz clock for the ARM core */
++
++/*
++ * Size of malloc() pool
++ */
++#define CONFIG_SYS_MALLOC_LEN (CONFIG_ENV_SIZE + 768*1024)
++#define CONFIG_SYS_GBL_DATA_SIZE 128 /* size in bytes reserved for initial data */
++
++/*
++ * Stack sizes, The stack sizes are set up in start.S using the settings below
++ */
++#define CONFIG_STACKSIZE (128*1024) /* regular stack */
++#define CONFIG_STACKSIZE_IRQ (4*1024) /* IRQ stack */
++#define CONFIG_STACKSIZE_FIQ (4*1024) /* FIQ stack */
++
++/*
++ * Memory Configuration
++ */
++#define CONFIG_NR_DRAM_BANKS 1 /* we have 1 bank of DRAM */
++#define PHYS_SDRAM_1 0x40000000 /* SDRAM Bank #1 */
++#define PHYS_SDRAM_1_SIZE 0x4000000 /* 64 MB */
++
++#define CONFIG_SYS_SDRAM_BASE 0x40000000
++
++/*
++ * FLASH Configuration
++ */
++#ifdef CONFIG_SYS_FLASH_CFI /* NOR Flash */
++
++#ifdef CONFIG_FLASH_AST2300
++#define PHYS_FLASH_1 0x20000000 /* Flash Bank #1 */
++#else
++#define PHYS_FLASH_1 0x10000000 /* Flash Bank #1 */
++#endif
++
++#define CONFIG_SYS_FLASH_BASE PHYS_FLASH_1
++#define CONFIG_FLASH_BANKS_LIST { PHYS_FLASH_1 }
++
++#define CONFIG_SYS_MAX_FLASH_BANKS 1
++#define CONFIG_SYS_MAX_FLASH_SECT (256) /* max number of sectors on one chip */
++
++#define CONFIG_ENV_IS_IN_FLASH 1
++#define CONFIG_ENV_OFFSET 0x60000 /* environment starts here */
++#define CONFIG_ENV_SIZE 0x20000 /* Total Size of Environment Sector */
++
++#define CONFIG_SYS_FLASH_CFI_AMD_RESET
++#define CONFIG_SYS_FLASH_USE_BUFFER_WRITE
++
++#else /* SPI Flash */
++
++#ifdef CONFIG_FLASH_AST2300
++#define PHYS_FLASH_1 0x20000000 /* Flash Bank #1 */
++#else
++#define PHYS_FLASH_1 0x14000000 /* Flash Bank #1 */
++#define PHYS_FLASH_2 0x14800000 /* Flash Bank #2 */
++#define PHYS_FLASH_2_BASE 0x10000000
++#endif
++
++#ifdef CONFIG_2SPIFLASH
++#define CONFIG_SYS_FLASH_BASE PHYS_FLASH_2_BASE
++#define CONFIG_FLASH_BANKS_LIST { PHYS_FLASH_1, PHYS_FLASH_2 }
++#define CONFIG_SYS_MAX_FLASH_BANKS 2
++#define CONFIG_SYS_MAX_FLASH_SECT (1024) /* max number of sectors on one chip */
++
++#define CONFIG_ENV_IS_IN_FLASH 1
++#define CONFIG_ENV_OFFSET 0x7F0000 /* environment starts here */
++#define CONFIG_ENV_SIZE 0x010000 /* Total Size of Environment Sector */
++#else
++#define CONFIG_SYS_FLASH_BASE PHYS_FLASH_1
++#define CONFIG_FLASH_BANKS_LIST { PHYS_FLASH_1 }
++#define CONFIG_SYS_MAX_FLASH_BANKS 1
++#define CONFIG_SYS_MAX_FLASH_SECT (1024) /* max number of sectors on one chip */
++
++#define CONFIG_ENV_IS_IN_FLASH 1
++#define CONFIG_ENV_OFFSET 0x7F0000 /* environment starts here */
++#define CONFIG_ENV_SIZE 0x010000 /* Total Size of Environment Sector */
++#endif
++
++#endif
++
++#define __LITTLE_ENDIAN
++
++#define CONFIG_MONITOR_BASE TEXT_BASE
++#define CONFIG_MONITOR_LEN (192 << 10)
++
++/* timeout values are in ticks */
++#define CONFIG_SYS_FLASH_ERASE_TOUT (20*CONFIG_SYS_HZ) /* Timeout for Flash Erase */
++#define CONFIG_SYS_FLASH_WRITE_TOUT (20*CONFIG_SYS_HZ) /* Timeout for Flash Write */
++
++/*
++ * Miscellaneous configurable options
++ */
++#define CONFIG_SYS_LONGHELP /* undef to save memory */
++
++#define CONFIG_SYS_PROMPT "boot# " /* Monitor Command Prompt */
++#define CONFIG_SYS_CBSIZE 256 /* Console I/O Buffer Size */
++#define CONFIG_SYS_PBSIZE (CONFIG_SYS_CBSIZE+sizeof(CONFIG_SYS_PROMPT)+16) /* Print Buffer Size */
++#define CONFIG_SYS_MAXARGS 16 /* max number of command args */
++#define CONFIG_SYS_BARGSIZE CONFIG_SYS_CBSIZE /* Boot Argument Buffer Size */
++
++#define CONFIG_SYS_MEMTEST_START 0x40000000 /* memtest works on */
++#define CONFIG_SYS_MEMTEST_END 0x44FFFFFF /* 256 MB in DRAM */
++
++#define CONFIG_SYS_CLKS_IN_HZ /* everything, incl board info, in Hz */
++#undef CONFIG_SYS_CLKS_IN_HZ /* everything, incl board info, in Hz */
++
++#define CONFIG_SYS_LOAD_ADDR 0x43000000 /* default load address */
++
++#define CONFIG_SYS_TIMERBASE 0x1E782000 /* use timer 1 */
++#define CONFIG_SYS_HZ (1*1000*1000) /* use external clk (1M) */
++
++/*
++ * Serial Configuration
++ */
++#define CONFIG_SYS_NS16550
++#define CONFIG_SYS_NS16550_SERIAL
++#define CONFIG_SYS_NS16550_REG_SIZE 4
++#define CONFIG_SYS_NS16550_CLK 24000000
++#define CONFIG_SYS_NS16550_COM1 0x1e783000
++#define CONFIG_SYS_NS16550_COM2 0x1e784000
++#define CONFIG_SYS_LOADS_BAUD_CHANGE
++#define CONFIG_SERIAL1 1
++#define CONFIG_CONS_INDEX 2
++#define CONFIG_BAUDRATE 115200
++#define CONFIG_SYS_BAUDRATE_TABLE { 9600, 19200, 38400, 57600, 115200 }
++
++/*
++ * USB device configuration
++ */
++/*
++#define CONFIG_USB_DEVICE 1
++#define CONFIG_USB_TTY 1
++
++#define CONFIG_USBD_VENDORID 0x1234
++#define CONFIG_USBD_PRODUCTID 0x5678
++#define CONFIG_USBD_MANUFACTURER "Siemens"
++#define CONFIG_USBD_PRODUCT_NAME "SX1"
++*/
++
++/*
++ * I2C configuration
++ */
++#define CONFIG_HARD_I2C
++#define CONFIG_SYS_I2C_SPEED 100000
++#define CONFIG_SYS_I2C_SLAVE 1
++#define CONFIG_DRIVER_ASPEED_I2C
++
++/*
++* EEPROM configuration
++*/
++#define CONFIG_SYS_I2C_EEPROM_ADDR_LEN 2
++#define CONFIG_SYS_I2C_EEPROM_ADDR 0xa0
++
++/*
++ * NIC configuration
++ */
++#define __BYTE_ORDER __LITTLE_ENDIAN
++#define __LITTLE_ENDIAN_BITFIELD
++#define CONFIG_MAC_PARTITION
++#define CONFIG_ASPEEDNIC
++//#define CONFIG_MAC1_PHY_LINK_INTERRUPT
++#define CONFIG_MAC2_ENABLE
++#define CONFIG_MAC2_PHY_LINK_INTERRUPT
++/*
++*-------------------------------------------------------------------------------
++* NOTICE: MAC1 and MAC2 now have their own seperate PHY configuration.
++* We use 2 bits for each MAC in the scratch register(D[15:11] in 0x1E6E2040) to
++* inform kernel driver.
++* The meanings of the 2 bits are:
++* 00(0): Dedicated PHY
++* 01(1): ASPEED's EVA + INTEL's NC-SI PHY chip EVA
++* 10(2): ASPEED's MAC is connected to NC-SI PHY chip directly
++* 11: Reserved
++*
++* We use CONFIG_MAC1_PHY_SETTING and CONFIG_MAC2_PHY_SETTING in U-Boot
++* 0: Dedicated PHY
++* 1: ASPEED's EVA + INTEL's NC-SI PHY chip EVA
++* 2: ASPEED's MAC is connected to NC-SI PHY chip directly
++* 3: Reserved
++*-------------------------------------------------------------------------------
++*/
++#define CONFIG_MAC1_PHY_SETTING 0
++#define CONFIG_MAC2_PHY_SETTING 0
++#define CONFIG_MAC_INTERFACE_CLOCK_DELAY 0x2255
++#define CONFIG_NET_MULTI
++#define CONFIG_ETHACT aspeednic#0
++#define CONFIG_GATEWAYIP 192.168.0.1
++#define CONFIG_NETMASK 255.255.255.0
++#define CONFIG_IPADDR 192.168.0.45
++#define CONFIG_SERVERIP 192.168.0.81
++#define CONFIG_ETHADDR 00:C0:A8:12:34:56
++#define CONFIG_ETH1ADDR 00:C0:A8:12:34:57
++
++/*
++ * SLT
++ */
++/*
++#define CONFIG_SLT
++#define CFG_CMD_SLT (CFG_CMD_VIDEOTEST | CFG_CMD_MACTEST | CFG_CMD_HACTEST | CFG_CMD_MICTEST)
++*/
++
++#endif /* __CONFIG_H */
+diff --git a/include/configs/ast2300_nor.h b/include/configs/ast2300_nor.h
+new file mode 100644
+index 0000000..77b8fe3
+--- /dev/null
++++ b/include/configs/ast2300_nor.h
+@@ -0,0 +1,322 @@
++/*
++ * (C) Copyright 2004
++ * Peter Chen <peterc@socle-tech.com.tw>
++ *
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License as
++ * published by the Free Software Foundation; either version 2 of
++ * the License, or (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
++ * MA 02111-1307 USA
++ */
++
++#ifndef __CONFIG_H
++#define __CONFIG_H
++
++/*
++ * High Level Configuration Options
++ * (easy to change)
++ */
++//#define CONFIG_INIT_CRITICAL /* define for U-BOOT 1.1.1 */
++#undef CONFIG_INIT_CRITICAL /* undef for U-BOOT 1.1.4 */
++#define CONFIG_ARM926EJS 1 /* This is an arm926ejs CPU */
++#define CONFIG_ASPEED 1
++#define CONFIG_AST2300 1
++#define CONFIG_SYS_FLASH_CFI /* CONFIG_FLASH_CFI, CONFIG_FLASH_SPI is exclusive*/
++//#define CONFIG_FLASH_SPI
++//#define CONFIG_2SPIFLASH /* Boot SPI: CS2, 2nd SPI: CS0 */
++#undef CONFIG_2SPIFLASH
++#undef CONFIG_ASPEED_SLT
++#define CONFIG_FLASH_AST2300
++#define CONFIG_FLASH_AST2300_DMA
++//#define CONFIG_FLASH_SPIx2_Dummy
++//#define CONFIG_FLASH_SPIx4_Dummy
++#define CONFIG_CRT_DISPLAY 1 /* undef if not support CRT */
++
++//#define CONFIG_USE_IRQ /* we don't need IRQ/FIQ stuff */
++#define CONFIG_MISC_INIT_R
++
++/*
++ * DRAM Config
++ *
++ * 1. DRAM Size //
++ * CONFIG_DRAM_512MBIT // 512M bit
++ * CONFIG_DRAM_1GBIT // 1G bit (default)
++ * CONFIG_DRAM_2GBIT // 2G bit
++ * CONFIG_DRAM_4GBIT // 4G bit
++ * 2. DRAM Speed //
++ * CONFIG_DRAM_336 // 336MHz (DDR-667)
++ * CONFIG_DRAM_408 // 408MHz (DDR-800) (default)
++ * 3. VGA Mode
++ * CONFIG_CRT_DISPLAY // define to disable VGA function
++ * 4. ECC Function enable
++ * CONFIG_DRAM_ECC // define to enable ECC function
++ * 5. UART Debug Message
++ * CONFIG_DRAM_UART_OUT // enable output message at UART5
++ * CONFIG_DRAM_UART_38400 // set the UART baud rate to 38400, default is 115200
++ */
++
++//1. DRAM Size
++//#define CONFIG_DRAM_512MBIT
++#define CONFIG_DRAM_1GBIT
++//#define CONFIG_DRAM_2GBIT
++//#define CONFIG_DRAM_4GBIT
++//2. DRAM Speed
++//#define CONFIG_DRAM_336
++#define CONFIG_DRAM_408
++//3. VGA Mode
++//#define CONFIG_CRT_DISPLAY
++//4. ECC Function enable
++//#define CONFIG_DRAM_ECC
++//5. UART Debug Message
++#define CONFIG_DRAM_UART_OUT
++//#define CONFIG_DRAM_UART_38400
++
++
++
++/*
++ * Environment Config
++ */
++#define CONFIG_CMDLINE_TAG 1 /* enable passing of ATAGs */
++#define CONFIG_SETUP_MEMORY_TAGS 1
++#define CONFIG_INITRD_TAG 1
++#define CONFIG_BOOTARGS "debug console=ttyS0,115200n8 ramdisk_size=16384 root=/dev/ram rw init=/linuxrc mem=80M"
++#define CONFIG_BOOTDELAY 3 /* autoboot after 3 seconds */
++#ifdef CONFIG_FLASH_AST2300
++#define CONFIG_BOOTCOMMAND "bootm 20080000 20300000"
++#else
++#ifdef CONFIG_SYS_FLASH_CFI
++#define CONFIG_BOOTCOMMAND "bootm 10080000 10300000"
++#else
++#define CONFIG_BOOTCOMMAND "bootm 14080000 14300000"
++#endif
++#endif
++#define CONFIG_BOOTFILE "all.bin"
++#define CONFIG_ENV_OVERWRITE
++
++/*
++ * Command line configuration.
++ */
++#include <config_cmd_default.h>
++
++#define CONFIG_CMD_DFL
++#define CONFIG_CMD_ENV
++#define CONFIG_CMD_FLASH
++#define CONFIG_CMD_NET
++#define CONFIG_CMD_PING
++#define CONFIG_CMD_I2C
++#define CONFIG_CMD_EEPROM
++
++/*
++ * CPU Setting
++ */
++#define CPU_CLOCK_RATE 18000000 /* 16.5 MHz clock for the ARM core */
++
++/*
++ * Size of malloc() pool
++ */
++#define CONFIG_SYS_MALLOC_LEN (CONFIG_ENV_SIZE + 768*1024)
++#define CONFIG_SYS_GBL_DATA_SIZE 128 /* size in bytes reserved for initial data */
++
++/*
++ * Stack sizes, The stack sizes are set up in start.S using the settings below
++ */
++#define CONFIG_STACKSIZE (128*1024) /* regular stack */
++#define CONFIG_STACKSIZE_IRQ (4*1024) /* IRQ stack */
++#define CONFIG_STACKSIZE_FIQ (4*1024) /* FIQ stack */
++
++/*
++ * Memory Configuration
++ */
++#define CONFIG_NR_DRAM_BANKS 1 /* we have 1 bank of DRAM */
++#define PHYS_SDRAM_1 0x40000000 /* SDRAM Bank #1 */
++#define PHYS_SDRAM_1_SIZE 0x4000000 /* 64 MB */
++
++#define CONFIG_SYS_SDRAM_BASE 0x40000000
++
++/*
++ * FLASH Configuration
++ */
++#ifdef CONFIG_SYS_FLASH_CFI /* NOR Flash */
++
++#ifdef CONFIG_FLASH_AST2300
++#define PHYS_FLASH_1 0x20000000 /* Flash Bank #1 */
++#else
++#define PHYS_FLASH_1 0x10000000 /* Flash Bank #1 */
++#endif
++
++#define CONFIG_SYS_FLASH_BASE PHYS_FLASH_1
++#define CONFIG_FLASH_BANKS_LIST { PHYS_FLASH_1 }
++
++#define CONFIG_SYS_MAX_FLASH_BANKS 1
++#define CONFIG_SYS_MAX_FLASH_SECT (256) /* max number of sectors on one chip */
++
++#define CONFIG_ENV_IS_IN_FLASH 1
++#define CONFIG_ENV_OFFSET 0x60000 /* environment starts here */
++#define CONFIG_ENV_SIZE 0x20000 /* Total Size of Environment Sector */
++
++#define CONFIG_SYS_FLASH_CFI_AMD_RESET
++#define CONFIG_SYS_FLASH_USE_BUFFER_WRITE
++
++#else /* SPI Flash */
++
++#ifdef CONFIG_FLASH_AST2300
++#define PHYS_FLASH_1 0x20000000 /* Flash Bank #1 */
++#else
++#define PHYS_FLASH_1 0x14000000 /* Flash Bank #1 */
++#define PHYS_FLASH_2 0x14800000 /* Flash Bank #2 */
++#define PHYS_FLASH_2_BASE 0x10000000
++#endif
++
++#ifdef CONFIG_2SPIFLASH
++#define CONFIG_SYS_FLASH_BASE PHYS_FLASH_2_BASE
++#define CONFIG_FLASH_BANKS_LIST { PHYS_FLASH_1, PHYS_FLASH_2 }
++#define CONFIG_SYS_MAX_FLASH_BANKS 2
++#define CONFIG_SYS_MAX_FLASH_SECT (1024) /* max number of sectors on one chip */
++
++#define CONFIG_ENV_IS_IN_FLASH 1
++#define CONFIG_ENV_OFFSET 0x7F0000 /* environment starts here */
++#define CONFIG_ENV_SIZE 0x010000 /* Total Size of Environment Sector */
++#else
++#define CONFIG_SYS_FLASH_BASE PHYS_FLASH_1
++#define CONFIG_FLASH_BANKS_LIST { PHYS_FLASH_1 }
++#define CONFIG_SYS_MAX_FLASH_BANKS 1
++#define CONFIG_SYS_MAX_FLASH_SECT (1024) /* max number of sectors on one chip */
++
++#define CONFIG_ENV_IS_IN_FLASH 1
++#define CONFIG_ENV_OFFSET 0x7F0000 /* environment starts here */
++#define CONFIG_ENV_SIZE 0x010000 /* Total Size of Environment Sector */
++#endif
++
++#endif
++
++#define __LITTLE_ENDIAN
++
++#define CONFIG_MONITOR_BASE TEXT_BASE
++#define CONFIG_MONITOR_LEN (192 << 10)
++
++/* timeout values are in ticks */
++#define CONFIG_SYS_FLASH_ERASE_TOUT (20*CONFIG_SYS_HZ) /* Timeout for Flash Erase */
++#define CONFIG_SYS_FLASH_WRITE_TOUT (20*CONFIG_SYS_HZ) /* Timeout for Flash Write */
++
++/*
++ * Miscellaneous configurable options
++ */
++#define CONFIG_SYS_LONGHELP /* undef to save memory */
++
++#define CONFIG_SYS_PROMPT "boot# " /* Monitor Command Prompt */
++#define CONFIG_SYS_CBSIZE 256 /* Console I/O Buffer Size */
++#define CONFIG_SYS_PBSIZE (CONFIG_SYS_CBSIZE+sizeof(CONFIG_SYS_PROMPT)+16) /* Print Buffer Size */
++#define CONFIG_SYS_MAXARGS 16 /* max number of command args */
++#define CONFIG_SYS_BARGSIZE CONFIG_SYS_CBSIZE /* Boot Argument Buffer Size */
++
++#define CONFIG_SYS_MEMTEST_START 0x40000000 /* memtest works on */
++#define CONFIG_SYS_MEMTEST_END 0x44FFFFFF /* 256 MB in DRAM */
++
++#define CONFIG_SYS_CLKS_IN_HZ /* everything, incl board info, in Hz */
++#undef CONFIG_SYS_CLKS_IN_HZ /* everything, incl board info, in Hz */
++
++#define CONFIG_SYS_LOAD_ADDR 0x43000000 /* default load address */
++
++#define CONFIG_SYS_TIMERBASE 0x1E782000 /* use timer 1 */
++#define CONFIG_SYS_HZ (1*1000*1000) /* use external clk (1M) */
++
++/*
++ * Serial Configuration
++ */
++#define CONFIG_SYS_NS16550
++#define CONFIG_SYS_NS16550_SERIAL
++#define CONFIG_SYS_NS16550_REG_SIZE 4
++#define CONFIG_SYS_NS16550_CLK 24000000
++#define CONFIG_SYS_NS16550_COM1 0x1e783000
++#define CONFIG_SYS_NS16550_COM2 0x1e784000
++#define CONFIG_SYS_LOADS_BAUD_CHANGE
++#define CONFIG_SERIAL1 1
++#define CONFIG_CONS_INDEX 2
++#define CONFIG_BAUDRATE 115200
++#define CONFIG_SYS_BAUDRATE_TABLE { 9600, 19200, 38400, 57600, 115200 }
++
++/*
++ * USB device configuration
++ */
++/*
++#define CONFIG_USB_DEVICE 1
++#define CONFIG_USB_TTY 1
++
++#define CONFIG_USBD_VENDORID 0x1234
++#define CONFIG_USBD_PRODUCTID 0x5678
++#define CONFIG_USBD_MANUFACTURER "Siemens"
++#define CONFIG_USBD_PRODUCT_NAME "SX1"
++*/
++
++/*
++ * I2C configuration
++ */
++#define CONFIG_HARD_I2C
++#define CONFIG_SYS_I2C_SPEED 100000
++#define CONFIG_SYS_I2C_SLAVE 1
++#define CONFIG_DRIVER_ASPEED_I2C
++
++/*
++* EEPROM configuration
++*/
++#define CONFIG_SYS_I2C_EEPROM_ADDR_LEN 2
++#define CONFIG_SYS_I2C_EEPROM_ADDR 0xa0
++
++/*
++ * NIC configuration
++ */
++#define __BYTE_ORDER __LITTLE_ENDIAN
++#define __LITTLE_ENDIAN_BITFIELD
++#define CONFIG_MAC_PARTITION
++#define CONFIG_ASPEEDNIC
++//#define CONFIG_MAC1_PHY_LINK_INTERRUPT
++#define CONFIG_MAC2_ENABLE
++#define CONFIG_MAC2_PHY_LINK_INTERRUPT
++/*
++*-------------------------------------------------------------------------------
++* NOTICE: MAC1 and MAC2 now have their own seperate PHY configuration.
++* We use 2 bits for each MAC in the scratch register(D[15:11] in 0x1E6E2040) to
++* inform kernel driver.
++* The meanings of the 2 bits are:
++* 00(0): Dedicated PHY
++* 01(1): ASPEED's EVA + INTEL's NC-SI PHY chip EVA
++* 10(2): ASPEED's MAC is connected to NC-SI PHY chip directly
++* 11: Reserved
++*
++* We use CONFIG_MAC1_PHY_SETTING and CONFIG_MAC2_PHY_SETTING in U-Boot
++* 0: Dedicated PHY
++* 1: ASPEED's EVA + INTEL's NC-SI PHY chip EVA
++* 2: ASPEED's MAC is connected to NC-SI PHY chip directly
++* 3: Reserved
++*-------------------------------------------------------------------------------
++*/
++#define CONFIG_MAC1_PHY_SETTING 0
++#define CONFIG_MAC2_PHY_SETTING 0
++#define CONFIG_MAC_INTERFACE_CLOCK_DELAY 0x2255
++#define CONFIG_NET_MULTI
++#define CONFIG_ETHACT aspeednic#0
++#define CONFIG_GATEWAYIP 192.168.0.1
++#define CONFIG_NETMASK 255.255.255.0
++#define CONFIG_IPADDR 192.168.0.188
++#define CONFIG_SERVERIP 192.168.0.106
++#define CONFIG_ETHADDR 00:C0:A8:12:34:56
++#define CONFIG_ETH1ADDR 00:C0:A8:12:34:57
++
++/*
++ * SLT
++ */
++/*
++#define CONFIG_SLT
++#define CFG_CMD_SLT (CFG_CMD_VIDEOTEST | CFG_CMD_MACTEST | CFG_CMD_HACTEST | CFG_CMD_MICTEST)
++*/
++
++#endif /* __CONFIG_H */
+diff --git a/include/configs/ast2300_spi.h b/include/configs/ast2300_spi.h
+new file mode 100644
+index 0000000..bc65530
+--- /dev/null
++++ b/include/configs/ast2300_spi.h
+@@ -0,0 +1,322 @@
++/*
++ * (C) Copyright 2004
++ * Peter Chen <peterc@socle-tech.com.tw>
++ *
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License as
++ * published by the Free Software Foundation; either version 2 of
++ * the License, or (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
++ * MA 02111-1307 USA
++ */
++
++#ifndef __CONFIG_H
++#define __CONFIG_H
++
++/*
++ * High Level Configuration Options
++ * (easy to change)
++ */
++//#define CONFIG_INIT_CRITICAL /* define for U-BOOT 1.1.1 */
++#undef CONFIG_INIT_CRITICAL /* undef for U-BOOT 1.1.4 */
++#define CONFIG_ARM926EJS 1 /* This is an arm926ejs CPU */
++#define CONFIG_ASPEED 1
++#define CONFIG_AST2300 1
++//#define CONFIG_SYS_FLASH_CFI /* CONFIG_FLASH_CFI, CONFIG_FLASH_SPI is exclusive*/
++#define CONFIG_FLASH_SPI
++//#define CONFIG_2SPIFLASH /* Boot SPI: CS2, 2nd SPI: CS0 */
++#undef CONFIG_2SPIFLASH
++#undef CONFIG_ASPEED_SLT
++#define CONFIG_FLASH_AST2300
++#define CONFIG_FLASH_AST2300_DMA
++//#define CONFIG_FLASH_SPIx2_Dummy
++//#define CONFIG_FLASH_SPIx4_Dummy
++#define CONFIG_CRT_DISPLAY 1 /* undef if not support CRT */
++
++//#define CONFIG_USE_IRQ /* we don't need IRQ/FIQ stuff */
++#define CONFIG_MISC_INIT_R
++
++/*
++ * DRAM Config
++ *
++ * 1. DRAM Size //
++ * CONFIG_DRAM_512MBIT // 512M bit
++ * CONFIG_DRAM_1GBIT // 1G bit (default)
++ * CONFIG_DRAM_2GBIT // 2G bit
++ * CONFIG_DRAM_4GBIT // 4G bit
++ * 2. DRAM Speed //
++ * CONFIG_DRAM_336 // 336MHz (DDR-667)
++ * CONFIG_DRAM_408 // 408MHz (DDR-800) (default)
++ * 3. VGA Mode
++ * CONFIG_CRT_DISPLAY // define to disable VGA function
++ * 4. ECC Function enable
++ * CONFIG_DRAM_ECC // define to enable ECC function
++ * 5. UART Debug Message
++ * CONFIG_DRAM_UART_OUT // enable output message at UART5
++ * CONFIG_DRAM_UART_38400 // set the UART baud rate to 38400, default is 115200
++ */
++
++//1. DRAM Size
++//#define CONFIG_DRAM_512MBIT
++#define CONFIG_DRAM_1GBIT
++//#define CONFIG_DRAM_2GBIT
++//#define CONFIG_DRAM_4GBIT
++//2. DRAM Speed
++//#define CONFIG_DRAM_336
++#define CONFIG_DRAM_408
++//3. VGA Mode
++//#define CONFIG_CRT_DISPLAY
++//4. ECC Function enable
++//#define CONFIG_DRAM_ECC
++//5. UART Debug Message
++#define CONFIG_DRAM_UART_OUT
++//#define CONFIG_DRAM_UART_38400
++
++
++
++/*
++ * Environment Config
++ */
++#define CONFIG_CMDLINE_TAG 1 /* enable passing of ATAGs */
++#define CONFIG_SETUP_MEMORY_TAGS 1
++#define CONFIG_INITRD_TAG 1
++#define CONFIG_BOOTARGS "debug console=ttyS0,115200n8 ramdisk_size=16384 root=/dev/ram rw init=/linuxrc mem=80M"
++#define CONFIG_BOOTDELAY 3 /* autoboot after 3 seconds */
++#ifdef CONFIG_FLASH_AST2300
++#define CONFIG_BOOTCOMMAND "bootm 20080000 20300000"
++#else
++#ifdef CONFIG_SYS_FLASH_CFI
++#define CONFIG_BOOTCOMMAND "bootm 10080000 10300000"
++#else
++#define CONFIG_BOOTCOMMAND "bootm 14080000 14300000"
++#endif
++#endif
++#define CONFIG_BOOTFILE "all.bin"
++#define CONFIG_ENV_OVERWRITE
++
++/*
++ * Command line configuration.
++ */
++#include <config_cmd_default.h>
++
++#define CONFIG_CMD_DFL
++#define CONFIG_CMD_ENV
++#define CONFIG_CMD_FLASH
++#define CONFIG_CMD_NET
++#define CONFIG_CMD_PING
++#define CONFIG_CMD_I2C
++#define CONFIG_CMD_EEPROM
++
++/*
++ * CPU Setting
++ */
++#define CPU_CLOCK_RATE 18000000 /* 16.5 MHz clock for the ARM core */
++
++/*
++ * Size of malloc() pool
++ */
++#define CONFIG_SYS_MALLOC_LEN (CONFIG_ENV_SIZE + 768*1024)
++#define CONFIG_SYS_GBL_DATA_SIZE 128 /* size in bytes reserved for initial data */
++
++/*
++ * Stack sizes, The stack sizes are set up in start.S using the settings below
++ */
++#define CONFIG_STACKSIZE (128*1024) /* regular stack */
++#define CONFIG_STACKSIZE_IRQ (4*1024) /* IRQ stack */
++#define CONFIG_STACKSIZE_FIQ (4*1024) /* FIQ stack */
++
++/*
++ * Memory Configuration
++ */
++#define CONFIG_NR_DRAM_BANKS 1 /* we have 1 bank of DRAM */
++#define PHYS_SDRAM_1 0x40000000 /* SDRAM Bank #1 */
++#define PHYS_SDRAM_1_SIZE 0x4000000 /* 64 MB */
++
++#define CONFIG_SYS_SDRAM_BASE 0x40000000
++
++/*
++ * FLASH Configuration
++ */
++#ifdef CONFIG_SYS_FLASH_CFI /* NOR Flash */
++
++#ifdef CONFIG_FLASH_AST2300
++#define PHYS_FLASH_1 0x20000000 /* Flash Bank #1 */
++#else
++#define PHYS_FLASH_1 0x10000000 /* Flash Bank #1 */
++#endif
++
++#define CONFIG_SYS_FLASH_BASE PHYS_FLASH_1
++#define CONFIG_FLASH_BANKS_LIST { PHYS_FLASH_1 }
++
++#define CONFIG_SYS_MAX_FLASH_BANKS 1
++#define CONFIG_SYS_MAX_FLASH_SECT (256) /* max number of sectors on one chip */
++
++#define CONFIG_ENV_IS_IN_FLASH 1
++#define CONFIG_ENV_OFFSET 0x60000 /* environment starts here */
++#define CONFIG_ENV_SIZE 0x20000 /* Total Size of Environment Sector */
++
++#define CONFIG_SYS_FLASH_CFI_AMD_RESET
++#define CONFIG_SYS_FLASH_USE_BUFFER_WRITE
++
++#else /* SPI Flash */
++
++#ifdef CONFIG_FLASH_AST2300
++#define PHYS_FLASH_1 0x20000000 /* Flash Bank #1 */
++#else
++#define PHYS_FLASH_1 0x14000000 /* Flash Bank #1 */
++#define PHYS_FLASH_2 0x14800000 /* Flash Bank #2 */
++#define PHYS_FLASH_2_BASE 0x10000000
++#endif
++
++#ifdef CONFIG_2SPIFLASH
++#define CONFIG_SYS_FLASH_BASE PHYS_FLASH_2_BASE
++#define CONFIG_FLASH_BANKS_LIST { PHYS_FLASH_1, PHYS_FLASH_2 }
++#define CONFIG_SYS_MAX_FLASH_BANKS 2
++#define CONFIG_SYS_MAX_FLASH_SECT (1024) /* max number of sectors on one chip */
++
++#define CONFIG_ENV_IS_IN_FLASH 1
++#define CONFIG_ENV_OFFSET 0x7F0000 /* environment starts here */
++#define CONFIG_ENV_SIZE 0x010000 /* Total Size of Environment Sector */
++#else
++#define CONFIG_SYS_FLASH_BASE PHYS_FLASH_1
++#define CONFIG_FLASH_BANKS_LIST { PHYS_FLASH_1 }
++#define CONFIG_SYS_MAX_FLASH_BANKS 1
++#define CONFIG_SYS_MAX_FLASH_SECT (1024) /* max number of sectors on one chip */
++
++#define CONFIG_ENV_IS_IN_FLASH 1
++#define CONFIG_ENV_OFFSET 0x7F0000 /* environment starts here */
++#define CONFIG_ENV_SIZE 0x010000 /* Total Size of Environment Sector */
++#endif
++
++#endif
++
++#define __LITTLE_ENDIAN
++
++#define CONFIG_MONITOR_BASE TEXT_BASE
++#define CONFIG_MONITOR_LEN (192 << 10)
++
++/* timeout values are in ticks */
++#define CONFIG_SYS_FLASH_ERASE_TOUT (20*CONFIG_SYS_HZ) /* Timeout for Flash Erase */
++#define CONFIG_SYS_FLASH_WRITE_TOUT (20*CONFIG_SYS_HZ) /* Timeout for Flash Write */
++
++/*
++ * Miscellaneous configurable options
++ */
++#define CONFIG_SYS_LONGHELP /* undef to save memory */
++
++#define CONFIG_SYS_PROMPT "boot# " /* Monitor Command Prompt */
++#define CONFIG_SYS_CBSIZE 256 /* Console I/O Buffer Size */
++#define CONFIG_SYS_PBSIZE (CONFIG_SYS_CBSIZE+sizeof(CONFIG_SYS_PROMPT)+16) /* Print Buffer Size */
++#define CONFIG_SYS_MAXARGS 16 /* max number of command args */
++#define CONFIG_SYS_BARGSIZE CONFIG_SYS_CBSIZE /* Boot Argument Buffer Size */
++
++#define CONFIG_SYS_MEMTEST_START 0x40000000 /* memtest works on */
++#define CONFIG_SYS_MEMTEST_END 0x44FFFFFF /* 256 MB in DRAM */
++
++#define CONFIG_SYS_CLKS_IN_HZ /* everything, incl board info, in Hz */
++#undef CONFIG_SYS_CLKS_IN_HZ /* everything, incl board info, in Hz */
++
++#define CONFIG_SYS_LOAD_ADDR 0x43000000 /* default load address */
++
++#define CONFIG_SYS_TIMERBASE 0x1E782000 /* use timer 1 */
++#define CONFIG_SYS_HZ (1*1000*1000) /* use external clk (1M) */
++
++/*
++ * Serial Configuration
++ */
++#define CONFIG_SYS_NS16550
++#define CONFIG_SYS_NS16550_SERIAL
++#define CONFIG_SYS_NS16550_REG_SIZE 4
++#define CONFIG_SYS_NS16550_CLK 24000000
++#define CONFIG_SYS_NS16550_COM1 0x1e783000
++#define CONFIG_SYS_NS16550_COM2 0x1e784000
++#define CONFIG_SYS_LOADS_BAUD_CHANGE
++#define CONFIG_SERIAL1 1
++#define CONFIG_CONS_INDEX 2
++#define CONFIG_BAUDRATE 115200
++#define CONFIG_SYS_BAUDRATE_TABLE { 9600, 19200, 38400, 57600, 115200 }
++
++/*
++ * USB device configuration
++ */
++/*
++#define CONFIG_USB_DEVICE 1
++#define CONFIG_USB_TTY 1
++
++#define CONFIG_USBD_VENDORID 0x1234
++#define CONFIG_USBD_PRODUCTID 0x5678
++#define CONFIG_USBD_MANUFACTURER "Siemens"
++#define CONFIG_USBD_PRODUCT_NAME "SX1"
++*/
++
++/*
++ * I2C configuration
++ */
++#define CONFIG_HARD_I2C
++#define CONFIG_SYS_I2C_SPEED 100000
++#define CONFIG_SYS_I2C_SLAVE 1
++#define CONFIG_DRIVER_ASPEED_I2C
++
++/*
++* EEPROM configuration
++*/
++#define CONFIG_SYS_I2C_EEPROM_ADDR_LEN 2
++#define CONFIG_SYS_I2C_EEPROM_ADDR 0xa0
++
++/*
++ * NIC configuration
++ */
++#define __BYTE_ORDER __LITTLE_ENDIAN
++#define __LITTLE_ENDIAN_BITFIELD
++#define CONFIG_MAC_PARTITION
++#define CONFIG_ASPEEDNIC
++//#define CONFIG_MAC1_PHY_LINK_INTERRUPT
++#define CONFIG_MAC2_ENABLE
++#define CONFIG_MAC2_PHY_LINK_INTERRUPT
++/*
++*-------------------------------------------------------------------------------
++* NOTICE: MAC1 and MAC2 now have their own seperate PHY configuration.
++* We use 2 bits for each MAC in the scratch register(D[15:11] in 0x1E6E2040) to
++* inform kernel driver.
++* The meanings of the 2 bits are:
++* 00(0): Dedicated PHY
++* 01(1): ASPEED's EVA + INTEL's NC-SI PHY chip EVA
++* 10(2): ASPEED's MAC is connected to NC-SI PHY chip directly
++* 11: Reserved
++*
++* We use CONFIG_MAC1_PHY_SETTING and CONFIG_MAC2_PHY_SETTING in U-Boot
++* 0: Dedicated PHY
++* 1: ASPEED's EVA + INTEL's NC-SI PHY chip EVA
++* 2: ASPEED's MAC is connected to NC-SI PHY chip directly
++* 3: Reserved
++*-------------------------------------------------------------------------------
++*/
++#define CONFIG_MAC1_PHY_SETTING 0
++#define CONFIG_MAC2_PHY_SETTING 0
++#define CONFIG_MAC_INTERFACE_CLOCK_DELAY 0x2255
++#define CONFIG_NET_MULTI
++#define CONFIG_ETHACT aspeednic#0
++#define CONFIG_GATEWAYIP 192.168.0.1
++#define CONFIG_NETMASK 255.255.255.0
++#define CONFIG_IPADDR 192.168.0.188
++#define CONFIG_SERVERIP 192.168.0.106
++#define CONFIG_ETHADDR 00:C0:A8:12:34:56
++#define CONFIG_ETH1ADDR 00:C0:A8:12:34:57
++
++/*
++ * SLT
++ */
++/*
++#define CONFIG_SLT
++#define CFG_CMD_SLT (CFG_CMD_VIDEOTEST | CFG_CMD_MACTEST | CFG_CMD_HACTEST | CFG_CMD_MICTEST)
++*/
++
++#endif /* __CONFIG_H */
+diff --git a/include/configs/ast2400.h b/include/configs/ast2400.h
+new file mode 100644
+index 0000000..670fcfd
+--- /dev/null
++++ b/include/configs/ast2400.h
+@@ -0,0 +1,328 @@
++/*
++ * (C) Copyright 2004
++ * Peter Chen <peterc@socle-tech.com.tw>
++ *
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License as
++ * published by the Free Software Foundation; either version 2 of
++ * the License, or (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
++ * MA 02111-1307 USA
++ */
++
++#ifndef __CONFIG_H
++#define __CONFIG_H
++
++/*
++ * High Level Configuration Options
++ * (easy to change)
++ */
++//#define CONFIG_INIT_CRITICAL /* define for U-BOOT 1.1.1 */
++#undef CONFIG_INIT_CRITICAL /* undef for U-BOOT 1.1.4 */
++//#define CONFIG_FPGA_ASPEED 1
++#define CONFIG_ARM926EJS 1 /* This is an arm926ejs CPU */
++#define CONFIG_ASPEED 1
++#define CONFIG_AST2400 1
++//#define CONFIG_AST1070 1
++//#define CONFIG_SYS_FLASH_CFI /* CONFIG_FLASH_CFI, CONFIG_FLASH_SPI is exclusive*/
++#define CONFIG_FLASH_SPI
++//#define CONFIG_2SPIFLASH /* Boot SPI: CS2, 2nd SPI: CS0 */
++#undef CONFIG_2SPIFLASH
++#undef CONFIG_ASPEED_SLT
++#define CONFIG_FLASH_AST2300
++//#define CONFIG_FLASH_AST2300_DMA
++//#define CONFIG_FLASH_SPIx2_Dummy
++//#define CONFIG_FLASH_SPIx4_Dummy
++#define CONFIG_CRT_DISPLAY 1 /* undef if not support CRT */
++
++//#define CONFIG_USE_IRQ /* we don't need IRQ/FIQ stuff */
++#define CONFIG_MISC_INIT_R
++
++/*
++ * DRAM Config
++ *
++ * 1. DRAM Size //
++ * CONFIG_DRAM_512MBIT // 512M bit
++ * CONFIG_DRAM_1GBIT // 1G bit (default)
++ * CONFIG_DRAM_2GBIT // 2G bit
++ * CONFIG_DRAM_4GBIT // 4G bit
++ * 2. DRAM Speed //
++ * CONFIG_DRAM_336 // 336MHz (DDR-667)
++ * CONFIG_DRAM_408 // 408MHz (DDR-800) (default)
++ * 3. VGA Mode
++ * CONFIG_CRT_DISPLAY // define to disable VGA function
++ * 4. ECC Function enable
++ * CONFIG_DRAM_ECC // define to enable ECC function
++ * 5. UART Debug Message
++ * CONFIG_DRAM_UART_OUT // enable output message at UART5
++ * CONFIG_DRAM_UART_38400 // set the UART baud rate to 38400, default is 115200
++ */
++
++//1. DRAM Size
++//#define CONFIG_DRAM_512MBIT
++#define CONFIG_DRAM_1GBIT
++//#define CONFIG_DRAM_2GBIT
++//#define CONFIG_DRAM_4GBIT
++//2. DRAM Speed
++//#define CONFIG_DRAM_336
++#define CONFIG_DRAM_408
++//3. VGA Mode
++//#define CONFIG_CRT_DISPLAY
++//4. ECC Function enable
++//#define CONFIG_DRAM_ECC
++//5. UART Debug Message
++#define CONFIG_DRAM_UART_OUT
++//#define CONFIG_DRAM_UART_38400
++
++
++
++/*
++ * Environment Config
++ */
++#define CONFIG_CMDLINE_TAG 1 /* enable passing of ATAGs */
++#define CONFIG_SETUP_MEMORY_TAGS 1
++#define CONFIG_INITRD_TAG 1
++#define CONFIG_BOOTARGS "debug console=ttyS0,115200n8 ramdisk_size=16384 root=/dev/ram rw init=/linuxrc mem=80M"
++#define CONFIG_UPDATE "tftp 40800000 ast2400.scr; so 40800000'"
++
++#define CONFIG_BOOTDELAY 3 /* autoboot after 3 seconds */
++#ifdef CONFIG_FLASH_AST2300
++#define CONFIG_BOOTCOMMAND "bootm 20080000 20300000"
++#else
++#ifdef CONFIG_SYS_FLASH_CFI
++#define CONFIG_BOOTCOMMAND "bootm 10080000 10300000"
++#else
++#define CONFIG_BOOTCOMMAND "bootm 14080000 14300000"
++#endif
++#endif
++#define CONFIG_BOOTFILE "all.bin"
++#define CONFIG_ENV_OVERWRITE
++
++/*
++ * Command line configuration.
++ */
++#include <config_cmd_default.h>
++
++#define CONFIG_CMD_DFL
++#define CONFIG_CMD_ENV
++#define CONFIG_CMD_FLASH
++#define CONFIG_CMD_NET
++#define CONFIG_CMD_PING
++#define CONFIG_CMD_I2C
++#define CONFIG_CMD_EEPROM
++#define CONFIG_CMD_NETTEST
++#define CONFIG_CMD_SLT
++
++/*
++ * CPU Setting
++ */
++#define CPU_CLOCK_RATE 18000000 /* 16.5 MHz clock for the ARM core */
++
++/*
++ * Size of malloc() pool
++ */
++#define CONFIG_SYS_MALLOC_LEN (CONFIG_ENV_SIZE + 768*1024)
++#define CONFIG_SYS_GBL_DATA_SIZE 128 /* size in bytes reserved for initial data */
++
++/*
++ * Stack sizes, The stack sizes are set up in start.S using the settings below
++ */
++#define CONFIG_STACKSIZE (128*1024) /* regular stack */
++#define CONFIG_STACKSIZE_IRQ (4*1024) /* IRQ stack */
++#define CONFIG_STACKSIZE_FIQ (4*1024) /* FIQ stack */
++
++/*
++ * Memory Configuration
++ */
++#define CONFIG_NR_DRAM_BANKS 1 /* we have 1 bank of DRAM */
++#define PHYS_SDRAM_1 0x40000000 /* SDRAM Bank #1 */
++#define PHYS_SDRAM_1_SIZE 0x4000000 /* 64 MB */
++
++#define CONFIG_SYS_SDRAM_BASE 0x40000000
++
++/*
++ * FLASH Configuration
++ */
++#ifdef CONFIG_SYS_FLASH_CFI /* NOR Flash */
++
++#ifdef CONFIG_FLASH_AST2300
++#define PHYS_FLASH_1 0x20000000 /* Flash Bank #1 */
++#else
++#define PHYS_FLASH_1 0x10000000 /* Flash Bank #1 */
++#endif
++
++#define CONFIG_SYS_FLASH_BASE PHYS_FLASH_1
++#define CONFIG_FLASH_BANKS_LIST { PHYS_FLASH_1 }
++
++#define CONFIG_SYS_MAX_FLASH_BANKS 1
++#define CONFIG_SYS_MAX_FLASH_SECT (256) /* max number of sectors on one chip */
++
++#define CONFIG_ENV_IS_IN_FLASH 1
++#define CONFIG_ENV_OFFSET 0x60000 /* environment starts here */
++#define CONFIG_ENV_SIZE 0x20000 /* Total Size of Environment Sector */
++
++#define CONFIG_SYS_FLASH_CFI_AMD_RESET
++#define CONFIG_SYS_FLASH_USE_BUFFER_WRITE
++
++#else /* SPI Flash */
++
++#ifdef CONFIG_FLASH_AST2300
++#define PHYS_FLASH_1 0x20000000 /* Flash Bank #1 */
++#else
++#define PHYS_FLASH_1 0x14000000 /* Flash Bank #1 */
++#define PHYS_FLASH_2 0x14800000 /* Flash Bank #2 */
++#define PHYS_FLASH_2_BASE 0x10000000
++#endif
++
++#ifdef CONFIG_2SPIFLASH
++#define CONFIG_SYS_FLASH_BASE PHYS_FLASH_2_BASE
++#define CONFIG_FLASH_BANKS_LIST { PHYS_FLASH_1, PHYS_FLASH_2 }
++#define CONFIG_SYS_MAX_FLASH_BANKS 2
++#define CONFIG_SYS_MAX_FLASH_SECT (1024) /* max number of sectors on one chip */
++
++#define CONFIG_ENV_IS_IN_FLASH 1
++#define CONFIG_ENV_OFFSET 0x7F0000 /* environment starts here */
++#define CONFIG_ENV_SIZE 0x010000 /* Total Size of Environment Sector */
++#else
++#define CONFIG_SYS_FLASH_BASE PHYS_FLASH_1
++#define CONFIG_FLASH_BANKS_LIST { PHYS_FLASH_1 }
++#define CONFIG_SYS_MAX_FLASH_BANKS 1
++#define CONFIG_SYS_MAX_FLASH_SECT (1024) /* max number of sectors on one chip */
++
++#define CONFIG_ENV_IS_IN_FLASH 1
++#define CONFIG_ENV_OFFSET 0x7F0000 /* environment starts here */
++#define CONFIG_ENV_SIZE 0x010000 /* Total Size of Environment Sector */
++#endif
++
++#endif
++
++#define __LITTLE_ENDIAN
++
++#define CONFIG_MONITOR_BASE TEXT_BASE
++#define CONFIG_MONITOR_LEN (192 << 10)
++
++/* timeout values are in ticks */
++#define CONFIG_SYS_FLASH_ERASE_TOUT (20*CONFIG_SYS_HZ) /* Timeout for Flash Erase */
++#define CONFIG_SYS_FLASH_WRITE_TOUT (20*CONFIG_SYS_HZ) /* Timeout for Flash Write */
++
++/*
++ * Miscellaneous configurable options
++ */
++#define CONFIG_SYS_LONGHELP /* undef to save memory */
++
++#define CONFIG_SYS_PROMPT "boot# " /* Monitor Command Prompt */
++#define CONFIG_SYS_CBSIZE 256 /* Console I/O Buffer Size */
++#define CONFIG_SYS_PBSIZE (CONFIG_SYS_CBSIZE+sizeof(CONFIG_SYS_PROMPT)+16) /* Print Buffer Size */
++#define CONFIG_SYS_MAXARGS 16 /* max number of command args */
++#define CONFIG_SYS_BARGSIZE CONFIG_SYS_CBSIZE /* Boot Argument Buffer Size */
++
++#define CONFIG_SYS_MEMTEST_START 0x40000000 /* memtest works on */
++#define CONFIG_SYS_MEMTEST_END 0x44FFFFFF /* 256 MB in DRAM */
++
++#define CONFIG_SYS_CLKS_IN_HZ /* everything, incl board info, in Hz */
++#undef CONFIG_SYS_CLKS_IN_HZ /* everything, incl board info, in Hz */
++
++#define CONFIG_SYS_LOAD_ADDR 0x43000000 /* default load address */
++
++#define CONFIG_SYS_TIMERBASE 0x1E782000 /* use timer 1 */
++#define CONFIG_SYS_HZ (1*1000*1000) /* use external clk (1M) */
++
++/*
++ * Serial Configuration
++ */
++#define CONFIG_SYS_NS16550
++#define CONFIG_SYS_NS16550_SERIAL
++#define CONFIG_SYS_NS16550_REG_SIZE 4
++#define CONFIG_SYS_NS16550_CLK 24000000
++#define CONFIG_SYS_NS16550_COM1 0x1e783000
++#define CONFIG_SYS_NS16550_COM2 0x1e784000
++#define CONFIG_SYS_LOADS_BAUD_CHANGE
++#define CONFIG_SERIAL1 1
++#define CONFIG_CONS_INDEX 2
++#define CONFIG_BAUDRATE 115200
++#define CONFIG_SYS_BAUDRATE_TABLE { 9600, 19200, 38400, 57600, 115200 }
++
++/*
++ * USB device configuration
++ */
++/*
++#define CONFIG_USB_DEVICE 1
++#define CONFIG_USB_TTY 1
++
++#define CONFIG_USBD_VENDORID 0x1234
++#define CONFIG_USBD_PRODUCTID 0x5678
++#define CONFIG_USBD_MANUFACTURER "Siemens"
++#define CONFIG_USBD_PRODUCT_NAME "SX1"
++*/
++
++/*
++ * I2C configuration
++ */
++#define CONFIG_HARD_I2C
++#define CONFIG_SYS_I2C_SPEED 100000
++#define CONFIG_SYS_I2C_SLAVE 1
++#define CONFIG_DRIVER_ASPEED_I2C
++
++/*
++* EEPROM configuration
++*/
++#define CONFIG_SYS_I2C_EEPROM_ADDR_LEN 2
++#define CONFIG_SYS_I2C_EEPROM_ADDR 0xa0
++
++/*
++ * NIC configuration
++ */
++#define __BYTE_ORDER __LITTLE_ENDIAN
++#define __LITTLE_ENDIAN_BITFIELD
++#define CONFIG_MAC_PARTITION
++#define CONFIG_ASPEEDNIC
++#define CONFIG_MAC1_PHY_LINK_INTERRUPT
++#define CONFIG_MAC2_ENABLE
++#define CONFIG_MAC2_PHY_LINK_INTERRUPT
++/*
++*-------------------------------------------------------------------------------
++* NOTICE: MAC1 and MAC2 now have their own seperate PHY configuration.
++* We use 2 bits for each MAC in the scratch register(D[15:11] in 0x1E6E2040) to
++* inform kernel driver.
++* The meanings of the 2 bits are:
++* 00(0): Dedicated PHY
++* 01(1): ASPEED's EVA + INTEL's NC-SI PHY chip EVA
++* 10(2): ASPEED's MAC is connected to NC-SI PHY chip directly
++* 11: Reserved
++*
++* We use CONFIG_MAC1_PHY_SETTING and CONFIG_MAC2_PHY_SETTING in U-Boot
++* 0: Dedicated PHY
++* 1: ASPEED's EVA + INTEL's NC-SI PHY chip EVA
++* 2: ASPEED's MAC is connected to NC-SI PHY chip directly
++* 3: Reserved
++*-------------------------------------------------------------------------------
++*/
++#define CONFIG_MAC1_PHY_SETTING 0
++#define CONFIG_MAC2_PHY_SETTING 0
++#define CONFIG_MAC_INTERFACE_CLOCK_DELAY 0x2255
++#define CONFIG_NET_MULTI
++#define CONFIG_ETHACT aspeednic#0
++#define CONFIG_GATEWAYIP 192.168.0.1
++#define CONFIG_NETMASK 255.255.255.0
++#define CONFIG_IPADDR 192.168.0.45
++#define CONFIG_SERVERIP 192.168.0.81
++#define CONFIG_ETHADDR 00:C0:A8:12:34:56
++#define CONFIG_ETH1ADDR 00:C0:A8:12:34:57
++
++/*
++ * SLT
++ */
++/*
++#define CONFIG_SLT
++#define CFG_CMD_SLT (CFG_CMD_VIDEOTEST | CFG_CMD_MACTEST | CFG_CMD_HACTEST | CFG_CMD_MICTEST)
++*/
++
++#endif /* __CONFIG_H */
+diff --git a/include/configs/ast2400_ast1070.h b/include/configs/ast2400_ast1070.h
+new file mode 100644
+index 0000000..df6c44b
+--- /dev/null
++++ b/include/configs/ast2400_ast1070.h
+@@ -0,0 +1,326 @@
++/*
++ * (C) Copyright 2004
++ * Peter Chen <peterc@socle-tech.com.tw>
++ *
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License as
++ * published by the Free Software Foundation; either version 2 of
++ * the License, or (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
++ * MA 02111-1307 USA
++ */
++
++#ifndef __CONFIG_H
++#define __CONFIG_H
++
++/*
++ * High Level Configuration Options
++ * (easy to change)
++ */
++//#define CONFIG_INIT_CRITICAL /* define for U-BOOT 1.1.1 */
++#undef CONFIG_INIT_CRITICAL /* undef for U-BOOT 1.1.4 */
++//#define CONFIG_FPGA_ASPEED 1
++#define CONFIG_ARM926EJS 1 /* This is an arm926ejs CPU */
++#define CONFIG_ASPEED 1
++#define CONFIG_AST2400 1
++#define CONFIG_AST1070 1
++//#define CONFIG_CALIBRATION 1
++//#define CONFIG_SYS_FLASH_CFI /* CONFIG_FLASH_CFI, CONFIG_FLASH_SPI is exclusive*/
++#define CONFIG_FLASH_SPI
++//#define CONFIG_2SPIFLASH /* Boot SPI: CS2, 2nd SPI: CS0 */
++#undef CONFIG_2SPIFLASH
++#undef CONFIG_ASPEED_SLT
++#define CONFIG_FLASH_AST2300
++#define CONFIG_FLASH_AST2300_DMA
++//#define CONFIG_FLASH_SPIx2_Dummy
++//#define CONFIG_FLASH_SPIx4_Dummy
++#define CONFIG_CRT_DISPLAY 1 /* undef if not support CRT */
++
++//#define CONFIG_USE_IRQ /* we don't need IRQ/FIQ stuff */
++#define CONFIG_MISC_INIT_R
++
++/*
++ * DRAM Config
++ *
++ * 1. DRAM Size //
++ * CONFIG_DRAM_512MBIT // 512M bit
++ * CONFIG_DRAM_1GBIT // 1G bit (default)
++ * CONFIG_DRAM_2GBIT // 2G bit
++ * CONFIG_DRAM_4GBIT // 4G bit
++ * 2. DRAM Speed //
++ * CONFIG_DRAM_336 // 336MHz (DDR-667)
++ * CONFIG_DRAM_408 // 408MHz (DDR-800) (default)
++ * 3. VGA Mode
++ * CONFIG_CRT_DISPLAY // define to disable VGA function
++ * 4. ECC Function enable
++ * CONFIG_DRAM_ECC // define to enable ECC function
++ * 5. UART Debug Message
++ * CONFIG_DRAM_UART_OUT // enable output message at UART5
++ * CONFIG_DRAM_UART_38400 // set the UART baud rate to 38400, default is 115200
++ */
++
++//1. DRAM Size
++//#define CONFIG_DRAM_512MBIT
++#define CONFIG_DRAM_1GBIT
++//#define CONFIG_DRAM_2GBIT
++//#define CONFIG_DRAM_4GBIT
++//2. DRAM Speed
++//#define CONFIG_DRAM_336
++#define CONFIG_DRAM_408
++//3. VGA Mode
++//#define CONFIG_CRT_DISPLAY
++//4. ECC Function enable
++//#define CONFIG_DRAM_ECC
++//5. UART Debug Message
++#define CONFIG_DRAM_UART_OUT
++//#define CONFIG_DRAM_UART_38400
++
++
++
++/*
++ * Environment Config
++ */
++#define CONFIG_CMDLINE_TAG 1 /* enable passing of ATAGs */
++#define CONFIG_SETUP_MEMORY_TAGS 1
++#define CONFIG_INITRD_TAG 1
++#define CONFIG_BOOTARGS "debug console=ttyS0,115200n8 ramdisk_size=16384 root=/dev/ram rw init=/linuxrc mem=80M"
++#define CONFIG_BOOTDELAY 3 /* autoboot after 3 seconds */
++#ifdef CONFIG_FLASH_AST2300
++#define CONFIG_BOOTCOMMAND "bootm 20080000 20300000"
++#else
++#ifdef CONFIG_SYS_FLASH_CFI
++#define CONFIG_BOOTCOMMAND "bootm 10080000 10300000"
++#else
++#define CONFIG_BOOTCOMMAND "bootm 14080000 14300000"
++#endif
++#endif
++#define CONFIG_BOOTFILE "all.bin"
++#define CONFIG_ENV_OVERWRITE
++
++/*
++ * Command line configuration.
++ */
++#include <config_cmd_default.h>
++
++#define CONFIG_CMD_DFL
++#define CONFIG_CMD_ENV
++#define CONFIG_CMD_FLASH
++#define CONFIG_CMD_NET
++#define CONFIG_CMD_PING
++#define CONFIG_CMD_I2C
++#define CONFIG_CMD_EEPROM
++#define CONFIG_CMD_NETTEST
++
++/*
++ * CPU Setting
++ */
++#define CPU_CLOCK_RATE 18000000 /* 16.5 MHz clock for the ARM core */
++
++/*
++ * Size of malloc() pool
++ */
++#define CONFIG_SYS_MALLOC_LEN (CONFIG_ENV_SIZE + 768*1024)
++#define CONFIG_SYS_GBL_DATA_SIZE 128 /* size in bytes reserved for initial data */
++
++/*
++ * Stack sizes, The stack sizes are set up in start.S using the settings below
++ */
++#define CONFIG_STACKSIZE (128*1024) /* regular stack */
++#define CONFIG_STACKSIZE_IRQ (4*1024) /* IRQ stack */
++#define CONFIG_STACKSIZE_FIQ (4*1024) /* FIQ stack */
++
++/*
++ * Memory Configuration
++ */
++#define CONFIG_NR_DRAM_BANKS 1 /* we have 1 bank of DRAM */
++#define PHYS_SDRAM_1 0x40000000 /* SDRAM Bank #1 */
++#define PHYS_SDRAM_1_SIZE 0x4000000 /* 64 MB */
++
++#define CONFIG_SYS_SDRAM_BASE 0x40000000
++
++/*
++ * FLASH Configuration
++ */
++#ifdef CONFIG_SYS_FLASH_CFI /* NOR Flash */
++
++#ifdef CONFIG_FLASH_AST2300
++#define PHYS_FLASH_1 0x20000000 /* Flash Bank #1 */
++#else
++#define PHYS_FLASH_1 0x10000000 /* Flash Bank #1 */
++#endif
++
++#define CONFIG_SYS_FLASH_BASE PHYS_FLASH_1
++#define CONFIG_FLASH_BANKS_LIST { PHYS_FLASH_1 }
++
++#define CONFIG_SYS_MAX_FLASH_BANKS 1
++#define CONFIG_SYS_MAX_FLASH_SECT (256) /* max number of sectors on one chip */
++
++#define CONFIG_ENV_IS_IN_FLASH 1
++#define CONFIG_ENV_OFFSET 0x60000 /* environment starts here */
++#define CONFIG_ENV_SIZE 0x20000 /* Total Size of Environment Sector */
++
++#define CONFIG_SYS_FLASH_CFI_AMD_RESET
++#define CONFIG_SYS_FLASH_USE_BUFFER_WRITE
++
++#else /* SPI Flash */
++
++#ifdef CONFIG_FLASH_AST2300
++#define PHYS_FLASH_1 0x20000000 /* Flash Bank #1 */
++#else
++#define PHYS_FLASH_1 0x14000000 /* Flash Bank #1 */
++#define PHYS_FLASH_2 0x14800000 /* Flash Bank #2 */
++#define PHYS_FLASH_2_BASE 0x10000000
++#endif
++
++#ifdef CONFIG_2SPIFLASH
++#define CONFIG_SYS_FLASH_BASE PHYS_FLASH_2_BASE
++#define CONFIG_FLASH_BANKS_LIST { PHYS_FLASH_1, PHYS_FLASH_2 }
++#define CONFIG_SYS_MAX_FLASH_BANKS 2
++#define CONFIG_SYS_MAX_FLASH_SECT (1024) /* max number of sectors on one chip */
++
++#define CONFIG_ENV_IS_IN_FLASH 1
++#define CONFIG_ENV_OFFSET 0x7F0000 /* environment starts here */
++#define CONFIG_ENV_SIZE 0x010000 /* Total Size of Environment Sector */
++#else
++#define CONFIG_SYS_FLASH_BASE PHYS_FLASH_1
++#define CONFIG_FLASH_BANKS_LIST { PHYS_FLASH_1 }
++#define CONFIG_SYS_MAX_FLASH_BANKS 1
++#define CONFIG_SYS_MAX_FLASH_SECT (1024) /* max number of sectors on one chip */
++
++#define CONFIG_ENV_IS_IN_FLASH 1
++#define CONFIG_ENV_OFFSET 0x7F0000 /* environment starts here */
++#define CONFIG_ENV_SIZE 0x010000 /* Total Size of Environment Sector */
++#endif
++
++#endif
++
++#define __LITTLE_ENDIAN
++
++#define CONFIG_MONITOR_BASE TEXT_BASE
++#define CONFIG_MONITOR_LEN (192 << 10)
++
++/* timeout values are in ticks */
++#define CONFIG_SYS_FLASH_ERASE_TOUT (20*CONFIG_SYS_HZ) /* Timeout for Flash Erase */
++#define CONFIG_SYS_FLASH_WRITE_TOUT (20*CONFIG_SYS_HZ) /* Timeout for Flash Write */
++
++/*
++ * Miscellaneous configurable options
++ */
++#define CONFIG_SYS_LONGHELP /* undef to save memory */
++
++#define CONFIG_SYS_PROMPT "boot# " /* Monitor Command Prompt */
++#define CONFIG_SYS_CBSIZE 256 /* Console I/O Buffer Size */
++#define CONFIG_SYS_PBSIZE (CONFIG_SYS_CBSIZE+sizeof(CONFIG_SYS_PROMPT)+16) /* Print Buffer Size */
++#define CONFIG_SYS_MAXARGS 16 /* max number of command args */
++#define CONFIG_SYS_BARGSIZE CONFIG_SYS_CBSIZE /* Boot Argument Buffer Size */
++
++#define CONFIG_SYS_MEMTEST_START 0x40000000 /* memtest works on */
++#define CONFIG_SYS_MEMTEST_END 0x44FFFFFF /* 256 MB in DRAM */
++
++#define CONFIG_SYS_CLKS_IN_HZ /* everything, incl board info, in Hz */
++#undef CONFIG_SYS_CLKS_IN_HZ /* everything, incl board info, in Hz */
++
++#define CONFIG_SYS_LOAD_ADDR 0x43000000 /* default load address */
++
++#define CONFIG_SYS_TIMERBASE 0x1E782000 /* use timer 1 */
++#define CONFIG_SYS_HZ (1*1000*1000) /* use external clk (1M) */
++
++/*
++ * Serial Configuration
++ */
++#define CONFIG_SYS_NS16550
++#define CONFIG_SYS_NS16550_SERIAL
++#define CONFIG_SYS_NS16550_REG_SIZE 4
++#define CONFIG_SYS_NS16550_CLK 24000000
++#define CONFIG_SYS_NS16550_COM1 0x1e783000
++#define CONFIG_SYS_NS16550_COM2 0x1e784000
++#define CONFIG_SYS_LOADS_BAUD_CHANGE
++#define CONFIG_SERIAL1 1
++#define CONFIG_CONS_INDEX 2
++#define CONFIG_BAUDRATE 115200
++#define CONFIG_SYS_BAUDRATE_TABLE { 9600, 19200, 38400, 57600, 115200 }
++
++/*
++ * USB device configuration
++ */
++/*
++#define CONFIG_USB_DEVICE 1
++#define CONFIG_USB_TTY 1
++
++#define CONFIG_USBD_VENDORID 0x1234
++#define CONFIG_USBD_PRODUCTID 0x5678
++#define CONFIG_USBD_MANUFACTURER "Siemens"
++#define CONFIG_USBD_PRODUCT_NAME "SX1"
++*/
++
++/*
++ * I2C configuration
++ */
++#define CONFIG_HARD_I2C
++#define CONFIG_SYS_I2C_SPEED 100000
++#define CONFIG_SYS_I2C_SLAVE 1
++#define CONFIG_DRIVER_ASPEED_I2C
++
++/*
++* EEPROM configuration
++*/
++#define CONFIG_SYS_I2C_EEPROM_ADDR_LEN 2
++#define CONFIG_SYS_I2C_EEPROM_ADDR 0xa0
++
++/*
++ * NIC configuration
++ */
++#define __BYTE_ORDER __LITTLE_ENDIAN
++#define __LITTLE_ENDIAN_BITFIELD
++#define CONFIG_MAC_PARTITION
++#define CONFIG_ASPEEDNIC
++#define CONFIG_MAC1_PHY_LINK_INTERRUPT
++#define CONFIG_MAC2_ENABLE
++#define CONFIG_MAC2_PHY_LINK_INTERRUPT
++/*
++*-------------------------------------------------------------------------------
++* NOTICE: MAC1 and MAC2 now have their own seperate PHY configuration.
++* We use 2 bits for each MAC in the scratch register(D[15:11] in 0x1E6E2040) to
++* inform kernel driver.
++* The meanings of the 2 bits are:
++* 00(0): Dedicated PHY
++* 01(1): ASPEED's EVA + INTEL's NC-SI PHY chip EVA
++* 10(2): ASPEED's MAC is connected to NC-SI PHY chip directly
++* 11: Reserved
++*
++* We use CONFIG_MAC1_PHY_SETTING and CONFIG_MAC2_PHY_SETTING in U-Boot
++* 0: Dedicated PHY
++* 1: ASPEED's EVA + INTEL's NC-SI PHY chip EVA
++* 2: ASPEED's MAC is connected to NC-SI PHY chip directly
++* 3: Reserved
++*-------------------------------------------------------------------------------
++*/
++#define CONFIG_MAC1_PHY_SETTING 0
++#define CONFIG_MAC2_PHY_SETTING 0
++#define CONFIG_MAC_INTERFACE_CLOCK_DELAY 0x2255
++#define CONFIG_NET_MULTI
++#define CONFIG_ETHACT aspeednic#0
++#define CONFIG_GATEWAYIP 192.168.0.1
++#define CONFIG_NETMASK 255.255.255.0
++#define CONFIG_IPADDR 192.168.0.41
++#define CONFIG_SERVERIP 192.168.0.81
++#define CONFIG_ETHADDR 00:C0:A8:12:34:56
++#define CONFIG_ETH1ADDR 00:C0:A8:12:34:57
++
++/*
++ * SLT
++ */
++/*
++#define CONFIG_SLT
++#define CFG_CMD_SLT (CFG_CMD_VIDEOTEST | CFG_CMD_MACTEST | CFG_CMD_HACTEST | CFG_CMD_MICTEST)
++*/
++
++#endif /* __CONFIG_H */
+diff --git a/include/configs/ast2400_ast10701.h b/include/configs/ast2400_ast10701.h
+new file mode 100644
+index 0000000..4553535
+--- /dev/null
++++ b/include/configs/ast2400_ast10701.h
+@@ -0,0 +1,327 @@
++/*
++ * (C) Copyright 2004
++ * Peter Chen <peterc@socle-tech.com.tw>
++ *
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License as
++ * published by the Free Software Foundation; either version 2 of
++ * the License, or (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
++ * MA 02111-1307 USA
++ */
++
++#ifndef __CONFIG_H
++#define __CONFIG_H
++
++/*
++ * High Level Configuration Options
++ * (easy to change)
++ */
++//#define CONFIG_INIT_CRITICAL /* define for U-BOOT 1.1.1 */
++#undef CONFIG_INIT_CRITICAL /* undef for U-BOOT 1.1.4 */
++//#define CONFIG_FPGA_ASPEED 1
++#define CONFIG_ARM926EJS 1 /* This is an arm926ejs CPU */
++#define CONFIG_ASPEED 1
++#define CONFIG_AST2400 1
++#define CONFIG_AST1070 1
++#define CONFIG_LPC_PLUS 1
++//#define CONFIG_CALIBRATION 1
++//#define CONFIG_SYS_FLASH_CFI /* CONFIG_FLASH_CFI, CONFIG_FLASH_SPI is exclusive*/
++#define CONFIG_FLASH_SPI
++//#define CONFIG_2SPIFLASH /* Boot SPI: CS2, 2nd SPI: CS0 */
++#undef CONFIG_2SPIFLASH
++#undef CONFIG_ASPEED_SLT
++#define CONFIG_FLASH_AST2300
++#define CONFIG_FLASH_AST2300_DMA
++//#define CONFIG_FLASH_SPIx2_Dummy
++//#define CONFIG_FLASH_SPIx4_Dummy
++#define CONFIG_CRT_DISPLAY 1 /* undef if not support CRT */
++
++//#define CONFIG_USE_IRQ /* we don't need IRQ/FIQ stuff */
++#define CONFIG_MISC_INIT_R
++
++/*
++ * DRAM Config
++ *
++ * 1. DRAM Size //
++ * CONFIG_DRAM_512MBIT // 512M bit
++ * CONFIG_DRAM_1GBIT // 1G bit (default)
++ * CONFIG_DRAM_2GBIT // 2G bit
++ * CONFIG_DRAM_4GBIT // 4G bit
++ * 2. DRAM Speed //
++ * CONFIG_DRAM_336 // 336MHz (DDR-667)
++ * CONFIG_DRAM_408 // 408MHz (DDR-800) (default)
++ * 3. VGA Mode
++ * CONFIG_CRT_DISPLAY // define to disable VGA function
++ * 4. ECC Function enable
++ * CONFIG_DRAM_ECC // define to enable ECC function
++ * 5. UART Debug Message
++ * CONFIG_DRAM_UART_OUT // enable output message at UART5
++ * CONFIG_DRAM_UART_38400 // set the UART baud rate to 38400, default is 115200
++ */
++
++//1. DRAM Size
++//#define CONFIG_DRAM_512MBIT
++#define CONFIG_DRAM_1GBIT
++//#define CONFIG_DRAM_2GBIT
++//#define CONFIG_DRAM_4GBIT
++//2. DRAM Speed
++//#define CONFIG_DRAM_336
++#define CONFIG_DRAM_408
++//3. VGA Mode
++//#define CONFIG_CRT_DISPLAY
++//4. ECC Function enable
++//#define CONFIG_DRAM_ECC
++//5. UART Debug Message
++#define CONFIG_DRAM_UART_OUT
++//#define CONFIG_DRAM_UART_38400
++
++
++
++/*
++ * Environment Config
++ */
++#define CONFIG_CMDLINE_TAG 1 /* enable passing of ATAGs */
++#define CONFIG_SETUP_MEMORY_TAGS 1
++#define CONFIG_INITRD_TAG 1
++#define CONFIG_BOOTARGS "debug console=ttyS0,115200n8 ramdisk_size=16384 root=/dev/ram rw init=/linuxrc mem=80M"
++#define CONFIG_BOOTDELAY 3 /* autoboot after 3 seconds */
++#ifdef CONFIG_FLASH_AST2300
++#define CONFIG_BOOTCOMMAND "bootm 20080000 20300000"
++#else
++#ifdef CONFIG_SYS_FLASH_CFI
++#define CONFIG_BOOTCOMMAND "bootm 10080000 10300000"
++#else
++#define CONFIG_BOOTCOMMAND "bootm 14080000 14300000"
++#endif
++#endif
++#define CONFIG_BOOTFILE "all.bin"
++#define CONFIG_ENV_OVERWRITE
++
++/*
++ * Command line configuration.
++ */
++#include <config_cmd_default.h>
++
++#define CONFIG_CMD_DFL
++#define CONFIG_CMD_ENV
++#define CONFIG_CMD_FLASH
++#define CONFIG_CMD_NET
++#define CONFIG_CMD_PING
++#define CONFIG_CMD_I2C
++#define CONFIG_CMD_EEPROM
++#define CONFIG_CMD_NETTEST
++
++/*
++ * CPU Setting
++ */
++#define CPU_CLOCK_RATE 18000000 /* 16.5 MHz clock for the ARM core */
++
++/*
++ * Size of malloc() pool
++ */
++#define CONFIG_SYS_MALLOC_LEN (CONFIG_ENV_SIZE + 768*1024)
++#define CONFIG_SYS_GBL_DATA_SIZE 128 /* size in bytes reserved for initial data */
++
++/*
++ * Stack sizes, The stack sizes are set up in start.S using the settings below
++ */
++#define CONFIG_STACKSIZE (128*1024) /* regular stack */
++#define CONFIG_STACKSIZE_IRQ (4*1024) /* IRQ stack */
++#define CONFIG_STACKSIZE_FIQ (4*1024) /* FIQ stack */
++
++/*
++ * Memory Configuration
++ */
++#define CONFIG_NR_DRAM_BANKS 1 /* we have 1 bank of DRAM */
++#define PHYS_SDRAM_1 0x40000000 /* SDRAM Bank #1 */
++#define PHYS_SDRAM_1_SIZE 0x4000000 /* 64 MB */
++
++#define CONFIG_SYS_SDRAM_BASE 0x40000000
++
++/*
++ * FLASH Configuration
++ */
++#ifdef CONFIG_SYS_FLASH_CFI /* NOR Flash */
++
++#ifdef CONFIG_FLASH_AST2300
++#define PHYS_FLASH_1 0x20000000 /* Flash Bank #1 */
++#else
++#define PHYS_FLASH_1 0x10000000 /* Flash Bank #1 */
++#endif
++
++#define CONFIG_SYS_FLASH_BASE PHYS_FLASH_1
++#define CONFIG_FLASH_BANKS_LIST { PHYS_FLASH_1 }
++
++#define CONFIG_SYS_MAX_FLASH_BANKS 1
++#define CONFIG_SYS_MAX_FLASH_SECT (256) /* max number of sectors on one chip */
++
++#define CONFIG_ENV_IS_IN_FLASH 1
++#define CONFIG_ENV_OFFSET 0xFE0000 /* environment starts here */
++#define CONFIG_ENV_SIZE 0x020000 /* Total Size of Environment Sector */
++
++#define CONFIG_SYS_FLASH_CFI_AMD_RESET
++#define CONFIG_SYS_FLASH_USE_BUFFER_WRITE
++
++#else /* SPI Flash */
++
++#ifdef CONFIG_FLASH_AST2300
++#define PHYS_FLASH_1 0x20000000 /* Flash Bank #1 */
++#else
++#define PHYS_FLASH_1 0x14000000 /* Flash Bank #1 */
++#define PHYS_FLASH_2 0x14800000 /* Flash Bank #2 */
++#define PHYS_FLASH_2_BASE 0x10000000
++#endif
++
++#ifdef CONFIG_2SPIFLASH
++#define CONFIG_SYS_FLASH_BASE PHYS_FLASH_2_BASE
++#define CONFIG_FLASH_BANKS_LIST { PHYS_FLASH_1, PHYS_FLASH_2 }
++#define CONFIG_SYS_MAX_FLASH_BANKS 2
++#define CONFIG_SYS_MAX_FLASH_SECT (1024) /* max number of sectors on one chip */
++
++#define CONFIG_ENV_IS_IN_FLASH 1
++#define CONFIG_ENV_OFFSET 0x7F0000 /* environment starts here */
++#define CONFIG_ENV_SIZE 0x010000 /* Total Size of Environment Sector */
++#else
++#define CONFIG_SYS_FLASH_BASE PHYS_FLASH_1
++#define CONFIG_FLASH_BANKS_LIST { PHYS_FLASH_1 }
++#define CONFIG_SYS_MAX_FLASH_BANKS 1
++#define CONFIG_SYS_MAX_FLASH_SECT (1024) /* max number of sectors on one chip */
++
++#define CONFIG_ENV_IS_IN_FLASH 1
++#define CONFIG_ENV_OFFSET 0x7F0000 /* environment starts here */
++#define CONFIG_ENV_SIZE 0x010000 /* Total Size of Environment Sector */
++#endif
++
++#endif
++
++#define __LITTLE_ENDIAN
++
++#define CONFIG_MONITOR_BASE TEXT_BASE
++#define CONFIG_MONITOR_LEN (192 << 10)
++
++/* timeout values are in ticks */
++#define CONFIG_SYS_FLASH_ERASE_TOUT (20*CONFIG_SYS_HZ) /* Timeout for Flash Erase */
++#define CONFIG_SYS_FLASH_WRITE_TOUT (20*CONFIG_SYS_HZ) /* Timeout for Flash Write */
++
++/*
++ * Miscellaneous configurable options
++ */
++#define CONFIG_SYS_LONGHELP /* undef to save memory */
++
++#define CONFIG_SYS_PROMPT "boot# " /* Monitor Command Prompt */
++#define CONFIG_SYS_CBSIZE 256 /* Console I/O Buffer Size */
++#define CONFIG_SYS_PBSIZE (CONFIG_SYS_CBSIZE+sizeof(CONFIG_SYS_PROMPT)+16) /* Print Buffer Size */
++#define CONFIG_SYS_MAXARGS 16 /* max number of command args */
++#define CONFIG_SYS_BARGSIZE CONFIG_SYS_CBSIZE /* Boot Argument Buffer Size */
++
++#define CONFIG_SYS_MEMTEST_START 0x40000000 /* memtest works on */
++#define CONFIG_SYS_MEMTEST_END 0x44FFFFFF /* 256 MB in DRAM */
++
++#define CONFIG_SYS_CLKS_IN_HZ /* everything, incl board info, in Hz */
++#undef CONFIG_SYS_CLKS_IN_HZ /* everything, incl board info, in Hz */
++
++#define CONFIG_SYS_LOAD_ADDR 0x43000000 /* default load address */
++
++#define CONFIG_SYS_TIMERBASE 0x1E782000 /* use timer 1 */
++#define CONFIG_SYS_HZ (1*1000*1000) /* use external clk (1M) */
++
++/*
++ * Serial Configuration
++ */
++#define CONFIG_SYS_NS16550
++#define CONFIG_SYS_NS16550_SERIAL
++#define CONFIG_SYS_NS16550_REG_SIZE 4
++#define CONFIG_SYS_NS16550_CLK 24000000
++#define CONFIG_SYS_NS16550_COM1 0x1e783000
++#define CONFIG_SYS_NS16550_COM2 0x1e784000
++#define CONFIG_SYS_LOADS_BAUD_CHANGE
++#define CONFIG_SERIAL1 1
++#define CONFIG_CONS_INDEX 2
++#define CONFIG_BAUDRATE 115200
++#define CONFIG_SYS_BAUDRATE_TABLE { 9600, 19200, 38400, 57600, 115200 }
++
++/*
++ * USB device configuration
++ */
++/*
++#define CONFIG_USB_DEVICE 1
++#define CONFIG_USB_TTY 1
++
++#define CONFIG_USBD_VENDORID 0x1234
++#define CONFIG_USBD_PRODUCTID 0x5678
++#define CONFIG_USBD_MANUFACTURER "Siemens"
++#define CONFIG_USBD_PRODUCT_NAME "SX1"
++*/
++
++/*
++ * I2C configuration
++ */
++#define CONFIG_HARD_I2C
++#define CONFIG_SYS_I2C_SPEED 100000
++#define CONFIG_SYS_I2C_SLAVE 1
++#define CONFIG_DRIVER_ASPEED_I2C
++
++/*
++* EEPROM configuration
++*/
++#define CONFIG_SYS_I2C_EEPROM_ADDR_LEN 2
++#define CONFIG_SYS_I2C_EEPROM_ADDR 0xa0
++
++/*
++ * NIC configuration
++ */
++#define __BYTE_ORDER __LITTLE_ENDIAN
++#define __LITTLE_ENDIAN_BITFIELD
++#define CONFIG_MAC_PARTITION
++#define CONFIG_ASPEEDNIC
++#define CONFIG_MAC1_PHY_LINK_INTERRUPT
++#define CONFIG_MAC2_ENABLE
++#define CONFIG_MAC2_PHY_LINK_INTERRUPT
++/*
++*-------------------------------------------------------------------------------
++* NOTICE: MAC1 and MAC2 now have their own seperate PHY configuration.
++* We use 2 bits for each MAC in the scratch register(D[15:11] in 0x1E6E2040) to
++* inform kernel driver.
++* The meanings of the 2 bits are:
++* 00(0): Dedicated PHY
++* 01(1): ASPEED's EVA + INTEL's NC-SI PHY chip EVA
++* 10(2): ASPEED's MAC is connected to NC-SI PHY chip directly
++* 11: Reserved
++*
++* We use CONFIG_MAC1_PHY_SETTING and CONFIG_MAC2_PHY_SETTING in U-Boot
++* 0: Dedicated PHY
++* 1: ASPEED's EVA + INTEL's NC-SI PHY chip EVA
++* 2: ASPEED's MAC is connected to NC-SI PHY chip directly
++* 3: Reserved
++*-------------------------------------------------------------------------------
++*/
++#define CONFIG_MAC1_PHY_SETTING 0
++#define CONFIG_MAC2_PHY_SETTING 0
++#define CONFIG_MAC_INTERFACE_CLOCK_DELAY 0x2255
++#define CONFIG_NET_MULTI
++#define CONFIG_ETHACT aspeednic#0
++#define CONFIG_GATEWAYIP 192.168.0.1
++#define CONFIG_NETMASK 255.255.255.0
++#define CONFIG_IPADDR 192.168.0.45
++#define CONFIG_SERVERIP 192.168.0.53
++#define CONFIG_ETHADDR 00:C0:A8:12:34:56
++#define CONFIG_ETH1ADDR 00:C0:A8:12:34:57
++
++/*
++ * SLT
++ */
++/*
++#define CONFIG_SLT
++#define CFG_CMD_SLT (CFG_CMD_VIDEOTEST | CFG_CMD_MACTEST | CFG_CMD_HACTEST | CFG_CMD_MICTEST)
++*/
++
++#endif /* __CONFIG_H */
+diff --git a/include/configs/ast2400_nor.h b/include/configs/ast2400_nor.h
+new file mode 100644
+index 0000000..5b10b36
+--- /dev/null
++++ b/include/configs/ast2400_nor.h
+@@ -0,0 +1,322 @@
++/*
++ * (C) Copyright 2004
++ * Peter Chen <peterc@socle-tech.com.tw>
++ *
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License as
++ * published by the Free Software Foundation; either version 2 of
++ * the License, or (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
++ * MA 02111-1307 USA
++ */
++
++#ifndef __CONFIG_H
++#define __CONFIG_H
++
++/*
++ * High Level Configuration Options
++ * (easy to change)
++ */
++//#define CONFIG_INIT_CRITICAL /* define for U-BOOT 1.1.1 */
++#undef CONFIG_INIT_CRITICAL /* undef for U-BOOT 1.1.4 */
++#define CONFIG_ARM926EJS 1 /* This is an arm926ejs CPU */
++#define CONFIG_ASPEED 1
++#define CONFIG_AST2400 1
++#define CONFIG_SYS_FLASH_CFI /* CONFIG_FLASH_CFI, CONFIG_FLASH_SPI is exclusive*/
++//#define CONFIG_FLASH_SPI
++//#define CONFIG_2SPIFLASH /* Boot SPI: CS2, 2nd SPI: CS0 */
++#undef CONFIG_2SPIFLASH
++#undef CONFIG_ASPEED_SLT
++#define CONFIG_FLASH_AST2300
++#define CONFIG_FLASH_AST2300_DMA
++//#define CONFIG_FLASH_SPIx2_Dummy
++//#define CONFIG_FLASH_SPIx4_Dummy
++#define CONFIG_CRT_DISPLAY 1 /* undef if not support CRT */
++
++//#define CONFIG_USE_IRQ /* we don't need IRQ/FIQ stuff */
++#define CONFIG_MISC_INIT_R
++
++/*
++ * DRAM Config
++ *
++ * 1. DRAM Size //
++ * CONFIG_DRAM_512MBIT // 512M bit
++ * CONFIG_DRAM_1GBIT // 1G bit (default)
++ * CONFIG_DRAM_2GBIT // 2G bit
++ * CONFIG_DRAM_4GBIT // 4G bit
++ * 2. DRAM Speed //
++ * CONFIG_DRAM_336 // 336MHz (DDR-667)
++ * CONFIG_DRAM_408 // 408MHz (DDR-800) (default)
++ * 3. VGA Mode
++ * CONFIG_CRT_DISPLAY // define to disable VGA function
++ * 4. ECC Function enable
++ * CONFIG_DRAM_ECC // define to enable ECC function
++ * 5. UART Debug Message
++ * CONFIG_DRAM_UART_OUT // enable output message at UART5
++ * CONFIG_DRAM_UART_38400 // set the UART baud rate to 38400, default is 115200
++ */
++
++//1. DRAM Size
++//#define CONFIG_DRAM_512MBIT
++#define CONFIG_DRAM_1GBIT
++//#define CONFIG_DRAM_2GBIT
++//#define CONFIG_DRAM_4GBIT
++//2. DRAM Speed
++//#define CONFIG_DRAM_336
++#define CONFIG_DRAM_408
++//3. VGA Mode
++//#define CONFIG_CRT_DISPLAY
++//4. ECC Function enable
++//#define CONFIG_DRAM_ECC
++//5. UART Debug Message
++#define CONFIG_DRAM_UART_OUT
++//#define CONFIG_DRAM_UART_38400
++
++
++
++/*
++ * Environment Config
++ */
++#define CONFIG_CMDLINE_TAG 1 /* enable passing of ATAGs */
++#define CONFIG_SETUP_MEMORY_TAGS 1
++#define CONFIG_INITRD_TAG 1
++#define CONFIG_BOOTARGS "debug console=ttyS0,115200n8 ramdisk_size=16384 root=/dev/ram rw init=/linuxrc mem=80M"
++#define CONFIG_BOOTDELAY 3 /* autoboot after 3 seconds */
++#ifdef CONFIG_FLASH_AST2300
++#define CONFIG_BOOTCOMMAND "bootm 20080000 20300000"
++#else
++#ifdef CONFIG_SYS_FLASH_CFI
++#define CONFIG_BOOTCOMMAND "bootm 10080000 10300000"
++#else
++#define CONFIG_BOOTCOMMAND "bootm 14080000 14300000"
++#endif
++#endif
++#define CONFIG_BOOTFILE "all.bin"
++#define CONFIG_ENV_OVERWRITE
++
++/*
++ * Command line configuration.
++ */
++#include <config_cmd_default.h>
++
++#define CONFIG_CMD_DFL
++#define CONFIG_CMD_ENV
++#define CONFIG_CMD_FLASH
++#define CONFIG_CMD_NET
++#define CONFIG_CMD_PING
++#define CONFIG_CMD_I2C
++#define CONFIG_CMD_EEPROM
++
++/*
++ * CPU Setting
++ */
++#define CPU_CLOCK_RATE 18000000 /* 16.5 MHz clock for the ARM core */
++
++/*
++ * Size of malloc() pool
++ */
++#define CONFIG_SYS_MALLOC_LEN (CONFIG_ENV_SIZE + 768*1024)
++#define CONFIG_SYS_GBL_DATA_SIZE 128 /* size in bytes reserved for initial data */
++
++/*
++ * Stack sizes, The stack sizes are set up in start.S using the settings below
++ */
++#define CONFIG_STACKSIZE (128*1024) /* regular stack */
++#define CONFIG_STACKSIZE_IRQ (4*1024) /* IRQ stack */
++#define CONFIG_STACKSIZE_FIQ (4*1024) /* FIQ stack */
++
++/*
++ * Memory Configuration
++ */
++#define CONFIG_NR_DRAM_BANKS 1 /* we have 1 bank of DRAM */
++#define PHYS_SDRAM_1 0x40000000 /* SDRAM Bank #1 */
++#define PHYS_SDRAM_1_SIZE 0x4000000 /* 64 MB */
++
++#define CONFIG_SYS_SDRAM_BASE 0x40000000
++
++/*
++ * FLASH Configuration
++ */
++#ifdef CONFIG_SYS_FLASH_CFI /* NOR Flash */
++
++#ifdef CONFIG_FLASH_AST2300
++#define PHYS_FLASH_1 0x20000000 /* Flash Bank #1 */
++#else
++#define PHYS_FLASH_1 0x10000000 /* Flash Bank #1 */
++#endif
++
++#define CONFIG_SYS_FLASH_BASE PHYS_FLASH_1
++#define CONFIG_FLASH_BANKS_LIST { PHYS_FLASH_1 }
++
++#define CONFIG_SYS_MAX_FLASH_BANKS 1
++#define CONFIG_SYS_MAX_FLASH_SECT (256) /* max number of sectors on one chip */
++
++#define CONFIG_ENV_IS_IN_FLASH 1
++#define CONFIG_ENV_OFFSET 0x60000 /* environment starts here */
++#define CONFIG_ENV_SIZE 0x20000 /* Total Size of Environment Sector */
++
++#define CONFIG_SYS_FLASH_CFI_AMD_RESET
++#define CONFIG_SYS_FLASH_USE_BUFFER_WRITE
++
++#else /* SPI Flash */
++
++#ifdef CONFIG_FLASH_AST2300
++#define PHYS_FLASH_1 0x20000000 /* Flash Bank #1 */
++#else
++#define PHYS_FLASH_1 0x14000000 /* Flash Bank #1 */
++#define PHYS_FLASH_2 0x14800000 /* Flash Bank #2 */
++#define PHYS_FLASH_2_BASE 0x10000000
++#endif
++
++#ifdef CONFIG_2SPIFLASH
++#define CONFIG_SYS_FLASH_BASE PHYS_FLASH_2_BASE
++#define CONFIG_FLASH_BANKS_LIST { PHYS_FLASH_1, PHYS_FLASH_2 }
++#define CONFIG_SYS_MAX_FLASH_BANKS 2
++#define CONFIG_SYS_MAX_FLASH_SECT (1024) /* max number of sectors on one chip */
++
++#define CONFIG_ENV_IS_IN_FLASH 1
++#define CONFIG_ENV_OFFSET 0x7F0000 /* environment starts here */
++#define CONFIG_ENV_SIZE 0x010000 /* Total Size of Environment Sector */
++#else
++#define CONFIG_SYS_FLASH_BASE PHYS_FLASH_1
++#define CONFIG_FLASH_BANKS_LIST { PHYS_FLASH_1 }
++#define CONFIG_SYS_MAX_FLASH_BANKS 1
++#define CONFIG_SYS_MAX_FLASH_SECT (1024) /* max number of sectors on one chip */
++
++#define CONFIG_ENV_IS_IN_FLASH 1
++#define CONFIG_ENV_OFFSET 0x7F0000 /* environment starts here */
++#define CONFIG_ENV_SIZE 0x010000 /* Total Size of Environment Sector */
++#endif
++
++#endif
++
++#define __LITTLE_ENDIAN
++
++#define CONFIG_MONITOR_BASE TEXT_BASE
++#define CONFIG_MONITOR_LEN (192 << 10)
++
++/* timeout values are in ticks */
++#define CONFIG_SYS_FLASH_ERASE_TOUT (20*CONFIG_SYS_HZ) /* Timeout for Flash Erase */
++#define CONFIG_SYS_FLASH_WRITE_TOUT (20*CONFIG_SYS_HZ) /* Timeout for Flash Write */
++
++/*
++ * Miscellaneous configurable options
++ */
++#define CONFIG_SYS_LONGHELP /* undef to save memory */
++
++#define CONFIG_SYS_PROMPT "boot# " /* Monitor Command Prompt */
++#define CONFIG_SYS_CBSIZE 256 /* Console I/O Buffer Size */
++#define CONFIG_SYS_PBSIZE (CONFIG_SYS_CBSIZE+sizeof(CONFIG_SYS_PROMPT)+16) /* Print Buffer Size */
++#define CONFIG_SYS_MAXARGS 16 /* max number of command args */
++#define CONFIG_SYS_BARGSIZE CONFIG_SYS_CBSIZE /* Boot Argument Buffer Size */
++
++#define CONFIG_SYS_MEMTEST_START 0x40000000 /* memtest works on */
++#define CONFIG_SYS_MEMTEST_END 0x44FFFFFF /* 256 MB in DRAM */
++
++#define CONFIG_SYS_CLKS_IN_HZ /* everything, incl board info, in Hz */
++#undef CONFIG_SYS_CLKS_IN_HZ /* everything, incl board info, in Hz */
++
++#define CONFIG_SYS_LOAD_ADDR 0x43000000 /* default load address */
++
++#define CONFIG_SYS_TIMERBASE 0x1E782000 /* use timer 1 */
++#define CONFIG_SYS_HZ (1*1000*1000) /* use external clk (1M) */
++
++/*
++ * Serial Configuration
++ */
++#define CONFIG_SYS_NS16550
++#define CONFIG_SYS_NS16550_SERIAL
++#define CONFIG_SYS_NS16550_REG_SIZE 4
++#define CONFIG_SYS_NS16550_CLK 24000000
++#define CONFIG_SYS_NS16550_COM1 0x1e783000
++#define CONFIG_SYS_NS16550_COM2 0x1e784000
++#define CONFIG_SYS_LOADS_BAUD_CHANGE
++#define CONFIG_SERIAL1 1
++#define CONFIG_CONS_INDEX 2
++#define CONFIG_BAUDRATE 115200
++#define CONFIG_SYS_BAUDRATE_TABLE { 9600, 19200, 38400, 57600, 115200 }
++
++/*
++ * USB device configuration
++ */
++/*
++#define CONFIG_USB_DEVICE 1
++#define CONFIG_USB_TTY 1
++
++#define CONFIG_USBD_VENDORID 0x1234
++#define CONFIG_USBD_PRODUCTID 0x5678
++#define CONFIG_USBD_MANUFACTURER "Siemens"
++#define CONFIG_USBD_PRODUCT_NAME "SX1"
++*/
++
++/*
++ * I2C configuration
++ */
++#define CONFIG_HARD_I2C
++#define CONFIG_SYS_I2C_SPEED 100000
++#define CONFIG_SYS_I2C_SLAVE 1
++#define CONFIG_DRIVER_ASPEED_I2C
++
++/*
++* EEPROM configuration
++*/
++#define CONFIG_SYS_I2C_EEPROM_ADDR_LEN 2
++#define CONFIG_SYS_I2C_EEPROM_ADDR 0xa0
++
++/*
++ * NIC configuration
++ */
++#define __BYTE_ORDER __LITTLE_ENDIAN
++#define __LITTLE_ENDIAN_BITFIELD
++#define CONFIG_MAC_PARTITION
++#define CONFIG_ASPEEDNIC
++#define CONFIG_MAC1_PHY_LINK_INTERRUPT
++#define CONFIG_MAC2_ENABLE
++#define CONFIG_MAC2_PHY_LINK_INTERRUPT
++/*
++*-------------------------------------------------------------------------------
++* NOTICE: MAC1 and MAC2 now have their own seperate PHY configuration.
++* We use 2 bits for each MAC in the scratch register(D[15:11] in 0x1E6E2040) to
++* inform kernel driver.
++* The meanings of the 2 bits are:
++* 00(0): Dedicated PHY
++* 01(1): ASPEED's EVA + INTEL's NC-SI PHY chip EVA
++* 10(2): ASPEED's MAC is connected to NC-SI PHY chip directly
++* 11: Reserved
++*
++* We use CONFIG_MAC1_PHY_SETTING and CONFIG_MAC2_PHY_SETTING in U-Boot
++* 0: Dedicated PHY
++* 1: ASPEED's EVA + INTEL's NC-SI PHY chip EVA
++* 2: ASPEED's MAC is connected to NC-SI PHY chip directly
++* 3: Reserved
++*-------------------------------------------------------------------------------
++*/
++#define CONFIG_MAC1_PHY_SETTING 0
++#define CONFIG_MAC2_PHY_SETTING 0
++#define CONFIG_MAC_INTERFACE_CLOCK_DELAY 0x2255
++#define CONFIG_NET_MULTI
++#define CONFIG_ETHACT aspeednic#0
++#define CONFIG_GATEWAYIP 192.168.0.1
++#define CONFIG_NETMASK 255.255.255.0
++#define CONFIG_IPADDR 192.168.0.188
++#define CONFIG_SERVERIP 192.168.0.106
++#define CONFIG_ETHADDR 00:C0:A8:12:34:56
++#define CONFIG_ETH1ADDR 00:C0:A8:12:34:57
++
++/*
++ * SLT
++ */
++/*
++#define CONFIG_SLT
++#define CFG_CMD_SLT (CFG_CMD_VIDEOTEST | CFG_CMD_MACTEST | CFG_CMD_HACTEST | CFG_CMD_MICTEST)
++*/
++
++#endif /* __CONFIG_H */
+diff --git a/include/configs/ast2400_slt.h b/include/configs/ast2400_slt.h
+new file mode 100644
+index 0000000..cfa1c31
+--- /dev/null
++++ b/include/configs/ast2400_slt.h
+@@ -0,0 +1,329 @@
++/*
++ * (C) Copyright 2004
++ * Peter Chen <peterc@socle-tech.com.tw>
++ *
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License as
++ * published by the Free Software Foundation; either version 2 of
++ * the License, or (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
++ * MA 02111-1307 USA
++ */
++
++#ifndef __CONFIG_H
++#define __CONFIG_H
++
++/*
++ * High Level Configuration Options
++ * (easy to change)
++ */
++//#define CONFIG_INIT_CRITICAL /* define for U-BOOT 1.1.1 */
++#undef CONFIG_INIT_CRITICAL /* undef for U-BOOT 1.1.4 */
++//#define CONFIG_FPGA_ASPEED 1
++#define CONFIG_ARM926EJS 1 /* This is an arm926ejs CPU */
++#define CONFIG_ASPEED 1
++#define CONFIG_AST2400 1
++#define CONFIG_SLT_ASPEED 1
++//#define CONFIG_AST1070 1
++//#define CONFIG_SYS_FLASH_CFI /* CONFIG_FLASH_CFI, CONFIG_FLASH_SPI is exclusive*/
++#define CONFIG_FLASH_SPI
++//#define CONFIG_2SPIFLASH /* Boot SPI: CS2, 2nd SPI: CS0 */
++#undef CONFIG_2SPIFLASH
++#undef CONFIG_ASPEED_SLT
++#define CONFIG_FLASH_AST2300
++//#define CONFIG_FLASH_AST2300_DMA
++//#define CONFIG_FLASH_SPIx2_Dummy
++//#define CONFIG_FLASH_SPIx4_Dummy
++#define CONFIG_CRT_DISPLAY 1 /* undef if not support CRT */
++
++//#define CONFIG_USE_IRQ /* we don't need IRQ/FIQ stuff */
++#define CONFIG_MISC_INIT_R
++
++/*
++ * DRAM Config
++ *
++ * 1. DRAM Size //
++ * CONFIG_DRAM_512MBIT // 512M bit
++ * CONFIG_DRAM_1GBIT // 1G bit (default)
++ * CONFIG_DRAM_2GBIT // 2G bit
++ * CONFIG_DRAM_4GBIT // 4G bit
++ * 2. DRAM Speed //
++ * CONFIG_DRAM_336 // 336MHz (DDR-667)
++ * CONFIG_DRAM_408 // 408MHz (DDR-800) (default)
++ * 3. VGA Mode
++ * CONFIG_CRT_DISPLAY // define to disable VGA function
++ * 4. ECC Function enable
++ * CONFIG_DRAM_ECC // define to enable ECC function
++ * 5. UART Debug Message
++ * CONFIG_DRAM_UART_OUT // enable output message at UART5
++ * CONFIG_DRAM_UART_38400 // set the UART baud rate to 38400, default is 115200
++ */
++
++//1. DRAM Size
++//#define CONFIG_DRAM_512MBIT
++#define CONFIG_DRAM_1GBIT
++//#define CONFIG_DRAM_2GBIT
++//#define CONFIG_DRAM_4GBIT
++//2. DRAM Speed
++//#define CONFIG_DRAM_336
++#define CONFIG_DRAM_408
++//3. VGA Mode
++//#define CONFIG_CRT_DISPLAY
++//4. ECC Function enable
++//#define CONFIG_DRAM_ECC
++//5. UART Debug Message
++#define CONFIG_DRAM_UART_OUT
++//#define CONFIG_DRAM_UART_38400
++
++
++
++/*
++ * Environment Config
++ */
++#define CONFIG_CMDLINE_TAG 1 /* enable passing of ATAGs */
++#define CONFIG_SETUP_MEMORY_TAGS 1
++#define CONFIG_INITRD_TAG 1
++#define CONFIG_BOOTARGS "debug console=ttyS0,115200n8 ramdisk_size=16384 root=/dev/ram rw init=/linuxrc mem=32M"
++#define CONFIG_UPDATE "tftp 40800000 ast2400.scr; so 40800000'"
++
++#define CONFIG_BOOTDELAY 0 /* autoboot after 3 seconds */
++#ifdef CONFIG_FLASH_AST2300
++#define CONFIG_BOOTCOMMAND "mactest 0 0 24 2 0 0 0; mactest 1 0 24 2 0 0 0; bootm 20080000 20300000"
++#else
++#ifdef CONFIG_SYS_FLASH_CFI
++#define CONFIG_BOOTCOMMAND "bootm 10080000 10300000"
++#else
++#define CONFIG_BOOTCOMMAND "bootm 14080000 14300000"
++#endif
++#endif
++#define CONFIG_BOOTFILE "all.bin"
++#define CONFIG_ENV_OVERWRITE
++
++/*
++ * Command line configuration.
++ */
++#include <config_cmd_default.h>
++
++#define CONFIG_CMD_DFL
++#define CONFIG_CMD_ENV
++#define CONFIG_CMD_FLASH
++#define CONFIG_CMD_NET
++#define CONFIG_CMD_PING
++#define CONFIG_CMD_I2C
++#define CONFIG_CMD_EEPROM
++#define CONFIG_CMD_NETTEST
++#define CONFIG_CMD_SLT
++
++/*
++ * CPU Setting
++ */
++#define CPU_CLOCK_RATE 18000000 /* 16.5 MHz clock for the ARM core */
++
++/*
++ * Size of malloc() pool
++ */
++#define CONFIG_SYS_MALLOC_LEN (CONFIG_ENV_SIZE + 768*1024)
++#define CONFIG_SYS_GBL_DATA_SIZE 128 /* size in bytes reserved for initial data */
++
++/*
++ * Stack sizes, The stack sizes are set up in start.S using the settings below
++ */
++#define CONFIG_STACKSIZE (128*1024) /* regular stack */
++#define CONFIG_STACKSIZE_IRQ (4*1024) /* IRQ stack */
++#define CONFIG_STACKSIZE_FIQ (4*1024) /* FIQ stack */
++
++/*
++ * Memory Configuration
++ */
++#define CONFIG_NR_DRAM_BANKS 1 /* we have 1 bank of DRAM */
++#define PHYS_SDRAM_1 0x40000000 /* SDRAM Bank #1 */
++#define PHYS_SDRAM_1_SIZE 0x4000000 /* 64 MB */
++
++#define CONFIG_SYS_SDRAM_BASE 0x40000000
++
++/*
++ * FLASH Configuration
++ */
++#ifdef CONFIG_SYS_FLASH_CFI /* NOR Flash */
++
++#ifdef CONFIG_FLASH_AST2300
++#define PHYS_FLASH_1 0x20000000 /* Flash Bank #1 */
++#else
++#define PHYS_FLASH_1 0x10000000 /* Flash Bank #1 */
++#endif
++
++#define CONFIG_SYS_FLASH_BASE PHYS_FLASH_1
++#define CONFIG_FLASH_BANKS_LIST { PHYS_FLASH_1 }
++
++#define CONFIG_SYS_MAX_FLASH_BANKS 1
++#define CONFIG_SYS_MAX_FLASH_SECT (256) /* max number of sectors on one chip */
++
++#define CONFIG_ENV_IS_IN_FLASH 1
++#define CONFIG_ENV_OFFSET 0xFE0000 /* environment starts here */
++#define CONFIG_ENV_SIZE 0x020000 /* Total Size of Environment Sector */
++
++#define CONFIG_SYS_FLASH_CFI_AMD_RESET
++#define CONFIG_SYS_FLASH_USE_BUFFER_WRITE
++
++#else /* SPI Flash */
++
++#ifdef CONFIG_FLASH_AST2300
++#define PHYS_FLASH_1 0x20000000 /* Flash Bank #1 */
++#else
++#define PHYS_FLASH_1 0x14000000 /* Flash Bank #1 */
++#define PHYS_FLASH_2 0x14800000 /* Flash Bank #2 */
++#define PHYS_FLASH_2_BASE 0x10000000
++#endif
++
++#ifdef CONFIG_2SPIFLASH
++#define CONFIG_SYS_FLASH_BASE PHYS_FLASH_2_BASE
++#define CONFIG_FLASH_BANKS_LIST { PHYS_FLASH_1, PHYS_FLASH_2 }
++#define CONFIG_SYS_MAX_FLASH_BANKS 2
++#define CONFIG_SYS_MAX_FLASH_SECT (1024) /* max number of sectors on one chip */
++
++#define CONFIG_ENV_IS_IN_FLASH 1
++#define CONFIG_ENV_OFFSET 0x7F0000 /* environment starts here */
++#define CONFIG_ENV_SIZE 0x010000 /* Total Size of Environment Sector */
++#else
++#define CONFIG_SYS_FLASH_BASE PHYS_FLASH_1
++#define CONFIG_FLASH_BANKS_LIST { PHYS_FLASH_1 }
++#define CONFIG_SYS_MAX_FLASH_BANKS 1
++#define CONFIG_SYS_MAX_FLASH_SECT (1024) /* max number of sectors on one chip */
++
++#define CONFIG_ENV_IS_IN_FLASH 1
++#define CONFIG_ENV_OFFSET 0x7F0000 /* environment starts here */
++#define CONFIG_ENV_SIZE 0x010000 /* Total Size of Environment Sector */
++#endif
++
++#endif
++
++#define __LITTLE_ENDIAN
++
++#define CONFIG_MONITOR_BASE TEXT_BASE
++#define CONFIG_MONITOR_LEN (192 << 10)
++
++/* timeout values are in ticks */
++#define CONFIG_SYS_FLASH_ERASE_TOUT (20*CONFIG_SYS_HZ) /* Timeout for Flash Erase */
++#define CONFIG_SYS_FLASH_WRITE_TOUT (20*CONFIG_SYS_HZ) /* Timeout for Flash Write */
++
++/*
++ * Miscellaneous configurable options
++ */
++#define CONFIG_SYS_LONGHELP /* undef to save memory */
++
++#define CONFIG_SYS_PROMPT "boot# " /* Monitor Command Prompt */
++#define CONFIG_SYS_CBSIZE 256 /* Console I/O Buffer Size */
++#define CONFIG_SYS_PBSIZE (CONFIG_SYS_CBSIZE+sizeof(CONFIG_SYS_PROMPT)+16) /* Print Buffer Size */
++#define CONFIG_SYS_MAXARGS 16 /* max number of command args */
++#define CONFIG_SYS_BARGSIZE CONFIG_SYS_CBSIZE /* Boot Argument Buffer Size */
++
++#define CONFIG_SYS_MEMTEST_START 0x40000000 /* memtest works on */
++#define CONFIG_SYS_MEMTEST_END 0x44FFFFFF /* 256 MB in DRAM */
++
++#define CONFIG_SYS_CLKS_IN_HZ /* everything, incl board info, in Hz */
++#undef CONFIG_SYS_CLKS_IN_HZ /* everything, incl board info, in Hz */
++
++#define CONFIG_SYS_LOAD_ADDR 0x43000000 /* default load address */
++
++#define CONFIG_SYS_TIMERBASE 0x1E782000 /* use timer 1 */
++#define CONFIG_SYS_HZ (1*1000*1000) /* use external clk (1M) */
++
++/*
++ * Serial Configuration
++ */
++#define CONFIG_SYS_NS16550
++#define CONFIG_SYS_NS16550_SERIAL
++#define CONFIG_SYS_NS16550_REG_SIZE 4
++#define CONFIG_SYS_NS16550_CLK 24000000
++#define CONFIG_SYS_NS16550_COM1 0x1e783000
++#define CONFIG_SYS_NS16550_COM2 0x1e784000
++#define CONFIG_SYS_LOADS_BAUD_CHANGE
++#define CONFIG_SERIAL1 1
++#define CONFIG_CONS_INDEX 2
++#define CONFIG_BAUDRATE 115200
++#define CONFIG_SYS_BAUDRATE_TABLE { 9600, 19200, 38400, 57600, 115200 }
++
++/*
++ * USB device configuration
++ */
++/*
++#define CONFIG_USB_DEVICE 1
++#define CONFIG_USB_TTY 1
++
++#define CONFIG_USBD_VENDORID 0x1234
++#define CONFIG_USBD_PRODUCTID 0x5678
++#define CONFIG_USBD_MANUFACTURER "Siemens"
++#define CONFIG_USBD_PRODUCT_NAME "SX1"
++*/
++
++/*
++ * I2C configuration
++ */
++#define CONFIG_HARD_I2C
++#define CONFIG_SYS_I2C_SPEED 100000
++#define CONFIG_SYS_I2C_SLAVE 1
++#define CONFIG_DRIVER_ASPEED_I2C
++
++/*
++* EEPROM configuration
++*/
++#define CONFIG_SYS_I2C_EEPROM_ADDR_LEN 2
++#define CONFIG_SYS_I2C_EEPROM_ADDR 0xa0
++
++/*
++ * NIC configuration
++ */
++#define __BYTE_ORDER __LITTLE_ENDIAN
++#define __LITTLE_ENDIAN_BITFIELD
++#define CONFIG_MAC_PARTITION
++/*#define CONFIG_ASPEEDNIC*/
++#define CONFIG_MAC1_PHY_LINK_INTERRUPT
++#define CONFIG_MAC2_ENABLE
++#define CONFIG_MAC2_PHY_LINK_INTERRUPT
++/*
++*-------------------------------------------------------------------------------
++* NOTICE: MAC1 and MAC2 now have their own seperate PHY configuration.
++* We use 2 bits for each MAC in the scratch register(D[15:11] in 0x1E6E2040) to
++* inform kernel driver.
++* The meanings of the 2 bits are:
++* 00(0): Dedicated PHY
++* 01(1): ASPEED's EVA + INTEL's NC-SI PHY chip EVA
++* 10(2): ASPEED's MAC is connected to NC-SI PHY chip directly
++* 11: Reserved
++*
++* We use CONFIG_MAC1_PHY_SETTING and CONFIG_MAC2_PHY_SETTING in U-Boot
++* 0: Dedicated PHY
++* 1: ASPEED's EVA + INTEL's NC-SI PHY chip EVA
++* 2: ASPEED's MAC is connected to NC-SI PHY chip directly
++* 3: Reserved
++*-------------------------------------------------------------------------------
++*/
++#define CONFIG_MAC1_PHY_SETTING 0
++#define CONFIG_MAC2_PHY_SETTING 0
++#define CONFIG_MAC_INTERFACE_CLOCK_DELAY 0x2255
++#define CONFIG_NET_MULTI
++#define CONFIG_ETHACT aspeednic#0
++#define CONFIG_GATEWAYIP 192.168.0.1
++#define CONFIG_NETMASK 255.255.255.0
++#define CONFIG_IPADDR 192.168.0.45
++#define CONFIG_SERVERIP 192.168.0.81
++#define CONFIG_ETHADDR 00:C0:A8:12:34:56
++#define CONFIG_ETH1ADDR 00:C0:A8:12:34:57
++
++/*
++ * SLT
++ */
++/*
++#define CONFIG_SLT
++#define CFG_CMD_SLT (CFG_CMD_VIDEOTEST | CFG_CMD_MACTEST | CFG_CMD_HACTEST | CFG_CMD_MICTEST)
++*/
++
++#endif /* __CONFIG_H */
+diff --git a/include/configs/ast2400_spi.h b/include/configs/ast2400_spi.h
+new file mode 100644
+index 0000000..398e168
+--- /dev/null
++++ b/include/configs/ast2400_spi.h
+@@ -0,0 +1,322 @@
++/*
++ * (C) Copyright 2004
++ * Peter Chen <peterc@socle-tech.com.tw>
++ *
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License as
++ * published by the Free Software Foundation; either version 2 of
++ * the License, or (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
++ * MA 02111-1307 USA
++ */
++
++#ifndef __CONFIG_H
++#define __CONFIG_H
++
++/*
++ * High Level Configuration Options
++ * (easy to change)
++ */
++//#define CONFIG_INIT_CRITICAL /* define for U-BOOT 1.1.1 */
++#undef CONFIG_INIT_CRITICAL /* undef for U-BOOT 1.1.4 */
++#define CONFIG_ARM926EJS 1 /* This is an arm926ejs CPU */
++#define CONFIG_ASPEED 1
++#define CONFIG_AST2400 1
++//#define CONFIG_SYS_FLASH_CFI /* CONFIG_FLASH_CFI, CONFIG_FLASH_SPI is exclusive*/
++#define CONFIG_FLASH_SPI
++//#define CONFIG_2SPIFLASH /* Boot SPI: CS2, 2nd SPI: CS0 */
++#undef CONFIG_2SPIFLASH
++#undef CONFIG_ASPEED_SLT
++#define CONFIG_FLASH_AST2300
++#define CONFIG_FLASH_AST2300_DMA
++//#define CONFIG_FLASH_SPIx2_Dummy
++//#define CONFIG_FLASH_SPIx4_Dummy
++#define CONFIG_CRT_DISPLAY 1 /* undef if not support CRT */
++
++//#define CONFIG_USE_IRQ /* we don't need IRQ/FIQ stuff */
++#define CONFIG_MISC_INIT_R
++
++/*
++ * DRAM Config
++ *
++ * 1. DRAM Size //
++ * CONFIG_DRAM_512MBIT // 512M bit
++ * CONFIG_DRAM_1GBIT // 1G bit (default)
++ * CONFIG_DRAM_2GBIT // 2G bit
++ * CONFIG_DRAM_4GBIT // 4G bit
++ * 2. DRAM Speed //
++ * CONFIG_DRAM_336 // 336MHz (DDR-667)
++ * CONFIG_DRAM_408 // 408MHz (DDR-800) (default)
++ * 3. VGA Mode
++ * CONFIG_CRT_DISPLAY // define to disable VGA function
++ * 4. ECC Function enable
++ * CONFIG_DRAM_ECC // define to enable ECC function
++ * 5. UART Debug Message
++ * CONFIG_DRAM_UART_OUT // enable output message at UART5
++ * CONFIG_DRAM_UART_38400 // set the UART baud rate to 38400, default is 115200
++ */
++
++//1. DRAM Size
++//#define CONFIG_DRAM_512MBIT
++#define CONFIG_DRAM_1GBIT
++//#define CONFIG_DRAM_2GBIT
++//#define CONFIG_DRAM_4GBIT
++//2. DRAM Speed
++//#define CONFIG_DRAM_336
++#define CONFIG_DRAM_408
++//3. VGA Mode
++//#define CONFIG_CRT_DISPLAY
++//4. ECC Function enable
++//#define CONFIG_DRAM_ECC
++//5. UART Debug Message
++#define CONFIG_DRAM_UART_OUT
++//#define CONFIG_DRAM_UART_38400
++
++
++
++/*
++ * Environment Config
++ */
++#define CONFIG_CMDLINE_TAG 1 /* enable passing of ATAGs */
++#define CONFIG_SETUP_MEMORY_TAGS 1
++#define CONFIG_INITRD_TAG 1
++#define CONFIG_BOOTARGS "debug console=ttyS0,115200n8 ramdisk_size=16384 root=/dev/ram rw init=/linuxrc mem=80M"
++#define CONFIG_BOOTDELAY 3 /* autoboot after 3 seconds */
++#ifdef CONFIG_FLASH_AST2300
++#define CONFIG_BOOTCOMMAND "bootm 20080000 20300000"
++#else
++#ifdef CONFIG_SYS_FLASH_CFI
++#define CONFIG_BOOTCOMMAND "bootm 10080000 10300000"
++#else
++#define CONFIG_BOOTCOMMAND "bootm 14080000 14300000"
++#endif
++#endif
++#define CONFIG_BOOTFILE "all.bin"
++#define CONFIG_ENV_OVERWRITE
++
++/*
++ * Command line configuration.
++ */
++#include <config_cmd_default.h>
++
++#define CONFIG_CMD_DFL
++#define CONFIG_CMD_ENV
++#define CONFIG_CMD_FLASH
++#define CONFIG_CMD_NET
++#define CONFIG_CMD_PING
++#define CONFIG_CMD_I2C
++#define CONFIG_CMD_EEPROM
++
++/*
++ * CPU Setting
++ */
++#define CPU_CLOCK_RATE 18000000 /* 16.5 MHz clock for the ARM core */
++
++/*
++ * Size of malloc() pool
++ */
++#define CONFIG_SYS_MALLOC_LEN (CONFIG_ENV_SIZE + 768*1024)
++#define CONFIG_SYS_GBL_DATA_SIZE 128 /* size in bytes reserved for initial data */
++
++/*
++ * Stack sizes, The stack sizes are set up in start.S using the settings below
++ */
++#define CONFIG_STACKSIZE (128*1024) /* regular stack */
++#define CONFIG_STACKSIZE_IRQ (4*1024) /* IRQ stack */
++#define CONFIG_STACKSIZE_FIQ (4*1024) /* FIQ stack */
++
++/*
++ * Memory Configuration
++ */
++#define CONFIG_NR_DRAM_BANKS 1 /* we have 1 bank of DRAM */
++#define PHYS_SDRAM_1 0x40000000 /* SDRAM Bank #1 */
++#define PHYS_SDRAM_1_SIZE 0x4000000 /* 64 MB */
++
++#define CONFIG_SYS_SDRAM_BASE 0x40000000
++
++/*
++ * FLASH Configuration
++ */
++#ifdef CONFIG_SYS_FLASH_CFI /* NOR Flash */
++
++#ifdef CONFIG_FLASH_AST2300
++#define PHYS_FLASH_1 0x20000000 /* Flash Bank #1 */
++#else
++#define PHYS_FLASH_1 0x10000000 /* Flash Bank #1 */
++#endif
++
++#define CONFIG_SYS_FLASH_BASE PHYS_FLASH_1
++#define CONFIG_FLASH_BANKS_LIST { PHYS_FLASH_1 }
++
++#define CONFIG_SYS_MAX_FLASH_BANKS 1
++#define CONFIG_SYS_MAX_FLASH_SECT (256) /* max number of sectors on one chip */
++
++#define CONFIG_ENV_IS_IN_FLASH 1
++#define CONFIG_ENV_OFFSET 0x60000 /* environment starts here */
++#define CONFIG_ENV_SIZE 0x20000 /* Total Size of Environment Sector */
++
++#define CONFIG_SYS_FLASH_CFI_AMD_RESET
++#define CONFIG_SYS_FLASH_USE_BUFFER_WRITE
++
++#else /* SPI Flash */
++
++#ifdef CONFIG_FLASH_AST2300
++#define PHYS_FLASH_1 0x20000000 /* Flash Bank #1 */
++#else
++#define PHYS_FLASH_1 0x14000000 /* Flash Bank #1 */
++#define PHYS_FLASH_2 0x14800000 /* Flash Bank #2 */
++#define PHYS_FLASH_2_BASE 0x10000000
++#endif
++
++#ifdef CONFIG_2SPIFLASH
++#define CONFIG_SYS_FLASH_BASE PHYS_FLASH_2_BASE
++#define CONFIG_FLASH_BANKS_LIST { PHYS_FLASH_1, PHYS_FLASH_2 }
++#define CONFIG_SYS_MAX_FLASH_BANKS 2
++#define CONFIG_SYS_MAX_FLASH_SECT (1024) /* max number of sectors on one chip */
++
++#define CONFIG_ENV_IS_IN_FLASH 1
++#define CONFIG_ENV_OFFSET 0x7F0000 /* environment starts here */
++#define CONFIG_ENV_SIZE 0x010000 /* Total Size of Environment Sector */
++#else
++#define CONFIG_SYS_FLASH_BASE PHYS_FLASH_1
++#define CONFIG_FLASH_BANKS_LIST { PHYS_FLASH_1 }
++#define CONFIG_SYS_MAX_FLASH_BANKS 1
++#define CONFIG_SYS_MAX_FLASH_SECT (1024) /* max number of sectors on one chip */
++
++#define CONFIG_ENV_IS_IN_FLASH 1
++#define CONFIG_ENV_OFFSET 0x7F0000 /* environment starts here */
++#define CONFIG_ENV_SIZE 0x010000 /* Total Size of Environment Sector */
++#endif
++
++#endif
++
++#define __LITTLE_ENDIAN
++
++#define CONFIG_MONITOR_BASE TEXT_BASE
++#define CONFIG_MONITOR_LEN (192 << 10)
++
++/* timeout values are in ticks */
++#define CONFIG_SYS_FLASH_ERASE_TOUT (20*CONFIG_SYS_HZ) /* Timeout for Flash Erase */
++#define CONFIG_SYS_FLASH_WRITE_TOUT (20*CONFIG_SYS_HZ) /* Timeout for Flash Write */
++
++/*
++ * Miscellaneous configurable options
++ */
++#define CONFIG_SYS_LONGHELP /* undef to save memory */
++
++#define CONFIG_SYS_PROMPT "boot# " /* Monitor Command Prompt */
++#define CONFIG_SYS_CBSIZE 256 /* Console I/O Buffer Size */
++#define CONFIG_SYS_PBSIZE (CONFIG_SYS_CBSIZE+sizeof(CONFIG_SYS_PROMPT)+16) /* Print Buffer Size */
++#define CONFIG_SYS_MAXARGS 16 /* max number of command args */
++#define CONFIG_SYS_BARGSIZE CONFIG_SYS_CBSIZE /* Boot Argument Buffer Size */
++
++#define CONFIG_SYS_MEMTEST_START 0x40000000 /* memtest works on */
++#define CONFIG_SYS_MEMTEST_END 0x44FFFFFF /* 256 MB in DRAM */
++
++#define CONFIG_SYS_CLKS_IN_HZ /* everything, incl board info, in Hz */
++#undef CONFIG_SYS_CLKS_IN_HZ /* everything, incl board info, in Hz */
++
++#define CONFIG_SYS_LOAD_ADDR 0x43000000 /* default load address */
++
++#define CONFIG_SYS_TIMERBASE 0x1E782000 /* use timer 1 */
++#define CONFIG_SYS_HZ (1*1000*1000) /* use external clk (1M) */
++
++/*
++ * Serial Configuration
++ */
++#define CONFIG_SYS_NS16550
++#define CONFIG_SYS_NS16550_SERIAL
++#define CONFIG_SYS_NS16550_REG_SIZE 4
++#define CONFIG_SYS_NS16550_CLK 24000000
++#define CONFIG_SYS_NS16550_COM1 0x1e783000
++#define CONFIG_SYS_NS16550_COM2 0x1e784000
++#define CONFIG_SYS_LOADS_BAUD_CHANGE
++#define CONFIG_SERIAL1 1
++#define CONFIG_CONS_INDEX 2
++#define CONFIG_BAUDRATE 115200
++#define CONFIG_SYS_BAUDRATE_TABLE { 9600, 19200, 38400, 57600, 115200 }
++
++/*
++ * USB device configuration
++ */
++/*
++#define CONFIG_USB_DEVICE 1
++#define CONFIG_USB_TTY 1
++
++#define CONFIG_USBD_VENDORID 0x1234
++#define CONFIG_USBD_PRODUCTID 0x5678
++#define CONFIG_USBD_MANUFACTURER "Siemens"
++#define CONFIG_USBD_PRODUCT_NAME "SX1"
++*/
++
++/*
++ * I2C configuration
++ */
++#define CONFIG_HARD_I2C
++#define CONFIG_SYS_I2C_SPEED 100000
++#define CONFIG_SYS_I2C_SLAVE 1
++#define CONFIG_DRIVER_ASPEED_I2C
++
++/*
++* EEPROM configuration
++*/
++#define CONFIG_SYS_I2C_EEPROM_ADDR_LEN 2
++#define CONFIG_SYS_I2C_EEPROM_ADDR 0xa0
++
++/*
++ * NIC configuration
++ */
++#define __BYTE_ORDER __LITTLE_ENDIAN
++#define __LITTLE_ENDIAN_BITFIELD
++#define CONFIG_MAC_PARTITION
++#define CONFIG_ASPEEDNIC
++#define CONFIG_MAC1_PHY_LINK_INTERRUPT
++#define CONFIG_MAC2_ENABLE
++#define CONFIG_MAC2_PHY_LINK_INTERRUPT
++/*
++*-------------------------------------------------------------------------------
++* NOTICE: MAC1 and MAC2 now have their own seperate PHY configuration.
++* We use 2 bits for each MAC in the scratch register(D[15:11] in 0x1E6E2040) to
++* inform kernel driver.
++* The meanings of the 2 bits are:
++* 00(0): Dedicated PHY
++* 01(1): ASPEED's EVA + INTEL's NC-SI PHY chip EVA
++* 10(2): ASPEED's MAC is connected to NC-SI PHY chip directly
++* 11: Reserved
++*
++* We use CONFIG_MAC1_PHY_SETTING and CONFIG_MAC2_PHY_SETTING in U-Boot
++* 0: Dedicated PHY
++* 1: ASPEED's EVA + INTEL's NC-SI PHY chip EVA
++* 2: ASPEED's MAC is connected to NC-SI PHY chip directly
++* 3: Reserved
++*-------------------------------------------------------------------------------
++*/
++#define CONFIG_MAC1_PHY_SETTING 0
++#define CONFIG_MAC2_PHY_SETTING 0
++#define CONFIG_MAC_INTERFACE_CLOCK_DELAY 0x2255
++#define CONFIG_NET_MULTI
++#define CONFIG_ETHACT aspeednic#0
++#define CONFIG_GATEWAYIP 192.168.0.1
++#define CONFIG_NETMASK 255.255.255.0
++#define CONFIG_IPADDR 192.168.0.45
++#define CONFIG_SERVERIP 192.168.0.81
++#define CONFIG_ETHADDR 00:C0:A8:12:34:56
++#define CONFIG_ETH1ADDR 00:C0:A8:12:34:57
++
++/*
++ * SLT
++ */
++/*
++#define CONFIG_SLT
++#define CFG_CMD_SLT (CFG_CMD_VIDEOTEST | CFG_CMD_MACTEST | CFG_CMD_HACTEST | CFG_CMD_MICTEST)
++*/
++
++#endif /* __CONFIG_H */
+diff --git a/include/configs/ast3100.h b/include/configs/ast3100.h
+new file mode 100644
+index 0000000..f2a2aed
+--- /dev/null
++++ b/include/configs/ast3100.h
+@@ -0,0 +1,325 @@
++/*
++ * (C) Copyright 2004
++ * Peter Chen <peterc@socle-tech.com.tw>
++ *
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License as
++ * published by the Free Software Foundation; either version 2 of
++ * the License, or (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
++ * MA 02111-1307 USA
++ */
++
++#ifndef __CONFIG_H
++#define __CONFIG_H
++
++/*
++ * High Level Configuration Options
++ * (easy to change)
++ */
++//#define CONFIG_INIT_CRITICAL /* define for U-BOOT 1.1.1 */
++#undef CONFIG_INIT_CRITICAL /* undef for U-BOOT 1.1.4 */
++#define CONFIG_ARM926EJS 1 /* This is an arm926ejs CPU */
++#define CONFIG_ASPEED 1
++//#define CONFIG_AST2300 1
++#define CONFIG_AST3100 1
++#define CONFIG_AST3100_D200 1 /* Clientron D200*/
++//#define CONFIG_SYS_FLASH_CFI /* CONFIG_FLASH_CFI, CONFIG_FLASH_SPI is exclusive*/
++#define CONFIG_FLASH_SPI
++//#define CONFIG_2SPIFLASH /* Boot SPI: CS2, 2nd SPI: CS0 */
++#undef CONFIG_2SPIFLASH
++#undef CONFIG_ASPEED_SLT
++#define CONFIG_FLASH_AST2300
++//#define CONFIG_FLASH_AST2300_DMA
++//#define CONFIG_FLASH_SPIx2_Dummy
++//#define CONFIG_FLASH_SPIx4_Dummy
++#define CONFIG_CRT_DISPLAY 1 /* undef if not support CRT */
++
++//#define CONFIG_USE_IRQ /* we don't need IRQ/FIQ stuff */
++#define CONFIG_MISC_INIT_R
++
++/*
++ * DRAM Config
++ *
++ * 1. DRAM Size //
++ * CONFIG_DRAM_512MBIT // 512M bit
++ * CONFIG_DRAM_1GBIT // 1G bit (default)
++ * CONFIG_DRAM_2GBIT // 2G bit
++ * CONFIG_DRAM_4GBIT // 4G bit
++ * 2. DRAM Speed //
++ * CONFIG_DRAM_336 // 336MHz (DDR-667)
++ * CONFIG_DRAM_408 // 408MHz (DDR-800) (default)
++ * 3. VGA Mode
++ * CONFIG_CRT_DISPLAY // define to disable VGA function
++ * 4. ECC Function enable
++ * CONFIG_DRAM_ECC // define to enable ECC function
++ * 5. UART Debug Message
++ * CONFIG_DRAM_UART_OUT // enable output message at UART5
++ * CONFIG_DRAM_UART_38400 // set the UART baud rate to 38400, default is 115200
++ */
++
++//1. DRAM Size
++//#define CONFIG_DRAM_512MBIT
++#define CONFIG_DRAM_1GBIT
++//#define CONFIG_DRAM_2GBIT
++//#define CONFIG_DRAM_4GBIT
++//2. DRAM Speed
++//#define CONFIG_DRAM_336
++#define CONFIG_DRAM_408
++//3. VGA Mode
++//#define CONFIG_CRT_DISPLAY
++//4. ECC Function enable
++//#define CONFIG_DRAM_ECC
++//5. UART Debug Message
++#define CONFIG_DRAM_UART_OUT
++//#define CONFIG_DRAM_UART_38400
++
++
++
++/*
++ * Environment Config
++ */
++#define CONFIG_CMDLINE_TAG 1 /* enable passing of ATAGs */
++#define CONFIG_SETUP_MEMORY_TAGS 1
++#define CONFIG_INITRD_TAG 1
++#define CONFIG_BOOTARGS "debug console=ttyS1,115200n8 ramdisk_size=16384 root=/dev/ram rw init=/linuxrc mem=80M"
++#define CONFIG_BOOTDELAY 4 /* autoboot after 4 seconds */
++#ifdef CONFIG_FLASH_AST2300
++#define CONFIG_BOOTCOMMAND "bootm 20080000 20300000"
++#else
++#ifdef CONFIG_SYS_FLASH_CFI
++#define CONFIG_BOOTCOMMAND "bootm 10080000 10300000"
++#else
++#define CONFIG_BOOTCOMMAND "bootm 14080000 14300000"
++#endif
++#endif
++#define CONFIG_BOOTFILE "allc.bin"
++#define CONFIG_ENV_OVERWRITE
++
++/*
++ * Command line configuration.
++ */
++#include <config_cmd_default.h>
++
++#define CONFIG_CMD_DFL
++#define CONFIG_CMD_ENV
++#define CONFIG_CMD_FLASH
++#define CONFIG_CMD_NET
++#define CONFIG_CMD_PING
++#define CONFIG_CMD_I2C
++#define CONFIG_CMD_EEPROM
++
++/*
++ * CPU Setting
++ */
++#define CPU_CLOCK_RATE 18000000 /* 16.5 MHz clock for the ARM core */
++
++/*
++ * Size of malloc() pool
++ */
++#define CONFIG_SYS_MALLOC_LEN (CONFIG_ENV_SIZE + 768*1024)
++#define CONFIG_SYS_GBL_DATA_SIZE 128 /* size in bytes reserved for initial data */
++
++/*
++ * Stack sizes, The stack sizes are set up in start.S using the settings below
++ */
++#define CONFIG_STACKSIZE (128*1024) /* regular stack */
++#define CONFIG_STACKSIZE_IRQ (4*1024) /* IRQ stack */
++#define CONFIG_STACKSIZE_FIQ (4*1024) /* FIQ stack */
++
++/*
++ * Memory Configuration
++ */
++#define CONFIG_DRAM_528
++#define CONFIG_NR_DRAM_BANKS 1 /* we have 1 bank of DRAM */
++#define PHYS_SDRAM_1 0x40000000 /* SDRAM Bank #1 */
++#define PHYS_SDRAM_1_SIZE 0x4000000 /* 64 MB */
++
++#define CONFIG_SYS_SDRAM_BASE 0x40000000
++
++/*
++ * FLASH Configuration
++ */
++#ifdef CONFIG_SYS_FLASH_CFI /* NOR Flash */
++
++#ifdef CONFIG_FLASH_AST2300
++#define PHYS_FLASH_1 0x20000000 /* Flash Bank #1 */
++#else
++#define PHYS_FLASH_1 0x10000000 /* Flash Bank #1 */
++#endif
++
++#define CONFIG_SYS_FLASH_BASE PHYS_FLASH_1
++#define CONFIG_FLASH_BANKS_LIST { PHYS_FLASH_1 }
++
++#define CONFIG_SYS_MAX_FLASH_BANKS 1
++#define CONFIG_SYS_MAX_FLASH_SECT (256) /* max number of sectors on one chip */
++
++#define CONFIG_ENV_IS_IN_FLASH 1
++#define CONFIG_ENV_OFFSET 0x60000 /* environment starts here */
++#define CONFIG_ENV_SIZE 0x20000 /* Total Size of Environment Sector */
++
++#define CONFIG_SYS_FLASH_CFI_AMD_RESET
++#define CONFIG_SYS_FLASH_USE_BUFFER_WRITE
++
++#else /* SPI Flash */
++
++#ifdef CONFIG_FLASH_AST2300
++#define PHYS_FLASH_1 0x20000000 /* Flash Bank #1 */
++#else
++#define PHYS_FLASH_1 0x14000000 /* Flash Bank #1 */
++#define PHYS_FLASH_2 0x14800000 /* Flash Bank #2 */
++#define PHYS_FLASH_2_BASE 0x10000000
++#endif
++
++#ifdef CONFIG_2SPIFLASH
++#define CONFIG_SYS_FLASH_BASE PHYS_FLASH_2_BASE
++#define CONFIG_FLASH_BANKS_LIST { PHYS_FLASH_1, PHYS_FLASH_2 }
++#define CONFIG_SYS_MAX_FLASH_BANKS 2
++#define CONFIG_SYS_MAX_FLASH_SECT (512) /* max number of sectors on one chip */
++
++#define CONFIG_ENV_IS_IN_FLASH 1
++#define CONFIG_ENV_OFFSET 0x7F0000 /* environment starts here */
++#define CONFIG_ENV_SIZE 0x010000 /* Total Size of Environment Sector */
++#else
++#define CONFIG_SYS_FLASH_BASE PHYS_FLASH_1
++#define CONFIG_FLASH_BANKS_LIST { PHYS_FLASH_1 }
++#define CONFIG_SYS_MAX_FLASH_BANKS 1
++#define CONFIG_SYS_MAX_FLASH_SECT (512) /* max number of sectors on one chip */
++
++#define CONFIG_ENV_IS_IN_FLASH 1
++#define CONFIG_ENV_OFFSET 0x7F0000 /* environment starts here */
++#define CONFIG_ENV_SIZE 0x010000 /* Total Size of Environment Sector */
++#endif
++
++#endif
++
++#define __LITTLE_ENDIAN
++
++#define CONFIG_MONITOR_BASE TEXT_BASE
++#define CONFIG_MONITOR_LEN (192 << 10)
++
++/* timeout values are in ticks */
++#define CONFIG_SYS_FLASH_ERASE_TOUT (20*CONFIG_SYS_HZ) /* Timeout for Flash Erase */
++#define CONFIG_SYS_FLASH_WRITE_TOUT (20*CONFIG_SYS_HZ) /* Timeout for Flash Write */
++
++/*
++ * Miscellaneous configurable options
++ */
++#define CONFIG_SYS_LONGHELP /* undef to save memory */
++
++#define CONFIG_SYS_PROMPT "boot# " /* Monitor Command Prompt */
++#define CONFIG_SYS_CBSIZE 256 /* Console I/O Buffer Size */
++#define CONFIG_SYS_PBSIZE (CONFIG_SYS_CBSIZE+sizeof(CONFIG_SYS_PROMPT)+16) /* Print Buffer Size */
++#define CONFIG_SYS_MAXARGS 16 /* max number of command args */
++#define CONFIG_SYS_BARGSIZE CONFIG_SYS_CBSIZE /* Boot Argument Buffer Size */
++
++#define CONFIG_SYS_MEMTEST_START 0x40000000 /* memtest works on */
++#define CONFIG_SYS_MEMTEST_END 0x44FFFFFF /* 256 MB in DRAM */
++
++#define CONFIG_SYS_CLKS_IN_HZ /* everything, incl board info, in Hz */
++#undef CONFIG_SYS_CLKS_IN_HZ /* everything, incl board info, in Hz */
++
++#define CONFIG_SYS_LOAD_ADDR 0x43000000 /* default load address */
++
++#define CONFIG_SYS_TIMERBASE 0x1E782000 /* use timer 1 */
++#define CONFIG_SYS_HZ (1*1000*1000) /* use external clk (1M) */
++
++/*
++ * Serial Configuration
++ */
++#define CONFIG_SYS_NS16550
++#define CONFIG_SYS_NS16550_SERIAL
++#define CONFIG_SYS_NS16550_REG_SIZE 4
++#define CONFIG_SYS_NS16550_CLK 24000000
++#define CONFIG_SYS_NS16550_COM1 0x1e783000
++#define CONFIG_SYS_NS16550_COM2 0x1e784000
++#define CONFIG_SYS_LOADS_BAUD_CHANGE
++#define CONFIG_SERIAL1 1
++#define CONFIG_CONS_INDEX 2
++#define CONFIG_BAUDRATE 115200
++#define CONFIG_SYS_BAUDRATE_TABLE { 9600, 19200, 38400, 57600, 115200 }
++
++/*
++ * USB device configuration
++ */
++/*
++#define CONFIG_USB_DEVICE 1
++#define CONFIG_USB_TTY 1
++
++#define CONFIG_USBD_VENDORID 0x1234
++#define CONFIG_USBD_PRODUCTID 0x5678
++#define CONFIG_USBD_MANUFACTURER "Siemens"
++#define CONFIG_USBD_PRODUCT_NAME "SX1"
++*/
++
++/*
++ * I2C configuration
++ */
++#define CONFIG_HARD_I2C
++#define CONFIG_SYS_I2C_SPEED 100000
++#define CONFIG_SYS_I2C_SLAVE 1
++#define CONFIG_DRIVER_ASPEED_I2C
++
++/*
++* EEPROM configuration
++*/
++#define CONFIG_SYS_I2C_EEPROM_ADDR_LEN 2
++#define CONFIG_SYS_I2C_EEPROM_ADDR 0xa0
++
++/*
++ * NIC configuration
++ */
++#define __BYTE_ORDER __LITTLE_ENDIAN
++#define __LITTLE_ENDIAN_BITFIELD
++#define CONFIG_MAC_PARTITION
++#define CONFIG_ASPEEDNIC
++//#define CONFIG_MAC1_PHY_LINK_INTERRUPT
++#define CONFIG_MAC2_ENABLE
++#define CONFIG_MAC2_PHY_LINK_INTERRUPT
++/*
++*-------------------------------------------------------------------------------
++* NOTICE: MAC1 and MAC2 now have their own seperate PHY configuration.
++* We use 2 bits for each MAC in the scratch register(D[15:11] in 0x1E6E2040) to
++* inform kernel driver.
++* The meanings of the 2 bits are:
++* 00(0): Dedicated PHY
++* 01(1): ASPEED's EVA + INTEL's NC-SI PHY chip EVA
++* 10(2): ASPEED's MAC is connected to NC-SI PHY chip directly
++* 11: Reserved
++*
++* We use CONFIG_MAC1_PHY_SETTING and CONFIG_MAC2_PHY_SETTING in U-Boot
++* 0: Dedicated PHY
++* 1: ASPEED's EVA + INTEL's NC-SI PHY chip EVA
++* 2: ASPEED's MAC is connected to NC-SI PHY chip directly
++* 3: Reserved
++*-------------------------------------------------------------------------------
++*/
++#define CONFIG_MAC1_PHY_SETTING 0
++#define CONFIG_MAC2_PHY_SETTING 0
++#define CONFIG_MAC_INTERFACE_CLOCK_DELAY 0x2255
++#define CONFIG_NET_MULTI
++#define CONFIG_ETHACT aspeednic#0
++#define CONFIG_GATEWAYIP 192.168.0.1
++#define CONFIG_NETMASK 255.255.255.0
++#define CONFIG_IPADDR 192.168.0.249
++#define CONFIG_SERVERIP 192.168.0.156
++#define CONFIG_ETHADDR 00:D0:A8:12:34:58
++#define CONFIG_ETH1ADDR 00:D0:A8:12:34:59
++
++/*
++ * SLT
++ */
++/*
++#define CONFIG_SLT
++#define CFG_CMD_SLT (CFG_CMD_VIDEOTEST | CFG_CMD_MACTEST | CFG_CMD_HACTEST | CFG_CMD_MICTEST)
++*/
++
++#endif /* __CONFIG_H */
+diff --git a/include/flash.h b/include/flash.h
+index c7acc97..e77be1f 100644
+--- a/include/flash.h
++++ b/include/flash.h
+@@ -57,6 +57,21 @@ typedef struct {
+ ulong addr_unlock2; /* unlock address 2 for AMD flash roms */
+ const char *name; /* human-readable name */
+ #endif
++#ifdef CONFIG_FLASH_SPI
++ ulong readcmd;
++ ulong dualport;
++ ulong dummybyte;
++ ulong tCK_Write;
++ ulong tCK_Erase;
++ ulong tCK_Read;
++ ulong CE;
++ ulong iomode;
++ ulong address32;
++ ulong quadport;
++ ulong dummydata;
++ ulong buffersize;
++ ulong specificspi;
++#endif
+ } flash_info_t;
+
+ extern flash_info_t flash_info[]; /* info for FLASH chips */
diff --git a/meta-aspeed/recipes-bsp/u-boot/files/patch-2013.07/0001-u-boot-openbmc.patch b/meta-aspeed/recipes-bsp/u-boot/files/patch-2013.07/0001-u-boot-openbmc.patch
new file mode 100644
index 0000000..e38ae5a
--- /dev/null
+++ b/meta-aspeed/recipes-bsp/u-boot/files/patch-2013.07/0001-u-boot-openbmc.patch
@@ -0,0 +1,1580 @@
+diff --git a/arch/arm/cpu/arm926ejs/aspeed/IO.c b/arch/arm/cpu/arm926ejs/aspeed/IO.c
+index 86e9918..b06fdba 100644
+--- a/arch/arm/cpu/arm926ejs/aspeed/IO.c
++++ b/arch/arm/cpu/arm926ejs/aspeed/IO.c
+@@ -31,7 +31,7 @@ static const char ThisFile[] = "IO.c";
+ #include <post.h>
+ #include <malloc.h>
+ #include <net.h>
+- #include <COMMINF.H>
++ #include "COMMINF.H"
+ #endif
+ #ifdef SLT_DOS
+ #include <stdlib.h>
+@@ -353,4 +353,3 @@ ULONG ReadSOC_DD(ULONG addr)
+ #endif
+ return 0;
+ }
+-
+diff --git a/arch/arm/cpu/arm926ejs/aspeed/LAN9303.c b/arch/arm/cpu/arm926ejs/aspeed/LAN9303.c
+index 498d4fd..fdabd45 100644
+--- a/arch/arm/cpu/arm926ejs/aspeed/LAN9303.c
++++ b/arch/arm/cpu/arm926ejs/aspeed/LAN9303.c
+@@ -13,9 +13,9 @@ static const char ThisFile[] = "LAN9303.c";
+
+ #include "SWFUNC.H"
+ #ifdef SLT_UBOOT
+- #include <COMMINF.H>
+- #include <MAC.H>
+- #include <IO.H>
++ #include "COMMINF.H"
++ #include "MAC.H"
++ #include "IO.H"
+ #endif
+
+ #ifdef SLT_DOS
+diff --git a/arch/arm/cpu/arm926ejs/aspeed/MAC.c b/arch/arm/cpu/arm926ejs/aspeed/MAC.c
+index 829da92..b4182f5 100644
+--- a/arch/arm/cpu/arm926ejs/aspeed/MAC.c
++++ b/arch/arm/cpu/arm926ejs/aspeed/MAC.c
+@@ -16,7 +16,7 @@ static const char ThisFile[] = "MAC.c";
+ #ifdef SLT_UBOOT
+ #include <common.h>
+ #include <command.h>
+- #include <COMMINF.H>
++ #include "COMMINF.H"
+ #include "STDUBOOT.H"
+ #endif
+ #ifdef SLT_DOS
+@@ -2081,5 +2081,3 @@ char TestingLoop (ULONG loop_checknum) {
+
+ return(0);
+ } // End char TestingLoop (ULONG loop_checknum)
+-
+-
+diff --git a/arch/arm/cpu/arm926ejs/aspeed/Makefile b/arch/arm/cpu/arm926ejs/aspeed/Makefile
+index 378745e..4c4e239 100644
+--- a/arch/arm/cpu/arm926ejs/aspeed/Makefile
++++ b/arch/arm/cpu/arm926ejs/aspeed/Makefile
+@@ -16,7 +16,7 @@
+
+ include $(TOPDIR)/config.mk
+
+-LIB = $(obj)lib$(SOC).a
++LIB = $(obj)lib$(SOC).o
+
+ COBJS = timer.o
+ COBJS += reset.o
+@@ -41,7 +41,7 @@ START := $(addprefix $(obj),$(START))
+ all: $(obj).depend $(LIB)
+
+ $(LIB): $(OBJS)
+- $(AR) $(ARFLAGS) $@ $(OBJS)
++ $(call cmd_link_o_target, $(OBJS))
+
+ #########################################################################
+
+diff --git a/arch/arm/cpu/arm926ejs/aspeed/NCSI.c b/arch/arm/cpu/arm926ejs/aspeed/NCSI.c
+index 7de06c3..7e86fb6 100644
+--- a/arch/arm/cpu/arm926ejs/aspeed/NCSI.c
++++ b/arch/arm/cpu/arm926ejs/aspeed/NCSI.c
+@@ -16,9 +16,9 @@ static const char ThisFile[] = "NCSI.c";
+ #ifdef SLT_UBOOT
+ #include <common.h>
+ #include <command.h>
+- #include <COMMINF.H>
+- #include <NCSI.H>
+- #include <IO.H>
++ #include "COMMINF.H"
++ #include "NCSI.H"
++ #include "IO.H"
+ #endif
+ #ifdef SLT_DOS
+ #include <stdio.h>
+diff --git a/arch/arm/cpu/arm926ejs/aspeed/PHY.c b/arch/arm/cpu/arm926ejs/aspeed/PHY.c
+index 6afed9d..db73a70 100644
+--- a/arch/arm/cpu/arm926ejs/aspeed/PHY.c
++++ b/arch/arm/cpu/arm926ejs/aspeed/PHY.c
+@@ -16,7 +16,7 @@ static const char ThisFile[] = "PHY.c";
+ #ifdef SLT_UBOOT
+ #include <common.h>
+ #include <command.h>
+- #include <COMMINF.H>
++ #include "COMMINF.H"
+ #include "STDUBOOT.H"
+ #endif
+ #ifdef SLT_DOS
+diff --git a/arch/arm/cpu/arm926ejs/aspeed/PLLTESTU.c b/arch/arm/cpu/arm926ejs/aspeed/PLLTESTU.c
+index 95958b0..2414d57 100644
+--- a/arch/arm/cpu/arm926ejs/aspeed/PLLTESTU.c
++++ b/arch/arm/cpu/arm926ejs/aspeed/PLLTESTU.c
+@@ -13,11 +13,11 @@ static const char ThisFile[] = "PLLTEST.c";
+
+ #include "SWFUNC.H"
+
+-#include <COMMINF.H>
+-#include <STDUBOOT.H>
+-#include <TYPEDEF.H>
+-#include <IO.H>
+-#include <PLLTESTU.H>
++#include "COMMINF.H"
++#include "STDUBOOT.H"
++#include "TYPEDEF.H"
++#include "IO.H"
++#include "PLLTESTU.H"
+
+ /*
+ * static
+@@ -407,5 +407,3 @@ int pll_function(int argc, char *argv[])
+ return (ERR_FATAL);
+ }
+ }
+-
+-
+diff --git a/arch/arm/cpu/arm926ejs/aspeed/STDUBOOT.H b/arch/arm/cpu/arm926ejs/aspeed/STDUBOOT.H
+index 7fbf590..4e0adf6 100644
+--- a/arch/arm/cpu/arm926ejs/aspeed/STDUBOOT.H
++++ b/arch/arm/cpu/arm926ejs/aspeed/STDUBOOT.H
+@@ -13,6 +13,5 @@
+
+ unsigned long int strtoul(char *string, char **endPtr, int base);
+ int atoi( char s[] );
+-int rand(void);
+
+ #endif // End STDUBOOT_H
+diff --git a/arch/arm/cpu/arm926ejs/aspeed/STDUBOOT.c b/arch/arm/cpu/arm926ejs/aspeed/STDUBOOT.c
+index 90e2997..4b1f439 100644
+--- a/arch/arm/cpu/arm926ejs/aspeed/STDUBOOT.c
++++ b/arch/arm/cpu/arm926ejs/aspeed/STDUBOOT.c
+@@ -19,11 +19,11 @@ int isspace ( char c )
+ {
+ if ( ( c == ' ' ) || ( c == 9 ) || ( c == 13 ) )
+ return 1;
+-
++
+ return 0;
+ }
+
+-/*
++/*
+ * strtoul.c --
+ *
+ * Source code for the "strtoul" library procedure.
+@@ -111,7 +111,7 @@ strtoul(char *string, char **endPtr, int base)
+ * If no base was provided, pick one from the leading characters
+ * of the string.
+ */
+-
++
+ if (base == 0)
+ {
+ if (*p == '0') {
+@@ -219,17 +219,6 @@ int atoi( char s[] )
+ ans = ( 10 * ans ) + ( s[i] - '0' );
+
+ return ans;
+-}
+-
+-// -----------------------------------------------------------------------------
+-/* rand:return pseudo-random integer on 0...32767 */
+-int rand(void)
+-{
+- static unsigned long int next = 1;
+-
+- next = next * 1103515245 + 12345;
+-
+- return (unsigned int) ( next / 65536 ) % 32768;
+ }
+
+ #endif // End SLT_UBOOT
+diff --git a/arch/arm/cpu/arm926ejs/aspeed/STRESS.c b/arch/arm/cpu/arm926ejs/aspeed/STRESS.c
+index dffd64f..e86685e 100644
+--- a/arch/arm/cpu/arm926ejs/aspeed/STRESS.c
++++ b/arch/arm/cpu/arm926ejs/aspeed/STRESS.c
+@@ -12,8 +12,8 @@
+ static const char ThisFile[] = "STRESS.c";
+
+ #include "SWFUNC.H"
+-#include <COMMINF.H>
+-#include <IO.H>
++#include "COMMINF.H"
++#include "IO.H"
+
+ #define TIMEOUT_DRAM 5000000
+
+@@ -142,4 +142,3 @@ int dram_stress_function(int argc, char *argv[])
+
+ return( ret );
+ }
+-
+diff --git a/arch/arm/cpu/arm926ejs/aspeed/TRAPTEST.c b/arch/arm/cpu/arm926ejs/aspeed/TRAPTEST.c
+index 72936c0..24ec0c5 100644
+--- a/arch/arm/cpu/arm926ejs/aspeed/TRAPTEST.c
++++ b/arch/arm/cpu/arm926ejs/aspeed/TRAPTEST.c
+@@ -13,9 +13,9 @@ static const char ThisFile[] = "PLLTEST.c";
+
+ #include "SWFUNC.H"
+
+-#include <COMMINF.H>
+-#include <TYPEDEF.H>
+-#include <IO.H>
++#include "COMMINF.H"
++#include "TYPEDEF.H"
++#include "IO.H"
+
+ #define ASTCHIP_2400 0
+ #define ASTCHIP_2300 1
+diff --git a/arch/arm/cpu/arm926ejs/aspeed/mactest.c b/arch/arm/cpu/arm926ejs/aspeed/mactest.c
+index 95bd560..62a696d 100644
+--- a/arch/arm/cpu/arm926ejs/aspeed/mactest.c
++++ b/arch/arm/cpu/arm926ejs/aspeed/mactest.c
+@@ -19,9 +19,9 @@ static const char ThisFile[] = "MACTEST.c";
+ #include <post.h>
+ #include <malloc.h>
+ #include <net.h>
+- #include <COMMINF.H>
+- #include <STDUBOOT.H>
+- #include <IO.H>
++ #include "COMMINF.H"
++ #include "STDUBOOT.H"
++ #include "IO.H"
+ #else
+ #include <stdlib.h>
+ #include <string.h>
+@@ -1212,4 +1212,3 @@ Find_Err_IOMargin:;
+ return(Finish_Check(0));
+
+ }
+-
+diff --git a/arch/arm/cpu/arm926ejs/aspeed/reset.c b/arch/arm/cpu/arm926ejs/aspeed/reset.c
+index e0a57f9..ce8dba1 100644
+--- a/arch/arm/cpu/arm926ejs/aspeed/reset.c
++++ b/arch/arm/cpu/arm926ejs/aspeed/reset.c
+@@ -17,7 +17,7 @@ void reset_cpu(ulong addr)
+ {
+ __raw_writel(0x10 , AST_WDT_BASE+0x04);
+ __raw_writel(0x4755, AST_WDT_BASE+0x08);
+- __raw_writel(0x3, AST_WDT_BASE+0x0c);
++ __raw_writel(0x23, AST_WDT_BASE+0x0c); /* reset the full chip */
+
+ while (1)
+ /*nothing*/;
+diff --git a/arch/arm/cpu/arm926ejs/aspeed/timer.c b/arch/arm/cpu/arm926ejs/aspeed/timer.c
+index 4bba5c5..add4c0e 100644
+--- a/arch/arm/cpu/arm926ejs/aspeed/timer.c
++++ b/arch/arm/cpu/arm926ejs/aspeed/timer.c
+@@ -16,12 +16,17 @@
+ */
+
+ #include <common.h>
+-#include <arm926ejs.h>
++
++#if CONFIG_ASPEED_TIMER_CLK < CONFIG_SYS_HZ
++#error "CONFIG_ASPEED_TIMER_CLK must be as large as CONFIG_SYS_HZ"
++#endif
+
+ #define TIMER_LOAD_VAL 0xffffffff
++#define CLK_PER_HZ (CONFIG_ASPEED_TIMER_CLK / CONFIG_SYS_HZ)
+
+ /* macro to read the 32 bit timer */
+-#define READ_TIMER (*(volatile ulong *)(CONFIG_SYS_TIMERBASE+0))
++#define READ_CLK (*(volatile ulong *)(CONFIG_SYS_TIMERBASE + 0))
++#define READ_TIMER (READ_CLK / CLK_PER_HZ)
+
+ static ulong timestamp;
+ static ulong lastdec;
+@@ -57,27 +62,25 @@ void set_timer (ulong t)
+ }
+
+ /* delay x useconds AND perserve advance timstamp value */
+-void udelay (unsigned long usec)
++void __udelay (unsigned long usec)
+ {
+- ulong tmo, tmp;
+-
+- if(usec >= 1000){ /* if "big" number, spread normalization to seconds */
+- tmo = usec / 1000; /* start to normalize for usec to ticks per sec */
+- tmo *= CONFIG_SYS_HZ; /* find number of "ticks" to wait to achieve target */
+- tmo /= 1000; /* finish normalize. */
+- }else{ /* else small number, don't kill it prior to HZ multiply */
+- tmo = usec * CONFIG_SYS_HZ;
+- tmo /= (1000*1000);
+- }
+-
+- tmp = get_timer (0); /* get current timestamp */
+- if( (tmo + tmp + 1) < tmp ) /* if setting this fordward will roll time stamp */
+- reset_timer_masked (); /* reset "advancing" timestamp to 0, set lastdec value */
+- else
+- tmo += tmp; /* else, set advancing stamp wake up time */
+-
+- while (get_timer_masked () < tmo)/* loop till event */
+- /*NOP*/;
++ ulong last = READ_CLK;
++ ulong clks;
++ ulong elapsed = 0;
++
++ /* translate usec to clocks */
++ clks = (usec / 1000) * CLK_PER_HZ;
++ clks += (usec % 1000) * CLK_PER_HZ / 1000;
++
++ while (clks > elapsed) {
++ ulong now = READ_CLK;
++ if (now <= last) {
++ elapsed += last - now;
++ } else {
++ elapsed += TIMER_LOAD_VAL - (now - last);
++ }
++ last = now;
++ }
+ }
+
+ void reset_timer_masked (void)
+@@ -100,7 +103,7 @@ ulong get_timer_masked (void)
+ * (TLV-now) amount of time after passing though -1
+ * nts = new "advancing time stamp"...it could also roll and cause problems.
+ */
+- timestamp += lastdec + TIMER_LOAD_VAL - now;
++ timestamp += lastdec + (TIMER_LOAD_VAL / CLK_PER_HZ) - now;
+ }
+ lastdec = now;
+
+@@ -110,25 +113,7 @@ ulong get_timer_masked (void)
+ /* waits specified delay value and resets timestamp */
+ void udelay_masked (unsigned long usec)
+ {
+- ulong tmo;
+- ulong endtime;
+- signed long diff;
+-
+- if (usec >= 1000) { /* if "big" number, spread normalization to seconds */
+- tmo = usec / 1000; /* start to normalize for usec to ticks per sec */
+- tmo *= CONFIG_SYS_HZ; /* find number of "ticks" to wait to achieve target */
+- tmo /= 1000; /* finish normalize. */
+- } else { /* else small number, don't kill it prior to HZ multiply */
+- tmo = usec * CONFIG_SYS_HZ;
+- tmo /= (1000*1000);
+- }
+-
+- endtime = get_timer_masked () + tmo;
+-
+- do {
+- ulong now = get_timer_masked ();
+- diff = endtime - now;
+- } while (diff >= 0);
++ __udelay(usec);
+ }
+
+ /*
+@@ -146,8 +131,5 @@ unsigned long long get_ticks(void)
+ */
+ ulong get_tbclk (void)
+ {
+- ulong tbclk;
+-
+- tbclk = CONFIG_SYS_HZ;
+- return tbclk;
++ return CONFIG_SYS_HZ;
+ }
+diff --git a/board/aspeed/ast2400/Makefile b/board/aspeed/ast2400/Makefile
+index 1970ea1..fb77fc9 100644
+--- a/board/aspeed/ast2400/Makefile
++++ b/board/aspeed/ast2400/Makefile
+@@ -11,7 +11,7 @@
+
+ include $(TOPDIR)/config.mk
+
+-LIB = $(obj)lib$(BOARD).a
++LIB = $(obj)lib$(BOARD).o
+
+ COBJS := ast2400.o flash.o flash_spi.o pci.o crc32.o slt.o regtest.o vfun.o vhace.o crt.o videotest.o mactest.o hactest.o mictest.o
+
+@@ -28,17 +28,13 @@ OBJS := $(addprefix $(obj),$(COBJS))
+ SOBJS := $(addprefix $(obj),$(SOBJS))
+
+ $(LIB): $(obj).depend $(OBJS) $(SOBJS)
+- $(AR) $(ARFLAGS) $@ $(OBJS) $(SOBJS)
++ $(call cmd_link_o_target, $(OBJS) $(SOBJS))
+
+-clean:
+- rm -f $(SOBJS) $(OBJS)
+-
+-distclean: clean
+- rm -f $(LIB) core *.bak $(obj).depend
++#########################################################################
+
+ # defines $(obj).depend target
+ include $(SRCTREE)/rules.mk
+
+-sinclude .depend
++sinclude $(obj).depend
+
+ #########################################################################
+diff --git a/board/aspeed/ast2400/ast2400.c b/board/aspeed/ast2400/ast2400.c
+index 65bccbe..55ed6b7 100644
+--- a/board/aspeed/ast2400/ast2400.c
++++ b/board/aspeed/ast2400/ast2400.c
+@@ -10,6 +10,7 @@
+ */
+
+ #include <common.h>
++#include <asm/io.h>
+ #include <command.h>
+ #include <pci.h>
+
+@@ -105,8 +106,8 @@ int dram_init (void)
+ {
+ DECLARE_GLOBAL_DATA_PTR;
+
+- gd->bd->bi_dram[0].start = PHYS_SDRAM_1;
+- gd->bd->bi_dram[0].size = PHYS_SDRAM_1_SIZE;
++ /* dram_init must store complete ramsize in gd->ram_size */
++ gd->ram_size = get_ram_size((void *)PHYS_SDRAM_1, PHYS_SDRAM_1_SIZE);
+
+ return 0;
+ }
+@@ -190,6 +191,22 @@ int ast1070_calibration()
+ return 0;
+ }
+
++static void watchdog_init()
++{
++#ifdef CONFIG_ASPEED_ENABLE_WATCHDOG
++#define AST_WDT_BASE 0x1e785000
++#define AST_WDT_CLK (1*1000*1000) /* 1M clock source */
++ u32 reload = AST_WDT_CLK * CONFIG_ASPEED_WATCHDOG_TIMEOUT;
++ /* set the reload value */
++ __raw_writel(reload, AST_WDT_BASE + 0x04);
++ /* magic word to reload */
++ __raw_writel(0x4755, AST_WDT_BASE + 0x08);
++ /* start the watchdog with 1M clk src and reset whole chip */
++ __raw_writel(0x33, AST_WDT_BASE + 0x0c);
++ printf("Watchdog: %us\n", CONFIG_ASPEED_WATCHDOG_TIMEOUT);
++#endif
++}
++
+ int misc_init_r(void)
+ {
+ unsigned int reg, reg1, revision, chip_id, lpc_plus;
+@@ -290,6 +307,8 @@ int misc_init_r(void)
+ if (getenv ("eeprom") == NULL) {
+ setenv ("eeprom", "y");
+ }
++
++ watchdog_init();
+ }
+
+ #ifdef CONFIG_PCI
+@@ -302,3 +321,15 @@ void pci_init_board(void)
+ aspeed_init_pci(&hose);
+ }
+ #endif
++
++int board_eth_init(bd_t *bis)
++{
++ int ret = -1;
++#if defined(CONFIG_ASPEEDNIC)
++ ret = aspeednic_initialize(bis);
++#else
++ printf("No ETH, ");
++#endif
++
++ return ret;
++}
+diff --git a/board/aspeed/ast2400/config.mk b/board/aspeed/ast2400/config.mk
+index 24ca09b..eddc3bf 100755
+--- a/board/aspeed/ast2400/config.mk
++++ b/board/aspeed/ast2400/config.mk
+@@ -9,10 +9,5 @@
+ # MA 02111-1307 USA
+ #
+
+-# ROM version
+-#TEXT_BASE = 0xBFC00000
+-
+-# RAM version
+-TEXT_BASE = 0x40500000
+-#TEXT_BASE = 0x00000000
+-#TEXT_BASE = 0x00400000
++# SPI flash is mapped to 0x00000000 initially
++CONFIG_SYS_TEXT_BASE = 0x00000000
+diff --git a/board/aspeed/ast2400/flash_spi.c b/board/aspeed/ast2400/flash_spi.c
+index ad89254..339e531 100755
+--- a/board/aspeed/ast2400/flash_spi.c
++++ b/board/aspeed/ast2400/flash_spi.c
+@@ -23,7 +23,7 @@
+ */
+
+ /* The DEBUG define must be before common to enable debugging */
+-/* #define DEBUG */
++/* #define DEBUG */
+
+ #include <common.h>
+ #include <asm/processor.h>
+@@ -68,6 +68,7 @@ flash_info_t flash_info[CONFIG_SYS_MAX_FLASH_BANKS]; /* FLASH chips info */
+ /* Support Flash ID */
+ #define STM25P64 0x172020
+ #define STM25P128 0x182020
++#define N25Q128 0x18ba20
+ #define N25Q256 0x19ba20
+ #define N25Q512 0x20ba20
+ #define S25FL064A 0x160201
+@@ -581,7 +582,7 @@ static ulong flash_get_size (ulong base, int banknum)
+ ulID = ((ulong)ch[0]) | ((ulong)ch[1] << 8) | ((ulong)ch[2] << 16) ;
+ info->flash_id = ulID;
+
+- //printf("SPI Flash ID: %x \n", ulID);
++ printf("SPI Flash ID: %x \n", ulID);
+
+ /* init default */
+ info->iomode = IOMODEx1;
+@@ -617,6 +618,19 @@ static ulong flash_get_size (ulong base, int banknum)
+ ReadClk = 50;
+ break;
+
++ case N25Q128:
++ info->sector_count = 256;
++ info->size = 0x1000000;
++ erase_region_size = 0x10000;
++ info->readcmd = 0x0b;
++ info->dualport = 0;
++ info->dummybyte = 1;
++ info->buffersize = 256;
++ WriteClk = 50;
++ EraseClk = 20;
++ ReadClk = 50;
++ break;
++
+ case N25Q256:
+ info->sector_count = 256;
+ info->size = 0x1000000;
+@@ -1051,8 +1065,7 @@ AST2300 A0 SPI can't run faster than 50Mhz
+ } /* JDEC */
+ }
+
+- debug ("erase_region_count = %d erase_region_size = %d\n",
+- erase_region_count, erase_region_size);
++ debug ("erase_region_size = %d\n", erase_region_size);
+
+ sector = base;
+ for (j = 0; j < info->sector_count; j++) {
+diff --git a/board/aspeed/ast2400/platform.S b/board/aspeed/ast2400/platform.S
+index 27e8f26..dd94da0 100644
+--- a/board/aspeed/ast2400/platform.S
++++ b/board/aspeed/ast2400/platform.S
+@@ -334,7 +334,11 @@ set_MPLL:
+ str r1, [r0]
+
+ /* Debug - UART console message */
+- ldr r0, =0x1e78400c
++ ldr r0, =0x1e6e2080
++ ldr r1, =0xFFFF0000 @ enable UART3 and UART4
++ str r1, [r0]
++
++ ldr r0, =CONFIG_ASPEED_COM_LCR
+ mov r1, #0x83
+ str r1, [r0]
+
+@@ -342,28 +346,38 @@ set_MPLL:
+ ldr r2, [r0]
+ mov r2, r2, lsr #12
+ tst r2, #0x01
+- ldr r0, =0x1e784000
++ ldr r0, =CONFIG_ASPEED_COM
++#if CONFIG_BAUDRATE == 115200
+ moveq r1, #0x0D @ Baudrate 115200
+ movne r1, #0x01 @ Baudrate 115200, div13
+-#if defined(CONFIG_DRAM_UART_38400)
++#endif
++#if CONFIG_BAUDRATE == 57600
++ moveq r1, #0x1A @ Baudrate 57600
++ movne r1, #0x02 @ Baudrate 57600, div13
++#endif
++#if CONFIG_BAUDRATE == 38400
+ moveq r1, #0x27 @ Baudrate 38400
+ movne r1, #0x03 @ Baudrate 38400 , div13
+ #endif
++#if CONFIG_BAUDRATE == 9600
++ moveq r1, #0x9c @ Baudrate 9600
++ movne r1, #0x0C @ Baudrate 9600 , div13
++#endif
+ str r1, [r0]
+
+- ldr r0, =0x1e784004
++ ldr r0, =CONFIG_ASPEED_COM_IER
+ mov r1, #0x00
+ str r1, [r0]
+
+- ldr r0, =0x1e78400c
++ ldr r0, =CONFIG_ASPEED_COM_LCR
+ mov r1, #0x03
+ str r1, [r0]
+
+- ldr r0, =0x1e784008
++ ldr r0, =CONFIG_ASPEED_COM_IIR
+ mov r1, #0x07
+ str r1, [r0]
+
+- ldr r0, =0x1e784000
++ ldr r0, =CONFIG_ASPEED_COM
+ mov r1, #0x0D @ '\r'
+ str r1, [r0]
+ mov r1, #0x0A @ '\n'
+@@ -575,7 +589,7 @@ delay_2:
+ ******************************************************************************/
+ ddr3_init:
+ /* Debug - UART console message */
+- ldr r0, =0x1e784000
++ ldr r0, =CONFIG_ASPEED_COM
+ mov r1, #0x33 @ '3'
+ str r1, [r0]
+ mov r1, #0x0D @ '\r'
+@@ -764,7 +778,7 @@ delay3_4:
+ ******************************************************************************/
+ ddr2_init:
+ /* Debug - UART console message */
+- ldr r0, =0x1e784000
++ ldr r0, =CONFIG_ASPEED_COM
+ mov r1, #0x32 @ '2'
+ str r1, [r0]
+ mov r1, #0x0D @ '\r'
+@@ -1416,7 +1430,7 @@ init_sram_start3:
+ *****************************************************************************/
+ CBR0_START:
+ /* Debug - UART console message */
+- ldr r0, =0x1e784000
++ ldr r0, =CONFIG_ASPEED_COM
+ mov r1, #0x43 @ 'C'
+ str r1, [r0]
+ mov r1, #0x42 @ 'B'
+@@ -1454,7 +1468,7 @@ cbr0_next_dqidly:
+ bgt CBR0_END
+
+ /* Debug - UART console message */
+- ldr r0, =0x1e784000
++ ldr r0, =CONFIG_ASPEED_COM
+ and r1, r8, #0x07
+ add r1, r1, #0x30 @ '0-7'
+ str r1, [r0]
+@@ -1776,7 +1790,7 @@ delay_5:
+ *****************************************************************************/
+ CBR1_START:
+ /* Debug - UART console message */
+- ldr r0, =0x1e784000
++ ldr r0, =CONFIG_ASPEED_COM
+ mov r1, #0x0D @ '\r'
+ str r1, [r0]
+ mov r1, #0x0A @ '\n'
+@@ -2057,7 +2071,7 @@ cbr1_set_result_end:
+
+ CBR3_START:
+ /* Debug - UART console message */
+- ldr r0, =0x1e784000
++ ldr r0, =CONFIG_ASPEED_COM
+ mov r1, #0x33 @ '3'
+ str r1, [r0]
+ /* Debug - UART console message */
+@@ -2276,7 +2290,7 @@ CBR3_END:
+ *****************************************************************************/
+ CBR4_START:
+ /* Debug - UART console message */
+- ldr r0, =0x1e784000
++ ldr r0, =CONFIG_ASPEED_COM
+ mov r1, #0x34 @ '4'
+ str r1, [r0]
+ /* Debug - UART console message */
+@@ -2556,7 +2570,7 @@ set_scratch:
+ str r1, [r0]
+
+ /* Debug - UART console message */
+- ldr r0, =0x1e784000
++ ldr r0, =CONFIG_ASPEED_COM
+ mov r1, #0x44 @ 'D'
+ str r1, [r0]
+ mov r1, #0x6F @ 'o'
+@@ -2724,11 +2738,13 @@ ECC_Init_Flag:
+ orr r1, r1, #0x08
+ str r1, [r0]
+
++#ifndef CONFIG_ASPEED_ENABLE_JTAG
+ ldr r0, =0x1e6e2004
+ ldr r1, [r0]
+ ldr r2, =0xFFBFFFFF @ Enable JTAG Master, solve ARM stucked by JTAG issue
+ and r1, r1, r2
+ str r1, [r0]
++#endif
+
+ ldr r0, =0x1e6e2048 @ Set MAC interface delay timing
+ ldr r1, =0x2255
+diff --git a/board/aspeed/ast2400/u-boot.lds b/board/aspeed/ast2400/u-boot.lds
+deleted file mode 100755
+index ff0fe22..0000000
+--- a/board/aspeed/ast2400/u-boot.lds
++++ /dev/null
+@@ -1,56 +0,0 @@
+-/*
+- * (C) Copyright 2004
+- * Wolfgang Denk, DENX Software Engineering, <wg@denx.de>
+- *
+- * See file CREDITS for list of people who contributed to this
+- * project.
+- *
+- * This program is free software; you can redistribute it and/or
+- * modify it under the terms of the GNU General Public License as
+- * published by the Free Software Foundation; either version 2 of
+- * the License, or (at your option) any later version.
+- *
+- * This program is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+- * GNU General Public License for more details.
+- *
+- * You should have received a copy of the GNU General Public License
+- * along with this program; if not, write to the Free Software
+- * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+- * MA 02111-1307 USA
+- */
+-
+-OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm")
+-/*OUTPUT_FORMAT("elf32-arm", "elf32-arm", "elf32-arm")*/
+-OUTPUT_ARCH(arm)
+-ENTRY(_start)
+-SECTIONS
+-{
+- . = 0x00000000;
+-
+- . = ALIGN(4);
+- .text :
+- {
+- cpu/arm926ejs/start.o (.text)
+- *(.text)
+- }
+-
+- . = ALIGN(4);
+- .rodata : { *(.rodata) }
+-
+- . = ALIGN(4);
+- .data : { *(.data) }
+-
+- . = ALIGN(4);
+- .got : { *(.got) }
+-
+- __u_boot_cmd_start = .;
+- .u_boot_cmd : { *(.u_boot_cmd) }
+- __u_boot_cmd_end = .;
+-
+- . = ALIGN(4);
+- __bss_start = .;
+- .bss : { *(.bss) }
+- _end = .;
+-}
+diff --git a/boards.cfg b/boards.cfg
+index 674896b..ce6bff1 100644
+--- a/boards.cfg
++++ b/boards.cfg
+@@ -72,7 +72,7 @@ mini2440 arm arm920t mini2440 friendl
+ VCMA9 arm arm920t vcma9 mpl s3c24x0
+ smdk2410 arm arm920t - samsung s3c24x0
+ omap1510inn arm arm925t - ti
+-ast2400 arm arm926ejs ast2400 aspeed aspeed
++wedge arm arm926ejs ast2400 aspeed aspeed
+ integratorap_cm926ejs arm arm926ejs integrator armltd - integratorap:CM926EJ_S
+ integratorcp_cm926ejs arm arm926ejs integrator armltd - integratorcp:CM924EJ_S
+ aspenite arm arm926ejs - Marvell armada100
+diff --git a/common/cmd_slt.c b/common/cmd_slt.c
+index 9763692..6296416 100644
+--- a/common/cmd_slt.c
++++ b/common/cmd_slt.c
+@@ -9,6 +9,7 @@
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
++#include <common.h>
+ #include <command.h>
+
+ extern int pll_function(int argc, char *argv[]);
+diff --git a/common/env_common.c b/common/env_common.c
+index 906b41f..f5af537 100644
+--- a/common/env_common.c
++++ b/common/env_common.c
+@@ -203,6 +203,9 @@ void env_relocate(void)
+ #else
+ bootstage_error(BOOTSTAGE_ID_NET_CHECKSUM);
+ set_default_env("!bad CRC");
++#ifdef CONFIG_ASPEED_WRITE_DEFAULT_ENV
++ saveenv();
++#endif
+ #endif
+ } else {
+ env_relocate_spec();
+diff --git a/common/image.c b/common/image.c
+index f5ad097..2fc071b 100644
+--- a/common/image.c
++++ b/common/image.c
+@@ -902,6 +902,11 @@ int boot_get_ramdisk(int argc, char * const argv[], bootm_headers_t *images,
+ rd_data = image_get_data(rd_hdr);
+ rd_len = image_get_data_size(rd_hdr);
+ rd_load = image_get_load(rd_hdr);
++#ifdef CONFIG_ASPEED
++ /* Need to copy the initrd into RAM */
++ memmove_wd((void *)rd_load, (void *)rd_data, rd_len, CHUNKSZ);
++ rd_data = rd_load;
++#endif
+ break;
+ #if defined(CONFIG_FIT)
+ case IMAGE_FORMAT_FIT:
+diff --git a/drivers/net/aspeednic.c b/drivers/net/aspeednic.c
+index 6b1ce05..d75ef67 100644
+--- a/drivers/net/aspeednic.c
++++ b/drivers/net/aspeednic.c
+@@ -16,6 +16,7 @@
+ #include <malloc.h>
+ #include <net.h>
+ #include <pci.h>
++#include <linux/mii.h>
+
+
+ /*
+@@ -53,7 +54,6 @@
+ #define MAC1_MDC (1 << 30)
+ #define MAC1_PHY_LINK (1 << 0)
+ #define MAC2_MDC_MDIO (1 << 2)
+-#define MAC1_PHY_LINK (1 << 0)
+ #define MAC2_PHY_LINK (1 << 1)
+ #else
+ #define MAC2_MDC_MDIO (1 << 20)
+@@ -69,6 +69,9 @@ unsigned int aspeednic_iobase[CONFIG_ASPEED_MAC_NUMBER] = {
+ 0x1E660000, 0x1E680000};
+ #endif
+
++/* PHY address */
++static u8 g_phy_addr = 0;
++
+ #undef DEBUG_SROM
+ #undef DEBUG_SROM2
+
+@@ -249,6 +252,7 @@ struct de4x5_desc {
+ #define PHYID_RTL8201EL 0x001cc810
+ #define PHYID_RTL8211 0x001cc910
+ #define PHYID_BCM54612E 0x03625E6A
++#define PHYID_BCM54616S 0x03625D12
+
+ //NCSI define & structure
+ //NC-SI Command Packet
+@@ -410,6 +414,12 @@ static void aspeednic_halt(struct eth_device* dev);
+ static void set_mac_address (struct eth_device* dev, bd_t* bis);
+ static void phy_write_register (struct eth_device* dev, u8 PHY_Register, u8 PHY_Address, u16 PHY_Data);
+ static u16 phy_read_register (struct eth_device* dev, u8 PHY_Register, u8 PHY_Address);
++#if defined(CONFIG_MII) || defined(CONFIG_CMD_MII)
++static int faraday_mdio_read(const char *devname, uint8_t addr, uint8_t reg,
++ uint16_t *value);
++static int faraday_mdio_write(const char *devname, uint8_t addr, uint8_t reg,
++ uint16_t value);
++#endif
+ static void set_mac_control_register(struct eth_device* dev);
+
+ #if defined(CONFIG_E500)
+@@ -456,7 +466,7 @@ void NCSI_Struct_Initialize(void)
+
+ int aspeednic_initialize(bd_t *bis)
+ {
+- int card_number = 0;
++ int card_number = CONFIG_ASPEED_MAC_CONFIG - 1;
+ unsigned int iobase, SCURegister;
+ struct eth_device* dev;
+
+@@ -538,7 +548,7 @@ int aspeednic_initialize(bd_t *bis)
+
+ dev->iobase = iobase;
+
+- if (CONFIG_MAC1_PHY_SETTING >= 1) {
++ if (CONFIG_ASPEED_MAC_PHY_SETTING >= 1) {
+ //NCSI Struct Initialize
+ NCSI_Struct_Initialize();
+ }
+@@ -556,20 +566,22 @@ int aspeednic_initialize(bd_t *bis)
+ dev->recv = aspeednic_recv;
+
+ /* Ensure we're not sleeping. */
+- if (CONFIG_MAC1_PHY_SETTING >= 1) {
++ if (CONFIG_ASPEED_MAC_PHY_SETTING >= 1) {
+ udelay(2000000); //2.0 sec
+ }
+ else {
+ udelay(10 * 1000);
+ }
+
+-
+ dev->init(dev, bis);
+
+ eth_register(dev);
+
++#if defined(CONFIG_MII) || defined(CONFIG_CMD_MII)
++ miiphy_register(dev->name, faraday_mdio_read, faraday_mdio_write);
++#endif
+
+- return card_number;
++ return 1;
+ }
+
+ void Calculate_Checksum(unsigned char *buffer_base, int Length)
+@@ -1114,11 +1126,37 @@ void Set_Link (struct eth_device* dev)
+ Retry = 0;
+ }
+
++static void aspeednic_probe_phy(struct eth_device *dev)
++{
++ u8 phy_addr;
++ u16 phy_id;
++
++ /* assume it as 0 */
++ g_phy_addr = 0;
++
++ /* Check if the PHY is up to snuff..., max phy addr is 0x1f */
++ for (phy_addr = 0; phy_addr <= 0x1f; phy_addr++) {
++ phy_id = phy_read_register(dev, MII_PHYSID1, phy_addr);
++ /*
++ * When it is unable to found PHY,
++ * the interface usually return 0xffff or 0x0000
++ */
++ if (phy_id != 0xffff && phy_id != 0x0) {
++ g_phy_addr = phy_addr;
++ break;
++ }
++ }
++ printf("%s: PHY at 0x%02x\n", dev->name, phy_addr);
++}
++
+ static int aspeednic_init(struct eth_device* dev, bd_t* bis)
+ {
+ unsigned long i, Package_Found = 0, Channel_Found = 0, Re_Send = 0, Link_Status;
+
+ RESET_DE4X5(dev);
++
++ aspeednic_probe_phy(dev);
++
+ set_mac_address (dev, bis);
+ set_mac_control_register (dev);
+
+@@ -1149,7 +1187,7 @@ static int aspeednic_init(struct eth_device* dev, bd_t* bis)
+ tx_new = 0;
+ rx_new = 0;
+
+- if (CONFIG_MAC1_PHY_SETTING >= 1) {
++ if (CONFIG_ASPEED_MAC_PHY_SETTING >= 1) {
+ //NCSI Start
+ //DeSelect Package/ Select Package
+ for (i = 0; i < 4; i++) {
+@@ -1313,58 +1351,23 @@ static void aspeednic_halt(struct eth_device* dev)
+
+ static void set_mac_address (struct eth_device* dev, bd_t* bis)
+ {
+- unsigned char mac_address[6]; // 6 bytes mac address
+- unsigned char ethaddress[20]; // string for setenv function
+- char *s;
+- int i, env; // env variable 0: eeprom, 1: environment parameters
+-
+- s = getenv ("eeprom");
+- env = (s && (*s == 'y')) ? 0 : 1;
+-
+- if (env == 0) {
+- env = 1;
+- eeprom_init ();
+- eeprom_read (0xA0, 0, mac_address, 6);
+-
+- for (i = 0; i < 6; i++) {
+- if (mac_address[i] != 0xFF) {
+- env = 0; //Suppose not all 0xFF is valid
+- }
+- }
++ if (!eth_getenv_enetaddr_by_index("eth", 0, dev->enetaddr)) {
++ eth_random_enetaddr(dev->enetaddr);
+ }
+
+- if (env == 0) { // EEPROM
+- sprintf (ethaddress, "%02X:%02X:%02X:%02X:%02X:%02X", mac_address[0], mac_address[1], mac_address[2], mac_address[3], mac_address[4], mac_address[5]);
+- setenv ("ethaddr", ethaddress);
+- OUTL(dev, ((mac_address[2] << 24) | (mac_address[3] << 16) | (mac_address[4] << 8) | mac_address[5]), MAC_LADR_REG);
+- OUTL(dev, ((mac_address[0] << 8) | mac_address[1]), MAC_MADR_REG);
+- if (CONFIG_MAC1_PHY_SETTING >= 1) {
+- for (i = 0; i < 6; i++) {
+- NCSI_Request.SA[i] = mac_address[i];
+- }
+- }
+- }
+- else { // Environment Parameters
+- OUTL(dev, ((bis->bi_enetaddr[2] << 24) | (bis->bi_enetaddr[3] << 16) | (bis->bi_enetaddr[4] << 8) | bis->bi_enetaddr[5]), MAC_LADR_REG);
+- OUTL(dev, ((bis->bi_enetaddr[0] << 8) | bis->bi_enetaddr[1]), MAC_MADR_REG);
+- if (CONFIG_MAC1_PHY_SETTING >= 1) {
+- for (i = 0; i < 6; i++) {
+- NCSI_Request.SA[i] = bis->bi_enetaddr[i];
+- }
+- }
++ OUTL(dev, ((dev->enetaddr[2] << 24) | (dev->enetaddr[3] << 16)
++ | (dev->enetaddr[4] << 8) | dev->enetaddr[5]), MAC_LADR_REG);
++ OUTL(dev, ((dev->enetaddr[0] << 8) | dev->enetaddr[1]), MAC_MADR_REG);
++ if (CONFIG_ASPEED_MAC_PHY_SETTING >= 1) {
++ memcpy(NCSI_Request.SA, dev->enetaddr, 6);
+ }
+-
+ }
+
+-
+ static u16 phy_read_register (struct eth_device* dev, u8 PHY_Register, u8 PHY_Address)
+ {
+ u32 Data, Status = 0, Loop_Count = 0, PHY_Ready = 1;
+ u16 Return_Data;
+
+-#ifdef REALTEK_PHY_SUPPORT
+- PHY_Address = 0x01;
+-#endif
+ //20us * 100 = 2ms > (1 / 2.5Mhz) * 0x34
+ OUTL(dev, (PHY_Register << 21) + (PHY_Address << 16) + MIIRD + MDC_CYCTHR, PHYCR_REG);
+ do {
+@@ -1378,7 +1381,6 @@ static u16 phy_read_register (struct eth_device* dev, u8 PHY_Register, u8 PHY_Ad
+ } while (Status == MIIRD);
+
+ if (PHY_Ready == 0) {
+- printf ("PHY NOT REDAY ");
+ return 0;
+ }
+ Data = INL (dev, PHYDATA_REG);
+@@ -1392,9 +1394,6 @@ static void phy_write_register (struct eth_device* dev, u8 PHY_Register, u8 PHY_
+ {
+ u32 Status = 0, Loop_Count = 0, PHY_Ready = 1;
+
+-#ifdef REALTEK_PHY_SUPPORT
+- PHY_Address = 0x01;
+-#endif
+ //20us * 100 = 2ms > (1 / 2.5Mhz) * 0x34
+ OUTL(dev, PHY_Data, PHYDATA_REG);
+ OUTL(dev, (PHY_Register << 21) + (PHY_Address << 16) + MIIWR + MDC_CYCTHR, PHYCR_REG);
+@@ -1407,31 +1406,66 @@ static void phy_write_register (struct eth_device* dev, u8 PHY_Register, u8 PHY_
+ break;
+ }
+ } while (Status == MIIWR);
+- if (PHY_Ready == 0) {
+- printf ("PHY NOT REDAY ");
++}
++
++#if defined(CONFIG_MII) || defined(CONFIG_CMD_MII)
++
++static int faraday_mdio_read(
++ const char *devname, uint8_t addr, uint8_t reg, uint16_t *value)
++{
++ int ret = 0;
++ struct eth_device *dev;
++
++ dev = eth_get_dev_by_name(devname);
++ if (dev == NULL) {
++ printf("%s: no such device\n", devname);
++ ret = -1;
++ } else {
++ *value = phy_read_register(dev, reg, addr);
++ }
++
++ return ret;
++}
++
++static int faraday_mdio_write(
++ const char *devname, uint8_t addr, uint8_t reg, uint16_t value)
++{
++ int ret = 0;
++ struct eth_device *dev;
++
++ dev = eth_get_dev_by_name(devname);
++ if (dev == NULL) {
++ printf("%s: no such device\n", devname);
++ ret = -1;
++ } else {
++ phy_write_register(dev, reg, addr, value);
+ }
++
++ return ret;
+ }
+
++#endif /* #if defined(CONFIG_MII) || defined(CONFIG_CMD_MII) */
++
+ static void set_mac_control_register (struct eth_device* dev)
+ {
+ unsigned long MAC_CR_Register = 0;
+- unsigned long Loop_Count = 0, PHY_Ready = 1, Chip_ID;
++ unsigned int Loop_Count = 0, PHY_Ready = 1, Chip_ID;
+ u16 PHY_Status, PHY_Speed, PHY_Duplex, Resolved_Status = 0, Advertise, Link_Partner;
+
+- if (CONFIG_MAC1_PHY_SETTING >= 1) {
++ if (CONFIG_ASPEED_MAC_PHY_SETTING >= 1) {
+ MAC_CR_Register = SPEED_100M_MODE_bit | RX_BROADPKT_bit | FULLDUP_bit | RXMAC_EN_bit | RXDMA_EN_bit | TXMAC_EN_bit | TXDMA_EN_bit | CRC_APD_bit;
+ }
+ else {
+ MAC_CR_Register = SPEED_100M_MODE_bit | FULLDUP_bit | RXMAC_EN_bit | RXDMA_EN_bit | TXMAC_EN_bit | TXDMA_EN_bit | CRC_APD_bit;
+ }
+
+- if (CONFIG_MAC1_PHY_SETTING != 2) {
+- Chip_ID = ((phy_read_register (dev, 0x02, 0)) << 16);
+- Chip_ID |= (phy_read_register (dev, 0x03, 0) & 0xffff);
++ if (CONFIG_ASPEED_MAC_PHY_SETTING != 2) {
++ Chip_ID = ((phy_read_register (dev, 0x02, g_phy_addr)) << 16);
++ Chip_ID |= (phy_read_register (dev, 0x03, g_phy_addr) & 0xffff);
+ if (((Chip_ID & PHYID_VENDOR_MASK) == PHYID_VENDOR_BROADCOM) ||
+ ((Chip_ID & PHYID_VENDOR_MODEL_MASK) == PHYID_RTL8201EL)) {
+- Advertise = phy_read_register (dev, 0x04, 0);
+- Link_Partner = phy_read_register (dev, 0x05, 0);
++ Advertise = phy_read_register (dev, 0x04, g_phy_addr);
++ Link_Partner = phy_read_register (dev, 0x05, g_phy_addr);
+ Advertise = (Advertise & PHY_SPEED_DUPLEX_MASK);
+ Link_Partner = (Link_Partner & PHY_SPEED_DUPLEX_MASK);
+ if ((Advertise & Link_Partner) & PHY_100M_DUPLEX) {
+@@ -1456,7 +1490,8 @@ static void set_mac_control_register (struct eth_device* dev)
+ //Max waiting time = (20 + 2)ms * 250(PHY_LOOP) = 5.5s
+ do {
+ udelay (20000);
+- Resolved_Status = (phy_read_register (dev, 0x11, 0) & RESOLVED_BIT);
++ Resolved_Status = (phy_read_register (dev, 0x11, g_phy_addr)
++ & RESOLVED_BIT);
+ Loop_Count++;
+ if (Loop_Count >= PHY_LOOP) {
+ PHY_Ready = 0;
+@@ -1466,7 +1501,7 @@ static void set_mac_control_register (struct eth_device* dev)
+ } while (Resolved_Status != RESOLVED_BIT);
+
+ if (PHY_Ready == 1) {
+- PHY_Status = phy_read_register (dev, 0x11, 0);
++ PHY_Status = phy_read_register (dev, 0x11, g_phy_addr);
+ PHY_Speed = (PHY_Status & PHY_SPEED_MASK) >> 14;
+ PHY_Duplex = (PHY_Status & PHY_DUPLEX_MASK) >> 13;
+
+@@ -1485,40 +1520,54 @@ static void set_mac_control_register (struct eth_device* dev)
+ }
+ //LED Control
+ // if (Chip_ID == 0x1C) {
+-// PHY_Status = phy_read_register (dev, 0x18, 0);
+-// phy_write_register (dev, 0x18, 0, (PHY_Status | 0x09));
++// PHY_Status = phy_read_register (dev, 0x18, g_phy_addr);
++// phy_write_register (dev, 0x18, g_phy_addr, (PHY_Status | 0x09));
+ // }
+ //LED Control D[0], D[6]
+ // if (Chip_ID == 0x141) {
+-// PHY_Status = phy_read_register (dev, 0x18, 0);
+-// phy_write_register (dev, 0x18, 0, ((PHY_Status & ~(0x41)) | 0x01));
++// PHY_Status = phy_read_register (dev, 0x18, g_phy_addr);
++// phy_write_register (dev, 0x18, g_phy_addr, ((PHY_Status & ~(0x41)) | 0x01));
+ // }
+ }
+- else if (Chip_ID == PHYID_BCM54612E ) {
+- phy_write_register ( dev, 0x1C, 1, 0x8C00 ); // Disable GTXCLK Clock Delay Enable
+- phy_write_register ( dev, 0x18, 1, 0xF0E7 ); // Disable RGMII RXD to RXC Skew
+-
+- Advertise = phy_read_register (dev, 0x04, 1);
+- Link_Partner = phy_read_register (dev, 0x05, 1);
+- Advertise = (Advertise & PHY_SPEED_DUPLEX_MASK);
+- Link_Partner = (Link_Partner & PHY_SPEED_DUPLEX_MASK);
+- if ((Advertise & Link_Partner) & PHY_100M_DUPLEX) {
+- MAC_CR_Register |= SPEED_100M_MODE_bit;
+- MAC_CR_Register |= FULLDUP_bit;
++ else if (Chip_ID == PHYID_BCM54612E || Chip_ID == PHYID_BCM54616S) {
++ // Disable GTXCLK Clock Delay Enable
++ phy_write_register( dev, 0x1C, g_phy_addr, 0x8C00);
++ // Disable RGMII RXD to RXC Skew
++ phy_write_register( dev, 0x18, g_phy_addr, 0xF0E7);
++ // First Switch shadow register selector
++ phy_write_register(dev, 0x1C, g_phy_addr, 0x2000);
++ PHY_Status = phy_read_register(dev, 0x1C, g_phy_addr);
++ PHY_Duplex = (PHY_Status & 0x0080);
++ switch (PHY_Status & 0x0018) {
++ case 0x0000:
++ PHY_Speed = SPEED_1000M;
++ break;
++ case 0x0008:
++ PHY_Speed = SPEED_100M;
++ break;
++ case 0x0010:
++ PHY_Speed = SPEED_10M;
++ break;
++ default:
++ PHY_Speed = SPEED_100M;
++ break;
+ }
+- else if ((Advertise & Link_Partner) & PHY_100M_HALF) {
+- MAC_CR_Register |= SPEED_100M_MODE_bit;
+- MAC_CR_Register &= ~FULLDUP_bit;
++ if (PHY_Speed == SPEED_1000M) {
++ MAC_CR_Register |= GMAC_MODE_bit;
++ } else {
++ MAC_CR_Register &= ~GMAC_MODE_bit;
++ if (PHY_Speed == SPEED_100M) {
++ MAC_CR_Register |= SPEED_100M_MODE_bit;
++ } else {
++ MAC_CR_Register &= ~SPEED_100M_MODE_bit;
++ }
+ }
+- else if ((Advertise & Link_Partner) & PHY_10M_DUPLEX) {
+- MAC_CR_Register &= ~SPEED_100M_MODE_bit;
++ if (PHY_Duplex) {
+ MAC_CR_Register |= FULLDUP_bit;
+- }
+- else if ((Advertise & Link_Partner) & PHY_10M_HALF) {
+- MAC_CR_Register &= ~SPEED_100M_MODE_bit;
++ } else {
+ MAC_CR_Register &= ~FULLDUP_bit;
+ }
+- }else {
++ } else {
+ printf("Unknow Chip_ID %x\n",Chip_ID);
+ }
+ }
+diff --git a/include/configs/wedge.h b/include/configs/wedge.h
+new file mode 100644
+index 0000000..6bb7639
+--- /dev/null
++++ b/include/configs/wedge.h
+@@ -0,0 +1,350 @@
++/*
++ * Copyright 2004-present Facebook. All Rights Reserved.
++ *
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License as
++ * published by the Free Software Foundation; either version 2 of
++ * the License, or (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
++ * MA 02111-1307 USA
++ */
++
++#ifndef __CONFIG_H
++#define __CONFIG_H
++
++/* Uncommit the following line to enable JTAG in u-boot */
++//#define CONFIG_ASPEED_ENABLE_JTAG
++
++/*
++ * High Level Configuration Options
++ * (easy to change)
++ */
++//#define CONFIG_INIT_CRITICAL /* define for U-BOOT 1.1.1 */
++#undef CONFIG_INIT_CRITICAL /* undef for U-BOOT 1.1.4 */
++//#define CONFIG_FPGA_ASPEED 1
++#define CONFIG_ARM926EJS 1 /* This is an arm926ejs CPU */
++#define CONFIG_ASPEED 1
++#define CONFIG_AST2400 1
++//#define CONFIG_AST1070 1
++//#define CONFIG_SYS_FLASH_CFI /* CONFIG_FLASH_CFI, CONFIG_FLASH_SPI is exclusive*/
++#define CONFIG_FLASH_SPI
++//#define CONFIG_2SPIFLASH /* Boot SPI: CS2, 2nd SPI: CS0 */
++#undef CONFIG_2SPIFLASH
++#undef CONFIG_ASPEED_SLT
++#define CONFIG_FLASH_AST2300
++//#define CONFIG_FLASH_AST2300_DMA
++//#define CONFIG_FLASH_SPIx2_Dummy
++//#define CONFIG_FLASH_SPIx4_Dummy
++#define CONFIG_CRT_DISPLAY 1 /* undef if not support CRT */
++
++//#define CONFIG_USE_IRQ /* we don't need IRQ/FIQ stuff */
++#define CONFIG_MISC_INIT_R
++
++/*
++ * DRAM Config
++ *
++ * 1. DRAM Size //
++ * CONFIG_DRAM_512MBIT // 512M bit
++ * CONFIG_DRAM_1GBIT // 1G bit (default)
++ * CONFIG_DRAM_2GBIT // 2G bit
++ * CONFIG_DRAM_4GBIT // 4G bit
++ * 2. DRAM Speed //
++ * CONFIG_DRAM_336 // 336MHz (DDR-667)
++ * CONFIG_DRAM_408 // 408MHz (DDR-800) (default)
++ * 3. VGA Mode
++ * CONFIG_CRT_DISPLAY // define to disable VGA function
++ * 4. ECC Function enable
++ * CONFIG_DRAM_ECC // define to enable ECC function
++ * 5. UART Debug Message
++ * CONFIG_DRAM_UART_OUT // enable output message at UART5
++ * CONFIG_DRAM_UART_38400 // set the UART baud rate to 38400, default is 115200
++ */
++
++//1. DRAM Size
++//#define CONFIG_DRAM_512MBIT
++#define CONFIG_DRAM_1GBIT
++//#define CONFIG_DRAM_2GBIT
++//#define CONFIG_DRAM_4GBIT
++//2. DRAM Speed
++//#define CONFIG_DRAM_336
++#define CONFIG_DRAM_408
++//3. VGA Mode
++//#define CONFIG_CRT_DISPLAY
++//4. ECC Function enable
++//#define CONFIG_DRAM_ECC
++//5. UART Debug Message
++#define CONFIG_DRAM_UART_OUT
++//#define CONFIG_DRAM_UART_38400
++
++
++
++/*
++ * Environment Config
++ */
++#define CONFIG_CMDLINE_TAG 1 /* enable passing of ATAGs */
++#define CONFIG_SETUP_MEMORY_TAGS 1
++#define CONFIG_INITRD_TAG 1
++#define CONFIG_BOOTARGS "debug console=ttyS2,9600n8 root=/dev/ram rw"
++#define CONFIG_UPDATE "tftp 40800000 ast2400.scr; so 40800000'"
++
++#define CONFIG_BOOTDELAY 3 /* autoboot after 3 seconds */
++#define CONFIG_AUTOBOOT_KEYED
++#define CONFIG_AUTOBOOT_PROMPT \
++ "autoboot in %d seconds (stop with 'Delete' key)...\n", bootdelay
++#define CONFIG_AUTOBOOT_STOP_STR "\x1b\x5b\x33\x7e" /* 'Delete', ESC[3~ */
++#define CONFIG_ZERO_BOOTDELAY_CHECK
++
++#ifdef CONFIG_FLASH_AST2300
++#define CONFIG_BOOTCOMMAND "bootm 20080000 20300000"
++#else
++#ifdef CONFIG_SYS_FLASH_CFI
++#define CONFIG_BOOTCOMMAND "bootm 10080000 10300000"
++#else
++#define CONFIG_BOOTCOMMAND "bootm 14080000 14300000"
++#endif
++#endif
++#define CONFIG_BOOTFILE "all.bin"
++#define CONFIG_ENV_OVERWRITE
++
++/*
++ * Command line configuration.
++ */
++#include <config_cmd_default.h>
++
++#define CONFIG_CMD_DFL
++#define CONFIG_CMD_ENV
++#define CONFIG_CMD_FLASH
++#define CONFIG_CMD_MII
++#define CONFIG_CMD_NET
++#define CONFIG_CMD_PING
++#define CONFIG_CMD_I2C
++#define CONFIG_CMD_EEPROM
++#define CONFIG_CMD_NETTEST
++#define CONFIG_CMD_SLT
++
++/*
++ * CPU Setting
++ */
++#define CPU_CLOCK_RATE 18000000 /* 16.5 MHz clock for the ARM core */
++
++/*
++ * Size of malloc() pool
++ */
++#define CONFIG_SYS_MALLOC_LEN (CONFIG_ENV_SIZE + 768*1024)
++#define CONFIG_SYS_GBL_DATA_SIZE 128 /* size in bytes reserved for initial data */
++
++/*
++ * Stack sizes, The stack sizes are set up in start.S using the settings below
++ */
++#define CONFIG_STACKSIZE (128*1024) /* regular stack */
++#define CONFIG_STACKSIZE_IRQ (4*1024) /* IRQ stack */
++#define CONFIG_STACKSIZE_FIQ (4*1024) /* FIQ stack */
++
++/*
++ * Memory Configuration
++ */
++#define CONFIG_NR_DRAM_BANKS 1 /* we have 1 bank of DRAM */
++#define PHYS_SDRAM_1 0x40000000 /* SDRAM Bank #1 */
++#define PHYS_SDRAM_1_SIZE 0x10000000 /* 256 MB */
++
++#define CONFIG_SYS_SDRAM_BASE 0x40000000
++
++/*
++ * FLASH Configuration
++ */
++#ifdef CONFIG_SYS_FLASH_CFI /* NOR Flash */
++
++#ifdef CONFIG_FLASH_AST2300
++#define PHYS_FLASH_1 0x20000000 /* Flash Bank #1 */
++#else
++#define PHYS_FLASH_1 0x10000000 /* Flash Bank #1 */
++#endif
++
++#define CONFIG_SYS_FLASH_BASE PHYS_FLASH_1
++#define CONFIG_FLASH_BANKS_LIST { PHYS_FLASH_1 }
++
++#define CONFIG_SYS_MAX_FLASH_BANKS 1
++#define CONFIG_SYS_MAX_FLASH_SECT (256) /* max number of sectors on one chip */
++
++#define CONFIG_ENV_IS_IN_FLASH 1
++#define CONFIG_ENV_OFFSET 0x60000 /* environment starts here */
++#define CONFIG_ENV_SIZE 0x20000 /* Total Size of Environment Sector */
++
++#define CONFIG_SYS_FLASH_CFI_AMD_RESET
++#define CONFIG_SYS_FLASH_USE_BUFFER_WRITE
++
++#else /* SPI Flash */
++
++#ifdef CONFIG_FLASH_AST2300
++#define PHYS_FLASH_1 0x20000000 /* Flash Bank #1 */
++#else
++#define PHYS_FLASH_1 0x14000000 /* Flash Bank #1 */
++#define PHYS_FLASH_2 0x14800000 /* Flash Bank #2 */
++#define PHYS_FLASH_2_BASE 0x10000000
++#endif
++
++#ifdef CONFIG_2SPIFLASH
++#define CONFIG_SYS_FLASH_BASE PHYS_FLASH_2_BASE
++#define CONFIG_FLASH_BANKS_LIST { PHYS_FLASH_1, PHYS_FLASH_2 }
++#define CONFIG_SYS_MAX_FLASH_BANKS 2
++#define CONFIG_SYS_MAX_FLASH_SECT (1024) /* max number of sectors on one chip */
++
++#define CONFIG_ENV_IS_IN_FLASH 1
++#define CONFIG_ENV_OFFSET 0x7F0000 /* environment starts here */
++#define CONFIG_ENV_SIZE 0x010000 /* Total Size of Environment Sector */
++#else
++#define CONFIG_SYS_FLASH_BASE PHYS_FLASH_1
++#define CONFIG_FLASH_BANKS_LIST { PHYS_FLASH_1 }
++#define CONFIG_SYS_MAX_FLASH_BANKS 1
++#define CONFIG_SYS_MAX_FLASH_SECT (1024) /* max number of sectors on one chip */
++
++#define CONFIG_ENV_IS_IN_FLASH 1
++#define CONFIG_ENV_OFFSET 0x60000 /* environment starts here */
++#define CONFIG_ENV_SIZE 0x20000 /* Total Size of Environment Sector */
++#define CONFIG_ASPEED_WRITE_DEFAULT_ENV
++#endif
++
++#endif
++
++#define __LITTLE_ENDIAN 1
++
++#define CONFIG_MONITOR_BASE TEXT_BASE
++#define CONFIG_MONITOR_LEN (192 << 10)
++
++/* timeout values are in ticks */
++#define CONFIG_SYS_FLASH_ERASE_TOUT (20*CONFIG_SYS_HZ) /* Timeout for Flash Erase */
++#define CONFIG_SYS_FLASH_WRITE_TOUT (20*CONFIG_SYS_HZ) /* Timeout for Flash Write */
++
++/*
++ * Miscellaneous configurable options
++ */
++#define CONFIG_SYS_LONGHELP /* undef to save memory */
++
++#define CONFIG_SYS_PROMPT "boot# " /* Monitor Command Prompt */
++#define CONFIG_SYS_CBSIZE 256 /* Console I/O Buffer Size */
++#define CONFIG_SYS_PBSIZE (CONFIG_SYS_CBSIZE+sizeof(CONFIG_SYS_PROMPT)+16) /* Print Buffer Size */
++#define CONFIG_SYS_MAXARGS 16 /* max number of command args */
++#define CONFIG_SYS_BARGSIZE CONFIG_SYS_CBSIZE /* Boot Argument Buffer Size */
++
++#define CONFIG_SYS_MEMTEST_START 0x40000000 /* memtest works on */
++#define CONFIG_SYS_MEMTEST_END 0x44FFFFFF /* 256 MB in DRAM */
++
++#define CONFIG_SYS_LOAD_ADDR 0x43000000 /* default load address */
++
++#define CONFIG_SYS_TIMERBASE 0x1E782000 /* use timer 1 */
++#define CONFIG_SYS_HZ 1000
++#define CONFIG_ASPEED_TIMER_CLK (1*1000*1000) /* use external clk (1M) */
++
++/*
++ * Serial Configuration
++ */
++#define CONFIG_SYS_NS16550
++#define CONFIG_SYS_NS16550_SERIAL
++#define CONFIG_SYS_NS16550_MEM32
++#define CONFIG_SYS_NS16550_REG_SIZE -4
++#define CONFIG_SYS_NS16550_CLK 24000000
++#define CONFIG_SYS_NS16550_COM1 0x1e783000
++#define CONFIG_SYS_NS16550_COM2 0x1e784000
++#define CONFIG_SYS_NS16550_COM3 0x1e78e000
++#define CONFIG_SYS_LOADS_BAUD_CHANGE
++#define CONFIG_CONS_INDEX 3
++#define CONFIG_BAUDRATE 9600
++#define CONFIG_SYS_BAUDRATE_TABLE { 9600, 19200, 38400, 57600, 115200 }
++#define CONFIG_ASPEED_COM 0x1e78e000 // COM3
++#define CONFIG_ASPEED_COM_IER (CONFIG_ASPEED_COM + 0x4)
++#define CONFIG_ASPEED_COM_IIR (CONFIG_ASPEED_COM + 0x8)
++#define CONFIG_ASPEED_COM_LCR (CONFIG_ASPEED_COM + 0xc)
++
++/*
++ * USB device configuration
++ */
++/*
++#define CONFIG_USB_DEVICE 1
++#define CONFIG_USB_TTY 1
++
++#define CONFIG_USBD_VENDORID 0x1234
++#define CONFIG_USBD_PRODUCTID 0x5678
++#define CONFIG_USBD_MANUFACTURER "Siemens"
++#define CONFIG_USBD_PRODUCT_NAME "SX1"
++*/
++
++/*
++ * I2C configuration
++ */
++#define CONFIG_HARD_I2C
++#define CONFIG_SYS_I2C_SPEED 100000
++#define CONFIG_SYS_I2C_SLAVE 1
++#define CONFIG_DRIVER_ASPEED_I2C
++
++/*
++* EEPROM configuration
++*/
++#define CONFIG_SYS_I2C_EEPROM_ADDR_LEN 2
++#define CONFIG_SYS_I2C_EEPROM_ADDR 0xa0
++
++#define __BYTE_ORDER __LITTLE_ENDIAN
++#define __LITTLE_ENDIAN_BITFIELD
++
++/*
++ * NIC configuration
++ */
++#define CONFIG_ASPEEDNIC
++#define CONFIG_NET_MULTI
++#define CONFIG_MAC1_PHY_LINK_INTERRUPT
++#define CONFIG_MAC2_ENABLE
++#define CONFIG_MAC2_PHY_LINK_INTERRUPT
++/*
++*-------------------------------------------------------------------------------
++* NOTICE: MAC1 and MAC2 now have their own seperate PHY configuration.
++* We use 2 bits for each MAC in the scratch register(D[15:11] in 0x1E6E2040) to
++* inform kernel driver.
++* The meanings of the 2 bits are:
++* 00(0): Dedicated PHY
++* 01(1): ASPEED's EVA + INTEL's NC-SI PHY chip EVA
++* 10(2): ASPEED's MAC is connected to NC-SI PHY chip directly
++* 11: Reserved
++*
++* We use CONFIG_MAC1_PHY_SETTING and CONFIG_MAC2_PHY_SETTING in U-Boot
++* 0: Dedicated PHY
++* 1: ASPEED's EVA + INTEL's NC-SI PHY chip EVA
++* 2: ASPEED's MAC is connected to NC-SI PHY chip directly
++* 3: Reserved
++*-------------------------------------------------------------------------------
++*/
++#define CONFIG_MAC1_PHY_SETTING 0
++#define CONFIG_MAC2_PHY_SETTING 0
++#define CONFIG_ASPEED_MAC_NUMBER 2
++#define CONFIG_ASPEED_MAC_CONFIG 2 // config MAC2
++#define _PHY_SETTING_CONCAT(mac) CONFIG_MAC##mac##_PHY_SETTING
++#define _GET_MAC_PHY_SETTING(mac) _PHY_SETTING_CONCAT(mac)
++#define CONFIG_ASPEED_MAC_PHY_SETTING \
++ _GET_MAC_PHY_SETTING(CONFIG_ASPEED_MAC_CONFIG)
++#define CONFIG_MAC_INTERFACE_CLOCK_DELAY 0x2255
++#define CONFIG_RANDOM_MACADDR
++//#define CONFIG_GATEWAYIP 192.168.0.1
++//#define CONFIG_NETMASK 255.255.255.0
++//#define CONFIG_IPADDR 192.168.0.45
++//#define CONFIG_SERVERIP 192.168.0.81
++
++/*
++ * SLT
++ */
++/*
++#define CONFIG_SLT
++#define CFG_CMD_SLT (CFG_CMD_VIDEOTEST | CFG_CMD_MACTEST | CFG_CMD_HACTEST | CFG_CMD_MICTEST)
++*/
++
++#define CONFIG_SYS_INIT_SP_ADDR (CONFIG_SYS_SDRAM_BASE + 0x1000 - GENERATED_GBL_DATA_SIZE)
++
++#define CONFIG_ASPEED_ENABLE_WATCHDOG
++#define CONFIG_ASPEED_WATCHDOG_TIMEOUT (5*60) // 5m
++
++#endif /* __CONFIG_H */
diff --git a/meta-aspeed/recipes-bsp/u-boot/u-boot-fw-utils_2013.07%.bbappend b/meta-aspeed/recipes-bsp/u-boot/u-boot-fw-utils_2013.07%.bbappend
new file mode 100644
index 0000000..c93571b
--- /dev/null
+++ b/meta-aspeed/recipes-bsp/u-boot/u-boot-fw-utils_2013.07%.bbappend
@@ -0,0 +1,5 @@
+FILESEXTRAPATHS_prepend := "${THISDIR}/files:"
+
+SRC_URI += "file://patch-2013.07/0000-u-boot-aspeed-064.patch \
+ file://patch-2013.07/0001-u-boot-openbmc.patch \
+ "
diff --git a/meta-aspeed/recipes-bsp/u-boot/u-boot_2013.07%.bbappend b/meta-aspeed/recipes-bsp/u-boot/u-boot_2013.07%.bbappend
new file mode 100644
index 0000000..d4e347b
--- /dev/null
+++ b/meta-aspeed/recipes-bsp/u-boot/u-boot_2013.07%.bbappend
@@ -0,0 +1,12 @@
+FILESEXTRAPATHS_prepend := "${THISDIR}/files:"
+
+SRC_URI += "file://fw_env.config \
+ file://patch-2013.07/0000-u-boot-aspeed-064.patch \
+ file://patch-2013.07/0001-u-boot-openbmc.patch \
+ "
+
+# Do not install u-boot in rootfs
+do_install[postfuncs] += "remove_uboot_from_rootfs"
+remove_uboot_from_rootfs() {
+ rm -rf ${D}/boot/u-boot*
+}
diff --git a/meta-aspeed/recipes-core/images/aspeed-dev.inc b/meta-aspeed/recipes-core/images/aspeed-dev.inc
new file mode 100644
index 0000000..ea3d97f
--- /dev/null
+++ b/meta-aspeed/recipes-core/images/aspeed-dev.inc
@@ -0,0 +1,5 @@
+
+# linux 2.6.28 does not support devtmpfs, manually populate dev
+USE_DEVFS = "0"
+
+IMAGE_DEVICE_TABLES += "recipes-core/images/files/aspeed_device_table" \ No newline at end of file
diff --git a/meta-aspeed/recipes-core/images/files/aspeed_device_table b/meta-aspeed/recipes-core/images/files/aspeed_device_table
new file mode 100644
index 0000000..fac26b9
--- /dev/null
+++ b/meta-aspeed/recipes-core/images/files/aspeed_device_table
@@ -0,0 +1,41 @@
+#<path> <type> <mode> <uid> <gid> <major> <minor> <start> <inc> <count>
+#/dev/mem c 640 0 0 1 1 0 0 -
+#
+#type can be one of:
+# f A regular file
+# d Directory
+# c Character special device file
+# b Block special device file
+# p Fifo (named pipe)
+
+/dev d 755 root root - - - - -
+/dev/console c 662 root tty 5 1 - - -
+/dev/fb0 c 600 root root 29 0 - - -
+/dev/hda b 660 root disk 3 0 - - -
+/dev/hda b 660 root disk 3 1 1 1 4
+/dev/kmem c 640 root kmem 1 2 - - -
+/dev/kmsg c 600 root root 1 11 - - -
+/dev/mem c 640 root kmem 1 1 - - -
+/dev/mmcblk0 b 660 root disk 179 0 - - -
+/dev/mmcblk0p b 660 root disk 179 1 1 1 4
+/dev/mtd c 660 root disk 90 0 0 2 8
+/dev/mtdblock b 640 root root 31 0 0 1 8
+/dev/null c 666 root root 1 3 - - -
+/dev/ram b 640 root root 1 0 0 1 4
+/dev/random c 644 root root 1 8 - - -
+/dev/rtc c 644 root root 254 0 0 1 2
+/dev/sda b 660 root disk 8 0 - - -
+/dev/sda b 660 root disk 8 1 1 1 4
+/dev/sdb b 660 root disk 8 16 - - -
+/dev/sdb b 660 root disk 8 17 1 1 4
+/dev/tty c 662 root tty 5 0 - - -
+/dev/tty c 666 root tty 4 0 0 1 8
+/dev/ttyS c 666 root tty 4 64 0 1 5
+/dev/ttyGS c 666 root tty 253 0 0 1 1
+/dev/urandom c 644 root root 1 9 - - -
+/dev/watchdog c 660 root root 10 130 - - -
+/dev/zero c 644 root root 1 5 - - -
+/dev/i2c- c 600 root root 89 0 0 1 10
+/dev/i2c- c 600 root root 89 11 11 1 2
+/dev/net d 755 root root - - - - -
+/dev/net/tun c 600 root root 10 200 - - -
diff --git a/meta-aspeed/recipes-kernel/linux/files/patch-2.6.28.9/0000-linux-aspeed-064.patch b/meta-aspeed/recipes-kernel/linux/files/patch-2.6.28.9/0000-linux-aspeed-064.patch
new file mode 100644
index 0000000..903cd75
--- /dev/null
+++ b/meta-aspeed/recipes-kernel/linux/files/patch-2.6.28.9/0000-linux-aspeed-064.patch
@@ -0,0 +1,50917 @@
+diff --git a/Documentation/spi/Makefile b/Documentation/spi/Makefile
+index a5b03c8..6155d94 100644
+--- a/Documentation/spi/Makefile
++++ b/Documentation/spi/Makefile
+@@ -1,6 +1,7 @@
+ # kbuild trick to avoid linker error. Can be omitted if a module is built.
+ obj- := dummy.o
+
++CC = $(CROSS_COMPILE)gcc
+ # List of programs to build
+ hostprogs-y := spidev_test spidev_fdx
+
+diff --git a/Makefile b/Makefile
+index 17bfe08..9ca7825 100644
+--- a/Makefile
++++ b/Makefile
+@@ -1670,3 +1670,16 @@ FORCE:
+ # Declare the contents of the .PHONY variable as phony. We keep that
+ # information in a variable se we can use it in if_changed and friends.
+ .PHONY: $(PHONY)
++
++pub:
++ cp arch/arm/boot/uImage /tftpboot/
++
++m68:
++ m68k-uclinux-objcopy vmlinux -O binary uc.bin
++ mv uc.bin /tftpboot/
++
++opub:
++ cp arch/arm/boot/Image .
++ gzip -f -9 Image
++ mkimage -A arm -O linux -T kernel -C gzip -a 40008000 -e 40008000 -d Image.gz uImage
++ cp uImage /tftpboot/
+diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
+index 9722f8b..71db83f 100644
+--- a/arch/arm/Kconfig
++++ b/arch/arm/Kconfig
+@@ -199,6 +199,14 @@ choice
+ prompt "ARM system type"
+ default ARCH_VERSATILE
+
++config ARCH_ASPEED
++ bool "ASPEED AST Family"
++ select ARM_AMBA
++ select PLAT_ASPEED
++ select GENERIC_GPIO
++ select ARCH_REQUIRE_GPIOLIB
++
++
+ config ARCH_AAEC2000
+ bool "Agilent AAEC-2000 based"
+ select ARM_AMBA
+@@ -551,6 +559,8 @@ config ARCH_MSM
+
+ endchoice
+
++source "arch/arm/mach-aspeed/Kconfig"
++
+ source "arch/arm/mach-clps711x/Kconfig"
+
+ source "arch/arm/mach-ep93xx/Kconfig"
+@@ -637,6 +647,9 @@ config PLAT_IOP
+ config PLAT_ORION
+ bool
+
++config PLAT_ASPEED
++ bool
++
+ source arch/arm/mm/Kconfig
+
+ config IWMMXT
+diff --git a/arch/arm/Makefile b/arch/arm/Makefile
+index bd6e281..b039927 100644
+--- a/arch/arm/Makefile
++++ b/arch/arm/Makefile
+@@ -144,6 +144,8 @@ endif
+ machine-$(CONFIG_ARCH_MSM) := msm
+ machine-$(CONFIG_ARCH_LOKI) := loki
+ machine-$(CONFIG_ARCH_MV78XX0) := mv78xx0
++ machine-$(CONFIG_ARCH_ASPEED) := aspeed
++ plat-$(CONFIG_PLAT_ASPEED) := aspeed
+
+ ifeq ($(CONFIG_ARCH_EBSA110),y)
+ # This is what happens if you forget the IOCS16 line.
+diff --git a/arch/arm/configs/ast2300_ast1070_defconfig b/arch/arm/configs/ast2300_ast1070_defconfig
+new file mode 100644
+index 0000000..2285e61
+--- /dev/null
++++ b/arch/arm/configs/ast2300_ast1070_defconfig
+@@ -0,0 +1,1037 @@
++#
++# Automatically generated make config: don't edit
++# Linux kernel version: 2.6.28.9
++# Fri Nov 1 16:40:08 2013
++#
++CONFIG_ARM=y
++CONFIG_SYS_SUPPORTS_APM_EMULATION=y
++CONFIG_GENERIC_GPIO=y
++# CONFIG_GENERIC_TIME is not set
++# CONFIG_GENERIC_CLOCKEVENTS is not set
++CONFIG_MMU=y
++# CONFIG_NO_IOPORT is not set
++CONFIG_GENERIC_HARDIRQS=y
++CONFIG_STACKTRACE_SUPPORT=y
++CONFIG_HAVE_LATENCYTOP_SUPPORT=y
++CONFIG_LOCKDEP_SUPPORT=y
++CONFIG_TRACE_IRQFLAGS_SUPPORT=y
++CONFIG_HARDIRQS_SW_RESEND=y
++CONFIG_GENERIC_IRQ_PROBE=y
++CONFIG_RWSEM_GENERIC_SPINLOCK=y
++# CONFIG_ARCH_HAS_ILOG2_U32 is not set
++# CONFIG_ARCH_HAS_ILOG2_U64 is not set
++CONFIG_GENERIC_HWEIGHT=y
++CONFIG_GENERIC_CALIBRATE_DELAY=y
++CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
++CONFIG_VECTORS_BASE=0xffff0000
++CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
++
++#
++# General setup
++#
++CONFIG_EXPERIMENTAL=y
++CONFIG_BROKEN_ON_SMP=y
++CONFIG_INIT_ENV_ARG_LIMIT=32
++CONFIG_LOCALVERSION=""
++# CONFIG_LOCALVERSION_AUTO is not set
++CONFIG_SWAP=y
++CONFIG_SYSVIPC=y
++CONFIG_SYSVIPC_SYSCTL=y
++# CONFIG_POSIX_MQUEUE is not set
++# CONFIG_BSD_PROCESS_ACCT is not set
++# CONFIG_TASKSTATS is not set
++# CONFIG_AUDIT is not set
++# CONFIG_IKCONFIG is not set
++CONFIG_LOG_BUF_SHIFT=16
++# CONFIG_CGROUPS is not set
++# CONFIG_GROUP_SCHED is not set
++CONFIG_SYSFS_DEPRECATED=y
++CONFIG_SYSFS_DEPRECATED_V2=y
++# CONFIG_RELAY is not set
++CONFIG_NAMESPACES=y
++# CONFIG_UTS_NS is not set
++# CONFIG_IPC_NS is not set
++# CONFIG_USER_NS is not set
++# CONFIG_PID_NS is not set
++CONFIG_BLK_DEV_INITRD=y
++CONFIG_INITRAMFS_SOURCE=""
++CONFIG_CC_OPTIMIZE_FOR_SIZE=y
++CONFIG_SYSCTL=y
++CONFIG_ANON_INODES=y
++# CONFIG_EMBEDDED is not set
++CONFIG_UID16=y
++CONFIG_SYSCTL_SYSCALL=y
++CONFIG_KALLSYMS=y
++CONFIG_KALLSYMS_EXTRA_PASS=y
++CONFIG_HOTPLUG=y
++CONFIG_PRINTK=y
++CONFIG_BUG=y
++CONFIG_ELF_CORE=y
++CONFIG_BASE_FULL=y
++CONFIG_FUTEX=y
++CONFIG_EPOLL=y
++CONFIG_SIGNALFD=y
++CONFIG_TIMERFD=y
++CONFIG_EVENTFD=y
++CONFIG_SHMEM=y
++CONFIG_AIO=y
++CONFIG_VM_EVENT_COUNTERS=y
++CONFIG_SLUB_DEBUG=y
++CONFIG_COMPAT_BRK=y
++# CONFIG_SLAB is not set
++CONFIG_SLUB=y
++# CONFIG_SLOB is not set
++# CONFIG_PROFILING is not set
++# CONFIG_MARKERS is not set
++CONFIG_HAVE_OPROFILE=y
++# CONFIG_KPROBES is not set
++CONFIG_HAVE_KPROBES=y
++CONFIG_HAVE_KRETPROBES=y
++CONFIG_HAVE_GENERIC_DMA_COHERENT=y
++CONFIG_SLABINFO=y
++CONFIG_RT_MUTEXES=y
++# CONFIG_TINY_SHMEM is not set
++CONFIG_BASE_SMALL=0
++CONFIG_MODULES=y
++# CONFIG_MODULE_FORCE_LOAD is not set
++CONFIG_MODULE_UNLOAD=y
++# CONFIG_MODULE_FORCE_UNLOAD is not set
++# CONFIG_MODVERSIONS is not set
++# CONFIG_MODULE_SRCVERSION_ALL is not set
++CONFIG_KMOD=y
++CONFIG_BLOCK=y
++# CONFIG_LBD is not set
++# CONFIG_BLK_DEV_IO_TRACE is not set
++# CONFIG_LSF is not set
++# CONFIG_BLK_DEV_BSG is not set
++# CONFIG_BLK_DEV_INTEGRITY is not set
++
++#
++# IO Schedulers
++#
++CONFIG_IOSCHED_NOOP=y
++CONFIG_IOSCHED_AS=y
++CONFIG_IOSCHED_DEADLINE=y
++CONFIG_IOSCHED_CFQ=y
++# CONFIG_DEFAULT_AS is not set
++# CONFIG_DEFAULT_DEADLINE is not set
++CONFIG_DEFAULT_CFQ=y
++# CONFIG_DEFAULT_NOOP is not set
++CONFIG_DEFAULT_IOSCHED="cfq"
++CONFIG_CLASSIC_RCU=y
++CONFIG_FREEZER=y
++
++#
++# System Type
++#
++CONFIG_ARCH_ASPEED=y
++# CONFIG_ARCH_AAEC2000 is not set
++# CONFIG_ARCH_INTEGRATOR is not set
++# CONFIG_ARCH_REALVIEW is not set
++# CONFIG_ARCH_VERSATILE is not set
++# CONFIG_ARCH_AT91 is not set
++# CONFIG_ARCH_CLPS7500 is not set
++# CONFIG_ARCH_CLPS711X is not set
++# CONFIG_ARCH_EBSA110 is not set
++# CONFIG_ARCH_EP93XX is not set
++# CONFIG_ARCH_FOOTBRIDGE is not set
++# CONFIG_ARCH_NETX is not set
++# CONFIG_ARCH_H720X is not set
++# CONFIG_ARCH_IMX is not set
++# CONFIG_ARCH_IOP13XX is not set
++# CONFIG_ARCH_IOP32X is not set
++# CONFIG_ARCH_IOP33X is not set
++# CONFIG_ARCH_IXP23XX is not set
++# CONFIG_ARCH_IXP2000 is not set
++# CONFIG_ARCH_IXP4XX is not set
++# CONFIG_ARCH_L7200 is not set
++# CONFIG_ARCH_KIRKWOOD is not set
++# CONFIG_ARCH_KS8695 is not set
++# CONFIG_ARCH_NS9XXX is not set
++# CONFIG_ARCH_LOKI is not set
++# CONFIG_ARCH_MV78XX0 is not set
++# CONFIG_ARCH_MXC is not set
++# CONFIG_ARCH_ORION5X is not set
++# CONFIG_ARCH_PNX4008 is not set
++# CONFIG_ARCH_PXA is not set
++# CONFIG_ARCH_RPC is not set
++# CONFIG_ARCH_SA1100 is not set
++# CONFIG_ARCH_S3C2410 is not set
++# CONFIG_ARCH_SHARK is not set
++# CONFIG_ARCH_LH7A40X is not set
++# CONFIG_ARCH_DAVINCI is not set
++# CONFIG_ARCH_OMAP is not set
++# CONFIG_ARCH_MSM is not set
++CONFIG_IRMP=y
++# CONFIG_PCEXT is not set
++# CONFIG_REMOTEFX is not set
++# CONFIG_ARCH_AST1100 is not set
++# CONFIG_ARCH_AST2100 is not set
++# CONFIG_ARCH_AST2200 is not set
++CONFIG_ARCH_AST2300=y
++# CONFIG_ARCH_AST2400 is not set
++# CONFIG_ARCH_AST2500 is not set
++
++#
++# FLASH Chip Select
++#
++CONFIG_AST_CS0_NOR=y
++# CONFIG_AST_CS0_NAND is not set
++# CONFIG_AST_CS0_SPI is not set
++# CONFIG_AST_CS0_NONE is not set
++CONFIG_AST_CS1_NOR=y
++# CONFIG_AST_CS1_NAND is not set
++# CONFIG_AST_CS1_SPI is not set
++# CONFIG_AST_CS1_NONE is not set
++CONFIG_AST_CS2_NOR=y
++# CONFIG_AST_CS2_NAND is not set
++# CONFIG_AST_CS2_SPI is not set
++# CONFIG_AST_CS2_NONE is not set
++CONFIG_AST_CS3_NOR=y
++# CONFIG_AST_CS3_NAND is not set
++# CONFIG_AST_CS3_SPI is not set
++# CONFIG_AST_CS3_NONE is not set
++CONFIG_AST_CS4_NOR=y
++# CONFIG_AST_CS4_NAND is not set
++# CONFIG_AST_CS4_SPI is not set
++# CONFIG_AST_CS4_NONE is not set
++CONFIG_ARCH_AST1070=y
++CONFIG_AST1070_NR=1
++# CONFIG_AST_LPC_PLUS is not set
++CONFIG_AST_LPC=y
++# CONFIG_AST_SCU_LOCK is not set
++
++#
++# Boot options
++#
++
++#
++# Power management
++#
++CONFIG_PLAT_ASPEED=y
++
++#
++# Processor Type
++#
++CONFIG_CPU_32=y
++CONFIG_CPU_ARM926T=y
++CONFIG_CPU_32v5=y
++CONFIG_CPU_ABRT_EV5TJ=y
++CONFIG_CPU_PABRT_NOIFAR=y
++CONFIG_CPU_CACHE_VIVT=y
++CONFIG_CPU_COPY_V4WB=y
++CONFIG_CPU_TLB_V4WBI=y
++CONFIG_CPU_CP15=y
++CONFIG_CPU_CP15_MMU=y
++
++#
++# Processor Features
++#
++CONFIG_ARM_THUMB=y
++# CONFIG_CPU_ICACHE_DISABLE is not set
++# CONFIG_CPU_DCACHE_DISABLE is not set
++# CONFIG_CPU_DCACHE_WRITETHROUGH is not set
++# CONFIG_CPU_CACHE_ROUND_ROBIN is not set
++# CONFIG_OUTER_CACHE is not set
++
++#
++# Bus support
++#
++CONFIG_ARM_AMBA=y
++# CONFIG_PCI_SYSCALL is not set
++# CONFIG_ARCH_SUPPORTS_MSI is not set
++# CONFIG_PCCARD is not set
++
++#
++# Kernel Features
++#
++CONFIG_VMSPLIT_3G=y
++# CONFIG_VMSPLIT_2G is not set
++# CONFIG_VMSPLIT_1G is not set
++CONFIG_PAGE_OFFSET=0xC0000000
++# CONFIG_PREEMPT is not set
++CONFIG_HZ=100
++# CONFIG_AEABI is not set
++CONFIG_ARCH_FLATMEM_HAS_HOLES=y
++# CONFIG_ARCH_SPARSEMEM_DEFAULT is not set
++# CONFIG_ARCH_SELECT_MEMORY_MODEL is not set
++CONFIG_SELECT_MEMORY_MODEL=y
++CONFIG_FLATMEM_MANUAL=y
++# CONFIG_DISCONTIGMEM_MANUAL is not set
++# CONFIG_SPARSEMEM_MANUAL is not set
++CONFIG_FLATMEM=y
++CONFIG_FLAT_NODE_MEM_MAP=y
++CONFIG_PAGEFLAGS_EXTENDED=y
++CONFIG_SPLIT_PTLOCK_CPUS=4096
++# CONFIG_RESOURCES_64BIT is not set
++# CONFIG_PHYS_ADDR_T_64BIT is not set
++CONFIG_ZONE_DMA_FLAG=0
++CONFIG_VIRT_TO_BUS=y
++CONFIG_UNEVICTABLE_LRU=y
++CONFIG_ALIGNMENT_TRAP=y
++
++#
++# Boot options
++#
++CONFIG_ZBOOT_ROM_TEXT=0
++CONFIG_ZBOOT_ROM_BSS=0
++CONFIG_CMDLINE=""
++# CONFIG_XIP_KERNEL is not set
++# CONFIG_KEXEC is not set
++
++#
++# CPU Power Management
++#
++# CONFIG_CPU_IDLE is not set
++
++#
++# Floating point emulation
++#
++
++#
++# At least one emulation must be selected
++#
++CONFIG_FPE_NWFPE=y
++CONFIG_FPE_NWFPE_XP=y
++# CONFIG_FPE_FASTFPE is not set
++CONFIG_VFP=y
++
++#
++# Userspace binary formats
++#
++CONFIG_BINFMT_ELF=y
++# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
++CONFIG_HAVE_AOUT=y
++CONFIG_BINFMT_AOUT=y
++# CONFIG_BINFMT_MISC is not set
++# CONFIG_ARTHUR is not set
++
++#
++# Power management options
++#
++CONFIG_PM=y
++# CONFIG_PM_DEBUG is not set
++CONFIG_PM_SLEEP=y
++CONFIG_SUSPEND=y
++CONFIG_SUSPEND_FREEZER=y
++# CONFIG_APM_EMULATION is not set
++CONFIG_ARCH_SUSPEND_POSSIBLE=y
++CONFIG_NET=y
++
++#
++# Networking options
++#
++CONFIG_PACKET=y
++# CONFIG_PACKET_MMAP is not set
++CONFIG_UNIX=y
++CONFIG_XFRM=y
++# CONFIG_XFRM_USER is not set
++# CONFIG_XFRM_SUB_POLICY is not set
++# CONFIG_XFRM_MIGRATE is not set
++# CONFIG_XFRM_STATISTICS is not set
++# CONFIG_NET_KEY is not set
++CONFIG_INET=y
++CONFIG_IP_MULTICAST=y
++# CONFIG_IP_ADVANCED_ROUTER is not set
++CONFIG_IP_FIB_HASH=y
++CONFIG_IP_PNP=y
++CONFIG_IP_PNP_DHCP=y
++CONFIG_IP_PNP_BOOTP=y
++# CONFIG_IP_PNP_RARP is not set
++# CONFIG_NET_IPIP is not set
++# CONFIG_NET_IPGRE is not set
++# CONFIG_IP_MROUTE is not set
++# CONFIG_ARPD is not set
++# CONFIG_SYN_COOKIES is not set
++# CONFIG_INET_AH is not set
++# CONFIG_INET_ESP is not set
++# CONFIG_INET_IPCOMP is not set
++# CONFIG_INET_XFRM_TUNNEL is not set
++# CONFIG_INET_TUNNEL is not set
++CONFIG_INET_XFRM_MODE_TRANSPORT=y
++CONFIG_INET_XFRM_MODE_TUNNEL=y
++CONFIG_INET_XFRM_MODE_BEET=y
++# CONFIG_INET_LRO is not set
++CONFIG_INET_DIAG=y
++CONFIG_INET_TCP_DIAG=y
++# CONFIG_TCP_CONG_ADVANCED is not set
++CONFIG_TCP_CONG_CUBIC=y
++CONFIG_DEFAULT_TCP_CONG="cubic"
++# CONFIG_TCP_MD5SIG is not set
++# CONFIG_IPV6 is not set
++# CONFIG_NETWORK_SECMARK is not set
++# CONFIG_NETFILTER is not set
++# CONFIG_IP_DCCP is not set
++# CONFIG_IP_SCTP is not set
++# CONFIG_TIPC is not set
++# CONFIG_ATM is not set
++# CONFIG_BRIDGE is not set
++# CONFIG_NET_DSA is not set
++# CONFIG_VLAN_8021Q is not set
++# CONFIG_DECNET is not set
++# CONFIG_LLC2 is not set
++# CONFIG_IPX is not set
++# CONFIG_ATALK is not set
++# CONFIG_X25 is not set
++# CONFIG_LAPB is not set
++# CONFIG_ECONET is not set
++CONFIG_WAN_ROUTER=y
++# CONFIG_NET_SCHED is not set
++
++#
++# Network testing
++#
++# CONFIG_NET_PKTGEN is not set
++# CONFIG_HAMRADIO is not set
++# CONFIG_CAN is not set
++# CONFIG_IRDA is not set
++# CONFIG_BT is not set
++# CONFIG_AF_RXRPC is not set
++# CONFIG_PHONET is not set
++# CONFIG_WIRELESS is not set
++# CONFIG_RFKILL is not set
++# CONFIG_NET_9P is not set
++
++#
++# Device Drivers
++#
++
++#
++# Generic Driver Options
++#
++CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
++CONFIG_STANDALONE=y
++CONFIG_PREVENT_FIRMWARE_BUILD=y
++CONFIG_FW_LOADER=y
++CONFIG_FIRMWARE_IN_KERNEL=y
++CONFIG_EXTRA_FIRMWARE=""
++# CONFIG_SYS_HYPERVISOR is not set
++CONFIG_CONNECTOR=y
++CONFIG_PROC_EVENTS=y
++# CONFIG_MTD is not set
++# CONFIG_PARPORT is not set
++CONFIG_BLK_DEV=y
++# CONFIG_BLK_DEV_COW_COMMON is not set
++CONFIG_BLK_DEV_LOOP=y
++# CONFIG_BLK_DEV_CRYPTOLOOP is not set
++CONFIG_BLK_DEV_NBD=m
++CONFIG_BLK_DEV_RAM=y
++CONFIG_BLK_DEV_RAM_COUNT=16
++CONFIG_BLK_DEV_RAM_SIZE=16384
++# CONFIG_BLK_DEV_XIP is not set
++# CONFIG_CDROM_PKTCDVD is not set
++# CONFIG_ATA_OVER_ETH is not set
++CONFIG_MISC_DEVICES=y
++# CONFIG_EEPROM_93CX6 is not set
++# CONFIG_ICS932S401 is not set
++# CONFIG_ENCLOSURE_SERVICES is not set
++# CONFIG_C2PORT is not set
++CONFIG_HAVE_IDE=y
++# CONFIG_IDE is not set
++
++#
++# SCSI device support
++#
++# CONFIG_RAID_ATTRS is not set
++CONFIG_SCSI=y
++CONFIG_SCSI_DMA=y
++CONFIG_SCSI_TGT=y
++# CONFIG_SCSI_NETLINK is not set
++CONFIG_SCSI_PROC_FS=y
++
++#
++# SCSI support type (disk, tape, CD-ROM)
++#
++CONFIG_BLK_DEV_SD=y
++# CONFIG_CHR_DEV_ST is not set
++# CONFIG_CHR_DEV_OSST is not set
++# CONFIG_BLK_DEV_SR is not set
++CONFIG_CHR_DEV_SG=y
++# CONFIG_CHR_DEV_SCH is not set
++
++#
++# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
++#
++# CONFIG_SCSI_MULTI_LUN is not set
++# CONFIG_SCSI_CONSTANTS is not set
++# CONFIG_SCSI_LOGGING is not set
++CONFIG_SCSI_SCAN_ASYNC=y
++CONFIG_SCSI_WAIT_SCAN=m
++
++#
++# SCSI Transports
++#
++# CONFIG_SCSI_SPI_ATTRS is not set
++# CONFIG_SCSI_FC_ATTRS is not set
++CONFIG_SCSI_ISCSI_ATTRS=m
++# CONFIG_SCSI_SAS_LIBSAS is not set
++# CONFIG_SCSI_SRP_ATTRS is not set
++# CONFIG_SCSI_LOWLEVEL is not set
++# CONFIG_SCSI_DH is not set
++# CONFIG_ATA is not set
++# CONFIG_MD is not set
++CONFIG_NETDEVICES=y
++# CONFIG_DUMMY is not set
++# CONFIG_BONDING is not set
++# CONFIG_MACVLAN is not set
++# CONFIG_EQUALIZER is not set
++# CONFIG_TUN is not set
++# CONFIG_VETH is not set
++# CONFIG_NET_ETHERNET is not set
++CONFIG_NETDEV_1000=y
++CONFIG_ASPEEDMAC=y
++# CONFIG_MAC0_PHY_LINK is not set
++# CONFIG_NETDEV_10000 is not set
++
++#
++# Wireless LAN
++#
++# CONFIG_WLAN_PRE80211 is not set
++# CONFIG_WLAN_80211 is not set
++# CONFIG_IWLWIFI_LEDS is not set
++# CONFIG_WAN is not set
++# CONFIG_PPP is not set
++# CONFIG_SLIP is not set
++# CONFIG_NETCONSOLE is not set
++# CONFIG_NETPOLL is not set
++# CONFIG_NET_POLL_CONTROLLER is not set
++# CONFIG_ISDN is not set
++
++#
++# Input device support
++#
++CONFIG_INPUT=y
++# CONFIG_INPUT_FF_MEMLESS is not set
++# CONFIG_INPUT_POLLDEV is not set
++
++#
++# Userland interfaces
++#
++CONFIG_INPUT_MOUSEDEV=y
++CONFIG_INPUT_MOUSEDEV_PSAUX=y
++CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
++CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
++# CONFIG_INPUT_JOYDEV is not set
++CONFIG_INPUT_EVDEV=y
++# CONFIG_INPUT_EVBUG is not set
++
++#
++# Input Device Drivers
++#
++CONFIG_INPUT_KEYBOARD=y
++CONFIG_KEYBOARD_ATKBD=y
++# CONFIG_KEYBOARD_SUNKBD is not set
++# CONFIG_KEYBOARD_LKKBD is not set
++# CONFIG_KEYBOARD_XTKBD is not set
++# CONFIG_KEYBOARD_NEWTON is not set
++# CONFIG_KEYBOARD_STOWAWAY is not set
++# CONFIG_KEYBOARD_GPIO is not set
++CONFIG_INPUT_MOUSE=y
++CONFIG_MOUSE_PS2=y
++CONFIG_MOUSE_PS2_ALPS=y
++CONFIG_MOUSE_PS2_LOGIPS2PP=y
++CONFIG_MOUSE_PS2_SYNAPTICS=y
++CONFIG_MOUSE_PS2_LIFEBOOK=y
++CONFIG_MOUSE_PS2_TRACKPOINT=y
++# CONFIG_MOUSE_PS2_ELANTECH is not set
++# CONFIG_MOUSE_PS2_TOUCHKIT is not set
++CONFIG_MOUSE_SERIAL=y
++# CONFIG_MOUSE_VSXXXAA is not set
++# CONFIG_MOUSE_GPIO is not set
++# CONFIG_INPUT_JOYSTICK is not set
++# CONFIG_INPUT_TABLET is not set
++# CONFIG_INPUT_TOUCHSCREEN is not set
++# CONFIG_INPUT_MISC is not set
++
++#
++# Hardware I/O ports
++#
++CONFIG_SERIO=y
++CONFIG_SERIO_SERPORT=y
++# CONFIG_SERIO_AMBAKMI is not set
++CONFIG_SERIO_LIBPS2=y
++# CONFIG_SERIO_RAW is not set
++# CONFIG_GAMEPORT is not set
++
++#
++# Character devices
++#
++CONFIG_VT=y
++CONFIG_CONSOLE_TRANSLATIONS=y
++CONFIG_VT_CONSOLE=y
++CONFIG_HW_CONSOLE=y
++# CONFIG_VT_HW_CONSOLE_BINDING is not set
++CONFIG_DEVKMEM=y
++CONFIG_SERIAL_NONSTANDARD=y
++# CONFIG_N_HDLC is not set
++# CONFIG_RISCOM8 is not set
++# CONFIG_SPECIALIX is not set
++# CONFIG_RIO is not set
++# CONFIG_STALDRV is not set
++
++#
++# Serial drivers
++#
++CONFIG_SERIAL_8250=y
++CONFIG_SERIAL_8250_CONSOLE=y
++CONFIG_SERIAL_8250_NR_UARTS=3
++CONFIG_SERIAL_8250_RUNTIME_UARTS=3
++CONFIG_SERIAL_AST_DMA_UART=y
++CONFIG_AST_NR_DMA_UARTS=8
++CONFIG_AST_RUNTIME_DMA_UARTS=8
++# CONFIG_SERIAL_8250_EXTENDED is not set
++
++#
++# Non-8250 serial port support
++#
++# CONFIG_SERIAL_AMBA_PL010 is not set
++# CONFIG_SERIAL_AMBA_PL011 is not set
++# CONFIG_SERIAL_AST is not set
++CONFIG_SERIAL_CORE=y
++CONFIG_SERIAL_CORE_CONSOLE=y
++CONFIG_UNIX98_PTYS=y
++CONFIG_LEGACY_PTYS=y
++CONFIG_LEGACY_PTY_COUNT=256
++# CONFIG_IPMI_HANDLER is not set
++# CONFIG_AST_MISC is not set
++# CONFIG_HW_RANDOM is not set
++CONFIG_NVRAM=y
++# CONFIG_R3964 is not set
++# CONFIG_RAW_DRIVER is not set
++# CONFIG_TCG_TPM is not set
++CONFIG_I2C=y
++CONFIG_I2C_BOARDINFO=y
++CONFIG_I2C_CHARDEV=y
++CONFIG_I2C_HELPER_AUTO=y
++
++#
++# I2C Hardware Bus support
++#
++
++#
++# I2C system bus drivers (mostly embedded / system-on-chip)
++#
++# CONFIG_I2C_GPIO is not set
++# CONFIG_I2C_OCORES is not set
++CONFIG_I2C_AST=y
++CONFIG_I2C_AST1070=y
++CONFIG_AST_I2C_SLAVE_MODE=y
++CONFIG_AST_I2C_SLAVE_EEPROM=y
++# CONFIG_AST_I2C_SLAVE_RDWR is not set
++# CONFIG_I2C_SIMTEC is not set
++
++#
++# External I2C/SMBus adapter drivers
++#
++# CONFIG_I2C_PARPORT_LIGHT is not set
++# CONFIG_I2C_TAOS_EVM is not set
++
++#
++# Other I2C/SMBus bus drivers
++#
++# CONFIG_I2C_PCA_PLATFORM is not set
++# CONFIG_I2C_STUB is not set
++
++#
++# Miscellaneous I2C Chip support
++#
++# CONFIG_DS1682 is not set
++# CONFIG_AT24 is not set
++# CONFIG_SENSORS_EEPROM is not set
++# CONFIG_SENSORS_PCF8574 is not set
++# CONFIG_PCF8575 is not set
++# CONFIG_SENSORS_PCA9539 is not set
++# CONFIG_SENSORS_PCF8591 is not set
++# CONFIG_TPS65010 is not set
++# CONFIG_SENSORS_MAX6875 is not set
++# CONFIG_SENSORS_TSL2550 is not set
++# CONFIG_I2C_DEBUG_CORE is not set
++# CONFIG_I2C_DEBUG_ALGO is not set
++# CONFIG_I2C_DEBUG_BUS is not set
++# CONFIG_I2C_DEBUG_CHIP is not set
++# CONFIG_SPI is not set
++CONFIG_ARCH_REQUIRE_GPIOLIB=y
++CONFIG_GPIOLIB=y
++CONFIG_GPIO_SYSFS=y
++
++#
++# Memory mapped GPIO expanders:
++#
++
++#
++# I2C GPIO expanders:
++#
++# CONFIG_GPIO_MAX732X is not set
++# CONFIG_GPIO_PCA953X is not set
++# CONFIG_GPIO_PCF857X is not set
++
++#
++# PCI GPIO expanders:
++#
++
++#
++# SPI GPIO expanders:
++#
++# CONFIG_W1 is not set
++# CONFIG_POWER_SUPPLY is not set
++# CONFIG_HWMON is not set
++# CONFIG_THERMAL is not set
++# CONFIG_THERMAL_HWMON is not set
++# CONFIG_WATCHDOG is not set
++CONFIG_SSB_POSSIBLE=y
++
++#
++# Sonics Silicon Backplane
++#
++# CONFIG_SSB is not set
++
++#
++# Multifunction device drivers
++#
++# CONFIG_MFD_CORE is not set
++# CONFIG_MFD_SM501 is not set
++# CONFIG_MFD_ASIC3 is not set
++# CONFIG_HTC_EGPIO is not set
++# CONFIG_HTC_PASIC3 is not set
++# CONFIG_MFD_TMIO is not set
++# CONFIG_MFD_TC6393XB is not set
++# CONFIG_PMIC_DA903X is not set
++# CONFIG_MFD_WM8400 is not set
++# CONFIG_MFD_WM8350_I2C is not set
++
++#
++# Multimedia devices
++#
++
++#
++# Multimedia core support
++#
++# CONFIG_VIDEO_DEV is not set
++# CONFIG_DVB_CORE is not set
++# CONFIG_VIDEO_MEDIA is not set
++
++#
++# Multimedia drivers
++#
++# CONFIG_DAB is not set
++
++#
++# Graphics support
++#
++# CONFIG_VGASTATE is not set
++# CONFIG_VIDEO_OUTPUT_CONTROL is not set
++# CONFIG_FB is not set
++# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
++
++#
++# Display device support
++#
++# CONFIG_DISPLAY_SUPPORT is not set
++
++#
++# Console display driver support
++#
++# CONFIG_VGA_CONSOLE is not set
++CONFIG_DUMMY_CONSOLE=y
++# CONFIG_SOUND is not set
++# CONFIG_HID_SUPPORT is not set
++# CONFIG_USB_SUPPORT is not set
++# CONFIG_MMC is not set
++# CONFIG_MEMSTICK is not set
++# CONFIG_ACCESSIBILITY is not set
++# CONFIG_NEW_LEDS is not set
++CONFIG_RTC_LIB=y
++# CONFIG_RTC_CLASS is not set
++# CONFIG_DMADEVICES is not set
++# CONFIG_REGULATOR is not set
++# CONFIG_UIO is not set
++
++#
++# File systems
++#
++CONFIG_EXT2_FS=y
++CONFIG_EXT2_FS_XATTR=y
++CONFIG_EXT2_FS_POSIX_ACL=y
++CONFIG_EXT2_FS_SECURITY=y
++# CONFIG_EXT2_FS_XIP is not set
++# CONFIG_EXT3_FS is not set
++# CONFIG_EXT4_FS is not set
++CONFIG_FS_MBCACHE=y
++# CONFIG_REISERFS_FS is not set
++# CONFIG_JFS_FS is not set
++CONFIG_FS_POSIX_ACL=y
++CONFIG_FILE_LOCKING=y
++# CONFIG_XFS_FS is not set
++# CONFIG_OCFS2_FS is not set
++CONFIG_DNOTIFY=y
++CONFIG_INOTIFY=y
++CONFIG_INOTIFY_USER=y
++# CONFIG_QUOTA is not set
++# CONFIG_AUTOFS_FS is not set
++# CONFIG_AUTOFS4_FS is not set
++# CONFIG_FUSE_FS is not set
++CONFIG_GENERIC_ACL=y
++
++#
++# CD-ROM/DVD Filesystems
++#
++# CONFIG_ISO9660_FS is not set
++# CONFIG_UDF_FS is not set
++
++#
++# DOS/FAT/NT Filesystems
++#
++CONFIG_FAT_FS=y
++CONFIG_MSDOS_FS=y
++CONFIG_VFAT_FS=y
++CONFIG_FAT_DEFAULT_CODEPAGE=437
++CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
++CONFIG_NTFS_FS=y
++# CONFIG_NTFS_DEBUG is not set
++CONFIG_NTFS_RW=y
++
++#
++# Pseudo filesystems
++#
++CONFIG_PROC_FS=y
++CONFIG_PROC_SYSCTL=y
++CONFIG_PROC_PAGE_MONITOR=y
++CONFIG_SYSFS=y
++CONFIG_TMPFS=y
++CONFIG_TMPFS_POSIX_ACL=y
++# CONFIG_HUGETLB_PAGE is not set
++CONFIG_CONFIGFS_FS=m
++
++#
++# Miscellaneous filesystems
++#
++# CONFIG_ADFS_FS is not set
++# CONFIG_AFFS_FS is not set
++# CONFIG_HFS_FS is not set
++# CONFIG_HFSPLUS_FS is not set
++# CONFIG_BEFS_FS is not set
++# CONFIG_BFS_FS is not set
++# CONFIG_EFS_FS is not set
++# CONFIG_CRAMFS is not set
++# CONFIG_VXFS_FS is not set
++# CONFIG_MINIX_FS is not set
++# CONFIG_OMFS_FS is not set
++# CONFIG_HPFS_FS is not set
++# CONFIG_QNX4FS_FS is not set
++# CONFIG_ROMFS_FS is not set
++# CONFIG_SYSV_FS is not set
++# CONFIG_UFS_FS is not set
++CONFIG_NETWORK_FILESYSTEMS=y
++CONFIG_NFS_FS=y
++# CONFIG_NFS_V3 is not set
++# CONFIG_NFS_V4 is not set
++CONFIG_ROOT_NFS=y
++# CONFIG_NFSD is not set
++CONFIG_LOCKD=y
++CONFIG_NFS_COMMON=y
++CONFIG_SUNRPC=y
++# CONFIG_SUNRPC_REGISTER_V4 is not set
++# CONFIG_RPCSEC_GSS_KRB5 is not set
++# CONFIG_RPCSEC_GSS_SPKM3 is not set
++# CONFIG_SMB_FS is not set
++# CONFIG_CIFS is not set
++# CONFIG_NCP_FS is not set
++# CONFIG_CODA_FS is not set
++# CONFIG_AFS_FS is not set
++
++#
++# Partition Types
++#
++# CONFIG_PARTITION_ADVANCED is not set
++CONFIG_MSDOS_PARTITION=y
++CONFIG_NLS=y
++CONFIG_NLS_DEFAULT="utf8"
++CONFIG_NLS_CODEPAGE_437=y
++# CONFIG_NLS_CODEPAGE_737 is not set
++# CONFIG_NLS_CODEPAGE_775 is not set
++# CONFIG_NLS_CODEPAGE_850 is not set
++# CONFIG_NLS_CODEPAGE_852 is not set
++# CONFIG_NLS_CODEPAGE_855 is not set
++# CONFIG_NLS_CODEPAGE_857 is not set
++# CONFIG_NLS_CODEPAGE_860 is not set
++# CONFIG_NLS_CODEPAGE_861 is not set
++# CONFIG_NLS_CODEPAGE_862 is not set
++# CONFIG_NLS_CODEPAGE_863 is not set
++# CONFIG_NLS_CODEPAGE_864 is not set
++# CONFIG_NLS_CODEPAGE_865 is not set
++# CONFIG_NLS_CODEPAGE_866 is not set
++# CONFIG_NLS_CODEPAGE_869 is not set
++CONFIG_NLS_CODEPAGE_936=y
++CONFIG_NLS_CODEPAGE_950=y
++CONFIG_NLS_CODEPAGE_932=y
++# CONFIG_NLS_CODEPAGE_949 is not set
++# CONFIG_NLS_CODEPAGE_874 is not set
++# CONFIG_NLS_ISO8859_8 is not set
++# CONFIG_NLS_CODEPAGE_1250 is not set
++# CONFIG_NLS_CODEPAGE_1251 is not set
++CONFIG_NLS_ASCII=y
++CONFIG_NLS_ISO8859_1=y
++# CONFIG_NLS_ISO8859_2 is not set
++# CONFIG_NLS_ISO8859_3 is not set
++# CONFIG_NLS_ISO8859_4 is not set
++# CONFIG_NLS_ISO8859_5 is not set
++# CONFIG_NLS_ISO8859_6 is not set
++# CONFIG_NLS_ISO8859_7 is not set
++# CONFIG_NLS_ISO8859_9 is not set
++# CONFIG_NLS_ISO8859_13 is not set
++# CONFIG_NLS_ISO8859_14 is not set
++# CONFIG_NLS_ISO8859_15 is not set
++# CONFIG_NLS_KOI8_R is not set
++# CONFIG_NLS_KOI8_U is not set
++CONFIG_NLS_UTF8=y
++# CONFIG_DLM is not set
++
++#
++# Kernel hacking
++#
++# CONFIG_PRINTK_TIME is not set
++# CONFIG_ENABLE_WARN_DEPRECATED is not set
++CONFIG_ENABLE_MUST_CHECK=y
++CONFIG_FRAME_WARN=1024
++CONFIG_MAGIC_SYSRQ=y
++# CONFIG_UNUSED_SYMBOLS is not set
++# CONFIG_DEBUG_FS is not set
++# CONFIG_HEADERS_CHECK is not set
++# CONFIG_DEBUG_KERNEL is not set
++# CONFIG_SLUB_DEBUG_ON is not set
++# CONFIG_SLUB_STATS is not set
++CONFIG_DEBUG_BUGVERBOSE=y
++CONFIG_DEBUG_MEMORY_INIT=y
++CONFIG_FRAME_POINTER=y
++# CONFIG_RCU_CPU_STALL_DETECTOR is not set
++# CONFIG_LATENCYTOP is not set
++# CONFIG_SYSCTL_SYSCALL_CHECK is not set
++CONFIG_HAVE_FUNCTION_TRACER=y
++
++#
++# Tracers
++#
++# CONFIG_DYNAMIC_PRINTK_DEBUG is not set
++# CONFIG_SAMPLES is not set
++CONFIG_HAVE_ARCH_KGDB=y
++# CONFIG_DEBUG_USER is not set
++
++#
++# Security options
++#
++# CONFIG_KEYS is not set
++# CONFIG_SECURITY is not set
++# CONFIG_SECURITYFS is not set
++# CONFIG_SECURITY_FILE_CAPABILITIES is not set
++CONFIG_CRYPTO=y
++
++#
++# Crypto core or helper
++#
++# CONFIG_CRYPTO_FIPS is not set
++CONFIG_CRYPTO_ALGAPI=y
++CONFIG_CRYPTO_ALGAPI2=y
++CONFIG_CRYPTO_AEAD=m
++CONFIG_CRYPTO_AEAD2=y
++CONFIG_CRYPTO_BLKCIPHER=y
++CONFIG_CRYPTO_BLKCIPHER2=y
++CONFIG_CRYPTO_HASH=y
++CONFIG_CRYPTO_HASH2=y
++CONFIG_CRYPTO_RNG2=y
++CONFIG_CRYPTO_MANAGER=y
++CONFIG_CRYPTO_MANAGER2=y
++# CONFIG_CRYPTO_GF128MUL is not set
++CONFIG_CRYPTO_NULL=y
++# CONFIG_CRYPTO_CRYPTD is not set
++CONFIG_CRYPTO_AUTHENC=m
++# CONFIG_CRYPTO_TEST is not set
++
++#
++# Authenticated Encryption with Associated Data
++#
++# CONFIG_CRYPTO_CCM is not set
++# CONFIG_CRYPTO_GCM is not set
++# CONFIG_CRYPTO_SEQIV is not set
++
++#
++# Block modes
++#
++CONFIG_CRYPTO_CBC=y
++# CONFIG_CRYPTO_CTR is not set
++# CONFIG_CRYPTO_CTS is not set
++# CONFIG_CRYPTO_ECB is not set
++# CONFIG_CRYPTO_LRW is not set
++# CONFIG_CRYPTO_PCBC is not set
++# CONFIG_CRYPTO_XTS is not set
++
++#
++# Hash modes
++#
++CONFIG_CRYPTO_HMAC=y
++# CONFIG_CRYPTO_XCBC is not set
++
++#
++# Digest
++#
++# CONFIG_CRYPTO_CRC32C is not set
++# CONFIG_CRYPTO_MD4 is not set
++CONFIG_CRYPTO_MD5=y
++# CONFIG_CRYPTO_MICHAEL_MIC is not set
++# CONFIG_CRYPTO_RMD128 is not set
++# CONFIG_CRYPTO_RMD160 is not set
++# CONFIG_CRYPTO_RMD256 is not set
++# CONFIG_CRYPTO_RMD320 is not set
++CONFIG_CRYPTO_SHA1=y
++# CONFIG_CRYPTO_SHA256 is not set
++# CONFIG_CRYPTO_SHA512 is not set
++# CONFIG_CRYPTO_TGR192 is not set
++# CONFIG_CRYPTO_WP512 is not set
++
++#
++# Ciphers
++#
++# CONFIG_CRYPTO_AES is not set
++# CONFIG_CRYPTO_ANUBIS is not set
++# CONFIG_CRYPTO_ARC4 is not set
++# CONFIG_CRYPTO_BLOWFISH is not set
++# CONFIG_CRYPTO_CAMELLIA is not set
++# CONFIG_CRYPTO_CAST5 is not set
++# CONFIG_CRYPTO_CAST6 is not set
++CONFIG_CRYPTO_DES=y
++# CONFIG_CRYPTO_FCRYPT is not set
++# CONFIG_CRYPTO_KHAZAD is not set
++# CONFIG_CRYPTO_SALSA20 is not set
++# CONFIG_CRYPTO_SEED is not set
++# CONFIG_CRYPTO_SERPENT is not set
++# CONFIG_CRYPTO_TEA is not set
++# CONFIG_CRYPTO_TWOFISH is not set
++
++#
++# Compression
++#
++CONFIG_CRYPTO_DEFLATE=m
++# CONFIG_CRYPTO_LZO is not set
++
++#
++# Random Number Generation
++#
++# CONFIG_CRYPTO_ANSI_CPRNG is not set
++# CONFIG_CRYPTO_HW is not set
++
++#
++# Library routines
++#
++CONFIG_BITREVERSE=y
++# CONFIG_CRC_CCITT is not set
++# CONFIG_CRC16 is not set
++# CONFIG_CRC_T10DIF is not set
++CONFIG_CRC_ITU_T=m
++CONFIG_CRC32=y
++# CONFIG_CRC7 is not set
++# CONFIG_LIBCRC32C is not set
++CONFIG_ZLIB_INFLATE=m
++CONFIG_ZLIB_DEFLATE=m
++CONFIG_PLIST=y
++CONFIG_HAS_IOMEM=y
++CONFIG_HAS_IOPORT=y
++CONFIG_HAS_DMA=y
+diff --git a/arch/arm/configs/ast2300_defconfig b/arch/arm/configs/ast2300_defconfig
+new file mode 100644
+index 0000000..5ac2120
+--- /dev/null
++++ b/arch/arm/configs/ast2300_defconfig
+@@ -0,0 +1,1464 @@
++#
++# Automatically generated make config: don't edit
++# Linux kernel version: 2.6.28.9
++# Wed Aug 7 16:52:42 2013
++#
++CONFIG_ARM=y
++CONFIG_SYS_SUPPORTS_APM_EMULATION=y
++CONFIG_GENERIC_GPIO=y
++# CONFIG_GENERIC_TIME is not set
++# CONFIG_GENERIC_CLOCKEVENTS is not set
++CONFIG_MMU=y
++# CONFIG_NO_IOPORT is not set
++CONFIG_GENERIC_HARDIRQS=y
++CONFIG_STACKTRACE_SUPPORT=y
++CONFIG_HAVE_LATENCYTOP_SUPPORT=y
++CONFIG_LOCKDEP_SUPPORT=y
++CONFIG_TRACE_IRQFLAGS_SUPPORT=y
++CONFIG_HARDIRQS_SW_RESEND=y
++CONFIG_GENERIC_IRQ_PROBE=y
++CONFIG_RWSEM_GENERIC_SPINLOCK=y
++# CONFIG_ARCH_HAS_ILOG2_U32 is not set
++# CONFIG_ARCH_HAS_ILOG2_U64 is not set
++CONFIG_GENERIC_HWEIGHT=y
++CONFIG_GENERIC_CALIBRATE_DELAY=y
++CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
++CONFIG_VECTORS_BASE=0xffff0000
++CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
++
++#
++# General setup
++#
++CONFIG_EXPERIMENTAL=y
++CONFIG_BROKEN_ON_SMP=y
++CONFIG_INIT_ENV_ARG_LIMIT=32
++CONFIG_LOCALVERSION=""
++# CONFIG_LOCALVERSION_AUTO is not set
++CONFIG_SWAP=y
++CONFIG_SYSVIPC=y
++CONFIG_SYSVIPC_SYSCTL=y
++# CONFIG_POSIX_MQUEUE is not set
++# CONFIG_BSD_PROCESS_ACCT is not set
++# CONFIG_TASKSTATS is not set
++# CONFIG_AUDIT is not set
++# CONFIG_IKCONFIG is not set
++CONFIG_LOG_BUF_SHIFT=16
++# CONFIG_CGROUPS is not set
++# CONFIG_GROUP_SCHED is not set
++CONFIG_SYSFS_DEPRECATED=y
++CONFIG_SYSFS_DEPRECATED_V2=y
++# CONFIG_RELAY is not set
++CONFIG_NAMESPACES=y
++# CONFIG_UTS_NS is not set
++# CONFIG_IPC_NS is not set
++# CONFIG_USER_NS is not set
++# CONFIG_PID_NS is not set
++CONFIG_BLK_DEV_INITRD=y
++CONFIG_INITRAMFS_SOURCE=""
++CONFIG_CC_OPTIMIZE_FOR_SIZE=y
++CONFIG_SYSCTL=y
++CONFIG_ANON_INODES=y
++# CONFIG_EMBEDDED is not set
++CONFIG_UID16=y
++CONFIG_SYSCTL_SYSCALL=y
++CONFIG_KALLSYMS=y
++CONFIG_KALLSYMS_EXTRA_PASS=y
++CONFIG_HOTPLUG=y
++CONFIG_PRINTK=y
++CONFIG_BUG=y
++CONFIG_ELF_CORE=y
++CONFIG_BASE_FULL=y
++CONFIG_FUTEX=y
++CONFIG_EPOLL=y
++CONFIG_SIGNALFD=y
++CONFIG_TIMERFD=y
++CONFIG_EVENTFD=y
++CONFIG_SHMEM=y
++CONFIG_AIO=y
++CONFIG_VM_EVENT_COUNTERS=y
++CONFIG_SLUB_DEBUG=y
++CONFIG_COMPAT_BRK=y
++# CONFIG_SLAB is not set
++CONFIG_SLUB=y
++# CONFIG_SLOB is not set
++# CONFIG_PROFILING is not set
++# CONFIG_MARKERS is not set
++CONFIG_HAVE_OPROFILE=y
++# CONFIG_KPROBES is not set
++CONFIG_HAVE_KPROBES=y
++CONFIG_HAVE_KRETPROBES=y
++CONFIG_HAVE_GENERIC_DMA_COHERENT=y
++CONFIG_SLABINFO=y
++CONFIG_RT_MUTEXES=y
++# CONFIG_TINY_SHMEM is not set
++CONFIG_BASE_SMALL=0
++CONFIG_MODULES=y
++# CONFIG_MODULE_FORCE_LOAD is not set
++CONFIG_MODULE_UNLOAD=y
++# CONFIG_MODULE_FORCE_UNLOAD is not set
++# CONFIG_MODVERSIONS is not set
++# CONFIG_MODULE_SRCVERSION_ALL is not set
++CONFIG_KMOD=y
++CONFIG_BLOCK=y
++# CONFIG_LBD is not set
++# CONFIG_BLK_DEV_IO_TRACE is not set
++# CONFIG_LSF is not set
++# CONFIG_BLK_DEV_BSG is not set
++# CONFIG_BLK_DEV_INTEGRITY is not set
++
++#
++# IO Schedulers
++#
++CONFIG_IOSCHED_NOOP=y
++CONFIG_IOSCHED_AS=y
++CONFIG_IOSCHED_DEADLINE=y
++CONFIG_IOSCHED_CFQ=y
++# CONFIG_DEFAULT_AS is not set
++# CONFIG_DEFAULT_DEADLINE is not set
++CONFIG_DEFAULT_CFQ=y
++# CONFIG_DEFAULT_NOOP is not set
++CONFIG_DEFAULT_IOSCHED="cfq"
++CONFIG_CLASSIC_RCU=y
++CONFIG_FREEZER=y
++
++#
++# System Type
++#
++CONFIG_ARCH_ASPEED=y
++# CONFIG_ARCH_AAEC2000 is not set
++# CONFIG_ARCH_INTEGRATOR is not set
++# CONFIG_ARCH_REALVIEW is not set
++# CONFIG_ARCH_VERSATILE is not set
++# CONFIG_ARCH_AT91 is not set
++# CONFIG_ARCH_CLPS7500 is not set
++# CONFIG_ARCH_CLPS711X is not set
++# CONFIG_ARCH_EBSA110 is not set
++# CONFIG_ARCH_EP93XX is not set
++# CONFIG_ARCH_FOOTBRIDGE is not set
++# CONFIG_ARCH_NETX is not set
++# CONFIG_ARCH_H720X is not set
++# CONFIG_ARCH_IMX is not set
++# CONFIG_ARCH_IOP13XX is not set
++# CONFIG_ARCH_IOP32X is not set
++# CONFIG_ARCH_IOP33X is not set
++# CONFIG_ARCH_IXP23XX is not set
++# CONFIG_ARCH_IXP2000 is not set
++# CONFIG_ARCH_IXP4XX is not set
++# CONFIG_ARCH_L7200 is not set
++# CONFIG_ARCH_KIRKWOOD is not set
++# CONFIG_ARCH_KS8695 is not set
++# CONFIG_ARCH_NS9XXX is not set
++# CONFIG_ARCH_LOKI is not set
++# CONFIG_ARCH_MV78XX0 is not set
++# CONFIG_ARCH_MXC is not set
++# CONFIG_ARCH_ORION5X is not set
++# CONFIG_ARCH_PNX4008 is not set
++# CONFIG_ARCH_PXA is not set
++# CONFIG_ARCH_RPC is not set
++# CONFIG_ARCH_SA1100 is not set
++# CONFIG_ARCH_S3C2410 is not set
++# CONFIG_ARCH_SHARK is not set
++# CONFIG_ARCH_LH7A40X is not set
++# CONFIG_ARCH_DAVINCI is not set
++# CONFIG_ARCH_OMAP is not set
++# CONFIG_ARCH_MSM is not set
++CONFIG_IRMP=y
++# CONFIG_PCEXT is not set
++# CONFIG_REMOTEFX is not set
++# CONFIG_ARCH_AST1100 is not set
++# CONFIG_ARCH_AST2100 is not set
++# CONFIG_ARCH_AST2200 is not set
++CONFIG_ARCH_AST2300=y
++# CONFIG_ARCH_AST2400 is not set
++# CONFIG_ARCH_AST2500 is not set
++
++#
++# FLASH Chip Select
++#
++CONFIG_AST_CS0_NOR=y
++# CONFIG_AST_CS0_NAND is not set
++# CONFIG_AST_CS0_SPI is not set
++# CONFIG_AST_CS0_NONE is not set
++CONFIG_AST_CS1_NOR=y
++# CONFIG_AST_CS1_NAND is not set
++# CONFIG_AST_CS1_SPI is not set
++# CONFIG_AST_CS1_NONE is not set
++CONFIG_AST_CS2_NOR=y
++# CONFIG_AST_CS2_NAND is not set
++# CONFIG_AST_CS2_SPI is not set
++# CONFIG_AST_CS2_NONE is not set
++CONFIG_AST_CS3_NOR=y
++# CONFIG_AST_CS3_NAND is not set
++# CONFIG_AST_CS3_SPI is not set
++# CONFIG_AST_CS3_NONE is not set
++CONFIG_AST_CS4_NOR=y
++# CONFIG_AST_CS4_NAND is not set
++# CONFIG_AST_CS4_SPI is not set
++# CONFIG_AST_CS4_NONE is not set
++# CONFIG_ARCH_AST1070 is not set
++# CONFIG_AST_SCU_LOCK is not set
++
++#
++# Boot options
++#
++
++#
++# Power management
++#
++CONFIG_PLAT_ASPEED=y
++
++#
++# Processor Type
++#
++CONFIG_CPU_32=y
++CONFIG_CPU_ARM926T=y
++CONFIG_CPU_32v5=y
++CONFIG_CPU_ABRT_EV5TJ=y
++CONFIG_CPU_PABRT_NOIFAR=y
++CONFIG_CPU_CACHE_VIVT=y
++CONFIG_CPU_COPY_V4WB=y
++CONFIG_CPU_TLB_V4WBI=y
++CONFIG_CPU_CP15=y
++CONFIG_CPU_CP15_MMU=y
++
++#
++# Processor Features
++#
++CONFIG_ARM_THUMB=y
++# CONFIG_CPU_ICACHE_DISABLE is not set
++# CONFIG_CPU_DCACHE_DISABLE is not set
++# CONFIG_CPU_DCACHE_WRITETHROUGH is not set
++# CONFIG_CPU_CACHE_ROUND_ROBIN is not set
++# CONFIG_OUTER_CACHE is not set
++
++#
++# Bus support
++#
++CONFIG_ARM_AMBA=y
++# CONFIG_PCI_SYSCALL is not set
++# CONFIG_ARCH_SUPPORTS_MSI is not set
++# CONFIG_PCCARD is not set
++
++#
++# Kernel Features
++#
++CONFIG_VMSPLIT_3G=y
++# CONFIG_VMSPLIT_2G is not set
++# CONFIG_VMSPLIT_1G is not set
++CONFIG_PAGE_OFFSET=0xC0000000
++# CONFIG_PREEMPT is not set
++CONFIG_HZ=100
++# CONFIG_AEABI is not set
++CONFIG_ARCH_FLATMEM_HAS_HOLES=y
++# CONFIG_ARCH_SPARSEMEM_DEFAULT is not set
++# CONFIG_ARCH_SELECT_MEMORY_MODEL is not set
++CONFIG_SELECT_MEMORY_MODEL=y
++CONFIG_FLATMEM_MANUAL=y
++# CONFIG_DISCONTIGMEM_MANUAL is not set
++# CONFIG_SPARSEMEM_MANUAL is not set
++CONFIG_FLATMEM=y
++CONFIG_FLAT_NODE_MEM_MAP=y
++CONFIG_PAGEFLAGS_EXTENDED=y
++CONFIG_SPLIT_PTLOCK_CPUS=4096
++# CONFIG_RESOURCES_64BIT is not set
++# CONFIG_PHYS_ADDR_T_64BIT is not set
++CONFIG_ZONE_DMA_FLAG=0
++CONFIG_VIRT_TO_BUS=y
++CONFIG_UNEVICTABLE_LRU=y
++CONFIG_ALIGNMENT_TRAP=y
++
++#
++# Boot options
++#
++CONFIG_ZBOOT_ROM_TEXT=0
++CONFIG_ZBOOT_ROM_BSS=0
++CONFIG_CMDLINE=""
++# CONFIG_XIP_KERNEL is not set
++# CONFIG_KEXEC is not set
++
++#
++# CPU Power Management
++#
++# CONFIG_CPU_IDLE is not set
++
++#
++# Floating point emulation
++#
++
++#
++# At least one emulation must be selected
++#
++CONFIG_FPE_NWFPE=y
++CONFIG_FPE_NWFPE_XP=y
++# CONFIG_FPE_FASTFPE is not set
++# CONFIG_VFP is not set
++
++#
++# Userspace binary formats
++#
++CONFIG_BINFMT_ELF=y
++# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
++CONFIG_HAVE_AOUT=y
++CONFIG_BINFMT_AOUT=y
++# CONFIG_BINFMT_MISC is not set
++# CONFIG_ARTHUR is not set
++
++#
++# Power management options
++#
++CONFIG_PM=y
++# CONFIG_PM_DEBUG is not set
++CONFIG_PM_SLEEP=y
++CONFIG_SUSPEND=y
++CONFIG_SUSPEND_FREEZER=y
++# CONFIG_APM_EMULATION is not set
++CONFIG_ARCH_SUSPEND_POSSIBLE=y
++CONFIG_NET=y
++
++#
++# Networking options
++#
++CONFIG_PACKET=y
++# CONFIG_PACKET_MMAP is not set
++CONFIG_UNIX=y
++CONFIG_XFRM=y
++# CONFIG_XFRM_USER is not set
++# CONFIG_XFRM_SUB_POLICY is not set
++# CONFIG_XFRM_MIGRATE is not set
++# CONFIG_XFRM_STATISTICS is not set
++CONFIG_XFRM_IPCOMP=m
++# CONFIG_NET_KEY is not set
++CONFIG_INET=y
++CONFIG_IP_MULTICAST=y
++# CONFIG_IP_ADVANCED_ROUTER is not set
++CONFIG_IP_FIB_HASH=y
++CONFIG_IP_PNP=y
++CONFIG_IP_PNP_DHCP=y
++CONFIG_IP_PNP_BOOTP=y
++# CONFIG_IP_PNP_RARP is not set
++# CONFIG_NET_IPIP is not set
++# CONFIG_NET_IPGRE is not set
++# CONFIG_IP_MROUTE is not set
++# CONFIG_ARPD is not set
++# CONFIG_SYN_COOKIES is not set
++# CONFIG_INET_AH is not set
++# CONFIG_INET_ESP is not set
++# CONFIG_INET_IPCOMP is not set
++# CONFIG_INET_XFRM_TUNNEL is not set
++CONFIG_INET_TUNNEL=m
++CONFIG_INET_XFRM_MODE_TRANSPORT=y
++CONFIG_INET_XFRM_MODE_TUNNEL=y
++CONFIG_INET_XFRM_MODE_BEET=y
++# CONFIG_INET_LRO is not set
++CONFIG_INET_DIAG=y
++CONFIG_INET_TCP_DIAG=y
++# CONFIG_TCP_CONG_ADVANCED is not set
++CONFIG_TCP_CONG_CUBIC=y
++CONFIG_DEFAULT_TCP_CONG="cubic"
++# CONFIG_TCP_MD5SIG is not set
++CONFIG_IPV6=m
++CONFIG_IPV6_PRIVACY=y
++CONFIG_IPV6_ROUTER_PREF=y
++CONFIG_IPV6_ROUTE_INFO=y
++CONFIG_IPV6_OPTIMISTIC_DAD=y
++CONFIG_INET6_AH=m
++CONFIG_INET6_ESP=m
++CONFIG_INET6_IPCOMP=m
++CONFIG_IPV6_MIP6=m
++CONFIG_INET6_XFRM_TUNNEL=m
++CONFIG_INET6_TUNNEL=m
++CONFIG_INET6_XFRM_MODE_TRANSPORT=m
++CONFIG_INET6_XFRM_MODE_TUNNEL=m
++CONFIG_INET6_XFRM_MODE_BEET=m
++CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION=m
++CONFIG_IPV6_SIT=m
++CONFIG_IPV6_NDISC_NODETYPE=y
++CONFIG_IPV6_TUNNEL=m
++CONFIG_IPV6_MULTIPLE_TABLES=y
++CONFIG_IPV6_SUBTREES=y
++# CONFIG_IPV6_MROUTE is not set
++# CONFIG_NETWORK_SECMARK is not set
++# CONFIG_NETFILTER is not set
++# CONFIG_IP_DCCP is not set
++# CONFIG_IP_SCTP is not set
++# CONFIG_TIPC is not set
++# CONFIG_ATM is not set
++# CONFIG_BRIDGE is not set
++# CONFIG_NET_DSA is not set
++# CONFIG_VLAN_8021Q is not set
++# CONFIG_DECNET is not set
++# CONFIG_LLC2 is not set
++# CONFIG_IPX is not set
++# CONFIG_ATALK is not set
++# CONFIG_X25 is not set
++# CONFIG_LAPB is not set
++# CONFIG_ECONET is not set
++CONFIG_WAN_ROUTER=y
++# CONFIG_NET_SCHED is not set
++
++#
++# Network testing
++#
++# CONFIG_NET_PKTGEN is not set
++# CONFIG_HAMRADIO is not set
++# CONFIG_CAN is not set
++# CONFIG_IRDA is not set
++# CONFIG_BT is not set
++# CONFIG_AF_RXRPC is not set
++# CONFIG_PHONET is not set
++CONFIG_FIB_RULES=y
++# CONFIG_WIRELESS is not set
++# CONFIG_RFKILL is not set
++# CONFIG_NET_9P is not set
++
++#
++# Device Drivers
++#
++
++#
++# Generic Driver Options
++#
++CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
++CONFIG_STANDALONE=y
++CONFIG_PREVENT_FIRMWARE_BUILD=y
++CONFIG_FW_LOADER=y
++CONFIG_FIRMWARE_IN_KERNEL=y
++CONFIG_EXTRA_FIRMWARE=""
++# CONFIG_SYS_HYPERVISOR is not set
++CONFIG_CONNECTOR=y
++CONFIG_PROC_EVENTS=y
++CONFIG_MTD=y
++# CONFIG_MTD_DEBUG is not set
++CONFIG_MTD_CONCAT=y
++CONFIG_MTD_PARTITIONS=y
++# CONFIG_MTD_REDBOOT_PARTS is not set
++# CONFIG_MTD_CMDLINE_PARTS is not set
++# CONFIG_MTD_AFS_PARTS is not set
++# CONFIG_MTD_AR7_PARTS is not set
++
++#
++# User Modules And Translation Layers
++#
++CONFIG_MTD_CHAR=y
++CONFIG_MTD_BLKDEVS=y
++CONFIG_MTD_BLOCK=y
++# CONFIG_FTL is not set
++# CONFIG_NFTL is not set
++# CONFIG_INFTL is not set
++# CONFIG_RFD_FTL is not set
++# CONFIG_SSFDC is not set
++# CONFIG_MTD_OOPS is not set
++
++#
++# RAM/ROM/Flash chip drivers
++#
++# CONFIG_MTD_CFI is not set
++# CONFIG_MTD_JEDECPROBE is not set
++CONFIG_MTD_MAP_BANK_WIDTH_1=y
++CONFIG_MTD_MAP_BANK_WIDTH_2=y
++CONFIG_MTD_MAP_BANK_WIDTH_4=y
++# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
++# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
++# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
++CONFIG_MTD_CFI_I1=y
++CONFIG_MTD_CFI_I2=y
++# CONFIG_MTD_CFI_I4 is not set
++# CONFIG_MTD_CFI_I8 is not set
++# CONFIG_MTD_RAM is not set
++# CONFIG_MTD_ROM is not set
++# CONFIG_MTD_ABSENT is not set
++
++#
++# Mapping drivers for chip access
++#
++# CONFIG_MTD_COMPLEX_MAPPINGS is not set
++# CONFIG_MTD_PLATRAM is not set
++
++#
++# Self-contained MTD device drivers
++#
++CONFIG_MTD_DATAFLASH=y
++# CONFIG_MTD_DATAFLASH_WRITE_VERIFY is not set
++# CONFIG_MTD_DATAFLASH_OTP is not set
++CONFIG_MTD_M25P80=y
++CONFIG_M25PXX_USE_FAST_READ=y
++# CONFIG_MTD_SLRAM is not set
++# CONFIG_MTD_PHRAM is not set
++# CONFIG_MTD_MTDRAM is not set
++# CONFIG_MTD_BLOCK2MTD is not set
++
++#
++# Disk-On-Chip Device Drivers
++#
++# CONFIG_MTD_DOC2000 is not set
++# CONFIG_MTD_DOC2001 is not set
++# CONFIG_MTD_DOC2001PLUS is not set
++CONFIG_MTD_NAND=y
++# CONFIG_MTD_NAND_VERIFY_WRITE is not set
++# CONFIG_MTD_NAND_ECC_SMC is not set
++# CONFIG_MTD_NAND_MUSEUM_IDS is not set
++CONFIG_MTD_NAND_AST=y
++# CONFIG_MTD_NAND_GPIO is not set
++CONFIG_MTD_NAND_IDS=y
++# CONFIG_MTD_NAND_DISKONCHIP is not set
++# CONFIG_MTD_NAND_NANDSIM is not set
++# CONFIG_MTD_NAND_PLATFORM is not set
++# CONFIG_MTD_ALAUDA is not set
++# CONFIG_MTD_ONENAND is not set
++
++#
++# UBI - Unsorted block images
++#
++# CONFIG_MTD_UBI is not set
++# CONFIG_PARPORT is not set
++CONFIG_BLK_DEV=y
++# CONFIG_BLK_DEV_COW_COMMON is not set
++CONFIG_BLK_DEV_LOOP=y
++# CONFIG_BLK_DEV_CRYPTOLOOP is not set
++CONFIG_BLK_DEV_NBD=m
++# CONFIG_BLK_DEV_UB is not set
++CONFIG_BLK_DEV_RAM=y
++CONFIG_BLK_DEV_RAM_COUNT=16
++CONFIG_BLK_DEV_RAM_SIZE=16384
++# CONFIG_BLK_DEV_XIP is not set
++# CONFIG_CDROM_PKTCDVD is not set
++# CONFIG_ATA_OVER_ETH is not set
++CONFIG_MISC_DEVICES=y
++# CONFIG_EEPROM_93CX6 is not set
++# CONFIG_ICS932S401 is not set
++# CONFIG_ENCLOSURE_SERVICES is not set
++# CONFIG_C2PORT is not set
++CONFIG_HAVE_IDE=y
++# CONFIG_IDE is not set
++
++#
++# SCSI device support
++#
++# CONFIG_RAID_ATTRS is not set
++CONFIG_SCSI=y
++CONFIG_SCSI_DMA=y
++CONFIG_SCSI_TGT=y
++# CONFIG_SCSI_NETLINK is not set
++CONFIG_SCSI_PROC_FS=y
++
++#
++# SCSI support type (disk, tape, CD-ROM)
++#
++CONFIG_BLK_DEV_SD=y
++# CONFIG_CHR_DEV_ST is not set
++# CONFIG_CHR_DEV_OSST is not set
++# CONFIG_BLK_DEV_SR is not set
++CONFIG_CHR_DEV_SG=y
++# CONFIG_CHR_DEV_SCH is not set
++
++#
++# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
++#
++# CONFIG_SCSI_MULTI_LUN is not set
++# CONFIG_SCSI_CONSTANTS is not set
++# CONFIG_SCSI_LOGGING is not set
++CONFIG_SCSI_SCAN_ASYNC=y
++CONFIG_SCSI_WAIT_SCAN=m
++
++#
++# SCSI Transports
++#
++# CONFIG_SCSI_SPI_ATTRS is not set
++# CONFIG_SCSI_FC_ATTRS is not set
++CONFIG_SCSI_ISCSI_ATTRS=m
++# CONFIG_SCSI_SAS_LIBSAS is not set
++# CONFIG_SCSI_SRP_ATTRS is not set
++# CONFIG_SCSI_LOWLEVEL is not set
++# CONFIG_SCSI_DH is not set
++# CONFIG_ATA is not set
++# CONFIG_MD is not set
++CONFIG_NETDEVICES=y
++# CONFIG_DUMMY is not set
++CONFIG_BONDING=y
++# CONFIG_MACVLAN is not set
++# CONFIG_EQUALIZER is not set
++# CONFIG_TUN is not set
++# CONFIG_VETH is not set
++# CONFIG_NET_ETHERNET is not set
++CONFIG_NETDEV_1000=y
++CONFIG_ASPEEDMAC=y
++CONFIG_MAC0_PHY_LINK=y
++# CONFIG_NETDEV_10000 is not set
++
++#
++# Wireless LAN
++#
++# CONFIG_WLAN_PRE80211 is not set
++# CONFIG_WLAN_80211 is not set
++# CONFIG_IWLWIFI_LEDS is not set
++
++#
++# USB Network Adapters
++#
++# CONFIG_USB_CATC is not set
++# CONFIG_USB_KAWETH is not set
++# CONFIG_USB_PEGASUS is not set
++# CONFIG_USB_RTL8150 is not set
++# CONFIG_USB_USBNET is not set
++# CONFIG_WAN is not set
++# CONFIG_PPP is not set
++# CONFIG_SLIP is not set
++# CONFIG_NETCONSOLE is not set
++# CONFIG_NETPOLL is not set
++# CONFIG_NET_POLL_CONTROLLER is not set
++# CONFIG_ISDN is not set
++
++#
++# Input device support
++#
++CONFIG_INPUT=y
++# CONFIG_INPUT_FF_MEMLESS is not set
++# CONFIG_INPUT_POLLDEV is not set
++
++#
++# Userland interfaces
++#
++CONFIG_INPUT_MOUSEDEV=y
++CONFIG_INPUT_MOUSEDEV_PSAUX=y
++CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
++CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
++# CONFIG_INPUT_JOYDEV is not set
++CONFIG_INPUT_EVDEV=y
++# CONFIG_INPUT_EVBUG is not set
++
++#
++# Input Device Drivers
++#
++CONFIG_INPUT_KEYBOARD=y
++CONFIG_KEYBOARD_ATKBD=y
++# CONFIG_KEYBOARD_SUNKBD is not set
++# CONFIG_KEYBOARD_LKKBD is not set
++# CONFIG_KEYBOARD_XTKBD is not set
++# CONFIG_KEYBOARD_NEWTON is not set
++# CONFIG_KEYBOARD_STOWAWAY is not set
++# CONFIG_KEYBOARD_GPIO is not set
++CONFIG_INPUT_MOUSE=y
++CONFIG_MOUSE_PS2=y
++CONFIG_MOUSE_PS2_ALPS=y
++CONFIG_MOUSE_PS2_LOGIPS2PP=y
++CONFIG_MOUSE_PS2_SYNAPTICS=y
++CONFIG_MOUSE_PS2_LIFEBOOK=y
++CONFIG_MOUSE_PS2_TRACKPOINT=y
++# CONFIG_MOUSE_PS2_ELANTECH is not set
++# CONFIG_MOUSE_PS2_TOUCHKIT is not set
++CONFIG_MOUSE_SERIAL=y
++# CONFIG_MOUSE_APPLETOUCH is not set
++# CONFIG_MOUSE_BCM5974 is not set
++# CONFIG_MOUSE_VSXXXAA is not set
++# CONFIG_MOUSE_GPIO is not set
++# CONFIG_INPUT_JOYSTICK is not set
++# CONFIG_INPUT_TABLET is not set
++# CONFIG_INPUT_TOUCHSCREEN is not set
++# CONFIG_INPUT_MISC is not set
++
++#
++# Hardware I/O ports
++#
++CONFIG_SERIO=y
++CONFIG_SERIO_SERPORT=y
++# CONFIG_SERIO_AMBAKMI is not set
++CONFIG_SERIO_LIBPS2=y
++# CONFIG_SERIO_RAW is not set
++# CONFIG_GAMEPORT is not set
++
++#
++# Character devices
++#
++CONFIG_VT=y
++CONFIG_CONSOLE_TRANSLATIONS=y
++CONFIG_VT_CONSOLE=y
++CONFIG_HW_CONSOLE=y
++# CONFIG_VT_HW_CONSOLE_BINDING is not set
++CONFIG_DEVKMEM=y
++CONFIG_SERIAL_NONSTANDARD=y
++# CONFIG_N_HDLC is not set
++# CONFIG_RISCOM8 is not set
++# CONFIG_SPECIALIX is not set
++# CONFIG_RIO is not set
++# CONFIG_STALDRV is not set
++
++#
++# Serial drivers
++#
++CONFIG_SERIAL_8250=y
++CONFIG_SERIAL_8250_CONSOLE=y
++CONFIG_SERIAL_8250_NR_UARTS=2
++CONFIG_SERIAL_8250_RUNTIME_UARTS=2
++# CONFIG_SERIAL_AST_DMA_UART is not set
++# CONFIG_SERIAL_8250_EXTENDED is not set
++
++#
++# Non-8250 serial port support
++#
++# CONFIG_SERIAL_AMBA_PL010 is not set
++# CONFIG_SERIAL_AMBA_PL011 is not set
++# CONFIG_SERIAL_AST is not set
++CONFIG_SERIAL_CORE=y
++CONFIG_SERIAL_CORE_CONSOLE=y
++CONFIG_UNIX98_PTYS=y
++CONFIG_LEGACY_PTYS=y
++CONFIG_LEGACY_PTY_COUNT=256
++# CONFIG_IPMI_HANDLER is not set
++# CONFIG_AST_MISC is not set
++# CONFIG_HW_RANDOM is not set
++CONFIG_NVRAM=y
++# CONFIG_R3964 is not set
++# CONFIG_RAW_DRIVER is not set
++# CONFIG_TCG_TPM is not set
++CONFIG_I2C=y
++CONFIG_I2C_BOARDINFO=y
++CONFIG_I2C_CHARDEV=y
++CONFIG_I2C_HELPER_AUTO=y
++
++#
++# I2C Hardware Bus support
++#
++
++#
++# I2C system bus drivers (mostly embedded / system-on-chip)
++#
++# CONFIG_I2C_GPIO is not set
++# CONFIG_I2C_OCORES is not set
++# CONFIG_I2C_AST is not set
++# CONFIG_I2C_SIMTEC is not set
++
++#
++# External I2C/SMBus adapter drivers
++#
++# CONFIG_I2C_PARPORT_LIGHT is not set
++# CONFIG_I2C_TAOS_EVM is not set
++# CONFIG_I2C_TINY_USB is not set
++
++#
++# Other I2C/SMBus bus drivers
++#
++# CONFIG_I2C_PCA_PLATFORM is not set
++# CONFIG_I2C_STUB is not set
++
++#
++# Miscellaneous I2C Chip support
++#
++# CONFIG_DS1682 is not set
++CONFIG_AT24=y
++# CONFIG_SENSORS_EEPROM is not set
++# CONFIG_SENSORS_PCF8574 is not set
++# CONFIG_PCF8575 is not set
++# CONFIG_SENSORS_PCA9539 is not set
++# CONFIG_SENSORS_PCF8591 is not set
++# CONFIG_TPS65010 is not set
++# CONFIG_SENSORS_MAX6875 is not set
++# CONFIG_SENSORS_TSL2550 is not set
++# CONFIG_I2C_DEBUG_CORE is not set
++# CONFIG_I2C_DEBUG_ALGO is not set
++# CONFIG_I2C_DEBUG_BUS is not set
++# CONFIG_I2C_DEBUG_CHIP is not set
++CONFIG_SPI=y
++CONFIG_SPI_MASTER=y
++
++#
++# SPI Master Controller Drivers
++#
++# CONFIG_SPI_AST is not set
++CONFIG_SPI_FMC=y
++CONFIG_SPI_BITBANG=y
++
++#
++# SPI Protocol Masters
++#
++# CONFIG_SPI_AT25 is not set
++# CONFIG_SPI_SPIDEV is not set
++# CONFIG_SPI_TLE62X0 is not set
++CONFIG_ARCH_REQUIRE_GPIOLIB=y
++CONFIG_GPIOLIB=y
++CONFIG_GPIO_SYSFS=y
++
++#
++# Memory mapped GPIO expanders:
++#
++
++#
++# I2C GPIO expanders:
++#
++# CONFIG_GPIO_MAX732X is not set
++# CONFIG_GPIO_PCA953X is not set
++# CONFIG_GPIO_PCF857X is not set
++
++#
++# PCI GPIO expanders:
++#
++
++#
++# SPI GPIO expanders:
++#
++# CONFIG_GPIO_MAX7301 is not set
++# CONFIG_GPIO_MCP23S08 is not set
++# CONFIG_W1 is not set
++# CONFIG_POWER_SUPPLY is not set
++CONFIG_HWMON=y
++# CONFIG_HWMON_VID is not set
++# CONFIG_SENSORS_AD7414 is not set
++# CONFIG_SENSORS_AD7418 is not set
++# CONFIG_SENSORS_ADCXX is not set
++# CONFIG_SENSORS_ADM1021 is not set
++# CONFIG_SENSORS_ADM1025 is not set
++# CONFIG_SENSORS_ADM1026 is not set
++# CONFIG_SENSORS_ADM1029 is not set
++# CONFIG_SENSORS_ADM1031 is not set
++# CONFIG_SENSORS_ADM9240 is not set
++# CONFIG_SENSORS_ADT7462 is not set
++# CONFIG_SENSORS_ADT7470 is not set
++# CONFIG_SENSORS_ADT7473 is not set
++# CONFIG_SENSORS_ATXP1 is not set
++# CONFIG_SENSORS_DS1621 is not set
++# CONFIG_SENSORS_F71805F is not set
++# CONFIG_SENSORS_F71882FG is not set
++# CONFIG_SENSORS_F75375S is not set
++# CONFIG_SENSORS_GL518SM is not set
++# CONFIG_SENSORS_GL520SM is not set
++# CONFIG_SENSORS_IT87 is not set
++# CONFIG_SENSORS_LM63 is not set
++# CONFIG_SENSORS_LM70 is not set
++# CONFIG_SENSORS_LM75 is not set
++# CONFIG_SENSORS_LM77 is not set
++# CONFIG_SENSORS_LM78 is not set
++# CONFIG_SENSORS_LM80 is not set
++# CONFIG_SENSORS_LM83 is not set
++# CONFIG_SENSORS_LM85 is not set
++# CONFIG_SENSORS_LM87 is not set
++# CONFIG_SENSORS_LM90 is not set
++# CONFIG_SENSORS_LM92 is not set
++# CONFIG_SENSORS_LM93 is not set
++# CONFIG_SENSORS_MAX1111 is not set
++# CONFIG_SENSORS_MAX1619 is not set
++# CONFIG_SENSORS_MAX6650 is not set
++# CONFIG_SENSORS_PC87360 is not set
++# CONFIG_SENSORS_PC87427 is not set
++# CONFIG_SENSORS_DME1737 is not set
++# CONFIG_SENSORS_SMSC47M1 is not set
++# CONFIG_SENSORS_SMSC47M192 is not set
++# CONFIG_SENSORS_SMSC47B397 is not set
++# CONFIG_SENSORS_ADS7828 is not set
++# CONFIG_SENSORS_THMC50 is not set
++# CONFIG_SENSORS_VT1211 is not set
++# CONFIG_SENSORS_W83781D is not set
++# CONFIG_SENSORS_W83791D is not set
++# CONFIG_SENSORS_W83792D is not set
++# CONFIG_SENSORS_W83793 is not set
++# CONFIG_SENSORS_W83L785TS is not set
++# CONFIG_SENSORS_W83L786NG is not set
++# CONFIG_SENSORS_W83627HF is not set
++# CONFIG_SENSORS_W83627EHF is not set
++# CONFIG_SENSORS_AST_ADC is not set
++CONFIG_SENSORS_AST_PWM_FAN=y
++# CONFIG_HWMON_DEBUG_CHIP is not set
++# CONFIG_THERMAL is not set
++# CONFIG_THERMAL_HWMON is not set
++CONFIG_WATCHDOG=y
++# CONFIG_WATCHDOG_NOWAYOUT is not set
++
++#
++# Watchdog Device Drivers
++#
++# CONFIG_SOFT_WATCHDOG is not set
++# CONFIG_AST_WATCHDOG is not set
++
++#
++# USB-based Watchdog Cards
++#
++# CONFIG_USBPCWATCHDOG is not set
++CONFIG_SSB_POSSIBLE=y
++
++#
++# Sonics Silicon Backplane
++#
++# CONFIG_SSB is not set
++
++#
++# Multifunction device drivers
++#
++# CONFIG_MFD_CORE is not set
++# CONFIG_MFD_SM501 is not set
++# CONFIG_MFD_ASIC3 is not set
++# CONFIG_HTC_EGPIO is not set
++# CONFIG_HTC_PASIC3 is not set
++# CONFIG_MFD_TMIO is not set
++# CONFIG_MFD_TC6393XB is not set
++# CONFIG_PMIC_DA903X is not set
++# CONFIG_MFD_WM8400 is not set
++# CONFIG_MFD_WM8350_I2C is not set
++
++#
++# Multimedia devices
++#
++
++#
++# Multimedia core support
++#
++# CONFIG_VIDEO_DEV is not set
++# CONFIG_DVB_CORE is not set
++# CONFIG_VIDEO_MEDIA is not set
++
++#
++# Multimedia drivers
++#
++# CONFIG_DAB is not set
++
++#
++# Graphics support
++#
++# CONFIG_VGASTATE is not set
++# CONFIG_VIDEO_OUTPUT_CONTROL is not set
++# CONFIG_FB is not set
++# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
++
++#
++# Display device support
++#
++# CONFIG_DISPLAY_SUPPORT is not set
++
++#
++# Console display driver support
++#
++# CONFIG_VGA_CONSOLE is not set
++CONFIG_DUMMY_CONSOLE=y
++# CONFIG_SOUND is not set
++CONFIG_HID_SUPPORT=y
++CONFIG_HID=y
++CONFIG_HID_DEBUG=y
++# CONFIG_HIDRAW is not set
++
++#
++# USB Input Devices
++#
++CONFIG_USB_HID=y
++# CONFIG_HID_PID is not set
++# CONFIG_USB_HIDDEV is not set
++
++#
++# Special HID drivers
++#
++CONFIG_HID_COMPAT=y
++CONFIG_HID_A4TECH=y
++CONFIG_HID_APPLE=y
++CONFIG_HID_BELKIN=y
++CONFIG_HID_BRIGHT=y
++CONFIG_HID_CHERRY=y
++CONFIG_HID_CHICONY=y
++CONFIG_HID_CYPRESS=y
++CONFIG_HID_DELL=y
++CONFIG_HID_EZKEY=y
++CONFIG_HID_GYRATION=y
++CONFIG_HID_LOGITECH=y
++# CONFIG_LOGITECH_FF is not set
++# CONFIG_LOGIRUMBLEPAD2_FF is not set
++CONFIG_HID_MICROSOFT=y
++CONFIG_HID_MONTEREY=y
++CONFIG_HID_PANTHERLORD=y
++# CONFIG_PANTHERLORD_FF is not set
++CONFIG_HID_PETALYNX=y
++CONFIG_HID_SAMSUNG=y
++CONFIG_HID_SONY=y
++CONFIG_HID_SUNPLUS=y
++# CONFIG_THRUSTMASTER_FF is not set
++# CONFIG_ZEROPLUS_FF is not set
++CONFIG_USB_SUPPORT=y
++CONFIG_USB_ARCH_HAS_HCD=y
++# CONFIG_USB_ARCH_HAS_OHCI is not set
++CONFIG_USB_ARCH_HAS_EHCI=y
++CONFIG_USB=y
++# CONFIG_USB_DEBUG is not set
++# CONFIG_USB_ANNOUNCE_NEW_DEVICES is not set
++
++#
++# Miscellaneous USB options
++#
++CONFIG_USB_DEVICEFS=y
++CONFIG_USB_DEVICE_CLASS=y
++# CONFIG_USB_DYNAMIC_MINORS is not set
++# CONFIG_USB_SUSPEND is not set
++# CONFIG_USB_OTG is not set
++# CONFIG_USB_MON is not set
++# CONFIG_USB_WUSB is not set
++# CONFIG_USB_WUSB_CBAF is not set
++
++#
++# USB Host Controller Drivers
++#
++# CONFIG_USB_C67X00_HCD is not set
++# CONFIG_USB_EHCI_HCD is not set
++# CONFIG_USB_ISP116X_HCD is not set
++# CONFIG_USB_SL811_HCD is not set
++# CONFIG_USB_R8A66597_HCD is not set
++# CONFIG_USB_HWA_HCD is not set
++
++#
++# AST USB Drivers
++#
++CONFIG_AST_USB_UHCI_HCD=y
++# CONFIG_AST_USB_UHCI_MULTIPORT_1 is not set
++# CONFIG_AST_USB_UHCI_MULTIPORT_2 is not set
++CONFIG_AST_USB_UHCI_MULTIPORT_4=y
++
++#
++# USB Device Class drivers
++#
++# CONFIG_USB_ACM is not set
++# CONFIG_USB_PRINTER is not set
++# CONFIG_USB_WDM is not set
++# CONFIG_USB_TMC is not set
++
++#
++# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may also be needed;
++#
++
++#
++# see USB_STORAGE Help for more information
++#
++CONFIG_USB_STORAGE=y
++# CONFIG_USB_STORAGE_DEBUG is not set
++# CONFIG_USB_STORAGE_DATAFAB is not set
++# CONFIG_USB_STORAGE_FREECOM is not set
++# CONFIG_USB_STORAGE_ISD200 is not set
++# CONFIG_USB_STORAGE_DPCM is not set
++# CONFIG_USB_STORAGE_USBAT is not set
++# CONFIG_USB_STORAGE_SDDR09 is not set
++# CONFIG_USB_STORAGE_SDDR55 is not set
++# CONFIG_USB_STORAGE_JUMPSHOT is not set
++# CONFIG_USB_STORAGE_ALAUDA is not set
++# CONFIG_USB_STORAGE_ONETOUCH is not set
++# CONFIG_USB_STORAGE_KARMA is not set
++# CONFIG_USB_STORAGE_CYPRESS_ATACB is not set
++# CONFIG_USB_LIBUSUAL is not set
++
++#
++# USB Imaging devices
++#
++# CONFIG_USB_MDC800 is not set
++# CONFIG_USB_MICROTEK is not set
++
++#
++# USB port drivers
++#
++# CONFIG_USB_SERIAL is not set
++
++#
++# USB Miscellaneous drivers
++#
++# CONFIG_USB_EMI62 is not set
++# CONFIG_USB_EMI26 is not set
++# CONFIG_USB_ADUTUX is not set
++# CONFIG_USB_SEVSEG is not set
++# CONFIG_USB_RIO500 is not set
++# CONFIG_USB_LEGOTOWER is not set
++# CONFIG_USB_LCD is not set
++# CONFIG_USB_BERRY_CHARGE is not set
++# CONFIG_USB_LED is not set
++# CONFIG_USB_CYPRESS_CY7C63 is not set
++# CONFIG_USB_CYTHERM is not set
++# CONFIG_USB_PHIDGET is not set
++# CONFIG_USB_IDMOUSE is not set
++# CONFIG_USB_FTDI_ELAN is not set
++# CONFIG_USB_APPLEDISPLAY is not set
++# CONFIG_USB_LD is not set
++# CONFIG_USB_TRANCEVIBRATOR is not set
++# CONFIG_USB_IOWARRIOR is not set
++# CONFIG_USB_TEST is not set
++# CONFIG_USB_ISIGHTFW is not set
++# CONFIG_USB_VST is not set
++# CONFIG_USB_GADGET is not set
++CONFIG_MMC=y
++# CONFIG_MMC_DEBUG is not set
++# CONFIG_MMC_UNSAFE_RESUME is not set
++
++#
++# MMC/SD/SDIO Card Drivers
++#
++CONFIG_MMC_BLOCK=y
++CONFIG_MMC_BLOCK_BOUNCE=y
++# CONFIG_SDIO_UART is not set
++# CONFIG_MMC_TEST is not set
++
++#
++# MMC/SD/SDIO Host Controller Drivers
++#
++# CONFIG_MMC_ARMMMCI is not set
++# CONFIG_MMC_SDHCI is not set
++# CONFIG_MMC_AST is not set
++# CONFIG_MMC_SPI is not set
++# CONFIG_MEMSTICK is not set
++# CONFIG_ACCESSIBILITY is not set
++# CONFIG_NEW_LEDS is not set
++CONFIG_RTC_LIB=y
++CONFIG_RTC_CLASS=y
++# CONFIG_RTC_HCTOSYS is not set
++# CONFIG_RTC_DEBUG is not set
++
++#
++# RTC interfaces
++#
++CONFIG_RTC_INTF_SYSFS=y
++CONFIG_RTC_INTF_PROC=y
++CONFIG_RTC_INTF_DEV=y
++# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set
++# CONFIG_RTC_DRV_TEST is not set
++
++#
++# I2C RTC drivers
++#
++# CONFIG_RTC_DRV_DS1307 is not set
++# CONFIG_RTC_DRV_DS1374 is not set
++# CONFIG_RTC_DRV_DS1672 is not set
++# CONFIG_RTC_DRV_MAX6900 is not set
++# CONFIG_RTC_DRV_RS5C372 is not set
++# CONFIG_RTC_DRV_ISL1208 is not set
++# CONFIG_RTC_DRV_X1205 is not set
++# CONFIG_RTC_DRV_PCF8563 is not set
++# CONFIG_RTC_DRV_PCF8583 is not set
++# CONFIG_RTC_DRV_M41T80 is not set
++# CONFIG_RTC_DRV_S35390A is not set
++# CONFIG_RTC_DRV_FM3130 is not set
++# CONFIG_RTC_DRV_RX8581 is not set
++
++#
++# SPI RTC drivers
++#
++# CONFIG_RTC_DRV_M41T94 is not set
++# CONFIG_RTC_DRV_DS1305 is not set
++# CONFIG_RTC_DRV_DS1390 is not set
++# CONFIG_RTC_DRV_MAX6902 is not set
++# CONFIG_RTC_DRV_R9701 is not set
++# CONFIG_RTC_DRV_RS5C348 is not set
++# CONFIG_RTC_DRV_DS3234 is not set
++
++#
++# Platform RTC drivers
++#
++# CONFIG_RTC_DRV_CMOS is not set
++# CONFIG_RTC_DRV_DS1286 is not set
++# CONFIG_RTC_DRV_DS1511 is not set
++# CONFIG_RTC_DRV_DS1553 is not set
++# CONFIG_RTC_DRV_DS1742 is not set
++# CONFIG_RTC_DRV_STK17TA8 is not set
++# CONFIG_RTC_DRV_M48T86 is not set
++# CONFIG_RTC_DRV_M48T35 is not set
++# CONFIG_RTC_DRV_M48T59 is not set
++# CONFIG_RTC_DRV_BQ4802 is not set
++# CONFIG_RTC_DRV_V3020 is not set
++
++#
++# on-CPU RTC drivers
++#
++# CONFIG_RTC_DRV_PL030 is not set
++# CONFIG_RTC_DRV_PL031 is not set
++CONFIG_RTC_DRV_ASPEED=y
++# CONFIG_DMADEVICES is not set
++# CONFIG_REGULATOR is not set
++# CONFIG_UIO is not set
++
++#
++# File systems
++#
++CONFIG_EXT2_FS=y
++CONFIG_EXT2_FS_XATTR=y
++CONFIG_EXT2_FS_POSIX_ACL=y
++CONFIG_EXT2_FS_SECURITY=y
++# CONFIG_EXT2_FS_XIP is not set
++# CONFIG_EXT3_FS is not set
++# CONFIG_EXT4_FS is not set
++CONFIG_FS_MBCACHE=y
++# CONFIG_REISERFS_FS is not set
++# CONFIG_JFS_FS is not set
++CONFIG_FS_POSIX_ACL=y
++CONFIG_FILE_LOCKING=y
++# CONFIG_XFS_FS is not set
++# CONFIG_OCFS2_FS is not set
++CONFIG_DNOTIFY=y
++CONFIG_INOTIFY=y
++CONFIG_INOTIFY_USER=y
++# CONFIG_QUOTA is not set
++# CONFIG_AUTOFS_FS is not set
++# CONFIG_AUTOFS4_FS is not set
++# CONFIG_FUSE_FS is not set
++CONFIG_GENERIC_ACL=y
++
++#
++# CD-ROM/DVD Filesystems
++#
++# CONFIG_ISO9660_FS is not set
++# CONFIG_UDF_FS is not set
++
++#
++# DOS/FAT/NT Filesystems
++#
++CONFIG_FAT_FS=y
++CONFIG_MSDOS_FS=y
++CONFIG_VFAT_FS=y
++CONFIG_FAT_DEFAULT_CODEPAGE=437
++CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
++CONFIG_NTFS_FS=y
++# CONFIG_NTFS_DEBUG is not set
++CONFIG_NTFS_RW=y
++
++#
++# Pseudo filesystems
++#
++CONFIG_PROC_FS=y
++CONFIG_PROC_SYSCTL=y
++CONFIG_PROC_PAGE_MONITOR=y
++CONFIG_SYSFS=y
++CONFIG_TMPFS=y
++CONFIG_TMPFS_POSIX_ACL=y
++# CONFIG_HUGETLB_PAGE is not set
++CONFIG_CONFIGFS_FS=m
++
++#
++# Miscellaneous filesystems
++#
++# CONFIG_ADFS_FS is not set
++# CONFIG_AFFS_FS is not set
++# CONFIG_HFS_FS is not set
++# CONFIG_HFSPLUS_FS is not set
++# CONFIG_BEFS_FS is not set
++# CONFIG_BFS_FS is not set
++# CONFIG_EFS_FS is not set
++CONFIG_YAFFS_FS=y
++CONFIG_YAFFS_YAFFS1=y
++# CONFIG_YAFFS_9BYTE_TAGS is not set
++# CONFIG_YAFFS_DOES_ECC is not set
++CONFIG_YAFFS_YAFFS2=y
++CONFIG_YAFFS_AUTO_YAFFS2=y
++# CONFIG_YAFFS_DISABLE_TAGS_ECC is not set
++# CONFIG_YAFFS_DISABLE_LAZY_LOAD is not set
++# CONFIG_YAFFS_DISABLE_WIDE_TNODES is not set
++# CONFIG_YAFFS_ALWAYS_CHECK_CHUNK_ERASED is not set
++CONFIG_YAFFS_SHORT_NAMES_IN_RAM=y
++# CONFIG_YAFFS_EMPTY_LOST_AND_FOUND is not set
++# CONFIG_JFFS2_FS is not set
++# CONFIG_CRAMFS is not set
++# CONFIG_VXFS_FS is not set
++# CONFIG_MINIX_FS is not set
++# CONFIG_OMFS_FS is not set
++# CONFIG_HPFS_FS is not set
++# CONFIG_QNX4FS_FS is not set
++# CONFIG_ROMFS_FS is not set
++# CONFIG_SYSV_FS is not set
++# CONFIG_UFS_FS is not set
++CONFIG_NETWORK_FILESYSTEMS=y
++CONFIG_NFS_FS=y
++# CONFIG_NFS_V3 is not set
++# CONFIG_NFS_V4 is not set
++CONFIG_ROOT_NFS=y
++# CONFIG_NFSD is not set
++CONFIG_LOCKD=y
++CONFIG_NFS_COMMON=y
++CONFIG_SUNRPC=y
++# CONFIG_SUNRPC_REGISTER_V4 is not set
++# CONFIG_RPCSEC_GSS_KRB5 is not set
++# CONFIG_RPCSEC_GSS_SPKM3 is not set
++# CONFIG_SMB_FS is not set
++# CONFIG_CIFS is not set
++# CONFIG_NCP_FS is not set
++# CONFIG_CODA_FS is not set
++# CONFIG_AFS_FS is not set
++
++#
++# Partition Types
++#
++# CONFIG_PARTITION_ADVANCED is not set
++CONFIG_MSDOS_PARTITION=y
++CONFIG_NLS=y
++CONFIG_NLS_DEFAULT="utf8"
++CONFIG_NLS_CODEPAGE_437=y
++# CONFIG_NLS_CODEPAGE_737 is not set
++# CONFIG_NLS_CODEPAGE_775 is not set
++# CONFIG_NLS_CODEPAGE_850 is not set
++# CONFIG_NLS_CODEPAGE_852 is not set
++# CONFIG_NLS_CODEPAGE_855 is not set
++# CONFIG_NLS_CODEPAGE_857 is not set
++# CONFIG_NLS_CODEPAGE_860 is not set
++# CONFIG_NLS_CODEPAGE_861 is not set
++# CONFIG_NLS_CODEPAGE_862 is not set
++# CONFIG_NLS_CODEPAGE_863 is not set
++# CONFIG_NLS_CODEPAGE_864 is not set
++# CONFIG_NLS_CODEPAGE_865 is not set
++# CONFIG_NLS_CODEPAGE_866 is not set
++# CONFIG_NLS_CODEPAGE_869 is not set
++CONFIG_NLS_CODEPAGE_936=y
++CONFIG_NLS_CODEPAGE_950=y
++CONFIG_NLS_CODEPAGE_932=y
++# CONFIG_NLS_CODEPAGE_949 is not set
++# CONFIG_NLS_CODEPAGE_874 is not set
++# CONFIG_NLS_ISO8859_8 is not set
++# CONFIG_NLS_CODEPAGE_1250 is not set
++# CONFIG_NLS_CODEPAGE_1251 is not set
++CONFIG_NLS_ASCII=y
++CONFIG_NLS_ISO8859_1=y
++# CONFIG_NLS_ISO8859_2 is not set
++# CONFIG_NLS_ISO8859_3 is not set
++# CONFIG_NLS_ISO8859_4 is not set
++# CONFIG_NLS_ISO8859_5 is not set
++# CONFIG_NLS_ISO8859_6 is not set
++# CONFIG_NLS_ISO8859_7 is not set
++# CONFIG_NLS_ISO8859_9 is not set
++# CONFIG_NLS_ISO8859_13 is not set
++# CONFIG_NLS_ISO8859_14 is not set
++# CONFIG_NLS_ISO8859_15 is not set
++# CONFIG_NLS_KOI8_R is not set
++# CONFIG_NLS_KOI8_U is not set
++CONFIG_NLS_UTF8=y
++# CONFIG_DLM is not set
++
++#
++# Kernel hacking
++#
++# CONFIG_PRINTK_TIME is not set
++# CONFIG_ENABLE_WARN_DEPRECATED is not set
++CONFIG_ENABLE_MUST_CHECK=y
++CONFIG_FRAME_WARN=1024
++CONFIG_MAGIC_SYSRQ=y
++# CONFIG_UNUSED_SYMBOLS is not set
++# CONFIG_DEBUG_FS is not set
++# CONFIG_HEADERS_CHECK is not set
++# CONFIG_DEBUG_KERNEL is not set
++# CONFIG_SLUB_DEBUG_ON is not set
++# CONFIG_SLUB_STATS is not set
++CONFIG_DEBUG_BUGVERBOSE=y
++CONFIG_DEBUG_MEMORY_INIT=y
++CONFIG_FRAME_POINTER=y
++# CONFIG_RCU_CPU_STALL_DETECTOR is not set
++# CONFIG_LATENCYTOP is not set
++# CONFIG_SYSCTL_SYSCALL_CHECK is not set
++CONFIG_HAVE_FUNCTION_TRACER=y
++
++#
++# Tracers
++#
++# CONFIG_DYNAMIC_PRINTK_DEBUG is not set
++# CONFIG_SAMPLES is not set
++CONFIG_HAVE_ARCH_KGDB=y
++# CONFIG_DEBUG_USER is not set
++
++#
++# Security options
++#
++# CONFIG_KEYS is not set
++# CONFIG_SECURITY is not set
++# CONFIG_SECURITYFS is not set
++# CONFIG_SECURITY_FILE_CAPABILITIES is not set
++CONFIG_CRYPTO=y
++
++#
++# Crypto core or helper
++#
++# CONFIG_CRYPTO_FIPS is not set
++CONFIG_CRYPTO_ALGAPI=y
++CONFIG_CRYPTO_ALGAPI2=y
++CONFIG_CRYPTO_AEAD=m
++CONFIG_CRYPTO_AEAD2=y
++CONFIG_CRYPTO_BLKCIPHER=y
++CONFIG_CRYPTO_BLKCIPHER2=y
++CONFIG_CRYPTO_HASH=y
++CONFIG_CRYPTO_HASH2=y
++CONFIG_CRYPTO_RNG2=y
++CONFIG_CRYPTO_MANAGER=y
++CONFIG_CRYPTO_MANAGER2=y
++# CONFIG_CRYPTO_GF128MUL is not set
++CONFIG_CRYPTO_NULL=y
++# CONFIG_CRYPTO_CRYPTD is not set
++CONFIG_CRYPTO_AUTHENC=m
++# CONFIG_CRYPTO_TEST is not set
++
++#
++# Authenticated Encryption with Associated Data
++#
++# CONFIG_CRYPTO_CCM is not set
++# CONFIG_CRYPTO_GCM is not set
++# CONFIG_CRYPTO_SEQIV is not set
++
++#
++# Block modes
++#
++CONFIG_CRYPTO_CBC=y
++# CONFIG_CRYPTO_CTR is not set
++# CONFIG_CRYPTO_CTS is not set
++# CONFIG_CRYPTO_ECB is not set
++# CONFIG_CRYPTO_LRW is not set
++# CONFIG_CRYPTO_PCBC is not set
++# CONFIG_CRYPTO_XTS is not set
++
++#
++# Hash modes
++#
++CONFIG_CRYPTO_HMAC=y
++# CONFIG_CRYPTO_XCBC is not set
++
++#
++# Digest
++#
++# CONFIG_CRYPTO_CRC32C is not set
++# CONFIG_CRYPTO_MD4 is not set
++CONFIG_CRYPTO_MD5=y
++# CONFIG_CRYPTO_MICHAEL_MIC is not set
++# CONFIG_CRYPTO_RMD128 is not set
++# CONFIG_CRYPTO_RMD160 is not set
++# CONFIG_CRYPTO_RMD256 is not set
++# CONFIG_CRYPTO_RMD320 is not set
++CONFIG_CRYPTO_SHA1=y
++# CONFIG_CRYPTO_SHA256 is not set
++# CONFIG_CRYPTO_SHA512 is not set
++# CONFIG_CRYPTO_TGR192 is not set
++# CONFIG_CRYPTO_WP512 is not set
++
++#
++# Ciphers
++#
++# CONFIG_CRYPTO_AES is not set
++# CONFIG_CRYPTO_ANUBIS is not set
++# CONFIG_CRYPTO_ARC4 is not set
++# CONFIG_CRYPTO_BLOWFISH is not set
++# CONFIG_CRYPTO_CAMELLIA is not set
++# CONFIG_CRYPTO_CAST5 is not set
++# CONFIG_CRYPTO_CAST6 is not set
++CONFIG_CRYPTO_DES=y
++# CONFIG_CRYPTO_FCRYPT is not set
++# CONFIG_CRYPTO_KHAZAD is not set
++# CONFIG_CRYPTO_SALSA20 is not set
++# CONFIG_CRYPTO_SEED is not set
++# CONFIG_CRYPTO_SERPENT is not set
++# CONFIG_CRYPTO_TEA is not set
++# CONFIG_CRYPTO_TWOFISH is not set
++
++#
++# Compression
++#
++CONFIG_CRYPTO_DEFLATE=m
++# CONFIG_CRYPTO_LZO is not set
++
++#
++# Random Number Generation
++#
++# CONFIG_CRYPTO_ANSI_CPRNG is not set
++# CONFIG_CRYPTO_HW is not set
++
++#
++# Library routines
++#
++CONFIG_BITREVERSE=y
++# CONFIG_CRC_CCITT is not set
++# CONFIG_CRC16 is not set
++# CONFIG_CRC_T10DIF is not set
++CONFIG_CRC_ITU_T=m
++CONFIG_CRC32=y
++# CONFIG_CRC7 is not set
++# CONFIG_LIBCRC32C is not set
++CONFIG_ZLIB_INFLATE=m
++CONFIG_ZLIB_DEFLATE=m
++CONFIG_PLIST=y
++CONFIG_HAS_IOMEM=y
++CONFIG_HAS_IOPORT=y
++CONFIG_HAS_DMA=y
+diff --git a/arch/arm/configs/ast2300_fb_defconfig b/arch/arm/configs/ast2300_fb_defconfig
+new file mode 100644
+index 0000000..817e089
+--- /dev/null
++++ b/arch/arm/configs/ast2300_fb_defconfig
+@@ -0,0 +1,1514 @@
++#
++# Automatically generated make config: don't edit
++# Linux kernel version: 2.6.28.9
++# Thu Jan 10 10:44:05 2013
++#
++CONFIG_ARM=y
++CONFIG_SYS_SUPPORTS_APM_EMULATION=y
++CONFIG_GENERIC_GPIO=y
++# CONFIG_GENERIC_TIME is not set
++# CONFIG_GENERIC_CLOCKEVENTS is not set
++CONFIG_MMU=y
++# CONFIG_NO_IOPORT is not set
++CONFIG_GENERIC_HARDIRQS=y
++CONFIG_STACKTRACE_SUPPORT=y
++CONFIG_HAVE_LATENCYTOP_SUPPORT=y
++CONFIG_LOCKDEP_SUPPORT=y
++CONFIG_TRACE_IRQFLAGS_SUPPORT=y
++CONFIG_HARDIRQS_SW_RESEND=y
++CONFIG_GENERIC_IRQ_PROBE=y
++CONFIG_RWSEM_GENERIC_SPINLOCK=y
++# CONFIG_ARCH_HAS_ILOG2_U32 is not set
++# CONFIG_ARCH_HAS_ILOG2_U64 is not set
++CONFIG_GENERIC_HWEIGHT=y
++CONFIG_GENERIC_CALIBRATE_DELAY=y
++CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
++CONFIG_VECTORS_BASE=0xffff0000
++CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
++
++#
++# General setup
++#
++CONFIG_EXPERIMENTAL=y
++CONFIG_BROKEN_ON_SMP=y
++CONFIG_INIT_ENV_ARG_LIMIT=32
++CONFIG_LOCALVERSION=""
++# CONFIG_LOCALVERSION_AUTO is not set
++CONFIG_SWAP=y
++CONFIG_SYSVIPC=y
++CONFIG_SYSVIPC_SYSCTL=y
++# CONFIG_POSIX_MQUEUE is not set
++# CONFIG_BSD_PROCESS_ACCT is not set
++# CONFIG_TASKSTATS is not set
++# CONFIG_AUDIT is not set
++# CONFIG_IKCONFIG is not set
++CONFIG_LOG_BUF_SHIFT=16
++# CONFIG_CGROUPS is not set
++# CONFIG_GROUP_SCHED is not set
++CONFIG_SYSFS_DEPRECATED=y
++CONFIG_SYSFS_DEPRECATED_V2=y
++# CONFIG_RELAY is not set
++CONFIG_NAMESPACES=y
++# CONFIG_UTS_NS is not set
++# CONFIG_IPC_NS is not set
++# CONFIG_USER_NS is not set
++# CONFIG_PID_NS is not set
++CONFIG_BLK_DEV_INITRD=y
++CONFIG_INITRAMFS_SOURCE=""
++CONFIG_CC_OPTIMIZE_FOR_SIZE=y
++CONFIG_SYSCTL=y
++CONFIG_ANON_INODES=y
++# CONFIG_EMBEDDED is not set
++CONFIG_UID16=y
++CONFIG_SYSCTL_SYSCALL=y
++CONFIG_KALLSYMS=y
++CONFIG_KALLSYMS_EXTRA_PASS=y
++CONFIG_HOTPLUG=y
++CONFIG_PRINTK=y
++CONFIG_BUG=y
++CONFIG_ELF_CORE=y
++CONFIG_BASE_FULL=y
++CONFIG_FUTEX=y
++CONFIG_EPOLL=y
++CONFIG_SIGNALFD=y
++CONFIG_TIMERFD=y
++CONFIG_EVENTFD=y
++CONFIG_SHMEM=y
++CONFIG_AIO=y
++CONFIG_VM_EVENT_COUNTERS=y
++CONFIG_SLUB_DEBUG=y
++CONFIG_COMPAT_BRK=y
++# CONFIG_SLAB is not set
++CONFIG_SLUB=y
++# CONFIG_SLOB is not set
++# CONFIG_PROFILING is not set
++# CONFIG_MARKERS is not set
++CONFIG_HAVE_OPROFILE=y
++# CONFIG_KPROBES is not set
++CONFIG_HAVE_KPROBES=y
++CONFIG_HAVE_KRETPROBES=y
++CONFIG_HAVE_GENERIC_DMA_COHERENT=y
++CONFIG_SLABINFO=y
++CONFIG_RT_MUTEXES=y
++# CONFIG_TINY_SHMEM is not set
++CONFIG_BASE_SMALL=0
++CONFIG_MODULES=y
++# CONFIG_MODULE_FORCE_LOAD is not set
++CONFIG_MODULE_UNLOAD=y
++# CONFIG_MODULE_FORCE_UNLOAD is not set
++# CONFIG_MODVERSIONS is not set
++# CONFIG_MODULE_SRCVERSION_ALL is not set
++CONFIG_KMOD=y
++CONFIG_BLOCK=y
++# CONFIG_LBD is not set
++# CONFIG_BLK_DEV_IO_TRACE is not set
++# CONFIG_LSF is not set
++# CONFIG_BLK_DEV_BSG is not set
++# CONFIG_BLK_DEV_INTEGRITY is not set
++
++#
++# IO Schedulers
++#
++CONFIG_IOSCHED_NOOP=y
++CONFIG_IOSCHED_AS=y
++CONFIG_IOSCHED_DEADLINE=y
++CONFIG_IOSCHED_CFQ=y
++# CONFIG_DEFAULT_AS is not set
++# CONFIG_DEFAULT_DEADLINE is not set
++CONFIG_DEFAULT_CFQ=y
++# CONFIG_DEFAULT_NOOP is not set
++CONFIG_DEFAULT_IOSCHED="cfq"
++CONFIG_CLASSIC_RCU=y
++CONFIG_FREEZER=y
++
++#
++# System Type
++#
++CONFIG_ARCH_ASPEED=y
++# CONFIG_ARCH_AAEC2000 is not set
++# CONFIG_ARCH_INTEGRATOR is not set
++# CONFIG_ARCH_REALVIEW is not set
++# CONFIG_ARCH_VERSATILE is not set
++# CONFIG_ARCH_AT91 is not set
++# CONFIG_ARCH_CLPS7500 is not set
++# CONFIG_ARCH_CLPS711X is not set
++# CONFIG_ARCH_EBSA110 is not set
++# CONFIG_ARCH_EP93XX is not set
++# CONFIG_ARCH_FOOTBRIDGE is not set
++# CONFIG_ARCH_NETX is not set
++# CONFIG_ARCH_H720X is not set
++# CONFIG_ARCH_IMX is not set
++# CONFIG_ARCH_IOP13XX is not set
++# CONFIG_ARCH_IOP32X is not set
++# CONFIG_ARCH_IOP33X is not set
++# CONFIG_ARCH_IXP23XX is not set
++# CONFIG_ARCH_IXP2000 is not set
++# CONFIG_ARCH_IXP4XX is not set
++# CONFIG_ARCH_L7200 is not set
++# CONFIG_ARCH_KIRKWOOD is not set
++# CONFIG_ARCH_KS8695 is not set
++# CONFIG_ARCH_NS9XXX is not set
++# CONFIG_ARCH_LOKI is not set
++# CONFIG_ARCH_MV78XX0 is not set
++# CONFIG_ARCH_MXC is not set
++# CONFIG_ARCH_ORION5X is not set
++# CONFIG_ARCH_PNX4008 is not set
++# CONFIG_ARCH_PXA is not set
++# CONFIG_ARCH_RPC is not set
++# CONFIG_ARCH_SA1100 is not set
++# CONFIG_ARCH_S3C2410 is not set
++# CONFIG_ARCH_SHARK is not set
++# CONFIG_ARCH_LH7A40X is not set
++# CONFIG_ARCH_DAVINCI is not set
++# CONFIG_ARCH_OMAP is not set
++# CONFIG_ARCH_MSM is not set
++CONFIG_IRMP=y
++# CONFIG_PCEXT is not set
++# CONFIG_REMOTEFX is not set
++# CONFIG_ARCH_AST1100 is not set
++# CONFIG_ARCH_AST2100 is not set
++# CONFIG_ARCH_AST2200 is not set
++CONFIG_ARCH_AST2300=y
++# CONFIG_ARCH_AST2400 is not set
++
++#
++# FLASH Chip Select
++#
++# CONFIG_ASPEED_CS0_NOR is not set
++# CONFIG_ASPEED_CS0_NAND is not set
++CONFIG_ASPEED_CS0_SPI=y
++# CONFIG_ASPEED_CS0_NONE is not set
++# CONFIG_ASPEED_CS1_NOR is not set
++# CONFIG_ASPEED_CS1_NAND is not set
++# CONFIG_ASPEED_CS1_SPI is not set
++CONFIG_ASPEED_CS1_NONE=y
++# CONFIG_ASPEED_CS2_NOR is not set
++# CONFIG_ASPEED_CS2_NAND is not set
++# CONFIG_ASPEED_CS2_SPI is not set
++CONFIG_ASPEED_CS2_NONE=y
++# CONFIG_ASPEED_CS3_NOR is not set
++# CONFIG_ASPEED_CS3_NAND is not set
++# CONFIG_ASPEED_CS3_SPI is not set
++CONFIG_ASPEED_CS3_NONE=y
++# CONFIG_ASPEED_CS4_NOR is not set
++CONFIG_ASPEED_CS4_NAND=y
++# CONFIG_ASPEED_CS4_SPI is not set
++# CONFIG_ASPEED_CS4_NONE is not set
++# CONFIG_ARCH_AST1070 is not set
++# CONFIG_ASPEED_SCU_LOCK is not set
++
++#
++# Boot options
++#
++
++#
++# Power management
++#
++CONFIG_PLAT_ASPEED=y
++
++#
++# Processor Type
++#
++CONFIG_CPU_32=y
++CONFIG_CPU_ARM926T=y
++CONFIG_CPU_32v5=y
++CONFIG_CPU_ABRT_EV5TJ=y
++CONFIG_CPU_PABRT_NOIFAR=y
++CONFIG_CPU_CACHE_VIVT=y
++CONFIG_CPU_COPY_V4WB=y
++CONFIG_CPU_TLB_V4WBI=y
++CONFIG_CPU_CP15=y
++CONFIG_CPU_CP15_MMU=y
++
++#
++# Processor Features
++#
++CONFIG_ARM_THUMB=y
++# CONFIG_CPU_ICACHE_DISABLE is not set
++# CONFIG_CPU_DCACHE_DISABLE is not set
++# CONFIG_CPU_DCACHE_WRITETHROUGH is not set
++# CONFIG_CPU_CACHE_ROUND_ROBIN is not set
++# CONFIG_OUTER_CACHE is not set
++
++#
++# Bus support
++#
++CONFIG_ARM_AMBA=y
++# CONFIG_PCI_SYSCALL is not set
++# CONFIG_ARCH_SUPPORTS_MSI is not set
++# CONFIG_PCCARD is not set
++
++#
++# Kernel Features
++#
++CONFIG_VMSPLIT_3G=y
++# CONFIG_VMSPLIT_2G is not set
++# CONFIG_VMSPLIT_1G is not set
++CONFIG_PAGE_OFFSET=0xC0000000
++# CONFIG_PREEMPT is not set
++CONFIG_HZ=100
++# CONFIG_AEABI is not set
++CONFIG_ARCH_FLATMEM_HAS_HOLES=y
++# CONFIG_ARCH_SPARSEMEM_DEFAULT is not set
++# CONFIG_ARCH_SELECT_MEMORY_MODEL is not set
++CONFIG_SELECT_MEMORY_MODEL=y
++CONFIG_FLATMEM_MANUAL=y
++# CONFIG_DISCONTIGMEM_MANUAL is not set
++# CONFIG_SPARSEMEM_MANUAL is not set
++CONFIG_FLATMEM=y
++CONFIG_FLAT_NODE_MEM_MAP=y
++CONFIG_PAGEFLAGS_EXTENDED=y
++CONFIG_SPLIT_PTLOCK_CPUS=4096
++# CONFIG_RESOURCES_64BIT is not set
++# CONFIG_PHYS_ADDR_T_64BIT is not set
++CONFIG_ZONE_DMA_FLAG=0
++CONFIG_VIRT_TO_BUS=y
++CONFIG_UNEVICTABLE_LRU=y
++CONFIG_ALIGNMENT_TRAP=y
++
++#
++# Boot options
++#
++CONFIG_ZBOOT_ROM_TEXT=0
++CONFIG_ZBOOT_ROM_BSS=0
++CONFIG_CMDLINE=""
++# CONFIG_XIP_KERNEL is not set
++# CONFIG_KEXEC is not set
++
++#
++# CPU Power Management
++#
++# CONFIG_CPU_IDLE is not set
++
++#
++# Floating point emulation
++#
++
++#
++# At least one emulation must be selected
++#
++CONFIG_FPE_NWFPE=y
++CONFIG_FPE_NWFPE_XP=y
++# CONFIG_FPE_FASTFPE is not set
++# CONFIG_VFP is not set
++
++#
++# Userspace binary formats
++#
++CONFIG_BINFMT_ELF=y
++# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
++CONFIG_HAVE_AOUT=y
++CONFIG_BINFMT_AOUT=y
++# CONFIG_BINFMT_MISC is not set
++# CONFIG_ARTHUR is not set
++
++#
++# Power management options
++#
++CONFIG_PM=y
++# CONFIG_PM_DEBUG is not set
++CONFIG_PM_SLEEP=y
++CONFIG_SUSPEND=y
++CONFIG_SUSPEND_FREEZER=y
++# CONFIG_APM_EMULATION is not set
++CONFIG_ARCH_SUSPEND_POSSIBLE=y
++CONFIG_NET=y
++
++#
++# Networking options
++#
++CONFIG_PACKET=y
++# CONFIG_PACKET_MMAP is not set
++CONFIG_UNIX=y
++CONFIG_XFRM=y
++# CONFIG_XFRM_USER is not set
++# CONFIG_XFRM_SUB_POLICY is not set
++# CONFIG_XFRM_MIGRATE is not set
++# CONFIG_XFRM_STATISTICS is not set
++CONFIG_XFRM_IPCOMP=m
++# CONFIG_NET_KEY is not set
++CONFIG_INET=y
++CONFIG_IP_MULTICAST=y
++# CONFIG_IP_ADVANCED_ROUTER is not set
++CONFIG_IP_FIB_HASH=y
++CONFIG_IP_PNP=y
++CONFIG_IP_PNP_DHCP=y
++CONFIG_IP_PNP_BOOTP=y
++# CONFIG_IP_PNP_RARP is not set
++# CONFIG_NET_IPIP is not set
++# CONFIG_NET_IPGRE is not set
++# CONFIG_IP_MROUTE is not set
++# CONFIG_ARPD is not set
++# CONFIG_SYN_COOKIES is not set
++# CONFIG_INET_AH is not set
++# CONFIG_INET_ESP is not set
++# CONFIG_INET_IPCOMP is not set
++# CONFIG_INET_XFRM_TUNNEL is not set
++CONFIG_INET_TUNNEL=m
++CONFIG_INET_XFRM_MODE_TRANSPORT=y
++CONFIG_INET_XFRM_MODE_TUNNEL=y
++CONFIG_INET_XFRM_MODE_BEET=y
++# CONFIG_INET_LRO is not set
++CONFIG_INET_DIAG=y
++CONFIG_INET_TCP_DIAG=y
++# CONFIG_TCP_CONG_ADVANCED is not set
++CONFIG_TCP_CONG_CUBIC=y
++CONFIG_DEFAULT_TCP_CONG="cubic"
++# CONFIG_TCP_MD5SIG is not set
++CONFIG_IPV6=m
++CONFIG_IPV6_PRIVACY=y
++CONFIG_IPV6_ROUTER_PREF=y
++CONFIG_IPV6_ROUTE_INFO=y
++CONFIG_IPV6_OPTIMISTIC_DAD=y
++CONFIG_INET6_AH=m
++CONFIG_INET6_ESP=m
++CONFIG_INET6_IPCOMP=m
++CONFIG_IPV6_MIP6=m
++CONFIG_INET6_XFRM_TUNNEL=m
++CONFIG_INET6_TUNNEL=m
++CONFIG_INET6_XFRM_MODE_TRANSPORT=m
++CONFIG_INET6_XFRM_MODE_TUNNEL=m
++CONFIG_INET6_XFRM_MODE_BEET=m
++CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION=m
++CONFIG_IPV6_SIT=m
++CONFIG_IPV6_NDISC_NODETYPE=y
++CONFIG_IPV6_TUNNEL=m
++CONFIG_IPV6_MULTIPLE_TABLES=y
++CONFIG_IPV6_SUBTREES=y
++# CONFIG_IPV6_MROUTE is not set
++# CONFIG_NETWORK_SECMARK is not set
++# CONFIG_NETFILTER is not set
++# CONFIG_IP_DCCP is not set
++# CONFIG_IP_SCTP is not set
++# CONFIG_TIPC is not set
++# CONFIG_ATM is not set
++# CONFIG_BRIDGE is not set
++# CONFIG_NET_DSA is not set
++# CONFIG_VLAN_8021Q is not set
++# CONFIG_DECNET is not set
++# CONFIG_LLC2 is not set
++# CONFIG_IPX is not set
++# CONFIG_ATALK is not set
++# CONFIG_X25 is not set
++# CONFIG_LAPB is not set
++# CONFIG_ECONET is not set
++CONFIG_WAN_ROUTER=y
++# CONFIG_NET_SCHED is not set
++
++#
++# Network testing
++#
++# CONFIG_NET_PKTGEN is not set
++# CONFIG_HAMRADIO is not set
++# CONFIG_CAN is not set
++# CONFIG_IRDA is not set
++# CONFIG_BT is not set
++# CONFIG_AF_RXRPC is not set
++# CONFIG_PHONET is not set
++CONFIG_FIB_RULES=y
++# CONFIG_WIRELESS is not set
++# CONFIG_RFKILL is not set
++# CONFIG_NET_9P is not set
++
++#
++# Device Drivers
++#
++
++#
++# Generic Driver Options
++#
++CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
++CONFIG_STANDALONE=y
++CONFIG_PREVENT_FIRMWARE_BUILD=y
++CONFIG_FW_LOADER=y
++CONFIG_FIRMWARE_IN_KERNEL=y
++CONFIG_EXTRA_FIRMWARE=""
++# CONFIG_SYS_HYPERVISOR is not set
++CONFIG_CONNECTOR=y
++CONFIG_PROC_EVENTS=y
++CONFIG_MTD=y
++# CONFIG_MTD_DEBUG is not set
++CONFIG_MTD_CONCAT=y
++CONFIG_MTD_PARTITIONS=y
++# CONFIG_MTD_REDBOOT_PARTS is not set
++# CONFIG_MTD_CMDLINE_PARTS is not set
++# CONFIG_MTD_AFS_PARTS is not set
++# CONFIG_MTD_AR7_PARTS is not set
++
++#
++# User Modules And Translation Layers
++#
++CONFIG_MTD_CHAR=y
++CONFIG_MTD_BLKDEVS=y
++CONFIG_MTD_BLOCK=y
++# CONFIG_FTL is not set
++# CONFIG_NFTL is not set
++# CONFIG_INFTL is not set
++# CONFIG_RFD_FTL is not set
++# CONFIG_SSFDC is not set
++# CONFIG_MTD_OOPS is not set
++
++#
++# RAM/ROM/Flash chip drivers
++#
++# CONFIG_MTD_CFI is not set
++# CONFIG_MTD_JEDECPROBE is not set
++CONFIG_MTD_MAP_BANK_WIDTH_1=y
++CONFIG_MTD_MAP_BANK_WIDTH_2=y
++CONFIG_MTD_MAP_BANK_WIDTH_4=y
++# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
++# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
++# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
++CONFIG_MTD_CFI_I1=y
++CONFIG_MTD_CFI_I2=y
++# CONFIG_MTD_CFI_I4 is not set
++# CONFIG_MTD_CFI_I8 is not set
++# CONFIG_MTD_RAM is not set
++# CONFIG_MTD_ROM is not set
++# CONFIG_MTD_ABSENT is not set
++
++#
++# Mapping drivers for chip access
++#
++# CONFIG_MTD_COMPLEX_MAPPINGS is not set
++# CONFIG_MTD_PLATRAM is not set
++
++#
++# Self-contained MTD device drivers
++#
++CONFIG_MTD_DATAFLASH=y
++# CONFIG_MTD_DATAFLASH_WRITE_VERIFY is not set
++# CONFIG_MTD_DATAFLASH_OTP is not set
++CONFIG_MTD_M25P80=y
++CONFIG_M25PXX_USE_FAST_READ=y
++# CONFIG_MTD_SLRAM is not set
++# CONFIG_MTD_PHRAM is not set
++# CONFIG_MTD_MTDRAM is not set
++# CONFIG_MTD_BLOCK2MTD is not set
++
++#
++# Disk-On-Chip Device Drivers
++#
++# CONFIG_MTD_DOC2000 is not set
++# CONFIG_MTD_DOC2001 is not set
++# CONFIG_MTD_DOC2001PLUS is not set
++CONFIG_MTD_NAND=y
++# CONFIG_MTD_NAND_VERIFY_WRITE is not set
++# CONFIG_MTD_NAND_ECC_SMC is not set
++# CONFIG_MTD_NAND_MUSEUM_IDS is not set
++CONFIG_MTD_NAND_AST=y
++# CONFIG_MTD_NAND_GPIO is not set
++CONFIG_MTD_NAND_IDS=y
++# CONFIG_MTD_NAND_DISKONCHIP is not set
++# CONFIG_MTD_NAND_NANDSIM is not set
++# CONFIG_MTD_NAND_PLATFORM is not set
++# CONFIG_MTD_ALAUDA is not set
++# CONFIG_MTD_ONENAND is not set
++
++#
++# UBI - Unsorted block images
++#
++# CONFIG_MTD_UBI is not set
++# CONFIG_PARPORT is not set
++CONFIG_BLK_DEV=y
++# CONFIG_BLK_DEV_COW_COMMON is not set
++CONFIG_BLK_DEV_LOOP=y
++# CONFIG_BLK_DEV_CRYPTOLOOP is not set
++CONFIG_BLK_DEV_NBD=m
++# CONFIG_BLK_DEV_UB is not set
++CONFIG_BLK_DEV_RAM=y
++CONFIG_BLK_DEV_RAM_COUNT=16
++CONFIG_BLK_DEV_RAM_SIZE=16384
++# CONFIG_BLK_DEV_XIP is not set
++# CONFIG_CDROM_PKTCDVD is not set
++# CONFIG_ATA_OVER_ETH is not set
++CONFIG_MISC_DEVICES=y
++# CONFIG_EEPROM_93CX6 is not set
++# CONFIG_ICS932S401 is not set
++# CONFIG_ENCLOSURE_SERVICES is not set
++# CONFIG_C2PORT is not set
++CONFIG_HAVE_IDE=y
++# CONFIG_IDE is not set
++
++#
++# SCSI device support
++#
++# CONFIG_RAID_ATTRS is not set
++CONFIG_SCSI=y
++CONFIG_SCSI_DMA=y
++CONFIG_SCSI_TGT=y
++# CONFIG_SCSI_NETLINK is not set
++CONFIG_SCSI_PROC_FS=y
++
++#
++# SCSI support type (disk, tape, CD-ROM)
++#
++CONFIG_BLK_DEV_SD=y
++# CONFIG_CHR_DEV_ST is not set
++# CONFIG_CHR_DEV_OSST is not set
++# CONFIG_BLK_DEV_SR is not set
++CONFIG_CHR_DEV_SG=y
++# CONFIG_CHR_DEV_SCH is not set
++
++#
++# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
++#
++# CONFIG_SCSI_MULTI_LUN is not set
++# CONFIG_SCSI_CONSTANTS is not set
++# CONFIG_SCSI_LOGGING is not set
++CONFIG_SCSI_SCAN_ASYNC=y
++CONFIG_SCSI_WAIT_SCAN=m
++
++#
++# SCSI Transports
++#
++# CONFIG_SCSI_SPI_ATTRS is not set
++# CONFIG_SCSI_FC_ATTRS is not set
++CONFIG_SCSI_ISCSI_ATTRS=m
++# CONFIG_SCSI_SAS_LIBSAS is not set
++# CONFIG_SCSI_SRP_ATTRS is not set
++# CONFIG_SCSI_LOWLEVEL is not set
++# CONFIG_SCSI_DH is not set
++# CONFIG_ATA is not set
++# CONFIG_MD is not set
++CONFIG_NETDEVICES=y
++# CONFIG_DUMMY is not set
++CONFIG_BONDING=y
++# CONFIG_MACVLAN is not set
++# CONFIG_EQUALIZER is not set
++# CONFIG_TUN is not set
++# CONFIG_VETH is not set
++# CONFIG_NET_ETHERNET is not set
++CONFIG_NETDEV_1000=y
++CONFIG_ASPEEDMAC=y
++CONFIG_MAC0_PHY_LINK=y
++# CONFIG_NETDEV_10000 is not set
++
++#
++# Wireless LAN
++#
++# CONFIG_WLAN_PRE80211 is not set
++# CONFIG_WLAN_80211 is not set
++# CONFIG_IWLWIFI_LEDS is not set
++
++#
++# USB Network Adapters
++#
++# CONFIG_USB_CATC is not set
++# CONFIG_USB_KAWETH is not set
++# CONFIG_USB_PEGASUS is not set
++# CONFIG_USB_RTL8150 is not set
++# CONFIG_USB_USBNET is not set
++# CONFIG_WAN is not set
++# CONFIG_PPP is not set
++# CONFIG_SLIP is not set
++# CONFIG_NETCONSOLE is not set
++# CONFIG_NETPOLL is not set
++# CONFIG_NET_POLL_CONTROLLER is not set
++# CONFIG_ISDN is not set
++
++#
++# Input device support
++#
++CONFIG_INPUT=y
++# CONFIG_INPUT_FF_MEMLESS is not set
++# CONFIG_INPUT_POLLDEV is not set
++
++#
++# Userland interfaces
++#
++CONFIG_INPUT_MOUSEDEV=y
++CONFIG_INPUT_MOUSEDEV_PSAUX=y
++CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
++CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
++# CONFIG_INPUT_JOYDEV is not set
++CONFIG_INPUT_EVDEV=y
++# CONFIG_INPUT_EVBUG is not set
++
++#
++# Input Device Drivers
++#
++CONFIG_INPUT_KEYBOARD=y
++CONFIG_KEYBOARD_ATKBD=y
++# CONFIG_KEYBOARD_SUNKBD is not set
++# CONFIG_KEYBOARD_LKKBD is not set
++# CONFIG_KEYBOARD_XTKBD is not set
++# CONFIG_KEYBOARD_NEWTON is not set
++# CONFIG_KEYBOARD_STOWAWAY is not set
++# CONFIG_KEYBOARD_GPIO is not set
++CONFIG_INPUT_MOUSE=y
++CONFIG_MOUSE_PS2=y
++CONFIG_MOUSE_PS2_ALPS=y
++CONFIG_MOUSE_PS2_LOGIPS2PP=y
++CONFIG_MOUSE_PS2_SYNAPTICS=y
++CONFIG_MOUSE_PS2_LIFEBOOK=y
++CONFIG_MOUSE_PS2_TRACKPOINT=y
++# CONFIG_MOUSE_PS2_ELANTECH is not set
++# CONFIG_MOUSE_PS2_TOUCHKIT is not set
++CONFIG_MOUSE_SERIAL=y
++# CONFIG_MOUSE_APPLETOUCH is not set
++# CONFIG_MOUSE_BCM5974 is not set
++# CONFIG_MOUSE_VSXXXAA is not set
++# CONFIG_MOUSE_GPIO is not set
++# CONFIG_INPUT_JOYSTICK is not set
++# CONFIG_INPUT_TABLET is not set
++# CONFIG_INPUT_TOUCHSCREEN is not set
++# CONFIG_INPUT_MISC is not set
++
++#
++# Hardware I/O ports
++#
++CONFIG_SERIO=y
++CONFIG_SERIO_SERPORT=y
++# CONFIG_SERIO_AMBAKMI is not set
++CONFIG_SERIO_LIBPS2=y
++# CONFIG_SERIO_RAW is not set
++# CONFIG_GAMEPORT is not set
++
++#
++# Character devices
++#
++CONFIG_VT=y
++CONFIG_CONSOLE_TRANSLATIONS=y
++CONFIG_VT_CONSOLE=y
++CONFIG_HW_CONSOLE=y
++# CONFIG_VT_HW_CONSOLE_BINDING is not set
++CONFIG_DEVKMEM=y
++CONFIG_SERIAL_NONSTANDARD=y
++# CONFIG_N_HDLC is not set
++# CONFIG_RISCOM8 is not set
++# CONFIG_SPECIALIX is not set
++# CONFIG_RIO is not set
++# CONFIG_STALDRV is not set
++
++#
++# Serial drivers
++#
++# CONFIG_SERIAL_8250 is not set
++
++#
++# Non-8250 serial port support
++#
++# CONFIG_SERIAL_AMBA_PL010 is not set
++# CONFIG_SERIAL_AMBA_PL011 is not set
++CONFIG_SERIAL_ASPEED=y
++CONFIG_SERIAL_ASPEED_CONSOLE=y
++CONFIG_SERIAL_ASPEED_CONSOLE_BAUD=115200
++CONFIG_SERIAL_CORE=y
++CONFIG_SERIAL_CORE_CONSOLE=y
++CONFIG_UNIX98_PTYS=y
++CONFIG_LEGACY_PTYS=y
++CONFIG_LEGACY_PTY_COUNT=256
++# CONFIG_IPMI_HANDLER is not set
++# CONFIG_HW_RANDOM is not set
++CONFIG_NVRAM=y
++# CONFIG_R3964 is not set
++# CONFIG_RAW_DRIVER is not set
++# CONFIG_TCG_TPM is not set
++CONFIG_I2C=y
++CONFIG_I2C_BOARDINFO=y
++CONFIG_I2C_CHARDEV=y
++CONFIG_I2C_HELPER_AUTO=y
++
++#
++# I2C Hardware Bus support
++#
++
++#
++# I2C system bus drivers (mostly embedded / system-on-chip)
++#
++# CONFIG_I2C_GPIO is not set
++# CONFIG_I2C_OCORES is not set
++CONFIG_I2C_ASPEED=y
++CONFIG_AST_I2C_SLAVE_MODE=y
++# CONFIG_I2C_SIMTEC is not set
++
++#
++# External I2C/SMBus adapter drivers
++#
++# CONFIG_I2C_PARPORT_LIGHT is not set
++# CONFIG_I2C_TAOS_EVM is not set
++# CONFIG_I2C_TINY_USB is not set
++
++#
++# Other I2C/SMBus bus drivers
++#
++# CONFIG_I2C_PCA_PLATFORM is not set
++# CONFIG_I2C_STUB is not set
++
++#
++# Miscellaneous I2C Chip support
++#
++# CONFIG_DS1682 is not set
++CONFIG_AT24=y
++# CONFIG_SENSORS_EEPROM is not set
++# CONFIG_SENSORS_PCF8574 is not set
++# CONFIG_PCF8575 is not set
++# CONFIG_SENSORS_PCA9539 is not set
++# CONFIG_SENSORS_PCF8591 is not set
++# CONFIG_TPS65010 is not set
++# CONFIG_SENSORS_MAX6875 is not set
++# CONFIG_SENSORS_TSL2550 is not set
++# CONFIG_I2C_DEBUG_CORE is not set
++# CONFIG_I2C_DEBUG_ALGO is not set
++# CONFIG_I2C_DEBUG_BUS is not set
++# CONFIG_I2C_DEBUG_CHIP is not set
++CONFIG_SPI=y
++CONFIG_SPI_MASTER=y
++
++#
++# SPI Master Controller Drivers
++#
++CONFIG_SPI_AST=y
++# CONFIG_SPI_FMC is not set
++CONFIG_SPI_BITBANG=y
++
++#
++# SPI Protocol Masters
++#
++# CONFIG_SPI_AT25 is not set
++# CONFIG_SPI_SPIDEV is not set
++# CONFIG_SPI_TLE62X0 is not set
++CONFIG_ARCH_REQUIRE_GPIOLIB=y
++CONFIG_GPIOLIB=y
++CONFIG_GPIO_SYSFS=y
++
++#
++# Memory mapped GPIO expanders:
++#
++
++#
++# I2C GPIO expanders:
++#
++# CONFIG_GPIO_MAX732X is not set
++# CONFIG_GPIO_PCA953X is not set
++# CONFIG_GPIO_PCF857X is not set
++
++#
++# PCI GPIO expanders:
++#
++
++#
++# SPI GPIO expanders:
++#
++# CONFIG_GPIO_MAX7301 is not set
++# CONFIG_GPIO_MCP23S08 is not set
++# CONFIG_W1 is not set
++# CONFIG_POWER_SUPPLY is not set
++CONFIG_HWMON=y
++# CONFIG_HWMON_VID is not set
++# CONFIG_SENSORS_AD7414 is not set
++# CONFIG_SENSORS_AD7418 is not set
++# CONFIG_SENSORS_ADCXX is not set
++# CONFIG_SENSORS_ADM1021 is not set
++# CONFIG_SENSORS_ADM1025 is not set
++# CONFIG_SENSORS_ADM1026 is not set
++# CONFIG_SENSORS_ADM1029 is not set
++# CONFIG_SENSORS_ADM1031 is not set
++# CONFIG_SENSORS_ADM9240 is not set
++# CONFIG_SENSORS_ADT7462 is not set
++# CONFIG_SENSORS_ADT7470 is not set
++# CONFIG_SENSORS_ADT7473 is not set
++# CONFIG_SENSORS_ATXP1 is not set
++# CONFIG_SENSORS_DS1621 is not set
++# CONFIG_SENSORS_F71805F is not set
++# CONFIG_SENSORS_F71882FG is not set
++# CONFIG_SENSORS_F75375S is not set
++# CONFIG_SENSORS_GL518SM is not set
++# CONFIG_SENSORS_GL520SM is not set
++# CONFIG_SENSORS_IT87 is not set
++# CONFIG_SENSORS_LM63 is not set
++# CONFIG_SENSORS_LM70 is not set
++# CONFIG_SENSORS_LM75 is not set
++# CONFIG_SENSORS_LM77 is not set
++# CONFIG_SENSORS_LM78 is not set
++# CONFIG_SENSORS_LM80 is not set
++# CONFIG_SENSORS_LM83 is not set
++# CONFIG_SENSORS_LM85 is not set
++# CONFIG_SENSORS_LM87 is not set
++# CONFIG_SENSORS_LM90 is not set
++# CONFIG_SENSORS_LM92 is not set
++# CONFIG_SENSORS_LM93 is not set
++# CONFIG_SENSORS_MAX1111 is not set
++# CONFIG_SENSORS_MAX1619 is not set
++# CONFIG_SENSORS_MAX6650 is not set
++# CONFIG_SENSORS_PC87360 is not set
++# CONFIG_SENSORS_PC87427 is not set
++# CONFIG_SENSORS_DME1737 is not set
++# CONFIG_SENSORS_SMSC47M1 is not set
++# CONFIG_SENSORS_SMSC47M192 is not set
++# CONFIG_SENSORS_SMSC47B397 is not set
++# CONFIG_SENSORS_ADS7828 is not set
++# CONFIG_SENSORS_THMC50 is not set
++# CONFIG_SENSORS_VT1211 is not set
++# CONFIG_SENSORS_W83781D is not set
++# CONFIG_SENSORS_W83791D is not set
++# CONFIG_SENSORS_W83792D is not set
++# CONFIG_SENSORS_W83793 is not set
++# CONFIG_SENSORS_W83L785TS is not set
++# CONFIG_SENSORS_W83L786NG is not set
++# CONFIG_SENSORS_W83627HF is not set
++# CONFIG_SENSORS_W83627EHF is not set
++# CONFIG_SENSORS_AST_ADC is not set
++CONFIG_SENSORS_AST_PWM_FAN=y
++# CONFIG_SENSORS_AST_PECI is not set
++# CONFIG_HWMON_DEBUG_CHIP is not set
++# CONFIG_THERMAL is not set
++# CONFIG_THERMAL_HWMON is not set
++CONFIG_WATCHDOG=y
++# CONFIG_WATCHDOG_NOWAYOUT is not set
++
++#
++# Watchdog Device Drivers
++#
++# CONFIG_SOFT_WATCHDOG is not set
++CONFIG_ASPEED_WATCHDOG=y
++
++#
++# USB-based Watchdog Cards
++#
++# CONFIG_USBPCWATCHDOG is not set
++CONFIG_SSB_POSSIBLE=y
++
++#
++# Sonics Silicon Backplane
++#
++# CONFIG_SSB is not set
++
++#
++# Multifunction device drivers
++#
++# CONFIG_MFD_CORE is not set
++# CONFIG_MFD_SM501 is not set
++# CONFIG_MFD_ASIC3 is not set
++# CONFIG_HTC_EGPIO is not set
++# CONFIG_HTC_PASIC3 is not set
++# CONFIG_MFD_TMIO is not set
++# CONFIG_MFD_TC6393XB is not set
++# CONFIG_PMIC_DA903X is not set
++# CONFIG_MFD_WM8400 is not set
++# CONFIG_MFD_WM8350_I2C is not set
++
++#
++# Multimedia devices
++#
++
++#
++# Multimedia core support
++#
++# CONFIG_VIDEO_DEV is not set
++# CONFIG_DVB_CORE is not set
++# CONFIG_VIDEO_MEDIA is not set
++
++#
++# Multimedia drivers
++#
++# CONFIG_DAB is not set
++
++#
++# Graphics support
++#
++# CONFIG_VGASTATE is not set
++# CONFIG_VIDEO_OUTPUT_CONTROL is not set
++CONFIG_FB=y
++CONFIG_FIRMWARE_EDID=y
++# CONFIG_FB_DDC is not set
++# CONFIG_FB_BOOT_VESA_SUPPORT is not set
++CONFIG_FB_CFB_FILLRECT=y
++CONFIG_FB_CFB_COPYAREA=y
++CONFIG_FB_CFB_IMAGEBLIT=y
++# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set
++# CONFIG_FB_SYS_FILLRECT is not set
++# CONFIG_FB_SYS_COPYAREA is not set
++# CONFIG_FB_SYS_IMAGEBLIT is not set
++# CONFIG_FB_FOREIGN_ENDIAN is not set
++# CONFIG_FB_SYS_FOPS is not set
++# CONFIG_FB_SVGALIB is not set
++# CONFIG_FB_MACMODES is not set
++# CONFIG_FB_BACKLIGHT is not set
++CONFIG_FB_MODE_HELPERS=y
++CONFIG_FB_TILEBLITTING=y
++
++#
++# Frame buffer hardware drivers
++#
++# CONFIG_FB_ARMCLCD is not set
++# CONFIG_FB_UVESA is not set
++# CONFIG_FB_S1D13XXX is not set
++CONFIG_FB_AST=y
++CONFIG_AST_DAC=y
++# CONFIG_AST_DVO is not set
++# CONFIG_FB_VIRTUAL is not set
++# CONFIG_FB_METRONOME is not set
++# CONFIG_FB_MB862XX is not set
++CONFIG_BACKLIGHT_LCD_SUPPORT=y
++CONFIG_LCD_CLASS_DEVICE=m
++# CONFIG_LCD_LTV350QV is not set
++# CONFIG_LCD_ILI9320 is not set
++# CONFIG_LCD_TDO24M is not set
++# CONFIG_LCD_VGG2432A4 is not set
++# CONFIG_LCD_PLATFORM is not set
++CONFIG_BACKLIGHT_CLASS_DEVICE=m
++# CONFIG_BACKLIGHT_CORGI is not set
++
++#
++# Display device support
++#
++# CONFIG_DISPLAY_SUPPORT is not set
++
++#
++# Console display driver support
++#
++# CONFIG_VGA_CONSOLE is not set
++CONFIG_DUMMY_CONSOLE=y
++CONFIG_FRAMEBUFFER_CONSOLE=y
++# CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY is not set
++# CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set
++CONFIG_FONTS=y
++CONFIG_FONT_8x8=y
++CONFIG_FONT_8x16=y
++# CONFIG_FONT_6x11 is not set
++# CONFIG_FONT_7x14 is not set
++# CONFIG_FONT_PEARL_8x8 is not set
++# CONFIG_FONT_ACORN_8x8 is not set
++# CONFIG_FONT_MINI_4x6 is not set
++# CONFIG_FONT_SUN8x16 is not set
++# CONFIG_FONT_SUN12x22 is not set
++# CONFIG_FONT_10x18 is not set
++# CONFIG_LOGO is not set
++# CONFIG_SOUND is not set
++CONFIG_HID_SUPPORT=y
++CONFIG_HID=y
++CONFIG_HID_DEBUG=y
++# CONFIG_HIDRAW is not set
++
++#
++# USB Input Devices
++#
++CONFIG_USB_HID=y
++# CONFIG_HID_PID is not set
++# CONFIG_USB_HIDDEV is not set
++
++#
++# Special HID drivers
++#
++CONFIG_HID_COMPAT=y
++CONFIG_HID_A4TECH=y
++CONFIG_HID_APPLE=y
++CONFIG_HID_BELKIN=y
++CONFIG_HID_BRIGHT=y
++CONFIG_HID_CHERRY=y
++CONFIG_HID_CHICONY=y
++CONFIG_HID_CYPRESS=y
++CONFIG_HID_DELL=y
++CONFIG_HID_EZKEY=y
++CONFIG_HID_GYRATION=y
++CONFIG_HID_LOGITECH=y
++# CONFIG_LOGITECH_FF is not set
++# CONFIG_LOGIRUMBLEPAD2_FF is not set
++CONFIG_HID_MICROSOFT=y
++CONFIG_HID_MONTEREY=y
++CONFIG_HID_PANTHERLORD=y
++# CONFIG_PANTHERLORD_FF is not set
++CONFIG_HID_PETALYNX=y
++CONFIG_HID_SAMSUNG=y
++CONFIG_HID_SONY=y
++CONFIG_HID_SUNPLUS=y
++# CONFIG_THRUSTMASTER_FF is not set
++# CONFIG_ZEROPLUS_FF is not set
++CONFIG_USB_SUPPORT=y
++CONFIG_USB_ARCH_HAS_HCD=y
++# CONFIG_USB_ARCH_HAS_OHCI is not set
++CONFIG_USB_ARCH_HAS_EHCI=y
++CONFIG_USB=y
++# CONFIG_USB_DEBUG is not set
++# CONFIG_USB_ANNOUNCE_NEW_DEVICES is not set
++
++#
++# Miscellaneous USB options
++#
++CONFIG_USB_DEVICEFS=y
++CONFIG_USB_DEVICE_CLASS=y
++# CONFIG_USB_DYNAMIC_MINORS is not set
++# CONFIG_USB_SUSPEND is not set
++# CONFIG_USB_OTG is not set
++# CONFIG_USB_MON is not set
++# CONFIG_USB_WUSB is not set
++# CONFIG_USB_WUSB_CBAF is not set
++
++#
++# USB Host Controller Drivers
++#
++# CONFIG_USB_C67X00_HCD is not set
++# CONFIG_USB_EHCI_HCD is not set
++# CONFIG_USB_ISP116X_HCD is not set
++# CONFIG_USB_SL811_HCD is not set
++# CONFIG_USB_R8A66597_HCD is not set
++# CONFIG_USB_HWA_HCD is not set
++
++#
++# AST USB Drivers
++#
++CONFIG_AST_USB_UHCI_HCD=y
++# CONFIG_AST_USB_UHCI_MULTIPORT_1 is not set
++# CONFIG_AST_USB_UHCI_MULTIPORT_2 is not set
++CONFIG_AST_USB_UHCI_MULTIPORT_4=y
++
++#
++# USB Device Class drivers
++#
++# CONFIG_USB_ACM is not set
++# CONFIG_USB_PRINTER is not set
++# CONFIG_USB_WDM is not set
++# CONFIG_USB_TMC is not set
++
++#
++# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may also be needed;
++#
++
++#
++# see USB_STORAGE Help for more information
++#
++CONFIG_USB_STORAGE=y
++# CONFIG_USB_STORAGE_DEBUG is not set
++# CONFIG_USB_STORAGE_DATAFAB is not set
++# CONFIG_USB_STORAGE_FREECOM is not set
++# CONFIG_USB_STORAGE_ISD200 is not set
++# CONFIG_USB_STORAGE_DPCM is not set
++# CONFIG_USB_STORAGE_USBAT is not set
++# CONFIG_USB_STORAGE_SDDR09 is not set
++# CONFIG_USB_STORAGE_SDDR55 is not set
++# CONFIG_USB_STORAGE_JUMPSHOT is not set
++# CONFIG_USB_STORAGE_ALAUDA is not set
++# CONFIG_USB_STORAGE_ONETOUCH is not set
++# CONFIG_USB_STORAGE_KARMA is not set
++# CONFIG_USB_STORAGE_CYPRESS_ATACB is not set
++# CONFIG_USB_LIBUSUAL is not set
++
++#
++# USB Imaging devices
++#
++# CONFIG_USB_MDC800 is not set
++# CONFIG_USB_MICROTEK is not set
++
++#
++# USB port drivers
++#
++# CONFIG_USB_SERIAL is not set
++
++#
++# USB Miscellaneous drivers
++#
++# CONFIG_USB_EMI62 is not set
++# CONFIG_USB_EMI26 is not set
++# CONFIG_USB_ADUTUX is not set
++# CONFIG_USB_SEVSEG is not set
++# CONFIG_USB_RIO500 is not set
++# CONFIG_USB_LEGOTOWER is not set
++# CONFIG_USB_LCD is not set
++# CONFIG_USB_BERRY_CHARGE is not set
++# CONFIG_USB_LED is not set
++# CONFIG_USB_CYPRESS_CY7C63 is not set
++# CONFIG_USB_CYTHERM is not set
++# CONFIG_USB_PHIDGET is not set
++# CONFIG_USB_IDMOUSE is not set
++# CONFIG_USB_FTDI_ELAN is not set
++# CONFIG_USB_APPLEDISPLAY is not set
++# CONFIG_USB_LD is not set
++# CONFIG_USB_TRANCEVIBRATOR is not set
++# CONFIG_USB_IOWARRIOR is not set
++# CONFIG_USB_TEST is not set
++# CONFIG_USB_ISIGHTFW is not set
++# CONFIG_USB_VST is not set
++# CONFIG_USB_GADGET is not set
++CONFIG_MMC=y
++# CONFIG_MMC_DEBUG is not set
++# CONFIG_MMC_UNSAFE_RESUME is not set
++
++#
++# MMC/SD/SDIO Card Drivers
++#
++CONFIG_MMC_BLOCK=y
++CONFIG_MMC_BLOCK_BOUNCE=y
++# CONFIG_SDIO_UART is not set
++# CONFIG_MMC_TEST is not set
++
++#
++# MMC/SD/SDIO Host Controller Drivers
++#
++# CONFIG_MMC_ARMMMCI is not set
++# CONFIG_MMC_SDHCI is not set
++CONFIG_MMC_ASPEED=y
++# CONFIG_MMC_SPI is not set
++# CONFIG_MEMSTICK is not set
++# CONFIG_ACCESSIBILITY is not set
++# CONFIG_NEW_LEDS is not set
++CONFIG_RTC_LIB=y
++CONFIG_RTC_CLASS=y
++# CONFIG_RTC_HCTOSYS is not set
++# CONFIG_RTC_DEBUG is not set
++
++#
++# RTC interfaces
++#
++CONFIG_RTC_INTF_SYSFS=y
++CONFIG_RTC_INTF_PROC=y
++CONFIG_RTC_INTF_DEV=y
++# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set
++# CONFIG_RTC_DRV_TEST is not set
++
++#
++# I2C RTC drivers
++#
++# CONFIG_RTC_DRV_DS1307 is not set
++# CONFIG_RTC_DRV_DS1374 is not set
++# CONFIG_RTC_DRV_DS1672 is not set
++# CONFIG_RTC_DRV_MAX6900 is not set
++# CONFIG_RTC_DRV_RS5C372 is not set
++# CONFIG_RTC_DRV_ISL1208 is not set
++# CONFIG_RTC_DRV_X1205 is not set
++# CONFIG_RTC_DRV_PCF8563 is not set
++# CONFIG_RTC_DRV_PCF8583 is not set
++# CONFIG_RTC_DRV_M41T80 is not set
++# CONFIG_RTC_DRV_S35390A is not set
++# CONFIG_RTC_DRV_FM3130 is not set
++# CONFIG_RTC_DRV_RX8581 is not set
++
++#
++# SPI RTC drivers
++#
++# CONFIG_RTC_DRV_M41T94 is not set
++# CONFIG_RTC_DRV_DS1305 is not set
++# CONFIG_RTC_DRV_DS1390 is not set
++# CONFIG_RTC_DRV_MAX6902 is not set
++# CONFIG_RTC_DRV_R9701 is not set
++# CONFIG_RTC_DRV_RS5C348 is not set
++# CONFIG_RTC_DRV_DS3234 is not set
++
++#
++# Platform RTC drivers
++#
++# CONFIG_RTC_DRV_CMOS is not set
++# CONFIG_RTC_DRV_DS1286 is not set
++# CONFIG_RTC_DRV_DS1511 is not set
++# CONFIG_RTC_DRV_DS1553 is not set
++# CONFIG_RTC_DRV_DS1742 is not set
++# CONFIG_RTC_DRV_STK17TA8 is not set
++# CONFIG_RTC_DRV_M48T86 is not set
++# CONFIG_RTC_DRV_M48T35 is not set
++# CONFIG_RTC_DRV_M48T59 is not set
++# CONFIG_RTC_DRV_BQ4802 is not set
++# CONFIG_RTC_DRV_V3020 is not set
++
++#
++# on-CPU RTC drivers
++#
++# CONFIG_RTC_DRV_PL030 is not set
++# CONFIG_RTC_DRV_PL031 is not set
++CONFIG_RTC_DRV_ASPEED=y
++# CONFIG_DMADEVICES is not set
++# CONFIG_REGULATOR is not set
++# CONFIG_UIO is not set
++
++#
++# File systems
++#
++CONFIG_EXT2_FS=y
++CONFIG_EXT2_FS_XATTR=y
++CONFIG_EXT2_FS_POSIX_ACL=y
++CONFIG_EXT2_FS_SECURITY=y
++# CONFIG_EXT2_FS_XIP is not set
++# CONFIG_EXT3_FS is not set
++# CONFIG_EXT4_FS is not set
++CONFIG_FS_MBCACHE=y
++# CONFIG_REISERFS_FS is not set
++# CONFIG_JFS_FS is not set
++CONFIG_FS_POSIX_ACL=y
++CONFIG_FILE_LOCKING=y
++# CONFIG_XFS_FS is not set
++# CONFIG_OCFS2_FS is not set
++CONFIG_DNOTIFY=y
++CONFIG_INOTIFY=y
++CONFIG_INOTIFY_USER=y
++# CONFIG_QUOTA is not set
++# CONFIG_AUTOFS_FS is not set
++# CONFIG_AUTOFS4_FS is not set
++# CONFIG_FUSE_FS is not set
++CONFIG_GENERIC_ACL=y
++
++#
++# CD-ROM/DVD Filesystems
++#
++# CONFIG_ISO9660_FS is not set
++# CONFIG_UDF_FS is not set
++
++#
++# DOS/FAT/NT Filesystems
++#
++CONFIG_FAT_FS=y
++CONFIG_MSDOS_FS=y
++CONFIG_VFAT_FS=y
++CONFIG_FAT_DEFAULT_CODEPAGE=437
++CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
++CONFIG_NTFS_FS=y
++# CONFIG_NTFS_DEBUG is not set
++CONFIG_NTFS_RW=y
++
++#
++# Pseudo filesystems
++#
++CONFIG_PROC_FS=y
++CONFIG_PROC_SYSCTL=y
++CONFIG_PROC_PAGE_MONITOR=y
++CONFIG_SYSFS=y
++CONFIG_TMPFS=y
++CONFIG_TMPFS_POSIX_ACL=y
++# CONFIG_HUGETLB_PAGE is not set
++CONFIG_CONFIGFS_FS=m
++
++#
++# Miscellaneous filesystems
++#
++# CONFIG_ADFS_FS is not set
++# CONFIG_AFFS_FS is not set
++# CONFIG_HFS_FS is not set
++# CONFIG_HFSPLUS_FS is not set
++# CONFIG_BEFS_FS is not set
++# CONFIG_BFS_FS is not set
++# CONFIG_EFS_FS is not set
++CONFIG_YAFFS_FS=y
++CONFIG_YAFFS_YAFFS1=y
++# CONFIG_YAFFS_9BYTE_TAGS is not set
++# CONFIG_YAFFS_DOES_ECC is not set
++CONFIG_YAFFS_YAFFS2=y
++CONFIG_YAFFS_AUTO_YAFFS2=y
++# CONFIG_YAFFS_DISABLE_TAGS_ECC is not set
++# CONFIG_YAFFS_DISABLE_LAZY_LOAD is not set
++# CONFIG_YAFFS_DISABLE_WIDE_TNODES is not set
++# CONFIG_YAFFS_ALWAYS_CHECK_CHUNK_ERASED is not set
++CONFIG_YAFFS_SHORT_NAMES_IN_RAM=y
++# CONFIG_YAFFS_EMPTY_LOST_AND_FOUND is not set
++# CONFIG_JFFS2_FS is not set
++# CONFIG_CRAMFS is not set
++# CONFIG_VXFS_FS is not set
++# CONFIG_MINIX_FS is not set
++# CONFIG_OMFS_FS is not set
++# CONFIG_HPFS_FS is not set
++# CONFIG_QNX4FS_FS is not set
++# CONFIG_ROMFS_FS is not set
++# CONFIG_SYSV_FS is not set
++# CONFIG_UFS_FS is not set
++CONFIG_NETWORK_FILESYSTEMS=y
++CONFIG_NFS_FS=y
++# CONFIG_NFS_V3 is not set
++# CONFIG_NFS_V4 is not set
++CONFIG_ROOT_NFS=y
++# CONFIG_NFSD is not set
++CONFIG_LOCKD=y
++CONFIG_NFS_COMMON=y
++CONFIG_SUNRPC=y
++# CONFIG_SUNRPC_REGISTER_V4 is not set
++# CONFIG_RPCSEC_GSS_KRB5 is not set
++# CONFIG_RPCSEC_GSS_SPKM3 is not set
++# CONFIG_SMB_FS is not set
++# CONFIG_CIFS is not set
++# CONFIG_NCP_FS is not set
++# CONFIG_CODA_FS is not set
++# CONFIG_AFS_FS is not set
++
++#
++# Partition Types
++#
++# CONFIG_PARTITION_ADVANCED is not set
++CONFIG_MSDOS_PARTITION=y
++CONFIG_NLS=y
++CONFIG_NLS_DEFAULT="utf8"
++CONFIG_NLS_CODEPAGE_437=y
++# CONFIG_NLS_CODEPAGE_737 is not set
++# CONFIG_NLS_CODEPAGE_775 is not set
++# CONFIG_NLS_CODEPAGE_850 is not set
++# CONFIG_NLS_CODEPAGE_852 is not set
++# CONFIG_NLS_CODEPAGE_855 is not set
++# CONFIG_NLS_CODEPAGE_857 is not set
++# CONFIG_NLS_CODEPAGE_860 is not set
++# CONFIG_NLS_CODEPAGE_861 is not set
++# CONFIG_NLS_CODEPAGE_862 is not set
++# CONFIG_NLS_CODEPAGE_863 is not set
++# CONFIG_NLS_CODEPAGE_864 is not set
++# CONFIG_NLS_CODEPAGE_865 is not set
++# CONFIG_NLS_CODEPAGE_866 is not set
++# CONFIG_NLS_CODEPAGE_869 is not set
++CONFIG_NLS_CODEPAGE_936=y
++CONFIG_NLS_CODEPAGE_950=y
++CONFIG_NLS_CODEPAGE_932=y
++# CONFIG_NLS_CODEPAGE_949 is not set
++# CONFIG_NLS_CODEPAGE_874 is not set
++# CONFIG_NLS_ISO8859_8 is not set
++# CONFIG_NLS_CODEPAGE_1250 is not set
++# CONFIG_NLS_CODEPAGE_1251 is not set
++CONFIG_NLS_ASCII=y
++CONFIG_NLS_ISO8859_1=y
++# CONFIG_NLS_ISO8859_2 is not set
++# CONFIG_NLS_ISO8859_3 is not set
++# CONFIG_NLS_ISO8859_4 is not set
++# CONFIG_NLS_ISO8859_5 is not set
++# CONFIG_NLS_ISO8859_6 is not set
++# CONFIG_NLS_ISO8859_7 is not set
++# CONFIG_NLS_ISO8859_9 is not set
++# CONFIG_NLS_ISO8859_13 is not set
++# CONFIG_NLS_ISO8859_14 is not set
++# CONFIG_NLS_ISO8859_15 is not set
++# CONFIG_NLS_KOI8_R is not set
++# CONFIG_NLS_KOI8_U is not set
++CONFIG_NLS_UTF8=y
++# CONFIG_DLM is not set
++
++#
++# Kernel hacking
++#
++# CONFIG_PRINTK_TIME is not set
++# CONFIG_ENABLE_WARN_DEPRECATED is not set
++CONFIG_ENABLE_MUST_CHECK=y
++CONFIG_FRAME_WARN=1024
++CONFIG_MAGIC_SYSRQ=y
++# CONFIG_UNUSED_SYMBOLS is not set
++# CONFIG_DEBUG_FS is not set
++# CONFIG_HEADERS_CHECK is not set
++# CONFIG_DEBUG_KERNEL is not set
++# CONFIG_SLUB_DEBUG_ON is not set
++# CONFIG_SLUB_STATS is not set
++CONFIG_DEBUG_BUGVERBOSE=y
++CONFIG_DEBUG_MEMORY_INIT=y
++CONFIG_FRAME_POINTER=y
++# CONFIG_RCU_CPU_STALL_DETECTOR is not set
++# CONFIG_LATENCYTOP is not set
++# CONFIG_SYSCTL_SYSCALL_CHECK is not set
++CONFIG_HAVE_FUNCTION_TRACER=y
++
++#
++# Tracers
++#
++# CONFIG_DYNAMIC_PRINTK_DEBUG is not set
++# CONFIG_SAMPLES is not set
++CONFIG_HAVE_ARCH_KGDB=y
++# CONFIG_DEBUG_USER is not set
++
++#
++# Security options
++#
++# CONFIG_KEYS is not set
++# CONFIG_SECURITY is not set
++# CONFIG_SECURITYFS is not set
++# CONFIG_SECURITY_FILE_CAPABILITIES is not set
++CONFIG_CRYPTO=y
++
++#
++# Crypto core or helper
++#
++# CONFIG_CRYPTO_FIPS is not set
++CONFIG_CRYPTO_ALGAPI=y
++CONFIG_CRYPTO_ALGAPI2=y
++CONFIG_CRYPTO_AEAD=m
++CONFIG_CRYPTO_AEAD2=y
++CONFIG_CRYPTO_BLKCIPHER=y
++CONFIG_CRYPTO_BLKCIPHER2=y
++CONFIG_CRYPTO_HASH=y
++CONFIG_CRYPTO_HASH2=y
++CONFIG_CRYPTO_RNG2=y
++CONFIG_CRYPTO_MANAGER=y
++CONFIG_CRYPTO_MANAGER2=y
++# CONFIG_CRYPTO_GF128MUL is not set
++CONFIG_CRYPTO_NULL=y
++# CONFIG_CRYPTO_CRYPTD is not set
++CONFIG_CRYPTO_AUTHENC=m
++# CONFIG_CRYPTO_TEST is not set
++
++#
++# Authenticated Encryption with Associated Data
++#
++# CONFIG_CRYPTO_CCM is not set
++# CONFIG_CRYPTO_GCM is not set
++# CONFIG_CRYPTO_SEQIV is not set
++
++#
++# Block modes
++#
++CONFIG_CRYPTO_CBC=y
++# CONFIG_CRYPTO_CTR is not set
++# CONFIG_CRYPTO_CTS is not set
++# CONFIG_CRYPTO_ECB is not set
++# CONFIG_CRYPTO_LRW is not set
++# CONFIG_CRYPTO_PCBC is not set
++# CONFIG_CRYPTO_XTS is not set
++
++#
++# Hash modes
++#
++CONFIG_CRYPTO_HMAC=y
++# CONFIG_CRYPTO_XCBC is not set
++
++#
++# Digest
++#
++# CONFIG_CRYPTO_CRC32C is not set
++# CONFIG_CRYPTO_MD4 is not set
++CONFIG_CRYPTO_MD5=y
++# CONFIG_CRYPTO_MICHAEL_MIC is not set
++# CONFIG_CRYPTO_RMD128 is not set
++# CONFIG_CRYPTO_RMD160 is not set
++# CONFIG_CRYPTO_RMD256 is not set
++# CONFIG_CRYPTO_RMD320 is not set
++CONFIG_CRYPTO_SHA1=y
++# CONFIG_CRYPTO_SHA256 is not set
++# CONFIG_CRYPTO_SHA512 is not set
++# CONFIG_CRYPTO_TGR192 is not set
++# CONFIG_CRYPTO_WP512 is not set
++
++#
++# Ciphers
++#
++# CONFIG_CRYPTO_AES is not set
++# CONFIG_CRYPTO_ANUBIS is not set
++# CONFIG_CRYPTO_ARC4 is not set
++# CONFIG_CRYPTO_BLOWFISH is not set
++# CONFIG_CRYPTO_CAMELLIA is not set
++# CONFIG_CRYPTO_CAST5 is not set
++# CONFIG_CRYPTO_CAST6 is not set
++CONFIG_CRYPTO_DES=y
++# CONFIG_CRYPTO_FCRYPT is not set
++# CONFIG_CRYPTO_KHAZAD is not set
++# CONFIG_CRYPTO_SALSA20 is not set
++# CONFIG_CRYPTO_SEED is not set
++# CONFIG_CRYPTO_SERPENT is not set
++# CONFIG_CRYPTO_TEA is not set
++# CONFIG_CRYPTO_TWOFISH is not set
++
++#
++# Compression
++#
++CONFIG_CRYPTO_DEFLATE=m
++# CONFIG_CRYPTO_LZO is not set
++
++#
++# Random Number Generation
++#
++# CONFIG_CRYPTO_ANSI_CPRNG is not set
++# CONFIG_CRYPTO_HW is not set
++
++#
++# Library routines
++#
++CONFIG_BITREVERSE=y
++# CONFIG_CRC_CCITT is not set
++# CONFIG_CRC16 is not set
++# CONFIG_CRC_T10DIF is not set
++CONFIG_CRC_ITU_T=m
++CONFIG_CRC32=y
++# CONFIG_CRC7 is not set
++# CONFIG_LIBCRC32C is not set
++CONFIG_ZLIB_INFLATE=m
++CONFIG_ZLIB_DEFLATE=m
++CONFIG_PLIST=y
++CONFIG_HAS_IOMEM=y
++CONFIG_HAS_IOPORT=y
++CONFIG_HAS_DMA=y
+diff --git a/arch/arm/configs/ast2400_ast1070-1_defconfig b/arch/arm/configs/ast2400_ast1070-1_defconfig
+new file mode 100644
+index 0000000..93f3df9
+--- /dev/null
++++ b/arch/arm/configs/ast2400_ast1070-1_defconfig
+@@ -0,0 +1,1038 @@
++#
++# Automatically generated make config: don't edit
++# Linux kernel version: 2.6.28.9
++# Fri Nov 8 16:04:52 2013
++#
++CONFIG_ARM=y
++CONFIG_SYS_SUPPORTS_APM_EMULATION=y
++CONFIG_GENERIC_GPIO=y
++# CONFIG_GENERIC_TIME is not set
++# CONFIG_GENERIC_CLOCKEVENTS is not set
++CONFIG_MMU=y
++# CONFIG_NO_IOPORT is not set
++CONFIG_GENERIC_HARDIRQS=y
++CONFIG_STACKTRACE_SUPPORT=y
++CONFIG_HAVE_LATENCYTOP_SUPPORT=y
++CONFIG_LOCKDEP_SUPPORT=y
++CONFIG_TRACE_IRQFLAGS_SUPPORT=y
++CONFIG_HARDIRQS_SW_RESEND=y
++CONFIG_GENERIC_IRQ_PROBE=y
++CONFIG_RWSEM_GENERIC_SPINLOCK=y
++# CONFIG_ARCH_HAS_ILOG2_U32 is not set
++# CONFIG_ARCH_HAS_ILOG2_U64 is not set
++CONFIG_GENERIC_HWEIGHT=y
++CONFIG_GENERIC_CALIBRATE_DELAY=y
++CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
++CONFIG_VECTORS_BASE=0xffff0000
++CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
++
++#
++# General setup
++#
++CONFIG_EXPERIMENTAL=y
++CONFIG_BROKEN_ON_SMP=y
++CONFIG_INIT_ENV_ARG_LIMIT=32
++CONFIG_LOCALVERSION=""
++# CONFIG_LOCALVERSION_AUTO is not set
++CONFIG_SWAP=y
++CONFIG_SYSVIPC=y
++CONFIG_SYSVIPC_SYSCTL=y
++# CONFIG_POSIX_MQUEUE is not set
++# CONFIG_BSD_PROCESS_ACCT is not set
++# CONFIG_TASKSTATS is not set
++# CONFIG_AUDIT is not set
++# CONFIG_IKCONFIG is not set
++CONFIG_LOG_BUF_SHIFT=16
++# CONFIG_CGROUPS is not set
++# CONFIG_GROUP_SCHED is not set
++CONFIG_SYSFS_DEPRECATED=y
++CONFIG_SYSFS_DEPRECATED_V2=y
++# CONFIG_RELAY is not set
++CONFIG_NAMESPACES=y
++# CONFIG_UTS_NS is not set
++# CONFIG_IPC_NS is not set
++# CONFIG_USER_NS is not set
++# CONFIG_PID_NS is not set
++CONFIG_BLK_DEV_INITRD=y
++CONFIG_INITRAMFS_SOURCE=""
++CONFIG_CC_OPTIMIZE_FOR_SIZE=y
++CONFIG_SYSCTL=y
++CONFIG_ANON_INODES=y
++# CONFIG_EMBEDDED is not set
++CONFIG_UID16=y
++CONFIG_SYSCTL_SYSCALL=y
++CONFIG_KALLSYMS=y
++CONFIG_KALLSYMS_EXTRA_PASS=y
++CONFIG_HOTPLUG=y
++CONFIG_PRINTK=y
++CONFIG_BUG=y
++CONFIG_ELF_CORE=y
++CONFIG_BASE_FULL=y
++CONFIG_FUTEX=y
++CONFIG_EPOLL=y
++CONFIG_SIGNALFD=y
++CONFIG_TIMERFD=y
++CONFIG_EVENTFD=y
++CONFIG_SHMEM=y
++CONFIG_AIO=y
++CONFIG_VM_EVENT_COUNTERS=y
++CONFIG_SLUB_DEBUG=y
++CONFIG_COMPAT_BRK=y
++# CONFIG_SLAB is not set
++CONFIG_SLUB=y
++# CONFIG_SLOB is not set
++# CONFIG_PROFILING is not set
++# CONFIG_MARKERS is not set
++CONFIG_HAVE_OPROFILE=y
++# CONFIG_KPROBES is not set
++CONFIG_HAVE_KPROBES=y
++CONFIG_HAVE_KRETPROBES=y
++CONFIG_HAVE_GENERIC_DMA_COHERENT=y
++CONFIG_SLABINFO=y
++CONFIG_RT_MUTEXES=y
++# CONFIG_TINY_SHMEM is not set
++CONFIG_BASE_SMALL=0
++CONFIG_MODULES=y
++# CONFIG_MODULE_FORCE_LOAD is not set
++CONFIG_MODULE_UNLOAD=y
++# CONFIG_MODULE_FORCE_UNLOAD is not set
++# CONFIG_MODVERSIONS is not set
++# CONFIG_MODULE_SRCVERSION_ALL is not set
++CONFIG_KMOD=y
++CONFIG_BLOCK=y
++# CONFIG_LBD is not set
++# CONFIG_BLK_DEV_IO_TRACE is not set
++# CONFIG_LSF is not set
++# CONFIG_BLK_DEV_BSG is not set
++# CONFIG_BLK_DEV_INTEGRITY is not set
++
++#
++# IO Schedulers
++#
++CONFIG_IOSCHED_NOOP=y
++CONFIG_IOSCHED_AS=y
++CONFIG_IOSCHED_DEADLINE=y
++CONFIG_IOSCHED_CFQ=y
++# CONFIG_DEFAULT_AS is not set
++# CONFIG_DEFAULT_DEADLINE is not set
++CONFIG_DEFAULT_CFQ=y
++# CONFIG_DEFAULT_NOOP is not set
++CONFIG_DEFAULT_IOSCHED="cfq"
++CONFIG_CLASSIC_RCU=y
++CONFIG_FREEZER=y
++
++#
++# System Type
++#
++CONFIG_ARCH_ASPEED=y
++# CONFIG_ARCH_AAEC2000 is not set
++# CONFIG_ARCH_INTEGRATOR is not set
++# CONFIG_ARCH_REALVIEW is not set
++# CONFIG_ARCH_VERSATILE is not set
++# CONFIG_ARCH_AT91 is not set
++# CONFIG_ARCH_CLPS7500 is not set
++# CONFIG_ARCH_CLPS711X is not set
++# CONFIG_ARCH_EBSA110 is not set
++# CONFIG_ARCH_EP93XX is not set
++# CONFIG_ARCH_FOOTBRIDGE is not set
++# CONFIG_ARCH_NETX is not set
++# CONFIG_ARCH_H720X is not set
++# CONFIG_ARCH_IMX is not set
++# CONFIG_ARCH_IOP13XX is not set
++# CONFIG_ARCH_IOP32X is not set
++# CONFIG_ARCH_IOP33X is not set
++# CONFIG_ARCH_IXP23XX is not set
++# CONFIG_ARCH_IXP2000 is not set
++# CONFIG_ARCH_IXP4XX is not set
++# CONFIG_ARCH_L7200 is not set
++# CONFIG_ARCH_KIRKWOOD is not set
++# CONFIG_ARCH_KS8695 is not set
++# CONFIG_ARCH_NS9XXX is not set
++# CONFIG_ARCH_LOKI is not set
++# CONFIG_ARCH_MV78XX0 is not set
++# CONFIG_ARCH_MXC is not set
++# CONFIG_ARCH_ORION5X is not set
++# CONFIG_ARCH_PNX4008 is not set
++# CONFIG_ARCH_PXA is not set
++# CONFIG_ARCH_RPC is not set
++# CONFIG_ARCH_SA1100 is not set
++# CONFIG_ARCH_S3C2410 is not set
++# CONFIG_ARCH_SHARK is not set
++# CONFIG_ARCH_LH7A40X is not set
++# CONFIG_ARCH_DAVINCI is not set
++# CONFIG_ARCH_OMAP is not set
++# CONFIG_ARCH_MSM is not set
++CONFIG_IRMP=y
++# CONFIG_PCEXT is not set
++# CONFIG_REMOTEFX is not set
++# CONFIG_ARCH_AST1100 is not set
++# CONFIG_ARCH_AST2100 is not set
++# CONFIG_ARCH_AST2200 is not set
++# CONFIG_ARCH_AST2300 is not set
++CONFIG_ARCH_AST2400=y
++# CONFIG_ARCH_AST2500 is not set
++
++#
++# FLASH Chip Select
++#
++CONFIG_AST_CS0_NOR=y
++# CONFIG_AST_CS0_NAND is not set
++# CONFIG_AST_CS0_SPI is not set
++# CONFIG_AST_CS0_NONE is not set
++CONFIG_AST_CS1_NOR=y
++# CONFIG_AST_CS1_NAND is not set
++# CONFIG_AST_CS1_SPI is not set
++# CONFIG_AST_CS1_NONE is not set
++CONFIG_AST_CS2_NOR=y
++# CONFIG_AST_CS2_NAND is not set
++# CONFIG_AST_CS2_SPI is not set
++# CONFIG_AST_CS2_NONE is not set
++CONFIG_AST_CS3_NOR=y
++# CONFIG_AST_CS3_NAND is not set
++# CONFIG_AST_CS3_SPI is not set
++# CONFIG_AST_CS3_NONE is not set
++CONFIG_AST_CS4_NOR=y
++# CONFIG_AST_CS4_NAND is not set
++# CONFIG_AST_CS4_SPI is not set
++# CONFIG_AST_CS4_NONE is not set
++CONFIG_ARCH_AST1070=y
++CONFIG_AST1070_NR=1
++CONFIG_AST_LPC_PLUS=y
++# CONFIG_AST_LPC is not set
++# CONFIG_AST_SCU_LOCK is not set
++
++#
++# Boot options
++#
++
++#
++# Power management
++#
++CONFIG_PLAT_ASPEED=y
++
++#
++# Processor Type
++#
++CONFIG_CPU_32=y
++CONFIG_CPU_ARM926T=y
++CONFIG_CPU_32v5=y
++CONFIG_CPU_ABRT_EV5TJ=y
++CONFIG_CPU_PABRT_NOIFAR=y
++CONFIG_CPU_CACHE_VIVT=y
++CONFIG_CPU_COPY_V4WB=y
++CONFIG_CPU_TLB_V4WBI=y
++CONFIG_CPU_CP15=y
++CONFIG_CPU_CP15_MMU=y
++
++#
++# Processor Features
++#
++CONFIG_ARM_THUMB=y
++# CONFIG_CPU_ICACHE_DISABLE is not set
++# CONFIG_CPU_DCACHE_DISABLE is not set
++# CONFIG_CPU_DCACHE_WRITETHROUGH is not set
++# CONFIG_CPU_CACHE_ROUND_ROBIN is not set
++# CONFIG_OUTER_CACHE is not set
++
++#
++# Bus support
++#
++CONFIG_ARM_AMBA=y
++# CONFIG_PCI_SYSCALL is not set
++# CONFIG_ARCH_SUPPORTS_MSI is not set
++# CONFIG_PCCARD is not set
++
++#
++# Kernel Features
++#
++CONFIG_VMSPLIT_3G=y
++# CONFIG_VMSPLIT_2G is not set
++# CONFIG_VMSPLIT_1G is not set
++CONFIG_PAGE_OFFSET=0xC0000000
++# CONFIG_PREEMPT is not set
++CONFIG_HZ=100
++# CONFIG_AEABI is not set
++CONFIG_ARCH_FLATMEM_HAS_HOLES=y
++# CONFIG_ARCH_SPARSEMEM_DEFAULT is not set
++# CONFIG_ARCH_SELECT_MEMORY_MODEL is not set
++CONFIG_SELECT_MEMORY_MODEL=y
++CONFIG_FLATMEM_MANUAL=y
++# CONFIG_DISCONTIGMEM_MANUAL is not set
++# CONFIG_SPARSEMEM_MANUAL is not set
++CONFIG_FLATMEM=y
++CONFIG_FLAT_NODE_MEM_MAP=y
++CONFIG_PAGEFLAGS_EXTENDED=y
++CONFIG_SPLIT_PTLOCK_CPUS=4096
++# CONFIG_RESOURCES_64BIT is not set
++# CONFIG_PHYS_ADDR_T_64BIT is not set
++CONFIG_ZONE_DMA_FLAG=0
++CONFIG_VIRT_TO_BUS=y
++CONFIG_UNEVICTABLE_LRU=y
++CONFIG_ALIGNMENT_TRAP=y
++
++#
++# Boot options
++#
++CONFIG_ZBOOT_ROM_TEXT=0
++CONFIG_ZBOOT_ROM_BSS=0
++CONFIG_CMDLINE=""
++# CONFIG_XIP_KERNEL is not set
++# CONFIG_KEXEC is not set
++
++#
++# CPU Power Management
++#
++# CONFIG_CPU_IDLE is not set
++
++#
++# Floating point emulation
++#
++
++#
++# At least one emulation must be selected
++#
++CONFIG_FPE_NWFPE=y
++CONFIG_FPE_NWFPE_XP=y
++# CONFIG_FPE_FASTFPE is not set
++CONFIG_VFP=y
++
++#
++# Userspace binary formats
++#
++CONFIG_BINFMT_ELF=y
++# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
++CONFIG_HAVE_AOUT=y
++CONFIG_BINFMT_AOUT=y
++# CONFIG_BINFMT_MISC is not set
++# CONFIG_ARTHUR is not set
++
++#
++# Power management options
++#
++CONFIG_PM=y
++# CONFIG_PM_DEBUG is not set
++CONFIG_PM_SLEEP=y
++CONFIG_SUSPEND=y
++CONFIG_SUSPEND_FREEZER=y
++# CONFIG_APM_EMULATION is not set
++CONFIG_ARCH_SUSPEND_POSSIBLE=y
++CONFIG_NET=y
++
++#
++# Networking options
++#
++CONFIG_PACKET=y
++# CONFIG_PACKET_MMAP is not set
++CONFIG_UNIX=y
++CONFIG_XFRM=y
++# CONFIG_XFRM_USER is not set
++# CONFIG_XFRM_SUB_POLICY is not set
++# CONFIG_XFRM_MIGRATE is not set
++# CONFIG_XFRM_STATISTICS is not set
++# CONFIG_NET_KEY is not set
++CONFIG_INET=y
++CONFIG_IP_MULTICAST=y
++# CONFIG_IP_ADVANCED_ROUTER is not set
++CONFIG_IP_FIB_HASH=y
++CONFIG_IP_PNP=y
++CONFIG_IP_PNP_DHCP=y
++CONFIG_IP_PNP_BOOTP=y
++# CONFIG_IP_PNP_RARP is not set
++# CONFIG_NET_IPIP is not set
++# CONFIG_NET_IPGRE is not set
++# CONFIG_IP_MROUTE is not set
++# CONFIG_ARPD is not set
++# CONFIG_SYN_COOKIES is not set
++# CONFIG_INET_AH is not set
++# CONFIG_INET_ESP is not set
++# CONFIG_INET_IPCOMP is not set
++# CONFIG_INET_XFRM_TUNNEL is not set
++# CONFIG_INET_TUNNEL is not set
++CONFIG_INET_XFRM_MODE_TRANSPORT=y
++CONFIG_INET_XFRM_MODE_TUNNEL=y
++CONFIG_INET_XFRM_MODE_BEET=y
++# CONFIG_INET_LRO is not set
++CONFIG_INET_DIAG=y
++CONFIG_INET_TCP_DIAG=y
++# CONFIG_TCP_CONG_ADVANCED is not set
++CONFIG_TCP_CONG_CUBIC=y
++CONFIG_DEFAULT_TCP_CONG="cubic"
++# CONFIG_TCP_MD5SIG is not set
++# CONFIG_IPV6 is not set
++# CONFIG_NETWORK_SECMARK is not set
++# CONFIG_NETFILTER is not set
++# CONFIG_IP_DCCP is not set
++# CONFIG_IP_SCTP is not set
++# CONFIG_TIPC is not set
++# CONFIG_ATM is not set
++# CONFIG_BRIDGE is not set
++# CONFIG_NET_DSA is not set
++# CONFIG_VLAN_8021Q is not set
++# CONFIG_DECNET is not set
++# CONFIG_LLC2 is not set
++# CONFIG_IPX is not set
++# CONFIG_ATALK is not set
++# CONFIG_X25 is not set
++# CONFIG_LAPB is not set
++# CONFIG_ECONET is not set
++CONFIG_WAN_ROUTER=y
++# CONFIG_NET_SCHED is not set
++
++#
++# Network testing
++#
++# CONFIG_NET_PKTGEN is not set
++# CONFIG_HAMRADIO is not set
++# CONFIG_CAN is not set
++# CONFIG_IRDA is not set
++# CONFIG_BT is not set
++# CONFIG_AF_RXRPC is not set
++# CONFIG_PHONET is not set
++# CONFIG_WIRELESS is not set
++# CONFIG_RFKILL is not set
++# CONFIG_NET_9P is not set
++
++#
++# Device Drivers
++#
++
++#
++# Generic Driver Options
++#
++CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
++CONFIG_STANDALONE=y
++CONFIG_PREVENT_FIRMWARE_BUILD=y
++CONFIG_FW_LOADER=y
++CONFIG_FIRMWARE_IN_KERNEL=y
++CONFIG_EXTRA_FIRMWARE=""
++# CONFIG_SYS_HYPERVISOR is not set
++CONFIG_CONNECTOR=y
++CONFIG_PROC_EVENTS=y
++# CONFIG_MTD is not set
++# CONFIG_PARPORT is not set
++CONFIG_BLK_DEV=y
++# CONFIG_BLK_DEV_COW_COMMON is not set
++CONFIG_BLK_DEV_LOOP=y
++# CONFIG_BLK_DEV_CRYPTOLOOP is not set
++CONFIG_BLK_DEV_NBD=m
++CONFIG_BLK_DEV_RAM=y
++CONFIG_BLK_DEV_RAM_COUNT=16
++CONFIG_BLK_DEV_RAM_SIZE=16384
++# CONFIG_BLK_DEV_XIP is not set
++# CONFIG_CDROM_PKTCDVD is not set
++# CONFIG_ATA_OVER_ETH is not set
++CONFIG_MISC_DEVICES=y
++# CONFIG_EEPROM_93CX6 is not set
++# CONFIG_ICS932S401 is not set
++# CONFIG_ENCLOSURE_SERVICES is not set
++# CONFIG_C2PORT is not set
++CONFIG_HAVE_IDE=y
++# CONFIG_IDE is not set
++
++#
++# SCSI device support
++#
++# CONFIG_RAID_ATTRS is not set
++CONFIG_SCSI=y
++CONFIG_SCSI_DMA=y
++CONFIG_SCSI_TGT=y
++# CONFIG_SCSI_NETLINK is not set
++CONFIG_SCSI_PROC_FS=y
++
++#
++# SCSI support type (disk, tape, CD-ROM)
++#
++CONFIG_BLK_DEV_SD=y
++# CONFIG_CHR_DEV_ST is not set
++# CONFIG_CHR_DEV_OSST is not set
++# CONFIG_BLK_DEV_SR is not set
++CONFIG_CHR_DEV_SG=y
++# CONFIG_CHR_DEV_SCH is not set
++
++#
++# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
++#
++# CONFIG_SCSI_MULTI_LUN is not set
++# CONFIG_SCSI_CONSTANTS is not set
++# CONFIG_SCSI_LOGGING is not set
++CONFIG_SCSI_SCAN_ASYNC=y
++CONFIG_SCSI_WAIT_SCAN=m
++
++#
++# SCSI Transports
++#
++# CONFIG_SCSI_SPI_ATTRS is not set
++# CONFIG_SCSI_FC_ATTRS is not set
++CONFIG_SCSI_ISCSI_ATTRS=m
++# CONFIG_SCSI_SAS_LIBSAS is not set
++# CONFIG_SCSI_SRP_ATTRS is not set
++# CONFIG_SCSI_LOWLEVEL is not set
++# CONFIG_SCSI_DH is not set
++# CONFIG_ATA is not set
++# CONFIG_MD is not set
++CONFIG_NETDEVICES=y
++# CONFIG_DUMMY is not set
++# CONFIG_BONDING is not set
++# CONFIG_MACVLAN is not set
++# CONFIG_EQUALIZER is not set
++# CONFIG_TUN is not set
++# CONFIG_VETH is not set
++# CONFIG_NET_ETHERNET is not set
++CONFIG_NETDEV_1000=y
++CONFIG_ASPEEDMAC=y
++# CONFIG_MAC0_PHY_LINK is not set
++# CONFIG_NETDEV_10000 is not set
++
++#
++# Wireless LAN
++#
++# CONFIG_WLAN_PRE80211 is not set
++# CONFIG_WLAN_80211 is not set
++# CONFIG_IWLWIFI_LEDS is not set
++# CONFIG_WAN is not set
++# CONFIG_PPP is not set
++# CONFIG_SLIP is not set
++# CONFIG_NETCONSOLE is not set
++# CONFIG_NETPOLL is not set
++# CONFIG_NET_POLL_CONTROLLER is not set
++# CONFIG_ISDN is not set
++
++#
++# Input device support
++#
++CONFIG_INPUT=y
++# CONFIG_INPUT_FF_MEMLESS is not set
++# CONFIG_INPUT_POLLDEV is not set
++
++#
++# Userland interfaces
++#
++CONFIG_INPUT_MOUSEDEV=y
++CONFIG_INPUT_MOUSEDEV_PSAUX=y
++CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
++CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
++# CONFIG_INPUT_JOYDEV is not set
++CONFIG_INPUT_EVDEV=y
++# CONFIG_INPUT_EVBUG is not set
++
++#
++# Input Device Drivers
++#
++CONFIG_INPUT_KEYBOARD=y
++CONFIG_KEYBOARD_ATKBD=y
++# CONFIG_KEYBOARD_SUNKBD is not set
++# CONFIG_KEYBOARD_LKKBD is not set
++# CONFIG_KEYBOARD_XTKBD is not set
++# CONFIG_KEYBOARD_NEWTON is not set
++# CONFIG_KEYBOARD_STOWAWAY is not set
++# CONFIG_KEYBOARD_GPIO is not set
++CONFIG_INPUT_MOUSE=y
++CONFIG_MOUSE_PS2=y
++CONFIG_MOUSE_PS2_ALPS=y
++CONFIG_MOUSE_PS2_LOGIPS2PP=y
++CONFIG_MOUSE_PS2_SYNAPTICS=y
++CONFIG_MOUSE_PS2_LIFEBOOK=y
++CONFIG_MOUSE_PS2_TRACKPOINT=y
++# CONFIG_MOUSE_PS2_ELANTECH is not set
++# CONFIG_MOUSE_PS2_TOUCHKIT is not set
++CONFIG_MOUSE_SERIAL=y
++# CONFIG_MOUSE_VSXXXAA is not set
++# CONFIG_MOUSE_GPIO is not set
++# CONFIG_INPUT_JOYSTICK is not set
++# CONFIG_INPUT_TABLET is not set
++# CONFIG_INPUT_TOUCHSCREEN is not set
++# CONFIG_INPUT_MISC is not set
++
++#
++# Hardware I/O ports
++#
++CONFIG_SERIO=y
++CONFIG_SERIO_SERPORT=y
++# CONFIG_SERIO_AMBAKMI is not set
++CONFIG_SERIO_LIBPS2=y
++# CONFIG_SERIO_RAW is not set
++# CONFIG_GAMEPORT is not set
++
++#
++# Character devices
++#
++CONFIG_VT=y
++CONFIG_CONSOLE_TRANSLATIONS=y
++CONFIG_VT_CONSOLE=y
++CONFIG_HW_CONSOLE=y
++# CONFIG_VT_HW_CONSOLE_BINDING is not set
++CONFIG_DEVKMEM=y
++CONFIG_SERIAL_NONSTANDARD=y
++# CONFIG_N_HDLC is not set
++# CONFIG_RISCOM8 is not set
++# CONFIG_SPECIALIX is not set
++# CONFIG_RIO is not set
++# CONFIG_STALDRV is not set
++
++#
++# Serial drivers
++#
++CONFIG_SERIAL_8250=y
++CONFIG_SERIAL_8250_CONSOLE=y
++CONFIG_SERIAL_8250_NR_UARTS=3
++CONFIG_SERIAL_8250_RUNTIME_UARTS=3
++CONFIG_SERIAL_AST_DMA_UART=y
++CONFIG_AST_NR_DMA_UARTS=4
++CONFIG_AST_RUNTIME_DMA_UARTS=4
++# CONFIG_SERIAL_8250_EXTENDED is not set
++
++#
++# Non-8250 serial port support
++#
++# CONFIG_SERIAL_AMBA_PL010 is not set
++# CONFIG_SERIAL_AMBA_PL011 is not set
++# CONFIG_SERIAL_AST is not set
++CONFIG_SERIAL_CORE=y
++CONFIG_SERIAL_CORE_CONSOLE=y
++CONFIG_UNIX98_PTYS=y
++CONFIG_LEGACY_PTYS=y
++CONFIG_LEGACY_PTY_COUNT=256
++# CONFIG_IPMI_HANDLER is not set
++# CONFIG_AST_MISC is not set
++# CONFIG_HW_RANDOM is not set
++CONFIG_NVRAM=y
++# CONFIG_R3964 is not set
++# CONFIG_RAW_DRIVER is not set
++# CONFIG_TCG_TPM is not set
++CONFIG_I2C=y
++CONFIG_I2C_BOARDINFO=y
++CONFIG_I2C_CHARDEV=y
++CONFIG_I2C_HELPER_AUTO=y
++
++#
++# I2C Hardware Bus support
++#
++
++#
++# I2C system bus drivers (mostly embedded / system-on-chip)
++#
++# CONFIG_I2C_GPIO is not set
++# CONFIG_I2C_OCORES is not set
++CONFIG_I2C_AST=y
++CONFIG_I2C_AST1070=y
++CONFIG_AST_I2C_SLAVE_MODE=y
++CONFIG_AST_I2C_SLAVE_EEPROM=y
++# CONFIG_AST_I2C_SLAVE_RDWR is not set
++# CONFIG_I2C_SIMTEC is not set
++
++#
++# External I2C/SMBus adapter drivers
++#
++# CONFIG_I2C_PARPORT_LIGHT is not set
++# CONFIG_I2C_TAOS_EVM is not set
++
++#
++# Other I2C/SMBus bus drivers
++#
++# CONFIG_I2C_PCA_PLATFORM is not set
++# CONFIG_I2C_STUB is not set
++
++#
++# Miscellaneous I2C Chip support
++#
++# CONFIG_DS1682 is not set
++# CONFIG_AT24 is not set
++# CONFIG_SENSORS_EEPROM is not set
++# CONFIG_SENSORS_PCF8574 is not set
++# CONFIG_PCF8575 is not set
++# CONFIG_SENSORS_PCA9539 is not set
++# CONFIG_SENSORS_PCF8591 is not set
++# CONFIG_TPS65010 is not set
++# CONFIG_SENSORS_MAX6875 is not set
++# CONFIG_SENSORS_TSL2550 is not set
++# CONFIG_I2C_DEBUG_CORE is not set
++# CONFIG_I2C_DEBUG_ALGO is not set
++# CONFIG_I2C_DEBUG_BUS is not set
++# CONFIG_I2C_DEBUG_CHIP is not set
++# CONFIG_SPI is not set
++CONFIG_ARCH_REQUIRE_GPIOLIB=y
++CONFIG_GPIOLIB=y
++CONFIG_GPIO_SYSFS=y
++
++#
++# Memory mapped GPIO expanders:
++#
++
++#
++# I2C GPIO expanders:
++#
++# CONFIG_GPIO_MAX732X is not set
++# CONFIG_GPIO_PCA953X is not set
++# CONFIG_GPIO_PCF857X is not set
++
++#
++# PCI GPIO expanders:
++#
++
++#
++# SPI GPIO expanders:
++#
++# CONFIG_W1 is not set
++# CONFIG_POWER_SUPPLY is not set
++# CONFIG_HWMON is not set
++# CONFIG_THERMAL is not set
++# CONFIG_THERMAL_HWMON is not set
++# CONFIG_WATCHDOG is not set
++CONFIG_SSB_POSSIBLE=y
++
++#
++# Sonics Silicon Backplane
++#
++# CONFIG_SSB is not set
++
++#
++# Multifunction device drivers
++#
++# CONFIG_MFD_CORE is not set
++# CONFIG_MFD_SM501 is not set
++# CONFIG_MFD_ASIC3 is not set
++# CONFIG_HTC_EGPIO is not set
++# CONFIG_HTC_PASIC3 is not set
++# CONFIG_MFD_TMIO is not set
++# CONFIG_MFD_TC6393XB is not set
++# CONFIG_PMIC_DA903X is not set
++# CONFIG_MFD_WM8400 is not set
++# CONFIG_MFD_WM8350_I2C is not set
++
++#
++# Multimedia devices
++#
++
++#
++# Multimedia core support
++#
++# CONFIG_VIDEO_DEV is not set
++# CONFIG_DVB_CORE is not set
++# CONFIG_VIDEO_MEDIA is not set
++
++#
++# Multimedia drivers
++#
++# CONFIG_DAB is not set
++
++#
++# Graphics support
++#
++# CONFIG_VGASTATE is not set
++# CONFIG_VIDEO_OUTPUT_CONTROL is not set
++# CONFIG_FB is not set
++# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
++
++#
++# Display device support
++#
++# CONFIG_DISPLAY_SUPPORT is not set
++
++#
++# Console display driver support
++#
++# CONFIG_VGA_CONSOLE is not set
++CONFIG_DUMMY_CONSOLE=y
++# CONFIG_SOUND is not set
++# CONFIG_HID_SUPPORT is not set
++# CONFIG_USB_SUPPORT is not set
++CONFIG_USB_ARCH_HAS_EHCI=y
++# CONFIG_MMC is not set
++# CONFIG_MEMSTICK is not set
++# CONFIG_ACCESSIBILITY is not set
++# CONFIG_NEW_LEDS is not set
++CONFIG_RTC_LIB=y
++# CONFIG_RTC_CLASS is not set
++# CONFIG_DMADEVICES is not set
++# CONFIG_REGULATOR is not set
++# CONFIG_UIO is not set
++
++#
++# File systems
++#
++CONFIG_EXT2_FS=y
++CONFIG_EXT2_FS_XATTR=y
++CONFIG_EXT2_FS_POSIX_ACL=y
++CONFIG_EXT2_FS_SECURITY=y
++# CONFIG_EXT2_FS_XIP is not set
++# CONFIG_EXT3_FS is not set
++# CONFIG_EXT4_FS is not set
++CONFIG_FS_MBCACHE=y
++# CONFIG_REISERFS_FS is not set
++# CONFIG_JFS_FS is not set
++CONFIG_FS_POSIX_ACL=y
++CONFIG_FILE_LOCKING=y
++# CONFIG_XFS_FS is not set
++# CONFIG_OCFS2_FS is not set
++CONFIG_DNOTIFY=y
++CONFIG_INOTIFY=y
++CONFIG_INOTIFY_USER=y
++# CONFIG_QUOTA is not set
++# CONFIG_AUTOFS_FS is not set
++# CONFIG_AUTOFS4_FS is not set
++# CONFIG_FUSE_FS is not set
++CONFIG_GENERIC_ACL=y
++
++#
++# CD-ROM/DVD Filesystems
++#
++# CONFIG_ISO9660_FS is not set
++# CONFIG_UDF_FS is not set
++
++#
++# DOS/FAT/NT Filesystems
++#
++CONFIG_FAT_FS=y
++CONFIG_MSDOS_FS=y
++CONFIG_VFAT_FS=y
++CONFIG_FAT_DEFAULT_CODEPAGE=437
++CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
++CONFIG_NTFS_FS=y
++# CONFIG_NTFS_DEBUG is not set
++CONFIG_NTFS_RW=y
++
++#
++# Pseudo filesystems
++#
++CONFIG_PROC_FS=y
++CONFIG_PROC_SYSCTL=y
++CONFIG_PROC_PAGE_MONITOR=y
++CONFIG_SYSFS=y
++CONFIG_TMPFS=y
++CONFIG_TMPFS_POSIX_ACL=y
++# CONFIG_HUGETLB_PAGE is not set
++CONFIG_CONFIGFS_FS=m
++
++#
++# Miscellaneous filesystems
++#
++# CONFIG_ADFS_FS is not set
++# CONFIG_AFFS_FS is not set
++# CONFIG_HFS_FS is not set
++# CONFIG_HFSPLUS_FS is not set
++# CONFIG_BEFS_FS is not set
++# CONFIG_BFS_FS is not set
++# CONFIG_EFS_FS is not set
++# CONFIG_CRAMFS is not set
++# CONFIG_VXFS_FS is not set
++# CONFIG_MINIX_FS is not set
++# CONFIG_OMFS_FS is not set
++# CONFIG_HPFS_FS is not set
++# CONFIG_QNX4FS_FS is not set
++# CONFIG_ROMFS_FS is not set
++# CONFIG_SYSV_FS is not set
++# CONFIG_UFS_FS is not set
++CONFIG_NETWORK_FILESYSTEMS=y
++CONFIG_NFS_FS=y
++# CONFIG_NFS_V3 is not set
++# CONFIG_NFS_V4 is not set
++CONFIG_ROOT_NFS=y
++# CONFIG_NFSD is not set
++CONFIG_LOCKD=y
++CONFIG_NFS_COMMON=y
++CONFIG_SUNRPC=y
++# CONFIG_SUNRPC_REGISTER_V4 is not set
++# CONFIG_RPCSEC_GSS_KRB5 is not set
++# CONFIG_RPCSEC_GSS_SPKM3 is not set
++# CONFIG_SMB_FS is not set
++# CONFIG_CIFS is not set
++# CONFIG_NCP_FS is not set
++# CONFIG_CODA_FS is not set
++# CONFIG_AFS_FS is not set
++
++#
++# Partition Types
++#
++# CONFIG_PARTITION_ADVANCED is not set
++CONFIG_MSDOS_PARTITION=y
++CONFIG_NLS=y
++CONFIG_NLS_DEFAULT="utf8"
++CONFIG_NLS_CODEPAGE_437=y
++# CONFIG_NLS_CODEPAGE_737 is not set
++# CONFIG_NLS_CODEPAGE_775 is not set
++# CONFIG_NLS_CODEPAGE_850 is not set
++# CONFIG_NLS_CODEPAGE_852 is not set
++# CONFIG_NLS_CODEPAGE_855 is not set
++# CONFIG_NLS_CODEPAGE_857 is not set
++# CONFIG_NLS_CODEPAGE_860 is not set
++# CONFIG_NLS_CODEPAGE_861 is not set
++# CONFIG_NLS_CODEPAGE_862 is not set
++# CONFIG_NLS_CODEPAGE_863 is not set
++# CONFIG_NLS_CODEPAGE_864 is not set
++# CONFIG_NLS_CODEPAGE_865 is not set
++# CONFIG_NLS_CODEPAGE_866 is not set
++# CONFIG_NLS_CODEPAGE_869 is not set
++CONFIG_NLS_CODEPAGE_936=y
++CONFIG_NLS_CODEPAGE_950=y
++CONFIG_NLS_CODEPAGE_932=y
++# CONFIG_NLS_CODEPAGE_949 is not set
++# CONFIG_NLS_CODEPAGE_874 is not set
++# CONFIG_NLS_ISO8859_8 is not set
++# CONFIG_NLS_CODEPAGE_1250 is not set
++# CONFIG_NLS_CODEPAGE_1251 is not set
++CONFIG_NLS_ASCII=y
++CONFIG_NLS_ISO8859_1=y
++# CONFIG_NLS_ISO8859_2 is not set
++# CONFIG_NLS_ISO8859_3 is not set
++# CONFIG_NLS_ISO8859_4 is not set
++# CONFIG_NLS_ISO8859_5 is not set
++# CONFIG_NLS_ISO8859_6 is not set
++# CONFIG_NLS_ISO8859_7 is not set
++# CONFIG_NLS_ISO8859_9 is not set
++# CONFIG_NLS_ISO8859_13 is not set
++# CONFIG_NLS_ISO8859_14 is not set
++# CONFIG_NLS_ISO8859_15 is not set
++# CONFIG_NLS_KOI8_R is not set
++# CONFIG_NLS_KOI8_U is not set
++CONFIG_NLS_UTF8=y
++# CONFIG_DLM is not set
++
++#
++# Kernel hacking
++#
++# CONFIG_PRINTK_TIME is not set
++# CONFIG_ENABLE_WARN_DEPRECATED is not set
++CONFIG_ENABLE_MUST_CHECK=y
++CONFIG_FRAME_WARN=1024
++CONFIG_MAGIC_SYSRQ=y
++# CONFIG_UNUSED_SYMBOLS is not set
++# CONFIG_DEBUG_FS is not set
++# CONFIG_HEADERS_CHECK is not set
++# CONFIG_DEBUG_KERNEL is not set
++# CONFIG_SLUB_DEBUG_ON is not set
++# CONFIG_SLUB_STATS is not set
++CONFIG_DEBUG_BUGVERBOSE=y
++CONFIG_DEBUG_MEMORY_INIT=y
++CONFIG_FRAME_POINTER=y
++# CONFIG_RCU_CPU_STALL_DETECTOR is not set
++# CONFIG_LATENCYTOP is not set
++# CONFIG_SYSCTL_SYSCALL_CHECK is not set
++CONFIG_HAVE_FUNCTION_TRACER=y
++
++#
++# Tracers
++#
++# CONFIG_DYNAMIC_PRINTK_DEBUG is not set
++# CONFIG_SAMPLES is not set
++CONFIG_HAVE_ARCH_KGDB=y
++# CONFIG_DEBUG_USER is not set
++
++#
++# Security options
++#
++# CONFIG_KEYS is not set
++# CONFIG_SECURITY is not set
++# CONFIG_SECURITYFS is not set
++# CONFIG_SECURITY_FILE_CAPABILITIES is not set
++CONFIG_CRYPTO=y
++
++#
++# Crypto core or helper
++#
++# CONFIG_CRYPTO_FIPS is not set
++CONFIG_CRYPTO_ALGAPI=y
++CONFIG_CRYPTO_ALGAPI2=y
++CONFIG_CRYPTO_AEAD=m
++CONFIG_CRYPTO_AEAD2=y
++CONFIG_CRYPTO_BLKCIPHER=y
++CONFIG_CRYPTO_BLKCIPHER2=y
++CONFIG_CRYPTO_HASH=y
++CONFIG_CRYPTO_HASH2=y
++CONFIG_CRYPTO_RNG2=y
++CONFIG_CRYPTO_MANAGER=y
++CONFIG_CRYPTO_MANAGER2=y
++# CONFIG_CRYPTO_GF128MUL is not set
++CONFIG_CRYPTO_NULL=y
++# CONFIG_CRYPTO_CRYPTD is not set
++CONFIG_CRYPTO_AUTHENC=m
++# CONFIG_CRYPTO_TEST is not set
++
++#
++# Authenticated Encryption with Associated Data
++#
++# CONFIG_CRYPTO_CCM is not set
++# CONFIG_CRYPTO_GCM is not set
++# CONFIG_CRYPTO_SEQIV is not set
++
++#
++# Block modes
++#
++CONFIG_CRYPTO_CBC=y
++# CONFIG_CRYPTO_CTR is not set
++# CONFIG_CRYPTO_CTS is not set
++# CONFIG_CRYPTO_ECB is not set
++# CONFIG_CRYPTO_LRW is not set
++# CONFIG_CRYPTO_PCBC is not set
++# CONFIG_CRYPTO_XTS is not set
++
++#
++# Hash modes
++#
++CONFIG_CRYPTO_HMAC=y
++# CONFIG_CRYPTO_XCBC is not set
++
++#
++# Digest
++#
++# CONFIG_CRYPTO_CRC32C is not set
++# CONFIG_CRYPTO_MD4 is not set
++CONFIG_CRYPTO_MD5=y
++# CONFIG_CRYPTO_MICHAEL_MIC is not set
++# CONFIG_CRYPTO_RMD128 is not set
++# CONFIG_CRYPTO_RMD160 is not set
++# CONFIG_CRYPTO_RMD256 is not set
++# CONFIG_CRYPTO_RMD320 is not set
++CONFIG_CRYPTO_SHA1=y
++# CONFIG_CRYPTO_SHA256 is not set
++# CONFIG_CRYPTO_SHA512 is not set
++# CONFIG_CRYPTO_TGR192 is not set
++# CONFIG_CRYPTO_WP512 is not set
++
++#
++# Ciphers
++#
++# CONFIG_CRYPTO_AES is not set
++# CONFIG_CRYPTO_ANUBIS is not set
++# CONFIG_CRYPTO_ARC4 is not set
++# CONFIG_CRYPTO_BLOWFISH is not set
++# CONFIG_CRYPTO_CAMELLIA is not set
++# CONFIG_CRYPTO_CAST5 is not set
++# CONFIG_CRYPTO_CAST6 is not set
++CONFIG_CRYPTO_DES=y
++# CONFIG_CRYPTO_FCRYPT is not set
++# CONFIG_CRYPTO_KHAZAD is not set
++# CONFIG_CRYPTO_SALSA20 is not set
++# CONFIG_CRYPTO_SEED is not set
++# CONFIG_CRYPTO_SERPENT is not set
++# CONFIG_CRYPTO_TEA is not set
++# CONFIG_CRYPTO_TWOFISH is not set
++
++#
++# Compression
++#
++CONFIG_CRYPTO_DEFLATE=m
++# CONFIG_CRYPTO_LZO is not set
++
++#
++# Random Number Generation
++#
++# CONFIG_CRYPTO_ANSI_CPRNG is not set
++# CONFIG_CRYPTO_HW is not set
++
++#
++# Library routines
++#
++CONFIG_BITREVERSE=y
++# CONFIG_CRC_CCITT is not set
++# CONFIG_CRC16 is not set
++# CONFIG_CRC_T10DIF is not set
++CONFIG_CRC_ITU_T=m
++CONFIG_CRC32=y
++# CONFIG_CRC7 is not set
++# CONFIG_LIBCRC32C is not set
++CONFIG_ZLIB_INFLATE=m
++CONFIG_ZLIB_DEFLATE=m
++CONFIG_PLIST=y
++CONFIG_HAS_IOMEM=y
++CONFIG_HAS_IOPORT=y
++CONFIG_HAS_DMA=y
+diff --git a/arch/arm/configs/ast2400_ast1070_defconfig b/arch/arm/configs/ast2400_ast1070_defconfig
+new file mode 100644
+index 0000000..552523e
+--- /dev/null
++++ b/arch/arm/configs/ast2400_ast1070_defconfig
+@@ -0,0 +1,1036 @@
++#
++# Automatically generated make config: don't edit
++# Linux kernel version: 2.6.28.9
++# Mon Jul 15 18:21:08 2013
++#
++CONFIG_ARM=y
++CONFIG_SYS_SUPPORTS_APM_EMULATION=y
++CONFIG_GENERIC_GPIO=y
++# CONFIG_GENERIC_TIME is not set
++# CONFIG_GENERIC_CLOCKEVENTS is not set
++CONFIG_MMU=y
++# CONFIG_NO_IOPORT is not set
++CONFIG_GENERIC_HARDIRQS=y
++CONFIG_STACKTRACE_SUPPORT=y
++CONFIG_HAVE_LATENCYTOP_SUPPORT=y
++CONFIG_LOCKDEP_SUPPORT=y
++CONFIG_TRACE_IRQFLAGS_SUPPORT=y
++CONFIG_HARDIRQS_SW_RESEND=y
++CONFIG_GENERIC_IRQ_PROBE=y
++CONFIG_RWSEM_GENERIC_SPINLOCK=y
++# CONFIG_ARCH_HAS_ILOG2_U32 is not set
++# CONFIG_ARCH_HAS_ILOG2_U64 is not set
++CONFIG_GENERIC_HWEIGHT=y
++CONFIG_GENERIC_CALIBRATE_DELAY=y
++CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
++CONFIG_VECTORS_BASE=0xffff0000
++CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
++
++#
++# General setup
++#
++CONFIG_EXPERIMENTAL=y
++CONFIG_BROKEN_ON_SMP=y
++CONFIG_INIT_ENV_ARG_LIMIT=32
++CONFIG_LOCALVERSION=""
++# CONFIG_LOCALVERSION_AUTO is not set
++CONFIG_SWAP=y
++CONFIG_SYSVIPC=y
++CONFIG_SYSVIPC_SYSCTL=y
++# CONFIG_POSIX_MQUEUE is not set
++# CONFIG_BSD_PROCESS_ACCT is not set
++# CONFIG_TASKSTATS is not set
++# CONFIG_AUDIT is not set
++# CONFIG_IKCONFIG is not set
++CONFIG_LOG_BUF_SHIFT=16
++# CONFIG_CGROUPS is not set
++# CONFIG_GROUP_SCHED is not set
++CONFIG_SYSFS_DEPRECATED=y
++CONFIG_SYSFS_DEPRECATED_V2=y
++# CONFIG_RELAY is not set
++CONFIG_NAMESPACES=y
++# CONFIG_UTS_NS is not set
++# CONFIG_IPC_NS is not set
++# CONFIG_USER_NS is not set
++# CONFIG_PID_NS is not set
++CONFIG_BLK_DEV_INITRD=y
++CONFIG_INITRAMFS_SOURCE=""
++CONFIG_CC_OPTIMIZE_FOR_SIZE=y
++CONFIG_SYSCTL=y
++CONFIG_ANON_INODES=y
++# CONFIG_EMBEDDED is not set
++CONFIG_UID16=y
++CONFIG_SYSCTL_SYSCALL=y
++CONFIG_KALLSYMS=y
++CONFIG_KALLSYMS_EXTRA_PASS=y
++CONFIG_HOTPLUG=y
++CONFIG_PRINTK=y
++CONFIG_BUG=y
++CONFIG_ELF_CORE=y
++CONFIG_BASE_FULL=y
++CONFIG_FUTEX=y
++CONFIG_EPOLL=y
++CONFIG_SIGNALFD=y
++CONFIG_TIMERFD=y
++CONFIG_EVENTFD=y
++CONFIG_SHMEM=y
++CONFIG_AIO=y
++CONFIG_VM_EVENT_COUNTERS=y
++CONFIG_SLUB_DEBUG=y
++CONFIG_COMPAT_BRK=y
++# CONFIG_SLAB is not set
++CONFIG_SLUB=y
++# CONFIG_SLOB is not set
++# CONFIG_PROFILING is not set
++# CONFIG_MARKERS is not set
++CONFIG_HAVE_OPROFILE=y
++# CONFIG_KPROBES is not set
++CONFIG_HAVE_KPROBES=y
++CONFIG_HAVE_KRETPROBES=y
++CONFIG_HAVE_GENERIC_DMA_COHERENT=y
++CONFIG_SLABINFO=y
++CONFIG_RT_MUTEXES=y
++# CONFIG_TINY_SHMEM is not set
++CONFIG_BASE_SMALL=0
++CONFIG_MODULES=y
++# CONFIG_MODULE_FORCE_LOAD is not set
++CONFIG_MODULE_UNLOAD=y
++# CONFIG_MODULE_FORCE_UNLOAD is not set
++# CONFIG_MODVERSIONS is not set
++# CONFIG_MODULE_SRCVERSION_ALL is not set
++CONFIG_KMOD=y
++CONFIG_BLOCK=y
++# CONFIG_LBD is not set
++# CONFIG_BLK_DEV_IO_TRACE is not set
++# CONFIG_LSF is not set
++# CONFIG_BLK_DEV_BSG is not set
++# CONFIG_BLK_DEV_INTEGRITY is not set
++
++#
++# IO Schedulers
++#
++CONFIG_IOSCHED_NOOP=y
++CONFIG_IOSCHED_AS=y
++CONFIG_IOSCHED_DEADLINE=y
++CONFIG_IOSCHED_CFQ=y
++# CONFIG_DEFAULT_AS is not set
++# CONFIG_DEFAULT_DEADLINE is not set
++CONFIG_DEFAULT_CFQ=y
++# CONFIG_DEFAULT_NOOP is not set
++CONFIG_DEFAULT_IOSCHED="cfq"
++CONFIG_CLASSIC_RCU=y
++CONFIG_FREEZER=y
++
++#
++# System Type
++#
++CONFIG_ARCH_ASPEED=y
++# CONFIG_ARCH_AAEC2000 is not set
++# CONFIG_ARCH_INTEGRATOR is not set
++# CONFIG_ARCH_REALVIEW is not set
++# CONFIG_ARCH_VERSATILE is not set
++# CONFIG_ARCH_AT91 is not set
++# CONFIG_ARCH_CLPS7500 is not set
++# CONFIG_ARCH_CLPS711X is not set
++# CONFIG_ARCH_EBSA110 is not set
++# CONFIG_ARCH_EP93XX is not set
++# CONFIG_ARCH_FOOTBRIDGE is not set
++# CONFIG_ARCH_NETX is not set
++# CONFIG_ARCH_H720X is not set
++# CONFIG_ARCH_IMX is not set
++# CONFIG_ARCH_IOP13XX is not set
++# CONFIG_ARCH_IOP32X is not set
++# CONFIG_ARCH_IOP33X is not set
++# CONFIG_ARCH_IXP23XX is not set
++# CONFIG_ARCH_IXP2000 is not set
++# CONFIG_ARCH_IXP4XX is not set
++# CONFIG_ARCH_L7200 is not set
++# CONFIG_ARCH_KIRKWOOD is not set
++# CONFIG_ARCH_KS8695 is not set
++# CONFIG_ARCH_NS9XXX is not set
++# CONFIG_ARCH_LOKI is not set
++# CONFIG_ARCH_MV78XX0 is not set
++# CONFIG_ARCH_MXC is not set
++# CONFIG_ARCH_ORION5X is not set
++# CONFIG_ARCH_PNX4008 is not set
++# CONFIG_ARCH_PXA is not set
++# CONFIG_ARCH_RPC is not set
++# CONFIG_ARCH_SA1100 is not set
++# CONFIG_ARCH_S3C2410 is not set
++# CONFIG_ARCH_SHARK is not set
++# CONFIG_ARCH_LH7A40X is not set
++# CONFIG_ARCH_DAVINCI is not set
++# CONFIG_ARCH_OMAP is not set
++# CONFIG_ARCH_MSM is not set
++CONFIG_IRMP=y
++# CONFIG_PCEXT is not set
++# CONFIG_REMOTEFX is not set
++# CONFIG_ARCH_AST1100 is not set
++# CONFIG_ARCH_AST2100 is not set
++# CONFIG_ARCH_AST2200 is not set
++# CONFIG_ARCH_AST2300 is not set
++CONFIG_ARCH_AST2400=y
++# CONFIG_ARCH_AST2500 is not set
++
++#
++# FLASH Chip Select
++#
++CONFIG_AST_CS0_NOR=y
++# CONFIG_AST_CS0_NAND is not set
++# CONFIG_AST_CS0_SPI is not set
++# CONFIG_AST_CS0_NONE is not set
++CONFIG_AST_CS1_NOR=y
++# CONFIG_AST_CS1_NAND is not set
++# CONFIG_AST_CS1_SPI is not set
++# CONFIG_AST_CS1_NONE is not set
++CONFIG_AST_CS2_NOR=y
++# CONFIG_AST_CS2_NAND is not set
++# CONFIG_AST_CS2_SPI is not set
++# CONFIG_AST_CS2_NONE is not set
++CONFIG_AST_CS3_NOR=y
++# CONFIG_AST_CS3_NAND is not set
++# CONFIG_AST_CS3_SPI is not set
++# CONFIG_AST_CS3_NONE is not set
++CONFIG_AST_CS4_NOR=y
++# CONFIG_AST_CS4_NAND is not set
++# CONFIG_AST_CS4_SPI is not set
++# CONFIG_AST_CS4_NONE is not set
++CONFIG_ARCH_AST1070=y
++CONFIG_AST1070_NR=2
++CONFIG_AST_LPC_PLUS=y
++# CONFIG_AST_LPC is not set
++# CONFIG_AST_SCU_LOCK is not set
++
++#
++# Boot options
++#
++
++#
++# Power management
++#
++CONFIG_PLAT_ASPEED=y
++
++#
++# Processor Type
++#
++CONFIG_CPU_32=y
++CONFIG_CPU_ARM926T=y
++CONFIG_CPU_32v5=y
++CONFIG_CPU_ABRT_EV5TJ=y
++CONFIG_CPU_PABRT_NOIFAR=y
++CONFIG_CPU_CACHE_VIVT=y
++CONFIG_CPU_COPY_V4WB=y
++CONFIG_CPU_TLB_V4WBI=y
++CONFIG_CPU_CP15=y
++CONFIG_CPU_CP15_MMU=y
++
++#
++# Processor Features
++#
++CONFIG_ARM_THUMB=y
++# CONFIG_CPU_ICACHE_DISABLE is not set
++# CONFIG_CPU_DCACHE_DISABLE is not set
++# CONFIG_CPU_DCACHE_WRITETHROUGH is not set
++# CONFIG_CPU_CACHE_ROUND_ROBIN is not set
++# CONFIG_OUTER_CACHE is not set
++
++#
++# Bus support
++#
++CONFIG_ARM_AMBA=y
++# CONFIG_PCI_SYSCALL is not set
++# CONFIG_ARCH_SUPPORTS_MSI is not set
++# CONFIG_PCCARD is not set
++
++#
++# Kernel Features
++#
++CONFIG_VMSPLIT_3G=y
++# CONFIG_VMSPLIT_2G is not set
++# CONFIG_VMSPLIT_1G is not set
++CONFIG_PAGE_OFFSET=0xC0000000
++# CONFIG_PREEMPT is not set
++CONFIG_HZ=100
++# CONFIG_AEABI is not set
++CONFIG_ARCH_FLATMEM_HAS_HOLES=y
++# CONFIG_ARCH_SPARSEMEM_DEFAULT is not set
++# CONFIG_ARCH_SELECT_MEMORY_MODEL is not set
++CONFIG_SELECT_MEMORY_MODEL=y
++CONFIG_FLATMEM_MANUAL=y
++# CONFIG_DISCONTIGMEM_MANUAL is not set
++# CONFIG_SPARSEMEM_MANUAL is not set
++CONFIG_FLATMEM=y
++CONFIG_FLAT_NODE_MEM_MAP=y
++CONFIG_PAGEFLAGS_EXTENDED=y
++CONFIG_SPLIT_PTLOCK_CPUS=4096
++# CONFIG_RESOURCES_64BIT is not set
++# CONFIG_PHYS_ADDR_T_64BIT is not set
++CONFIG_ZONE_DMA_FLAG=0
++CONFIG_VIRT_TO_BUS=y
++CONFIG_UNEVICTABLE_LRU=y
++CONFIG_ALIGNMENT_TRAP=y
++
++#
++# Boot options
++#
++CONFIG_ZBOOT_ROM_TEXT=0
++CONFIG_ZBOOT_ROM_BSS=0
++CONFIG_CMDLINE=""
++# CONFIG_XIP_KERNEL is not set
++# CONFIG_KEXEC is not set
++
++#
++# CPU Power Management
++#
++# CONFIG_CPU_IDLE is not set
++
++#
++# Floating point emulation
++#
++
++#
++# At least one emulation must be selected
++#
++CONFIG_FPE_NWFPE=y
++CONFIG_FPE_NWFPE_XP=y
++# CONFIG_FPE_FASTFPE is not set
++CONFIG_VFP=y
++
++#
++# Userspace binary formats
++#
++CONFIG_BINFMT_ELF=y
++# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
++CONFIG_HAVE_AOUT=y
++CONFIG_BINFMT_AOUT=y
++# CONFIG_BINFMT_MISC is not set
++# CONFIG_ARTHUR is not set
++
++#
++# Power management options
++#
++CONFIG_PM=y
++# CONFIG_PM_DEBUG is not set
++CONFIG_PM_SLEEP=y
++CONFIG_SUSPEND=y
++CONFIG_SUSPEND_FREEZER=y
++# CONFIG_APM_EMULATION is not set
++CONFIG_ARCH_SUSPEND_POSSIBLE=y
++CONFIG_NET=y
++
++#
++# Networking options
++#
++CONFIG_PACKET=y
++# CONFIG_PACKET_MMAP is not set
++CONFIG_UNIX=y
++CONFIG_XFRM=y
++# CONFIG_XFRM_USER is not set
++# CONFIG_XFRM_SUB_POLICY is not set
++# CONFIG_XFRM_MIGRATE is not set
++# CONFIG_XFRM_STATISTICS is not set
++# CONFIG_NET_KEY is not set
++CONFIG_INET=y
++CONFIG_IP_MULTICAST=y
++# CONFIG_IP_ADVANCED_ROUTER is not set
++CONFIG_IP_FIB_HASH=y
++CONFIG_IP_PNP=y
++CONFIG_IP_PNP_DHCP=y
++CONFIG_IP_PNP_BOOTP=y
++# CONFIG_IP_PNP_RARP is not set
++# CONFIG_NET_IPIP is not set
++# CONFIG_NET_IPGRE is not set
++# CONFIG_IP_MROUTE is not set
++# CONFIG_ARPD is not set
++# CONFIG_SYN_COOKIES is not set
++# CONFIG_INET_AH is not set
++# CONFIG_INET_ESP is not set
++# CONFIG_INET_IPCOMP is not set
++# CONFIG_INET_XFRM_TUNNEL is not set
++# CONFIG_INET_TUNNEL is not set
++CONFIG_INET_XFRM_MODE_TRANSPORT=y
++CONFIG_INET_XFRM_MODE_TUNNEL=y
++CONFIG_INET_XFRM_MODE_BEET=y
++# CONFIG_INET_LRO is not set
++CONFIG_INET_DIAG=y
++CONFIG_INET_TCP_DIAG=y
++# CONFIG_TCP_CONG_ADVANCED is not set
++CONFIG_TCP_CONG_CUBIC=y
++CONFIG_DEFAULT_TCP_CONG="cubic"
++# CONFIG_TCP_MD5SIG is not set
++# CONFIG_IPV6 is not set
++# CONFIG_NETWORK_SECMARK is not set
++# CONFIG_NETFILTER is not set
++# CONFIG_IP_DCCP is not set
++# CONFIG_IP_SCTP is not set
++# CONFIG_TIPC is not set
++# CONFIG_ATM is not set
++# CONFIG_BRIDGE is not set
++# CONFIG_NET_DSA is not set
++# CONFIG_VLAN_8021Q is not set
++# CONFIG_DECNET is not set
++# CONFIG_LLC2 is not set
++# CONFIG_IPX is not set
++# CONFIG_ATALK is not set
++# CONFIG_X25 is not set
++# CONFIG_LAPB is not set
++# CONFIG_ECONET is not set
++CONFIG_WAN_ROUTER=y
++# CONFIG_NET_SCHED is not set
++
++#
++# Network testing
++#
++# CONFIG_NET_PKTGEN is not set
++# CONFIG_HAMRADIO is not set
++# CONFIG_CAN is not set
++# CONFIG_IRDA is not set
++# CONFIG_BT is not set
++# CONFIG_AF_RXRPC is not set
++# CONFIG_PHONET is not set
++# CONFIG_WIRELESS is not set
++# CONFIG_RFKILL is not set
++# CONFIG_NET_9P is not set
++
++#
++# Device Drivers
++#
++
++#
++# Generic Driver Options
++#
++CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
++CONFIG_STANDALONE=y
++CONFIG_PREVENT_FIRMWARE_BUILD=y
++CONFIG_FW_LOADER=y
++CONFIG_FIRMWARE_IN_KERNEL=y
++CONFIG_EXTRA_FIRMWARE=""
++# CONFIG_SYS_HYPERVISOR is not set
++CONFIG_CONNECTOR=y
++CONFIG_PROC_EVENTS=y
++# CONFIG_MTD is not set
++# CONFIG_PARPORT is not set
++CONFIG_BLK_DEV=y
++# CONFIG_BLK_DEV_COW_COMMON is not set
++CONFIG_BLK_DEV_LOOP=y
++# CONFIG_BLK_DEV_CRYPTOLOOP is not set
++CONFIG_BLK_DEV_NBD=m
++CONFIG_BLK_DEV_RAM=y
++CONFIG_BLK_DEV_RAM_COUNT=16
++CONFIG_BLK_DEV_RAM_SIZE=16384
++# CONFIG_BLK_DEV_XIP is not set
++# CONFIG_CDROM_PKTCDVD is not set
++# CONFIG_ATA_OVER_ETH is not set
++CONFIG_MISC_DEVICES=y
++# CONFIG_EEPROM_93CX6 is not set
++# CONFIG_ICS932S401 is not set
++# CONFIG_ENCLOSURE_SERVICES is not set
++# CONFIG_C2PORT is not set
++CONFIG_HAVE_IDE=y
++# CONFIG_IDE is not set
++
++#
++# SCSI device support
++#
++# CONFIG_RAID_ATTRS is not set
++CONFIG_SCSI=y
++CONFIG_SCSI_DMA=y
++CONFIG_SCSI_TGT=y
++# CONFIG_SCSI_NETLINK is not set
++CONFIG_SCSI_PROC_FS=y
++
++#
++# SCSI support type (disk, tape, CD-ROM)
++#
++CONFIG_BLK_DEV_SD=y
++# CONFIG_CHR_DEV_ST is not set
++# CONFIG_CHR_DEV_OSST is not set
++# CONFIG_BLK_DEV_SR is not set
++CONFIG_CHR_DEV_SG=y
++# CONFIG_CHR_DEV_SCH is not set
++
++#
++# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
++#
++# CONFIG_SCSI_MULTI_LUN is not set
++# CONFIG_SCSI_CONSTANTS is not set
++# CONFIG_SCSI_LOGGING is not set
++CONFIG_SCSI_SCAN_ASYNC=y
++CONFIG_SCSI_WAIT_SCAN=m
++
++#
++# SCSI Transports
++#
++# CONFIG_SCSI_SPI_ATTRS is not set
++# CONFIG_SCSI_FC_ATTRS is not set
++CONFIG_SCSI_ISCSI_ATTRS=m
++# CONFIG_SCSI_SAS_LIBSAS is not set
++# CONFIG_SCSI_SRP_ATTRS is not set
++# CONFIG_SCSI_LOWLEVEL is not set
++# CONFIG_SCSI_DH is not set
++# CONFIG_ATA is not set
++# CONFIG_MD is not set
++CONFIG_NETDEVICES=y
++# CONFIG_DUMMY is not set
++# CONFIG_BONDING is not set
++# CONFIG_MACVLAN is not set
++# CONFIG_EQUALIZER is not set
++# CONFIG_TUN is not set
++# CONFIG_VETH is not set
++# CONFIG_NET_ETHERNET is not set
++CONFIG_NETDEV_1000=y
++CONFIG_ASPEEDMAC=y
++# CONFIG_MAC0_PHY_LINK is not set
++# CONFIG_NETDEV_10000 is not set
++
++#
++# Wireless LAN
++#
++# CONFIG_WLAN_PRE80211 is not set
++# CONFIG_WLAN_80211 is not set
++# CONFIG_IWLWIFI_LEDS is not set
++# CONFIG_WAN is not set
++# CONFIG_PPP is not set
++# CONFIG_SLIP is not set
++# CONFIG_NETCONSOLE is not set
++# CONFIG_NETPOLL is not set
++# CONFIG_NET_POLL_CONTROLLER is not set
++# CONFIG_ISDN is not set
++
++#
++# Input device support
++#
++CONFIG_INPUT=y
++# CONFIG_INPUT_FF_MEMLESS is not set
++# CONFIG_INPUT_POLLDEV is not set
++
++#
++# Userland interfaces
++#
++CONFIG_INPUT_MOUSEDEV=y
++CONFIG_INPUT_MOUSEDEV_PSAUX=y
++CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
++CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
++# CONFIG_INPUT_JOYDEV is not set
++CONFIG_INPUT_EVDEV=y
++# CONFIG_INPUT_EVBUG is not set
++
++#
++# Input Device Drivers
++#
++CONFIG_INPUT_KEYBOARD=y
++CONFIG_KEYBOARD_ATKBD=y
++# CONFIG_KEYBOARD_SUNKBD is not set
++# CONFIG_KEYBOARD_LKKBD is not set
++# CONFIG_KEYBOARD_XTKBD is not set
++# CONFIG_KEYBOARD_NEWTON is not set
++# CONFIG_KEYBOARD_STOWAWAY is not set
++# CONFIG_KEYBOARD_GPIO is not set
++CONFIG_INPUT_MOUSE=y
++CONFIG_MOUSE_PS2=y
++CONFIG_MOUSE_PS2_ALPS=y
++CONFIG_MOUSE_PS2_LOGIPS2PP=y
++CONFIG_MOUSE_PS2_SYNAPTICS=y
++CONFIG_MOUSE_PS2_LIFEBOOK=y
++CONFIG_MOUSE_PS2_TRACKPOINT=y
++# CONFIG_MOUSE_PS2_ELANTECH is not set
++# CONFIG_MOUSE_PS2_TOUCHKIT is not set
++CONFIG_MOUSE_SERIAL=y
++# CONFIG_MOUSE_VSXXXAA is not set
++# CONFIG_MOUSE_GPIO is not set
++# CONFIG_INPUT_JOYSTICK is not set
++# CONFIG_INPUT_TABLET is not set
++# CONFIG_INPUT_TOUCHSCREEN is not set
++# CONFIG_INPUT_MISC is not set
++
++#
++# Hardware I/O ports
++#
++CONFIG_SERIO=y
++CONFIG_SERIO_SERPORT=y
++# CONFIG_SERIO_AMBAKMI is not set
++CONFIG_SERIO_LIBPS2=y
++# CONFIG_SERIO_RAW is not set
++# CONFIG_GAMEPORT is not set
++
++#
++# Character devices
++#
++CONFIG_VT=y
++CONFIG_CONSOLE_TRANSLATIONS=y
++CONFIG_VT_CONSOLE=y
++CONFIG_HW_CONSOLE=y
++# CONFIG_VT_HW_CONSOLE_BINDING is not set
++CONFIG_DEVKMEM=y
++CONFIG_SERIAL_NONSTANDARD=y
++# CONFIG_N_HDLC is not set
++# CONFIG_RISCOM8 is not set
++# CONFIG_SPECIALIX is not set
++# CONFIG_RIO is not set
++# CONFIG_STALDRV is not set
++
++#
++# Serial drivers
++#
++CONFIG_SERIAL_8250=y
++CONFIG_SERIAL_8250_CONSOLE=y
++CONFIG_SERIAL_8250_NR_UARTS=3
++CONFIG_SERIAL_8250_RUNTIME_UARTS=3
++CONFIG_SERIAL_AST_DMA_UART=y
++CONFIG_AST_NR_DMA_UARTS=8
++CONFIG_AST_RUNTIME_DMA_UARTS=8
++# CONFIG_SERIAL_8250_EXTENDED is not set
++
++#
++# Non-8250 serial port support
++#
++# CONFIG_SERIAL_AMBA_PL010 is not set
++# CONFIG_SERIAL_AMBA_PL011 is not set
++# CONFIG_SERIAL_AST is not set
++CONFIG_SERIAL_CORE=y
++CONFIG_SERIAL_CORE_CONSOLE=y
++CONFIG_UNIX98_PTYS=y
++CONFIG_LEGACY_PTYS=y
++CONFIG_LEGACY_PTY_COUNT=256
++# CONFIG_IPMI_HANDLER is not set
++# CONFIG_AST_MISC is not set
++# CONFIG_HW_RANDOM is not set
++CONFIG_NVRAM=y
++# CONFIG_R3964 is not set
++# CONFIG_RAW_DRIVER is not set
++# CONFIG_TCG_TPM is not set
++CONFIG_I2C=y
++CONFIG_I2C_BOARDINFO=y
++CONFIG_I2C_CHARDEV=y
++CONFIG_I2C_HELPER_AUTO=y
++
++#
++# I2C Hardware Bus support
++#
++
++#
++# I2C system bus drivers (mostly embedded / system-on-chip)
++#
++# CONFIG_I2C_GPIO is not set
++# CONFIG_I2C_OCORES is not set
++CONFIG_I2C_AST=y
++CONFIG_I2C_AST1070=y
++CONFIG_AST_I2C_SLAVE_MODE=y
++# CONFIG_I2C_SIMTEC is not set
++
++#
++# External I2C/SMBus adapter drivers
++#
++# CONFIG_I2C_PARPORT_LIGHT is not set
++# CONFIG_I2C_TAOS_EVM is not set
++
++#
++# Other I2C/SMBus bus drivers
++#
++# CONFIG_I2C_PCA_PLATFORM is not set
++# CONFIG_I2C_STUB is not set
++
++#
++# Miscellaneous I2C Chip support
++#
++# CONFIG_DS1682 is not set
++# CONFIG_AT24 is not set
++# CONFIG_SENSORS_EEPROM is not set
++# CONFIG_SENSORS_PCF8574 is not set
++# CONFIG_PCF8575 is not set
++# CONFIG_SENSORS_PCA9539 is not set
++# CONFIG_SENSORS_PCF8591 is not set
++# CONFIG_TPS65010 is not set
++# CONFIG_SENSORS_MAX6875 is not set
++# CONFIG_SENSORS_TSL2550 is not set
++# CONFIG_I2C_DEBUG_CORE is not set
++# CONFIG_I2C_DEBUG_ALGO is not set
++# CONFIG_I2C_DEBUG_BUS is not set
++# CONFIG_I2C_DEBUG_CHIP is not set
++# CONFIG_SPI is not set
++CONFIG_ARCH_REQUIRE_GPIOLIB=y
++CONFIG_GPIOLIB=y
++CONFIG_GPIO_SYSFS=y
++
++#
++# Memory mapped GPIO expanders:
++#
++
++#
++# I2C GPIO expanders:
++#
++# CONFIG_GPIO_MAX732X is not set
++# CONFIG_GPIO_PCA953X is not set
++# CONFIG_GPIO_PCF857X is not set
++
++#
++# PCI GPIO expanders:
++#
++
++#
++# SPI GPIO expanders:
++#
++# CONFIG_W1 is not set
++# CONFIG_POWER_SUPPLY is not set
++# CONFIG_HWMON is not set
++# CONFIG_THERMAL is not set
++# CONFIG_THERMAL_HWMON is not set
++# CONFIG_WATCHDOG is not set
++CONFIG_SSB_POSSIBLE=y
++
++#
++# Sonics Silicon Backplane
++#
++# CONFIG_SSB is not set
++
++#
++# Multifunction device drivers
++#
++# CONFIG_MFD_CORE is not set
++# CONFIG_MFD_SM501 is not set
++# CONFIG_MFD_ASIC3 is not set
++# CONFIG_HTC_EGPIO is not set
++# CONFIG_HTC_PASIC3 is not set
++# CONFIG_MFD_TMIO is not set
++# CONFIG_MFD_TC6393XB is not set
++# CONFIG_PMIC_DA903X is not set
++# CONFIG_MFD_WM8400 is not set
++# CONFIG_MFD_WM8350_I2C is not set
++
++#
++# Multimedia devices
++#
++
++#
++# Multimedia core support
++#
++# CONFIG_VIDEO_DEV is not set
++# CONFIG_DVB_CORE is not set
++# CONFIG_VIDEO_MEDIA is not set
++
++#
++# Multimedia drivers
++#
++# CONFIG_DAB is not set
++
++#
++# Graphics support
++#
++# CONFIG_VGASTATE is not set
++# CONFIG_VIDEO_OUTPUT_CONTROL is not set
++# CONFIG_FB is not set
++# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
++
++#
++# Display device support
++#
++# CONFIG_DISPLAY_SUPPORT is not set
++
++#
++# Console display driver support
++#
++# CONFIG_VGA_CONSOLE is not set
++CONFIG_DUMMY_CONSOLE=y
++# CONFIG_SOUND is not set
++# CONFIG_HID_SUPPORT is not set
++# CONFIG_USB_SUPPORT is not set
++CONFIG_USB_ARCH_HAS_EHCI=y
++# CONFIG_MMC is not set
++# CONFIG_MEMSTICK is not set
++# CONFIG_ACCESSIBILITY is not set
++# CONFIG_NEW_LEDS is not set
++CONFIG_RTC_LIB=y
++# CONFIG_RTC_CLASS is not set
++# CONFIG_DMADEVICES is not set
++# CONFIG_REGULATOR is not set
++# CONFIG_UIO is not set
++
++#
++# File systems
++#
++CONFIG_EXT2_FS=y
++CONFIG_EXT2_FS_XATTR=y
++CONFIG_EXT2_FS_POSIX_ACL=y
++CONFIG_EXT2_FS_SECURITY=y
++# CONFIG_EXT2_FS_XIP is not set
++# CONFIG_EXT3_FS is not set
++# CONFIG_EXT4_FS is not set
++CONFIG_FS_MBCACHE=y
++# CONFIG_REISERFS_FS is not set
++# CONFIG_JFS_FS is not set
++CONFIG_FS_POSIX_ACL=y
++CONFIG_FILE_LOCKING=y
++# CONFIG_XFS_FS is not set
++# CONFIG_OCFS2_FS is not set
++CONFIG_DNOTIFY=y
++CONFIG_INOTIFY=y
++CONFIG_INOTIFY_USER=y
++# CONFIG_QUOTA is not set
++# CONFIG_AUTOFS_FS is not set
++# CONFIG_AUTOFS4_FS is not set
++# CONFIG_FUSE_FS is not set
++CONFIG_GENERIC_ACL=y
++
++#
++# CD-ROM/DVD Filesystems
++#
++# CONFIG_ISO9660_FS is not set
++# CONFIG_UDF_FS is not set
++
++#
++# DOS/FAT/NT Filesystems
++#
++CONFIG_FAT_FS=y
++CONFIG_MSDOS_FS=y
++CONFIG_VFAT_FS=y
++CONFIG_FAT_DEFAULT_CODEPAGE=437
++CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
++CONFIG_NTFS_FS=y
++# CONFIG_NTFS_DEBUG is not set
++CONFIG_NTFS_RW=y
++
++#
++# Pseudo filesystems
++#
++CONFIG_PROC_FS=y
++CONFIG_PROC_SYSCTL=y
++CONFIG_PROC_PAGE_MONITOR=y
++CONFIG_SYSFS=y
++CONFIG_TMPFS=y
++CONFIG_TMPFS_POSIX_ACL=y
++# CONFIG_HUGETLB_PAGE is not set
++CONFIG_CONFIGFS_FS=m
++
++#
++# Miscellaneous filesystems
++#
++# CONFIG_ADFS_FS is not set
++# CONFIG_AFFS_FS is not set
++# CONFIG_HFS_FS is not set
++# CONFIG_HFSPLUS_FS is not set
++# CONFIG_BEFS_FS is not set
++# CONFIG_BFS_FS is not set
++# CONFIG_EFS_FS is not set
++# CONFIG_CRAMFS is not set
++# CONFIG_VXFS_FS is not set
++# CONFIG_MINIX_FS is not set
++# CONFIG_OMFS_FS is not set
++# CONFIG_HPFS_FS is not set
++# CONFIG_QNX4FS_FS is not set
++# CONFIG_ROMFS_FS is not set
++# CONFIG_SYSV_FS is not set
++# CONFIG_UFS_FS is not set
++CONFIG_NETWORK_FILESYSTEMS=y
++CONFIG_NFS_FS=y
++# CONFIG_NFS_V3 is not set
++# CONFIG_NFS_V4 is not set
++CONFIG_ROOT_NFS=y
++# CONFIG_NFSD is not set
++CONFIG_LOCKD=y
++CONFIG_NFS_COMMON=y
++CONFIG_SUNRPC=y
++# CONFIG_SUNRPC_REGISTER_V4 is not set
++# CONFIG_RPCSEC_GSS_KRB5 is not set
++# CONFIG_RPCSEC_GSS_SPKM3 is not set
++# CONFIG_SMB_FS is not set
++# CONFIG_CIFS is not set
++# CONFIG_NCP_FS is not set
++# CONFIG_CODA_FS is not set
++# CONFIG_AFS_FS is not set
++
++#
++# Partition Types
++#
++# CONFIG_PARTITION_ADVANCED is not set
++CONFIG_MSDOS_PARTITION=y
++CONFIG_NLS=y
++CONFIG_NLS_DEFAULT="utf8"
++CONFIG_NLS_CODEPAGE_437=y
++# CONFIG_NLS_CODEPAGE_737 is not set
++# CONFIG_NLS_CODEPAGE_775 is not set
++# CONFIG_NLS_CODEPAGE_850 is not set
++# CONFIG_NLS_CODEPAGE_852 is not set
++# CONFIG_NLS_CODEPAGE_855 is not set
++# CONFIG_NLS_CODEPAGE_857 is not set
++# CONFIG_NLS_CODEPAGE_860 is not set
++# CONFIG_NLS_CODEPAGE_861 is not set
++# CONFIG_NLS_CODEPAGE_862 is not set
++# CONFIG_NLS_CODEPAGE_863 is not set
++# CONFIG_NLS_CODEPAGE_864 is not set
++# CONFIG_NLS_CODEPAGE_865 is not set
++# CONFIG_NLS_CODEPAGE_866 is not set
++# CONFIG_NLS_CODEPAGE_869 is not set
++CONFIG_NLS_CODEPAGE_936=y
++CONFIG_NLS_CODEPAGE_950=y
++CONFIG_NLS_CODEPAGE_932=y
++# CONFIG_NLS_CODEPAGE_949 is not set
++# CONFIG_NLS_CODEPAGE_874 is not set
++# CONFIG_NLS_ISO8859_8 is not set
++# CONFIG_NLS_CODEPAGE_1250 is not set
++# CONFIG_NLS_CODEPAGE_1251 is not set
++CONFIG_NLS_ASCII=y
++CONFIG_NLS_ISO8859_1=y
++# CONFIG_NLS_ISO8859_2 is not set
++# CONFIG_NLS_ISO8859_3 is not set
++# CONFIG_NLS_ISO8859_4 is not set
++# CONFIG_NLS_ISO8859_5 is not set
++# CONFIG_NLS_ISO8859_6 is not set
++# CONFIG_NLS_ISO8859_7 is not set
++# CONFIG_NLS_ISO8859_9 is not set
++# CONFIG_NLS_ISO8859_13 is not set
++# CONFIG_NLS_ISO8859_14 is not set
++# CONFIG_NLS_ISO8859_15 is not set
++# CONFIG_NLS_KOI8_R is not set
++# CONFIG_NLS_KOI8_U is not set
++CONFIG_NLS_UTF8=y
++# CONFIG_DLM is not set
++
++#
++# Kernel hacking
++#
++# CONFIG_PRINTK_TIME is not set
++# CONFIG_ENABLE_WARN_DEPRECATED is not set
++CONFIG_ENABLE_MUST_CHECK=y
++CONFIG_FRAME_WARN=1024
++CONFIG_MAGIC_SYSRQ=y
++# CONFIG_UNUSED_SYMBOLS is not set
++# CONFIG_DEBUG_FS is not set
++# CONFIG_HEADERS_CHECK is not set
++# CONFIG_DEBUG_KERNEL is not set
++# CONFIG_SLUB_DEBUG_ON is not set
++# CONFIG_SLUB_STATS is not set
++CONFIG_DEBUG_BUGVERBOSE=y
++CONFIG_DEBUG_MEMORY_INIT=y
++CONFIG_FRAME_POINTER=y
++# CONFIG_RCU_CPU_STALL_DETECTOR is not set
++# CONFIG_LATENCYTOP is not set
++# CONFIG_SYSCTL_SYSCALL_CHECK is not set
++CONFIG_HAVE_FUNCTION_TRACER=y
++
++#
++# Tracers
++#
++# CONFIG_DYNAMIC_PRINTK_DEBUG is not set
++# CONFIG_SAMPLES is not set
++CONFIG_HAVE_ARCH_KGDB=y
++# CONFIG_DEBUG_USER is not set
++
++#
++# Security options
++#
++# CONFIG_KEYS is not set
++# CONFIG_SECURITY is not set
++# CONFIG_SECURITYFS is not set
++# CONFIG_SECURITY_FILE_CAPABILITIES is not set
++CONFIG_CRYPTO=y
++
++#
++# Crypto core or helper
++#
++# CONFIG_CRYPTO_FIPS is not set
++CONFIG_CRYPTO_ALGAPI=y
++CONFIG_CRYPTO_ALGAPI2=y
++CONFIG_CRYPTO_AEAD=m
++CONFIG_CRYPTO_AEAD2=y
++CONFIG_CRYPTO_BLKCIPHER=y
++CONFIG_CRYPTO_BLKCIPHER2=y
++CONFIG_CRYPTO_HASH=y
++CONFIG_CRYPTO_HASH2=y
++CONFIG_CRYPTO_RNG2=y
++CONFIG_CRYPTO_MANAGER=y
++CONFIG_CRYPTO_MANAGER2=y
++# CONFIG_CRYPTO_GF128MUL is not set
++CONFIG_CRYPTO_NULL=y
++# CONFIG_CRYPTO_CRYPTD is not set
++CONFIG_CRYPTO_AUTHENC=m
++# CONFIG_CRYPTO_TEST is not set
++
++#
++# Authenticated Encryption with Associated Data
++#
++# CONFIG_CRYPTO_CCM is not set
++# CONFIG_CRYPTO_GCM is not set
++# CONFIG_CRYPTO_SEQIV is not set
++
++#
++# Block modes
++#
++CONFIG_CRYPTO_CBC=y
++# CONFIG_CRYPTO_CTR is not set
++# CONFIG_CRYPTO_CTS is not set
++# CONFIG_CRYPTO_ECB is not set
++# CONFIG_CRYPTO_LRW is not set
++# CONFIG_CRYPTO_PCBC is not set
++# CONFIG_CRYPTO_XTS is not set
++
++#
++# Hash modes
++#
++CONFIG_CRYPTO_HMAC=y
++# CONFIG_CRYPTO_XCBC is not set
++
++#
++# Digest
++#
++# CONFIG_CRYPTO_CRC32C is not set
++# CONFIG_CRYPTO_MD4 is not set
++CONFIG_CRYPTO_MD5=y
++# CONFIG_CRYPTO_MICHAEL_MIC is not set
++# CONFIG_CRYPTO_RMD128 is not set
++# CONFIG_CRYPTO_RMD160 is not set
++# CONFIG_CRYPTO_RMD256 is not set
++# CONFIG_CRYPTO_RMD320 is not set
++CONFIG_CRYPTO_SHA1=y
++# CONFIG_CRYPTO_SHA256 is not set
++# CONFIG_CRYPTO_SHA512 is not set
++# CONFIG_CRYPTO_TGR192 is not set
++# CONFIG_CRYPTO_WP512 is not set
++
++#
++# Ciphers
++#
++# CONFIG_CRYPTO_AES is not set
++# CONFIG_CRYPTO_ANUBIS is not set
++# CONFIG_CRYPTO_ARC4 is not set
++# CONFIG_CRYPTO_BLOWFISH is not set
++# CONFIG_CRYPTO_CAMELLIA is not set
++# CONFIG_CRYPTO_CAST5 is not set
++# CONFIG_CRYPTO_CAST6 is not set
++CONFIG_CRYPTO_DES=y
++# CONFIG_CRYPTO_FCRYPT is not set
++# CONFIG_CRYPTO_KHAZAD is not set
++# CONFIG_CRYPTO_SALSA20 is not set
++# CONFIG_CRYPTO_SEED is not set
++# CONFIG_CRYPTO_SERPENT is not set
++# CONFIG_CRYPTO_TEA is not set
++# CONFIG_CRYPTO_TWOFISH is not set
++
++#
++# Compression
++#
++CONFIG_CRYPTO_DEFLATE=m
++# CONFIG_CRYPTO_LZO is not set
++
++#
++# Random Number Generation
++#
++# CONFIG_CRYPTO_ANSI_CPRNG is not set
++# CONFIG_CRYPTO_HW is not set
++
++#
++# Library routines
++#
++CONFIG_BITREVERSE=y
++# CONFIG_CRC_CCITT is not set
++# CONFIG_CRC16 is not set
++# CONFIG_CRC_T10DIF is not set
++CONFIG_CRC_ITU_T=m
++CONFIG_CRC32=y
++# CONFIG_CRC7 is not set
++# CONFIG_LIBCRC32C is not set
++CONFIG_ZLIB_INFLATE=m
++CONFIG_ZLIB_DEFLATE=m
++CONFIG_PLIST=y
++CONFIG_HAS_IOMEM=y
++CONFIG_HAS_IOPORT=y
++CONFIG_HAS_DMA=y
+diff --git a/arch/arm/configs/ast2400_defconfig b/arch/arm/configs/ast2400_defconfig
+new file mode 100644
+index 0000000..22b76fe
+--- /dev/null
++++ b/arch/arm/configs/ast2400_defconfig
+@@ -0,0 +1,1412 @@
++#
++# Automatically generated make config: don't edit
++# Linux kernel version: 2.6.28.9
++# Tue Jan 20 09:41:35 2015
++#
++CONFIG_ARM=y
++CONFIG_SYS_SUPPORTS_APM_EMULATION=y
++CONFIG_GENERIC_GPIO=y
++# CONFIG_GENERIC_TIME is not set
++# CONFIG_GENERIC_CLOCKEVENTS is not set
++CONFIG_MMU=y
++# CONFIG_NO_IOPORT is not set
++CONFIG_GENERIC_HARDIRQS=y
++CONFIG_STACKTRACE_SUPPORT=y
++CONFIG_HAVE_LATENCYTOP_SUPPORT=y
++CONFIG_LOCKDEP_SUPPORT=y
++CONFIG_TRACE_IRQFLAGS_SUPPORT=y
++CONFIG_HARDIRQS_SW_RESEND=y
++CONFIG_GENERIC_IRQ_PROBE=y
++CONFIG_RWSEM_GENERIC_SPINLOCK=y
++# CONFIG_ARCH_HAS_ILOG2_U32 is not set
++# CONFIG_ARCH_HAS_ILOG2_U64 is not set
++CONFIG_GENERIC_HWEIGHT=y
++CONFIG_GENERIC_CALIBRATE_DELAY=y
++CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
++CONFIG_VECTORS_BASE=0xffff0000
++CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
++
++#
++# General setup
++#
++CONFIG_EXPERIMENTAL=y
++CONFIG_BROKEN_ON_SMP=y
++CONFIG_INIT_ENV_ARG_LIMIT=32
++CONFIG_LOCALVERSION=""
++# CONFIG_LOCALVERSION_AUTO is not set
++CONFIG_SWAP=y
++CONFIG_SYSVIPC=y
++CONFIG_SYSVIPC_SYSCTL=y
++# CONFIG_POSIX_MQUEUE is not set
++# CONFIG_BSD_PROCESS_ACCT is not set
++# CONFIG_TASKSTATS is not set
++# CONFIG_AUDIT is not set
++# CONFIG_IKCONFIG is not set
++CONFIG_LOG_BUF_SHIFT=16
++# CONFIG_CGROUPS is not set
++# CONFIG_GROUP_SCHED is not set
++CONFIG_SYSFS_DEPRECATED=y
++CONFIG_SYSFS_DEPRECATED_V2=y
++# CONFIG_RELAY is not set
++CONFIG_NAMESPACES=y
++# CONFIG_UTS_NS is not set
++# CONFIG_IPC_NS is not set
++# CONFIG_USER_NS is not set
++# CONFIG_PID_NS is not set
++CONFIG_BLK_DEV_INITRD=y
++CONFIG_INITRAMFS_SOURCE=""
++CONFIG_CC_OPTIMIZE_FOR_SIZE=y
++CONFIG_SYSCTL=y
++CONFIG_ANON_INODES=y
++# CONFIG_EMBEDDED is not set
++CONFIG_UID16=y
++CONFIG_SYSCTL_SYSCALL=y
++CONFIG_KALLSYMS=y
++CONFIG_KALLSYMS_EXTRA_PASS=y
++CONFIG_HOTPLUG=y
++CONFIG_PRINTK=y
++CONFIG_BUG=y
++CONFIG_ELF_CORE=y
++CONFIG_BASE_FULL=y
++CONFIG_FUTEX=y
++CONFIG_EPOLL=y
++CONFIG_SIGNALFD=y
++CONFIG_TIMERFD=y
++CONFIG_EVENTFD=y
++CONFIG_SHMEM=y
++CONFIG_AIO=y
++CONFIG_VM_EVENT_COUNTERS=y
++CONFIG_SLUB_DEBUG=y
++CONFIG_COMPAT_BRK=y
++# CONFIG_SLAB is not set
++CONFIG_SLUB=y
++# CONFIG_SLOB is not set
++# CONFIG_PROFILING is not set
++# CONFIG_MARKERS is not set
++CONFIG_HAVE_OPROFILE=y
++# CONFIG_KPROBES is not set
++CONFIG_HAVE_KPROBES=y
++CONFIG_HAVE_KRETPROBES=y
++CONFIG_HAVE_GENERIC_DMA_COHERENT=y
++CONFIG_SLABINFO=y
++CONFIG_RT_MUTEXES=y
++# CONFIG_TINY_SHMEM is not set
++CONFIG_BASE_SMALL=0
++CONFIG_MODULES=y
++# CONFIG_MODULE_FORCE_LOAD is not set
++CONFIG_MODULE_UNLOAD=y
++# CONFIG_MODULE_FORCE_UNLOAD is not set
++# CONFIG_MODVERSIONS is not set
++# CONFIG_MODULE_SRCVERSION_ALL is not set
++CONFIG_KMOD=y
++CONFIG_BLOCK=y
++# CONFIG_LBD is not set
++# CONFIG_BLK_DEV_IO_TRACE is not set
++# CONFIG_LSF is not set
++# CONFIG_BLK_DEV_BSG is not set
++# CONFIG_BLK_DEV_INTEGRITY is not set
++
++#
++# IO Schedulers
++#
++CONFIG_IOSCHED_NOOP=y
++CONFIG_IOSCHED_AS=y
++CONFIG_IOSCHED_DEADLINE=y
++CONFIG_IOSCHED_CFQ=y
++# CONFIG_DEFAULT_AS is not set
++# CONFIG_DEFAULT_DEADLINE is not set
++CONFIG_DEFAULT_CFQ=y
++# CONFIG_DEFAULT_NOOP is not set
++CONFIG_DEFAULT_IOSCHED="cfq"
++CONFIG_CLASSIC_RCU=y
++CONFIG_FREEZER=y
++
++#
++# System Type
++#
++CONFIG_ARCH_ASPEED=y
++# CONFIG_ARCH_AAEC2000 is not set
++# CONFIG_ARCH_INTEGRATOR is not set
++# CONFIG_ARCH_REALVIEW is not set
++# CONFIG_ARCH_VERSATILE is not set
++# CONFIG_ARCH_AT91 is not set
++# CONFIG_ARCH_CLPS7500 is not set
++# CONFIG_ARCH_CLPS711X is not set
++# CONFIG_ARCH_EBSA110 is not set
++# CONFIG_ARCH_EP93XX is not set
++# CONFIG_ARCH_FOOTBRIDGE is not set
++# CONFIG_ARCH_NETX is not set
++# CONFIG_ARCH_H720X is not set
++# CONFIG_ARCH_IMX is not set
++# CONFIG_ARCH_IOP13XX is not set
++# CONFIG_ARCH_IOP32X is not set
++# CONFIG_ARCH_IOP33X is not set
++# CONFIG_ARCH_IXP23XX is not set
++# CONFIG_ARCH_IXP2000 is not set
++# CONFIG_ARCH_IXP4XX is not set
++# CONFIG_ARCH_L7200 is not set
++# CONFIG_ARCH_KIRKWOOD is not set
++# CONFIG_ARCH_KS8695 is not set
++# CONFIG_ARCH_NS9XXX is not set
++# CONFIG_ARCH_LOKI is not set
++# CONFIG_ARCH_MV78XX0 is not set
++# CONFIG_ARCH_MXC is not set
++# CONFIG_ARCH_ORION5X is not set
++# CONFIG_ARCH_PNX4008 is not set
++# CONFIG_ARCH_PXA is not set
++# CONFIG_ARCH_RPC is not set
++# CONFIG_ARCH_SA1100 is not set
++# CONFIG_ARCH_S3C2410 is not set
++# CONFIG_ARCH_SHARK is not set
++# CONFIG_ARCH_LH7A40X is not set
++# CONFIG_ARCH_DAVINCI is not set
++# CONFIG_ARCH_OMAP is not set
++# CONFIG_ARCH_MSM is not set
++CONFIG_IRMP=y
++# CONFIG_PCEXT is not set
++# CONFIG_REMOTEFX is not set
++# CONFIG_ARCH_AST1100 is not set
++# CONFIG_ARCH_AST2100 is not set
++# CONFIG_ARCH_AST2200 is not set
++# CONFIG_ARCH_AST2300 is not set
++CONFIG_ARCH_AST2400=y
++# CONFIG_ARCH_AST2500 is not set
++
++#
++# FLASH Chip Select
++#
++# CONFIG_AST_CS0_NOR is not set
++# CONFIG_AST_CS0_NAND is not set
++# CONFIG_AST_CS0_SPI is not set
++CONFIG_AST_CS0_NONE=y
++# CONFIG_AST_CS1_NOR is not set
++# CONFIG_AST_CS1_NAND is not set
++# CONFIG_AST_CS1_SPI is not set
++CONFIG_AST_CS1_NONE=y
++# CONFIG_AST_CS2_NOR is not set
++# CONFIG_AST_CS2_NAND is not set
++# CONFIG_AST_CS2_SPI is not set
++CONFIG_AST_CS2_NONE=y
++# CONFIG_AST_CS3_NOR is not set
++# CONFIG_AST_CS3_NAND is not set
++# CONFIG_AST_CS3_SPI is not set
++CONFIG_AST_CS3_NONE=y
++# CONFIG_AST_CS4_NOR is not set
++# CONFIG_AST_CS4_NAND is not set
++# CONFIG_AST_CS4_SPI is not set
++CONFIG_AST_CS4_NONE=y
++# CONFIG_ARCH_AST1070 is not set
++# CONFIG_AST_SCU_LOCK is not set
++
++#
++# Boot options
++#
++
++#
++# Power management
++#
++CONFIG_PLAT_ASPEED=y
++
++#
++# Processor Type
++#
++CONFIG_CPU_32=y
++CONFIG_CPU_ARM926T=y
++CONFIG_CPU_32v5=y
++CONFIG_CPU_ABRT_EV5TJ=y
++CONFIG_CPU_PABRT_NOIFAR=y
++CONFIG_CPU_CACHE_VIVT=y
++CONFIG_CPU_COPY_V4WB=y
++CONFIG_CPU_TLB_V4WBI=y
++CONFIG_CPU_CP15=y
++CONFIG_CPU_CP15_MMU=y
++
++#
++# Processor Features
++#
++CONFIG_ARM_THUMB=y
++# CONFIG_CPU_ICACHE_DISABLE is not set
++# CONFIG_CPU_DCACHE_DISABLE is not set
++# CONFIG_CPU_DCACHE_WRITETHROUGH is not set
++# CONFIG_CPU_CACHE_ROUND_ROBIN is not set
++# CONFIG_OUTER_CACHE is not set
++
++#
++# Bus support
++#
++CONFIG_ARM_AMBA=y
++# CONFIG_PCI_SYSCALL is not set
++# CONFIG_ARCH_SUPPORTS_MSI is not set
++# CONFIG_PCCARD is not set
++
++#
++# Kernel Features
++#
++CONFIG_VMSPLIT_3G=y
++# CONFIG_VMSPLIT_2G is not set
++# CONFIG_VMSPLIT_1G is not set
++CONFIG_PAGE_OFFSET=0xC0000000
++# CONFIG_PREEMPT is not set
++CONFIG_HZ=100
++# CONFIG_AEABI is not set
++CONFIG_ARCH_FLATMEM_HAS_HOLES=y
++# CONFIG_ARCH_SPARSEMEM_DEFAULT is not set
++# CONFIG_ARCH_SELECT_MEMORY_MODEL is not set
++CONFIG_SELECT_MEMORY_MODEL=y
++CONFIG_FLATMEM_MANUAL=y
++# CONFIG_DISCONTIGMEM_MANUAL is not set
++# CONFIG_SPARSEMEM_MANUAL is not set
++CONFIG_FLATMEM=y
++CONFIG_FLAT_NODE_MEM_MAP=y
++CONFIG_PAGEFLAGS_EXTENDED=y
++CONFIG_SPLIT_PTLOCK_CPUS=4096
++# CONFIG_RESOURCES_64BIT is not set
++# CONFIG_PHYS_ADDR_T_64BIT is not set
++CONFIG_ZONE_DMA_FLAG=0
++CONFIG_VIRT_TO_BUS=y
++CONFIG_UNEVICTABLE_LRU=y
++CONFIG_ALIGNMENT_TRAP=y
++
++#
++# Boot options
++#
++CONFIG_ZBOOT_ROM_TEXT=0
++CONFIG_ZBOOT_ROM_BSS=0
++CONFIG_CMDLINE=""
++# CONFIG_XIP_KERNEL is not set
++# CONFIG_KEXEC is not set
++
++#
++# CPU Power Management
++#
++# CONFIG_CPU_IDLE is not set
++
++#
++# Floating point emulation
++#
++
++#
++# At least one emulation must be selected
++#
++CONFIG_FPE_NWFPE=y
++CONFIG_FPE_NWFPE_XP=y
++# CONFIG_FPE_FASTFPE is not set
++CONFIG_VFP=y
++
++#
++# Userspace binary formats
++#
++CONFIG_BINFMT_ELF=y
++# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
++CONFIG_HAVE_AOUT=y
++CONFIG_BINFMT_AOUT=y
++# CONFIG_BINFMT_MISC is not set
++# CONFIG_ARTHUR is not set
++
++#
++# Power management options
++#
++CONFIG_PM=y
++# CONFIG_PM_DEBUG is not set
++CONFIG_PM_SLEEP=y
++CONFIG_SUSPEND=y
++CONFIG_SUSPEND_FREEZER=y
++# CONFIG_APM_EMULATION is not set
++CONFIG_ARCH_SUSPEND_POSSIBLE=y
++CONFIG_NET=y
++
++#
++# Networking options
++#
++CONFIG_PACKET=y
++# CONFIG_PACKET_MMAP is not set
++CONFIG_UNIX=y
++CONFIG_XFRM=y
++# CONFIG_XFRM_USER is not set
++# CONFIG_XFRM_SUB_POLICY is not set
++# CONFIG_XFRM_MIGRATE is not set
++# CONFIG_XFRM_STATISTICS is not set
++# CONFIG_NET_KEY is not set
++CONFIG_INET=y
++CONFIG_IP_MULTICAST=y
++# CONFIG_IP_ADVANCED_ROUTER is not set
++CONFIG_IP_FIB_HASH=y
++CONFIG_IP_PNP=y
++CONFIG_IP_PNP_DHCP=y
++CONFIG_IP_PNP_BOOTP=y
++# CONFIG_IP_PNP_RARP is not set
++# CONFIG_NET_IPIP is not set
++# CONFIG_NET_IPGRE is not set
++# CONFIG_IP_MROUTE is not set
++# CONFIG_ARPD is not set
++# CONFIG_SYN_COOKIES is not set
++# CONFIG_INET_AH is not set
++# CONFIG_INET_ESP is not set
++# CONFIG_INET_IPCOMP is not set
++# CONFIG_INET_XFRM_TUNNEL is not set
++# CONFIG_INET_TUNNEL is not set
++CONFIG_INET_XFRM_MODE_TRANSPORT=y
++CONFIG_INET_XFRM_MODE_TUNNEL=y
++CONFIG_INET_XFRM_MODE_BEET=y
++# CONFIG_INET_LRO is not set
++CONFIG_INET_DIAG=y
++CONFIG_INET_TCP_DIAG=y
++# CONFIG_TCP_CONG_ADVANCED is not set
++CONFIG_TCP_CONG_CUBIC=y
++CONFIG_DEFAULT_TCP_CONG="cubic"
++# CONFIG_TCP_MD5SIG is not set
++# CONFIG_IPV6 is not set
++# CONFIG_NETWORK_SECMARK is not set
++# CONFIG_NETFILTER is not set
++# CONFIG_IP_DCCP is not set
++# CONFIG_IP_SCTP is not set
++# CONFIG_TIPC is not set
++# CONFIG_ATM is not set
++# CONFIG_BRIDGE is not set
++# CONFIG_NET_DSA is not set
++# CONFIG_VLAN_8021Q is not set
++# CONFIG_DECNET is not set
++# CONFIG_LLC2 is not set
++# CONFIG_IPX is not set
++# CONFIG_ATALK is not set
++# CONFIG_X25 is not set
++# CONFIG_LAPB is not set
++# CONFIG_ECONET is not set
++CONFIG_WAN_ROUTER=y
++# CONFIG_NET_SCHED is not set
++
++#
++# Network testing
++#
++# CONFIG_NET_PKTGEN is not set
++# CONFIG_HAMRADIO is not set
++# CONFIG_CAN is not set
++# CONFIG_IRDA is not set
++# CONFIG_BT is not set
++# CONFIG_AF_RXRPC is not set
++# CONFIG_PHONET is not set
++# CONFIG_WIRELESS is not set
++# CONFIG_RFKILL is not set
++# CONFIG_NET_9P is not set
++
++#
++# Device Drivers
++#
++
++#
++# Generic Driver Options
++#
++CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
++CONFIG_STANDALONE=y
++CONFIG_PREVENT_FIRMWARE_BUILD=y
++CONFIG_FW_LOADER=y
++CONFIG_FIRMWARE_IN_KERNEL=y
++CONFIG_EXTRA_FIRMWARE=""
++# CONFIG_SYS_HYPERVISOR is not set
++CONFIG_CONNECTOR=y
++CONFIG_PROC_EVENTS=y
++CONFIG_MTD=y
++# CONFIG_MTD_DEBUG is not set
++CONFIG_MTD_CONCAT=y
++CONFIG_MTD_PARTITIONS=y
++# CONFIG_MTD_REDBOOT_PARTS is not set
++# CONFIG_MTD_CMDLINE_PARTS is not set
++# CONFIG_MTD_AFS_PARTS is not set
++# CONFIG_MTD_AR7_PARTS is not set
++
++#
++# User Modules And Translation Layers
++#
++CONFIG_MTD_CHAR=y
++CONFIG_MTD_BLKDEVS=y
++CONFIG_MTD_BLOCK=y
++# CONFIG_FTL is not set
++# CONFIG_NFTL is not set
++# CONFIG_INFTL is not set
++# CONFIG_RFD_FTL is not set
++# CONFIG_SSFDC is not set
++# CONFIG_MTD_OOPS is not set
++
++#
++# RAM/ROM/Flash chip drivers
++#
++# CONFIG_MTD_CFI is not set
++# CONFIG_MTD_JEDECPROBE is not set
++CONFIG_MTD_MAP_BANK_WIDTH_1=y
++CONFIG_MTD_MAP_BANK_WIDTH_2=y
++CONFIG_MTD_MAP_BANK_WIDTH_4=y
++# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
++# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
++# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
++CONFIG_MTD_CFI_I1=y
++CONFIG_MTD_CFI_I2=y
++# CONFIG_MTD_CFI_I4 is not set
++# CONFIG_MTD_CFI_I8 is not set
++# CONFIG_MTD_RAM is not set
++# CONFIG_MTD_ROM is not set
++# CONFIG_MTD_ABSENT is not set
++
++#
++# Mapping drivers for chip access
++#
++# CONFIG_MTD_COMPLEX_MAPPINGS is not set
++# CONFIG_MTD_PLATRAM is not set
++
++#
++# Self-contained MTD device drivers
++#
++# CONFIG_MTD_SLRAM is not set
++# CONFIG_MTD_PHRAM is not set
++# CONFIG_MTD_MTDRAM is not set
++# CONFIG_MTD_BLOCK2MTD is not set
++
++#
++# Disk-On-Chip Device Drivers
++#
++# CONFIG_MTD_DOC2000 is not set
++# CONFIG_MTD_DOC2001 is not set
++# CONFIG_MTD_DOC2001PLUS is not set
++# CONFIG_MTD_NAND is not set
++# CONFIG_MTD_ONENAND is not set
++
++#
++# UBI - Unsorted block images
++#
++# CONFIG_MTD_UBI is not set
++# CONFIG_PARPORT is not set
++CONFIG_BLK_DEV=y
++# CONFIG_BLK_DEV_COW_COMMON is not set
++CONFIG_BLK_DEV_LOOP=y
++# CONFIG_BLK_DEV_CRYPTOLOOP is not set
++CONFIG_BLK_DEV_NBD=y
++# CONFIG_BLK_DEV_UB is not set
++CONFIG_BLK_DEV_RAM=y
++CONFIG_BLK_DEV_RAM_COUNT=16
++CONFIG_BLK_DEV_RAM_SIZE=16384
++# CONFIG_BLK_DEV_XIP is not set
++# CONFIG_CDROM_PKTCDVD is not set
++# CONFIG_ATA_OVER_ETH is not set
++CONFIG_MISC_DEVICES=y
++# CONFIG_EEPROM_93CX6 is not set
++# CONFIG_ICS932S401 is not set
++# CONFIG_ENCLOSURE_SERVICES is not set
++# CONFIG_C2PORT is not set
++CONFIG_HAVE_IDE=y
++# CONFIG_IDE is not set
++
++#
++# SCSI device support
++#
++# CONFIG_RAID_ATTRS is not set
++CONFIG_SCSI=y
++CONFIG_SCSI_DMA=y
++CONFIG_SCSI_TGT=y
++# CONFIG_SCSI_NETLINK is not set
++CONFIG_SCSI_PROC_FS=y
++
++#
++# SCSI support type (disk, tape, CD-ROM)
++#
++CONFIG_BLK_DEV_SD=y
++# CONFIG_CHR_DEV_ST is not set
++# CONFIG_CHR_DEV_OSST is not set
++# CONFIG_BLK_DEV_SR is not set
++CONFIG_CHR_DEV_SG=y
++# CONFIG_CHR_DEV_SCH is not set
++
++#
++# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
++#
++# CONFIG_SCSI_MULTI_LUN is not set
++# CONFIG_SCSI_CONSTANTS is not set
++# CONFIG_SCSI_LOGGING is not set
++CONFIG_SCSI_SCAN_ASYNC=y
++CONFIG_SCSI_WAIT_SCAN=m
++
++#
++# SCSI Transports
++#
++# CONFIG_SCSI_SPI_ATTRS is not set
++# CONFIG_SCSI_FC_ATTRS is not set
++CONFIG_SCSI_ISCSI_ATTRS=m
++# CONFIG_SCSI_SAS_LIBSAS is not set
++# CONFIG_SCSI_SRP_ATTRS is not set
++# CONFIG_SCSI_LOWLEVEL is not set
++# CONFIG_SCSI_DH is not set
++# CONFIG_ATA is not set
++# CONFIG_MD is not set
++CONFIG_NETDEVICES=y
++# CONFIG_DUMMY is not set
++CONFIG_BONDING=y
++# CONFIG_MACVLAN is not set
++# CONFIG_EQUALIZER is not set
++# CONFIG_TUN is not set
++# CONFIG_VETH is not set
++# CONFIG_NET_ETHERNET is not set
++CONFIG_NETDEV_1000=y
++CONFIG_ASPEEDMAC=y
++# CONFIG_NETDEV_10000 is not set
++
++#
++# Wireless LAN
++#
++# CONFIG_WLAN_PRE80211 is not set
++# CONFIG_WLAN_80211 is not set
++# CONFIG_IWLWIFI_LEDS is not set
++
++#
++# USB Network Adapters
++#
++# CONFIG_USB_CATC is not set
++# CONFIG_USB_KAWETH is not set
++# CONFIG_USB_PEGASUS is not set
++# CONFIG_USB_RTL8150 is not set
++# CONFIG_USB_USBNET is not set
++# CONFIG_WAN is not set
++# CONFIG_PPP is not set
++# CONFIG_SLIP is not set
++# CONFIG_NETCONSOLE is not set
++# CONFIG_NETPOLL is not set
++# CONFIG_NET_POLL_CONTROLLER is not set
++# CONFIG_ISDN is not set
++
++#
++# Input device support
++#
++CONFIG_INPUT=y
++# CONFIG_INPUT_FF_MEMLESS is not set
++# CONFIG_INPUT_POLLDEV is not set
++
++#
++# Userland interfaces
++#
++CONFIG_INPUT_MOUSEDEV=y
++CONFIG_INPUT_MOUSEDEV_PSAUX=y
++CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
++CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
++# CONFIG_INPUT_JOYDEV is not set
++CONFIG_INPUT_EVDEV=y
++# CONFIG_INPUT_EVBUG is not set
++
++#
++# Input Device Drivers
++#
++CONFIG_INPUT_KEYBOARD=y
++CONFIG_KEYBOARD_ATKBD=y
++# CONFIG_KEYBOARD_SUNKBD is not set
++# CONFIG_KEYBOARD_LKKBD is not set
++# CONFIG_KEYBOARD_XTKBD is not set
++# CONFIG_KEYBOARD_NEWTON is not set
++# CONFIG_KEYBOARD_STOWAWAY is not set
++# CONFIG_KEYBOARD_GPIO is not set
++CONFIG_INPUT_MOUSE=y
++CONFIG_MOUSE_PS2=y
++CONFIG_MOUSE_PS2_ALPS=y
++CONFIG_MOUSE_PS2_LOGIPS2PP=y
++CONFIG_MOUSE_PS2_SYNAPTICS=y
++CONFIG_MOUSE_PS2_LIFEBOOK=y
++CONFIG_MOUSE_PS2_TRACKPOINT=y
++# CONFIG_MOUSE_PS2_ELANTECH is not set
++# CONFIG_MOUSE_PS2_TOUCHKIT is not set
++CONFIG_MOUSE_SERIAL=y
++# CONFIG_MOUSE_APPLETOUCH is not set
++# CONFIG_MOUSE_BCM5974 is not set
++# CONFIG_MOUSE_VSXXXAA is not set
++# CONFIG_MOUSE_GPIO is not set
++# CONFIG_INPUT_JOYSTICK is not set
++# CONFIG_INPUT_TABLET is not set
++# CONFIG_INPUT_TOUCHSCREEN is not set
++# CONFIG_INPUT_MISC is not set
++
++#
++# Hardware I/O ports
++#
++CONFIG_SERIO=y
++CONFIG_SERIO_SERPORT=y
++# CONFIG_SERIO_AMBAKMI is not set
++CONFIG_SERIO_LIBPS2=y
++# CONFIG_SERIO_RAW is not set
++# CONFIG_GAMEPORT is not set
++
++#
++# Character devices
++#
++CONFIG_VT=y
++CONFIG_CONSOLE_TRANSLATIONS=y
++CONFIG_VT_CONSOLE=y
++CONFIG_HW_CONSOLE=y
++# CONFIG_VT_HW_CONSOLE_BINDING is not set
++CONFIG_DEVKMEM=y
++CONFIG_SERIAL_NONSTANDARD=y
++# CONFIG_N_HDLC is not set
++# CONFIG_RISCOM8 is not set
++# CONFIG_SPECIALIX is not set
++# CONFIG_RIO is not set
++# CONFIG_STALDRV is not set
++
++#
++# Serial drivers
++#
++CONFIG_SERIAL_8250=y
++CONFIG_SERIAL_8250_CONSOLE=y
++CONFIG_SERIAL_8250_NR_UARTS=4
++CONFIG_SERIAL_8250_RUNTIME_UARTS=4
++# CONFIG_SERIAL_AST_DMA_UART is not set
++# CONFIG_SERIAL_8250_EXTENDED is not set
++
++#
++# Non-8250 serial port support
++#
++# CONFIG_SERIAL_AMBA_PL010 is not set
++# CONFIG_SERIAL_AMBA_PL011 is not set
++# CONFIG_SERIAL_AST is not set
++CONFIG_SERIAL_CORE=y
++CONFIG_SERIAL_CORE_CONSOLE=y
++CONFIG_UNIX98_PTYS=y
++CONFIG_LEGACY_PTYS=y
++CONFIG_LEGACY_PTY_COUNT=256
++# CONFIG_IPMI_HANDLER is not set
++CONFIG_AST_MISC=y
++# CONFIG_AST_VIDEO is not set
++# CONFIG_ADC_CAT9883 is not set
++# CONFIG_AST_SPI_BIOS is not set
++CONFIG_AST_PECI=y
++# CONFIG_AST_KCS is not set
++# CONFIG_AST_GPIO is not set
++# CONFIG_HW_RANDOM is not set
++CONFIG_NVRAM=y
++# CONFIG_R3964 is not set
++# CONFIG_RAW_DRIVER is not set
++# CONFIG_TCG_TPM is not set
++CONFIG_I2C=y
++CONFIG_I2C_BOARDINFO=y
++CONFIG_I2C_CHARDEV=y
++CONFIG_I2C_HELPER_AUTO=y
++
++#
++# I2C Hardware Bus support
++#
++
++#
++# I2C system bus drivers (mostly embedded / system-on-chip)
++#
++# CONFIG_I2C_GPIO is not set
++# CONFIG_I2C_OCORES is not set
++CONFIG_I2C_AST=y
++CONFIG_AST_I2C_SLAVE_MODE=y
++CONFIG_AST_I2C_SLAVE_EEPROM=y
++# CONFIG_AST_I2C_SLAVE_RDWR is not set
++# CONFIG_I2C_SIMTEC is not set
++
++#
++# External I2C/SMBus adapter drivers
++#
++# CONFIG_I2C_PARPORT_LIGHT is not set
++# CONFIG_I2C_TAOS_EVM is not set
++# CONFIG_I2C_TINY_USB is not set
++
++#
++# Other I2C/SMBus bus drivers
++#
++# CONFIG_I2C_PCA_PLATFORM is not set
++# CONFIG_I2C_STUB is not set
++
++#
++# Miscellaneous I2C Chip support
++#
++# CONFIG_DS1682 is not set
++CONFIG_AT24=y
++# CONFIG_SENSORS_EEPROM is not set
++# CONFIG_SENSORS_PCF8574 is not set
++# CONFIG_PCF8575 is not set
++# CONFIG_SENSORS_PCA9539 is not set
++# CONFIG_SENSORS_PCF8591 is not set
++# CONFIG_TPS65010 is not set
++# CONFIG_SENSORS_MAX6875 is not set
++# CONFIG_SENSORS_TSL2550 is not set
++# CONFIG_I2C_DEBUG_CORE is not set
++# CONFIG_I2C_DEBUG_ALGO is not set
++# CONFIG_I2C_DEBUG_BUS is not set
++# CONFIG_I2C_DEBUG_CHIP is not set
++# CONFIG_SPI is not set
++CONFIG_ARCH_REQUIRE_GPIOLIB=y
++CONFIG_GPIOLIB=y
++CONFIG_GPIO_SYSFS=y
++
++#
++# Memory mapped GPIO expanders:
++#
++
++#
++# I2C GPIO expanders:
++#
++# CONFIG_GPIO_MAX732X is not set
++# CONFIG_GPIO_PCA953X is not set
++# CONFIG_GPIO_PCF857X is not set
++
++#
++# PCI GPIO expanders:
++#
++
++#
++# SPI GPIO expanders:
++#
++# CONFIG_W1 is not set
++# CONFIG_POWER_SUPPLY is not set
++CONFIG_HWMON=y
++# CONFIG_HWMON_VID is not set
++# CONFIG_SENSORS_AD7414 is not set
++# CONFIG_SENSORS_AD7418 is not set
++# CONFIG_SENSORS_ADM1021 is not set
++# CONFIG_SENSORS_ADM1025 is not set
++# CONFIG_SENSORS_ADM1026 is not set
++# CONFIG_SENSORS_ADM1029 is not set
++# CONFIG_SENSORS_ADM1031 is not set
++# CONFIG_SENSORS_ADM9240 is not set
++# CONFIG_SENSORS_ADT7462 is not set
++# CONFIG_SENSORS_ADT7470 is not set
++# CONFIG_SENSORS_ADT7473 is not set
++# CONFIG_SENSORS_ATXP1 is not set
++# CONFIG_SENSORS_DS1621 is not set
++# CONFIG_SENSORS_F71805F is not set
++# CONFIG_SENSORS_F71882FG is not set
++# CONFIG_SENSORS_F75375S is not set
++# CONFIG_SENSORS_GL518SM is not set
++# CONFIG_SENSORS_GL520SM is not set
++# CONFIG_SENSORS_IT87 is not set
++# CONFIG_SENSORS_LM63 is not set
++# CONFIG_SENSORS_LM75 is not set
++# CONFIG_SENSORS_LM77 is not set
++# CONFIG_SENSORS_LM78 is not set
++# CONFIG_SENSORS_LM80 is not set
++# CONFIG_SENSORS_LM83 is not set
++# CONFIG_SENSORS_LM85 is not set
++# CONFIG_SENSORS_LM87 is not set
++# CONFIG_SENSORS_LM90 is not set
++# CONFIG_SENSORS_LM92 is not set
++# CONFIG_SENSORS_LM93 is not set
++# CONFIG_SENSORS_MAX1619 is not set
++# CONFIG_SENSORS_MAX6650 is not set
++# CONFIG_SENSORS_PC87360 is not set
++# CONFIG_SENSORS_PC87427 is not set
++# CONFIG_SENSORS_DME1737 is not set
++# CONFIG_SENSORS_SMSC47M1 is not set
++# CONFIG_SENSORS_SMSC47M192 is not set
++# CONFIG_SENSORS_SMSC47B397 is not set
++# CONFIG_SENSORS_ADS7828 is not set
++# CONFIG_SENSORS_THMC50 is not set
++# CONFIG_SENSORS_VT1211 is not set
++# CONFIG_SENSORS_W83781D is not set
++# CONFIG_SENSORS_W83791D is not set
++# CONFIG_SENSORS_W83792D is not set
++# CONFIG_SENSORS_W83793 is not set
++# CONFIG_SENSORS_W83L785TS is not set
++# CONFIG_SENSORS_W83L786NG is not set
++# CONFIG_SENSORS_W83627HF is not set
++# CONFIG_SENSORS_W83627EHF is not set
++CONFIG_SENSORS_AST_ADC=y
++CONFIG_SENSORS_AST_PWM_FAN=y
++# CONFIG_HWMON_DEBUG_CHIP is not set
++# CONFIG_THERMAL is not set
++# CONFIG_THERMAL_HWMON is not set
++CONFIG_WATCHDOG=y
++# CONFIG_WATCHDOG_NOWAYOUT is not set
++
++#
++# Watchdog Device Drivers
++#
++# CONFIG_SOFT_WATCHDOG is not set
++CONFIG_AST_WATCHDOG=y
++
++#
++# USB-based Watchdog Cards
++#
++# CONFIG_USBPCWATCHDOG is not set
++CONFIG_SSB_POSSIBLE=y
++
++#
++# Sonics Silicon Backplane
++#
++# CONFIG_SSB is not set
++
++#
++# Multifunction device drivers
++#
++# CONFIG_MFD_CORE is not set
++# CONFIG_MFD_SM501 is not set
++# CONFIG_MFD_ASIC3 is not set
++# CONFIG_HTC_EGPIO is not set
++# CONFIG_HTC_PASIC3 is not set
++# CONFIG_MFD_TMIO is not set
++# CONFIG_MFD_TC6393XB is not set
++# CONFIG_PMIC_DA903X is not set
++# CONFIG_MFD_WM8400 is not set
++# CONFIG_MFD_WM8350_I2C is not set
++
++#
++# Multimedia devices
++#
++
++#
++# Multimedia core support
++#
++# CONFIG_VIDEO_DEV is not set
++# CONFIG_DVB_CORE is not set
++# CONFIG_VIDEO_MEDIA is not set
++
++#
++# Multimedia drivers
++#
++# CONFIG_DAB is not set
++
++#
++# Graphics support
++#
++# CONFIG_VGASTATE is not set
++# CONFIG_VIDEO_OUTPUT_CONTROL is not set
++# CONFIG_FB is not set
++# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
++
++#
++# Display device support
++#
++# CONFIG_DISPLAY_SUPPORT is not set
++
++#
++# Console display driver support
++#
++# CONFIG_VGA_CONSOLE is not set
++CONFIG_DUMMY_CONSOLE=y
++# CONFIG_SOUND is not set
++CONFIG_HID_SUPPORT=y
++CONFIG_HID=y
++CONFIG_HID_DEBUG=y
++# CONFIG_HIDRAW is not set
++
++#
++# USB Input Devices
++#
++CONFIG_USB_HID=y
++# CONFIG_HID_PID is not set
++# CONFIG_USB_HIDDEV is not set
++
++#
++# Special HID drivers
++#
++CONFIG_HID_COMPAT=y
++CONFIG_HID_A4TECH=y
++CONFIG_HID_APPLE=y
++CONFIG_HID_BELKIN=y
++CONFIG_HID_BRIGHT=y
++CONFIG_HID_CHERRY=y
++CONFIG_HID_CHICONY=y
++CONFIG_HID_CYPRESS=y
++CONFIG_HID_DELL=y
++CONFIG_HID_EZKEY=y
++CONFIG_HID_GYRATION=y
++CONFIG_HID_LOGITECH=y
++# CONFIG_LOGITECH_FF is not set
++# CONFIG_LOGIRUMBLEPAD2_FF is not set
++CONFIG_HID_MICROSOFT=y
++CONFIG_HID_MONTEREY=y
++CONFIG_HID_PANTHERLORD=y
++# CONFIG_PANTHERLORD_FF is not set
++CONFIG_HID_PETALYNX=y
++CONFIG_HID_SAMSUNG=y
++CONFIG_HID_SONY=y
++CONFIG_HID_SUNPLUS=y
++# CONFIG_THRUSTMASTER_FF is not set
++# CONFIG_ZEROPLUS_FF is not set
++CONFIG_USB_SUPPORT=y
++CONFIG_USB_ARCH_HAS_HCD=y
++# CONFIG_USB_ARCH_HAS_OHCI is not set
++CONFIG_USB_ARCH_HAS_EHCI=y
++CONFIG_USB=y
++# CONFIG_USB_DEBUG is not set
++# CONFIG_USB_ANNOUNCE_NEW_DEVICES is not set
++
++#
++# Miscellaneous USB options
++#
++CONFIG_USB_DEVICEFS=y
++CONFIG_USB_DEVICE_CLASS=y
++# CONFIG_USB_DYNAMIC_MINORS is not set
++# CONFIG_USB_SUSPEND is not set
++# CONFIG_USB_OTG is not set
++# CONFIG_USB_MON is not set
++# CONFIG_USB_WUSB is not set
++# CONFIG_USB_WUSB_CBAF is not set
++
++#
++# USB Host Controller Drivers
++#
++# CONFIG_USB_C67X00_HCD is not set
++CONFIG_USB_EHCI_HCD=y
++# CONFIG_USB_EHCI_ROOT_HUB_TT is not set
++CONFIG_USB_EHCI_TT_NEWSCHED=y
++CONFIG_USB_EHCI_AST=y
++# CONFIG_USB_ISP116X_HCD is not set
++# CONFIG_USB_SL811_HCD is not set
++# CONFIG_USB_R8A66597_HCD is not set
++# CONFIG_USB_HWA_HCD is not set
++
++#
++# AST USB Drivers
++#
++CONFIG_AST_USB_UHCI_HCD=y
++# CONFIG_AST_USB_UHCI_MULTIPORT_1 is not set
++# CONFIG_AST_USB_UHCI_MULTIPORT_2 is not set
++CONFIG_AST_USB_UHCI_MULTIPORT_4=y
++# CONFIG_USB_EHCI_SPLIT_ISO is not set
++
++#
++# USB Device Class drivers
++#
++# CONFIG_USB_ACM is not set
++# CONFIG_USB_PRINTER is not set
++# CONFIG_USB_WDM is not set
++# CONFIG_USB_TMC is not set
++
++#
++# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may also be needed;
++#
++
++#
++# see USB_STORAGE Help for more information
++#
++CONFIG_USB_STORAGE=y
++# CONFIG_USB_STORAGE_DEBUG is not set
++# CONFIG_USB_STORAGE_DATAFAB is not set
++# CONFIG_USB_STORAGE_FREECOM is not set
++# CONFIG_USB_STORAGE_ISD200 is not set
++# CONFIG_USB_STORAGE_DPCM is not set
++# CONFIG_USB_STORAGE_USBAT is not set
++# CONFIG_USB_STORAGE_SDDR09 is not set
++# CONFIG_USB_STORAGE_SDDR55 is not set
++# CONFIG_USB_STORAGE_JUMPSHOT is not set
++# CONFIG_USB_STORAGE_ALAUDA is not set
++# CONFIG_USB_STORAGE_ONETOUCH is not set
++# CONFIG_USB_STORAGE_KARMA is not set
++# CONFIG_USB_STORAGE_CYPRESS_ATACB is not set
++# CONFIG_USB_LIBUSUAL is not set
++
++#
++# USB Imaging devices
++#
++# CONFIG_USB_MDC800 is not set
++# CONFIG_USB_MICROTEK is not set
++
++#
++# USB port drivers
++#
++# CONFIG_USB_SERIAL is not set
++
++#
++# USB Miscellaneous drivers
++#
++# CONFIG_USB_EMI62 is not set
++# CONFIG_USB_EMI26 is not set
++# CONFIG_USB_ADUTUX is not set
++# CONFIG_USB_SEVSEG is not set
++# CONFIG_USB_RIO500 is not set
++# CONFIG_USB_LEGOTOWER is not set
++# CONFIG_USB_LCD is not set
++# CONFIG_USB_BERRY_CHARGE is not set
++# CONFIG_USB_LED is not set
++# CONFIG_USB_CYPRESS_CY7C63 is not set
++# CONFIG_USB_CYTHERM is not set
++# CONFIG_USB_PHIDGET is not set
++# CONFIG_USB_IDMOUSE is not set
++# CONFIG_USB_FTDI_ELAN is not set
++# CONFIG_USB_APPLEDISPLAY is not set
++# CONFIG_USB_SISUSBVGA is not set
++# CONFIG_USB_LD is not set
++# CONFIG_USB_TRANCEVIBRATOR is not set
++# CONFIG_USB_IOWARRIOR is not set
++# CONFIG_USB_TEST is not set
++# CONFIG_USB_ISIGHTFW is not set
++# CONFIG_USB_VST is not set
++# CONFIG_USB_GADGET is not set
++CONFIG_MMC=y
++# CONFIG_MMC_DEBUG is not set
++# CONFIG_MMC_UNSAFE_RESUME is not set
++
++#
++# MMC/SD/SDIO Card Drivers
++#
++CONFIG_MMC_BLOCK=y
++CONFIG_MMC_BLOCK_BOUNCE=y
++# CONFIG_SDIO_UART is not set
++# CONFIG_MMC_TEST is not set
++
++#
++# MMC/SD/SDIO Host Controller Drivers
++#
++# CONFIG_MMC_ARMMMCI is not set
++# CONFIG_MMC_SDHCI is not set
++CONFIG_MMC_AST=y
++# CONFIG_MEMSTICK is not set
++# CONFIG_ACCESSIBILITY is not set
++# CONFIG_NEW_LEDS is not set
++CONFIG_RTC_LIB=y
++CONFIG_RTC_CLASS=y
++# CONFIG_RTC_HCTOSYS is not set
++# CONFIG_RTC_DEBUG is not set
++
++#
++# RTC interfaces
++#
++CONFIG_RTC_INTF_SYSFS=y
++CONFIG_RTC_INTF_PROC=y
++CONFIG_RTC_INTF_DEV=y
++# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set
++# CONFIG_RTC_DRV_TEST is not set
++
++#
++# I2C RTC drivers
++#
++# CONFIG_RTC_DRV_DS1307 is not set
++# CONFIG_RTC_DRV_DS1374 is not set
++# CONFIG_RTC_DRV_DS1672 is not set
++# CONFIG_RTC_DRV_MAX6900 is not set
++# CONFIG_RTC_DRV_RS5C372 is not set
++# CONFIG_RTC_DRV_ISL1208 is not set
++# CONFIG_RTC_DRV_X1205 is not set
++# CONFIG_RTC_DRV_PCF8563 is not set
++# CONFIG_RTC_DRV_PCF8583 is not set
++# CONFIG_RTC_DRV_M41T80 is not set
++# CONFIG_RTC_DRV_S35390A is not set
++# CONFIG_RTC_DRV_FM3130 is not set
++# CONFIG_RTC_DRV_RX8581 is not set
++
++#
++# SPI RTC drivers
++#
++
++#
++# Platform RTC drivers
++#
++# CONFIG_RTC_DRV_CMOS is not set
++# CONFIG_RTC_DRV_DS1286 is not set
++# CONFIG_RTC_DRV_DS1511 is not set
++# CONFIG_RTC_DRV_DS1553 is not set
++# CONFIG_RTC_DRV_DS1742 is not set
++# CONFIG_RTC_DRV_STK17TA8 is not set
++# CONFIG_RTC_DRV_M48T86 is not set
++# CONFIG_RTC_DRV_M48T35 is not set
++# CONFIG_RTC_DRV_M48T59 is not set
++# CONFIG_RTC_DRV_BQ4802 is not set
++# CONFIG_RTC_DRV_V3020 is not set
++
++#
++# on-CPU RTC drivers
++#
++# CONFIG_RTC_DRV_PL030 is not set
++# CONFIG_RTC_DRV_PL031 is not set
++CONFIG_RTC_DRV_ASPEED=y
++# CONFIG_DMADEVICES is not set
++# CONFIG_REGULATOR is not set
++# CONFIG_UIO is not set
++
++#
++# File systems
++#
++CONFIG_EXT2_FS=y
++CONFIG_EXT2_FS_XATTR=y
++CONFIG_EXT2_FS_POSIX_ACL=y
++CONFIG_EXT2_FS_SECURITY=y
++# CONFIG_EXT2_FS_XIP is not set
++# CONFIG_EXT3_FS is not set
++# CONFIG_EXT4_FS is not set
++CONFIG_FS_MBCACHE=y
++# CONFIG_REISERFS_FS is not set
++# CONFIG_JFS_FS is not set
++CONFIG_FS_POSIX_ACL=y
++CONFIG_FILE_LOCKING=y
++# CONFIG_XFS_FS is not set
++# CONFIG_OCFS2_FS is not set
++CONFIG_DNOTIFY=y
++CONFIG_INOTIFY=y
++CONFIG_INOTIFY_USER=y
++# CONFIG_QUOTA is not set
++# CONFIG_AUTOFS_FS is not set
++# CONFIG_AUTOFS4_FS is not set
++# CONFIG_FUSE_FS is not set
++CONFIG_GENERIC_ACL=y
++
++#
++# CD-ROM/DVD Filesystems
++#
++# CONFIG_ISO9660_FS is not set
++# CONFIG_UDF_FS is not set
++
++#
++# DOS/FAT/NT Filesystems
++#
++CONFIG_FAT_FS=y
++CONFIG_MSDOS_FS=y
++CONFIG_VFAT_FS=y
++CONFIG_FAT_DEFAULT_CODEPAGE=437
++CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
++CONFIG_NTFS_FS=y
++# CONFIG_NTFS_DEBUG is not set
++CONFIG_NTFS_RW=y
++
++#
++# Pseudo filesystems
++#
++CONFIG_PROC_FS=y
++CONFIG_PROC_SYSCTL=y
++CONFIG_PROC_PAGE_MONITOR=y
++CONFIG_SYSFS=y
++CONFIG_TMPFS=y
++CONFIG_TMPFS_POSIX_ACL=y
++# CONFIG_HUGETLB_PAGE is not set
++CONFIG_CONFIGFS_FS=m
++
++#
++# Miscellaneous filesystems
++#
++# CONFIG_ADFS_FS is not set
++# CONFIG_AFFS_FS is not set
++# CONFIG_HFS_FS is not set
++# CONFIG_HFSPLUS_FS is not set
++# CONFIG_BEFS_FS is not set
++# CONFIG_BFS_FS is not set
++# CONFIG_EFS_FS is not set
++CONFIG_YAFFS_FS=y
++CONFIG_YAFFS_YAFFS1=y
++# CONFIG_YAFFS_9BYTE_TAGS is not set
++# CONFIG_YAFFS_DOES_ECC is not set
++CONFIG_YAFFS_YAFFS2=y
++CONFIG_YAFFS_AUTO_YAFFS2=y
++# CONFIG_YAFFS_DISABLE_TAGS_ECC is not set
++# CONFIG_YAFFS_DISABLE_LAZY_LOAD is not set
++# CONFIG_YAFFS_DISABLE_WIDE_TNODES is not set
++# CONFIG_YAFFS_ALWAYS_CHECK_CHUNK_ERASED is not set
++CONFIG_YAFFS_SHORT_NAMES_IN_RAM=y
++# CONFIG_YAFFS_EMPTY_LOST_AND_FOUND is not set
++# CONFIG_JFFS2_FS is not set
++# CONFIG_CRAMFS is not set
++# CONFIG_VXFS_FS is not set
++# CONFIG_MINIX_FS is not set
++# CONFIG_OMFS_FS is not set
++# CONFIG_HPFS_FS is not set
++# CONFIG_QNX4FS_FS is not set
++# CONFIG_ROMFS_FS is not set
++# CONFIG_SYSV_FS is not set
++# CONFIG_UFS_FS is not set
++CONFIG_NETWORK_FILESYSTEMS=y
++CONFIG_NFS_FS=y
++# CONFIG_NFS_V3 is not set
++# CONFIG_NFS_V4 is not set
++CONFIG_ROOT_NFS=y
++# CONFIG_NFSD is not set
++CONFIG_LOCKD=y
++CONFIG_NFS_COMMON=y
++CONFIG_SUNRPC=y
++# CONFIG_SUNRPC_REGISTER_V4 is not set
++# CONFIG_RPCSEC_GSS_KRB5 is not set
++# CONFIG_RPCSEC_GSS_SPKM3 is not set
++# CONFIG_SMB_FS is not set
++# CONFIG_CIFS is not set
++# CONFIG_NCP_FS is not set
++# CONFIG_CODA_FS is not set
++# CONFIG_AFS_FS is not set
++
++#
++# Partition Types
++#
++# CONFIG_PARTITION_ADVANCED is not set
++CONFIG_MSDOS_PARTITION=y
++CONFIG_NLS=y
++CONFIG_NLS_DEFAULT="utf8"
++CONFIG_NLS_CODEPAGE_437=y
++# CONFIG_NLS_CODEPAGE_737 is not set
++# CONFIG_NLS_CODEPAGE_775 is not set
++# CONFIG_NLS_CODEPAGE_850 is not set
++# CONFIG_NLS_CODEPAGE_852 is not set
++# CONFIG_NLS_CODEPAGE_855 is not set
++# CONFIG_NLS_CODEPAGE_857 is not set
++# CONFIG_NLS_CODEPAGE_860 is not set
++# CONFIG_NLS_CODEPAGE_861 is not set
++# CONFIG_NLS_CODEPAGE_862 is not set
++# CONFIG_NLS_CODEPAGE_863 is not set
++# CONFIG_NLS_CODEPAGE_864 is not set
++# CONFIG_NLS_CODEPAGE_865 is not set
++# CONFIG_NLS_CODEPAGE_866 is not set
++# CONFIG_NLS_CODEPAGE_869 is not set
++CONFIG_NLS_CODEPAGE_936=y
++CONFIG_NLS_CODEPAGE_950=y
++CONFIG_NLS_CODEPAGE_932=y
++# CONFIG_NLS_CODEPAGE_949 is not set
++# CONFIG_NLS_CODEPAGE_874 is not set
++# CONFIG_NLS_ISO8859_8 is not set
++# CONFIG_NLS_CODEPAGE_1250 is not set
++# CONFIG_NLS_CODEPAGE_1251 is not set
++CONFIG_NLS_ASCII=y
++CONFIG_NLS_ISO8859_1=y
++# CONFIG_NLS_ISO8859_2 is not set
++# CONFIG_NLS_ISO8859_3 is not set
++# CONFIG_NLS_ISO8859_4 is not set
++# CONFIG_NLS_ISO8859_5 is not set
++# CONFIG_NLS_ISO8859_6 is not set
++# CONFIG_NLS_ISO8859_7 is not set
++# CONFIG_NLS_ISO8859_9 is not set
++# CONFIG_NLS_ISO8859_13 is not set
++# CONFIG_NLS_ISO8859_14 is not set
++# CONFIG_NLS_ISO8859_15 is not set
++# CONFIG_NLS_KOI8_R is not set
++# CONFIG_NLS_KOI8_U is not set
++CONFIG_NLS_UTF8=y
++# CONFIG_DLM is not set
++
++#
++# Kernel hacking
++#
++# CONFIG_PRINTK_TIME is not set
++# CONFIG_ENABLE_WARN_DEPRECATED is not set
++CONFIG_ENABLE_MUST_CHECK=y
++CONFIG_FRAME_WARN=1024
++CONFIG_MAGIC_SYSRQ=y
++# CONFIG_UNUSED_SYMBOLS is not set
++# CONFIG_DEBUG_FS is not set
++# CONFIG_HEADERS_CHECK is not set
++# CONFIG_DEBUG_KERNEL is not set
++# CONFIG_SLUB_DEBUG_ON is not set
++# CONFIG_SLUB_STATS is not set
++CONFIG_DEBUG_BUGVERBOSE=y
++CONFIG_DEBUG_MEMORY_INIT=y
++CONFIG_FRAME_POINTER=y
++# CONFIG_RCU_CPU_STALL_DETECTOR is not set
++# CONFIG_LATENCYTOP is not set
++# CONFIG_SYSCTL_SYSCALL_CHECK is not set
++CONFIG_HAVE_FUNCTION_TRACER=y
++
++#
++# Tracers
++#
++# CONFIG_DYNAMIC_PRINTK_DEBUG is not set
++# CONFIG_SAMPLES is not set
++CONFIG_HAVE_ARCH_KGDB=y
++# CONFIG_DEBUG_USER is not set
++
++#
++# Security options
++#
++# CONFIG_KEYS is not set
++# CONFIG_SECURITY is not set
++# CONFIG_SECURITYFS is not set
++# CONFIG_SECURITY_FILE_CAPABILITIES is not set
++CONFIG_CRYPTO=y
++
++#
++# Crypto core or helper
++#
++# CONFIG_CRYPTO_FIPS is not set
++CONFIG_CRYPTO_ALGAPI=y
++CONFIG_CRYPTO_ALGAPI2=y
++CONFIG_CRYPTO_AEAD=m
++CONFIG_CRYPTO_AEAD2=y
++CONFIG_CRYPTO_BLKCIPHER=y
++CONFIG_CRYPTO_BLKCIPHER2=y
++CONFIG_CRYPTO_HASH=y
++CONFIG_CRYPTO_HASH2=y
++CONFIG_CRYPTO_RNG2=y
++CONFIG_CRYPTO_MANAGER=y
++CONFIG_CRYPTO_MANAGER2=y
++# CONFIG_CRYPTO_GF128MUL is not set
++CONFIG_CRYPTO_NULL=y
++# CONFIG_CRYPTO_CRYPTD is not set
++CONFIG_CRYPTO_AUTHENC=m
++# CONFIG_CRYPTO_TEST is not set
++
++#
++# Authenticated Encryption with Associated Data
++#
++# CONFIG_CRYPTO_CCM is not set
++# CONFIG_CRYPTO_GCM is not set
++# CONFIG_CRYPTO_SEQIV is not set
++
++#
++# Block modes
++#
++CONFIG_CRYPTO_CBC=y
++# CONFIG_CRYPTO_CTR is not set
++# CONFIG_CRYPTO_CTS is not set
++# CONFIG_CRYPTO_ECB is not set
++# CONFIG_CRYPTO_LRW is not set
++# CONFIG_CRYPTO_PCBC is not set
++# CONFIG_CRYPTO_XTS is not set
++
++#
++# Hash modes
++#
++CONFIG_CRYPTO_HMAC=y
++# CONFIG_CRYPTO_XCBC is not set
++
++#
++# Digest
++#
++# CONFIG_CRYPTO_CRC32C is not set
++# CONFIG_CRYPTO_MD4 is not set
++CONFIG_CRYPTO_MD5=y
++# CONFIG_CRYPTO_MICHAEL_MIC is not set
++# CONFIG_CRYPTO_RMD128 is not set
++# CONFIG_CRYPTO_RMD160 is not set
++# CONFIG_CRYPTO_RMD256 is not set
++# CONFIG_CRYPTO_RMD320 is not set
++CONFIG_CRYPTO_SHA1=y
++# CONFIG_CRYPTO_SHA256 is not set
++# CONFIG_CRYPTO_SHA512 is not set
++# CONFIG_CRYPTO_TGR192 is not set
++# CONFIG_CRYPTO_WP512 is not set
++
++#
++# Ciphers
++#
++# CONFIG_CRYPTO_AES is not set
++# CONFIG_CRYPTO_ANUBIS is not set
++# CONFIG_CRYPTO_ARC4 is not set
++# CONFIG_CRYPTO_BLOWFISH is not set
++# CONFIG_CRYPTO_CAMELLIA is not set
++# CONFIG_CRYPTO_CAST5 is not set
++# CONFIG_CRYPTO_CAST6 is not set
++CONFIG_CRYPTO_DES=y
++# CONFIG_CRYPTO_FCRYPT is not set
++# CONFIG_CRYPTO_KHAZAD is not set
++# CONFIG_CRYPTO_SALSA20 is not set
++# CONFIG_CRYPTO_SEED is not set
++# CONFIG_CRYPTO_SERPENT is not set
++# CONFIG_CRYPTO_TEA is not set
++# CONFIG_CRYPTO_TWOFISH is not set
++
++#
++# Compression
++#
++CONFIG_CRYPTO_DEFLATE=m
++# CONFIG_CRYPTO_LZO is not set
++
++#
++# Random Number Generation
++#
++# CONFIG_CRYPTO_ANSI_CPRNG is not set
++# CONFIG_CRYPTO_HW is not set
++
++#
++# Library routines
++#
++CONFIG_BITREVERSE=y
++# CONFIG_CRC_CCITT is not set
++# CONFIG_CRC16 is not set
++# CONFIG_CRC_T10DIF is not set
++CONFIG_CRC_ITU_T=m
++CONFIG_CRC32=y
++# CONFIG_CRC7 is not set
++# CONFIG_LIBCRC32C is not set
++CONFIG_ZLIB_INFLATE=m
++CONFIG_ZLIB_DEFLATE=m
++CONFIG_PLIST=y
++CONFIG_HAS_IOMEM=y
++CONFIG_HAS_IOPORT=y
++CONFIG_HAS_DMA=y
+diff --git a/arch/arm/configs/ast2400_fb_defconfig b/arch/arm/configs/ast2400_fb_defconfig
+new file mode 100644
+index 0000000..71a1239
+--- /dev/null
++++ b/arch/arm/configs/ast2400_fb_defconfig
+@@ -0,0 +1,1516 @@
++#
++# Automatically generated make config: don't edit
++# Linux kernel version: 2.6.28.9
++# Thu Jan 10 10:40:53 2013
++#
++CONFIG_ARM=y
++CONFIG_SYS_SUPPORTS_APM_EMULATION=y
++CONFIG_GENERIC_GPIO=y
++# CONFIG_GENERIC_TIME is not set
++# CONFIG_GENERIC_CLOCKEVENTS is not set
++CONFIG_MMU=y
++# CONFIG_NO_IOPORT is not set
++CONFIG_GENERIC_HARDIRQS=y
++CONFIG_STACKTRACE_SUPPORT=y
++CONFIG_HAVE_LATENCYTOP_SUPPORT=y
++CONFIG_LOCKDEP_SUPPORT=y
++CONFIG_TRACE_IRQFLAGS_SUPPORT=y
++CONFIG_HARDIRQS_SW_RESEND=y
++CONFIG_GENERIC_IRQ_PROBE=y
++CONFIG_RWSEM_GENERIC_SPINLOCK=y
++# CONFIG_ARCH_HAS_ILOG2_U32 is not set
++# CONFIG_ARCH_HAS_ILOG2_U64 is not set
++CONFIG_GENERIC_HWEIGHT=y
++CONFIG_GENERIC_CALIBRATE_DELAY=y
++CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
++CONFIG_VECTORS_BASE=0xffff0000
++CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
++
++#
++# General setup
++#
++CONFIG_EXPERIMENTAL=y
++CONFIG_BROKEN_ON_SMP=y
++CONFIG_INIT_ENV_ARG_LIMIT=32
++CONFIG_LOCALVERSION=""
++# CONFIG_LOCALVERSION_AUTO is not set
++CONFIG_SWAP=y
++CONFIG_SYSVIPC=y
++CONFIG_SYSVIPC_SYSCTL=y
++# CONFIG_POSIX_MQUEUE is not set
++# CONFIG_BSD_PROCESS_ACCT is not set
++# CONFIG_TASKSTATS is not set
++# CONFIG_AUDIT is not set
++# CONFIG_IKCONFIG is not set
++CONFIG_LOG_BUF_SHIFT=16
++# CONFIG_CGROUPS is not set
++# CONFIG_GROUP_SCHED is not set
++CONFIG_SYSFS_DEPRECATED=y
++CONFIG_SYSFS_DEPRECATED_V2=y
++# CONFIG_RELAY is not set
++CONFIG_NAMESPACES=y
++# CONFIG_UTS_NS is not set
++# CONFIG_IPC_NS is not set
++# CONFIG_USER_NS is not set
++# CONFIG_PID_NS is not set
++CONFIG_BLK_DEV_INITRD=y
++CONFIG_INITRAMFS_SOURCE=""
++CONFIG_CC_OPTIMIZE_FOR_SIZE=y
++CONFIG_SYSCTL=y
++CONFIG_ANON_INODES=y
++# CONFIG_EMBEDDED is not set
++CONFIG_UID16=y
++CONFIG_SYSCTL_SYSCALL=y
++CONFIG_KALLSYMS=y
++CONFIG_KALLSYMS_EXTRA_PASS=y
++CONFIG_HOTPLUG=y
++CONFIG_PRINTK=y
++CONFIG_BUG=y
++CONFIG_ELF_CORE=y
++CONFIG_BASE_FULL=y
++CONFIG_FUTEX=y
++CONFIG_EPOLL=y
++CONFIG_SIGNALFD=y
++CONFIG_TIMERFD=y
++CONFIG_EVENTFD=y
++CONFIG_SHMEM=y
++CONFIG_AIO=y
++CONFIG_VM_EVENT_COUNTERS=y
++CONFIG_SLUB_DEBUG=y
++CONFIG_COMPAT_BRK=y
++# CONFIG_SLAB is not set
++CONFIG_SLUB=y
++# CONFIG_SLOB is not set
++# CONFIG_PROFILING is not set
++# CONFIG_MARKERS is not set
++CONFIG_HAVE_OPROFILE=y
++# CONFIG_KPROBES is not set
++CONFIG_HAVE_KPROBES=y
++CONFIG_HAVE_KRETPROBES=y
++CONFIG_HAVE_GENERIC_DMA_COHERENT=y
++CONFIG_SLABINFO=y
++CONFIG_RT_MUTEXES=y
++# CONFIG_TINY_SHMEM is not set
++CONFIG_BASE_SMALL=0
++CONFIG_MODULES=y
++# CONFIG_MODULE_FORCE_LOAD is not set
++CONFIG_MODULE_UNLOAD=y
++# CONFIG_MODULE_FORCE_UNLOAD is not set
++# CONFIG_MODVERSIONS is not set
++# CONFIG_MODULE_SRCVERSION_ALL is not set
++CONFIG_KMOD=y
++CONFIG_BLOCK=y
++# CONFIG_LBD is not set
++# CONFIG_BLK_DEV_IO_TRACE is not set
++# CONFIG_LSF is not set
++# CONFIG_BLK_DEV_BSG is not set
++# CONFIG_BLK_DEV_INTEGRITY is not set
++
++#
++# IO Schedulers
++#
++CONFIG_IOSCHED_NOOP=y
++CONFIG_IOSCHED_AS=y
++CONFIG_IOSCHED_DEADLINE=y
++CONFIG_IOSCHED_CFQ=y
++# CONFIG_DEFAULT_AS is not set
++# CONFIG_DEFAULT_DEADLINE is not set
++CONFIG_DEFAULT_CFQ=y
++# CONFIG_DEFAULT_NOOP is not set
++CONFIG_DEFAULT_IOSCHED="cfq"
++CONFIG_CLASSIC_RCU=y
++CONFIG_FREEZER=y
++
++#
++# System Type
++#
++CONFIG_ARCH_ASPEED=y
++# CONFIG_ARCH_AAEC2000 is not set
++# CONFIG_ARCH_INTEGRATOR is not set
++# CONFIG_ARCH_REALVIEW is not set
++# CONFIG_ARCH_VERSATILE is not set
++# CONFIG_ARCH_AT91 is not set
++# CONFIG_ARCH_CLPS7500 is not set
++# CONFIG_ARCH_CLPS711X is not set
++# CONFIG_ARCH_EBSA110 is not set
++# CONFIG_ARCH_EP93XX is not set
++# CONFIG_ARCH_FOOTBRIDGE is not set
++# CONFIG_ARCH_NETX is not set
++# CONFIG_ARCH_H720X is not set
++# CONFIG_ARCH_IMX is not set
++# CONFIG_ARCH_IOP13XX is not set
++# CONFIG_ARCH_IOP32X is not set
++# CONFIG_ARCH_IOP33X is not set
++# CONFIG_ARCH_IXP23XX is not set
++# CONFIG_ARCH_IXP2000 is not set
++# CONFIG_ARCH_IXP4XX is not set
++# CONFIG_ARCH_L7200 is not set
++# CONFIG_ARCH_KIRKWOOD is not set
++# CONFIG_ARCH_KS8695 is not set
++# CONFIG_ARCH_NS9XXX is not set
++# CONFIG_ARCH_LOKI is not set
++# CONFIG_ARCH_MV78XX0 is not set
++# CONFIG_ARCH_MXC is not set
++# CONFIG_ARCH_ORION5X is not set
++# CONFIG_ARCH_PNX4008 is not set
++# CONFIG_ARCH_PXA is not set
++# CONFIG_ARCH_RPC is not set
++# CONFIG_ARCH_SA1100 is not set
++# CONFIG_ARCH_S3C2410 is not set
++# CONFIG_ARCH_SHARK is not set
++# CONFIG_ARCH_LH7A40X is not set
++# CONFIG_ARCH_DAVINCI is not set
++# CONFIG_ARCH_OMAP is not set
++# CONFIG_ARCH_MSM is not set
++CONFIG_IRMP=y
++# CONFIG_PCEXT is not set
++# CONFIG_REMOTEFX is not set
++# CONFIG_ARCH_AST1100 is not set
++# CONFIG_ARCH_AST2100 is not set
++# CONFIG_ARCH_AST2200 is not set
++# CONFIG_ARCH_AST2300 is not set
++CONFIG_ARCH_AST2400=y
++
++#
++# FLASH Chip Select
++#
++# CONFIG_ASPEED_CS0_NOR is not set
++# CONFIG_ASPEED_CS0_NAND is not set
++CONFIG_ASPEED_CS0_SPI=y
++# CONFIG_ASPEED_CS0_NONE is not set
++# CONFIG_ASPEED_CS1_NOR is not set
++# CONFIG_ASPEED_CS1_NAND is not set
++# CONFIG_ASPEED_CS1_SPI is not set
++CONFIG_ASPEED_CS1_NONE=y
++# CONFIG_ASPEED_CS2_NOR is not set
++# CONFIG_ASPEED_CS2_NAND is not set
++# CONFIG_ASPEED_CS2_SPI is not set
++CONFIG_ASPEED_CS2_NONE=y
++# CONFIG_ASPEED_CS3_NOR is not set
++# CONFIG_ASPEED_CS3_NAND is not set
++# CONFIG_ASPEED_CS3_SPI is not set
++CONFIG_ASPEED_CS3_NONE=y
++# CONFIG_ASPEED_CS4_NOR is not set
++CONFIG_ASPEED_CS4_NAND=y
++# CONFIG_ASPEED_CS4_SPI is not set
++# CONFIG_ASPEED_CS4_NONE is not set
++# CONFIG_ARCH_AST1070 is not set
++# CONFIG_ASPEED_SCU_LOCK is not set
++
++#
++# Boot options
++#
++
++#
++# Power management
++#
++CONFIG_PLAT_ASPEED=y
++
++#
++# Processor Type
++#
++CONFIG_CPU_32=y
++CONFIG_CPU_ARM926T=y
++CONFIG_CPU_32v5=y
++CONFIG_CPU_ABRT_EV5TJ=y
++CONFIG_CPU_PABRT_NOIFAR=y
++CONFIG_CPU_CACHE_VIVT=y
++CONFIG_CPU_COPY_V4WB=y
++CONFIG_CPU_TLB_V4WBI=y
++CONFIG_CPU_CP15=y
++CONFIG_CPU_CP15_MMU=y
++
++#
++# Processor Features
++#
++CONFIG_ARM_THUMB=y
++# CONFIG_CPU_ICACHE_DISABLE is not set
++# CONFIG_CPU_DCACHE_DISABLE is not set
++# CONFIG_CPU_DCACHE_WRITETHROUGH is not set
++# CONFIG_CPU_CACHE_ROUND_ROBIN is not set
++# CONFIG_OUTER_CACHE is not set
++
++#
++# Bus support
++#
++CONFIG_ARM_AMBA=y
++# CONFIG_PCI_SYSCALL is not set
++# CONFIG_ARCH_SUPPORTS_MSI is not set
++# CONFIG_PCCARD is not set
++
++#
++# Kernel Features
++#
++CONFIG_VMSPLIT_3G=y
++# CONFIG_VMSPLIT_2G is not set
++# CONFIG_VMSPLIT_1G is not set
++CONFIG_PAGE_OFFSET=0xC0000000
++# CONFIG_PREEMPT is not set
++CONFIG_HZ=100
++# CONFIG_AEABI is not set
++CONFIG_ARCH_FLATMEM_HAS_HOLES=y
++# CONFIG_ARCH_SPARSEMEM_DEFAULT is not set
++# CONFIG_ARCH_SELECT_MEMORY_MODEL is not set
++CONFIG_SELECT_MEMORY_MODEL=y
++CONFIG_FLATMEM_MANUAL=y
++# CONFIG_DISCONTIGMEM_MANUAL is not set
++# CONFIG_SPARSEMEM_MANUAL is not set
++CONFIG_FLATMEM=y
++CONFIG_FLAT_NODE_MEM_MAP=y
++CONFIG_PAGEFLAGS_EXTENDED=y
++CONFIG_SPLIT_PTLOCK_CPUS=4096
++# CONFIG_RESOURCES_64BIT is not set
++# CONFIG_PHYS_ADDR_T_64BIT is not set
++CONFIG_ZONE_DMA_FLAG=0
++CONFIG_VIRT_TO_BUS=y
++CONFIG_UNEVICTABLE_LRU=y
++CONFIG_ALIGNMENT_TRAP=y
++
++#
++# Boot options
++#
++CONFIG_ZBOOT_ROM_TEXT=0
++CONFIG_ZBOOT_ROM_BSS=0
++CONFIG_CMDLINE=""
++# CONFIG_XIP_KERNEL is not set
++# CONFIG_KEXEC is not set
++
++#
++# CPU Power Management
++#
++# CONFIG_CPU_IDLE is not set
++
++#
++# Floating point emulation
++#
++
++#
++# At least one emulation must be selected
++#
++CONFIG_FPE_NWFPE=y
++CONFIG_FPE_NWFPE_XP=y
++# CONFIG_FPE_FASTFPE is not set
++# CONFIG_VFP is not set
++
++#
++# Userspace binary formats
++#
++CONFIG_BINFMT_ELF=y
++# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
++CONFIG_HAVE_AOUT=y
++CONFIG_BINFMT_AOUT=y
++# CONFIG_BINFMT_MISC is not set
++# CONFIG_ARTHUR is not set
++
++#
++# Power management options
++#
++CONFIG_PM=y
++# CONFIG_PM_DEBUG is not set
++CONFIG_PM_SLEEP=y
++CONFIG_SUSPEND=y
++CONFIG_SUSPEND_FREEZER=y
++# CONFIG_APM_EMULATION is not set
++CONFIG_ARCH_SUSPEND_POSSIBLE=y
++CONFIG_NET=y
++
++#
++# Networking options
++#
++CONFIG_PACKET=y
++# CONFIG_PACKET_MMAP is not set
++CONFIG_UNIX=y
++CONFIG_XFRM=y
++# CONFIG_XFRM_USER is not set
++# CONFIG_XFRM_SUB_POLICY is not set
++# CONFIG_XFRM_MIGRATE is not set
++# CONFIG_XFRM_STATISTICS is not set
++CONFIG_XFRM_IPCOMP=m
++# CONFIG_NET_KEY is not set
++CONFIG_INET=y
++CONFIG_IP_MULTICAST=y
++# CONFIG_IP_ADVANCED_ROUTER is not set
++CONFIG_IP_FIB_HASH=y
++CONFIG_IP_PNP=y
++CONFIG_IP_PNP_DHCP=y
++CONFIG_IP_PNP_BOOTP=y
++# CONFIG_IP_PNP_RARP is not set
++# CONFIG_NET_IPIP is not set
++# CONFIG_NET_IPGRE is not set
++# CONFIG_IP_MROUTE is not set
++# CONFIG_ARPD is not set
++# CONFIG_SYN_COOKIES is not set
++# CONFIG_INET_AH is not set
++# CONFIG_INET_ESP is not set
++# CONFIG_INET_IPCOMP is not set
++# CONFIG_INET_XFRM_TUNNEL is not set
++CONFIG_INET_TUNNEL=m
++CONFIG_INET_XFRM_MODE_TRANSPORT=y
++CONFIG_INET_XFRM_MODE_TUNNEL=y
++CONFIG_INET_XFRM_MODE_BEET=y
++# CONFIG_INET_LRO is not set
++CONFIG_INET_DIAG=y
++CONFIG_INET_TCP_DIAG=y
++# CONFIG_TCP_CONG_ADVANCED is not set
++CONFIG_TCP_CONG_CUBIC=y
++CONFIG_DEFAULT_TCP_CONG="cubic"
++# CONFIG_TCP_MD5SIG is not set
++CONFIG_IPV6=m
++CONFIG_IPV6_PRIVACY=y
++CONFIG_IPV6_ROUTER_PREF=y
++CONFIG_IPV6_ROUTE_INFO=y
++CONFIG_IPV6_OPTIMISTIC_DAD=y
++CONFIG_INET6_AH=m
++CONFIG_INET6_ESP=m
++CONFIG_INET6_IPCOMP=m
++CONFIG_IPV6_MIP6=m
++CONFIG_INET6_XFRM_TUNNEL=m
++CONFIG_INET6_TUNNEL=m
++CONFIG_INET6_XFRM_MODE_TRANSPORT=m
++CONFIG_INET6_XFRM_MODE_TUNNEL=m
++CONFIG_INET6_XFRM_MODE_BEET=m
++CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION=m
++CONFIG_IPV6_SIT=m
++CONFIG_IPV6_NDISC_NODETYPE=y
++CONFIG_IPV6_TUNNEL=m
++CONFIG_IPV6_MULTIPLE_TABLES=y
++CONFIG_IPV6_SUBTREES=y
++# CONFIG_IPV6_MROUTE is not set
++# CONFIG_NETWORK_SECMARK is not set
++# CONFIG_NETFILTER is not set
++# CONFIG_IP_DCCP is not set
++# CONFIG_IP_SCTP is not set
++# CONFIG_TIPC is not set
++# CONFIG_ATM is not set
++# CONFIG_BRIDGE is not set
++# CONFIG_NET_DSA is not set
++# CONFIG_VLAN_8021Q is not set
++# CONFIG_DECNET is not set
++# CONFIG_LLC2 is not set
++# CONFIG_IPX is not set
++# CONFIG_ATALK is not set
++# CONFIG_X25 is not set
++# CONFIG_LAPB is not set
++# CONFIG_ECONET is not set
++CONFIG_WAN_ROUTER=y
++# CONFIG_NET_SCHED is not set
++
++#
++# Network testing
++#
++# CONFIG_NET_PKTGEN is not set
++# CONFIG_HAMRADIO is not set
++# CONFIG_CAN is not set
++# CONFIG_IRDA is not set
++# CONFIG_BT is not set
++# CONFIG_AF_RXRPC is not set
++# CONFIG_PHONET is not set
++CONFIG_FIB_RULES=y
++# CONFIG_WIRELESS is not set
++# CONFIG_RFKILL is not set
++# CONFIG_NET_9P is not set
++
++#
++# Device Drivers
++#
++
++#
++# Generic Driver Options
++#
++CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
++CONFIG_STANDALONE=y
++CONFIG_PREVENT_FIRMWARE_BUILD=y
++CONFIG_FW_LOADER=y
++CONFIG_FIRMWARE_IN_KERNEL=y
++CONFIG_EXTRA_FIRMWARE=""
++# CONFIG_SYS_HYPERVISOR is not set
++CONFIG_CONNECTOR=y
++CONFIG_PROC_EVENTS=y
++CONFIG_MTD=y
++# CONFIG_MTD_DEBUG is not set
++CONFIG_MTD_CONCAT=y
++CONFIG_MTD_PARTITIONS=y
++# CONFIG_MTD_REDBOOT_PARTS is not set
++# CONFIG_MTD_CMDLINE_PARTS is not set
++# CONFIG_MTD_AFS_PARTS is not set
++# CONFIG_MTD_AR7_PARTS is not set
++
++#
++# User Modules And Translation Layers
++#
++CONFIG_MTD_CHAR=y
++CONFIG_MTD_BLKDEVS=y
++CONFIG_MTD_BLOCK=y
++# CONFIG_FTL is not set
++# CONFIG_NFTL is not set
++# CONFIG_INFTL is not set
++# CONFIG_RFD_FTL is not set
++# CONFIG_SSFDC is not set
++# CONFIG_MTD_OOPS is not set
++
++#
++# RAM/ROM/Flash chip drivers
++#
++# CONFIG_MTD_CFI is not set
++# CONFIG_MTD_JEDECPROBE is not set
++CONFIG_MTD_MAP_BANK_WIDTH_1=y
++CONFIG_MTD_MAP_BANK_WIDTH_2=y
++CONFIG_MTD_MAP_BANK_WIDTH_4=y
++# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
++# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
++# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
++CONFIG_MTD_CFI_I1=y
++CONFIG_MTD_CFI_I2=y
++# CONFIG_MTD_CFI_I4 is not set
++# CONFIG_MTD_CFI_I8 is not set
++# CONFIG_MTD_RAM is not set
++# CONFIG_MTD_ROM is not set
++# CONFIG_MTD_ABSENT is not set
++
++#
++# Mapping drivers for chip access
++#
++# CONFIG_MTD_COMPLEX_MAPPINGS is not set
++# CONFIG_MTD_PLATRAM is not set
++
++#
++# Self-contained MTD device drivers
++#
++CONFIG_MTD_DATAFLASH=y
++# CONFIG_MTD_DATAFLASH_WRITE_VERIFY is not set
++# CONFIG_MTD_DATAFLASH_OTP is not set
++CONFIG_MTD_M25P80=y
++CONFIG_M25PXX_USE_FAST_READ=y
++# CONFIG_MTD_SLRAM is not set
++# CONFIG_MTD_PHRAM is not set
++# CONFIG_MTD_MTDRAM is not set
++# CONFIG_MTD_BLOCK2MTD is not set
++
++#
++# Disk-On-Chip Device Drivers
++#
++# CONFIG_MTD_DOC2000 is not set
++# CONFIG_MTD_DOC2001 is not set
++# CONFIG_MTD_DOC2001PLUS is not set
++CONFIG_MTD_NAND=y
++# CONFIG_MTD_NAND_VERIFY_WRITE is not set
++# CONFIG_MTD_NAND_ECC_SMC is not set
++# CONFIG_MTD_NAND_MUSEUM_IDS is not set
++CONFIG_MTD_NAND_AST=y
++# CONFIG_MTD_NAND_GPIO is not set
++CONFIG_MTD_NAND_IDS=y
++# CONFIG_MTD_NAND_DISKONCHIP is not set
++# CONFIG_MTD_NAND_NANDSIM is not set
++# CONFIG_MTD_NAND_PLATFORM is not set
++# CONFIG_MTD_ALAUDA is not set
++# CONFIG_MTD_ONENAND is not set
++
++#
++# UBI - Unsorted block images
++#
++# CONFIG_MTD_UBI is not set
++# CONFIG_PARPORT is not set
++CONFIG_BLK_DEV=y
++# CONFIG_BLK_DEV_COW_COMMON is not set
++CONFIG_BLK_DEV_LOOP=y
++# CONFIG_BLK_DEV_CRYPTOLOOP is not set
++CONFIG_BLK_DEV_NBD=m
++# CONFIG_BLK_DEV_UB is not set
++CONFIG_BLK_DEV_RAM=y
++CONFIG_BLK_DEV_RAM_COUNT=16
++CONFIG_BLK_DEV_RAM_SIZE=16384
++# CONFIG_BLK_DEV_XIP is not set
++# CONFIG_CDROM_PKTCDVD is not set
++# CONFIG_ATA_OVER_ETH is not set
++CONFIG_MISC_DEVICES=y
++# CONFIG_EEPROM_93CX6 is not set
++# CONFIG_ICS932S401 is not set
++# CONFIG_ENCLOSURE_SERVICES is not set
++# CONFIG_C2PORT is not set
++CONFIG_HAVE_IDE=y
++# CONFIG_IDE is not set
++
++#
++# SCSI device support
++#
++# CONFIG_RAID_ATTRS is not set
++CONFIG_SCSI=y
++CONFIG_SCSI_DMA=y
++CONFIG_SCSI_TGT=y
++# CONFIG_SCSI_NETLINK is not set
++CONFIG_SCSI_PROC_FS=y
++
++#
++# SCSI support type (disk, tape, CD-ROM)
++#
++CONFIG_BLK_DEV_SD=y
++# CONFIG_CHR_DEV_ST is not set
++# CONFIG_CHR_DEV_OSST is not set
++# CONFIG_BLK_DEV_SR is not set
++CONFIG_CHR_DEV_SG=y
++# CONFIG_CHR_DEV_SCH is not set
++
++#
++# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
++#
++# CONFIG_SCSI_MULTI_LUN is not set
++# CONFIG_SCSI_CONSTANTS is not set
++# CONFIG_SCSI_LOGGING is not set
++CONFIG_SCSI_SCAN_ASYNC=y
++CONFIG_SCSI_WAIT_SCAN=m
++
++#
++# SCSI Transports
++#
++# CONFIG_SCSI_SPI_ATTRS is not set
++# CONFIG_SCSI_FC_ATTRS is not set
++CONFIG_SCSI_ISCSI_ATTRS=m
++# CONFIG_SCSI_SAS_LIBSAS is not set
++# CONFIG_SCSI_SRP_ATTRS is not set
++# CONFIG_SCSI_LOWLEVEL is not set
++# CONFIG_SCSI_DH is not set
++# CONFIG_ATA is not set
++# CONFIG_MD is not set
++CONFIG_NETDEVICES=y
++# CONFIG_DUMMY is not set
++CONFIG_BONDING=y
++# CONFIG_MACVLAN is not set
++# CONFIG_EQUALIZER is not set
++# CONFIG_TUN is not set
++# CONFIG_VETH is not set
++# CONFIG_NET_ETHERNET is not set
++CONFIG_NETDEV_1000=y
++CONFIG_ASPEEDMAC=y
++CONFIG_MAC0_PHY_LINK=y
++# CONFIG_NETDEV_10000 is not set
++
++#
++# Wireless LAN
++#
++# CONFIG_WLAN_PRE80211 is not set
++# CONFIG_WLAN_80211 is not set
++# CONFIG_IWLWIFI_LEDS is not set
++
++#
++# USB Network Adapters
++#
++# CONFIG_USB_CATC is not set
++# CONFIG_USB_KAWETH is not set
++# CONFIG_USB_PEGASUS is not set
++# CONFIG_USB_RTL8150 is not set
++# CONFIG_USB_USBNET is not set
++# CONFIG_WAN is not set
++# CONFIG_PPP is not set
++# CONFIG_SLIP is not set
++# CONFIG_NETCONSOLE is not set
++# CONFIG_NETPOLL is not set
++# CONFIG_NET_POLL_CONTROLLER is not set
++# CONFIG_ISDN is not set
++
++#
++# Input device support
++#
++CONFIG_INPUT=y
++# CONFIG_INPUT_FF_MEMLESS is not set
++# CONFIG_INPUT_POLLDEV is not set
++
++#
++# Userland interfaces
++#
++CONFIG_INPUT_MOUSEDEV=y
++CONFIG_INPUT_MOUSEDEV_PSAUX=y
++CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
++CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
++# CONFIG_INPUT_JOYDEV is not set
++CONFIG_INPUT_EVDEV=y
++# CONFIG_INPUT_EVBUG is not set
++
++#
++# Input Device Drivers
++#
++CONFIG_INPUT_KEYBOARD=y
++CONFIG_KEYBOARD_ATKBD=y
++# CONFIG_KEYBOARD_SUNKBD is not set
++# CONFIG_KEYBOARD_LKKBD is not set
++# CONFIG_KEYBOARD_XTKBD is not set
++# CONFIG_KEYBOARD_NEWTON is not set
++# CONFIG_KEYBOARD_STOWAWAY is not set
++# CONFIG_KEYBOARD_GPIO is not set
++CONFIG_INPUT_MOUSE=y
++CONFIG_MOUSE_PS2=y
++CONFIG_MOUSE_PS2_ALPS=y
++CONFIG_MOUSE_PS2_LOGIPS2PP=y
++CONFIG_MOUSE_PS2_SYNAPTICS=y
++CONFIG_MOUSE_PS2_LIFEBOOK=y
++CONFIG_MOUSE_PS2_TRACKPOINT=y
++# CONFIG_MOUSE_PS2_ELANTECH is not set
++# CONFIG_MOUSE_PS2_TOUCHKIT is not set
++CONFIG_MOUSE_SERIAL=y
++# CONFIG_MOUSE_APPLETOUCH is not set
++# CONFIG_MOUSE_BCM5974 is not set
++# CONFIG_MOUSE_VSXXXAA is not set
++# CONFIG_MOUSE_GPIO is not set
++# CONFIG_INPUT_JOYSTICK is not set
++# CONFIG_INPUT_TABLET is not set
++# CONFIG_INPUT_TOUCHSCREEN is not set
++# CONFIG_INPUT_MISC is not set
++
++#
++# Hardware I/O ports
++#
++CONFIG_SERIO=y
++CONFIG_SERIO_SERPORT=y
++# CONFIG_SERIO_AMBAKMI is not set
++CONFIG_SERIO_LIBPS2=y
++# CONFIG_SERIO_RAW is not set
++# CONFIG_GAMEPORT is not set
++
++#
++# Character devices
++#
++CONFIG_VT=y
++CONFIG_CONSOLE_TRANSLATIONS=y
++CONFIG_VT_CONSOLE=y
++CONFIG_HW_CONSOLE=y
++# CONFIG_VT_HW_CONSOLE_BINDING is not set
++CONFIG_DEVKMEM=y
++CONFIG_SERIAL_NONSTANDARD=y
++# CONFIG_N_HDLC is not set
++# CONFIG_RISCOM8 is not set
++# CONFIG_SPECIALIX is not set
++# CONFIG_RIO is not set
++# CONFIG_STALDRV is not set
++
++#
++# Serial drivers
++#
++CONFIG_SERIAL_8250=y
++CONFIG_SERIAL_8250_CONSOLE=y
++CONFIG_SERIAL_8250_NR_UARTS=3
++CONFIG_SERIAL_8250_RUNTIME_UARTS=3
++# CONFIG_SERIAL_8250_EXTENDED is not set
++
++#
++# Non-8250 serial port support
++#
++# CONFIG_SERIAL_AMBA_PL010 is not set
++# CONFIG_SERIAL_AMBA_PL011 is not set
++# CONFIG_SERIAL_ASPEED is not set
++CONFIG_SERIAL_CORE=y
++CONFIG_SERIAL_CORE_CONSOLE=y
++CONFIG_UNIX98_PTYS=y
++CONFIG_LEGACY_PTYS=y
++CONFIG_LEGACY_PTY_COUNT=256
++# CONFIG_IPMI_HANDLER is not set
++# CONFIG_HW_RANDOM is not set
++CONFIG_NVRAM=y
++# CONFIG_R3964 is not set
++# CONFIG_RAW_DRIVER is not set
++# CONFIG_TCG_TPM is not set
++CONFIG_I2C=y
++CONFIG_I2C_BOARDINFO=y
++CONFIG_I2C_CHARDEV=y
++CONFIG_I2C_HELPER_AUTO=y
++
++#
++# I2C Hardware Bus support
++#
++
++#
++# I2C system bus drivers (mostly embedded / system-on-chip)
++#
++# CONFIG_I2C_GPIO is not set
++# CONFIG_I2C_OCORES is not set
++CONFIG_I2C_ASPEED=y
++CONFIG_AST_I2C_SLAVE_MODE=y
++# CONFIG_I2C_SIMTEC is not set
++
++#
++# External I2C/SMBus adapter drivers
++#
++# CONFIG_I2C_PARPORT_LIGHT is not set
++# CONFIG_I2C_TAOS_EVM is not set
++# CONFIG_I2C_TINY_USB is not set
++
++#
++# Other I2C/SMBus bus drivers
++#
++# CONFIG_I2C_PCA_PLATFORM is not set
++# CONFIG_I2C_STUB is not set
++
++#
++# Miscellaneous I2C Chip support
++#
++# CONFIG_DS1682 is not set
++CONFIG_AT24=y
++# CONFIG_SENSORS_EEPROM is not set
++# CONFIG_SENSORS_PCF8574 is not set
++# CONFIG_PCF8575 is not set
++# CONFIG_SENSORS_PCA9539 is not set
++# CONFIG_SENSORS_PCF8591 is not set
++# CONFIG_TPS65010 is not set
++# CONFIG_SENSORS_MAX6875 is not set
++# CONFIG_SENSORS_TSL2550 is not set
++# CONFIG_I2C_DEBUG_CORE is not set
++# CONFIG_I2C_DEBUG_ALGO is not set
++# CONFIG_I2C_DEBUG_BUS is not set
++# CONFIG_I2C_DEBUG_CHIP is not set
++CONFIG_SPI=y
++CONFIG_SPI_MASTER=y
++
++#
++# SPI Master Controller Drivers
++#
++# CONFIG_SPI_AST is not set
++CONFIG_SPI_FMC=y
++CONFIG_SPI_BITBANG=y
++
++#
++# SPI Protocol Masters
++#
++# CONFIG_SPI_AT25 is not set
++# CONFIG_SPI_SPIDEV is not set
++# CONFIG_SPI_TLE62X0 is not set
++CONFIG_ARCH_REQUIRE_GPIOLIB=y
++CONFIG_GPIOLIB=y
++CONFIG_GPIO_SYSFS=y
++
++#
++# Memory mapped GPIO expanders:
++#
++
++#
++# I2C GPIO expanders:
++#
++# CONFIG_GPIO_MAX732X is not set
++# CONFIG_GPIO_PCA953X is not set
++# CONFIG_GPIO_PCF857X is not set
++
++#
++# PCI GPIO expanders:
++#
++
++#
++# SPI GPIO expanders:
++#
++# CONFIG_GPIO_MAX7301 is not set
++# CONFIG_GPIO_MCP23S08 is not set
++# CONFIG_W1 is not set
++# CONFIG_POWER_SUPPLY is not set
++CONFIG_HWMON=y
++# CONFIG_HWMON_VID is not set
++# CONFIG_SENSORS_AD7414 is not set
++# CONFIG_SENSORS_AD7418 is not set
++# CONFIG_SENSORS_ADCXX is not set
++# CONFIG_SENSORS_ADM1021 is not set
++# CONFIG_SENSORS_ADM1025 is not set
++# CONFIG_SENSORS_ADM1026 is not set
++# CONFIG_SENSORS_ADM1029 is not set
++# CONFIG_SENSORS_ADM1031 is not set
++# CONFIG_SENSORS_ADM9240 is not set
++# CONFIG_SENSORS_ADT7462 is not set
++# CONFIG_SENSORS_ADT7470 is not set
++# CONFIG_SENSORS_ADT7473 is not set
++# CONFIG_SENSORS_ATXP1 is not set
++# CONFIG_SENSORS_DS1621 is not set
++# CONFIG_SENSORS_F71805F is not set
++# CONFIG_SENSORS_F71882FG is not set
++# CONFIG_SENSORS_F75375S is not set
++# CONFIG_SENSORS_GL518SM is not set
++# CONFIG_SENSORS_GL520SM is not set
++# CONFIG_SENSORS_IT87 is not set
++# CONFIG_SENSORS_LM63 is not set
++# CONFIG_SENSORS_LM70 is not set
++# CONFIG_SENSORS_LM75 is not set
++# CONFIG_SENSORS_LM77 is not set
++# CONFIG_SENSORS_LM78 is not set
++# CONFIG_SENSORS_LM80 is not set
++# CONFIG_SENSORS_LM83 is not set
++# CONFIG_SENSORS_LM85 is not set
++# CONFIG_SENSORS_LM87 is not set
++# CONFIG_SENSORS_LM90 is not set
++# CONFIG_SENSORS_LM92 is not set
++# CONFIG_SENSORS_LM93 is not set
++# CONFIG_SENSORS_MAX1111 is not set
++# CONFIG_SENSORS_MAX1619 is not set
++# CONFIG_SENSORS_MAX6650 is not set
++# CONFIG_SENSORS_PC87360 is not set
++# CONFIG_SENSORS_PC87427 is not set
++# CONFIG_SENSORS_DME1737 is not set
++# CONFIG_SENSORS_SMSC47M1 is not set
++# CONFIG_SENSORS_SMSC47M192 is not set
++# CONFIG_SENSORS_SMSC47B397 is not set
++# CONFIG_SENSORS_ADS7828 is not set
++# CONFIG_SENSORS_THMC50 is not set
++# CONFIG_SENSORS_VT1211 is not set
++# CONFIG_SENSORS_W83781D is not set
++# CONFIG_SENSORS_W83791D is not set
++# CONFIG_SENSORS_W83792D is not set
++# CONFIG_SENSORS_W83793 is not set
++# CONFIG_SENSORS_W83L785TS is not set
++# CONFIG_SENSORS_W83L786NG is not set
++# CONFIG_SENSORS_W83627HF is not set
++# CONFIG_SENSORS_W83627EHF is not set
++# CONFIG_SENSORS_AST_ADC is not set
++CONFIG_SENSORS_AST_PWM_FAN=y
++# CONFIG_SENSORS_AST_PECI is not set
++# CONFIG_HWMON_DEBUG_CHIP is not set
++# CONFIG_THERMAL is not set
++# CONFIG_THERMAL_HWMON is not set
++CONFIG_WATCHDOG=y
++# CONFIG_WATCHDOG_NOWAYOUT is not set
++
++#
++# Watchdog Device Drivers
++#
++# CONFIG_SOFT_WATCHDOG is not set
++CONFIG_ASPEED_WATCHDOG=y
++
++#
++# USB-based Watchdog Cards
++#
++# CONFIG_USBPCWATCHDOG is not set
++CONFIG_SSB_POSSIBLE=y
++
++#
++# Sonics Silicon Backplane
++#
++# CONFIG_SSB is not set
++
++#
++# Multifunction device drivers
++#
++# CONFIG_MFD_CORE is not set
++# CONFIG_MFD_SM501 is not set
++# CONFIG_MFD_ASIC3 is not set
++# CONFIG_HTC_EGPIO is not set
++# CONFIG_HTC_PASIC3 is not set
++# CONFIG_MFD_TMIO is not set
++# CONFIG_MFD_TC6393XB is not set
++# CONFIG_PMIC_DA903X is not set
++# CONFIG_MFD_WM8400 is not set
++# CONFIG_MFD_WM8350_I2C is not set
++
++#
++# Multimedia devices
++#
++
++#
++# Multimedia core support
++#
++# CONFIG_VIDEO_DEV is not set
++# CONFIG_DVB_CORE is not set
++# CONFIG_VIDEO_MEDIA is not set
++
++#
++# Multimedia drivers
++#
++# CONFIG_DAB is not set
++
++#
++# Graphics support
++#
++# CONFIG_VGASTATE is not set
++# CONFIG_VIDEO_OUTPUT_CONTROL is not set
++CONFIG_FB=y
++CONFIG_FIRMWARE_EDID=y
++# CONFIG_FB_DDC is not set
++# CONFIG_FB_BOOT_VESA_SUPPORT is not set
++CONFIG_FB_CFB_FILLRECT=y
++CONFIG_FB_CFB_COPYAREA=y
++CONFIG_FB_CFB_IMAGEBLIT=y
++# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set
++# CONFIG_FB_SYS_FILLRECT is not set
++# CONFIG_FB_SYS_COPYAREA is not set
++# CONFIG_FB_SYS_IMAGEBLIT is not set
++# CONFIG_FB_FOREIGN_ENDIAN is not set
++# CONFIG_FB_SYS_FOPS is not set
++# CONFIG_FB_SVGALIB is not set
++# CONFIG_FB_MACMODES is not set
++# CONFIG_FB_BACKLIGHT is not set
++CONFIG_FB_MODE_HELPERS=y
++CONFIG_FB_TILEBLITTING=y
++
++#
++# Frame buffer hardware drivers
++#
++# CONFIG_FB_ARMCLCD is not set
++CONFIG_FB_UVESA=y
++# CONFIG_FB_S1D13XXX is not set
++CONFIG_FB_AST=y
++CONFIG_AST_DAC=y
++# CONFIG_AST_DVO is not set
++# CONFIG_FB_VIRTUAL is not set
++# CONFIG_FB_METRONOME is not set
++# CONFIG_FB_MB862XX is not set
++# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
++
++#
++# Display device support
++#
++# CONFIG_DISPLAY_SUPPORT is not set
++
++#
++# Console display driver support
++#
++# CONFIG_VGA_CONSOLE is not set
++CONFIG_DUMMY_CONSOLE=y
++CONFIG_FRAMEBUFFER_CONSOLE=y
++# CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY is not set
++# CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set
++CONFIG_FONTS=y
++CONFIG_FONT_8x8=y
++CONFIG_FONT_8x16=y
++# CONFIG_FONT_6x11 is not set
++# CONFIG_FONT_7x14 is not set
++# CONFIG_FONT_PEARL_8x8 is not set
++# CONFIG_FONT_ACORN_8x8 is not set
++# CONFIG_FONT_MINI_4x6 is not set
++# CONFIG_FONT_SUN8x16 is not set
++# CONFIG_FONT_SUN12x22 is not set
++# CONFIG_FONT_10x18 is not set
++CONFIG_LOGO=y
++CONFIG_LOGO_LINUX_MONO=y
++CONFIG_LOGO_LINUX_VGA16=y
++CONFIG_LOGO_LINUX_CLUT224=y
++# CONFIG_SOUND is not set
++CONFIG_HID_SUPPORT=y
++CONFIG_HID=y
++CONFIG_HID_DEBUG=y
++# CONFIG_HIDRAW is not set
++
++#
++# USB Input Devices
++#
++CONFIG_USB_HID=y
++# CONFIG_HID_PID is not set
++# CONFIG_USB_HIDDEV is not set
++
++#
++# Special HID drivers
++#
++CONFIG_HID_COMPAT=y
++CONFIG_HID_A4TECH=y
++CONFIG_HID_APPLE=y
++CONFIG_HID_BELKIN=y
++CONFIG_HID_BRIGHT=y
++CONFIG_HID_CHERRY=y
++CONFIG_HID_CHICONY=y
++CONFIG_HID_CYPRESS=y
++CONFIG_HID_DELL=y
++CONFIG_HID_EZKEY=y
++CONFIG_HID_GYRATION=y
++CONFIG_HID_LOGITECH=y
++# CONFIG_LOGITECH_FF is not set
++# CONFIG_LOGIRUMBLEPAD2_FF is not set
++CONFIG_HID_MICROSOFT=y
++CONFIG_HID_MONTEREY=y
++CONFIG_HID_PANTHERLORD=y
++# CONFIG_PANTHERLORD_FF is not set
++CONFIG_HID_PETALYNX=y
++CONFIG_HID_SAMSUNG=y
++CONFIG_HID_SONY=y
++CONFIG_HID_SUNPLUS=y
++# CONFIG_THRUSTMASTER_FF is not set
++# CONFIG_ZEROPLUS_FF is not set
++CONFIG_USB_SUPPORT=y
++CONFIG_USB_ARCH_HAS_HCD=y
++# CONFIG_USB_ARCH_HAS_OHCI is not set
++CONFIG_USB_ARCH_HAS_EHCI=y
++CONFIG_USB=y
++# CONFIG_USB_DEBUG is not set
++# CONFIG_USB_ANNOUNCE_NEW_DEVICES is not set
++
++#
++# Miscellaneous USB options
++#
++CONFIG_USB_DEVICEFS=y
++CONFIG_USB_DEVICE_CLASS=y
++# CONFIG_USB_DYNAMIC_MINORS is not set
++# CONFIG_USB_SUSPEND is not set
++# CONFIG_USB_OTG is not set
++# CONFIG_USB_MON is not set
++# CONFIG_USB_WUSB is not set
++# CONFIG_USB_WUSB_CBAF is not set
++
++#
++# USB Host Controller Drivers
++#
++# CONFIG_USB_C67X00_HCD is not set
++CONFIG_USB_EHCI_HCD=y
++# CONFIG_USB_EHCI_ROOT_HUB_TT is not set
++CONFIG_USB_EHCI_TT_NEWSCHED=y
++CONFIG_USB_EHCI_AST=y
++# CONFIG_USB_ISP116X_HCD is not set
++# CONFIG_USB_SL811_HCD is not set
++# CONFIG_USB_R8A66597_HCD is not set
++# CONFIG_USB_HWA_HCD is not set
++
++#
++# AST USB Drivers
++#
++CONFIG_AST_USB_UHCI_HCD=y
++# CONFIG_AST_USB_UHCI_MULTIPORT_1 is not set
++# CONFIG_AST_USB_UHCI_MULTIPORT_2 is not set
++CONFIG_AST_USB_UHCI_MULTIPORT_4=y
++# CONFIG_USB_EHCI_SPLIT_ISO is not set
++
++#
++# USB Device Class drivers
++#
++# CONFIG_USB_ACM is not set
++# CONFIG_USB_PRINTER is not set
++# CONFIG_USB_WDM is not set
++# CONFIG_USB_TMC is not set
++
++#
++# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may also be needed;
++#
++
++#
++# see USB_STORAGE Help for more information
++#
++CONFIG_USB_STORAGE=y
++# CONFIG_USB_STORAGE_DEBUG is not set
++# CONFIG_USB_STORAGE_DATAFAB is not set
++# CONFIG_USB_STORAGE_FREECOM is not set
++# CONFIG_USB_STORAGE_ISD200 is not set
++# CONFIG_USB_STORAGE_DPCM is not set
++# CONFIG_USB_STORAGE_USBAT is not set
++# CONFIG_USB_STORAGE_SDDR09 is not set
++# CONFIG_USB_STORAGE_SDDR55 is not set
++# CONFIG_USB_STORAGE_JUMPSHOT is not set
++# CONFIG_USB_STORAGE_ALAUDA is not set
++# CONFIG_USB_STORAGE_ONETOUCH is not set
++# CONFIG_USB_STORAGE_KARMA is not set
++# CONFIG_USB_STORAGE_CYPRESS_ATACB is not set
++# CONFIG_USB_LIBUSUAL is not set
++
++#
++# USB Imaging devices
++#
++# CONFIG_USB_MDC800 is not set
++# CONFIG_USB_MICROTEK is not set
++
++#
++# USB port drivers
++#
++# CONFIG_USB_SERIAL is not set
++
++#
++# USB Miscellaneous drivers
++#
++# CONFIG_USB_EMI62 is not set
++# CONFIG_USB_EMI26 is not set
++# CONFIG_USB_ADUTUX is not set
++# CONFIG_USB_SEVSEG is not set
++# CONFIG_USB_RIO500 is not set
++# CONFIG_USB_LEGOTOWER is not set
++# CONFIG_USB_LCD is not set
++# CONFIG_USB_BERRY_CHARGE is not set
++# CONFIG_USB_LED is not set
++# CONFIG_USB_CYPRESS_CY7C63 is not set
++# CONFIG_USB_CYTHERM is not set
++# CONFIG_USB_PHIDGET is not set
++# CONFIG_USB_IDMOUSE is not set
++# CONFIG_USB_FTDI_ELAN is not set
++# CONFIG_USB_APPLEDISPLAY is not set
++# CONFIG_USB_SISUSBVGA is not set
++# CONFIG_USB_LD is not set
++# CONFIG_USB_TRANCEVIBRATOR is not set
++# CONFIG_USB_IOWARRIOR is not set
++# CONFIG_USB_TEST is not set
++# CONFIG_USB_ISIGHTFW is not set
++# CONFIG_USB_VST is not set
++# CONFIG_USB_GADGET is not set
++CONFIG_MMC=y
++# CONFIG_MMC_DEBUG is not set
++# CONFIG_MMC_UNSAFE_RESUME is not set
++
++#
++# MMC/SD/SDIO Card Drivers
++#
++CONFIG_MMC_BLOCK=y
++CONFIG_MMC_BLOCK_BOUNCE=y
++# CONFIG_SDIO_UART is not set
++# CONFIG_MMC_TEST is not set
++
++#
++# MMC/SD/SDIO Host Controller Drivers
++#
++# CONFIG_MMC_ARMMMCI is not set
++# CONFIG_MMC_SDHCI is not set
++CONFIG_MMC_ASPEED=y
++# CONFIG_MMC_SPI is not set
++# CONFIG_MEMSTICK is not set
++# CONFIG_ACCESSIBILITY is not set
++# CONFIG_NEW_LEDS is not set
++CONFIG_RTC_LIB=y
++CONFIG_RTC_CLASS=y
++# CONFIG_RTC_HCTOSYS is not set
++# CONFIG_RTC_DEBUG is not set
++
++#
++# RTC interfaces
++#
++CONFIG_RTC_INTF_SYSFS=y
++CONFIG_RTC_INTF_PROC=y
++CONFIG_RTC_INTF_DEV=y
++# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set
++# CONFIG_RTC_DRV_TEST is not set
++
++#
++# I2C RTC drivers
++#
++# CONFIG_RTC_DRV_DS1307 is not set
++# CONFIG_RTC_DRV_DS1374 is not set
++# CONFIG_RTC_DRV_DS1672 is not set
++# CONFIG_RTC_DRV_MAX6900 is not set
++# CONFIG_RTC_DRV_RS5C372 is not set
++# CONFIG_RTC_DRV_ISL1208 is not set
++# CONFIG_RTC_DRV_X1205 is not set
++# CONFIG_RTC_DRV_PCF8563 is not set
++# CONFIG_RTC_DRV_PCF8583 is not set
++# CONFIG_RTC_DRV_M41T80 is not set
++# CONFIG_RTC_DRV_S35390A is not set
++# CONFIG_RTC_DRV_FM3130 is not set
++# CONFIG_RTC_DRV_RX8581 is not set
++
++#
++# SPI RTC drivers
++#
++# CONFIG_RTC_DRV_M41T94 is not set
++# CONFIG_RTC_DRV_DS1305 is not set
++# CONFIG_RTC_DRV_DS1390 is not set
++# CONFIG_RTC_DRV_MAX6902 is not set
++# CONFIG_RTC_DRV_R9701 is not set
++# CONFIG_RTC_DRV_RS5C348 is not set
++# CONFIG_RTC_DRV_DS3234 is not set
++
++#
++# Platform RTC drivers
++#
++# CONFIG_RTC_DRV_CMOS is not set
++# CONFIG_RTC_DRV_DS1286 is not set
++# CONFIG_RTC_DRV_DS1511 is not set
++# CONFIG_RTC_DRV_DS1553 is not set
++# CONFIG_RTC_DRV_DS1742 is not set
++# CONFIG_RTC_DRV_STK17TA8 is not set
++# CONFIG_RTC_DRV_M48T86 is not set
++# CONFIG_RTC_DRV_M48T35 is not set
++# CONFIG_RTC_DRV_M48T59 is not set
++# CONFIG_RTC_DRV_BQ4802 is not set
++# CONFIG_RTC_DRV_V3020 is not set
++
++#
++# on-CPU RTC drivers
++#
++# CONFIG_RTC_DRV_PL030 is not set
++# CONFIG_RTC_DRV_PL031 is not set
++CONFIG_RTC_DRV_ASPEED=y
++# CONFIG_DMADEVICES is not set
++# CONFIG_REGULATOR is not set
++# CONFIG_UIO is not set
++
++#
++# File systems
++#
++CONFIG_EXT2_FS=y
++CONFIG_EXT2_FS_XATTR=y
++CONFIG_EXT2_FS_POSIX_ACL=y
++CONFIG_EXT2_FS_SECURITY=y
++# CONFIG_EXT2_FS_XIP is not set
++# CONFIG_EXT3_FS is not set
++# CONFIG_EXT4_FS is not set
++CONFIG_FS_MBCACHE=y
++# CONFIG_REISERFS_FS is not set
++# CONFIG_JFS_FS is not set
++CONFIG_FS_POSIX_ACL=y
++CONFIG_FILE_LOCKING=y
++# CONFIG_XFS_FS is not set
++# CONFIG_OCFS2_FS is not set
++CONFIG_DNOTIFY=y
++CONFIG_INOTIFY=y
++CONFIG_INOTIFY_USER=y
++# CONFIG_QUOTA is not set
++# CONFIG_AUTOFS_FS is not set
++# CONFIG_AUTOFS4_FS is not set
++# CONFIG_FUSE_FS is not set
++CONFIG_GENERIC_ACL=y
++
++#
++# CD-ROM/DVD Filesystems
++#
++# CONFIG_ISO9660_FS is not set
++# CONFIG_UDF_FS is not set
++
++#
++# DOS/FAT/NT Filesystems
++#
++CONFIG_FAT_FS=y
++CONFIG_MSDOS_FS=y
++CONFIG_VFAT_FS=y
++CONFIG_FAT_DEFAULT_CODEPAGE=437
++CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
++CONFIG_NTFS_FS=y
++# CONFIG_NTFS_DEBUG is not set
++CONFIG_NTFS_RW=y
++
++#
++# Pseudo filesystems
++#
++CONFIG_PROC_FS=y
++CONFIG_PROC_SYSCTL=y
++CONFIG_PROC_PAGE_MONITOR=y
++CONFIG_SYSFS=y
++CONFIG_TMPFS=y
++CONFIG_TMPFS_POSIX_ACL=y
++# CONFIG_HUGETLB_PAGE is not set
++CONFIG_CONFIGFS_FS=m
++
++#
++# Miscellaneous filesystems
++#
++# CONFIG_ADFS_FS is not set
++# CONFIG_AFFS_FS is not set
++# CONFIG_HFS_FS is not set
++# CONFIG_HFSPLUS_FS is not set
++# CONFIG_BEFS_FS is not set
++# CONFIG_BFS_FS is not set
++# CONFIG_EFS_FS is not set
++CONFIG_YAFFS_FS=y
++CONFIG_YAFFS_YAFFS1=y
++# CONFIG_YAFFS_9BYTE_TAGS is not set
++# CONFIG_YAFFS_DOES_ECC is not set
++CONFIG_YAFFS_YAFFS2=y
++CONFIG_YAFFS_AUTO_YAFFS2=y
++# CONFIG_YAFFS_DISABLE_TAGS_ECC is not set
++# CONFIG_YAFFS_DISABLE_LAZY_LOAD is not set
++# CONFIG_YAFFS_DISABLE_WIDE_TNODES is not set
++# CONFIG_YAFFS_ALWAYS_CHECK_CHUNK_ERASED is not set
++CONFIG_YAFFS_SHORT_NAMES_IN_RAM=y
++# CONFIG_YAFFS_EMPTY_LOST_AND_FOUND is not set
++# CONFIG_JFFS2_FS is not set
++# CONFIG_CRAMFS is not set
++# CONFIG_VXFS_FS is not set
++# CONFIG_MINIX_FS is not set
++# CONFIG_OMFS_FS is not set
++# CONFIG_HPFS_FS is not set
++# CONFIG_QNX4FS_FS is not set
++# CONFIG_ROMFS_FS is not set
++# CONFIG_SYSV_FS is not set
++# CONFIG_UFS_FS is not set
++CONFIG_NETWORK_FILESYSTEMS=y
++CONFIG_NFS_FS=y
++# CONFIG_NFS_V3 is not set
++# CONFIG_NFS_V4 is not set
++CONFIG_ROOT_NFS=y
++# CONFIG_NFSD is not set
++CONFIG_LOCKD=y
++CONFIG_NFS_COMMON=y
++CONFIG_SUNRPC=y
++# CONFIG_SUNRPC_REGISTER_V4 is not set
++# CONFIG_RPCSEC_GSS_KRB5 is not set
++# CONFIG_RPCSEC_GSS_SPKM3 is not set
++# CONFIG_SMB_FS is not set
++# CONFIG_CIFS is not set
++# CONFIG_NCP_FS is not set
++# CONFIG_CODA_FS is not set
++# CONFIG_AFS_FS is not set
++
++#
++# Partition Types
++#
++# CONFIG_PARTITION_ADVANCED is not set
++CONFIG_MSDOS_PARTITION=y
++CONFIG_NLS=y
++CONFIG_NLS_DEFAULT="utf8"
++CONFIG_NLS_CODEPAGE_437=y
++# CONFIG_NLS_CODEPAGE_737 is not set
++# CONFIG_NLS_CODEPAGE_775 is not set
++# CONFIG_NLS_CODEPAGE_850 is not set
++# CONFIG_NLS_CODEPAGE_852 is not set
++# CONFIG_NLS_CODEPAGE_855 is not set
++# CONFIG_NLS_CODEPAGE_857 is not set
++# CONFIG_NLS_CODEPAGE_860 is not set
++# CONFIG_NLS_CODEPAGE_861 is not set
++# CONFIG_NLS_CODEPAGE_862 is not set
++# CONFIG_NLS_CODEPAGE_863 is not set
++# CONFIG_NLS_CODEPAGE_864 is not set
++# CONFIG_NLS_CODEPAGE_865 is not set
++# CONFIG_NLS_CODEPAGE_866 is not set
++# CONFIG_NLS_CODEPAGE_869 is not set
++CONFIG_NLS_CODEPAGE_936=y
++CONFIG_NLS_CODEPAGE_950=y
++CONFIG_NLS_CODEPAGE_932=y
++# CONFIG_NLS_CODEPAGE_949 is not set
++# CONFIG_NLS_CODEPAGE_874 is not set
++# CONFIG_NLS_ISO8859_8 is not set
++# CONFIG_NLS_CODEPAGE_1250 is not set
++# CONFIG_NLS_CODEPAGE_1251 is not set
++CONFIG_NLS_ASCII=y
++CONFIG_NLS_ISO8859_1=y
++# CONFIG_NLS_ISO8859_2 is not set
++# CONFIG_NLS_ISO8859_3 is not set
++# CONFIG_NLS_ISO8859_4 is not set
++# CONFIG_NLS_ISO8859_5 is not set
++# CONFIG_NLS_ISO8859_6 is not set
++# CONFIG_NLS_ISO8859_7 is not set
++# CONFIG_NLS_ISO8859_9 is not set
++# CONFIG_NLS_ISO8859_13 is not set
++# CONFIG_NLS_ISO8859_14 is not set
++# CONFIG_NLS_ISO8859_15 is not set
++# CONFIG_NLS_KOI8_R is not set
++# CONFIG_NLS_KOI8_U is not set
++CONFIG_NLS_UTF8=y
++# CONFIG_DLM is not set
++
++#
++# Kernel hacking
++#
++# CONFIG_PRINTK_TIME is not set
++# CONFIG_ENABLE_WARN_DEPRECATED is not set
++CONFIG_ENABLE_MUST_CHECK=y
++CONFIG_FRAME_WARN=1024
++CONFIG_MAGIC_SYSRQ=y
++# CONFIG_UNUSED_SYMBOLS is not set
++# CONFIG_DEBUG_FS is not set
++# CONFIG_HEADERS_CHECK is not set
++# CONFIG_DEBUG_KERNEL is not set
++# CONFIG_SLUB_DEBUG_ON is not set
++# CONFIG_SLUB_STATS is not set
++CONFIG_DEBUG_BUGVERBOSE=y
++CONFIG_DEBUG_MEMORY_INIT=y
++CONFIG_FRAME_POINTER=y
++# CONFIG_RCU_CPU_STALL_DETECTOR is not set
++# CONFIG_LATENCYTOP is not set
++# CONFIG_SYSCTL_SYSCALL_CHECK is not set
++CONFIG_HAVE_FUNCTION_TRACER=y
++
++#
++# Tracers
++#
++# CONFIG_DYNAMIC_PRINTK_DEBUG is not set
++# CONFIG_SAMPLES is not set
++CONFIG_HAVE_ARCH_KGDB=y
++# CONFIG_DEBUG_USER is not set
++
++#
++# Security options
++#
++# CONFIG_KEYS is not set
++# CONFIG_SECURITY is not set
++# CONFIG_SECURITYFS is not set
++# CONFIG_SECURITY_FILE_CAPABILITIES is not set
++CONFIG_CRYPTO=y
++
++#
++# Crypto core or helper
++#
++# CONFIG_CRYPTO_FIPS is not set
++CONFIG_CRYPTO_ALGAPI=y
++CONFIG_CRYPTO_ALGAPI2=y
++CONFIG_CRYPTO_AEAD=m
++CONFIG_CRYPTO_AEAD2=y
++CONFIG_CRYPTO_BLKCIPHER=y
++CONFIG_CRYPTO_BLKCIPHER2=y
++CONFIG_CRYPTO_HASH=y
++CONFIG_CRYPTO_HASH2=y
++CONFIG_CRYPTO_RNG2=y
++CONFIG_CRYPTO_MANAGER=y
++CONFIG_CRYPTO_MANAGER2=y
++# CONFIG_CRYPTO_GF128MUL is not set
++CONFIG_CRYPTO_NULL=y
++# CONFIG_CRYPTO_CRYPTD is not set
++CONFIG_CRYPTO_AUTHENC=m
++# CONFIG_CRYPTO_TEST is not set
++
++#
++# Authenticated Encryption with Associated Data
++#
++# CONFIG_CRYPTO_CCM is not set
++# CONFIG_CRYPTO_GCM is not set
++# CONFIG_CRYPTO_SEQIV is not set
++
++#
++# Block modes
++#
++CONFIG_CRYPTO_CBC=y
++# CONFIG_CRYPTO_CTR is not set
++# CONFIG_CRYPTO_CTS is not set
++# CONFIG_CRYPTO_ECB is not set
++# CONFIG_CRYPTO_LRW is not set
++# CONFIG_CRYPTO_PCBC is not set
++# CONFIG_CRYPTO_XTS is not set
++
++#
++# Hash modes
++#
++CONFIG_CRYPTO_HMAC=y
++# CONFIG_CRYPTO_XCBC is not set
++
++#
++# Digest
++#
++# CONFIG_CRYPTO_CRC32C is not set
++# CONFIG_CRYPTO_MD4 is not set
++CONFIG_CRYPTO_MD5=y
++# CONFIG_CRYPTO_MICHAEL_MIC is not set
++# CONFIG_CRYPTO_RMD128 is not set
++# CONFIG_CRYPTO_RMD160 is not set
++# CONFIG_CRYPTO_RMD256 is not set
++# CONFIG_CRYPTO_RMD320 is not set
++CONFIG_CRYPTO_SHA1=y
++# CONFIG_CRYPTO_SHA256 is not set
++# CONFIG_CRYPTO_SHA512 is not set
++# CONFIG_CRYPTO_TGR192 is not set
++# CONFIG_CRYPTO_WP512 is not set
++
++#
++# Ciphers
++#
++# CONFIG_CRYPTO_AES is not set
++# CONFIG_CRYPTO_ANUBIS is not set
++# CONFIG_CRYPTO_ARC4 is not set
++# CONFIG_CRYPTO_BLOWFISH is not set
++# CONFIG_CRYPTO_CAMELLIA is not set
++# CONFIG_CRYPTO_CAST5 is not set
++# CONFIG_CRYPTO_CAST6 is not set
++CONFIG_CRYPTO_DES=y
++# CONFIG_CRYPTO_FCRYPT is not set
++# CONFIG_CRYPTO_KHAZAD is not set
++# CONFIG_CRYPTO_SALSA20 is not set
++# CONFIG_CRYPTO_SEED is not set
++# CONFIG_CRYPTO_SERPENT is not set
++# CONFIG_CRYPTO_TEA is not set
++# CONFIG_CRYPTO_TWOFISH is not set
++
++#
++# Compression
++#
++CONFIG_CRYPTO_DEFLATE=m
++# CONFIG_CRYPTO_LZO is not set
++
++#
++# Random Number Generation
++#
++# CONFIG_CRYPTO_ANSI_CPRNG is not set
++# CONFIG_CRYPTO_HW is not set
++
++#
++# Library routines
++#
++CONFIG_BITREVERSE=y
++# CONFIG_CRC_CCITT is not set
++# CONFIG_CRC16 is not set
++# CONFIG_CRC_T10DIF is not set
++CONFIG_CRC_ITU_T=m
++CONFIG_CRC32=y
++# CONFIG_CRC7 is not set
++# CONFIG_LIBCRC32C is not set
++CONFIG_ZLIB_INFLATE=m
++CONFIG_ZLIB_DEFLATE=m
++CONFIG_PLIST=y
++CONFIG_HAS_IOMEM=y
++CONFIG_HAS_IOPORT=y
++CONFIG_HAS_DMA=y
+diff --git a/arch/arm/configs/ast2400_slt_defconfig b/arch/arm/configs/ast2400_slt_defconfig
+new file mode 100644
+index 0000000..fece826
+--- /dev/null
++++ b/arch/arm/configs/ast2400_slt_defconfig
+@@ -0,0 +1,1015 @@
++#
++# Automatically generated make config: don't edit
++# Linux kernel version: 2.6.28.9
++# Thu Mar 27 14:10:01 2014
++#
++CONFIG_ARM=y
++CONFIG_SYS_SUPPORTS_APM_EMULATION=y
++CONFIG_GENERIC_GPIO=y
++# CONFIG_GENERIC_TIME is not set
++# CONFIG_GENERIC_CLOCKEVENTS is not set
++CONFIG_MMU=y
++# CONFIG_NO_IOPORT is not set
++CONFIG_GENERIC_HARDIRQS=y
++CONFIG_STACKTRACE_SUPPORT=y
++CONFIG_HAVE_LATENCYTOP_SUPPORT=y
++CONFIG_LOCKDEP_SUPPORT=y
++CONFIG_TRACE_IRQFLAGS_SUPPORT=y
++CONFIG_HARDIRQS_SW_RESEND=y
++CONFIG_GENERIC_IRQ_PROBE=y
++CONFIG_RWSEM_GENERIC_SPINLOCK=y
++# CONFIG_ARCH_HAS_ILOG2_U32 is not set
++# CONFIG_ARCH_HAS_ILOG2_U64 is not set
++CONFIG_GENERIC_HWEIGHT=y
++CONFIG_GENERIC_CALIBRATE_DELAY=y
++CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
++CONFIG_VECTORS_BASE=0xffff0000
++CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
++
++#
++# General setup
++#
++CONFIG_EXPERIMENTAL=y
++CONFIG_BROKEN_ON_SMP=y
++CONFIG_INIT_ENV_ARG_LIMIT=32
++CONFIG_LOCALVERSION=""
++# CONFIG_LOCALVERSION_AUTO is not set
++CONFIG_SWAP=y
++CONFIG_SYSVIPC=y
++CONFIG_SYSVIPC_SYSCTL=y
++# CONFIG_BSD_PROCESS_ACCT is not set
++# CONFIG_IKCONFIG is not set
++CONFIG_LOG_BUF_SHIFT=16
++# CONFIG_CGROUPS is not set
++# CONFIG_GROUP_SCHED is not set
++CONFIG_SYSFS_DEPRECATED=y
++CONFIG_SYSFS_DEPRECATED_V2=y
++# CONFIG_RELAY is not set
++CONFIG_NAMESPACES=y
++# CONFIG_UTS_NS is not set
++# CONFIG_IPC_NS is not set
++# CONFIG_USER_NS is not set
++# CONFIG_PID_NS is not set
++CONFIG_BLK_DEV_INITRD=y
++CONFIG_INITRAMFS_SOURCE=""
++CONFIG_CC_OPTIMIZE_FOR_SIZE=y
++CONFIG_SYSCTL=y
++CONFIG_ANON_INODES=y
++# CONFIG_EMBEDDED is not set
++CONFIG_UID16=y
++CONFIG_SYSCTL_SYSCALL=y
++CONFIG_KALLSYMS=y
++CONFIG_KALLSYMS_EXTRA_PASS=y
++CONFIG_HOTPLUG=y
++CONFIG_PRINTK=y
++CONFIG_BUG=y
++CONFIG_ELF_CORE=y
++CONFIG_BASE_FULL=y
++CONFIG_FUTEX=y
++CONFIG_EPOLL=y
++CONFIG_SIGNALFD=y
++CONFIG_TIMERFD=y
++CONFIG_EVENTFD=y
++CONFIG_SHMEM=y
++CONFIG_AIO=y
++CONFIG_VM_EVENT_COUNTERS=y
++CONFIG_SLUB_DEBUG=y
++CONFIG_COMPAT_BRK=y
++# CONFIG_SLAB is not set
++CONFIG_SLUB=y
++# CONFIG_SLOB is not set
++# CONFIG_PROFILING is not set
++# CONFIG_MARKERS is not set
++CONFIG_HAVE_OPROFILE=y
++# CONFIG_KPROBES is not set
++CONFIG_HAVE_KPROBES=y
++CONFIG_HAVE_KRETPROBES=y
++CONFIG_HAVE_GENERIC_DMA_COHERENT=y
++CONFIG_SLABINFO=y
++CONFIG_RT_MUTEXES=y
++# CONFIG_TINY_SHMEM is not set
++CONFIG_BASE_SMALL=0
++CONFIG_MODULES=y
++# CONFIG_MODULE_FORCE_LOAD is not set
++CONFIG_MODULE_UNLOAD=y
++# CONFIG_MODULE_FORCE_UNLOAD is not set
++# CONFIG_MODVERSIONS is not set
++# CONFIG_MODULE_SRCVERSION_ALL is not set
++CONFIG_KMOD=y
++CONFIG_BLOCK=y
++# CONFIG_LBD is not set
++# CONFIG_BLK_DEV_IO_TRACE is not set
++# CONFIG_LSF is not set
++# CONFIG_BLK_DEV_BSG is not set
++# CONFIG_BLK_DEV_INTEGRITY is not set
++
++#
++# IO Schedulers
++#
++CONFIG_IOSCHED_NOOP=y
++CONFIG_IOSCHED_AS=y
++CONFIG_IOSCHED_DEADLINE=y
++CONFIG_IOSCHED_CFQ=y
++# CONFIG_DEFAULT_AS is not set
++# CONFIG_DEFAULT_DEADLINE is not set
++CONFIG_DEFAULT_CFQ=y
++# CONFIG_DEFAULT_NOOP is not set
++CONFIG_DEFAULT_IOSCHED="cfq"
++CONFIG_CLASSIC_RCU=y
++CONFIG_FREEZER=y
++
++#
++# System Type
++#
++CONFIG_ARCH_ASPEED=y
++# CONFIG_ARCH_AAEC2000 is not set
++# CONFIG_ARCH_INTEGRATOR is not set
++# CONFIG_ARCH_REALVIEW is not set
++# CONFIG_ARCH_VERSATILE is not set
++# CONFIG_ARCH_AT91 is not set
++# CONFIG_ARCH_CLPS7500 is not set
++# CONFIG_ARCH_CLPS711X is not set
++# CONFIG_ARCH_EBSA110 is not set
++# CONFIG_ARCH_EP93XX is not set
++# CONFIG_ARCH_FOOTBRIDGE is not set
++# CONFIG_ARCH_NETX is not set
++# CONFIG_ARCH_H720X is not set
++# CONFIG_ARCH_IMX is not set
++# CONFIG_ARCH_IOP13XX is not set
++# CONFIG_ARCH_IOP32X is not set
++# CONFIG_ARCH_IOP33X is not set
++# CONFIG_ARCH_IXP23XX is not set
++# CONFIG_ARCH_IXP2000 is not set
++# CONFIG_ARCH_IXP4XX is not set
++# CONFIG_ARCH_L7200 is not set
++# CONFIG_ARCH_KIRKWOOD is not set
++# CONFIG_ARCH_KS8695 is not set
++# CONFIG_ARCH_NS9XXX is not set
++# CONFIG_ARCH_LOKI is not set
++# CONFIG_ARCH_MV78XX0 is not set
++# CONFIG_ARCH_MXC is not set
++# CONFIG_ARCH_ORION5X is not set
++# CONFIG_ARCH_PNX4008 is not set
++# CONFIG_ARCH_PXA is not set
++# CONFIG_ARCH_RPC is not set
++# CONFIG_ARCH_SA1100 is not set
++# CONFIG_ARCH_S3C2410 is not set
++# CONFIG_ARCH_SHARK is not set
++# CONFIG_ARCH_LH7A40X is not set
++# CONFIG_ARCH_DAVINCI is not set
++# CONFIG_ARCH_OMAP is not set
++# CONFIG_ARCH_MSM is not set
++CONFIG_IRMP=y
++# CONFIG_PCEXT is not set
++# CONFIG_REMOTEFX is not set
++# CONFIG_ARCH_AST1100 is not set
++# CONFIG_ARCH_AST2100 is not set
++# CONFIG_ARCH_AST2200 is not set
++# CONFIG_ARCH_AST2300 is not set
++CONFIG_ARCH_AST2400=y
++# CONFIG_ARCH_AST2500 is not set
++
++#
++# FLASH Chip Select
++#
++# CONFIG_AST_CS0_NOR is not set
++# CONFIG_AST_CS0_NAND is not set
++CONFIG_AST_CS0_SPI=y
++# CONFIG_AST_CS0_NONE is not set
++# CONFIG_AST_CS1_NOR is not set
++# CONFIG_AST_CS1_NAND is not set
++# CONFIG_AST_CS1_SPI is not set
++CONFIG_AST_CS1_NONE=y
++# CONFIG_AST_CS2_NOR is not set
++# CONFIG_AST_CS2_NAND is not set
++# CONFIG_AST_CS2_SPI is not set
++CONFIG_AST_CS2_NONE=y
++# CONFIG_AST_CS3_NOR is not set
++# CONFIG_AST_CS3_NAND is not set
++# CONFIG_AST_CS3_SPI is not set
++CONFIG_AST_CS3_NONE=y
++# CONFIG_AST_CS4_NOR is not set
++# CONFIG_AST_CS4_NAND is not set
++# CONFIG_AST_CS4_SPI is not set
++CONFIG_AST_CS4_NONE=y
++# CONFIG_ARCH_AST1070 is not set
++# CONFIG_AST_SCU_LOCK is not set
++
++#
++# Boot options
++#
++
++#
++# Power management
++#
++CONFIG_PLAT_ASPEED=y
++
++#
++# Processor Type
++#
++CONFIG_CPU_32=y
++CONFIG_CPU_ARM926T=y
++CONFIG_CPU_32v5=y
++CONFIG_CPU_ABRT_EV5TJ=y
++CONFIG_CPU_PABRT_NOIFAR=y
++CONFIG_CPU_CACHE_VIVT=y
++CONFIG_CPU_COPY_V4WB=y
++CONFIG_CPU_TLB_V4WBI=y
++CONFIG_CPU_CP15=y
++CONFIG_CPU_CP15_MMU=y
++
++#
++# Processor Features
++#
++CONFIG_ARM_THUMB=y
++# CONFIG_CPU_ICACHE_DISABLE is not set
++# CONFIG_CPU_DCACHE_DISABLE is not set
++# CONFIG_CPU_DCACHE_WRITETHROUGH is not set
++# CONFIG_CPU_CACHE_ROUND_ROBIN is not set
++# CONFIG_OUTER_CACHE is not set
++
++#
++# Bus support
++#
++CONFIG_ARM_AMBA=y
++# CONFIG_PCI_SYSCALL is not set
++# CONFIG_ARCH_SUPPORTS_MSI is not set
++# CONFIG_PCCARD is not set
++
++#
++# Kernel Features
++#
++CONFIG_VMSPLIT_3G=y
++# CONFIG_VMSPLIT_2G is not set
++# CONFIG_VMSPLIT_1G is not set
++CONFIG_PAGE_OFFSET=0xC0000000
++# CONFIG_PREEMPT is not set
++CONFIG_HZ=100
++# CONFIG_AEABI is not set
++CONFIG_ARCH_FLATMEM_HAS_HOLES=y
++# CONFIG_ARCH_SPARSEMEM_DEFAULT is not set
++# CONFIG_ARCH_SELECT_MEMORY_MODEL is not set
++CONFIG_SELECT_MEMORY_MODEL=y
++CONFIG_FLATMEM_MANUAL=y
++# CONFIG_DISCONTIGMEM_MANUAL is not set
++# CONFIG_SPARSEMEM_MANUAL is not set
++CONFIG_FLATMEM=y
++CONFIG_FLAT_NODE_MEM_MAP=y
++CONFIG_PAGEFLAGS_EXTENDED=y
++CONFIG_SPLIT_PTLOCK_CPUS=4096
++# CONFIG_RESOURCES_64BIT is not set
++# CONFIG_PHYS_ADDR_T_64BIT is not set
++CONFIG_ZONE_DMA_FLAG=0
++CONFIG_VIRT_TO_BUS=y
++CONFIG_UNEVICTABLE_LRU=y
++CONFIG_ALIGNMENT_TRAP=y
++
++#
++# Boot options
++#
++CONFIG_ZBOOT_ROM_TEXT=0
++CONFIG_ZBOOT_ROM_BSS=0
++CONFIG_CMDLINE=""
++# CONFIG_XIP_KERNEL is not set
++# CONFIG_KEXEC is not set
++
++#
++# CPU Power Management
++#
++# CONFIG_CPU_IDLE is not set
++
++#
++# Floating point emulation
++#
++
++#
++# At least one emulation must be selected
++#
++CONFIG_FPE_NWFPE=y
++CONFIG_FPE_NWFPE_XP=y
++# CONFIG_FPE_FASTFPE is not set
++CONFIG_VFP=y
++
++#
++# Userspace binary formats
++#
++CONFIG_BINFMT_ELF=y
++# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
++CONFIG_HAVE_AOUT=y
++CONFIG_BINFMT_AOUT=y
++# CONFIG_BINFMT_MISC is not set
++# CONFIG_ARTHUR is not set
++
++#
++# Power management options
++#
++CONFIG_PM=y
++# CONFIG_PM_DEBUG is not set
++CONFIG_PM_SLEEP=y
++CONFIG_SUSPEND=y
++CONFIG_SUSPEND_FREEZER=y
++# CONFIG_APM_EMULATION is not set
++CONFIG_ARCH_SUSPEND_POSSIBLE=y
++# CONFIG_NET is not set
++
++#
++# Device Drivers
++#
++
++#
++# Generic Driver Options
++#
++CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
++CONFIG_STANDALONE=y
++CONFIG_PREVENT_FIRMWARE_BUILD=y
++CONFIG_FW_LOADER=y
++CONFIG_FIRMWARE_IN_KERNEL=y
++CONFIG_EXTRA_FIRMWARE=""
++# CONFIG_SYS_HYPERVISOR is not set
++CONFIG_MTD=y
++# CONFIG_MTD_DEBUG is not set
++CONFIG_MTD_CONCAT=y
++CONFIG_MTD_PARTITIONS=y
++# CONFIG_MTD_REDBOOT_PARTS is not set
++# CONFIG_MTD_CMDLINE_PARTS is not set
++# CONFIG_MTD_AFS_PARTS is not set
++# CONFIG_MTD_AR7_PARTS is not set
++
++#
++# User Modules And Translation Layers
++#
++CONFIG_MTD_CHAR=y
++CONFIG_MTD_BLKDEVS=y
++CONFIG_MTD_BLOCK=y
++# CONFIG_FTL is not set
++# CONFIG_NFTL is not set
++# CONFIG_INFTL is not set
++# CONFIG_RFD_FTL is not set
++# CONFIG_SSFDC is not set
++# CONFIG_MTD_OOPS is not set
++
++#
++# RAM/ROM/Flash chip drivers
++#
++# CONFIG_MTD_CFI is not set
++# CONFIG_MTD_JEDECPROBE is not set
++CONFIG_MTD_MAP_BANK_WIDTH_1=y
++CONFIG_MTD_MAP_BANK_WIDTH_2=y
++CONFIG_MTD_MAP_BANK_WIDTH_4=y
++# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
++# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
++# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
++CONFIG_MTD_CFI_I1=y
++CONFIG_MTD_CFI_I2=y
++# CONFIG_MTD_CFI_I4 is not set
++# CONFIG_MTD_CFI_I8 is not set
++# CONFIG_MTD_RAM is not set
++# CONFIG_MTD_ROM is not set
++# CONFIG_MTD_ABSENT is not set
++
++#
++# Mapping drivers for chip access
++#
++# CONFIG_MTD_COMPLEX_MAPPINGS is not set
++# CONFIG_MTD_PLATRAM is not set
++
++#
++# Self-contained MTD device drivers
++#
++CONFIG_MTD_DATAFLASH=y
++# CONFIG_MTD_DATAFLASH_WRITE_VERIFY is not set
++# CONFIG_MTD_DATAFLASH_OTP is not set
++CONFIG_MTD_M25P80=y
++CONFIG_M25PXX_USE_FAST_READ=y
++# CONFIG_MTD_SLRAM is not set
++# CONFIG_MTD_PHRAM is not set
++# CONFIG_MTD_MTDRAM is not set
++# CONFIG_MTD_BLOCK2MTD is not set
++
++#
++# Disk-On-Chip Device Drivers
++#
++# CONFIG_MTD_DOC2000 is not set
++# CONFIG_MTD_DOC2001 is not set
++# CONFIG_MTD_DOC2001PLUS is not set
++CONFIG_MTD_NAND=y
++# CONFIG_MTD_NAND_VERIFY_WRITE is not set
++# CONFIG_MTD_NAND_ECC_SMC is not set
++# CONFIG_MTD_NAND_MUSEUM_IDS is not set
++CONFIG_MTD_NAND_AST=y
++# CONFIG_MTD_NAND_GPIO is not set
++CONFIG_MTD_NAND_IDS=y
++# CONFIG_MTD_NAND_DISKONCHIP is not set
++# CONFIG_MTD_NAND_NANDSIM is not set
++# CONFIG_MTD_NAND_PLATFORM is not set
++# CONFIG_MTD_ALAUDA is not set
++# CONFIG_MTD_ONENAND is not set
++
++#
++# UBI - Unsorted block images
++#
++# CONFIG_MTD_UBI is not set
++# CONFIG_PARPORT is not set
++CONFIG_BLK_DEV=y
++# CONFIG_BLK_DEV_COW_COMMON is not set
++CONFIG_BLK_DEV_LOOP=y
++# CONFIG_BLK_DEV_CRYPTOLOOP is not set
++# CONFIG_BLK_DEV_UB is not set
++CONFIG_BLK_DEV_RAM=y
++CONFIG_BLK_DEV_RAM_COUNT=16
++CONFIG_BLK_DEV_RAM_SIZE=16384
++# CONFIG_BLK_DEV_XIP is not set
++# CONFIG_CDROM_PKTCDVD is not set
++CONFIG_MISC_DEVICES=y
++# CONFIG_EEPROM_93CX6 is not set
++# CONFIG_ENCLOSURE_SERVICES is not set
++# CONFIG_C2PORT is not set
++CONFIG_HAVE_IDE=y
++# CONFIG_IDE is not set
++
++#
++# SCSI device support
++#
++# CONFIG_RAID_ATTRS is not set
++CONFIG_SCSI=y
++CONFIG_SCSI_DMA=y
++CONFIG_SCSI_TGT=y
++# CONFIG_SCSI_NETLINK is not set
++CONFIG_SCSI_PROC_FS=y
++
++#
++# SCSI support type (disk, tape, CD-ROM)
++#
++CONFIG_BLK_DEV_SD=y
++# CONFIG_CHR_DEV_ST is not set
++# CONFIG_CHR_DEV_OSST is not set
++# CONFIG_BLK_DEV_SR is not set
++CONFIG_CHR_DEV_SG=y
++# CONFIG_CHR_DEV_SCH is not set
++
++#
++# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
++#
++# CONFIG_SCSI_MULTI_LUN is not set
++# CONFIG_SCSI_CONSTANTS is not set
++# CONFIG_SCSI_LOGGING is not set
++CONFIG_SCSI_SCAN_ASYNC=y
++CONFIG_SCSI_WAIT_SCAN=m
++
++#
++# SCSI Transports
++#
++# CONFIG_SCSI_SPI_ATTRS is not set
++# CONFIG_SCSI_FC_ATTRS is not set
++# CONFIG_SCSI_SAS_LIBSAS is not set
++# CONFIG_SCSI_SRP_ATTRS is not set
++# CONFIG_SCSI_LOWLEVEL is not set
++# CONFIG_SCSI_DH is not set
++# CONFIG_ATA is not set
++# CONFIG_MD is not set
++
++#
++# Input device support
++#
++CONFIG_INPUT=y
++# CONFIG_INPUT_FF_MEMLESS is not set
++# CONFIG_INPUT_POLLDEV is not set
++
++#
++# Userland interfaces
++#
++CONFIG_INPUT_MOUSEDEV=y
++CONFIG_INPUT_MOUSEDEV_PSAUX=y
++CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
++CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
++# CONFIG_INPUT_JOYDEV is not set
++CONFIG_INPUT_EVDEV=y
++# CONFIG_INPUT_EVBUG is not set
++
++#
++# Input Device Drivers
++#
++CONFIG_INPUT_KEYBOARD=y
++CONFIG_KEYBOARD_ATKBD=y
++# CONFIG_KEYBOARD_SUNKBD is not set
++# CONFIG_KEYBOARD_LKKBD is not set
++# CONFIG_KEYBOARD_XTKBD is not set
++# CONFIG_KEYBOARD_NEWTON is not set
++# CONFIG_KEYBOARD_STOWAWAY is not set
++# CONFIG_KEYBOARD_GPIO is not set
++CONFIG_INPUT_MOUSE=y
++CONFIG_MOUSE_PS2=y
++CONFIG_MOUSE_PS2_ALPS=y
++CONFIG_MOUSE_PS2_LOGIPS2PP=y
++CONFIG_MOUSE_PS2_SYNAPTICS=y
++CONFIG_MOUSE_PS2_LIFEBOOK=y
++CONFIG_MOUSE_PS2_TRACKPOINT=y
++# CONFIG_MOUSE_PS2_ELANTECH is not set
++# CONFIG_MOUSE_PS2_TOUCHKIT is not set
++CONFIG_MOUSE_SERIAL=y
++# CONFIG_MOUSE_APPLETOUCH is not set
++# CONFIG_MOUSE_BCM5974 is not set
++# CONFIG_MOUSE_VSXXXAA is not set
++# CONFIG_MOUSE_GPIO is not set
++# CONFIG_INPUT_JOYSTICK is not set
++# CONFIG_INPUT_TABLET is not set
++# CONFIG_INPUT_TOUCHSCREEN is not set
++# CONFIG_INPUT_MISC is not set
++
++#
++# Hardware I/O ports
++#
++CONFIG_SERIO=y
++CONFIG_SERIO_SERPORT=y
++# CONFIG_SERIO_AMBAKMI is not set
++CONFIG_SERIO_LIBPS2=y
++# CONFIG_SERIO_RAW is not set
++# CONFIG_GAMEPORT is not set
++
++#
++# Character devices
++#
++CONFIG_VT=y
++CONFIG_CONSOLE_TRANSLATIONS=y
++CONFIG_VT_CONSOLE=y
++CONFIG_HW_CONSOLE=y
++# CONFIG_VT_HW_CONSOLE_BINDING is not set
++CONFIG_DEVKMEM=y
++CONFIG_SERIAL_NONSTANDARD=y
++# CONFIG_N_HDLC is not set
++# CONFIG_RISCOM8 is not set
++# CONFIG_SPECIALIX is not set
++# CONFIG_RIO is not set
++# CONFIG_STALDRV is not set
++
++#
++# Serial drivers
++#
++CONFIG_SERIAL_8250=y
++CONFIG_SERIAL_8250_CONSOLE=y
++CONFIG_SERIAL_8250_NR_UARTS=4
++CONFIG_SERIAL_8250_RUNTIME_UARTS=4
++# CONFIG_SERIAL_AST_DMA_UART is not set
++# CONFIG_SERIAL_8250_EXTENDED is not set
++
++#
++# Non-8250 serial port support
++#
++# CONFIG_SERIAL_AMBA_PL010 is not set
++# CONFIG_SERIAL_AMBA_PL011 is not set
++# CONFIG_SERIAL_AST is not set
++CONFIG_SERIAL_CORE=y
++CONFIG_SERIAL_CORE_CONSOLE=y
++CONFIG_UNIX98_PTYS=y
++CONFIG_LEGACY_PTYS=y
++CONFIG_LEGACY_PTY_COUNT=256
++# CONFIG_IPMI_HANDLER is not set
++CONFIG_AST_MISC=y
++# CONFIG_AST_VIDEO is not set
++# CONFIG_ADC_CAT9883 is not set
++# CONFIG_AST_SPI_BIOS is not set
++CONFIG_AST_PECI=y
++# CONFIG_AST_KCS is not set
++# CONFIG_AST_GPIO is not set
++# CONFIG_HW_RANDOM is not set
++CONFIG_NVRAM=y
++# CONFIG_R3964 is not set
++# CONFIG_RAW_DRIVER is not set
++# CONFIG_TCG_TPM is not set
++# CONFIG_I2C is not set
++# CONFIG_AST_I2C_SLAVE_EEPROM is not set
++# CONFIG_AST_I2C_SLAVE_RDWR is not set
++CONFIG_SPI=y
++CONFIG_SPI_MASTER=y
++
++#
++# SPI Master Controller Drivers
++#
++# CONFIG_SPI_AST is not set
++CONFIG_SPI_FMC=y
++# CONFIG_SPI_BITBANG is not set
++
++#
++# SPI Protocol Masters
++#
++# CONFIG_SPI_AT25 is not set
++CONFIG_SPI_SPIDEV=y
++# CONFIG_SPI_TLE62X0 is not set
++CONFIG_ARCH_REQUIRE_GPIOLIB=y
++CONFIG_GPIOLIB=y
++CONFIG_GPIO_SYSFS=y
++
++#
++# Memory mapped GPIO expanders:
++#
++
++#
++# I2C GPIO expanders:
++#
++
++#
++# PCI GPIO expanders:
++#
++
++#
++# SPI GPIO expanders:
++#
++# CONFIG_GPIO_MAX7301 is not set
++# CONFIG_GPIO_MCP23S08 is not set
++# CONFIG_W1 is not set
++# CONFIG_POWER_SUPPLY is not set
++# CONFIG_HWMON is not set
++# CONFIG_THERMAL is not set
++# CONFIG_THERMAL_HWMON is not set
++CONFIG_WATCHDOG=y
++# CONFIG_WATCHDOG_NOWAYOUT is not set
++
++#
++# Watchdog Device Drivers
++#
++# CONFIG_SOFT_WATCHDOG is not set
++CONFIG_AST_WATCHDOG=y
++
++#
++# USB-based Watchdog Cards
++#
++# CONFIG_USBPCWATCHDOG is not set
++CONFIG_SSB_POSSIBLE=y
++
++#
++# Sonics Silicon Backplane
++#
++# CONFIG_SSB is not set
++
++#
++# Multifunction device drivers
++#
++# CONFIG_MFD_CORE is not set
++# CONFIG_MFD_SM501 is not set
++# CONFIG_MFD_ASIC3 is not set
++# CONFIG_HTC_EGPIO is not set
++# CONFIG_HTC_PASIC3 is not set
++# CONFIG_MFD_TMIO is not set
++# CONFIG_MFD_TC6393XB is not set
++
++#
++# Multimedia devices
++#
++
++#
++# Multimedia core support
++#
++# CONFIG_VIDEO_DEV is not set
++# CONFIG_VIDEO_MEDIA is not set
++
++#
++# Multimedia drivers
++#
++# CONFIG_DAB is not set
++
++#
++# Graphics support
++#
++# CONFIG_VGASTATE is not set
++# CONFIG_VIDEO_OUTPUT_CONTROL is not set
++# CONFIG_FB is not set
++# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
++
++#
++# Display device support
++#
++# CONFIG_DISPLAY_SUPPORT is not set
++
++#
++# Console display driver support
++#
++# CONFIG_VGA_CONSOLE is not set
++CONFIG_DUMMY_CONSOLE=y
++# CONFIG_SOUND is not set
++# CONFIG_HID_SUPPORT is not set
++CONFIG_USB_SUPPORT=y
++CONFIG_USB_ARCH_HAS_HCD=y
++# CONFIG_USB_ARCH_HAS_OHCI is not set
++CONFIG_USB_ARCH_HAS_EHCI=y
++CONFIG_USB=y
++# CONFIG_USB_DEBUG is not set
++# CONFIG_USB_ANNOUNCE_NEW_DEVICES is not set
++
++#
++# Miscellaneous USB options
++#
++CONFIG_USB_DEVICEFS=y
++CONFIG_USB_DEVICE_CLASS=y
++# CONFIG_USB_DYNAMIC_MINORS is not set
++# CONFIG_USB_SUSPEND is not set
++# CONFIG_USB_OTG is not set
++# CONFIG_USB_MON is not set
++# CONFIG_USB_WUSB is not set
++# CONFIG_USB_WUSB_CBAF is not set
++
++#
++# USB Host Controller Drivers
++#
++# CONFIG_USB_C67X00_HCD is not set
++CONFIG_USB_EHCI_HCD=y
++# CONFIG_USB_EHCI_ROOT_HUB_TT is not set
++CONFIG_USB_EHCI_TT_NEWSCHED=y
++CONFIG_USB_EHCI_AST=y
++# CONFIG_USB_ISP116X_HCD is not set
++# CONFIG_USB_SL811_HCD is not set
++# CONFIG_USB_R8A66597_HCD is not set
++# CONFIG_USB_HWA_HCD is not set
++
++#
++# AST USB Drivers
++#
++CONFIG_AST_USB_UHCI_HCD=y
++# CONFIG_AST_USB_UHCI_MULTIPORT_1 is not set
++# CONFIG_AST_USB_UHCI_MULTIPORT_2 is not set
++CONFIG_AST_USB_UHCI_MULTIPORT_4=y
++# CONFIG_USB_EHCI_SPLIT_ISO is not set
++
++#
++# USB Device Class drivers
++#
++# CONFIG_USB_ACM is not set
++# CONFIG_USB_PRINTER is not set
++# CONFIG_USB_WDM is not set
++# CONFIG_USB_TMC is not set
++
++#
++# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may also be needed;
++#
++
++#
++# see USB_STORAGE Help for more information
++#
++CONFIG_USB_STORAGE=y
++# CONFIG_USB_STORAGE_DEBUG is not set
++# CONFIG_USB_STORAGE_DATAFAB is not set
++# CONFIG_USB_STORAGE_FREECOM is not set
++# CONFIG_USB_STORAGE_ISD200 is not set
++# CONFIG_USB_STORAGE_DPCM is not set
++# CONFIG_USB_STORAGE_USBAT is not set
++# CONFIG_USB_STORAGE_SDDR09 is not set
++# CONFIG_USB_STORAGE_SDDR55 is not set
++# CONFIG_USB_STORAGE_JUMPSHOT is not set
++# CONFIG_USB_STORAGE_ALAUDA is not set
++# CONFIG_USB_STORAGE_ONETOUCH is not set
++# CONFIG_USB_STORAGE_KARMA is not set
++# CONFIG_USB_STORAGE_CYPRESS_ATACB is not set
++# CONFIG_USB_LIBUSUAL is not set
++
++#
++# USB Imaging devices
++#
++# CONFIG_USB_MDC800 is not set
++# CONFIG_USB_MICROTEK is not set
++
++#
++# USB port drivers
++#
++# CONFIG_USB_SERIAL is not set
++
++#
++# USB Miscellaneous drivers
++#
++# CONFIG_USB_EMI62 is not set
++# CONFIG_USB_EMI26 is not set
++# CONFIG_USB_ADUTUX is not set
++# CONFIG_USB_SEVSEG is not set
++# CONFIG_USB_RIO500 is not set
++# CONFIG_USB_LEGOTOWER is not set
++# CONFIG_USB_LCD is not set
++# CONFIG_USB_BERRY_CHARGE is not set
++# CONFIG_USB_LED is not set
++# CONFIG_USB_CYPRESS_CY7C63 is not set
++# CONFIG_USB_CYTHERM is not set
++# CONFIG_USB_PHIDGET is not set
++# CONFIG_USB_IDMOUSE is not set
++# CONFIG_USB_FTDI_ELAN is not set
++# CONFIG_USB_APPLEDISPLAY is not set
++# CONFIG_USB_SISUSBVGA is not set
++# CONFIG_USB_LD is not set
++# CONFIG_USB_TRANCEVIBRATOR is not set
++# CONFIG_USB_IOWARRIOR is not set
++# CONFIG_USB_TEST is not set
++# CONFIG_USB_ISIGHTFW is not set
++# CONFIG_USB_VST is not set
++# CONFIG_USB_GADGET is not set
++CONFIG_MMC=y
++# CONFIG_MMC_DEBUG is not set
++# CONFIG_MMC_UNSAFE_RESUME is not set
++
++#
++# MMC/SD/SDIO Card Drivers
++#
++CONFIG_MMC_BLOCK=y
++CONFIG_MMC_BLOCK_BOUNCE=y
++# CONFIG_SDIO_UART is not set
++# CONFIG_MMC_TEST is not set
++
++#
++# MMC/SD/SDIO Host Controller Drivers
++#
++# CONFIG_MMC_ARMMMCI is not set
++# CONFIG_MMC_SDHCI is not set
++CONFIG_MMC_AST=y
++# CONFIG_MMC_SPI is not set
++# CONFIG_MEMSTICK is not set
++# CONFIG_ACCESSIBILITY is not set
++# CONFIG_NEW_LEDS is not set
++CONFIG_RTC_LIB=y
++# CONFIG_RTC_CLASS is not set
++# CONFIG_DMADEVICES is not set
++# CONFIG_REGULATOR is not set
++# CONFIG_UIO is not set
++
++#
++# File systems
++#
++CONFIG_EXT2_FS=y
++CONFIG_EXT2_FS_XATTR=y
++CONFIG_EXT2_FS_POSIX_ACL=y
++CONFIG_EXT2_FS_SECURITY=y
++# CONFIG_EXT2_FS_XIP is not set
++# CONFIG_EXT3_FS is not set
++# CONFIG_EXT4_FS is not set
++CONFIG_FS_MBCACHE=y
++# CONFIG_REISERFS_FS is not set
++# CONFIG_JFS_FS is not set
++CONFIG_FS_POSIX_ACL=y
++CONFIG_FILE_LOCKING=y
++# CONFIG_XFS_FS is not set
++CONFIG_DNOTIFY=y
++CONFIG_INOTIFY=y
++CONFIG_INOTIFY_USER=y
++# CONFIG_QUOTA is not set
++# CONFIG_AUTOFS_FS is not set
++# CONFIG_AUTOFS4_FS is not set
++# CONFIG_FUSE_FS is not set
++CONFIG_GENERIC_ACL=y
++
++#
++# CD-ROM/DVD Filesystems
++#
++# CONFIG_ISO9660_FS is not set
++# CONFIG_UDF_FS is not set
++
++#
++# DOS/FAT/NT Filesystems
++#
++CONFIG_FAT_FS=y
++CONFIG_MSDOS_FS=y
++CONFIG_VFAT_FS=y
++CONFIG_FAT_DEFAULT_CODEPAGE=437
++CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
++CONFIG_NTFS_FS=y
++# CONFIG_NTFS_DEBUG is not set
++CONFIG_NTFS_RW=y
++
++#
++# Pseudo filesystems
++#
++CONFIG_PROC_FS=y
++CONFIG_PROC_SYSCTL=y
++CONFIG_PROC_PAGE_MONITOR=y
++CONFIG_SYSFS=y
++CONFIG_TMPFS=y
++CONFIG_TMPFS_POSIX_ACL=y
++# CONFIG_HUGETLB_PAGE is not set
++CONFIG_CONFIGFS_FS=m
++
++#
++# Miscellaneous filesystems
++#
++# CONFIG_ADFS_FS is not set
++# CONFIG_AFFS_FS is not set
++# CONFIG_HFS_FS is not set
++# CONFIG_HFSPLUS_FS is not set
++# CONFIG_BEFS_FS is not set
++# CONFIG_BFS_FS is not set
++# CONFIG_EFS_FS is not set
++CONFIG_YAFFS_FS=y
++CONFIG_YAFFS_YAFFS1=y
++# CONFIG_YAFFS_9BYTE_TAGS is not set
++# CONFIG_YAFFS_DOES_ECC is not set
++CONFIG_YAFFS_YAFFS2=y
++CONFIG_YAFFS_AUTO_YAFFS2=y
++# CONFIG_YAFFS_DISABLE_TAGS_ECC is not set
++# CONFIG_YAFFS_DISABLE_LAZY_LOAD is not set
++# CONFIG_YAFFS_DISABLE_WIDE_TNODES is not set
++# CONFIG_YAFFS_ALWAYS_CHECK_CHUNK_ERASED is not set
++CONFIG_YAFFS_SHORT_NAMES_IN_RAM=y
++# CONFIG_YAFFS_EMPTY_LOST_AND_FOUND is not set
++# CONFIG_JFFS2_FS is not set
++# CONFIG_CRAMFS is not set
++# CONFIG_VXFS_FS is not set
++# CONFIG_MINIX_FS is not set
++# CONFIG_OMFS_FS is not set
++# CONFIG_HPFS_FS is not set
++# CONFIG_QNX4FS_FS is not set
++# CONFIG_ROMFS_FS is not set
++# CONFIG_SYSV_FS is not set
++# CONFIG_UFS_FS is not set
++
++#
++# Partition Types
++#
++# CONFIG_PARTITION_ADVANCED is not set
++CONFIG_MSDOS_PARTITION=y
++CONFIG_NLS=y
++CONFIG_NLS_DEFAULT="utf8"
++CONFIG_NLS_CODEPAGE_437=y
++# CONFIG_NLS_CODEPAGE_737 is not set
++# CONFIG_NLS_CODEPAGE_775 is not set
++# CONFIG_NLS_CODEPAGE_850 is not set
++# CONFIG_NLS_CODEPAGE_852 is not set
++# CONFIG_NLS_CODEPAGE_855 is not set
++# CONFIG_NLS_CODEPAGE_857 is not set
++# CONFIG_NLS_CODEPAGE_860 is not set
++# CONFIG_NLS_CODEPAGE_861 is not set
++# CONFIG_NLS_CODEPAGE_862 is not set
++# CONFIG_NLS_CODEPAGE_863 is not set
++# CONFIG_NLS_CODEPAGE_864 is not set
++# CONFIG_NLS_CODEPAGE_865 is not set
++# CONFIG_NLS_CODEPAGE_866 is not set
++# CONFIG_NLS_CODEPAGE_869 is not set
++CONFIG_NLS_CODEPAGE_936=y
++CONFIG_NLS_CODEPAGE_950=y
++CONFIG_NLS_CODEPAGE_932=y
++# CONFIG_NLS_CODEPAGE_949 is not set
++# CONFIG_NLS_CODEPAGE_874 is not set
++# CONFIG_NLS_ISO8859_8 is not set
++# CONFIG_NLS_CODEPAGE_1250 is not set
++# CONFIG_NLS_CODEPAGE_1251 is not set
++CONFIG_NLS_ASCII=y
++CONFIG_NLS_ISO8859_1=y
++# CONFIG_NLS_ISO8859_2 is not set
++# CONFIG_NLS_ISO8859_3 is not set
++# CONFIG_NLS_ISO8859_4 is not set
++# CONFIG_NLS_ISO8859_5 is not set
++# CONFIG_NLS_ISO8859_6 is not set
++# CONFIG_NLS_ISO8859_7 is not set
++# CONFIG_NLS_ISO8859_9 is not set
++# CONFIG_NLS_ISO8859_13 is not set
++# CONFIG_NLS_ISO8859_14 is not set
++# CONFIG_NLS_ISO8859_15 is not set
++# CONFIG_NLS_KOI8_R is not set
++# CONFIG_NLS_KOI8_U is not set
++CONFIG_NLS_UTF8=y
++
++#
++# Kernel hacking
++#
++# CONFIG_PRINTK_TIME is not set
++# CONFIG_ENABLE_WARN_DEPRECATED is not set
++CONFIG_ENABLE_MUST_CHECK=y
++CONFIG_FRAME_WARN=1024
++CONFIG_MAGIC_SYSRQ=y
++# CONFIG_UNUSED_SYMBOLS is not set
++# CONFIG_DEBUG_FS is not set
++# CONFIG_HEADERS_CHECK is not set
++# CONFIG_DEBUG_KERNEL is not set
++# CONFIG_SLUB_DEBUG_ON is not set
++# CONFIG_SLUB_STATS is not set
++CONFIG_DEBUG_BUGVERBOSE=y
++CONFIG_DEBUG_MEMORY_INIT=y
++CONFIG_FRAME_POINTER=y
++# CONFIG_RCU_CPU_STALL_DETECTOR is not set
++# CONFIG_LATENCYTOP is not set
++# CONFIG_SYSCTL_SYSCALL_CHECK is not set
++CONFIG_HAVE_FUNCTION_TRACER=y
++
++#
++# Tracers
++#
++# CONFIG_DYNAMIC_PRINTK_DEBUG is not set
++# CONFIG_SAMPLES is not set
++CONFIG_HAVE_ARCH_KGDB=y
++# CONFIG_DEBUG_USER is not set
++
++#
++# Security options
++#
++# CONFIG_KEYS is not set
++# CONFIG_SECURITY is not set
++# CONFIG_SECURITYFS is not set
++# CONFIG_SECURITY_FILE_CAPABILITIES is not set
++# CONFIG_CRYPTO is not set
++
++#
++# Library routines
++#
++CONFIG_BITREVERSE=y
++# CONFIG_CRC_CCITT is not set
++# CONFIG_CRC16 is not set
++# CONFIG_CRC_T10DIF is not set
++CONFIG_CRC_ITU_T=m
++CONFIG_CRC32=y
++# CONFIG_CRC7 is not set
++# CONFIG_LIBCRC32C is not set
++CONFIG_PLIST=y
++CONFIG_HAS_IOMEM=y
++CONFIG_HAS_IOPORT=y
++CONFIG_HAS_DMA=y
+diff --git a/arch/arm/kernel/head.S b/arch/arm/kernel/head.S
+index 21e17dc..8ff0e23 100644
+--- a/arch/arm/kernel/head.S
++++ b/arch/arm/kernel/head.S
+@@ -21,6 +21,7 @@
+ #include <asm/memory.h>
+ #include <asm/thread_info.h>
+ #include <asm/system.h>
++#include <asm/mach-types.h>
+
+ #if (PHYS_OFFSET & 0x001fffff)
+ #error "PHYS_OFFSET must be at an even 2MiB boundary!"
+@@ -76,13 +77,14 @@
+ */
+ .section ".text.head", "ax"
+ ENTRY(stext)
++ ldr r5, =machine_arch_type @ find the machine type
+ msr cpsr_c, #PSR_F_BIT | PSR_I_BIT | SVC_MODE @ ensure svc mode
+ @ and irqs disabled
+ mrc p15, 0, r9, c0, c0 @ get processor id
+ bl __lookup_processor_type @ r5=procinfo r9=cpuid
+ movs r10, r5 @ invalid processor (r5=0)?
+ beq __error_p @ yes, error 'p'
+- bl __lookup_machine_type @ r5=machinfo
++@ bl __lookup_machine_type @ r5=machinfo
+ movs r8, r5 @ invalid machine (r5=0)?
+ beq __error_a @ yes, error 'a'
+ bl __vet_atags
+diff --git a/arch/arm/mach-aspeed/Kconfig b/arch/arm/mach-aspeed/Kconfig
+new file mode 100644
+index 0000000..a948ab8
+--- /dev/null
++++ b/arch/arm/mach-aspeed/Kconfig
+@@ -0,0 +1,214 @@
++if ARCH_ASPEED
++
++choice
++ prompt "ASPEED Processor Family"
++ default CONFIG_IRMP
++
++config IRMP
++ bool "IRMP Serials"
++
++config PCEXT
++ bool "PC Extender Serials"
++
++config REMOTEFX
++ bool "RemoteFX Zero-Client Serials"
++
++endchoice
++
++if IRMP
++
++choice
++ prompt "IRMP Serials"
++ default CONFIG_ARCH_AST2300
++
++config ARCH_AST1100
++ bool "AST1100"
++
++config ARCH_AST2100
++ bool "AST2100"
++
++config ARCH_AST2200
++ bool "AST2200"
++
++config ARCH_AST2300
++ bool "AST2300"
++
++config ARCH_AST2400
++ select USB_ARCH_HAS_EHCI
++ bool "AST2400"
++
++config ARCH_AST2500
++ select USB_ARCH_HAS_EHCI
++ bool "AST2500"
++
++endchoice
++
++endif
++
++if PCEXT
++
++choice
++ prompt "PC Extender Serials"
++ default CONFIG_ARCH_AST1510
++
++config ARCH_AST1500
++ bool "AST1500"
++
++config ARCH_AST1510
++ bool "AST1510"
++
++config ARCH_AST1520
++ select USB_ARCH_HAS_EHCI
++ bool "AST1520"
++
++endchoice
++
++endif
++
++if REMOTEFX
++
++choice
++ prompt "RemoteFX Zero-Client Serials"
++ default CONFIG_ARCH_AST3100
++
++config ARCH_AST3100
++ select USB_ARCH_HAS_EHCI
++ bool "AST3100"
++
++config ARCH_AST3200
++ select USB_ARCH_HAS_EHCI
++ bool "AST3200"
++
++endchoice
++
++endif
++
++menu "FLASH Chip Select"
++
++choice
++ prompt "CS0 Config"
++ default CONFIG_AST_CS0_SPI
++
++config AST_CS0_NOR
++ bool "NOR"
++
++config AST_CS0_NAND
++ bool "NAND"
++
++config AST_CS0_SPI
++ bool "SPI_NOR"
++
++config AST_CS0_NONE
++ bool "NONE"
++
++endchoice
++
++choice
++ prompt "CS1 Config"
++ default CONFIG_AST_CS1_SPI
++
++config AST_CS1_NOR
++ bool "NOR"
++
++config AST_CS1_NAND
++ bool "NAND"
++
++config AST_CS1_SPI
++ bool "SPI_NOR"
++
++config AST_CS1_NONE
++ bool "NONE"
++
++endchoice
++
++choice
++ prompt "CS2 Config"
++ default CONFIG_AST_CS2_SPI
++
++config AST_CS2_NOR
++ bool "NOR"
++
++config AST_CS2_NAND
++ bool "NAND"
++
++config AST_CS2_SPI
++ bool "SPI_NOR"
++
++config AST_CS2_NONE
++ bool "NONE"
++
++endchoice
++
++choice
++ prompt "CS3 Config"
++ default CONFIG_AST_CS3_SPI
++
++config AST_CS3_NOR
++ bool "NOR"
++
++config AST_CS3_NAND
++ bool "NAND"
++
++config AST_CS3_SPI
++ bool "SPI_NOR"
++
++config AST_CS3_NONE
++ bool "NONE"
++
++endchoice
++
++choice
++ prompt "CS4 Config"
++ default CONFIG_AST_CS4_SPI
++
++config AST_CS4_NOR
++ bool "NOR"
++
++config AST_CS4_NAND
++ bool "NAND"
++
++config AST_CS4_SPI
++ bool "SPI_NOR"
++
++config AST_CS4_NONE
++ bool "NONE"
++
++endchoice
++
++endmenu
++
++config ARCH_AST1070
++ bool "AST1070 Comapnion chip combination"
++
++config AST1070_NR
++ int "Number of AST1070 Comapniion Chip combination"
++ depends on ARCH_AST1070
++ default "1"
++ help
++ Set this to the number of ast1070
++
++choice
++ prompt "Connect Bus Interface"
++ depends on ARCH_AST1070
++ default CONFIG_AST_LPC_PLUS
++
++config AST_LPC_PLUS
++ bool "LPC PLUS"
++
++config AST_LPC
++ bool "LPC"
++
++endchoice
++
++config AST_SCU_LOCK
++ bool "AST SCU Protection Key"
++
++# Support PCIE
++config PCIE
++ bool "ASPEED PCIE support"
++ depends on PCI && ARCH_ASPEED
++ select ARCH_SUPPORTS_MSI
++ help
++ Socle PCIE support
++
++endif
+diff --git a/arch/arm/mach-aspeed/Makefile b/arch/arm/mach-aspeed/Makefile
+new file mode 100644
+index 0000000..ae63d8c
+--- /dev/null
++++ b/arch/arm/mach-aspeed/Makefile
+@@ -0,0 +1,22 @@
++#
++# Makefile for the linux kernel.
++#
++
++# Common support (must be linked before board specific support)
++
++# Specific board support
++obj-$(CONFIG_ARCH_AST1100) += ast1100.o
++obj-$(CONFIG_ARCH_AST2100) += ast2100.o
++obj-$(CONFIG_ARCH_AST2300) += ast2300.o gpio.o ast-lpc.o
++obj-$(CONFIG_ARCH_AST2400) += ast2400.o gpio.o ast-lpc.o ast-lpc_plus.o
++obj-$(CONFIG_ARCH_AST2500) += ast2500.o ast-mctp.o
++#PC Ext
++obj-$(CONFIG_ARCH_AST1510) += ast1510.o gpio.o
++obj-$(CONFIG_ARCH_AST1520) += ast1520.o ast-mctp.o
++
++#RemoteFx Zero client
++obj-$(CONFIG_ARCH_AST3100) += ast3100.o gpio.o
++obj-$(CONFIG_ARCH_AST3200) += ast3200.o ast-mctp.o
++
++#BMC Comapnion Controller
++obj-$(CONFIG_ARCH_AST1070) += ast1070.o
+diff --git a/arch/arm/mach-aspeed/Makefile.boot b/arch/arm/mach-aspeed/Makefile.boot
+new file mode 100644
+index 0000000..a1e3bf8
+--- /dev/null
++++ b/arch/arm/mach-aspeed/Makefile.boot
+@@ -0,0 +1,42 @@
++ifeq ($(CONFIG_ARCH_AST1510),y)
++ zreladdr-y := 0x40008000
++params_phys-y := 0x40000100
++initrd_phys-y := 0x40800000
++endif
++
++ifeq ($(CONFIG_ARCH_AST2300),y)
++ zreladdr-y := 0x40008000
++params_phys-y := 0x40000100
++initrd_phys-y := 0x40800000
++endif
++
++ifeq ($(CONFIG_ARCH_AST2400),y)
++ zreladdr-y := 0x40008000
++params_phys-y := 0x40000100
++initrd_phys-y := 0x40800000
++endif
++
++ifeq ($(CONFIG_ARCH_AST2500),y)
++ zreladdr-y := 0x80008000
++params_phys-y := 0x80000100
++initrd_phys-y := 0x80800000
++endif
++
++ifeq ($(CONFIG_ARCH_AST3100),y)
++ zreladdr-y := 0x40008000
++params_phys-y := 0x40000100
++initrd_phys-y := 0x40800000
++endif
++
++ifeq ($(CONFIG_ARCH_AST1520),y)
++ zreladdr-y := 0x80008000
++params_phys-y := 0x80000100
++initrd_phys-y := 0x80800000
++endif
++
++ifeq ($(CONFIG_ARCH_AST3200),y)
++ zreladdr-y := 0x80008000
++params_phys-y := 0x80000100
++initrd_phys-y := 0x80800000
++endif
++
+diff --git a/arch/arm/mach-aspeed/ast-lpc.c b/arch/arm/mach-aspeed/ast-lpc.c
+new file mode 100644
+index 0000000..b26e2cc
+--- /dev/null
++++ b/arch/arm/mach-aspeed/ast-lpc.c
+@@ -0,0 +1,423 @@
++/********************************************************************************
++* File Name : arch/arm/mach-aspeed/ast-lpc.c
++* Author : Ryan Chen
++* Description : AST LPC
++*
++* Copyright (C) 2012-2020 ASPEED Technology Inc.
++* This program is free software; you can redistribute it and/or modify
++* it under the terms of the GNU General Public License as published by the Free Software Foundation;
++* either version 2 of the License, or (at your option) any later version.
++* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
++* without even the implied warranty of MERCHANTABILITY or
++* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
++* You should have received a copy of the GNU General Public License
++* along with this program; if not, write to the Free Software
++* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++
++* History :
++* 1. 2013/05/15 Ryan Chen Create
++*
++********************************************************************************/
++#include <linux/platform_device.h>
++#include <linux/slab.h>
++
++#include <linux/kernel.h>
++#include <linux/module.h>
++#include <linux/delay.h>
++
++#include <mach/platform.h>
++#include <asm/io.h>
++#include <linux/interrupt.h>
++
++#include <mach/hardware.h>
++
++#include <plat/regs-lpc.h>
++#include <plat/ast-snoop.h>
++#include <plat/ast-lpc.h>
++#ifdef CONFIG_ARCH_AST1070
++#include <plat/ast1070-scu.h>
++#include <plat/ast1070-devs.h>
++#include <plat/regs-ast1070-intc.h>
++#include <plat/ast1070-uart-dma.h>
++#endif
++
++//#define AST_LPC_DEBUG
++
++#ifdef AST_LPC_DEBUG
++#define LPCDBUG(fmt, args...) printk("%s() " fmt, __FUNCTION__, ## args)
++#else
++#define LPCDBUG(fmt, args...)
++#endif
++
++#if 0
++static inline u32
++ast_lpc_read(u32 reg)
++{
++ u32 val;
++
++ val = readl(ast_lpc_base + reg);
++
++ LPCDBUG("ast_lpc_read : reg = 0x%08x, val = 0x%08x\n", reg, val);
++
++ return val;
++}
++
++static inline void
++ast_lpc_write(u32 val, u32 reg)
++{
++ LPCDBUG("ast_lpc_write : reg = 0x%08x, val = 0x%08x\n", reg, val);
++ writel(val, ast_lpc_base + reg);
++}
++
++/******************************************************************************/
++
++//Suppose you are going to snoop 0x80 ~ 0x87
++//snoop_init(0x80, 0x7, WORD_MODE, buf_dma, (SNOOP_DMA_BOUNDARY / 4)); //register in unit of DWORD
++#if 0
++extern void
++ast_lpc_snoop_dma_enable(u16 port_number, u8 port_mask, u8 mode, dma_addr_t dma_base, u16 size)
++{
++ write_register(0x1e789134, (port_mask << 16) + port_number);
++ write_register(0x1e7890d0, dma_base);
++ write_register(0x1e7890d4, (size - 1));
++ write_register(0x1e789130, (mode << 4) | ENABLE_DMA_INTERRUPT | ENABLE_POST_CODE_FUNCTION | ENABLE_SNOOP_DMA_MODE);
++
++ //Enable error interrupt to check LPC reset
++ write_register_or(0x1e789008, 1);
++
++}
++
++EXPORT_SYMBOL(ast_lpc_snoop_dma_init);
++#endif
++
++extern irqreturn_t ast_snoop_handler(int this_irq, void *dev_id)
++{
++ u32 snoop_sts;
++ struct ast_snoop *snoop = dev_id;
++
++ snoop_sts = ast_lpc_read(AST_LPC_HICR6);
++ if((snoop_sts & (LPC_HICR6_STR_SNP1W | LPC_HICR6_STR_SNP0W)) == 0)
++ return IRQ_NONE;
++
++ if(snoop_sts & LPC_HICR6_STR_SNP0W) {
++ snoop->snoop_ch0->snoop_data = GET_LPC_SNPD0(ast_lpc_read(AST_LPC_SNPWDR));
++ //clear
++ ast_lpc_write(LPC_HICR6_STR_SNP0W, AST_LPC_HICR6);
++ }
++
++ if(snoop_sts & LPC_HICR6_STR_SNP1W) {
++ snoop->snoop_ch1->snoop_data = GET_LPC_SNPD1(ast_lpc_read(AST_LPC_SNPWDR));
++ //clear
++ ast_lpc_write(LPC_HICR6_STR_SNP1W, AST_LPC_HICR6);
++
++ }
++
++ return IRQ_HANDLED;
++
++}
++EXPORT_SYMBOL(ast_snoop_handler);
++
++extern irqreturn_t ast_snoop_dma_handler(int this_irq, void *dev_id)
++{
++ u32 snoop_dma_sts, lpc_sts;
++ struct ast_snoop_dma_channel *snoop_dma_ch = dev_id;
++
++ snoop_dma_sts = ast_lpc_read(AST_LPC_PCCR2);
++
++ lpc_sts = ast_lpc_read(AST_LPC_HICR2);
++
++ printk("ISR : snoop_dma_sts = %x , lpc_sts = %x \n",snoop_dma_sts, lpc_sts);
++
++ if(lpc_sts & LPC_LRST) {
++ printk("LPC RST === > \n");
++ //clear fifo ??
++ ast_lpc_write(ast_lpc_read(AST_LPC_PCCR0) | LPC_RX_FIFO_CLR, AST_LPC_PCCR0);
++ //clear
++ ast_lpc_write(lpc_sts & ~LPC_LRST, AST_LPC_HICR2);
++
++ }
++
++ if(snoop_dma_sts & LPC_POST_CODE_DMA_RDY) {
++
++
++ }
++
++
++ return IRQ_HANDLED;
++
++}
++EXPORT_SYMBOL(ast_snoop_dma_handler);
++
++extern void ast_snoop_channel_int_enable(struct ast_snoop_channel *ast_ch, u8 enable)
++{
++ printk("ch[%d]int : %s , snoop port : %x",ast_ch->snoop_ch, enable? "Enable":"Disable", ast_ch->snoop_port);
++
++ if(enable) {
++ switch(ast_ch->snoop_ch) {
++ case 0:
++ //enable
++ ast_lpc_write(ast_lpc_read(AST_LPC_HICR5) | LPC_HICR5_SNP0INT_EN,
++ AST_LPC_HICR5);
++ break;
++ case 1:
++ //enable
++ ast_lpc_write(ast_lpc_read(AST_LPC_HICR5) | LPC_HICR5_SNP1INT_EN,
++ AST_LPC_HICR5);
++ break;
++ };
++
++ } else {
++ switch(ast_ch->snoop_ch) {
++ case 0:
++ //disable
++ ast_lpc_write(ast_lpc_read(AST_LPC_HICR5) & ~LPC_HICR5_SNP0INT_EN,
++ AST_LPC_HICR5);
++
++ break;
++ case 1:
++ //disable
++ ast_lpc_write(ast_lpc_read(AST_LPC_HICR5) & ~LPC_HICR5_SNP1INT_EN,
++ AST_LPC_HICR5);
++ };
++
++ }
++
++}
++EXPORT_SYMBOL(ast_snoop_channel_int_enable);
++
++extern void ast_snoop_channel_enable(struct ast_snoop_channel *ast_ch, u8 enable)
++{
++ printk("ch[%d] : %s , snoop port : %x",ast_ch->snoop_ch, enable? "Enable":"Disable", ast_ch->snoop_port);
++
++ if(enable) {
++ switch(ast_ch->snoop_ch) {
++ case 0:
++ //disable
++ ast_lpc_write(ast_lpc_read(AST_LPC_HICR5) & ~LPC_HICR5_SNP0W_EN,
++ AST_LPC_HICR5);
++
++ //set port address
++ ast_lpc_write((ast_lpc_read(AST_LPC_SNPWADR) & ~LPC_SNOOP_ADDR0_MASK) |
++ ast_ch->snoop_port,
++ AST_LPC_SNPWADR);
++ //enable
++ ast_lpc_write(ast_lpc_read(AST_LPC_HICR5) | LPC_HICR5_SNP0W_EN,
++ AST_LPC_HICR5);
++ break;
++ case 1:
++ //disable
++ ast_lpc_write(ast_lpc_read(AST_LPC_HICR5) & ~LPC_HICR5_SNP1W_EN,
++ AST_LPC_HICR5);
++
++ //set port address
++ ast_lpc_write((ast_lpc_read(AST_LPC_SNPWADR) & ~LPC_SNOOP_ADDR1_MASK) |
++ ast_ch->snoop_port,
++ AST_LPC_SNPWADR);
++ //enable
++ ast_lpc_write(ast_lpc_read(AST_LPC_HICR5) | LPC_HICR5_SNP1W_EN,
++ AST_LPC_HICR5);
++ break;
++ };
++
++ } else {
++ switch(ast_ch->snoop_ch) {
++ case 0:
++ //disable
++ ast_lpc_write(ast_lpc_read(AST_LPC_HICR5) & ~LPC_HICR5_SNP0W_EN,
++ AST_LPC_HICR5);
++
++ break;
++ case 1:
++ //disable
++ ast_lpc_write(ast_lpc_read(AST_LPC_HICR5) & ~LPC_HICR5_SNP1W_EN,
++ AST_LPC_HICR5);
++
++ };
++
++ }
++
++}
++EXPORT_SYMBOL(ast_snoop_channel_enable);
++
++extern void ast_snoop_dma_ch_enable(struct ast_snoop_dma_channel *ast_dma_ch, u8 enable)
++{
++ printk("ch[%d] : %s , snoop port : %x",ast_dma_ch->snoop_ch, enable? "Enable":"Disable", ast_dma_ch->snoop_port);
++
++ if(enable) {
++ //disable
++ ast_lpc_write(ast_lpc_read(AST_LPC_PCCR0) & ~LPC_POST_CODE_EN,
++ AST_LPC_PCCR0);
++
++ //set port address
++ ast_lpc_write((ast_lpc_read(AST_LPC_PCCR0) & ~LPC_POST_ADDR_MASK) |
++ LPC_CAPTURE_ADDR_MASK(ast_dma_ch->snoop_mask) |
++ LPC_CAPTURE_BASE_ADDR(ast_dma_ch->snoop_port),
++ AST_LPC_PCCR0);
++
++ ast_lpc_write(ast_dma_ch->dma_addr, AST_LPC_PCCR4);
++ ast_lpc_write(ast_dma_ch->dma_size - 1 , AST_LPC_PCCR5);
++
++ //enable
++ ast_lpc_write((ast_lpc_read(AST_LPC_PCCR0) & ~LPC_POST_CODE_MODE_MASK) |
++ LPC_POST_CODE_MODE(ast_dma_ch->snoop_mode) |
++ LPC_POST_DMA_MODE_EN |
++ LPC_POST_CODE_EN,
++ AST_LPC_PCCR0);
++
++ } else {
++ //disable
++ ast_lpc_write(ast_lpc_read(AST_LPC_PCCR0) & ~LPC_POST_CODE_EN,
++ AST_LPC_PCCR0);
++ }
++
++}
++EXPORT_SYMBOL(ast_snoop_dma_ch_enable);
++
++extern int ast_snoop_init(struct ast_snoop *snoop)
++{
++ int ret=0;
++
++ ast_snoop_channel_enable(snoop->snoop_ch0, 1);
++ ast_snoop_channel_enable(snoop->snoop_ch1, 1);
++ //request irq
++ ret = request_irq(IRQ_LPC, ast_snoop_handler, IRQF_SHARED,
++ "ast-snoop", snoop);
++
++ //enable irq
++ ast_lpc_write(ast_lpc_read(AST_LPC_HICR5) | LPC_HICR5_SNP0INT_EN | LPC_HICR5_SNP1INT_EN,
++ AST_LPC_HICR5);
++ return ret;
++}
++EXPORT_SYMBOL(ast_snoop_init);
++
++extern void ast_snoop_dma_init(struct ast_snoop_dma_channel *ast_dma_ch)
++{
++ int ret=0;
++
++ ast_snoop_dma_ch_enable(ast_dma_ch, 1);
++
++ //request irq
++ ret = request_irq(IRQ_LPC, ast_snoop_dma_handler, IRQF_SHARED,
++ "ast-snoop", ast_dma_ch);
++
++ //enable irq
++ ast_lpc_write(ast_lpc_read(AST_LPC_PCCR0) |
++ LPC_POST_DMA_INT_EN,
++ AST_LPC_PCCR0);
++
++ return ret;
++
++}
++EXPORT_SYMBOL(ast_snoop_dma_init);
++#endif
++static struct ast_lpc_driver_data *lpc_driver_data;
++
++static int __devinit ast_lpc_probe(struct platform_device *pdev)
++{
++// const struct platform_device_id *id = platform_get_device_id(pdev);
++ struct resource *res;
++ int ret = 0;
++ int i;
++
++ lpc_driver_data = kzalloc(sizeof(struct ast_lpc_driver_data), GFP_KERNEL);
++ if (lpc_driver_data == NULL) {
++ dev_err(&pdev->dev, "failed to allocate memory\n");
++ return -ENOMEM;
++ }
++
++ lpc_driver_data->pdev = pdev;
++
++ lpc_driver_data->bus_info = pdev->dev.platform_data;
++
++ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
++ if (res == NULL) {
++ dev_err(&pdev->dev, "no memory resource defined\n");
++ ret = -ENODEV;
++ goto err_free;
++ }
++
++ res = request_mem_region(res->start, resource_size(res), pdev->name);
++ if (res == NULL) {
++ dev_err(&pdev->dev, "failed to request memory resource\n");
++ ret = -EBUSY;
++ goto err_free;
++ }
++
++ lpc_driver_data->reg_base = ioremap(res->start, resource_size(res));
++ if (lpc_driver_data->reg_base == NULL) {
++ dev_err(&pdev->dev, "failed to ioremap() registers\n");
++ ret = -ENODEV;
++ goto err_free_mem;
++ }
++
++#ifdef CONFIG_ARCH_AST1070
++ if(lpc_driver_data->bus_info->bus_scan) {
++ printk("LPC Scan Device... \n");
++ for(i=0;i<lpc_driver_data->bus_info->scan_node;i++) {
++ ast1070_scu_init(i ,lpc_driver_data->bus_info->bridge_phy_addr + i*0x10000);
++ printk("C%d-[%x] ", i, ast1070_revision_id_info(i));
++ ast1070_vic_init(i, (lpc_driver_data->bus_info->bridge_phy_addr + i*0x10000), IRQ_C0_VIC_CHAIN + i, IRQ_C0_VIC_CHAIN_START + (i*AST_CVIC_NUM));
++ ast1070_scu_dma_init(i);
++ ast1070_uart_dma_init(i, lpc_driver_data->bus_info->bridge_phy_addr);
++ ast_add_device_cuart(i,lpc_driver_data->bus_info->bridge_phy_addr + i*0x10000);
++ ast_add_device_ci2c(i,lpc_driver_data->bus_info->bridge_phy_addr + i*0x10000);
++ }
++ printk("\n");
++
++ }
++
++#endif
++
++ platform_set_drvdata(pdev, lpc_driver_data);
++ return 0;
++
++err_free_mem:
++ release_mem_region(res->start, resource_size(res));
++err_free:
++ kfree(lpc_driver_data);
++
++ return ret;
++}
++
++static int __devexit ast_lpc_remove(struct platform_device *pdev)
++{
++ struct ast_lpc_driver_data *lpc_driver_data;
++ struct resource *res;
++
++ lpc_driver_data = platform_get_drvdata(pdev);
++ if (lpc_driver_data == NULL)
++ return -ENODEV;
++
++ iounmap(lpc_driver_data->reg_base);
++
++ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
++ release_mem_region(res->start, resource_size(res));
++
++ kfree(lpc_driver_data);
++
++ return 0;
++}
++
++static struct platform_driver ast_lpc_driver = {
++ .driver = {
++ .name = "ast_lpc",
++ .owner = THIS_MODULE,
++ },
++ .probe = ast_lpc_probe,
++ .remove = __devexit_p(ast_lpc_remove),
++// .id_table = pwm_id_table,
++};
++
++static int __init ast_lpc_init(void)
++{
++ return platform_driver_register(&ast_lpc_driver);
++}
++arch_initcall(ast_lpc_init);
++
++static void __exit ast_lpc_exit(void)
++{
++ platform_driver_unregister(&ast_lpc_driver);
++}
++module_exit(ast_lpc_exit);
++
++MODULE_LICENSE("GPL v2");
+diff --git a/arch/arm/mach-aspeed/ast-lpc_plus.c b/arch/arm/mach-aspeed/ast-lpc_plus.c
+new file mode 100644
+index 0000000..187b8b8
+--- /dev/null
++++ b/arch/arm/mach-aspeed/ast-lpc_plus.c
+@@ -0,0 +1,182 @@
++/********************************************************************************
++* File Name : arch/arm/mach-aspeed/ast-lpc_plus.c
++* Author : Ryan Chen
++* Description : AST LPC
++*
++* Copyright (C) 2012-2020 ASPEED Technology Inc.
++* This program is free software; you can redistribute it and/or modify
++* it under the terms of the GNU General Public License as published by the Free Software Foundation;
++* either version 2 of the License, or (at your option) any later version.
++* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
++* without even the implied warranty of MERCHANTABILITY or
++* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
++* You should have received a copy of the GNU General Public License
++* along with this program; if not, write to the Free Software
++* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++
++* History :
++* 1. 2013/05/15 Ryan Chen Create
++*
++********************************************************************************/
++#include <linux/platform_device.h>
++#include <linux/slab.h>
++
++#include <linux/kernel.h>
++#include <linux/module.h>
++#include <linux/delay.h>
++
++#include <mach/platform.h>
++#include <asm/io.h>
++#include <linux/interrupt.h>
++
++#include <mach/hardware.h>
++
++#include <plat/regs-lpc.h>
++#include <plat/ast-snoop.h>
++#include <plat/ast-lpc.h>
++#ifdef CONFIG_ARCH_AST1070
++#include <plat/ast1070-scu.h>
++#include <plat/ast1070-devs.h>
++#include <plat/regs-ast1070-intc.h>
++#include <plat/ast1070-uart-dma.h>
++#endif
++
++//#define AST_LPCP_DEBUG
++
++#ifdef AST_LPCP_DEBUG
++#define LPCP_DBUG(fmt, args...) printk("%s() " fmt, __FUNCTION__, ## args)
++#else
++#define LPCP_DBUG(fmt, args...)
++#endif
++
++#if 0
++static inline u32
++ast_lpc_plus_write(u32 reg)
++{
++ u32 val;
++
++ val = readl(ast_lpc_base + reg);
++
++ LPCDBUG("ast_lpc_read : reg = 0x%08x, val = 0x%08x\n", reg, val);
++
++ return val;
++}
++
++static inline void
++ast_lpc_plus_write(u32 val, u32 reg)
++{
++ LPCDBUG("ast_lpc_write : reg = 0x%08x, val = 0x%08x\n", reg, val);
++ writel(val, ast_lpc_base + reg);
++}
++#endif
++
++static int __devinit ast_lpc_plus_probe(struct platform_device *pdev)
++{
++ static struct ast_lpc_driver_data *lpc_plus_driver_data;
++// const struct platform_device_id *id = platform_get_device_id(pdev);
++ struct resource *res;
++ int ret = 0;
++ int i;
++
++ lpc_plus_driver_data = kzalloc(sizeof(struct ast_lpc_driver_data), GFP_KERNEL);
++ if (lpc_plus_driver_data == NULL) {
++ dev_err(&pdev->dev, "failed to allocate memory\n");
++ return -ENOMEM;
++ }
++
++ lpc_plus_driver_data->pdev = pdev;
++
++ lpc_plus_driver_data->bus_info = pdev->dev.platform_data;
++
++ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
++ if (res == NULL) {
++ dev_err(&pdev->dev, "no memory resource defined\n");
++ ret = -ENODEV;
++ goto err_free;
++ }
++
++ res = request_mem_region(res->start, resource_size(res), pdev->name);
++ if (res == NULL) {
++ dev_err(&pdev->dev, "failed to request memory resource\n");
++ ret = -EBUSY;
++ goto err_free;
++ }
++
++ lpc_plus_driver_data->reg_base = ioremap(res->start, resource_size(res));
++ if (lpc_plus_driver_data->reg_base == NULL) {
++ dev_err(&pdev->dev, "failed to ioremap() registers\n");
++ ret = -ENODEV;
++ goto err_free_mem;
++ }
++
++#ifdef CONFIG_ARCH_AST1070
++ if(lpc_plus_driver_data->bus_info->bus_scan) {
++ printk("LPC PLUS Scan Device... ");
++ for(i=0;i<lpc_plus_driver_data->bus_info->scan_node;i++) {
++ ast1070_scu_init(i ,lpc_plus_driver_data->bus_info->bridge_phy_addr + i*0x10000);
++ printk("C%d-[%x] ", i, ast1070_revision_id_info(i));
++ ast1070_vic_init(i, (lpc_plus_driver_data->bus_info->bridge_phy_addr + i*0x10000), IRQ_C0_VIC_CHAIN + i, IRQ_C0_VIC_CHAIN_START + (i*AST_CVIC_NUM));
++ ast1070_scu_dma_init(i);
++ ast1070_uart_dma_init(i, lpc_plus_driver_data->bus_info->bridge_phy_addr);
++ ast_add_device_cuart(i,lpc_plus_driver_data->bus_info->bridge_phy_addr + i*0x10000);
++ ast_add_device_ci2c(i,lpc_plus_driver_data->bus_info->bridge_phy_addr + i*0x10000);
++ }
++ printk("\n");
++
++ }
++
++#endif
++
++ platform_set_drvdata(pdev, lpc_plus_driver_data);
++ return 0;
++
++err_free_mem:
++ release_mem_region(res->start, resource_size(res));
++err_free:
++ kfree(lpc_plus_driver_data);
++
++ return ret;
++}
++
++static int __devexit ast_lpc_plus_remove(struct platform_device *pdev)
++{
++ struct ast_lpc_driver_data *lpc_plus_driver_data;
++ struct resource *res;
++
++ lpc_plus_driver_data = platform_get_drvdata(pdev);
++ if (lpc_plus_driver_data == NULL)
++ return -ENODEV;
++
++ iounmap(lpc_plus_driver_data->reg_base);
++
++ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
++ release_mem_region(res->start, resource_size(res));
++
++ kfree(lpc_plus_driver_data);
++
++ return 0;
++}
++
++static struct platform_driver ast_lpc_plus_driver = {
++ .driver = {
++ .name = "ast_lpc_plus",
++ .owner = THIS_MODULE,
++ },
++ .probe = ast_lpc_plus_probe,
++ .remove = __devexit_p(ast_lpc_plus_remove),
++// .id_table = pwm_id_table,
++};
++
++static int __init ast_lpc_plus_init(void)
++{
++ return platform_driver_register(&ast_lpc_plus_driver);
++}
++arch_initcall(ast_lpc_plus_init);
++
++static void __exit ast_lpc_plus_exit(void)
++{
++ platform_driver_unregister(&ast_lpc_plus_driver);
++}
++module_exit(ast_lpc_plus_exit);
++
++MODULE_LICENSE("GPL v2");
+diff --git a/arch/arm/mach-aspeed/ast-mctp.c b/arch/arm/mach-aspeed/ast-mctp.c
+new file mode 100644
+index 0000000..1dd746b
+--- /dev/null
++++ b/arch/arm/mach-aspeed/ast-mctp.c
+@@ -0,0 +1,153 @@
++/********************************************************************************
++* File Name : arch/arm/mach-aspeed/ast-mctp.c
++* Author : Ryan Chen
++* Description : AST MCTP Ctrl
++*
++* Copyright (C) 2012-2020 ASPEED Technology Inc.
++* This program is free software; you can redistribute it and/or modify
++* it under the terms of the GNU General Public License as published by the Free Software Foundation;
++* either version 2 of the License, or (at your option) any later version.
++* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
++* without even the implied warranty of MERCHANTABILITY or
++* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
++* You should have received a copy of the GNU General Public License
++* along with this program; if not, write to the Free Software
++* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++
++
++* History :
++* 1. 2013/07/15 Ryan Chen Create
++*
++********************************************************************************/
++#include <linux/kernel.h>
++#include <linux/module.h>
++#include <linux/delay.h>
++
++#include <mach/platform.h>
++#include <asm/io.h>
++
++#include <mach/hardware.h>
++#include <plat/regs-mctp.h>
++#include <plat/ast_mctp.h>
++
++//#define AST_MCTP_DEBUG 1
++
++#ifdef AST_MCTP_DEBUG
++#define MCTPDBUG(fmt, args...) printk("%s() " fmt, __FUNCTION__, ## args)
++#else
++#define MCTPDBUG(fmt, args...)
++#endif
++
++static u32 ast_mctp_base = 0;
++static u8 txTag = 0;
++static inline u32
++ast_mctp_read(u32 reg)
++{
++ u32 val;
++
++ val = readl(ast_mctp_base + reg);
++
++ MCTPDBUG("reg = 0x%08x, val = 0x%08x\n", reg, val);
++
++ return val;
++}
++
++static inline void
++ast_mctp_write(u32 val, u32 reg)
++{
++ MCTPDBUG("reg = 0x%08x, val = 0x%08x\n", reg, val);
++
++ writel(val, ast_mctp_base + reg);
++}
++
++//***********************************Information ***********************************
++
++extern void ast_pcie_cfg_read(u8 type, u32 bdf_offset, u32 *value)
++{
++ u32 timeout =0;
++ u32 desc3,desc2;
++ txTag %= 0xf;
++// printf("type = %d, busfunc = %x \n",type, bdf);
++ if((ast_mctp_read(AST_MCTP_INT) & MCTP_RX_COMPLETE) != 0)
++ printk("EEEEEEEE \n");
++
++ ast_mctp_write(0x4000001 | (type << 24), AST_MCTP_TX_DESC3);
++ ast_mctp_write(0x200f | (txTag << 8), AST_MCTP_TX_DESC2);
++ ast_mctp_write(bdf_offset, AST_MCTP_TX_DESC1);
++ ast_mctp_write(0, AST_MCTP_TX_DESC0);
++// ast_mctp_write(0, AST_MCTP_TX_DATA);
++
++ //trigger
++ ast_mctp_write(7, AST_MCTP_CTRL);
++ //wait
++// printf("trigger \n");
++ while(!(ast_mctp_read(AST_MCTP_INT) & MCTP_RX_COMPLETE)) {
++ timeout++;
++ if(timeout > 10000) {
++ printk("time out \n");
++ *value = 0xffffffff;
++ goto out;
++ }
++ };
++
++ //read
++ desc3 = ast_mctp_read(AST_MCTP_RX_DESC3);
++ desc2 = ast_mctp_read(AST_MCTP_RX_DESC2);
++ ast_mctp_read(AST_MCTP_RX_DESC1);
++
++ if( ((desc3 >> 24) == 0x4A) &&
++ ((desc3 & 0xfff) == 0x1) &&
++ ((desc2 & 0xe000) == 0)) {
++ *value = ast_mctp_read(AST_MCTP_RX_DATA);
++
++ } else {
++ *value = 0xffffffff;
++
++ }
++
++out:
++ txTag++;
++ ast_mctp_write(0x15, AST_MCTP_CTRL);
++ ast_mctp_write(0x3, AST_MCTP_INT);
++ //wait
++ while(ast_mctp_read(AST_MCTP_INT) & MCTP_RX_COMPLETE);
++
++}
++
++extern void ast_pcie_cfg_write(u8 type, u32 bdf_offset, u32 data)
++{
++ txTag %= 0xf;
++
++ ast_mctp_write(0x44000001 | (type << 24), AST_MCTP_TX_DESC3);
++ ast_mctp_write(0x200f | (txTag << 8), AST_MCTP_TX_DESC2);
++ ast_mctp_write(bdf_offset, AST_MCTP_TX_DESC1);
++ ast_mctp_write(0, AST_MCTP_TX_DESC0);
++ ast_mctp_write(data, AST_MCTP_TX_DATA);
++
++ //trigger
++ ast_mctp_write(7, AST_MCTP_CTRL);
++// printf("trigger \n");
++ //wait
++ while(!(ast_mctp_read(AST_MCTP_INT) & MCTP_RX_COMPLETE));
++
++ //read
++ ast_mctp_read(AST_MCTP_RX_DESC3);
++ ast_mctp_read(AST_MCTP_RX_DESC2);
++ ast_mctp_read(AST_MCTP_RX_DESC1);
++ txTag++;
++ ast_mctp_write(0x15, AST_MCTP_CTRL);
++ ast_mctp_write(0x3, AST_MCTP_INT);
++ //wait
++ while(ast_mctp_read(AST_MCTP_INT) & MCTP_RX_COMPLETE);
++
++}
++
++static int __init ast_mctp_init(void)
++{
++ MCTPDBUG("\n");
++ ast_mctp_base = (u32)ioremap(AST_MCTP_BASE , SZ_256);
++ return 0;
++}
++
++subsys_initcall(ast_mctp_init);
++
+diff --git a/arch/arm/mach-aspeed/ast1070.c b/arch/arm/mach-aspeed/ast1070.c
+new file mode 100644
+index 0000000..12ede8b
+--- /dev/null
++++ b/arch/arm/mach-aspeed/ast1070.c
+@@ -0,0 +1,60 @@
++/*
++ * linux/arch/arm/mach-ast1070/ast1070.c
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++ */
++//#include <linux/config.h>
++#include <linux/types.h>
++#include <linux/sched.h>
++#include <linux/interrupt.h>
++#include <linux/init.h>
++#include <asm/mach/arch.h>
++#include <asm/mach/map.h>
++#include <plat/devs.h>
++#include <plat/ast1070-scu.h>
++#include <plat/ast1070-uart-dma.h>
++#include <mach/time.h>
++#include <mach/gpio.h>
++
++static int __init ast1070_init(void)
++{
++ int i=0;
++ u8 num = 0;
++ if(gpio_get_value(PIN_GPIOI2))
++ num = 2; //dual 1070
++ else
++ num = 1; //single 1070
++
++ if(CONFIG_AST1070_NR != num)
++ printk("Please check Configuration !!! \n");
++
++#if 0
++ if(gpio_get_value(PIN_GPIOI1))
++ printk("Use LPC+ Bus Access \n");
++ else
++ printk("Use LPC Bus Access \n");
++#endif
++
++ for(i=0; i< CONFIG_AST1070_NR;i++) {
++ ast1070_scu_revision_id(i);
++ ast1070_dma_init(i);
++ ast1070_uart_dma_init(i);
++ }
++
++ return 0;
++}
++
++subsys_initcall(ast1070_init);
++
+diff --git a/arch/arm/mach-aspeed/ast1100.c b/arch/arm/mach-aspeed/ast1100.c
+new file mode 100644
+index 0000000..e2629f1
+--- /dev/null
++++ b/arch/arm/mach-aspeed/ast1100.c
+@@ -0,0 +1,49 @@
++/*
++ * linux/arch/arm/mach-ast2000/ast2000.c
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++ */
++//#include <linux/config.h>
++#include <linux/types.h>
++#include <linux/sched.h>
++#include <linux/interrupt.h>
++#include <linux/init.h>
++
++#include <mach/hardware.h>
++#include <asm/irq.h>
++#include <asm/setup.h>
++#include <asm/mach-types.h>
++
++#include <asm/mach/arch.h>
++#include <mach/time.h>
++
++extern void aspeed_map_io(void);
++extern void aspeed_init_irq(void);
++extern struct sys_timer aspeed_timer;
++
++static void __init aspeed_init(void)
++{
++ ast_add_all_devices();
++}
++
++MACHINE_START(ASPEED, "AST1100")
++ .phys_io = ASPEED_IO_START,
++// .phys_ram = ASPEED_SDRAM_BASE,
++ .io_pg_offst = (IO_ADDRESS(IO_START)>>18) & 0xfffc,
++ .map_io = aspeed_map_io,
++ .timer = &aspeed_timer,
++ .init_irq = aspeed_init_irq,
++ .init_machine = aspeed_init,
++MACHINE_END
+diff --git a/arch/arm/mach-aspeed/ast2100.c b/arch/arm/mach-aspeed/ast2100.c
+new file mode 100644
+index 0000000..06da653
+--- /dev/null
++++ b/arch/arm/mach-aspeed/ast2100.c
+@@ -0,0 +1,49 @@
++/*
++ * linux/arch/arm/mach-ast2100/ast2100.c
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++ */
++//#include <linux/config.h>
++#include <linux/types.h>
++#include <linux/sched.h>
++#include <linux/interrupt.h>
++#include <linux/init.h>
++
++#include <mach/hardware.h>
++#include <asm/irq.h>
++#include <asm/setup.h>
++#include <asm/mach-types.h>
++
++#include <asm/mach/arch.h>
++#include <mach/time.h>
++
++extern void aspeed_map_io(void);
++extern void aspeed_init_irq(void);
++extern struct sys_timer aspeed_timer;
++
++static void __init aspeed_init(void)
++{
++ ast_add_all_devices();
++}
++
++MACHINE_START(ASPEED, "AST1100")
++ .phys_io = ASPEED_IO_START,
++// .phys_ram = ASPEED_SDRAM_BASE,
++ .io_pg_offst = (IO_ADDRESS(IO_START)>>18) & 0xfffc,
++ .map_io = aspeed_map_io,
++ .timer = &aspeed_timer,
++ .init_irq = aspeed_init_irq,
++ .init_machine = aspeed_init,
++MACHINE_END
+diff --git a/arch/arm/mach-aspeed/ast2300.c b/arch/arm/mach-aspeed/ast2300.c
+new file mode 100644
+index 0000000..a223d74
+--- /dev/null
++++ b/arch/arm/mach-aspeed/ast2300.c
+@@ -0,0 +1,206 @@
++/*
++ * linux/arch/arm/mach-ast2300/ast2300.c
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++ */
++#include <linux/types.h>
++#include <linux/kernel.h>
++#include <linux/init.h>
++#include <linux/list.h>
++#include <linux/slab.h>
++#include <linux/string.h>
++#include <linux/sysdev.h>
++#include <asm/mach-types.h>
++#include <asm/mach/irq.h>
++#include <asm/mach/arch.h>
++#include <asm/mach/map.h>
++#include <mach/time.h>
++#include <mach/hardware.h>
++#include <plat/devs.h>
++
++#include "core.h"
++
++static struct map_desc ast_io_desc[] __initdata = {
++ {
++ .virtual = IO_ADDRESS(AST_VIC_BASE),
++ .pfn = __phys_to_pfn(AST_VIC_BASE),
++ .length = SZ_64K,
++ .type = MT_DEVICE,
++ }, {
++ .virtual = IO_ADDRESS(AST_SCU_BASE),
++ .pfn = __phys_to_pfn(AST_SCU_BASE),
++ .length = SZ_4K,
++ .type = MT_DEVICE,
++ }, {
++ .virtual = IO_ADDRESS(AST_SDMC_BASE),
++ .pfn = __phys_to_pfn(AST_SDMC_BASE),
++ .length = SZ_4K,
++ .type = MT_DEVICE,
++ }, {
++ .virtual = IO_ADDRESS(AST_MAC0_BASE),
++ .pfn = __phys_to_pfn(AST_MAC0_BASE),
++ .length = SZ_64K,
++ .type = MT_DEVICE,
++ }, {
++ .virtual = IO_ADDRESS(AST_MAC1_BASE),
++ .pfn = __phys_to_pfn(AST_MAC1_BASE),
++ .length = SZ_64K,
++ .type = MT_DEVICE,
++ }, {
++ .virtual = IO_ADDRESS(AST_CRYPTO_BASE),
++ .pfn = __phys_to_pfn(AST_CRYPTO_BASE),
++ .length = SZ_4K,
++ .type = MT_DEVICE,
++ }, {
++ .virtual = IO_ADDRESS(AST_XDMA_BASE),
++ .pfn = __phys_to_pfn(AST_XDMA_BASE),
++ .length = SZ_4K,
++ .type = MT_DEVICE,
++ }, {
++ .virtual = IO_ADDRESS(AST_MCTP_BASE),
++ .pfn = __phys_to_pfn(AST_MCTP_BASE),
++ .length = SZ_4K,
++ .type = MT_DEVICE,
++ }, {
++ .virtual = IO_ADDRESS(AST_SRAM_BASE),
++ .pfn = __phys_to_pfn(AST_SRAM_BASE),
++ .length = SZ_64K,
++ .type = MT_DEVICE,
++ }, {
++ .virtual = IO_ADDRESS(AST_2D_BASE),
++ .pfn = __phys_to_pfn(AST_2D_BASE),
++ .length = SZ_64K,
++ .type = MT_DEVICE,
++ }, {
++ .virtual = IO_ADDRESS(AST_GPIO_BASE),
++ .pfn = __phys_to_pfn(AST_GPIO_BASE),
++ .length = SZ_4K,
++ .type = MT_DEVICE,
++ }, {
++ .virtual = IO_ADDRESS(AST_TIMER_BASE),
++ .pfn = __phys_to_pfn(AST_TIMER_BASE),
++ .length = SZ_4K,
++ .type = MT_DEVICE,
++ }, {
++ .virtual = IO_ADDRESS(AST_UART0_BASE),
++ .pfn = __phys_to_pfn(AST_UART0_BASE),
++ .length = SZ_4K,
++ .type = MT_DEVICE,
++ }, {
++ .virtual = IO_ADDRESS(AST_UART4_BASE),
++ .pfn = __phys_to_pfn(AST_UART4_BASE),
++ .length = SZ_4K,
++ .type = MT_DEVICE,
++ }, {
++ .virtual = IO_ADDRESS(AST_WDT_BASE),
++ .pfn = __phys_to_pfn(AST_WDT_BASE),
++ .length = SZ_4K,
++ .type = MT_DEVICE,
++ }, {
++ .virtual = IO_ADDRESS(AST_VUART0_BASE),
++ .pfn = __phys_to_pfn(AST_VUART0_BASE),
++ .length = SZ_1K,
++ .type = MT_DEVICE,
++ }, {
++ .virtual = IO_ADDRESS(AST_PUART_BASE),
++ .pfn = __phys_to_pfn(AST_PUART_BASE),
++ .length = SZ_4K,
++ .type = MT_DEVICE,
++ }, {
++ .virtual = IO_ADDRESS(AST_LPC_BASE),
++ .pfn = __phys_to_pfn(AST_LPC_BASE),
++ .length = SZ_4K,
++ .type = MT_DEVICE,
++ }, {
++ .virtual = IO_ADDRESS(AST_PECI_BASE),
++ .pfn = __phys_to_pfn(AST_PECI_BASE),
++ .length = SZ_4K,
++ .type = MT_DEVICE,
++ }, {
++#if defined(CONFIG_ARCH_AST1070)
++ .virtual = IO_ADDRESS2(AST_C0_VIC_BASE),
++ .pfn = __phys_to_pfn(AST_C0_VIC_BASE),
++ .length = SZ_1K,
++ .type = MT_DEVICE,
++ }, {
++ .virtual = IO_ADDRESS2(AST_C0_SCU_BASE),
++ .pfn = __phys_to_pfn(AST_C0_SCU_BASE),
++ .length = SZ_1K,
++ .type = MT_DEVICE,
++ }, {
++ .virtual = IO_ADDRESS2(AST_C0_I2C_BASE),
++ .pfn = __phys_to_pfn(AST_C0_I2C_BASE),
++ .length = SZ_1K,
++ .type = MT_DEVICE,
++ }, {
++ .virtual = IO_ADDRESS2(AST_C0_UART0_BASE),
++ .pfn = __phys_to_pfn(AST_C0_UART0_BASE),
++ .length = SZ_1K,
++ .type = MT_DEVICE,
++ }, {
++ .virtual = IO_ADDRESS2(AST_C0_UART1_BASE),
++ .pfn = __phys_to_pfn(AST_C0_UART0_BASE),
++ .length = SZ_1K,
++ .type = MT_DEVICE,
++ }, {
++ .virtual = IO_ADDRESS2(AST_C0_UART2_BASE),
++ .pfn = __phys_to_pfn(AST_C0_UART0_BASE),
++ .length = SZ_1K,
++ .type = MT_DEVICE,
++ }, {
++ .virtual = IO_ADDRESS2(AST_C0_UART3_BASE),
++ .pfn = __phys_to_pfn(AST_C0_UART0_BASE),
++
++ .length = SZ_1K,
++ .type = MT_DEVICE,
++ }, {
++#endif
++ .virtual = IO_ADDRESS(AST_UART1_BASE),
++ .pfn = __phys_to_pfn(AST_UART1_BASE),
++ .length = SZ_4K,
++ .type = MT_DEVICE,
++ }, {
++ .virtual = IO_ADDRESS(AST_UART2_BASE),
++ .pfn = __phys_to_pfn(AST_UART2_BASE),
++ .length = SZ_4K,
++ .type = MT_DEVICE,
++ }, {
++ .virtual = IO_ADDRESS(AST_UART3_BASE),
++ .pfn = __phys_to_pfn(AST_UART3_BASE),
++ .length = SZ_4K,
++ .type = MT_DEVICE,
++ },
++};
++
++void __init ast_map_io(void)
++{
++ iotable_init(ast_io_desc, ARRAY_SIZE(ast_io_desc));
++}
++
++static void __init ast_init(void)
++{
++ ast_add_all_devices();
++}
++
++MACHINE_START(ASPEED, "AST2300")
++ .phys_io = AST_IO_START,
++// .phys_ram = AST_SDRAM_BASE,
++ .io_pg_offst = (IO_ADDRESS(AST_IO_START)>>18) & 0xfffc,
++ .boot_params = 0x40000100,
++ .map_io = ast_map_io,
++ .timer = &ast_timer,
++ .init_irq = ast_init_irq,
++ .init_machine = ast_init,
++MACHINE_END
+diff --git a/arch/arm/mach-aspeed/ast2400.c b/arch/arm/mach-aspeed/ast2400.c
+new file mode 100644
+index 0000000..3567d3c
+--- /dev/null
++++ b/arch/arm/mach-aspeed/ast2400.c
+@@ -0,0 +1,255 @@
++/*
++ * linux/arch/arm/mach-ast2300/ast2300.c
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++ */
++#include <linux/types.h>
++#include <linux/kernel.h>
++#include <linux/init.h>
++#include <linux/list.h>
++#include <linux/slab.h>
++#include <linux/string.h>
++#include <linux/sysdev.h>
++#include <asm/mach-types.h>
++#include <asm/mach/irq.h>
++#include <asm/mach/arch.h>
++#include <asm/mach/map.h>
++#include <mach/time.h>
++#include <mach/hardware.h>
++#include <plat/devs.h>
++
++#include "core.h"
++
++static struct map_desc ast_io_desc[] __initdata = {
++ {
++ .virtual = IO_ADDRESS(AST_VIC_BASE),
++ .pfn = __phys_to_pfn(AST_VIC_BASE),
++ .length = SZ_64K,
++ .type = MT_DEVICE,
++ }, {
++ .virtual = IO_ADDRESS(AST_SCU_BASE),
++ .pfn = __phys_to_pfn(AST_SCU_BASE),
++ .length = SZ_4K,
++ .type = MT_DEVICE,
++ }, {
++ .virtual = IO_ADDRESS(AST_SDMC_BASE),
++ .pfn = __phys_to_pfn(AST_SDMC_BASE),
++ .length = SZ_4K,
++ .type = MT_DEVICE,
++ }, {
++ .virtual = IO_ADDRESS(AST_VIDEO_BASE),
++ .pfn = __phys_to_pfn(AST_VIDEO_BASE),
++ .length = SZ_4K,
++ .type = MT_DEVICE,
++ }, {
++ .virtual = IO_ADDRESS(AST_MAC0_BASE),
++ .pfn = __phys_to_pfn(AST_MAC0_BASE),
++ .length = SZ_64K,
++ .type = MT_DEVICE,
++ }, {
++ .virtual = IO_ADDRESS(AST_MAC1_BASE),
++ .pfn = __phys_to_pfn(AST_MAC1_BASE),
++ .length = SZ_64K,
++ .type = MT_DEVICE,
++ }, {
++ .virtual = IO_ADDRESS(AST_CRYPTO_BASE),
++ .pfn = __phys_to_pfn(AST_CRYPTO_BASE),
++ .length = SZ_4K,
++ .type = MT_DEVICE,
++ }, {
++ .virtual = IO_ADDRESS(AST_JTAG_BASE),
++ .pfn = __phys_to_pfn(AST_JTAG_BASE),
++ .length = SZ_4K,
++ .type = MT_DEVICE,
++ }, {
++ .virtual = IO_ADDRESS(AST_XDMA_BASE),
++ .pfn = __phys_to_pfn(AST_XDMA_BASE),
++ .length = SZ_4K,
++ .type = MT_DEVICE,
++ }, {
++ .virtual = IO_ADDRESS(AST_MCTP_BASE),
++ .pfn = __phys_to_pfn(AST_MCTP_BASE),
++ .length = SZ_4K,
++ .type = MT_DEVICE,
++ }, {
++ .virtual = IO_ADDRESS(AST_SRAM_BASE),
++ .pfn = __phys_to_pfn(AST_SRAM_BASE),
++ .length = SZ_16K*2,
++ .type = MT_DEVICE,
++ }, {
++ .virtual = IO_ADDRESS(AST_2D_BASE),
++ .pfn = __phys_to_pfn(AST_2D_BASE),
++ .length = SZ_64K,
++ .type = MT_DEVICE,
++ }, {
++ .virtual = IO_ADDRESS(AST_GPIO_BASE),
++ .pfn = __phys_to_pfn(AST_GPIO_BASE),
++ .length = SZ_4K,
++ .type = MT_DEVICE,
++ }, {
++ .virtual = IO_ADDRESS(AST_TIMER_BASE),
++ .pfn = __phys_to_pfn(AST_TIMER_BASE),
++ .length = SZ_4K,
++ .type = MT_DEVICE,
++ }, {
++ .virtual = IO_ADDRESS(AST_UART0_BASE),
++ .pfn = __phys_to_pfn(AST_UART0_BASE),
++ .length = SZ_4K,
++ .type = MT_DEVICE,
++ }, {
++ .virtual = IO_ADDRESS(AST_UART4_BASE),
++ .pfn = __phys_to_pfn(AST_UART4_BASE),
++ .length = SZ_4K,
++ .type = MT_DEVICE,
++ }, {
++ .virtual = IO_ADDRESS(AST_WDT_BASE),
++ .pfn = __phys_to_pfn(AST_WDT_BASE),
++ .length = SZ_4K,
++ .type = MT_DEVICE,
++ }, {
++ .virtual = IO_ADDRESS(AST_UDC11_BASE ),
++ .pfn = __phys_to_pfn(AST_UDC11_BASE),
++ .length = SZ_1K,
++ .type = MT_DEVICE,
++ }, {
++ .virtual = IO_ADDRESS(AST_VUART0_BASE),
++ .pfn = __phys_to_pfn(AST_VUART0_BASE),
++ .length = SZ_1K,
++ .type = MT_DEVICE,
++ }, {
++ .virtual = IO_ADDRESS(AST_PUART_BASE),
++ .pfn = __phys_to_pfn(AST_PUART_BASE),
++ .length = SZ_4K,
++ .type = MT_DEVICE,
++ }, {
++ .virtual = IO_ADDRESS(AST_LPC_BASE),
++ .pfn = __phys_to_pfn(AST_LPC_BASE),
++ .length = SZ_4K,
++ .type = MT_DEVICE,
++ }, {
++ .virtual = IO_ADDRESS(AST_PECI_BASE),
++ .pfn = __phys_to_pfn(AST_PECI_BASE),
++ .length = SZ_4K,
++ .type = MT_DEVICE,
++ }, {
++#if defined(CONFIG_ARCH_AST1070)
++ .virtual = IO_ADDRESS2(AST_C0_VIC_BASE),
++ .pfn = __phys_to_pfn(AST_C0_VIC_BASE),
++ .length = SZ_1K,
++ .type = MT_DEVICE,
++ }, {
++ .virtual = IO_ADDRESS2(AST_C0_SCU_BASE),
++ .pfn = __phys_to_pfn(AST_C0_SCU_BASE),
++ .length = SZ_1K,
++ .type = MT_DEVICE,
++ }, {
++ .virtual = IO_ADDRESS2(AST_C0_I2C_BASE),
++ .pfn = __phys_to_pfn(AST_C0_I2C_BASE),
++ .length = SZ_1K,
++ .type = MT_DEVICE,
++ }, {
++ .virtual = IO_ADDRESS2(AST_C1_VIC_BASE),
++ .pfn = __phys_to_pfn(AST_C1_VIC_BASE),
++ .length = SZ_1K,
++ .type = MT_DEVICE,
++ }, {
++ .virtual = IO_ADDRESS2(AST_C1_SCU_BASE),
++ .pfn = __phys_to_pfn(AST_C1_SCU_BASE),
++ .length = SZ_1K,
++ .type = MT_DEVICE,
++ }, {
++ .virtual = IO_ADDRESS2(AST_C1_I2C_BASE),
++ .pfn = __phys_to_pfn(AST_C1_I2C_BASE),
++ .length = SZ_1K,
++ .type = MT_DEVICE,
++ }, {
++ .virtual = IO_ADDRESS2(AST_C0_UART0_BASE),
++ .pfn = __phys_to_pfn(AST_C0_UART0_BASE),
++ .length = SZ_1K,
++ .type = MT_DEVICE,
++ }, {
++ .virtual = IO_ADDRESS2(AST_C0_UART1_BASE),
++ .pfn = __phys_to_pfn(AST_C0_UART0_BASE),
++ .length = SZ_1K,
++ .type = MT_DEVICE,
++ }, {
++ .virtual = IO_ADDRESS2(AST_C0_UART2_BASE),
++ .pfn = __phys_to_pfn(AST_C0_UART0_BASE),
++ .length = SZ_1K,
++ .type = MT_DEVICE,
++ }, {
++ .virtual = IO_ADDRESS2(AST_C0_UART3_BASE),
++ .pfn = __phys_to_pfn(AST_C0_UART0_BASE),
++ .length = SZ_1K,
++ .type = MT_DEVICE,
++ }, {
++ .virtual = IO_ADDRESS2(AST_C1_UART0_BASE),
++ .pfn = __phys_to_pfn(AST_C1_UART0_BASE),
++ .length = SZ_1K,
++ .type = MT_DEVICE,
++ }, {
++ .virtual = IO_ADDRESS2(AST_C1_UART1_BASE),
++ .pfn = __phys_to_pfn(AST_C1_UART0_BASE),
++ .length = SZ_1K,
++ .type = MT_DEVICE,
++ }, {
++ .virtual = IO_ADDRESS2(AST_C1_UART2_BASE),
++ .pfn = __phys_to_pfn(AST_C1_UART0_BASE),
++ .length = SZ_1K,
++ .type = MT_DEVICE,
++ }, {
++ .virtual = IO_ADDRESS2(AST_C1_UART3_BASE),
++ .pfn = __phys_to_pfn(AST_C1_UART0_BASE),
++ .length = SZ_1K,
++ .type = MT_DEVICE,
++ }, {
++#endif
++ .virtual = IO_ADDRESS(AST_UART1_BASE),
++ .pfn = __phys_to_pfn(AST_UART1_BASE),
++ .length = SZ_4K,
++ .type = MT_DEVICE,
++ }, {
++ .virtual = IO_ADDRESS(AST_UART2_BASE),
++ .pfn = __phys_to_pfn(AST_UART2_BASE),
++ .length = SZ_4K,
++ .type = MT_DEVICE,
++ }, {
++ .virtual = IO_ADDRESS(AST_UART3_BASE),
++ .pfn = __phys_to_pfn(AST_UART3_BASE),
++ .length = SZ_4K,
++ .type = MT_DEVICE,
++ },
++};
++
++void __init ast_map_io(void)
++{
++ iotable_init(ast_io_desc, ARRAY_SIZE(ast_io_desc));
++}
++
++static void __init ast_init(void)
++{
++ ast_add_all_devices();
++}
++
++MACHINE_START(ASPEED, "AST2400")
++ .phys_io = AST_IO_START,
++// .phys_ram = AST_SDRAM_BASE,
++ .io_pg_offst = (IO_ADDRESS(AST_IO_START)>>18) & 0xfffc,
++ .boot_params = 0x40000100,
++ .map_io = ast_map_io,
++ .timer = &ast_timer,
++ .init_irq = ast_init_irq,
++ .init_machine = ast_init,
++MACHINE_END
+diff --git a/arch/arm/mach-aspeed/ast3100.c b/arch/arm/mach-aspeed/ast3100.c
+new file mode 100644
+index 0000000..cf220e7
+--- /dev/null
++++ b/arch/arm/mach-aspeed/ast3100.c
+@@ -0,0 +1,230 @@
++/*
++ * linux/arch/arm/mach-ast2300/ast2300.c
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++ */
++//#include <linux/config.h>
++#include <linux/types.h>
++#include <linux/sched.h>
++#include <linux/interrupt.h>
++#include <linux/init.h>
++
++#include <mach/hardware.h>
++#include <asm/irq.h>
++#include <asm/setup.h>
++#include <asm/mach-types.h>
++
++#include <asm/mach/arch.h>
++#include <mach/time.h>
++
++#include <asm/mach/map.h>
++#include <plat/devs.h>
++
++#include "core.h"
++
++static struct map_desc ast_io_desc[] __initdata = {
++ {
++ .virtual = IO_ADDRESS(AST_AHB_CTRL_BASE),
++ .pfn = __phys_to_pfn(AST_AHB_CTRL_BASE),
++ .length = SZ_64K,
++ .type = MT_DEVICE,
++ }, {
++ .virtual = IO_ADDRESS(AST_NEW_SMC_CONTROLLER_BASE),
++ .pfn = __phys_to_pfn(AST_NEW_SMC_CONTROLLER_BASE),
++ .length = SZ_64K,
++ .type = MT_DEVICE,
++ }, {
++ .virtual = IO_ADDRESS(AST_LPC_SPI_CONTROLLER_BASE),
++ .pfn = __phys_to_pfn(AST_LPC_SPI_CONTROLLER_BASE),
++ .length = SZ_64K,
++ .type = MT_DEVICE,
++ }, {
++ .virtual = IO_ADDRESS(AST_MIC_BASE),
++ .pfn = __phys_to_pfn(AST_MIC_BASE),
++ .length = SZ_64K,
++ .type = MT_DEVICE,
++ }, {
++ .virtual = IO_ADDRESS(AST_MAC1_BASE),
++ .pfn = __phys_to_pfn(AST_MAC1_BASE),
++ .length = SZ_64K,
++ .type = MT_DEVICE,
++ }, {
++ .virtual = IO_ADDRESS(AST_MAC2_BASE),
++ .pfn = __phys_to_pfn(AST_MAC2_BASE),
++ .length = SZ_64K,
++ .type = MT_DEVICE,
++ }, {
++ .virtual = IO_ADDRESS(AST_VIC_BASE),
++ .pfn = __phys_to_pfn(AST_VIC_BASE),
++ .length = SZ_64K,
++ .type = MT_DEVICE,
++ }, {
++ .virtual = IO_ADDRESS(AST_SCU_BASE),
++ .pfn = __phys_to_pfn(AST_SCU_BASE),
++ .length = SZ_4K,
++ .type = MT_DEVICE,
++ }, {
++ .virtual = IO_ADDRESS(AST_CRYPTO_BASE),
++ .pfn = __phys_to_pfn(AST_CRYPTO_BASE),
++ .length = SZ_4K,
++ .type = MT_DEVICE,
++ }, {
++ .virtual = IO_ADDRESS(AST_JTAG_BASE),
++ .pfn = __phys_to_pfn(AST_JTAG_BASE),
++ .length = SZ_4K,
++ .type = MT_DEVICE,
++ }, {
++ .virtual = IO_ADDRESS(AST_I2S_BASE),
++ .pfn = __phys_to_pfn(AST_I2S_BASE),
++ .length = SZ_4K,
++ .type = MT_DEVICE,
++ }, {
++ .virtual = IO_ADDRESS(AST_GRAPHIC_BASE),
++ .pfn = __phys_to_pfn(AST_GRAPHIC_BASE),
++ .length = SZ_4K,
++ .type = MT_DEVICE,
++ }, {
++ .virtual = IO_ADDRESS(AST_XDMA_BASE),
++ .pfn = __phys_to_pfn(AST_XDMA_BASE),
++ .length = SZ_4K,
++ .type = MT_DEVICE,
++ }, {
++ .virtual = IO_ADDRESS(AST_MCTP_BASE),
++ .pfn = __phys_to_pfn(AST_MCTP_BASE),
++ .length = SZ_4K,
++ .type = MT_DEVICE,
++ }, {
++ .virtual = IO_ADDRESS(AST_ADC_BASE),
++ .pfn = __phys_to_pfn(AST_ADC_BASE),
++ .length = SZ_4K,
++ .type = MT_DEVICE,
++ }, {
++ .virtual = IO_ADDRESS(AST_VIDEO_BASE),
++ .pfn = __phys_to_pfn(AST_VIDEO_BASE),
++ .length = SZ_4K,
++ .type = MT_DEVICE,
++ }, {
++ .virtual = IO_ADDRESS(AST_SRAM_BASE),
++ .pfn = __phys_to_pfn(AST_SRAM_BASE),
++ .length = SZ_64K,
++ .type = MT_DEVICE,
++ }, {
++ .virtual = IO_ADDRESS(AST_SDHC_BASE),
++ .pfn = __phys_to_pfn(AST_SDHC_BASE),
++ .length = SZ_64K,
++ .type = MT_DEVICE,
++ }, {
++ .virtual = IO_ADDRESS(AST_2D_BASE),
++ .pfn = __phys_to_pfn(AST_2D_BASE),
++ .length = SZ_64K,
++ .type = MT_DEVICE,
++ }, {
++ .virtual = IO_ADDRESS(AST_GPIO_BASE),
++ .pfn = __phys_to_pfn(AST_GPIO_BASE),
++ .length = SZ_4K,
++ .type = MT_DEVICE,
++ }, {
++ .virtual = IO_ADDRESS(AST_RTC_BASE),
++ .pfn = __phys_to_pfn(AST_RTC_BASE),
++ .length = SZ_4K,
++ .type = MT_DEVICE,
++ }, {
++ .virtual = IO_ADDRESS(AST_TIMER_BASE),
++ .pfn = __phys_to_pfn(AST_TIMER_BASE),
++ .length = SZ_4K,
++ .type = MT_DEVICE,
++ }, {
++ .virtual = IO_ADDRESS(AST_UART0_BASE),
++ .pfn = __phys_to_pfn(AST_UART0_BASE),
++ .length = SZ_4K,
++ .type = MT_DEVICE,
++ }, {
++ .virtual = IO_ADDRESS(AST_UART1_BASE),
++ .pfn = __phys_to_pfn(AST_UART1_BASE),
++ .length = SZ_4K,
++ .type = MT_DEVICE,
++ }, {
++ .virtual = IO_ADDRESS(AST_WDT_BASE),
++ .pfn = __phys_to_pfn(AST_WDT_BASE),
++ .length = SZ_4K,
++ .type = MT_DEVICE,
++ }, {
++ .virtual = IO_ADDRESS(AST_PWM_BASE),
++ .pfn = __phys_to_pfn(AST_PWM_BASE),
++ .length = SZ_4K,
++ .type = MT_DEVICE,
++ }, {
++ .virtual = IO_ADDRESS(AST_VUART0_BASE),
++ .pfn = __phys_to_pfn(AST_VUART0_BASE),
++ .length = SZ_4K,
++ .type = MT_DEVICE,
++ }, {
++ .virtual = IO_ADDRESS(AST_PUART_BASE),
++ .pfn = __phys_to_pfn(AST_PUART_BASE),
++ .length = SZ_4K,
++ .type = MT_DEVICE,
++ }, {
++ .virtual = IO_ADDRESS(AST_LPC_BASE),
++ .pfn = __phys_to_pfn(AST_LPC_BASE),
++ .length = SZ_4K,
++ .type = MT_DEVICE,
++ }, {
++ .virtual = IO_ADDRESS(AST_I2C_BASE),
++ .pfn = __phys_to_pfn(AST_I2C_BASE),
++ .length = SZ_4K,
++ .type = MT_DEVICE,
++ }, {
++ .virtual = IO_ADDRESS(AST_PECI_BASE),
++ .pfn = __phys_to_pfn(AST_PECI_BASE),
++ .length = SZ_4K,
++ .type = MT_DEVICE,
++ }, {
++ .virtual = IO_ADDRESS(AST_UART2_BASE),
++ .pfn = __phys_to_pfn(AST_UART2_BASE),
++ .length = SZ_4K,
++ .type = MT_DEVICE,
++ }, {
++ .virtual = IO_ADDRESS(AST_UART3_BASE),
++ .pfn = __phys_to_pfn(AST_UART2_BASE),
++ .length = SZ_4K,
++ .type = MT_DEVICE,
++ }, {
++ .virtual = IO_ADDRESS(AST_UART4_BASE),
++ .pfn = __phys_to_pfn(AST_UART2_BASE),
++ .length = SZ_4K,
++ .type = MT_DEVICE,
++ },
++};
++
++void __init ast_map_io(void)
++{
++ iotable_init(ast_io_desc, ARRAY_SIZE(ast_io_desc));
++}
++
++static void __init ast_init(void)
++{
++ ast_add_all_devices();
++}
++
++MACHINE_START(ASPEED, "AST2300")
++ .phys_io = AST_IO_START,
++// .phys_ram = AST_SDRAM_BASE,
++ .io_pg_offst = (IO_ADDRESS(AST_IO_START)>>18) & 0xfffc,
++ .boot_params = 0x40000100,
++ .map_io = ast_map_io,
++ .timer = &ast_timer,
++ .init_irq = ast_init_irq,
++ .init_machine = ast_init,
++MACHINE_END
+diff --git a/arch/arm/mach-aspeed/core.h b/arch/arm/mach-aspeed/core.h
+new file mode 100644
+index 0000000..eb5ac89
+--- /dev/null
++++ b/arch/arm/mach-aspeed/core.h
+@@ -0,0 +1,25 @@
++/*
++ * linux/arch/arm/mach-aspeed/core.h
++ *
++* Copyright (C) ASPEED Tech. Corp.
++* This program is free software; you can redistribute it and/or modify
++* it under the terms of the GNU General Public License as published by the Free Software Foundation;
++* either version 2 of the License, or (at your option) any later version.
++*
++* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
++* without even the implied warranty of MERCHANTABILITY or
++* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
++*
++* You should have received a copy of the GNU General Public License
++* along with this program; if not, write to the Free Software
++* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++*
++ */
++
++#ifndef __ASM_ARCH_ASPEED_CORE_H
++#define __ASM_ARCH_ASPEED_CORE_H
++
++extern struct sys_timer ast_timer;
++
++extern void __init ast_init_irq(void);
++#endif
+diff --git a/arch/arm/mach-aspeed/gpio.c b/arch/arm/mach-aspeed/gpio.c
+new file mode 100644
+index 0000000..3a633e9
+--- /dev/null
++++ b/arch/arm/mach-aspeed/gpio.c
+@@ -0,0 +1,635 @@
++/*
++ * linux/arch/arm/plat-aspeed/gpio.c
++ *
++ * Support functions for ASPEED GPIO
++ *
++ * Copyright (C) 2012-2020 ASPEED Technology Inc.
++ * Written by Ryan Chen <ryan_chen@aspeedtech.com>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++
++#include <linux/init.h>
++#include <linux/module.h>
++#include <linux/interrupt.h>
++#include <linux/sysdev.h>
++#include <linux/err.h>
++#include <linux/clk.h>
++#include <linux/io.h>
++
++#include <mach/hardware.h>
++#include <asm/irq.h>
++#include <mach/irqs.h>
++#include <mach/gpio.h>
++#include <asm/mach/irq.h>
++
++#include <plat/regs-gpio.h>
++#include <asm-generic/gpio.h>
++
++//#define AST_GPIO_DEBUG
++
++#ifdef AST_GPIO_DEBUG
++//#define GPIODBUG(fmt, args...) printk("%s() " fmt, __FUNCTION__, ## args)
++#define GPIODBUG(fmt, args...) printk(fmt, ## args)
++
++#else
++#define GPIODBUG(fmt, args...)
++#endif
++
++/*************************************************************/
++//GPIO group structure
++struct ast_gpio_bank {
++ int irq;
++ u32 base;
++//TODO remove base
++ u32 index;
++ u32 data_offset;
++ u32 dir_offset;
++ u32 int_en_offset;
++ u32 int_type_offset;
++ u32 int_sts_offset;
++ u32 rst_tol_offset;
++ u32 debounce_offset;
++ u32 cmd_source_offset;
++ struct gpio_chip chip;
++
++//#ifdef CONFIG_PM
++//#define NR_REGS (7)
++// u32 regs[NR_REGS];
++//#endif
++};
++
++int ast_gpio_to_irq(unsigned gpio)
++{
++ return (gpio + IRQ_GPIO_CHAIN_START);
++}
++
++EXPORT_SYMBOL(ast_gpio_to_irq);
++
++int ast_irq_to_gpio(unsigned irq)
++{
++ return (irq - IRQ_GPIO_CHAIN_START);
++}
++
++EXPORT_SYMBOL(ast_irq_to_gpio);
++
++static inline u32
++ast_gpio_read(struct ast_gpio_bank *ast_gpio ,u32 offset)
++{
++ GPIODBUG("base = 0x%08x, offset = 0x%08x \n", ast_gpio->base, offset);
++
++ return readl(ast_gpio->base + offset);
++}
++
++static inline void
++ast_gpio_write(struct ast_gpio_bank *ast_gpio , u32 val, u32 offset)
++{
++ GPIODBUG("base = 0x%08x, offset = 0x%08x, val = 0x%08x\n", ast_gpio->base, offset, val);
++ writel(val, ast_gpio->base + offset);
++}
++
++/***************************************************************************************/
++static int
++ast_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
++{
++ struct ast_gpio_bank *ast_gpio = container_of(chip, struct ast_gpio_bank, chip);
++ unsigned long flags;
++ u32 v;
++ int ret = -1;
++
++ GPIODBUG("dir_in %s[%d] \n",chip->label, offset);
++
++ local_irq_save(flags);
++
++ v = ast_gpio_read(ast_gpio, ast_gpio->dir_offset);
++
++ v &= ~(GPIO_OUTPUT_MODE << (offset + (ast_gpio->index * 8)));
++ ast_gpio_write(ast_gpio, v, ast_gpio->dir_offset);
++
++ ret = 0;
++
++ local_irq_restore(flags);
++ return ret;
++
++}
++
++static int
++ast_gpio_direction_output(struct gpio_chip *chip, unsigned offset, int val)
++{
++ struct ast_gpio_bank *ast_gpio = container_of(chip, struct ast_gpio_bank, chip);
++ unsigned long flags;
++ u32 v;
++ int ret = -1;
++ GPIODBUG("dir_out %s[%d], val %d \n",chip->label, offset, val);
++
++ local_irq_save(flags);
++
++ /* Drive as an output */
++ v = ast_gpio_read(ast_gpio, ast_gpio->dir_offset);
++
++ v |= (GPIO_OUTPUT_MODE << (offset + (ast_gpio->index * 8)));
++
++ ast_gpio_write(ast_gpio, v, ast_gpio->dir_offset);
++
++ local_irq_restore(flags);
++
++ ret = 0;
++ return ret;
++}
++
++static int
++ast_gpio_get(struct gpio_chip *chip, unsigned offset)
++{
++ struct ast_gpio_bank *ast_gpio = container_of(chip, struct ast_gpio_bank, chip);
++ unsigned long flags;
++ u32 v;
++
++ GPIODBUG("Get %s[%d] \n",chip->label, offset);
++
++ local_irq_save(flags);
++
++ v = ast_gpio_read(ast_gpio, ast_gpio->data_offset);
++
++ v &= (1 << (offset + (ast_gpio->index * 8)));
++
++ if(v)
++ v = 1;
++ else
++ v = 0;
++
++ local_irq_restore(flags);
++
++ return v;
++}
++
++static void
++ast_gpio_set(struct gpio_chip *chip, unsigned offset, int val)
++{
++ struct ast_gpio_bank *ast_gpio = container_of(chip, struct ast_gpio_bank, chip);
++ unsigned long flags;
++ u32 v;
++ GPIODBUG("Set %s[%d] = %d\n",chip->label, offset, val);
++
++ local_irq_save(flags);
++
++ /* Set the value */
++
++ v = ast_gpio_read(ast_gpio, ast_gpio->data_offset);
++
++ if (val)
++ v |= (1 << (offset + (ast_gpio->index * 8)));
++ else
++ v &= ~(1 << (offset + (ast_gpio->index * 8)));
++
++ ast_gpio_write(ast_gpio, v, ast_gpio->data_offset);
++
++ local_irq_restore(flags);
++}
++
++
++#define AST_GPIO_BANK(name, gpio_base, index_no, data, dir, int_en, int_type, int_sts, rst_tol, debounce, cmd_s) \
++ { \
++ .base = gpio_base, \
++ .index = index_no, \
++ .data_offset = data, \
++ .dir_offset = dir, \
++ .int_en_offset = int_en, \
++ .int_type_offset = int_type, \
++ .int_sts_offset = int_sts, \
++ .rst_tol_offset = rst_tol, \
++ .debounce_offset = debounce, \
++ .cmd_source_offset = cmd_s, \
++ .chip = { \
++ .label = name, \
++ .direction_input = ast_gpio_direction_input, \
++ .direction_output = ast_gpio_direction_output, \
++ .get = ast_gpio_get, \
++ .set = ast_gpio_set, \
++ .ngpio = GPIO_PER_PORT_PIN_NUM, \
++ }, \
++ }
++
++static struct ast_gpio_bank ast_gpio_gp[] = {
++ AST_GPIO_BANK("GPIOA", IO_ADDRESS(AST_GPIO_BASE), 0, 0x000, 0x004, 0x008, 0x00c, 0x018, 0x01c, 0x040, 0x060),
++ AST_GPIO_BANK("GPIOB", IO_ADDRESS(AST_GPIO_BASE), 1, 0x000, 0x004, 0x008, 0x00c, 0x018, 0x01c, 0x040, 0x060),
++ AST_GPIO_BANK("GPIOC", IO_ADDRESS(AST_GPIO_BASE), 2, 0x000, 0x004, 0x008, 0x00c, 0x018, 0x01c, 0x040, 0x060),
++ AST_GPIO_BANK("GPIOD", IO_ADDRESS(AST_GPIO_BASE), 3, 0x000, 0x004, 0x008, 0x00c, 0x018, 0x01c, 0x040, 0x060),
++ AST_GPIO_BANK("GPIOE", IO_ADDRESS(AST_GPIO_BASE), 0, 0x020, 0x024, 0x028, 0x02c, 0x038, 0x03c, 0x048, 0x068),
++ AST_GPIO_BANK("GPIOF", IO_ADDRESS(AST_GPIO_BASE), 1, 0x020, 0x024, 0x028, 0x02c, 0x038, 0x03c, 0x048, 0x068),
++ AST_GPIO_BANK("GPIOG", IO_ADDRESS(AST_GPIO_BASE), 2, 0x020, 0x024, 0x028, 0x02c, 0x038, 0x03c, 0x048, 0x068),
++ AST_GPIO_BANK("GPIOH", IO_ADDRESS(AST_GPIO_BASE), 3, 0x020, 0x024, 0x028, 0x02c, 0x038, 0x03c, 0x048, 0x068),
++ AST_GPIO_BANK("GPIOI", IO_ADDRESS(AST_GPIO_BASE), 0, 0x070, 0x074, 0x098, 0x09c, 0x0a8, 0x0ac, 0x0b0, 0x090),
++ AST_GPIO_BANK("GPIOJ", IO_ADDRESS(AST_GPIO_BASE), 1, 0x070, 0x074, 0x098, 0x09c, 0x0a8, 0x0ac, 0x0b0, 0x090),
++ AST_GPIO_BANK("GPIOK", IO_ADDRESS(AST_GPIO_BASE), 2, 0x070, 0x074, 0x098, 0x09c, 0x0a8, 0x0ac, 0x0b0, 0x090),
++ AST_GPIO_BANK("GPIOL", IO_ADDRESS(AST_GPIO_BASE), 3, 0x070, 0x074, 0x098, 0x09c, 0x0a8, 0x0ac, 0x0b0, 0x090),
++ AST_GPIO_BANK("GPIOM", IO_ADDRESS(AST_GPIO_BASE), 0, 0x078, 0x07c, 0x0e8, 0x0ec, 0x0f8, 0x0fc, 0x100, 0x0e0),
++ AST_GPIO_BANK("GPION", IO_ADDRESS(AST_GPIO_BASE), 1, 0x078, 0x07c, 0x0e8, 0x0ec, 0x0f8, 0x0fc, 0x100, 0x0e0),
++ AST_GPIO_BANK("GPIOO", IO_ADDRESS(AST_GPIO_BASE), 2, 0x078, 0x07c, 0x0e8, 0x0ec, 0x0f8, 0x0fc, 0x100, 0x0e0),
++ AST_GPIO_BANK("GPIOP", IO_ADDRESS(AST_GPIO_BASE), 3, 0x078, 0x07c, 0x0e8, 0x0ec, 0x0f8, 0x0fc, 0x100, 0x0e0),
++ AST_GPIO_BANK("GPIOQ", IO_ADDRESS(AST_GPIO_BASE), 0, 0x080, 0x084, 0x118, 0x11c, 0x128, 0x12c, 0x130, 0x110),
++ AST_GPIO_BANK("GPIOR", IO_ADDRESS(AST_GPIO_BASE), 1, 0x080, 0x084, 0x118, 0x11c, 0x128, 0x12c, 0x130, 0x110),
++ AST_GPIO_BANK("GPIOS", IO_ADDRESS(AST_GPIO_BASE), 2, 0x080, 0x084, 0x118, 0x11c, 0x128, 0x12c, 0x130, 0x110),
++#if defined(CONFIG_ARCH_AST2400)
++ AST_GPIO_BANK("GPIOT", IO_ADDRESS(AST_GPIO_BASE), 4, 0x080, 0x084, 0x118, 0x11c, 0x128, 0x12c, 0x130, 0x110),
++ AST_GPIO_BANK("GPIOU", IO_ADDRESS(AST_GPIO_BASE), 0, 0x088, 0x08c, 0x148, 0x14c, 0x158, 0x15c, 0x160, 0x140),
++ AST_GPIO_BANK("GPIOV", IO_ADDRESS(AST_GPIO_BASE), 1, 0x088, 0x08c, 0x148, 0x14c, 0x158, 0x15c, 0x160, 0x140),
++ AST_GPIO_BANK("GPIOW", IO_ADDRESS(AST_GPIO_BASE), 2, 0x088, 0x08c, 0x148, 0x14c, 0x158, 0x15c, 0x160, 0x140),
++ AST_GPIO_BANK("GPIOX", IO_ADDRESS(AST_GPIO_BASE), 3, 0x088, 0x08c, 0x148, 0x14c, 0x158, 0x15c, 0x160, 0x140),
++ AST_GPIO_BANK("GPIOY", IO_ADDRESS(AST_GPIO_BASE), 0, 0x1e0, 0x1e4, 0x178, 0x17c, 0x188, 0x18c, 0x190, 0x170),
++ AST_GPIO_BANK("GPIOZ", IO_ADDRESS(AST_GPIO_BASE), 1, 0x1e0, 0x1e4, 0x178, 0x17c, 0x188, 0x18c, 0x190, 0x170),
++ AST_GPIO_BANK("GPIOAA", IO_ADDRESS(AST_GPIO_BASE), 2, 0x1e0, 0x1e4, 0x178, 0x17c, 0x188, 0x18c, 0x190, 0x170),
++ AST_GPIO_BANK("GPIOAB", IO_ADDRESS(AST_GPIO_BASE), 3, 0x1e0, 0x1e4, 0x178, 0x17c, 0x188, 0x18c, 0x190, 0x170),
++#endif
++};
++
++
++/***************************************************************************************/
++/*
++ * assuming the pin is muxed as a gpio output, set its value.
++ */
++int ast_set_gpio_value(unsigned gpio_pin, int value)
++{
++ u32 data;
++ u32 gp, pin;
++ gp = gpio_pin / 8;
++ pin = gpio_pin % 32;
++ data = ast_gpio_read(&ast_gpio_gp[gp], ast_gpio_gp[gp].data_offset);
++ if(value)
++ data |= (1 << pin);
++ else
++ data &= ~(1 << pin);
++
++ GPIODBUG("gp : %d, pin %d, data = %x \n ", gp, pin, data);
++ ast_gpio_write(&ast_gpio_gp[gp], data, ast_gpio_gp[gp].data_offset);
++
++ return 0;
++}
++EXPORT_SYMBOL(ast_set_gpio_value);
++
++
++/*
++ * read the pin's value (works even if it's not muxed as a gpio).
++ */
++int ast_get_gpio_value(unsigned gpio_pin)
++{
++ u32 data;
++ u32 gp, pin;
++ gp = gpio_pin / 8;
++ pin = gpio_pin % 32;
++ data = ast_gpio_read(&ast_gpio_gp[gp], ast_gpio_gp[gp].data_offset);
++
++ GPIODBUG("gp : %d, pin %d, data = %x, value = %d \n ", gp, pin, data, (data >> pin) & 1);
++
++ return ((data >> pin) & 1);
++}
++EXPORT_SYMBOL(ast_get_gpio_value);
++
++//timer 0/1/2
++//Debounce time = PCLK * (val+1)
++void ast_set_gpio_debounce_timer(int timer, int val)
++{
++ switch(timer) {
++ case 0:
++ writel(val, IO_ADDRESS(AST_GPIO_BASE) + 0x50);
++ break;
++ case 1:
++ writel(val, IO_ADDRESS(AST_GPIO_BASE) + 0x54);
++ break;
++ case 2:
++ writel(val, IO_ADDRESS(AST_GPIO_BASE) + 0x58);
++ break;
++ }
++}
++
++EXPORT_SYMBOL(ast_set_gpio_debounce_timer);
++
++//TODO ......
++//mode 0 : no debounce , 1: set 0x50, 2: 0x54, 3: 0x58
++void ast_set_gpio_debounce(int gpio_port, int mode)
++{
++#if 0
++ u32 set0, set1;
++ u16 gp, port;
++ gp = gpio_port / 4;
++ port = gpio_port % 4;
++ set0 = ast_gpio_read(&ast_gpio_gp[gp], ast_gpio_gp[gp].debounce_offset);
++ set1 = ast_gpio_read(&ast_gpio_gp[gp], ast_gpio_gp[gp].debounce_offset + 0x04);
++
++ switch(port) {
++ case 0: //A , H , ......
++ set0 = port
++ ast_gpio_write(ast_gpio, val, 0x50);
++ break;
++ case 1:
++ ast_gpio_write(ast_gpio, val, 0x54);
++ break;
++ case 2:
++ ast_gpio_write(ast_gpio, val, 0x58);
++ break;
++ case 3:
++ ast_gpio_write(ast_gpio, val, 0x58);
++ break;
++ default:
++ GPIODBUG("not support \n");
++ return;
++ break;
++
++ }
++
++ ast_gpio_write(&ast_gpio_gp[gp], set0, ast_gpio_gp[gp].debounce_offset);
++ ast_gpio_write(&ast_gpio_gp[gp], set1, ast_gpio_gp[gp].debounce_offset + 0x04);
++#endif
++}
++
++EXPORT_SYMBOL(ast_set_gpio_debounce);
++
++//TODO ......
++//
++void ast_set_gpio_tolerant(int gpio_port, int mode)
++{
++#if 0
++ u32 set0, set1;
++ u16 gp, port;
++ gp = gpio_port / 4;
++ port = gpio_port % 4;
++ set0 = ast_gpio_read(&ast_gpio_gp[gp], ast_gpio_gp[gp].debounce_offset);
++ set1 = ast_gpio_read(&ast_gpio_gp[gp], ast_gpio_gp[gp].debounce_offset + 0x04);
++
++ switch(port) {
++ case 0: //A , H , ......
++ set0 = port
++ ast_gpio_write(ast_gpio, val, 0x50);
++ break;
++ case 1:
++ ast_gpio_write(ast_gpio, val, 0x54);
++ break;
++ case 2:
++ ast_gpio_write(ast_gpio, val, 0x58);
++ break;
++ case 3:
++ ast_gpio_write(ast_gpio, val, 0x58);
++ break;
++ default:
++ GPIODBUG("not support \n");
++ return;
++ break;
++
++ }
++
++ ast_gpio_write(&ast_gpio_gp[gp], set0, ast_gpio_gp[gp].debounce_offset);
++ ast_gpio_write(&ast_gpio_gp[gp], set1, ast_gpio_gp[gp].debounce_offset + 0x04);
++#endif
++}
++
++EXPORT_SYMBOL(ast_set_gpio_tolerant);
++
++/*
++ * We need to unmask the GPIO bank interrupt as soon as possible to
++ * avoid missing GPIO interrupts for other lines in the bank.
++ * Then we need to mask-read-clear-unmask the triggered GPIO lines
++ * in the bank to avoid missing nested interrupts for a GPIO line.
++ * If we wait to unmask individual GPIO lines in the bank after the
++ * line's interrupt handler has been run, we may miss some nested
++ * interrupts.
++ */
++static void
++ast_gpio_irq_handler(unsigned int irq, struct irq_desc *desc)
++{
++ u32 isr;
++ int i,j;
++ struct ast_gpio_bank *ast_gpio;
++
++ if(irq != IRQ_GPIO)
++ BUG();
++
++ GPIODBUG("ast_gpio_irq_handler %d \n ", irq);
++
++// ast_gpio = get_irq_data(irq);
++
++// GPIODBUG("[%s] ------\n ",ast_gpio->chip.label );
++
++ desc->chip->ack(IRQ_GPIO);
++
++ for (i = 0; i < GPIO_PORT_NUM; i++) {
++ ast_gpio = &ast_gpio_gp[i];
++ isr = ast_gpio_read(ast_gpio, ast_gpio->int_sts_offset);
++ GPIODBUG("isr %x \n", isr);
++ isr = (isr >> (8 * ast_gpio->index)) & 0xff;
++ GPIODBUG("[%s] isr %x \n", ast_gpio->chip.label, isr);
++ if(isr != 0) {
++ //get gpio isr and --> to IRQ number ....
++ for (j=0; j<8;j++) {
++ if((1<<j) & isr) {
++ // dispach interrupt
++// GPIODBUG("[%s] pin %d -> irq [%d]\n",ast_gpio->chip.label, j, j + IRQ_GPIO_CHAIN_START + (8 * i));
++ generic_handle_irq(j + IRQ_GPIO_CHAIN_START + (8 * i));
++ }
++ }
++// GPIODBUG("isr -- ? %x \n",ast_gpio_read(ast_gpio, ast_gpio->int_sts_offset));
++ }
++ }
++
++#if 0
++ while(1) {
++ isr = ast_gpio_read(ast_gpio, ast_gpio->int_sts_offset);
++ printk("isr %x \n", isr);
++ isr = isr >> (8 * ast_gpio->index);
++ //get gpio isr and --> to IRQ number ....
++ for (i=0; i<8;i++) {
++ if((1<<i) & isr) {
++ // dispach interrupt
++ printk("[%s] pin %d -> irq [%d]\n",ast_gpio->chip.label, i,i + IRQ_GPIO_CHAIN_START + (8 * ast_gpio->index));
++ generic_handle_irq(i + IRQ_GPIO_CHAIN_START + (8 * ast_gpio->index));
++ }
++ }
++ if(isr == 0)
++ break;
++ }
++#endif
++ desc->chip->unmask(IRQ_GPIO);
++ /* now it may re-trigger */
++
++}
++
++static void ast_gpio_ack_irq(unsigned int irq)
++{
++ struct ast_gpio_bank *ast_gpio = get_irq_chip_data(irq);
++
++ unsigned int gpio_irq = irq - IRQ_GPIO_CHAIN_START;
++
++ gpio_irq = gpio_irq % 8;
++
++ GPIODBUG("irq [%d] : ast_gpio_ack_irq [%s] pin %d\n ",irq, ast_gpio->chip.label, gpio_irq);
++
++ GPIODBUG("write clr [%x] %x\n ",ast_gpio->int_sts_offset, 1<< (gpio_irq + (ast_gpio->index * 8)));
++
++ ast_gpio_write(ast_gpio, 1<< (gpio_irq + (ast_gpio->index * 8)), ast_gpio->int_sts_offset);
++
++ GPIODBUG("read sts %x\n ",ast_gpio_read(ast_gpio, ast_gpio->int_sts_offset));
++
++}
++
++static void ast_gpio_mask_irq(unsigned int irq)
++{
++ struct ast_gpio_bank *ast_gpio = get_irq_chip_data(irq);
++ unsigned int gpio_irq = irq - IRQ_GPIO_CHAIN_START;
++ gpio_irq = gpio_irq%8;
++
++
++ GPIODBUG("irq [%d] : ast_gpio_mask_irq [%s] pin %d\n ",irq, ast_gpio->chip.label, gpio_irq);
++
++ //disable irq
++ ast_gpio_write(ast_gpio, ast_gpio_read(ast_gpio, ast_gpio->int_en_offset) &
++ ~(1<< (gpio_irq + (ast_gpio->index * 8))), ast_gpio->int_en_offset);
++}
++
++static void ast_gpio_unmask_irq(unsigned int irq)
++{
++ struct ast_gpio_bank *ast_gpio = get_irq_chip_data(irq);
++ unsigned int gpio_irq = irq - IRQ_GPIO_CHAIN_START;
++ gpio_irq = gpio_irq%8;
++
++
++ GPIODBUG("irq[%d], [%s] pin %d\n",irq, ast_gpio->chip.label, gpio_irq);
++
++ //Enable IRQ ..
++ ast_gpio_write(ast_gpio, 1<< (gpio_irq + (ast_gpio->index * 8)), ast_gpio->int_sts_offset);
++
++ ast_gpio_write(ast_gpio, ast_gpio_read(ast_gpio, ast_gpio->int_en_offset) |
++ (1<< (gpio_irq + (ast_gpio->index * 8))), ast_gpio->int_en_offset);
++
++}
++
++static int
++ast_gpio_irq_type(unsigned int irq, unsigned int type)
++{
++ u32 type0, type1, type2;
++ struct ast_gpio_bank *ast_gpio;
++ int retval = 0;
++ unsigned int gpio_irq = irq - IRQ_GPIO_CHAIN_START;
++ gpio_irq = gpio_irq%32;
++
++
++
++ GPIODBUG("ast_gpio_irq_type %d : %x \n",irq,type);
++ if (type & ~IRQ_TYPE_SENSE_MASK)
++ return -EINVAL;
++
++ ast_gpio = get_irq_chip_data(irq);
++
++ type0 = ast_gpio_read(ast_gpio, ast_gpio->int_type_offset);
++ type1 = ast_gpio_read(ast_gpio, ast_gpio->int_type_offset + 0x04);
++ type2 = ast_gpio_read(ast_gpio, ast_gpio->int_type_offset + 0x08);
++
++ switch(type) {
++ /* Edge rising type */
++ case IRQ_TYPE_EDGE_RISING:
++ type0 |=(1<<irq);
++ type1 &=~(1<<irq);
++ type2 &=~(1<<irq);
++ break;
++ /* Edge falling type */
++ case IRQ_TYPE_EDGE_FALLING:
++ type2 |=(1<<irq);
++ break;
++ case IRQ_TYPE_EDGE_BOTH:
++ type0 &=~(1<<irq);
++ type1 |=(1<<irq);
++ type2 &=~(1<<irq);
++ break;
++ case IRQ_TYPE_LEVEL_HIGH:
++ type0 |=(1<<irq);
++ type1 |=(1<<irq);
++ type2 &=~(1<<irq);
++ break;
++ case IRQ_TYPE_LEVEL_LOW:
++ type0 &=~(1<<irq);
++ type1 |=(1<<irq);
++ type2 &=~(1<<irq);
++ break;
++ default:
++ GPIODBUG("not support trigger");
++ return -EINVAL;
++ break;
++ }
++
++ ast_gpio_write(ast_gpio, type0, ast_gpio->int_type_offset);
++ ast_gpio_write(ast_gpio, type1, ast_gpio->int_type_offset + 0x04);
++ ast_gpio_write(ast_gpio, type2, ast_gpio->int_type_offset + 0x08);
++
++ return retval;
++
++}
++
++static struct irq_chip ast_gpio_irq_chip = {
++ .name = "GPIO",
++ .ack = ast_gpio_ack_irq,
++ .mask = ast_gpio_mask_irq,
++ .unmask = ast_gpio_unmask_irq,
++ .set_type = ast_gpio_irq_type,
++};
++
++/*---------------------------------------------------------------------*/
++static int __init ast_gpio_init(void)
++{
++ int i,j;
++ struct ast_gpio_bank *ast_gpio;
++
++ GPIODBUG("gpio port num %d, total gpio pin : %d\n",
++ GPIO_PORT_NUM, ARCH_NR_GPIOS);
++
++ GPIODBUG("gpio chain start %d \n",IRQ_GPIO_CHAIN_START);
++ for (i = 0; i < GPIO_PORT_NUM; i++) {
++ ast_gpio = &ast_gpio_gp[i];
++
++ GPIODBUG("add gpio_chip [%s] : %d\n",ast_gpio->chip.label, i);
++
++#if 0
++ bank->chip.direction_input = ast_gpio_direction_input;
++ bank->chip.get = ast_gpio_get;
++ bank->chip.direction_output = ast_gpio_direction_output;
++ bank->chip.set = ast_gpio_set;
++
++ bank->chip.label = "gpio";
++#endif
++ ast_gpio->chip.base = i*8;
++ ast_gpio->chip.ngpio = 8;
++
++ gpiochip_add(&ast_gpio->chip);
++
++#if 1
++ //Set Level Trigger
++ ast_gpio_write(ast_gpio, 0xffffffff, ast_gpio->int_type_offset);
++ ast_gpio_write(ast_gpio, 0xffffffff, ast_gpio->int_type_offset + 0x04);
++ ast_gpio_write(ast_gpio, 0, ast_gpio->int_type_offset + 0x08);
++ //remove clear direction for keep orignal state
++// ast_gpio_write(ast_gpio, 0, ast_gpio->dir_offset);
++ //Enable IRQ
++// ast_gpio_write(ast_gpio, 0xffffffff, ast_gpio->int_en_offset);
++
++#endif
++
++ for(j=0;j<8;j++) {
++ GPIODBUG("inst chip data %d\n",i*8 + j + IRQ_GPIO_CHAIN_START);
++ set_irq_chip_data(i*8 + j + IRQ_GPIO_CHAIN_START, ast_gpio);
++ set_irq_chip(i*8 + j + IRQ_GPIO_CHAIN_START, &ast_gpio_irq_chip);
++ set_irq_handler(i*8 + j + IRQ_GPIO_CHAIN_START, handle_level_irq);
++ set_irq_flags(i*8 + j + IRQ_GPIO_CHAIN_START, IRQF_VALID);
++ }
++ set_irq_chained_handler(IRQ_GPIO, ast_gpio_irq_handler);
++// set_irq_chip_data(IRQ_GPIO, ast_gpio);
++// set_irq_data(IRQ_GPIO, ast_gpio_gp[]);
++
++
++ }
++
++ return 0;
++
++}
++
++core_initcall(ast_gpio_init);
++
++//arch_initcall(ast_gpio_init);
++
+diff --git a/arch/arm/mach-aspeed/include/mach/aspeed_serial.h b/arch/arm/mach-aspeed/include/mach/aspeed_serial.h
+new file mode 100644
+index 0000000..33bf333
+--- /dev/null
++++ b/arch/arm/mach-aspeed/include/mach/aspeed_serial.h
+@@ -0,0 +1,61 @@
++/*
++ * file : aspeed_serial.h
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++ */
++#ifndef ASM_ARM_HARDWARE_AST_SERIAL_H
++#define ASM_ARM_HARDWARE_AST_SERIAL_H
++
++#define UART_RBR 0x00 /* Receiver Buffer Register */
++#define UART_THR 0x00 /* Transmit Holding Register */
++#define UART_DLL 0x00 /* Divisor Latch Low Register */
++#define UART_DLH 0x04 /* Divisor Latch High Register */
++#define UART_IER 0x04 /* Interrupt Enable Register */
++#define UART_IIR 0x08 /* Interrupt Identity Register */
++#define UART_FCR 0x08 /* FIFO Control Register */
++#define UART_LCR 0x0C /* Line Control Register */
++#define UART_MCR 0x10 /* Modem Control Register */
++#define UART_LSR 0x14 /* Line Status Register */
++#define UART_MSR 0x18 /* Modem Status Register */
++#define UART_SCR 0x1C /* Scratch Register */
++
++/* Interrupt Enable Register */
++#define UART_IER_EMSI 0x08 /* Enable Modem Status Interrupt */
++#define UART_IER_ELSI 0x04 /* Enable Line Status Interrupt */
++#define UART_IER_ETEI 0x02 /* Enable Transmit Holding Empty Interrupt */
++#define UART_IER_ERDI 0X01 /* Enable Received Data Interrupt */
++
++/* FIFO Control Register */
++#define UART_FCR_XMITR 0x04 /* XMIT FIFO Reset */
++#define UART_FCR_RCVRR 0x02 /* RCVR FIFO Reset */
++#define UART_FCR_FIFOE 0x01 /* FIEO Enable */
++
++/* Line Control Register */
++#define UART_LCR_DLAB 0x80 /* Divisor Latch Address Bit */
++#define UART_LCR_BRK 0x40 /* Break Control */
++#define UART_LCR_EPS 0x10 /* Even Parity Select */
++#define UART_LCR_PEN 0x08 /* Parity Enable */
++#define UART_LCR_STOP 0x04 /* Stop Bit */
++#define UART_LCR_WLEN_MASK 0x03 /* bits per character mask */
++#define UART_LCR_WLEN_8 0x03 /* 8 bits per character */
++#define UART_LCR_WLEN_7 0x02 /* 7 bits per character */
++#define UART_LCR_WLEN_6 0x01 /* 6 bits per character */
++#define UART_LCR_WLEN_5 0x00 /* 5 bits per character */
++
++/* Line Status Register */
++#define UART_LSR_TEMT 0x40 /* Transmitter Empty */
++#define UART_LSR_THRE 0x20 /* Transmitter Holding Register Empty */
++#define UART_LSR_BE 0x10 /* Break Error */
++#define UART_LSR_FE 0x08 /* Framing Error */
++#define UART_LSR_PE 0x04 /* Parity Error */
++#define UART_LSR_OE 0x02 /* Overrun Error */
++#define UART_LSR_DR 0x01 /* Data Ready */
++#define UART_LSR_ANY (UART_LSR_BE|UART_LSR_FE|UART_LSR_PE|UART_LSR_OE)
++
++#endif
+diff --git a/arch/arm/mach-aspeed/include/mach/ast-uart-dma.h b/arch/arm/mach-aspeed/include/mach/ast-uart-dma.h
+new file mode 100644
+index 0000000..2ac2b41
+--- /dev/null
++++ b/arch/arm/mach-aspeed/include/mach/ast-uart-dma.h
+@@ -0,0 +1,86 @@
++/********************************************************************************
++* File Name : ast-uart-dma.h
++*
++* Copyright (C) 2012-2020 ASPEED Technology Inc.
++* This program is free software; you can redistribute it and/or modify
++* it under the terms of the GNU General Public License as published by the Free Software Foundation;
++* either version 2 of the License, or (at your option) any later version.
++* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
++* without even the implied warranty of MERCHANTABILITY or
++* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
++* You should have received a copy of the GNU General Public License
++* along with this program; if not, write to the Free Software
++* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++********************************************************************************/
++#ifndef AST_UART_DMA_H_INCLUDED
++#define AST_UART_DMA_H_INCLUDED
++
++
++#define DMA_BUFF_SIZE 0x1000 //4096
++
++struct ast_uart_dma_data {
++ u8 chip_no; //campain chip number
++ u8 dma_ch; //dma channel number
++};
++
++
++/* enum ast_uart_chan_op
++ *
++ * operation codes passed to the DMA code by the user, and also used
++ * to inform the current channel owner of any changes to the system state
++*/
++
++enum ast_uart_chan_op {
++ AST_UART_DMAOP_TRIGGER,
++ AST_UART_DMAOP_STOP,
++};
++
++struct ast1070_dma_ch;
++
++/* ast_uart_dma_cbfn_t * * buffer callback routine type */
++typedef void (*ast_uart_dma_cbfn_t)(struct ast1070_dma_ch *,void *dev_id, u16 len);
++
++struct uart_dma_desc {
++ u32 desc0;
++ u32 desc1;
++ u32 desc2;
++ u32 desc3;
++} __attribute__ ((aligned(16)));
++
++struct ast1070_dma_ch {
++ u8 ch_no;
++ u8 direction;
++ u8 enable;
++ u32 ctrl_offset;
++ u32 desc_offset;
++ void *priv;
++ struct uart_dma_desc *desc;
++ dma_addr_t desc_dma_addr; /* Mapped descr. table */
++ /* cdriver callbacks */
++ ast_uart_dma_cbfn_t callback_fn; /* buffer done callback */
++};
++
++#define AST1070_UART_DMA_CH 4
++
++struct ast1070_dma {
++ void __iomem *reg_base;
++ struct ast1070_dma_ch dma_tx_ch[AST1070_UART_DMA_CH];
++ struct ast1070_dma_ch dma_rx_ch[AST1070_UART_DMA_CH];
++};
++
++
++/* ast_uart_dma_request * * request a dma channel exclusivley */
++extern int ast_uart_rx_dma_request(u8 node, u8 channel, ast_uart_dma_cbfn_t rtn, void *id);
++extern int ast_uart_tx_dma_request(u8 node, u8 channel, ast_uart_dma_cbfn_t rtn, void *id);
++
++/* ast_uart_dma_ctrl * * change the state of the dma channel */
++extern int ast_uart_rx_dma_ctrl(u8 node, u8 ch, enum ast_uart_chan_op op);
++extern int ast_uart_tx_dma_ctrl(u8 node, u8 ch, enum ast_uart_chan_op op);
++
++extern int ast_uart_rx_dma_enqueue(u8 node, u8 ch, dma_addr_t rx_buff, u16 len);
++extern int ast_uart_tx_dma_enqueue(u8 node, u8 ch, dma_addr_t tx_buff, u16 len);
++
++
++
++#endif
++
+diff --git a/arch/arm/mach-aspeed/include/mach/ast1070_irqs.h b/arch/arm/mach-aspeed/include/mach/ast1070_irqs.h
+new file mode 100644
+index 0000000..0774417
+--- /dev/null
++++ b/arch/arm/mach-aspeed/include/mach/ast1070_irqs.h
+@@ -0,0 +1,142 @@
++/*
++ * arch/arm/plat-aspeed/include/plat/irqs.h
++ *
++ * Copyright (C) 2012-2020 ASPEED Technology Inc.
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++ */
++
++#ifndef _AST1070_IRQS_H_
++#define _AST1070_IRQS_H_ 1
++
++#define IRQ_C0_VIC_CHAIN IRQ_EXT0
++#define IRQ_C0_VIC_CHAIN_START (AST_VIC_NUM)
++
++#define IRQ_C1_VIC_CHAIN IRQ_EXT1
++#define IRQ_C1_VIC_CHAIN_START (IRQ_C0_VIC_CHAIN_START + AST_CVIC_NUM)
++
++#define IRQ_C2_VIC_CHAIN IRQ_EXT2
++#define IRQ_C2_VIC_CHAIN_START (IRQ_C1_VIC_CHAIN_START + AST_CVIC_NUM)
++
++#define IRQ_C3_VIC_CHAIN IRQ_EXT3
++#define IRQ_C3_VIC_CHAIN_START (IRQ_C2_VIC_CHAIN_START + AST_CVIC_NUM)
++
++#define AST_CVIC_NUM 25
++
++#define IRQ_C0_N1_KCS (IRQ_C0_VIC_CHAIN_START + 0)
++#define IRQ_C0_N1_UART (IRQ_C0_VIC_CHAIN_START + 1)
++#define IRQ_C0_N1_MAILBOX (IRQ_C0_VIC_CHAIN_START + 2)
++#define IRQ_C0_N1_PORT80 (IRQ_C0_VIC_CHAIN_START + 3)
++#define IRQ_C0_N1_RESET (IRQ_C0_VIC_CHAIN_START + 4)
++#define IRQ_C0_N2_KCS (IRQ_C0_VIC_CHAIN_START + 5)
++#define IRQ_C0_N2_UART (IRQ_C0_VIC_CHAIN_START + 6)
++#define IRQ_C0_N2_MAILBOX (IRQ_C0_VIC_CHAIN_START + 7)
++#define IRQ_C0_N2_PORT80 (IRQ_C0_VIC_CHAIN_START + 8)
++#define IRQ_C0_N2_RESET (IRQ_C0_VIC_CHAIN_START + 9)
++#define IRQ_C0_N3_KCS (IRQ_C0_VIC_CHAIN_START + 10)
++#define IRQ_C0_N3_UART (IRQ_C0_VIC_CHAIN_START + 11)
++#define IRQ_C0_N3_MAILBOX (IRQ_C0_VIC_CHAIN_START + 12)
++#define IRQ_C0_N3_PORT80 (IRQ_C0_VIC_CHAIN_START + 13)
++#define IRQ_C0_N3_RESET (IRQ_C0_VIC_CHAIN_START + 14)
++#define IRQ_C0_N4_KCS (IRQ_C0_VIC_CHAIN_START + 15)
++#define IRQ_C0_N4_UART (IRQ_C0_VIC_CHAIN_START + 16)
++#define IRQ_C0_N4_MAILBOX (IRQ_C0_VIC_CHAIN_START + 17)
++#define IRQ_C0_N4_PORT80 (IRQ_C0_VIC_CHAIN_START + 18)
++#define IRQ_C0_N4_RESET (IRQ_C0_VIC_CHAIN_START + 19)
++#define IRQ_C0_N1_UART_DMA (IRQ_C0_VIC_CHAIN_START + 20)
++#define IRQ_C0_N2_UART_DMA (IRQ_C0_VIC_CHAIN_START + 21)
++#define IRQ_C0_N3_UART_DMA (IRQ_C0_VIC_CHAIN_START + 22)
++#define IRQ_C0_N4_UART_DMA (IRQ_C0_VIC_CHAIN_START + 23)
++#define IRQ_C0_I2C (IRQ_C0_VIC_CHAIN_START + 24)
++
++#define IRQ_C1_N1_KCS (IRQ_C1_VIC_CHAIN_START + 0)
++#define IRQ_C1_N1_UART (IRQ_C1_VIC_CHAIN_START + 1)
++#define IRQ_C1_N1_MAILBOX (IRQ_C1_VIC_CHAIN_START + 2)
++#define IRQ_C1_N1_PORT80 (IRQ_C1_VIC_CHAIN_START + 3)
++#define IRQ_C1_N1_RESET (IRQ_C1_VIC_CHAIN_START + 4)
++#define IRQ_C1_N2_KCS (IRQ_C1_VIC_CHAIN_START + 5)
++#define IRQ_C1_N2_UART (IRQ_C1_VIC_CHAIN_START + 6)
++#define IRQ_C1_N2_MAILBOX (IRQ_C1_VIC_CHAIN_START + 7)
++#define IRQ_C1_N2_PORT80 (IRQ_C1_VIC_CHAIN_START + 8)
++#define IRQ_C1_N2_RESET (IRQ_C1_VIC_CHAIN_START + 9)
++#define IRQ_C1_N3_KCS (IRQ_C1_VIC_CHAIN_START + 10)
++#define IRQ_C1_N3_UART (IRQ_C1_VIC_CHAIN_START + 11)
++#define IRQ_C1_N3_MAILBOX (IRQ_C1_VIC_CHAIN_START + 12)
++#define IRQ_C1_N3_PORT80 (IRQ_C1_VIC_CHAIN_START + 13)
++#define IRQ_C1_N3_RESET (IRQ_C1_VIC_CHAIN_START + 14)
++#define IRQ_C1_N4_KCS (IRQ_C1_VIC_CHAIN_START + 15)
++#define IRQ_C1_N4_UART (IRQ_C1_VIC_CHAIN_START + 16)
++#define IRQ_C1_N4_MAILBOX (IRQ_C1_VIC_CHAIN_START + 17)
++#define IRQ_C1_N4_PORT80 (IRQ_C1_VIC_CHAIN_START + 18)
++#define IRQ_C1_N4_RESET (IRQ_C1_VIC_CHAIN_START + 19)
++#define IRQ_C1_N1_UART_DMA (IRQ_C1_VIC_CHAIN_START + 20)
++#define IRQ_C1_N2_UART_DMA (IRQ_C1_VIC_CHAIN_START + 21)
++#define IRQ_C1_N3_UART_DMA (IRQ_C1_VIC_CHAIN_START + 22)
++#define IRQ_C1_N4_UART_DMA (IRQ_C1_VIC_CHAIN_START + 23)
++#define IRQ_C1_I2C (IRQ_C1_VIC_CHAIN_START + 24)
++
++#define IRQ_C2_N1_KCS (IRQ_C2_VIC_CHAIN_START + 0)
++#define IRQ_C2_N1_UART (IRQ_C2_VIC_CHAIN_START + 1)
++#define IRQ_C2_N1_MAILBOX (IRQ_C2_VIC_CHAIN_START + 2)
++#define IRQ_C2_N1_PORT80 (IRQ_C2_VIC_CHAIN_START + 3)
++#define IRQ_C2_N1_RESET (IRQ_C2_VIC_CHAIN_START + 4)
++#define IRQ_C2_N2_KCS (IRQ_C2_VIC_CHAIN_START + 5)
++#define IRQ_C2_N2_UART (IRQ_C2_VIC_CHAIN_START + 6)
++#define IRQ_C2_N2_MAILBOX (IRQ_C2_VIC_CHAIN_START + 7)
++#define IRQ_C2_N2_PORT80 (IRQ_C2_VIC_CHAIN_START + 8)
++#define IRQ_C2_N2_RESET (IRQ_C2_VIC_CHAIN_START + 9)
++#define IRQ_C2_N3_KCS (IRQ_C2_VIC_CHAIN_START + 10)
++#define IRQ_C2_N3_UART (IRQ_C2_VIC_CHAIN_START + 11)
++#define IRQ_C2_N3_MAILBOX (IRQ_C2_VIC_CHAIN_START + 12)
++#define IRQ_C2_N3_PORT80 (IRQ_C2_VIC_CHAIN_START + 13)
++#define IRQ_C2_N3_RESET (IRQ_C2_VIC_CHAIN_START + 14)
++#define IRQ_C2_N4_KCS (IRQ_C2_VIC_CHAIN_START + 15)
++#define IRQ_C2_N4_UART (IRQ_C2_VIC_CHAIN_START + 16)
++#define IRQ_C2_N4_MAILBOX (IRQ_C2_VIC_CHAIN_START + 17)
++#define IRQ_C2_N4_PORT80 (IRQ_C2_VIC_CHAIN_START + 18)
++#define IRQ_C2_N4_RESET (IRQ_C2_VIC_CHAIN_START + 19)
++#define IRQ_C2_N1_UART_DMA (IRQ_C2_VIC_CHAIN_START + 20)
++#define IRQ_C2_N2_UART_DMA (IRQ_C2_VIC_CHAIN_START + 21)
++#define IRQ_C2_N3_UART_DMA (IRQ_C2_VIC_CHAIN_START + 22)
++#define IRQ_C2_N4_UART_DMA (IRQ_C2_VIC_CHAIN_START + 23)
++#define IRQ_C2_I2C (IRQ_C2_VIC_CHAIN_START + 24)
++
++#define IRQ_C3_N1_KCS (IRQ_C3_VIC_CHAIN_START + 0)
++#define IRQ_C3_N1_UART (IRQ_C3_VIC_CHAIN_START + 1)
++#define IRQ_C3_N1_MAILBOX (IRQ_C3_VIC_CHAIN_START + 2)
++#define IRQ_C3_N1_PORT80 (IRQ_C3_VIC_CHAIN_START + 3)
++#define IRQ_C3_N1_RESET (IRQ_C3_VIC_CHAIN_START + 4)
++#define IRQ_C3_N2_KCS (IRQ_C3_VIC_CHAIN_START + 5)
++#define IRQ_C3_N2_UART (IRQ_C3_VIC_CHAIN_START + 6)
++#define IRQ_C3_N2_MAILBOX (IRQ_C3_VIC_CHAIN_START + 7)
++#define IRQ_C3_N2_PORT80 (IRQ_C3_VIC_CHAIN_START + 8)
++#define IRQ_C3_N2_RESET (IRQ_C3_VIC_CHAIN_START + 9)
++#define IRQ_C3_N3_KCS (IRQ_C3_VIC_CHAIN_START + 10)
++#define IRQ_C3_N3_UART (IRQ_C3_VIC_CHAIN_START + 11)
++#define IRQ_C3_N3_MAILBOX (IRQ_C3_VIC_CHAIN_START + 12)
++#define IRQ_C3_N3_PORT80 (IRQ_C3_VIC_CHAIN_START + 13)
++#define IRQ_C3_N3_RESET (IRQ_C3_VIC_CHAIN_START + 14)
++#define IRQ_C3_N4_KCS (IRQ_C3_VIC_CHAIN_START + 15)
++#define IRQ_C3_N4_UART (IRQ_C3_VIC_CHAIN_START + 16)
++#define IRQ_C3_N4_MAILBOX (IRQ_C3_VIC_CHAIN_START + 17)
++#define IRQ_C3_N4_PORT80 (IRQ_C3_VIC_CHAIN_START + 18)
++#define IRQ_C3_N4_RESET (IRQ_C3_VIC_CHAIN_START + 19)
++#define IRQ_C3_N1_UART_DMA (IRQ_C3_VIC_CHAIN_START + 20)
++#define IRQ_C3_N2_UART_DMA (IRQ_C3_VIC_CHAIN_START + 21)
++#define IRQ_C3_N3_UART_DMA (IRQ_C3_VIC_CHAIN_START + 22)
++#define IRQ_C3_N4_UART_DMA (IRQ_C3_VIC_CHAIN_START + 23)
++#define IRQ_C3_I2C (IRQ_C3_VIC_CHAIN_START + 24)
++
++#endif
+diff --git a/arch/arm/mach-aspeed/include/mach/ast1070_platform.h b/arch/arm/mach-aspeed/include/mach/ast1070_platform.h
+new file mode 100644
+index 0000000..feefd91
+--- /dev/null
++++ b/arch/arm/mach-aspeed/include/mach/ast1070_platform.h
+@@ -0,0 +1,100 @@
++/*
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++ */
++
++#ifndef _AST1070_PLATFORM_H_
++#define _AST1070_PLATFORM_H_ 1
++
++#define AST_C0_BASE (AST_LPC_BRIDGE)
++
++#define AST_C0_UART0_BASE (AST_C0_BASE) /* Companion UART1 */
++#define AST_C0_UART1_BASE (AST_C0_BASE + 0x400) /* Companion UART2 */
++#define AST_C0_UART2_BASE (AST_C0_BASE + 0x800) /* Companion UART3 */
++#define AST_C0_UART3_BASE (AST_C0_BASE + 0xc00) /* Companion UART4 */
++#define AST_C0_LPC0_BASE (AST_C0_BASE + 0x1000) /* Companion LPC1 */
++#define AST_C0_LPC1_BASE (AST_C0_BASE + 0x1400) /* Companion LPC2 */
++#define AST_C0_LPC2_BASE (AST_C0_BASE + 0x1800) /* Companion LPC3 */
++#define AST_C0_LPC3_BASE (AST_C0_BASE + 0x1c00) /* Companion LPC4 */
++#define AST_C0_SCU_BASE (AST_C0_BASE + 0x2000) /* Companion SCU */
++#define AST_C0_VIC_BASE (AST_C0_BASE + 0x2400) /* Companion VIC */
++#define AST_C0_LPC_SLAVE_BASE (AST_C0_BASE + 0x2c00) /* Companion LPC SlLAVE */
++#define AST_C0_I2C_BASE (AST_C0_BASE + 0x3000) /* Companion I2C */
++#define AST_C0_SPI_BASE (AST_C0_BASE + 0x4000) /* Companion SPI */
++#define AST_C0_LPC_SPI_BASE (AST_C0_BASE + 0x4400) /* Companion LPC SPI */
++#define AST_C0_UART_DMA_BASE (AST_C0_BASE + 0x4800) /* Companion UART DMA */
++#define AST_C0_SPI_CONTROL_BASE (AST_C0_BASE + 0x4c00) /* Companion SPI CONTROL */
++#define AST_C0_SPI_SHADOW_SRAM_BASE (AST_C0_BASE + 0x5000) /* Companion SPI SHADOW SRAM */
++
++#define AST_C1_BASE (AST_LPC_BRIDGE + 0x10000)
++
++#define AST_C1_UART0_BASE (AST_C1_BASE) /* Companion UART1 */
++#define AST_C1_UART1_BASE (AST_C1_BASE + 0x400) /* Companion UART2 */
++#define AST_C1_UART2_BASE (AST_C1_BASE + 0x800) /* Companion UART3 */
++#define AST_C1_UART3_BASE (AST_C1_BASE + 0xc00) /* Companion UART4 */
++#define AST_C1_LPC0_BASE (AST_C1_BASE + 0x1000) /* Companion LPC1 */
++#define AST_C1_LPC1_BASE (AST_C1_BASE + 0x1400) /* Companion LPC2 */
++#define AST_C1_LPC2_BASE (AST_C1_BASE + 0x1800) /* Companion LPC3 */
++#define AST_C1_LPC3_BASE (AST_C1_BASE + 0x1c00) /* Companion LPC4 */
++#define AST_C1_SCU_BASE (AST_C1_BASE + 0x2000) /* Companion SCU */
++#define AST_C1_VIC_BASE (AST_C1_BASE + 0x2400) /* Companion VIC */
++#define AST_C1_LPC_SLAVE_BASE (AST_C1_BASE + 0x2c00) /* Companion LPC SlLAVE */
++#define AST_C1_I2C_BASE (AST_C1_BASE + 0x3000) /* Companion I2C */
++#define AST_C1_SPI_BASE (AST_C1_BASE + 0x4000) /* Companion SPI */
++#define AST_C1_LPC_SPI_BASE (AST_C1_BASE + 0x4400) /* Companion LPC SPI */
++#define AST_C1_UART_DMA_BASE (AST_C1_BASE + 0x4800) /* Companion UART DMA */
++#define AST_C1_SPI_CONTROL_BASE (AST_C1_BASE + 0x4c00) /* Companion SPI CONTROL */
++#define AST_C1_SPI_SHADOW_SRAM_BASE (AST_C1_BASE + 0x5000) /* Companion SPI SHADOW SRAM */
++
++#define AST_C2_BASE (AST_LPC_BRIDGE + 0x20000)
++
++#define AST_C2_UART0_BASE (AST_C2_BASE) /* Companion UART1 */
++#define AST_C2_UART1_BASE (AST_C2_BASE + 0x400) /* Companion UART2 */
++#define AST_C2_UART2_BASE (AST_C2_BASE + 0x800) /* Companion UART3 */
++#define AST_C2_UART3_BASE (AST_C2_BASE + 0xc00) /* Companion UART4 */
++#define AST_C2_LPC1_BASE (AST_C2_BASE + 0x1000) /* Companion LPC1 */
++#define AST_C2_LPC2_BASE (AST_C2_BASE + 0x1400) /* Companion LPC2 */
++#define AST_C2_LPC3_BASE (AST_C2_BASE + 0x1800) /* Companion LPC3 */
++#define AST_C2_LPC4_BASE (AST_C2_BASE + 0x1c00) /* Companion LPC4 */
++#define AST_C2_SCU_BASE (AST_C2_BASE + 0x2000) /* Companion SCU */
++#define AST_C2_VIC_BASE (AST_C2_BASE + 0x2400) /* Companion VIC */
++#define AST_C2_LPC_SLAVE_BASE (AST_C2_BASE + 0x2c00) /* Companion LPC SlLAVE */
++#define AST_C2_I2C_BASE (AST_C2_BASE + 0x3000) /* Companion I2C */
++#define AST_C2_SPI_BASE (AST_C2_BASE + 0x4000) /* Companion SPI */
++#define AST_C2_LPC_SPI_BASE (AST_C2_BASE + 0x4400) /* Companion LPC SPI */
++#define AST_C2_UART_DMA_BASE (AST_C2_BASE + 0x4800) /* Companion UART DMA */
++#define AST_C2_SPI_CONTROL_BASE (AST_C2_BASE + 0x4c00) /* Companion SPI CONTROL */
++#define AST_C2_SPI_SHADOW_SRAM_BASE (AST_C2_BASE + 0x5000) /* Companion SPI SHADOW SRAM */
++
++#define AST_C3_BASE (AST_LPC_BRIDGE + 0x30000)
++
++#define AST_C3_UART0_BASE (AST_C3_BASE) /* Companion UART1 */
++#define AST_C3_UART1_BASE (AST_C3_BASE + 0x400) /* Companion UART2 */
++#define AST_C3_UART2_BASE (AST_C3_BASE + 0x800) /* Companion UART3 */
++#define AST_C3_UART3_BASE (AST_C3_BASE + 0xc00) /* Companion UART4 */
++#define AST_C3_LPC0_BASE (AST_C3_BASE + 0x1000) /* Companion LPC1 */
++#define AST_C3_LPC1_BASE (AST_C3_BASE + 0x1400) /* Companion LPC2 */
++#define AST_C3_LPC2_BASE (AST_C3_BASE + 0x1800) /* Companion LPC3 */
++#define AST_C3_LPC3_BASE (AST_C3_BASE + 0x1c00) /* Companion LPC4 */
++#define AST_C3_SCU_BASE (AST_C3_BASE + 0x2000) /* Companion SCU */
++#define AST_C3_VIC_BASE (AST_C3_BASE + 0x2400) /* Companion VIC */
++#define AST_C3_LPC_SLAVE_BASE (AST_C3_BASE + 0x2c00) /* Companion LPC SlLAVE */
++#define AST_C3_I2C_BASE (AST_C3_BASE + 0x3000) /* Companion I2C */
++#define AST_C3_SPI_BASE (AST_C3_BASE + 0x4000) /* Companion SPI */
++#define AST_C3_LPC_SPI_BASE (AST_C3_BASE + 0x4400) /* Companion LPC SPI */
++#define AST_C3_UART_DMA_BASE (AST_C3_BASE + 0x4800) /* Companion UART DMA */
++#define AST_C3_SPI_CONTROL_BASE (AST_C3_BASE + 0x4c00) /* Companion SPI CONTROL */
++#define AST_C3_SPI_SHADOW_SRAM_BASE (AST_C3_BASE + 0x5000) /* Companion SPI SHADOW SRAM */
++
++#endif
+diff --git a/arch/arm/mach-aspeed/include/mach/ast1520_irqs.h b/arch/arm/mach-aspeed/include/mach/ast1520_irqs.h
+new file mode 100644
+index 0000000..3ebc91b
+--- /dev/null
++++ b/arch/arm/mach-aspeed/include/mach/ast1520_irqs.h
+@@ -0,0 +1,107 @@
++/*
++ * arch/arm/plat-aspeed/include/plat/irqs.h
++ *
++ * Copyright (C) 2012-2020 ASPEED Technology Inc.
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++ */
++
++#ifndef _AST1520_IRQS_H_
++#define _AST1520_IRQS_H_ 1
++
++
++#ifdef CONFIG_PCIE
++#define NR_IRQS (ARCH_NR_GPIOS +ARCH_NR_PCIE + AST_VIC_NUM)
++
++//--------------GPIO ---------------------------------------------------------------
++#define ARCH_NR_GPIOS (GPIO_PORT_NUM*8)
++#define IRQ_GPIO_CHAIN_START AST_VIC_NUM
++//------------------- ---------------------------------------------------------------
++
++#define ARCH_NR_PCIE 5
++#define IRQ_PCIE_CHAIN IRQ_PCIE
++#define IRQ_PCIE_CHAIN_START (ARCH_NR_GPIOS + AST_VIC_NUM)
++
++#define IRQ_PCIE_INTA (IRQ_PCIE_CHAIN_START)
++#define IRQ_PCIE_INTB (IRQ_PCIE_CHAIN_START + 1)
++#define IRQ_PCIE_INTC (IRQ_PCIE_CHAIN_START + 2)
++#define IRQ_PCIE_INTD (IRQ_PCIE_CHAIN_START + 3)
++#define IRQ_PCIE_MSI0 (IRQ_PCIE_INTD + 1) // support max 32 MSI
++
++#else
++#define NR_IRQS (AST_VIC_NUM + ARCH_NR_GPIOS)
++//--------------GPIO ---------------------------------------------------------------
++#define ARCH_NR_GPIOS (GPIO_PORT_NUM*8)
++#define IRQ_GPIO_CHAIN_START AST_VIC_NUM
++//------------------- ---------------------------------------------------------------
++#endif
++
++#define AST_VIC_NUM 51
++
++//#define IRQ_SDRAM_ECC 0
++//#define IRQ_MIC 1
++#define IRQ_MAC0 2 /* MAC 1 interrupt */
++//#define IRQ_MAC1 3 /* MAC 2 interrupt */
++#define IRQ_CRYPTO 4
++#define IRQ_USB20_HUB 5
++#define IRQ_EHCI 5
++#define IRQ_XDMA 6
++#define IRQ_VIDEO 7
++//#define IRQ_LPC 8
++#define IRQ_UART1 9 /* UART 1 interrupt */
++#define IRQ_UART0 10 /* UART 3 interrupt */
++//11 Reserved
++#define IRQ_I2C 12
++//#define IRQ_UDC11 13
++#define IRQ_UHCI 14
++//#define IRQ_PECI 15
++#define IRQ_TIMER0 16 /* TIMER 1 interrupt */
++#define IRQ_TIMER1 17 /* TIMER 2 interrupt */
++#define IRQ_TIMER2 18 /* TIMER 3 interrupt */
++//#define IRQ_SMC 19
++#define IRQ_GPIO 20
++#define IRQ_SCU 21
++#define IRQ_RTC 22
++//23 , 24 reserverd
++#define IRQ_CRT 25
++#define IRQ_SDHC 26
++#define IRQ_WDT 27
++#define IRQ_TACHO 28
++#define IRQ_2D 29
++#define IRQ_SYS_WAKEUP 30
++//#define IRQ_ADC 31
++#define IRQ_UART2 32 /* UART 2 interrupt */
++//#define IRQ_UART2 33 /* UART 3 interrupt */
++//#define IRQ_UART3 34 /* UART 4 interrupt */
++//#define IRQ_TIMER3 35 /* TIMER 4 interrupt */
++//#define IRQ_TIMER4 36
++//#define IRQ_TIMER5 37
++//#define IRQ_TIMER6 38
++//#define IRQ_TIMER7 39 /* TIMER 8 interrupt */
++//#define IRQ_SGPIO_MASTER 40
++//#define IRQ_SGPIO_SLAVE 41
++#define IRQ_PCIE 41
++
++#define IRQ_MCTP 42
++//#define IRQ_JTAG 43
++#define IRQ_PS2 44
++#define IRQ_CPU1 45
++//#define IRQ_MAILBOX 46
++#define IRQ_EXT0_GPIOL1 47
++#define IRQ_EXT1_GPIOL3 48
++#define IRQ_EXT2_GPIOM3 49
++#define IRQ_EXT3_GPIOM3 50
++
++#endif
+diff --git a/arch/arm/mach-aspeed/include/mach/ast1520_platform.h b/arch/arm/mach-aspeed/include/mach/ast1520_platform.h
+new file mode 100644
+index 0000000..daded5d
+--- /dev/null
++++ b/arch/arm/mach-aspeed/include/mach/ast1520_platform.h
+@@ -0,0 +1,61 @@
++/*
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++ */
++
++#ifndef _AST1520_PLATFORM_H_
++#define _AST1520_PLATFORM_H_ 1
++
++#define AST_SRAM_SIZE (SZ_8K)
++
++#define AST_AHB_CTRL_BASE 0x1E600000 /* AHB CONTROLLER */
++
++#define AST_SPI_BASE 0x1E620000 /* SPI CONTROLLER */
++
++#define AST_MAC0_BASE 0x1E660000 /* MAC1 */
++
++#define AST_USB20_BASE 0x1E6A0000 /* USB 2.0 VIRTUAL HUB CONTROLLER */
++#define AST_EHCI_BASE 0x1E6A1000 /* USB 2.0 HOST CONTROLLER */
++#define AST_UHCI_BASE 0x1E6B0000 /* USB 1.1 HOST CONTROLLER */
++#define AST_VIC_BASE 0x1E6C0000 /* VIC */
++#define AST_SDMC_BASE 0x1E6E0000 /* MMC SDRAM*/
++#define AST_SCU_BASE 0x1E6E2000 /* SCU */
++#define AST_CRYPTO_BASE 0x1E6E3000 /* Crypto */
++
++#define AST_I2S_BASE 0x1E6E5000 /* I2S */
++#define AST_GRAPHIC_BASE 0x1E6E6000 /* Graphics */
++#define AST_XDMA_BASE 0x1E6E7000 /* XDMA */
++#define AST_MCTP_BASE 0x1E6E8000 /* MCTP */
++#define AST_PCIE_BASE 0x1E6ED000 /* PCIE */
++
++#define AST_VIDEO_BASE 0x1E700000 /* VIDEO ENGINE */
++#define AST_SRAM_BASE 0x1E720000 /* SRAM */
++#define AST_SDHC_BASE 0x1E740000 /* SD */
++#define AST_2D_BASE 0x1E760000 /* 2D */
++#define AST_GPIO_BASE 0x1E780000 /* GPIO */
++#define AST_RTC_BASE 0x1E781000 /* RTC */
++#define AST_TIMER_BASE 0x1E782000 /* TIMER #0~2*/
++#define AST_UART1_BASE 0x1E783000 /* UART1 */
++#define AST_UART0_BASE 0x1E784000 /* UART3 */
++#define AST_WDT_BASE 0x1E785000 /* WDT */
++
++#define AST_I2C_BASE 0x1E78A000 /* I2C */
++#define AST_UART2_BASE 0x1E78D000 /* UART2 */
++
++#define AST_SPI0_MEM 0x20000000
++
++#define AST_PCIE_WIN_BASE 0x70000000
++#define AST_PCIE_WIN_SIZE 0x01000000
++
++#endif
+diff --git a/arch/arm/mach-aspeed/include/mach/ast2000_irqs.h b/arch/arm/mach-aspeed/include/mach/ast2000_irqs.h
+new file mode 100644
+index 0000000..50aece9
+--- /dev/null
++++ b/arch/arm/mach-aspeed/include/mach/ast2000_irqs.h
+@@ -0,0 +1,64 @@
++/*
++ * arch/arm/plat-aspeed/include/plat/irqs.h
++ *
++ * Copyright (C) 2012-2020 ASPEED Technology Inc.
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++ */
++
++#ifndef _AST2000_IRQS_H_
++#define _AST2000_IRQS_H_ 1
++
++#define NR_IRQS (AST_VIC_NUM + ARCH_NR_GPIOS)
++//--------------GPIO ---------------------------------------------------------------
++#define ARCH_NR_GPIOS (GPIO_PORT_NUM*8)
++#define IRQ_GPIO_CHAIN_START AST_VIC_NUM
++
++#define AST_VIC_NUM 32
++
++#define IRQ_SPI 0
++#define IRQ_UART0 1
++#define IRQ_UART1 2
++#define IRQ_TIMER0 3
++#define IRQ_TIMER1 4
++#define IRQ_TIMER2 5
++#define IRQ_RTC 6
++#define IRQ_MAC0 7
++#define IRQ_GPIO_B0 8
++#define IRQ_UDC 9
++#define IRQ_PCI 10
++#define IRQ_GPIO_B1 11
++#define IRQ_GPIO_B2 12
++#define IRQ_GPIO_B3 13
++#define IRQ_LPC 14
++#define IRQ_I2C 15
++#define IRQ_USB11 16
++#define IRQ_VIDEO 17
++#define IRQ_CRYPTO 18
++#define IRQ_SCU 19
++#define IRQ_GPIO_B4 20
++#define IRQ_GPIO_B5 21
++#define IRQ_GPIO_B6 22
++#define IRQ_GPIO_A0 23
++#define IRQ_GPIO_A1 24
++#define IRQ_GPIO_A2 25
++#define IRQ_GPIO_A3 26
++#define IRQ_HDMA 27
++#define IRQ_GPIO_A4 28
++#define IRQ_GPIO_A5 29
++#define IRQ_GPIO_A6 30
++#define IRQ_WDT 31
++
++#endif
+diff --git a/arch/arm/mach-aspeed/include/mach/ast2000_platform.h b/arch/arm/mach-aspeed/include/mach/ast2000_platform.h
+new file mode 100644
+index 0000000..ff34f5b
+--- /dev/null
++++ b/arch/arm/mach-aspeed/include/mach/ast2000_platform.h
+@@ -0,0 +1,40 @@
++/*
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++ */
++
++#ifndef _AST2000_PLATFORM_H_
++#define _AST2000_PLATFORM_H_ 1
++
++#define AST_MAC0_BASE 0x19c80000 /* MAC1 */
++#define AST_CRYPTO_BASE 0x1E6E0040 /* Crypto */
++#define AST_UDC11_BASE 0x1E6E0080 /* USB11 */
++#define AST_SCU0_BASE 0x1E6E0100 /* SCU1 */
++#define AST_LPC_BASE 0x1E6E0400 /* LPC */
++#define AST_I2C_BASE 0x1E6E0800 /* I2C */
++//---//
++#define AST_VIDEO_BASE 0x1E700000 /* VIDEO ENGINE */
++#define AST_AHB_TO_PBUS_BASE 0x1E720000 /* APB -> PBUS */
++//...//
++#define AST_HDMA_BASE 0x1E7c0000 /* HDMA */
++#define AST_TIMER_BASE 0x1E800000 /* TIMER0/1/2 */
++#define AST_RTC_BASE 0x1E820000 /* RTC */
++#define AST_UART0_BASE 0x1E840000 /* UART0 */
++#define AST_UART1_BASE 0x1E860000 /* UART1 */
++#define AST_SPI_BASE 0x1E880000 /* SPI */
++#define AST_GPIO_BASE 0x1E8A0000 /* GPIO */
++#define AST_WDT_BASE 0x1E8C0000 /* WDT */
++#define AST_SCU0_BASE 0x1E8E000c /* SCU2 */
++
++#endif
+diff --git a/arch/arm/mach-aspeed/include/mach/ast2100_irqs.h b/arch/arm/mach-aspeed/include/mach/ast2100_irqs.h
+new file mode 100644
+index 0000000..8513909
+--- /dev/null
++++ b/arch/arm/mach-aspeed/include/mach/ast2100_irqs.h
+@@ -0,0 +1,64 @@
++/*
++ * arch/arm/plat-aspeed/include/plat/irqs.h
++ *
++ * Copyright (C) 2012-2020 ASPEED Technology Inc.
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++ */
++
++#ifndef _AST2100_IRQS_H_
++#define _AST2100_IRQS_H_ 1
++
++
++#define NR_IRQS (AST_VIC_NUM + ARCH_NR_GPIOS)
++//--------------GPIO ---------------------------------------------------------------
++#define ARCH_NR_GPIOS (GPIO_PORT_NUM*8)
++#define IRQ_GPIO_CHAIN_START AST_VIC_NUM
++
++#define AST_VIC_NUM 32
++#define IRQ_SDRAM_ECC 0
++#define IRQ_MIC 1
++#define IRQ_MAC0 2 /* MAC 1 interrupt */
++#define IRQ_MAC1 3 /* MAC 2 interrupt */
++#define IRQ_CRYPTO 4
++#define IRQ_USB20_HUB 5
++#define IRQ_EHCI 5
++#define IRQ_XDMA 6
++#define IRQ_VIDEO 7
++#define IRQ_LPC 8
++#define IRQ_UART0 9 /* UART 1 interrupt */
++#define IRQ_UART1 10 /* UART 2 interrupt */
++//11 reserved
++#define IRQ_I2C 12
++#define IRQ_UDC11 13
++//14 reserved
++#define IRQ_PECI 15
++#define IRQ_TIMER0 16 /* TIMER 1 interrupt */
++#define IRQ_TIMER1 17 /* TIMER 2 interrupt */
++#define IRQ_TIMER2 18 /* TIMER 3 interrupt */
++#define IRQ_SMC 19
++#define IRQ_GPIO 20
++#define IRQ_SCU 21
++#define IRQ_RTC_SEC 22
++#define IRQ_RTC_DAY 23
++#define IRQ_RTC_HOUR 24
++#define IRQ_RTC_MIN 25
++#define IRQ_RTC 26
++#define IRQ_WDT 27
++#define IRQ_TACHO 28
++#define IRQ_2D 29
++#define IRQ_PCI 30
++#define IRQ_AHBC 31
++#endif
+diff --git a/arch/arm/mach-aspeed/include/mach/ast2100_platform.h b/arch/arm/mach-aspeed/include/mach/ast2100_platform.h
+new file mode 100644
+index 0000000..6d59ca4
+--- /dev/null
++++ b/arch/arm/mach-aspeed/include/mach/ast2100_platform.h
+@@ -0,0 +1,56 @@
++/*
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++ */
++
++#ifndef _AST2100_PLATFORM_H_
++#define _AST2100_PLATFORM_H_ 1
++
++#define AST_OLD_SMC_BASE 0x10000000 /*Legacy BMC Static Memory */
++#define AST_OLD_SMC_CTRL_BASE 0x16000000 /*Legacy BMC Static Memory Ctrl*/
++
++#define AST_AHB_CTRL_BASE 0x1E600000 /* AHB CONTROLLER */
++
++#define AST_MIC_BASE 0x1E640000 /* MIC CONTROLLER */
++#define AST_MAC1_BASE 0x1E660000 /* MAC1 */
++#define AST_MAC2_BASE 0x1E680000 /* MAC2 */
++
++#define AST_USB20_BASE 0x1E6A0000 /* USB 2.0 VIRTUAL HUB CONTROLLER */
++#define AST_VIC_BASE 0x1E6C0000 /* VIC */
++#define AST_SDMC_BASE 0x1E6E0000 /* MMC */
++#define AST_UDC11_BASE 0x1E6E1000 /* USB11 */
++#define AST_SCU_BASE 0x1E6E2000 /* SCU */
++#define AST_CRYPTO_BASE 0x1E6E3000 /* Crypto */
++
++#define AST_GRAPHIC_BASE 0x1E6E6000 /* Graphics */
++
++#define AST_VIDEO_BASE 0x1E700000 /* VIDEO ENGINE */
++#define AST_AHB_TO_PBUS_BASE 0x1E720000 /* APB -> PBUS */
++#define AST_MDMA_BASE 0x1E740000 /* MDMA */
++#define AST_2D_BASE 0x1E760000 /* 2D */
++#define AST_GPIO_BASE 0x1E780000 /* GPIO */
++#define AST_RTC_BASE 0x1E781000 /* RTC */
++#define AST_TIMER_BASE 0x1E782000 /* TIMER #0~7*/
++#define AST_UART0_BASE 0x1E783000 /* UART1 */
++#define AST_UART1_BASE 0x1E784000 /* UART2 */
++#define AST_WDT_BASE 0x1E785000 /* WDT */
++#define AST_PWM_BASE 0x1E786000 /* PWM */
++#define AST_VUART0_BASE 0x1E787000 /* VUART1 */
++#define AST_PUART_BASE 0x1E788000 /* PUART */
++#define AST_LPC_BASE 0x1E789000 /* LPC */
++#define AST_I2C_BASE 0x1E78A000 /* I2C */
++#define AST_PECI_BASE 0x1E78B000 /* PECI */
++#define AST_PCIARBITER_BASE 0x1E78C000 /* PCI ARBITER */
++
++#endif
+diff --git a/arch/arm/mach-aspeed/include/mach/ast2200_irqs.h b/arch/arm/mach-aspeed/include/mach/ast2200_irqs.h
+new file mode 100644
+index 0000000..f0b880f
+--- /dev/null
++++ b/arch/arm/mach-aspeed/include/mach/ast2200_irqs.h
+@@ -0,0 +1,65 @@
++/*
++ * arch/arm/plat-aspeed/include/plat/irqs.h
++ *
++ * Copyright (C) 2012-2020 ASPEED Technology Inc.
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++ */
++
++#ifndef _AST2200_IRQS_H_
++#define _AST2200_IRQS_H_ 1
++
++#define NR_IRQS (AST_VIC_NUM + ARCH_NR_GPIOS)
++//--------------GPIO ---------------------------------------------------------------
++#define ARCH_NR_GPIOS (GPIO_PORT_NUM*8)
++#define IRQ_GPIO_CHAIN_START AST_VIC_NUM
++
++#define AST_VIC_NUM 32
++
++#define IRQ_SDRAM_ECC 0
++#define IRQ_MIC 1
++#define IRQ_MAC0 2 /* MAC 1 interrupt */
++#define IRQ_MAC1 3 /* MAC 2 interrupt */
++#define IRQ_CRYPTO 4
++#define IRQ_USB20_HUB 5
++#define IRQ_EHCI 5
++#define IRQ_XDMA 6
++#define IRQ_VIDEO 7
++#define IRQ_LPC 8
++#define IRQ_UART0 9 /* UART 1 interrupt */
++#define IRQ_UART1 10 /* UART 2 interrupt */
++//11 reserved
++#define IRQ_I2C 12
++#define IRQ_UDC11 13
++//14 reserved
++#define IRQ_PECI 15
++#define IRQ_TIMER0 16 /* TIMER 1 interrupt */
++#define IRQ_TIMER1 17 /* TIMER 2 interrupt */
++#define IRQ_TIMER2 18 /* TIMER 3 interrupt */
++#define IRQ_SMC 19
++#define IRQ_GPIO 20
++#define IRQ_SCU 21
++#define IRQ_RTC_SEC 22
++#define IRQ_RTC_DAY 23
++#define IRQ_RTC_HOUR 24
++#define IRQ_RTC_MIN 25
++#define IRQ_RTC 26
++#define IRQ_WDT 27
++#define IRQ_TACHO 28
++#define IRQ_2D 29
++#define IRQ_PCI 30
++#define IRQ_AHBC 31
++
++#endif
+diff --git a/arch/arm/mach-aspeed/include/mach/ast2200_platform.h b/arch/arm/mach-aspeed/include/mach/ast2200_platform.h
+new file mode 100644
+index 0000000..324e15b
+--- /dev/null
++++ b/arch/arm/mach-aspeed/include/mach/ast2200_platform.h
+@@ -0,0 +1,55 @@
++/*
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++ */
++
++#ifndef _AST2200_PLATFORM_H_
++#define _AST2200_PLATFORM_H_ 1
++
++#define AST_OLD_SMC_BASE 0x10000000 /*Legacy BMC Static Memory */
++#define AST_OLD_SMC_CTRL_BASE 0x16000000 /*Legacy BMC Static Memory Ctrl*/
++
++#define AST_AHB_CTRL_BASE 0x1E600000 /* AHB CONTROLLER */
++
++#define AST_MIC_BASE 0x1E640000 /* MIC CONTROLLER */
++#define AST_MAC1_BASE 0x1E660000 /* MAC1 */
++#define AST_MAC2_BASE 0x1E680000 /* MAC2 */
++
++#define AST_USB20_BASE 0x1E6A0000 /* USB 2.0 VIRTUAL HUB CONTROLLER */
++#define AST_VIC_BASE 0x1E6C0000 /* VIC */
++#define AST_SDMC_BASE 0x1E6E0000 /* MMC */
++#define AST_UDC11_BASE 0x1E6E1000 /* USB11 */
++#define AST_SCU_BASE 0x1E6E2000 /* SCU */
++#define AST_CRYPTO_BASE 0x1E6E3000 /* Crypto */
++
++#define AST_GRAPHIC_BASE 0x1E6E6000 /* Graphics */
++
++#define AST_VIDEO_BASE 0x1E700000 /* VIDEO ENGINE */
++#define AST_AHB_TO_PBUS_BASE 0x1E720000 /* APB -> PBUS */
++#define AST_MDMA_BASE 0x1E740000 /* MDMA */
++#define AST_2D_BASE 0x1E760000 /* 2D */
++#define AST_GPIO_BASE 0x1E780000 /* GPIO */
++#define AST_RTC_BASE 0x1E781000 /* RTC */
++#define AST_TIMER_BASE 0x1E782000 /* TIMER #0~7*/
++#define AST_UART0_BASE 0x1E783000 /* UART1 */
++#define AST_UART1_BASE 0x1E784000 /* UART2 */
++#define AST_WDT_BASE 0x1E785000 /* WDT */
++#define AST_PWM_BASE 0x1E786000 /* PWM */
++#define AST_VUART0_BASE 0x1E787000 /* VUART1 */
++#define AST_PUART_BASE 0x1E788000 /* PUART */
++#define AST_LPC_BASE 0x1E789000 /* LPC */
++#define AST_I2C_BASE 0x1E78A000 /* I2C */
++#define AST_PECI_BASE 0x1E78B000 /* PECI */
++
++#endif
+diff --git a/arch/arm/mach-aspeed/include/mach/ast2300_irqs.h b/arch/arm/mach-aspeed/include/mach/ast2300_irqs.h
+new file mode 100644
+index 0000000..2d7b0c8
+--- /dev/null
++++ b/arch/arm/mach-aspeed/include/mach/ast2300_irqs.h
+@@ -0,0 +1,92 @@
++/*
++ * arch/arm/plat-aspeed/include/plat/irqs.h
++ *
++ * Copyright (C) 2012-2020 ASPEED Technology Inc.
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++ */
++
++#ifndef _AST2300_IRQS_H_
++#define _AST2300_IRQS_H_ 1
++
++#if defined(CONFIG_ARCH_AST1070)
++//----------VIC + GPIO + CVIC chain--------------------------------------------------
++#define NR_IRQS (AST_VIC_NUM + ARCH_NR_GPIOS + AST_CVIC_NUM)
++//--------------GPIO ---------------------------------------------------------------
++#define ARCH_NR_GPIOS (GPIO_PORT_NUM*8)
++#define IRQ_GPIO_CHAIN_START (AST_VIC_NUM)
++//---------------CVIC---------------------------------------------------------------
++#define IRQ_C0_VIC_CHAIN IRQ_GPIOL1
++#define IRQ_C0_VIC_CHAIN_START (AST_VIC_NUM + ARCH_NR_GPIOS)
++//------------------- ---------------------------------------------------------------
++#else
++#define NR_IRQS (AST_VIC_NUM + ARCH_NR_GPIOS)
++//--------------GPIO ---------------------------------------------------------------
++#define ARCH_NR_GPIOS (GPIO_PORT_NUM*8)
++#define IRQ_GPIO_CHAIN_START AST_VIC_NUM
++
++#endif
++
++
++#define AST_VIC_NUM 46
++
++#define IRQ_SDRAM_ECC 0
++#define IRQ_MIC 1
++#define IRQ_MAC0 2 /* MAC 1 interrupt */
++#define IRQ_MAC1 3 /* MAC 2 interrupt */
++#define IRQ_CRYPTO 4
++#define IRQ_USB20_HUB 5
++#define IRQ_EHCI 5
++#define IRQ_XDMA 6
++#define IRQ_VIDEO 7
++#define IRQ_LPC 8
++#define IRQ_UART1 9 /* UART 1 interrupt */
++#define IRQ_UART0 10 /* UART 5 interrupt */
++//11 Reserved
++#define IRQ_I2C 12
++#define IRQ_UDC11 13
++#define IRQ_UHCI 14
++#define IRQ_PECI 15
++#define IRQ_TIMER0 16 /* TIMER 1 interrupt */
++#define IRQ_TIMER1 17 /* TIMER 2 interrupt */
++#define IRQ_TIMER2 18 /* TIMER 3 interrupt */
++#define IRQ_SMC 19
++#define IRQ_GPIO 20
++#define IRQ_SCU 21
++#define IRQ_RTC 22
++//23 , 24 reserverd
++#define IRQ_CRT 25
++#define IRQ_SDHC 26
++#define IRQ_WDT 27
++#define IRQ_TACHO 28
++#define IRQ_2D 29
++#define IRQ_SYS_WAKEUP 30
++#define IRQ_ADC 31
++#define IRQ_UART2 32 /* UART 2 interrupt */
++#define IRQ_UART3 33 /* UART 3 interrupt */
++#define IRQ_UART4 34 /* UART 4 interrupt */
++#define IRQ_TIMER3 35 /* TIMER 4 interrupt */
++#define IRQ_TIMER4 36
++#define IRQ_TIMER5 37
++#define IRQ_TIMER6 38
++#define IRQ_TIMER7 39 /* TIMER 8 interrupt */
++#define IRQ_SGPIO_MASTER 40
++#define IRQ_SGPIO_SLAVE 41
++#define IRQ_MCTP 42
++#define IRQ_JTAG 43
++//#define IRQ_RESERVED 44
++#define IRQ_CPU1 45
++
++#endif
+diff --git a/arch/arm/mach-aspeed/include/mach/ast2300_platform.h b/arch/arm/mach-aspeed/include/mach/ast2300_platform.h
+new file mode 100644
+index 0000000..4898856
+--- /dev/null
++++ b/arch/arm/mach-aspeed/include/mach/ast2300_platform.h
+@@ -0,0 +1,72 @@
++/*
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++ */
++
++#ifndef _AST2300_PLATFORM_H_
++#define _AST2300_PLATFORM_H_ 1
++
++#define AST_DRAM_BASE 0x40000000
++#define AST_SRAM_SIZE (SZ_16K)
++
++#define AST_OLD_SMC_BASE 0x10000000 /*Legacy BMC Static Memory */
++#define AST_OLD_SMC_CTRL_BASE 0x16000000 /*Legacy BMC Static Memory Ctrl*/
++
++#define AST_AHB_CTRL_BASE 0x1E600000 /* AHB CONTROLLER */
++
++#define AST_FMC_BASE 0x1E620000 /* NEW SMC CONTROLLER */
++#define AST_SPI_BASE 0x1E630000 /* SPI CONTROLLER */
++#define AST_MIC_BASE 0x1E640000 /* MIC CONTROLLER */
++#define AST_MAC0_BASE 0x1E660000 /* MAC1 */
++#define AST_MAC1_BASE 0x1E680000 /* MAC2 */
++
++#define AST_USB20_BASE 0x1E6A0000 /* USB 2.0 VIRTUAL HUB CONTROLLER */
++#define AST_UHCI_BASE 0x1E6B0000 /* USB 1.1 HOST CONTROLLER */
++#define AST_VIC_BASE 0x1E6C0000 /* VIC */
++#define AST_SDMC_BASE 0x1E6E0000 /* SDRAM CTRL */
++#define AST_UDC11_BASE 0x1E6E1000 /* USB11 */
++#define AST_SCU_BASE 0x1E6E2000 /* SCU */
++#define AST_CRYPTO_BASE 0x1E6E3000 /* Crypto */
++#define AST_JTAG_BASE 0x1E6E4000 /* JTAG */
++#define AST_GRAPHIC_BASE 0x1E6E6000 /* Graphics */
++#define AST_XDMA_BASE 0x1E6E7000 /* XDMA */
++#define AST_MCTP_BASE 0x1E6E8000 /* MCTP */
++#define AST_ADC_BASE 0x1E6E9000 /* ADC */
++
++#define AST_LPC_PLUS_BASE 0x1E6EC000 /* LPC+ Controller */
++
++#define AST_VIDEO_BASE 0x1E700000 /* VIDEO ENGINE */
++#define AST_SRAM_BASE 0x1E720000 /* SRAM */
++#define AST_SDHC_BASE 0x1E740000 /* SDHC */
++#define AST_2D_BASE 0x1E760000 /* 2D */
++#define AST_GPIO_BASE 0x1E780000 /* GPIO */
++#define AST_RTC_BASE 0x1E781000 /* RTC */
++#define AST_TIMER_BASE 0x1E782000 /* TIMER #0~7*/
++#define AST_UART1_BASE 0x1E783000 /* UART1 */
++#define AST_UART0_BASE 0x1E784000 /* UART5 */
++#define AST_WDT_BASE 0x1E785000 /* WDT */
++#define AST_PWM_BASE 0x1E786000 /* PWM */
++#define AST_VUART0_BASE 0x1E787000 /* VUART1 */
++#define AST_PUART_BASE 0x1E788000 /* PUART */
++#define AST_LPC_BASE 0x1E789000 /* LPC */
++#define AST_MBX_BASE 0x1E789200 /* MailBox */
++#define AST_I2C_BASE 0x1E78A000 /* I2C */
++#define AST_PECI_BASE 0x1E78B000 /* PECI */
++#define AST_UART2_BASE 0x1E78D000 /* UART2 */
++#define AST_UART3_BASE 0x1E78E000 /* UART3 */
++#define AST_UART4_BASE 0x1E78F000 /* UART4 */
++
++#define AST_LPC_BRIDGE 0x60000000
++
++#endif
+diff --git a/arch/arm/mach-aspeed/include/mach/ast2400_irqs.h b/arch/arm/mach-aspeed/include/mach/ast2400_irqs.h
+new file mode 100644
+index 0000000..17c59da
+--- /dev/null
++++ b/arch/arm/mach-aspeed/include/mach/ast2400_irqs.h
+@@ -0,0 +1,96 @@
++/*
++ * arch/arm/plat-aspeed/include/plat/irqs.h
++ *
++ * Copyright (C) 2012-2020 ASPEED Technology Inc.
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++ */
++
++#ifndef _AST2400_IRQS_H_
++#define _AST2400_IRQS_H_ 1
++
++#if defined(CONFIG_ARCH_AST1070)
++#include <mach/ast1070_irqs.h>
++#define MAX_AST1070_NR 2
++//----------VIC + CVIC + GPIO chain--------------------------------------------------
++#define NR_IRQS (AST_VIC_NUM + (AST_CVIC_NUM * MAX_AST1070_NR) + ARCH_NR_GPIOS)
++//--------------GPIO ---------------------------------------------------------------
++#define ARCH_NR_GPIOS (GPIO_PORT_NUM*8)
++#define IRQ_GPIO_CHAIN_START (AST_VIC_NUM + (AST_CVIC_NUM * MAX_AST1070_NR))
++//------------------- ---------------------------------------------------------------
++#else
++//--------------GPIO ---------------------------------------------------------------
++#define ARCH_NR_GPIOS (GPIO_PORT_NUM*8)
++#define IRQ_GPIO_CHAIN_START (AST_VIC_NUM)
++//------------------- ---------------------------------------------------------------
++#define NR_IRQS (AST_VIC_NUM + ARCH_NR_GPIOS)
++
++#endif
++
++#define AST_VIC_NUM 51
++
++#define IRQ_SDRAM_ECC 0
++#define IRQ_MIC 1
++#define IRQ_MAC0 2 /* MAC 1 interrupt */
++#define IRQ_MAC1 3 /* MAC 2 interrupt */
++#define IRQ_CRYPTO 4
++#define IRQ_USB20_HUB 5
++#define IRQ_EHCI 5
++#define IRQ_XDMA 6
++#define IRQ_VIDEO 7
++#define IRQ_LPC 8
++#define IRQ_UART1 9 /* UART 1 interrupt */
++#define IRQ_UART0 10 /* UART 5 interrupt */
++//11 Reserved
++#define IRQ_I2C 12
++#define IRQ_UDC11 13
++#define IRQ_UHCI 14
++#define IRQ_PECI 15
++#define IRQ_TIMER0 16 /* TIMER 1 interrupt */
++#define IRQ_TIMER1 17 /* TIMER 2 interrupt */
++#define IRQ_TIMER2 18 /* TIMER 3 interrupt */
++#define IRQ_SMC 19
++#define IRQ_GPIO 20
++#define IRQ_SCU 21
++#define IRQ_RTC 22
++//23 , 24 reserverd
++#define IRQ_CRT 25
++#define IRQ_SDHC 26
++#define IRQ_WDT 27
++#define IRQ_TACHO 28
++#define IRQ_2D 29
++#define IRQ_SYS_WAKEUP 30
++#define IRQ_ADC 31
++#define IRQ_UART2 32 /* UART 2 interrupt */
++#define IRQ_UART3 33 /* UART 3 interrupt */
++#define IRQ_UART4 34 /* UART 4 interrupt */
++#define IRQ_TIMER3 35 /* TIMER 4 interrupt */
++#define IRQ_TIMER4 36
++#define IRQ_TIMER5 37
++#define IRQ_TIMER6 38
++#define IRQ_TIMER7 39 /* TIMER 8 interrupt */
++#define IRQ_SGPIO_MASTER 40
++#define IRQ_SGPIO_SLAVE 41
++#define IRQ_MCTP 42
++#define IRQ_JTAG 43
++//#define IRQ_RESERVED 44
++#define IRQ_CPU1 45
++#define IRQ_MAILBOX 46
++#define IRQ_EXT0 47
++#define IRQ_EXT1 48
++#define IRQ_EXT2 49
++#define IRQ_EXT3 50
++
++#endif
+diff --git a/arch/arm/mach-aspeed/include/mach/ast2400_platform.h b/arch/arm/mach-aspeed/include/mach/ast2400_platform.h
+new file mode 100644
+index 0000000..e507953
+--- /dev/null
++++ b/arch/arm/mach-aspeed/include/mach/ast2400_platform.h
+@@ -0,0 +1,79 @@
++/*
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++ */
++
++#ifndef _AST2400_PLATFORM_H_
++#define _AST2400_PLATFORM_H_ 1
++
++#define AST_DRAM_BASE 0x40000000
++
++#define AST_SRAM_SIZE (SZ_16K*2)
++
++#define AST_OLD_SMC_BASE 0x10000000 /*Legacy BMC Static Memory */
++#define AST_OLD_SMC_CTRL_BASE 0x16000000 /*Legacy BMC Static Memory Ctrl*/
++
++#define AST_AHB_CTRL_BASE 0x1E600000 /* AHB CONTROLLER */
++
++#define AST_FMC_BASE 0x1E620000 /* NEW SMC CONTROLLER */
++#define AST_SPI_BASE 0x1E630000 /* SPI CONTROLLER */
++#define AST_MIC_BASE 0x1E640000 /* MIC CONTROLLER */
++#define AST_MAC0_BASE 0x1E660000 /* MAC1 */
++#define AST_MAC1_BASE 0x1E680000 /* MAC2 */
++
++#define AST_USB20_BASE 0x1E6A0000 /* USB 2.0 VIRTUAL HUB CONTROLLER */
++#define AST_EHCI_BASE 0x1E6A1000 /* USB 2.0 HOST CONTROLLER */
++#define AST_UHCI_BASE 0x1E6B0000 /* USB 1.1 HOST CONTROLLER */
++#define AST_VIC_BASE 0x1E6C0000 /* VIC */
++#define AST_SDMC_BASE 0x1E6E0000 /* SDRAM CTRL */
++#define AST_UDC11_BASE 0x1E6E1000 /* USB11 */
++#define AST_SCU_BASE 0x1E6E2000 /* SCU */
++#define AST_CRYPTO_BASE 0x1E6E3000 /* Crypto */
++#define AST_JTAG_BASE 0x1E6E4000 /* JTAG */
++#define AST_GRAPHIC_BASE 0x1E6E6000 /* Graphics */
++#define AST_XDMA_BASE 0x1E6E7000 /* XDMA */
++#define AST_MCTP_BASE 0x1E6E8000 /* MCTP */
++#define AST_ADC_BASE 0x1E6E9000 /* ADC */
++
++#define AST_LPC_PLUS_BASE 0x1E6EC000 /* LPC+ Controller */
++
++#define AST_VIDEO_BASE 0x1E700000 /* VIDEO ENGINE */
++#define AST_SRAM_BASE 0x1E720000 /* SRAM */
++#define AST_SDHC_BASE 0x1E740000 /* SDHC */
++#define AST_2D_BASE 0x1E760000 /* 2D */
++#define AST_GPIO_BASE 0x1E780000 /* GPIO */
++#define AST_RTC_BASE 0x1E781000 /* RTC */
++#define AST_TIMER_BASE 0x1E782000 /* TIMER #0~7*/
++#define AST_UART1_BASE 0x1E783000 /* UART1 */
++#define AST_UART0_BASE 0x1E784000 /* UART5 */
++#define AST_WDT_BASE 0x1E785000 /* WDT */
++#define AST_PWM_BASE 0x1E786000 /* PWM */
++#define AST_VUART0_BASE 0x1E787000 /* VUART1 */
++#define AST_PUART_BASE 0x1E788000 /* PUART */
++#define AST_LPC_BASE 0x1E789000 /* LPC */
++#define AST_MBX_BASE 0x1E789200 /* MailBox */
++#define AST_I2C_BASE 0x1E78A000 /* I2C */
++#define AST_PECI_BASE 0x1E78B000 /* PECI */
++#define AST_PCIARBITER_BASE 0x1E78C000 /* PCI ARBITER */
++#define AST_UART2_BASE 0x1E78D000 /* UART2 */
++#define AST_UART3_BASE 0x1E78E000 /* UART3 */
++#define AST_UART4_BASE 0x1E78F000 /* UART4 */
++#define AST_SPI0_MEM 0x30000000
++
++#define AST_LPC_PLUS_BRIDGE 0x70000000
++
++#define AST_LPC_BRIDGE 0x60000000
++
++
++#endif
+diff --git a/arch/arm/mach-aspeed/include/mach/ast_gpio_irqs.h b/arch/arm/mach-aspeed/include/mach/ast_gpio_irqs.h
+new file mode 100644
+index 0000000..3bae742
+--- /dev/null
++++ b/arch/arm/mach-aspeed/include/mach/ast_gpio_irqs.h
+@@ -0,0 +1,272 @@
++/*
++ * file : gpio_irqs.h
++ *
++ * Copyright (C) 2012-2020 ASPEED Technology Inc.
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++ */
++
++#ifndef _GPIO_IRQS_H_
++#define _GPIO_IRQS_H_ 1
++
++#if defined(CONFIG_ARCH_AST1010)
++#define GPIO_PORT_NUM 19
++#elif defined(CONFIG_ARCH_AST2000)
++#define GPIO_PORT_NUM 19
++#elif defined(CONFIG_ARCH_AST2100)
++#define GPIO_PORT_NUM 19
++#elif defined(CONFIG_ARCH_AST2200)
++#define GPIO_PORT_NUM 19
++#elif defined(CONFIG_ARCH_AST2300)
++#define GPIO_PORT_NUM 19
++#elif defined(CONFIG_ARCH_AST2400)
++#define GPIO_PORT_NUM 28
++#elif defined(CONFIG_ARCH_AST1520)
++#define GPIO_PORT_NUM 28
++#else
++#err "no define for gpio irqs.h"
++#endif
++
++
++#define IRQ_GPIOA0 (IRQ_GPIO_CHAIN_START + 0)
++#define IRQ_GPIOA1 (IRQ_GPIO_CHAIN_START + 1)
++#define IRQ_GPIOA2 (IRQ_GPIO_CHAIN_START + 2)
++#define IRQ_GPIOA3 (IRQ_GPIO_CHAIN_START + 3)
++#define IRQ_GPIOA4 (IRQ_GPIO_CHAIN_START + 4)
++#define IRQ_GPIOA5 (IRQ_GPIO_CHAIN_START + 5)
++#define IRQ_GPIOA6 (IRQ_GPIO_CHAIN_START + 6)
++#define IRQ_GPIOA7 (IRQ_GPIO_CHAIN_START + 7)
++#define IRQ_GPIOB0 (IRQ_GPIO_CHAIN_START + 8)
++#define IRQ_GPIOB1 (IRQ_GPIO_CHAIN_START + 9)
++#define IRQ_GPIOB2 (IRQ_GPIO_CHAIN_START + 10)
++#define IRQ_GPIOB3 (IRQ_GPIO_CHAIN_START + 11)
++#define IRQ_GPIOB4 (IRQ_GPIO_CHAIN_START + 12)
++#define IRQ_GPIOB5 (IRQ_GPIO_CHAIN_START + 13)
++#define IRQ_GPIOB6 (IRQ_GPIO_CHAIN_START + 14)
++#define IRQ_GPIOB7 (IRQ_GPIO_CHAIN_START + 15)
++#define IRQ_GPIOC0 (IRQ_GPIO_CHAIN_START + 16)
++#define IRQ_GPIOC1 (IRQ_GPIO_CHAIN_START + 17)
++#define IRQ_GPIOC2 (IRQ_GPIO_CHAIN_START + 18)
++#define IRQ_GPIOC3 (IRQ_GPIO_CHAIN_START + 19)
++#define IRQ_GPIOC4 (IRQ_GPIO_CHAIN_START + 20)
++#define IRQ_GPIOC5 (IRQ_GPIO_CHAIN_START + 21)
++#define IRQ_GPIOC6 (IRQ_GPIO_CHAIN_START + 22)
++#define IRQ_GPIOC7 (IRQ_GPIO_CHAIN_START + 23)
++#define IRQ_GPIOD0 (IRQ_GPIO_CHAIN_START + 24)
++#define IRQ_GPIOD1 (IRQ_GPIO_CHAIN_START + 25)
++#define IRQ_GPIOD2 (IRQ_GPIO_CHAIN_START + 26)
++#define IRQ_GPIOD3 (IRQ_GPIO_CHAIN_START + 27)
++#define IRQ_GPIOD4 (IRQ_GPIO_CHAIN_START + 28)
++#define IRQ_GPIOD5 (IRQ_GPIO_CHAIN_START + 29)
++#define IRQ_GPIOD6 (IRQ_GPIO_CHAIN_START + 30)
++#define IRQ_GPIOD7 (IRQ_GPIO_CHAIN_START + 31)
++#define IRQ_GPIOE0 (IRQ_GPIO_CHAIN_START + 32)
++#define IRQ_GPIOE1 (IRQ_GPIO_CHAIN_START + 33)
++#define IRQ_GPIOE2 (IRQ_GPIO_CHAIN_START + 34)
++#define IRQ_GPIOE3 (IRQ_GPIO_CHAIN_START + 35)
++#define IRQ_GPIOE4 (IRQ_GPIO_CHAIN_START + 36)
++#define IRQ_GPIOE5 (IRQ_GPIO_CHAIN_START + 37)
++#define IRQ_GPIOE6 (IRQ_GPIO_CHAIN_START + 38)
++#define IRQ_GPIOE7 (IRQ_GPIO_CHAIN_START + 39)
++#define IRQ_GPIOF0 (IRQ_GPIO_CHAIN_START + 40)
++#define IRQ_GPIOF1 (IRQ_GPIO_CHAIN_START + 41)
++#define IRQ_GPIOF2 (IRQ_GPIO_CHAIN_START + 42)
++#define IRQ_GPIOF3 (IRQ_GPIO_CHAIN_START + 43)
++#define IRQ_GPIOF4 (IRQ_GPIO_CHAIN_START + 44)
++#define IRQ_GPIOF5 (IRQ_GPIO_CHAIN_START + 45)
++#define IRQ_GPIOF6 (IRQ_GPIO_CHAIN_START + 46)
++#define IRQ_GPIOF7 (IRQ_GPIO_CHAIN_START + 47)
++#define IRQ_GPIOG0 (IRQ_GPIO_CHAIN_START + 48)
++#define IRQ_GPIOG1 (IRQ_GPIO_CHAIN_START + 49)
++#define IRQ_GPIOG2 (IRQ_GPIO_CHAIN_START + 50)
++#define IRQ_GPIOG3 (IRQ_GPIO_CHAIN_START + 51)
++#define IRQ_GPIOG4 (IRQ_GPIO_CHAIN_START + 52)
++#define IRQ_GPIOG5 (IRQ_GPIO_CHAIN_START + 53)
++#define IRQ_GPIOG6 (IRQ_GPIO_CHAIN_START + 54)
++#define IRQ_GPIOG7 (IRQ_GPIO_CHAIN_START + 55)
++#define IRQ_GPIOH0 (IRQ_GPIO_CHAIN_START + 56)
++#define IRQ_GPIOH1 (IRQ_GPIO_CHAIN_START + 57)
++#define IRQ_GPIOH2 (IRQ_GPIO_CHAIN_START + 58)
++#define IRQ_GPIOH3 (IRQ_GPIO_CHAIN_START + 59)
++#define IRQ_GPIOH4 (IRQ_GPIO_CHAIN_START + 60)
++#define IRQ_GPIOH5 (IRQ_GPIO_CHAIN_START + 61)
++#define IRQ_GPIOH6 (IRQ_GPIO_CHAIN_START + 62)
++#define IRQ_GPIOH7 (IRQ_GPIO_CHAIN_START + 63)
++#define IRQ_GPIOI0 (IRQ_GPIO_CHAIN_START + 64)
++#define IRQ_GPIOI1 (IRQ_GPIO_CHAIN_START + 65)
++#define IRQ_GPIOI2 (IRQ_GPIO_CHAIN_START + 66)
++#define IRQ_GPIOI3 (IRQ_GPIO_CHAIN_START + 67)
++#define IRQ_GPIOI4 (IRQ_GPIO_CHAIN_START + 68)
++#define IRQ_GPIOI5 (IRQ_GPIO_CHAIN_START + 69)
++#define IRQ_GPIOI6 (IRQ_GPIO_CHAIN_START + 70)
++#define IRQ_GPIOI7 (IRQ_GPIO_CHAIN_START + 71)
++#define IRQ_GPIOJ0 (IRQ_GPIO_CHAIN_START + 72)
++#define IRQ_GPIOJ1 (IRQ_GPIO_CHAIN_START + 73)
++#define IRQ_GPIOJ2 (IRQ_GPIO_CHAIN_START + 74)
++#define IRQ_GPIOJ3 (IRQ_GPIO_CHAIN_START + 75)
++#define IRQ_GPIOJ4 (IRQ_GPIO_CHAIN_START + 76)
++#define IRQ_GPIOJ5 (IRQ_GPIO_CHAIN_START + 77)
++#define IRQ_GPIOJ6 (IRQ_GPIO_CHAIN_START + 78)
++#define IRQ_GPIOJ7 (IRQ_GPIO_CHAIN_START + 79)
++#define IRQ_GPIOK0 (IRQ_GPIO_CHAIN_START + 80)
++#define IRQ_GPIOK1 (IRQ_GPIO_CHAIN_START + 81)
++#define IRQ_GPIOK2 (IRQ_GPIO_CHAIN_START + 82)
++#define IRQ_GPIOK3 (IRQ_GPIO_CHAIN_START + 83)
++#define IRQ_GPIOK4 (IRQ_GPIO_CHAIN_START + 84)
++#define IRQ_GPIOK5 (IRQ_GPIO_CHAIN_START + 85)
++#define IRQ_GPIOK6 (IRQ_GPIO_CHAIN_START + 86)
++#define IRQ_GPIOK7 (IRQ_GPIO_CHAIN_START + 87)
++#define IRQ_GPIOL0 (IRQ_GPIO_CHAIN_START + 88)
++#define IRQ_GPIOL1 (IRQ_GPIO_CHAIN_START + 89)
++#define IRQ_GPIOL2 (IRQ_GPIO_CHAIN_START + 90)
++#define IRQ_GPIOL3 (IRQ_GPIO_CHAIN_START + 91)
++#define IRQ_GPIOL4 (IRQ_GPIO_CHAIN_START + 92)
++#define IRQ_GPIOL5 (IRQ_GPIO_CHAIN_START + 93)
++#define IRQ_GPIOL6 (IRQ_GPIO_CHAIN_START + 94)
++#define IRQ_GPIOL7 (IRQ_GPIO_CHAIN_START + 95)
++#define IRQ_GPIOM0 (IRQ_GPIO_CHAIN_START + 96)
++#define IRQ_GPIOM1 (IRQ_GPIO_CHAIN_START + 97)
++#define IRQ_GPIOM2 (IRQ_GPIO_CHAIN_START + 98)
++#define IRQ_GPIOM3 (IRQ_GPIO_CHAIN_START + 99)
++#define IRQ_GPIOM4 (IRQ_GPIO_CHAIN_START + 100)
++#define IRQ_GPIOM5 (IRQ_GPIO_CHAIN_START + 101)
++#define IRQ_GPIOM6 (IRQ_GPIO_CHAIN_START + 102)
++#define IRQ_GPIOM7 (IRQ_GPIO_CHAIN_START + 103)
++#define IRQ_GPION0 (IRQ_GPIO_CHAIN_START + 104)
++#define IRQ_GPION1 (IRQ_GPIO_CHAIN_START + 105)
++#define IRQ_GPION2 (IRQ_GPIO_CHAIN_START + 106)
++#define IRQ_GPION3 (IRQ_GPIO_CHAIN_START + 107)
++#define IRQ_GPION4 (IRQ_GPIO_CHAIN_START + 108)
++#define IRQ_GPION5 (IRQ_GPIO_CHAIN_START + 109)
++#define IRQ_GPION6 (IRQ_GPIO_CHAIN_START + 110)
++#define IRQ_GPION7 (IRQ_GPIO_CHAIN_START + 111)
++#define IRQ_GPIOO0 (IRQ_GPIO_CHAIN_START + 112)
++#define IRQ_GPIOO1 (IRQ_GPIO_CHAIN_START + 113)
++#define IRQ_GPIOO2 (IRQ_GPIO_CHAIN_START + 114)
++#define IRQ_GPIOO3 (IRQ_GPIO_CHAIN_START + 115)
++#define IRQ_GPIOO4 (IRQ_GPIO_CHAIN_START + 116)
++#define IRQ_GPIOO5 (IRQ_GPIO_CHAIN_START + 117)
++#define IRQ_GPIOO6 (IRQ_GPIO_CHAIN_START + 118)
++#define IRQ_GPIOO7 (IRQ_GPIO_CHAIN_START + 119)
++#define IRQ_GPIOP0 (IRQ_GPIO_CHAIN_START + 120)
++#define IRQ_GPIOP1 (IRQ_GPIO_CHAIN_START + 121)
++#define IRQ_GPIOP2 (IRQ_GPIO_CHAIN_START + 122)
++#define IRQ_GPIOP3 (IRQ_GPIO_CHAIN_START + 123)
++#define IRQ_GPIOP4 (IRQ_GPIO_CHAIN_START + 124)
++#define IRQ_GPIOP5 (IRQ_GPIO_CHAIN_START + 125)
++#define IRQ_GPIOP6 (IRQ_GPIO_CHAIN_START + 126)
++#define IRQ_GPIOP7 (IRQ_GPIO_CHAIN_START + 127)
++#define IRQ_GPIOQ0 (IRQ_GPIO_CHAIN_START + 128)
++#define IRQ_GPIOQ1 (IRQ_GPIO_CHAIN_START + 129)
++#define IRQ_GPIOQ2 (IRQ_GPIO_CHAIN_START + 130)
++#define IRQ_GPIOQ3 (IRQ_GPIO_CHAIN_START + 131)
++#define IRQ_GPIOQ4 (IRQ_GPIO_CHAIN_START + 132)
++#define IRQ_GPIOQ5 (IRQ_GPIO_CHAIN_START + 133)
++#define IRQ_GPIOQ6 (IRQ_GPIO_CHAIN_START + 134)
++#define IRQ_GPIOQ7 (IRQ_GPIO_CHAIN_START + 135)
++#define IRQ_GPIOR0 (IRQ_GPIO_CHAIN_START + 136)
++#define IRQ_GPIOR1 (IRQ_GPIO_CHAIN_START + 137)
++#define IRQ_GPIOR2 (IRQ_GPIO_CHAIN_START + 138)
++#define IRQ_GPIOR3 (IRQ_GPIO_CHAIN_START + 139)
++#define IRQ_GPIOR4 (IRQ_GPIO_CHAIN_START + 140)
++#define IRQ_GPIOR5 (IRQ_GPIO_CHAIN_START + 141)
++#define IRQ_GPIOR6 (IRQ_GPIO_CHAIN_START + 142)
++#define IRQ_GPIOR7 (IRQ_GPIO_CHAIN_START + 143)
++#define IRQ_GPIOS0 (IRQ_GPIO_CHAIN_START + 144)
++#define IRQ_GPIOS1 (IRQ_GPIO_CHAIN_START + 145)
++#define IRQ_GPIOS2 (IRQ_GPIO_CHAIN_START + 146)
++#define IRQ_GPIOS3 (IRQ_GPIO_CHAIN_START + 147)
++#define IRQ_GPIOS4 (IRQ_GPIO_CHAIN_START + 148)
++#define IRQ_GPIOS5 (IRQ_GPIO_CHAIN_START + 149)
++#define IRQ_GPIOS6 (IRQ_GPIO_CHAIN_START + 150)
++#define IRQ_GPIOS7 (IRQ_GPIO_CHAIN_START + 151)
++
++#if defined(CONFIG_ARCH_AST2400) || defined(CONFIG_ARCH_AST1520)
++
++#define IRQ_GPIOT0 (IRQ_GPIO_CHAIN_START + 152)
++#define IRQ_GPIOT1 (IRQ_GPIO_CHAIN_START + 153)
++#define IRQ_GPIOT2 (IRQ_GPIO_CHAIN_START + 154)
++#define IRQ_GPIOT3 (IRQ_GPIO_CHAIN_START + 155)
++#define IRQ_GPIOT4 (IRQ_GPIO_CHAIN_START + 156)
++#define IRQ_GPIOT5 (IRQ_GPIO_CHAIN_START + 157)
++#define IRQ_GPIOT6 (IRQ_GPIO_CHAIN_START + 158)
++#define IRQ_GPIOT7 (IRQ_GPIO_CHAIN_START + 159)
++#define IRQ_GPIOU0 (IRQ_GPIO_CHAIN_START + 161)
++#define IRQ_GPIOU1 (IRQ_GPIO_CHAIN_START + 162)
++#define IRQ_GPIOU2 (IRQ_GPIO_CHAIN_START + 163)
++#define IRQ_GPIOU3 (IRQ_GPIO_CHAIN_START + 164)
++#define IRQ_GPIOU4 (IRQ_GPIO_CHAIN_START + 165)
++#define IRQ_GPIOU5 (IRQ_GPIO_CHAIN_START + 166)
++#define IRQ_GPIOU6 (IRQ_GPIO_CHAIN_START + 167)
++#define IRQ_GPIOU7 (IRQ_GPIO_CHAIN_START + 168)
++#define IRQ_GPIOV0 (IRQ_GPIO_CHAIN_START + 169)
++#define IRQ_GPIOV1 (IRQ_GPIO_CHAIN_START + 170)
++#define IRQ_GPIOV2 (IRQ_GPIO_CHAIN_START + 171)
++#define IRQ_GPIOV3 (IRQ_GPIO_CHAIN_START + 172)
++#define IRQ_GPIOV4 (IRQ_GPIO_CHAIN_START + 173)
++#define IRQ_GPIOV5 (IRQ_GPIO_CHAIN_START + 174)
++#define IRQ_GPIOV6 (IRQ_GPIO_CHAIN_START + 175)
++#define IRQ_GPIOV7 (IRQ_GPIO_CHAIN_START + 176)
++#define IRQ_GPIOW0 (IRQ_GPIO_CHAIN_START + 177)
++#define IRQ_GPIOW1 (IRQ_GPIO_CHAIN_START + 178)
++#define IRQ_GPIOW2 (IRQ_GPIO_CHAIN_START + 179)
++#define IRQ_GPIOW3 (IRQ_GPIO_CHAIN_START + 181)
++#define IRQ_GPIOW4 (IRQ_GPIO_CHAIN_START + 182)
++#define IRQ_GPIOW5 (IRQ_GPIO_CHAIN_START + 183)
++#define IRQ_GPIOW6 (IRQ_GPIO_CHAIN_START + 184)
++#define IRQ_GPIOW7 (IRQ_GPIO_CHAIN_START + 185)
++#define IRQ_GPIOX0 (IRQ_GPIO_CHAIN_START + 186)
++#define IRQ_GPIOX1 (IRQ_GPIO_CHAIN_START + 187)
++#define IRQ_GPIOX2 (IRQ_GPIO_CHAIN_START + 188)
++#define IRQ_GPIOX3 (IRQ_GPIO_CHAIN_START + 189)
++#define IRQ_GPIOX4 (IRQ_GPIO_CHAIN_START + 190)
++#define IRQ_GPIOX5 (IRQ_GPIO_CHAIN_START + 191)
++#define IRQ_GPIOX6 (IRQ_GPIO_CHAIN_START + 192)
++#define IRQ_GPIOX7 (IRQ_GPIO_CHAIN_START + 193)
++#define IRQ_GPIOY0 (IRQ_GPIO_CHAIN_START + 194)
++#define IRQ_GPIOY1 (IRQ_GPIO_CHAIN_START + 195)
++#define IRQ_GPIOY2 (IRQ_GPIO_CHAIN_START + 196)
++#define IRQ_GPIOY3 (IRQ_GPIO_CHAIN_START + 197)
++#define IRQ_GPIOY4 (IRQ_GPIO_CHAIN_START + 198)
++#define IRQ_GPIOY5 (IRQ_GPIO_CHAIN_START + 199)
++#define IRQ_GPIOY6 (IRQ_GPIO_CHAIN_START + 200)
++#define IRQ_GPIOY7 (IRQ_GPIO_CHAIN_START + 201)
++#define IRQ_GPIOZ0 (IRQ_GPIO_CHAIN_START + 202)
++#define IRQ_GPIOZ1 (IRQ_GPIO_CHAIN_START + 203)
++#define IRQ_GPIOZ2 (IRQ_GPIO_CHAIN_START + 204)
++#define IRQ_GPIOZ3 (IRQ_GPIO_CHAIN_START + 205)
++#define IRQ_GPIOZ4 (IRQ_GPIO_CHAIN_START + 206)
++#define IRQ_GPIOZ5 (IRQ_GPIO_CHAIN_START + 207)
++#define IRQ_GPIOZ6 (IRQ_GPIO_CHAIN_START + 208)
++#define IRQ_GPIOZ7 (IRQ_GPIO_CHAIN_START + 209)
++#define IRQ_GPIOAA0 (IRQ_GPIO_CHAIN_START + 210)
++#define IRQ_GPIOAA1 (IRQ_GPIO_CHAIN_START + 211)
++#define IRQ_GPIOAA2 (IRQ_GPIO_CHAIN_START + 212)
++#define IRQ_GPIOAA3 (IRQ_GPIO_CHAIN_START + 213)
++#define IRQ_GPIOAA4 (IRQ_GPIO_CHAIN_START + 214)
++#define IRQ_GPIOAA5 (IRQ_GPIO_CHAIN_START + 215)
++#define IRQ_GPIOAA6 (IRQ_GPIO_CHAIN_START + 216)
++#define IRQ_GPIOAA7 (IRQ_GPIO_CHAIN_START + 217)
++#define IRQ_GPIOBB0 (IRQ_GPIO_CHAIN_START + 218)
++#define IRQ_GPIOBB1 (IRQ_GPIO_CHAIN_START + 219)
++#define IRQ_GPIOBB2 (IRQ_GPIO_CHAIN_START + 220)
++#define IRQ_GPIOBB3 (IRQ_GPIO_CHAIN_START + 221)
++#define IRQ_GPIOBB4 (IRQ_GPIO_CHAIN_START + 222)
++#define IRQ_GPIOBB5 (IRQ_GPIO_CHAIN_START + 223)
++#define IRQ_GPIOBB6 (IRQ_GPIO_CHAIN_START + 224)
++#define IRQ_GPIOBB7 (IRQ_GPIO_CHAIN_START + 225)
++#endif
++
++#endif
+diff --git a/arch/arm/mach-aspeed/include/mach/ast_lcd.h b/arch/arm/mach-aspeed/include/mach/ast_lcd.h
+new file mode 100755
+index 0000000..20963eb
+--- /dev/null
++++ b/arch/arm/mach-aspeed/include/mach/ast_lcd.h
+@@ -0,0 +1,61 @@
++ /********************************************************************************
++* File Name : drivers/video/ast_lcd.h
++* Author : Ryan Chen
++* Description : ASPEED LCD Panel Timing
++*
++* Copyright (C) ASPEED Tech. Inc.
++* This program is free software; you can redistribute it and/or modify
++* it under the terms of the GNU General Public License as published by the Free Software Foundation;
++* either version 2 of the License, or (at your option) any later version.
++*
++* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
++* without even the implied warranty of MERCHANTABILITY or
++* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
++*
++* You should have received a copy of the GNU General Public License
++* along with this program; if not, write to the Free Software
++* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++
++* History :
++* 1. 2012/12/27 Ryan Chen create this file
++*
++*
++********************************************************************************/
++#include <linux/fb.h>
++
++//# Define IO __ for control
++#define YUV_MODE 0x4630
++#define CHANGE_YUV_ADDR 0x4631
++#define CHANGE_ADDR 0x4632
++#define OVERSCAN 0x4634
++
++
++enum astfb_color_format {
++ ASTFB_COLOR_RGB565 = 0,
++ ASTFB_COLOR_RGB888,
++ ASTFB_COLOR_YUV444,
++ ASTFB_COLOR_YUV420,
++};
++
++struct aspeed_lcd_panel {
++ struct fb_videomode mode;
++ signed short width; /* width in mm */
++ signed short height; /* height in mm */
++};
++
++struct ast_monitor_info {
++ int status; //0: no data 1:get data
++ int type; //0:dvi 1:hdmi
++ struct fb_monspecs specs;
++ char edid[256];
++};
++
++struct ast_fb_plat_data {
++ u32 (*get_clk)(void);
++};
++
++int ast_vga_get_info(struct fb_info *fb_info);
++int ast_hdmi_get_info(struct fb_info *fb_info);
++void ast_hdmi_enable(int en);
++int vga_read_edid(void);
++
+diff --git a/arch/arm/mach-aspeed/include/mach/ast_lpc_irqs.h b/arch/arm/mach-aspeed/include/mach/ast_lpc_irqs.h
+new file mode 100644
+index 0000000..bbb3878
+--- /dev/null
++++ b/arch/arm/mach-aspeed/include/mach/ast_lpc_irqs.h
+@@ -0,0 +1,34 @@
++/*
++ * arch/arm/plat-aspeed/include/plat/gpio_irqs.h
++ *
++ * Copyright (C) 2012-2020 ASPEED Technology Inc.
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++ */
++
++#ifndef _LPC_IRQS_H_
++#define _LPC_IRQS_H_ 1
++
++#define AST_LPC_IRQ_NUM 7
++
++#define IRQ_KCS0 (IRQ_LPC_CHAIN_START + 0)
++#define IRQ_KCS1 (IRQ_LPC_CHAIN_START + 1)
++#define IRQ_KCS2 (IRQ_LPC_CHAIN_START + 2)
++#define IRQ_KCS3 (IRQ_LPC_CHAIN_START + 3)
++#define IRQ_KCS4 (IRQ_LPC_CHAIN_START + 4)
++#define IRQ_SNOOP0 (IRQ_LPC_CHAIN_START + 5)
++#define IRQ_SNOOP1 (IRQ_LPC_CHAIN_START + 6)
++
++#endif
+diff --git a/arch/arm/mach-aspeed/include/mach/ast_pwm_techo.h b/arch/arm/mach-aspeed/include/mach/ast_pwm_techo.h
+new file mode 100644
+index 0000000..51d4ae3
+--- /dev/null
++++ b/arch/arm/mach-aspeed/include/mach/ast_pwm_techo.h
+@@ -0,0 +1,13 @@
++/*
++ * ast_pwm_techo_h
++ *
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or (at
++ * your option) any later version.
++ */
++struct ast_pwm_driver_data {
++ u32 (*get_pwm_clock)(void);
++};
++
+diff --git a/arch/arm/mach-aspeed/include/mach/ast_spi.h b/arch/arm/mach-aspeed/include/mach/ast_spi.h
+new file mode 100755
+index 0000000..d612967
+--- /dev/null
++++ b/arch/arm/mach-aspeed/include/mach/ast_spi.h
+@@ -0,0 +1,14 @@
++/*
++ * ast_spi_h
++ *
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or (at
++ * your option) any later version.
++ */
++
++struct ast_spi_driver_data {
++ u32 (*get_div)(u32 max_speed_hz);
++ u16 num_chipselect;
++};
+diff --git a/arch/arm/mach-aspeed/include/mach/ast_video.h b/arch/arm/mach-aspeed/include/mach/ast_video.h
+new file mode 100644
+index 0000000..18f9189
+--- /dev/null
++++ b/arch/arm/mach-aspeed/include/mach/ast_video.h
+@@ -0,0 +1,89 @@
++ /********************************************************************************
++* File Name : drivers/video/ast_video.h
++* Author : Ryan Chen
++* Description : ASPEED Video Engine
++*
++* Copyright (C) ASPEED Tech. Inc.
++* This program is free software; you can redistribute it and/or modify
++* it under the terms of the GNU General Public License as published by the Free Software Foundation;
++* either version 2 of the License, or (at your option) any later version.
++*
++* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
++* without even the implied warranty of MERCHANTABILITY or
++* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
++*
++* You should have received a copy of the GNU General Public License
++* along with this program; if not, write to the Free Software
++* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++
++* History :
++* 1. 2012/12/27 Ryan Chen create this file
++*
++*
++********************************************************************************/
++typedef enum ast_video_mode {
++ VIDEO_SINGLE_MODE = 0,
++ VIDEO_FRAME_MODE,
++ VIDEO_STREAM_MODE,
++} video_mode;
++
++//VR08[2]
++typedef enum ast_video_source {
++ VIDEO_SOURCE_UNKNOW = 0, //maybe memory .. TODO ...
++ VIDEO_SOURCE_INTERNAL,
++ VIDEO_SOURCE_EXTERNAL,
++} video_source;
++
++//VR08[5]
++typedef enum ast_vga_mode {
++ VIDEO_VGA_DIRECT_MODE = 0,
++ VIDEO_VGA_CAPTURE_MODE,
++} vga_mode;
++
++//VR08[4]
++typedef enum ast_video_dis_en {
++ VIDEO_EXT_DE_SIGNAL = 0,
++ VIDEO_INT_DE_SIGNAL,
++} display_enable;
++
++typedef enum video_compress_format {
++ VIDEO_YUV444 = 0,
++ VIDEO_YUV420,
++} compress_formate;
++
++typedef enum video_color_format {
++ VIDEO_COLOR_RGB565 = 0,
++ VIDEO_COLOR_RGB888,
++ VIDEO_COLOR_YUV444,
++ VIDEO_COLOR_YUV420,
++} color_formate;
++
++typedef enum vga_color_mode {
++ VGA_NO_SIGNAL = 0,
++ EGA_MODE,
++ VGA_MODE,
++ VGA_15BPP_MODE,
++ VGA_16BPP_MODE,
++ VGA_32BPP_MODE,
++} color_mode;
++
++typedef enum video_stage {
++ NONE,
++ POLARITY,
++ RESOLUTION,
++ INIT,
++ RUN,
++} stage;
++
++struct ast_video_plat_data {
++ u32 (*get_clk)(void);
++ void (*ctrl_reset)(void);
++ void (*vga_display)(u8 enable);
++ u32 (*get_vga_base)(void);
++ video_source input_source;
++ video_mode mode;
++ u8 rc4_enable;
++ u8 scaling;
++ compress_formate compress;
++};
++
+diff --git a/arch/arm/mach-aspeed/include/mach/ast_wdt.h b/arch/arm/mach-aspeed/include/mach/ast_wdt.h
+new file mode 100755
+index 0000000..6d7d7f47
+--- /dev/null
++++ b/arch/arm/mach-aspeed/include/mach/ast_wdt.h
+@@ -0,0 +1,11 @@
++/*
++ * ast_wdt_h
++ *
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or (at
++ * your option) any later version.
++ */
++
++ extern void ast_soc_wdt_reset(void);
+diff --git a/arch/arm/mach-aspeed/include/mach/debug-macro.S b/arch/arm/mach-aspeed/include/mach/debug-macro.S
+new file mode 100644
+index 0000000..0b7c927
+--- /dev/null
++++ b/arch/arm/mach-aspeed/include/mach/debug-macro.S
+@@ -0,0 +1,22 @@
++/* debug-macro.S
++ *
++ * Debugging macro include header
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++*/
++#include <mach/platform.h>
++#include <mach/hardware.h>
++
++ .macro addruart, rx, tmp
++ mrc p15, 0, \rx, c1, c0
++ tst \rx, #1 @ MMU enabled?
++ ldreq \rx, =AST_UART0_BASE
++ ldrne \rx, =IO_ADDRESS(AST_UART0_BASE)
++ orr \rx, \rx, #0x00012000
++ .endm
++
++#define UART_SHIFT 2
++#include <asm/hardware/debug-8250.S>
+diff --git a/arch/arm/mach-aspeed/include/mach/dma.h b/arch/arm/mach-aspeed/include/mach/dma.h
+new file mode 100644
+index 0000000..36c141d
+--- /dev/null
++++ b/arch/arm/mach-aspeed/include/mach/dma.h
+@@ -0,0 +1,25 @@
++/*
++ * dma.h
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++ */
++#ifndef __ASM_ARCH_DMA_H
++#define __ASM_ARCH_DMA_H
++
++#define MAX_DMA_ADDRESS 0xffffffff
++
++#define MAX_DMA_CHANNELS 0
++
++#endif /* _ASM_ARCH_DMA_H */
+diff --git a/arch/arm/mach-aspeed/include/mach/entry-macro.S b/arch/arm/mach-aspeed/include/mach/entry-macro.S
+new file mode 100644
+index 0000000..88b4417
+--- /dev/null
++++ b/arch/arm/mach-aspeed/include/mach/entry-macro.S
+@@ -0,0 +1,191 @@
++/*
++ * entry-macro.S
++ *
++ * This file is licensed under the terms of the GNU General Public
++ * License version 2. This program is licensed "as is" without any
++ * warranty of any kind, whether express or implied.
++ */
++#include <mach/hardware.h>
++#include <mach/irqs.h>
++#include <mach/platform.h>
++#include <plat/regs-intr.h>
++
++ .macro disable_fiq
++ .endm
++
++ .macro get_irqnr_preamble, base, tmp
++ ldr \base, =IO_ADDRESS(AST_VIC_BASE)
++ .endm
++
++ .macro arch_ret_to_user, tmp1, tmp2
++ .endm
++#if 1
++
++#if defined(NEW_VIC)
++ .macro get_irqnr_and_base, irqnr, irqstat, base, tmp
++
++ ldr \tmp, =IO_ADDRESS(AST_SCU_BASE)
++ ldr \irqnr, [\tmp, #0x44]
++
++ cmp \irqnr, #0
++ beq 2000f
++
++1000: /* pass1 */
++ cmp \irqnr, #32
++ ble 1001f
++ ldr \tmp, =IO_ADDRESS(AST_VIC_BASE)
++ ldr \irqstat, [\tmp, #0x84]
++ sub \irqnr, \irqnr, #32
++ mov \tmp, #32
++ sub \tmp, \tmp, \irqnr
++ mov \irqstat, \irqstat, lsl \tmp /* mask uncompare parts */
++ mov \irqstat, \irqstat, lsr \tmp
++ mov \irqnr, #63
++ clz \tmp, \irqstat
++ cmp \tmp, #32
++ bne 3000f
++ mov \irqnr, #32
++1001:
++ ldr \tmp, =IO_ADDRESS(AST_VIC_BASE)
++ ldr \irqstat, [\tmp, #0x00]
++ mov \tmp, #32
++ sub \tmp, \tmp, \irqnr
++ mov \irqstat, \irqstat, lsl \tmp /* mask uncompare parts */
++ mov \irqstat, \irqstat, lsr \tmp
++ mov \irqnr, #31
++ clz \tmp, \irqstat
++ cmp \tmp, #32
++ bne 3000f
++
++2000: /* pass 2 */
++ ldr \tmp, =IO_ADDRESS(AST_VIC_BASE)
++ ldr \irqstat, [\tmp, #0x84]
++ mov \irqnr, #63
++ clz \tmp, \irqstat
++ cmp \tmp, #32
++ bne 3000f
++2001:
++ ldr \tmp, =IO_ADDRESS(AST_VIC_BASE)
++ ldr \irqstat, [\tmp, #0x00]
++ mov \irqnr, #31
++ clz \tmp, \irqstat
++ cmp \tmp, #32
++ beq 4000f /* not find */
++
++3000: /* find */
++ sub \irqnr, \irqnr, \tmp
++ ldr \tmp, =IO_ADDRESS(AST_SCU_BASE)
++ str \irqnr, [\tmp, #0x44]
++ cmp \irqnr, #64
++4000: /* done */
++ .endm
++#else
++ .macro get_irqnr_and_base, irqnr, irqstat, base, tmp
++/* FIXME: should not be using soo many LDRs here */
++ ldr \irqnr, =IO_ADDRESS(AST_VIC_BASE)
++ ldr \irqstat, [\irqnr, #ASPEED_VIC_STATUS_OFFSET] @ get masked status
++
++ mov \irqnr, #0
++1001: tst \irqstat, #1
++ bne 1002f
++ add \irqnr, \irqnr, #1
++ mov \irqstat, \irqstat, lsr #1
++ cmp \irqnr, #31
++ bcc 1001b
++1002: /* EQ will be set if we reach 31 */
++ .endm
++
++#endif
++#else
++
++ .macro get_irqnr_and_base, irqnr, irqstat, base, tmp
++
++ /*********************************************/
++ /* load VIC (VIC1) status value into irqstat */
++ /*********************************************/
++ ldr \irqnr, =IO_ADDRESS(MVP2_VIC_BASE)
++ ldr \irqstat, [\irqnr, #MVP2_VIC_STATUS_OFFSET]
++
++
++ /**********************************************/
++ /* check each status bit and start from bit 0 */
++ /**********************************************/
++ mov \irqnr, #0
++1000: tst \irqstat, #1 /* Check irqstat[irqnr] is 1 or not. */
++ bne 1100f /* If irqstat[irqnr] is 1, service */
++ /* this interrupt. */
++1001:
++ /* check next bit */
++ add \irqnr, \irqnr, #1
++ mov \irqstat, \irqstat, lsr #1
++
++ cmp \irqnr, #32 /* If irqnr is number 32, all bits on VIC1 */
++ beq 1300f /* have been checked and leave this macro. */
++ /* Note that the Zero bit should be 1. */
++
++ bne 1000b /* continue to check next bit */
++
++
++
++1100: ldr \irqstat, =INT_VIC2IRQ /* interrupt from VIC2? */
++ cmp \irqnr, \irqstat
++
++ bne 1300f /* Interupt isn't from VIC2 (i.e. irqnr != INT_VIC2IRQ). */
++ /* Leave this macro with irqnr isn't changed and keep Zero */
++ /* flag not set */
++
++
++ /***************************************/
++ /* load VIC2 status value into irqstat */
++ /***************************************/
++#if 0
++ ldr \irqnr, =IO_ADDRESS(MVP2_VIC2_BASE)
++ ldr \irqstat, [\irqnr, #MVP2_VIC_STATUS_OFFSET]
++#else
++ ldr \irqnr, =IO_ADDRESS(MVP2_VIC_BASE)
++ ldr \irqstat, =0x1000
++ add \irqnr, \irqnr, \irqstat
++ ldr \irqstat, [\irqnr, #MVP2_VIC_STATUS_OFFSET]
++#endif
++
++ /***********************************************/
++ /* Check each status bit and start from bit 0. */
++ /* Note that bit 0 in VIC2 is IRQ number 32. */
++ /***********************************************/
++ mov \irqnr, #32
++1200: tst \irqstat, #1
++ bne 1300f
++
++
++ /* check next bit */
++ add \irqnr, \irqnr, #1
++ mov \irqstat, \irqstat, lsr #1
++
++ cmp \irqnr, #64 /* If irqnr isn't reach 64 */
++ bne 1200b /* continue check irqstat. */
++
++
++
++ /*************************************************************************/
++ /* Examine all the other interrupt bits larger than INT_VIC2IRQ on VIC1. */
++ /*************************************************************************/
++ ldr \irqnr, =IO_ADDRESS(MVP2_VIC_BASE)
++ ldr \irqstat, [\irqnr, #MVP2_VIC_STATUS_OFFSET]
++ mov \irqnr, #INT_VIC2IRQ
++ mov \irqstat, \irqstat, lsr #INT_VIC2IRQ
++ b 1001b
++
++ /* TODO : if needed */
++ /* All interrupt bits on VIC2 have been checked and no bit with value */
++ /* 1 is found. Write 1 to EdgeClearReg[INT_VIC2IRQ] to clear interrupt. */
++
++1300:
++ .endm
++
++#endif
++
++
++
++ .macro irq_prio_table
++ .endm
++
+diff --git a/arch/arm/mach-aspeed/include/mach/ftgmac100_drv.h b/arch/arm/mach-aspeed/include/mach/ftgmac100_drv.h
+new file mode 100644
+index 0000000..40a59e3
+--- /dev/null
++++ b/arch/arm/mach-aspeed/include/mach/ftgmac100_drv.h
+@@ -0,0 +1,18 @@
++/*
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or (at
++ * your option) any later version.
++ */
++
++/* store this information for the driver.. */
++
++struct ftgmac100_eth_data
++{
++ unsigned char dev_addr[6]; //MAC address
++ unsigned char phy_addr; //Phy Address
++ unsigned char phy_id; //Phy ID
++ unsigned char DF_support; //Defragment support
++ unsigned long NCSI_support;
++ unsigned long INTEL_NCSI_EVA_support;
++};
+diff --git a/arch/arm/mach-aspeed/include/mach/gpio.h b/arch/arm/mach-aspeed/include/mach/gpio.h
+new file mode 100644
+index 0000000..9ff3863
+--- /dev/null
++++ b/arch/arm/mach-aspeed/include/mach/gpio.h
+@@ -0,0 +1,352 @@
++/*
++ * arch/arm/mach-aspeed/include/mach/gpio.h
++ *
++ * Support functions for ASPEED GPIO
++ *
++ * Copyright (C) 2012-2020 ASPEED Technology Inc.
++ * Written by Ryan Chen <ryan_chen@aspeedtech.com>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++ *
++ */
++
++#ifndef __ASM_ARCH_ASPEED_GPIO_H
++#define __ASM_ARCH_ASPEED_GPIO_H
++
++#include <linux/kernel.h>
++#include <mach/irqs.h>
++#include <plat/aspeed.h>
++
++/*************************************************************/
++#define GPIO_PORTA 0x0
++#define GPIO_PORTB 0x1
++#define GPIO_PORTC 0x2
++#define GPIO_PORTD 0x3
++#define GPIO_PORTE 0x4
++#define GPIO_PORTF 0x5
++#define GPIO_PORTG 0x6
++#define GPIO_PORTH 0x7
++#define GPIO_PORTI 0x8
++#define GPIO_PORTJ 0x9
++#define GPIO_PORTK 0xa
++#define GPIO_PORTL 0xb
++#define GPIO_PORTM 0xc
++#define GPIO_PORTN 0xd
++#define GPIO_PORTO 0xe
++#define GPIO_PORTP 0xf
++#define GPIO_PORTQ 0x10
++#define GPIO_PORTR 0x11
++#define GPIO_PORTS 0x12
++//AST2300 didn't have PORT TT
++#define GPIO_PORTT 0x13
++#if defined(AST_SOC_G4) || defined(CONFIG_AST2400_BMC)
++#define GPIO_PORTU 0x14
++#define GPIO_PORTV 0x15
++#define GPIO_PORTW 0x16
++#define GPIO_PORTX 0x17
++#define GPIO_PORTY 0x18
++#define GPIO_PORTZ 0x19
++#define GPIO_PORTAA 0x1a
++#define GPIO_PORTAB 0x1b
++#endif
++
++#define GPIO_PER_PORT_PIN_NUM 8
++
++#define GPIO_INPUT_MODE 0
++#define GPIO_OUTPUT_MODE 1
++
++#define GPIO_RISING_EDGE 1
++#define GPIO_FALLING_EDGE 0
++
++#define GPIO_LEVEL_HIGH 1
++#define GPIO_LEVEL_LOW 1
++
++#define GPIO_EDGE_MODE 0
++#define GPIO_LEVEL_MODE 1
++
++#define GPIO_EDGE_LEVEL_MODE 0
++#define GPIO_DUAL_EDGE_MODE 1
++
++#define GPIO_NO_DEBOUNCE 0
++#define GPIO_DEBOUNCE_TIMER0 2 //GPIO 50 as debounce timer
++#define GPIO_DEBOUNCE_TIMER1 1 //GPIO 54 as debounce timer
++#define GPIO_DEBOUNCE_TIMER2 3 //GPIO 58 as debounce timer
++
++#define GPIO_CMD_ARM 0
++#define GPIO_CMD_LPC 1
++#define GPIO_CMD_COPROCESSOR 2
++
++#define PIN_GPIOA0 (0)
++#define PIN_GPIOA1 (1)
++#define PIN_GPIOA2 (2)
++#define PIN_GPIOA3 (3)
++#define PIN_GPIOA4 (4)
++#define PIN_GPIOA5 (5)
++#define PIN_GPIOA6 (6)
++#define PIN_GPIOA7 (7)
++#define PIN_GPIOB0 (8)
++#define PIN_GPIOB1 (9)
++#define PIN_GPIOB2 (10)
++#define PIN_GPIOB3 (11)
++#define PIN_GPIOB4 (12)
++#define PIN_GPIOB5 (13)
++#define PIN_GPIOB6 (14)
++#define PIN_GPIOB7 (15)
++#define PIN_GPIOC0 (16)
++#define PIN_GPIOC1 (17)
++#define PIN_GPIOC2 (18)
++#define PIN_GPIOC3 (19)
++#define PIN_GPIOC4 (20)
++#define PIN_GPIOC5 (21)
++#define PIN_GPIOC6 (22)
++#define PIN_GPIOC7 (23)
++#define PIN_GPIOD0 (24)
++#define PIN_GPIOD1 (25)
++#define PIN_GPIOD2 (26)
++#define PIN_GPIOD3 (27)
++#define PIN_GPIOD4 (28)
++#define PIN_GPIOD5 (29)
++#define PIN_GPIOD6 (30)
++#define PIN_GPIOD7 (31)
++#define PIN_GPIOE0 (32)
++#define PIN_GPIOE1 (33)
++#define PIN_GPIOE2 (34)
++#define PIN_GPIOE3 (35)
++#define PIN_GPIOE4 (36)
++#define PIN_GPIOE5 (37)
++#define PIN_GPIOE6 (38)
++#define PIN_GPIOE7 (39)
++#define PIN_GPIOF0 (40)
++#define PIN_GPIOF1 (41)
++#define PIN_GPIOF2 (42)
++#define PIN_GPIOF3 (43)
++#define PIN_GPIOF4 (44)
++#define PIN_GPIOF5 (45)
++#define PIN_GPIOF6 (46)
++#define PIN_GPIOF7 (47)
++#define PIN_GPIOG0 (48)
++#define PIN_GPIOG1 (49)
++#define PIN_GPIOG2 (50)
++#define PIN_GPIOG3 (51)
++#define PIN_GPIOG4 (52)
++#define PIN_GPIOG5 (53)
++#define PIN_GPIOG6 (54)
++#define PIN_GPIOG7 (55)
++#define PIN_GPIOH0 (56)
++#define PIN_GPIOH1 (57)
++#define PIN_GPIOH2 (58)
++#define PIN_GPIOH3 (59)
++#define PIN_GPIOH4 (60)
++#define PIN_GPIOH5 (61)
++#define PIN_GPIOH6 (62)
++#define PIN_GPIOH7 (63)
++#define PIN_GPIOI0 (64)
++#define PIN_GPIOI1 (65)
++#define PIN_GPIOI2 (66)
++#define PIN_GPIOI3 (67)
++#define PIN_GPIOI4 (68)
++#define PIN_GPIOI5 (69)
++#define PIN_GPIOI6 (70)
++#define PIN_GPIOI7 (71)
++#define PIN_GPIOJ0 (72)
++#define PIN_GPIOJ1 (73)
++#define PIN_GPIOJ2 (74)
++#define PIN_GPIOJ3 (75)
++#define PIN_GPIOJ4 (76)
++#define PIN_GPIOJ5 (77)
++#define PIN_GPIOJ6 (78)
++#define PIN_GPIOJ7 (79)
++#define PIN_GPIOK0 (80)
++#define PIN_GPIOK1 (81)
++#define PIN_GPIOK2 (82)
++#define PIN_GPIOK3 (83)
++#define PIN_GPIOK4 (84)
++#define PIN_GPIOK5 (85)
++#define PIN_GPIOK6 (86)
++#define PIN_GPIOK7 (87)
++#define PIN_GPIOL0 (88)
++#define PIN_GPIOL1 (89)
++#define PIN_GPIOL2 (90)
++#define PIN_GPIOL3 (91)
++#define PIN_GPIOL4 (92)
++#define PIN_GPIOL5 (93)
++#define PIN_GPIOL6 (94)
++#define PIN_GPIOL7 (95)
++#define PIN_GPIOM0 (96)
++#define PIN_GPIOM1 (97)
++#define PIN_GPIOM2 (98)
++#define PIN_GPIOM3 (99)
++#define PIN_GPIOM4 (100)
++#define PIN_GPIOM5 (101)
++#define PIN_GPIOM6 (102)
++#define PIN_GPIOM7 (103)
++#define PIN_GPION0 (104)
++#define PIN_GPION1 (105)
++#define PIN_GPION2 (106)
++#define PIN_GPION3 (107)
++#define PIN_GPION4 (108)
++#define PIN_GPION5 (109)
++#define PIN_GPION6 (110)
++#define PIN_GPION7 (111)
++#define PIN_GPIOO0 (112)
++#define PIN_GPIOO1 (113)
++#define PIN_GPIOO2 (114)
++#define PIN_GPIOO3 (115)
++#define PIN_GPIOO4 (116)
++#define PIN_GPIOO5 (117)
++#define PIN_GPIOO6 (118)
++#define PIN_GPIOO7 (119)
++#define PIN_GPIOP0 (120)
++#define PIN_GPIOP1 (121)
++#define PIN_GPIOP2 (122)
++#define PIN_GPIOP3 (123)
++#define PIN_GPIOP4 (124)
++#define PIN_GPIOP5 (125)
++#define PIN_GPIOP6 (126)
++#define PIN_GPIOP7 (127)
++#define PIN_GPIOQ0 (128)
++#define PIN_GPIOQ1 (129)
++#define PIN_GPIOQ2 (130)
++#define PIN_GPIOQ3 (131)
++#define PIN_GPIOQ4 (132)
++#define PIN_GPIOQ5 (133)
++#define PIN_GPIOQ6 (134)
++#define PIN_GPIOQ7 (135)
++#define PIN_GPIOR0 (136)
++#define PIN_GPIOR1 (137)
++#define PIN_GPIOR2 (138)
++#define PIN_GPIOR3 (139)
++#define PIN_GPIOR4 (140)
++#define PIN_GPIOR5 (141)
++#define PIN_GPIOR6 (142)
++#define PIN_GPIOR7 (143)
++#define PIN_GPIOS0 (144)
++#define PIN_GPIOS1 (145)
++#define PIN_GPIOS2 (146)
++#define PIN_GPIOS3 (147)
++#define PIN_GPIOS4 (148)
++#define PIN_GPIOS5 (149)
++#define PIN_GPIOS6 (150)
++#define PIN_GPIOS7 (151)
++#if defined(AST_SOC_G4) || defined(CONFIG_AST2400_BMC)
++#define PIN_GPIOT0 (152)
++#define PIN_GPIOT1 (153)
++#define PIN_GPIOT2 (154)
++#define PIN_GPIOT3 (155)
++#define PIN_GPIOT4 (156)
++#define PIN_GPIOT5 (157)
++#define PIN_GPIOT6 (158)
++#define PIN_GPIOT7 (159)
++#define PIN_GPIOU0 (161)
++#define PIN_GPIOU1 (162)
++#define PIN_GPIOU2 (163)
++#define PIN_GPIOU3 (164)
++#define PIN_GPIOU4 (165)
++#define PIN_GPIOU5 (166)
++#define PIN_GPIOU6 (167)
++#define PIN_GPIOU7 (168)
++#define PIN_GPIOV0 (169)
++#define PIN_GPIOV1 (170)
++#define PIN_GPIOV2 (171)
++#define PIN_GPIOV3 (172)
++#define PIN_GPIOV4 (173)
++#define PIN_GPIOV5 (174)
++#define PIN_GPIOV6 (175)
++#define PIN_GPIOV7 (176)
++#define PIN_GPIOW0 (177)
++#define PIN_GPIOW1 (178)
++#define PIN_GPIOW2 (179)
++#define PIN_GPIOW3 (181)
++#define PIN_GPIOW4 (182)
++#define PIN_GPIOW5 (183)
++#define PIN_GPIOW6 (184)
++#define PIN_GPIOW7 (185)
++#define PIN_GPIOX0 (186)
++#define PIN_GPIOX1 (187)
++#define PIN_GPIOX2 (188)
++#define PIN_GPIOX3 (189)
++#define PIN_GPIOX4 (190)
++#define PIN_GPIOX5 (191)
++#define PIN_GPIOX6 (192)
++#define PIN_GPIOX7 (193)
++#define PIN_GPIOY0 (194)
++#define PIN_GPIOY1 (195)
++#define PIN_GPIOY2 (196)
++#define PIN_GPIOY3 (197)
++#define PIN_GPIOY4 (198)
++#define PIN_GPIOY5 (199)
++#define PIN_GPIOY6 (200)
++#define PIN_GPIOY7 (201)
++#define PIN_GPIOZ0 (202)
++#define PIN_GPIOZ1 (203)
++#define PIN_GPIOZ2 (204)
++#define PIN_GPIOZ3 (205)
++#define PIN_GPIOZ4 (206)
++#define PIN_GPIOZ5 (207)
++#define PIN_GPIOZ6 (208)
++#define PIN_GPIOZ7 (209)
++#define PIN_GPIOAA0 (210)
++#define PIN_GPIOAA1 (211)
++#define PIN_GPIOAA2 (212)
++#define PIN_GPIOAA3 (213)
++#define PIN_GPIOAA4 (214)
++#define PIN_GPIOAA5 (215)
++#define PIN_GPIOAA6 (216)
++#define PIN_GPIOAA7 (217)
++#define PIN_GPIOBB0 (218)
++#define PIN_GPIOBB1 (219)
++#define PIN_GPIOBB2 (220)
++#define PIN_GPIOBB3 (221)
++#define PIN_GPIOBB4 (222)
++#define PIN_GPIOBB5 (223)
++#define PIN_GPIOBB6 (224)
++#define PIN_GPIOBB7 (225)
++#endif
++/*************************************************************/
++#ifndef __ASSEMBLY__
++
++/* callable at any time */
++extern int ast_set_gpio_value(unsigned gpio_pin, int value);
++extern int ast_get_gpio_value(unsigned gpio_pin);
++
++/*-------------------------------------------------------------------------*/
++
++/* wrappers for "new style" GPIO calls. the old AT91-specfic ones should
++ * eventually be removed (along with this errno.h inclusion), and the
++ * gpio request/free calls should probably be implemented.
++ */
++
++//extern int gpio_direction_input(unsigned gpio);
++//extern int gpio_direction_output(unsigned gpio, int value);
++
++static inline int gpio_get_value(unsigned gpio)
++{
++ return ast_get_gpio_value(gpio);
++}
++
++static inline void gpio_set_value(unsigned gpio, int value)
++{
++ ast_set_gpio_value(gpio, value);
++}
++
++#include <asm-generic/gpio.h> /* cansleep wrappers */
++
++#define gpio_to_irq(gpio) (IRQ_GPIO_CHAIN_START + (gpio))
++#define irq_to_gpio(irq) ((irq) - IRQ_GPIO_CHAIN_START)
++
++#endif /* __ASSEMBLY__ */
++
++
++#endif
+diff --git a/arch/arm/mach-aspeed/include/mach/hardware.h b/arch/arm/mach-aspeed/include/mach/hardware.h
+new file mode 100644
+index 0000000..be3f23d
+--- /dev/null
++++ b/arch/arm/mach-aspeed/include/mach/hardware.h
+@@ -0,0 +1,51 @@
++/*
++ * hardware.h
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++ */
++#ifndef __ASM_ARCH_HARDWARE_H
++#define __ASM_ARCH_HARDWARE_H
++
++#include <mach/platform.h>
++
++/*
++ * Where in virtual memory the IO devices (timers, system controllers
++ * and so on)
++ */
++
++#define IO_BASE 0xF8000000 // VA of IO
++/*#define IO_BASE2 0xE0000000 // VA of IO2 (AST1070) */
++
++#ifdef CONFIG_AST_PCIE_EXT
++#define ASPEED_IO_START2 AST_PCIE_WIN_BASE
++#else
++#define ASPEED_IO_START2 AST_LPC_BRIDGE
++#endif
++
++/* macro to get at IO space when running virtually */
++//#define IO_ADDRESS(x) (((x) >> 4) + IO_BASE)
++/*#define IO_ADDRESS(x) (x - 0x10000000 + IO_BASE) */
++#define IO_ADDRESS(x) (x - 0x1e600000 + IO_BASE)
++/*#define IO_ADDRESS2(x) (x - ASPEED_IO_START2 + IO_BASE2) */
++
++//PCIE
++#ifdef CONFIG_AST_PCIE
++#define PCIBIOS_MIN_IO 0x0
++#define PCIBIOS_MIN_MEM 0x0
++#define pcibios_assign_all_busses() 1
++#endif
++
++#endif /* __ASM_ARCH_HARDWARE_H END */
++
+diff --git a/arch/arm/mach-aspeed/include/mach/io.h b/arch/arm/mach-aspeed/include/mach/io.h
+new file mode 100644
+index 0000000..baf86d2
+--- /dev/null
++++ b/arch/arm/mach-aspeed/include/mach/io.h
+@@ -0,0 +1,28 @@
++/*
++ * io.h
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++ */
++#ifndef __ASM_ARM_ARCH_IO_H
++#define __ASM_ARM_ARCH_IO_H
++
++#include <mach/hardware.h>
++#define IO_SPACE_LIMIT 0xffffffff
++
++#define __io(a) ((void __iomem *)(a))
++#define __mem_pci(a) (a)
++#define __mem_isa(a) (a)
++#endif
++
+diff --git a/arch/arm/mach-aspeed/include/mach/irqs.h b/arch/arm/mach-aspeed/include/mach/irqs.h
+new file mode 100644
+index 0000000..d133251
+--- /dev/null
++++ b/arch/arm/mach-aspeed/include/mach/irqs.h
+@@ -0,0 +1,61 @@
++/*
++ * arch/arm/plat-aspeed/include/plat/irqs.h
++ *
++ * Copyright (C) 2012-2020 ASPEED Technology Inc.
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++ */
++
++#include <plat/aspeed.h>
++
++#if defined(CONFIG_ARCH_AST1010)
++#include <mach/ast1010_irqs.h>
++#elif defined(CONFIG_ARCH_AST1510)
++#include <mach/ast1510_irqs.h>
++#elif defined(CONFIG_ARCH_AST1520)
++#include <mach/ast1520_irqs.h>
++#elif defined(CONFIG_ARCH_AST2000)
++#include <mach/ast2000_irqs.h>
++#elif defined(CONFIG_ARCH_AST2100)
++#include <mach/ast2100_irqs.h>
++#elif defined(CONFIG_ARCH_AST2200)
++#include <mach/ast2200_irqs.h>
++#elif defined(CONFIG_ARCH_AST2300)
++#include <mach/ast2300_irqs.h>
++#elif defined(CONFIG_ARCH_AST2400)
++#include <mach/ast2400_irqs.h>
++#elif defined(CONFIG_ARCH_AST2500)
++#include <mach/ast2500_irqs.h>
++#elif defined(CONFIG_ARCH_AST3100)
++#include <mach/ast3100_irqs.h>
++#elif defined(CONFIG_ARCH_AST3200)
++#include <mach/ast3200_irqs.h>
++#else
++#err "no define for irqs.h"
++#endif
++
++#include <mach/ast_gpio_irqs.h>
++//#include <mach/ast_lpc_irqs.h>
++
++/*********************************************************************************/
++//CVIC
++#if defined(CONFIG_ARCH_AST1070)
++//Companion chip irq
++#include <mach/ast1070_irqs.h>
++#endif
++
++#if defined(CONFIG_AST2400_BMC)
++#include <mach/ext_ast2400_irqs.h>
++#endif
+diff --git a/arch/arm/mach-aspeed/include/mach/memory.h b/arch/arm/mach-aspeed/include/mach/memory.h
+new file mode 100644
+index 0000000..d9927b2
+--- /dev/null
++++ b/arch/arm/mach-aspeed/include/mach/memory.h
+@@ -0,0 +1,48 @@
++/*
++ * memory.h
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++ */
++#include <mach/platform.h>
++#include <plat/aspeed.h>
++
++#ifndef __ASM_ARCH_MEMORY_H
++#define __ASM_ARCH_MEMORY_H
++
++/*
++ * Physical DRAM offset.
++ */
++#if defined(AST_SOC_G3) || defined(AST_SOC_G4)
++#define PHYS_OFFSET UL(0x40000000)
++#define BUS_OFFSET UL(0x40000000)
++#elif defined(AST_SOC_G5)
++#define PHYS_OFFSET UL(0x80000000)
++#define BUS_OFFSET UL(0x80000000)
++#else
++#define PHYS_OFFSET UL(0x40000000)
++#define BUS_OFFSET UL(0x40000000)
++#endif
++
++/*
++ * Virtual view <-> DMA view memory address translations
++ * virt_to_bus: Used to translate the virtual address to an
++ * address suitable to be passed to set_dma_addr
++ * bus_to_virt: Used to convert an address for DMA operations
++ * to an address that the kernel can use.
++ */
++#define __virt_to_bus(x) (x - PAGE_OFFSET + BUS_OFFSET)
++#define __bus_to_virt(x) (x - BUS_OFFSET + PAGE_OFFSET)
++
++#endif
+diff --git a/arch/arm/mach-aspeed/include/mach/platform.h b/arch/arm/mach-aspeed/include/mach/platform.h
+new file mode 100644
+index 0000000..8951ffc
+--- /dev/null
++++ b/arch/arm/mach-aspeed/include/mach/platform.h
+@@ -0,0 +1,66 @@
++/*
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++ */
++
++#ifndef _AST_PLATFORM_H_
++#define _AST_PLATFORM_H_ 1
++
++#define AST_PLL_25MHZ 25000000
++#define AST_PLL_24MHZ 24000000
++#define AST_PLL_12MHZ 12000000
++
++#define AST_IO_START 0x1E600000
++#define AST_IO_SIZE 0x00200000
++
++/*********************************************************************************/
++#if defined(CONFIG_ARCH_AST1520)
++#include <mach/ast1520_platform.h>
++#elif defined(CONFIG_ARCH_AST2000)
++#include <mach/ast2000_platform.h>
++#elif defined(CONFIG_ARCH_AST2100)
++#include <mach/ast2100_platform.h>
++#elif defined(CONFIG_ARCH_AST2200)
++#include <mach/ast2200_platform.h>
++#elif defined(CONFIG_ARCH_AST2300)
++#include <mach/ast2300_platform.h>
++#elif defined(CONFIG_ARCH_AST2400)
++#include <mach/ast2400_platform.h>
++#elif defined(CONFIG_ARCH_AST2500)
++#include <mach/ast2500_platform.h>
++#elif defined(CONFIG_ARCH_AST3200)
++#include <mach/ast3200_platform.h>
++#else
++#err "No define for platform.h"
++#endif
++/*********************************************************************************/
++/* Companion Base Address */
++#if defined(CONFIG_ARCH_AST1070)
++#include <mach/ast1070_platform.h>
++#endif
++/*********************************************************************************/
++#define AST_CS0_DEF_BASE 0x20000000 /* CS0 */
++#define AST_CS1_DEF_BASE 0x24000000 /* CS1 */
++#define AST_CS2_DEF_BASE 0x26000000 /* CS2 */
++#define AST_CS3_DEF_BASE 0x28000000 /* CS3 */
++#define AST_CS4_DEF_BASE 0x2a000000 /* CS4 */
++
++#define AST_NOR_SIZE 0x01000000 /* AST2300 NOR size 16MB */
++
++/*
++ * Watchdog
++ */
++#define AST_WDT_VA_BASE (IO_ADDRESS(AST_WDT_BASE))
++
++#endif
+diff --git a/arch/arm/mach-aspeed/include/mach/system.h b/arch/arm/mach-aspeed/include/mach/system.h
+new file mode 100644
+index 0000000..96e90da
+--- /dev/null
++++ b/arch/arm/mach-aspeed/include/mach/system.h
+@@ -0,0 +1,44 @@
++/*
++ * system.h
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++ */
++#ifndef __ASM_ARCH_SYSTEM_H
++#define __ASM_ARCH_SYSTEM_H
++
++#include <mach/hardware.h>
++#include <asm/io.h>
++#include <mach/ast_wdt.h>
++
++static inline void arch_idle(void)
++{
++ /*
++ * This should do all the clock switching
++ * and wait for interrupt tricks
++ */
++ cpu_do_idle();
++}
++
++static inline void arch_reset(char mode)
++{
++ /*
++ * Use WDT to restart system
++ */
++#if defined(CONFIG_AST_WATCHDOG) || defined(CONFIG_AST_WATCHDOG_MODULE)
++ ast_soc_wdt_reset();
++#endif
++}
++
++#endif
+diff --git a/arch/arm/mach-aspeed/include/mach/time.h b/arch/arm/mach-aspeed/include/mach/time.h
+new file mode 100644
+index 0000000..973a0b0
+--- /dev/null
++++ b/arch/arm/mach-aspeed/include/mach/time.h
+@@ -0,0 +1,73 @@
++/*
++ * time.h
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++ */
++#include <asm/system.h>
++#include <asm/mach/time.h>
++#include <asm/param.h>
++
++/*
++ * How long is the timer interval?
++ */
++#define TIMER_INTERVAL (ASPEED_TIMER_CLKRATE / HZ)
++#define TIMER_RELOAD (TIMER_INTERVAL)
++#define TICKS2USECS(x) ((x) / TICKS_PER_uSEC)
++
++/*
++ * Timer
++ */
++#define ASPEED_TIMER0_OFFSET 0x0000 /* Timer0 Offset */
++#define ASPEED_TIMER1_OFFSET 0x0010 /* Timer1 Offset */
++#define ASPEED_TIMER2_OFFSET 0x0020 /* Timer2 Offset */
++#define ASPEED_TIMERRC_OFFSET 0x0030 /* Timer RC Offset */
++
++#define ASPEED_TIMER_CLKRATE (ASPEED_EXTCLK)
++#define ASPEED_EXTCLK (1*1000*1000) /* 1M */
++
++/*
++ * Ticks
++ */
++//#define TICKS_PER_uSEC 40 // IP Cam
++//#define TICKS_PER_uSEC 24 // FPGA
++#define TICKS_PER_uSEC 1 /* ASPEED_EXTCLK / 10 ^ 6 */
++
++#define mSEC_1 1000
++#define mSEC_5 (mSEC_1 * 5)
++#define mSEC_10 (mSEC_1 * 10)
++#define mSEC_25 (mSEC_1 * 25)
++#define SEC_1 (mSEC_1 * 1000)
++
++/*
++ * Timer Control
++ */
++#define TIMER0_ENABLE 0x0001
++#define TIMER1_ENABLE 0x0010
++#define TIMER2_ENABLE 0x0100
++
++#define TIMER0_RefExt 0x0002
++#define TIMER1_RefExt 0x0020
++#define TIMER2_RefExt 0x0200
++
++/*
++ * What does it look like?
++ */
++typedef struct TimerStruct {
++ unsigned long TimerValue;
++ unsigned long TimerLoad;
++ unsigned long TimerMatch1;
++ unsigned long TimerMatch2;
++} TimerStruct_t;
++
+diff --git a/arch/arm/mach-aspeed/include/mach/timex.h b/arch/arm/mach-aspeed/include/mach/timex.h
+new file mode 100644
+index 0000000..e907a30
+--- /dev/null
++++ b/arch/arm/mach-aspeed/include/mach/timex.h
+@@ -0,0 +1,21 @@
++/*
++ * timex.h
++ *
++ * Integrator architecture timex specifications
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++ */
++
++#define CLOCK_TICK_RATE (50000000 / 16)
+diff --git a/arch/arm/mach-aspeed/include/mach/uncompress.h b/arch/arm/mach-aspeed/include/mach/uncompress.h
+new file mode 100644
+index 0000000..896b854
+--- /dev/null
++++ b/arch/arm/mach-aspeed/include/mach/uncompress.h
+@@ -0,0 +1,38 @@
++/*
++ * uncompress.h
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++
++#ifndef __ASM_ARCH_UNCOMPRESS_H
++#define __ASM_ARCH_UNCOMPRESS_H
++
++#include <mach/platform.h>
++#include <mach/aspeed_serial.h>
++
++#define UART_PUT_CHAR (*(volatile unsigned char *)(AST_UART0_BASE + UART_THR))
++#define UART_GET_LSR (*(volatile unsigned char *)(AST_UART0_BASE + UART_LSR))
++
++static void putc(int c)
++{
++
++ /* wait for space in the UART's transmitter */
++ while (!(UART_GET_LSR & UART_LSR_THRE))
++ barrier();
++
++ /* send the character out. */
++ UART_PUT_CHAR = c;
++}
++
++static inline void flush(void)
++{
++ while (UART_GET_LSR & (1 << 3))
++ barrier();
++}
++
++#define arch_decomp_setup()
++#define arch_decomp_wdog()
++
++#endif /* __ASM_ARCH_UNCOMPRESS_H */
+diff --git a/arch/arm/mach-aspeed/include/mach/vmalloc.h b/arch/arm/mach-aspeed/include/mach/vmalloc.h
+new file mode 100644
+index 0000000..3706cf1
+--- /dev/null
++++ b/arch/arm/mach-aspeed/include/mach/vmalloc.h
+@@ -0,0 +1,29 @@
++/*
++ * vmalloc.h
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++ */
++
++/*
++ * Just any arbitrary offset to the start of the vmalloc VM area: the
++ * current 8MB value just means that there will be a 8MB "hole" after the
++ * physical memory until the kernel virtual memory starts. That means that
++ * any out-of-bounds memory accesses will hopefully be caught.
++ * The vmalloc() routines leaves a hole of 4kB between each vmalloced
++ * area for the same reason. ;)
++ */
++#if 0
++#define VMALLOC_OFFSET (8*1024*1024)
++#define VMALLOC_START (((unsigned long)high_memory + VMALLOC_OFFSET) & ~(VMALLOC_OFFSET-1))
++#define VMALLOC_VMADDR(x) ((unsigned long)(x))
++#define VMALLOC_END (PAGE_OFFSET + 0x10000000)
++#else
++#define VMALLOC_END 0xf8000000UL
++#endif
+\ No newline at end of file
+diff --git a/arch/arm/mm/Kconfig b/arch/arm/mm/Kconfig
+index ab5f7a2..d7b499a 100644
+--- a/arch/arm/mm/Kconfig
++++ b/arch/arm/mm/Kconfig
+@@ -180,7 +180,7 @@ config CPU_ARM925T
+ # ARM926T
+ config CPU_ARM926T
+ bool "Support ARM926T processor"
+- depends on ARCH_INTEGRATOR || ARCH_VERSATILE_PB || \
++ depends on ARCH_ASPEED || ARCH_INTEGRATOR || ARCH_VERSATILE_PB || \
+ MACH_VERSATILE_AB || ARCH_OMAP730 || \
+ ARCH_OMAP16XX || MACH_REALVIEW_EB || \
+ ARCH_PNX4008 || ARCH_NETX || CPU_S3C2412 || \
+@@ -188,7 +188,7 @@ config CPU_ARM926T
+ ARCH_AT91SAM9263 || ARCH_AT91SAM9RL || \
+ ARCH_AT91SAM9G20 || ARCH_AT91CAP9 || \
+ ARCH_NS9XXX || ARCH_DAVINCI || ARCH_MX2
+- default y if ARCH_VERSATILE_PB || MACH_VERSATILE_AB || \
++ default y if ARCH_ASPEED || ARCH_VERSATILE_PB || MACH_VERSATILE_AB || \
+ ARCH_OMAP730 || ARCH_OMAP16XX || \
+ ARCH_PNX4008 || ARCH_NETX || CPU_S3C2412 || \
+ ARCH_AT91SAM9260 || ARCH_AT91SAM9261 || \
+diff --git a/arch/arm/plat-aspeed/Makefile b/arch/arm/plat-aspeed/Makefile
+new file mode 100644
+index 0000000..faba830
+--- /dev/null
++++ b/arch/arm/plat-aspeed/Makefile
+@@ -0,0 +1,35 @@
++#
++# Makefile for the linux kernel.
++#
++
++obj-y += irq.o timer.o devs.o ast-scu.o ast-sdmc.o
++
++obj-$(CONFIG_ARCH_AST1070) += ast1070_irq.o ast1070-scu.o ast1070-uart-dma.o dev-ci2c.o dev-cuart.o dev-clpc.o
++
++obj-$(CONFIG_AST_I2C_SLAVE_MODE) += i2c-slave-eeprom.o
++
++obj-$(CONFIG_AST2400_BMC) += ast2400-irq.o ast2400-scu.o dev-ast2400-uart.o #dev-ast2400-i2c.o
++
++#obj-n := dummy.o
++#platform
++obj-y += dev-uart.o dev-vuart.o dev-wdt.o dev-rtc.o dev-gpio.o dev-sgpio.o
++
++#Storage
++obj-y += dev-nor.o dev-nand.o dev-sdhci.o
++
++#bus
++obj-y += dev-i2c.o dev-spi.o dev-ehci.o dev-uhci.o dev-lpc.o dev-peci.o dev-kcs.o dev-mbx.o dev-snoop.o
++
++#dev
++#obj-y += dev-udc11.o
++#net
++obj-y += dev-eth.o
++
++#hwmon
++obj-y += dev-pwm-fan.o dev-adc.o
++
++#video
++obj-y += dev-fb.o dev-video.o
++#obj-m :=
++#obj-n :=
++#obj- :=
+diff --git a/arch/arm/plat-aspeed/ast-scu.c b/arch/arm/plat-aspeed/ast-scu.c
+new file mode 100644
+index 0000000..1f1dde2
+--- /dev/null
++++ b/arch/arm/plat-aspeed/ast-scu.c
+@@ -0,0 +1,1202 @@
++/********************************************************************************
++* File Name : arch/arm/plat-aspeed/ast-scu.c
++* Author : Ryan Chen
++* Description : AST SCU
++*
++* Copyright (C) 2012-2020 ASPEED Technology Inc.
++* This program is free software; you can redistribute it and/or modify
++* it under the terms of the GNU General Public License as published by the Free Software Foundation;
++* either version 2 of the License, or (at your option) any later version.
++* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
++* without even the implied warranty of MERCHANTABILITY or
++* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
++* You should have received a copy of the GNU General Public License
++* along with this program; if not, write to the Free Software
++* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++
++CLK24M
++ |
++ |--> H-PLL -->HCLK
++ |
++ |--> M-PLL -xx->MCLK
++ |
++ |--> V-PLL1 -xx->DCLK
++ |
++ |--> V-PLL2 -xx->D2CLK
++ |
++ |--> USB2PHY -->UTMICLK
++
++
++* History :
++* 1. 2012/08/15 Ryan Chen Create
++*
++********************************************************************************/
++#include <linux/kernel.h>
++#include <linux/module.h>
++#include <linux/delay.h>
++
++#include <mach/platform.h>
++#include <asm/io.h>
++
++#include <mach/hardware.h>
++
++#include <plat/ast-scu.h>
++#include <plat/regs-scu.h>
++
++//#define ASPEED_SCU_LOCK
++//#define ASPEED_SCU_DEBUG
++
++#ifdef ASPEED_SCU_DEBUG
++#define SCUDBUG(fmt, args...) printk("%s() " fmt, __FUNCTION__, ## args)
++#else
++#define SCUDBUG(fmt, args...)
++#endif
++
++#define SCUMSG(fmt, args...) printk(fmt, ## args)
++
++static u32 ast_scu_base = IO_ADDRESS(AST_SCU_BASE);
++
++static inline u32
++ast_scu_read(u32 reg)
++{
++ u32 val;
++
++ val = readl(ast_scu_base + reg);
++
++ SCUDBUG("ast_scu_read : reg = 0x%08x, val = 0x%08x\n", reg, val);
++
++ return val;
++}
++
++static inline void
++ast_scu_write(u32 val, u32 reg)
++{
++ SCUDBUG("ast_scu_write : reg = 0x%08x, val = 0x%08x\n", reg, val);
++#ifdef CONFIG_AST_SCU_LOCK
++ //unlock
++ writel(SCU_PROTECT_UNLOCK, ast_scu_base);
++ writel(val, ast_scu_base + reg);
++ //lock
++ writel(0xaa,ast_scu_base);
++#else
++ writel(val, ast_scu_base + reg);
++#endif
++}
++
++//SoC mapping Table
++struct soc_id {
++ const char * name;
++ u32 rev_id;
++};
++
++static struct soc_id soc_map_table[] = {
++ [0] = {
++ .name = "AST1100/AST2050-A0",
++ .rev_id = 0x00000200,
++ },
++ [1] = {
++ .name = "AST1100/AST2050-A1",
++ .rev_id = 0x00000201,
++ },
++ [2] = {
++ .name = "AST1100/AST2050-A2,3/AST2150-A0,1",
++ .rev_id = 0x00000202,
++ },
++ [3] = {
++ .name = "AST1510/AST2100-A0",
++ .rev_id = 0x00000300,
++ },
++ [4] = {
++ .name = "AST1510/AST2100-A1",
++ .rev_id = 0x00000301,
++ },
++ [5] = {
++ .name = "AST1510/AST2100-A2,3",
++ .rev_id = 0x00000302,
++ },
++ [6] = {
++ .name = "AST2200-A0,1",
++ .rev_id = 0x00000102,
++ },
++ [7] = {
++ .name = "AST2300-A0",
++ .rev_id = 0x01000003,
++ },
++ [8] = {
++ .name = "AST2300-A1",
++ .rev_id = 0x01010303,
++ },
++ [9] = {
++ .name = "AST1300-A1",
++ .rev_id = 0x01010003,
++ },
++ [10] = {
++ .name = "AST1050-A1",
++ .rev_id = 0x01010203,
++ },
++ [11] = {
++ .name = "AST2400-A0",
++ .rev_id = 0x02000303,
++ },
++ [12] = {
++ .name = "AST2400-A1",
++ .rev_id = 0x02010303,
++ },
++ [13] = {
++ .name = "AST1010-A0",
++ .rev_id = 0x03000003,
++ },
++ [14] = {
++ .name = "AST1010-A1",
++ .rev_id = 0x03010003,
++ },
++ [15] = {
++ .name = "AST1520-A0",
++ .rev_id = 0x03000003,
++ },
++ [16] = {
++ .name = "AST3200-A0",
++ .rev_id = 0x03000003,
++ },
++};
++
++//***********************************Initial control***********************************
++extern void
++ast_scu_reset_video(void)
++{
++ ast_scu_write(ast_scu_read(AST_SCU_RESET) | SCU_RESET_VIDEO, AST_SCU_RESET);
++ udelay(100);
++ ast_scu_write(ast_scu_read(AST_SCU_RESET) & ~SCU_RESET_VIDEO, AST_SCU_RESET);
++}
++
++EXPORT_SYMBOL(ast_scu_reset_video);
++
++extern void
++ast_scu_init_video(u8 dynamic_en)
++{
++ //Video Engine Clock Enable and Reset
++ // Enable Clock & ECLK = inverse of (M-PLL / 2)
++ if(dynamic_en)
++ ast_scu_write((ast_scu_read(AST_SCU_CLK_SEL) & ~SCU_CLK_VIDEO_SLOW_MASK) | SCU_CLK_VIDEO_SLOW_EN | SCU_CLK_VIDEO_SLOW_SET(0), AST_SCU_CLK_SEL);
++ else
++ ast_scu_write((ast_scu_read(AST_SCU_CLK_SEL) & ~SCU_ECLK_SOURCE_MASK) | SCU_ECLK_SOURCE(2), AST_SCU_CLK_SEL);
++
++ // Enable CLK
++ ast_scu_write(ast_scu_read(AST_SCU_CLK_STOP) & ~(SCU_ECLK_STOP_EN | SCU_VCLK_STOP_EN), AST_SCU_CLK_STOP);
++ mdelay(10);
++ ast_scu_write(ast_scu_read(AST_SCU_RESET) | SCU_RESET_VIDEO, AST_SCU_RESET);
++ udelay(100);
++ ast_scu_write(ast_scu_read(AST_SCU_RESET) & ~SCU_RESET_VIDEO, AST_SCU_RESET);
++}
++
++EXPORT_SYMBOL(ast_scu_init_video);
++
++extern void
++ast_scu_init_eth(u8 num)
++{
++ //AST2300 max clk to 125Mhz, AST2400 max clk to 198Mhz
++ if(ast_scu_read(AST_SCU_HW_STRAP1) && (SCU_HW_STRAP_MAC1_RGMII | SCU_HW_STRAP_MAC0_RGMII)) //RGMII --> H-PLL/6
++ ast_scu_write((ast_scu_read(AST_SCU_CLK_SEL) & ~SCU_CLK_MAC_MASK) | SCU_CLK_MAC_DIV(2), AST_SCU_CLK_SEL);
++ else //RMII --> H-PLL/10
++ ast_scu_write((ast_scu_read(AST_SCU_CLK_SEL) & ~SCU_CLK_MAC_MASK) | SCU_CLK_MAC_DIV(4), AST_SCU_CLK_SEL);
++
++ //Set MAC delay Timing
++ ast_scu_write(0x2255, AST_SCU_MAC_CLK);
++
++ switch(num) {
++ case 0:
++ ast_scu_write(ast_scu_read(AST_SCU_RESET) | SCU_RESET_MAC0,
++ AST_SCU_RESET);
++ udelay(100);
++ ast_scu_write(ast_scu_read(AST_SCU_CLK_STOP) & ~SCU_MAC0CLK_STOP_EN,
++ AST_SCU_CLK_STOP);
++ udelay(1000);
++ ast_scu_write(ast_scu_read(AST_SCU_RESET) & ~SCU_RESET_MAC0,
++ AST_SCU_RESET);
++
++ break;
++ case 1:
++ ast_scu_write(ast_scu_read(AST_SCU_RESET) | SCU_RESET_MAC1,
++ AST_SCU_RESET);
++ udelay(100);
++ ast_scu_write(ast_scu_read(AST_SCU_CLK_STOP) & ~SCU_MAC1CLK_STOP_EN,
++ AST_SCU_CLK_STOP);
++ udelay(1000);
++ ast_scu_write(ast_scu_read(AST_SCU_RESET) & ~SCU_RESET_MAC1,
++ AST_SCU_RESET);
++ break;
++
++ }
++}
++
++
++extern void
++ast_scu_init_usb20(void)
++{
++ /* EHCI controller engine init. Process similar to VHub. */
++ /* Following reset sequence can resolve "vhub dead on first power on" issue on V4 board. */
++ //reset USB20
++ ast_scu_write(ast_scu_read(AST_SCU_RESET) | SCU_RESET_USB20, AST_SCU_RESET);
++
++ //enable USB20 clock
++ ast_scu_write(ast_scu_read(AST_SCU_CLK_STOP) | SCU_USB20_CLK_EN, AST_SCU_CLK_STOP);
++ mdelay(10);
++
++ ast_scu_write(ast_scu_read(AST_SCU_RESET) & ~SCU_RESET_USB20, AST_SCU_RESET);
++
++ udelay(500);
++
++// printk("%x \n",ast_scu_read(AST_SCU_RESET));
++
++
++}
++
++EXPORT_SYMBOL(ast_scu_init_usb20);
++
++extern void
++ast_scu_init_uhci(void)
++{
++ //USB1.1 Host's Clock Enable and Reset
++ ast_scu_write(ast_scu_read(AST_SCU_CLK_STOP) & ~SCU_USB11CLK_STOP_EN, AST_SCU_CLK_STOP);
++ mdelay(10);
++
++ ast_scu_write(ast_scu_read(AST_SCU_RESET) & ~SCU_RESET_USB11, AST_SCU_RESET);
++}
++
++EXPORT_SYMBOL(ast_scu_init_uhci);
++
++extern void
++ast_scu_init_udc11(void)
++{
++ //USB1.1 device Clock Enable and Reset
++ ast_scu_write(ast_scu_read(AST_SCU_CLK_STOP) & ~SCU_UCLK_STOP_EN, AST_SCU_CLK_STOP);
++ mdelay(10);
++
++ ast_scu_write(ast_scu_read(AST_SCU_RESET) & ~SCU_RESET_USB11_HID, AST_SCU_RESET);
++}
++
++EXPORT_SYMBOL(ast_scu_init_udc11);
++
++///
++extern void
++ast_scu_init_sdhci(void)
++{
++ //SDHCI Host's Clock Enable and Reset
++ ast_scu_write(ast_scu_read(AST_SCU_RESET) | SCU_RESET_SD, AST_SCU_RESET);
++
++ ast_scu_write(ast_scu_read(AST_SCU_CLK_STOP) & ~SCU_SDCLK_STOP_EN, AST_SCU_CLK_STOP);
++ mdelay(10);
++
++ ast_scu_write(ast_scu_read(AST_SCU_CLK_SEL) | SCU_CLK_SD_EN, AST_SCU_CLK_SEL);
++ mdelay(10);
++
++ // SDCLK = H-PLL / 4
++ ast_scu_write((ast_scu_read(AST_SCU_CLK_SEL) & ~SCU_CLK_SD_MASK) | SCU_CLK_SD_DIV(1),
++ AST_SCU_CLK_SEL);
++ mdelay(10);
++
++ ast_scu_write(ast_scu_read(AST_SCU_RESET) & ~SCU_RESET_SD, AST_SCU_RESET);
++}
++
++EXPORT_SYMBOL(ast_scu_init_sdhci);
++
++extern void
++ast_scu_init_i2c(void)
++{
++ ast_scu_write(ast_scu_read(AST_SCU_RESET) & ~SCU_RESET_I2C, AST_SCU_RESET);
++}
++
++EXPORT_SYMBOL(ast_scu_init_i2c);
++
++extern void
++ast_scu_init_pwm_tacho(void)
++{
++ ast_scu_write(ast_scu_read(AST_SCU_RESET) | SCU_RESET_PWM, AST_SCU_RESET);
++ ast_scu_write(ast_scu_read(AST_SCU_RESET) & ~SCU_RESET_PWM, AST_SCU_RESET);
++}
++
++EXPORT_SYMBOL(ast_scu_init_pwm_tacho);
++
++extern void
++ast_scu_init_adc(void)
++{
++ ast_scu_write(ast_scu_read(AST_SCU_RESET) | SCU_RESET_ADC, AST_SCU_RESET);
++ ast_scu_write(ast_scu_read(AST_SCU_RESET) & ~SCU_RESET_ADC, AST_SCU_RESET);
++}
++
++EXPORT_SYMBOL(ast_scu_init_adc);
++
++extern void
++ast_scu_init_peci(void)
++{
++ ast_scu_write(ast_scu_read(AST_SCU_RESET) | SCU_RESET_PECI, AST_SCU_RESET);
++ udelay(3);
++ ast_scu_write(ast_scu_read(AST_SCU_RESET) & ~SCU_RESET_PECI, AST_SCU_RESET);
++}
++
++EXPORT_SYMBOL(ast_scu_init_peci);
++
++extern void
++ast_scu_init_jtag(void)
++{
++ ast_scu_write(ast_scu_read(AST_SCU_RESET) | SCU_RESET_JTAG, AST_SCU_RESET);
++ udelay(3);
++ ast_scu_write(ast_scu_read(AST_SCU_RESET) & ~SCU_RESET_JTAG, AST_SCU_RESET);
++}
++
++EXPORT_SYMBOL(ast_scu_init_jtag);
++
++extern void
++ast_scu_init_lpc(void)
++{
++ //Note .. It have been enable in U-boot.....
++// ast_scu_write(ast_scu_read(AST_SCU_RESET) | SCU_RESET_LPC, AST_SCU_RESET);
++
++ //enable LPC clock LHCLK = H-PLL/8
++ ast_scu_write(ast_scu_read(AST_SCU_CLK_STOP) |
++ SCU_SET_LHCLK_DIV(3) |
++ SCU_LHCLK_SOURCE_EN,
++ AST_SCU_CLK_STOP);
++
++}
++
++EXPORT_SYMBOL(ast_scu_init_lpc);
++
++//////1 : lpc plus modes
++extern u8
++ast_scu_get_lpc_plus_enable(void)
++{
++ if(ast_scu_read(AST_SCU_FUN_PIN_CTRL5) & SCU_FUN_PIN_LPC_PLUS)
++ return 1;
++ else
++ return 0;
++}
++
++EXPORT_SYMBOL(ast_scu_get_lpc_plus_enable);
++
++extern void
++ast_scu_init_crt(void)
++{
++ //enable D2 pll , //enable DVO (bit18) is VGA , enable DAC (bit16) is CRT
++#if defined(CONFIG_AST_DAC) || defined(CONFIG_AST_DVO)
++ ast_scu_write((ast_scu_read(AST_SCU_MISC1_CTRL) & ~(SCU_MISC_D2_PLL_DIS | SCU_MISC_DAC_MASK))
++ | SCU_MISC_DAC_SOURCE_CRT | SCU_MISC_DVO_SOURCE_CRT | SCU_MISC_2D_CRT_EN , AST_SCU_MISC1_CTRL);
++#elif defined(CONFIG_AST_DVO)
++ ast_scu_write((ast_scu_read(AST_SCU_MISC1_CTRL) & ~(SCU_MISC_D2_PLL_DIS)) |
++ SCU_MISC_DVO_SOURCE_CRT| SCU_MISC_2D_CRT_EN, AST_SCU_MISC1_CTRL);
++#else //default(CONFIG_AST_DAC)
++ ast_scu_write((ast_scu_read(AST_SCU_MISC1_CTRL) & ~(SCU_MISC_D2_PLL_DIS | SCU_MISC_DAC_MASK))
++ | SCU_MISC_DAC_SOURCE_CRT | SCU_MISC_2D_CRT_EN, AST_SCU_MISC1_CTRL);
++#endif
++ /* Set Delay 5 Compensation TODO ...*/
++ ast_scu_write((ast_scu_read(AST_SCU_CLK_SEL) & ~SCU_CLK_VIDEO_DELAY_MASK) |
++ SCU_CLK_VIDEO_DELAY(5), AST_SCU_CLK_SEL);
++
++ /* Reset CRT */
++ ast_scu_write(ast_scu_read(AST_SCU_RESET) | SCU_RESET_CRT, AST_SCU_RESET);
++
++ //enable D2 CLK
++ ast_scu_write(ast_scu_read(AST_SCU_CLK_STOP) & ~SCU_D2CLK_STOP_EN , AST_SCU_CLK_STOP);
++
++ udelay(10);
++ ast_scu_write(ast_scu_read(AST_SCU_RESET) & ~SCU_RESET_CRT, AST_SCU_RESET);
++
++}
++
++EXPORT_SYMBOL(ast_scu_init_crt);
++//***********************************CLK control***********************************
++extern void
++ast_scu_clk_stop(u32 clk_name,u8 stop_enable)
++{
++ switch(clk_name){
++ default:
++ SCUMSG("ERRO clk_name :%d \n",clk_name);
++ break;
++ }
++}
++
++EXPORT_SYMBOL(ast_scu_clk_stop);
++
++
++//***********************************CLK Information***********************************
++extern u32
++ast_get_clk_source(void)
++{
++ if(ast_scu_read(AST_SCU_HW_STRAP1) & CLK_25M_IN)
++ return AST_PLL_25MHZ;
++ else
++ return AST_PLL_24MHZ;
++}
++
++EXPORT_SYMBOL(ast_get_clk_source);
++
++
++extern u32
++ast_get_h_pll_clk(void)
++{
++ u32 speed,clk=0;
++ u32 h_pll_set = ast_scu_read(AST_SCU_H_PLL);
++
++ if(h_pll_set & SCU_H_PLL_OFF)
++ return 0;
++
++ if(h_pll_set & SCU_H_PLL_PARAMETER) {
++ // Programming
++ clk = ast_get_clk_source();
++ if(h_pll_set & SCU_H_PLL_BYPASS_EN) {
++ return clk;
++ } else {
++ //OD == SCU24[4]
++ //OD = SCU_H_PLL_GET_DIV(h_pll_set);
++ //Numerator == SCU24[10:5]
++ //num = SCU_H_PLL_GET_NUM(h_pll_set);
++ //Denumerator == SCU24[3:0]
++ //denum = SCU_H_PLL_GET_DENUM(h_pll_set);
++
++ //hpll = 24MHz * (2-OD) * ((Numerator+2)/(Denumerator+1))
++ clk = ((clk * (2-SCU_H_PLL_GET_DIV(h_pll_set)) * (SCU_H_PLL_GET_NUM(h_pll_set)+2))/(SCU_H_PLL_GET_DENUM(h_pll_set)+1));
++ }
++ } else {
++ // HW Trap
++ speed = SCU_HW_STRAP_GET_H_PLL_CLK(ast_scu_read(AST_SCU_HW_STRAP1));
++ switch (speed) {
++ case 0:
++ clk = 384000000;
++ break;
++ case 1:
++ clk = 360000000;
++ break;
++ case 2:
++ clk = 336000000;
++ break;
++ case 3:
++ clk = 408000000;
++ break;
++ default:
++ BUG();
++ break;
++ }
++ }
++ SCUDBUG("h_pll = %d\n",clk);
++ return clk;
++}
++
++EXPORT_SYMBOL(ast_get_h_pll_clk);
++
++extern u32
++ast_get_m_pll_clk(void)
++{
++ u32 clk=0;
++ u32 m_pll_set = ast_scu_read(AST_SCU_M_PLL);
++
++ if(m_pll_set & SCU_M_PLL_OFF)
++ return 0;
++
++ // Programming
++ clk = ast_get_clk_source();
++ if(m_pll_set & SCU_M_PLL_BYPASS_EN) {
++ return clk;
++ } else {
++ //OD == SCU24[4]
++ //OD = SCU_M_PLL_GET_DIV(h_pll_set);
++ //Numerator == SCU24[10:5]
++ //num = SCU_M_PLL_GET_NUM(h_pll_set);
++ //Denumerator == SCU24[3:0]
++ //denum = SCU_M_PLL_GET_DENUM(h_pll_set);
++
++ //hpll = 24MHz * (2-OD) * ((Numerator+2)/(Denumerator+1))
++ clk = (clk * (2-SCU_M_PLL_GET_DIV(m_pll_set)) * ((SCU_M_PLL_GET_NUM(m_pll_set)+2)/(SCU_M_PLL_GET_DENUM(m_pll_set)+1)));
++ }
++ SCUDBUG("m_pll = %d\n",clk);
++ return clk;
++}
++
++EXPORT_SYMBOL(ast_get_m_pll_clk);
++
++extern u32
++ast_get_ahbclk(void)
++{
++ unsigned int div, hpll;
++
++ hpll = ast_get_h_pll_clk();
++ div = SCU_HW_STRAP_GET_CPU_AHB_RATIO(ast_scu_read(AST_SCU_HW_STRAP1));
++ switch(div) {
++ case 0:
++ div = 1;
++ break;
++ case 1:
++ div = 2;
++ break;
++ case 2:
++ div = 3;
++ break;
++ case 3:
++ div = 4;
++ break;
++
++ }
++
++ SCUDBUG("HPLL=%d, Div=%d, AHB CLK=%d\n", hpll, div, hpll/div);
++ return (hpll/div);
++
++}
++EXPORT_SYMBOL(ast_get_ahbclk);
++
++extern u32
++ast_get_pclk(void)
++{
++ unsigned int div, hpll;
++
++ hpll = ast_get_h_pll_clk();
++ div = SCU_GET_PCLK_DIV(ast_scu_read(AST_SCU_CLK_SEL));
++ div = (div+1) << 1;
++
++ SCUDBUG("HPLL=%d, Div=%d, PCLK=%d\n", hpll, div, hpll/div);
++ return (hpll/div);
++
++}
++EXPORT_SYMBOL(ast_get_pclk);
++
++extern u32
++ast_get_lhclk(void)
++{
++ unsigned int div, hpll;
++ u32 clk_sel = ast_scu_read(AST_SCU_CLK_SEL);
++//FPGA AST1070 is default 100/2 Mhz input
++// return 50000000;
++ hpll = ast_get_h_pll_clk();
++ if(SCU_LHCLK_SOURCE_EN & clk_sel) {
++ div = SCU_GET_LHCLK_DIV(clk_sel);
++ switch(div) {
++ case 0:
++ div = 2;
++ break;
++ case 1:
++ div = 4;
++ break;
++ case 2:
++ div = 6;
++ break;
++ case 3:
++ div = 8;
++ break;
++ case 4:
++ div = 10;
++ break;
++ case 5:
++ div = 12;
++ break;
++ case 6:
++ div = 14;
++ break;
++ case 7:
++ div = 16;
++ break;
++ }
++
++ SCUDBUG("HPLL=%d, Div=%d, LHCLK = %d\n", hpll, div, hpll/div);
++ return (hpll/div);
++ } else {
++ SCUMSG("LPC CLK not enable \n");
++ return 0;
++ }
++
++}
++
++EXPORT_SYMBOL(ast_get_lhclk);
++
++extern u32
++ast_get_d2_pll_clk(void)
++{
++ u32 clk=0;
++ u32 d2_pll_set = ast_scu_read(AST_SCU_D2_PLL);
++ u32 OD,NUM,DENUM,PD,PD2;
++
++ if(d2_pll_set & SCU_D2_PLL_OFF)
++ return 0;
++
++ // Programming
++ clk = ast_get_clk_source();
++ if(d2_pll_set & SCU_D2_PLL_BYPASS_EN) {
++ return clk;
++ } else {
++ NUM = SCU_D2_PLL_GET_NUM(d2_pll_set);
++ DENUM = SCU_D2_PLL_GET_DENUM(d2_pll_set);
++ OD = SCU_D2_PLL_GET_OD(d2_pll_set);
++ OD = (1 << (OD - 1));
++ PD = SCU_D2_PLL_GET_PD(d2_pll_set);
++ switch(PD) {
++ case 0:
++ PD = 1;
++ break;
++ case 1:
++ PD = 2;
++ break;
++ case 2:
++ PD = 2;
++ break;
++ case 3:
++ PD = 4;
++ break;
++ }
++ PD2 = SCU_D2_PLL_GET_PD2(d2_pll_set);
++ PD2 = PD2+1;
++// printk("clk %d ,num %d ,denum %d ,od %d ,pd %d ,pd2 %d \n",clk, NUM , DENUM, OD, PD, PD2);
++ //hpll = 24MHz * (Numerator * 2) / (Denumerator * OD * PD * PD2)
++ clk = (clk * NUM * 2) / (DENUM* OD * PD * PD2);
++ }
++
++ SCUDBUG("d2_pll = %d\n",clk);
++ return clk;
++}
++
++EXPORT_SYMBOL(ast_get_d2_pll_clk);
++
++//Because value 0 is not allowed in SDIO12C D[15:8]: Host Control Settings #1 Register, we have to increase the maximum
++//host's clock in case that system will not ask host to set 1 in the sdhci_set_clock() function
++/*
++SCU7C: Silicon Revision ID Register
++D[31:24]: Chip ID
++0: AST2050/AST2100/AST2150/AST2200/AST3000
++1: AST2300
++
++D[23:16] Silicon revision ID for AST2300 generation and later
++0: A0
++1: A1
++2: A2
++.
++.
++.
++FPGA revision starts from 0x80
++
++
++D[11:8] Bounding option
++
++D[7:0] Silicon revision ID for AST2050/AST2100 generation (for software compatible)
++0: A0
++1: A1
++2: A2
++3: A3
++.
++.
++FPGA revision starts from 0x08, 8~10 means A0, 11+ means A1, AST2300 should be assigned to 3
++*/
++
++extern u32
++ast_get_sd_clock_src(void)
++{
++ u32 clk=0, sd_div;
++
++#if defined(FPGA)
++ clk = 100000000;
++#else
++ clk = ast_get_h_pll_clk();
++ //get div
++ sd_div = SCU_CLK_SD_GET_DIV(ast_scu_read(AST_SCU_CLK_SEL));
++ SCUDBUG("div %d, sdclk =%d \n",((sd_div + 1) * 2),clk/((sd_div + 1) * 2));
++ clk /= ((sd_div + 1) * 2);
++
++#endif
++ return clk;
++}
++
++EXPORT_SYMBOL(ast_get_sd_clock_src);
++
++extern void
++ast_scu_show_system_info (void)
++{
++ u32 h_pll, div;
++
++ h_pll = ast_get_h_pll_clk();
++
++ div = SCU_HW_STRAP_GET_CPU_AHB_RATIO(ast_scu_read(AST_SCU_HW_STRAP1));
++ switch(div) {
++ case 0:
++ div = 1;
++ break;
++ case 1:
++ div = 2;
++ break;
++ case 2:
++ div = 3;
++ break;
++ case 3:
++ div = 4;
++ break;
++
++ }
++
++ SCUMSG("CPU = %d MHz ,AHB = %d MHz (%d:1) \n", h_pll/1000000, h_pll/div/1000000,div);
++
++ return ;
++}
++
++EXPORT_SYMBOL(ast_scu_show_system_info);
++
++//*********************************** Multi-function pin control ***********************************
++extern void
++ast_scu_multi_func_uart(u8 uart)
++{
++ switch(uart) {
++ case 1:
++ ast_scu_write(ast_scu_read(AST_SCU_FUN_PIN_CTRL1) |
++ SCU_FUN_PIN_UART1_RXD |
++ SCU_FUN_PIN_UART1_TXD |
++ SCU_FUN_PIN_UART1_NRTS |
++ SCU_FUN_PIN_UART1_NDTR |
++ SCU_FUN_PIN_UART1_NRI |
++ SCU_FUN_PIN_UART1_NDSR |
++ SCU_FUN_PIN_UART1_NDCD |
++ SCU_FUN_PIN_UART1_NCTS,
++ AST_SCU_FUN_PIN_CTRL1);
++ break;
++ case 2:
++ ast_scu_write(ast_scu_read(AST_SCU_FUN_PIN_CTRL1) |
++ SCU_FUN_PIN_UART2_RXD |
++ SCU_FUN_PIN_UART2_TXD |
++ SCU_FUN_PIN_UART2_NRTS |
++ SCU_FUN_PIN_UART2_NDTR |
++ SCU_FUN_PIN_UART2_NRI |
++ SCU_FUN_PIN_UART2_NDSR |
++ SCU_FUN_PIN_UART2_NDCD |
++ SCU_FUN_PIN_UART2_NCTS,
++ AST_SCU_FUN_PIN_CTRL1);
++ break;
++ case 3:
++ ast_scu_write(ast_scu_read(AST_SCU_FUN_PIN_CTRL1) |
++ SCU_FUN_PIN_UART3_RXD |
++ SCU_FUN_PIN_UART3_TXD |
++ SCU_FUN_PIN_UART3_NRTS |
++ SCU_FUN_PIN_UART3_NDTR |
++ SCU_FUN_PIN_UART3_NRI |
++ SCU_FUN_PIN_UART3_NDSR |
++ SCU_FUN_PIN_UART3_NDCD |
++ SCU_FUN_PIN_UART3_NCTS,
++ AST_SCU_FUN_PIN_CTRL1);
++ break;
++ case 4:
++ ast_scu_write(ast_scu_read(AST_SCU_FUN_PIN_CTRL1) |
++ SCU_FUN_PIN_UART4_RXD |
++ SCU_FUN_PIN_UART4_TXD |
++ SCU_FUN_PIN_UART4_NRTS |
++ SCU_FUN_PIN_UART4_NDTR |
++ SCU_FUN_PIN_UART4_NRI |
++ SCU_FUN_PIN_UART4_NDSR |
++ SCU_FUN_PIN_UART4_NDCD |
++ SCU_FUN_PIN_UART4_NCTS,
++ AST_SCU_FUN_PIN_CTRL1);
++ break;
++ }
++
++
++}
++
++extern void
++ast_scu_multi_func_video()
++{
++#if defined(CONFIG_ARCH_2100) || defined(CONFIG_ARCH_2200)
++ ast_scu_write(ast_scu_read(AST_SCU_MULTI_FUNC_2) |
++ MULTI_FUNC_VIDEO_RGB18 |
++ MULTI_FUNC_VIDEO_SINGLE_EDGE,
++ AST_SCU_MULTI_FUNC_2);
++#elif defined(CONFIG_ARCH_1100) || defined(CONFIG_ARCH_2050)
++ ast_scu_write(ast_scu_read(AST_SCU_MULTI_FUNC_2) |
++ MULTI_FUNC_VIDEO_RGB18 |
++ MULTI_FUNC_VIDEO_SINGLE_EDGE,
++ AST_SCU_MULTI_FUNC_2);
++#else
++
++#endif
++}
++
++extern void
++ast_scu_multi_func_eth(u8 num)
++{
++ switch(num) {
++ case 0:
++ if(ast_scu_read(AST_SCU_HW_STRAP1) && SCU_HW_STRAP_MAC0_RGMII) {
++ SCUMSG("MAC0 : RGMII \n");
++ ast_scu_write(ast_scu_read(AST_SCU_FUN_PIN_CTRL1) |
++ SCU_FUN_PIN_MAC0_PHY_LINK,
++ AST_SCU_FUN_PIN_CTRL1);
++ } else {
++ SCUMSG("MAC0 : RMII/NCSI \n");
++ ast_scu_write(ast_scu_read(AST_SCU_FUN_PIN_CTRL1) &
++ ~SCU_FUN_PIN_MAC0_PHY_LINK,
++ AST_SCU_FUN_PIN_CTRL1);
++ }
++
++ ast_scu_write(ast_scu_read(AST_SCU_FUN_PIN_CTRL3) |
++ SCU_FUN_PIN_MAC0_MDIO |
++ SCU_FUN_PIN_MAC0_MDC,
++ AST_SCU_FUN_PIN_CTRL3);
++
++ break;
++ case 1:
++ if(ast_scu_read(AST_SCU_HW_STRAP1) && SCU_HW_STRAP_MAC1_RGMII) {
++ SCUMSG("MAC1 : RGMII \n");
++ ast_scu_write(ast_scu_read(AST_SCU_FUN_PIN_CTRL1) |
++ SCU_FUN_PIN_MAC1_PHY_LINK,
++ AST_SCU_FUN_PIN_CTRL1);
++ } else {
++ SCUMSG("MAC1 : RMII/NCSI \n");
++ ast_scu_write(ast_scu_read(AST_SCU_FUN_PIN_CTRL1) &
++ ~SCU_FUN_PIN_MAC1_PHY_LINK,
++ AST_SCU_FUN_PIN_CTRL1);
++ }
++
++ ast_scu_write(ast_scu_read(AST_SCU_FUN_PIN_CTRL5) |
++ SCU_FUC_PIN_MAC1_MDIO,
++ AST_SCU_FUN_PIN_CTRL5);
++
++ break;
++ }
++}
++
++extern void
++ast_scu_multi_func_nand(void)
++{
++ //enable NAND flash multipin FLBUSY and FLWP
++ ast_scu_write(ast_scu_read(AST_SCU_FUN_PIN_CTRL2) |
++ SCU_FUN_PIN_NAND_FLBUSY | SCU_FUN_PIN_NAND_FLWP,
++ AST_SCU_FUN_PIN_CTRL2);
++
++}
++
++extern void
++ast_scu_multi_func_nor(void)
++{
++ //Address
++ //ROMA2~17
++ ast_scu_write(ast_scu_read(AST_SCU_FUN_PIN_CTRL8) |
++ SCU_FUN_PIN_ROMA2 | SCU_FUN_PIN_ROMA3 |
++ SCU_FUN_PIN_ROMA4 | SCU_FUN_PIN_ROMA5 |
++ SCU_FUN_PIN_ROMA6 | SCU_FUN_PIN_ROMA7 |
++ SCU_FUN_PIN_ROMA8 | SCU_FUN_PIN_ROMA9 |
++ SCU_FUN_PIN_ROMA10 | SCU_FUN_PIN_ROMA11 |
++ SCU_FUN_PIN_ROMA12 | SCU_FUN_PIN_ROMA13 |
++ SCU_FUN_PIN_ROMA14 | SCU_FUN_PIN_ROMA15 |
++ SCU_FUN_PIN_ROMA16 | SCU_FUN_PIN_ROMA17,
++ AST_SCU_FUN_PIN_CTRL8);
++
++ //ROMA18~21
++ ast_scu_write(ast_scu_read(AST_SCU_FUN_PIN_CTRL9) |
++ SCU_FUN_PIN_ROMA18 | SCU_FUN_PIN_ROMA19 |
++ SCU_FUN_PIN_ROMA20 | SCU_FUN_PIN_ROMA21,
++ AST_SCU_FUN_PIN_CTRL9);
++
++ //ROMA22,23
++ ast_scu_write(ast_scu_read(AST_SCU_FUN_PIN_CTRL4) | SCU_FUN_PIN_ROMA22 | SCU_FUN_PIN_ROMA23,
++ AST_SCU_FUN_PIN_CTRL4);
++
++ //ROMA24,25
++ ast_scu_write(ast_scu_read(AST_SCU_FUN_PIN_CTRL3) | SCU_FUN_PIN_ROMA24 | SCU_FUN_PIN_ROMA25,
++ AST_SCU_FUN_PIN_CTRL3);
++
++ //SCU94 [1] = 0
++ ast_scu_write(ast_scu_read(AST_SCU_FUN_PIN_CTRL6) & SCU_VIDEO_OUT_MASK,
++ AST_SCU_FUN_PIN_CTRL6);
++
++
++ //data
++ //ROMD 4~7 //ROMWE#, OE#
++ ast_scu_write(ast_scu_read(AST_SCU_FUN_PIN_CTRL4) |
++ SCU_FUN_PIN_ROMOE | SCU_FUN_PIN_ROMWE |
++ SCU_FUN_PIN_ROMD4 | SCU_FUN_PIN_ROMD5 |
++ SCU_FUN_PIN_ROMD6 | SCU_FUN_PIN_ROMD7,
++ AST_SCU_FUN_PIN_CTRL4);
++
++ //ROMD 8~15
++ ast_scu_write(ast_scu_read(AST_SCU_FUN_PIN_CTRL5) |
++ SCU_FUC_PIN_ROM_16BIT,
++ AST_SCU_FUN_PIN_CTRL5);
++
++}
++
++extern void
++ast_scu_multi_func_romcs(u8 num)
++{
++ ast_scu_write(ast_scu_read(AST_SCU_FUN_PIN_CTRL3) |
++ SCU_FUN_PIN_ROMCS(num),
++ AST_SCU_FUN_PIN_CTRL3);
++}
++
++extern void
++ast_scu_multi_func_i2c(void)
++{
++ //TODO check ... //In AST2400 Due to share pin with SD , please not enable I2C 10 ~14
++ // AST 2400 have 14 , AST 2300 9 ...
++#ifdef CONFIG_MMC_AST
++ ast_scu_write(ast_scu_read(AST_SCU_FUN_PIN_CTRL5) |
++ SCU_FUC_PIN_I2C3 |
++ SCU_FUC_PIN_I2C4 |
++ SCU_FUC_PIN_I2C5 |
++ SCU_FUC_PIN_I2C6 |
++ SCU_FUC_PIN_I2C7 |
++ SCU_FUC_PIN_I2C8 |
++ SCU_FUC_PIN_I2C9,
++ AST_SCU_FUN_PIN_CTRL5);
++#else
++ ast_scu_write((ast_scu_read(AST_SCU_FUN_PIN_CTRL5) |
++ SCU_FUC_PIN_I2C3 |
++ SCU_FUC_PIN_I2C4 |
++ SCU_FUC_PIN_I2C5 |
++ SCU_FUC_PIN_I2C6 |
++ SCU_FUC_PIN_I2C7 |
++ SCU_FUC_PIN_I2C8 |
++ SCU_FUC_PIN_I2C9 |
++ SCU_FUC_PIN_I2C10 |
++ SCU_FUC_PIN_I2C11 |
++ SCU_FUC_PIN_I2C12 |
++ SCU_FUC_PIN_I2C13 |
++ SCU_FUC_PIN_I2C14) &
++ ~(SCU_FUC_PIN_SD1 | SCU_FUC_PIN_SD2),
++ AST_SCU_FUN_PIN_CTRL5);
++#endif
++}
++
++EXPORT_SYMBOL(ast_scu_multi_func_i2c);
++
++extern void
++ast_scu_multi_func_pwm_tacho(void)
++{
++ //TODO check
++ u32 sts = ast_scu_read(AST_SCU_FUN_PIN_CTRL3) &~0xcfffff;
++ ast_scu_write(sts | 0xc000ff, AST_SCU_FUN_PIN_CTRL3);
++}
++
++EXPORT_SYMBOL(ast_scu_multi_func_pwm_tacho);
++
++//0 : hub mode , 1: usb host mode
++extern void
++ast_scu_multi_func_usb20_host_hub(u8 mode)
++{
++ if(mode)
++ ast_scu_write(ast_scu_read(AST_SCU_FUN_PIN_CTRL5) | SCU_FUC_PIN_USB20_HOST,
++ AST_SCU_FUN_PIN_CTRL5);
++ else
++ ast_scu_write(ast_scu_read(AST_SCU_FUN_PIN_CTRL5) & ~SCU_FUC_PIN_USB20_HOST,
++ AST_SCU_FUN_PIN_CTRL5);
++}
++
++EXPORT_SYMBOL(ast_scu_multi_func_usb20_host_hub);
++
++//0 : gpioQ6,7 mode , 1: usb1.1 host port 4 mode
++extern void
++ast_scu_multi_func_usb11_host_port4(u8 mode)
++{
++ if(mode)
++ ast_scu_write(ast_scu_read(AST_SCU_FUN_PIN_CTRL5) | SCU_FUC_PIN_USB11_PORT4,
++ AST_SCU_FUN_PIN_CTRL5);
++ else
++ ast_scu_write(ast_scu_read(AST_SCU_FUN_PIN_CTRL5) & ~SCU_FUC_PIN_USB11_PORT4,
++ AST_SCU_FUN_PIN_CTRL5);
++}
++
++EXPORT_SYMBOL(ast_scu_multi_func_usb11_host_port4);
++
++//0 : USB 1.1 HID mode , 1: usb1.1 host port 2 mode
++extern void
++ast_scu_multi_func_usb11_host_port2(u8 mode)
++{
++ if(mode)
++ ast_scu_write(ast_scu_read(AST_SCU_FUN_PIN_CTRL5) | SCU_FUC_PIN_USB11_PORT2,
++ AST_SCU_FUN_PIN_CTRL5);
++ else
++ ast_scu_write(ast_scu_read(AST_SCU_FUN_PIN_CTRL5) & ~SCU_FUC_PIN_USB11_PORT2,
++ AST_SCU_FUN_PIN_CTRL5);
++}
++
++EXPORT_SYMBOL(ast_scu_multi_func_usb11_host_port2);
++
++//0 : 1: SD1 function
++extern void
++ast_scu_multi_func_sdhc_slot1(u8 mode)
++{
++ if(mode)
++ ast_scu_write(ast_scu_read(AST_SCU_FUN_PIN_CTRL5) | SCU_FUC_PIN_SD1,
++ AST_SCU_FUN_PIN_CTRL5);
++ else
++ ast_scu_write(ast_scu_read(AST_SCU_FUN_PIN_CTRL5) & ~SCU_FUC_PIN_SD1,
++ AST_SCU_FUN_PIN_CTRL5);
++}
++
++EXPORT_SYMBOL(ast_scu_multi_func_sdhc_slot1);
++
++extern void
++ast_scu_multi_func_sdhc_slot2(u8 mode)
++{
++ if(mode)
++ ast_scu_write(ast_scu_read(AST_SCU_FUN_PIN_CTRL5) | SCU_FUC_PIN_SD2,
++ AST_SCU_FUN_PIN_CTRL5);
++ else
++ ast_scu_write(ast_scu_read(AST_SCU_FUN_PIN_CTRL5) & ~SCU_FUC_PIN_SD2,
++ AST_SCU_FUN_PIN_CTRL5);
++
++}
++
++EXPORT_SYMBOL(ast_scu_multi_func_sdhc_slot2);
++
++extern void
++ast_scu_multi_func_crt(void)
++{
++ /* multi-pin for DVO */
++
++ //Digital vodeo input function pins : 00 disable, 10 24bits mode 888,
++ ast_scu_write((ast_scu_read(AST_SCU_FUN_PIN_CTRL5) &
++ ~SCU_FUC_PIN_DIGI_V_OUT_MASK) |
++ SCU_FUC_PIN_DIGI_V_OUT(VIDEO_24BITS),AST_SCU_FUN_PIN_CTRL5);
++
++ //VPI input
++#if 0
++ ast_scu_write(ast_scu_read(AST_SCU_FUN_PIN_CTRL2) |
++ SCU_FUN_PIN_VPIB9 | SCU_FUN_PIN_VPIB8 |
++ SCU_FUN_PIN_VPIB7 | SCU_FUN_PIN_VPIB6 |
++ SCU_FUN_PIN_VPIB5 | SCU_FUN_PIN_VPIB4 |
++ SCU_FUN_PIN_VPIB3 | SCU_FUN_PIN_VPIB2 |
++ SCU_FUN_PIN_VPIB1 | SCU_FUN_PIN_VPIB0 |
++ SCU_FUN_PIN_VPICLK | SCU_FUN_PIN_VPIVS |
++ SCU_FUN_PIN_VPIHS | SCU_FUN_PIN_VPIODD |
++ SCU_FUN_PIN_VPIDE ,AST_SCU_FUN_PIN_CTRL2);
++
++ ast_scu_write(ast_scu_read(AST_SCU_FUN_PIN_CTRL3) |
++ SCU_FUN_PIN_VPIR9 | SCU_FUN_PIN_VPIR8 |
++ SCU_FUN_PIN_VPIR7 | SCU_FUN_PIN_VPIR6 |
++ SCU_FUN_PIN_VPIR5 | SCU_FUN_PIN_VPIR4 |
++ SCU_FUN_PIN_VPIR3 | SCU_FUN_PIN_VPIR2 |
++ SCU_FUN_PIN_VPIR1 | SCU_FUN_PIN_VPIR0 |
++ SCU_FUN_PIN_VPIG9 | SCU_FUN_PIN_VPIG8 |
++ SCU_FUN_PIN_VPIG7 | SCU_FUN_PIN_VPIG6 |
++ SCU_FUN_PIN_VPIG5 | SCU_FUN_PIN_VPIG4 |
++ SCU_FUN_PIN_VPIG3 | SCU_FUN_PIN_VPIG2 |
++ SCU_FUN_PIN_VPIG1 | SCU_FUN_PIN_VPIG0 ,AST_SCU_FUN_PIN_CTRL3);
++#endif
++}
++
++EXPORT_SYMBOL(ast_scu_multi_func_crt);
++//***********************************Information ***********************************
++extern u32
++ast_scu_revision_id(void)
++{
++ int i;
++ u32 rev_id = ast_scu_read(AST_SCU_REVISION_ID);
++ for(i=0;i<ARRAY_SIZE(soc_map_table);i++) {
++ if(rev_id == soc_map_table[i].rev_id)
++ break;
++ }
++ if(i == ARRAY_SIZE(soc_map_table))
++ SCUMSG("UnKnow-SOC : %x \n",rev_id);
++ else
++ SCUMSG("SOC : %4s \n",soc_map_table[i].name);
++
++ return rev_id;
++}
++
++EXPORT_SYMBOL(ast_scu_revision_id);
++
++/*
++* D[15:11] in 0x1E6E2040 is NCSI scratch from U-Boot. D[15:14] = MAC1, D[13:12] = MAC2
++* The meanings of the 2 bits are:
++* 00(0): Dedicated PHY
++* 01(1): ASPEED's EVA + INTEL's NC-SI PHY chip EVA
++* 10(2): ASPEED's MAC is connected to NC-SI PHY chip directly
++* 11: Reserved
++*/
++
++extern u32
++ast_scu_get_phy_config(u8 mac_num)
++{
++ u32 scatch = ast_scu_read(AST_SCU_SOC_SCRATCH0);
++
++ switch(mac_num) {
++ case 0:
++ return (SCU_MAC0_GET_PHY_MODE(scatch));
++ break;
++ case 1:
++ return (SCU_MAC1_GET_PHY_MODE(scatch));
++ break;
++ default:
++ SCUMSG("error mac number \n");
++ break;
++ }
++ return -1;
++}
++EXPORT_SYMBOL(ast_scu_get_phy_config);
++
++extern u32
++ast_scu_get_phy_interface(u8 mac_num)
++{
++ u32 trap1 = ast_scu_read(AST_SCU_HW_STRAP1);
++
++ switch(mac_num) {
++ case 0:
++ if(SCU_HW_STRAP_MAC0_RGMII & trap1)
++ return 1;
++ else
++ return 0;
++ break;
++ case 1:
++ if(SCU_HW_STRAP_MAC1_RGMII & trap1)
++ return 1;
++ else
++ return 0;
++ break;
++ default:
++ SCUMSG("error mac number \n");
++ break;
++ }
++ return -1;
++}
++EXPORT_SYMBOL(ast_scu_get_phy_interface);
++
++extern void
++ast_scu_set_vga_display(u8 enable)
++{
++ if(enable)
++ printk("111111");
++}
++
++EXPORT_SYMBOL(ast_scu_set_vga_display);
++
++extern u32
++ast_scu_get_vga_memsize(void)
++{
++ u32 size=0;
++
++ switch(SCU_HW_STRAP_VGA_SIZE_GET(ast_scu_read(AST_SCU_HW_STRAP1))) {
++ case 0:
++ size = 8*1024*1024;
++ break;
++ case 1:
++ size = 16*1024*1024;
++ break;
++ case 2:
++ size = 32*1024*1024;
++ break;
++ case 3:
++ size = 64*1024*1024;
++ break;
++ default:
++ SCUMSG("error vga size \n");
++ break;
++ }
++ return size;
++}
++
++EXPORT_SYMBOL(ast_scu_get_vga_memsize);
++
++extern void
++ast_scu_get_who_init_dram(void)
++{
++ switch(SCU_VGA_DRAM_INIT_MASK(ast_scu_read(AST_SCU_VGA0))) {
++ case 0:
++ SCUMSG("VBIOS init \n");
++ break;
++ case 1:
++ SCUMSG("SOC init \n");
++ break;
++ default:
++ SCUMSG("error vga size \n");
++ break;
++ }
++}
+diff --git a/arch/arm/plat-aspeed/ast-sdmc.c b/arch/arm/plat-aspeed/ast-sdmc.c
+new file mode 100644
+index 0000000..238cf79
+--- /dev/null
++++ b/arch/arm/plat-aspeed/ast-sdmc.c
+@@ -0,0 +1,100 @@
++/********************************************************************************
++* File Name : arch/arm/mach-aspeed/ast-sdmc.c
++* Author : Ryan Chen
++* Description : AST SDRAM Memory Ctrl
++*
++* Copyright (C) 2012-2020 ASPEED Technology Inc.
++* This program is free software; you can redistribute it and/or modify
++* it under the terms of the GNU General Public License as published by the Free Software Foundation;
++* either version 2 of the License, or (at your option) any later version.
++* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
++* without even the implied warranty of MERCHANTABILITY or
++* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
++* You should have received a copy of the GNU General Public License
++* along with this program; if not, write to the Free Software
++* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++
++
++* History :
++* 1. 2013/03/15 Ryan Chen Create
++*
++********************************************************************************/
++#include <linux/kernel.h>
++#include <linux/module.h>
++#include <linux/delay.h>
++#include <asm/io.h>
++
++#include <mach/platform.h>
++#include <mach/hardware.h>
++
++#include <plat/ast-sdmc.h>
++#include <plat/regs-sdmc.h>
++
++//#define AST_SDMC_LOCK
++//#define AST_SDMC_DEBUG
++
++#ifdef AST_SDMC_DEBUG
++#define SDMCDBUG(fmt, args...) printk("%s() " fmt, __FUNCTION__, ## args)
++#else
++#define SDMCDBUG(fmt, args...)
++#endif
++
++#define SDMCMSG(fmt, args...) printk(fmt, ## args)
++
++static u32 ast_sdmc_base = IO_ADDRESS(AST_SDMC_BASE);
++
++static inline u32
++ast_sdmc_read(u32 reg)
++{
++ u32 val;
++
++ val = readl(ast_sdmc_base + reg);
++
++ SDMCDBUG("ast_sdmc_read : reg = 0x%08x, val = 0x%08x\n", reg, val);
++
++ return val;
++}
++
++static inline void
++ast_sdmc_write(u32 val, u32 reg)
++{
++ SDMCDBUG("ast_sdmc_write : reg = 0x%08x, val = 0x%08x\n", reg, val);
++#ifdef CONFIG_AST_SDMC_LOCK
++ //unlock
++ writel(SDMC_PROTECT_UNLOCK, ast_sdmc_base);
++ writel(val, ast_sdmc_base + reg);
++ //lock
++ writel(0xaa,ast_sdmc_base);
++#else
++ writel(SDMC_PROTECT_UNLOCK, ast_sdmc_base);
++
++ writel(val, ast_sdmc_base + reg);
++#endif
++}
++
++//***********************************Information ***********************************
++extern u32
++ast_sdmc_get_mem_size(void)
++{
++ u32 size=0;
++ switch(SDMC_CONFIG_MEM_GET(ast_sdmc_read(AST_SDMC_CONFIG))) {
++ case 0:
++ size = 64*1024*1024;
++ break;
++ case 1:
++ size = 128*1024*1024;
++ break;
++ case 2:
++ size = 256*1024*1024;
++ break;
++ case 3:
++ size = 512*1024*1024;
++ break;
++
++ default:
++ SDMCMSG("error ddr size \n");
++ break;
++ }
++ return size;
++}
++
+diff --git a/arch/arm/plat-aspeed/ast1070-scu.c b/arch/arm/plat-aspeed/ast1070-scu.c
+new file mode 100644
+index 0000000..4ad12c7
+--- /dev/null
++++ b/arch/arm/plat-aspeed/ast1070-scu.c
+@@ -0,0 +1,178 @@
++/********************************************************************************
++* File Name : arch/arm/mach-aspeed/ast1070-scu.c
++* Author : Ryan Chen
++* Description : AST1070 SCU
++*
++* Copyright (C) 2012-2020 ASPEED Technology Inc.
++* This program is free software; you can redistribute it and/or modify
++* it under the terms of the GNU General Public License as published by the Free Software Foundation;
++* either version 2 of the License, or (at your option) any later version.
++* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
++* without even the implied warranty of MERCHANTABILITY or
++* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
++* You should have received a copy of the GNU General Public License
++* along with this program; if not, write to the Free Software
++* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++
++* History :
++* 1. 2013/05/15 Ryan Chen Create
++*
++********************************************************************************/
++#include <linux/kernel.h>
++#include <linux/module.h>
++#include <linux/delay.h>
++
++#include <mach/platform.h>
++#include <asm/io.h>
++
++#include <mach/hardware.h>
++
++#include <plat/ast1070-scu.h>
++#include <plat/regs-ast1070-scu.h>
++
++#define CONFIG_AST1070_SCU_LOCK
++//#define AST1070_SCU_DEBUG
++
++#ifdef AST1070_SCU_DEBUG
++#define SCUDBUG(fmt, args...) printk("%s() " fmt, __FUNCTION__, ## args)
++#else
++#define SCUDBUG(fmt, args...)
++#endif
++
++#define SCUMSG(fmt, args...) printk(fmt, ## args)
++
++static u32 ast1070_scu_base = IO_ADDRESS2(AST_C0_SCU_BASE);
++
++static inline u32
++ast1070_scu_read(u8 node, u32 reg)
++{
++ u32 val;
++
++ val = readl(ast1070_scu_base + (node * 0x10000) + reg);
++
++ SCUDBUG("ast1070_scu_read : reg = 0x%08x, val = 0x%08x\n", reg, val);
++
++ return val;
++}
++
++static inline void
++ast1070_scu_write(u8 node, u32 val, u32 reg)
++{
++ SCUDBUG("ast1070_scu_write : reg = 0x%08x, val = 0x%08x\n", reg, val);
++#ifdef CONFIG_AST1070_SCU_LOCK
++ //unlock
++ writel(AST1070_SCU_PROTECT_UNLOCK, ast1070_scu_base + (node * 0x10000));
++ writel(val, ast1070_scu_base + (node * 0x10000) + reg);
++ //lock
++// writel(0xaa,ast1070_scu_base + (node * 0x10000));
++#else
++ writel(val, ast1070_scu_base + (node * 0x10000) + reg);
++#endif
++}
++
++extern void
++ast1070_scu_init_uart(u8 node)
++{
++ //SCU UART Reset
++ ast1070_scu_write(node, ast1070_scu_read(node, AST1070_SCU_RESET) &
++ ~(SCU_RESET_N1_UART | SCU_RESET_N2_UART |
++ SCU_RESET_N3_UART | SCU_RESET_N4_UART),
++ AST1070_SCU_RESET);
++}
++
++EXPORT_SYMBOL(ast1070_scu_init_uart);
++
++extern void
++ast1070_scu_init_i2c(u8 node)
++{
++ //SCU I2C Reset
++ ast1070_scu_write(node, ast1070_scu_read(node, AST1070_SCU_RESET) & ~SCU_RESET_I2C, AST1070_SCU_RESET);
++}
++
++EXPORT_SYMBOL(ast1070_scu_init_i2c);
++
++extern void
++ast1070_dma_init(u8 node)
++{
++ u32 val =0;
++
++ //let the uart_dma engine leave the reset state
++ ast1070_scu_write(node, ast1070_scu_read(node, AST1070_SCU_RESET) & ~SCU_RESET_DMA, AST1070_SCU_RESET);
++
++ val = ast1070_scu_read(node, AST1070_SCU_MISC_CTRL) & ~SCU_DMA_M_S_MASK;
++
++ if(ast1070_scu_read(node, AST1070_SCU_TRAP) & TRAP_MULTI_MASTER) {
++ //AST1070 multi Initial DMA
++ if(ast1070_scu_read(node, AST1070_SCU_TRAP) & TRAP_DEVICE_SLAVE)
++ ast1070_scu_write(node, val | SCU_DMA_SLAVE_EN, AST1070_SCU_MISC_CTRL);
++ else
++ //Enable DMA master
++ ast1070_scu_write(node, val | SCU_DMA_MASTER_EN, AST1070_SCU_MISC_CTRL);
++
++ } else {
++ //AST1070 single
++ ast1070_scu_write(node, val, AST1070_SCU_MISC_CTRL);
++ }
++}
++EXPORT_SYMBOL(ast1070_dma_init);
++
++
++extern void
++ast1070_scu_init_lpc(void)
++{
++
++}
++
++EXPORT_SYMBOL(ast1070_scu_init_lpc);
++
++//***********************************Multi-function pin control***********************************
++
++extern void
++ast1070_multi_func_uart(u8 node, u8 uart)
++{
++ ast1070_scu_write(node, (ast1070_scu_read(node, AST1070_SCU_UART_MUX) &
++ ~UART_MUX_MASK(uart)) |
++ SET_UART_IO_PAD(uart,PAD_FROM_BMC) |
++ SET_NODE_UART_CTRL(uart, NODE_UART_FROM_NONE) |
++ SET_BMC_UART_CTRL(uart, BMC_UART_FROM_PAD1),
++ AST1070_SCU_UART_MUX);
++
++}
++
++EXPORT_SYMBOL(ast1070_multi_func_uart);
++
++
++//***********************************CLK control***********************************
++
++
++//***********************************CLK Information***********************************
++extern u32
++ast1070_get_clk_source(void)
++{
++
++}
++EXPORT_SYMBOL(ast1070_get_clk_source);
++
++//***********************************Information ***********************************
++extern void
++ast1070_scu_revision_id(u8 node)
++{
++ u32 rev_id;
++
++#if 0
++ if(gpio_get_value(PIN_GPIOI1))
++ printk("Use LPC+ Bus Access \n");
++ else
++ printk("Use LPC Bus Access \n");
++#endif
++
++ rev_id = ast1070_scu_read(node, AST1070_SCU_CHIP_ID);
++ if (ast1070_scu_read(node, AST1070_SCU_TRAP) & TRAP_LPC_PLUS_MODE) {
++ printk("LPC+ : ");
++ } else
++ printk("LPC : ");
++
++ printk("AST1070-[C%d] rev_id[%x] \n",node,rev_id);
++}
++
++EXPORT_SYMBOL(ast1070_scu_revision_id);
+diff --git a/arch/arm/plat-aspeed/ast1070-uart-dma.c b/arch/arm/plat-aspeed/ast1070-uart-dma.c
+new file mode 100644
+index 0000000..9da401e
+--- /dev/null
++++ b/arch/arm/plat-aspeed/ast1070-uart-dma.c
+@@ -0,0 +1,572 @@
++/*
++ * ast1070-uart-dma.c
++ *
++ * UART DMA for the AST1070 UART access.
++ *
++ * Copyright (C) 2012-2020 ASPEED Technology Inc.
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * History:
++ * 2012.05.26: Initial version [Ryan Chen]
++ */
++
++#include <linux/sysdev.h>
++#include <linux/dma-mapping.h>
++#include <linux/interrupt.h>
++#include <asm/io.h>
++#include <mach/irqs.h>
++#include <mach/hardware.h>
++#include <mach/ast-uart-dma.h>
++#include <plat/regs-uart-dma.h>
++
++//#define AST_UART_DMA_DEBUG
++
++#ifdef AST_UART_DMA_DEBUG
++#define DMADUG(fmt, args...) printk("%s() " fmt, __FUNCTION__, ## args)
++#else
++#define DMADUG(fmt, args...)
++#endif
++
++//#define AST1070_FPGA 1
++
++struct ast1070_dma uart_dma[CONFIG_AST1070_NR];
++
++static inline void
++ast1070_uart_dma_write(struct ast1070_dma *dma, u32 val, u32 reg)
++{
++ //printk("uart dma write : val: %x , reg : %x \n",val,reg);
++ writel(val, dma->reg_base+ reg);
++}
++
++static inline u32
++ast1070_uart_dma_read(struct ast1070_dma *dma, u32 reg)
++{
++#if 0
++ u32 val = readl(i2c_dev->reg_base + reg);
++ printk("R : reg %x , val: %x \n",reg, val);
++ return val;
++#else
++ return readl(dma->reg_base + reg);
++#endif
++}
++
++/* *****************************************************************************/
++int ast_uart_rx_dma_enqueue(u8 node, u8 ch, dma_addr_t rx_buff, u16 len)
++{
++ unsigned long flags;
++ struct ast1070_dma *dma = &uart_dma[node];
++ struct ast1070_dma_ch *dma_ch = &(dma->dma_rx_ch[ch]);
++ struct uart_dma_desc *rx_desc = dma_ch->desc;
++
++ if(len > 4096)
++ printk("ERROR !!! Please Check ...\n");
++
++ local_irq_save(flags);
++
++ //fill to rx desc -->
++ rx_desc->desc0 = DESC0_END | DESC0_INT_EN | DESC0_HW_OWN;
++ rx_desc->desc1 = DESC1_LEN(len);
++ rx_desc->desc2 = rx_buff;
++ rx_desc->desc3 = 0;
++
++ DMADUG("[c%d]: ch = %d, rx buff = %x, len = %d \n",node, ch, rx_buff, len);
++
++ //fill in tx descriptor base register
++ DMADUG("desc_addr : %x, reg offset %x \n",dma_ch->desc_dma_addr, dma_ch->desc_offset);
++ ast1070_uart_dma_write(dma, dma_ch->desc_dma_addr, dma_ch->desc_offset);
++
++ local_irq_restore(flags);
++
++ return 0;
++}
++
++EXPORT_SYMBOL(ast_uart_rx_dma_enqueue);
++
++int ast_uart_tx_dma_enqueue(u8 node, u8 ch, dma_addr_t tx_buff, u16 len)
++{
++ unsigned long flags;
++ struct ast1070_dma *dma = &uart_dma[node];
++ struct ast1070_dma_ch *dma_ch = &(dma->dma_tx_ch[ch]);
++ struct uart_dma_desc *tx_desc = dma_ch->desc;
++
++ DMADUG("[c%d]: ch = %d, tx buff = %x, len = %d \n",node, ch, tx_buff, len);
++
++ local_irq_save(flags);
++
++ //fill to rx desc -->
++ tx_desc->desc0 = DESC0_END | DESC0_INT_EN | DESC0_HW_OWN;
++ tx_desc->desc1 = DESC1_LEN(len);
++ tx_desc->desc2 = tx_buff;
++ tx_desc->desc3 = 0;
++
++// DMADUG("desc vir = %x, tx desc = %x, %x, %x, %x ===\n",tx_desc, tx_desc->desc0 ,tx_desc->desc1,tx_desc->desc2,tx_desc->desc3);
++ //fill in tx descriptor base register
++ DMADUG("desc_addr : %x, in offset %x \n",dma_ch->desc_dma_addr, dma_ch->desc_offset);
++ ast1070_uart_dma_write(dma, dma_ch->desc_dma_addr, dma_ch->desc_offset);
++
++ local_irq_restore(flags);
++
++ return 0;
++}
++
++EXPORT_SYMBOL(ast_uart_tx_dma_enqueue);
++
++int ast_uart_rx_dma_ctrl(u8 node, u8 ch, enum ast_uart_chan_op op)
++{
++ unsigned long flags;
++ struct ast1070_dma *dma = &uart_dma[node];
++ struct ast1070_dma_ch *dma_ch = &(dma->dma_rx_ch[ch]);
++ DMADUG("[c%d]: ch = %d \n",node, ch);
++
++ local_irq_save(flags);
++
++ switch (op) {
++ case AST_UART_DMAOP_TRIGGER:
++ //trigger
++ DMADUG("Trigger \n");
++ dma_ch->enable = 1;
++// ast1070_uart_dma_write(dma, DMA_ENABLE, dma_ch->ctrl_offset);
++ ast1070_uart_dma_write(dma, DMA_TRIGGER | DMA_ENABLE, dma_ch->ctrl_offset);
++ break;
++
++ case AST_UART_DMAOP_STOP:
++ //disable engine
++ DMADUG("Stop \n");
++ dma_ch->enable = 0;
++ ast1070_uart_dma_write(dma, 0, dma_ch->ctrl_offset);
++ break;
++ }
++
++
++ return 0;
++}
++EXPORT_SYMBOL(ast_uart_rx_dma_ctrl);
++
++int ast_uart_tx_dma_ctrl(u8 node, u8 ch, enum ast_uart_chan_op op)
++{
++ unsigned long flags;
++ struct ast1070_dma *dma = &uart_dma[node];
++ struct ast1070_dma_ch *dma_ch = &(dma->dma_tx_ch[ch]);
++ DMADUG("TX DMA CTRL [c%d]: ch = %d \n",node, ch);
++
++ local_irq_save(flags);
++
++ switch (op) {
++ case AST_UART_DMAOP_TRIGGER:
++ //trigger
++ DMADUG("Trigger \n");
++ ast1070_uart_dma_write(dma, DMA_ENABLE, dma_ch->ctrl_offset);
++ ast1070_uart_dma_write(dma, DMA_TRIGGER | DMA_ENABLE, dma_ch->ctrl_offset);
++ break;
++
++ case AST_UART_DMAOP_STOP:
++ //disable engine
++ DMADUG("STOP \n");
++ ast1070_uart_dma_write(dma, 0, dma_ch->ctrl_offset);
++ break;
++ }
++
++
++ return 0;
++}
++EXPORT_SYMBOL(ast_uart_tx_dma_ctrl);
++
++int ast_uart_tx_dma_request(u8 node, u8 ch, ast_uart_dma_cbfn_t rtn, void *id)
++{
++ unsigned long flags;
++ struct ast1070_dma *dma = &uart_dma[node];
++ struct ast1070_dma_ch *dma_ch = &(dma->dma_tx_ch[ch]);
++
++ DMADUG("TX DMA REQUEST [c%d]: ch = %d \n",node, ch);
++
++ local_irq_save(flags);
++
++ if (dma_ch->enable) {
++ local_irq_restore(flags);
++ return -EBUSY;
++ }
++
++ dma_ch->priv = id;
++ dma_ch->enable = 1;
++ dma_ch->callback_fn = rtn;
++ //DMA IRQ En
++ ast1070_uart_dma_write(dma,
++ ast1070_uart_dma_read(dma, UART_DMA_IER) |
++ (1 << ch)
++ , UART_DMA_IER);
++
++ //enable engine
++// ast1070_uart_dma_write(dma, DMA_ENABLE, dma_ch->ctrl_offset);
++ local_irq_restore(flags);
++
++ return 0;
++
++}
++
++EXPORT_SYMBOL(ast_uart_tx_dma_request);
++
++int ast_uart_rx_dma_request(u8 node, u8 ch, ast_uart_dma_cbfn_t rtn, void *id)
++{
++ unsigned long flags;
++ struct ast1070_dma *dma = &uart_dma[node];
++ struct ast1070_dma_ch *dma_ch = &(dma->dma_rx_ch[ch]);
++
++ DMADUG("RX DMA REQUEST [c%d] : ch = %d \n",node, ch);
++
++ local_irq_save(flags);
++
++ if (dma->dma_rx_ch[ch].enable) {
++ local_irq_restore(flags);
++ return -EBUSY;
++ }
++ dma_ch->priv = id;
++// dma_ch->enable = 1;
++ dma_ch->callback_fn = rtn;
++// dma_ch->name
++ //DMA IRQ En
++ ast1070_uart_dma_write(dma,
++ ast1070_uart_dma_read(dma, UART_DMA_IER) |
++ (1 << (4+ch))
++ , UART_DMA_IER);
++
++ //enable engine
++// ast1070_uart_dma_write(dma, DMA_ENABLE, dma_ch->ctrl_offset);
++ local_irq_restore(flags);
++
++ return 0;
++
++}
++
++EXPORT_SYMBOL(ast_uart_rx_dma_request);
++/* *****************************************************************************/
++static inline void ast_dma_bufffdone(struct ast1070_dma_ch *dma_ch)
++{
++ ////TODO desc -- remove ......
++ //workaround : Issue RX dma can;t be stoped , close open close
++ if(dma_ch->enable == 0) {
++// printk("workaround \n");
++ return;
++ }
++
++// u32 sts = ast1070_uart_dma_read(dma, dma_ch->ctrl_offset);
++ DMADUG("dma dwn : ch[%d] : %s ,len : %d \n", dma_ch->ch_no, dma_ch->direction ? "tx" : "rx", DESC3_GET_LEN(dma_ch->desc->desc3));
++
++ DMADUG(" == desc = %x, %x, %x, %x ===\n",dma_ch->desc->desc0,dma_ch->desc->desc1,dma_ch->desc->desc2,dma_ch->desc->desc3);
++
++
++ if(dma_ch->desc->desc0 & DESC0_HW_OWN)
++ printk("ERROR ..... \n");
++
++ if (dma_ch->callback_fn != NULL)
++ (dma_ch->callback_fn)(dma_ch, dma_ch->priv, DESC3_GET_LEN(dma_ch->desc->desc3));
++}
++
++
++static irqreturn_t
++ast1070_c0_uart_dma_irq(int irq, void *dev_id)
++{
++// struct ast1070_dma *dma = dev_id;
++ int i;
++ struct ast1070_dma *dma = &uart_dma[0];
++ u32 sts = ast1070_uart_dma_read(dma, UART_DMA_ISR);
++ DMADUG("C0 int -- > \n");
++ DMADUG("isr sts = %x\n", sts);
++
++ for(i = 0;i < 17 ; i++)
++ DMADUG("offset : %x , val %x \n",i*4, ast1070_uart_dma_read(dma, i*4));
++
++ if (sts & UART_DMA3_RX_INT) {
++ ast1070_uart_dma_write(dma, UART_DMA3_RX_INT, UART_DMA_ISR);
++ ast_dma_bufffdone(&(dma->dma_rx_ch[3]));
++ } else if (sts & UART_DMA2_RX_INT) {
++ ast1070_uart_dma_write(dma, UART_DMA2_RX_INT, UART_DMA_ISR);
++ ast_dma_bufffdone(&(dma->dma_rx_ch[2]));
++ } else if (sts & UART_DMA1_RX_INT) {
++ ast1070_uart_dma_write(dma, UART_DMA1_RX_INT, UART_DMA_ISR);
++ ast_dma_bufffdone(&(dma->dma_rx_ch[1]));
++ } else if (sts & UART_DMA0_RX_INT) {
++ ast1070_uart_dma_write(dma, UART_DMA0_RX_INT, UART_DMA_ISR);
++ ast_dma_bufffdone(&(dma->dma_rx_ch[0]));
++ } else if (sts & UART_DMA3_TX_INT) {
++ ast1070_uart_dma_write(dma, UART_DMA3_TX_INT, UART_DMA_ISR);
++ ast_dma_bufffdone(&(dma->dma_tx_ch[3]));
++ } else if (sts & UART_DMA2_TX_INT) {
++ ast1070_uart_dma_write(dma, UART_DMA2_TX_INT, UART_DMA_ISR);
++ ast_dma_bufffdone(&(dma->dma_tx_ch[2]));
++ } else if (sts & UART_DMA1_TX_INT) {
++ ast1070_uart_dma_write(dma, UART_DMA1_TX_INT, UART_DMA_ISR);
++ ast_dma_bufffdone(&(dma->dma_tx_ch[1]));
++ } else if (sts & UART_DMA0_TX_INT) {
++ ast1070_uart_dma_write(dma, UART_DMA0_TX_INT, UART_DMA_ISR);
++ ast_dma_bufffdone(&(dma->dma_tx_ch[0]));
++ } else {
++ printk("No body .. !!! \n");
++ }
++
++ return IRQ_HANDLED;
++}
++
++#if (CONFIG_AST1070_NR >=2)
++static irqreturn_t
++ast1070_c1_uart_dma_irq(int irq, void *dev_id)
++{
++// struct ast1070_dma *dma = dev_id;
++ struct ast1070_dma *dma = &uart_dma[1];
++ u32 sts = ast1070_uart_dma_read(dma, UART_DMA_ISR);
++ DMADUG("C1 int -- > \n");
++
++// DMADUG("isr sts = %x\n", sts);
++ if (sts & UART_DMA3_RX_INT) {
++ ast1070_uart_dma_write(dma, UART_DMA3_RX_INT, UART_DMA_ISR);
++ ast_dma_bufffdone(&(dma->dma_rx_ch[3]));
++ } else if (sts & UART_DMA2_RX_INT) {
++ ast1070_uart_dma_write(dma, UART_DMA2_RX_INT, UART_DMA_ISR);
++ ast_dma_bufffdone(&(dma->dma_rx_ch[2]));
++ } else if (sts & UART_DMA1_RX_INT) {
++ ast1070_uart_dma_write(dma, UART_DMA1_RX_INT, UART_DMA_ISR);
++ ast_dma_bufffdone(&(dma->dma_rx_ch[1]));
++ } else if (sts & UART_DMA0_RX_INT) {
++ ast1070_uart_dma_write(dma, UART_DMA0_RX_INT, UART_DMA_ISR);
++ ast_dma_bufffdone(&(dma->dma_rx_ch[0]));
++ } else if (sts & UART_DMA3_TX_INT) {
++ ast1070_uart_dma_write(dma, UART_DMA3_TX_INT, UART_DMA_ISR);
++ ast_dma_bufffdone(&(dma->dma_tx_ch[3]));
++ } else if (sts & UART_DMA2_TX_INT) {
++ ast1070_uart_dma_write(dma, UART_DMA2_TX_INT, UART_DMA_ISR);
++ ast_dma_bufffdone(&(dma->dma_tx_ch[2]));
++ } else if (sts & UART_DMA1_TX_INT) {
++ ast1070_uart_dma_write(dma, UART_DMA1_TX_INT, UART_DMA_ISR);
++ ast_dma_bufffdone(&(dma->dma_tx_ch[1]));
++ } else if (sts & UART_DMA0_TX_INT) {
++ ast1070_uart_dma_write(dma, UART_DMA0_TX_INT, UART_DMA_ISR);
++ ast_dma_bufffdone(&(dma->dma_tx_ch[0]));
++ } else {
++ printk("No body .. !!! \n");
++ }
++
++ return IRQ_HANDLED;
++}
++#endif
++
++#if (CONFIG_AST1070_NR >=3)
++static irqreturn_t
++ast1070_c2_uart_dma_irq(int irq, void *dev_id)
++{
++ struct ast1070_dma *dma = dev_id;
++ u32 sts = ast1070_uart_dma_read(dma, UART_DMA_ISR);
++
++// DMADUG("isr sts = %x\n", sts);
++ if (sts & UART_DMA3_RX_INT) {
++ ast1070_uart_dma_write(dma, UART_DMA3_RX_INT, UART_DMA_ISR);
++ ast_dma_bufffdone(&(dma->dma_rx_ch[3]));
++ } else if (sts & UART_DMA2_RX_INT) {
++ ast1070_uart_dma_write(dma, UART_DMA2_RX_INT, UART_DMA_ISR);
++ ast_dma_bufffdone(&(dma->dma_rx_ch[2]));
++ } else if (sts & UART_DMA1_RX_INT) {
++ ast1070_uart_dma_write(dma, UART_DMA1_RX_INT, UART_DMA_ISR);
++ ast_dma_bufffdone(&(dma->dma_rx_ch[1]));
++ } else if (sts & UART_DMA0_RX_INT) {
++ ast1070_uart_dma_write(dma, UART_DMA0_RX_INT, UART_DMA_ISR);
++ ast_dma_bufffdone(&(dma->dma_rx_ch[0]));
++ } else if (sts & UART_DMA3_TX_INT) {
++ ast1070_uart_dma_write(dma, UART_DMA3_TX_INT, UART_DMA_ISR);
++ ast_dma_bufffdone(&(dma->dma_tx_ch[3]));
++ } else if (sts & UART_DMA2_TX_INT) {
++ ast1070_uart_dma_write(dma, UART_DMA2_TX_INT, UART_DMA_ISR);
++ ast_dma_bufffdone(&(dma->dma_tx_ch[2]));
++ } else if (sts & UART_DMA1_TX_INT) {
++ ast1070_uart_dma_write(dma, UART_DMA1_TX_INT, UART_DMA_ISR);
++ ast_dma_bufffdone(&(dma->dma_tx_ch[1]));
++ } else if (sts & UART_DMA0_TX_INT) {
++ ast1070_uart_dma_write(dma, UART_DMA0_TX_INT, UART_DMA_ISR);
++ ast_dma_bufffdone(&(dma->dma_tx_ch[0]));
++ } else {
++ printk("No body .. !!! \n");
++ }
++
++ return IRQ_HANDLED;
++}
++#endif
++
++#if (CONFIG_AST1070_NR >=4)
++static irqreturn_t
++ast1070_c3_uart_dma_irq(int irq, void *dev_id)
++{
++ struct ast1070_dma *dma = dev_id;
++ u32 sts = ast1070_uart_dma_read(dma, UART_DMA_ISR);
++
++// DMADUG("isr sts = %x\n", sts);
++ if (sts & UART_DMA3_RX_INT) {
++ ast1070_uart_dma_write(dma, UART_DMA3_RX_INT, UART_DMA_ISR);
++ ast_dma_bufffdone(&(dma->dma_rx_ch[3]));
++ } else if (sts & UART_DMA2_RX_INT) {
++ ast1070_uart_dma_write(dma, UART_DMA2_RX_INT, UART_DMA_ISR);
++ ast_dma_bufffdone(&(dma->dma_rx_ch[2]));
++ } else if (sts & UART_DMA1_RX_INT) {
++ ast1070_uart_dma_write(dma, UART_DMA1_RX_INT, UART_DMA_ISR);
++ ast_dma_bufffdone(&(dma->dma_rx_ch[1]));
++ } else if (sts & UART_DMA0_RX_INT) {
++ ast1070_uart_dma_write(dma, UART_DMA0_RX_INT, UART_DMA_ISR);
++ ast_dma_bufffdone(&(dma->dma_rx_ch[0]));
++ } else if (sts & UART_DMA3_TX_INT) {
++ ast1070_uart_dma_write(dma, UART_DMA3_TX_INT, UART_DMA_ISR);
++ ast_dma_bufffdone(&(dma->dma_tx_ch[3]));
++ } else if (sts & UART_DMA2_TX_INT) {
++ ast1070_uart_dma_write(dma, UART_DMA2_TX_INT, UART_DMA_ISR);
++ ast_dma_bufffdone(&(dma->dma_tx_ch[2]));
++ } else if (sts & UART_DMA1_TX_INT) {
++ ast1070_uart_dma_write(dma, UART_DMA1_TX_INT, UART_DMA_ISR);
++ ast_dma_bufffdone(&(dma->dma_tx_ch[1]));
++ } else if (sts & UART_DMA0_TX_INT) {
++ ast1070_uart_dma_write(dma, UART_DMA0_TX_INT, UART_DMA_ISR);
++ ast_dma_bufffdone(&(dma->dma_tx_ch[0]));
++ } else {
++ printk("No body .. !!! \n");
++ }
++
++ return IRQ_HANDLED;
++}
++#endif
++
++extern int
++ast1070_uart_dma_init(u8 node)
++{
++ int ret,i;
++ struct ast1070_dma *dma = &uart_dma[node];
++
++ DMADUG("ast1070 uart_dma_init [c%d]\n", node);
++
++ if(node == 0) {
++ dma->reg_base = ioremap(AST_C0_UART_DMA_BASE, 0x100);
++#if (CONFIG_AST1070_NR >=2)
++ } else if (node == 1) {
++ dma->reg_base = ioremap(AST_C1_UART_DMA_BASE, 0x100);
++#endif
++#if (CONFIG_AST1070_NR >=3)
++ } else if (node == 2) {
++ dma->reg_base = ioremap(AST_C2_UART_DMA_BASE, 0x100);
++#endif
++#if (CONFIG_AST1070_NR >=4)
++ } else if (node == 3) {
++ dma->reg_base = ioremap(AST_C3_UART_DMA_BASE, 0x100);
++#endif
++ } else {
++ printk("node out of range !! \n");
++ return 1;
++ }
++
++ if (!dma->reg_base) {
++ printk(KERN_ERR "%s: failed to ioremap()\n", __func__);
++ return -ENXIO;
++ }
++
++ ast1070_uart_dma_write(dma, 0xff, UART_DMA_ISR);
++ ast1070_uart_dma_write(dma, 0, UART_DMA_IER);
++
++ for(i=0;i<4;i++) {
++ //TX ------------------------
++ dma->dma_tx_ch[i].enable = 0;
++ dma->dma_tx_ch[i].ch_no = i;
++ dma->dma_tx_ch[i].direction = 1;
++ //tx descriptor allocation
++ dma->dma_tx_ch[i].desc = dma_alloc_coherent(NULL, sizeof(struct uart_dma_desc), &(dma->dma_tx_ch[i].desc_dma_addr), GFP_KERNEL);
++ if (dma->dma_tx_ch[i].desc == NULL) {
++ DMADUG("Can't allocate tx descriptor\n");
++ return 0;
++ }
++ memset(dma->dma_tx_ch[i].desc, 0, sizeof(struct uart_dma_desc));
++ DMADUG("tx_desc [%d] virt = %x, dma = %x\n", i, (u32)dma->dma_tx_ch[i].desc, dma->dma_tx_ch[i].desc_dma_addr);
++
++ ast1070_uart_dma_write(dma, 0, UART_DMA0_TX_CTRL + (i*8));
++ dma->dma_tx_ch[i].ctrl_offset = UART_DMA0_TX_CTRL + (i*8);
++ dma->dma_tx_ch[i].desc_offset = UART_DMA0_TX_DESCPT + (i*8);
++
++ //RX ------------------------
++ dma->dma_rx_ch[i].enable = 0;
++ dma->dma_rx_ch[i].ch_no = i;
++ dma->dma_rx_ch[i].direction = 0;
++ //rx descriptor allocation
++ dma->dma_rx_ch[i].desc = dma_alloc_coherent(NULL, sizeof(struct uart_dma_desc), &(dma->dma_rx_ch[i].desc_dma_addr), GFP_KERNEL);
++ if (dma->dma_rx_ch[i].desc == NULL) {
++ DMADUG("Can't allocate tx descriptor\n");
++ return 0;
++ }
++ memset(dma->dma_rx_ch[i].desc, 0, sizeof(struct uart_dma_desc));
++ DMADUG("rx_desc [%d] virt = %x, dma = %x\n", i, (u32)dma->dma_rx_ch[i].desc, dma->dma_rx_ch[i].desc_dma_addr);
++ ast1070_uart_dma_write(dma, 0, UART_DMA0_RX_CTRL + (i*8));
++ dma->dma_rx_ch[i].ctrl_offset = UART_DMA0_RX_CTRL + (i*8);
++ dma->dma_rx_ch[i].desc_offset = UART_DMA0_RX_DESCPT + (i*8);
++ }
++
++ DMADUG("reg base = %x \n", (u32)dma->reg_base);
++
++ if(node == 0) {
++ for(i=0;i<4;i++) {
++ ret = request_irq(IRQ_C0_N1_UART_DMA + i,
++ ast1070_c0_uart_dma_irq, IRQF_SHARED,
++ "ast1070_n1_uart_dma", dma);
++ if (ret)
++ printk ("Unable to get UART DMA IRQ !!!!!!!!!!!!!!!!!!!!\n");
++ }
++#if (CONFIG_AST1070_NR >=2)
++ } else if (node == 1) {
++ for(i=0;i<4;i++) {
++ ret = request_irq(IRQ_C1_N1_UART_DMA + i,
++ ast1070_c1_uart_dma_irq, IRQF_SHARED,
++ "ast1070_n1_uart_dma", dma);
++ if (ret)
++ printk ("Unable to get UART DMA IRQ !!!!!!!!!!!!!!!!!!!!\n");
++ }
++#endif
++#if (CONFIG_AST1070_NR >=3)
++ } else if (node == 2) {
++ for(i=0;i<4;i++) {
++ ret = request_irq(IRQ_C2_N1_UART_DMA + i,
++ ast1070_c2_uart_dma_irq, IRQF_SHARED,
++ "ast1070_n1_uart_dma", dma);
++ if (ret)
++ printk ("Unable to get UART DMA IRQ !!!!!!!!!!!!!!!!!!!!\n");
++ }
++#endif
++#if (CONFIG_AST1070_NR >=4)
++ } else if (node == 3) {
++ for(i=0;i<4;i++) {
++ ret = request_irq(IRQ_C3_N1_UART_DMA + i,
++ ast1070_c3_uart_dma_irq, IRQF_SHARED,
++ "ast1070_n1_uart_dma", dma);
++ if (ret)
++ printk ("Unable to get UART DMA IRQ !!!!!!!!!!!!!!!!!!!!\n");
++ }
++#endif
++ } else {
++ printk("ERROR !! \n");
++ }
++
++ //Limit : AST1070 4* SPI CLK < AST2400 HCLK
++
++#ifdef AST1070_FPGA
++ //Low SPI clk setting == PCLK/8 , set 11
++ ast1070_uart_dma_write(dma,
++ (ast1070_uart_dma_read(dma, UART_DMA_CTRL) & ~SPI_CLK_MASK) |
++ SPI_CLK_SET(0x3) |
++ DMA_RX_TIMEOUT(0xfff) |
++ TXDESC_AUTO_POLLING |
++ RXDESC_AUTO_POLLING
++ , UART_DMA_CTRL);
++#else
++ ast1070_uart_dma_write(dma,
++ (ast1070_uart_dma_read(dma, UART_DMA_CTRL) &
++ ~DMA_BURST_MASK) |
++ DMA_RX_TIMEOUT(0xfff) |
++ TXDESC_AUTO_POLLING |
++ RXDESC_AUTO_POLLING
++ , UART_DMA_CTRL);
++#endif
++
++ return 0;
++}
++
++EXPORT_SYMBOL(ast1070_uart_dma_init);
+diff --git a/arch/arm/plat-aspeed/ast1070_irq.c b/arch/arm/plat-aspeed/ast1070_irq.c
+new file mode 100644
+index 0000000..e859cd1
+--- /dev/null
++++ b/arch/arm/plat-aspeed/ast1070_irq.c
+@@ -0,0 +1,220 @@
++/*
++ * linux/arch/arm/plat-aspeed/ast1070_irq.c
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++ */
++#include <linux/init.h>
++#include <linux/stddef.h>
++#include <linux/list.h>
++#include <linux/timer.h>
++
++#include <linux/device.h>
++#include <linux/dma-mapping.h>
++#include <linux/platform_device.h>
++#include <linux/sysdev.h>
++#include <linux/interrupt.h>
++#include <asm/system.h>
++#include <linux/irq.h>
++
++#include <mach/hardware.h>
++#include <asm/mach/irq.h>
++
++#include <asm/irq.h>
++#include <asm/io.h>
++
++#include <plat/regs-ast1070-intc.h>
++
++#define irq_to_c0_vic(irq_no) (irq_no-IRQ_C0_VIC_CHAIN_START)
++
++static void ast1070_c0_mask_irq(unsigned int irq)
++{
++ u32 regVal;
++// printk("ast_c0_mask_irq %d\n",irq);
++ irq = irq_to_c0_vic(irq);
++// printk("ast_c0_mask_irq cvic %d\n",irq);
++ regVal = readl(AST_INTR_DIS(0));
++ regVal |= (1 << irq);
++ writel(regVal, AST_INTR_DIS(0));
++
++}
++
++static void ast1070_c0_unmask_irq(unsigned int irq)
++{
++ u32 regVal;
++// printk("ast_c0_unmask_irq %d\n",irq);
++ irq = irq_to_c0_vic(irq);
++// printk("ast_c0_unmask_irq cvic %d\n",irq);
++ regVal = readl(AST_INTR_EN(0));
++ regVal |= (1 << irq);
++ writel(regVal, AST_INTR_EN(0));
++}
++
++static struct irq_chip ast1070_c0_irq_chip = {
++ .name = "ast1070_c0",
++ .ack = ast1070_c0_mask_irq,
++ .mask = ast1070_c0_mask_irq,
++ .unmask = ast1070_c0_unmask_irq,
++};
++
++static void
++ast1070_c0_handle_irq(unsigned int irq, struct irq_desc *desc)
++{
++ int i,cvic_irq=0;
++ unsigned long sts = readl(AST_IRQ_STS(0));
++
++ if(irq != IRQ_C0_VIC_CHAIN)
++ BUG();
++
++ desc->chip->ack(IRQ_C0_VIC_CHAIN);
++
++ if (sts == 0) {
++ do_bad_IRQ(irq, desc);
++ return;
++ }
++
++ do {
++ for(i=0; i<AST_CVIC_NUM; i++) {
++ if((1<<i)& readl(AST_IRQ_STS(0))) {
++ cvic_irq =i;
++ break;
++ }
++ }
++ cvic_irq += IRQ_C0_VIC_CHAIN_START;
++ //dispatch IRQ
++// printk("dispatch ast1070 IRQ %d\n",cvic_irq);
++ generic_handle_irq(cvic_irq);
++
++ } while (readl(AST_IRQ_STS(0)));
++
++ desc->chip->unmask(IRQ_C0_VIC_CHAIN);
++
++}
++
++static int __init ast1070_c0_init_irq(void)
++{
++ unsigned int i;
++// printk("ast1070_c0_init_irq **==== Start ---------------\n");
++ /* CVIC */
++ writel(0, AST_INTR_EN(0));
++ writel(0xFFFFFFFF, AST_INTR_DIS(0));
++
++ //AST1070 total IRQ# 25
++ for (i = 0; i < AST_CVIC_NUM; i++)
++ {
++ IRQ_SET_HIGH_LEVEL(0,i);
++ IRQ_SET_LEVEL_TRIGGER(0,i);
++ set_irq_chip(i + IRQ_C0_VIC_CHAIN_START, &ast1070_c0_irq_chip);
++ set_irq_handler(i + IRQ_C0_VIC_CHAIN_START, handle_level_irq);
++ set_irq_flags(i + IRQ_C0_VIC_CHAIN_START, IRQF_VALID);
++ }
++ set_irq_chained_handler(IRQ_C0_VIC_CHAIN, ast1070_c0_handle_irq);
++// printk("ast1070_init_irq **==== END ----------\n");
++ return 0;
++}
++
++arch_initcall(ast1070_c0_init_irq);
++
++#if (CONFIG_AST1070_NR >= 2)
++#define irq_to_c1_vic(irq_no) (irq_no-IRQ_C1_VIC_CHAIN_START)
++
++static void ast1070_c1_mask_irq(unsigned int irq)
++{
++ u32 regVal;
++// printk("ast_mask_irq %d\n",irq);
++ irq = irq_to_c1_vic(irq);
++// printk("ast_mask_irq cvic %d\n",irq);
++ regVal = readl(AST_INTR_DIS(1));
++ regVal |= (1 << irq);
++ writel(regVal, AST_INTR_DIS(1));
++
++}
++
++static void ast1070_c1_unmask_irq(unsigned int irq)
++{
++ u32 regVal;
++// printk("ast_unmask_irq %d\n",irq);
++ irq = irq_to_c1_vic(irq);
++// printk("ast_unmask_irq cvic %d\n",irq);
++ regVal = readl(AST_INTR_EN(1));
++ regVal |= (1 << irq);
++ writel(regVal, AST_INTR_EN(1));
++}
++
++static struct irq_chip ast1070_c1_irq_chip = {
++ .name = "ast1070_c1",
++ .ack = ast1070_c1_mask_irq,
++ .mask = ast1070_c1_mask_irq,
++ .unmask = ast1070_c1_unmask_irq,
++};
++
++static void
++ast1070_c1_handle_irq(unsigned int irq, struct irq_desc *desc)
++{
++ int i,cvic_irq=0;
++ unsigned long sts = readl(AST_IRQ_STS(1));
++
++ if(irq != IRQ_C1_VIC_CHAIN)
++ BUG();
++
++ desc->chip->ack(IRQ_C1_VIC_CHAIN);
++
++ if (sts == 0) {
++ do_bad_IRQ(irq, desc);
++ return;
++ }
++
++ do {
++ for(i=0; i<AST_CVIC_NUM; i++) {
++ if((1<<i)& readl(AST_IRQ_STS(1))) {
++ cvic_irq =i;
++ break;
++ }
++ }
++ cvic_irq += IRQ_C1_VIC_CHAIN_START;
++ //dispatch IRQ
++// printk("dispatch ast1070 IRQ %d\n",cvic_irq);
++ generic_handle_irq(cvic_irq);
++
++ } while (readl(AST_IRQ_STS(1)));
++
++ desc->chip->unmask(IRQ_C1_VIC_CHAIN);
++
++}
++
++static int __init ast1070_c1_init_irq(void)
++{
++ unsigned int i;
++// printk("ast1070_c1_init_irq **==== Start ---------------\n");
++ /* CVIC */
++ writel(0, AST_INTR_EN(1));
++ writel(0xFFFFFFFF, AST_INTR_DIS(1));
++
++ //AST1070 total IRQ# 25
++ for (i = 0; i < AST_CVIC_NUM; i++)
++ {
++ IRQ_SET_HIGH_LEVEL(1,i);
++ IRQ_SET_LEVEL_TRIGGER(1,i);
++ set_irq_chip(i + IRQ_C1_VIC_CHAIN_START, &ast1070_c1_irq_chip);
++ set_irq_handler(i + IRQ_C1_VIC_CHAIN_START, handle_level_irq);
++ set_irq_flags(i + IRQ_C1_VIC_CHAIN_START, IRQF_VALID);
++ }
++ set_irq_chained_handler(IRQ_C1_VIC_CHAIN, ast1070_c1_handle_irq);
++// printk("ast1070_init_irq **==== END ----------\n");
++ return 0;
++}
++
++arch_initcall(ast1070_c1_init_irq);
++
++#endif
+diff --git a/arch/arm/plat-aspeed/dev-adc.c b/arch/arm/plat-aspeed/dev-adc.c
+new file mode 100644
+index 0000000..e8d325a
+--- /dev/null
++++ b/arch/arm/plat-aspeed/dev-adc.c
+@@ -0,0 +1,76 @@
++/********************************************************************************
++* File Name : linux/arch/arm/plat-aspeed/dev-adc.c
++* Author : Ryan chen
++* Description : ASPEED ADC Device
++*
++* Copyright (C) ASPEED Technology Inc.
++* This program is free software; you can redistribute it and/or modify
++* it under the terms of the GNU General Public License as published by the Free Software Foundation;
++* either version 2 of the License, or (at your option) any later version.
++*
++* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
++* without even the implied warranty of MERCHANTABILITY or
++* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
++*
++* You should have received a copy of the GNU General Public License
++* along with this program; if not, write to the Free Software
++* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++
++* History :
++* 1. 2012/08/06 ryan chen create this file
++*
++********************************************************************************/
++
++#include <linux/kernel.h>
++#include <linux/string.h>
++#include <linux/platform_device.h>
++
++#if defined(CONFIG_COLDFIRE)
++#include <asm/sizes.h>
++
++#include <asm/arch/irqs.h>
++#include <asm/arch/platform.h>
++#include <asm/arch/devs.h>
++#include <asm/arch/ast-scu.h>
++#else
++#include <mach/irqs.h>
++#include <mach/platform.h>
++#include <plat/devs.h>
++#include <plat/ast-scu.h>
++#endif
++
++/* --------------------------------------------------------------------
++ * ADC
++ * -------------------------------------------------------------------- */
++
++#if defined(CONFIG_SENSORS_AST_ADC) || defined(CONFIG_SENSORS_AST_ADC_MODULE) || defined(CONFIG_SENSORS_AST1010_ADC) || defined(CONFIG_SENSORS_AST1010_ADC_MODULE)
++static struct resource ast_adc_resources[] = {
++ [0] = {
++ .start = AST_ADC_BASE,
++ .end = AST_ADC_BASE + SZ_4K - 1,
++ .flags = IORESOURCE_MEM,
++ },
++ [1] = {
++ .start = IRQ_ADC,
++ .end = IRQ_ADC,
++ .flags = IORESOURCE_IRQ,
++ },
++};
++
++struct platform_device ast_adc_device = {
++ .name = "ast_adc",
++ .id = 0,
++ .resource = ast_adc_resources,
++ .num_resources = ARRAY_SIZE(ast_adc_resources),
++};
++
++void __init ast_add_device_adc(void)
++{
++ //SCU ADC CTRL Reset
++ ast_scu_init_adc();
++
++ platform_device_register(&ast_adc_device);
++}
++#else
++void __init ast_add_device_adc(void) {}
++#endif
+diff --git a/arch/arm/plat-aspeed/dev-ci2c.c b/arch/arm/plat-aspeed/dev-ci2c.c
+new file mode 100644
+index 0000000..875639f
+--- /dev/null
++++ b/arch/arm/plat-aspeed/dev-ci2c.c
+@@ -0,0 +1,521 @@
++/********************************************************************************
++* File Name : linux/arch/arm/plat-aspeed/dev-ci2c.c
++* Author : Ryan chen
++* Description : ASPEED I2C Device
++*
++* Copyright (C) ASPEED Technology Inc.
++* This program is free software; you can redistribute it and/or modify
++* it under the terms of the GNU General Public License as published by the Free Software Foundation;
++* either version 2 of the License, or (at your option) any later version.
++*
++* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
++* without even the implied warranty of MERCHANTABILITY or
++* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
++*
++* You should have received a copy of the GNU General Public License
++* along with this program; if not, write to the Free Software
++* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++
++* History :
++* 1. 2012/07/30 ryan chen create this file
++*
++********************************************************************************/
++
++#include <linux/kernel.h>
++#include <linux/string.h>
++#include <linux/platform_device.h>
++#include <linux/i2c.h>
++
++#include <asm/io.h>
++#include <mach/irqs.h>
++#include <mach/platform.h>
++#include <plat/ast_i2c.h>
++
++#include <plat/devs.h>
++#include <plat/regs-iic.h>
++#include <plat/ast-scu.h>
++#include <plat/ast1070-scu.h>
++/* --------------------------------------------------------------------
++ * CI2C
++ * -------------------------------------------------------------------- */
++#if defined(CONFIG_I2C_AST1070) || defined(CONFIG_I2C_AST1070_MODULE)
++
++static struct ast_i2c_driver_data ast_ci2c_data = {
++ .bus_clk = 100000, //bus clock 100KHz
++ .master_dma = DMA_MODE,
++ .slave_dma = BYTE_MODE,
++#ifdef CONFIG_AST_I2C_SLAVE_MODE
++ .slave_xfer = i2c_slave_xfer,
++ .slave_init = i2c_slave_init,
++#endif
++#ifdef CONFIG_AST_LPC_PLUS
++ //use lpc+ clock
++ .get_i2c_clock = ast_get_lhclk,
++#else
++ .get_i2c_clock = ast_get_d2_pll_clk,
++#endif
++};
++
++static u64 ast_i2c_dma_mask = 0xffffffffUL;
++static struct resource ast_ci2c_dev1_resources[] = {
++ [0] = {
++ .start = AST_C0_I2C_BASE + AST_CI2C_DEVICE1,
++ .end = AST_C0_I2C_BASE + AST_CI2C_DEVICE1 + 4*SZ_16 - 1,
++ .flags = IORESOURCE_MEM,
++ },
++ [1] = {
++ .start = IRQ_C0_I2C,
++ .end = IRQ_C0_I2C,
++ .flags = IORESOURCE_IRQ,
++ },
++};
++
++struct platform_device ast_ci2c_dev1_device = {
++ .name = "ast-i2c",
++ .id = NUM_BUS + 0,
++ .dev = {
++ .dma_mask = &ast_i2c_dma_mask,
++ .coherent_dma_mask = 0xffffffff,
++ .platform_data = &ast_ci2c_data,
++ },
++ .resource = ast_ci2c_dev1_resources,
++ .num_resources = ARRAY_SIZE(ast_ci2c_dev1_resources),
++};
++
++static struct resource ast_ci2c_dev2_resources[] = {
++ [0] = {
++ .start = AST_C0_I2C_BASE + AST_CI2C_DEVICE2,
++ .end = AST_C0_I2C_BASE + AST_CI2C_DEVICE2 + 4*SZ_16 - 1,
++ .flags = IORESOURCE_MEM,
++ },
++ [1] = {
++ .start = IRQ_C0_I2C,
++ .end = IRQ_C0_I2C,
++ .flags = IORESOURCE_IRQ,
++ },
++};
++
++struct platform_device ast_ci2c_dev2_device = {
++ .name = "ast-i2c",
++ .id = NUM_BUS + 1,
++ .dev = {
++ .dma_mask = &ast_i2c_dma_mask,
++ .coherent_dma_mask = 0xffffffff,
++ .platform_data = &ast_ci2c_data,
++ },
++ .resource = ast_ci2c_dev2_resources,
++ .num_resources = ARRAY_SIZE(ast_ci2c_dev2_resources),
++};
++
++static struct resource ast_ci2c_dev3_resources[] = {
++ [0] = {
++ .start = AST_C0_I2C_BASE + AST_CI2C_DEVICE3,
++ .end = AST_C0_I2C_BASE + AST_CI2C_DEVICE3 + 4*SZ_16 - 1,
++ .flags = IORESOURCE_MEM,
++ },
++ [1] = {
++ .start = IRQ_C0_I2C,
++ .end = IRQ_C0_I2C,
++ .flags = IORESOURCE_IRQ,
++ },
++};
++
++struct platform_device ast_ci2c_dev3_device = {
++ .name = "ast-i2c",
++ .id = NUM_BUS + 2,
++ .dev = {
++ .dma_mask = &ast_i2c_dma_mask,
++ .coherent_dma_mask = 0xffffffff,
++ .platform_data = &ast_ci2c_data,
++ },
++ .resource = ast_ci2c_dev3_resources,
++ .num_resources = ARRAY_SIZE(ast_ci2c_dev3_resources),
++};
++
++static struct resource ast_ci2c_dev4_resources[] = {
++ [0] = {
++ .start = AST_C0_I2C_BASE + AST_CI2C_DEVICE4,
++ .end = AST_C0_I2C_BASE + AST_CI2C_DEVICE4 + 4*SZ_16 - 1,
++ .flags = IORESOURCE_MEM,
++ },
++ [1] = {
++ .start = IRQ_C0_I2C,
++ .end = IRQ_C0_I2C,
++ .flags = IORESOURCE_IRQ,
++ },
++};
++
++struct platform_device ast_ci2c_dev4_device = {
++ .name = "ast-i2c",
++ .id = NUM_BUS + 3,
++ .dev = {
++ .dma_mask = &ast_i2c_dma_mask,
++ .coherent_dma_mask = 0xffffffff,
++ .platform_data = &ast_ci2c_data,
++ },
++ .resource = ast_ci2c_dev4_resources,
++ .num_resources = ARRAY_SIZE(ast_ci2c_dev4_resources),
++};
++
++static struct resource ast_ci2c_dev5_resources[] = {
++ [0] = {
++ .start = AST_C0_I2C_BASE + AST_CI2C_DEVICE5,
++ .end = AST_C0_I2C_BASE + AST_CI2C_DEVICE5 + 4*SZ_16 - 1,
++ .flags = IORESOURCE_MEM,
++ },
++ [1] = {
++ .start = IRQ_C0_I2C,
++ .end = IRQ_C0_I2C,
++ .flags = IORESOURCE_IRQ,
++ },
++};
++
++struct platform_device ast_ci2c_dev5_device = {
++ .name = "ast-i2c",
++ .id = NUM_BUS + 4,
++ .dev = {
++ .dma_mask = &ast_i2c_dma_mask,
++ .coherent_dma_mask = 0xffffffff,
++ .platform_data = &ast_ci2c_data,
++ },
++ .resource = ast_ci2c_dev5_resources,
++ .num_resources = ARRAY_SIZE(ast_ci2c_dev5_resources),
++};
++
++static struct resource ast_ci2c_dev6_resources[] = {
++ [0] = {
++ .start = AST_C0_I2C_BASE + AST_CI2C_DEVICE6,
++ .end = AST_C0_I2C_BASE + AST_CI2C_DEVICE6 + 4*SZ_16 - 1,
++ .flags = IORESOURCE_MEM,
++ },
++ [1] = {
++ .start = IRQ_C0_I2C,
++ .end = IRQ_C0_I2C,
++ .flags = IORESOURCE_IRQ,
++ },
++};
++
++struct platform_device ast_ci2c_dev6_device = {
++ .name = "ast-i2c",
++ .id = NUM_BUS + 5,
++ .dev = {
++ .dma_mask = &ast_i2c_dma_mask,
++ .coherent_dma_mask = 0xffffffff,
++ .platform_data = &ast_ci2c_data,
++ },
++ .resource = ast_ci2c_dev6_resources,
++ .num_resources = ARRAY_SIZE(ast_ci2c_dev6_resources),
++};
++
++static struct resource ast_ci2c_dev7_resources[] = {
++ [0] = {
++ .start = AST_C0_I2C_BASE + AST_CI2C_DEVICE7,
++ .end = AST_C0_I2C_BASE + AST_CI2C_DEVICE7 + 4*SZ_16 - 1,
++ .flags = IORESOURCE_MEM,
++ },
++ [1] = {
++ .start = IRQ_C0_I2C,
++ .end = IRQ_C0_I2C,
++ .flags = IORESOURCE_IRQ,
++ },
++};
++
++struct platform_device ast_ci2c_dev7_device = {
++ .name = "ast-i2c",
++ .id = NUM_BUS + 6,
++ .dev = {
++ .dma_mask = &ast_i2c_dma_mask,
++ .coherent_dma_mask = 0xffffffff,
++ .platform_data = &ast_ci2c_data,
++ },
++ .resource = ast_ci2c_dev7_resources,
++ .num_resources = ARRAY_SIZE(ast_ci2c_dev7_resources),
++};
++
++static struct resource ast_ci2c_dev8_resources[] = {
++ [0] = {
++ .start = AST_C0_I2C_BASE + AST_CI2C_DEVICE8,
++ .end = AST_C0_I2C_BASE + AST_CI2C_DEVICE8 + 4*SZ_16 - 1,
++ .flags = IORESOURCE_MEM,
++ },
++ [1] = {
++ .start = IRQ_C0_I2C,
++ .end = IRQ_C0_I2C,
++ .flags = IORESOURCE_IRQ,
++ },
++};
++
++struct platform_device ast_ci2c_dev8_device = {
++ .name = "ast-i2c",
++ .id = NUM_BUS + 7,
++ .dev = {
++ .dma_mask = &ast_i2c_dma_mask,
++ .coherent_dma_mask = 0xffffffff,
++ .platform_data = &ast_ci2c_data,
++ },
++ .resource = ast_ci2c_dev8_resources,
++ .num_resources = ARRAY_SIZE(ast_ci2c_dev8_resources),
++};
++
++//
++#if (CONFIG_AST1070_NR >= 2)
++
++static struct ast_i2c_driver_data ast_c1_i2c_data = {
++ .bus_clk = 100000, //bus clock 100KHz
++ .master_dma = DMA_MODE,
++ .slave_dma = BYTE_MODE,
++#ifdef CONFIG_AST_I2C_SLAVE_MODE
++ .slave_xfer = i2c_slave_xfer,
++ .slave_init = i2c_slave_init,
++#endif
++#ifdef CONFIG_ARCH_AST2300
++ .get_i2c_clock = ast_get_d2_pll_clk,
++#else //AST2400 use lpc+ clock
++ .get_i2c_clock = ast_get_lhclk,
++#endif
++};
++
++static struct resource ast_c1_i2c_dev1_resources[] = {
++ [0] = {
++ .start = AST_C1_I2C_BASE + AST_CI2C_DEVICE1,
++ .end = AST_C1_I2C_BASE + AST_CI2C_DEVICE1 + 4*SZ_16 - 1,
++ .flags = IORESOURCE_MEM,
++ },
++ [1] = {
++ .start = IRQ_C1_I2C,
++ .end = IRQ_C1_I2C,
++ .flags = IORESOURCE_IRQ,
++ },
++};
++
++struct platform_device ast_c1_i2c_dev1_device = {
++ .name = "ast-i2c",
++ .id = NUM_BUS + 8 + 0,
++ .dev = {
++ .dma_mask = &ast_i2c_dma_mask,
++ .coherent_dma_mask = 0xffffffff,
++ .platform_data = &ast_c1_i2c_data,
++ },
++ .resource = ast_c1_i2c_dev1_resources,
++ .num_resources = ARRAY_SIZE(ast_c1_i2c_dev1_resources),
++};
++
++static struct resource ast_c1_i2c_dev2_resources[] = {
++ [0] = {
++ .start = AST_C1_I2C_BASE + AST_CI2C_DEVICE2,
++ .end = AST_C1_I2C_BASE + AST_CI2C_DEVICE2 + 4*SZ_16 - 1,
++ .flags = IORESOURCE_MEM,
++ },
++ [1] = {
++ .start = IRQ_C1_I2C,
++ .end = IRQ_C1_I2C,
++ .flags = IORESOURCE_IRQ,
++ },
++};
++
++struct platform_device ast_c1_i2c_dev2_device = {
++ .name = "ast-i2c",
++ .id = NUM_BUS + 8 + 1,
++ .dev = {
++ .dma_mask = &ast_i2c_dma_mask,
++ .coherent_dma_mask = 0xffffffff,
++ .platform_data = &ast_c1_i2c_data,
++ },
++ .resource = ast_c1_i2c_dev2_resources,
++ .num_resources = ARRAY_SIZE(ast_c1_i2c_dev2_resources),
++};
++
++static struct resource ast_c1_i2c_dev3_resources[] = {
++ [0] = {
++ .start = AST_C1_I2C_BASE + AST_CI2C_DEVICE3,
++ .end = AST_C1_I2C_BASE + AST_CI2C_DEVICE3 + 4*SZ_16 - 1,
++ .flags = IORESOURCE_MEM,
++ },
++ [1] = {
++ .start = IRQ_C1_I2C,
++ .end = IRQ_C1_I2C,
++ .flags = IORESOURCE_IRQ,
++ },
++};
++
++struct platform_device ast_c1_i2c_dev3_device = {
++ .name = "ast-i2c",
++ .id = NUM_BUS + 8 + 2,
++ .dev = {
++ .dma_mask = &ast_i2c_dma_mask,
++ .coherent_dma_mask = 0xffffffff,
++ .platform_data = &ast_c1_i2c_data,
++ },
++ .resource = ast_c1_i2c_dev3_resources,
++ .num_resources = ARRAY_SIZE(ast_c1_i2c_dev3_resources),
++};
++
++static struct resource ast_c1_i2c_dev4_resources[] = {
++ [0] = {
++ .start = AST_C1_I2C_BASE + AST_CI2C_DEVICE4,
++ .end = AST_C1_I2C_BASE + AST_CI2C_DEVICE4 + 4*SZ_16 - 1,
++ .flags = IORESOURCE_MEM,
++ },
++ [1] = {
++ .start = IRQ_C1_I2C,
++ .end = IRQ_C1_I2C,
++ .flags = IORESOURCE_IRQ,
++ },
++};
++
++struct platform_device ast_c1_i2c_dev4_device = {
++ .name = "ast-i2c",
++ .id = NUM_BUS + 8 + 3,
++ .dev = {
++ .dma_mask = &ast_i2c_dma_mask,
++ .coherent_dma_mask = 0xffffffff,
++ .platform_data = &ast_c1_i2c_data,
++ },
++ .resource = ast_c1_i2c_dev4_resources,
++ .num_resources = ARRAY_SIZE(ast_c1_i2c_dev4_resources),
++};
++
++static struct resource ast_c1_i2c_dev5_resources[] = {
++ [0] = {
++ .start = AST_C1_I2C_BASE + AST_CI2C_DEVICE5,
++ .end = AST_C1_I2C_BASE + AST_CI2C_DEVICE5 + 4*SZ_16 - 1,
++ .flags = IORESOURCE_MEM,
++ },
++ [1] = {
++ .start = IRQ_C1_I2C,
++ .end = IRQ_C1_I2C,
++ .flags = IORESOURCE_IRQ,
++ },
++};
++
++struct platform_device ast_c1_i2c_dev5_device = {
++ .name = "ast-i2c",
++ .id = NUM_BUS + 8 + 4,
++ .dev = {
++ .dma_mask = &ast_i2c_dma_mask,
++ .coherent_dma_mask = 0xffffffff,
++ .platform_data = &ast_c1_i2c_data,
++ },
++ .resource = ast_c1_i2c_dev5_resources,
++ .num_resources = ARRAY_SIZE(ast_c1_i2c_dev5_resources),
++};
++
++static struct resource ast_c1_i2c_dev6_resources[] = {
++ [0] = {
++ .start = AST_C1_I2C_BASE + AST_CI2C_DEVICE6,
++ .end = AST_C1_I2C_BASE + AST_CI2C_DEVICE6 + 4*SZ_16 - 1,
++ .flags = IORESOURCE_MEM,
++ },
++ [1] = {
++ .start = IRQ_C1_I2C,
++ .end = IRQ_C1_I2C,
++ .flags = IORESOURCE_IRQ,
++ },
++};
++
++struct platform_device ast_c1_i2c_dev6_device = {
++ .name = "ast-i2c",
++ .id = NUM_BUS + 8 + 5,
++ .dev = {
++ .dma_mask = &ast_i2c_dma_mask,
++ .coherent_dma_mask = 0xffffffff,
++ .platform_data = &ast_c1_i2c_data,
++ },
++ .resource = ast_c1_i2c_dev6_resources,
++ .num_resources = ARRAY_SIZE(ast_c1_i2c_dev6_resources),
++};
++
++static struct resource ast_c1_i2c_dev7_resources[] = {
++ [0] = {
++ .start = AST_C1_I2C_BASE + AST_CI2C_DEVICE7,
++ .end = AST_C1_I2C_BASE + AST_CI2C_DEVICE7 + 4*SZ_16 - 1,
++ .flags = IORESOURCE_MEM,
++ },
++ [1] = {
++ .start = IRQ_C1_I2C,
++ .end = IRQ_C1_I2C,
++ .flags = IORESOURCE_IRQ,
++ },
++};
++
++struct platform_device ast_c1_i2c_dev7_device = {
++ .name = "ast-i2c",
++ .id = NUM_BUS + 8 + 6,
++ .dev = {
++ .dma_mask = &ast_i2c_dma_mask,
++ .coherent_dma_mask = 0xffffffff,
++ .platform_data = &ast_c1_i2c_data,
++ },
++ .resource = ast_c1_i2c_dev7_resources,
++ .num_resources = ARRAY_SIZE(ast_c1_i2c_dev7_resources),
++};
++
++static struct resource ast_c1_i2c_dev8_resources[] = {
++ [0] = {
++ .start = AST_C1_I2C_BASE + AST_CI2C_DEVICE8,
++ .end = AST_C1_I2C_BASE + AST_CI2C_DEVICE8 + 4*SZ_16 - 1,
++ .flags = IORESOURCE_MEM,
++ },
++ [1] = {
++ .start = IRQ_C1_I2C,
++ .end = IRQ_C1_I2C,
++ .flags = IORESOURCE_IRQ,
++ },
++};
++
++struct platform_device ast_c1_i2c_dev8_device = {
++ .name = "ast-i2c",
++ .id = NUM_BUS + 8 + 7,
++ .dev = {
++ .dma_mask = &ast_i2c_dma_mask,
++ .coherent_dma_mask = 0xffffffff,
++ .platform_data = &ast_c1_i2c_data,
++ },
++ .resource = ast_c1_i2c_dev8_resources,
++ .num_resources = ARRAY_SIZE(ast_c1_i2c_dev8_resources),
++};
++#endif
++//
++/*-------------------------------------*/
++void __init ast_add_device_ci2c(void)
++{
++ ast1070_scu_init_i2c(0);
++
++ ast_ci2c_data.reg_gr = IO_ADDRESS2(AST_C0_I2C_BASE);
++ if (!ast_ci2c_data.reg_gr) {
++ printk("ast_add_device_i2c ERROR \n");
++ return;
++ }
++ platform_device_register(&ast_ci2c_dev1_device);
++ platform_device_register(&ast_ci2c_dev2_device);
++ platform_device_register(&ast_ci2c_dev3_device);
++ platform_device_register(&ast_ci2c_dev4_device);
++ platform_device_register(&ast_ci2c_dev5_device);
++ platform_device_register(&ast_ci2c_dev6_device);
++ platform_device_register(&ast_ci2c_dev7_device);
++ platform_device_register(&ast_ci2c_dev8_device);
++
++
++#if (CONFIG_AST1070_NR >= 2)
++
++ ast1070_scu_init_i2c(1);
++
++ ast_c1_i2c_data.reg_gr = IO_ADDRESS2(AST_C1_I2C_BASE);
++ if (!ast_c1_i2c_data.reg_gr) {
++ printk("ast_add_device_i2c ERROR \n");
++ return;
++ }
++ platform_device_register(&ast_c1_i2c_dev1_device);
++ platform_device_register(&ast_c1_i2c_dev2_device);
++ platform_device_register(&ast_c1_i2c_dev3_device);
++ platform_device_register(&ast_c1_i2c_dev4_device);
++ platform_device_register(&ast_c1_i2c_dev5_device);
++ platform_device_register(&ast_c1_i2c_dev6_device);
++ platform_device_register(&ast_c1_i2c_dev7_device);
++ platform_device_register(&ast_c1_i2c_dev8_device);
++#endif
++
++}
++#else
++void __init ast_add_device_ci2c(void) {}
++#endif
+diff --git a/arch/arm/plat-aspeed/dev-clpc.c b/arch/arm/plat-aspeed/dev-clpc.c
+new file mode 100644
+index 0000000..d9fde7a
+--- /dev/null
++++ b/arch/arm/plat-aspeed/dev-clpc.c
+@@ -0,0 +1,240 @@
++/********************************************************************************
++* File Name : linux/arch/arm/plat-aspeed/dev-clpc.c
++* Author : Ryan chen
++* Description : ASPEED LPC Controller
++*
++* Copyright (C) ASPEED Technology Inc.
++* This program is free software; you can redistribute it and/or modify
++* it under the terms of the GNU General Public License as published by the Free Software Foundation;
++* either version 2 of the License, or (at your option) any later version.
++*
++* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
++* without even the implied warranty of MERCHANTABILITY or
++* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
++*
++* You should have received a copy of the GNU General Public License
++* along with this program; if not, write to the Free Software
++* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++
++* History :
++* 1. 2012/11/29 ryan chen create this file
++*
++********************************************************************************/
++
++#include <linux/kernel.h>
++#include <linux/string.h>
++#include <linux/platform_device.h>
++
++#include <mach/irqs.h>
++#include <mach/platform.h>
++#include <plat/devs.h>
++#include <plat/ast-scu.h>
++
++
++
++#include <linux/kernel.h>
++#include <linux/string.h>
++#include <linux/platform_device.h>
++
++#include <mach/irqs.h>
++#include <mach/platform.h>
++#include <plat/devs.h>
++#include <plat/ast-scu.h>
++
++
++/* --------------------------------------------------------------------
++ * LPC
++ * -------------------------------------------------------------------- */
++#if defined(CONFIG_CLPC) || defined(CONFIG_CLPC_MODULE)
++static u64 aspeed_lpc_dma_mask = 0xffffffffUL;
++
++static struct resource aspeed_clpc0_resource[] = {
++ [0] = {
++ .start = AST_CLPC1_BASE,
++ .end = AST_CLPC1_BASE + SZ_4K,
++ .flags = IORESOURCE_MEM,
++ },
++ [1] = {
++ .start = IRQ_N1_KCS,
++ .end = IRQ_N1_KCS,
++ .flags = IORESOURCE_IRQ,
++ },
++ [2] = {
++ .start = IRQ_N1_UART,
++ .end = IRQ_N1_UART,
++ .flags = IORESOURCE_IRQ,
++ },
++ [3] = {
++ .start = IRQ_N1_MAILBOX,
++ .end = IRQ_N1_MAILBOX,
++ .flags = IORESOURCE_IRQ,
++ },
++ [4] = {
++ .start = IRQ_N1_PORT80,
++ .end = IRQ_N1_PORT80,
++ .flags = IORESOURCE_IRQ,
++ },
++ [4] = {
++ .start = IRQ_N1_RESET,
++ .end = IRQ_N1_RESET,
++ .flags = IORESOURCE_IRQ,
++ },
++};
++
++static struct platform_device aspeed_clpc0_device = {
++ .name = "aspeed_lpc",
++ .id = 0,
++ .dev = {
++ .dma_mask = &aspeed_lpc_dma_mask,
++ .coherent_dma_mask = 0xffffffff,
++ },
++ .resource = aspeed_clpc0_resource,
++ .num_resources = ARRAY_SIZE(aspeed_clpc0_resource),
++};
++
++static struct resource aspeed_clpc1_resource[] = {
++ [0] = {
++ .start = AST_CLPC2_BASE,
++ .end = AST_CLPC2_BASE + SZ_4K,
++ .flags = IORESOURCE_MEM,
++ },
++ [1] = {
++ .start = IRQ_N2_KCS,
++ .end = IRQ_N2_KCS,
++ .flags = IORESOURCE_IRQ,
++ },
++ [2] = {
++ .start = IRQ_N2_UART,
++ .end = IRQ_N2_UART,
++ .flags = IORESOURCE_IRQ,
++ },
++ [3] = {
++ .start = IRQ_N2_MAILBOX,
++ .end = IRQ_N2_MAILBOX,
++ .flags = IORESOURCE_IRQ,
++ },
++ [4] = {
++ .start = IRQ_N2_PORT80,
++ .end = IRQ_N2_PORT80,
++ .flags = IORESOURCE_IRQ,
++ },
++ [4] = {
++ .start = IRQ_N2_RESET,
++ .end = IRQ_N2_RESET,
++ .flags = IORESOURCE_IRQ,
++ },
++};
++
++static struct platform_device aspeed_clpc1_device = {
++ .name = "aspeed_lpc",
++ .id = 1,
++ .dev = {
++ .dma_mask = &aspeed_lpc_dma_mask,
++ .coherent_dma_mask = 0xffffffff,
++ },
++ .resource = aspeed_clpc1_resource,
++ .num_resources = ARRAY_SIZE(aspeed_clpc1_resource),
++};
++
++static struct resource aspeed_clpc2_resource[] = {
++ [0] = {
++ .start = AST_CLPC3_BASE,
++ .end = AST_CLPC3_BASE + SZ_4K,
++ .flags = IORESOURCE_MEM,
++ },
++ [1] = {
++ .start = IRQ_N3_KCS,
++ .end = IRQ_N3_KCS,
++ .flags = IORESOURCE_IRQ,
++ },
++ [2] = {
++ .start = IRQ_N3_UART,
++ .end = IRQ_N3_UART,
++ .flags = IORESOURCE_IRQ,
++ },
++ [3] = {
++ .start = IRQ_N3_MAILBOX,
++ .end = IRQ_N3_MAILBOX,
++ .flags = IORESOURCE_IRQ,
++ },
++ [4] = {
++ .start = IRQ_N3_PORT80,
++ .end = IRQ_N3_PORT80,
++ .flags = IORESOURCE_IRQ,
++ },
++ [4] = {
++ .start = IRQ_N3_RESET,
++ .end = IRQ_N3_RESET,
++ .flags = IORESOURCE_IRQ,
++ },
++};
++
++static struct platform_device aspeed_clpc2_device = {
++ .name = "aspeed_lpc",
++ .id = 2,
++ .dev = {
++ .dma_mask = &aspeed_lpc_dma_mask,
++ .coherent_dma_mask = 0xffffffff,
++ },
++ .resource = aspeed_clpc2_resource,
++ .num_resources = ARRAY_SIZE(aspeed_clpc2_resource),
++};
++
++static struct resource aspeed_clpc3_resource[] = {
++ [0] = {
++ .start = AST_CLPC4_BASE,
++ .end = AST_CLPC4_BASE + SZ_4K,
++ .flags = IORESOURCE_MEM,
++ },
++ [1] = {
++ .start = IRQ_N4_KCS,
++ .end = IRQ_N4_KCS,
++ .flags = IORESOURCE_IRQ,
++ },
++ [2] = {
++ .start = IRQ_N4_UART,
++ .end = IRQ_N4_UART,
++ .flags = IORESOURCE_IRQ,
++ },
++ [3] = {
++ .start = IRQ_N4_MAILBOX,
++ .end = IRQ_N4_MAILBOX,
++ .flags = IORESOURCE_IRQ,
++ },
++ [4] = {
++ .start = IRQ_N4_PORT80,
++ .end = IRQ_N4_PORT80,
++ .flags = IORESOURCE_IRQ,
++ },
++ [4] = {
++ .start = IRQ_N4_RESET,
++ .end = IRQ_N4_RESET,
++ .flags = IORESOURCE_IRQ,
++ },
++};
++
++static struct platform_device aspeed_clpc3_device = {
++ .name = "aspeed_lpc",
++ .id = 3,
++ .dev = {
++ .dma_mask = &aspeed_lpc_dma_mask,
++ .coherent_dma_mask = 0xffffffff,
++ },
++ .resource = aspeed_clpc3_resource,
++ .num_resources = ARRAY_SIZE(aspeed_clpc3_resource),
++};
++
++void __init aspeed_add_device_clpc(void)
++{
++// it should enable at u-boot
++// aspeed_scu_init_lpc();
++
++ platform_device_register(&aspeed_clpc0_device);
++ platform_device_register(&aspeed_clpc1_device);
++ platform_device_register(&aspeed_clpc2_device);
++ platform_device_register(&aspeed_clpc3_device);
++}
++#else
++void __init aspeed_add_device_clpc(void) {}
++#endif
++
+diff --git a/arch/arm/plat-aspeed/dev-cuart.c b/arch/arm/plat-aspeed/dev-cuart.c
+new file mode 100644
+index 0000000..8731f7c
+--- /dev/null
++++ b/arch/arm/plat-aspeed/dev-cuart.c
+@@ -0,0 +1,197 @@
++/********************************************************************************
++* File Name : linux/arch/arm/plat-aspeed/dev-cuart.c
++* Author : Ryan chen
++*
++* Copyright (C) 2012-2020 ASPEED Technology Inc.
++* This program is free software; you can redistribute it and/or modify
++* it under the terms of the GNU General Public License as published by the Free Software Foundation;
++* either version 2 of the License, or (at your option) any later version.
++*
++* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
++* without even the implied warranty of MERCHANTABILITY or
++* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
++*
++* You should have received a copy of the GNU General Public License
++* along with this program; if not, write to the Free Software
++* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++
++* History :
++* 1. 2012/09/15 ryan chen create this file
++*
++********************************************************************************/
++
++#include <linux/kernel.h>
++#include <linux/string.h>
++#include <linux/platform_device.h>
++#include <linux/serial.h>
++#include <linux/tty.h>
++#include <linux/serial_8250.h>
++
++#include <mach/irqs.h>
++#include <mach/platform.h>
++#include <mach/hardware.h>
++#include <mach/ast-uart-dma.h>
++
++#include <plat/ast1070-devs.h>
++#include <plat/ast1070-scu.h>
++
++/* --------------------------------------------------------------------
++ * UART
++ * -------------------------------------------------------------------- */
++#if defined(CONFIG_SERIAL_8250) && defined(CONFIG_ARCH_AST1070)
++static struct ast_uart_dma_data c0_uart0_dma_data = {
++ .chip_no = 0,
++ .dma_ch = 0,
++};
++
++static struct ast_uart_dma_data c0_uart1_dma_data = {
++ .chip_no = 0,
++ .dma_ch = 1,
++};
++
++static struct ast_uart_dma_data c0_uart2_dma_data = {
++ .chip_no = 0,
++ .dma_ch = 2,
++};
++
++static struct ast_uart_dma_data c0_uart3_dma_data = {
++ .chip_no = 0,
++ .dma_ch = 3,
++};
++
++#if (CONFIG_AST1070_NR >=2)
++static struct ast_uart_dma_data c1_uart0_dma_data = {
++ .chip_no = 1,
++ .dma_ch = 0,
++};
++
++static struct ast_uart_dma_data c1_uart1_dma_data = {
++ .chip_no = 1,
++ .dma_ch = 1,
++};
++
++static struct ast_uart_dma_data c1_uart2_dma_data = {
++ .chip_no = 1,
++ .dma_ch = 2,
++};
++
++static struct ast_uart_dma_data c1_uart3_dma_data = {
++ .chip_no = 1,
++ .dma_ch = 3,
++};
++#endif
++
++static struct plat_serial8250_port ast1070_c_uart_data[] = {
++ {
++ .mapbase = AST_C0_UART0_BASE,
++ .membase = (char*)(IO_ADDRESS2(AST_C0_UART0_BASE)),
++ .irq = IRQ_C0_N1_UART,
++ .uartclk = (24*1000000L),
++ .regshift = 2,
++ .iotype = UPIO_MEM,
++ .flags = UPF_IOREMAP | UPF_BOOT_AUTOCONF | UPF_SKIP_TEST,
++ .private_data = &c0_uart0_dma_data,
++ },
++ {
++ .mapbase = AST_C0_UART1_BASE,
++ .membase = (char*)(IO_ADDRESS2(AST_C0_UART1_BASE)),
++ .irq = IRQ_C0_N2_UART,
++ .uartclk = (24*1000000L),
++ .regshift = 2,
++ .iotype = UPIO_MEM,
++ .flags = UPF_IOREMAP | UPF_BOOT_AUTOCONF | UPF_SKIP_TEST,
++ .private_data = &c0_uart1_dma_data,
++ },
++ {
++ .mapbase = AST_C0_UART2_BASE,
++ .membase = (char*)(IO_ADDRESS2(AST_C0_UART2_BASE)),
++ .irq = IRQ_C0_N3_UART,
++ .uartclk = (24*1000000L),
++ .regshift = 2,
++ .iotype = UPIO_MEM,
++ .flags = UPF_IOREMAP | UPF_BOOT_AUTOCONF | UPF_SKIP_TEST,
++ .private_data = &c0_uart2_dma_data,
++ },
++ {
++ .mapbase = AST_C0_UART3_BASE,
++ .membase = (char*)(IO_ADDRESS2(AST_C0_UART3_BASE)),
++ .irq = IRQ_C0_N4_UART,
++ .uartclk = (24*1000000L),
++ .regshift = 2,
++ .iotype = UPIO_MEM,
++ .flags = UPF_IOREMAP | UPF_BOOT_AUTOCONF | UPF_SKIP_TEST,
++ .private_data = &c0_uart3_dma_data,
++ },
++#if (CONFIG_AST1070_NR >=2)
++ {
++ .mapbase = AST_C1_UART0_BASE,
++ .membase = (char*)(IO_ADDRESS2(AST_C1_UART0_BASE)),
++ .irq = IRQ_C1_N1_UART,
++ .uartclk = (24*1000000L),
++ .regshift = 2,
++ .iotype = UPIO_MEM,
++ .flags = UPF_IOREMAP | UPF_BOOT_AUTOCONF | UPF_SKIP_TEST,
++ .private_data = &c1_uart0_dma_data,
++ },
++ {
++ .mapbase = AST_C1_UART1_BASE,
++ .membase = (char*)(IO_ADDRESS2(AST_C1_UART1_BASE)),
++ .irq = IRQ_C1_N2_UART,
++ .uartclk = (24*1000000L),
++ .regshift = 2,
++ .iotype = UPIO_MEM,
++ .flags = UPF_IOREMAP | UPF_BOOT_AUTOCONF | UPF_SKIP_TEST,
++ .private_data = &c1_uart1_dma_data,
++ },
++ {
++ .mapbase = AST_C1_UART2_BASE,
++ .membase = (char*)(IO_ADDRESS2(AST_C1_UART2_BASE)),
++ .irq = IRQ_C1_N3_UART,
++ .uartclk = (24*1000000L),
++ .regshift = 2,
++ .iotype = UPIO_MEM,
++ .flags = UPF_IOREMAP | UPF_BOOT_AUTOCONF | UPF_SKIP_TEST,
++ .private_data = &c1_uart2_dma_data,
++ },
++ {
++ .mapbase = AST_C1_UART3_BASE,
++ .membase = (char*)(IO_ADDRESS2(AST_C1_UART3_BASE)),
++ .irq = IRQ_C1_N4_UART,
++ .uartclk = (24*1000000L),
++ .regshift = 2,
++ .iotype = UPIO_MEM,
++ .flags = UPF_IOREMAP | UPF_BOOT_AUTOCONF | UPF_SKIP_TEST,
++ .private_data = &c1_uart3_dma_data,
++ },
++#endif
++ { },
++};
++
++struct platform_device ast1070_c_uart_device = {
++#ifdef CONFIG_SERIAL_AST_DMA_UART
++ .name = "ast-uart-dma",
++#else
++ .name = "serial8250",
++#endif
++ .id = PLAT8250_DEV_PLATFORM1,
++ .dev = {
++ .platform_data = ast1070_c_uart_data,
++ },
++};
++
++void __init ast_add_device_cuart(void)
++{
++ int i;//j;
++ for(i=0;i<CONFIG_AST1070_NR;i++) {
++ //reset 4 UART
++ ast1070_scu_init_uart(i);
++ //Please don't enable : Feature remove
++// for(j=0;j<4;j++)
++// ast1070_multi_func_uart(i, j);
++ }
++
++ platform_device_register(&ast1070_c_uart_device);
++}
++#else
++void __init ast_add_device_cuart(void) {}
++#endif
+diff --git a/arch/arm/plat-aspeed/dev-ehci.c b/arch/arm/plat-aspeed/dev-ehci.c
+new file mode 100644
+index 0000000..8c34a63
+--- /dev/null
++++ b/arch/arm/plat-aspeed/dev-ehci.c
+@@ -0,0 +1,73 @@
++/********************************************************************************
++* File Name : linux/arch/arm/plat-aspeed/dev-ehci.c
++* Author : Ryan chen
++* Description : ASPEED EHCI Device
++*
++* Copyright (C) ASPEED Technology Inc.
++* This program is free software; you can redistribute it and/or modify
++* it under the terms of the GNU General Public License as published by the Free Software Foundation;
++* either version 2 of the License, or (at your option) any later version.
++*
++* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
++* without even the implied warranty of MERCHANTABILITY or
++* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
++*
++* You should have received a copy of the GNU General Public License
++* along with this program; if not, write to the Free Software
++* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++
++* History :
++* 1. 2012/07/30 ryan chen create this file
++*
++********************************************************************************/
++
++#include <linux/kernel.h>
++#include <linux/string.h>
++#include <linux/platform_device.h>
++
++#include <mach/irqs.h>
++#include <mach/platform.h>
++#include <plat/devs.h>
++#include <plat/ast-scu.h>
++
++
++/* --------------------------------------------------------------------
++ * EHCI
++ * -------------------------------------------------------------------- */
++#if defined(CONFIG_USB_EHCI_AST) || defined(CONFIG_USB_EHCI_AST_MODULE)
++static struct resource ast_echi_resource[] = {
++ [0] = {
++ .start = AST_EHCI_BASE,
++ .end = AST_EHCI_BASE + SZ_256,
++ .flags = IORESOURCE_MEM,
++ },
++ [1] = {
++ .start = IRQ_EHCI,
++ .end = IRQ_EHCI,
++ .flags = IORESOURCE_IRQ,
++ },
++};
++
++static u64 ast_ehci_dma_mask = 0xffffffffUL;
++
++static struct platform_device ast_ehci_device = {
++ .name = "ehci-ast",
++ .id = 0,
++ .dev = {
++ .dma_mask = &ast_ehci_dma_mask,
++ .coherent_dma_mask = 0xffffffff,
++ },
++ .resource = ast_echi_resource,
++ .num_resources = ARRAY_SIZE(ast_echi_resource),
++};
++
++void __init ast_add_device_ehci(void)
++{
++ ast_scu_multi_func_usb20_host_hub(1);
++ ast_scu_init_usb20();
++
++ platform_device_register(&ast_ehci_device);
++}
++#else
++void __init ast_add_device_ehci(void) {}
++#endif
+diff --git a/arch/arm/plat-aspeed/dev-eth.c b/arch/arm/plat-aspeed/dev-eth.c
+new file mode 100644
+index 0000000..5d33e33
+--- /dev/null
++++ b/arch/arm/plat-aspeed/dev-eth.c
+@@ -0,0 +1,201 @@
++/********************************************************************************
++* File Name : linux/arch/arm/plat-aspeed/dev-eth.c
++* Author : Ryan Chen
++* Description : Aspeed Ethernet Device
++*
++* Copyright (C) ASPEED Technology Inc.
++* This program is free software; you can redistribute it and/or modify
++* it under the terms of the GNU General Public License as published by the Free Software Foundation;
++* either version 2 of the License, or (at your option) any later version.
++*
++* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
++* without even the implied warranty of MERCHANTABILITY or
++* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
++*
++* You should have received a copy of the GNU General Public License
++* along with this program; if not, write to the Free Software
++* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++
++* History :
++* 1. 2012/08/24 Ryan Chen initial
++*
++********************************************************************************/
++#include <linux/kernel.h>
++#include <linux/string.h>
++#include <linux/platform_device.h>
++
++#include <mach/irqs.h>
++#include <mach/platform.h>
++#include <mach/ftgmac100_drv.h>
++
++#include <plat/devs.h>
++#include <plat/ast-scu.h>
++
++/* --------------------------------------------------------------------
++ * Ethernet
++ * -------------------------------------------------------------------- */
++#if defined(CONFIG_ASPEEDMAC) || defined(CONFIG_ASPEEDMAC_MODULE)
++#ifdef AST_MAC0_BASE
++static struct ftgmac100_eth_data ast_eth0_data = {
++ .dev_addr = { 0x00, 0x84, 0x14, 0xA0, 0xB0, 0x22},
++ .phy_id = 1,
++};
++
++static u64 ast_eth_dmamask = 0xffffffffUL;
++static struct resource ast_mac0_resources[] = {
++ [0] = {
++ .start = AST_MAC0_BASE,
++ .end = AST_MAC0_BASE + SZ_128K - 1,
++ .flags = IORESOURCE_MEM,
++ },
++ [1] = {
++ .start = IRQ_MAC0,
++ .end = IRQ_MAC0,
++ .flags = IORESOURCE_IRQ,
++ },
++};
++
++static struct platform_device ast_eth0_device = {
++ .name = "ast_gmac",
++ .id = 0,
++ .dev = {
++ .dma_mask = &ast_eth_dmamask,
++ .coherent_dma_mask = 0xffffffff,
++ .platform_data = &ast_eth0_data,
++ },
++ .resource = ast_mac0_resources,
++ .num_resources = ARRAY_SIZE(ast_mac0_resources),
++};
++#endif
++#ifdef AST_MAC1_BASE
++static struct ftgmac100_eth_data ast_eth1_data = {
++ .dev_addr = { 0x00, 0x84, 0x14, 0xA0, 0xB0, 0x23},
++ .phy_id = 1,
++};
++
++static struct resource ast_mac1_resources[] = {
++ [0] = {
++ .start = AST_MAC1_BASE,
++ .end = AST_MAC1_BASE + SZ_128K - 1,
++ .flags = IORESOURCE_MEM,
++ },
++ [1] = {
++ .start = IRQ_MAC1,
++ .end = IRQ_MAC1,
++ .flags = IORESOURCE_IRQ,
++ },
++};
++
++static struct platform_device ast_eth1_device = {
++ .name = "ast_gmac",
++ .id = 1,
++ .dev = {
++ .dma_mask = &ast_eth_dmamask,
++ .coherent_dma_mask = 0xffffffff,
++ .platform_data = &ast_eth1_data,
++ },
++ .resource = ast_mac1_resources,
++ .num_resources = ARRAY_SIZE(ast_mac1_resources),
++};
++#endif
++
++/*
++ * MAC1 always has MII MDC+MDIO pins to access PHY registers. We assume MAC1
++ * always has a PHY chip, if MAC1 is enabled.
++ * U-Boot can enable MAC2 MDC+MDIO pins for a 2nd PHY, or MAC2 might be
++ * disabled (only one port), or it's sideband-RMII which has no PHY chip.
++ *
++ * Return miiPhyId==0 if the MAC cannot be accessed.
++ * Return miiPhyId==1 if the MAC registers are OK but it cannot carry traffic.
++ * Return miiPhyId==2 if the MAC can send/receive but it has no PHY chip.
++ * Else return the PHY 22-bit vendor ID, 6-bit model and 4-bit revision.
++ */
++
++void __init ast_add_device_gmac(void)
++{
++
++ u8 phy_mode,phy_inter;
++ u32 isRevA0;
++ u32 rev_id;
++
++ rev_id = ast_scu_revision_id() & 0xff;
++
++
++ if (rev_id >= 0x08 && rev_id <= 0x0f) {
++ // AST2100 FPGA board: up to 10 means rev.A0, 11 means rev.A1
++ isRevA0 = (rev_id < 11);
++ } else {
++ // Real silicon: rev.A0 has 0x00 in bits[7:0]. rev A2 = 0x02 in bits[7:0]
++ isRevA0 = 0; //((regVal & 0x00ff) == 0x00);
++// out->isRevA2 = 1; //((regVal & 0x00ff) == 0x02);
++ }
++
++ ast_eth0_data.DF_support = !isRevA0;
++
++ ast_scu_init_eth(0);
++ ast_scu_multi_func_eth(0);
++
++
++ /*
++ * D[15:11] in 0x1E6E2040 is NCSI scratch from U-Boot. D[15:14] = MAC1, D[13:12] = MAC2
++ * The meanings of the 2 bits are:
++ * 00(0): Dedicated PHY
++ * 01(1): ASPEED's EVA + INTEL's NC-SI PHY chip EVA
++ * 10(2): ASPEED's MAC is connected to NC-SI PHY chip directly
++ * 11: Reserved
++ */
++
++ phy_mode = ast_scu_get_phy_config(0);
++ switch(phy_mode) {
++ case 0:
++ ast_eth0_data.INTEL_NCSI_EVA_support = 0;
++ ast_eth0_data.NCSI_support = 0;
++ break;
++ case 1:
++ ast_eth0_data.NCSI_support = 1;
++ break;
++ case 2:
++ ast_eth0_data.INTEL_NCSI_EVA_support = 1;
++ break;
++
++ }
++
++ phy_inter = ast_scu_get_phy_interface(0);
++
++ // We assume the Clock Stop register does not disable the MAC1 or MAC2 clock
++ // unless Reset Control also holds the MAC in reset.
++
++
++ platform_device_register(&ast_eth0_device);
++
++#ifdef AST_MAC1_BASE
++ ast_scu_init_eth(1);
++ ast_scu_multi_func_eth(1);
++
++ ast_eth1_data.DF_support = !isRevA0;
++
++ phy_mode = ast_scu_get_phy_config(1);
++ switch(phy_mode) {
++ case 0:
++ ast_eth1_data.INTEL_NCSI_EVA_support = 0;
++ ast_eth1_data.NCSI_support = 0;
++ break;
++ case 1:
++ ast_eth1_data.NCSI_support = 1;
++ break;
++ case 2:
++ ast_eth1_data.INTEL_NCSI_EVA_support = 1;
++ break;
++
++ }
++ phy_inter = ast_scu_get_phy_interface(1);
++
++ platform_device_register(&ast_eth1_device);
++
++#endif
++
++}
++#else
++void __init ast_add_device_gmac(void) {}
++#endif
++
+diff --git a/arch/arm/plat-aspeed/dev-fb.c b/arch/arm/plat-aspeed/dev-fb.c
+new file mode 100644
+index 0000000..3673160
+--- /dev/null
++++ b/arch/arm/plat-aspeed/dev-fb.c
+@@ -0,0 +1,80 @@
++/********************************************************************************
++* File Name : linux/arch/arm/plat-aspeed/dev-fb.c
++* Author : Ryan Chen
++* Description : ASPEED Frambuffer Driver
++*
++* Copyright (C) ASPEED Tech. Inc.
++* This program is free software; you can redistribute it and/or modify
++* it under the terms of the GNU General Public License as published by the Free Software Foundation;
++* either version 2 of the License, or (at your option) any later version.
++*
++* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
++* without even the implied warranty of MERCHANTABILITY or
++* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
++*
++* You should have received a copy of the GNU General Public License
++* along with this program; if not, write to the Free Software
++* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++
++* History :
++* 1. 2012/12/15 Ryan Chen initial
++*
++********************************************************************************/
++#include <linux/kernel.h>
++#include <linux/platform_device.h>
++
++#include <mach/irqs.h>
++#include <mach/platform.h>
++
++#include <plat/devs.h>
++#include <plat/ast-scu.h>
++
++#include <mach/ast_lcd.h>
++
++/* --------------------------------------------------------------------
++ * ASPEED FB
++ * -------------------------------------------------------------------- */
++
++#if defined(CONFIG_FB_AST) || defined(CONFIG_FB_AST_MODULE)
++static struct ast_fb_plat_data fb_plat_data = {
++ .get_clk = ast_get_d2_pll_clk,
++};
++
++
++static struct resource ast_fb_resources[] = {
++ [0] = {
++ .start = AST_GRAPHIC_BASE,
++ .end = AST_GRAPHIC_BASE + SZ_1K - 1,
++ .flags = IORESOURCE_MEM,
++ },
++ [1] = {
++ .start = IRQ_CRT,
++ .end = IRQ_CRT,
++ .flags = IORESOURCE_IRQ,
++ },
++};
++
++static u64 ast_device_fb_dmamask = 0xffffffffUL;
++struct platform_device ast_fb_device = {
++ .name = "ast-fb",
++ .id = 0,
++ .dev = {
++ .dma_mask = &ast_device_fb_dmamask,
++ .coherent_dma_mask = 0xffffffffUL,
++ .platform_data= &fb_plat_data,
++ },
++ .resource = ast_fb_resources,
++ .num_resources = ARRAY_SIZE(ast_fb_resources),
++};
++
++void __init ast_add_device_fb(void)
++{
++ ast_scu_multi_func_crt();
++
++ ast_scu_init_crt();
++
++ platform_device_register(&ast_fb_device);
++}
++#else
++void __init ast_add_device_fb(void) {}
++#endif
+diff --git a/arch/arm/plat-aspeed/dev-gpio.c b/arch/arm/plat-aspeed/dev-gpio.c
+new file mode 100644
+index 0000000..356fd53
+--- /dev/null
++++ b/arch/arm/plat-aspeed/dev-gpio.c
+@@ -0,0 +1,68 @@
++/********************************************************************************
++* File Name : linux/arch/arm/plat-aspeed/dev-rtc.c
++* Author : Ryan chen
++* Description : Socle Real Time Clock Device (RTC)
++*
++* Copyright (C) Socle Tech. Corp.
++* This program is free software; you can redistribute it and/or modify
++* it under the terms of the GNU General Public License as published by the Free Software Foundation;
++* either version 2 of the License, or (at your option) any later version.
++*
++* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
++* without even the implied warranty of MERCHANTABILITY or
++* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
++*
++* You should have received a copy of the GNU General Public License
++* along with this program; if not, write to the Free Software
++* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++
++* History :
++* 1. 2010/09/15 ryan chen create this file
++*
++********************************************************************************/
++
++#include <linux/kernel.h>
++#include <linux/string.h>
++#include <linux/platform_device.h>
++
++#include <mach/irqs.h>
++#include <mach/platform.h>
++#include <plat/regs-gpio.h>
++
++#include <plat/devs.h>
++
++/* --------------------------------------------------------------------
++ * ASPEED GPIO
++ * -------------------------------------------------------------------- */
++
++#if defined(CONFIG_GPIO_AST) || defined(CONFIG_GPIO_AST_MODULE)
++static struct resource ast_gpio_resource[] = {
++ [0] = {
++ .start = AST_GPIO_BASE,
++ .end = AST_GPIO_BASE + SZ_4K - 1,
++ .flags = IORESOURCE_MEM,
++ },
++ [1] = {
++ .start = IRQ_GPIO,
++ .end = IRQ_GPIO,
++ .flags = IORESOURCE_IRQ,
++ },
++};
++
++static struct platform_device ast_device_gpio = {
++ .name = "ast-gpio",
++ .id = 0,
++ .num_resources = ARRAY_SIZE(ast_gpio_resource),
++ .resource = ast_gpio_resource,
++};
++
++extern void __init
++ast_add_device_gpio(void)
++{
++ platform_device_register(&ast_device_gpio);
++}
++
++#else
++extern void __init ast_add_device_gpio(void) {}
++#endif
++
+diff --git a/arch/arm/plat-aspeed/dev-i2c.c b/arch/arm/plat-aspeed/dev-i2c.c
+new file mode 100644
+index 0000000..47cd152
+--- /dev/null
++++ b/arch/arm/plat-aspeed/dev-i2c.c
+@@ -0,0 +1,669 @@
++/********************************************************************************
++* File Name : linux/arch/arm/plat-aspeed/dev-i2c.c
++* Author : Ryan chen
++* Description : ASPEED I2C Device
++*
++* Copyright (C) ASPEED Technology Inc.
++* This program is free software; you can redistribute it and/or modify
++* it under the terms of the GNU General Public License as published by the Free Software Foundation;
++* either version 2 of the License, or (at your option) any later version.
++*
++* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
++* without even the implied warranty of MERCHANTABILITY or
++* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
++*
++* You should have received a copy of the GNU General Public License
++* along with this program; if not, write to the Free Software
++* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++
++* History :
++* 1. 2012/07/30 ryan chen create this file
++*
++********************************************************************************/
++
++#include <linux/kernel.h>
++#include <linux/string.h>
++#include <linux/platform_device.h>
++#include <linux/i2c.h>
++#include <asm/io.h>
++#include <mach/irqs.h>
++#include <mach/platform.h>
++#include <plat/ast_i2c.h>
++#include <plat/devs.h>
++#include <plat/regs-iic.h>
++#include <plat/ast-scu.h>
++
++/* --------------------------------------------------------------------
++ * I2C
++ * -------------------------------------------------------------------- */
++#ifdef AST_I2C_DEBUG
++#define I2CDBUG(fmt, args...) printk("%s() " fmt, __FUNCTION__, ## args)
++#else
++#define I2CDBUG(fmt, args...)
++#endif
++
++#if defined(CONFIG_I2C_AST) || defined(CONFIG_I2C_AST_MODULE)
++
++#if defined (CONFIG_ARCH_AST2400)
++#define I2C_PAGE_SIZE 8
++struct buf_page page_info[I2C_PAGE_SIZE] =
++{
++ [0] = {
++ .flag = 0,
++ .page_no = 0,
++ .page_size = 256,
++ .page_addr_point = 0,
++ },
++ [1] = {
++ .flag = 0,
++ .page_no = 1,
++ .page_size = 256,
++ .page_addr_point = 0,
++ },
++ [2] = {
++ .flag = 0,
++ .page_no = 2,
++ .page_size = 256,
++ .page_addr_point = 0,
++ },
++ [3] = {
++ .flag = 0,
++ .page_no = 3,
++ .page_size = 256,
++ .page_addr_point = 0,
++ },
++ [4] = {
++ .flag = 0,
++ .page_no = 4,
++ .page_size = 256,
++ .page_addr_point = 0,
++ },
++ [5] = {
++ .flag = 0,
++ .page_no = 5,
++ .page_size = 256,
++ .page_addr_point = 0,
++ },
++ [6] = {
++ .flag = 0,
++ .page_no = 6,
++ .page_size = 256,
++ .page_addr_point = 0,
++ },
++ [7] = {
++ .flag = 0,
++ .page_no = 7,
++ .page_size = 256,
++ .page_addr_point = 0,
++ },
++};
++
++static void pool_buff_page_init(u32 buf_pool_addr)
++{
++ u32 offset;
++ int i ,j;
++
++ for(i=0;i<I2C_PAGE_SIZE;i++) {
++ offset = 0;
++ for(j=0;j<i;j++)
++ offset += page_info[i].page_size;
++
++ page_info[i].page_addr = buf_pool_addr + offset;
++// I2CDBUG( "page[%d],addr :%x \n", i, page_info[i].page_addr);
++ }
++
++}
++
++static u8 request_pool_buff_page(struct buf_page **req_page)
++{
++ int i;
++ //TODO
++ spinlock_t lock;
++ spin_lock(&lock);
++ for(i=0;i<I2C_PAGE_SIZE;i++) {
++ if(page_info[i].flag ==0) {
++ page_info[i].flag = 1;
++ *req_page = &page_info[i];
++// I2CDBUG( "request page addr %x \n", page_info[i].page_addr);
++ break;
++ }
++ }
++ spin_unlock(&lock);
++ return 0;
++}
++
++static void free_pool_buff_page(struct buf_page *req_page)
++{
++ req_page->flag = 0;
++// I2CDBUG( "free page addr %x \n", req_page->page_addr);
++ req_page = NULL;
++}
++
++#elif defined (CONFIG_ARCH_AST2300)
++#define I2C_PAGE_SIZE 5
++
++struct buf_page page_info[I2C_PAGE_SIZE] =
++{
++ [0] = {
++ .flag = 0,
++ .page_size = 128,
++ },
++ [1] = {
++ .flag = 0,
++ .page_size = 32,
++ },
++ [2] = {
++ .flag = 0,
++ .page_size = 32,
++ },
++ [3] = {
++ .flag = 0,
++ .page_size = 32,
++ },
++ [4] = {
++ .flag = 0,
++ .page_size = 32,
++ },
++};
++
++static void pool_buff_page_init(u32 buf_pool_addr)
++{
++
++ u32 offset;
++ int i ,j;
++
++ for(i=0;i<I2C_PAGE_SIZE;i++) {
++ offset = 0;
++ for(j=0;j<i;j++)
++ offset += page_info[i].page_size;
++
++ page_info[i].page_addr = buf_pool_addr + offset;
++ page_info[i].page_addr_point = page_info[i].page_addr/4;
++// printk("page[%d],addr :%x , point : %d\n", i, page_info[i].page_addr, page_info[i].page_addr_point);
++ }
++}
++
++static u8 request_pool_buff_page(struct buf_page **req_page)
++{
++ int i;
++ //TODO
++ spinlock_t lock;
++ spin_lock(&lock);
++ for(i=0;i<I2C_PAGE_SIZE;i++) {
++ if(page_info[i].flag ==0) {
++ page_info[i].flag = 1;
++ *req_page = &page_info[i];
++ spin_unlock(&lock);
++ return 1;
++ }
++ }
++ spin_unlock(&lock);
++ return 0;
++
++}
++
++//TODO check free ?
++static void free_pool_buff_page(struct buf_page *req_page)
++{
++ req_page->flag = 0;
++ req_page = NULL;
++}
++
++#else
++//DO nothing
++static void pool_buff_page_init(void) {}
++static u8 request_pool_buff_page(struct buf_page **req_page) {return 0;}
++static void free_pool_buff_page(struct buf_page *req_page) {}
++#endif
++
++static struct ast_i2c_driver_data ast_i2c_data = {
++ .bus_clk = 100000, //bus clock 100KHz
++ .master_dma = BUFF_MODE,
++ .slave_dma = BYTE_MODE,
++ .request_pool_buff_page = request_pool_buff_page,
++ .free_pool_buff_page = free_pool_buff_page,
++#ifdef CONFIG_AST_I2C_SLAVE_MODE
++ .slave_xfer = i2c_slave_xfer,
++ .slave_init = i2c_slave_init,
++#endif
++ .get_i2c_clock = ast_get_pclk,
++};
++
++static u64 ast_i2c_dma_mask = 0xffffffffUL;
++static struct resource ast_i2c_dev1_resources[] = {
++ [0] = {
++ .start = AST_I2C_BASE + AST_I2C_DEVICE1,
++ .end = AST_I2C_BASE + AST_I2C_DEVICE1 + 4*SZ_16 - 1,
++ .flags = IORESOURCE_MEM,
++ },
++ [1] = {
++ .start = IRQ_I2C,
++ .end = IRQ_I2C,
++ .flags = IORESOURCE_IRQ,
++ },
++};
++
++struct platform_device ast_i2c_dev1_device = {
++ .name = "ast-i2c",
++ .id = 0,
++ .dev = {
++ .dma_mask = &ast_i2c_dma_mask,
++ .coherent_dma_mask = 0xffffffff,
++ .platform_data = &ast_i2c_data,
++ },
++ .resource = ast_i2c_dev1_resources,
++ .num_resources = ARRAY_SIZE(ast_i2c_dev1_resources),
++};
++
++static struct resource ast_i2c_dev2_resources[] = {
++ [0] = {
++ .start = AST_I2C_BASE + AST_I2C_DEVICE2,
++ .end = AST_I2C_BASE + AST_I2C_DEVICE2 + 4*SZ_16 - 1,
++ .flags = IORESOURCE_MEM,
++ },
++ [1] = {
++ .start = IRQ_I2C,
++ .end = IRQ_I2C,
++ .flags = IORESOURCE_IRQ,
++ },
++};
++
++struct platform_device ast_i2c_dev2_device = {
++ .name = "ast-i2c",
++ .id = 1,
++ .dev = {
++ .dma_mask = &ast_i2c_dma_mask,
++ .coherent_dma_mask = 0xffffffff,
++ .platform_data = &ast_i2c_data,
++ },
++ .resource = ast_i2c_dev2_resources,
++ .num_resources = ARRAY_SIZE(ast_i2c_dev2_resources),
++};
++
++static struct resource ast_i2c_dev3_resources[] = {
++ [0] = {
++ .start = AST_I2C_BASE + AST_I2C_DEVICE3,
++ .end = AST_I2C_BASE + AST_I2C_DEVICE3 + 4*SZ_16 - 1,
++ .flags = IORESOURCE_MEM,
++ },
++ [1] = {
++ .start = IRQ_I2C,
++ .end = IRQ_I2C,
++ .flags = IORESOURCE_IRQ,
++ },
++};
++
++struct platform_device ast_i2c_dev3_device = {
++ .name = "ast-i2c",
++ .id = 2,
++ .dev = {
++ .dma_mask = &ast_i2c_dma_mask,
++ .coherent_dma_mask = 0xffffffff,
++ .platform_data = &ast_i2c_data,
++ },
++ .resource = ast_i2c_dev3_resources,
++ .num_resources = ARRAY_SIZE(ast_i2c_dev3_resources),
++};
++
++static struct resource ast_i2c_dev4_resources[] = {
++ [0] = {
++ .start = AST_I2C_BASE + AST_I2C_DEVICE4,
++ .end = AST_I2C_BASE + AST_I2C_DEVICE4 + 4*SZ_16 - 1,
++ .flags = IORESOURCE_MEM,
++ },
++ [1] = {
++ .start = IRQ_I2C,
++ .end = IRQ_I2C,
++ .flags = IORESOURCE_IRQ,
++ },
++};
++
++struct platform_device ast_i2c_dev4_device = {
++ .name = "ast-i2c",
++ .id = 3,
++ .dev = {
++ .dma_mask = &ast_i2c_dma_mask,
++ .coherent_dma_mask = 0xffffffff,
++ .platform_data = &ast_i2c_data,
++ },
++ .resource = ast_i2c_dev4_resources,
++ .num_resources = ARRAY_SIZE(ast_i2c_dev4_resources),
++};
++
++static struct resource ast_i2c_dev5_resources[] = {
++ [0] = {
++ .start = AST_I2C_BASE + AST_I2C_DEVICE5,
++ .end = AST_I2C_BASE + AST_I2C_DEVICE5 + 4*SZ_16 - 1,
++ .flags = IORESOURCE_MEM,
++ },
++ [1] = {
++ .start = IRQ_I2C,
++ .end = IRQ_I2C,
++ .flags = IORESOURCE_IRQ,
++ },
++};
++
++struct platform_device ast_i2c_dev5_device = {
++ .name = "ast-i2c",
++ .id = 4,
++ .dev = {
++ .dma_mask = &ast_i2c_dma_mask,
++ .coherent_dma_mask = 0xffffffff,
++ .platform_data = &ast_i2c_data,
++ },
++ .resource = ast_i2c_dev5_resources,
++ .num_resources = ARRAY_SIZE(ast_i2c_dev5_resources),
++};
++
++static struct resource ast_i2c_dev6_resources[] = {
++ [0] = {
++ .start = AST_I2C_BASE + AST_I2C_DEVICE6,
++ .end = AST_I2C_BASE + AST_I2C_DEVICE6 + 4*SZ_16 - 1,
++ .flags = IORESOURCE_MEM,
++ },
++ [1] = {
++ .start = IRQ_I2C,
++ .end = IRQ_I2C,
++ .flags = IORESOURCE_IRQ,
++ },
++};
++
++struct platform_device ast_i2c_dev6_device = {
++ .name = "ast-i2c",
++ .id = 5,
++ .dev = {
++ .dma_mask = &ast_i2c_dma_mask,
++ .coherent_dma_mask = 0xffffffff,
++ .platform_data = &ast_i2c_data,
++ },
++ .resource = ast_i2c_dev6_resources,
++ .num_resources = ARRAY_SIZE(ast_i2c_dev6_resources),
++};
++
++static struct resource ast_i2c_dev7_resources[] = {
++ [0] = {
++ .start = AST_I2C_BASE + AST_I2C_DEVICE7,
++ .end = AST_I2C_BASE + AST_I2C_DEVICE7 + 4*SZ_16 - 1,
++ .flags = IORESOURCE_MEM,
++ },
++ [1] = {
++ .start = IRQ_I2C,
++ .end = IRQ_I2C,
++ .flags = IORESOURCE_IRQ,
++ },
++};
++
++struct platform_device ast_i2c_dev7_device = {
++ .name = "ast-i2c",
++ .id = 6,
++ .dev = {
++ .dma_mask = &ast_i2c_dma_mask,
++ .coherent_dma_mask = 0xffffffff,
++ .platform_data = &ast_i2c_data,
++ },
++ .resource = ast_i2c_dev7_resources,
++ .num_resources = ARRAY_SIZE(ast_i2c_dev7_resources),
++};
++
++static struct resource ast_i2c_dev8_resources[] = {
++ [0] = {
++ .start = AST_I2C_BASE + AST_I2C_DEVICE8,
++ .end = AST_I2C_BASE + AST_I2C_DEVICE8 + 4*SZ_16 - 1,
++ .flags = IORESOURCE_MEM,
++ },
++ [1] = {
++ .start = IRQ_I2C,
++ .end = IRQ_I2C,
++ .flags = IORESOURCE_IRQ,
++ },
++};
++
++struct platform_device ast_i2c_dev8_device = {
++ .name = "ast-i2c",
++ .id = 7,
++ .dev = {
++ .dma_mask = &ast_i2c_dma_mask,
++ .coherent_dma_mask = 0xffffffff,
++ .platform_data = &ast_i2c_data,
++ },
++ .resource = ast_i2c_dev8_resources,
++ .num_resources = ARRAY_SIZE(ast_i2c_dev8_resources),
++};
++
++static struct resource ast_i2c_dev9_resources[] = {
++ [0] = {
++ .start = AST_I2C_BASE + AST_I2C_DEVICE9,
++ .end = AST_I2C_BASE + AST_I2C_DEVICE9 + 4*SZ_16 - 1,
++ .flags = IORESOURCE_MEM,
++ },
++ [1] = {
++ .start = IRQ_I2C,
++ .end = IRQ_I2C,
++ .flags = IORESOURCE_IRQ,
++ },
++};
++
++struct platform_device ast_i2c_dev9_device = {
++ .name = "ast-i2c",
++ .id = 8,
++ .dev = {
++ .dma_mask = &ast_i2c_dma_mask,
++ .coherent_dma_mask = 0xffffffff,
++ .platform_data = &ast_i2c_data,
++ },
++ .resource = ast_i2c_dev9_resources,
++ .num_resources = ARRAY_SIZE(ast_i2c_dev9_resources),
++};
++
++#if defined(CONFIG_ARCH_AST2400)
++static struct resource ast_i2c_dev10_resources[] = {
++ [0] = {
++ .start = AST_I2C_BASE + AST_I2C_DEVICE10,
++ .end = AST_I2C_BASE + AST_I2C_DEVICE10 + 4*SZ_16 - 1,
++ .flags = IORESOURCE_MEM,
++ },
++ [1] = {
++ .start = IRQ_I2C,
++ .end = IRQ_I2C,
++ .flags = IORESOURCE_IRQ,
++ },
++};
++
++struct platform_device ast_i2c_dev10_device = {
++ .name = "ast-i2c",
++ .id = 9,
++ .dev = {
++ .dma_mask = &ast_i2c_dma_mask,
++ .coherent_dma_mask = 0xffffffff,
++ .platform_data = &ast_i2c_data,
++ },
++ .resource = ast_i2c_dev10_resources,
++ .num_resources = ARRAY_SIZE(ast_i2c_dev10_resources),
++};
++
++static struct resource ast_i2c_dev11_resources[] = {
++ [0] = {
++ .start = AST_I2C_BASE + AST_I2C_DEVICE11,
++ .end = AST_I2C_BASE + AST_I2C_DEVICE11 + 4*SZ_16 - 1,
++ .flags = IORESOURCE_MEM,
++ },
++ [1] = {
++ .start = IRQ_I2C,
++ .end = IRQ_I2C,
++ .flags = IORESOURCE_IRQ,
++ },
++};
++
++struct platform_device ast_i2c_dev11_device = {
++ .name = "ast-i2c",
++ .id = 10,
++ .dev = {
++ .dma_mask = &ast_i2c_dma_mask,
++ .coherent_dma_mask = 0xffffffff,
++ .platform_data = &ast_i2c_data,
++ },
++ .resource = ast_i2c_dev11_resources,
++ .num_resources = ARRAY_SIZE(ast_i2c_dev11_resources),
++};
++
++static struct resource ast_i2c_dev12_resources[] = {
++ [0] = {
++ .start = AST_I2C_BASE + AST_I2C_DEVICE12,
++ .end = AST_I2C_BASE + AST_I2C_DEVICE12 + 4*SZ_16 - 1,
++ .flags = IORESOURCE_MEM,
++ },
++ [1] = {
++ .start = IRQ_I2C,
++ .end = IRQ_I2C,
++ .flags = IORESOURCE_IRQ,
++ },
++};
++
++struct platform_device ast_i2c_dev12_device = {
++ .name = "ast-i2c",
++ .id = 11,
++ .dev = {
++ .dma_mask = &ast_i2c_dma_mask,
++ .coherent_dma_mask = 0xffffffff,
++ .platform_data = &ast_i2c_data,
++ },
++ .resource = ast_i2c_dev12_resources,
++ .num_resources = ARRAY_SIZE(ast_i2c_dev12_resources),
++};
++
++static struct resource ast_i2c_dev13_resources[] = {
++ [0] = {
++ .start = AST_I2C_BASE + AST_I2C_DEVICE13,
++ .end = AST_I2C_BASE + AST_I2C_DEVICE13 + 4*SZ_16 - 1,
++ .flags = IORESOURCE_MEM,
++ },
++ [1] = {
++ .start = IRQ_I2C,
++ .end = IRQ_I2C,
++ .flags = IORESOURCE_IRQ,
++ },
++};
++
++struct platform_device ast_i2c_dev13_device = {
++ .name = "ast-i2c",
++ .id = 12,
++ .dev = {
++ .dma_mask = &ast_i2c_dma_mask,
++ .coherent_dma_mask = 0xffffffff,
++ .platform_data = &ast_i2c_data,
++ },
++ .resource = ast_i2c_dev13_resources,
++ .num_resources = ARRAY_SIZE(ast_i2c_dev13_resources),
++};
++
++static struct resource ast_i2c_dev14_resources[] = {
++ [0] = {
++ .start = AST_I2C_BASE + AST_I2C_DEVICE14,
++ .end = AST_I2C_BASE + AST_I2C_DEVICE14 + 4*SZ_16 - 1,
++ .flags = IORESOURCE_MEM,
++ },
++ [1] = {
++ .start = IRQ_I2C,
++ .end = IRQ_I2C,
++ .flags = IORESOURCE_IRQ,
++ },
++};
++
++struct platform_device ast_i2c_dev14_device = {
++ .name = "ast-i2c",
++ .id = 13,
++ .dev = {
++ .dma_mask = &ast_i2c_dma_mask,
++ .coherent_dma_mask = 0xffffffff,
++ .platform_data = &ast_i2c_data,
++ },
++ .resource = ast_i2c_dev14_resources,
++ .num_resources = ARRAY_SIZE(ast_i2c_dev14_resources),
++};
++#endif
++
++/*--------- I2C Board devices ------------*/
++//ASPEED AST2300 EVB I2C Device
++#if defined(CONFIG_ARCH_AST2300) || defined(CONFIG_ARCH_AST2400)
++//Under I2C Dev 1
++static struct i2c_board_info __initdata ast_i2c_board_info_1[] = {
++ {
++ I2C_BOARD_INFO("cat9883", 0x4d),
++ }
++};
++
++//Under I2C Dev 4
++static struct i2c_board_info __initdata ast_i2c_board_info_4[] = {
++ {
++ I2C_BOARD_INFO("24c128", 0x50),
++
++
++ }
++};
++//Under I2C Dev 8
++static struct i2c_board_info __initdata ast_i2c_board_info_8[] = {
++ {
++ I2C_BOARD_INFO("lm75b", 0x4a),
++ }
++};
++
++#endif
++
++/*-------------------------------------*/
++void __init ast_add_device_i2c(void)
++{
++ //I2C Multi-Pin
++ ast_scu_multi_func_i2c();
++
++ //SCU I2C Reset
++ ast_scu_init_i2c();
++
++ ast_i2c_data.reg_gr = ioremap(AST_I2C_BASE, 4*SZ_16);
++ if (!ast_i2c_data.reg_gr) {
++ printk("ast_add_device_i2c ERROR \n");
++ return;
++ }
++
++#if defined (CONFIG_ARCH_AST2400)
++ ast_i2c_data.buf_pool= ioremap(AST_I2C_BASE+0x800, 2048);
++ if (!ast_i2c_data.buf_pool) {
++ printk("ast_add_device_i2c ERROR \n");
++ return;
++ }
++#else
++ ast_i2c_data.buf_pool = ioremap(AST_I2C_BASE+0x200, 256);
++ if (!ast_i2c_data.buf_pool) {
++ printk("ast_add_device_i2c ERROR \n");
++ return;
++ }
++#endif
++ //TODO
++ pool_buff_page_init(ast_i2c_data.buf_pool);
++ platform_device_register(&ast_i2c_dev1_device);
++ i2c_register_board_info(0, ast_i2c_board_info_1, ARRAY_SIZE(ast_i2c_board_info_1));
++ platform_device_register(&ast_i2c_dev2_device);
++ platform_device_register(&ast_i2c_dev3_device);
++ platform_device_register(&ast_i2c_dev4_device);
++ i2c_register_board_info(3, ast_i2c_board_info_4, ARRAY_SIZE(ast_i2c_board_info_4));
++ platform_device_register(&ast_i2c_dev5_device);
++ platform_device_register(&ast_i2c_dev6_device);
++ platform_device_register(&ast_i2c_dev7_device);
++ platform_device_register(&ast_i2c_dev8_device);
++ i2c_register_board_info(7, ast_i2c_board_info_8, ARRAY_SIZE(ast_i2c_board_info_8));
++ platform_device_register(&ast_i2c_dev9_device);
++
++#if defined(CONFIG_ARCH_AST2400)
++ platform_device_register(&ast_i2c_dev10_device);
++#if defined(CONFIG_MMC_AST)
++ //Due to share pin with SD
++#else
++ platform_device_register(&ast_i2c_dev11_device);
++ platform_device_register(&ast_i2c_dev12_device);
++ platform_device_register(&ast_i2c_dev13_device);
++ platform_device_register(&ast_i2c_dev14_device);
++#endif
++#endif
++}
++#else
++void __init ast_add_device_i2c(void) {}
++#endif
+diff --git a/arch/arm/plat-aspeed/dev-kcs.c b/arch/arm/plat-aspeed/dev-kcs.c
+new file mode 100644
+index 0000000..726dbf7
+--- /dev/null
++++ b/arch/arm/plat-aspeed/dev-kcs.c
+@@ -0,0 +1,129 @@
++/********************************************************************************
++* File Name : linux/arch/arm/plat-aspeed/dev-kcs.c
++* Author : Ryan chen
++* Description : ASPEED KCS
++*
++* Copyright (C) ASPEED Technology Inc.
++* This program is free software; you can redistribute it and/or modify
++* it under the terms of the GNU General Public License as published by the Free Software Foundation;
++* either version 2 of the License, or (at your option) any later version.
++*
++* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
++* without even the implied warranty of MERCHANTABILITY or
++* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
++*
++* You should have received a copy of the GNU General Public License
++* along with this program; if not, write to the Free Software
++* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++
++* History :
++* 1. 2012/11/29 ryan chen create this file
++*
++********************************************************************************/
++
++#include <linux/kernel.h>
++#include <linux/string.h>
++#include <linux/platform_device.h>
++
++#include <mach/irqs.h>
++#include <mach/platform.h>
++#include <plat/devs.h>
++#include <plat/ast-scu.h>
++
++#include <linux/kernel.h>
++#include <linux/string.h>
++#include <linux/platform_device.h>
++
++#include <mach/irqs.h>
++#include <mach/platform.h>
++#include <plat/devs.h>
++#include <plat/ast-scu.h>
++
++/* --------------------------------------------------------------------
++ * KCS
++ * -------------------------------------------------------------------- */
++#if defined(CONFIG_AST_KCS) || defined(CONFIG_AST_KCS_MODULE)
++static u64 ast_kcs_dma_mask = 0xffffffffUL;
++
++static struct resource ast_kcs0_resource[] = {
++ [0] = {
++ .start = AST_LPC_BASE,
++ .end = AST_LPC_BASE + SZ_256,
++ .flags = IORESOURCE_MEM,
++ },
++ [1] = {
++ .start = IRQ_LPC,
++ .end = IRQ_LPC,
++ .flags = IORESOURCE_IRQ,
++ },
++};
++
++static struct platform_device ast_kcs0_device = {
++ .name = "ast-kcs",
++ .id = 0,
++ .dev = {
++ .dma_mask = &ast_kcs_dma_mask,
++ .coherent_dma_mask = 0xffffffff,
++ },
++ .resource = ast_kcs0_resource,
++ .num_resources = ARRAY_SIZE(ast_kcs0_resource),
++};
++
++static struct resource ast_kcs1_resource[] = {
++ [0] = {
++ .start = AST_LPC_BASE,
++ .end = AST_LPC_BASE + SZ_256,
++ .flags = IORESOURCE_MEM,
++ },
++ [1] = {
++ .start = IRQ_LPC,
++ .end = IRQ_LPC,
++ .flags = IORESOURCE_IRQ,
++ },
++};
++
++static struct platform_device ast_kcs1_device = {
++ .name = "ast-kcs",
++ .id = 1,
++ .dev = {
++ .dma_mask = &ast_kcs_dma_mask,
++ .coherent_dma_mask = 0xffffffff,
++ },
++ .resource = ast_kcs1_resource,
++ .num_resources = ARRAY_SIZE(ast_kcs1_resource),
++};
++
++static struct resource ast_kcs2_resource[] = {
++ [0] = {
++ .start = AST_LPC_BASE,
++ .end = AST_LPC_BASE + SZ_256,
++ .flags = IORESOURCE_MEM,
++ },
++ [1] = {
++ .start = IRQ_LPC,
++ .end = IRQ_LPC,
++ .flags = IORESOURCE_IRQ,
++ },
++};
++
++static struct platform_device ast_kcs2_device = {
++ .name = "ast-kcs",
++ .id = 2,
++ .dev = {
++ .dma_mask = &ast_kcs_dma_mask,
++ .coherent_dma_mask = 0xffffffff,
++ },
++ .resource = ast_kcs2_resource,
++ .num_resources = ARRAY_SIZE(ast_kcs2_resource),
++};
++
++void __init ast_add_device_kcs(void)
++{
++// platform_device_register(&ast_kcs0_device);
++// platform_device_register(&ast_kcs1_device);
++ platform_device_register(&ast_kcs2_device);
++}
++#else
++void __init ast_add_device_kcs(void) {}
++#endif
++
+diff --git a/arch/arm/plat-aspeed/dev-lpc.c b/arch/arm/plat-aspeed/dev-lpc.c
+new file mode 100644
+index 0000000..50eb4e6
+--- /dev/null
++++ b/arch/arm/plat-aspeed/dev-lpc.c
+@@ -0,0 +1,105 @@
++/********************************************************************************
++* File Name : linux/arch/arm/plat-aspeed/dev-lpc.c
++* Author : Ryan chen
++* Description : ASPEED LPC Controller
++*
++* Copyright (C) ASPEED Technology Inc.
++* This program is free software; you can redistribute it and/or modify
++* it under the terms of the GNU General Public License as published by the Free Software Foundation;
++* either version 2 of the License, or (at your option) any later version.
++*
++* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
++* without even the implied warranty of MERCHANTABILITY or
++* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
++*
++* You should have received a copy of the GNU General Public License
++* along with this program; if not, write to the Free Software
++* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++
++* History :
++* 1. 2012/11/29 ryan chen create this file
++*
++********************************************************************************/
++
++#include <linux/kernel.h>
++#include <linux/string.h>
++#include <linux/platform_device.h>
++
++#include <mach/irqs.h>
++#include <mach/platform.h>
++#include <plat/devs.h>
++#include <plat/ast-scu.h>
++
++
++
++#include <linux/kernel.h>
++#include <linux/string.h>
++#include <linux/platform_device.h>
++
++#include <mach/irqs.h>
++#include <mach/platform.h>
++#include <plat/devs.h>
++#include <plat/ast-scu.h>
++
++
++/* --------------------------------------------------------------------
++ * LPC
++ * -------------------------------------------------------------------- */
++#if defined(CONFIG_LPC) || defined(CONFIG_LPC_MODULE)
++static struct resource ast_lpc_resource[] = {
++ [0] = {
++ .start = AST_LPC_BASE,
++ .end = AST_LPC_BASE + SZ_4K,
++ .flags = IORESOURCE_MEM,
++ },
++ [1] = {
++ .start = IRQ_LPC,
++ .end = IRQ_LPC,
++ .flags = IORESOURCE_IRQ,
++ },
++};
++
++static u64 ast_lpc_dma_mask = 0xffffffffUL;
++
++static struct platform_device ast_lpc_device = {
++ .name = "ast_lpc",
++ .id = 0,
++ .dev = {
++ .dma_mask = &ast_lpc_dma_mask,
++ .coherent_dma_mask = 0xffffffff,
++ },
++ .resource = ast_lpc_resource,
++ .num_resources = ARRAY_SIZE(ast_lpc_resource),
++};
++
++static struct resource ast_lpc_plus_resource[] = {
++ [0] = {
++ .start = AST_LPC_PLUS_BASE,
++ .end = AST_LPC_PLUS_BASE + SZ_4K,
++ .flags = IORESOURCE_MEM,
++ },
++};
++
++static struct platform_device ast_lpc_plus_device = {
++ .name = "ast_lpc_plus",
++ .id = 1,
++ .dev = {
++ .dma_mask = &ast_lpc_dma_mask,
++ .coherent_dma_mask = 0xffffffff,
++ },
++ .resource = ast_lpc_plus_resource,
++ .num_resources = ARRAY_SIZE(ast_lpc_plus_resource),
++};
++
++void __init ast_add_device_lpc(void)
++{
++// it should enable at u-boot
++// ast_scu_init_lpc();
++
++ platform_device_register(&ast_lpc_device);
++ platform_device_register(&ast_lpc_plus_device);
++}
++#else
++void __init ast_add_device_lpc(void) {}
++#endif
++
+diff --git a/arch/arm/plat-aspeed/dev-mbx.c b/arch/arm/plat-aspeed/dev-mbx.c
+new file mode 100644
+index 0000000..75baf87
+--- /dev/null
++++ b/arch/arm/plat-aspeed/dev-mbx.c
+@@ -0,0 +1,79 @@
++/********************************************************************************
++* File Name : linux/arch/arm/plat-aspeed/dev-mbx.c
++* Author : Ryan chen
++* Description : ASPEED MailBox Controller
++*
++* Copyright (C) ASPEED Technology Inc.
++* This program is free software; you can redistribute it and/or modify
++* it under the terms of the GNU General Public License as published by the Free Software Foundation;
++* either version 2 of the License, or (at your option) any later version.
++*
++* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
++* without even the implied warranty of MERCHANTABILITY or
++* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
++*
++* You should have received a copy of the GNU General Public License
++* along with this program; if not, write to the Free Software
++* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++
++* History :
++* 1. 2012/11/29 ryan chen create this file
++*
++********************************************************************************/
++
++#include <linux/kernel.h>
++#include <linux/string.h>
++#include <linux/platform_device.h>
++
++#include <mach/irqs.h>
++#include <mach/platform.h>
++#include <plat/devs.h>
++#include <plat/ast-scu.h>
++
++#include <linux/kernel.h>
++#include <linux/string.h>
++#include <linux/platform_device.h>
++
++#include <mach/irqs.h>
++#include <mach/platform.h>
++#include <plat/devs.h>
++#include <plat/ast-scu.h>
++
++/* --------------------------------------------------------------------
++ * MailBox
++ * -------------------------------------------------------------------- */
++#if defined(CONFIG_AST_MBX) || defined(CONFIG_AST_MBX_MODULE)
++static struct resource ast_mbx_resource[] = {
++ [0] = {
++ .start = AST_MBX_BASE,
++ .end = AST_MBX_BASE + SZ_256,
++ .flags = IORESOURCE_MEM,
++ },
++ [1] = {
++ .start = IRQ_MAILBOX,
++ .end = IRQ_MAILBOX,
++ .flags = IORESOURCE_IRQ,
++ },
++};
++
++static u64 ast_mbx_dma_mask = 0xffffffffUL;
++
++static struct platform_device ast_mbx_device = {
++ .name = "ast-mailbox",
++ .id = 0,
++ .dev = {
++ .dma_mask = &ast_mbx_dma_mask,
++ .coherent_dma_mask = 0xffffffff,
++ },
++ .resource = ast_mbx_resource,
++ .num_resources = ARRAY_SIZE(ast_mbx_resource),
++};
++
++void __init ast_add_device_mailbox(void)
++{
++ platform_device_register(&ast_mbx_device);
++}
++#else
++void __init ast_add_device_mailbox(void) {}
++#endif
++
+diff --git a/arch/arm/plat-aspeed/dev-nand.c b/arch/arm/plat-aspeed/dev-nand.c
+new file mode 100644
+index 0000000..f11ff31
+--- /dev/null
++++ b/arch/arm/plat-aspeed/dev-nand.c
+@@ -0,0 +1,331 @@
++/********************************************************************************
++* File Name : linux/arch/arm/plat-aspeed/dev-nand.c
++* Author : Ryan chen
++* Description : ASPEED NAND Device
++*
++* Copyright (C) ASPEED Technology Inc.
++* This program is free software; you can redistribute it and/or modify
++* it under the terms of the GNU General Public License as published by the Free Software Foundation;
++* either version 2 of the License, or (at your option) any later version.
++*
++* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
++* without even the implied warranty of MERCHANTABILITY or
++* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
++*
++* You should have received a copy of the GNU General Public License
++* along with this program; if not, write to the Free Software
++* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++
++* History :
++* 1. 2012/10/15 ryan chen create this file
++*
++********************************************************************************/
++
++#include <linux/kernel.h>
++#include <linux/string.h>
++#include <linux/platform_device.h>
++#include <linux/mtd/mtd.h>
++#include <linux/mtd/partitions.h>
++#include <asm/mach/flash.h>
++
++#include <mach/irqs.h>
++#include <mach/platform.h>
++#include <plat/devs.h>
++#include <plat/regs-fmc.h>
++#include <asm/io.h>
++
++#include <linux/mtd/nand.h>
++
++#include <plat/ast-scu.h>
++#include <linux/mtd/mtd.h>
++
++
++
++/* --------------------------------------------------------------------
++ * NAND Flash
++ * -------------------------------------------------------------------- */
++
++#if defined(CONFIG_MTD_NAND_AST) || defined(CONFIG_MTD_NAND_AST_MODULE)
++static void __iomem *fmc_regs;
++
++/* returns 0 if the nand is busy, returns 1 if the nand is ready */
++static int
++ast_nand_dev_ready(struct mtd_info *mtd)
++{
++ int status;
++ status = (readl(fmc_regs + FMC_MISC_CTRL1) & READ_BUSY_PIN_STS) >> 3;
++ return status;
++}
++
++/* We use 2 256bytes as ECC's data length in sample code */
++static void
++ast_enable_hwecc(struct mtd_info *mtd, int cmd)
++{
++ writel(NAND_ECC_DATA_BLK_256 | NAND_ECC_ENABLE , fmc_regs + FMC_NAND_ECC);
++
++ writel(NAND_ECC_RESET , fmc_regs + FMC_NAND_ECC);
++
++ writel(NAND_ECC_DATA_BLK_256 | NAND_ECC_ENABLE , fmc_regs + FMC_NAND_ECC);
++}
++
++static int
++ast_calculate_ecc(struct mtd_info *mtd, const u_char *dat, u_char *ecc_code)
++{
++ uint32_t ecc_1, ecc_2, ecc_3;
++
++ ecc_1 = readl(fmc_regs + FMC_NAND_ECC_GEN1);
++ ecc_2 = readl(fmc_regs + FMC_NAND_ECC_GEN2);
++ ecc_3 = readl(fmc_regs + FMC_NAND_ECC_GEN3);
++
++ ecc_code[0] = ecc_1;
++ ecc_code[1] = ecc_1 >> 8;
++ ecc_code[2] = ecc_1 >> 16;
++ ecc_code[3] = ecc_1 >> 24;
++ ecc_code[4] = ecc_2;
++ ecc_code[5] = (((ecc_2 >> 8) & 0x0F) | 0xF0); //Becase flash's data value will be 0xff after flash is erased. The 256bytes mode will use 44bits to do ECC, the software needs to add 0xF0 for the last 4 bits.
++
++ return 0;
++}
++
++static int
++ast_nand_correct_data(struct mtd_info *mtd, u_char *dat,
++ u_char *read_ecc, u_char *calc_ecc)
++{
++ unsigned int dw_read_data[3], dw_calc_data[3];
++ unsigned int data1_check_status, data2_check_status;
++ unsigned int i, ecc_position, ecc_bit;
++
++ for (i = 0; i < 3; i++) {
++ dw_read_data[i] = 0;
++ dw_calc_data[i] = 0;
++ }
++ memcpy (dw_read_data, read_ecc, 6);
++ memcpy (dw_calc_data, calc_ecc, 6);
++ for (i = 0; i < 2; i++) {
++ writel(dw_read_data[i], fmc_regs + FMC_NAND_ECC_CK1 + (i*4));
++ writel(dw_calc_data[i], fmc_regs + FMC_NAND_ECC_GEN1 + (i*4));
++ }
++
++ data1_check_status = readl(fmc_regs + FMC_NAND_ECC_CK_R1) & 0xffff;
++ data2_check_status = (readl(fmc_regs + FMC_NAND_ECC_CK_R1) & 0xffff0000) >> 16;
++
++ if ((data1_check_status & 0x1000) && (data2_check_status & 0x1000)) {
++ return 0;
++ }
++
++ if ((data1_check_status & 0x8000) || (data2_check_status & 0x8000)) {
++ printk(KERN_ERR "uncorrectable error : ");
++ return -1;
++ }
++
++ if ((data1_check_status & 0x4000) || (data2_check_status & 0x4000)) {
++ printk ("error in ecc data\n");
++ return 1; /* error in ecc data; no action needed */
++ }
++
++//Correctable
++ if (data1_check_status & 0x2000) {
++ printk ("correctable in data area 1\n");
++ ecc_position = (data1_check_status & 0xff8) >> 3;
++ ecc_bit = (data1_check_status & 0x07);
++ dat[ecc_position] ^= (1 << ecc_bit);
++ }
++ if (data2_check_status & 0x2000) {
++ printk ("correctable in data area 2\n");
++ ecc_position = (data2_check_status & 0xff8) >> 3;
++ ecc_bit = (data2_check_status & 0x07);
++ dat[128 + ecc_position] ^= (1 << ecc_bit);
++ }
++
++ return 1;
++}
++
++/*---------------------------------------------------------
++ * AST2300 1 NAND * 128MB
++ *--------------------------------------------------------*/
++
++static struct mtd_partition ast_nand_partition_info[] = {
++ [0] = {
++ .name = "ASPEED NAND Flash 0",
++ .offset = 0,
++ .size = SZ_64M,
++ },
++ [1] = {
++ .name = "ASPEED NAND Flash 1",
++ .offset = MTDPART_OFS_APPEND,
++ .size = MTDPART_SIZ_FULL
++ },
++};
++
++static const char *ast_nand_part_probes[] = { "cmdlinepart", NULL };
++
++struct platform_nand_data ast_nand_platdata = {
++ .chip = {
++ .nr_chips = 1,
++ .chip_offset = 0,
++ .nr_partitions = ARRAY_SIZE(ast_nand_partition_info),
++ .partitions = ast_nand_partition_info,
++ /* 50 us command delay time */
++ .chip_delay = 50,
++ .options = NAND_NO_AUTOINCR,
++ .part_probe_types = ast_nand_part_probes,
++ },
++ .ctrl = {
++ .hwcontrol = ast_enable_hwecc,
++ .dev_ready = ast_nand_dev_ready,
++ .select_chip = 0,
++ .calculate = ast_calculate_ecc,
++ .correct = ast_nand_correct_data,
++ },
++};
++
++#if defined(CONFIG_AST_CS0_NAND)
++static struct resource ast_nand_resource0[] = {
++ {
++ .start = AST_CS0_DEF_BASE,
++ .end = AST_CS0_DEF_BASE + 0x10000,
++ .flags = IORESOURCE_MEM,
++ },
++};
++
++static struct platform_device ast_nand_device0 = {
++ .name = "ast-nand",
++ .id = 0,
++ .dev = {
++ .platform_data = &ast_nand_platdata,
++ },
++ .num_resources = ARRAY_SIZE(ast_nand_resource0),
++ .resource = ast_nand_resource0,
++};
++#endif
++
++#if defined(CONFIG_AST_CS1_NAND)
++static struct resource ast_nand_resource1[] = {
++ {
++ .start = AST_CS1_DEF_BASE,
++ .end = AST_CS1_DEF_BASE + 0x10000,
++ .flags = IORESOURCE_MEM,
++ },
++};
++
++static struct platform_device ast_nand_device1 = {
++ .name = "ast-nand",
++ .id = 1,
++ .dev = {
++ .platform_data = &ast_nand_platdata,
++ },
++ .num_resources = ARRAY_SIZE(ast_nand_resource1),
++ .resource = ast_nand_resource1,
++};
++#endif
++
++#if defined(CONFIG_AST_CS2_NAND)
++static struct resource ast_nand_resource2[] = {
++ {
++ .start = AST_CS2_DEF_BASE,
++ .end = AST_CS2_DEF_BASE + 0x10000,
++ .flags = IORESOURCE_MEM,
++ },
++};
++
++static struct platform_device ast_nand_device2 = {
++ .name = "ast-nand",
++ .id = 2,
++ .dev = {
++ .platform_data = &ast_nand_platdata,
++ },
++ .num_resources = ARRAY_SIZE(ast_nand_resource2),
++ .resource = ast_nand_resource2,
++};
++#endif
++
++#if defined(CONFIG_AST_CS3_NAND)
++static struct resource ast_nand_resource3[] = {
++ {
++ .start = AST_CS3_DEF_BASE,
++ .end = AST_CS3_DEF_BASE + 0x10000,
++ .flags = IORESOURCE_MEM,
++ },
++};
++
++static struct platform_device ast_nand_device3 = {
++ .name = "ast-nand",
++ .id = 3,
++ .dev = {
++ .platform_data = &ast_nand_platdata,
++ },
++ .num_resources = ARRAY_SIZE(ast_nand_resource3),
++ .resource = ast_nand_resource3,
++};
++#endif
++
++#if defined(CONFIG_AST_CS4_NAND)
++static struct resource ast_nand_resource4[] = {
++ {
++ .start = AST_CS4_DEF_BASE,
++ .end = AST_CS4_DEF_BASE + 0x10000,
++ .flags = IORESOURCE_MEM,
++ },
++};
++
++static struct platform_device ast_nand_device4 = {
++ .name = "ast-nand",
++ .id = 4,
++ .dev = {
++ .platform_data = &ast_nand_platdata,
++ },
++ .num_resources = ARRAY_SIZE(ast_nand_resource4),
++ .resource = ast_nand_resource4,
++};
++#endif
++
++/*-------------------------------------*/
++void __init ast_add_device_nand(void)
++{
++ u32 tmp;
++ fmc_regs = ioremap(AST_FMC_BASE, 4*SZ_16);
++
++ ast_scu_multi_func_nand();
++ writel(0x31 , fmc_regs + FMC_MISC_CTRL1);
++
++#if defined(CONFIG_AST_CS0_NAND)
++ platform_device_register(&ast_nand_device0);
++ tmp = (readl(fmc_regs) | FMC_SET_WRITE_CS(0)) & FMC_MASK_TYPE_CS(0);
++ writel( tmp | FMC_SET_TYPE_NAND_CS(0), fmc_regs);
++ writel(0x9 , fmc_regs + FMC_CE0_CTRL);
++#endif
++
++#if defined(CONFIG_AST_CS1_NAND)
++ ast_scu_multi_func_romcs(1);
++ tmp = (readl(fmc_regs) | FMC_SET_WRITE_CS(1)) & FMC_MASK_TYPE_CS(1);
++ writel( tmp | FMC_SET_TYPE_NAND_CS(1), fmc_regs);
++ writel(0x9 , fmc_regs + FMC_CE1_CTRL);
++ platform_device_register(&ast_nand_device1);
++#endif
++#if defined(CONFIG_AST_CS2_NAND)
++ ast_scu_multi_func_romcs(2);
++ tmp = (readl(fmc_regs) | FMC_SET_WRITE_CS(2)) & FMC_MASK_TYPE_CS(2);
++ writel( tmp | FMC_SET_TYPE_NAND_CS(2), fmc_regs);
++ writel(0x9 , fmc_regs + FMC_CE2_CTRL);
++ platform_device_register(&ast_nand_device2);
++#endif
++#if defined(CONFIG_AST_CS3_NAND)
++ ast_scu_multi_func_romcs(3);
++ tmp = (readl(fmc_regs) | FMC_SET_WRITE_CS(3)) & FMC_MASK_TYPE_CS(3);
++ writel( tmp | FMC_SET_TYPE_NAND_CS(3), fmc_regs);
++ writel(0x9 , fmc_regs + FMC_CE3_CTRL);
++ platform_device_register(&ast_nand_device3);
++#endif
++#if defined(CONFIG_AST_CS4_NAND)
++ ast_scu_multi_func_romcs(4);
++ tmp = (readl(fmc_regs) | FMC_SET_WRITE_CS(4)) & FMC_MASK_TYPE_CS(4);
++ writel( tmp | FMC_SET_TYPE_NAND_CS(4), fmc_regs);
++ writel(0x9 , fmc_regs + FMC_CE4_CTRL);
++ platform_device_register(&ast_nand_device4);
++#endif
++ iounmap(fmc_regs);
++
++}
++#else
++void __init ast_add_device_nand(void) {}
++#endif
+diff --git a/arch/arm/plat-aspeed/dev-nor.c b/arch/arm/plat-aspeed/dev-nor.c
+new file mode 100644
+index 0000000..abf49c0
+--- /dev/null
++++ b/arch/arm/plat-aspeed/dev-nor.c
+@@ -0,0 +1,219 @@
++/********************************************************************************
++* File Name : linux/arch/arm/plat-aspeed/dev-nor.c
++* Author : Ryan chen
++* Description : ASPEED NOR Device
++*
++* Copyright (C) ASPEED Technology Inc.
++* This program is free software; you can redistribute it and/or modify
++* it under the terms of the GNU General Public License as published by the Free Software Foundation;
++* either version 2 of the License, or (at your option) any later version.
++*
++* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
++* without even the implied warranty of MERCHANTABILITY or
++* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
++*
++* You should have received a copy of the GNU General Public License
++* along with this program; if not, write to the Free Software
++* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++
++* History :
++* 1. 2012/08/01 ryan chen create this file
++*
++********************************************************************************/
++
++#include <linux/kernel.h>
++#include <linux/string.h>
++#include <linux/platform_device.h>
++#include <linux/mtd/mtd.h>
++#include <linux/mtd/partitions.h>
++#include <asm/mach/flash.h>
++
++#include <mach/irqs.h>
++#include <mach/platform.h>
++#include <plat/devs.h>
++#include <plat/regs-fmc.h>
++#include <asm/io.h>
++#include <plat/ast-scu.h>
++
++
++/* --------------------------------------------------------------------
++ * NOR Flash
++ * -------------------------------------------------------------------- */
++
++#if defined(CONFIG_MTD_AST) || defined(CONFIG_MTD_AST_MODULE)
++/*---------------------------------------------------------
++ * AST2300 1 NOR * 16MB
++ *--------------------------------------------------------*/
++static struct mtd_partition nor_partitions[] = {
++ /* bootloader (U-Boot, etc) in first sector */
++ {
++ .name = "u-boot",
++ .offset = 0,
++ .size = 0x80000,
++ .mask_flags = MTD_WRITEABLE, /* force read-only */
++ },
++ /* kernel */
++ {
++ .name = "kernel",
++ .offset = MTDPART_OFS_APPEND,
++ .size = 0x300000,
++ },
++ /* file system */
++ {
++ .name = "ramdisk",
++ .offset = MTDPART_OFS_APPEND,
++ .size = 0x500000,
++ },
++ {
++ .name = "data",
++ .offset = MTDPART_OFS_APPEND,
++ .size = MTDPART_SIZ_FULL,
++ }
++};
++
++static struct flash_platform_data ast_nor_data = {
++ .map_name = "cfi_probe",
++ .width = 2,
++ .parts = nor_partitions,
++ .nr_parts = ARRAY_SIZE(nor_partitions),
++};
++
++#if defined(CONFIG_AST_CS0_NOR)
++static struct resource ast_nor_resource0[] = {
++ {
++ .start = AST_CS0_DEF_BASE,
++ .end = AST_CS0_DEF_BASE + AST_NOR_SIZE- 1,
++ .flags = IORESOURCE_MEM,
++ },
++};
++
++static struct platform_device ast_nor_device0 = {
++ .name = "ast-nor",
++ .id = 0,
++ .dev = {
++ .platform_data = &ast_nor_data,
++ },
++ .num_resources = ARRAY_SIZE(ast_nor_resource0),
++ .resource = ast_nor_resource0,
++};
++#endif
++
++#if defined(CONFIG_AST_CS1_NOR)
++static struct resource ast_nor_resource1[] = {
++ {
++ .start = AST_CS1_DEF_BASE,
++ .end = AST_CS1_DEF_BASE + AST_NOR_SIZE- 1,
++ .flags = IORESOURCE_MEM,
++ },
++};
++
++static struct platform_device ast_nor_device1 = {
++ .name = "ast-nor",
++ .id = 1,
++ .dev = {
++ .platform_data = &ast_nor_data,
++ },
++ .num_resources = ARRAY_SIZE(ast_nor_resource1),
++ .resource = ast_nor_resource1,
++};
++#endif
++
++#if defined(CONFIG_AST_CS2_NOR)
++static struct resource ast_nor_resource2[] = {
++ {
++ .start = AST_CS2_DEF_BASE,
++ .end = AST_CS2_DEF_BASE + AST_NOR_SIZE- 1,
++ .flags = IORESOURCE_MEM,
++ },
++};
++
++static struct platform_device ast_nor_device2 = {
++ .name = "ast-nor",
++ .id = 2,
++ .dev = {
++ .platform_data = &ast_nor_data,
++ },
++ .num_resources = ARRAY_SIZE(ast_nor_resource2),
++ .resource = ast_nor_resource2,
++};
++#endif
++
++#if defined(CONFIG_AST_CS3_NOR)
++static struct resource ast_nor_resource3[] = {
++ {
++ .start = AST_CS3_DEF_BASE,
++ .end = AST_CS3_DEF_BASE + AST_NOR_SIZE- 1,
++ .flags = IORESOURCE_MEM,
++ },
++};
++
++static struct platform_device ast_nor_device3 = {
++ .name = "ast-nor",
++ .id = 3,
++ .dev = {
++ .platform_data = &ast_nor_data,
++ },
++ .num_resources = ARRAY_SIZE(ast_nor_resource3),
++ .resource = ast_nor_resource3,
++};
++#endif
++
++#if defined(CONFIG_AST_CS4_NOR)
++static struct resource ast_nor_resource4[] = {
++ {
++ .start = AST_CS4_DEF_BASE,
++ .end = AST_CS4_DEF_BASE + AST_NOR_SIZE- 1,
++ .flags = IORESOURCE_MEM,
++ },
++};
++
++static struct platform_device ast_nor_device4 = {
++ .name = "ast-nor",
++ .id = 4,
++ .dev = {
++ .platform_data = &ast_nor_data,
++ },
++ .num_resources = ARRAY_SIZE(ast_nor_resource4),
++ .resource = ast_nor_resource4,
++};
++#endif
++
++/*-------------------------------------*/
++void __init ast_add_device_flash(void)
++{
++ void __iomem *fmc_regs = ioremap(AST_FMC_BASE, 4*SZ_16);
++
++ ast_scu_multi_func_nor();
++
++#if defined(CONFIG_AST_CS0_NOR)
++ //Enable NOR ACK
++ ast_scu_multi_func_romcs(0);
++ platform_device_register(&ast_nor_device0);
++ writel((readl(fmc_regs) | FMC_SET_WRITE_CS(0)) & FMC_MASK_TYPE_CS(0), fmc_regs);
++#endif
++#if defined(CONFIG_AST_CS1_NOR)
++ ast_scu_multi_func_romcs(1);
++ writel((readl(fmc_regs) | FMC_SET_WRITE_CS(1)) & FMC_MASK_TYPE_CS(1), fmc_regs);
++ platform_device_register(&ast_nor_device1);
++#endif
++#if defined(CONFIG_AST_CS2_NOR)
++ ast_scu_multi_func_romcs(2);
++ writel((readl(fmc_regs) | FMC_SET_WRITE_CS(2)) & FMC_MASK_TYPE_CS(2), fmc_regs);
++ platform_device_register(&ast_nor_device2);
++#endif
++#if defined(CONFIG_AST_CS3_NOR)
++ ast_scu_multi_func_romcs(3);
++ writel((readl(fmc_regs) | FMC_SET_WRITE_CS(3)) & FMC_MASK_TYPE_CS(3), fmc_regs);
++ platform_device_register(&ast_nor_device3);
++#endif
++#if defined(CONFIG_AST_CS4_NOR)
++ ast_scu_multi_func_romcs(4);
++ writel((readl(fmc_regs) | FMC_SET_WRITE_CS(4)) & FMC_MASK_TYPE_CS(4), fmc_regs);
++ platform_device_register(&ast_nor_device4);
++#endif
++ iounmap(fmc_regs);
++
++}
++#else
++void __init ast_add_device_flash(void) {}
++#endif
+diff --git a/arch/arm/plat-aspeed/dev-peci.c b/arch/arm/plat-aspeed/dev-peci.c
+new file mode 100644
+index 0000000..28ad1a5
+--- /dev/null
++++ b/arch/arm/plat-aspeed/dev-peci.c
+@@ -0,0 +1,68 @@
++/********************************************************************************
++* File Name : linux/arch/arm/plat-aspeed/dev-peci.c
++* Author : Ryan chen
++* Description : ASPEED PECI Device
++*
++* Copyright (C) ASPEED Technology Inc.
++* This program is free software; you can redistribute it and/or modify
++* it under the terms of the GNU General Public License as published by the Free Software Foundation;
++* either version 2 of the License, or (at your option) any later version.
++*
++* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
++* without even the implied warranty of MERCHANTABILITY or
++* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
++*
++* You should have received a copy of the GNU General Public License
++* along with this program; if not, write to the Free Software
++* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++
++* History :
++* 1. 2012/08/06 ryan chen create this file
++*
++********************************************************************************/
++
++#include <linux/kernel.h>
++#include <linux/string.h>
++#include <linux/platform_device.h>
++
++#include <mach/irqs.h>
++#include <mach/platform.h>
++#include <plat/devs.h>
++#include <plat/ast-scu.h>
++
++
++/* --------------------------------------------------------------------
++ * PECI
++ * -------------------------------------------------------------------- */
++
++#if defined(CONFIG_AST_PECI) || defined(CONFIG_AST_PECI_MODULE)
++static struct resource ast_peci_resources[] = {
++ [0] = {
++ .start = AST_PECI_BASE,
++ .end = AST_PECI_BASE + SZ_4K - 1,
++ .flags = IORESOURCE_MEM,
++ },
++ [1] = {
++ .start = IRQ_PECI,
++ .end = IRQ_PECI,
++ .flags = IORESOURCE_IRQ,
++ },
++};
++
++struct platform_device ast_peci_device = {
++ .name = "ast_peci",
++ .id = 0,
++ .resource = ast_peci_resources,
++ .num_resources = ARRAY_SIZE(ast_peci_resources),
++};
++
++void __init ast_add_device_peci(void)
++{
++ //SCU PECI CTRL Reset
++ ast_scu_init_peci();
++
++ platform_device_register(&ast_peci_device);
++}
++#else
++void __init ast_add_device_peci(void) {}
++#endif
+diff --git a/arch/arm/plat-aspeed/dev-pwm-fan.c b/arch/arm/plat-aspeed/dev-pwm-fan.c
+new file mode 100644
+index 0000000..85570bb
+--- /dev/null
++++ b/arch/arm/plat-aspeed/dev-pwm-fan.c
+@@ -0,0 +1,80 @@
++/********************************************************************************
++* File Name : linux/arch/arm/plat-aspeed/dev-pwm-fan.c
++* Author : Ryan chen
++* Description : ASPEED PWM-FAN Device
++*
++* Copyright (C) ASPEED Technology Inc.
++* This program is free software; you can redistribute it and/or modify
++* it under the terms of the GNU General Public License as published by the Free Software Foundation;
++* either version 2 of the License, or (at your option) any later version.
++*
++* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
++* without even the implied warranty of MERCHANTABILITY or
++* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
++*
++* You should have received a copy of the GNU General Public License
++* along with this program; if not, write to the Free Software
++* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++
++* History :
++* 1. 2012/08/06 ryan chen create this file
++*
++********************************************************************************/
++
++#include <linux/kernel.h>
++#include <linux/string.h>
++#include <linux/platform_device.h>
++
++#include <mach/irqs.h>
++#include <mach/platform.h>
++#include <plat/devs.h>
++#include <plat/ast-scu.h>
++#include <mach/ast_pwm_techo.h>
++
++/* --------------------------------------------------------------------
++ * PWM-FAN
++ * -------------------------------------------------------------------- */
++
++#if defined(CONFIG_SENSORS_AST_PWM_FAN) || defined(CONFIG_SENSORS_AST_PWM_FAN_MODULE)
++static struct resource ast_pwm_fan_resources[] = {
++ [0] = {
++ .start = AST_PWM_BASE,
++ .end = AST_PWM_BASE + SZ_4K - 1,
++ .flags = IORESOURCE_MEM,
++ },
++ [1] = {
++ .start = IRQ_TACHO,
++ .end = IRQ_TACHO,
++ .flags = IORESOURCE_IRQ,
++ },
++};
++
++static struct ast_pwm_driver_data ast_pwm_data = {
++ .get_pwm_clock = ast_get_h_pll_clk,
++};
++
++struct platform_device ast_pwm_fan_device = {
++ .name = "ast_pwm_tacho",
++ .id = 0,
++ .dev = {
++ .platform_data = &ast_pwm_data,
++ },
++ .resource = ast_pwm_fan_resources,
++ .num_resources = ARRAY_SIZE(ast_pwm_fan_resources),
++};
++
++void __init ast_add_device_pwm_fan(void)
++{
++ //SCU Initial
++
++ //SCU Pin-MUX //PWM & TACHO
++ ast_scu_multi_func_pwm_tacho();
++
++ //SCU PWM CTRL Reset
++ ast_scu_init_pwm_tacho();
++
++ platform_device_register(&ast_pwm_fan_device);
++}
++#else
++void __init ast_add_device_pwm_fan(void) {}
++#endif
+diff --git a/arch/arm/plat-aspeed/dev-rtc.c b/arch/arm/plat-aspeed/dev-rtc.c
+new file mode 100644
+index 0000000..214aa68
+--- /dev/null
++++ b/arch/arm/plat-aspeed/dev-rtc.c
+@@ -0,0 +1,65 @@
++/********************************************************************************
++* File Name : linux/arch/arm/plat-aspeed/dev-wdt.c
++* Author : Ryan Chen
++* Description : AST WDT Device
++*
++* Copyright (C) ASPEED Technology Inc.
++* This program is free software; you can redistribute it and/or modify
++* it under the terms of the GNU General Public License as published by the Free Software Foundation;
++* either version 2 of the License, or (at your option) any later version.
++*
++* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
++* without even the implied warranty of MERCHANTABILITY or
++* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
++*
++* You should have received a copy of the GNU General Public License
++* along with this program; if not, write to the Free Software
++* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++
++* History :
++* 1. 2012/09/15 Ryan Chen initial
++*
++********************************************************************************/
++#include <linux/kernel.h>
++#include <linux/platform_device.h>
++
++#include <mach/irqs.h>
++#include <mach/platform.h>
++
++#include <plat/devs.h>
++
++
++/* --------------------------------------------------------------------
++ * Watchdog
++ * -------------------------------------------------------------------- */
++
++#if defined(CONFIG_RTC_DRV_AST) || defined(CONFIG_RTC_DRV_AST_MODULE)
++
++static struct resource ast_rtc_resource[] = {
++ [0] = {
++ .start = AST_RTC_BASE,
++ .end = AST_RTC_BASE + SZ_4K - 1,
++ .flags = IORESOURCE_MEM,
++ },
++ [1] = {
++ .start = IRQ_RTC,
++ .end = IRQ_RTC,
++ .flags = IORESOURCE_IRQ,
++ },
++
++};
++
++static struct platform_device ast_device_rtc = {
++ .name = "ast_rtc",
++ .id = -1,
++ .resource = ast_rtc_resource,
++ .num_resources = ARRAY_SIZE(ast_rtc_resource),
++};
++
++void __init ast_add_device_rtc(void)
++{
++ platform_device_register(&ast_device_rtc);
++}
++#else
++void __init ast_add_device_rtc(void) {}
++#endif
+diff --git a/arch/arm/plat-aspeed/dev-sdhci.c b/arch/arm/plat-aspeed/dev-sdhci.c
+new file mode 100644
+index 0000000..bcc8cce
+--- /dev/null
++++ b/arch/arm/plat-aspeed/dev-sdhci.c
+@@ -0,0 +1,110 @@
++/********************************************************************************
++* File Name : linux/arch/arm/plat-aspeed/dev-sdhc.c
++* Author : Ryan chen
++* Description : ASPEED SDHC Device
++*
++* Copyright (C) ASPEED Technology Inc.
++* This program is free software; you can redistribute it and/or modify
++* it under the terms of the GNU General Public License as published by the Free Software Foundation;
++* either version 2 of the License, or (at your option) any later version.
++*
++* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
++* without even the implied warranty of MERCHANTABILITY or
++* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
++*
++* You should have received a copy of the GNU General Public License
++* along with this program; if not, write to the Free Software
++* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++
++* History :
++* 1. 2012/07/30 ryan chen create this file
++*
++********************************************************************************/
++
++#include <linux/kernel.h>
++#include <linux/string.h>
++#include <linux/platform_device.h>
++
++#include <mach/irqs.h>
++#include <mach/platform.h>
++#include <plat/devs.h>
++#include <plat/ast_sdhci.h>
++#include <plat/ast-scu.h>
++
++
++/* --------------------------------------------------------------------
++ * SDHC
++ * -------------------------------------------------------------------- */
++#if defined(CONFIG_MMC_AST) || defined(CONFIG_MMC_AST_MODULE)
++static struct ast_sdhc_platform_data ast_sdhc_info = {
++ .sd_clock_src_get = ast_get_sd_clock_src,
++};
++
++static struct resource ast_sdhci0_resource[] = {
++ [0] = {
++ .start = AST_SDHC_BASE + 0x100,
++ .end = AST_SDHC_BASE + 0x100 + 0xFF,
++ .flags = IORESOURCE_MEM,
++ },
++ [1] = {
++ .start = IRQ_SDHC,
++ .end = IRQ_SDHC,
++ .flags = IORESOURCE_IRQ,
++ },
++};
++
++static struct resource ast_sdhci1_resource[] = {
++ [0] = {
++ .start = AST_SDHC_BASE + 0x200,
++ .end = AST_SDHC_BASE + 0x200 + 0xFF,
++ .flags = IORESOURCE_MEM,
++ },
++ [1] = {
++ .start = IRQ_SDHC,
++ .end = IRQ_SDHC,
++ .flags = IORESOURCE_IRQ,
++ },
++};
++
++static u64 ast_sdhc_dma_mask = 0xffffffffUL;
++
++static struct platform_device ast_sdhci_device0 = {
++ .name = "ast_sdhci",
++ .id = 0,
++ .dev = {
++ .dma_mask = &ast_sdhc_dma_mask,
++ .coherent_dma_mask = 0xffffffff,
++ .platform_data = &ast_sdhc_info,
++ },
++ .resource = ast_sdhci0_resource,
++ .num_resources = ARRAY_SIZE(ast_sdhci0_resource),
++};
++
++static struct platform_device ast_sdhci_device1 = {
++ .name = "ast_sdhci",
++ .id = 1,
++ .dev = {
++ .dma_mask = &ast_sdhc_dma_mask,
++ .coherent_dma_mask = 0xffffffff,
++ .platform_data = &ast_sdhc_info,
++ },
++ .resource = ast_sdhci1_resource,
++ .num_resources = ARRAY_SIZE(ast_sdhci1_resource),
++};
++
++void __init ast_add_device_sdhci(void)
++{
++ ast_scu_init_sdhci();
++ //multipin. Remind: AST2300FPGA only supports one port at a time
++
++ ast_scu_multi_func_sdhc_slot1(1);
++
++ platform_device_register(&ast_sdhci_device0);
++
++ ast_scu_multi_func_sdhc_slot2(1);
++
++ platform_device_register(&ast_sdhci_device1);
++}
++#else
++void __init ast_add_device_sdhci(void) {}
++#endif
+diff --git a/arch/arm/plat-aspeed/dev-sgpio.c b/arch/arm/plat-aspeed/dev-sgpio.c
+new file mode 100644
+index 0000000..c6ca2c4
+--- /dev/null
++++ b/arch/arm/plat-aspeed/dev-sgpio.c
+@@ -0,0 +1,68 @@
++/********************************************************************************
++* File Name : linux/arch/arm/plat-aspeed/dev-rtc.c
++* Author : Ryan chen
++* Description : Socle Real Time Clock Device (RTC)
++*
++* Copyright (C) Socle Tech. Corp.
++* This program is free software; you can redistribute it and/or modify
++* it under the terms of the GNU General Public License as published by the Free Software Foundation;
++* either version 2 of the License, or (at your option) any later version.
++*
++* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
++* without even the implied warranty of MERCHANTABILITY or
++* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
++*
++* You should have received a copy of the GNU General Public License
++* along with this program; if not, write to the Free Software
++* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++
++* History :
++* 1. 2010/09/15 ryan chen create this file
++*
++********************************************************************************/
++
++#include <linux/kernel.h>
++#include <linux/string.h>
++#include <linux/platform_device.h>
++
++#include <mach/irqs.h>
++#include <mach/platform.h>
++//#include <plat/regs-sgpio.h>
++
++#include <plat/devs.h>
++
++/* --------------------------------------------------------------------
++ * ASPEED SGPIO
++ * -------------------------------------------------------------------- */
++
++#if defined(CONFIG_SGPIO_AST) || defined(CONFIG_SGPIO_AST_MODULE)
++static struct resource ast_sgpio_resource[] = {
++ [0] = {
++ .start = AST_SGPIO_BASE,
++ .end = AST_SGPIO_BASE + SZ_4K - 1,
++ .flags = IORESOURCE_MEM,
++ },
++ [1] = {
++ .start = IRQ_SGPIO,
++ .end = IRQ_SGPIO,
++ .flags = IORESOURCE_IRQ,
++ },
++};
++
++static struct platform_device ast_device_sgpio = {
++ .name = "ast-sgpio",
++ .id = 0,
++ .num_resources = ARRAY_SIZE(ast_sgpio_resource),
++ .resource = ast_sgpio_resource,
++};
++
++extern void __init
++ast_add_device_sgpio(void)
++{
++ platform_device_register(&ast_device_sgpio);
++}
++
++#else
++extern void __init ast_add_device_sgpio(void) {}
++#endif
++
+diff --git a/arch/arm/plat-aspeed/dev-snoop.c b/arch/arm/plat-aspeed/dev-snoop.c
+new file mode 100644
+index 0000000..9e286bc
+--- /dev/null
++++ b/arch/arm/plat-aspeed/dev-snoop.c
+@@ -0,0 +1,94 @@
++/********************************************************************************
++* File Name : linux/arch/arm/plat-aspeed/dev-snoop.c
++* Author : Ryan chen
++* Description : ASPEED SNOOP Device
++*
++* Copyright (C) ASPEED Technology Inc.
++* This program is free software; you can redistribute it and/or modify
++* it under the terms of the GNU General Public License as published by the Free Software Foundation;
++* either version 2 of the License, or (at your option) any later version.
++*
++* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
++* without even the implied warranty of MERCHANTABILITY or
++* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
++*
++* You should have received a copy of the GNU General Public License
++* along with this program; if not, write to the Free Software
++* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++
++* History :
++* 1. 2012/11/29 ryan chen create this file
++*
++********************************************************************************/
++
++#include <linux/kernel.h>
++#include <linux/string.h>
++#include <linux/platform_device.h>
++
++#include <mach/irqs.h>
++#include <mach/platform.h>
++#include <plat/devs.h>
++#include <linux/kernel.h>
++#include <linux/string.h>
++#include <linux/platform_device.h>
++
++#include <mach/platform.h>
++#include <plat/devs.h>
++#include <plat/ast-snoop.h>
++
++/* --------------------------------------------------------------------
++ * AST SNOOP -- DMA or 80Port SNOOP
++ * -------------------------------------------------------------------- */
++#if defined(CONFIG_SNOOP_AST) || defined(CONFIG_SNOOP_AST_MODULE)
++static u64 ast_snoop_dma_mask = 0xffffffffUL;
++
++static struct ast_snoop_channel snoop_ch0 = {
++ .snoop_ch = 0,
++ .snoop_port = 0x80,
++};
++
++static struct ast_snoop_channel snoop_ch1 = {
++ .snoop_ch = 1,
++ .snoop_port = 0x81,
++};
++
++static struct ast_snoop snoop = {
++ .snoop_ch0 = &snoop_ch0,
++ .snoop_ch1 = &snoop_ch1,
++};
++
++static struct platform_device ast_snoop_device = {
++ .name = "ast_snoop",
++ .id = 0,
++ .dev = {
++ .dma_mask = &ast_snoop_dma_mask,
++ .coherent_dma_mask = 0xffffffff,
++ .platform_data = &snoop,
++ },
++};
++
++struct ast_snoop_dma_channel snoop_dma_ch0 = {
++ .snoop_ch = 0,
++ .snoop_port = 0x3f8,
++ .snoop_mask = 7,
++};
++
++static struct platform_device ast_snoop_dma_device = {
++ .name = "ast_snoop_dma",
++ .id = 0,
++ .dev = {
++ .dma_mask = &ast_snoop_dma_mask,
++ .coherent_dma_mask = 0xffffffff,
++ .platform_data = &snoop_dma_ch0,
++ },
++};
++
++void __init ast_add_device_snoop(void)
++{
++ platform_device_register(&ast_snoop_device);
++ platform_device_register(&ast_snoop_dma_device);
++}
++#else
++void __init ast_add_device_snoop(void) {}
++#endif
++
+diff --git a/arch/arm/plat-aspeed/dev-spi.c b/arch/arm/plat-aspeed/dev-spi.c
+new file mode 100644
+index 0000000..7ddd2e4
+--- /dev/null
++++ b/arch/arm/plat-aspeed/dev-spi.c
+@@ -0,0 +1,448 @@
++/********************************************************************************
++* File Name : linux/arch/arm/plat-aspeed/dev-spi.c
++* Author : Ryan chen
++* Description : ASPEED SPI device
++*
++* Copyright (C) ASPEED Technology Inc.
++* This program is free software; you can redistribute it and/or modify
++* it under the terms of the GNU General Public License as published by the Free Software Foundation;
++* either version 2 of the License, or (at your option) any later version.
++*
++* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
++* without even the implied warranty of MERCHANTABILITY or
++* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
++*
++* You should have received a copy of the GNU General Public License
++* along with this program; if not, write to the Free Software
++* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++
++* History :
++* 1. 2012/08/01 ryan chen create this file
++*
++********************************************************************************/
++
++#include <linux/kernel.h>
++#include <linux/string.h>
++#include <linux/platform_device.h>
++#include <linux/mtd/mtd.h>
++#include <linux/mtd/partitions.h>
++#include <linux/spi/flash.h>
++
++#include <linux/spi/spi.h>
++
++
++#include <asm/io.h>
++#if defined(CONFIG_COLDFIRE)
++#include <asm/sizes.h>
++#include <asm/arch/ast_spi.h>
++#include <asm/arch/ast-scu.h>
++#include <asm/arch/irqs.h>
++#include <asm/arch/platform.h>
++#include <asm/arch/devs.h>
++#else
++#include <mach/irqs.h>
++#include <mach/platform.h>
++#include <plat/devs.h>
++#include <plat/regs-fmc.h>
++#include <plat/ast-scu.h>
++#include <mach/ast_spi.h>
++#endif
++
++/* --------------------------------------------------------------------
++ * SPI Ctrl, (AST SPI + FMC SPI)
++ * -------------------------------------------------------------------- */
++#if defined(CONFIG_SPI_FMC) || defined(CONFIG_SPI_FMC_MODULE) || defined(CONFIG_SPI_AST) || defined(CONFIG_SPI_AST_MODULE)
++static u32 ast_spi_calculate_divisor(u32 max_speed_hz)
++{
++ // [0] ->15 : HCLK , HCLK/16
++ u8 SPI_DIV[16] = {16, 7, 14, 6, 13, 5, 12, 4, 11, 3, 10, 2, 9, 1, 8, 0};
++ u32 i, hclk, spi_cdvr=0;
++
++ hclk = ast_get_h_pll_clk();
++ for(i=1;i<17;i++) {
++ if(max_speed_hz >= (hclk/i)) {
++ spi_cdvr = SPI_DIV[i-1];
++ break;
++ }
++ }
++
++// printk("hclk is %d, divisor is %d, target :%d , cal speed %d\n", hclk, spi_cdvr, spi->max_speed_hz, hclk/i);
++ return spi_cdvr;
++}
++#endif
++
++#if defined(CONFIG_SPI_FMC) || defined(CONFIG_SPI_FMC_MODULE)
++static struct ast_spi_driver_data fmc_spi_data = {
++ .get_div = ast_spi_calculate_divisor,
++ .num_chipselect = 1,
++};
++
++#if defined(CONFIG_AST_CS0_SPI)
++static struct resource ast_fmc_spi_resource0[] = {
++ {
++ .start = AST_FMC_BASE + 0x10,
++ .end = AST_FMC_BASE + 0x10 + SZ_16,
++ .flags = IORESOURCE_MEM,
++ },
++ {
++ .start = AST_CS0_DEF_BASE,
++ .end = AST_CS0_DEF_BASE + SZ_16,
++ .flags = IORESOURCE_IO,
++ },
++};
++static struct platform_device ast_fmc_spi_device0 = {
++ .name = "fmc-spi",
++ .id = 0,
++ .dev = {
++ .platform_data = &fmc_spi_data,
++ },
++ .num_resources = ARRAY_SIZE(ast_fmc_spi_resource0),
++ .resource = ast_fmc_spi_resource0,
++};
++#endif
++
++#if defined(CONFIG_AST_CS1_SPI)
++static struct resource ast_fmc_spi_resource1[] = {
++ {
++ .start = AST_FMC_BASE + 0x14,
++ .end = AST_FMC_BASE + 0x14 + SZ_16,
++ .flags = IORESOURCE_MEM,
++ },
++ {
++ .start = AST_CS1_DEF_BASE,
++ .end = AST_CS1_DEF_BASE + SZ_16,
++ .flags = IORESOURCE_IO,
++ },
++};
++static struct platform_device ast_fmc_spi_device1 = {
++ .name = "fmc-spi",
++ .id = 1,
++ .dev = {
++ .platform_data = &fmc_spi_data,
++ },
++ .num_resources = ARRAY_SIZE(ast_fmc_spi_resource1),
++ .resource = ast_fmc_spi_resource1,
++};
++#endif
++
++#if defined(CONFIG_AST_CS2_SPI)
++static struct resource ast_fmc_spi_resource2[] = {
++ {
++ .start = AST_FMC_BASE + 0x18,
++ .end = AST_FMC_BASE + 0x18 + SZ_16,
++ .flags = IORESOURCE_MEM,
++ },
++ {
++ .start = AST_CS2_DEF_BASE,
++ .end = AST_CS2_DEF_BASE + SZ_16,
++ .flags = IORESOURCE_IO,
++ },
++};
++
++static struct platform_device ast_fmc_spi_device2 = {
++ .name = "fmc-spi",
++ .id = 2,
++ .dev = {
++ .platform_data = &fmc_spi_data,
++ },
++ .num_resources = ARRAY_SIZE(ast_fmc_spi_resource2),
++ .resource = ast_fmc_spi_resource2,
++};
++#endif
++
++#if defined(CONFIG_AST_CS3_SPI)
++static struct resource ast_fmc_spi_resource3[] = {
++ {
++ .start = AST_FMC_BASE + 0x1c,
++ .end = AST_FMC_BASE + 0x1c + SZ_16,
++ .flags = IORESOURCE_MEM,
++ },
++ {
++ .start = AST_CS3_DEF_BASE,
++ .end = AST_CS3_DEF_BASE + SZ_16,
++ .flags = IORESOURCE_IO,
++ },
++};
++
++static struct platform_device ast_fmc_spi_device3 = {
++ .name = "fmc-spi",
++ .id = 3,
++ .dev = {
++ .platform_data = &fmc_spi_data,
++ },
++ .num_resources = ARRAY_SIZE(ast_fmc_spi_resource3),
++ .resource = ast_fmc_spi_resource3,
++};
++#endif
++
++#if defined(CONFIG_AST_CS4_SPI)
++static struct resource ast_fmc_spi_resource4[] = {
++ {
++ .start = AST_FMC_BASE + 0x20,
++ .end = AST_FMC_BASE + 0x20 + SZ_16,
++ .flags = IORESOURCE_MEM,
++ },
++ {
++ .start = AST_CS4_DEF_BASE,
++ .end = AST_CS4_DEF_BASE + SZ_16,
++ .flags = IORESOURCE_IO,
++ },
++};
++
++static struct platform_device ast_fmc_spi_device4 = {
++ .name = "fmc-spi",
++ .id = 4,
++ .dev = {
++ .platform_data = &fmc_spi_data,
++ },
++ .num_resources = ARRAY_SIZE(ast_fmc_spi_resource4),
++ .resource = ast_fmc_spi_resource4,
++};
++#endif
++
++#endif //CONFIG_SPI_FMC
++
++#if defined(CONFIG_SPI_AST) || defined(CONFIG_SPI_AST_MODULE)
++static struct ast_spi_driver_data ast_spi0_data = {
++ .get_div = ast_spi_calculate_divisor,
++ .num_chipselect = 1,
++};
++
++static struct resource ast_spi_resource0[] = {
++ {
++ .start = AST_SPI0_BASE,
++ .end = AST_SPI0_BASE + SZ_16,
++ .flags = IORESOURCE_MEM,
++ },
++ {
++ .start = AST_SPI0_MEM + 0x04,
++ .end = AST_SPI0_MEM + SZ_16,
++ .flags = IORESOURCE_IO,
++ },
++};
++
++static struct platform_device ast_spi_device0 = {
++ .name = "ast-spi",
++#if defined(CONFIG_ARCH_AST1010)
++ .id = 0,
++#else
++ .id = 5,
++#endif
++ .dev = {
++ .platform_data = &ast_spi0_data,
++ },
++ .num_resources = ARRAY_SIZE(ast_spi_resource0),
++ .resource = ast_spi_resource0,
++};
++
++#if defined(AST_SPI1_BASE)
++static struct ast_spi_driver_data ast_spi1_data = {
++ .get_div = ast_spi_calculate_divisor,
++ .num_chipselect = 1,
++};
++
++static struct resource aspeed_spi1_resource[] = {
++ {
++ .start = AST_SPI1_BASE,
++ .end = AST_SPI1_BASE + SZ_16,
++ .flags = IORESOURCE_MEM,
++ },
++ {
++ .start = AST_SPI1_MEM,
++ .end = AST_SPI1_MEM + SZ_16,
++ .flags = IORESOURCE_IO,
++ },
++};
++
++static struct platform_device aspeed_spi_device1 = {
++ .name = "ast-spi",
++ .id = 1,
++ .dev = {
++ .platform_data = &ast_spi1_data,
++ },
++ .num_resources = ARRAY_SIZE(aspeed_spi1_resource),
++ .resource = aspeed_spi1_resource,
++};
++
++#endif
++
++#endif //CONFIG_SPI_AST
++
++#if defined(CONFIG_ARCH_AST1010)
++static struct mtd_partition ast_spi_flash_partitions[] = {
++ {
++ .name = "uboot",
++ .offset = 0,
++ .size = 0x00030000,
++ .mask_flags = MTD_WRITEABLE,
++ },
++ {
++ .name = "uboot-env",
++ .offset = MTDPART_OFS_APPEND,
++ .size = 0x00010000,
++// .mask_flags = MTD_WRITEABLE,
++ },
++ {
++ .name = "uCLinux",
++ .offset = MTDPART_OFS_APPEND,
++ .size = 0x003c0000,
++// .mask_flags = MTD_CAP_NORFLASH,
++ },
++ {
++ .name = "data",
++ .offset = MTDPART_OFS_APPEND,
++ .size = MTDPART_SIZ_FULL,
++// .mask_flags = MTD_CAP_NORFLASH,
++ }
++};
++#else
++static struct mtd_partition ast_spi_flash_partitions[] = {
++ {
++ .name = "u-boot",
++ .offset = 0,
++ .size = 0x80000,
++ .mask_flags = MTD_WRITEABLE,
++ }, {
++ .name = "kernel",
++ .offset = 0x80000,
++ .size = 0x200000,
++ }, {
++ .name = "rootfs",
++ .offset = 0x300000,
++ .size = 0x4F0000,
++ }, {
++ .name = "env",
++ .offset = 0x7f0000,
++ .size = 0x10000,
++ }, {
++ .name = "data0",
++ .offset = MTDPART_OFS_APPEND,
++ .size = MTDPART_SIZ_FULL,
++ },
++};
++#endif
++
++static struct flash_platform_data ast_spi_flash_data = {
++#if defined(CONFIG_ARCH_AST2400)
++ .type = "mx25l25635e", //AST2400 A1
++#elif defined(CONFIG_ARCH_AST1010)
++ .type = "mx25l6405d",
++#else
++ .type = "mx25l12805d", //old AST2300
++#endif
++ .nr_parts = ARRAY_SIZE(ast_spi_flash_partitions),
++ .parts = ast_spi_flash_partitions,
++};
++
++static struct spi_board_info ast_spi_devices[] = {
++ {
++ .modalias = "m25p80",
++ .platform_data = &ast_spi_flash_data,
++ .chip_select = 0, //.chip_select This tells your device driver which chipselect to use.
++ .max_speed_hz = 50 * 1000 * 1000,
++ .bus_num = 0, // This chooses if SPI0 or SPI1 of the SoC is used.
++ .mode = SPI_MODE_0,
++ },
++ {
++ .modalias = "spidev",
++ .chip_select = 0,
++ .max_speed_hz = 30 * 1000 * 1000,
++ .bus_num = 1,
++ .mode = SPI_MODE_0,
++ },
++};
++
++#if defined(AST_SPI1_BASE)
++static struct mtd_partition ast_spi_flash1_partitions[] = {
++ {
++ .name = "bios",
++ .offset = 0,
++ .size = MTDPART_SIZ_FULL,
++ }
++};
++
++static struct flash_platform_data ast_spi_flash1_data = {
++ .type = "mx25l6405d",
++// .type = "w25q64",
++ .nr_parts = ARRAY_SIZE(ast_spi_flash1_partitions),
++ .parts = ast_spi_flash1_partitions,
++};
++
++
++static struct spi_board_info ast_spi1_devices[] = {
++ {
++ .modalias = "m25p80",
++ .platform_data = &ast_spi_flash1_data,
++ .chip_select = 0, //.chip_select This tells your device driver which chipselect to use.
++ .max_speed_hz = 100 * 1000 * 1000,
++ .bus_num = 1, // This chooses if SPI0 or SPI1 of the SoC is used.
++ .mode = SPI_MODE_0,
++ },
++};
++#endif
++
++#if defined(CONFIG_SPI_FMC) || defined(CONFIG_SPI_FMC_MODULE) || defined(CONFIG_SPI_AST) || defined(CONFIG_SPI_AST_MODULE)
++
++/*-------------------------------------*/
++void __init ast_add_device_spi(void)
++{
++#if defined(CONFIG_SPI_FMC) || defined(CONFIG_SPI_FMC_MODULE)
++ void __iomem *fmc_regs = ioremap(AST_FMC_BASE, 4*SZ_16);
++ u32 tmp = 0;
++
++#if defined(CONFIG_AST_CS0_SPI)
++ platform_device_register(&ast_fmc_spi_device0);
++ tmp = (readl(fmc_regs) | FMC_SET_WRITE_CS(0)) & FMC_MASK_TYPE_CS(0);
++ writel( tmp | FMC_SET_TYPE_SPI_CS(0), fmc_regs);
++#endif
++
++#if defined(CONFIG_AST_CS1_SPI)
++ ast_scu_multi_func_romcs(1);
++ tmp = (readl(fmc_regs) | FMC_SET_WRITE_CS(1)) & FMC_MASK_TYPE_CS(1);
++ writel( tmp | FMC_SET_TYPE_SPI_CS(1), fmc_regs);
++ platform_device_register(&ast_fmc_spi_device1);
++#endif
++
++#if defined(CONFIG_AST_CS2_SPI)
++ ast_scu_multi_func_romcs(2);
++ tmp = (readl(fmc_regs) | FMC_SET_WRITE_CS(2)) & FMC_MASK_TYPE_CS(2);
++ writel( tmp | FMC_SET_TYPE_SPI_CS(2), fmc_regs);
++ platform_device_register(&ast_fmc_spi_device2);
++#endif
++#if defined(CONFIG_AST_CS3_SPI)
++ ast_scu_multi_func_romcs(3);
++ tmp = (readl(fmc_regs) | FMC_SET_WRITE_CS(3)) & FMC_MASK_TYPE_CS(3);
++ writel( tmp | FMC_SET_TYPE_SPI_CS(3), fmc_regs);
++ platform_device_register(&ast_fmc_spi_device3);
++#endif
++#if defined(CONFIG_AST_CS4_SPI)
++ ast_scu_multi_func_romcs(4);
++ tmp = (readl(fmc_regs) | FMC_SET_WRITE_CS(4)) & FMC_MASK_TYPE_CS(4);
++ writel( tmp | FMC_SET_TYPE_SPI_CS(4), fmc_regs);
++ platform_device_register(&ast_fmc_spi_device4);
++#endif
++
++ iounmap(fmc_regs);
++
++#endif
++
++#if defined(CONFIG_SPI_AST) || defined(CONFIG_SPI_AST_MODULE)
++ //pin switch by trap[13:12]
++ platform_device_register(&ast_spi_device0);
++#endif
++
++ spi_register_board_info(ast_spi_devices, ARRAY_SIZE(ast_spi_devices));
++
++#if defined(AST_SPI1_BASE)
++ //AST1010 SCU CONFIG TODO .......
++ writel(readl(AST_SCU_BASE + 0x70) | 0x10,AST_SCU_BASE + 0x70);
++ platform_device_register(&aspeed_spi_device1);
++ spi_register_board_info(ast_spi1_devices, ARRAY_SIZE(ast_spi1_devices));
++#endif
++
++}
++#else
++void __init ast_add_device_spi(void) {}
++#endif
++
++
+diff --git a/arch/arm/plat-aspeed/dev-uart.c b/arch/arm/plat-aspeed/dev-uart.c
+new file mode 100644
+index 0000000..592ef4f
+--- /dev/null
++++ b/arch/arm/plat-aspeed/dev-uart.c
+@@ -0,0 +1,144 @@
++/********************************************************************************
++* File Name : linux/arch/arm/plat-aspeed/dev-uart.c
++* Author : Ryan chen
++*
++* Copyright (C) 2012-2020 ASPEED Technology Inc.
++* This program is free software; you can redistribute it and/or modify
++* it under the terms of the GNU General Public License as published by the Free Software Foundation;
++* either version 2 of the License, or (at your option) any later version.
++*
++* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
++* without even the implied warranty of MERCHANTABILITY or
++* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
++*
++* You should have received a copy of the GNU General Public License
++* along with this program; if not, write to the Free Software
++* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++
++* History :
++* 1. 2012/09/15 ryan chen create this file
++*
++********************************************************************************/
++
++#include <linux/kernel.h>
++#include <linux/string.h>
++#include <linux/platform_device.h>
++#include <linux/serial.h>
++#include <linux/tty.h>
++#include <linux/serial_8250.h>
++
++#if defined(CONFIG_COLDFIRE)
++#include <asm/sizes.h>
++#include <asm/arch/devs.h>
++#include <asm/arch/platform.h>
++#include <asm/arch/irqs.h>
++#else
++#include <mach/irqs.h>
++#include <mach/platform.h>
++#include <mach/hardware.h>
++#include <plat/ast-scu.h>
++#include <plat/devs.h>
++#endif
++
++/* --------------------------------------------------------------------
++ * UART
++ * -------------------------------------------------------------------- */
++#ifdef CONFIG_SERIAL_8250
++static struct plat_serial8250_port ast_uart_data[] = {
++ {
++ .mapbase = AST_UART0_BASE,
++ .irq = IRQ_UART0,
++ .uartclk = (24*1000000L),
++ .regshift = 2,
++#if defined(CONFIG_COLDFIRE)
++ .iotype = UPIO_MEM32,
++#else
++ .iotype = UPIO_MEM,
++#endif
++ .flags = UPF_IOREMAP | UPF_BOOT_AUTOCONF | UPF_SKIP_TEST,
++ },
++#if defined(CONFIG_ARCH_AST1010)
++ {
++ .mapbase = AST_UART1_BASE,
++ .irq = IRQ_UART1,
++ .uartclk = (24*1000000L),
++ .regshift = 2,
++ .iotype = UPIO_MEM32,
++ .flags = UPF_IOREMAP | UPF_BOOT_AUTOCONF | UPF_SKIP_TEST,
++ },
++ {
++ .mapbase = AST_UART2_BASE,
++ .irq = IRQ_UART2,
++ .uartclk = (24*1000000L),
++ .regshift = 2,
++ .iotype = UPIO_MEM32,
++ .flags = UPF_IOREMAP | UPF_BOOT_AUTOCONF | UPF_SKIP_TEST,
++ },
++#else
++//BMC UART 1 ,2 default to LPC
++#ifdef CONFIG_ARCH_AST1070
++#ifdef AST_UART1_BASE
++ {
++ .mapbase = AST_UART1_BASE,
++ .irq = IRQ_UART1,
++ .uartclk = (24*1000000L),
++ .regshift = 2,
++ .iotype = UPIO_MEM,
++ .flags = UPF_IOREMAP | UPF_BOOT_AUTOCONF | UPF_SKIP_TEST,
++ },
++#endif
++#ifdef AST_UART2_BASE
++ {
++ .mapbase = AST_UART2_BASE,
++ .irq = IRQ_UART2,
++ .uartclk = (24*1000000L),
++ .regshift = 2,
++ .iotype = UPIO_MEM,
++ .flags = UPF_IOREMAP | UPF_BOOT_AUTOCONF | UPF_SKIP_TEST,
++ },
++#endif
++#endif
++#ifdef AST_UART3_BASE
++ {
++ .mapbase = AST_UART3_BASE,
++ .irq = IRQ_UART3,
++ .uartclk = (24*1000000L),
++ .regshift = 2,
++ .iotype = UPIO_MEM,
++ .flags = UPF_IOREMAP | UPF_BOOT_AUTOCONF | UPF_SKIP_TEST,
++ },
++#endif
++#ifdef AST_UART4_BASE
++ {
++ .mapbase = AST_UART4_BASE,
++ .irq = IRQ_UART4,
++ .uartclk = (24*1000000L),
++ .regshift = 2,
++ .iotype = UPIO_MEM,
++ .flags = UPF_IOREMAP | UPF_BOOT_AUTOCONF | UPF_SKIP_TEST,
++ },
++#endif
++#endif
++ { },
++};
++
++struct platform_device ast_uart_device = {
++ .name = "serial8250",
++ .id = PLAT8250_DEV_PLATFORM,
++ .dev = {
++ .platform_data = ast_uart_data,
++ },
++};
++
++void __init ast_add_device_uart(void)
++{
++#if defined(CONFIG_ARCH_AST1010)
++#else
++ ast_scu_multi_func_uart(3);
++ ast_scu_multi_func_uart(4);
++#endif
++ platform_device_register(&ast_uart_device);
++}
++#else
++void __init ast_add_device_uart(void) {}
++#endif
+diff --git a/arch/arm/plat-aspeed/dev-uhci.c b/arch/arm/plat-aspeed/dev-uhci.c
+new file mode 100644
+index 0000000..961ec9b
+--- /dev/null
++++ b/arch/arm/plat-aspeed/dev-uhci.c
+@@ -0,0 +1,82 @@
++/********************************************************************************
++* File Name : linux/arch/arm/plat-aspeed/dev-uhci.c
++* Author : Ryan chen
++* Description : ASPEED EHCI Device
++*
++* Copyright (C) ASPEED Technology Inc.
++* This program is free software; you can redistribute it and/or modify
++* it under the terms of the GNU General Public License as published by the Free Software Foundation;
++* either version 2 of the License, or (at your option) any later version.
++*
++* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
++* without even the implied warranty of MERCHANTABILITY or
++* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
++*
++* You should have received a copy of the GNU General Public License
++* along with this program; if not, write to the Free Software
++* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++
++* History :
++* 1. 2012/07/30 ryan chen create this file
++*
++********************************************************************************/
++
++#include <linux/kernel.h>
++#include <linux/string.h>
++#include <linux/platform_device.h>
++
++#include <mach/irqs.h>
++#include <mach/platform.h>
++#include <plat/devs.h>
++#include <plat/ast-scu.h>
++
++/* --------------------------------------------------------------------
++ * UHCI
++ * -------------------------------------------------------------------- */
++#if defined(CONFIG_AST_USB_UHCI_HCD) || defined(CONFIG_AST_USB_UHCI_HCD_MODULE)
++static struct resource ast_uchi_resource[] = {
++ [0] = {
++ .start = AST_UHCI_BASE,
++ .end = AST_UHCI_BASE + SZ_256,
++ .flags = IORESOURCE_MEM,
++ },
++ [1] = {
++ .start = IRQ_UHCI,
++ .end = IRQ_UHCI,
++ .flags = IORESOURCE_IRQ,
++ },
++};
++
++static u64 ast_uhci_dma_mask = 0xffffffffUL;
++
++static struct platform_device ast_uhci_device = {
++ .name = "ast_uhci",
++ .id = 0,
++ .dev = {
++ .dma_mask = &ast_uhci_dma_mask,
++ .coherent_dma_mask = 0xffffffff,
++ },
++ .resource = ast_uchi_resource,
++ .num_resources = ARRAY_SIZE(ast_uchi_resource),
++};
++
++void __init ast_add_device_uhci(void)
++{
++
++#if defined (CONFIG_AST_USB_UHCI_MULTIPORT_2)
++ ast_scu_multi_func_usb11_host_port2(1);
++#elif defined (CONFIG_AST_USB_UHCI_MULTIPORT_4)
++ ast_scu_multi_func_usb11_host_port2(1);
++ ast_scu_multi_func_usb11_host_port4(1);
++#else
++ ast_scu_multi_func_usb11_host_port2(0);
++ ast_scu_multi_func_usb11_host_port4(0);
++#endif
++
++ ast_scu_init_uhci();
++
++ platform_device_register(&ast_uhci_device);
++}
++#else
++void __init ast_add_device_uhci(void) {}
++#endif
+diff --git a/arch/arm/plat-aspeed/dev-video.c b/arch/arm/plat-aspeed/dev-video.c
+new file mode 100644
+index 0000000..3d66eff
+--- /dev/null
++++ b/arch/arm/plat-aspeed/dev-video.c
+@@ -0,0 +1,102 @@
++/********************************************************************************
++* File Name : linux/arch/arm/plat-aspeed/dev-video.c
++* Author : Ryan Chen
++* Description : ASPEED Video Driver
++*
++* Copyright (C) ASPEED Tech. Inc.
++* This program is free software; you can redistribute it and/or modify
++* it under the terms of the GNU General Public License as published by the Free Software Foundation;
++* either version 2 of the License, or (at your option) any later version.
++*
++* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
++* without even the implied warranty of MERCHANTABILITY or
++* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
++*
++* You should have received a copy of the GNU General Public License
++* along with this program; if not, write to the Free Software
++* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++
++* History :
++* 1. 2013/04/15 Ryan Chen initial
++*
++********************************************************************************/
++#include <linux/kernel.h>
++#include <linux/platform_device.h>
++
++#include <mach/irqs.h>
++#include <mach/platform.h>
++
++#include <plat/devs.h>
++#include <plat/ast-scu.h>
++#include <plat/ast-sdmc.h>
++
++#include <mach/ast_video.h>
++
++/* --------------------------------------------------------------------
++ * AST VIDEO
++ * -------------------------------------------------------------------- */
++#if defined(CONFIG_AST_VIDEO) || defined(CONFIG_AST_VIDEO_MODULE)
++
++#define ASR_VIDEO_MEM AST_DRAM_BASE + SZ_8M*10
++static u32 get_vga_mem_base(void)
++{
++ u32 vga_mem_size, mem_size;
++ mem_size = ast_sdmc_get_mem_size();
++ vga_mem_size = ast_scu_get_vga_memsize();
++ printk("VGA Info : MEM Size %d, VGA Mem Size %d \n",mem_size, vga_mem_size);
++ return (mem_size - vga_mem_size);
++}
++
++static struct ast_video_plat_data video_plat_data = {
++ .get_clk = ast_get_m_pll_clk,
++ .ctrl_reset = ast_scu_reset_video,
++ .vga_display = ast_scu_set_vga_display,
++ .get_vga_base = get_vga_mem_base,
++ .input_source = VIDEO_SOURCE_INTERNAL,
++ .mode = VIDEO_FRAME_MODE,
++ .rc4_enable = 0,
++ .compress = VIDEO_YUV444,
++ .scaling = 0,
++};
++
++
++static struct resource ast_video_resources[] = {
++ [0] = {
++ .start = AST_VIDEO_BASE,
++ .end = AST_VIDEO_BASE + SZ_1K*2 - 1,
++ .flags = IORESOURCE_MEM,
++ },
++ [1] = {
++ .start = IRQ_VIDEO,
++ .end = IRQ_VIDEO,
++ .flags = IORESOURCE_IRQ,
++ },
++ [2] = {
++ .start = ASR_VIDEO_MEM,
++ .end = ASR_VIDEO_MEM + SZ_32M,
++ .flags = IORESOURCE_DMA,
++ },
++};
++
++static u64 ast_device_video_dmamask = 0xffffffffUL;
++struct platform_device ast_video_device = {
++ .name = "ast-video",
++ .id = 0,
++ .dev = {
++ .dma_mask = &ast_device_video_dmamask,
++ .coherent_dma_mask = 0xffffffffUL,
++ .platform_data= &video_plat_data,
++ },
++ .resource = ast_video_resources,
++ .num_resources = ARRAY_SIZE(ast_video_resources),
++};
++
++void __init ast_add_device_video(void)
++{
++ ast_scu_init_video(0);
++ ast_scu_multi_func_video();
++ platform_device_register(&ast_video_device);
++}
++#else
++void __init ast_add_device_video(void) {}
++#endif
+diff --git a/arch/arm/plat-aspeed/dev-vuart.c b/arch/arm/plat-aspeed/dev-vuart.c
+new file mode 100644
+index 0000000..0e2ab8a
+--- /dev/null
++++ b/arch/arm/plat-aspeed/dev-vuart.c
+@@ -0,0 +1,100 @@
++/********************************************************************************
++* File Name : linux/arch/arm/plat-aspeed/dev-uart.c
++* Author : Ryan chen
++*
++* Copyright (C) 2012-2020 ASPEED Technology Inc.
++* This program is free software; you can redistribute it and/or modify
++* it under the terms of the GNU General Public License as published by the Free Software Foundation;
++* either version 2 of the License, or (at your option) any later version.
++*
++* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
++* without even the implied warranty of MERCHANTABILITY or
++* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
++*
++* You should have received a copy of the GNU General Public License
++* along with this program; if not, write to the Free Software
++* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++
++* History :
++* 1. 2012/09/15 ryan chen create this file
++*
++********************************************************************************/
++
++#include <linux/kernel.h>
++#include <linux/string.h>
++#include <linux/platform_device.h>
++#include <linux/serial.h>
++#include <linux/tty.h>
++#include <linux/serial_8250.h>
++
++#include <mach/irqs.h>
++#include <mach/platform.h>
++#include <mach/hardware.h>
++#include <asm/io.h>
++
++#include <plat/ast-scu.h>
++#include <plat/devs.h>
++
++#include <plat/regs-vuart.h>
++
++#define AST_COM_PORT PORT_3F8
++#define AST_SIRQ SIRQ4
++
++#define PORT_2F8 0x2f8
++#define PORT_3F8 0x3f8
++
++typedef enum SIO_serial_irq {
++ SIRQ0 = 0,
++ SIRQ1,
++ SIRQ2,
++ SIRQ3,
++ SIRQ4,
++ SIRQ5,
++ SIRQ6,
++ SIRQ7,
++ SIRQ8,
++ SIRQ9,
++};
++
++/* --------------------------------------------------------------------
++ * UART
++ * -------------------------------------------------------------------- */
++#if defined(CONFIG_SERIAL_8250) && defined(CONFIG_SERIAL_AST_VUART)
++static struct plat_serial8250_port ast_vuart_data[] = {
++ {
++ .mapbase = AST_VUART0_BASE,
++ .membase = (char*)(IO_ADDRESS(AST_VUART0_BASE)),
++ .irq = IRQ_LPC,
++ .uartclk = (24*1000000L),
++ .regshift = 2,
++ .iotype = UPIO_MEM,
++ .flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST | UPF_SHARE_IRQ,
++ },
++ { },
++};
++
++struct platform_device ast_vuart_device = {
++ .name = "serial8250",
++ .id = PLAT8250_DEV_PLATFORM1,
++ .dev = {
++ .platform_data = ast_vuart_data,
++ },
++};
++
++void __init ast_add_device_vuart(void)
++{
++ u32 vuart_base = ioremap(AST_VUART0_BASE, SZ_256);
++
++ writel(0x0, vuart_base + AST_VUART_CTRLA);
++ writel(SET_SIRQ_NUM(AST_SIRQ) |0x3, vuart_base + AST_VUART_CTRLB);
++ writel(AST_COM_PORT & 0xff, vuart_base + AST_VUART_ADDRL);
++ writel(AST_COM_PORT >> 8, vuart_base + AST_VUART_ADDRH);
++ writel(0x0, vuart_base + AST_VUART_CTRLF);
++ writel(VUART_ENABLE | VUART_SIRQ_POLARITY | VUART_DISABLE_H_TX_DISCARD, vuart_base + AST_VUART_CTRLA);
++
++ iounmap(vuart_base);
++ platform_device_register(&ast_vuart_device);
++}
++#else
++void __init ast_add_device_vuart(void) {}
++#endif
+diff --git a/arch/arm/plat-aspeed/dev-wdt.c b/arch/arm/plat-aspeed/dev-wdt.c
+new file mode 100644
+index 0000000..079d1a9
+--- /dev/null
++++ b/arch/arm/plat-aspeed/dev-wdt.c
+@@ -0,0 +1,76 @@
++/********************************************************************************
++* File Name : linux/arch/arm/plat-aspeed/dev-wdt.c
++* Author : Ryan Chen
++* Description : AST WDT Device
++*
++* Copyright (C) ASPEED Technology Inc.
++* This program is free software; you can redistribute it and/or modify
++* it under the terms of the GNU General Public License as published by the Free Software Foundation;
++* either version 2 of the License, or (at your option) any later version.
++*
++* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
++* without even the implied warranty of MERCHANTABILITY or
++* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
++*
++* You should have received a copy of the GNU General Public License
++* along with this program; if not, write to the Free Software
++* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++
++* History :
++* 1. 2012/09/15 Ryan Chen initial
++*
++********************************************************************************/
++#include <linux/kernel.h>
++#include <linux/platform_device.h>
++
++#include <mach/irqs.h>
++#include <mach/platform.h>
++
++#include <plat/devs.h>
++
++/* --------------------------------------------------------------------
++ * Watchdog
++ * -------------------------------------------------------------------- */
++
++#if defined(CONFIG_AST_WATCHDOG) || defined(CONFIG_AST_WATCHDOG_MODULE)
++
++static struct resource ast_wdt_resource0[] = {
++ [0] = {
++ .start = AST_WDT_BASE,
++ .end = AST_WDT_BASE + (SZ_16*2) - 1,
++ .flags = IORESOURCE_MEM,
++ },
++ [1] = {
++ .start = IRQ_WDT,
++ .end = IRQ_WDT,
++ .flags = IORESOURCE_IRQ,
++ },
++};
++
++static struct resource ast_wdt_resource1[] = {
++ [0] = {
++ .start = AST_WDT_BASE + (SZ_16*2),
++ .end = AST_WDT_BASE + (SZ_16*4) - 1,
++ .flags = IORESOURCE_MEM,
++ },
++ [1] = {
++ .start = IRQ_WDT,
++ .end = IRQ_WDT,
++ .flags = IORESOURCE_IRQ,
++ },
++};
++
++static struct platform_device ast_device_wdt = {
++ .name = "ast-wdt",
++ .id = -1,
++ .resource = ast_wdt_resource0,
++ .num_resources = ARRAY_SIZE(ast_wdt_resource0),
++};
++
++void __init ast_add_device_watchdog(void)
++{
++ platform_device_register(&ast_device_wdt);
++}
++#else
++void __init ast_add_device_watchdog(void) {}
++#endif
+diff --git a/arch/arm/plat-aspeed/devs.c b/arch/arm/plat-aspeed/devs.c
+new file mode 100644
+index 0000000..7906b9c
+--- /dev/null
++++ b/arch/arm/plat-aspeed/devs.c
+@@ -0,0 +1,69 @@
++/********************************************************************************
++* File Name : linux/arch/arm/plat-aspeed/devs.c
++* Author : Ryan chen
++*
++* Copyright (C) 2012-2020 ASPEED Technology Inc.
++* This program is free software; you can redistribute it and/or modify
++* it under the terms of the GNU General Public License as published by the Free Software Foundation;
++* either version 2 of the License, or (at your option) any later version.
++*
++* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
++* without even the implied warranty of MERCHANTABILITY or
++* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
++*
++* You should have received a copy of the GNU General Public License
++* along with this program; if not, write to the Free Software
++* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++
++* History :
++* 1. 2012/08/10 create this file [Ryan Chen]
++*
++********************************************************************************/
++
++#include <linux/kernel.h>
++#include <linux/string.h>
++#include <linux/platform_device.h>
++
++#include <mach/platform.h>
++
++#include <plat/devs.h>
++
++typedef void (init_fnc_t) (void);
++
++init_fnc_t __initdata *init_all_device[] = {
++ ast_add_device_uart,
++ ast_add_device_vuart,
++ ast_add_device_watchdog,
++ ast_add_device_rtc,
++ ast_add_device_i2c,
++ ast_add_device_spi,
++ ast_add_device_ehci,
++ ast_add_device_nand,
++ ast_add_device_flash,
++ ast_add_device_pwm_fan,
++ ast_add_device_adc,
++ ast_add_device_gpio,
++ ast_add_device_sgpio,
++ ast_add_device_peci,
++ ast_add_device_fb,
++ ast_add_device_sdhci,
++ ast_add_device_uhci,
++ ast_add_device_video,
++ ast_add_device_kcs,
++ ast_add_device_mailbox,
++ ast_add_device_snoop,
++ ast_add_device_gmac,
++// ast_add_device_nand,
++ NULL,
++};
++
++void __init ast_add_all_devices(void)
++{
++ init_fnc_t **init_fnc_ptr;
++
++ for (init_fnc_ptr = init_all_device; *init_fnc_ptr; ++init_fnc_ptr) {
++ (*init_fnc_ptr)();
++ }
++
++ return;
++}
+diff --git a/arch/arm/plat-aspeed/i2c-slave-eeprom.c b/arch/arm/plat-aspeed/i2c-slave-eeprom.c
+new file mode 100644
+index 0000000..fd53f1a
+--- /dev/null
++++ b/arch/arm/plat-aspeed/i2c-slave-eeprom.c
+@@ -0,0 +1,141 @@
++/********************************************************************************
++* File Name : linux/arch/arm/plat-aspeed/i2c-slave-eeprom.c
++* Author : Ryan chen
++* Description : ASPEED I2C Device
++*
++* Copyright (C) ASPEED Technology Inc.
++* This program is free software; you can redistribute it and/or modify
++* it under the terms of the GNU General Public License as published by the Free Software Foundation;
++* either version 2 of the License, or (at your option) any later version.
++*
++* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
++* without even the implied warranty of MERCHANTABILITY or
++* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
++*
++* You should have received a copy of the GNU General Public License
++* along with this program; if not, write to the Free Software
++* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++
++* History :
++* 1. 2013/05/30 ryan chen create this file
++*
++********************************************************************************/
++#include <linux/i2c.h>
++#if defined(CONFIG_COLDFIRE)
++#include <asm/arch/ast_i2c.h>
++#else
++#include <plat/ast_i2c.h>
++#endif
++
++#ifdef I2C_EEPROM
++#define EEPROM_DBUG(fmt, args...) printk("%s() " fmt, __FUNCTION__, ## args)
++#else
++#define EEPROM_DBUG(fmt, args...)
++#endif
++
++static u8 cmd_buf[1] = {0};
++static struct i2c_msg cmd_msg = {
++ .addr = 0x04,
++ .len = 1,
++ .buf = cmd_buf,
++};
++
++//Note 10 byte data memory share for all bus slave device ...........
++#define BUF_SIZE 10
++
++static u8 store_memory[BUF_SIZE] = {0x03,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09};
++ // RO, RW, .................
++static struct i2c_msg data_msg = {
++ .addr = 0x04,
++ .len = BUF_SIZE,
++ .buf = store_memory,
++};
++static u8 mem_index = 0;
++static u8 slave_stage = INIT_STAGE;
++
++extern void i2c_slave_init(struct i2c_msg **msgs)
++{
++ *msgs = &cmd_msg;
++}
++
++extern void i2c_slave_xfer(i2c_slave_event_t event, struct i2c_msg **msgs)
++{
++ EEPROM_DBUG("[event %d] \n",event);
++ switch(event) {
++ case I2C_SLAVE_EVENT_START_READ:
++ cmd_msg.flags = I2C_M_RD;
++ data_msg.flags = I2C_M_RD;
++ if(slave_stage == INIT_STAGE) {
++ EEPROM_DBUG("Rt DATA_MSG [%x]\n",data_msg.buf[0]);
++ slave_stage = DATA_STAGE;
++ *msgs = &data_msg;
++ } else {
++ //CMD_STAGE
++ if(cmd_msg.buf[0] != ((cmd_msg.addr << 1)|1))
++ printk("START READ ADDR Error %x\n",cmd_msg.buf[0]);
++
++ EEPROM_DBUG("Rt CMD_DATA_MSG data [%x]\n",store_memory[mem_index]);
++ cmd_msg.buf[0] = store_memory[mem_index];
++ mem_index++;
++ mem_index %=BUF_SIZE;
++ slave_stage = CMD_DATA_STAGE;
++ *msgs = &cmd_msg;
++ }
++ break;
++ case I2C_SLAVE_EVENT_START_WRITE:
++ EEPROM_DBUG("Rt CMD_MSG START_WRITE %x\n",cmd_msg.buf[0]);
++ cmd_msg.flags = 0;
++ if(cmd_msg.buf[0] != cmd_msg.addr <<1)
++ printk("ERROR ADDRESS Match [%x] \n", cmd_msg.buf[0]);
++ slave_stage = CMD_STAGE;
++
++ *msgs = &cmd_msg;
++
++ break;
++
++ case I2C_SLAVE_EVENT_WRITE:
++ cmd_msg.flags = 0;
++ if(slave_stage == CMD_STAGE) {
++ EEPROM_DBUG("w CMD = [index %x] \n",cmd_msg.buf[0]);
++ mem_index = cmd_msg.buf[0];
++ mem_index %= BUF_SIZE;
++ slave_stage = CMD_DATA_STAGE;
++ *msgs = &cmd_msg;
++ } else {
++ EEPROM_DBUG("w index %d CMD_DATA [%x] \n",mem_index, cmd_msg.buf[0]);
++ if(mem_index !=0)
++ store_memory[mem_index] = cmd_msg.buf[0];
++ mem_index++;
++ mem_index %=BUF_SIZE;
++ EEPROM_DBUG("Rt CMD_DATA_MSG \n");
++ *msgs = &cmd_msg;
++ }
++ break;
++ case I2C_SLAVE_EVENT_READ:
++ cmd_msg.flags = I2C_M_RD;
++ if(slave_stage == CMD_DATA_STAGE) {
++ cmd_msg.buf[0] = store_memory[mem_index];
++ mem_index++;
++ mem_index %=BUF_SIZE;
++ EEPROM_DBUG("Rt CMD_DATA_MSG [%x]\n",cmd_msg.buf[0]);
++ *msgs = &cmd_msg;
++ } else {
++ EEPROM_DBUG("Rt DATA_MSG [%x]\n",data_msg.buf[0]);
++ *msgs = &data_msg;
++ }
++ break;
++ case I2C_SLAVE_EVENT_NACK:
++ cmd_msg.flags = I2C_M_RD;
++ slave_stage = INIT_STAGE;
++ *msgs = &cmd_msg;
++
++ break;
++
++ case I2C_SLAVE_EVENT_STOP:
++ cmd_msg.flags = I2C_M_RD;
++ slave_stage = INIT_STAGE;
++ *msgs = &cmd_msg;
++ break;
++ }
++
++}
+diff --git a/arch/arm/plat-aspeed/include/plat/aspeed.h b/arch/arm/plat-aspeed/include/plat/aspeed.h
+new file mode 100644
+index 0000000..4f7c240
+--- /dev/null
++++ b/arch/arm/plat-aspeed/include/plat/aspeed.h
+@@ -0,0 +1,44 @@
++/*
++ * arch/arm/plat-aspeed/include/plat/aspeed.h
++ *
++ * Copyright (C) 2012-2020 ASPEED Technology Inc.
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++ */
++
++#if defined(CONFIG_ARCH_AST3200) || defined(CONFIG_ARCH_AST2500) || defined(CONFIG_ARCH_AST1520)
++#define AST_SOC_G5
++#define NEW_VIC
++#define SRAM_SIZE SZ_32K
++#elif defined(CONFIG_ARCH_AST1400) || defined(CONFIG_ARCH_AST2400) || defined(CONFIG_ARCH_AST3100)
++#define AST_SOC_G4
++#define NEW_VIC
++#define SRAM_SIZE SZ_32K
++#elif defined(CONFIG_ARCH_AST1300) || defined(CONFIG_ARCH_AST2300) || defined(CONFIG_ARCH_AST1510)
++#define AST_SOC_G3
++#define NEW_VIC
++#define SRAM_SIZE SZ_16K
++#elif defined(CONFIG_ARCH_AST2150) || defined(CONFIG_ARCH_AST2200)
++#define AST_SOC_G2_5
++#elif defined(CONFIG_ARCH_AST1100) || defined(CONFIG_ARCH_AST2050) || defined(CONFIG_ARCH_AST2100)
++#define AST_SOC_G2
++#elif defined(CONFIG_ARCH_AST2000) || defined(CONFIG_ARCH_AST1000)
++#define AST_SOC_G1
++#else
++#error "Not define SoC generation"
++#endif
++
++
++
+diff --git a/arch/arm/plat-aspeed/include/plat/ast-lpc.h b/arch/arm/plat-aspeed/include/plat/ast-lpc.h
+new file mode 100644
+index 0000000..1bf2bef
+--- /dev/null
++++ b/arch/arm/plat-aspeed/include/plat/ast-lpc.h
+@@ -0,0 +1,34 @@
++/*
++ * Platform data for AST LPC .
++ *
++ * Copyright (C) ASPEED Technology Inc.
++ *
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License as
++ * published by the Free Software Foundation version 2.
++ *
++ * This program is distributed "as is" WITHOUT ANY WARRANTY of any
++ * kind, whether express or implied; without even the implied warranty
++ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ */
++
++struct ast_lpc_bus_info
++{
++ u8 lpc_dev_mode; /* 0: host mode , 1: dev mode*/
++ u8 bus_scan;
++ u8 scan_node;
++ u8 lpc_mode; /* 0: lpc , 1: lpc+ */
++ u32 bridge_phy_addr;
++};
++
++struct ast_lpc_driver_data
++{
++ struct platform_device *pdev;
++ void __iomem *reg_base; /* virtual */
++ int irq; //I2C IRQ number
++ u32 bus_id; //for i2c dev# IRQ number check
++ struct ast_lpc_bus_info *bus_info;
++};
++
++extern struct ast_lpc_info *ast_get_lpc_info(void);
+diff --git a/arch/arm/plat-aspeed/include/plat/ast-pcie.h b/arch/arm/plat-aspeed/include/plat/ast-pcie.h
+new file mode 100644
+index 0000000..d099c57
+--- /dev/null
++++ b/arch/arm/plat-aspeed/include/plat/ast-pcie.h
+@@ -0,0 +1,28 @@
++/*
++ * Platform data for AST PCIe Root Complex module.
++ *
++ * Copyright (C) ASPEED Technology Inc.
++ *
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License as
++ * published by the Free Software Foundation version 2.
++ *
++ * This program is distributed "as is" WITHOUT ANY WARRANTY of any
++ * kind, whether express or implied; without even the implied warranty
++ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ */
++
++#ifndef __AST_PCIE_H_
++#define __AST_PCIE_H_
++
++struct ast_pcie_data {
++ int msi_irq_base;
++ int msi_irq_num;
++ int force_x1;
++ int msi_inv; /* 1 = MSI ack requires "write 0 to clear" */
++ unsigned short int device_id;
++};
++
++#endif
++
+diff --git a/arch/arm/plat-aspeed/include/plat/ast-scu.h b/arch/arm/plat-aspeed/include/plat/ast-scu.h
+new file mode 100644
+index 0000000..77169ee
+--- /dev/null
++++ b/arch/arm/plat-aspeed/include/plat/ast-scu.h
+@@ -0,0 +1,92 @@
++/********************************************************************************
++* File Name : arch/arm/mach-aspeed/include/plat/ast-scu.h
++* Author : Ryan Chen
++* Description : AST SCU Service Header
++*
++* Copyright (C) 2012-2020 ASPEED Technology Inc.
++* This program is free software; you can redistribute it and/or modify
++* it under the terms of the GNU General Public License as published by the Free Software Foundation;
++* either version 2 of the License, or (at your option) any later version.
++* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
++* without even the implied warranty of MERCHANTABILITY or
++* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
++* You should have received a copy of the GNU General Public License
++* along with this program; if not, write to the Free Software
++* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++
++* History :
++* 1. 2012/08/03 Ryan Chen create this file
++*
++********************************************************************************/
++
++#ifndef __AST_SCU_H_INCLUDED
++#define __AST_SCU_H_INCLUDED
++
++//information
++extern void ast_scu_show_system_info (void);
++extern u32 ast_scu_revision_id(void);
++extern u32 ast_scu_get_phy_interface(u8 mac_num);
++extern u32 ast_scu_get_phy_config(u8 mac_num);
++
++
++//CLK
++extern u32 ast_get_clk_source(void);
++extern u32 ast_get_h_pll_clk(void);
++extern u32 ast_get_m_pll_clk(void);
++extern u32 ast_get_pclk(void);
++extern u32 ast_get_sd_clock_src(void);
++extern u32 ast_get_d2_pll_clk(void);
++extern u32 ast_get_lhclk(void);
++
++extern void ast_scu_set_vga_display(u8 enable);
++extern u32 ast_scu_get_vga_memsize(void);
++
++//Ctrl Initial
++extern void ast_scu_init_video(u8 dynamic_en);
++extern void ast_scu_reset_video(void);
++extern void ast_scu_init_eth(u8 num);
++extern void ast_scu_init_lpc(void);
++extern u8 ast_scu_get_lpc_plus_enable(void);
++extern void ast_scu_init_udc11(void);
++extern void ast_scu_init_usb20(void);
++extern void ast_scu_init_uhci(void);
++extern void ast_scu_init_sdhci(void);
++extern void ast_scu_init_i2c(void);
++extern void ast_scu_init_pwm_tacho(void);
++extern void ast_scu_init_adc(void);
++extern void ast_scu_init_peci(void);
++extern void ast_scu_init_jtag(void);
++extern void ast_scu_init_crt(void);
++
++
++
++//Share pin
++extern void ast_scu_multi_func_uart(u8 uart);
++extern void ast_scu_multi_func_video(void);
++
++extern void ast_scu_multi_func_eth(u8 num);
++
++extern void ast_scu_multi_func_nand(void);
++
++extern void ast_scu_multi_func_nor(void);
++
++extern void ast_scu_multi_func_romcs(u8 num);
++
++extern void ast_scu_multi_func_i2c(void);
++extern void ast_scu_multi_func_pwm_tacho(void);
++//0 : hub mode , 1: usb host mode
++extern void ast_scu_multi_func_usb20_host_hub(u8 mode);
++//0 : gpioQ6,7 mode , 1: usb1.1 host port 4 mode
++extern void ast_scu_multi_func_usb11_host_port4(u8 mode);
++//0 : USB 1.1 HID mode , 1: usb1.1 host port 2 mode
++extern void ast_scu_multi_func_usb11_host_port2(u8 mode);
++
++extern void ast_scu_multi_func_sdhc_slot1(u8 mode);
++extern void ast_scu_multi_func_sdhc_slot2(u8 mode);
++extern void ast_scu_multi_func_crt(void);
++
++
++
++
++
++#endif
+diff --git a/arch/arm/plat-aspeed/include/plat/ast-sdmc.h b/arch/arm/plat-aspeed/include/plat/ast-sdmc.h
+new file mode 100644
+index 0000000..72d8d72
+--- /dev/null
++++ b/arch/arm/plat-aspeed/include/plat/ast-sdmc.h
+@@ -0,0 +1,26 @@
++/********************************************************************************
++* File Name : arch/arm/mach-aspeed/include/plat/ast-scu.h
++* Author : Ryan Chen
++* Description : AST SCU Service Header
++*
++* Copyright (C) 2012-2020 ASPEED Technology Inc.
++* This program is free software; you can redistribute it and/or modify
++* it under the terms of the GNU General Public License as published by the Free Software Foundation;
++* either version 2 of the License, or (at your option) any later version.
++* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
++* without even the implied warranty of MERCHANTABILITY or
++* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
++* You should have received a copy of the GNU General Public License
++* along with this program; if not, write to the Free Software
++* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++
++* History :
++* 1. 2012/08/03 Ryan Chen create this file
++*
++********************************************************************************/
++
++#ifndef __AST_SDMC_H_INCLUDED
++#define __AST_SDMC_H_INCLUDED
++
++extern u32 ast_sdmc_get_mem_size(void);
++#endif
+diff --git a/arch/arm/plat-aspeed/include/plat/ast-snoop.h b/arch/arm/plat-aspeed/include/plat/ast-snoop.h
+new file mode 100644
+index 0000000..76ea7611
+--- /dev/null
++++ b/arch/arm/plat-aspeed/include/plat/ast-snoop.h
+@@ -0,0 +1,37 @@
++/*
++ * ast-snoop_h
++ *
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or (at
++ * your option) any later version.
++ */
++
++struct ast_snoop_channel {
++ u8 snoop_ch;
++ u8 snoop_port;
++ u8 snoop_data;
++};
++
++struct ast_snoop {
++ struct ast_snoop_channel *snoop_ch0;
++ struct ast_snoop_channel *snoop_ch1;
++};
++
++struct ast_snoop_dma_channel {
++ u8 snoop_ch;
++ u8 snoop_port;
++ u8 snoop_mask;
++ u8 snoop_mode;
++ u8 snoop_index;
++ u32 dma_virt;
++ dma_addr_t dma_addr;
++ u16 dma_size;
++};
++
++extern int ast_snoop_init(struct ast_snoop *snoop);
++extern void ast_snoop_dma_init(struct ast_snoop_dma_channel *ast_dma_ch);
++
++
++
+diff --git a/arch/arm/plat-aspeed/include/plat/ast1070-devs.h b/arch/arm/plat-aspeed/include/plat/ast1070-devs.h
+new file mode 100644
+index 0000000..b3aa799
+--- /dev/null
++++ b/arch/arm/plat-aspeed/include/plat/ast1070-devs.h
+@@ -0,0 +1,25 @@
++/********************************************************************************
++* arch/arm/plat-aspeed/include/plat/devs.h
++*
++* Copyright (C) ASPEED Technology Inc.
++* This program is free software; you can redistribute it and/or modify
++* it under the terms of the GNU General Public License as published by the Free Software Foundation;
++* either version 2 of the License, or (at your option) any later version.
++*
++* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
++* without even the implied warranty of MERCHANTABILITY or
++* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
++*
++* You should have received a copy of the GNU General Public License
++* along with this program; if not, write to the Free Software
++* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++********************************************************************************/
++#ifndef __ASM_PLAT_AST1070_H
++#define __ASM_PLAT_AST1070_H
++
++//ast1070
++extern void __init ast_add_device_cuart(u8 chip, u32 lpc_base);
++extern void __init ast_add_device_clpc(u8 chip, u32 lpc_base);
++extern void __init ast_add_device_ci2c(u8 chip, u32 lpc_base);
++
++#endif
+diff --git a/arch/arm/plat-aspeed/include/plat/ast1070-scu.h b/arch/arm/plat-aspeed/include/plat/ast1070-scu.h
+new file mode 100644
+index 0000000..70c63e2
+--- /dev/null
++++ b/arch/arm/plat-aspeed/include/plat/ast1070-scu.h
+@@ -0,0 +1,34 @@
++/********************************************************************************
++* File Name : arch/arm/mach-aspeed/include/plat/ast1070-scu.h
++* Author : Ryan Chen
++* Description : AST1070 SCU Service Header
++*
++* Copyright (C) 2012-2020 ASPEED Technology Inc.
++* This program is free software; you can redistribute it and/or modify
++* it under the terms of the GNU General Public License as published by the Free Software Foundation;
++* either version 2 of the License, or (at your option) any later version.
++* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
++* without even the implied warranty of MERCHANTABILITY or
++* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
++* You should have received a copy of the GNU General Public License
++* along with this program; if not, write to the Free Software
++* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++
++* History :
++* 1. 2013/05/03 Ryan Chen create this file
++*
++********************************************************************************/
++
++#ifndef __AST1070_SCU_H_INCLUDED
++#define __AST1070_SCU_H_INCLUDED
++
++extern void ast1070_scu_init_i2c(u8 node);
++extern void ast1070_scu_init_uart(u8 node);
++extern void ast1070_scu_revision_id(u8 node);
++extern void ast1070_dma_init(u8 node);
++extern void ast1070_multi_func_uart(u8 node, u8 uart);
++
++
++
++
++#endif
+diff --git a/arch/arm/plat-aspeed/include/plat/ast1070-uart-dma.h b/arch/arm/plat-aspeed/include/plat/ast1070-uart-dma.h
+new file mode 100644
+index 0000000..c4edd75
+--- /dev/null
++++ b/arch/arm/plat-aspeed/include/plat/ast1070-uart-dma.h
+@@ -0,0 +1,27 @@
++/********************************************************************************
++* File Name : arch/arm/mach-aspeed/include/plat/ast1070-scu.h
++* Author : Ryan Chen
++* Description : AST1070 SCU Service Header
++*
++* Copyright (C) 2012-2020 ASPEED Technology Inc.
++* This program is free software; you can redistribute it and/or modify
++* it under the terms of the GNU General Public License as published by the Free Software Foundation;
++* either version 2 of the License, or (at your option) any later version.
++* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
++* without even the implied warranty of MERCHANTABILITY or
++* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
++* You should have received a copy of the GNU General Public License
++* along with this program; if not, write to the Free Software
++* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++
++* History :
++* 1. 2013/05/03 Ryan Chen create this file
++*
++********************************************************************************/
++
++#ifndef __AST1070_UART_DMA_H_INCLUDED
++#define __AST1070_UART_DMA_H_INCLUDED
++
++extern void ast1070_uart_dma_init(u8 node);
++
++#endif
+diff --git a/arch/arm/plat-aspeed/include/plat/ast_i2c.h b/arch/arm/plat-aspeed/include/plat/ast_i2c.h
+new file mode 100644
+index 0000000..b0ff995
+--- /dev/null
++++ b/arch/arm/plat-aspeed/include/plat/ast_i2c.h
+@@ -0,0 +1,64 @@
++/*
++ * ast_i2c_h
++ *
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or (at
++ * your option) any later version.
++ */
++
++//I2C MEMORY Device state machine
++typedef enum i2c_slave_stage {
++ INIT_STAGE,
++ CMD_STAGE,
++ CMD_DATA_STAGE,
++ DATA_STAGE
++} stage;
++
++typedef enum i2c_xfer_mode {
++ BYTE_XFER,
++ BUFF_XFER,
++ DMA_XFER
++} i2c_xfer_mode_t;
++
++//1. usage flag , 2 size, 3. request address
++struct buf_page
++{
++ u8 flag; //0:free to usage, 1: used
++ u8 page_no; //for AST2400 usage
++ u16 page_size;
++ u32 page_addr;
++ u32 page_addr_point;
++};
++
++typedef enum i2c_slave_event_e {
++ I2C_SLAVE_EVENT_START_READ,
++ I2C_SLAVE_EVENT_READ,
++ I2C_SLAVE_EVENT_START_WRITE,
++ I2C_SLAVE_EVENT_WRITE,
++ I2C_SLAVE_EVENT_NACK,
++ I2C_SLAVE_EVENT_STOP
++} i2c_slave_event_t;
++
++#define BYTE_MODE 0
++#define BUFF_MODE 1
++#define DMA_MODE 2
++
++struct ast_i2c_driver_data {
++ void __iomem *reg_gr;
++ u32 bus_clk;
++ u8 master_dma; //0,byte mode 1,Buffer pool mode 256 , or 2048 , 2: DMA mode
++ u8 slave_dma; //0,byte mode 1,Buffer pool mode 256 , or 2048 , 2: DMA mode
++ u8 (*request_pool_buff_page)(struct buf_page **page);
++ void (*free_pool_buff_page)(struct buf_page *page);
++ unsigned char *buf_pool;
++ void (*slave_xfer)(i2c_slave_event_t event, struct i2c_msg **msgs);
++ void (*slave_init)(struct i2c_msg **msgs);
++ u32 (*get_i2c_clock)(void);
++};
++
++#ifdef CONFIG_AST_I2C_SLAVE_MODE
++extern void i2c_slave_init(struct i2c_msg **msgs);
++extern void i2c_slave_xfer(i2c_slave_event_t event, struct i2c_msg **msgs);
++#endif
+\ No newline at end of file
+diff --git a/arch/arm/plat-aspeed/include/plat/ast_mctp.h b/arch/arm/plat-aspeed/include/plat/ast_mctp.h
+new file mode 100644
+index 0000000..51396ff
+--- /dev/null
++++ b/arch/arm/plat-aspeed/include/plat/ast_mctp.h
+@@ -0,0 +1,31 @@
++/********************************************************************************
++* File Name : arch/arm/mach-aspeed/include/plat/ast-scu.h
++* Author : Ryan Chen
++* Description : AST SCU Service Header
++*
++* Copyright (C) 2012-2020 ASPEED Technology Inc.
++* This program is free software; you can redistribute it and/or modify
++* it under the terms of the GNU General Public License as published by the Free Software Foundation;
++* either version 2 of the License, or (at your option) any later version.
++* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
++* without even the implied warranty of MERCHANTABILITY or
++* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
++* You should have received a copy of the GNU General Public License
++* along with this program; if not, write to the Free Software
++* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++
++* History :
++* 1. 2012/08/03 Ryan Chen create this file
++*
++********************************************************************************/
++
++#ifndef __AST_P2X_H_INCLUDED
++#define __AST_P2X_H_INCLUDED
++
++extern void ast_pcie_cfg_read(u8 type, u32 bdf_offset, u32 *value);
++//extern void ast_pcie_cfg_write(u8 type, u32 bdf_offset, u32 data);
++extern void ast_pcie_cfg_write(u8 type, u8 byte_en, u32 bdf_offset, u32 data);
++extern void ast_mctp_addr_map(u32 mask, u32 addr);
++
++#endif
++
+diff --git a/arch/arm/plat-aspeed/include/plat/ast_sdhci.h b/arch/arm/plat-aspeed/include/plat/ast_sdhci.h
+new file mode 100644
+index 0000000..13547af
+--- /dev/null
++++ b/arch/arm/plat-aspeed/include/plat/ast_sdhci.h
+@@ -0,0 +1,290 @@
++/*
++ * sdhci.h - Secure Digital Host Controller Interface driver
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or (at
++ * your option) any later version.
++ */
++
++#include <linux/scatterlist.h>
++#include <linux/leds.h>
++#include <linux/interrupt.h>
++
++
++/*
++ * Controller registers
++ */
++
++#define SDHCI_DMA_ADDRESS 0x00
++
++#define SDHCI_BLOCK_SIZE 0x04
++#define SDHCI_MAKE_BLKSZ(dma, blksz) (((dma & 0x7) << 12) | (blksz & 0xFFF))
++
++#define SDHCI_BLOCK_COUNT 0x06
++
++#define SDHCI_ARGUMENT 0x08
++
++#define SDHCI_TRANSFER_MODE 0x0C
++#define SDHCI_TRNS_DMA 0x01
++#define SDHCI_TRNS_BLK_CNT_EN 0x02
++#define SDHCI_TRNS_ACMD12 0x04
++#define SDHCI_TRNS_READ 0x10
++#define SDHCI_TRNS_MULTI 0x20
++
++#define SDHCI_COMMAND 0x0E
++#define SDHCI_CMD_RESP_MASK 0x03
++#define SDHCI_CMD_CRC 0x08
++#define SDHCI_CMD_INDEX 0x10
++#define SDHCI_CMD_DATA 0x20
++
++#define SDHCI_CMD_RESP_NONE 0x00
++#define SDHCI_CMD_RESP_LONG 0x01
++#define SDHCI_CMD_RESP_SHORT 0x02
++#define SDHCI_CMD_RESP_SHORT_BUSY 0x03
++
++#define SDHCI_MAKE_CMD(c, f) (((c & 0xff) << 8) | (f & 0xff))
++
++#define SDHCI_RESPONSE 0x10
++
++#define SDHCI_BUFFER 0x20
++
++#define SDHCI_PRESENT_STATE 0x24
++#define SDHCI_CMD_INHIBIT 0x00000001
++#define SDHCI_DATA_INHIBIT 0x00000002
++#define SDHCI_DOING_WRITE 0x00000100
++#define SDHCI_DOING_READ 0x00000200
++#define SDHCI_SPACE_AVAILABLE 0x00000400
++#define SDHCI_DATA_AVAILABLE 0x00000800
++#define SDHCI_CARD_PRESENT 0x00010000
++#define SDHCI_WRITE_PROTECT 0x00080000
++
++#define SDHCI_HOST_CONTROL 0x28
++#define SDHCI_CTRL_LED 0x01
++#define SDHCI_CTRL_4BITBUS 0x02
++#define SDHCI_CTRL_HISPD 0x04
++#define SDHCI_CTRL_DMA_MASK 0x18
++#define SDHCI_CTRL_SDMA 0x00
++#define SDHCI_CTRL_ADMA1 0x08
++#define SDHCI_CTRL_ADMA32 0x10
++#define SDHCI_CTRL_ADMA64 0x18
++
++#define SDHCI_POWER_CONTROL 0x29
++#define SDHCI_POWER_ON 0x01
++#define SDHCI_POWER_180 0x0A
++#define SDHCI_POWER_300 0x0C
++#define SDHCI_POWER_330 0x0E
++
++#define SDHCI_BLOCK_GAP_CONTROL 0x2A
++
++#define SDHCI_WAKE_UP_CONTROL 0x2B
++
++#define SDHCI_CLOCK_CONTROL 0x2C
++#define SDHCI_DIVIDER_SHIFT 8
++#define SDHCI_CLOCK_CARD_EN 0x0004
++#define SDHCI_CLOCK_INT_STABLE 0x0002
++#define SDHCI_CLOCK_INT_EN 0x0001
++
++#define SDHCI_TIMEOUT_CONTROL 0x2E
++
++#define SDHCI_SOFTWARE_RESET 0x2F
++#define SDHCI_RESET_ALL 0x01
++#define SDHCI_RESET_CMD 0x02
++#define SDHCI_RESET_DATA 0x04
++
++#define SDHCI_INT_STATUS 0x30
++#define SDHCI_INT_ENABLE 0x34
++#define SDHCI_SIGNAL_ENABLE 0x38
++#define SDHCI_INT_RESPONSE 0x00000001
++#define SDHCI_INT_DATA_END 0x00000002
++#define SDHCI_INT_DMA_END 0x00000008
++#define SDHCI_INT_SPACE_AVAIL 0x00000010
++#define SDHCI_INT_DATA_AVAIL 0x00000020
++#define SDHCI_INT_CARD_INSERT 0x00000040
++#define SDHCI_INT_CARD_REMOVE 0x00000080
++#define SDHCI_INT_CARD_INT 0x00000100
++#define SDHCI_INT_ERROR 0x00008000
++#define SDHCI_INT_TIMEOUT 0x00010000
++#define SDHCI_INT_CRC 0x00020000
++#define SDHCI_INT_END_BIT 0x00040000
++#define SDHCI_INT_INDEX 0x00080000
++#define SDHCI_INT_DATA_TIMEOUT 0x00100000
++#define SDHCI_INT_DATA_CRC 0x00200000
++#define SDHCI_INT_DATA_END_BIT 0x00400000
++#define SDHCI_INT_BUS_POWER 0x00800000
++#define SDHCI_INT_ACMD12ERR 0x01000000
++#define SDHCI_INT_ADMA_ERROR 0x02000000
++
++#define SDHCI_INT_NORMAL_MASK 0x00007FFF
++#define SDHCI_INT_ERROR_MASK 0xFFFF8000
++
++#define SDHCI_INT_CMD_MASK (SDHCI_INT_RESPONSE | SDHCI_INT_TIMEOUT | \
++ SDHCI_INT_CRC | SDHCI_INT_END_BIT | SDHCI_INT_INDEX)
++#define SDHCI_INT_DATA_MASK (SDHCI_INT_DATA_END | SDHCI_INT_DMA_END | \
++ SDHCI_INT_DATA_AVAIL | SDHCI_INT_SPACE_AVAIL | \
++ SDHCI_INT_DATA_TIMEOUT | SDHCI_INT_DATA_CRC | \
++ SDHCI_INT_DATA_END_BIT)
++
++#define SDHCI_ACMD12_ERR 0x3C
++
++/* 3E-3F reserved */
++
++#define SDHCI_CAPABILITIES 0x40
++#define SDHCI_TIMEOUT_CLK_MASK 0x0000003F
++#define SDHCI_TIMEOUT_CLK_SHIFT 0
++#define SDHCI_TIMEOUT_CLK_UNIT 0x00000080
++#define SDHCI_CLOCK_BASE_MASK 0x00003F00
++#define SDHCI_CLOCK_BASE_SHIFT 8
++#define SDHCI_MAX_BLOCK_MASK 0x00030000
++#define SDHCI_MAX_BLOCK_SHIFT 16
++#define SDHCI_CAN_DO_ADMA2 0x00080000
++#define SDHCI_CAN_DO_ADMA1 0x00100000
++#define SDHCI_CAN_DO_HISPD 0x00200000
++#define SDHCI_CAN_DO_DMA 0x00400000
++#define SDHCI_CAN_VDD_330 0x01000000
++#define SDHCI_CAN_VDD_300 0x02000000
++#define SDHCI_CAN_VDD_180 0x04000000
++#define SDHCI_CAN_64BIT 0x10000000
++
++/* 44-47 reserved for more caps */
++
++#define SDHCI_MAX_CURRENT 0x48
++
++/* 4C-4F reserved for more max current */
++
++#define SDHCI_SET_ACMD12_ERROR 0x50
++#define SDHCI_SET_INT_ERROR 0x52
++
++#define SDHCI_ADMA_ERROR 0x54
++
++/* 55-57 reserved */
++
++#define SDHCI_ADMA_ADDRESS 0x58
++
++/* 60-FB reserved */
++
++#define SDHCI_SLOT_INT_STATUS 0xFC
++
++#define SDHCI_HOST_VERSION 0xFE
++#define SDHCI_VENDOR_VER_MASK 0xFF00
++#define SDHCI_VENDOR_VER_SHIFT 8
++#define SDHCI_SPEC_VER_MASK 0x00FF
++#define SDHCI_SPEC_VER_SHIFT 0
++#define SDHCI_SPEC_100 0
++#define SDHCI_SPEC_200 1
++
++struct sdhci_ops;
++
++struct sdhci_host {
++ /* Data set by hardware interface driver */
++ const char *hw_name; /* Hardware bus name */
++
++ unsigned int quirks; /* Deviations from spec. */
++
++/* Controller doesn't honor resets unless we touch the clock register */
++#define SDHCI_QUIRK_CLOCK_BEFORE_RESET (1<<0)
++/* Controller has bad caps bits, but really supports DMA */
++#define SDHCI_QUIRK_FORCE_DMA (1<<1)
++/* Controller doesn't like to be reset when there is no card inserted. */
++#define SDHCI_QUIRK_NO_CARD_NO_RESET (1<<2)
++/* Controller doesn't like clearing the power reg before a change */
++#define SDHCI_QUIRK_SINGLE_POWER_WRITE (1<<3)
++/* Controller has flaky internal state so reset it on each ios change */
++#define SDHCI_QUIRK_RESET_CMD_DATA_ON_IOS (1<<4)
++/* Controller has an unusable DMA engine */
++#define SDHCI_QUIRK_BROKEN_DMA (1<<5)
++/* Controller has an unusable ADMA engine */
++#define SDHCI_QUIRK_BROKEN_ADMA (1<<6)
++/* Controller can only DMA from 32-bit aligned addresses */
++#define SDHCI_QUIRK_32BIT_DMA_ADDR (1<<7)
++/* Controller can only DMA chunk sizes that are a multiple of 32 bits */
++#define SDHCI_QUIRK_32BIT_DMA_SIZE (1<<8)
++/* Controller can only ADMA chunks that are a multiple of 32 bits */
++#define SDHCI_QUIRK_32BIT_ADMA_SIZE (1<<9)
++/* Controller needs to be reset after each request to stay stable */
++#define SDHCI_QUIRK_RESET_AFTER_REQUEST (1<<10)
++/* Controller needs voltage and power writes to happen separately */
++#define SDHCI_QUIRK_NO_SIMULT_VDD_AND_POWER (1<<11)
++/* Controller provides an incorrect timeout value for transfers */
++#define SDHCI_QUIRK_BROKEN_TIMEOUT_VAL (1<<12)
++/* Controller has an issue with buffer bits for small transfers */
++#define SDHCI_QUIRK_BROKEN_SMALL_PIO (1<<13)
++/* Controller supports high speed but doesn't have the caps bit set */
++#define SDHCI_QUIRK_FORCE_HIGHSPEED (1<<14)
++/* Controller does not provide transfer-complete interrupt when not busy */
++#define SDHCI_QUIRK_NO_BUSY_IRQ (1<<15)
++
++ int irq; /* Device IRQ */
++ void __iomem * ioaddr; /* Mapped address */
++
++ const struct sdhci_ops *ops; /* Low level hw interface */
++
++ /* Internal data */
++ struct mmc_host *mmc; /* MMC structure */
++ u64 dma_mask; /* custom DMA mask */
++
++#ifdef CONFIG_LEDS_CLASS
++ struct led_classdev led; /* LED control */
++ char led_name[32];
++#endif
++
++ spinlock_t lock; /* Mutex */
++
++ int flags; /* Host attributes */
++#define SDHCI_USE_DMA (1<<0) /* Host is DMA capable */
++#define SDHCI_USE_ADMA (1<<1) /* Host is ADMA capable */
++#define SDHCI_REQ_USE_DMA (1<<2) /* Use DMA for this req. */
++#define SDHCI_DEVICE_DEAD (1<<3) /* Device unresponsive */
++
++ unsigned int version; /* SDHCI spec. version */
++
++ unsigned int max_clk; /* Max possible freq (MHz) */
++ unsigned int timeout_clk; /* Timeout freq (KHz) */
++
++ unsigned int clock; /* Current clock (MHz) */
++ unsigned short power; /* Current voltage */
++
++ struct mmc_request *mrq; /* Current request */
++ struct mmc_command *cmd; /* Current command */
++ struct mmc_data *data; /* Current data request */
++ unsigned int data_early:1; /* Data finished before cmd */
++
++ struct sg_mapping_iter sg_miter; /* SG state for PIO */
++ unsigned int blocks; /* remaining PIO blocks */
++
++ int sg_count; /* Mapped sg entries */
++
++ u8 *adma_desc; /* ADMA descriptor table */
++ u8 *align_buffer; /* Bounce buffer */
++
++ dma_addr_t adma_addr; /* Mapped ADMA descr. table */
++ dma_addr_t align_addr; /* Mapped bounce buffer */
++
++ struct tasklet_struct card_tasklet; /* Tasklet structures */
++ struct tasklet_struct finish_tasklet;
++
++ struct timer_list timer; /* Timer for timeouts */
++
++ unsigned long private[0] ____cacheline_aligned;
++};
++
++struct ast_sdhc_platform_data {
++ u32 (*sd_clock_src_get)(void);
++};
++
++extern struct sdhci_host *sdhci_alloc_host(struct device *dev,
++ size_t priv_size);
++extern void sdhci_free_host(struct sdhci_host *host);
++
++static inline void *sdhci_priv(struct sdhci_host *host)
++{
++ return (void *)host->private;
++}
++
++extern int sdhci_add_host(struct sdhci_host *host);
++extern void sdhci_remove_host(struct sdhci_host *host, int dead);
++
++#ifdef CONFIG_PM
++extern int sdhci_suspend_host(struct sdhci_host *host, pm_message_t state);
++extern int sdhci_resume_host(struct sdhci_host *host);
++#endif
+diff --git a/arch/arm/plat-aspeed/include/plat/devs.h b/arch/arm/plat-aspeed/include/plat/devs.h
+new file mode 100644
+index 0000000..41cbea9
+--- /dev/null
++++ b/arch/arm/plat-aspeed/include/plat/devs.h
+@@ -0,0 +1,65 @@
++/********************************************************************************
++* arch/arm/plat-aspeed/include/plat/devs.h
++*
++* Copyright (C) ASPEED Technology Inc.
++* This program is free software; you can redistribute it and/or modify
++* it under the terms of the GNU General Public License as published by the Free Software Foundation;
++* either version 2 of the License, or (at your option) any later version.
++*
++* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
++* without even the implied warranty of MERCHANTABILITY or
++* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
++*
++* You should have received a copy of the GNU General Public License
++* along with this program; if not, write to the Free Software
++* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++********************************************************************************/
++#ifndef __ASM_PLAT_ASPEED_H
++#define __ASM_PLAT_ASPEED_H
++
++extern void __init ast_add_all_devices(void);
++
++//platform
++extern void __init ast_add_device_uart(void);
++extern void __init ast_add_device_vuart(void);
++extern void __init ast_add_device_watchdog(void);
++extern void __init ast_add_device_rtc(void);
++extern void __init ast_add_device_gpio(void);
++extern void __init ast_add_device_sgpio(void);
++
++//ADC
++
++//Bus
++extern void __init ast_add_device_lpc(void);
++extern void __init ast_add_device_snoop(void);
++extern void __init ast_add_device_kcs(void);
++extern void __init ast_add_device_mailbox(void);
++extern void __init ast_add_device_i2c(void);
++extern void __init ast_add_device_spi(void);
++extern void __init ast_add_device_ehci(void);
++extern void __init ast_add_device_uhci(void);
++extern void __init ast_add_device_gmac(void);
++extern void __init ast_add_device_udc11(void);
++extern void __init ast_add_device_hid(void);
++
++extern void __init ast_add_device_pcie(void);
++
++extern void __init ast_add_device_peci(void);
++extern void __init ast_add_device_jtag(void);
++
++//hwmon
++extern void __init ast_add_device_pwm_fan(void);
++extern void __init ast_add_device_adc(void);
++
++
++//Storage
++extern void __init ast_add_device_nand(void);
++extern void __init ast_add_device_flash(void);
++extern void __init ast_add_device_sdhci(void);
++extern void __init ast_add_device_nand(void);
++
++//video
++extern void __init ast_add_device_fb(void);
++extern void __init ast_add_device_video(void);
++
++#endif
+diff --git a/arch/arm/plat-aspeed/include/plat/regs-1070_lpc.h b/arch/arm/plat-aspeed/include/plat/regs-1070_lpc.h
+new file mode 100644
+index 0000000..ef8cd8c
+--- /dev/null
++++ b/arch/arm/plat-aspeed/include/plat/regs-1070_lpc.h
+@@ -0,0 +1,32 @@
++/* arch/arm/plat-aspeed/include/mach/regs-1070_lpc.h
++ *
++ * Copyright (c) 2012 ASPEED Technology Inc. <ryan_chen@aspeedtech.com>
++ * http://www.aspeedtech.com/
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * ASPEED AST1070 LPC Controller
++*/
++
++#ifndef __ASM_ARCH_REGS_LPC_H
++#define __ASM_ARCH_REGS_LPC_H __FILE__
++
++#define AST1070_LPC_HICR0 0x00
++#define AST1070_LPC_HICR1 0x04
++#define AST1070_LPC_HICR2 0x08
++#define AST1070_LPC_HICR3 0x0c
++#define AST1070_LPC_HICR4 0x10
++
++//for snoop driver
++#define AST1070_LPC_L_80H_ADDR 0x220
++#define AST1070_LPC_H_80H_ADDR 0x224
++#define AST1070_LPC_80H_DATA 0x228
++#define AST1070_LPC_80H_CTRL 0x22c
++
++
++#define AST1070_LPC_80H_CLR (0x1 << 4)
++
++#define AST1070_LPC_80H_EN 0x1
++#endif /* __ASM_ARCH_REGS_LPC_H */
+diff --git a/arch/arm/plat-aspeed/include/plat/regs-adc.h b/arch/arm/plat-aspeed/include/plat/regs-adc.h
+new file mode 100644
+index 0000000..97f5919
+--- /dev/null
++++ b/arch/arm/plat-aspeed/include/plat/regs-adc.h
+@@ -0,0 +1,191 @@
++/* arch/arm/plat-aspeed/include/mach/regs-adc.h
++ *
++ * Copyright (c) 2012 ASPEED Technology Inc. <ryan_chen@aspeedtech.com>
++ * http://www.aspeedtech.com/
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * ASPEED ADC Controller
++*/
++
++#ifndef __ASM_ARCH_REGS_ADC_H
++#define __ASM_ARCH_REGS_ADC_H __FILE__
++
++#if defined(CONFIG_ARCH_AST2300)
++#define MAX_CH_NO 12
++#elif defined(CONFIG_ARCH_AST2400) || defined(CONFIG_ARCH_AST2500)
++#define MAX_CH_NO 16
++#elif defined(CONFIG_ARCH_AST1010)
++#define MAX_CH_NO 8
++#else
++#err "ADC NO define MAX CHANNEL NO"
++#endif
++
++#if defined(CONFIG_ARCH_AST2500)
++#define TEMPER_CH_NO 2
++#endif
++
++/*AST ADC Register Definition */
++#define AST_ADC_CTRL 0x00
++#define AST_ADC_IER 0x04
++#define AST_ADC_VGA 0x08
++#if defined(CONFIG_ARCH_AST1010)
++#define AST_ADC_TRIM 0x08
++#endif
++#define AST_ADC_CLK 0x0c
++#define AST_ADC_CH0_1 0x10
++#define AST_ADC_CH2_3 0x14
++#define AST_ADC_CH4_5 0x18
++#define AST_ADC_CH6_7 0x1c
++#define AST_ADC_CH8_9 0x20
++#define AST_ADC_CH10_11 0x24
++#define AST_ADC_CH12_13 0x28
++#define AST_ADC_CH14_15 0x2c
++#define AST_ADC_BOUND0 0x30
++#define AST_ADC_BOUND1 0x34
++#define AST_ADC_BOUND2 0x38
++#define AST_ADC_BOUND3 0x3c
++#define AST_ADC_BOUND4 0x40
++#define AST_ADC_BOUND5 0x44
++#define AST_ADC_BOUND6 0x48
++#define AST_ADC_BOUND7 0x4c
++#define AST_ADC_BOUND8 0x50
++#define AST_ADC_BOUND9 0x54
++#define AST_ADC_BOUND10 0x58
++#define AST_ADC_BOUND11 0x5c
++#define AST_ADC_BOUND12 0x60
++#define AST_ADC_BOUND13 0x64
++#define AST_ADC_BOUND14 0x68
++#define AST_ADC_BOUND15 0x6c
++#define AST_ADC_HYSTER0 0x70
++#define AST_ADC_HYSTER1 0x74
++#define AST_ADC_HYSTER2 0x78
++#define AST_ADC_HYSTER3 0x7c
++#define AST_ADC_HYSTER4 0x80
++#define AST_ADC_HYSTER5 0x84
++#define AST_ADC_HYSTER6 0x88
++#define AST_ADC_HYSTER7 0x8c
++#define AST_ADC_HYSTER8 0x90
++#define AST_ADC_HYSTER9 0x94
++#define AST_ADC_HYSTER10 0x98
++#define AST_ADC_HYSTER11 0x9c
++#define AST_ADC_HYSTER12 0xa0
++#define AST_ADC_HYSTER13 0xa4
++#define AST_ADC_HYSTER14 0xa8
++#define AST_ADC_HYSTER15 0xac
++#define AST_ADC_INTR_SEL 0xC0
++#if defined(CONFIG_ARCH_AST2500)
++#define AST_ADC_CH16 0xD0
++#define AST_ADC_CH17 0xD4
++#endif
++
++
++#define AST_ADC_TRIM 0xC4
++
++// AST_ADC_CTRL:0x00 - ADC Engine Control Register
++#define AST_ADC_CTRL_CH15_EN (0x1 << 31)
++#define AST_ADC_CTRL_CH14_EN (0x1 << 30)
++#define AST_ADC_CTRL_CH13_EN (0x1 << 29)
++#define AST_ADC_CTRL_CH12_EN (0x1 << 28)
++#define AST_ADC_CTRL_CH11_EN (0x1 << 27)
++#define AST_ADC_CTRL_CH10_EN (0x1 << 26)
++#define AST_ADC_CTRL_CH9_EN (0x1 << 25)
++#define AST_ADC_CTRL_CH8_EN (0x1 << 24)
++#define AST_ADC_CTRL_CH7_EN (0x1 << 23)
++#define AST_ADC_CTRL_CH6_EN (0x1 << 22)
++#define AST_ADC_CTRL_CH5_EN (0x1 << 21)
++#define AST_ADC_CTRL_CH4_EN (0x1 << 20)
++#define AST_ADC_CTRL_CH3_EN (0x1 << 19)
++#define AST_ADC_CTRL_CH2_EN (0x1 << 18)
++#define AST_ADC_CTRL_CH1_EN (0x1 << 17)
++#define AST_ADC_CTRL_CH0_EN (0x1 << 16)
++
++#if defined(CONFIG_ARCH_AST2300)
++#define AST_ADC_CTRL_COMPEN_CLR (0x1 << 6)
++#define AST_ADC_CTRL_COMPEN (0x1 << 5)
++#elif defined(CONFIG_ARCH_AST2400)
++#define AST_ADC_CTRL_COMPEN (0x1 << 4)
++#elif defined(CONFIG_ARCH_AST2500)
++#define AST_ADC_CTRL_INIT_RDY (0x1 << 8)
++#define AST_ADC_CTRL_COMPEN (0x1 << 5)
++#else
++#err "ERROR define COMPEN ADC"
++#endif
++
++#if defined(CONFIG_ARCH_AST1010)
++#define AST_ADC_CTRL_OTP (0x1 << 3)
++#define AST_ADC_CTRL_PWR_DWN (0x1 << 2)
++#define AST_ADC_CTRL_TEST (0x1 << 1)
++#endif
++
++#define AST_ADC_CTRL_NORMAL (0x7 << 1)
++
++#define AST_ADC_CTRL_EN (0x1)
++
++
++/* AST_ADC_IER : 0x04 - Interrupt Enable and Interrupt status */
++#define AST_ADC_IER_CH15 (0x1 << 31)
++#define AST_ADC_IER_CH14 (0x1 << 30)
++#define AST_ADC_IER_CH13 (0x1 << 29)
++#define AST_ADC_IER_CH12 (0x1 << 28)
++#define AST_ADC_IER_CH11 (0x1 << 27)
++#define AST_ADC_IER_CH10 (0x1 << 26)
++#define AST_ADC_IER_CH9 (0x1 << 25)
++#define AST_ADC_IER_CH8 (0x1 << 24)
++#define AST_ADC_IER_CH7 (0x1 << 23)
++#define AST_ADC_IER_CH6 (0x1 << 22)
++#define AST_ADC_IER_CH5 (0x1 << 21)
++#define AST_ADC_IER_CH4 (0x1 << 20)
++#define AST_ADC_IER_CH3 (0x1 << 19)
++#define AST_ADC_IER_CH2 (0x1 << 18)
++#define AST_ADC_IER_CH1 (0x1 << 17)
++#define AST_ADC_IER_CH0 (0x1 << 16)
++#define AST_ADC_STS_CH15 (0x1 << 15)
++#define AST_ADC_STS_CH14 (0x1 << 14)
++#define AST_ADC_STS_CH13 (0x1 << 13)
++#define AST_ADC_STS_CH12 (0x1 << 12)
++#define AST_ADC_STS_CH11 (0x1 << 11)
++#define AST_ADC_STS_CH10 (0x1 << 10)
++#define AST_ADC_STS_CH9 (0x1 << 9)
++#define AST_ADC_STS_CH8 (0x1 << 8)
++#define AST_ADC_STS_CH7 (0x1 << 7)
++#define AST_ADC_STS_CH6 (0x1 << 6)
++#define AST_ADC_STS_CH5 (0x1 << 5)
++#define AST_ADC_STS_CH4 (0x1 << 4)
++#define AST_ADC_STS_CH3 (0x1 << 3)
++#define AST_ADC_STS_CH2 (0x1 << 2)
++#define AST_ADC_STS_CH1 (0x1 << 1)
++#define AST_ADC_STS_CH0 (0x1)
++
++/* AST_ADC_VGA : 0x08 - VGA Detect Control */
++#define AST_ADC_VGA_EN (0x1 << 16)
++#define AST_ADC_VGA_DIV_MASK (0x3ff)
++
++/* AST_ADC_CLK : 0x0c - ADC CLK Control */
++#define AST_ADC_CLK_PRE_DIV_MASK (0x7fff << 17)
++#define AST_ADC_CLK_PRE_DIV (0x1 << 17)
++#define AST_ADC_CLK_INVERT (0x1 << 16) //only for ast2300
++#define AST_ADC_CLK_DIV_MASK (0x3ff)
++
++#define AST_ADC_H_CH_MASK (0x3ff << 16)
++#define AST_ADC_L_CH_MASK (0x3ff)
++
++#define AST_ADC_H_BOUND (0x3ff << 16)
++#define AST_ADC_L_BOUND (0x3ff)
++
++#define AST_ADC_HYSTER_EN (0x1 << 31)
++
++#if defined(CONFIG_ARCH_AST2500)
++/* AST_ADC_CH16 : 0xD0 - */
++/* AST_ADC_CH17 : 0xD4 - */
++#define AST_TEMP_CH_RDY (0x1 << 31)
++#define AST_GET_TEMP_A_MASK(x) ((x >>16) & 0xfff)
++#define AST_TEMP_CH_EN (0x1 << 15)
++#define AST_GET_TEMP_B_MASK(x) (x & 0xfff)
++
++
++#endif
++
++#endif /* __ASM_ARCH_REGS_ADC_H */
+diff --git a/arch/arm/plat-aspeed/include/plat/regs-ast1070-intc.h b/arch/arm/plat-aspeed/include/plat/regs-ast1070-intc.h
+new file mode 100644
+index 0000000..00dd1cb
+--- /dev/null
++++ b/arch/arm/plat-aspeed/include/plat/regs-ast1070-intc.h
+@@ -0,0 +1,42 @@
++/* arch/arm/mach-aspeed/include/mach/regs-intr.h
++ *
++ * Copyright (C) 2012-2020 ASPEED Technology Inc.
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * History :
++ * 1. 2012/08/15 Ryan Chen Create
++ *
++********************************************************************************/
++#ifndef __ASPEED_AST1070_INTR_H
++#define __ASPEED_AST1070_INTR_H 1
++
++#include <asm/io.h>
++#include <mach/platform.h>
++#include <mach/irqs.h>
++
++/*
++ * VIC Register (VA)
++ */
++
++#define VIC_BASE_VA(x) IO_ADDRESS2(AST_C0_VIC_BASE + (0x10000*x))
++
++#define AST_IRQ_STS(x) (VIC_BASE_VA(x) + 0x00)
++#define AST_RAW_STS(x) (VIC_BASE_VA(x) + 0x08)
++#define AST_INTR_EN(x) (VIC_BASE_VA(x) + 0x10)
++#define AST_INTR_DIS(x) (VIC_BASE_VA(x) + 0x14)
++#define AST_INTR_SENSE(x) (VIC_BASE_VA(x) + 0x24)
++#define AST_INTR_BOTH_EDGE(x) (VIC_BASE_VA(x) + 0x28)
++#define AST_INTR_EVENT(x) (VIC_BASE_VA(x) + 0x2C)
++
++#define IRQ_SET_LEVEL_TRIGGER(x,irq_no) *((volatile unsigned long*)AST_INTR_SENSE(x)) |= 1 << (irq_no)
++#define IRQ_SET_EDGE_TRIGGER(x,irq_no) *((volatile unsigned long*)AST_INTR_SENSE(x)) &= ~(1 << (irq_no))
++#define IRQ_SET_RISING_EDGE(x,irq_no) *((volatile unsigned long*)AST_INTR_EVENT(x)) |= 1 << (irq_no)
++#define IRQ_SET_FALLING_EDGE(x,irq_no) *((volatile unsigned long*)AST_INTR_EVENT(x)) &= ~(1 << (irq_no))
++#define IRQ_SET_HIGH_LEVEL(x,irq_no) *((volatile unsigned long*)AST_INTR_EVENT(x)) |= 1 << (irq_no)
++#define IRQ_SET_LOW_LEVEL(x,irq_no) *((volatile unsigned long*)AST_INTR_EVENT(x)) &= ~(1 << (irq_no))
++
++
++#endif
+diff --git a/arch/arm/plat-aspeed/include/plat/regs-ast1070-lpc.h b/arch/arm/plat-aspeed/include/plat/regs-ast1070-lpc.h
+new file mode 100644
+index 0000000..22f8475
+--- /dev/null
++++ b/arch/arm/plat-aspeed/include/plat/regs-ast1070-lpc.h
+@@ -0,0 +1,117 @@
++/* arch/arm/plat-aspeed/include/mach/regs-lpc.h
++ *
++ * Copyright (c) 2012 ASPEED Technology Inc. <ryan_chen@aspeedtech.com>
++ * http://www.aspeedtech.com/
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * ASPEED LPC Controller
++*/
++
++#ifndef __AST1070_LPC_H_
++#define __AST1070_LPC_H_
++
++#define AST_LPC_HICR0 0x000
++#define AST_LPC_HICR1 0x004
++#define AST_LPC_HICR2 0x008
++#define AST_LPC_HICR3 0x00C
++#define AST_LPC_HICR4 0x010
++#define AST_LPC_LADR3H 0x014
++#define AST_LPC_LADR3L 0x018
++#define AST_LPC_LADR12H 0x01C
++#define AST_LPC_LADR12L 0x020
++#define AST_LPC_IDR1 0x024
++#define AST_LPC_IDR2 0x028
++#define AST_LPC_IDR3 0x02C
++#define AST_LPC_ODR1 0x030
++#define AST_LPC_ODR2 0x034
++#define AST_LPC_ODR3 0x038
++#define AST_LPC_STR1 0x03C
++#define AST_LPC_STR2 0x040
++#define AST_LPC_STR3 0x044
++////
++#define AST_LPC_SIRQCR0 0x048
++#define AST_LPC_SIRQCR1 0x04C
++#define AST_LPC_SIRQCR2 0x050
++#define AST_LPC_SIRQCR3 0x06C
++////
++#define AST_LPC_ADR1 0x070
++#define AST_LPC_IRQ1 0x074
++#define AST_LPC_ADR2 0x078
++#define AST_LPC_IRQ2 0x07C
++#define AST_LPC_ADR3 0x080
++#define AST_LPC_IRQ3 0x084
++
++#define AST_LPC_DEV_ADDRM0 0x100
++#define AST_LPC_DEV_ADDRM1 0x104
++#define AST_LPC_DEV_ADDRM2 0x108
++#define AST_LPC_DEV_ADDRM3 0x10C
++#define AST_LPC_DEV_ADDR0 0x110
++#define AST_LPC_DEV_ADDR1 0x114
++#define AST_LPC_DEV_ADDR2 0x118
++#define AST_LPC_DEV_ADDR3 0x11C
++#define AST_LPC_DEC_ADDR0 0x120
++#define AST_LPC_DEC_ADDR1 0x124
++#define AST_LPC_DEC_RANGE0 0x128
++#define AST_LPC_DEC_RANGE1 0x12C
++
++#define AST_LPC_MBXDAT0 0x180
++#define AST_LPC_MBXDAT1 0x184
++#define AST_LPC_MBXDAT2 0x188
++#define AST_LPC_MBXDAT3 0x18C
++#define AST_LPC_MBXDAT4 0x190
++#define AST_LPC_MBXDAT5 0x194
++#define AST_LPC_MBXDAT6 0x198
++#define AST_LPC_MBXDAT7 0x19C
++#define AST_LPC_MBXDAT8 0x1A0
++#define AST_LPC_MBXDAT9 0x1A4
++#define AST_LPC_MBXDATA 0x1A8
++#define AST_LPC_MBXDATB 0x1AC
++#define AST_LPC_MBXDATC 0x1B0
++#define AST_LPC_MBXDATD 0x1B4
++#define AST_LPC_MBXDATE 0x1B8
++#define AST_LPC_MBXDATF 0x1BC
++
++#define AST_LPC_MBXSTS0 0x1C0
++#define AST_LPC_MBXSTS1 0x1C4
++
++#define AST_LPC_MBXBICR 0x1C8
++#define AST_LPC_MBXHICR 0x1CC
++#define AST_LPC_MBXBIE0 0x1D0
++#define AST_LPC_MBXBIE1 0x1D4
++#define AST_LPC_MBXHIE0 0x1D8
++#define AST_LPC_MBXHIE1 0x1DC
++
++#define AST_LPC_PIN_MON 0x200
++#define AST_LPC_SIRQ_CTRL 0x208
++#define AST_LPC_INT_STS 0x20C
++#define AST_LPC_CTRL_STS 0x210
++#define AST_LPC_PME 0x218
++#define AST_LPC_SMI 0x21C
++#define AST_LPC_80H_ADDR0 0x220
++#define AST_LPC_80H_ADDR1 0x224
++#define AST_LPC_80H_DATA 0x228
++#define AST_LPC_80H_CTRL 0x22C
++
++#define AST_LPC_CHIP_VER 0x240
++#define AST_LPC_CHIP_REVER 0x244
++#define AST_LPC_BMC_SCH0 0x248
++#define AST_LPC_BMC_SCH1 0x24C
++#define AST_LPC_NODE_SCH0 0x250
++#define AST_LPC_NODE_SCH1 0x254
++#define AST_LPC_NODE_SCH2 0x258
++#define AST_LPC_NODE_SCH3 0x25C
++
++
++
++
++
++
++
++
++
++
++
++#endif
+diff --git a/arch/arm/plat-aspeed/include/plat/regs-ast1070-scu.h b/arch/arm/plat-aspeed/include/plat/regs-ast1070-scu.h
+new file mode 100644
+index 0000000..a5a4f95
+--- /dev/null
++++ b/arch/arm/plat-aspeed/include/plat/regs-ast1070-scu.h
+@@ -0,0 +1,95 @@
++/* arch/arm/mach-aspeed/include/mach/regs-ast1070-scu.h
++ *
++ * Copyright (C) 2012-2020 ASPEED Technology Inc.
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * History :
++ * 1. 2013/05/15 Ryan Chen Create
++ *
++********************************************************************************/
++#ifndef __AST1070_SCU_H
++#define __AST1070_SCU_H 1
++
++/*
++ * Register for SCU
++ * */
++#define AST1070_SCU_PROTECT 0x00 /* protection key register */
++#define AST1070_SCU_RESET 0x04 /* system reset control register */
++#define AST1070_SCU_MISC_CTRL 0x08 /* misc control register */
++#define AST1070_SCU_UART_MUX 0x0C /* UART Mux control register */
++#define AST1070_SCU_SPI_USB_MUX 0x10 /* SPI/USB Mux control register */
++#define AST1070_SCU_IO_DRIVING 0x14 /* I/O Driving Strength control register */
++#define AST1070_SCU_IO_PULL 0x18 /* I/O Internal Pull control register */
++#define AST1070_SCU_IO_SLEW 0x1C /* I/O Slew Rate control register */
++#define AST1070_SCU_IO_SCHMITT 0x20 /* I/O Schmitt Trigger Control register */
++#define AST1070_SCU_IO_SELECT 0x24 /* I/O Port Selection register */
++#define AST1070_SCU_TRAP 0x30 /* HW TRAPPING register */
++#define AST1070_SCU_CHIP_ID 0x34 /* CHIP ID register */
++
++
++/* AST1070_SCU_PROTECT: 0x00 - protection key register */
++#define AST1070_SCU_PROTECT_UNLOCK 0x16881A78
++
++/* AST1070_SCU_RESET :0x04 - system reset control register */
++#define SCU_RESET_DMA (0x1 << 11)
++#define SCU_RESET_SPI_M (0x1 << 10)
++#define SCU_RESET_SPI_S (0x1 << 9)
++#define SCU_RESET_N4_LPC (0x1 << 8)
++#define SCU_RESET_N3_LPC (0x1 << 7)
++#define SCU_RESET_N2_LPC (0x1 << 6)
++#define SCU_RESET_N1_LPC (0x1 << 5)
++#define SCU_RESET_I2C (0x1 << 4)
++#define SCU_RESET_N4_UART (0x1 << 3)
++#define SCU_RESET_N3_UART (0x1 << 2)
++#define SCU_RESET_N2_UART (0x1 << 1)
++#define SCU_RESET_N1_UART (0x1 << 0)
++
++/* AST1070_SCU_MISC_CTRL 0x08 misc control register */
++#define SCU_DMA_M_S_MASK (0x3 << 9)
++
++#define SCU_DMA_SLAVE_EN (0x1 << 10)
++#define SCU_DMA_MASTER_EN (0x1 << 9)
++
++/* AST1070_SCU_UART_MUX 0x0C UART Mux control register */
++#define UART_MUX_MASK(x) (0xff << (x*8))
++
++#define BMC_UART_CTRL(x) (6 + (x*8))
++#define BMC_UART_CTRL_MASK(x) (0x3 << (6 + (x*8)))
++#define SET_BMC_UART_CTRL(x,v) ((v) << (6 + (x*8)))
++#define BMC_UART_FROM_N1 0
++#define BMC_UART_FROM_PAD1 1
++#define BMC_UART_FROM_NONE 2
++
++#define NODE_UART_CTRL(x) (3 + (x*8))
++#define NODE_UART_CTRL_MASK(x) (0x7 << (3 + (x*8)))
++#define SET_NODE_UART_CTRL(x,v) ((v) << (3 + (x*8)))
++#define NODE_UART_FROM_BMC 0
++#define NODE_UART_FROM_PAD1 1
++#define NODE_UART_FROM_PAD2 2
++#define NODE_UART_FROM_PAD3 3
++#define NODE_UART_FROM_PAD4 4
++#define NODE_UART_FROM_NONE 5
++#define NODE_UART_FROM_N2 6
++#define NODE_UART_FROM_N3 7
++
++
++#define SCU_UART_IO_PAD(x) (x*8)
++#define UART_IO_PAD_MASK(x) (0x7 << (x*8))
++#define SET_UART_IO_PAD(x,v) ((v) << (x*8))
++#define PAD_FROM_NONE 0
++#define PAD_FROM_N1_UART 1
++#define PAD_FROM_N2_UART 2
++#define PAD_FROM_N3_UART 3
++#define PAD_FROM_N4_UART 4
++#define PAD_FROM_BMC 5
++
++/* AST1070_SCU_TRAP 0x30 HW TRAPPING register */
++#define TRAP_DEVICE_SLAVE (0x1 << 2)
++#define TRAP_MULTI_MASTER (0x1 << 1)
++#define TRAP_LPC_PLUS_MODE (0x1 << 0)
++
++#endif
++
+diff --git a/arch/arm/plat-aspeed/include/plat/regs-crt.h b/arch/arm/plat-aspeed/include/plat/regs-crt.h
+new file mode 100644
+index 0000000..6749285
+--- /dev/null
++++ b/arch/arm/plat-aspeed/include/plat/regs-crt.h
+@@ -0,0 +1,183 @@
++/* linux/include/asm-arm/arch-aspeed/regs-crt.h
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++*/
++
++#ifndef ___ASM_ARCH_REGS_CRT_H
++#define ___ASM_ARCH_REGS_CRT_H
++
++/* CRT control registers */
++
++
++//////////////////////////////////////////////////////////////////
++#define AST3000_VGA1_CTLREG 0x00
++#define AST3000_VGA1_CTLREG2 0x04
++#define AST3000_VGA1_STATUSREG 0x08
++#define AST3000_VGA1_PLL 0x0C
++#define AST3000_VGA1_HTREG 0x10
++#define AST3000_VGA1_HRREG 0x14
++#define AST3000_VGA1_VTREG 0x18
++#define AST3000_VGA1_VRREG 0x1C
++#define AST3000_VGA1_STARTADDR 0x20
++#define AST3000_VGA1_OFFSETREG 0x24
++#define AST3000_VGA1_THRESHOLD 0x28
++
++#define AST3000_VGA2_CTLREG 0x60
++#define AST3000_VGA2_CTLREG2 0x64
++#define AST3000_VGA2_STATUSREG 0x68
++#define AST3000_VGA2_PLL 0x6C
++#define AST3000_VGA2_HTREG 0x70
++#define AST3000_VGA2_HRREG 0x74
++#define AST3000_VGA2_VTREG 0x78
++#define AST3000_VGA2_VRREG 0x7C
++#define AST3000_VGA2_STARTADDR 0x80
++#define AST3000_VGA2_OFFSETREG 0x84
++#define AST3000_VGA2_THRESHOLD 0x88
++//////////////////////////////////////////////////////////////////
++
++//0x00 ~ 0x5F Reserved - FB0
++//0x60 ~ 90 FB1
++#define AST_CRT_CTRL1 0x60
++#define AST_CRT_CTRL2 0x64
++#define AST_CRT_STS 0x68
++#define AST_CRT_PLL 0x6C
++#define AST_CRT_HORIZ0 0x70
++#define AST_CRT_HORIZ1 0x74
++#define AST_CRT_VERTI0 0x78
++#define AST_CRT_VERTI1 0x7C
++#define AST_CRT_ADDR 0x80
++#define AST_CRT_OFFSET 0x84
++#define AST_CRT_THROD 0x88
++#define AST_CRT_XSCALING 0x8C
++//0x8c Reserved
++//0x90 ~ Cursor
++#define AST_CRT_CURSOR0 0x90
++#define AST_CRT_CURSOR1 0x94
++#define AST_CRT_CURSOR2 0x98
++#define AST_CRT_UADDR 0x9C
++//0x9c Reserved
++//0xA0 ~ OSD
++#define AST_CRT_OSDH 0xA0
++#define AST_CRT_OSDV 0xA4
++#define AST_CRT_OSDADDR 0xA8
++#define AST_CRT_OSDDISP 0xAC
++#define AST_CRT_OSDTHROD 0xB0
++#define AST_CRT_VADDR 0xB4
++
++//0xb4 Reserved
++#define AST_CRT_STS_V 0xB8
++#define AST_CRT_SCRATCH 0xBC
++#define AST_CRT_X 0xC0
++//0xC4
++#define AST_CRT_OSD_COLOR 0xE0
++
++/* AST_CRT_CTRL1 - 0x60 : CRT Control Register I */
++#define CRT_CTRL_VERTICAL_INTR_STS (0x1 << 31)
++#define CRT_CTRL_VERTICAL_INTR_EN (0x1 << 30)
++//24~28 reserved
++#define CRT_CTRL_DESK_OFF (0x1 << 23)
++#define CRT_CTRL_FSYNC_OFF (0x1 << 22)
++#define CRT_CTRL_FSYNC_POLARITY (0x1 << 21)
++#define CRT_CTRL_SCREEN_OFF (0x1 << 20)
++#define CRT_CTRL_VSYNC_OFF (0x1 << 19)
++#define CRT_CTRL_HSYNC_OFF (0x1 << 18)
++#define CRT_CTRL_VSYNC_POLARITY (0x1 << 17)
++#define CRT_CTRL_HSYNC_POLARITY (0x1 << 16)
++#define CRT_CTRL_TILE_EN (0x1 << 15)
++#define CRT_CTRL_HDTVYUV_EN (0x1 << 14)
++#define CRT_CTRL_YUV_FORMAT(x) (x << 12)
++#define YUV_MODE0 0
++#define YUV_MODE1 1
++#define YUV_MODE2 2
++// bit 11 reserved
++#define CRT_CTRL_HW_CURSOR_FORMAT (0x1 << 10) // 0: XRGB4444, 1:ARGB4444
++#define CRT_CTRL_FORMAT_MASK (0x7 << 7)
++#define CRT_CTRL_FORMAT(x) (x << 7)
++#define COLOR_RGB565 (0)
++#define COLOR_YUV444 (1)
++#define COLOR_XRGB8888 (2)
++#define COLOR_YUV444_2RGB (5)
++#define CRT_CTRL_ENVEFLIP (0x1 << 6)
++//bit 5
++#define CRT_CTRL_SCALING_X (0x1 << 4)
++#define CRT_CTRL_INTER_TIMING (0x1 << 3)
++#define CRT_CTRL_OSD_EN (0x1 << 2)
++#define CRT_CTRL_HW_CURSOR_EN (0x1 << 1)
++#define CRT_CTRL_GRAPHIC_EN (0x1)
++
++/*AST_CRT_CTRL2 - 0x64 : CRT Control Register II */
++#define CRT_CTRL_VLINE_NUM_MASK (0xfff << 20)
++#define CRT_CTRL_VLINE_NUM(x) (x << 20)
++#define CRT_CTRL_TESTDVO_MASK (0xfff << 8)
++#define CRT_CTRL_TESTDVO(x) (x << 8)
++#define CRT_CTRL_DVO_EN (0x1 << 7)
++#define CRT_CTRL_DVO_DUAL (0x1 << 6)
++#define CRT_CTRL_FIFO_FULL (0x1 << 5)
++#define CRT_CTRL_TEST_EN (0x1 << 4)
++#define CRT_CTRL_SIGN_DON (0x1 << 3)
++#define CRT_CTRL_SIGN_TRIGGER (0x1 << 2)
++#define CRT_CTRL_DAC_TEST_EN (0x1 << 1)
++#define CRT_CTRL_DAC_PWR_EN (0x1)
++
++/* AST_CRT_STS - 0x68 : CRT Status Register */
++#define CRT_STS_RED_RB(x) (x << 24)
++#define CRT_STS_GREEN_RB(x) (x << 16)
++#define CRT_STS_BLUE_RB(x) (x << 8)
++#define CRT_STS_DAC_SENSE_EN (0x1 << 7)
++//6 reserved
++#define CRT_STS_ODDFIELD_SYNC (0x1 << 5)
++#define CRT_STS_ODDFIELD (0x1 << 4)
++#define CRT_STS_HDISPLAY_RB (0x1 << 3)
++#define CRT_STS_HRETRACE_RB (0x1 << 2)
++#define CRT_STS_VDISPLAY_RB (0x1 << 1)
++#define CRT_STS_VRETRACE_RB (0x1)
++
++/* AST_CRT_PLL - 0x6C : CRT Video PLL Setting Register */
++#define CRT_PLL_DAC_MODE_SENSE(x) (x << 30)
++#define CRT_PLL_DAC_SENSE(x) (x << 28)
++#define CRT_PLL_BYPASS (0x1 << 17)
++#define CRT_PLL_PWR_DWN (0x1 << 16)
++#define CRT_PLL_POST_DIVIDER(x) (((x & 0x3) << 13) | (((x >> 2) & 0xf) << 18) | (((x >> 6) & 0x1) << 23) | (((x >> 7) & 0x1) << 22))
++#define CRT_PLL_DENUM(x) (x << 8)
++#define CRT_PLL_NUM(x) (x)
++
++/* AST_CRT_HORIZ0 - 0x70 : CRT Horizontal Total & Display Enable End Register */
++#define CRT_H_TOTAL(x) (x)
++#define CRT_H_DE(x) (x << 16)
++
++/* AST_ 0x74 : CRT Horizontal Retrace Start & End Register */
++#define CRT_H_RS_START(x) (x)
++#define CRT_H_RS_END(x) (x << 16)
++
++/* AST_CRT_ - 0x78 : CRT Horizontal Total & Display Enable End Register */
++#define CRT_V_TOTAL(x) (x)
++#define CRT_V_DE(x) (x << 16)
++
++/* AST_ 0x7C : CRT Horizontal Retrace Start & End Register */
++#define CRT_V_RS_START(x) (x)
++#define CRT_V_RS_END(x) (x << 16)
++
++/* AST_CRT_OFFSET - 0x84 : CRT Display Offset & Terminal Count Register */
++#define CRT_DISP_OFFSET(x) (x)
++#define CRT_TERM_COUNT(x) (x << 16)
++
++/* AST_CRT_THROD - 0x88 : CRT Threadhold Register */
++#define CRT_THROD_LOW(x) (x)
++#define CRT_THROD_HIGH(x) (x << 8)
++#define CRT_THROD_X_SCALING(x) (x << 16)
++#define CRT_THROD_CRT2Y (0x1 << 20)
++
++/* AST_CRT_XSCALING - 0x8C : CRT X Scaling-up Factor Register */
++
++
++/* AST_CRT_CURSOR0 : 0x90 - CRT Hardware Cursor X & Y Offset Register */
++#define CRT_HW_CURSOR_X_OFFSET(x) (x)
++#define CRT_HW_CURSOR_Y_OFFSET(x) (x << 16)
++
++/* AST_CRT_CURSOR1 : 0x94 - CRT Hardware Cursor X & Y Position Register */
++#define CRT_HW_CURSOR_X_POSITION(x) (x)
++#define CRT_HW_CURSOR_Y_POSITION(x) (x << 16)
++
++#endif /* ___ASM_ARCH_REGS_CRT_H */
+diff --git a/arch/arm/plat-aspeed/include/plat/regs-fmc.h b/arch/arm/plat-aspeed/include/plat/regs-fmc.h
+new file mode 100644
+index 0000000..25c3046
+--- /dev/null
++++ b/arch/arm/plat-aspeed/include/plat/regs-fmc.h
+@@ -0,0 +1,112 @@
++/* arch/arm/plat-aspeed/include/mach/regs-smc.h
++ *
++ * Copyright (c) 2012 ASPEED Technology Inc. <ryan_chen@aspeedtech.com>
++ * http://www.aspeedtech.com/
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * ASPEED Static memory ctrol
++*/
++
++#ifndef __ASM_ARCH_REGS_FMC_H
++#define __ASM_ARCH_REGS_FMC_H __FILE__
++
++#define FMC_CE_TYPE 0x00
++#define FMC_CE_CTRL 0x04
++#define FMC_INTR_CTRL 0x08
++#define FMC_CE0_CTRL 0x10
++#define FMC_CE1_CTRL 0x14
++#define FMC_CE2_CTRL 0x18
++#define FMC_CE3_CTRL 0x1c
++#define FMC_CE4_CTRL 0x20
++
++#define FMC_CE0_ADDR 0x30
++#define FMC_CE1_ADDR 0x34
++#define FMC_CE2_ADDR 0x38
++#define FMC_CE3_ADDR 0x3c
++#define FMC_CE4_ADDR 0x40
++
++#define FMC_MISC_CTRL1 0x50
++#define FMC_MISC_CTRL2 0x54
++#define FMC_NAND_CTRL 0x58
++#define FMC_NAND_ECC 0x5c
++#define FMC_NAND_ECC_CK1 0x60
++#define FMC_NAND_ECC_CK2 0x64
++#define FMC_NAND_ECC_CK3 0x68
++#define FMC_NAND_ECC_GEN1 0x6c
++#define FMC_NAND_ECC_GEN2 0x70
++#define FMC_NAND_ECC_GEN3 0x74
++#define FMC_NAND_ECC_CK_R1 0x78
++#define FMC_NAND_ECC_CK_R2 0x7c
++#define FMC_DMA_CTRL 0x80
++#define FMC_DMA_FLASH_ADDR 0x84
++#define FMC_DMA_DRAM_ADDR 0x88
++#define FMC_DMA_LEN 0x8C
++#define FMC_CHECK_SUM 0x90
++#define FMC_SPI_TIMING 0x94
++
++/* FMC_CE_TYPE 0x00 */
++#define FMC_SET_WRITE_CS(x) (0x1 << (x+16))
++#define FMC_MASK_TYPE_CS(x) (~(0x3 << (2*x)))
++#define FMC_SET_TYPE_NAND_CS(x) (0x1 << (2*x))
++#define FMC_SET_TYPE_SPI_CS(x) (0x2 << (2*x))
++
++#define FMC_TYPE_NOR 0
++#define FMC_TYPE_NAND 1
++#define FMC_TYPE_SPI 2
++
++
++/* FMC_CE0_CTRL for NAND 0x10, 0x14, 0x18, 0x1c, 0x20 */
++#define NAND_T_WEH(x) (x << 28)
++#define NAND_T_WEL(x) (x << 24)
++#define NAND_T_REH(x) (x << 20)
++#define NAND_T_REL(x) (x << 16)
++#define NAND_T_CESH(x) (x << 12)
++#define NAND_T_WTR(x) (x << 10)
++#define NAND_T_R(x) (x << 4)
++#define NAND_ADDR_CYCLE (1 << 3)
++#define NAND_CE_ACTIVE (1 << 2)
++#define NAND_OP_MODE (1 << 0)
++
++/* FMC_CE0_CTRL for SPI 0x10, 0x14, 0x18, 0x1c, 0x20 */
++#define SPI_IO_MODE(x) (x << 28)
++#define SPI_CE_WIDTH(x) (x << 24)
++#define SPI_CMD_DATA(x) (x << 16)
++#define SPI_DUMMY_CMD (1 << 15)
++#define SPI_DUMMY_HIGH (1 << 14)
++#define SPI_CLK_DIV (1 << 13)
++#define SPI_ADDR_CYCLE (1 << 13)
++#define SPI_CMD_MERGE_DIS (1 << 12)
++#define SPI_T_CLK (x << 8)
++#define SPI_DUMMY_LOW (x << 6)
++#define SPI_LSB_FIRST_CTRL (1 << 5)
++#define SPI_CPOL_1 (1 << 4)
++#define SPI_DUAL_DATA (1 << 3)
++#define SPI_CE_INACTIVE (1 << 2)
++#define SPI_CMD_MODE (x)
++#define SPI_CMD_NOR_R_MODE 0
++#define SPI_CMD_FAST_R_MODE 1
++#define SPI_CMD_NOR_W_MODE 2
++#define SPI_CMD_USER_MODE 3
++
++
++/* FMC_CE0_ADDR 0x30 0x34 0x38 0x3c 0x40*/
++#define FMC_END_ADDR(x) (x << 24)
++#define FMC_START_ADDR(x) (x << 16)
++
++
++/* FMC_MISC_CTRL1 0x50 */
++#define READ_BUSY_PIN_STS (1 << 3)
++
++/* FMC_NAND_ECC 0x5c */
++#define NAND_ECC_RESET (1 << 3)
++#define NAND_ECC_ENABLE (1 << 2)
++#define NAND_ECC_DATA_BLK_512 2
++#define NAND_ECC_DATA_BLK_256 1
++#define NAND_ECC_DATA_BLK_128 0
++
++
++
++#endif /* __ASM_ARCH_REGS_FMC_H */
+diff --git a/arch/arm/plat-aspeed/include/plat/regs-gpio.h b/arch/arm/plat-aspeed/include/plat/regs-gpio.h
+new file mode 100644
+index 0000000..d6e7de0
+--- /dev/null
++++ b/arch/arm/plat-aspeed/include/plat/regs-gpio.h
+@@ -0,0 +1,338 @@
++/* arch/arm/plat-aspeed/include/mach/regs-gpio.h
++ *
++ * Copyright (c) 2012 ASPEED Technology Inc. <ryan_chen@aspeedtech.com>
++ * http://www.aspeedtech.com/
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * ASPEED I2C Controller
++*/
++
++#ifndef __ASM_ARCH_REGS_GPIO_H
++#define __ASM_ARCH_REGS_GPIO_H __FILE__
++
++/*AST GPIO Register Definition */
++#define AST_GPIO_DATA 0x000
++#define AST_GPIO_DIR 0x004
++#define AST_GPIO_INT_EN 0x008
++#define AST_GPIO_INT_SEN_T0 0x00c
++#define AST_GPIO_INT_SEN_T1 0x010
++#define AST_GPIO_INT_SEN_T2 0x014
++#define AST_GPIO_INT_STS 0x018
++#define AST_GPIO_RST_TOR 0x01c
++#define AST_EXT_GPIO_DATA 0x020
++#define AST_EXT_GPIO_DIR 0x024
++#define AST_EXT_GPIO_INT_EN 0x028
++#define AST_EXT_GPIO_INT_SEN_T0 0x02c
++#define AST_EXT_GPIO_INT_SEN_T1 0x030
++#define AST_EXT_GPIO_INT_SEN_T2 0x034
++#define AST_EXT_GPIO_INT_STS 0x038
++#define AST_EXT_GPIO_RST_TOR 0x03c
++#define AST_GPIO_DEBOUNCE_SET1 0x040 //A/B/C/D
++#define AST_GPIO_DEBOUNCE_SET2 0x044 //A/B/C/D
++#define AST_EXT_GPIO_DEBOUNCE_SET1 0x048 //E/F/G/H
++#define AST_EXT_GPIO_DEBOUNCE_SET2 0x04C //E/F/G/H
++#define AST_DEBOUNCE_TIME_SET1 0x050
++#define AST_DEBOUNCE_TIME_SET2 0x054
++#define AST_DEBOUNCE_TIME_SET3 0x058
++#define AST_GPIO_CMD_S0 0x060
++#define AST_GPIO_CMD_S1 0x064
++#define AST_EXT_GPIO_CMD_S0 0x068
++#define AST_EXT_GPIO_CMD_S1 0x06C
++#define AST_SIMPLE_GPIO_DATA0 0x070
++#define AST_SIMPLE_GPIO_DIR0 0x074
++#define AST_SIMPLE_GPIO_DATA1 0x078
++#define AST_SIMPLE_GPIO_DIR1 0x07C
++#define AST_SIMPLE_GPIO_DATA2 0x080
++#define AST_SIMPLE_GPIO_DIR2 0x084
++#define AST_SIMPLE_GPIO_DATA3 0x088
++#define AST_SIMPLE_GPIO_DIR3 0x08C
++#define AST_SIMPLE_GPIO0_CMD_S0 0x090
++#define AST_SIMPLE_GPIO0_CMD_S1 0x094
++#define AST_SIMPLE_GPIO0_INT_EN 0x098
++#define AST_SIMPLE_GPIO0_INT_SEN_T0 0x09c
++#define AST_SIMPLE_GPIO0_INT_SEN_T1 0x0a0
++#define AST_SIMPLE_GPIO0_INT_SEN_T2 0x0a4
++#define AST_SIMPLE_GPIO0_INT_STS 0x0a8
++#define AST_SIMPLE_GPIO0_RST_TOR 0x0ac
++#define AST_SIMPLE_GPIO0_DEBOUNCE_SET1 0x0b0
++#define AST_SIMPLE_GPIO0_DEBOUNCE_SET2 0x0b4
++#define AST_SIMPLE_GPIO0_INT_MASK 0x0b8
++#define AST_GPIO_DATA_READ 0x0c0
++#define AST_EXT_GPIO_DATA_READ 0x0c4
++#define AST_SIMPLE_GPIO0_DATA_READ 0x0c8
++#define AST_SIMPLE_GPIO1_DATA_READ 0x0cc
++#define AST_SIMPLE_GPIO2_DATA_READ 0x0d0
++#define AST_SIMPLE_GPIO3_DATA_READ 0x0d4
++#define AST_SIMPLE_GPIO4_DATA_READ 0x0d8
++#define AST_SIMPLE_GPIO1_CMD_S0 0x0e0
++#define AST_SIMPLE_GPIO1_CMD_S1 0x0e4
++#define AST_SIMPLE_GPIO1_INT_EN 0x0e8
++#define AST_SIMPLE_GPIO1_INT_SEN_T0 0x0ec
++#define AST_SIMPLE_GPIO1_INT_SEN_T1 0x0f0
++#define AST_SIMPLE_GPIO1_INT_SEN_T2 0x0f4
++#define AST_SIMPLE_GPIO1_INT_STS 0x0f8
++#define AST_SIMPLE_GPIO1_RST_TOR 0x0fc
++#define AST_SIMPLE_GPIO1_DEBOUNCE_SET1 0x100
++#define AST_SIMPLE_GPIO1_DEBOUNCE_SET2 0x104
++#define AST_SIMPLE_GPIO1_INT_MASK 0x108
++#define AST_SIMPLE_GPIO2_CMD_S0 0x110
++#define AST_SIMPLE_GPIO2_CMD_S1 0x114
++#define AST_SIMPLE_GPIO2_INT_EN 0x118
++#define AST_SIMPLE_GPIO2_INT_SEN_T0 0x11c
++#define AST_SIMPLE_GPIO2_INT_SEN_T1 0x120
++#define AST_SIMPLE_GPIO2_INT_SEN_T2 0x124
++#define AST_SIMPLE_GPIO2_INT_STS 0x128
++#define AST_SIMPLE_GPIO2_RST_TOR 0x12c
++#define AST_SIMPLE_GPIO2_DEBOUNCE_SET1 0x130
++#define AST_SIMPLE_GPIO2_DEBOUNCE_SET2 0x134
++#define AST_SIMPLE_GPIO2_INT_MASK 0x138
++#define AST_SIMPLE_GPIO3_CMD_S0 0x140
++#define AST_SIMPLE_GPIO3_CMD_S1 0x144
++#define AST_SIMPLE_GPIO3_INT_EN 0x148
++#define AST_SIMPLE_GPIO3_INT_SEN_T0 0x14c
++#define AST_SIMPLE_GPIO3_INT_SEN_T1 0x150
++#define AST_SIMPLE_GPIO3_INT_SEN_T2 0x154
++#define AST_SIMPLE_GPIO3_INT_STS 0x158
++#define AST_SIMPLE_GPIO3_RST_TOR 0x15c
++#define AST_SIMPLE_GPIO3_DEBOUNCE_SET1 0x160
++#define AST_SIMPLE_GPIO3_DEBOUNCE_SET2 0x164
++#define AST_SIMPLE_GPIO3_INT_MASK 0x168
++#define AST_SIMPLE_GPIO4_CMD_S0 0x170
++#define AST_SIMPLE_GPIO4_CMD_S1 0x174
++#define AST_SIMPLE_GPIO4_INT_EN 0x178
++#define AST_SIMPLE_GPIO4_INT_SEN_T0 0x17c
++#define AST_SIMPLE_GPIO4_INT_SEN_T1 0x180
++#define AST_SIMPLE_GPIO4_INT_SEN_T2 0x184
++#define AST_SIMPLE_GPIO4_INT_STS 0x188
++#define AST_SIMPLE_GPIO4_RST_TOR 0x18c
++#define AST_SIMPLE_GPIO4_DEBOUNCE_SET1 0x190
++#define AST_SIMPLE_GPIO4_DEBOUNCE_SET2 0x194
++#define AST_SIMPLE_GPIO4_INT_MASK 0x198
++#define AST_GPIO_INT_MASK 0x1d0
++#define AST_EXT_GPIO_INT_MASK 0x1d4
++#ifdef CONFIG_ARCH_AST1010
++#else
++#define AST_SIMPLE_GPIO_DATA4 0x1e0
++#define AST_SIMPLE_GPIO_DIR4 0x1e4
++#endif
++
++//Serial GPIO
++#define AST_SGPIO_DATA 0x200
++#define AST_SGPIO_INT_EN 0x204
++#define AST_SGPIO_INT_SEN_T0 0x208
++#define AST_SGPIO_INT_SEN_T1 0x20c
++#define AST_SGPIO_INT_SEN_T2 0x210
++#define AST_SGPIO_INT_STS 0x214
++#define AST_SGPIO_RST_TOR 0x218
++#define AST_EXT_SGPIO_DATA 0x21c
++#define AST_EXT_SGPIO_INT_EN 0x220
++#define AST_EXT_SGPIO_INT_SEN_T0 0x224
++#define AST_EXT_SGPIO_INT_SEN_T1 0x228
++#define AST_EXT_SGPIO_INT_SEN_T2 0x22c
++#define AST_EXT_SGPIO_INT_STS 0x230
++#define AST_EXT_SGPIO_RST_TOR 0x234
++#define AST_SGPIO_CTRL 0x254
++#define AST_SGPIO_DATA_READ 0x270
++#define AST_EXT_SGPIO_DAT 0x274
++
++//Serial GPIO Slave Monitor
++#define AST_SGPIO_SLAVE_DATA_INIT 0x300
++#define AST_SGPIO_SLAVE_DATA_TARGET 0x304
++#define AST_SGPIO_SLAVE_DATA_LOAD 0x308
++#define AST_SGPIO_SLAVE_INT_EN0 0x30c
++#define AST_SGPIO_SLAVE_INT_EN1 0x310
++#define AST_SGPIO_SLAVE_INT_EN2 0x314
++#define AST_SGPIO_SLAVE_INT_STS0 0x318
++#define AST_SGPIO_SLAVE_INT_STS1 0x31c
++#define AST_SGPIO_SLAVE_INT_STS2 0x320
++
++/**********************************************************************************/
++/* AST_GPIO_DATA - 0x000 : A/B/C/D Data Vale */
++#define GET_GPIOD_DATA(x) ((x&0xff000000) >> 24)
++#define SET_GPIOD_DATA(x) (x << 24)
++#define GET_GPIOD_PIN_DATA(x,pin) ((x >> (pin + 24)) & 1)
++#define SET_GPIOD_PIN_DATA(pin) (1<<(pin + 24))
++#define GET_GPIOC_DATA(x) ((x&0xff0000) >> 16)
++#define SET_GPIOC_DATA(x) (x << 16)
++#define GET_GPIOC_PIN_DATA(x,pin) ((x >> (pin + 16)) & 1)
++#define SET_GPIOC_PIN_DATA(pin) (1<<(pin + 16))
++#define GET_GPIOB_DATA(x) ((x&0xff00) >> 8)
++#define SET_GPIOB_DATA(x) (x << 8)
++#define GET_GPIOB_PIN_DATA(x,pin) ((x >> (pin + 8)) & 1)
++#define SET_GPIOB_PIN_DATA(pin) (1<<(pin + 8))
++#define GET_GPIOA_DATA(x) (x&0xff)
++#define SET_GPIOA_DATA(x) (x)
++#define GET_GPIOA_PIN_DATA(x,pin) ((x >> pin) & 1)
++#define SET_GPIOA_PIN_DATA(pin) (1<<pin)
++
++/* AST_GPIO_DIR - 0x004 : Direction */
++#define GET_GPIOD_DIR(x) ((x&0xff000000) >> 24)
++#define SET_GPIOD_DIR(x) (x << 24)
++#define GET_GPIOD_PIN_DIR(x,pin) ((x >> (pin + 24)) & 1)
++#define SET_GPIOD_PIN_DIR(pin) (1<<(pin + 24))
++#define GET_GPIOC_DIR(x) ((x&0xff0000) >> 16)
++#define SET_GPIOC_DIR(x) (x << 16)
++#define GET_GPIOC_PIN_DIR(x,pin) ((x >> (pin + 16)) & 1)
++#define SET_GPIOC_PIN_DIR(pin) (1<<(pin + 16))
++#define GET_GPIOB_DIR(x) ((x&0xff00) >> 8)
++#define SET_GPIOB_DIR(x) (x << 8)
++#define GET_GPIOB_PIN_DIR(x,pin) ((x >> (pin + 8)) & 1)
++#define SET_GPIOB_PIN_DIR(pin) (1<<(pin + 8))
++#define GET_GPIOA_DIR(x) (x&0xff)
++#define SET_GPIOA_DIR(x) (x)
++#define GET_GPIOA_PIN_DIR(x,pin) ((x >> pin) & 1)
++#define SET_GPIOA_PIN_DIR(pin) (1<<pin)
++
++/* AST_GPIO_INT_EN - 0x008 : Interrupt Enable */
++#define GET_GPIOD_INT_EN(x) ((x&0xff000000) >> 24)
++#define SET_GPIOD_INT_EN(x) (x << 24)
++#define GET_GPIOD_PIN_INT_EN(x,pin) ((x >> (pin + 24)) & 1)
++#define SET_GPIOD_PIN_INT_EN(pin) (1<<(pin + 24))
++#define GET_GPIOC_INT_EN(x) ((x&0xff0000) >> 16)
++#define SET_GPIOC_INT_EN(x) (x << 16)
++#define GET_GPIOC_PIN_INT_EN(x,pin) ((x >> (pin + 16)) & 1)
++#define SET_GPIOC_PIN_INT_EN(pin) (1<<(pin + 16))
++#define GET_GPIOB_INT_EN(x) ((x&0xff00) >> 8)
++#define SET_GPIOB_INT_EN(x) (x << 8)
++#define GET_GPIOB_PIN_INT_EN(x,pin) ((x >> (pin + 8)) & 1)
++#define SET_GPIOB_PIN_INT_EN(pin) (1<<(pin + 8))
++#define GET_GPIOA_INT_EN(x) (x&0xff)
++#define SET_GPIOA_INT_EN(x) (x)
++#define GET_GPIOA_PIN_INT_EN(x,pin) ((x >> pin) & 1)
++#define SET_GPIOA_PIN_INT_EN(pin) (1<<pin)
++
++/* AST_GPIO_INT_SEN_T0/1/2 - 0x00c/0x010/0x014 : Interrupt Sensitivity Type 0/1/2 */
++#define GET_GPIOD_INT_MODE(x) ((x&0xff000000) >> 24)
++#define SET_GPIOD_INT_MODE(x) (x << 24)
++#define GET_GPIOD_PIN_INT_MODE(x,pin) ((x >> (pin + 24)) & 1)
++#define SET_GPIOD_PIN_INT_MODE(pin) (1<<(pin + 24))
++#define GET_GPIOC_INT_MODE(x) ((x&0xff0000) >> 16)
++#define SET_GPIOC_INT_MODE(x) (x << 16)
++#define GET_GPIOC_PIN_INT_MODE(x,pin) ((x >> (pin + 16)) & 1)
++#define SET_GPIOC_PIN_INT_MODE(pin) (1<<(pin + 16))
++#define GET_GPIOB_INT_MODE(x) ((x&0xff00) >> 8)
++#define SET_GPIOB_INT_MODE(x) (x << 16)
++#define GET_GPIOB_PIN_INT_MODE(x,pin) ((x >> (pin + 8)) & 1)
++#define SET_GPIOB_PIN_INT_MODE(pin) (1<<(pin + 8))
++#define GET_GPIOA_INT_MODE(x) (x&0xff)
++#define SET_GPIOA_INT_MODE(x) (x)
++#define GET_GPIOA_PIN_INT_MODE(x,pin) ((x >> pin) & 1)
++#define SET_GPIOA_PIN_INT_MODE(pin) (1 << pin)
++
++/* AST_GPIO_INT_STS - 0x018 : Interrupt Status */
++#define GET_GPIOD_INT_STS(x) ((x&0xff000000) >> 24)
++#define SET_GPIOD_INT_STS(x) (x << 24)
++#define GET_GPIOD_PIN_INT_STS(x,pin) ((x >> (pin + 24)) & 1)
++#define SET_GPIOD_PIN_INT_STS(pin) (1<<(pin + 24))
++#define GET_GPIOC_INT_STS(x) ((x&0xff0000) >> 16)
++#define SET_GPIOC_INT_STS(x) (x << 16)
++#define GET_GPIOC_PIN_INT_STS(x,pin) ((x >> (pin + 16)) & 1)
++#define SET_GPIOC_PIN_INT_STS(pin) (1<<(pin + 16))
++#define GET_GPIOB_INT_STS(x) ((x&0xff00) >> 8)
++#define SET_GPIOB_INT_STS(x) (x << 16)
++#define GET_GPIOB_PIN_INT_STS(x,pin) ((x >> (pin + 8)) & 1)
++#define SET_GPIOB_PIN_INT_STS(pin) (1<<(pin + 8))
++#define GET_GPIOA_INT_STS(x) (x&0xff)
++#define SET_GPIOA_INT_STS(x) (x)
++#define GET_GPIOA_PIN_INT_STS(x,pin) ((x >> pin) & 1)
++#define SET_GPIOA_PIN_INT_STS(pin) (1 << pin)
++
++/* AST_GPIO_RST_TOR - 0x01c : Reset Tolerant */
++#define GET_GPIOD_RST_EN(x) ((x&0xff000000) >> 24)
++#define SET_GPIOD_RST_EN(x) (x << 24)
++#define GET_GPIOD_PIN_RST_EN(x,pin) ((x >> (pin + 24)) & 1)
++#define SET_GPIOD_PIN_RST_EN(pin) (1<<(pin + 24))
++#define GET_GPIOC_RST_EN(x) ((x&0xff0000) >> 16)
++#define SET_GPIOC_RST_EN(x) (x << 16)
++#define GET_GPIOC_PIN_RST_EN(x,pin) ((x >> (pin + 16)) & 1)
++#define SET_GPIOC_PIN_RST_EN(pin) (1<<(pin + 16))
++#define GET_GPIOB_RST_EN(x) ((x&0xff00) >> 8)
++#define SET_GPIOB_RST_EN(x) (x << 16)
++#define GET_GPIOB_PIN_RST_EN(x,pin) ((x >> (pin + 8)) & 1)
++#define SET_GPIOB_PIN_RST_EN(pin) (1<<(pin + 8))
++#define GET_GPIOA_RST_EN(x) (x&0xff)
++#define SET_GPIOA_RST_EN(x) (x)
++#define GET_GPIOA_PIN_RST_EN(x,pin) ((x >> pin) & 1)
++#define SET_GPIOA_PIN_RST_EN(pin) (1 << pin)
++
++/* AST_EXT_GPIO_DATA - 0x020 : E/F/G/H Data Vale */
++#define GET_GPIOH_DATA(x) ((x&0xff000000) >> 24)
++#define SET_GPIOH_DATA(x) (x << 24)
++#define GET_GPIOH_PIN_DATA(x,pin) ((x >> (pin + 24)) & 1)
++#define SET_GPIOH_PIN_DATA(pin) (1<<(pin + 24))
++#define GET_GPIOG_DATA(x) ((x&0xff0000) >> 16)
++#define SET_GPIOG_DATA(x) (x << 16)
++#define GET_GPIOG_PIN_DATA(x,pin) ((x >> (pin + 16)) & 1)
++#define SET_GPIOG_PIN_DATA(pin) (1<<(pin + 16))
++#define GET_GPIOF_DATA(x) ((x&0xff00) >> 8)
++#define SET_GPIOF_DATA(x) (x << 8)
++#define GET_GPIOF_PIN_DATA(x,pin) ((x >> (pin + 8)) & 1)
++#define SET_GPIOF_PIN_DATA(pin) (1<<(pin + 8))
++#define GET_GPIOE_DATA(x) (x&0xff)
++#define SET_GPIOE_DATA(x) (x)
++#define GET_GPIOE_PIN_DATA(x,pin) ((x >> pin) & 1)
++#define SET_GPIOE_PIN_DATA(pin) (1<<pin)
++
++/* AST_EXT_GPIO_DIR - 0x024 : */
++#define GET_GPIOH_DIR(x) ((x&0xff000000) >> 24)
++#define SET_GPIOH_DIR(x) (x << 24)
++#define GET_GPIOH_PIN_DIR(x,pin) ((x >> (pin + 24)) & 1)
++#define SET_GPIOH_PIN_DIR(pin) (1<<(pin + 24))
++#define GET_GPIOG_DIR(x) ((x&0xff0000) >> 16)
++#define SET_GPIOG_DIR(x) (x << 16)
++#define GET_GPIOG_PIN_DIR(x,pin) ((x >> (pin + 16)) & 1)
++#define SET_GPIOG_PIN_DIR(pin) (1<<(pin + 16))
++#define GET_GPIOF_DIR(x) ((x&0xff00) >> 8)
++#define SET_GPIOF_DIR(x) (x << 8)
++#define GET_GPIOF_PIN_DIR(x,pin) ((x >> (pin + 8)) & 1)
++#define SET_GPIOF_PIN_DIR(pin) (1<<(pin + 8))
++#define GET_GPIOE_DIR(x) (x&0xff)
++#define SET_GPIOE_DIR(x) (x)
++#define GET_GPIOE_PIN_DIR(x,pin) ((x >> pin) & 1)
++#define SET_GPIOE_PIN_DIR(pin) (1<<pin)
++
++/* AST_EXT_GPIO_INT_EN - 0x028 */
++#define GET_GPIOH_INT_EN(x) ((x&0xff000000) >> 24)
++#define SET_GPIOH_INT_EN(x) (x << 24)
++#define GET_GPIOH_PIN_INT_EN(x,pin) ((x >> (pin + 24)) & 1)
++#define SET_GPIOH_PIN_INT_EN(pin) (1<<(pin + 24))
++#define GET_GPIOG_INT_EN(x) ((x&0xff0000) >> 16)
++#define SET_GPIOG_INT_EN(x) (x << 16)
++#define GET_GPIOG_PIN_INT_EN(x,pin) ((x >> (pin + 16)) & 1)
++#define SET_GPIOG_PIN_INT_EN(pin) (1<<(pin + 16))
++#define GET_GPIOF_INT_EN(x) ((x&0xff00) >> 8)
++#define SET_GPIOF_INT_EN(x) (x << 8)
++#define GET_GPIOF_PIN_INT_EN(x,pin) ((x >> (pin + 8)) & 1)
++#define SET_GPIOF_PIN_INT_EN(pin) (1<<(pin + 8))
++#define GET_GPIOE_INT_EN(x) (x&0xff)
++#define SET_GPIOE_INT_EN(x) (x)
++#define GET_GPIOE_PIN_INT_EN(x,pin) ((x >> pin) & 1)
++#define SET_GPIOE_PIN_INT_EN(pin) (1<<pin)
++
++/* AST_EXT_GPIO_INT_SEN_T0/1/2 - 0x02c/0x30/0x34 : */
++/* AST_EXT_GPIO_INT_STS 0x038 */
++/* AST_EXT_GPIO_RST_TOR 0x03c */
++
++/* AST_GPIO_DEBOUNCE_SET1 - 0x040 : Debounce Setting #1 */
++#define GET_GPIO3_DEBOUNCE(x) ((x&0xff000000) >> 24)
++#define SET_GPIO3_DEBOUNCE(x) (x << 24)
++#define GET_GPIO3_PIN_DEBOUNCE(x,pin) ((x >> (pin + 24)) & 1)
++#define SET_GPIO3_PIN_DEBOUNCE(pin) (1<<(pin + 24))
++#define GET_GPIO2_DEBOUNCE(x) ((x&0xff0000) >> 16)
++#define SET_GPIO2_DEBOUNCE(x) (x << 16)
++#define GET_GPIO2_PIN_DEBOUNCE(x,pin) ((x >> (pin + 16)) & 1)
++#define SET_GPIO2_PIN_DEBOUNCE(pin) (1<<(pin + 16))
++#define GET_GPIO1_DEBOUNCE(x) ((x&0xff00) >> 8)
++#define SET_GPIO1_DEBOUNCE(x) (x << 8)
++#define GET_GPIO1_PIN_DEBOUNCE(x,pin) ((x >> (pin + 8)) & 1)
++#define SET_GPIO1_PIN_DEBOUNCE(pin) (1<<(pin + 8))
++#define GET_GPIO0_DEBOUNCE(x) (x&0xff)
++#define SET_GPIO0_DEBOUNCE(x) (x)
++#define GET_GPIO0_PIN_DEBOUNCE(x,pin) ((x >> pin) & 1)
++#define SET_GPIO0_PIN_DEBOUNCE(pin) (1<<pin)
++
++
++#endif /* __ASM_ARCH_REGS_GPIO_H */
+\ No newline at end of file
+diff --git a/arch/arm/plat-aspeed/include/plat/regs-iic.h b/arch/arm/plat-aspeed/include/plat/regs-iic.h
+new file mode 100644
+index 0000000..14db73c
+--- /dev/null
++++ b/arch/arm/plat-aspeed/include/plat/regs-iic.h
+@@ -0,0 +1,286 @@
++/* arch/arm/plat-aspeed/include/mach/regs-iic.h
++ *
++ * Copyright (c) 2012 ASPEED Technology Inc. <ryan_chen@aspeedtech.com>
++ * http://www.aspeedtech.com/
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * ASPEED I2C Controller
++*/
++
++#ifndef __ASM_ARCH_REGS_IIC_H
++#define __ASM_ARCH_REGS_IIC_H __FILE__
++
++#ifdef CONFIG_ARCH_AST1010
++#define AST_I2C_DMA_SIZE 512
++#else
++#define AST_I2C_DMA_SIZE 4096
++#endif
++
++#define AST_I2C_PAGE_SIZE 256
++
++#if defined(CONFIG_ARCH_AST2300)
++#define MASTER_XFER_MODE BUFF_MODE
++#define SLAVE_XFER_MODE BYTE_MODE
++#define NUM_BUS 9
++#elif defined(CONFIG_ARCH_AST2400)
++#define MASTER_XFER_MODE BUFF_MODE
++#define SLAVE_XFER_MODE BYTE_MODE
++#define NUM_BUS 14
++#elif defined(CONFIG_ARCH_AST1010)
++#define MASTER_XFER_MODE BYTE_MODE
++#define SLAVE_XFER_MODE BYTE_MODE
++#define NUM_BUS 15
++#elif defined(CONFIG_ARCH_AST1520) || defined(CONFIG_ARCH_AST3200) || defined(CONFIG_ARCH_AST2500)
++#define MASTER_XFER_MODE BYTE_MODE
++#define SLAVE_XFER_MODE BYTE_MODE
++#define NUM_BUS 4
++#else
++#err "NO define NUM_BUS"
++#endif
++
++#if defined(CONFIG_ARCH_AST1070)
++#define AST_CI2C_GLOBAL_REG 0x00
++#define AST_CI2C_DEVICE1 0x40
++#define AST_CI2C_DEVICE2 0x80
++#define AST_CI2C_DEVICE3 0xc0
++#define AST_CI2C_DEVICE4 0x100
++#define AST_CI2C_DEVICE5 0x140
++#define AST_CI2C_DEVICE6 0x180
++#define AST_CI2C_DEVICE7 0x1c0
++#define AST_CI2C_DEVICE8 0x200
++#endif
++
++/*AST I2C Register Definition */
++#if defined(CONFIG_ARCH_AST2400) || defined(CONFIG_AST2400_BMC)
++#define AST_I2C_POOL_BUFF_2048
++#define AST_I2C_GLOBAL_REG 0x00
++#define AST_I2C_DEVICE1 0x40
++#define AST_I2C_DEVICE2 0x80
++#define AST_I2C_DEVICE3 0xc0
++#define AST_I2C_DEVICE4 0x100
++#define AST_I2C_DEVICE5 0x140
++#define AST_I2C_DEVICE6 0x180
++#define AST_I2C_DEVICE7 0x1c0
++#define AST_I2C_BUFFER_POOL2 0x200
++#define AST_I2C_DEVICE8 0x300
++#define AST_I2C_DEVICE9 0x340
++#define AST_I2C_DEVICE10 0x380
++#define AST_I2C_DEVICE11 0x3c0
++#define AST_I2C_DEVICE12 0x400
++#define AST_I2C_DEVICE13 0x440
++#define AST_I2C_DEVICE14 0x480
++#define AST_I2C_BUFFER_POOL1 0x800
++
++#elif defined(CONFIG_ARCH_AST2300)
++#define AST_I2C_POOL_BUFF_256
++#define AST_I2C_GLOBAL_REG 0x00
++#define AST_I2C_DEVICE1 0x40
++#define AST_I2C_DEVICE2 0x80
++#define AST_I2C_DEVICE3 0xc0
++#define AST_I2C_DEVICE4 0x100
++#define AST_I2C_DEVICE5 0x140
++#define AST_I2C_DEVICE6 0x180
++#define AST_I2C_DEVICE7 0x1c0
++#define AST_I2C_BUFFER_POOL2 0x200
++#define AST_I2C_DEVICE8 0x300
++#define AST_I2C_DEVICE9 0x340
++#elif defined(CONFIG_ARCH_AST1010)
++#define AST_I2C_GLOBAL_REG 0x00
++#define AST_I2C_DEVICE1 0x40
++#define AST_I2C_DEVICE2 0x80
++#define AST_I2C_DEVICE3 0xc0
++#define AST_I2C_DEVICE4 0x100
++#define AST_I2C_DEVICE5 0x140
++#define AST_I2C_DEVICE6 0x180
++#define AST_I2C_DEVICE7 0x1c0
++#define AST_I2C_DEVICE8 0x200
++#define AST_I2C_DEVICE9 0x240
++#define AST_I2C_DEVICE10 0x280
++#define AST_I2C_DEVICE11 0x2c0
++#define AST_I2C_DEVICE12 0x300
++#define AST_I2C_DEVICE13 0x340
++#define AST_I2C_DEVICE14 0x380
++#define AST_I2C_DEVICE15 0x3c0
++#elif defined(CONFIG_ARCH_AST1520) || defined(CONFIG_ARCH_AST3200) || defined(CONFIG_ARCH_AST2500)
++#define AST_I2C_GLOBAL_REG 0x00
++#define AST_I2C_DEVICE1 0x40
++#define AST_I2C_DEVICE2 0x80
++#define AST_I2C_DEVICE3 0xc0
++#define AST_I2C_DEVICE4 0x100
++#else
++#err "NO define for I2C"
++#endif
++
++
++
++/* I2C Register */
++#define I2C_FUN_CTRL_REG 0x00
++#define I2C_AC_TIMING_REG1 0x04
++#define I2C_AC_TIMING_REG2 0x08
++#define I2C_INTR_CTRL_REG 0x0c
++#define I2C_INTR_STS_REG 0x10
++#define I2C_CMD_REG 0x14
++#define I2C_DEV_ADDR_REG 0x18
++#define I2C_BUF_CTRL_REG 0x1c
++#define I2C_BYTE_BUF_REG 0x20
++#define I2C_DMA_BASE_REG 0x24
++#define I2C_DMA_LEN_REG 0x28
++
++
++/* Gloable Register Definition */
++/* 0x00 : I2C Interrupt Status Register */
++/* 0x08 : I2C Interrupt Target Assignment */
++#if defined(CONFIG_ARCH_AST2400)
++#define AST_I2CG_INTR14 (0x1 << 13)
++#define AST_I2CG_INTR13 (0x1 << 12)
++#define AST_I2CG_INTR12 (0x1 << 11)
++#define AST_I2CG_INTR11 (0x1 << 10)
++#define AST_I2CG_INTR10 (0x1 << 9)
++#elif defined(CONFIG_ARCH_AST1010)
++#define AST_I2CG_INTR14 (0x1 << 13)
++#define AST_I2CG_INTR13 (0x1 << 12)
++#define AST_I2CG_INTR12 (0x1 << 11)
++#define AST_I2CG_INTR11 (0x1 << 10)
++#define AST_I2CG_INTR10 (0x1 << 9)
++#endif
++#define AST_I2CG_INTR09 (0x1 << 8)
++#define AST_I2CG_INTR08 (0x1 << 7)
++#define AST_I2CG_INTR07 (0x1 << 6)
++#define AST_I2CG_INTR06 (0x1 << 5)
++#define AST_I2CG_INTR05 (0x1 << 4)
++#define AST_I2CG_INTR04 (0x1 << 3)
++#define AST_I2CG_INTR03 (0x1 << 2)
++#define AST_I2CG_INTR02 (0x1 << 1)
++#define AST_I2CG_INTR01 (0x1 )
++
++/* Device Register Definition */
++/* 0x00 : I2CD Function Control Register */
++#define AST_I2CD_BUFF_SEL_MASK (0x7 << 20)
++#define AST_I2CD_BUFF_SEL(x) (x << 20) // page 0 ~ 7
++#define AST_I2CD_M_SDA_LOCK_EN (0x1 << 16)
++#define AST_I2CD_MULTI_MASTER_DIS (0x1 << 15)
++#define AST_I2CD_M_SCL_DRIVE_EN (0x1 << 14)
++#define AST_I2CD_MSB_STS (0x1 << 9)
++#define AST_I2CD_SDA_DRIVE_1T_EN (0x1 << 8)
++#define AST_I2CD_M_SDA_DRIVE_1T_EN (0x1 << 7)
++#define AST_I2CD_M_HIGH_SPEED_EN (0x1 << 6)
++#define AST_I2CD_DEF_ADDR_EN (0x1 << 5)
++#define AST_I2CD_DEF_ALERT_EN (0x1 << 4)
++#define AST_I2CD_DEF_ARP_EN (0x1 << 3)
++#define AST_I2CD_DEF_GCALL_EN (0x1 << 2)
++#define AST_I2CD_SLAVE_EN (0x1 << 1)
++#define AST_I2CD_MASTER_EN (0x1 )
++
++/* 0x04 : I2CD Clock and AC Timing Control Register #1 */
++#define AST_I2CD_tBUF (0x1 << 28) // 0~7
++#define AST_I2CD_tHDSTA (0x1 << 24) // 0~7
++#define AST_I2CD_tACST (0x1 << 20) // 0~7
++#define AST_I2CD_tCKHIGH (0x1 << 16) // 0~7
++#define AST_I2CD_tCKLOW (0x1 << 12) // 0~7
++#define AST_I2CD_tHDDAT (0x1 << 10) // 0~7
++#define AST_I2CD_CLK_TO_BASE_DIV (0x1 << 8) // 0~3
++#define AST_I2CD_CLK_BASE_DIV (0x1 ) // 0~0xf
++
++/* 0x08 : I2CD Clock and AC Timing Control Register #2 */
++#define AST_I2CD_tTIMEOUT (0x1 ) // 0~7
++#define AST_NO_TIMEOUT_CTRL 0x0
++
++
++/* 0x0c : I2CD Interrupt Control Register */
++#define AST_I2CD_SDA_DL_TO_INTR_EN (0x1 << 14)
++#define AST_I2CD_BUS_RECOVER_INTR_EN (0x1 << 13)
++#define AST_I2CD_SMBUS_ALT_INTR_EN (0x1 << 12)
++#define AST_I2CD_SLAVE_MATCH_INTR_EN (0x1 << 7)
++#define AST_I2CD_SCL_TO_INTR_EN (0x1 << 6)
++#define AST_I2CD_ABNORMAL_INTR_EN (0x1 << 5)
++#define AST_I2CD_NORMAL_STOP_INTR_EN (0x1 << 4)
++#define AST_I2CD_ARBIT_LOSS_INTR_EN (0x1 << 3)
++#define AST_I2CD_RX_DOWN_INTR_EN (0x1 << 2)
++#define AST_I2CD_TX_NAK_INTR_EN (0x1 << 1)
++#define AST_I2CD_TX_ACK_INTR_EN (0x1 )
++
++/* 0x10 : I2CD Interrupt Status Register : WC */
++#define AST_I2CD_INTR_STS_SDA_DL_TO (0x1 << 14)
++#define AST_I2CD_INTR_STS_BUS_RECOVER (0x1 << 13)
++#define AST_I2CD_INTR_STS_SMBUS_ALT (0x1 << 12)
++#define AST_I2CD_INTR_STS_SMBUS_ARP_ADDR (0x1 << 11)
++#define AST_I2CD_INTR_STS_SMBUS_DEV_ALT (0x1 << 10)
++#define AST_I2CD_INTR_STS_SMBUS_DEF_ADDR (0x1 << 9)
++#define AST_I2CD_INTR_STS_GCALL_ADDR (0x1 << 8)
++#define AST_I2CD_INTR_STS_SLAVE_MATCH (0x1 << 7)
++#define AST_I2CD_INTR_STS_SCL_TO (0x1 << 6)
++#define AST_I2CD_INTR_STS_ABNORMAL (0x1 << 5)
++#define AST_I2CD_INTR_STS_NORMAL_STOP (0x1 << 4)
++#define AST_I2CD_INTR_STS_ARBIT_LOSS (0x1 << 3)
++#define AST_I2CD_INTR_STS_RX_DOWN (0x1 << 2)
++#define AST_I2CD_INTR_STS_TX_NAK (0x1 << 1)
++#define AST_I2CD_INTR_STS_TX_ACK (0x1 )
++
++/* 0x14 : I2CD Command/Status Register */
++#define AST_I2CD_SDA_OE (0x1 << 28)
++#define AST_I2CD_SDA_O (0x1 << 27)
++#define AST_I2CD_SCL_OE (0x1 << 26)
++#define AST_I2CD_SCL_O (0x1 << 25)
++#define AST_I2CD_TX_TIMING (0x1 << 24) // 0 ~3
++#define AST_I2CD_TX_STATUS (0x1 << 23)
++// Tx State Machine
++#define AST_I2CD_IDLE 0x0
++#define AST_I2CD_MACTIVE 0x8
++#define AST_I2CD_MSTART 0x9
++#define AST_I2CD_MSTARTR 0xa
++#define AST_I2CD_MSTOP 0xb
++#define AST_I2CD_MTXD 0xc
++#define AST_I2CD_MRXACK 0xd
++#define AST_I2CD_MRXD 0xe
++#define AST_I2CD_MTXACK 0xf
++#define AST_I2CD_SWAIT 0x1
++#define AST_I2CD_SRXD 0x4
++#define AST_I2CD_STXACK 0x5
++#define AST_I2CD_STXD 0x6
++#define AST_I2CD_SRXACK 0x7
++#define AST_I2CD_RECOVER 0x3
++
++#define AST_I2CD_SCL_LINE_STS (0x1 << 18)
++#define AST_I2CD_SDA_LINE_STS (0x1 << 17)
++#define AST_I2CD_BUS_BUSY_STS (0x1 << 16)
++#define AST_I2CD_SDA_OE_OUT_DIR (0x1 << 15)
++#define AST_I2CD_SDA_O_OUT_DIR (0x1 << 14)
++#define AST_I2CD_SCL_OE_OUT_DIR (0x1 << 13)
++#define AST_I2CD_SCL_O_OUT_DIR (0x1 << 12)
++#define AST_I2CD_BUS_RECOVER_CMD_EN (0x1 << 11)
++#define AST_I2CD_S_ALT_EN (0x1 << 10)
++// 0 : DMA Buffer, 1: Pool Buffer
++//AST1070 DMA register
++#define AST_I2CD_RX_DMA_ENABLE (0x1 << 9)
++#define AST_I2CD_TX_DMA_ENABLE (0x1 << 8)
++
++/* Command Bit */
++#define AST_I2CD_RX_BUFF_ENABLE (0x1 << 7)
++#define AST_I2CD_TX_BUFF_ENABLE (0x1 << 6)
++#define AST_I2CD_M_STOP_CMD (0x1 << 5)
++#define AST_I2CD_M_S_RX_CMD_LAST (0x1 << 4)
++#define AST_I2CD_M_RX_CMD (0x1 << 3)
++#define AST_I2CD_S_TX_CMD (0x1 << 2)
++#define AST_I2CD_M_TX_CMD (0x1 << 1)
++#define AST_I2CD_M_START_CMD (0x1 )
++
++/* 0x18 : I2CD Slave Device Address Register */
++
++/* 0x1C : I2CD Pool Buffer Control Register */
++#define AST_I2CD_RX_BUF_ADDR_GET(x) ((x>> 24)& 0xff)
++#define AST_I2CD_RX_BUF_END_ADDR_SET(x) (x << 16)
++#define AST_I2CD_TX_DATA_BUF_END_SET(x) ((x&0xff) << 8)
++#define AST_I2CD_TX_DATA_BUF_GET(x) ((x >>8) & 0xff)
++#define AST_I2CD_BUF_BASE_ADDR_SET(x) (x & 0x3f)
++
++/* 0x20 : I2CD Transmit/Receive Byte Buffer Register */
++#define AST_I2CD_GET_MODE(x) ((x >> 8) & 0x1)
++
++#define AST_I2CD_RX_BYTE_BUFFER (0xff << 8)
++#define AST_I2CD_TX_BYTE_BUFFER (0xff )
++
++
++#endif /* __ASM_ARCH_REGS_IIC_H */
+diff --git a/arch/arm/plat-aspeed/include/plat/regs-intr.h b/arch/arm/plat-aspeed/include/plat/regs-intr.h
+new file mode 100644
+index 0000000..cea0132
+--- /dev/null
++++ b/arch/arm/plat-aspeed/include/plat/regs-intr.h
+@@ -0,0 +1,74 @@
++/* arch/arm/mach-aspeed/include/mach/regs-intr.h
++ *
++ * Copyright (C) 2012-2020 ASPEED Technology Inc.
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * History :
++ * 1. 2012/08/15 Ryan Chen Create
++ *
++********************************************************************************/
++#ifndef __ASPEED_AST_INTR_H
++#define __ASPEED_AST_INTR_H 1
++
++#ifndef __ASSEMBLY__
++#include <asm/io.h>
++#endif
++//============== INTERRUPT========================================
++#include <mach/platform.h>
++#include <mach/irqs.h>
++#include <plat/aspeed.h>
++
++/*
++ * VIC Register (VA)
++ */
++
++#define VIC_BASE_VA IO_ADDRESS(AST_VIC_BASE)
++
++#if defined(NEW_VIC)
++//New Mappling
++
++#define AST_IRQ_STS(x) (VIC_BASE_VA + 0x80 + (x*0x04))
++#define AST_FIQ_STS(x) (VIC_BASE_VA + 0x88 + (x*0x04))
++#define AST_RAW_STS(x) (VIC_BASE_VA + 0x90 + (x*0x04))
++#define AST_INTR_SEL(x) (VIC_BASE_VA + 0x98 + (x*0x04))
++#define AST_INTR_EN(x) (VIC_BASE_VA + 0xA0 + (x*0x04))
++#define AST_INTR_DIS(x) (VIC_BASE_VA + 0xA8 + (x*0x04))
++#define AST_INTR_SW_EN(x) (VIC_BASE_VA + 0xB0 + (x*0x04))
++#define AST_INTR_SW_CLR(x) (VIC_BASE_VA + 0xB8 + (x*0x04))
++#define AST_INTR_SENSE(x) (VIC_BASE_VA + 0xC0 + (x*0x04))
++#define AST_INTR_BOTH_EDGE(x) (VIC_BASE_VA + 0xC8 + (x*0x04))
++#define AST_INTR_EVENT(x) (VIC_BASE_VA + 0xD0 + (x*0x04))
++#define AST_INTR_EDGE_CLR(x) (VIC_BASE_VA + 0xD8 + (x*0x04))
++#define AST_INTR_EDGE_STS(x) (VIC_BASE_VA + 0xE0 + (x*0x04))
++
++#else
++
++//Legacy Maping
++
++#define AST_IRQ_STS(x) (VIC_BASE_VA + 0x00)
++#define AST_FIQ_STS(x) (VIC_BASE_VA + 0x04)
++#define AST_RAW_STS(x) (VIC_BASE_VA + 0x08)
++#define AST_INTR_SEL(x) (VIC_BASE_VA + 0x0C)
++#define AST_INTR_EN(x) (VIC_BASE_VA + 0x10)
++#define AST_INTR_DIS(x) (VIC_BASE_VA + 0x14)
++#define AST_INTR_SW_EN(x) (VIC_BASE_VA + 0x18)
++#define AST_INTR_SW_CLR(x) (VIC_BASE_VA + 0x1C)
++#define AST_INTR_SENSE(x) (VIC_BASE_VA + 0x24)
++#define AST_INTR_BOTH_EDGE(x) (VIC_BASE_VA + 0x28)
++#define AST_INTR_EVENT(x) (VIC_BASE_VA + 0x2C)
++#define AST_INTR_EDGE_CLR(x) (VIC_BASE_VA + 0x38)
++#endif
++
++#define IRQ_SET_LEVEL_TRIGGER(x, irq_no) *((volatile unsigned long*)AST_INTR_SENSE(x)) |= 1 << (irq_no)
++#define IRQ_SET_EDGE_TRIGGER(x, irq_no) *((volatile unsigned long*)AST_INTR_SENSE(x)) &= ~(1 << (irq_no))
++#define IRQ_SET_RISING_EDGE(x, irq_no) *((volatile unsigned long*)AST_INTR_EVENT(x)) |= 1 << (irq_no)
++#define IRQ_SET_FALLING_EDGE(x, irq_no) *((volatile unsigned long*)AST_INTR_EVENT(x)) &= ~(1 << (irq_no))
++#define IRQ_SET_HIGH_LEVEL(x,irq_no) *((volatile unsigned long*)AST_INTR_EVENT(x)) |= 1 << (irq_no)
++#define IRQ_SET_LOW_LEVEL(x, irq_no) *((volatile unsigned long*)AST_INTR_EVENT(x)) &= ~(1 << (irq_no))
++#define IRQ_EDGE_CLEAR(x, irq_no) *((volatile unsigned long*)AST_INTR_EDGE_CLR(x)) |= 1 << (irq_no)
++
++#endif
++
+diff --git a/arch/arm/plat-aspeed/include/plat/regs-jtag.h b/arch/arm/plat-aspeed/include/plat/regs-jtag.h
+new file mode 100644
+index 0000000..7df385d
+--- /dev/null
++++ b/arch/arm/plat-aspeed/include/plat/regs-jtag.h
+@@ -0,0 +1,65 @@
++/* arch/arm/plat-aspeed/include/mach/regs-jtag.h
++ *
++ * Copyright (c) 2012 ASPEED Technology Inc. <ryan_chen@aspeedtech.com>
++ * http://www.aspeedtech.com/
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * ASPEED JTAG Controller
++*/
++
++#define AST_JTAG_DATA 0x00
++#define AST_JTAG_INST 0x04
++#define AST_JTAG_CTRL 0x08
++#define AST_JTAG_ISR 0x0C
++#define AST_JTAG_SW 0x10
++#define AST_JTAG_TCK 0x14
++#define AST_JTAG_IDLE 0x18
++
++/* AST_JTAG_CTRL - 0x08 : Engine Control */
++#define JTAG_ENG_EN (0x1 << 31)
++#define JTAG_ENG_OUT_EN (0x1 << 30)
++#define JTAG_FORCE_TMS (0x1 << 29)
++
++#define JTAG_IR_UPDATE (0x1 << 26) //AST2500 only
++#define JTAG_INST_LEN_MASK (0x3f << 20)
++#define JTAG_SET_INST_LEN(x) (x << 20)
++#define JTAG_SET_INST_MSB (0x1 << 19)
++#define JTAG_TERMINATE_INST (0x1 << 18)
++#define JTAG_LAST_INST (0x1 << 17)
++#define JTAG_INST_EN (0x1 << 16)
++#define JTAG_DATA_LEN_MASK (0x3f << 4)
++
++#define JTAG_DR_UPDATE (0x1 << 10) //AST2500 only
++#define JTAG_DATA_LEN(x) (x << 4)
++#define JTAG_SET_DATA_MSB (0x1 << 3)
++#define JTAG_TERMINATE_DATA (0x1 << 2)
++#define JTAG_LAST_DATA (0x1 << 1)
++#define JTAG_DATA_EN (0x1)
++
++/* AST_JTAG_ISR - 0x0C : INterrupt status and enable */
++#define JTAG_INST_PAUSE (0x1 << 19)
++#define JTAG_INST_COMPLETE (0x1 << 18)
++#define JTAG_DATA_PAUSE (0x1 << 17)
++#define JTAG_DATA_COMPLETE (0x1 << 16)
++
++#define JTAG_INST_PAUSE_EN (0x1 << 3)
++#define JTAG_INST_COMPLETE_EN (0x1 << 2)
++#define JTAG_DATA_PAUSE_EN (0x1 << 1)
++#define JTAG_DATA_COMPLETE_EN (0x1)
++
++
++/* AST_JTAG_SW - 0x10 : Software Mode and Status */
++#define JTAG_SW_MODE_EN (0x1 << 19)
++#define JTAG_SW_MODE_TCK (0x1 << 18)
++#define JTAG_SW_MODE_TMS (0x1 << 17)
++#define JTAG_SW_MODE_TDIO (0x1 << 16)
++//
++#define JTAG_STS_INST_PAUSE (0x1 << 2)
++#define JTAG_STS_DATA_PAUSE (0x1 << 1)
++#define JTAG_STS_ENG_IDLE (0x1)
++
++/* AST_JTAG_IDLE - 0x18 : Ctroller set for go to IDLE */
++#define JTAG_GO_IDLE (0x1)
+diff --git a/arch/arm/plat-aspeed/include/plat/regs-lpc.h b/arch/arm/plat-aspeed/include/plat/regs-lpc.h
+new file mode 100644
+index 0000000..f4523d7
+--- /dev/null
++++ b/arch/arm/plat-aspeed/include/plat/regs-lpc.h
+@@ -0,0 +1,215 @@
++/* arch/arm/plat-aspeed/include/mach/regs-lpc.h
++ *
++ * Copyright (c) 2012 ASPEED Technology Inc. <ryan_chen@aspeedtech.com>
++ * http://www.aspeedtech.com/
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * ASPEED LPC Controller
++*/
++
++#ifndef __AST_LPC_H_
++#define __AST_LPC_H_
++
++#define AST_LPC_HICR0 0x000
++#define AST_LPC_HICR1 0x004
++#define AST_LPC_HICR2 0x008 /* Host Interface Control Register 2 */
++#define AST_LPC_HICR3 0x00C
++#define AST_LPC_HICR4 0x010
++#define AST_LPC_LADR3H 0x014
++#define AST_LPC_LADR3L 0x018
++#define AST_LPC_LADR12H 0x01C
++#define AST_LPC_LADR12L 0x020
++#define AST_LPC_IDR1 0x024
++#define AST_LPC_IDR2 0x028
++#define AST_LPC_IDR3 0x02C
++#define AST_LPC_ODR1 0x030
++#define AST_LPC_ODR2 0x034
++#define AST_LPC_ODR3 0x038
++#define AST_LPC_STR1 0x03C
++#define AST_LPC_STR2 0x040
++#define AST_LPC_STR3 0x044
++#define AST_LPC_BTR0 0x048
++#define AST_LPC_BTR1 0x04C
++#define AST_LPC_BTCSR0 0x050
++#define AST_LPC_BTCSR1 0x054
++#define AST_LPC_BTCR 0x058
++#define AST_LPC_BTDTR 0x05C
++#define AST_LPC_BTIMSR 0x060
++#define AST_LPC_BTFVSR0 0x064
++#define AST_LPC_BTFVSR1 0x068
++#define AST_LPC_SIRQCR0 0x06C
++#define AST_LPC_SIRQCR1 0x070
++#define AST_LPC_SIRQCR2 0x074
++#define AST_LPC_SIRQCR3 0x078
++
++//////
++#define AST_LPC_HICR5 0x080 /* LPC Host interface Control Register 5 */
++#define AST_LPC_HICR6 0x084 /* LPC Host Interface Control Register 6 */
++#define AST_LPC_HICR7 0x088
++#define AST_LPC_HICR8 0x08C
++#define AST_LPC_SNPWADR 0x090 /* LPC Snoop Address Register */
++#define AST_LPC_SNPWDR 0x094 /* LPC SNoop Data Register */
++#define AST_LPC_HICR9 0x098
++#define AST_LPC_HICRA 0x09C
++#define AST_LPC_LHCR0 0x0A0
++#define AST_LPC_LHCR1 0x0A4
++#define AST_LPC_LHCR2 0x0A8
++#define AST_LPC_LHCR3 0x0AC
++#define AST_LPC_LHCR4 0x0B0
++#define AST_LPC_LHCR5 0x0B4
++#define AST_LPC_LHCR6 0x0B8
++#define AST_LPC_LHCR7 0x0BC
++#define AST_LPC_LHCR8 0x0C0
++#define AST_LPC_PCCR6 0x0C4
++#define AST_LPC_LHCRA 0x0C8
++#define AST_LPC_LHCRB 0x0CC
++
++
++#define AST_LPC_PCCR4 0x0D0 /* Post Code Control Regiter 4 */
++#define AST_LPC_PCCR5 0x0D4 /* Post Code Control Regiter 5 */
++
++#define AST_LPC_HICRB 0x0D8
++#define AST_LPC_HICRC 0x0DC
++#define AST_LPC_HISR0 0x0E0
++#define AST_LPC_HISR1 0x0E4
++#define AST_LPC_LADR4 0x0E8
++#define AST_LPC_IDR4 0x0EC
++#define AST_LPC_ODR4 0x0F0
++#define AST_LPC_STR4 0x0F4
++#define AST_LPC_LSADR12 0x0F8
++#define AST_LPC_IDR5 0x0FC
++#define AST_LPC_ODR5 0x100
++#define AST_LPC_STR5 0x104
++
++
++
++#define AST_LPC_PCCR0 0x130 /*Post Code Contol Register 0 */
++#define AST_LPC_PCCR1 0x134 /*Post Code Contol Register 1 */
++#define AST_LPC_PCCR2 0x138 /*Post Code Contol Register 2 */
++#define AST_LPC_PCCR3 0x13C /*Post Code Contol Register 3 */
++
++
++#define AST_LPC_IBTCR0 0x140
++#define AST_LPC_IBTCR1 0x144
++#define AST_LPC_IBTCR2 0x148
++#define AST_LPC_IBTCR3 0x14C
++#define AST_LPC_IBTCR4 0x150
++#define AST_LPC_IBTCR5 0x154
++#define AST_LPC_IBTCR6 0x158
++#define AST_LPC_SRUART1 0x15C
++#define AST_LPC_SRUART2 0x160
++#define AST_LPC_SRUART3 0x164
++#define AST_LPC_SRUART4 0x168
++#define AST_LPC_SCR0SIO 0x16C
++#define AST_LPC_SCR0SI1 0x170
++#define AST_LPC_SCR0SI2 0x174
++#define AST_LPC_SCR0SI3 0x17C
++
++#define AST_LPC_SWCR0300 0x180
++#define AST_LPC_SWCR0704 0x184
++#define AST_LPC_SWCR0B08 0x188
++#define AST_LPC_SWCR0F0C 0x18C
++#define AST_LPC_SWCR1310 0x190
++#define AST_LPC_SWCR1714 0x194
++#define AST_LPC_SWCR1B18 0x198
++#define AST_LPC_SWCR1F1C 0x19C
++#define AST_LPC_ACPIE3E0 0x1A0
++#define AST_LPC_ACPIC1C0 0x1A4
++#define AST_LPC_ACPIB3B0 0x1A8
++#define AST_LPC_ACPIB7B4 0x1AC
++
++/* AST_LPC_HICR0 0x000 */
++#define LPC_LPC3_EN (1 << 7)
++#define LPC_LPC2_EN (1 << 6)
++#define LPC_LPC1_EN (1 << 5)
++
++#define LPC_SDWNE (1 << 3)
++#define LPC_PMEE (1 << 2)
++
++/* AST_LPC_HICR2 0x008 */
++#define LPC_LRST (1 << 6)
++#define LPC_SDWN (1 << 5)
++#define LPC_ABRT (1 << 4)
++#define LPC_IBFIF3 (1 << 3)
++#define LPC_IBFIF2 (1 << 2)
++#define LPC_IBFIF1 (1 << 1)
++#define LPC_EERIE (1)
++
++
++
++
++
++
++
++/* AST_LPC_HICR4 0x010 */
++#define LPC_HICS_LADR12AS (1 << 7)
++#define LPC_HICS_CLRINTLRSTR (1 << 6)
++#define LPC_HICS_STSINTLRSTR (1 << 5)
++#define LPC_HICS_ENINTLRSTR (1 << 4)
++/* bit 3 reserved */
++#define LPC_HICS_KCSENBL (1 << 2)
++/* bit 1 reserved */
++#define LPC_HICS_BTENBL (1)
++
++
++/* AST_LPC_STR1 0: 0x03C, 1: 0x40, 2 : 0x44, 3: 4: */
++#define LPC_STR_DBU4 (1 << 7)
++#define LPC_STR_DBU3 (1 << 6)
++#define LPC_STR_DBU2 (1 << 5)
++#define LPC_STR_DBU1 (1 << 4)
++#define LPC_STR_CMD_DAT (1 << 3)
++#define LPC_STR_DBU0 (1 << 2)
++#define LPC_STR_IBF (1 << 1)
++#define LPC_STR_OBF (1)
++
++
++/* AST_LPC_HICR5 0x080 - LPC Host interface Control Register */
++#define LPC_HICR5_SNP1INT_EN (1 << 3)
++#define LPC_HICR5_SNP1W_EN (1 << 2)
++#define LPC_HICR5_SNP0INT_EN (1 << 1)
++#define LPC_HICR5_SNP0W_EN (1)
++
++/* AST_LPC_HICR6 0x084 - LPC Host Interface Control Register 6 */
++#define LPC_HICR6_STR_BAUD (1 << 3)
++#define LPC_HICR6_STR_PME (1 << 2)
++#define LPC_HICR6_STR_SNP1W (1 << 1)
++#define LPC_HICR6_STR_SNP0W (1)
++
++/* AST_LPC_SNPWADR 0x090 - LPC Snoop Address Register*/
++#define LPC_SNOOP_ADDR1_MASK (0xffff << 16)
++#define LPC_SNOOP_ADDR0_MASK (0xffff)
++
++/* AST_LPC_SNPWDR 0x094 - LPC SNoop Data Register */
++#define GET_LPC_SNPD1(x) ((x >> 7) & 0xff)
++#define GET_LPC_SNPD0(x) (x & 0xff)
++
++/*AST_LPC_PCCR0 0x130 - Post Code Contol Register 0 */
++#define LPC_POST_DMA_INT_EN (1 << 31)
++#define LPC_POST_DMA_MODE_EN (1 << 14)
++#define LPC_RX_FIFO_CLR (1 << 7)
++#define LPC_POST_
++#define LPC_POST_CODE_MODE_MASK (0x3 << 4)
++#define LPC_POST_CODE_MODE(x) (x << 4)
++#define BYTE_MODE 0
++#define WORD_MODE 1
++#define DWORD_MODE 2
++#define FULL_MODE 3
++
++#define LPC_POST_CODE_RXOVR (1 << 3)
++#define LPC_POST_CODE_RXTO (1 << 2)
++#define LPC_POST_CODE_RXAVA (1 << 1)
++#define LPC_POST_CODE_EN (1)
++
++/*AST_LPC_PCCR1 0x134 Post Code Contol Register 1 */
++#define LPC_POST_ADDR_MASK 0x3fffff
++#define LPC_CAPTURE_ADDR_MASK(x) (x << 16)
++#define LPC_CAPTURE_BASE_ADDR(x) (x)
++
++/*AST_LPC_PCCR2 0x138 Post Code Contol Register 2 */
++#define LPC_POST_CODE_DMA_RDY (1 << 4)
++#define LPC_POST_CODE_STS (1)
++
++#endif
+diff --git a/arch/arm/plat-aspeed/include/plat/regs-mbx.h b/arch/arm/plat-aspeed/include/plat/regs-mbx.h
+new file mode 100644
+index 0000000..636207f
+--- /dev/null
++++ b/arch/arm/plat-aspeed/include/plat/regs-mbx.h
+@@ -0,0 +1,48 @@
++/* arch/arm/plat-aspeed/include/mach/regs-lpc.h
++ *
++ * Copyright (c) 2012 ASPEED Technology Inc. <ryan_chen@aspeedtech.com>
++ * http://www.aspeedtech.com/
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * ASPEED LPC Controller
++*/
++
++#ifndef __AST_MBX_H_
++#define __AST_MBX_H_
++
++#define AST_MBX_DAT0 0x00
++#define AST_MBX_DAT1 0x04
++#define AST_MBX_DAT2 0x08
++#define AST_MBX_DAT3 0x0C
++#define AST_MBX_DAT4 0x10
++#define AST_MBX_DAT5 0x14
++#define AST_MBX_DAT6 0x18
++#define AST_MBX_DAT7 0x1C
++#define AST_MBX_DAT8 0x20
++#define AST_MBX_DAT9 0x24
++#define AST_MBX_DATA 0x28
++#define AST_MBX_DATB 0x2C
++#define AST_MBX_DATC 0x30
++#define AST_MBX_DATD 0x34
++#define AST_MBX_DATE 0x38
++#define AST_MBX_DATF 0x3C
++#define AST_MBX_STS0 0x40
++#define AST_MBX_STS1 0x44
++#define AST_MBX_BCR 0x48
++#define AST_MBX_HCR 0x4C
++#define AST_MBX_BIE0 0x50
++#define AST_MBX_BIE1 0x54
++#define AST_MBX_HIE0 0x58
++#define AST_MBX_HIE1 0x5C
++
++/* AST_MBX_BCR 0x48 */
++#define MBHIST (1 << 7)
++#define MBHMK (1 << 1)
++#define MBBINT (1)
++
++
++
++#endif
+diff --git a/arch/arm/plat-aspeed/include/plat/regs-mctp.h b/arch/arm/plat-aspeed/include/plat/regs-mctp.h
+new file mode 100644
+index 0000000..2237cfe
+--- /dev/null
++++ b/arch/arm/plat-aspeed/include/plat/regs-mctp.h
+@@ -0,0 +1,47 @@
++/* arch/arm/mach-aspeed/include/mach/regs-ast1010-scu.h
++ *
++ * Copyright (C) 2012-2020 ASPEED Technology Inc.
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * History :
++ * 1. 2012/12/29 Ryan Chen Create
++ *
++********************************************************************************/
++#ifndef __AST_MCTP_H
++#define __AST_MCTP_H 1
++
++/*
++ * Register for MCTP
++ * */
++#define AST_MCTP_CTRL 0x00 /* Engine Status and Engine Control */
++#define AST_MCTP_INT 0x04 /* Interrupt Enable and Status Register */
++#define AST_MCTP_ID 0x08 /* Target ID and Mask */
++#define AST_MCTP_TX_DESC3 0x10 /* Sending Descriptor [127:96] */
++#define AST_MCTP_TX_DESC2 0x14 /* Sending Descriptor [95:64] */
++#define AST_MCTP_TX_DESC1 0x18 /* Sending Descriptor [63:32] */
++#define AST_MCTP_TX_DESC0 0x1C /* Sending Descriptor [31:0] */
++#define AST_MCTP_TX_DATA 0x20 /* Sending Data Port */
++#define AST_MCTP_RX_DESC3 0x40 /* Received Descriptor [127:96] */
++#define AST_MCTP_RX_DESC2 0x44 /* Received Descriptor [95:64] */
++#define AST_MCTP_RX_DESC1 0x48 /* Received Descriptor [63:32] */
++#define AST_MCTP_RX_DESC0 0x4C /* Received Descriptor [31:0] */
++#define AST_MCTP_RX_DATA 0x50 /* Received Data Port */
++
++#define AST_MCTP_DEC_ADDR 0x80 /* ADDR */
++#define AST_MCTP_DEC_MASK 0x84 /* MASK */
++#define AST_MCTP_DEC_TAG 0x88 /* TAG */
++
++/* AST_MCTP_CTRL 0x00 Engine Status and Engine Control */
++
++/* AST_MCTP_INT 0x04 Interrupt Enable and Status Register */
++#define MCTP_RX_INT_EN (1 << 17)
++#define MCTP_TX_INT_EN (1 << 16)
++
++#define MCTP_RX_COMPLETE (1 << 1)
++#define MCTP_TX_COMPLETE (1)
++
++#endif
++
+diff --git a/arch/arm/plat-aspeed/include/plat/regs-pcie.h b/arch/arm/plat-aspeed/include/plat/regs-pcie.h
+new file mode 100644
+index 0000000..bd699fc
+--- /dev/null
++++ b/arch/arm/plat-aspeed/include/plat/regs-pcie.h
+@@ -0,0 +1,68 @@
++/* arch/arm/mach-aspeed/include/mach/regs-ast1010-scu.h
++ *
++ * Copyright (C) 2012-2020 ASPEED Technology Inc.
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * History :
++ * 1. 2012/12/29 Ryan Chen Create
++ *
++********************************************************************************/
++#ifndef __AST_PCIE_H
++#define __AST_PCIE_H 1
++
++/*
++ * Register for PCIE
++ * */
++#define AST_PCIE_CFG2 0x04
++#define AST_PCIE_SSID 0x28
++#define AST_PCIE_GLOBAL 0x30
++#define AST_PCIE_LOCK 0x7C
++
++#define AST_PCIE_LINK 0xC0
++#define AST_PCIE_INT 0xC4
++
++/* AST_PCIE_CFG2 0x04 */
++#define PCIE_CFG_CLASS_CODE(x) (x << 8)
++#define PCIE_CFG_REV_ID(x) (x)
++
++
++/*SSID: 1E6ED028h[19:4]*/
++/*SSVID: 1E6ED028h[3:0], 1E6ED024h[31:20]*/
++
++/* AST_PCIE_SSID_A 0x24 */
++/* 31:20 */
++#define PCIE_SSVID_H(x) (x)
++
++/* AST_PCIE_SSID_B 0x28 */
++/* 19:14 */
++#define PCIE_SSID(x) (x << 4)
++/* 3:0 */
++#define PCIE_SSVID_L(x) (x)
++
++
++/* AST_PCIE_GLOBAL 0x30 */
++#define ROOT_COMPLEX_ID(x) (x << 4)
++
++
++/* AST_PCIE_LOCK 0x7C */
++#define PCIE_UNLOCK 0xa8
++
++/* AST_PCIE_LINK 0xC0 */
++#define PCIE_LINK_STS (1 << 5)
++
++/* AST_PCIE_INT 0xC4 */
++#define PCIE_INTD (1 << 16)
++#define PCIE_INTC (1 << 15)
++#define PCIE_INTB (1 << 14)
++#define PCIE_INTA (1 << 13)
++
++#define AST_PCIE_NONP_MEM_BASE AST_PCIE0_WIN_BASE0
++#define AST_PCIE_NONP_MEM_SIZE AST_PCIE0_WIN_SIZE0
++#define AST_PCIE_PREF_MEM_BASE 0x0
++#define AST_PCIE_PREF_MEM_SIZE 0x0
++
++#endif
++
+diff --git a/arch/arm/plat-aspeed/include/plat/regs-peci.h b/arch/arm/plat-aspeed/include/plat/regs-peci.h
+new file mode 100644
+index 0000000..266daca
+--- /dev/null
++++ b/arch/arm/plat-aspeed/include/plat/regs-peci.h
+@@ -0,0 +1,106 @@
++/* arch/arm/plat-aspeed/include/mach/regs-peci.h
++ *
++ * Copyright (c) 2012 ASPEED Technology Inc. <ryan_chen@aspeedtech.com>
++ * http://www.aspeedtech.com/
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * ASPEED PECI Controller
++*/
++
++#ifndef __ASM_ARCH_REGS_PECI_H
++#define __ASM_ARCH_REGS_PECI_H __FILE__
++
++/*AST PECI Register Definition */
++#define AST_PECI_CTRL 0x00
++#define AST_PECI_TIMING 0x04
++#define AST_PECI_CMD 0x08
++#define AST_PECI_CMD_CTRL 0x0C
++#define AST_PECI_EXP_FCS 0x10
++#define AST_PECI_CAP_FCS 0x14
++#define AST_PECI_INT_CTRL 0x18
++#define AST_PECI_INT_STS 0x1C
++#define AST_PECI_W_DATA0 0x20
++#define AST_PECI_W_DATA1 0x24
++#define AST_PECI_W_DATA2 0x28
++#define AST_PECI_W_DATA3 0x2c
++#define AST_PECI_R_DATA0 0x30
++#define AST_PECI_R_DATA1 0x34
++#define AST_PECI_R_DATA2 0x38
++#define AST_PECI_R_DATA3 0x3c
++#define AST_PECI_W_DATA4 0x40
++#define AST_PECI_W_DATA5 0x44
++#define AST_PECI_W_DATA6 0x48
++#define AST_PECI_W_DATA7 0x4c
++#define AST_PECI_R_DATA4 0x50
++#define AST_PECI_R_DATA5 0x54
++#define AST_PECI_R_DATA6 0x58
++#define AST_PECI_R_DATA7 0x5c
++
++
++/* AST_PECI_CTRL - 0x00 : Control Register */
++#define PECI_CTRL_SAMPLING_MASK (0xf << 16)
++#define PECI_CTRL_SAMPLING(x) (x << 16)
++#define PECI_CTRL_READ_MODE_MASK (0xf << 12)
++#define PECI_CTRL_CONT_MODE (1 << 16)
++#define PECI_CTRL_DBG_MODE (2 << 16)
++#define PECI_CTRL_CLK_SOURCE (0x1 << 11) //0: 24Mhz, 1: MCLK
++#define PECI_CTRL_CLK_DIV_MASK (0x3 << 8)
++#define PECI_CTRL_CLK_DIV(x) (x << 8)
++#define PECI_CTRL_INVERT_OUT (0x1 << 7)
++#define PECI_CTRL_INVERT_IN (0x1 << 6)
++#define PECI_CTRL_BUS_CONTENT_EN (0x1 << 5)
++#define PECI_CTRL_PECI_EN (0x1 << 4)
++#define PECI_CTRL_PECI_CLK_EN (0x1)
++
++/* AST_PECI_TIMING - 0x04 : Timing Negotiation */
++#define PECI_TIMING_MESSAGE_GET(x) ((x & 0xff00) >> 8)
++#define PECI_TIMING_MESSAGE(x) (x << 8)
++#define PECI_TIMING_ADDRESS_GET(x) (x & 0xff)
++#define PECI_TIMING_ADDRESS(x) (x)
++
++/* AST_PECI_CMD - 0x08 : Command Register */
++#define PECI_CMD_PIN_MON (0x1 << 31)
++#define PECI_CMD_STS (0xf << 24)
++#define PECI_CMD_FIRE (0x1)
++
++/* AST_PECI_LEN - 0x0C : Read/Write Length Register */
++#define PECI_AW_FCS_EN (0x1 << 31)
++#define PECI_READ_LEN_MASK (0xff << 16)
++#define PECI_READ_LEN(x) (x << 16)
++#define PECI_WRITE_LEN_MASK (0xff << 8)
++#define PECI_WRITE_LEN(x) (x << 8)
++#define PECI_TAGET_ADDR_MASK (0xff)
++#define PECI_TAGET_ADDR(x) (x)
++
++
++/* AST_PECI_EXP_FCS - 0x10 : Expected FCS Data Register */
++#define PECI_PROGRAM_AW_FCS (0xf << 24)
++#define PECI_EXPECT_READ_FCS (0xf << 16)
++#define PECI_EXPECT_AW_FCS_AUTO (0xf << 8)
++#define PECI_EXPECT_WRITE_FCS (0xf)
++
++/* AST_PECI_CAP_FCS - 0x14 : Captured FCS Data Register */
++#define PECI_CAPTURE_READ_FCS(x) ((x & 0xff) >> 16)
++#define PECI_CAPTURE_WRITE_FCS (0xff)
++
++/* AST_PECI_INT_CTRL/ STS - 0x18/0x1c : Interrupt Register */
++#define PECI_INT_TIMING_RESULT_MASK (0x3 << 30)
++#define PECI_INT_TIMEOUT (0x1 << 4)
++#define PECI_INT_CONNECT (0x1 << 3)
++#define PECI_INT_W_FCS_BAD (0x1 << 2)
++#define PECI_INT_W_FCS_ABORT (0x1 << 1)
++#define PECI_INT_CMD_DONE (0x1)
++
++#define AUTO_GEN_AWFCS 1
++//#define ENABLE_BUS_CONTENTION 0x20
++
++#define DISABLE_ENGINE 0
++#define ENABLE_RX_ENGINE (1 << 0)
++#define ENABLE_TX_ENGINE (1 << 1)
++#define LEFT_CHANNEL_HIGH (1 << 16)
++#define DELAY_CLOCK_CYCLE (1 << 17)
++
++#endif /* __ASM_ARCH_REGS_PECI_H */
+diff --git a/arch/arm/plat-aspeed/include/plat/regs-pwm_fan.h b/arch/arm/plat-aspeed/include/plat/regs-pwm_fan.h
+new file mode 100644
+index 0000000..23d5b77
+--- /dev/null
++++ b/arch/arm/plat-aspeed/include/plat/regs-pwm_fan.h
+@@ -0,0 +1,250 @@
++/* arch/arm/plat-aspeed/include/mach/regs-pwm-fan.h
++ *
++ * Copyright (c) 2012 ASPEED Technology Inc. <ryan_chen@aspeedtech.com>
++ * http://www.aspeedtech.com/
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * ASPEED PWM & Fan Tacho Controller
++*/
++
++#ifndef __ASM_ARCH_REGS_PWM_FAN_H
++#define __ASM_ARCH_REGS_PWM_FAN_H __FILE__
++
++/*AST PWM & FAN Register Definition */
++#define AST_PTCR_CTRL 0x00
++#define AST_PTCR_CLK_CTRL 0x04
++#define AST_PTCR_DUTY0_CTRL 0x08
++#define AST_PTCR_DUTY1_CTRL 0x0c
++#define AST_PTCR_TYPEM_CTRL0 0x10
++#define AST_PTCR_TYPEM_CTRL1 0x14
++#define AST_PTCR_TYPEN_CTRL0 0x18
++#define AST_PTCR_TYPEN_CTRL1 0x1c
++#define AST_PTCR_TACH_SOURCE 0x20
++// no 0x24
++#define AST_PTCR_TRIGGER 0x28
++#define AST_PTCR_RESULT 0x2c
++#define AST_PTCR_INTR_CTRL 0x30
++#define AST_PTCR_INTR_STS 0x34
++#define AST_PTCR_TYPEM_LIMIT 0x38
++#define AST_PTCR_TYPEN_LIMIT 0x3C
++#define AST_PTCR_CTRL_EXT 0x40
++#define AST_PTCR_CLK_EXT_CTRL 0x44
++#define AST_PTCR_DUTY2_CTRL 0x48
++#define AST_PTCR_DUTY3_CTRL 0x4c
++#define AST_PTCR_TYPEO_CTRL0 0x50
++#define AST_PTCR_TYPEO_CTRL1 0x54
++#define AST_PTCR_TACH_SOURCE_EXT 0x60
++#define AST_PTCR_TYPEO_LIMIT 0x78
++
++//COMMON Definition
++#define FALL_EDGE (0)
++#define RISE_EDGE (0x1)
++#define BOTH_EDGE (0x2)
++
++#ifdef CONFIG_ARCH_AST1010
++#define PWM_TYPE_NUM 2
++#define PWM_TYPE_M 0x0
++#define PWM_TYPE_N 0x1
++#define PWM_TYPE_MASK 0x1
++#else
++#define PWM_TYPE_NUM 3
++#define PWM_TYPE_M 0x0
++#define PWM_TYPE_N 0x1
++#define PWM_TYPE_O 0x2
++#define PWM_TYPE_MASK 0x3
++
++#endif
++
++#define TACHO_NUM 16
++#define PWM_CH_NUM 8
++#define PWMA 0x0
++#define PWMB 0x1
++#define PWMC 0x2
++#define PWMD 0x3
++#define PWME 0x4
++#define PWMF 0x5
++#define PWMG 0x6
++#define PWMH 0x7
++
++
++// AST_PTCR_CTRL:0x00 - PWM-FAN General Control Register
++#define AST_PTCR_CTRL_SET_PWMD_TYPE(x) ((x&0x1)<<15 | (x&0x2) <<6)
++#define AST_PTCR_CTRL_GET_PWMD_TYPE(x) (((x&(0x1<<7))>>6) | ((x&(0x1<<15))>>15))
++#define AST_PTCR_CTRL_SET_PWMD_TYPE_MASK ((0x1<<7) | (0x1<<15))
++
++#define AST_PTCR_CTRL_SET_PWMC_TYPE(x) ((x&0x1)<<14 | (x&0x2) <<5)
++#define AST_PTCR_CTRL_GET_PWMC_TYPE(x) (((x&(0x1<<6))>>5) | ((x&(0x1<<14))>>14))
++#define AST_PTCR_CTRL_SET_PWMC_TYPE_MASK ((0x1<<6) | (0x1<<14))
++
++#define AST_PTCR_CTRL_SET_PWMB_TYPE(x) ((x&0x1)<<13 | (x&0x2) <<4)
++#define AST_PTCR_CTRL_GET_PWMB_TYPE(x) (((x&(0x1<<5))>>4) | ((x&(0x1<<13))>>13))
++#define AST_PTCR_CTRL_SET_PWMB_TYPE_MASK ((0x1<<5) | (0x1<<13))
++
++
++#define AST_PTCR_CTRL_SET_PWMA_TYPE(x) ((x&0x1)<<12 | (x&0x2) <<3)
++#define AST_PTCR_CTRL_GET_PWMA_TYPE(x) (((x&(0x1<<4))>>3) | ((x&(0x1<<12))>>12))
++#define AST_PTCR_CTRL_SET_PWMA_TYPE_MASK ((0x1<<4) | (0x1<<12))
++
++#define AST_PTCR_CTRL_FAN_NUM_EN(x) (0x1 << (16+x))
++
++#define AST_PTCR_CTRL_PMWD (11)
++#define AST_PTCR_CTRL_PMWD_EN (0x1 << 11)
++#define AST_PTCR_CTRL_PMWC (10)
++#define AST_PTCR_CTRL_PMWC_EN (0x1 << 10)
++#define AST_PTCR_CTRL_PMWB (9)
++#define AST_PTCR_CTRL_PMWB_EN (0x1 << 9)
++#define AST_PTCR_CTRL_PMWA (8)
++#define AST_PTCR_CTRL_PMWA_EN (0x1 << 8)
++
++#define AST_PTCR_CTRL_CLK_MCLK 0x2 //0:24Mhz, 1:MCLK
++#define AST_PTCR_CTRL_CLK_EN 0x1
++
++// AST_PTCR_CLK_CTRL:0x04 - PWM-FAN Clock Control Register
++//TYPE N
++#define AST_PTCR_CLK_CTRL_TYPEN_UNIT (24)
++#define AST_PTCR_CLK_CTRL_TYPEN_UNIT_MASK (0xff<<24)
++#define AST_PTCR_CLK_CTRL_TYPEN_H (20)
++#define AST_PTCR_CLK_CTRL_TYPEN_H_MASK (0xf<<20)
++#define AST_PTCR_CLK_CTRL_TYPEN_L (16)
++#define AST_PTCR_CLK_CTRL_TYPEN_L_MASK (0xf<<16)
++//TYPE M
++#define AST_PTCR_CLK_CTRL_TYPEM_UNIT (8)
++#define AST_PTCR_CLK_CTRL_TYPEM_UNIT_MASK (0xff<<8)
++#define AST_PTCR_CLK_CTRL_TYPEM_H (4)
++#define AST_PTCR_CLK_CTRL_TYPEM_H_MASK (0xf<<4)
++#define AST_PTCR_CLK_CTRL_TYPEM_L (0)
++#define AST_PTCR_CLK_CTRL_TYPEM_L_MASK (0xf)
++
++
++// AST_PTCR_DUTY_CTRL0:0x08 - PWM-FAN duty control 0 register
++#define DUTY_CTRL0_PWMB_FALL_POINT (24)
++#define DUTY_CTRL0_PWMB_FALL_POINT_MASK (0xff<<24)
++#define DUTY_CTRL0_PWMB_RISE_POINT (16)
++#define DUTY_CTRL0_PWMB_RISE_POINT_MASK (0xff<<16)
++#define DUTY_CTRL0_PWMA_FALL_POINT (8)
++#define DUTY_CTRL0_PWMA_FALL_POINT_MASK (0xff<<8)
++#define DUTY_CTRL0_PWMA_RISE_POINT (0)
++#define DUTY_CTRL0_PWMA_RISE_POINT_MASK (0xff)
++
++
++// AST_PTCR_DUTY_CTRL1 : 0x0c - PWM-FAN duty control 1 register
++#define DUTY_CTRL1_PWMD_FALL_POINT (24)
++#define DUTY_CTRL1_PWMD_FALL_POINT_MASK (0xff<<24)
++#define DUTY_CTRL1_PWMD_RISE_POINT (16)
++#define DUTY_CTRL1_PWMD_RISE_POINT_MASK (0xff<<16)
++#define DUTY_CTRL1_PWMC_FALL_POINT (8)
++#define DUTY_CTRL1_PWMC_FALL_POINT_MASK (0xff<<8)
++#define DUTY_CTRL1_PWMC_RISE_POINT (0)
++#define DUTY_CTRL1_PWMC_RISE_POINT_MASK (0xff)
++
++
++// AST_PTCR_TYPEM_CTRL0 : 0x10/0x18/0x50 - Type M/N/O Ctrl 0 Register
++#define TYPE_CTRL0_FAN_PERIOD (16)
++#define TYPE_CTRL0_FAN_PERIOD_MASK (0xffff<<16)
++//Type O not have this
++#define TYPE_CTRL0_FLAT_EN (0x1<<7)
++
++
++// 0 : FALL_EDGE, 0x1 : RISE_EDGE , 0x2 :BOTH_EDGE
++#define TYPE_CTRL0_FAN_MODE (4)
++#define TYPE_CTRL0_FAN_MODE_MASK (0x3<<4)
++
++
++
++#define TYPE_CTRL0_CLK_DIVISION (1)
++#define TYPE_CTRL0_CLK_DIVISION_MASK (0x7<<1)
++
++#define TYPE_CTRL0_FAN_TYPE_EN (1)
++
++
++// AST_PTCR_TYPEM_CTRL1 : 0x14/0x1c/0x54 - Type M/N/O Ctrl 1 Register
++#define TYPE_CTRL1_FALL_POINT (16)
++#define TYPE_CTRL1_FALL_POINT_MASK (0xff<<16)
++#define TYPE_CTRL1_RISE_POINT (0)
++#define TYPE_CTRL1_RISE_POINT_MASK (0xff)
++
++
++// AST_PTCR_TACH_SOURCE : 0x20/0x60 - Tach Source Register
++//bit [0,1] at 0x20, bit [2] at 0x60
++#define TACH_PWM_SOURCE_BIT01(x) (x*2)
++#define TACH_PWM_SOURCE_BIT2(x) (x*2)
++
++#define TACH_PWM_SOURCE_MASK_BIT01(x) (0x3<<(x*2))
++#define TACH_PWM_SOURCE_MASK_BIT2(x) (0x1<<(x*2))
++
++// AST_PTCR_TRIGGER : 0x28 - Trigger Register
++#define TRIGGER_READ_FAN_NUM(x) (0x1<<x)
++
++// AST_PTCR_RESULT : 0x2c - Result Register
++#define RESULT_STATUS (31)
++
++#define RESULT_VALUE_MASK (0xfffff)
++
++// AST_PTCR_INTR_CTRL : 0x30 - Interrupt Ctrl Register
++#define INTR_CTRL_EN_NUM(x) (0x1<<x)
++
++// AST_PTCR_INTR_STS : 0x34 - Interrupt Status Register
++#define INTR_CTRL_NUM(x) (0x1<<x)
++
++//AST_PTCR_TYPEM_LIMIT, AST_PTCR_TYPEN_LIMIT,AST_PTCR_TYPEO_LIMIT : 0x38/0x3C/0x78 - Type M / N / O Limit Register
++#define FAN_LIMIT_MASK (0xfffff)
++
++// AST_PTCR_CTRL_EXT : 0x40 - General Ctrl Extension #1
++#define AST_PTCR_CTRL_SET_PWMH_TYPE(x) ((x&0x1)<<15 | (x&0x2) <<6)
++#define AST_PTCR_CTRL_GET_PWMH_TYPE(x) (((x&(0x1<<7))>>6) | ((x&(0x1<<15))>>15))
++#define AST_PTCR_CTRL_SET_PWMH_TYPE_MASK ((0x1<<7) | (0x1<<15))
++
++#define AST_PTCR_CTRL_SET_PWMG_TYPE(x) ((x&0x1)<<14 | (x&0x2) <<5)
++#define AST_PTCR_CTRL_GET_PWMG_TYPE(x) (((x&(0x1<<6))>>5) | ((x&(0x1<<14))>>14))
++#define AST_PTCR_CTRL_SET_PWMG_TYPE_MASK ((0x1<<6) | (0x1<<14))
++
++#define AST_PTCR_CTRL_SET_PWMF_TYPE(x) ((x&0x1)<<13 | (x&0x2) <<4)
++#define AST_PTCR_CTRL_GET_PWMF_TYPE(x) (((x&(0x1<<5))>>4) | ((x&(0x1<<13))>>13))
++#define AST_PTCR_CTRL_SET_PWMF_TYPE_MASK ((0x1<<5) | (0x1<<13))
++
++#define AST_PTCR_CTRL_SET_PWME_TYPE(x) ((x&0x1)<<12 | (x&0x2) <<3)
++#define AST_PTCR_CTRL_GET_PWME_TYPE(x) (((x&(0x1<<4))>>3) | ((x&(0x1<<12))>>12))
++#define AST_PTCR_CTRL_SET_PWME_TYPE_MASK ((0x1<<4) | (0x1<<12))
++
++#define AST_PTCR_CTRL_PMWH (11)
++#define AST_PTCR_CTRL_PMWH_EN (0x1 << 11)
++#define AST_PTCR_CTRL_PMWG (10)
++#define AST_PTCR_CTRL_PMWG_EN (0x1 << 10)
++#define AST_PTCR_CTRL_PMWF (9)
++#define AST_PTCR_CTRL_PMWF_EN (0x1 << 9)
++#define AST_PTCR_CTRL_PMWE (8)
++#define AST_PTCR_CTRL_PMWE_EN (0x1 << 8)
++
++// AST_PTCR_CLK_EXT_CTRL : 0x44 - Clock Control Extension #1
++//TYPE O
++#define AST_PTCR_CLK_CTRL_TYPEO_UNIT (8)
++#define AST_PTCR_CLK_CTRL_TYPEO_UNIT_MASK (0xff<<8)
++#define AST_PTCR_CLK_CTRL_TYPEO_H (4)
++#define AST_PTCR_CLK_CTRL_TYPEO_H_MASK (0xf<<4)
++#define AST_PTCR_CLK_CTRL_TYPEO_L (0)
++#define AST_PTCR_CLK_CTRL_TYPEO_L_MASK (0xf)
++
++// AST_PTCR_DUTY2_CTRL : 0x48 - Duty Control 2 Register
++#define DUTY_CTRL2_PWMF_FALL_POINT (24)
++#define DUTY_CTRL2_PWMF_FALL_POINT_MASK (0xff<<24)
++#define DUTY_CTRL2_PWMF_RISE_POINT (16)
++#define DUTY_CTRL2_PWMF_RISE_POINT_MASK (0xff<<16)
++#define DUTY_CTRL2_PWME_FALL_POINT (8)
++#define DUTY_CTRL2_PWME_FALL_POINT_MASK (0xff<<8)
++#define DUTY_CTRL2_PWME_RISE_POINT (0)
++#define DUTY_CTRL2_PWME_RISE_POINT_MASK (0xff)
++
++// AST_PTCR_DUTY3_CTRL : 0x4c - Duty Control 3 Register
++#define DUTY_CTRL3_PWMH_FALL_POINT (24)
++#define DUTY_CTRL3_PWMH_FALL_POINT_MASK (0xff<<24)
++#define DUTY_CTRL3_PWMH_RISE_POINT (16)
++#define DUTY_CTRL3_PWMH_RISE_POINT_MASK (0xff<<16)
++#define DUTY_CTRL3_PWMG_FALL_POINT (8)
++#define DUTY_CTRL3_PWMG_FALL_POINT_MASK (0xff<<8)
++#define DUTY_CTRL3_PWMG_RISE_POINT (0)
++#define DUTY_CTRL3_PWMG_RISE_POINT_MASK (0xff)
++
++#endif /* __ASM_ARCH_REGS_PWM_FAN_H */
+diff --git a/arch/arm/plat-aspeed/include/plat/regs-rtc.h b/arch/arm/plat-aspeed/include/plat/regs-rtc.h
+new file mode 100644
+index 0000000..8a09a4b
+--- /dev/null
++++ b/arch/arm/plat-aspeed/include/plat/regs-rtc.h
+@@ -0,0 +1,64 @@
++/* arch/arm/plat-aspeed/include/mach/regs-iic.h
++ *
++ * Copyright (c) 2012 ASPEED Technology Inc. <ryan_chen@aspeedtech.com>
++ * http://www.aspeedtech.com/
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * ASPEED I2C Controller
++*/
++
++#ifndef __ASM_ARCH_REGS_RTC_H
++#define __ASM_ARCH_REGS_RTC_H __FILE__
++
++#define RTC_CNTR_STS_1 0x00
++#define RTC_CNTR_STS_2 0x04
++#define RTC_ALARM 0x08
++#define RTC_CONTROL 0x10
++#define RTC_ALARM_STS 0x14
++
++/* RTC_CNTR_STS_1 0x00 */
++/* RTC_ALARM 0x08 */
++#define GET_DAY_VAL(x) ((x >> 24)&0x1f)
++#define GET_HOUR_VAL(x) ((x >> 16)&0x1f)
++#define GET_MIN_VAL(x) ((x >> 8)&0x3f)
++#define GET_SEC_VAL(x) (x & 0x3f)
++
++#define SET_DAY_VAL(x) ((x&0x1f) << 24)
++#define SET_HOUR_VAL(x) ((x&0x1f) << 16)
++#define SET_MIN_VAL(x) ((x&0x3f) << 8)
++#define SET_SEC_VAL(x) (x & 0x3f)
++
++/* RTC_CNTR_STS_2 0x04 */
++#define GET_CENT_VAL(x) ((x >> 16)&0x1f)
++#define GET_YEAR_VAL(x) ((x >> 8)&0x7f)
++#define GET_MON_VAL(x) (x & 0xf)
++
++#define SET_CENT_VAL(x) ((x &0x1f) << 16)
++#define SET_YEAR_VAL(x) ((x &0x7f) << 8)
++#define SET_MON_VAL(x) (x & 0xf)
++
++/* RTC_CONTROL 0x10 */
++#define ENABLE_SEC_INTERRUPT (1 << 7)
++#define ENABLE_DAY_ALARM (1 << 6)
++#define ENABLE_HOUR_ALARM (1 << 5)
++#define ENABLE_MIN_ALARM (1 << 4)
++#define ENABLE_SEC_ALARM (1 << 3)
++#define ALARM_MODE_SELECT (1 << 2)
++#define RTC_LOCK (1 << 1)
++#define RTC_ENABLE (1 << 0)
++#define ENABLE_ALL_ALARM 0x0000007c
++
++
++/* RTC_ALARM_STS 0x14 */
++#define SEC_INTERRUPT_STATUS (1 << 4)
++#define DAY_ALARM_STATUS (1 << 3)
++#define HOUR_ALARM_STATUS (1 << 2)
++#define MIN_ALARM_STATUS (1 << 1)
++#define SEC_ALARM_STATUS (1 << 0)
++
++
++
++#endif /* __ASM_ARCH_REGS_RTC_H */
+diff --git a/arch/arm/plat-aspeed/include/plat/regs-scu-g5.h b/arch/arm/plat-aspeed/include/plat/regs-scu-g5.h
+new file mode 100644
+index 0000000..0720be5
+--- /dev/null
++++ b/arch/arm/plat-aspeed/include/plat/regs-scu-g5.h
+@@ -0,0 +1,702 @@
++/* arch/arm/mach-aspeed/include/mach/regs-ast2300-scu.h
++ *
++ * Copyright (C) 2012-2020 ASPEED Technology Inc.
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * History :
++ * 1. 2012/12/29 Ryan Chen Create
++ *
++********************************************************************************/
++#ifndef __AST_SCU_G5_REGS_H
++#define __AST_SCU_G5_REGS_H 1
++
++/*
++ * Register for SCU
++ * */
++#define AST_SCU_PROTECT 0x00 /* protection key register */
++#define AST_SCU_RESET 0x04 /* system reset control register */
++#define AST_SCU_CLK_SEL 0x08 /* clock selection register */
++#define AST_SCU_CLK_STOP 0x0C /* clock stop control register */
++#define AST_SCU_COUNT_CTRL 0x10 /* frequency counter control register */
++#define AST_SCU_INTR_CTRL 0x14 /* Interrupt control and status register */
++#define AST_SCU_D1_PLL 0x18 /* D1-PLL Parameter register */
++#define AST_SCU_D2_PLL 0x1C /* D2-PLL Parameter register */
++#define AST_SCU_M_PLL 0x20 /* M-PLL Parameter register */
++#define AST_SCU_H_PLL 0x24 /* H-PLL Parameter register */
++#define AST_SCU_FREQ_LIMIT 0x28 /* frequency counter comparsion register */
++#define AST_SCU_MISC1_CTRL 0x2C /* Misc. Control register */
++#define AST_SCU_PCI_CONF1 0x30 /* PCI configuration setting register#1 */
++#define AST_SCU_PCI_CONF2 0x34 /* PCI configuration setting register#2 */
++#define AST_SCU_PCI_CONF3 0x38 /* PCI configuration setting register#3 */
++#define AST_SCU_SYS_CTRL 0x3C /* System reset contrl/status register*/
++#define AST_SCU_SOC_SCRATCH0 0x40 /* SOC scratch 0~31 register */
++#define AST_SCU_SOC_SCRATCH1 0x44 /* SOC scratch 32~63 register */
++#define AST_SCU_VGA0 0x40 /* VGA fuction handshake register */
++#define AST_SCU_VGA1 0x44 /* VGA fuction handshake register */
++#define AST_SCU_MAC_CLK 0x48 /* MAC interface clock delay setting register */
++#define AST_SCU_MISC2_CTRL 0x4C /* Misc. 2 Control register */
++#define AST_SCU_VGA_SCRATCH0 0x50 /* VGA Scratch register */
++#define AST_SCU_VGA_SCRATCH1 0x54 /* VGA Scratch register */
++#define AST_SCU_VGA_SCRATCH2 0x58 /* VGA Scratch register */
++#define AST_SCU_VGA_SCRATCH3 0x5c /* VGA Scratch register */
++#define AST_SCU_VGA_SCRATCH4 0x60 /* VGA Scratch register */
++#define AST_SCU_VGA_SCRATCH5 0x64 /* VGA Scratch register */
++#define AST_SCU_VGA_SCRATCH6 0x68 /* VGA Scratch register */
++#define AST_SCU_VGA_SCRATCH7 0x6c /* VGA Scratch register */
++#define AST_SCU_HW_STRAP1 0x70 /* hardware strapping register */
++#define AST_SCU_RAMDOM_GEN 0x74 /* random number generator register */
++#if defined(CONFIG_ARCH_1100) || defined(CONFIG_ARCH_2050) || defined(CONFIG_ARCH_2100) || defined(CONFIG_ARCH_2200)
++#define AST_SCU_MULTI_FUNC_2 0x78
++#else
++#define AST_SCU_RAMDOM_DATA 0x78 /* random number generator data output*/
++#endif
++#define AST_SCU_REVISION_ID 0x7C /* Silicon revision ID register */
++#define AST_SCU_FUN_PIN_CTRL1 0x80 /* Multi-function Pin Control#1*/
++#define AST_SCU_FUN_PIN_CTRL2 0x84 /* Multi-function Pin Control#2*/
++#define AST_SCU_FUN_PIN_CTRL3 0x88 /* Multi-function Pin Control#3*/
++#define AST_SCU_FUN_PIN_CTRL4 0x8C /* Multi-function Pin Control#4*/
++#define AST_SCU_FUN_PIN_CTRL5 0x90 /* Multi-function Pin Control#5*/
++#define AST_SCU_FUN_PIN_CTRL6 0x94 /* Multi-function Pin Control#6*/
++#define AST_SCU_WDT_RESET 0x9C /* Watchdog Reset Selection */
++#define AST_SCU_FUN_PIN_CTRL7 0xA0 /* Multi-function Pin Control#7*/
++#define AST_SCU_FUN_PIN_CTRL8 0xA4 /* Multi-function Pin Control#8*/
++#define AST_SCU_FUN_PIN_CTRL9 0xA8 /* Multi-function Pin Control#9*/
++#define AST_SCU_PWR_SAVING_EN 0xC0 /* Power Saving Wakeup Enable*/
++#define AST_SCU_PWR_SAVING_CTRL 0xC4 /* Power Saving Wakeup Control*/
++#define AST_SCU_HW_STRAP2 0xD0 /* Haardware strapping register set 2*/
++#define AST_SCU_COUNTER4 0xE0 /* SCU Free Run Counter Read Back #4*/
++#define AST_SCU_COUNTER4_EXT 0xE4 /* SCU Free Run Counter Extended Read Back #4*/
++
++//CPU 2
++#define AST_SCU_CPU2_CTRL 0x100 /* CPU2 Control Register*/
++#define AST_SCU_CPU2_BASE0_ADDR 0x104 /* CPU2 Base Address for Segment 0x00:0000~0x1F:FFFF*/
++#define AST_SCU_CPU2_BASE1_ADDR 0x108 /* CPU2 Base Address for Segment 0x20:0000~0x3F:FFFF*/
++#define AST_SCU_CPU2_BASE2_ADDR 0x10C /* CPU2 Base Address for Segment 0x40:0000~0x5F:FFFF*/
++#define AST_SCU_CPU2_BASE3_ADDR 0x110 /* CPU2 Base Address for Segment 0x60:0000~0x7F:FFFF*/
++#define AST_SCU_CPU2_BASE4_ADDR 0x114 /* CPU2 Base Address for Segment 0x80:0000~0xFF:FFFF*/
++#define AST_SCU_CPU2_CACHE_CTRL 0x118 /* CPU2 Cache Function Control */
++
++//
++#define AST_SCU_UART24_REF 0x160 /* Generate UART 24Mhz Ref from H-PLL when CLKIN is 25Mhz */
++#define AST_SCU_PCIE_CONFIG_SET 0x180 /* PCI-E Configuration Setting Control Register */
++#define AST_SCU_BMC_MMIO_DEC 0x184 /* BMC MMIO Decode Setting Register */
++#define AST_SCU_DEC_AREA1 0x188 /* 1st relocated controller decode area location */
++#define AST_SCU_DEC_AREA2 0x18C /* 2nd relocated controller decode area location */
++#define AST_SCU_MBOX_DEC_AREA 0x190 /* Mailbox decode area location*/
++#define AST_SCU_SRAM_DEC_AREA0 0x194 /* Shared SRAM area decode location*/
++#define AST_SCU_SRAM_DEC_AREA1 0x198 /* Shared SRAM area decode location*/
++#define AST_SCU_BMC_CLASS 0x19C /* BMC device class code and revision ID */
++#define AST_SCU_BMC_DEV_ID 0x1A4 /* BMC device ID */
++
++
++/* AST_SCU_PROTECT: 0x00 - protection key register */
++#define SCU_PROTECT_UNLOCK 0x1688A8A8
++
++/* AST_SCU_RESET :0x04 - system reset control register */
++#define SCU_RESET_I2S (0x1 << 31)
++#define SCU_RESET_IR (0x1 << 30)
++#define SCU_RESET_PS21 (0x1 << 29)
++#define SCU_RESET_PS20 (0x1 << 28)
++#define SCU_PWAKE_PIN_EN (0x1 << 27)
++#define SCU_PWAKE_PIN_OUT (0x1 << 26
++#define SCU_RESET_X_DMA (0x1 << 25)
++#define SCU_RESET_MCTP (0x1 << 24)
++//#define SCU_RESET_ADC (0x1 << 23) reserved
++#define SCU_RESET_JTAG (0x1 << 22)
++#define SCU_RESET_PCIE_EN (0x1 << 21)
++#define SCU_RESET_PCIE_OUT (0x1 << 20)
++#define SCU_RESET_PCIE (0x1 << 19)
++#define SCU_RESET_H264 (0x1 << 18)
++#define SCU_RESET_RFX (0x1 << 17)
++#define SCU_RESET_SD (0x1 << 16)
++#define SCU_RESET_USB11 (0x1 << 15)
++#define SCU_RESET_USB20 (0x1 << 14)
++#define SCU_RESET_CRT (0x1 << 13)
++//#define SCU_RESET_MAC1 (0x1 << 12) reserved
++#define SCU_RESET_MAC0 (0x1 << 11)
++//#define SCU_RESET_PECI (0x1 << 10)
++//#define SCU_RESET_PWM (0x1 << 9)
++#define SCU_PCI_VGA_DIS (0x1 << 8)
++#define SCU_RESET_2D (0x1 << 7)
++#define SCU_RESET_VIDEO (0x1 << 6)
++//#define SCU_RESET_LPC (0x1 << 5)
++#define SCU_RESET_HAC (0x1 << 4)
++//#define SCU_RESET_USB11_HID (0x1 << 3)
++#define SCU_RESET_I2C (0x1 << 2)
++#define SCU_RESET_AHB (0x1 << 1)
++#define SCU_RESET_SRAM_CTRL (0x1 << 0)
++
++/* AST_SCU_CLK_SEL : 0x08 - clock selection register */
++#define SCU_CLK_VIDEO_SLOW_EN (0x1 << 31)
++#define SCU_CLK_VIDEO_SLOW_SET(x) ((x & 0x7) << 28)
++#define SCU_CLK_VIDEO_SLOW_MASK (0x7 << 28)
++#define SCU_CLK_2D_ENG_GCLK_INVERT (0x1 << 27) //valid only at CRT mode SCU2C[7]
++#define SCU_CLK_2D_ENG_THROT_EN (0x1 << 26) //valid only at CRT mode SCU2C[7]
++#define SCU_PCLK_APB_DIV(x) ((x & 0x7) << 23)
++#define SCU_GET_PCLK_DIV(x) ((x >> 23) & 0x7)
++#define SCU_PCLK_APB_DIV_MASK (0x7 << 23) //limitation on PCLK .. PCLK > 0.5*LCLK (33Mhz)
++//#define SCU_GET_LHCLK_DIV(x) ((x >> 20) & 0x7)
++//#define SCU_SET_LHCLK_DIV(x) (x << 20)
++//#define SCU_LHCLK_DIV_MASK (0x7 << 20)
++//#define SCU_LHCLK_SOURCE_EN (0x1 << 19) //0: ext , 1:internel
++#define SCU_SET_MAC_DIV(x) ((x & 0x7) << 16)
++#define SCU_GET_MAC_DIV(x) ((x >> 16) & 0x7)
++#define SCU_CLK_MAC_MASK (0x7 << 16)
++#define SCU_CLK_SD_EN (0x1 << 15)
++#define SCU_SET_SD_DIV(x) ((x & 0x7) << 12)
++#define SCU_GET_SD_DIV(x) ((x >> 12) & 0x7)
++#define SCU_CLK_SD_MASK (0x7 << 12)
++//
++#define SCU_CLK_VIDEO_DELAY(x) ((x & 0xf) << 8)
++#define SCU_CLK_VIDEO_DELAY_MASK (0xf << 8)
++#define SCU_CLK_CPU_AHB_SLOW_EN (0x1 << 7)
++#define SCU_CLK_CPU_AHB_SLOW(x) ((x & 0x7) << 4)
++#define SCU_CLK_CPU_AHB_SLOW_MASK (0x7 << 4)
++#define SCU_GET_CPU_AHB_DIV(x) ((x >> 4) & 0x7)
++#define SCU_ECLK_SOURCE(x) (x << 2)
++#define SCU_ECLK_SOURCE_MASK (0x3 << 2)
++#define SCU_CLK_CPU_AHB_SLOW_IDLE (0x1 << 1)
++#define SCU_CLK_CPU_AHB_DYN_SLOW_EN (0x1 << 0)
++
++/* AST_SCU_CLK_STOP : 0x0C - clock stop control register */
++//#define SCU_LHCLK_STOP_EN (0x1 << 28)
++#define SCU_SDCLK_STOP_EN (0x1 << 27)
++#define SCU_IRCLK_STOP_EN (0x1 << 26)
++#define SCU_I2SCLK_STOP_EN (0x1 << 25)
++#define SCU_RSACLK_STOP_EN (0x1 << 24)
++#define SCU_H264CLK_STOP_EN (0x1 << 23)
++//bit 22 must keep 1
++//#define SCU_MAC1CLK_STOP_EN (0x1 << 21)
++#define SCU_MAC0CLK_STOP_EN (0x1 << 20)
++#define SCU_BBCLK_STOP_EN (0x1 << 19)
++#define SCU_RFXCLK_STOP_EN (0x1 << 18)
++#define SCU_UART0_CLK_STOP_EN (0x1 << 17)
++#define SCU_UART2_CLK_STOP_EN (0x1 << 16)
++#define SCU_UART1_CLK_STOP_EN (0x1 << 15)
++#define SCU_USB20_CLK_EN (0x1 << 14)
++#define SCU_YCLK_STOP_EN (0x1 << 13)
++#define SCU_PS2CLK_STOP_EN (0x1 << 12)
++//
++#define SCU_D1CLK_STOP_EN (0x1 << 10)
++#define SCU_USB11CLK_STOP_EN (0x1 << 9)
++#define SCU_D4CLK_STOP_EN (0x1 << 8)
++#define SCU_D3CLK_STOP_EN (0x1 << 7)
++#define SCU_REFCLK_STOP_EN (0x1 << 6)
++#define SCU_D2CLK_STOP_EN (0x1 << 5)
++#define SCU_SACLK_STOP_EN (0x1 << 4)
++#define SCU_VCLK_STOP_EN (0x1 << 3)
++#define SCU_MCLK_STOP_EN (0x1 << 2)
++#define SCU_GCLK_STOP_EN (0x1 << 1)
++#define SCU_ECLK_STOP_EN (0x1 << 0)
++
++/* AST_SCU_COUNT_CTRL : 0x10 - frequency counter control register */
++#define SCU_FREQ_COMP_RESULT (0x1 << 7)
++#define SCU_FREQ_MEASU_FINISH (0x1 << 6)
++#define SCU_FREQ_SOURCE_FOR_MEASU(x) ((x & 0xf) << 2)
++#define SCU_FREQ_SOURCE_FOR_MEASU_MASK (0xf << 2)
++
++#define SCU_SOURCE_6M 0xf
++#define SCU_SOURCE_12M 0xe
++#define SCU_SOURCE_I2SM_CLK 0xd
++#define SCU_SOURCE_H_CLK 0xc
++#define SCU_SOURCE_B_CLK 0xb
++#define SCU_SOURCE_D2_PLL 0xa
++
++#define SCU_SOURCE_VIDEO_CLK 0x7
++#define SCU_SOURCE_LPC_CLK 0x6
++#define SCU_SOURCE_JITTER_CLK 0x5
++#define SCU_SOURCE_M_CLK 0x4
++#define SCU_SOURCE_XP_CLK 0x3
++#define SCU_SOURCE_D_PLL 0x2
++#define SCU_SOURCE_NAND 0x1
++#define SCU_SOURCE_DEL_CELL 0x0
++
++#define SCU_OSC_COUNT_EN (0x1 << 1)
++#define SCU_RING_OSC_EN (0x1 << 0)
++
++/* AST_SCU_INTR_CTRL : 0x14 - Interrupt control and status register */
++//#define INTR_LPC_H_L_RESET (0x1 << 21)
++//#define INTR_LPC_L_H_RESET (0x1 << 20)
++#define INTR_PCIE_H_L_RESET (0x1 << 17)
++#define INTR_PCIE_L_H_RESET (0x1 << 16)
++//#define INTR_VGA_SCRATCH_CHANGE (0x1 << 17)
++//#define INTR_VGA_CURSOR_CHANGE (0x1 << 16)
++#define INTR_MSI_EN (0x1 << 2)
++//#define INTR_LPC_H_L_RESET_EN (0x1 << 1)
++//#define INTR_LPC_L_H_RESET_EN (0x1 << 0)
++#define INTR_PCIE_H_L_RESET_EN (0x1 << 1)
++#define INTR_PCIE_L_H_RESET_EN (0x1 << 0)
++//#define INTR_VGA_SCRATCH_CHANGE_EN (0x1 << 1)
++//#define INTR_VGA_CURSOR_CHANGE_EN (0x1 << 0)
++
++
++/* AST_SCU_D1_PLL: 0x18 - D1-PLL Parameter register */
++#define SCU_D1_PLL_SET_PD2(x) ((x & 0x7) << 19)
++#define SCU_D1_PLL_GET_PD2(x) ((x >> 19) & 0x7)
++#define SCU_D1_PLL_PD2_MASK (0x7 << 19)
++#define SCU_D1_PLL_BYPASS_EN (0x1 << 18)
++#define SCU_D1_PLL_OFF (0x1 << 17)
++#define SCU_D1_PLL_SET_PD(x) ((x & 0x3) << 15)
++#define SCU_D1_PLL_GET_PD(x) ((x >> 15) & 0x3)
++#define SCU_D1_PLL_PD_MASK (0x3 << 15)
++#define SCU_D1_PLL_SET_OD(x) ((x & 0x3) << 13)
++#define SCU_D1_PLL_GET_OD(x) ((x >> 13) & 0x3)
++#define SCU_D1_PLL_OD_MASK (0x3 << 13)
++#define SCU_D1_PLL_SET_DENUM(x) ((x & 0x1f) << 8)
++#define SCU_D1_PLL_GET_DENUM(x) ((x >> 8) & 0x1f)
++#define SCU_D1_PLL_DENUM_MASK (0x1f << 8)
++#define SCU_D1_PLL_SET_NUM(x) (x & 0xff)
++#define SCU_D1_PLL_GET_NUM(x) (x & 0xff)
++#define SCU_D1_PLL_NUM_MASK (0xff)
++
++/* AST_SCU_D2_PLL: 0x1C - D2-PLL Parameter register */
++#define SCU_D2_PLL_SET_PD2(x) ((x & 0x7) << 19)
++#define SCU_D2_PLL_GET_PD2(x) ((x >> 19) & 0x7)
++#define SCU_D2_PLL_PD2_MASK (0x7 << 19)
++#define SCU_D2_PLL_BYPASS_EN (0x1 << 18)
++#define SCU_D2_PLL_OFF (0x1 << 17)
++#define SCU_D2_PLL_SET_PD(x) ((x & 0x3) << 15)
++#define SCU_D2_PLL_GET_PD(x) ((x >> 15) & 0x3)
++#define SCU_D2_PLL_PD_MASK (0x3 << 15)
++#define SCU_D2_PLL_SET_OD(x) ((x & 0x3) << 13)
++#define SCU_D2_PLL_GET_OD(x) ((x >> 13) & 0x3)
++#define SCU_D2_PLL_OD_MASK (0x3 << 13)
++#define SCU_D2_PLL_SET_DENUM(x) ((x & 0x1f) << 8)
++#define SCU_D2_PLL_GET_DENUM(x) ((x >> 8) & 0x1f)
++#define SCU_D2_PLL_DENUM_MASK (0x1f << 8)
++#define SCU_D2_PLL_SET_NUM(x) (x & 0xff)
++#define SCU_D2_PLL_GET_NUM(x) (x & 0xff)
++#define SCU_D2_PLL_NUM_MASK (0xff)
++
++/* AST_SCU_M_PLL : 0x20 - M-PLL Parameter register */
++#define SCU_M_PLL_BYPASS_EN (0x1 << 17)
++#define SCU_M_PLL_OFF (0x1 << 16)
++#define SCU_M_PLL_NUM(x) ((x & 0x3f) << 5)
++#define SCU_M_PLL_GET_NUM(x) ((x >> 5) & 0x3f)
++#define SCU_M_PLL_NUM_MASK (0x3f << 5)
++#define SCU_M_PLL_OUT_DIV (0x1 << 4)
++#define SCU_M_PLL_GET_DIV(x) ((x >> 4) & 0x1)
++#define SCU_M_PLL_SET_DENUM(x) (x & 0xf)
++#define SCU_M_PLL_GET_DENUM(x) (x & 0xf)
++
++/* AST_SCU_H_PLL: 0x24- H-PLL Parameter register */
++#define SCU_H_PLL_BYPASS_EN (0x1 << 17)
++#define SCU_H_PLL_OFF (0x1 << 16)
++#define SCU_H_PLL_SET_NUM(x) ((x & 0x3f) << 5)
++#define SCU_H_PLL_GET_NUM(x) ((x >> 5) & 0x3f)
++#define SCU_H_PLL_NUM_MASK (0x3f << 5)
++#define SCU_H_PLL_OUT_DIV (0x1 << 4)
++#define SCU_H_PLL_GET_DIV(x) ((x >> 4) & 0x1)
++#define SCU_H_PLL_SET_DENUM(x) (x & 0xf)
++#define SCU_H_PLL_GET_DENUM(x) (x & 0xf)
++#define SCU_H_PLL_DENUM_MASK (0xf)
++
++/* AST_SCU_FREQ_LIMIT : 0x28 - frequency counter comparsion register */
++#define SCU_FREQ_U_LIMIT(x) ((x & 0x3fff) << 16)
++#define SCU_FREQ_U_LIMIT_MASK (0x3fff << 16)
++#define SCU_FREQ_L_LIMIT(x) (x & 0x3fff)
++#define SCU_FREQ_L_LIMIT_MASK (0x3fff)
++
++/* AST_SCU_MISC_CTRL : 0x2C - Misc. Control register */
++#define HPLL_MPLL 0
++#define HPLL_DIV2 1
++#define SCU_MISC_24MHZ_BCLK (0x1 << 28)
++#define SCU_MISC_RFX_CLK_SEL(x) ((x & 0x1) << 27)
++#define SCU_MISC_RFX_CLK_HPLL_DIV2 (0x1 << 27)
++#define SCU_MISC_JTAG_MASTER_DIS (0x1 << 26)
++#define SCU_MISC_ST_CLK_HPLL_DIV2 (0x1 << 25)
++#define SCU_MISC_H264_CLK_HPLL_DIV2 (0x1 << 24)
++#define SCU_MISC_AX_CLK_HPLL_DIV2 (0x1 << 23)
++#define SCU_MISC_BB_CLK_HPLL_DIV2 (0x1 << 22)
++#define SCU_MISC_D4_CLK_D2_PLL (0x1 << 21)
++#define SCU_MISC_D3_CLK_D2_PLL (0x1 << 20)
++#define SCU_MISC_D2_CLK_D2_PLL (0x1 << 19)
++#define SCU_MISC_D1_CLK_D2_PLL (0x1 << 18)
++#define SCU_MISC_DAC_MASK (0x3 << 16)
++#define SCU_MISC_DAC_SOURCE_CRT (0x1 << 16) //00 VGA, 01: CRT, 1x: PASS-Through DVO
++#define SCU_MISC_DAC_SOURCE_MASK (0x3 << 16)
++#define SCU_MISC_RST_CRT1_EN (0x1 << 15)
++#define SCU_MISC_RST_CRT2_EN (0x1 << 14)
++#define SCU_MISC_RST_CRT3_EN (0x1 << 13)
++#define SCU_MISC_RST_CRT4_EN (0x1 << 12)
++#define SCU_MISC_Y_CLK_INVERT (0x1 << 11)
++
++#define SCU_MISC_OUT_DELAY (0x1 << 9)
++#define SCU_MISC_PCI_TO_AHB_DIS (0x1 << 8)
++//#define SCU_MISC_2D_CRT_EN (0x1 << 7)
++//#define SCU_MISC_VGA_CRT_DIS (0x1 << 6)
++//#define SCU_MISC_VGA_REG_ACCESS_EN (0x1 << 5)
++#define SCU_MISC_D2_PLL_DIS (0x1 << 4)
++#define SCU_MISC_DAC_DIS (0x1 << 3)
++#define SCU_MISC_D1_PLL_DIS (0x1 << 2)
++#define SCU_MISC_OSC_CLK_OUT_PIN (0x1 << 1)
++//#define SCU_MISC_LPC_TO_SPI_DIS (0x1 << 0)
++
++/* AST_SCU_PCI_CONF1 : 0x30 - PCI configuration setting register#1 */
++#define SCU_PCI_DEVICE_ID(x) (x << 16)
++#define SCU_PCI_VENDOR_ID(x) (x)
++
++/* AST_SCU_PCI_CONF2 0x34 PCI configuration setting register#2 */
++#define SCU_PCI_SUB_SYS_ID(x) (x << 16)
++#define SCU_PCI_SUB_VENDOR_ID(x) (x)
++
++/* AST_SCU_PCI_CONF3 0x38 PCI configuration setting register#3 */
++#define SCU_PCI_CLASS_CODE(x) (x << 8)
++#define SCU_PCI_REVISION_ID(x) (x)
++
++/* AST_SCU_SYS_CTRL 0x3C System reset contrl/status register*/
++#define SCU_SYS_EXT_SOC_RESET_EN (0x1 << 3)
++#define SCU_SYS_EXT_RESET_FLAG (0x1 << 2)
++#define SCU_SYS_WDT_RESET_FLAG (0x1 << 1)
++#define SCU_SYS_PWR_RESET_FLAG (0x1 << 0)
++
++/* AST_SCU_SOC_SCRATCH0 0x40 SOC scratch 0~31 register */
++
++
++
++
++/* AST_SCU_SOC_SCRATCH1 0x44 SOC scratch 32~63 register */
++
++
++/* AST_SCU_VGA0 0x40 VGA fuction handshake register */
++#define SCU_VGA_SLT_HANDSHAKE(x) (x << 24)
++#define SCU_VGA_SLT_HANDSHAKE_MASK (0xff << 24)
++#define SCU_VGA_CTM_DEF(x) (x << 16)
++#define SCU_VGA_CTM_DEF_MASK (0xff << 16)
++#define SCU_MAC0_PHY_MODE(x) (x << 14)
++#define SCU_MAC0_GET_PHY_MODE(x) ((x >> 14) & 0x3)
++#define SCU_MAC0_PHY_MODE_MASK(x) (0x3 << 14)
++#define SCU_MAC1_PHY_MODE(x) (x << 12)
++#define SCU_MAC1_PHY_MODE_MASK (0x3 << 12)
++#define SCU_MAC1_GET_PHY_MODE(x) ((x >> 12) & 0x3)
++
++#define SCU_VGA_ASPEED_DEF(x) (x << 8)
++#define SCU_VGA_ASPEED_DEF_MASK (0xf << 8)
++
++#define SCU_VGA_DRAM_INIT_MASK(x) ((x >> 7) & 0x1)
++
++/* AST_SCU_VGA1 0x44 VGA fuction handshake register */
++
++
++/* AST_SCU_MAC_CLK 0x48 MAC interface clock delay setting register */
++
++
++
++/* AST_SCU_MISC_CTRL 0x4C Misc. 2 Control register */
++/* AST_SCU_VGA_SCRATCH0 0x50 VGA Scratch register */
++/* AST_SCU_VGA_SCRATCH1 0x54 VGA Scratch register */
++/* AST_SCU_VGA_SCRATCH2 0x58 VGA Scratch register */
++/* AST_SCU_VGA_SCRATCH3 0x5c VGA Scratch register */
++/* AST_SCU_VGA_SCRATCH4 0x60 VGA Scratch register */
++/* AST_SCU_VGA_SCRATCH5 0x64 VGA Scratch register */
++/* AST_SCU_VGA_SCRATCH6 0x68 VGA Scratch register */
++/* AST_SCU_VGA_SCRATCH7 0x6c VGA Scratch register */
++
++/* AST_SCU_HW_STRAP1 0x70 hardware strapping register */
++#define SCU_HW_STRAP_SW_DEFINE(x) (x << 29)
++#define SCU_HW_STRAP_SW_DEFINE_MASK (0x3 << 29)
++#define SCU_HW_STRAP_DRAM_SIZE(x) (x << 27)
++#define SCU_HW_STRAP_DRAM_SIZE_MASK (0x3 << 27)
++
++#define VGA_64M_DRAM 0
++#define VGA_128M_DRAM 1
++#define VGA_256M_DRAM 2
++#define VGA_512M_DRAM 3
++
++#define SCU_HW_STRAP_DRAM_CONFIG(x) ((x & 0x7) << 24)
++#define SCU_HW_STRAP_DRAM_CONFIG_MASK (0x7 << 24)
++
++#define SCU_HW_STRAP_SPI_MODE(x) ((x & 0x3) << 12)
++#define SCU_HW_STRAP_SPI_MODE_MASK (0x3 << 12)
++#define SPI_MODE_DIS (0)
++#define SPI_MODE_MASTER_EN (1)
++#define SPI_MODE_M_S_EN (2)
++#define SPI_MODE_PS (3)
++
++#define SCU_HW_STRAP_SET_CPU_AHB_RATIO(x) (x << 10)
++#define SCU_HW_STRAP_GET_CPU_AHB_RATIO(x) ((x >> 10) & 3)
++#define SCU_HW_STRAP_CPU_AHB_RATIO_MASK (0x3 << 10)
++
++
++#define CPU_AHB_RATIO_1_1 0
++#define CPU_AHB_RATIO_2_1 1
++#define CPU_AHB_RATIO_4_1 2
++#define CPU_AHB_RATIO_3_1 3
++
++#define SCU_HW_STRAP_GET_H_PLL_CLK(x) ((x >> 8 )& 0x3)
++#define SCU_HW_STRAP_H_PLL_CLK_MASK (0x3 << 8)
++#define CPU_384MHZ 0
++#define CPU_360MHZ 1
++#define CPU_336MHZ 2
++#define CPU_408MHZ 3
++
++//#define SCU_HW_STRAP_MAC1_INF (0x1 << 7)
++#define SCU_HW_STRAP_MAC0_INF (0x1 << 6)
++//#define SCU_HW_STRAP_VGA_BIOS_ROM (0x1 << 5)
++#define SCU_HW_STRAP_SPI_WIDTH (0x1 << 4)
++//#define SCU_HW_STRAP_VGA_SIZE_GET(x) ((x >> 2)& 0x3)
++
++#define SCU_HW_STRAP_BOOT_MODE(x) (x)
++#define NOR_BOOT 0
++#define NAND_BOOT 1
++#define SPI_BOOT 2
++#define DIS_BOOT 3
++
++/* AST_SCU_RAMDOM_GEN 0x74 random number generator register */
++/* AST_SCU_RAMDOM_DATA 0x78 random number generator data output*/
++
++/* AST_SCU_MULTI_FUNC_2 0x78 */
++
++/* AST_SCU_REVISION_ID 0x7C Silicon revision ID register */
++#define AST1100_A0 0x00000200
++#define AST1100_A1 0x00000201
++#define AST1100_A2 0x00000202
++#define AST1100_A3 0x00000202
++
++#define AST2050_A0 0x00000200
++#define AST2050_A1 0x00000201
++#define AST2050_A2 0x00000202
++#define AST2050_A3 0x00000202
++
++#define AST2100_A0 0x00000300
++#define AST2100_A1 0x00000301
++#define AST2100_A2 0x00000302
++#define AST2100_A3 0x00000302
++
++#define AST2200_A0 0x00000102
++#define AST2200_A1 0x00000102
++
++#define AST2300_A0 0x01000003
++#define AST2300_A1 0x01010303
++#define AST1300_A1 0x01010003
++#define AST1050_A1 0x01010203
++
++#define AST2400_A0 0x02000303
++
++
++/* AST_SCU_FUN_PIN_CTRL1 0x80 Multi-function Pin Control#1*/
++#define SCU_FUN_PIN_UART4_RXD (0x1 << 31)
++#define SCU_FUN_PIN_UART4_TXD (0x1 << 30)
++#define SCU_FUN_PIN_UART4_NRTS (0x1 << 29)
++#define SCU_FUN_PIN_UART4_NDTR (0x1 << 28)
++#define SCU_FUN_PIN_UART4_NRI (0x1 << 27)
++#define SCU_FUN_PIN_UART4_NDSR (0x1 << 26)
++#define SCU_FUN_PIN_UART4_NDCD (0x1 << 25)
++#define SCU_FUN_PIN_UART4_NCTS (0x1 << 24)
++#define SCU_FUN_PIN_UART3_RXD (0x1 << 23)
++#define SCU_FUN_PIN_UART3_TXD (0x1 << 22)
++#define SCU_FUN_PIN_UART3_NRTS (0x1 << 21)
++#define SCU_FUN_PIN_UART3_NDTR (0x1 << 20)
++#define SCU_FUN_PIN_UART3_NRI (0x1 << 19)
++#define SCU_FUN_PIN_UART3_NDSR (0x1 << 18)
++#define SCU_FUN_PIN_UART3_NDCD (0x1 << 17)
++#define SCU_FUN_PIN_UART3_NCTS (0x1 << 16)
++#define SCU_FUN_PIN_SPICS1 (0x1 << 15)
++#define SCU_FUN_PIN_LPCPME (0x1 << 14)
++#define SCU_FUN_PIN_LPCPD (0x1 << 13)
++#define SCU_FUN_PIN_LPCRST (0x1 << 12)
++#define SCU_FUN_PIN_I2C_SALT4 (0x1 << 11)
++#define SCU_FUN_PIN_I2C_SALT3 (0x1 << 10)
++#define SCU_FUN_PIN_I2C_SALT2 (0x1 << 9)
++#define SCU_FUN_PIN_I2C_SALT1 (0x1 << 8)
++#define SCU_FUN_PIN_TIMER8 (0x1 << 7)
++#define SCU_FUN_PIN_TIMER7 (0x1 << 6)
++#define SCU_FUN_PIN_TIMER6 (0x1 << 5)
++#define SCU_FUN_PIN_TIMER5 (0x1 << 4)
++#define SCU_FUN_PIN_TIMER4 (0x1 << 3)
++#define SCU_FUN_PIN_TIMER3 (0x1 << 2)
++#define SCU_FUN_PIN_MAC1_PHY_LINK (0x1 << 1)
++#define SCU_FUN_PIN_MAC0_PHY_LINK (0x1)
++
++/* AST_SCU_FUN_PIN_CTRL2 0x84 Multi-function Pin Control#2*/
++#define SCU_FUN_PIN_VPIB9 (0x1 << 31)
++#define SCU_FUN_PIN_VPIB8 (0x1 << 30)
++#define SCU_FUN_PIN_VPIB7 (0x1 << 29)
++#define SCU_FUN_PIN_VPIB6 (0x1 << 28)
++#define SCU_FUN_PIN_VPIB5 (0x1 << 27)
++#define SCU_FUN_PIN_VPIB4 (0x1 << 26)
++#define SCU_FUN_PIN_VPIB3 (0x1 << 25)
++#define SCU_FUN_PIN_VPIB2 (0x1 << 24)
++#define SCU_FUN_PIN_VPIB1 (0x1 << 23)
++#define SCU_FUN_PIN_VPIB0 (0x1 << 22)
++#define SCU_FUN_PIN_VPICLK (0x1 << 21)
++#define SCU_FUN_PIN_VPIVS (0x1 << 20)
++#define SCU_FUN_PIN_VPIHS (0x1 << 19)
++#define SCU_FUN_PIN_VPIODD (0x1 << 18)
++#define SCU_FUN_PIN_VPIDE (0x1 << 17)
++
++#define SCU_FUN_PIN_UART2_RXD (0x1 << 31)
++#define SCU_FUN_PIN_UART2_TXD (0x1 << 30)
++#define SCU_FUN_PIN_UART2_NRTS (0x1 << 29)
++#define SCU_FUN_PIN_UART2_NDTR (0x1 << 28)
++#define SCU_FUN_PIN_UART2_NRI (0x1 << 27)
++#define SCU_FUN_PIN_UART2_NDSR (0x1 << 26)
++#define SCU_FUN_PIN_UART2_NDCD (0x1 << 25)
++#define SCU_FUN_PIN_UART2_NCTS (0x1 << 24)
++#define SCU_FUN_PIN_UART1_RXD (0x1 << 23)
++#define SCU_FUN_PIN_UART1_TXD (0x1 << 22)
++#define SCU_FUN_PIN_UART1_NRTS (0x1 << 21)
++#define SCU_FUN_PIN_UART1_NDTR (0x1 << 20)
++#define SCU_FUN_PIN_UART1_NRI (0x1 << 19)
++#define SCU_FUN_PIN_UART1_NDSR (0x1 << 18)
++#define SCU_FUN_PIN_UART1_NDCD (0x1 << 17)
++#define SCU_FUN_PIN_UART1_NCTS (0x1 << 16)
++
++
++#define SCU_FUN_PIN_NAND_FLWP (0x1 << 7)
++#define SCU_FUN_PIN_NAND_FLBUSY (0x1 << 6)
++
++/* AST_SCU_FUN_PIN_CTRL3 0x88 Multi-function Pin Control#3*/
++#define SCU_FUN_PIN_MAC0_MDIO (0x1 << 31)
++#define SCU_FUN_PIN_MAC0_MDC (0x1 << 30)
++#define SCU_FUN_PIN_ROMA25 (0x1 << 29)
++#define SCU_FUN_PIN_ROMA24 (0x1 << 28)
++#define SCU_FUN_PIN_ROMCS4 (0x1 << 27)
++#define SCU_FUN_PIN_ROMCS3 (0x1 << 26)
++#define SCU_FUN_PIN_ROMCS2 (0x1 << 25)
++#define SCU_FUN_PIN_ROMCS1 (0x1 << 24)
++#define SCU_FUN_PIN_ROMCS(x) (0x1 << (23+x))
++
++//Video pin
++#define SCU_FUN_PIN_VPIR9 (0x1 << 19)
++#define SCU_FUN_PIN_VPIR8 (0x1 << 18)
++#define SCU_FUN_PIN_VPIR7 (0x1 << 17)
++#define SCU_FUN_PIN_VPIR6 (0x1 << 16)
++#define SCU_FUN_PIN_VPIR5 (0x1 << 15)
++#define SCU_FUN_PIN_VPIR4 (0x1 << 14)
++#define SCU_FUN_PIN_VPIR3 (0x1 << 13)
++#define SCU_FUN_PIN_VPIR2 (0x1 << 12)
++#define SCU_FUN_PIN_VPIR1 (0x1 << 11)
++#define SCU_FUN_PIN_VPIR0 (0x1 << 10)
++#define SCU_FUN_PIN_VPIG9 (0x1 << 9)
++#define SCU_FUN_PIN_VPIG8 (0x1 << 8)
++#define SCU_FUN_PIN_VPIG7 (0x1 << 7)
++#define SCU_FUN_PIN_VPIG6 (0x1 << 6)
++#define SCU_FUN_PIN_VPIG5 (0x1 << 5)
++#define SCU_FUN_PIN_VPIG4 (0x1 << 4)
++#define SCU_FUN_PIN_VPIG3 (0x1 << 3)
++#define SCU_FUN_PIN_VPIG2 (0x1 << 2)
++#define SCU_FUN_PIN_VPIG1 (0x1 << 1)
++#define SCU_FUN_PIN_VPIG0 (0x1 << 0)
++
++//pwm pin
++#define SCU_FUN_PIN_PWM_TACHO (0)
++
++/* AST_SCU_FUN_PIN_CTRL4 0x8C Multi-function Pin Control#4*/
++#define SCU_FUN_PIN_ROMA23 (0x1 << 7)
++#define SCU_FUN_PIN_ROMA22 (0x1 << 6)
++
++#define SCU_FUN_PIN_ROMWE (0x1 << 5)
++#define SCU_FUN_PIN_ROMOE (0x1 << 4)
++#define SCU_FUN_PIN_ROMD7 (0x1 << 3)
++#define SCU_FUN_PIN_ROMD6 (0x1 << 2)
++#define SCU_FUN_PIN_ROMD5 (0x1 << 1)
++#define SCU_FUN_PIN_ROMD4 (0x1)
++
++/* AST_SCU_FUN_PIN_CTRL5 0x90 Multi-function Pin Control#5*/
++#define SCU_FUN_PIN_SPICS1 (0x1 << 31)
++#define SCU_FUN_PIN_LPC_PLUS (0x1 << 30)
++#define SCU_FUC_PIN_USB20_HOST (0x1 << 29)
++#define SCU_FUC_PIN_USB11_PORT4 (0x1 << 28)
++#define SCU_FUC_PIN_I2C14 (0x1 << 27)
++#define SCU_FUC_PIN_I2C13 (0x1 << 26)
++#define SCU_FUC_PIN_I2C12 (0x1 << 25)
++#define SCU_FUC_PIN_I2C11 (0x1 << 24)
++#define SCU_FUC_PIN_I2C10 (0x1 << 23)
++#define SCU_FUC_PIN_I2C9 (0x1 << 22)
++#define SCU_FUC_PIN_I2C8 (0x1 << 21)
++#define SCU_FUC_PIN_I2C7 (0x1 << 20)
++#define SCU_FUC_PIN_I2C6 (0x1 << 19)
++#define SCU_FUC_PIN_I2C5 (0x1 << 18)
++#define SCU_FUC_PIN_I2C4 (0x1 << 17)
++#define SCU_FUC_PIN_I2C3 (0x1 << 16)
++#define SCU_FUC_PIN_MII2_RX_DWN_DIS (0x1 << 15)
++#define SCU_FUC_PIN_MII2_TX_DWN_DIS (0x1 << 14)
++#define SCU_FUC_PIN_MII1_RX_DWN_DIS (0x1 << 13)
++#define SCU_FUC_PIN_MII1_TX_DWN_DIS (0x1 << 12)
++
++#define SCU_FUC_PIN_MII2_TX_DRIV(x) (x << 10)
++#define SCU_FUC_PIN_MII2_TX_DRIV_MASK (0x3 << 10)
++#define SCU_FUC_PIN_MII1_TX_DRIV(x) (x << 8)
++#define SCU_FUC_PIN_MII1_TX_DRIV_MASK (0x3 << 8)
++
++#define MII_NORMAL_DRIV 0x0
++#define MII_HIGH_DRIV 0x2
++
++#define SCU_FUC_PIN_UART6 (0x1 << 7)
++#define SCU_FUC_PIN_ROM_16BIT (0x1 << 6)
++#define SCU_FUC_PIN_DIGI_V_OUT(x) (x << 4)
++#define SCU_FUC_PIN_DIGI_V_OUT_MASK (0x3 << 4)
++
++#define VIDEO_DISABLE 0x0
++#define VIDEO_12BITS 0x1
++#define VIDEO_24BITS 0x2
++//#define VIDEO_DISABLE 0x3
++
++#define SCU_FUC_PIN_USB11_PORT2 (0x1 << 3)
++#define SCU_FUC_PIN_MAC1_MDIO (0x1 << 2)
++#define SCU_FUC_PIN_SD2 (0x1 << 1)
++#define SCU_FUC_PIN_SD1 (0x1 << 0)
++
++
++/* AST_SCU_FUN_PIN_CTRL6 0x94 Multi-function Pin Control#6*/
++#define SCU_VIDEO_OUT_MASK (~0x3)
++
++/* AST_SCU_WDT_RESET 0x9C Watchdog Reset Selection */
++/* AST_SCU_FUN_PIN_CTRL7 0xA0 Multi-function Pin Control#7*/
++/* AST_SCU_FUN_PIN_CTRL8 0xA4 Multi-function Pin Control#8*/
++#define SCU_FUN_PIN_ROMA17 (0x1 << 31)
++#define SCU_FUN_PIN_ROMA16 (0x1 << 30)
++#define SCU_FUN_PIN_ROMA15 (0x1 << 29)
++#define SCU_FUN_PIN_ROMA14 (0x1 << 28)
++#define SCU_FUN_PIN_ROMA13 (0x1 << 27)
++#define SCU_FUN_PIN_ROMA12 (0x1 << 26)
++#define SCU_FUN_PIN_ROMA11 (0x1 << 25)
++#define SCU_FUN_PIN_ROMA10 (0x1 << 24)
++#define SCU_FUN_PIN_ROMA9 (0x1 << 23)
++#define SCU_FUN_PIN_ROMA8 (0x1 << 22)
++#define SCU_FUN_PIN_ROMA7 (0x1 << 21)
++#define SCU_FUN_PIN_ROMA6 (0x1 << 20)
++#define SCU_FUN_PIN_ROMA5 (0x1 << 19)
++#define SCU_FUN_PIN_ROMA4 (0x1 << 18)
++#define SCU_FUN_PIN_ROMA3 (0x1 << 17)
++#define SCU_FUN_PIN_ROMA2 (0x1 << 16)
++
++/* AST_SCU_FUN_PIN_CTRL9 0xA8 Multi-function Pin Control#9*/
++#define SCU_FUN_PIN_ROMA21 (0x1 << 3)
++#define SCU_FUN_PIN_ROMA20 (0x1 << 2)
++#define SCU_FUN_PIN_ROMA19 (0x1 << 1)
++#define SCU_FUN_PIN_ROMA18 (0x1)
++
++/* AST_SCU_PWR_SAVING_EN 0xC0 Power Saving Wakeup Enable*/
++/* AST_SCU_PWR_SAVING_CTRL 0xC4 Power Saving Wakeup Control*/
++/* AST_SCU_HW_STRAP2 0xD0 Haardware strapping register set 2*/
++/* AST_SCU_COUNTER4 0xE0 SCU Free Run Counter Read Back #4*/
++/* AST_SCU_COUNTER4_EXT 0xE4 SCU Free Run Counter Extended Read Back #4*/
++
++//CPU 2
++/* AST_SCU_CPU2_CTRL 0x100 CPU2 Control Register*/
++/* AST_SCU_CPU2_BASE0_ADDR 0x104 CPU2 Base Address for Segment 0x00:0000~0x1F:FFFF*/
++/* AST_SCU_CPU2_BASE1_ADDR 0x108 CPU2 Base Address for Segment 0x20:0000~0x3F:FFFF*/
++/* AST_SCU_CPU2_BASE2_ADDR 0x10C CPU2 Base Address for Segment 0x40:0000~0x5F:FFFF*/
++/* AST_SCU_CPU2_BASE3_ADDR 0x110 CPU2 Base Address for Segment 0x60:0000~0x7F:FFFF*/
++/* AST_SCU_CPU2_BASE4_ADDR 0x114 CPU2 Base Address for Segment 0x80:0000~0xFF:FFFF*/
++/* AST_SCU_CPU2_CACHE_CTRL 0x118 CPU2 Cache Function Control */
++
++//
++/* AST_SCU_UART24_REF 0x160 Generate UART 24Mhz Ref from H-PLL when CLKIN is 25Mhz */
++/* AST_SCU_PCIE_CONFIG_SET 0x180 PCI-E Configuration Setting Control Register */
++/* AST_SCU_BMC_MMIO_DEC 0x184 BMC MMIO Decode Setting Register */
++/* AST_SCU_DEC_AREA1 0x188 1st relocated controller decode area location */
++/* AST_SCU_DEC_AREA2 0x18C 2nd relocated controller decode area location */
++/* AST_SCU_MBOX_DEC_AREA 0x190 Mailbox decode area location*/
++/* AST_SCU_SRAM_DEC_AREA0 0x194 Shared SRAM area decode location*/
++/* AST_SCU_SRAM_DEC_AREA1 0x198 Shared SRAM area decode location*/
++/* AST_SCU_BMC_CLASS 0x19C BMC device class code and revision ID */
++/* AST_SCU_BMC_DEV_ID 0x1A4 BMC device ID */
++
++#endif /* __AST_SCU_G5_REGS_H */
++
+diff --git a/arch/arm/plat-aspeed/include/plat/regs-scu.h b/arch/arm/plat-aspeed/include/plat/regs-scu.h
+new file mode 100644
+index 0000000..0abdcbd
+--- /dev/null
++++ b/arch/arm/plat-aspeed/include/plat/regs-scu.h
+@@ -0,0 +1,740 @@
++/* arch/arm/mach-aspeed/include/mach/regs-ast2300-scu.h
++ *
++ * Copyright (C) 2012-2020 ASPEED Technology Inc.
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * History :
++ * 1. 2012/12/29 Ryan Chen Create
++ *
++********************************************************************************/
++#ifndef __AST_SCU_H
++#define __AST_SCU_H 1
++
++/*
++ * Register for SCU
++ * */
++#define AST_SCU_PROTECT 0x00 /* protection key register */
++#define AST_SCU_RESET 0x04 /* system reset control register */
++#define AST_SCU_CLK_SEL 0x08 /* clock selection register */
++#define AST_SCU_CLK_STOP 0x0C /* clock stop control register */
++#define AST_SCU_COUNT_CTRL 0x10 /* frequency counter control register */
++#define AST_SCU_COUNT_VAL 0x14 /* frequency counter measure register */
++#define AST_SCU_INTR_CTRL 0x18 /* Interrupt control and status register */
++#define AST_SCU_D2_PLL 0x1C /* D2-PLL Parameter register */
++#define AST_SCU_M_PLL 0x20 /* M-PLL Parameter register */
++#define AST_SCU_H_PLL 0x24 /* H-PLL Parameter register */
++#define AST_SCU_FREQ_LIMIT 0x28 /* frequency counter comparsion register */
++#define AST_SCU_MISC1_CTRL 0x2C /* Misc. Control register */
++#define AST_SCU_PCI_CONF1 0x30 /* PCI configuration setting register#1 */
++#define AST_SCU_PCI_CONF2 0x34 /* PCI configuration setting register#2 */
++#define AST_SCU_PCI_CONF3 0x38 /* PCI configuration setting register#3 */
++#define AST_SCU_SYS_CTRL 0x3C /* System reset contrl/status register*/
++#define AST_SCU_SOC_SCRATCH0 0x40 /* SOC scratch 0~31 register */
++#define AST_SCU_SOC_SCRATCH1 0x44 /* SOC scratch 32~63 register */
++#define AST_SCU_VGA0 0x40 /* VGA fuction handshake register */
++#define AST_SCU_VGA1 0x44 /* VGA fuction handshake register */
++#define AST_SCU_MAC_CLK 0x48 /* MAC interface clock delay setting register */
++#define AST_SCU_MISC2_CTRL 0x4C /* Misc. 2 Control register */
++#define AST_SCU_VGA_SCRATCH0 0x50 /* VGA Scratch register */
++#define AST_SCU_VGA_SCRATCH1 0x54 /* VGA Scratch register */
++#define AST_SCU_VGA_SCRATCH2 0x58 /* VGA Scratch register */
++#define AST_SCU_VGA_SCRATCH3 0x5c /* VGA Scratch register */
++#define AST_SCU_VGA_SCRATCH4 0x60 /* VGA Scratch register */
++#define AST_SCU_VGA_SCRATCH5 0x64 /* VGA Scratch register */
++#define AST_SCU_VGA_SCRATCH6 0x68 /* VGA Scratch register */
++#define AST_SCU_VGA_SCRATCH7 0x6c /* VGA Scratch register */
++#define AST_SCU_HW_STRAP1 0x70 /* hardware strapping register */
++#define AST_SCU_RAMDOM_GEN 0x74 /* random number generator register */
++#if defined(CONFIG_ARCH_1100) || defined(CONFIG_ARCH_2050) || defined(CONFIG_ARCH_2100) || defined(CONFIG_ARCH_2200)
++#define AST_SCU_MULTI_FUNC_2 0x78
++#else
++#define AST_SCU_RAMDOM_DATA 0x78 /* random number generator data output*/
++#endif
++#define AST_SCU_REVISION_ID 0x7C /* Silicon revision ID register */
++#define AST_SCU_FUN_PIN_CTRL1 0x80 /* Multi-function Pin Control#1*/
++#define AST_SCU_FUN_PIN_CTRL2 0x84 /* Multi-function Pin Control#2*/
++#define AST_SCU_FUN_PIN_CTRL3 0x88 /* Multi-function Pin Control#3*/
++#define AST_SCU_FUN_PIN_CTRL4 0x8C /* Multi-function Pin Control#4*/
++#define AST_SCU_FUN_PIN_CTRL5 0x90 /* Multi-function Pin Control#5*/
++#define AST_SCU_FUN_PIN_CTRL6 0x94 /* Multi-function Pin Control#6*/
++#define AST_SCU_WDT_RESET 0x9C /* Watchdog Reset Selection */
++#define AST_SCU_FUN_PIN_CTRL7 0xA0 /* Multi-function Pin Control#7*/
++#define AST_SCU_FUN_PIN_CTRL8 0xA4 /* Multi-function Pin Control#8*/
++#define AST_SCU_FUN_PIN_CTRL9 0xA8 /* Multi-function Pin Control#9*/
++#define AST_SCU_PWR_SAVING_EN 0xC0 /* Power Saving Wakeup Enable*/
++#define AST_SCU_PWR_SAVING_CTRL 0xC4 /* Power Saving Wakeup Control*/
++#define AST_SCU_HW_STRAP2 0xD0 /* Haardware strapping register set 2*/
++#define AST_SCU_COUNTER4 0xE0 /* SCU Free Run Counter Read Back #4*/
++#define AST_SCU_COUNTER4_EXT 0xE4 /* SCU Free Run Counter Extended Read Back #4*/
++
++//CPU 2
++#define AST_SCU_CPU2_CTRL 0x100 /* CPU2 Control Register*/
++#define AST_SCU_CPU2_BASE0_ADDR 0x104 /* CPU2 Base Address for Segment 0x00:0000~0x1F:FFFF*/
++#define AST_SCU_CPU2_BASE1_ADDR 0x108 /* CPU2 Base Address for Segment 0x20:0000~0x3F:FFFF*/
++#define AST_SCU_CPU2_BASE2_ADDR 0x10C /* CPU2 Base Address for Segment 0x40:0000~0x5F:FFFF*/
++#define AST_SCU_CPU2_BASE3_ADDR 0x110 /* CPU2 Base Address for Segment 0x60:0000~0x7F:FFFF*/
++#define AST_SCU_CPU2_BASE4_ADDR 0x114 /* CPU2 Base Address for Segment 0x80:0000~0xFF:FFFF*/
++#define AST_SCU_CPU2_CACHE_CTRL 0x118 /* CPU2 Cache Function Control */
++
++//
++#define AST_SCU_UART24_REF 0x160 /* Generate UART 24Mhz Ref from H-PLL when CLKIN is 25Mhz */
++#define AST_SCU_PCIE_CONFIG_SET 0x180 /* PCI-E Configuration Setting Control Register */
++#define AST_SCU_BMC_MMIO_DEC 0x184 /* BMC MMIO Decode Setting Register */
++#define AST_SCU_DEC_AREA1 0x188 /* 1st relocated controller decode area location */
++#define AST_SCU_DEC_AREA2 0x18C /* 2nd relocated controller decode area location */
++#define AST_SCU_MBOX_DEC_AREA 0x190 /* Mailbox decode area location*/
++#define AST_SCU_SRAM_DEC_AREA0 0x194 /* Shared SRAM area decode location*/
++#define AST_SCU_SRAM_DEC_AREA1 0x198 /* Shared SRAM area decode location*/
++#define AST_SCU_BMC_CLASS 0x19C /* BMC device class code and revision ID */
++#define AST_SCU_BMC_DEV_ID 0x1A4 /* BMC device ID */
++
++
++/* AST_SCU_PROTECT: 0x00 - protection key register */
++#define SCU_PROTECT_UNLOCK 0x1688A8A8
++
++/* AST_SCU_RESET :0x04 - system reset control register */
++#if defined (CONFIG_ARCH_AST1010)
++#define SCU_RESET_ADC (0x1 << 6)
++#define SCU_RESET_JTAG (0x1 << 5)
++#define SCU_RESET_MAC0 (0x1 << 4)
++#define SCU_RESET_PECI (0x1 << 3)
++#define SCU_RESET_PWM (0x1 << 2)
++#define SCU_RESET_LPC (0x1 << 1)
++#define SCU_RESET_I2C (0x1)
++#else
++#define SCU_RESET_X_DMA (0x1 << 25)
++#define SCU_RESET_MCTP (0x1 << 24)
++#define SCU_RESET_ADC (0x1 << 23)
++#define SCU_RESET_JTAG (0x1 << 22)
++#define SCU_PWAKE_PIN_EN (0x1 << 20)
++#define SCU_PWAKE_PIN_OUT (0x1 << 19)
++#define SCU_RESET_MIC (0x1 << 18)
++#define SCU_RESET_RESV (0x1 << 17) //must keep 1
++#define SCU_RESET_SD (0x1 << 16)
++#define SCU_RESET_USB11 (0x1 << 15)
++#define SCU_RESET_USB20 (0x1 << 14)
++#define SCU_RESET_CRT (0x1 << 13)
++#define SCU_RESET_MAC1 (0x1 << 12)
++#define SCU_RESET_MAC0 (0x1 << 11)
++#define SCU_RESET_PECI (0x1 << 10)
++#define SCU_RESET_PWM (0x1 << 9)
++#define SCU_PCI_VGA_DIS (0x1 << 8)
++#define SCU_RESET_2D (0x1 << 7)
++#define SCU_RESET_VIDEO (0x1 << 6)
++#define SCU_RESET_LPC (0x1 << 5)
++#define SCU_RESET_HAC (0x1 << 4)
++#define SCU_RESET_USB11_HID (0x1 << 3)
++#define SCU_RESET_I2C (0x1 << 2)
++#define SCU_RESET_AHB (0x1 << 1)
++#define SCU_RESET_SRAM_CTRL (0x1 << 0)
++#endif
++
++/* AST_SCU_CLK_SEL : 0x08 - clock selection register */
++#if defined(CONFIG_ARCH_AST1010)
++#define SCU_CLK_MAC_DIV(x) (x << 12)
++#define SCU_CLK_MAC_MASK (0x3 << 12)
++#define SCU_LHCLK_SOURCE_EN (0x1 << 11) //0: ext , 1:internel
++#define SCU_LHCLK_LPC_DIV(x) (x << 8)
++#define SCU_LHCLK_LPC_MASK (0x7 << 8)
++#define SCU_PCLK_APB_DIV(x) (x << 5)
++#define SCU_GET_PCLK_DIV(x) ((x >> 5) & 0x7)
++#define SCU_PCLK_APB_DIV_MASK (0x7 << 5) //limitation on PCLK .. PCLK > 0.5*LCLK (33Mhz)
++#define SCU_CLK_CPU_AHB_SLOW_EN (0x1 << 4)
++#define SCU_CLK_CPU_AHB_SLOW(x) (x << 3)
++#define SCU_CLK_CPU_AHB_SLOW_MASK (0x3 << 3)
++#define SCU_GET_AHB_DIV(x) ((x >> 3) & 0x3)
++#define SCU_CLK_CPU_AHB_SLOW_IDLE (0x1 << 1)
++#define SCU_CLK_CPU_AHB_DYN_SLOW_EN (0x1)
++#else
++#define SCU_CLK_VIDEO_SLOW_EN (0x1 << 31)
++#define SCU_CLK_VIDEO_SLOW_SET(x) (x << 28)
++#define SCU_CLK_VIDEO_SLOW_MASK (0x7 << 28)
++#define SCU_CLK_2D_ENG_GCLK_INVERT (0x1 << 27) //valid only at CRT mode SCU2C[7]
++#define SCU_CLK_2D_ENG_THROT_EN (0x1 << 26) //valid only at CRT mode SCU2C[7]
++#define SCU_PCLK_APB_DIV(x) (x << 23)
++#define SCU_GET_PCLK_DIV(x) ((x >> 23) & 0x7)
++#define SCU_PCLK_APB_DIV_MASK (0x7 << 23) //limitation on PCLK .. PCLK > 0.5*LCLK (33Mhz)
++#define SCU_GET_LHCLK_DIV(x) ((x >> 20) & 0x7)
++#define SCU_SET_LHCLK_DIV(x) (x << 20)
++#define SCU_LHCLK_DIV_MASK (0x7 << 20)
++#define SCU_LHCLK_SOURCE_EN (0x1 << 19) //0: ext , 1:internel
++#define SCU_CLK_MAC_DIV(x) (x << 16)
++#define SCU_CLK_MAC_MASK (0x7 << 16)
++#define SCU_CLK_SD_EN (0x1 << 15)
++#define SCU_CLK_SD_DIV(x) (x << 12)
++#define SCU_CLK_SD_GET_DIV(x) ((x >> 12) & 0x7)
++#define SCU_CLK_SD_MASK (0x7 << 12)
++#define SCU_CLK_VIDEO_DELAY(x) (x << 8)
++#define SCU_CLK_VIDEO_DELAY_MASK (0xf << 8)
++#define SCU_CLK_CPU_AHB_SLOW_EN (0x1 << 7)
++#define SCU_CLK_CPU_AHB_SLOW(x) (x << 4)
++#define SCU_CLK_CPU_AHB_SLOW_MASK (0x7 << 4)
++#define SCU_GET_AHB_DIV(x) ((x >> 4) & 0x7)
++#define SCU_ECLK_SOURCE(x) (x << 2)
++#define SCU_ECLK_SOURCE_MASK (0x3 << 2)
++#define SCU_CLK_CPU_AHB_SLOW_IDLE (0x1 << 1)
++#define SCU_CLK_CPU_AHB_DYN_SLOW_EN (0x1 << 0)
++
++#endif
++
++/* AST_SCU_CLK_STOP : 0x0C - clock stop control register */
++#if defined(CONFIG_ARCH_AST1010)
++#define SCU_LHCLK_STOP_EN (0x1 << 7)
++#define SCU_MAC0CLK_STOP_EN (0x1 << 6)
++#define SCU_UART3_CLK_STOP_EN (0x1 << 5)
++#define SCU_UART2_CLK_STOP_EN (0x1 << 4)
++#define SCU_UART1_CLK_STOP_EN (0x1 << 3)
++#define SCU_LCLK_STOP_EN (0x1 << 2)
++#define SCU_REFCLK_STOP_EN (0x1 << 1)
++#define SCU_MCLK_STOP_EN (0x1)
++#else
++#define SCU_LHCLK_STOP_EN (0x1 << 28)
++#define SCU_SDCLK_STOP_EN (0x1 << 27)
++#define SCU_UART4CLK_STOP_EN (0x1 << 26)
++#define SCU_UART3CLK_STOP_EN (0x1 << 25)
++#define SCU_RSACLK_STOP_EN (0x1 << 24)
++//bit 22~23 must keep 1
++#define SCU_MAC1CLK_STOP_EN (0x1 << 21)
++#define SCU_MAC0CLK_STOP_EN (0x1 << 20)
++//bit 18~19 must keep 1
++#define SCU_UART5_CLK_STOP_EN (0x1 << 17)
++#define SCU_UART2_CLK_STOP_EN (0x1 << 16)
++#define SCU_UART1_CLK_STOP_EN (0x1 << 15)
++#define SCU_USB20_CLK_EN (0x1 << 14)
++#define SCU_YCLK_STOP_EN (0x1 << 13)
++#define SCU_D2CLK_STOP_EN (0x1 << 10)
++#define SCU_USB11CLK_STOP_EN (0x1 << 9)
++#define SCU_LCLK_STOP_EN (0x1 << 8)
++#define SCU_UCLK_STOP_EN (0x1 << 7)
++#define SCU_REFCLK_STOP_EN (0x1 << 6)
++#define SCU_DCLK_STOP_EN (0x1 << 5)
++#define SCU_SACLK_STOP_EN (0x1 << 4)
++#define SCU_VCLK_STOP_EN (0x1 << 3)
++#define SCU_MCLK_STOP_EN (0x1 << 2)
++#define SCU_GCLK_STOP_EN (0x1 << 1)
++#define SCU_ECLK_STOP_EN (0x1 << 0)
++#endif
++
++/* AST_SCU_COUNT_CTRL : 0x10 - frequency counter control register */
++#define SCU_FREQ_COMP_RESULT (0x1 << 7)
++#define SCU_FREQ_MEASU_FINISH (0x1 << 6)
++#define SCU_FREQ_SOURCE_FOR_MEASU(x) (x << 2)
++#define SCU_FREQ_SOURCE_FOR_MEASU_MASK (0xf << 2)
++
++#define SCU_SOURCE_6M 0xf
++#define SCU_SOURCE_12M 0xe
++#define SCU_SOURCE_I2SM_CLK 0xd
++#define SCU_SOURCE_H_CLK 0xc
++#define SCU_SOURCE_B_CLK 0xb
++#define SCU_SOURCE_D2_PLL 0xa
++
++#define SCU_SOURCE_VIDEO_CLK 0x7
++#define SCU_SOURCE_LPC_CLK 0x6
++#define SCU_SOURCE_I2S_CLK 0x5
++#define SCU_SOURCE_M_CLK 0x4
++#define SCU_SOURCE_SALI_CLK 0x3
++#define SCU_SOURCE_D_PLL 0x2
++#define SCU_SOURCE_NAND 0x1
++#define SCU_SOURCE_DEL_CELL 0x0
++
++#define SCU_OSC_COUNT_EN (0x1 << 1)
++#define SCU_RING_OSC_EN (0x1 << 0)
++
++
++/* AST_SCU_INTR_CTRL : 0x18 - Interrupt control and status register */
++#define INTR_LPC_H_L_RESET (0x1 << 21)
++#define INTR_LPC_L_H_RESET (0x1 << 20)
++#define INTR_PCIE_H_L_RESET (0x1 << 19)
++#define INTR_PCIE_L_H_RESET (0x1 << 18)
++#define INTR_VGA_SCRATCH_CHANGE (0x1 << 17)
++#define INTR_VGA_CURSOR_CHANGE (0x1 << 16)
++#define INTR_MSI_EN (0x1 << 6)
++#define INTR_LPC_H_L_RESET_EN (0x1 << 5)
++#define INTR_LPC_L_H_RESET_EN (0x1 << 4)
++#define INTR_PCIE_H_L_RESET_EN (0x1 << 3)
++#define INTR_PCIE_L_H_RESET_EN (0x1 << 2)
++#define INTR_VGA_SCRATCH_CHANGE_EN (0x1 << 1)
++#define INTR_VGA_CURSOR_CHANGE_EN (0x1 << 0)
++
++/* AST_SCU_D2_PLL: 0x1C - D2-PLL Parameter register */
++#define SCU_D2_PLL_SET_PD2(x) (x << 19)
++#define SCU_D2_PLL_GET_PD2(x) ((x >> 19)&0x7)
++#define SCU_D2_PLL_PD2_MASK (0x7 << 19)
++#define SCU_D2_PLL_BYPASS_EN (0x1 << 18)
++#define SCU_D2_PLL_OFF (0x1 << 17)
++#define SCU_D2_PLL_SET_PD(x) (x << 15)
++#define SCU_D2_PLL_GET_PD(x) ((x >> 15) &0x3)
++#define SCU_D2_PLL_PD_MASK (0x3 << 15)
++#define SCU_D2_PLL_SET_OD(x) (x << 13)
++#define SCU_D2_PLL_GET_OD(x) ((x >> 13) & 0x3)
++#define SCU_D2_PLL_OD_MASK (0x3 << 13)
++#define SCU_D2_PLL_SET_DENUM(x) (x << 8)
++#define SCU_D2_PLL_GET_DENUM(x) ((x >>8)&0x1f)
++#define SCU_D2_PLL_DENUM_MASK (0x1f << 8)
++#define SCU_D2_PLL_SET_NUM(x) (x)
++#define SCU_D2_PLL_GET_NUM(x) (x & 0xff)
++#define SCU_D2_PLL_NUM_MASK (0xff)
++
++
++/* AST_SCU_M_PLL : 0x20 - M-PLL Parameter register */
++#define SCU_M_PLL_BYPASS_EN (0x1 << 17)
++#define SCU_M_PLL_OFF (0x1 << 16)
++#define SCU_M_PLL_NUM(x) (x << 5)
++#define SCU_M_PLL_GET_NUM(x) ((x >> 5) & 0x3f)
++#define SCU_M_PLL_NUM_MASK (0x3f << 5)
++#define SCU_M_PLL_OUT_DIV (0x1 << 4)
++#define SCU_M_PLL_GET_DIV(x) ((x >> 4) & 0x1)
++#define SCU_M_PLL_DENUM(x) (x)
++#define SCU_M_PLL_GET_DENUM(x) (x & 0xf)
++
++
++/* AST_SCU_H_PLL: 0x24- H-PLL Parameter register */
++#if defined(CONFIG_ARCH_AST1010)
++#define SCU_H_PLL_MASK_EN (0x1 << 10)
++#define SCU_H_PLL_REST_EN (0x1 << 9)
++#define SCU_H_PLL_OUT_DIV(x) (x << 7)
++#define SCU_H_PLL_GET_DIV(x) ((x >> 7) & 0x3)
++#define SCU_H_PLL_GET_DENUM(x) ((x >> 6) & 0x1)
++#define SCU_H_PLL_NUM(x) (x)
++#define SCU_H_PLL_GET_NUM(x) (x & 0x3f)
++#define SCU_H_PLL_NUM_MASK (0x3f)
++
++#else
++#define SCU_H_PLL_PARAMETER (0x1 << 18)
++#define SCU_H_PLL_BYPASS_EN (0x1 << 17)
++#define SCU_H_PLL_OFF (0x1 << 16)
++#define SCU_H_PLL_NUM(x) (x << 5)
++#define SCU_H_PLL_GET_NUM(x) ((x >> 5) & 0x3f)
++#define SCU_H_PLL_NUM_MASK (0x3f << 5)
++#define SCU_H_PLL_OUT_DIV (0x1 << 4)
++#define SCU_H_PLL_GET_DIV(x) ((x >> 4) & 0x1)
++#define SCU_H_PLL_DENUM(x) (x)
++#define SCU_H_PLL_GET_DENUM(x) (x & 0xf)
++#define SCU_H_PLL_DENUM_MASK (0xf)
++#endif
++
++/* AST_SCU_FREQ_LIMIT : 0x28 - frequency counter comparsion register */
++#define SCU_FREQ_U_LIMIT(x) (x << 16)
++#define SCU_FREQ_U_LIMIT_MASK (0x3fff << 16)
++#define SCU_FREQ_L_LIMIT(x) (x)
++#define SCU_FREQ_L_LIMIT_MASK (0x3fff)
++
++
++/* AST_SCU_MISC_CTRL : 0x2C - Misc. Control register */
++#define SCU_MISC_JTAG_MASTER_DIS (0x1 << 26)
++#define SCU_MISC_DRAM_W_P2A_DIS (0x1 << 25)
++#define SCU_MISC_SPI_W_P2A_DIS (0x1 << 24)
++#define SCU_MISC_SOC_W_P2A_DIS (0x1 << 23)
++#define SCU_MISC_FLASH_W_P2A_DIS (0x1 << 22)
++#define SCU_MISC_D_PLL_ASSIGN(x) (x << 20)
++#define SCU_MISC_D_PLL_ASSIGN_MASK (0x3 << 20)
++#define SCU_MISC_VGA_CONFIG_PREFETCH (0x1 << 19)
++#define SCU_MISC_DVO_SOURCE_CRT (0x1 << 18) //0:VGA , 1:CRT
++#define SCU_MISC_DAC_MASK (0x3 << 16)
++#define SCU_MISC_DAC_SOURCE_CRT (0x1 << 16) //00 VGA, 01: CRT, 1x: PASS-Through DVO
++#define SCU_MISC_DAC_SOURCE_MASK (0x3 << 16)
++#define SCU_MISC_JTAG_TO_PCIE_EN (0x1 << 15)
++#define SCU_MISC_JTAG__M_TO_PCIE_EN (0x1 << 14)
++#define SCU_MISC_VUART_TO_CTRL (0x1 << 13)
++#define SCU_MISC_DIV13_EN (0x1 << 12)
++#define SCU_MISC_Y_CLK_INVERT (0x1 << 11)
++#define SCU_MISC_OUT_DELAY (0x1 << 9)
++#define SCU_MISC_PCI_TO_AHB_DIS (0x1 << 8)
++#define SCU_MISC_2D_CRT_EN (0x1 << 7)
++#define SCU_MISC_VGA_CRT_DIS (0x1 << 6)
++#define SCU_MISC_VGA_REG_ACCESS_EN (0x1 << 5)
++#define SCU_MISC_D2_PLL_DIS (0x1 << 4)
++#define SCU_MISC_DAC_DIS (0x1 << 3)
++#define SCU_MISC_D_PLL_DIS (0x1 << 2)
++#define SCU_MISC_OSC_CLK_OUT_PIN (0x1 << 1)
++#define SCU_MISC_LPC_TO_SPI_DIS (0x1 << 0)
++
++/* AST_SCU_PCI_CONF1 : 0x30 - PCI configuration setting register#1 */
++#define SCU_PCI_DEVICE_ID(x) (x << 16)
++#define SCU_PCI_VENDOR_ID(x) (x)
++
++/* AST_SCU_PCI_CONF2 0x34 PCI configuration setting register#2 */
++#define SCU_PCI_SUB_SYS_ID(x) (x << 16)
++#define SCU_PCI_SUB_VENDOR_ID(x) (x)
++
++/* AST_SCU_PCI_CONF3 0x38 PCI configuration setting register#3 */
++#define SCU_PCI_CLASS_CODE(x) (x << 8)
++#define SCU_PCI_REVISION_ID(x) (x)
++
++/* AST_SCU_SYS_CTRL 0x3C System reset contrl/status register*/
++#define SCU_SYS_EXT_SOC_RESET_EN (0x1 << 3)
++#define SCU_SYS_EXT_RESET_FLAG (0x1 << 2)
++#define SCU_SYS_WDT_RESET_FLAG (0x1 << 1)
++#define SCU_SYS_PWR_RESET_FLAG (0x1 << 0)
++
++/* AST_SCU_SOC_SCRATCH0 0x40 SOC scratch 0~31 register */
++
++
++
++
++/* AST_SCU_SOC_SCRATCH1 0x44 SOC scratch 32~63 register */
++
++
++/* AST_SCU_VGA0 0x40 VGA fuction handshake register */
++#define SCU_VGA_SLT_HANDSHAKE(x) (x << 24)
++#define SCU_VGA_SLT_HANDSHAKE_MASK (0xff << 24)
++#define SCU_VGA_CTM_DEF(x) (x << 16)
++#define SCU_VGA_CTM_DEF_MASK (0xff << 16)
++#define SCU_MAC0_PHY_MODE(x) (x << 14)
++#define SCU_MAC0_GET_PHY_MODE(x) ((x >> 14) & 0x3)
++#define SCU_MAC0_PHY_MODE_MASK(x) (0x3 << 14)
++#define SCU_MAC1_PHY_MODE(x) (x << 12)
++#define SCU_MAC1_PHY_MODE_MASK (0x3 << 12)
++#define SCU_MAC1_GET_PHY_MODE(x) ((x >> 12) & 0x3)
++
++#define SCU_VGA_ASPEED_DEF(x) (x << 8)
++#define SCU_VGA_ASPEED_DEF_MASK (0xf << 8)
++
++#define SCU_VGA_DRAM_INIT_MASK(x) ((x >> 7) & 0x1)
++
++/* AST_SCU_VGA1 0x44 VGA fuction handshake register */
++
++
++/* AST_SCU_MAC_CLK 0x48 MAC interface clock delay setting register */
++
++
++
++/* AST_SCU_MISC_CTRL 0x4C Misc. 2 Control register */
++/* AST_SCU_VGA_SCRATCH0 0x50 VGA Scratch register */
++/* AST_SCU_VGA_SCRATCH1 0x54 VGA Scratch register */
++/* AST_SCU_VGA_SCRATCH2 0x58 VGA Scratch register */
++/* AST_SCU_VGA_SCRATCH3 0x5c VGA Scratch register */
++/* AST_SCU_VGA_SCRATCH4 0x60 VGA Scratch register */
++/* AST_SCU_VGA_SCRATCH5 0x64 VGA Scratch register */
++/* AST_SCU_VGA_SCRATCH6 0x68 VGA Scratch register */
++/* AST_SCU_VGA_SCRATCH7 0x6c VGA Scratch register */
++
++/* AST_SCU_HW_STRAP1 0x70 hardware strapping register */
++#define SCU_HW_STRAP_SW_DEFINE(x) (x << 29)
++#define SCU_HW_STRAP_SW_DEFINE_MASK (0x3 << 29)
++#define SCU_HW_STRAP_DRAM_SIZE (x << 29)
++#define SCU_HW_STRAP_DRAM_SIZE_MASK (0x3 << 29)
++
++#define VGA_64M_DRAM 0
++#define VGA_128M_DRAM 1
++#define VGA_256M_DRAM 2
++#define VGA_512M_DRAM 3
++
++#define SCU_HW_STRAP_DRAM_CONFIG (x << 24)
++#define SCU_HW_STRAP_DRAM_CONFIG_MASK (0x7 << 24)
++
++#define SCU_HW_STRAP_GPIOE_PT_EN (0x1 << 22)
++#define SCU_HW_STRAP_GPIOD_PT_EN (0x1 << 21)
++#define SCU_HW_STRAP_LPC_DEC_SUPER_IO (0x1 << 20)
++#define SCU_HW_STRAP_ACPI_DIS (0x1 << 19)
++
++//bit 23, 18 [1,0]
++#define SCU_HW_STRAP_SET_CLK_SOURCE(x) ((((x&0x3) >> 1)<<23)||((x&0x1) << 18))
++#define SCU_HW_STRAP_GET_CLK_SOURCE(x) (((x>>23)&0x1<<1) | ((x>>18)&0x1))
++#define SCU_HW_STRAP_CLK_SOURCE_MASK ((0x1 << 23) | (0x1 << 18))
++
++#define CLK_25M_IN (0x1 << 23)
++#define CLK_24M_IN 0
++#define CLK_48M_IN 1
++#define CLK_25M_IN_24M_USB_CKI 3
++#define CLK_25M_IN_48M_USB_CKI 3
++
++#define SCU_HW_STRAP_2ND_BOOT_WDT (0x1 << 17)
++#define SCU_HW_STRAP_SUPER_IO_CONFIG (0x1 << 16)
++#define SCU_HW_STRAP_VGA_CLASS_CODE (0x1 << 15)
++#define SCU_HW_STRAP_LPC_RESET_PIN (0x1 << 14)
++#define SCU_HW_STRAP_SPI_MODE(x) (x << 12)
++#define SCU_HW_STRAP_SPI_MODE_MASK (0x3 << 12)
++#define SPI_MODE_DIS (0)
++#define SPI_MODE_MASTER_EN (1)
++#define SPI_MODE_M_S_EN (2)
++#define SPI_MODE_PS (3)
++
++#define SCU_HW_STRAP_SET_CPU_AHB_RATIO(x) (x << 10)
++#define SCU_HW_STRAP_GET_CPU_AHB_RATIO(x) ((x >> 10) & 3)
++#define SCU_HW_STRAP_CPU_AHB_RATIO_MASK (0x3 << 10)
++
++
++#define CPU_AHB_RATIO_1_1 0
++#define CPU_AHB_RATIO_2_1 1
++#define CPU_AHB_RATIO_4_1 2
++#define CPU_AHB_RATIO_3_1 3
++
++#define SCU_HW_STRAP_GET_H_PLL_CLK(x) ((x >> 8 )& 0x3)
++#define SCU_HW_STRAP_H_PLL_CLK_MASK (0x3 << 8)
++#define CPU_384MHZ 0
++#define CPU_360MHZ 1
++#define CPU_336MHZ 2
++#define CPU_408MHZ 3
++
++#define SCU_HW_STRAP_MAC1_RGMII (0x1 << 7)
++#define SCU_HW_STRAP_MAC0_RGMII (0x1 << 6)
++#define SCU_HW_STRAP_VGA_BIOS_ROM (0x1 << 5)
++#define SCU_HW_STRAP_SPI_WIDTH (0x1 << 4)
++#define SCU_HW_STRAP_VGA_SIZE_GET(x) ((x >> 2)& 0x3)
++
++#define SCU_HW_STRAP_BOOT_MODE(x) (x)
++#define NOR_BOOT 0
++#define NAND_BOOT 1
++#define SPI_BOOT 2
++#define DIS_BOOT 3
++
++/* AST_SCU_RAMDOM_GEN 0x74 random number generator register */
++/* AST_SCU_RAMDOM_DATA 0x78 random number generator data output*/
++
++/* AST_SCU_MULTI_FUNC_2 0x78 */
++
++#define MULTI_FUNC_VIDEO_RGB18 (0x1 << 2)
++#define MULTI_FUNC_VIDEO_SINGLE_EDGE (0x1 << 0)
++
++
++
++/* AST_SCU_REVISION_ID 0x7C Silicon revision ID register */
++#define AST1100_A0 0x00000200
++#define AST1100_A1 0x00000201
++#define AST1100_A2 0x00000202
++#define AST1100_A3 0x00000202
++
++#define AST2050_A0 0x00000200
++#define AST2050_A1 0x00000201
++#define AST2050_A2 0x00000202
++#define AST2050_A3 0x00000202
++
++#define AST2100_A0 0x00000300
++#define AST2100_A1 0x00000301
++#define AST2100_A2 0x00000302
++#define AST2100_A3 0x00000302
++
++#define AST2200_A0 0x00000102
++#define AST2200_A1 0x00000102
++
++#define AST2300_A0 0x01000003
++#define AST2300_A1 0x01010303
++#define AST1300_A1 0x01010003
++#define AST1050_A1 0x01010203
++
++#define AST2400_A0 0x02000303
++
++
++/* AST_SCU_FUN_PIN_CTRL1 0x80 Multi-function Pin Control#1*/
++#define SCU_FUN_PIN_UART4_RXD (0x1 << 31)
++#define SCU_FUN_PIN_UART4_TXD (0x1 << 30)
++#define SCU_FUN_PIN_UART4_NRTS (0x1 << 29)
++#define SCU_FUN_PIN_UART4_NDTR (0x1 << 28)
++#define SCU_FUN_PIN_UART4_NRI (0x1 << 27)
++#define SCU_FUN_PIN_UART4_NDSR (0x1 << 26)
++#define SCU_FUN_PIN_UART4_NDCD (0x1 << 25)
++#define SCU_FUN_PIN_UART4_NCTS (0x1 << 24)
++#define SCU_FUN_PIN_UART3_RXD (0x1 << 23)
++#define SCU_FUN_PIN_UART3_TXD (0x1 << 22)
++#define SCU_FUN_PIN_UART3_NRTS (0x1 << 21)
++#define SCU_FUN_PIN_UART3_NDTR (0x1 << 20)
++#define SCU_FUN_PIN_UART3_NRI (0x1 << 19)
++#define SCU_FUN_PIN_UART3_NDSR (0x1 << 18)
++#define SCU_FUN_PIN_UART3_NDCD (0x1 << 17)
++#define SCU_FUN_PIN_UART3_NCTS (0x1 << 16)
++
++
++
++
++#define SCU_FUN_PIN_MAC1_PHY_LINK (0x1 << 1)
++#define SCU_FUN_PIN_MAC0_PHY_LINK (0x1)
++
++
++/* AST_SCU_FUN_PIN_CTRL2 0x84 Multi-function Pin Control#2*/
++#define SCU_FUN_PIN_VPIB9 (0x1 << 31)
++#define SCU_FUN_PIN_VPIB8 (0x1 << 30)
++#define SCU_FUN_PIN_VPIB7 (0x1 << 29)
++#define SCU_FUN_PIN_VPIB6 (0x1 << 28)
++#define SCU_FUN_PIN_VPIB5 (0x1 << 27)
++#define SCU_FUN_PIN_VPIB4 (0x1 << 26)
++#define SCU_FUN_PIN_VPIB3 (0x1 << 25)
++#define SCU_FUN_PIN_VPIB2 (0x1 << 24)
++#define SCU_FUN_PIN_VPIB1 (0x1 << 23)
++#define SCU_FUN_PIN_VPIB0 (0x1 << 22)
++#define SCU_FUN_PIN_VPICLK (0x1 << 21)
++#define SCU_FUN_PIN_VPIVS (0x1 << 20)
++#define SCU_FUN_PIN_VPIHS (0x1 << 19)
++#define SCU_FUN_PIN_VPIODD (0x1 << 18)
++#define SCU_FUN_PIN_VPIDE (0x1 << 17)
++
++#define SCU_FUN_PIN_UART2_RXD (0x1 << 31)
++#define SCU_FUN_PIN_UART2_TXD (0x1 << 30)
++#define SCU_FUN_PIN_UART2_NRTS (0x1 << 29)
++#define SCU_FUN_PIN_UART2_NDTR (0x1 << 28)
++#define SCU_FUN_PIN_UART2_NRI (0x1 << 27)
++#define SCU_FUN_PIN_UART2_NDSR (0x1 << 26)
++#define SCU_FUN_PIN_UART2_NDCD (0x1 << 25)
++#define SCU_FUN_PIN_UART2_NCTS (0x1 << 24)
++#define SCU_FUN_PIN_UART1_RXD (0x1 << 23)
++#define SCU_FUN_PIN_UART1_TXD (0x1 << 22)
++#define SCU_FUN_PIN_UART1_NRTS (0x1 << 21)
++#define SCU_FUN_PIN_UART1_NDTR (0x1 << 20)
++#define SCU_FUN_PIN_UART1_NRI (0x1 << 19)
++#define SCU_FUN_PIN_UART1_NDSR (0x1 << 18)
++#define SCU_FUN_PIN_UART1_NDCD (0x1 << 17)
++#define SCU_FUN_PIN_UART1_NCTS (0x1 << 16)
++
++
++#define SCU_FUN_PIN_NAND_FLWP (0x1 << 7)
++#define SCU_FUN_PIN_NAND_FLBUSY (0x1 << 6)
++
++/* AST_SCU_FUN_PIN_CTRL3 0x88 Multi-function Pin Control#3*/
++#if defined(CONFIG_ARCH_AST1010)
++#define SCU_FUN_PIN_MAC0_MDIO (0x1 << 23)
++#define SCU_FUN_PIN_MAC0_MDC (0x1 << 22)
++#else
++#define SCU_FUN_PIN_MAC0_MDIO (0x1 << 31)
++#define SCU_FUN_PIN_MAC0_MDC (0x1 << 30)
++#define SCU_FUN_PIN_ROMA25 (0x1 << 29)
++#define SCU_FUN_PIN_ROMA24 (0x1 << 28)
++#define SCU_FUN_PIN_ROMCS4 (0x1 << 27)
++#define SCU_FUN_PIN_ROMCS3 (0x1 << 26)
++#define SCU_FUN_PIN_ROMCS2 (0x1 << 25)
++#define SCU_FUN_PIN_ROMCS1 (0x1 << 24)
++#define SCU_FUN_PIN_ROMCS(x) (0x1 << (23+x))
++
++//Video pin
++#define SCU_FUN_PIN_VPIR9 (0x1 << 19)
++#define SCU_FUN_PIN_VPIR8 (0x1 << 18)
++#define SCU_FUN_PIN_VPIR7 (0x1 << 17)
++#define SCU_FUN_PIN_VPIR6 (0x1 << 16)
++#define SCU_FUN_PIN_VPIR5 (0x1 << 15)
++#define SCU_FUN_PIN_VPIR4 (0x1 << 14)
++#define SCU_FUN_PIN_VPIR3 (0x1 << 13)
++#define SCU_FUN_PIN_VPIR2 (0x1 << 12)
++#define SCU_FUN_PIN_VPIR1 (0x1 << 11)
++#define SCU_FUN_PIN_VPIR0 (0x1 << 10)
++#define SCU_FUN_PIN_VPIG9 (0x1 << 9)
++#define SCU_FUN_PIN_VPIG8 (0x1 << 8)
++#define SCU_FUN_PIN_VPIG7 (0x1 << 7)
++#define SCU_FUN_PIN_VPIG6 (0x1 << 6)
++#define SCU_FUN_PIN_VPIG5 (0x1 << 5)
++#define SCU_FUN_PIN_VPIG4 (0x1 << 4)
++#define SCU_FUN_PIN_VPIG3 (0x1 << 3)
++#define SCU_FUN_PIN_VPIG2 (0x1 << 2)
++#define SCU_FUN_PIN_VPIG1 (0x1 << 1)
++#define SCU_FUN_PIN_VPIG0 (0x1 << 0)
++#endif
++
++
++//pwm pin
++#define SCU_FUN_PIN_PWM_TACHO (0)
++/* AST_SCU_FUN_PIN_CTRL4 0x8C Multi-function Pin Control#4*/
++#define SCU_FUN_PIN_ROMA23 (0x1 << 7)
++#define SCU_FUN_PIN_ROMA22 (0x1 << 6)
++
++#define SCU_FUN_PIN_ROMWE (0x1 << 5)
++#define SCU_FUN_PIN_ROMOE (0x1 << 4)
++#define SCU_FUN_PIN_ROMD7 (0x1 << 3)
++#define SCU_FUN_PIN_ROMD6 (0x1 << 2)
++#define SCU_FUN_PIN_ROMD5 (0x1 << 1)
++#define SCU_FUN_PIN_ROMD4 (0x1)
++
++/* AST_SCU_FUN_PIN_CTRL5 0x90 Multi-function Pin Control#5*/
++#define SCU_FUN_PIN_SPICS1 (0x1 << 31)
++#define SCU_FUN_PIN_LPC_PLUS (0x1 << 30)
++#define SCU_FUC_PIN_USB20_HOST (0x1 << 29)
++#define SCU_FUC_PIN_USB11_PORT4 (0x1 << 28)
++#define SCU_FUC_PIN_I2C14 (0x1 << 27)
++#define SCU_FUC_PIN_I2C13 (0x1 << 26)
++#define SCU_FUC_PIN_I2C12 (0x1 << 25)
++#define SCU_FUC_PIN_I2C11 (0x1 << 24)
++#define SCU_FUC_PIN_I2C10 (0x1 << 23)
++#define SCU_FUC_PIN_I2C9 (0x1 << 22)
++#define SCU_FUC_PIN_I2C8 (0x1 << 21)
++#define SCU_FUC_PIN_I2C7 (0x1 << 20)
++#define SCU_FUC_PIN_I2C6 (0x1 << 19)
++#define SCU_FUC_PIN_I2C5 (0x1 << 18)
++#define SCU_FUC_PIN_I2C4 (0x1 << 17)
++#define SCU_FUC_PIN_I2C3 (0x1 << 16)
++#define SCU_FUC_PIN_MII2_RX_DWN_DIS (0x1 << 15)
++#define SCU_FUC_PIN_MII2_TX_DWN_DIS (0x1 << 14)
++#define SCU_FUC_PIN_MII1_RX_DWN_DIS (0x1 << 13)
++#define SCU_FUC_PIN_MII1_TX_DWN_DIS (0x1 << 12)
++
++#define SCU_FUC_PIN_MII2_TX_DRIV(x) (x << 10)
++#define SCU_FUC_PIN_MII2_TX_DRIV_MASK (0x3 << 10)
++#define SCU_FUC_PIN_MII1_TX_DRIV(x) (x << 8)
++#define SCU_FUC_PIN_MII1_TX_DRIV_MASK (0x3 << 8)
++
++#define MII_NORMAL_DRIV 0x0
++#define MII_HIGH_DRIV 0x2
++
++#define SCU_FUC_PIN_UART6 (0x1 << 7)
++#define SCU_FUC_PIN_ROM_16BIT (0x1 << 6)
++#define SCU_FUC_PIN_DIGI_V_OUT(x) (x << 4)
++#define SCU_FUC_PIN_DIGI_V_OUT_MASK (0x3 << 4)
++
++#define VIDEO_DISABLE 0x0
++#define VIDEO_12BITS 0x1
++#define VIDEO_24BITS 0x2
++//#define VIDEO_DISABLE 0x3
++
++#define SCU_FUC_PIN_USB11_PORT2 (0x1 << 3)
++#define SCU_FUC_PIN_MAC1_MDIO (0x1 << 2)
++#define SCU_FUC_PIN_SD2 (0x1 << 1)
++#define SCU_FUC_PIN_SD1 (0x1 << 0)
++
++
++/* AST_SCU_FUN_PIN_CTRL6 0x94 Multi-function Pin Control#6*/
++#define SCU_VIDEO_OUT_MASK (~0x3)
++
++/* AST_SCU_WDT_RESET 0x9C Watchdog Reset Selection */
++/* AST_SCU_FUN_PIN_CTRL7 0xA0 Multi-function Pin Control#7*/
++/* AST_SCU_FUN_PIN_CTRL8 0xA4 Multi-function Pin Control#8*/
++#define SCU_FUN_PIN_ROMA17 (0x1 << 31)
++#define SCU_FUN_PIN_ROMA16 (0x1 << 30)
++#define SCU_FUN_PIN_ROMA15 (0x1 << 29)
++#define SCU_FUN_PIN_ROMA14 (0x1 << 28)
++#define SCU_FUN_PIN_ROMA13 (0x1 << 27)
++#define SCU_FUN_PIN_ROMA12 (0x1 << 26)
++#define SCU_FUN_PIN_ROMA11 (0x1 << 25)
++#define SCU_FUN_PIN_ROMA10 (0x1 << 24)
++#define SCU_FUN_PIN_ROMA9 (0x1 << 23)
++#define SCU_FUN_PIN_ROMA8 (0x1 << 22)
++#define SCU_FUN_PIN_ROMA7 (0x1 << 21)
++#define SCU_FUN_PIN_ROMA6 (0x1 << 20)
++#define SCU_FUN_PIN_ROMA5 (0x1 << 19)
++#define SCU_FUN_PIN_ROMA4 (0x1 << 18)
++#define SCU_FUN_PIN_ROMA3 (0x1 << 17)
++#define SCU_FUN_PIN_ROMA2 (0x1 << 16)
++
++/* AST_SCU_FUN_PIN_CTRL9 0xA8 Multi-function Pin Control#9*/
++#define SCU_FUN_PIN_ROMA21 (0x1 << 3)
++#define SCU_FUN_PIN_ROMA20 (0x1 << 2)
++#define SCU_FUN_PIN_ROMA19 (0x1 << 1)
++#define SCU_FUN_PIN_ROMA18 (0x1)
++
++/* AST_SCU_PWR_SAVING_EN 0xC0 Power Saving Wakeup Enable*/
++/* AST_SCU_PWR_SAVING_CTRL 0xC4 Power Saving Wakeup Control*/
++/* AST_SCU_HW_STRAP2 0xD0 Haardware strapping register set 2*/
++/* AST_SCU_COUNTER4 0xE0 SCU Free Run Counter Read Back #4*/
++/* AST_SCU_COUNTER4_EXT 0xE4 SCU Free Run Counter Extended Read Back #4*/
++
++//CPU 2
++/* AST_SCU_CPU2_CTRL 0x100 CPU2 Control Register*/
++/* AST_SCU_CPU2_BASE0_ADDR 0x104 CPU2 Base Address for Segment 0x00:0000~0x1F:FFFF*/
++/* AST_SCU_CPU2_BASE1_ADDR 0x108 CPU2 Base Address for Segment 0x20:0000~0x3F:FFFF*/
++/* AST_SCU_CPU2_BASE2_ADDR 0x10C CPU2 Base Address for Segment 0x40:0000~0x5F:FFFF*/
++/* AST_SCU_CPU2_BASE3_ADDR 0x110 CPU2 Base Address for Segment 0x60:0000~0x7F:FFFF*/
++/* AST_SCU_CPU2_BASE4_ADDR 0x114 CPU2 Base Address for Segment 0x80:0000~0xFF:FFFF*/
++/* AST_SCU_CPU2_CACHE_CTRL 0x118 CPU2 Cache Function Control */
++
++//
++/* AST_SCU_UART24_REF 0x160 Generate UART 24Mhz Ref from H-PLL when CLKIN is 25Mhz */
++/* AST_SCU_PCIE_CONFIG_SET 0x180 PCI-E Configuration Setting Control Register */
++/* AST_SCU_BMC_MMIO_DEC 0x184 BMC MMIO Decode Setting Register */
++/* AST_SCU_DEC_AREA1 0x188 1st relocated controller decode area location */
++/* AST_SCU_DEC_AREA2 0x18C 2nd relocated controller decode area location */
++/* AST_SCU_MBOX_DEC_AREA 0x190 Mailbox decode area location*/
++/* AST_SCU_SRAM_DEC_AREA0 0x194 Shared SRAM area decode location*/
++/* AST_SCU_SRAM_DEC_AREA1 0x198 Shared SRAM area decode location*/
++/* AST_SCU_BMC_CLASS 0x19C BMC device class code and revision ID */
++/* AST_SCU_BMC_DEV_ID 0x1A4 BMC device ID */
++
++#endif
++
+diff --git a/arch/arm/plat-aspeed/include/plat/regs-sdmc.h b/arch/arm/plat-aspeed/include/plat/regs-sdmc.h
+new file mode 100644
+index 0000000..2bcc948
+--- /dev/null
++++ b/arch/arm/plat-aspeed/include/plat/regs-sdmc.h
+@@ -0,0 +1,31 @@
++/* arch/arm/mach-aspeed/include/mach/regs-ast1010-scu.h
++ *
++ * Copyright (C) 2012-2020 ASPEED Technology Inc.
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * History :
++ * 1. 2012/12/29 Ryan Chen Create
++ *
++********************************************************************************/
++#ifndef __AST_SDMC_H
++#define __AST_SDMC_H 1
++
++/*
++ * Register for SDMC
++ * */
++#define AST_SDMC_PROTECT 0x00 /* protection key register */
++#define AST_SDMC_CONFIG 0x04 /* Configuration register */
++
++
++/* AST_SDMC_PROTECT: 0x00 - protection key register */
++#define SDMC_PROTECT_UNLOCK 0xFC600309
++
++/* AST_SDMC_CONFIG :0x04 - Configuration register */
++#define SDMC_CONFIG_MEM_GET(x) (x & 0x3)
++
++
++#endif
++
+diff --git a/arch/arm/plat-aspeed/include/plat/regs-smc.h b/arch/arm/plat-aspeed/include/plat/regs-smc.h
+new file mode 100644
+index 0000000..d4e0252
+--- /dev/null
++++ b/arch/arm/plat-aspeed/include/plat/regs-smc.h
+@@ -0,0 +1,54 @@
++/* arch/arm/plat-aspeed/include/mach/regs-smc.h
++ *
++ * Copyright (c) 2012 ASPEED Technology Inc. <ryan_chen@aspeedtech.com>
++ * http://www.aspeedtech.com/
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * ASPEED Static memory ctrol
++*/
++
++#ifndef __ASM_ARCH_REGS_FMC_H
++#define __ASM_ARCH_REGS_FMC_H __FILE__
++
++#define FMC_CE_TYPE 0x00
++#define FMC_CE_CTRL 0x04
++#define FMC_INTR_CTRL 0x08
++#define FMC_CE0_CTRL 0x10
++#define FMC_CE1_CTRL 0x14
++#define FMC_CE2_CTRL 0x18
++#define FMC_CE3_CTRL 0x1c
++#define FMC_CE4_CTRL 0x20
++
++#define FMC_CE0_ADDR 0x30
++#define FMC_CE1_ADDR 0x34
++#define FMC_CE2_ADDR 0x38
++#define FMC_CE3_ADDR 0x3c
++#define FMC_CE4_ADDR 0x40
++
++#define FMC_MISC_CTRL1 0x50
++#define FMC_MISC_CTRL2 0x54
++#define FMC_NAND_CTRL 0x58
++#define FMC_NAND_ECC 0x5c
++#define FMC_NAND_ECC_CK1 0x60
++#define FMC_NAND_ECC_CK2 0x64
++#define FMC_NAND_ECC_CK3 0x68
++#define FMC_NAND_ECC_GEN1 0x6c
++#define FMC_NAND_ECC_GEN2 0x70
++#define FMC_NAND_ECC_GEN3 0x74
++#define FMC_NAND_ECC_CK_R1 0x78
++#define FMC_NAND_ECC_CK_R2 0x7c
++#define FMC_DMA_CTRL 0x80
++#define FMC_DMA_FLASH_ADDR 0x84
++#define FMC_DMA_DRAM_ADDR 0x88
++#define FMC_DMA_LEN 0x8C
++#define FMC_CHECK_SUM 0x90
++#define FMC_SPI_TIMING 0x94
++
++
++
++
++
++#endif /* __ASM_ARCH_REGS_FMC_H */
+diff --git a/arch/arm/plat-aspeed/include/plat/regs-spi.h b/arch/arm/plat-aspeed/include/plat/regs-spi.h
+new file mode 100644
+index 0000000..9b20cf8
+--- /dev/null
++++ b/arch/arm/plat-aspeed/include/plat/regs-spi.h
+@@ -0,0 +1,51 @@
++/********************************************************************************
++* File Name : regs-spi.h
++*
++* Copyright (C) 2012-2020 ASPEED Technology Inc.
++* This program is free software; you can redistribute it and/or modify
++* it under the terms of the GNU General Public License as published by the Free Software Foundation;
++* either version 2 of the License, or (at your option) any later version.
++* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
++* without even the implied warranty of MERCHANTABILITY or
++* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
++* You should have received a copy of the GNU General Public License
++* along with this program; if not, write to the Free Software
++* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++********************************************************************************/
++
++/* Register offsets */
++#define AST_SPI_CONFIG 0x00
++#define AST_SPI_CTRL 0x04
++#define AST_SPI_MISC 0x10
++#define AST_SPI_TIMING 0x14
++
++/* AST_SPI_CONFIG 0x00 : SPI Flash Configuration Register */
++#define SPI_CONF_CLKX2 (0x1 << 1)
++#define SPI_CONF_WRITE_EN (0x1)
++
++/* FMC_CE0_CTRL for SPI 0x10, 0x14, 0x18, 0x1c, 0x20 */
++#define SPI_IO_MODE(x) (x << 28)
++#define SPI_SINGLE_BIT 0
++#define SPI_DUAL_BIT_D 2
++#define SPI_DUAL_BIT_DA 3
++#define SPI_CE_WIDTH(x) (x << 24)
++#define SPI_CMD_DATA(x) (x << 16)
++#define SPI_DUMMY_CMD (1 << 15)
++#define SPI_DUMMY_HIGH (1 << 14)
++//#define SPI_CLK_DIV (1 << 13) ?? TODO ask....
++//#define SPI_ADDR_CYCLE (1 << 13) ?? TODO ask....
++#define SPI_CMD_MERGE_DIS (1 << 12)
++#define SPI_CLK_DIV(x) (x << 8)
++#define SPI_CLK_DIV_MASK (0xf << 8)
++
++#define SPI_DUMMY_LOW (x << 6)
++#define SPI_LSB_FIRST_CTRL (1 << 5)
++#define SPI_CPOL_1 (1 << 4)
++#define SPI_DUAL_DATA (1 << 3)
++#define SPI_CE_INACTIVE (1 << 2)
++#define SPI_CMD_MODE (x)
++#define SPI_CMD_NOR_R_MODE 0
++#define SPI_CMD_FAST_R_MODE 1
++#define SPI_CMD_NOR_W_MODE 2
++#define SPI_CMD_USER_MODE 3
++
+diff --git a/arch/arm/plat-aspeed/include/plat/regs-uart-dma.h b/arch/arm/plat-aspeed/include/plat/regs-uart-dma.h
+new file mode 100644
+index 0000000..2282bb1
+--- /dev/null
++++ b/arch/arm/plat-aspeed/include/plat/regs-uart-dma.h
+@@ -0,0 +1,79 @@
++/* arch/arm/mach-aspeed/include/mach/regs-uart-dma.h
++ *
++ * Copyright (C) 2012-2020 ASPEED Technology Inc.
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * History :
++ * 1. 2013/05/15 Ryan Chen Create
++ *
++********************************************************************************/
++#ifndef __AST1070_UART_DMA_H
++#define __AST1070_UART_DMA_H 1
++
++#define UART_DMA0_TX_CTRL 0x00
++#define UART_DMA0_TX_DESCPT 0x04
++#define UART_DMA1_TX_CTRL 0x08
++#define UART_DMA1_TX_DESCPT 0x0C
++#define UART_DMA2_TX_CTRL 0x10
++#define UART_DMA2_TX_DESCPT 0x14
++#define UART_DMA3_TX_CTRL 0x18
++#define UART_DMA3_TX_DESCPT 0x1C
++#define UART_DMA0_RX_CTRL 0x20
++#define UART_DMA0_RX_DESCPT 0x24
++#define UART_DMA1_RX_CTRL 0x28
++#define UART_DMA1_RX_DESCPT 0x2C
++#define UART_DMA2_RX_CTRL 0x30
++#define UART_DMA2_RX_DESCPT 0x34
++#define UART_DMA3_RX_CTRL 0x38
++#define UART_DMA3_RX_DESCPT 0x3C
++#define UART_DMA_CTRL 0x40
++#define UART_DMA_IER 0x44
++#define UART_DMA_ISR 0x48
++
++/* */
++#define DMA_TRIGGER (1 << 2)
++#define DMA_ENABLE (1 << 0)
++
++/* UART_DMA_CTRL 0x40 */
++#define SPI_CLK_MASK (0x1f << 16)
++#define SPI_CLK_SET(x) ((x) << 16)
++#define DMA_RX_TIMEOUT(x) ((x) << 4)
++#define DMA_BURST_LEN(x) ((x) << 2)
++#define DMA_BURST_MASK (0x3 << 2)
++#define BURST_1 0
++#define BURST_2 1
++#define BURST_4 2
++#define BURST_8 3
++#define RXDESC_AUTO_POLLING (1 << 1)
++#define TXDESC_AUTO_POLLING (1 << 0)
++
++/* UART_DMA_IER / UART_DMA_ISR 0x44 0x48 */
++
++#define UART_DMA3_RX_INT (1 << 7)
++#define UART_DMA2_RX_INT (1 << 6)
++#define UART_DMA1_RX_INT (1 << 5)
++#define UART_DMA0_RX_INT (1 << 4)
++#define UART_DMA3_TX_INT (1 << 3)
++#define UART_DMA2_TX_INT (1 << 2)
++#define UART_DMA1_TX_INT (1 << 1)
++#define UART_DMA0_TX_INT (1 << 0)
++
++
++/* UART DESC #0 Command Register */
++#define DESC0_INT_EN (1 << 9)
++#define DESC0_END (1 << 8)
++#define DESC0_HW_OWN (1 << 0)
++
++/* UART DESC #1 Base Address of Data */
++#define DESC1_LEN(x) ((x) << 16)
++#define DESC1_NEXT(x) (x)
++
++/* UART DESC #2 Base Address of Data */
++
++/* UART DESC #3 Descriptor Status Register */
++#define DESC3_TIMEOUT_STS (1 << 16)
++#define DESC3_GET_LEN(x) ((x) & 0xffff)
++#endif
+diff --git a/arch/arm/plat-aspeed/include/plat/regs-udc11.h b/arch/arm/plat-aspeed/include/plat/regs-udc11.h
+new file mode 100644
+index 0000000..3b74d63
+--- /dev/null
++++ b/arch/arm/plat-aspeed/include/plat/regs-udc11.h
+@@ -0,0 +1,98 @@
++/* arch/arm/plat-aspeed/include/mach/regs-udc11.h
++ *
++ * Copyright (c) 2012 ASPEED Technology Inc. <ryan_chen@aspeedtech.com>
++ * http://www.aspeedtech.com/
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * ASPEED UDC11 Controller
++*/
++
++#ifndef __ASM_ARCH_REGS_UDC11_H
++#define __ASM_ARCH_REGS_UDC11_H __FILE__
++
++#define AST_UDC11_CTRL 0x00 /* Function Control and Status Register */
++#define AST_UDC11_CONF 0x04 /* Function Configuration Setting Register */
++#define AST_UDC11_REST 0x08 /* Endpoint Toggle Bit Reset Register */
++#define AST_UDC11_STS 0x0C /* USB Status Register */
++#define AST_UDC11_IER 0x10 /* Interrupt Control Register */
++#define AST_UDC11_ISR 0x14 /* Interrupt Status Register */
++#define AST_UDC11_EP0_CTRL 0x18 /* Endpoint 0 Control and Status Register */
++#define AST_UDC11_EP1_CTRL 0x1C /* Endpoint 1 Control and Status Register */
++#define AST_UDC11_EP2_CTRL 0x20 /* Endpoint 2 Control and Status Register */
++#define AST_UDC11_EP0_SETUP0 0x24 /* Endpoint 0 Setup/OUT Data Buffer LOW Register */
++#define AST_UDC11_EP0_SETUP1 0x28 /* Endpoint 0 Setup/OUT Data Buffer HIGH Register */
++#define AST_UDC11_EP0_DATA0 0x2C /* Endpoint 0 IN DATA Buffer LOW Register */
++#define AST_UDC11_EP0_DATA1 0x30 /* Endpoint 0 IN DATA Buffer HIGH Register */
++#define AST_UDC11_EP1_DATA0 0x34 /* Endpoint 1 IN DATA Buffer LOW Register */
++#define AST_UDC11_EP1_DATA1 0x38 /* Endpoint 1 IN DATA Buffer HIGH Register */
++#define AST_UDC11_EP2_DATA0 0x3C /* Endpoint 2 IN DATA Buffer LOW Register */
++#define AST_UDC11_EP2_DATA1 0x40 /* Endpoint 2 IN DATA Buffer HIGH Register */
++
++/* AST_UDC11_CTRL 0x00 Function Control and Status Register */
++#define UDC11_CTRL_TEST_RESULT (1 << 10)
++#define UDC11_CTRL_TEST_STS (1 << 9)
++#define UDC11_CTRL_TEST_MODE(x) ((x) << 6)
++#define UDC11_CTRL_WKP(x) ((x) << 4)
++#define UDC11_CTRL_WKP_EN (1 << 3)
++#define UDC11_CTRL_CLK_STOP (1 << 2)
++#define UDC11_CTRL_LS_EN (1 << 1)
++#define UDC11_CTRL_CONNECT_EN (1)
++
++/* AST_UDC11_CONF 0x04 Function Configuration Setting Register */
++#define UDC11_CONF_ADDR_MASK (0x3f << 1)
++#define UDC11_CONF_SET_ADDR(x) (x << 1)
++#define UDC11_CONF_SET_CONF (1)
++
++/* AST_UDC11_REST 0x08 Endpoint Toggle Bit Reset Register */
++#define UDC11_REST_EP2 (1 << 1)
++#define UDC11_REST_EP1 (1)
++
++
++/* AST_UDC11_STS 0x0C USB Status Register */
++#define UDC11_STS_SUSPEND (1 << 31)
++#define UDC11_STS_BUS_RST (1 << 30)
++#define UDC11_STS_LINE_DP (1 << 29)
++#define UDC11_STS_LINE_DN (1 << 28)
++#define UDC11_STS_FRAM_NUM_MASK (0x7ff << 16)
++#define UDC11_STS_GET_FRAM_NUM(x) ((x >> 16) & 0x7ff)
++#define UDC11_STS_LAST_ADDR (0x7f << 4)
++#define UDC11_STS_LAST_EP (0xf)
++
++/* AST_UDC11_IER 0x10 Interrupt Control Register */
++/* AST_UDC11_ISR 0x14 Interrupt Status Register */
++#define UDC11_EP0_OUT (1 << 9)
++#define UDC11_EP0_NAK (1 << 8)
++#define UDC11_EP2_IN_ACK (1 << 7)
++#define UDC11_EP1_IN_ACK (1 << 6)
++#define UDC11_EP0_IN_ACK (1 << 5)
++#define UDC11_EP0_OUT_ACK (1 << 4)
++#define UDC11_EP0_SETUP (1 << 3)
++#define UDC11_SUSPEND_RESUME (1 << 2)
++#define UDC11_SUSPEND_ENTRY (1 << 1)
++#define UDC11_BUS_REST (1)
++
++/* AST_UDC11_EP0_CTRL 0x18 Endpoint 0 Control and Status Register */
++/* AST_UDC11_EP1_CTRL 0x1C Endpoint 1 Control and Status Register */
++/* AST_UDC11_EP2_CTRL 0x20 Endpoint 2 Control and Status Register */
++#define GET_EP_OUT_RX_LEN(x) ((x & 0xf) >> 8) //only for EP0
++#define GET_EP_IN_TX_LEN(x) ((x & 0xf) >> 4)
++#define SET_EP_IN_TX_LEN(x) ((x & 0xf) << 4)
++#define EP_OUT_BUFF_RX_RDY (1 << 2) //only for EP0
++#define EP_IN_BUFF_TX_RDY (1 << 1)
++#define EP_CTRL_STALL
++
++
++
++
++
++
++
++
++
++
++
++
++#endif /* __ASM_ARCH_REGS_UDC11_H */
+diff --git a/arch/arm/plat-aspeed/include/plat/regs-video.h b/arch/arm/plat-aspeed/include/plat/regs-video.h
+new file mode 100644
+index 0000000..ee99075
+--- /dev/null
++++ b/arch/arm/plat-aspeed/include/plat/regs-video.h
+@@ -0,0 +1,348 @@
++/* arch/arm/mach-aspeed/include/mach/regs-video.h
++ *
++ * Copyright (C) 2012-2020 ASPEED Technology Inc.
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * History :
++ * 1. 2012/08/15 Ryan Chen Create
++ *
++********************************************************************************/
++#ifndef __AST_VIDEO_H
++#define __AST_VIDEO_H 1
++
++/*
++ * Register for VIDEO
++ * */
++#define AST_VIDEO_PROTECT 0x000 /* protection key register */
++#define AST_VIDEO_SEQ_CTRL 0x004 /* Video Sequence Control register */
++#define AST_VIDEO_PASS_CTRL 0x008 /* Video Pass 1 Control register */
++
++#define AST_VIDEO_DIRECT_BASE 0x00C /* Video Direct Frame buffer mode control Register VR008[5]=1 */
++#define AST_VIDEO_DIRECT_CTRL 0x010 /* Video Direct Frame buffer mode control Register VR008[5]=1 */
++
++#define AST_VIDEO_TIMING_H 0x00C /* Video Timing Generation Setting Register */
++#define AST_VIDEO_TIMING_V 0x010 /* Video Timing Generation Setting Register */
++#define AST_VIDEO_SCAL_FACTOR 0x014 /* Video Scaling Factor Register */
++
++#define AST_VIDEO_SCALING0 0x018 /* Video Scaling Filter Parameter Register #0 */
++#define AST_VIDEO_SCALING1 0x01C /* Video Scaling Filter Parameter Register #1 */
++#define AST_VIDEO_SCALING2 0x020 /* Video Scaling Filter Parameter Register #2 */
++#define AST_VIDEO_SCALING3 0x024 /* Video Scaling Filter Parameter Register #3 */
++
++#define AST_VIDEO_BCD_CTRL 0x02C /* Video BCD Control Register */
++#define AST_VIDEO_CAPTURE_WIN 0x030 /* Video Capturing Window Setting Register */
++#define AST_VIDEO_COMPRESS_WIN 0x034 /* Video Compression Window Setting Register */
++
++
++#define AST_VIDEO_COMPRESS_PRO 0x038 /* Video Compression Stream Buffer Processing Offset Register */
++#define AST_VIDEO_COMPRESS_READ 0x03C /* Video Compression Stream Buffer Read Offset Register */
++
++#define AST_VIDEO_SOURCE_BUFF0 0x044 /* Video Based Address of Video Source Buffer #1 Register */
++#define AST_VIDEO_SOURCE_SCAN_LINE 0x048 /* Video Scan Line Offset of Video Source Buffer Register */
++#define AST_VIDEO_SOURCE_BUFF1 0x04C /* Video Based Address of Video Source Buffer #2 Register */
++#define AST_VIDEO_BCD_BUFF 0x050 /* Video Base Address of BCD Flag Buffer Register */
++#define AST_VIDEO_STREAM_BUFF 0x054 /* Video Base Address of Compressed Video Stream Buffer Register */
++#define AST_VIDEO_STREAM_SIZE 0x058 /* Video Stream Buffer Size Register */
++
++
++#define AST_VIDEO_COMPRESS_CTRL 0x060 /* Video Compression Control Register */
++
++
++#define AST_VIDEO_DEF_HEADER 0x080 /* Video User Defined Header Parameter Setting with Compression */
++
++#define AST_VIDEO_H_DETECT_STS 0x090 /* Video Source Left/Right Edge Detection Read Back Register */
++#define AST_VIDEO_V_DETECT_STS 0x094 /* Video Source Top/Bottom Edge Detection Read Back Register */
++
++
++#define AST_VIDEO_MODE_DET_STS 0x098 /* Video Mode Detection Status Read Back Register */
++
++#define AST_VIDEO_MODE_DET1 0x0A4 /* Video Mode Detection Control Register 1*/
++
++
++#define AST_VIDEO_CTRL 0x300 /* Video Control Register */
++#define AST_VIDEO_INT_EN 0x304 /* Video interrupt Enable */
++#define AST_VIDEO_INT_STS 0x308 /* Video interrupt status */
++#define AST_VIDEO_MODE_DETECT 0x30C /* Video Mode Detection Parameter Register */
++
++#define AST_VIDEO_CRC1 0x320 /* Primary CRC Parameter Register */
++#define AST_VIDEO_CRC2 0x324 /* Second CRC Parameter Register */
++#define AST_VIDEO_DATA_TRUNCA 0x328 /* Video Data Truncation Register */
++
++
++#define AST_VIDEO_SCRATCH_340 0x340 /* Video Scratch Remap Read Back */
++#define AST_VIDEO_SCRATCH_344 0x344 /* Video Scratch Remap Read Back */
++#define AST_VIDEO_SCRATCH_348 0x348 /* Video Scratch Remap Read Back */
++#define AST_VIDEO_SCRATCH_34C 0x34C /* Video Scratch Remap Read Back */
++#define AST_VIDEO_SCRATCH_350 0x350 /* Video Scratch Remap Read Back */
++#define AST_VIDEO_SCRATCH_354 0x354 /* Video Scratch Remap Read Back */
++#define AST_VIDEO_SCRATCH_358 0x358 /* Video Scratch Remap Read Back */
++#define AST_VIDEO_SCRATCH_35C 0x35C /* Video Scratch Remap Read Back */
++#define AST_VIDEO_SCRATCH_360 0x360 /* Video Scratch Remap Read Back */
++#define AST_VIDEO_SCRATCH_364 0x364 /* Video Scratch Remap Read Back */
++
++
++#define AST_VIDEO_ENCRYPT_SRAM 0x400 /* Video RC4/AES128 Encryption Key Register #0 ~ #63 */
++
++/////////////////////////////////////////////////////////////////////////////
++
++/* AST_VIDEO_PROTECT: 0x000 - protection key register */
++#define VIDEO_PROTECT_UNLOCK 0x1A038AA8
++
++/* AST_VIDEO_SEQ_CTRL 0x004 Video Sequence Control register */
++#define VIDEO_HALT_ENG_STS (1 << 21)
++#define VIDEO_COMPRESS_BUSY (1 << 18)
++#define VIDEO_CAPTURE_BUSY (1 << 16)
++#define VIDEO_HALT_ENG_TRIGGER (1 << 12)
++#define VIDEO_COMPRESS_FORMAT_MASK (3 << 10)
++#define VIDEO_COMPRESS_FORMAT(x) (x << 10) // 0 YUV444
++#define YUV420 1
++#define VIDEO_COMPRESS_JPEG_CPB (1 << 8)
++//if bit 0 : 1
++#define VIDEO_INPUT_MODE_CHG_WDT (1 << 7)
++#define VIDEO_INSERT_FULL_COMPRESS (1 << 6)
++#define VIDEO_AUTO_COMPRESS (1 << 5)
++#define VIDEO_COMPRESS_TRIGGER (1 << 4)
++#define VIDEO_CAPTURE_MULTI_FRAME (1 << 3)
++#define VIDEO_COMPRESS_FORCE_IDLE (1 << 2)
++#define VIDEO_CAPTURE_TIRGGER (1 << 1)
++#define VIDEO_DETECT_TRIGGER (1 << 0)
++
++
++#define VIDEO_HALT_ENG_RB (1 << 21)
++#define VIDEO_HALT_ENG_RB (1 << 21)
++#define VIDEO_HALT_ENG_RB (1 << 21)
++#define VIDEO_HALT_ENG_RB (1 << 21)
++#define VIDEO_HALT_ENG_RB (1 << 21)
++#define VIDEO_HALT_ENG_RB (1 << 21)
++
++
++/* AST_VIDEO_PASS_CTRL 0x008 Video Pass1 Control register */
++//x * source frame rate / 60
++#define VIDEO_FRAME_RATE_CTRL(x) (x << 16)
++#define VIDEO_HSYNC_POLARITY_CTRL (1 << 15)
++#define VIDEO_INTERLANCE_MODE (1 << 14)
++#define VIDEO_DUAL_EDGE_MODE (1 << 13) //0 : Single edage
++#define VIDEO_18BIT_SINGLE_EDGE (1 << 12) //0: 24bits
++#define VIDEO_DVO_INPUT_DELAY_MASK (7 << 9)
++#define VIDEO_DVO_INPUT_DELAY(x) (x << 9) //0 : no delay , 1: 1ns, 2: 2ns, 3:3ns
++// if biit 5 : 0
++#define VIDEO_HW_CURSOR_DIS (1 << 8)
++// if biit 5 : 1
++#define VIDEO_AUTO_FATCH (1 << 8)
++#define VIDEO_CAPTURE_MODE(x) (x << 6)
++#define YUV_MODE 1
++#define RGB_MODE 2
++#define GRAY_MODE 3
++#define VIDEO_DIRT_FATCH (1 << 5)
++// if biit 5 : 0
++#define VIDEO_INTERNAL_DE (1 << 4)
++#define VIDEO_EXT_ADC_ATTRIBUTE (1 << 3)
++
++// if biit 5 : 1
++#define VIDEO_16BPP_MODE (1 << 4)
++#define VIDEO_16BPP_MODE_555 (1 << 3) //0:565
++
++#define VIDEO_FROM_EXT_SOURCE (1 << 2)
++#define VIDEO_SO_VSYNC_POLARITY (1 << 1)
++#define VIDEO_SO_HSYNC_POLARITY (1 << 0)
++
++/* AST_VIDEO_TIMING_H 0x00C Video Timing Generation Setting Register */
++#define VIDEO_HSYNC_PIXEL_FIRST_SET(x) ((x) << 16)
++#define VIDEO_HSYNC_PIXEL_LAST_SET(x) (x)
++
++
++/* AST_VIDEO_DIRECT_CTRL 0x010 Video Direct Frame buffer mode control Register VR008[5]=1 */
++#define VIDEO_FETCH_TIMING(x) ((x) << 16)
++#define VIDEO_FETCH_LINE_OFFSET(x) (x)
++
++/* AST_VIDEO_TIMING_V 0x010 Video Timing Generation Setting Register */
++#define VIDEO_VSYNC_PIXEL_FIRST_SET(x) ((x) << 16)
++#define VIDEO_VSYNC_PIXEL_LAST_SET(x) (x)
++
++
++/* AST_VIDEO_SCAL_FACTOR 0x014 Video Scaling Factor Register */
++#define VIDEO_V_SCAL_FACTOR(x) (((x) & 0xffff) << 16)
++#define VIDEO_H_SCAL_FACTOR(x) (x & 0xffff)
++
++
++/* AST_VIDEO_SCALING0 0x018 Video Scaling Filter Parameter Register #0 */
++/* AST_VIDEO_SCALING1 0x01C Video Scaling Filter Parameter Register #1 */
++/* AST_VIDEO_SCALING2 0x020 Video Scaling Filter Parameter Register #2 */
++/* AST_VIDEO_SCALING3 0x024 Video Scaling Filter Parameter Register #3 */
++
++
++/* AST_VIDEO_BCD_CTRL 0x02C Video BCD Control Register */
++#define VIDEO_ABCD_TOL(x) (x << 24)
++#define VIDEO_BCD_TOL(x) (x << 16)
++#define VIDEO_ABCD_CHG_EN (1 << 1)
++#define VIDEO_BCD_CHG_EN (1 << 0)
++
++
++
++/* AST_VIDEO_CAPTURE_WIN 0x030 Video Capturing Window Setting Register */
++#define VIDEO_CAPTURE_V(x) (x & 0x7ff)
++#define VIDEO_CAPTURE_H(x) ((x & 0x7ff) << 16)
++
++/* AST_VIDEO_COMPRESS_WIN 0x034 Video Compression Window Setting Register */
++#define VIDEO_COMPRESS_V(x) (x & 0x7ff)
++#define VIDEO_COMPRESS_H(x) ((x & 0x7ff) << 16)
++
++
++
++/* AST_VIDEO_RESET :0x03c - system reset control register */
++
++/* AST_VIDEO_STREAM_SIZE 0x058 Video Stream Buffer Size Register */
++#define VIDEO_STREAM_PKT_N(x) (x << 3)
++#define STREAM_4_PKTS 0
++#define STREAM_8_PKTS 1
++#define STREAM_16_PKTS 2
++#define STREAM_32_PKTS 3
++#define STREAM_64_PKTS 4
++#define STREAM_128_PKTS 5
++
++#define VIDEO_STREAM_PKT_SIZE(x) (x)
++#define STREAM_1KB 0
++#define STREAM_2KB 1
++#define STREAM_4KB 2
++#define STREAM_8KB 3
++#define STREAM_16KB 4
++#define STREAM_32KB 5
++#define STREAM_64KB 6
++#define STREAM_128KB 7
++
++
++
++
++
++
++
++
++/* AST_VIDEO_COMPRESS_CTRL 0x060 Video Compression Control Register */
++#define VIDEO_HQ_DCT_LUM(x) ((x) << 27)
++#define VIDEO_HQ_DCT_CHROM(x) ((x) << 22)
++#define VIDEO_DCT_HUFFMAN_ENCODE(x) ((x) << 20)
++#define VIDEO_DCT_RESET (1 << 17)
++#define VIDEO_HQ_ENABLE (1 << 16)
++#define VIDEO_DCT_LUM(x) ((x) << 11)
++#define VIDEO_DCT_CHROM(x) ((x) << 6)
++#define VIDEO_RC4_ENABLE (1 << 5)
++#define VIDEO_COMPRESS_QUANTIZ_MODE (1 << 2)
++#define VIDEO_4COLOR_VQ_ENCODE (1 << 1)
++#define VIDEO_DCT_ONLY_ENCODE (1 << 0)
++
++
++/* AST_VIDEO_H_DETECT_STS 0x090 Video Source Left/Right Edge Detection Read Back Register */
++#define VIDEO_DET_INTERLANCE_MODE (1 << 31)
++#define VIDEO_GET_HSYNC_RIGHT(x) ((x & 0x0FFF0000) >> 16)
++#define VIDEO_GET_HSYNC_LEFT(x) (x & 0xFFF)
++#define VIDEO_NO_DISPLAY_CLOCK_DET (1 << 15)
++#define VIDEO_NO_ACT_DISPLAY_DET (1 << 14)
++#define VIDEO_NO_HSYNC_DET (1 << 13)
++#define VIDEO_NO_VSYNC_DET (1 << 12)
++
++/* AST_VIDEO_V_DETECT_STS 0x094 Video Source Top/Bottom Edge Detection Read Back Register */
++#define VIDEO_GET_VSYNC_BOTTOM(x) ((x & 0x0FFF0000) >> 16)
++#define VIDEO_GET_VSYNC_TOP(x) (x & 0xFFF)
++
++
++/* AST_VIDEO_MODE_DET_STS 0x098 Video Mode Detection Status Read Back Register */
++#define VIDEO_DET_HSYNC_RDY (1 << 31)
++#define VIDEO_DET_VSYNC_RDY (1 << 30)
++#define VIDEO_DET_HSYNC_POLAR (1 << 29)
++#define VIDEO_DET_VSYNC_POLAR (1 << 28)
++#define VIDEO_GET_VER_SCAN_LINE(x) ((x >> 16) & 0xfff)
++#define VIDEO_OUT_SYNC (1 << 15)
++#define VIDEO_DET_VER_STABLE (1 << 14)
++#define VIDEO_DET_HOR_STABLE (1 << 13)
++#define VIDEO_DET_FROM_ADC (1 << 12)
++#define VIDEO_DET_HOR_PERIOD(x) (x & 0xfff)
++
++
++/* AST_VIDEO_MODE_DET1 0x0A4 Video Mode Detection Control Register 1*/
++#define VIDEO_DET_HSYNC_DELAY_MASK (0xff << 16)
++#define VIDEO_DET_LONG_H_STABLE_EN (1 << 29)
++
++
++/* AST_VIDEO_CTRL 0x300 Video Control Register */
++#define VIDEO_CTRL_CRYPTO(x) (x << 17)
++#define VIDEO_CTRL_CRYPTO_MASK (1 << 17)
++#define CRYPTO_RC4_MODE 0
++#define CRYPTO_AES_MODE 1
++#define VIDEO_CTRL_CRYPTO_FAST (1 << 16)
++//15 reserved
++#define VIDEO_CTRL_RC4_VC (1 << 14)
++#define VIDEO_CTRL_CAPTURE_MASK (3 << 12)
++#define VIDEO_CTRL_CAPTURE_MODE(x) (x << 12)
++#define VIDEO_CTRL_COMPRESS_MASK (3 << 10)
++#define VIDEO_CTRL_COMPRESS_MODE(x) (x << 10)
++#define MODE_32BPP_YUV444 0
++#define MODE_24BPP_YUV444 1
++#define MODE_16BPP_YUV422 3
++
++#define VIDEO_CTRL_RC4_TEST_MODE (1 << 9)
++#define VIDEO_CTRL_RC4_RST (1 << 8)
++#define VIDEO_CTRL_RC4_VIDEO_M_SEL (1 << 7) //video management
++#define VIDEO_CTRL_RC4_VIDEO_2_SEL (1 << 6) // Video 2
++
++#define VIDEO_CTRL_DWN_SCALING_MASK (0x3 << 4)
++#define VIDEO_CTRL_DWN_SCALING(x) (x << 4)
++#define DWN_V1 0x1
++#define DWN_V2 0x2
++#define DWN_VM 0x3
++
++
++
++#define VIDEO_CTRL_VSYNC_DELAY_MASK (3 << 2)
++#define VIDEO_CTRL_VSYNC_DELAY(x) (x << 2)
++#define NO_DELAY 0
++#define DELAY_DIV12_HSYNC 1
++#define AUTO_DELAY 2
++
++
++/* AST_VIDEO_INT_EN 0x304 Video interrupt Enable */
++/* AST_VIDEO_INT_STS 0x308 Video interrupt status */
++#define VIDEO_FRAME_COMPLETE (1 << 5)
++#define VIDEO_MODE_DETECT_RDY (1 << 4)
++#define VIDEO_COMPRESS_COMPLETE (1 << 3)
++#define VIDEO_COMPRESS_PKT_COMPLETE (1 << 2)
++#define VIDEO_CAPTURE_COMPLETE (1 << 1)
++#define VIDEO_MODE_DETECT_WDT (1 << 0)
++
++/* AST_VIDEO_MODE_DETECT 0x30C Video Mode Detection Parameter Register */
++#define VIDEO_MODE_HOR_TOLER(x) (x << 28)
++#define VIDEO_MODE_VER_TOLER(x) (x << 24)
++#define VIDEO_MODE_HOR_STABLE(x) (x << 20)
++#define VIDEO_MODE_VER_STABLE(x) (x << 16)
++#define VIDEO_MODE_EDG_THROD(x) (x << 8)
++
++#define MODEDETECTION_VERTICAL_STABLE_MAXIMUM 0x6
++#define MODEDETECTION_HORIZONTAL_STABLE_MAXIMUM 0x6
++#define MODEDETECTION_VERTICAL_STABLE_THRESHOLD 0x2
++#define MODEDETECTION_HORIZONTAL_STABLE_THRESHOLD 0x2
++
++/* AST_VIDEO_SCRATCH_34C 0x34C Video Scratch Remap Read Back */
++#define SCRATCH_VGA_GET_REFLASH_RATE(x) ((x >> 8) & 0xf)
++#define SCRATCH_VGA_GET_COLOR_MODE(x) ((x >> 4) & 0xf)
++
++/* AST_VIDEO_SCRATCH_350 0x350 Video Scratch Remap Read Back */
++#define SCRATCH_VGA_GET_MODE_HEADER(x) ((x >> 8) & 0xff)
++#define SCRATCH_VGA_GET_NEW_COLOR_MODE(x) ((x >> 16) & 0xff)
++#define SCRATCH_VGA_GET_NEW_PIXEL_CLK(x) ((x >> 24) & 0xff)
++
++
++/* AST_VIDEO_SCRATCH_35C 0x35C Video Scratch Remap Read Back */
++#define SCRATCH_VGA_PWR_STS_HSYNC (1 << 31)
++#define SCRATCH_VGA_PWR_STS_VSYNC (1 << 30)
++#define SCRATCH_VGA_ATTRIBTE_INDEX_BIT5 (1 << 29)
++#define SCRATCH_VGA_MASK_REG (1 << 28)
++#define SCRATCH_VGA_CRT_RST (1 << 27)
++#define SCRATCH_VGA_SCREEN_OFF (1 << 26)
++#define SCRATCH_VGA_RESET (1 << 25)
++#define SCRATCH_VGA_ENABLE (1 << 24)
++
++
++#endif
++
+diff --git a/arch/arm/plat-aspeed/include/plat/regs-vuart.h b/arch/arm/plat-aspeed/include/plat/regs-vuart.h
+new file mode 100644
+index 0000000..b4bb88a
+--- /dev/null
++++ b/arch/arm/plat-aspeed/include/plat/regs-vuart.h
+@@ -0,0 +1,39 @@
++/* arch/arm/plat-aspeed/include/mach/regs-iic.h
++ *
++ * Copyright (c) 2012 ASPEED Technology Inc. <ryan_chen@aspeedtech.com>
++ * http://www.aspeedtech.com/
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * ASPEED VUART Controller
++*/
++
++#ifndef __AST_VUART_H_
++#define __AST_VUART_H_
++
++#define AST_VUART_CTRLA 0x20
++#define AST_VUART_CTRLB 0x24
++#define AST_VUART_ADDRL 0x28
++#define AST_VUART_ADDRH 0x2C
++#define AST_VUART_CTRLE 0x30
++#define AST_VUART_CTRLF 0x34
++#define AST_VUART_CTRLG 0x38
++#define AST_VUART_CTRLH 0x3C
++
++
++
++/* AST_VUART_CTRLA 0x20 */
++#define VUART_ENABLE (1 << 0)
++#define VUART_SIRQ_POLARITY (1 << 1)
++#define VUART_DISABLE_H_TX_DISCARD (1 << 5)
++
++
++/* AST_VUART_CTRLB 0x24 */
++#define SET_SIRQ_NUM(x) (x << 4)
++
++
++
++
++#endif
+diff --git a/arch/arm/plat-aspeed/irq.c b/arch/arm/plat-aspeed/irq.c
+new file mode 100644
+index 0000000..b118359
+--- /dev/null
++++ b/arch/arm/plat-aspeed/irq.c
+@@ -0,0 +1,136 @@
++/*
++ * linux/arch/arm/plat-aspeed/irq.c
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++ */
++#include <linux/init.h>
++#include <linux/stddef.h>
++#include <linux/list.h>
++#include <linux/timer.h>
++
++#include <linux/device.h>
++#include <linux/dma-mapping.h>
++#include <linux/platform_device.h>
++#include <linux/sysdev.h>
++#include <linux/interrupt.h>
++#include <linux/irq.h>
++#include <asm/system.h>
++#include <asm/irq.h>
++#include <asm/io.h>
++#include <asm/mach/irq.h>
++#include <mach/hardware.h>
++
++#include <plat/regs-intr.h>
++
++static void ast_mask_irq(unsigned int irq)
++{
++ int i=0;
++ u32 regVal;
++ u8 timer;
++
++#ifdef IRQ_TIMER7
++ if(((irq >= IRQ_TIMER0) && (irq <= IRQ_TIMER2)) || ((i >= IRQ_TIMER3) && (i <= IRQ_TIMER7)))
++ timer = 1;
++
++#else
++ if((irq >= IRQ_TIMER0) && (irq <= IRQ_TIMER2))
++ timer = 1;
++#endif
++
++ if (irq > 32) {
++ i=1;
++ irq = irq - 32;
++ } else
++ i=0;
++
++ regVal = readl(AST_INTR_DIS(i));
++ regVal |= (1 << irq);
++ writel(regVal, AST_INTR_DIS(i));
++
++ /*
++ * clear the interrupt
++ */
++ if(timer)
++ IRQ_EDGE_CLEAR(i,irq);
++
++}
++
++static void ast_unmask_irq(unsigned int irq)
++{
++ int i;
++ u32 regVal;
++
++ if (irq > 32) {
++ i=1;
++ irq = irq - 32;
++ } else
++ i=0;
++
++ regVal = readl(AST_INTR_EN(i));
++ regVal |= (1 << irq);
++ writel(regVal, AST_INTR_EN(i));
++}
++
++static struct irq_chip ast_irq_chip = {
++ .name = "ast_irq",
++ .ack = ast_mask_irq,
++ .mask = ast_mask_irq,
++ .unmask = ast_unmask_irq,
++};
++
++void __init ast_init_irq(void)
++{
++ unsigned int i;
++
++ /* VIC1 */
++ writel(0, AST_INTR_SEL(0));
++ writel(0, AST_INTR_EN(0));
++ writel(0xFFFFFFFF, AST_INTR_DIS(0));
++ writel(0xFFFFFFFF, AST_INTR_EDGE_CLR(0));
++
++#if defined(NEW_VIC)
++ writel(0, AST_INTR_SEL(1));
++ writel(0, AST_INTR_EN(1));
++ writel(0xFFFFFFFF, AST_INTR_DIS(1));
++ writel(0xFFFFFFFF, AST_INTR_EDGE_CLR(1));
++#endif
++
++ //TOTAL IRQ NUM =
++ for (i = 0; i < AST_VIC_NUM; i++)
++ {
++ if(i<32) {
++ if((i >= IRQ_TIMER0) && (i <= IRQ_TIMER2)) //Timer0/1/2
++ IRQ_SET_RISING_EDGE(0,i);
++ else {
++ IRQ_SET_HIGH_LEVEL(0,i);
++ IRQ_SET_LEVEL_TRIGGER(0,i);
++ }
++#ifdef IRQ_TIMER7
++ } else {
++ if((i >= IRQ_TIMER3) && (i <= IRQ_TIMER7)) //Timer3/4/5/6/7
++ IRQ_SET_RISING_EDGE(0,i-32);
++ else {
++ IRQ_SET_HIGH_LEVEL(1,i-32);
++ IRQ_SET_LEVEL_TRIGGER(1,i-32);
++ }
++#endif
++ }
++
++ set_irq_chip(i, &ast_irq_chip);
++ set_irq_handler(i, handle_level_irq);
++ set_irq_flags(i, IRQF_VALID);
++ }
++
++}
+diff --git a/arch/arm/plat-aspeed/timer.c b/arch/arm/plat-aspeed/timer.c
+new file mode 100644
+index 0000000..079d958
+--- /dev/null
++++ b/arch/arm/plat-aspeed/timer.c
+@@ -0,0 +1,137 @@
++/*
++ * timer.c
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++ */
++
++#include <linux/types.h>
++#include <linux/kernel.h>
++#include <linux/init.h>
++#include <linux/device.h>
++#include <linux/spinlock.h>
++#include <linux/interrupt.h>
++#include <linux/sched.h>
++
++#include <linux/irq.h>
++#include <asm/system.h>
++#include <asm/io.h>
++#include <mach/hardware.h>
++#include <mach/irqs.h>
++#include <mach/time.h>
++#include <plat/ast-scu.h>
++
++#define ASPEED_TIMER0_VA_BASE (IO_ADDRESS(AST_TIMER_BASE)+ASPEED_TIMER0_OFFSET)
++#define ASPEED_TIMER1_VA_BASE (IO_ADDRESS(AST_TIMER_BASE)+ASPEED_TIMER1_OFFSET)
++#define ASPEED_TIMER2_VA_BASE (IO_ADDRESS(AST_TIMER_BASE)+ASPEED_TIMER2_OFFSET)
++#define ASPEED_TIMERC_VA_BASE (IO_ADDRESS(AST_TIMER_BASE)+ASPEED_TIMERRC_OFFSET)
++
++/*
++ * Returns number of ms since last clock interrupt. Note that interrupts
++ * will have been disabled by do_gettimeoffset()
++ */
++static unsigned long ast_gettimeoffset(void)
++{
++ volatile TimerStruct_t *timer0 = (TimerStruct_t *) ASPEED_TIMER0_VA_BASE;
++ unsigned long ticks1, ticks2;//, status;
++
++ /*
++ * Get the current number of ticks. Note that there is a race
++ * condition between us reading the timer and checking for
++ * an interrupt. We get around this by ensuring that the
++ * counter has not reloaded between our two reads.
++ */
++ ticks2 = timer0->TimerValue;
++ do {
++ ticks1 = ticks2;
++// status = readl(AST_RAW_STS(0));// __raw_readl(IO_ADDRESS(ASPEED_VIC_BASE) + ASPEED_VIC_RAW_STATUS_OFFSET);
++ ticks2 = timer0->TimerValue;
++ } while (ticks2 > ticks1);
++
++ /*
++ * Number of ticks since last interrupt.
++ */
++ ticks1 = TIMER_RELOAD - ticks2;
++
++ /*
++ * Interrupt pending? If so, we've reloaded once already.
++ */
++// if (status & (1 << IRQ_TIMER0))
++// ticks1 += TIMER_RELOAD;
++
++ /*
++ * Convert the ticks to usecs
++ */
++ return TICKS2USECS(ticks1);
++}
++
++
++/*
++ * IRQ handler for the timer
++ */
++static irqreturn_t
++ast_timer_interrupt(int irq, void *dev_id)
++{
++
++// write_seqlock(&xtime_lock);
++
++ /*
++ * clear the interrupt in Irq.c
++ */
++// IRQ_EDGE_CLEAR(0,IRQ_TIMER0);
++
++ timer_tick();
++
++
++// write_sequnlock(&xtime_lock);
++
++ return IRQ_HANDLED;
++}
++
++static struct irqaction ast_timer_irq = {
++ .name = "ast timer",
++ .flags = IRQF_DISABLED | IRQF_TIMER,
++ .handler = ast_timer_interrupt,
++};
++
++/*
++ * Set up timer interrupt, and return the current time in seconds.
++ */
++static void __init ast_setup_timer(void)
++{
++ volatile TimerStruct_t *timer0 = (volatile TimerStruct_t *) ASPEED_TIMER0_VA_BASE;
++ volatile __u32 *timerc = (volatile __u32*) ASPEED_TIMERC_VA_BASE;
++
++ /*
++ * Initialise to a known state (all timers off)
++ */
++ *timerc = 0;
++
++ timer0->TimerLoad = TIMER_RELOAD - 1;
++ timer0->TimerValue = TIMER_RELOAD - 1;
++ *timerc = TIMER0_ENABLE | TIMER0_RefExt;
++
++ /*
++ * Make irqs happen for the system timer
++ */
++ ast_scu_show_system_info();
++
++ setup_irq(IRQ_TIMER0, &ast_timer_irq);
++
++}
++
++struct sys_timer ast_timer = {
++ .init = ast_setup_timer,
++// .offset = ast_gettimeoffset,
++};
+diff --git a/arch/arm/tools/mach-types b/arch/arm/tools/mach-types
+index 43aa202..d2bf539 100644
+--- a/arch/arm/tools/mach-types
++++ b/arch/arm/tools/mach-types
+@@ -1899,3 +1899,4 @@ rut100 MACH_RUT100 RUT100 1908
+ asusp535 MACH_ASUSP535 ASUSP535 1909
+ htcraphael MACH_HTCRAPHAEL HTCRAPHAEL 1910
+ sygdg1 MACH_SYGDG1 SYGDG1 1911
++aspeed MACH_ASPEED ASPEED 8888
+diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig
+index 43d6ba8..a714292 100644
+--- a/drivers/char/Kconfig
++++ b/drivers/char/Kconfig
+@@ -665,6 +665,7 @@ config IBM_BSR
+ between several cores on a system
+
+ source "drivers/char/ipmi/Kconfig"
++source "drivers/char/aspeed/Kconfig"
+
+ config DS1620
+ tristate "NetWinder thermometer support"
+diff --git a/drivers/char/Makefile b/drivers/char/Makefile
+index 438f713..ee197cb 100644
+--- a/drivers/char/Makefile
++++ b/drivers/char/Makefile
+@@ -85,6 +85,7 @@ obj-$(CONFIG_TOSHIBA) += toshiba.o
+ obj-$(CONFIG_I8K) += i8k.o
+ obj-$(CONFIG_DS1620) += ds1620.o
+ obj-$(CONFIG_HW_RANDOM) += hw_random/
++obj-$(CONFIG_AST_MISC) += aspeed/
+ obj-$(CONFIG_PPDEV) += ppdev.o
+ obj-$(CONFIG_NWBUTTON) += nwbutton.o
+ obj-$(CONFIG_NWFLASH) += nwflash.o
+diff --git a/drivers/char/aspeed/Kconfig b/drivers/char/aspeed/Kconfig
+new file mode 100644
+index 0000000..7aee8d3
+--- /dev/null
++++ b/drivers/char/aspeed/Kconfig
+@@ -0,0 +1,52 @@
++#
++# MISC configuration for ASPEED SOCs
++#
++
++if ARCH_ASPEED
++menuconfig AST_MISC
++ tristate 'MISC drivers for ASPEED SOCs'
++ help
++ We can select misc drivers for ASPEED SOC in this sub-function.
++
++if AST_MISC
++config AST_VIDEO
++ tristate "ASPEED Video Engine driver"
++ default n
++ help
++ Driver for AST Video Engine
++
++config ADC_CAT9883
++ tristate "CAT 9883 ADC driver"
++ default n
++ help
++ Driver for CAT 9883
++
++config AST_SPI_BIOS
++ tristate "ASPEED SPI BIOS flash register"
++ default n
++ help
++ Driver for SPI BIOS flash register
++
++config AST_PECI
++ tristate "ASPEED PECI Controller"
++ default n
++ help
++ Driver for PECI Controller
++
++config AST_KCS
++ tristate 'ASPEED KCS support'
++ help
++ Support for the KCS channels on the ASPEED chips,
++ providing /dev/kcs0, 1 and 2 (note, some machines may not
++ provide all of these ports, depending on how the serial port
++ pins are configured.
++
++config AST_GPIO
++ tristate "ASPEED GPIO Controller"
++ default n
++ help
++ Driver for GPIO Controller included in ASPEED SOCs.
++
++endif # CONFIG_AST_MISC
++endif # CONFIG_AST
++
+diff --git a/drivers/char/aspeed/Makefile b/drivers/char/aspeed/Makefile
+new file mode 100644
+index 0000000..517b2b7
+--- /dev/null
++++ b/drivers/char/aspeed/Makefile
+@@ -0,0 +1,9 @@
++#
++# Makefile for the ASPEED drivers.
++#
++
++obj-$(CONFIG_AST_VIDEO) += ast_video.o
++obj-$(CONFIG_ADC_CAT9883) += adc_cat9883.o
++obj-$(CONFIG_AST_KCS) += ast_kcs.o
++obj-$(CONFIG_AST_GPIO) += ast_gpio.o
++obj-$(CONFIG_AST_PECI) += ast_peci.o
+diff --git a/drivers/char/aspeed/ast_peci.c b/drivers/char/aspeed/ast_peci.c
+new file mode 100644
+index 0000000..1f7cae3
+--- /dev/null
++++ b/drivers/char/aspeed/ast_peci.c
+@@ -0,0 +1,508 @@
++/********************************************************************************
++* File Name : ast_peci.c
++* Author : Ryan Chen
++* Description : AST PECI Controller
++*
++* Copyright (C) 2012-2020 ASPEED Technology Inc.
++* This program is free software; you can redistribute it and/or modify
++* it under the terms of the GNU General Public License as published by the Free Software Foundation;
++* either version 2 of the License, or (at your option) any later version.
++* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
++* without even the implied warranty of MERCHANTABILITY or
++* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
++* You should have received a copy of the GNU General Public License
++* along with this program; if not, write to the Free Software
++* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++*
++* Version : 1.0
++* History :
++* 1. 2013/01/30 Ryan Chen create this file
++*
++********************************************************************************/
++
++#include <linux/module.h>
++#include <linux/fs.h>
++#include <linux/init.h>
++#include <linux/platform_device.h>
++#include <linux/types.h>
++#include <linux/interrupt.h>
++#include <asm/uaccess.h>
++
++#include <asm/io.h>
++#include <linux/delay.h>
++#include <linux/miscdevice.h>
++#ifdef CONFIG_COLDFIRE
++#include <asm/arch/regs-peci.h>
++#else
++#include <plat/regs-peci.h>
++#endif
++
++//#define CONFIG_AST_PECI_DEBUG
++
++#ifdef CONFIG_AST_PECI_DEBUG
++ #define PECI_DBG(fmt, args...) printk("%s(): " fmt, __FUNCTION__, ## args)
++#else
++ #define PECI_DBG(fmt, args...)
++#endif
++
++/***********************************************************************/
++struct timing_negotiation {
++ u8 msg_timing;
++ u8 addr_timing;
++};
++
++struct xfer_msg {
++ u8 client_addr;
++ u8 tx_len;
++ u8 rx_len;
++ u8 tx_fcs;
++ u8 rx_fcs;
++ u8 fcs_en;
++ u8 sw_fcs;
++ u8 *tx_buf;
++ u8 *rx_buf;
++ u32 sts;
++};
++
++#define PECI_DEVICE "/dev/ast-peci"
++
++//IOCTL ..
++#define PECIIOC_BASE 'P'
++
++#define AST_PECI_IOCRTIMING _IOR(PECIIOC_BASE, 0, struct timing_negotiation*)
++#define AST_PECI_IOCWTIMING _IOW(PECIIOC_BASE, 1, struct timing_negotiation*)
++#define AST_PECI_IOCXFER _IOWR(PECIIOC_BASE, 2, struct xfer_msg*)
++
++
++/***********************************************************************/
++
++static struct ast_peci_data {
++ struct device *misc_dev;
++ void __iomem *reg_base; /* virtual */
++ int irq; //PECI IRQ number
++ int open_count;
++ struct completion xfer_complete;
++ u32 sts;
++ struct mutex lock;
++} ast_peci;
++
++static inline void
++ast_peci_write(u32 val, u32 reg)
++{
++ PECI_DBG("write offset: %x, val: %x \n",reg,val);
++ writel(val, ast_peci.reg_base + reg);
++}
++
++static inline u32
++ast_peci_read(u32 reg)
++{
++ u32 val = readl(ast_peci.reg_base + reg);
++ PECI_DBG("read offset: %x, val: %x \n",reg,val);
++ return val;
++}
++
++static long ast_peci_ioctl(struct file *fp,
++ unsigned int cmd, unsigned long arg)
++{
++ long ret = 0;
++ void __user *argp = (void __user *)arg;
++ struct xfer_msg msg;
++ struct timing_negotiation tim_ng;
++ u32 peci_head;
++ int i=0;
++ u32 *tx_buf0 = (u32 *) (ast_peci.reg_base + AST_PECI_W_DATA0);
++ u32 *tx_buf1 = (u32 *) (ast_peci.reg_base + AST_PECI_W_DATA4);
++ u32 *rx_buf0 = (u32 *) (ast_peci.reg_base + AST_PECI_R_DATA0);
++ u32 *rx_buf1 = (u32 *) (ast_peci.reg_base + AST_PECI_R_DATA4);
++ u32 rx_data;
++
++ PECI_DBG("ast_peci_ioctl cmd %x \n", cmd);
++
++ switch(cmd) {
++ case AST_PECI_IOCRTIMING:
++ tim_ng.msg_timing = PECI_TIMING_MESSAGE_GET(ast_peci_read(AST_PECI_TIMING));
++ tim_ng.addr_timing = PECI_TIMING_ADDRESS_GET(ast_peci_read(AST_PECI_TIMING));
++ if (copy_to_user(argp, &tim_ng, sizeof(struct timing_negotiation)))
++ ret = -EFAULT;
++ break;
++
++ case AST_PECI_IOCWTIMING:
++ if (copy_from_user(&tim_ng, argp, sizeof(struct timing_negotiation))) {
++ ret = -EFAULT;
++ } else {
++ ast_peci_write(PECI_TIMING_MESSAGE(tim_ng.msg_timing) |
++ PECI_TIMING_ADDRESS(tim_ng.addr_timing), AST_PECI_TIMING);
++ }
++ break;
++
++ case AST_PECI_IOCXFER:
++ //Check cmd operation sts
++ while(ast_peci_read(AST_PECI_CMD) & PECI_CMD_FIRE) {
++ printk("wait for free \n");
++ };
++
++ if (copy_from_user(&msg, argp, sizeof(struct xfer_msg))) {
++ ret = -EFAULT;
++ break;
++ }
++
++#ifdef CONFIG_AST_PECI_DEBUG
++ printk("fcs_en %d, client_addr %x, tx_len %d, rx_len %d",msg.fcs_en ,msg.client_addr, msg.tx_len, msg.rx_len);
++ printk("\ntx_buf : ");
++ for(i = 0;i< msg.tx_len; i++)
++ printk(" %x ",msg.tx_buf[i]);
++ printk("\n");
++#endif
++
++ if(msg.fcs_en)
++ peci_head = PECI_TAGET_ADDR(msg.client_addr) |
++ PECI_WRITE_LEN(msg.tx_len) |
++ PECI_READ_LEN(msg.rx_len) | PECI_AW_FCS_EN;
++ else
++ peci_head = PECI_TAGET_ADDR(msg.client_addr) |
++ PECI_WRITE_LEN(msg.tx_len) |
++ PECI_READ_LEN(msg.rx_len);
++
++
++ ast_peci_write(peci_head, AST_PECI_CMD_CTRL);
++
++ for(i = 0; i < msg.tx_len; i++) {
++ if(i < 16) {
++ if(i%4 == 0)
++ tx_buf0[i/4] = 0;
++ tx_buf0[i/4] |= (msg.tx_buf[i] << ((i%4)*8)) ;
++ } else {
++ if(i%4 == 0)
++ tx_buf1[i/4] = 0;
++ tx_buf1[i/4] |= (msg.tx_buf[i] << ((i%4)*8)) ;
++ }
++ }
++
++#ifdef CONFIG_AST_PECI_DEBUG
++ printk("\nWD \n ");
++ ast_peci_read(AST_PECI_W_DATA0);
++ ast_peci_read(AST_PECI_W_DATA1);
++ ast_peci_read(AST_PECI_W_DATA2);
++ ast_peci_read(AST_PECI_W_DATA3);
++ ast_peci_read(AST_PECI_W_DATA4);
++ ast_peci_read(AST_PECI_W_DATA5);
++ ast_peci_read(AST_PECI_W_DATA6);
++ ast_peci_read(AST_PECI_W_DATA7);
++#endif
++ init_completion(&ast_peci.xfer_complete);
++ //Fire Command
++ ast_peci_write(PECI_CMD_FIRE, AST_PECI_CMD);
++
++
++ ret = wait_for_completion_interruptible_timeout(&ast_peci.xfer_complete, 30*HZ);
++
++ if (ret == 0)
++ printk("peci controller timed out\n");
++
++ for(i = 0; i < msg.rx_len; i++) {
++ if(i < 16) {
++ switch(i%4) {
++ case 0:
++ rx_data = rx_buf0[i/4];
++
++ msg.rx_buf[i] = rx_data & 0xff;
++ break;
++ case 1:
++ msg.rx_buf[i] = (rx_data & 0xff00) >> 8;
++ break;
++ case 2:
++ msg.rx_buf[i] = (rx_data & 0xff0000) >> 16;
++ break;
++ case 3:
++ msg.rx_buf[i] = (rx_data & 0xff000000) >> 24;
++ break;
++
++ }
++ } else {
++ switch(i%4) {
++ case 0:
++ rx_data = rx_buf1[i/4];
++ msg.rx_buf[i] = rx_data & 0xff;
++ break;
++ case 1:
++ msg.rx_buf[i] = (rx_data & 0xff00) >> 8;
++ break;
++ case 2:
++ msg.rx_buf[i] = (rx_data & 0xff0000) >> 16;
++ break;
++ case 3:
++ msg.rx_buf[i] = (rx_data & 0xff000000) >> 24;
++ break;
++
++ }
++ }
++ }
++#ifdef CONFIG_AST_PECI_DEBUG
++ printk("\nRD \n");
++ ast_peci_read(AST_PECI_R_DATA0);
++ ast_peci_read(AST_PECI_R_DATA1);
++ ast_peci_read(AST_PECI_R_DATA2);
++ ast_peci_read(AST_PECI_R_DATA3);
++ ast_peci_read(AST_PECI_R_DATA4);
++ ast_peci_read(AST_PECI_R_DATA5);
++ ast_peci_read(AST_PECI_R_DATA6);
++ ast_peci_read(AST_PECI_R_DATA7);
++
++ printk("rx_buf : ");
++ for(i = 0;i< msg.rx_len; i++)
++ printk("%x ",msg.rx_buf[i]);
++ printk("\n");
++#endif
++ msg.sts = ast_peci.sts;
++ msg.rx_fcs = PECI_CAPTURE_READ_FCS(ast_peci_read(AST_PECI_CAP_FCS));
++ if (copy_to_user(argp, &msg, sizeof(struct xfer_msg)))
++ ret = -EFAULT;
++
++ break;
++ default:
++ printk("ast_peci_ioctl command fail\n");
++ ret = -ENOTTY;
++ break;
++ }
++
++ return ret;
++}
++
++static int ast_peci_open(struct inode *inode, struct file *file)
++{
++ PECI_DBG("ast_peci_open\n");
++
++
++ /* Flush input queue on first open */
++ if (ast_peci.open_count)
++ return -1;
++
++ ast_peci.open_count++;
++
++
++ return 0;
++}
++
++static int ast_peci_release(struct inode *inode, struct file *file)
++{
++ PECI_DBG("ast_peci_release\n");
++ ast_peci.open_count--;
++
++ return 0;
++}
++
++static irqreturn_t ast_peci_handler(int this_irq, void *dev_id)
++{
++ ast_peci.sts = (0x1f & ast_peci_read(AST_PECI_INT_STS));
++
++ switch(ast_peci.sts) {
++ case PECI_INT_TIMEOUT:
++ printk("PECI_INT_TIMEOUT \n");
++ ast_peci_write(PECI_INT_TIMEOUT, AST_PECI_INT_STS);
++ break;
++ case PECI_INT_CONNECT:
++ printk("PECI_INT_CONNECT \n");
++ ast_peci_write(PECI_INT_CONNECT, AST_PECI_INT_STS);
++ break;
++ case PECI_INT_W_FCS_BAD:
++ printk("PECI_INT_W_FCS_BAD \n");
++ ast_peci_write(PECI_INT_W_FCS_BAD, AST_PECI_INT_STS);
++ break;
++ case PECI_INT_W_FCS_ABORT:
++ printk("PECI_INT_W_FCS_ABORT \n");
++ ast_peci_write(PECI_INT_W_FCS_ABORT, AST_PECI_INT_STS);
++ break;
++ case PECI_INT_CMD_DONE:
++ printk("PECI_INT_CMD_DONE \n");
++ ast_peci_write(PECI_INT_CMD_DONE, AST_PECI_INT_STS);
++ ast_peci_write(0, AST_PECI_CMD);
++ break;
++ default:
++ printk("no one handle .... \n");
++ break;
++
++ }
++
++ complete(&ast_peci.xfer_complete);
++
++ return IRQ_HANDLED;
++
++}
++
++static void ast_peci_ctrl_init(void)
++{
++ //PECI Timing Setting : should 4 times of peci clk period 64 = 16 * 4 ??
++ ast_peci_write(PECI_TIMING_MESSAGE(64) | PECI_TIMING_ADDRESS(64), AST_PECI_TIMING);
++
++
++ //PECI Programmable AWFCS
++ //ast_peci_write(ast_peci, PECI_PROGRAM_AW_FCS, AST_PECI_EXP_FCS);
++
++ //TODO .....
++ //Clear Interrupt
++ ast_peci_write(PECI_INT_TIMEOUT | PECI_INT_CONNECT |
++ PECI_INT_W_FCS_BAD | PECI_INT_W_FCS_ABORT |
++ PECI_INT_CMD_DONE, AST_PECI_INT_STS);
++
++ //PECI Negotiation Selection , interrupt enable
++ //Set nego mode : 1st bit of addr negotiation
++ ast_peci_write(PECI_INT_TIMEOUT | PECI_INT_CONNECT |
++ PECI_INT_W_FCS_BAD | PECI_INT_W_FCS_ABORT |
++ PECI_INT_CMD_DONE, AST_PECI_INT_CTRL);
++
++ //PECI Spec wide speed rangs [2kbps~2Mbps]
++ //Sampling 8/16, READ mode : Point Sampling , CLK source : 24Mhz , DIV by 8 : 3 --> CLK is 3Mhz
++ //PECI CTRL Enable
++
++ ast_peci_write(PECI_CTRL_SAMPLING(8) | PECI_CTRL_CLK_DIV(3) |
++ PECI_CTRL_PECI_EN |
++ PECI_CTRL_PECI_CLK_EN, AST_PECI_CTRL);
++}
++
++static const struct file_operations ast_peci_fops = {
++ .owner = THIS_MODULE,
++ .llseek = no_llseek,
++ .unlocked_ioctl = ast_peci_ioctl,
++ .open = ast_peci_open,
++ .release = ast_peci_release,
++};
++
++struct miscdevice ast_peci_misc = {
++ .minor = MISC_DYNAMIC_MINOR,
++ .name = "ast-peci",
++ .fops = &ast_peci_fops,
++};
++
++static int ast_peci_probe(struct platform_device *pdev)
++{
++ struct resource *res;
++ int ret=0;
++
++
++ PECI_DBG("ast_peci_probe\n");
++
++ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
++ if (NULL == res) {
++ dev_err(&pdev->dev, "cannot get IORESOURCE_MEM\n");
++ ret = -ENOENT;
++ goto out;
++ }
++
++ if (!request_mem_region(res->start, resource_size(res), res->name)) {
++ dev_err(&pdev->dev, "cannot reserved region\n");
++ ret = -ENXIO;
++ goto out;
++ }
++
++ ast_peci.reg_base = ioremap(res->start, resource_size(res));
++ if (!ast_peci.reg_base) {
++ ret = -EIO;
++ goto out_region;
++ }
++
++ ast_peci.irq = platform_get_irq(pdev, 0);
++ if (ast_peci.irq < 0) {
++ dev_err(&pdev->dev, "no irq specified\n");
++ ret = -ENOENT;
++ goto out_region;
++ }
++
++ ret = request_irq(ast_peci.irq, ast_peci_handler, IRQF_SHARED,
++ "ast-peci", &ast_peci);
++
++ if (ret) {
++ printk(KERN_INFO "PECI: Failed request irq %d\n", ast_peci.irq);
++ goto out_region;
++ }
++
++ ret = misc_register(&ast_peci_misc);
++ if (ret){
++ printk(KERN_ERR "PECI : failed to request interrupt\n");
++ goto out_irq;
++ }
++
++ ast_peci_ctrl_init();
++
++ printk(KERN_INFO "ast_peci: driver successfully loaded.\n");
++
++ return 0;
++
++
++out_irq:
++ free_irq(ast_peci.irq, NULL);
++out_region:
++ release_mem_region(res->start, res->end - res->start + 1);
++out:
++ printk(KERN_WARNING "applesmc: driver init failed (ret=%d)!\n", ret);
++ return ret;
++}
++
++static int ast_peci_remove(struct platform_device *pdev)
++{
++ struct resource *res;
++
++ PECI_DBG("ast_peci_remove\n");
++
++ misc_deregister(&ast_peci_misc);
++
++ free_irq(ast_peci.irq, &ast_peci);
++
++ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
++
++ iounmap(ast_peci.reg_base);
++
++ release_mem_region(res->start, res->end - res->start + 1);
++
++ return 0;
++}
++
++#ifdef CONFIG_PM
++static int
++ast_peci_suspend(struct platform_device *pdev, pm_message_t state)
++{
++ printk("ast_peci_suspend : TODO \n");
++ return 0;
++}
++
++static int
++ast_peci_resume(struct platform_device *pdev)
++{
++ ast_peci_ctrl_init();
++ return 0;
++}
++
++#else
++#define ast_peci_suspend NULL
++#define ast_peci_resume NULL
++#endif
++
++static struct platform_driver ast_peci_driver = {
++ .probe = ast_peci_probe,
++ .remove = __devexit_p(ast_peci_remove),
++ .suspend = ast_peci_suspend,
++ .resume = ast_peci_resume,
++ .driver = {
++ .name = "ast_peci",
++ .owner = THIS_MODULE,
++ },
++};
++
++static int __init
++ast_peci_init(void)
++{
++ return platform_driver_register(&ast_peci_driver);
++}
++
++static void __exit
++ast_peci_exit(void)
++{
++ platform_driver_unregister(&ast_peci_driver);
++}
++
++module_init(ast_peci_init);
++module_exit(ast_peci_exit);
++
++MODULE_AUTHOR("Ryan Chen <ryan_chen@aspeedtech.com>");
++MODULE_DESCRIPTION("PECI driver");
++MODULE_LICENSE("GPL");
++
+diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c
+index a4424c8..1963ba6 100644
+--- a/drivers/gpio/gpiolib.c
++++ b/drivers/gpio/gpiolib.c
+@@ -265,9 +265,13 @@ static ssize_t gpio_value_store(struct device *dev,
+
+ if (!test_bit(FLAG_EXPORT, &desc->flags))
+ status = -EIO;
+- else if (!test_bit(FLAG_IS_OUT, &desc->flags))
++#if 0 //Ryan Modify for AST GPIO Feature
++ else if (!test_bit(FLAG_IS_OUT, &desc->flags)) {
+ status = -EPERM;
++ } else {
++#else
+ else {
++#endif
+ long value;
+
+ status = strict_strtol(buf, 0, &value);
+diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig
+index c709e82..681782b 100644
+--- a/drivers/hwmon/Kconfig
++++ b/drivers/hwmon/Kconfig
+@@ -854,6 +854,22 @@ config SENSORS_LIS3LV02D
+ This driver can also be built as a module. If so, the module
+ will be called lis3lv02d.
+
++config SENSORS_AST_ADC
++ tristate "ASPEED ADC Controller Driver"
++ depends on ARCH_ASPEED
++ default n
++ help
++ This driver provides support for the ASPEED ADC
++ Controller, which provides an Voltage Sensor.
++
++config SENSORS_AST_PWM_FAN
++ tristate "ASPEED PWM & FAN Tacho Controller Driver"
++ depends on ARCH_ASPEED
++ default n
++ help
++ This driver provides support for the ASPEED PWM & FAN Tacho
++ Controller, which provides an Sensor, fan control.
++
+ config SENSORS_APPLESMC
+ tristate "Apple SMC (Motion sensor, light sensor, keyboard backlight)"
+ depends on INPUT && X86
+diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile
+index 58fc5be..5629727 100644
+--- a/drivers/hwmon/Makefile
++++ b/drivers/hwmon/Makefile
+@@ -29,6 +29,8 @@ obj-$(CONFIG_SENSORS_ADT7462) += adt7462.o
+ obj-$(CONFIG_SENSORS_ADT7470) += adt7470.o
+ obj-$(CONFIG_SENSORS_ADT7473) += adt7473.o
+ obj-$(CONFIG_SENSORS_APPLESMC) += applesmc.o
++obj-$(CONFIG_SENSORS_AST_ADC) += ast_adc.o
++obj-$(CONFIG_SENSORS_AST_PWM_FAN) += ast_pwm_fan.o
+ obj-$(CONFIG_SENSORS_AMS) += ams/
+ obj-$(CONFIG_SENSORS_ATXP1) += atxp1.o
+ obj-$(CONFIG_SENSORS_CORETEMP) += coretemp.o
+diff --git a/drivers/hwmon/ast_adc.c b/drivers/hwmon/ast_adc.c
+new file mode 100644
+index 0000000..0969e39
+--- /dev/null
++++ b/drivers/hwmon/ast_adc.c
+@@ -0,0 +1,734 @@
++/*
++ * ast_adc.c
++ *
++ * ASPEED ADC controller driver
++ *
++ * Copyright (C) 2012-2020 ASPEED Technology Inc.
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * History:
++ * 2012.11.26: Initial version [Ryan Chen]
++ */
++
++/* attr ADC sysfs 0~max adc channel
++* 0 - show/store enable
++* 3 - show value
++* 1 - show/store alarm_en set enable
++* 2 - show alarm get statuse
++* 4 - show/store upper
++* 5 - show/store lower */
++
++
++#include <linux/delay.h>
++#include <linux/platform_device.h>
++#include <linux/kernel.h>
++#include <linux/module.h>
++#include <linux/timer.h>
++#include <linux/mutex.h>
++#include <linux/hwmon-sysfs.h>
++#include <linux/hwmon.h>
++#include <linux/workqueue.h>
++#include <linux/sysfs.h>
++#include <linux/err.h>
++
++#include <mach/hardware.h>
++#include <asm/irq.h>
++#include <asm/io.h>
++
++#include <plat/regs-adc.h>
++#include <plat/ast-scu.h>
++
++
++#define REST_DESIGN 0
++
++struct adc_vcc_ref_data {
++ int v2;
++ int r1;
++ int r2;
++};
++
++static struct adc_vcc_ref_data adc_vcc_ref[5] = {
++ [0] = {
++ .v2 = 0,
++ .r1 = 5600,
++ .r2 = 1000,
++ },
++ [1] = {
++ .v2 = -12,
++ .r1 = 1000,
++ .r2 = 10000,
++ },
++ [2] = {
++ .v2 = 0,
++ .r1 = 1800,
++ .r2 = 1000,
++ },
++ [3] = {
++ .v2 = -5,
++ .r1 = 2200,
++ .r2 = 10000,
++ },
++ [4] = {
++ .v2 = 0,
++ .r1 = 56000,
++ .r2 = 1000,
++ },
++};
++
++struct ast_adc_data {
++ struct device *hwmon_dev;
++ void __iomem *reg_base; /* virtual */
++ int irq; //ADC IRQ number
++ int compen_value; //Compensating value
++};
++
++struct ast_adc_data *ast_adc;
++
++static u8 ast_get_adc_en(struct ast_adc_data *ast_adc, u8 adc_ch);
++
++
++static inline void
++ast_adc_write(struct ast_adc_data *ast_adc, u32 val, u32 reg)
++{
++// printk("write offset: %x, val: %x \n",reg,val);
++ writel(val, ast_adc->reg_base+ reg);
++}
++
++static inline u32
++ast_adc_read(struct ast_adc_data *ast_adc, u32 reg)
++{
++ u32 val = readl(ast_adc->reg_base + reg);
++// printk("read offset: %x, val: %x \n",reg,val);
++ return val;
++}
++
++static void ast_adc_ctrl_init(void)
++{
++ u32 pclk;
++ ast_adc_write(ast_adc, AST_ADC_CTRL_COMPEN | AST_ADC_CTRL_NORMAL | AST_ADC_CTRL_EN, AST_ADC_CTRL);
++
++ //Set wait a sensing cycle t (s) = 1000 * 12 * (1/PCLK) * 2 * (ADC0c[31:17] + 1) * (ADC0c[9:0] +1)
++ //ex : pclk = 48Mhz , ADC0c[31:17] = 0, ADC0c[9:0] = 0x40 : 64, ADC0c[31:17] = 0x3e7 : 999
++ // --> 0.0325s = 12 * 2 * (0x3e7 + 1) *(64+1) / 48000000
++ // --> 0.0005s = 12 * 2 * (0x3e7 + 1) / 48000000
++
++ pclk = ast_get_pclk();
++
++#if defined(CONFIG_ARCH_AST2300)
++ ast_adc_write(ast_adc, 0x3e7, AST_ADC_CLK);
++
++ ast_adc_write(ast_adc, AST_ADC_CTRL_CH12_EN | AST_ADC_CTRL_COMPEN_CLR| ast_adc_read(ast_adc, AST_ADC_CTRL), AST_ADC_CTRL);
++
++ mdelay(50);
++
++ //compensating value = 0x200 - ADC10[9:0]
++ if(ast_adc_read(ast_adc, AST_ADC_CH12_13) & (0x1 << 8))
++ ast_adc->compen_value = 0x200 - (ast_adc_read(ast_adc, AST_ADC_CH12_13) & AST_ADC_L_CH_MASK);
++ else
++ ast_adc->compen_value = 0 - (ast_adc_read(ast_adc, AST_ADC_CH12_13) & AST_ADC_L_CH_MASK);
++
++ printk("compensating value %d \n",ast_adc->compen_value);
++
++#elif defined(CONFIG_ARCH_AST2400)
++
++ //For AST2400 A0 workaround ... ADC0c = 1 ;
++// ast_adc_write(ast_adc, 1, AST_ADC_CLK);
++// ast_adc_write(ast_adc, (0x3e7<< 17) | 0x40, AST_ADC_CLK);
++ ast_adc_write(ast_adc, 0x40, AST_ADC_CLK);
++
++ ast_adc_write(ast_adc, AST_ADC_CTRL_CH0_EN | AST_ADC_CTRL_COMPEN | AST_ADC_CTRL_NORMAL | AST_ADC_CTRL_EN, AST_ADC_CTRL);
++
++ ast_adc_read(ast_adc, AST_ADC_CTRL);
++
++ mdelay(1);
++
++ //compensating value = 0x200 - ADC10[9:0]
++ ast_adc->compen_value = 0x200 - (ast_adc_read(ast_adc, AST_ADC_CH0_1) & AST_ADC_L_CH_MASK);
++ printk("compensating value %d \n",ast_adc->compen_value);
++
++#elif defined(CONFIG_ARCH_AST2500)
++// TODO ...
++// scu read trim
++// write trim 0xc4 [3:0]
++
++ ast_adc_write(ast_adc, 0x40, AST_ADC_CLK);
++
++ ast_adc_write(ast_adc, AST_ADC_CTRL_NORMAL | AST_ADC_CTRL_EN, AST_ADC_CTRL);
++
++ while(!ast_adc_read(ast_adc, AST_ADC_CTRL) & 0x100);
++
++ ast_adc_write(ast_adc, AST_ADC_CTRL_COMPEN | AST_ADC_CTRL_NORMAL | AST_ADC_CTRL_EN, AST_ADC_CTRL);
++
++ while(ast_adc_read(ast_adc, AST_ADC_CTRL) & AST_ADC_CTRL_COMPEN);
++
++ //compensating value = 0x200 - ADC10[9:0]
++ ast_adc->compen_value = 0x200 - ((ast_adc_read(ast_adc, AST_ADC_TRIM) >> 16) & 0x3ff);
++ printk("compensating value %d \n",ast_adc->compen_value);
++
++#else
++#err "No define for ADC "
++#endif
++
++ ast_adc_write(ast_adc, AST_ADC_CTRL_NORMAL | AST_ADC_CTRL_EN, AST_ADC_CTRL);
++
++}
++
++static u16
++ast_get_adc_hyster_lower(struct ast_adc_data *ast_adc, u8 adc_ch)
++{
++ u16 tmp=0;
++ tmp = ast_adc_read(ast_adc, AST_ADC_HYSTER0 + (adc_ch *4)) & AST_ADC_L_BOUND;
++
++// printk("read val = %d \n",tmp);
++
++ return tmp;
++
++}
++
++static void
++ast_set_adc_hyster_lower(struct ast_adc_data *ast_adc, u8 adc_ch, u16 value)
++{
++ ast_adc_write(ast_adc,
++ (ast_adc_read(ast_adc, AST_ADC_HYSTER0 + (adc_ch *4)) & ~AST_ADC_L_BOUND) |
++ value,
++ AST_ADC_HYSTER0 + (adc_ch *4));
++
++}
++
++static u16
++ast_get_adc_hyster_upper(struct ast_adc_data *ast_adc, u8 adc_ch)
++{
++ u16 tmp=0;
++ tmp = ((ast_adc_read(ast_adc, AST_ADC_HYSTER0 + (adc_ch *4)) & AST_ADC_H_BOUND) >> 16);
++
++// printk("read val = %d \n",tmp);
++
++ return tmp;
++}
++
++static void
++ast_set_adc_hyster_upper(struct ast_adc_data *ast_adc, u8 adc_ch, u32 value)
++{
++ ast_adc_write(ast_adc,
++ (ast_adc_read(ast_adc, AST_ADC_HYSTER0 + (adc_ch *4)) & ~AST_ADC_H_BOUND) |
++ (value << 16),
++ AST_ADC_HYSTER0 + (adc_ch *4));
++
++}
++
++static u8
++ast_get_adc_hyster_en(struct ast_adc_data *ast_adc, u8 adc_ch)
++{
++ //tacho source
++ if(ast_adc_read(ast_adc, AST_ADC_HYSTER0 + (adc_ch *4)) & AST_ADC_HYSTER_EN)
++ return 1;
++ else
++ return 0;
++}
++
++static void
++ast_set_adc_hyster_en(struct ast_adc_data *ast_adc, u8 adc_ch, u8 enable)
++{
++ //tacho source
++ if(enable == 1)
++ ast_adc_write(ast_adc,
++ ast_adc_read(ast_adc, AST_ADC_HYSTER0 + (adc_ch *4)) | AST_ADC_HYSTER_EN,
++ AST_ADC_HYSTER0 + (adc_ch *4));
++ else
++ ast_adc_write(ast_adc,
++ ast_adc_read(ast_adc, AST_ADC_HYSTER0 + (adc_ch *4)) & ~AST_ADC_HYSTER_EN,
++ AST_ADC_HYSTER0 + (adc_ch *4));
++}
++
++static u16
++ast_get_adc_lower(struct ast_adc_data *ast_adc, u8 adc_ch)
++{
++ u16 tmp=0;
++ tmp = ast_adc_read(ast_adc, AST_ADC_BOUND0 + (adc_ch *4)) & AST_ADC_L_BOUND;
++
++// printk("read val = %d \n",tmp);
++
++ return tmp;
++
++}
++
++static void
++ast_set_adc_lower(struct ast_adc_data *ast_adc, u8 adc_ch, u16 value)
++{
++ ast_adc_write(ast_adc,
++ (ast_adc_read(ast_adc, AST_ADC_BOUND0 + (adc_ch *4)) & ~AST_ADC_L_BOUND) |
++ value,
++ AST_ADC_BOUND0 + (adc_ch *4));
++
++}
++
++static u16
++ast_get_adc_upper(struct ast_adc_data *ast_adc, u8 adc_ch)
++{
++ u16 tmp=0;
++ tmp = ((ast_adc_read(ast_adc, AST_ADC_BOUND0 + (adc_ch *4)) & AST_ADC_H_BOUND) >> 16);
++
++ printk("read val = %d \n",tmp);
++
++ return tmp;
++
++
++}
++
++static void
++ast_set_adc_upper(struct ast_adc_data *ast_adc, u8 adc_ch, u32 value)
++{
++ ast_adc_write(ast_adc,
++ (ast_adc_read(ast_adc, AST_ADC_BOUND0 + (adc_ch *4)) & ~AST_ADC_H_BOUND) |
++ (value << 16),
++ AST_ADC_BOUND0 + (adc_ch *4));
++
++}
++
++
++static u8
++ast_get_adc_alarm(struct ast_adc_data *ast_adc, u8 adc_ch)
++{
++ //adc ch source
++ if(ast_adc_read(ast_adc, AST_ADC_IER) & (0x1 << adc_ch))
++ return 1;
++ else
++ return 0;
++}
++
++static u16
++ast_get_adc_value(struct ast_adc_data *ast_adc, u8 adc_ch)
++{
++ int tmp;
++
++ switch(adc_ch) {
++ case 0:
++ tmp = ast_adc_read(ast_adc, AST_ADC_CH0_1) & AST_ADC_L_CH_MASK;
++ break;
++ case 1:
++ tmp = (ast_adc_read(ast_adc, AST_ADC_CH0_1) & AST_ADC_H_CH_MASK) >> 16;
++ break;
++ case 2:
++ tmp = ast_adc_read(ast_adc, AST_ADC_CH2_3) & AST_ADC_L_CH_MASK;
++ break;
++ case 3:
++ tmp = (ast_adc_read(ast_adc, AST_ADC_CH2_3) & AST_ADC_H_CH_MASK) >> 16;
++ break;
++ case 4:
++ tmp = ast_adc_read(ast_adc, AST_ADC_CH4_5) & AST_ADC_L_CH_MASK;
++ break;
++ case 5:
++ tmp = (ast_adc_read(ast_adc, AST_ADC_CH4_5) & AST_ADC_H_CH_MASK) >> 16;
++ break;
++ case 6:
++ tmp = ast_adc_read(ast_adc, AST_ADC_CH6_7) & AST_ADC_L_CH_MASK;
++ break;
++ case 7:
++ tmp = (ast_adc_read(ast_adc, AST_ADC_CH6_7) & AST_ADC_H_CH_MASK) >> 16;
++ break;
++ case 8:
++ tmp = ast_adc_read(ast_adc, AST_ADC_CH8_9) & AST_ADC_L_CH_MASK;
++ break;
++ case 9:
++ tmp = (ast_adc_read(ast_adc, AST_ADC_CH8_9) & AST_ADC_H_CH_MASK) >> 16;
++ break;
++ case 10:
++ tmp = ast_adc_read(ast_adc, AST_ADC_CH10_11) & AST_ADC_L_CH_MASK;
++ break;
++ case 11:
++ tmp = (ast_adc_read(ast_adc, AST_ADC_CH10_11) & AST_ADC_H_CH_MASK) >> 16;
++ break;
++ case 12:
++ tmp = ast_adc_read(ast_adc, AST_ADC_CH12_13) & AST_ADC_L_CH_MASK;
++ break;
++ case 13:
++ tmp = (ast_adc_read(ast_adc, AST_ADC_CH12_13) & AST_ADC_H_CH_MASK) >> 16;
++ break;
++ case 14:
++ tmp = ast_adc_read(ast_adc, AST_ADC_CH14_15) & AST_ADC_L_CH_MASK;
++ break;
++ case 15:
++ tmp = (ast_adc_read(ast_adc, AST_ADC_CH14_15) & AST_ADC_H_CH_MASK) >> 16;
++ break;
++
++ }
++
++ tmp += ast_adc->compen_value;
++
++// printk("voltage = %d \n",tmp);
++
++ return tmp;
++
++}
++
++static u8
++ast_get_adc_en(struct ast_adc_data *ast_adc, u8 adc_ch)
++{
++ u8 tmp=0;
++
++ if(ast_adc_read(ast_adc, AST_ADC_CTRL) & (0x1 << (16+adc_ch)))
++ tmp = 1;
++ else
++ tmp = 0;
++
++ return tmp;
++
++}
++
++static void
++ast_set_adc_en(struct ast_adc_data *ast_adc, u8 adc_ch, u8 enable)
++{
++ if(enable)
++ ast_adc_write(ast_adc, ast_adc_read(ast_adc, AST_ADC_CTRL) | (0x1 << (16+adc_ch)), AST_ADC_CTRL);
++ else
++ ast_adc_write(ast_adc, ast_adc_read(ast_adc, AST_ADC_CTRL) & ~(0x1 << (16+adc_ch)), AST_ADC_CTRL);
++}
++
++
++/* attr ADC sysfs 0~max adc channel
++* 0 - show/store channel enable
++* 1 - show value
++* 2 - show alarm get statuse
++* 3 - show/store upper
++* 4 - show/store lower
++* 5 - show/store hystersis enable
++* 6 - show/store hystersis upper
++* 7 - show/store hystersis low
++*/
++
++static ssize_t
++ast_show_adc(struct device *dev, struct device_attribute *attr, char *sysfsbuf)
++{
++ struct sensor_device_attribute_2 *sensor_attr = to_sensor_dev_attr_2(attr);
++ u16 tmp;
++ u32 voltage,tmp1, tmp2,tmp3;
++
++ //sensor_attr->index : pwm_ch#
++ //sensor_attr->nr : attr#
++ switch(sensor_attr->nr)
++ {
++ case 0: //channel enable, disable
++ return sprintf(sysfsbuf, "%d : %s\n", ast_get_adc_en(ast_adc,sensor_attr->index),ast_get_adc_en(ast_adc,sensor_attr->index) ? "Enable":"Disable");
++ break;
++ case 1: //value
++ tmp = ast_get_adc_value(ast_adc, sensor_attr->index);
++ //Voltage Sense Method
++ tmp1 = (adc_vcc_ref[REST_DESIGN].r1 + adc_vcc_ref[REST_DESIGN].r2) * tmp * 25 * 10;
++ tmp2 = adc_vcc_ref[REST_DESIGN].r2 * 1023 ;
++
++ tmp3 = (adc_vcc_ref[REST_DESIGN].r1 * adc_vcc_ref[REST_DESIGN].v2) / adc_vcc_ref[REST_DESIGN].r2;
++ // printk("tmp3 = %d \n",tmp3);
++ voltage = (tmp1/tmp2) - tmp3;
++
++ return sprintf(sysfsbuf, "%d.%d (V)\n",voltage/100, voltage%100);
++ break;
++ case 2: //alarm
++ return sprintf(sysfsbuf, "%d \n", ast_get_adc_alarm(ast_adc,sensor_attr->index));
++ break;
++ case 3: //upper
++ return sprintf(sysfsbuf, "%d \n", ast_get_adc_upper(ast_adc,sensor_attr->index));
++ break;
++ case 4: //lower
++ return sprintf(sysfsbuf, "%d \n", ast_get_adc_lower(ast_adc,sensor_attr->index));
++ break;
++ case 5: //hystersis enable
++ return sprintf(sysfsbuf, "%d : %s\n", ast_get_adc_hyster_en(ast_adc,sensor_attr->index),ast_get_adc_hyster_en(ast_adc,sensor_attr->index) ? "Enable":"Disable");
++ break;
++ case 6: //hystersis upper
++ return sprintf(sysfsbuf, "%d \n", ast_get_adc_hyster_upper(ast_adc,sensor_attr->index));
++ break;
++ case 7: //hystersis lower
++ return sprintf(sysfsbuf, "%d \n", ast_get_adc_hyster_lower(ast_adc,sensor_attr->index));
++ break;
++
++ default:
++ return -EINVAL;
++ break;
++ }
++}
++
++static ssize_t
++ast_store_adc(struct device *dev, struct device_attribute *attr, const char *sysfsbuf, size_t count)
++{
++ u32 input_val;
++ struct sensor_device_attribute_2 *sensor_attr =
++ to_sensor_dev_attr_2(attr);
++
++ input_val = simple_strtoul(sysfsbuf, NULL, 10);
++
++ //sensor_attr->index : pwm_ch#
++ //sensor_attr->nr : attr#
++ switch(sensor_attr->nr)
++ {
++ case 0: //enable, disable
++ ast_set_adc_en(ast_adc, sensor_attr->index, input_val);
++ break;
++ case 1: //value
++
++ break;
++ case 2: //alarm
++ break;
++ case 3:
++ ast_set_adc_upper(ast_adc, sensor_attr->index, input_val);
++ break;
++ case 4:
++ ast_set_adc_lower(ast_adc, sensor_attr->index, input_val);
++ break;
++ case 5: //hystersis
++ ast_set_adc_hyster_en(ast_adc, sensor_attr->index, input_val);
++ break;
++ case 6:
++ ast_set_adc_hyster_upper(ast_adc, sensor_attr->index, input_val);
++ break;
++ case 7:
++ ast_set_adc_hyster_lower(ast_adc, sensor_attr->index, input_val);
++ break;
++
++ default:
++ return -EINVAL;
++ break;
++ }
++
++ return count;
++}
++
++/* attr ADC sysfs 0~max adc channel
++* 0 - show/store channel enable
++* 1 - show value
++* 2 - show alarm get statuse
++* 3 - show/store upper
++* 4 - show/store lower
++* 5 - show/store hystersis enable
++* 6 - show/store hystersis upper
++* 7 - show/store hystersis low
++*/
++
++#define sysfs_adc_ch(index) \
++static SENSOR_DEVICE_ATTR_2(adc##index##_en, S_IRUGO | S_IWUSR, \
++ ast_show_adc, ast_store_adc, 0, index); \
++\
++static SENSOR_DEVICE_ATTR_2(adc##index##_value, S_IRUGO | S_IWUSR, \
++ ast_show_adc, NULL, 1, index); \
++\
++static SENSOR_DEVICE_ATTR_2(adc##index##_alarm, S_IRUGO | S_IWUSR, \
++ ast_show_adc, NULL, 2, index); \
++\
++static SENSOR_DEVICE_ATTR_2(adc##index##_upper, S_IRUGO | S_IWUSR, \
++ ast_show_adc, ast_store_adc, 3, index); \
++\
++static SENSOR_DEVICE_ATTR_2(adc##index##_lower, S_IRUGO | S_IWUSR, \
++ ast_show_adc, ast_store_adc, 4, index); \
++\
++static SENSOR_DEVICE_ATTR_2(adc##index##_hyster_en, S_IRUGO | S_IWUSR, \
++ ast_show_adc, ast_store_adc, 5, index); \
++\
++static SENSOR_DEVICE_ATTR_2(adc##index##_hyster_upper, S_IRUGO | S_IWUSR, \
++ ast_show_adc, ast_store_adc, 6, index); \
++\
++static SENSOR_DEVICE_ATTR_2(adc##index##_hyster_lower, S_IRUGO | S_IWUSR, \
++ ast_show_adc, ast_store_adc, 7, index); \
++\
++static struct attribute *adc##index##_attributes[] = { \
++ &sensor_dev_attr_adc##index##_en.dev_attr.attr, \
++ &sensor_dev_attr_adc##index##_value.dev_attr.attr, \
++ &sensor_dev_attr_adc##index##_alarm.dev_attr.attr, \
++ &sensor_dev_attr_adc##index##_upper.dev_attr.attr, \
++ &sensor_dev_attr_adc##index##_lower.dev_attr.attr, \
++ &sensor_dev_attr_adc##index##_hyster_en.dev_attr.attr, \
++ &sensor_dev_attr_adc##index##_hyster_upper.dev_attr.attr, \
++ &sensor_dev_attr_adc##index##_hyster_lower.dev_attr.attr, \
++ NULL \
++};
++
++/*
++ * Create the needed functions for each pwm using the macro defined above
++ * (4 pwms are supported)
++ */
++sysfs_adc_ch(0);
++sysfs_adc_ch(1);
++sysfs_adc_ch(2);
++sysfs_adc_ch(3);
++sysfs_adc_ch(4);
++sysfs_adc_ch(5);
++sysfs_adc_ch(6);
++sysfs_adc_ch(7);
++sysfs_adc_ch(8);
++sysfs_adc_ch(9);
++sysfs_adc_ch(10);
++sysfs_adc_ch(11);
++#if defined(CONFIG_ARCH_AST2400) || defined(CONFIG_ARCH_AST2500)
++sysfs_adc_ch(12);
++sysfs_adc_ch(13);
++sysfs_adc_ch(14);
++sysfs_adc_ch(15);
++#endif
++
++static const struct attribute_group adc_attribute_groups[] = {
++ { .attrs = adc0_attributes },
++ { .attrs = adc1_attributes },
++ { .attrs = adc2_attributes },
++ { .attrs = adc3_attributes },
++ { .attrs = adc4_attributes },
++ { .attrs = adc5_attributes },
++ { .attrs = adc6_attributes },
++ { .attrs = adc7_attributes },
++ { .attrs = adc8_attributes },
++ { .attrs = adc9_attributes },
++ { .attrs = adc10_attributes },
++ { .attrs = adc11_attributes },
++#if defined(CONFIG_ARCH_AST2400) || defined(CONFIG_ARCH_AST2500)
++ { .attrs = adc12_attributes },
++ { .attrs = adc13_attributes },
++ { .attrs = adc14_attributes },
++ { .attrs = adc15_attributes },
++#endif
++};
++
++
++static int
++ast_adc_probe(struct platform_device *pdev)
++{
++ struct resource *res;
++ int err;
++ int ret=0;
++ int i;
++
++ dev_dbg(&pdev->dev, "ast_adc_probe \n");
++
++ ast_adc = kzalloc(sizeof(struct ast_adc_data), GFP_KERNEL);
++ if (!ast_adc) {
++ ret = -ENOMEM;
++ goto out;
++ }
++
++ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
++ if (NULL == res) {
++ dev_err(&pdev->dev, "cannot get IORESOURCE_MEM\n");
++ ret = -ENOENT;
++ goto out_mem;
++ }
++
++ if (!request_mem_region(res->start, resource_size(res), res->name)) {
++ dev_err(&pdev->dev, "cannot reserved region\n");
++ ret = -ENXIO;
++ goto out_mem;
++ }
++
++ ast_adc->reg_base = ioremap(res->start, resource_size(res));
++ if (!ast_adc->reg_base) {
++ ret = -EIO;
++ goto out_region;
++ }
++
++ ast_adc->irq = platform_get_irq(pdev, 0);
++ if (ast_adc->irq < 0) {
++ dev_err(&pdev->dev, "no irq specified\n");
++ ret = -ENOENT;
++ goto out_region;
++ }
++
++ /* Register sysfs hooks */
++ ast_adc->hwmon_dev = hwmon_device_register(&pdev->dev);
++ if (IS_ERR(ast_adc->hwmon_dev)) {
++ ret = PTR_ERR(ast_adc->hwmon_dev);
++ goto out_region;
++ }
++
++ for(i=0; i<MAX_CH_NO; i++) {
++ err = sysfs_create_group(&pdev->dev.kobj, &adc_attribute_groups[i]);
++ if (err)
++ goto out_region;
++ }
++
++ ast_adc_ctrl_init();
++
++ printk(KERN_INFO "ast_adc: driver successfully loaded.\n");
++
++ return 0;
++
++
++//out_irq:
++// free_irq(ast_adc->irq, NULL);
++out_region:
++ release_mem_region(res->start, res->end - res->start + 1);
++out_mem:
++ kfree(ast_adc);
++out:
++ printk(KERN_WARNING "applesmc: driver init failed (ret=%d)!\n", ret);
++ return ret;
++}
++
++static int
++ast_adc_remove(struct platform_device *pdev)
++{
++ int i=0;
++ struct ast_adc_data *ast_adc = platform_get_drvdata(pdev);
++ struct resource *res;
++ printk(KERN_INFO "ast_adc: driver unloaded.\n");
++
++ hwmon_device_unregister(ast_adc->hwmon_dev);
++
++ for(i=0; i<5; i++)
++ sysfs_remove_group(&pdev->dev.kobj, &adc_attribute_groups[i]);
++
++ platform_set_drvdata(pdev, NULL);
++// free_irq(ast_adc->irq, ast_adc);
++ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
++ iounmap(ast_adc->reg_base);
++ release_mem_region(res->start, res->end - res->start + 1);
++ kfree(ast_adc);
++ return 0;
++}
++
++#ifdef CONFIG_PM
++static int
++ast_adc_suspend(struct platform_device *pdev, pm_message_t state)
++{
++ printk("ast_adc_suspend : TODO \n");
++ return 0;
++}
++
++static int
++ast_adc_resume(struct platform_device *pdev)
++{
++ ast_adc_ctrl_init();
++ return 0;
++}
++
++#else
++#define ast_adc_suspend NULL
++#define ast_adc_resume NULL
++#endif
++
++static struct platform_driver ast_adc_driver = {
++ .probe = ast_adc_probe,
++ .remove = __devexit_p(ast_adc_remove),
++ .suspend = ast_adc_suspend,
++ .resume = ast_adc_resume,
++ .driver = {
++ .name = "ast_adc",
++ .owner = THIS_MODULE,
++ },
++};
++
++static int __init
++ast_adc_init(void)
++{
++ return platform_driver_register(&ast_adc_driver);
++}
++
++static void __exit
++ast_adc_exit(void)
++{
++ platform_driver_unregister(&ast_adc_driver);
++}
++
++module_init(ast_adc_init);
++module_exit(ast_adc_exit);
++
++MODULE_AUTHOR("Ryan Chen <ryan_chen@aspeedtech.com>");
++MODULE_DESCRIPTION("ADC driver");
++MODULE_LICENSE("GPL");
+diff --git a/drivers/hwmon/ast_lcp_80h.c b/drivers/hwmon/ast_lcp_80h.c
+new file mode 100755
+index 0000000..681d2d6
+--- /dev/null
++++ b/drivers/hwmon/ast_lcp_80h.c
+@@ -0,0 +1,312 @@
++/*
++ * ast_lpc_snoop.c
++ *
++ * ASPEED LPC Snoop controller driver
++ *
++ * Copyright (C) 2012-2020 ASPEED Technology Inc.
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * History:
++ * 2012.11.26: Initial version [Ryan Chen]
++ */
++
++#include <linux/delay.h>
++#include <linux/platform_device.h>
++#include <linux/kernel.h>
++#include <linux/module.h>
++#include <linux/timer.h>
++#include <linux/mutex.h>
++#include <linux/hwmon-sysfs.h>
++#include <linux/hwmon.h>
++#include <linux/workqueue.h>
++#include <linux/sysfs.h>
++#include <linux/err.h>
++
++#include <mach/hardware.h>
++#include <asm/irq.h>
++#include <asm/io.h>
++
++#include <plat/regs-1070_lpc.h>
++
++struct ast_clpc_data {
++ struct device *hwmon_dev;
++ void __iomem *reg_base; /* virtual */
++ int irq; //ADC IRQ number
++ u8 80h_data; //80h_data
++};
++
++static inline void
++ast_clpc_write(struct ast_clpc_data *ast_clpc, u32 val, u32 reg)
++{
++// printk("write offset: %x, val: %x \n",reg,val);
++ writel(val, ast_clpc->reg_base+ reg);
++}
++
++static inline u32
++ast_clpc_read(struct ast_adc_data *ast_clpc, u32 reg)
++{
++ u32 val = readl(ast_clpc->reg_base + reg);
++// printk("read offset: %x, val: %x \n",reg,val);
++ return val;
++}
++
++static irqreturn_t ast_lpc_80h_handler(int irq, void *dev_id)
++{
++ struct ast_clpc_data *ast_clpc = dev_id;
++ u32 sts = ast_clpc_read(ast_clpc, AST1070_LPC_80H_CTRL);
++
++ if(isr_sts & AST1070_LPC_80H_CLR) {
++ ast_clpc->80h_data = ast_clpc_read(ast_clpc, AST1070_LPC_80H_DATA);
++ ast_clpc_write(ast_clpc, AST1070_LPC_80H_CLR, AST1070_LPC_80H_DATA);
++ } else
++ printk("IRQ ISSUE bug \n");
++
++ return IRQ_HANDLED;
++
++}
++
++static void ast_clpc_80h_init(struct ast_clpc_data *ast_clpc, u16 addr)
++{
++ ast_clpc_write(ast_clpc, AST1070_LPC_80H_CLR, AST1070_LPC_80H_CTRL);
++
++ //Snoop Port
++ ast_clpc_write(ast_clpc, addr & 0xff, AST1070_LPC_L_80H_ADDR);
++ ast_clpc_write(ast_clpc, (addr & 0xff) >> 8 , AST1070_LPC_H_80H_ADDR);
++ //Clear Interrupt and Enable
++ //AST1070 BUG :===: D[4] W1C
++ ast_clpc_write(ast_clpc, AST1070_LPC_80H_CLR, AST1070_LPC_80H_DATA);
++ ast_clpc_write(ast_clpc, AST1070_LPC_80H_CLR | AST1070_LPC_80H_EN, AST1070_LPC_80H_CTRL);
++}
++
++/* attr 80H sysfs 0~max adc channel
++* 0 - show/store 80h addr
++* 1 - show 80h data
++*/
++
++static ssize_t
++ast_show_clpc(struct device *dev, struct device_attribute *attr, char *sysfsbuf)
++{
++ struct sensor_device_attribute_2 *sensor_attr = to_sensor_dev_attr_2(attr);
++ u16 tmp;
++ u32 voltage,tmp1, tmp2,tmp3;
++
++ //sensor_attr->index : pwm_ch#
++ //sensor_attr->nr : attr#
++ switch(sensor_attr->nr)
++ {
++ case 0: //channel enable, disable
++ return sprintf(sysfsbuf, "%d \n", ast_clpc->80h_data);
++ break;
++
++ default:
++ return -EINVAL;
++ break;
++ }
++}
++
++static ssize_t
++ast_store_clpc(struct device *dev, struct device_attribute *attr, const char *sysfsbuf, size_t count)
++{
++ u32 input_val;
++ struct sensor_device_attribute_2 *sensor_attr =
++ to_sensor_dev_attr_2(attr);
++
++ input_val = simple_strtoul(sysfsbuf, NULL, 10);
++
++ //sensor_attr->index : pwm_ch#
++ //sensor_attr->nr : attr#
++ switch(sensor_attr->nr)
++ {
++ case 0: //enable, disable
++
++ break;
++ default:
++ return -EINVAL;
++ break;
++ }
++
++ return count;
++}
++
++/* attr ADC sysfs 0~max adc channel
++* 0 - show 80h data
++*/
++
++#define sysfs_clpc(index) \
++static SENSOR_DEVICE_ATTR_2(clpc##index##_en, S_IRUGO | S_IWUSR, \
++ ast_show_clpc, NULL, 0, index); \
++\
++static struct attribute *clpc##index##_attributes[] = { \
++ &sensor_dev_attr_clpc##index##_80h.dev_attr.attr, \
++ NULL \
++};
++
++/*
++ * Create the needed functions for each pwm using the macro defined above
++ * (4 pwms are supported)
++ */
++sysfs_clpc(0);
++
++static const struct attribute_group clpc_attribute_groups[] = {
++ { .attrs = clpc0_attributes },
++};
++
++
++static int
++ast_clpc_probe(struct platform_device *pdev)
++{
++ struct ast_clpc_data *ast_clpc;
++ struct resource *res;
++ int err;
++ int ret=0;
++ int i;
++
++ dev_dbg(&pdev->dev, "ast_clpc_probe \n");
++
++ ast_clpc = kzalloc(sizeof(struct ast_clpc_data), GFP_KERNEL);
++ if (!ast_adc) {
++ ret = -ENOMEM;
++ goto out;
++ }
++
++ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
++ if (NULL == res) {
++ dev_err(&pdev->dev, "cannot get IORESOURCE_MEM\n");
++ ret = -ENOENT;
++ goto out_mem;
++ }
++
++ if (!request_mem_region(res->start, resource_size(res), res->name)) {
++ dev_err(&pdev->dev, "cannot reserved region\n");
++ ret = -ENXIO;
++ goto out_mem;
++ }
++
++ ast_clpc->reg_base = ioremap(res->start, resource_size(res));
++ if (!ast_clpc->reg_base) {
++ ret = -EIO;
++ goto out_region;
++ }
++
++ ast_clpc->irq = platform_get_irq(pdev, 3);
++ if (ast_clpc->irq < 0) {
++ dev_err(&pdev->dev, "no irq specified\n");
++ ret = -ENOENT;
++ goto out_region;
++ }
++
++
++ /* Register sysfs hooks */
++ ast_clpc->hwmon_dev = hwmon_device_register(&pdev->dev);
++ if (IS_ERR(ast_clpc->hwmon_dev)) {
++ ret = PTR_ERR(ast_clpc->hwmon_dev);
++ goto out_region;
++ }
++
++ for(i=0; i< MAX_CH_NO; i++) {
++ err = sysfs_create_group(&pdev->dev.kobj, &clpc_attribute_groups[i]);
++ if (err)
++ goto out_region;
++ }
++
++ ast_clpc_80h_init();
++
++ ret = request_irq(ast_clpc->irq, ast_lpc_handler, IRQF_SHARED,
++ i2c_dev->adap.name, i2c_dev);
++ if (ret) {
++ printk(KERN_INFO "I2C: Failed request irq %d\n", i2c_dev->irq);
++ goto out_region;
++ }
++
++ platform_set_drvdata(pdev, ast_clpc);
++
++ printk(KERN_INFO "ast_adc: driver successfully loaded.\n");
++
++ return 0;
++
++
++//out_irq:
++// free_irq(ast_clpc->irq, NULL);
++out_region:
++ release_mem_region(res->start, res->end - res->start + 1);
++out_mem:
++ kfree(ast_clpc);
++out:
++ printk(KERN_WARNING "applesmc: driver init failed (ret=%d)!\n", ret);
++ return ret;
++}
++
++static int
++ast_adc_remove(struct platform_device *pdev)
++{
++ int i=0;
++ struct ast_adc_data *ast_clpc = platform_get_drvdata(pdev);
++ struct resource *res;
++ printk(KERN_INFO "ast_adc: driver unloaded.\n");
++
++ hwmon_device_unregister(ast_clpc->hwmon_dev);
++
++ for(i=0; i<5; i++)
++ sysfs_remove_group(&pdev->dev.kobj, &clpc_attribute_groups[i]);
++
++ platform_set_drvdata(pdev, NULL);
++// free_irq(ast_adc->irq, ast_adc);
++ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
++ iounmap(ast_clpc->reg_base);
++ release_mem_region(res->start, res->end - res->start + 1);
++ kfree(ast_clpc);
++ return 0;
++}
++
++#ifdef CONFIG_PM
++static int
++ast_adc_suspend(struct platform_device *pdev, pm_message_t state)
++{
++ printk("ast_adc_suspend : TODO \n");
++ return 0;
++}
++
++static int
++ast_adc_resume(struct platform_device *pdev)
++{
++ ast_adc_ctrl_init();
++ return 0;
++}
++
++#else
++#define ast_adc_suspend NULL
++#define ast_adc_resume NULL
++#endif
++
++static struct platform_driver ast_adc_driver = {
++ .probe = ast_adc_probe,
++ .remove = __devexit_p(ast_adc_remove),
++ .suspend = ast_adc_suspend,
++ .resume = ast_adc_resume,
++ .driver = {
++ .name = "ast_adc",
++ .owner = THIS_MODULE,
++ },
++};
++
++static int __init
++ast_adc_init(void)
++{
++ return platform_driver_register(&ast_adc_driver);
++}
++
++static void __exit
++ast_adc_exit(void)
++{
++ platform_driver_unregister(&ast_adc_driver);
++}
++
++module_init(ast_adc_init);
++module_exit(ast_adc_exit);
++
++MODULE_AUTHOR("Ryan Chen <ryan_chen@aspeedtech.com>");
++MODULE_DESCRIPTION("ADC driver");
++MODULE_LICENSE("GPL");
+diff --git a/drivers/hwmon/ast_pwm_fan.c b/drivers/hwmon/ast_pwm_fan.c
+new file mode 100644
+index 0000000..02784c5
+--- /dev/null
++++ b/drivers/hwmon/ast_pwm_fan.c
+@@ -0,0 +1,2129 @@
++/*
++ * ast_pwm_fan.c
++ *
++ * ASPEED PWM & Fan Tacho controller driver
++ *
++ * Copyright (C) 2012-2020 ASPEED Technology Inc.
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * History:
++ * 2012.08.06: Initial version [Ryan Chen]
++ */
++/* CLK sysfs
++* 0 : enable
++* 1 : clk_source */
++
++/* PWM sysfs A~H (0~7)
++* 0 - show/store enable
++* 1 - show/store type
++* 2 - show/store falling
++* 3 - show/store rising */
++
++/*PWM M/N/O Type sysfs
++* 0 - show/store unit
++* 1 - show/store division_l
++* 2 - show/store division_h */
++
++/* FAN sysfs (0~15)
++* - show/store enable
++* - show/store source
++* - show/store rpm
++* - show/store alarm
++* - show/store alarm_en */
++
++/* Fan M/N/O Type sysfs
++* 0 - show/store enable
++* 1 - show/store mode
++* 2 - show/store unit
++* 3 - show/store division
++* 4 - show/store limit */
++
++#include <linux/delay.h>
++#include <linux/platform_device.h>
++#include <linux/kernel.h>
++#include <linux/module.h>
++#include <linux/timer.h>
++#include <linux/mutex.h>
++#include <linux/hwmon-sysfs.h>
++#include <linux/hwmon.h>
++#include <linux/workqueue.h>
++#include <linux/sysfs.h>
++#include <linux/err.h>
++#include <linux/slab.h>
++
++#include <asm/irq.h>
++#include <asm/io.h>
++
++#ifdef CONFIG_COLDFIRE
++#include <asm/arch/regs-pwm_fan.h>
++#include <asm/arch/ast_pwm_techo.h>
++#else
++#include <plat/regs-pwm_fan.h>
++#include <mach/ast_pwm_techo.h>
++#endif
++
++//#define MCLK 1
++
++struct ast_pwm_tacho_data {
++ struct device *hwmon_dev;
++ void __iomem *reg_base; /* virtual */
++ int irq;
++ struct ast_pwm_driver_data *ast_pwm_data;
++};
++
++struct ast_pwm_tacho_data *ast_pwm_tacho;
++
++static u8 ast_get_pwm_type(struct ast_pwm_tacho_data *ast_pwm_tacho, u8 pwm_ch);
++static u8 ast_get_pwm_en(struct ast_pwm_tacho_data *ast_pwm_tacho, u8 pwm_ch);
++static u8 ast_get_tacho_type_division(struct ast_pwm_tacho_data *ast_pwm_tacho, u8 pwm_type);
++static u16 ast_get_tacho_type_unit(struct ast_pwm_tacho_data *ast_pwm_tacho, u8 pwm_type);
++static u8 ast_get_pwm_clock_division_h(struct ast_pwm_tacho_data *ast_pwm_tacho, u8 pwm_type);
++static u8 ast_get_pwm_clock_division_l(struct ast_pwm_tacho_data *ast_pwm_tacho, u8 pwm_type);
++static u8 ast_get_pwm_clock_unit(struct ast_pwm_tacho_data *ast_pwm_tacho, u8 pwm_type);
++
++static inline void
++ast_pwm_tacho_write(struct ast_pwm_tacho_data *ast_pwm_tacho, u32 val, u32 reg)
++{
++// printk("write offset: %x, val: %x \n",reg,val);
++ writel(val, ast_pwm_tacho->reg_base+ reg);
++}
++
++static inline u32
++ast_pwm_tacho_read(struct ast_pwm_tacho_data *ast_pwm_tacho, u32 reg)
++{
++ u32 val = readl(ast_pwm_tacho->reg_base + reg);
++// printk("read offset: %x, val: %x \n",reg,val);
++ return val;
++}
++
++/////////////////////////////////////////
++/*
++//1. The PWM base clock = 24Mhz / (Clock_Division_H D[7:4] in PTCR04 * Clock_Division_L D[3:0] in PTCR04)
++//2. The frequency of PWM = The PWM base clock / (PWM period D[15:8] in PTCR04 + 1)
++//3. If you plan to output 25Khz PWM frequency and 10% step of duty cycle, we suggest to set 0x943 in PTCR04 register.
++// The PWM frequency = 24Mhz / (16 * 6 * (9 + 1)) = 25Khz
++// duty cycle settings in the PTCR08 register:
++// 0x1e786008 D[15:0] = 0x0900, duty = 90%
++// 0x1e786008 D[15:0] = 0x0902, duty = 70%
++// .
++// .
++// .
++// 0x1e786008 D[15:0] = 0x0908, duty = 10%
++// 0x1e786008 D[15:0] = 0x0909, duty = 100%
++// 0x1e786008 D[15:0] = 0x0000, duty = 100%
++ (falling) - (rising+1) /unit
++*/
++
++static void ast_pwm_taco_init(void)
++{
++ //Enable PWM TACH CLK **************************************************
++ // Set M/N/O out is 25Khz
++ //The PWM frequency = 24Mhz / (16 * 6 * (9 + 1)) = 25Khz
++ ast_pwm_tacho_write(ast_pwm_tacho, 0x09430943, AST_PTCR_CLK_CTRL);
++ ast_pwm_tacho_write(ast_pwm_tacho, 0x0943, AST_PTCR_CLK_EXT_CTRL);
++
++ //FULL SPEED at initialize 100% pwm A~H
++ ast_pwm_tacho_write(ast_pwm_tacho, 0x0, AST_PTCR_DUTY0_CTRL);
++ ast_pwm_tacho_write(ast_pwm_tacho, 0x0, AST_PTCR_DUTY1_CTRL);
++ ast_pwm_tacho_write(ast_pwm_tacho, 0x0, AST_PTCR_DUTY2_CTRL);
++ ast_pwm_tacho_write(ast_pwm_tacho, 0x0, AST_PTCR_DUTY3_CTRL);
++
++ //Set TACO M/N/O initial unit 0x1000, falling , divide 4 , Enable
++ ast_pwm_tacho_write(ast_pwm_tacho, 0x10000001, AST_PTCR_TYPEM_CTRL0);
++ ast_pwm_tacho_write(ast_pwm_tacho, 0x10000001, AST_PTCR_TYPEN_CTRL0);
++#ifdef PWM_TYPE_O
++ ast_pwm_tacho_write(ast_pwm_tacho, 0x10000001, AST_PTCR_TYPEO_CTRL0);
++#endif
++
++ // TACO measure period = 24000000 / 2 / 2 / 256 / 4096 / 1 (only enable 1 TACHO) = 5.72Hz, it means that software needs to
++ // wait at least 0.2 sec to get refreshed TACO value. If you will enable more TACO or require faster response, you have to
++ // control the clock divisor and the period to be smaller
++
++ //Full Range to do measure unit 0x1000
++ ast_pwm_tacho_write(ast_pwm_tacho, 0x10000000, AST_PTCR_TYPEM_CTRL1);
++ ast_pwm_tacho_write(ast_pwm_tacho, 0x10000000, AST_PTCR_TYPEN_CTRL1);
++#ifdef PWM_TYPE_O
++ ast_pwm_tacho_write(ast_pwm_tacho, 0x10000000, AST_PTCR_TYPEO_CTRL1);
++#endif
++
++ //TACO Source Selection, PWMA for fan0~15
++ ast_pwm_tacho_write(ast_pwm_tacho, 0x0, AST_PTCR_TACH_SOURCE);
++ ast_pwm_tacho_write(ast_pwm_tacho, 0x0, AST_PTCR_TACH_SOURCE_EXT);
++
++ //PWM A~D -> Disable , type M,
++ //Tacho 0~15 Disable
++ //CLK source 24Mhz
++#ifdef MCLK
++ ast_pwm_tacho_write(ast_pwm_tacho, AST_PTCR_CTRL_CLK_MCLK | AST_PTCR_CTRL_CLK_EN, AST_PTCR_CTRL);
++#else
++ ast_pwm_tacho_write(ast_pwm_tacho, AST_PTCR_CTRL_CLK_EN, AST_PTCR_CTRL);
++#endif
++
++}
++
++/*index 0 : clk_en , 1: clk_source*/
++static ssize_t
++ast_store_clk(struct device *dev, struct device_attribute *attr, const char *sysfsbuf, size_t count)
++{
++ u32 input_val;
++ struct sensor_device_attribute_2 *sensor_attr = to_sensor_dev_attr_2(attr);
++
++ input_val = simple_strtoul(sysfsbuf, NULL, 10);
++
++ if ((input_val > 1) || (input_val < 0))
++ return -EINVAL;
++
++ //sensor_attr->index : tacho#
++ //sensor_attr->nr : attr#
++ switch(sensor_attr->nr)
++ {
++ case 0: //clk_en
++ if(input_val)
++ ast_pwm_tacho_write(ast_pwm_tacho,
++ ast_pwm_tacho_read(ast_pwm_tacho, AST_PTCR_CTRL) | AST_PTCR_CTRL_CLK_EN,
++ AST_PTCR_CTRL);
++ else
++ ast_pwm_tacho_write(ast_pwm_tacho,
++ ast_pwm_tacho_read(ast_pwm_tacho, AST_PTCR_CTRL) & ~AST_PTCR_CTRL_CLK_EN,
++ AST_PTCR_CTRL);
++ break;
++ case 1: //clk_source
++ if(input_val) {
++ ast_pwm_tacho_write(ast_pwm_tacho,
++ ast_pwm_tacho_read(ast_pwm_tacho, AST_PTCR_CTRL) | AST_PTCR_CTRL_CLK_MCLK,
++ AST_PTCR_CTRL);
++ } else {
++ ast_pwm_tacho_write(ast_pwm_tacho,
++ ast_pwm_tacho_read(ast_pwm_tacho, AST_PTCR_CTRL) & ~AST_PTCR_CTRL_CLK_MCLK,
++ AST_PTCR_CTRL);
++ }
++ break;
++ default:
++ return -EINVAL;
++ break;
++ }
++
++ return count;
++
++}
++
++
++static ssize_t
++ast_show_clk(struct device *dev, struct device_attribute *attr, char *sysfsbuf)
++{
++ struct sensor_device_attribute_2 *sensor_attr = to_sensor_dev_attr_2(attr);
++
++ //sensor_attr->index : fan#
++ //sensor_attr->nr : attr#
++ switch(sensor_attr->nr)
++ {
++ case 0: //clk_en
++ if(AST_PTCR_CTRL_CLK_EN & ast_pwm_tacho_read(ast_pwm_tacho, AST_PTCR_CTRL))
++ return sprintf(sysfsbuf, "1: Enable\n");
++ else
++ return sprintf(sysfsbuf, "0: Disable\n");
++ break;
++ case 1: //clk_source
++ if(AST_PTCR_CTRL_CLK_MCLK & ast_pwm_tacho_read(ast_pwm_tacho, AST_PTCR_CTRL))
++ return sprintf(sysfsbuf, "1: MCLK \n");
++ else
++ return sprintf(sysfsbuf, "0: 24Mhz\n");
++
++ break;
++ default:
++ return sprintf(sysfsbuf, "ERROR CLK Index\n");
++ break;
++ }
++}
++
++static u32
++ast_get_tacho_measure_period(struct ast_pwm_tacho_data *ast_pwm_tacho, u8 pwm_type)
++{
++ u32 clk,clk_unit,div_h,div_l,tacho_unit,tacho_div;
++ //TODO ... 266
++ if(AST_PTCR_CTRL_CLK_MCLK & ast_pwm_tacho_read(ast_pwm_tacho, AST_PTCR_CTRL)) {
++ //TODO .....
++ clk = ast_pwm_tacho->ast_pwm_data->get_pwm_clock();
++ } else
++ clk = 24*1000*1000;
++
++ clk_unit = ast_get_pwm_clock_unit(ast_pwm_tacho,pwm_type);
++ div_h = ast_get_pwm_clock_division_h(ast_pwm_tacho,pwm_type);
++ div_h = 0x1 << div_h;
++ div_l = ast_get_pwm_clock_division_l(ast_pwm_tacho,pwm_type);
++// div_l = (div_l) << 1;
++ if(div_l == 0)
++ div_l = 1;
++ else
++ div_l = div_l * 2;
++
++ tacho_unit = ast_get_tacho_type_unit(ast_pwm_tacho,pwm_type);
++ tacho_div = ast_get_tacho_type_division(ast_pwm_tacho,pwm_type);
++
++ tacho_div = 0x4 << (tacho_div*2);
++// printk("clk %d,clk_unit %d, div_h %d, div_l %d, tacho_unit %d, tacho_div %d\n",clk,clk_unit, div_h, div_l, tacho_unit, tacho_div);
++ return clk/(clk_unit*div_h*div_l*tacho_div*tacho_unit);
++}
++
++static u8
++ast_get_tacho_type_division(struct ast_pwm_tacho_data *ast_pwm_tacho, u8 pwm_type)
++{
++ u32 tmp = 0;
++ switch(pwm_type) {
++ case PWM_TYPE_M:
++ tmp = ast_pwm_tacho_read(ast_pwm_tacho, AST_PTCR_TYPEM_CTRL0);
++ break;
++ case PWM_TYPE_N:
++ tmp = ast_pwm_tacho_read(ast_pwm_tacho, AST_PTCR_TYPEN_CTRL0);
++ break;
++#ifdef PWM_TYPE_O
++ case PWM_TYPE_O:
++ tmp = ast_pwm_tacho_read(ast_pwm_tacho, AST_PTCR_TYPEO_CTRL0);
++ break;
++#endif
++ default:
++ printk("error type !! \n");
++ break;
++
++ }
++
++ return ((tmp & TYPE_CTRL0_CLK_DIVISION_MASK) >> TYPE_CTRL0_CLK_DIVISION);
++}
++
++static void
++ast_set_tacho_type_division(struct ast_pwm_tacho_data *ast_pwm_tacho, u8 pwm_type, u32 division)
++{
++ u32 tmp = 0;
++ if(division > 0x7)
++ return;
++
++ switch(pwm_type) {
++ case PWM_TYPE_M:
++ tmp = ast_pwm_tacho_read(ast_pwm_tacho, AST_PTCR_TYPEM_CTRL0);
++ break;
++ case PWM_TYPE_N:
++ tmp = ast_pwm_tacho_read(ast_pwm_tacho, AST_PTCR_TYPEN_CTRL0);
++ break;
++#ifdef PWM_TYPE_O
++ case PWM_TYPE_O:
++ tmp = ast_pwm_tacho_read(ast_pwm_tacho, AST_PTCR_TYPEO_CTRL0);
++ break;
++#endif
++ default:
++ printk("ERROR type !! \n");
++ break;
++ }
++
++ tmp &= ~TYPE_CTRL0_CLK_DIVISION_MASK;
++ tmp |= (division << TYPE_CTRL0_CLK_DIVISION);
++
++ switch(pwm_type) {
++ case PWM_TYPE_M:
++ ast_pwm_tacho_write(ast_pwm_tacho, tmp, AST_PTCR_TYPEM_CTRL0);
++ break;
++ case PWM_TYPE_N:
++ ast_pwm_tacho_write(ast_pwm_tacho, tmp, AST_PTCR_TYPEN_CTRL0);
++ break;
++#ifdef PWM_TYPE_O
++ case PWM_TYPE_O:
++ ast_pwm_tacho_write(ast_pwm_tacho, tmp, AST_PTCR_TYPEO_CTRL0);
++ break;
++#endif
++ default:
++ printk("ERROR type !! \n");
++ break;
++ }
++
++}
++
++static u16
++ast_get_tacho_type_unit(struct ast_pwm_tacho_data *ast_pwm_tacho, u8 pwm_type)
++{
++ u32 tmp = 0;
++
++ switch(pwm_type) {
++ case PWM_TYPE_M:
++ tmp = ast_pwm_tacho_read(ast_pwm_tacho, AST_PTCR_TYPEM_CTRL0);
++ break;
++ case PWM_TYPE_N:
++ tmp = ast_pwm_tacho_read(ast_pwm_tacho, AST_PTCR_TYPEN_CTRL0);
++ break;
++#ifdef PWM_TYPE_O
++ case PWM_TYPE_O:
++ tmp = ast_pwm_tacho_read(ast_pwm_tacho, AST_PTCR_TYPEO_CTRL0);
++ break;
++#endif
++ default:
++ printk("ERROR type !! \n");
++ break;
++ }
++
++ return ((tmp & TYPE_CTRL0_FAN_PERIOD_MASK) >> TYPE_CTRL0_FAN_PERIOD);
++}
++
++static void
++ast_set_tacho_type_unit(struct ast_pwm_tacho_data *ast_pwm_tacho, u8 pwm_type,u32 unit)
++{
++ u32 tmp = 0;
++
++ if(unit > 0xffff)
++ return;
++
++ switch(pwm_type) {
++ case PWM_TYPE_M:
++ tmp = ast_pwm_tacho_read(ast_pwm_tacho, AST_PTCR_TYPEM_CTRL0);
++ break;
++ case PWM_TYPE_N:
++ tmp = ast_pwm_tacho_read(ast_pwm_tacho, AST_PTCR_TYPEN_CTRL0);
++ break;
++#ifdef PWM_TYPE_O
++ case PWM_TYPE_O:
++ tmp = ast_pwm_tacho_read(ast_pwm_tacho, AST_PTCR_TYPEO_CTRL0);
++ break;
++#endif
++ default:
++ printk("ERROR type !! \n");
++ break;
++ }
++
++ tmp &= ~TYPE_CTRL0_FAN_PERIOD_MASK;
++ tmp |= (unit << TYPE_CTRL0_FAN_PERIOD);
++
++ switch(pwm_type) {
++ case PWM_TYPE_M:
++ ast_pwm_tacho_write(ast_pwm_tacho, tmp, AST_PTCR_TYPEM_CTRL0);
++ break;
++ case PWM_TYPE_N:
++ ast_pwm_tacho_write(ast_pwm_tacho, tmp, AST_PTCR_TYPEN_CTRL0);
++ break;
++#ifdef PWM_TYPE_O
++ case PWM_TYPE_O:
++ ast_pwm_tacho_write(ast_pwm_tacho, tmp, AST_PTCR_TYPEO_CTRL0);
++ break;
++#endif
++ default:
++ printk("ERROR type !! \n");
++ break;
++ }
++
++}
++
++static u32
++ast_get_tacho_type_mode(struct ast_pwm_tacho_data *ast_pwm_tacho, u8 pwm_type)
++{
++ u32 tmp = 0;
++
++ switch(pwm_type) {
++ case PWM_TYPE_M:
++ tmp = ast_pwm_tacho_read(ast_pwm_tacho, AST_PTCR_TYPEM_CTRL0);
++ break;
++ case PWM_TYPE_N:
++ tmp = ast_pwm_tacho_read(ast_pwm_tacho, AST_PTCR_TYPEN_CTRL0);
++ break;
++#ifdef PWM_TYPE_O
++ case PWM_TYPE_O:
++ tmp = ast_pwm_tacho_read(ast_pwm_tacho, AST_PTCR_TYPEO_CTRL0);
++ break;
++#endif
++ default:
++ printk("ERROR type !! \n");
++ break;
++ }
++
++ return ((tmp & TYPE_CTRL0_FAN_MODE_MASK) >> TYPE_CTRL0_FAN_MODE);
++}
++
++static void
++ast_set_tacho_type_mode(struct ast_pwm_tacho_data *ast_pwm_tacho, u8 pwm_type,u32 mode)
++{
++ u32 tmp = 0;
++ if(mode > 0x2)
++ return;
++
++ switch(pwm_type) {
++ case PWM_TYPE_M:
++ tmp = ast_pwm_tacho_read(ast_pwm_tacho, AST_PTCR_TYPEM_CTRL0);
++ break;
++ case PWM_TYPE_N:
++ tmp = ast_pwm_tacho_read(ast_pwm_tacho, AST_PTCR_TYPEN_CTRL0);
++ break;
++#ifdef PWM_TYPE_O
++ case PWM_TYPE_O:
++ tmp = ast_pwm_tacho_read(ast_pwm_tacho, AST_PTCR_TYPEO_CTRL0);
++ break;
++#endif
++ default:
++ printk("ERROR type !! \n");
++ break;
++ }
++
++ tmp &= ~TYPE_CTRL0_FAN_MODE_MASK;
++ tmp |= (mode << TYPE_CTRL0_FAN_MODE);
++
++ switch(pwm_type) {
++ case PWM_TYPE_M:
++ ast_pwm_tacho_write(ast_pwm_tacho, tmp, AST_PTCR_TYPEM_CTRL0);
++ break;
++ case PWM_TYPE_N:
++ ast_pwm_tacho_write(ast_pwm_tacho, tmp, AST_PTCR_TYPEN_CTRL0);
++ break;
++#ifdef PWM_TYPE_O
++ case PWM_TYPE_O:
++ ast_pwm_tacho_write(ast_pwm_tacho, tmp, AST_PTCR_TYPEO_CTRL0);
++ break;
++#endif
++ default:
++ printk("ERROR type !! \n");
++ break;
++ }
++
++}
++
++static u8
++ast_get_tacho_type_en(struct ast_pwm_tacho_data *ast_pwm_tacho, u8 pwm_type)
++{
++ u8 tmp;
++ switch(pwm_type) {
++ case PWM_TYPE_M:
++ tmp = (TYPE_CTRL0_FAN_TYPE_EN & ast_pwm_tacho_read(ast_pwm_tacho, AST_PTCR_TYPEM_CTRL0));
++ break;
++ case PWM_TYPE_N:
++ tmp = (TYPE_CTRL0_FAN_TYPE_EN & ast_pwm_tacho_read(ast_pwm_tacho, AST_PTCR_TYPEN_CTRL0));
++ break;
++#ifdef PWM_TYPE_O
++ case PWM_TYPE_O:
++ tmp = (TYPE_CTRL0_FAN_TYPE_EN & ast_pwm_tacho_read(ast_pwm_tacho, AST_PTCR_TYPEO_CTRL0));
++ break;
++#endif
++ default:
++ printk("ERROR type !! \n");
++ break;
++ }
++
++ return tmp;
++}
++
++static void
++ast_set_tacho_type_en(struct ast_pwm_tacho_data *ast_pwm_tacho, u8 pwm_type,u32 enable)
++{
++ switch(pwm_type) {
++ case PWM_TYPE_M:
++ ast_pwm_tacho_write(ast_pwm_tacho,
++ ast_pwm_tacho_read(ast_pwm_tacho, AST_PTCR_TYPEM_CTRL0) | enable,
++ AST_PTCR_TYPEM_CTRL0);
++
++ break;
++ case PWM_TYPE_N:
++ ast_pwm_tacho_write(ast_pwm_tacho,
++ ast_pwm_tacho_read(ast_pwm_tacho, AST_PTCR_TYPEN_CTRL0) | enable,
++ AST_PTCR_TYPEN_CTRL0);
++
++ break;
++#ifdef PWM_TYPE_O
++ case PWM_TYPE_O:
++ ast_pwm_tacho_write(ast_pwm_tacho,
++ ast_pwm_tacho_read(ast_pwm_tacho, AST_PTCR_TYPEO_CTRL0) | enable,
++ AST_PTCR_TYPEO_CTRL0);
++
++ break;
++#endif
++ default:
++ printk("ERROR type !! \n");
++ break;
++ }
++}
++
++static u32
++ast_get_tacho_type_limit(struct ast_pwm_tacho_data *ast_pwm_tacho, u8 pwm_type)
++{
++ switch(pwm_type) {
++ case PWM_TYPE_M:
++ return (FAN_LIMIT_MASK & ast_pwm_tacho_read(ast_pwm_tacho, AST_PTCR_TYPEM_LIMIT));
++ break;
++ case PWM_TYPE_N:
++ return (FAN_LIMIT_MASK & ast_pwm_tacho_read(ast_pwm_tacho, AST_PTCR_TYPEN_LIMIT));
++ break;
++#ifdef PWM_TYPE_O
++ case PWM_TYPE_O:
++ return (FAN_LIMIT_MASK & ast_pwm_tacho_read(ast_pwm_tacho, AST_PTCR_TYPEO_LIMIT));
++ break;
++#endif
++ default:
++ printk("ERROR type !! \n");
++ break;
++ }
++}
++
++static void
++ast_set_tacho_type_limit(struct ast_pwm_tacho_data *ast_pwm_tacho, u8 pwm_type,u32 limit)
++{
++ if(limit > FAN_LIMIT_MASK)
++ return;
++
++ switch(pwm_type) {
++ case PWM_TYPE_M:
++ ast_pwm_tacho_write(ast_pwm_tacho, limit, AST_PTCR_TYPEM_LIMIT);
++ break;
++ case PWM_TYPE_N:
++ ast_pwm_tacho_write(ast_pwm_tacho, limit, AST_PTCR_TYPEN_LIMIT);
++ break;
++#ifdef PWM_TYPE_O
++ case PWM_TYPE_O:
++ ast_pwm_tacho_write(ast_pwm_tacho, limit, AST_PTCR_TYPEO_LIMIT);
++ break;
++#endif
++ default:
++ printk("ERROR type !! \n");
++ break;
++ }
++
++}
++
++static u8
++ast_get_tacho_alarm_en(struct ast_pwm_tacho_data *ast_pwm_tacho, u8 tacho_ch)
++{
++ //tacho source
++ if( ast_pwm_tacho_read(ast_pwm_tacho, AST_PTCR_INTR_CTRL) & INTR_CTRL_EN_NUM(tacho_ch))
++ return 1;
++ else
++ return 0;
++}
++
++static void
++ast_set_tacho_alarm_en(struct ast_pwm_tacho_data *ast_pwm_tacho, u8 tacho_ch, u8 enable)
++{
++ //tacho source
++ if(enable == 1)
++ ast_pwm_tacho_write(ast_pwm_tacho,
++ ast_pwm_tacho_read(ast_pwm_tacho, AST_PTCR_INTR_CTRL) | INTR_CTRL_EN_NUM(tacho_ch),
++ AST_PTCR_INTR_CTRL);
++ else
++ ast_pwm_tacho_write(ast_pwm_tacho,
++ ast_pwm_tacho_read(ast_pwm_tacho, AST_PTCR_INTR_CTRL) & ~(INTR_CTRL_EN_NUM(tacho_ch)),
++ AST_PTCR_INTR_CTRL);
++}
++
++static u8
++ast_get_tacho_alarm(struct ast_pwm_tacho_data *ast_pwm_tacho, u8 tacho_ch)
++{
++ //tacho source
++ if(ast_pwm_tacho_read(ast_pwm_tacho, AST_PTCR_INTR_STS) & INTR_CTRL_NUM(tacho_ch))
++ return 1;
++ else
++ return 0;
++}
++
++static u8
++ast_get_tacho_en(struct ast_pwm_tacho_data *ast_pwm_tacho, u8 tacho_ch)
++{
++ if(ast_pwm_tacho_read(ast_pwm_tacho, AST_PTCR_CTRL) & AST_PTCR_CTRL_FAN_NUM_EN(tacho_ch))
++ return 1;
++ else
++ return 0;
++}
++
++static void
++ast_set_tacho_en(struct ast_pwm_tacho_data *ast_pwm_tacho, u8 tacho_ch, u8 enable)
++{
++ //tacho number enable
++ if(enable)
++ ast_pwm_tacho_write(ast_pwm_tacho,
++ ast_pwm_tacho_read(ast_pwm_tacho, AST_PTCR_CTRL) | AST_PTCR_CTRL_FAN_NUM_EN(tacho_ch),
++ AST_PTCR_CTRL);
++ else
++ ast_pwm_tacho_write(ast_pwm_tacho,
++ ast_pwm_tacho_read(ast_pwm_tacho, AST_PTCR_CTRL) & ~(AST_PTCR_CTRL_FAN_NUM_EN(tacho_ch)),
++ AST_PTCR_CTRL);
++}
++
++static u8
++ast_get_tacho_source(struct ast_pwm_tacho_data *ast_pwm_tacho, u8 tacho_ch)
++{
++ u32 tmp1, tmp2;
++
++ //tacho source
++ tmp1 = ast_pwm_tacho_read(ast_pwm_tacho, AST_PTCR_TACH_SOURCE);
++ tmp1 &= TACH_PWM_SOURCE_MASK_BIT01(tacho_ch);
++ tmp1 = tmp1 >> (TACH_PWM_SOURCE_BIT01(tacho_ch));
++
++ tmp2 = ast_pwm_tacho_read(ast_pwm_tacho, AST_PTCR_TACH_SOURCE_EXT);
++ tmp2 &= TACH_PWM_SOURCE_MASK_BIT2(tacho_ch);
++ tmp2 = tmp2 >> (TACH_PWM_SOURCE_BIT2(tacho_ch));
++ tmp2 = tmp2 << 2;
++
++ return (tmp2 | tmp1);
++}
++
++static void
++ast_set_tacho_source(struct ast_pwm_tacho_data *ast_pwm_tacho, u8 tacho_ch, u8 tacho_source)
++{
++ u32 tmp1, tmp2;
++ if(tacho_source > 7)
++ return;
++
++ //tacho source
++ tmp1 = ast_pwm_tacho_read(ast_pwm_tacho, AST_PTCR_TACH_SOURCE);
++ tmp1 &= ~(TACH_PWM_SOURCE_MASK_BIT01(tacho_ch));
++ tmp1 |= ((tacho_source &0x3) << (TACH_PWM_SOURCE_BIT01(tacho_ch)));
++
++ tmp2 = ast_pwm_tacho_read(ast_pwm_tacho, AST_PTCR_TACH_SOURCE_EXT);
++ tmp2 &= ~(TACH_PWM_SOURCE_MASK_BIT2(tacho_ch));
++ tmp2 |= (((tacho_source &0x4)>>2) << (TACH_PWM_SOURCE_BIT2(tacho_ch)));
++
++ ast_pwm_tacho_write(ast_pwm_tacho, tmp1, AST_PTCR_TACH_SOURCE);
++ ast_pwm_tacho_write(ast_pwm_tacho, tmp2, AST_PTCR_TACH_SOURCE_EXT);
++
++}
++
++static u32
++ast_get_tacho_rpm(struct ast_pwm_tacho_data *ast_pwm_tacho, u8 tacho_ch)
++{
++ u32 raw_data, rpm, tacho_clk_div, clk_source, timeout=0;
++ u8 tacho_source, pwm_type,tacho_type_en;
++
++ if(!(ast_get_tacho_en(ast_pwm_tacho,tacho_ch)))
++ return 0;
++
++ //write 0
++ ast_pwm_tacho_write(ast_pwm_tacho, 0, AST_PTCR_TRIGGER);
++
++ //write 1
++ ast_pwm_tacho_write(ast_pwm_tacho, 0x1 << tacho_ch, AST_PTCR_TRIGGER);
++
++ tacho_source = ast_get_tacho_source(ast_pwm_tacho, tacho_ch);
++ pwm_type = ast_get_pwm_type(ast_pwm_tacho, tacho_source);
++ tacho_type_en = ast_get_tacho_type_en(ast_pwm_tacho, pwm_type);
++
++// printk("source: %d,type: %d,en: %d \n",tacho_source,pwm_type,tacho_type_en);
++
++ //check pwm_type and get clock division
++ if(!tacho_type_en)
++ return 0;
++
++ //Wait ready
++ while(!(ast_pwm_tacho_read(ast_pwm_tacho, AST_PTCR_RESULT) & (0x1 << RESULT_STATUS))) {
++ timeout++;
++ if(timeout > 25)
++ return 0;
++ };
++
++ raw_data = ast_pwm_tacho_read(ast_pwm_tacho, AST_PTCR_RESULT)& RESULT_VALUE_MASK;
++ tacho_clk_div = ast_get_tacho_type_division(ast_pwm_tacho, pwm_type);
++
++// printk("raw div = %d \n",tacho_clk_div);
++
++ tacho_clk_div = 0x4 << (tacho_clk_div*2);
++// printk("raw div = %d \n",tacho_clk_div);
++
++ //TODO 166
++ if(AST_PTCR_CTRL_CLK_MCLK & ast_pwm_tacho_read(ast_pwm_tacho, AST_PTCR_CTRL))
++ clk_source = 166*1000*1000;
++ else
++ clk_source = 24*1000*1000;
++
++ printk("raw_data %d, clk_source %d, tacho_clk_div %d \n",raw_data, clk_source, tacho_clk_div);
++ rpm = (clk_source * 60) / (2 * raw_data * tacho_clk_div);
++
++ return rpm;
++}
++
++static u8
++ast_get_pwm_clock_division_h(struct ast_pwm_tacho_data *ast_pwm_tacho, u8 pwm_type)
++{
++ u8 tmp=0;
++
++ switch (pwm_type) {
++ case PWM_TYPE_M:
++ tmp = (ast_pwm_tacho_read(ast_pwm_tacho, AST_PTCR_CLK_CTRL) & AST_PTCR_CLK_CTRL_TYPEM_H_MASK) >> AST_PTCR_CLK_CTRL_TYPEM_H;
++ break;
++ case PWM_TYPE_N:
++ tmp = (ast_pwm_tacho_read(ast_pwm_tacho, AST_PTCR_CLK_CTRL) & AST_PTCR_CLK_CTRL_TYPEN_H_MASK) >> AST_PTCR_CLK_CTRL_TYPEN_H;
++ break;
++#ifdef PWM_TYPE_O
++ case PWM_TYPE_O:
++ tmp = (ast_pwm_tacho_read(ast_pwm_tacho, AST_PTCR_CLK_EXT_CTRL) & AST_PTCR_CLK_CTRL_TYPEO_H_MASK) >> AST_PTCR_CLK_CTRL_TYPEO_H;
++ break;
++#endif
++ default:
++ printk("error channel ast_get_pwm_clock_division_h %d \n",pwm_type);
++ break;
++ }
++ return tmp;
++}
++
++static void
++ast_set_pwm_clock_division_h(struct ast_pwm_tacho_data *ast_pwm_tacho, u8 pwm_type, u8 div_high)
++{
++ if(div_high > 0xf)
++ return;
++ switch (pwm_type) {
++ case PWM_TYPE_M:
++ ast_pwm_tacho_write(ast_pwm_tacho,
++ (ast_pwm_tacho_read(ast_pwm_tacho, AST_PTCR_CLK_CTRL) & ~AST_PTCR_CLK_CTRL_TYPEM_H_MASK) | (div_high << AST_PTCR_CLK_CTRL_TYPEM_H),
++ AST_PTCR_CLK_CTRL);
++ break;
++ case PWM_TYPE_N:
++ ast_pwm_tacho_write(ast_pwm_tacho,
++ (ast_pwm_tacho_read(ast_pwm_tacho, AST_PTCR_CLK_CTRL) & ~AST_PTCR_CLK_CTRL_TYPEN_H_MASK) | (div_high << AST_PTCR_CLK_CTRL_TYPEN_H),
++ AST_PTCR_CLK_CTRL);
++ break;
++#ifdef PWM_TYPE_O
++ case PWM_TYPE_O:
++ ast_pwm_tacho_write(ast_pwm_tacho,
++ (ast_pwm_tacho_read(ast_pwm_tacho, AST_PTCR_CLK_EXT_CTRL) & ~AST_PTCR_CLK_CTRL_TYPEO_H_MASK) | (div_high << AST_PTCR_CLK_CTRL_TYPEO_H),
++ AST_PTCR_CLK_EXT_CTRL);
++ break;
++#endif
++ default:
++ printk("error channel ast_get_pwm_type %d \n",pwm_type);
++ break;
++ }
++
++}
++
++static u8
++ast_get_pwm_clock_division_l(struct ast_pwm_tacho_data *ast_pwm_tacho, u8 pwm_type)
++{
++ u8 tmp=0;
++
++ switch (pwm_type) {
++ case PWM_TYPE_M:
++ tmp = (ast_pwm_tacho_read(ast_pwm_tacho, AST_PTCR_CLK_CTRL) & AST_PTCR_CLK_CTRL_TYPEM_L_MASK) >> AST_PTCR_CLK_CTRL_TYPEM_L;
++ break;
++ case PWM_TYPE_N:
++ tmp = (ast_pwm_tacho_read(ast_pwm_tacho, AST_PTCR_CLK_CTRL) & AST_PTCR_CLK_CTRL_TYPEN_L_MASK) >> AST_PTCR_CLK_CTRL_TYPEN_L;
++ break;
++#ifdef PWM_TYPE_O
++ case PWM_TYPE_O:
++ tmp = (ast_pwm_tacho_read(ast_pwm_tacho, AST_PTCR_CLK_EXT_CTRL) & AST_PTCR_CLK_CTRL_TYPEO_L_MASK) >> AST_PTCR_CLK_CTRL_TYPEO_L;
++ break;
++#endif
++ default:
++ printk("error channel ast_get_pwm_clock_division_l %d \n",pwm_type);
++ break;
++ }
++ return tmp;
++}
++
++static void
++ast_set_pwm_clock_division_l(struct ast_pwm_tacho_data *ast_pwm_tacho, u8 pwm_type, u8 div_low)
++{
++ if(div_low> 0xf)
++ return;
++ switch (pwm_type) {
++ case PWM_TYPE_M:
++ ast_pwm_tacho_write(ast_pwm_tacho,
++ (ast_pwm_tacho_read(ast_pwm_tacho, AST_PTCR_CLK_CTRL) & ~AST_PTCR_CLK_CTRL_TYPEM_L_MASK) | (div_low << AST_PTCR_CLK_CTRL_TYPEM_L),
++ AST_PTCR_CLK_CTRL);
++ break;
++ case PWM_TYPE_N:
++ ast_pwm_tacho_write(ast_pwm_tacho,
++ (ast_pwm_tacho_read(ast_pwm_tacho, AST_PTCR_CLK_CTRL) & ~AST_PTCR_CLK_CTRL_TYPEN_L_MASK) | (div_low << AST_PTCR_CLK_CTRL_TYPEN_L),
++ AST_PTCR_CLK_CTRL);
++ break;
++#ifdef PWM_TYPE_O
++ case PWM_TYPE_O:
++ ast_pwm_tacho_write(ast_pwm_tacho,
++ (ast_pwm_tacho_read(ast_pwm_tacho, AST_PTCR_CLK_EXT_CTRL) & ~AST_PTCR_CLK_CTRL_TYPEO_L_MASK) | (div_low << AST_PTCR_CLK_CTRL_TYPEO_L),
++ AST_PTCR_CLK_EXT_CTRL);
++ break;
++#endif
++ default:
++ printk("error channel ast_get_pwm_type %d \n",pwm_type);
++ break;
++ }
++}
++
++static u8
++ast_get_pwm_clock_unit(struct ast_pwm_tacho_data *ast_pwm_tacho, u8 pwm_type)
++{
++ u8 tmp=0;
++
++ switch (pwm_type) {
++ case PWM_TYPE_M:
++ tmp = (ast_pwm_tacho_read(ast_pwm_tacho, AST_PTCR_CLK_CTRL) & AST_PTCR_CLK_CTRL_TYPEM_UNIT_MASK) >> AST_PTCR_CLK_CTRL_TYPEM_UNIT;
++ break;
++ case PWM_TYPE_N:
++ tmp = (ast_pwm_tacho_read(ast_pwm_tacho, AST_PTCR_CLK_CTRL) & AST_PTCR_CLK_CTRL_TYPEN_UNIT_MASK) >> AST_PTCR_CLK_CTRL_TYPEN_UNIT;
++ break;
++#ifdef PWM_TYPE_O
++ case PWM_TYPE_O:
++ tmp = (ast_pwm_tacho_read(ast_pwm_tacho, AST_PTCR_CLK_EXT_CTRL) & AST_PTCR_CLK_CTRL_TYPEO_UNIT_MASK) >> AST_PTCR_CLK_CTRL_TYPEO_UNIT;
++ break;
++#endif
++ default:
++ printk("error channel ast_get_pwm_clock_unit %d \n",pwm_type);
++ break;
++ }
++ return tmp;
++}
++
++static void
++ast_set_pwm_clock_unit(struct ast_pwm_tacho_data *ast_pwm_tacho, u8 pwm_type, u8 unit)
++{
++ if(unit > 0xff)
++ return;
++ switch (pwm_type) {
++ case PWM_TYPE_M:
++ ast_pwm_tacho_write(ast_pwm_tacho,
++ (ast_pwm_tacho_read(ast_pwm_tacho, AST_PTCR_CLK_CTRL) & ~AST_PTCR_CLK_CTRL_TYPEM_UNIT_MASK) | (unit << AST_PTCR_CLK_CTRL_TYPEM_UNIT),
++ AST_PTCR_CLK_CTRL);
++ break;
++ case PWM_TYPE_N:
++ ast_pwm_tacho_write(ast_pwm_tacho,
++ (ast_pwm_tacho_read(ast_pwm_tacho, AST_PTCR_CLK_CTRL) & ~AST_PTCR_CLK_CTRL_TYPEN_UNIT_MASK) | (unit << AST_PTCR_CLK_CTRL_TYPEN_UNIT),
++ AST_PTCR_CLK_CTRL);
++ break;
++#ifdef PWM_TYPE_O
++ case PWM_TYPE_O:
++ ast_pwm_tacho_write(ast_pwm_tacho,
++ (ast_pwm_tacho_read(ast_pwm_tacho, AST_PTCR_CLK_EXT_CTRL) & ~AST_PTCR_CLK_CTRL_TYPEO_UNIT_MASK) | (unit << AST_PTCR_CLK_CTRL_TYPEO_UNIT),
++ AST_PTCR_CLK_EXT_CTRL);
++ break;
++#endif
++ default:
++ printk("error channel ast_get_pwm_type %d \n",pwm_type);
++ break;
++ }
++}
++
++static u32
++ast_get_pwm_clock(struct ast_pwm_tacho_data *ast_pwm_tacho, u8 pwm_type)
++{
++ u32 unit, div_low, div_high, clk_source;
++
++ unit = ast_get_pwm_clock_unit(ast_pwm_tacho,pwm_type);
++
++ div_high = ast_get_pwm_clock_division_h(ast_pwm_tacho,pwm_type);
++ div_high = (0x1<<div_high);
++
++ div_low = ast_get_pwm_clock_division_l(ast_pwm_tacho,pwm_type);
++ if(div_low == 0)
++ div_low = 1;
++ else
++ div_low = div_low*2;
++ //TODO 266
++
++ if(AST_PTCR_CTRL_CLK_MCLK & ast_pwm_tacho_read(ast_pwm_tacho, AST_PTCR_CTRL))
++ clk_source = ast_pwm_tacho->ast_pwm_data->get_pwm_clock();
++ else
++ clk_source = 24*1000*1000;
++
++// printk("%d, %d, %d, %d \n",clk_source,div_high,div_low,unit);
++ return (clk_source/(div_high*div_low*(unit+1)));
++}
++
++static u8
++ast_get_pwm_en(struct ast_pwm_tacho_data *ast_pwm_tacho, u8 pwm_ch)
++{
++ u8 tmp=0;
++
++ switch (pwm_ch) {
++ case PWMA:
++ tmp = (ast_pwm_tacho_read(ast_pwm_tacho, AST_PTCR_CTRL) & AST_PTCR_CTRL_PMWA_EN) >> AST_PTCR_CTRL_PMWA;
++ break;
++ case PWMB:
++ tmp = (ast_pwm_tacho_read(ast_pwm_tacho, AST_PTCR_CTRL) & AST_PTCR_CTRL_PMWB_EN) >> AST_PTCR_CTRL_PMWB;
++ break;
++ case PWMC:
++ tmp = (ast_pwm_tacho_read(ast_pwm_tacho, AST_PTCR_CTRL) & AST_PTCR_CTRL_PMWC_EN) >> AST_PTCR_CTRL_PMWC;
++ break;
++ case PWMD:
++ tmp = (ast_pwm_tacho_read(ast_pwm_tacho, AST_PTCR_CTRL) & AST_PTCR_CTRL_PMWD_EN) >> AST_PTCR_CTRL_PMWD;
++ break;
++ case PWME:
++ tmp = (ast_pwm_tacho_read(ast_pwm_tacho, AST_PTCR_CTRL_EXT) & AST_PTCR_CTRL_PMWE_EN) >> AST_PTCR_CTRL_PMWE;
++ break;
++ case PWMF:
++ tmp = (ast_pwm_tacho_read(ast_pwm_tacho, AST_PTCR_CTRL_EXT) & AST_PTCR_CTRL_PMWF_EN) >> AST_PTCR_CTRL_PMWF;
++ break;
++ case PWMG:
++ tmp = (ast_pwm_tacho_read(ast_pwm_tacho, AST_PTCR_CTRL_EXT) & AST_PTCR_CTRL_PMWG_EN) >> AST_PTCR_CTRL_PMWG;
++ break;
++ case PWMH:
++ tmp = (ast_pwm_tacho_read(ast_pwm_tacho, AST_PTCR_CTRL_EXT) & AST_PTCR_CTRL_PMWH_EN) >> AST_PTCR_CTRL_PMWH;
++ break;
++ default:
++ printk("error channel ast_get_pwm_type %d \n",pwm_ch);
++ break;
++ }
++
++ return tmp;
++
++}
++
++static void
++ast_set_pwm_en(struct ast_pwm_tacho_data *ast_pwm_tacho, u8 pwm_ch, u8 enable)
++{
++ switch (pwm_ch) {
++ case PWMA:
++ if(enable)
++ ast_pwm_tacho_write(ast_pwm_tacho,
++ ast_pwm_tacho_read(ast_pwm_tacho, AST_PTCR_CTRL) | AST_PTCR_CTRL_PMWA_EN,
++ AST_PTCR_CTRL);
++ else
++ ast_pwm_tacho_write(ast_pwm_tacho,
++ ast_pwm_tacho_read(ast_pwm_tacho, AST_PTCR_CTRL) & ~AST_PTCR_CTRL_PMWA_EN,
++ AST_PTCR_CTRL);
++
++ break;
++ case PWMB:
++ if(enable)
++ ast_pwm_tacho_write(ast_pwm_tacho,
++ (ast_pwm_tacho_read(ast_pwm_tacho, AST_PTCR_CTRL) | AST_PTCR_CTRL_PMWB_EN),
++ AST_PTCR_CTRL);
++ else
++ ast_pwm_tacho_write(ast_pwm_tacho,
++ (ast_pwm_tacho_read(ast_pwm_tacho, AST_PTCR_CTRL) & ~AST_PTCR_CTRL_PMWB_EN),
++ AST_PTCR_CTRL);
++ break;
++ case PWMC:
++ if(enable)
++ ast_pwm_tacho_write(ast_pwm_tacho,
++ (ast_pwm_tacho_read(ast_pwm_tacho, AST_PTCR_CTRL) | AST_PTCR_CTRL_PMWC_EN),
++ AST_PTCR_CTRL);
++ else
++ ast_pwm_tacho_write(ast_pwm_tacho,
++ (ast_pwm_tacho_read(ast_pwm_tacho, AST_PTCR_CTRL) & ~AST_PTCR_CTRL_PMWC_EN),
++ AST_PTCR_CTRL);
++
++ break;
++ case PWMD:
++ if(enable)
++ ast_pwm_tacho_write(ast_pwm_tacho,
++ (ast_pwm_tacho_read(ast_pwm_tacho, AST_PTCR_CTRL) | AST_PTCR_CTRL_PMWD_EN),
++ AST_PTCR_CTRL);
++ else
++ ast_pwm_tacho_write(ast_pwm_tacho,
++ (ast_pwm_tacho_read(ast_pwm_tacho, AST_PTCR_CTRL) & ~AST_PTCR_CTRL_PMWD_EN),
++ AST_PTCR_CTRL);
++
++ break;
++ case PWME:
++ if(enable)
++ ast_pwm_tacho_write(ast_pwm_tacho,
++ (ast_pwm_tacho_read(ast_pwm_tacho, AST_PTCR_CTRL_EXT) | AST_PTCR_CTRL_PMWE_EN),
++ AST_PTCR_CTRL_EXT);
++ else
++ ast_pwm_tacho_write(ast_pwm_tacho,
++ (ast_pwm_tacho_read(ast_pwm_tacho, AST_PTCR_CTRL_EXT) & ~AST_PTCR_CTRL_PMWE_EN),
++ AST_PTCR_CTRL_EXT);
++
++ break;
++ case PWMF:
++ if(enable)
++ ast_pwm_tacho_write(ast_pwm_tacho,
++ (ast_pwm_tacho_read(ast_pwm_tacho, AST_PTCR_CTRL_EXT) | AST_PTCR_CTRL_PMWF_EN),
++ AST_PTCR_CTRL_EXT);
++ else
++ ast_pwm_tacho_write(ast_pwm_tacho,
++ (ast_pwm_tacho_read(ast_pwm_tacho, AST_PTCR_CTRL_EXT) & ~AST_PTCR_CTRL_PMWF_EN),
++ AST_PTCR_CTRL_EXT);
++
++ break;
++ case PWMG:
++ if(enable)
++ ast_pwm_tacho_write(ast_pwm_tacho,
++ (ast_pwm_tacho_read(ast_pwm_tacho, AST_PTCR_CTRL_EXT) | AST_PTCR_CTRL_PMWG_EN),
++ AST_PTCR_CTRL_EXT);
++ else
++ ast_pwm_tacho_write(ast_pwm_tacho,
++ (ast_pwm_tacho_read(ast_pwm_tacho, AST_PTCR_CTRL_EXT) & ~AST_PTCR_CTRL_PMWG_EN),
++ AST_PTCR_CTRL_EXT);
++
++ break;
++ case PWMH:
++ if(enable)
++ ast_pwm_tacho_write(ast_pwm_tacho,
++ (ast_pwm_tacho_read(ast_pwm_tacho, AST_PTCR_CTRL_EXT) | AST_PTCR_CTRL_PMWH_EN),
++ AST_PTCR_CTRL_EXT);
++ else
++ ast_pwm_tacho_write(ast_pwm_tacho,
++ (ast_pwm_tacho_read(ast_pwm_tacho, AST_PTCR_CTRL_EXT) & ~AST_PTCR_CTRL_PMWH_EN),
++ AST_PTCR_CTRL_EXT);
++
++ break;
++ default:
++ printk("error channel ast_get_pwm_type %d \n",pwm_ch);
++ break;
++ }
++}
++
++static u8
++ast_get_pwm_type(struct ast_pwm_tacho_data *ast_pwm_tacho, u8 pwm_ch)
++{
++ u8 tmp=0;
++
++ switch (pwm_ch) {
++ case PWMA:
++ tmp = AST_PTCR_CTRL_GET_PWMA_TYPE(ast_pwm_tacho_read(ast_pwm_tacho, AST_PTCR_CTRL));
++ break;
++ case PWMB:
++ tmp = AST_PTCR_CTRL_GET_PWMB_TYPE(ast_pwm_tacho_read(ast_pwm_tacho, AST_PTCR_CTRL));
++ break;
++ case PWMC:
++ tmp = AST_PTCR_CTRL_GET_PWMC_TYPE(ast_pwm_tacho_read(ast_pwm_tacho, AST_PTCR_CTRL));
++ break;
++ case PWMD:
++ tmp = AST_PTCR_CTRL_GET_PWMD_TYPE(ast_pwm_tacho_read(ast_pwm_tacho, AST_PTCR_CTRL));
++ break;
++ case PWME:
++ tmp = AST_PTCR_CTRL_GET_PWME_TYPE(ast_pwm_tacho_read(ast_pwm_tacho, AST_PTCR_CTRL_EXT));
++ break;
++ case PWMF:
++ tmp = AST_PTCR_CTRL_GET_PWMF_TYPE(ast_pwm_tacho_read(ast_pwm_tacho, AST_PTCR_CTRL_EXT));
++ break;
++ case PWMG:
++ tmp = AST_PTCR_CTRL_GET_PWMG_TYPE(ast_pwm_tacho_read(ast_pwm_tacho, AST_PTCR_CTRL_EXT));
++ break;
++ case PWMH:
++ tmp = AST_PTCR_CTRL_GET_PWMH_TYPE(ast_pwm_tacho_read(ast_pwm_tacho, AST_PTCR_CTRL_EXT));
++ break;
++ default:
++ printk("error channel ast_get_pwm_type %d \n",pwm_ch);
++ break;
++ }
++
++ return tmp;
++}
++
++static void
++ast_set_pwm_type(struct ast_pwm_tacho_data *ast_pwm_tacho, u8 pwm_ch, u8 type)
++{
++ u32 tmp1,tmp2;
++
++ if(type > 0x2)
++ return;
++
++ tmp1 = ast_pwm_tacho_read(ast_pwm_tacho, AST_PTCR_CTRL);
++ tmp2 = ast_pwm_tacho_read(ast_pwm_tacho, AST_PTCR_CTRL_EXT);
++
++ switch (pwm_ch) {
++ case PWMA:
++ tmp1 &= ~AST_PTCR_CTRL_SET_PWMA_TYPE_MASK;
++ tmp1 |= AST_PTCR_CTRL_SET_PWMA_TYPE(type);
++ ast_pwm_tacho_write(ast_pwm_tacho, tmp1, AST_PTCR_CTRL);
++ break;
++ case PWMB:
++ tmp1 &= ~AST_PTCR_CTRL_SET_PWMB_TYPE_MASK;
++ tmp1 |= AST_PTCR_CTRL_SET_PWMB_TYPE(type);
++ ast_pwm_tacho_write(ast_pwm_tacho, tmp1, AST_PTCR_CTRL);
++ break;
++ case PWMC:
++ tmp1 &= ~AST_PTCR_CTRL_SET_PWMC_TYPE_MASK;
++ tmp1 |= AST_PTCR_CTRL_SET_PWMC_TYPE(type);
++ ast_pwm_tacho_write(ast_pwm_tacho, tmp1, AST_PTCR_CTRL);
++ break;
++ case PWMD:
++ tmp1 &= ~AST_PTCR_CTRL_SET_PWMD_TYPE_MASK;
++ tmp1 |= AST_PTCR_CTRL_SET_PWMD_TYPE(type);
++ ast_pwm_tacho_write(ast_pwm_tacho, tmp1, AST_PTCR_CTRL);
++ break;
++ case PWME:
++ tmp2 &= ~AST_PTCR_CTRL_SET_PWME_TYPE_MASK;
++ tmp2 |= AST_PTCR_CTRL_SET_PWME_TYPE(type);
++ ast_pwm_tacho_write(ast_pwm_tacho, tmp2, AST_PTCR_CTRL_EXT);
++ break;
++ case PWMF:
++ tmp2 &= ~AST_PTCR_CTRL_SET_PWMF_TYPE_MASK;
++ tmp2 |= AST_PTCR_CTRL_SET_PWMF_TYPE(type);
++ ast_pwm_tacho_write(ast_pwm_tacho, tmp2, AST_PTCR_CTRL_EXT);
++ break;
++ case PWMG:
++ tmp2 &= ~AST_PTCR_CTRL_SET_PWMG_TYPE_MASK;
++ tmp2 |= AST_PTCR_CTRL_SET_PWMG_TYPE(type);
++ ast_pwm_tacho_write(ast_pwm_tacho, tmp2, AST_PTCR_CTRL_EXT);
++ break;
++ case PWMH:
++ tmp2 &= ~AST_PTCR_CTRL_SET_PWMH_TYPE_MASK;
++ tmp2 |= AST_PTCR_CTRL_SET_PWMH_TYPE(type);
++ ast_pwm_tacho_write(ast_pwm_tacho, tmp2, AST_PTCR_CTRL_EXT);
++ break;
++ default:
++ printk("error channel %d \n",pwm_ch);
++ break;
++ }
++}
++
++// PWM DUTY
++static u8
++ast_get_pwm_duty_rising(struct ast_pwm_tacho_data *ast_pwm_tacho, u8 pwm_ch)
++{
++ u32 tmp=0;
++ switch (pwm_ch) {
++ case PWMA:
++ tmp = ast_pwm_tacho_read(ast_pwm_tacho, AST_PTCR_DUTY0_CTRL);
++ tmp &= DUTY_CTRL0_PWMA_RISE_POINT_MASK;
++ break;
++ case PWMB:
++ tmp = ast_pwm_tacho_read(ast_pwm_tacho, AST_PTCR_DUTY0_CTRL);
++ tmp &= DUTY_CTRL0_PWMB_RISE_POINT_MASK;
++ tmp = (tmp >> DUTY_CTRL0_PWMB_RISE_POINT);
++ break;
++ case PWMC:
++ tmp = ast_pwm_tacho_read(ast_pwm_tacho, AST_PTCR_DUTY1_CTRL);
++ tmp &= DUTY_CTRL1_PWMC_RISE_POINT_MASK;
++ break;
++ case PWMD:
++ tmp = ast_pwm_tacho_read(ast_pwm_tacho, AST_PTCR_DUTY1_CTRL);
++ tmp &= DUTY_CTRL1_PWMD_RISE_POINT_MASK;
++ tmp = (tmp >> DUTY_CTRL1_PWMD_RISE_POINT);
++ break;
++ case PWME:
++ tmp = ast_pwm_tacho_read(ast_pwm_tacho, AST_PTCR_DUTY2_CTRL);
++ tmp &= DUTY_CTRL2_PWME_RISE_POINT_MASK;
++ break;
++ case PWMF:
++ tmp = ast_pwm_tacho_read(ast_pwm_tacho, AST_PTCR_DUTY2_CTRL);
++ tmp &= DUTY_CTRL2_PWMF_RISE_POINT_MASK;
++ tmp = (tmp >> DUTY_CTRL2_PWMF_RISE_POINT);
++ break;
++ case PWMG:
++ tmp = ast_pwm_tacho_read(ast_pwm_tacho, AST_PTCR_DUTY3_CTRL);
++ tmp &= DUTY_CTRL3_PWMG_RISE_POINT_MASK;
++ break;
++ case PWMH:
++ tmp = ast_pwm_tacho_read(ast_pwm_tacho, AST_PTCR_DUTY3_CTRL);
++ tmp &= DUTY_CTRL3_PWMH_RISE_POINT_MASK;
++ tmp = (tmp >> DUTY_CTRL3_PWMH_RISE_POINT);
++ break;
++ default:
++ printk("error pwm channel %d with duty R \n",pwm_ch);
++ break;
++ }
++
++ return tmp;
++}
++
++static void
++ast_set_pwm_duty_rising(struct ast_pwm_tacho_data *ast_pwm_tacho, u8 pwm_ch, u8 rising)
++{
++ u32 tmp=0;
++ u32 pwm_type = ast_get_pwm_type(ast_pwm_tacho,pwm_ch);
++
++ if((rising > 0xff) || (rising > ast_get_pwm_clock_unit(ast_pwm_tacho,pwm_type)))
++ return;
++
++ switch (pwm_ch) {
++ case PWMA:
++ tmp = ast_pwm_tacho_read(ast_pwm_tacho, AST_PTCR_DUTY0_CTRL);
++ tmp &= ~DUTY_CTRL0_PWMA_RISE_POINT_MASK;
++ tmp |= rising;
++ ast_pwm_tacho_write(ast_pwm_tacho, tmp, AST_PTCR_DUTY0_CTRL);
++ break;
++ case PWMB:
++ tmp = ast_pwm_tacho_read(ast_pwm_tacho, AST_PTCR_DUTY0_CTRL);
++ tmp &= ~DUTY_CTRL0_PWMB_RISE_POINT_MASK;
++ tmp |= (rising << DUTY_CTRL0_PWMB_RISE_POINT);
++ ast_pwm_tacho_write(ast_pwm_tacho, tmp, AST_PTCR_DUTY0_CTRL);
++ break;
++ case PWMC:
++ tmp = ast_pwm_tacho_read(ast_pwm_tacho, AST_PTCR_DUTY1_CTRL);
++ tmp &= ~DUTY_CTRL1_PWMC_RISE_POINT_MASK;
++ tmp |= rising;
++ ast_pwm_tacho_write(ast_pwm_tacho, tmp, AST_PTCR_DUTY1_CTRL);
++ break;
++ case PWMD:
++ tmp = ast_pwm_tacho_read(ast_pwm_tacho, AST_PTCR_DUTY1_CTRL);
++ tmp &= ~DUTY_CTRL1_PWMD_RISE_POINT_MASK;
++ tmp |= (rising << DUTY_CTRL1_PWMD_RISE_POINT);
++ ast_pwm_tacho_write(ast_pwm_tacho, tmp, AST_PTCR_DUTY1_CTRL);
++ break;
++ case PWME:
++ tmp = ast_pwm_tacho_read(ast_pwm_tacho, AST_PTCR_DUTY2_CTRL);
++ tmp &= ~DUTY_CTRL2_PWME_RISE_POINT_MASK;
++ tmp |= rising;
++ ast_pwm_tacho_write(ast_pwm_tacho, tmp, AST_PTCR_DUTY2_CTRL);
++ break;
++ case PWMF:
++ tmp = ast_pwm_tacho_read(ast_pwm_tacho, AST_PTCR_DUTY2_CTRL);
++ tmp &= ~DUTY_CTRL2_PWMF_RISE_POINT_MASK;
++ tmp |= (rising << DUTY_CTRL2_PWMF_RISE_POINT);
++ ast_pwm_tacho_write(ast_pwm_tacho, tmp, AST_PTCR_DUTY2_CTRL);
++ break;
++ case PWMG:
++ tmp = ast_pwm_tacho_read(ast_pwm_tacho, AST_PTCR_DUTY3_CTRL);
++ tmp &= ~DUTY_CTRL3_PWMG_RISE_POINT_MASK;
++ tmp |= rising;
++ ast_pwm_tacho_write(ast_pwm_tacho, tmp, AST_PTCR_DUTY3_CTRL);
++ break;
++ case PWMH:
++ tmp = ast_pwm_tacho_read(ast_pwm_tacho, AST_PTCR_DUTY3_CTRL);
++ tmp &= ~DUTY_CTRL3_PWMH_RISE_POINT_MASK;
++ tmp |= (rising << DUTY_CTRL3_PWMH_RISE_POINT);
++ ast_pwm_tacho_write(ast_pwm_tacho, tmp, AST_PTCR_DUTY3_CTRL);
++ break;
++
++ default:
++ printk("error pwm channel %d with duty \n",pwm_ch);
++ break;
++ }
++}
++
++static u8
++ast_get_pwm_duty_falling(struct ast_pwm_tacho_data *ast_pwm_tacho, u8 pwm_ch)
++{
++ u32 tmp=0;
++ switch (pwm_ch) {
++ case PWMA:
++ tmp = ast_pwm_tacho_read(ast_pwm_tacho, AST_PTCR_DUTY0_CTRL);
++ tmp &= DUTY_CTRL0_PWMA_FALL_POINT_MASK;
++ tmp = (tmp >> DUTY_CTRL0_PWMA_FALL_POINT);
++ break;
++ case PWMB:
++ tmp = ast_pwm_tacho_read(ast_pwm_tacho, AST_PTCR_DUTY0_CTRL);
++ tmp &= DUTY_CTRL0_PWMB_FALL_POINT_MASK;
++ tmp = (tmp >> DUTY_CTRL0_PWMB_FALL_POINT);
++ break;
++ case PWMC:
++ tmp = ast_pwm_tacho_read(ast_pwm_tacho, AST_PTCR_DUTY1_CTRL);
++ tmp &= DUTY_CTRL1_PWMC_FALL_POINT_MASK;
++ tmp = (tmp >> DUTY_CTRL1_PWMC_FALL_POINT);
++ break;
++ case PWMD:
++ tmp = ast_pwm_tacho_read(ast_pwm_tacho, AST_PTCR_DUTY1_CTRL);
++ tmp &= DUTY_CTRL1_PWMD_FALL_POINT_MASK;
++ tmp = (tmp >> DUTY_CTRL1_PWMD_FALL_POINT);
++ break;
++ case PWME:
++ tmp = ast_pwm_tacho_read(ast_pwm_tacho, AST_PTCR_DUTY2_CTRL);
++ tmp &= DUTY_CTRL2_PWME_FALL_POINT_MASK;
++ tmp = (tmp >> DUTY_CTRL2_PWME_FALL_POINT);
++ break;
++ case PWMF:
++ tmp = ast_pwm_tacho_read(ast_pwm_tacho, AST_PTCR_DUTY2_CTRL);
++ tmp &= DUTY_CTRL2_PWMF_FALL_POINT_MASK;
++ tmp = (tmp >> DUTY_CTRL2_PWMF_FALL_POINT);
++ break;
++ case PWMG:
++ tmp = ast_pwm_tacho_read(ast_pwm_tacho, AST_PTCR_DUTY3_CTRL);
++ tmp &= DUTY_CTRL3_PWMG_FALL_POINT_MASK;
++ tmp = (tmp >> DUTY_CTRL3_PWMG_FALL_POINT);
++ break;
++ case PWMH:
++ tmp = ast_pwm_tacho_read(ast_pwm_tacho, AST_PTCR_DUTY3_CTRL);
++ tmp &= DUTY_CTRL3_PWMH_FALL_POINT_MASK;
++ tmp = (tmp >> DUTY_CTRL3_PWMH_FALL_POINT);
++ break;
++
++ default:
++ printk("error pwm channel %d with duty F \n",pwm_ch);
++ break;
++ }
++
++ return tmp;
++}
++
++static void
++ast_set_pwm_duty_falling(struct ast_pwm_tacho_data *ast_pwm_tacho, u8 pwm_ch, u8 falling)
++{
++ u32 tmp =0;
++ u32 pwm_type = ast_get_pwm_type(ast_pwm_tacho,pwm_ch);
++
++ if((falling > 0xff) || (falling > ast_get_pwm_clock_unit(ast_pwm_tacho,pwm_type)))
++ return;
++
++ switch (pwm_ch) {
++ case PWMA:
++ tmp = ast_pwm_tacho_read(ast_pwm_tacho, AST_PTCR_DUTY0_CTRL);
++ tmp &= ~DUTY_CTRL0_PWMA_FALL_POINT_MASK;
++ tmp |= (falling << DUTY_CTRL0_PWMA_FALL_POINT);
++ ast_pwm_tacho_write(ast_pwm_tacho, tmp, AST_PTCR_DUTY0_CTRL);
++ break;
++ case PWMB:
++ tmp = ast_pwm_tacho_read(ast_pwm_tacho, AST_PTCR_DUTY0_CTRL);
++ tmp &= ~DUTY_CTRL0_PWMB_FALL_POINT_MASK;
++ tmp |= (falling << DUTY_CTRL0_PWMB_FALL_POINT);
++ ast_pwm_tacho_write(ast_pwm_tacho, tmp, AST_PTCR_DUTY0_CTRL);
++ break;
++ case PWMC:
++ tmp = ast_pwm_tacho_read(ast_pwm_tacho, AST_PTCR_DUTY1_CTRL);
++ tmp &= ~DUTY_CTRL1_PWMC_FALL_POINT_MASK;
++ tmp |= (falling << DUTY_CTRL1_PWMC_FALL_POINT);
++ ast_pwm_tacho_write(ast_pwm_tacho, tmp, AST_PTCR_DUTY1_CTRL);
++ break;
++ case PWMD:
++ tmp = ast_pwm_tacho_read(ast_pwm_tacho, AST_PTCR_DUTY1_CTRL);
++ tmp &= ~DUTY_CTRL1_PWMD_FALL_POINT_MASK;
++ tmp |= (falling << DUTY_CTRL1_PWMD_FALL_POINT);
++ ast_pwm_tacho_write(ast_pwm_tacho, tmp, AST_PTCR_DUTY1_CTRL);
++ break;
++ case PWME:
++ tmp = ast_pwm_tacho_read(ast_pwm_tacho, AST_PTCR_DUTY2_CTRL);
++ tmp &= ~DUTY_CTRL2_PWME_FALL_POINT_MASK;
++ tmp |= (falling << DUTY_CTRL2_PWME_FALL_POINT);
++ ast_pwm_tacho_write(ast_pwm_tacho, tmp, AST_PTCR_DUTY2_CTRL);
++ break;
++ case PWMF:
++ tmp = ast_pwm_tacho_read(ast_pwm_tacho, AST_PTCR_DUTY2_CTRL);
++ tmp &= ~DUTY_CTRL2_PWMF_FALL_POINT_MASK;
++ tmp |= (falling << DUTY_CTRL2_PWMF_FALL_POINT);
++ ast_pwm_tacho_write(ast_pwm_tacho, tmp, AST_PTCR_DUTY2_CTRL);
++ break;
++ case PWMG:
++ tmp = ast_pwm_tacho_read(ast_pwm_tacho, AST_PTCR_DUTY3_CTRL);
++ tmp &= ~DUTY_CTRL3_PWMG_FALL_POINT_MASK;
++ tmp |= (falling << DUTY_CTRL3_PWMG_FALL_POINT);
++ ast_pwm_tacho_write(ast_pwm_tacho, tmp, AST_PTCR_DUTY3_CTRL);
++ break;
++ case PWMH:
++ tmp = ast_pwm_tacho_read(ast_pwm_tacho, AST_PTCR_DUTY3_CTRL);
++ tmp &= ~DUTY_CTRL3_PWMH_FALL_POINT_MASK;
++ tmp |= (falling << DUTY_CTRL3_PWMH_FALL_POINT);
++ ast_pwm_tacho_write(ast_pwm_tacho, tmp, AST_PTCR_DUTY3_CTRL);
++ break;
++
++ default:
++ printk("error pwm channel %d with duty \n",pwm_ch);
++ break;
++ }
++
++}
++
++/*PWM M/N/O Type sysfs*/
++/*
++ * Macro defining SENSOR_DEVICE_ATTR for a pwm sysfs entries.
++ * 0 - show/store unit
++ * 1 - show/store division_l
++ * 2 - show/store division_h
++ */
++
++static ssize_t
++ast_show_pwm_type_clock(struct device *dev, struct device_attribute *attr, char *sysfsbuf)
++{
++ struct sensor_device_attribute_2 *sensor_attr =
++ to_sensor_dev_attr_2(attr);
++
++
++ //sensor_attr->index : M/N/O#
++ //sensor_attr->nr : attr#
++ switch(sensor_attr->nr)
++ {
++ case 0: //unit : 0~256
++ return sprintf(sysfsbuf, "%d (0~255)\n", ast_get_pwm_clock_unit(ast_pwm_tacho,sensor_attr->index));
++ break;
++ case 1: //division_l
++ return sprintf(sysfsbuf, "%d (0~15) \n", ast_get_pwm_clock_division_l(ast_pwm_tacho,sensor_attr->index));
++ break;
++ case 2: //division_h
++ return sprintf(sysfsbuf, "%d (0~15) \n", ast_get_pwm_clock_division_h(ast_pwm_tacho,sensor_attr->index));
++
++ break;
++ case 3: //expect clock
++
++ return sprintf(sysfsbuf, "%d \n", ast_get_pwm_clock(ast_pwm_tacho,sensor_attr->index));
++
++ break;
++
++ default:
++ return -EINVAL;
++ break;
++ }
++
++ return sprintf(sysfsbuf, "%d : %d\n", sensor_attr->nr,sensor_attr->index);
++
++
++}
++
++static ssize_t
++ast_store_pwm_type_clock(struct device *dev, struct device_attribute *attr, const char *sysfsbuf, size_t count)
++{
++ u32 input_val;
++ struct sensor_device_attribute_2 *sensor_attr =
++ to_sensor_dev_attr_2(attr);
++
++ input_val = simple_strtoul(sysfsbuf, NULL, 10);
++
++ switch(sensor_attr->nr)
++ {
++ case 0: //unit : 0~256
++ ast_set_pwm_clock_unit(ast_pwm_tacho, sensor_attr->index, input_val);
++ break;
++ case 1: //division_l
++ ast_set_pwm_clock_division_l(ast_pwm_tacho, sensor_attr->index, input_val);
++ break;
++ case 2: //division_h
++ ast_set_pwm_clock_division_h(ast_pwm_tacho, sensor_attr->index, input_val);
++ break;
++ default:
++ return -EINVAL;
++ break;
++ }
++
++ return count;
++}
++
++/* attr
++ * 0 - show/store enable
++ * 1 - show/store type
++ * 2 - show/store falling
++ * 3 - show/store rising */
++static ssize_t
++ast_show_pwm_speed(struct device *dev, struct device_attribute *attr, char *sysfsbuf)
++{
++ struct sensor_device_attribute_2 *sensor_attr = to_sensor_dev_attr_2(attr);
++
++ //sensor_attr->index : pwm_ch#
++ //sensor_attr->nr : attr#
++ switch(sensor_attr->nr)
++ {
++ case 0: //enable, disable
++ return sprintf(sysfsbuf, "%d : %s\n", ast_get_pwm_en(ast_pwm_tacho,sensor_attr->index),ast_get_pwm_en(ast_pwm_tacho,sensor_attr->index) ? "Enable":"Disable");
++ break;
++ case 1: //pwm type M/N/O
++ return sprintf(sysfsbuf, "%d (0:M/1:N/2:O)\n",ast_get_pwm_type(ast_pwm_tacho, sensor_attr->index));
++ break;
++ case 2: //rising
++ return sprintf(sysfsbuf, "%x : unit limit (0~%d)\n",ast_get_pwm_duty_rising(ast_pwm_tacho, sensor_attr->index),
++ ast_get_pwm_clock_unit(ast_pwm_tacho, ast_get_pwm_type(ast_pwm_tacho, sensor_attr->index)));
++ break;
++ case 3: //falling
++ return sprintf(sysfsbuf, "%x : unit limit (0~%d)\n",ast_get_pwm_duty_falling(ast_pwm_tacho, sensor_attr->index),
++ ast_get_pwm_clock_unit(ast_pwm_tacho, ast_get_pwm_type(ast_pwm_tacho, sensor_attr->index)));
++ break;
++ default:
++ return -EINVAL;
++ break;
++ }
++}
++
++static ssize_t
++ast_store_pwm_speed(struct device *dev, struct device_attribute *attr, const char *sysfsbuf, size_t count)
++{
++ u32 input_val;
++ struct sensor_device_attribute_2 *sensor_attr =
++ to_sensor_dev_attr_2(attr);
++
++ input_val = simple_strtoul(sysfsbuf, NULL, 10);
++
++ //sensor_attr->index : pwm_ch#
++ //sensor_attr->nr : attr#
++ switch(sensor_attr->nr)
++ {
++ case 0: //enable, disable
++ ast_set_pwm_en(ast_pwm_tacho, sensor_attr->index, input_val);
++ break;
++ case 1: //pwm type M/N/O
++ ast_set_pwm_type(ast_pwm_tacho, sensor_attr->index, input_val);
++ break;
++ case 2: //rising
++ ast_set_pwm_duty_rising(ast_pwm_tacho, sensor_attr->index, input_val);
++ break;
++ case 3: //falling
++ ast_set_pwm_duty_falling(ast_pwm_tacho, sensor_attr->index, input_val);
++ break;
++ default:
++ return -EINVAL;
++ break;
++ }
++
++ return count;
++}
++
++/* Fan Type */
++/* Fan M/N/O Type sysfs
++ * Macro defining SENSOR_DEVICE_ATTR for a pwm sysfs entries.
++ * 0 - show/store enable
++ * 1 - show/store mode
++ * 2 - show/store unit
++ * 3 - show/store division
++ * 4 - show/store limit
++ */
++
++static ssize_t
++ast_show_tacho_type(struct device *dev, struct device_attribute *attr, char *sysfsbuf)
++{
++ struct sensor_device_attribute_2 *sensor_attr =
++ to_sensor_dev_attr_2(attr);
++
++ //sensor_attr->index : M/N/O
++ //sensor_attr->nr : attr#
++ switch(sensor_attr->nr)
++ {
++ case 0: //enable, disable
++ return sprintf(sysfsbuf, "%d : %s\n", ast_get_tacho_type_en(ast_pwm_tacho,sensor_attr->index),ast_get_tacho_type_en(ast_pwm_tacho,sensor_attr->index) ? "Enable":"Disable");
++ break;
++ case 1: //fan tacho mode
++ if(ast_get_tacho_type_mode(ast_pwm_tacho, sensor_attr->index) == FALL_EDGE)
++ return sprintf(sysfsbuf, "0: falling\n");
++ else if(ast_get_tacho_type_mode(ast_pwm_tacho, sensor_attr->index) == RISE_EDGE)
++ return sprintf(sysfsbuf, "1: rising\n");
++ else if (ast_get_tacho_type_mode(ast_pwm_tacho, sensor_attr->index) == BOTH_EDGE)
++ return sprintf(sysfsbuf, "2: both\n");
++ else
++ return sprintf(sysfsbuf, "3: unknown\n");
++ break;
++ case 2: //unit
++ return sprintf(sysfsbuf, "%d (0~65535)\n",ast_get_tacho_type_unit(ast_pwm_tacho, sensor_attr->index));
++
++ break;
++ case 3: //division
++ return sprintf(sysfsbuf, "%d (0~7) \n",ast_get_tacho_type_division(ast_pwm_tacho, sensor_attr->index));
++ break;
++ case 4: //limit
++ return sprintf(sysfsbuf, "%d (0~1048575)\n",ast_get_tacho_type_limit(ast_pwm_tacho, sensor_attr->index));
++ break;
++ case 5: //measure period
++ return sprintf(sysfsbuf, "%d \n",ast_get_tacho_measure_period(ast_pwm_tacho, sensor_attr->index));
++ break;
++ default:
++ return -EINVAL;
++ break;
++ }
++}
++
++static ssize_t
++ast_store_tacho_type(struct device *dev, struct device_attribute *attr, const char *sysfsbuf, size_t count)
++{
++ u32 input_val;
++ struct sensor_device_attribute_2 *sensor_attr =
++ to_sensor_dev_attr_2(attr);
++
++ input_val = simple_strtoul(sysfsbuf, NULL, 10);
++
++ //sensor_attr->index : pwm_ch#
++ //sensor_attr->nr : attr#
++ switch(sensor_attr->nr)
++ {
++ case 0: //enable, disable
++ ast_set_tacho_type_en(ast_pwm_tacho,sensor_attr->index, input_val);
++ break;
++ case 1: //fan tacho mode
++ ast_set_tacho_type_mode(ast_pwm_tacho, sensor_attr->index, input_val);
++ break;
++ case 2: //unit
++ ast_set_tacho_type_unit(ast_pwm_tacho, sensor_attr->index, input_val);
++ break;
++ case 3: //division
++ ast_set_tacho_type_division(ast_pwm_tacho, sensor_attr->index, input_val);
++ break;
++ case 4: //limit
++ ast_set_tacho_type_limit(ast_pwm_tacho, sensor_attr->index, input_val);
++ break;
++ default:
++ return -EINVAL;
++ break;
++ }
++ return count;
++
++}
++
++/* fan detect */
++/* FAN sysfs
++ * Macro defining SENSOR_DEVICE_ATTR for a tacho sysfs entries.
++ * - show/store enable
++ * - show/store source
++ * - show/store rpm
++ * - show/store alarm
++ * - show/store alarm_en
++*/
++static ssize_t
++ast_show_tacho_speed(struct device *dev, struct device_attribute *attr, char *sysfsbuf)
++{
++ struct sensor_device_attribute_2 *sensor_attr =
++ to_sensor_dev_attr_2(attr);
++
++ //sensor_attr->index : pwm_ch#
++ //sensor_attr->nr : attr#
++ switch(sensor_attr->nr)
++ {
++ case 0: //enable, disable
++ return sprintf(sysfsbuf, "%d : %s\n", ast_get_tacho_en(ast_pwm_tacho,sensor_attr->index),ast_get_tacho_en(ast_pwm_tacho,sensor_attr->index) ? "Enable":"Disable");
++ break;
++ case 1: //tacho source PWMA~H - 0~7
++ return sprintf(sysfsbuf, "PWM%d (0~7)\n", ast_get_tacho_source(ast_pwm_tacho,sensor_attr->index));
++ break;
++ case 2: //rpm
++ return sprintf(sysfsbuf, "%d \n", ast_get_tacho_rpm(ast_pwm_tacho,sensor_attr->index));
++ break;
++ case 3: //alarm
++ return sprintf(sysfsbuf, "%d \n", ast_get_tacho_alarm(ast_pwm_tacho,sensor_attr->index));
++ break;
++ case 4: //alarm_en
++ return sprintf(sysfsbuf, "%d : %s\n",
++ ast_get_tacho_alarm_en(ast_pwm_tacho,sensor_attr->index),
++ ast_get_tacho_alarm_en(ast_pwm_tacho,sensor_attr->index) ? "Enable":"Disable");
++ break;
++ default:
++ return -EINVAL;
++ break;
++ }
++
++}
++
++static ssize_t
++ast_store_tacho_speed(struct device *dev, struct device_attribute *attr, const char *sysfsbuf, size_t count)
++{
++ u32 input_val;
++ struct sensor_device_attribute_2 *sensor_attr =
++ to_sensor_dev_attr_2(attr);
++
++ input_val = simple_strtoul(sysfsbuf, NULL, 10);
++
++
++ //sensor_attr->index : tacho_ch#
++ //sensor_attr->nr : attr#
++ switch(sensor_attr->nr)
++ {
++ case 0: //enable, disable
++ ast_set_tacho_en(ast_pwm_tacho,sensor_attr->index,input_val);
++ break;
++ case 1: //tacho source PWMA~H - 0~7
++ ast_set_tacho_source(ast_pwm_tacho,sensor_attr->index,input_val);
++ break;
++ case 2: //rpm
++ return -EINVAL;
++ break;
++ case 3: //alarm
++ return -EINVAL;
++ break;
++ case 4: //alarm_en
++ ast_set_tacho_alarm_en(ast_pwm_tacho,sensor_attr->index,input_val);
++ break;
++ default:
++ return -EINVAL;
++ break;
++ }
++ return count;
++}
++
++/*
++ * sysfs attributes
++ */
++/* CLK sysfs*/
++static SENSOR_DEVICE_ATTR_2(clk_en, S_IRUGO | S_IWUSR, ast_show_clk, ast_store_clk, 0, 0);
++static SENSOR_DEVICE_ATTR_2(clk_source, S_IRUGO | S_IWUSR, ast_show_clk, ast_store_clk, 1, 0);
++
++
++static struct attribute *clk_attributes[] = {
++ &sensor_dev_attr_clk_source.dev_attr.attr,
++ &sensor_dev_attr_clk_en.dev_attr.attr,
++ NULL
++};
++
++static const struct attribute_group clk_attribute_groups = {
++ .attrs = clk_attributes,
++};
++
++/*PWM M/N/O Type sysfs*/
++/*
++ * Macro defining SENSOR_DEVICE_ATTR for a pwm sysfs entries.
++ * 0 - show/store unit
++ * 1 - show/store division_l
++ * 2 - show/store division_h
++ */
++
++#define sysfs_pwm_type(type,index) \
++static SENSOR_DEVICE_ATTR_2(pwm_type_##type##_unit, S_IRUGO | S_IWUSR, \
++ ast_show_pwm_type_clock, ast_store_pwm_type_clock, 0, index); \
++\
++static SENSOR_DEVICE_ATTR_2(pwm_type_##type##_division_l, S_IRUGO | S_IWUSR, \
++ ast_show_pwm_type_clock, ast_store_pwm_type_clock, 1, index); \
++\
++static SENSOR_DEVICE_ATTR_2(pwm_type_##type##_division_h, S_IRUGO | S_IWUSR, \
++ ast_show_pwm_type_clock, ast_store_pwm_type_clock, 2, index); \
++\
++static SENSOR_DEVICE_ATTR_2(pwm_type_##type##_clk, S_IRUGO, \
++ ast_show_pwm_type_clock, NULL, 3, index); \
++\
++static struct attribute *pwm_type_##type##_attributes[] = { \
++ &sensor_dev_attr_pwm_type_##type##_unit.dev_attr.attr, \
++ &sensor_dev_attr_pwm_type_##type##_division_l.dev_attr.attr, \
++ &sensor_dev_attr_pwm_type_##type##_division_h.dev_attr.attr, \
++ &sensor_dev_attr_pwm_type_##type##_clk.dev_attr.attr, \
++ NULL \
++};
++
++/*
++ * Create the needed functions for each pwm using the macro defined above
++ * (4 pwms are supported)
++ */
++sysfs_pwm_type(m,0);
++sysfs_pwm_type(n,1);
++#ifdef PWM_TYPE_O
++sysfs_pwm_type(o,2);
++#endif
++
++static const struct attribute_group pwm_type_attribute_groups[] = {
++ { .attrs = pwm_type_m_attributes },
++ { .attrs = pwm_type_n_attributes },
++#ifdef PWM_TYPE_O
++ { .attrs = pwm_type_o_attributes },
++#endif
++};
++
++/* PWM sysfs
++ * Macro defining SENSOR_DEVICE_ATTR for a pwm sysfs entries.
++ * 0 - show/store enable
++ * 1 - show/store type
++ * 2 - show/store rising
++ * 3 - show/store falling
++ */
++
++#define sysfs_pwm_speeds_num(index) \
++static SENSOR_DEVICE_ATTR_2(pwm##index##_en, S_IRUGO | S_IWUSR, \
++ ast_show_pwm_speed, ast_store_pwm_speed, 0, index); \
++\
++static SENSOR_DEVICE_ATTR_2(pwm##index##_type, S_IRUGO | S_IWUSR, \
++ ast_show_pwm_speed, ast_store_pwm_speed, 1, index); \
++\
++static SENSOR_DEVICE_ATTR_2(pwm##index##_rising, S_IRUGO | S_IWUSR, \
++ ast_show_pwm_speed, ast_store_pwm_speed, 2, index); \
++\
++static SENSOR_DEVICE_ATTR_2(pwm##index##_falling, S_IRUGO | S_IWUSR, \
++ ast_show_pwm_speed, ast_store_pwm_speed, 3, index); \
++\
++static struct attribute *pwm##index##_attributes[] = { \
++ &sensor_dev_attr_pwm##index##_en.dev_attr.attr, \
++ &sensor_dev_attr_pwm##index##_type.dev_attr.attr, \
++ &sensor_dev_attr_pwm##index##_rising.dev_attr.attr, \
++ &sensor_dev_attr_pwm##index##_falling.dev_attr.attr, \
++ NULL \
++};
++
++/*
++ * Create the needed functions for each pwm using the macro defined above
++ * (4 pwms are supported)
++ */
++sysfs_pwm_speeds_num(0);
++sysfs_pwm_speeds_num(1);
++sysfs_pwm_speeds_num(2);
++sysfs_pwm_speeds_num(3);
++sysfs_pwm_speeds_num(4);
++sysfs_pwm_speeds_num(5);
++sysfs_pwm_speeds_num(6);
++sysfs_pwm_speeds_num(7);
++
++static const struct attribute_group pwm_attribute_groups[] = {
++ { .attrs = pwm0_attributes },
++ { .attrs = pwm1_attributes },
++ { .attrs = pwm2_attributes },
++ { .attrs = pwm3_attributes },
++ { .attrs = pwm4_attributes },
++ { .attrs = pwm5_attributes },
++ { .attrs = pwm6_attributes },
++ { .attrs = pwm7_attributes },
++};
++
++/* Fan M/N/O Type sysfs
++ * Macro defining SENSOR_DEVICE_ATTR for a pwm sysfs entries.
++ * 0 - show/store enable
++ * 1 - show/store mode
++ * 2 - show/store unit
++ * 3 - show/store division
++ * 4 - show/store limit
++ */
++
++#define sysfs_tacho_type(type,index) \
++static SENSOR_DEVICE_ATTR_2(tacho_type_##type##_en, S_IRUGO | S_IWUSR, \
++ ast_show_tacho_type, ast_store_tacho_type, 0, index); \
++\
++static SENSOR_DEVICE_ATTR_2(tacho_type_##type##_mode, S_IRUGO | S_IWUSR, \
++ ast_show_tacho_type, ast_store_tacho_type, 1, index); \
++\
++static SENSOR_DEVICE_ATTR_2(tacho_type_##type##_unit, S_IRUGO | S_IWUSR, \
++ ast_show_tacho_type, ast_store_tacho_type, 2, index); \
++\
++static SENSOR_DEVICE_ATTR_2(tacho_type_##type##_division, S_IRUGO | S_IWUSR, \
++ ast_show_tacho_type, ast_store_tacho_type, 3, index); \
++\
++static SENSOR_DEVICE_ATTR_2(tacho_type_##type##_limit, S_IRUGO | S_IWUSR, \
++ ast_show_tacho_type, ast_store_tacho_type, 4, index); \
++\
++static SENSOR_DEVICE_ATTR_2(tacho_type_##type##_measure_period, S_IRUGO | S_IWUSR, \
++ ast_show_tacho_type, ast_store_tacho_type, 5, index); \
++\
++static struct attribute *tacho_type_##type##_attributes[] = { \
++ &sensor_dev_attr_tacho_type_##type##_en.dev_attr.attr, \
++ &sensor_dev_attr_tacho_type_##type##_mode.dev_attr.attr, \
++ &sensor_dev_attr_tacho_type_##type##_unit.dev_attr.attr, \
++ &sensor_dev_attr_tacho_type_##type##_division.dev_attr.attr, \
++ &sensor_dev_attr_tacho_type_##type##_limit.dev_attr.attr, \
++ &sensor_dev_attr_tacho_type_##type##_measure_period.dev_attr.attr, \
++ NULL \
++};
++
++/*
++ * Create the needed functions for each pwm using the macro defined above
++ * (4 pwms are supported)
++ */
++sysfs_tacho_type(m,0);
++sysfs_tacho_type(n,1);
++#ifdef PWM_TYPE_O
++sysfs_tacho_type(o,2);
++#endif
++
++static const struct attribute_group tacho_type_attribute_groups[] = {
++ { .attrs = tacho_type_m_attributes },
++ { .attrs = tacho_type_n_attributes },
++#ifdef PWM_TYPE_O
++ { .attrs = tacho_type_o_attributes },
++#endif
++};
++
++/* FAN sysfs
++ * Macro defining SENSOR_DEVICE_ATTR for a tacho sysfs entries.
++ * - show/store enable
++ * - show/store source
++ * - show/store rpm
++ * - show/store alarm
++ * - show/store alarm_en
++ */
++#define sysfs_tacho_speeds_num(index) \
++static SENSOR_DEVICE_ATTR_2(tacho##index##_en, S_IRUGO | S_IWUSR, \
++ ast_show_tacho_speed, ast_store_tacho_speed, 0, index); \
++\
++static SENSOR_DEVICE_ATTR_2(tacho##index##_source, S_IRUGO | S_IWUSR, \
++ ast_show_tacho_speed, ast_store_tacho_speed, 1, index); \
++\
++static SENSOR_DEVICE_ATTR_2(tacho##index##_rpm, S_IRUGO, \
++ ast_show_tacho_speed, NULL, 2, index); \
++\
++static SENSOR_DEVICE_ATTR_2(tacho##index##_alarm, S_IRUGO, \
++ ast_show_tacho_speed, ast_store_tacho_speed, 3, index); \
++\
++static SENSOR_DEVICE_ATTR_2(tacho##index##_alarm_en, S_IRUGO | S_IWUSR, \
++ ast_show_tacho_speed, ast_store_tacho_speed, 4, index); \
++\
++static struct attribute *tacho##index##_attributes[] = { \
++ &sensor_dev_attr_tacho##index##_en.dev_attr.attr, \
++ &sensor_dev_attr_tacho##index##_source.dev_attr.attr, \
++ &sensor_dev_attr_tacho##index##_rpm.dev_attr.attr, \
++ &sensor_dev_attr_tacho##index##_alarm.dev_attr.attr, \
++ &sensor_dev_attr_tacho##index##_alarm_en.dev_attr.attr, \
++ NULL \
++};
++
++/*
++ * Create the needed functions for each tacho using the macro defined above
++ * (4 tachos are supported)
++ */
++sysfs_tacho_speeds_num(0);
++sysfs_tacho_speeds_num(1);
++sysfs_tacho_speeds_num(2);
++sysfs_tacho_speeds_num(3);
++sysfs_tacho_speeds_num(4);
++sysfs_tacho_speeds_num(5);
++sysfs_tacho_speeds_num(6);
++sysfs_tacho_speeds_num(7);
++sysfs_tacho_speeds_num(8);
++sysfs_tacho_speeds_num(9);
++sysfs_tacho_speeds_num(10);
++sysfs_tacho_speeds_num(11);
++sysfs_tacho_speeds_num(12);
++sysfs_tacho_speeds_num(13);
++sysfs_tacho_speeds_num(14);
++sysfs_tacho_speeds_num(15);
++
++static const struct attribute_group tacho_attribute_groups[] = {
++ { .attrs = tacho0_attributes },
++ { .attrs = tacho1_attributes },
++ { .attrs = tacho2_attributes },
++ { .attrs = tacho3_attributes },
++ { .attrs = tacho4_attributes },
++ { .attrs = tacho5_attributes },
++ { .attrs = tacho6_attributes },
++ { .attrs = tacho7_attributes },
++ { .attrs = tacho8_attributes },
++ { .attrs = tacho9_attributes },
++ { .attrs = tacho10_attributes },
++ { .attrs = tacho11_attributes },
++ { .attrs = tacho12_attributes },
++ { .attrs = tacho13_attributes },
++ { .attrs = tacho14_attributes },
++ { .attrs = tacho15_attributes },
++};
++
++static int
++ast_pwm_tacho_probe(struct platform_device *pdev)
++{
++ struct resource *res;
++ int err;
++ int ret=0;
++ int i;
++
++ dev_dbg(&pdev->dev, "ast_pwm_fan_probe \n");
++
++ ast_pwm_tacho = kzalloc(sizeof(struct ast_pwm_tacho_data), GFP_KERNEL);
++ if (!ast_pwm_tacho) {
++ ret = -ENOMEM;
++ goto out;
++ }
++
++ ast_pwm_tacho->ast_pwm_data = pdev->dev.platform_data;
++
++ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
++ if (NULL == res) {
++ dev_err(&pdev->dev, "cannot get IORESOURCE_MEM\n");
++ ret = -ENOENT;
++ goto out_mem;
++ }
++
++ if (!request_mem_region(res->start, resource_size(res), res->name)) {
++ dev_err(&pdev->dev, "cannot reserved region\n");
++ ret = -ENXIO;
++ goto out_mem;
++ }
++
++ ast_pwm_tacho->reg_base = ioremap(res->start, resource_size(res));
++ if (!ast_pwm_tacho->reg_base) {
++ ret = -EIO;
++ goto out_region;
++ }
++
++ ast_pwm_tacho->irq = platform_get_irq(pdev, 0);
++ if (ast_pwm_tacho->irq < 0) {
++ dev_err(&pdev->dev, "no irq specified\n");
++ ret = -ENOENT;
++ goto out_region;
++ }
++
++ /* Register sysfs hooks */
++ err = sysfs_create_group(&pdev->dev.kobj, &clk_attribute_groups);
++ if (err)
++ goto out_region;
++
++ ast_pwm_tacho->hwmon_dev = hwmon_device_register(&pdev->dev);
++ if (IS_ERR(ast_pwm_tacho->hwmon_dev)) {
++ ret = PTR_ERR(ast_pwm_tacho->hwmon_dev);
++ goto out_sysfs0;
++ }
++
++ for(i=0; i< PWM_CH_NUM; i++) {
++ err = sysfs_create_group(&pdev->dev.kobj, &pwm_attribute_groups[i]);
++ if (err)
++ goto out_sysfs0;
++ }
++
++ for(i=0; i< PWM_TYPE_NUM; i++) {
++ err = sysfs_create_group(&pdev->dev.kobj, &pwm_type_attribute_groups[i]);
++ if (err)
++ goto out_sysfs1;
++ }
++
++
++ for(i=0; i< TACHO_NUM; i++) {
++ err = sysfs_create_group(&pdev->dev.kobj, &tacho_attribute_groups[i]);
++ if (err)
++ goto out_sysfs2;
++ }
++
++ for(i=0; i< PWM_TYPE_NUM; i++) {
++ err = sysfs_create_group(&pdev->dev.kobj, &tacho_type_attribute_groups[i]);
++ if (err)
++ goto out_sysfs3;
++ }
++
++ ast_pwm_taco_init();
++
++ printk(KERN_INFO "ast_pwm_tacho: driver successfully loaded.\n");
++
++ return 0;
++
++out_sysfs3:
++ for(i=0; i< TACHO_NUM; i++)
++ sysfs_remove_group(&pdev->dev.kobj, &tacho_attribute_groups[i]);
++
++out_sysfs2:
++ for(i=0; i< PWM_TYPE_NUM; i++)
++ sysfs_remove_group(&pdev->dev.kobj, &pwm_type_attribute_groups[i]);
++
++out_sysfs1:
++ for(i=0; i< PWM_CH_NUM; i++)
++ sysfs_remove_group(&pdev->dev.kobj, &pwm_attribute_groups[i]);
++out_sysfs0:
++ sysfs_remove_group(&pdev->dev.kobj, &clk_attribute_groups);
++
++//out_irq:
++// free_irq(ast_pwm_tacho->irq, NULL);
++out_region:
++ release_mem_region(res->start, res->end - res->start + 1);
++out_mem:
++ kfree(ast_pwm_tacho);
++out:
++ printk(KERN_WARNING "applesmc: driver init failed (ret=%d)!\n", ret);
++ return ret;
++}
++
++static int
++ast_pwm_tacho_remove(struct platform_device *pdev)
++{
++ int i=0;
++ struct ast_pwm_tacho_data *ast_pwm_tacho = platform_get_drvdata(pdev);
++ struct resource *res;
++ printk(KERN_INFO "ast_pwm_tacho: driver unloaded.\n");
++
++ hwmon_device_unregister(ast_pwm_tacho->hwmon_dev);
++
++ for(i=0; i<16; i++)
++ sysfs_remove_group(&pdev->dev.kobj, &tacho_attribute_groups[i]);
++
++ for(i=0; i<3; i++)
++ sysfs_remove_group(&pdev->dev.kobj, &pwm_type_attribute_groups[i]);
++
++ for(i=0; i<8; i++)
++ sysfs_remove_group(&pdev->dev.kobj, &pwm_attribute_groups[i]);
++
++ sysfs_remove_group(&pdev->dev.kobj, &clk_attribute_groups);
++
++ platform_set_drvdata(pdev, NULL);
++// free_irq(ast_pwm_tacho->irq, ast_pwm_tacho);
++ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
++ iounmap(ast_pwm_tacho->reg_base);
++ release_mem_region(res->start, res->end - res->start + 1);
++ kfree(ast_pwm_tacho);
++ return 0;
++}
++
++#ifdef CONFIG_PM
++static int
++ast_pwm_tacho_suspend(struct platform_device *pdev, pm_message_t state)
++{
++ printk("ast_pwm_tacho_suspend : TODO \n");
++ return 0;
++}
++
++static int
++ast_pwm_tacho_resume(struct platform_device *pdev)
++{
++ ast_pwm_taco_init();
++ return 0;
++}
++
++#else
++#define ast_pwm_tacho_suspend NULL
++#define ast_pwm_tacho_resume NULL
++#endif
++
++static struct platform_driver ast_pwm_tacho_driver = {
++ .probe = ast_pwm_tacho_probe,
++ .remove = __devexit_p(ast_pwm_tacho_remove),
++ .suspend = ast_pwm_tacho_suspend,
++ .resume = ast_pwm_tacho_resume,
++ .driver = {
++ .name = "ast_pwm_tacho",
++ .owner = THIS_MODULE,
++ },
++};
++
++static int __init
++ast_pwm_tacho_init(void)
++{
++ return platform_driver_register(&ast_pwm_tacho_driver);
++}
++
++static void __exit
++ast_pwm_tacho_exit(void)
++{
++ platform_driver_unregister(&ast_pwm_tacho_driver);
++}
++
++module_init(ast_pwm_tacho_init);
++module_exit(ast_pwm_tacho_exit);
++
++MODULE_AUTHOR("Ryan Chen <ryan_chen@aspeedtech.com>");
++MODULE_DESCRIPTION("PWM TACHO driver");
++MODULE_LICENSE("GPL");
+diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig
+index 7f95905..2ed0928 100644
+--- a/drivers/i2c/busses/Kconfig
++++ b/drivers/i2c/busses/Kconfig
+@@ -454,6 +454,51 @@ config I2C_PXA_SLAVE
+ is necessary for systems where the PXA may be a target on the
+ I2C bus.
+
++config I2C_AST
++ tristate "ASPEED AST I2C adapter "
++# depends on ARCH_ASPEED
++ help
++ If you have devices in the AST I2C bus, say yes to this option.
++ This driver can also be built as a module. If so, the module
++ will be called i2c-ast.
++
++config I2C_AST1070
++ tristate "ASPEED AST1070 I2C adapter "
++ depends on ARCH_AST1070
++ help
++ If you have devices in the AST1070 I2C bus, say yes to this option.
++ This driver can also be built as a module. If so, the module
++ will be called i2c-ast.
++
++config AST_I2C_SLAVE_MODE
++ bool "AST I2C Slave mode"
++ depends on I2C_AST
++
++if AST_I2C_SLAVE_MODE
++
++choice
++ prompt "I2C slave config"
++ default AST_I2C_SLAVE_EEPROM
++
++config AST_I2C_SLAVE_EEPROM
++ bool "10 byte EEPROM Device"
++ help
++ Support I2C slave mode communications on the AST I2C bus. This
++ is necessary for systems where the AST may be a target on the
++ I2C bus.
++
++config AST_I2C_SLAVE_RDWR
++ bool "I2C Slave RD/WR via ioctl"
++
++ help
++ Support I2C slave mode communications on the AST I2C bus. This
++ is necessary for systems where the AST may be a target on the
++ I2C bus.
++
++endchoice
++
++endif
++
+ config I2C_S3C2410
+ tristate "S3C2410 I2C Driver"
+ depends on ARCH_S3C2410
+diff --git a/drivers/i2c/busses/Makefile b/drivers/i2c/busses/Makefile
+index 0c2c4b2..a3b523e 100644
+--- a/drivers/i2c/busses/Makefile
++++ b/drivers/i2c/busses/Makefile
+@@ -42,6 +42,7 @@ obj-$(CONFIG_I2C_OMAP) += i2c-omap.o
+ obj-$(CONFIG_I2C_PASEMI) += i2c-pasemi.o
+ obj-$(CONFIG_I2C_PNX) += i2c-pnx.o
+ obj-$(CONFIG_I2C_PXA) += i2c-pxa.o
++obj-$(CONFIG_I2C_AST) += i2c-ast.o
+ obj-$(CONFIG_I2C_S3C2410) += i2c-s3c2410.o
+ obj-$(CONFIG_I2C_SH7760) += i2c-sh7760.o
+ obj-$(CONFIG_I2C_SH_MOBILE) += i2c-sh_mobile.o
+diff --git a/drivers/i2c/busses/i2c-ast.c b/drivers/i2c/busses/i2c-ast.c
+new file mode 100644
+index 0000000..bccf5a3
+--- /dev/null
++++ b/drivers/i2c/busses/i2c-ast.c
+@@ -0,0 +1,1725 @@
++/*
++ * i2c_adap_ast.c
++ *
++ * I2C adapter for the ASPEED I2C bus access.
++ *
++ * Copyright (C) 2012-2020 ASPEED Technology Inc.
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * History:
++ * 2012.07.26: Initial version [Ryan Chen]
++ */
++#include <linux/kernel.h>
++#include <linux/module.h>
++#include <linux/i2c.h>
++#include <linux/i2c-id.h>
++#include <linux/init.h>
++#include <linux/time.h>
++#include <linux/delay.h>
++#include <linux/errno.h>
++#include <linux/interrupt.h>
++#include <linux/completion.h>
++
++#include <linux/platform_device.h>
++#include <linux/err.h>
++#include <linux/clk.h>
++
++#include <linux/dma-mapping.h>
++
++#include <asm/irq.h>
++#include <asm/io.h>
++
++#if defined(CONFIG_COLDFIRE)
++#include <asm/arch/regs-iic.h>
++#include <asm/arch/ast_i2c.h>
++#else
++#include <plat/regs-iic.h>
++#include <plat/ast_i2c.h>
++#endif
++
++//AST2400 buffer mode issue , force I2C slave write use byte mode , read use buffer mode
++/* Use platform_data instead of module parameters */
++/* Fast Mode = 400 kHz, Standard = 100 kHz */
++//static int clock = 100; /* Default: 100 kHz */
++
++
++/***************************************************************************/
++struct ast_i2c_dev {
++ struct ast_i2c_driver_data *ast_i2c_data;
++ struct device *dev;
++ void __iomem *reg_base; /* virtual */
++ int irq; //I2C IRQ number
++ u32 bus_id; //for i2c dev# IRQ number check
++ u32 state; //I2C xfer mode state matchine
++ struct i2c_adapter adap;
++ struct buf_page *req_page;
++//dma or buff mode needed
++ unsigned char *dma_buf;
++ dma_addr_t dma_addr;
++
++//master
++ int xfer_last; //cur xfer is last msgs for stop msgs
++ struct i2c_msg *master_msgs; //cur xfer msgs
++ int master_xfer_len; //cur xfer len
++ int master_xfer_cnt; //total xfer count
++ u32 master_xfer_mode; //cur xfer mode ... 0 : no_op , master: 1 byte , 2 : buffer , 3: dma , slave : xxxx
++ struct completion cmd_complete;
++ int cmd_err;
++ u8 blk_r_flag; //for smbus block read
++ void (*do_master_xfer)(struct ast_i2c_dev *i2c_dev);
++//Slave structure
++ u8 slave_operation;
++ u8 slave_event;
++ struct i2c_msg *slave_msgs; //cur slave xfer msgs
++ int slave_xfer_len;
++ int slave_xfer_cnt;
++ u32 slave_xfer_mode; //cur xfer mode ... 0 : no_op , master: 1 byte , 2 : buffer , 3: dma , slave : xxxx
++ void (*do_slave_xfer)(struct ast_i2c_dev *i2c_dev);
++};
++
++#ifdef CONFIG_AST_I2C_SLAVE_RDWR
++#define I2C_S_BUF_SIZE 64
++#define I2C_S_RX_BUF_NUM 4
++#define BUFF_FULL 0xff00
++#define BUFF_ONGOING 1
++
++struct i2c_msg slave_rx_msg[I2C_S_RX_BUF_NUM + 1];
++struct i2c_msg slave_tx_msg;
++#endif
++
++
++static inline void
++ast_i2c_write(struct ast_i2c_dev *i2c_dev, u32 val, u32 reg)
++{
++// dev_dbg(i2c_dev->dev, "ast_i2c_write : val: %x , reg : %x \n",val,reg);
++ writel(val, i2c_dev->reg_base+ reg);
++}
++
++static inline u32
++ast_i2c_read(struct ast_i2c_dev *i2c_dev, u32 reg)
++{
++#if 0
++ u32 val = readl(i2c_dev->reg_base + reg);
++ printk("R : reg %x , val: %x \n",reg, val);
++ return val;
++#else
++ return readl(i2c_dev->reg_base + reg);
++#endif
++}
++
++static u32 select_i2c_clock(struct ast_i2c_dev *i2c_dev)
++{
++
++ unsigned int clk, inc = 0, div, divider_ratio;
++ u32 SCL_Low, SCL_High, data;
++
++ clk = i2c_dev->ast_i2c_data->get_i2c_clock();
++// printk("pclk = %d \n",clk);
++ divider_ratio = clk / i2c_dev->ast_i2c_data->bus_clk;
++ for (div = 0; divider_ratio >= 16; div++)
++ {
++ inc |= (divider_ratio & 1);
++ divider_ratio >>= 1;
++ }
++ divider_ratio += inc;
++ SCL_Low = (divider_ratio >> 1) - 1;
++ SCL_High = divider_ratio - SCL_Low - 2;
++ data = 0x77700300 | (SCL_High << 16) | (SCL_Low << 12) | div;
++// printk("I2CD04 for %d = %08X\n", target_speed, data);
++ return data;
++}
++
++#ifdef CONFIG_AST_I2C_SLAVE_MODE
++/* AST I2C Slave mode */
++static void ast_slave_issue_alert(struct ast_i2c_dev *i2c_dev, u8 enable)
++{
++ //only support dev0~3
++ if(i2c_dev->bus_id > 3)
++ return;
++ else {
++ if(enable)
++ ast_i2c_write(i2c_dev, ast_i2c_read(i2c_dev,I2C_CMD_REG) | AST_I2CD_S_ALT_EN, I2C_CMD_REG);
++ else
++ ast_i2c_write(i2c_dev, ast_i2c_read(i2c_dev,I2C_CMD_REG) & ~AST_I2CD_S_ALT_EN, I2C_CMD_REG);
++ }
++}
++
++static void ast_slave_mode_enable(struct ast_i2c_dev *i2c_dev, struct i2c_msg *msgs)
++{
++ if(msgs->buf[0] == 1) {
++ ast_i2c_write(i2c_dev, msgs->addr, I2C_DEV_ADDR_REG);
++ ast_i2c_write(i2c_dev, ast_i2c_read(i2c_dev,I2C_FUN_CTRL_REG) | AST_I2CD_SLAVE_EN, I2C_FUN_CTRL_REG);
++ } else
++ ast_i2c_write(i2c_dev, ast_i2c_read(i2c_dev,I2C_FUN_CTRL_REG) & ~AST_I2CD_SLAVE_EN, I2C_FUN_CTRL_REG);
++}
++
++#endif
++
++static void ast_i2c_dev_init(struct ast_i2c_dev *i2c_dev)
++{
++ //I2CG Reset
++ ast_i2c_write(i2c_dev, 0, I2C_FUN_CTRL_REG);
++
++#ifdef CONFIG_AST_I2C_SLAVE_EEPROM
++ i2c_dev->ast_i2c_data->slave_init(&(i2c_dev->slave_msgs));
++ ast_slave_mode_enable(i2c_dev, i2c_dev->slave_msgs);
++#endif
++
++ //Enable Master Mode
++ ast_i2c_write(i2c_dev, ast_i2c_read(i2c_dev, I2C_FUN_CTRL_REG) | AST_I2CD_MASTER_EN, I2C_FUN_CTRL_REG);
++
++
++ /* Set AC Timing */
++#if defined(CONFIG_ARCH_AST2400)
++ if(i2c_dev->ast_i2c_data->bus_clk/1000 > 400) {
++ printk("high speed mode enable clk [%dkhz]\n",i2c_dev->ast_i2c_data->bus_clk/1000);
++ ast_i2c_write(i2c_dev, ast_i2c_read(i2c_dev, I2C_FUN_CTRL_REG) |
++ AST_I2CD_M_HIGH_SPEED_EN |
++ AST_I2CD_M_SDA_DRIVE_1T_EN |
++ AST_I2CD_SDA_DRIVE_1T_EN
++ , I2C_FUN_CTRL_REG);
++
++ /* Set AC Timing */
++ ast_i2c_write(i2c_dev, 0x3, I2C_AC_TIMING_REG2);
++ ast_i2c_write(i2c_dev, select_i2c_clock(i2c_dev), I2C_AC_TIMING_REG1);
++ }else {
++ /* target apeed is xxKhz*/
++ ast_i2c_write(i2c_dev, select_i2c_clock(i2c_dev), I2C_AC_TIMING_REG1);
++ ast_i2c_write(i2c_dev, AST_NO_TIMEOUT_CTRL, I2C_AC_TIMING_REG2);
++ }
++#else
++ /* target apeed is xxKhz*/
++ ast_i2c_write(i2c_dev, select_i2c_clock(i2c_dev), I2C_AC_TIMING_REG1);
++ ast_i2c_write(i2c_dev, AST_NO_TIMEOUT_CTRL, I2C_AC_TIMING_REG2);
++#endif
++// ast_i2c_write(i2c_dev, 0x77743335, I2C_AC_TIMING_REG1);
++/////
++
++
++ //Clear Interrupt
++ ast_i2c_write(i2c_dev, 0xfffffff, I2C_INTR_STS_REG);
++
++ //TODO
++// ast_i2c_write(i2c_dev, 0xAF, I2C_INTR_CTRL_REG);
++ //Enable Interrupt, STOP Interrupt has bug in AST2000
++
++ /* Set interrupt generation of I2C controller */
++ ast_i2c_write(i2c_dev,
++ AST_I2CD_SDA_DL_TO_INTR_EN |
++ AST_I2CD_BUS_RECOVER_INTR_EN |
++ AST_I2CD_SMBUS_ALT_INTR_EN |
++// AST_I2CD_SLAVE_MATCH_INTR_EN |
++ AST_I2CD_SCL_TO_INTR_EN |
++ AST_I2CD_ABNORMAL_INTR_EN |
++ AST_I2CD_NORMAL_STOP_INTR_EN |
++ AST_I2CD_ARBIT_LOSS_INTR_EN |
++ AST_I2CD_RX_DOWN_INTR_EN |
++ AST_I2CD_TX_NAK_INTR_EN |
++ AST_I2CD_TX_ACK_INTR_EN,
++ I2C_INTR_CTRL_REG);
++
++}
++
++#ifdef CONFIG_AST_I2C_SLAVE_RDWR
++//for memory buffer initial
++static void ast_i2c_slave_buff_init(struct ast_i2c_dev *i2c_dev)
++{
++ int i;
++ //Tx buf 1
++ slave_tx_msg.len = I2C_S_BUF_SIZE;
++ slave_tx_msg.buf = kzalloc(I2C_S_BUF_SIZE, GFP_KERNEL);
++ //Rx buf 4
++ for(i=0; i<I2C_S_RX_BUF_NUM+1; i++) {
++ slave_rx_msg[i].addr = ~BUFF_ONGOING;
++ slave_rx_msg[i].flags = 0; //mean empty buffer
++ slave_rx_msg[i].len = I2C_S_BUF_SIZE;
++ slave_rx_msg[i].buf = kzalloc(I2C_S_BUF_SIZE, GFP_KERNEL);
++ }
++}
++
++static void ast_i2c_slave_rdwr_xfer(struct ast_i2c_dev *i2c_dev)
++{
++ int i;
++ spinlock_t lock;
++ spin_lock(&lock);
++
++ switch(i2c_dev->slave_event) {
++ case I2C_SLAVE_EVENT_START_WRITE:
++ for(i=0; i<I2C_S_RX_BUF_NUM; i++) {
++ if((slave_rx_msg[i].flags == 0) && (slave_rx_msg[i].addr != BUFF_ONGOING)) {
++ slave_rx_msg[i].addr = BUFF_ONGOING;
++ break;
++ }
++ }
++ if(i == I2C_S_RX_BUF_NUM) {
++ printk("RX buffer full ........use tmp msgs buff \n");
++ //TODO...
++ }
++ printk("I2C_SLAVE_EVENT_START_WRITE ... %d \n", i);
++
++ i2c_dev->slave_msgs = &slave_rx_msg[i];
++ break;
++ case I2C_SLAVE_EVENT_START_READ:
++ printk("I2C_SLAVE_EVENT_START_READ ERROR .. not imple \n");
++ i2c_dev->slave_msgs = &slave_tx_msg;
++ break;
++ case I2C_SLAVE_EVENT_WRITE:
++ printk("I2C_SLAVE_EVENT_WRITE next write ERROR ...\n");
++ i2c_dev->slave_msgs = &slave_tx_msg;
++ break;
++ case I2C_SLAVE_EVENT_READ:
++ printk("I2C_SLAVE_EVENT_READ ERROR ... \n");
++ i2c_dev->slave_msgs = &slave_tx_msg;
++ break;
++ case I2C_SLAVE_EVENT_NACK:
++ printk("I2C_SLAVE_EVENT_NACK ERROR ... \n");
++ i2c_dev->slave_msgs = &slave_tx_msg;
++ break;
++ case I2C_SLAVE_EVENT_STOP:
++ printk("I2C_SLAVE_EVENT_STOP \n");
++ for(i=0; i<I2C_S_RX_BUF_NUM; i++) {
++ if(slave_rx_msg[i].addr == BUFF_ONGOING) {
++ slave_rx_msg[i].flags = BUFF_FULL;
++ slave_rx_msg[i].addr = 0;
++ break;
++ }
++ }
++
++ i2c_dev->slave_msgs = &slave_tx_msg;
++ break;
++ }
++ spin_unlock(&lock);
++
++}
++
++static int ast_i2c_slave_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs)
++{
++ struct ast_i2c_dev *i2c_dev = adap->algo_data;
++ int ret=0, i;
++
++ switch(msgs->flags) {
++ case 0:
++// printk("slave read \n");
++ //cur_msg = get_free_msg;
++ for(i=0; i<I2C_S_RX_BUF_NUM; i++) {
++ if((slave_rx_msg[i].addr == 0) && (slave_rx_msg[i].flags == BUFF_FULL)) {
++ memcpy(msgs->buf, slave_rx_msg[i].buf, slave_rx_msg[i].len);
++ msgs->len = slave_rx_msg[i].len;
++ slave_rx_msg[i].flags = 0;
++ slave_rx_msg[i].len = 0;
++ break;
++ }
++ }
++
++ if(i == I2C_S_RX_BUF_NUM) {
++ printk("No buffer ........ \n");
++ msgs->len = 0;
++ ret = -1;
++ }
++ break;
++ case I2C_M_RD: //slave write
++// printk("slave write \n");
++ memcpy(msgs->buf, slave_tx_msg.buf, I2C_S_BUF_SIZE);
++ break;
++ case I2C_S_EN:
++ if((msgs->addr < 0x1) || (msgs->addr > 0xff)) {
++ ret = -1;
++ printk("addrsss not correct !! \n");
++ return ret;
++ }
++ if(msgs->len != 1) printk("ERROR \n");
++ ast_slave_mode_enable(i2c_dev, msgs);
++ break;
++ case I2C_S_ALT:
++// printk("slave issue alt\n");
++ if(msgs->len != 1) printk("ERROR \n");
++ if(msgs->buf[0]==1)
++ ast_slave_issue_alert(i2c_dev, 1);
++ else
++ ast_slave_issue_alert(i2c_dev, 0);
++ break;
++
++ default:
++ printk("slave xfer error \n");
++ break;
++
++ }
++ return ret;
++}
++
++
++#endif
++
++static u8
++ast_i2c_bus_error_recover(struct ast_i2c_dev *i2c_dev)
++{
++ u32 sts;
++ int r;
++ u32 i = 0;
++
++ //Check 0x14's SDA and SCL status
++ sts = ast_i2c_read(i2c_dev,I2C_CMD_REG);
++
++ if ((sts & AST_I2CD_SDA_LINE_STS) && (sts & AST_I2CD_SCL_LINE_STS)) {
++ //Means bus is idle.
++ dev_dbg(i2c_dev->dev, "I2C bus (%d) is idle. I2C slave doesn't exist?!\n", i2c_dev->bus_id);
++ return -1;
++ }
++
++ dev_dbg(i2c_dev->dev, "ERROR!! I2C(%d) bus hanged, try to recovery it!\n", i2c_dev->bus_id);
++
++
++ if ((sts & AST_I2CD_SDA_LINE_STS) && !(sts & AST_I2CD_SCL_LINE_STS)) {
++ //if SDA == 1 and SCL == 0, it means the master is locking the bus.
++ //Send a stop command to unlock the bus.
++ dev_dbg(i2c_dev->dev, "I2C's master is locking the bus, try to stop it.\n");
++//
++ init_completion(&i2c_dev->cmd_complete);
++
++ ast_i2c_write(i2c_dev, AST_I2CD_M_STOP_CMD, I2C_CMD_REG);
++
++ r = wait_for_completion_interruptible_timeout(&i2c_dev->cmd_complete,
++ i2c_dev->adap.timeout*HZ);
++
++ if(i2c_dev->cmd_err) {
++ dev_dbg(i2c_dev->dev, "recovery error \n");
++ return -1;
++ }
++
++ if (r == 0) {
++ dev_dbg(i2c_dev->dev, "recovery timed out\n");
++ return -1;
++ } else {
++ dev_dbg(i2c_dev->dev, "Recovery successfully\n");
++ return 0;
++ }
++
++
++ } else if (!(sts & AST_I2CD_SDA_LINE_STS)) {
++ //else if SDA == 0, the device is dead. We need to reset the bus
++ //And do the recovery command.
++ dev_dbg(i2c_dev->dev, "I2C's slave is dead, try to recover it\n");
++ //Let's retry 10 times
++ for (i = 0; i < 10; i++) {
++ ast_i2c_dev_init(i2c_dev);
++ //Do the recovery command BIT11
++ init_completion(&i2c_dev->cmd_complete);
++ ast_i2c_write(i2c_dev, AST_I2CD_BUS_RECOVER_CMD_EN, I2C_CMD_REG);
++
++ r = wait_for_completion_interruptible_timeout(&i2c_dev->cmd_complete,
++ i2c_dev->adap.timeout*HZ);
++ if (i2c_dev->cmd_err != 0) {
++ dev_dbg(i2c_dev->dev, "ERROR!! Failed to do recovery command(0x%08x)\n", i2c_dev->cmd_err);
++ return -1;
++ }
++ //Check 0x14's SDA and SCL status
++ sts = ast_i2c_read(i2c_dev,I2C_CMD_REG);
++ if (sts & AST_I2CD_SDA_LINE_STS) //Recover OK
++ break;
++ }
++ if (i == 10) {
++ dev_dbg(i2c_dev->dev, "ERROR!! recover failed\n");
++ return -1;
++ }
++ } else {
++ dev_dbg(i2c_dev->dev, "Don't know how to handle this case?!\n");
++ return -1;
++ }
++ dev_dbg(i2c_dev->dev, "Recovery successfully\n");
++ return 0;
++}
++
++static void ast_master_alert_recv(struct ast_i2c_dev *i2c_dev)
++{
++ printk("ast_master_alert_recv bus id %d, Disable Alt, Please Imple \n",i2c_dev->bus_id);
++}
++
++static int ast_i2c_wait_bus_not_busy(struct ast_i2c_dev *i2c_dev)
++{
++ int timeout = 32; //TODO number
++// printk("ast_i2c_wait_bus_not_busy \n");
++ while (ast_i2c_read(i2c_dev,I2C_CMD_REG) & AST_I2CD_BUS_BUSY_STS) {
++ ast_i2c_bus_error_recover(i2c_dev);
++ if(timeout<=0)
++ break;
++ timeout--;
++ msleep(2);
++ }
++
++ return timeout <= 0 ? EAGAIN : 0;
++}
++
++static void ast_i2c_do_dma_xfer(struct ast_i2c_dev *i2c_dev)
++{
++ u32 cmd = 0;
++ int i;
++
++ i2c_dev->master_xfer_mode = DMA_XFER;
++ i2c_dev->slave_xfer_mode = DMA_XFER;
++
++ if(i2c_dev->slave_operation == 1) {
++ if(i2c_dev->slave_msgs->flags & I2C_M_RD) {
++ //DMA tx mode
++ if(i2c_dev->slave_msgs->len > AST_I2C_DMA_SIZE)
++ i2c_dev->slave_xfer_len = AST_I2C_DMA_SIZE;
++ else
++ i2c_dev->slave_xfer_len = i2c_dev->slave_msgs->len;
++
++ dev_dbg(i2c_dev->dev, "(<--) slave tx DMA \n");
++ for(i=0; i<i2c_dev->slave_xfer_len; i++)
++ i2c_dev->dma_buf[i] = i2c_dev->slave_msgs->buf[i2c_dev->slave_xfer_cnt + i];
++
++ ast_i2c_write(i2c_dev, i2c_dev->dma_addr, I2C_DMA_BASE_REG);
++ ast_i2c_write(i2c_dev, (i2c_dev->slave_xfer_len-1), I2C_DMA_LEN_REG);
++ ast_i2c_write(i2c_dev, AST_I2CD_TX_DMA_ENABLE | AST_I2CD_S_TX_CMD,I2C_CMD_REG);
++ } else {
++ //DMA prepare rx
++ dev_dbg(i2c_dev->dev, "(-->) slave rx DMA \n");
++ ast_i2c_write(i2c_dev, i2c_dev->dma_addr, I2C_DMA_BASE_REG);
++ ast_i2c_write(i2c_dev, (AST_I2C_DMA_SIZE-1), I2C_DMA_LEN_REG);
++ ast_i2c_write(i2c_dev, AST_I2CD_RX_DMA_ENABLE, I2C_CMD_REG);
++ }
++ } else {
++ dev_dbg(i2c_dev->dev,"M cnt %d, xf len %d \n",i2c_dev->master_xfer_cnt, i2c_dev->master_msgs->len);
++ if(i2c_dev->master_xfer_cnt == -1) {
++ //send start
++ dev_dbg(i2c_dev->dev, " %sing %d byte%s %s 0x%02x\n",
++ i2c_dev->master_msgs->flags & I2C_M_RD ? "read" : "write",
++ i2c_dev->master_msgs->len, i2c_dev->master_msgs->len > 1 ? "s" : "",
++ i2c_dev->master_msgs->flags & I2C_M_RD ? "from" : "to", i2c_dev->master_msgs->addr);
++
++ if(i2c_dev->master_msgs->flags & I2C_M_RD) {
++ //workaround .. HW can;t send start read addr with buff mode
++ cmd = AST_I2CD_M_START_CMD | AST_I2CD_M_TX_CMD;
++ ast_i2c_write(i2c_dev, (i2c_dev->master_msgs->addr <<1) |0x1, I2C_BYTE_BUF_REG);
++
++// tx_buf[0] = (i2c_dev->master_msgs->addr <<1); //+1
++ i2c_dev->master_xfer_len = 1;
++ ast_i2c_write(i2c_dev, ast_i2c_read(i2c_dev,I2C_INTR_CTRL_REG) |
++ AST_I2CD_TX_ACK_INTR_EN, I2C_INTR_CTRL_REG);
++ } else {
++ //tx
++ cmd = AST_I2CD_M_START_CMD | AST_I2CD_M_TX_CMD | AST_I2CD_TX_DMA_ENABLE;
++
++ i2c_dev->dma_buf[0] = (i2c_dev->master_msgs->addr <<1); //+1
++ //next data write
++ if((i2c_dev->master_msgs->len + 1) > AST_I2C_DMA_SIZE)
++ i2c_dev->master_xfer_len = AST_I2C_DMA_SIZE;
++ else
++ i2c_dev->master_xfer_len = i2c_dev->master_msgs->len + 1;
++
++ for(i = 1; i < i2c_dev->master_xfer_len; i++)
++ i2c_dev->dma_buf[i] = i2c_dev->master_msgs->buf[i2c_dev->master_xfer_cnt+i];
++
++ if (i2c_dev->xfer_last == 1) {
++ dev_dbg(i2c_dev->dev, "last stop \n");
++ cmd |= AST_I2CD_M_STOP_CMD;
++ ast_i2c_write(i2c_dev, ast_i2c_read(i2c_dev,I2C_INTR_CTRL_REG) &
++ ~AST_I2CD_TX_ACK_INTR_EN, I2C_INTR_CTRL_REG);
++
++ } else {
++ ast_i2c_write(i2c_dev, ast_i2c_read(i2c_dev,I2C_INTR_CTRL_REG) |
++ AST_I2CD_TX_ACK_INTR_EN, I2C_INTR_CTRL_REG);
++ }
++ ast_i2c_write(i2c_dev, i2c_dev->dma_addr, I2C_DMA_BASE_REG);
++ ast_i2c_write(i2c_dev, (i2c_dev->master_xfer_len-1), I2C_DMA_LEN_REG);
++
++ }
++ ast_i2c_write(i2c_dev, cmd, I2C_CMD_REG);
++ dev_dbg(i2c_dev->dev, "txfer size %d , cmd = %x \n",i2c_dev->master_xfer_len, cmd);
++
++ } else if (i2c_dev->master_xfer_cnt < i2c_dev->master_msgs->len){
++ //Next send
++ if(i2c_dev->master_msgs->flags & I2C_M_RD) {
++ //Rx data
++ cmd = AST_I2CD_M_RX_CMD | AST_I2CD_RX_DMA_ENABLE;
++
++ if((i2c_dev->master_msgs->len - i2c_dev->master_xfer_cnt) > AST_I2C_DMA_SIZE) {
++ i2c_dev->master_xfer_len = AST_I2C_DMA_SIZE;
++ ast_i2c_write(i2c_dev, ast_i2c_read(i2c_dev,I2C_INTR_CTRL_REG) |
++ AST_I2CD_RX_DOWN_INTR_EN, I2C_INTR_CTRL_REG);
++
++ } else {
++ i2c_dev->master_xfer_len = i2c_dev->master_msgs->len - i2c_dev->master_xfer_cnt;
++ if((i2c_dev->master_msgs->flags & I2C_M_RECV_LEN) && (i2c_dev->blk_r_flag == 0)) {
++ dev_dbg(i2c_dev->dev, "I2C_M_RECV_LEN \n");
++ ast_i2c_write(i2c_dev, ast_i2c_read(i2c_dev,I2C_INTR_CTRL_REG) |
++ AST_I2CD_RX_DOWN_INTR_EN, I2C_INTR_CTRL_REG);
++ } else {
++#ifdef CONFIG_AST1010
++ //Workaround for ast1010 can't send NACK
++ if((i2c_dev->master_xfer_len == 1) && (i2c_dev->xfer_last == 1)) {
++ //change to byte mode
++ cmd |= AST_I2CD_M_STOP_CMD | AST_I2CD_M_S_RX_CMD_LAST;
++ cmd &= ~AST_I2CD_RX_DMA_ENABLE;
++ i2c_dev->master_xfer_mode = BYTE_XFER;
++ ast_i2c_write(i2c_dev, ast_i2c_read(i2c_dev,I2C_INTR_CTRL_REG) &
++ ~AST_I2CD_RX_DOWN_INTR_EN, I2C_INTR_CTRL_REG);
++
++ } else if (i2c_dev->master_xfer_len > 1) {
++ i2c_dev->master_xfer_len -=1;
++ ast_i2c_write(i2c_dev, ast_i2c_read(i2c_dev,I2C_INTR_CTRL_REG) |
++ AST_I2CD_RX_DOWN_INTR_EN, I2C_INTR_CTRL_REG);
++ } else {
++ printk(" Fix Me !! \n");
++ }
++#else
++ if(i2c_dev->xfer_last == 1) {
++ dev_dbg(i2c_dev->dev, "last stop \n");
++ cmd |= AST_I2CD_M_STOP_CMD;
++ ast_i2c_write(i2c_dev, ast_i2c_read(i2c_dev,I2C_INTR_CTRL_REG) &
++ ~AST_I2CD_RX_DOWN_INTR_EN, I2C_INTR_CTRL_REG);
++ } else {
++ ast_i2c_write(i2c_dev, ast_i2c_read(i2c_dev,I2C_INTR_CTRL_REG) |
++ AST_I2CD_RX_DOWN_INTR_EN, I2C_INTR_CTRL_REG);
++ }
++ //TODO check....
++ cmd |= AST_I2CD_M_S_RX_CMD_LAST;
++#endif
++ }
++
++ }
++ ast_i2c_write(i2c_dev, i2c_dev->dma_addr, I2C_DMA_BASE_REG);
++ ast_i2c_write(i2c_dev, i2c_dev->master_xfer_len-1, I2C_DMA_LEN_REG);
++ ast_i2c_write(i2c_dev, cmd, I2C_CMD_REG);
++ dev_dbg(i2c_dev->dev, "rxfer size %d , cmd = %x \n",i2c_dev->master_xfer_len, cmd);
++ } else {
++ //Tx data
++ //next data write
++ cmd = AST_I2CD_M_TX_CMD | AST_I2CD_TX_DMA_ENABLE;
++ if((i2c_dev->master_msgs->len - i2c_dev->master_xfer_cnt) > AST_I2C_DMA_SIZE) {
++ i2c_dev->master_xfer_len = AST_I2C_DMA_SIZE;
++ ast_i2c_write(i2c_dev, ast_i2c_read(i2c_dev,I2C_INTR_CTRL_REG) |
++ AST_I2CD_TX_ACK_INTR_EN, I2C_INTR_CTRL_REG);
++
++ } else {
++ i2c_dev->master_xfer_len = i2c_dev->master_msgs->len - i2c_dev->master_xfer_cnt;
++ if(i2c_dev->xfer_last == 1) {
++ dev_dbg(i2c_dev->dev, "last stop \n");
++ cmd |= AST_I2CD_M_STOP_CMD;
++ ast_i2c_write(i2c_dev, ast_i2c_read(i2c_dev,I2C_INTR_CTRL_REG) &
++ ~AST_I2CD_TX_ACK_INTR_EN, I2C_INTR_CTRL_REG);
++
++ } else {
++ ast_i2c_write(i2c_dev, ast_i2c_read(i2c_dev,I2C_INTR_CTRL_REG) |
++ AST_I2CD_TX_ACK_INTR_EN, I2C_INTR_CTRL_REG);
++ }
++ }
++
++ for(i = 0; i < i2c_dev->master_xfer_len; i++)
++ i2c_dev->dma_buf[i] = i2c_dev->master_msgs->buf[i2c_dev->master_xfer_cnt + i];
++
++ ast_i2c_write(i2c_dev, i2c_dev->dma_addr, I2C_DMA_BASE_REG);
++ ast_i2c_write(i2c_dev, (i2c_dev->master_xfer_len-1), I2C_DMA_LEN_REG);
++ ast_i2c_write(i2c_dev, cmd , I2C_CMD_REG);
++ dev_dbg(i2c_dev->dev, "txfer size %d , cmd = %x \n",i2c_dev->master_xfer_len, cmd);
++
++ }
++ }else {
++ //should send next msg
++ if(i2c_dev->master_xfer_cnt != i2c_dev->master_msgs->len)
++ printk("complete rx ... ERROR \n");
++
++ dev_dbg(i2c_dev->dev, "ast_i2c_do_byte_xfer complete \n");
++ i2c_dev->cmd_err = 0;
++ complete(&i2c_dev->cmd_complete);
++ }
++
++ }
++
++
++}
++
++static void ast_i2c_do_pool_xfer(struct ast_i2c_dev *i2c_dev)
++{
++ u32 cmd = 0;
++ int i;
++ u32 *tx_buf;
++
++ i2c_dev->master_xfer_mode = BUFF_XFER;
++ i2c_dev->slave_xfer_mode = BUFF_XFER;
++
++#if defined(CONFIG_ARCH_AST2400)
++ ast_i2c_write(i2c_dev,
++ (ast_i2c_read(i2c_dev, I2C_FUN_CTRL_REG) &
++ ~AST_I2CD_BUFF_SEL_MASK) |
++ AST_I2CD_BUFF_SEL(i2c_dev->req_page->page_no),
++ I2C_FUN_CTRL_REG);
++#endif
++
++ tx_buf = (u32 *) i2c_dev->req_page->page_addr;
++
++
++ if(i2c_dev->slave_operation == 1) {
++ if(i2c_dev->slave_msgs->flags & I2C_M_RD) {
++ dev_dbg(i2c_dev->dev, "(<--) slave tx buf \n");
++
++ if(i2c_dev->slave_msgs->len > i2c_dev->req_page->page_size)
++ i2c_dev->slave_xfer_len = i2c_dev->req_page->page_size;
++ else
++ i2c_dev->slave_xfer_len = i2c_dev->slave_msgs->len;
++
++ for(i = 0; i< i2c_dev->slave_xfer_len; i++) {
++ if(i%4 == 0)
++ tx_buf[i/4] = 0;
++ tx_buf[i/4] |= (i2c_dev->slave_msgs->buf[i2c_dev->slave_xfer_cnt + i] << ((i%4)*8)) ;
++ dev_dbg(i2c_dev->dev, "[%x] ",tx_buf[i/4]);
++ }
++ dev_dbg(i2c_dev->dev, "\n");
++
++ ast_i2c_write(i2c_dev, AST_I2CD_TX_DATA_BUF_END_SET((i2c_dev->slave_xfer_len-1)) |
++ AST_I2CD_BUF_BASE_ADDR_SET((i2c_dev->req_page->page_addr_point)),
++ I2C_BUF_CTRL_REG);
++
++ ast_i2c_write(i2c_dev, AST_I2CD_TX_BUFF_ENABLE | AST_I2CD_S_TX_CMD, I2C_CMD_REG);
++ } else {
++ //prepare for new rx
++ dev_dbg(i2c_dev->dev, "(-->) slave prepare rx buf \n");
++ ast_i2c_write(i2c_dev,
++ AST_I2CD_RX_BUF_END_ADDR_SET((i2c_dev->req_page->page_size-1)) |
++ AST_I2CD_BUF_BASE_ADDR_SET((i2c_dev->req_page->page_addr_point)),
++ I2C_BUF_CTRL_REG);
++
++ ast_i2c_write(i2c_dev, AST_I2CD_RX_BUFF_ENABLE, I2C_CMD_REG);
++
++ }
++ } else {
++ dev_dbg(i2c_dev->dev,"M cnt %d, xf len %d \n",i2c_dev->master_xfer_cnt, i2c_dev->master_msgs->len);
++ if(i2c_dev->master_xfer_cnt == -1) {
++ //send start
++ dev_dbg(i2c_dev->dev, " %sing %d byte%s %s 0x%02x\n",
++ i2c_dev->master_msgs->flags & I2C_M_RD ? "read" : "write",
++ i2c_dev->master_msgs->len, i2c_dev->master_msgs->len > 1 ? "s" : "",
++ i2c_dev->master_msgs->flags & I2C_M_RD ? "from" : "to", i2c_dev->master_msgs->addr);
++
++ if(i2c_dev->master_msgs->flags & I2C_M_RD) {
++//workaround .. HW can;t send start read addr with buff mode
++ cmd = AST_I2CD_M_START_CMD | AST_I2CD_M_TX_CMD;
++ ast_i2c_write(i2c_dev, (i2c_dev->master_msgs->addr <<1) |0x1, I2C_BYTE_BUF_REG);
++
++// tx_buf[0] = (i2c_dev->master_msgs->addr <<1); //+1
++ i2c_dev->master_xfer_len = 1;
++ ast_i2c_write(i2c_dev, ast_i2c_read(i2c_dev,I2C_INTR_CTRL_REG) |
++ AST_I2CD_TX_ACK_INTR_EN, I2C_INTR_CTRL_REG);
++ } else {
++ cmd = AST_I2CD_M_START_CMD | AST_I2CD_M_TX_CMD | AST_I2CD_TX_BUFF_ENABLE;
++ tx_buf[0] = (i2c_dev->master_msgs->addr <<1); //+1
++ //next data write
++ if((i2c_dev->master_msgs->len + 1) > i2c_dev->req_page->page_size)
++ i2c_dev->master_xfer_len = i2c_dev->req_page->page_size;
++ else
++ i2c_dev->master_xfer_len = i2c_dev->master_msgs->len + 1;
++
++ for(i = 1; i < i2c_dev->master_xfer_len; i++) {
++ if(i%4 == 0)
++ tx_buf[i/4] = 0;
++ tx_buf[i/4] |= (i2c_dev->master_msgs->buf[i2c_dev->master_xfer_cnt + i] << ((i%4)*8)) ;
++ }
++
++ if (i2c_dev->xfer_last == 1) {
++ dev_dbg(i2c_dev->dev, "last stop \n");
++ cmd |= AST_I2CD_M_STOP_CMD;
++ ast_i2c_write(i2c_dev, ast_i2c_read(i2c_dev,I2C_INTR_CTRL_REG) &
++ ~AST_I2CD_TX_ACK_INTR_EN, I2C_INTR_CTRL_REG);
++
++ } else {
++ ast_i2c_write(i2c_dev, ast_i2c_read(i2c_dev,I2C_INTR_CTRL_REG) |
++ AST_I2CD_TX_ACK_INTR_EN, I2C_INTR_CTRL_REG);
++ }
++ ast_i2c_write(i2c_dev,
++ AST_I2CD_TX_DATA_BUF_END_SET((i2c_dev->master_xfer_len - 1)) |
++ AST_I2CD_BUF_BASE_ADDR_SET(i2c_dev->req_page->page_addr_point),
++ I2C_BUF_CTRL_REG);
++ }
++ ast_i2c_write(i2c_dev, cmd, I2C_CMD_REG);
++ dev_dbg(i2c_dev->dev, "txfer size %d , cmd = %x \n",i2c_dev->master_xfer_len, cmd);
++
++ } else if (i2c_dev->master_xfer_cnt < i2c_dev->master_msgs->len){
++ //Next send
++ if(i2c_dev->master_msgs->flags & I2C_M_RD) {
++ //Rx data
++ cmd = AST_I2CD_M_RX_CMD | AST_I2CD_RX_BUFF_ENABLE;
++
++ if((i2c_dev->master_msgs->len - i2c_dev->master_xfer_cnt) > i2c_dev->req_page->page_size) {
++ i2c_dev->master_xfer_len = i2c_dev->req_page->page_size;
++ ast_i2c_write(i2c_dev, ast_i2c_read(i2c_dev,I2C_INTR_CTRL_REG) |
++ AST_I2CD_RX_DOWN_INTR_EN, I2C_INTR_CTRL_REG);
++ } else {
++ i2c_dev->master_xfer_len = i2c_dev->master_msgs->len - i2c_dev->master_xfer_cnt;
++ if((i2c_dev->master_msgs->flags & I2C_M_RECV_LEN) && (i2c_dev->blk_r_flag == 0)) {
++ dev_dbg(i2c_dev->dev, "I2C_M_RECV_LEN \n");
++ ast_i2c_write(i2c_dev, ast_i2c_read(i2c_dev,I2C_INTR_CTRL_REG) |
++ AST_I2CD_RX_DOWN_INTR_EN, I2C_INTR_CTRL_REG);
++ } else {
++ if(i2c_dev->xfer_last == 1) {
++ dev_dbg(i2c_dev->dev, "last stop \n");
++ cmd |= AST_I2CD_M_STOP_CMD;
++ ast_i2c_write(i2c_dev, ast_i2c_read(i2c_dev,I2C_INTR_CTRL_REG) &
++ ~AST_I2CD_RX_DOWN_INTR_EN, I2C_INTR_CTRL_REG);
++ } else {
++ ast_i2c_write(i2c_dev, ast_i2c_read(i2c_dev,I2C_INTR_CTRL_REG) |
++ AST_I2CD_RX_DOWN_INTR_EN, I2C_INTR_CTRL_REG);
++ }
++ cmd |= AST_I2CD_M_S_RX_CMD_LAST;
++ }
++ }
++ ast_i2c_write(i2c_dev,
++ AST_I2CD_RX_BUF_END_ADDR_SET((i2c_dev->master_xfer_len-1))|
++ AST_I2CD_BUF_BASE_ADDR_SET((i2c_dev->req_page->page_addr_point)),
++ I2C_BUF_CTRL_REG);
++ ast_i2c_write(i2c_dev, cmd, I2C_CMD_REG);
++ dev_dbg(i2c_dev->dev, "rxfer size %d , cmd = %x \n",i2c_dev->master_xfer_len, cmd);
++ } else {
++ //Tx data
++ //next data write
++ cmd = AST_I2CD_M_TX_CMD | AST_I2CD_TX_BUFF_ENABLE;
++ if((i2c_dev->master_msgs->len - i2c_dev->master_xfer_cnt) > i2c_dev->req_page->page_size) {
++ i2c_dev->master_xfer_len = i2c_dev->req_page->page_size;
++ ast_i2c_write(i2c_dev, ast_i2c_read(i2c_dev,I2C_INTR_CTRL_REG) |
++ AST_I2CD_TX_ACK_INTR_EN, I2C_INTR_CTRL_REG);
++
++ } else {
++ i2c_dev->master_xfer_len = i2c_dev->master_msgs->len - i2c_dev->master_xfer_cnt;
++ if(i2c_dev->xfer_last == 1) {
++ dev_dbg(i2c_dev->dev, "last stop \n");
++ cmd |= AST_I2CD_M_STOP_CMD;
++ ast_i2c_write(i2c_dev, ast_i2c_read(i2c_dev,I2C_INTR_CTRL_REG) &
++ ~AST_I2CD_TX_ACK_INTR_EN, I2C_INTR_CTRL_REG);
++
++ } else {
++ ast_i2c_write(i2c_dev, ast_i2c_read(i2c_dev,I2C_INTR_CTRL_REG) |
++ AST_I2CD_TX_ACK_INTR_EN, I2C_INTR_CTRL_REG);
++ }
++ }
++
++ for(i = 0; i < i2c_dev->master_xfer_len; i++) {
++ if(i%4 == 0)
++ tx_buf[i/4] = 0;
++ tx_buf[i/4] |= (i2c_dev->master_msgs->buf[i2c_dev->master_xfer_cnt + i] << ((i%4)*8)) ;
++ }
++// printk("count %x \n",ast_i2c_read(i2c_dev,I2C_CMD_REG));
++ ast_i2c_write(i2c_dev,
++ AST_I2CD_TX_DATA_BUF_END_SET((i2c_dev->master_xfer_len - 1)) |
++ AST_I2CD_BUF_BASE_ADDR_SET(i2c_dev->req_page->page_addr_point),
++ I2C_BUF_CTRL_REG);
++
++ ast_i2c_write(i2c_dev, cmd , I2C_CMD_REG);
++ dev_dbg(i2c_dev->dev, "txfer size %d , cmd = %x \n",i2c_dev->master_xfer_len, cmd);
++ }
++ } else {
++ //should send next msg
++ if(i2c_dev->master_xfer_cnt != i2c_dev->master_msgs->len)
++ printk("complete rx ... ERROR \n");
++
++ dev_dbg(i2c_dev->dev, "ast_i2c_do_byte_xfer complete \n");
++ i2c_dev->cmd_err = 0;
++ complete(&i2c_dev->cmd_complete);
++ }
++
++ }
++}
++static void ast_i2c_do_byte_xfer(struct ast_i2c_dev *i2c_dev)
++{
++ u8 *xfer_buf;
++ u32 cmd = 0;
++
++ i2c_dev->master_xfer_mode = BYTE_XFER;
++ i2c_dev->master_xfer_len = 1;
++
++ i2c_dev->slave_xfer_mode = BYTE_XFER;
++ i2c_dev->slave_xfer_len = 1;
++
++ if(i2c_dev->slave_operation == 1) {
++ dev_dbg(i2c_dev->dev,"S cnt %d, xf len %d \n",i2c_dev->slave_xfer_cnt, i2c_dev->slave_msgs->len);
++ if(i2c_dev->slave_msgs->flags & I2C_M_RD) {
++ //READ <-- TX
++ dev_dbg(i2c_dev->dev, "(<--) slave(tx) buf %d [%x]\n", i2c_dev->slave_xfer_cnt, i2c_dev->slave_msgs->buf[i2c_dev->slave_xfer_cnt]);
++ ast_i2c_write(i2c_dev, i2c_dev->slave_msgs->buf[i2c_dev->slave_xfer_cnt], I2C_BYTE_BUF_REG);
++ ast_i2c_write(i2c_dev, AST_I2CD_S_TX_CMD, I2C_CMD_REG);
++ } else {
++ // Write -->Rx
++ //no need to handle in byte mode
++ dev_dbg(i2c_dev->dev, "(-->) slave(rx) BYTE do nothing\n");
++
++ }
++ } else {
++ dev_dbg(i2c_dev->dev,"M cnt %d, xf len %d \n",i2c_dev->master_xfer_cnt, i2c_dev->master_msgs->len);
++ if(i2c_dev->master_xfer_cnt == -1) {
++ //first start
++ dev_dbg(i2c_dev->dev, " %sing %d byte%s %s 0x%02x\n",
++ i2c_dev->master_msgs->flags & I2C_M_RD ? "read" : "write",
++ i2c_dev->master_msgs->len, i2c_dev->master_msgs->len > 1 ? "s" : "",
++ i2c_dev->master_msgs->flags & I2C_M_RD ? "from" : "to", i2c_dev->master_msgs->addr);
++
++
++ if(i2c_dev->master_msgs->flags & I2C_M_RD)
++ ast_i2c_write(i2c_dev, (i2c_dev->master_msgs->addr <<1) |0x1, I2C_BYTE_BUF_REG);
++ else
++ ast_i2c_write(i2c_dev, (i2c_dev->master_msgs->addr <<1), I2C_BYTE_BUF_REG);
++
++ ast_i2c_write(i2c_dev, ast_i2c_read(i2c_dev,I2C_INTR_CTRL_REG) |
++ AST_I2CD_TX_ACK_INTR_EN, I2C_INTR_CTRL_REG);
++
++ ast_i2c_write(i2c_dev, AST_I2CD_M_TX_CMD | AST_I2CD_M_START_CMD, I2C_CMD_REG);
++
++
++ } else if (i2c_dev->master_xfer_cnt < i2c_dev->master_msgs->len){
++ xfer_buf = i2c_dev->master_msgs->buf;
++ if(i2c_dev->master_msgs->flags & I2C_M_RD) {
++ //Rx data
++ cmd = AST_I2CD_M_RX_CMD;
++ if((i2c_dev->master_msgs->flags & I2C_M_RECV_LEN) && (i2c_dev->master_xfer_cnt == 0)) {
++ dev_dbg(i2c_dev->dev, "I2C_M_RECV_LEN \n");
++ ast_i2c_write(i2c_dev, ast_i2c_read(i2c_dev,I2C_INTR_CTRL_REG) |
++ AST_I2CD_RX_DOWN_INTR_EN, I2C_INTR_CTRL_REG);
++
++ } else if((i2c_dev->xfer_last == 1) && (i2c_dev->master_xfer_cnt + 1 == i2c_dev->master_msgs->len)) {
++ cmd |= AST_I2CD_M_S_RX_CMD_LAST | AST_I2CD_M_STOP_CMD;
++ // disable rx_dwn isr
++ ast_i2c_write(i2c_dev, ast_i2c_read(i2c_dev,I2C_INTR_CTRL_REG) &
++ ~AST_I2CD_RX_DOWN_INTR_EN, I2C_INTR_CTRL_REG);
++ } else {
++ ast_i2c_write(i2c_dev, ast_i2c_read(i2c_dev,I2C_INTR_CTRL_REG) |
++ AST_I2CD_RX_DOWN_INTR_EN, I2C_INTR_CTRL_REG);
++ }
++
++ dev_dbg(i2c_dev->dev, "(<--) rx byte, cmd = %x \n",cmd);
++
++ ast_i2c_write(i2c_dev, cmd, I2C_CMD_REG);
++
++
++ } else {
++ //Tx data
++ dev_dbg(i2c_dev->dev, "(-->) xfer byte data index[%02x]:%02x \n",i2c_dev->master_xfer_cnt, *(xfer_buf + i2c_dev->master_xfer_cnt));
++ ast_i2c_write(i2c_dev, *(xfer_buf + i2c_dev->master_xfer_cnt), I2C_BYTE_BUF_REG);
++ if((i2c_dev->xfer_last == 1) && (i2c_dev->master_xfer_cnt + 1 == i2c_dev->master_msgs->len)) {
++ ast_i2c_write(i2c_dev, ast_i2c_read(i2c_dev,I2C_INTR_CTRL_REG) &
++ ~AST_I2CD_TX_ACK_INTR_EN, I2C_INTR_CTRL_REG);
++ ast_i2c_write(i2c_dev, AST_I2CD_M_TX_CMD | AST_I2CD_M_STOP_CMD, I2C_CMD_REG);
++ } else {
++ ast_i2c_write(i2c_dev, ast_i2c_read(i2c_dev,I2C_INTR_CTRL_REG) |
++ AST_I2CD_TX_ACK_INTR_EN, I2C_INTR_CTRL_REG);
++ ast_i2c_write(i2c_dev, AST_I2CD_M_TX_CMD, I2C_CMD_REG);
++ }
++ }
++
++ } else {
++ //should send next msg
++ if(i2c_dev->master_xfer_cnt != i2c_dev->master_msgs->len)
++ printk("CNT ERROR \n");
++
++ dev_dbg(i2c_dev->dev, "ast_i2c_do_byte_xfer complete \n");
++ i2c_dev->cmd_err = 0;
++ complete(&i2c_dev->cmd_complete);
++
++ }
++ }
++
++}
++
++static void ast_i2c_slave_xfer_done(struct ast_i2c_dev *i2c_dev)
++{
++ u32 xfer_len;
++ int i;
++ u8 *rx_buf;
++
++ dev_dbg(i2c_dev->dev, "ast_i2c_slave_xfer_done [%d]\n",i2c_dev->slave_xfer_mode);
++
++ if (i2c_dev->slave_msgs->flags & I2C_M_RD) {
++ //tx done , only check tx count ...
++ if(i2c_dev->master_xfer_mode == BYTE_XFER) {
++ xfer_len = 1;
++ } else if (i2c_dev->master_xfer_mode == BUFF_XFER) {
++ xfer_len = AST_I2CD_TX_DATA_BUF_GET(ast_i2c_read(i2c_dev, I2C_BUF_CTRL_REG));
++ xfer_len++;
++ dev_dbg(i2c_dev->dev,"S tx buff done len %d \n",xfer_len);
++ } else {
++ //DMA mode
++ xfer_len = ast_i2c_read(i2c_dev, I2C_DMA_LEN_REG);
++ if(xfer_len == 0)
++ xfer_len = i2c_dev->slave_xfer_len;
++ else
++ xfer_len = i2c_dev->slave_xfer_len - xfer_len - 1;
++
++ dev_dbg(i2c_dev->dev,"S tx rx dma done len %d \n",xfer_len);
++ }
++
++ } else {
++ //rx done
++ if(i2c_dev->slave_xfer_mode == BYTE_XFER) {
++ //TODO
++ xfer_len = 1;
++ if(i2c_dev->slave_event == I2C_SLAVE_EVENT_STOP) {
++ i2c_dev->slave_msgs->buf[i2c_dev->slave_xfer_cnt] = 0;
++ i2c_dev->slave_msgs->len = i2c_dev->slave_xfer_cnt;
++ } else {
++ i2c_dev->slave_msgs->buf[i2c_dev->slave_xfer_cnt] = ast_i2c_read(i2c_dev,I2C_BYTE_BUF_REG) >> 8;
++ }
++ dev_dbg(i2c_dev->dev,"rx buff %d, [%x] \n",i2c_dev->slave_xfer_cnt ,i2c_dev->slave_msgs->buf[i2c_dev->slave_xfer_cnt]);
++ } else if (i2c_dev->master_xfer_mode == BUFF_XFER) {
++ xfer_len = AST_I2CD_RX_BUF_ADDR_GET(ast_i2c_read(i2c_dev, I2C_BUF_CTRL_REG));
++ if(xfer_len == 0)
++ xfer_len = AST_I2C_PAGE_SIZE;
++
++ dev_dbg(i2c_dev->dev,"rx buff done len %d \n",xfer_len);
++
++ rx_buf = (u8 *)i2c_dev->req_page->page_addr;
++
++ for(i=0;i<xfer_len;i++) {
++ i2c_dev->slave_msgs->buf[i2c_dev->slave_xfer_cnt+i] = rx_buf[i];
++ dev_dbg(i2c_dev->dev,"%d, [%x] \n",i2c_dev->slave_xfer_cnt+i ,i2c_dev->slave_msgs->buf[i2c_dev->slave_xfer_cnt+i]);
++ }
++
++ } else {
++ //RX DMA DOWN
++ xfer_len = ast_i2c_read(i2c_dev, I2C_DMA_LEN_REG);
++ if(xfer_len == 0)
++ xfer_len = i2c_dev->slave_xfer_len;
++ else
++ xfer_len = i2c_dev->slave_xfer_len - xfer_len - 1;
++
++ dev_dbg(i2c_dev->dev, " rx dma done len %d \n", xfer_len);
++
++ for(i=0;i<xfer_len;i++) {
++ i2c_dev->slave_msgs->buf[i2c_dev->slave_xfer_cnt+i] = i2c_dev->dma_buf[i];
++ dev_dbg(i2c_dev->dev,"%d, [%x] \n",i2c_dev->slave_xfer_cnt+i ,i2c_dev->slave_msgs->buf[i2c_dev->slave_xfer_cnt+i]);
++ }
++ }
++
++ }
++
++ if(xfer_len !=i2c_dev->slave_xfer_len) {
++ //TODO..
++ printk(" **slave xfer error ====\n");
++ //should goto stop....
++ } else
++ i2c_dev->slave_xfer_cnt += i2c_dev->slave_xfer_len;
++
++
++ if((i2c_dev->slave_event == I2C_SLAVE_EVENT_NACK) || (i2c_dev->slave_event == I2C_SLAVE_EVENT_STOP)) {
++#ifdef CONFIG_AST_I2C_SLAVE_RDWR
++ ast_i2c_slave_rdwr_xfer(i2c_dev);
++#else
++ i2c_dev->ast_i2c_data->slave_xfer(i2c_dev->slave_event, &(i2c_dev->slave_msgs));
++#endif
++ i2c_dev->slave_xfer_cnt = 0;
++ } else {
++ if(i2c_dev->slave_xfer_cnt == i2c_dev->slave_msgs->len) {
++ dev_dbg(i2c_dev->dev,"slave next msgs \n");
++#ifdef CONFIG_AST_I2C_SLAVE_RDWR
++ ast_i2c_slave_rdwr_xfer(i2c_dev);
++#else
++ i2c_dev->ast_i2c_data->slave_xfer(i2c_dev->slave_event, &(i2c_dev->slave_msgs));
++#endif
++
++ i2c_dev->slave_xfer_cnt = 0;
++ }
++ i2c_dev->do_slave_xfer(i2c_dev);
++ }
++
++
++ if(AST_I2CD_IDLE == i2c_dev->state) {
++ dev_dbg(i2c_dev->dev,"** Slave go IDLE **\n");
++ i2c_dev->slave_operation = 0;
++
++ if(i2c_dev->slave_xfer_mode == BUFF_XFER) {
++ i2c_dev->ast_i2c_data->free_pool_buff_page(i2c_dev->req_page);
++ }
++
++ }
++
++}
++
++//TX/Rx Done
++static void ast_i2c_master_xfer_done(struct ast_i2c_dev *i2c_dev)
++{
++ u32 xfer_len;
++ int i;
++ u8 *pool_buf;
++
++ dev_dbg(i2c_dev->dev, "ast_i2c_master_xfer_done mode[%d]\n",i2c_dev->master_xfer_mode);
++
++ if (i2c_dev->master_msgs->flags & I2C_M_RD) {
++ if(i2c_dev->master_xfer_cnt == -1) {
++ xfer_len = 1;
++ goto next_xfer;
++ }
++ if(i2c_dev->master_xfer_mode == BYTE_XFER) {
++ if ((i2c_dev->master_msgs->flags & I2C_M_RECV_LEN) && (i2c_dev->blk_r_flag == 0)) {
++ i2c_dev->master_msgs->len += (ast_i2c_read(i2c_dev,I2C_BYTE_BUF_REG) & AST_I2CD_RX_BYTE_BUFFER) >> 8;
++ i2c_dev->blk_r_flag = 1;
++ dev_dbg(i2c_dev->dev, "I2C_M_RECV_LEN %d \n", i2c_dev->master_msgs->len -1);
++ }
++ xfer_len = 1;
++ i2c_dev->master_msgs->buf[i2c_dev->master_xfer_cnt] = (ast_i2c_read(i2c_dev,I2C_BYTE_BUF_REG) & AST_I2CD_RX_BYTE_BUFFER) >> 8;
++ } else if (i2c_dev->master_xfer_mode == BUFF_XFER) {
++ pool_buf = (u8 *)i2c_dev->req_page->page_addr;
++ xfer_len = AST_I2CD_RX_BUF_ADDR_GET(ast_i2c_read(i2c_dev, I2C_BUF_CTRL_REG));
++
++ if(xfer_len == 0)
++ xfer_len = AST_I2C_PAGE_SIZE;
++
++ for(i = 0; i< xfer_len; i++) {
++ i2c_dev->master_msgs->buf[i2c_dev->master_xfer_cnt + i] = pool_buf[i];
++ dev_dbg(i2c_dev->dev, "rx %d buff[%x]\n",i2c_dev->master_xfer_cnt+i, i2c_dev->master_msgs->buf[i2c_dev->master_xfer_cnt+i]);
++ }
++
++ if ((i2c_dev->master_msgs->flags & I2C_M_RECV_LEN) && (i2c_dev->blk_r_flag == 0)) {
++ i2c_dev->master_msgs->len += pool_buf[0];
++ i2c_dev->blk_r_flag = 1;
++ dev_dbg(i2c_dev->dev, "I2C_M_RECV_LEN %d \n", i2c_dev->master_msgs->len -1);
++ }
++ } else {
++ //DMA Mode
++ xfer_len = ast_i2c_read(i2c_dev, I2C_DMA_LEN_REG);
++
++ if(xfer_len == 0)
++ xfer_len = i2c_dev->master_xfer_len;
++ else
++ xfer_len = i2c_dev->master_xfer_len - xfer_len - 1;
++
++ for(i = 0; i < xfer_len; i++) {
++ i2c_dev->master_msgs->buf[i2c_dev->master_xfer_cnt + i] = i2c_dev->dma_buf[i];
++ dev_dbg(i2c_dev->dev, "buf[%x] \n", i2c_dev->dma_buf[i]);
++ dev_dbg(i2c_dev->dev, "buf[%x] \n", i2c_dev->dma_buf[i+1]);
++ }
++
++ if ((i2c_dev->master_msgs->flags & I2C_M_RECV_LEN) && (i2c_dev->blk_r_flag == 0)) {
++ i2c_dev->master_msgs->len += i2c_dev->dma_buf[0];
++ i2c_dev->blk_r_flag = 1;
++ dev_dbg(i2c_dev->dev, "I2C_M_RECV_LEN %d \n", i2c_dev->master_msgs->len -1);
++ }
++
++ }
++
++ }else {
++ if(i2c_dev->master_xfer_mode == BYTE_XFER) {
++ xfer_len = 1;
++ } else if(i2c_dev->master_xfer_mode == BUFF_XFER) {
++ xfer_len = AST_I2CD_TX_DATA_BUF_GET(ast_i2c_read(i2c_dev, I2C_BUF_CTRL_REG));
++ xfer_len++;
++ dev_dbg(i2c_dev->dev,"tx buff done len %d \n",xfer_len);
++ } else {
++ //DMA
++ xfer_len = ast_i2c_read(i2c_dev, I2C_DMA_LEN_REG);
++ if(xfer_len == 0)
++ xfer_len = i2c_dev->master_xfer_len;
++ else
++ xfer_len = i2c_dev->master_xfer_len - xfer_len - 1;
++
++ dev_dbg(i2c_dev->dev,"tx dma done len %d \n",xfer_len);
++ }
++ }
++
++next_xfer:
++
++ if(xfer_len !=i2c_dev->master_xfer_len) {
++ //TODO..
++ printk(" ** xfer error \n");
++ //should goto stop....
++ i2c_dev->cmd_err = 1;
++ goto done_out;
++ } else
++ i2c_dev->master_xfer_cnt += i2c_dev->master_xfer_len;
++
++ if(i2c_dev->master_xfer_cnt != i2c_dev->master_msgs->len) {
++ dev_dbg(i2c_dev->dev,"do next cnt \n");
++ i2c_dev->do_master_xfer(i2c_dev);
++ } else {
++#if 0
++ int i;
++ printk(" ===== \n");
++ for(i=0;i<i2c_dev->master_msgs->len;i++)
++ printk("rx buf i,[%x]\n",i,i2c_dev->master_msgs->buf[i]);
++ printk(" ===== \n");
++#endif
++ i2c_dev->cmd_err = 0;
++
++done_out:
++ dev_dbg(i2c_dev->dev,"msgs complete \n");
++ complete(&i2c_dev->cmd_complete);
++ }
++}
++
++static void ast_i2c_slave_addr_match(struct ast_i2c_dev *i2c_dev)
++{
++ u8 match;
++
++ i2c_dev->slave_operation = 1;
++ i2c_dev->slave_xfer_cnt = 0;
++ match = ast_i2c_read(i2c_dev,I2C_BYTE_BUF_REG) >> 8;
++ i2c_dev->slave_msgs->buf[0] = match;
++ dev_dbg(i2c_dev->dev, "S Start Addr match [%x] \n",match);
++
++
++ if(match & 1) {
++ i2c_dev->slave_event = I2C_SLAVE_EVENT_START_READ;
++ } else {
++ i2c_dev->slave_event = I2C_SLAVE_EVENT_START_WRITE;
++ }
++
++#ifdef CONFIG_AST_I2C_SLAVE_RDWR
++ ast_i2c_slave_rdwr_xfer(i2c_dev);
++ i2c_dev->slave_msgs->buf[0] = match;
++ i2c_dev->slave_xfer_cnt = 1;
++#else
++ i2c_dev->ast_i2c_data->slave_xfer(i2c_dev->slave_event, &(i2c_dev->slave_msgs));
++ i2c_dev->slave_xfer_cnt = 0;
++#endif
++
++ //request
++ if(i2c_dev->ast_i2c_data->slave_dma == BYTE_MODE)
++ i2c_dev->do_slave_xfer = ast_i2c_do_byte_xfer;
++ else if (i2c_dev->ast_i2c_data->slave_dma == DMA_MODE)
++ i2c_dev->do_slave_xfer = ast_i2c_do_dma_xfer;
++ else {
++ if(i2c_dev->ast_i2c_data->request_pool_buff_page(&(i2c_dev->req_page)) == 0)
++ i2c_dev->do_slave_xfer = ast_i2c_do_pool_xfer;
++ else
++ i2c_dev->do_slave_xfer = ast_i2c_do_byte_xfer;
++ }
++
++ i2c_dev->do_slave_xfer(i2c_dev);
++
++}
++
++static irqreturn_t i2c_ast_handler(int this_irq, void *dev_id)
++{
++ u32 sts;
++
++ struct ast_i2c_dev *i2c_dev = dev_id;
++ u32 isr_sts = readl(i2c_dev->ast_i2c_data->reg_gr);
++
++ if(!(isr_sts & (1<< i2c_dev->bus_id)))
++ return IRQ_NONE;
++
++ i2c_dev->state = (ast_i2c_read(i2c_dev,I2C_CMD_REG) >> 19) & 0xf;
++ sts = ast_i2c_read(i2c_dev,I2C_INTR_STS_REG);
++// printk("ISR : %x , sts [%x]\n",sts , xfer_sts);
++// dev_dbg(i2c_dev->dev,"ISR : %x , sts [%x]\n",sts , xfer_sts);
++
++// dev_dbg(i2c_dev->dev,"sts machine %x, slave_op %d \n", xfer_sts,i2c_dev->slave_operation);
++
++ if(AST_I2CD_INTR_STS_SMBUS_ALT & sts) {
++ dev_dbg(i2c_dev->dev, "M clear isr: AST_I2CD_INTR_STS_SMBUS_ALT= %x\n",sts);
++ //Disable ALT INT
++ ast_i2c_write(i2c_dev, ast_i2c_read(i2c_dev, I2C_INTR_CTRL_REG) &
++ ~AST_I2CD_SMBUS_ALT_INTR_EN,
++ I2C_INTR_CTRL_REG);
++ ast_i2c_write(i2c_dev, AST_I2CD_INTR_STS_SMBUS_ALT, I2C_INTR_STS_REG);
++ ast_master_alert_recv(i2c_dev);
++ sts &= ~AST_I2CD_SMBUS_ALT_INTR_EN;
++ }
++
++ switch(sts) {
++ case AST_I2CD_INTR_STS_TX_ACK:
++ if(i2c_dev->slave_operation == 1) {
++ i2c_dev->slave_event = I2C_SLAVE_EVENT_READ;
++ ast_i2c_slave_xfer_done(i2c_dev);
++ dev_dbg(i2c_dev->dev, "S clear isr: AST_I2CD_INTR_STS_TX_ACK = %x\n",sts);
++ ast_i2c_write(i2c_dev, AST_I2CD_INTR_STS_TX_ACK, I2C_INTR_STS_REG);
++ } else {
++ dev_dbg(i2c_dev->dev, "M clear isr: AST_I2CD_INTR_STS_TX_ACK = %x\n",sts);
++ ast_i2c_write(i2c_dev, AST_I2CD_INTR_STS_TX_ACK, I2C_INTR_STS_REG);
++ ast_i2c_master_xfer_done(i2c_dev);
++ }
++ break;
++ case AST_I2CD_INTR_STS_TX_ACK | AST_I2CD_INTR_STS_NORMAL_STOP:
++ if((i2c_dev->xfer_last == 1) && (i2c_dev->slave_operation == 0)) {
++ dev_dbg(i2c_dev->dev, "M clear isr: AST_I2CD_INTR_STS_TX_ACK | AST_I2CD_INTR_STS_NORMAL_STOP= %x\n",sts);
++ ast_i2c_write(i2c_dev, AST_I2CD_INTR_STS_TX_ACK | AST_I2CD_INTR_STS_NORMAL_STOP, I2C_INTR_STS_REG);
++ //take care
++ ast_i2c_write(i2c_dev, ast_i2c_read(i2c_dev,I2C_INTR_CTRL_REG) |
++ AST_I2CD_TX_ACK_INTR_EN, I2C_INTR_CTRL_REG);
++ ast_i2c_master_xfer_done(i2c_dev);
++
++ } else {
++ printk("TODO ...\n");
++ }
++ break;
++
++ case AST_I2CD_INTR_STS_TX_NAK:
++ if(i2c_dev->slave_operation == 1) {
++ i2c_dev->slave_event = I2C_SLAVE_EVENT_NACK;
++ ast_i2c_slave_xfer_done(i2c_dev);
++ dev_dbg(i2c_dev->dev, "S clear isr: AST_I2CD_INTR_STS_TX_NAK = %x\n",sts);
++ ast_i2c_write(i2c_dev, AST_I2CD_INTR_STS_TX_NAK, I2C_INTR_STS_REG);
++
++ } else {
++ dev_dbg(i2c_dev->dev, "M clear isr: AST_I2CD_INTR_STS_TX_NAK = %x\n",sts);
++ ast_i2c_write(i2c_dev, AST_I2CD_INTR_STS_TX_NAK, I2C_INTR_STS_REG);
++ if(i2c_dev->master_msgs->flags == I2C_M_IGNORE_NAK) {
++ dev_dbg(i2c_dev->dev, "I2C_M_IGNORE_NAK next send\n");
++ i2c_dev->cmd_err = 0;
++ } else {
++ dev_dbg(i2c_dev->dev, "NAK error\n");
++ i2c_dev->cmd_err = AST_I2CD_INTR_STS_TX_NAK;
++ }
++ complete(&i2c_dev->cmd_complete);
++ }
++ break;
++
++ case AST_I2CD_INTR_STS_TX_NAK | AST_I2CD_INTR_STS_NORMAL_STOP:
++ if(i2c_dev->slave_operation == 1) {
++ printk("SLAVE TODO .... \n");
++
++ } else {
++ dev_dbg(i2c_dev->dev, "M clear isr: AST_I2CD_INTR_STS_TX_NAK| AST_I2CD_INTR_STS_NORMAL_STOP = %x\n",sts);
++ ast_i2c_write(i2c_dev, AST_I2CD_INTR_STS_TX_NAK | AST_I2CD_INTR_STS_NORMAL_STOP, I2C_INTR_STS_REG);
++ dev_dbg(i2c_dev->dev, "M TX NAK | NORMAL STOP \n");
++ i2c_dev->cmd_err = AST_I2CD_INTR_STS_TX_NAK | AST_I2CD_INTR_STS_NORMAL_STOP;
++ complete(&i2c_dev->cmd_complete);
++ }
++ break;
++
++ //Issue : Workaround for I2C slave mode
++ case AST_I2CD_INTR_STS_TX_NAK | AST_I2CD_INTR_STS_SLAVE_MATCH:
++ if(i2c_dev->slave_operation == 1) {
++ i2c_dev->slave_event = I2C_SLAVE_EVENT_NACK;
++ ast_i2c_slave_xfer_done(i2c_dev);
++ ast_i2c_slave_addr_match(i2c_dev);
++ ast_i2c_write(i2c_dev, AST_I2CD_INTR_STS_TX_NAK | AST_I2CD_INTR_STS_SLAVE_MATCH , I2C_INTR_STS_REG);
++ } else {
++ printk("ERROR !!!!\n");
++ }
++ break;
++ case AST_I2CD_INTR_STS_RX_DOWN | AST_I2CD_INTR_STS_SLAVE_MATCH:
++ ast_i2c_slave_addr_match(i2c_dev);
++ dev_dbg(i2c_dev->dev, "S clear isr: AST_I2CD_INTR_STS_RX_DOWN | AST_I2CD_INTR_STS_SLAVE_MATCH = %x\n",sts);
++ ast_i2c_write(i2c_dev, AST_I2CD_INTR_STS_RX_DOWN | AST_I2CD_INTR_STS_SLAVE_MATCH, I2C_INTR_STS_REG);
++ break;
++
++ case AST_I2CD_INTR_STS_RX_DOWN:
++ if(i2c_dev->slave_operation == 1) {
++ i2c_dev->slave_event = I2C_SLAVE_EVENT_WRITE;
++ ast_i2c_slave_xfer_done(i2c_dev);
++ dev_dbg(i2c_dev->dev, "S clear isr: AST_I2CD_INTR_STS_RX_DOWN = %x\n",sts);
++ ast_i2c_write(i2c_dev, AST_I2CD_INTR_STS_RX_DOWN, I2C_INTR_STS_REG);
++ } else {
++ dev_dbg(i2c_dev->dev, "M clear isr: AST_I2CD_INTR_STS_RX_DOWN = %x\n",sts);
++ ast_i2c_write(i2c_dev, AST_I2CD_INTR_STS_RX_DOWN, I2C_INTR_STS_REG);
++ ast_i2c_master_xfer_done(i2c_dev);
++
++ }
++ break;
++
++ case AST_I2CD_INTR_STS_NORMAL_STOP:
++ if(i2c_dev->slave_operation == 1) {
++ i2c_dev->slave_event = I2C_SLAVE_EVENT_STOP;
++ ast_i2c_slave_xfer_done(i2c_dev);
++ dev_dbg(i2c_dev->dev, "S clear isr: AST_I2CD_INTR_STS_NORMAL_STOP = %x\n",sts);
++ ast_i2c_write(i2c_dev, AST_I2CD_INTR_STS_NORMAL_STOP, I2C_INTR_STS_REG);
++ dev_dbg(i2c_dev->dev, "state [%x] \n",i2c_dev->state);
++ } else {
++ dev_dbg(i2c_dev->dev, "M clear isr: AST_I2CD_INTR_STS_NORMAL_STOP = %x\n",sts);
++ ast_i2c_write(i2c_dev, AST_I2CD_INTR_STS_NORMAL_STOP, I2C_INTR_STS_REG);
++ i2c_dev->cmd_err = 0;
++ complete(&i2c_dev->cmd_complete);
++ }
++ break;
++ case (AST_I2CD_INTR_STS_RX_DOWN | AST_I2CD_INTR_STS_NORMAL_STOP):
++ if((i2c_dev->xfer_last == 1) && (i2c_dev->slave_operation == 0)) {
++ dev_dbg(i2c_dev->dev, "M clear isr: AST_I2CD_INTR_STS_RX_DOWN | AST_I2CD_INTR_STS_NORMAL_STOP = %x\n",sts);
++ ast_i2c_write(i2c_dev, AST_I2CD_INTR_STS_RX_DOWN | AST_I2CD_INTR_STS_NORMAL_STOP, I2C_INTR_STS_REG);
++ //take care
++ ast_i2c_write(i2c_dev, ast_i2c_read(i2c_dev,I2C_INTR_CTRL_REG) |
++ AST_I2CD_RX_DOWN_INTR_EN, I2C_INTR_CTRL_REG);
++ ast_i2c_master_xfer_done(i2c_dev);
++ } else {
++ printk("TODO .. .. ..\n");
++ }
++ break;
++ case AST_I2CD_INTR_STS_ARBIT_LOSS:
++ dev_dbg(i2c_dev->dev, "M clear isr: AST_I2CD_INTR_STS_ARBIT_LOSS = %x\n",sts);
++ ast_i2c_write(i2c_dev, AST_I2CD_INTR_STS_ARBIT_LOSS, I2C_INTR_STS_REG);
++ i2c_dev->cmd_err = AST_I2CD_INTR_STS_ARBIT_LOSS;
++ complete(&i2c_dev->cmd_complete);
++ break;
++ case AST_I2CD_INTR_STS_ABNORMAL:
++ i2c_dev->cmd_err = AST_I2CD_INTR_STS_ABNORMAL;
++ complete(&i2c_dev->cmd_complete);
++ break;
++ case AST_I2CD_INTR_STS_SCL_TO:
++ i2c_dev->cmd_err = AST_I2CD_INTR_STS_SCL_TO;
++ complete(&i2c_dev->cmd_complete);
++
++ break;
++ case AST_I2CD_INTR_STS_GCALL_ADDR:
++ i2c_dev->cmd_err = AST_I2CD_INTR_STS_GCALL_ADDR;
++ complete(&i2c_dev->cmd_complete);
++
++ break;
++ case AST_I2CD_INTR_STS_SMBUS_DEF_ADDR:
++ break;
++ case AST_I2CD_INTR_STS_SMBUS_DEV_ALT:
++
++ break;
++
++ case AST_I2CD_INTR_STS_SMBUS_ARP_ADDR:
++ break;
++ case AST_I2CD_INTR_STS_SDA_DL_TO:
++ break;
++ case AST_I2CD_INTR_STS_BUS_RECOVER:
++ dev_dbg(i2c_dev->dev, "M clear isr: AST_I2CD_INTR_STS_BUS_RECOVER= %x\n",sts);
++ ast_i2c_write(i2c_dev, AST_I2CD_INTR_STS_BUS_RECOVER, I2C_INTR_STS_REG);
++ i2c_dev->cmd_err = 0;
++ complete(&i2c_dev->cmd_complete);
++ break;
++ default:
++ if(sts)
++ printk("GR %x : No one care : %x, bus_id %d\n",i2c_dev->ast_i2c_data->reg_gr, sts, i2c_dev->bus_id);
++ return IRQ_NONE;
++ }
++
++ return IRQ_HANDLED;
++
++}
++
++static int ast_i2c_do_msgs_xfer(struct ast_i2c_dev *i2c_dev, struct i2c_msg *msgs, int num)
++{
++ int i;
++ int ret = 1;
++
++ //request
++ if(i2c_dev->ast_i2c_data->master_dma == BYTE_MODE)
++ i2c_dev->do_master_xfer = ast_i2c_do_byte_xfer;
++ else if (i2c_dev->ast_i2c_data->master_dma == DMA_MODE)
++ i2c_dev->do_master_xfer = ast_i2c_do_dma_xfer;
++ else {
++ if(i2c_dev->ast_i2c_data->request_pool_buff_page(&(i2c_dev->req_page)) == 0)
++ i2c_dev->do_master_xfer = ast_i2c_do_pool_xfer;
++ else
++ i2c_dev->do_master_xfer = ast_i2c_do_byte_xfer;
++ }
++
++// printk("start xfer ret = %d \n",ret);
++
++ for (i=0; i < num; i++) {
++ i2c_dev->blk_r_flag = 0;
++ i2c_dev->master_msgs = &msgs[i];
++ if(num == i+1)
++ i2c_dev->xfer_last = 1;
++ else
++ i2c_dev->xfer_last = 0;
++
++ i2c_dev->blk_r_flag = 0;
++ init_completion(&i2c_dev->cmd_complete);
++
++ if(i2c_dev->master_msgs->flags & I2C_M_NOSTART)
++ i2c_dev->master_xfer_cnt = 0;
++ else
++ i2c_dev->master_xfer_cnt = -1;
++
++ i2c_dev->do_master_xfer(i2c_dev);
++
++ ret = wait_for_completion_interruptible_timeout(&i2c_dev->cmd_complete,
++ i2c_dev->adap.timeout*HZ);
++
++ if (ret == 0) {
++ dev_dbg(i2c_dev->dev, "controller timed out\n");
++ i2c_dev->state = (ast_i2c_read(i2c_dev,I2C_CMD_REG) >> 19) & 0xf;
++// printk("sts [%x], isr sts [%x] \n",i2c_dev->state, ast_i2c_read(i2c_dev,I2C_INTR_STS_REG));
++ ret = -ETIMEDOUT;
++ goto stop;
++ }
++
++ if(i2c_dev->cmd_err != 0) {
++ ret = -EAGAIN;
++ goto stop;
++ }
++
++ }
++
++ if(i2c_dev->cmd_err == 0) {
++ ret = num;
++ goto out;
++
++ }
++stop:
++ init_completion(&i2c_dev->cmd_complete);
++ ast_i2c_write(i2c_dev, AST_I2CD_M_STOP_CMD, I2C_CMD_REG);
++ wait_for_completion_interruptible_timeout(&i2c_dev->cmd_complete,
++ i2c_dev->adap.timeout*HZ);
++
++out:
++ //Free ..
++ if(i2c_dev->master_xfer_mode == BUFF_XFER) {
++ i2c_dev->ast_i2c_data->free_pool_buff_page(i2c_dev->req_page);
++
++ }
++ dev_dbg(i2c_dev->dev, "end xfer ret = %d, xfer mode[%d]\n",ret, i2c_dev->master_xfer_mode);
++ return ret;
++
++}
++
++static int ast_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)
++{
++ struct ast_i2c_dev *i2c_dev = adap->algo_data;
++ int ret, i;
++ int sts;
++
++ sts = ast_i2c_read(i2c_dev,I2C_CMD_REG);
++ dev_dbg(i2c_dev->dev, "state[%x],SCL[%d],SDA[%d],BUS[%d]\n", (sts >> 19) & 0xf, (sts >> 18) & 0x1,(sts >> 17) & 0x1,(sts >> 16) & 1);
++ /*
++ * Wait for the bus to become free.
++ */
++
++ ret = ast_i2c_wait_bus_not_busy(i2c_dev);
++ if (ret) {
++ dev_err(&i2c_dev->adap.dev, "i2c_ast: timeout waiting for bus free\n");
++ goto out;
++ }
++
++ for (i = adap->retries; i >= 0; i--) {
++
++ ret = ast_i2c_do_msgs_xfer(i2c_dev, msgs, num);
++ if (ret != -EAGAIN)
++ goto out;
++ dev_dbg(&adap->dev, "Retrying transmission [%d]\n",i);
++ udelay(100);
++ }
++
++ ret = -EREMOTEIO;
++out:
++
++ return ret;
++}
++
++static u32 ast_i2c_functionality(struct i2c_adapter *adap)
++{
++ return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL | I2C_FUNC_SMBUS_BLOCK_DATA;
++}
++
++static const struct i2c_algorithm i2c_ast_algorithm = {
++ .master_xfer = ast_i2c_xfer,
++#ifdef CONFIG_AST_I2C_SLAVE_RDWR
++ .slave_xfer = ast_i2c_slave_xfer,
++#endif
++ .functionality = ast_i2c_functionality,
++};
++
++static int ast_i2c_probe(struct platform_device *pdev)
++{
++ struct ast_i2c_dev *i2c_dev;
++ struct resource *res;
++ int ret;
++
++ dev_dbg(&pdev->dev, "ast_i2c_probe \n");
++
++ i2c_dev = kzalloc(sizeof(struct ast_i2c_dev), GFP_KERNEL);
++ if (!i2c_dev) {
++ ret = -ENOMEM;
++ goto err_no_mem;
++ }
++
++ i2c_dev->ast_i2c_data = pdev->dev.platform_data;
++ if(i2c_dev->ast_i2c_data->master_dma == BUFF_MODE) {
++ dev_dbg(&pdev->dev, "use buffer pool mode 256\n");
++
++ } else if ((i2c_dev->ast_i2c_data->master_dma == DMA_MODE) || (i2c_dev->ast_i2c_data->slave_dma == DMA_MODE)) {
++ dev_dbg(&pdev->dev, "use dma mode \n");
++ if (!i2c_dev->dma_buf) {
++ i2c_dev->dma_buf = dma_alloc_coherent(NULL, AST_I2C_DMA_SIZE, &i2c_dev->dma_addr, GFP_KERNEL);
++ if (!i2c_dev->dma_buf) {
++ printk("unable to allocate tx Buffer memory\n");
++ ret = -ENOMEM;
++ goto err_no_dma;
++ }
++ if(i2c_dev->dma_addr%4 !=0) {
++ printk("not 4 byte boundary \n");
++ ret = -ENOMEM;
++ goto err_no_dma;
++ }
++// printk("dma_buf = [0x%x] dma_addr = [0x%x], please check 4byte boundary \n",i2c_dev->dma_buf,i2c_dev->dma_addr);
++ memset (i2c_dev->dma_buf, 0, AST_I2C_DMA_SIZE);
++ }
++
++ } else {
++ //master_mode 0: use byte mode
++ dev_dbg(&pdev->dev, "use default byte mode \n");
++ }
++
++ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
++ if (NULL == res) {
++ dev_err(&pdev->dev, "cannot get IORESOURCE_MEM\n");
++ ret = -ENOENT;
++ goto err_no_io_res;
++ }
++ if (!request_mem_region(res->start, resource_size(res), res->name)) {
++ dev_err(&pdev->dev, "cannot reserved region\n");
++ ret = -ENXIO;
++ goto err_no_io_res;
++ }
++
++ i2c_dev->reg_base = ioremap(res->start, resource_size(res));
++ if (!i2c_dev->reg_base) {
++ ret = -EIO;
++ goto release_mem;
++ }
++
++ i2c_dev->irq = platform_get_irq(pdev, 0);
++ if (i2c_dev->irq < 0) {
++ dev_err(&pdev->dev, "no irq specified\n");
++ ret = -ENOENT;
++ goto ereqirq;
++ }
++
++ i2c_dev->dev = &pdev->dev;
++
++#if defined (CONFIG_ARCH_AST1070)
++ if(i2c_dev->irq == IRQ_C0_I2C) {
++ i2c_dev->bus_id = pdev->id - NUM_BUS;
++ dev_dbg(&pdev->dev, "C0 :: pdev->id %d , i2c_dev->bus_id = %d, i2c_dev->irq =%d\n",pdev->id, i2c_dev->bus_id,i2c_dev->irq);
++#if (CONFIG_AST1070_NR >= 2)
++ } else if(i2c_dev->irq == IRQ_C1_I2C) {
++ i2c_dev->bus_id = pdev->id - (NUM_BUS + 8);
++ dev_dbg(&pdev->dev, "C1 :: pdev->id %d , i2c_dev->bus_id = %d, i2c_dev->irq =%d\n",pdev->id, i2c_dev->bus_id,i2c_dev->irq);
++#endif
++ } else {
++ i2c_dev->bus_id = pdev->id;
++ dev_dbg(&pdev->dev, "AST pdev->id %d , i2c_dev->bus_id = %d, i2c_dev->irq =%d\n",pdev->id, i2c_dev->bus_id,i2c_dev->irq);
++ }
++#else
++ i2c_dev->bus_id = pdev->id;
++#endif
++
++ /* Initialize the I2C adapter */
++ i2c_dev->adap.owner = THIS_MODULE;
++//TODO
++ i2c_dev->adap.retries = 0;
++
++// i2c_dev->adap.retries = 3;
++
++ i2c_dev->adap.timeout = 5;
++
++ i2c_dev->master_xfer_mode = BYTE_XFER;
++
++ /*
++ * If "pdev->id" is negative we consider it as zero.
++ * The reason to do so is to avoid sysfs names that only make
++ * sense when there are multiple adapters.
++ */
++ i2c_dev->adap.nr = pdev->id != -1 ? pdev->id : 0;
++ snprintf(i2c_dev->adap.name, sizeof(i2c_dev->adap.name), "ast_i2c.%u",
++ i2c_dev->adap.nr);
++
++ i2c_dev->slave_operation = 0;
++ i2c_dev->blk_r_flag = 0;
++ i2c_dev->adap.algo = &i2c_ast_algorithm;
++
++ ret = request_irq(i2c_dev->irq, i2c_ast_handler, IRQF_SHARED,
++ i2c_dev->adap.name, i2c_dev);
++ if (ret) {
++ printk(KERN_INFO "I2C: Failed request irq %d\n", i2c_dev->irq);
++ goto ereqirq;
++ }
++
++ ast_i2c_dev_init(i2c_dev);
++
++#ifdef CONFIG_AST_I2C_SLAVE_RDWR
++ ast_i2c_slave_buff_init(i2c_dev);
++#endif
++
++ i2c_dev->adap.algo_data = i2c_dev;
++ i2c_dev->adap.dev.parent = &pdev->dev;
++
++ i2c_dev->adap.id = pdev->id;
++
++ ret = i2c_add_numbered_adapter(&i2c_dev->adap);
++ if (ret < 0) {
++ printk(KERN_INFO "I2C: Failed to add bus\n");
++ goto eadapt;
++ }
++
++ platform_set_drvdata(pdev, i2c_dev);
++
++ printk(KERN_INFO "I2C: %s: AST I2C adapter [%d khz]\n",
++ i2c_dev->adap.dev.bus_id,i2c_dev->ast_i2c_data->bus_clk/1000);
++
++ return 0;
++
++eadapt:
++ free_irq(i2c_dev->irq, i2c_dev);
++ereqirq:
++ iounmap(i2c_dev->reg_base);
++
++release_mem:
++ release_mem_region(res->start, resource_size(res));
++err_no_io_res:
++err_no_dma:
++ kfree(i2c_dev);
++
++err_no_mem:
++ return ret;
++}
++
++static int ast_i2c_remove(struct platform_device *pdev)
++{
++ struct ast_i2c_dev *i2c_dev = platform_get_drvdata(pdev);
++ struct resource *res;
++
++ platform_set_drvdata(pdev, NULL);
++ i2c_del_adapter(&i2c_dev->adap);
++
++ free_irq(i2c_dev->irq, i2c_dev);
++
++ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
++ iounmap(i2c_dev->reg_base);
++ release_mem_region(res->start, res->end - res->start + 1);
++
++ kfree(i2c_dev);
++
++ return 0;
++}
++
++#ifdef CONFIG_PM
++static int ast_i2c_suspend(struct platform_device *pdev, pm_message_t state)
++{
++ //TODO
++// struct ast_i2c_dev *i2c_dev = platform_get_drvdata(pdev);
++ return 0;
++}
++
++static int ast_i2c_resume(struct platform_device *pdev)
++{
++ //TODO
++// struct ast_i2c_dev *i2c_dev = platform_get_drvdata(pdev);
++ //Should reset i2c ???
++ return 0;
++}
++#else
++#define ast_i2c_suspend NULL
++#define ast_i2c_resume NULL
++#endif
++
++static struct platform_driver i2c_ast_driver = {
++ .probe = ast_i2c_probe,
++ .remove = __devexit_p(ast_i2c_remove),
++ .suspend = ast_i2c_suspend,
++ .resume = ast_i2c_resume,
++ .driver = {
++ .name = "ast-i2c",
++ .owner = THIS_MODULE,
++ },
++};
++
++static int __init ast_i2c_init(void)
++{
++ return platform_driver_register(&i2c_ast_driver);
++}
++
++static void __exit ast_i2c_exit(void)
++{
++ platform_driver_unregister(&i2c_ast_driver);
++}
++//TODO : check module init sequence
++module_init(ast_i2c_init);
++module_exit(ast_i2c_exit);
++
++MODULE_AUTHOR("Ryan Chen <ryan_chen@aspeedtech.com>");
++MODULE_DESCRIPTION("ASPEED AST I2C Bus Driver");
++MODULE_LICENSE("GPL");
++MODULE_ALIAS("platform:ast_i2c");
+diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c
+index feb00df..5ced92c 100644
+--- a/drivers/i2c/i2c-core.c
++++ b/drivers/i2c/i2c-core.c
+@@ -1063,6 +1063,32 @@ int i2c_transfer(struct i2c_adapter * adap, struct i2c_msg *msgs, int num)
+ }
+ EXPORT_SYMBOL(i2c_transfer);
+
++#ifdef CONFIG_AST_I2C_SLAVE_RDWR
++int i2c_slave_transfer(struct i2c_adapter *adap, struct i2c_msg *msgs)
++{
++ unsigned long orig_jiffies;
++ int ret, try;
++
++ if (adap->algo->slave_xfer) {
++#ifdef DEBUG
++ dev_dbg(&adap->dev, "slave_xfer %c, addr=0x%02x, "
++ "len=%d\n", (msgs->flags & I2C_S_RD)
++ ? 'R' : 'W', msgs->addr, msgs->len);
++#endif
++ i2c_lock_adapter(adap);
++ ret = adap->algo->slave_xfer(adap, msgs);
++ i2c_unlock_adapter(adap);
++
++ return ret;
++ } else {
++ dev_dbg(&adap->dev, "I2C level transfers not supported\n");
++ return -EOPNOTSUPP;
++ }
++}
++EXPORT_SYMBOL(i2c_slave_transfer);
++
++#endif
++
+ /**
+ * i2c_master_send - issue a single I2C message in master transmit mode
+ * @client: Handle to slave device
+diff --git a/drivers/i2c/i2c-dev.c b/drivers/i2c/i2c-dev.c
+index c171988..7d1f7e9 100644
+--- a/drivers/i2c/i2c-dev.c
++++ b/drivers/i2c/i2c-dev.c
+@@ -37,6 +37,10 @@
+ #include <linux/smp_lock.h>
+ #include <asm/uaccess.h>
+
++#ifdef CONFIG_AST_I2C_SLAVE_RDWR
++#include <asm/arch/ast_i2c.h>
++#endif
++
+ static struct i2c_driver i2cdev_driver;
+
+ /*
+@@ -415,6 +419,11 @@ static long i2cdev_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+ case I2C_RDWR:
+ return i2cdev_ioctl_rdrw(client, arg);
+
++#ifdef CONFIG_AST_I2C_SLAVE_RDWR
++ case I2C_SLAVE_RDWR:
++ return i2cdev_ioctl_slave_rdrw(client->adapter, (struct i2c_msg __user *)arg);
++#endif
++
+ case I2C_SMBUS:
+ return i2cdev_ioctl_smbus(client, arg);
+
+diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c
+index fdd7c76..1928a42 100644
+--- a/drivers/mmc/core/mmc.c
++++ b/drivers/mmc/core/mmc.c
+@@ -113,20 +113,29 @@ static int mmc_decode_cid(struct mmc_card *card)
+ static int mmc_decode_csd(struct mmc_card *card)
+ {
+ struct mmc_csd *csd = &card->csd;
+- unsigned int e, m, csd_struct;
++ unsigned int e, m;
+ u32 *resp = card->raw_csd;
+
+ /*
+ * We only understand CSD structure v1.1 and v1.2.
+ * v1.2 has extra information in bits 15, 11 and 10.
++ * We also support eMMC v4.4 & v4.41.
+ */
++#if 0
+ csd_struct = UNSTUFF_BITS(resp, 126, 2);
+ if (csd_struct != 1 && csd_struct != 2) {
+ printk(KERN_ERR "%s: unrecognised CSD structure version %d\n",
+ mmc_hostname(card->host), csd_struct);
+ return -EINVAL;
+ }
+-
++#else
++ csd->structure = UNSTUFF_BITS(resp, 126, 2);
++ if (csd->structure == 0) {
++ printk(KERN_ERR "%s: unrecognised CSD structure version %d\n",
++ mmc_hostname(card->host), csd->structure);
++ return -EINVAL;
++ }
++#endif
+ csd->mmca_vsn = UNSTUFF_BITS(resp, 122, 4);
+ m = UNSTUFF_BITS(resp, 115, 4);
+ e = UNSTUFF_BITS(resp, 112, 3);
+@@ -207,6 +216,7 @@ static int mmc_read_ext_csd(struct mmc_card *card)
+ goto out;
+ }
+
++#if 0
+ ext_csd_struct = ext_csd[EXT_CSD_REV];
+ if (ext_csd_struct > 2) {
+ printk(KERN_ERR "%s: unrecognised EXT_CSD structure "
+@@ -215,7 +225,7 @@ static int mmc_read_ext_csd(struct mmc_card *card)
+ err = -EINVAL;
+ goto out;
+ }
+-
++
+ if (ext_csd_struct >= 2) {
+ card->ext_csd.sectors =
+ ext_csd[EXT_CSD_SEC_CNT + 0] << 0 |
+@@ -224,7 +234,8 @@ static int mmc_read_ext_csd(struct mmc_card *card)
+ ext_csd[EXT_CSD_SEC_CNT + 3] << 24;
+ if (card->ext_csd.sectors)
+ mmc_card_set_blockaddr(card);
+- }
++ }
++
+
+ switch (ext_csd[EXT_CSD_CARD_TYPE]) {
+ case EXT_CSD_CARD_TYPE_52 | EXT_CSD_CARD_TYPE_26:
+@@ -239,8 +250,86 @@ static int mmc_read_ext_csd(struct mmc_card *card)
+ "support any high-speed modes.\n",
+ mmc_hostname(card->host));
+ goto out;
++ }
++#else
++ /* Version is coded in the CSD_STRUCTURE byte in the EXT_CSD register */
++ if (card->csd.structure == 3) {
++ int ext_csd_struct = ext_csd[EXT_CSD_STRUCTURE];
++ if (ext_csd_struct > 2) {
++ printk(KERN_ERR "%s: unrecognised EXT_CSD structure "
++ "version %d\n", mmc_hostname(card->host),
++ ext_csd_struct);
++ err = -EINVAL;
++ goto out;
++ }
+ }
+
++ card->ext_csd.rev = ext_csd[EXT_CSD_REV];
++ if (card->ext_csd.rev > 6) {
++ printk(KERN_ERR "%s: unrecognised EXT_CSD revision %d\n",
++ mmc_hostname(card->host), card->ext_csd.rev);
++ err = -EINVAL;
++ goto out;
++ }
++
++ if (card->ext_csd.rev >= 2) {
++ card->ext_csd.sectors =
++ ext_csd[EXT_CSD_SEC_CNT + 0] << 0 |
++ ext_csd[EXT_CSD_SEC_CNT + 1] << 8 |
++ ext_csd[EXT_CSD_SEC_CNT + 2] << 16 |
++ ext_csd[EXT_CSD_SEC_CNT + 3] << 24;
++
++ /* Cards with density > 2GiB are sector addressed */
++ if (card->ext_csd.sectors > (2u * 1024 * 1024 * 1024) / 512)
++ mmc_card_set_blockaddr(card);
++ }
++
++ switch (ext_csd[EXT_CSD_CARD_TYPE] & EXT_CSD_CARD_TYPE_MASK) {
++ case EXT_CSD_CARD_TYPE_52 | EXT_CSD_CARD_TYPE_26:
++ card->ext_csd.hs_max_dtr = 52000000;
++ break;
++ case EXT_CSD_CARD_TYPE_26:
++ card->ext_csd.hs_max_dtr = 26000000;
++ break;
++ default:
++ /* MMC v4 spec says this cannot happen */
++ printk(KERN_WARNING "%s: card is mmc v4 but doesn't "
++ "support any high-speed modes.\n",
++ mmc_hostname(card->host));
++ }
++
++ if (card->ext_csd.rev >= 3) {
++ u8 sa_shift = ext_csd[EXT_CSD_S_A_TIMEOUT];
++
++ /* Sleep / awake timeout in 100ns units */
++ if (sa_shift > 0 && sa_shift <= 0x17)
++ card->ext_csd.sa_timeout =
++ 1 << ext_csd[EXT_CSD_S_A_TIMEOUT];
++ card->ext_csd.erase_group_def =
++ ext_csd[EXT_CSD_ERASE_GROUP_DEF];
++ card->ext_csd.hc_erase_timeout = 300 *
++ ext_csd[EXT_CSD_ERASE_TIMEOUT_MULT];
++ card->ext_csd.hc_erase_size =
++ ext_csd[EXT_CSD_HC_ERASE_GRP_SIZE] << 10;
++ }
++
++ if (card->ext_csd.rev >= 4) {
++ card->ext_csd.sec_trim_mult =
++ ext_csd[EXT_CSD_SEC_TRIM_MULT];
++ card->ext_csd.sec_erase_mult =
++ ext_csd[EXT_CSD_SEC_ERASE_MULT];
++ card->ext_csd.sec_feature_support =
++ ext_csd[EXT_CSD_SEC_FEATURE_SUPPORT];
++ card->ext_csd.trim_timeout = 300 *
++ ext_csd[EXT_CSD_TRIM_MULT];
++ }
++
++ if (ext_csd[EXT_CSD_ERASED_MEM_CONT])
++ card->erased_byte = 0xFF;
++ else
++ card->erased_byte = 0x0;
++#endif
++
+ out:
+ kfree(ext_csd);
+
+diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig
+index dfa585f..ce66df5 100644
+--- a/drivers/mmc/host/Kconfig
++++ b/drivers/mmc/host/Kconfig
+@@ -37,6 +37,17 @@ config MMC_SDHCI
+
+ If unsure, say N.
+
++config MMC_AST
++ tristate "ASPEED Secure Digital Host Controller Interface support"
++ depends on HAS_DMA
++ help
++ This selects the ASPEED Secure Digital Host Controller Interface.
++
++ If you have a controller with this interface, say Y or M here. You
++ also need to enable an appropriate bus interface.
++
++ If unsure, say N.
++
+ config MMC_SDHCI_PCI
+ tristate "SDHCI support on PCI bus"
+ depends on MMC_SDHCI && PCI
+diff --git a/drivers/mmc/host/Makefile b/drivers/mmc/host/Makefile
+index c794cc5..5078ba2 100644
+--- a/drivers/mmc/host/Makefile
++++ b/drivers/mmc/host/Makefile
+@@ -10,6 +10,7 @@ obj-$(CONFIG_MMC_ARMMMCI) += mmci.o
+ obj-$(CONFIG_MMC_PXA) += pxamci.o
+ obj-$(CONFIG_MMC_IMX) += imxmmc.o
+ obj-$(CONFIG_MMC_SDHCI) += sdhci.o
++obj-$(CONFIG_MMC_AST) += ast_sdhci.o
+ obj-$(CONFIG_MMC_SDHCI_PCI) += sdhci-pci.o
+ obj-$(CONFIG_MMC_RICOH_MMC) += ricoh_mmc.o
+ obj-$(CONFIG_MMC_WBSD) += wbsd.o
+diff --git a/drivers/mmc/host/ast_sdhci.c b/drivers/mmc/host/ast_sdhci.c
+new file mode 100644
+index 0000000..8b5d80d
+--- /dev/null
++++ b/drivers/mmc/host/ast_sdhci.c
+@@ -0,0 +1,1929 @@
++/*
++ * aspeed_sdhci.c - ASPEED Secure Digital Host Controller Interface driver
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or (at
++ * your option) any later version.
++ *
++ */
++
++#include <linux/delay.h>
++#include <linux/highmem.h>
++#include <linux/io.h>
++#include <linux/dma-mapping.h>
++#include <linux/scatterlist.h>
++#include <linux/platform_device.h>
++#include <mach/hardware.h>
++#include <mach/platform.h>
++
++#include <linux/leds.h>
++
++#include <linux/mmc/host.h>
++
++#include <plat/ast_sdhci.h>
++
++
++#define DRIVER_NAME "ast_sdhci"
++
++#define DBG(f, x...) \
++ pr_debug(DRIVER_NAME " [%s()]: " f, __func__,## x)
++
++static unsigned int debug_quirks = 0;
++
++struct ast_sdhc_platform_data *ast_sdhc_info;
++
++static void sdhci_prepare_data(struct sdhci_host *, struct mmc_data *);
++static void sdhci_finish_data(struct sdhci_host *);
++
++static void sdhci_send_command(struct sdhci_host *, struct mmc_command *);
++static void sdhci_finish_command(struct sdhci_host *);
++
++static void sdhci_dumpregs(struct sdhci_host *host)
++{
++ printk(KERN_DEBUG DRIVER_NAME ": ============== REGISTER DUMP ==============\n");
++
++ printk(KERN_DEBUG DRIVER_NAME ": Sys addr: 0x%08x | Version: 0x%08x\n",
++ readl(host->ioaddr + SDHCI_DMA_ADDRESS),
++ readw(host->ioaddr + SDHCI_HOST_VERSION));
++ printk(KERN_DEBUG DRIVER_NAME ": Blk size: 0x%08x | Blk cnt: 0x%08x\n",
++ readw(host->ioaddr + SDHCI_BLOCK_SIZE),
++ readw(host->ioaddr + SDHCI_BLOCK_COUNT));
++ printk(KERN_DEBUG DRIVER_NAME ": Argument: 0x%08x | Trn mode: 0x%08x\n",
++ readl(host->ioaddr + SDHCI_ARGUMENT),
++ readw(host->ioaddr + SDHCI_TRANSFER_MODE));
++ printk(KERN_DEBUG DRIVER_NAME ": Present: 0x%08x | Host ctl: 0x%08x\n",
++ readl(host->ioaddr + SDHCI_PRESENT_STATE),
++ readb(host->ioaddr + SDHCI_HOST_CONTROL));
++ printk(KERN_DEBUG DRIVER_NAME ": Power: 0x%08x | Blk gap: 0x%08x\n",
++ readb(host->ioaddr + SDHCI_POWER_CONTROL),
++ readb(host->ioaddr + SDHCI_BLOCK_GAP_CONTROL));
++ printk(KERN_DEBUG DRIVER_NAME ": Wake-up: 0x%08x | Clock: 0x%08x\n",
++ readb(host->ioaddr + SDHCI_WAKE_UP_CONTROL),
++ readw(host->ioaddr + SDHCI_CLOCK_CONTROL));
++ printk(KERN_DEBUG DRIVER_NAME ": Timeout: 0x%08x | Int stat: 0x%08x\n",
++ readb(host->ioaddr + SDHCI_TIMEOUT_CONTROL),
++ readl(host->ioaddr + SDHCI_INT_STATUS));
++ printk(KERN_DEBUG DRIVER_NAME ": Int enab: 0x%08x | Sig enab: 0x%08x\n",
++ readl(host->ioaddr + SDHCI_INT_ENABLE),
++ readl(host->ioaddr + SDHCI_SIGNAL_ENABLE));
++ printk(KERN_DEBUG DRIVER_NAME ": AC12 err: 0x%08x | Slot int: 0x%08x\n",
++ readw(host->ioaddr + SDHCI_ACMD12_ERR),
++ readw(host->ioaddr + SDHCI_SLOT_INT_STATUS));
++ printk(KERN_DEBUG DRIVER_NAME ": Caps: 0x%08x | Max curr: 0x%08x\n",
++ readl(host->ioaddr + SDHCI_CAPABILITIES),
++ readl(host->ioaddr + SDHCI_MAX_CURRENT));
++
++ printk(KERN_DEBUG DRIVER_NAME ": ===========================================\n");
++}
++
++/*****************************************************************************\
++ * *
++ * Low level functions *
++ * *
++\*****************************************************************************/
++
++static void sdhci_reset(struct sdhci_host *host, u8 mask)
++{
++ unsigned long timeout;
++
++ if (host->quirks & SDHCI_QUIRK_NO_CARD_NO_RESET) {
++ if (!(readl(host->ioaddr + SDHCI_PRESENT_STATE) &
++ SDHCI_CARD_PRESENT))
++ return;
++ }
++
++ writeb(mask, host->ioaddr + SDHCI_SOFTWARE_RESET);
++
++ if (mask & SDHCI_RESET_ALL)
++ host->clock = 0;
++
++ /* Wait max 100 ms */
++ timeout = 100;
++
++ /* hw clears the bit when it's done */
++ while (readb(host->ioaddr + SDHCI_SOFTWARE_RESET) & mask) {
++ if (timeout == 0) {
++ printk(KERN_ERR "%s: Reset 0x%x never completed.\n",
++ mmc_hostname(host->mmc), (int)mask);
++ sdhci_dumpregs(host);
++ return;
++ }
++ timeout--;
++ mdelay(1);
++ }
++}
++
++static void sdhci_init(struct sdhci_host *host)
++{
++ u32 intmask;
++
++ sdhci_reset(host, SDHCI_RESET_ALL);
++
++ intmask = SDHCI_INT_BUS_POWER | SDHCI_INT_DATA_END_BIT |
++ SDHCI_INT_DATA_CRC | SDHCI_INT_DATA_TIMEOUT | SDHCI_INT_INDEX |
++ SDHCI_INT_END_BIT | SDHCI_INT_CRC | SDHCI_INT_TIMEOUT |
++ SDHCI_INT_CARD_REMOVE | SDHCI_INT_CARD_INSERT |
++ SDHCI_INT_DATA_AVAIL | SDHCI_INT_SPACE_AVAIL |
++ SDHCI_INT_DMA_END | SDHCI_INT_DATA_END | SDHCI_INT_RESPONSE |
++ SDHCI_INT_ADMA_ERROR;
++
++ writel(intmask, host->ioaddr + SDHCI_INT_ENABLE);
++ writel(intmask, host->ioaddr + SDHCI_SIGNAL_ENABLE);
++}
++
++static void sdhci_activate_led(struct sdhci_host *host)
++{
++ u8 ctrl;
++
++ ctrl = readb(host->ioaddr + SDHCI_HOST_CONTROL);
++ ctrl |= SDHCI_CTRL_LED;
++ writeb(ctrl, host->ioaddr + SDHCI_HOST_CONTROL);
++}
++
++static void sdhci_deactivate_led(struct sdhci_host *host)
++{
++ u8 ctrl;
++
++ ctrl = readb(host->ioaddr + SDHCI_HOST_CONTROL);
++ ctrl &= ~SDHCI_CTRL_LED;
++ writeb(ctrl, host->ioaddr + SDHCI_HOST_CONTROL);
++}
++
++#ifdef CONFIG_LEDS_CLASS
++static void sdhci_led_control(struct led_classdev *led,
++ enum led_brightness brightness)
++{
++ struct sdhci_host *host = container_of(led, struct sdhci_host, led);
++ unsigned long flags;
++
++ spin_lock_irqsave(&host->lock, flags);
++
++ if (brightness == LED_OFF)
++ sdhci_deactivate_led(host);
++ else
++ sdhci_activate_led(host);
++
++ spin_unlock_irqrestore(&host->lock, flags);
++}
++#endif
++
++/*****************************************************************************\
++ * *
++ * Core functions *
++ * *
++\*****************************************************************************/
++
++static void sdhci_read_block_pio(struct sdhci_host *host)
++{
++ unsigned long flags;
++ size_t blksize, len, chunk;
++ u32 uninitialized_var(scratch);
++ u8 *buf;
++
++ DBG("PIO reading\n");
++
++ blksize = host->data->blksz;
++ chunk = 0;
++
++ local_irq_save(flags);
++
++ while (blksize) {
++ if (!sg_miter_next(&host->sg_miter))
++ BUG();
++
++ len = min(host->sg_miter.length, blksize);
++
++ blksize -= len;
++ host->sg_miter.consumed = len;
++
++ buf = host->sg_miter.addr;
++
++ while (len) {
++ if (chunk == 0) {
++ scratch = readl(host->ioaddr + SDHCI_BUFFER);
++ chunk = 4;
++ }
++
++ *buf = scratch & 0xFF;
++
++ buf++;
++ scratch >>= 8;
++ chunk--;
++ len--;
++ }
++ }
++
++ sg_miter_stop(&host->sg_miter);
++
++ local_irq_restore(flags);
++}
++
++static void sdhci_write_block_pio(struct sdhci_host *host)
++{
++ unsigned long flags;
++ size_t blksize, len, chunk;
++ u32 scratch;
++ u8 *buf;
++
++ DBG("PIO writing\n");
++
++ blksize = host->data->blksz;
++ chunk = 0;
++ scratch = 0;
++
++ local_irq_save(flags);
++
++ while (blksize) {
++ if (!sg_miter_next(&host->sg_miter))
++ BUG();
++
++ len = min(host->sg_miter.length, blksize);
++
++ blksize -= len;
++ host->sg_miter.consumed = len;
++
++ buf = host->sg_miter.addr;
++
++ while (len) {
++ scratch |= (u32)*buf << (chunk * 8);
++
++ buf++;
++ chunk++;
++ len--;
++
++ if ((chunk == 4) || ((len == 0) && (blksize == 0))) {
++ writel(scratch, host->ioaddr + SDHCI_BUFFER);
++ chunk = 0;
++ scratch = 0;
++ }
++ }
++ }
++
++ sg_miter_stop(&host->sg_miter);
++
++ local_irq_restore(flags);
++}
++
++static void sdhci_transfer_pio(struct sdhci_host *host)
++{
++ u32 mask;
++
++ BUG_ON(!host->data);
++
++ if (host->blocks == 0)
++ return;
++
++ if (host->data->flags & MMC_DATA_READ)
++ mask = SDHCI_DATA_AVAILABLE;
++ else
++ mask = SDHCI_SPACE_AVAILABLE;
++
++ /*
++ * Some controllers (JMicron JMB38x) mess up the buffer bits
++ * for transfers < 4 bytes. As long as it is just one block,
++ * we can ignore the bits.
++ */
++ if ((host->quirks & SDHCI_QUIRK_BROKEN_SMALL_PIO) &&
++ (host->data->blocks == 1))
++ mask = ~0;
++
++ while (readl(host->ioaddr + SDHCI_PRESENT_STATE) & mask) {
++ if (host->data->flags & MMC_DATA_READ)
++ sdhci_read_block_pio(host);
++ else
++ sdhci_write_block_pio(host);
++
++ host->blocks--;
++ if (host->blocks == 0)
++ break;
++ }
++
++ DBG("PIO transfer complete.\n");
++}
++
++static char *sdhci_kmap_atomic(struct scatterlist *sg, unsigned long *flags)
++{
++ local_irq_save(*flags);
++ return kmap_atomic(sg_page(sg), KM_BIO_SRC_IRQ) + sg->offset;
++}
++
++static void sdhci_kunmap_atomic(void *buffer, unsigned long *flags)
++{
++ kunmap_atomic(buffer, KM_BIO_SRC_IRQ);
++ local_irq_restore(*flags);
++}
++
++static int sdhci_adma_table_pre(struct sdhci_host *host,
++ struct mmc_data *data)
++{
++ int direction;
++
++ u8 *desc;
++ u8 *align;
++ dma_addr_t addr;
++ dma_addr_t align_addr;
++ int len, offset;
++
++ struct scatterlist *sg;
++ int i;
++ char *buffer;
++ unsigned long flags;
++
++ /*
++ * The spec does not specify endianness of descriptor table.
++ * We currently guess that it is LE.
++ */
++
++ if (data->flags & MMC_DATA_READ)
++ direction = DMA_FROM_DEVICE;
++ else
++ direction = DMA_TO_DEVICE;
++
++ /*
++ * The ADMA descriptor table is mapped further down as we
++ * need to fill it with data first.
++ */
++
++ host->align_addr = dma_map_single(mmc_dev(host->mmc),
++ host->align_buffer, 128 * 4, direction);
++ if (dma_mapping_error(mmc_dev(host->mmc), host->align_addr))
++ goto fail;
++ BUG_ON(host->align_addr & 0x3);
++
++ host->sg_count = dma_map_sg(mmc_dev(host->mmc),
++ data->sg, data->sg_len, direction);
++ if (host->sg_count == 0)
++ goto unmap_align;
++
++ desc = host->adma_desc;
++ align = host->align_buffer;
++
++ align_addr = host->align_addr;
++
++ for_each_sg(data->sg, sg, host->sg_count, i) {
++ addr = sg_dma_address(sg);
++ len = sg_dma_len(sg);
++
++ /*
++ * The SDHCI specification states that ADMA
++ * addresses must be 32-bit aligned. If they
++ * aren't, then we use a bounce buffer for
++ * the (up to three) bytes that screw up the
++ * alignment.
++ */
++ offset = (4 - (addr & 0x3)) & 0x3;
++ if (offset) {
++ if (data->flags & MMC_DATA_WRITE) {
++ buffer = sdhci_kmap_atomic(sg, &flags);
++ WARN_ON(((long)buffer & PAGE_MASK) > (PAGE_SIZE - 3));
++ memcpy(align, buffer, offset);
++ sdhci_kunmap_atomic(buffer, &flags);
++ }
++
++ desc[7] = (align_addr >> 24) & 0xff;
++ desc[6] = (align_addr >> 16) & 0xff;
++ desc[5] = (align_addr >> 8) & 0xff;
++ desc[4] = (align_addr >> 0) & 0xff;
++
++ BUG_ON(offset > 65536);
++
++ desc[3] = (offset >> 8) & 0xff;
++ desc[2] = (offset >> 0) & 0xff;
++
++ desc[1] = 0x00;
++ desc[0] = 0x21; /* tran, valid */
++
++ align += 4;
++ align_addr += 4;
++
++ desc += 8;
++
++ addr += offset;
++ len -= offset;
++ }
++
++ desc[7] = (addr >> 24) & 0xff;
++ desc[6] = (addr >> 16) & 0xff;
++ desc[5] = (addr >> 8) & 0xff;
++ desc[4] = (addr >> 0) & 0xff;
++
++ BUG_ON(len > 65536);
++
++ desc[3] = (len >> 8) & 0xff;
++ desc[2] = (len >> 0) & 0xff;
++
++ desc[1] = 0x00;
++ desc[0] = 0x21; /* tran, valid */
++
++ desc += 8;
++
++ /*
++ * If this triggers then we have a calculation bug
++ * somewhere. :/
++ */
++ WARN_ON((desc - host->adma_desc) > (128 * 2 + 1) * 4);
++ }
++
++ /*
++ * Add a terminating entry.
++ */
++ desc[7] = 0;
++ desc[6] = 0;
++ desc[5] = 0;
++ desc[4] = 0;
++
++ desc[3] = 0;
++ desc[2] = 0;
++
++ desc[1] = 0x00;
++ desc[0] = 0x03; /* nop, end, valid */
++
++ /*
++ * Resync align buffer as we might have changed it.
++ */
++ if (data->flags & MMC_DATA_WRITE) {
++ dma_sync_single_for_device(mmc_dev(host->mmc),
++ host->align_addr, 128 * 4, direction);
++ }
++
++ host->adma_addr = dma_map_single(mmc_dev(host->mmc),
++ host->adma_desc, (128 * 2 + 1) * 4, DMA_TO_DEVICE);
++ if (dma_mapping_error(mmc_dev(host->mmc), host->adma_addr))
++ goto unmap_entries;
++ BUG_ON(host->adma_addr & 0x3);
++
++ return 0;
++
++unmap_entries:
++ dma_unmap_sg(mmc_dev(host->mmc), data->sg,
++ data->sg_len, direction);
++unmap_align:
++ dma_unmap_single(mmc_dev(host->mmc), host->align_addr,
++ 128 * 4, direction);
++fail:
++ return -EINVAL;
++}
++
++static void sdhci_adma_table_post(struct sdhci_host *host,
++ struct mmc_data *data)
++{
++ int direction;
++
++ struct scatterlist *sg;
++ int i, size;
++ u8 *align;
++ char *buffer;
++ unsigned long flags;
++
++ if (data->flags & MMC_DATA_READ)
++ direction = DMA_FROM_DEVICE;
++ else
++ direction = DMA_TO_DEVICE;
++
++ dma_unmap_single(mmc_dev(host->mmc), host->adma_addr,
++ (128 * 2 + 1) * 4, DMA_TO_DEVICE);
++
++ dma_unmap_single(mmc_dev(host->mmc), host->align_addr,
++ 128 * 4, direction);
++
++ if (data->flags & MMC_DATA_READ) {
++ dma_sync_sg_for_cpu(mmc_dev(host->mmc), data->sg,
++ data->sg_len, direction);
++
++ align = host->align_buffer;
++
++ for_each_sg(data->sg, sg, host->sg_count, i) {
++ if (sg_dma_address(sg) & 0x3) {
++ size = 4 - (sg_dma_address(sg) & 0x3);
++
++ buffer = sdhci_kmap_atomic(sg, &flags);
++ WARN_ON(((long)buffer & PAGE_MASK) > (PAGE_SIZE - 3));
++ memcpy(buffer, align, size);
++ sdhci_kunmap_atomic(buffer, &flags);
++
++ align += 4;
++ }
++ }
++ }
++
++ dma_unmap_sg(mmc_dev(host->mmc), data->sg,
++ data->sg_len, direction);
++}
++
++static u8 sdhci_calc_timeout(struct sdhci_host *host, struct mmc_data *data)
++{
++ u8 count;
++ unsigned target_timeout, current_timeout;
++
++ /*
++ * If the host controller provides us with an incorrect timeout
++ * value, just skip the check and use 0xE. The hardware may take
++ * longer to time out, but that's much better than having a too-short
++ * timeout value.
++ */
++ if ((host->quirks & SDHCI_QUIRK_BROKEN_TIMEOUT_VAL))
++ return 0xE;
++
++ /* timeout in us */
++ target_timeout = data->timeout_ns / 1000 +
++ data->timeout_clks / host->clock;
++
++ /*
++ * Figure out needed cycles.
++ * We do this in steps in order to fit inside a 32 bit int.
++ * The first step is the minimum timeout, which will have a
++ * minimum resolution of 6 bits:
++ * (1) 2^13*1000 > 2^22,
++ * (2) host->timeout_clk < 2^16
++ * =>
++ * (1) / (2) > 2^6
++ */
++ count = 0;
++ current_timeout = (1 << 13) * 1000 / host->timeout_clk;
++ while (current_timeout < target_timeout) {
++ count++;
++ current_timeout <<= 1;
++ if (count >= 0xF)
++ break;
++ }
++
++ if (count >= 0xF) {
++ printk(KERN_WARNING "%s: Too large timeout requested!\n",
++ mmc_hostname(host->mmc));
++ count = 0xE;
++ }
++
++ return count;
++}
++
++static void sdhci_prepare_data(struct sdhci_host *host, struct mmc_data *data)
++{
++ u8 count;
++ u8 ctrl;
++ int ret;
++
++ WARN_ON(host->data);
++
++ if (data == NULL)
++ return;
++
++ /* Sanity checks */
++ BUG_ON(data->blksz * data->blocks > 524288);
++ BUG_ON(data->blksz > host->mmc->max_blk_size);
++ BUG_ON(data->blocks > 65535);
++
++ host->data = data;
++ host->data_early = 0;
++
++ count = sdhci_calc_timeout(host, data);
++ writeb(count, host->ioaddr + SDHCI_TIMEOUT_CONTROL);
++
++ if (host->flags & SDHCI_USE_DMA)
++ host->flags |= SDHCI_REQ_USE_DMA;
++
++ /*
++ * FIXME: This doesn't account for merging when mapping the
++ * scatterlist.
++ */
++ if (host->flags & SDHCI_REQ_USE_DMA) {
++ int broken, i;
++ struct scatterlist *sg;
++
++ broken = 0;
++ if (host->flags & SDHCI_USE_ADMA) {
++ if (host->quirks & SDHCI_QUIRK_32BIT_ADMA_SIZE)
++ broken = 1;
++ } else {
++ if (host->quirks & SDHCI_QUIRK_32BIT_DMA_SIZE)
++ broken = 1;
++ }
++
++ if (unlikely(broken)) {
++ for_each_sg(data->sg, sg, data->sg_len, i) {
++ if (sg->length & 0x3) {
++ DBG("Reverting to PIO because of "
++ "transfer size (%d)\n",
++ sg->length);
++ host->flags &= ~SDHCI_REQ_USE_DMA;
++ break;
++ }
++ }
++ }
++ }
++
++ /*
++ * The assumption here being that alignment is the same after
++ * translation to device address space.
++ */
++ if (host->flags & SDHCI_REQ_USE_DMA) {
++ int broken, i;
++ struct scatterlist *sg;
++
++ broken = 0;
++ if (host->flags & SDHCI_USE_ADMA) {
++ /*
++ * As we use 3 byte chunks to work around
++ * alignment problems, we need to check this
++ * quirk.
++ */
++ if (host->quirks & SDHCI_QUIRK_32BIT_ADMA_SIZE)
++ broken = 1;
++ } else {
++ if (host->quirks & SDHCI_QUIRK_32BIT_DMA_ADDR)
++ broken = 1;
++ }
++
++ if (unlikely(broken)) {
++ for_each_sg(data->sg, sg, data->sg_len, i) {
++ if (sg->offset & 0x3) {
++ DBG("Reverting to PIO because of "
++ "bad alignment\n");
++ host->flags &= ~SDHCI_REQ_USE_DMA;
++ break;
++ }
++ }
++ }
++ }
++
++ if (host->flags & SDHCI_REQ_USE_DMA) {
++ if (host->flags & SDHCI_USE_ADMA) {
++ ret = sdhci_adma_table_pre(host, data);
++ if (ret) {
++ /*
++ * This only happens when someone fed
++ * us an invalid request.
++ */
++ WARN_ON(1);
++ host->flags &= ~SDHCI_REQ_USE_DMA;
++ } else {
++ writel(host->adma_addr,
++ host->ioaddr + SDHCI_ADMA_ADDRESS);
++ }
++ } else {
++ int sg_cnt;
++
++ sg_cnt = dma_map_sg(mmc_dev(host->mmc),
++ data->sg, data->sg_len,
++ (data->flags & MMC_DATA_READ) ?
++ DMA_FROM_DEVICE :
++ DMA_TO_DEVICE);
++ if (sg_cnt == 0) {
++ /*
++ * This only happens when someone fed
++ * us an invalid request.
++ */
++ WARN_ON(1);
++ host->flags &= ~SDHCI_REQ_USE_DMA;
++ } else {
++ WARN_ON(sg_cnt != 1);
++ writel(sg_dma_address(data->sg),
++ host->ioaddr + SDHCI_DMA_ADDRESS);
++ }
++ }
++ }
++
++ /*
++ * Always adjust the DMA selection as some controllers
++ * (e.g. JMicron) can't do PIO properly when the selection
++ * is ADMA.
++ */
++ if (host->version >= SDHCI_SPEC_200) {
++ ctrl = readb(host->ioaddr + SDHCI_HOST_CONTROL);
++ ctrl &= ~SDHCI_CTRL_DMA_MASK;
++ if ((host->flags & SDHCI_REQ_USE_DMA) &&
++ (host->flags & SDHCI_USE_ADMA))
++ ctrl |= SDHCI_CTRL_ADMA32;
++ else
++ ctrl |= SDHCI_CTRL_SDMA;
++ writeb(ctrl, host->ioaddr + SDHCI_HOST_CONTROL);
++ }
++
++ if (!(host->flags & SDHCI_REQ_USE_DMA)) {
++ sg_miter_start(&host->sg_miter,
++ data->sg, data->sg_len, SG_MITER_ATOMIC);
++ host->blocks = data->blocks;
++ }
++
++ /* We do not handle DMA boundaries, so set it to max (512 KiB) */
++ writew(SDHCI_MAKE_BLKSZ(7, data->blksz),
++ host->ioaddr + SDHCI_BLOCK_SIZE);
++ writew(data->blocks, host->ioaddr + SDHCI_BLOCK_COUNT);
++}
++
++static void sdhci_set_transfer_mode(struct sdhci_host *host,
++ struct mmc_data *data)
++{
++ u16 mode;
++
++ if (data == NULL)
++ return;
++
++ WARN_ON(!host->data);
++
++ mode = SDHCI_TRNS_BLK_CNT_EN;
++ if (data->blocks > 1)
++ mode |= SDHCI_TRNS_MULTI | SDHCI_TRNS_ACMD12;
++// mode |= SDHCI_TRNS_MULTI;
++ if (data->flags & MMC_DATA_READ)
++ mode |= SDHCI_TRNS_READ;
++ if (host->flags & SDHCI_REQ_USE_DMA)
++ mode |= SDHCI_TRNS_DMA;
++
++ writew(mode, host->ioaddr + SDHCI_TRANSFER_MODE);
++}
++
++static void sdhci_finish_data(struct sdhci_host *host)
++{
++ struct mmc_data *data;
++
++ BUG_ON(!host->data);
++
++ data = host->data;
++ host->data = NULL;
++
++ if (host->flags & SDHCI_REQ_USE_DMA) {
++ if (host->flags & SDHCI_USE_ADMA)
++ sdhci_adma_table_post(host, data);
++ else {
++ dma_unmap_sg(mmc_dev(host->mmc), data->sg,
++ data->sg_len, (data->flags & MMC_DATA_READ) ?
++ DMA_FROM_DEVICE : DMA_TO_DEVICE);
++ }
++ }
++
++ /*
++ * The specification states that the block count register must
++ * be updated, but it does not specify at what point in the
++ * data flow. That makes the register entirely useless to read
++ * back so we have to assume that nothing made it to the card
++ * in the event of an error.
++ */
++ if (data->error)
++ data->bytes_xfered = 0;
++ else
++ data->bytes_xfered = data->blksz * data->blocks;
++
++ if (data->stop) {
++ /*
++ * The controller needs a reset of internal state machines
++ * upon error conditions.
++ */
++ if (data->error) {
++ sdhci_reset(host, SDHCI_RESET_CMD);
++ sdhci_reset(host, SDHCI_RESET_DATA);
++ }
++
++ sdhci_send_command(host, data->stop);
++ } else
++ tasklet_schedule(&host->finish_tasklet);
++}
++
++static void sdhci_send_command(struct sdhci_host *host, struct mmc_command *cmd)
++{
++ int flags;
++ u32 mask;
++ unsigned long timeout;
++
++ WARN_ON(host->cmd);
++
++ /* Wait max 10 ms */
++ timeout = 10;
++
++ mask = SDHCI_CMD_INHIBIT;
++ if ((cmd->data != NULL) || (cmd->flags & MMC_RSP_BUSY))
++ mask |= SDHCI_DATA_INHIBIT;
++
++ /* We shouldn't wait for data inihibit for stop commands, even
++ though they might use busy signaling */
++ if (host->mrq->data && (cmd == host->mrq->data->stop))
++ mask &= ~SDHCI_DATA_INHIBIT;
++
++ while (readl(host->ioaddr + SDHCI_PRESENT_STATE) & mask) {
++ if (timeout == 0) {
++ printk(KERN_ERR "%s: Controller never released "
++ "inhibit bit(s).\n", mmc_hostname(host->mmc));
++ sdhci_dumpregs(host);
++ cmd->error = -EIO;
++ tasklet_schedule(&host->finish_tasklet);
++ return;
++ }
++ timeout--;
++ mdelay(1);
++ }
++
++ mod_timer(&host->timer, jiffies + 10 * HZ);
++
++ host->cmd = cmd;
++
++ sdhci_prepare_data(host, cmd->data);
++
++ writel(cmd->arg, host->ioaddr + SDHCI_ARGUMENT);
++
++ sdhci_set_transfer_mode(host, cmd->data);
++
++ if ((cmd->flags & MMC_RSP_136) && (cmd->flags & MMC_RSP_BUSY)) {
++ printk(KERN_ERR "%s: Unsupported response type!\n",
++ mmc_hostname(host->mmc));
++ cmd->error = -EINVAL;
++ tasklet_schedule(&host->finish_tasklet);
++ return;
++ }
++
++ if (!(cmd->flags & MMC_RSP_PRESENT))
++ flags = SDHCI_CMD_RESP_NONE;
++ else if (cmd->flags & MMC_RSP_136)
++ flags = SDHCI_CMD_RESP_LONG;
++ else if (cmd->flags & MMC_RSP_BUSY)
++ flags = SDHCI_CMD_RESP_SHORT_BUSY;
++ else
++ flags = SDHCI_CMD_RESP_SHORT;
++
++ if (cmd->flags & MMC_RSP_CRC)
++ flags |= SDHCI_CMD_CRC;
++ if (cmd->flags & MMC_RSP_OPCODE)
++ flags |= SDHCI_CMD_INDEX;
++ if (cmd->data)
++ flags |= SDHCI_CMD_DATA;
++
++ writew(SDHCI_MAKE_CMD(cmd->opcode, flags),
++ host->ioaddr + SDHCI_COMMAND);
++}
++
++static void sdhci_finish_command(struct sdhci_host *host)
++{
++ int i;
++
++ BUG_ON(host->cmd == NULL);
++
++ if (host->cmd->flags & MMC_RSP_PRESENT) {
++ if (host->cmd->flags & MMC_RSP_136) {
++ /* CRC is stripped so we need to do some shifting. */
++ for (i = 0;i < 4;i++) {
++ host->cmd->resp[i] = readl(host->ioaddr +
++ SDHCI_RESPONSE + (3-i)*4) << 8;
++ if (i != 3)
++ host->cmd->resp[i] |=
++ readb(host->ioaddr +
++ SDHCI_RESPONSE + (3-i)*4-1);
++ }
++ } else {
++ host->cmd->resp[0] = readl(host->ioaddr + SDHCI_RESPONSE);
++ }
++ }
++
++ host->cmd->error = 0;
++
++ if (host->data && host->data_early)
++ sdhci_finish_data(host);
++
++ if (!host->cmd->data)
++ tasklet_schedule(&host->finish_tasklet);
++
++ host->cmd = NULL;
++}
++
++static void sdhci_set_clock(struct sdhci_host *host, unsigned int clock)
++{
++ int div;
++ u16 clk;
++ unsigned long timeout;
++
++ if (clock == host->clock)
++ return;
++
++ writew(0, host->ioaddr + SDHCI_CLOCK_CONTROL);
++
++ if (clock == 0)
++ goto out;
++
++ for (div = 1;div < 256;div *= 2) {
++ if ((host->max_clk / div) <= clock)
++ break;
++ }
++ div >>= 1;
++
++ //Issue : For ast2300, ast2400 couldn't set div = 0 means /1 , so set source is ~50Mhz up
++
++ clk = div << SDHCI_DIVIDER_SHIFT;
++ clk |= SDHCI_CLOCK_INT_EN;
++ writew(clk, host->ioaddr + SDHCI_CLOCK_CONTROL);
++
++ /* Wait max 10 ms */
++ timeout = 10;
++ while (!((clk = readw(host->ioaddr + SDHCI_CLOCK_CONTROL))
++ & SDHCI_CLOCK_INT_STABLE)) {
++ if (timeout == 0) {
++ printk(KERN_ERR "%s: Internal clock never "
++ "stabilised.\n", mmc_hostname(host->mmc));
++ sdhci_dumpregs(host);
++ return;
++ }
++ timeout--;
++ mdelay(1);
++ }
++
++ clk |= SDHCI_CLOCK_CARD_EN;
++ writew(clk, host->ioaddr + SDHCI_CLOCK_CONTROL);
++
++out:
++ host->clock = clock;
++}
++
++static void sdhci_set_power(struct sdhci_host *host, unsigned short power)
++{
++ u8 pwr;
++
++ if (host->power == power)
++ return;
++
++ if (power == (unsigned short)-1) {
++ writeb(0, host->ioaddr + SDHCI_POWER_CONTROL);
++ goto out;
++ }
++
++ /*
++ * Spec says that we should clear the power reg before setting
++ * a new value. Some controllers don't seem to like this though.
++ */
++ if (!(host->quirks & SDHCI_QUIRK_SINGLE_POWER_WRITE))
++ writeb(0, host->ioaddr + SDHCI_POWER_CONTROL);
++
++ pwr = SDHCI_POWER_ON;
++
++ switch (1 << power) {
++ case MMC_VDD_165_195:
++ pwr |= SDHCI_POWER_180;
++ break;
++ case MMC_VDD_29_30:
++ case MMC_VDD_30_31:
++ pwr |= SDHCI_POWER_300;
++ break;
++ case MMC_VDD_32_33:
++ case MMC_VDD_33_34:
++ pwr |= SDHCI_POWER_330;
++ break;
++ default:
++ BUG();
++ }
++
++ /*
++ * At least the Marvell CaFe chip gets confused if we set the voltage
++ * and set turn on power at the same time, so set the voltage first.
++ */
++ if ((host->quirks & SDHCI_QUIRK_NO_SIMULT_VDD_AND_POWER))
++ writeb(pwr & ~SDHCI_POWER_ON,
++ host->ioaddr + SDHCI_POWER_CONTROL);
++
++ writeb(pwr, host->ioaddr + SDHCI_POWER_CONTROL);
++
++out:
++ host->power = power;
++}
++
++/*****************************************************************************\
++ * *
++ * MMC callbacks *
++ * *
++\*****************************************************************************/
++
++static void sdhci_request(struct mmc_host *mmc, struct mmc_request *mrq)
++{
++ struct sdhci_host *host;
++ unsigned long flags;
++
++ host = mmc_priv(mmc);
++
++ spin_lock_irqsave(&host->lock, flags);
++
++ WARN_ON(host->mrq != NULL);
++
++#ifndef CONFIG_LEDS_CLASS
++ sdhci_activate_led(host);
++#endif
++
++ host->mrq = mrq;
++
++ if (!(readl(host->ioaddr + SDHCI_PRESENT_STATE) & SDHCI_CARD_PRESENT)
++ || (host->flags & SDHCI_DEVICE_DEAD)) {
++ host->mrq->cmd->error = -ENOMEDIUM;
++ tasklet_schedule(&host->finish_tasklet);
++ } else
++ sdhci_send_command(host, mrq->cmd);
++
++ mmiowb();
++ spin_unlock_irqrestore(&host->lock, flags);
++}
++
++static void sdhci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
++{
++ struct sdhci_host *host;
++ unsigned long flags;
++ u8 ctrl;
++
++ host = mmc_priv(mmc);
++
++ spin_lock_irqsave(&host->lock, flags);
++
++ if (host->flags & SDHCI_DEVICE_DEAD)
++ goto out;
++
++ /*
++ * Reset the chip on each power off.
++ * Should clear out any weird states.
++ */
++ if (ios->power_mode == MMC_POWER_OFF) {
++ writel(0, host->ioaddr + SDHCI_SIGNAL_ENABLE);
++ sdhci_init(host);
++ }
++
++ sdhci_set_clock(host, ios->clock);
++
++ if (ios->power_mode == MMC_POWER_OFF)
++ sdhci_set_power(host, -1);
++ else
++ sdhci_set_power(host, ios->vdd);
++
++ ctrl = readb(host->ioaddr + SDHCI_HOST_CONTROL);
++
++ if (ios->bus_width == MMC_BUS_WIDTH_4)
++ ctrl |= SDHCI_CTRL_4BITBUS;
++ else
++ ctrl &= ~SDHCI_CTRL_4BITBUS;
++
++ if (ios->timing == MMC_TIMING_SD_HS)
++ ctrl |= SDHCI_CTRL_HISPD;
++ else
++ ctrl &= ~SDHCI_CTRL_HISPD;
++
++ writeb(ctrl, host->ioaddr + SDHCI_HOST_CONTROL);
++
++ /*
++ * Some (ENE) controllers go apeshit on some ios operation,
++ * signalling timeout and CRC errors even on CMD0. Resetting
++ * it on each ios seems to solve the problem.
++ */
++ if(host->quirks & SDHCI_QUIRK_RESET_CMD_DATA_ON_IOS)
++ sdhci_reset(host, SDHCI_RESET_CMD | SDHCI_RESET_DATA);
++
++out:
++ mmiowb();
++ spin_unlock_irqrestore(&host->lock, flags);
++}
++
++static int sdhci_get_ro(struct mmc_host *mmc)
++{
++ struct sdhci_host *host;
++ unsigned long flags;
++ int present;
++
++ host = mmc_priv(mmc);
++
++ spin_lock_irqsave(&host->lock, flags);
++
++ if (host->flags & SDHCI_DEVICE_DEAD)
++ present = 0;
++ else
++ present = readl(host->ioaddr + SDHCI_PRESENT_STATE);
++
++ spin_unlock_irqrestore(&host->lock, flags);
++
++ return !(present & SDHCI_WRITE_PROTECT);
++}
++
++static void sdhci_enable_sdio_irq(struct mmc_host *mmc, int enable)
++{
++ struct sdhci_host *host;
++ unsigned long flags;
++ u32 ier;
++
++ host = mmc_priv(mmc);
++
++ spin_lock_irqsave(&host->lock, flags);
++
++ if (host->flags & SDHCI_DEVICE_DEAD)
++ goto out;
++
++ ier = readl(host->ioaddr + SDHCI_INT_ENABLE);
++
++ ier &= ~SDHCI_INT_CARD_INT;
++ if (enable)
++ ier |= SDHCI_INT_CARD_INT;
++
++ writel(ier, host->ioaddr + SDHCI_INT_ENABLE);
++ writel(ier, host->ioaddr + SDHCI_SIGNAL_ENABLE);
++
++out:
++ mmiowb();
++
++ spin_unlock_irqrestore(&host->lock, flags);
++}
++
++static const struct mmc_host_ops sdhci_ops = {
++ .request = sdhci_request,
++ .set_ios = sdhci_set_ios,
++ .get_ro = sdhci_get_ro,
++ .enable_sdio_irq = sdhci_enable_sdio_irq,
++};
++
++/*****************************************************************************\
++ * *
++ * Tasklets *
++ * *
++\*****************************************************************************/
++
++static void sdhci_tasklet_card(unsigned long param)
++{
++ struct sdhci_host *host;
++ unsigned long flags;
++
++ host = (struct sdhci_host*)param;
++
++ spin_lock_irqsave(&host->lock, flags);
++
++ if (!(readl(host->ioaddr + SDHCI_PRESENT_STATE) & SDHCI_CARD_PRESENT)) {
++ if (host->mrq) {
++ printk(KERN_ERR "%s: Card removed during transfer!\n",
++ mmc_hostname(host->mmc));
++ printk(KERN_ERR "%s: Resetting controller.\n",
++ mmc_hostname(host->mmc));
++
++ sdhci_reset(host, SDHCI_RESET_CMD);
++ sdhci_reset(host, SDHCI_RESET_DATA);
++
++ host->mrq->cmd->error = -ENOMEDIUM;
++ tasklet_schedule(&host->finish_tasklet);
++ }
++ }
++
++ spin_unlock_irqrestore(&host->lock, flags);
++
++ mmc_detect_change(host->mmc, msecs_to_jiffies(200));
++}
++
++static void sdhci_tasklet_finish(unsigned long param)
++{
++ struct sdhci_host *host;
++ unsigned long flags;
++ struct mmc_request *mrq;
++
++ host = (struct sdhci_host*)param;
++
++ spin_lock_irqsave(&host->lock, flags);
++
++ del_timer(&host->timer);
++
++ mrq = host->mrq;
++
++ /*
++ * The controller needs a reset of internal state machines
++ * upon error conditions.
++ */
++ if (!(host->flags & SDHCI_DEVICE_DEAD) &&
++ (mrq->cmd->error ||
++ (mrq->data && (mrq->data->error ||
++ (mrq->data->stop && mrq->data->stop->error))) ||
++ (host->quirks & SDHCI_QUIRK_RESET_AFTER_REQUEST))) {
++
++ /* Some controllers need this kick or reset won't work here */
++ if (host->quirks & SDHCI_QUIRK_CLOCK_BEFORE_RESET) {
++ unsigned int clock;
++
++ /* This is to force an update */
++ clock = host->clock;
++ host->clock = 0;
++ sdhci_set_clock(host, clock);
++ }
++
++ /* Spec says we should do both at the same time, but Ricoh
++ controllers do not like that. */
++ sdhci_reset(host, SDHCI_RESET_CMD);
++ sdhci_reset(host, SDHCI_RESET_DATA);
++ }
++
++ host->mrq = NULL;
++ host->cmd = NULL;
++ host->data = NULL;
++
++#ifndef CONFIG_LEDS_CLASS
++ sdhci_deactivate_led(host);
++#endif
++
++ mmiowb();
++ spin_unlock_irqrestore(&host->lock, flags);
++
++ mmc_request_done(host->mmc, mrq);
++}
++
++static void sdhci_timeout_timer(unsigned long data)
++{
++ struct sdhci_host *host;
++ unsigned long flags;
++
++ host = (struct sdhci_host*)data;
++
++ spin_lock_irqsave(&host->lock, flags);
++
++ if (host->mrq) {
++ printk(KERN_ERR "%s: Timeout waiting for hardware "
++ "interrupt.\n", mmc_hostname(host->mmc));
++ sdhci_dumpregs(host);
++
++ if (host->data) {
++ host->data->error = -ETIMEDOUT;
++ sdhci_finish_data(host);
++ } else {
++ if (host->cmd)
++ host->cmd->error = -ETIMEDOUT;
++ else
++ host->mrq->cmd->error = -ETIMEDOUT;
++
++ tasklet_schedule(&host->finish_tasklet);
++ }
++ }
++
++ mmiowb();
++ spin_unlock_irqrestore(&host->lock, flags);
++}
++
++/*****************************************************************************\
++ * *
++ * Interrupt handling *
++ * *
++\*****************************************************************************/
++
++static void sdhci_cmd_irq(struct sdhci_host *host, u32 intmask)
++{
++ BUG_ON(intmask == 0);
++
++ if (!host->cmd) {
++ printk(KERN_ERR "%s: Got command interrupt 0x%08x even "
++ "though no command operation was in progress.\n",
++ mmc_hostname(host->mmc), (unsigned)intmask);
++ sdhci_dumpregs(host);
++ return;
++ }
++
++ if (intmask & SDHCI_INT_TIMEOUT)
++ host->cmd->error = -ETIMEDOUT;
++ else if (intmask & (SDHCI_INT_CRC | SDHCI_INT_END_BIT |
++ SDHCI_INT_INDEX))
++ host->cmd->error = -EILSEQ;
++
++ if (host->cmd->error) {
++ tasklet_schedule(&host->finish_tasklet);
++ return;
++ }
++
++ /*
++ * The host can send and interrupt when the busy state has
++ * ended, allowing us to wait without wasting CPU cycles.
++ * Unfortunately this is overloaded on the "data complete"
++ * interrupt, so we need to take some care when handling
++ * it.
++ *
++ * Note: The 1.0 specification is a bit ambiguous about this
++ * feature so there might be some problems with older
++ * controllers.
++ */
++ if (host->cmd->flags & MMC_RSP_BUSY) {
++ if (host->cmd->data)
++ DBG("Cannot wait for busy signal when also "
++ "doing a data transfer");
++ else if (!(host->quirks & SDHCI_QUIRK_NO_BUSY_IRQ))
++ return;
++
++ /* The controller does not support the end-of-busy IRQ,
++ * fall through and take the SDHCI_INT_RESPONSE */
++ }
++
++ if (intmask & SDHCI_INT_RESPONSE)
++ sdhci_finish_command(host);
++}
++
++static void sdhci_data_irq(struct sdhci_host *host, u32 intmask)
++{
++ BUG_ON(intmask == 0);
++
++ if (!host->data) {
++ /*
++ * The "data complete" interrupt is also used to
++ * indicate that a busy state has ended. See comment
++ * above in sdhci_cmd_irq().
++ */
++ if (host->cmd && (host->cmd->flags & MMC_RSP_BUSY)) {
++ if (intmask & SDHCI_INT_DATA_END) {
++ sdhci_finish_command(host);
++ return;
++ }
++ }
++
++ printk(KERN_ERR "%s: Got data interrupt 0x%08x even "
++ "though no data operation was in progress.\n",
++ mmc_hostname(host->mmc), (unsigned)intmask);
++ sdhci_dumpregs(host);
++
++ return;
++ }
++
++ if (intmask & SDHCI_INT_DATA_TIMEOUT)
++ host->data->error = -ETIMEDOUT;
++ else if (intmask & (SDHCI_INT_DATA_CRC | SDHCI_INT_DATA_END_BIT))
++ host->data->error = -EILSEQ;
++ else if (intmask & SDHCI_INT_ADMA_ERROR)
++ host->data->error = -EIO;
++
++ if (host->data->error)
++ sdhci_finish_data(host);
++ else {
++ if (intmask & (SDHCI_INT_DATA_AVAIL | SDHCI_INT_SPACE_AVAIL))
++ sdhci_transfer_pio(host);
++
++ /*
++ * We currently don't do anything fancy with DMA
++ * boundaries, but as we can't disable the feature
++ * we need to at least restart the transfer.
++ */
++ if (intmask & SDHCI_INT_DMA_END)
++ writel(readl(host->ioaddr + SDHCI_DMA_ADDRESS),
++ host->ioaddr + SDHCI_DMA_ADDRESS);
++
++ if (intmask & SDHCI_INT_DATA_END) {
++ if (host->cmd) {
++ /*
++ * Data managed to finish before the
++ * command completed. Make sure we do
++ * things in the proper order.
++ */
++ host->data_early = 1;
++ } else {
++ sdhci_finish_data(host);
++ }
++ }
++ }
++}
++
++static irqreturn_t sdhci_irq(int irq, void *dev_id)
++{
++ irqreturn_t result;
++ struct sdhci_host* host = dev_id;
++ u32 intmask;
++ int cardint = 0;
++
++ spin_lock(&host->lock);
++
++ intmask = readl(host->ioaddr + SDHCI_INT_STATUS);
++
++ if (!intmask || intmask == 0xffffffff) {
++ result = IRQ_NONE;
++ goto out;
++ }
++
++ DBG("*** %s got interrupt: 0x%08x\n",
++ mmc_hostname(host->mmc), intmask);
++
++ if (intmask & (SDHCI_INT_CARD_INSERT | SDHCI_INT_CARD_REMOVE)) {
++ writel(intmask & (SDHCI_INT_CARD_INSERT | SDHCI_INT_CARD_REMOVE),
++ host->ioaddr + SDHCI_INT_STATUS);
++ tasklet_schedule(&host->card_tasklet);
++ }
++
++ intmask &= ~(SDHCI_INT_CARD_INSERT | SDHCI_INT_CARD_REMOVE);
++
++ if (intmask & SDHCI_INT_CMD_MASK) {
++ writel(intmask & SDHCI_INT_CMD_MASK,
++ host->ioaddr + SDHCI_INT_STATUS);
++ sdhci_cmd_irq(host, intmask & SDHCI_INT_CMD_MASK);
++ }
++
++ if (intmask & SDHCI_INT_DATA_MASK) {
++ writel(intmask & SDHCI_INT_DATA_MASK,
++ host->ioaddr + SDHCI_INT_STATUS);
++ sdhci_data_irq(host, intmask & SDHCI_INT_DATA_MASK);
++ }
++
++ intmask &= ~(SDHCI_INT_CMD_MASK | SDHCI_INT_DATA_MASK);
++
++ intmask &= ~SDHCI_INT_ERROR;
++
++ if (intmask & SDHCI_INT_BUS_POWER) {
++ printk(KERN_ERR "%s: Card is consuming too much power!\n",
++ mmc_hostname(host->mmc));
++ writel(SDHCI_INT_BUS_POWER, host->ioaddr + SDHCI_INT_STATUS);
++ }
++
++ intmask &= ~SDHCI_INT_BUS_POWER;
++
++ if (intmask & SDHCI_INT_CARD_INT)
++ cardint = 1;
++
++ intmask &= ~SDHCI_INT_CARD_INT;
++
++ if (intmask) {
++ printk(KERN_ERR "%s: Unexpected interrupt 0x%08x.\n",
++ mmc_hostname(host->mmc), intmask);
++ sdhci_dumpregs(host);
++
++ writel(intmask, host->ioaddr + SDHCI_INT_STATUS);
++ }
++
++ result = IRQ_HANDLED;
++
++ mmiowb();
++out:
++ spin_unlock(&host->lock);
++
++ /*
++ * We have to delay this as it calls back into the driver.
++ */
++ if (cardint)
++ mmc_signal_sdio_irq(host->mmc);
++
++ return result;
++}
++
++/*****************************************************************************\
++ * *
++ * Suspend/resume *
++ * *
++\*****************************************************************************/
++
++#ifdef CONFIG_PM
++
++int sdhci_suspend_host(struct sdhci_host *host, pm_message_t state)
++{
++ int ret;
++
++ ret = mmc_suspend_host(host->mmc, state);
++ if (ret)
++ return ret;
++
++ free_irq(host->irq, host);
++
++ return 0;
++}
++
++EXPORT_SYMBOL_GPL(sdhci_suspend_host);
++
++int sdhci_resume_host(struct sdhci_host *host)
++{
++ int ret;
++
++ if (host->flags & SDHCI_USE_DMA) {
++/*
++ if (host->ops->enable_dma)
++ host->ops->enable_dma(host);
++*/
++ }
++
++ ret = request_irq(host->irq, sdhci_irq, IRQF_SHARED,
++ mmc_hostname(host->mmc), host);
++ if (ret)
++ return ret;
++
++ sdhci_init(host);
++ mmiowb();
++
++ ret = mmc_resume_host(host->mmc);
++ if (ret)
++ return ret;
++
++ return 0;
++}
++
++EXPORT_SYMBOL_GPL(sdhci_resume_host);
++
++#endif /* CONFIG_PM */
++
++/*****************************************************************************\
++ * *
++ * Device allocation/registration *
++ * *
++\*****************************************************************************/
++
++struct sdhci_host *sdhci_alloc_host(struct device *dev,
++ size_t priv_size)
++{
++ struct mmc_host *mmc;
++ struct sdhci_host *host;
++
++ WARN_ON(dev == NULL);
++
++ mmc = mmc_alloc_host(sizeof(struct sdhci_host) + priv_size, dev);
++ if (!mmc)
++ return ERR_PTR(-ENOMEM);
++
++ host = mmc_priv(mmc);
++ host->mmc = mmc;
++
++ return host;
++}
++
++//EXPORT_SYMBOL_GPL(sdhci_alloc_host);
++
++int sdhci_add_host(struct sdhci_host *host)
++{
++ struct mmc_host *mmc;
++ unsigned int caps, temp;
++ int ret;
++
++ WARN_ON(host == NULL);
++ if (host == NULL)
++ return -EINVAL;
++#if 0
++ //TODO
++//Both ports's capabilities are 0, software needs to reset SDIO
++#define SDIO000 0x1e740000
++#define SDIO004 0x1e740004
++
++#define SDIO_ALL_SOFTWARE_RESET 0x01
++
++ if ((*(unsigned int*)(IO_ADDRESS(0x1E740140)) == 0) && (*(unsigned int*)(IO_ADDRESS(0x1E740240)) == 0)) {
++ temp = *(unsigned int*)(IO_ADDRESS(SDIO000));
++ *(unsigned int*)(IO_ADDRESS(SDIO000)) = temp | SDIO_ALL_SOFTWARE_RESET;
++ barrier();
++ do {
++ temp = (*(unsigned int*)(IO_ADDRESS(SDIO000)) & SDIO_ALL_SOFTWARE_RESET);
++ } while (temp == SDIO_ALL_SOFTWARE_RESET);
++ }
++ //Card detect debounce timing
++ *(unsigned int*)(IO_ADDRESS(SDIO004)) = 0x1000;
++#endif
++ ///////////////////////////////////////////////////////////////////
++
++ mmc = host->mmc;
++
++ if (debug_quirks)
++ host->quirks = debug_quirks;
++
++ sdhci_reset(host, SDHCI_RESET_ALL);
++
++ host->version = readw(host->ioaddr + SDHCI_HOST_VERSION);
++ host->version = (host->version & SDHCI_SPEC_VER_MASK)
++ >> SDHCI_SPEC_VER_SHIFT;
++ if (host->version > SDHCI_SPEC_200) {
++ printk(KERN_ERR "%s: Unknown controller version (%d). "
++ "You may experience problems.\n", mmc_hostname(mmc),
++ host->version);
++ }
++
++ caps = readl(host->ioaddr + SDHCI_CAPABILITIES);
++
++ //Ryan Add for timeout
++ host->quirks |= SDHCI_QUIRK_BROKEN_TIMEOUT_VAL;
++// host->quirks |= SDHCI_QUIRK_MULTIBLOCK_READ_ACMD12;
++
++ if (host->quirks & SDHCI_QUIRK_FORCE_DMA)
++ host->flags |= SDHCI_USE_DMA;
++ else if (!(caps & SDHCI_CAN_DO_DMA))
++ DBG("Controller doesn't have DMA capability\n");
++ else
++ host->flags |= SDHCI_USE_DMA;
++
++ if ((host->quirks & SDHCI_QUIRK_BROKEN_DMA) &&
++ (host->flags & SDHCI_USE_DMA)) {
++ DBG("Disabling DMA as it is marked broken\n");
++ host->flags &= ~SDHCI_USE_DMA;
++ }
++
++ if (host->flags & SDHCI_USE_DMA) {
++ if ((host->version >= SDHCI_SPEC_200) &&
++ (caps & SDHCI_CAN_DO_ADMA2))
++ host->flags |= SDHCI_USE_ADMA;
++ }
++
++ if ((host->quirks & SDHCI_QUIRK_BROKEN_ADMA) &&
++ (host->flags & SDHCI_USE_ADMA)) {
++ DBG("Disabling ADMA as it is marked broken\n");
++ host->flags &= ~SDHCI_USE_ADMA;
++ }
++
++ if (host->flags & SDHCI_USE_DMA) {
++/*
++ if (host->ops->enable_dma) {
++ if (host->ops->enable_dma(host)) {
++ printk(KERN_WARNING "%s: No suitable DMA "
++ "available. Falling back to PIO.\n",
++ mmc_hostname(mmc));
++ host->flags &= ~(SDHCI_USE_DMA | SDHCI_USE_ADMA);
++ }
++ }
++*/
++ }
++
++ if (host->flags & SDHCI_USE_ADMA) {
++ /*
++ * We need to allocate descriptors for all sg entries
++ * (128) and potentially one alignment transfer for
++ * each of those entries.
++ */
++ host->adma_desc = kmalloc((128 * 2 + 1) * 4, GFP_KERNEL);
++ host->align_buffer = kmalloc(128 * 4, GFP_KERNEL);
++ if (!host->adma_desc || !host->align_buffer) {
++ kfree(host->adma_desc);
++ kfree(host->align_buffer);
++ printk(KERN_WARNING "%s: Unable to allocate ADMA "
++ "buffers. Falling back to standard DMA.\n",
++ mmc_hostname(mmc));
++ host->flags &= ~SDHCI_USE_ADMA;
++ }
++ }
++
++ /*
++ * If we use DMA, then it's up to the caller to set the DMA
++ * mask, but PIO does not need the hw shim so we set a new
++ * mask here in that case.
++ */
++ if (!(host->flags & SDHCI_USE_DMA)) {
++ host->dma_mask = DMA_BIT_MASK(64);
++ mmc_dev(host->mmc)->dma_mask = &host->dma_mask;
++ }
++
++// host->max_clk =
++// (caps & SDHCI_CLOCK_BASE_MASK) >> SDHCI_CLOCK_BASE_SHIFT;
++
++ host->max_clk = ast_sdhc_info->sd_clock_src_get()/1000000;
++// printk("host->max_clk = %d Mhz\n",host->max_clk);
++
++ if (host->max_clk == 0) {
++ printk(KERN_ERR "%s: Hardware doesn't specify base clock "
++ "frequency.\n", mmc_hostname(mmc));
++ return -ENODEV;
++ }
++ host->max_clk *= 1000000;
++
++ //Ryan modify for calc timeout issue
++ host->timeout_clk = ast_sdhc_info->sd_clock_src_get()/1000000;
++// (caps & SDHCI_TIMEOUT_CLK_MASK) >> SDHCI_TIMEOUT_CLK_SHIFT;
++ if (host->timeout_clk == 0) {
++ printk(KERN_ERR "%s: Hardware doesn't specify timeout clock "
++ "frequency.\n", mmc_hostname(mmc));
++ return -ENODEV;
++ }
++ if (caps & SDHCI_TIMEOUT_CLK_UNIT)
++ host->timeout_clk *= 1000;
++
++ /*
++ * Set host parameters.
++ */
++ mmc->ops = &sdhci_ops;
++ mmc->f_min = host->max_clk / 256;
++ mmc->f_max = host->max_clk;
++ mmc->caps = MMC_CAP_4_BIT_DATA | MMC_CAP_SDIO_IRQ;
++
++ if ((caps & SDHCI_CAN_DO_HISPD) ||
++ (host->quirks & SDHCI_QUIRK_FORCE_HIGHSPEED))
++ mmc->caps |= MMC_CAP_SD_HIGHSPEED;
++
++ mmc->caps |= MMC_CAP_MMC_HIGHSPEED;
++
++ mmc->ocr_avail = 0;
++ if (caps & SDHCI_CAN_VDD_330)
++ mmc->ocr_avail |= MMC_VDD_32_33|MMC_VDD_33_34;
++ if (caps & SDHCI_CAN_VDD_300)
++ mmc->ocr_avail |= MMC_VDD_29_30|MMC_VDD_30_31;
++ if (caps & SDHCI_CAN_VDD_180)
++ mmc->ocr_avail |= MMC_VDD_165_195;
++
++ if (mmc->ocr_avail == 0) {
++ printk(KERN_ERR "%s: Hardware doesn't report any "
++ "support voltages.\n", mmc_hostname(mmc));
++ return -ENODEV;
++ }
++
++ spin_lock_init(&host->lock);
++
++ /*
++ * Maximum number of segments. Depends on if the hardware
++ * can do scatter/gather or not.
++ */
++ if (host->flags & SDHCI_USE_ADMA)
++ mmc->max_hw_segs = 128;
++ else if (host->flags & SDHCI_USE_DMA)
++ mmc->max_hw_segs = 1;
++ else /* PIO */
++ mmc->max_hw_segs = 128;
++ mmc->max_phys_segs = 128;
++
++ /*
++ * Maximum number of sectors in one transfer. Limited by DMA boundary
++ * size (512KiB).
++ */
++ mmc->max_req_size = 524288;
++
++ /*
++ * Maximum segment size. Could be one segment with the maximum number
++ * of bytes. When doing hardware scatter/gather, each entry cannot
++ * be larger than 64 KiB though.
++ */
++ if (host->flags & SDHCI_USE_ADMA)
++ mmc->max_seg_size = 65536;
++ else
++ mmc->max_seg_size = mmc->max_req_size;
++
++ /*
++ * Maximum block size. This varies from controller to controller and
++ * is specified in the capabilities register.
++ */
++ mmc->max_blk_size = (caps & SDHCI_MAX_BLOCK_MASK) >> SDHCI_MAX_BLOCK_SHIFT;
++ if (mmc->max_blk_size >= 3) {
++ printk(KERN_WARNING "%s: Invalid maximum block size, "
++ "assuming 512 bytes\n", mmc_hostname(mmc));
++ mmc->max_blk_size = 512;
++ } else
++ mmc->max_blk_size = 512 << mmc->max_blk_size;
++
++ /*
++ * Maximum block count.
++ */
++ mmc->max_blk_count = 65535;
++
++ /*
++ * Init tasklets.
++ */
++ tasklet_init(&host->card_tasklet,
++ sdhci_tasklet_card, (unsigned long)host);
++ tasklet_init(&host->finish_tasklet,
++ sdhci_tasklet_finish, (unsigned long)host);
++
++ setup_timer(&host->timer, sdhci_timeout_timer, (unsigned long)host);
++
++ ret = request_irq(host->irq, sdhci_irq, IRQF_SHARED,
++ mmc_hostname(mmc), host);
++ if (ret)
++ goto untasklet;
++
++ sdhci_init(host);
++
++#ifdef CONFIG_MMC_DEBUG
++ sdhci_dumpregs(host);
++#endif
++
++#ifdef CONFIG_LEDS_CLASS
++ snprintf(host->led_name, sizeof(host->led_name),
++ "%s::", mmc_hostname(mmc));
++ host->led.name = host->led_name;
++ host->led.brightness = LED_OFF;
++ host->led.default_trigger = mmc_hostname(mmc);
++ host->led.brightness_set = sdhci_led_control;
++
++ ret = led_classdev_register(mmc_dev(mmc), &host->led);
++ if (ret)
++ goto reset;
++#endif
++
++ mmiowb();
++
++ mmc_add_host(mmc);
++
++ printk(KERN_INFO "%s: SDHCI controller on %s [%s] using %s%s\n",
++ mmc_hostname(mmc), host->hw_name, dev_name(mmc_dev(mmc)),
++ (host->flags & SDHCI_USE_ADMA)?"A":"",
++ (host->flags & SDHCI_USE_DMA)?"DMA":"PIO");
++
++ return 0;
++
++#ifdef CONFIG_LEDS_CLASS
++reset:
++ sdhci_reset(host, SDHCI_RESET_ALL);
++ free_irq(host->irq, host);
++#endif
++untasklet:
++ tasklet_kill(&host->card_tasklet);
++ tasklet_kill(&host->finish_tasklet);
++
++ return ret;
++}
++
++//EXPORT_SYMBOL_GPL(sdhci_add_host);
++
++static int sdhci_probe(struct platform_device *pdev)
++{
++ struct sdhci_host *host;
++ struct resource *res;
++ int ret;
++ ast_sdhc_info = pdev->dev.platform_data;
++
++ host = sdhci_alloc_host(&pdev->dev, sizeof(struct sdhci_host));
++
++ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
++ if (NULL == res) {
++ dev_err(&pdev->dev, "cannot get IORESOURCE_MEM\n");
++ ret = -ENOENT;
++ return ret;
++ }
++
++ if (!request_mem_region(res->start, resource_size(res), res->name)) {
++ dev_err(&pdev->dev, "cannot reserved region\n");
++ ret = -ENXIO;
++ return ret;
++ }
++
++ host->ioaddr = ioremap(res->start, resource_size(res));
++ if (!host->ioaddr) {
++ ret = -EIO;
++ return ret;
++ }
++
++ host->hw_name = res->name;
++ host->irq = platform_get_irq(pdev, 0);
++ if (host->irq < 0) {
++ dev_err(&pdev->dev, "no irq specified\n");
++ ret = -ENOENT;
++ return ret;
++ }
++
++ ret = sdhci_add_host(host);
++
++ return ret;
++}
++
++void sdhci_remove_host(struct sdhci_host *host, int dead)
++{
++ unsigned long flags;
++
++ if (dead) {
++ spin_lock_irqsave(&host->lock, flags);
++
++ host->flags |= SDHCI_DEVICE_DEAD;
++
++ if (host->mrq) {
++ printk(KERN_ERR "%s: Controller removed during "
++ " transfer!\n", mmc_hostname(host->mmc));
++
++ host->mrq->cmd->error = -ENOMEDIUM;
++ tasklet_schedule(&host->finish_tasklet);
++ }
++
++ spin_unlock_irqrestore(&host->lock, flags);
++ }
++
++ mmc_remove_host(host->mmc);
++
++#ifdef CONFIG_LEDS_CLASS
++ led_classdev_unregister(&host->led);
++#endif
++
++ if (!dead)
++ sdhci_reset(host, SDHCI_RESET_ALL);
++
++ free_irq(host->irq, host);
++
++ del_timer_sync(&host->timer);
++
++ tasklet_kill(&host->card_tasklet);
++ tasklet_kill(&host->finish_tasklet);
++
++ kfree(host->adma_desc);
++ kfree(host->align_buffer);
++
++ host->adma_desc = NULL;
++ host->align_buffer = NULL;
++}
++
++EXPORT_SYMBOL_GPL(sdhci_remove_host);
++
++void sdhci_free_host(struct sdhci_host *host)
++{
++ mmc_free_host(host->mmc);
++}
++
++EXPORT_SYMBOL_GPL(sdhci_free_host);
++
++/*****************************************************************************\
++ * *
++ * Driver init/exit *
++ * *
++\*****************************************************************************/
++
++static struct platform_driver ast_sdhci_driver = {
++ .driver.name = "ast_sdhci",
++ .driver.owner = THIS_MODULE,
++ .probe = sdhci_probe,
++ .remove = __exit_p(sdhci_remove_host),
++#ifdef CONFIG_PM
++ .resume = sdhci_resume_host,
++ .suspend = sdhci_suspend_host,
++#endif
++};
++
++static int __init ast_sdhci_drv_init(void)
++{
++ return platform_driver_register(&ast_sdhci_driver);
++}
++
++static void __exit ast_sdhci_drv_exit(void)
++{
++ platform_driver_unregister(&ast_sdhci_driver);
++}
++
++module_init(ast_sdhci_drv_init);
++module_exit(ast_sdhci_drv_exit);
++
++module_param(debug_quirks, uint, 0444);
++
++MODULE_AUTHOR("Pierre Ossman <drzeus@drzeus.cx> & River Huang");
++MODULE_DESCRIPTION("ASPEED Secure Digital Host Controller Interface core driver");
++MODULE_LICENSE("GPL");
++
++MODULE_PARM_DESC(debug_quirks, "Force certain quirks.");
+diff --git a/drivers/mtd/devices/m25p80.c b/drivers/mtd/devices/m25p80.c
+index 6659b22..45cb05a 100644
+--- a/drivers/mtd/devices/m25p80.c
++++ b/drivers/mtd/devices/m25p80.c
+@@ -503,6 +503,15 @@ static struct flash_info __devinitdata m25p_data [] = {
+ { "at26df161a", 0x1f4601, 0, 64 * 1024, 32, SECT_4K, },
+ { "at26df321", 0x1f4701, 0, 64 * 1024, 64, SECT_4K, },
+
++ /* Macronix */
++ { "mx25l4005a", 0xc22013, 0, 64 * 1024, 8, SECT_4K },
++ { "mx25l3205d", 0xc22016, 0, 64 * 1024, 64, 0 },
++ { "mx25l6405d", 0xc22017, 0, 64 * 1024, 128, 0 },
++ { "mx25l12805d", 0xc22018, 0, 64 * 1024, 256, 0 },
++
++ { "mx25l12855e", 0xc22618, 0, 64 * 1024, 256, 0 },
++ { "mx25l25635e", 0xc22019, 0, 64 * 1024, 512, 0 },
++
+ /* Spansion -- single (large) sector size only, at least
+ * for the chips listed here (without boot sectors).
+ */
+@@ -511,7 +520,7 @@ static struct flash_info __devinitdata m25p_data [] = {
+ { "s25sl016a", 0x010214, 0, 64 * 1024, 32, },
+ { "s25sl032a", 0x010215, 0, 64 * 1024, 64, },
+ { "s25sl064a", 0x010216, 0, 64 * 1024, 128, },
+- { "s25sl12800", 0x012018, 0x0300, 256 * 1024, 64, },
++ { "s25sl12800", 0x012018, 0x0300, 256 * 1024, 64, },
+ { "s25sl12801", 0x012018, 0x0301, 64 * 1024, 256, },
+
+ /* SST -- large erase sizes are "overlays", "sectors" are 4K */
+diff --git a/drivers/mtd/maps/Kconfig b/drivers/mtd/maps/Kconfig
+index 5ea1693..bafa60c 100644
+--- a/drivers/mtd/maps/Kconfig
++++ b/drivers/mtd/maps/Kconfig
+@@ -351,6 +351,10 @@ config MTD_ARM_INTEGRATOR
+ tristate "CFI Flash device mapped on ARM Integrator/P720T"
+ depends on ARM && MTD_CFI
+
++config MTD_AST
++ tristate "CFI Flash device mapped on ASPEED"
++ depends on ARCH_ASPEED && MTD_CFI
++
+ config MTD_CDB89712
+ tristate "Cirrus CDB89712 evaluation board mappings"
+ depends on MTD_CFI && ARCH_CDB89712
+diff --git a/drivers/mtd/maps/Makefile b/drivers/mtd/maps/Makefile
+index 6d9ba35..3d8b1f2 100644
+--- a/drivers/mtd/maps/Makefile
++++ b/drivers/mtd/maps/Makefile
+@@ -9,6 +9,7 @@ endif
+ # Chip mappings
+ obj-$(CONFIG_MTD_CDB89712) += cdb89712.o
+ obj-$(CONFIG_MTD_ARM_INTEGRATOR)+= integrator-flash.o
++obj-$(CONFIG_MTD_AST) += ast-nor.o
+ obj-$(CONFIG_MTD_CFI_FLAGADM) += cfi_flagadm.o
+ obj-$(CONFIG_MTD_DC21285) += dc21285.o
+ obj-$(CONFIG_MTD_DILNETPC) += dilnetpc.o
+diff --git a/drivers/mtd/maps/ast-nor.c b/drivers/mtd/maps/ast-nor.c
+new file mode 100644
+index 0000000..7cc4741
+--- /dev/null
++++ b/drivers/mtd/maps/ast-nor.c
+@@ -0,0 +1,221 @@
++/*======================================================================
++
++ drivers/mtd/maps/ast-nor.c: ASPEED flash map driver
++
++ Copyright (C) 2012-2020 ASPEED Technology Inc.
++
++ This program is free software; you can redistribute it and/or modify
++ it under the terms of the GNU General Public License as published by
++ the Free Software Foundation; either version 2 of the License, or
++ (at your option) any later version.
++
++ This program is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ GNU General Public License for more details.
++
++ You should have received a copy of the GNU General Public License
++ along with this program; if not, write to the Free Software
++ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++
++ This is access code for flashes using ARM's flash partitioning
++ standards.
++
++* History:
++* 2012.10.11: Initial version [Ryan Chen]
++
++======================================================================*/
++
++#include <linux/module.h>
++#include <linux/types.h>
++#include <linux/kernel.h>
++#include <linux/slab.h>
++#include <linux/ioport.h>
++#include <linux/platform_device.h>
++#include <linux/init.h>
++
++#include <linux/mtd/mtd.h>
++#include <linux/mtd/map.h>
++#include <linux/mtd/partitions.h>
++
++#include <asm/mach/flash.h>
++#include <mach/hardware.h>
++#include <asm/io.h>
++#include <asm/system.h>
++#include <mach/platform.h>
++
++#define PFX "ast-flash: "
++
++struct ast_flash_info {
++ struct mtd_info *mtd;
++ struct map_info map;
++ struct resource *res;
++ struct mtd_partition *partitions;
++// struct flash_platform_data *plat;
++};
++
++static int ast_flash_probe(struct platform_device *pdev)
++{
++ struct ast_flash_info *info;
++ struct flash_platform_data *pdata = pdev->dev.platform_data;
++ struct resource *res = NULL;
++
++ int ret;
++ static int no_partitions;
++ info = kzalloc(sizeof(struct ast_flash_info), GFP_KERNEL);
++ if (info == NULL) {
++ printk(KERN_ERR PFX "no memory for flash info\n");
++ return -ENOMEM;
++ }
++
++ /* request register map resource & check */
++ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
++ if (!res) {
++ dev_err(&pdev->dev, "register resources unusable\n");
++ ret = -ENXIO;
++ goto free_dev;
++ }
++
++ if (!request_mem_region(res->start, res->end - res->start + 1, pdev->name)) {
++ ret = -EBUSY;
++ goto free_something_1;
++ }
++
++ info->map.virt = ioremap(res->start, (res->end - res->start) + 1);
++ if (!info->map.virt) {
++ dev_err(&pdev->dev, "cannot map ast_flash_info registers\n");
++ ret = -ENOMEM;
++ goto release_mem;
++ }
++ info->map.phys = res->start;
++ info->map.size = res->end - res->start + 1;
++ info->map.name = (char *) pdata->map_name;
++#ifdef CONFIG_MTD_MAP_BANK_WIDTH_1
++ info->map.bankwidth = 1;
++#endif
++#ifdef CONFIG_MTD_MAP_BANK_WIDTH_2
++ info->map.bankwidth = 2;
++#endif
++ platform_set_drvdata(pdev, info);
++
++ printk("%s %x, %x, %s \n",__FUNCTION__,res->start,res->end,pdev->dev.bus_id);
++
++ printk("%s: area %08lx, size %lx\n", __FUNCTION__, info->map.phys, info->map.size);
++
++ printk("%s: virt at %08x, res->start %x \n", __FUNCTION__, (int)info->map.virt,res->start);
++
++ info->partitions = pdata->parts;
++
++ simple_map_init(&info->map);
++
++ /* probe for the device(s) */
++
++ info->mtd = do_map_probe(pdata->map_name, &info->map);
++ if (!info->mtd) {
++ ret = -EIO;
++ goto reset_drvdata;
++ }
++
++ /* mark ourselves as the owner */
++ info->mtd->owner = THIS_MODULE;
++
++ no_partitions = pdata->nr_parts;//ARRAY_SIZE(nor_partitions);
++ ret = add_mtd_partitions(info->mtd, info->partitions, no_partitions);
++ if (ret){
++ printk(KERN_ERR PFX "cannot add/parse partitions\n");
++ goto free_something_2;
++ }
++
++ return 0;
++
++ /* fall through to exit error */
++
++free_something_2:
++ del_mtd_partitions(info->mtd);
++ map_destroy(info->mtd);
++reset_drvdata:
++ //kfree(info->partitions);
++ platform_set_drvdata(pdev, NULL);
++//unmap_regs:
++ iounmap(info->map.virt);
++release_mem:
++ release_mem_region(res->start, (res->end - res->start) + 1);
++free_something_1:
++
++free_dev:
++ kfree(info);
++
++ return ret;
++}
++
++static int ast_flash_remove(struct platform_device *pdev)
++{
++ struct ast_flash_info *info = platform_get_drvdata(pdev);
++ struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
++
++ if(info) {
++ if (info->mtd) {
++ del_mtd_partitions(info->mtd);
++ map_destroy(info->mtd);
++ }
++ platform_set_drvdata(pdev, NULL);
++ iounmap(info->map.virt);
++
++ release_mem_region(res->start, (res->end - res->start) + 1);
++ kfree(info);
++ }
++
++ return 0;
++}
++
++
++#ifdef CONFIG_PM
++static int
++ast_flash_suspend(struct platform_device *pdev, pm_message_t msg)
++{
++ pr_debug("ast_flash_suspend\n");
++
++ return 0;
++}
++
++static int
++ast_flash_resume(struct platform_device *pdev)
++{
++ pr_debug("ast_flash_resume\n");
++
++ return 0;
++}
++#else
++#define ast_flash_suspend NULL
++#define ast_flash_resume NULL
++#endif
++
++static struct platform_driver ast_flash_driver = {
++ .probe = ast_flash_probe,
++ .remove = ast_flash_remove,
++ .suspend = ast_flash_suspend,
++ .resume = ast_flash_resume,
++ .driver = {
++ .name = "ast-nor",
++ .owner = THIS_MODULE,
++ },
++};
++
++static int __init ast_flash_init(void)
++{
++ printk("ASPEED NOR-Flash Driver, (c) 2012 Aspeed Tech \n");
++ return platform_driver_register(&ast_flash_driver);
++}
++
++static void __exit ast_flash_exit(void)
++{
++ platform_driver_unregister(&ast_flash_driver);
++}
++
++module_init(ast_flash_init);
++module_exit(ast_flash_exit);
++
++MODULE_AUTHOR("Ryan Chen");
++MODULE_DESCRIPTION("ASPEED AST CFI map driver");
++MODULE_LICENSE("GPL");
++MODULE_ALIAS("platform:astflash");
+diff --git a/drivers/mtd/nand/Kconfig b/drivers/mtd/nand/Kconfig
+index 1c2e945..e1ab76b 100644
+--- a/drivers/mtd/nand/Kconfig
++++ b/drivers/mtd/nand/Kconfig
+@@ -56,6 +56,12 @@ config MTD_NAND_H1900
+ help
+ This enables the driver for the iPAQ h1900 flash.
+
++config MTD_NAND_AST
++ tristate "AST NAND flash"
++ depends on MTD_NAND && ARCH_ASPEED && MTD_PARTITIONS
++ help
++ This enables the driver for the ASPEED NAND flash.
++
+ config MTD_NAND_GPIO
+ tristate "GPIO NAND Flash driver"
+ depends on GENERIC_GPIO && ARM
+diff --git a/drivers/mtd/nand/Makefile b/drivers/mtd/nand/Makefile
+index b661586..129dfd3 100644
+--- a/drivers/mtd/nand/Makefile
++++ b/drivers/mtd/nand/Makefile
+@@ -36,5 +36,6 @@ obj-$(CONFIG_MTD_NAND_FSL_ELBC) += fsl_elbc_nand.o
+ obj-$(CONFIG_MTD_NAND_FSL_UPM) += fsl_upm.o
+ obj-$(CONFIG_MTD_NAND_SH_FLCTL) += sh_flctl.o
+ obj-$(CONFIG_MTD_NAND_MXC) += mxc_nand.o
++obj-$(CONFIG_MTD_NAND_AST) += ast_nand.o
+
+ nand-objs := nand_base.o nand_bbt.o
+diff --git a/drivers/mtd/nand/ast_nand.c b/drivers/mtd/nand/ast_nand.c
+new file mode 100755
+index 0000000..240a832
+--- /dev/null
++++ b/drivers/mtd/nand/ast_nand.c
+@@ -0,0 +1,197 @@
++/********************************************************************************
++* File Name : drivers/mtd/nand/aspeed_nand.c
++* Author : Ryan Chen
++* Description : ASPEED NAND driver
++*
++* Copyright (C) 2012-2020 ASPEED Technology Inc.
++* This program is free software; you can redistribute it and/or modify
++* it under the terms of the GNU General Public License as published by the Free Software Foundation;
++* either version 2 of the License, or (at your option) any later version.
++*
++* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
++* without even the implied warranty of MERCHANTABILITY or
++* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
++*
++* You should have received a copy of the GNU General Public License
++* along with this program; if not, write to the Free Software
++* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++
++* Overview:
++* This is a device driver for the NAND flash device found on the
++* ASPEED board which utilizes the Samsung K9F2808 part. This is
++* a 128Mibit (16MiB x 8 bits) NAND flash device.
++
++* History :
++* 1. 2012/10/20 Ryan Chen create this file
++*
++********************************************************************************/
++#include <linux/io.h>
++#include <linux/module.h>
++#include <linux/platform_device.h>
++#include <linux/slab.h>
++#include <linux/mtd/mtd.h>
++#include <linux/mtd/nand.h>
++#include <linux/mtd/partitions.h>
++
++struct ast_nand_data {
++ struct nand_chip chip;
++ struct mtd_info mtd;
++ void __iomem *io_base;
++#ifdef CONFIG_MTD_PARTITIONS
++ int nr_parts;
++ struct mtd_partition *parts;
++#endif
++};
++
++static struct nand_ecclayout aspeed_nand_hw_eccoob = {
++ .eccbytes = 24,
++ .eccpos = {40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63},
++};
++
++/* hardware specific access to control-lines */
++static void
++ast_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int ctrl)
++{
++ struct nand_chip *chip = mtd->priv;
++
++ if (cmd != NAND_CMD_NONE) {
++ //writeb(cmd, chip->IO_ADDR_W + ((ctrl & 0x6) << 11));
++ //user mode cmd addr[13:12]
++ if(ctrl & NAND_CLE)
++ writeb(cmd, chip->IO_ADDR_W + (0x1 << 12));
++ else if (ctrl & NAND_ALE)
++ writeb(cmd, chip->IO_ADDR_W + (0x2 << 12));
++ else
++ writeb(cmd, chip->IO_ADDR_W + (1 << 12));
++ }
++}
++
++/*
++ * Main initialization routine
++ */
++static int __init
++ast_nand_probe(struct platform_device *pdev)
++{
++ struct ast_nand_data *data;
++ struct platform_nand_data *pdata = pdev->dev.platform_data;
++ int res = 0;
++
++ /* Allocate memory for the device structure (and zero it) */
++ data = kzalloc(sizeof(struct ast_nand_data), GFP_KERNEL);
++ if (!data) {
++ dev_err(&pdev->dev, "failed to allocate device structure.\n");
++ return -ENOMEM;
++ }
++
++ data->io_base = ioremap(pdev->resource[0].start,
++ pdev->resource[0].end - pdev->resource[0].start );
++ if (data->io_base == NULL) {
++ dev_err(&pdev->dev, "ioremap failed\n");
++ kfree(data);
++ return -EIO;
++ }
++
++ data->chip.priv = &data;
++ data->mtd.priv = &data->chip;
++ data->mtd.owner = THIS_MODULE;
++ data->mtd.name = pdev->dev.bus_id;
++
++ data->chip.IO_ADDR_R = data->io_base;
++ data->chip.IO_ADDR_W = data->io_base;
++ data->chip.cmd_ctrl = ast_hwcontrol;
++ data->chip.dev_ready = pdata->ctrl.dev_ready;
++ data->chip.select_chip = pdata->ctrl.select_chip;
++ data->chip.chip_delay = pdata->chip.chip_delay;
++ data->chip.options |= pdata->chip.options;
++
++ data->chip.ecc.hwctl = pdata->ctrl.hwcontrol;
++ data->chip.ecc.calculate = pdata->ctrl.calculate;
++ data->chip.ecc.correct = pdata->ctrl.correct;
++// data->chip.ecc.layout = pdata->chip.ecclayout;
++ data->chip.ecc.layout = &aspeed_nand_hw_eccoob;
++
++ data->chip.ecc.bytes = 6;
++ data->chip.ecc.size = 512;
++ data->chip.ecc.mode = NAND_ECC_HW; //NAND_ECC_SOFT;
++
++ platform_set_drvdata(pdev, data);
++
++ /* Scan to find existance of the device */
++ if (nand_scan(&data->mtd, 1)) {
++ res = -ENXIO;
++ goto out;
++ }
++#ifdef CONFIG_MTD_PARTITIONS
++ if (pdata->chip.part_probe_types) {
++ res = parse_mtd_partitions(&data->mtd,
++ pdata->chip.part_probe_types,
++ &data->parts, 0);
++ if (res > 0) {
++ add_mtd_partitions(&data->mtd, data->parts, res);
++ return 0;
++ }
++ }
++ if (pdata->chip.partitions) {
++ data->parts = pdata->chip.partitions;
++ res = add_mtd_partitions(&data->mtd, data->parts,
++ pdata->chip.nr_partitions);
++ } else
++#endif
++ res = add_mtd_device(&data->mtd);
++
++ if (!res)
++ return res;
++
++ nand_release(&data->mtd);
++out:
++ platform_set_drvdata(pdev, NULL);
++ iounmap(data->io_base);
++ kfree(data);
++
++ return res;
++
++}
++
++static int __devexit ast_nand_remove(struct platform_device *pdev)
++{
++ struct ast_nand_data *data = platform_get_drvdata(pdev);
++#ifdef CONFIG_MTD_PARTITIONS
++ struct platform_nand_data *pdata = pdev->dev.platform_data;
++#endif
++
++ nand_release(&data->mtd);
++#ifdef CONFIG_MTD_PARTITIONS
++ if (data->parts && data->parts != pdata->chip.partitions)
++ kfree(data->parts);
++#endif
++ iounmap(data->io_base);
++ kfree(data);
++
++ return 0;
++}
++
++static struct platform_driver ast_nand_driver = {
++ .probe = ast_nand_probe,
++ .remove = ast_nand_remove,
++ .driver = {
++ .name = "ast-nand",
++ .owner = THIS_MODULE,
++ },
++};
++
++static int __init ast_nand_init(void)
++{
++ return platform_driver_register(&ast_nand_driver);
++}
++
++static void __exit ast_nand_exit(void)
++{
++ platform_driver_unregister(&ast_nand_driver);
++}
++
++module_init(ast_nand_init);
++module_exit(ast_nand_exit);
++
++MODULE_LICENSE("GPL");
++MODULE_AUTHOR("Ryan Chen");
++MODULE_DESCRIPTION("NAND flash driver for ASPEED");
+diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
+index 231eeaf..e017c36 100644
+--- a/drivers/net/Kconfig
++++ b/drivers/net/Kconfig
+@@ -1889,6 +1889,9 @@ menuconfig NETDEV_1000
+
+ if NETDEV_1000
+
++config ASPEEDMAC
++ tristate "ASPEED MAC support"
++
+ config ACENIC
+ tristate "Alteon AceNIC/3Com 3C985/NetGear GA620 Gigabit support"
+ depends on PCI
+diff --git a/drivers/net/Makefile b/drivers/net/Makefile
+index 017383a..3c04c0b 100644
+--- a/drivers/net/Makefile
++++ b/drivers/net/Makefile
+@@ -85,6 +85,7 @@ obj-$(CONFIG_VIA_VELOCITY) += via-velocity.o
+ obj-$(CONFIG_ADAPTEC_STARFIRE) += starfire.o
+ obj-$(CONFIG_RIONET) += rionet.o
+ obj-$(CONFIG_SH_ETH) += sh_eth.o
++obj-$(CONFIG_ASPEEDMAC) += ftgmac100_26.o
+
+ #
+ # end link order section
+diff --git a/drivers/net/ftgmac100_26.c b/drivers/net/ftgmac100_26.c
+new file mode 100644
+index 0000000..8575293
+--- /dev/null
++++ b/drivers/net/ftgmac100_26.c
+@@ -0,0 +1,1883 @@
++/********************************************************************************
++* File Name : ftgmac100_26.c
++*
++* Copyright (C) 2012-2020 ASPEED Technology Inc.
++* This program is free software; you can redistribute it and/or modify
++* it under the terms of the GNU General Public License as published by the Free Software Foundation;
++* either version 2 of the License, or (at your option) any later version.
++* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
++* without even the implied warranty of MERCHANTABILITY or
++* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
++* You should have received a copy of the GNU General Public License
++* along with this program; if not, write to the Free Software
++* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++********************************************************************************/
++//-----------------------------------------------------------------------------
++// "ASPEED MAC Driver, (Linux Kernel 2.6.15.7) 10/02/07 - by ASPEED\n"
++// Further improvements:
++//
++// -- Assume MAC1 has a PHY chip. Read the chip type and handle Marvell
++// or Broadcom, else don't touch PHY chip (if present).
++//
++// -- If MAC2 is on, check if U-Boot enabled the MII2DC+MII2DIO pins.
++// If yes, handle Marvell or Broadcom PHY. If no, assume sideband RMII
++// interface with no PHY chip.
++// 1.12/27/07 - by river@aspeed
++// Workaround for the gigabit hash function
++// 2.12/27/07 - by river@aspeed
++// Synchronize the EDORR bit with document, D[30], D[15] both are EDORR
++// 3.12/31/07 - by river@aspeed
++// Add aspeed_i2c_init and aspeed_i2c_read function for DHCP
++// 4.04/10/2008 - by river@aspeed
++// Synchronize the EDOTR bit with document, D[30] is EDOTR
++// 5.04/10/2008 - by river@aspeed
++// Remove the workaround for multicast hash function in A2 chip
++// SDK 0.19
++// 6.05/15/2008 - by river@aspeed
++// Fix bug of free sk_buff in wrong routine
++// 7.05/16/2008 - by river@aspeed
++// Fix bug of skb_over_panic()
++// 8.05/22/2008 - by river@aspeed
++// Support NCSI Feature
++// SDK 0.20
++// 9.07/02/2008 - by river@aspeed
++// Fix TX will drop packet bug
++// SDK 0.21
++//10.08/06/2008 - by river@aspeed
++// Add the netif_carrier_on() and netif_carrier_off()
++//11.08/06/2008 - by river@aspeed
++// Fix the timer did not work after device closed
++// SDK0.22
++//12.08/12/2008 - by river@aspeed
++// Support different PHY configuration
++// SDK0.23
++//13.10/14/2008 - by river@aspeed
++// Support Realtek RTL8211BN Gigabit PHY
++//14.11/17/2008 - by river@aspeed
++// Modify the allocate buffer to alignment to IP header
++// SDK0.26
++//15.07/28/2009 - by river@aspeed
++// Fix memory leakage problem in using multicast
++//16.07/28/2009 - by river@aspeed
++// tx_free field in the local structure should be integer
++//
++//
++//
++//AST2300 SDK 0.12
++//17.03/30/2010 - by river@aspeed
++// Modify for AST2300's hardware CLOCK/RESET/MULTI-PIN configuration
++//18.03/30/2010 - by river@aspeed
++// Fix does not report netif_carrier_on() and netif_carrier_off() when use MARVELL PHY
++//AST2300 SDK 0.13
++//17.06/10/2010 - by river@aspeed
++// Support AST2300 A0
++//18.06/10/2010 - by river@aspeed
++// EEPROM is at I2C channel 4 on AST2300 A0 EVB
++//AST2300 SDK 0.14
++//19.09/13/2010 - by river@aspeed
++// Support Realtek RTL8201EL 10/100M PHY
++//AST2400
++//20.06/25/2013 - by CC@aspeed
++// Support BCM54612E 10/100/1000M PHY
++//-----------------------------------------------------------------------------
++
++#include <linux/module.h>
++#include <linux/version.h>
++#include <linux/kernel.h>
++#include <linux/sched.h>
++#include <linux/types.h>
++#include <linux/fcntl.h>
++#include <linux/interrupt.h>
++#include <linux/ptrace.h>
++#include <linux/ioport.h>
++#include <linux/in.h>
++#include <linux/slab.h>
++#include <linux/string.h>
++#include <linux/init.h>
++#include <linux/proc_fs.h>
++#include <asm/bitops.h>
++#include <asm/io.h>
++#include <linux/pci.h>
++#include <linux/errno.h>
++#include <linux/delay.h>
++#include <linux/netdevice.h>
++#include <linux/etherdevice.h>
++#include <linux/platform_device.h>
++#include <mach/ftgmac100_drv.h>
++
++#include <linux/skbuff.h>
++
++#include "ftgmac100_26.h"
++
++#if defined(CONFIG_ARM)
++#include <mach/hardware.h>
++#include <asm/cacheflush.h>
++
++#elif defined(CONFIG_COLDFIRE)
++#include <asm/astsim.h>
++
++#else
++#err "Not define include for GMAC"
++#endif
++
++/*------------------------------------------------------------------------
++ .
++ . Configuration options, for the experienced user to change.
++ .
++ -------------------------------------------------------------------------*/
++
++/*
++ . DEBUGGING LEVELS
++ .
++ . 0 for normal operation
++ . 1 for slightly more details
++ . >2 for various levels of increasingly useless information
++ . 2 for interrupt tracking, status flags
++ . 3 for packet info
++ . 4 for complete packet dumps
++*/
++
++#define DO_PRINT(args...) printk(": " args)
++
++#define FTMAC100_DEBUG 1
++
++#if (FTMAC100_DEBUG > 2 )
++#define PRINTK3(args...) DO_PRINT(args)
++#else
++#define PRINTK3(args...)
++#endif
++
++#if FTMAC100_DEBUG > 1
++#define PRINTK2(args...) DO_PRINT(args)
++#else
++#define PRINTK2(args...)
++#endif
++
++#ifdef FTMAC100_DEBUG
++#define PRINTK(args...) DO_PRINT(args)
++#else
++#define PRINTK(args...)
++#endif
++
++/*
++ . A rather simple routine to print out a packet for debugging purposes.
++*/
++#if FTMAC100_DEBUG > 2
++static void print_packet( u8 *, int );
++#endif
++
++static int ftgmac100_wait_to_send_packet(struct sk_buff * skb, struct net_device * dev);
++
++static volatile int trans_busy = 0;
++
++
++void ftgmac100_phy_rw_waiting(unsigned int ioaddr)
++{
++ unsigned int tmp;
++
++ do {
++ mdelay(10);
++ tmp =inl(ioaddr + PHYCR_REG);
++ } while ((tmp&(PHY_READ_bit|PHY_WRITE_bit)) > 0);
++}
++
++
++/*------------------------------------------------------------
++ . Reads a register from the MII Management serial interface
++ .-------------------------------------------------------------*/
++static u16 ftgmac100_read_phy_register(unsigned int ioaddr, u8 phyaddr, u8 phyreg)
++{
++ unsigned int tmp;
++
++ if (phyaddr > 0x1f) // MII chip IDs are 5 bits long
++ return 0xffff;
++
++ tmp = inl(ioaddr + PHYCR_REG);
++ tmp &= 0x3000003F;
++ tmp |=(phyaddr<<16);
++ tmp |=(phyreg<<(16+5));
++ tmp |=PHY_READ_bit;
++
++ outl( tmp, ioaddr + PHYCR_REG );
++ ftgmac100_phy_rw_waiting(ioaddr);
++
++ return (inl(ioaddr + PHYDATA_REG)>>16);
++}
++
++
++/*------------------------------------------------------------
++ . Writes a register to the MII Management serial interface
++ .-------------------------------------------------------------*/
++static void ftgmac100_write_phy_register(unsigned int ioaddr,
++ u8 phyaddr, u8 phyreg, u16 phydata)
++{
++ unsigned int tmp;
++
++ if (phyaddr > 0x1f) // MII chip IDs are 5 bits long
++ return;
++
++ tmp = inl(ioaddr + PHYCR_REG);
++ tmp &= 0x3000003F;
++ tmp |=(phyaddr<<16);
++ tmp |=(phyreg<<(16+5));
++ tmp |=PHY_WRITE_bit;
++
++ outl( phydata, ioaddr + PHYDATA_REG );
++ outl( tmp, ioaddr + PHYCR_REG );
++ ftgmac100_phy_rw_waiting(ioaddr);
++}
++
++static void ast_gmac_set_mac(struct ftgmac100_priv *priv, const unsigned char *mac)
++{
++ unsigned int maddr = mac[0] << 8 | mac[1];
++ unsigned int laddr = mac[2] << 24 | mac[3] << 16 | mac[4] << 8 | mac[5];
++
++ iowrite32(maddr, priv->netdev->base_addr + MAC_MADR_REG);
++ iowrite32(laddr, priv->netdev->base_addr + MAC_LADR_REG);
++}
++
++/*
++ * MAC1 always has MII MDC+MDIO pins to access PHY registers. We assume MAC1
++ * always has a PHY chip, if MAC1 is enabled.
++ * U-Boot can enable MAC2 MDC+MDIO pins for a 2nd PHY, or MAC2 might be
++ * disabled (only one port), or it's sideband-RMII which has no PHY chip.
++ *
++ * Return miiPhyId==0 if the MAC cannot be accessed.
++ * Return miiPhyId==1 if the MAC registers are OK but it cannot carry traffic.
++ * Return miiPhyId==2 if the MAC can send/receive but it has no PHY chip.
++ * Else return the PHY 22-bit vendor ID, 6-bit model and 4-bit revision.
++ */
++static void getMacHwConfig( struct net_device* dev, struct AstMacHwConfig* out )
++{
++ struct ftgmac100_priv *priv = (struct ftgmac100_priv *)dev->priv;
++
++// out->macId = dev->dev_id;
++//.. getMacAndPhy(dev, out);
++ out->miiPhyId = 0;
++
++ // We assume the Clock Stop register does not disable the MAC1 or MAC2 clock
++ // unless Reset Control also holds the MAC in reset.
++ // For now, we only support a PHY chip on the MAC's own MDC+MDIO bus.
++ if (out->phyAddr > 0x1f) {
++no_phy_access:
++ out->phyAddr = 0xff;
++ return;
++ }
++
++ if (priv->NCSI_support == 0) {
++ out->miiPhyId = ftgmac100_read_phy_register(dev->base_addr, out->phyAddr, 0x02);
++ if (out->miiPhyId == 0xFFFF) { //Realtek PHY at address 1
++ out->phyAddr = 1;
++ }
++ if (out->miiPhyId == 0x0362) {
++ out->phyAddr = 1;
++ }
++ out->miiPhyId = ftgmac100_read_phy_register(dev->base_addr, out->phyAddr, 0x02);
++ out->miiPhyId = (out->miiPhyId & 0xffff) << 16;
++ out->miiPhyId |= ftgmac100_read_phy_register(dev->base_addr, out->phyAddr, 0x03) & 0xffff;
++
++ switch (out->miiPhyId >> 16) {
++ case 0x0040: // Broadcom
++ case 0x0141: // Marvell
++ case 0x001c: // Realtek
++ case 0x0362: // BCM54612
++ break;
++
++ default:
++ // Leave miiPhyId for DO_PRINT(), but reset phyAddr.
++ // out->miiPhyId = 2;
++ goto no_phy_access;
++ break;
++ }
++ }
++ return;
++}
++
++
++static void ftgmac100_reset( struct net_device* dev )
++{
++ struct ftgmac100_priv *priv = (struct ftgmac100_priv *)dev->priv;
++ struct AstMacHwConfig* ids = &priv->ids;
++ unsigned int tmp, speed, duplex;
++
++ getMacHwConfig(dev, ids);
++ PRINTK("%s:ftgmac100_reset, phyAddr=0x%x, miiPhyId=0x%04x_%04x\n",
++ dev->name, ids->phyAddr, (ids->miiPhyId >> 16), (ids->miiPhyId & 0xffff));
++
++ if (ids->miiPhyId < 1)
++ return; // Cannot access MAC registers
++
++ // Check the link speed and duplex.
++ // They are not valid until auto-neg is resolved, which is reg.1 bit[5],
++ // or the link is up, which is reg.1 bit[2].
++
++ if (ids->phyAddr < 0xff)
++ tmp = ftgmac100_read_phy_register(dev->base_addr, ids->phyAddr, 0x1);
++ else tmp = 0;
++
++ if (0==(tmp & (1u<<5 | 1u<<2)) || ids->phyAddr >= 0xff) {
++ // No PHY chip, or link has not negotiated.
++ speed = PHY_SPEED_100M;
++ duplex = 1;
++ netif_carrier_off(dev);
++ }
++ else if (((ids->miiPhyId & PHYID_VENDOR_MODEL_MASK) == PHYID_RTL8201EL)) {
++ tmp = ftgmac100_read_phy_register(dev->base_addr, priv->ids.phyAddr, 0x00);
++ duplex = (tmp & 0x0100) ? 1 : 0;
++ speed = (tmp & 0x2000) ? PHY_SPEED_100M : PHY_SPEED_10M;
++ }
++ else if (((ids->miiPhyId & PHYID_VENDOR_MASK) == PHYID_VENDOR_MARVELL) ||
++ ((ids->miiPhyId & PHYID_VENDOR_MODEL_MASK) == PHYID_RTL8211)) {
++ // Use reg.17_0.bit[15:13] for {speed[1:0], duplex}.
++ tmp = ftgmac100_read_phy_register(dev->base_addr, ids->phyAddr, 0x11);
++ duplex = (tmp & PHY_DUPLEX_mask)>>13;
++ speed = (tmp & PHY_SPEED_mask)>>14;
++ netif_carrier_on(dev);
++ }
++ else if (priv->ids.miiPhyId == PHYID_BCM54612E) {
++ // Get link status
++ // First Switch shadow register selector
++ ftgmac100_write_phy_register(dev->base_addr, priv->ids.phyAddr, 0x1C, 0x2000);
++ tmp = ftgmac100_read_phy_register(dev->base_addr, priv->ids.phyAddr, 0x1C);
++ if ( (tmp & 0x0080) == 0x0080 )
++ duplex = 0;
++ else
++ duplex = 1;
++
++ switch(tmp & 0x0018) {
++ case 0x0000:
++ speed = PHY_SPEED_1G; break;
++ case 0x0008:
++ speed = PHY_SPEED_100M; break;
++ case 0x0010:
++ speed = PHY_SPEED_10M; break;
++ default:
++ speed = PHY_SPEED_100M;
++ }
++ }
++ else {
++ // Assume Broadcom BCM5221. Use reg.18 bits [1:0] for {100Mb/s, fdx}.
++ tmp = ftgmac100_read_phy_register(dev->base_addr, ids->phyAddr, 0x18);
++ duplex = (tmp & 0x0001);
++ speed = (tmp & 0x0002) ? PHY_SPEED_100M : PHY_SPEED_10M;
++ }
++
++ if (speed == PHY_SPEED_1G) {
++ // Set SPEED_100_bit too, for consistency.
++ priv->maccr_val |= GMAC_MODE_bit | SPEED_100_bit;
++ tmp = inl( dev->base_addr + MACCR_REG );
++ tmp |= GMAC_MODE_bit | SPEED_100_bit;
++ outl(tmp, dev->base_addr + MACCR_REG );
++ } else {
++ priv->maccr_val &= ~(GMAC_MODE_bit | SPEED_100_bit);
++ tmp = inl( dev->base_addr + MACCR_REG );
++ tmp &= ~(GMAC_MODE_bit | SPEED_100_bit);
++ if (speed == PHY_SPEED_100M) {
++ priv->maccr_val |= SPEED_100_bit;
++ tmp |= SPEED_100_bit;
++ }
++ outl(tmp, dev->base_addr + MACCR_REG );
++ }
++ if (duplex)
++ priv->maccr_val |= FULLDUP_bit;
++ else
++ priv->maccr_val &= ~FULLDUP_bit;
++
++ outl( SW_RST_bit, dev->base_addr + MACCR_REG );
++
++#ifdef not_complete_yet
++ /* Setup for fast accesses if requested */
++ /* If the card/system can't handle it then there will */
++ /* be no recovery except for a hard reset or power cycle */
++ if (dev->dma)
++ {
++ outw( inw( dev->base_addr + CONFIG_REG ) | CONFIG_NO_WAIT,
++ dev->base_addr + CONFIG_REG );
++ }
++#endif /* end_of_not */
++
++ /* this should pause enough for the chip to be happy */
++ for (; (inl( dev->base_addr + MACCR_REG ) & SW_RST_bit) != 0; )
++ {
++ mdelay(10);
++ PRINTK3("RESET: reset not complete yet\n" );
++ }
++
++ outl( 0, dev->base_addr + IER_REG ); /* Disable all interrupts */
++}
++
++static void ftgmac100_enable( struct net_device *dev )
++{
++ int i;
++ struct ftgmac100_priv *priv = (struct ftgmac100_priv *)dev->priv;
++ unsigned int tmp_rsize; //Richard
++ unsigned int rfifo_rsize; //Richard
++ unsigned int tfifo_rsize; //Richard
++ unsigned int rxbuf_size;
++
++ rxbuf_size = RX_BUF_SIZE & 0x3fff;
++ outl( rxbuf_size , dev->base_addr + RBSR_REG); //for NC Body
++
++ for (i=0; i<RXDES_NUM; ++i)
++ priv->rx_descs[i].RXPKT_RDY = RX_OWNBY_FTGMAC100; // owned by FTMAC100
++
++ priv->rx_idx = 0;
++
++ for (i=0; i<TXDES_NUM; ++i) {
++ priv->tx_descs[i].TXDMA_OWN = TX_OWNBY_SOFTWARE; // owned by software
++ priv->tx_skbuff[i] = 0;
++ }
++
++ priv->tx_idx = 0;
++ priv->old_tx = 0;
++ priv->tx_free=TXDES_NUM;
++
++ /* Set the MAC address */
++ ast_gmac_set_mac(priv, dev->dev_addr);
++
++ outl( priv->rx_descs_dma, dev->base_addr + RXR_BADR_REG);
++ outl( priv->tx_descs_dma, dev->base_addr + TXR_BADR_REG);
++ outl( 0x00001010, dev->base_addr + ITC_REG);
++
++ outl( (0UL<<TXPOLL_CNT)|(0x1<<RXPOLL_CNT), dev->base_addr + APTC_REG);
++ outl( 0x44f97, dev->base_addr + DBLAC_REG );
++
++ /// outl( inl(FCR_REG)|0x1, ioaddr + FCR_REG ); // enable flow control
++ /// outl( inl(BPR_REG)|0x1, ioaddr + BPR_REG ); // enable back pressure register
++
++ // +++++ Richard +++++ //
++ tmp_rsize = inl( dev->base_addr + FEAR_REG );
++ rfifo_rsize = tmp_rsize & 0x00000007;
++ tfifo_rsize = (tmp_rsize >> 3)& 0x00000007;
++
++ tmp_rsize = inl( dev->base_addr + TPAFCR_REG );
++ tmp_rsize &= ~0x3f000000;
++ tmp_rsize |= (tfifo_rsize << 27);
++ tmp_rsize |= (rfifo_rsize << 24);
++
++ outl(tmp_rsize, dev->base_addr + TPAFCR_REG);
++ // ----- Richard ----- //
++
++//river set MAHT0, MAHT1
++ if (priv->maccr_val & GMAC_MODE_bit) {
++ outl (priv->GigaBit_MAHT0, dev->base_addr + MAHT0_REG);
++ outl (priv->GigaBit_MAHT1, dev->base_addr + MAHT1_REG);
++ }
++ else {
++ outl (priv->Not_GigaBit_MAHT0, dev->base_addr + MAHT0_REG);
++ outl (priv->Not_GigaBit_MAHT1, dev->base_addr + MAHT1_REG);
++ }
++
++ /// enable trans/recv,...
++ outl(priv->maccr_val, dev->base_addr + MACCR_REG );
++#if 0
++//NCSI Start
++//DeSelect Package/ Select Package
++ if ((priv->NCSI_support == 1) || (priv->INTEL_NCSI_EVA_support == 1)) {
++ NCSI_Struct_Initialize(dev);
++ for (i = 0; i < 4; i++) {
++ DeSelect_Package (dev, i);
++ Package_Found = Select_Package (dev, i);
++ if (Package_Found == 1) {
++//AST2100/AST2050/AST1100 supports 1 slave only
++ priv->NCSI_Cap.Package_ID = i;
++ break;
++ }
++ }
++ if (Package_Found != 0) {
++//Initiali State
++ for (i = 0; i < 2; i++) { //Suppose 2 channels in current version, You could modify it to 0x1F to support 31 channels
++ Channel_Found = Clear_Initial_State(dev, i);
++ if (Channel_Found == 1) {
++ priv->NCSI_Cap.Channel_ID = i;
++ printk ("Found NCSI Network Controller at (%d, %d)\n", priv->NCSI_Cap.Package_ID, priv->NCSI_Cap.Channel_ID);
++//Get Version and Capabilities
++ Get_Version_ID(dev);
++ Get_Capabilities(dev);
++//Configuration
++ Select_Active_Package(dev);
++//Set MAC Address
++ Enable_Set_MAC_Address(dev);
++//Enable Broadcast Filter
++ Enable_Broadcast_Filter(dev);
++//Disable VLAN
++ Disable_VLAN(dev);
++//Enable AEN
++ Enable_AEN(dev);
++//Get Parameters
++ Get_Parameters(dev);
++//Enable TX
++ Enable_Network_TX(dev);
++//Enable Channel
++ Enable_Channel(dev);
++//Get Link Status
++Re_Get_Link_Status:
++ Link_Status = Get_Link_Status(dev);
++ if (Link_Status == LINK_UP) {
++ printk ("Using NCSI Network Controller (%d, %d)\n", priv->NCSI_Cap.Package_ID, priv->NCSI_Cap.Channel_ID);
++ netif_carrier_on(dev);
++ break;
++ }
++ else if ((Link_Status == LINK_DOWN) && (Re_Send < 2)) {
++ Re_Send++;
++ netif_carrier_off(dev);
++ goto Re_Get_Link_Status;
++ }
++//Disable TX
++ Disable_Network_TX(dev);
++//Disable Channel
++// Disable_Channel(dev);
++ Re_Send = 0;
++ Channel_Found = 0;
++ }
++ }
++ }
++ }
++ /* now, enable interrupts */
++#endif
++ if (((priv->ids.miiPhyId & PHYID_VENDOR_MASK) == PHYID_VENDOR_MARVELL) ||
++ ((priv->ids.miiPhyId & PHYID_VENDOR_MODEL_MASK) == PHYID_RTL8211)) {
++ outl(
++ PHYSTS_CHG_bit |
++ AHB_ERR_bit |
++ TPKT_LOST_bit |
++ TPKT2E_bit |
++ RXBUF_UNAVA_bit |
++ RPKT2B_bit
++ ,dev->base_addr + IER_REG
++ );
++ }
++ else if (((priv->ids.miiPhyId & PHYID_VENDOR_MASK) == PHYID_VENDOR_BROADCOM) ||
++ ((priv->ids.miiPhyId & PHYID_VENDOR_MODEL_MASK) == PHYID_RTL8201EL)) {
++ outl(
++ AHB_ERR_bit |
++ TPKT_LOST_bit |
++ TPKT2E_bit |
++ RXBUF_UNAVA_bit |
++ RPKT2B_bit
++ ,dev->base_addr + IER_REG
++ );
++ }
++ else if (priv->ids.miiPhyId == PHYID_BCM54612E) {
++ outl(
++// no link PHY link status pin PHYSTS_CHG_bit |
++ AHB_ERR_bit |
++ TPKT_LOST_bit |
++ TPKT2E_bit |
++ RXBUF_UNAVA_bit |
++ RPKT2B_bit
++ ,dev->base_addr + IER_REG
++ );
++ } else {
++ outl(
++// no link PHY link status pin PHYSTS_CHG_bit |
++ AHB_ERR_bit |
++ TPKT_LOST_bit |
++ TPKT2E_bit |
++ RXBUF_UNAVA_bit |
++ RPKT2B_bit
++ ,dev->base_addr + IER_REG
++ );
++ }
++}
++
++static void aspeed_mac_timer(unsigned long data)
++{
++ struct net_device *dev = (struct net_device *)data;
++ struct ftgmac100_priv *priv = (struct ftgmac100_priv *)dev->priv;
++ unsigned int status, tmp, speed, duplex, macSpeed;
++
++#ifdef CONFIG_ARCH_AST2300
++ //Fix issue for tx/rx arbiter lock
++ outl( 0xffffffff, dev->base_addr + TXPD_REG);
++#endif
++ status = ftgmac100_read_phy_register(dev->base_addr, priv->ids.phyAddr, 0x01);
++
++ if (status & LINK_STATUS) { // Bit[2], Link Status, link is up
++ priv->timer.expires = jiffies + 10 * HZ;
++
++ if ((priv->ids.miiPhyId & PHYID_VENDOR_MASK) == PHYID_VENDOR_BROADCOM) {
++ tmp = ftgmac100_read_phy_register(dev->base_addr, priv->ids.phyAddr, 0x18);
++ duplex = (tmp & 0x0001);
++ speed = (tmp & 0x0002) ? PHY_SPEED_100M : PHY_SPEED_10M;
++ }
++ else if ((priv->ids.miiPhyId & PHYID_VENDOR_MODEL_MASK) == PHYID_RTL8201EL) {
++ tmp = ftgmac100_read_phy_register(dev->base_addr, priv->ids.phyAddr, 0x00);
++ duplex = (tmp & 0x0100) ? 1 : 0;
++ speed = (tmp & 0x2000) ? PHY_SPEED_100M : PHY_SPEED_10M;
++ }
++ else if (((priv->ids.miiPhyId & PHYID_VENDOR_MASK) == PHYID_VENDOR_MARVELL) ||
++ ((priv->ids.miiPhyId & PHYID_VENDOR_MODEL_MASK) == PHYID_RTL8211)) {
++ tmp = ftgmac100_read_phy_register(dev->base_addr, priv->ids.phyAddr, 0x11);
++ duplex = (tmp & PHY_DUPLEX_mask)>>13;
++ speed = (tmp & PHY_SPEED_mask)>>14;
++ }
++ else if (priv->ids.miiPhyId == PHYID_BCM54612E) {
++ // Get link status
++ // First Switch shadow register selector
++ ftgmac100_write_phy_register(dev->base_addr, priv->ids.phyAddr, 0x1C, 0x2000);
++ tmp = ftgmac100_read_phy_register(dev->base_addr, priv->ids.phyAddr, 0x1C);
++ if ( (tmp & 0x0080) == 0x0080 )
++ duplex = 0;
++ else
++ duplex = 1;
++
++ switch(tmp & 0x0018) {
++ case 0x0000:
++ speed = PHY_SPEED_1G;
++
++ break;
++ case 0x0008:
++ speed = PHY_SPEED_100M;
++
++ break;
++ case 0x0010:
++ speed = PHY_SPEED_10M;
++
++ break;
++ default:
++ speed = PHY_SPEED_100M;
++ }
++ }
++ else {
++ duplex = 1; speed = PHY_SPEED_100M;
++ }
++
++ macSpeed = ((priv->maccr_val & GMAC_MODE_bit)>>8 // Move bit[9] to bit[1]
++ | (priv->maccr_val & SPEED_100_bit)>>19); // bit[19] to bit[0]
++ // The MAC hardware ignores SPEED_100_bit if GMAC_MODE_bit is set.
++ if (macSpeed > PHY_SPEED_1G) macSpeed = PHY_SPEED_1G; // 0x3 --> 0x2
++
++ if ( ((priv->maccr_val & FULLDUP_bit)!=0) != duplex
++ || macSpeed != speed )
++ {
++ PRINTK("%s:aspeed_mac_timer, priv->maccr_val=0x%05x, PHY {speed,duplex}=%d,%d\n",
++ dev->name, priv->maccr_val, speed, duplex);
++ ftgmac100_reset(dev);
++ ftgmac100_enable(dev);
++ }
++ netif_carrier_on(dev);
++ }
++ else {
++ netif_carrier_off(dev);
++ priv->timer.expires = jiffies + 1 * HZ;
++ }
++ add_timer(&priv->timer);
++}
++
++/*
++ . Function: ftgmac100_shutdown
++ . Purpose: closes down the SMC91xxx chip.
++ . Method:
++ . 1. zero the interrupt mask
++ . 2. clear the enable receive flag
++ . 3. clear the enable xmit flags
++ .
++ . TODO:
++ . (1) maybe utilize power down mode.
++ . Why not yet? Because while the chip will go into power down mode,
++ . the manual says that it will wake up in response to any I/O requests
++ . in the register space. Empirical results do not show this working.
++*/
++static void ftgmac100_shutdown( unsigned int ioaddr )
++{
++ ///interrupt mask register
++ outl( 0, ioaddr + IER_REG );
++ /* enable trans/recv,... */
++ outl( 0, ioaddr + MACCR_REG );
++}
++
++/*
++ . Function: ftgmac100_wait_to_send_packet( struct sk_buff * skb, struct device * )
++ . Purpose:
++ . Attempt to allocate memory for a packet, if chip-memory is not
++ . available, then tell the card to generate an interrupt when it
++ . is available.
++ .
++ . Algorithm:
++ .
++ . o if the saved_skb is not currently null, then drop this packet
++ . on the floor. This should never happen, because of TBUSY.
++ . o if the saved_skb is null, then replace it with the current packet,
++ . o See if I can sending it now.
++ . o (NO): Enable interrupts and let the interrupt handler deal with it.
++ . o (YES):Send it now.
++*/
++static int ftgmac100_wait_to_send_packet( struct sk_buff * skb, struct net_device * dev )
++{
++ struct ftgmac100_priv *priv = (struct ftgmac100_priv *)dev->priv;
++ unsigned long ioaddr = dev->base_addr;
++ volatile TX_DESC *cur_desc;
++ int length;
++ unsigned long flags;
++
++ spin_lock_irqsave(&priv->tx_lock,flags);
++
++ if (skb==NULL)
++ {
++ DO_PRINT("%s(%d): NULL skb???\n", __FILE__,__LINE__);
++ spin_unlock_irqrestore(&priv->tx_lock, flags);
++ return 0;
++ }
++
++ PRINTK3("%s:ftgmac100_wait_to_send_packet, skb=%x\n", dev->name, skb);
++ cur_desc = &priv->tx_descs[priv->tx_idx];
++
++#ifdef not_complete_yet
++ if (cur_desc->TXDMA_OWN != TX_OWNBY_SOFTWARE) /// no empty transmit descriptor
++ {
++ DO_PRINT("no empty transmit descriptor\n");
++ DO_PRINT("jiffies = %d\n", jiffies);
++ priv->stats.tx_dropped++;
++ netif_stop_queue(dev); /// waiting to do:
++ spin_unlock_irqrestore(&priv->tx_lock, flags);
++
++ return 1;
++ }
++#endif /* end_of_not */
++
++ if (cur_desc->TXDMA_OWN != TX_OWNBY_SOFTWARE) /// no empty transmit descriptor
++ {
++ DO_PRINT("no empty TX descriptor:0x%x:0x%x\n",
++ (unsigned int)cur_desc,((unsigned int *)cur_desc)[0]);
++ priv->stats.tx_dropped++;
++ netif_stop_queue(dev); /// waiting to do:
++ spin_unlock_irqrestore(&priv->tx_lock, flags);
++
++ return 1;
++ }
++ priv->tx_skbuff[priv->tx_idx] = skb;
++ length = (ETH_ZLEN < skb->len) ? skb->len : ETH_ZLEN;
++ length = min(length, TX_BUF_SIZE);
++
++#if FTMAC100_DEBUG > 2
++ DO_PRINT("Transmitting Packet at 0x%x, skb->data = %x, len = %x\n",
++ (unsigned int)cur_desc->VIR_TXBUF_BADR, skb->data, length);
++ print_packet( skb->data, length );
++#endif
++
++ cur_desc->VIR_TXBUF_BADR = (unsigned long)skb->data;
++ cur_desc->TXBUF_BADR = virt_to_phys(skb->data);
++#ifndef CONFIG_CPU_FA52x_DCE
++ dmac_clean_range((void *)skb->data, (void *)(skb->data + length));
++#endif
++
++ //clean_dcache_range(skb->data, (char*)(skb->data + length));
++
++ cur_desc->TXBUF_Size = length;
++ cur_desc->LTS = 1;
++ cur_desc->FTS = 1;
++
++ cur_desc->TX2FIC = 0;
++ cur_desc->TXIC = 0;
++
++ cur_desc->TXDMA_OWN = TX_OWNBY_FTGMAC100;
++
++ outl( 0xffffffff, ioaddr + TXPD_REG);
++
++ priv->tx_idx = (priv->tx_idx + 1) % TXDES_NUM;
++ priv->stats.tx_packets++;
++ priv->tx_free--;
++
++ if (priv->tx_free <= 0) {
++ netif_stop_queue(dev);
++
++ }
++
++
++ dev->trans_start = jiffies;
++ spin_unlock_irqrestore(&priv->tx_lock, flags);
++
++ return 0;
++}
++
++static int ftgmac100_ringbuf_alloc(struct ftgmac100_priv *priv)
++{
++ int i;
++ struct sk_buff *skb;
++
++ priv->rx_descs = dma_alloc_coherent(priv->dev,
++ sizeof(RX_DESC)*RXDES_NUM,
++ &priv->rx_descs_dma, GFP_KERNEL);
++
++ if(!priv->rx_descs)
++ return -ENOMEM;
++
++ memset(priv->rx_descs, 0, sizeof(RX_DESC)*RXDES_NUM);
++ priv->rx_descs[RXDES_NUM-1].EDORR = 1;
++
++ for (i=0; i<RXDES_NUM; i++) {
++ dma_addr_t mapping;
++ skb = dev_alloc_skb(RX_BUF_SIZE + NET_IP_ALIGN);
++ skb_reserve(skb, NET_IP_ALIGN);
++
++ priv->rx_skbuff[i] = skb;
++ if (skb == NULL) {
++ printk ("alloc_list: allocate Rx buffer error! ");
++ break;
++ }
++ mapping = dma_map_single(priv->dev, skb->data, skb->len, DMA_FROM_DEVICE);
++ skb->dev = priv->netdev; /* Mark as being used by this device. */
++ priv->rx_descs[i].RXBUF_BADR = mapping;
++ priv->rx_descs[i].VIR_RXBUF_BADR = skb->data;
++ }
++
++ priv->tx_descs = dma_alloc_coherent(priv->dev,
++ sizeof(TX_DESC)*TXDES_NUM,
++ &priv->tx_descs_dma ,GFP_KERNEL);
++
++ if(!priv->tx_descs)
++ return -ENOMEM;
++
++ memset((void*)priv->tx_descs, 0, sizeof(TX_DESC)*TXDES_NUM);
++ priv->tx_descs[TXDES_NUM-1].EDOTR = 1; // is last descriptor
++
++}
++
++#if FTMAC100_DEBUG > 2
++static void print_packet( u8 * buf, int length )
++{
++#if 1
++#if FTMAC100_DEBUG > 3
++ int i;
++ int remainder;
++ int lines;
++#endif
++
++
++#if FTMAC100_DEBUG > 3
++ lines = length / 16;
++ remainder = length % 16;
++
++ for ( i = 0; i < lines ; i ++ ) {
++ int cur;
++
++ for ( cur = 0; cur < 8; cur ++ ) {
++ u8 a, b;
++
++ a = *(buf ++ );
++ b = *(buf ++ );
++ DO_PRINT("%02x%02x ", a, b );
++ }
++ DO_PRINT("\n");
++ }
++ for ( i = 0; i < remainder/2 ; i++ ) {
++ u8 a, b;
++
++ a = *(buf ++ );
++ b = *(buf ++ );
++ DO_PRINT("%02x%02x ", a, b );
++ }
++ DO_PRINT("\n");
++#endif
++#endif
++}
++#endif
++
++/*------------------------------------------------------------
++ . Configures the specified PHY using Autonegotiation.
++ .-------------------------------------------------------------*/
++static void ftgmac100_phy_configure(struct net_device* dev)
++{
++ struct ftgmac100_priv *priv = (struct ftgmac100_priv *)dev->priv;
++ unsigned long ioaddr = dev->base_addr;
++ u32 tmp;
++// printk("priv->ids.miiPhyId = %x \n",priv->ids.miiPhyId);
++ switch (priv->ids.miiPhyId & PHYID_VENDOR_MASK) {
++ case PHYID_VENDOR_MARVELL:
++ ftgmac100_write_phy_register(ioaddr, priv->ids.phyAddr, 0x12, 0x4400);
++ tmp = ftgmac100_read_phy_register(ioaddr, priv->ids.phyAddr, 0x13 );
++ break;
++ case PHYID_VENDOR_REALTEK:
++ switch (priv->ids.miiPhyId) {
++ case PHYID_RTL8211:
++ ftgmac100_write_phy_register(ioaddr, priv->ids.phyAddr, 0x12, 0x4400);
++ tmp = ftgmac100_read_phy_register(ioaddr, priv->ids.phyAddr, 0x13 );
++ break;
++ case PHYID_RTL8201EL:
++ break;
++ case PHYID_RTL8201F:
++ ftgmac100_write_phy_register(ioaddr, priv->ids.phyAddr, 0x1f, 0x0007);
++ tmp = ftgmac100_read_phy_register(ioaddr, priv->ids.phyAddr, 0x13 );
++ tmp &= ~(0x0030);
++ tmp |= 0x0008;
++ ftgmac100_write_phy_register(ioaddr, priv->ids.phyAddr, 0x13, (u16) tmp);
++ tmp = ftgmac100_read_phy_register(ioaddr, priv->ids.phyAddr, 0x11);
++ tmp &= ~(0x0fff);
++ tmp |= 0x0008;
++ ftgmac100_write_phy_register(ioaddr, priv->ids.phyAddr, 0x11, (u16) tmp);
++ ftgmac100_write_phy_register(ioaddr, priv->ids.phyAddr, 0x1f, 0x0000);
++ break;
++ }
++ break;
++ case PHYID_VENDOR_BROADCOM:
++ switch (priv->ids.miiPhyId) {
++ case PHYID_BCM54612E:
++ ftgmac100_write_phy_register(ioaddr, priv->ids.phyAddr, 0x1C, 0x8C00); // Disable GTXCLK Clock Delay Enable
++ ftgmac100_write_phy_register(ioaddr, priv->ids.phyAddr, 0x18, 0xF0E7); // Disable RGMII RXD to RXC Skew
++ break;
++ case PHYID_BCM5221A4:
++ default:
++ tmp = ftgmac100_read_phy_register(ioaddr, priv->ids.phyAddr, 0x1b);
++ tmp |= 0x0004;
++ ftgmac100_write_phy_register(ioaddr, priv->ids.phyAddr, 0x1b, (u16) tmp);
++ break;
++ }
++ break;
++ }
++}
++
++
++/*--------------------------------------------------------
++ . Called by the kernel to send a packet out into the void
++ . of the net. This routine is largely based on
++ . skeleton.c, from Becker.
++ .--------------------------------------------------------
++*/
++static void ftgmac100_timeout (struct net_device *dev)
++{
++ /* If we get here, some higher level has decided we are broken.
++ There should really be a "kick me" function call instead. */
++ DO_PRINT(KERN_WARNING "%s: transmit timed out? (jiffies=%ld)\n",
++ dev->name, jiffies);
++ /* "kick" the adaptor */
++ ftgmac100_reset( dev );
++ ftgmac100_enable( dev );
++
++ /* Reconfigure the PHY */
++ ftgmac100_phy_configure(dev);
++
++ netif_wake_queue(dev);
++ dev->trans_start = jiffies;
++}
++
++
++static void ftgmac100_free_tx (struct net_device *dev)
++{
++ struct ftgmac100_priv *priv = (struct ftgmac100_priv *)dev->priv;
++ int entry = priv->old_tx % TXDES_NUM;
++ unsigned long flags = 0;
++
++ spin_lock_irqsave(&priv->tx_lock,flags);
++
++ /* Free used tx skbuffs */
++
++ while ((priv->tx_descs[entry].TXDMA_OWN == TX_OWNBY_SOFTWARE) && (priv->tx_skbuff[entry] != NULL)) {
++ struct sk_buff *skb;
++
++ skb = priv->tx_skbuff[entry];
++ dev_kfree_skb_any (skb);
++ priv->tx_skbuff[entry] = 0;
++ entry = (entry + 1) % TXDES_NUM;
++ priv->tx_free++;
++ }
++
++ spin_unlock_irqrestore(&priv->tx_lock, flags);
++ priv->old_tx = entry;
++ if ((netif_queue_stopped(dev)) && (priv->tx_free > 0)) {
++ netif_wake_queue (dev);
++ }
++}
++
++
++/*-------------------------------------------------------------
++ .
++ . ftgmac100_rcv - receive a packet from the card
++ .
++ . There is ( at least ) a packet waiting to be read from
++ . chip-memory.
++ .
++ . o Read the status
++ . o If an error, record it
++ . o otherwise, read in the packet
++ --------------------------------------------------------------
++*/
++// extern dce_dcache_invalidate_range(unsigned int start, unsigned int end);
++
++static void ftgmac100_rcv(struct net_device *dev)
++{
++ struct ftgmac100_priv *priv = (struct ftgmac100_priv *)dev->priv;
++ unsigned long ioaddr = dev->base_addr;
++ int packet_length;
++ int rcv_cnt;
++ volatile RX_DESC *cur_desc;
++ int cur_idx;
++ int have_package;
++ int have_frs;
++ int start_idx;
++ int count = 0;
++ int packet_full = 0;
++ int data_not_fragment = 1;
++
++ start_idx = priv->rx_idx;
++
++ for (rcv_cnt=0; rcv_cnt<RXDES_NUM ; ++rcv_cnt)
++ {
++ packet_length = 0;
++ cur_idx = priv->rx_idx;
++
++ have_package = 0;
++ have_frs = 0;
++
++ for (; (cur_desc = &priv->rx_descs[priv->rx_idx])->RXPKT_RDY==RX_OWNBY_SOFTWARE; )
++ {
++ have_package = 1;
++ priv->rx_idx = (priv->rx_idx+1)%RXDES_NUM;
++ count++;
++ if (count == RXDES_NUM) {
++ packet_full = 1;
++ }
++//DF_support
++ if (data_not_fragment == 1) {
++ if (!(cur_desc->DF)) {
++ data_not_fragment = 0;
++ }
++ }
++
++ if (cur_desc->FRS)
++ {
++ have_frs = 1;
++ if (cur_desc->RX_ERR || cur_desc->CRC_ERR || cur_desc->FTL ||
++ cur_desc->RUNT || cur_desc->RX_ODD_NB
++ // cur_desc->IPCS_FAIL || cur_desc->UDPCS_FAIL || cur_desc->TCPCS_FAIL
++ )
++ {
++ // #ifdef not_complete_yet
++ if (cur_desc->RX_ERR)
++ {
++ DO_PRINT("err: RX_ERR\n");
++ }
++ if (cur_desc->CRC_ERR)
++ {
++ // DO_PRINT("err: CRC_ERR\n");
++ }
++ if (cur_desc->FTL)
++ {
++ DO_PRINT("err: FTL\n");
++ }
++ if (cur_desc->RX_ODD_NB)
++ {
++ // DO_PRINT("err: RX_ODD_NB\n");
++ }
++// if (cur_desc->IPCS_FAIL || cur_desc->UDPCS_FAIL || cur_desc->TCPCS_FAIL)
++// {
++// DO_PRINT("err: CS FAIL\n");
++// }
++ // #endif /* end_of_not */
++ priv->stats.rx_errors++; // error frame....
++ break;
++ }
++//DF_support
++ if (cur_desc->DF) {
++ if (cur_desc->IPCS_FAIL || cur_desc->UDPCS_FAIL || cur_desc->TCPCS_FAIL)
++ {
++ DO_PRINT("err: CS FAIL\n");
++ priv->stats.rx_errors++; // error frame....
++ break;
++ }
++ }
++
++ if (cur_desc->MULTICAST)
++ {
++ priv->stats.multicast++;
++ }
++ if ((priv->NCSI_support == 1) || (priv->INTEL_NCSI_EVA_support == 1)) {
++ if (cur_desc->BROADCAST) {
++ if (*(unsigned short *)(cur_desc->VIR_RXBUF_BADR + 12) == NCSI_HEADER) {
++ printk ("AEN PACKET ARRIVED\n");
++ ftgmac100_reset(dev);
++ ftgmac100_enable(dev);
++ return;
++ }
++ }
++ }
++ }
++
++ packet_length += cur_desc->VDBC;
++
++// if ( cur_desc->LRS ) // packet's last frame
++// {
++ break;
++// }
++ }
++ if (have_package==0)
++ {
++ goto done;
++ }
++ if (!have_frs)
++ {
++ DO_PRINT("error, loss first\n");
++ priv->stats.rx_over_errors++;
++ }
++
++ if (packet_length > 0)
++ {
++ struct sk_buff * skb;
++ u8 * data = 0; if (data) { }
++
++ packet_length -= 4;
++
++ skb_put (skb = priv->rx_skbuff[cur_idx], packet_length);
++
++// Rx Offload DF_support
++
++ if (data_not_fragment) {
++ skb->ip_summed = CHECKSUM_UNNECESSARY;
++ data_not_fragment = 1;
++ }
++
++#if FTMAC100_DEBUG > 2
++ DO_PRINT("Receiving Packet at 0x%x, packet len = %x\n",(unsigned int)data, packet_length);
++ print_packet( data, packet_length );
++#endif
++
++ skb->protocol = eth_type_trans(skb, dev );
++ netif_rx(skb);
++ priv->stats.rx_packets++;
++ priv->rx_skbuff[cur_idx] = NULL;
++ }
++ if (packet_full) {
++// DO_PRINT ("RX Buffer full before driver entered ISR\n");
++ goto done;
++ }
++ }
++
++done:
++
++ if (packet_full) {
++
++ struct sk_buff *skb;
++
++ for (cur_idx = 0; cur_idx < RXDES_NUM; cur_idx++)
++ {
++ if (priv->rx_skbuff[cur_idx] == NULL) {
++ skb = dev_alloc_skb (RX_BUF_SIZE + 16);
++ if (skb == NULL) {
++ printk (KERN_INFO
++ "%s: receive_packet: "
++ "Unable to re-allocate Rx skbuff.#%d\n",
++ dev->name, cur_idx);
++ }
++ priv->rx_skbuff[cur_idx] = skb;
++ skb->dev = dev;
++ // ASPEED: See earlier skb_reserve() cache alignment
++ skb_reserve (skb, 2);
++ dmac_inv_range ((void *)skb->data, (void *)skb->data + RX_BUF_SIZE);
++ priv->rx_descs[cur_idx].RXBUF_BADR = cpu_to_le32(virt_to_phys(skb->tail));
++ priv->rx_descs[cur_idx].VIR_RXBUF_BADR = cpu_to_le32((u32)skb->tail);
++ }
++ priv->rx_descs[cur_idx].RXPKT_RDY = RX_OWNBY_FTGMAC100;
++ }
++ packet_full = 0;
++
++ }
++ else {
++ if (start_idx != priv->rx_idx) {
++ struct sk_buff *skb;
++
++ for (cur_idx = (start_idx+1)%RXDES_NUM; cur_idx != priv->rx_idx; cur_idx = (cur_idx+1)%RXDES_NUM)
++ {
++
++
++ //struct sk_buff *skb;
++ /* Dropped packets don't need to re-allocate */
++ if (priv->rx_skbuff[cur_idx] == NULL) {
++ skb = dev_alloc_skb (RX_BUF_SIZE + 16);
++ if (skb == NULL) {
++ printk (KERN_INFO
++ "%s: receive_packet: "
++ "Unable to re-allocate Rx skbuff.#%d\n",
++ dev->name, cur_idx);
++ break;
++ }
++ priv->rx_skbuff[cur_idx] = skb;
++ skb->dev = dev;
++ /* 16 byte align the IP header */
++ skb_reserve (skb, 2);
++ dmac_inv_range ((void *)skb->data,
++ (void *)skb->data + RX_BUF_SIZE);
++ priv->rx_descs[cur_idx].RXBUF_BADR = cpu_to_le32(virt_to_phys(skb->tail));
++ priv->rx_descs[cur_idx].VIR_RXBUF_BADR = cpu_to_le32((u32)skb->tail);
++ }
++
++ priv->rx_descs[cur_idx].RXPKT_RDY = RX_OWNBY_FTGMAC100;
++ }
++
++
++ //struct sk_buff *skb;
++ /* Dropped packets don't need to re-allocate */
++ if (priv->rx_skbuff[start_idx] == NULL) {
++ skb = dev_alloc_skb (RX_BUF_SIZE + 16);
++ if (skb == NULL) {
++ printk (KERN_INFO
++ "%s: receive_packet: "
++ "Unable to re-allocate Rx skbuff.#%d\n",
++ dev->name, start_idx);
++ }
++ priv->rx_skbuff[start_idx] = skb;
++ skb->dev = dev;
++ /* 16 byte align the IP header */
++ skb_reserve (skb, 2);
++ dmac_inv_range ((void *)skb->data,
++ (void *)skb->data + RX_BUF_SIZE);
++ priv->rx_descs[start_idx].RXBUF_BADR = cpu_to_le32(virt_to_phys(skb->tail));
++ priv->rx_descs[start_idx].VIR_RXBUF_BADR = cpu_to_le32((u32)skb->tail);
++ }
++
++
++ priv->rx_descs[start_idx].RXPKT_RDY = RX_OWNBY_FTGMAC100;
++ }
++ }
++ if (trans_busy == 1)
++ {
++ /// priv->maccr_val |= RXMAC_EN_bit;
++ outl( priv->maccr_val, ioaddr + MACCR_REG );
++ outl( inl(ioaddr + IER_REG) | RXBUF_UNAVA_bit, ioaddr + IER_REG);
++ }
++ return;
++}
++
++/*--------------------------------------------------------------------
++ .
++ . This is the main routine of the driver, to handle the net_device when
++ . it needs some attention.
++ .
++ . So:
++ . first, save state of the chipset
++ . branch off into routines to handle each case, and acknowledge
++ . each to the interrupt register
++ . and finally restore state.
++ .
++ ---------------------------------------------------------------------*/
++static irqreturn_t ftgmac100_interrupt(int irq, void * dev_id, struct pt_regs * regs)
++{
++ struct net_device *dev = dev_id;
++ struct ftgmac100_priv *priv = (struct ftgmac100_priv *)dev->priv;
++ unsigned long ioaddr = dev->base_addr;
++ int timeout;
++ unsigned int tmp;
++ unsigned int mask; // interrupt mask
++ unsigned int status; // interrupt status
++
++// PRINTK3("%s: ftgmac100 interrupt started \n", dev->name);
++
++ if (dev == NULL) {
++ DO_PRINT(KERN_WARNING "%s: irq %d for unknown device.\n", dev->name, irq);
++ return IRQ_HANDLED;
++ }
++
++ /* read the interrupt status register */
++ mask = inl( ioaddr + IER_REG );
++
++ /* set a timeout value, so I don't stay here forever */
++
++ for (timeout=1; timeout>0; --timeout)
++ {
++ /* read the status flag, and mask it */
++ status = inl( ioaddr + ISR_REG ) & mask;
++
++ outl(status, ioaddr + ISR_REG ); //Richard, write to clear
++
++ if (!status )
++ {
++ break;
++ }
++
++ if (status & PHYSTS_CHG_bit) {
++ DO_PRINT("PHYSTS_CHG \n");
++ // Is this interrupt for changes of the PHYLINK pin?
++ // Note: PHYLINK is optional; not all boards connect it.
++ if (((priv->ids.miiPhyId & PHYID_VENDOR_MASK) == PHYID_VENDOR_MARVELL) ||
++ ((priv->ids.miiPhyId & PHYID_VENDOR_MODEL_MASK) == PHYID_RTL8211))
++ {
++ tmp = ftgmac100_read_phy_register(ioaddr, priv->ids.phyAddr, 0x13);
++ PRINTK("%s: PHY interrupt status, read_phy_reg(0x13) = 0x%04x\n",
++ dev->name, tmp);
++ tmp &= (PHY_SPEED_CHG_bit | PHY_DUPLEX_CHG_bit | PHY_LINK_CHG_bit);
++ }
++ else if ((priv->ids.miiPhyId & PHYID_VENDOR_MASK) == PHYID_VENDOR_BROADCOM)
++ {
++ tmp = ftgmac100_read_phy_register(ioaddr, priv->ids.phyAddr, 0x1a);
++ PRINTK("%s: PHY interrupt status, read_phy_reg(0x1a) = 0x%04x\n",
++ dev->name, tmp);
++ // Bits [3:1] are {duplex, speed, link} change interrupts.
++ tmp &= 0x000e;
++ }
++ else if (priv->ids.miiPhyId == PHYID_BCM54612E) {
++ tmp = ftgmac100_read_phy_register(ioaddr, priv->ids.phyAddr, 0x1A);
++ PRINTK("%s: PHY interrupt status, read_phy_reg(0x1A) = 0x%04x\n",
++ dev->name, tmp);
++ tmp &= 0x000E;
++ }
++ else tmp = 0;
++
++ if (tmp) {
++ ftgmac100_reset(dev);
++ ftgmac100_enable(dev);
++ }
++ }
++
++#ifdef not_complete_yet
++ if (status & AHB_ERR_bit)
++ {
++ DO_PRINT("AHB_ERR \n");
++ }
++
++ if (status & RPKT_LOST_bit)
++ {
++ DO_PRINT("RPKT_LOST ");
++ }
++ if (status & RPKT2F_bit)
++ {
++ PRINTK2("RPKT_SAV ");
++ }
++
++ if (status & TPKT_LOST_bit)
++ {
++ PRINTK("XPKT_LOST ");
++ }
++ if (status & TPKT2E_bit)
++ {
++ PRINTK("XPKT_OK ");
++ }
++ if (status & NPTXBUF_UNAVA_bit)
++ {
++ PRINTK("NOTXBUF ");
++ }
++ if (status & TPKT2F_bit)
++ {
++ PRINTK("XPKT_FINISH ");
++ }
++
++ if (status & RPKT2B_bit)
++ {
++ DO_PRINT("RPKT_FINISH ");
++ }
++ PRINTK2("\n");
++#endif /* end_of_not */
++
++// PRINTK3(KERN_WARNING "%s: Handling interrupt status %x \n", dev->name, status);
++
++ if ( status & (TPKT2E_bit|TPKT_LOST_bit))
++ {
++ //free tx skb buf
++ ftgmac100_free_tx(dev);
++
++ }
++
++ if ( status & RPKT2B_bit )
++ {
++ ftgmac100_rcv(dev); //Richard
++ }
++ else if (status & RXBUF_UNAVA_bit)
++ {
++ outl( mask & ~RXBUF_UNAVA_bit, ioaddr + IER_REG);
++ trans_busy = 1;
++ /*
++ rcv_tq.sync = 0;
++ rcv_tq.routine = ftgmac100_rcv;
++ rcv_tq.data = dev;
++ queue_task(&rcv_tq, &tq_timer);
++ */
++
++ } else if (status & AHB_ERR_bit)
++ {
++ DO_PRINT("AHB ERR \n");
++ }
++ }
++
++// PRINTK3("%s: Interrupt done\n", dev->name);
++ return IRQ_HANDLED;
++}
++
++/*------------------------------------------------------------
++ . Get the current statistics.
++ . This may be called with the card open or closed.
++ .-------------------------------------------------------------*/
++static struct net_device_stats* ftgmac100_query_statistics(struct net_device *dev)
++{
++ struct ftgmac100_priv *priv = (struct ftgmac100_priv *)dev->priv;
++
++ return &priv->stats;
++}
++
++#ifdef HAVE_MULTICAST
++
++// --------------------------------------------------------------------
++// Finds the CRC32 of a set of bytes.
++// Again, from Peter Cammaert's code.
++// --------------------------------------------------------------------
++static int crc32( char * s, int length )
++{
++ /* indices */
++ int perByte;
++ int perBit;
++ /* crc polynomial for Ethernet */
++ const u32 poly = 0xedb88320;
++ /* crc value - preinitialized to all 1's */
++ u32 crc_value = 0xffffffff;
++
++ for ( perByte = 0; perByte < length; perByte ++ ) {
++ unsigned char c;
++
++ c = *(s++);
++ for ( perBit = 0; perBit < 8; perBit++ ) {
++ crc_value = (crc_value>>1)^
++ (((crc_value^c)&0x01)?poly:0);
++ c >>= 1;
++ }
++ }
++ return crc_value;
++}
++
++/*
++ . Function: ftgmac100_setmulticast( struct net_device *dev, int count, struct dev_mc_list * addrs )
++ . Purpose:
++ . This sets the internal hardware table to filter out unwanted multicast
++ . packets before they take up memory.
++*/
++
++static void ftgmac100_setmulticast( struct net_device *dev, int count, struct dev_mc_list * addrs )
++{
++ struct dev_mc_list * cur_addr;
++ int crc_val;
++ unsigned int ioaddr = dev->base_addr;
++ struct ftgmac100_priv *priv = (struct ftgmac100_priv *)dev->priv;
++ struct AstMacHwConfig* ids = &priv->ids;
++ unsigned long Combined_Channel_ID, i;
++ struct sk_buff * skb;
++ cur_addr = addrs;
++
++//TX
++#if 0
++ if (priv->NCSI_support == 1) {
++ skb = dev_alloc_skb (TX_BUF_SIZE + 16);
++ priv->InstanceID++;
++ priv->NCSI_Request.IID = priv->InstanceID;
++ priv->NCSI_Request.Command = SET_MAC_ADDRESS;
++ Combined_Channel_ID = (priv->NCSI_Cap.Package_ID << 5) + priv->NCSI_Cap.Channel_ID;
++ priv->NCSI_Request.Channel_ID = Combined_Channel_ID;
++ priv->NCSI_Request.Payload_Length = (8 << 8);
++ memcpy ((unsigned char *)skb->data, &priv->NCSI_Request, 30);
++ priv->NCSI_Request.Payload_Length = 8;
++ for (i = 0; i < 6; i++) {
++ priv->Payload_Data[i] = cur_addr->dmi_addr[i];
++ }
++ priv->Payload_Data[6] = 2; //MAC Address Num = 1 --> address filter 1, fixed in sample code
++ priv->Payload_Data[7] = MULTICAST_ADDRESS + 0 + ENABLE_MAC_ADDRESS_FILTER; //AT + Reserved + E
++ copy_data (dev, skb, priv->NCSI_Request.Payload_Length);
++ skb->len = 30 + priv->NCSI_Request.Payload_Length + 4;
++ ftgmac100_wait_to_send_packet(skb, dev);
++ }
++#endif
++ for (cur_addr = addrs ; cur_addr!=NULL ; cur_addr = cur_addr->next )
++ {
++ /* make sure this is a multicast address - shouldn't this be a given if we have it here ? */
++ if ( !( *cur_addr->dmi_addr & 1 ) )
++ {
++ continue;
++ }
++#if 1
++//A0, A1
++ crc_val = crc32( cur_addr->dmi_addr, 5 );
++ crc_val = (~(crc_val>>2)) & 0x3f;
++ if (crc_val >= 32)
++ {
++ outl(inl(ioaddr+MAHT1_REG) | (1UL<<(crc_val-32)), ioaddr+MAHT1_REG);
++ priv->GigaBit_MAHT1 = inl (ioaddr + MAHT1_REG);
++ }
++ else
++ {
++ outl(inl(ioaddr+MAHT0_REG) | (1UL<<crc_val), ioaddr+MAHT0_REG);
++ priv->GigaBit_MAHT0 = inl (ioaddr + MAHT0_REG);
++ }
++//10/100M
++ crc_val = crc32( cur_addr->dmi_addr, 6 );
++ crc_val = (~(crc_val>>2)) & 0x3f;
++ if (crc_val >= 32)
++ {
++ outl(inl(ioaddr+MAHT1_REG) | (1UL<<(crc_val-32)), ioaddr+MAHT1_REG);
++ priv->Not_GigaBit_MAHT1 = inl (ioaddr + MAHT1_REG);
++ }
++ else
++ {
++ outl(inl(ioaddr+MAHT0_REG) | (1UL<<crc_val), ioaddr+MAHT0_REG);
++ priv->Not_GigaBit_MAHT0 = inl (ioaddr + MAHT0_REG);
++ }
++#else
++//A2
++ crc_val = crc32( cur_addr->dmi_addr, 6 );
++ crc_val = (~(crc_val>>2)) & 0x3f;
++ if (crc_val >= 32)
++ {
++ outl(inl(ioaddr+MAHT1_REG) | (1UL<<(crc_val-32)), ioaddr+MAHT1_REG);
++ priv->Not_GigaBit_MAHT1 = inl (ioaddr + MAHT1_REG);
++ priv->GigaBit_MAHT1 = inl (ioaddr + MAHT1_REG);
++ }
++ else
++ {
++ outl(inl(ioaddr+MAHT0_REG) | (1UL<<crc_val), ioaddr+MAHT0_REG);
++ priv->Not_GigaBit_MAHT0 = inl (ioaddr + MAHT0_REG);
++ priv->GigaBit_MAHT0 = inl (ioaddr + MAHT0_REG);
++ }
++#endif
++ }
++}
++
++/*-----------------------------------------------------------
++ . ftgmac100_set_multicast_list
++ .
++ . This routine will, depending on the values passed to it,
++ . either make it accept multicast packets, go into
++ . promiscuous mode ( for TCPDUMP and cousins ) or accept
++ . a select set of multicast packets
++*/
++static void ftgmac100_set_multicast_list(struct net_device *dev)
++{
++ unsigned int ioaddr = dev->base_addr;
++ struct ftgmac100_priv *priv = (struct ftgmac100_priv *)dev->priv;
++
++ PRINTK2("%s:ftgmac100_set_multicast_list\n", dev->name);
++
++ if (dev->flags & IFF_PROMISC)
++ priv->maccr_val |= RX_ALLADR_bit;
++ else
++ priv->maccr_val &= ~RX_ALLADR_bit;
++
++ if (dev->flags & IFF_ALLMULTI)
++ priv->maccr_val |= RX_MULTIPKT_bit;
++ else
++ priv->maccr_val &= ~RX_MULTIPKT_bit;
++
++ if (dev->mc_count)
++ {
++// PRINTK("set multicast\n");
++ priv->maccr_val |= RX_HT_EN_bit;
++ ftgmac100_setmulticast( dev, dev->mc_count, dev->mc_list );
++ }
++ else
++ {
++ priv->maccr_val &= ~RX_HT_EN_bit;
++ }
++
++ outl( priv->maccr_val, ioaddr + MACCR_REG );
++
++}
++#endif
++
++static int ast_gmac_stop(struct net_device *dev)
++{
++ struct ftgmac100_priv *priv = (struct ftgmac100_priv *)dev->priv;
++
++ netif_stop_queue(dev);
++
++ /* clear everything */
++ ftgmac100_shutdown(dev->base_addr);
++ free_irq(dev->irq, dev);
++
++ if (priv->timer.function != NULL) {
++ del_timer_sync(&priv->timer);
++ }
++
++ if (priv->rx_descs)
++ dma_free_coherent( NULL, sizeof(RX_DESC)*RXDES_NUM, (void*)priv->rx_descs, (dma_addr_t)priv->rx_descs_dma );
++ if (priv->tx_descs)
++ dma_free_coherent( NULL, sizeof(TX_DESC)*TXDES_NUM, (void*)priv->tx_descs, (dma_addr_t)priv->tx_descs_dma );
++ if (priv->tx_buf)
++ dma_free_coherent( NULL, TX_BUF_SIZE*TXDES_NUM, (void*)priv->tx_buf, (dma_addr_t)priv->tx_buf_dma );
++ priv->rx_descs = NULL; priv->rx_descs_dma = 0;
++ priv->tx_descs = NULL; priv->tx_descs_dma = 0;
++ priv->tx_buf = NULL; priv->tx_buf_dma = 0;
++
++
++ return 0;
++}
++
++static struct proc_dir_entry *proc_ftgmac100;
++
++static int ftgmac100_read_proc(char *page, char **start, off_t off, int count, int *eof, void *data)
++{
++ struct net_device *dev = (struct net_device *)data;
++ struct ftgmac100_priv *priv = (struct ftgmac100_priv *)dev->priv;
++ int num;
++ int i;
++
++ num = sprintf(page, "priv->rx_idx = %d\n", priv->rx_idx);
++ for (i=0; i<RXDES_NUM; ++i)
++ {
++ num += sprintf(page + num, "[%d].RXDMA_OWN = %d\n", i, priv->rx_descs[i].RXPKT_RDY);
++ }
++ return num;
++}
++
++static int ftgmac100_open(struct net_device *netdev)
++{
++ struct ftgmac100_priv *priv = netdev_priv(netdev);
++ int err;
++
++ DO_PRINT("%s:ftgmac100_open\n", netdev->name);
++
++ priv->maccr_val = (CRC_APD_bit | RXMAC_EN_bit | TXMAC_EN_bit | RXDMA_EN_bit
++ | TXDMA_EN_bit | CRC_CHK_bit | RX_BROADPKT_bit | SPEED_100_bit | FULLDUP_bit);
++
++ ftgmac100_ringbuf_alloc(priv);
++
++
++ /* Grab the IRQ next. Beyond this, we will free the IRQ. */
++ err = request_irq(netdev->irq, (void *)&ftgmac100_interrupt,
++ IRQF_DISABLED, netdev->name, netdev);
++ if (err)
++ {
++ DO_PRINT("%s: unable to get IRQ %d (retval=%d).\n",
++ netdev->name, netdev->irq, err);
++ kfree(netdev->priv);
++ netdev->priv = NULL;
++ return err;
++ }
++
++
++ netif_start_queue(netdev);
++
++ /* reset the hardware */
++ ftgmac100_reset(netdev);
++ ftgmac100_enable(netdev);
++
++ if (((priv->ids.miiPhyId & PHYID_VENDOR_MASK) == PHYID_VENDOR_BROADCOM) ||
++ ((priv->ids.miiPhyId & PHYID_VENDOR_MODEL_MASK) == PHYID_RTL8201EL) ||
++ (priv->ids.miiPhyId == PHYID_BCM54612E)) {
++
++ init_timer(&priv->timer);
++ priv->timer.data = (unsigned long)netdev;
++ priv->timer.function = aspeed_mac_timer;
++ priv->timer.expires = jiffies + 1 * HZ;
++ add_timer (&priv->timer);
++ }
++
++ /* Configure the PHY */
++ ftgmac100_phy_configure(netdev);
++
++ netif_start_queue(netdev);
++ return 0;
++}
++
++static int __init ast_gmac_probe(struct platform_device *pdev)
++{
++ struct resource *res;
++ struct net_device *netdev;
++ struct ftgmac100_priv *priv;
++ struct ftgmac100_eth_data *ast_eth_data = pdev->dev.platform_data;;
++ int err;
++
++ if (!pdev)
++ return -ENODEV;
++
++ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
++ if (!res)
++ return -ENXIO;
++
++ /* setup net_device */
++ netdev = alloc_etherdev(sizeof(*priv));
++ if (!netdev) {
++ err = -ENOMEM;
++ goto err_alloc_etherdev;
++ }
++
++ netdev->irq = platform_get_irq(pdev, 0);
++ if (netdev->irq < 0) {
++ err = -ENXIO;
++ goto err_netdev;
++ }
++
++ SET_NETDEV_DEV(netdev, &pdev->dev);
++
++
++// SET_ETHTOOL_OPS(netdev, &ftgmac100_ethtool_ops);
++
++#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,30))
++ netdev->netdev_ops = &ftgmac100_netdev_ops;
++#else
++ printk("ast_gmac_probe 5\n");
++
++ ether_setup(netdev);
++
++ netdev->open = ftgmac100_open;
++ netdev->stop = ast_gmac_stop;
++ netdev->hard_start_xmit = ftgmac100_wait_to_send_packet;
++ netdev->tx_timeout = ftgmac100_timeout;
++ netdev->get_stats = ftgmac100_query_statistics;
++//#ifdef HAVE_MULTICAST
++#if 0
++ netdev->set_multicast_list = &ftgmac100_set_multicast_list;
++#endif
++
++#endif
++
++
++#ifdef CONFIG_AST_NPAI
++// netdev->features = NETIF_F_GRO;
++// netdev->features = NETIF_F_IP_CSUM | NETIF_F_GRO;
++#endif
++
++ platform_set_drvdata(pdev, netdev);
++
++ /* setup private data */
++ priv = netdev_priv(netdev);
++ priv->netdev = netdev;
++ priv->dev = &pdev->dev;
++
++
++ priv->ids.macId = pdev->id;
++
++ priv->NCSI_support = ast_eth_data->NCSI_support;
++ priv->INTEL_NCSI_EVA_support= ast_eth_data->INTEL_NCSI_EVA_support;
++ spin_lock_init(&priv->tx_lock);
++
++#if 0
++ /* initialize NAPI */
++ netif_napi_add(netdev, &priv->napi, ftgmac100_poll, 64);
++#endif
++ /* map io memory */
++ res = request_mem_region(res->start, resource_size(res),
++ dev_name(&pdev->dev));
++ if (!res) {
++ dev_err(&pdev->dev, "Could not reserve memory region\n");
++ err = -ENOMEM;
++ goto err_req_mem;
++ }
++
++ netdev->base_addr = (u32)ioremap(res->start, resource_size(res));
++
++ if (!netdev->base_addr) {
++ dev_err(&pdev->dev, "Failed to ioremap ethernet registers\n");
++ err = -EIO;
++ goto err_ioremap;
++ }
++
++// priv->irq = irq;
++#if 0//CONFIG_AST_MDIO
++ /* initialize mdio bus */
++ priv->mii_bus = mdiobus_alloc();
++ if (!priv->mii_bus) {
++ err = -EIO;
++ goto err_alloc_mdiobus;
++ }
++
++ priv->mii_bus->name = "ftgmac100_mdio";
++ snprintf(priv->mii_bus->id, MII_BUS_ID_SIZE, "ftgmac100_mii.%d",pdev->id);
++
++ priv->mii_bus->priv = netdev;
++ priv->mii_bus->read = ftgmac100_mdiobus_read;
++ priv->mii_bus->write = ftgmac100_mdiobus_write;
++ priv->mii_bus->reset = ftgmac100_mdiobus_reset;
++ priv->mii_bus->irq = priv->phy_irq;
++
++ for (i = 0; i < PHY_MAX_ADDR; i++)
++ priv->mii_bus->irq[i] = PHY_POLL;
++
++ err = mdiobus_register(priv->mii_bus);
++ if (err) {
++ dev_err(&pdev->dev, "Cannot register MDIO bus!\n");
++ goto err_register_mdiobus;
++ }
++
++ err = ftgmac100_mii_probe(priv);
++ if (err) {
++ dev_err(&pdev->dev, "MII Probe failed!\n");
++ goto err_mii_probe;
++ }
++#endif
++ /* register network device */
++ err = register_netdev(netdev);
++ if (err) {
++ dev_err(&pdev->dev, "Failed to register netdev\n");
++ goto err_alloc_mdiobus;
++ }
++
++// printk("irq %d, mapped at %x\n", netdev->irq, (u32)netdev->base_addr);
++
++ if (!is_valid_ether_addr(netdev->dev_addr)) {
++ random_ether_addr(netdev->dev_addr);
++ printk("generated random MAC address %pM\n",
++ netdev->dev_addr);
++ }
++#if 0
++ if ((proc_ftgmac100 = create_proc_entry( dev->name, 0, 0 )))
++ {
++ proc_ftgmac100->read_proc = ftgmac100_read_proc;
++ proc_ftgmac100->data = dev;
++ proc_ftgmac100->owner = THIS_MODULE;
++ }
++#endif
++ return 0;
++
++//err_register_netdev:
++// phy_disconnect(priv->phydev);
++//err_mii_probe:
++// mdiobus_unregister(priv->mii_bus);
++//err_register_mdiobus:
++// mdiobus_free(priv->mii_bus);
++err_alloc_mdiobus:
++ iounmap((void __iomem *)netdev->base_addr);
++err_ioremap:
++ release_resource(res);
++err_req_mem:
++// netif_napi_del(&priv->napi);
++ platform_set_drvdata(pdev, NULL);
++err_netdev:
++ free_netdev(netdev);
++err_alloc_etherdev:
++ return err;
++
++}
++
++static int __devexit ast_gmac_remove(struct platform_device *pdev)
++{
++ struct net_device *dev = platform_get_drvdata(pdev);
++// struct ftgmac100_priv *priv = netdev_priv(dev);
++
++// remove_proc_entry(dev->name, 0);
++
++ unregister_netdev(dev);
++
++#ifdef CONFIG_MII_PHY
++ phy_disconnect(priv->phydev);
++ mdiobus_unregister(priv->mii_bus);
++ mdiobus_free(priv->mii_bus);
++#endif
++
++ iounmap((void __iomem *)dev->base_addr);
++
++#ifdef CONFIG_AST_NPAI
++ netif_napi_del(&priv->napi);
++#endif
++
++ platform_set_drvdata(pdev, NULL);
++ free_netdev(dev);
++ return 0;
++}
++
++static struct platform_driver ast_gmac_driver = {
++ .remove = __devexit_p(ast_gmac_remove),
++ .driver = {
++ .name = "ast_gmac",
++ .owner = THIS_MODULE,
++ },
++};
++
++static int __init ast_gmac_init(void)
++{
++ return platform_driver_probe(&ast_gmac_driver, ast_gmac_probe);
++}
++
++static void __exit ast_gmac_exit(void)
++{
++ platform_driver_unregister(&ast_gmac_driver);
++}
++
++module_init(ast_gmac_init)
++module_exit(ast_gmac_exit)
++
++MODULE_LICENSE("GPL");
++MODULE_AUTHOR("ASPEED Technology Inc.");
++MODULE_DESCRIPTION("NIC driver for AST Series");
++MODULE_LICENSE("GPL");
+diff --git a/drivers/net/ftgmac100_26.h b/drivers/net/ftgmac100_26.h
+new file mode 100644
+index 0000000..f145b05
+--- /dev/null
++++ b/drivers/net/ftgmac100_26.h
+@@ -0,0 +1,580 @@
++/********************************************************************************
++* File Name : ftgmac100_26.h
++*
++* Copyright (C) 2012-2020 ASPEED Technology Inc.
++* This program is free software; you can redistribute it and/or modify
++* it under the terms of the GNU General Public License as published by the Free Software Foundation;
++* either version 2 of the License, or (at your option) any later version.
++* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
++* without even the implied warranty of MERCHANTABILITY or
++* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
++* You should have received a copy of the GNU General Public License
++* along with this program; if not, write to the Free Software
++* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++********************************************************************************/
++// --------------------------------------------------------------------
++
++#ifndef FTMAC100_H
++#define FTMAC100_H
++
++#define HAVE_MULTICAST
++
++#define ISR_REG 0x00 // interrups status register
++#define IER_REG 0x04 // interrupt maks register
++#define MAC_MADR_REG 0x08 // MAC address (Most significant)
++#define MAC_LADR_REG 0x0c // MAC address (Least significant)
++
++#define MAHT0_REG 0x10 // Multicast Address Hash Table 0 register
++#define MAHT1_REG 0x14 // Multicast Address Hash Table 1 register
++#define TXPD_REG 0x18 // Transmit Poll Demand register
++#define RXPD_REG 0x1c // Receive Poll Demand register
++#define TXR_BADR_REG 0x20 // Transmit Ring Base Address register
++#define RXR_BADR_REG 0x24 // Receive Ring Base Address register
++
++#define HPTXPD_REG 0x28 //
++#define HPTXR_BADR_REG 0x2c //
++
++#define ITC_REG 0x30 // interrupt timer control register
++#define APTC_REG 0x34 // Automatic Polling Timer control register
++#define DBLAC_REG 0x38 // DMA Burst Length and Arbitration control register
++
++#define DMAFIFOS_REG 0x3c //
++#define FEAR_REG 0x44 //
++#define TPAFCR_REG 0x48 //
++#define RBSR_REG 0x4c //for NC Body
++#define MACCR_REG 0x50 // MAC control register
++#define MACSR_REG 0x54 // MAC status register
++#define PHYCR_REG 0x60 // PHY control register
++#define PHYDATA_REG 0x64 // PHY Write Data register
++#define FCR_REG 0x68 // Flow Control register
++#define BPR_REG 0x6c // back pressure register
++#define WOLCR_REG 0x70 // Wake-On-Lan control register
++#define WOLSR_REG 0x74 // Wake-On-Lan status register
++#define WFCRC_REG 0x78 // Wake-up Frame CRC register
++#define WFBM1_REG 0x80 // wake-up frame byte mask 1st double word register
++#define WFBM2_REG 0x84 // wake-up frame byte mask 2nd double word register
++#define WFBM3_REG 0x88 // wake-up frame byte mask 3rd double word register
++#define WFBM4_REG 0x8c // wake-up frame byte mask 4th double word register
++
++#define NPTXR_PTR_REG 0x90 //
++#define HPTXR_PTR_REG 0x94 //
++#define RXR_PTR_REG 0x98 //
++
++
++// --------------------------------------------------------------------
++// ISR_REG ¤Î IMR_REG
++// --------------------------------------------------------------------
++#define HPTXBUF_UNAVA_bit (1UL<<10)
++#define PHYSTS_CHG_bit (1UL<<9)
++#define AHB_ERR_bit (1UL<<8)
++#define TPKT_LOST_bit (1UL<<7)
++#define NPTXBUF_UNAVA_bit (1UL<<6)
++#define TPKT2F_bit (1UL<<5)
++#define TPKT2E_bit (1UL<<4)
++#define RPKT_LOST_bit (1UL<<3)
++#define RXBUF_UNAVA_bit (1UL<<2)
++#define RPKT2F_bit (1UL<<1)
++#define RPKT2B_bit (1UL<<0)
++
++
++// --------------------------------------------------------------------
++// APTC_REG
++// --------------------------------------------------------------------
++
++
++typedef struct
++{
++ u32 RXPOLL_CNT:4;
++ u32 RXPOLL_TIME_SEL:1;
++ u32 Reserved1:3;
++ u32 TXPOLL_CNT:4;
++ u32 TXPOLL_TIME_SEL:1;
++ u32 Reserved2:19;
++}FTGMAC100_APTCR_Status;
++
++// --------------------------------------------------------------------
++// PHYCR_REG
++// --------------------------------------------------------------------
++#define PHY_RE_AUTO_bit (1UL<<9)
++#define PHY_READ_bit (1UL<<26)
++#define PHY_WRITE_bit (1UL<<27)
++// --------------------------------------------------------------------
++// PHYCR_REG
++// --------------------------------------------------------------------
++#define PHY_AUTO_OK_bit (1UL<<5)
++// --------------------------------------------------------------------
++// PHY INT_STAT_REG
++// --------------------------------------------------------------------
++#define PHY_SPEED_CHG_bit (1UL<<14)
++#define PHY_DUPLEX_CHG_bit (1UL<<13)
++#define PHY_LINK_CHG_bit (1UL<<10)
++#define PHY_AUTO_COMP_bit (1UL<<11)
++// --------------------------------------------------------------------
++// PHY SPE_STAT_REG
++// --------------------------------------------------------------------
++#define PHY_RESOLVED_bit (1UL<<11)
++#define PHY_SPEED_mask 0xC000
++#define PHY_SPEED_10M 0x0
++#define PHY_SPEED_100M 0x1
++#define PHY_SPEED_1G 0x2
++#define PHY_DUPLEX_mask 0x2000
++//#define PHY_FULLDUPLEX 0x1
++#define PHY_SPEED_DUPLEX_MASK 0x01E0
++#define PHY_100M_DUPLEX 0x0100
++#define PHY_100M_HALF 0x0080
++#define PHY_10M_DUPLEX 0x0040
++#define PHY_10M_HALF 0x0020
++#define LINK_STATUS 0x04
++
++
++// --------------------------------------------------------------------
++// MACCR_REG
++// --------------------------------------------------------------------
++
++#define SW_RST_bit (1UL<<31) // software reset/
++#define DIRPATH_bit (1UL<<21)
++#define RX_IPCS_FAIL_bit (1UL<<20) //
++#define SPEED_100_bit (1UL<<19) //
++#define RX_UDPCS_FAIL_bit (1UL<<18) //
++#define RX_BROADPKT_bit (1UL<<17) // Receiving broadcast packet
++#define RX_MULTIPKT_bit (1UL<<16) // receiving multicast packet
++#define RX_HT_EN_bit (1UL<<15)
++#define RX_ALLADR_bit (1UL<<14) // not check incoming packet's destination address
++#define JUMBO_LF_bit (1UL<<13) //
++#define RX_RUNT_bit (1UL<<12) // Store incoming packet even its length is les than 64 byte
++#define CRC_CHK_bit (1UL<<11) //
++#define CRC_APD_bit (1UL<<10) // append crc to transmit packet
++#define GMAC_MODE_bit (1UL<<9) //
++#define FULLDUP_bit (1UL<<8) // full duplex
++#define ENRX_IN_HALFTX_bit (1UL<<7) //
++#define LOOP_EN_bit (1UL<<6) // Internal loop-back
++#define HPTXR_EN_bit (1UL<<5) //
++#define REMOVE_VLAN_bit (1UL<<4) //
++//#define MDC_SEL_bit (1UL<<13) // set MDC as TX_CK/10
++//#define RX_FTL_bit (1UL<<11) // Store incoming packet even its length is great than 1518 byte
++#define RXMAC_EN_bit (1UL<<3) // receiver enable
++#define TXMAC_EN_bit (1UL<<2) // transmitter enable
++#define RXDMA_EN_bit (1UL<<1) // enable DMA receiving channel
++#define TXDMA_EN_bit (1UL<<0) // enable DMA transmitting channel
++
++
++// --------------------------------------------------------------------
++// SCU_REG
++// --------------------------------------------------------------------
++#define SCU_PROTECT_KEY_REG 0x0
++#define SCU_PROT_KEY_MAGIC 0x1688a8a8
++#define SCU_RESET_CONTROL_REG 0x04
++#define SCU_RESET_MAC1 (1u << 11)
++#define SCU_RESET_MAC2 (1u << 12)
++
++#define SCU_HARDWARE_TRAPPING_REG 0x70
++#define SCU_HT_MAC_INTF_LSBIT 6
++#define SCU_HT_MAC_INTERFACE (0x7u << SCU_HT_MAC_INTF_LSBIT)
++#define MAC_INTF_SINGLE_PORT_MODES (1u<<0/*GMII*/ | 1u<<3/*MII_ONLY*/ | 1u<<4/*RMII_ONLY*/)
++#define SCU_HT_MAC_GMII 0x0u
++// MII and MII mode
++#define SCU_HT_MAC_MII_MII 0x1u
++#define SCU_HT_MAC_MII_ONLY 0x3u
++#define SCU_HT_MAC_RMII_ONLY 0x4u
++
++/*
++SCU88 D[31]: MAC1 MDIO
++SCU88 D[30]: MAC1 MDC
++SCU90 D[2]: MAC2 MDC/MDIO
++SCU80 D[0]: MAC1 Link
++SCU80 D[1]: MAC2 Link
++*/
++#define SCU_MULTIFUNCTION_PIN_REG 0x74
++#define SCU_MULTIFUNCTION_PIN_CTL1_REG 0x80
++#define SCU_MULTIFUNCTION_PIN_CTL3_REG 0x88
++#define SCU_MULTIFUNCTION_PIN_CTL5_REG 0x90
++#define SCU_MFP_MAC2_PHYLINK (1u << 1)
++#define SCU_MFP_MAC1_PHYLINK (1u << 0)
++#define SCU_MFP_MAC2_MII_INTF (1u << 21)
++#define SCU_MFP_MAC2_MDC_MDIO (1u << 2)
++#define SCU_MFP_MAC1_MDIO (1u << 31)
++#define SCU_MFP_MAC1_MDC (1u << 30)
++#define SCU_SILICON_REVISION_REG 0x7C
++#define SCU_SCRATCH_REG 0x40
++
++
++
++// --------------------------------------------------------------------
++// NCSI
++// --------------------------------------------------------------------
++
++//NCSI define & structure
++//NC-SI Command Packet
++typedef struct {
++//Ethernet Header
++ unsigned char DA[6];
++ unsigned char SA[6];
++ unsigned short EtherType; //DMTF NC-SI
++//NC-SI Control Packet
++ unsigned char MC_ID; //Management Controller should set this field to 0x00
++ unsigned char Header_Revision; //For NC-SI 1.0 spec, this field has to set 0x01
++ unsigned char Reserved_1; //Reserved has to set to 0x00
++ unsigned char IID; //Instance ID
++ unsigned char Command;
++ unsigned char Channel_ID;
++ unsigned short Payload_Length; //Payload Length = 12 bits, 4 bits are reserved
++ unsigned long Reserved_2;
++ unsigned long Reserved_3;
++} NCSI_Command_Packet;
++
++//Command and Response Type
++#define CLEAR_INITIAL_STATE 0x00 //M
++#define SELECT_PACKAGE 0x01 //M
++#define DESELECT_PACKAGE 0x02 //M
++#define ENABLE_CHANNEL 0x03 //M
++#define DISABLE_CHANNEL 0x04 //M
++#define RESET_CHANNEL 0x05 //M
++#define ENABLE_CHANNEL_NETWORK_TX 0x06 //M
++#define DISABLE_CHANNEL_NETWORK_TX 0x07 //M
++#define AEN_ENABLE 0x08
++#define SET_LINK 0x09 //M
++#define GET_LINK_STATUS 0x0A //M
++#define SET_VLAN_FILTER 0x0B //M
++#define ENABLE_VLAN 0x0C //M
++#define DISABLE_VLAN 0x0D //M
++#define SET_MAC_ADDRESS 0x0E //M
++#define ENABLE_BROADCAST_FILTERING 0x10 //M
++#define DISABLE_BROADCAST_FILTERING 0x11 //M
++#define ENABLE_GLOBAL_MULTICAST_FILTERING 0x12
++#define DISABLE_GLOBAL_MULTICAST_FILTERING 0x13
++#define SET_NCSI_FLOW_CONTROL 0x14
++#define GET_VERSION_ID 0x15 //M
++#define GET_CAPABILITIES 0x16 //M
++#define GET_PARAMETERS 0x17 //M
++#define GET_CONTROLLER_PACKET_STATISTICS 0x18
++#define GET_NCSI_STATISTICS 0x19
++#define GET_NCSI_PASS_THROUGH_STATISTICS 0x1A
++
++//NC-SI Response Packet
++typedef struct {
++ unsigned char DA[6];
++ unsigned char SA[6];
++ unsigned short EtherType; //DMTF NC-SI
++//NC-SI Control Packet
++ unsigned char MC_ID; //Management Controller should set this field to 0x00
++ unsigned char Header_Revision; //For NC-SI 1.0 spec, this field has to set 0x01
++ unsigned char Reserved_1; //Reserved has to set to 0x00
++ unsigned char IID; //Instance ID
++ unsigned char Command;
++ unsigned char Channel_ID;
++ unsigned short Payload_Length; //Payload Length = 12 bits, 4 bits are reserved
++ unsigned short Reserved_2;
++ unsigned short Reserved_3;
++ unsigned short Reserved_4;
++ unsigned short Reserved_5;
++ unsigned short Response_Code;
++ unsigned short Reason_Code;
++ unsigned char Payload_Data[64];
++} NCSI_Response_Packet;
++
++//Standard Response Code
++#define COMMAND_COMPLETED 0x00
++#define COMMAND_FAILED 0x01
++#define COMMAND_UNAVAILABLE 0x02
++#define COMMAND_UNSUPPORTED 0x03
++
++//Standard Reason Code
++#define NO_ERROR 0x0000
++#define INTERFACE_INITIALIZATION_REQUIRED 0x0001
++#define PARAMETER_IS_INVALID 0x0002
++#define CHANNEL_NOT_READY 0x0003
++#define PACKAGE_NOT_READY 0x0004
++#define INVALID_PAYLOAD_LENGTH 0x0005
++#define UNKNOWN_COMMAND_TYPE 0x7FFF
++
++
++struct AEN_Packet {
++//Ethernet Header
++ unsigned char DA[6];
++ unsigned char SA[6]; //Network Controller SA = FF:FF:FF:FF:FF:FF
++ unsigned short EtherType; //DMTF NC-SI
++//AEN Packet Format
++ unsigned char MC_ID; //Network Controller should set this field to 0x00
++ unsigned char Header_Revision; //For NC-SI 1.0 spec, this field has to set 0x01
++ unsigned char Reserved_1; //Reserved has to set to 0x00
++// unsigned char IID = 0x00; //Instance ID = 0 in Network Controller
++// unsigned char Command = 0xFF; //AEN = 0xFF
++ unsigned char Channel_ID;
++// unsigned short Payload_Length = 0x04; //Payload Length = 4 in Network Controller AEN Packet
++ unsigned long Reserved_2;
++ unsigned long Reserved_3;
++ unsigned char AEN_Type;
++// unsigned char Reserved_4[3] = {0x00, 0x00, 0x00};
++ unsigned long Optional_AEN_Data;
++ unsigned long Payload_Checksum;
++};
++
++//AEN Type
++#define LINK_STATUS_CHANGE 0x0
++#define CONFIGURATION_REQUIRED 0x1
++#define HOST_NC_DRIVER_STATUS_CHANGE 0x2
++
++typedef struct {
++ unsigned char Package_ID;
++ unsigned char Channel_ID;
++ unsigned long Capabilities_Flags;
++ unsigned long Broadcast_Packet_Filter_Capabilities;
++ unsigned long Multicast_Packet_Filter_Capabilities;
++ unsigned long Buffering_Capabilities;
++ unsigned long AEN_Control_Support;
++} NCSI_Capability;
++NCSI_Capability NCSI_Cap;
++
++//SET_MAC_ADDRESS
++#define UNICAST (0x00 << 5)
++#define MULTICAST_ADDRESS (0x01 << 5)
++#define DISABLE_MAC_ADDRESS_FILTER 0x00
++#define ENABLE_MAC_ADDRESS_FILTER 0x01
++
++//GET_LINK_STATUS
++#define LINK_DOWN 0
++#define LINK_UP 1
++
++#define NCSI_LOOP 1500000
++#define RETRY_COUNT 1
++
++#define NCSI_HEADER 0xF888 //Reversed because of 0x88 is low byte, 0xF8 is high byte in memory
++
++// --------------------------------------------------------------------
++// Receive Ring descriptor structure
++// --------------------------------------------------------------------
++
++typedef struct
++{
++ // RXDES0
++ u32 VDBC:14;//0~10
++ u32 Reserved1:1; //11~15
++ u32 Reserved3:1;
++ u32 MULTICAST:1; //16
++ u32 BROADCAST:1; //17
++ u32 RX_ERR:1; //18
++ u32 CRC_ERR:1; //19
++ u32 FTL:1;
++ u32 RUNT:1;
++ u32 RX_ODD_NB:1;
++ u32 FIFO_FULL:1;
++ u32 PAUSE_OPCODE:1;
++ u32 PAUSE_FRAME:1;
++ u32 Reserved2:2;
++ u32 LRS:1;
++ u32 FRS:1;
++ u32 EDORR:1;
++ u32 RXPKT_RDY:1; // 1 ==> owned by FTMAC100, 0 ==> owned by software
++
++ // RXDES1
++ u32 VLAN_TAGC:16;
++ u32 Reserved4:4;
++ u32 PROTL_TYPE:2;
++ u32 LLC_PKT:1;
++ u32 DF:1;
++ u32 VLAN_AVA:1;
++ u32 TCPCS_FAIL:1;
++ u32 UDPCS_FAIL:1;
++ u32 IPCS_FAIL:1;
++ u32 Reserved5:4;
++
++ // RXDES2
++ u32 Reserved6:32;
++
++ // RXDES3
++ u32 RXBUF_BADR;
++
++ u32 VIR_RXBUF_BADR; // not defined, the virtual address of receive buffer is placed here
++
++ u32 RESERVED;
++ u32 RESERVED1;
++ u32 RESERVED2;
++}RX_DESC;
++
++
++typedef struct
++{
++ // TXDES0
++ u32 TXBUF_Size:14;
++ u32 Reserved1:1;
++ u32 Reserved2:1;
++ u32 Reserved3:3;
++ u32 CRC_ERR:1;
++ u32 Reserved4:8;
++ u32 LTS:1;
++ u32 FTS:1;
++ u32 EDOTR:1;
++ u32 TXDMA_OWN:1;
++
++ // TXDES1
++ u32 VLAN_TAGC:16;
++ u32 INS_VLAN:1;
++ u32 TCPCS_EN:1;
++ u32 UDPCS_EN:1;
++ u32 IPCS_EN:1;
++ u32 Reserved5:2;
++ u32 LLC_PKT:1;
++ u32 Reserved6:7;
++ u32 TX2FIC:1;
++ u32 TXIC:1;
++
++ // TXDES2
++ u32 Reserved7:32;
++
++ // TXDES3
++ u32 TXBUF_BADR;
++
++ u32 VIR_TXBUF_BADR; // Reserve, the virtual address of transmit buffer is placed here
++
++ u32 RESERVED;
++ u32 RESERVED1;
++ u32 RESERVED2;
++
++}TX_DESC;
++
++
++
++// waiting to do:
++#define TXPOLL_CNT 8
++#define RXPOLL_CNT 0
++
++#define TX_OWNBY_SOFTWARE 0
++#define TX_OWNBY_FTGMAC100 1
++
++
++#define RX_OWNBY_SOFTWARE 1
++#define RX_OWNBY_FTGMAC100 0
++
++// --------------------------------------------------------------------
++// driver related definition
++// --------------------------------------------------------------------
++
++
++//#define RXDES_NUM 64//64 // we defined 32 descriptor for OTG issue
++#define RXDES_NUM 32
++
++#define RX_BUF_SIZE 1536
++
++#define TXDES_NUM 32
++#define TX_BUF_SIZE 1536
++
++#define PHYID_VENDOR_MASK 0xfffffc00
++#define PHYID_VENDOR_MODEL_MASK 0xfffffff0
++#define PHYID_MODEL_MASK 0x000003f0
++#define PHYID_REVISION_MASK 0x0000000f
++#define PHYID_VENDOR_MARVELL 0x01410c00
++#define PHYID_VENDOR_BROADCOM 0x00406000
++#define PHYID_VENDOR_REALTEK 0x001cc800
++
++#define PHYID_BCM5221A4 0x004061e4
++//#define PHYID_RTL8201EL 0x001cc815
++#define PHYID_RTL8201EL 0x001cc810
++#define PHYID_RTL8201F 0x001cc816
++#define PHYID_RTL8211 0x001cc910
++#define PHYID_RTL8211E 0x001cc915
++#define PHYID_BCM54612E 0x03625E6A
++
++
++/* store this information for the driver.. */
++
++struct AstMacHwConfig {
++ unsigned char phyAddr; // See IP_phy_addr[] encoding
++ unsigned char macId;
++ unsigned char isRevA0;
++ unsigned char isRevA2;
++ unsigned char pad[1];
++ unsigned int miiPhyId;
++};
++
++struct ftgmac100_priv {
++
++ // these are things that the kernel wants me to keep, so users
++ // can find out semi-useless statistics of how well the card is
++ // performing
++ struct net_device_stats stats;
++
++ struct AstMacHwConfig ids;
++
++ struct net_device *netdev;
++ struct device *dev;
++
++ // Set to true during the auto-negotiation sequence
++ int autoneg_active;
++
++ // Last contents of PHY Register 18
++ u32 lastPhy18;
++
++ spinlock_t tx_lock;
++
++ //RX ..
++ volatile RX_DESC *rx_descs; // receive ring base address
++ struct sk_buff *rx_skbuff[RXDES_NUM];
++ u32 rx_descs_dma; // receive ring physical base address
++ int rx_idx; // receive descriptor
++
++ //TX ..
++ volatile TX_DESC *tx_descs;
++ u32 tx_descs_dma;
++ char *tx_buf;
++ int tx_buf_dma;
++ int tx_idx;
++ int old_tx;
++ struct sk_buff *tx_skbuff[TXDES_NUM];
++
++ int maccr_val;
++ struct timer_list timer;
++ u32 GigaBit_MAHT0;
++ u32 GigaBit_MAHT1;
++ u32 Not_GigaBit_MAHT0;
++ u32 Not_GigaBit_MAHT1;
++ NCSI_Command_Packet NCSI_Request;
++ NCSI_Response_Packet NCSI_Respond;
++ NCSI_Capability NCSI_Cap;
++ unsigned int InstanceID;
++ unsigned int Retry;
++ unsigned char Payload_Data[16];
++ unsigned char Payload_Pad[4];
++ unsigned long Payload_Checksum;
++ int tx_free;
++ unsigned long NCSI_support;
++ unsigned long INTEL_NCSI_EVA_support;
++};
++
++
++#define FTGMAC100_STROBE_TIME (10*HZ)
++///#define FTMAC100_STROBE_TIME 1
++
++//I2C define for EEPROM
++#define AC_TIMING 0x77743335
++#define ALL_CLEAR 0xFFFFFFFF
++#define MASTER_ENABLE 0x01
++#define SLAVE_ENABLE 0x02
++#define LOOP_COUNT 0x100000
++
++
++#define I2C_BASE 0x1e78A000
++#define I2C_FUNCTION_CONTROL_REGISTER 0x00
++#define I2C_AC_TIMING_REGISTER_1 0x04
++#define I2C_AC_TIMING_REGISTER_2 0x08
++#define I2C_INTERRUPT_CONTROL_REGISTER 0x0C
++#define I2C_INTERRUPT_STATUS_REGISTER 0x10
++#define I2C_COMMAND_REGISTER 0x14
++#define I2C_BYTE_BUFFER_REGISTER 0x20
++
++
++#define MASTER_START_COMMAND (1 << 0)
++#define MASTER_TX_COMMAND (1 << 1)
++#define MASTER_RX_COMMAND (1 << 3)
++#define RX_COMMAND_LIST (1 << 4)
++#define MASTER_STOP_COMMAND (1 << 5)
++
++#define TX_ACK (1 << 0)
++#define TX_NACK (1 << 1)
++#define RX_DONE (1 << 2)
++#define STOP_DONE (1 << 4)
++
++
++
++#endif /* _SMC_91111_H_ */
++
++
+diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig
+index 123092d..f60078c7 100644
+--- a/drivers/rtc/Kconfig
++++ b/drivers/rtc/Kconfig
+@@ -679,4 +679,10 @@ config RTC_DRV_STARFIRE
+ If you say Y here you will get support for the RTC found on
+ Starfire systems.
+
++config RTC_DRV_ASPEED
++ bool "ASPEED RTC"
++ depends on ARM
++ help
++ RTC driver for ASPEED chips.
++
+ endif # RTC_CLASS
+diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile
+index 6e79c91..7a16fed 100644
+--- a/drivers/rtc/Makefile
++++ b/drivers/rtc/Makefile
+@@ -70,3 +70,4 @@ obj-$(CONFIG_RTC_DRV_V3020) += rtc-v3020.o
+ obj-$(CONFIG_RTC_DRV_VR41XX) += rtc-vr41xx.o
+ obj-$(CONFIG_RTC_DRV_WM8350) += rtc-wm8350.o
+ obj-$(CONFIG_RTC_DRV_X1205) += rtc-x1205.o
++obj-$(CONFIG_RTC_DRV_ASPEED) += rtc-aspeed.o
+diff --git a/drivers/rtc/rtc-aspeed.c b/drivers/rtc/rtc-aspeed.c
+new file mode 100755
+index 0000000..477032e
+--- /dev/null
++++ b/drivers/rtc/rtc-aspeed.c
+@@ -0,0 +1,495 @@
++/********************************************************************************
++* File Name : drivers/rtc/rtc-ast.c
++* Author : Ryan chen
++* Description : ASPEED Real Time Clock Driver (RTC)
++*
++* Copyright (C) 2012-2020 ASPEED Technology Inc.
++* This program is free software; you can redistribute it and/or modify
++* it under the terms of the GNU General Public License as published by the Free Software Foundation;
++* either version 2 of the License, or (at your option) any later version.
++*
++* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
++* without even the implied warranty of MERCHANTABILITY or
++* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
++*
++* You should have received a copy of the GNU General Public License
++* along with this program; if not, write to the Free Software
++* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++
++* History :
++* 1. 2012/09/21 ryan chen create this file
++*
++********************************************************************************/
++
++#include <linux/module.h>
++#include <linux/platform_device.h>
++#include <linux/interrupt.h>
++#include <linux/rtc.h>
++#include <linux/delay.h>
++#include <linux/slab.h>
++#include <asm/io.h>
++
++#include <plat/regs-rtc.h>
++
++struct ast_rtc {
++ void __iomem *base;
++ int irq;
++ struct resource *res;
++ struct rtc_device *rtc_dev;
++ spinlock_t lock;
++};
++
++//static char banner[] = "ASPEED RTC, (C) ASPEED Technology Inc.\n";
++//#define CONFIG_RTC_DEBUG
++
++
++static inline u32
++rtc_read(void __iomem *base, u32 reg)
++{
++#ifdef CONFIG_RTC_DEBUG
++ int val = readl(base + reg);
++ pr_debug("base = 0x%p, offset = 0x%08x, value = 0x%08x\n", base, reg, val);
++ return val;
++#else
++ return readl(base + reg);
++#endif
++}
++
++static inline void
++rtc_write(void __iomem * base, u32 val, u32 reg)
++{
++ pr_debug("base = 0x%p, offset = 0x%08x, data = 0x%08x\n", base, reg, val);
++ writel(val, base + reg);
++}
++
++static int
++ast_rtc_ioctl(struct device *dev, unsigned int cmd, unsigned long arg)
++{
++ struct ast_rtc *ast_rtc = dev_get_drvdata(dev);
++ pr_debug("cmd = 0x%08x, arg = 0x%08lx\n", cmd, arg);
++
++ switch (cmd) {
++ case RTC_AIE_ON: /* alarm on */
++ {
++ rtc_write(ast_rtc->base, rtc_read(ast_rtc->base, RTC_CONTROL) | ENABLE_ALL_ALARM, RTC_CONTROL);
++ return 0;
++ }
++
++ case RTC_AIE_OFF: /* alarm off */
++ {
++ rtc_write(ast_rtc->base, rtc_read(ast_rtc->base, RTC_CONTROL) &~ENABLE_ALL_ALARM, RTC_CONTROL);
++ return 0;
++ }
++ case RTC_UIE_ON: /* update on */
++ {
++ pr_debug("no such function \n");
++ return 0;
++ }
++ case RTC_UIE_OFF: /* update off */
++ {
++ pr_debug("no such function \n");
++ return 0;
++ }
++ case RTC_PIE_OFF: /* periodic off */
++ {
++ rtc_write(ast_rtc->base, rtc_read(ast_rtc->base, RTC_CONTROL) | ENABLE_SEC_INTERRUPT, RTC_CONTROL);
++
++ return 0;
++ }
++ case RTC_PIE_ON: /* periodic on */
++ {
++ rtc_write(ast_rtc->base, rtc_read(ast_rtc->base, RTC_CONTROL) & ~ENABLE_SEC_INTERRUPT, RTC_CONTROL);
++
++ return 0;
++ }
++ default:
++ return -ENOTTY;
++ }
++
++ return 0;
++}
++
++
++/* Time read/write */
++static int
++ast_rtc_get_time(struct device *dev, struct rtc_time *rtc_tm)
++{
++ struct ast_rtc *ast_rtc = dev_get_drvdata(dev);
++ unsigned long flags;
++ u32 reg_time, reg_date;
++
++ spin_lock_irqsave(&ast_rtc->lock, flags);
++
++ reg_time = rtc_read(ast_rtc->base, RTC_CNTR_STS_1);
++ reg_date = rtc_read(ast_rtc->base, RTC_CNTR_STS_2);
++
++ spin_unlock_irqrestore(&ast_rtc->lock, flags);
++
++ rtc_tm->tm_year = GET_CENT_VAL(reg_date)*1000 | GET_YEAR_VAL(reg_date);
++ rtc_tm->tm_mon = GET_MON_VAL(reg_date);
++
++ rtc_tm->tm_mday = GET_DAY_VAL(reg_time);
++ rtc_tm->tm_hour = GET_HOUR_VAL(reg_time);
++ rtc_tm->tm_min = GET_MIN_VAL(reg_time);
++ rtc_tm->tm_sec = GET_SEC_VAL(reg_time);
++
++ pr_debug("read time %02x.%02x.%02x %02x/%02x/%02x\n",
++ rtc_tm->tm_year, rtc_tm->tm_mon, rtc_tm->tm_mday,
++ rtc_tm->tm_hour, rtc_tm->tm_min, rtc_tm->tm_sec);
++ return 0;
++
++}
++
++static int
++ast_rtc_set_time(struct device *dev, struct rtc_time *tm)
++{
++ struct ast_rtc *ast_rtc = dev_get_drvdata(dev);
++ unsigned long flags;
++ u32 reg_time, reg_date;
++
++ pr_debug("set time %02d.%02d.%02d %02d/%02d/%02d\n",
++ tm->tm_year, tm->tm_mon, tm->tm_mday,
++ tm->tm_hour, tm->tm_min, tm->tm_sec);
++
++ spin_lock_irqsave(&ast_rtc->lock, flags);
++
++ /* set hours */
++ reg_time = SET_DAY_VAL(tm->tm_mday) | SET_HOUR_VAL(tm->tm_hour) | SET_MIN_VAL(tm->tm_min) | SET_SEC_VAL(tm->tm_sec);
++
++ /* set century */
++ /* set mon */
++ reg_date = SET_CENT_VAL(tm->tm_year / 1000) | SET_YEAR_VAL(tm->tm_year % 1000) | SET_MON_VAL(tm->tm_mon);
++
++ rtc_write(ast_rtc->base, rtc_read(ast_rtc->base, RTC_CONTROL) | RTC_LOCK, RTC_CONTROL);
++
++ rtc_write(ast_rtc->base, reg_time, RTC_CNTR_STS_1);
++ rtc_write(ast_rtc->base, reg_date, RTC_CNTR_STS_2);
++
++ rtc_write(ast_rtc->base, rtc_read(ast_rtc->base, RTC_CONTROL) &~RTC_LOCK , RTC_CONTROL);
++
++ spin_unlock_irqrestore(&ast_rtc->lock, flags);
++
++ return 0;
++}
++static int
++ast_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alarm)
++{
++ struct ast_rtc *ast_rtc = dev_get_drvdata(dev);
++ unsigned long flags;
++ struct rtc_time *alm_tm = &alarm->time;
++ u32 alarm_reg;
++
++ spin_lock_irqsave(&ast_rtc->lock, flags);
++ alarm_reg = rtc_read(ast_rtc->base, RTC_ALARM);
++ spin_unlock_irqrestore(&ast_rtc->lock, flags);
++
++//DAY
++ alm_tm->tm_mday = GET_DAY_VAL(alarm_reg);
++
++//HR
++ alm_tm->tm_hour = GET_HOUR_VAL(alarm_reg);
++
++//MIN
++ alm_tm->tm_min= GET_MIN_VAL(alarm_reg);
++
++//SEC
++ alm_tm->tm_sec= GET_SEC_VAL(alarm_reg);
++
++ pr_debug("ast_rtc_read_alarm: %d, %02x %02x.%02x.%02x\n",
++ alarm->enabled,
++ alm_tm->tm_mday & 0xff, alm_tm->tm_hour & 0xff, alm_tm->tm_min & 0xff, alm_tm->tm_sec);
++
++ return 0;
++
++
++}
++
++static int
++ast_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alarm)
++{
++ struct ast_rtc *ast_rtc = dev_get_drvdata(dev);
++ struct rtc_time *tm = &alarm->time;
++ unsigned long flags;
++ u32 reg_alarm = 0;
++
++ pr_debug("ast_rtc_setalarm: %d, %02x %02x.%02x.%02x\n",
++ alarm->enabled,
++ tm->tm_mday & 0xff, tm->tm_hour & 0xff, tm->tm_min & 0xff, tm->tm_sec);
++
++//DAY
++ /* set day of week */
++ if (tm->tm_mday <= 31 && tm->tm_mday >= 1) {
++ reg_alarm |= SET_DAY_VAL(tm->tm_mday);
++ }
++
++//HR
++ /* set ten hours */
++ if (tm->tm_hour <= 23 && tm->tm_hour >= 0) {
++ reg_alarm |= SET_HOUR_VAL(tm->tm_hour);
++ }
++
++//MIN
++ /* set ten minutes */
++ if (tm->tm_min <= 59 && tm->tm_min >= 0) {
++ reg_alarm |= SET_MIN_VAL(tm->tm_min);
++ }
++
++//SEC
++ /* set ten secondss */
++ if (tm->tm_sec <= 59 && tm->tm_sec >= 0) {
++ reg_alarm |= SET_SEC_VAL(tm->tm_sec);
++ }
++
++ pr_debug("ast_rtc_set alarm reg: %x \n", reg_alarm);
++
++ spin_lock_irqsave(&ast_rtc->lock, flags);
++
++ rtc_write(ast_rtc->base, reg_alarm, RTC_ALARM);
++
++ if(alarm->enabled)
++ rtc_write(ast_rtc->base, reg_alarm, RTC_CONTROL);
++ else
++ rtc_write(ast_rtc->base, reg_alarm, RTC_CONTROL);
++
++ spin_unlock_irqrestore(&ast_rtc->lock, flags);
++ return 0;
++
++}
++static int
++ast_rtc_proc(struct device *dev, struct seq_file *seq)
++{
++ struct ast_rtc *ast_rtc = dev_get_drvdata(dev);
++ u32 ctrl_reg;
++
++ ctrl_reg = rtc_read(ast_rtc->base, RTC_CONTROL);
++
++ pr_debug("ctrl_reg = 0x%08x\n", ctrl_reg);
++
++ seq_printf(seq, "periodic_IRQ\t: %s\n",
++ (ctrl_reg & ENABLE_SEC_INTERRUPT) ? "yes" : "no" );
++
++ return 0;
++}
++
++static int
++ast_rtc_irq_set_freq(struct device *dev, int freq)
++{
++ struct ast_rtc *ast_rtc = dev_get_drvdata(dev);
++ pr_debug("freq = %d\n", freq);
++
++ spin_lock_irq(&ast_rtc->lock);
++
++ if(freq == 0)
++ rtc_write(ast_rtc->base, rtc_read(ast_rtc->base, RTC_CONTROL)&~ENABLE_SEC_INTERRUPT, RTC_CONTROL);
++ else
++ rtc_write(ast_rtc->base, rtc_read(ast_rtc->base, RTC_CONTROL)|ENABLE_SEC_INTERRUPT, RTC_CONTROL);
++
++ spin_unlock_irq(&ast_rtc->lock);
++
++ return 0;
++}
++
++static irqreturn_t
++ast_rtc_interrupt(int irq, void *dev_id)
++{
++ struct ast_rtc *ast_rtc = dev_id;
++
++ unsigned int status = rtc_read(ast_rtc->base, RTC_ALARM_STS);
++ rtc_write(ast_rtc->base, status, RTC_ALARM_STS);
++
++ if (status & SEC_INTERRUPT_STATUS) {
++ printk("RTC Alarm SEC_INTERRUPT_STATUS!!\n");
++ }
++
++ if (status & DAY_ALARM_STATUS) {
++ printk("RTC Alarm DAY_ALARM_STATUS!!\n");
++ }
++
++ if (status & HOUR_ALARM_STATUS) {
++ printk("RTC Alarm HOUR_ALARM_STATUS!!\n");
++ }
++
++ if (status & MIN_ALARM_STATUS) {
++ printk("RTC Alarm MIN_ALARM_STATUS!!\n");
++ }
++
++ if (status & SEC_ALARM_STATUS) {
++ printk("RTC Alarm SEC_ALARM_STATUS!!\n");
++ }
++
++ rtc_update_irq(ast_rtc->rtc_dev, 1, RTC_AF | RTC_IRQF);
++
++ return (IRQ_HANDLED);
++}
++
++static struct rtc_class_ops ast_rtcops = {
++ .ioctl = ast_rtc_ioctl,
++ .read_time = ast_rtc_get_time,
++ .set_time = ast_rtc_set_time,
++ .read_alarm = ast_rtc_read_alarm,
++ .set_alarm = ast_rtc_set_alarm,
++ .proc = ast_rtc_proc,
++ .irq_set_freq = ast_rtc_irq_set_freq,
++};
++
++/*
++ * Initialize and install RTC driver
++ */
++static int __init ast_rtc_probe(struct platform_device *pdev)
++{
++ struct ast_rtc *ast_rtc;
++ struct rtc_device *rtc_dev;
++ struct resource *res;
++ int ret;
++
++ pr_debug("%s: probe=%p\n", __func__, pdev);
++
++ ast_rtc = kzalloc(sizeof *ast_rtc, GFP_KERNEL);
++ if (!ast_rtc)
++ return -ENOMEM;
++
++ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
++ if (!res) {
++ dev_err(&pdev->dev, "register resources unusable\n");
++ ret = -ENXIO;
++ goto free_rtc;
++ }
++
++ ast_rtc->irq = platform_get_irq(pdev, 0);
++ if (ast_rtc->irq < 0) {
++ dev_err(&pdev->dev, "unable to get irq\n");
++ ret = -ENXIO;
++ goto free_rtc;
++ }
++
++ if (!request_mem_region(res->start, resource_size(res), pdev->name)) {
++ ret = -EBUSY;
++ goto free_rtc;
++ }
++
++ ast_rtc->base = ioremap(res->start, resource_size(res));
++ if (!ast_rtc->base) {
++ dev_err(&pdev->dev, "cannot map SocleDev registers\n");
++ ret = -ENOMEM;
++ goto release_mem;
++ }
++
++ pr_debug("base = 0x%p, irq = %d\n", ast_rtc->base, ast_rtc->irq);
++
++ rtc_dev = rtc_device_register(pdev->name, &pdev->dev, &ast_rtcops, THIS_MODULE);
++ if (IS_ERR(rtc_dev)) {
++ ret = PTR_ERR(rtc_dev);
++ goto unmap;
++ }
++
++ ast_rtc->res = res;
++ ast_rtc->rtc_dev = rtc_dev;
++ spin_lock_init(&ast_rtc->lock);
++
++ platform_set_drvdata(pdev, ast_rtc);
++
++// ast_rtc_irq_set_freq(&pdev->dev, 1);
++
++ /* start the RTC from dddd:hh:mm:ss = 0000:00:00:00 */
++ spin_lock_irq(&ast_rtc->lock);
++ if(!(rtc_read(ast_rtc->base, RTC_CONTROL) & RTC_ENABLE)) {
++ //combination mode
++ rtc_write(ast_rtc->base, ALARM_MODE_SELECT | RTC_LOCK | RTC_ENABLE, RTC_CONTROL);
++
++ rtc_write(ast_rtc->base, 0, RTC_CNTR_STS_1);
++
++ rtc_write(ast_rtc->base, 0, RTC_CNTR_STS_2);
++
++ rtc_write(ast_rtc->base, 0, RTC_ALARM);
++ rtc_write(ast_rtc->base, ~RTC_LOCK & rtc_read(ast_rtc->base, RTC_CONTROL), RTC_CONTROL);
++ } else
++ printk("no need to enable RTC \n");
++
++ spin_unlock_irq(&ast_rtc->lock);
++
++ /* register ISR */
++ ret = request_irq(ast_rtc->irq, ast_rtc_interrupt, IRQF_DISABLED, dev_name(&rtc_dev->dev), ast_rtc);
++ if (ret) {
++ printk(KERN_ERR "ast_rtc: IRQ %d already in use.\n",
++ ast_rtc->irq);
++ goto unregister;
++ }
++
++ return 0;
++
++unregister:
++ rtc_device_unregister(rtc_dev);
++ platform_set_drvdata(pdev, NULL);
++unmap:
++ iounmap(ast_rtc->base);
++release_mem:
++ release_mem_region(res->start, resource_size(res));
++free_rtc:
++ kfree(ast_rtc);
++ return ret;
++
++}
++
++/*
++ * Disable and remove the RTC driver
++ */
++static int __exit ast_rtc_remove(struct platform_device *pdev)
++{
++ struct ast_rtc *ast_rtc = platform_get_drvdata(pdev);
++
++ free_irq(IRQ_RTC, pdev);
++ rtc_device_unregister(ast_rtc->rtc_dev);
++ platform_set_drvdata(pdev, NULL);
++ iounmap(ast_rtc->base);
++ release_resource(ast_rtc->res);
++ kfree(ast_rtc);
++
++ return 0;
++}
++
++#ifdef CONFIG_PM
++
++/* ASPEED RTC Power management control */
++static int ast_rtc_suspend(struct platform_device *pdev, pm_message_t state)
++{
++ return 0;
++}
++
++static int ast_rtc_resume(struct platform_device *pdev)
++{
++ return 0;
++}
++#else
++#define ast_rtc_suspend NULL
++#define ast_rtc_resume NULL
++#endif
++
++static struct platform_driver ast_rtc_driver = {
++ .probe = ast_rtc_probe,
++ .remove = __exit_p(ast_rtc_remove),
++ .suspend = ast_rtc_suspend,
++ .resume = ast_rtc_resume,
++ .driver = {
++ .name = "ast_rtc",
++ .owner = THIS_MODULE,
++ },
++};
++
++static int __init ast_rtc_init(void)
++{
++ return platform_driver_register(&ast_rtc_driver);
++}
++
++static void __exit ast_rtc_exit(void)
++{
++ platform_driver_unregister(&ast_rtc_driver);
++}
++
++module_init(ast_rtc_init);
++module_exit(ast_rtc_exit);
++
++MODULE_AUTHOR("Ryan Chen");
++MODULE_DESCRIPTION("RTC driver for ASPEED AST ");
++MODULE_LICENSE("GPL");
++MODULE_ALIAS("platform:ast_rtc");
++
+diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig
+index 579d63a..5666583 100644
+--- a/drivers/serial/Kconfig
++++ b/drivers/serial/Kconfig
+@@ -137,6 +137,34 @@ config SERIAL_8250_RUNTIME_UARTS
+ with the module parameter "nr_uarts", or boot-time parameter
+ 8250.nr_uarts
+
++config SERIAL_AST_DMA_UART
++ tristate "AST UART driver with DMA"
++ depends on ARCH_ASPEED
++ select SERIAL_CORE
++ help
++ The ASPEED UART driver with DMA supporting. The device node is /dev/ttyDMA
++
++config AST_NR_DMA_UARTS
++ int "Maximum number of ast1070 uart dma serial ports"
++ depends on SERIAL_AST_DMA_UART
++ default "4"
++ help
++ Set this to the number of serial ports you want the driver
++ to support. This includes any ports discovered via ACPI or
++ PCI enumeration and any ports that may be added at run-time
++ via hot-plug, or any ISA multi-port serial cards.
++
++config AST_RUNTIME_DMA_UARTS
++ int "Number of ast1070 uart dma serial ports to register at runtime"
++ depends on SERIAL_AST_DMA_UART
++ range 0 AST_NR_DMA_UARTS
++ default "4"
++ help
++ Set this to the maximum number of serial ports you want
++ the kernel to register at boot time. This can be overridden
++ with the module parameter "nr_uarts", or boot-time parameter
++ 8250.nr_uarts
++
+ config SERIAL_8250_EXTENDED
+ bool "Extended 8250/16550 serial driver options"
+ depends on SERIAL_8250
+@@ -510,6 +538,39 @@ config SERIAL_S3C2440
+
+
+
++config SERIAL_AST
++ tristate "ASPEED serial port support"
++ depends on ARCH_ASPEED
++ select SERIAL_CORE
++ help
++ Support for the on-chip UARTs on the ASPEED chips,
++ providing /dev/ttySAC0, 1 and 2 (note, some machines may not
++ provide all of these ports, depending on how the serial port
++ pins are configured.
++
++config SERIAL_ASPEED_CONSOLE
++ bool "Support for console on ASPEED serial port"
++ depends on SERIAL_AST=y
++ select SERIAL_CORE_CONSOLE
++ help
++ Allow selection of the ASPEED on-board serial ports for use as
++ an virtual console.
++
++ Even if you say Y here, the currently visible virtual console
++ (/dev/ttyS0) will still be used as the system console by default, but
++ you can alter that using a kernel command line option such as
++ "console=ttySx". (Try "man bootparam" or see the documentation of
++ your boot loader about how to pass options to the kernel at
++ boot time.)
++
++config SERIAL_ASPEED_CONSOLE_BAUD
++ int "ASPEED serial port baud"
++ depends on SERIAL_ASPEED_CONSOLE=y
++ default "115200"
++ help
++ Select the ASPEED console baud rate.
++ This value is only used if the bootloader doesn't pass in the
++
+ config SERIAL_DZ
+ bool "DECstation DZ serial driver"
+ depends on MACH_DECSTATION && 32BIT
+diff --git a/drivers/serial/Makefile b/drivers/serial/Makefile
+index 0c17c8d..9a0059f 100644
+--- a/drivers/serial/Makefile
++++ b/drivers/serial/Makefile
+@@ -19,6 +19,7 @@ obj-$(CONFIG_SERIAL_8250_PNP) += 8250_pnp.o
+ obj-$(CONFIG_SERIAL_8250_GSC) += 8250_gsc.o
+ obj-$(CONFIG_SERIAL_8250_PCI) += 8250_pci.o
+ obj-$(CONFIG_SERIAL_8250_HP300) += 8250_hp300.o
++obj-$(CONFIG_SERIAL_AST) += ast_serial.o
+ obj-$(CONFIG_SERIAL_8250_CS) += serial_cs.o
+ obj-$(CONFIG_SERIAL_8250_ACORN) += 8250_acorn.o
+ obj-$(CONFIG_SERIAL_8250_CONSOLE) += 8250_early.o
+@@ -28,6 +29,7 @@ obj-$(CONFIG_SERIAL_8250_BOCA) += 8250_boca.o
+ obj-$(CONFIG_SERIAL_8250_EXAR_ST16C554) += 8250_exar_st16c554.o
+ obj-$(CONFIG_SERIAL_8250_HUB6) += 8250_hub6.o
+ obj-$(CONFIG_SERIAL_8250_MCA) += 8250_mca.o
++obj-$(CONFIG_SERIAL_AST_DMA_UART) += ast1070_dma_uart.o
+ obj-$(CONFIG_SERIAL_AMBA_PL010) += amba-pl010.o
+ obj-$(CONFIG_SERIAL_AMBA_PL011) += amba-pl011.o
+ obj-$(CONFIG_SERIAL_CLPS711X) += clps711x.o
+diff --git a/drivers/serial/ast1070_dma_uart.c b/drivers/serial/ast1070_dma_uart.c
+new file mode 100644
+index 0000000..16eb3c5
+--- /dev/null
++++ b/drivers/serial/ast1070_dma_uart.c
+@@ -0,0 +1,1511 @@
++/********************************************************************************
++* File Name : ast1070_dma_uart.c
++*
++* Copyright (C) 2012-2020 ASPEED Technology Inc.
++* This program is free software; you can redistribute it and/or modify
++* it under the terms of the GNU General Public License as published by the Free Software Foundation;
++* either version 2 of the License, or (at your option) any later version.
++* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
++* without even the implied warranty of MERCHANTABILITY or
++* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
++* You should have received a copy of the GNU General Public License
++* along with this program; if not, write to the Free Software
++* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++********************************************************************************/
++
++#include <linux/module.h>
++#include <linux/moduleparam.h>
++#include <linux/ioport.h>
++#include <linux/init.h>
++#include <linux/console.h>
++#include <linux/delay.h>
++#include <linux/platform_device.h>
++#include <linux/tty.h>
++#include <linux/tty_flip.h>
++#include <linux/serial_reg.h>
++#include <linux/serial_core.h>
++#include <linux/serial.h>
++#include <linux/serial_8250.h>
++#include <linux/nmi.h>
++#include <linux/mutex.h>
++
++#include <asm/io.h>
++#include <asm/irq.h>
++
++#include "8250.h"
++#include <linux/dma-mapping.h>
++#include <linux/miscdevice.h>
++#include <plat/regs-uart-dma.h>
++#include <mach/ast-uart-dma.h>
++
++//#define CONFIG_UART_DMA_DEBUG
++
++#ifdef CONFIG_UART_DMA_DEBUG
++ #define DBG(fmt, args...) printk("%s() " fmt, __FUNCTION__, ## args)
++#else
++ #define DBG(fmt, args...)
++#endif
++
++/*
++ * Configuration:
++ * share_irqs - whether we pass IRQF_SHARED to request_irq(). This option
++ * is unsafe when used on edge-triggered interrupts.
++ */
++static unsigned int share_irqs = SERIAL8250_SHARE_IRQS;
++
++static unsigned int nr_uarts = CONFIG_AST_RUNTIME_DMA_UARTS;
++
++/*
++ * Debugging.
++ */
++#if 0
++#define DEBUG_AUTOCONF(fmt...) printk(fmt)
++#else
++#define DEBUG_AUTOCONF(fmt...) do { } while (0)
++#endif
++
++#if 0
++#define DEBUG_INTR(fmt...) printk(fmt)
++#else
++#define DEBUG_INTR(fmt...) do { } while (0)
++#endif
++
++#define PASS_LIMIT 256
++
++#include <asm/serial.h>
++
++
++#define UART_DMA_NR CONFIG_AST_NR_DMA_UARTS
++
++struct ast_uart_port {
++ struct uart_port port;
++ unsigned short capabilities; /* port capabilities */
++ unsigned short bugs; /* port bugs */
++ unsigned int tx_loadsz; /* transmit fifo load size */
++ unsigned char acr;
++ unsigned char ier;
++ unsigned char lcr;
++ unsigned char mcr;
++ unsigned char mcr_mask; /* mask of user bits */
++ unsigned char mcr_force; /* mask of forced bits */
++ struct circ_buf rx_dma_buf;
++ struct circ_buf tx_dma_buf;
++ dma_addr_t dma_rx_addr; /* Mapped ADMA descr. table */
++ dma_addr_t dma_tx_addr; /* Mapped ADMA descr. table */
++ unsigned int dma_buf_size; //total allocation dma size ..
++ struct tasklet_struct rx_tasklet;
++ int rx_tasklet_done;
++ struct tasklet_struct tx_tasklet;
++ spinlock_t lock;
++ int tx_done;
++ int tx_count;
++ /*
++ * Some bits in registers are cleared on a read, so they must
++ * be saved whenever the register is read but the bits will not
++ * be immediately processed.
++ */
++#define LSR_SAVE_FLAGS UART_LSR_BRK_ERROR_BITS
++ unsigned char lsr_saved_flags;
++#define MSR_SAVE_FLAGS UART_MSR_ANY_DELTA
++ unsigned char msr_saved_flags;
++
++ /*
++ * We provide a per-port pm hook.
++ */
++ void (*pm)(struct uart_port *port,
++ unsigned int state, unsigned int old);
++};
++
++static struct ast_uart_port ast_uart_ports[UART_DMA_NR];
++
++static inline struct ast_uart_port *
++to_ast_dma_uart_port(struct uart_port *uart)
++{
++ return container_of(uart, struct ast_uart_port, port);
++}
++
++struct irq_info {
++ spinlock_t lock;
++ struct ast_uart_port *up;
++};
++
++static struct irq_info ast_uart_irq[1];
++static DEFINE_MUTEX(ast_uart_mutex);
++
++/*
++ * Here we define the default xmit fifo size used for each type of UART.
++ */
++static const struct serial8250_config uart_config[] = {
++ [PORT_UNKNOWN] = {
++ .name = "unknown",
++ .fifo_size = 1,
++ .tx_loadsz = 1,
++ },
++ [PORT_8250] = {
++ .name = "8250",
++ .fifo_size = 1,
++ .tx_loadsz = 1,
++ },
++ [PORT_16450] = {
++ .name = "16450",
++ .fifo_size = 1,
++ .tx_loadsz = 1,
++ },
++ [PORT_16550] = {
++ .name = "16550",
++ .fifo_size = 1,
++ .tx_loadsz = 1,
++ },
++ [PORT_16550A] = {
++ .name = "16550A",
++ .fifo_size = 16,
++ .tx_loadsz = 16,
++ .fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10 | UART_FCR_DMA_SELECT,
++ .flags = UART_CAP_FIFO,
++ },
++};
++
++/* sane hardware needs no mapping */
++#define map_8250_in_reg(up, offset) (offset)
++#define map_8250_out_reg(up, offset) (offset)
++
++void ast_uart_unregister_port(int line);
++int ast_uart_register_port(struct uart_port *port);
++
++static unsigned int serial_in(struct ast_uart_port *up, int offset)
++{
++ offset = map_8250_in_reg(up, offset) << up->port.regshift;
++
++ return readb(up->port.membase + offset);
++}
++
++static void
++serial_out(struct ast_uart_port *up, int offset, int value)
++{
++ /* Save the offset before it's remapped */
++ offset = map_8250_out_reg(up, offset) << up->port.regshift;
++
++ writeb(value, up->port.membase + offset);
++}
++
++
++/*
++ * We used to support using pause I/O for certain machines. We
++ * haven't supported this for a while, but just in case it's badly
++ * needed for certain old 386 machines, I've left these #define's
++ * in....
++ */
++#define serial_inp(up, offset) serial_in(up, offset)
++#define serial_outp(up, offset, value) serial_out(up, offset, value)
++
++/* Uart divisor latch read */
++static inline int _serial_dl_read(struct ast_uart_port *up)
++{
++ return serial_inp(up, UART_DLL) | serial_inp(up, UART_DLM) << 8;
++}
++
++/* Uart divisor latch write */
++static inline void _serial_dl_write(struct ast_uart_port *up, int value)
++{
++ serial_outp(up, UART_DLL, value & 0xff);
++ serial_outp(up, UART_DLM, value >> 8 & 0xff);
++}
++
++#define serial_dl_read(up) _serial_dl_read(up)
++#define serial_dl_write(up, value) _serial_dl_write(up, value)
++
++static void ast_uart_tx_tasklet_func(unsigned long data)
++{
++ struct ast_uart_port *up = to_ast_dma_uart_port((struct uart_port *)data);
++ struct circ_buf *xmit = &up->port.info->xmit;
++ struct ast_uart_dma_data *uart_dma_data = up->port.private_data;
++
++ up->tx_done = 0;
++ DBG("line [%d], xmit->head =%d, xmit->tail = %d\n",up->port.line,xmit->head, xmit->tail);
++
++ if (uart_circ_empty(xmit) || uart_tx_stopped(&up->port)) {
++ up->tx_count = 0;
++ up->tx_done = 1;
++ return;
++ }
++
++ if (up->port.x_char) {
++ serial_outp(up, UART_TX, up->port.x_char);
++ up->port.icount.tx++;
++ up->port.x_char = 0;
++ return;
++ }
++
++ up->tx_count = CIRC_CNT(xmit->head, xmit->tail, UART_XMIT_SIZE);
++
++ if (up->tx_count > (UART_XMIT_SIZE - xmit->tail)) {
++ up->tx_count = UART_XMIT_SIZE - xmit->tail;
++ }
++
++ if (up->tx_count > 4095) {
++ printk("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! TODO ....\n");
++ up->tx_count = 4095;
++ }
++
++ ast_uart_tx_dma_ctrl(uart_dma_data->chip_no,
++ uart_dma_data->dma_ch, AST_UART_DMAOP_STOP);
++
++ ast_uart_tx_dma_enqueue(uart_dma_data->chip_no,
++ uart_dma_data->dma_ch, up->dma_tx_addr, up->tx_count);
++
++ dma_sync_single_for_device(up->port.dev,
++ up->dma_tx_addr,
++ up->tx_count,
++ DMA_TO_DEVICE);
++
++ ast_uart_tx_dma_ctrl(uart_dma_data->chip_no,
++ uart_dma_data->dma_ch, AST_UART_DMAOP_TRIGGER);
++
++
++}
++
++static void ast_uart_tx_buffdone(struct ast1070_dma_ch *dma_ch, void *dev_id, u16 len)
++{
++ struct ast_uart_port *up = (struct ast_uart_port *) dev_id;
++ struct circ_buf *xmit = &up->port.info->xmit;
++
++ DBG("line [%d] : tx len = %d \n", up->port.line, len);
++
++ spin_lock(&up->port.lock);
++//TODO .....................................len ---->
++ xmit->tail = (xmit->tail + up->tx_count) & (UART_XMIT_SIZE - 1);
++ up->port.icount.tx += up->tx_count;
++
++ if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
++ uart_write_wakeup(&up->port);
++
++ tasklet_schedule(&up->tx_tasklet);
++
++ spin_unlock(&up->port.lock);
++}
++
++static void ast_uart_rx_tasklet_func(unsigned long data)
++{
++ struct ast_uart_port *up = to_ast_dma_uart_port((struct uart_port *)data);
++ struct circ_buf *rx_ring = &up->rx_dma_buf;
++ struct tty_struct *tty = up->port.info->port.tty;
++ char flag;
++ DBG("line [%d]\n",up->port.line);
++ DBG("rx_ring->head = %d, rx_ring->tail = %d , buff addr = %x \n",rx_ring->head, rx_ring->tail, rx_ring->buf);
++
++ spin_lock_irq(&up->lock);
++#if 1
++ DBG("\n rx data : -- >");
++
++ while (rx_ring->head != rx_ring->tail) {
++ DBG(" %x ",rx_ring->buf[rx_ring->tail]);
++ flag = TTY_NORMAL;
++ uart_insert_char(&up->port, 0, UART_LSR_OE, \
++ rx_ring->buf[rx_ring->tail], flag);
++
++// tty_insert_flip_string
++
++ rx_ring->tail++;
++ if (rx_ring->tail == up->dma_buf_size)
++ rx_ring->tail = 0;
++ }
++ DBG("\n");
++#else
++
++ tty_insert_flip_string(tty, rx_ring->buf + rx_ring->tail, (rx_ring->head - rx_ring->tail));
++ rx_ring->tail = rx_ring->head;
++#endif
++ spin_unlock_irq(&up->lock);
++
++ spin_unlock(&up->port.lock);
++ tty_flip_buffer_push(tty);
++ spin_lock(&up->port.lock);
++
++
++}
++
++static void ast_uart_rx_buffdone(struct ast1070_dma_ch *dma_ch,
++ void *dev_id, u16 len)
++{
++ struct ast_uart_port *up = (struct ast_uart_port *)dev_id;
++// struct tty_struct *tty = up->port.info->port.tty;
++ struct circ_buf *rx_ring = &up->rx_dma_buf;
++ struct ast_uart_dma_data *uart_dma_data = up->port.private_data;
++ u16 remain_size;
++
++ DBG("line [%d]\n",up->port.line);
++#if 0
++ int i;
++ printk("Buff virt addr = %x \n",rx_ring->buf);
++ for(i=0;i<len;i++)
++ printk("Buff [%x] \n", rx_ring->buf[up->rx_dma_buf.head + i]);
++#endif
++ DBG("head = %d, len : %d\n",up->rx_dma_buf.head, len);
++
++
++ //FOR NEXT ......
++ rx_ring->head += len;
++
++ if (rx_ring->head == up->dma_buf_size) {
++ rx_ring->head = 0;
++ }
++
++ remain_size = up->dma_buf_size - rx_ring->head;
++
++ //Trigger Next RX dma
++ DBG("trigger next size = %d \n",remain_size);
++
++ ast_uart_rx_dma_ctrl(uart_dma_data->chip_no,
++ uart_dma_data->dma_ch, AST_UART_DMAOP_STOP);
++
++ if(remain_size > DMA_BUFF_SIZE)
++ printk("Please check ---> \n");
++
++ if(remain_size != 0) {
++ ast_uart_rx_dma_enqueue(uart_dma_data->chip_no,
++ uart_dma_data->dma_ch, up->dma_rx_addr + up->rx_dma_buf.head, remain_size);
++ }
++ ast_uart_rx_dma_ctrl(uart_dma_data->chip_no,
++ uart_dma_data->dma_ch, AST_UART_DMAOP_TRIGGER);
++
++ tasklet_schedule(&up->rx_tasklet);
++
++}
++
++/*
++ * FIFO support.
++ */
++static inline void serial8250_clear_fifos(struct ast_uart_port *p)
++{
++ serial_outp(p, UART_FCR, UART_FCR_ENABLE_FIFO);
++ serial_outp(p, UART_FCR, UART_FCR_ENABLE_FIFO |
++ UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT);
++ serial_outp(p, UART_FCR, 0);
++}
++
++
++/*
++ * This routine is called by rs_init() to initialize a specific serial
++ * port.
++ */
++static void autoconfig(struct ast_uart_port *up, unsigned int probeflags)
++{
++ unsigned long flags;
++
++ if (!up->port.iobase && !up->port.mapbase && !up->port.membase)
++ return;
++
++ DEBUG_AUTOCONF("ttyDMA%d: autoconf (0x%04x, 0x%p): ",
++ up->port.line, up->port.iobase, up->port.membase);
++
++ spin_lock_irqsave(&up->port.lock, flags);
++
++ up->capabilities = 0;
++ up->bugs = 0;
++
++ up->port.type = PORT_16550A;
++ up->capabilities |= UART_CAP_FIFO;
++
++ up->port.fifosize = uart_config[up->port.type].fifo_size;
++ up->capabilities = uart_config[up->port.type].flags;
++ up->tx_loadsz = uart_config[up->port.type].tx_loadsz;
++
++ if (up->port.type == PORT_UNKNOWN)
++ goto out;
++
++ /*
++ * Reset the UART.
++ */
++ serial8250_clear_fifos(up);
++ serial_in(up, UART_RX);
++ serial_outp(up, UART_IER, 0);
++
++ out:
++ spin_unlock_irqrestore(&up->port.lock, flags);
++ DEBUG_AUTOCONF("type=%s\n", uart_config[up->port.type].name);
++}
++
++
++static inline void __stop_tx(struct ast_uart_port *p)
++{
++ if (p->ier & UART_IER_THRI) {
++ p->ier &= ~UART_IER_THRI;
++ serial_out(p, UART_IER, p->ier);
++ }
++}
++
++static void serial8250_stop_tx(struct uart_port *port)
++{
++ struct ast_uart_port *up = to_ast_dma_uart_port(port);
++
++ __stop_tx(up);
++
++}
++
++static void transmit_chars(struct ast_uart_port *up);
++
++static void serial8250_start_tx(struct uart_port *port)
++{
++ struct ast_uart_port *up = to_ast_dma_uart_port(port);
++
++ DBG("line [%d] --> \n", port->line);
++ if (up->tx_done)
++ tasklet_schedule(&up->tx_tasklet);
++}
++
++static void serial8250_stop_rx(struct uart_port *port)
++{
++ struct ast_uart_port *up = to_ast_dma_uart_port(port);
++
++ DBG("line [%d] --> \n", port->line);
++ up->ier &= ~UART_IER_RLSI;
++ up->port.read_status_mask &= ~UART_LSR_DR;
++ serial_out(up, UART_IER, up->ier);
++}
++
++static void serial8250_enable_ms(struct uart_port *port)
++{
++ struct ast_uart_port *up = to_ast_dma_uart_port(port);
++
++ up->ier |= UART_IER_MSI;
++ serial_out(up, UART_IER, up->ier);
++}
++
++static void transmit_chars(struct ast_uart_port *up)
++{
++ struct circ_buf *xmit = &up->port.info->xmit;
++ int count;
++
++ if (up->port.x_char) {
++ serial_outp(up, UART_TX, up->port.x_char);
++ up->port.icount.tx++;
++ up->port.x_char = 0;
++ return;
++ }
++ if (uart_tx_stopped(&up->port)) {
++ serial8250_stop_tx(&up->port);
++ return;
++ }
++ if (uart_circ_empty(xmit)) {
++ __stop_tx(up);
++ return;
++ }
++
++// printk("uart_circ_chars_pending=%d\n",uart_circ_chars_pending(xmit));
++
++ count = up->tx_loadsz;
++ do {
++//printk("TX : buf = 0x%x\n", xmit->buf[xmit->tail]);
++ serial_out(up, UART_TX, xmit->buf[xmit->tail]);
++ xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
++ up->port.icount.tx++;
++ if (uart_circ_empty(xmit))
++ break;
++ } while (--count > 0);
++
++ if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
++ uart_write_wakeup(&up->port);
++
++ DEBUG_INTR("THRE...");
++
++ if (uart_circ_empty(xmit))
++ __stop_tx(up);
++}
++
++static unsigned int check_modem_status(struct ast_uart_port *up)
++{
++ unsigned int status = serial_in(up, UART_MSR);
++
++ status |= up->msr_saved_flags;
++ up->msr_saved_flags = 0;
++ if (status & UART_MSR_ANY_DELTA && up->ier & UART_IER_MSI &&
++ up->port.info != NULL) {
++ if (status & UART_MSR_TERI)
++ up->port.icount.rng++;
++ if (status & UART_MSR_DDSR)
++ up->port.icount.dsr++;
++ if (status & UART_MSR_DDCD)
++ uart_handle_dcd_change(&up->port, status & UART_MSR_DCD);
++ if (status & UART_MSR_DCTS)
++ uart_handle_cts_change(&up->port, status & UART_MSR_CTS);
++
++ wake_up_interruptible(&up->port.info->delta_msr_wait);
++ }
++
++ return status;
++}
++
++/*
++ * This handles the interrupt from one port.
++ */
++static inline void
++serial8250_handle_port(struct ast_uart_port *up)
++{
++ unsigned int status;
++ unsigned long flags;
++
++ spin_lock_irqsave(&up->port.lock, flags);
++ DEBUG_INTR("serial8250_handle_port \n");
++
++ status = serial_inp(up, UART_LSR);
++
++ DEBUG_INTR("status = %x...", status);
++
++ check_modem_status(up);
++ if (status & UART_LSR_THRE)
++ transmit_chars(up);
++
++ spin_unlock_irqrestore(&up->port.lock, flags);
++}
++
++/*
++ * This is the serial driver's interrupt routine.
++ */
++static irqreturn_t ast_uart_interrupt(int irq, void *dev_id)
++{
++ struct irq_info *i = dev_id;
++ int pass_counter = 0, handled = 0, end = 0;
++
++ DEBUG_INTR("ast_uart_interrupt(%d)...", irq);
++ spin_lock(&i->lock);
++
++ do {
++ struct ast_uart_port *up;
++ unsigned int iir;
++
++ up = (struct ast_uart_port *)(i->up);
++
++ iir = serial_in(up, UART_IIR);
++ DEBUG_INTR("iir %x \n", iir);
++ if (!(iir & UART_IIR_NO_INT)) {
++ printk("handle port \n");
++ serial8250_handle_port(up);
++ handled = 1;
++
++ }
++ else
++ end = 1;
++
++ if (pass_counter++ > PASS_LIMIT) {
++ /* If we hit this, we're dead. */
++ printk(KERN_ERR "ast-uart-dma: too much work for "
++ "irq%d\n", irq);
++ break;
++ }
++ } while (end);
++
++ spin_unlock(&i->lock);
++
++ DEBUG_INTR("end.\n");
++
++ return IRQ_RETVAL(handled);
++}
++
++static unsigned int serial8250_tx_empty(struct uart_port *port)
++{
++ struct ast_uart_port *up = to_ast_dma_uart_port(port);
++ unsigned long flags;
++ unsigned int lsr;
++
++ spin_lock_irqsave(&up->port.lock, flags);
++ lsr = serial_in(up, UART_LSR);
++ up->lsr_saved_flags |= lsr & LSR_SAVE_FLAGS;
++ spin_unlock_irqrestore(&up->port.lock, flags);
++
++ return lsr & UART_LSR_TEMT ? TIOCSER_TEMT : 0;
++}
++
++static unsigned int serial8250_get_mctrl(struct uart_port *port)
++{
++ struct ast_uart_port *up = to_ast_dma_uart_port(port);
++ unsigned int status;
++ unsigned int ret;
++
++ status = check_modem_status(up);
++
++ ret = 0;
++ if (status & UART_MSR_DCD)
++ ret |= TIOCM_CAR;
++ if (status & UART_MSR_RI)
++ ret |= TIOCM_RNG;
++ if (status & UART_MSR_DSR)
++ ret |= TIOCM_DSR;
++ if (status & UART_MSR_CTS)
++ ret |= TIOCM_CTS;
++ return ret;
++}
++
++static void serial8250_set_mctrl(struct uart_port *port, unsigned int mctrl)
++{
++ struct ast_uart_port *up = to_ast_dma_uart_port(port);
++ unsigned char mcr = 0;
++
++ if (mctrl & TIOCM_RTS)
++ mcr |= UART_MCR_RTS;
++ if (mctrl & TIOCM_DTR)
++ mcr |= UART_MCR_DTR;
++ if (mctrl & TIOCM_OUT1)
++ mcr |= UART_MCR_OUT1;
++ if (mctrl & TIOCM_OUT2)
++ mcr |= UART_MCR_OUT2;
++ if (mctrl & TIOCM_LOOP)
++ mcr |= UART_MCR_LOOP;
++
++ mcr = (mcr & up->mcr_mask) | up->mcr_force | up->mcr;
++
++ serial_out(up, UART_MCR, mcr);
++}
++
++static void serial8250_break_ctl(struct uart_port *port, int break_state)
++{
++ struct ast_uart_port *up = to_ast_dma_uart_port(port);
++ unsigned long flags;
++
++ spin_lock_irqsave(&up->port.lock, flags);
++ if (break_state == -1)
++ up->lcr |= UART_LCR_SBC;
++ else
++ up->lcr &= ~UART_LCR_SBC;
++ serial_out(up, UART_LCR, up->lcr);
++ spin_unlock_irqrestore(&up->port.lock, flags);
++}
++
++static int serial8250_startup(struct uart_port *port)
++{
++ struct ast_uart_port *up = to_ast_dma_uart_port(port);
++ //TX DMA
++ struct circ_buf *xmit = &port->info->xmit;
++ struct ast_uart_dma_data *uart_dma_data = up->port.private_data;
++ unsigned long flags;
++ unsigned char lsr, iir;
++ int retval;
++ int irq_flags = up->port.flags & UPF_SHARE_IRQ ? IRQF_SHARED : 0;
++
++ DBG("line [%d] \n",port->line);
++
++ up->capabilities = uart_config[up->port.type].flags;
++ up->mcr = 0;
++
++ /*
++ * Clear the FIFO buffers and disable them.
++ * (they will be reenabled in set_termios())
++ */
++ serial8250_clear_fifos(up);
++
++ /*
++ * Clear the interrupt registers.
++ */
++ (void) serial_inp(up, UART_LSR);
++ (void) serial_inp(up, UART_RX);
++ (void) serial_inp(up, UART_IIR);
++ (void) serial_inp(up, UART_MSR);
++
++ ast_uart_irq[0].up = up;
++ retval = request_irq(up->port.irq, ast_uart_interrupt,
++ irq_flags, "ast-uart-dma", ast_uart_irq);
++ if (retval)
++ return retval;
++
++ /*
++ * Now, initialize the UART
++ */
++ serial_outp(up, UART_LCR, UART_LCR_WLEN8);
++
++ spin_lock_irqsave(&up->port.lock, flags);
++ up->port.mctrl |= TIOCM_OUT2;
++
++ serial8250_set_mctrl(&up->port, up->port.mctrl);
++
++ /*
++ * Do a quick test to see if we receive an
++ * interrupt when we enable the TX irq.
++ */
++ serial_outp(up, UART_IER, UART_IER_THRI);
++ lsr = serial_in(up, UART_LSR);
++ iir = serial_in(up, UART_IIR);
++ serial_outp(up, UART_IER, 0);
++
++ if (lsr & UART_LSR_TEMT && iir & UART_IIR_NO_INT) {
++ if (!(up->bugs & UART_BUG_TXEN)) {
++ up->bugs |= UART_BUG_TXEN;
++ printk("ttyDMA%d - enabling bad tx status \n",
++ port->line);
++ }
++ } else {
++ up->bugs &= ~UART_BUG_TXEN;
++ }
++
++ spin_unlock_irqrestore(&up->port.lock, flags);
++
++ /*
++ * Clear the interrupt registers again for luck, and clear the
++ * saved flags to avoid getting false values from polling
++ * routines or the previous session.
++ */
++ serial_inp(up, UART_LSR);
++ serial_inp(up, UART_RX);
++ serial_inp(up, UART_IIR);
++ serial_inp(up, UART_MSR);
++ up->lsr_saved_flags = 0;
++ up->msr_saved_flags = 0;
++
++ //RX DMA
++ up->rx_dma_buf.head = 0;
++ up->rx_dma_buf.tail = 0;
++ up->dma_buf_size = 2048;//DMA_BUFF_SIZE -1; //4096 is dma size please check
++#if 0
++ up->dma_rx_addr = dma_map_single(port->dev,
++ up->rx_dma_buf.buf,
++ up->dma_buf_size,
++ DMA_FROM_DEVICE);
++#else
++ up->rx_dma_buf.buf = (unsigned char *)dma_alloc_coherent(NULL,
++ up->dma_buf_size, &up->dma_rx_addr, GFP_KERNEL);
++#endif
++ DBG("RX buff vir = %x, phy = %x \n", up->rx_dma_buf.buf, up->dma_rx_addr);
++
++ ast_uart_rx_dma_ctrl(uart_dma_data->chip_no, uart_dma_data->dma_ch, AST_UART_DMAOP_STOP);
++
++ ast_uart_rx_dma_enqueue(uart_dma_data->chip_no, uart_dma_data->dma_ch, up->dma_rx_addr, up->dma_buf_size);
++
++ up->rx_tasklet_done = 1;
++ ast_uart_rx_dma_ctrl(uart_dma_data->chip_no, uart_dma_data->dma_ch, AST_UART_DMAOP_TRIGGER);
++
++ up->tx_dma_buf.head = 0;
++ up->tx_dma_buf.buf = xmit->buf;
++ up->dma_tx_addr = dma_map_single(port->dev,
++ up->tx_dma_buf.buf,
++ UART_XMIT_SIZE,
++ DMA_TO_DEVICE);
++ up->tx_done = 1;
++ up->tx_count = 0;
++
++ return 0;
++}
++
++static void serial8250_shutdown(struct uart_port *port)
++{
++ struct ast_uart_port *up = to_ast_dma_uart_port(port);
++ struct ast_uart_dma_data *uart_dma_data = up->port.private_data;
++ unsigned long flags;
++ //int i;
++ DBG("line [%d]\n",port->line);
++ /*
++ * Disable interrupts from this port
++ */
++#if 0
++ for(i=0; i<100; i++) {
++ printk("tx_count_table[%d] = %d\n", i, tx_count_table[i]);
++ }
++#endif
++
++ up->ier = 0;
++ serial_outp(up, UART_IER, 0);
++
++ spin_lock_irqsave(&up->port.lock, flags);
++ up->port.mctrl &= ~TIOCM_OUT2;
++
++ serial8250_set_mctrl(&up->port, up->port.mctrl);
++ spin_unlock_irqrestore(&up->port.lock, flags);
++
++ /*
++ * Disable break condition and FIFOs
++ */
++ serial_out(up, UART_LCR, serial_inp(up, UART_LCR) & ~UART_LCR_SBC);
++ serial8250_clear_fifos(up);
++
++ (void) serial_in(up, UART_RX);
++
++ ast_uart_rx_dma_ctrl(uart_dma_data->chip_no, uart_dma_data->dma_ch, AST_UART_DMAOP_STOP);
++
++ ast_uart_tx_dma_ctrl(uart_dma_data->chip_no, uart_dma_data->dma_ch, AST_UART_DMAOP_STOP);
++ //TODO .... Free ---- dma
++ DBG("free TX , RX buffer \n");
++#if 1
++ dma_unmap_single(port->dev, up->dma_rx_addr,
++ up->dma_buf_size,
++ DMA_FROM_DEVICE);
++#else
++ dma_free_coherent(port->dev, up->dma_buf_size,
++ up->rx_dma_buf.buf, up->dma_rx_addr);
++#endif
++
++ dma_unmap_single(port->dev, up->dma_tx_addr,
++ UART_XMIT_SIZE,
++ DMA_TO_DEVICE);
++
++
++ free_irq(up->port.irq, ast_uart_irq);
++
++}
++
++static unsigned int serial8250_get_divisor(struct uart_port *port, unsigned int baud)
++{
++ unsigned int quot;
++
++ quot = uart_get_divisor(port, baud);
++
++ return quot;
++}
++
++static void
++serial8250_set_termios(struct uart_port *port, struct ktermios *termios,
++ struct ktermios *old)
++{
++ struct ast_uart_port *up = to_ast_dma_uart_port(port);
++ unsigned char cval, fcr = 0;
++ unsigned long flags;
++ unsigned int baud, quot;
++
++ switch (termios->c_cflag & CSIZE) {
++ case CS5:
++ cval = UART_LCR_WLEN5;
++ break;
++ case CS6:
++ cval = UART_LCR_WLEN6;
++ break;
++ case CS7:
++ cval = UART_LCR_WLEN7;
++ break;
++ default:
++ case CS8:
++ cval = UART_LCR_WLEN8;
++ break;
++ }
++
++ if (termios->c_cflag & CSTOPB)
++ cval |= UART_LCR_STOP;
++ if (termios->c_cflag & PARENB)
++ cval |= UART_LCR_PARITY;
++ if (!(termios->c_cflag & PARODD))
++ cval |= UART_LCR_EPAR;
++#ifdef CMSPAR
++ if (termios->c_cflag & CMSPAR)
++ cval |= UART_LCR_SPAR;
++#endif
++
++ /*
++ * Ask the core to calculate the divisor for us.
++ */
++ baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk/16);
++ quot = serial8250_get_divisor(port, baud);
++
++ if (up->capabilities & UART_CAP_FIFO && up->port.fifosize > 1) {
++ if (baud < 2400)
++ fcr = UART_FCR_ENABLE_FIFO | UART_FCR_TRIGGER_1;
++ else
++ fcr = uart_config[up->port.type].fcr;
++ }
++
++ /*
++ * Ok, we're now changing the port state. Do it with
++ * interrupts disabled.
++ */
++ spin_lock_irqsave(&up->port.lock, flags);
++
++ /*
++ * Update the per-port timeout.
++ */
++ uart_update_timeout(port, termios->c_cflag, baud);
++
++ up->port.read_status_mask = UART_LSR_OE | UART_LSR_THRE | UART_LSR_DR;
++ if (termios->c_iflag & INPCK)
++ up->port.read_status_mask |= UART_LSR_FE | UART_LSR_PE;
++ if (termios->c_iflag & (BRKINT | PARMRK))
++ up->port.read_status_mask |= UART_LSR_BI;
++
++ /*
++ * Characteres to ignore
++ */
++ up->port.ignore_status_mask = 0;
++ if (termios->c_iflag & IGNPAR)
++ up->port.ignore_status_mask |= UART_LSR_PE | UART_LSR_FE;
++ if (termios->c_iflag & IGNBRK) {
++ up->port.ignore_status_mask |= UART_LSR_BI;
++ /*
++ * If we're ignoring parity and break indicators,
++ * ignore overruns too (for real raw support).
++ */
++ if (termios->c_iflag & IGNPAR)
++ up->port.ignore_status_mask |= UART_LSR_OE;
++ }
++
++ /*
++ * ignore all characters if CREAD is not set
++ */
++ if ((termios->c_cflag & CREAD) == 0)
++ up->port.ignore_status_mask |= UART_LSR_DR;
++
++ /*
++ * CTS flow control flag and modem status interrupts
++ */
++ up->ier &= ~UART_IER_MSI;
++ if (UART_ENABLE_MS(&up->port, termios->c_cflag))
++ up->ier |= UART_IER_MSI;
++
++ serial_out(up, UART_IER, up->ier);
++
++
++ serial_outp(up, UART_LCR, cval | UART_LCR_DLAB);/* set DLAB */
++
++ serial_dl_write(up, quot);
++
++ /*
++ * LCR DLAB must be set to enable 64-byte FIFO mode. If the FCR
++ * is written without DLAB set, this mode will be disabled.
++ */
++
++ serial_outp(up, UART_LCR, cval); /* reset DLAB */
++ up->lcr = cval; /* Save LCR */
++ if (fcr & UART_FCR_ENABLE_FIFO) {
++ /* emulated UARTs (Lucent Venus 167x) need two steps */
++ serial_outp(up, UART_FCR, UART_FCR_ENABLE_FIFO);
++ }
++ serial_outp(up, UART_FCR, fcr); /* set fcr */
++ serial8250_set_mctrl(&up->port, up->port.mctrl);
++ spin_unlock_irqrestore(&up->port.lock, flags);
++ /* Don't rewrite B0 */
++ if (tty_termios_baud_rate(termios))
++ tty_termios_encode_baud_rate(termios, baud, baud);
++}
++
++static void
++serial8250_pm(struct uart_port *port, unsigned int state,
++ unsigned int oldstate)
++{
++ struct ast_uart_port *p = (struct ast_uart_port *)port;
++
++ if (p->pm)
++ p->pm(port, state, oldstate);
++}
++
++/*
++ * Resource handling.
++ */
++static int serial8250_request_std_resource(struct ast_uart_port *up)
++{
++ unsigned int size = 8 << up->port.regshift;
++ int ret = 0;
++
++ if (!up->port.mapbase)
++ return ret;
++
++ if (!request_mem_region(up->port.mapbase, size, "ast-uart-dma")) {
++ ret = -EBUSY;
++ return ret;
++ }
++
++ if (up->port.flags & UPF_IOREMAP) {
++ up->port.membase = ioremap_nocache(up->port.mapbase,
++ size);
++ if (!up->port.membase) {
++ release_mem_region(up->port.mapbase, size);
++ ret = -ENOMEM;
++ return ret;
++ }
++ }
++ return ret;
++}
++
++static void serial8250_release_std_resource(struct ast_uart_port *up)
++{
++ unsigned int size = 8 << up->port.regshift;
++
++ if (!up->port.mapbase)
++ return;
++
++ if (up->port.flags & UPF_IOREMAP) {
++ iounmap(up->port.membase);
++ up->port.membase = NULL;
++ }
++
++ release_mem_region(up->port.mapbase, size);
++}
++
++
++static void serial8250_release_port(struct uart_port *port)
++{
++ struct ast_uart_port *up = (struct ast_uart_port *)port;
++
++ serial8250_release_std_resource(up);
++}
++
++static int serial8250_request_port(struct uart_port *port)
++{
++ struct ast_uart_port *up = (struct ast_uart_port *)port;
++ int ret = 0;
++
++ ret = serial8250_request_std_resource(up);
++ if (ret == 0 )
++ serial8250_release_std_resource(up);
++
++ return ret;
++}
++
++static void serial8250_config_port(struct uart_port *port, int flags)
++{
++ struct ast_uart_port *up = (struct ast_uart_port *)port;
++ int probeflags = PROBE_ANY;
++ int ret;
++
++ /*
++ * Find the region that we can probe for. This in turn
++ * tells us whether we can probe for the type of port.
++ */
++ ret = serial8250_request_std_resource(up);
++ if (ret < 0)
++ return;
++
++ if (flags & UART_CONFIG_TYPE)
++ autoconfig(up, probeflags);
++
++ if (up->port.type == PORT_UNKNOWN)
++ serial8250_release_std_resource(up);
++}
++
++static int
++serial8250_verify_port(struct uart_port *port, struct serial_struct *ser)
++{
++ return 0;
++}
++
++static const char *
++serial8250_type(struct uart_port *port)
++{
++ int type = port->type;
++
++ if (type >= ARRAY_SIZE(uart_config))
++ type = 0;
++ return uart_config[type].name;
++}
++
++static struct uart_ops serial8250_pops = {
++ .tx_empty = serial8250_tx_empty,
++ .set_mctrl = serial8250_set_mctrl,
++ .get_mctrl = serial8250_get_mctrl,
++ .stop_tx = serial8250_stop_tx,
++ .start_tx = serial8250_start_tx,
++ .stop_rx = serial8250_stop_rx,
++ .enable_ms = serial8250_enable_ms,
++ .break_ctl = serial8250_break_ctl,
++ .startup = serial8250_startup,
++ .shutdown = serial8250_shutdown,
++ .set_termios = serial8250_set_termios,
++ .pm = serial8250_pm,
++ .type = serial8250_type,
++ .release_port = serial8250_release_port,
++ .request_port = serial8250_request_port,
++ .config_port = serial8250_config_port,
++ .verify_port = serial8250_verify_port,
++};
++
++static void __init serial8250_isa_init_ports(void)
++{
++ static int first = 1;
++ int i;
++
++ if (!first)
++ return;
++ first = 0;
++
++ for (i = 0; i < nr_uarts; i++) {
++ struct ast_uart_port *up = &ast_uart_ports[i];
++
++ up->port.line = i;
++ spin_lock_init(&up->port.lock);
++
++ /*
++ * ALPHA_KLUDGE_MCR needs to be killed.
++ */
++ up->mcr_mask = ~ALPHA_KLUDGE_MCR;
++ up->mcr_force = ALPHA_KLUDGE_MCR;
++
++ up->port.ops = &serial8250_pops;
++ }
++
++}
++
++static void __init
++serial8250_register_ports(struct uart_driver *drv, struct device *dev)
++{
++ int i;
++ printk("serial8250_register_ports \n");
++
++ serial8250_isa_init_ports();
++
++ for (i = 0; i < nr_uarts; i++) {
++ struct ast_uart_port *up = &ast_uart_ports[i];
++ up->port.dev = dev;
++ uart_add_one_port(drv, &up->port);
++ }
++}
++
++#define SERIAL8250_CONSOLE NULL
++
++static struct uart_driver serial8250_reg = {
++ .owner = THIS_MODULE,
++ .driver_name = "ast-uart-dma",
++ .dev_name = "ttyDMA",
++#if 0
++ .major = TTY_MAJOR,
++ .minor = 64,
++#else
++ .major = 204, // like atmel_serial
++ .minor = 155,
++#endif
++ .nr = UART_DMA_NR,
++ .cons = SERIAL8250_CONSOLE,
++};
++
++
++#if 0
++/**
++ * serial8250_suspend_port - suspend one serial port
++ * @line: serial line number
++ *
++ * Suspend one serial port.
++ */
++void serial8250_suspend_port(int line)
++{
++ uart_suspend_port(&serial8250_reg, &ast_uart_ports[line].port);
++}
++
++/**
++ * serial8250_resume_port - resume one serial port
++ * @line: serial line number
++ *
++ * Resume one serial port.
++ */
++void serial8250_resume_port(int line)
++{
++ struct ast_uart_port *up = &ast_uart_ports[line];
++
++ uart_resume_port(&serial8250_reg, &up->port);
++}
++#endif
++
++/*
++ * Register a set of serial devices attached to a platform device. The
++ * list is terminated with a zero flags entry, which means we expect
++ * all entries to have at least UPF_BOOT_AUTOCONF set.
++ */
++static int __devinit serial8250_probe(struct platform_device *dev)
++{
++ struct plat_serial8250_port *p = dev->dev.platform_data;
++ struct uart_port port;
++ struct ast_uart_dma_data *uart_dma_data;
++ int ret, i;
++
++ if(UART_XMIT_SIZE > DMA_BUFF_SIZE)
++ printk("UART_XMIT_SIZE > DMA_BUFF_SIZE : Please Check \n");
++
++ memset(&port, 0, sizeof(struct uart_port));
++
++ for (i = 0; p && p->flags != 0; p++, i++) {
++ port.iobase = p->iobase;
++ port.membase = p->membase;
++ port.irq = p->irq;
++ port.uartclk = p->uartclk;
++ port.regshift = p->regshift;
++ port.iotype = p->iotype;
++ port.flags = p->flags;
++ port.mapbase = p->mapbase;
++ port.hub6 = p->hub6;
++ port.private_data = p->private_data;
++ port.dev = &dev->dev;
++ uart_dma_data = p->private_data;
++ if (share_irqs)
++ port.flags |= UPF_SHARE_IRQ;
++ ret = ast_uart_register_port(&port);
++ if (ret < 0) {
++ dev_err(&dev->dev, "unable to register port at index %d "
++ "(IO%lx MEM%llx IRQ%d): %d\n", i,
++ p->iobase, (unsigned long long)p->mapbase,
++ p->irq, ret);
++ }
++// printk("TODO ...... line = %d \n",i);
++ ret = ast_uart_rx_dma_request(uart_dma_data->chip_no, uart_dma_data->dma_ch, ast_uart_rx_buffdone, &ast_uart_ports[i]);
++ if (ret < 0) {
++ printk("Error : failed to get rx dma channel[%d]\n", uart_dma_data->dma_ch);
++ goto out_ast_uart_unregister_port;
++ }
++
++ ret = ast_uart_tx_dma_request(uart_dma_data->chip_no, uart_dma_data->dma_ch, ast_uart_tx_buffdone, &ast_uart_ports[i]);
++ if (ret < 0) {
++ printk("Error : failed to get tx dma channel[%d]\n", uart_dma_data->dma_ch);
++ return ret;
++ }
++ }
++
++ return 0;
++
++out_ast_uart_unregister_port:
++ for (i = 0; i < nr_uarts; i++) {
++ struct ast_uart_port *up = &ast_uart_ports[i];
++
++ if (up->port.dev == &dev->dev)
++ ast_uart_unregister_port(i);
++ };
++ return ret;
++
++}
++
++/*
++ * Remove serial ports registered against a platform device.
++ */
++static int __devexit serial8250_remove(struct platform_device *dev)
++{
++ int i;
++
++ for (i = 0; i < nr_uarts; i++) {
++ struct ast_uart_port *up = &ast_uart_ports[i];
++
++ if (up->port.dev == &dev->dev)
++ ast_uart_unregister_port(i);
++ }
++ //TODO ..
++// pl080_dma_free(uart_dma_rx.channel, (void *)uart_dma_rx.client);
++// pl080_dma_free(uart_dma_tx.channel, (void *)uart_dma_tx.client);
++
++ return 0;
++}
++
++static int serial8250_suspend(struct platform_device *dev, pm_message_t state)
++{
++ int i;
++
++ for (i = 0; i < UART_DMA_NR; i++) {
++ struct ast_uart_port *up = &ast_uart_ports[i];
++
++ if (up->port.type != PORT_UNKNOWN && up->port.dev == &dev->dev)
++ uart_suspend_port(&serial8250_reg, &up->port);
++ }
++
++ return 0;
++}
++
++static int serial8250_resume(struct platform_device *dev)
++{
++ int i;
++
++ for (i = 0; i < UART_DMA_NR; i++) {
++ struct ast_uart_port *up = &ast_uart_ports[i];
++
++ if (up->port.type != PORT_UNKNOWN && up->port.dev == &dev->dev)
++ serial8250_resume_port(i);
++ }
++
++ return 0;
++}
++
++static struct platform_driver serial8250_ast_dma_driver = {
++ .probe = serial8250_probe,
++ .remove = __devexit_p(serial8250_remove),
++ .suspend = serial8250_suspend,
++ .resume = serial8250_resume,
++ .driver = {
++ .name = "ast-uart-dma",
++ .owner = THIS_MODULE,
++ },
++};
++
++/*
++ * This "device" covers _all_ ISA 8250-compatible serial devices listed
++ * in the table in include/asm/serial.h
++ */
++static struct platform_device *serial8250_isa_devs;
++
++/*
++ * serial8250_register_port and serial8250_unregister_port allows for
++ * 16x50 serial ports to be configured at run-time, to support PCMCIA
++ * modems and PCI multiport cards.
++ */
++
++static struct ast_uart_port *serial8250_find_match_or_unused(struct uart_port *port)
++{
++ int i;
++
++ /*
++ * First, find a port entry which matches.
++ */
++ for (i = 0; i < nr_uarts; i++)
++ if (uart_match_port(&ast_uart_ports[i].port, port))
++ return &ast_uart_ports[i];
++
++ /*
++ * We didn't find a matching entry, so look for the first
++ * free entry. We look for one which hasn't been previously
++ * used (indicated by zero iobase).
++ */
++ for (i = 0; i < nr_uarts; i++)
++ if (ast_uart_ports[i].port.type == PORT_UNKNOWN &&
++ ast_uart_ports[i].port.iobase == 0)
++ return &ast_uart_ports[i];
++
++ /*
++ * That also failed. Last resort is to find any entry which
++ * doesn't have a real port associated with it.
++ */
++ for (i = 0; i < nr_uarts; i++)
++ if (ast_uart_ports[i].port.type == PORT_UNKNOWN)
++ return &ast_uart_ports[i];
++
++ return NULL;
++}
++
++/**
++ * serial8250_register_port - register a serial port
++ * @port: serial port template
++ *
++ * Configure the serial port specified by the request. If the
++ * port exists and is in use, it is hung up and unregistered
++ * first.
++ *
++ * The port is then probed and if necessary the IRQ is autodetected
++ * If this fails an error is returned.
++ *
++ * On success the port is ready to use and the line number is returned.
++ */
++int ast_uart_register_port(struct uart_port *port)
++{
++ struct ast_uart_port *uart;
++ int ret = -ENOSPC;
++
++ if (port->uartclk == 0)
++ return -EINVAL;
++printk("register port line %d\n",port->line);
++ mutex_lock(&ast_uart_mutex);
++
++ uart = serial8250_find_match_or_unused(port);
++ if (uart) {
++ uart_remove_one_port(&serial8250_reg, &uart->port);
++
++ uart->port.iobase = port->iobase;
++ uart->port.membase = port->membase;
++ uart->port.irq = port->irq;
++ uart->port.uartclk = port->uartclk;
++ uart->port.fifosize = port->fifosize;
++ uart->port.regshift = port->regshift;
++ uart->port.iotype = port->iotype;
++ uart->port.flags = port->flags | UPF_BOOT_AUTOCONF;
++ uart->port.mapbase = port->mapbase;
++ uart->port.private_data = port->private_data;
++ if (port->dev)
++ uart->port.dev = port->dev;
++
++ ret = uart_add_one_port(&serial8250_reg, &uart->port);
++ if (ret == 0)
++ ret = uart->port.line;
++
++ spin_lock_init(&uart->lock);
++
++ tasklet_init(&uart->rx_tasklet, ast_uart_rx_tasklet_func,
++ (unsigned long)uart);
++
++ tasklet_init(&uart->tx_tasklet, ast_uart_tx_tasklet_func,
++ (unsigned long)uart);
++
++ }
++
++ mutex_unlock(&ast_uart_mutex);
++
++ return ret;
++}
++EXPORT_SYMBOL(ast_uart_register_port);
++
++/**
++ * serial8250_unregister_port - remove a 16x50 serial port at runtime
++ * @line: serial line number
++ *
++ * Remove one serial port. This may not be called from interrupt
++ * context. We hand the port back to the our control.
++ */
++void ast_uart_unregister_port(int line)
++{
++ struct ast_uart_port *uart = &ast_uart_ports[line];
++
++ mutex_lock(&ast_uart_mutex);
++ uart_remove_one_port(&serial8250_reg, &uart->port);
++ if (serial8250_isa_devs) {
++ uart->port.flags &= ~UPF_BOOT_AUTOCONF;
++ uart->port.type = PORT_UNKNOWN;
++ uart->port.dev = &serial8250_isa_devs->dev;
++ uart_add_one_port(&serial8250_reg, &uart->port);
++ } else {
++ uart->port.dev = NULL;
++ }
++ mutex_unlock(&ast_uart_mutex);
++}
++EXPORT_SYMBOL(ast_uart_unregister_port);
++
++static int __init ast_uart_init(void)
++{
++ int ret;
++
++ if (nr_uarts > UART_DMA_NR)
++ nr_uarts = UART_DMA_NR;
++
++ printk(KERN_INFO "ast-uart-dma: UART driver with DMA "
++ "%d ports, IRQ sharing %sabled\n", nr_uarts,
++ share_irqs ? "en" : "dis");
++
++ spin_lock_init(&ast_uart_irq[0].lock);
++
++ ret = uart_register_driver(&serial8250_reg);
++ if (ret)
++ goto out;
++
++ serial8250_isa_devs = platform_device_alloc("ast-uart-dma",
++ PLAT8250_DEV_LEGACY);
++ if (!serial8250_isa_devs) {
++ ret = -ENOMEM;
++ goto unreg_uart_drv;
++ }
++
++ ret = platform_device_add(serial8250_isa_devs);
++ if (ret)
++ goto put_dev;
++
++ serial8250_register_ports(&serial8250_reg, &serial8250_isa_devs->dev);
++
++ ret = platform_driver_register(&serial8250_ast_dma_driver);
++ if (ret == 0)
++ goto out;
++
++ platform_device_del(serial8250_isa_devs);
++ put_dev:
++ platform_device_put(serial8250_isa_devs);
++ unreg_uart_drv:
++ uart_unregister_driver(&serial8250_reg);
++ out:
++ return ret;
++}
++
++static void __exit ast_uart_exit(void)
++{
++ struct platform_device *isa_dev = serial8250_isa_devs;
++
++ /*
++ * This tells serial8250_unregister_port() not to re-register
++ * the ports (thereby making serial8250_ast_dma_driver permanently
++ * in use.)
++ */
++ serial8250_isa_devs = NULL;
++
++ platform_driver_unregister(&serial8250_ast_dma_driver);
++ platform_device_unregister(isa_dev);
++
++ uart_unregister_driver(&serial8250_reg);
++}
++
++late_initcall(ast_uart_init);
++module_exit(ast_uart_exit);
++
++#if 0
++EXPORT_SYMBOL(serial8250_suspend_port);
++EXPORT_SYMBOL(serial8250_resume_port);
++#endif
++
++MODULE_LICENSE("GPL");
++MODULE_DESCRIPTION("AST DMA serial driver");
++MODULE_ALIAS_CHARDEV_MAJOR(TTY_MAJOR);
+diff --git a/drivers/serial/ast_serial.c b/drivers/serial/ast_serial.c
+new file mode 100644
+index 0000000..d1822e4
+--- /dev/null
++++ b/drivers/serial/ast_serial.c
+@@ -0,0 +1,675 @@
++/********************************************************************************
++* File Name : ast_serial.c
++*
++* Copyright (C) 2012-2020 ASPEED Technology Inc.
++* This program is free software; you can redistribute it and/or modify
++* it under the terms of the GNU General Public License as published by the Free Software Foundation;
++* either version 2 of the License, or (at your option) any later version.
++* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
++* without even the implied warranty of MERCHANTABILITY or
++* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
++* You should have received a copy of the GNU General Public License
++* along with this program; if not, write to the Free Software
++* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++********************************************************************************/
++
++#include <linux/module.h>
++#include <linux/tty.h>
++#include <linux/ioport.h>
++#include <linux/init.h>
++#include <linux/sched.h>
++#include <linux/serial.h>
++#include <linux/console.h>
++#include <linux/sysrq.h>
++
++#include <asm/io.h>
++#include <asm/irq.h>
++
++#if defined(CONFIG_SERIAL_ASPEED_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
++#define SUPPORT_SYSRQ
++#endif
++
++#include <linux/serial_core.h>
++
++#if defined(CONFIG_COLDFIRE)
++#include <asm/astsim.h>
++#include <asm/ast_serial.h>
++#define UART_NR 1
++
++#elif defined(CONFIG_ARM)
++#include <mach/hardware.h>
++#include <mach/aspeed_serial.h>
++#define UART_NR 2
++
++#else
++#err "NO CONFIG CPU for Serial UART"
++#endif
++
++#define PORT_AST 255
++
++
++
++#define SERIAL_AST_CONSLE_NAME "ttyS"
++#define SERIAL_AST_TTY_NAME "ttyS"
++#define SERIAL_AST_DEVFS_NAME "tts/"
++#define SERIAL_AST_MAJOR 4
++#define SERIAL_AST_MINOR 64
++#define SERIAL_AST_NR UART_NR
++
++#define CALLOUT_AST_NAME "cuaam"
++#define CALLOUT_AST_MAJOR 4
++#define CALLOUT_AST_MINOR 65
++#define CALLOUT_AST_NR UART_NR
++
++
++#ifdef SUPPORT_SYSRQ
++static struct console ast_console;
++#endif
++
++#define MVP2000_ISR_PASS_LIMIT 256
++
++
++/*
++ * Access macros for the UARTs
++ */
++#define UART_GET_CHAR(p) readl((p)->membase + UART_RBR)
++#define UART_PUT_CHAR(p, v) writel((v), (p)->membase + UART_THR)
++#define UART_GET_DLL(p) readl((p)->membase + UART_DLL)
++#define UART_PUT_DLL(p, v) writel((v), (p)->membase + UART_DLL)
++#define UART_GET_DLH(p) readl((p)->membase + UART_DLH)
++#define UART_PUT_DLH(p, v) writel((v), (p)->membase + UART_DLH)
++#define UART_GET_IER(p) readl((p)->membase + UART_IER)
++#define UART_PUT_IER(p, v) writel((v), (p)->membase + UART_IER)
++#define UART_GET_IIR(p) readl((p)->membase + UART_IIR)
++#define UART_GET_FCR(p) readl((p)->membase + UART_FCR)
++#define UART_PUT_FCR(p, v) writel((v), (p)->membase + UART_FCR)
++#define UART_GET_LCR(p) readl((p)->membase + UART_LCR)
++#define UART_PUT_LCR(p, v) writel((v), (p)->membase + UART_LCR)
++#define UART_GET_LSR(p) readl((p)->membase + UART_LSR)
++
++#define UART_DUMMY_RSR_RX 256
++#define UART_PORT_SIZE 64
++
++/*
++ * We wrap our port structure around the generic uart_port.
++ */
++struct uart_ast_port {
++ struct uart_port port;
++};
++
++static void ast_uart_stop_tx(struct uart_port *port)
++{
++ unsigned int cr;
++
++ cr = UART_GET_IER(port);
++ cr &= ~UART_IER_ETEI;
++ UART_PUT_IER(port, cr);
++}
++
++static void ast_uart_start_tx(struct uart_port *port)
++{
++ unsigned int cr;
++
++ cr = UART_GET_IER(port);
++ cr |= UART_IER_ETEI;
++ UART_PUT_IER(port, cr);
++}
++
++static void ast_uart_stop_rx(struct uart_port *port)
++{
++ unsigned int cr;
++
++ cr = UART_GET_IER(port);
++ cr &= ~UART_IER_ERDI;
++ UART_PUT_IER(port, cr);
++}
++
++static void ast_uart_enable_ms(struct uart_port *port)
++{
++ /* printk(KERN_WARNING "ASPEED UART DO NOT Support MODEM operations(emable_ms)\n"); */
++}
++
++static void
++ast_uart_rx_chars(struct uart_port *port)
++{
++ struct tty_struct *tty = port->info->port.tty;
++ unsigned int status, ch, flag, lsr, max_count = 256;
++
++ status = UART_GET_LSR(port);;
++ while ((status & UART_LSR_DR) && max_count--) {
++
++ ch = UART_GET_CHAR(port);
++ flag = TTY_NORMAL;
++ port->icount.rx++;
++
++ /*
++ * Note that the error handling code is
++ * out of the main execution path
++ */
++ lsr = UART_GET_LSR(port);
++ if (unlikely(lsr & UART_LSR_ANY)) {
++ if (lsr & UART_LSR_BE) {
++ lsr &= ~(UART_LSR_FE | UART_LSR_PE);
++ port->icount.brk++;
++ if (uart_handle_break(port))
++ goto ignore_char;
++ } else if (lsr & UART_LSR_PE)
++ port->icount.parity++;
++ else if (lsr & UART_LSR_FE)
++ port->icount.frame++;
++ if (lsr & UART_LSR_OE)
++ port->icount.overrun++;
++
++ lsr &= port->read_status_mask;
++
++ if (lsr & UART_LSR_BE)
++ flag = TTY_BREAK;
++ else if (lsr & UART_LSR_PE)
++ flag = TTY_PARITY;
++ else if (lsr & UART_LSR_FE)
++ flag = TTY_FRAME;
++ }
++
++ if (uart_handle_sysrq_char(port, ch & 255))
++ goto ignore_char;
++
++ uart_insert_char(port, lsr, UART_LSR_OE, ch, flag);
++
++ ignore_char:
++ status = UART_GET_LSR(port);
++ }
++ tty_flip_buffer_push(tty);
++ return;
++}
++
++static void ast_uart_tx_chars(struct uart_port *port)
++{
++ struct circ_buf *xmit = &port->info->xmit;
++ int count;
++
++ if (port->x_char) {
++ UART_PUT_CHAR(port, port->x_char);
++ port->icount.tx++;
++ port->x_char = 0;
++ return;
++ }
++ if (uart_circ_empty(xmit) || uart_tx_stopped(port)) {
++ ast_uart_stop_tx(port);
++ return;
++ }
++
++ count = port->fifosize >> 1;
++ do {
++ UART_PUT_CHAR(port, xmit->buf[xmit->tail]);
++ xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
++ port->icount.tx++;
++ if (uart_circ_empty(xmit))
++ break;
++ } while (--count > 0);
++
++ if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
++ uart_write_wakeup(port);
++
++ if (uart_circ_empty(xmit))
++ ast_uart_stop_tx(port);
++}
++
++static irqreturn_t ast_uart_int(int irq, void *dev_id)
++{
++ struct uart_port *port = dev_id;
++ unsigned int status, iir, pass_counter = MVP2000_ISR_PASS_LIMIT;
++
++ spin_lock(&port->lock);
++
++ status = UART_GET_LSR(port);
++ do {
++ if (status & UART_LSR_DR)
++ ast_uart_rx_chars(port);
++
++ if (status & UART_LSR_THRE) {
++ ast_uart_tx_chars(port);
++ iir = UART_GET_IIR(port);
++ }
++
++ if (pass_counter-- == 0)
++ break;
++
++ status = UART_GET_LSR(port);
++ } while (status & (UART_LSR_THRE|UART_LSR_DR));
++
++ spin_unlock(&port->lock);
++
++ return IRQ_HANDLED;
++}
++
++static unsigned int ast_uart_tx_empty(struct uart_port *port)
++{
++ return UART_GET_LSR(port) & UART_LSR_TEMT ? TIOCSER_TEMT : 0;
++}
++
++static unsigned int ast_uart_get_mctrl(struct uart_port *port)
++{
++ /* printk(KERN_WARNING "ASPEED UART DO NOT Support MODEM operations(get_mctrl)\n"); */
++ return 0;
++}
++
++static void ast_uart_set_mctrl(struct uart_port *port, unsigned int mctrl)
++{
++ /* printk(KERN_WARNING "ASPEED UART DO NOT Support MODEM operations(set_mctrl)\n"); */
++}
++
++static void ast_uart_break_ctl(struct uart_port *port, int break_state)
++{
++ unsigned long flags;
++ unsigned int lcr;
++
++ spin_lock_irqsave(&port->lock, flags);
++ lcr = UART_GET_LCR(port);
++ if (break_state == -1)
++ lcr |= UART_LCR_BRK;
++ else
++ lcr &= ~UART_LCR_BRK;
++ UART_PUT_LCR(port, lcr);
++ spin_unlock_irqrestore(&port->lock, flags);
++}
++
++static int ast_uart_startup(struct uart_port *port)
++{
++ int retval;
++
++ /*
++ * Allocate the IRQ
++ */
++ retval = request_irq(port->irq, ast_uart_int, IRQF_DISABLED, "ast_serial", port);
++ if (retval)
++ {
++ printk("ast_uart_startup: Can't Get IRQ\n");
++ return retval;
++ }
++
++ /*
++ * Finally, enable interrupts
++ */
++// IRQ_SET_HIGH_LEVEL(port->irq);
++// IRQ_SET_LEVEL_TRIGGER(port->irq);
++ UART_PUT_IER(port, UART_IER_ERDI);
++
++ return 0;
++}
++
++static void ast_uart_shutdown(struct uart_port *port)
++{
++ /*
++ * Free the interrupt
++ */
++ free_irq(port->irq, port);
++
++ /*
++ * disable all interrupts, disable the port
++ */
++ UART_PUT_IER(port, 0);
++
++ /* disable break condition and fifos */
++ UART_PUT_LCR(port, UART_GET_LCR(port)&(~UART_LCR_BRK));
++ UART_PUT_FCR(port, UART_GET_FCR(port)&(~UART_FCR_FIFOE));
++}
++
++static void
++ast_set_termios(struct uart_port *port, struct ktermios *termios,
++ struct ktermios *old)
++{
++ unsigned int lcr, fcr = 0;
++ unsigned long flags;
++ unsigned int baud, quot;
++ int ch, i;
++
++ /*
++ * Ask the core to calculate the divisor for us.
++ */
++ baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk/16);
++ quot = port->uartclk / (16 * baud);
++
++ switch (termios->c_cflag & CSIZE) {
++ case CS5:
++ lcr = UART_LCR_WLEN_5;
++ break;
++ case CS6:
++ lcr = UART_LCR_WLEN_6;
++ break;
++ case CS7:
++ lcr = UART_LCR_WLEN_7;
++ break;
++ default: // CS8
++ lcr = UART_LCR_WLEN_8;
++ break;
++ }
++ if (termios->c_cflag & CSTOPB)
++ lcr |= UART_LCR_STOP;
++ if (termios->c_cflag & PARENB) {
++ lcr |= UART_LCR_PEN;
++ if (!(termios->c_cflag & PARODD))
++ lcr |= UART_LCR_EPS;
++ }
++ if (port->fifosize > 1)
++ fcr |= (UART_FCR_XMITR|UART_FCR_RCVRR|UART_FCR_FIFOE);
++
++
++ spin_lock_irqsave(&port->lock, flags);
++
++ /*
++ * Update the per-port timeout.
++ */
++ uart_update_timeout(port, termios->c_cflag, baud);
++
++ port->read_status_mask = UART_LSR_OE;
++ if (termios->c_iflag & INPCK)
++ port->read_status_mask |= UART_LSR_FE | UART_LSR_PE;
++ if (termios->c_iflag & (BRKINT | PARMRK))
++ port->read_status_mask |= UART_LSR_BE;
++
++ /*
++ * Characters to ignore
++ */
++ port->ignore_status_mask = 0;
++ if (termios->c_iflag & IGNPAR)
++ port->ignore_status_mask |= UART_LSR_FE | UART_LSR_PE;
++ if (termios->c_iflag & IGNBRK) {
++ port->ignore_status_mask |= UART_LSR_BE;
++ /*
++ * If we're ignoring parity and break indicators,
++ * ignore overruns too (for real raw support).
++ */
++ if (termios->c_iflag & IGNPAR)
++ port->ignore_status_mask |= UART_LSR_OE;
++ }
++
++ /*
++ * Ignore all characters if CREAD is not set.
++ */
++ if ((termios->c_cflag & CREAD) == 0)
++ port->ignore_status_mask |= UART_DUMMY_RSR_RX;
++
++
++ /* Set baud rate */
++ UART_PUT_LCR(port, UART_LCR_DLAB); /* enable Divisor Latach Address Bit */
++ UART_PUT_DLH(port, ((quot >> 8) & 0xFF));
++ UART_PUT_DLL(port, (quot & 0xff));
++
++ UART_PUT_FCR(port, fcr);
++ UART_PUT_LCR(port, lcr);
++ for (i = 0; i < 16; i++) {
++ ch = UART_GET_CHAR (port); /* Clear Timeout Interrupt */
++ }
++
++ spin_unlock_irqrestore(&port->lock, flags);
++}
++
++static const char *ast_uart_type(struct uart_port *port)
++{
++ return port->type == PORT_AST ? "AST UART" : NULL;
++}
++
++/*
++ * Release the memory region(s) being used by 'port'
++ */
++static void ast_uart_release_port(struct uart_port *port)
++{
++ release_mem_region(port->mapbase, UART_PORT_SIZE);
++}
++
++/*
++ * Request the memory region(s) being used by 'port'
++ */
++static int ast_uart_request_port(struct uart_port *port)
++{
++ return request_mem_region(port->mapbase, UART_PORT_SIZE, "serial_ast")
++ != NULL ? 0 : -EBUSY;
++}
++
++/*
++ * Configure/autoconfigure the port.
++ */
++static void ast_uart_config_port(struct uart_port *port, int flags)
++{
++ if (flags & UART_CONFIG_TYPE) {
++ port->type = PORT_AST;
++ ast_uart_request_port(port);
++ }
++}
++
++/*
++ * verify the new serial_struct (for TIOCSSERIAL).
++ */
++static int ast_uart_verify_port(struct uart_port *port, struct serial_struct *ser)
++{
++ int ret = 0;
++ if (ser->type != PORT_UNKNOWN && ser->type != PORT_AST)
++ ret = -EINVAL;
++ if (ser->irq < 0 || ser->irq >= NR_IRQS)
++ ret = -EINVAL;
++ if (ser->baud_base < 9600)
++ ret = -EINVAL;
++ return ret;
++}
++
++static struct uart_ops ast_pops = {
++ .tx_empty = ast_uart_tx_empty,
++ .set_mctrl = ast_uart_set_mctrl,
++ .get_mctrl = ast_uart_get_mctrl,
++ .stop_tx = ast_uart_stop_tx,
++ .start_tx = ast_uart_start_tx,
++ .stop_rx = ast_uart_stop_rx,
++ .enable_ms = ast_uart_enable_ms,
++ .break_ctl = ast_uart_break_ctl,
++ .startup = ast_uart_startup,
++ .shutdown = ast_uart_shutdown,
++ .set_termios = ast_set_termios,
++ .type = ast_uart_type,
++ .release_port = ast_uart_release_port,
++ .request_port = ast_uart_request_port,
++ .config_port = ast_uart_config_port,
++ .verify_port = ast_uart_verify_port,
++};
++
++#if defined(CONFIG_COLDFIRE)
++static struct uart_ast_port ast_ports[UART_NR] = {
++ {
++ .port = {
++ .membase = (void *) AST_UART0_BASE,
++ .mapbase = AST_UART0_BASE,
++ .iotype = SERIAL_IO_MEM,
++ .irq = IRQ_UART0,
++ .uartclk = (24*1000000L),
++ .fifosize = 16,
++ .ops = &ast_pops,
++ .flags = ASYNC_BOOT_AUTOCONF,
++ .line = 0,
++ },
++ }
++};
++
++#elif defined (CONFIG_ARM)
++static struct uart_ast_port ast_ports[UART_NR] = {
++ {
++ .port = {
++ .membase = (void *) (IO_ADDRESS(AST_UART0_BASE)),
++ .mapbase = AST_UART0_BASE,
++ .iotype = SERIAL_IO_MEM,
++ .irq = IRQ_UART0,
++ .uartclk = (24*1000000L),
++ .fifosize = 16,
++ .ops = &ast_pops,
++ .flags = ASYNC_BOOT_AUTOCONF,
++ .line = 0,
++ },
++ }
++};
++#else
++#err "ERROR~~~"
++#endif
++
++#ifdef CONFIG_SERIAL_ASPEED_CONSOLE
++
++static void aspeed_console_putchar(struct uart_port *port, int ch)
++{
++ while (!(UART_GET_LSR(port) & UART_LSR_THRE))
++ barrier();
++ UART_PUT_CHAR(port, ch);
++}
++
++static void ast_uart_console_write(struct console *co, const char *s, unsigned int count)
++{
++ struct uart_port *port = &ast_ports[co->index].port;
++ unsigned int status, old_ier;
++
++ /*
++ * First save the IER then disable the interrupts
++ */
++ old_ier = UART_GET_IER(port);
++ UART_PUT_IER(port, 0);
++
++ /*
++ * Now, do each character
++ */
++ uart_console_write(port, s, count, aspeed_console_putchar);
++
++ /*
++ * Finally, wait for transmitter to become empty
++ * and restore the IER
++ */
++ do {
++ status = UART_GET_LSR(port);
++ } while (!(status & UART_LSR_TEMT));
++ UART_PUT_IER(port, old_ier);
++}
++
++static void __init
++ast_uart_console_get_options(struct uart_port *port, int *baud, int *parity, int *bits)
++{
++ if (UART_GET_IER(port) & UART_IER_ERDI) {
++ unsigned int lcr, quot;
++ lcr = UART_GET_LCR(port);
++
++ *parity = 'n';
++ if (lcr & UART_LCR_PEN) {
++ if (lcr & UART_LCR_EPS)
++ *parity = 'e';
++ else
++ *parity = 'o';
++ }
++
++ switch (lcr & UART_LCR_WLEN_MASK) {
++ case UART_LCR_WLEN_8:
++ default:
++ *bits = 8;
++ break;
++ case UART_LCR_WLEN_7:
++ *bits = 7;
++ break;
++ case UART_LCR_WLEN_6:
++ *bits = 6;
++ break;
++ case UART_LCR_WLEN_5:
++ *bits = 5;
++ break;
++ }
++
++ UART_PUT_LCR(port, UART_LCR_DLAB); /* enable Divisor Latach Address Bit */
++ quot = UART_GET_DLL(port) | (UART_GET_DLH(port) << 8);
++ *baud = port->uartclk / (16 * quot);
++ UART_PUT_LCR(port, lcr);
++ }
++}
++
++static int __init ast_uart_console_setup(struct console *co, char *options)
++{
++ struct uart_port *port;
++ int baud = CONFIG_SERIAL_ASPEED_CONSOLE_BAUD;
++ int bits = 8;
++ int parity = 'n';
++ int flow = 'n';
++
++ /*
++ * Check whether an invalid uart number has been specified, and
++ * if so, search for the first available port that does have
++ * console support.
++ */
++ if (co->index >= UART_NR)
++ co->index = 0;
++ port = &ast_ports[co->index].port;
++
++
++ if (options)
++ uart_parse_options(options, &baud, &parity, &bits, &flow);
++ else
++ ast_uart_console_get_options(port, &baud, &parity, &bits);
++
++
++ return uart_set_options(port, co, baud, parity, bits, flow);
++}
++
++static struct uart_driver ast_reg;
++
++static struct console ast_console = {
++ .name = SERIAL_AST_CONSLE_NAME,
++ .write = ast_uart_console_write,
++ .device = uart_console_device,
++ .setup = ast_uart_console_setup,
++ .flags = CON_PRINTBUFFER,
++ .index = -1,
++ .data = &ast_reg,
++};
++
++int __init ast_uart_console_init(void)
++{
++ register_console(&ast_console);
++ return 0;
++}
++
++console_initcall(ast_uart_console_init);
++
++#define MVP2000_CONSOLE &ast_console
++#else
++#define MVP2000_CONSOLE NULL
++#endif
++
++
++static struct uart_driver ast_reg = {
++ .owner = THIS_MODULE,
++ .major = SERIAL_AST_MAJOR,
++ .minor = SERIAL_AST_MINOR,
++ .dev_name = SERIAL_AST_TTY_NAME,
++ .nr = UART_NR,
++ .cons = MVP2000_CONSOLE,
++};
++
++static int __init ast_uart_init(void)
++{
++ int ret;
++
++ ret = uart_register_driver(&ast_reg);
++ if (ret == 0) {
++ int i;
++
++ for (i = 0; i < UART_NR; i++)
++ uart_add_one_port(&ast_reg, &ast_ports[i].port);
++ }
++ return ret;
++}
++
++static void __exit ast_uart_exit(void)
++{
++ int i;
++
++ for (i = 0; i < UART_NR; i++)
++ uart_remove_one_port(&ast_reg, &ast_ports[i].port);
++
++ uart_unregister_driver(&ast_reg);
++}
++
++module_init(ast_uart_init);
++module_exit(ast_uart_exit);
++
++MODULE_AUTHOR("ASPEED Technology Inc.");
++MODULE_DESCRIPTION("ASPEED serial port driver");
++MODULE_LICENSE("GPL");
+diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
+index b9d0efb..d95c2c8 100644
+--- a/drivers/spi/Kconfig
++++ b/drivers/spi/Kconfig
+@@ -53,6 +53,19 @@ if SPI_MASTER
+
+ comment "SPI Master Controller Drivers"
+
++config SPI_AST
++ tristate "Aspeed SPI Controller"
++ depends on ARCH_ASPEED
++ select SPI_BITBANG
++ help
++ This selects a driver for the AST SPI Controller
++
++config SPI_FMC
++ tristate "Aspeed FMC SPI Controller"
++ depends on ARCH_ASPEED
++ help
++ This selects a driver for the AST FMC SPI Controller
++
+ config SPI_ATMEL
+ tristate "Atmel SPI Controller"
+ depends on (ARCH_AT91 || AVR32)
+diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile
+index ccf18de..3d1286e 100644
+--- a/drivers/spi/Makefile
++++ b/drivers/spi/Makefile
+@@ -29,6 +29,8 @@ obj-$(CONFIG_SPI_S3C24XX) += spi_s3c24xx.o
+ obj-$(CONFIG_SPI_TXX9) += spi_txx9.o
+ obj-$(CONFIG_SPI_XILINX) += xilinx_spi.o
+ obj-$(CONFIG_SPI_SH_SCI) += spi_sh_sci.o
++obj-$(CONFIG_SPI_AST) += ast_spi.o
++obj-$(CONFIG_SPI_FMC) += fmc_spi.o
+ # ... add above this line ...
+
+ # SPI protocol drivers (device/link on bus)
+diff --git a/drivers/spi/ast_spi.c b/drivers/spi/ast_spi.c
+new file mode 100644
+index 0000000..e8f80e8
+--- /dev/null
++++ b/drivers/spi/ast_spi.c
+@@ -0,0 +1,416 @@
++/********************************************************************************
++* File Name : driver/spi/ast-spi.c
++* Author : Ryan Chen
++* Description : ASPEED SPI host driver
++*
++* Copyright (C) 2012-2020 ASPEED Technology Inc.
++* This program is free software; you can redistribute it and/or modify
++* it under the terms of the GNU General Public License as published by the Free Software Foundation;
++* either version 2 of the License, or (at your option) any later version.
++*
++* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
++* without even the implied warranty of MERCHANTABILITY or
++* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
++*
++* You should have received a copy of the GNU General Public License
++* along with this program; if not, write to the Free Software
++* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++
++* History :
++* 1. 2012/10/20 Ryan Chen create this file
++* 1. 2013/01/05 Ryan Chen modify
++*
++********************************************************************************/
++//#define DEBUG
++
++#include <linux/module.h>
++#include <linux/init.h>
++#include <linux/sched.h>
++#include <linux/kernel.h>
++#include <linux/interrupt.h>
++#include <linux/ioport.h>
++#include <linux/platform_device.h>
++#include <linux/err.h>
++#include <linux/errno.h>
++#include <linux/wait.h>
++#include <linux/delay.h>
++#include <linux/spi/spi.h>
++#include <asm/io.h>
++#include <mach/ast_spi.h>
++#include <plat/regs-spi.h>
++
++struct ast_spi_host {
++ void __iomem *reg;
++ void __iomem *buff;
++ struct ast_spi_driver_data *spi_data;
++ struct spi_master *master;
++ struct spi_device *spi_dev;
++ struct device *dev;
++ spinlock_t lock;
++};
++
++static inline void
++ast_spi_write(struct ast_spi_host *spi, u32 val, u32 reg)
++{
++// dev_dbg(i2c_dev->dev, "ast_i2c_write : val: %x , reg : %x \n",val,reg);
++ writel(val, spi->reg+ reg);
++}
++
++static inline u32
++ast_spi_read(struct ast_spi_host *spi, u32 reg)
++{
++ return readl(spi->reg + reg);
++}
++
++/* the spi->mode bits understood by this driver: */
++#define MODEBITS (SPI_CPOL | SPI_CPHA | SPI_CS_HIGH)
++
++static int
++ast_spi_setup(struct spi_device *spi)
++{
++ struct ast_spi_host *host = (struct ast_spi_host *)spi_master_get_devdata(spi->master);
++ unsigned int bits = spi->bits_per_word;
++ u32 spi_ctrl;
++ u32 divisor;
++
++ int err = 0;
++ return err;
++
++ dev_dbg(host->dev, "ast_spi_setup() , cs %d\n", spi->chip_select);
++
++ host->spi_dev = spi;
++
++ spi_ctrl = ast_spi_read(host, AST_SPI_CTRL);
++
++ if (spi->chip_select > spi->master->num_chipselect) {
++ dev_dbg(&spi->dev,
++ "setup: invalid chipselect %u (%u defined)\n",
++ spi->chip_select, spi->master->num_chipselect);
++ return -EINVAL;
++ }
++
++ if (bits == 0)
++ bits = 8;
++
++ if (bits < 8 || bits > 16) {
++ dev_dbg(&spi->dev,
++ "setup: invalid bits_per_word %u (8 to 16)\n",
++ bits);
++ return -EINVAL;
++ }
++
++ if (spi->mode & ~MODEBITS) {
++ dev_dbg(&spi->dev, "setup: unsupported mode bits %x\n",
++ spi->mode & ~MODEBITS);
++ return -EINVAL;
++ }
++
++ /* see notes above re chipselect */
++ if((spi->chip_select == 0) && (spi->mode & SPI_CS_HIGH)) {
++ dev_dbg(&spi->dev, "setup: can't be active-high\n");
++ return -EINVAL;
++ }
++
++ /*
++ * Pre-new_1 chips start out at half the peripheral
++ * bus speed.
++ */
++
++ if (spi->max_speed_hz) {
++ /* Set the SPI slaves select and characteristic control register */
++ divisor = host->spi_data->get_div(spi->max_speed_hz);
++ } else {
++ /* speed zero means "as slow as possible" */
++ divisor = 15;
++ }
++
++ //TODO MASK first
++ spi_ctrl |= (divisor << 8);
++
++ if (spi->chip_select > (spi->master->num_chipselect - 1)) {
++ dev_err(&spi->dev, "chipselect %d exceed the number of chipselect master supoort\n", spi->chip_select);
++ return -EINVAL;
++ }
++
++#if 0
++ if (SPI_CPHA & spi->mode)
++ cpha = SPI_CPHA_1;
++ else
++ cpha = SPI_CPHA_0;
++#endif
++
++// if (SPI_CPOL & spi->mode)
++// spi_ctrl |= SPI_CPOL_1;
++// else
++// spi_ctrl &= ~SPI_CPOL_1;
++
++ //ISSUE : ast spi ctrl couldn't use mode 3, so fix mode 0
++ spi_ctrl &= ~SPI_CPOL_1;
++
++
++ if (SPI_LSB_FIRST & spi->mode)
++ spi_ctrl |= SPI_LSB_FIRST_CTRL;
++ else
++ spi_ctrl &= ~SPI_LSB_FIRST_CTRL;
++
++
++ /* Configure SPI controller */
++ ast_spi_write(host, spi_ctrl, AST_SPI_CTRL);
++
++ dev_dbg(&spi->dev, "%s: mode %d, %u bpw, %d hz\n", __FUNCTION__, spi->mode, spi->bits_per_word, spi->max_speed_hz);
++ return err;
++}
++
++static int ast_spi_transfer(struct spi_device *spi, struct spi_message *msg)
++{
++ struct ast_spi_host *host = (struct ast_spi_host *)spi_master_get_devdata(spi->master);
++ struct spi_transfer *xfer;
++ const u8 *tx_buf;
++ u8 *rx_buf;
++
++
++ int i=0,j=0;
++
++ dev_dbg(host->dev, "new message %p submitted for %s\n",
++ msg, spi->dev.bus_id);
++
++ ast_spi_write(host, ast_spi_read(host, AST_SPI_CONFIG) | SPI_CONF_WRITE_EN, AST_SPI_CONFIG);
++// writel( (readl(host->spi_data->ctrl_reg) | SPI_CMD_USER_MODE) | SPI_CE_INACTIVE,host->spi_data->ctrl_reg);
++ ast_spi_write(host, ast_spi_read(host, AST_SPI_CTRL) | SPI_CMD_USER_MODE, AST_SPI_CTRL);
++
++// writel( ~SPI_CE_INACTIVE & readl(host->spi_data->ctrl_reg),host->spi_data->ctrl_reg);
++ msg->actual_length = 0;
++ msg->status = 0;
++
++
++ list_for_each_entry(xfer, &msg->transfers, transfer_list) {
++ dev_dbg(host->dev,
++ "xfer[%d] %p: width %d, len %u, tx %p/%08x, rx %p/%08x\n",
++ j, xfer,
++ xfer->bits_per_word, xfer->len,
++ xfer->tx_buf, xfer->tx_dma,
++ xfer->rx_buf, xfer->rx_dma);
++
++ //TX ----
++ if(xfer->tx_buf) {
++#if 0
++ if(xfer->bits_per_word == 16)
++ const u16 *tx_buf;
++ else
++ const u8 *tx_buf;
++#endif
++ tx_buf = xfer->tx_buf;
++ for(i=0;i<xfer->len;i++) {
++ dev_dbg(host->dev, "[%d] : %x \n",i, tx_buf[i]);
++ writeb(tx_buf[i], host->buff);
++// writeb(tx_buf[i], host->spi_data->buf_reg);
++ }
++ }
++ udelay(1);
++ //RX----
++ if(xfer->rx_buf) {
++
++ rx_buf = xfer->rx_buf;
++ dev_dbg(host->dev, "rx len [%d] \n",xfer->len );
++ for(i=0;i<xfer->len;i++) {
++// rx_buf[i] = readb(host->spi_data->buf_reg);
++ rx_buf[i] = readb(host->buff);
++ dev_dbg(host->dev, "[%d] : %x \n",i, rx_buf[i]);
++ }
++ }
++ msg->actual_length += xfer->len;
++ j++;
++ }
++
++// writel( SPI_CE_INACTIVE | readl(host->spi_data->ctrl_reg),host->spi_data->ctrl_reg);
++ ast_spi_write(host, (ast_spi_read(host, AST_SPI_CTRL) & ~SPI_CMD_USER_MODE) | SPI_CMD_FAST_R_MODE, AST_SPI_CTRL);
++
++ ast_spi_write(host, ast_spi_read(host, AST_SPI_CONFIG) & ~SPI_CONF_WRITE_EN, AST_SPI_CONFIG);
++
++ msg->status = 0;
++
++ spin_unlock(&host->lock);
++ msg->complete(msg->context);
++ spin_lock(&host->lock);
++
++ return 0;
++
++}
++static void ast_spi_cleanup(struct spi_device *spi)
++{
++ struct ast_spi_host *host = spi_master_get_devdata(spi->master);
++ unsigned long flags;
++ dev_dbg(host->dev, "ast_spi_cleanup() \n");
++
++ spin_lock_irqsave(&host->lock, flags);
++// if (host->stay == spi) {
++// host->stay = NULL;
++// cs_deactivate(host, spi);
++// }
++ spin_unlock_irqrestore(&host->lock, flags);
++}
++
++static int ast_spi_probe(struct platform_device *pdev)
++{
++ struct resource *res0, *res1;
++ struct ast_spi_host *host;
++ struct spi_master *master;
++ int err;
++
++ dev_dbg(&pdev->dev, "ast_spi_probe() \n\n\n");
++
++ master = spi_alloc_master(&pdev->dev, sizeof(struct ast_spi_host));
++ if (NULL == master) {
++ dev_err(&pdev->dev, "No memory for spi_master\n");
++ err = -ENOMEM;
++ goto err_nomem;
++ }
++ host = spi_master_get_devdata(master);
++ memset(host, 0, sizeof(struct ast_spi_host));
++
++ res0 = platform_get_resource(pdev, IORESOURCE_MEM, 0);
++ if (!res0) {
++ dev_err(&pdev->dev, "cannot get IORESOURCE_MEM 0\n");
++ err = -ENXIO;
++ goto err_no_io_res;
++ }
++
++ host->reg = ioremap(res0->start, resource_size(res0));
++ if (!host->reg) {
++ dev_err(&pdev->dev, "cannot remap register\n");
++ err = -EIO;
++ goto release_mem;
++ }
++
++ dev_dbg(&pdev->dev, "remap phy %x, virt %x \n",(u32)res0->start, (u32)host->reg);
++
++ res1 = platform_get_resource(pdev, IORESOURCE_IO, 0);
++ if (!res1) {
++ dev_err(&pdev->dev, "cannot get IORESOURCE_IO 0\n");
++ return -ENXIO;
++ }
++
++ host->buff = ioremap(res1->start, resource_size(res1));
++ if (!host->buff) {
++ dev_err(&pdev->dev, "cannot remap buffer \n");
++ err = -EIO;
++ goto release_mem;
++ }
++
++ dev_dbg(&pdev->dev, "remap io phy %x, virt %x \n",(u32)res1->start, (u32)host->buff);
++
++ host->master = spi_master_get(master);
++ host->master->bus_num = pdev->id;
++ host->master->num_chipselect = 1;
++ host->dev = &pdev->dev;
++
++ /* Setup the state for bitbang driver */
++ host->master->setup = ast_spi_setup;
++ host->master->transfer = ast_spi_transfer;
++ host->master->cleanup = ast_spi_cleanup;
++
++ /* Find and claim our resources */
++ host->spi_data = pdev->dev.driver_data;
++
++ platform_set_drvdata(pdev, host);
++
++ /* Register our spi controller */
++ err = spi_register_master(host->master);
++ if (err) {
++ dev_err(&pdev->dev, "failed to register SPI master\n");
++ goto err_register;
++ }
++
++ dev_dbg(&pdev->dev, "ast_spi_probe() return \n\n\n");
++
++ return 0;
++
++err_register:
++ spi_master_put(host->master);
++ iounmap(host->reg);
++ iounmap(host->buff);
++
++release_mem:
++ release_mem_region(res0->start, res0->end - res0->start + 1);
++ release_mem_region(res1->start, res1->end - res1->start + 1);
++
++err_no_io_res:
++ kfree(master);
++ kfree(host);
++
++err_nomem:
++ return err;
++
++}
++
++static int
++ast_spi_remove(struct platform_device *pdev)
++{
++ struct resource *res0, *res1;
++ struct ast_spi_host *host = platform_get_drvdata(pdev);
++
++ dev_dbg(host->dev, "ast_spi_remove()\n");
++
++ if (!host)
++ return -1;
++
++ res0 = platform_get_resource(pdev, IORESOURCE_MEM, 0);
++ res1 = platform_get_resource(pdev, IORESOURCE_IO, 0);
++ release_mem_region(res0->start, res0->end - res0->start + 1);
++ release_mem_region(res1->start, res1->end - res1->start + 1);
++ iounmap(host->reg);
++ iounmap(host->buff);
++
++ platform_set_drvdata(pdev, NULL);
++ spi_unregister_master(host->master);
++ spi_master_put(host->master);
++ return 0;
++}
++
++#ifdef CONFIG_PM
++static int
++ast_spi_suspend(struct platform_device *pdev, pm_message_t msg)
++{
++ return 0;
++}
++
++static int
++ast_spi_resume(struct platform_device *pdev)
++{
++ return 0;
++}
++#else
++#define ast_spi_suspend NULL
++#define ast_spi_resume NULL
++#endif
++
++static struct platform_driver ast_spi_driver = {
++ .probe = ast_spi_probe,
++ .remove = ast_spi_remove,
++ .suspend = ast_spi_suspend,
++ .resume = ast_spi_resume,
++ .driver = {
++ .name = "ast-spi",
++ .owner = THIS_MODULE,
++ },
++};
++
++static int __init
++ast_spi_init(void)
++{
++ return platform_driver_register(&ast_spi_driver);
++}
++
++static void __exit
++ast_spi_exit(void)
++{
++ platform_driver_unregister(&ast_spi_driver);
++}
++
++subsys_initcall(ast_spi_init);
++//module_init(ast_spi_init);
++module_exit(ast_spi_exit);
++
++MODULE_DESCRIPTION("AST SPI Driver");
++MODULE_AUTHOR("Ryan Chen");
++MODULE_LICENSE("GPL");
+diff --git a/drivers/spi/fmc_spi.c b/drivers/spi/fmc_spi.c
+new file mode 100644
+index 0000000..ccc0d1c
+--- /dev/null
++++ b/drivers/spi/fmc_spi.c
+@@ -0,0 +1,436 @@
++/********************************************************************************
++* File Name : driver/spi/ast-spi.c
++* Author : Ryan Chen
++* Description : ASPEED SPI host driver
++*
++* Copyright (C) 2012-2020 ASPEED Technology Inc.
++* This program is free software; you can redistribute it and/or modify
++* it under the terms of the GNU General Public License as published by the Free Software Foundation;
++* either version 2 of the License, or (at your option) any later version.
++*
++* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
++* without even the implied warranty of MERCHANTABILITY or
++* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
++*
++* You should have received a copy of the GNU General Public License
++* along with this program; if not, write to the Free Software
++* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++
++* History :
++* 1. 2012/10/20 Ryan Chen create this file
++* 1. 2013/01/05 Ryan Chen modify
++*
++********************************************************************************/
++//#define DEBUG
++
++#include <linux/module.h>
++#include <linux/init.h>
++#include <linux/sched.h>
++#include <linux/kernel.h>
++#include <linux/interrupt.h>
++#include <linux/ioport.h>
++#include <linux/platform_device.h>
++#include <linux/err.h>
++#include <linux/errno.h>
++#include <linux/wait.h>
++#include <linux/delay.h>
++#include <linux/spi/spi.h>
++#include <asm/io.h>
++#include <mach/ast_spi.h>
++#include <plat/regs-spi.h>
++
++//IN FMC SPI always control offset 0x00
++
++struct fmc_spi_host {
++ void __iomem *reg;
++ void __iomem *buff;
++ struct ast_spi_driver_data *spi_data;
++ struct spi_master *master;
++ struct spi_device *spi_dev;
++ struct device *dev;
++ spinlock_t lock;
++};
++
++static inline void
++fmc_spi_write(struct fmc_spi_host *host, u32 val, u32 reg)
++{
++// printk("write : val: %x , offset : %x \n",val, reg);
++ writel(val, host->reg + reg);
++}
++
++static inline u32
++fmc_spi_read(struct fmc_spi_host *host, u32 reg)
++{
++ return readl(host->reg + reg);
++}
++
++/* the spi->mode bits understood by this driver: */
++#define MODEBITS (SPI_CPOL | SPI_CPHA | SPI_CS_HIGH)
++
++static int
++fmc_spi_setup(struct spi_device *spi)
++{
++ struct fmc_spi_host *host = (struct fmc_spi_host *)spi_master_get_devdata(spi->master);
++ unsigned int bits = spi->bits_per_word;
++ u32 spi_ctrl;
++ u32 divisor;
++
++ int err = 0;
++ dev_dbg(host->dev, "fmc_spi_setup() ======================>>\n");
++
++
++ dev_dbg(host->dev, "fmc_spi_setup() ======================>>\n");
++
++ host->spi_dev = spi;
++
++ spi_ctrl = fmc_spi_read(host, 0x00);
++// printk("trl : %x \n",spi_ctrl);
++
++ if (spi->chip_select > spi->master->num_chipselect) {
++ dev_dbg(&spi->dev,
++ "setup: invalid chipselect %u (%u defined)\n",
++ spi->chip_select, spi->master->num_chipselect);
++ return -EINVAL;
++ }
++
++ if (bits == 0)
++ bits = 8;
++
++ if (bits < 8 || bits > 16) {
++ dev_dbg(&spi->dev,
++ "setup: invalid bits_per_word %u (8 to 16)\n",
++ bits);
++ return -EINVAL;
++ }
++
++ if (spi->mode & ~MODEBITS) {
++ dev_dbg(&spi->dev, "setup: unsupported mode bits %x\n",
++ spi->mode & ~MODEBITS);
++ return -EINVAL;
++ }
++
++ /* see notes above re chipselect */
++ if((spi->chip_select == 0) && (spi->mode & SPI_CS_HIGH)) {
++ dev_dbg(&spi->dev, "setup: can't be active-high\n");
++ return -EINVAL;
++ }
++
++ /*
++ * Pre-new_1 chips start out at half the peripheral
++ * bus speed.
++ */
++
++ if (spi->max_speed_hz) {
++ /* Set the SPI slaves select and characteristic control register */
++ divisor = host->spi_data->get_div(spi->max_speed_hz);
++ } else {
++ /* speed zero means "as slow as possible" */
++ divisor = 15;
++ }
++
++ spi_ctrl &= ~SPI_CLK_DIV_MASK;
++// printk("set div %x \n",divisor);
++ //TODO MASK first
++ spi_ctrl |= SPI_CLK_DIV(divisor);
++
++ if (spi->chip_select > (spi->master->num_chipselect - 1)) {
++ dev_err(&spi->dev, "chipselect %d exceed the number of chipselect master supoort\n", spi->chip_select);
++ return -EINVAL;
++ }
++
++#if 0
++ if (SPI_CPHA & spi->mode)
++ cpha = SPI_CPHA_1;
++ else
++ cpha = SPI_CPHA_0;
++#endif
++
++// if (SPI_CPOL & spi->mode)
++// spi_ctrl |= SPI_CPOL_1;
++// else
++// spi_ctrl &= ~SPI_CPOL_1;
++
++ //ISSUE : ast spi ctrl couldn't use mode 3, so fix mode 0
++ spi_ctrl &= ~SPI_CPOL_1;
++
++
++ if (SPI_LSB_FIRST & spi->mode)
++ spi_ctrl |= SPI_LSB_FIRST_CTRL;
++ else
++ spi_ctrl &= ~SPI_LSB_FIRST_CTRL;
++
++
++ /* Configure SPI controller */
++ fmc_spi_write(host, spi_ctrl, 0x00);
++
++ dev_dbg(&spi->dev, "%s: mode %d, %u bpw, %d hz\n", __FUNCTION__, spi->mode, spi->bits_per_word, spi->max_speed_hz);
++ return err;
++}
++
++static int fmc_spi_transfer(struct spi_device *spi, struct spi_message *msg)
++{
++ struct fmc_spi_host *host = (struct fmc_spi_host *)spi_master_get_devdata(spi->master);
++ struct spi_transfer *xfer;
++ const u8 *tx_buf;
++ u8 *rx_buf;
++ unsigned long flags;
++
++ int i=0,j=0;
++
++ dev_dbg(host->dev, "new message %p submitted for %s \n",
++ msg, dev_name(&spi->dev));
++
++ spin_lock_irqsave(&host->lock, flags);
++// writel( (readl(host->spi_data->ctrl_reg) | SPI_CMD_USER_MODE) | SPI_CE_INACTIVE,host->spi_data->ctrl_reg);
++ fmc_spi_write(host, fmc_spi_read(host, 0x00) | SPI_CMD_USER_MODE, 0x00);
++ msg->actual_length = 0;
++ msg->status = 0;
++
++// writel( ~SPI_CE_INACTIVE & readl(host->spi_data->ctrl_reg),host->spi_data->ctrl_reg);
++
++ list_for_each_entry(xfer, &msg->transfers, transfer_list) {
++ dev_dbg(host->dev,
++ "xfer[%d] %p: width %d, len %u, tx %p/%08x, rx %p/%08x\n",
++ j, xfer,
++ xfer->bits_per_word, xfer->len,
++ xfer->tx_buf, xfer->tx_dma,
++ xfer->rx_buf, xfer->rx_dma);
++
++ tx_buf = xfer->tx_buf;
++ rx_buf = xfer->rx_buf;
++
++
++ if(tx_buf != 0) {
++#if 0
++ printk("tx : ");
++ if(xfer->len > 10) {
++ for(i=0;i<10;i++)
++ printk("%x ",tx_buf[i]);
++ } else {
++ for(i=0;i<xfer->len;i++)
++ printk("%x ",tx_buf[i]);
++ }
++ printk("\n");
++#endif
++ for(i=0;i<xfer->len;i++) {
++ writeb(tx_buf[i], host->buff);
++ }
++ }
++ //Issue need clarify
++ udelay(1);
++ if(rx_buf != 0) {
++ for(i=0;i<xfer->len;i++) {
++ rx_buf[i] = readb(host->buff);
++ }
++#if 0
++ printk("rx : ");
++ if(xfer->len > 10) {
++ for(i=0;i<10;i++)
++ printk(" %x",rx_buf[i]);
++ } else {
++ for(i=0;i<xfer->len;i++)
++ printk(" %x",rx_buf[i]);
++ }
++ printk("\n");
++#endif
++ }
++ dev_dbg(host->dev,"old msg->actual_length %d , +len %d \n",msg->actual_length, xfer->len);
++ msg->actual_length += xfer->len;
++ dev_dbg(host->dev,"new msg->actual_length %d \n",msg->actual_length);
++// j++;
++
++ }
++
++// writel( SPI_CE_INACTIVE | readl(host->spi_data->ctrl_reg),host->spi_data->ctrl_reg);
++ fmc_spi_write(host, (fmc_spi_read(host, 0x00) & ~SPI_CMD_USER_MODE), 0x00);
++ msg->status = 0;
++
++ msg->complete(msg->context);
++
++// spin_unlock(&host->lock);
++ spin_unlock_irqrestore(&host->lock, flags);
++
++
++
++
++ return 0;
++
++}
++static void fmc_spi_cleanup(struct spi_device *spi)
++{
++ struct fmc_spi_host *host = spi_master_get_devdata(spi->master);
++ unsigned long flags;
++ dev_dbg(host->dev, "fmc_spi_cleanup() \n");
++
++ spin_lock_irqsave(&host->lock, flags);
++// if (host->stay == spi) {
++// host->stay = NULL;
++// cs_deactivate(host, spi);
++// }
++ spin_unlock_irqrestore(&host->lock, flags);
++}
++
++static int fmc_spi_probe(struct platform_device *pdev)
++{
++ struct resource *res0, *res1=0;
++ struct fmc_spi_host *host;
++ struct spi_master *master;
++ int err;
++
++ dev_dbg(&pdev->dev, "fmc_spi_probe() \n\n\n");
++
++ master = spi_alloc_master(&pdev->dev, sizeof(struct fmc_spi_host));
++ if (NULL == master) {
++ dev_err(&pdev->dev, "No memory for spi_master\n");
++ err = -ENOMEM;
++ goto err_nomem;
++ }
++ host = spi_master_get_devdata(master);
++ memset(host, 0, sizeof(struct fmc_spi_host));
++
++ res0 = platform_get_resource(pdev, IORESOURCE_MEM, 0);
++ if (!res0) {
++ dev_err(&pdev->dev, "cannot get IORESOURCE_MEM 0\n");
++ err = -ENXIO;
++ goto err_no_io_res;
++ }
++
++ host->reg = ioremap(res0->start, resource_size(res0));
++ if (!host->reg) {
++ dev_err(&pdev->dev, "cannot remap register\n");
++ err = -EIO;
++ goto release_mem;
++ }
++
++ dev_dbg(&pdev->dev, "remap phy %x, virt %x \n",(u32)res0->start, (u32)host->reg);
++
++ res1 = platform_get_resource(pdev, IORESOURCE_IO, 0);
++ if (!res1) {
++ dev_err(&pdev->dev, "cannot get IORESOURCE_IO 0\n");
++ return -ENXIO;
++ }
++
++ host->buff = ioremap(res1->start, resource_size(res1));
++ if (!host->buff) {
++ dev_err(&pdev->dev, "cannot remap buffer \n");
++ err = -EIO;
++ goto release_mem;
++ }
++
++ dev_dbg(&pdev->dev, "remap io phy %x, virt %x \n",(u32)res1->start, (u32)host->buff);
++
++ host->master = spi_master_get(master);
++ host->master->bus_num = pdev->id;
++ host->master->num_chipselect = 1;
++ host->dev = &pdev->dev;
++
++ /* Setup the state for bitbang driver */
++ host->master->setup = fmc_spi_setup;
++ host->master->transfer = fmc_spi_transfer;
++ host->master->cleanup = fmc_spi_cleanup;
++
++ /* Find and claim our resources */
++ host->spi_data = pdev->dev.platform_data;
++
++ platform_set_drvdata(pdev, host);
++
++ /* Register our spi controller */
++ err = spi_register_master(host->master);
++ if (err) {
++ dev_err(&pdev->dev, "failed to register SPI master\n");
++ goto err_register;
++ }
++
++ dev_dbg(&pdev->dev, "fmc_spi_probe() return \n\n\n");
++
++ return 0;
++
++err_register:
++ spi_master_put(host->master);
++ iounmap(host->reg);
++ iounmap(host->buff);
++
++release_mem:
++ release_mem_region(res0->start, res0->end - res0->start + 1);
++ release_mem_region(res1->start, res1->end - res1->start + 1);
++
++err_no_io_res:
++ kfree(master);
++ kfree(host);
++
++err_nomem:
++ return err;
++
++}
++
++static int
++fmc_spi_remove(struct platform_device *pdev)
++{
++ struct resource *res0, *res1;
++ struct fmc_spi_host *host = platform_get_drvdata(pdev);
++
++ dev_dbg(host->dev, "fmc_spi_remove()\n");
++
++ if (!host)
++ return -1;
++
++ res0 = platform_get_resource(pdev, IORESOURCE_MEM, 0);
++ res1 = platform_get_resource(pdev, IORESOURCE_IO, 0);
++ release_mem_region(res0->start, res0->end - res0->start + 1);
++ release_mem_region(res1->start, res1->end - res1->start + 1);
++ iounmap(host->reg);
++ iounmap(host->buff);
++
++ platform_set_drvdata(pdev, NULL);
++ spi_unregister_master(host->master);
++ spi_master_put(host->master);
++ return 0;
++}
++
++#ifdef CONFIG_PM
++static int
++fmc_spi_suspend(struct platform_device *pdev, pm_message_t msg)
++{
++ return 0;
++}
++
++static int
++fmc_spi_resume(struct platform_device *pdev)
++{
++ return 0;
++}
++#else
++#define fmc_spi_suspend NULL
++#define fmc_spi_resume NULL
++#endif
++
++static struct platform_driver fmc_spi_driver = {
++ .probe = fmc_spi_probe,
++ .remove = fmc_spi_remove,
++ .suspend = fmc_spi_suspend,
++ .resume = fmc_spi_resume,
++ .driver = {
++ .name = "fmc-spi",
++ .owner = THIS_MODULE,
++ },
++};
++
++static int __init
++fmc_spi_init(void)
++{
++ return platform_driver_register(&fmc_spi_driver);
++}
++
++static void __exit
++fmc_spi_exit(void)
++{
++ platform_driver_unregister(&fmc_spi_driver);
++}
++
++subsys_initcall(fmc_spi_init);
++//module_init(fmc_spi_init);
++module_exit(fmc_spi_exit);
++
++MODULE_DESCRIPTION("FMC SPI Driver");
++MODULE_AUTHOR("Ryan Chen");
++MODULE_LICENSE("GPL");
+diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c
+index 3734dc9..ec88fc7 100644
+--- a/drivers/spi/spi.c
++++ b/drivers/spi/spi.c
+@@ -652,54 +652,61 @@ static u8 *buf;
+ * Performance-sensitive or bulk transfer code should instead use
+ * spi_{async,sync}() calls with dma-safe buffers.
+ */
+-int spi_write_then_read(struct spi_device *spi,
+- const u8 *txbuf, unsigned n_tx,
+- u8 *rxbuf, unsigned n_rx)
+-{
+- static DEFINE_MUTEX(lock);
+-
+- int status;
+- struct spi_message message;
+- struct spi_transfer x;
+- u8 *local_buf;
+-
+- /* Use preallocated DMA-safe buffer. We can't avoid copying here,
+- * (as a pure convenience thing), but we can keep heap costs
+- * out of the hot path ...
+- */
+- if ((n_tx + n_rx) > SPI_BUFSIZ)
+- return -EINVAL;
+-
+- spi_message_init(&message);
+- memset(&x, 0, sizeof x);
+- x.len = n_tx + n_rx;
+- spi_message_add_tail(&x, &message);
+-
+- /* ... unless someone else is using the pre-allocated buffer */
+- if (!mutex_trylock(&lock)) {
+- local_buf = kmalloc(SPI_BUFSIZ, GFP_KERNEL);
+- if (!local_buf)
+- return -ENOMEM;
+- } else
+- local_buf = buf;
+-
+- memcpy(local_buf, txbuf, n_tx);
+- x.tx_buf = local_buf;
+- x.rx_buf = local_buf;
+-
+- /* do the i/o */
+- status = spi_sync(spi, &message);
+- if (status == 0)
+- memcpy(rxbuf, x.rx_buf + n_tx, n_rx);
+-
+- if (x.tx_buf == buf)
+- mutex_unlock(&lock);
+- else
+- kfree(local_buf);
++ int spi_write_then_read(struct spi_device *spi,
++ const u8 *txbuf, unsigned n_tx,
++ u8 *rxbuf, unsigned n_rx)
++ {
++ static DEFINE_MUTEX(lock);
++
++ int status;
++ struct spi_message message;
++ struct spi_transfer x[2];
++ u8 *local_buf;
++
++ /* Use preallocated DMA-safe buffer. We can't avoid copying here,
++ * (as a pure convenience thing), but we can keep heap costs
++ * out of the hot path ...
++ */
++ if ((n_tx + n_rx) > SPI_BUFSIZ)
++ return -EINVAL;
++
++ spi_message_init(&message);
++ memset(x, 0, sizeof x);
++ if (n_tx) {
++ x[0].len = n_tx;
++ spi_message_add_tail(&x[0], &message);
++ }
++ if (n_rx) {
++ x[1].len = n_rx;
++ spi_message_add_tail(&x[1], &message);
++ }
++
++ /* ... unless someone else is using the pre-allocated buffer */
++ if (!mutex_trylock(&lock)) {
++ local_buf = kmalloc(SPI_BUFSIZ, GFP_KERNEL);
++ if (!local_buf)
++ return -ENOMEM;
++ } else
++ local_buf = buf;
++
++ memcpy(local_buf, txbuf, n_tx);
++ x[0].tx_buf = local_buf;
++ x[1].rx_buf = local_buf + n_tx;
++
++ /* do the i/o */
++ status = spi_sync(spi, &message);
++ if (status == 0)
++ memcpy(rxbuf, x[1].rx_buf, n_rx);
++
++ if (x[0].tx_buf == buf)
++ mutex_unlock(&lock);
++ else
++ kfree(local_buf);
++
++ return status;
++ }
++ EXPORT_SYMBOL_GPL(spi_write_then_read);
+
+- return status;
+-}
+-EXPORT_SYMBOL_GPL(spi_write_then_read);
+
+ /*-------------------------------------------------------------------------*/
+
+diff --git a/drivers/usb/Kconfig b/drivers/usb/Kconfig
+index 289d81a..2cba323 100644
+--- a/drivers/usb/Kconfig
++++ b/drivers/usb/Kconfig
+@@ -56,6 +56,7 @@ config USB_ARCH_HAS_EHCI
+ default y if PPC_83xx
+ default y if SOC_AU1200
+ default y if ARCH_IXP4XX
++ default y if ARCH_ASPEED
+ default PCI
+
+ # ARM SA1111 chips have a non-PCI based "OHCI-compatible" USB host interface.
+@@ -102,6 +103,8 @@ source "drivers/usb/wusbcore/Kconfig"
+
+ source "drivers/usb/host/Kconfig"
+
++source "drivers/usb/astuhci/Kconfig"
++
+ source "drivers/usb/musb/Kconfig"
+
+ source "drivers/usb/class/Kconfig"
+diff --git a/drivers/usb/Makefile b/drivers/usb/Makefile
+index 8b7c419..f6f180c 100644
+--- a/drivers/usb/Makefile
++++ b/drivers/usb/Makefile
+@@ -8,6 +8,8 @@ obj-$(CONFIG_USB) += core/
+
+ obj-$(CONFIG_USB_MON) += mon/
+
++obj-$(CONFIG_AST_USB_UHCI_HCD) += astuhci/
++
+ obj-$(CONFIG_PCI) += host/
+ obj-$(CONFIG_USB_EHCI_HCD) += host/
+ obj-$(CONFIG_USB_ISP116X_HCD) += host/
+diff --git a/drivers/usb/astuhci/Kconfig b/drivers/usb/astuhci/Kconfig
+new file mode 100644
+index 0000000..69c6d79
+--- /dev/null
++++ b/drivers/usb/astuhci/Kconfig
+@@ -0,0 +1,56 @@
++#
++# USB Host Controller Drivers
++#
++comment "AST USB Drivers"
++ depends on USB
++
++
++config AST_USB_UHCI_HCD
++ tristate "AST UHCI (USB 1.1) support"
++ depends on USB
++ ---help---
++ The AST Universal Host Controller Interface (UHCI) is standard for
++ USB 1.1 host controller hardware. It is an embedded HC based on AMBA bus.
++ You may want to read <file:Documentation/usb/uhci.txt>.
++
++ To compile this driver as a module, choose M here: the
++ module will be called uhci-hcd.
++
++choice
++ prompt "Config AST USB UHCI Number of Ports"
++ default AST_USB_UHCI_MULTIPORT_4
++
++config AST_USB_UHCI_MULTIPORT_1
++ bool "AST UHCI support 1 ports"
++ depends on AST_USB_UHCI_HCD
++
++config AST_USB_UHCI_MULTIPORT_2
++ bool "AST UHCI support 2 ports"
++ depends on AST_USB_UHCI_HCD
++
++config AST_USB_UHCI_MULTIPORT_4
++ bool "AST UHCI support 4 ports"
++ depends on AST_USB_UHCI_HCD
++
++endchoice
++
++config USB_EHCI_SPLIT_ISO
++ bool "Full speed ISO transactions (EXPERIMENTAL)"
++ depends on USB_EHCI_HCD
++ default n
++ ---help---
++ This code is new and hasn't been used with many different
++ EHCI or USB 2.0 transaction translator implementations.
++ It should work for ISO-OUT transfers, like audio.
++
++config USB_EHCI_ROOT_HUB_TT
++ bool "Root Hub Transaction Translators (EXPERIMENTAL)"
++ depends on USB_EHCI_HCD
++ ---help---
++ Some EHCI chips have vendor-specific extensions to integrate
++ transaction translators, so that no OHCI or UHCI companion
++ controller is needed. It's safe to say "y" even if your
++ controller doesn't support this feature.
++
++ This supports the EHCI implementation from TransDimension Inc.
++
+diff --git a/drivers/usb/astuhci/Makefile b/drivers/usb/astuhci/Makefile
+new file mode 100644
+index 0000000..6b858f7
+--- /dev/null
++++ b/drivers/usb/astuhci/Makefile
+@@ -0,0 +1,10 @@
++#
++# Makefile for USB Host Controller Drivers
++#
++
++ifeq ($(CONFIG_USB_DEBUG),y)
++ EXTRA_CFLAGS += -DDEBUG
++endif
++
++
++obj-$(CONFIG_AST_USB_UHCI_HCD) += uhci-hcd.o
+diff --git a/drivers/usb/astuhci/uhci-debug.c b/drivers/usb/astuhci/uhci-debug.c
+new file mode 100644
+index 0000000..c617644
+--- /dev/null
++++ b/drivers/usb/astuhci/uhci-debug.c
+@@ -0,0 +1,595 @@
++/********************************************************************************
++* File Name : uhci-debug.c
++*
++* port from uhci-debug.c
++* This program is free software; you can redistribute it and/or modify
++* it under the terms of the GNU General Public License as published by the Free Software Foundation;
++* either version 2 of the License, or (at your option) any later version.
++* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
++* without even the implied warranty of MERCHANTABILITY or
++* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
++* You should have received a copy of the GNU General Public License
++* along with this program; if not, write to the Free Software
++* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++********************************************************************************/
++#include <linux/kernel.h>
++#include <linux/debugfs.h>
++#include <linux/smp_lock.h>
++#include <asm/io.h>
++
++#include "uhci-hcd.h"
++
++#define uhci_debug_operations (* (const struct file_operations *) NULL)
++static struct dentry *uhci_debugfs_root;
++
++#ifdef DEBUG
++
++/* Handle REALLY large printks so we don't overflow buffers */
++static void lprintk(char *buf)
++{
++ char *p;
++
++ /* Just write one line at a time */
++ while (buf) {
++ p = strchr(buf, '\n');
++ if (p)
++ *p = 0;
++ printk(KERN_DEBUG "%s\n", buf);
++ buf = p;
++ if (buf)
++ buf++;
++ }
++}
++
++static int uhci_show_td(struct uhci_td *td, char *buf, int len, int space)
++{
++ char *out = buf;
++ char *spid;
++ u32 status, token;
++
++ /* Try to make sure there's enough memory */
++ if (len < 160)
++ return 0;
++
++ status = td_status(td);
++ out += sprintf(out, "%*s[%p] link (%08x) ", space, "", td, le32_to_cpu(td->link));
++ out += sprintf(out, "e%d %s%s%s%s%s%s%s%s%s%sLength=%x ",
++ ((status >> 27) & 3),
++ (status & TD_CTRL_SPD) ? "SPD " : "",
++ (status & TD_CTRL_LS) ? "LS " : "",
++ (status & TD_CTRL_IOC) ? "IOC " : "",
++ (status & TD_CTRL_ACTIVE) ? "Active " : "",
++ (status & TD_CTRL_STALLED) ? "Stalled " : "",
++ (status & TD_CTRL_DBUFERR) ? "DataBufErr " : "",
++ (status & TD_CTRL_BABBLE) ? "Babble " : "",
++ (status & TD_CTRL_NAK) ? "NAK " : "",
++ (status & TD_CTRL_CRCTIMEO) ? "CRC/Timeo " : "",
++ (status & TD_CTRL_BITSTUFF) ? "BitStuff " : "",
++ status & 0x7ff);
++
++ token = td_token(td);
++ switch (uhci_packetid(token)) {
++ case USB_PID_SETUP:
++ spid = "SETUP";
++ break;
++ case USB_PID_OUT:
++ spid = "OUT";
++ break;
++ case USB_PID_IN:
++ spid = "IN";
++ break;
++ default:
++ spid = "?";
++ break;
++ }
++
++ out += sprintf(out, "MaxLen=%x DT%d EndPt=%x Dev=%x, PID=%x(%s) ",
++ token >> 21,
++ ((token >> 19) & 1),
++ (token >> 15) & 15,
++ (token >> 8) & 127,
++ (token & 0xff),
++ spid);
++ out += sprintf(out, "(buf=%08x)\n", le32_to_cpu(td->buffer));
++
++ return out - buf;
++}
++
++static int uhci_show_urbp(struct urb_priv *urbp, char *buf, int len, int space)
++{
++ char *out = buf;
++ struct uhci_td *td;
++ int i, nactive, ninactive;
++ char *ptype;
++
++ if (len < 200)
++ return 0;
++
++ out += sprintf(out, "urb_priv [%p] ", urbp);
++ out += sprintf(out, "urb [%p] ", urbp->urb);
++ out += sprintf(out, "qh [%p] ", urbp->qh);
++ out += sprintf(out, "Dev=%d ", usb_pipedevice(urbp->urb->pipe));
++ out += sprintf(out, "EP=%x(%s) ", usb_pipeendpoint(urbp->urb->pipe),
++ (usb_pipein(urbp->urb->pipe) ? "IN" : "OUT"));
++
++ switch (usb_pipetype(urbp->urb->pipe)) {
++ case PIPE_ISOCHRONOUS: ptype = "ISO"; break;
++ case PIPE_INTERRUPT: ptype = "INT"; break;
++ case PIPE_BULK: ptype = "BLK"; break;
++ default:
++ case PIPE_CONTROL: ptype = "CTL"; break;
++ }
++
++ out += sprintf(out, "%s%s", ptype, (urbp->fsbr ? " FSBR" : ""));
++ out += sprintf(out, " Actlen=%d", urbp->urb->actual_length);
++
++ if (urbp->urb->unlinked)
++ out += sprintf(out, " Unlinked=%d", urbp->urb->unlinked);
++ out += sprintf(out, "\n");
++
++ i = nactive = ninactive = 0;
++ list_for_each_entry(td, &urbp->td_list, list) {
++ if (urbp->qh->type != USB_ENDPOINT_XFER_ISOC &&
++ (++i <= 10 || debug > 2)) {
++ out += sprintf(out, "%*s%d: ", space + 2, "", i);
++ out += uhci_show_td(td, out, len - (out - buf), 0);
++ } else {
++ if (td_status(td) & TD_CTRL_ACTIVE)
++ ++nactive;
++ else
++ ++ninactive;
++ }
++ }
++ if (nactive + ninactive > 0)
++ out += sprintf(out, "%*s[skipped %d inactive and %d active "
++ "TDs]\n",
++ space, "", ninactive, nactive);
++
++ return out - buf;
++}
++
++static int uhci_show_qh(struct uhci_hcd *uhci,
++ struct uhci_qh *qh, char *buf, int len, int space)
++{
++ char *out = buf;
++ int i, nurbs;
++ __le32 element = qh_element(qh);
++ char *qtype;
++
++ /* Try to make sure there's enough memory */
++ if (len < 80 * 7)
++ return 0;
++
++ switch (qh->type) {
++ case USB_ENDPOINT_XFER_ISOC: qtype = "ISO"; break;
++ case USB_ENDPOINT_XFER_INT: qtype = "INT"; break;
++ case USB_ENDPOINT_XFER_BULK: qtype = "BLK"; break;
++ case USB_ENDPOINT_XFER_CONTROL: qtype = "CTL"; break;
++ default: qtype = "Skel" ; break;
++ }
++
++ out += sprintf(out, "%*s[%p] %s QH link (%08x) element (%08x)\n",
++ space, "", qh, qtype,
++ le32_to_cpu(qh->link), le32_to_cpu(element));
++ if (qh->type == USB_ENDPOINT_XFER_ISOC)
++ out += sprintf(out, "%*s period %d phase %d load %d us, "
++ "frame %x desc [%p]\n",
++ space, "", qh->period, qh->phase, qh->load,
++ qh->iso_frame, qh->iso_packet_desc);
++ else if (qh->type == USB_ENDPOINT_XFER_INT)
++ out += sprintf(out, "%*s period %d phase %d load %d us\n",
++ space, "", qh->period, qh->phase, qh->load);
++
++ if (element & UHCI_PTR_QH)
++ out += sprintf(out, "%*s Element points to QH (bug?)\n", space, "");
++
++ if (element & UHCI_PTR_DEPTH)
++ out += sprintf(out, "%*s Depth traverse\n", space, "");
++
++ if (element & cpu_to_le32(8))
++ out += sprintf(out, "%*s Bit 3 set (bug?)\n", space, "");
++
++ if (!(element & ~(UHCI_PTR_QH | UHCI_PTR_DEPTH)))
++ out += sprintf(out, "%*s Element is NULL (bug?)\n", space, "");
++
++ if (list_empty(&qh->queue)) {
++ out += sprintf(out, "%*s queue is empty\n", space, "");
++ if (qh == uhci->skel_async_qh)
++ out += uhci_show_td(uhci->term_td, out,
++ len - (out - buf), 0);
++ } else {
++ struct urb_priv *urbp = list_entry(qh->queue.next,
++ struct urb_priv, node);
++ struct uhci_td *td = list_entry(urbp->td_list.next,
++ struct uhci_td, list);
++
++ if (element != LINK_TO_TD(td))
++ out += sprintf(out, "%*s Element != First TD\n",
++ space, "");
++ i = nurbs = 0;
++ list_for_each_entry(urbp, &qh->queue, node) {
++ if (++i <= 10)
++ out += uhci_show_urbp(urbp, out,
++ len - (out - buf), space + 2);
++ else
++ ++nurbs;
++ }
++ if (nurbs > 0)
++ out += sprintf(out, "%*s Skipped %d URBs\n",
++ space, "", nurbs);
++ }
++
++ if (qh->dummy_td) {
++ out += sprintf(out, "%*s Dummy TD\n", space, "");
++ out += uhci_show_td(qh->dummy_td, out, len - (out - buf), 0);
++ }
++
++ return out - buf;
++}
++
++static int uhci_show_sc(int port, unsigned short status, char *buf, int len)
++{
++ char *out = buf;
++
++ /* Try to make sure there's enough memory */
++ if (len < 160)
++ return 0;
++
++ out += sprintf(out, " stat%d = %04x %s%s%s%s%s%s%s%s%s%s\n",
++ port,
++ status,
++ (status & USBPORTSC_SUSP) ? " Suspend" : "",
++ (status & USBPORTSC_OCC) ? " OverCurrentChange" : "",
++ (status & USBPORTSC_OC) ? " OverCurrent" : "",
++ (status & USBPORTSC_PR) ? " Reset" : "",
++ (status & USBPORTSC_LSDA) ? " LowSpeed" : "",
++ (status & USBPORTSC_RD) ? " ResumeDetect" : "",
++ (status & USBPORTSC_PEC) ? " EnableChange" : "",
++ (status & USBPORTSC_PE) ? " Enabled" : "",
++ (status & USBPORTSC_CSC) ? " ConnectChange" : "",
++ (status & USBPORTSC_CCS) ? " Connected" : "");
++
++ return out - buf;
++}
++
++static int uhci_show_root_hub_state(struct uhci_hcd *uhci, char *buf, int len)
++{
++ char *out = buf;
++ char *rh_state;
++
++ /* Try to make sure there's enough memory */
++ if (len < 60)
++ return 0;
++
++ switch (uhci->rh_state) {
++ case UHCI_RH_RESET:
++ rh_state = "reset"; break;
++ case UHCI_RH_SUSPENDED:
++ rh_state = "suspended"; break;
++ case UHCI_RH_AUTO_STOPPED:
++ rh_state = "auto-stopped"; break;
++ case UHCI_RH_RESUMING:
++ rh_state = "resuming"; break;
++ case UHCI_RH_SUSPENDING:
++ rh_state = "suspending"; break;
++ case UHCI_RH_RUNNING:
++ rh_state = "running"; break;
++ case UHCI_RH_RUNNING_NODEVS:
++ rh_state = "running, no devs"; break;
++ default:
++ rh_state = "?"; break;
++ }
++ out += sprintf(out, "Root-hub state: %s FSBR: %d\n",
++ rh_state, uhci->fsbr_is_on);
++ return out - buf;
++}
++
++static int uhci_show_status(struct uhci_hcd *uhci, char *buf, int len)
++{
++ char *out = buf;
++ unsigned long io_addr = uhci->io_addr;
++ unsigned short usbcmd, usbstat, usbint, usbfrnum;
++ unsigned int flbaseadd;
++ unsigned char sof;
++ unsigned short portsc1, portsc2;
++
++ /* Try to make sure there's enough memory */
++ if (len < 80 * 9)
++ return 0;
++
++ usbcmd = inw(io_addr + 0);
++ usbstat = inw(io_addr + 2);
++ usbint = inw(io_addr + 4);
++ usbfrnum = inw(io_addr + 6);
++ flbaseadd = inl(io_addr + 8);
++ sof = inb(io_addr + 12);
++ portsc1 = inw(io_addr + 16);
++ portsc2 = inw(io_addr + 18);
++
++ out += sprintf(out, " usbcmd = %04x %s%s%s%s%s%s%s%s\n",
++ usbcmd,
++ (usbcmd & USBCMD_MAXP) ? "Maxp64 " : "Maxp32 ",
++ (usbcmd & USBCMD_CF) ? "CF " : "",
++ (usbcmd & USBCMD_SWDBG) ? "SWDBG " : "",
++ (usbcmd & USBCMD_FGR) ? "FGR " : "",
++ (usbcmd & USBCMD_EGSM) ? "EGSM " : "",
++ (usbcmd & USBCMD_GRESET) ? "GRESET " : "",
++ (usbcmd & USBCMD_HCRESET) ? "HCRESET " : "",
++ (usbcmd & USBCMD_RS) ? "RS " : "");
++
++ out += sprintf(out, " usbstat = %04x %s%s%s%s%s%s\n",
++ usbstat,
++ (usbstat & USBSTS_HCH) ? "HCHalted " : "",
++ (usbstat & USBSTS_HCPE) ? "HostControllerProcessError " : "",
++ (usbstat & USBSTS_HSE) ? "HostSystemError " : "",
++ (usbstat & USBSTS_RD) ? "ResumeDetect " : "",
++ (usbstat & USBSTS_ERROR) ? "USBError " : "",
++ (usbstat & USBSTS_USBINT) ? "USBINT " : "");
++
++ out += sprintf(out, " usbint = %04x\n", usbint);
++ out += sprintf(out, " usbfrnum = (%d)%03x\n", (usbfrnum >> 10) & 1,
++ 0xfff & (4*(unsigned int)usbfrnum));
++ out += sprintf(out, " flbaseadd = %08x\n", flbaseadd);
++ out += sprintf(out, " sof = %02x\n", sof);
++ out += uhci_show_sc(1, portsc1, out, len - (out - buf));
++ out += uhci_show_sc(2, portsc2, out, len - (out - buf));
++ out += sprintf(out, "Most recent frame: %x (%d) "
++ "Last ISO frame: %x (%d)\n",
++ uhci->frame_number, uhci->frame_number & 1023,
++ uhci->last_iso_frame, uhci->last_iso_frame & 1023);
++
++ return out - buf;
++}
++
++static int uhci_sprint_schedule(struct uhci_hcd *uhci, char *buf, int len)
++{
++ char *out = buf;
++ int i, j;
++ struct uhci_qh *qh;
++ struct uhci_td *td;
++ struct list_head *tmp, *head;
++ int nframes, nerrs;
++ __le32 link;
++ __le32 fsbr_link;
++
++ static const char * const qh_names[] = {
++ "unlink", "iso", "int128", "int64", "int32", "int16",
++ "int8", "int4", "int2", "async", "term"
++ };
++
++ out += uhci_show_root_hub_state(uhci, out, len - (out - buf));
++ out += sprintf(out, "HC status\n");
++ out += uhci_show_status(uhci, out, len - (out - buf));
++
++ out += sprintf(out, "Periodic load table\n");
++ for (i = 0; i < MAX_PHASE; ++i) {
++ out += sprintf(out, "\t%d", uhci->load[i]);
++ if (i % 8 == 7)
++ *out++ = '\n';
++ }
++ out += sprintf(out, "Total: %d, #INT: %d, #ISO: %d\n",
++ uhci->total_load,
++ uhci_to_hcd(uhci)->self.bandwidth_int_reqs,
++ uhci_to_hcd(uhci)->self.bandwidth_isoc_reqs);
++ if (debug <= 1)
++ return out - buf;
++
++ out += sprintf(out, "Frame List\n");
++ nframes = 10;
++ nerrs = 0;
++ for (i = 0; i < UHCI_NUMFRAMES; ++i) {
++ __le32 qh_dma;
++
++ j = 0;
++ td = uhci->frame_cpu[i];
++ link = uhci->frame[i];
++ if (!td)
++ goto check_link;
++
++ if (nframes > 0) {
++ out += sprintf(out, "- Frame %d -> (%08x)\n",
++ i, le32_to_cpu(link));
++ j = 1;
++ }
++
++ head = &td->fl_list;
++ tmp = head;
++ do {
++ td = list_entry(tmp, struct uhci_td, fl_list);
++ tmp = tmp->next;
++ if (link != LINK_TO_TD(td)) {
++ if (nframes > 0)
++ out += sprintf(out, " link does "
++ "not match list entry!\n");
++ else
++ ++nerrs;
++ }
++ if (nframes > 0)
++ out += uhci_show_td(td, out,
++ len - (out - buf), 4);
++ link = td->link;
++ } while (tmp != head);
++
++check_link:
++ qh_dma = uhci_frame_skel_link(uhci, i);
++ if (link != qh_dma) {
++ if (nframes > 0) {
++ if (!j) {
++ out += sprintf(out,
++ "- Frame %d -> (%08x)\n",
++ i, le32_to_cpu(link));
++ j = 1;
++ }
++ out += sprintf(out, " link does not match "
++ "QH (%08x)!\n", le32_to_cpu(qh_dma));
++ } else
++ ++nerrs;
++ }
++ nframes -= j;
++ }
++ if (nerrs > 0)
++ out += sprintf(out, "Skipped %d bad links\n", nerrs);
++
++ out += sprintf(out, "Skeleton QHs\n");
++
++ fsbr_link = 0;
++ for (i = 0; i < UHCI_NUM_SKELQH; ++i) {
++ int cnt = 0;
++
++ qh = uhci->skelqh[i];
++ out += sprintf(out, "- skel_%s_qh\n", qh_names[i]); \
++ out += uhci_show_qh(uhci, qh, out, len - (out - buf), 4);
++
++ /* Last QH is the Terminating QH, it's different */
++ if (i == SKEL_TERM) {
++ if (qh_element(qh) != LINK_TO_TD(uhci->term_td))
++ out += sprintf(out, " skel_term_qh element is not set to term_td!\n");
++ link = fsbr_link;
++ if (!link)
++ link = LINK_TO_QH(uhci->skel_term_qh);
++ goto check_qh_link;
++ }
++
++ head = &qh->node;
++ tmp = head->next;
++
++ while (tmp != head) {
++ qh = list_entry(tmp, struct uhci_qh, node);
++ tmp = tmp->next;
++ if (++cnt <= 10)
++ out += uhci_show_qh(uhci, qh, out,
++ len - (out - buf), 4);
++ if (!fsbr_link && qh->skel >= SKEL_FSBR)
++ fsbr_link = LINK_TO_QH(qh);
++ }
++ if ((cnt -= 10) > 0)
++ out += sprintf(out, " Skipped %d QHs\n", cnt);
++
++ link = UHCI_PTR_TERM;
++ if (i <= SKEL_ISO)
++ ;
++ else if (i < SKEL_ASYNC)
++ link = LINK_TO_QH(uhci->skel_async_qh);
++ else if (!uhci->fsbr_is_on)
++ ;
++ else
++ link = LINK_TO_QH(uhci->skel_term_qh);
++check_qh_link:
++ if (qh->link != link)
++ out += sprintf(out, " last QH not linked to next skeleton!\n");
++ }
++
++ return out - buf;
++}
++
++#ifdef CONFIG_DEBUG_FS
++
++#define MAX_OUTPUT (64 * 1024)
++
++struct uhci_debug {
++ int size;
++ char *data;
++};
++
++static int uhci_debug_open(struct inode *inode, struct file *file)
++{
++ struct uhci_hcd *uhci = inode->i_private;
++ struct uhci_debug *up;
++ int ret = -ENOMEM;
++ unsigned long flags;
++
++ lock_kernel();
++ up = kmalloc(sizeof(*up), GFP_KERNEL);
++ if (!up)
++ goto out;
++
++ up->data = kmalloc(MAX_OUTPUT, GFP_KERNEL);
++ if (!up->data) {
++ kfree(up);
++ goto out;
++ }
++
++ up->size = 0;
++ spin_lock_irqsave(&uhci->lock, flags);
++ if (uhci->is_initialized)
++ up->size = uhci_sprint_schedule(uhci, up->data, MAX_OUTPUT);
++ spin_unlock_irqrestore(&uhci->lock, flags);
++
++ file->private_data = up;
++
++ ret = 0;
++out:
++ unlock_kernel();
++ return ret;
++}
++
++static loff_t uhci_debug_lseek(struct file *file, loff_t off, int whence)
++{
++ struct uhci_debug *up;
++ loff_t new = -1;
++
++ lock_kernel();
++ up = file->private_data;
++
++ switch (whence) {
++ case 0:
++ new = off;
++ break;
++ case 1:
++ new = file->f_pos + off;
++ break;
++ }
++ if (new < 0 || new > up->size) {
++ unlock_kernel();
++ return -EINVAL;
++ }
++ unlock_kernel();
++ return (file->f_pos = new);
++}
++
++static ssize_t uhci_debug_read(struct file *file, char __user *buf,
++ size_t nbytes, loff_t *ppos)
++{
++ struct uhci_debug *up = file->private_data;
++ return simple_read_from_buffer(buf, nbytes, ppos, up->data, up->size);
++}
++
++static int uhci_debug_release(struct inode *inode, struct file *file)
++{
++ struct uhci_debug *up = file->private_data;
++
++ kfree(up->data);
++ kfree(up);
++
++ return 0;
++}
++
++#undef uhci_debug_operations
++static const struct file_operations uhci_debug_operations = {
++ .owner = THIS_MODULE,
++ .open = uhci_debug_open,
++ .llseek = uhci_debug_lseek,
++ .read = uhci_debug_read,
++ .release = uhci_debug_release,
++};
++
++#endif /* CONFIG_DEBUG_FS */
++
++#else /* DEBUG */
++
++static inline void lprintk(char *buf)
++{}
++
++static inline int uhci_show_qh(struct uhci_hcd *uhci,
++ struct uhci_qh *qh, char *buf, int len, int space)
++{
++ return 0;
++}
++
++static inline int uhci_sprint_schedule(struct uhci_hcd *uhci,
++ char *buf, int len)
++{
++ return 0;
++}
++
++#endif
+diff --git a/drivers/usb/astuhci/uhci-hcd.c b/drivers/usb/astuhci/uhci-hcd.c
+new file mode 100644
+index 0000000..fcfb6dbb
+--- /dev/null
++++ b/drivers/usb/astuhci/uhci-hcd.c
+@@ -0,0 +1,1229 @@
++/********************************************************************************
++* File Name : uhci-hcd.c
++*
++* port from uhci-hcd.c
++* This program is free software; you can redistribute it and/or modify
++* it under the terms of the GNU General Public License as published by the Free Software Foundation;
++* either version 2 of the License, or (at your option) any later version.
++* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
++* without even the implied warranty of MERCHANTABILITY or
++* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
++* You should have received a copy of the GNU General Public License
++* along with this program; if not, write to the Free Software
++* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++********************************************************************************/
++
++#include <linux/module.h>
++#include <linux/pci.h>
++#include <linux/kernel.h>
++#include <linux/init.h>
++#include <linux/delay.h>
++#include <linux/ioport.h>
++#include <linux/slab.h>
++#include <linux/errno.h>
++#include <linux/unistd.h>
++#include <linux/interrupt.h>
++#include <linux/spinlock.h>
++#include <linux/debugfs.h>
++#include <linux/pm.h>
++#include <linux/dmapool.h>
++#include <linux/dma-mapping.h>
++#include <linux/usb.h>
++#include <linux/bitops.h>
++#include <linux/dmi.h>
++#include <linux/platform_device.h>
++
++#include <asm/uaccess.h>
++#include <asm/io.h>
++#include <asm/irq.h>
++#include <asm/system.h>
++
++#include <mach/platform.h>
++#include "../core/hcd.h"
++#include "uhci-hcd.h"
++//#include "pci-quirks.h"
++
++/*
++ * Version Information
++ */
++#define DRIVER_AUTHOR "Linus 'Frodo Rabbit' Torvalds, Johannes Erdfelt, \
++Randy Dunlap, Georg Acher, Deti Fliegl, Thomas Sailer, Roman Weissgaerber, \
++Alan Stern"
++#define DRIVER_DESC "USB Universal Host Controller Interface driver"
++
++/* for flakey hardware, ignore overcurrent indicators */
++static int ignore_oc;
++module_param(ignore_oc, bool, S_IRUGO);
++MODULE_PARM_DESC(ignore_oc, "ignore hardware overcurrent indications");
++
++/*
++ * debug = 0, no debugging messages
++ * debug = 1, dump failed URBs except for stalls
++ * debug = 2, dump all failed URBs (including stalls)
++ * show all queues in /debug/uhci/[pci_addr]
++ * debug = 3, show all TDs in URBs when dumping
++ */
++#ifdef DEBUG
++#define DEBUG_CONFIGURED 1
++static int debug = 1;
++module_param(debug, int, S_IRUGO | S_IWUSR);
++MODULE_PARM_DESC(debug, "Debug level");
++
++#else
++#define DEBUG_CONFIGURED 0
++#define debug 0
++#endif
++
++
++
++static char *errbuf;
++#define ERRBUF_LEN (32 * 1024)
++
++static struct kmem_cache *uhci_up_cachep; /* urb_priv */
++
++void suspend_rh(struct uhci_hcd *uhci, enum uhci_rh_state new_state);
++void wakeup_rh(struct uhci_hcd *uhci);
++void uhci_get_current_frame_number(struct uhci_hcd *uhci);
++
++void uhci_reset_hc(struct uhci_hcd *uhci);
++int uhci_check_and_reset_hc(struct uhci_hcd *uhci);
++
++/*
++ * Calculate the link pointer DMA value for the first Skeleton QH in a frame.
++ */
++static __le32 uhci_frame_skel_link(struct uhci_hcd *uhci, int frame)
++{
++ int skelnum;
++
++ /*
++ * The interrupt queues will be interleaved as evenly as possible.
++ * There's not much to be done about period-1 interrupts; they have
++ * to occur in every frame. But we can schedule period-2 interrupts
++ * in odd-numbered frames, period-4 interrupts in frames congruent
++ * to 2 (mod 4), and so on. This way each frame only has two
++ * interrupt QHs, which will help spread out bandwidth utilization.
++ *
++ * ffs (Find First bit Set) does exactly what we need:
++ * 1,3,5,... => ffs = 0 => use period-2 QH = skelqh[8],
++ * 2,6,10,... => ffs = 1 => use period-4 QH = skelqh[7], etc.
++ * ffs >= 7 => not on any high-period queue, so use
++ * period-1 QH = skelqh[9].
++ * Add in UHCI_NUMFRAMES to insure at least one bit is set.
++ */
++ skelnum = 8 - (int) __ffs(frame | UHCI_NUMFRAMES);
++ if (skelnum <= 1)
++ skelnum = 9;
++ return LINK_TO_QH(uhci->skelqh[skelnum]);
++}
++
++#include "uhci-debug.c"
++#include "uhci-q.c"
++#include "uhci-hub.c"
++
++/*
++ * Finish up a host controller reset and update the recorded state.
++ */
++void finish_reset(struct uhci_hcd *uhci)
++{
++ int port;
++
++ /* HCRESET doesn't affect the Suspend, Reset, and Resume Detect
++ * bits in the port status and control registers.
++ * We have to clear them by hand.
++ */
++ for (port = 0; port < uhci->rh_numports; ++port)
++ writel(0, uhci->regbase + USBPORTSC1 + (port * 1));
++
++ uhci->port_c_suspend = uhci->resuming_ports = 0;
++ uhci->rh_state = UHCI_RH_RESET;
++ uhci->is_stopped = UHCI_IS_STOPPED;
++ uhci_to_hcd(uhci)->state = HC_STATE_HALT;
++ uhci_to_hcd(uhci)->poll_rh = 0;
++
++ uhci->dead = 0; /* Full reset resurrects the controller */
++}
++
++/*
++ * Last rites for a defunct/nonfunctional controller
++ * or one we don't want to use any more.
++ */
++void uhci_hc_died(struct uhci_hcd *uhci)
++{
++ uhci_get_current_frame_number(uhci);
++//yriver
++// uhci_reset_hc(to_pci_dev(uhci_dev(uhci)), uhci->io_addr);
++ uhci_reset_hc(uhci);
++ finish_reset(uhci);
++ uhci->dead = 1;
++
++ /* The current frame may already be partway finished */
++ ++uhci->frame_number;
++}
++
++/*
++ * Initialize a controller that was newly discovered or has lost power
++ * or otherwise been reset while it was suspended. In none of these cases
++ * can we be sure of its previous state.
++ */
++void check_and_reset_hc(struct uhci_hcd *uhci)
++{
++//yriver
++// if (uhci_check_and_reset_hc(to_pci_dev(uhci_dev(uhci)), uhci->io_addr))
++ if (uhci_check_and_reset_hc(uhci))
++ finish_reset(uhci);
++}
++
++/*
++ * Store the basic register settings needed by the controller.
++ */
++void configure_hc(struct uhci_hcd *uhci)
++{
++ /* Set the frame length to the default: 1 ms exactly */
++// outb(USBSOF_DEFAULT, uhci->io_addr + USBSOF);
++ writel(USBSOF_DEFAULT, uhci->regbase + USBSOF);
++
++ /* Store the frame list base address */
++// outl(uhci->frame_dma_handle, uhci->io_addr + USBFLBASEADD);
++ writel(uhci->frame_dma_handle, uhci->regbase + USBFLBASEADD);
++
++ /* Set the current frame number */
++// outw(uhci->frame_number & UHCI_MAX_SOF_NUMBER,
++// uhci->io_addr + USBFRNUM);
++ writel(uhci->frame_number & UHCI_MAX_SOF_NUMBER,
++ uhci->regbase + USBFRNUM);
++
++ /* Mark controller as not halted before we enable interrupts */
++ uhci_to_hcd(uhci)->state = HC_STATE_SUSPENDED;
++ mb();
++ /* Enable PIRQ */
++//yriver
++// pci_write_config_word(to_pci_dev(uhci_dev(uhci)), USBLEGSUP,
++// USBLEGSUP_DEFAULT);
++}
++
++
++int resume_detect_interrupts_are_broken(struct uhci_hcd *uhci)
++{
++/*
++
++ int port;
++
++
++ if (ignore_oc)
++ return 1;
++
++ switch (to_pci_dev(uhci_dev(uhci))->vendor) {
++ default:
++ break;
++
++ case PCI_VENDOR_ID_GENESYS:
++ return 1;
++
++ case PCI_VENDOR_ID_INTEL:
++ for (port = 0; port < uhci->rh_numports; ++port) {
++ if (inw(uhci->io_addr + USBPORTSC1 + port * 2) &
++ USBPORTSC_OC)
++ return 1;
++ }
++ break;
++ }
++*/
++ return 0;
++}
++
++int global_suspend_mode_is_broken(struct uhci_hcd *uhci)
++{
++ int port;
++ const char *sys_info;
++ static char bad_Asus_board[] = "A7V8X";
++
++ /* One of Asus's motherboards has a bug which causes it to
++ * wake up immediately from suspend-to-RAM if any of the ports
++ * are connected. In such cases we will not set EGSM.
++ */
++ sys_info = dmi_get_system_info(DMI_BOARD_NAME);
++ if (sys_info && !strcmp(sys_info, bad_Asus_board)) {
++ for (port = 0; port < uhci->rh_numports; ++port) {
++//yriver
++// if (inw(uhci->io_addr + USBPORTSC1 + port * 2) &
++ if (readl(uhci->regbase + USBPORTSC1 + port * 1) &
++ USBPORTSC_CCS)
++ return 1;
++ }
++ }
++
++ return 0;
++}
++
++void suspend_rh(struct uhci_hcd *uhci, enum uhci_rh_state new_state)
++__releases(uhci->lock)
++__acquires(uhci->lock)
++{
++ int auto_stop;
++ int int_enable, egsm_enable, wakeup_enable;
++ struct usb_device *rhdev = uhci_to_hcd(uhci)->self.root_hub;
++
++ auto_stop = (new_state == UHCI_RH_AUTO_STOPPED);
++ dev_dbg(&rhdev->dev, "%s%s\n", __func__,
++ (auto_stop ? " (auto-stop)" : ""));
++
++ /* Start off by assuming Resume-Detect interrupts and EGSM work
++ * and that remote wakeups should be enabled.
++ */
++ egsm_enable = USBCMD_EGSM;
++ uhci->RD_enable = 1;
++ int_enable = USBINTR_RESUME;
++ wakeup_enable = 1;
++/*
++ if (auto_stop) {
++ if (!device_may_wakeup(&rhdev->dev))
++ int_enable = 0;
++
++ } else {
++#ifdef CONFIG_PM
++ if (!rhdev->do_remote_wakeup)
++ wakeup_enable = 0;
++#endif
++ }
++
++ if (!wakeup_enable || global_suspend_mode_is_broken(uhci))
++ egsm_enable = 0;
++*/
++ /* If we're ignoring wakeup events then there's no reason to
++ * enable Resume-Detect interrupts. We also shouldn't enable
++ * them if they are broken or disallowed.
++ *
++ * This logic may lead us to enabling RD but not EGSM. The UHCI
++ * spec foolishly says that RD works only when EGSM is on, but
++ * there's no harm in enabling it anyway -- perhaps some chips
++ * will implement it!
++ */
++//yriver
++// if (!wakeup_enable || resume_detect_interrupts_are_broken(uhci) ||
++// !int_enable)
++// uhci->RD_enable = int_enable = 0;
++
++// outw(int_enable, uhci->io_addr + USBINTR);
++// outw(egsm_enable | USBCMD_CF, uhci->io_addr + USBCMD);
++ writel(int_enable, uhci->regbase + USBINTR);
++// writel(egsm_enable | USBCMD_CF, uhci->regbase + USBCMD);
++ writel(USBCMD_EGSM | USBCMD_CF, uhci->regbase + USBCMD);
++ mb();
++ udelay(5);
++
++ /* If we're auto-stopping then no devices have been attached
++ * for a while, so there shouldn't be any active URBs and the
++ * controller should stop after a few microseconds. Otherwise
++ * we will give the controller one frame to stop.
++ */
++//yriver
++// if (!auto_stop && !(inw(uhci->io_addr + USBSTS) & USBSTS_HCH)) {
++ if (!auto_stop && !(readl(uhci->regbase + USBSTS) & USBSTS_HCH)) {
++ uhci->rh_state = UHCI_RH_SUSPENDING;
++ spin_unlock_irq(&uhci->lock);
++ msleep(1);
++ spin_lock_irq(&uhci->lock);
++ if (uhci->dead)
++ return;
++ }
++//yriver
++// if (!(inw(uhci->io_addr + USBSTS) & USBSTS_HCH))
++// if (!(readl(uhci->regbase + USBSTS) & USBSTS_HCH))
++// dev_warn(uhci_dev(uhci), "Controller not stopped yet!\n");
++
++ uhci_get_current_frame_number(uhci);
++
++ uhci->rh_state = new_state;
++ uhci->is_stopped = UHCI_IS_STOPPED;
++
++ /* If interrupts don't work and remote wakeup is enabled then
++ * the suspended root hub needs to be polled.
++ */
++//yriver
++// uhci_to_hcd(uhci)->poll_rh = (!int_enable && wakeup_enable);
++ uhci_to_hcd(uhci)->poll_rh = !int_enable;
++
++ uhci_scan_schedule(uhci);
++ uhci_fsbr_off(uhci);
++}
++
++void start_rh(struct uhci_hcd *uhci)
++{
++ uhci_to_hcd(uhci)->state = HC_STATE_RUNNING;
++ uhci->is_stopped = 0;
++ /* Mark it configured and running with a 64-byte max packet.
++ * All interrupts are enabled, even though RESUME won't do anything.
++ */
++//yriver
++// outw(USBCMD_RS | USBCMD_CF | USBCMD_MAXP, uhci->io_addr + USBCMD);
++// outw(USBINTR_TIMEOUT | USBINTR_RESUME | USBINTR_IOC | USBINTR_SP,
++// uhci->io_addr + USBINTR);
++
++ writel(USBCMD_RS | USBCMD_CF | USBCMD_MAXP, uhci->regbase + USBCMD);
++ writel(USBINTR_TIMEOUT | USBINTR_RESUME | USBINTR_IOC | USBINTR_SP,
++ uhci->regbase + USBINTR);
++ mb();
++ uhci->rh_state = UHCI_RH_RUNNING;
++ uhci_to_hcd(uhci)->poll_rh = 1;
++}
++
++void wakeup_rh(struct uhci_hcd *uhci)
++__releases(uhci->lock)
++__acquires(uhci->lock)
++{
++ dev_dbg(&uhci_to_hcd(uhci)->self.root_hub->dev,
++ "%s%s\n", __func__,
++ uhci->rh_state == UHCI_RH_AUTO_STOPPED ?
++ " (auto-start)" : "");
++
++ /* If we are auto-stopped then no devices are attached so there's
++ * no need for wakeup signals. Otherwise we send Global Resume
++ * for 20 ms.
++ */
++ if (uhci->rh_state == UHCI_RH_SUSPENDED) {
++ uhci->rh_state = UHCI_RH_RESUMING;
++ }
++
++ start_rh(uhci);
++
++ /* Restart root hub polling */
++ mod_timer(&uhci_to_hcd(uhci)->rh_timer, jiffies);
++}
++
++void wakeup_hc(struct uhci_hcd *uhci) {
++// printk("wake_uhci\n");
++ wakeup_rh(uhci);
++
++
++}
++
++irqreturn_t uhci_irq(struct usb_hcd *hcd)
++{
++ struct uhci_hcd *uhci = hcd_to_uhci(hcd);
++ unsigned short status;
++
++ /*
++ * Read the interrupt status, and write it back to clear the
++ * interrupt cause. Contrary to the UHCI specification, the
++ * "HC Halted" status bit is persistent: it is RO, not R/WC.
++ */
++//yriver
++// status = inw(uhci->io_addr + USBSTS);
++ status = readl(uhci->regbase + USBSTS);
++ if (!(status & ~USBSTS_HCH)) /* shared interrupt, not mine */
++ return IRQ_NONE;
++// outw(status, uhci->io_addr + USBSTS); /* Clear it */
++ writel(status, uhci->regbase + USBSTS); /* Clear it */
++
++ if (status & ~(USBSTS_USBINT | USBSTS_ERROR | USBSTS_RD)) {
++ if (status & USBSTS_HSE)
++ dev_err(uhci_dev(uhci), "host system error, "
++ "PCI problems?\n");
++ if (status & USBSTS_HCPE)
++ dev_err(uhci_dev(uhci), "host controller process "
++ "error, something bad happened!\n");
++ if (status & USBSTS_HCH) {
++ spin_lock(&uhci->lock);
++ if (uhci->rh_state >= UHCI_RH_RUNNING) {
++ dev_err(uhci_dev(uhci),
++ "host controller halted, "
++ "very bad!\n");
++ if (debug > 1 && errbuf) {
++ /* Print the schedule for debugging */
++ uhci_sprint_schedule(uhci,
++ errbuf, ERRBUF_LEN);
++ lprintk(errbuf);
++ }
++ uhci_hc_died(uhci);
++
++ /* Force a callback in case there are
++ * pending unlinks */
++//yriver
++// mod_timer(&hcd->rh_timer, jiffies);
++ mod_timer(&uhci_to_hcd(uhci)->rh_timer, jiffies);
++ }
++ spin_unlock(&uhci->lock);
++ }
++ }
++
++ if (status & USBSTS_RD)
++ usb_hcd_poll_rh_status(hcd);
++ else {
++ spin_lock(&uhci->lock);
++ uhci_scan_schedule(uhci);
++ spin_unlock(&uhci->lock);
++ }
++
++ return IRQ_HANDLED;
++}
++
++/*
++ * Store the current frame number in uhci->frame_number if the controller
++ * is runnning. Expand from 11 bits (of which we use only 10) to a
++ * full-sized integer.
++ *
++ * Like many other parts of the driver, this code relies on being polled
++ * more than once per second as long as the controller is running.
++ */
++void uhci_get_current_frame_number(struct uhci_hcd *uhci)
++{
++ if (!uhci->is_stopped) {
++ unsigned delta;
++//yriver
++// delta = (inw(uhci->io_addr + USBFRNUM) - uhci->frame_number) &
++// (UHCI_NUMFRAMES - 1);
++ delta = (readl(uhci->regbase + USBFRNUM) - uhci->frame_number) &
++ (UHCI_NUMFRAMES - 1);
++ uhci->frame_number += delta;
++ }
++}
++
++/*
++ * De-allocate all resources
++ */
++void release_uhci(struct uhci_hcd *uhci)
++{
++ int i;
++
++ if (DEBUG_CONFIGURED) {
++ spin_lock_irq(&uhci->lock);
++ uhci->is_initialized = 0;
++ spin_unlock_irq(&uhci->lock);
++
++ debugfs_remove(uhci->dentry);
++ }
++
++ for (i = 0; i < UHCI_NUM_SKELQH; i++)
++ uhci_free_qh(uhci, uhci->skelqh[i]);
++
++ uhci_free_td(uhci, uhci->term_td);
++
++ dma_pool_destroy(uhci->qh_pool);
++
++ dma_pool_destroy(uhci->td_pool);
++
++ kfree(uhci->frame_cpu);
++
++ dma_free_coherent(uhci_dev(uhci),
++ UHCI_NUMFRAMES * sizeof(*uhci->frame),
++ uhci->frame, uhci->frame_dma_handle);
++}
++
++void uhci_reset_hc(struct uhci_hcd *uhci)
++{
++ /* Reset the HC - this will force us to get a
++ * new notification of any already connected
++ * ports due to the virtual disconnect that it
++ * implies.
++ */
++ writel(0,(uhci->regbase + USBINTR));
++ writel(USBCMD_GRESET,(uhci->regbase + USBCMD));
++ mdelay(50);
++
++ writel(0,(uhci->regbase + USBCMD));
++ mdelay(10);
++}
++
++int uhci_check_and_reset_hc(struct uhci_hcd *uhci)
++{
++ unsigned int cmd, intr;
++
++ cmd = readl((uhci->regbase + USBCMD));
++ if ((cmd & USBCMD_RS) || !(cmd & USBCMD_CF) ||
++ !(cmd & USBCMD_EGSM)) {
++ printk("%s: cmd = 0x%04x\n", __FUNCTION__, cmd);
++ goto reset_needed;
++ }
++
++ //intr = inw(base + UHCI_USBINTR);
++ intr = readl((uhci->regbase + USBINTR));
++ if (intr & (~USBINTR_RESUME)) {
++ printk("%s: intr = 0x%04x\n", __FUNCTION__, intr);
++ goto reset_needed;
++ }
++ return 0;
++
++reset_needed:
++// printk("Performing full reset\n");
++ uhci_reset_hc(uhci);
++ return 1;
++}
++
++int uhci_reset(struct usb_hcd *hcd)
++{
++ struct uhci_hcd *uhci = hcd_to_uhci(hcd);
++
++
++#ifdef CONFIG_GUC_USB_UHCI_MULTIPORT_2
++ uhci->rh_numports = 2;
++#elif defined (CONFIG_GUC_USB_UHCI_MULTIPORT_4)
++ uhci->rh_numports = 4;
++#else
++ uhci->rh_numports = 1;
++#endif
++
++ /* Kick BIOS off this hardware and reset if the controller
++ * isn't already safely quiescent.
++ */
++ check_and_reset_hc(uhci);
++ return 0;
++}
++
++int uhci_init(struct usb_hcd *hcd)
++{
++ struct uhci_hcd *uhci = hcd_to_uhci(hcd);
++ //unsigned io_size = (unsigned) hcd->rsrc_len;
++ int port;
++
++ uhci->io_addr = (unsigned long) hcd->rsrc_start;
++
++ /* The UHCI spec says devices must have 2 ports, and goes on to say
++ * they may have more but gives no way to determine how many there
++ * are. However according to the UHCI spec, Bit 7 of the port
++ * status and control register is always set to 1. So we try to
++ * use this to our advantage. Another common failure mode when
++ * a nonexistent register is addressed is to return all ones, so
++ * we test for that also.
++ */
++ for (port = 0; port < UHCI_RH_MAXCHILD; port++) {
++ unsigned int portstatus;
++//yriver
++// portstatus = inw(uhci->io_addr + USBPORTSC1 + (port * 2));
++ portstatus = readl(uhci->regbase + USBPORTSC1 + (port * 1));
++ if (!(portstatus & 0x0080) || portstatus == 0xffff)
++ break;
++ }
++ if (debug) {
++ dev_info(uhci_dev(uhci), "detected %d ports\n", port);
++ }
++
++ /* Anything greater than 7 is weird so we'll ignore it. */
++ if (port > UHCI_RH_MAXCHILD) {
++ dev_info(uhci_dev(uhci), "port count misdetected? "
++ "forcing to 2 ports\n");
++ port = 2;
++ }
++ uhci->rh_numports = port;
++
++ /* Kick BIOS off this hardware and reset if the controller
++ * isn't already safely quiescent.
++ */
++ check_and_reset_hc(uhci);
++ return 0;
++}
++
++/* Make sure the controller is quiescent and that we're not using it
++ * any more. This is mainly for the benefit of programs which, like kexec,
++ * expect the hardware to be idle: not doing DMA or generating IRQs.
++ *
++ * This routine may be called in a damaged or failing kernel. Hence we
++ * do not acquire the spinlock before shutting down the controller.
++ */
++void uhci_shutdown(struct pci_dev *pdev)
++{
++ struct usb_hcd *hcd = (struct usb_hcd *) pci_get_drvdata(pdev);
++
++ uhci_hc_died(hcd_to_uhci(hcd));
++}
++
++/*
++ * Allocate a frame list, and then setup the skeleton
++ *
++ * The hardware doesn't really know any difference
++ * in the queues, but the order does matter for the
++ * protocols higher up. The order in which the queues
++ * are encountered by the hardware is:
++ *
++ * - All isochronous events are handled before any
++ * of the queues. We don't do that here, because
++ * we'll create the actual TD entries on demand.
++ * - The first queue is the high-period interrupt queue.
++ * - The second queue is the period-1 interrupt and async
++ * (low-speed control, full-speed control, then bulk) queue.
++ * - The third queue is the terminating bandwidth reclamation queue,
++ * which contains no members, loops back to itself, and is present
++ * only when FSBR is on and there are no full-speed control or bulk QHs.
++ */
++int uhci_start(struct usb_hcd *hcd)
++{
++ struct uhci_hcd *uhci = hcd_to_uhci(hcd);
++ int retval = -EBUSY;
++ int i;
++ struct dentry *dentry;
++
++ hcd->uses_new_polling = 1;
++
++ spin_lock_init(&uhci->lock);
++ setup_timer(&uhci->fsbr_timer, uhci_fsbr_timeout,
++ (unsigned long) uhci);
++ INIT_LIST_HEAD(&uhci->idle_qh_list);
++ init_waitqueue_head(&uhci->waitqh);
++
++ if (DEBUG_CONFIGURED) {
++ dentry = debugfs_create_file(hcd->self.bus_name,
++ S_IFREG|S_IRUGO|S_IWUSR, uhci_debugfs_root,
++ uhci, &uhci_debug_operations);
++ if (!dentry) {
++ dev_err(uhci_dev(uhci), "couldn't create uhci "
++ "debugfs entry\n");
++ retval = -ENOMEM;
++ goto err_create_debug_entry;
++ }
++ uhci->dentry = dentry;
++ }
++
++ uhci->frame = dma_alloc_coherent(uhci_dev(uhci),
++ UHCI_NUMFRAMES * sizeof(*uhci->frame),
++ &uhci->frame_dma_handle, 0);
++ if (!uhci->frame) {
++ dev_err(uhci_dev(uhci), "unable to allocate "
++ "consistent memory for frame list\n");
++ goto err_alloc_frame;
++ }
++
++ memset(uhci->frame, 0, UHCI_NUMFRAMES * sizeof(*uhci->frame));
++
++ uhci->frame_cpu = kcalloc(UHCI_NUMFRAMES, sizeof(*uhci->frame_cpu),
++ GFP_KERNEL);
++ if (!uhci->frame_cpu) {
++ dev_err(uhci_dev(uhci), "unable to allocate "
++ "memory for frame pointers\n");
++ goto err_alloc_frame_cpu;
++ }
++
++ uhci->td_pool = dma_pool_create("uhci_td", uhci_dev(uhci),
++ sizeof(struct uhci_td), 16, 0);
++ if (!uhci->td_pool) {
++ dev_err(uhci_dev(uhci), "unable to create td dma_pool\n");
++ goto err_create_td_pool;
++ }
++
++ uhci->qh_pool = dma_pool_create("uhci_qh", uhci_dev(uhci),
++ sizeof(struct uhci_qh), 16, 0);
++ if (!uhci->qh_pool) {
++ dev_err(uhci_dev(uhci), "unable to create qh dma_pool\n");
++ goto err_create_qh_pool;
++ }
++
++ uhci->term_td = uhci_alloc_td(uhci);
++ if (!uhci->term_td) {
++ dev_err(uhci_dev(uhci), "unable to allocate terminating TD\n");
++ goto err_alloc_term_td;
++ }
++
++ for (i = 0; i < UHCI_NUM_SKELQH; i++) {
++ uhci->skelqh[i] = uhci_alloc_qh(uhci, NULL, NULL);
++ if (!uhci->skelqh[i]) {
++ dev_err(uhci_dev(uhci), "unable to allocate QH\n");
++ goto err_alloc_skelqh;
++ }
++ }
++
++ /*
++ * 8 Interrupt queues; link all higher int queues to int1 = async
++ */
++ for (i = SKEL_ISO + 1; i < SKEL_ASYNC; ++i)
++ uhci->skelqh[i]->link = LINK_TO_QH(uhci->skel_async_qh);
++ uhci->skel_async_qh->link = UHCI_PTR_TERM;
++ uhci->skel_term_qh->link = LINK_TO_QH(uhci->skel_term_qh);
++
++ /* This dummy TD is to work around a bug in Intel PIIX controllers */
++ uhci_fill_td(uhci->term_td, 0, uhci_explen(0) |
++ (0x7f << TD_TOKEN_DEVADDR_SHIFT) | USB_PID_IN, 0);
++ uhci->term_td->link = UHCI_PTR_TERM;
++ uhci->skel_async_qh->element = uhci->skel_term_qh->element =
++ LINK_TO_TD(uhci->term_td);
++
++ /*
++ * Fill the frame list: make all entries point to the proper
++ * interrupt queue.
++ */
++ for (i = 0; i < UHCI_NUMFRAMES; i++) {
++
++ /* Only place we don't use the frame list routines */
++ uhci->frame[i] = uhci_frame_skel_link(uhci, i);
++ }
++
++ /*
++ * Some architectures require a full mb() to enforce completion of
++ * the memory writes above before the I/O transfers in configure_hc().
++ */
++ mb();
++
++ configure_hc(uhci);
++
++ uhci->is_initialized = 1;
++ start_rh(uhci);
++
++ return 0;
++
++/*
++ * error exits:
++ */
++err_alloc_skelqh:
++ for (i = 0; i < UHCI_NUM_SKELQH; i++) {
++ if (uhci->skelqh[i])
++ uhci_free_qh(uhci, uhci->skelqh[i]);
++ }
++
++ uhci_free_td(uhci, uhci->term_td);
++
++err_alloc_term_td:
++ dma_pool_destroy(uhci->qh_pool);
++
++err_create_qh_pool:
++ dma_pool_destroy(uhci->td_pool);
++
++err_create_td_pool:
++ kfree(uhci->frame_cpu);
++
++err_alloc_frame_cpu:
++ dma_free_coherent(uhci_dev(uhci),
++ UHCI_NUMFRAMES * sizeof(*uhci->frame),
++ uhci->frame, uhci->frame_dma_handle);
++
++err_alloc_frame:
++ debugfs_remove(uhci->dentry);
++
++err_create_debug_entry:
++ return retval;
++}
++
++void uhci_stop(struct usb_hcd *hcd)
++{
++ struct uhci_hcd *uhci = hcd_to_uhci(hcd);
++
++ spin_lock_irq(&uhci->lock);
++ if (test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags) && !uhci->dead)
++ uhci_hc_died(uhci);
++ uhci_scan_schedule(uhci);
++ spin_unlock_irq(&uhci->lock);
++
++ del_timer_sync(&uhci->fsbr_timer);
++ release_uhci(uhci);
++}
++
++void stop_hc(struct uhci_hcd *uhci)
++{
++ // Disable all interrupts
++ writel(0, (uhci->regbase + USBINTR));
++ writel(USBCMD_MAXP,(uhci->regbase + USBCMD)); // disable hc
++
++}
++
++#ifdef CONFIG_PM
++int uhci_rh_suspend(struct usb_hcd *hcd)
++{
++ struct uhci_hcd *uhci = hcd_to_uhci(hcd);
++ int rc = 0;
++
++ spin_lock_irq(&uhci->lock);
++ if (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags))
++ rc = -ESHUTDOWN;
++ else if (!uhci->dead)
++ suspend_rh(uhci, UHCI_RH_SUSPENDED);
++ spin_unlock_irq(&uhci->lock);
++ return rc;
++}
++
++int uhci_rh_resume(struct usb_hcd *hcd)
++{
++ struct uhci_hcd *uhci = hcd_to_uhci(hcd);
++ int rc = 0;
++
++ spin_lock_irq(&uhci->lock);
++ if (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags))
++ rc = -ESHUTDOWN;
++ else if (!uhci->dead)
++ wakeup_rh(uhci);
++ spin_unlock_irq(&uhci->lock);
++ return rc;
++}
++
++int uhci_pci_suspend(struct usb_hcd *hcd, pm_message_t message)
++{
++ struct uhci_hcd *uhci = hcd_to_uhci(hcd);
++ int rc = 0;
++
++ dev_dbg(uhci_dev(uhci), "%s\n", __func__);
++
++ spin_lock_irq(&uhci->lock);
++ if (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags) || uhci->dead)
++ goto done_okay; /* Already suspended or dead */
++
++ if (uhci->rh_state > UHCI_RH_SUSPENDED) {
++ dev_warn(uhci_dev(uhci), "Root hub isn't suspended!\n");
++ rc = -EBUSY;
++ goto done;
++ };
++
++ /* All PCI host controllers are required to disable IRQ generation
++ * at the source, so we must turn off PIRQ.
++ */
++ pci_write_config_word(to_pci_dev(uhci_dev(uhci)), USBLEGSUP, 0);
++ mb();
++ hcd->poll_rh = 0;
++
++ /* FIXME: Enable non-PME# remote wakeup? */
++
++ /* make sure snapshot being resumed re-enumerates everything */
++ if (message.event == PM_EVENT_PRETHAW)
++ uhci_hc_died(uhci);
++
++done_okay:
++ clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
++done:
++ spin_unlock_irq(&uhci->lock);
++ return rc;
++}
++
++int uhci_pci_resume(struct usb_hcd *hcd)
++{
++ struct uhci_hcd *uhci = hcd_to_uhci(hcd);
++
++ dev_dbg(uhci_dev(uhci), "%s\n", __func__);
++
++ /* Since we aren't in D3 any more, it's safe to set this flag
++ * even if the controller was dead.
++ */
++ set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
++ mb();
++
++ spin_lock_irq(&uhci->lock);
++
++ /* FIXME: Disable non-PME# remote wakeup? */
++
++ /* The firmware or a boot kernel may have changed the controller
++ * settings during a system wakeup. Check it and reconfigure
++ * to avoid problems.
++ */
++ check_and_reset_hc(uhci);
++
++ /* If the controller was dead before, it's back alive now */
++ configure_hc(uhci);
++
++ if (uhci->rh_state == UHCI_RH_RESET) {
++
++ /* The controller had to be reset */
++ usb_root_hub_lost_power(hcd->self.root_hub);
++ suspend_rh(uhci, UHCI_RH_SUSPENDED);
++ }
++
++ spin_unlock_irq(&uhci->lock);
++
++ /* If interrupts don't work and remote wakeup is enabled then
++ * the suspended root hub needs to be polled.
++ */
++ if (!uhci->RD_enable && hcd->self.root_hub->do_remote_wakeup) {
++ hcd->poll_rh = 1;
++ usb_hcd_poll_rh_status(hcd);
++ }
++ return 0;
++}
++#endif
++
++/* Wait until a particular device/endpoint's QH is idle, and free it */
++void uhci_hcd_endpoint_disable(struct usb_hcd *hcd,
++ struct usb_host_endpoint *hep)
++{
++ struct uhci_hcd *uhci = hcd_to_uhci(hcd);
++ struct uhci_qh *qh;
++
++ spin_lock_irq(&uhci->lock);
++ qh = (struct uhci_qh *) hep->hcpriv;
++ if (qh == NULL)
++ goto done;
++
++ while (qh->state != UHCI_QH_STATE_IDLE) {
++ ++uhci->num_waiting;
++ spin_unlock_irq(&uhci->lock);
++ wait_event_interruptible(uhci->waitqh,
++ qh->state == UHCI_QH_STATE_IDLE);
++ spin_lock_irq(&uhci->lock);
++ --uhci->num_waiting;
++ }
++
++ uhci_free_qh(uhci, qh);
++done:
++ spin_unlock_irq(&uhci->lock);
++}
++
++int uhci_hcd_get_frame_number(struct usb_hcd *hcd)
++{
++ struct uhci_hcd *uhci = hcd_to_uhci(hcd);
++ unsigned frame_number;
++ unsigned delta;
++
++ /* Minimize latency by avoiding the spinlock */
++ frame_number = uhci->frame_number;
++ barrier();
++//yriver
++// delta = (inw(uhci->io_addr + USBFRNUM) - frame_number) &
++// (UHCI_NUMFRAMES - 1);
++ delta = (readl(uhci->regbase + USBFRNUM) - frame_number) &
++ (UHCI_NUMFRAMES - 1);
++ return frame_number + delta;
++}
++
++//static const char hcd_name[] = "uhci_hcd";
++
++static const struct hc_driver _uhci_driver = {
++//yriver
++// .description = hcd_name,
++ .description = "ast uhci",
++ .product_desc = "UHCI Host Controller",
++ .hcd_priv_size = sizeof(struct uhci_hcd),
++
++ /* Generic hardware linkage */
++ .irq = uhci_irq,
++ .flags = HCD_USB11,
++
++ /* Basic lifecycle operations */
++// .reset = uhci_init,
++ .reset = uhci_reset,
++ .start = uhci_start,
++#ifdef CONFIG_PM
++ .pci_suspend = uhci_pci_suspend,
++ .pci_resume = uhci_pci_resume,
++ .bus_suspend = uhci_rh_suspend,
++ .bus_resume = uhci_rh_resume,
++#endif
++ .stop = uhci_stop,
++
++ .urb_enqueue = uhci_urb_enqueue,
++ .urb_dequeue = uhci_urb_dequeue,
++
++ .endpoint_disable = uhci_hcd_endpoint_disable,
++ .get_frame_number = uhci_hcd_get_frame_number,
++
++ .hub_status_data = uhci_hub_status_data,
++ .hub_control = uhci_hub_control,
++};
++
++int __init uhci_hcd_init(void)
++{
++ int retval = -ENOMEM;
++
++ if (usb_disabled())
++ return -ENODEV;
++
++ printk(KERN_INFO "uhci_hcd: " DRIVER_DESC "%s\n",
++ ignore_oc ? ", overcurrent ignored" : "");
++ set_bit(USB_UHCI_LOADED, &usb_hcds_loaded);
++
++ if (DEBUG_CONFIGURED) {
++ errbuf = kmalloc(ERRBUF_LEN, GFP_KERNEL);
++ if (!errbuf)
++ goto errbuf_failed;
++ uhci_debugfs_root = debugfs_create_dir("uhci", NULL);
++ if (!uhci_debugfs_root)
++ goto debug_failed;
++ }
++
++ uhci_up_cachep = kmem_cache_create("uhci_urb_priv",
++ sizeof(struct urb_priv), 0, 0, NULL);
++ if (!uhci_up_cachep)
++ goto up_failed;
++/*
++ retval = pci_register_driver(&uhci_pci_driver);
++ if (retval)
++ goto init_failed;
++*/
++ return 0;
++
++//init_failed:
++// kmem_cache_destroy(uhci_up_cachep);
++
++up_failed:
++ debugfs_remove(uhci_debugfs_root);
++
++debug_failed:
++ kfree(errbuf);
++
++errbuf_failed:
++
++ clear_bit(USB_UHCI_LOADED, &usb_hcds_loaded);
++ return retval;
++}
++
++void uhci_hcd_cleanup(void)
++{
++// pci_unregister_driver(&uhci_pci_driver);
++ kmem_cache_destroy(uhci_up_cachep);
++ debugfs_remove(uhci_debugfs_root);
++ kfree(errbuf);
++ clear_bit(USB_UHCI_LOADED, &usb_hcds_loaded);
++}
++
++void __exit cleanup_UHCI(void)
++{
++ uhci_hcd_cleanup();
++}
++
++/*-------------------------------------------------------------------------*/
++static int usb_hcd_guc_probe (const struct hc_driver *driver,
++ struct platform_device *pdev)
++{
++ unsigned int *base, temp;
++ int retval;
++ struct resource *res;
++ struct usb_hcd *hcd = 0;
++ struct uhci_hcd *uhci;
++ int irq;
++
++ irq = platform_get_irq(pdev, 0);
++ if (irq <= 0) {
++ dev_err(&pdev->dev,
++ "Found HC with no IRQ. Check %s setup!\n",
++ dev_name(&pdev->dev));
++ retval = -ENODEV;
++ goto err1;
++ }
++
++ hcd = usb_create_hcd (driver, &pdev->dev, dev_name(&pdev->dev));
++// printk("alloc_uhci(2): uhci_dev:%x, _uhci_hcd.state:%x\n", &uhci_dev, _uhci_hcd->state);
++ if (!hcd) {
++ retval = -ENOMEM;
++ return retval;
++ }
++
++
++ uhci = hcd_to_uhci(hcd);
++
++ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
++ if (!res) {
++ dev_err(&pdev->dev,
++ "Found HC with no register addr. Check %s setup!\n",
++ dev_name(&pdev->dev));
++ retval = -ENODEV;
++ goto err1;
++ }
++
++ if (!request_mem_region(res->start, res->end - res->start + 1,
++ res->name)) {
++ dev_dbg(&pdev->dev, "controller already in use\n");
++ retval = -EBUSY;
++ goto err1;
++ }
++
++ base = ioremap_nocache(res->start, res->end - res->start + 1);
++ if (base == NULL) {
++ dev_dbg(&pdev->dev, "error mapping memory\n");
++ retval = -ENOMEM;
++ goto err1;
++ }
++
++ uhci->regbase = (unsigned int *)base;
++ uhci->io_addr = (unsigned int)base;
++
++// printk("UHCI Base address is %x, phy %08x\n",(unsigned int)base, UHC_BASE_ADDR);
++
++ retval = usb_add_hcd (hcd, irq, IRQF_SHARED);
++
++ // printk("alloc_uhci(3): uhci_dev:%x, _uhci_hcd.state:%x\n", &uhci_dev, _uhci_hcd->state);
++
++ if (retval == 0)
++ return retval;
++
++ //BruceToDo. Stop USB 1.1 Host's clock.
++ iounmap((void*)uhci->io_addr);
++err1:
++ usb_put_hcd(hcd);
++
++ printk("add UHCI to USB host controller list failed!\n");
++ return retval;
++}
++
++
++static inline void
++usb_hcd_guc_remove (struct usb_hcd *hcd, struct platform_device *pdev)
++{
++ struct uhci_hcd *uhci = hcd_to_uhci(hcd);
++
++ usb_remove_hcd(hcd);
++ //BruceToDo. Stop USB 1.1 Host's clock.
++ iounmap((void*)uhci->io_addr);
++ usb_put_hcd(hcd);
++}
++
++/*-------------------------------------------------------------------------*/
++#ifdef CONFIG_PM
++static int uhci_guc_suspend(struct platform_device *dev, pm_message_t message)
++{
++ struct uhci_hcd *uhci = hcd_to_uhci(platform_get_drvdata(dev));
++#if 0
++ if (time_before(jiffies, ohci->next_statechange))
++ msleep(5);
++ ohci->next_statechange = jiffies;
++ omap_ohci_clock_power(0);
++#endif
++ uhci_to_hcd(uhci)->state = HC_STATE_SUSPENDED;
++ return 0;
++}
++static int uhci_guc_resume(struct platform_device *dev)
++{
++ struct usb_hcd *hcd = platform_get_drvdata(dev);
++#if 0
++ struct uhci_hcd *uhci = hcd_to_uhci(hcd);
++
++ if (time_before(jiffies, ohci->next_statechange))
++ msleep(5);
++ ohci->next_statechange = jiffies;
++ omap_ohci_clock_power(1);
++ ohci_finish_controller_resume(hcd);
++#endif
++
++ /*Bruce111220. This line is copied from AST1510 uhci-hcd.c and OMAP kernel 2.6.15*/
++ usb_hcd_resume_root_hub(hcd);
++ return 0;
++}
++#endif
++/*-------------------------------------------------------------------------*/
++
++static int uhci_hcd_guc_drv_probe(struct platform_device *dev)
++{
++ return usb_hcd_guc_probe(&_uhci_driver, dev);
++}
++static int uhci_hcd_guc_drv_remove(struct platform_device *dev)
++{
++ struct usb_hcd *hcd = platform_get_drvdata(dev);
++
++ usb_hcd_guc_remove(hcd, dev);
++ platform_set_drvdata(dev, NULL);
++ return 0;
++}
++
++/*
++ * Driver definition to register
++ */
++static struct platform_driver uhci_hcd_guc_driver = {
++ .probe = uhci_hcd_guc_drv_probe,
++ .remove = uhci_hcd_guc_drv_remove,
++#ifdef CONFIG_PM
++ .suspend = uhci_guc_suspend,
++ .resume = uhci_guc_resume,
++#endif
++ .driver = {
++ .owner = THIS_MODULE,
++ .name = "ast_uhci",
++ },
++};
++
++static int __init uhci_hcd_guc_init (void)
++{
++ uhci_hcd_init();
++ return platform_driver_register(&uhci_hcd_guc_driver);
++}
++
++static void __exit uhci_hcd_guc_cleanup (void)
++{
++ uhci_hcd_cleanup();
++ platform_driver_unregister(&uhci_hcd_guc_driver);
++}
++
++module_init(uhci_hcd_guc_init);
++module_exit(uhci_hcd_guc_cleanup);
++
++MODULE_AUTHOR(DRIVER_AUTHOR);
++MODULE_DESCRIPTION(DRIVER_DESC);
++MODULE_LICENSE("GPL");
+diff --git a/drivers/usb/astuhci/uhci-hcd.h b/drivers/usb/astuhci/uhci-hcd.h
+new file mode 100644
+index 0000000..c4a903e
+--- /dev/null
++++ b/drivers/usb/astuhci/uhci-hcd.h
+@@ -0,0 +1,496 @@
++/********************************************************************************
++* File Name : uhci-hcd.h
++*
++* port from uhci-hcd.h
++* This program is free software; you can redistribute it and/or modify
++* it under the terms of the GNU General Public License as published by the Free Software Foundation;
++* either version 2 of the License, or (at your option) any later version.
++* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
++* without even the implied warranty of MERCHANTABILITY or
++* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
++* You should have received a copy of the GNU General Public License
++* along with this program; if not, write to the Free Software
++* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++********************************************************************************/
++
++#ifndef __LINUX_UHCI_HCD_H
++#define __LINUX_UHCI_HCD_H
++
++#include <linux/list.h>
++#include <linux/usb.h>
++
++#define usb_packetid(pipe) (usb_pipein(pipe) ? USB_PID_IN : USB_PID_OUT)
++#define PIPE_DEVEP_MASK 0x0007ff00
++
++
++/*
++ * Universal Host Controller Interface data structures and defines
++ */
++
++/* Command register */
++#define USBCMD 0
++#define USBCMD_RS 0x0001 /* Run/Stop */
++#define USBCMD_HCRESET 0x0002 /* Host reset */
++#define USBCMD_GRESET 0x0004 /* Global reset */
++#define USBCMD_EGSM 0x0008 /* Global Suspend Mode */
++#define USBCMD_FGR 0x0010 /* Force Global Resume */
++#define USBCMD_SWDBG 0x0020 /* SW Debug mode */
++#define USBCMD_CF 0x0040 /* Config Flag (sw only) */
++#define USBCMD_MAXP 0x0080 /* Max Packet (0 = 32, 1 = 64) */
++
++/* Status register */
++//#define USBSTS 2
++#define USBSTS 1
++#define USBSTS_USBINT 0x0001 /* Interrupt due to IOC */
++#define USBSTS_ERROR 0x0002 /* Interrupt due to error */
++#define USBSTS_RD 0x0004 /* Resume Detect */
++#define USBSTS_HSE 0x0008 /* Host System Error: PCI problems */
++#define USBSTS_HCPE 0x0010 /* Host Controller Process Error:
++ * the schedule is buggy */
++#define USBSTS_HCH 0x0020 /* HC Halted */
++
++/* Interrupt enable register */
++//#define USBINTR 4
++#define USBINTR 2
++#define USBINTR_TIMEOUT 0x0001 /* Timeout/CRC error enable */
++#define USBINTR_RESUME 0x0002 /* Resume interrupt enable */
++#define USBINTR_IOC 0x0004 /* Interrupt On Complete enable */
++#define USBINTR_SP 0x0008 /* Short packet interrupt enable */
++
++//#define USBFRNUM 6
++//#define USBFLBASEADD 8
++//#define USBSOF 12
++#define USBFRNUM 32
++#define USBFLBASEADD 3
++#define USBSOF 33
++#define USBSOF_DEFAULT 64 /* Frame length is exactly 1 ms */
++
++/* USB port status and control registers */
++//#define USBPORTSC1 16
++//#define USBPORTSC2 18
++#define USBPORTSC1 (34)
++#define USBPORTSC2 (35)
++#define USBPORTSC_CCS 0x0001 /* Current Connect Status
++ * ("device present") */
++#define USBPORTSC_CSC 0x0002 /* Connect Status Change */
++#define USBPORTSC_PE 0x0004 /* Port Enable */
++#define USBPORTSC_PEC 0x0008 /* Port Enable Change */
++#define USBPORTSC_DPLUS 0x0010 /* D+ high (line status) */
++#define USBPORTSC_DMINUS 0x0020 /* D- high (line status) */
++#define USBPORTSC_RD 0x0040 /* Resume Detect */
++#define USBPORTSC_RES1 0x0080 /* reserved, always 1 */
++#define USBPORTSC_LSDA 0x0100 /* Low Speed Device Attached */
++#define USBPORTSC_PR 0x0200 /* Port Reset */
++/* OC and OCC from Intel 430TX and later (not UHCI 1.1d spec) */
++#define USBPORTSC_OC 0x0400 /* Over Current condition */
++#define USBPORTSC_OCC 0x0800 /* Over Current Change R/WC */
++#define USBPORTSC_SUSP 0x1000 /* Suspend */
++#define USBPORTSC_RES2 0x2000 /* reserved, write zeroes */
++#define USBPORTSC_RES3 0x4000 /* reserved, write zeroes */
++#define USBPORTSC_RES4 0x8000 /* reserved, write zeroes */
++
++/* Legacy support register */
++#define USBLEGSUP 0xc0
++#define USBLEGSUP_DEFAULT 0x2000 /* only PIRQ enable set */
++#define USBLEGSUP_RWC 0x8f00 /* the R/WC bits */
++#define USBLEGSUP_RO 0x5040 /* R/O and reserved bits */
++
++#define UHCI_PTR_BITS __constant_cpu_to_le32(0x000F)
++#define UHCI_PTR_TERM __constant_cpu_to_le32(0x0001)
++#define UHCI_PTR_QH __constant_cpu_to_le32(0x0002)
++#define UHCI_PTR_DEPTH __constant_cpu_to_le32(0x0004)
++#define UHCI_PTR_BREADTH __constant_cpu_to_le32(0x0000)
++
++#define UHCI_NUMFRAMES 1024 /* in the frame list [array] */
++#define UHCI_MAX_SOF_NUMBER 2047 /* in an SOF packet */
++#define CAN_SCHEDULE_FRAMES 1000 /* how far in the future frames
++ * can be scheduled */
++#define MAX_PHASE 32 /* Periodic scheduling length */
++
++/* Otg Features*/
++#define RH_PORT_BHNP_ENABLE 0x03
++#define RH_PORT_AHNP_SUPPORT 0x04
++#define SF_BHNP_ENABLE 0x34
++
++/* When no queues need Full-Speed Bandwidth Reclamation,
++ * delay this long before turning FSBR off */
++#define FSBR_OFF_DELAY msecs_to_jiffies(10)
++
++/* If a queue hasn't advanced after this much time, assume it is stuck */
++#define QH_WAIT_TIMEOUT msecs_to_jiffies(200)
++
++
++/*
++ * Queue Headers
++ */
++
++/*
++ * One role of a QH is to hold a queue of TDs for some endpoint. One QH goes
++ * with each endpoint, and qh->element (updated by the HC) is either:
++ * - the next unprocessed TD in the endpoint's queue, or
++ * - UHCI_PTR_TERM (when there's no more traffic for this endpoint).
++ *
++ * The other role of a QH is to serve as a "skeleton" framelist entry, so we
++ * can easily splice a QH for some endpoint into the schedule at the right
++ * place. Then qh->element is UHCI_PTR_TERM.
++ *
++ * In the schedule, qh->link maintains a list of QHs seen by the HC:
++ * skel1 --> ep1-qh --> ep2-qh --> ... --> skel2 --> ...
++ *
++ * qh->node is the software equivalent of qh->link. The differences
++ * are that the software list is doubly-linked and QHs in the UNLINKING
++ * state are on the software list but not the hardware schedule.
++ *
++ * For bookkeeping purposes we maintain QHs even for Isochronous endpoints,
++ * but they never get added to the hardware schedule.
++ */
++#define QH_STATE_IDLE 1 /* QH is not being used */
++#define UHCI_QH_STATE_IDLE 1 /* QH is not being used */
++#define QH_STATE_UNLINKING 2 /* QH has been removed from the
++ * schedule but the hardware may
++ * still be using it */
++#define QH_STATE_ACTIVE 3 /* QH is on the schedule */
++
++struct uhci_qh {
++ /* Hardware fields */
++ __le32 link; /* Next QH in the schedule */
++ __le32 element; /* Queue element (TD) pointer */
++
++ /* Software fields */
++ dma_addr_t dma_handle;
++
++ struct list_head node; /* Node in the list of QHs */
++ struct usb_host_endpoint *hep; /* Endpoint information */
++ struct usb_device *udev;
++ struct list_head queue; /* Queue of urbps for this QH */
++ struct uhci_td *dummy_td; /* Dummy TD to end the queue */
++ struct uhci_td *post_td; /* Last TD completed */
++
++ struct usb_iso_packet_descriptor *iso_packet_desc;
++ /* Next urb->iso_frame_desc entry */
++ unsigned long advance_jiffies; /* Time of last queue advance */
++ unsigned int unlink_frame; /* When the QH was unlinked */
++ unsigned int period; /* For Interrupt and Isochronous QHs */
++ short phase; /* Between 0 and period-1 */
++ short load; /* Periodic time requirement, in us */
++ unsigned int iso_frame; /* Frame # for iso_packet_desc */
++
++ int state; /* QH_STATE_xxx; see above */
++ int type; /* Queue type (control, bulk, etc) */
++ int skel; /* Skeleton queue number */
++
++ unsigned int initial_toggle:1; /* Endpoint's current toggle value */
++ unsigned int needs_fixup:1; /* Must fix the TD toggle values */
++ unsigned int is_stopped:1; /* Queue was stopped by error/unlink */
++ unsigned int wait_expired:1; /* QH_WAIT_TIMEOUT has expired */
++ unsigned int bandwidth_reserved:1; /* Periodic bandwidth has
++ * been allocated */
++} __attribute__((aligned(16)));
++
++/*
++ * We need a special accessor for the element pointer because it is
++ * subject to asynchronous updates by the controller.
++ */
++static inline __le32 qh_element(struct uhci_qh *qh) {
++ __le32 element = qh->element;
++
++ barrier();
++ return element;
++}
++
++#define LINK_TO_QH(qh) (UHCI_PTR_QH | cpu_to_le32((qh)->dma_handle))
++
++
++/*
++ * Transfer Descriptors
++ */
++
++/*
++ * for TD <status>:
++ */
++#define TD_CTRL_SPD (1 << 29) /* Short Packet Detect */
++#define TD_CTRL_C_ERR_MASK (3 << 27) /* Error Counter bits */
++#define TD_CTRL_C_ERR_SHIFT 27
++#define TD_CTRL_LS (1 << 26) /* Low Speed Device */
++#define TD_CTRL_IOS (1 << 25) /* Isochronous Select */
++#define TD_CTRL_IOC (1 << 24) /* Interrupt on Complete */
++#define TD_CTRL_ACTIVE (1 << 23) /* TD Active */
++#define TD_CTRL_STALLED (1 << 22) /* TD Stalled */
++#define TD_CTRL_DBUFERR (1 << 21) /* Data Buffer Error */
++#define TD_CTRL_BABBLE (1 << 20) /* Babble Detected */
++#define TD_CTRL_NAK (1 << 19) /* NAK Received */
++#define TD_CTRL_CRCTIMEO (1 << 18) /* CRC/Time Out Error */
++#define TD_CTRL_BITSTUFF (1 << 17) /* Bit Stuff Error */
++#define TD_CTRL_ACTLEN_MASK 0x7FF /* actual length, encoded as n - 1 */
++
++#define TD_CTRL_ANY_ERROR (TD_CTRL_STALLED | TD_CTRL_DBUFERR | \
++ TD_CTRL_BABBLE | TD_CTRL_CRCTIME | \
++ TD_CTRL_BITSTUFF)
++
++#define uhci_maxerr(err) ((err) << TD_CTRL_C_ERR_SHIFT)
++#define uhci_status_bits(ctrl_sts) ((ctrl_sts) & 0xF60000)
++#define uhci_actual_length(ctrl_sts) (((ctrl_sts) + 1) & \
++ TD_CTRL_ACTLEN_MASK) /* 1-based */
++
++/*
++ * for TD <info>: (a.k.a. Token)
++ */
++#define td_token(td) le32_to_cpu((td)->token)
++#define TD_TOKEN_DEVADDR_SHIFT 8
++#define TD_TOKEN_TOGGLE_SHIFT 19
++#define TD_TOKEN_TOGGLE (1 << 19)
++#define TD_TOKEN_EXPLEN_SHIFT 21
++#define TD_TOKEN_EXPLEN_MASK 0x7FF /* expected length, encoded as n-1 */
++#define TD_TOKEN_PID_MASK 0xFF
++
++#define uhci_explen(len) ((((len) - 1) & TD_TOKEN_EXPLEN_MASK) << \
++ TD_TOKEN_EXPLEN_SHIFT)
++
++#define uhci_expected_length(token) ((((token) >> TD_TOKEN_EXPLEN_SHIFT) + \
++ 1) & TD_TOKEN_EXPLEN_MASK)
++#define uhci_toggle(token) (((token) >> TD_TOKEN_TOGGLE_SHIFT) & 1)
++#define uhci_endpoint(token) (((token) >> 15) & 0xf)
++#define uhci_devaddr(token) (((token) >> TD_TOKEN_DEVADDR_SHIFT) & 0x7f)
++#define uhci_devep(token) (((token) >> TD_TOKEN_DEVADDR_SHIFT) & 0x7ff)
++#define uhci_packetid(token) ((token) & TD_TOKEN_PID_MASK)
++#define uhci_packetout(token) (uhci_packetid(token) != USB_PID_IN)
++#define uhci_packetin(token) (uhci_packetid(token) == USB_PID_IN)
++
++/*
++ * The documentation says "4 words for hardware, 4 words for software".
++ *
++ * That's silly, the hardware doesn't care. The hardware only cares that
++ * the hardware words are 16-byte aligned, and we can have any amount of
++ * sw space after the TD entry.
++ *
++ * td->link points to either another TD (not necessarily for the same urb or
++ * even the same endpoint), or nothing (PTR_TERM), or a QH.
++ */
++struct uhci_td {
++ /* Hardware fields */
++ __le32 link;
++ __le32 status;
++ __le32 token;
++ __le32 buffer;
++
++ /* Software fields */
++ dma_addr_t dma_handle;
++
++ struct list_head list;
++
++ int frame; /* for iso: what frame? */
++ struct list_head fl_list;
++} __attribute__((aligned(16)));
++
++/*
++ * We need a special accessor for the control/status word because it is
++ * subject to asynchronous updates by the controller.
++ */
++static inline u32 td_status(struct uhci_td *td) {
++ __le32 status = td->status;
++
++ barrier();
++ return le32_to_cpu(status);
++}
++
++#define LINK_TO_TD(td) (cpu_to_le32((td)->dma_handle))
++
++
++/*
++ * Skeleton Queue Headers
++ */
++
++/*
++ * The UHCI driver uses QHs with Interrupt, Control and Bulk URBs for
++ * automatic queuing. To make it easy to insert entries into the schedule,
++ * we have a skeleton of QHs for each predefined Interrupt latency.
++ * Asynchronous QHs (low-speed control, full-speed control, and bulk)
++ * go onto the period-1 interrupt list, since they all get accessed on
++ * every frame.
++ *
++ * When we want to add a new QH, we add it to the list starting from the
++ * appropriate skeleton QH. For instance, the schedule can look like this:
++ *
++ * skel int128 QH
++ * dev 1 interrupt QH
++ * dev 5 interrupt QH
++ * skel int64 QH
++ * skel int32 QH
++ * ...
++ * skel int1 + async QH
++ * dev 5 low-speed control QH
++ * dev 1 bulk QH
++ * dev 2 bulk QH
++ *
++ * There is a special terminating QH used to keep full-speed bandwidth
++ * reclamation active when no full-speed control or bulk QHs are linked
++ * into the schedule. It has an inactive TD (to work around a PIIX bug,
++ * see the Intel errata) and it points back to itself.
++ *
++ * There's a special skeleton QH for Isochronous QHs which never appears
++ * on the schedule. Isochronous TDs go on the schedule before the
++ * the skeleton QHs. The hardware accesses them directly rather than
++ * through their QH, which is used only for bookkeeping purposes.
++ * While the UHCI spec doesn't forbid the use of QHs for Isochronous,
++ * it doesn't use them either. And the spec says that queues never
++ * advance on an error completion status, which makes them totally
++ * unsuitable for Isochronous transfers.
++ *
++ * There's also a special skeleton QH used for QHs which are in the process
++ * of unlinking and so may still be in use by the hardware. It too never
++ * appears on the schedule.
++ */
++
++#define UHCI_NUM_SKELQH 11
++#define SKEL_UNLINK 0
++#define skel_unlink_qh skelqh[SKEL_UNLINK]
++#define SKEL_ISO 1
++#define skel_iso_qh skelqh[SKEL_ISO]
++ /* int128, int64, ..., int1 = 2, 3, ..., 9 */
++#define SKEL_INDEX(exponent) (9 - exponent)
++#define SKEL_ASYNC 9
++#define skel_async_qh skelqh[SKEL_ASYNC]
++#define SKEL_TERM 10
++#define skel_term_qh skelqh[SKEL_TERM]
++
++/* The following entries refer to sublists of skel_async_qh */
++#define SKEL_LS_CONTROL 20
++#define SKEL_FS_CONTROL 21
++#define SKEL_FSBR SKEL_FS_CONTROL
++#define SKEL_BULK 22
++
++/*
++ * The UHCI controller and root hub
++ */
++
++/*
++ * States for the root hub:
++ *
++ * To prevent "bouncing" in the presence of electrical noise,
++ * when there are no devices attached we delay for 1 second in the
++ * RUNNING_NODEVS state before switching to the AUTO_STOPPED state.
++ *
++ * (Note that the AUTO_STOPPED state won't be necessary once the hub
++ * driver learns to autosuspend.)
++ */
++enum uhci_rh_state {
++ /* In the following states the HC must be halted.
++ * These two must come first. */
++ UHCI_RH_RESET,
++ UHCI_RH_SUSPENDED,
++
++ UHCI_RH_AUTO_STOPPED,
++ UHCI_RH_RESUMING,
++
++ /* In this state the HC changes from running to halted,
++ * so it can legally appear either way. */
++ UHCI_RH_SUSPENDING,
++
++ /* In the following states it's an error if the HC is halted.
++ * These two must come last. */
++ UHCI_RH_RUNNING, /* The normal state */
++ UHCI_RH_RUNNING_NODEVS, /* Running with no devices attached */
++};
++
++/*
++ * The full UHCI controller information:
++ */
++struct uhci_hcd {
++
++ /* debugfs */
++ struct dentry *dentry;
++
++ /* Grabbed from PCI */
++ unsigned long io_addr;
++
++ struct dma_pool *qh_pool;
++ struct dma_pool *td_pool;
++
++ struct uhci_td *term_td; /* Terminating TD, see UHCI bug */
++ struct uhci_qh *skelqh[UHCI_NUM_SKELQH]; /* Skeleton QHs */
++ struct uhci_qh *next_qh; /* Next QH to scan */
++
++ spinlock_t lock;
++
++ dma_addr_t frame_dma_handle; /* Hardware frame list */
++ __le32 *frame;
++ void **frame_cpu; /* CPU's frame list */
++
++ enum uhci_rh_state rh_state;
++ unsigned long auto_stop_time; /* When to AUTO_STOP */
++
++ unsigned int frame_number; /* As of last check */
++ unsigned int is_stopped;
++#define UHCI_IS_STOPPED 9999 /* Larger than a frame # */
++ unsigned int last_iso_frame; /* Frame of last scan */
++ unsigned int cur_iso_frame; /* Frame for current scan */
++
++ unsigned int scan_in_progress:1; /* Schedule scan is running */
++ unsigned int need_rescan:1; /* Redo the schedule scan */
++ unsigned int dead:1; /* Controller has died */
++ unsigned int RD_enable:1; /* Suspended root hub with
++ Resume-Detect interrupts
++ enabled */
++ unsigned int is_initialized:1; /* Data structure is usable */
++ unsigned int fsbr_is_on:1; /* FSBR is turned on */
++ unsigned int fsbr_is_wanted:1; /* Does any URB want FSBR? */
++ unsigned int fsbr_expiring:1; /* FSBR is timing out */
++
++ struct timer_list fsbr_timer; /* For turning off FBSR */
++
++ /* Support for port suspend/resume/reset */
++ unsigned long port_c_suspend; /* Bit-arrays of ports */
++ unsigned long resuming_ports;
++ unsigned long ports_timeout; /* Time to stop signalling */
++
++ struct list_head idle_qh_list; /* Where the idle QHs live */
++
++ int rh_numports; /* Number of root-hub ports */
++
++ wait_queue_head_t waitqh; /* endpoint_disable waiters */
++ int num_waiting; /* Number of waiters */
++
++ int total_load; /* Sum of array values */
++ short load[MAX_PHASE]; /* Periodic allocations */
++ int is_suspended;
++ unsigned int *regbase; // eric
++ unsigned int *ptr_usb_hcd; // eric
++};
++
++/* Convert between a usb_hcd pointer and the corresponding uhci_hcd */
++static inline struct uhci_hcd *hcd_to_uhci(struct usb_hcd *hcd)
++{
++ return (struct uhci_hcd *) (hcd->hcd_priv);
++}
++static inline struct usb_hcd *uhci_to_hcd(struct uhci_hcd *uhci)
++{
++ return container_of((void *) uhci, struct usb_hcd, hcd_priv);
++}
++
++#define uhci_dev(u) (uhci_to_hcd(u)->self.controller)
++
++/* Utility macro for comparing frame numbers */
++#define uhci_frame_before_eq(f1, f2) (0 <= (int) ((f2) - (f1)))
++
++
++/*
++ * Private per-URB data
++ */
++struct urb_priv {
++ struct list_head node; /* Node in the QH's urbp list */
++
++ struct urb *urb;
++
++ struct uhci_qh *qh; /* QH for this URB */
++ struct list_head td_list;
++
++ unsigned fsbr:1; /* URB wants FSBR */
++};
++
++
++/* Some special IDs */
++
++#define PCI_VENDOR_ID_GENESYS 0x17a0
++#define PCI_DEVICE_ID_GL880S_UHCI 0x8083
++
++#endif
+diff --git a/drivers/usb/astuhci/uhci-hub.c b/drivers/usb/astuhci/uhci-hub.c
+new file mode 100644
+index 0000000..64a4496
+--- /dev/null
++++ b/drivers/usb/astuhci/uhci-hub.c
+@@ -0,0 +1,437 @@
++/********************************************************************************
++* File Name : uhci-hub.c
++*
++* port from uhci-hub.c
++* This program is free software; you can redistribute it and/or modify
++* it under the terms of the GNU General Public License as published by the Free Software Foundation;
++* either version 2 of the License, or (at your option) any later version.
++* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
++* without even the implied warranty of MERCHANTABILITY or
++* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
++* You should have received a copy of the GNU General Public License
++* along with this program; if not, write to the Free Software
++* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++********************************************************************************/
++
++static const __u8 root_hub_hub_des[] =
++{
++ 0x09, /* __u8 bLength; */
++ 0x29, /* __u8 bDescriptorType; Hub-descriptor */
++ 0x02, /* __u8 bNbrPorts; */
++ 0x0a, /* __u16 wHubCharacteristics; */
++ 0x00, /* (per-port OC, no power switching) */
++ 0x01, /* __u8 bPwrOn2pwrGood; 2ms */
++ 0x00, /* __u8 bHubContrCurrent; 0 mA */
++ 0x00, /* __u8 DeviceRemovable; *** 7 Ports max *** */
++ 0xff /* __u8 PortPwrCtrlMask; *** 7 ports max *** */
++};
++
++#define UHCI_RH_MAXCHILD 7
++
++/* must write as zeroes */
++#define WZ_BITS (USBPORTSC_RES2 | USBPORTSC_RES3 | USBPORTSC_RES4)
++
++/* status change bits: nonzero writes will clear */
++#define RWC_BITS (USBPORTSC_OCC | USBPORTSC_PEC | USBPORTSC_CSC)
++
++/* suspend/resume bits: port suspended or port resuming */
++#define SUSPEND_BITS (USBPORTSC_SUSP | USBPORTSC_RD)
++
++/* A port that either is connected or has a changed-bit set will prevent
++ * us from AUTO_STOPPING.
++ */
++static int any_ports_active(struct uhci_hcd *uhci)
++{
++ int port;
++
++ for (port = 0; port < uhci->rh_numports; ++port) {
++//yriver
++// if ((inw(uhci->io_addr + USBPORTSC1 + port * 2) &
++ if ((readl(uhci->regbase + USBPORTSC1 + port * 1) &
++ (USBPORTSC_CCS | RWC_BITS)) ||
++ test_bit(port, &uhci->port_c_suspend))
++ return 1;
++ }
++ return 0;
++}
++
++static inline int get_hub_status_data(struct uhci_hcd *uhci, char *buf)
++{
++ int port;
++ int mask = RWC_BITS;
++
++ /* Some boards (both VIA and Intel apparently) report bogus
++ * overcurrent indications, causing massive log spam unless
++ * we completely ignore them. This doesn't seem to be a problem
++ * with the chipset so much as with the way it is connected on
++ * the motherboard; if the overcurrent input is left to float
++ * then it may constantly register false positives. */
++ if (ignore_oc)
++ mask &= ~USBPORTSC_OCC;
++
++ *buf = 0;
++ for (port = 0; port < uhci->rh_numports; ++port) {
++//yriver
++// if ((inw(uhci->io_addr + USBPORTSC1 + port * 2) & mask) ||
++ if ((readl(uhci->regbase + USBPORTSC1 + port * 1) & mask) ||
++ test_bit(port, &uhci->port_c_suspend))
++ *buf |= (1 << (port + 1));
++ }
++ return !!*buf;
++}
++
++#define OK(x) len = (x); break
++//yriver
++#define CLR_RH_PORTSTAT(x) \
++ status = readl(port_addr); \
++ status &= ~(RWC_BITS|WZ_BITS); \
++ status &= ~(x); \
++ status |= RWC_BITS & (x); \
++ writel(status, port_addr)
++
++#define SET_RH_PORTSTAT(x) \
++ status = readl(port_addr); \
++ status |= (x); \
++ status &= ~(RWC_BITS|WZ_BITS); \
++ writel(status, port_addr)
++
++/* UHCI controllers don't automatically stop resume signalling after 20 msec,
++ * so we have to poll and check timeouts in order to take care of it.
++ */
++static void uhci_finish_suspend(struct uhci_hcd *uhci, int port,
++ unsigned long port_addr)
++{
++ int status;
++ int i;
++//yriver
++// if (inw(port_addr) & SUSPEND_BITS) {
++ if (readl(port_addr) & SUSPEND_BITS) {
++ CLR_RH_PORTSTAT(SUSPEND_BITS);
++ if (test_bit(port, &uhci->resuming_ports))
++ set_bit(port, &uhci->port_c_suspend);
++
++ /* The controller won't actually turn off the RD bit until
++ * it has had a chance to send a low-speed EOP sequence,
++ * which is supposed to take 3 bit times (= 2 microseconds).
++ * Experiments show that some controllers take longer, so
++ * we'll poll for completion. */
++ for (i = 0; i < 10; ++i) {
++//yriver
++// if (!(inw(port_addr) & SUSPEND_BITS))
++ if (!(readl(port_addr) & SUSPEND_BITS))
++ break;
++ udelay(1);
++ }
++ }
++ clear_bit(port, &uhci->resuming_ports);
++}
++
++/* Wait for the UHCI controller in HP's iLO2 server management chip.
++ * It can take up to 250 us to finish a reset and set the CSC bit.
++ */
++static void wait_for_HP(unsigned long port_addr)
++{
++ int i;
++
++ for (i = 10; i < 250; i += 10) {
++//yriver
++// if (inw(port_addr) & USBPORTSC_CSC)
++ if (readl(port_addr) & USBPORTSC_CSC)
++ return;
++ udelay(10);
++ }
++ /* Log a warning? */
++}
++
++static void uhci_check_ports(struct uhci_hcd *uhci)
++{
++ unsigned int port;
++ unsigned long port_addr;
++ int status;
++
++ for (port = 0; port < uhci->rh_numports; ++port) {
++//yriver
++// port_addr = uhci->io_addr + USBPORTSC1 + 2 * port;
++// status = inw(port_addr);
++ port_addr = uhci->regbase + USBPORTSC1 + 1 * port;
++ status = readl(port_addr);
++ if (unlikely(status & USBPORTSC_PR)) {
++ if (time_after_eq(jiffies, uhci->ports_timeout)) {
++ CLR_RH_PORTSTAT(USBPORTSC_PR);
++ udelay(10);
++
++ /* HP's server management chip requires
++ * a longer delay. */
++ if (to_pci_dev(uhci_dev(uhci))->vendor ==
++ PCI_VENDOR_ID_HP)
++ wait_for_HP(port_addr);
++
++ /* If the port was enabled before, turning
++ * reset on caused a port enable change.
++ * Turning reset off causes a port connect
++ * status change. Clear these changes. */
++ CLR_RH_PORTSTAT(USBPORTSC_CSC | USBPORTSC_PEC);
++ SET_RH_PORTSTAT(USBPORTSC_PE);
++ }
++ }
++ if (unlikely(status & USBPORTSC_RD)) {
++ if (!test_bit(port, &uhci->resuming_ports)) {
++
++ /* Port received a wakeup request */
++ set_bit(port, &uhci->resuming_ports);
++ uhci->ports_timeout = jiffies +
++ msecs_to_jiffies(20);
++
++ /* Make sure we see the port again
++ * after the resuming period is over. */
++ mod_timer(&uhci_to_hcd(uhci)->rh_timer,
++ uhci->ports_timeout);
++ } else if (time_after_eq(jiffies,
++ uhci->ports_timeout)) {
++ uhci_finish_suspend(uhci, port, port_addr);
++ }
++ }
++ }
++}
++
++static int uhci_hub_status_data(struct usb_hcd *hcd, char *buf)
++{
++ struct uhci_hcd *uhci = hcd_to_uhci(hcd);
++ unsigned long flags;
++ int status = 0;
++
++ spin_lock_irqsave(&uhci->lock, flags);
++
++ uhci_scan_schedule(uhci);
++ if (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags) || uhci->dead)
++ goto done;
++ uhci_check_ports(uhci);
++
++ status = get_hub_status_data(uhci, buf);
++
++ switch (uhci->rh_state) {
++ case UHCI_RH_SUSPENDING:
++ case UHCI_RH_SUSPENDED:
++ /* if port change, ask to be resumed */
++ if (status)
++ usb_hcd_resume_root_hub(hcd);
++ break;
++
++ case UHCI_RH_AUTO_STOPPED:
++ /* if port change, auto start */
++ if (status)
++ wakeup_rh(uhci);
++ break;
++
++ case UHCI_RH_RUNNING:
++ /* are any devices attached? */
++ if (!any_ports_active(uhci)) {
++ uhci->rh_state = UHCI_RH_RUNNING_NODEVS;
++ uhci->auto_stop_time = jiffies + HZ;
++ }
++ break;
++
++ case UHCI_RH_RUNNING_NODEVS:
++ /* auto-stop if nothing connected for 1 second */
++ if (any_ports_active(uhci))
++ uhci->rh_state = UHCI_RH_RUNNING;
++//yriver
++// else if (time_after_eq(jiffies, uhci->auto_stop_time))
++// suspend_rh(uhci, UHCI_RH_AUTO_STOPPED);
++ break;
++
++ default:
++ break;
++ }
++
++done:
++ spin_unlock_irqrestore(&uhci->lock, flags);
++ return status;
++}
++
++/* size of returned buffer is part of USB spec */
++static int uhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
++ u16 wIndex, char *buf, u16 wLength)
++{
++ struct uhci_hcd *uhci = hcd_to_uhci(hcd);
++ int status, lstatus, retval = 0, len = 0;
++//yriver
++// unsigned int port = wIndex - 1;
++// unsigned long port_addr = uhci->io_addr + USBPORTSC1 + 2 * port;
++ unsigned int port = wIndex - 1;
++ unsigned long port_addr = uhci->regbase + USBPORTSC1 + 1 * port;
++ u16 wPortChange, wPortStatus;
++ unsigned long flags;
++
++ if (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags) || uhci->dead)
++ return -ETIMEDOUT;
++
++ spin_lock_irqsave(&uhci->lock, flags);
++ switch (typeReq) {
++
++ case GetHubStatus:
++ *(__le32 *)buf = cpu_to_le32(0);
++ OK(4); /* hub power */
++ case GetPortStatus:
++ if (port >= uhci->rh_numports)
++ goto err;
++
++ uhci_check_ports(uhci);
++//yriver
++// status = inw(port_addr);
++ status = readl(port_addr);
++
++ /* Intel controllers report the OverCurrent bit active on.
++ * VIA controllers report it active off, so we'll adjust the
++ * bit value. (It's not standardized in the UHCI spec.)
++ */
++ if (to_pci_dev(hcd->self.controller)->vendor ==
++ PCI_VENDOR_ID_VIA)
++ status ^= USBPORTSC_OC;
++
++ /* UHCI doesn't support C_RESET (always false) */
++ wPortChange = lstatus = 0;
++ if (status & USBPORTSC_CSC)
++ wPortChange |= USB_PORT_STAT_C_CONNECTION;
++ if (status & USBPORTSC_PEC)
++ wPortChange |= USB_PORT_STAT_C_ENABLE;
++ if ((status & USBPORTSC_OCC) && !ignore_oc)
++ wPortChange |= USB_PORT_STAT_C_OVERCURRENT;
++
++ if (test_bit(port, &uhci->port_c_suspend)) {
++ wPortChange |= USB_PORT_STAT_C_SUSPEND;
++ lstatus |= 1;
++ }
++ if (test_bit(port, &uhci->resuming_ports))
++ lstatus |= 4;
++
++ /* UHCI has no power switching (always on) */
++ wPortStatus = USB_PORT_STAT_POWER;
++ if (status & USBPORTSC_CCS)
++ wPortStatus |= USB_PORT_STAT_CONNECTION;
++ if (status & USBPORTSC_PE) {
++ wPortStatus |= USB_PORT_STAT_ENABLE;
++ if (status & SUSPEND_BITS)
++ wPortStatus |= USB_PORT_STAT_SUSPEND;
++ }
++ if (status & USBPORTSC_OC)
++ wPortStatus |= USB_PORT_STAT_OVERCURRENT;
++ if (status & USBPORTSC_PR)
++ wPortStatus |= USB_PORT_STAT_RESET;
++ if (status & USBPORTSC_LSDA)
++ wPortStatus |= USB_PORT_STAT_LOW_SPEED;
++
++ if (wPortChange)
++ dev_dbg(uhci_dev(uhci), "port %d portsc %04x,%02x\n",
++ wIndex, status, lstatus);
++
++ *(__le16 *)buf = cpu_to_le16(wPortStatus);
++ *(__le16 *)(buf + 2) = cpu_to_le16(wPortChange);
++ OK(4);
++ case SetHubFeature: /* We don't implement these */
++ case ClearHubFeature:
++ switch (wValue) {
++ case C_HUB_OVER_CURRENT:
++ case C_HUB_LOCAL_POWER:
++ OK(0);
++ default:
++ goto err;
++ }
++ break;
++ case SetPortFeature:
++ if (port >= uhci->rh_numports)
++ goto err;
++
++ switch (wValue) {
++ case USB_PORT_FEAT_SUSPEND:
++ SET_RH_PORTSTAT(USBPORTSC_SUSP);
++ OK(0);
++ case USB_PORT_FEAT_RESET:
++ SET_RH_PORTSTAT(USBPORTSC_PR);
++
++ /* Reset terminates Resume signalling */
++ uhci_finish_suspend(uhci, port, port_addr);
++
++ /* USB v2.0 7.1.7.5 */
++ uhci->ports_timeout = jiffies + msecs_to_jiffies(50);
++ OK(0);
++ case USB_PORT_FEAT_POWER:
++ /* UHCI has no power switching */
++ OK(0);
++ default:
++ goto err;
++ }
++ break;
++ case ClearPortFeature:
++ if (port >= uhci->rh_numports)
++ goto err;
++
++ switch (wValue) {
++ case USB_PORT_FEAT_ENABLE:
++ CLR_RH_PORTSTAT(USBPORTSC_PE);
++
++ /* Disable terminates Resume signalling */
++ uhci_finish_suspend(uhci, port, port_addr);
++ OK(0);
++ case USB_PORT_FEAT_C_ENABLE:
++ CLR_RH_PORTSTAT(USBPORTSC_PEC);
++ OK(0);
++ case USB_PORT_FEAT_SUSPEND:
++//yriver
++// if (!(inw(port_addr) & USBPORTSC_SUSP)) {
++ if (!(readl(port_addr) & USBPORTSC_SUSP)) {
++
++ /* Make certain the port isn't suspended */
++ uhci_finish_suspend(uhci, port, port_addr);
++ } else if (!test_and_set_bit(port,
++ &uhci->resuming_ports)) {
++ SET_RH_PORTSTAT(USBPORTSC_RD);
++
++ /* The controller won't allow RD to be set
++ * if the port is disabled. When this happens
++ * just skip the Resume signalling.
++ */
++//yriver
++// if (!(inw(port_addr) & USBPORTSC_RD))
++ if (!(readl(port_addr) & USBPORTSC_RD))
++ uhci_finish_suspend(uhci, port,
++ port_addr);
++ else
++ /* USB v2.0 7.1.7.7 */
++ uhci->ports_timeout = jiffies +
++ msecs_to_jiffies(20);
++ }
++ OK(0);
++ case USB_PORT_FEAT_C_SUSPEND:
++ clear_bit(port, &uhci->port_c_suspend);
++ OK(0);
++ case USB_PORT_FEAT_POWER:
++ /* UHCI has no power switching */
++ goto err;
++ case USB_PORT_FEAT_C_CONNECTION:
++ CLR_RH_PORTSTAT(USBPORTSC_CSC);
++ OK(0);
++ case USB_PORT_FEAT_C_OVER_CURRENT:
++ CLR_RH_PORTSTAT(USBPORTSC_OCC);
++ OK(0);
++ case USB_PORT_FEAT_C_RESET:
++ /* this driver won't report these */
++ OK(0);
++ default:
++ goto err;
++ }
++ break;
++ case GetHubDescriptor:
++ len = min_t(unsigned int, sizeof(root_hub_hub_des), wLength);
++ memcpy(buf, root_hub_hub_des, len);
++ if (len > 2)
++ buf[2] = uhci->rh_numports;
++ OK(len);
++ default:
++err:
++ retval = -EPIPE;
++ }
++ spin_unlock_irqrestore(&uhci->lock, flags);
++
++ return retval;
++}
+diff --git a/drivers/usb/astuhci/uhci-q.c b/drivers/usb/astuhci/uhci-q.c
+new file mode 100644
+index 0000000..eb24599
+--- /dev/null
++++ b/drivers/usb/astuhci/uhci-q.c
+@@ -0,0 +1,1760 @@
++/********************************************************************************
++* File Name : uhci-q.c
++*
++* port from uhci-q.c
++* This program is free software; you can redistribute it and/or modify
++* it under the terms of the GNU General Public License as published by the Free Software Foundation;
++* either version 2 of the License, or (at your option) any later version.
++* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
++* without even the implied warranty of MERCHANTABILITY or
++* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
++* You should have received a copy of the GNU General Public License
++* along with this program; if not, write to the Free Software
++* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++********************************************************************************/
++static void uhci_set_next_interrupt(struct uhci_hcd *uhci)
++{
++ if (uhci->is_stopped)
++ mod_timer(&uhci_to_hcd(uhci)->rh_timer, jiffies);
++ uhci->term_td->status |= cpu_to_le32(TD_CTRL_IOC);
++}
++
++static inline void uhci_clear_next_interrupt(struct uhci_hcd *uhci)
++{
++ uhci->term_td->status &= ~cpu_to_le32(TD_CTRL_IOC);
++}
++
++
++/*
++ * Full-Speed Bandwidth Reclamation (FSBR).
++ * We turn on FSBR whenever a queue that wants it is advancing,
++ * and leave it on for a short time thereafter.
++ */
++static void uhci_fsbr_on(struct uhci_hcd *uhci)
++{
++ struct uhci_qh *lqh;
++
++ /* The terminating skeleton QH always points back to the first
++ * FSBR QH. Make the last async QH point to the terminating
++ * skeleton QH. */
++ uhci->fsbr_is_on = 1;
++ lqh = list_entry(uhci->skel_async_qh->node.prev,
++ struct uhci_qh, node);
++ lqh->link = LINK_TO_QH(uhci->skel_term_qh);
++}
++
++static void uhci_fsbr_off(struct uhci_hcd *uhci)
++{
++ struct uhci_qh *lqh;
++
++ /* Remove the link from the last async QH to the terminating
++ * skeleton QH. */
++ uhci->fsbr_is_on = 0;
++ lqh = list_entry(uhci->skel_async_qh->node.prev,
++ struct uhci_qh, node);
++ lqh->link = UHCI_PTR_TERM;
++}
++
++static void uhci_add_fsbr(struct uhci_hcd *uhci, struct urb *urb)
++{
++ struct urb_priv *urbp = urb->hcpriv;
++
++ if (!(urb->transfer_flags & URB_NO_FSBR))
++ urbp->fsbr = 1;
++}
++
++static void uhci_urbp_wants_fsbr(struct uhci_hcd *uhci, struct urb_priv *urbp)
++{
++ if (urbp->fsbr) {
++ uhci->fsbr_is_wanted = 1;
++ if (!uhci->fsbr_is_on)
++ uhci_fsbr_on(uhci);
++ else if (uhci->fsbr_expiring) {
++ uhci->fsbr_expiring = 0;
++ del_timer(&uhci->fsbr_timer);
++ }
++ }
++}
++
++static void uhci_fsbr_timeout(unsigned long _uhci)
++{
++ struct uhci_hcd *uhci = (struct uhci_hcd *) _uhci;
++ unsigned long flags;
++
++ spin_lock_irqsave(&uhci->lock, flags);
++ if (uhci->fsbr_expiring) {
++ uhci->fsbr_expiring = 0;
++ uhci_fsbr_off(uhci);
++ }
++ spin_unlock_irqrestore(&uhci->lock, flags);
++}
++
++
++static struct uhci_td *uhci_alloc_td(struct uhci_hcd *uhci)
++{
++ dma_addr_t dma_handle;
++ struct uhci_td *td;
++
++ td = dma_pool_alloc(uhci->td_pool, GFP_ATOMIC, &dma_handle);
++ if (!td)
++ return NULL;
++
++ td->dma_handle = dma_handle;
++ td->frame = -1;
++
++ INIT_LIST_HEAD(&td->list);
++ INIT_LIST_HEAD(&td->fl_list);
++
++ return td;
++}
++
++static void uhci_free_td(struct uhci_hcd *uhci, struct uhci_td *td)
++{
++ if (!list_empty(&td->list))
++ dev_WARN(uhci_dev(uhci), "td %p still in list!\n", td);
++ if (!list_empty(&td->fl_list))
++ dev_WARN(uhci_dev(uhci), "td %p still in fl_list!\n", td);
++
++ dma_pool_free(uhci->td_pool, td, td->dma_handle);
++}
++
++static inline void uhci_fill_td(struct uhci_td *td, u32 status,
++ u32 token, u32 buffer)
++{
++ td->status = cpu_to_le32(status);
++ td->token = cpu_to_le32(token);
++ td->buffer = cpu_to_le32(buffer);
++}
++
++static void uhci_add_td_to_urbp(struct uhci_td *td, struct urb_priv *urbp)
++{
++ list_add_tail(&td->list, &urbp->td_list);
++}
++
++static void uhci_remove_td_from_urbp(struct uhci_td *td)
++{
++ list_del_init(&td->list);
++}
++
++/*
++ * We insert Isochronous URBs directly into the frame list at the beginning
++ */
++static inline void uhci_insert_td_in_frame_list(struct uhci_hcd *uhci,
++ struct uhci_td *td, unsigned framenum)
++{
++ framenum &= (UHCI_NUMFRAMES - 1);
++
++ td->frame = framenum;
++
++ /* Is there a TD already mapped there? */
++ if (uhci->frame_cpu[framenum]) {
++ struct uhci_td *ftd, *ltd;
++
++ ftd = uhci->frame_cpu[framenum];
++ ltd = list_entry(ftd->fl_list.prev, struct uhci_td, fl_list);
++
++ list_add_tail(&td->fl_list, &ftd->fl_list);
++
++ td->link = ltd->link;
++ wmb();
++ ltd->link = LINK_TO_TD(td);
++ } else {
++ td->link = uhci->frame[framenum];
++ wmb();
++ uhci->frame[framenum] = LINK_TO_TD(td);
++ uhci->frame_cpu[framenum] = td;
++ }
++}
++
++static inline void uhci_remove_td_from_frame_list(struct uhci_hcd *uhci,
++ struct uhci_td *td)
++{
++ /* If it's not inserted, don't remove it */
++ if (td->frame == -1) {
++ WARN_ON(!list_empty(&td->fl_list));
++ return;
++ }
++
++ if (uhci->frame_cpu[td->frame] == td) {
++ if (list_empty(&td->fl_list)) {
++ uhci->frame[td->frame] = td->link;
++ uhci->frame_cpu[td->frame] = NULL;
++ } else {
++ struct uhci_td *ntd;
++
++ ntd = list_entry(td->fl_list.next, struct uhci_td, fl_list);
++ uhci->frame[td->frame] = LINK_TO_TD(ntd);
++ uhci->frame_cpu[td->frame] = ntd;
++ }
++ } else {
++ struct uhci_td *ptd;
++
++ ptd = list_entry(td->fl_list.prev, struct uhci_td, fl_list);
++ ptd->link = td->link;
++ }
++
++ list_del_init(&td->fl_list);
++ td->frame = -1;
++}
++
++static inline void uhci_remove_tds_from_frame(struct uhci_hcd *uhci,
++ unsigned int framenum)
++{
++ struct uhci_td *ftd, *ltd;
++
++ framenum &= (UHCI_NUMFRAMES - 1);
++
++ ftd = uhci->frame_cpu[framenum];
++ if (ftd) {
++ ltd = list_entry(ftd->fl_list.prev, struct uhci_td, fl_list);
++ uhci->frame[framenum] = ltd->link;
++ uhci->frame_cpu[framenum] = NULL;
++
++ while (!list_empty(&ftd->fl_list))
++ list_del_init(ftd->fl_list.prev);
++ }
++}
++
++/*
++ * Remove all the TDs for an Isochronous URB from the frame list
++ */
++static void uhci_unlink_isochronous_tds(struct uhci_hcd *uhci, struct urb *urb)
++{
++ struct urb_priv *urbp = (struct urb_priv *) urb->hcpriv;
++ struct uhci_td *td;
++
++ list_for_each_entry(td, &urbp->td_list, list)
++ uhci_remove_td_from_frame_list(uhci, td);
++}
++
++static struct uhci_qh *uhci_alloc_qh(struct uhci_hcd *uhci,
++ struct usb_device *udev, struct usb_host_endpoint *hep)
++{
++ dma_addr_t dma_handle;
++ struct uhci_qh *qh;
++
++ qh = dma_pool_alloc(uhci->qh_pool, GFP_ATOMIC, &dma_handle);
++ if (!qh)
++ return NULL;
++
++ memset(qh, 0, sizeof(*qh));
++ qh->dma_handle = dma_handle;
++
++ qh->element = UHCI_PTR_TERM;
++ qh->link = UHCI_PTR_TERM;
++
++ INIT_LIST_HEAD(&qh->queue);
++ INIT_LIST_HEAD(&qh->node);
++
++ if (udev) { /* Normal QH */
++ qh->type = hep->desc.bmAttributes & USB_ENDPOINT_XFERTYPE_MASK;
++ if (qh->type != USB_ENDPOINT_XFER_ISOC) {
++ qh->dummy_td = uhci_alloc_td(uhci);
++ if (!qh->dummy_td) {
++ dma_pool_free(uhci->qh_pool, qh, dma_handle);
++ return NULL;
++ }
++ }
++//yriver
++// qh->state = QH_STATE_IDLE;
++ qh->state = UHCI_QH_STATE_IDLE;
++ qh->hep = hep;
++ qh->udev = udev;
++ hep->hcpriv = qh;
++
++ if (qh->type == USB_ENDPOINT_XFER_INT ||
++ qh->type == USB_ENDPOINT_XFER_ISOC)
++ qh->load = usb_calc_bus_time(udev->speed,
++ usb_endpoint_dir_in(&hep->desc),
++ qh->type == USB_ENDPOINT_XFER_ISOC,
++ le16_to_cpu(hep->desc.wMaxPacketSize))
++ / 1000 + 1;
++
++ } else { /* Skeleton QH */
++ qh->state = QH_STATE_ACTIVE;
++ qh->type = -1;
++ }
++ return qh;
++}
++
++static void uhci_free_qh(struct uhci_hcd *uhci, struct uhci_qh *qh)
++{
++//yriver
++// WARN_ON(qh->state != QH_STATE_IDLE && qh->udev);
++ WARN_ON(qh->state != UHCI_QH_STATE_IDLE && qh->udev);
++ if (!list_empty(&qh->queue))
++ dev_WARN(uhci_dev(uhci), "qh %p list not empty!\n", qh);
++
++ list_del(&qh->node);
++ if (qh->udev) {
++ qh->hep->hcpriv = NULL;
++ if (qh->dummy_td)
++ uhci_free_td(uhci, qh->dummy_td);
++ }
++ dma_pool_free(uhci->qh_pool, qh, qh->dma_handle);
++}
++
++/*
++ * When a queue is stopped and a dequeued URB is given back, adjust
++ * the previous TD link (if the URB isn't first on the queue) or
++ * save its toggle value (if it is first and is currently executing).
++ *
++ * Returns 0 if the URB should not yet be given back, 1 otherwise.
++ */
++static int uhci_cleanup_queue(struct uhci_hcd *uhci, struct uhci_qh *qh,
++ struct urb *urb)
++{
++ struct urb_priv *urbp = urb->hcpriv;
++ struct uhci_td *td;
++ int ret = 1;
++
++ /* Isochronous pipes don't use toggles and their TD link pointers
++ * get adjusted during uhci_urb_dequeue(). But since their queues
++ * cannot truly be stopped, we have to watch out for dequeues
++ * occurring after the nominal unlink frame. */
++ if (qh->type == USB_ENDPOINT_XFER_ISOC) {
++ ret = (uhci->frame_number + uhci->is_stopped !=
++ qh->unlink_frame);
++ goto done;
++ }
++
++ /* If the URB isn't first on its queue, adjust the link pointer
++ * of the last TD in the previous URB. The toggle doesn't need
++ * to be saved since this URB can't be executing yet. */
++ if (qh->queue.next != &urbp->node) {
++ struct urb_priv *purbp;
++ struct uhci_td *ptd;
++
++ purbp = list_entry(urbp->node.prev, struct urb_priv, node);
++ WARN_ON(list_empty(&purbp->td_list));
++ ptd = list_entry(purbp->td_list.prev, struct uhci_td,
++ list);
++ td = list_entry(urbp->td_list.prev, struct uhci_td,
++ list);
++ ptd->link = td->link;
++ goto done;
++ }
++
++ /* If the QH element pointer is UHCI_PTR_TERM then then currently
++ * executing URB has already been unlinked, so this one isn't it. */
++ if (qh_element(qh) == UHCI_PTR_TERM)
++ goto done;
++ qh->element = UHCI_PTR_TERM;
++
++ /* Control pipes don't have to worry about toggles */
++ if (qh->type == USB_ENDPOINT_XFER_CONTROL)
++ goto done;
++
++ /* Save the next toggle value */
++ WARN_ON(list_empty(&urbp->td_list));
++ td = list_entry(urbp->td_list.next, struct uhci_td, list);
++ qh->needs_fixup = 1;
++ qh->initial_toggle = uhci_toggle(td_token(td));
++
++done:
++ return ret;
++}
++
++/*
++ * Fix up the data toggles for URBs in a queue, when one of them
++ * terminates early (short transfer, error, or dequeued).
++ */
++static void uhci_fixup_toggles(struct uhci_qh *qh, int skip_first)
++{
++ struct urb_priv *urbp = NULL;
++ struct uhci_td *td;
++ unsigned int toggle = qh->initial_toggle;
++ unsigned int pipe;
++
++ /* Fixups for a short transfer start with the second URB in the
++ * queue (the short URB is the first). */
++ if (skip_first)
++ urbp = list_entry(qh->queue.next, struct urb_priv, node);
++
++ /* When starting with the first URB, if the QH element pointer is
++ * still valid then we know the URB's toggles are okay. */
++ else if (qh_element(qh) != UHCI_PTR_TERM)
++ toggle = 2;
++
++ /* Fix up the toggle for the URBs in the queue. Normally this
++ * loop won't run more than once: When an error or short transfer
++ * occurs, the queue usually gets emptied. */
++ urbp = list_prepare_entry(urbp, &qh->queue, node);
++ list_for_each_entry_continue(urbp, &qh->queue, node) {
++
++ /* If the first TD has the right toggle value, we don't
++ * need to change any toggles in this URB */
++ td = list_entry(urbp->td_list.next, struct uhci_td, list);
++ if (toggle > 1 || uhci_toggle(td_token(td)) == toggle) {
++ td = list_entry(urbp->td_list.prev, struct uhci_td,
++ list);
++ toggle = uhci_toggle(td_token(td)) ^ 1;
++
++ /* Otherwise all the toggles in the URB have to be switched */
++ } else {
++ list_for_each_entry(td, &urbp->td_list, list) {
++ td->token ^= __constant_cpu_to_le32(
++ TD_TOKEN_TOGGLE);
++ toggle ^= 1;
++ }
++ }
++ }
++
++ wmb();
++ pipe = list_entry(qh->queue.next, struct urb_priv, node)->urb->pipe;
++ usb_settoggle(qh->udev, usb_pipeendpoint(pipe),
++ usb_pipeout(pipe), toggle);
++ qh->needs_fixup = 0;
++}
++
++/*
++ * Link an Isochronous QH into its skeleton's list
++ */
++static inline void link_iso(struct uhci_hcd *uhci, struct uhci_qh *qh)
++{
++ list_add_tail(&qh->node, &uhci->skel_iso_qh->node);
++
++ /* Isochronous QHs aren't linked by the hardware */
++}
++
++/*
++ * Link a high-period interrupt QH into the schedule at the end of its
++ * skeleton's list
++ */
++static void link_interrupt(struct uhci_hcd *uhci, struct uhci_qh *qh)
++{
++ struct uhci_qh *pqh;
++
++ list_add_tail(&qh->node, &uhci->skelqh[qh->skel]->node);
++
++ pqh = list_entry(qh->node.prev, struct uhci_qh, node);
++ qh->link = pqh->link;
++ wmb();
++ pqh->link = LINK_TO_QH(qh);
++}
++
++/*
++ * Link a period-1 interrupt or async QH into the schedule at the
++ * correct spot in the async skeleton's list, and update the FSBR link
++ */
++static void link_async(struct uhci_hcd *uhci, struct uhci_qh *qh)
++{
++ struct uhci_qh *pqh;
++ __le32 link_to_new_qh;
++
++ /* Find the predecessor QH for our new one and insert it in the list.
++ * The list of QHs is expected to be short, so linear search won't
++ * take too long. */
++ list_for_each_entry_reverse(pqh, &uhci->skel_async_qh->node, node) {
++ if (pqh->skel <= qh->skel)
++ break;
++ }
++ list_add(&qh->node, &pqh->node);
++
++ /* Link it into the schedule */
++ qh->link = pqh->link;
++ wmb();
++ link_to_new_qh = LINK_TO_QH(qh);
++ pqh->link = link_to_new_qh;
++
++ /* If this is now the first FSBR QH, link the terminating skeleton
++ * QH to it. */
++ if (pqh->skel < SKEL_FSBR && qh->skel >= SKEL_FSBR)
++ uhci->skel_term_qh->link = link_to_new_qh;
++}
++
++/*
++ * Put a QH on the schedule in both hardware and software
++ */
++static void uhci_activate_qh(struct uhci_hcd *uhci, struct uhci_qh *qh)
++{
++ WARN_ON(list_empty(&qh->queue));
++
++ /* Set the element pointer if it isn't set already.
++ * This isn't needed for Isochronous queues, but it doesn't hurt. */
++ if (qh_element(qh) == UHCI_PTR_TERM) {
++ struct urb_priv *urbp = list_entry(qh->queue.next,
++ struct urb_priv, node);
++ struct uhci_td *td = list_entry(urbp->td_list.next,
++ struct uhci_td, list);
++
++ qh->element = LINK_TO_TD(td);
++ }
++
++ /* Treat the queue as if it has just advanced */
++ qh->wait_expired = 0;
++ qh->advance_jiffies = jiffies;
++
++ if (qh->state == QH_STATE_ACTIVE)
++ return;
++ qh->state = QH_STATE_ACTIVE;
++
++ /* Move the QH from its old list to the correct spot in the appropriate
++ * skeleton's list */
++ if (qh == uhci->next_qh)
++ uhci->next_qh = list_entry(qh->node.next, struct uhci_qh,
++ node);
++ list_del(&qh->node);
++
++ if (qh->skel == SKEL_ISO)
++ link_iso(uhci, qh);
++ else if (qh->skel < SKEL_ASYNC)
++ link_interrupt(uhci, qh);
++ else
++ link_async(uhci, qh);
++}
++
++/*
++ * Unlink a high-period interrupt QH from the schedule
++ */
++static void unlink_interrupt(struct uhci_hcd *uhci, struct uhci_qh *qh)
++{
++ struct uhci_qh *pqh;
++
++ pqh = list_entry(qh->node.prev, struct uhci_qh, node);
++ pqh->link = qh->link;
++ mb();
++}
++
++/*
++ * Unlink a period-1 interrupt or async QH from the schedule
++ */
++static void unlink_async(struct uhci_hcd *uhci, struct uhci_qh *qh)
++{
++ struct uhci_qh *pqh;
++ __le32 link_to_next_qh = qh->link;
++
++ pqh = list_entry(qh->node.prev, struct uhci_qh, node);
++ pqh->link = link_to_next_qh;
++
++ /* If this was the old first FSBR QH, link the terminating skeleton
++ * QH to the next (new first FSBR) QH. */
++ if (pqh->skel < SKEL_FSBR && qh->skel >= SKEL_FSBR)
++ uhci->skel_term_qh->link = link_to_next_qh;
++ mb();
++}
++
++/*
++ * Take a QH off the hardware schedule
++ */
++static void uhci_unlink_qh(struct uhci_hcd *uhci, struct uhci_qh *qh)
++{
++ if (qh->state == QH_STATE_UNLINKING)
++ return;
++ WARN_ON(qh->state != QH_STATE_ACTIVE || !qh->udev);
++ qh->state = QH_STATE_UNLINKING;
++
++ /* Unlink the QH from the schedule and record when we did it */
++ if (qh->skel == SKEL_ISO)
++ ;
++ else if (qh->skel < SKEL_ASYNC)
++ unlink_interrupt(uhci, qh);
++ else
++ unlink_async(uhci, qh);
++
++ uhci_get_current_frame_number(uhci);
++ qh->unlink_frame = uhci->frame_number;
++
++ /* Force an interrupt so we know when the QH is fully unlinked */
++ if (list_empty(&uhci->skel_unlink_qh->node))
++ uhci_set_next_interrupt(uhci);
++
++ /* Move the QH from its old list to the end of the unlinking list */
++ if (qh == uhci->next_qh)
++ uhci->next_qh = list_entry(qh->node.next, struct uhci_qh,
++ node);
++ list_move_tail(&qh->node, &uhci->skel_unlink_qh->node);
++}
++
++/*
++ * When we and the controller are through with a QH, it becomes IDLE.
++ * This happens when a QH has been off the schedule (on the unlinking
++ * list) for more than one frame, or when an error occurs while adding
++ * the first URB onto a new QH.
++ */
++static void uhci_make_qh_idle(struct uhci_hcd *uhci, struct uhci_qh *qh)
++{
++ WARN_ON(qh->state == QH_STATE_ACTIVE);
++
++ if (qh == uhci->next_qh)
++ uhci->next_qh = list_entry(qh->node.next, struct uhci_qh,
++ node);
++ list_move(&qh->node, &uhci->idle_qh_list);
++//yriver
++// qh->state = QH_STATE_IDLE;
++ qh->state = UHCI_QH_STATE_IDLE;
++
++ /* Now that the QH is idle, its post_td isn't being used */
++ if (qh->post_td) {
++ uhci_free_td(uhci, qh->post_td);
++ qh->post_td = NULL;
++ }
++
++ /* If anyone is waiting for a QH to become idle, wake them up */
++ if (uhci->num_waiting)
++ wake_up_all(&uhci->waitqh);
++}
++
++/*
++ * Find the highest existing bandwidth load for a given phase and period.
++ */
++static int uhci_highest_load(struct uhci_hcd *uhci, int phase, int period)
++{
++ int highest_load = uhci->load[phase];
++
++ for (phase += period; phase < MAX_PHASE; phase += period)
++ highest_load = max_t(int, highest_load, uhci->load[phase]);
++ return highest_load;
++}
++
++/*
++ * Set qh->phase to the optimal phase for a periodic transfer and
++ * check whether the bandwidth requirement is acceptable.
++ */
++static int uhci_check_bandwidth(struct uhci_hcd *uhci, struct uhci_qh *qh)
++{
++ int minimax_load;
++
++ /* Find the optimal phase (unless it is already set) and get
++ * its load value. */
++ if (qh->phase >= 0)
++ minimax_load = uhci_highest_load(uhci, qh->phase, qh->period);
++ else {
++ int phase, load;
++ int max_phase = min_t(int, MAX_PHASE, qh->period);
++
++ qh->phase = 0;
++ minimax_load = uhci_highest_load(uhci, qh->phase, qh->period);
++ for (phase = 1; phase < max_phase; ++phase) {
++ load = uhci_highest_load(uhci, phase, qh->period);
++ if (load < minimax_load) {
++ minimax_load = load;
++ qh->phase = phase;
++ }
++ }
++ }
++
++ /* Maximum allowable periodic bandwidth is 90%, or 900 us per frame */
++ if (minimax_load + qh->load > 900) {
++ dev_dbg(uhci_dev(uhci), "bandwidth allocation failed: "
++ "period %d, phase %d, %d + %d us\n",
++ qh->period, qh->phase, minimax_load, qh->load);
++ return -ENOSPC;
++ }
++ return 0;
++}
++
++/*
++ * Reserve a periodic QH's bandwidth in the schedule
++ */
++static void uhci_reserve_bandwidth(struct uhci_hcd *uhci, struct uhci_qh *qh)
++{
++ int i;
++ int load = qh->load;
++ char *p = "??";
++
++ for (i = qh->phase; i < MAX_PHASE; i += qh->period) {
++ uhci->load[i] += load;
++ uhci->total_load += load;
++ }
++ uhci_to_hcd(uhci)->self.bandwidth_allocated =
++ uhci->total_load / MAX_PHASE;
++ switch (qh->type) {
++ case USB_ENDPOINT_XFER_INT:
++ ++uhci_to_hcd(uhci)->self.bandwidth_int_reqs;
++ p = "INT";
++ break;
++ case USB_ENDPOINT_XFER_ISOC:
++ ++uhci_to_hcd(uhci)->self.bandwidth_isoc_reqs;
++ p = "ISO";
++ break;
++ }
++ qh->bandwidth_reserved = 1;
++ dev_dbg(uhci_dev(uhci),
++ "%s dev %d ep%02x-%s, period %d, phase %d, %d us\n",
++ "reserve", qh->udev->devnum,
++ qh->hep->desc.bEndpointAddress, p,
++ qh->period, qh->phase, load);
++}
++
++/*
++ * Release a periodic QH's bandwidth reservation
++ */
++static void uhci_release_bandwidth(struct uhci_hcd *uhci, struct uhci_qh *qh)
++{
++ int i;
++ int load = qh->load;
++ char *p = "??";
++
++ for (i = qh->phase; i < MAX_PHASE; i += qh->period) {
++ uhci->load[i] -= load;
++ uhci->total_load -= load;
++ }
++ uhci_to_hcd(uhci)->self.bandwidth_allocated =
++ uhci->total_load / MAX_PHASE;
++ switch (qh->type) {
++ case USB_ENDPOINT_XFER_INT:
++ --uhci_to_hcd(uhci)->self.bandwidth_int_reqs;
++ p = "INT";
++ break;
++ case USB_ENDPOINT_XFER_ISOC:
++ --uhci_to_hcd(uhci)->self.bandwidth_isoc_reqs;
++ p = "ISO";
++ break;
++ }
++ qh->bandwidth_reserved = 0;
++ dev_dbg(uhci_dev(uhci),
++ "%s dev %d ep%02x-%s, period %d, phase %d, %d us\n",
++ "release", qh->udev->devnum,
++ qh->hep->desc.bEndpointAddress, p,
++ qh->period, qh->phase, load);
++}
++
++static inline struct urb_priv *uhci_alloc_urb_priv(struct uhci_hcd *uhci,
++ struct urb *urb)
++{
++ struct urb_priv *urbp;
++
++ urbp = kmem_cache_zalloc(uhci_up_cachep, GFP_ATOMIC);
++ if (!urbp)
++ return NULL;
++
++ urbp->urb = urb;
++ urb->hcpriv = urbp;
++
++ INIT_LIST_HEAD(&urbp->node);
++ INIT_LIST_HEAD(&urbp->td_list);
++
++ return urbp;
++}
++
++static void uhci_free_urb_priv(struct uhci_hcd *uhci,
++ struct urb_priv *urbp)
++{
++ struct uhci_td *td, *tmp;
++
++ if (!list_empty(&urbp->node))
++ dev_WARN(uhci_dev(uhci), "urb %p still on QH's list!\n",
++ urbp->urb);
++
++ list_for_each_entry_safe(td, tmp, &urbp->td_list, list) {
++ uhci_remove_td_from_urbp(td);
++ uhci_free_td(uhci, td);
++ }
++
++ kmem_cache_free(uhci_up_cachep, urbp);
++}
++
++/*
++ * Map status to standard result codes
++ *
++ * <status> is (td_status(td) & 0xF60000), a.k.a.
++ * uhci_status_bits(td_status(td)).
++ * Note: <status> does not include the TD_CTRL_NAK bit.
++ * <dir_out> is True for output TDs and False for input TDs.
++ */
++static int uhci_map_status(int status, int dir_out)
++{
++ if (!status)
++ return 0;
++ if (status & TD_CTRL_BITSTUFF) /* Bitstuff error */
++ return -EPROTO;
++ if (status & TD_CTRL_CRCTIMEO) { /* CRC/Timeout */
++ if (dir_out)
++ return -EPROTO;
++ else
++ return -EILSEQ;
++ }
++ if (status & TD_CTRL_BABBLE) /* Babble */
++ return -EOVERFLOW;
++ if (status & TD_CTRL_DBUFERR) /* Buffer error */
++ return -ENOSR;
++ if (status & TD_CTRL_STALLED) /* Stalled */
++ return -EPIPE;
++ return 0;
++}
++
++/*
++ * Control transfers
++ */
++static int uhci_submit_control(struct uhci_hcd *uhci, struct urb *urb,
++ struct uhci_qh *qh)
++{
++ struct uhci_td *td;
++ unsigned long destination, status;
++ int maxsze = le16_to_cpu(qh->hep->desc.wMaxPacketSize);
++ int len = urb->transfer_buffer_length;
++ dma_addr_t data = urb->transfer_dma;
++ __le32 *plink;
++ struct urb_priv *urbp = urb->hcpriv;
++ int skel;
++
++ /* The "pipe" thing contains the destination in bits 8--18 */
++ destination = (urb->pipe & PIPE_DEVEP_MASK) | USB_PID_SETUP;
++
++ /* 3 errors, dummy TD remains inactive */
++ status = uhci_maxerr(3);
++ if (urb->dev->speed == USB_SPEED_LOW)
++ status |= TD_CTRL_LS;
++
++ /*
++ * Build the TD for the control request setup packet
++ */
++ td = qh->dummy_td;
++ uhci_add_td_to_urbp(td, urbp);
++ uhci_fill_td(td, status, destination | uhci_explen(8),
++ urb->setup_dma);
++ plink = &td->link;
++ status |= TD_CTRL_ACTIVE;
++
++ /*
++ * If direction is "send", change the packet ID from SETUP (0x2D)
++ * to OUT (0xE1). Else change it from SETUP to IN (0x69) and
++ * set Short Packet Detect (SPD) for all data packets.
++ *
++ * 0-length transfers always get treated as "send".
++ */
++ if (usb_pipeout(urb->pipe) || len == 0)
++ destination ^= (USB_PID_SETUP ^ USB_PID_OUT);
++ else {
++ destination ^= (USB_PID_SETUP ^ USB_PID_IN);
++ status |= TD_CTRL_SPD;
++ }
++
++ /*
++ * Build the DATA TDs
++ */
++ while (len > 0) {
++ int pktsze = maxsze;
++
++ if (len <= pktsze) { /* The last data packet */
++ pktsze = len;
++ status &= ~TD_CTRL_SPD;
++ }
++
++ td = uhci_alloc_td(uhci);
++ if (!td)
++ goto nomem;
++ *plink = LINK_TO_TD(td);
++
++ /* Alternate Data0/1 (start with Data1) */
++ destination ^= TD_TOKEN_TOGGLE;
++
++ uhci_add_td_to_urbp(td, urbp);
++ uhci_fill_td(td, status, destination | uhci_explen(pktsze),
++ data);
++ plink = &td->link;
++
++ data += pktsze;
++ len -= pktsze;
++ }
++
++ /*
++ * Build the final TD for control status
++ */
++ td = uhci_alloc_td(uhci);
++ if (!td)
++ goto nomem;
++ *plink = LINK_TO_TD(td);
++
++ /* Change direction for the status transaction */
++ destination ^= (USB_PID_IN ^ USB_PID_OUT);
++ destination |= TD_TOKEN_TOGGLE; /* End in Data1 */
++
++ uhci_add_td_to_urbp(td, urbp);
++ uhci_fill_td(td, status | TD_CTRL_IOC,
++ destination | uhci_explen(0), 0);
++ plink = &td->link;
++
++ /*
++ * Build the new dummy TD and activate the old one
++ */
++ td = uhci_alloc_td(uhci);
++ if (!td)
++ goto nomem;
++ *plink = LINK_TO_TD(td);
++
++ uhci_fill_td(td, 0, USB_PID_OUT | uhci_explen(0), 0);
++ wmb();
++ qh->dummy_td->status |= __constant_cpu_to_le32(TD_CTRL_ACTIVE);
++ qh->dummy_td = td;
++
++ /* Low-speed transfers get a different queue, and won't hog the bus.
++ * Also, some devices enumerate better without FSBR; the easiest way
++ * to do that is to put URBs on the low-speed queue while the device
++ * isn't in the CONFIGURED state. */
++ if (urb->dev->speed == USB_SPEED_LOW ||
++ urb->dev->state != USB_STATE_CONFIGURED)
++ skel = SKEL_LS_CONTROL;
++ else {
++ skel = SKEL_FS_CONTROL;
++ uhci_add_fsbr(uhci, urb);
++ }
++ if (qh->state != QH_STATE_ACTIVE)
++ qh->skel = skel;
++
++ urb->actual_length = -8; /* Account for the SETUP packet */
++ return 0;
++
++nomem:
++ /* Remove the dummy TD from the td_list so it doesn't get freed */
++ uhci_remove_td_from_urbp(qh->dummy_td);
++ return -ENOMEM;
++}
++
++/*
++ * Common submit for bulk and interrupt
++ */
++static int uhci_submit_common(struct uhci_hcd *uhci, struct urb *urb,
++ struct uhci_qh *qh)
++{
++ struct uhci_td *td;
++ unsigned long destination, status;
++ int maxsze = le16_to_cpu(qh->hep->desc.wMaxPacketSize);
++ int len = urb->transfer_buffer_length;
++ dma_addr_t data = urb->transfer_dma;
++ __le32 *plink;
++ struct urb_priv *urbp = urb->hcpriv;
++ unsigned int toggle;
++
++ if (len < 0)
++ return -EINVAL;
++
++ /* The "pipe" thing contains the destination in bits 8--18 */
++ destination = (urb->pipe & PIPE_DEVEP_MASK) | usb_packetid(urb->pipe);
++ toggle = usb_gettoggle(urb->dev, usb_pipeendpoint(urb->pipe),
++ usb_pipeout(urb->pipe));
++
++ /* 3 errors, dummy TD remains inactive */
++ status = uhci_maxerr(3);
++ if (urb->dev->speed == USB_SPEED_LOW)
++ status |= TD_CTRL_LS;
++ if (usb_pipein(urb->pipe))
++ status |= TD_CTRL_SPD;
++
++ /*
++ * Build the DATA TDs
++ */
++ plink = NULL;
++ td = qh->dummy_td;
++ do { /* Allow zero length packets */
++ int pktsze = maxsze;
++
++ if (len <= pktsze) { /* The last packet */
++ pktsze = len;
++ if (!(urb->transfer_flags & URB_SHORT_NOT_OK))
++ status &= ~TD_CTRL_SPD;
++ }
++
++ if (plink) {
++ td = uhci_alloc_td(uhci);
++ if (!td)
++ goto nomem;
++ *plink = LINK_TO_TD(td);
++ }
++ uhci_add_td_to_urbp(td, urbp);
++ uhci_fill_td(td, status,
++ destination | uhci_explen(pktsze) |
++ (toggle << TD_TOKEN_TOGGLE_SHIFT),
++ data);
++ plink = &td->link;
++ status |= TD_CTRL_ACTIVE;
++
++ data += pktsze;
++ len -= maxsze;
++ toggle ^= 1;
++ } while (len > 0);
++
++ /*
++ * URB_ZERO_PACKET means adding a 0-length packet, if direction
++ * is OUT and the transfer_length was an exact multiple of maxsze,
++ * hence (len = transfer_length - N * maxsze) == 0
++ * however, if transfer_length == 0, the zero packet was already
++ * prepared above.
++ */
++ if ((urb->transfer_flags & URB_ZERO_PACKET) &&
++ usb_pipeout(urb->pipe) && len == 0 &&
++ urb->transfer_buffer_length > 0) {
++ td = uhci_alloc_td(uhci);
++ if (!td)
++ goto nomem;
++ *plink = LINK_TO_TD(td);
++
++ uhci_add_td_to_urbp(td, urbp);
++ uhci_fill_td(td, status,
++ destination | uhci_explen(0) |
++ (toggle << TD_TOKEN_TOGGLE_SHIFT),
++ data);
++ plink = &td->link;
++
++ toggle ^= 1;
++ }
++
++ /* Set the interrupt-on-completion flag on the last packet.
++ * A more-or-less typical 4 KB URB (= size of one memory page)
++ * will require about 3 ms to transfer; that's a little on the
++ * fast side but not enough to justify delaying an interrupt
++ * more than 2 or 3 URBs, so we will ignore the URB_NO_INTERRUPT
++ * flag setting. */
++ td->status |= __constant_cpu_to_le32(TD_CTRL_IOC);
++
++ /*
++ * Build the new dummy TD and activate the old one
++ */
++ td = uhci_alloc_td(uhci);
++ if (!td)
++ goto nomem;
++ *plink = LINK_TO_TD(td);
++
++ uhci_fill_td(td, 0, USB_PID_OUT | uhci_explen(0), 0);
++ wmb();
++ qh->dummy_td->status |= __constant_cpu_to_le32(TD_CTRL_ACTIVE);
++ qh->dummy_td = td;
++
++ usb_settoggle(urb->dev, usb_pipeendpoint(urb->pipe),
++ usb_pipeout(urb->pipe), toggle);
++ return 0;
++
++nomem:
++ /* Remove the dummy TD from the td_list so it doesn't get freed */
++ uhci_remove_td_from_urbp(qh->dummy_td);
++ return -ENOMEM;
++}
++
++static int uhci_submit_bulk(struct uhci_hcd *uhci, struct urb *urb,
++ struct uhci_qh *qh)
++{
++ int ret;
++
++ /* Can't have low-speed bulk transfers */
++ if (urb->dev->speed == USB_SPEED_LOW)
++ return -EINVAL;
++
++ if (qh->state != QH_STATE_ACTIVE)
++ qh->skel = SKEL_BULK;
++ ret = uhci_submit_common(uhci, urb, qh);
++ if (ret == 0)
++ uhci_add_fsbr(uhci, urb);
++ return ret;
++}
++
++static int uhci_submit_interrupt(struct uhci_hcd *uhci, struct urb *urb,
++ struct uhci_qh *qh)
++{
++ int ret;
++
++ /* USB 1.1 interrupt transfers only involve one packet per interval.
++ * Drivers can submit URBs of any length, but longer ones will need
++ * multiple intervals to complete.
++ */
++
++ if (!qh->bandwidth_reserved) {
++ int exponent;
++
++ /* Figure out which power-of-two queue to use */
++ for (exponent = 7; exponent >= 0; --exponent) {
++ if ((1 << exponent) <= urb->interval)
++ break;
++ }
++ if (exponent < 0)
++ return -EINVAL;
++
++ /* If the slot is full, try a lower period */
++ do {
++ qh->period = 1 << exponent;
++ qh->skel = SKEL_INDEX(exponent);
++
++ /* For now, interrupt phase is fixed by the layout
++ * of the QH lists.
++ */
++ qh->phase = (qh->period / 2) & (MAX_PHASE - 1);
++ ret = uhci_check_bandwidth(uhci, qh);
++ } while (ret != 0 && --exponent >= 0);
++ if (ret)
++ return ret;
++ } else if (qh->period > urb->interval)
++ return -EINVAL; /* Can't decrease the period */
++
++ ret = uhci_submit_common(uhci, urb, qh);
++ if (ret == 0) {
++ urb->interval = qh->period;
++ if (!qh->bandwidth_reserved)
++ uhci_reserve_bandwidth(uhci, qh);
++ }
++ return ret;
++}
++
++/*
++ * Fix up the data structures following a short transfer
++ */
++static int uhci_fixup_short_transfer(struct uhci_hcd *uhci,
++ struct uhci_qh *qh, struct urb_priv *urbp)
++{
++ struct uhci_td *td;
++ struct list_head *tmp;
++ int ret;
++
++ td = list_entry(urbp->td_list.prev, struct uhci_td, list);
++ if (qh->type == USB_ENDPOINT_XFER_CONTROL) {
++
++ /* When a control transfer is short, we have to restart
++ * the queue at the status stage transaction, which is
++ * the last TD. */
++ WARN_ON(list_empty(&urbp->td_list));
++ qh->element = LINK_TO_TD(td);
++ tmp = td->list.prev;
++ ret = -EINPROGRESS;
++
++ } else {
++
++ /* When a bulk/interrupt transfer is short, we have to
++ * fix up the toggles of the following URBs on the queue
++ * before restarting the queue at the next URB. */
++ qh->initial_toggle = uhci_toggle(td_token(qh->post_td)) ^ 1;
++ uhci_fixup_toggles(qh, 1);
++
++ if (list_empty(&urbp->td_list))
++ td = qh->post_td;
++ qh->element = td->link;
++ tmp = urbp->td_list.prev;
++ ret = 0;
++ }
++
++ /* Remove all the TDs we skipped over, from tmp back to the start */
++ while (tmp != &urbp->td_list) {
++ td = list_entry(tmp, struct uhci_td, list);
++ tmp = tmp->prev;
++
++ uhci_remove_td_from_urbp(td);
++ uhci_free_td(uhci, td);
++ }
++ return ret;
++}
++
++/*
++ * Common result for control, bulk, and interrupt
++ */
++static int uhci_result_common(struct uhci_hcd *uhci, struct urb *urb)
++{
++ struct urb_priv *urbp = urb->hcpriv;
++ struct uhci_qh *qh = urbp->qh;
++ struct uhci_td *td, *tmp;
++ unsigned status;
++ int ret = 0;
++
++ list_for_each_entry_safe(td, tmp, &urbp->td_list, list) {
++ unsigned int ctrlstat;
++ int len;
++
++ ctrlstat = td_status(td);
++ status = uhci_status_bits(ctrlstat);
++ if (status & TD_CTRL_ACTIVE)
++ return -EINPROGRESS;
++
++ len = uhci_actual_length(ctrlstat);
++ urb->actual_length += len;
++
++ if (status) {
++ ret = uhci_map_status(status,
++ uhci_packetout(td_token(td)));
++ if ((debug == 1 && ret != -EPIPE) || debug > 1) {
++ /* Some debugging code */
++ dev_dbg(&urb->dev->dev,
++ "%s: failed with status %x\n",
++ __func__, status);
++
++ if (debug > 1 && errbuf) {
++ /* Print the chain for debugging */
++ uhci_show_qh(uhci, urbp->qh, errbuf,
++ ERRBUF_LEN, 0);
++ lprintk(errbuf);
++ }
++ }
++
++ /* Did we receive a short packet? */
++ } else if (len < uhci_expected_length(td_token(td))) {
++
++ /* For control transfers, go to the status TD if
++ * this isn't already the last data TD */
++ if (qh->type == USB_ENDPOINT_XFER_CONTROL) {
++ if (td->list.next != urbp->td_list.prev)
++ ret = 1;
++ }
++
++ /* For bulk and interrupt, this may be an error */
++ else if (urb->transfer_flags & URB_SHORT_NOT_OK)
++ ret = -EREMOTEIO;
++
++ /* Fixup needed only if this isn't the URB's last TD */
++ else if (&td->list != urbp->td_list.prev)
++ ret = 1;
++ }
++
++ uhci_remove_td_from_urbp(td);
++ if (qh->post_td)
++ uhci_free_td(uhci, qh->post_td);
++ qh->post_td = td;
++
++ if (ret != 0)
++ goto err;
++ }
++ return ret;
++
++err:
++ if (ret < 0) {
++ /* Note that the queue has stopped and save
++ * the next toggle value */
++ qh->element = UHCI_PTR_TERM;
++ qh->is_stopped = 1;
++ qh->needs_fixup = (qh->type != USB_ENDPOINT_XFER_CONTROL);
++ qh->initial_toggle = uhci_toggle(td_token(td)) ^
++ (ret == -EREMOTEIO);
++
++ } else /* Short packet received */
++ ret = uhci_fixup_short_transfer(uhci, qh, urbp);
++ return ret;
++}
++
++/*
++ * Isochronous transfers
++ */
++static int uhci_submit_isochronous(struct uhci_hcd *uhci, struct urb *urb,
++ struct uhci_qh *qh)
++{
++ struct uhci_td *td = NULL; /* Since urb->number_of_packets > 0 */
++ int i, frame;
++ unsigned long destination, status;
++ struct urb_priv *urbp = (struct urb_priv *) urb->hcpriv;
++
++ /* Values must not be too big (could overflow below) */
++ if (urb->interval >= UHCI_NUMFRAMES ||
++ urb->number_of_packets >= UHCI_NUMFRAMES)
++ return -EFBIG;
++
++ /* Check the period and figure out the starting frame number */
++ if (!qh->bandwidth_reserved) {
++ qh->period = urb->interval;
++ if (urb->transfer_flags & URB_ISO_ASAP) {
++ qh->phase = -1; /* Find the best phase */
++ i = uhci_check_bandwidth(uhci, qh);
++ if (i)
++ return i;
++
++ /* Allow a little time to allocate the TDs */
++ uhci_get_current_frame_number(uhci);
++ frame = uhci->frame_number + 10;
++
++ /* Move forward to the first frame having the
++ * correct phase */
++ urb->start_frame = frame + ((qh->phase - frame) &
++ (qh->period - 1));
++ } else {
++ i = urb->start_frame - uhci->last_iso_frame;
++ if (i <= 0 || i >= UHCI_NUMFRAMES)
++ return -EINVAL;
++ qh->phase = urb->start_frame & (qh->period - 1);
++ i = uhci_check_bandwidth(uhci, qh);
++ if (i)
++ return i;
++ }
++
++ } else if (qh->period != urb->interval) {
++ return -EINVAL; /* Can't change the period */
++
++ } else {
++ /* Find the next unused frame */
++ if (list_empty(&qh->queue)) {
++ frame = qh->iso_frame;
++ } else {
++ struct urb *lurb;
++
++ lurb = list_entry(qh->queue.prev,
++ struct urb_priv, node)->urb;
++ frame = lurb->start_frame +
++ lurb->number_of_packets *
++ lurb->interval;
++ }
++ if (urb->transfer_flags & URB_ISO_ASAP) {
++ /* Skip some frames if necessary to insure
++ * the start frame is in the future.
++ */
++ uhci_get_current_frame_number(uhci);
++ if (uhci_frame_before_eq(frame, uhci->frame_number)) {
++ frame = uhci->frame_number + 1;
++ frame += ((qh->phase - frame) &
++ (qh->period - 1));
++ }
++ } /* Otherwise pick up where the last URB leaves off */
++ urb->start_frame = frame;
++ }
++
++ /* Make sure we won't have to go too far into the future */
++ if (uhci_frame_before_eq(uhci->last_iso_frame + UHCI_NUMFRAMES,
++ urb->start_frame + urb->number_of_packets *
++ urb->interval))
++ return -EFBIG;
++
++ status = TD_CTRL_ACTIVE | TD_CTRL_IOS;
++ destination = (urb->pipe & PIPE_DEVEP_MASK) | usb_packetid(urb->pipe);
++
++ for (i = 0; i < urb->number_of_packets; i++) {
++ td = uhci_alloc_td(uhci);
++ if (!td)
++ return -ENOMEM;
++
++ uhci_add_td_to_urbp(td, urbp);
++ uhci_fill_td(td, status, destination |
++ uhci_explen(urb->iso_frame_desc[i].length),
++ urb->transfer_dma +
++ urb->iso_frame_desc[i].offset);
++ }
++
++ /* Set the interrupt-on-completion flag on the last packet. */
++ td->status |= __constant_cpu_to_le32(TD_CTRL_IOC);
++
++ /* Add the TDs to the frame list */
++ frame = urb->start_frame;
++ list_for_each_entry(td, &urbp->td_list, list) {
++ uhci_insert_td_in_frame_list(uhci, td, frame);
++ frame += qh->period;
++ }
++
++ if (list_empty(&qh->queue)) {
++ qh->iso_packet_desc = &urb->iso_frame_desc[0];
++ qh->iso_frame = urb->start_frame;
++ }
++
++ qh->skel = SKEL_ISO;
++ if (!qh->bandwidth_reserved)
++ uhci_reserve_bandwidth(uhci, qh);
++ return 0;
++}
++
++static int uhci_result_isochronous(struct uhci_hcd *uhci, struct urb *urb)
++{
++ struct uhci_td *td, *tmp;
++ struct urb_priv *urbp = urb->hcpriv;
++ struct uhci_qh *qh = urbp->qh;
++
++ list_for_each_entry_safe(td, tmp, &urbp->td_list, list) {
++ unsigned int ctrlstat;
++ int status;
++ int actlength;
++
++ if (uhci_frame_before_eq(uhci->cur_iso_frame, qh->iso_frame))
++ return -EINPROGRESS;
++
++ uhci_remove_tds_from_frame(uhci, qh->iso_frame);
++
++ ctrlstat = td_status(td);
++ if (ctrlstat & TD_CTRL_ACTIVE) {
++ status = -EXDEV; /* TD was added too late? */
++ } else {
++ status = uhci_map_status(uhci_status_bits(ctrlstat),
++ usb_pipeout(urb->pipe));
++ actlength = uhci_actual_length(ctrlstat);
++
++ urb->actual_length += actlength;
++ qh->iso_packet_desc->actual_length = actlength;
++ qh->iso_packet_desc->status = status;
++ }
++ if (status)
++ urb->error_count++;
++
++ uhci_remove_td_from_urbp(td);
++ uhci_free_td(uhci, td);
++ qh->iso_frame += qh->period;
++ ++qh->iso_packet_desc;
++ }
++ return 0;
++}
++
++static int uhci_urb_enqueue(struct usb_hcd *hcd,
++ struct urb *urb, gfp_t mem_flags)
++{
++ int ret;
++ struct uhci_hcd *uhci = hcd_to_uhci(hcd);
++ unsigned long flags;
++ struct urb_priv *urbp;
++ struct uhci_qh *qh;
++
++ spin_lock_irqsave(&uhci->lock, flags);
++
++ ret = usb_hcd_link_urb_to_ep(hcd, urb);
++ if (ret)
++ goto done_not_linked;
++
++ ret = -ENOMEM;
++ urbp = uhci_alloc_urb_priv(uhci, urb);
++ if (!urbp)
++ goto done;
++
++ if (urb->ep->hcpriv)
++ qh = urb->ep->hcpriv;
++ else {
++ qh = uhci_alloc_qh(uhci, urb->dev, urb->ep);
++ if (!qh)
++ goto err_no_qh;
++ }
++ urbp->qh = qh;
++
++ switch (qh->type) {
++ case USB_ENDPOINT_XFER_CONTROL:
++ ret = uhci_submit_control(uhci, urb, qh);
++ break;
++ case USB_ENDPOINT_XFER_BULK:
++ ret = uhci_submit_bulk(uhci, urb, qh);
++ break;
++ case USB_ENDPOINT_XFER_INT:
++ ret = uhci_submit_interrupt(uhci, urb, qh);
++ break;
++ case USB_ENDPOINT_XFER_ISOC:
++ urb->error_count = 0;
++ ret = uhci_submit_isochronous(uhci, urb, qh);
++ break;
++ }
++ if (ret != 0)
++ goto err_submit_failed;
++
++ /* Add this URB to the QH */
++ urbp->qh = qh;
++ list_add_tail(&urbp->node, &qh->queue);
++
++ /* If the new URB is the first and only one on this QH then either
++ * the QH is new and idle or else it's unlinked and waiting to
++ * become idle, so we can activate it right away. But only if the
++ * queue isn't stopped. */
++ if (qh->queue.next == &urbp->node && !qh->is_stopped) {
++ uhci_activate_qh(uhci, qh);
++ uhci_urbp_wants_fsbr(uhci, urbp);
++ }
++ goto done;
++
++err_submit_failed:
++//yriver
++// if (qh->state == QH_STATE_IDLE)
++ if (qh->state == UHCI_QH_STATE_IDLE)
++ uhci_make_qh_idle(uhci, qh); /* Reclaim unused QH */
++err_no_qh:
++ uhci_free_urb_priv(uhci, urbp);
++done:
++ if (ret)
++ usb_hcd_unlink_urb_from_ep(hcd, urb);
++done_not_linked:
++ spin_unlock_irqrestore(&uhci->lock, flags);
++ return ret;
++}
++
++static int uhci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status)
++{
++ struct uhci_hcd *uhci = hcd_to_uhci(hcd);
++ unsigned long flags;
++ struct uhci_qh *qh;
++ int rc;
++
++ spin_lock_irqsave(&uhci->lock, flags);
++ rc = usb_hcd_check_unlink_urb(hcd, urb, status);
++ if (rc)
++ goto done;
++
++ qh = ((struct urb_priv *) urb->hcpriv)->qh;
++
++ /* Remove Isochronous TDs from the frame list ASAP */
++ if (qh->type == USB_ENDPOINT_XFER_ISOC) {
++ uhci_unlink_isochronous_tds(uhci, urb);
++ mb();
++
++ /* If the URB has already started, update the QH unlink time */
++ uhci_get_current_frame_number(uhci);
++ if (uhci_frame_before_eq(urb->start_frame, uhci->frame_number))
++ qh->unlink_frame = uhci->frame_number;
++ }
++
++ uhci_unlink_qh(uhci, qh);
++
++done:
++ spin_unlock_irqrestore(&uhci->lock, flags);
++ return rc;
++}
++
++/*
++ * Finish unlinking an URB and give it back
++ */
++static void uhci_giveback_urb(struct uhci_hcd *uhci, struct uhci_qh *qh,
++ struct urb *urb, int status)
++__releases(uhci->lock)
++__acquires(uhci->lock)
++{
++ struct urb_priv *urbp = (struct urb_priv *) urb->hcpriv;
++
++ if (qh->type == USB_ENDPOINT_XFER_CONTROL) {
++
++ /* urb->actual_length < 0 means the setup transaction didn't
++ * complete successfully. Either it failed or the URB was
++ * unlinked first. Regardless, don't confuse people with a
++ * negative length. */
++ urb->actual_length = max(urb->actual_length, 0);
++ }
++
++ /* When giving back the first URB in an Isochronous queue,
++ * reinitialize the QH's iso-related members for the next URB. */
++ else if (qh->type == USB_ENDPOINT_XFER_ISOC &&
++ urbp->node.prev == &qh->queue &&
++ urbp->node.next != &qh->queue) {
++ struct urb *nurb = list_entry(urbp->node.next,
++ struct urb_priv, node)->urb;
++
++ qh->iso_packet_desc = &nurb->iso_frame_desc[0];
++ qh->iso_frame = nurb->start_frame;
++ }
++
++ /* Take the URB off the QH's queue. If the queue is now empty,
++ * this is a perfect time for a toggle fixup. */
++ list_del_init(&urbp->node);
++ if (list_empty(&qh->queue) && qh->needs_fixup) {
++ usb_settoggle(urb->dev, usb_pipeendpoint(urb->pipe),
++ usb_pipeout(urb->pipe), qh->initial_toggle);
++ qh->needs_fixup = 0;
++ }
++
++ uhci_free_urb_priv(uhci, urbp);
++ usb_hcd_unlink_urb_from_ep(uhci_to_hcd(uhci), urb);
++
++ spin_unlock(&uhci->lock);
++ usb_hcd_giveback_urb(uhci_to_hcd(uhci), urb, status);
++ spin_lock(&uhci->lock);
++
++ /* If the queue is now empty, we can unlink the QH and give up its
++ * reserved bandwidth. */
++ if (list_empty(&qh->queue)) {
++ uhci_unlink_qh(uhci, qh);
++ if (qh->bandwidth_reserved)
++ uhci_release_bandwidth(uhci, qh);
++ }
++}
++
++/*
++ * Scan the URBs in a QH's queue
++ */
++#define QH_FINISHED_UNLINKING(qh) \
++ (qh->state == QH_STATE_UNLINKING && \
++ uhci->frame_number + uhci->is_stopped != qh->unlink_frame)
++
++static void uhci_scan_qh(struct uhci_hcd *uhci, struct uhci_qh *qh)
++{
++ struct urb_priv *urbp;
++ struct urb *urb;
++ int status;
++
++ while (!list_empty(&qh->queue)) {
++ urbp = list_entry(qh->queue.next, struct urb_priv, node);
++ urb = urbp->urb;
++
++ if (qh->type == USB_ENDPOINT_XFER_ISOC)
++ status = uhci_result_isochronous(uhci, urb);
++ else
++ status = uhci_result_common(uhci, urb);
++ if (status == -EINPROGRESS)
++ break;
++
++ /* Dequeued but completed URBs can't be given back unless
++ * the QH is stopped or has finished unlinking. */
++ if (urb->unlinked) {
++ if (QH_FINISHED_UNLINKING(qh))
++ qh->is_stopped = 1;
++ else if (!qh->is_stopped)
++ return;
++ }
++
++ uhci_giveback_urb(uhci, qh, urb, status);
++ if (status < 0)
++ break;
++ }
++
++ /* If the QH is neither stopped nor finished unlinking (normal case),
++ * our work here is done. */
++ if (QH_FINISHED_UNLINKING(qh))
++ qh->is_stopped = 1;
++ else if (!qh->is_stopped)
++ return;
++
++ /* Otherwise give back each of the dequeued URBs */
++restart:
++ list_for_each_entry(urbp, &qh->queue, node) {
++ urb = urbp->urb;
++ if (urb->unlinked) {
++
++ /* Fix up the TD links and save the toggles for
++ * non-Isochronous queues. For Isochronous queues,
++ * test for too-recent dequeues. */
++ if (!uhci_cleanup_queue(uhci, qh, urb)) {
++ qh->is_stopped = 0;
++ return;
++ }
++ uhci_giveback_urb(uhci, qh, urb, 0);
++ goto restart;
++ }
++ }
++ qh->is_stopped = 0;
++
++ /* There are no more dequeued URBs. If there are still URBs on the
++ * queue, the QH can now be re-activated. */
++ if (!list_empty(&qh->queue)) {
++ if (qh->needs_fixup)
++ uhci_fixup_toggles(qh, 0);
++
++ /* If the first URB on the queue wants FSBR but its time
++ * limit has expired, set the next TD to interrupt on
++ * completion before reactivating the QH. */
++ urbp = list_entry(qh->queue.next, struct urb_priv, node);
++ if (urbp->fsbr && qh->wait_expired) {
++ struct uhci_td *td = list_entry(urbp->td_list.next,
++ struct uhci_td, list);
++
++ td->status |= __cpu_to_le32(TD_CTRL_IOC);
++ }
++
++ uhci_activate_qh(uhci, qh);
++ }
++
++ /* The queue is empty. The QH can become idle if it is fully
++ * unlinked. */
++ else if (QH_FINISHED_UNLINKING(qh))
++ uhci_make_qh_idle(uhci, qh);
++}
++
++/*
++ * Check for queues that have made some forward progress.
++ * Returns 0 if the queue is not Isochronous, is ACTIVE, and
++ * has not advanced since last examined; 1 otherwise.
++ *
++ * Early Intel controllers have a bug which causes qh->element sometimes
++ * not to advance when a TD completes successfully. The queue remains
++ * stuck on the inactive completed TD. We detect such cases and advance
++ * the element pointer by hand.
++ */
++static int uhci_advance_check(struct uhci_hcd *uhci, struct uhci_qh *qh)
++{
++ struct urb_priv *urbp = NULL;
++ struct uhci_td *td;
++ int ret = 1;
++ unsigned status;
++
++ if (qh->type == USB_ENDPOINT_XFER_ISOC)
++ goto done;
++
++ /* Treat an UNLINKING queue as though it hasn't advanced.
++ * This is okay because reactivation will treat it as though
++ * it has advanced, and if it is going to become IDLE then
++ * this doesn't matter anyway. Furthermore it's possible
++ * for an UNLINKING queue not to have any URBs at all, or
++ * for its first URB not to have any TDs (if it was dequeued
++ * just as it completed). So it's not easy in any case to
++ * test whether such queues have advanced. */
++ if (qh->state != QH_STATE_ACTIVE) {
++ urbp = NULL;
++ status = 0;
++
++ } else {
++ urbp = list_entry(qh->queue.next, struct urb_priv, node);
++ td = list_entry(urbp->td_list.next, struct uhci_td, list);
++ status = td_status(td);
++ if (!(status & TD_CTRL_ACTIVE)) {
++
++ /* We're okay, the queue has advanced */
++ qh->wait_expired = 0;
++ qh->advance_jiffies = jiffies;
++ goto done;
++ }
++ ret = 0;
++ }
++
++ /* The queue hasn't advanced; check for timeout */
++ if (qh->wait_expired)
++ goto done;
++
++ if (time_after(jiffies, qh->advance_jiffies + QH_WAIT_TIMEOUT)) {
++
++ /* Detect the Intel bug and work around it */
++ if (qh->post_td && qh_element(qh) == LINK_TO_TD(qh->post_td)) {
++ qh->element = qh->post_td->link;
++ qh->advance_jiffies = jiffies;
++ ret = 1;
++ goto done;
++ }
++
++ qh->wait_expired = 1;
++
++ /* If the current URB wants FSBR, unlink it temporarily
++ * so that we can safely set the next TD to interrupt on
++ * completion. That way we'll know as soon as the queue
++ * starts moving again. */
++ if (urbp && urbp->fsbr && !(status & TD_CTRL_IOC))
++ uhci_unlink_qh(uhci, qh);
++
++ } else {
++ /* Unmoving but not-yet-expired queues keep FSBR alive */
++ if (urbp)
++ uhci_urbp_wants_fsbr(uhci, urbp);
++ }
++
++done:
++ return ret;
++}
++
++/*
++ * Process events in the schedule, but only in one thread at a time
++ */
++static void uhci_scan_schedule(struct uhci_hcd *uhci)
++{
++ int i;
++ struct uhci_qh *qh;
++
++ /* Don't allow re-entrant calls */
++ if (uhci->scan_in_progress) {
++ uhci->need_rescan = 1;
++ return;
++ }
++ uhci->scan_in_progress = 1;
++rescan:
++ uhci->need_rescan = 0;
++ uhci->fsbr_is_wanted = 0;
++
++ uhci_clear_next_interrupt(uhci);
++ uhci_get_current_frame_number(uhci);
++ uhci->cur_iso_frame = uhci->frame_number;
++
++ /* Go through all the QH queues and process the URBs in each one */
++ for (i = 0; i < UHCI_NUM_SKELQH - 1; ++i) {
++ uhci->next_qh = list_entry(uhci->skelqh[i]->node.next,
++ struct uhci_qh, node);
++ while ((qh = uhci->next_qh) != uhci->skelqh[i]) {
++ uhci->next_qh = list_entry(qh->node.next,
++ struct uhci_qh, node);
++
++ if (uhci_advance_check(uhci, qh)) {
++ uhci_scan_qh(uhci, qh);
++ if (qh->state == QH_STATE_ACTIVE) {
++ uhci_urbp_wants_fsbr(uhci,
++ list_entry(qh->queue.next, struct urb_priv, node));
++ }
++ }
++ }
++ }
++
++ uhci->last_iso_frame = uhci->cur_iso_frame;
++ if (uhci->need_rescan)
++ goto rescan;
++ uhci->scan_in_progress = 0;
++
++ if (uhci->fsbr_is_on && !uhci->fsbr_is_wanted &&
++ !uhci->fsbr_expiring) {
++ uhci->fsbr_expiring = 1;
++ mod_timer(&uhci->fsbr_timer, jiffies + FSBR_OFF_DELAY);
++ }
++
++ if (list_empty(&uhci->skel_unlink_qh->node))
++ uhci_clear_next_interrupt(uhci);
++ else
++ uhci_set_next_interrupt(uhci);
++}
+diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig
+index f3a75a9..97a22b9 100644
+--- a/drivers/usb/host/Kconfig
++++ b/drivers/usb/host/Kconfig
+@@ -88,6 +88,13 @@ config USB_EHCI_FSL
+ ---help---
+ Variation of ARC USB block used in some Freescale chips.
+
++config USB_EHCI_AST
++ bool "Support for ASPEED SoC EHCI USB controller"
++ depends on USB_EHCI_HCD && ARCH_ASPEED
++# select USB_EHCI_ROOT_HUB_TT
++ ---help---
++ Variation of ARC USB block used in some ASPEED SoC chips.
++
+ config USB_EHCI_HCD_PPC_OF
+ bool "EHCI support for PPC USB controller on OF platform bus"
+ depends on USB_EHCI_HCD && PPC_OF
+diff --git a/drivers/usb/host/ehci-ast.c b/drivers/usb/host/ehci-ast.c
+new file mode 100644
+index 0000000..503df9a
+--- /dev/null
++++ b/drivers/usb/host/ehci-ast.c
+@@ -0,0 +1,297 @@
++/********************************************************************************
++* File Name : drivers/usb/host/ehci-aspeed.c
++* Author : Ryan Chen
++* Description : EHCI HCD (Host Controller Driver) for USB
++*
++* Copyright (C) ASPEED Technology Inc.
++* This program is free software; you can redistribute it and/or modify
++* it under the terms of the GNU General Public License as published by the Free Software Foundation;
++* either version 2 of the License, or (at your option) any later version.
++*
++* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
++* without even the implied warranty of MERCHANTABILITY or
++* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
++*
++* You should have received a copy of the GNU General Public License
++* along with this program; if not, write to the Free Software
++* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++
++* History :
++* 1. 2012/08/17 ryan chen create this file
++*
++********************************************************************************/
++
++#include <linux/kernel.h>
++#include <linux/module.h>
++#include <linux/platform_device.h>
++
++#include <mach/hardware.h>
++
++
++/* ASPEED EHCI USB Host Controller */
++
++/*-------------------------------------------------------------------------*/
++
++/* configure so an HC device and id are always provided */
++/* always called with process context; sleeping is OK */
++
++static int ehci_ast_setup(struct usb_hcd *hcd)
++{
++ struct ehci_hcd *ehci = hcd_to_ehci(hcd);
++ int retval;
++
++ ehci->caps = hcd->regs;
++ ehci->regs = hcd->regs +
++ HC_LENGTH(ehci_readl(ehci, &ehci->caps->hc_capbase));
++ dbg_hcs_params(ehci, "reset");
++
++ /* cache this readonly data; minimize chip reads */
++ ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params);
++
++#ifdef CONFIG_USB_EHCI_ROOT_HUB_TT
++ hcd->has_tt = 1;
++#else
++ hcd->has_tt = 0;
++#endif
++
++ ehci->sbrn = 0x20;
++
++// retval = ehci_halt(ehci);
++// if (retval)
++// return retval;
++
++
++ /*
++ * data structure init
++ */
++ retval = ehci_init(hcd);
++ if (retval)
++ return retval;
++
++ ehci_reset(ehci);
++ ehci_port_power(ehci, 0);
++
++ return retval;
++}
++
++static const struct hc_driver ehci_ast_hc_driver = {
++ .description = hcd_name,
++ .product_desc = "ASPEED On-Chip EHCI Host Controller",
++ .hcd_priv_size = sizeof(struct ehci_hcd),
++ /*
++ * generic hardware linkage
++ */
++ .irq = ehci_irq,
++ .flags = HCD_USB2,
++ /*
++ * basic lifecycle operations
++ */
++ .reset = ehci_ast_setup,
++ .start = ehci_run,
++ .stop = ehci_stop,
++ .shutdown = ehci_shutdown,
++ /*
++ * managing i/o requests and associated device resources
++ */
++ .urb_enqueue = ehci_urb_enqueue,
++ .urb_dequeue = ehci_urb_dequeue,
++ .endpoint_disable = ehci_endpoint_disable,
++ /*
++ * scheduling support
++ */
++ .get_frame_number = ehci_get_frame,
++ /*
++ * root hub support
++ */
++ .hub_status_data = ehci_hub_status_data,
++ .hub_control = ehci_hub_control,
++ .bus_suspend = ehci_bus_suspend,
++ .bus_resume = ehci_bus_resume,
++ .relinquish_port = ehci_relinquish_port,
++ .port_handed_over = ehci_port_handed_over,
++};
++
++static int ehci_ast_drv_probe(struct platform_device *pdev)
++{
++ struct resource *res;
++ struct usb_hcd *hcd;
++// struct ehci_hcd *ehci;
++ void __iomem *regs;
++ int irq, err;
++
++ if (usb_disabled())
++ return -ENODEV;
++
++ pr_debug("Initializing ASPEED-SoC USB Host Controller\n");
++
++ irq = platform_get_irq(pdev, 0);
++ if (irq <= 0) {
++ dev_err(&pdev->dev,
++ "Found HC with no IRQ. Check %s setup!\n",
++ dev_name(&pdev->dev));
++ err = -ENODEV;
++ goto err1;
++ }
++
++ //TODO
++// IRQ_SET_HIGH_LEVEL (irq);
++// IRQ_SET_LEVEL_TRIGGER (irq);
++
++ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
++ if (!res) {
++ dev_err(&pdev->dev,
++ "Found HC with no register addr. Check %s setup!\n",
++ dev_name(&pdev->dev));
++ err = -ENODEV;
++ goto err1;
++ }
++
++ if (!request_mem_region(res->start, res->end - res->start + 1,
++ res->name)) {
++ dev_dbg(&pdev->dev, "controller already in use\n");
++ err = -EBUSY;
++ goto err1;
++ }
++
++ regs = ioremap_nocache(res->start, res->end - res->start + 1);
++ if (regs == NULL) {
++ dev_dbg(&pdev->dev, "error mapping memory\n");
++ err = -EFAULT;
++ goto err2;
++ }
++
++ hcd = usb_create_hcd(&ehci_ast_hc_driver,
++ &pdev->dev, dev_name(&pdev->dev));
++ if (!hcd) {
++ err = -ENOMEM;
++ goto err3;
++ }
++
++ hcd->rsrc_start = res->start;
++ hcd->rsrc_len = res->end - res->start + 1;
++ hcd->regs = regs;
++
++ err = usb_add_hcd(hcd, irq, IRQF_DISABLED);
++ if (err)
++ goto err4;
++
++ return 0;
++
++ err4:
++ usb_put_hcd(hcd);
++ err3:
++ iounmap(regs);
++ err2:
++ release_mem_region(res->start, res->end - res->start + 1);
++ err1:
++ dev_err(&pdev->dev, "init %s fail, %d\n",
++ dev_name(&pdev->dev), err);
++
++ return err;
++
++
++}
++
++static int ehci_ast_drv_remove(struct platform_device *pdev)
++{
++ struct usb_hcd *hcd = platform_get_drvdata(pdev);
++
++ usb_remove_hcd(hcd);
++ iounmap(hcd->regs);
++ release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
++ usb_put_hcd(hcd);
++
++ return 0;
++}
++
++ /*TBD*/
++#ifdef CONFIG_PM
++static int ehci_hcd_ast_drv_suspend(struct platform_device *pdev, pm_message_t msg)
++{
++ struct usb_hcd *hcd = platform_get_drvdata(pdev);
++ struct ehci_hcd *ehci = hcd_to_ehci(hcd);
++ unsigned long flags;
++ int rc = 0;
++
++ if (time_before(jiffies, ehci->next_statechange))
++ msleep(10);
++
++ /* Root hub was already suspended. Disable irq emission and
++ * mark HW unaccessible, bail out if RH has been resumed. Use
++ * the spinlock to properly synchronize with possible pending
++ * RH suspend or resume activity.
++ *
++ * This is still racy as hcd->state is manipulated outside of
++ * any locks =P But that will be a different fix.
++ */
++ spin_lock_irqsave (&ehci->lock, flags);
++ if (hcd->state != HC_STATE_SUSPENDED) {
++ rc = -EINVAL;
++ goto bail;
++ }
++ ehci_writel(ehci, 0, &ehci->regs->intr_enable);
++ (void)ehci_readl(ehci, &ehci->regs->intr_enable);
++
++ clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
++ bail:
++ spin_unlock_irqrestore (&ehci->lock, flags);
++
++ // could save FLADJ in case of Vaux power loss
++ // ... we'd only use it to handle clock skew
++
++ return rc;
++}
++static int ehci_hcd_ast_drv_resume(struct platform_device *pdev)
++{
++ struct usb_hcd *hcd = platform_get_drvdata(pdev);
++ struct ehci_hcd *ehci = hcd_to_ehci(hcd);
++
++ // maybe restore FLADJ
++
++ if (time_before(jiffies, ehci->next_statechange))
++ msleep(100);
++
++ /* Mark hardware accessible again as we are out of D3 state by now */
++ set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
++
++ usb_root_hub_lost_power(hcd->self.root_hub);
++
++ /* Else reset, to cope with power loss or flush-to-storage
++ * style "resume" having let BIOS kick in during reboot.
++ */
++ (void) ehci_halt(ehci);
++ (void) ehci_reset(ehci);
++
++ /* emptying the schedule aborts any urbs */
++ spin_lock_irq(&ehci->lock);
++ if (ehci->reclaim)
++ end_unlink_async(ehci);
++ ehci_work(ehci);
++ spin_unlock_irq(&ehci->lock);
++
++ ehci_writel(ehci, ehci->command, &ehci->regs->command);
++ ehci_writel(ehci, FLAG_CF, &ehci->regs->configured_flag);
++ ehci_readl(ehci, &ehci->regs->command); /* unblock posted writes */
++
++ /* here we "know" root ports should always stay powered */
++ ehci_port_power(ehci, 1);
++
++ hcd->state = HC_STATE_SUSPENDED;
++ return 0;
++}
++#endif
++
++MODULE_ALIAS("platform:ehci_ast");
++
++static struct platform_driver ehci_hcd_ast_driver = {
++ .probe = ehci_ast_drv_probe,
++ .remove = ehci_ast_drv_remove,
++ .shutdown = usb_hcd_platform_shutdown,
++#ifdef CONFIG_PM
++ .suspend = ehci_hcd_ast_drv_suspend,
++ .resume = ehci_hcd_ast_drv_resume,
++#endif
++ .driver = {
++ .name = "ehci-ast",
++ },
++};
+diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
+index e551bb3..a34a4cf 100644
+--- a/drivers/usb/host/ehci-hcd.c
++++ b/drivers/usb/host/ehci-hcd.c
+@@ -581,6 +581,7 @@ static int ehci_run (struct usb_hcd *hcd)
+ * Scsi_Host.highmem_io, and so forth. It's readonly to all
+ * host side drivers though.
+ */
++
+ hcc_params = ehci_readl(ehci, &ehci->caps->hcc_params);
+ if (HCC_64BIT_ADDR(hcc_params)) {
+ ehci_writel(ehci, 0, &ehci->regs->segment);
+@@ -1036,6 +1037,11 @@ MODULE_LICENSE ("GPL");
+ #define PLATFORM_DRIVER ixp4xx_ehci_driver
+ #endif
+
++#ifdef CONFIG_USB_EHCI_AST
++#include "ehci-ast.c"
++#define PLATFORM_DRIVER ehci_hcd_ast_driver
++#endif
++
+ #if !defined(PCI_DRIVER) && !defined(PLATFORM_DRIVER) && \
+ !defined(PS3_SYSTEM_BUS_DRIVER) && !defined(OF_PLATFORM_DRIVER)
+ #error "missing bus glue for ehci-hcd"
+@@ -1117,7 +1123,10 @@ err_debug:
+ clear_bit(USB_EHCI_LOADED, &usb_hcds_loaded);
+ return retval;
+ }
+-module_init(ehci_hcd_init);
++
++//ehci must after uhci driver module load. Ryan Modify
++late_initcall(ehci_hcd_init);
++//module_init(ehci_hcd_init);
+
+ static void __exit ehci_hcd_cleanup(void)
+ {
+diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig
+index 3f3ce13..a8be29b 100644
+--- a/drivers/video/Kconfig
++++ b/drivers/video/Kconfig
+@@ -1473,6 +1473,30 @@ config FB_SAVAGE_ACCEL
+ the resulting framebuffer console has bothersome glitches, then
+ choose N here.
+
++menuconfig FB_AST
++ tristate "ASPEED Framebuffer Driver"
++ depends on FB
++ select FB_CFB_FILLRECT
++ select FB_CFB_COPYAREA
++ select FB_CFB_IMAGEBLIT
++ default n
++
++if FB_AST
++
++config AST_DAC
++ bool "CRT DAC output"
++
++config AST_DVO
++ bool "CRT DVO output"
++
++config HDMI_CAT6613
++ bool "Enable CAT6613 HDMI TX"
++ depends on FB_AST && AST_DVO
++ help
++ This option will support CAT6613 HDMI TX driver
++
++endif
++
+ config FB_SIS
+ tristate "SiS/XGI display support"
+ depends on FB && PCI
+diff --git a/drivers/video/Makefile b/drivers/video/Makefile
+index e39e33e..97bc000 100644
+--- a/drivers/video/Makefile
++++ b/drivers/video/Makefile
+@@ -41,6 +41,8 @@ obj-$(CONFIG_FB_NVIDIA) += nvidia/
+ obj-$(CONFIG_FB_ATY) += aty/ macmodes.o
+ obj-$(CONFIG_FB_ATY128) += aty/ macmodes.o
+ obj-$(CONFIG_FB_RADEON) += aty/
++obj-$(CONFIG_FB_AST) += astfb.o
++obj-$(CONFIG_HDMI_CAT6613) += hdmi_cat6613.o
+ obj-$(CONFIG_FB_SIS) += sis/
+ obj-$(CONFIG_FB_VIA) += via/
+ obj-$(CONFIG_FB_KYRO) += kyro/
+diff --git a/drivers/video/astfb.c b/drivers/video/astfb.c
+new file mode 100644
+index 0000000..8292bb8
+--- /dev/null
++++ b/drivers/video/astfb.c
+@@ -0,0 +1,1056 @@
++ /********************************************************************************
++* File Name : drivers/video/astfb.c
++* Author : Ryan Chen
++* Description : ASPEED Framebuffer Driver
++*
++* Copyright (C) ASPEED Tech. Inc.
++* This program is free software; you can redistribute it and/or modify
++* it under the terms of the GNU General Public License as published by the Free Software Foundation;
++* either version 2 of the License, or (at your option) any later version.
++*
++* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
++* without even the implied warranty of MERCHANTABILITY or
++* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
++*
++* You should have received a copy of the GNU General Public License
++* along with this program; if not, write to the Free Software
++* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++
++* History :
++* 1. 2012/12/27 Ryan Chen create this file
++*
++*
++********************************************************************************/
++#include <linux/module.h>
++#include <linux/kernel.h>
++#include <linux/errno.h>
++#include <linux/string.h>
++#include <linux/mm.h>
++#include <linux/slab.h>
++#include <linux/delay.h>
++#include <linux/fb.h>
++#include <linux/init.h>
++#include <linux/dma-mapping.h>
++#include <linux/interrupt.h>
++#include <linux/wait.h>
++#include <linux/platform_device.h>
++
++#include <asm/io.h>
++#include <asm/uaccess.h>
++#include <asm/mach/map.h>
++#include <plat/regs-crt.h>
++#include <mach/ast_lcd.h>
++
++#ifdef CONFIG_DOUBLE_BUFFER
++#define NUMBER_OF_BUFFERS 2
++#else
++#define NUMBER_OF_BUFFERS 1
++#endif
++
++//////////////////////////////////////////////////////////////
++/* H/W Feature Definition */
++#define DEFAULT_MMIO_SIZE 0x00020000
++#define DEFAULT_CMDQ_SIZE 0x00100000
++#define MIN_CMDQ_SIZE 0x00040000
++#define CMD_QUEUE_GUARD_BAND 0x00000020
++#define DEFAULT_HWC_NUM 0x00000002
++
++////////////////////////////////////////////////////////////////
++static wait_queue_head_t wq;
++static int gNoPanDisplay;
++static int gGUIWaitVsync;
++
++#define ASTFB_GET_DFBINFO _IOR(0xF3,0x00,struct astfb_dfbinfo)
++
++/* Default Threshold Seting */
++#define CRT_LOW_THRESHOLD_VALUE 0x12
++#define CRT_HIGH_THRESHOLD_VALUE 0x1E
++
++//#define CRT_LOW_THRESHOLD_VALUE 0x60
++//#define CRT_HIGH_THRESHOLD_VALUE 0x78
++//for fix 1920X1080
++//#define CRT_LOW_THRESHOLD_VALUE 0x16
++//#define CRT_HIGH_THRESHOLD_VALUE 0x1E
++
++////////////////////////////////////////////////////////////
++
++/* Debugging stuff */
++
++#define FBDBG 1
++
++#define dprintk(msg...) if (FBDBG) { printk(KERN_DEBUG "astfb: " msg); }
++
++struct pixel_freq_pll_data {
++ u32 pixel_freq; //*10000
++ u32 pll_set;
++};
++
++static struct pixel_freq_pll_data pll_table[] = {
++ {39721, 0x00046515}, /* 00: VCLK25_175 */
++ {35308, 0x00047255}, /* 01: VCLK28_322 */
++ {31746, 0x0004682a}, /* 02: VCLK31_5 */
++ {27777, 0x0004672a}, /* 03: VCLK36 */
++ {25000, 0x00046c50}, /* 04: VCLK40 */
++ {20202, 0x00046842}, /* 05: VCLK49_5 */
++ {20000, 0x00006c32}, /* 06: VCLK50 */
++ {17777, 0x00006a2f}, /* 07: VCLK56_25 */
++ {15384, 0x00006c41}, /* 08: VCLK65 */
++ {13333, 0x00006832}, /* 09: VCLK75 */
++ {12690, 0x0000672e}, /* 0A: VCLK78_75 */
++ {10582, 0x0000683f}, /* 0B: VCLK94_5 */
++ {9259, 0x00004824}, /* 0C: VCLK108 */
++ {7407, 0x0000482d}, /* 0D: VCLK135 */
++ {6349, 0x0000472e}, /* 0E: VCLK157_5 */
++ {6172, 0x00004836}, /* 0F: VCLK162 */
++};
++
++// ARGB4444 format
++unsigned short cursor_8x8[] = {
++ 0x0FFF, 0x1FFF, 0x2FFF, 0x3777, 0x4777, 0x5777, 0x6777, 0x7888,
++ 0x8FFF, 0xF000, 0xAFFF, 0xB777, 0xC777, 0xD777, 0xE777, 0xF888,
++ 0x0FFF, 0x1FFF, 0x2FFF, 0x3FFF, 0x4777, 0x5777, 0x6777, 0x7888,
++ 0x8FFF, 0x9FFF, 0xAFFF, 0xBFFF, 0xCFFF, 0xD777, 0xE777, 0xF888,
++ 0x0FFF, 0x1FFF, 0x2FFF, 0x3FFF, 0x4FFF, 0x5FFF, 0x6FFF, 0x7888,
++ 0x8FFF, 0x9FFF, 0xAFFF, 0xBFFF, 0xCFFF, 0xDFFF, 0xEFFF, 0xFFFF,
++ 0x0FFF, 0x1FFF, 0x2777, 0x3FFF, 0x4FFF, 0x5FFF, 0x6FFF, 0x7FFF,
++ 0x8FFF, 0x9777, 0xA777, 0xB777, 0xC777, 0xDFFF, 0xEFFF, 0xFFFF,
++};
++
++// XRGB4444 format
++unsigned short cursor_16x16[] = {
++ 0x8777, 0x8777, 0x8777, 0x8777, 0x8FFF, 0x8FFF, 0x8FFF, 0x8FFF, 0x8FFF, 0x8FFF, 0x8FFF, 0x8FFF, 0x8FFF, 0x8FFF, 0x8FFF, 0x8FFF,
++ 0x8777, 0xC888, 0x8FFF, 0x8FFF, 0x8FFF, 0x8FFF, 0x8FFF, 0x8FFF, 0x8FFF, 0x8FFF, 0x8FFF, 0x8FFF, 0x8FFF, 0x8FFF, 0x8FFF, 0x8FFF,
++ 0x8777, 0x8FFF, 0x8FFF, 0x8FFF, 0x8FFF, 0x8FFF, 0x8FFF, 0x8FFF, 0x8FFF, 0x8FFF, 0x8FFF, 0x8FFF, 0x8FFF, 0x8FFF, 0x8FFF, 0x8FFF,
++ 0x8777, 0x8FFF, 0x8FFF, 0x8FFF, 0x8FFF, 0x8FFF, 0x8FFF, 0x8FFF, 0x8FFF, 0x8FFF, 0x8FFF, 0x8FFF, 0x8FFF, 0x8FFF, 0x8FFF, 0x8FFF,
++ 0x8777, 0x8FFF, 0x8FFF, 0x8FFF, 0x8FFF, 0x8FFF, 0x8FFF, 0x8FFF, 0x8FFF, 0x8FFF, 0x8FFF, 0x8FFF, 0x8FFF, 0x8FFF, 0x8FFF, 0x8FFF,
++ 0x4777, 0x4FFF, 0x4FFF, 0x4FFF, 0x4FFF, 0x8FFF, 0x8FFF, 0x8FFF, 0x8FFF, 0x8FFF, 0x8FFF, 0x8FFF, 0x8FFF, 0x8FFF, 0x8FFF, 0x8FFF,
++ 0x4FFF, 0x4FFF, 0x4FFF, 0x4FFF, 0x4FFF, 0x8FFF, 0x8FFF, 0x8FFF, 0x8FFF, 0x8FFF, 0x8FFF, 0x8FFF, 0x8FFF, 0x8FFF, 0x8FFF, 0x8FFF,
++ 0x0FFF, 0x0FFF, 0x0FFF, 0x0FFF, 0x4FFF, 0x8FFF, 0x8FFF, 0x8FFF, 0x8FFF, 0x8FFF, 0x8FFF, 0x8FFF, 0x8FFF, 0x8FFF, 0x8FFF, 0x8FFF,
++ 0x0FFF, 0x0FFF, 0x0FFF, 0x0FFF, 0x4FFF, 0x8FFF, 0x8FFF, 0x8FFF, 0x8FFF, 0x8FFF, 0x8FFF, 0x8FFF, 0x8FFF, 0x8FFF, 0x8FFF, 0x8FFF,
++ 0x0FFF, 0x0FFF, 0x0FFF, 0x0FFF, 0x4FFF, 0x8FFF, 0x8FFF, 0x8FFF, 0x8FFF, 0x8FFF, 0x8FFF, 0x8FFF, 0x8FFF, 0x8FFF, 0x8FFF, 0x8FFF,
++ 0x0FFF, 0x0FFF, 0x0FFF, 0x0FFF, 0x4FFF, 0x8FFF, 0x8FFF, 0x8FFF, 0x8FFF, 0x8FFF, 0x8FFF, 0x8FFF, 0x8FFF, 0x8FFF, 0x8FFF, 0x8FFF,
++ 0xCFFF, 0xCFFF, 0xCFFF, 0xCFFF, 0x4FFF, 0x8FFF, 0x8FFF, 0x8FFF, 0x8FFF, 0x8FFF, 0x8FFF, 0x8FFF, 0x8FFF, 0x8FFF, 0x8FFF, 0x8FFF,
++ 0xCFFF, 0xCFFF, 0xCFFF, 0xCFFF, 0x4FFF, 0x8FFF, 0x8FFF, 0x8FFF, 0x8FFF, 0x8FFF, 0x8FFF, 0x8FFF, 0x8FFF, 0x8FFF, 0x8FFF, 0x8FFF,
++ 0xCFFF, 0xCFFF, 0xCFFF, 0xCFFF, 0x4FFF, 0x8FFF, 0x8FFF, 0x8FFF, 0x8FFF, 0x8FFF, 0x8FFF, 0x8FFF, 0x8FFF, 0x8FFF, 0x8FFF, 0x8FFF,
++ 0xCFFF, 0xCFFF, 0xCFFF, 0xCFFF, 0x4FFF, 0x8FFF, 0x8FFF, 0x8FFF, 0x8FFF, 0x8FFF, 0x8FFF, 0x8FFF, 0x8FFF, 0x8FFF, 0x8FFF, 0x8FFF,
++ 0xCFFF, 0xCFFF, 0xCFFF, 0xCFFF, 0x4FFF, 0x8FFF, 0x8FFF, 0x8FFF, 0x8FFF, 0x8FFF, 0x8FFF, 0x8FFF, 0x8FFF, 0x8FFF, 0x8FFF, 0x8FFF,
++};
++
++struct astfb_device {
++ int state;
++ struct mutex rqueue_mutex;
++ int palette_size;
++ u32 pseudo_palette[17];
++ struct platform_device *pdev;
++ struct fb_var_screeninfo new_var; /* for mode changes */
++};
++
++
++/* data structure */
++struct astfb_info {
++ struct platform_device *pdev;
++ struct fb_info *info;
++ struct resource *reg_res;
++ struct resource *fb_res;
++ void __iomem *base;
++ int addr_assign;
++ int irq;
++ int yuv_mode;
++ u32 pseudo_palette[17];
++
++ struct timer_list timer;
++
++ /* driver registered */
++ int registered;
++ /* console control */
++ int currcon;
++
++ int need_wakeup;
++ void __iomem *next_addr;
++
++
++ u8 hwcursor; //0: disable , 1 : enable
++ u8 dac; //0: disable , 1 : enable
++ u8 dvo; //0: disable , 1 : enable
++ u8 xmiter; //0: dvi, 1:hdmi;
++ struct ast_fb_plat_data *fb_plat_data;
++
++};
++
++static inline void
++astfb_write(struct astfb_info *fbinfo, u32 val, u32 reg)
++{
++// dprintk("astfb_write : val: %x , reg : %x \n",val,reg);
++ writel(val, fbinfo->base+ reg);
++}
++
++static inline u32
++astfb_read(struct astfb_info *fbinfo, u32 reg)
++{
++ return readl(fbinfo->base + reg);
++}
++
++static void astfb_osd_enable(struct astfb_info *sfb, u8 enable)
++{
++ if(enable)
++ astfb_write(sfb, astfb_read(sfb, AST_CRT_CTRL1) | CRT_CTRL_OSD_EN, AST_CRT_CTRL1);
++ else
++ astfb_write(sfb, astfb_read(sfb, AST_CRT_CTRL1) & ~CRT_CTRL_OSD_EN, AST_CRT_CTRL1);
++}
++
++static void astfb_cursor_enable(struct astfb_info *sfb, u8 enable)
++{
++ if(enable) {
++ astfb_write(sfb, astfb_read(sfb, AST_CRT_CTRL1) | CRT_CTRL_HW_CURSOR_EN, AST_CRT_CTRL1);
++ } else {
++ astfb_write(sfb, astfb_read(sfb, AST_CRT_CTRL1) & ~CRT_CTRL_HW_CURSOR_EN, AST_CRT_CTRL1);
++ }
++}
++
++int
++astfb_crtc_to_var(struct fb_var_screeninfo *var, struct astfb_info *sfb)
++{
++
++ /* crtc */
++ var->xoffset = var->yoffset = 0;
++
++ /* palette */
++ switch(var->bits_per_pixel) {
++ case 8:
++ var->red.offset = var->green.offset = var->blue.offset = 0;
++ var->red.length = var->green.length = var->blue.length = 6;
++ break;
++ case 16:
++ var->red.offset = 11;
++ var->red.length = 5;
++ var->green.offset = 5;
++ var->green.length = 6;
++ var->blue.offset = 0;
++ var->blue.length = 5;
++ var->transp.offset = 0;
++ var->transp.length = 0;
++ break;
++ case 24:
++ case 32:
++ var->red.offset = 16;
++ var->red.length = 8;
++ var->green.offset = 8;
++ var->green.length = 8;
++ var->blue.offset = 0;
++ var->blue.length = 8;
++ var->transp.offset = 24;
++ var->transp.length = 8;
++ break;
++ }
++
++ var->red.msb_right =
++ var->green.msb_right =
++ var->blue.msb_right =
++ var->transp.offset =
++ var->transp.length =
++ var->transp.msb_right = 0;
++
++ return 0;
++}
++
++/*-------------------------------------------------------------------------*/
++static int astfb_hw_cursor(struct fb_info *info, struct fb_cursor *cursor)
++{
++// printk("astfb_hw_cursor \n");
++ return 0;
++}
++
++#if (NUMBER_OF_BUFFERS > 1)
++static int astfb_pan_display(struct fb_var_screeninfo *var, struct fb_info* info)
++{
++ struct astfb_info *sfb = info->par;
++ u32 addr;
++ s32 timeout;
++
++ if(gNoPanDisplay)
++ return 0;
++
++ addr = var->yoffset * info->fix.line_length + info->fix.smem_start;
++
++ astfb_write(sfb, addr, AST_CRT_ADDR);
++
++ if(gGUIWaitVsync)
++ {
++ timeout = interruptible_sleep_on_timeout(&wq,HZ/60);
++ if(timeout<0)
++ dprintk("%s: interruptible_sleep_on_timeout, may lost interrupt! timeout=%d\n",__FUNCTION__,timeout);
++ }
++ return 0;
++
++} /* astfb_pan_display */
++#endif
++
++static int astfb_set_par(struct fb_info *info)
++{
++ struct astfb_info *sfb = info->par;
++ struct fb_var_screeninfo *var = &info->var;
++ u32 i,ctrl1, ctrl2, htt, hde, hrs_s, hrs_e, vtt, vde, vrs_s, vrs_e;
++ u32 d_offset, t_count, thshld;
++ u32 d2_pll;
++
++ //S1 : set H / V
++ // Horizontal Timing
++ htt = var->xres + var->left_margin + var->right_margin + var->hsync_len;
++ hde = var->xres;
++ astfb_write(sfb, CRT_H_TOTAL((htt - 1)) | CRT_H_DE((hde - 1)), AST_CRT_HORIZ0);
++
++ hrs_s = var->xres + var->right_margin;
++ hrs_e = var->xres + var->right_margin + var->hsync_len;
++ astfb_write(sfb, CRT_H_RS_START((hrs_s - 1)) | CRT_H_RS_END((hrs_e - 1)), AST_CRT_HORIZ1);
++
++ dprintk("var->upper_margin= %d, var->lower_margin= %d, var->vsync_len = %d \n",var->upper_margin, var->lower_margin, var->vsync_len);
++
++ vtt = var->yres + var->upper_margin + var->lower_margin + var->vsync_len;
++ vde = var->yres;
++ astfb_write(sfb, CRT_V_TOTAL((vtt - 1)) | CRT_V_DE((vde - 1)), AST_CRT_VERTI0);
++ vrs_s = var->yres + var->lower_margin;
++ vrs_e = var->yres + var->lower_margin + var->vsync_len;
++ astfb_write(sfb, CRT_V_RS_START((vrs_s - 1)) | CRT_V_RS_END((vrs_e - 1)), AST_CRT_VERTI1);
++
++ if(var->nonstd != 0)
++ printk("TODO Check .... nonstd \n");
++
++ switch (var->nonstd) {
++ case 0:
++ break;
++ case ASTFB_COLOR_YUV444:
++ var->bits_per_pixel = 32;
++ return 0;
++ case ASTFB_COLOR_YUV420:
++ var->bits_per_pixel = 32;
++ return 0;
++ }
++
++ //S2 : Offset , TODO ... (x + 0x1f) & ~0x1f
++ d_offset = var->xres * var->bits_per_pixel /8;
++// dprintk("d_offset %d\n",d_offset);
++
++ switch (var->nonstd) {
++ case 0:
++ break;
++ case ASTFB_COLOR_YUV444:
++ var->bits_per_pixel = 24;
++ return 0;
++ case ASTFB_COLOR_YUV420:
++ var->bits_per_pixel = 16;
++ return 0;
++ }
++
++ t_count =(var->xres * var->bits_per_pixel + 63) / 64;
++// dprintk("t_count %d \n",t_count);
++ astfb_write(sfb, CRT_DISP_OFFSET(d_offset) | CRT_TERM_COUNT(t_count), AST_CRT_OFFSET);
++
++
++ //S3 : DCLK
++ dprintk("var->pixclock = %d \n",var->pixclock);
++
++ for(i=0; i<sizeof(pll_table)/sizeof(struct pixel_freq_pll_data); i++) {
++ if(pll_table[i].pixel_freq == var->pixclock) {
++ astfb_write(sfb, pll_table[i].pll_set, AST_CRT_PLL);
++ dprintk("find pixclk in table set 0x%x \n",pll_table[i].pll_set);
++ break;
++ }
++ }
++ if(i == sizeof(pll_table)/sizeof(struct pixel_freq_pll_data))
++ printk("ERROR pixclk in table ... FIXME \n");
++#if 0
++ d2_pll = sfb->fb_plat_data->get_clk();
++ u32 num, denum, div0,
++ num = pll_table[i].pll_set & 0xff;
++ denum = (pll_table[i].pll_set >> 8) & 0x1f;
++ div0 = (pll_table[i].pll_set >> 13) & 0x3;
++ div1 = (pll_table[i].pll_set >> 13) & 0x3;
++ printk
++#endif
++
++ //S4
++ astfb_write(sfb, sfb->info->fix.smem_start, AST_CRT_ADDR);
++
++ thshld = CRT_THROD_HIGH(CRT_HIGH_THRESHOLD_VALUE) | CRT_THROD_LOW(CRT_LOW_THRESHOLD_VALUE);
++ astfb_write(sfb, thshld, AST_CRT_THROD);
++
++
++ info->fix.line_length = (var->xres*var->bits_per_pixel)/8;
++ dprintk("x :%d , y : %d , bpp = %d \n",var->xres, var->yres, var->bits_per_pixel);
++ //disable crt first .....
++ astfb_write(sfb, astfb_read(sfb, AST_CRT_CTRL2) & ~(CRT_CTRL_DAC_PWR_EN | CRT_CTRL_DVO_EN), AST_CRT_CTRL2);
++
++ ctrl1 = astfb_read(sfb, AST_CRT_CTRL1);
++ //CTRL 1
++ // SetPolarity
++ dprintk("var->sync : %x , var->vmode = %d \n",var->sync, var->vmode);
++
++ if(var->sync & FB_SYNC_HOR_HIGH_ACT)
++ ctrl1 &= ~CRT_CTRL_HSYNC_POLARITY;
++ else
++ ctrl1 |= CRT_CTRL_HSYNC_POLARITY;
++
++ if(var->sync & FB_SYNC_VERT_HIGH_ACT)
++ ctrl1 &= ~CRT_CTRL_VSYNC_POLARITY;
++ else
++ ctrl1 |= CRT_CTRL_VSYNC_POLARITY;
++
++ /* Mode Type Setting */
++
++ if(var->bits_per_pixel==16)
++ ctrl1 &= ~CRT_CTRL_FORMAT_MASK; //RGB565
++ else
++ ctrl1 |= CRT_CTRL_FORMAT(COLOR_XRGB8888);
++
++ if (var->vmode & FB_VMODE_INTERLACED)
++ ctrl1 |= CRT_CTRL_INTER_TIMING;
++ else
++ ctrl1 &= ~CRT_CTRL_INTER_TIMING;
++
++ //enable crt ...
++ astfb_write(sfb, ctrl1 | CRT_CTRL_GRAPHIC_EN, AST_CRT_CTRL1);
++
++ dprintk("var->left_margin= %d, var->right_margin= %d, var->hsync_len = %d \n",var->left_margin, var->right_margin, var->hsync_len);
++
++
++ //enable dac / dvo
++ //CTRL 2
++ ctrl2 = 0;//astfb_read(sfb, AST_CRT_CTRL2);
++
++ // SoC V2 add CRT interrupt support. We should not touch this setting when changing video timing.
++ ctrl2 &= ~CRT_CTRL_VLINE_NUM_MASK;
++
++#ifdef CONFIG_AST_DAC
++ ctrl2 |= CRT_CTRL_DAC_PWR_EN;
++#endif
++
++#ifdef CONFIG_AST_DVO
++ ctrl2 |= CRT_CTRL_DVO_EN;
++#endif
++
++ astfb_write(sfb, ctrl2 , AST_CRT_CTRL2);
++
++ return 0;
++}
++
++static int astfb_get_cmap_len(struct fb_var_screeninfo *var)
++{
++ return (var->bits_per_pixel == 8) ? 256 : 16;
++}
++
++static int astfb_setcolreg(unsigned regno,
++ unsigned red, unsigned green, unsigned blue,
++ unsigned transp, struct fb_info *info)
++{
++ if(regno >= astfb_get_cmap_len(&info->var))
++ return 1;
++
++ switch(info->var.bits_per_pixel) {
++ case 8:
++ return 1;
++ break;
++ case 16:
++ ((u32 *)(info->pseudo_palette))[regno] =
++ (red & 0xf800) |
++ ((green & 0xfc00) >> 5) |
++ ((blue & 0xf800) >> 11);
++ break;
++ case 24:
++ case 32:
++ red >>= 8;
++ green >>= 8;
++ blue >>= 8;
++ ((u32 *)(info->pseudo_palette))[regno] =
++ (red << 16) | (green << 8) | (blue);
++ break;
++ }
++ return 0;
++
++}
++
++/*
++ * Blank the screen if blank_mode != 0, else unblank. Return 0 if blanking
++ * succeeded, != 0 if un-/blanking failed.
++ * blank_mode == 2: suspend vsync
++ * blank_mode == 3: suspend hsync
++ * blank_mode == 4: powerdown
++ */
++static int astfb_blank(int blank_mode, struct fb_info *info)
++{
++ u32 ctrl;
++ struct astfb_info *sfb = info->par;
++
++ printk(KERN_DEBUG "astfb: astfb_blank mode %d \n",blank_mode);
++ ctrl = astfb_read(sfb, AST_CRT_CTRL1);
++
++ switch(blank_mode) {
++ case FB_BLANK_UNBLANK: /* on */
++ ctrl &= ~CRT_CTRL_SCREEN_OFF;
++ break;
++ case FB_BLANK_NORMAL: /* blank */
++ ctrl |= CRT_CTRL_SCREEN_OFF;
++ break;
++ case FB_BLANK_VSYNC_SUSPEND: /* no vsync */
++ ctrl |= CRT_CTRL_VSYNC_OFF;
++ break;
++ case FB_BLANK_HSYNC_SUSPEND: /* no hsync */
++ ctrl |= CRT_CTRL_HSYNC_OFF;
++ break;
++ case FB_BLANK_POWERDOWN: /* off */
++ ctrl |= (CRT_CTRL_SCREEN_OFF | CRT_CTRL_VSYNC_OFF | CRT_CTRL_HSYNC_OFF);
++ break;
++ default:
++ return 1;
++ }
++
++ /* set reg */
++ astfb_write(sfb, ctrl, AST_CRT_CTRL1);
++
++ return 0;
++
++} /* astfb_blank */
++
++static int astfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
++{
++ var->xres_virtual = var->xres;
++ var->yres_virtual =var->yres * NUMBER_OF_BUFFERS;
++////////////////////////////////////////////////////////////////////
++ /* Sanity check for offsets */
++ if(var->xoffset < 0) var->xoffset = 0;
++ if(var->yoffset < 0) var->yoffset = 0;
++
++ if(var->xres > var->xres_virtual)
++ var->xres_virtual = var->xres;
++
++ /* Truncate offsets to maximum if too high */
++ if(var->xoffset > var->xres_virtual - var->xres) {
++ var->xoffset = var->xres_virtual - var->xres - 1;
++ }
++
++ if(var->yoffset > var->yres_virtual - var->yres) {
++ var->yoffset = var->yres_virtual - var->yres - 1;
++ }
++////////////////////////////////////////////////////////////////////
++ switch(var->bits_per_pixel) {
++ case 8:
++ var->red.offset = var->green.offset = var->blue.offset = 0;
++ var->red.length = var->green.length = var->blue.length = 6;
++ break;
++ case 16:
++ var->red.offset = 11;
++ var->red.length = 5;
++ var->green.offset = 5;
++ var->green.length = 6;
++ var->blue.offset = 0;
++ var->blue.length = 5;
++ var->transp.offset = 0;
++ var->transp.length = 0;
++ break;
++ case 24:
++ case 32:
++ var->red.offset = 16;
++ var->red.length = 8;
++ var->green.offset = 8;
++ var->green.length = 8;
++ var->blue.offset = 0;
++ var->blue.length = 8;
++ var->transp.length = 8;
++ var->transp.offset = 24;
++ break;
++ default:
++ dprintk("bpp=%d not support\n",var->bits_per_pixel);
++ return -EINVAL;
++ break;
++ }
++ return 0;
++}
++
++static int
++astfb_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg)
++{
++ struct astfb_info *sfb = info->par;
++
++ printk(KERN_DEBUG "astfb: astfb_ioctl is called \n");
++
++ switch(cmd) {
++// case AST_COLOR_FORMAT:
++// return 0;
++
++ default:
++ return -EINVAL;
++ }
++
++ return 0;
++
++} /* astfb_ioctl */
++
++/* fb ops */
++static struct fb_ops astfb_ops = {
++ .owner = THIS_MODULE,
++ .fb_check_var = astfb_check_var,
++ .fb_set_par = astfb_set_par,
++ .fb_blank = astfb_blank,
++ .fb_setcolreg = astfb_setcolreg,
++ .fb_fillrect = cfb_fillrect,
++ .fb_copyarea = cfb_copyarea,
++ .fb_imageblit = cfb_imageblit,
++ .fb_ioctl = astfb_ioctl,
++ .fb_cursor = astfb_hw_cursor,
++#if (NUMBER_OF_BUFFERS > 1)
++ .fb_pan_display = astfb_pan_display,
++#endif
++};
++
++static void ast_fbmem_free(struct astfb_info *sfb)
++{
++ iounmap(sfb->info->screen_base);
++}
++
++static irqreturn_t
++astfb_isr(int irq, void *parm)
++{
++ u32 status;
++ struct astfb_info *sfb=parm;
++ status = astfb_read(sfb, AST_CRT_CTRL1);
++ astfb_write(sfb, status, AST_CRT_CTRL1);
++ if (status & CRT_CTRL_VERTICAL_INTR_STS)
++ wake_up_interruptible(&wq);
++
++ return IRQ_HANDLED;
++}
++
++//TODO ..
++static int astfb_setup(struct astfb_info *sfb)
++{
++ char *this_opt = NULL;
++ char *options = NULL;
++ char tmp[128];
++ char *tmp_opt;
++ char name[10];
++ int i;
++
++ fb_get_options("astfb", &options);
++ dprintk("%s\n", options);
++
++ if (!options || !*options)
++ return -1;
++
++ strcpy(tmp, options);
++ tmp_opt=tmp;
++ while ((this_opt = strsep(&tmp_opt, ",")) != NULL) {
++ printk("x %s \n",this_opt);
++ if (!strncmp(this_opt, "mode:", 5)) {
++ printk("%s \n",this_opt);
++ } else if(!strncmp(this_opt, "hwcursor:", 9)) {
++ printk("%s \n",this_opt);
++ } else if(!strncmp(this_opt, "osd:", 4)) {
++ printk("%s \n",this_opt);
++ } else if (!strncmp(this_opt, "vram:", 8)) {
++ printk("%s \n",this_opt);
++ } else if(!strncmp(this_opt, "dac:", 4)) {
++ printk("%s \n",this_opt);
++ } else if(!strncmp(this_opt, "dvo:", 4)) {
++ printk("%s \n",this_opt);
++ } else {
++ printk("f %s \n",this_opt);
++ }
++
++ }
++
++ return 0;
++
++} /* astfb_setup */
++
++static void sfb_timer(unsigned long private)
++{
++ struct astfb_info *sfb = (void *) private;
++ if(sfb->need_wakeup)
++ {
++ sfb->need_wakeup=0;
++ wake_up_interruptible(&wq);
++ }
++ if(sfb->next_addr)
++ {
++ astfb_write(sfb, (u32)sfb->next_addr, AST_CRT_ADDR);
++ sfb->need_wakeup=1;
++ }
++ mod_timer(&sfb->timer, jiffies + HZ/24);
++}
++
++#ifdef CONFIG_HDMI_CAT6613
++static ssize_t show_hdmi_status(struct device *device,
++ struct device_attribute *attr, char *buf)
++{
++ struct fb_info *fb_info = dev_get_drvdata(device);
++ ssize_t len = 0;
++ int rc;
++
++ rc=ast_hdmi_get_info(fb_info);
++ if(rc==1)
++ len=sprintf(buf, "UNPLUG\n");
++ else if(rc==0)
++ len=sprintf(buf, "PLUG\n");
++ else
++ len=sprintf(buf, "UNKNOWN\n");
++ return len;
++}
++
++static ssize_t show_hdmi_enable(struct device *device,
++ struct device_attribute *attr, char *buf)
++{
++ struct fb_info *info = dev_get_drvdata(device);
++ struct astfb_info *sfb = info->par;
++
++ return sprintf(buf, "%d\n",sfb->hdmi_en);
++}
++
++static ssize_t store_hdmi_enable(struct device *device,
++ struct device_attribute *attr,
++ const char *buf, size_t count)
++{
++ struct fb_info *info = dev_get_drvdata(device);
++ struct astfb_info *sfb = info->par;
++ if(buf[0]=='1') {
++ ast_hdmi_enable(1);
++ sfb->hdmi_en=1;
++ }
++ else {
++ ast_hdmi_enable(0);
++ sfb->hdmi_en=0;
++ }
++
++ return count;
++}
++#endif
++
++static ssize_t show_lcd_enable(struct device *device,
++ struct device_attribute *attr, char *buf)
++{
++ struct fb_info *info = dev_get_drvdata(device);
++ struct astfb_info *sfb = info->par;
++ if(astfb_read(sfb, AST_CRT_CTRL1) & CRT_CTRL_GRAPHIC_EN)
++ return sprintf(buf, "%d\n",1);
++ else
++ return sprintf(buf, "%d\n",0);
++}
++
++static ssize_t store_lcd_enable(struct device *device,
++ struct device_attribute *attr,
++ const char *buf, size_t count)
++{
++ struct fb_info *info = dev_get_drvdata(device);
++ struct astfb_info *sfb = info->par;
++ if(buf[0]=='1') {
++ astfb_write(sfb, astfb_read(sfb, AST_CRT_CTRL1) | CRT_CTRL_GRAPHIC_EN, AST_CRT_CTRL1);
++ }
++ else {
++ astfb_write(sfb, astfb_read(sfb, AST_CRT_CTRL1) & ~CRT_CTRL_GRAPHIC_EN, AST_CRT_CTRL1);
++ }
++
++ return count;
++}
++
++static ssize_t show_pix_clk(struct device *device,
++ struct device_attribute *attr, char *buf)
++{
++ struct fb_info *info = dev_get_drvdata(device);
++ struct astfb_info *sfb = info->par;
++
++// return sprintf(buf, "target_clk=%d\ncalc_clk=%d\n",sfb->target_clk,sfb->calc_clk);
++}
++
++static ssize_t no_pan_display_show(struct device *device,
++ struct device_attribute *attr, char *buf)
++{
++ return sprintf(buf, "%hu\n", gNoPanDisplay);
++}
++
++static ssize_t no_pan_display_store(struct device *device,
++ struct device_attribute *attr,
++ const char *buf, size_t count)
++{
++ unsigned short value;
++
++ if (sscanf(buf, "%hu", &value) != 1 ||
++ (value != 0 && value != 1 )) {
++ dprintk(KERN_ERR "no_pan_display_store : Invalid value\n");
++ return -EINVAL;
++ }
++
++ if(value == 0)
++ gNoPanDisplay = 0;
++ else if(value == 1)
++ gNoPanDisplay = 1;
++
++ return count;
++}
++
++static ssize_t phys_addr_show(struct device *device,
++ struct device_attribute *attr, char *buf)
++{
++ struct fb_info *info = dev_get_drvdata(device);
++ return sprintf(buf, "%hu\n", info->fix.smem_start);
++}
++
++static ssize_t virt_addr_show(struct device *device,
++ struct device_attribute *attr, char *buf)
++{
++ struct fb_info *info = dev_get_drvdata(device);
++ return sprintf(buf, "%hu\n", info->screen_base);
++}
++
++static struct device_attribute device_attrs[] = {
++ __ATTR(virt_addr, S_IRUGO | S_IWUGO, virt_addr_show, NULL),
++ __ATTR(phys_addr, S_IRUGO | S_IWUGO, phys_addr_show, NULL),
++ __ATTR(no_pan_display, S_IRUGO | S_IWUGO, no_pan_display_show, no_pan_display_store),
++ __ATTR(lcd_enable, S_IRUGO | S_IWUGO, show_lcd_enable, store_lcd_enable),
++ __ATTR(pixel_clock, S_IRUGO, show_pix_clk, NULL),
++// __ATTR(osd_enable, S_IRUGO, show_osd_enable, store_osd_enable),
++// __ATTR(cursor_enable, S_IRUGO, show_cursor_enable, store_cursor_enable),
++#ifdef CONFIG_HDMI_CAT6613
++ __ATTR(hdmi_status, S_IRUGO, show_hdmi_status, NULL),
++ __ATTR(hdmi_enable, S_IRUGO | S_IWUGO, show_hdmi_enable, store_hdmi_enable),
++#endif
++#ifdef CONFIG_VGA_EDID
++ __ATTR(vga_status, S_IRUGO, show_vga_status, NULL),
++ __ATTR(vga_detect, S_IRUGO | S_IWUGO, show_vga_edid, NULL),
++#endif
++};
++
++static int astfb_probe(struct platform_device *pdev)
++{
++ struct astfb_device *astfbdev = NULL;
++ struct astfb_info *sfb;
++ struct fb_info *info;
++ struct device *dev = &pdev->dev;
++ int ret,i,retval;
++ char *mode_option;
++
++ dprintk("astfb_probe \n");
++
++ info = framebuffer_alloc(sizeof(struct astfb_info), dev);
++ if (!info) {
++ dev_err(dev, "cannot allocate memory\n");
++ return -ENOMEM;
++ }
++
++ sfb = info->par;
++ sfb->info = info;
++ sfb->pdev = pdev;
++ sfb->fb_plat_data = (struct ast_fb_plat_data *)dev->platform_data;
++ strcpy(info->fix.id, sfb->pdev->name);
++
++ sfb->reg_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
++ if (!sfb->reg_res) {
++ dev_err(dev, "register resources unusable\n");
++ ret = -ENXIO;
++ goto free_info;
++ }
++
++ sfb->irq = platform_get_irq(pdev, 0);
++ if (!sfb->irq) {
++ dev_err(dev, "unable to get irq\n");
++ ret = -ENXIO;
++ goto free_info;
++ }
++
++ if(!sfb->fb_plat_data) {
++ dev_err(dev, "unable to get ast fb platform data\n");
++ ret = -ENXIO;
++ goto free_info;
++ }
++
++ info->fix.mmio_start = sfb->reg_res->start;
++ info->fix.mmio_len = sfb->reg_res->end - sfb->reg_res->start + 1;
++
++ if (!request_mem_region(info->fix.mmio_start, info->fix.mmio_len, pdev->name)) {
++ dev_err(dev, "cannot request CRT registers\n");
++ ret = -EBUSY;
++ goto free_info;
++ }
++
++ sfb->base = ioremap(info->fix.mmio_start, info->fix.mmio_len);
++ if (!sfb->base) {
++ dev_err(dev, "cannot map LCDC registers\n");
++ ret = -ENOMEM;
++ goto free_res;
++ }
++
++ info->fbops = &astfb_ops;
++
++ if(astfb_setup(sfb)) {
++ dev_warn(dev, "cannot get fb boot options will use default !!!\n");
++ }
++// if (!mode_option) {
++ mode_option = "640x480-32@60";
++ info->fix.smem_start = 0x47000000;
++
++// }
++
++ if(fb_find_mode(&info->var, info, mode_option, NULL, 0, NULL, 8) != 1) {
++ dev_err(dev, "cannot find db modes \n");
++ ret = -ENOMEM;
++ goto free_res;
++ }
++
++
++ /* resource allocation */
++ info->fix.smem_len = SZ_2M * ((info->var.bits_per_pixel)/8 * NUMBER_OF_BUFFERS); //assign 16M for 1920*1080*32it double-buffering
++
++ printk("info->fix.smem_start = %x , len = %d , bpp = %d\n",info->fix.smem_start, info->fix.smem_len, info->var.bits_per_pixel);
++
++ if (!request_mem_region(info->fix.smem_start, info->fix.smem_len, pdev->name)) {
++ dev_err(dev, "cannot request CRT mem\n");
++ ret = -EBUSY;
++ goto free_io;
++ }
++
++ info->screen_base = ioremap(info->fix.smem_start, info->fix.smem_len);
++ if (!info->screen_base) {
++ dev_err(dev, "cannot map CRT mem\n");
++ ret = -ENOMEM;
++ goto free_addr;
++ }
++
++ printk(KERN_INFO "FB Phys:%x, Virtual:%x \n", info->fix.smem_start, info->screen_base);
++
++ info->fix.type = FB_TYPE_PACKED_PIXELS;
++ info->fix.type_aux = 0;
++
++#if (NUMBER_OF_BUFFERS > 1)
++ info->fix.ypanstep = 1;
++#else
++ info->fix.ypanstep = 0;
++#endif
++
++ info->fix.xpanstep = 0;
++ info->fix.ywrapstep = 0;
++ info->fix.visual = FB_VISUAL_TRUECOLOR,
++ info->fix.accel = FB_ACCEL_NONE;
++ info->flags = FBINFO_FLAG_DEFAULT;
++ info->pseudo_palette = sfb->pseudo_palette;
++
++ /*
++ * Allocate colourmap.
++ */
++ ret=fb_alloc_cmap(&(info->cmap), 256, 0);
++ if(ret) {
++ dev_err(dev, "Alloc color map failed\n");
++ goto free_mem;
++ }
++
++ ret = request_irq(sfb->irq, astfb_isr, IRQF_SHARED, pdev->name, sfb);
++ if (ret) {
++ dev_err(dev, "Can't request LCD irq");
++ ret = -EBUSY;
++ goto free_cmap;
++ }
++ init_waitqueue_head(&wq);
++
++ ret = astfb_check_var(&info->var, info);
++ if (ret)
++ goto free_irq;
++
++ init_timer(&sfb->timer);
++ sfb->timer.data = (long) sfb;
++ sfb->timer.function = sfb_timer;
++ astfb_set_par(info);
++ platform_set_drvdata(pdev, sfb);
++ ret = register_framebuffer(info);
++ if (!ret) {
++ for(i=0;i<sizeof(device_attrs)/sizeof(struct device_attribute);i++)
++ device_create_file(info->dev, &device_attrs[i]);
++ return 0;
++ }
++
++ dev_err(dev, "Failed to register framebuffer device: %d\n", ret);
++
++ astfb_write(sfb, astfb_read(sfb, AST_CRT_CTRL1) & ~CRT_CTRL_GRAPHIC_EN, AST_CRT_CTRL1);
++ platform_set_drvdata(pdev, NULL);
++free_irq:
++ free_irq(sfb->irq,sfb);
++free_cmap:
++ fb_dealloc_cmap(&info->cmap);
++free_mem:
++ ast_fbmem_free(sfb);
++free_addr:
++ if(sfb->addr_assign)
++ release_mem_region(info->fix.smem_start, info->fix.smem_len);
++free_io:
++ iounmap(sfb->base);
++free_res:
++ release_mem_region(info->fix.mmio_start, info->fix.mmio_len);
++free_info:
++ framebuffer_release(info);
++ return ret;
++
++}
++
++static int
++astfb_remove(struct platform_device *pdev)
++{
++ struct astfb_info *sfb = platform_get_drvdata(pdev);
++
++ unregister_framebuffer(sfb->info);
++ astfb_write(sfb, astfb_read(sfb, AST_CRT_CTRL1) & ~CRT_CTRL_GRAPHIC_EN, AST_CRT_CTRL1);
++ free_irq(sfb->irq,sfb);
++ fb_dealloc_cmap(&sfb->info->cmap);
++ iounmap(sfb->info->screen_base);
++ if(sfb->addr_assign)
++ release_mem_region(sfb->info->fix.smem_start, sfb->info->fix.smem_len);
++ iounmap(sfb->base);
++ release_mem_region(sfb->info->fix.mmio_start, sfb->info->fix.mmio_len);
++ framebuffer_release(sfb->info);
++ platform_set_drvdata(pdev, NULL);
++ dprintk("astfb_remove \n");
++
++ return 0;
++}
++
++#ifdef CONFIG_PM
++static int astfb_suspend(struct platform_device *pdev, pm_message_t state)
++{
++ /* TODO */
++ return 0;
++}
++
++static int astfb_resume(struct platform_device *pdev)
++{
++ /* TODO */
++ return 0;
++}
++#else
++#define astfb_suspend NULL
++#define astfb_resume NULL
++#endif
++
++/* driver ops */
++static struct platform_driver astfb_driver = {
++ .probe = astfb_probe,
++ .remove = astfb_remove,
++ .suspend = astfb_suspend,
++ .resume = astfb_resume,
++ .driver = {
++ .name = "ast-fb",
++ .owner = THIS_MODULE,
++ },
++
++};
++int __devinit astfb_init(void)
++{
++ return platform_driver_register(&astfb_driver);
++}
++
++static void __exit astfb_cleanup(void)
++{
++ printk(KERN_DEBUG "astfb: astfb_remove_module is called \n");
++
++ platform_driver_unregister(&astfb_driver);
++}
++
++module_init(astfb_init);
++module_exit(astfb_cleanup);
++
++MODULE_AUTHOR("Ryan Chen");
++MODULE_DESCRIPTION("Framebuffer driver for the ASPEED");
++MODULE_LICENSE("GPL");
+diff --git a/drivers/video/hdmi_cat6613.c b/drivers/video/hdmi_cat6613.c
+new file mode 100755
+index 0000000..2a6d21f
+--- /dev/null
++++ b/drivers/video/hdmi_cat6613.c
+@@ -0,0 +1,545 @@
++/********************************************************************************
++* File Name : drivers/video/hdmi_cat6613.c
++* Author : Ryan Chen
++* Description : HDMI CAT6613 driver
++*
++* Copyright (C) 2012-2020 ASPEED Technology Inc.
++* This program is free software; you can redistribute it and/or modify
++* it under the terms of the GNU General Public License as published by the Free Software Foundation;
++* either version 2 of the License, or (at your option) any later version.
++*
++* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
++* without even the implied warranty of MERCHANTABILITY or
++* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
++*
++* You should have received a copy of the GNU General Public License
++* along with this program; if not, write to the Free Software
++* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++
++* History :
++* 1. 2012/08/24 Ryan Chen create this file
++*
++********************************************************************************/
++
++#include <linux/i2c.h>
++#include <linux/delay.h>
++#include <linux/interrupt.h>
++#include <linux/fb.h>
++
++#include <mach/regs-cat6613.h>
++#include "edid.h"
++
++#define DEVICE_NAME "cat6613"
++#define CAT6613_DEVICE_ID 0xCA13
++
++struct cat6613_info {
++ struct i2c_client *client;
++ struct fb_info *fb_info;
++ struct aspeed_monitor_info *mon_info;
++ struct work_struct cat6613_work;
++ int state;//0:unplug 1:plug
++ int irq;
++};
++
++static struct cat6613_info cat6613_device;
++struct aspeed_monitor_info monitor_info;
++
++
++static void get_detailed_timing(unsigned char *block,
++ struct fb_videomode *mode)
++{
++ mode->xres = H_ACTIVE;
++ mode->yres = V_ACTIVE;
++ mode->pixclock = PIXEL_CLOCK;
++ mode->pixclock /= 1000;
++ mode->pixclock = KHZ2PICOS(mode->pixclock);
++ mode->right_margin = H_SYNC_OFFSET;
++ mode->left_margin = (H_ACTIVE + H_BLANKING) -
++ (H_ACTIVE + H_SYNC_OFFSET + H_SYNC_WIDTH);
++ mode->upper_margin = V_BLANKING - V_SYNC_OFFSET -
++ V_SYNC_WIDTH;
++ mode->lower_margin = V_SYNC_OFFSET;
++ mode->hsync_len = H_SYNC_WIDTH;
++ mode->vsync_len = V_SYNC_WIDTH;
++ if (HSYNC_POSITIVE)
++ mode->sync |= FB_SYNC_HOR_HIGH_ACT;
++ if (VSYNC_POSITIVE)
++ mode->sync |= FB_SYNC_VERT_HIGH_ACT;
++ mode->refresh = PIXEL_CLOCK/((H_ACTIVE + H_BLANKING) *
++ (V_ACTIVE + V_BLANKING));
++ if (INTERLACED) {
++ mode->yres *= 2;
++ mode->upper_margin *= 2;
++ mode->lower_margin *= 2;
++ mode->vsync_len *= 2;
++ mode->vmode |= FB_VMODE_INTERLACED;
++ }
++ else
++ mode->vmode=0;
++ mode->flag = FB_MODE_IS_DETAILED;
++
++}
++
++static void cat6613_parse_cea(void)
++{
++ int timing_offset,cea_data_offset=0,data_tag,data_len,vic,i;
++ char *ext=&cat6613_device.mon_info->edid[128];
++ struct fb_monspecs *specs=&cat6613_device.mon_info->specs;
++
++ if(cat6613_device.mon_info->edid[126]==0 || ext[0]!=0x2) {
++ printk("DVI mode\n");
++ cat6613_device.mon_info->type=0; //dvi mode
++ return;
++ }
++
++ printk("CEA Revision=%d\n", ext[1]);
++
++ if(ext[3]& (1<<6)) {
++ printk("HDMI mode\n");
++ cat6613_device.mon_info->type=1; //hdmi mode
++ }
++ else {
++ printk("HDMI mode without audio\n");
++ cat6613_device.mon_info->type=0; //dvi mode
++ }
++
++ if(ext[2]==0) //no timing & cea data for parsing
++ return;
++
++ timing_offset=ext[2];
++
++ //parsing cea data
++ if(timing_offset!=4) {
++ while((cea_data_offset+4)!=timing_offset) {
++ data_tag=(ext[cea_data_offset+4]>>5)&0x7; //bit 5~7
++ data_len=ext[cea_data_offset+4]&0x1f; //bit 0~4
++ switch(data_tag) {
++ case 1:
++ //printk("audio data block\n");
++ break;
++ case 2:
++ //printk("video data block\n");
++ for(i=1;i<=data_len;i++) {
++ vic=ext[cea_data_offset+4+i]&0x7f;
++ //add 720p60 timing
++ if(vic==4) {
++ //printk("add 1280x720p60 timing\n");
++ memcpy(&specs->modedb[specs->modedb_len], &(panels[8].mode),sizeof(struct fb_videomode));
++ specs->modedb_len++;
++ }
++ //add 1080p60 timing
++ if(vic==16) {
++ //printk("add 1920x1080p60 timing\n");
++ memcpy(&specs->modedb[specs->modedb_len], &(panels[9].mode),sizeof(struct fb_videomode));
++ specs->modedb_len++;
++ }
++ if(vic==2 || vic==3) {
++ //printk("add 720x480p60 timing\n");
++ memcpy(&specs->modedb[specs->modedb_len], &(panels[10].mode),sizeof(struct fb_videomode));
++ specs->modedb_len++;
++ }
++
++ }
++ break;
++ case 3:
++ //printk("vendor data block\n");
++ break;
++ case 4:
++ //printk("speaker data block\n");
++ break;
++ default:
++ //printk("unknown data block tag=%d\n",data_tag);
++ break;
++ }
++ cea_data_offset+=(data_len+1); //go to next block
++ }
++ }
++ while(ext[timing_offset]!=0) {
++ //printk("%x\n",ext[timing_offset+17]);
++ get_detailed_timing(&ext[timing_offset], &specs->modedb[specs->modedb_len]);
++ specs->modedb_len++;
++ timing_offset+=18;
++ }
++
++}
++
++static int cat6613_reset(struct i2c_client *client)
++{
++ int rc;
++ rc = i2c_smbus_write_byte_data(client, REG_TX_BANK_CTRL, 0x00);
++ rc |= i2c_smbus_write_byte_data(client, REG_TX_SW_RST, 0x3d);
++ msleep(2);
++ rc |= i2c_smbus_write_byte_data(client, REG_TX_SW_RST, 0x1d);
++ msleep(2);
++ rc |= i2c_smbus_write_byte_data(client, REG_TX_HDMI_MODE, 0x00);
++ rc |= i2c_smbus_write_byte_data(client, REG_TX_AV_MUTE, 0x01);
++
++ //set int
++ rc |=i2c_smbus_write_byte_data(client,REG_TX_INT_CTRL, 0x40);
++ rc |=i2c_smbus_write_byte_data(client,REG_TX_INT_MASK1, 0xfd);
++ rc |=i2c_smbus_write_byte_data(client,REG_TX_INT_MASK2, 0xff) ;
++ rc |=i2c_smbus_write_byte_data(client,REG_TX_INT_MASK3, 0x7f);
++
++ return rc;
++
++}
++
++static int cat6613_afe(struct i2c_client *client)
++{
++ int tmds,rc=0;
++ if(cat6613_device.fb_info) {
++ tmds=1000000/(cat6613_device.fb_info->var.pixclock);
++ if(tmds > 80) {
++ rc = i2c_smbus_write_byte_data(client, REG_TX_AFE_DRV_CTRL,0x10);
++ rc |= i2c_smbus_write_byte_data(client, REG_TX_AFE_XP_CTRL,0x88);
++ rc |= i2c_smbus_write_byte_data(client, REG_TX_AFE_ISW_CTRL,0x10);
++ rc |= i2c_smbus_write_byte_data(client, REG_TX_AFE_IP_CTRL,0x84);
++
++ }
++ else {
++
++ rc = i2c_smbus_write_byte_data(client, REG_TX_AFE_DRV_CTRL,0x10);
++ rc |= i2c_smbus_write_byte_data(client, REG_TX_AFE_XP_CTRL,0x18);
++ rc |= i2c_smbus_write_byte_data(client, REG_TX_AFE_ISW_CTRL,0x10);
++ rc |= i2c_smbus_write_byte_data(client, REG_TX_AFE_IP_CTRL,0x0c);
++ }
++ rc |= i2c_smbus_write_byte_data(client, REG_TX_AFE_DRV_CTRL,0x00);
++ }
++
++ return rc;
++}
++
++static int cat6613_set_av(struct i2c_client *client)
++{
++ int rc=0;
++
++ rc |= i2c_smbus_write_byte_data(client, REG_TX_SW_RST,0xd); //reset av
++ msleep(1);
++ if(cat6613_device.mon_info->type==0) {
++ rc |= i2c_smbus_write_byte_data(client, REG_TX_HDMI_MODE,0); //dvi mode
++ rc |= i2c_smbus_write_byte_data(client, REG_TX_SW_RST,5);
++ msleep(1);
++ return rc;
++ }
++
++ rc |= i2c_smbus_write_byte_data(client, REG_TX_BANK_CTRL,1); //switch bank 1
++
++ rc |= i2c_smbus_write_byte_data(client, REG_TX_AVIINFO_DB1,0x12); //set underscan
++ rc |= i2c_smbus_write_byte_data(client, REG_TX_AVIINFO_DB2,0x8);
++ rc |= i2c_smbus_write_byte_data(client, REG_TX_AVIINFO_DB3,0x0);
++ rc |= i2c_smbus_write_byte_data(client, REG_TX_AVIINFO_DB4,0x0);
++ rc |= i2c_smbus_write_byte_data(client, REG_TX_AVIINFO_DB5,0x0);
++ rc |= i2c_smbus_write_byte_data(client, REG_TX_AVIINFO_DB6,0x0);
++ rc |= i2c_smbus_write_byte_data(client, REG_TX_AVIINFO_DB7,0x0);
++ rc |= i2c_smbus_write_byte_data(client, REG_TX_AVIINFO_DB8,0x0);
++ rc |= i2c_smbus_write_byte_data(client, REG_TX_AVIINFO_DB9,0x0);
++ rc |= i2c_smbus_write_byte_data(client, REG_TX_AVIINFO_DB10,0x0);
++ rc |= i2c_smbus_write_byte_data(client, REG_TX_AVIINFO_DB11,0x0);
++ rc |= i2c_smbus_write_byte_data(client, REG_TX_AVIINFO_DB12,0x0);
++ rc |= i2c_smbus_write_byte_data(client, REG_TX_AVIINFO_DB13,0x0);
++
++ rc |= i2c_smbus_write_byte_data(client, REG_TX_AVIINFO_SUM,0x55); //check sum
++
++ rc |= i2c_smbus_write_byte_data(client, REG_TX_BANK_CTRL,0); //switch bank 0
++ rc |= i2c_smbus_write_byte_data(client, REG_TX_PKT_GENERAL_CTRL,1);
++ rc |= i2c_smbus_write_byte_data(client, REG_TX_NULL_CTRL,1);
++ rc |= i2c_smbus_write_byte_data(client, REG_TX_ACP_CTRL,0);
++ rc |= i2c_smbus_write_byte_data(client, REG_TX_AVI_INFOFRM_CTRL,3);
++ rc |= i2c_smbus_write_byte_data(client, REG_TX_AUD_INFOFRM_CTRL,1);
++ rc |= i2c_smbus_write_byte_data(client, REG_TX_MPG_INFOFRM_CTRL,0);
++
++ rc |= i2c_smbus_write_byte_data(client, REG_TX_HDMI_MODE,1); //hdmi mode
++
++ rc |= i2c_smbus_write_byte_data(client, 0xf8,0xc3);
++ rc |= i2c_smbus_write_byte_data(client, 0xf8,0xa5);
++ rc |= i2c_smbus_write_byte_data(client, REG_TX_PKT_SINGLE_CTRL,0x0); //set auto cts
++
++ rc |= i2c_smbus_write_byte_data(client, REG_TX_AUDIO_CTRL0,0x0);
++ rc |= i2c_smbus_write_byte_data(client, REG_TX_AUDIO_CTRL0,0x1); //set i2s 16bit
++ rc |= i2c_smbus_write_byte_data(client, REG_TX_AUDIO_CTRL1,0x1); //set not full packet mode & 32bit i2s
++
++ rc |= i2c_smbus_write_byte_data(client, REG_TX_SW_RST,1);
++ msleep(1);
++
++ return rc;
++
++}
++
++static int cat6613_clear_mute(struct i2c_client *client)
++{
++ int rc;
++ rc = i2c_smbus_write_byte_data(client, REG_TX_AV_MUTE,0);
++ return rc;
++}
++
++
++static int cat6613_wait_ddc(struct i2c_client *client)
++{
++ int rc,count;
++
++ for(count=0;count<10;count++) {
++ rc=i2c_smbus_read_byte_data(client,REG_TX_DDC_STATUS);
++ if(rc & B_DDC_DONE)
++ return 0;
++ msleep(1);
++ }
++ printk("ddc timeout\n");
++ i2c_smbus_write_byte_data(client,REG_TX_DDC_MASTER_CTRL, B_MASTERHOST ) ;
++ i2c_smbus_write_byte_data(client,REG_TX_DDC_CMD, CMD_DDC_ABORT) ;
++ return -1;
++
++}
++
++static int cat6613_read_edid(struct i2c_client *client)
++{
++ int j ;
++ int remained_byte, offset, count;
++ remained_byte = 256 ;
++ offset=0;
++
++ while(offset<256) {
++ count = (remained_byte<32)?remained_byte:32 ;
++ i2c_smbus_write_byte_data(cat6613_device.client,REG_TX_DDC_MASTER_CTRL, B_MASTERDDC|B_MASTERHOST ) ;
++ i2c_smbus_write_byte_data(cat6613_device.client,REG_TX_DDC_CMD, CMD_FIFO_CLR);
++ if(cat6613_wait_ddc(cat6613_device.client)) {
++ return -1;
++ }
++
++ i2c_smbus_write_byte_data(client,REG_TX_DDC_HEADER, 0xA0) ;
++ i2c_smbus_write_byte_data(client,REG_TX_DDC_REQOFF, offset) ;
++ i2c_smbus_write_byte_data(client,REG_TX_DDC_REQCOUNT, count) ;
++ i2c_smbus_write_byte_data(client,REG_TX_DDC_EDIDSEG, 0) ;
++ i2c_smbus_write_byte_data(client,REG_TX_DDC_CMD, 3);
++ if(cat6613_wait_ddc(cat6613_device.client)) {
++ return -1;
++ }
++ for( j = 0 ; j < count ; j++)
++ {
++ cat6613_device.mon_info->edid[offset+j] = i2c_smbus_read_byte_data(client,REG_TX_DDC_READFIFO); ;
++ }
++ remained_byte -= count ;
++ offset += count ;
++ }
++ return 0;
++
++}
++
++static void cat6613_add_modes(void)
++{
++ int i;
++ struct fb_monspecs *specs=&cat6613_device.mon_info->specs;
++ struct fb_info *info=cat6613_device.fb_info;
++
++ for(i=0;i<specs->modedb_len;i++) {
++ fb_add_videomode(&specs->modedb[i],&info->modelist);
++ }
++
++}
++
++static void cat6613_del_modes(void)
++{
++ int i;
++ struct fb_monspecs *specs=&cat6613_device.mon_info->specs;
++ struct fb_info *info=cat6613_device.fb_info;
++ if(!info)
++ return;
++
++ for(i=0;i<specs->modedb_len;i++) {
++ fb_delete_videomode(&specs->modedb[i],&info->modelist);
++ }
++}
++
++static void cat6613_handle(struct work_struct *work)
++{
++ char int_status,sys_status,rc,int_status3;
++ struct fb_var_screeninfo tmp_var;
++ int_status=i2c_smbus_read_byte_data(cat6613_device.client,REG_TX_INT_STAT1);
++ sys_status=i2c_smbus_read_byte_data(cat6613_device.client, REG_TX_SYS_STATUS);
++ int_status3=i2c_smbus_read_byte_data(cat6613_device.client,REG_TX_INT_STAT3);
++ if(!(sys_status&B_INT_ACTIVE))
++ printk("cat6613_handle: no int\n");
++ else {
++#if 0
++ if(int_status & B_INT_DDCFIFO_ERR) {
++ printk("B_INT_DDCFIFO_ERR\n");
++ i2c_smbus_write_byte_data(cat6613_device.client,REG_TX_DDC_MASTER_CTRL, B_MASTERHOST ) ;
++ i2c_smbus_write_byte_data(cat6613_device.client,REG_TX_DDC_CMD, CMD_FIFO_CLR);
++ }
++
++ if(int_status & B_INT_DDC_BUS_HANG) {
++ printk("B_INT_DDC_BUS_HANG\n");
++ i2c_smbus_write_byte_data(cat6613_device.client,REG_TX_DDC_MASTER_CTRL, B_MASTERHOST ) ;
++ i2c_smbus_write_byte_data(cat6613_device.client,REG_TX_DDC_CMD, CMD_DDC_ABORT) ;
++ }
++ if(int_status & B_INT_HPD_PLUG) {
++ if(sys_status & B_HPDETECT)
++ printk("HPD PLUG\n");
++ else
++ printk("HPD UN PLUG 0\n");
++ i2c_smbus_write_byte_data(cat6613_device.client,REG_TX_INT_CLR0,B_CLR_HPD);
++ }
++ if(int_status3 & B_INT_VIDSTABLE) {
++ if(sys_status & B_TXVIDSTABLE) {
++ printk("VIDSTABLE\n");
++ i2c_smbus_write_byte_data(cat6613_device.client, REG_TX_AFE_DRV_CTRL,0x00);
++ }
++ else
++ printk("UN VIDSTABLE\n");
++ i2c_smbus_write_byte_data(cat6613_device.client,REG_TX_INT_CLR1,B_CLR_VIDSTABLE);
++ }
++#endif
++ if(int_status & B_INT_RX_SENSE) {
++ if(sys_status& B_RXSENDETECT) {
++ if(cat6613_device.state==0) {
++ rc=cat6613_read_edid(cat6613_device.client);
++ if(!rc) {
++ rc=fb_parse_edid(cat6613_device.mon_info->edid,&tmp_var);
++ if(!rc)
++ cat6613_device.state=1;
++ }
++ }
++ }
++ else {
++ printk("HPD UN PLUG 0\n");
++ if(cat6613_device.state==1) {
++ printk("HPD UN PLUG 1\n");
++ cat6613_del_modes();
++ cat6613_device.mon_info->status=0;
++ cat6613_device.state=0;
++ }
++ }
++ i2c_smbus_write_byte_data(cat6613_device.client,REG_TX_INT_CLR0,B_CLR_RXSENSE);
++ }
++ }
++
++ i2c_smbus_write_byte_data(cat6613_device.client,REG_TX_SYS_STATUS, sys_status | B_INTACTDONE );
++ i2c_smbus_write_byte_data(cat6613_device.client,REG_TX_SYS_STATUS, sys_status);
++ enable_irq(cat6613_device.irq);
++}
++
++static irqreturn_t cat6613_isr(int irq, void *parm)
++{
++
++ disable_irq_nosync(cat6613_device.irq);
++ schedule_work(&cat6613_device.cat6613_work);
++ return IRQ_HANDLED;
++}
++
++static int hdmi_cat6613_probe(struct i2c_client *client,
++ const struct i2c_device_id *id)
++{
++ int rc=0;
++ if (!i2c_check_functionality(client->adapter,
++ I2C_FUNC_SMBUS_BYTE | I2C_FUNC_I2C))
++ return -ENODEV;
++
++ rc=(i2c_smbus_read_byte_data(client, REG_TX_VENDOR_ID1)<<8)&0xff00;
++ rc|=i2c_smbus_read_byte_data(client, REG_TX_DEVICE_ID0);
++ if(rc != CAT6613_DEVICE_ID) {
++ printk(KERN_ERR "%s: read id fail\n", __func__);
++ return -ENODEV;
++ }
++
++ cat6613_device.client=client;
++ cat6613_device.irq=client->irq;
++ cat6613_device.mon_info=&monitor_info;
++
++ //reset
++ rc=cat6613_reset(client);
++ if(rc)
++ printk(KERN_ERR "%s: reset fail\n", __func__);
++
++ INIT_WORK(&cat6613_device.cat6613_work, cat6613_handle);
++ rc = request_irq(cat6613_device.irq, cat6613_isr, IRQF_DISABLED, DEVICE_NAME, NULL);
++ if(rc) {
++ printk(KERN_ERR "%s: request irq fail\n", __func__);
++ return rc;
++ }
++
++ return rc;
++}
++
++static int __devexit hdmi_cat6613_remove(struct i2c_client *client)
++{
++
++ return 0;
++}
++
++
++static const struct i2c_device_id hmdi_cat6613_id[] = {
++ { DEVICE_NAME, 0 },
++ { }
++};
++
++static struct i2c_driver hdmi_cat6613_i2c_driver = {
++ .driver = {
++ .name = DEVICE_NAME,
++ .owner = THIS_MODULE,
++ },
++ .probe = hdmi_cat6613_probe,
++ .remove = __exit_p(hdmi_cat6613_remove),
++ .id_table = hmdi_cat6613_id,
++};
++
++
++int aspeed_hdmi_get_info(struct fb_info *fb_info)
++{
++
++ if(!fb_info) {
++ printk("no fb_info\n");
++ return -1;
++ }
++ cat6613_device.fb_info=fb_info;
++
++ if(cat6613_device.state==0)
++ return 1;
++
++ if(cat6613_device.mon_info->status==0) {
++ if(monitor_info.specs.modedb)
++ fb_destroy_modedb(monitor_info.specs.modedb);
++ fb_edid_to_monspecs(cat6613_device.mon_info->edid, &cat6613_device.mon_info->specs);
++ cat6613_parse_cea();
++ cat6613_add_modes();
++ cat6613_device.mon_info->status=1;
++ }
++ return 0;
++}
++
++void aspeed_hdmi_enable(int en)
++{
++ if(en==0) {
++ i2c_smbus_write_byte_data(cat6613_device.client, REG_TX_HDMI_MODE, 0x00);
++ i2c_smbus_write_byte_data(cat6613_device.client, REG_TX_AV_MUTE, 0x01);
++ }
++ else {
++ cat6613_set_av(cat6613_device.client);
++ cat6613_afe(cat6613_device.client);
++ cat6613_clear_mute(cat6613_device.client);
++ }
++}
++
++static int __init hdmi_cat6613_init(void)
++{
++ int ret;
++
++ ret = i2c_add_driver(&hdmi_cat6613_i2c_driver);
++ if (ret)
++ printk(KERN_ERR "%s: failed to add i2c driver\n", __func__);
++
++ return ret;
++}
++
++static void __exit hdmi_cat6613_exit(void)
++{
++ i2c_del_driver(&hdmi_cat6613_i2c_driver);
++}
++
++module_init(hdmi_cat6613_init);
++module_exit(hdmi_cat6613_exit);
++
++EXPORT_SYMBOL(aspeed_hdmi_get_info);
++EXPORT_SYMBOL(aspeed_hdmi_enable);
++
++MODULE_AUTHOR("Ryan Chen <jsho@aspeed-tech.com>");
++MODULE_DESCRIPTION("CAT6023 HDMI Driver");
++MODULE_LICENSE("GPL");
+diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig
+index 9d285f6..5702145 100644
+--- a/drivers/watchdog/Kconfig
++++ b/drivers/watchdog/Kconfig
+@@ -233,6 +233,12 @@ config ORION5X_WATCHDOG
+ To compile this driver as a module, choose M here: the
+ module will be called orion5x_wdt.
+
++config AST_WATCHDOG
++ tristate "ASPEED GUC watchdog"
++ depends on WATCHDOG
++ help
++ Watchdog timer for ASPEED chips.
++
+ # ARM26 Architecture
+
+ # AVR32 Architecture
+diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile
+index e352bbb..ba47642 100644
+--- a/drivers/watchdog/Makefile
++++ b/drivers/watchdog/Makefile
+@@ -41,6 +41,7 @@ obj-$(CONFIG_PNX4008_WATCHDOG) += pnx4008_wdt.o
+ obj-$(CONFIG_IOP_WATCHDOG) += iop_wdt.o
+ obj-$(CONFIG_DAVINCI_WATCHDOG) += davinci_wdt.o
+ obj-$(CONFIG_ORION5X_WATCHDOG) += orion5x_wdt.o
++obj-$(CONFIG_AST_WATCHDOG) += ast_wdt.o
+
+ # ARM26 Architecture
+
+diff --git a/drivers/watchdog/ast_wdt.c b/drivers/watchdog/ast_wdt.c
+new file mode 100644
+index 0000000..845f1db
+--- /dev/null
++++ b/drivers/watchdog/ast_wdt.c
+@@ -0,0 +1,519 @@
++/********************************************************************************
++* File Name : ast_wdt
++*
++* Copyright (C) 2012-2020 ASPEED Technology Inc.
++* This program is free software; you can redistribute it and/or modify
++* it under the terms of the GNU General Public License as published by the Free Software Foundation;
++* either version 2 of the License, or (at your option) any later version.
++* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
++* without even the implied warranty of MERCHANTABILITY or
++* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
++* You should have received a copy of the GNU General Public License
++* along with this program; if not, write to the Free Software
++* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++********************************************************************************/
++
++#include <linux/module.h>
++#include <linux/kernel.h>
++#include <linux/init.h>
++#include <linux/poll.h>
++#include <linux/interrupt.h>
++#include <linux/errno.h>
++#include <linux/types.h>
++#include <linux/string.h>
++#include <linux/delay.h>
++#include <linux/sched.h>
++#include <linux/slab.h>
++#include <linux/mm.h>
++#include <linux/miscdevice.h>
++#include <linux/watchdog.h>
++#include <linux/fs.h>
++#include <linux/notifier.h>
++#include <linux/reboot.h>
++#include <linux/init.h>
++#include <linux/semaphore.h>
++#include <asm/uaccess.h>
++
++#include <linux/platform_device.h>
++#include <asm/io.h>
++
++#ifdef CONFIG_COLDFIRE
++#include <asm/arch/irqs.h>
++#include <asm/arch/ast_wdt.h>
++#include <asm/arch/platform.h>
++#else
++#include <mach/irqs.h>
++#include <mach/ast_wdt.h>
++#include <mach/platform.h>
++#endif
++
++#define TICKS_PER_uSEC 1
++
++
++typedef unsigned char bool_T;
++
++#ifdef TRUE
++#undef TRUE
++#endif
++
++#ifdef FALSE
++#undef FALSE
++#endif
++
++#define TRUE 1
++#define FALSE 0
++
++#if defined(CONFIG_COLDFIRE)
++#define WDT_BASE_VA AST_WDT_BASE
++
++#else
++#define WDT_BASE_VA (IO_ADDRESS(AST_WDT_BASE))
++#endif
++
++#define WDT_CntSts (WDT_BASE_VA+0x00)
++#define WDT_Reload (WDT_BASE_VA+0x04)
++#define WDT_Restart (WDT_BASE_VA+0x08)
++#define WDT_Ctrl (WDT_BASE_VA+0x0C)
++#define WDT_TimeOut (WDT_BASE_VA+0x10)
++#define WDT_Clr (WDT_BASE_VA+0x14)
++#define WDT_RstWd (WDT_BASE_VA+0x18)
++
++
++#define AST_READ_REG(r) (*((volatile unsigned int *) (r)))
++#define AST_WRITE_REG(r,v) (*((volatile unsigned int *) (r)) = ((unsigned int) (v)))
++
++
++#define WDT_CLK_SRC_EXT 0
++#define WDT_CLK_SRC_PCLK 1
++
++//Global Variables
++#define WD_TIMO 6 /* Default heartbeat = 6 seconds */
++
++static int heartbeat = WD_TIMO;
++module_param(heartbeat, int, 0);
++MODULE_PARM_DESC(heartbeat, "Watchdog heartbeat in seconds. (0<heartbeat<65536, default=" __MODULE_STRING(WD_TIMO) ")");
++
++static int nowayout = WATCHDOG_NOWAYOUT;
++module_param(nowayout, int, 0);
++MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)");
++
++static unsigned long wdt_is_open;
++static char expect_close;
++
++//Function Declaration
++int __init wdt_init(void);
++
++static irqreturn_t wdt_isr(int irq, void *devid, struct pt_regs *regs)
++{
++ /* clear timeout */
++ AST_WRITE_REG(WDT_Clr, 1);
++
++ return (IRQ_HANDLED);
++}
++
++void wdt_disable(void)
++{
++ register unsigned int regVal;
++
++ /* reset WDT_Ctrl[0] as 0 */
++ regVal = AST_READ_REG(WDT_Ctrl);
++ regVal &= 0xFFFFFFFE;
++ AST_WRITE_REG(WDT_Ctrl, regVal);
++}
++
++void wdt_sel_clk_src(unsigned char sourceClk)
++{
++ register unsigned int regVal;
++
++ regVal = AST_READ_REG(WDT_Ctrl);
++ if (sourceClk == WDT_CLK_SRC_PCLK)
++ {
++ /* reset WDT_Ctrl[4] as 0 */
++ regVal &= 0xFFFFFFEF;
++ }
++ else
++ {
++ /* set WDT_Ctrl[4] as 1 */
++ regVal |= 0x00000010;
++ }
++ AST_WRITE_REG(WDT_Ctrl, regVal);
++}
++
++void wdt_set_timeout_action(bool_T bResetOut, bool_T bIntrSys, bool_T bResetSys)
++{
++ register unsigned int regVal;
++
++ regVal = AST_READ_REG(WDT_Ctrl);
++
++ if (bResetOut)
++ {
++ /* set WDT_Ctrl[3] = 1 */
++ regVal |= 0x00000008;
++ }
++ else
++ {
++ /* reset WDT_Ctrl[3] = 0 */
++ regVal &= 0xFFFFFFF7;
++ }
++
++ if (bIntrSys)
++ {
++ /* set WDT_Ctrl[2] = 1 */
++ regVal |= 0x00000004;
++ }
++ else
++ {
++ /* reset WDT_Ctrl[2] = 0 */
++ regVal &= 0xFFFFFFFB;
++ }
++
++ if (bResetSys)
++ {
++ /* set WDT_Ctrl[1] = 1 */
++ regVal |= 0x00000002;
++ }
++ else
++ {
++ /* reset WDT_Ctrl[1] = 0 */
++ regVal &= 0xFFFFFFFD;
++ }
++
++ AST_WRITE_REG(WDT_Ctrl, regVal);
++}
++
++void wdt_enable(void)
++{
++ register unsigned int regVal;
++
++ /* set WDT_Ctrl[0] as 1 */
++ regVal = AST_READ_REG(WDT_Ctrl);
++ regVal |= 1;
++ AST_WRITE_REG(WDT_Ctrl, regVal);
++}
++
++void wdt_restart_new(unsigned int nPeriod, int sourceClk, bool_T bResetOut, bool_T bIntrSys, bool_T bResetSys, bool_T bUpdated)
++{
++ wdt_disable();
++
++ AST_WRITE_REG(WDT_Reload, nPeriod);
++
++ wdt_sel_clk_src(sourceClk);
++
++ wdt_set_timeout_action(bResetOut, bIntrSys, bResetSys);
++
++ AST_WRITE_REG(WDT_Restart, 0x4755); /* reload! */
++
++ if (!bUpdated)
++ wdt_enable();
++}
++
++void wdt_restart(void)
++{
++ wdt_disable();
++ AST_WRITE_REG(WDT_Restart, 0x4755); /* reload! */
++ wdt_enable();
++}
++
++
++/**
++ * wdt_set_heartbeat:
++ * @t: the new heartbeat value that needs to be set.
++ *
++ * Set a new heartbeat value for the watchdog device. If the heartbeat value is
++ * incorrect we keep the old value and return -EINVAL. If successfull we
++ * return 0.
++ */
++static int wdt_set_heartbeat(int t)
++{
++ if ((t < 1) || (t > 1000))
++ return -EINVAL;
++
++ heartbeat=t;
++
++ wdt_restart_new(TICKS_PER_uSEC*1000000*t, WDT_CLK_SRC_EXT, FALSE, TRUE, FALSE, FALSE);
++ return 0;
++}
++
++/*
++ Kernel Interfaces
++*/
++
++/**
++ * ast_wdt_write:
++ * @file: file handle to the watchdog
++ * @buf: buffer to write (unused as data does not matter here
++ * @count: count of bytes
++ * @ppos: pointer to the position to write. No seeks allowed
++ *
++ * A write to a watchdog device is defined as a keepalive signal. Any
++ * write of data will do, as we we don't define content meaning.
++ */
++
++ static ssize_t ast_wdt_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos)
++ {
++ if(count)
++ {
++ if (!nowayout)
++ {
++ size_t i;
++
++ /* In case it was set long ago */
++ expect_close = 0;
++
++ for (i = 0; i != count; i++)
++ {
++ char c;
++ if (get_user(c, buf + i))
++ return -EFAULT;
++ if (c == 'V')
++ expect_close = 42;
++ }
++ }
++ wdt_restart();
++ }
++ return count;
++ }
++
++/**
++ * ast_wdt_ioctl:
++ * @inode: inode of the device
++ * @file: file handle to the device
++ * @cmd: watchdog command
++ * @arg: argument pointer
++ * * The watchdog API defines a common set of functions for all watchdogs
++ * according to their available features. We only actually usefully support
++ * querying capabilities and current status.
++ */
++
++static int ast_wdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
++{
++ void __user *argp = (void __user *)arg;
++ int __user *p = argp;
++ int new_heartbeat;
++
++ static struct watchdog_info ident =
++ {
++ .options = WDIOF_SETTIMEOUT|
++ WDIOF_MAGICCLOSE|
++ WDIOF_KEEPALIVEPING,
++ .firmware_version = 1,
++ .identity = "AST WDT",
++ };
++
++ switch(cmd)
++ {
++ default:
++ return -ENOIOCTLCMD;
++ case WDIOC_GETSUPPORT:
++ return copy_to_user(argp, &ident, sizeof(ident))?-EFAULT:0;
++ case WDIOC_GETSTATUS:
++ case WDIOC_GETBOOTSTATUS:
++ return put_user(0, p);
++ case WDIOC_KEEPALIVE:
++ wdt_restart();
++ return 0;
++ case WDIOC_SETTIMEOUT:
++ if (get_user(new_heartbeat, p))
++ return -EFAULT;
++
++ if (wdt_set_heartbeat(new_heartbeat))
++ return -EINVAL;
++
++ /* Fall */
++ case WDIOC_GETTIMEOUT:
++ return put_user(heartbeat, p);
++ }
++}
++/**
++* ast_wdt_open:
++* @inode: inode of device
++* @file: file handle to device
++*
++* The watchdog device has been opened. The watchdog device is single
++* open and on opening we load the counters. Counter zero is a 100Hz
++* cascade, into counter 1 which downcounts to reboot. When the counter
++* triggers counter 2 downcounts the length of the reset pulse which
++* set set to be as long as possible.
++*/
++
++static int ast_wdt_open(struct inode *inode, struct file *file)
++{
++ if(test_and_set_bit(0, &wdt_is_open))
++ return -EBUSY;
++ /*
++ * Activate
++ */
++ // wdt_init();
++ wdt_restart();
++ return nonseekable_open(inode, file);
++}
++
++/**
++* ast_wdt_release:
++* @inode: inode to board
++* @file: file handle to board
++*
++* The watchdog has a configurable API. There is a religious dispute
++* between people who want their watchdog to be able to shut down and
++* those who want to be sure if the watchdog manager dies the machine
++* reboots. In the former case we disable the counters, in the latter
++* case you have to open it again very soon.
++*/
++
++static int ast_wdt_release(struct inode *inode, struct file *file)
++{
++ if (expect_close == 42 || !nowayout)
++ {
++ wdt_disable();
++ clear_bit(0, &wdt_is_open);
++ }
++ else
++ {
++ printk(KERN_CRIT "wdt: WDT device closed unexpectedly. WDT will not stop!\n");
++ wdt_restart();
++ }
++ expect_close = 0;
++ return 0;
++}
++
++/**
++* notify_sys:
++* @this: our notifier block
++* @code: the event being reported
++* @unused: unused
++*
++* Our notifier is called on system shutdowns. We want to turn the card
++* off at reboot otherwise the machine will reboot again during memory
++* test or worse yet during the following fsck. This would suck, in fact
++* trust me - if it happens it does suck.
++*/
++
++static int ast_wdt_notify_sys(struct notifier_block *this, unsigned long code, void *unused)
++{
++ if(code==SYS_DOWN || code==SYS_HALT)
++ {
++ /* Turn the WDT off */
++ wdt_disable();
++ }
++ return NOTIFY_DONE;
++}
++
++extern void ast_soc_wdt_reset(void)
++{
++ writel(0x10 , WDT_BASE_VA+0x04);
++ writel(0x4755, WDT_BASE_VA+0x08);
++ writel(0x3, WDT_BASE_VA+0x0c);
++}
++
++EXPORT_SYMBOL(ast_soc_wdt_reset);
++
++static struct file_operations ast_wdt_fops =
++{
++ .owner = THIS_MODULE,
++ .llseek = no_llseek,
++ .write = ast_wdt_write,
++ .ioctl = ast_wdt_ioctl,
++ .open = ast_wdt_open,
++ .release = ast_wdt_release,
++};
++
++static struct miscdevice ast_wdt_miscdev =
++{
++ .minor = WATCHDOG_MINOR,
++ .name = "watchdog",
++ .fops = &ast_wdt_fops,
++};
++
++static struct notifier_block ast_wdt_notifier =
++{
++ .notifier_call=ast_wdt_notify_sys,
++};
++
++static int ast_wdt_probe(struct platform_device *pdev)
++{
++ int ret;
++
++ wdt_disable();
++ wdt_sel_clk_src(WDT_CLK_SRC_EXT);
++ wdt_set_timeout_action(FALSE, FALSE, FALSE);
++
++ /* register ISR */
++ if (request_irq(IRQ_WDT, (void *)wdt_isr, IRQF_DISABLED, "WDT", NULL))
++ {
++ printk("unable to register interrupt INT_WDT = %d\n", IRQ_WDT);
++ return (-1);
++ }
++ else
++ printk("success to register interrupt for INT_WDT (%d)\n", IRQ_WDT);
++
++ ret = register_reboot_notifier(&ast_wdt_notifier);
++ if(ret)
++ {
++ printk(KERN_ERR "wdt: cannot register reboot notifier (err=%d)\n", ret);
++ free_irq(IRQ_WDT, NULL);
++ return ret;
++ }
++
++ ret = misc_register(&ast_wdt_miscdev);
++ if (ret)
++ {
++ printk(KERN_ERR "wdt: cannot register miscdev on minor=%d (err=%d)\n",WATCHDOG_MINOR, ret);
++ unregister_reboot_notifier(&ast_wdt_notifier);
++ return ret;
++ }
++
++ /* interrupt the system while WDT timeout */
++ wdt_restart_new(TICKS_PER_uSEC*1000000*heartbeat, WDT_CLK_SRC_EXT, FALSE, TRUE, FALSE, TRUE);
++
++ printk(KERN_INFO "AST WDT is installed.(irq = %d, heartbeat = %d secs, nowayout = %d)\n",IRQ_WDT,heartbeat,nowayout);
++
++ return (0);
++}
++
++static int ast_wdt_remove(struct platform_device *dev)
++{
++ misc_deregister(&ast_wdt_miscdev);
++ disable_irq(IRQ_WDT);
++ free_irq(IRQ_WDT, NULL);
++ return 0;
++}
++
++static void ast_wdt_shutdown(struct platform_device *dev)
++{
++ wdt_disable();
++}
++
++static struct platform_driver ast_wdt_driver = {
++ .probe = ast_wdt_probe,
++ .remove = ast_wdt_remove,
++ .shutdown = ast_wdt_shutdown,
++#if 0
++ .suspend = ast_wdt_suspend,
++ .resume = ast_wdt_resume,
++#endif
++ .driver = {
++ .owner = THIS_MODULE,
++ .name = "ast-wdt",
++ },
++};
++
++static char banner[] __initdata = KERN_INFO "ASPEED Watchdog Timer, ASPEED Technology Inc.\n";
++
++static int __init watchdog_init(void)
++{
++ printk(banner);
++
++ return platform_driver_register(&ast_wdt_driver);
++}
++
++static void __exit watchdog_exit(void)
++{
++ platform_driver_unregister(&ast_wdt_driver);
++}
++
++module_init(watchdog_init);
++module_exit(watchdog_exit);
++
++MODULE_DESCRIPTION("Driver for AST Watch Dog");
++MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
++MODULE_LICENSE("GPL");
+diff --git a/fs/Kconfig b/fs/Kconfig
+index 522469a..382fa76 100644
+--- a/fs/Kconfig
++++ b/fs/Kconfig
+@@ -907,6 +907,10 @@ config EFS_FS
+ To compile the EFS file system support as a module, choose M here: the
+ module will be called efs.
+
++
++# Patched by YAFFS
++#source "fs/yaffs2/Kconfig"
++
+ source "fs/jffs2/Kconfig"
+ # UBIFS File system configuration
+ source "fs/ubifs/Kconfig"
+diff --git a/fs/Makefile b/fs/Makefile
+index d9f8afe..cbb1738 100644
+--- a/fs/Makefile
++++ b/fs/Makefile
+@@ -122,3 +122,6 @@ obj-$(CONFIG_HPPFS) += hppfs/
+ obj-$(CONFIG_DEBUG_FS) += debugfs/
+ obj-$(CONFIG_OCFS2_FS) += ocfs2/
+ obj-$(CONFIG_GFS2_FS) += gfs2/
++
++# Patched by YAFFS
++#obj-$(CONFIG_YAFFS_FS) += yaffs2/
+diff --git a/include/linux/mmc/card.h b/include/linux/mmc/card.h
+index 403aa50..b0068f7 100644
+--- a/include/linux/mmc/card.h
++++ b/include/linux/mmc/card.h
+@@ -24,12 +24,14 @@ struct mmc_cid {
+ };
+
+ struct mmc_csd {
++ unsigned char structure;
+ unsigned char mmca_vsn;
+ unsigned short cmdclass;
+ unsigned short tacc_clks;
+ unsigned int tacc_ns;
+ unsigned int r2w_factor;
+ unsigned int max_dtr;
++ unsigned int erase_size; /* In sectors */
+ unsigned int read_blkbits;
+ unsigned int write_blkbits;
+ unsigned int capacity;
+@@ -40,8 +42,17 @@ struct mmc_csd {
+ };
+
+ struct mmc_ext_csd {
++ u8 rev;
++ u8 erase_group_def;
++ u8 sec_feature_support;
++ unsigned int sa_timeout; /* Units: 100ns */
+ unsigned int hs_max_dtr;
+ unsigned int sectors;
++ unsigned int hc_erase_size; /* In sectors */
++ unsigned int hc_erase_timeout; /* In milliseconds */
++ unsigned int sec_trim_mult; /* Secure trim multiplier */
++ unsigned int sec_erase_mult; /* Secure erase multiplier */
++ unsigned int trim_timeout; /* In milliseconds */
+ };
+
+ struct sd_scr {
+@@ -89,12 +100,18 @@ struct mmc_card {
+ #define MMC_TYPE_MMC 0 /* MMC card */
+ #define MMC_TYPE_SD 1 /* SD card */
+ #define MMC_TYPE_SDIO 2 /* SDIO card */
++#define MMC_TYPE_SD_COMBO 3 /* SD combo (IO+mem) card */
+ unsigned int state; /* (our) card state */
+ #define MMC_STATE_PRESENT (1<<0) /* present in sysfs */
+ #define MMC_STATE_READONLY (1<<1) /* card is read-only */
+ #define MMC_STATE_HIGHSPEED (1<<2) /* card is in high speed mode */
+ #define MMC_STATE_BLOCKADDR (1<<3) /* card uses block-addressing */
+
++ unsigned int erase_size; /* erase size in sectors */
++ unsigned int erase_shift; /* if erase unit is power 2 */
++ unsigned int pref_erase; /* in sectors */
++ u8 erased_byte; /* value of erased bytes */
++
+ u32 raw_cid[4]; /* raw card CID */
+ u32 raw_csd[4]; /* raw card CSD */
+ u32 raw_scr[2]; /* raw card SCR */
+diff --git a/include/linux/mmc/mmc.h b/include/linux/mmc/mmc.h
+index 14b81f3..dd11ae5 100644
+--- a/include/linux/mmc/mmc.h
++++ b/include/linux/mmc/mmc.h
+@@ -31,6 +31,7 @@
+ #define MMC_ALL_SEND_CID 2 /* bcr R2 */
+ #define MMC_SET_RELATIVE_ADDR 3 /* ac [31:16] RCA R1 */
+ #define MMC_SET_DSR 4 /* bc [31:16] RCA */
++#define MMC_SLEEP_AWAKE 5 /* ac [31:16] RCA 15:flg R1b */
+ #define MMC_SWITCH 6 /* ac [31:0] See below R1b */
+ #define MMC_SELECT_CARD 7 /* ac [31:16] RCA R1 */
+ #define MMC_SEND_EXT_CSD 8 /* adtc R1 */
+@@ -127,6 +128,7 @@
+ #define R1_STATUS(x) (x & 0xFFFFE000)
+ #define R1_CURRENT_STATE(x) ((x & 0x00001E00) >> 9) /* sx, b (4 bits) */
+ #define R1_READY_FOR_DATA (1 << 8) /* sx, a */
++#define R1_SWITCH_ERROR (1 << 7) /* sx, c */
+ #define R1_APP_CMD (1 << 5) /* sr, c */
+
+ /*
+@@ -249,11 +251,21 @@ struct _mmc_csd {
+ * EXT_CSD fields
+ */
+
+-#define EXT_CSD_BUS_WIDTH 183 /* R/W */
+-#define EXT_CSD_HS_TIMING 185 /* R/W */
+-#define EXT_CSD_CARD_TYPE 196 /* RO */
+-#define EXT_CSD_REV 192 /* RO */
+-#define EXT_CSD_SEC_CNT 212 /* RO, 4 bytes */
++#define EXT_CSD_ERASE_GROUP_DEF 175 /* R/W */
++#define EXT_CSD_ERASED_MEM_CONT 181 /* RO */
++#define EXT_CSD_BUS_WIDTH 183 /* R/W */
++#define EXT_CSD_HS_TIMING 185 /* R/W */
++#define EXT_CSD_REV 192 /* RO */
++#define EXT_CSD_STRUCTURE 194 /* RO */
++#define EXT_CSD_CARD_TYPE 196 /* RO */
++#define EXT_CSD_SEC_CNT 212 /* RO, 4 bytes */
++#define EXT_CSD_S_A_TIMEOUT 217 /* RO */
++#define EXT_CSD_ERASE_TIMEOUT_MULT 223 /* RO */
++#define EXT_CSD_HC_ERASE_GRP_SIZE 224 /* RO */
++#define EXT_CSD_SEC_TRIM_MULT 229 /* RO */
++#define EXT_CSD_SEC_ERASE_MULT 230 /* RO */
++#define EXT_CSD_SEC_FEATURE_SUPPORT 231 /* RO */
++#define EXT_CSD_TRIM_MULT 232 /* RO */
+
+ /*
+ * EXT_CSD field definitions
+@@ -265,11 +277,16 @@ struct _mmc_csd {
+
+ #define EXT_CSD_CARD_TYPE_26 (1<<0) /* Card can run at 26MHz */
+ #define EXT_CSD_CARD_TYPE_52 (1<<1) /* Card can run at 52MHz */
++#define EXT_CSD_CARD_TYPE_MASK 0x3 /* Mask out reserved and DDR bits */
+
+ #define EXT_CSD_BUS_WIDTH_1 0 /* Card is in 1 bit mode */
+ #define EXT_CSD_BUS_WIDTH_4 1 /* Card is in 4 bit mode */
+ #define EXT_CSD_BUS_WIDTH_8 2 /* Card is in 8 bit mode */
+
++#define EXT_CSD_SEC_ER_EN BIT(0)
++#define EXT_CSD_SEC_BD_BLK_EN BIT(2)
++#define EXT_CSD_SEC_GB_CL_EN BIT(4)
++
+ /*
+ * MMC_SWITCH access modes
+ */
+diff --git a/include/linux/mtd/nand.h b/include/linux/mtd/nand.h
+index 733d3f3..ff8a124 100644
+--- a/include/linux/mtd/nand.h
++++ b/include/linux/mtd/nand.h
+@@ -599,6 +599,12 @@ struct platform_nand_ctrl {
+ void (*select_chip)(struct mtd_info *mtd, int chip);
+ void (*cmd_ctrl)(struct mtd_info *mtd, int dat,
+ unsigned int ctrl);
++ int (*calculate)(struct mtd_info *mtd,
++ const uint8_t *dat,
++ uint8_t *ecc_code);
++ int (*correct)(struct mtd_info *mtd, uint8_t *dat,
++ uint8_t *read_ecc,
++ uint8_t *calc_ecc);
+ void *priv;
+ };
+
diff --git a/meta-aspeed/recipes-kernel/linux/files/patch-2.6.28.9/0000-linux-openbmc.patch b/meta-aspeed/recipes-kernel/linux/files/patch-2.6.28.9/0000-linux-openbmc.patch
new file mode 100644
index 0000000..434a873
--- /dev/null
+++ b/meta-aspeed/recipes-kernel/linux/files/patch-2.6.28.9/0000-linux-openbmc.patch
@@ -0,0 +1,13400 @@
+diff --git a/Documentation/hwmon/pmbus b/Documentation/hwmon/pmbus
+new file mode 100644
+index 0000000..bc342af
+--- /dev/null
++++ b/Documentation/hwmon/pmbus
+@@ -0,0 +1,214 @@
++Kernel driver pmbus
++====================
++
++Supported chips:
++ * Ericsson BMR453, BMR454
++ Prefixes: 'bmr453', 'bmr454'
++ Addresses scanned: -
++ Datasheet:
++ http://archive.ericsson.net/service/internet/picov/get?DocNo=28701-EN/LZT146395
++ * ON Semiconductor ADP4000, NCP4200, NCP4208
++ Prefixes: 'adp4000', 'ncp4200', 'ncp4208'
++ Addresses scanned: -
++ Datasheets:
++ http://www.onsemi.com/pub_link/Collateral/ADP4000-D.PDF
++ http://www.onsemi.com/pub_link/Collateral/NCP4200-D.PDF
++ http://www.onsemi.com/pub_link/Collateral/JUNE%202009-%20REV.%200.PDF
++ * Lineage Power
++ Prefixes: 'mdt040', 'pdt003', 'pdt006', 'pdt012', 'udt020'
++ Addresses scanned: -
++ Datasheets:
++ http://www.lineagepower.com/oem/pdf/PDT003A0X.pdf
++ http://www.lineagepower.com/oem/pdf/PDT006A0X.pdf
++ http://www.lineagepower.com/oem/pdf/PDT012A0X.pdf
++ http://www.lineagepower.com/oem/pdf/UDT020A0X.pdf
++ http://www.lineagepower.com/oem/pdf/MDT040A0X.pdf
++ * Texas Instruments TPS40400, TPS40422
++ Prefixes: 'tps40400', 'tps40422'
++ Addresses scanned: -
++ Datasheets:
++ http://www.ti.com/lit/gpn/tps40400
++ http://www.ti.com/lit/gpn/tps40422
++ * Generic PMBus devices
++ Prefix: 'pmbus'
++ Addresses scanned: -
++ Datasheet: n.a.
++
++Author: Guenter Roeck <linux@roeck-us.net>
++
++
++Description
++-----------
++
++This driver supports hardware montoring for various PMBus compliant devices.
++It supports voltage, current, power, and temperature sensors as supported
++by the device.
++
++Each monitored channel has its own high and low limits, plus a critical
++limit.
++
++Fan support will be added in a later version of this driver.
++
++
++Usage Notes
++-----------
++
++This driver does not probe for PMBus devices, since there is no register
++which can be safely used to identify the chip (The MFG_ID register is not
++supported by all chips), and since there is no well defined address range for
++PMBus devices. You will have to instantiate the devices explicitly.
++
++Example: the following will load the driver for an LTC2978 at address 0x60
++on I2C bus #1:
++$ modprobe pmbus
++[KML: Not for the backport]
++$ echo ltc2978 0x60 > /sys/bus/i2c/devices/i2c-1/new_device
++
++
++Platform data support
++---------------------
++
++Support for additional PMBus chips can be added by defining chip parameters in
++a new chip specific driver file. For example, (untested) code to add support for
++Emerson DS1200 power modules might look as follows.
++
++static struct pmbus_driver_info ds1200_info = {
++ .pages = 1,
++ /* Note: All other sensors are in linear mode */
++ .direct[PSC_VOLTAGE_OUT] = true,
++ .direct[PSC_TEMPERATURE] = true,
++ .direct[PSC_CURRENT_OUT] = true,
++ .m[PSC_VOLTAGE_IN] = 1,
++ .b[PSC_VOLTAGE_IN] = 0,
++ .R[PSC_VOLTAGE_IN] = 3,
++ .m[PSC_VOLTAGE_OUT] = 1,
++ .b[PSC_VOLTAGE_OUT] = 0,
++ .R[PSC_VOLTAGE_OUT] = 3,
++ .m[PSC_TEMPERATURE] = 1,
++ .b[PSC_TEMPERATURE] = 0,
++ .R[PSC_TEMPERATURE] = 3,
++ .func[0] = PMBUS_HAVE_VIN | PMBUS_HAVE_IIN | PMBUS_HAVE_STATUS_INPUT
++ | PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT
++ | PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT
++ | PMBUS_HAVE_PIN | PMBUS_HAVE_POUT
++ | PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP
++ | PMBUS_HAVE_FAN12 | PMBUS_HAVE_STATUS_FAN12,
++};
++
++static int ds1200_probe(struct i2c_client *client,
++ const struct i2c_device_id *id)
++{
++ return pmbus_do_probe(client, id, &ds1200_info);
++}
++
++static int ds1200_remove(struct i2c_client *client)
++{
++ return pmbus_do_remove(client);
++}
++
++static const struct i2c_device_id ds1200_id[] = {
++ {"ds1200", 0},
++ {}
++};
++
++MODULE_DEVICE_TABLE(i2c, ds1200_id);
++
++/* This is the driver that will be inserted */
++static struct i2c_driver ds1200_driver = {
++ .driver = {
++ .name = "ds1200",
++ },
++ .probe = ds1200_probe,
++ .remove = ds1200_remove,
++ .id_table = ds1200_id,
++};
++
++static int __init ds1200_init(void)
++{
++ return i2c_add_driver(&ds1200_driver);
++}
++
++static void __exit ds1200_exit(void)
++{
++ i2c_del_driver(&ds1200_driver);
++}
++
++
++Sysfs entries
++-------------
++
++When probing the chip, the driver identifies which PMBus registers are
++supported, and determines available sensors from this information.
++Attribute files only exist if respective sensors are supported by the chip.
++Labels are provided to inform the user about the sensor associated with
++a given sysfs entry.
++
++The following attributes are supported. Limits are read-write; all other
++attributes are read-only.
++
++inX_input Measured voltage. From READ_VIN or READ_VOUT register.
++inX_min Minimum Voltage.
++ From VIN_UV_WARN_LIMIT or VOUT_UV_WARN_LIMIT register.
++inX_max Maximum voltage.
++ From VIN_OV_WARN_LIMIT or VOUT_OV_WARN_LIMIT register.
++inX_lcrit Critical minimum Voltage.
++ From VIN_UV_FAULT_LIMIT or VOUT_UV_FAULT_LIMIT register.
++inX_crit Critical maximum voltage.
++ From VIN_OV_FAULT_LIMIT or VOUT_OV_FAULT_LIMIT register.
++inX_min_alarm Voltage low alarm. From VOLTAGE_UV_WARNING status.
++inX_max_alarm Voltage high alarm. From VOLTAGE_OV_WARNING status.
++inX_lcrit_alarm Voltage critical low alarm.
++ From VOLTAGE_UV_FAULT status.
++inX_crit_alarm Voltage critical high alarm.
++ From VOLTAGE_OV_FAULT status.
++inX_label "vin", "vcap", or "voutY"
++
++currX_input Measured current. From READ_IIN or READ_IOUT register.
++currX_max Maximum current.
++ From IIN_OC_WARN_LIMIT or IOUT_OC_WARN_LIMIT register.
++currX_lcrit Critical minimum output current.
++ From IOUT_UC_FAULT_LIMIT register.
++currX_crit Critical maximum current.
++ From IIN_OC_FAULT_LIMIT or IOUT_OC_FAULT_LIMIT register.
++currX_alarm Current high alarm.
++ From IIN_OC_WARNING or IOUT_OC_WARNING status.
++currX_max_alarm Current high alarm.
++ From IIN_OC_WARN_LIMIT or IOUT_OC_WARN_LIMIT status.
++currX_lcrit_alarm Output current critical low alarm.
++ From IOUT_UC_FAULT status.
++currX_crit_alarm Current critical high alarm.
++ From IIN_OC_FAULT or IOUT_OC_FAULT status.
++currX_label "iin" or "ioutY"
++
++powerX_input Measured power. From READ_PIN or READ_POUT register.
++powerX_cap Output power cap. From POUT_MAX register.
++powerX_max Power limit. From PIN_OP_WARN_LIMIT or
++ POUT_OP_WARN_LIMIT register.
++powerX_crit Critical output power limit.
++ From POUT_OP_FAULT_LIMIT register.
++powerX_alarm Power high alarm.
++ From PIN_OP_WARNING or POUT_OP_WARNING status.
++powerX_crit_alarm Output power critical high alarm.
++ From POUT_OP_FAULT status.
++powerX_label "pin" or "poutY"
++
++tempX_input Measured temperature.
++ From READ_TEMPERATURE_X register.
++tempX_min Mimimum temperature. From UT_WARN_LIMIT register.
++tempX_max Maximum temperature. From OT_WARN_LIMIT register.
++tempX_lcrit Critical low temperature.
++ From UT_FAULT_LIMIT register.
++tempX_crit Critical high temperature.
++ From OT_FAULT_LIMIT register.
++tempX_min_alarm Chip temperature low alarm. Set by comparing
++ READ_TEMPERATURE_X with UT_WARN_LIMIT if
++ TEMP_UT_WARNING status is set.
++tempX_max_alarm Chip temperature high alarm. Set by comparing
++ READ_TEMPERATURE_X with OT_WARN_LIMIT if
++ TEMP_OT_WARNING status is set.
++tempX_lcrit_alarm Chip temperature critical low alarm. Set by comparing
++ READ_TEMPERATURE_X with UT_FAULT_LIMIT if
++ TEMP_UT_FAULT status is set.
++tempX_crit_alarm Chip temperature critical high alarm. Set by comparing
++ READ_TEMPERATURE_X with OT_FAULT_LIMIT if
++ TEMP_OT_FAULT status is set.
+diff --git a/Documentation/hwmon/pmbus-core b/Documentation/hwmon/pmbus-core
+new file mode 100644
+index 0000000..31e4720
+--- /dev/null
++++ b/Documentation/hwmon/pmbus-core
+@@ -0,0 +1,283 @@
++PMBus core driver and internal API
++==================================
++
++Introduction
++============
++
++[from pmbus.org] The Power Management Bus (PMBus) is an open standard
++power-management protocol with a fully defined command language that facilitates
++communication with power converters and other devices in a power system. The
++protocol is implemented over the industry-standard SMBus serial interface and
++enables programming, control, and real-time monitoring of compliant power
++conversion products. This flexible and highly versatile standard allows for
++communication between devices based on both analog and digital technologies, and
++provides true interoperability which will reduce design complexity and shorten
++time to market for power system designers. Pioneered by leading power supply and
++semiconductor companies, this open power system standard is maintained and
++promoted by the PMBus Implementers Forum (PMBus-IF), comprising 30+ adopters
++with the objective to provide support to, and facilitate adoption among, users.
++
++Unfortunately, while PMBus commands are standardized, there are no mandatory
++commands, and manufacturers can add as many non-standard commands as they like.
++Also, different PMBUs devices act differently if non-supported commands are
++executed. Some devices return an error, some devices return 0xff or 0xffff and
++set a status error flag, and some devices may simply hang up.
++
++Despite all those difficulties, a generic PMBus device driver is still useful
++and supported since kernel version 2.6.39. However, it was necessary to support
++device specific extensions in addition to the core PMBus driver, since it is
++simply unknown what new device specific functionality PMBus device developers
++come up with next.
++
++To make device specific extensions as scalable as possible, and to avoid having
++to modify the core PMBus driver repeatedly for new devices, the PMBus driver was
++split into core, generic, and device specific code. The core code (in
++pmbus_core.c) provides generic functionality. The generic code (in pmbus.c)
++provides support for generic PMBus devices. Device specific code is responsible
++for device specific initialization and, if needed, maps device specific
++functionality into generic functionality. This is to some degree comparable
++to PCI code, where generic code is augmented as needed with quirks for all kinds
++of devices.
++
++PMBus device capabilities auto-detection
++========================================
++
++For generic PMBus devices, code in pmbus.c attempts to auto-detect all supported
++PMBus commands. Auto-detection is somewhat limited, since there are simply too
++many variables to consider. For example, it is almost impossible to autodetect
++which PMBus commands are paged and which commands are replicated across all
++pages (see the PMBus specification for details on multi-page PMBus devices).
++
++For this reason, it often makes sense to provide a device specific driver if not
++all commands can be auto-detected. The data structures in this driver can be
++used to inform the core driver about functionality supported by individual
++chips.
++
++Some commands are always auto-detected. This applies to all limit commands
++(lcrit, min, max, and crit attributes) as well as associated alarm attributes.
++Limits and alarm attributes are auto-detected because there are simply too many
++possible combinations to provide a manual configuration interface.
++
++PMBus internal API
++==================
++
++The API between core and device specific PMBus code is defined in
++drivers/hwmon/pmbus/pmbus.h. In addition to the internal API, pmbus.h defines
++standard PMBus commands and virtual PMBus commands.
++
++Standard PMBus commands
++-----------------------
++
++Standard PMBus commands (commands values 0x00 to 0xff) are defined in the PMBUs
++specification.
++
++Virtual PMBus commands
++----------------------
++
++Virtual PMBus commands are provided to enable support for non-standard
++functionality which has been implemented by several chip vendors and is thus
++desirable to support.
++
++Virtual PMBus commands start with command value 0x100 and can thus easily be
++distinguished from standard PMBus commands (which can not have values larger
++than 0xff). Support for virtual PMBus commands is device specific and thus has
++to be implemented in device specific code.
++
++Virtual commands are named PMBUS_VIRT_xxx and start with PMBUS_VIRT_BASE. All
++virtual commands are word sized.
++
++There are currently two types of virtual commands.
++
++- READ commands are read-only; writes are either ignored or return an error.
++- RESET commands are read/write. Reading reset registers returns zero
++ (used for detection), writing any value causes the associated history to be
++ reset.
++
++Virtual commands have to be handled in device specific driver code. Chip driver
++code returns non-negative values if a virtual command is supported, or a
++negative error code if not. The chip driver may return -ENODATA or any other
++Linux error code in this case, though an error code other than -ENODATA is
++handled more efficiently and thus preferred. Either case, the calling PMBus
++core code will abort if the chip driver returns an error code when reading
++or writing virtual registers (in other words, the PMBus core code will never
++send a virtual command to a chip).
++
++PMBus driver information
++------------------------
++
++PMBus driver information, defined in struct pmbus_driver_info, is the main means
++for device specific drivers to pass information to the core PMBus driver.
++Specifically, it provides the following information.
++
++- For devices supporting its data in Direct Data Format, it provides coefficients
++ for converting register values into normalized data. This data is usually
++ provided by chip manufacturers in device datasheets.
++- Supported chip functionality can be provided to the core driver. This may be
++ necessary for chips which react badly if non-supported commands are executed,
++ and/or to speed up device detection and initialization.
++- Several function entry points are provided to support overriding and/or
++ augmenting generic command execution. This functionality can be used to map
++ non-standard PMBus commands to standard commands, or to augment standard
++ command return values with device specific information.
++
++ API functions
++ -------------
++
++ Functions provided by chip driver
++ ---------------------------------
++
++ All functions return the command return value (read) or zero (write) if
++ successful. A return value of -ENODATA indicates that there is no manufacturer
++ specific command, but that a standard PMBus command may exist. Any other
++ negative return value indicates that the commands does not exist for this
++ chip, and that no attempt should be made to read or write the standard
++ command.
++
++ As mentioned above, an exception to this rule applies to virtual commands,
++ which _must_ be handled in driver specific code. See "Virtual PMBus Commands"
++ above for more details.
++
++ Command execution in the core PMBus driver code is as follows.
++
++ if (chip_access_function) {
++ status = chip_access_function();
++ if (status != -ENODATA)
++ return status;
++ }
++ if (command >= PMBUS_VIRT_BASE) /* For word commands/registers only */
++ return -EINVAL;
++ return generic_access();
++
++ Chip drivers may provide pointers to the following functions in struct
++ pmbus_driver_info. All functions are optional.
++
++ int (*read_byte_data)(struct i2c_client *client, int page, int reg);
++
++ Read byte from page <page>, register <reg>.
++ <page> may be -1, which means "current page".
++
++ int (*read_word_data)(struct i2c_client *client, int page, int reg);
++
++ Read word from page <page>, register <reg>.
++
++ int (*write_word_data)(struct i2c_client *client, int page, int reg,
++ u16 word);
++
++ Write word to page <page>, register <reg>.
++
++ int (*write_byte)(struct i2c_client *client, int page, u8 value);
++
++ Write byte to page <page>, register <reg>.
++ <page> may be -1, which means "current page".
++
++ int (*identify)(struct i2c_client *client, struct pmbus_driver_info *info);
++
++ Determine supported PMBus functionality. This function is only necessary
++ if a chip driver supports multiple chips, and the chip functionality is not
++ pre-determined. It is currently only used by the generic pmbus driver
++ (pmbus.c).
++
++ Functions exported by core driver
++ ---------------------------------
++
++ Chip drivers are expected to use the following functions to read or write
++ PMBus registers. Chip drivers may also use direct I2C commands. If direct I2C
++ commands are used, the chip driver code must not directly modify the current
++ page, since the selected page is cached in the core driver and the core driver
++ will assume that it is selected. Using pmbus_set_page() to select a new page
++ is mandatory.
++
++ int pmbus_set_page(struct i2c_client *client, u8 page);
++
++ Set PMBus page register to <page> for subsequent commands.
++
++ int pmbus_read_word_data(struct i2c_client *client, u8 page, u8 reg);
++
++ Read word data from <page>, <reg>. Similar to i2c_smbus_read_word_data(), but
++ selects page first.
++
++ int pmbus_write_word_data(struct i2c_client *client, u8 page, u8 reg,
++ u16 word);
++
++ Write word data to <page>, <reg>. Similar to i2c_smbus_write_word_data(), but
++ selects page first.
++
++ int pmbus_read_byte_data(struct i2c_client *client, int page, u8 reg);
++
++ Read byte data from <page>, <reg>. Similar to i2c_smbus_read_byte_data(), but
++ selects page first. <page> may be -1, which means "current page".
++
++ int pmbus_write_byte(struct i2c_client *client, int page, u8 value);
++
++ Write byte data to <page>, <reg>. Similar to i2c_smbus_write_byte(), but
++ selects page first. <page> may be -1, which means "current page".
++
++ void pmbus_clear_faults(struct i2c_client *client);
++
++ Execute PMBus "Clear Fault" command on all chip pages.
++ This function calls the device specific write_byte function if defined.
++ Therefore, it must _not_ be called from that function.
++
++ bool pmbus_check_byte_register(struct i2c_client *client, int page, int reg);
++
++ Check if byte register exists. Return true if the register exists, false
++ otherwise.
++ This function calls the device specific write_byte function if defined to
++ obtain the chip status. Therefore, it must _not_ be called from that function.
++
++ bool pmbus_check_word_register(struct i2c_client *client, int page, int reg);
++
++ Check if word register exists. Return true if the register exists, false
++ otherwise.
++ This function calls the device specific write_byte function if defined to
++ obtain the chip status. Therefore, it must _not_ be called from that function.
++
++ int pmbus_do_probe(struct i2c_client *client, const struct i2c_device_id *id,
++ struct pmbus_driver_info *info);
++
++ Execute probe function. Similar to standard probe function for other drivers,
++ with the pointer to struct pmbus_driver_info as additional argument. Calls
++ identify function if supported. Must only be called from device probe
++ function.
++
++ void pmbus_do_remove(struct i2c_client *client);
++
++ Execute driver remove function. Similar to standard driver remove function.
++
++ const struct pmbus_driver_info
++ *pmbus_get_driver_info(struct i2c_client *client);
++
++ Return pointer to struct pmbus_driver_info as passed to pmbus_do_probe().
++
++
++PMBus driver platform data
++==========================
++
++PMBus platform data is defined in include/linux/i2c/pmbus.h. Platform data
++currently only provides a flag field with a single bit used.
++
++#define PMBUS_SKIP_STATUS_CHECK (1 << 0)
++
++struct pmbus_platform_data {
++ u32 flags; /* Device specific flags */
++};
++
++
++Flags
++-----
++
++PMBUS_SKIP_STATUS_CHECK
++
++During register detection, skip checking the status register for
++communication or command errors.
++
++Some PMBus chips respond with valid data when trying to read an unsupported
++register. For such chips, checking the status register is mandatory when
++trying to determine if a chip register exists or not.
++Other PMBus chips don't support the STATUS_CML register, or report
++communication errors for no explicable reason. For such chips, checking the
++status register must be disabled.
++
++Some i2c controllers do not support single-byte commands (write commands with
++no data, i2c_smbus_write_byte()). With such controllers, clearing the status
++register is impossible, and the PMBUS_SKIP_STATUS_CHECK flag must be set.
+diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
+index 71db83f..1869327 100644
+--- a/arch/arm/Kconfig
++++ b/arch/arm/Kconfig
+@@ -203,8 +203,10 @@ config ARCH_ASPEED
+ bool "ASPEED AST Family"
+ select ARM_AMBA
+ select PLAT_ASPEED
+- select GENERIC_GPIO
+ select ARCH_REQUIRE_GPIOLIB
++ select GENERIC_GPIO
++ select GENERIC_TIME
++ select GENERIC_CLOCKEVENTS
+
+
+ config ARCH_AAEC2000
+diff --git a/arch/arm/configs/wedge_defconfig b/arch/arm/configs/wedge_defconfig
+new file mode 100644
+index 0000000..23a9fe3
+--- /dev/null
++++ b/arch/arm/configs/wedge_defconfig
+@@ -0,0 +1,1479 @@
++#
++# Automatically generated make config: don't edit
++# Linux kernel version: 2.6.28.9
++# Tue Feb 3 16:41:40 2015
++#
++CONFIG_ARM=y
++CONFIG_SYS_SUPPORTS_APM_EMULATION=y
++CONFIG_GENERIC_GPIO=y
++CONFIG_GENERIC_TIME=y
++CONFIG_GENERIC_CLOCKEVENTS=y
++CONFIG_MMU=y
++# CONFIG_NO_IOPORT is not set
++CONFIG_GENERIC_HARDIRQS=y
++CONFIG_STACKTRACE_SUPPORT=y
++CONFIG_HAVE_LATENCYTOP_SUPPORT=y
++CONFIG_LOCKDEP_SUPPORT=y
++CONFIG_TRACE_IRQFLAGS_SUPPORT=y
++CONFIG_HARDIRQS_SW_RESEND=y
++CONFIG_GENERIC_IRQ_PROBE=y
++CONFIG_RWSEM_GENERIC_SPINLOCK=y
++# CONFIG_ARCH_HAS_ILOG2_U32 is not set
++# CONFIG_ARCH_HAS_ILOG2_U64 is not set
++CONFIG_GENERIC_HWEIGHT=y
++CONFIG_GENERIC_CALIBRATE_DELAY=y
++CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
++CONFIG_VECTORS_BASE=0xffff0000
++CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
++
++#
++# General setup
++#
++CONFIG_EXPERIMENTAL=y
++CONFIG_BROKEN_ON_SMP=y
++CONFIG_INIT_ENV_ARG_LIMIT=32
++CONFIG_LOCALVERSION=""
++# CONFIG_LOCALVERSION_AUTO is not set
++CONFIG_KERNEL_GZIP=y
++# CONFIG_KERNEL_BZIP2 is not set
++# CONFIG_KERNEL_LZMA is not set
++CONFIG_SWAP=y
++CONFIG_SYSVIPC=y
++CONFIG_SYSVIPC_SYSCTL=y
++# CONFIG_POSIX_MQUEUE is not set
++# CONFIG_BSD_PROCESS_ACCT is not set
++# CONFIG_TASKSTATS is not set
++# CONFIG_AUDIT is not set
++CONFIG_IKCONFIG=m
++CONFIG_IKCONFIG_PROC=y
++CONFIG_LOG_BUF_SHIFT=16
++# CONFIG_CGROUPS is not set
++# CONFIG_GROUP_SCHED is not set
++CONFIG_SYSFS_DEPRECATED=y
++CONFIG_SYSFS_DEPRECATED_V2=y
++# CONFIG_RELAY is not set
++CONFIG_NAMESPACES=y
++# CONFIG_UTS_NS is not set
++# CONFIG_IPC_NS is not set
++# CONFIG_USER_NS is not set
++# CONFIG_PID_NS is not set
++CONFIG_BLK_DEV_INITRD=y
++CONFIG_INITRAMFS_SOURCE=""
++CONFIG_CC_OPTIMIZE_FOR_SIZE=y
++CONFIG_SYSCTL=y
++CONFIG_ANON_INODES=y
++# CONFIG_EMBEDDED is not set
++CONFIG_UID16=y
++CONFIG_SYSCTL_SYSCALL=y
++CONFIG_KALLSYMS=y
++CONFIG_KALLSYMS_EXTRA_PASS=y
++CONFIG_HOTPLUG=y
++CONFIG_PRINTK=y
++CONFIG_BUG=y
++CONFIG_ELF_CORE=y
++CONFIG_BASE_FULL=y
++CONFIG_FUTEX=y
++CONFIG_EPOLL=y
++CONFIG_SIGNALFD=y
++CONFIG_TIMERFD=y
++CONFIG_EVENTFD=y
++CONFIG_SHMEM=y
++CONFIG_AIO=y
++CONFIG_VM_EVENT_COUNTERS=y
++CONFIG_SLUB_DEBUG=y
++CONFIG_COMPAT_BRK=y
++# CONFIG_SLAB is not set
++CONFIG_SLUB=y
++# CONFIG_SLOB is not set
++# CONFIG_PROFILING is not set
++# CONFIG_MARKERS is not set
++CONFIG_HAVE_OPROFILE=y
++# CONFIG_KPROBES is not set
++CONFIG_HAVE_KPROBES=y
++CONFIG_HAVE_KRETPROBES=y
++CONFIG_HAVE_GENERIC_DMA_COHERENT=y
++CONFIG_SLABINFO=y
++CONFIG_RT_MUTEXES=y
++# CONFIG_TINY_SHMEM is not set
++CONFIG_BASE_SMALL=0
++CONFIG_MODULES=y
++# CONFIG_MODULE_FORCE_LOAD is not set
++CONFIG_MODULE_UNLOAD=y
++# CONFIG_MODULE_FORCE_UNLOAD is not set
++# CONFIG_MODVERSIONS is not set
++# CONFIG_MODULE_SRCVERSION_ALL is not set
++CONFIG_KMOD=y
++CONFIG_BLOCK=y
++# CONFIG_LBD is not set
++# CONFIG_BLK_DEV_IO_TRACE is not set
++# CONFIG_LSF is not set
++# CONFIG_BLK_DEV_BSG is not set
++# CONFIG_BLK_DEV_INTEGRITY is not set
++
++#
++# IO Schedulers
++#
++CONFIG_IOSCHED_NOOP=y
++CONFIG_IOSCHED_AS=y
++CONFIG_IOSCHED_DEADLINE=y
++CONFIG_IOSCHED_CFQ=y
++# CONFIG_DEFAULT_AS is not set
++# CONFIG_DEFAULT_DEADLINE is not set
++CONFIG_DEFAULT_CFQ=y
++# CONFIG_DEFAULT_NOOP is not set
++CONFIG_DEFAULT_IOSCHED="cfq"
++CONFIG_CLASSIC_RCU=y
++CONFIG_FREEZER=y
++
++#
++# System Type
++#
++CONFIG_ARCH_ASPEED=y
++# CONFIG_ARCH_AAEC2000 is not set
++# CONFIG_ARCH_INTEGRATOR is not set
++# CONFIG_ARCH_REALVIEW is not set
++# CONFIG_ARCH_VERSATILE is not set
++# CONFIG_ARCH_AT91 is not set
++# CONFIG_ARCH_CLPS7500 is not set
++# CONFIG_ARCH_CLPS711X is not set
++# CONFIG_ARCH_EBSA110 is not set
++# CONFIG_ARCH_EP93XX is not set
++# CONFIG_ARCH_FOOTBRIDGE is not set
++# CONFIG_ARCH_NETX is not set
++# CONFIG_ARCH_H720X is not set
++# CONFIG_ARCH_IMX is not set
++# CONFIG_ARCH_IOP13XX is not set
++# CONFIG_ARCH_IOP32X is not set
++# CONFIG_ARCH_IOP33X is not set
++# CONFIG_ARCH_IXP23XX is not set
++# CONFIG_ARCH_IXP2000 is not set
++# CONFIG_ARCH_IXP4XX is not set
++# CONFIG_ARCH_L7200 is not set
++# CONFIG_ARCH_KIRKWOOD is not set
++# CONFIG_ARCH_KS8695 is not set
++# CONFIG_ARCH_NS9XXX is not set
++# CONFIG_ARCH_LOKI is not set
++# CONFIG_ARCH_MV78XX0 is not set
++# CONFIG_ARCH_MXC is not set
++# CONFIG_ARCH_ORION5X is not set
++# CONFIG_ARCH_PNX4008 is not set
++# CONFIG_ARCH_PXA is not set
++# CONFIG_ARCH_RPC is not set
++# CONFIG_ARCH_SA1100 is not set
++# CONFIG_ARCH_S3C2410 is not set
++# CONFIG_ARCH_SHARK is not set
++# CONFIG_ARCH_LH7A40X is not set
++# CONFIG_ARCH_DAVINCI is not set
++# CONFIG_ARCH_OMAP is not set
++# CONFIG_ARCH_MSM is not set
++CONFIG_IRMP=y
++# CONFIG_PCEXT is not set
++# CONFIG_REMOTEFX is not set
++# CONFIG_ARCH_AST1100 is not set
++# CONFIG_ARCH_AST2100 is not set
++# CONFIG_ARCH_AST2200 is not set
++# CONFIG_ARCH_AST2300 is not set
++CONFIG_ARCH_AST2400=y
++# CONFIG_ARCH_AST2500 is not set
++
++#
++# FLASH Chip Select
++#
++# CONFIG_AST_CS0_NOR is not set
++# CONFIG_AST_CS0_NAND is not set
++CONFIG_AST_CS0_SPI=y
++# CONFIG_AST_CS0_NONE is not set
++# CONFIG_AST_CS1_NOR is not set
++# CONFIG_AST_CS1_NAND is not set
++# CONFIG_AST_CS1_SPI is not set
++CONFIG_AST_CS1_NONE=y
++# CONFIG_AST_CS2_NOR is not set
++# CONFIG_AST_CS2_NAND is not set
++# CONFIG_AST_CS2_SPI is not set
++CONFIG_AST_CS2_NONE=y
++# CONFIG_AST_CS3_NOR is not set
++# CONFIG_AST_CS3_NAND is not set
++# CONFIG_AST_CS3_SPI is not set
++CONFIG_AST_CS3_NONE=y
++# CONFIG_AST_CS4_NOR is not set
++# CONFIG_AST_CS4_NAND is not set
++# CONFIG_AST_CS4_SPI is not set
++CONFIG_AST_CS4_NONE=y
++# CONFIG_ARCH_AST1070 is not set
++# CONFIG_AST_SCU_LOCK is not set
++
++#
++# Boot options
++#
++
++#
++# Power management
++#
++CONFIG_PLAT_ASPEED=y
++
++#
++# Processor Type
++#
++CONFIG_CPU_32=y
++CONFIG_CPU_ARM926T=y
++CONFIG_CPU_32v5=y
++CONFIG_CPU_ABRT_EV5TJ=y
++CONFIG_CPU_PABRT_NOIFAR=y
++CONFIG_CPU_CACHE_VIVT=y
++CONFIG_CPU_COPY_V4WB=y
++CONFIG_CPU_TLB_V4WBI=y
++CONFIG_CPU_CP15=y
++CONFIG_CPU_CP15_MMU=y
++
++#
++# Processor Features
++#
++CONFIG_ARM_THUMB=y
++# CONFIG_CPU_ICACHE_DISABLE is not set
++# CONFIG_CPU_DCACHE_DISABLE is not set
++# CONFIG_CPU_DCACHE_WRITETHROUGH is not set
++# CONFIG_CPU_CACHE_ROUND_ROBIN is not set
++# CONFIG_OUTER_CACHE is not set
++
++#
++# Bus support
++#
++CONFIG_ARM_AMBA=y
++# CONFIG_PCI_SYSCALL is not set
++# CONFIG_ARCH_SUPPORTS_MSI is not set
++# CONFIG_PCCARD is not set
++
++#
++# Kernel Features
++#
++CONFIG_TICK_ONESHOT=y
++CONFIG_NO_HZ=y
++CONFIG_HIGH_RES_TIMERS=y
++CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
++CONFIG_VMSPLIT_3G=y
++# CONFIG_VMSPLIT_2G is not set
++# CONFIG_VMSPLIT_1G is not set
++CONFIG_PAGE_OFFSET=0xC0000000
++# CONFIG_PREEMPT is not set
++CONFIG_HZ=100
++CONFIG_AEABI=y
++CONFIG_OABI_COMPAT=y
++CONFIG_ARCH_FLATMEM_HAS_HOLES=y
++# CONFIG_ARCH_SPARSEMEM_DEFAULT is not set
++# CONFIG_ARCH_SELECT_MEMORY_MODEL is not set
++CONFIG_SELECT_MEMORY_MODEL=y
++CONFIG_FLATMEM_MANUAL=y
++# CONFIG_DISCONTIGMEM_MANUAL is not set
++# CONFIG_SPARSEMEM_MANUAL is not set
++CONFIG_FLATMEM=y
++CONFIG_FLAT_NODE_MEM_MAP=y
++CONFIG_PAGEFLAGS_EXTENDED=y
++CONFIG_SPLIT_PTLOCK_CPUS=4096
++# CONFIG_RESOURCES_64BIT is not set
++# CONFIG_PHYS_ADDR_T_64BIT is not set
++CONFIG_ZONE_DMA_FLAG=0
++CONFIG_VIRT_TO_BUS=y
++CONFIG_UNEVICTABLE_LRU=y
++CONFIG_ALIGNMENT_TRAP=y
++
++#
++# Boot options
++#
++CONFIG_ZBOOT_ROM_TEXT=0
++CONFIG_ZBOOT_ROM_BSS=0
++CONFIG_CMDLINE=""
++# CONFIG_XIP_KERNEL is not set
++# CONFIG_KEXEC is not set
++
++#
++# CPU Power Management
++#
++# CONFIG_CPU_IDLE is not set
++
++#
++# Floating point emulation
++#
++
++#
++# At least one emulation must be selected
++#
++CONFIG_FPE_NWFPE=y
++CONFIG_FPE_NWFPE_XP=y
++# CONFIG_FPE_FASTFPE is not set
++CONFIG_VFP=y
++
++#
++# Userspace binary formats
++#
++CONFIG_BINFMT_ELF=y
++# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
++CONFIG_HAVE_AOUT=y
++CONFIG_BINFMT_AOUT=y
++# CONFIG_BINFMT_MISC is not set
++
++#
++# Power management options
++#
++CONFIG_PM=y
++# CONFIG_PM_DEBUG is not set
++CONFIG_PM_SLEEP=y
++CONFIG_SUSPEND=y
++CONFIG_SUSPEND_FREEZER=y
++# CONFIG_APM_EMULATION is not set
++CONFIG_ARCH_SUSPEND_POSSIBLE=y
++CONFIG_NET=y
++
++#
++# Networking options
++#
++CONFIG_PACKET=y
++# CONFIG_PACKET_MMAP is not set
++CONFIG_UNIX=y
++CONFIG_XFRM=y
++# CONFIG_XFRM_USER is not set
++# CONFIG_XFRM_SUB_POLICY is not set
++# CONFIG_XFRM_MIGRATE is not set
++# CONFIG_XFRM_STATISTICS is not set
++# CONFIG_NET_KEY is not set
++CONFIG_INET=y
++CONFIG_IP_MULTICAST=y
++# CONFIG_IP_ADVANCED_ROUTER is not set
++CONFIG_IP_FIB_HASH=y
++CONFIG_IP_PNP=y
++CONFIG_IP_PNP_DHCP=y
++CONFIG_IP_PNP_BOOTP=y
++# CONFIG_IP_PNP_RARP is not set
++# CONFIG_NET_IPIP is not set
++# CONFIG_NET_IPGRE is not set
++# CONFIG_IP_MROUTE is not set
++# CONFIG_ARPD is not set
++# CONFIG_SYN_COOKIES is not set
++# CONFIG_INET_AH is not set
++# CONFIG_INET_ESP is not set
++# CONFIG_INET_IPCOMP is not set
++# CONFIG_INET_XFRM_TUNNEL is not set
++CONFIG_INET_TUNNEL=m
++CONFIG_INET_XFRM_MODE_TRANSPORT=y
++CONFIG_INET_XFRM_MODE_TUNNEL=y
++CONFIG_INET_XFRM_MODE_BEET=y
++# CONFIG_INET_LRO is not set
++CONFIG_INET_DIAG=y
++CONFIG_INET_TCP_DIAG=y
++# CONFIG_TCP_CONG_ADVANCED is not set
++CONFIG_TCP_CONG_CUBIC=y
++CONFIG_DEFAULT_TCP_CONG="cubic"
++# CONFIG_TCP_MD5SIG is not set
++CONFIG_IPV6=m
++# CONFIG_IPV6_PRIVACY is not set
++# CONFIG_IPV6_ROUTER_PREF is not set
++# CONFIG_IPV6_OPTIMISTIC_DAD is not set
++# CONFIG_INET6_AH is not set
++# CONFIG_INET6_ESP is not set
++# CONFIG_INET6_IPCOMP is not set
++# CONFIG_IPV6_MIP6 is not set
++# CONFIG_INET6_XFRM_TUNNEL is not set
++# CONFIG_INET6_TUNNEL is not set
++CONFIG_INET6_XFRM_MODE_TRANSPORT=m
++CONFIG_INET6_XFRM_MODE_TUNNEL=m
++CONFIG_INET6_XFRM_MODE_BEET=m
++# CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION is not set
++CONFIG_IPV6_SIT=m
++CONFIG_IPV6_NDISC_NODETYPE=y
++# CONFIG_IPV6_TUNNEL is not set
++# CONFIG_IPV6_MULTIPLE_TABLES is not set
++# CONFIG_IPV6_MROUTE is not set
++# CONFIG_NETWORK_SECMARK is not set
++# CONFIG_NETFILTER is not set
++# CONFIG_IP_DCCP is not set
++# CONFIG_IP_SCTP is not set
++# CONFIG_TIPC is not set
++# CONFIG_ATM is not set
++# CONFIG_BRIDGE is not set
++# CONFIG_NET_DSA is not set
++CONFIG_VLAN_8021Q=m
++# CONFIG_VLAN_8021Q_GVRP is not set
++# CONFIG_DECNET is not set
++# CONFIG_LLC2 is not set
++# CONFIG_IPX is not set
++# CONFIG_ATALK is not set
++# CONFIG_X25 is not set
++# CONFIG_LAPB is not set
++# CONFIG_ECONET is not set
++CONFIG_WAN_ROUTER=y
++# CONFIG_NET_SCHED is not set
++
++#
++# Network testing
++#
++# CONFIG_NET_PKTGEN is not set
++# CONFIG_HAMRADIO is not set
++# CONFIG_CAN is not set
++# CONFIG_IRDA is not set
++# CONFIG_BT is not set
++# CONFIG_AF_RXRPC is not set
++# CONFIG_PHONET is not set
++# CONFIG_WIRELESS is not set
++# CONFIG_RFKILL is not set
++# CONFIG_NET_9P is not set
++
++#
++# Device Drivers
++#
++
++#
++# Generic Driver Options
++#
++CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
++CONFIG_STANDALONE=y
++CONFIG_PREVENT_FIRMWARE_BUILD=y
++CONFIG_FW_LOADER=y
++CONFIG_FIRMWARE_IN_KERNEL=y
++CONFIG_EXTRA_FIRMWARE=""
++# CONFIG_SYS_HYPERVISOR is not set
++CONFIG_CONNECTOR=y
++CONFIG_PROC_EVENTS=y
++CONFIG_MTD=y
++# CONFIG_MTD_DEBUG is not set
++CONFIG_MTD_CONCAT=y
++CONFIG_MTD_PARTITIONS=y
++# CONFIG_MTD_REDBOOT_PARTS is not set
++CONFIG_MTD_CMDLINE_PARTS=y
++# CONFIG_MTD_AFS_PARTS is not set
++# CONFIG_MTD_AR7_PARTS is not set
++
++#
++# User Modules And Translation Layers
++#
++CONFIG_MTD_CHAR=y
++CONFIG_MTD_BLKDEVS=y
++CONFIG_MTD_BLOCK=y
++# CONFIG_FTL is not set
++# CONFIG_NFTL is not set
++# CONFIG_INFTL is not set
++# CONFIG_RFD_FTL is not set
++# CONFIG_SSFDC is not set
++# CONFIG_MTD_OOPS is not set
++
++#
++# RAM/ROM/Flash chip drivers
++#
++# CONFIG_MTD_CFI is not set
++# CONFIG_MTD_JEDECPROBE is not set
++CONFIG_MTD_MAP_BANK_WIDTH_1=y
++CONFIG_MTD_MAP_BANK_WIDTH_2=y
++CONFIG_MTD_MAP_BANK_WIDTH_4=y
++# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
++# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
++# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
++CONFIG_MTD_CFI_I1=y
++CONFIG_MTD_CFI_I2=y
++# CONFIG_MTD_CFI_I4 is not set
++# CONFIG_MTD_CFI_I8 is not set
++# CONFIG_MTD_RAM is not set
++# CONFIG_MTD_ROM is not set
++# CONFIG_MTD_ABSENT is not set
++
++#
++# Mapping drivers for chip access
++#
++# CONFIG_MTD_COMPLEX_MAPPINGS is not set
++# CONFIG_MTD_PLATRAM is not set
++
++#
++# Self-contained MTD device drivers
++#
++CONFIG_MTD_DATAFLASH=m
++CONFIG_MTD_DATAFLASH_WRITE_VERIFY=y
++# CONFIG_MTD_DATAFLASH_OTP is not set
++CONFIG_MTD_M25P80=y
++CONFIG_M25PXX_USE_FAST_READ=y
++# CONFIG_MTD_SLRAM is not set
++# CONFIG_MTD_PHRAM is not set
++# CONFIG_MTD_MTDRAM is not set
++# CONFIG_MTD_BLOCK2MTD is not set
++
++#
++# Disk-On-Chip Device Drivers
++#
++# CONFIG_MTD_DOC2000 is not set
++# CONFIG_MTD_DOC2001 is not set
++# CONFIG_MTD_DOC2001PLUS is not set
++# CONFIG_MTD_NAND is not set
++# CONFIG_MTD_ONENAND is not set
++
++#
++# UBI - Unsorted block images
++#
++# CONFIG_MTD_UBI is not set
++# CONFIG_PARPORT is not set
++CONFIG_BLK_DEV=y
++# CONFIG_BLK_DEV_COW_COMMON is not set
++CONFIG_BLK_DEV_LOOP=y
++# CONFIG_BLK_DEV_CRYPTOLOOP is not set
++CONFIG_BLK_DEV_NBD=y
++# CONFIG_BLK_DEV_UB is not set
++CONFIG_BLK_DEV_RAM=y
++CONFIG_BLK_DEV_RAM_COUNT=16
++CONFIG_BLK_DEV_RAM_SIZE=16384
++# CONFIG_BLK_DEV_XIP is not set
++# CONFIG_RD_BZIP2 is not set
++CONFIG_RD_LZMA=y
++CONFIG_RD_GZIP=y
++# CONFIG_CDROM_PKTCDVD is not set
++# CONFIG_ATA_OVER_ETH is not set
++CONFIG_MISC_DEVICES=y
++# CONFIG_EEPROM_93CX6 is not set
++# CONFIG_ICS932S401 is not set
++# CONFIG_ENCLOSURE_SERVICES is not set
++# CONFIG_C2PORT is not set
++CONFIG_HAVE_IDE=y
++# CONFIG_IDE is not set
++
++#
++# SCSI device support
++#
++# CONFIG_RAID_ATTRS is not set
++CONFIG_SCSI=y
++CONFIG_SCSI_DMA=y
++CONFIG_SCSI_TGT=y
++# CONFIG_SCSI_NETLINK is not set
++CONFIG_SCSI_PROC_FS=y
++
++#
++# SCSI support type (disk, tape, CD-ROM)
++#
++CONFIG_BLK_DEV_SD=y
++# CONFIG_CHR_DEV_ST is not set
++# CONFIG_CHR_DEV_OSST is not set
++# CONFIG_BLK_DEV_SR is not set
++CONFIG_CHR_DEV_SG=y
++# CONFIG_CHR_DEV_SCH is not set
++
++#
++# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
++#
++# CONFIG_SCSI_MULTI_LUN is not set
++# CONFIG_SCSI_CONSTANTS is not set
++# CONFIG_SCSI_LOGGING is not set
++CONFIG_SCSI_SCAN_ASYNC=y
++CONFIG_SCSI_WAIT_SCAN=m
++
++#
++# SCSI Transports
++#
++# CONFIG_SCSI_SPI_ATTRS is not set
++# CONFIG_SCSI_FC_ATTRS is not set
++CONFIG_SCSI_ISCSI_ATTRS=m
++# CONFIG_SCSI_SAS_LIBSAS is not set
++# CONFIG_SCSI_SRP_ATTRS is not set
++# CONFIG_SCSI_LOWLEVEL is not set
++# CONFIG_SCSI_DH is not set
++# CONFIG_ATA is not set
++# CONFIG_MD is not set
++CONFIG_NETDEVICES=y
++# CONFIG_DUMMY is not set
++CONFIG_BONDING=m
++# CONFIG_MACVLAN is not set
++# CONFIG_EQUALIZER is not set
++CONFIG_TUN=m
++# CONFIG_VETH is not set
++# CONFIG_NET_ETHERNET is not set
++CONFIG_NETDEV_1000=y
++CONFIG_ASPEEDMAC=y
++# CONFIG_NETDEV_10000 is not set
++
++#
++# Wireless LAN
++#
++# CONFIG_WLAN_PRE80211 is not set
++# CONFIG_WLAN_80211 is not set
++# CONFIG_IWLWIFI_LEDS is not set
++
++#
++# USB Network Adapters
++#
++# CONFIG_USB_CATC is not set
++# CONFIG_USB_KAWETH is not set
++# CONFIG_USB_PEGASUS is not set
++# CONFIG_USB_RTL8150 is not set
++# CONFIG_USB_USBNET is not set
++# CONFIG_WAN is not set
++# CONFIG_PPP is not set
++# CONFIG_SLIP is not set
++# CONFIG_NETCONSOLE is not set
++# CONFIG_NETPOLL is not set
++# CONFIG_NET_POLL_CONTROLLER is not set
++# CONFIG_ISDN is not set
++
++#
++# Input device support
++#
++CONFIG_INPUT=y
++# CONFIG_INPUT_FF_MEMLESS is not set
++# CONFIG_INPUT_POLLDEV is not set
++
++#
++# Userland interfaces
++#
++CONFIG_INPUT_MOUSEDEV=y
++CONFIG_INPUT_MOUSEDEV_PSAUX=y
++CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
++CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
++# CONFIG_INPUT_JOYDEV is not set
++CONFIG_INPUT_EVDEV=y
++# CONFIG_INPUT_EVBUG is not set
++
++#
++# Input Device Drivers
++#
++CONFIG_INPUT_KEYBOARD=y
++CONFIG_KEYBOARD_ATKBD=y
++# CONFIG_KEYBOARD_SUNKBD is not set
++# CONFIG_KEYBOARD_LKKBD is not set
++# CONFIG_KEYBOARD_XTKBD is not set
++# CONFIG_KEYBOARD_NEWTON is not set
++# CONFIG_KEYBOARD_STOWAWAY is not set
++# CONFIG_KEYBOARD_GPIO is not set
++CONFIG_INPUT_MOUSE=y
++CONFIG_MOUSE_PS2=y
++CONFIG_MOUSE_PS2_ALPS=y
++CONFIG_MOUSE_PS2_LOGIPS2PP=y
++CONFIG_MOUSE_PS2_SYNAPTICS=y
++CONFIG_MOUSE_PS2_LIFEBOOK=y
++CONFIG_MOUSE_PS2_TRACKPOINT=y
++# CONFIG_MOUSE_PS2_ELANTECH is not set
++# CONFIG_MOUSE_PS2_TOUCHKIT is not set
++CONFIG_MOUSE_SERIAL=y
++# CONFIG_MOUSE_APPLETOUCH is not set
++# CONFIG_MOUSE_BCM5974 is not set
++# CONFIG_MOUSE_VSXXXAA is not set
++# CONFIG_MOUSE_GPIO is not set
++# CONFIG_INPUT_JOYSTICK is not set
++# CONFIG_INPUT_TABLET is not set
++# CONFIG_INPUT_TOUCHSCREEN is not set
++# CONFIG_INPUT_MISC is not set
++
++#
++# Hardware I/O ports
++#
++CONFIG_SERIO=y
++CONFIG_SERIO_SERPORT=y
++# CONFIG_SERIO_AMBAKMI is not set
++CONFIG_SERIO_LIBPS2=y
++# CONFIG_SERIO_RAW is not set
++# CONFIG_GAMEPORT is not set
++
++#
++# Character devices
++#
++CONFIG_VT=y
++CONFIG_CONSOLE_TRANSLATIONS=y
++CONFIG_VT_CONSOLE=y
++CONFIG_HW_CONSOLE=y
++# CONFIG_VT_HW_CONSOLE_BINDING is not set
++CONFIG_DEVKMEM=y
++CONFIG_SERIAL_NONSTANDARD=y
++# CONFIG_N_HDLC is not set
++# CONFIG_RISCOM8 is not set
++# CONFIG_SPECIALIX is not set
++# CONFIG_RIO is not set
++# CONFIG_STALDRV is not set
++
++#
++# Serial drivers
++#
++CONFIG_SERIAL_8250=y
++CONFIG_SERIAL_8250_CONSOLE=y
++CONFIG_SERIAL_8250_NR_UARTS=4
++CONFIG_SERIAL_8250_RUNTIME_UARTS=4
++# CONFIG_SERIAL_AST_DMA_UART is not set
++# CONFIG_SERIAL_8250_EXTENDED is not set
++
++#
++# Non-8250 serial port support
++#
++# CONFIG_SERIAL_AMBA_PL010 is not set
++# CONFIG_SERIAL_AMBA_PL011 is not set
++# CONFIG_SERIAL_AST is not set
++CONFIG_SERIAL_CORE=y
++CONFIG_SERIAL_CORE_CONSOLE=y
++CONFIG_UNIX98_PTYS=y
++CONFIG_LEGACY_PTYS=y
++CONFIG_LEGACY_PTY_COUNT=256
++# CONFIG_IPMI_HANDLER is not set
++CONFIG_AST_MISC=y
++# CONFIG_AST_VIDEO is not set
++# CONFIG_ADC_CAT9883 is not set
++# CONFIG_AST_SPI_BIOS is not set
++CONFIG_AST_PECI=y
++# CONFIG_AST_KCS is not set
++# CONFIG_AST_GPIO is not set
++# CONFIG_HW_RANDOM is not set
++CONFIG_NVRAM=y
++# CONFIG_R3964 is not set
++# CONFIG_RAW_DRIVER is not set
++# CONFIG_TCG_TPM is not set
++CONFIG_I2C=y
++CONFIG_I2C_BOARDINFO=y
++CONFIG_I2C_CHARDEV=y
++CONFIG_I2C_HELPER_AUTO=y
++
++#
++# I2C Hardware Bus support
++#
++
++#
++# I2C system bus drivers (mostly embedded / system-on-chip)
++#
++# CONFIG_I2C_GPIO is not set
++# CONFIG_I2C_OCORES is not set
++CONFIG_I2C_AST=y
++CONFIG_AST_I2C_SLAVE_MODE=y
++CONFIG_AST_I2C_SLAVE_EEPROM=y
++# CONFIG_AST_I2C_SLAVE_RDWR is not set
++# CONFIG_I2C_SIMTEC is not set
++
++#
++# External I2C/SMBus adapter drivers
++#
++# CONFIG_I2C_PARPORT_LIGHT is not set
++# CONFIG_I2C_TAOS_EVM is not set
++# CONFIG_I2C_TINY_USB is not set
++
++#
++# Other I2C/SMBus bus drivers
++#
++# CONFIG_I2C_PCA_PLATFORM is not set
++# CONFIG_I2C_STUB is not set
++
++#
++# Miscellaneous I2C Chip support
++#
++# CONFIG_DS1682 is not set
++CONFIG_AT24=m
++# CONFIG_SENSORS_EEPROM is not set
++CONFIG_SENSORS_PCF8574=m
++# CONFIG_PCF8575 is not set
++# CONFIG_SENSORS_PCA9539 is not set
++# CONFIG_SENSORS_PCF8591 is not set
++# CONFIG_TPS65010 is not set
++# CONFIG_SENSORS_MAX6875 is not set
++# CONFIG_SENSORS_TSL2550 is not set
++# CONFIG_I2C_DEBUG_CORE is not set
++# CONFIG_I2C_DEBUG_ALGO is not set
++# CONFIG_I2C_DEBUG_BUS is not set
++# CONFIG_I2C_DEBUG_CHIP is not set
++CONFIG_SPI=y
++CONFIG_SPI_MASTER=y
++
++#
++# SPI Master Controller Drivers
++#
++CONFIG_SPI_AST=y
++CONFIG_SPI_FMC=y
++CONFIG_SPI_BITBANG=y
++
++#
++# SPI Protocol Masters
++#
++CONFIG_SPI_AT25=m
++# CONFIG_SPI_SPIDEV is not set
++# CONFIG_SPI_TLE62X0 is not set
++CONFIG_ARCH_REQUIRE_GPIOLIB=y
++CONFIG_GPIOLIB=y
++CONFIG_GPIO_SYSFS=y
++
++#
++# Memory mapped GPIO expanders:
++#
++
++#
++# I2C GPIO expanders:
++#
++# CONFIG_GPIO_MAX732X is not set
++# CONFIG_GPIO_PCA953X is not set
++# CONFIG_GPIO_PCF857X is not set
++
++#
++# PCI GPIO expanders:
++#
++
++#
++# SPI GPIO expanders:
++#
++# CONFIG_GPIO_MAX7301 is not set
++# CONFIG_GPIO_MCP23S08 is not set
++# CONFIG_W1 is not set
++# CONFIG_POWER_SUPPLY is not set
++CONFIG_HWMON=y
++# CONFIG_HWMON_VID is not set
++# CONFIG_SENSORS_AD7414 is not set
++# CONFIG_SENSORS_AD7418 is not set
++# CONFIG_SENSORS_ADCXX is not set
++# CONFIG_SENSORS_ADM1021 is not set
++# CONFIG_SENSORS_ADM1025 is not set
++# CONFIG_SENSORS_ADM1026 is not set
++# CONFIG_SENSORS_ADM1029 is not set
++# CONFIG_SENSORS_ADM1031 is not set
++# CONFIG_SENSORS_ADM9240 is not set
++# CONFIG_SENSORS_ADT7462 is not set
++# CONFIG_SENSORS_ADT7470 is not set
++# CONFIG_SENSORS_ADT7473 is not set
++# CONFIG_SENSORS_ATXP1 is not set
++# CONFIG_SENSORS_DS1621 is not set
++# CONFIG_SENSORS_F71805F is not set
++# CONFIG_SENSORS_F71882FG is not set
++# CONFIG_SENSORS_F75375S is not set
++# CONFIG_SENSORS_GL518SM is not set
++# CONFIG_SENSORS_GL520SM is not set
++# CONFIG_SENSORS_IT87 is not set
++# CONFIG_SENSORS_LM63 is not set
++# CONFIG_SENSORS_LM70 is not set
++CONFIG_SENSORS_LM75=m
++# CONFIG_SENSORS_LM77 is not set
++# CONFIG_SENSORS_LM78 is not set
++# CONFIG_SENSORS_LM80 is not set
++# CONFIG_SENSORS_LM83 is not set
++# CONFIG_SENSORS_LM85 is not set
++# CONFIG_SENSORS_LM87 is not set
++# CONFIG_SENSORS_LM90 is not set
++# CONFIG_SENSORS_LM92 is not set
++# CONFIG_SENSORS_LM93 is not set
++CONFIG_SENSORS_MAX127=m
++# CONFIG_SENSORS_MAX1111 is not set
++# CONFIG_SENSORS_MAX1619 is not set
++# CONFIG_SENSORS_MAX6650 is not set
++# CONFIG_SENSORS_PC87360 is not set
++# CONFIG_SENSORS_PC87427 is not set
++# CONFIG_SENSORS_DME1737 is not set
++# CONFIG_SENSORS_SMSC47M1 is not set
++# CONFIG_SENSORS_SMSC47M192 is not set
++# CONFIG_SENSORS_SMSC47B397 is not set
++CONFIG_SENSORS_ADS7828=m
++# CONFIG_SENSORS_THMC50 is not set
++# CONFIG_SENSORS_VT1211 is not set
++# CONFIG_SENSORS_W83781D is not set
++# CONFIG_SENSORS_W83791D is not set
++# CONFIG_SENSORS_W83792D is not set
++# CONFIG_SENSORS_W83793 is not set
++# CONFIG_SENSORS_W83L785TS is not set
++# CONFIG_SENSORS_W83L786NG is not set
++# CONFIG_SENSORS_W83627HF is not set
++# CONFIG_SENSORS_W83627EHF is not set
++CONFIG_SENSORS_AST_ADC=y
++CONFIG_SENSORS_AST_PWM_FAN=y
++CONFIG_SENSORS_FB_PANTHER_PLUS=m
++CONFIG_PMBUS=m
++CONFIG_SENSORS_PMBUS=m
++CONFIG_SENSORS_ADM1275=m
++# CONFIG_SENSORS_LM25066 is not set
++# CONFIG_SENSORS_LTC2978 is not set
++# CONFIG_SENSORS_MAX16064 is not set
++# CONFIG_SENSORS_MAX34440 is not set
++# CONFIG_SENSORS_MAX8688 is not set
++CONFIG_SENSORS_PFE1100=m
++CONFIG_SENSORS_PFE3000=m
++# CONFIG_SENSORS_UCD9000 is not set
++# CONFIG_SENSORS_UCD9200 is not set
++# CONFIG_SENSORS_ZL6100 is not set
++# CONFIG_HWMON_DEBUG_CHIP is not set
++CONFIG_THERMAL=y
++CONFIG_THERMAL_HWMON=y
++CONFIG_WATCHDOG=y
++# CONFIG_WATCHDOG_NOWAYOUT is not set
++
++#
++# Watchdog Device Drivers
++#
++# CONFIG_SOFT_WATCHDOG is not set
++CONFIG_AST_WATCHDOG=y
++
++#
++# USB-based Watchdog Cards
++#
++# CONFIG_USBPCWATCHDOG is not set
++CONFIG_SSB_POSSIBLE=y
++
++#
++# Sonics Silicon Backplane
++#
++# CONFIG_SSB is not set
++
++#
++# Multifunction device drivers
++#
++# CONFIG_MFD_CORE is not set
++# CONFIG_MFD_SM501 is not set
++# CONFIG_MFD_ASIC3 is not set
++# CONFIG_HTC_EGPIO is not set
++# CONFIG_HTC_PASIC3 is not set
++# CONFIG_MFD_TMIO is not set
++# CONFIG_MFD_TC6393XB is not set
++# CONFIG_PMIC_DA903X is not set
++# CONFIG_MFD_WM8400 is not set
++# CONFIG_MFD_WM8350_I2C is not set
++
++#
++# Multimedia devices
++#
++
++#
++# Multimedia core support
++#
++# CONFIG_VIDEO_DEV is not set
++# CONFIG_DVB_CORE is not set
++# CONFIG_VIDEO_MEDIA is not set
++
++#
++# Multimedia drivers
++#
++# CONFIG_DAB is not set
++
++#
++# Graphics support
++#
++# CONFIG_VGASTATE is not set
++# CONFIG_VIDEO_OUTPUT_CONTROL is not set
++# CONFIG_FB is not set
++# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
++
++#
++# Display device support
++#
++# CONFIG_DISPLAY_SUPPORT is not set
++
++#
++# Console display driver support
++#
++# CONFIG_VGA_CONSOLE is not set
++CONFIG_DUMMY_CONSOLE=y
++# CONFIG_SOUND is not set
++# CONFIG_HID_SUPPORT is not set
++CONFIG_USB_SUPPORT=y
++CONFIG_USB_ARCH_HAS_HCD=y
++# CONFIG_USB_ARCH_HAS_OHCI is not set
++CONFIG_USB_ARCH_HAS_EHCI=y
++CONFIG_USB=m
++# CONFIG_USB_DEBUG is not set
++# CONFIG_USB_ANNOUNCE_NEW_DEVICES is not set
++
++#
++# Miscellaneous USB options
++#
++CONFIG_USB_DEVICEFS=y
++CONFIG_USB_DEVICE_CLASS=y
++# CONFIG_USB_DYNAMIC_MINORS is not set
++# CONFIG_USB_SUSPEND is not set
++# CONFIG_USB_OTG is not set
++# CONFIG_USB_MON is not set
++# CONFIG_USB_WUSB is not set
++# CONFIG_USB_WUSB_CBAF is not set
++
++#
++# USB Host Controller Drivers
++#
++# CONFIG_USB_C67X00_HCD is not set
++# CONFIG_USB_EHCI_HCD is not set
++# CONFIG_USB_ISP116X_HCD is not set
++# CONFIG_USB_SL811_HCD is not set
++# CONFIG_USB_R8A66597_HCD is not set
++# CONFIG_USB_HWA_HCD is not set
++
++#
++# AST USB Drivers
++#
++CONFIG_AST_USB_UHCI_HCD=y
++# CONFIG_AST_USB_UHCI_MULTIPORT_1 is not set
++# CONFIG_AST_USB_UHCI_MULTIPORT_2 is not set
++CONFIG_AST_USB_UHCI_MULTIPORT_4=y
++# CONFIG_USB_EHCI_SPLIT_ISO is not set
++
++#
++# USB Device Class drivers
++#
++# CONFIG_USB_ACM is not set
++# CONFIG_USB_PRINTER is not set
++# CONFIG_USB_WDM is not set
++# CONFIG_USB_TMC is not set
++
++#
++# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may also be needed;
++#
++
++#
++# see USB_STORAGE Help for more information
++#
++CONFIG_USB_STORAGE=m
++# CONFIG_USB_STORAGE_DEBUG is not set
++# CONFIG_USB_STORAGE_DATAFAB is not set
++# CONFIG_USB_STORAGE_FREECOM is not set
++# CONFIG_USB_STORAGE_ISD200 is not set
++# CONFIG_USB_STORAGE_DPCM is not set
++# CONFIG_USB_STORAGE_USBAT is not set
++# CONFIG_USB_STORAGE_SDDR09 is not set
++# CONFIG_USB_STORAGE_SDDR55 is not set
++# CONFIG_USB_STORAGE_JUMPSHOT is not set
++# CONFIG_USB_STORAGE_ALAUDA is not set
++# CONFIG_USB_STORAGE_ONETOUCH is not set
++# CONFIG_USB_STORAGE_KARMA is not set
++# CONFIG_USB_STORAGE_CYPRESS_ATACB is not set
++# CONFIG_USB_LIBUSUAL is not set
++
++#
++# USB Imaging devices
++#
++# CONFIG_USB_MDC800 is not set
++# CONFIG_USB_MICROTEK is not set
++
++#
++# USB port drivers
++#
++# CONFIG_USB_SERIAL is not set
++
++#
++# USB Miscellaneous drivers
++#
++# CONFIG_USB_EMI62 is not set
++# CONFIG_USB_EMI26 is not set
++# CONFIG_USB_ADUTUX is not set
++# CONFIG_USB_SEVSEG is not set
++# CONFIG_USB_RIO500 is not set
++# CONFIG_USB_LEGOTOWER is not set
++# CONFIG_USB_LCD is not set
++# CONFIG_USB_BERRY_CHARGE is not set
++# CONFIG_USB_LED is not set
++# CONFIG_USB_CYPRESS_CY7C63 is not set
++# CONFIG_USB_CYTHERM is not set
++# CONFIG_USB_PHIDGET is not set
++# CONFIG_USB_IDMOUSE is not set
++# CONFIG_USB_FTDI_ELAN is not set
++# CONFIG_USB_APPLEDISPLAY is not set
++# CONFIG_USB_LD is not set
++# CONFIG_USB_TRANCEVIBRATOR is not set
++# CONFIG_USB_IOWARRIOR is not set
++# CONFIG_USB_TEST is not set
++# CONFIG_USB_ISIGHTFW is not set
++# CONFIG_USB_VST is not set
++CONFIG_USB_GADGET=y
++# CONFIG_USB_GADGET_DEBUG_FILES is not set
++CONFIG_USB_GADGET_VBUS_DRAW=2
++CONFIG_USB_GADGET_SELECTED=y
++# CONFIG_USB_GADGET_AT91 is not set
++# CONFIG_USB_GADGET_ATMEL_USBA is not set
++# CONFIG_USB_GADGET_FSL_USB2 is not set
++# CONFIG_USB_GADGET_LH7A40X is not set
++# CONFIG_USB_GADGET_OMAP is not set
++# CONFIG_USB_GADGET_PXA25X is not set
++# CONFIG_USB_GADGET_PXA27X is not set
++# CONFIG_USB_GADGET_S3C2410 is not set
++# CONFIG_USB_GADGET_M66592 is not set
++# CONFIG_USB_GADGET_AMD5536UDC is not set
++# CONFIG_USB_GADGET_FSL_QE is not set
++# CONFIG_USB_GADGET_NET2280 is not set
++# CONFIG_USB_GADGET_GOKU is not set
++CONFIG_USB_GADGET_ASPEED_AST=y
++CONFIG_USB_ASPEED_AST=y
++# CONFIG_USB_GADGET_DUMMY_HCD is not set
++CONFIG_USB_GADGET_DUALSPEED=y
++CONFIG_USB_ZERO=m
++CONFIG_USB_ETH=m
++CONFIG_USB_ETH_RNDIS=y
++CONFIG_USB_GADGETFS=m
++CONFIG_USB_FILE_STORAGE=m
++# CONFIG_USB_FILE_STORAGE_TEST is not set
++CONFIG_USB_G_SERIAL=m
++# CONFIG_USB_MIDI_GADGET is not set
++# CONFIG_USB_G_PRINTER is not set
++CONFIG_USB_CDC_COMPOSITE=m
++# CONFIG_MMC is not set
++# CONFIG_MEMSTICK is not set
++# CONFIG_ACCESSIBILITY is not set
++# CONFIG_NEW_LEDS is not set
++CONFIG_RTC_LIB=y
++CONFIG_RTC_CLASS=y
++# CONFIG_RTC_HCTOSYS is not set
++# CONFIG_RTC_DEBUG is not set
++
++#
++# RTC interfaces
++#
++CONFIG_RTC_INTF_SYSFS=y
++CONFIG_RTC_INTF_PROC=y
++CONFIG_RTC_INTF_DEV=y
++# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set
++# CONFIG_RTC_DRV_TEST is not set
++
++#
++# I2C RTC drivers
++#
++# CONFIG_RTC_DRV_DS1307 is not set
++# CONFIG_RTC_DRV_DS1374 is not set
++# CONFIG_RTC_DRV_DS1672 is not set
++# CONFIG_RTC_DRV_MAX6900 is not set
++# CONFIG_RTC_DRV_RS5C372 is not set
++# CONFIG_RTC_DRV_ISL1208 is not set
++# CONFIG_RTC_DRV_X1205 is not set
++# CONFIG_RTC_DRV_PCF8563 is not set
++# CONFIG_RTC_DRV_PCF8583 is not set
++# CONFIG_RTC_DRV_M41T80 is not set
++# CONFIG_RTC_DRV_S35390A is not set
++# CONFIG_RTC_DRV_FM3130 is not set
++# CONFIG_RTC_DRV_RX8581 is not set
++
++#
++# SPI RTC drivers
++#
++# CONFIG_RTC_DRV_M41T94 is not set
++# CONFIG_RTC_DRV_DS1305 is not set
++# CONFIG_RTC_DRV_DS1390 is not set
++# CONFIG_RTC_DRV_MAX6902 is not set
++# CONFIG_RTC_DRV_R9701 is not set
++# CONFIG_RTC_DRV_RS5C348 is not set
++# CONFIG_RTC_DRV_DS3234 is not set
++
++#
++# Platform RTC drivers
++#
++# CONFIG_RTC_DRV_CMOS is not set
++# CONFIG_RTC_DRV_DS1286 is not set
++# CONFIG_RTC_DRV_DS1511 is not set
++# CONFIG_RTC_DRV_DS1553 is not set
++# CONFIG_RTC_DRV_DS1742 is not set
++# CONFIG_RTC_DRV_STK17TA8 is not set
++# CONFIG_RTC_DRV_M48T86 is not set
++# CONFIG_RTC_DRV_M48T35 is not set
++# CONFIG_RTC_DRV_M48T59 is not set
++# CONFIG_RTC_DRV_BQ4802 is not set
++# CONFIG_RTC_DRV_V3020 is not set
++
++#
++# on-CPU RTC drivers
++#
++# CONFIG_RTC_DRV_PL030 is not set
++# CONFIG_RTC_DRV_PL031 is not set
++CONFIG_RTC_DRV_ASPEED=y
++# CONFIG_DMADEVICES is not set
++# CONFIG_REGULATOR is not set
++# CONFIG_UIO is not set
++
++#
++# File systems
++#
++CONFIG_EXT2_FS=y
++CONFIG_EXT2_FS_XATTR=y
++CONFIG_EXT2_FS_POSIX_ACL=y
++CONFIG_EXT2_FS_SECURITY=y
++# CONFIG_EXT2_FS_XIP is not set
++# CONFIG_EXT3_FS is not set
++# CONFIG_EXT4_FS is not set
++CONFIG_FS_MBCACHE=y
++# CONFIG_REISERFS_FS is not set
++# CONFIG_JFS_FS is not set
++CONFIG_FS_POSIX_ACL=y
++CONFIG_FILE_LOCKING=y
++# CONFIG_XFS_FS is not set
++# CONFIG_OCFS2_FS is not set
++CONFIG_DNOTIFY=y
++CONFIG_INOTIFY=y
++CONFIG_INOTIFY_USER=y
++# CONFIG_QUOTA is not set
++# CONFIG_AUTOFS_FS is not set
++# CONFIG_AUTOFS4_FS is not set
++# CONFIG_FUSE_FS is not set
++CONFIG_GENERIC_ACL=y
++
++#
++# CD-ROM/DVD Filesystems
++#
++# CONFIG_ISO9660_FS is not set
++# CONFIG_UDF_FS is not set
++
++#
++# DOS/FAT/NT Filesystems
++#
++CONFIG_FAT_FS=y
++CONFIG_MSDOS_FS=y
++CONFIG_VFAT_FS=y
++CONFIG_FAT_DEFAULT_CODEPAGE=437
++CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
++CONFIG_NTFS_FS=y
++# CONFIG_NTFS_DEBUG is not set
++CONFIG_NTFS_RW=y
++
++#
++# Pseudo filesystems
++#
++CONFIG_PROC_FS=y
++CONFIG_PROC_SYSCTL=y
++CONFIG_PROC_PAGE_MONITOR=y
++CONFIG_SYSFS=y
++CONFIG_TMPFS=y
++CONFIG_TMPFS_POSIX_ACL=y
++# CONFIG_HUGETLB_PAGE is not set
++CONFIG_CONFIGFS_FS=m
++
++#
++# Miscellaneous filesystems
++#
++# CONFIG_ADFS_FS is not set
++# CONFIG_AFFS_FS is not set
++# CONFIG_HFS_FS is not set
++# CONFIG_HFSPLUS_FS is not set
++# CONFIG_BEFS_FS is not set
++# CONFIG_BFS_FS is not set
++# CONFIG_EFS_FS is not set
++CONFIG_YAFFS_FS=y
++CONFIG_YAFFS_YAFFS1=y
++# CONFIG_YAFFS_9BYTE_TAGS is not set
++# CONFIG_YAFFS_DOES_ECC is not set
++CONFIG_YAFFS_YAFFS2=y
++CONFIG_YAFFS_AUTO_YAFFS2=y
++# CONFIG_YAFFS_DISABLE_TAGS_ECC is not set
++# CONFIG_YAFFS_DISABLE_LAZY_LOAD is not set
++# CONFIG_YAFFS_DISABLE_WIDE_TNODES is not set
++# CONFIG_YAFFS_ALWAYS_CHECK_CHUNK_ERASED is not set
++CONFIG_YAFFS_SHORT_NAMES_IN_RAM=y
++# CONFIG_YAFFS_EMPTY_LOST_AND_FOUND is not set
++CONFIG_JFFS2_FS=y
++CONFIG_JFFS2_FS_DEBUG=0
++CONFIG_JFFS2_FS_WRITEBUFFER=y
++# CONFIG_JFFS2_FS_WBUF_VERIFY is not set
++# CONFIG_JFFS2_SUMMARY is not set
++# CONFIG_JFFS2_FS_XATTR is not set
++# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
++CONFIG_JFFS2_ZLIB=y
++# CONFIG_JFFS2_LZO is not set
++CONFIG_JFFS2_RTIME=y
++# CONFIG_JFFS2_RUBIN is not set
++# CONFIG_CRAMFS is not set
++# CONFIG_VXFS_FS is not set
++# CONFIG_MINIX_FS is not set
++# CONFIG_OMFS_FS is not set
++# CONFIG_HPFS_FS is not set
++# CONFIG_QNX4FS_FS is not set
++# CONFIG_ROMFS_FS is not set
++# CONFIG_SYSV_FS is not set
++# CONFIG_UFS_FS is not set
++CONFIG_NETWORK_FILESYSTEMS=y
++CONFIG_NFS_FS=y
++# CONFIG_NFS_V3 is not set
++# CONFIG_NFS_V4 is not set
++CONFIG_ROOT_NFS=y
++# CONFIG_NFSD is not set
++CONFIG_LOCKD=y
++CONFIG_NFS_COMMON=y
++CONFIG_SUNRPC=y
++# CONFIG_SUNRPC_REGISTER_V4 is not set
++# CONFIG_RPCSEC_GSS_KRB5 is not set
++# CONFIG_RPCSEC_GSS_SPKM3 is not set
++# CONFIG_SMB_FS is not set
++# CONFIG_CIFS is not set
++# CONFIG_NCP_FS is not set
++# CONFIG_CODA_FS is not set
++# CONFIG_AFS_FS is not set
++
++#
++# Partition Types
++#
++# CONFIG_PARTITION_ADVANCED is not set
++CONFIG_MSDOS_PARTITION=y
++CONFIG_NLS=y
++CONFIG_NLS_DEFAULT="utf8"
++CONFIG_NLS_CODEPAGE_437=y
++# CONFIG_NLS_CODEPAGE_737 is not set
++# CONFIG_NLS_CODEPAGE_775 is not set
++# CONFIG_NLS_CODEPAGE_850 is not set
++# CONFIG_NLS_CODEPAGE_852 is not set
++# CONFIG_NLS_CODEPAGE_855 is not set
++# CONFIG_NLS_CODEPAGE_857 is not set
++# CONFIG_NLS_CODEPAGE_860 is not set
++# CONFIG_NLS_CODEPAGE_861 is not set
++# CONFIG_NLS_CODEPAGE_862 is not set
++# CONFIG_NLS_CODEPAGE_863 is not set
++# CONFIG_NLS_CODEPAGE_864 is not set
++# CONFIG_NLS_CODEPAGE_865 is not set
++# CONFIG_NLS_CODEPAGE_866 is not set
++# CONFIG_NLS_CODEPAGE_869 is not set
++CONFIG_NLS_CODEPAGE_936=y
++CONFIG_NLS_CODEPAGE_950=y
++CONFIG_NLS_CODEPAGE_932=y
++# CONFIG_NLS_CODEPAGE_949 is not set
++# CONFIG_NLS_CODEPAGE_874 is not set
++# CONFIG_NLS_ISO8859_8 is not set
++# CONFIG_NLS_CODEPAGE_1250 is not set
++# CONFIG_NLS_CODEPAGE_1251 is not set
++CONFIG_NLS_ASCII=y
++CONFIG_NLS_ISO8859_1=y
++# CONFIG_NLS_ISO8859_2 is not set
++# CONFIG_NLS_ISO8859_3 is not set
++# CONFIG_NLS_ISO8859_4 is not set
++# CONFIG_NLS_ISO8859_5 is not set
++# CONFIG_NLS_ISO8859_6 is not set
++# CONFIG_NLS_ISO8859_7 is not set
++# CONFIG_NLS_ISO8859_9 is not set
++# CONFIG_NLS_ISO8859_13 is not set
++# CONFIG_NLS_ISO8859_14 is not set
++# CONFIG_NLS_ISO8859_15 is not set
++# CONFIG_NLS_KOI8_R is not set
++# CONFIG_NLS_KOI8_U is not set
++CONFIG_NLS_UTF8=y
++# CONFIG_DLM is not set
++
++#
++# Kernel hacking
++#
++# CONFIG_PRINTK_TIME is not set
++# CONFIG_ENABLE_WARN_DEPRECATED is not set
++CONFIG_ENABLE_MUST_CHECK=y
++CONFIG_FRAME_WARN=1024
++CONFIG_MAGIC_SYSRQ=y
++# CONFIG_UNUSED_SYMBOLS is not set
++# CONFIG_DEBUG_FS is not set
++# CONFIG_HEADERS_CHECK is not set
++# CONFIG_DEBUG_KERNEL is not set
++# CONFIG_SLUB_DEBUG_ON is not set
++# CONFIG_SLUB_STATS is not set
++CONFIG_DEBUG_BUGVERBOSE=y
++CONFIG_DEBUG_MEMORY_INIT=y
++CONFIG_FRAME_POINTER=y
++# CONFIG_RCU_CPU_STALL_DETECTOR is not set
++# CONFIG_LATENCYTOP is not set
++# CONFIG_SYSCTL_SYSCALL_CHECK is not set
++CONFIG_HAVE_FUNCTION_TRACER=y
++
++#
++# Tracers
++#
++# CONFIG_DYNAMIC_PRINTK_DEBUG is not set
++# CONFIG_SAMPLES is not set
++CONFIG_HAVE_ARCH_KGDB=y
++# CONFIG_DEBUG_USER is not set
++
++#
++# Security options
++#
++# CONFIG_KEYS is not set
++# CONFIG_SECURITY is not set
++# CONFIG_SECURITYFS is not set
++# CONFIG_SECURITY_FILE_CAPABILITIES is not set
++CONFIG_CRYPTO=y
++
++#
++# Crypto core or helper
++#
++# CONFIG_CRYPTO_FIPS is not set
++CONFIG_CRYPTO_ALGAPI=y
++CONFIG_CRYPTO_ALGAPI2=y
++CONFIG_CRYPTO_AEAD=m
++CONFIG_CRYPTO_AEAD2=y
++CONFIG_CRYPTO_BLKCIPHER=y
++CONFIG_CRYPTO_BLKCIPHER2=y
++CONFIG_CRYPTO_HASH=y
++CONFIG_CRYPTO_HASH2=y
++CONFIG_CRYPTO_RNG2=y
++CONFIG_CRYPTO_MANAGER=y
++CONFIG_CRYPTO_MANAGER2=y
++# CONFIG_CRYPTO_GF128MUL is not set
++CONFIG_CRYPTO_NULL=y
++# CONFIG_CRYPTO_CRYPTD is not set
++CONFIG_CRYPTO_AUTHENC=m
++# CONFIG_CRYPTO_TEST is not set
++
++#
++# Authenticated Encryption with Associated Data
++#
++# CONFIG_CRYPTO_CCM is not set
++# CONFIG_CRYPTO_GCM is not set
++# CONFIG_CRYPTO_SEQIV is not set
++
++#
++# Block modes
++#
++CONFIG_CRYPTO_CBC=y
++# CONFIG_CRYPTO_CTR is not set
++# CONFIG_CRYPTO_CTS is not set
++# CONFIG_CRYPTO_ECB is not set
++# CONFIG_CRYPTO_LRW is not set
++# CONFIG_CRYPTO_PCBC is not set
++# CONFIG_CRYPTO_XTS is not set
++
++#
++# Hash modes
++#
++CONFIG_CRYPTO_HMAC=y
++# CONFIG_CRYPTO_XCBC is not set
++
++#
++# Digest
++#
++# CONFIG_CRYPTO_CRC32C is not set
++# CONFIG_CRYPTO_MD4 is not set
++CONFIG_CRYPTO_MD5=y
++# CONFIG_CRYPTO_MICHAEL_MIC is not set
++# CONFIG_CRYPTO_RMD128 is not set
++# CONFIG_CRYPTO_RMD160 is not set
++# CONFIG_CRYPTO_RMD256 is not set
++# CONFIG_CRYPTO_RMD320 is not set
++CONFIG_CRYPTO_SHA1=y
++# CONFIG_CRYPTO_SHA256 is not set
++# CONFIG_CRYPTO_SHA512 is not set
++# CONFIG_CRYPTO_TGR192 is not set
++# CONFIG_CRYPTO_WP512 is not set
++
++#
++# Ciphers
++#
++# CONFIG_CRYPTO_AES is not set
++# CONFIG_CRYPTO_ANUBIS is not set
++# CONFIG_CRYPTO_ARC4 is not set
++# CONFIG_CRYPTO_BLOWFISH is not set
++# CONFIG_CRYPTO_CAMELLIA is not set
++# CONFIG_CRYPTO_CAST5 is not set
++# CONFIG_CRYPTO_CAST6 is not set
++CONFIG_CRYPTO_DES=y
++# CONFIG_CRYPTO_FCRYPT is not set
++# CONFIG_CRYPTO_KHAZAD is not set
++# CONFIG_CRYPTO_SALSA20 is not set
++# CONFIG_CRYPTO_SEED is not set
++# CONFIG_CRYPTO_SERPENT is not set
++# CONFIG_CRYPTO_TEA is not set
++# CONFIG_CRYPTO_TWOFISH is not set
++
++#
++# Compression
++#
++CONFIG_CRYPTO_DEFLATE=m
++# CONFIG_CRYPTO_LZO is not set
++
++#
++# Random Number Generation
++#
++# CONFIG_CRYPTO_ANSI_CPRNG is not set
++# CONFIG_CRYPTO_HW is not set
++
++#
++# Library routines
++#
++CONFIG_BITREVERSE=y
++# CONFIG_CRC_CCITT is not set
++# CONFIG_CRC16 is not set
++# CONFIG_CRC_T10DIF is not set
++CONFIG_CRC_ITU_T=m
++CONFIG_CRC32=y
++# CONFIG_CRC7 is not set
++# CONFIG_LIBCRC32C is not set
++CONFIG_ZLIB_INFLATE=y
++CONFIG_ZLIB_DEFLATE=y
++CONFIG_PLIST=y
++CONFIG_HAS_IOMEM=y
++CONFIG_HAS_IOPORT=y
++CONFIG_HAS_DMA=y
++
++
++# GUC USB Drivers
++#
++CONFIG_GUC_USB_UHCI_HCD=m
++# CONFIG_GUC_USB_UHCI_MULTIPORT_1 is not set
++# CONFIG_GUC_USB_UHCI_MULTIPORT_2 is not set
++CONFIG_GUC_USB_UHCI_MULTIPORT_4=y
++# CONFIG_USB_GADGET_MUSB_HDRC is not set
+diff --git a/arch/arm/kernel/head.S b/arch/arm/kernel/head.S
+index 8ff0e23..21e17dc 100644
+--- a/arch/arm/kernel/head.S
++++ b/arch/arm/kernel/head.S
+@@ -21,7 +21,6 @@
+ #include <asm/memory.h>
+ #include <asm/thread_info.h>
+ #include <asm/system.h>
+-#include <asm/mach-types.h>
+
+ #if (PHYS_OFFSET & 0x001fffff)
+ #error "PHYS_OFFSET must be at an even 2MiB boundary!"
+@@ -77,14 +76,13 @@
+ */
+ .section ".text.head", "ax"
+ ENTRY(stext)
+- ldr r5, =machine_arch_type @ find the machine type
+ msr cpsr_c, #PSR_F_BIT | PSR_I_BIT | SVC_MODE @ ensure svc mode
+ @ and irqs disabled
+ mrc p15, 0, r9, c0, c0 @ get processor id
+ bl __lookup_processor_type @ r5=procinfo r9=cpuid
+ movs r10, r5 @ invalid processor (r5=0)?
+ beq __error_p @ yes, error 'p'
+-@ bl __lookup_machine_type @ r5=machinfo
++ bl __lookup_machine_type @ r5=machinfo
+ movs r8, r5 @ invalid machine (r5=0)?
+ beq __error_a @ yes, error 'a'
+ bl __vet_atags
+diff --git a/arch/arm/mach-aspeed/include/mach/ast_wdt.h b/arch/arm/mach-aspeed/include/mach/ast_wdt.h
+index 6d7d7f47..f9125a1 100755
+--- a/arch/arm/mach-aspeed/include/mach/ast_wdt.h
++++ b/arch/arm/mach-aspeed/include/mach/ast_wdt.h
+@@ -8,4 +8,4 @@
+ * your option) any later version.
+ */
+
+- extern void ast_soc_wdt_reset(void);
++ extern void ast_wdt_reset_full(void);
+diff --git a/arch/arm/mach-aspeed/include/mach/debug-macro.S b/arch/arm/mach-aspeed/include/mach/debug-macro.S
+index 0b7c927..ff3195a 100644
+--- a/arch/arm/mach-aspeed/include/mach/debug-macro.S
++++ b/arch/arm/mach-aspeed/include/mach/debug-macro.S
+@@ -13,9 +13,8 @@
+ .macro addruart, rx, tmp
+ mrc p15, 0, \rx, c1, c0
+ tst \rx, #1 @ MMU enabled?
+- ldreq \rx, =AST_UART0_BASE
+- ldrne \rx, =IO_ADDRESS(AST_UART0_BASE)
+- orr \rx, \rx, #0x00012000
++ ldreq \rx, =AST_UART3_BASE
++ ldrne \rx, =IO_ADDRESS(AST_UART3_BASE)
+ .endm
+
+ #define UART_SHIFT 2
+diff --git a/arch/arm/mach-aspeed/include/mach/system.h b/arch/arm/mach-aspeed/include/mach/system.h
+index 96e90da..926268b 100644
+--- a/arch/arm/mach-aspeed/include/mach/system.h
++++ b/arch/arm/mach-aspeed/include/mach/system.h
+@@ -37,7 +37,7 @@ static inline void arch_reset(char mode)
+ * Use WDT to restart system
+ */
+ #if defined(CONFIG_AST_WATCHDOG) || defined(CONFIG_AST_WATCHDOG_MODULE)
+- ast_soc_wdt_reset();
++ ast_wdt_reset_full();
+ #endif
+ }
+
+diff --git a/arch/arm/mach-aspeed/include/mach/uncompress.h b/arch/arm/mach-aspeed/include/mach/uncompress.h
+index 896b854..80e560d 100644
+--- a/arch/arm/mach-aspeed/include/mach/uncompress.h
++++ b/arch/arm/mach-aspeed/include/mach/uncompress.h
+@@ -12,8 +12,8 @@
+ #include <mach/platform.h>
+ #include <mach/aspeed_serial.h>
+
+-#define UART_PUT_CHAR (*(volatile unsigned char *)(AST_UART0_BASE + UART_THR))
+-#define UART_GET_LSR (*(volatile unsigned char *)(AST_UART0_BASE + UART_LSR))
++#define UART_PUT_CHAR (*(volatile unsigned char *)(AST_UART3_BASE + UART_THR))
++#define UART_GET_LSR (*(volatile unsigned char *)(AST_UART3_BASE + UART_LSR))
+
+ static void putc(int c)
+ {
+diff --git a/arch/arm/mach-aspeed/include/mach/vmalloc.h b/arch/arm/mach-aspeed/include/mach/vmalloc.h
+index 3706cf1..51912ae 100644
+--- a/arch/arm/mach-aspeed/include/mach/vmalloc.h
++++ b/arch/arm/mach-aspeed/include/mach/vmalloc.h
+@@ -23,7 +23,7 @@
+ #define VMALLOC_OFFSET (8*1024*1024)
+ #define VMALLOC_START (((unsigned long)high_memory + VMALLOC_OFFSET) & ~(VMALLOC_OFFSET-1))
+ #define VMALLOC_VMADDR(x) ((unsigned long)(x))
+-#define VMALLOC_END (PAGE_OFFSET + 0x10000000)
++#define VMALLOC_END (PAGE_OFFSET + 0x20000000)
+ #else
+ #define VMALLOC_END 0xf8000000UL
+ #endif
+\ No newline at end of file
+diff --git a/arch/arm/plat-aspeed/Makefile b/arch/arm/plat-aspeed/Makefile
+index faba830..b63191c 100644
+--- a/arch/arm/plat-aspeed/Makefile
++++ b/arch/arm/plat-aspeed/Makefile
+@@ -18,7 +18,7 @@ obj-y += dev-uart.o dev-vuart.o dev-wdt.o dev-rtc.o dev-gpio.o dev-sgpio.o
+ obj-y += dev-nor.o dev-nand.o dev-sdhci.o
+
+ #bus
+-obj-y += dev-i2c.o dev-spi.o dev-ehci.o dev-uhci.o dev-lpc.o dev-peci.o dev-kcs.o dev-mbx.o dev-snoop.o
++obj-y += dev-i2c.o dev-spi.o dev-ehci.o dev-uhci.o dev-lpc.o dev-peci.o dev-kcs.o dev-mbx.o dev-snoop.o dev-lpc.o
+
+ #dev
+ #obj-y += dev-udc11.o
+@@ -33,3 +33,6 @@ obj-y += dev-fb.o dev-video.o
+ #obj-m :=
+ #obj-n :=
+ #obj- :=
++
++#usbdevicegadgetthing
++obj-y += dev-virthub.o
+diff --git a/arch/arm/plat-aspeed/ast-scu.c b/arch/arm/plat-aspeed/ast-scu.c
+index 1f1dde2..76722f4 100644
+--- a/arch/arm/plat-aspeed/ast-scu.c
++++ b/arch/arm/plat-aspeed/ast-scu.c
+@@ -251,6 +251,15 @@ ast_scu_init_usb20(void)
+
+ }
+
++extern void
++ast_scu_init_vhub(void) {
++ //start USB20 clock
++ ast_scu_write(ast_scu_read(AST_SCU_CLK_STOP) | SCU_USB20_CLK_EN, AST_SCU_CLK_STOP);
++ mdelay(10);
++ //disable USB20 reset
++ ast_scu_write(ast_scu_read(AST_SCU_RESET) & ~SCU_RESET_USB20, AST_SCU_RESET);
++}
++
+ EXPORT_SYMBOL(ast_scu_init_usb20);
+
+ extern void
+@@ -739,7 +748,7 @@ ast_scu_multi_func_uart(u8 uart)
+ {
+ switch(uart) {
+ case 1:
+- ast_scu_write(ast_scu_read(AST_SCU_FUN_PIN_CTRL1) |
++ ast_scu_write(ast_scu_read(AST_SCU_FUN_PIN_CTRL2) |
+ SCU_FUN_PIN_UART1_RXD |
+ SCU_FUN_PIN_UART1_TXD |
+ SCU_FUN_PIN_UART1_NRTS |
+@@ -748,10 +757,10 @@ ast_scu_multi_func_uart(u8 uart)
+ SCU_FUN_PIN_UART1_NDSR |
+ SCU_FUN_PIN_UART1_NDCD |
+ SCU_FUN_PIN_UART1_NCTS,
+- AST_SCU_FUN_PIN_CTRL1);
++ AST_SCU_FUN_PIN_CTRL2);
+ break;
+ case 2:
+- ast_scu_write(ast_scu_read(AST_SCU_FUN_PIN_CTRL1) |
++ ast_scu_write(ast_scu_read(AST_SCU_FUN_PIN_CTRL2) |
+ SCU_FUN_PIN_UART2_RXD |
+ SCU_FUN_PIN_UART2_TXD |
+ SCU_FUN_PIN_UART2_NRTS |
+@@ -760,7 +769,7 @@ ast_scu_multi_func_uart(u8 uart)
+ SCU_FUN_PIN_UART2_NDSR |
+ SCU_FUN_PIN_UART2_NDCD |
+ SCU_FUN_PIN_UART2_NCTS,
+- AST_SCU_FUN_PIN_CTRL1);
++ AST_SCU_FUN_PIN_CTRL2);
+ break;
+ case 3:
+ ast_scu_write(ast_scu_read(AST_SCU_FUN_PIN_CTRL1) |
+diff --git a/arch/arm/plat-aspeed/dev-i2c.c b/arch/arm/plat-aspeed/dev-i2c.c
+index 47cd152..9905390 100644
+--- a/arch/arm/plat-aspeed/dev-i2c.c
++++ b/arch/arm/plat-aspeed/dev-i2c.c
+@@ -46,7 +46,8 @@
+
+ #if defined (CONFIG_ARCH_AST2400)
+ #define I2C_PAGE_SIZE 8
+-struct buf_page page_info[I2C_PAGE_SIZE] =
++static spinlock_t page_info_lock = SPIN_LOCK_UNLOCKED;
++static struct buf_page page_info[I2C_PAGE_SIZE] =
+ {
+ [0] = {
+ .flag = 0,
+@@ -117,9 +118,10 @@ static void pool_buff_page_init(u32 buf_pool_addr)
+ static u8 request_pool_buff_page(struct buf_page **req_page)
+ {
+ int i;
++ unsigned long flags;
+ //TODO
+- spinlock_t lock;
+- spin_lock(&lock);
++
++ spin_lock_irqsave(&page_info_lock, flags);
+ for(i=0;i<I2C_PAGE_SIZE;i++) {
+ if(page_info[i].flag ==0) {
+ page_info[i].flag = 1;
+@@ -128,21 +130,26 @@ static u8 request_pool_buff_page(struct buf_page **req_page)
+ break;
+ }
+ }
+- spin_unlock(&lock);
+- return 0;
++ spin_unlock_irqrestore(&page_info_lock, flags);
++ return (i >= I2C_PAGE_SIZE);
+ }
+
+ static void free_pool_buff_page(struct buf_page *req_page)
+ {
++ unsigned long flags;
++ spin_lock_irqsave(&page_info_lock, flags);
++
+ req_page->flag = 0;
+ // I2CDBUG( "free page addr %x \n", req_page->page_addr);
+ req_page = NULL;
++ spin_unlock_irqrestore(&page_info_lock, flags);
+ }
+
+ #elif defined (CONFIG_ARCH_AST2300)
+ #define I2C_PAGE_SIZE 5
+
+-struct buf_page page_info[I2C_PAGE_SIZE] =
++static spinlock_t page_info_lock = SPIN_LOCK_UNLOCKED;
++static struct buf_page page_info[I2C_PAGE_SIZE] =
+ {
+ [0] = {
+ .flag = 0,
+@@ -186,27 +193,31 @@ static void pool_buff_page_init(u32 buf_pool_addr)
+ static u8 request_pool_buff_page(struct buf_page **req_page)
+ {
+ int i;
++ unsigned long flags;
+ //TODO
+- spinlock_t lock;
+- spin_lock(&lock);
++
++ spin_lock_irqsave(&page_info_lock, flags);
+ for(i=0;i<I2C_PAGE_SIZE;i++) {
+ if(page_info[i].flag ==0) {
+ page_info[i].flag = 1;
+ *req_page = &page_info[i];
+- spin_unlock(&lock);
+- return 1;
++ spin_unlock_irqrestore(&page_info_lock, flags);
++ return 0;
+ }
+ }
+- spin_unlock(&lock);
+- return 0;
++ spin_unlock_irqrestore(&page_info_lock, flags);
++ return 1;
+
+ }
+
+ //TODO check free ?
+ static void free_pool_buff_page(struct buf_page *req_page)
+ {
++ unsigned long flags;
++ spin_lock_irqsave(&page_info_lock, flags);
+ req_page->flag = 0;
+ req_page = NULL;
++ spin_unlock_irqrestore(&page_info_lock, flags);
+ }
+
+ #else
+@@ -592,19 +603,148 @@ static struct i2c_board_info __initdata ast_i2c_board_info_1[] = {
+ }
+ };
+
++
++//Under I2C Dev 2
++static struct i2c_board_info __initdata ast_i2c_board_info_2[] = {
++ // Looks like ncp4200 i2c address could be floating depending
++ // on the system. List all possibilities here (0x60 - 0x63).
++ // Hope the address will not change after probing.
++ {
++ I2C_BOARD_INFO("ncp4200", 0x60),
++ },
++ {
++ I2C_BOARD_INFO("ncp4200", 0x61),
++ },
++ {
++ I2C_BOARD_INFO("ncp4200", 0x62),
++ },
++ {
++ I2C_BOARD_INFO("ncp4200", 0x63),
++ },
++};
++
++
++//Under I2C Dev 3
++static struct i2c_board_info __initdata ast_i2c_board_info_3[] = {
++ // Looks like ncp4200 i2c address could be floating depending
++ // on the system. List all possibilities here (0x60 - 0x63)
++ // Hope the address will not change after probing.
++ {
++ I2C_BOARD_INFO("ncp4200", 0x60),
++ },
++ {
++ I2C_BOARD_INFO("ncp4200", 0x61),
++ },
++ {
++ I2C_BOARD_INFO("ncp4200", 0x62),
++ },
++ {
++ I2C_BOARD_INFO("ncp4200", 0x63),
++ },
++};
++
++
+ //Under I2C Dev 4
+ static struct i2c_board_info __initdata ast_i2c_board_info_4[] = {
++ // Temperature sensors on Wedge:
++ {
++ I2C_BOARD_INFO("tmp75", 0x48),
++ },
++ {
++ I2C_BOARD_INFO("tmp75", 0x49),
++ },
+ {
+- I2C_BOARD_INFO("24c128", 0x50),
++ I2C_BOARD_INFO("tmp75", 0x4a),
++ },
++};
+
++//Under I2C Dev 5
++static struct i2c_board_info __initdata ast_i2c_board_info_5[] = {
++ /* Panther+ microserver */
++ {
++ I2C_BOARD_INFO("fb_panther_plus", 0x40),
++ },
++ // Temperature sensor on uServer:
++ {
++ I2C_BOARD_INFO("tmp75", 0x4c),
++ },
++ {
++ I2C_BOARD_INFO("ads7828", 0x4b),
++ },
++ {
++ I2C_BOARD_INFO("24c128", 0x51),
++ },
++};
+
++//Under I2C Dev 7
++static struct i2c_board_info __initdata ast_i2c_board_info_7[] = {
++ // Wedge devices
++ {
++ I2C_BOARD_INFO("max127", 0x28),
++ },
++ {
++ // Differs from the schematic, but appears to be correct
++ I2C_BOARD_INFO("pcf8574", 0x3f),
++ },
++ {
++ I2C_BOARD_INFO("24c64", 0x50),
+ }
+ };
++
++
+ //Under I2C Dev 8
+ static struct i2c_board_info __initdata ast_i2c_board_info_8[] = {
+ {
++ // Eval board:
+ I2C_BOARD_INFO("lm75b", 0x4a),
+- }
++ },
++ // EEPROMS on the pfe1100 power supplies
++ {
++ I2C_BOARD_INFO("24c64", 0x51),
++ },
++ {
++ I2C_BOARD_INFO("24c64", 0x52),
++ },
++ {
++ I2C_BOARD_INFO("pfe1100", 0x59),
++ },
++ {
++ I2C_BOARD_INFO("pfe1100", 0x5a),
++ },
++};
++
++
++//Under I2C Dev 9
++static struct i2c_board_info __initdata ast_i2c_board_info_9[] = {
++ // Looks like ncp4200 i2c address could be floating depending
++ // on the system. List all possibilities here (0x60 - 0x63)
++ // Hope the address will not change after probing.
++ {
++ I2C_BOARD_INFO("ncp4200", 0x60),
++ },
++ {
++ I2C_BOARD_INFO("ncp4200", 0x61),
++ },
++ {
++ I2C_BOARD_INFO("ncp4200", 0x62),
++ },
++ {
++ I2C_BOARD_INFO("ncp4200", 0x63),
++ },
++};
++
++//Under I2C Dev 12
++static struct i2c_board_info __initdata ast_i2c_board_info_12[] = {
++ {
++ I2C_BOARD_INFO("pfe3000", 0x10),
++ },
++};
++
++//Under I2C Dev 13
++static struct i2c_board_info __initdata ast_i2c_board_info_13[] = {
++ {
++ I2C_BOARD_INFO("adm1278", 0x10),
++ },
+ };
+
+ #endif
+@@ -642,25 +782,36 @@ void __init ast_add_device_i2c(void)
+ platform_device_register(&ast_i2c_dev1_device);
+ i2c_register_board_info(0, ast_i2c_board_info_1, ARRAY_SIZE(ast_i2c_board_info_1));
+ platform_device_register(&ast_i2c_dev2_device);
++ i2c_register_board_info(1, ast_i2c_board_info_2, ARRAY_SIZE(ast_i2c_board_info_2));
+ platform_device_register(&ast_i2c_dev3_device);
++ i2c_register_board_info(2, ast_i2c_board_info_3, ARRAY_SIZE(ast_i2c_board_info_3));
+ platform_device_register(&ast_i2c_dev4_device);
+ i2c_register_board_info(3, ast_i2c_board_info_4, ARRAY_SIZE(ast_i2c_board_info_4));
+ platform_device_register(&ast_i2c_dev5_device);
++ i2c_register_board_info(4, ast_i2c_board_info_5, ARRAY_SIZE(ast_i2c_board_info_5));
+ platform_device_register(&ast_i2c_dev6_device);
+ platform_device_register(&ast_i2c_dev7_device);
++ i2c_register_board_info(6, ast_i2c_board_info_7, ARRAY_SIZE(ast_i2c_board_info_7));
+ platform_device_register(&ast_i2c_dev8_device);
+ i2c_register_board_info(7, ast_i2c_board_info_8, ARRAY_SIZE(ast_i2c_board_info_8));
+ platform_device_register(&ast_i2c_dev9_device);
++ i2c_register_board_info(8, ast_i2c_board_info_9, ARRAY_SIZE(ast_i2c_board_info_9));
+
+ #if defined(CONFIG_ARCH_AST2400)
+ platform_device_register(&ast_i2c_dev10_device);
+ #if defined(CONFIG_MMC_AST)
+ //Due to share pin with SD
+ #else
+- platform_device_register(&ast_i2c_dev11_device);
++ /*
++ * On Wedge, bus 13 is used as i2c bus. Bus 12 is used on other
++ * hardware. Pins for bus 11, 12, and 14 are used as GPIOs, on
++ * various hardware, but enabling the i2c bus does not seem to
++ * interfere with the GPIOs.
++ */
+ platform_device_register(&ast_i2c_dev12_device);
++ i2c_register_board_info(11, ast_i2c_board_info_12, ARRAY_SIZE(ast_i2c_board_info_12));
+ platform_device_register(&ast_i2c_dev13_device);
+- platform_device_register(&ast_i2c_dev14_device);
++ i2c_register_board_info(12, ast_i2c_board_info_13, ARRAY_SIZE(ast_i2c_board_info_13));
+ #endif
+ #endif
+ }
+diff --git a/arch/arm/plat-aspeed/dev-lpc.c b/arch/arm/plat-aspeed/dev-lpc.c
+index 50eb4e6..945e320 100644
+--- a/arch/arm/plat-aspeed/dev-lpc.c
++++ b/arch/arm/plat-aspeed/dev-lpc.c
+@@ -25,22 +25,14 @@
+ #include <linux/string.h>
+ #include <linux/platform_device.h>
+
++#include <asm/io.h>
+ #include <mach/irqs.h>
+ #include <mach/platform.h>
+ #include <plat/devs.h>
+ #include <plat/ast-scu.h>
++#include <plat/regs-lpc.h>
+
+-
+-
+-#include <linux/kernel.h>
+-#include <linux/string.h>
+-#include <linux/platform_device.h>
+-
+-#include <mach/irqs.h>
+-#include <mach/platform.h>
+-#include <plat/devs.h>
+-#include <plat/ast-scu.h>
+-
++static u32 ast_lpc_base = IO_ADDRESS(AST_LPC_BASE);
+
+ /* --------------------------------------------------------------------
+ * LPC
+@@ -100,6 +92,12 @@ void __init ast_add_device_lpc(void)
+ platform_device_register(&ast_lpc_plus_device);
+ }
+ #else
+-void __init ast_add_device_lpc(void) {}
++void __init ast_add_device_lpc(void) {
++ // Since we disable LPC, bring the UART1 and UART2 out from LPC control
++ writel((readl(ast_lpc_base + AST_LPC_HICR9)
++ & ~(LPC_HICR9_SOURCE_UART1|LPC_HICR9_SOURCE_UART2
++ |LPC_HICR9_SOURCE_UART3|LPC_HICR9_SOURCE_UART4)),
++ ast_lpc_base + AST_LPC_HICR9);
++}
+ #endif
+
+diff --git a/arch/arm/plat-aspeed/dev-pwm-fan.c b/arch/arm/plat-aspeed/dev-pwm-fan.c
+index 85570bb..c667194 100644
+--- a/arch/arm/plat-aspeed/dev-pwm-fan.c
++++ b/arch/arm/plat-aspeed/dev-pwm-fan.c
+@@ -65,14 +65,6 @@ struct platform_device ast_pwm_fan_device = {
+
+ void __init ast_add_device_pwm_fan(void)
+ {
+- //SCU Initial
+-
+- //SCU Pin-MUX //PWM & TACHO
+- ast_scu_multi_func_pwm_tacho();
+-
+- //SCU PWM CTRL Reset
+- ast_scu_init_pwm_tacho();
+-
+ platform_device_register(&ast_pwm_fan_device);
+ }
+ #else
+diff --git a/arch/arm/plat-aspeed/dev-rtc.c b/arch/arm/plat-aspeed/dev-rtc.c
+index 214aa68..a8d9b2f 100644
+--- a/arch/arm/plat-aspeed/dev-rtc.c
++++ b/arch/arm/plat-aspeed/dev-rtc.c
+@@ -33,7 +33,7 @@
+ * Watchdog
+ * -------------------------------------------------------------------- */
+
+-#if defined(CONFIG_RTC_DRV_AST) || defined(CONFIG_RTC_DRV_AST_MODULE)
++#if defined(CONFIG_RTC_DRV_ASPEED) || defined(CONFIG_RTC_DRV_ASPEED_MODULE)
+
+ static struct resource ast_rtc_resource[] = {
+ [0] = {
+diff --git a/arch/arm/plat-aspeed/dev-spi.c b/arch/arm/plat-aspeed/dev-spi.c
+index 7ddd2e4..e22c49e 100644
+--- a/arch/arm/plat-aspeed/dev-spi.c
++++ b/arch/arm/plat-aspeed/dev-spi.c
+@@ -210,8 +210,8 @@ static struct ast_spi_driver_data ast_spi0_data = {
+
+ static struct resource ast_spi_resource0[] = {
+ {
+- .start = AST_SPI0_BASE,
+- .end = AST_SPI0_BASE + SZ_16,
++ .start = AST_SPI_BASE,
++ .end = AST_SPI_BASE + SZ_16,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+@@ -299,21 +299,21 @@ static struct mtd_partition ast_spi_flash_partitions[] = {
+ static struct mtd_partition ast_spi_flash_partitions[] = {
+ {
+ .name = "u-boot",
+- .offset = 0,
+- .size = 0x80000,
++ .offset = 0, /* From 0 */
++ .size = 0x60000, /* Size 384K */
+ .mask_flags = MTD_WRITEABLE,
++ }, {
++ .name = "env",
++ .offset = 0x60000, /* From 384K */
++ .size = 0x20000, /* Size 128K, two sectors */
+ }, {
+- .name = "kernel",
+- .offset = 0x80000,
+- .size = 0x200000,
++ .name = "kernel",
++ .offset = 0x80000, /* From 512K */
++ .size = 0x200000, /* Size 2M */
+ }, {
+- .name = "rootfs",
+- .offset = 0x300000,
+- .size = 0x4F0000,
+- }, {
+- .name = "env",
+- .offset = 0x7f0000,
+- .size = 0x10000,
++ .name = "rootfs",
++ .offset = 0x300000, /* From 3M */
++ .size = 0xC00000, /* Size 12M */
+ }, {
+ .name = "data0",
+ .offset = MTDPART_OFS_APPEND,
+@@ -334,7 +334,34 @@ static struct flash_platform_data ast_spi_flash_data = {
+ .parts = ast_spi_flash_partitions,
+ };
+
++#ifdef CONFIG_ARCH_AST2400
++static struct flash_platform_data wedge_spi_flash_data = {
++ .type = "n25q128a13",
++ .nr_parts = ARRAY_SIZE(ast_spi_flash_partitions),
++ .parts = ast_spi_flash_partitions,
++};
++#endif
++
++
++/* Device info for the flash on ast-spi */
++#ifdef CONFIG_ARCH_AST2400
++static struct mtd_partition ast_spi5_flash_partitions[] = {
++ {
++ .name = "led-fpga",
++ .offset = 0, /* From 0 */
++ .size = MTDPART_SIZ_FULL,
++ },
++};
++
++static struct flash_platform_data wedge_spi5_flash_data = {
++ .type = "at45db011d",
++ .nr_parts = ARRAY_SIZE(ast_spi5_flash_partitions),
++ .parts = ast_spi5_flash_partitions,
++};
++#endif
++
+ static struct spi_board_info ast_spi_devices[] = {
++#if 0
+ {
+ .modalias = "m25p80",
+ .platform_data = &ast_spi_flash_data,
+@@ -343,6 +370,25 @@ static struct spi_board_info ast_spi_devices[] = {
+ .bus_num = 0, // This chooses if SPI0 or SPI1 of the SoC is used.
+ .mode = SPI_MODE_0,
+ },
++#endif
++#ifdef CONFIG_ARCH_AST2400
++ {
++ .modalias = "mtd_dataflash",
++ .platform_data = &wedge_spi5_flash_data,
++ .chip_select = 0,
++ .max_speed_hz = 33 * 1000 * 1000,
++ .bus_num = 5,
++ .mode = SPI_MODE_0,
++ },
++ {
++ .modalias = "m25p80",
++ .platform_data = &wedge_spi_flash_data,
++ .chip_select = 0, //.chip_select This tells your device driver which chipselect to use.
++ .max_speed_hz = 50 * 1000 * 1000,
++ .bus_num = 0, // This chooses if SPI0 or SPI1 of the SoC is used.
++ .mode = SPI_MODE_0,
++ },
++#endif
+ {
+ .modalias = "spidev",
+ .chip_select = 0,
+diff --git a/arch/arm/plat-aspeed/dev-uart.c b/arch/arm/plat-aspeed/dev-uart.c
+index 592ef4f..0b7b614 100644
+--- a/arch/arm/plat-aspeed/dev-uart.c
++++ b/arch/arm/plat-aspeed/dev-uart.c
+@@ -98,6 +98,17 @@ static struct plat_serial8250_port ast_uart_data[] = {
+ },
+ #endif
+ #endif
++#ifdef AST_UART1_BASE
++ {
++ .mapbase = AST_UART1_BASE,
++ .membase = (char*)(IO_ADDRESS(AST_UART1_BASE)),
++ .irq = IRQ_UART1,
++ .uartclk = (24*1000000L),
++ .regshift = 2,
++ .iotype = UPIO_MEM,
++ .flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST,
++ },
++#endif
+ #ifdef AST_UART3_BASE
+ {
+ .mapbase = AST_UART3_BASE,
+@@ -134,6 +145,7 @@ void __init ast_add_device_uart(void)
+ {
+ #if defined(CONFIG_ARCH_AST1010)
+ #else
++ ast_scu_multi_func_uart(1);
+ ast_scu_multi_func_uart(3);
+ ast_scu_multi_func_uart(4);
+ #endif
+diff --git a/arch/arm/plat-aspeed/dev-virthub.c b/arch/arm/plat-aspeed/dev-virthub.c
+new file mode 100644
+index 0000000..34a5ae1
+--- /dev/null
++++ b/arch/arm/plat-aspeed/dev-virthub.c
+@@ -0,0 +1,62 @@
++/*
++ * dev-virthub
++ *
++ * Copyright 2014-present Facebook. All Rights Reserved.
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
++ */
++
++#include <linux/kernel.h>
++#include <linux/string.h>
++#include <linux/platform_device.h>
++
++#include <mach/irqs.h>
++#include <mach/platform.h>
++#include <plat/devs.h>
++#include <plat/ast-scu.h>
++
++static struct resource ast_virthub_resource[] = {
++ [0] = {
++ .start = AST_USB20_BASE,
++ .end = AST_USB20_BASE + SZ_1K,
++ .flags = IORESOURCE_MEM,
++ },
++ [1] = {
++ .start = IRQ_USB20_HUB,
++ .end = IRQ_USB20_HUB,
++ .flags = IORESOURCE_IRQ,
++ },
++};
++
++static u64 ast_virthub_dma_mask = 0xfffffff8UL;
++
++static struct platform_device ast_virthub_device = {
++ .name = "aspeed_udc",
++ .id = 0,
++ .dev = {
++ .dma_mask = &ast_virthub_dma_mask,
++ .coherent_dma_mask = 0xffffffff,
++ },
++ .resource = ast_virthub_resource,
++ .num_resources = ARRAY_SIZE(ast_virthub_resource),
++};
++
++void __init ast_add_device_virthub(void)
++{
++ ast_scu_multi_func_usb20_host_hub(0);
++ ast_scu_init_vhub();
++ printk("virtual hub inited?\n");
++ platform_device_register(&ast_virthub_device);
++}
+diff --git a/arch/arm/plat-aspeed/devs.c b/arch/arm/plat-aspeed/devs.c
+index 7906b9c..be6d7f4 100644
+--- a/arch/arm/plat-aspeed/devs.c
++++ b/arch/arm/plat-aspeed/devs.c
+@@ -31,13 +31,14 @@
+ typedef void (init_fnc_t) (void);
+
+ init_fnc_t __initdata *init_all_device[] = {
++ ast_add_device_lpc,
+ ast_add_device_uart,
+ ast_add_device_vuart,
+ ast_add_device_watchdog,
+ ast_add_device_rtc,
+ ast_add_device_i2c,
+ ast_add_device_spi,
+- ast_add_device_ehci,
++//ast_add_device_ehci, disabled by tfang for USB HUB mode
+ ast_add_device_nand,
+ ast_add_device_flash,
+ ast_add_device_pwm_fan,
+@@ -46,13 +47,14 @@ init_fnc_t __initdata *init_all_device[] = {
+ ast_add_device_sgpio,
+ ast_add_device_peci,
+ ast_add_device_fb,
+- ast_add_device_sdhci,
+- ast_add_device_uhci,
+- ast_add_device_video,
++// ast_add_device_sdhci, disabled by tfang
++// ast_add_device_uhci, disabled by tfang
++// ast_add_device_video, disabled by tfang
+ ast_add_device_kcs,
+ ast_add_device_mailbox,
+ ast_add_device_snoop,
+ ast_add_device_gmac,
++ ast_add_device_virthub,
+ // ast_add_device_nand,
+ NULL,
+ };
+diff --git a/arch/arm/plat-aspeed/include/plat/ast-scu.h b/arch/arm/plat-aspeed/include/plat/ast-scu.h
+index 77169ee..14a437f 100644
+--- a/arch/arm/plat-aspeed/include/plat/ast-scu.h
++++ b/arch/arm/plat-aspeed/include/plat/ast-scu.h
+@@ -49,6 +49,7 @@ extern void ast_scu_init_lpc(void);
+ extern u8 ast_scu_get_lpc_plus_enable(void);
+ extern void ast_scu_init_udc11(void);
+ extern void ast_scu_init_usb20(void);
++extern void ast_scu_init_vhub(void);
+ extern void ast_scu_init_uhci(void);
+ extern void ast_scu_init_sdhci(void);
+ extern void ast_scu_init_i2c(void);
+diff --git a/arch/arm/plat-aspeed/include/plat/devs.h b/arch/arm/plat-aspeed/include/plat/devs.h
+index 41cbea9..8653e95 100644
+--- a/arch/arm/plat-aspeed/include/plat/devs.h
++++ b/arch/arm/plat-aspeed/include/plat/devs.h
+@@ -41,6 +41,8 @@ extern void __init ast_add_device_uhci(void);
+ extern void __init ast_add_device_gmac(void);
+ extern void __init ast_add_device_udc11(void);
+ extern void __init ast_add_device_hid(void);
++extern void __init ast_add_device_lpc(void);
++extern void __init ast_add_device_virthub(void);
+
+ extern void __init ast_add_device_pcie(void);
+
+diff --git a/arch/arm/plat-aspeed/include/plat/regs-lpc.h b/arch/arm/plat-aspeed/include/plat/regs-lpc.h
+index f4523d7..92c5130 100644
+--- a/arch/arm/plat-aspeed/include/plat/regs-lpc.h
++++ b/arch/arm/plat-aspeed/include/plat/regs-lpc.h
+@@ -186,6 +186,12 @@
+ #define GET_LPC_SNPD1(x) ((x >> 7) & 0xff)
+ #define GET_LPC_SNPD0(x) (x & 0xff)
+
++/* AST_LPC_HICR9 0x098 - LPC Host Interface Control Register 9 */
++#define LPC_HICR9_SOURCE_UART1 (1 << 4)
++#define LPC_HICR9_SOURCE_UART2 (1 << 5)
++#define LPC_HICR9_SOURCE_UART3 (1 << 6)
++#define LPC_HICR9_SOURCE_UART4 (1 << 7)
++
+ /*AST_LPC_PCCR0 0x130 - Post Code Contol Register 0 */
+ #define LPC_POST_DMA_INT_EN (1 << 31)
+ #define LPC_POST_DMA_MODE_EN (1 << 14)
+diff --git a/arch/arm/plat-aspeed/include/plat/regs-pwm_fan.h b/arch/arm/plat-aspeed/include/plat/regs-pwm_fan.h
+index 23d5b77..f1c474c 100644
+--- a/arch/arm/plat-aspeed/include/plat/regs-pwm_fan.h
++++ b/arch/arm/plat-aspeed/include/plat/regs-pwm_fan.h
+@@ -90,14 +90,14 @@
+
+ #define AST_PTCR_CTRL_FAN_NUM_EN(x) (0x1 << (16+x))
+
+-#define AST_PTCR_CTRL_PMWD (11)
+-#define AST_PTCR_CTRL_PMWD_EN (0x1 << 11)
+-#define AST_PTCR_CTRL_PMWC (10)
+-#define AST_PTCR_CTRL_PMWC_EN (0x1 << 10)
+-#define AST_PTCR_CTRL_PMWB (9)
+-#define AST_PTCR_CTRL_PMWB_EN (0x1 << 9)
+-#define AST_PTCR_CTRL_PMWA (8)
+-#define AST_PTCR_CTRL_PMWA_EN (0x1 << 8)
++#define AST_PTCR_CTRL_PWMD (11)
++#define AST_PTCR_CTRL_PWMD_EN (0x1 << 11)
++#define AST_PTCR_CTRL_PWMC (10)
++#define AST_PTCR_CTRL_PWMC_EN (0x1 << 10)
++#define AST_PTCR_CTRL_PWMB (9)
++#define AST_PTCR_CTRL_PWMB_EN (0x1 << 9)
++#define AST_PTCR_CTRL_PWMA (8)
++#define AST_PTCR_CTRL_PWMA_EN (0x1 << 8)
+
+ #define AST_PTCR_CTRL_CLK_MCLK 0x2 //0:24Mhz, 1:MCLK
+ #define AST_PTCR_CTRL_CLK_EN 0x1
+@@ -209,14 +209,14 @@
+ #define AST_PTCR_CTRL_GET_PWME_TYPE(x) (((x&(0x1<<4))>>3) | ((x&(0x1<<12))>>12))
+ #define AST_PTCR_CTRL_SET_PWME_TYPE_MASK ((0x1<<4) | (0x1<<12))
+
+-#define AST_PTCR_CTRL_PMWH (11)
+-#define AST_PTCR_CTRL_PMWH_EN (0x1 << 11)
+-#define AST_PTCR_CTRL_PMWG (10)
+-#define AST_PTCR_CTRL_PMWG_EN (0x1 << 10)
+-#define AST_PTCR_CTRL_PMWF (9)
+-#define AST_PTCR_CTRL_PMWF_EN (0x1 << 9)
+-#define AST_PTCR_CTRL_PMWE (8)
+-#define AST_PTCR_CTRL_PMWE_EN (0x1 << 8)
++#define AST_PTCR_CTRL_PWMH (11)
++#define AST_PTCR_CTRL_PWMH_EN (0x1 << 11)
++#define AST_PTCR_CTRL_PWMG (10)
++#define AST_PTCR_CTRL_PWMG_EN (0x1 << 10)
++#define AST_PTCR_CTRL_PWMF (9)
++#define AST_PTCR_CTRL_PWMF_EN (0x1 << 9)
++#define AST_PTCR_CTRL_PWME (8)
++#define AST_PTCR_CTRL_PWME_EN (0x1 << 8)
+
+ // AST_PTCR_CLK_EXT_CTRL : 0x44 - Clock Control Extension #1
+ //TYPE O
+diff --git a/arch/arm/plat-aspeed/timer.c b/arch/arm/plat-aspeed/timer.c
+index 079d958..6805beb 100644
+--- a/arch/arm/plat-aspeed/timer.c
++++ b/arch/arm/plat-aspeed/timer.c
+@@ -16,19 +16,13 @@
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
++#include <asm/io.h>
++#include <linux/clocksource.h>
++#include <linux/clockchips.h>
+ #include <linux/types.h>
+-#include <linux/kernel.h>
+ #include <linux/init.h>
+-#include <linux/device.h>
+-#include <linux/spinlock.h>
+ #include <linux/interrupt.h>
+-#include <linux/sched.h>
+-
+ #include <linux/irq.h>
+-#include <asm/system.h>
+-#include <asm/io.h>
+-#include <mach/hardware.h>
+-#include <mach/irqs.h>
+ #include <mach/time.h>
+ #include <plat/ast-scu.h>
+
+@@ -37,72 +31,145 @@
+ #define ASPEED_TIMER2_VA_BASE (IO_ADDRESS(AST_TIMER_BASE)+ASPEED_TIMER2_OFFSET)
+ #define ASPEED_TIMERC_VA_BASE (IO_ADDRESS(AST_TIMER_BASE)+ASPEED_TIMERRC_OFFSET)
+
+-/*
+- * Returns number of ms since last clock interrupt. Note that interrupts
+- * will have been disabled by do_gettimeoffset()
+- */
+-static unsigned long ast_gettimeoffset(void)
++#define ASPEED_TIMER_RELOAD_MAX 0xFFFFFFFF
++#define ASPEED_TIMER_RELOAD_MIN 1
++
++static struct clock_event_device clockevent_ast;
++
++static inline unsigned long ast_timer_read_count(void *base)
+ {
+- volatile TimerStruct_t *timer0 = (TimerStruct_t *) ASPEED_TIMER0_VA_BASE;
+- unsigned long ticks1, ticks2;//, status;
++ volatile TimerStruct_t *timer = (volatile TimerStruct_t *)(base);
++ return timer->TimerValue;
++}
+
+- /*
+- * Get the current number of ticks. Note that there is a race
+- * condition between us reading the timer and checking for
+- * an interrupt. We get around this by ensuring that the
+- * counter has not reloaded between our two reads.
+- */
+- ticks2 = timer0->TimerValue;
+- do {
+- ticks1 = ticks2;
+-// status = readl(AST_RAW_STS(0));// __raw_readl(IO_ADDRESS(ASPEED_VIC_BASE) + ASPEED_VIC_RAW_STATUS_OFFSET);
+- ticks2 = timer0->TimerValue;
+- } while (ticks2 > ticks1);
++/* change the timer count and load value (if requeseted) */
++static inline void ast_timer_set_count(void *base, unsigned long count,
++ unsigned long reload)
++{
++ volatile TimerStruct_t *timer = (volatile TimerStruct_t *)(base);
++ timer->TimerValue = count;
++ timer->TimerLoad = reload;
++}
+
+- /*
+- * Number of ticks since last interrupt.
+- */
+- ticks1 = TIMER_RELOAD - ticks2;
++#define AST_TIMER_DISABLE 0
++#define AST_TIMER_ENABLE 1
+
+- /*
+- * Interrupt pending? If so, we've reloaded once already.
+- */
+-// if (status & (1 << IRQ_TIMER0))
+-// ticks1 += TIMER_RELOAD;
++static inline void ast_timer0_ctrl(int enable)
++{
++ volatile __u32 *timerc = (volatile __u32*) ASPEED_TIMERC_VA_BASE;
++ if (enable == AST_TIMER_ENABLE) {
++ *timerc |= TIMER0_ENABLE | TIMER0_RefExt;
++ } else {
++ *timerc &= ~TIMER0_ENABLE;
++ }
++}
+
+- /*
+- * Convert the ticks to usecs
+- */
+- return TICKS2USECS(ticks1);
++static inline void ast_timer1_ctrl(int enable)
++{
++ volatile __u32 *timerc = (volatile __u32*) ASPEED_TIMERC_VA_BASE;
++ if (enable == AST_TIMER_ENABLE) {
++ *timerc |= TIMER1_ENABLE | TIMER1_RefExt;
++ } else {
++ *timerc &= ~TIMER1_ENABLE;
++ }
+ }
+
++static inline void ast_timer_disable_all()
++{
++ volatile __u32 *timerc = (volatile __u32*) ASPEED_TIMERC_VA_BASE;
++ *timerc = 0;
++}
+
+ /*
+- * IRQ handler for the timer
++ * clocksource
+ */
+-static irqreturn_t
+-ast_timer_interrupt(int irq, void *dev_id)
++static irqreturn_t ast_clocksource_interrupt(int irq, void *dev_id)
+ {
++ return IRQ_HANDLED;
++}
+
+-// write_seqlock(&xtime_lock);
++static struct irqaction ast_clocksource_irq = {
++ .name = "ast-clocksource",
++ .flags = IRQF_DISABLED | IRQF_TIMER,
++ .handler = ast_clocksource_interrupt,
++};
++
++static cycle_t read_cycles(void)
++{
++#if 1
++ return (cycles_t)(ASPEED_TIMER_RELOAD_MAX
++ - ast_timer_read_count(ASPEED_TIMER1_VA_BASE));
++#else
++ return (cycles_t) ast_timer_read_count(ASPEED_TIMER1_VA_BASE);
++#endif
++}
++
++static struct clocksource clocksource_ast = {
++ .name = "ast-clocksource",
++ .rating = 300,
++ .read = read_cycles,
++ .mask = CLOCKSOURCE_MASK(32),
++ .shift = 20,
++ .flags = CLOCK_SOURCE_IS_CONTINUOUS,
++};
+
+ /*
+- * clear the interrupt in Irq.c
++ * clockevent
+ */
+-// IRQ_EDGE_CLEAR(0,IRQ_TIMER0);
+-
+- timer_tick();
++/* IRQ handler for the timer */
++static irqreturn_t ast_clockevent_interrupt(int irq, void *dev_id)
++{
++ struct clock_event_device *evt = &clockevent_ast;
++ evt->event_handler(evt);
++ return IRQ_HANDLED;
++}
+
++static struct irqaction ast_clockevent_irq = {
++ .name = "ast-clockevent",
++ .flags = IRQF_DISABLED | IRQF_TIMER,
++ .handler = ast_clockevent_interrupt,
++};
+
+-// write_sequnlock(&xtime_lock);
++static int ast_timer_set_next_event(unsigned long cycles,
++ struct clock_event_device *evt)
++{
++ /* In this case, we shall not set the load value. */
++ ast_timer_set_count(ASPEED_TIMER0_VA_BASE, cycles, 0);
++ /* turn on the timer */
++ ast_timer0_ctrl(AST_TIMER_ENABLE);
++ return 0;
++}
+
+- return IRQ_HANDLED;
++static void ast_timer_set_mode(enum clock_event_mode mode,
++ struct clock_event_device *evt)
++{
++ /* stop timer first */
++ ast_timer0_ctrl(AST_TIMER_DISABLE);
++ switch (mode) {
++ case CLOCK_EVT_MODE_PERIODIC:
++ ast_timer_set_count(ASPEED_TIMER0_VA_BASE,
++ TIMER_RELOAD - 1, TIMER_RELOAD - 1);
++ ast_timer0_ctrl(AST_TIMER_ENABLE);
++ break;
++ case CLOCK_EVT_MODE_ONESHOT:
++ /*
++ * Leave the timer disabled, ast_timer_set_next_event() will
++ * enable it later
++ */
++ break;
++ case CLOCK_EVT_MODE_UNUSED:
++ case CLOCK_EVT_MODE_SHUTDOWN:
++ case CLOCK_EVT_MODE_RESUME:
++ break;
++ }
+ }
+
+-static struct irqaction ast_timer_irq = {
+- .name = "ast timer",
+- .flags = IRQF_DISABLED | IRQF_TIMER,
+- .handler = ast_timer_interrupt,
++static struct clock_event_device clockevent_ast = {
++ .name = "ast-clockevent",
++ .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
++ .shift = 32,
++ .set_next_event = ast_timer_set_next_event,
++ .set_mode = ast_timer_set_mode,
+ };
+
+ /*
+@@ -110,28 +177,50 @@ static struct irqaction ast_timer_irq = {
+ */
+ static void __init ast_setup_timer(void)
+ {
+- volatile TimerStruct_t *timer0 = (volatile TimerStruct_t *) ASPEED_TIMER0_VA_BASE;
+- volatile __u32 *timerc = (volatile __u32*) ASPEED_TIMERC_VA_BASE;
+-
+ /*
+ * Initialise to a known state (all timers off)
+ */
+- *timerc = 0;
+-
+- timer0->TimerLoad = TIMER_RELOAD - 1;
+- timer0->TimerValue = TIMER_RELOAD - 1;
+- *timerc = TIMER0_ENABLE | TIMER0_RefExt;
++ ast_timer_disable_all();
+
+ /*
+- * Make irqs happen for the system timer
++ * For clock event, set the value and reload to 0, so that no interrupt even
++ * after enabling timer.
+ */
++ ast_timer_set_count(ASPEED_TIMER0_VA_BASE, 0, 0);
++ /*
++ * For clock source, set the value and reload to the max
++ */
++ ast_timer_set_count(ASPEED_TIMER1_VA_BASE,
++ ASPEED_TIMER_RELOAD_MAX, ASPEED_TIMER_RELOAD_MAX);
++
++ /* Enable timer */
++ ast_timer0_ctrl(AST_TIMER_ENABLE);
++ ast_timer1_ctrl(AST_TIMER_ENABLE);
++
+ ast_scu_show_system_info();
+
+- setup_irq(IRQ_TIMER0, &ast_timer_irq);
+-
++ /* irqs happen for the system timer */
++ setup_irq(IRQ_TIMER0, &ast_clockevent_irq);
++ setup_irq(IRQ_TIMER1, &ast_clocksource_irq);
++
++ /* setup clocksource */
++ clocksource_ast.mult = clocksource_hz2mult(ASPEED_TIMER_CLKRATE,
++ clocksource_ast.shift);
++ if (clocksource_register(&clocksource_ast)) {
++ printk(KERN_ERR "Failed to register clock source %s", clocksource_ast.name);
++ }
++
++ /* setup clockevent */
++ clockevent_ast.mult = div_sc(ASPEED_TIMER_CLKRATE, NSEC_PER_SEC,
++ clockevent_ast.shift);
++ clockevent_ast.max_delta_ns = clockevent_delta2ns(ASPEED_TIMER_RELOAD_MAX,
++ &clockevent_ast);
++ clockevent_ast.min_delta_ns = clockevent_delta2ns(ASPEED_TIMER_RELOAD_MIN,
++ &clockevent_ast);
++ clockevent_ast.cpumask = cpumask_of_cpu(0);
++ clockevents_register_device(&clockevent_ast);
+ }
+
+ struct sys_timer ast_timer = {
+ .init = ast_setup_timer,
+-// .offset = ast_gettimeoffset,
+ };
+diff --git a/drivers/Makefile b/drivers/Makefile
+index fceb71a..0f19c40f 100644
+--- a/drivers/Makefile
++++ b/drivers/Makefile
+@@ -102,3 +102,4 @@ obj-$(CONFIG_SSB) += ssb/
+ obj-$(CONFIG_VIRTIO) += virtio/
+ obj-$(CONFIG_REGULATOR) += regulator/
+ obj-$(CONFIG_STAGING) += staging/
++
+diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig
+index 681782b..6055720 100644
+--- a/drivers/hwmon/Kconfig
++++ b/drivers/hwmon/Kconfig
+@@ -548,6 +548,16 @@ config SENSORS_LM93
+ This driver can also be built as a module. If so, the module
+ will be called lm93.
+
++config SENSORS_MAX127
++ tristate "Maxim MAX127 sensor chip"
++ depends on I2C
++ help
++ If you say yes here you get support for the MAX127,
++ 5 channel, 12-bit DAC sensor chip.
++
++ This driver can also be built as a module. If so, the module
++ will be called max127.
++
+ config SENSORS_MAX1111
+ tristate "Maxim MAX1111 Multichannel, Serial 8-bit ADC chip"
+ depends on SPI_MASTER
+@@ -870,6 +880,15 @@ config SENSORS_AST_PWM_FAN
+ This driver provides support for the ASPEED PWM & FAN Tacho
+ Controller, which provides an Sensor, fan control.
+
++config SENSORS_FB_PANTHER_PLUS
++ tristate "Facebook Panther+ Microserver Driver"
++ depends on ARCH_ASPEED && I2C
++ default n
++ help
++ This driver provides support for Facebook Panther+ microserver.
++
++ Say Y here if you run on the BMC which connects to Panther+ microserver
++
+ config SENSORS_APPLESMC
+ tristate "Apple SMC (Motion sensor, light sensor, keyboard backlight)"
+ depends on INPUT && X86
+@@ -895,6 +914,8 @@ config SENSORS_APPLESMC
+ Say Y here if you have an applicable laptop and want to experience
+ the awesome power of applesmc.
+
++source drivers/hwmon/pmbus/Kconfig
++
+ config HWMON_DEBUG_CHIP
+ bool "Hardware Monitoring Chip debugging messages"
+ default n
+diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile
+index 5629727..8039515 100644
+--- a/drivers/hwmon/Makefile
++++ b/drivers/hwmon/Makefile
+@@ -31,6 +31,7 @@ obj-$(CONFIG_SENSORS_ADT7473) += adt7473.o
+ obj-$(CONFIG_SENSORS_APPLESMC) += applesmc.o
+ obj-$(CONFIG_SENSORS_AST_ADC) += ast_adc.o
+ obj-$(CONFIG_SENSORS_AST_PWM_FAN) += ast_pwm_fan.o
++obj-$(CONFIG_SENSORS_FB_PANTHER_PLUS) += fb_panther_plus.o
+ obj-$(CONFIG_SENSORS_AMS) += ams/
+ obj-$(CONFIG_SENSORS_ATXP1) += atxp1.o
+ obj-$(CONFIG_SENSORS_CORETEMP) += coretemp.o
+@@ -64,6 +65,7 @@ obj-$(CONFIG_SENSORS_LM87) += lm87.o
+ obj-$(CONFIG_SENSORS_LM90) += lm90.o
+ obj-$(CONFIG_SENSORS_LM92) += lm92.o
+ obj-$(CONFIG_SENSORS_LM93) += lm93.o
++obj-$(CONFIG_SENSORS_MAX127) += max127.o
+ obj-$(CONFIG_SENSORS_MAX1111) += max1111.o
+ obj-$(CONFIG_SENSORS_MAX1619) += max1619.o
+ obj-$(CONFIG_SENSORS_MAX6650) += max6650.o
+@@ -81,6 +83,8 @@ obj-$(CONFIG_SENSORS_W83627EHF) += w83627ehf.o
+ obj-$(CONFIG_SENSORS_W83L785TS) += w83l785ts.o
+ obj-$(CONFIG_SENSORS_W83L786NG) += w83l786ng.o
+
++obj-$(CONFIG_PMBUS) += pmbus/
++
+ ifeq ($(CONFIG_HWMON_DEBUG_CHIP),y)
+ EXTRA_CFLAGS += -DDEBUG
+ endif
+diff --git a/drivers/hwmon/ast_adc.c b/drivers/hwmon/ast_adc.c
+index 0969e39..3f95dc6 100644
+--- a/drivers/hwmon/ast_adc.c
++++ b/drivers/hwmon/ast_adc.c
+@@ -42,7 +42,7 @@
+ #include <plat/ast-scu.h>
+
+
+-#define REST_DESIGN 0
++#define REST_DESIGN 5
+
+ struct adc_vcc_ref_data {
+ int v2;
+@@ -50,7 +50,7 @@ struct adc_vcc_ref_data {
+ int r2;
+ };
+
+-static struct adc_vcc_ref_data adc_vcc_ref[5] = {
++static struct adc_vcc_ref_data adc_vcc_ref[6] = {
+ [0] = {
+ .v2 = 0,
+ .r1 = 5600,
+@@ -76,8 +76,20 @@ static struct adc_vcc_ref_data adc_vcc_ref[5] = {
+ .r1 = 56000,
+ .r2 = 1000,
+ },
++ [5] = {
++ .v2 = 0,
++ .r1 = 1000,
++ .r2 = 1000,
++ },
+ };
+
++/* Divisors for voltage sense; right now adc5 & adc6 divide by 2 */
++
++static int adc_divisor[] = { 1, 1, 1, 1,
++ 1, 2, 2, 1,
++ 1, 1, 1, 1,
++ 1, 1, 1, 1};
++
+ struct ast_adc_data {
+ struct device *hwmon_dev;
+ void __iomem *reg_base; /* virtual */
+@@ -388,6 +400,22 @@ ast_set_adc_en(struct ast_adc_data *ast_adc, u8 adc_ch, u8 enable)
+ }
+
+
++/* NAME sysfs */
++static ssize_t
++show_name(struct device *dev, struct device_attribute *devattr,
++ char *buf)
++{
++ return sprintf(buf, "ast_adc\n");
++}
++static SENSOR_DEVICE_ATTR_2(name, S_IRUGO, show_name, NULL, 0, 0);
++static struct attribute *name_attributes[] = {
++ &sensor_dev_attr_name.dev_attr.attr,
++ NULL
++};
++static const struct attribute_group name_attribute_groups = {
++ .attrs = name_attributes,
++};
++
+ /* attr ADC sysfs 0~max adc channel
+ * 0 - show/store channel enable
+ * 1 - show value
+@@ -399,12 +427,31 @@ ast_set_adc_en(struct ast_adc_data *ast_adc, u8 adc_ch, u8 enable)
+ * 7 - show/store hystersis low
+ */
+
++static u32
++ast_get_voltage(int idx) {
++ u16 tmp;
++ u32 voltage, tmp1, tmp2, tmp3;
++ tmp = ast_get_adc_value(ast_adc, idx);
++ // Voltage Sense Method
++ tmp1 = (adc_vcc_ref[REST_DESIGN].r1 + adc_vcc_ref[REST_DESIGN].r2) * tmp * 25 * 10;
++ tmp2 = adc_vcc_ref[REST_DESIGN].r2 * 1024 ;
++ tmp3 = (adc_vcc_ref[REST_DESIGN].r1 * adc_vcc_ref[REST_DESIGN].v2) / adc_vcc_ref[REST_DESIGN].r2;
++ // printk("tmp3 = %d \n",tmp3);
++ voltage = (tmp1/tmp2) - tmp3;
++
++ // Higher voltage inputs require a divisor
++
++ if (adc_divisor[idx])
++ voltage /= adc_divisor[idx];
++
++ return voltage;
++}
++
+ static ssize_t
+ ast_show_adc(struct device *dev, struct device_attribute *attr, char *sysfsbuf)
+ {
+ struct sensor_device_attribute_2 *sensor_attr = to_sensor_dev_attr_2(attr);
+- u16 tmp;
+- u32 voltage,tmp1, tmp2,tmp3;
++ u32 voltage;
+
+ //sensor_attr->index : pwm_ch#
+ //sensor_attr->nr : attr#
+@@ -414,15 +461,7 @@ ast_show_adc(struct device *dev, struct device_attribute *attr, char *sysfsbuf)
+ return sprintf(sysfsbuf, "%d : %s\n", ast_get_adc_en(ast_adc,sensor_attr->index),ast_get_adc_en(ast_adc,sensor_attr->index) ? "Enable":"Disable");
+ break;
+ case 1: //value
+- tmp = ast_get_adc_value(ast_adc, sensor_attr->index);
+- //Voltage Sense Method
+- tmp1 = (adc_vcc_ref[REST_DESIGN].r1 + adc_vcc_ref[REST_DESIGN].r2) * tmp * 25 * 10;
+- tmp2 = adc_vcc_ref[REST_DESIGN].r2 * 1023 ;
+-
+- tmp3 = (adc_vcc_ref[REST_DESIGN].r1 * adc_vcc_ref[REST_DESIGN].v2) / adc_vcc_ref[REST_DESIGN].r2;
+- // printk("tmp3 = %d \n",tmp3);
+- voltage = (tmp1/tmp2) - tmp3;
+-
++ voltage = ast_get_voltage(sensor_attr->index);
+ return sprintf(sysfsbuf, "%d.%d (V)\n",voltage/100, voltage%100);
+ break;
+ case 2: //alarm
+@@ -443,6 +482,9 @@ ast_show_adc(struct device *dev, struct device_attribute *attr, char *sysfsbuf)
+ case 7: //hystersis lower
+ return sprintf(sysfsbuf, "%d \n", ast_get_adc_hyster_lower(ast_adc,sensor_attr->index));
+ break;
++ case 8:
++ voltage = ast_get_voltage(sensor_attr->index);
++ return sprintf(sysfsbuf, "%d\n",voltage * 10);
+
+ default:
+ return -EINVAL;
+@@ -504,6 +546,7 @@ ast_store_adc(struct device *dev, struct device_attribute *attr, const char *sys
+ * 5 - show/store hystersis enable
+ * 6 - show/store hystersis upper
+ * 7 - show/store hystersis low
++* 8 - show value as 1000s, expected by lm-sensors
+ */
+
+ #define sysfs_adc_ch(index) \
+@@ -531,6 +574,9 @@ static SENSOR_DEVICE_ATTR_2(adc##index##_hyster_upper, S_IRUGO | S_IWUSR, \
+ static SENSOR_DEVICE_ATTR_2(adc##index##_hyster_lower, S_IRUGO | S_IWUSR, \
+ ast_show_adc, ast_store_adc, 7, index); \
+ \
++static SENSOR_DEVICE_ATTR_2(in##index##_input, S_IRUGO | S_IWUSR, \
++ ast_show_adc, NULL, 8, index); \
++\
+ static struct attribute *adc##index##_attributes[] = { \
+ &sensor_dev_attr_adc##index##_en.dev_attr.attr, \
+ &sensor_dev_attr_adc##index##_value.dev_attr.attr, \
+@@ -540,6 +586,7 @@ static struct attribute *adc##index##_attributes[] = { \
+ &sensor_dev_attr_adc##index##_hyster_en.dev_attr.attr, \
+ &sensor_dev_attr_adc##index##_hyster_upper.dev_attr.attr, \
+ &sensor_dev_attr_adc##index##_hyster_lower.dev_attr.attr, \
++ &sensor_dev_attr_in##index##_input.dev_attr.attr, \
+ NULL \
+ };
+
+@@ -637,10 +684,14 @@ ast_adc_probe(struct platform_device *pdev)
+ goto out_region;
+ }
+
++ err = sysfs_create_group(&pdev->dev.kobj, &name_attribute_groups);
++ if (err)
++ goto out_region;
++
+ for(i=0; i<MAX_CH_NO; i++) {
+ err = sysfs_create_group(&pdev->dev.kobj, &adc_attribute_groups[i]);
+ if (err)
+- goto out_region;
++ goto out_sysfs00;
+ }
+
+ ast_adc_ctrl_init();
+@@ -652,6 +703,8 @@ ast_adc_probe(struct platform_device *pdev)
+
+ //out_irq:
+ // free_irq(ast_adc->irq, NULL);
++out_sysfs00:
++ sysfs_remove_group(&pdev->dev.kobj, &name_attribute_groups);
+ out_region:
+ release_mem_region(res->start, res->end - res->start + 1);
+ out_mem:
+@@ -674,6 +727,8 @@ ast_adc_remove(struct platform_device *pdev)
+ for(i=0; i<5; i++)
+ sysfs_remove_group(&pdev->dev.kobj, &adc_attribute_groups[i]);
+
++ sysfs_remove_group(&pdev->dev.kobj, &name_attribute_groups);
++
+ platform_set_drvdata(pdev, NULL);
+ // free_irq(ast_adc->irq, ast_adc);
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+diff --git a/drivers/hwmon/ast_pwm_fan.c b/drivers/hwmon/ast_pwm_fan.c
+index 02784c5..5864f5c 100644
+--- a/drivers/hwmon/ast_pwm_fan.c
++++ b/drivers/hwmon/ast_pwm_fan.c
+@@ -65,6 +65,8 @@
+ #include <mach/ast_pwm_techo.h>
+ #endif
+
++#include <plat/ast-scu.h>
++
+ //#define MCLK 1
+
+ struct ast_pwm_tacho_data {
+@@ -119,6 +121,8 @@ ast_pwm_tacho_read(struct ast_pwm_tacho_data *ast_pwm_tacho, u32 reg)
+
+ static void ast_pwm_taco_init(void)
+ {
++ uint32_t val;
++
+ //Enable PWM TACH CLK **************************************************
+ // Set M/N/O out is 25Khz
+ //The PWM frequency = 24Mhz / (16 * 6 * (9 + 1)) = 25Khz
+@@ -153,15 +157,20 @@ static void ast_pwm_taco_init(void)
+ ast_pwm_tacho_write(ast_pwm_tacho, 0x0, AST_PTCR_TACH_SOURCE);
+ ast_pwm_tacho_write(ast_pwm_tacho, 0x0, AST_PTCR_TACH_SOURCE_EXT);
+
+- //PWM A~D -> Disable , type M,
++ //PWM A~H -> Disable , type M,
+ //Tacho 0~15 Disable
+ //CLK source 24Mhz
++ val = AST_PTCR_CTRL_PWMA_EN | AST_PTCR_CTRL_PWMB_EN
++ | AST_PTCR_CTRL_PWMC_EN | AST_PTCR_CTRL_PWMD_EN
++ | AST_PTCR_CTRL_CLK_EN;
+ #ifdef MCLK
+- ast_pwm_tacho_write(ast_pwm_tacho, AST_PTCR_CTRL_CLK_MCLK | AST_PTCR_CTRL_CLK_EN, AST_PTCR_CTRL);
++ ast_pwm_tacho_write(ast_pwm_tacho, val|AST_PTCR_CTRL_CLK_MCLK, AST_PTCR_CTRL);
+ #else
+- ast_pwm_tacho_write(ast_pwm_tacho, AST_PTCR_CTRL_CLK_EN, AST_PTCR_CTRL);
++ ast_pwm_tacho_write(ast_pwm_tacho, val, AST_PTCR_CTRL);
+ #endif
+-
++ val = AST_PTCR_CTRL_PWME_EN | AST_PTCR_CTRL_PWMF_EN
++ | AST_PTCR_CTRL_PWMG_EN | AST_PTCR_CTRL_PWMH_EN;
++ ast_pwm_tacho_write(ast_pwm_tacho, val, AST_PTCR_CTRL_EXT);
+ }
+
+ /*index 0 : clk_en , 1: clk_source*/
+@@ -724,7 +733,7 @@ ast_get_tacho_rpm(struct ast_pwm_tacho_data *ast_pwm_tacho, u8 tacho_ch)
+ else
+ clk_source = 24*1000*1000;
+
+- printk("raw_data %d, clk_source %d, tacho_clk_div %d \n",raw_data, clk_source, tacho_clk_div);
++ // printk("raw_data %d, clk_source %d, tacho_clk_div %d \n",raw_data, clk_source, tacho_clk_div);
+ rpm = (clk_source * 60) / (2 * raw_data * tacho_clk_div);
+
+ return rpm;
+@@ -923,28 +932,28 @@ ast_get_pwm_en(struct ast_pwm_tacho_data *ast_pwm_tacho, u8 pwm_ch)
+
+ switch (pwm_ch) {
+ case PWMA:
+- tmp = (ast_pwm_tacho_read(ast_pwm_tacho, AST_PTCR_CTRL) & AST_PTCR_CTRL_PMWA_EN) >> AST_PTCR_CTRL_PMWA;
++ tmp = (ast_pwm_tacho_read(ast_pwm_tacho, AST_PTCR_CTRL) & AST_PTCR_CTRL_PWMA_EN) >> AST_PTCR_CTRL_PWMA;
+ break;
+ case PWMB:
+- tmp = (ast_pwm_tacho_read(ast_pwm_tacho, AST_PTCR_CTRL) & AST_PTCR_CTRL_PMWB_EN) >> AST_PTCR_CTRL_PMWB;
++ tmp = (ast_pwm_tacho_read(ast_pwm_tacho, AST_PTCR_CTRL) & AST_PTCR_CTRL_PWMB_EN) >> AST_PTCR_CTRL_PWMB;
+ break;
+ case PWMC:
+- tmp = (ast_pwm_tacho_read(ast_pwm_tacho, AST_PTCR_CTRL) & AST_PTCR_CTRL_PMWC_EN) >> AST_PTCR_CTRL_PMWC;
++ tmp = (ast_pwm_tacho_read(ast_pwm_tacho, AST_PTCR_CTRL) & AST_PTCR_CTRL_PWMC_EN) >> AST_PTCR_CTRL_PWMC;
+ break;
+ case PWMD:
+- tmp = (ast_pwm_tacho_read(ast_pwm_tacho, AST_PTCR_CTRL) & AST_PTCR_CTRL_PMWD_EN) >> AST_PTCR_CTRL_PMWD;
++ tmp = (ast_pwm_tacho_read(ast_pwm_tacho, AST_PTCR_CTRL) & AST_PTCR_CTRL_PWMD_EN) >> AST_PTCR_CTRL_PWMD;
+ break;
+ case PWME:
+- tmp = (ast_pwm_tacho_read(ast_pwm_tacho, AST_PTCR_CTRL_EXT) & AST_PTCR_CTRL_PMWE_EN) >> AST_PTCR_CTRL_PMWE;
++ tmp = (ast_pwm_tacho_read(ast_pwm_tacho, AST_PTCR_CTRL_EXT) & AST_PTCR_CTRL_PWME_EN) >> AST_PTCR_CTRL_PWME;
+ break;
+ case PWMF:
+- tmp = (ast_pwm_tacho_read(ast_pwm_tacho, AST_PTCR_CTRL_EXT) & AST_PTCR_CTRL_PMWF_EN) >> AST_PTCR_CTRL_PMWF;
++ tmp = (ast_pwm_tacho_read(ast_pwm_tacho, AST_PTCR_CTRL_EXT) & AST_PTCR_CTRL_PWMF_EN) >> AST_PTCR_CTRL_PWMF;
+ break;
+ case PWMG:
+- tmp = (ast_pwm_tacho_read(ast_pwm_tacho, AST_PTCR_CTRL_EXT) & AST_PTCR_CTRL_PMWG_EN) >> AST_PTCR_CTRL_PMWG;
++ tmp = (ast_pwm_tacho_read(ast_pwm_tacho, AST_PTCR_CTRL_EXT) & AST_PTCR_CTRL_PWMG_EN) >> AST_PTCR_CTRL_PWMG;
+ break;
+ case PWMH:
+- tmp = (ast_pwm_tacho_read(ast_pwm_tacho, AST_PTCR_CTRL_EXT) & AST_PTCR_CTRL_PMWH_EN) >> AST_PTCR_CTRL_PMWH;
++ tmp = (ast_pwm_tacho_read(ast_pwm_tacho, AST_PTCR_CTRL_EXT) & AST_PTCR_CTRL_PWMH_EN) >> AST_PTCR_CTRL_PWMH;
+ break;
+ default:
+ printk("error channel ast_get_pwm_type %d \n",pwm_ch);
+@@ -962,87 +971,87 @@ ast_set_pwm_en(struct ast_pwm_tacho_data *ast_pwm_tacho, u8 pwm_ch, u8 enable)
+ case PWMA:
+ if(enable)
+ ast_pwm_tacho_write(ast_pwm_tacho,
+- ast_pwm_tacho_read(ast_pwm_tacho, AST_PTCR_CTRL) | AST_PTCR_CTRL_PMWA_EN,
++ ast_pwm_tacho_read(ast_pwm_tacho, AST_PTCR_CTRL) | AST_PTCR_CTRL_PWMA_EN,
+ AST_PTCR_CTRL);
+ else
+ ast_pwm_tacho_write(ast_pwm_tacho,
+- ast_pwm_tacho_read(ast_pwm_tacho, AST_PTCR_CTRL) & ~AST_PTCR_CTRL_PMWA_EN,
++ ast_pwm_tacho_read(ast_pwm_tacho, AST_PTCR_CTRL) & ~AST_PTCR_CTRL_PWMA_EN,
+ AST_PTCR_CTRL);
+
+ break;
+ case PWMB:
+ if(enable)
+ ast_pwm_tacho_write(ast_pwm_tacho,
+- (ast_pwm_tacho_read(ast_pwm_tacho, AST_PTCR_CTRL) | AST_PTCR_CTRL_PMWB_EN),
++ (ast_pwm_tacho_read(ast_pwm_tacho, AST_PTCR_CTRL) | AST_PTCR_CTRL_PWMB_EN),
+ AST_PTCR_CTRL);
+ else
+ ast_pwm_tacho_write(ast_pwm_tacho,
+- (ast_pwm_tacho_read(ast_pwm_tacho, AST_PTCR_CTRL) & ~AST_PTCR_CTRL_PMWB_EN),
++ (ast_pwm_tacho_read(ast_pwm_tacho, AST_PTCR_CTRL) & ~AST_PTCR_CTRL_PWMB_EN),
+ AST_PTCR_CTRL);
+ break;
+ case PWMC:
+ if(enable)
+ ast_pwm_tacho_write(ast_pwm_tacho,
+- (ast_pwm_tacho_read(ast_pwm_tacho, AST_PTCR_CTRL) | AST_PTCR_CTRL_PMWC_EN),
++ (ast_pwm_tacho_read(ast_pwm_tacho, AST_PTCR_CTRL) | AST_PTCR_CTRL_PWMC_EN),
+ AST_PTCR_CTRL);
+ else
+ ast_pwm_tacho_write(ast_pwm_tacho,
+- (ast_pwm_tacho_read(ast_pwm_tacho, AST_PTCR_CTRL) & ~AST_PTCR_CTRL_PMWC_EN),
++ (ast_pwm_tacho_read(ast_pwm_tacho, AST_PTCR_CTRL) & ~AST_PTCR_CTRL_PWMC_EN),
+ AST_PTCR_CTRL);
+
+ break;
+ case PWMD:
+ if(enable)
+ ast_pwm_tacho_write(ast_pwm_tacho,
+- (ast_pwm_tacho_read(ast_pwm_tacho, AST_PTCR_CTRL) | AST_PTCR_CTRL_PMWD_EN),
++ (ast_pwm_tacho_read(ast_pwm_tacho, AST_PTCR_CTRL) | AST_PTCR_CTRL_PWMD_EN),
+ AST_PTCR_CTRL);
+ else
+ ast_pwm_tacho_write(ast_pwm_tacho,
+- (ast_pwm_tacho_read(ast_pwm_tacho, AST_PTCR_CTRL) & ~AST_PTCR_CTRL_PMWD_EN),
++ (ast_pwm_tacho_read(ast_pwm_tacho, AST_PTCR_CTRL) & ~AST_PTCR_CTRL_PWMD_EN),
+ AST_PTCR_CTRL);
+
+ break;
+ case PWME:
+ if(enable)
+ ast_pwm_tacho_write(ast_pwm_tacho,
+- (ast_pwm_tacho_read(ast_pwm_tacho, AST_PTCR_CTRL_EXT) | AST_PTCR_CTRL_PMWE_EN),
++ (ast_pwm_tacho_read(ast_pwm_tacho, AST_PTCR_CTRL_EXT) | AST_PTCR_CTRL_PWME_EN),
+ AST_PTCR_CTRL_EXT);
+ else
+ ast_pwm_tacho_write(ast_pwm_tacho,
+- (ast_pwm_tacho_read(ast_pwm_tacho, AST_PTCR_CTRL_EXT) & ~AST_PTCR_CTRL_PMWE_EN),
++ (ast_pwm_tacho_read(ast_pwm_tacho, AST_PTCR_CTRL_EXT) & ~AST_PTCR_CTRL_PWME_EN),
+ AST_PTCR_CTRL_EXT);
+
+ break;
+ case PWMF:
+ if(enable)
+ ast_pwm_tacho_write(ast_pwm_tacho,
+- (ast_pwm_tacho_read(ast_pwm_tacho, AST_PTCR_CTRL_EXT) | AST_PTCR_CTRL_PMWF_EN),
++ (ast_pwm_tacho_read(ast_pwm_tacho, AST_PTCR_CTRL_EXT) | AST_PTCR_CTRL_PWMF_EN),
+ AST_PTCR_CTRL_EXT);
+ else
+ ast_pwm_tacho_write(ast_pwm_tacho,
+- (ast_pwm_tacho_read(ast_pwm_tacho, AST_PTCR_CTRL_EXT) & ~AST_PTCR_CTRL_PMWF_EN),
++ (ast_pwm_tacho_read(ast_pwm_tacho, AST_PTCR_CTRL_EXT) & ~AST_PTCR_CTRL_PWMF_EN),
+ AST_PTCR_CTRL_EXT);
+
+ break;
+ case PWMG:
+ if(enable)
+ ast_pwm_tacho_write(ast_pwm_tacho,
+- (ast_pwm_tacho_read(ast_pwm_tacho, AST_PTCR_CTRL_EXT) | AST_PTCR_CTRL_PMWG_EN),
++ (ast_pwm_tacho_read(ast_pwm_tacho, AST_PTCR_CTRL_EXT) | AST_PTCR_CTRL_PWMG_EN),
+ AST_PTCR_CTRL_EXT);
+ else
+ ast_pwm_tacho_write(ast_pwm_tacho,
+- (ast_pwm_tacho_read(ast_pwm_tacho, AST_PTCR_CTRL_EXT) & ~AST_PTCR_CTRL_PMWG_EN),
++ (ast_pwm_tacho_read(ast_pwm_tacho, AST_PTCR_CTRL_EXT) & ~AST_PTCR_CTRL_PWMG_EN),
+ AST_PTCR_CTRL_EXT);
+
+ break;
+ case PWMH:
+ if(enable)
+ ast_pwm_tacho_write(ast_pwm_tacho,
+- (ast_pwm_tacho_read(ast_pwm_tacho, AST_PTCR_CTRL_EXT) | AST_PTCR_CTRL_PMWH_EN),
++ (ast_pwm_tacho_read(ast_pwm_tacho, AST_PTCR_CTRL_EXT) | AST_PTCR_CTRL_PWMH_EN),
+ AST_PTCR_CTRL_EXT);
+ else
+ ast_pwm_tacho_write(ast_pwm_tacho,
+- (ast_pwm_tacho_read(ast_pwm_tacho, AST_PTCR_CTRL_EXT) & ~AST_PTCR_CTRL_PMWH_EN),
++ (ast_pwm_tacho_read(ast_pwm_tacho, AST_PTCR_CTRL_EXT) & ~AST_PTCR_CTRL_PWMH_EN),
+ AST_PTCR_CTRL_EXT);
+
+ break;
+@@ -1383,6 +1392,22 @@ ast_set_pwm_duty_falling(struct ast_pwm_tacho_data *ast_pwm_tacho, u8 pwm_ch, u8
+
+ }
+
++/* NAME sysfs */
++static ssize_t
++show_name(struct device *dev, struct device_attribute *devattr,
++ char *buf)
++{
++ return sprintf(buf, "ast_pwm\n");
++}
++static SENSOR_DEVICE_ATTR_2(name, S_IRUGO, show_name, NULL, 0, 0);
++static struct attribute *name_attributes[] = {
++ &sensor_dev_attr_name.dev_attr.attr,
++ NULL
++};
++static const struct attribute_group name_attribute_groups = {
++ .attrs = name_attributes,
++};
++
+ /*PWM M/N/O Type sysfs*/
+ /*
+ * Macro defining SENSOR_DEVICE_ATTR for a pwm sysfs entries.
+@@ -1937,6 +1962,51 @@ static const struct attribute_group tacho_attribute_groups[] = {
+ { .attrs = tacho15_attributes },
+ };
+
++/* Create fan sysfs for lm-sensors, index starts from 1 */
++#define sysfs_fan_speeds_num(index) \
++static SENSOR_DEVICE_ATTR_2(fan##index##_input, S_IRUGO, \
++ ast_show_tacho_speed, NULL, 2, index - 1); \
++static struct attribute *fan##index##_attributes[] = { \
++ &sensor_dev_attr_fan##index##_input.dev_attr.attr, \
++ NULL \
++};
++
++sysfs_fan_speeds_num(1);
++sysfs_fan_speeds_num(2);
++sysfs_fan_speeds_num(3);
++sysfs_fan_speeds_num(4);
++sysfs_fan_speeds_num(5);
++sysfs_fan_speeds_num(6);
++sysfs_fan_speeds_num(7);
++sysfs_fan_speeds_num(8);
++sysfs_fan_speeds_num(9);
++sysfs_fan_speeds_num(10);
++sysfs_fan_speeds_num(11);
++sysfs_fan_speeds_num(12);
++sysfs_fan_speeds_num(13);
++sysfs_fan_speeds_num(14);
++sysfs_fan_speeds_num(15);
++sysfs_fan_speeds_num(16);
++
++static const struct attribute_group fan_attribute_groups[] = {
++ { .attrs = fan1_attributes },
++ { .attrs = fan2_attributes },
++ { .attrs = fan3_attributes },
++ { .attrs = fan4_attributes },
++ { .attrs = fan5_attributes },
++ { .attrs = fan6_attributes },
++ { .attrs = fan7_attributes },
++ { .attrs = fan8_attributes },
++ { .attrs = fan9_attributes },
++ { .attrs = fan10_attributes },
++ { .attrs = fan11_attributes },
++ { .attrs = fan12_attributes },
++ { .attrs = fan13_attributes },
++ { .attrs = fan14_attributes },
++ { .attrs = fan15_attributes },
++ { .attrs = fan16_attributes },
++};
++
+ static int
+ ast_pwm_tacho_probe(struct platform_device *pdev)
+ {
+@@ -1947,6 +2017,12 @@ ast_pwm_tacho_probe(struct platform_device *pdev)
+
+ dev_dbg(&pdev->dev, "ast_pwm_fan_probe \n");
+
++ //SCU Pin-MUX //PWM & TACHO
++ ast_scu_multi_func_pwm_tacho();
++
++ //SCU PWM CTRL Reset
++ ast_scu_init_pwm_tacho();
++
+ ast_pwm_tacho = kzalloc(sizeof(struct ast_pwm_tacho_data), GFP_KERNEL);
+ if (!ast_pwm_tacho) {
+ ret = -ENOMEM;
+@@ -1982,10 +2058,14 @@ ast_pwm_tacho_probe(struct platform_device *pdev)
+ }
+
+ /* Register sysfs hooks */
+- err = sysfs_create_group(&pdev->dev.kobj, &clk_attribute_groups);
++ err = sysfs_create_group(&pdev->dev.kobj, &name_attribute_groups);
+ if (err)
+ goto out_region;
+
++ err = sysfs_create_group(&pdev->dev.kobj, &clk_attribute_groups);
++ if (err)
++ goto out_sysfs00;
++
+ ast_pwm_tacho->hwmon_dev = hwmon_device_register(&pdev->dev);
+ if (IS_ERR(ast_pwm_tacho->hwmon_dev)) {
+ ret = PTR_ERR(ast_pwm_tacho->hwmon_dev);
+@@ -2017,12 +2097,22 @@ ast_pwm_tacho_probe(struct platform_device *pdev)
+ goto out_sysfs3;
+ }
+
++ for(i=0; i< TACHO_NUM; i++) {
++ err = sysfs_create_group(&pdev->dev.kobj, &fan_attribute_groups[i]);
++ if (err)
++ goto out_sysfs4;
++ }
++
+ ast_pwm_taco_init();
+
+ printk(KERN_INFO "ast_pwm_tacho: driver successfully loaded.\n");
+
+ return 0;
+
++out_sysfs4:
++ for(i=0; i< PWM_TYPE_NUM; i++)
++ sysfs_remove_group(&pdev->dev.kobj, &tacho_type_attribute_groups[i]);
++
+ out_sysfs3:
+ for(i=0; i< TACHO_NUM; i++)
+ sysfs_remove_group(&pdev->dev.kobj, &tacho_attribute_groups[i]);
+@@ -2036,6 +2126,8 @@ out_sysfs1:
+ sysfs_remove_group(&pdev->dev.kobj, &pwm_attribute_groups[i]);
+ out_sysfs0:
+ sysfs_remove_group(&pdev->dev.kobj, &clk_attribute_groups);
++out_sysfs00:
++ sysfs_remove_group(&pdev->dev.kobj, &name_attribute_groups);
+
+ //out_irq:
+ // free_irq(ast_pwm_tacho->irq, NULL);
+@@ -2058,9 +2150,10 @@ ast_pwm_tacho_remove(struct platform_device *pdev)
+
+ hwmon_device_unregister(ast_pwm_tacho->hwmon_dev);
+
+- for(i=0; i<16; i++)
++ for(i=0; i<16; i++) {
+ sysfs_remove_group(&pdev->dev.kobj, &tacho_attribute_groups[i]);
+-
++ sysfs_remove_group(&pdev->dev.kobj, &fan_attribute_groups[i]);
++ }
+ for(i=0; i<3; i++)
+ sysfs_remove_group(&pdev->dev.kobj, &pwm_type_attribute_groups[i]);
+
+@@ -2069,6 +2162,8 @@ ast_pwm_tacho_remove(struct platform_device *pdev)
+
+ sysfs_remove_group(&pdev->dev.kobj, &clk_attribute_groups);
+
++ sysfs_remove_group(&pdev->dev.kobj, &name_attribute_groups);
++
+ platform_set_drvdata(pdev, NULL);
+ // free_irq(ast_pwm_tacho->irq, ast_pwm_tacho);
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+diff --git a/drivers/hwmon/fb_panther_plus.c b/drivers/hwmon/fb_panther_plus.c
+new file mode 100644
+index 0000000..1dde2ec
+--- /dev/null
++++ b/drivers/hwmon/fb_panther_plus.c
+@@ -0,0 +1,722 @@
++/*
++ * fb_panther_plus.c - Driver for Panther+ microserver
++ *
++ * Copyright 2014-present Facebook. All Rights Reserved.
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
++ */
++
++//#define DEBUG
++
++#include <linux/delay.h>
++#include <linux/module.h>
++#include <linux/init.h>
++#include <linux/slab.h>
++#include <linux/jiffies.h>
++#include <linux/i2c.h>
++#include <linux/hwmon.h>
++#include <linux/hwmon-sysfs.h>
++#include <linux/err.h>
++#include <linux/mutex.h>
++#include <linux/sysfs.h>
++
++#ifdef DEBUG
++
++#define PP_DEBUG(fmt, ...) do { \
++ printk(KERN_DEBUG "%s:%d " fmt "\n", \
++ __FUNCTION__, __LINE__, ##__VA_ARGS__); \
++} while (0)
++
++#else /* !DEBUG */
++
++#define PP_DEBUG(fmt, ...)
++
++#endif
++
++static const unsigned short normal_i2c[] = {
++ 0x40, I2C_CLIENT_END
++};
++
++/*
++ * Insmod parameters
++ */
++
++I2C_CLIENT_INSMOD_1(panther_plus);
++
++/*
++ * Driver data (common to all clients)
++ */
++
++static const struct i2c_device_id panther_plus_id[] = {
++ { "fb_panther_plus", panther_plus },
++ { },
++};
++MODULE_DEVICE_TABLE(i2c, panther_plus_id);
++
++struct panther_plus_data {
++ struct device *hwmon_dev;
++ struct mutex update_lock;
++};
++
++// Identifies the sysfs attribute panther_plus_show is requesting.
++enum {
++ PANTHER_PLUS_SYSFS_CPU_TEMP,
++ PANTHER_PLUS_SYSFS_DIMM_TEMP,
++ PANTHER_PLUS_SYSFS_GPIO_INPUTS,
++ PANTHER_PLUS_SYSFS_SMS_KCS,
++ PANTHER_PLUS_SYSFS_ALERT_CONTROL,
++ PANTHER_PLUS_SYSFS_ALERT_STATUS,
++ PANTHER_PLUS_SYSFS_DISCOVERY_SPEC_VER,
++ PANTHER_PLUS_SYSFS_DISCOVERY_HW_VER,
++ PANTHER_PLUS_SYSFS_DISCOVERY_MANUFACTURER_ID,
++ PANTHER_PLUS_SYSFS_DISCOVERY_DEVICE_ID,
++ PANTHER_PLUS_SYSFS_DISCOVERY_PRODUCT_ID,
++};
++
++// Function Block ID identifiers.
++enum panther_plus_fbid_en {
++ PANTHER_PLUS_FBID_IPMI_SMS_KCS = 0x0,
++ PANTHER_PLUS_FBID_GPIO_INPUTS = 0xd,
++ PANTHER_PLUS_FBID_READ_REGISTER = 0x10,
++ PANTHER_PLUS_FBID_ALERT_CONTROL = 0xFD,
++ PANTHER_PLUS_FBID_ALERT_STATUS = 0xFE,
++ PANTHER_PLUS_FBID_DISCOVERY = 0xFF,
++};
++
++static inline void panther_plus_make_read(struct i2c_msg *msg,
++ u8 addr,
++ u8 *buf,
++ int len)
++{
++ msg->addr = addr;
++ msg->flags = I2C_M_RD;
++ msg->buf = buf;
++ msg->len = len;
++}
++
++static inline void panther_plus_make_write(struct i2c_msg *msg,
++ u8 addr,
++ u8 *buf,
++ int len)
++{
++ msg->addr = addr;
++ msg->flags = 0;
++ msg->buf = buf;
++ msg->len = len;
++}
++
++static int panther_plus_fbid_io(struct i2c_client *client,
++ enum panther_plus_fbid_en fbid,
++ const u8 *write_buf, u8 write_len,
++ u8 *read_buf, u8 read_len)
++{
++ // The Intel uServer Module Management Interface Spec defines SMBus blocks,
++ // but block sizes exceed the SMBus maximum block sizes
++ // (32, see I2C_SMBUS_BLOCK_MAX). So we basically have to re-implement the
++ // smbus functions with a larger max.
++ struct i2c_msg msg[2];
++ u8 buf[255];
++ u8 buf_len;
++ int rc;
++ u8 num_msgs = 1;
++
++ if (write_len + 1 > sizeof(buf)) {
++ return -EINVAL;
++ }
++
++ /* first, write the FBID, followed by the write_buf if there is one */
++ buf[0] = fbid;
++ buf_len = 1;
++ if (write_buf) {
++ memcpy(&buf[1], write_buf, write_len);
++ buf_len += write_len;
++ }
++ panther_plus_make_write(&msg[0], client->addr, buf, buf_len);
++
++ /* then, read */
++ if (read_buf) {
++ panther_plus_make_read(&msg[1], client->addr, read_buf, read_len);
++ num_msgs = 2;
++ }
++
++ rc = i2c_transfer(client->adapter, msg, num_msgs);
++ if (rc < 0) {
++ PP_DEBUG("Failed to read FBID: %d, error=%d", fbid, rc);
++ return rc;
++ }
++
++ if (rc != num_msgs) { /* expect 2 */
++ PP_DEBUG("Unexpected rc (%d != %d) when reading FBID: %d", rc, num_msgs, fbid);
++ return -EIO;
++ }
++
++ /* the first byte read should match fbid */
++
++ if (read_buf && read_buf[0] != fbid) {
++ PP_DEBUG("Unexpected FBID returned (%d != %d)", read_buf[0], fbid);
++ return -EIO;
++ }
++
++ return 0;
++}
++
++#define PP_GPIO_POWER_ON 0x1
++#define PP_GPIO_PWRGD_P1V35 (0x1 << 1)
++#define PP_GPIO_RST_EAGE_N (0x1 << 2)
++#define PP_GPIO_FM_BIOS_POST_CMPLT_N (0x1 << 3)
++#define PP_GPIO_IERR_FPGA (0x1 << 4)
++#define PP_GPIO_AVN_PLD_PROCHOT_N (0x1 << 5)
++#define PP_GPIO_BUS1_ERROR (0x1 << 6)
++#define PP_GPIO_AVN_PLD_THERMTRIP_N (0x1 << 7)
++#define PP_GPIO_MCERR_FPGA (0x1 << 8)
++#define PP_GPIO_ERROR_AVN_2 (0x1 << 9)
++#define PP_GPIO_ERROR_AVN_1 (0x1 << 10)
++#define PP_GPIO_ERROR_AVN_0 (0x1 << 11)
++#define PP_GPIO_H_MEMHOT_CO_N (0x1 << 12)
++#define PP_GPIO_SLP_S45_N (0x1 << 13)
++#define PP_GPIO_PLTRST_FPGA_N (0x1 << 14)
++#define PP_GPIO_FPGA_GPI_PWD_FAIL (0x1 << 15)
++#define PP_GPIO_FPGA_GPI_NMI (0x1 << 16)
++#define PP_GPIO_GPI_VCCP_VRHOT_N (0x1 << 17)
++#define PP_GPIO_FPGA_GPI_TMP75_ALERT (0x1 << 18)
++#define PP_GPIO_LPC_CLKRUN_N (0x1 << 19)
++
++static int panther_plus_read_gpio_inputs_value(
++ struct i2c_client *client, u32 *val)
++{
++ int rc;
++ u8 read_buf[5];
++
++ rc = panther_plus_fbid_io(client, PANTHER_PLUS_FBID_GPIO_INPUTS,
++ NULL, 0, read_buf, sizeof(read_buf));
++ if (rc < 0) {
++ return rc;
++ }
++
++ /*
++ * expect receiving 5 bytes as:
++ * 0xd 0x3 <gpio0-7> <gpio8-15> <gpio9-23>
++ */
++ if (read_buf[1] != 0x3) {
++ PP_DEBUG("Unexpected length %d != 3", read_buf[1]);
++ return -EIO;
++ }
++
++ *val = read_buf[2] | (read_buf[3] << 8) | (read_buf[4] << 16);
++
++ return 0;
++}
++
++static int panther_plus_is_in_post(struct i2c_client *client)
++{
++ u32 val;
++ int rc;
++
++ rc = panther_plus_read_gpio_inputs_value(client, &val);
++ if (rc < 0) {
++ /* failed to read gpio, treat it as in post */
++ return 1;
++ }
++
++ /* if PP_GPIO_FM_BIOS_POST_CMPLT_N is set, post is _not_ done yet */
++ return (val & PP_GPIO_FM_BIOS_POST_CMPLT_N);
++}
++
++static int panther_plus_read_register(struct i2c_client *client,
++ u8 reg_idx, u32 *reg_val)
++{
++ u8 write_buf[2];
++ u8 read_buf[8];
++ int rc;
++
++ /* need to send the register index for the reading */
++ write_buf[0] = 0x1; /* one byte */
++ write_buf[1] = reg_idx;
++
++ rc = panther_plus_fbid_io(client, PANTHER_PLUS_FBID_READ_REGISTER,
++ write_buf, sizeof(write_buf),
++ read_buf, sizeof(read_buf));
++ if (rc < 0) {
++ return -EIO;
++ }
++
++ /*
++ * expect receiving 8 bytes as:
++ * 0x10 0x6 <reg_idx> LSB LSB+1 LSB+2 LSB+3 valid
++ */
++ if (read_buf[1] != 0x6
++ || read_buf[2] != reg_idx
++ || read_buf[7] != 0) {
++ return -EIO;
++ }
++
++ *reg_val = read_buf[3] | (read_buf[4] << 8)
++ | (read_buf[5] << 16) | (read_buf[6] << 24);
++
++ PP_DEBUG("Read register %d: 0x%x", reg_idx, *reg_val);
++
++ return 0;
++}
++
++#define PANTHER_PLUS_REG_SOC_TJMAX 0
++#define PANTHER_PLUS_REG_SOC_RUNTIME 1
++#define PANTHER_PLUS_REG_SOC_THERMAL_MARGIN 2
++#define PANTHER_PLUS_REG_SOC_DIMM0_A_TEMP 3
++#define PANTHER_PLUS_REG_SOC_DIMM0_B_TEMP 4
++#define PANTHER_PLUS_REG_SOC_POWER_UNIT 5
++#define PANTHER_PLUS_REG_SOC_POWER_CONSUMPTION 6
++#define PANTHER_PLUS_REG_SOC_POWER_CALC 7
++#define PANTHER_PLUS_REG_SOC_DIMM1_A_TEMP 8
++#define PANTHER_PLUS_REG_SOC_DIMM1_B_TEMP 9
++
++static int panther_plus_read_cpu_temp(struct i2c_client *client, char *ret)
++{
++ int rc;
++ u32 tjmax;
++ u32 tmargin;
++ int val;
++ int temp;
++
++ /*
++ * make sure POST is done, accessing CPU temperature during POST phase could
++ * confusing POST and make it hang
++ */
++ if (panther_plus_is_in_post(client)) {
++ return -EBUSY;
++ }
++
++ mdelay(10);
++
++ /* first read Tjmax: register 0, bit[16-23] */
++ rc = panther_plus_read_register(client, PANTHER_PLUS_REG_SOC_TJMAX, &tjmax);
++ if (rc < 0) {
++ return rc;
++ }
++
++ mdelay(10);
++
++ /* then, read the thermal margin */
++ rc = panther_plus_read_register(client, PANTHER_PLUS_REG_SOC_THERMAL_MARGIN,
++ &tmargin);
++ if (rc < 0) {
++ return rc;
++ }
++ /*
++ * thermal margin is 16b 2's complement value representing a number of 1/64
++ * degress centigrade.
++ */
++ tmargin &= 0xFFFF;
++ if ((tmargin & 0x8000)) {
++ /* signed */
++ val = -((tmargin - 1) ^ 0xFFFF);
++ } else {
++ val = tmargin;
++ }
++
++ /*
++ * now val holds the margin (a number of 1/64), add it to the Tjmax.
++ * Times 1000 for lm-sensors.
++ */
++ temp = ((tjmax >> 16) & 0xFF) * 1000 + val * 1000 / 64;
++
++ return sprintf(ret, "%d\n", temp);
++}
++
++static int panther_plus_read_dimm_temp(struct i2c_client *client,
++ int dimm, char *ret)
++{
++ int rc;
++ u32 val;
++ int temp;
++
++ /*
++ * make sure POST is done, accessing DIMM temperature will fail anyway if
++ * POST is not done.
++ */
++ if (panther_plus_is_in_post(client)) {
++ return -EBUSY;
++ }
++
++ mdelay(10);
++
++ rc = panther_plus_read_register(client, dimm, &val);
++ if (rc < 0) {
++ return rc;
++ }
++
++ /*
++ * DIMM temperature is encoded in 16b as the following:
++ * b15-b12: TCRIT HIGH LOW SIGN
++ * b11-b08: 128 64 32 16
++ * b07-b04: 8 4 2 1
++ * b03-b00: 0.5 0.25 0.125 0.0625
++ */
++ /* For now, only care about those 12 data bits and SIGN */
++ val &= 0x1FFF;
++ if ((val & 0x1000)) {
++ /* signed */
++ val = -((val - 1) ^ 0x1FFF);
++ }
++
++ /*
++ * now val holds the value as a number of 1/16, times 1000 for lm-sensors */
++ temp = val * 1000 / 16;
++
++ return sprintf(ret, "%d\n", temp);
++}
++
++static int panther_plus_read_gpio_inputs(struct i2c_client *client, char *ret)
++{
++ u32 val;
++ int rc;
++
++ rc = panther_plus_read_gpio_inputs_value(client, &val);
++ if (rc < 0) {
++ return rc;
++ }
++ return sprintf(ret, "0x%x\n", val);
++}
++
++static int panther_plus_read_sms_kcs(struct i2c_client *client, char *ret)
++{
++ int rc;
++ u8 read_buf[255] = {0x0};
++
++ rc = panther_plus_fbid_io(client, PANTHER_PLUS_FBID_IPMI_SMS_KCS,
++ NULL, 0, read_buf, sizeof(read_buf));
++ if (rc < 0) {
++ return rc;
++ }
++
++ memcpy(ret, read_buf, read_buf[1]+2);
++
++ return (read_buf[1]+2);
++}
++
++static int panther_plus_write_sms_kcs(struct i2c_client *client, const char *buf, u8 count)
++{
++ int rc;
++
++ rc = panther_plus_fbid_io(client, PANTHER_PLUS_FBID_IPMI_SMS_KCS,
++ buf, count, NULL, 0);
++ if (rc < 0) {
++ return rc;
++ }
++
++ return count;
++}
++
++static int panther_plus_read_alert_status(struct i2c_client *client, char *ret)
++{
++ int rc;
++ u8 rbuf[5] = {0};
++
++ rc = panther_plus_fbid_io(client, PANTHER_PLUS_FBID_ALERT_STATUS,
++ NULL, 0, rbuf, sizeof(rbuf));
++ if (rc < 0) {
++ return rc;
++ }
++
++ memcpy(ret, rbuf, rbuf[1]+2);
++
++ return (rbuf[1]+2);
++}
++
++static int panther_plus_read_alert_control(struct i2c_client *client, char *ret)
++{
++ int rc;
++ u8 rbuf[5] = {0};
++
++ rc = panther_plus_fbid_io(client, PANTHER_PLUS_FBID_ALERT_CONTROL,
++ NULL, 0, rbuf, sizeof(rbuf));
++ if (rc < 0) {
++ return rc;
++ }
++
++ memcpy(ret, rbuf, rbuf[1]+2);
++
++ return (rbuf[1]+2);
++}
++
++static int panther_plus_read_discovery(struct i2c_client *client, char *ret,
++ int which_attribute)
++{
++ int rc;
++ u8 datalen;
++#define DISCOVERY_DATA_SIZE 10
++ u8 rbuf[DISCOVERY_DATA_SIZE+2] = {0};
++ rc = panther_plus_fbid_io(client, PANTHER_PLUS_FBID_DISCOVERY,
++ NULL, 0, rbuf, sizeof(rbuf));
++ if (rc < 0) {
++ return rc;
++ }
++ datalen = rbuf[1];
++ if (datalen < DISCOVERY_DATA_SIZE) {
++ return -EINVAL;
++ }
++ switch (which_attribute) {
++ case PANTHER_PLUS_SYSFS_DISCOVERY_SPEC_VER:
++ return scnprintf(ret, PAGE_SIZE, "%u.%u\n", rbuf[2], rbuf[3]);
++ case PANTHER_PLUS_SYSFS_DISCOVERY_HW_VER:
++ return scnprintf(ret, PAGE_SIZE, "%u.%u\n", rbuf[4], rbuf[5]);
++ case PANTHER_PLUS_SYSFS_DISCOVERY_MANUFACTURER_ID:
++ return scnprintf(ret, PAGE_SIZE, "0x%02X%02X%02X\n", rbuf[8], rbuf[7],
++ rbuf[6]);
++ case PANTHER_PLUS_SYSFS_DISCOVERY_DEVICE_ID:
++ return scnprintf(ret, PAGE_SIZE, "0x%02X\n", rbuf[9]);
++ case PANTHER_PLUS_SYSFS_DISCOVERY_PRODUCT_ID:
++ return scnprintf(ret, PAGE_SIZE, "0x%02X%02X\n", rbuf[11], rbuf[10]);
++ default:
++ return -EINVAL;
++ }
++ return -EINVAL;
++}
++
++static int panther_plus_write_alert_control(struct i2c_client *client, const char *buf, u8 count)
++{
++ int rc;
++
++ rc = panther_plus_fbid_io(client, PANTHER_PLUS_FBID_ALERT_CONTROL,
++ buf, count, NULL, 0);
++ if (rc < 0) {
++ return rc;
++ }
++
++ return count;
++}
++
++static ssize_t panther_plus_show(struct device *dev,
++ struct device_attribute *attr,
++ char *buf)
++{
++ struct i2c_client *client = to_i2c_client(dev);
++ struct panther_plus_data *data = i2c_get_clientdata(client);
++ struct sensor_device_attribute_2 *sensor_attr = to_sensor_dev_attr_2(attr);
++ int which = sensor_attr->index;
++ int rc = -EIO;
++
++ mutex_lock(&data->update_lock);
++ switch (which) {
++ case PANTHER_PLUS_SYSFS_CPU_TEMP:
++ rc = panther_plus_read_cpu_temp(client, buf);
++ break;
++ case PANTHER_PLUS_SYSFS_DIMM_TEMP:
++ rc = panther_plus_read_dimm_temp(client, sensor_attr->nr, buf);
++ break;
++ case PANTHER_PLUS_SYSFS_GPIO_INPUTS:
++ rc = panther_plus_read_gpio_inputs(client, buf);
++ break;
++ case PANTHER_PLUS_SYSFS_SMS_KCS:
++ rc = panther_plus_read_sms_kcs(client, buf);
++ break;
++ case PANTHER_PLUS_SYSFS_ALERT_STATUS:
++ rc = panther_plus_read_alert_status(client, buf);
++ break;
++ case PANTHER_PLUS_SYSFS_ALERT_CONTROL:
++ rc = panther_plus_read_alert_control(client, buf);
++ break;
++ case PANTHER_PLUS_SYSFS_DISCOVERY_SPEC_VER:
++ case PANTHER_PLUS_SYSFS_DISCOVERY_HW_VER:
++ case PANTHER_PLUS_SYSFS_DISCOVERY_MANUFACTURER_ID:
++ case PANTHER_PLUS_SYSFS_DISCOVERY_DEVICE_ID:
++ case PANTHER_PLUS_SYSFS_DISCOVERY_PRODUCT_ID:
++ rc = panther_plus_read_discovery(client, buf, which);
++ default:
++ break;
++ }
++
++ /*
++ * With the current i2c driver, the bus/kernel could hang if accessing the
++ * FPGA too fast. Adding some delay here until we fix the i2c driver bug
++ */
++ mdelay(10);
++
++ mutex_unlock(&data->update_lock);
++
++ return rc;
++}
++
++static ssize_t panther_plus_set(struct device *dev,
++ struct device_attribute *attr,
++ const char *buf, size_t count)
++{
++ struct i2c_client *client = to_i2c_client(dev);
++ struct panther_plus_data *data = i2c_get_clientdata(client);
++ struct sensor_device_attribute_2 *sensor_attr = to_sensor_dev_attr_2(attr);
++ int which = sensor_attr->index;
++
++ int rc = -EIO;
++ mutex_lock(&data->update_lock);
++ switch (which) {
++ case PANTHER_PLUS_SYSFS_SMS_KCS:
++ rc = panther_plus_write_sms_kcs(client, buf, count);
++ break;
++ case PANTHER_PLUS_SYSFS_ALERT_CONTROL:
++ rc = panther_plus_write_alert_control(client, buf, count);
++ break;
++ default:
++ break;
++ }
++
++ mdelay(10);
++
++ mutex_unlock(&data->update_lock);
++
++ return rc;
++}
++
++static SENSOR_DEVICE_ATTR_2(temp1_input, S_IRUGO, panther_plus_show, NULL,
++ 0, PANTHER_PLUS_SYSFS_CPU_TEMP);
++static SENSOR_DEVICE_ATTR_2(temp2_input, S_IRUGO, panther_plus_show, NULL,
++ PANTHER_PLUS_REG_SOC_DIMM0_A_TEMP,
++ PANTHER_PLUS_SYSFS_DIMM_TEMP);
++static SENSOR_DEVICE_ATTR_2(temp3_input, S_IRUGO, panther_plus_show, NULL,
++ PANTHER_PLUS_REG_SOC_DIMM0_B_TEMP,
++ PANTHER_PLUS_SYSFS_DIMM_TEMP);
++static SENSOR_DEVICE_ATTR_2(temp4_input, S_IRUGO, panther_plus_show, NULL,
++ PANTHER_PLUS_REG_SOC_DIMM1_A_TEMP,
++ PANTHER_PLUS_SYSFS_DIMM_TEMP);
++static SENSOR_DEVICE_ATTR_2(temp5_input, S_IRUGO, panther_plus_show, NULL,
++ PANTHER_PLUS_REG_SOC_DIMM1_B_TEMP,
++ PANTHER_PLUS_SYSFS_DIMM_TEMP);
++static SENSOR_DEVICE_ATTR_2(gpio_inputs, S_IRUGO, panther_plus_show, NULL,
++ 0, PANTHER_PLUS_SYSFS_GPIO_INPUTS);
++static SENSOR_DEVICE_ATTR_2(sms_kcs, S_IWUSR | S_IRUGO, panther_plus_show, panther_plus_set,
++ 0, PANTHER_PLUS_SYSFS_SMS_KCS);
++static SENSOR_DEVICE_ATTR_2(alert_status, S_IRUGO, panther_plus_show, NULL,
++ 0, PANTHER_PLUS_SYSFS_ALERT_STATUS);
++static SENSOR_DEVICE_ATTR_2(alert_control, S_IWUSR | S_IRUGO, panther_plus_show, panther_plus_set,
++ 0, PANTHER_PLUS_SYSFS_ALERT_CONTROL);
++static SENSOR_DEVICE_ATTR_2(spec_ver, S_IRUGO, panther_plus_show, NULL,
++ 0, PANTHER_PLUS_SYSFS_DISCOVERY_SPEC_VER);
++static SENSOR_DEVICE_ATTR_2(hw_ver, S_IRUGO, panther_plus_show, NULL,
++ 0, PANTHER_PLUS_SYSFS_DISCOVERY_HW_VER);
++static SENSOR_DEVICE_ATTR_2(manufacturer_id, S_IRUGO, panther_plus_show, NULL,
++ 0, PANTHER_PLUS_SYSFS_DISCOVERY_MANUFACTURER_ID);
++static SENSOR_DEVICE_ATTR_2(device_id, S_IRUGO, panther_plus_show, NULL,
++ 0, PANTHER_PLUS_SYSFS_DISCOVERY_DEVICE_ID);
++static SENSOR_DEVICE_ATTR_2(product_id, S_IRUGO, panther_plus_show, NULL,
++ 0, PANTHER_PLUS_SYSFS_DISCOVERY_PRODUCT_ID);
++
++static struct attribute *panther_plus_attributes[] = {
++ &sensor_dev_attr_temp1_input.dev_attr.attr,
++ &sensor_dev_attr_temp2_input.dev_attr.attr,
++ &sensor_dev_attr_temp3_input.dev_attr.attr,
++ &sensor_dev_attr_temp4_input.dev_attr.attr,
++ &sensor_dev_attr_temp5_input.dev_attr.attr,
++ &sensor_dev_attr_gpio_inputs.dev_attr.attr,
++ &sensor_dev_attr_sms_kcs.dev_attr.attr,
++ &sensor_dev_attr_alert_status.dev_attr.attr,
++ &sensor_dev_attr_alert_control.dev_attr.attr,
++ &sensor_dev_attr_spec_ver.dev_attr.attr,
++ &sensor_dev_attr_hw_ver.dev_attr.attr,
++ &sensor_dev_attr_manufacturer_id.dev_attr.attr,
++ &sensor_dev_attr_device_id.dev_attr.attr,
++ &sensor_dev_attr_product_id.dev_attr.attr,
++ NULL
++};
++
++static const struct attribute_group panther_plus_group = {
++ .attrs = panther_plus_attributes,
++};
++
++/* Return 0 if detection is successful, -ENODEV otherwise */
++static int panther_plus_detect(struct i2c_client *client, int kind,
++ struct i2c_board_info *info)
++{
++ /*
++ * We don't currently do any detection of the Panther+, although
++ * presumably we could try to query FBID 0xFF for HW ID.
++ */
++ strlcpy(info->type, "panther_plus", I2C_NAME_SIZE);
++ return 0;
++}
++
++static int panther_plus_probe(struct i2c_client *client,
++ const struct i2c_device_id *id)
++{
++ struct panther_plus_data *data;
++ int err;
++
++ data = kzalloc(sizeof(struct panther_plus_data), GFP_KERNEL);
++ if (!data) {
++ err = -ENOMEM;
++ goto exit;
++ }
++
++ i2c_set_clientdata(client, data);
++ mutex_init(&data->update_lock);
++
++ /* Register sysfs hooks */
++ if ((err = sysfs_create_group(&client->dev.kobj, &panther_plus_group)))
++ goto exit_free;
++
++ data->hwmon_dev = hwmon_device_register(&client->dev);
++ if (IS_ERR(data->hwmon_dev)) {
++ err = PTR_ERR(data->hwmon_dev);
++ goto exit_remove_files;
++ }
++
++ printk(KERN_INFO "Panther+ driver successfully loaded.\n");
++
++ return 0;
++
++ exit_remove_files:
++ sysfs_remove_group(&client->dev.kobj, &panther_plus_group);
++ exit_free:
++ kfree(data);
++ exit:
++ return err;
++}
++
++static int panther_plus_remove(struct i2c_client *client)
++{
++ struct panther_plus_data *data = i2c_get_clientdata(client);
++
++ hwmon_device_unregister(data->hwmon_dev);
++ sysfs_remove_group(&client->dev.kobj, &panther_plus_group);
++
++ kfree(data);
++ return 0;
++}
++
++static struct i2c_driver panther_plus_driver = {
++ .class = I2C_CLASS_HWMON,
++ .driver = {
++ .name = "panther_plus",
++ },
++ .probe = panther_plus_probe,
++ .remove = panther_plus_remove,
++ .id_table = panther_plus_id,
++ .detect = panther_plus_detect,
++ .address_data = &addr_data,
++};
++
++static int __init sensors_panther_plus_init(void)
++{
++ return i2c_add_driver(&panther_plus_driver);
++}
++
++static void __exit sensors_panther_plus_exit(void)
++{
++ i2c_del_driver(&panther_plus_driver);
++}
++
++MODULE_AUTHOR("Tian Fang <tfang@fb.com>");
++MODULE_DESCRIPTION("Panther+ Driver");
++MODULE_LICENSE("GPL");
++
++module_init(sensors_panther_plus_init);
++module_exit(sensors_panther_plus_exit);
+diff --git a/drivers/hwmon/max127.c b/drivers/hwmon/max127.c
+new file mode 100644
+index 0000000..a223f94
+--- /dev/null
++++ b/drivers/hwmon/max127.c
+@@ -0,0 +1,312 @@
++/*
++ * max127.c - Part of lm_sensors, Linux kernel modules for hardware
++ * monitoring
++ * Copyright 2004-present Facebook. All Rights Reserved.
++ * Copyright (C) 2003-2004 Alexey Fisher <fishor@mail.ru>
++ * Jean Delvare <khali@linux-fr.org>
++ *
++ * Based on the max1619 driver, which was based on the lm90 driver.
++ * The MAX127 is a voltage sensor chip made by Maxim. It reports
++ * up to eight voltages, with a choice of maximums * of 5V or 10V.
++ * In addition, it can read either only positive voltages,
++ * or negative voltages as well, for a maximum range of -10V to +10V.
++ *
++ * Complete datasheet can be obtained from Maxim's website at:
++ * http://datasheets.maximintegrated.com/en/ds/MAX127-MAX128B.pdf
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
++ */
++
++
++#include <linux/module.h>
++#include <linux/init.h>
++#include <linux/slab.h>
++#include <linux/jiffies.h>
++#include <linux/i2c.h>
++#include <linux/hwmon.h>
++#include <linux/hwmon-sysfs.h>
++#include <linux/err.h>
++#include <linux/mutex.h>
++#include <linux/sysfs.h>
++
++static const unsigned short normal_i2c[] = {
++ 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, I2C_CLIENT_END };
++
++/*
++ * Insmod parameters
++ */
++
++I2C_CLIENT_INSMOD_1(max127);
++
++static int scaling;
++module_param(scaling, int, 0);
++MODULE_PARM_DESC(scaling, "Fixed-point scaling factor (* 10000), ie 24414");
++
++
++/*
++ * The MAX127 I2C messages
++ */
++
++/* We send a single query byte to the device, setting the following bits: */
++
++#define MAX127_REG_R_START 0x80 /* Top bit must be set */
++#define MAX127_REG_R_SEL_MASK 0x70 /* Which of 8 inputs to get */
++#define MAX127_REG_R_SEL_SHIFT 4
++#define MAX127_REG_R_RNG 0x08 /* 10v (otherwise 5v) */
++#define MAX127_REG_R_BIP 0x04 /* show negative voltage */
++#define MAX127_REG_R_PD1 0x02 /* power saving controls */
++#define MAX127_REG_R_PD0 0x01
++
++/* Must shift return value to get a 12-bit value */
++#define MAX127_RESULT_SHIFT 4
++
++#define MAX127_CHANNELS 8
++
++/*
++ * Functions declaration
++ */
++
++static int max127_probe(struct i2c_client *client,
++ const struct i2c_device_id *id);
++static int max127_detect(struct i2c_client *client, int kind,
++ struct i2c_board_info *info);
++static int max127_remove(struct i2c_client *client);
++static void max127_update_device(struct device *dev, int which);
++
++/*
++ * Driver data (common to all clients)
++ */
++
++static const struct i2c_device_id max127_id[] = {
++ { "max127", max127 },
++ { }
++};
++MODULE_DEVICE_TABLE(i2c, max127_id);
++
++static struct i2c_driver max127_driver = {
++ .class = I2C_CLASS_HWMON,
++ .driver = {
++ .name = "max127",
++ },
++ .probe = max127_probe,
++ .remove = max127_remove,
++ .id_table = max127_id,
++ .detect = max127_detect,
++ .address_data = &addr_data,
++};
++
++/*
++ * Client data (each client gets its own)
++ */
++
++struct max127_data {
++ struct device *hwmon_dev;
++ struct mutex update_lock;
++ u16 valid; /* zero until following fields are valid */
++
++ u16 voltage;
++};
++
++/*
++ * Sysfs stuff
++ */
++
++static ssize_t show_in(struct device *dev, struct device_attribute *attr,
++ char *buf)
++{
++ struct i2c_client *client = to_i2c_client(dev);
++ struct max127_data *data = i2c_get_clientdata(client);
++ struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
++ int which = sensor_attr->index;
++ int valid;
++ unsigned voltage;
++
++ mutex_lock(&data->update_lock);
++ max127_update_device(dev, which);
++ valid = data->valid;
++ voltage = data->voltage;
++ mutex_unlock(&data->update_lock);
++
++ if (scaling)
++ voltage = voltage * scaling / 10000;
++
++ if (!valid)
++ return -EIO;
++ return sprintf(buf, "%u\n", voltage);
++}
++
++
++static SENSOR_DEVICE_ATTR(in0_input, S_IRUGO, show_in, NULL, 0);
++static SENSOR_DEVICE_ATTR(in1_input, S_IRUGO, show_in, NULL, 1);
++static SENSOR_DEVICE_ATTR(in2_input, S_IRUGO, show_in, NULL, 2);
++static SENSOR_DEVICE_ATTR(in3_input, S_IRUGO, show_in, NULL, 3);
++static SENSOR_DEVICE_ATTR(in4_input, S_IRUGO, show_in, NULL, 4);
++static SENSOR_DEVICE_ATTR(in5_input, S_IRUGO, show_in, NULL, 5);
++static SENSOR_DEVICE_ATTR(in6_input, S_IRUGO, show_in, NULL, 6);
++static SENSOR_DEVICE_ATTR(in7_input, S_IRUGO, show_in, NULL, 7);
++
++static struct attribute *max127_attributes[] = {
++ &sensor_dev_attr_in0_input.dev_attr.attr,
++ &sensor_dev_attr_in1_input.dev_attr.attr,
++ &sensor_dev_attr_in2_input.dev_attr.attr,
++ &sensor_dev_attr_in3_input.dev_attr.attr,
++ &sensor_dev_attr_in4_input.dev_attr.attr,
++ &sensor_dev_attr_in5_input.dev_attr.attr,
++ &sensor_dev_attr_in6_input.dev_attr.attr,
++ &sensor_dev_attr_in7_input.dev_attr.attr,
++ NULL
++};
++
++static const struct attribute_group max127_group = {
++ .attrs = max127_attributes,
++};
++
++/*
++ * Real code
++ */
++
++/* Return 0 if detection is successful, -ENODEV otherwise */
++static int max127_detect(struct i2c_client *new_client, int kind,
++ struct i2c_board_info *info)
++{
++ struct i2c_adapter *adapter = new_client->adapter;
++
++ if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA |
++ I2C_FUNC_SMBUS_WORD_DATA))
++ return -EIO;
++
++ /*
++ * We don't currently do any detection of the MAX127, although
++ * presumably we could try setting and unsetting the top
++ * bit in a query to see whether it does conversions or fails.
++ */
++
++ strlcpy(info->type, "max127", I2C_NAME_SIZE);
++
++ return 0;
++}
++
++static int max127_probe(struct i2c_client *new_client,
++ const struct i2c_device_id *id)
++{
++ struct max127_data *data;
++ int err;
++
++ data = kzalloc(sizeof(struct max127_data), GFP_KERNEL);
++ if (!data) {
++ err = -ENOMEM;
++ goto exit;
++ }
++
++ i2c_set_clientdata(new_client, data);
++ data->valid = 0;
++ mutex_init(&data->update_lock);
++
++ /* Register sysfs hooks */
++ if ((err = sysfs_create_group(&new_client->dev.kobj, &max127_group)))
++ goto exit_free;
++
++ data->hwmon_dev = hwmon_device_register(&new_client->dev);
++ if (IS_ERR(data->hwmon_dev)) {
++ err = PTR_ERR(data->hwmon_dev);
++ goto exit_remove_files;
++ }
++
++ return 0;
++
++exit_remove_files:
++ sysfs_remove_group(&new_client->dev.kobj, &max127_group);
++exit_free:
++ kfree(data);
++exit:
++ return err;
++}
++
++static int max127_remove(struct i2c_client *client)
++{
++ struct max127_data *data = i2c_get_clientdata(client);
++
++ hwmon_device_unregister(data->hwmon_dev);
++ sysfs_remove_group(&client->dev.kobj, &max127_group);
++
++ kfree(data);
++ return 0;
++}
++
++static void max127_update_device(struct device *dev, int which)
++{
++ struct i2c_client *client = to_i2c_client(dev);
++ struct max127_data *data = i2c_get_clientdata(client);
++ struct i2c_msg msg;
++ int status;
++ u8 buf[2];
++
++ /*
++ * The MAX127 doesn't use standard SMBus queries; it needs a
++ * write to specify what conversion to make, followed by an i2c
++ * STOP. It can then be read for the two-byte voltage value.
++ * Perhaps the idea is that a query can be started, then
++ * checked at an arbitrarily later time. We don't support
++ * that -- we just get a result immediately.
++ *
++ * We have to use i2c_transfer to do the second read without
++ * writing to any registers, rather than using the i2c_smbus_xxxxxx
++ * queries that most of the other hwmon drivers do.
++ */
++
++ dev_dbg(&client->dev, "Updating max127 data for probe %d.\n", which);
++ data->valid = 0;
++
++ buf[0] = MAX127_REG_R_START | (which << MAX127_REG_R_SEL_SHIFT) |
++ MAX127_REG_R_RNG;
++ msg.addr = client->addr;
++ msg.flags = 0;
++ msg.buf = buf;
++ msg.len = 1;
++ status = i2c_transfer(client->adapter, &msg, 1);
++
++ if (status != 1) {
++ return;
++ }
++
++ msg.addr = client->addr;
++ msg.flags = I2C_M_RD;
++ msg.buf = buf;
++ msg.len = 2;
++ status = i2c_transfer(client->adapter, &msg, 1);
++
++ data->voltage = (buf[0] << 8) | buf[1];
++ data->voltage >>= MAX127_RESULT_SHIFT;
++
++ if (status == 1)
++ data->valid = 1;
++}
++
++static int __init sensors_max127_init(void)
++{
++ return i2c_add_driver(&max127_driver);
++}
++
++static void __exit sensors_max127_exit(void)
++{
++ i2c_del_driver(&max127_driver);
++}
++
++MODULE_AUTHOR("Kevin Lahey <klahey@fb.com>");
++MODULE_DESCRIPTION("MAX127 sensor driver");
++MODULE_LICENSE("GPL");
++
++module_init(sensors_max127_init);
++module_exit(sensors_max127_exit);
+diff --git a/drivers/hwmon/pmbus/Kconfig b/drivers/hwmon/pmbus/Kconfig
+new file mode 100644
+index 0000000..52a3c7e
+--- /dev/null
++++ b/drivers/hwmon/pmbus/Kconfig
+@@ -0,0 +1,144 @@
++#
++# PMBus chip drivers configuration
++#
++
++menuconfig PMBUS
++ tristate "PMBus support"
++ depends on I2C
++ default n
++ help
++ Say yes here if you want to enable PMBus support.
++
++ This driver can also be built as a module. If so, the module will
++ be called pmbus_core.
++
++if PMBUS
++
++config SENSORS_PMBUS
++ tristate "Generic PMBus devices"
++ default y
++ help
++ If you say yes here you get hardware monitoring support for generic
++ PMBus devices, including but not limited to ADP4000, BMR453, BMR454,
++ MDT040, NCP4200, NCP4208, PDT003, PDT006, PDT012, UDT020, TPS40400,
++ and TPS40422.
++
++ This driver can also be built as a module. If so, the module will
++ be called pmbus.
++
++config SENSORS_ADM1275
++ tristate "Analog Devices ADM1275 and compatibles"
++ default n
++ help
++ If you say yes here you get hardware monitoring support for Analog
++ Devices ADM1075, ADM1275, and ADM1276 Hot-Swap Controller and Digital
++ Power Monitors.
++
++ This driver can also be built as a module. If so, the module will
++ be called adm1275.
++
++config SENSORS_LM25066
++ tristate "National Semiconductor LM25066 and compatibles"
++ default n
++ help
++ If you say yes here you get hardware monitoring support for National
++ Semiconductor LM25056, LM25066, LM5064, and LM5066.
++
++ This driver can also be built as a module. If so, the module will
++ be called lm25066.
++
++config SENSORS_LTC2978
++ tristate "Linear Technologies LTC2974, LTC2978, LTC3880, and LTC3883"
++ default n
++ help
++ If you say yes here you get hardware monitoring support for Linear
++ Technology LTC2974, LTC2978, LTC3880, and LTC3883.
++
++ This driver can also be built as a module. If so, the module will
++ be called ltc2978.
++
++config SENSORS_MAX16064
++ tristate "Maxim MAX16064"
++ default n
++ help
++ If you say yes here you get hardware monitoring support for Maxim
++ MAX16064.
++
++ This driver can also be built as a module. If so, the module will
++ be called max16064.
++
++config SENSORS_MAX34440
++ tristate "Maxim MAX34440 and compatibles"
++ default n
++ help
++ If you say yes here you get hardware monitoring support for Maxim
++ MAX34440, MAX34441, MAX34446, MAX34460, and MAX34461.
++
++ This driver can also be built as a module. If so, the module will
++ be called max34440.
++
++config SENSORS_MAX8688
++ tristate "Maxim MAX8688"
++ default n
++ help
++ If you say yes here you get hardware monitoring support for Maxim
++ MAX8688.
++
++ This driver can also be built as a module. If so, the module will
++ be called max8688.
++
++config SENSORS_PFE1100
++ tristate "Power One PFE1100"
++ default n
++ help
++ If you say yes here you get hardware monitoring support for
++ Power One PFE1100 devices.
++
++ This driver can also be built as a module. If so, the module will
++ be called pfe1100.
++
++config SENSORS_PFE3000
++ tristate "Power One PFE3000"
++ default n
++ help
++ If you say yes here you get hardware monitoring support for
++ Power One PFE3000 devices.
++
++ This driver can also be built as a module. If so, the module will
++ be called pfe3000.
++
++config SENSORS_UCD9000
++ tristate "TI UCD90120, UCD90124, UCD9090, UCD90910"
++ default n
++ help
++ If you say yes here you get hardware monitoring support for TI
++ UCD90120, UCD90124, UCD9090, UCD90910 Sequencer and System Health
++ Controllers.
++
++ This driver can also be built as a module. If so, the module will
++ be called ucd9000.
++
++config SENSORS_UCD9200
++ tristate "TI UCD9220, UCD9222, UCD9224, UCD9240, UCD9244, UCD9246, UCD9248"
++ default n
++ help
++ If you say yes here you get hardware monitoring support for TI
++ UCD9220, UCD9222, UCD9224, UCD9240, UCD9244, UCD9246, and UCD9248
++ Digital PWM System Controllers.
++
++ This driver can also be built as a module. If so, the module will
++ be called ucd9200.
++
++config SENSORS_ZL6100
++ tristate "Intersil ZL6100 and compatibles"
++ default n
++ help
++ If you say yes here you get hardware monitoring support for Intersil
++ ZL2004, ZL2005, ZL2006, ZL2008, ZL2105, ZL2106, ZL6100, ZL6105,
++ ZL9101M, and ZL9117M Digital DC/DC Controllers, as well as for
++ Ericsson BMR450, BMR451, BMR462, BMR463, and BMR464.
++
++ This driver can also be built as a module. If so, the module will
++ be called zl6100.
++
++endif # PMBUS
+diff --git a/drivers/hwmon/pmbus/Makefile b/drivers/hwmon/pmbus/Makefile
+new file mode 100644
+index 0000000..6cb3f6d
+--- /dev/null
++++ b/drivers/hwmon/pmbus/Makefile
+@@ -0,0 +1,17 @@
++#
++# Makefile for PMBus chip drivers.
++#
++
++obj-$(CONFIG_PMBUS) += pmbus_core.o
++obj-$(CONFIG_SENSORS_PMBUS) += pmbus.o
++obj-$(CONFIG_SENSORS_ADM1275) += adm1275.o
++obj-$(CONFIG_SENSORS_LM25066) += lm25066.o
++obj-$(CONFIG_SENSORS_LTC2978) += ltc2978.o
++obj-$(CONFIG_SENSORS_MAX16064) += max16064.o
++obj-$(CONFIG_SENSORS_MAX34440) += max34440.o
++obj-$(CONFIG_SENSORS_MAX8688) += max8688.o
++obj-$(CONFIG_SENSORS_PFE1100) += pfe1100.o
++obj-$(CONFIG_SENSORS_PFE3000) += pfe3000.o
++obj-$(CONFIG_SENSORS_UCD9000) += ucd9000.o
++obj-$(CONFIG_SENSORS_UCD9200) += ucd9200.o
++obj-$(CONFIG_SENSORS_ZL6100) += zl6100.o
+diff --git a/drivers/hwmon/pmbus/adm1275.c b/drivers/hwmon/pmbus/adm1275.c
+new file mode 100644
+index 0000000..d29f604
+--- /dev/null
++++ b/drivers/hwmon/pmbus/adm1275.c
+@@ -0,0 +1,457 @@
++/*
++ * Hardware monitoring driver for Analog Devices ADM1275 Hot-Swap Controller
++ * and Digital Power Monitor
++ *
++ * Copyright (c) 2011 Ericsson AB.
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ */
++
++#include <linux/kernel.h>
++#include <linux/module.h>
++#include <linux/init.h>
++#include <linux/err.h>
++#include <linux/slab.h>
++#include <linux/i2c.h>
++#include "pmbus.h"
++
++enum chips { adm1075, adm1275, adm1276, adm1278 };
++
++#define ADM1275_PEAK_IOUT 0xd0
++#define ADM1275_PEAK_VIN 0xd1
++#define ADM1275_PEAK_VOUT 0xd2
++#define ADM1278_PMON_CONTROL 0xd3
++#define ADM1275_PMON_CONFIG 0xd4
++
++#define ADM1278_CFG_TSFLT (1 << 15)
++#define ADM1278_CFG_SIMULTANEOUS (1 << 14)
++#define ADM1278_CFG_PMON_MODE (1 << 4)
++#define ADM1278_CFG_TEMP1_EN (1 << 3)
++#define ADM1278_CFG_VIN_EN (1 << 2)
++#define ADM1278_CFG_VOUT_EN (1 << 1)
++
++#define ADM1275_VIN_VOUT_SELECT (1 << 6)
++#define ADM1275_VRANGE (1 << 5)
++#define ADM1075_IRANGE_50 (1 << 4)
++#define ADM1075_IRANGE_25 (1 << 3)
++#define ADM1075_IRANGE_MASK ((1 << 3) | (1 << 4))
++
++#define ADM1275_IOUT_WARN2_LIMIT 0xd7
++#define ADM1275_DEVICE_CONFIG 0xd8
++
++#define ADM1275_IOUT_WARN2_SELECT (1 << 4)
++
++#define ADM1276_PEAK_PIN 0xda
++
++#define ADM1275_MFR_STATUS_IOUT_WARN2 (1 << 0)
++
++#define ADM1075_READ_VAUX 0xdd
++#define ADM1075_VAUX_OV_WARN_LIMIT 0xde
++#define ADM1075_VAUX_UV_WARN_LIMIT 0xdf
++#define ADM1075_VAUX_STATUS 0xf6
++
++#define ADM1075_VAUX_OV_WARN (1<<7)
++#define ADM1075_VAUX_UV_WARN (1<<6)
++
++struct adm1275_data {
++ int id;
++ bool have_oc_fault;
++ struct pmbus_driver_info info;
++};
++
++#define to_adm1275_data(x) container_of(x, struct adm1275_data, info)
++
++#define ADM1278_R_SENSE 500 /* R_sense resistor value in microohms */
++
++static int r_sense = ADM1278_R_SENSE;
++module_param(r_sense, int, 0644);
++MODULE_PARM_DESC(r_sense, "Rsense resistor value in microohms");
++
++
++static int adm1275_read_word_data(struct i2c_client *client, int page, int reg)
++{
++ const struct pmbus_driver_info *info = pmbus_get_driver_info(client);
++ const struct adm1275_data *data = to_adm1275_data(info);
++ int ret = 0;
++
++ if (page)
++ return -ENXIO;
++
++ switch (reg) {
++ case PMBUS_IOUT_UC_FAULT_LIMIT:
++ if (data->have_oc_fault) {
++ ret = -ENXIO;
++ break;
++ }
++ ret = pmbus_read_word_data(client, 0, ADM1275_IOUT_WARN2_LIMIT);
++ break;
++ case PMBUS_IOUT_OC_FAULT_LIMIT:
++ if (!data->have_oc_fault) {
++ ret = -ENXIO;
++ break;
++ }
++ ret = pmbus_read_word_data(client, 0, ADM1275_IOUT_WARN2_LIMIT);
++ break;
++ case PMBUS_VOUT_OV_WARN_LIMIT:
++ if (data->id != adm1075) {
++ ret = -ENODATA;
++ break;
++ }
++ ret = pmbus_read_word_data(client, 0,
++ ADM1075_VAUX_OV_WARN_LIMIT);
++ break;
++ case PMBUS_VOUT_UV_WARN_LIMIT:
++ if (data->id != adm1075) {
++ ret = -ENODATA;
++ break;
++ }
++ ret = pmbus_read_word_data(client, 0,
++ ADM1075_VAUX_UV_WARN_LIMIT);
++ break;
++ case PMBUS_READ_VOUT:
++ if (data->id != adm1075) {
++ ret = -ENODATA;
++ break;
++ }
++ ret = pmbus_read_word_data(client, 0, ADM1075_READ_VAUX);
++ break;
++ case PMBUS_VIRT_READ_IOUT_MAX:
++ ret = pmbus_read_word_data(client, 0, ADM1275_PEAK_IOUT);
++ break;
++ case PMBUS_VIRT_READ_VOUT_MAX:
++ ret = pmbus_read_word_data(client, 0, ADM1275_PEAK_VOUT);
++ break;
++ case PMBUS_VIRT_READ_VIN_MAX:
++ ret = pmbus_read_word_data(client, 0, ADM1275_PEAK_VIN);
++ break;
++ case PMBUS_VIRT_READ_PIN_MAX:
++ if (data->id == adm1275) {
++ ret = -ENXIO;
++ break;
++ }
++ ret = pmbus_read_word_data(client, 0, ADM1276_PEAK_PIN);
++ break;
++ case PMBUS_VIRT_RESET_IOUT_HISTORY:
++ case PMBUS_VIRT_RESET_VOUT_HISTORY:
++ case PMBUS_VIRT_RESET_VIN_HISTORY:
++ break;
++ case PMBUS_VIRT_RESET_PIN_HISTORY:
++ if (data->id == adm1275)
++ ret = -ENXIO;
++ break;
++ default:
++ ret = -ENODATA;
++ break;
++ }
++ return ret;
++}
++
++static int adm1275_write_word_data(struct i2c_client *client, int page, int reg,
++ u16 word)
++{
++ int ret;
++
++ if (page)
++ return -ENXIO;
++
++ switch (reg) {
++ case PMBUS_IOUT_UC_FAULT_LIMIT:
++ case PMBUS_IOUT_OC_FAULT_LIMIT:
++ ret = pmbus_write_word_data(client, 0, ADM1275_IOUT_WARN2_LIMIT,
++ word);
++ break;
++ case PMBUS_VIRT_RESET_IOUT_HISTORY:
++ ret = pmbus_write_word_data(client, 0, ADM1275_PEAK_IOUT, 0);
++ break;
++ case PMBUS_VIRT_RESET_VOUT_HISTORY:
++ ret = pmbus_write_word_data(client, 0, ADM1275_PEAK_VOUT, 0);
++ break;
++ case PMBUS_VIRT_RESET_VIN_HISTORY:
++ ret = pmbus_write_word_data(client, 0, ADM1275_PEAK_VIN, 0);
++ break;
++ case PMBUS_VIRT_RESET_PIN_HISTORY:
++ ret = pmbus_write_word_data(client, 0, ADM1276_PEAK_PIN, 0);
++ break;
++ default:
++ ret = -ENODATA;
++ break;
++ }
++ return ret;
++}
++
++static int adm1275_read_byte_data(struct i2c_client *client, int page, int reg)
++{
++ const struct pmbus_driver_info *info = pmbus_get_driver_info(client);
++ const struct adm1275_data *data = to_adm1275_data(info);
++ int mfr_status, ret;
++
++ if (page > 0)
++ return -ENXIO;
++
++ switch (reg) {
++ case PMBUS_STATUS_IOUT:
++ ret = pmbus_read_byte_data(client, page, PMBUS_STATUS_IOUT);
++ if (ret < 0)
++ break;
++ mfr_status = pmbus_read_byte_data(client, page,
++ PMBUS_STATUS_MFR_SPECIFIC);
++ if (mfr_status < 0) {
++ ret = mfr_status;
++ break;
++ }
++ if (mfr_status & ADM1275_MFR_STATUS_IOUT_WARN2) {
++ ret |= data->have_oc_fault ?
++ PB_IOUT_OC_FAULT : PB_IOUT_UC_FAULT;
++ }
++ break;
++ case PMBUS_STATUS_VOUT:
++ if (data->id != adm1075) {
++ ret = -ENODATA;
++ break;
++ }
++ ret = 0;
++ mfr_status = pmbus_read_byte_data(client, 0,
++ ADM1075_VAUX_STATUS);
++ if (mfr_status & ADM1075_VAUX_OV_WARN)
++ ret |= PB_VOLTAGE_OV_WARNING;
++ if (mfr_status & ADM1075_VAUX_UV_WARN)
++ ret |= PB_VOLTAGE_UV_WARNING;
++ break;
++ default:
++ ret = -ENODATA;
++ break;
++ }
++ return ret;
++}
++
++static const struct i2c_device_id adm1275_id[] = {
++ { "adm1075", adm1075 },
++ { "adm1275", adm1275 },
++ { "adm1276", adm1276 },
++ { "adm1278", adm1278 },
++ { }
++};
++MODULE_DEVICE_TABLE(i2c, adm1275_id);
++
++static int adm1275_probe(struct i2c_client *client,
++ const struct i2c_device_id *id)
++{
++ u8 block_buffer[I2C_SMBUS_BLOCK_MAX + 1];
++ int config, device_config;
++ int ret;
++ struct pmbus_driver_info *info;
++ struct adm1275_data *data;
++ const struct i2c_device_id *mid;
++
++ if (!i2c_check_functionality(client->adapter,
++ I2C_FUNC_SMBUS_READ_BYTE_DATA
++ | I2C_FUNC_SMBUS_BLOCK_DATA))
++ return -ENODEV;
++
++ ret = i2c_smbus_read_block_data(client, PMBUS_MFR_ID, block_buffer);
++ if (ret < 0) {
++ dev_err(&client->dev, "Failed to read Manufacturer ID\n");
++ return ret;
++ }
++ if (ret != 3 || strncmp(block_buffer, "ADI", 3)) {
++ dev_err(&client->dev, "Unsupported Manufacturer ID\n");
++ return -ENODEV;
++ }
++
++ ret = i2c_smbus_read_block_data(client, PMBUS_MFR_MODEL, block_buffer);
++ if (ret < 0) {
++ dev_err(&client->dev, "Failed to read Manufacturer Model\n");
++ return ret;
++ }
++ for (mid = adm1275_id; mid->name[0]; mid++) {
++ if (!strncasecmp(mid->name, block_buffer, strlen(mid->name)))
++ break;
++ }
++ if (!mid->name[0]) {
++ dev_err(&client->dev, "Unsupported device\n");
++ return -ENODEV;
++ }
++
++ if (id->driver_data != mid->driver_data)
++ dev_notice(&client->dev,
++ "Device mismatch: Configured %s, detected %s\n",
++ id->name, mid->name);
++
++ config = i2c_smbus_read_byte_data(client, ADM1275_PMON_CONFIG);
++ if (config < 0)
++ return config;
++
++ device_config = i2c_smbus_read_byte_data(client, ADM1275_DEVICE_CONFIG);
++ if (device_config < 0)
++ return device_config;
++
++ data = devm_kzalloc(&client->dev, sizeof(struct adm1275_data),
++ GFP_KERNEL);
++ if (!data)
++ return -ENOMEM;
++
++ data->id = mid->driver_data;
++
++ info = &data->info;
++
++ info->pages = 1;
++ info->format[PSC_VOLTAGE_IN] = direct;
++ info->format[PSC_VOLTAGE_OUT] = direct;
++ info->format[PSC_CURRENT_OUT] = direct;
++ if (data->id == adm1278)
++ info->m[PSC_CURRENT_OUT] = 807 * r_sense / 1000;
++ else
++ info->m[PSC_CURRENT_OUT] = 807;
++ info->b[PSC_CURRENT_OUT] = 20475;
++ info->R[PSC_CURRENT_OUT] = -1;
++ info->func[0] = PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT;
++
++ if (data->id == adm1278) {
++ /* Configure monitoring */
++ ret = i2c_smbus_write_byte_data(client,
++ ADM1278_PMON_CONTROL, 0);
++ if (ret < 0)
++ return ret;
++ ret = i2c_smbus_read_word_data(client, ADM1275_PMON_CONFIG);
++ ret = i2c_smbus_write_word_data(client, ADM1275_PMON_CONFIG,
++ ADM1278_CFG_PMON_MODE |
++ ADM1278_CFG_TEMP1_EN |
++ ADM1278_CFG_VIN_EN |
++ ADM1278_CFG_VOUT_EN);
++ if (ret < 0)
++ return ret;
++ ret = i2c_smbus_read_word_data(client, ADM1275_PMON_CONFIG);
++ ret = i2c_smbus_write_byte_data(client, ADM1278_PMON_CONTROL, 1);
++ if (ret < 0)
++ return ret;
++ } else {
++ /* TODO klahey -- there might be adm1278 issues here, too. */
++ info->read_word_data = adm1275_read_word_data;
++ info->read_byte_data = adm1275_read_byte_data;
++ info->write_word_data = adm1275_write_word_data;
++ }
++
++ if (data->id == adm1278) {
++ info->m[PSC_VOLTAGE_IN] = 19599;
++ info->b[PSC_VOLTAGE_IN] = 0;
++ info->R[PSC_VOLTAGE_IN] = -2;
++ info->m[PSC_VOLTAGE_OUT] = 19599;
++ info->b[PSC_VOLTAGE_OUT] = 0;
++ info->R[PSC_VOLTAGE_OUT] = -2;
++ } else if (data->id == adm1075) {
++ info->m[PSC_VOLTAGE_IN] = 27169;
++ info->b[PSC_VOLTAGE_IN] = 0;
++ info->R[PSC_VOLTAGE_IN] = -1;
++ info->m[PSC_VOLTAGE_OUT] = 27169;
++ info->b[PSC_VOLTAGE_OUT] = 0;
++ info->R[PSC_VOLTAGE_OUT] = -1;
++ } else if (config & ADM1275_VRANGE) {
++ info->m[PSC_VOLTAGE_IN] = 19199;
++ info->b[PSC_VOLTAGE_IN] = 0;
++ info->R[PSC_VOLTAGE_IN] = -2;
++ info->m[PSC_VOLTAGE_OUT] = 19199;
++ info->b[PSC_VOLTAGE_OUT] = 0;
++ info->R[PSC_VOLTAGE_OUT] = -2;
++ } else {
++ info->m[PSC_VOLTAGE_IN] = 6720;
++ info->b[PSC_VOLTAGE_IN] = 0;
++ info->R[PSC_VOLTAGE_IN] = -1;
++ info->m[PSC_VOLTAGE_OUT] = 6720;
++ info->b[PSC_VOLTAGE_OUT] = 0;
++ info->R[PSC_VOLTAGE_OUT] = -1;
++ }
++
++ if (device_config & ADM1275_IOUT_WARN2_SELECT)
++ data->have_oc_fault = true;
++
++ switch (data->id) {
++ case adm1075:
++ info->format[PSC_POWER] = direct;
++ info->b[PSC_POWER] = 0;
++ info->R[PSC_POWER] = -1;
++ switch (config & ADM1075_IRANGE_MASK) {
++ case ADM1075_IRANGE_25:
++ info->m[PSC_POWER] = 8549;
++ info->m[PSC_CURRENT_OUT] = 806;
++ break;
++ case ADM1075_IRANGE_50:
++ info->m[PSC_POWER] = 4279;
++ info->m[PSC_CURRENT_OUT] = 404;
++ break;
++ default:
++ dev_err(&client->dev, "Invalid input current range");
++ info->m[PSC_POWER] = 0;
++ info->m[PSC_CURRENT_OUT] = 0;
++ break;
++ }
++ info->func[0] |= PMBUS_HAVE_VIN | PMBUS_HAVE_PIN
++ | PMBUS_HAVE_STATUS_INPUT;
++ if (config & ADM1275_VIN_VOUT_SELECT)
++ info->func[0] |=
++ PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT;
++ break;
++ case adm1275:
++ if (config & ADM1275_VIN_VOUT_SELECT)
++ info->func[0] |=
++ PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT;
++ else
++ info->func[0] |=
++ PMBUS_HAVE_VIN | PMBUS_HAVE_STATUS_INPUT;
++ break;
++ case adm1276:
++ info->format[PSC_POWER] = direct;
++ info->func[0] |= PMBUS_HAVE_VIN | PMBUS_HAVE_PIN
++ | PMBUS_HAVE_STATUS_INPUT;
++ if (config & ADM1275_VIN_VOUT_SELECT)
++ info->func[0] |=
++ PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT;
++ if (config & ADM1275_VRANGE) {
++ info->m[PSC_POWER] = 6043;
++ info->b[PSC_POWER] = 0;
++ info->R[PSC_POWER] = -2;
++ } else {
++ info->m[PSC_POWER] = 2115;
++ info->b[PSC_POWER] = 0;
++ info->R[PSC_POWER] = -1;
++ }
++ break;
++ case adm1278:
++ info->format[PSC_POWER] = direct;
++ info->format[PSC_TEMPERATURE] = direct;
++ info->func[0] |= PMBUS_HAVE_VIN | PMBUS_HAVE_VOUT
++ | PMBUS_HAVE_STATUS_INPUT
++ | PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP;
++ info->m[PSC_POWER] = 6123 * r_sense / 1000;
++ info->b[PSC_POWER] = 0;
++ info->R[PSC_POWER] = -2;
++ info->m[PSC_TEMPERATURE] = 42;
++ info->b[PSC_TEMPERATURE] = 31880;
++ info->R[PSC_TEMPERATURE] = -1;
++ break;
++ }
++
++ return pmbus_do_probe(client, id, info);
++}
++
++static struct i2c_driver adm1275_driver = {
++ .driver = {
++ .name = "adm1275",
++ },
++ .probe = adm1275_probe,
++ .remove = pmbus_do_remove,
++ .id_table = adm1275_id,
++};
++
++module_i2c_driver(adm1275_driver);
++
++MODULE_AUTHOR("Guenter Roeck");
++MODULE_DESCRIPTION("PMBus driver for Analog Devices ADM1275 and compatibles");
++MODULE_LICENSE("GPL");
+diff --git a/drivers/hwmon/pmbus/lm25066.c b/drivers/hwmon/pmbus/lm25066.c
+new file mode 100644
+index 0000000..6a9d6ed
+--- /dev/null
++++ b/drivers/hwmon/pmbus/lm25066.c
+@@ -0,0 +1,457 @@
++/*
++ * Hardware monitoring driver for LM25056 / LM25066 / LM5064 / LM5066
++ *
++ * Copyright (c) 2011 Ericsson AB.
++ * Copyright (c) 2013 Guenter Roeck
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
++ */
++
++#include <linux/kernel.h>
++#include <linux/module.h>
++#include <linux/init.h>
++#include <linux/err.h>
++#include <linux/slab.h>
++#include <linux/i2c.h>
++#include "pmbus.h"
++
++enum chips { lm25056, lm25066, lm5064, lm5066 };
++
++#define LM25066_READ_VAUX 0xd0
++#define LM25066_MFR_READ_IIN 0xd1
++#define LM25066_MFR_READ_PIN 0xd2
++#define LM25066_MFR_IIN_OC_WARN_LIMIT 0xd3
++#define LM25066_MFR_PIN_OP_WARN_LIMIT 0xd4
++#define LM25066_READ_PIN_PEAK 0xd5
++#define LM25066_CLEAR_PIN_PEAK 0xd6
++#define LM25066_DEVICE_SETUP 0xd9
++#define LM25066_READ_AVG_VIN 0xdc
++#define LM25066_READ_AVG_VOUT 0xdd
++#define LM25066_READ_AVG_IIN 0xde
++#define LM25066_READ_AVG_PIN 0xdf
++
++#define LM25066_DEV_SETUP_CL (1 << 4) /* Current limit */
++
++/* LM25056 only */
++
++#define LM25056_VAUX_OV_WARN_LIMIT 0xe3
++#define LM25056_VAUX_UV_WARN_LIMIT 0xe4
++
++#define LM25056_MFR_STS_VAUX_OV_WARN (1 << 1)
++#define LM25056_MFR_STS_VAUX_UV_WARN (1 << 0)
++
++struct __coeff {
++ short m, b, R;
++};
++
++#define PSC_CURRENT_IN_L (PSC_NUM_CLASSES)
++#define PSC_POWER_L (PSC_NUM_CLASSES + 1)
++
++static struct __coeff lm25066_coeff[4][PSC_NUM_CLASSES + 2] = {
++ [lm25056] = {
++ [PSC_VOLTAGE_IN] = {
++ .m = 16296,
++ .R = -2,
++ },
++ [PSC_CURRENT_IN] = {
++ .m = 13797,
++ .R = -2,
++ },
++ [PSC_CURRENT_IN_L] = {
++ .m = 6726,
++ .R = -2,
++ },
++ [PSC_POWER] = {
++ .m = 5501,
++ .R = -3,
++ },
++ [PSC_POWER_L] = {
++ .m = 26882,
++ .R = -4,
++ },
++ [PSC_TEMPERATURE] = {
++ .m = 1580,
++ .b = -14500,
++ .R = -2,
++ },
++ },
++ [lm25066] = {
++ [PSC_VOLTAGE_IN] = {
++ .m = 22070,
++ .R = -2,
++ },
++ [PSC_VOLTAGE_OUT] = {
++ .m = 22070,
++ .R = -2,
++ },
++ [PSC_CURRENT_IN] = {
++ .m = 13661,
++ .R = -2,
++ },
++ [PSC_CURRENT_IN_L] = {
++ .m = 6852,
++ .R = -2,
++ },
++ [PSC_POWER] = {
++ .m = 736,
++ .R = -2,
++ },
++ [PSC_POWER_L] = {
++ .m = 369,
++ .R = -2,
++ },
++ [PSC_TEMPERATURE] = {
++ .m = 16,
++ },
++ },
++ [lm5064] = {
++ [PSC_VOLTAGE_IN] = {
++ .m = 4611,
++ .R = -2,
++ },
++ [PSC_VOLTAGE_OUT] = {
++ .m = 4621,
++ .R = -2,
++ },
++ [PSC_CURRENT_IN] = {
++ .m = 10742,
++ .R = -2,
++ },
++ [PSC_CURRENT_IN_L] = {
++ .m = 5456,
++ .R = -2,
++ },
++ [PSC_POWER] = {
++ .m = 1204,
++ .R = -3,
++ },
++ [PSC_POWER_L] = {
++ .m = 612,
++ .R = -3,
++ },
++ [PSC_TEMPERATURE] = {
++ .m = 16,
++ },
++ },
++ [lm5066] = {
++ [PSC_VOLTAGE_IN] = {
++ .m = 4587,
++ .R = -2,
++ },
++ [PSC_VOLTAGE_OUT] = {
++ .m = 4587,
++ .R = -2,
++ },
++ [PSC_CURRENT_IN] = {
++ .m = 10753,
++ .R = -2,
++ },
++ [PSC_CURRENT_IN_L] = {
++ .m = 5405,
++ .R = -2,
++ },
++ [PSC_POWER] = {
++ .m = 1204,
++ .R = -3,
++ },
++ [PSC_POWER_L] = {
++ .m = 605,
++ .R = -3,
++ },
++ [PSC_TEMPERATURE] = {
++ .m = 16,
++ },
++ },
++};
++
++struct lm25066_data {
++ int id;
++ struct pmbus_driver_info info;
++};
++
++#define to_lm25066_data(x) container_of(x, struct lm25066_data, info)
++
++static int lm25066_read_word_data(struct i2c_client *client, int page, int reg)
++{
++ const struct pmbus_driver_info *info = pmbus_get_driver_info(client);
++ const struct lm25066_data *data = to_lm25066_data(info);
++ int ret;
++
++ switch (reg) {
++ case PMBUS_VIRT_READ_VMON:
++ ret = pmbus_read_word_data(client, 0, LM25066_READ_VAUX);
++ if (ret < 0)
++ break;
++ /* Adjust returned value to match VIN coefficients */
++ switch (data->id) {
++ case lm25056:
++ /* VIN: 6.14 mV VAUX: 293 uV LSB */
++ ret = DIV_ROUND_CLOSEST(ret * 293, 6140);
++ break;
++ case lm25066:
++ /* VIN: 4.54 mV VAUX: 283.2 uV LSB */
++ ret = DIV_ROUND_CLOSEST(ret * 2832, 45400);
++ break;
++ case lm5064:
++ /* VIN: 4.53 mV VAUX: 700 uV LSB */
++ ret = DIV_ROUND_CLOSEST(ret * 70, 453);
++ break;
++ case lm5066:
++ /* VIN: 2.18 mV VAUX: 725 uV LSB */
++ ret = DIV_ROUND_CLOSEST(ret * 725, 2180);
++ break;
++ }
++ break;
++ case PMBUS_READ_IIN:
++ ret = pmbus_read_word_data(client, 0, LM25066_MFR_READ_IIN);
++ break;
++ case PMBUS_READ_PIN:
++ ret = pmbus_read_word_data(client, 0, LM25066_MFR_READ_PIN);
++ break;
++ case PMBUS_IIN_OC_WARN_LIMIT:
++ ret = pmbus_read_word_data(client, 0,
++ LM25066_MFR_IIN_OC_WARN_LIMIT);
++ break;
++ case PMBUS_PIN_OP_WARN_LIMIT:
++ ret = pmbus_read_word_data(client, 0,
++ LM25066_MFR_PIN_OP_WARN_LIMIT);
++ break;
++ case PMBUS_VIRT_READ_VIN_AVG:
++ ret = pmbus_read_word_data(client, 0, LM25066_READ_AVG_VIN);
++ break;
++ case PMBUS_VIRT_READ_VOUT_AVG:
++ ret = pmbus_read_word_data(client, 0, LM25066_READ_AVG_VOUT);
++ break;
++ case PMBUS_VIRT_READ_IIN_AVG:
++ ret = pmbus_read_word_data(client, 0, LM25066_READ_AVG_IIN);
++ break;
++ case PMBUS_VIRT_READ_PIN_AVG:
++ ret = pmbus_read_word_data(client, 0, LM25066_READ_AVG_PIN);
++ break;
++ case PMBUS_VIRT_READ_PIN_MAX:
++ ret = pmbus_read_word_data(client, 0, LM25066_READ_PIN_PEAK);
++ break;
++ case PMBUS_VIRT_RESET_PIN_HISTORY:
++ ret = 0;
++ break;
++ default:
++ ret = -ENODATA;
++ break;
++ }
++ return ret;
++}
++
++static int lm25056_read_word_data(struct i2c_client *client, int page, int reg)
++{
++ int ret;
++
++ switch (reg) {
++ case PMBUS_VIRT_VMON_UV_WARN_LIMIT:
++ ret = pmbus_read_word_data(client, 0,
++ LM25056_VAUX_UV_WARN_LIMIT);
++ if (ret < 0)
++ break;
++ /* Adjust returned value to match VIN coefficients */
++ ret = DIV_ROUND_CLOSEST(ret * 293, 6140);
++ break;
++ case PMBUS_VIRT_VMON_OV_WARN_LIMIT:
++ ret = pmbus_read_word_data(client, 0,
++ LM25056_VAUX_OV_WARN_LIMIT);
++ if (ret < 0)
++ break;
++ /* Adjust returned value to match VIN coefficients */
++ ret = DIV_ROUND_CLOSEST(ret * 293, 6140);
++ break;
++ default:
++ ret = lm25066_read_word_data(client, page, reg);
++ break;
++ }
++ return ret;
++}
++
++static int lm25056_read_byte_data(struct i2c_client *client, int page, int reg)
++{
++ int ret, s;
++
++ switch (reg) {
++ case PMBUS_VIRT_STATUS_VMON:
++ ret = pmbus_read_byte_data(client, 0,
++ PMBUS_STATUS_MFR_SPECIFIC);
++ if (ret < 0)
++ break;
++ s = 0;
++ if (ret & LM25056_MFR_STS_VAUX_UV_WARN)
++ s |= PB_VOLTAGE_UV_WARNING;
++ if (ret & LM25056_MFR_STS_VAUX_OV_WARN)
++ s |= PB_VOLTAGE_OV_WARNING;
++ ret = s;
++ break;
++ default:
++ ret = -ENODATA;
++ break;
++ }
++ return ret;
++}
++
++static int lm25066_write_word_data(struct i2c_client *client, int page, int reg,
++ u16 word)
++{
++ int ret;
++
++ switch (reg) {
++ case PMBUS_VOUT_UV_WARN_LIMIT:
++ case PMBUS_OT_FAULT_LIMIT:
++ case PMBUS_OT_WARN_LIMIT:
++ case PMBUS_VIN_UV_WARN_LIMIT:
++ case PMBUS_VIN_OV_WARN_LIMIT:
++ word = ((s16)word < 0) ? 0 : clamp_val(word, 0, 0x0fff);
++ ret = pmbus_write_word_data(client, 0, reg, word);
++ pmbus_clear_cache(client);
++ break;
++ case PMBUS_IIN_OC_WARN_LIMIT:
++ word = ((s16)word < 0) ? 0 : clamp_val(word, 0, 0x0fff);
++ ret = pmbus_write_word_data(client, 0,
++ LM25066_MFR_IIN_OC_WARN_LIMIT,
++ word);
++ pmbus_clear_cache(client);
++ break;
++ case PMBUS_PIN_OP_WARN_LIMIT:
++ word = ((s16)word < 0) ? 0 : clamp_val(word, 0, 0x0fff);
++ ret = pmbus_write_word_data(client, 0,
++ LM25066_MFR_PIN_OP_WARN_LIMIT,
++ word);
++ pmbus_clear_cache(client);
++ break;
++ case PMBUS_VIRT_VMON_UV_WARN_LIMIT:
++ /* Adjust from VIN coefficients (for LM25056) */
++ word = DIV_ROUND_CLOSEST((int)word * 6140, 293);
++ word = ((s16)word < 0) ? 0 : clamp_val(word, 0, 0x0fff);
++ ret = pmbus_write_word_data(client, 0,
++ LM25056_VAUX_UV_WARN_LIMIT, word);
++ pmbus_clear_cache(client);
++ break;
++ case PMBUS_VIRT_VMON_OV_WARN_LIMIT:
++ /* Adjust from VIN coefficients (for LM25056) */
++ word = DIV_ROUND_CLOSEST((int)word * 6140, 293);
++ word = ((s16)word < 0) ? 0 : clamp_val(word, 0, 0x0fff);
++ ret = pmbus_write_word_data(client, 0,
++ LM25056_VAUX_OV_WARN_LIMIT, word);
++ pmbus_clear_cache(client);
++ break;
++ case PMBUS_VIRT_RESET_PIN_HISTORY:
++ ret = pmbus_write_byte(client, 0, LM25066_CLEAR_PIN_PEAK);
++ break;
++ default:
++ ret = -ENODATA;
++ break;
++ }
++ return ret;
++}
++
++static int lm25066_probe(struct i2c_client *client,
++ const struct i2c_device_id *id)
++{
++ int config;
++ struct lm25066_data *data;
++ struct pmbus_driver_info *info;
++ struct __coeff *coeff;
++
++ if (!i2c_check_functionality(client->adapter,
++ I2C_FUNC_SMBUS_READ_BYTE_DATA))
++ return -ENODEV;
++
++ data = devm_kzalloc(&client->dev, sizeof(struct lm25066_data),
++ GFP_KERNEL);
++ if (!data)
++ return -ENOMEM;
++
++ config = i2c_smbus_read_byte_data(client, LM25066_DEVICE_SETUP);
++ if (config < 0)
++ return config;
++
++ data->id = id->driver_data;
++ info = &data->info;
++
++ info->pages = 1;
++ info->format[PSC_VOLTAGE_IN] = direct;
++ info->format[PSC_VOLTAGE_OUT] = direct;
++ info->format[PSC_CURRENT_IN] = direct;
++ info->format[PSC_TEMPERATURE] = direct;
++ info->format[PSC_POWER] = direct;
++
++ info->func[0] = PMBUS_HAVE_VIN | PMBUS_HAVE_VMON
++ | PMBUS_HAVE_PIN | PMBUS_HAVE_IIN | PMBUS_HAVE_STATUS_INPUT
++ | PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP;
++
++ if (data->id == lm25056) {
++ info->func[0] |= PMBUS_HAVE_STATUS_VMON;
++ info->read_word_data = lm25056_read_word_data;
++ info->read_byte_data = lm25056_read_byte_data;
++ } else {
++ info->func[0] |= PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT;
++ info->read_word_data = lm25066_read_word_data;
++ }
++ info->write_word_data = lm25066_write_word_data;
++
++ coeff = &lm25066_coeff[data->id][0];
++ info->m[PSC_TEMPERATURE] = coeff[PSC_TEMPERATURE].m;
++ info->b[PSC_TEMPERATURE] = coeff[PSC_TEMPERATURE].b;
++ info->R[PSC_TEMPERATURE] = coeff[PSC_TEMPERATURE].R;
++ info->m[PSC_VOLTAGE_IN] = coeff[PSC_VOLTAGE_IN].m;
++ info->b[PSC_VOLTAGE_IN] = coeff[PSC_VOLTAGE_IN].b;
++ info->R[PSC_VOLTAGE_IN] = coeff[PSC_VOLTAGE_IN].R;
++ info->m[PSC_VOLTAGE_OUT] = coeff[PSC_VOLTAGE_OUT].m;
++ info->b[PSC_VOLTAGE_OUT] = coeff[PSC_VOLTAGE_OUT].b;
++ info->R[PSC_VOLTAGE_OUT] = coeff[PSC_VOLTAGE_OUT].R;
++ info->b[PSC_CURRENT_IN] = coeff[PSC_CURRENT_IN].b;
++ info->R[PSC_CURRENT_IN] = coeff[PSC_CURRENT_IN].R;
++ info->b[PSC_POWER] = coeff[PSC_POWER].b;
++ info->R[PSC_POWER] = coeff[PSC_POWER].R;
++ if (config & LM25066_DEV_SETUP_CL) {
++ info->m[PSC_CURRENT_IN] = coeff[PSC_CURRENT_IN_L].m;
++ info->m[PSC_POWER] = coeff[PSC_POWER_L].m;
++ } else {
++ info->m[PSC_CURRENT_IN] = coeff[PSC_CURRENT_IN].m;
++ info->m[PSC_POWER] = coeff[PSC_POWER].m;
++ }
++
++ return pmbus_do_probe(client, id, info);
++}
++
++static const struct i2c_device_id lm25066_id[] = {
++ {"lm25056", lm25056},
++ {"lm25066", lm25066},
++ {"lm5064", lm5064},
++ {"lm5066", lm5066},
++ { }
++};
++
++MODULE_DEVICE_TABLE(i2c, lm25066_id);
++
++/* This is the driver that will be inserted */
++static struct i2c_driver lm25066_driver = {
++ .driver = {
++ .name = "lm25066",
++ },
++ .probe = lm25066_probe,
++ .remove = pmbus_do_remove,
++ .id_table = lm25066_id,
++};
++
++module_i2c_driver(lm25066_driver);
++
++MODULE_AUTHOR("Guenter Roeck");
++MODULE_DESCRIPTION("PMBus driver for LM25056/LM25066/LM5064/LM5066");
++MODULE_LICENSE("GPL");
+diff --git a/drivers/hwmon/pmbus/ltc2978.c b/drivers/hwmon/pmbus/ltc2978.c
+new file mode 100644
+index 0000000..586a89e
+--- /dev/null
++++ b/drivers/hwmon/pmbus/ltc2978.c
+@@ -0,0 +1,496 @@
++/*
++ * Hardware monitoring driver for LTC2974, LTC2978, LTC3880, and LTC3883
++ *
++ * Copyright (c) 2011 Ericsson AB.
++ * Copyright (c) 2013 Guenter Roeck
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
++ */
++
++#include <linux/kernel.h>
++#include <linux/module.h>
++#include <linux/init.h>
++#include <linux/err.h>
++#include <linux/slab.h>
++#include <linux/i2c.h>
++#include "pmbus.h"
++
++enum chips { ltc2974, ltc2978, ltc3880, ltc3883 };
++
++/* Common for all chips */
++#define LTC2978_MFR_VOUT_PEAK 0xdd
++#define LTC2978_MFR_VIN_PEAK 0xde
++#define LTC2978_MFR_TEMPERATURE_PEAK 0xdf
++#define LTC2978_MFR_SPECIAL_ID 0xe7
++
++/* LTC2974 and LTC2978 */
++#define LTC2978_MFR_VOUT_MIN 0xfb
++#define LTC2978_MFR_VIN_MIN 0xfc
++#define LTC2978_MFR_TEMPERATURE_MIN 0xfd
++
++/* LTC2974 only */
++#define LTC2974_MFR_IOUT_PEAK 0xd7
++#define LTC2974_MFR_IOUT_MIN 0xd8
++
++/* LTC3880 and LTC3883 */
++#define LTC3880_MFR_IOUT_PEAK 0xd7
++#define LTC3880_MFR_CLEAR_PEAKS 0xe3
++#define LTC3880_MFR_TEMPERATURE2_PEAK 0xf4
++
++/* LTC3883 only */
++#define LTC3883_MFR_IIN_PEAK 0xe1
++
++#define LTC2974_ID 0x0212
++#define LTC2978_ID_REV1 0x0121
++#define LTC2978_ID_REV2 0x0122
++#define LTC3880_ID 0x4000
++#define LTC3880_ID_MASK 0xff00
++#define LTC3883_ID 0x4300
++#define LTC3883_ID_MASK 0xff00
++
++#define LTC2974_NUM_PAGES 4
++#define LTC2978_NUM_PAGES 8
++#define LTC3880_NUM_PAGES 2
++#define LTC3883_NUM_PAGES 1
++
++/*
++ * LTC2978 clears peak data whenever the CLEAR_FAULTS command is executed, which
++ * happens pretty much each time chip data is updated. Raw peak data therefore
++ * does not provide much value. To be able to provide useful peak data, keep an
++ * internal cache of measured peak data, which is only cleared if an explicit
++ * "clear peak" command is executed for the sensor in question.
++ */
++
++struct ltc2978_data {
++ enum chips id;
++ u16 vin_min, vin_max;
++ u16 temp_min[LTC2974_NUM_PAGES], temp_max[LTC2974_NUM_PAGES];
++ u16 vout_min[LTC2978_NUM_PAGES], vout_max[LTC2978_NUM_PAGES];
++ u16 iout_min[LTC2974_NUM_PAGES], iout_max[LTC2974_NUM_PAGES];
++ u16 iin_max;
++ u16 temp2_max;
++ struct pmbus_driver_info info;
++};
++
++#define to_ltc2978_data(x) container_of(x, struct ltc2978_data, info)
++
++static inline int lin11_to_val(int data)
++{
++ s16 e = ((s16)data) >> 11;
++ s32 m = (((s16)(data << 5)) >> 5);
++
++ /*
++ * mantissa is 10 bit + sign, exponent adds up to 15 bit.
++ * Add 6 bit to exponent for maximum accuracy (10 + 15 + 6 = 31).
++ */
++ e += 6;
++ return (e < 0 ? m >> -e : m << e);
++}
++
++static int ltc2978_read_word_data_common(struct i2c_client *client, int page,
++ int reg)
++{
++ const struct pmbus_driver_info *info = pmbus_get_driver_info(client);
++ struct ltc2978_data *data = to_ltc2978_data(info);
++ int ret;
++
++ switch (reg) {
++ case PMBUS_VIRT_READ_VIN_MAX:
++ ret = pmbus_read_word_data(client, page, LTC2978_MFR_VIN_PEAK);
++ if (ret >= 0) {
++ if (lin11_to_val(ret) > lin11_to_val(data->vin_max))
++ data->vin_max = ret;
++ ret = data->vin_max;
++ }
++ break;
++ case PMBUS_VIRT_READ_VOUT_MAX:
++ ret = pmbus_read_word_data(client, page, LTC2978_MFR_VOUT_PEAK);
++ if (ret >= 0) {
++ /*
++ * VOUT is 16 bit unsigned with fixed exponent,
++ * so we can compare it directly
++ */
++ if (ret > data->vout_max[page])
++ data->vout_max[page] = ret;
++ ret = data->vout_max[page];
++ }
++ break;
++ case PMBUS_VIRT_READ_TEMP_MAX:
++ ret = pmbus_read_word_data(client, page,
++ LTC2978_MFR_TEMPERATURE_PEAK);
++ if (ret >= 0) {
++ if (lin11_to_val(ret)
++ > lin11_to_val(data->temp_max[page]))
++ data->temp_max[page] = ret;
++ ret = data->temp_max[page];
++ }
++ break;
++ case PMBUS_VIRT_RESET_VOUT_HISTORY:
++ case PMBUS_VIRT_RESET_VIN_HISTORY:
++ case PMBUS_VIRT_RESET_TEMP_HISTORY:
++ ret = 0;
++ break;
++ default:
++ ret = -ENODATA;
++ break;
++ }
++ return ret;
++}
++
++static int ltc2978_read_word_data(struct i2c_client *client, int page, int reg)
++{
++ const struct pmbus_driver_info *info = pmbus_get_driver_info(client);
++ struct ltc2978_data *data = to_ltc2978_data(info);
++ int ret;
++
++ switch (reg) {
++ case PMBUS_VIRT_READ_VIN_MIN:
++ ret = pmbus_read_word_data(client, page, LTC2978_MFR_VIN_MIN);
++ if (ret >= 0) {
++ if (lin11_to_val(ret) < lin11_to_val(data->vin_min))
++ data->vin_min = ret;
++ ret = data->vin_min;
++ }
++ break;
++ case PMBUS_VIRT_READ_VOUT_MIN:
++ ret = pmbus_read_word_data(client, page, LTC2978_MFR_VOUT_MIN);
++ if (ret >= 0) {
++ /*
++ * VOUT_MIN is known to not be supported on some lots
++ * of LTC2978 revision 1, and will return the maximum
++ * possible voltage if read. If VOUT_MAX is valid and
++ * lower than the reading of VOUT_MIN, use it instead.
++ */
++ if (data->vout_max[page] && ret > data->vout_max[page])
++ ret = data->vout_max[page];
++ if (ret < data->vout_min[page])
++ data->vout_min[page] = ret;
++ ret = data->vout_min[page];
++ }
++ break;
++ case PMBUS_VIRT_READ_TEMP_MIN:
++ ret = pmbus_read_word_data(client, page,
++ LTC2978_MFR_TEMPERATURE_MIN);
++ if (ret >= 0) {
++ if (lin11_to_val(ret)
++ < lin11_to_val(data->temp_min[page]))
++ data->temp_min[page] = ret;
++ ret = data->temp_min[page];
++ }
++ break;
++ case PMBUS_VIRT_READ_IOUT_MAX:
++ case PMBUS_VIRT_RESET_IOUT_HISTORY:
++ case PMBUS_VIRT_READ_TEMP2_MAX:
++ case PMBUS_VIRT_RESET_TEMP2_HISTORY:
++ ret = -ENXIO;
++ break;
++ default:
++ ret = ltc2978_read_word_data_common(client, page, reg);
++ break;
++ }
++ return ret;
++}
++
++static int ltc2974_read_word_data(struct i2c_client *client, int page, int reg)
++{
++ const struct pmbus_driver_info *info = pmbus_get_driver_info(client);
++ struct ltc2978_data *data = to_ltc2978_data(info);
++ int ret;
++
++ switch (reg) {
++ case PMBUS_VIRT_READ_IOUT_MAX:
++ ret = pmbus_read_word_data(client, page, LTC2974_MFR_IOUT_PEAK);
++ if (ret >= 0) {
++ if (lin11_to_val(ret)
++ > lin11_to_val(data->iout_max[page]))
++ data->iout_max[page] = ret;
++ ret = data->iout_max[page];
++ }
++ break;
++ case PMBUS_VIRT_READ_IOUT_MIN:
++ ret = pmbus_read_word_data(client, page, LTC2974_MFR_IOUT_MIN);
++ if (ret >= 0) {
++ if (lin11_to_val(ret)
++ < lin11_to_val(data->iout_min[page]))
++ data->iout_min[page] = ret;
++ ret = data->iout_min[page];
++ }
++ break;
++ case PMBUS_VIRT_RESET_IOUT_HISTORY:
++ ret = 0;
++ break;
++ default:
++ ret = ltc2978_read_word_data(client, page, reg);
++ break;
++ }
++ return ret;
++}
++
++static int ltc3880_read_word_data(struct i2c_client *client, int page, int reg)
++{
++ const struct pmbus_driver_info *info = pmbus_get_driver_info(client);
++ struct ltc2978_data *data = to_ltc2978_data(info);
++ int ret;
++
++ switch (reg) {
++ case PMBUS_VIRT_READ_IOUT_MAX:
++ ret = pmbus_read_word_data(client, page, LTC3880_MFR_IOUT_PEAK);
++ if (ret >= 0) {
++ if (lin11_to_val(ret)
++ > lin11_to_val(data->iout_max[page]))
++ data->iout_max[page] = ret;
++ ret = data->iout_max[page];
++ }
++ break;
++ case PMBUS_VIRT_READ_TEMP2_MAX:
++ ret = pmbus_read_word_data(client, page,
++ LTC3880_MFR_TEMPERATURE2_PEAK);
++ if (ret >= 0) {
++ if (lin11_to_val(ret) > lin11_to_val(data->temp2_max))
++ data->temp2_max = ret;
++ ret = data->temp2_max;
++ }
++ break;
++ case PMBUS_VIRT_READ_VIN_MIN:
++ case PMBUS_VIRT_READ_VOUT_MIN:
++ case PMBUS_VIRT_READ_TEMP_MIN:
++ ret = -ENXIO;
++ break;
++ case PMBUS_VIRT_RESET_IOUT_HISTORY:
++ case PMBUS_VIRT_RESET_TEMP2_HISTORY:
++ ret = 0;
++ break;
++ default:
++ ret = ltc2978_read_word_data_common(client, page, reg);
++ break;
++ }
++ return ret;
++}
++
++static int ltc3883_read_word_data(struct i2c_client *client, int page, int reg)
++{
++ const struct pmbus_driver_info *info = pmbus_get_driver_info(client);
++ struct ltc2978_data *data = to_ltc2978_data(info);
++ int ret;
++
++ switch (reg) {
++ case PMBUS_VIRT_READ_IIN_MAX:
++ ret = pmbus_read_word_data(client, page, LTC3883_MFR_IIN_PEAK);
++ if (ret >= 0) {
++ if (lin11_to_val(ret)
++ > lin11_to_val(data->iin_max))
++ data->iin_max = ret;
++ ret = data->iin_max;
++ }
++ break;
++ case PMBUS_VIRT_RESET_IIN_HISTORY:
++ ret = 0;
++ break;
++ default:
++ ret = ltc3880_read_word_data(client, page, reg);
++ break;
++ }
++ return ret;
++}
++
++static int ltc2978_clear_peaks(struct i2c_client *client, int page,
++ enum chips id)
++{
++ int ret;
++
++ if (id == ltc3880 || id == ltc3883)
++ ret = pmbus_write_byte(client, 0, LTC3880_MFR_CLEAR_PEAKS);
++ else
++ ret = pmbus_write_byte(client, page, PMBUS_CLEAR_FAULTS);
++
++ return ret;
++}
++
++static int ltc2978_write_word_data(struct i2c_client *client, int page,
++ int reg, u16 word)
++{
++ const struct pmbus_driver_info *info = pmbus_get_driver_info(client);
++ struct ltc2978_data *data = to_ltc2978_data(info);
++ int ret;
++
++ switch (reg) {
++ case PMBUS_VIRT_RESET_IIN_HISTORY:
++ data->iin_max = 0x7c00;
++ ret = ltc2978_clear_peaks(client, page, data->id);
++ break;
++ case PMBUS_VIRT_RESET_IOUT_HISTORY:
++ data->iout_max[page] = 0x7c00;
++ data->iout_min[page] = 0xfbff;
++ ret = ltc2978_clear_peaks(client, page, data->id);
++ break;
++ case PMBUS_VIRT_RESET_TEMP2_HISTORY:
++ data->temp2_max = 0x7c00;
++ ret = ltc2978_clear_peaks(client, page, data->id);
++ break;
++ case PMBUS_VIRT_RESET_VOUT_HISTORY:
++ data->vout_min[page] = 0xffff;
++ data->vout_max[page] = 0;
++ ret = ltc2978_clear_peaks(client, page, data->id);
++ break;
++ case PMBUS_VIRT_RESET_VIN_HISTORY:
++ data->vin_min = 0x7bff;
++ data->vin_max = 0x7c00;
++ ret = ltc2978_clear_peaks(client, page, data->id);
++ break;
++ case PMBUS_VIRT_RESET_TEMP_HISTORY:
++ data->temp_min[page] = 0x7bff;
++ data->temp_max[page] = 0x7c00;
++ ret = ltc2978_clear_peaks(client, page, data->id);
++ break;
++ default:
++ ret = -ENODATA;
++ break;
++ }
++ return ret;
++}
++
++static const struct i2c_device_id ltc2978_id[] = {
++ {"ltc2974", ltc2974},
++ {"ltc2978", ltc2978},
++ {"ltc3880", ltc3880},
++ {"ltc3883", ltc3883},
++ {}
++};
++MODULE_DEVICE_TABLE(i2c, ltc2978_id);
++
++static int ltc2978_probe(struct i2c_client *client,
++ const struct i2c_device_id *id)
++{
++ int chip_id, i;
++ struct ltc2978_data *data;
++ struct pmbus_driver_info *info;
++
++ if (!i2c_check_functionality(client->adapter,
++ I2C_FUNC_SMBUS_READ_WORD_DATA))
++ return -ENODEV;
++
++ data = devm_kzalloc(&client->dev, sizeof(struct ltc2978_data),
++ GFP_KERNEL);
++ if (!data)
++ return -ENOMEM;
++
++ chip_id = i2c_smbus_read_word_data(client, LTC2978_MFR_SPECIAL_ID);
++ if (chip_id < 0)
++ return chip_id;
++
++ if (chip_id == LTC2974_ID) {
++ data->id = ltc2974;
++ } else if (chip_id == LTC2978_ID_REV1 || chip_id == LTC2978_ID_REV2) {
++ data->id = ltc2978;
++ } else if ((chip_id & LTC3880_ID_MASK) == LTC3880_ID) {
++ data->id = ltc3880;
++ } else if ((chip_id & LTC3883_ID_MASK) == LTC3883_ID) {
++ data->id = ltc3883;
++ } else {
++ dev_err(&client->dev, "Unsupported chip ID 0x%x\n", chip_id);
++ return -ENODEV;
++ }
++ if (data->id != id->driver_data)
++ dev_warn(&client->dev,
++ "Device mismatch: Configured %s, detected %s\n",
++ id->name,
++ ltc2978_id[data->id].name);
++
++ info = &data->info;
++ info->write_word_data = ltc2978_write_word_data;
++
++ data->vin_min = 0x7bff;
++ data->vin_max = 0x7c00;
++ for (i = 0; i < ARRAY_SIZE(data->vout_min); i++)
++ data->vout_min[i] = 0xffff;
++ for (i = 0; i < ARRAY_SIZE(data->iout_min); i++)
++ data->iout_min[i] = 0xfbff;
++ for (i = 0; i < ARRAY_SIZE(data->iout_max); i++)
++ data->iout_max[i] = 0x7c00;
++ for (i = 0; i < ARRAY_SIZE(data->temp_min); i++)
++ data->temp_min[i] = 0x7bff;
++ for (i = 0; i < ARRAY_SIZE(data->temp_max); i++)
++ data->temp_max[i] = 0x7c00;
++ data->temp2_max = 0x7c00;
++
++ switch (data->id) {
++ case ltc2974:
++ info->read_word_data = ltc2974_read_word_data;
++ info->pages = LTC2974_NUM_PAGES;
++ info->func[0] = PMBUS_HAVE_VIN | PMBUS_HAVE_STATUS_INPUT
++ | PMBUS_HAVE_TEMP2;
++ for (i = 0; i < info->pages; i++) {
++ info->func[i] |= PMBUS_HAVE_VOUT
++ | PMBUS_HAVE_STATUS_VOUT | PMBUS_HAVE_POUT
++ | PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP
++ | PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT;
++ }
++ break;
++ case ltc2978:
++ info->read_word_data = ltc2978_read_word_data;
++ info->pages = LTC2978_NUM_PAGES;
++ info->func[0] = PMBUS_HAVE_VIN | PMBUS_HAVE_STATUS_INPUT
++ | PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT
++ | PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP;
++ for (i = 1; i < LTC2978_NUM_PAGES; i++) {
++ info->func[i] = PMBUS_HAVE_VOUT
++ | PMBUS_HAVE_STATUS_VOUT;
++ }
++ break;
++ case ltc3880:
++ info->read_word_data = ltc3880_read_word_data;
++ info->pages = LTC3880_NUM_PAGES;
++ info->func[0] = PMBUS_HAVE_VIN | PMBUS_HAVE_IIN
++ | PMBUS_HAVE_STATUS_INPUT
++ | PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT
++ | PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT
++ | PMBUS_HAVE_POUT | PMBUS_HAVE_TEMP
++ | PMBUS_HAVE_TEMP2 | PMBUS_HAVE_STATUS_TEMP;
++ info->func[1] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT
++ | PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT
++ | PMBUS_HAVE_POUT
++ | PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP;
++ break;
++ case ltc3883:
++ info->read_word_data = ltc3883_read_word_data;
++ info->pages = LTC3883_NUM_PAGES;
++ info->func[0] = PMBUS_HAVE_VIN | PMBUS_HAVE_IIN
++ | PMBUS_HAVE_STATUS_INPUT
++ | PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT
++ | PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT
++ | PMBUS_HAVE_PIN | PMBUS_HAVE_POUT | PMBUS_HAVE_TEMP
++ | PMBUS_HAVE_TEMP2 | PMBUS_HAVE_STATUS_TEMP;
++ break;
++ default:
++ return -ENODEV;
++ }
++ return pmbus_do_probe(client, id, info);
++}
++
++/* This is the driver that will be inserted */
++static struct i2c_driver ltc2978_driver = {
++ .driver = {
++ .name = "ltc2978",
++ },
++ .probe = ltc2978_probe,
++ .remove = pmbus_do_remove,
++ .id_table = ltc2978_id,
++};
++
++module_i2c_driver(ltc2978_driver);
++
++MODULE_AUTHOR("Guenter Roeck");
++MODULE_DESCRIPTION("PMBus driver for LTC2974, LTC2978, LTC3880, and LTC3883");
++MODULE_LICENSE("GPL");
+diff --git a/drivers/hwmon/pmbus/max16064.c b/drivers/hwmon/pmbus/max16064.c
+new file mode 100644
+index 0000000..fa237a3
+--- /dev/null
++++ b/drivers/hwmon/pmbus/max16064.c
+@@ -0,0 +1,127 @@
++/*
++ * Hardware monitoring driver for Maxim MAX16064
++ *
++ * Copyright (c) 2011 Ericsson AB.
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
++ */
++
++#include <linux/kernel.h>
++#include <linux/module.h>
++#include <linux/init.h>
++#include <linux/err.h>
++#include <linux/i2c.h>
++#include "pmbus.h"
++
++#define MAX16064_MFR_VOUT_PEAK 0xd4
++#define MAX16064_MFR_TEMPERATURE_PEAK 0xd6
++
++static int max16064_read_word_data(struct i2c_client *client, int page, int reg)
++{
++ int ret;
++
++ switch (reg) {
++ case PMBUS_VIRT_READ_VOUT_MAX:
++ ret = pmbus_read_word_data(client, page,
++ MAX16064_MFR_VOUT_PEAK);
++ break;
++ case PMBUS_VIRT_READ_TEMP_MAX:
++ ret = pmbus_read_word_data(client, page,
++ MAX16064_MFR_TEMPERATURE_PEAK);
++ break;
++ case PMBUS_VIRT_RESET_VOUT_HISTORY:
++ case PMBUS_VIRT_RESET_TEMP_HISTORY:
++ ret = 0;
++ break;
++ default:
++ ret = -ENODATA;
++ break;
++ }
++ return ret;
++}
++
++static int max16064_write_word_data(struct i2c_client *client, int page,
++ int reg, u16 word)
++{
++ int ret;
++
++ switch (reg) {
++ case PMBUS_VIRT_RESET_VOUT_HISTORY:
++ ret = pmbus_write_word_data(client, page,
++ MAX16064_MFR_VOUT_PEAK, 0);
++ break;
++ case PMBUS_VIRT_RESET_TEMP_HISTORY:
++ ret = pmbus_write_word_data(client, page,
++ MAX16064_MFR_TEMPERATURE_PEAK,
++ 0xffff);
++ break;
++ default:
++ ret = -ENODATA;
++ break;
++ }
++ return ret;
++}
++
++static struct pmbus_driver_info max16064_info = {
++ .pages = 4,
++ .format[PSC_VOLTAGE_IN] = direct,
++ .format[PSC_VOLTAGE_OUT] = direct,
++ .format[PSC_TEMPERATURE] = direct,
++ .m[PSC_VOLTAGE_IN] = 19995,
++ .b[PSC_VOLTAGE_IN] = 0,
++ .R[PSC_VOLTAGE_IN] = -1,
++ .m[PSC_VOLTAGE_OUT] = 19995,
++ .b[PSC_VOLTAGE_OUT] = 0,
++ .R[PSC_VOLTAGE_OUT] = -1,
++ .m[PSC_TEMPERATURE] = -7612,
++ .b[PSC_TEMPERATURE] = 335,
++ .R[PSC_TEMPERATURE] = -3,
++ .func[0] = PMBUS_HAVE_VOUT | PMBUS_HAVE_TEMP
++ | PMBUS_HAVE_STATUS_VOUT | PMBUS_HAVE_STATUS_TEMP,
++ .func[1] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT,
++ .func[2] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT,
++ .func[3] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT,
++ .read_word_data = max16064_read_word_data,
++ .write_word_data = max16064_write_word_data,
++};
++
++static int max16064_probe(struct i2c_client *client,
++ const struct i2c_device_id *id)
++{
++ return pmbus_do_probe(client, id, &max16064_info);
++}
++
++static const struct i2c_device_id max16064_id[] = {
++ {"max16064", 0},
++ {}
++};
++
++MODULE_DEVICE_TABLE(i2c, max16064_id);
++
++/* This is the driver that will be inserted */
++static struct i2c_driver max16064_driver = {
++ .driver = {
++ .name = "max16064",
++ },
++ .probe = max16064_probe,
++ .remove = pmbus_do_remove,
++ .id_table = max16064_id,
++};
++
++module_i2c_driver(max16064_driver);
++
++MODULE_AUTHOR("Guenter Roeck");
++MODULE_DESCRIPTION("PMBus driver for Maxim MAX16064");
++MODULE_LICENSE("GPL");
+diff --git a/drivers/hwmon/pmbus/max34440.c b/drivers/hwmon/pmbus/max34440.c
+new file mode 100644
+index 0000000..7e930c3
+--- /dev/null
++++ b/drivers/hwmon/pmbus/max34440.c
+@@ -0,0 +1,435 @@
++/*
++ * Hardware monitoring driver for Maxim MAX34440/MAX34441
++ *
++ * Copyright (c) 2011 Ericsson AB.
++ * Copyright (c) 2012 Guenter Roeck
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
++ */
++
++#include <linux/kernel.h>
++#include <linux/module.h>
++#include <linux/init.h>
++#include <linux/err.h>
++#include <linux/i2c.h>
++#include "pmbus.h"
++
++enum chips { max34440, max34441, max34446, max34460, max34461 };
++
++#define MAX34440_MFR_VOUT_PEAK 0xd4
++#define MAX34440_MFR_IOUT_PEAK 0xd5
++#define MAX34440_MFR_TEMPERATURE_PEAK 0xd6
++#define MAX34440_MFR_VOUT_MIN 0xd7
++
++#define MAX34446_MFR_POUT_PEAK 0xe0
++#define MAX34446_MFR_POUT_AVG 0xe1
++#define MAX34446_MFR_IOUT_AVG 0xe2
++#define MAX34446_MFR_TEMPERATURE_AVG 0xe3
++
++#define MAX34440_STATUS_OC_WARN (1 << 0)
++#define MAX34440_STATUS_OC_FAULT (1 << 1)
++#define MAX34440_STATUS_OT_FAULT (1 << 5)
++#define MAX34440_STATUS_OT_WARN (1 << 6)
++
++struct max34440_data {
++ int id;
++ struct pmbus_driver_info info;
++};
++
++#define to_max34440_data(x) container_of(x, struct max34440_data, info)
++
++static int max34440_read_word_data(struct i2c_client *client, int page, int reg)
++{
++ int ret;
++ const struct pmbus_driver_info *info = pmbus_get_driver_info(client);
++ const struct max34440_data *data = to_max34440_data(info);
++
++ switch (reg) {
++ case PMBUS_VIRT_READ_VOUT_MIN:
++ ret = pmbus_read_word_data(client, page,
++ MAX34440_MFR_VOUT_MIN);
++ break;
++ case PMBUS_VIRT_READ_VOUT_MAX:
++ ret = pmbus_read_word_data(client, page,
++ MAX34440_MFR_VOUT_PEAK);
++ break;
++ case PMBUS_VIRT_READ_IOUT_AVG:
++ if (data->id != max34446)
++ return -ENXIO;
++ ret = pmbus_read_word_data(client, page,
++ MAX34446_MFR_IOUT_AVG);
++ break;
++ case PMBUS_VIRT_READ_IOUT_MAX:
++ ret = pmbus_read_word_data(client, page,
++ MAX34440_MFR_IOUT_PEAK);
++ break;
++ case PMBUS_VIRT_READ_POUT_AVG:
++ if (data->id != max34446)
++ return -ENXIO;
++ ret = pmbus_read_word_data(client, page,
++ MAX34446_MFR_POUT_AVG);
++ break;
++ case PMBUS_VIRT_READ_POUT_MAX:
++ if (data->id != max34446)
++ return -ENXIO;
++ ret = pmbus_read_word_data(client, page,
++ MAX34446_MFR_POUT_PEAK);
++ break;
++ case PMBUS_VIRT_READ_TEMP_AVG:
++ if (data->id != max34446 && data->id != max34460 &&
++ data->id != max34461)
++ return -ENXIO;
++ ret = pmbus_read_word_data(client, page,
++ MAX34446_MFR_TEMPERATURE_AVG);
++ break;
++ case PMBUS_VIRT_READ_TEMP_MAX:
++ ret = pmbus_read_word_data(client, page,
++ MAX34440_MFR_TEMPERATURE_PEAK);
++ break;
++ case PMBUS_VIRT_RESET_POUT_HISTORY:
++ if (data->id != max34446)
++ return -ENXIO;
++ ret = 0;
++ break;
++ case PMBUS_VIRT_RESET_VOUT_HISTORY:
++ case PMBUS_VIRT_RESET_IOUT_HISTORY:
++ case PMBUS_VIRT_RESET_TEMP_HISTORY:
++ ret = 0;
++ break;
++ default:
++ ret = -ENODATA;
++ break;
++ }
++ return ret;
++}
++
++static int max34440_write_word_data(struct i2c_client *client, int page,
++ int reg, u16 word)
++{
++ const struct pmbus_driver_info *info = pmbus_get_driver_info(client);
++ const struct max34440_data *data = to_max34440_data(info);
++ int ret;
++
++ switch (reg) {
++ case PMBUS_VIRT_RESET_POUT_HISTORY:
++ ret = pmbus_write_word_data(client, page,
++ MAX34446_MFR_POUT_PEAK, 0);
++ if (ret)
++ break;
++ ret = pmbus_write_word_data(client, page,
++ MAX34446_MFR_POUT_AVG, 0);
++ break;
++ case PMBUS_VIRT_RESET_VOUT_HISTORY:
++ ret = pmbus_write_word_data(client, page,
++ MAX34440_MFR_VOUT_MIN, 0x7fff);
++ if (ret)
++ break;
++ ret = pmbus_write_word_data(client, page,
++ MAX34440_MFR_VOUT_PEAK, 0);
++ break;
++ case PMBUS_VIRT_RESET_IOUT_HISTORY:
++ ret = pmbus_write_word_data(client, page,
++ MAX34440_MFR_IOUT_PEAK, 0);
++ if (!ret && data->id == max34446)
++ ret = pmbus_write_word_data(client, page,
++ MAX34446_MFR_IOUT_AVG, 0);
++
++ break;
++ case PMBUS_VIRT_RESET_TEMP_HISTORY:
++ ret = pmbus_write_word_data(client, page,
++ MAX34440_MFR_TEMPERATURE_PEAK,
++ 0x8000);
++ if (!ret && data->id == max34446)
++ ret = pmbus_write_word_data(client, page,
++ MAX34446_MFR_TEMPERATURE_AVG, 0);
++ break;
++ default:
++ ret = -ENODATA;
++ break;
++ }
++ return ret;
++}
++
++static int max34440_read_byte_data(struct i2c_client *client, int page, int reg)
++{
++ int ret = 0;
++ int mfg_status;
++
++ if (page >= 0) {
++ ret = pmbus_set_page(client, page);
++ if (ret < 0)
++ return ret;
++ }
++
++ switch (reg) {
++ case PMBUS_STATUS_IOUT:
++ mfg_status = pmbus_read_word_data(client, 0,
++ PMBUS_STATUS_MFR_SPECIFIC);
++ if (mfg_status < 0)
++ return mfg_status;
++ if (mfg_status & MAX34440_STATUS_OC_WARN)
++ ret |= PB_IOUT_OC_WARNING;
++ if (mfg_status & MAX34440_STATUS_OC_FAULT)
++ ret |= PB_IOUT_OC_FAULT;
++ break;
++ case PMBUS_STATUS_TEMPERATURE:
++ mfg_status = pmbus_read_word_data(client, 0,
++ PMBUS_STATUS_MFR_SPECIFIC);
++ if (mfg_status < 0)
++ return mfg_status;
++ if (mfg_status & MAX34440_STATUS_OT_WARN)
++ ret |= PB_TEMP_OT_WARNING;
++ if (mfg_status & MAX34440_STATUS_OT_FAULT)
++ ret |= PB_TEMP_OT_FAULT;
++ break;
++ default:
++ ret = -ENODATA;
++ break;
++ }
++ return ret;
++}
++
++static struct pmbus_driver_info max34440_info[] = {
++ [max34440] = {
++ .pages = 14,
++ .format[PSC_VOLTAGE_IN] = direct,
++ .format[PSC_VOLTAGE_OUT] = direct,
++ .format[PSC_TEMPERATURE] = direct,
++ .format[PSC_CURRENT_OUT] = direct,
++ .m[PSC_VOLTAGE_IN] = 1,
++ .b[PSC_VOLTAGE_IN] = 0,
++ .R[PSC_VOLTAGE_IN] = 3, /* R = 0 in datasheet reflects mV */
++ .m[PSC_VOLTAGE_OUT] = 1,
++ .b[PSC_VOLTAGE_OUT] = 0,
++ .R[PSC_VOLTAGE_OUT] = 3, /* R = 0 in datasheet reflects mV */
++ .m[PSC_CURRENT_OUT] = 1,
++ .b[PSC_CURRENT_OUT] = 0,
++ .R[PSC_CURRENT_OUT] = 3, /* R = 0 in datasheet reflects mA */
++ .m[PSC_TEMPERATURE] = 1,
++ .b[PSC_TEMPERATURE] = 0,
++ .R[PSC_TEMPERATURE] = 2,
++ .func[0] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT
++ | PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT,
++ .func[1] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT
++ | PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT,
++ .func[2] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT
++ | PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT,
++ .func[3] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT
++ | PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT,
++ .func[4] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT
++ | PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT,
++ .func[5] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT
++ | PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT,
++ .func[6] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP,
++ .func[7] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP,
++ .func[8] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP,
++ .func[9] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP,
++ .func[10] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP,
++ .func[11] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP,
++ .func[12] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP,
++ .func[13] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP,
++ .read_byte_data = max34440_read_byte_data,
++ .read_word_data = max34440_read_word_data,
++ .write_word_data = max34440_write_word_data,
++ },
++ [max34441] = {
++ .pages = 12,
++ .format[PSC_VOLTAGE_IN] = direct,
++ .format[PSC_VOLTAGE_OUT] = direct,
++ .format[PSC_TEMPERATURE] = direct,
++ .format[PSC_CURRENT_OUT] = direct,
++ .format[PSC_FAN] = direct,
++ .m[PSC_VOLTAGE_IN] = 1,
++ .b[PSC_VOLTAGE_IN] = 0,
++ .R[PSC_VOLTAGE_IN] = 3,
++ .m[PSC_VOLTAGE_OUT] = 1,
++ .b[PSC_VOLTAGE_OUT] = 0,
++ .R[PSC_VOLTAGE_OUT] = 3,
++ .m[PSC_CURRENT_OUT] = 1,
++ .b[PSC_CURRENT_OUT] = 0,
++ .R[PSC_CURRENT_OUT] = 3,
++ .m[PSC_TEMPERATURE] = 1,
++ .b[PSC_TEMPERATURE] = 0,
++ .R[PSC_TEMPERATURE] = 2,
++ .m[PSC_FAN] = 1,
++ .b[PSC_FAN] = 0,
++ .R[PSC_FAN] = 0,
++ .func[0] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT
++ | PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT,
++ .func[1] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT
++ | PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT,
++ .func[2] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT
++ | PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT,
++ .func[3] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT
++ | PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT,
++ .func[4] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT
++ | PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT,
++ .func[5] = PMBUS_HAVE_FAN12 | PMBUS_HAVE_STATUS_FAN12,
++ .func[6] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP,
++ .func[7] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP,
++ .func[8] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP,
++ .func[9] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP,
++ .func[10] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP,
++ .func[11] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP,
++ .read_byte_data = max34440_read_byte_data,
++ .read_word_data = max34440_read_word_data,
++ .write_word_data = max34440_write_word_data,
++ },
++ [max34446] = {
++ .pages = 7,
++ .format[PSC_VOLTAGE_IN] = direct,
++ .format[PSC_VOLTAGE_OUT] = direct,
++ .format[PSC_TEMPERATURE] = direct,
++ .format[PSC_CURRENT_OUT] = direct,
++ .format[PSC_POWER] = direct,
++ .m[PSC_VOLTAGE_IN] = 1,
++ .b[PSC_VOLTAGE_IN] = 0,
++ .R[PSC_VOLTAGE_IN] = 3,
++ .m[PSC_VOLTAGE_OUT] = 1,
++ .b[PSC_VOLTAGE_OUT] = 0,
++ .R[PSC_VOLTAGE_OUT] = 3,
++ .m[PSC_CURRENT_OUT] = 1,
++ .b[PSC_CURRENT_OUT] = 0,
++ .R[PSC_CURRENT_OUT] = 3,
++ .m[PSC_POWER] = 1,
++ .b[PSC_POWER] = 0,
++ .R[PSC_POWER] = 3,
++ .m[PSC_TEMPERATURE] = 1,
++ .b[PSC_TEMPERATURE] = 0,
++ .R[PSC_TEMPERATURE] = 2,
++ .func[0] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT
++ | PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT | PMBUS_HAVE_POUT,
++ .func[1] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT
++ | PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT,
++ .func[2] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT
++ | PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT | PMBUS_HAVE_POUT,
++ .func[3] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT
++ | PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT,
++ .func[4] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP,
++ .func[5] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP,
++ .func[6] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP,
++ .read_byte_data = max34440_read_byte_data,
++ .read_word_data = max34440_read_word_data,
++ .write_word_data = max34440_write_word_data,
++ },
++ [max34460] = {
++ .pages = 18,
++ .format[PSC_VOLTAGE_OUT] = direct,
++ .format[PSC_TEMPERATURE] = direct,
++ .m[PSC_VOLTAGE_OUT] = 1,
++ .b[PSC_VOLTAGE_OUT] = 0,
++ .R[PSC_VOLTAGE_OUT] = 3,
++ .m[PSC_TEMPERATURE] = 1,
++ .b[PSC_TEMPERATURE] = 0,
++ .R[PSC_TEMPERATURE] = 2,
++ .func[0] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT,
++ .func[1] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT,
++ .func[2] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT,
++ .func[3] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT,
++ .func[4] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT,
++ .func[5] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT,
++ .func[6] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT,
++ .func[7] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT,
++ .func[8] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT,
++ .func[9] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT,
++ .func[10] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT,
++ .func[11] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT,
++ .func[13] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP,
++ .func[14] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP,
++ .func[15] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP,
++ .func[16] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP,
++ .func[17] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP,
++ .read_byte_data = max34440_read_byte_data,
++ .read_word_data = max34440_read_word_data,
++ .write_word_data = max34440_write_word_data,
++ },
++ [max34461] = {
++ .pages = 23,
++ .format[PSC_VOLTAGE_OUT] = direct,
++ .format[PSC_TEMPERATURE] = direct,
++ .m[PSC_VOLTAGE_OUT] = 1,
++ .b[PSC_VOLTAGE_OUT] = 0,
++ .R[PSC_VOLTAGE_OUT] = 3,
++ .m[PSC_TEMPERATURE] = 1,
++ .b[PSC_TEMPERATURE] = 0,
++ .R[PSC_TEMPERATURE] = 2,
++ .func[0] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT,
++ .func[1] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT,
++ .func[2] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT,
++ .func[3] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT,
++ .func[4] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT,
++ .func[5] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT,
++ .func[6] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT,
++ .func[7] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT,
++ .func[8] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT,
++ .func[9] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT,
++ .func[10] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT,
++ .func[11] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT,
++ .func[12] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT,
++ .func[13] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT,
++ .func[14] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT,
++ .func[15] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT,
++ /* page 16 is reserved */
++ .func[17] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP,
++ .func[18] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP,
++ .func[19] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP,
++ .func[20] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP,
++ .func[21] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP,
++ .read_byte_data = max34440_read_byte_data,
++ .read_word_data = max34440_read_word_data,
++ .write_word_data = max34440_write_word_data,
++ },
++};
++
++static int max34440_probe(struct i2c_client *client,
++ const struct i2c_device_id *id)
++{
++ struct max34440_data *data;
++
++ data = devm_kzalloc(&client->dev, sizeof(struct max34440_data),
++ GFP_KERNEL);
++ if (!data)
++ return -ENOMEM;
++ data->id = id->driver_data;
++ data->info = max34440_info[id->driver_data];
++
++ return pmbus_do_probe(client, id, &data->info);
++}
++
++static const struct i2c_device_id max34440_id[] = {
++ {"max34440", max34440},
++ {"max34441", max34441},
++ {"max34446", max34446},
++ {"max34460", max34460},
++ {"max34461", max34461},
++ {}
++};
++MODULE_DEVICE_TABLE(i2c, max34440_id);
++
++/* This is the driver that will be inserted */
++static struct i2c_driver max34440_driver = {
++ .driver = {
++ .name = "max34440",
++ },
++ .probe = max34440_probe,
++ .remove = pmbus_do_remove,
++ .id_table = max34440_id,
++};
++
++module_i2c_driver(max34440_driver);
++
++MODULE_AUTHOR("Guenter Roeck");
++MODULE_DESCRIPTION("PMBus driver for Maxim MAX34440/MAX34441");
++MODULE_LICENSE("GPL");
+diff --git a/drivers/hwmon/pmbus/max8688.c b/drivers/hwmon/pmbus/max8688.c
+new file mode 100644
+index 0000000..f04454a
+--- /dev/null
++++ b/drivers/hwmon/pmbus/max8688.c
+@@ -0,0 +1,204 @@
++/*
++ * Hardware monitoring driver for Maxim MAX8688
++ *
++ * Copyright (c) 2011 Ericsson AB.
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
++ */
++
++#include <linux/kernel.h>
++#include <linux/module.h>
++#include <linux/init.h>
++#include <linux/err.h>
++#include <linux/i2c.h>
++#include "pmbus.h"
++
++#define MAX8688_MFR_VOUT_PEAK 0xd4
++#define MAX8688_MFR_IOUT_PEAK 0xd5
++#define MAX8688_MFR_TEMPERATURE_PEAK 0xd6
++#define MAX8688_MFG_STATUS 0xd8
++
++#define MAX8688_STATUS_OC_FAULT (1 << 4)
++#define MAX8688_STATUS_OV_FAULT (1 << 5)
++#define MAX8688_STATUS_OV_WARNING (1 << 8)
++#define MAX8688_STATUS_UV_FAULT (1 << 9)
++#define MAX8688_STATUS_UV_WARNING (1 << 10)
++#define MAX8688_STATUS_UC_FAULT (1 << 11)
++#define MAX8688_STATUS_OC_WARNING (1 << 12)
++#define MAX8688_STATUS_OT_FAULT (1 << 13)
++#define MAX8688_STATUS_OT_WARNING (1 << 14)
++
++static int max8688_read_word_data(struct i2c_client *client, int page, int reg)
++{
++ int ret;
++
++ if (page)
++ return -ENXIO;
++
++ switch (reg) {
++ case PMBUS_VIRT_READ_VOUT_MAX:
++ ret = pmbus_read_word_data(client, 0, MAX8688_MFR_VOUT_PEAK);
++ break;
++ case PMBUS_VIRT_READ_IOUT_MAX:
++ ret = pmbus_read_word_data(client, 0, MAX8688_MFR_IOUT_PEAK);
++ break;
++ case PMBUS_VIRT_READ_TEMP_MAX:
++ ret = pmbus_read_word_data(client, 0,
++ MAX8688_MFR_TEMPERATURE_PEAK);
++ break;
++ case PMBUS_VIRT_RESET_VOUT_HISTORY:
++ case PMBUS_VIRT_RESET_IOUT_HISTORY:
++ case PMBUS_VIRT_RESET_TEMP_HISTORY:
++ ret = 0;
++ break;
++ default:
++ ret = -ENODATA;
++ break;
++ }
++ return ret;
++}
++
++static int max8688_write_word_data(struct i2c_client *client, int page, int reg,
++ u16 word)
++{
++ int ret;
++
++ switch (reg) {
++ case PMBUS_VIRT_RESET_VOUT_HISTORY:
++ ret = pmbus_write_word_data(client, 0, MAX8688_MFR_VOUT_PEAK,
++ 0);
++ break;
++ case PMBUS_VIRT_RESET_IOUT_HISTORY:
++ ret = pmbus_write_word_data(client, 0, MAX8688_MFR_IOUT_PEAK,
++ 0);
++ break;
++ case PMBUS_VIRT_RESET_TEMP_HISTORY:
++ ret = pmbus_write_word_data(client, 0,
++ MAX8688_MFR_TEMPERATURE_PEAK,
++ 0xffff);
++ break;
++ default:
++ ret = -ENODATA;
++ break;
++ }
++ return ret;
++}
++
++static int max8688_read_byte_data(struct i2c_client *client, int page, int reg)
++{
++ int ret = 0;
++ int mfg_status;
++
++ if (page > 0)
++ return -ENXIO;
++
++ switch (reg) {
++ case PMBUS_STATUS_VOUT:
++ mfg_status = pmbus_read_word_data(client, 0,
++ MAX8688_MFG_STATUS);
++ if (mfg_status < 0)
++ return mfg_status;
++ if (mfg_status & MAX8688_STATUS_UV_WARNING)
++ ret |= PB_VOLTAGE_UV_WARNING;
++ if (mfg_status & MAX8688_STATUS_UV_FAULT)
++ ret |= PB_VOLTAGE_UV_FAULT;
++ if (mfg_status & MAX8688_STATUS_OV_WARNING)
++ ret |= PB_VOLTAGE_OV_WARNING;
++ if (mfg_status & MAX8688_STATUS_OV_FAULT)
++ ret |= PB_VOLTAGE_OV_FAULT;
++ break;
++ case PMBUS_STATUS_IOUT:
++ mfg_status = pmbus_read_word_data(client, 0,
++ MAX8688_MFG_STATUS);
++ if (mfg_status < 0)
++ return mfg_status;
++ if (mfg_status & MAX8688_STATUS_UC_FAULT)
++ ret |= PB_IOUT_UC_FAULT;
++ if (mfg_status & MAX8688_STATUS_OC_WARNING)
++ ret |= PB_IOUT_OC_WARNING;
++ if (mfg_status & MAX8688_STATUS_OC_FAULT)
++ ret |= PB_IOUT_OC_FAULT;
++ break;
++ case PMBUS_STATUS_TEMPERATURE:
++ mfg_status = pmbus_read_word_data(client, 0,
++ MAX8688_MFG_STATUS);
++ if (mfg_status < 0)
++ return mfg_status;
++ if (mfg_status & MAX8688_STATUS_OT_WARNING)
++ ret |= PB_TEMP_OT_WARNING;
++ if (mfg_status & MAX8688_STATUS_OT_FAULT)
++ ret |= PB_TEMP_OT_FAULT;
++ break;
++ default:
++ ret = -ENODATA;
++ break;
++ }
++ return ret;
++}
++
++static struct pmbus_driver_info max8688_info = {
++ .pages = 1,
++ .format[PSC_VOLTAGE_IN] = direct,
++ .format[PSC_VOLTAGE_OUT] = direct,
++ .format[PSC_TEMPERATURE] = direct,
++ .format[PSC_CURRENT_OUT] = direct,
++ .m[PSC_VOLTAGE_IN] = 19995,
++ .b[PSC_VOLTAGE_IN] = 0,
++ .R[PSC_VOLTAGE_IN] = -1,
++ .m[PSC_VOLTAGE_OUT] = 19995,
++ .b[PSC_VOLTAGE_OUT] = 0,
++ .R[PSC_VOLTAGE_OUT] = -1,
++ .m[PSC_CURRENT_OUT] = 23109,
++ .b[PSC_CURRENT_OUT] = 0,
++ .R[PSC_CURRENT_OUT] = -2,
++ .m[PSC_TEMPERATURE] = -7612,
++ .b[PSC_TEMPERATURE] = 335,
++ .R[PSC_TEMPERATURE] = -3,
++ .func[0] = PMBUS_HAVE_VOUT | PMBUS_HAVE_IOUT | PMBUS_HAVE_TEMP
++ | PMBUS_HAVE_STATUS_VOUT | PMBUS_HAVE_STATUS_IOUT
++ | PMBUS_HAVE_STATUS_TEMP,
++ .read_byte_data = max8688_read_byte_data,
++ .read_word_data = max8688_read_word_data,
++ .write_word_data = max8688_write_word_data,
++};
++
++static int max8688_probe(struct i2c_client *client,
++ const struct i2c_device_id *id)
++{
++ return pmbus_do_probe(client, id, &max8688_info);
++}
++
++static const struct i2c_device_id max8688_id[] = {
++ {"max8688", 0},
++ { }
++};
++
++MODULE_DEVICE_TABLE(i2c, max8688_id);
++
++/* This is the driver that will be inserted */
++static struct i2c_driver max8688_driver = {
++ .driver = {
++ .name = "max8688",
++ },
++ .probe = max8688_probe,
++ .remove = pmbus_do_remove,
++ .id_table = max8688_id,
++};
++
++module_i2c_driver(max8688_driver);
++
++MODULE_AUTHOR("Guenter Roeck");
++MODULE_DESCRIPTION("PMBus driver for Maxim MAX8688");
++MODULE_LICENSE("GPL");
+diff --git a/drivers/hwmon/pmbus/pfe1100.c b/drivers/hwmon/pmbus/pfe1100.c
+new file mode 100644
+index 0000000..3731fa0
+--- /dev/null
++++ b/drivers/hwmon/pmbus/pfe1100.c
+@@ -0,0 +1,249 @@
++/*
++ * Hardware monitoring driver for PFE1100 and compatibles
++ * Based on the zl6100 driver with the following copyright:
++ *
++ * Copyright (c) 2011 Ericsson AB.
++ * Copyright (c) 2012 Guenter Roeck
++ * Copyright 2004-present Facebook. All Rights Reserved.
++ *
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
++ */
++
++#include <linux/kernel.h>
++#include <linux/module.h>
++#include <linux/init.h>
++#include <linux/err.h>
++#include <linux/slab.h>
++#include <linux/i2c.h>
++#include <linux/ktime.h>
++#include <linux/delay.h>
++#include "pmbus.h"
++
++enum chips { SPDFCBK_15G, SPAFCBK_14G };
++
++struct pfe1100_data {
++ int id;
++ struct pmbus_driver_info info;
++};
++
++#define to_pfe1100_data(x) container_of(x, struct pfe1100_data, info)
++
++
++#define PFE1100_WAIT_TIME 5000 /* uS */
++
++static ushort delay = PFE1100_WAIT_TIME;
++module_param(delay, ushort, 0644);
++MODULE_PARM_DESC(delay, "Delay between chip accesses in uS");
++
++static const struct i2c_device_id pfe1100_id[] = {
++ {"pfe1100dc", SPDFCBK_15G},
++ {"pfe1100ac", SPAFCBK_14G},
++ {"pfe1100", 0},
++ { }
++};
++MODULE_DEVICE_TABLE(i2c, pfe1100_id);
++
++static int pfe1100_read_word_data(struct i2c_client *client, int page, int reg)
++{
++ const struct pmbus_driver_info *info = pmbus_get_driver_info(client);
++ struct pfe1100_data *data = to_pfe1100_data(info);
++ int ret;
++
++ if (data->id != SPAFCBK_14G && page > 0)
++ return -ENXIO;
++
++ if (reg >= PMBUS_VIRT_BASE)
++ return -ENXIO;
++
++ switch (reg) {
++ case PMBUS_FAN_COMMAND_1:
++ case PMBUS_STATUS_WORD:
++ case PMBUS_READ_VIN:
++ case PMBUS_READ_IIN:
++ case PMBUS_READ_VOUT:
++ case PMBUS_READ_IOUT:
++ case PMBUS_READ_TEMPERATURE_1:
++ case PMBUS_READ_TEMPERATURE_2:
++ case PMBUS_READ_TEMPERATURE_3:
++ case PMBUS_READ_FAN_SPEED_1:
++ case PMBUS_READ_POUT:
++ case PMBUS_READ_PIN:
++ case PMBUS_MFR_LOCATION:
++ ret = pmbus_read_word_data(client, page, reg);
++ return ret;
++ default:
++ return -ENXIO;
++ }
++}
++
++static int pfe1100_read_byte_data(struct i2c_client *client, int page, int reg)
++{
++ const struct pmbus_driver_info *info = pmbus_get_driver_info(client);
++ struct pfe1100_data *data = to_pfe1100_data(info);
++ int ret;
++
++ if (data->id != SPAFCBK_14G && page > 0)
++ return -ENXIO;
++
++ switch (reg) {
++ case PMBUS_PAGE:
++ case PMBUS_OPERATION:
++ case PMBUS_CLEAR_FAULTS:
++ case PMBUS_CAPABILITY:
++ case PMBUS_VOUT_MODE:
++ case PMBUS_FAN_CONFIG_12:
++ case PMBUS_STATUS_BYTE:
++ case PMBUS_STATUS_VOUT:
++ case PMBUS_STATUS_IOUT:
++ case PMBUS_STATUS_INPUT:
++ case PMBUS_STATUS_TEMPERATURE:
++ case PMBUS_STATUS_CML:
++ case PMBUS_STATUS_OTHER:
++ case PMBUS_STATUS_MFR_SPECIFIC:
++ case PMBUS_STATUS_FAN_12:
++ ret = pmbus_read_byte_data(client, page, reg);
++ return ret;
++ default:
++ return -ENXIO;
++ }
++}
++
++static int pfe1100_write_word_data(struct i2c_client *client, int page, int reg,
++ u16 word)
++{
++ const struct pmbus_driver_info *info = pmbus_get_driver_info(client);
++ struct pfe1100_data *data = to_pfe1100_data(info);
++ int ret;
++
++ if (data->id != SPAFCBK_14G && page > 0)
++ return -ENXIO;
++
++ if (reg >= PMBUS_VIRT_BASE)
++ return -ENXIO;
++
++ if (reg == PMBUS_FAN_COMMAND_1)
++ ret = pmbus_write_word_data(client, page, reg, word);
++ else
++ ret = -ENXIO;
++
++ return ret;
++}
++
++static int pfe1100_write_byte(struct i2c_client *client, int page, u8 value)
++{
++ const struct pmbus_driver_info *info = pmbus_get_driver_info(client);
++ struct pfe1100_data *data = to_pfe1100_data(info);
++ int ret;
++
++ if (data->id != SPAFCBK_14G && page > 0)
++ return -ENXIO;
++
++ switch (value) {
++ case PMBUS_PAGE:
++ case PMBUS_OPERATION:
++ case PMBUS_CLEAR_FAULTS:
++ ret = pmbus_write_byte(client, page, value);
++ return ret;
++ default:
++ return -ENXIO;
++ }
++}
++
++static int pfe1100_probe(struct i2c_client *client,
++ const struct i2c_device_id *id)
++{
++ int ret;
++ int kind;
++ struct pfe1100_data *data;
++ struct pmbus_driver_info *info;
++ u8 device_id[I2C_SMBUS_BLOCK_MAX + 1];
++
++ if (!i2c_check_functionality(client->adapter,
++ I2C_FUNC_SMBUS_READ_WORD_DATA
++ | I2C_FUNC_SMBUS_READ_BLOCK_DATA))
++ return -ENODEV;
++
++ ret = i2c_smbus_read_block_data(client, PMBUS_MFR_MODEL, device_id);
++ if (ret < 0) {
++ dev_err(&client->dev, "Failed to read Manufacturer ID\n");
++ kind = SPDFCBK_15G;
++ } else {
++ device_id[ret] = 0;
++ if (strncmp(device_id, "SPAFCBK-14G", ret))
++ kind = SPDFCBK_15G;
++ else
++ kind = SPAFCBK_14G;
++ dev_notice(&client->dev, "MFR_ID is [%s]\n", device_id);
++ }
++
++ data = devm_kzalloc(&client->dev, sizeof(struct pfe1100_data),
++ GFP_KERNEL);
++ if (!data)
++ return -ENOMEM;
++
++ data->id = kind;
++
++ info = &data->info;
++ info->delay = delay;
++ if (kind == SPAFCBK_14G)
++ info->pages = 2;
++ else
++ info->pages = 1;
++
++ /*
++ * It seems reasonable to just scan the device for supported
++ * values, but most drivers just seem to jam these values in
++ * there, so that's what we'll do.
++ */
++
++ info->func[0] = PMBUS_HAVE_VIN | PMBUS_HAVE_VOUT | PMBUS_HAVE_IIN |
++ PMBUS_HAVE_IOUT | PMBUS_HAVE_PIN | PMBUS_HAVE_POUT |
++ PMBUS_HAVE_FAN12 | PMBUS_HAVE_TEMP | PMBUS_HAVE_TEMP2 |
++ PMBUS_HAVE_STATUS_VOUT | PMBUS_HAVE_STATUS_IOUT |
++ PMBUS_HAVE_STATUS_INPUT | PMBUS_HAVE_STATUS_TEMP |
++ PMBUS_HAVE_STATUS_FAN12 | PMBUS_HAVE_MFRDATA;
++
++ /* AC units have a third temperature sensor, and data from 3V input: */
++
++ if (kind == SPAFCBK_14G) {
++ info->func[0] |= PMBUS_HAVE_TEMP3;
++ info->func[1] = PMBUS_HAVE_VOUT | PMBUS_HAVE_IOUT |
++ PMBUS_HAVE_POUT | PMBUS_HAVE_STATUS_VOUT |
++ PMBUS_HAVE_STATUS_IOUT;
++ }
++
++ info->read_word_data = pfe1100_read_word_data;
++ info->read_byte_data = pfe1100_read_byte_data;
++ info->write_word_data = pfe1100_write_word_data;
++ info->write_byte = pfe1100_write_byte;
++
++ return pmbus_do_probe(client, id, info);
++}
++
++static struct i2c_driver pfe1100_driver = {
++ .driver = {
++ .name = "pfe1100",
++ },
++ .probe = pfe1100_probe,
++ .remove = pmbus_do_remove,
++ .id_table = pfe1100_id,
++};
++
++module_i2c_driver(pfe1100_driver);
++
++MODULE_AUTHOR("Kevin Lahey, based on work by Guenter Roeck");
++MODULE_DESCRIPTION("PMBus driver for PFE1100");
++MODULE_LICENSE("GPL");
+diff --git a/drivers/hwmon/pmbus/pfe3000.c b/drivers/hwmon/pmbus/pfe3000.c
+new file mode 100644
+index 0000000..0ee2453
+--- /dev/null
++++ b/drivers/hwmon/pmbus/pfe3000.c
+@@ -0,0 +1,133 @@
++/*
++ * Hardware monitoring driver for PFE3000 and compatibles
++ * Based on the zl6100 driver with the following copyright:
++ *
++ * Copyright (c) 2011 Ericsson AB.
++ * Copyright (c) 2012 Guenter Roeck
++ * Copyright 2004-present Facebook. All Rights Reserved.
++ *
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
++ */
++
++#include <linux/kernel.h>
++#include <linux/module.h>
++#include <linux/init.h>
++#include <linux/err.h>
++#include <linux/slab.h>
++#include <linux/i2c.h>
++#include <linux/ktime.h>
++#include <linux/delay.h>
++#include <linux/i2c/pmbus.h>
++#include "pmbus.h"
++
++enum chips { PFE3000 };
++
++struct pfe3000_data {
++ struct pmbus_driver_info info;
++};
++
++#define to_pfe3000_data(x) container_of(x, struct pfe3000_data, info)
++
++/*
++ * Other PowerOne device require a wait time; this is included in case
++ * it is necessary for future debugging.
++ */
++
++#define PFE3000_WAIT_TIME 0 /* uS */
++
++static ushort delay = PFE3000_WAIT_TIME;
++module_param(delay, ushort, 0644);
++MODULE_PARM_DESC(delay, "Delay between chip accesses in uS");
++
++
++static const struct i2c_device_id pfe3000_id[] = {
++ {"pfe3000", PFE3000 },
++ {"pfe3000", 0},
++ { }
++};
++MODULE_DEVICE_TABLE(i2c, pfe3000_id);
++
++static struct pmbus_platform_data platform_data = {
++ .flags = PMBUS_SKIP_STATUS_CHECK
++};
++
++static int pfe3000_probe(struct i2c_client *client,
++ const struct i2c_device_id *id)
++{
++ struct device *dev = &client->dev;
++ struct pfe3000_data *data;
++ struct pmbus_driver_info *info;
++
++ data = devm_kzalloc(&client->dev, sizeof(struct pfe3000_data),
++ GFP_KERNEL);
++ if (!data)
++ return -ENOMEM;
++
++ info = &data->info;
++ info->pages = 7;
++ info->delay = delay;
++
++ /*
++ * Skip extra status checks; this is required to read the
++ * VOUT_MODE register to determine the exponent to apply
++ * to the VOUT values.
++ */
++ dev->platform_data = &platform_data;
++
++ /* Make sure that the page isn't pointing elsewhere! */
++
++ i2c_smbus_write_byte_data(client, PMBUS_PAGE, 0);
++
++ /*
++ * It seems reasonable to just scan the device for supported
++ * values, but most drivers seem to jam these values in
++ * there, so that's what we'll do.
++ */
++
++ info->func[0] = PMBUS_HAVE_VIN | PMBUS_HAVE_VOUT | PMBUS_HAVE_IIN |
++ PMBUS_HAVE_IOUT | PMBUS_HAVE_PIN | PMBUS_HAVE_POUT |
++ PMBUS_HAVE_FAN12 | PMBUS_HAVE_TEMP | PMBUS_HAVE_TEMP2 |
++ PMBUS_HAVE_TEMP3 | PMBUS_HAVE_STATUS_VOUT |
++ PMBUS_HAVE_STATUS_IOUT | PMBUS_HAVE_STATUS_INPUT |
++ PMBUS_HAVE_STATUS_TEMP | PMBUS_HAVE_STATUS_FAN12 |
++ PMBUS_HAVE_MFRDATA;
++ info->func[1] = PMBUS_HAVE_VIN | PMBUS_HAVE_VOUT | PMBUS_HAVE_IIN |
++ PMBUS_HAVE_IOUT | PMBUS_HAVE_PIN | PMBUS_HAVE_POUT |
++ PMBUS_HAVE_STATUS_VOUT | PMBUS_HAVE_STATUS_IOUT |
++ PMBUS_HAVE_STATUS_TEMP | PMBUS_HAVE_STATUS_FAN12 |
++ PMBUS_HAVE_STATUS_INPUT;
++ info->func[2] = PMBUS_HAVE_VOUT;
++ info->func[4] = PMBUS_HAVE_VOUT;
++ info->func[5] = PMBUS_HAVE_VOUT;
++ info->func[6] = PMBUS_HAVE_VOUT;
++
++ return pmbus_do_probe(client, id, info);
++}
++
++static struct i2c_driver pfe3000_driver = {
++ .driver = {
++ .name = "pfe3000",
++ },
++ .probe = pfe3000_probe,
++ .remove = pmbus_do_remove,
++ .id_table = pfe3000_id,
++};
++
++module_i2c_driver(pfe3000_driver);
++
++MODULE_AUTHOR("Kevin Lahey, based on work by Guenter Roeck");
++MODULE_DESCRIPTION("PMBus driver for PFE1100");
++MODULE_LICENSE("GPL");
+diff --git a/drivers/hwmon/pmbus/pmbus.c b/drivers/hwmon/pmbus/pmbus.c
+new file mode 100644
+index 0000000..7e91700
+--- /dev/null
++++ b/drivers/hwmon/pmbus/pmbus.c
+@@ -0,0 +1,217 @@
++/*
++ * Hardware monitoring driver for PMBus devices
++ *
++ * Copyright (c) 2010, 2011 Ericsson AB.
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
++ */
++
++#include <linux/kernel.h>
++#include <linux/module.h>
++#include <linux/init.h>
++#include <linux/err.h>
++#include <linux/slab.h>
++#include <linux/mutex.h>
++#include <linux/i2c.h>
++#include "pmbus.h"
++
++/*
++ * Find sensor groups and status registers on each page.
++ */
++static void pmbus_find_sensor_groups(struct i2c_client *client,
++ struct pmbus_driver_info *info)
++{
++ int page;
++
++ /* Sensors detected on page 0 only */
++ if (pmbus_check_word_register(client, 0, PMBUS_READ_VIN))
++ info->func[0] |= PMBUS_HAVE_VIN;
++ if (pmbus_check_word_register(client, 0, PMBUS_READ_VCAP))
++ info->func[0] |= PMBUS_HAVE_VCAP;
++ if (pmbus_check_word_register(client, 0, PMBUS_READ_IIN))
++ info->func[0] |= PMBUS_HAVE_IIN;
++ if (pmbus_check_word_register(client, 0, PMBUS_READ_PIN))
++ info->func[0] |= PMBUS_HAVE_PIN;
++ if (info->func[0]
++ && pmbus_check_byte_register(client, 0, PMBUS_STATUS_INPUT))
++ info->func[0] |= PMBUS_HAVE_STATUS_INPUT;
++ if (pmbus_check_byte_register(client, 0, PMBUS_FAN_CONFIG_12) &&
++ pmbus_check_word_register(client, 0, PMBUS_READ_FAN_SPEED_1)) {
++ info->func[0] |= PMBUS_HAVE_FAN12;
++ if (pmbus_check_byte_register(client, 0, PMBUS_STATUS_FAN_12))
++ info->func[0] |= PMBUS_HAVE_STATUS_FAN12;
++ }
++ if (pmbus_check_byte_register(client, 0, PMBUS_FAN_CONFIG_34) &&
++ pmbus_check_word_register(client, 0, PMBUS_READ_FAN_SPEED_3)) {
++ info->func[0] |= PMBUS_HAVE_FAN34;
++ if (pmbus_check_byte_register(client, 0, PMBUS_STATUS_FAN_34))
++ info->func[0] |= PMBUS_HAVE_STATUS_FAN34;
++ }
++ if (pmbus_check_word_register(client, 0, PMBUS_READ_TEMPERATURE_1))
++ info->func[0] |= PMBUS_HAVE_TEMP;
++ if (pmbus_check_word_register(client, 0, PMBUS_READ_TEMPERATURE_2))
++ info->func[0] |= PMBUS_HAVE_TEMP2;
++ if (pmbus_check_word_register(client, 0, PMBUS_READ_TEMPERATURE_3))
++ info->func[0] |= PMBUS_HAVE_TEMP3;
++ if (info->func[0] & (PMBUS_HAVE_TEMP | PMBUS_HAVE_TEMP2
++ | PMBUS_HAVE_TEMP3)
++ && pmbus_check_byte_register(client, 0,
++ PMBUS_STATUS_TEMPERATURE))
++ info->func[0] |= PMBUS_HAVE_STATUS_TEMP;
++
++ /* Sensors detected on all pages */
++ for (page = 0; page < info->pages; page++) {
++ if (pmbus_check_word_register(client, page, PMBUS_READ_VOUT)) {
++ info->func[page] |= PMBUS_HAVE_VOUT;
++ if (pmbus_check_byte_register(client, page,
++ PMBUS_STATUS_VOUT))
++ info->func[page] |= PMBUS_HAVE_STATUS_VOUT;
++ }
++ if (pmbus_check_word_register(client, page, PMBUS_READ_IOUT)) {
++ info->func[page] |= PMBUS_HAVE_IOUT;
++ if (pmbus_check_byte_register(client, 0,
++ PMBUS_STATUS_IOUT))
++ info->func[page] |= PMBUS_HAVE_STATUS_IOUT;
++ }
++ if (pmbus_check_word_register(client, page, PMBUS_READ_POUT))
++ info->func[page] |= PMBUS_HAVE_POUT;
++ }
++}
++
++/*
++ * Identify chip parameters.
++ */
++static int pmbus_identify(struct i2c_client *client,
++ struct pmbus_driver_info *info)
++{
++ int ret = 0;
++
++ if (!info->pages) {
++ /*
++ * Check if the PAGE command is supported. If it is,
++ * keep setting the page number until it fails or until the
++ * maximum number of pages has been reached. Assume that
++ * this is the number of pages supported by the chip.
++ */
++ if (pmbus_check_byte_register(client, 0, PMBUS_PAGE)) {
++ int page;
++
++ for (page = 1; page < PMBUS_PAGES; page++) {
++ if (pmbus_set_page(client, page) < 0)
++ break;
++ }
++ pmbus_set_page(client, 0);
++ info->pages = page;
++ } else {
++ info->pages = 1;
++ }
++ }
++
++ if (pmbus_check_byte_register(client, 0, PMBUS_VOUT_MODE)) {
++ int vout_mode;
++
++ vout_mode = pmbus_read_byte_data(client, 0, PMBUS_VOUT_MODE);
++ if (vout_mode >= 0 && vout_mode != 0xff) {
++ switch (vout_mode >> 5) {
++ case 0:
++ break;
++ case 1:
++ info->format[PSC_VOLTAGE_OUT] = vid;
++ break;
++ case 2:
++ info->format[PSC_VOLTAGE_OUT] = direct;
++ break;
++ default:
++ ret = -ENODEV;
++ goto abort;
++ }
++ }
++ }
++
++ /*
++ * We should check if the COEFFICIENTS register is supported.
++ * If it is, and the chip is configured for direct mode, we can read
++ * the coefficients from the chip, one set per group of sensor
++ * registers.
++ *
++ * To do this, we will need access to a chip which actually supports the
++ * COEFFICIENTS command, since the command is too complex to implement
++ * without testing it. Until then, abort if a chip configured for direct
++ * mode was detected.
++ */
++ if (info->format[PSC_VOLTAGE_OUT] == direct) {
++ ret = -ENODEV;
++ goto abort;
++ }
++
++ /* Try to find sensor groups */
++ pmbus_find_sensor_groups(client, info);
++abort:
++ return ret;
++}
++
++static int pmbus_probe(struct i2c_client *client,
++ const struct i2c_device_id *id)
++{
++ struct pmbus_driver_info *info;
++
++ info = devm_kzalloc(&client->dev, sizeof(struct pmbus_driver_info),
++ GFP_KERNEL);
++ if (!info)
++ return -ENOMEM;
++
++ info->pages = id->driver_data;
++ info->identify = pmbus_identify;
++
++ return pmbus_do_probe(client, id, info);
++}
++
++/*
++ * Use driver_data to set the number of pages supported by the chip.
++ */
++static const struct i2c_device_id pmbus_id[] = {
++ {"adp4000", 1},
++ {"bmr453", 1},
++ {"bmr454", 1},
++ {"mdt040", 1},
++ {"ncp4200", 1},
++ {"ncp4208", 1},
++ {"pdt003", 1},
++ {"pdt006", 1},
++ {"pdt012", 1},
++ {"pmbus", 0},
++ {"tps40400", 1},
++ {"tps40422", 2},
++ {"udt020", 1},
++ {}
++};
++
++MODULE_DEVICE_TABLE(i2c, pmbus_id);
++
++/* This is the driver that will be inserted */
++static struct i2c_driver pmbus_driver = {
++ .driver = {
++ .name = "pmbus",
++ },
++ .probe = pmbus_probe,
++ .remove = pmbus_do_remove,
++ .id_table = pmbus_id,
++};
++
++module_i2c_driver(pmbus_driver);
++
++MODULE_AUTHOR("Guenter Roeck");
++MODULE_DESCRIPTION("Generic PMBus driver");
++MODULE_LICENSE("GPL");
+diff --git a/drivers/hwmon/pmbus/pmbus.h b/drivers/hwmon/pmbus/pmbus.h
+new file mode 100644
+index 0000000..a6b5fba
+--- /dev/null
++++ b/drivers/hwmon/pmbus/pmbus.h
+@@ -0,0 +1,413 @@
++/*
++ * pmbus.h - Common defines and structures for PMBus devices
++ *
++ * Copyright (c) 2010, 2011 Ericsson AB.
++ * Copyright (c) 2012 Guenter Roeck
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
++ */
++
++#ifndef PMBUS_H
++#define PMBUS_H
++
++/* KML: Hacks to make this work on 2.6.28. Ugh. */
++
++#define DIV_ROUND_CLOSEST(x, divisor)( \
++{ \
++ typeof(x) __x = x; \
++ typeof(divisor) __d = divisor; \
++ (((typeof(x))-1) > 0 || \
++ ((typeof(divisor))-1) > 0 || (__x) > 0) ? \
++ (((__x) + ((__d) / 2)) / (__d)) : \
++ (((__x) - ((__d) / 2)) / (__d)); \
++} \
++)
++
++
++#define module_i2c_driver(__i2c_driver) \
++ static int __init __i2c_driver##_init(void) {return i2c_add_driver(&__i2c_driver);} \
++ static void __exit __i2c_driver##_exit(void) {i2c_del_driver(&__i2c_driver);} \
++module_init(__i2c_driver##_init); \
++module_exit(__i2c_driver##_exit);
++
++/* KML: Those are all the hacks needed, surprisingly. */
++
++/*
++ * Registers
++ */
++#define PMBUS_PAGE 0x00
++#define PMBUS_OPERATION 0x01
++#define PMBUS_ON_OFF_CONFIG 0x02
++#define PMBUS_CLEAR_FAULTS 0x03
++#define PMBUS_PHASE 0x04
++
++#define PMBUS_CAPABILITY 0x19
++#define PMBUS_QUERY 0x1A
++
++#define PMBUS_VOUT_MODE 0x20
++#define PMBUS_VOUT_COMMAND 0x21
++#define PMBUS_VOUT_TRIM 0x22
++#define PMBUS_VOUT_CAL_OFFSET 0x23
++#define PMBUS_VOUT_MAX 0x24
++#define PMBUS_VOUT_MARGIN_HIGH 0x25
++#define PMBUS_VOUT_MARGIN_LOW 0x26
++#define PMBUS_VOUT_TRANSITION_RATE 0x27
++#define PMBUS_VOUT_DROOP 0x28
++#define PMBUS_VOUT_SCALE_LOOP 0x29
++#define PMBUS_VOUT_SCALE_MONITOR 0x2A
++
++#define PMBUS_COEFFICIENTS 0x30
++#define PMBUS_POUT_MAX 0x31
++
++#define PMBUS_FAN_CONFIG_12 0x3A
++#define PMBUS_FAN_COMMAND_1 0x3B
++#define PMBUS_FAN_COMMAND_2 0x3C
++#define PMBUS_FAN_CONFIG_34 0x3D
++#define PMBUS_FAN_COMMAND_3 0x3E
++#define PMBUS_FAN_COMMAND_4 0x3F
++
++#define PMBUS_VOUT_OV_FAULT_LIMIT 0x40
++#define PMBUS_VOUT_OV_FAULT_RESPONSE 0x41
++#define PMBUS_VOUT_OV_WARN_LIMIT 0x42
++#define PMBUS_VOUT_UV_WARN_LIMIT 0x43
++#define PMBUS_VOUT_UV_FAULT_LIMIT 0x44
++#define PMBUS_VOUT_UV_FAULT_RESPONSE 0x45
++#define PMBUS_IOUT_OC_FAULT_LIMIT 0x46
++#define PMBUS_IOUT_OC_FAULT_RESPONSE 0x47
++#define PMBUS_IOUT_OC_LV_FAULT_LIMIT 0x48
++#define PMBUS_IOUT_OC_LV_FAULT_RESPONSE 0x49
++#define PMBUS_IOUT_OC_WARN_LIMIT 0x4A
++#define PMBUS_IOUT_UC_FAULT_LIMIT 0x4B
++#define PMBUS_IOUT_UC_FAULT_RESPONSE 0x4C
++
++#define PMBUS_OT_FAULT_LIMIT 0x4F
++#define PMBUS_OT_FAULT_RESPONSE 0x50
++#define PMBUS_OT_WARN_LIMIT 0x51
++#define PMBUS_UT_WARN_LIMIT 0x52
++#define PMBUS_UT_FAULT_LIMIT 0x53
++#define PMBUS_UT_FAULT_RESPONSE 0x54
++#define PMBUS_VIN_OV_FAULT_LIMIT 0x55
++#define PMBUS_VIN_OV_FAULT_RESPONSE 0x56
++#define PMBUS_VIN_OV_WARN_LIMIT 0x57
++#define PMBUS_VIN_UV_WARN_LIMIT 0x58
++#define PMBUS_VIN_UV_FAULT_LIMIT 0x59
++
++#define PMBUS_IIN_OC_FAULT_LIMIT 0x5B
++#define PMBUS_IIN_OC_WARN_LIMIT 0x5D
++
++#define PMBUS_POUT_OP_FAULT_LIMIT 0x68
++#define PMBUS_POUT_OP_WARN_LIMIT 0x6A
++#define PMBUS_PIN_OP_WARN_LIMIT 0x6B
++
++#define PMBUS_STATUS_BYTE 0x78
++#define PMBUS_STATUS_WORD 0x79
++#define PMBUS_STATUS_VOUT 0x7A
++#define PMBUS_STATUS_IOUT 0x7B
++#define PMBUS_STATUS_INPUT 0x7C
++#define PMBUS_STATUS_TEMPERATURE 0x7D
++#define PMBUS_STATUS_CML 0x7E
++#define PMBUS_STATUS_OTHER 0x7F
++#define PMBUS_STATUS_MFR_SPECIFIC 0x80
++#define PMBUS_STATUS_FAN_12 0x81
++#define PMBUS_STATUS_FAN_34 0x82
++
++#define PMBUS_READ_VIN 0x88
++#define PMBUS_READ_IIN 0x89
++#define PMBUS_READ_VCAP 0x8A
++#define PMBUS_READ_VOUT 0x8B
++#define PMBUS_READ_IOUT 0x8C
++#define PMBUS_READ_TEMPERATURE_1 0x8D
++#define PMBUS_READ_TEMPERATURE_2 0x8E
++#define PMBUS_READ_TEMPERATURE_3 0x8F
++#define PMBUS_READ_FAN_SPEED_1 0x90
++#define PMBUS_READ_FAN_SPEED_2 0x91
++#define PMBUS_READ_FAN_SPEED_3 0x92
++#define PMBUS_READ_FAN_SPEED_4 0x93
++#define PMBUS_READ_DUTY_CYCLE 0x94
++#define PMBUS_READ_FREQUENCY 0x95
++#define PMBUS_READ_POUT 0x96
++#define PMBUS_READ_PIN 0x97
++
++#define PMBUS_REVISION 0x98
++#define PMBUS_MFR_ID 0x99
++#define PMBUS_MFR_MODEL 0x9A
++#define PMBUS_MFR_REVISION 0x9B
++#define PMBUS_MFR_LOCATION 0x9C
++#define PMBUS_MFR_DATE 0x9D
++#define PMBUS_MFR_SERIAL 0x9E
++
++/*
++ * Virtual registers.
++ * Useful to support attributes which are not supported by standard PMBus
++ * registers but exist as manufacturer specific registers on individual chips.
++ * Must be mapped to real registers in device specific code.
++ *
++ * Semantics:
++ * Virtual registers are all word size.
++ * READ registers are read-only; writes are either ignored or return an error.
++ * RESET registers are read/write. Reading reset registers returns zero
++ * (used for detection), writing any value causes the associated history to be
++ * reset.
++ * Virtual registers have to be handled in device specific driver code. Chip
++ * driver code returns non-negative register values if a virtual register is
++ * supported, or a negative error code if not. The chip driver may return
++ * -ENODATA or any other error code in this case, though an error code other
++ * than -ENODATA is handled more efficiently and thus preferred. Either case,
++ * the calling PMBus core code will abort if the chip driver returns an error
++ * code when reading or writing virtual registers.
++ */
++#define PMBUS_VIRT_BASE 0x100
++#define PMBUS_VIRT_READ_TEMP_AVG (PMBUS_VIRT_BASE + 0)
++#define PMBUS_VIRT_READ_TEMP_MIN (PMBUS_VIRT_BASE + 1)
++#define PMBUS_VIRT_READ_TEMP_MAX (PMBUS_VIRT_BASE + 2)
++#define PMBUS_VIRT_RESET_TEMP_HISTORY (PMBUS_VIRT_BASE + 3)
++#define PMBUS_VIRT_READ_VIN_AVG (PMBUS_VIRT_BASE + 4)
++#define PMBUS_VIRT_READ_VIN_MIN (PMBUS_VIRT_BASE + 5)
++#define PMBUS_VIRT_READ_VIN_MAX (PMBUS_VIRT_BASE + 6)
++#define PMBUS_VIRT_RESET_VIN_HISTORY (PMBUS_VIRT_BASE + 7)
++#define PMBUS_VIRT_READ_IIN_AVG (PMBUS_VIRT_BASE + 8)
++#define PMBUS_VIRT_READ_IIN_MIN (PMBUS_VIRT_BASE + 9)
++#define PMBUS_VIRT_READ_IIN_MAX (PMBUS_VIRT_BASE + 10)
++#define PMBUS_VIRT_RESET_IIN_HISTORY (PMBUS_VIRT_BASE + 11)
++#define PMBUS_VIRT_READ_PIN_AVG (PMBUS_VIRT_BASE + 12)
++#define PMBUS_VIRT_READ_PIN_MAX (PMBUS_VIRT_BASE + 13)
++#define PMBUS_VIRT_RESET_PIN_HISTORY (PMBUS_VIRT_BASE + 14)
++#define PMBUS_VIRT_READ_POUT_AVG (PMBUS_VIRT_BASE + 15)
++#define PMBUS_VIRT_READ_POUT_MAX (PMBUS_VIRT_BASE + 16)
++#define PMBUS_VIRT_RESET_POUT_HISTORY (PMBUS_VIRT_BASE + 17)
++#define PMBUS_VIRT_READ_VOUT_AVG (PMBUS_VIRT_BASE + 18)
++#define PMBUS_VIRT_READ_VOUT_MIN (PMBUS_VIRT_BASE + 19)
++#define PMBUS_VIRT_READ_VOUT_MAX (PMBUS_VIRT_BASE + 20)
++#define PMBUS_VIRT_RESET_VOUT_HISTORY (PMBUS_VIRT_BASE + 21)
++#define PMBUS_VIRT_READ_IOUT_AVG (PMBUS_VIRT_BASE + 22)
++#define PMBUS_VIRT_READ_IOUT_MIN (PMBUS_VIRT_BASE + 23)
++#define PMBUS_VIRT_READ_IOUT_MAX (PMBUS_VIRT_BASE + 24)
++#define PMBUS_VIRT_RESET_IOUT_HISTORY (PMBUS_VIRT_BASE + 25)
++#define PMBUS_VIRT_READ_TEMP2_AVG (PMBUS_VIRT_BASE + 26)
++#define PMBUS_VIRT_READ_TEMP2_MIN (PMBUS_VIRT_BASE + 27)
++#define PMBUS_VIRT_READ_TEMP2_MAX (PMBUS_VIRT_BASE + 28)
++#define PMBUS_VIRT_RESET_TEMP2_HISTORY (PMBUS_VIRT_BASE + 29)
++
++#define PMBUS_VIRT_READ_VMON (PMBUS_VIRT_BASE + 30)
++#define PMBUS_VIRT_VMON_UV_WARN_LIMIT (PMBUS_VIRT_BASE + 31)
++#define PMBUS_VIRT_VMON_OV_WARN_LIMIT (PMBUS_VIRT_BASE + 32)
++#define PMBUS_VIRT_VMON_UV_FAULT_LIMIT (PMBUS_VIRT_BASE + 33)
++#define PMBUS_VIRT_VMON_OV_FAULT_LIMIT (PMBUS_VIRT_BASE + 34)
++#define PMBUS_VIRT_STATUS_VMON (PMBUS_VIRT_BASE + 35)
++
++/*
++ * CAPABILITY
++ */
++#define PB_CAPABILITY_SMBALERT (1<<4)
++#define PB_CAPABILITY_ERROR_CHECK (1<<7)
++
++/*
++ * VOUT_MODE
++ */
++#define PB_VOUT_MODE_MODE_MASK 0xe0
++#define PB_VOUT_MODE_PARAM_MASK 0x1f
++
++#define PB_VOUT_MODE_LINEAR 0x00
++#define PB_VOUT_MODE_VID 0x20
++#define PB_VOUT_MODE_DIRECT 0x40
++
++/*
++ * Fan configuration
++ */
++#define PB_FAN_2_PULSE_MASK ((1 << 0) | (1 << 1))
++#define PB_FAN_2_RPM (1 << 2)
++#define PB_FAN_2_INSTALLED (1 << 3)
++#define PB_FAN_1_PULSE_MASK ((1 << 4) | (1 << 5))
++#define PB_FAN_1_RPM (1 << 6)
++#define PB_FAN_1_INSTALLED (1 << 7)
++
++/*
++ * STATUS_BYTE, STATUS_WORD (lower)
++ */
++#define PB_STATUS_NONE_ABOVE (1<<0)
++#define PB_STATUS_CML (1<<1)
++#define PB_STATUS_TEMPERATURE (1<<2)
++#define PB_STATUS_VIN_UV (1<<3)
++#define PB_STATUS_IOUT_OC (1<<4)
++#define PB_STATUS_VOUT_OV (1<<5)
++#define PB_STATUS_OFF (1<<6)
++#define PB_STATUS_BUSY (1<<7)
++
++/*
++ * STATUS_WORD (upper)
++ */
++#define PB_STATUS_UNKNOWN (1<<8)
++#define PB_STATUS_OTHER (1<<9)
++#define PB_STATUS_FANS (1<<10)
++#define PB_STATUS_POWER_GOOD_N (1<<11)
++#define PB_STATUS_WORD_MFR (1<<12)
++#define PB_STATUS_INPUT (1<<13)
++#define PB_STATUS_IOUT_POUT (1<<14)
++#define PB_STATUS_VOUT (1<<15)
++
++/*
++ * STATUS_IOUT
++ */
++#define PB_POUT_OP_WARNING (1<<0)
++#define PB_POUT_OP_FAULT (1<<1)
++#define PB_POWER_LIMITING (1<<2)
++#define PB_CURRENT_SHARE_FAULT (1<<3)
++#define PB_IOUT_UC_FAULT (1<<4)
++#define PB_IOUT_OC_WARNING (1<<5)
++#define PB_IOUT_OC_LV_FAULT (1<<6)
++#define PB_IOUT_OC_FAULT (1<<7)
++
++/*
++ * STATUS_VOUT, STATUS_INPUT
++ */
++#define PB_VOLTAGE_UV_FAULT (1<<4)
++#define PB_VOLTAGE_UV_WARNING (1<<5)
++#define PB_VOLTAGE_OV_WARNING (1<<6)
++#define PB_VOLTAGE_OV_FAULT (1<<7)
++
++/*
++ * STATUS_INPUT
++ */
++#define PB_PIN_OP_WARNING (1<<0)
++#define PB_IIN_OC_WARNING (1<<1)
++#define PB_IIN_OC_FAULT (1<<2)
++
++/*
++ * STATUS_TEMPERATURE
++ */
++#define PB_TEMP_UT_FAULT (1<<4)
++#define PB_TEMP_UT_WARNING (1<<5)
++#define PB_TEMP_OT_WARNING (1<<6)
++#define PB_TEMP_OT_FAULT (1<<7)
++
++/*
++ * STATUS_FAN
++ */
++#define PB_FAN_AIRFLOW_WARNING (1<<0)
++#define PB_FAN_AIRFLOW_FAULT (1<<1)
++#define PB_FAN_FAN2_SPEED_OVERRIDE (1<<2)
++#define PB_FAN_FAN1_SPEED_OVERRIDE (1<<3)
++#define PB_FAN_FAN2_WARNING (1<<4)
++#define PB_FAN_FAN1_WARNING (1<<5)
++#define PB_FAN_FAN2_FAULT (1<<6)
++#define PB_FAN_FAN1_FAULT (1<<7)
++
++/*
++ * CML_FAULT_STATUS
++ */
++#define PB_CML_FAULT_OTHER_MEM_LOGIC (1<<0)
++#define PB_CML_FAULT_OTHER_COMM (1<<1)
++#define PB_CML_FAULT_PROCESSOR (1<<3)
++#define PB_CML_FAULT_MEMORY (1<<4)
++#define PB_CML_FAULT_PACKET_ERROR (1<<5)
++#define PB_CML_FAULT_INVALID_DATA (1<<6)
++#define PB_CML_FAULT_INVALID_COMMAND (1<<7)
++
++enum pmbus_sensor_classes {
++ PSC_VOLTAGE_IN = 0,
++ PSC_VOLTAGE_OUT,
++ PSC_CURRENT_IN,
++ PSC_CURRENT_OUT,
++ PSC_POWER,
++ PSC_TEMPERATURE,
++ PSC_FAN,
++ PSC_NUM_CLASSES /* Number of power sensor classes */
++};
++
++#define PMBUS_PAGES 32 /* Per PMBus specification */
++
++/* Functionality bit mask */
++#define PMBUS_HAVE_VIN (1 << 0)
++#define PMBUS_HAVE_VCAP (1 << 1)
++#define PMBUS_HAVE_VOUT (1 << 2)
++#define PMBUS_HAVE_IIN (1 << 3)
++#define PMBUS_HAVE_IOUT (1 << 4)
++#define PMBUS_HAVE_PIN (1 << 5)
++#define PMBUS_HAVE_POUT (1 << 6)
++#define PMBUS_HAVE_FAN12 (1 << 7)
++#define PMBUS_HAVE_FAN34 (1 << 8)
++#define PMBUS_HAVE_TEMP (1 << 9)
++#define PMBUS_HAVE_TEMP2 (1 << 10)
++#define PMBUS_HAVE_TEMP3 (1 << 11)
++#define PMBUS_HAVE_STATUS_VOUT (1 << 12)
++#define PMBUS_HAVE_STATUS_IOUT (1 << 13)
++#define PMBUS_HAVE_STATUS_INPUT (1 << 14)
++#define PMBUS_HAVE_STATUS_TEMP (1 << 15)
++#define PMBUS_HAVE_STATUS_FAN12 (1 << 16)
++#define PMBUS_HAVE_STATUS_FAN34 (1 << 17)
++#define PMBUS_HAVE_VMON (1 << 18)
++#define PMBUS_HAVE_STATUS_VMON (1 << 19)
++#define PMBUS_HAVE_MFRDATA (1 << 20)
++
++enum pmbus_data_format { linear = 0, direct, vid };
++
++struct pmbus_driver_info {
++ int pages; /* Total number of pages */
++ ushort delay;
++ enum pmbus_data_format format[PSC_NUM_CLASSES];
++ /*
++ * Support one set of coefficients for each sensor type
++ * Used for chips providing data in direct mode.
++ */
++ int m[PSC_NUM_CLASSES]; /* mantissa for direct data format */
++ int b[PSC_NUM_CLASSES]; /* offset */
++ int R[PSC_NUM_CLASSES]; /* exponent */
++
++ u32 func[PMBUS_PAGES]; /* Functionality, per page */
++ /*
++ * The following functions map manufacturing specific register values
++ * to PMBus standard register values. Specify only if mapping is
++ * necessary.
++ * Functions return the register value (read) or zero (write) if
++ * successful. A return value of -ENODATA indicates that there is no
++ * manufacturer specific register, but that a standard PMBus register
++ * may exist. Any other negative return value indicates that the
++ * register does not exist, and that no attempt should be made to read
++ * the standard register.
++ */
++ int (*read_byte_data)(struct i2c_client *client, int page, int reg);
++ int (*read_word_data)(struct i2c_client *client, int page, int reg);
++ int (*write_word_data)(struct i2c_client *client, int page, int reg,
++ u16 word);
++ int (*write_byte)(struct i2c_client *client, int page, u8 value);
++ /*
++ * The identify function determines supported PMBus functionality.
++ * This function is only necessary if a chip driver supports multiple
++ * chips, and the chip functionality is not pre-determined.
++ */
++ int (*identify)(struct i2c_client *client,
++ struct pmbus_driver_info *info);
++};
++
++/* Function declarations */
++
++void pmbus_wait(struct i2c_client *client);
++void pmbus_update_wait(struct i2c_client *client);
++void pmbus_clear_cache(struct i2c_client *client);
++int pmbus_set_page(struct i2c_client *client, u8 page);
++int pmbus_read_word_data(struct i2c_client *client, u8 page, u8 reg);
++int pmbus_write_word_data(struct i2c_client *client, u8 page, u8 reg, u16 word);
++int pmbus_read_byte_data(struct i2c_client *client, int page, u8 reg);
++int pmbus_write_byte(struct i2c_client *client, int page, u8 value);
++void pmbus_clear_faults(struct i2c_client *client);
++bool pmbus_check_byte_register(struct i2c_client *client, int page, int reg);
++bool pmbus_check_word_register(struct i2c_client *client, int page, int reg);
++int pmbus_do_probe(struct i2c_client *client, const struct i2c_device_id *id,
++ struct pmbus_driver_info *info);
++int pmbus_do_remove(struct i2c_client *client);
++const struct pmbus_driver_info *pmbus_get_driver_info(struct i2c_client
++ *client);
++
++#endif /* PMBUS_H */
+diff --git a/drivers/hwmon/pmbus/pmbus_core.c b/drivers/hwmon/pmbus/pmbus_core.c
+new file mode 100644
+index 0000000..d547fc8
+--- /dev/null
++++ b/drivers/hwmon/pmbus/pmbus_core.c
+@@ -0,0 +1,1940 @@
++/*
++ * Hardware monitoring driver for PMBus devices
++ *
++ * Copyright (c) 2010, 2011 Ericsson AB.
++ * Copyright (c) 2012 Guenter Roeck
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
++ */
++
++#include <linux/kernel.h>
++#include <linux/module.h>
++#include <linux/init.h>
++#include <linux/err.h>
++#include <linux/slab.h>
++#include <linux/i2c.h>
++#include <linux/hwmon.h>
++#include <linux/hwmon-sysfs.h>
++#include <linux/jiffies.h>
++#include <linux/delay.h>
++#include <linux/i2c/pmbus.h>
++#include "pmbus.h"
++
++/*
++ * Number of additional attribute pointers to allocate
++ * with each call to krealloc
++ */
++#define PMBUS_ATTR_ALLOC_SIZE 32
++
++/*
++ * Index into status register array, per status register group
++ */
++#define PB_STATUS_BASE 0
++#define PB_STATUS_VOUT_BASE (PB_STATUS_BASE + PMBUS_PAGES)
++#define PB_STATUS_IOUT_BASE (PB_STATUS_VOUT_BASE + PMBUS_PAGES)
++#define PB_STATUS_FAN_BASE (PB_STATUS_IOUT_BASE + PMBUS_PAGES)
++#define PB_STATUS_FAN34_BASE (PB_STATUS_FAN_BASE + PMBUS_PAGES)
++#define PB_STATUS_TEMP_BASE (PB_STATUS_FAN34_BASE + PMBUS_PAGES)
++#define PB_STATUS_INPUT_BASE (PB_STATUS_TEMP_BASE + PMBUS_PAGES)
++#define PB_STATUS_VMON_BASE (PB_STATUS_INPUT_BASE + 1)
++
++#define PB_NUM_STATUS_REG (PB_STATUS_VMON_BASE + 1)
++
++#define PMBUS_NAME_SIZE 24
++
++struct pmbus_sensor {
++ struct pmbus_sensor *next;
++ char name[PMBUS_NAME_SIZE]; /* sysfs sensor name */
++ struct device_attribute attribute;
++ u8 page; /* page number */
++ u16 reg; /* register */
++ enum pmbus_sensor_classes class; /* sensor class */
++ bool update; /* runtime sensor update needed */
++ int data; /* Sensor data.
++ Negative if there was a read error */
++};
++#define to_pmbus_sensor(_attr) \
++ container_of(_attr, struct pmbus_sensor, attribute)
++
++struct pmbus_boolean {
++ char name[PMBUS_NAME_SIZE]; /* sysfs boolean name */
++ struct sensor_device_attribute attribute;
++ struct pmbus_sensor *s1;
++ struct pmbus_sensor *s2;
++};
++#define to_pmbus_boolean(_attr) \
++ container_of(_attr, struct pmbus_boolean, attribute)
++
++struct pmbus_label {
++ char name[PMBUS_NAME_SIZE]; /* sysfs label name */
++ struct device_attribute attribute;
++ char label[PMBUS_NAME_SIZE]; /* label */
++};
++#define to_pmbus_label(_attr) \
++ container_of(_attr, struct pmbus_label, attribute)
++
++struct pmbus_data {
++ struct device *dev;
++ struct device *hwmon_dev;
++
++ u32 flags; /* from platform data */
++
++ int exponent; /* linear mode: exponent for output voltages */
++
++ const struct pmbus_driver_info *info;
++
++ int max_attributes;
++ int num_attributes;
++ struct attribute_group group;
++
++ struct pmbus_sensor *sensors;
++
++ struct mutex update_lock;
++ bool valid;
++ unsigned long last_updated; /* in jiffies */
++
++ ktime_t access;
++
++ /*
++ * A single status register covers multiple attributes,
++ * so we keep them all together.
++ */
++ u8 status[PB_NUM_STATUS_REG];
++ u8 status_register;
++
++ u8 currpage;
++};
++
++/* Some chips need a delay between accesses */
++void pmbus_wait(struct i2c_client *client)
++{
++ struct pmbus_data *data = i2c_get_clientdata(client);
++ const struct pmbus_driver_info *info = data->info;
++
++ if (info->delay) {
++ s64 delta = ktime_us_delta(ktime_get(), data->access);
++ if (delta < info->delay)
++ /*
++ * Note that udelay is busy waiting. msleep is
++ * quite a bit slower (it actually takes a
++ * minimum of 20ms), but doesn't busy wait. Hmmm.
++ */
++ udelay(info->delay - delta);
++ }
++}
++EXPORT_SYMBOL_GPL(pmbus_wait);
++
++void pmbus_update_wait(struct i2c_client *client)
++{
++ struct pmbus_data *data = i2c_get_clientdata(client);
++ const struct pmbus_driver_info *info = data->info;
++
++ if (info->delay)
++ data->access = ktime_get();
++}
++EXPORT_SYMBOL_GPL(pmbus_update_wait);
++
++void pmbus_clear_cache(struct i2c_client *client)
++{
++ struct pmbus_data *data = i2c_get_clientdata(client);
++
++ data->valid = false;
++}
++EXPORT_SYMBOL_GPL(pmbus_clear_cache);
++
++int pmbus_set_page(struct i2c_client *client, u8 page)
++{
++ struct pmbus_data *data = i2c_get_clientdata(client);
++ int rv = 0;
++ int newpage;
++
++ if (page != data->currpage) {
++ pmbus_wait(client);
++ rv = i2c_smbus_write_byte_data(client, PMBUS_PAGE, page);
++ pmbus_update_wait(client);
++ pmbus_wait(client);
++ newpage = i2c_smbus_read_byte_data(client, PMBUS_PAGE);
++ pmbus_update_wait(client);
++ if (newpage != page)
++ rv = -EIO;
++ else
++ data->currpage = page;
++ }
++ return rv;
++}
++EXPORT_SYMBOL_GPL(pmbus_set_page);
++
++int pmbus_write_byte(struct i2c_client *client, int page, u8 value)
++{
++ int rv;
++
++ if (page >= 0) {
++ rv = pmbus_set_page(client, page);
++ if (rv < 0)
++ return rv;
++ }
++
++ pmbus_wait(client);
++ rv = i2c_smbus_write_byte(client, value);
++ pmbus_update_wait(client);
++ return rv;
++}
++EXPORT_SYMBOL_GPL(pmbus_write_byte);
++
++/*
++ * _pmbus_write_byte() is similar to pmbus_write_byte(), but checks if
++ * a device specific mapping funcion exists and calls it if necessary.
++ */
++static int _pmbus_write_byte(struct i2c_client *client, int page, u8 value)
++{
++ struct pmbus_data *data = i2c_get_clientdata(client);
++ const struct pmbus_driver_info *info = data->info;
++ int status;
++
++ if (info->write_byte) {
++ status = info->write_byte(client, page, value);
++ if (status != -ENODATA)
++ return status;
++ }
++ return pmbus_write_byte(client, page, value);
++}
++
++int pmbus_write_word_data(struct i2c_client *client, u8 page, u8 reg, u16 word)
++{
++ int rv;
++
++ rv = pmbus_set_page(client, page);
++ if (rv < 0)
++ return rv;
++
++ pmbus_wait(client);
++ rv = i2c_smbus_write_word_data(client, reg, word);
++ pmbus_update_wait(client);
++ return rv;
++}
++EXPORT_SYMBOL_GPL(pmbus_write_word_data);
++
++/*
++ * _pmbus_write_word_data() is similar to pmbus_write_word_data(), but checks if
++ * a device specific mapping function exists and calls it if necessary.
++ */
++static int _pmbus_write_word_data(struct i2c_client *client, int page, int reg,
++ u16 word)
++{
++ struct pmbus_data *data = i2c_get_clientdata(client);
++ const struct pmbus_driver_info *info = data->info;
++ int status;
++
++ if (info->write_word_data) {
++ status = info->write_word_data(client, page, reg, word);
++ if (status != -ENODATA)
++ return status;
++ }
++ if (reg >= PMBUS_VIRT_BASE)
++ return -ENXIO;
++ return pmbus_write_word_data(client, page, reg, word);
++}
++
++int pmbus_read_word_data(struct i2c_client *client, u8 page, u8 reg)
++{
++ int rv;
++
++ rv = pmbus_set_page(client, page);
++ if (rv < 0)
++ return rv;
++
++ pmbus_wait(client);
++ rv = i2c_smbus_read_word_data(client, reg);
++ pmbus_update_wait(client);
++ return rv;
++}
++EXPORT_SYMBOL_GPL(pmbus_read_word_data);
++
++/*
++ * _pmbus_read_word_data() is similar to pmbus_read_word_data(), but checks if
++ * a device specific mapping function exists and calls it if necessary.
++ */
++static int _pmbus_read_word_data(struct i2c_client *client, int page, int reg)
++{
++ struct pmbus_data *data = i2c_get_clientdata(client);
++ const struct pmbus_driver_info *info = data->info;
++ int status;
++
++ if (info->read_word_data) {
++ status = info->read_word_data(client, page, reg);
++ if (status != -ENODATA)
++ return status;
++ }
++ if (reg >= PMBUS_VIRT_BASE)
++ return -ENXIO;
++ return pmbus_read_word_data(client, page, reg);
++}
++
++int pmbus_read_byte_data(struct i2c_client *client, int page, u8 reg)
++{
++ int rv;
++
++ if (page >= 0) {
++ rv = pmbus_set_page(client, page);
++ if (rv < 0)
++ return rv;
++ }
++
++ pmbus_wait(client);
++ rv = i2c_smbus_read_byte_data(client, reg);
++ pmbus_update_wait(client);
++ return rv;
++}
++EXPORT_SYMBOL_GPL(pmbus_read_byte_data);
++
++/*
++ * _pmbus_read_byte_data() is similar to pmbus_read_byte_data(), but checks if
++ * a device specific mapping function exists and calls it if necessary.
++ */
++static int _pmbus_read_byte_data(struct i2c_client *client, int page, int reg)
++{
++ struct pmbus_data *data = i2c_get_clientdata(client);
++ const struct pmbus_driver_info *info = data->info;
++ int status;
++
++ if (info->read_byte_data) {
++ status = info->read_byte_data(client, page, reg);
++ if (status != -ENODATA)
++ return status;
++ }
++ return pmbus_read_byte_data(client, page, reg);
++}
++
++static void pmbus_clear_fault_page(struct i2c_client *client, int page)
++{
++ _pmbus_write_byte(client, page, PMBUS_CLEAR_FAULTS);
++}
++
++void pmbus_clear_faults(struct i2c_client *client)
++{
++ struct pmbus_data *data = i2c_get_clientdata(client);
++ int i;
++
++ for (i = 0; i < data->info->pages; i++)
++ pmbus_clear_fault_page(client, i);
++}
++EXPORT_SYMBOL_GPL(pmbus_clear_faults);
++
++static int pmbus_check_status_cml(struct i2c_client *client)
++{
++ struct pmbus_data *data = i2c_get_clientdata(client);
++ int status, status2;
++
++ status = _pmbus_read_byte_data(client, -1, data->status_register);
++ if (status < 0 || (status & PB_STATUS_CML)) {
++ status2 = _pmbus_read_byte_data(client, -1, PMBUS_STATUS_CML);
++ if (status2 < 0 || (status2 & PB_CML_FAULT_INVALID_COMMAND))
++ return -EIO;
++ }
++ return 0;
++}
++
++static bool pmbus_check_register(struct i2c_client *client,
++ int (*func)(struct i2c_client *client,
++ int page, int reg),
++ int page, int reg)
++{
++ int rv;
++ struct pmbus_data *data = i2c_get_clientdata(client);
++
++ rv = func(client, page, reg);
++ if (rv >= 0 && !(data->flags & PMBUS_SKIP_STATUS_CHECK))
++ rv = pmbus_check_status_cml(client);
++ pmbus_clear_fault_page(client, -1);
++ return rv >= 0;
++}
++
++bool pmbus_check_byte_register(struct i2c_client *client, int page, int reg)
++{
++ return pmbus_check_register(client, _pmbus_read_byte_data, page, reg);
++}
++EXPORT_SYMBOL_GPL(pmbus_check_byte_register);
++
++bool pmbus_check_word_register(struct i2c_client *client, int page, int reg)
++{
++ return pmbus_check_register(client, _pmbus_read_word_data, page, reg);
++}
++EXPORT_SYMBOL_GPL(pmbus_check_word_register);
++
++const struct pmbus_driver_info *pmbus_get_driver_info(struct i2c_client *client)
++{
++ struct pmbus_data *data = i2c_get_clientdata(client);
++
++ return data->info;
++}
++EXPORT_SYMBOL_GPL(pmbus_get_driver_info);
++
++static struct _pmbus_status {
++ u32 func;
++ u16 base;
++ u16 reg;
++} pmbus_status[] = {
++ { PMBUS_HAVE_STATUS_VOUT, PB_STATUS_VOUT_BASE, PMBUS_STATUS_VOUT },
++ { PMBUS_HAVE_STATUS_IOUT, PB_STATUS_IOUT_BASE, PMBUS_STATUS_IOUT },
++ { PMBUS_HAVE_STATUS_TEMP, PB_STATUS_TEMP_BASE,
++ PMBUS_STATUS_TEMPERATURE },
++ { PMBUS_HAVE_STATUS_FAN12, PB_STATUS_FAN_BASE, PMBUS_STATUS_FAN_12 },
++ { PMBUS_HAVE_STATUS_FAN34, PB_STATUS_FAN34_BASE, PMBUS_STATUS_FAN_34 },
++};
++
++static struct pmbus_data *pmbus_update_device(struct device *dev)
++{
++ struct i2c_client *client = to_i2c_client(dev);
++ struct pmbus_data *data = i2c_get_clientdata(client);
++ const struct pmbus_driver_info *info = data->info;
++ struct pmbus_sensor *sensor;
++
++ mutex_lock(&data->update_lock);
++ if (time_after(jiffies, data->last_updated + HZ) || !data->valid) {
++ int i, j;
++
++ for (i = 0; i < info->pages; i++) {
++ data->status[PB_STATUS_BASE + i]
++ = _pmbus_read_byte_data(client, i,
++ data->status_register);
++ for (j = 0; j < ARRAY_SIZE(pmbus_status); j++) {
++ struct _pmbus_status *s = &pmbus_status[j];
++
++ if (!(info->func[i] & s->func))
++ continue;
++ data->status[s->base + i]
++ = _pmbus_read_byte_data(client, i,
++ s->reg);
++ }
++ }
++
++ if (info->func[0] & PMBUS_HAVE_STATUS_INPUT)
++ data->status[PB_STATUS_INPUT_BASE]
++ = _pmbus_read_byte_data(client, 0,
++ PMBUS_STATUS_INPUT);
++
++ if (info->func[0] & PMBUS_HAVE_STATUS_VMON)
++ data->status[PB_STATUS_VMON_BASE]
++ = _pmbus_read_byte_data(client, 0,
++ PMBUS_VIRT_STATUS_VMON);
++
++ for (sensor = data->sensors; sensor; sensor = sensor->next) {
++ if (!data->valid || sensor->update)
++ sensor->data
++ = _pmbus_read_word_data(client,
++ sensor->page,
++ sensor->reg);
++ }
++ pmbus_clear_faults(client);
++ data->last_updated = jiffies;
++ data->valid = 1;
++ }
++ mutex_unlock(&data->update_lock);
++ return data;
++}
++
++/*
++ * Convert linear sensor values to milli- or micro-units
++ * depending on sensor type.
++ */
++static long pmbus_reg2data_linear(struct pmbus_data *data,
++ struct pmbus_sensor *sensor)
++{
++ s16 exponent;
++ s32 mantissa;
++ long val;
++
++ if (sensor->class == PSC_VOLTAGE_OUT) { /* LINEAR16 */
++ exponent = data->exponent;
++ mantissa = (u16) sensor->data;
++ } else { /* LINEAR11 */
++ exponent = ((s16)sensor->data) >> 11;
++ mantissa = ((s16)((sensor->data & 0x7ff) << 5)) >> 5;
++ }
++
++ val = mantissa;
++
++ /* scale result to milli-units for all sensors except fans */
++ if (sensor->class != PSC_FAN)
++ val = val * 1000L;
++
++ /* scale result to micro-units for power sensors */
++ if (sensor->class == PSC_POWER)
++ val = val * 1000L;
++
++ if (exponent >= 0)
++ val <<= exponent;
++ else
++ val >>= -exponent;
++
++ return val;
++}
++
++/*
++ * Convert direct sensor values to milli- or micro-units
++ * depending on sensor type.
++ */
++static long pmbus_reg2data_direct(struct pmbus_data *data,
++ struct pmbus_sensor *sensor)
++{
++ long val = (s16) sensor->data;
++ long m, b, R;
++
++ m = data->info->m[sensor->class];
++ b = data->info->b[sensor->class];
++ R = data->info->R[sensor->class];
++
++ if (m == 0)
++ return 0;
++
++ /* X = 1/m * (Y * 10^-R - b) */
++ R = -R;
++ /* scale result to milli-units for everything but fans */
++ if (sensor->class != PSC_FAN) {
++ R += 3;
++ b *= 1000;
++ }
++
++ /* scale result to micro-units for power sensors */
++ if (sensor->class == PSC_POWER) {
++ R += 3;
++ b *= 1000;
++ }
++
++ while (R > 0) {
++ val *= 10;
++ R--;
++ }
++ while (R < 0) {
++ val = DIV_ROUND_CLOSEST(val, 10);
++ R++;
++ }
++
++ return (val - b) / m;
++}
++
++/*
++ * Convert VID sensor values to milli- or micro-units
++ * depending on sensor type.
++ * We currently only support VR11.
++ */
++static long pmbus_reg2data_vid(struct pmbus_data *data,
++ struct pmbus_sensor *sensor)
++{
++ long val = sensor->data;
++
++ if (val < 0x02 || val > 0xb2)
++ return 0;
++ return DIV_ROUND_CLOSEST(160000 - (val - 2) * 625, 100);
++}
++
++static long pmbus_reg2data(struct pmbus_data *data, struct pmbus_sensor *sensor)
++{
++ long val;
++
++ switch (data->info->format[sensor->class]) {
++ case direct:
++ val = pmbus_reg2data_direct(data, sensor);
++ break;
++ case vid:
++ val = pmbus_reg2data_vid(data, sensor);
++ break;
++ case linear:
++ default:
++ val = pmbus_reg2data_linear(data, sensor);
++ break;
++ }
++ return val;
++}
++
++#define MAX_MANTISSA (1023 * 1000)
++#define MIN_MANTISSA (511 * 1000)
++
++static u16 pmbus_data2reg_linear(struct pmbus_data *data,
++ enum pmbus_sensor_classes class, long val)
++{
++ s16 exponent = 0, mantissa;
++ bool negative = false;
++
++ /* simple case */
++ if (val == 0)
++ return 0;
++
++ if (class == PSC_VOLTAGE_OUT) {
++ /* LINEAR16 does not support negative voltages */
++ if (val < 0)
++ return 0;
++
++ /*
++ * For a static exponents, we don't have a choice
++ * but to adjust the value to it.
++ */
++ if (data->exponent < 0)
++ val <<= -data->exponent;
++ else
++ val >>= data->exponent;
++ val = DIV_ROUND_CLOSEST(val, 1000);
++ return val & 0xffff;
++ }
++
++ if (val < 0) {
++ negative = true;
++ val = -val;
++ }
++
++ /* Power is in uW. Convert to mW before converting. */
++ if (class == PSC_POWER)
++ val = DIV_ROUND_CLOSEST(val, 1000L);
++
++ /*
++ * For simplicity, convert fan data to milli-units
++ * before calculating the exponent.
++ */
++ if (class == PSC_FAN)
++ val = val * 1000;
++
++ /* Reduce large mantissa until it fits into 10 bit */
++ while (val >= MAX_MANTISSA && exponent < 15) {
++ exponent++;
++ val >>= 1;
++ }
++ /* Increase small mantissa to improve precision */
++ while (val < MIN_MANTISSA && exponent > -15) {
++ exponent--;
++ val <<= 1;
++ }
++
++ /* Convert mantissa from milli-units to units */
++ mantissa = DIV_ROUND_CLOSEST(val, 1000);
++
++ /* Ensure that resulting number is within range */
++ if (mantissa > 0x3ff)
++ mantissa = 0x3ff;
++
++ /* restore sign */
++ if (negative)
++ mantissa = -mantissa;
++
++ /* Convert to 5 bit exponent, 11 bit mantissa */
++ return (mantissa & 0x7ff) | ((exponent << 11) & 0xf800);
++}
++
++static u16 pmbus_data2reg_direct(struct pmbus_data *data,
++ enum pmbus_sensor_classes class, long val)
++{
++ long m, b, R;
++
++ m = data->info->m[class];
++ b = data->info->b[class];
++ R = data->info->R[class];
++
++ /* Power is in uW. Adjust R and b. */
++ if (class == PSC_POWER) {
++ R -= 3;
++ b *= 1000;
++ }
++
++ /* Calculate Y = (m * X + b) * 10^R */
++ if (class != PSC_FAN) {
++ R -= 3; /* Adjust R and b for data in milli-units */
++ b *= 1000;
++ }
++ val = val * m + b;
++
++ while (R > 0) {
++ val *= 10;
++ R--;
++ }
++ while (R < 0) {
++ val = DIV_ROUND_CLOSEST(val, 10);
++ R++;
++ }
++
++ return val;
++}
++
++static u16 pmbus_data2reg_vid(struct pmbus_data *data,
++ enum pmbus_sensor_classes class, long val)
++{
++ val = clamp_val(val, 500, 1600);
++
++ return 2 + DIV_ROUND_CLOSEST((1600 - val) * 100, 625);
++}
++
++static u16 pmbus_data2reg(struct pmbus_data *data,
++ enum pmbus_sensor_classes class, long val)
++{
++ u16 regval;
++
++ switch (data->info->format[class]) {
++ case direct:
++ regval = pmbus_data2reg_direct(data, class, val);
++ break;
++ case vid:
++ regval = pmbus_data2reg_vid(data, class, val);
++ break;
++ case linear:
++ default:
++ regval = pmbus_data2reg_linear(data, class, val);
++ break;
++ }
++ return regval;
++}
++
++/*
++ * Return boolean calculated from converted data.
++ * <index> defines a status register index and mask.
++ * The mask is in the lower 8 bits, the register index is in bits 8..23.
++ *
++ * The associated pmbus_boolean structure contains optional pointers to two
++ * sensor attributes. If specified, those attributes are compared against each
++ * other to determine if a limit has been exceeded.
++ *
++ * If the sensor attribute pointers are NULL, the function returns true if
++ * (status[reg] & mask) is true.
++ *
++ * If sensor attribute pointers are provided, a comparison against a specified
++ * limit has to be performed to determine the boolean result.
++ * In this case, the function returns true if v1 >= v2 (where v1 and v2 are
++ * sensor values referenced by sensor attribute pointers s1 and s2).
++ *
++ * To determine if an object exceeds upper limits, specify <s1,s2> = <v,limit>.
++ * To determine if an object exceeds lower limits, specify <s1,s2> = <limit,v>.
++ *
++ * If a negative value is stored in any of the referenced registers, this value
++ * reflects an error code which will be returned.
++ */
++static int pmbus_get_boolean(struct pmbus_data *data, struct pmbus_boolean *b,
++ int index)
++{
++ struct pmbus_sensor *s1 = b->s1;
++ struct pmbus_sensor *s2 = b->s2;
++ u16 reg = (index >> 8) & 0xffff;
++ u8 mask = index & 0xff;
++ int ret, status;
++ u8 regval;
++
++ status = data->status[reg];
++ if (status < 0)
++ return status;
++
++ regval = status & mask;
++ if (!s1 && !s2) {
++ ret = !!regval;
++ } else if (!s1 || !s2) {
++ BUG();
++ return 0;
++ } else {
++ long v1, v2;
++
++ if (s1->data < 0)
++ return s1->data;
++ if (s2->data < 0)
++ return s2->data;
++
++ v1 = pmbus_reg2data(data, s1);
++ v2 = pmbus_reg2data(data, s2);
++ ret = !!(regval && v1 >= v2);
++ }
++ return ret;
++}
++
++static ssize_t pmbus_show_boolean(struct device *dev,
++ struct device_attribute *da, char *buf)
++{
++ struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
++ struct pmbus_boolean *boolean = to_pmbus_boolean(attr);
++ struct pmbus_data *data = pmbus_update_device(dev);
++ int val;
++
++ val = pmbus_get_boolean(data, boolean, attr->index);
++ if (val < 0)
++ return val;
++ if (val == 0xff)
++ return 0;
++ return snprintf(buf, PAGE_SIZE, "%d\n", val);
++}
++
++static ssize_t pmbus_show_sensor(struct device *dev,
++ struct device_attribute *devattr, char *buf)
++{
++ struct pmbus_data *data = pmbus_update_device(dev);
++ struct pmbus_sensor *sensor = to_pmbus_sensor(devattr);
++
++ if (sensor->data < 0)
++ return sensor->data;
++ if (sensor->data == 0xffff)
++ return 0;
++
++ return snprintf(buf, PAGE_SIZE, "%ld\n", pmbus_reg2data(data, sensor));
++}
++
++static ssize_t pmbus_set_sensor(struct device *dev,
++ struct device_attribute *devattr,
++ const char *buf, size_t count)
++{
++ struct i2c_client *client = to_i2c_client(dev);
++ struct pmbus_data *data = i2c_get_clientdata(client);
++ struct pmbus_sensor *sensor = to_pmbus_sensor(devattr);
++ ssize_t rv = count;
++ long val = 0;
++ int ret;
++ u16 regval;
++
++ if ((val = simple_strtol(buf, NULL, 10)) < 0)
++ return -EINVAL;
++
++ mutex_lock(&data->update_lock);
++ regval = pmbus_data2reg(data, sensor->class, val);
++ ret = _pmbus_write_word_data(client, sensor->page, sensor->reg, regval);
++ if (ret < 0)
++ rv = ret;
++ else
++ sensor->data = regval;
++ mutex_unlock(&data->update_lock);
++ return rv;
++}
++
++static ssize_t pmbus_show_label(struct device *dev,
++ struct device_attribute *da, char *buf)
++{
++ struct pmbus_label *label = to_pmbus_label(da);
++
++ return snprintf(buf, PAGE_SIZE, "%s\n", label->label);
++}
++
++static int pmbus_add_attribute(struct pmbus_data *data, struct attribute *attr)
++{
++ if (data->num_attributes >= data->max_attributes - 1) {
++ int new_max_attrs = data->max_attributes + PMBUS_ATTR_ALLOC_SIZE;
++ void *new_attrs = krealloc(data->group.attrs,
++ new_max_attrs * sizeof(void *),
++ GFP_KERNEL);
++ if (!new_attrs)
++ return -ENOMEM;
++ data->group.attrs = new_attrs;
++ data->max_attributes = new_max_attrs;
++ }
++
++ data->group.attrs[data->num_attributes++] = attr;
++ data->group.attrs[data->num_attributes] = NULL;
++ return 0;
++}
++
++static void pmbus_dev_attr_init(struct device_attribute *dev_attr,
++ const char *name,
++ umode_t mode,
++ ssize_t (*show)(struct device *dev,
++ struct device_attribute *attr,
++ char *buf),
++ ssize_t (*store)(struct device *dev,
++ struct device_attribute *attr,
++ const char *buf, size_t count))
++{
++ // KML: Unnecessary in 2.6.28:
++ //sysfs_attr_init(&dev_attr->attr);
++ dev_attr->attr.name = name;
++ dev_attr->attr.mode = mode;
++ dev_attr->show = show;
++ dev_attr->store = store;
++}
++
++static void pmbus_attr_init(struct sensor_device_attribute *a,
++ const char *name,
++ umode_t mode,
++ ssize_t (*show)(struct device *dev,
++ struct device_attribute *attr,
++ char *buf),
++ ssize_t (*store)(struct device *dev,
++ struct device_attribute *attr,
++ const char *buf, size_t count),
++ int idx)
++{
++ pmbus_dev_attr_init(&a->dev_attr, name, mode, show, store);
++ a->index = idx;
++}
++
++static int pmbus_add_boolean(struct pmbus_data *data,
++ const char *name, const char *type, int seq,
++ struct pmbus_sensor *s1,
++ struct pmbus_sensor *s2,
++ u16 reg, u8 mask)
++{
++ struct pmbus_boolean *boolean;
++ struct sensor_device_attribute *a;
++
++ boolean = devm_kzalloc(data->dev, sizeof(*boolean), GFP_KERNEL);
++ if (!boolean)
++ return -ENOMEM;
++
++ a = &boolean->attribute;
++
++ snprintf(boolean->name, sizeof(boolean->name), "%s%d_%s",
++ name, seq, type);
++ boolean->s1 = s1;
++ boolean->s2 = s2;
++ pmbus_attr_init(a, boolean->name, S_IRUGO, pmbus_show_boolean, NULL,
++ (reg << 8) | mask);
++
++ return pmbus_add_attribute(data, &a->dev_attr.attr);
++}
++
++static struct pmbus_sensor *pmbus_add_sensor(struct pmbus_data *data,
++ const char *name, const char *type,
++ int seq, int page, int reg,
++ enum pmbus_sensor_classes class,
++ bool update, bool readonly)
++{
++ struct pmbus_sensor *sensor;
++ struct device_attribute *a;
++
++ sensor = devm_kzalloc(data->dev, sizeof(*sensor), GFP_KERNEL);
++ if (!sensor)
++ return NULL;
++ a = &sensor->attribute;
++
++ snprintf(sensor->name, sizeof(sensor->name), "%s%d_%s",
++ name, seq, type);
++ sensor->page = page;
++ sensor->reg = reg;
++ sensor->class = class;
++ sensor->update = update;
++ pmbus_dev_attr_init(a, sensor->name,
++ readonly ? S_IRUGO : S_IRUGO | S_IWUSR,
++ pmbus_show_sensor, pmbus_set_sensor);
++
++ if (pmbus_add_attribute(data, &a->attr))
++ return NULL;
++
++ sensor->next = data->sensors;
++ data->sensors = sensor;
++
++ return sensor;
++}
++
++static int pmbus_add_label(struct pmbus_data *data,
++ const char *name, int seq,
++ const char *lstring, int index)
++{
++ struct pmbus_label *label;
++ struct device_attribute *a;
++
++ label = devm_kzalloc(data->dev, sizeof(*label), GFP_KERNEL);
++ if (!label)
++ return -ENOMEM;
++
++ a = &label->attribute;
++
++ if (seq == -1)
++ snprintf(label->name, sizeof(label->name), "%s_label", name);
++ else
++ snprintf(label->name, sizeof(label->name), "%s%d_label",
++ name, seq);
++ if (!index)
++ strncpy(label->label, lstring, sizeof(label->label) - 1);
++ else
++ snprintf(label->label, sizeof(label->label), "%s%d", lstring,
++ index);
++
++ pmbus_dev_attr_init(a, label->name, S_IRUGO, pmbus_show_label, NULL);
++ return pmbus_add_attribute(data, &a->attr);
++}
++
++/*
++ * Search for attributes. Allocate sensors, booleans, and labels as needed.
++ */
++
++/*
++ * The pmbus_limit_attr structure describes a single limit attribute
++ * and its associated alarm attribute.
++ */
++struct pmbus_limit_attr {
++ u16 reg; /* Limit register */
++ u16 sbit; /* Alarm attribute status bit */
++ bool update; /* True if register needs updates */
++ bool low; /* True if low limit; for limits with compare
++ functions only */
++ const char *attr; /* Attribute name */
++ const char *alarm; /* Alarm attribute name */
++};
++
++/*
++ * The pmbus_sensor_attr structure describes one sensor attribute. This
++ * description includes a reference to the associated limit attributes.
++ */
++struct pmbus_sensor_attr {
++ u16 reg; /* sensor register */
++ u8 gbit; /* generic status bit */
++ u8 nlimit; /* # of limit registers */
++ enum pmbus_sensor_classes class;/* sensor class */
++ const char *label; /* sensor label */
++ bool paged; /* true if paged sensor */
++ bool update; /* true if update needed */
++ bool compare; /* true if compare function needed */
++ u32 func; /* sensor mask */
++ u32 sfunc; /* sensor status mask */
++ int sbase; /* status base register */
++ const struct pmbus_limit_attr *limit;/* limit registers */
++};
++
++/*
++ * Add a set of limit attributes and, if supported, the associated
++ * alarm attributes.
++ * returns 0 if no alarm register found, 1 if an alarm register was found,
++ * < 0 on errors.
++ */
++static int pmbus_add_limit_attrs(struct i2c_client *client,
++ struct pmbus_data *data,
++ const struct pmbus_driver_info *info,
++ const char *name, int index, int page,
++ struct pmbus_sensor *base,
++ const struct pmbus_sensor_attr *attr)
++{
++ const struct pmbus_limit_attr *l = attr->limit;
++ int nlimit = attr->nlimit;
++ int have_alarm = 0;
++ int i, ret;
++ struct pmbus_sensor *curr;
++
++ for (i = 0; i < nlimit; i++) {
++ if (pmbus_check_word_register(client, page, l->reg)) {
++ curr = pmbus_add_sensor(data, name, l->attr, index,
++ page, l->reg, attr->class,
++ attr->update || l->update,
++ false);
++ if (!curr)
++ return -ENOMEM;
++ if (l->sbit && (info->func[page] & attr->sfunc)) {
++ ret = pmbus_add_boolean(data, name,
++ l->alarm, index,
++ attr->compare ? l->low ? curr : base
++ : NULL,
++ attr->compare ? l->low ? base : curr
++ : NULL,
++ attr->sbase + page, l->sbit);
++ if (ret)
++ return ret;
++ have_alarm = 1;
++ }
++ }
++ l++;
++ }
++ return have_alarm;
++}
++
++static int pmbus_add_sensor_attrs_one(struct i2c_client *client,
++ struct pmbus_data *data,
++ const struct pmbus_driver_info *info,
++ const char *name,
++ int index, int page,
++ const struct pmbus_sensor_attr *attr)
++{
++ struct pmbus_sensor *base;
++ int ret;
++
++ if (attr->label) {
++ ret = pmbus_add_label(data, name, index, attr->label,
++ attr->paged ? page + 1 : 0);
++ if (ret)
++ return ret;
++ }
++ base = pmbus_add_sensor(data, name, "input", index, page, attr->reg,
++ attr->class, true, true);
++ if (!base)
++ return -ENOMEM;
++ if (attr->sfunc) {
++ ret = pmbus_add_limit_attrs(client, data, info, name,
++ index, page, base, attr);
++ if (ret < 0)
++ return ret;
++ /*
++ * Add generic alarm attribute only if there are no individual
++ * alarm attributes, if there is a global alarm bit, and if
++ * the generic status register for this page is accessible.
++ */
++ if (!ret && attr->gbit &&
++ pmbus_check_byte_register(client, page,
++ data->status_register)) {
++ ret = pmbus_add_boolean(data, name, "alarm", index,
++ NULL, NULL,
++ PB_STATUS_BASE + page,
++ attr->gbit);
++ if (ret)
++ return ret;
++ }
++ }
++ return 0;
++}
++
++static int pmbus_add_sensor_attrs(struct i2c_client *client,
++ struct pmbus_data *data,
++ const char *name,
++ const struct pmbus_sensor_attr *attrs,
++ int nattrs)
++{
++ const struct pmbus_driver_info *info = data->info;
++ int index, i;
++ int ret;
++
++ index = 1;
++ for (i = 0; i < nattrs; i++) {
++ int page, pages;
++
++ pages = attrs->paged ? info->pages : 1;
++ for (page = 0; page < pages; page++) {
++ if (!(info->func[page] & attrs->func))
++ continue;
++ ret = pmbus_add_sensor_attrs_one(client, data, info,
++ name, index, page,
++ attrs);
++ if (ret)
++ return ret;
++ index++;
++ }
++ attrs++;
++ }
++ return 0;
++}
++
++static const struct pmbus_limit_attr vin_limit_attrs[] = {
++ {
++ .reg = PMBUS_VIN_UV_WARN_LIMIT,
++ .attr = "min",
++ .alarm = "min_alarm",
++ .sbit = PB_VOLTAGE_UV_WARNING,
++ }, {
++ .reg = PMBUS_VIN_UV_FAULT_LIMIT,
++ .attr = "lcrit",
++ .alarm = "lcrit_alarm",
++ .sbit = PB_VOLTAGE_UV_FAULT,
++ }, {
++ .reg = PMBUS_VIN_OV_WARN_LIMIT,
++ .attr = "max",
++ .alarm = "max_alarm",
++ .sbit = PB_VOLTAGE_OV_WARNING,
++ }, {
++ .reg = PMBUS_VIN_OV_FAULT_LIMIT,
++ .attr = "crit",
++ .alarm = "crit_alarm",
++ .sbit = PB_VOLTAGE_OV_FAULT,
++ }, {
++ .reg = PMBUS_VIRT_READ_VIN_AVG,
++ .update = true,
++ .attr = "average",
++ }, {
++ .reg = PMBUS_VIRT_READ_VIN_MIN,
++ .update = true,
++ .attr = "lowest",
++ }, {
++ .reg = PMBUS_VIRT_READ_VIN_MAX,
++ .update = true,
++ .attr = "highest",
++ }, {
++ .reg = PMBUS_VIRT_RESET_VIN_HISTORY,
++ .attr = "reset_history",
++ },
++};
++
++static const struct pmbus_limit_attr vmon_limit_attrs[] = {
++ {
++ .reg = PMBUS_VIRT_VMON_UV_WARN_LIMIT,
++ .attr = "min",
++ .alarm = "min_alarm",
++ .sbit = PB_VOLTAGE_UV_WARNING,
++ }, {
++ .reg = PMBUS_VIRT_VMON_UV_FAULT_LIMIT,
++ .attr = "lcrit",
++ .alarm = "lcrit_alarm",
++ .sbit = PB_VOLTAGE_UV_FAULT,
++ }, {
++ .reg = PMBUS_VIRT_VMON_OV_WARN_LIMIT,
++ .attr = "max",
++ .alarm = "max_alarm",
++ .sbit = PB_VOLTAGE_OV_WARNING,
++ }, {
++ .reg = PMBUS_VIRT_VMON_OV_FAULT_LIMIT,
++ .attr = "crit",
++ .alarm = "crit_alarm",
++ .sbit = PB_VOLTAGE_OV_FAULT,
++ }
++};
++
++static const struct pmbus_limit_attr vout_limit_attrs[] = {
++ {
++ .reg = PMBUS_VOUT_UV_WARN_LIMIT,
++ .attr = "min",
++ .alarm = "min_alarm",
++ .sbit = PB_VOLTAGE_UV_WARNING,
++ }, {
++ .reg = PMBUS_VOUT_UV_FAULT_LIMIT,
++ .attr = "lcrit",
++ .alarm = "lcrit_alarm",
++ .sbit = PB_VOLTAGE_UV_FAULT,
++ }, {
++ .reg = PMBUS_VOUT_OV_WARN_LIMIT,
++ .attr = "max",
++ .alarm = "max_alarm",
++ .sbit = PB_VOLTAGE_OV_WARNING,
++ }, {
++ .reg = PMBUS_VOUT_OV_FAULT_LIMIT,
++ .attr = "crit",
++ .alarm = "crit_alarm",
++ .sbit = PB_VOLTAGE_OV_FAULT,
++ }, {
++ .reg = PMBUS_VIRT_READ_VOUT_AVG,
++ .update = true,
++ .attr = "average",
++ }, {
++ .reg = PMBUS_VIRT_READ_VOUT_MIN,
++ .update = true,
++ .attr = "lowest",
++ }, {
++ .reg = PMBUS_VIRT_READ_VOUT_MAX,
++ .update = true,
++ .attr = "highest",
++ }, {
++ .reg = PMBUS_VIRT_RESET_VOUT_HISTORY,
++ .attr = "reset_history",
++ }
++};
++
++static const struct pmbus_sensor_attr voltage_attributes[] = {
++ {
++ .reg = PMBUS_READ_VIN,
++ .class = PSC_VOLTAGE_IN,
++ .label = "vin",
++ .func = PMBUS_HAVE_VIN,
++ .sfunc = PMBUS_HAVE_STATUS_INPUT,
++ .sbase = PB_STATUS_INPUT_BASE,
++ .gbit = PB_STATUS_VIN_UV,
++ .limit = vin_limit_attrs,
++ .nlimit = ARRAY_SIZE(vin_limit_attrs),
++ }, {
++ .reg = PMBUS_VIRT_READ_VMON,
++ .class = PSC_VOLTAGE_IN,
++ .label = "vmon",
++ .func = PMBUS_HAVE_VMON,
++ .sfunc = PMBUS_HAVE_STATUS_VMON,
++ .sbase = PB_STATUS_VMON_BASE,
++ .limit = vmon_limit_attrs,
++ .nlimit = ARRAY_SIZE(vmon_limit_attrs),
++ }, {
++ .reg = PMBUS_READ_VCAP,
++ .class = PSC_VOLTAGE_IN,
++ .label = "vcap",
++ .func = PMBUS_HAVE_VCAP,
++ }, {
++ .reg = PMBUS_READ_VOUT,
++ .class = PSC_VOLTAGE_OUT,
++ .label = "vout",
++ .paged = true,
++ .func = PMBUS_HAVE_VOUT,
++ .sfunc = PMBUS_HAVE_STATUS_VOUT,
++ .sbase = PB_STATUS_VOUT_BASE,
++ .gbit = PB_STATUS_VOUT_OV,
++ .limit = vout_limit_attrs,
++ .nlimit = ARRAY_SIZE(vout_limit_attrs),
++ }
++};
++
++/* Current attributes */
++
++static const struct pmbus_limit_attr iin_limit_attrs[] = {
++ {
++ .reg = PMBUS_IIN_OC_WARN_LIMIT,
++ .attr = "max",
++ .alarm = "max_alarm",
++ .sbit = PB_IIN_OC_WARNING,
++ }, {
++ .reg = PMBUS_IIN_OC_FAULT_LIMIT,
++ .attr = "crit",
++ .alarm = "crit_alarm",
++ .sbit = PB_IIN_OC_FAULT,
++ }, {
++ .reg = PMBUS_VIRT_READ_IIN_AVG,
++ .update = true,
++ .attr = "average",
++ }, {
++ .reg = PMBUS_VIRT_READ_IIN_MIN,
++ .update = true,
++ .attr = "lowest",
++ }, {
++ .reg = PMBUS_VIRT_READ_IIN_MAX,
++ .update = true,
++ .attr = "highest",
++ }, {
++ .reg = PMBUS_VIRT_RESET_IIN_HISTORY,
++ .attr = "reset_history",
++ }
++};
++
++static const struct pmbus_limit_attr iout_limit_attrs[] = {
++ {
++ .reg = PMBUS_IOUT_OC_WARN_LIMIT,
++ .attr = "max",
++ .alarm = "max_alarm",
++ .sbit = PB_IOUT_OC_WARNING,
++ }, {
++ .reg = PMBUS_IOUT_UC_FAULT_LIMIT,
++ .attr = "lcrit",
++ .alarm = "lcrit_alarm",
++ .sbit = PB_IOUT_UC_FAULT,
++ }, {
++ .reg = PMBUS_IOUT_OC_FAULT_LIMIT,
++ .attr = "crit",
++ .alarm = "crit_alarm",
++ .sbit = PB_IOUT_OC_FAULT,
++ }, {
++ .reg = PMBUS_VIRT_READ_IOUT_AVG,
++ .update = true,
++ .attr = "average",
++ }, {
++ .reg = PMBUS_VIRT_READ_IOUT_MIN,
++ .update = true,
++ .attr = "lowest",
++ }, {
++ .reg = PMBUS_VIRT_READ_IOUT_MAX,
++ .update = true,
++ .attr = "highest",
++ }, {
++ .reg = PMBUS_VIRT_RESET_IOUT_HISTORY,
++ .attr = "reset_history",
++ }
++};
++
++static const struct pmbus_sensor_attr current_attributes[] = {
++ {
++ .reg = PMBUS_READ_IIN,
++ .class = PSC_CURRENT_IN,
++ .label = "iin",
++ .func = PMBUS_HAVE_IIN,
++ .sfunc = PMBUS_HAVE_STATUS_INPUT,
++ .sbase = PB_STATUS_INPUT_BASE,
++ .limit = iin_limit_attrs,
++ .nlimit = ARRAY_SIZE(iin_limit_attrs),
++ }, {
++ .reg = PMBUS_READ_IOUT,
++ .class = PSC_CURRENT_OUT,
++ .label = "iout",
++ .paged = true,
++ .func = PMBUS_HAVE_IOUT,
++ .sfunc = PMBUS_HAVE_STATUS_IOUT,
++ .sbase = PB_STATUS_IOUT_BASE,
++ .gbit = PB_STATUS_IOUT_OC,
++ .limit = iout_limit_attrs,
++ .nlimit = ARRAY_SIZE(iout_limit_attrs),
++ }
++};
++
++/* Power attributes */
++
++static const struct pmbus_limit_attr pin_limit_attrs[] = {
++ {
++ .reg = PMBUS_PIN_OP_WARN_LIMIT,
++ .attr = "max",
++ .alarm = "alarm",
++ .sbit = PB_PIN_OP_WARNING,
++ }, {
++ .reg = PMBUS_VIRT_READ_PIN_AVG,
++ .update = true,
++ .attr = "average",
++ }, {
++ .reg = PMBUS_VIRT_READ_PIN_MAX,
++ .update = true,
++ .attr = "input_highest",
++ }, {
++ .reg = PMBUS_VIRT_RESET_PIN_HISTORY,
++ .attr = "reset_history",
++ }
++};
++
++static const struct pmbus_limit_attr pout_limit_attrs[] = {
++ {
++ .reg = PMBUS_POUT_MAX,
++ .attr = "cap",
++ .alarm = "cap_alarm",
++ .sbit = PB_POWER_LIMITING,
++ }, {
++ .reg = PMBUS_POUT_OP_WARN_LIMIT,
++ .attr = "max",
++ .alarm = "max_alarm",
++ .sbit = PB_POUT_OP_WARNING,
++ }, {
++ .reg = PMBUS_POUT_OP_FAULT_LIMIT,
++ .attr = "crit",
++ .alarm = "crit_alarm",
++ .sbit = PB_POUT_OP_FAULT,
++ }, {
++ .reg = PMBUS_VIRT_READ_POUT_AVG,
++ .update = true,
++ .attr = "average",
++ }, {
++ .reg = PMBUS_VIRT_READ_POUT_MAX,
++ .update = true,
++ .attr = "input_highest",
++ }, {
++ .reg = PMBUS_VIRT_RESET_POUT_HISTORY,
++ .attr = "reset_history",
++ }
++};
++
++static const struct pmbus_sensor_attr power_attributes[] = {
++ {
++ .reg = PMBUS_READ_PIN,
++ .class = PSC_POWER,
++ .label = "pin",
++ .func = PMBUS_HAVE_PIN,
++ .sfunc = PMBUS_HAVE_STATUS_INPUT,
++ .sbase = PB_STATUS_INPUT_BASE,
++ .limit = pin_limit_attrs,
++ .nlimit = ARRAY_SIZE(pin_limit_attrs),
++ }, {
++ .reg = PMBUS_READ_POUT,
++ .class = PSC_POWER,
++ .label = "pout",
++ .paged = true,
++ .func = PMBUS_HAVE_POUT,
++ .sfunc = PMBUS_HAVE_STATUS_IOUT,
++ .sbase = PB_STATUS_IOUT_BASE,
++ .limit = pout_limit_attrs,
++ .nlimit = ARRAY_SIZE(pout_limit_attrs),
++ }
++};
++
++/* Temperature atributes */
++
++static const struct pmbus_limit_attr temp_limit_attrs[] = {
++ {
++ .reg = PMBUS_UT_WARN_LIMIT,
++ .low = true,
++ .attr = "min",
++ .alarm = "min_alarm",
++ .sbit = PB_TEMP_UT_WARNING,
++ }, {
++ .reg = PMBUS_UT_FAULT_LIMIT,
++ .low = true,
++ .attr = "lcrit",
++ .alarm = "lcrit_alarm",
++ .sbit = PB_TEMP_UT_FAULT,
++ }, {
++ .reg = PMBUS_OT_WARN_LIMIT,
++ .attr = "max",
++ .alarm = "max_alarm",
++ .sbit = PB_TEMP_OT_WARNING,
++ }, {
++ .reg = PMBUS_OT_FAULT_LIMIT,
++ .attr = "crit",
++ .alarm = "crit_alarm",
++ .sbit = PB_TEMP_OT_FAULT,
++ }, {
++ .reg = PMBUS_VIRT_READ_TEMP_MIN,
++ .attr = "lowest",
++ }, {
++ .reg = PMBUS_VIRT_READ_TEMP_AVG,
++ .attr = "average",
++ }, {
++ .reg = PMBUS_VIRT_READ_TEMP_MAX,
++ .attr = "highest",
++ }, {
++ .reg = PMBUS_VIRT_RESET_TEMP_HISTORY,
++ .attr = "reset_history",
++ }
++};
++
++static const struct pmbus_limit_attr temp_limit_attrs2[] = {
++ {
++ .reg = PMBUS_UT_WARN_LIMIT,
++ .low = true,
++ .attr = "min",
++ .alarm = "min_alarm",
++ .sbit = PB_TEMP_UT_WARNING,
++ }, {
++ .reg = PMBUS_UT_FAULT_LIMIT,
++ .low = true,
++ .attr = "lcrit",
++ .alarm = "lcrit_alarm",
++ .sbit = PB_TEMP_UT_FAULT,
++ }, {
++ .reg = PMBUS_OT_WARN_LIMIT,
++ .attr = "max",
++ .alarm = "max_alarm",
++ .sbit = PB_TEMP_OT_WARNING,
++ }, {
++ .reg = PMBUS_OT_FAULT_LIMIT,
++ .attr = "crit",
++ .alarm = "crit_alarm",
++ .sbit = PB_TEMP_OT_FAULT,
++ }, {
++ .reg = PMBUS_VIRT_READ_TEMP2_MIN,
++ .attr = "lowest",
++ }, {
++ .reg = PMBUS_VIRT_READ_TEMP2_AVG,
++ .attr = "average",
++ }, {
++ .reg = PMBUS_VIRT_READ_TEMP2_MAX,
++ .attr = "highest",
++ }, {
++ .reg = PMBUS_VIRT_RESET_TEMP2_HISTORY,
++ .attr = "reset_history",
++ }
++};
++
++static const struct pmbus_limit_attr temp_limit_attrs3[] = {
++ {
++ .reg = PMBUS_UT_WARN_LIMIT,
++ .low = true,
++ .attr = "min",
++ .alarm = "min_alarm",
++ .sbit = PB_TEMP_UT_WARNING,
++ }, {
++ .reg = PMBUS_UT_FAULT_LIMIT,
++ .low = true,
++ .attr = "lcrit",
++ .alarm = "lcrit_alarm",
++ .sbit = PB_TEMP_UT_FAULT,
++ }, {
++ .reg = PMBUS_OT_WARN_LIMIT,
++ .attr = "max",
++ .alarm = "max_alarm",
++ .sbit = PB_TEMP_OT_WARNING,
++ }, {
++ .reg = PMBUS_OT_FAULT_LIMIT,
++ .attr = "crit",
++ .alarm = "crit_alarm",
++ .sbit = PB_TEMP_OT_FAULT,
++ }
++};
++
++static const struct pmbus_sensor_attr temp_attributes[] = {
++ {
++ .reg = PMBUS_READ_TEMPERATURE_1,
++ .class = PSC_TEMPERATURE,
++ .paged = true,
++ .update = true,
++ .compare = true,
++ .func = PMBUS_HAVE_TEMP,
++ .sfunc = PMBUS_HAVE_STATUS_TEMP,
++ .sbase = PB_STATUS_TEMP_BASE,
++ .gbit = PB_STATUS_TEMPERATURE,
++ .limit = temp_limit_attrs,
++ .nlimit = ARRAY_SIZE(temp_limit_attrs),
++ }, {
++ .reg = PMBUS_READ_TEMPERATURE_2,
++ .class = PSC_TEMPERATURE,
++ .paged = true,
++ .update = true,
++ .compare = true,
++ .func = PMBUS_HAVE_TEMP2,
++ .sfunc = PMBUS_HAVE_STATUS_TEMP,
++ .sbase = PB_STATUS_TEMP_BASE,
++ .gbit = PB_STATUS_TEMPERATURE,
++ .limit = temp_limit_attrs2,
++ .nlimit = ARRAY_SIZE(temp_limit_attrs2),
++ }, {
++ .reg = PMBUS_READ_TEMPERATURE_3,
++ .class = PSC_TEMPERATURE,
++ .paged = true,
++ .update = true,
++ .compare = true,
++ .func = PMBUS_HAVE_TEMP3,
++ .sfunc = PMBUS_HAVE_STATUS_TEMP,
++ .sbase = PB_STATUS_TEMP_BASE,
++ .gbit = PB_STATUS_TEMPERATURE,
++ .limit = temp_limit_attrs3,
++ .nlimit = ARRAY_SIZE(temp_limit_attrs3),
++ }
++};
++
++static const int pmbus_fan_registers[] = {
++ PMBUS_READ_FAN_SPEED_1,
++ PMBUS_READ_FAN_SPEED_2,
++ PMBUS_READ_FAN_SPEED_3,
++ PMBUS_READ_FAN_SPEED_4
++};
++
++static const int pmbus_fan_config_registers[] = {
++ PMBUS_FAN_CONFIG_12,
++ PMBUS_FAN_CONFIG_12,
++ PMBUS_FAN_CONFIG_34,
++ PMBUS_FAN_CONFIG_34
++};
++
++static const int pmbus_fan_status_registers[] = {
++ PMBUS_STATUS_FAN_12,
++ PMBUS_STATUS_FAN_12,
++ PMBUS_STATUS_FAN_34,
++ PMBUS_STATUS_FAN_34
++};
++
++static const u32 pmbus_fan_flags[] = {
++ PMBUS_HAVE_FAN12,
++ PMBUS_HAVE_FAN12,
++ PMBUS_HAVE_FAN34,
++ PMBUS_HAVE_FAN34
++};
++
++static const u32 pmbus_fan_status_flags[] = {
++ PMBUS_HAVE_STATUS_FAN12,
++ PMBUS_HAVE_STATUS_FAN12,
++ PMBUS_HAVE_STATUS_FAN34,
++ PMBUS_HAVE_STATUS_FAN34
++};
++
++/* Fans */
++static int pmbus_add_fan_attributes(struct i2c_client *client,
++ struct pmbus_data *data)
++{
++ const struct pmbus_driver_info *info = data->info;
++ int index = 1;
++ int page;
++ int ret;
++
++ for (page = 0; page < info->pages; page++) {
++ int f;
++
++ for (f = 0; f < ARRAY_SIZE(pmbus_fan_registers); f++) {
++ int regval;
++
++ if (!(info->func[page] & pmbus_fan_flags[f]))
++ break;
++
++ if (!pmbus_check_word_register(client, page,
++ pmbus_fan_registers[f]))
++ break;
++
++ /*
++ * Skip fan if not installed.
++ * Each fan configuration register covers multiple fans,
++ * so we have to do some magic.
++ */
++ regval = _pmbus_read_byte_data(client, page,
++ pmbus_fan_config_registers[f]);
++ if (regval < 0 ||
++ (!(regval & (PB_FAN_1_INSTALLED >> ((f & 1) * 4)))))
++ continue;
++
++ if (pmbus_add_sensor(data, "fan", "input", index,
++ page, pmbus_fan_registers[f],
++ PSC_FAN, true, true) == NULL)
++ return -ENOMEM;
++
++ /*
++ * Each fan status register covers multiple fans,
++ * so we have to do some magic.
++ */
++ if ((info->func[page] & pmbus_fan_status_flags[f]) &&
++ pmbus_check_byte_register(client,
++ page, pmbus_fan_status_registers[f])) {
++ int base;
++
++ if (f > 1) /* fan 3, 4 */
++ base = PB_STATUS_FAN34_BASE + page;
++ else
++ base = PB_STATUS_FAN_BASE + page;
++ ret = pmbus_add_boolean(data, "fan",
++ "alarm", index, NULL, NULL, base,
++ PB_FAN_FAN1_WARNING >> (f & 1));
++ if (ret)
++ return ret;
++ ret = pmbus_add_boolean(data, "fan",
++ "fault", index, NULL, NULL, base,
++ PB_FAN_FAN1_FAULT >> (f & 1));
++ if (ret)
++ return ret;
++ }
++ index++;
++ }
++ }
++ return 0;
++}
++
++static const u32 pmbus_mfr_registers[] = {
++ PMBUS_MFR_ID,
++ PMBUS_MFR_MODEL,
++ PMBUS_MFR_REVISION,
++ /*
++ * PMBUS_MFR_LOCATION is not implemented according to spec
++ * in the pfe1100; rather than showing up as a block read,
++ * it's a word read. Even worse, our block read implementation
++ * will get the first byte, 'A', and stomp all over our buffer,
++ * rather than politely declining to read 65 bytes, as it should.
++ *
++ * Clearly, we should fix the implementation rather than hack it
++ * in here, but we want to get this out the door. With more
++ * experience, hopefully we can come up with a more general
++ * implmentation of the MFR register reads.
++ */
++ PMBUS_MFR_DATE,
++ PMBUS_MFR_SERIAL,
++};
++
++static const char *pmbus_mfr_names[] = {
++ "mfr_id",
++ "mfr_model",
++ "mfr_revision",
++ /* "mfr_location", as mentioned above, is not readable */
++ "mfr_date",
++ "mfr_serial",
++};
++
++/* MFR info */
++static int pmbus_add_mfr_attributes(struct i2c_client *client,
++ struct pmbus_data *data)
++{
++ int f;
++ char buf[I2C_SMBUS_BLOCK_MAX + 1];
++
++ if ((data->info->func[0] & PMBUS_HAVE_MFRDATA) == 0 ||
++ !i2c_check_functionality(client->adapter,
++ I2C_FUNC_SMBUS_READ_BLOCK_DATA))
++ return 0;
++
++ for (f = 0; f < ARRAY_SIZE(pmbus_mfr_registers); f++) {
++ int ret;
++
++ pmbus_wait(client);
++ ret = i2c_smbus_read_block_data(client, pmbus_mfr_registers[f],
++ buf);
++ pmbus_update_wait(client);
++ if (ret <= 0)
++ continue;
++
++ buf[ret] = 0;
++ if (!(data->flags & PMBUS_SKIP_STATUS_CHECK)) {
++ ret = pmbus_check_status_cml(client);
++ pmbus_clear_fault_page(client, -1);
++ if (ret < 0)
++ continue;
++ }
++
++ /* Note that the label code truncates to PMBUS_NAME_SIZE */
++
++ ret = pmbus_add_label(data, pmbus_mfr_names[f], -1, buf, 0);
++ if (ret)
++ return ret;
++ }
++ return 0;
++}
++
++static int pmbus_find_attributes(struct i2c_client *client,
++ struct pmbus_data *data)
++{
++ int ret;
++
++ /* Voltage sensors */
++ ret = pmbus_add_sensor_attrs(client, data, "in", voltage_attributes,
++ ARRAY_SIZE(voltage_attributes));
++ if (ret)
++ return ret;
++
++ /* Current sensors */
++ ret = pmbus_add_sensor_attrs(client, data, "curr", current_attributes,
++ ARRAY_SIZE(current_attributes));
++ if (ret)
++ return ret;
++
++ /* Power sensors */
++ ret = pmbus_add_sensor_attrs(client, data, "power", power_attributes,
++ ARRAY_SIZE(power_attributes));
++ if (ret)
++ return ret;
++
++ /* Temperature sensors */
++ ret = pmbus_add_sensor_attrs(client, data, "temp", temp_attributes,
++ ARRAY_SIZE(temp_attributes));
++ if (ret)
++ return ret;
++
++ /* Fans */
++ ret = pmbus_add_fan_attributes(client, data);
++ if (ret)
++ return ret;
++
++ /* Manufacturer strings */
++ ret = pmbus_add_mfr_attributes(client, data);
++ return ret;
++}
++
++/*
++ * Identify chip parameters.
++ * This function is called for all chips.
++ */
++static int pmbus_identify_common(struct i2c_client *client,
++ struct pmbus_data *data)
++{
++ int vout_mode = -1;
++
++ if (pmbus_check_byte_register(client, 0, PMBUS_VOUT_MODE))
++ vout_mode = _pmbus_read_byte_data(client, 0, PMBUS_VOUT_MODE);
++ if (vout_mode >= 0 && vout_mode != 0xff) {
++ /*
++ * Not all chips support the VOUT_MODE command,
++ * so a failure to read it is not an error.
++ */
++ switch (vout_mode >> 5) {
++ case 0: /* linear mode */
++ if (data->info->format[PSC_VOLTAGE_OUT] != linear)
++ return -ENODEV;
++
++ data->exponent = ((s8)(vout_mode << 3)) >> 3;
++ break;
++ case 1: /* VID mode */
++ if (data->info->format[PSC_VOLTAGE_OUT] != vid)
++ return -ENODEV;
++ break;
++ case 2: /* direct mode */
++ if (data->info->format[PSC_VOLTAGE_OUT] != direct)
++ return -ENODEV;
++ break;
++ default:
++ return -ENODEV;
++ }
++ }
++
++ pmbus_clear_fault_page(client, 0);
++ return 0;
++}
++
++static int pmbus_init_common(struct i2c_client *client, struct pmbus_data *data,
++ struct pmbus_driver_info *info)
++{
++ struct device *dev = &client->dev;
++ int ret;
++
++ /*
++ * Some PMBus chips don't support PMBUS_STATUS_BYTE, so try
++ * to use PMBUS_STATUS_WORD instead if that is the case.
++ * Bail out if both registers are not supported.
++ */
++ data->status_register = PMBUS_STATUS_WORD;
++ pmbus_wait(client);
++ ret = i2c_smbus_read_word_data(client, PMBUS_STATUS_WORD);
++ pmbus_update_wait(client);
++ if (ret < 0 || ret == 0xffff) {
++ data->status_register = PMBUS_STATUS_BYTE;
++ pmbus_wait(client);
++ ret = i2c_smbus_read_byte_data(client, PMBUS_STATUS_BYTE);
++ pmbus_update_wait(client);
++ if (ret < 0 || ret == 0xff) {
++ dev_err(dev, "PMBus status register not found\n");
++ return -ENODEV;
++ }
++ }
++
++ pmbus_clear_faults(client);
++
++ if (info->identify) {
++ ret = (*info->identify)(client, info);
++ if (ret < 0) {
++ dev_err(dev, "Chip identification failed\n");
++ return ret;
++ }
++ }
++
++ if (info->pages <= 0 || info->pages > PMBUS_PAGES) {
++ dev_err(dev, "Bad number of PMBus pages: %d\n", info->pages);
++ return -ENODEV;
++ }
++
++ ret = pmbus_identify_common(client, data);
++ if (ret < 0) {
++ dev_err(dev, "Failed to identify chip capabilities\n");
++ return ret;
++ }
++ return 0;
++}
++
++int pmbus_do_probe(struct i2c_client *client, const struct i2c_device_id *id,
++ struct pmbus_driver_info *info)
++{
++ struct device *dev = &client->dev;
++ const struct pmbus_platform_data *pdata = dev->platform_data;
++ struct pmbus_data *data;
++ int ret;
++
++ if (!info)
++ return -ENODEV;
++
++ if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_WRITE_BYTE
++ | I2C_FUNC_SMBUS_BYTE_DATA
++ | I2C_FUNC_SMBUS_WORD_DATA))
++ return -ENODEV;
++
++ data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
++ if (!data)
++ return -ENOMEM;
++
++ i2c_set_clientdata(client, data);
++ mutex_init(&data->update_lock);
++ data->dev = dev;
++
++ if (pdata)
++ data->flags = pdata->flags;
++ data->info = info;
++ pmbus_update_wait(client); /* Set time of access if info->delay */
++
++ ret = pmbus_init_common(client, data, info);
++ if (ret < 0)
++ return ret;
++
++ ret = pmbus_find_attributes(client, data);
++ if (ret)
++ goto out_kfree;
++
++ /*
++ * If there are no attributes, something is wrong.
++ * Bail out instead of trying to register nothing.
++ */
++ if (!data->num_attributes) {
++ dev_err(dev, "No attributes found\n");
++ ret = -ENODEV;
++ goto out_kfree;
++ }
++
++ /* Register sysfs hooks */
++ ret = sysfs_create_group(&dev->kobj, &data->group);
++ if (ret) {
++ dev_err(dev, "Failed to create sysfs entries\n");
++ goto out_kfree;
++ }
++ data->hwmon_dev = hwmon_device_register(dev);
++ if (IS_ERR(data->hwmon_dev)) {
++ ret = PTR_ERR(data->hwmon_dev);
++ dev_err(dev, "Failed to register hwmon device\n");
++ goto out_hwmon_device_register;
++ }
++ return 0;
++
++out_hwmon_device_register:
++ sysfs_remove_group(&dev->kobj, &data->group);
++out_kfree:
++ kfree(data->group.attrs);
++ return ret;
++}
++EXPORT_SYMBOL_GPL(pmbus_do_probe);
++
++int pmbus_do_remove(struct i2c_client *client)
++{
++ struct pmbus_data *data = i2c_get_clientdata(client);
++ hwmon_device_unregister(data->hwmon_dev);
++ sysfs_remove_group(&client->dev.kobj, &data->group);
++ kfree(data->group.attrs);
++ return 0;
++}
++EXPORT_SYMBOL_GPL(pmbus_do_remove);
++
++MODULE_AUTHOR("Guenter Roeck");
++MODULE_DESCRIPTION("PMBus core driver");
++MODULE_LICENSE("GPL");
+diff --git a/drivers/hwmon/pmbus/ucd9000.c b/drivers/hwmon/pmbus/ucd9000.c
+new file mode 100644
+index 0000000..fbb1479
+--- /dev/null
++++ b/drivers/hwmon/pmbus/ucd9000.c
+@@ -0,0 +1,246 @@
++/*
++ * Hardware monitoring driver for UCD90xxx Sequencer and System Health
++ * Controller series
++ *
++ * Copyright (C) 2011 Ericsson AB.
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
++ */
++
++#include <linux/kernel.h>
++#include <linux/module.h>
++#include <linux/init.h>
++#include <linux/err.h>
++#include <linux/slab.h>
++#include <linux/i2c.h>
++#include <linux/i2c/pmbus.h>
++#include "pmbus.h"
++
++enum chips { ucd9000, ucd90120, ucd90124, ucd9090, ucd90910 };
++
++#define UCD9000_MONITOR_CONFIG 0xd5
++#define UCD9000_NUM_PAGES 0xd6
++#define UCD9000_FAN_CONFIG_INDEX 0xe7
++#define UCD9000_FAN_CONFIG 0xe8
++#define UCD9000_DEVICE_ID 0xfd
++
++#define UCD9000_MON_TYPE(x) (((x) >> 5) & 0x07)
++#define UCD9000_MON_PAGE(x) ((x) & 0x0f)
++
++#define UCD9000_MON_VOLTAGE 1
++#define UCD9000_MON_TEMPERATURE 2
++#define UCD9000_MON_CURRENT 3
++#define UCD9000_MON_VOLTAGE_HW 4
++
++#define UCD9000_NUM_FAN 4
++
++struct ucd9000_data {
++ u8 fan_data[UCD9000_NUM_FAN][I2C_SMBUS_BLOCK_MAX];
++ struct pmbus_driver_info info;
++};
++#define to_ucd9000_data(_info) container_of(_info, struct ucd9000_data, info)
++
++static int ucd9000_get_fan_config(struct i2c_client *client, int fan)
++{
++ int fan_config = 0;
++ struct ucd9000_data *data
++ = to_ucd9000_data(pmbus_get_driver_info(client));
++
++ if (data->fan_data[fan][3] & 1)
++ fan_config |= PB_FAN_2_INSTALLED; /* Use lower bit position */
++
++ /* Pulses/revolution */
++ fan_config |= (data->fan_data[fan][3] & 0x06) >> 1;
++
++ return fan_config;
++}
++
++static int ucd9000_read_byte_data(struct i2c_client *client, int page, int reg)
++{
++ int ret = 0;
++ int fan_config;
++
++ switch (reg) {
++ case PMBUS_FAN_CONFIG_12:
++ if (page > 0)
++ return -ENXIO;
++
++ ret = ucd9000_get_fan_config(client, 0);
++ if (ret < 0)
++ return ret;
++ fan_config = ret << 4;
++ ret = ucd9000_get_fan_config(client, 1);
++ if (ret < 0)
++ return ret;
++ fan_config |= ret;
++ ret = fan_config;
++ break;
++ case PMBUS_FAN_CONFIG_34:
++ if (page > 0)
++ return -ENXIO;
++
++ ret = ucd9000_get_fan_config(client, 2);
++ if (ret < 0)
++ return ret;
++ fan_config = ret << 4;
++ ret = ucd9000_get_fan_config(client, 3);
++ if (ret < 0)
++ return ret;
++ fan_config |= ret;
++ ret = fan_config;
++ break;
++ default:
++ ret = -ENODATA;
++ break;
++ }
++ return ret;
++}
++
++static const struct i2c_device_id ucd9000_id[] = {
++ {"ucd9000", ucd9000},
++ {"ucd90120", ucd90120},
++ {"ucd90124", ucd90124},
++ {"ucd9090", ucd9090},
++ {"ucd90910", ucd90910},
++ {}
++};
++MODULE_DEVICE_TABLE(i2c, ucd9000_id);
++
++static int ucd9000_probe(struct i2c_client *client,
++ const struct i2c_device_id *id)
++{
++ u8 block_buffer[I2C_SMBUS_BLOCK_MAX + 1];
++ struct ucd9000_data *data;
++ struct pmbus_driver_info *info;
++ const struct i2c_device_id *mid;
++ int i, ret;
++
++ if (!i2c_check_functionality(client->adapter,
++ I2C_FUNC_SMBUS_BYTE_DATA |
++ I2C_FUNC_SMBUS_BLOCK_DATA))
++ return -ENODEV;
++
++ ret = i2c_smbus_read_block_data(client, UCD9000_DEVICE_ID,
++ block_buffer);
++ if (ret < 0) {
++ dev_err(&client->dev, "Failed to read device ID\n");
++ return ret;
++ }
++ block_buffer[ret] = '\0';
++ dev_info(&client->dev, "Device ID %s\n", block_buffer);
++
++ for (mid = ucd9000_id; mid->name[0]; mid++) {
++ if (!strncasecmp(mid->name, block_buffer, strlen(mid->name)))
++ break;
++ }
++ if (!mid->name[0]) {
++ dev_err(&client->dev, "Unsupported device\n");
++ return -ENODEV;
++ }
++
++ if (id->driver_data != ucd9000 && id->driver_data != mid->driver_data)
++ dev_notice(&client->dev,
++ "Device mismatch: Configured %s, detected %s\n",
++ id->name, mid->name);
++
++ data = devm_kzalloc(&client->dev, sizeof(struct ucd9000_data),
++ GFP_KERNEL);
++ if (!data)
++ return -ENOMEM;
++ info = &data->info;
++
++ ret = i2c_smbus_read_byte_data(client, UCD9000_NUM_PAGES);
++ if (ret < 0) {
++ dev_err(&client->dev,
++ "Failed to read number of active pages\n");
++ return ret;
++ }
++ info->pages = ret;
++ if (!info->pages) {
++ dev_err(&client->dev, "No pages configured\n");
++ return -ENODEV;
++ }
++
++ /* The internal temperature sensor is always active */
++ info->func[0] = PMBUS_HAVE_TEMP;
++
++ /* Everything else is configurable */
++ ret = i2c_smbus_read_block_data(client, UCD9000_MONITOR_CONFIG,
++ block_buffer);
++ if (ret <= 0) {
++ dev_err(&client->dev, "Failed to read configuration data\n");
++ return -ENODEV;
++ }
++ for (i = 0; i < ret; i++) {
++ int page = UCD9000_MON_PAGE(block_buffer[i]);
++
++ if (page >= info->pages)
++ continue;
++
++ switch (UCD9000_MON_TYPE(block_buffer[i])) {
++ case UCD9000_MON_VOLTAGE:
++ case UCD9000_MON_VOLTAGE_HW:
++ info->func[page] |= PMBUS_HAVE_VOUT
++ | PMBUS_HAVE_STATUS_VOUT;
++ break;
++ case UCD9000_MON_TEMPERATURE:
++ info->func[page] |= PMBUS_HAVE_TEMP2
++ | PMBUS_HAVE_STATUS_TEMP;
++ break;
++ case UCD9000_MON_CURRENT:
++ info->func[page] |= PMBUS_HAVE_IOUT
++ | PMBUS_HAVE_STATUS_IOUT;
++ break;
++ default:
++ break;
++ }
++ }
++
++ /* Fan configuration */
++ if (mid->driver_data == ucd90124) {
++ for (i = 0; i < UCD9000_NUM_FAN; i++) {
++ i2c_smbus_write_byte_data(client,
++ UCD9000_FAN_CONFIG_INDEX, i);
++ ret = i2c_smbus_read_block_data(client,
++ UCD9000_FAN_CONFIG,
++ data->fan_data[i]);
++ if (ret < 0)
++ return ret;
++ }
++ i2c_smbus_write_byte_data(client, UCD9000_FAN_CONFIG_INDEX, 0);
++
++ info->read_byte_data = ucd9000_read_byte_data;
++ info->func[0] |= PMBUS_HAVE_FAN12 | PMBUS_HAVE_STATUS_FAN12
++ | PMBUS_HAVE_FAN34 | PMBUS_HAVE_STATUS_FAN34;
++ }
++
++ return pmbus_do_probe(client, mid, info);
++}
++
++/* This is the driver that will be inserted */
++static struct i2c_driver ucd9000_driver = {
++ .driver = {
++ .name = "ucd9000",
++ },
++ .probe = ucd9000_probe,
++ .remove = pmbus_do_remove,
++ .id_table = ucd9000_id,
++};
++
++module_i2c_driver(ucd9000_driver);
++
++MODULE_AUTHOR("Guenter Roeck");
++MODULE_DESCRIPTION("PMBus driver for TI UCD90xxx");
++MODULE_LICENSE("GPL");
+diff --git a/drivers/hwmon/pmbus/ucd9200.c b/drivers/hwmon/pmbus/ucd9200.c
+new file mode 100644
+index 0000000..033d6ac
+--- /dev/null
++++ b/drivers/hwmon/pmbus/ucd9200.c
+@@ -0,0 +1,180 @@
++/*
++ * Hardware monitoring driver for ucd9200 series Digital PWM System Controllers
++ *
++ * Copyright (C) 2011 Ericsson AB.
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
++ */
++
++#include <linux/kernel.h>
++#include <linux/module.h>
++#include <linux/init.h>
++#include <linux/err.h>
++#include <linux/slab.h>
++#include <linux/i2c.h>
++#include <linux/i2c/pmbus.h>
++#include "pmbus.h"
++
++#define UCD9200_PHASE_INFO 0xd2
++#define UCD9200_DEVICE_ID 0xfd
++
++enum chips { ucd9200, ucd9220, ucd9222, ucd9224, ucd9240, ucd9244, ucd9246,
++ ucd9248 };
++
++static const struct i2c_device_id ucd9200_id[] = {
++ {"ucd9200", ucd9200},
++ {"ucd9220", ucd9220},
++ {"ucd9222", ucd9222},
++ {"ucd9224", ucd9224},
++ {"ucd9240", ucd9240},
++ {"ucd9244", ucd9244},
++ {"ucd9246", ucd9246},
++ {"ucd9248", ucd9248},
++ {}
++};
++MODULE_DEVICE_TABLE(i2c, ucd9200_id);
++
++static int ucd9200_probe(struct i2c_client *client,
++ const struct i2c_device_id *id)
++{
++ u8 block_buffer[I2C_SMBUS_BLOCK_MAX + 1];
++ struct pmbus_driver_info *info;
++ const struct i2c_device_id *mid;
++ int i, j, ret;
++
++ if (!i2c_check_functionality(client->adapter,
++ I2C_FUNC_SMBUS_BYTE_DATA |
++ I2C_FUNC_SMBUS_BLOCK_DATA))
++ return -ENODEV;
++
++ ret = i2c_smbus_read_block_data(client, UCD9200_DEVICE_ID,
++ block_buffer);
++ if (ret < 0) {
++ dev_err(&client->dev, "Failed to read device ID\n");
++ return ret;
++ }
++ block_buffer[ret] = '\0';
++ dev_info(&client->dev, "Device ID %s\n", block_buffer);
++
++ for (mid = ucd9200_id; mid->name[0]; mid++) {
++ if (!strncasecmp(mid->name, block_buffer, strlen(mid->name)))
++ break;
++ }
++ if (!mid->name[0]) {
++ dev_err(&client->dev, "Unsupported device\n");
++ return -ENODEV;
++ }
++ if (id->driver_data != ucd9200 && id->driver_data != mid->driver_data)
++ dev_notice(&client->dev,
++ "Device mismatch: Configured %s, detected %s\n",
++ id->name, mid->name);
++
++ info = devm_kzalloc(&client->dev, sizeof(struct pmbus_driver_info),
++ GFP_KERNEL);
++ if (!info)
++ return -ENOMEM;
++
++ ret = i2c_smbus_read_block_data(client, UCD9200_PHASE_INFO,
++ block_buffer);
++ if (ret < 0) {
++ dev_err(&client->dev, "Failed to read phase information\n");
++ return ret;
++ }
++
++ /*
++ * Calculate number of configured pages (rails) from PHASE_INFO
++ * register.
++ * Rails have to be sequential, so we can abort after finding
++ * the first unconfigured rail.
++ */
++ info->pages = 0;
++ for (i = 0; i < ret; i++) {
++ if (!block_buffer[i])
++ break;
++ info->pages++;
++ }
++ if (!info->pages) {
++ dev_err(&client->dev, "No rails configured\n");
++ return -ENODEV;
++ }
++ dev_info(&client->dev, "%d rails configured\n", info->pages);
++
++ /*
++ * Set PHASE registers on all pages to 0xff to ensure that phase
++ * specific commands will apply to all phases of a given page (rail).
++ * This only affects the READ_IOUT and READ_TEMPERATURE2 registers.
++ * READ_IOUT will return the sum of currents of all phases of a rail,
++ * and READ_TEMPERATURE2 will return the maximum temperature detected
++ * for the the phases of the rail.
++ */
++ for (i = 0; i < info->pages; i++) {
++ /*
++ * Setting PAGE & PHASE fails once in a while for no obvious
++ * reason, so we need to retry a couple of times.
++ */
++ for (j = 0; j < 3; j++) {
++ ret = i2c_smbus_write_byte_data(client, PMBUS_PAGE, i);
++ if (ret < 0)
++ continue;
++ ret = i2c_smbus_write_byte_data(client, PMBUS_PHASE,
++ 0xff);
++ if (ret < 0)
++ continue;
++ break;
++ }
++ if (ret < 0) {
++ dev_err(&client->dev,
++ "Failed to initialize PHASE registers\n");
++ return ret;
++ }
++ }
++ if (info->pages > 1)
++ i2c_smbus_write_byte_data(client, PMBUS_PAGE, 0);
++
++ info->func[0] = PMBUS_HAVE_VIN | PMBUS_HAVE_STATUS_INPUT |
++ PMBUS_HAVE_IIN | PMBUS_HAVE_PIN |
++ PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT |
++ PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT |
++ PMBUS_HAVE_POUT | PMBUS_HAVE_TEMP |
++ PMBUS_HAVE_TEMP2 | PMBUS_HAVE_STATUS_TEMP;
++
++ for (i = 1; i < info->pages; i++)
++ info->func[i] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT |
++ PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT |
++ PMBUS_HAVE_POUT |
++ PMBUS_HAVE_TEMP2 | PMBUS_HAVE_STATUS_TEMP;
++
++ /* ucd9240 supports a single fan */
++ if (mid->driver_data == ucd9240)
++ info->func[0] |= PMBUS_HAVE_FAN12 | PMBUS_HAVE_STATUS_FAN12;
++
++ return pmbus_do_probe(client, mid, info);
++}
++
++/* This is the driver that will be inserted */
++static struct i2c_driver ucd9200_driver = {
++ .driver = {
++ .name = "ucd9200",
++ },
++ .probe = ucd9200_probe,
++ .remove = pmbus_do_remove,
++ .id_table = ucd9200_id,
++};
++
++module_i2c_driver(ucd9200_driver);
++
++MODULE_AUTHOR("Guenter Roeck");
++MODULE_DESCRIPTION("PMBus driver for TI UCD922x, UCD924x");
++MODULE_LICENSE("GPL");
+diff --git a/drivers/hwmon/pmbus/zl6100.c b/drivers/hwmon/pmbus/zl6100.c
+new file mode 100644
+index 0000000..8196441
+--- /dev/null
++++ b/drivers/hwmon/pmbus/zl6100.c
+@@ -0,0 +1,419 @@
++/*
++ * Hardware monitoring driver for ZL6100 and compatibles
++ *
++ * Copyright (c) 2011 Ericsson AB.
++ * Copyright (c) 2012 Guenter Roeck
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
++ */
++
++#include <linux/kernel.h>
++#include <linux/module.h>
++#include <linux/init.h>
++#include <linux/err.h>
++#include <linux/slab.h>
++#include <linux/i2c.h>
++#include <linux/ktime.h>
++#include <linux/delay.h>
++#include "pmbus.h"
++
++enum chips { zl2004, zl2005, zl2006, zl2008, zl2105, zl2106, zl6100, zl6105,
++ zl9101, zl9117 };
++
++struct zl6100_data {
++ int id;
++ ktime_t access; /* chip access time */
++ int delay; /* Delay between chip accesses in uS */
++ struct pmbus_driver_info info;
++};
++
++#define to_zl6100_data(x) container_of(x, struct zl6100_data, info)
++
++#define ZL6100_MFR_CONFIG 0xd0
++#define ZL6100_DEVICE_ID 0xe4
++
++#define ZL6100_MFR_XTEMP_ENABLE (1 << 7)
++
++#define MFR_VMON_OV_FAULT_LIMIT 0xf5
++#define MFR_VMON_UV_FAULT_LIMIT 0xf6
++#define MFR_READ_VMON 0xf7
++
++#define VMON_UV_WARNING (1 << 5)
++#define VMON_OV_WARNING (1 << 4)
++#define VMON_UV_FAULT (1 << 1)
++#define VMON_OV_FAULT (1 << 0)
++
++#define ZL6100_WAIT_TIME 1000 /* uS */
++
++static ushort delay = ZL6100_WAIT_TIME;
++module_param(delay, ushort, 0644);
++MODULE_PARM_DESC(delay, "Delay between chip accesses in uS");
++
++/* Convert linear sensor value to milli-units */
++static long zl6100_l2d(s16 l)
++{
++ s16 exponent;
++ s32 mantissa;
++ long val;
++
++ exponent = l >> 11;
++ mantissa = ((s16)((l & 0x7ff) << 5)) >> 5;
++
++ val = mantissa;
++
++ /* scale result to milli-units */
++ val = val * 1000L;
++
++ if (exponent >= 0)
++ val <<= exponent;
++ else
++ val >>= -exponent;
++
++ return val;
++}
++
++#define MAX_MANTISSA (1023 * 1000)
++#define MIN_MANTISSA (511 * 1000)
++
++static u16 zl6100_d2l(long val)
++{
++ s16 exponent = 0, mantissa;
++ bool negative = false;
++
++ /* simple case */
++ if (val == 0)
++ return 0;
++
++ if (val < 0) {
++ negative = true;
++ val = -val;
++ }
++
++ /* Reduce large mantissa until it fits into 10 bit */
++ while (val >= MAX_MANTISSA && exponent < 15) {
++ exponent++;
++ val >>= 1;
++ }
++ /* Increase small mantissa to improve precision */
++ while (val < MIN_MANTISSA && exponent > -15) {
++ exponent--;
++ val <<= 1;
++ }
++
++ /* Convert mantissa from milli-units to units */
++ mantissa = DIV_ROUND_CLOSEST(val, 1000);
++
++ /* Ensure that resulting number is within range */
++ if (mantissa > 0x3ff)
++ mantissa = 0x3ff;
++
++ /* restore sign */
++ if (negative)
++ mantissa = -mantissa;
++
++ /* Convert to 5 bit exponent, 11 bit mantissa */
++ return (mantissa & 0x7ff) | ((exponent << 11) & 0xf800);
++}
++
++/* Some chips need a delay between accesses */
++static inline void zl6100_wait(const struct zl6100_data *data)
++{
++ if (data->delay) {
++ s64 delta = ktime_us_delta(ktime_get(), data->access);
++ if (delta < data->delay)
++ udelay(data->delay - delta);
++ }
++}
++
++static int zl6100_read_word_data(struct i2c_client *client, int page, int reg)
++{
++ const struct pmbus_driver_info *info = pmbus_get_driver_info(client);
++ struct zl6100_data *data = to_zl6100_data(info);
++ int ret, vreg;
++
++ if (page > 0)
++ return -ENXIO;
++
++ if (data->id == zl2005) {
++ /*
++ * Limit register detection is not reliable on ZL2005.
++ * Make sure registers are not erroneously detected.
++ */
++ switch (reg) {
++ case PMBUS_VOUT_OV_WARN_LIMIT:
++ case PMBUS_VOUT_UV_WARN_LIMIT:
++ case PMBUS_IOUT_OC_WARN_LIMIT:
++ return -ENXIO;
++ }
++ }
++
++ switch (reg) {
++ case PMBUS_VIRT_READ_VMON:
++ vreg = MFR_READ_VMON;
++ break;
++ case PMBUS_VIRT_VMON_OV_WARN_LIMIT:
++ case PMBUS_VIRT_VMON_OV_FAULT_LIMIT:
++ vreg = MFR_VMON_OV_FAULT_LIMIT;
++ break;
++ case PMBUS_VIRT_VMON_UV_WARN_LIMIT:
++ case PMBUS_VIRT_VMON_UV_FAULT_LIMIT:
++ vreg = MFR_VMON_UV_FAULT_LIMIT;
++ break;
++ default:
++ if (reg >= PMBUS_VIRT_BASE)
++ return -ENXIO;
++ vreg = reg;
++ break;
++ }
++
++ zl6100_wait(data);
++ ret = pmbus_read_word_data(client, page, vreg);
++ data->access = ktime_get();
++ if (ret < 0)
++ return ret;
++
++ switch (reg) {
++ case PMBUS_VIRT_VMON_OV_WARN_LIMIT:
++ ret = zl6100_d2l(DIV_ROUND_CLOSEST(zl6100_l2d(ret) * 9, 10));
++ break;
++ case PMBUS_VIRT_VMON_UV_WARN_LIMIT:
++ ret = zl6100_d2l(DIV_ROUND_CLOSEST(zl6100_l2d(ret) * 11, 10));
++ break;
++ }
++
++ return ret;
++}
++
++static int zl6100_read_byte_data(struct i2c_client *client, int page, int reg)
++{
++ const struct pmbus_driver_info *info = pmbus_get_driver_info(client);
++ struct zl6100_data *data = to_zl6100_data(info);
++ int ret, status;
++
++ if (page > 0)
++ return -ENXIO;
++
++ zl6100_wait(data);
++
++ switch (reg) {
++ case PMBUS_VIRT_STATUS_VMON:
++ ret = pmbus_read_byte_data(client, 0,
++ PMBUS_STATUS_MFR_SPECIFIC);
++ if (ret < 0)
++ break;
++
++ status = 0;
++ if (ret & VMON_UV_WARNING)
++ status |= PB_VOLTAGE_UV_WARNING;
++ if (ret & VMON_OV_WARNING)
++ status |= PB_VOLTAGE_OV_WARNING;
++ if (ret & VMON_UV_FAULT)
++ status |= PB_VOLTAGE_UV_FAULT;
++ if (ret & VMON_OV_FAULT)
++ status |= PB_VOLTAGE_OV_FAULT;
++ ret = status;
++ break;
++ default:
++ ret = pmbus_read_byte_data(client, page, reg);
++ break;
++ }
++ data->access = ktime_get();
++
++ return ret;
++}
++
++static int zl6100_write_word_data(struct i2c_client *client, int page, int reg,
++ u16 word)
++{
++ const struct pmbus_driver_info *info = pmbus_get_driver_info(client);
++ struct zl6100_data *data = to_zl6100_data(info);
++ int ret, vreg;
++
++ if (page > 0)
++ return -ENXIO;
++
++ switch (reg) {
++ case PMBUS_VIRT_VMON_OV_WARN_LIMIT:
++ word = zl6100_d2l(DIV_ROUND_CLOSEST(zl6100_l2d(word) * 10, 9));
++ vreg = MFR_VMON_OV_FAULT_LIMIT;
++ pmbus_clear_cache(client);
++ break;
++ case PMBUS_VIRT_VMON_OV_FAULT_LIMIT:
++ vreg = MFR_VMON_OV_FAULT_LIMIT;
++ pmbus_clear_cache(client);
++ break;
++ case PMBUS_VIRT_VMON_UV_WARN_LIMIT:
++ word = zl6100_d2l(DIV_ROUND_CLOSEST(zl6100_l2d(word) * 10, 11));
++ vreg = MFR_VMON_UV_FAULT_LIMIT;
++ pmbus_clear_cache(client);
++ break;
++ case PMBUS_VIRT_VMON_UV_FAULT_LIMIT:
++ vreg = MFR_VMON_UV_FAULT_LIMIT;
++ pmbus_clear_cache(client);
++ break;
++ default:
++ if (reg >= PMBUS_VIRT_BASE)
++ return -ENXIO;
++ vreg = reg;
++ }
++
++ zl6100_wait(data);
++ ret = pmbus_write_word_data(client, page, vreg, word);
++ data->access = ktime_get();
++
++ return ret;
++}
++
++static int zl6100_write_byte(struct i2c_client *client, int page, u8 value)
++{
++ const struct pmbus_driver_info *info = pmbus_get_driver_info(client);
++ struct zl6100_data *data = to_zl6100_data(info);
++ int ret;
++
++ if (page > 0)
++ return -ENXIO;
++
++ zl6100_wait(data);
++ ret = pmbus_write_byte(client, page, value);
++ data->access = ktime_get();
++
++ return ret;
++}
++
++static const struct i2c_device_id zl6100_id[] = {
++ {"bmr450", zl2005},
++ {"bmr451", zl2005},
++ {"bmr462", zl2008},
++ {"bmr463", zl2008},
++ {"bmr464", zl2008},
++ {"zl2004", zl2004},
++ {"zl2005", zl2005},
++ {"zl2006", zl2006},
++ {"zl2008", zl2008},
++ {"zl2105", zl2105},
++ {"zl2106", zl2106},
++ {"zl6100", zl6100},
++ {"zl6105", zl6105},
++ {"zl9101", zl9101},
++ {"zl9117", zl9117},
++ { }
++};
++MODULE_DEVICE_TABLE(i2c, zl6100_id);
++
++static int zl6100_probe(struct i2c_client *client,
++ const struct i2c_device_id *id)
++{
++ int ret;
++ struct zl6100_data *data;
++ struct pmbus_driver_info *info;
++ u8 device_id[I2C_SMBUS_BLOCK_MAX + 1];
++ const struct i2c_device_id *mid;
++
++ if (!i2c_check_functionality(client->adapter,
++ I2C_FUNC_SMBUS_READ_WORD_DATA
++ | I2C_FUNC_SMBUS_READ_BLOCK_DATA))
++ return -ENODEV;
++
++ ret = i2c_smbus_read_block_data(client, ZL6100_DEVICE_ID,
++ device_id);
++ if (ret < 0) {
++ dev_err(&client->dev, "Failed to read device ID\n");
++ return ret;
++ }
++ device_id[ret] = '\0';
++ dev_info(&client->dev, "Device ID %s\n", device_id);
++
++ mid = NULL;
++ for (mid = zl6100_id; mid->name[0]; mid++) {
++ if (!strncasecmp(mid->name, device_id, strlen(mid->name)))
++ break;
++ }
++ if (!mid->name[0]) {
++ dev_err(&client->dev, "Unsupported device\n");
++ return -ENODEV;
++ }
++ if (id->driver_data != mid->driver_data)
++ dev_notice(&client->dev,
++ "Device mismatch: Configured %s, detected %s\n",
++ id->name, mid->name);
++
++ data = devm_kzalloc(&client->dev, sizeof(struct zl6100_data),
++ GFP_KERNEL);
++ if (!data)
++ return -ENOMEM;
++
++ data->id = mid->driver_data;
++
++ /*
++ * According to information from the chip vendor, all currently
++ * supported chips are known to require a wait time between I2C
++ * accesses.
++ */
++ data->delay = delay;
++
++ /*
++ * Since there was a direct I2C device access above, wait before
++ * accessing the chip again.
++ */
++ data->access = ktime_get();
++ zl6100_wait(data);
++
++ info = &data->info;
++
++ info->pages = 1;
++ info->func[0] = PMBUS_HAVE_VIN | PMBUS_HAVE_STATUS_INPUT
++ | PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT
++ | PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT
++ | PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP;
++
++ /*
++ * ZL2004, ZL9101M, and ZL9117M support monitoring an extra voltage
++ * (VMON for ZL2004, VDRV for ZL9101M and ZL9117M). Report it as vmon.
++ */
++ if (data->id == zl2004 || data->id == zl9101 || data->id == zl9117)
++ info->func[0] |= PMBUS_HAVE_VMON | PMBUS_HAVE_STATUS_VMON;
++
++ ret = i2c_smbus_read_word_data(client, ZL6100_MFR_CONFIG);
++ if (ret < 0)
++ return ret;
++
++ if (ret & ZL6100_MFR_XTEMP_ENABLE)
++ info->func[0] |= PMBUS_HAVE_TEMP2;
++
++ data->access = ktime_get();
++ zl6100_wait(data);
++
++ info->read_word_data = zl6100_read_word_data;
++ info->read_byte_data = zl6100_read_byte_data;
++ info->write_word_data = zl6100_write_word_data;
++ info->write_byte = zl6100_write_byte;
++
++ return pmbus_do_probe(client, mid, info);
++}
++
++static struct i2c_driver zl6100_driver = {
++ .driver = {
++ .name = "zl6100",
++ },
++ .probe = zl6100_probe,
++ .remove = pmbus_do_remove,
++ .id_table = zl6100_id,
++};
++
++module_i2c_driver(zl6100_driver);
++
++MODULE_AUTHOR("Guenter Roeck");
++MODULE_DESCRIPTION("PMBus driver for ZL6100 and compatibles");
++MODULE_LICENSE("GPL");
+diff --git a/drivers/i2c/busses/i2c-ast.c b/drivers/i2c/busses/i2c-ast.c
+index bccf5a3..7a083de 100644
+--- a/drivers/i2c/busses/i2c-ast.c
++++ b/drivers/i2c/busses/i2c-ast.c
+@@ -88,8 +88,10 @@ struct ast_i2c_dev {
+
+ struct i2c_msg slave_rx_msg[I2C_S_RX_BUF_NUM + 1];
+ struct i2c_msg slave_tx_msg;
++static spinlock_t slave_rx_lock = SPIN_LOCK_UNLOCKED;
+ #endif
+
++static spinlock_t g_master_lock = SPIN_LOCK_UNLOCKED;
+
+ static inline void
+ ast_i2c_write(struct ast_i2c_dev *i2c_dev, u32 val, u32 reg)
+@@ -243,8 +245,9 @@ static void ast_i2c_slave_buff_init(struct ast_i2c_dev *i2c_dev)
+ static void ast_i2c_slave_rdwr_xfer(struct ast_i2c_dev *i2c_dev)
+ {
+ int i;
+- spinlock_t lock;
+- spin_lock(&lock);
++ unsigned long flags;
++
++ spin_lock_irqsave(&slave_rx_lock, flags);
+
+ switch(i2c_dev->slave_event) {
+ case I2C_SLAVE_EVENT_START_WRITE:
+@@ -291,7 +294,7 @@ static void ast_i2c_slave_rdwr_xfer(struct ast_i2c_dev *i2c_dev)
+ i2c_dev->slave_msgs = &slave_tx_msg;
+ break;
+ }
+- spin_unlock(&lock);
++ spin_unlock_irqrestore(&slave_rx_lock, flags);
+
+ }
+
+@@ -299,11 +302,14 @@ static int ast_i2c_slave_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs)
+ {
+ struct ast_i2c_dev *i2c_dev = adap->algo_data;
+ int ret=0, i;
++ unsigned long flags;
+
+ switch(msgs->flags) {
+ case 0:
+ // printk("slave read \n");
+ //cur_msg = get_free_msg;
++ spin_lock_irqsave(&slave_rx_lock, flags);
++
+ for(i=0; i<I2C_S_RX_BUF_NUM; i++) {
+ if((slave_rx_msg[i].addr == 0) && (slave_rx_msg[i].flags == BUFF_FULL)) {
+ memcpy(msgs->buf, slave_rx_msg[i].buf, slave_rx_msg[i].len);
+@@ -313,6 +319,7 @@ static int ast_i2c_slave_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs)
+ break;
+ }
+ }
++ spin_unlock_irqrestore(&slave_rx_lock, flags);
+
+ if(i == I2C_S_RX_BUF_NUM) {
+ printk("No buffer ........ \n");
+@@ -378,13 +385,15 @@ ast_i2c_bus_error_recover(struct ast_i2c_dev *i2c_dev)
+ dev_dbg(i2c_dev->dev, "I2C's master is locking the bus, try to stop it.\n");
+ //
+ init_completion(&i2c_dev->cmd_complete);
++ i2c_dev->cmd_err = 0;
+
+ ast_i2c_write(i2c_dev, AST_I2CD_M_STOP_CMD, I2C_CMD_REG);
+
+ r = wait_for_completion_interruptible_timeout(&i2c_dev->cmd_complete,
+ i2c_dev->adap.timeout*HZ);
+
+- if(i2c_dev->cmd_err) {
++ if(i2c_dev->cmd_err &&
++ i2c_dev->cmd_err != AST_I2CD_INTR_STS_NORMAL_STOP) {
+ dev_dbg(i2c_dev->dev, "recovery error \n");
+ return -1;
+ }
+@@ -411,7 +420,8 @@ ast_i2c_bus_error_recover(struct ast_i2c_dev *i2c_dev)
+
+ r = wait_for_completion_interruptible_timeout(&i2c_dev->cmd_complete,
+ i2c_dev->adap.timeout*HZ);
+- if (i2c_dev->cmd_err != 0) {
++ if (i2c_dev->cmd_err != 0 &&
++ i2c_dev->cmd_err != AST_I2CD_INTR_STS_NORMAL_STOP) {
+ dev_dbg(i2c_dev->dev, "ERROR!! Failed to do recovery command(0x%08x)\n", i2c_dev->cmd_err);
+ return -1;
+ }
+@@ -621,7 +631,9 @@ static void ast_i2c_do_dma_xfer(struct ast_i2c_dev *i2c_dev)
+ }else {
+ //should send next msg
+ if(i2c_dev->master_xfer_cnt != i2c_dev->master_msgs->len)
+- printk("complete rx ... ERROR \n");
++ printk("complete rx ... bus=%d addr=0x%x (%d vs. %d) ERROR\n",
++ i2c_dev->bus_id, i2c_dev->master_msgs->addr,
++ i2c_dev->master_xfer_cnt, i2c_dev->master_msgs->len);
+
+ dev_dbg(i2c_dev->dev, "ast_i2c_do_byte_xfer complete \n");
+ i2c_dev->cmd_err = 0;
+@@ -812,7 +824,9 @@ static void ast_i2c_do_pool_xfer(struct ast_i2c_dev *i2c_dev)
+ } else {
+ //should send next msg
+ if(i2c_dev->master_xfer_cnt != i2c_dev->master_msgs->len)
+- printk("complete rx ... ERROR \n");
++ printk("complete rx ... bus=%d addr=0x%x (%d vs. %d) ERROR\n",
++ i2c_dev->bus_id, i2c_dev->master_msgs->addr,
++ i2c_dev->master_xfer_cnt, i2c_dev->master_msgs->len);
+
+ dev_dbg(i2c_dev->dev, "ast_i2c_do_byte_xfer complete \n");
+ i2c_dev->cmd_err = 0;
+@@ -909,7 +923,9 @@ static void ast_i2c_do_byte_xfer(struct ast_i2c_dev *i2c_dev)
+ } else {
+ //should send next msg
+ if(i2c_dev->master_xfer_cnt != i2c_dev->master_msgs->len)
+- printk("CNT ERROR \n");
++ printk("CNT ERROR bus=%d addr=0x%x (%d vs. %d)\n",
++ i2c_dev->bus_id, i2c_dev->master_msgs->addr,
++ i2c_dev->master_xfer_cnt, i2c_dev->master_msgs->len);
+
+ dev_dbg(i2c_dev->dev, "ast_i2c_do_byte_xfer complete \n");
+ i2c_dev->cmd_err = 0;
+@@ -1039,6 +1055,18 @@ static void ast_i2c_master_xfer_done(struct ast_i2c_dev *i2c_dev)
+ u32 xfer_len;
+ int i;
+ u8 *pool_buf;
++ unsigned long flags;
++
++ spin_lock_irqsave(&g_master_lock, flags);
++
++ /*
++ * This function shall be involked during interrupt handling.
++ * Since the interrupt could be fired at anytime, we will need to make sure
++ * we have the buffer (i2c_dev->master_msgs) to handle the results.
++ */
++ if (!i2c_dev->master_msgs) {
++ goto unlock_out;
++ }
+
+ dev_dbg(i2c_dev->dev, "ast_i2c_master_xfer_done mode[%d]\n",i2c_dev->master_xfer_mode);
+
+@@ -1118,7 +1146,9 @@ next_xfer:
+
+ if(xfer_len !=i2c_dev->master_xfer_len) {
+ //TODO..
+- printk(" ** xfer error \n");
++ printk(" ** xfer error bus=%d addr=0x%x (%d vs. %d)\n",
++ i2c_dev->bus_id, i2c_dev->master_msgs->addr,
++ xfer_len, i2c_dev->master_xfer_len);
+ //should goto stop....
+ i2c_dev->cmd_err = 1;
+ goto done_out;
+@@ -1142,6 +1172,9 @@ done_out:
+ dev_dbg(i2c_dev->dev,"msgs complete \n");
+ complete(&i2c_dev->cmd_complete);
+ }
++
++unlock_out:
++ spin_unlock_irqrestore(&g_master_lock, flags);
+ }
+
+ static void ast_i2c_slave_addr_match(struct ast_i2c_dev *i2c_dev)
+@@ -1214,6 +1247,18 @@ static irqreturn_t i2c_ast_handler(int this_irq, void *dev_id)
+ sts &= ~AST_I2CD_SMBUS_ALT_INTR_EN;
+ }
+
++ if(AST_I2CD_INTR_STS_ABNORMAL & sts) {
++ i2c_dev->cmd_err |= AST_I2CD_INTR_STS_ABNORMAL;
++ // Turn off interrupts for further abnormal
++ // conditions until we fix this one.
++ ast_i2c_write(i2c_dev,
++ ast_i2c_read(i2c_dev,I2C_INTR_CTRL_REG) &
++ ~AST_I2CD_ABNORMAL_INTR_EN,
++ I2C_INTR_CTRL_REG);
++ complete(&i2c_dev->cmd_complete);
++ sts &= ~AST_I2CD_INTR_STS_ABNORMAL;
++ }
++
+ switch(sts) {
+ case AST_I2CD_INTR_STS_TX_ACK:
+ if(i2c_dev->slave_operation == 1) {
+@@ -1251,12 +1296,12 @@ static irqreturn_t i2c_ast_handler(int this_irq, void *dev_id)
+ } else {
+ dev_dbg(i2c_dev->dev, "M clear isr: AST_I2CD_INTR_STS_TX_NAK = %x\n",sts);
+ ast_i2c_write(i2c_dev, AST_I2CD_INTR_STS_TX_NAK, I2C_INTR_STS_REG);
+- if(i2c_dev->master_msgs->flags == I2C_M_IGNORE_NAK) {
++ if (i2c_dev->master_msgs
++ && i2c_dev->master_msgs->flags & I2C_M_IGNORE_NAK) {
+ dev_dbg(i2c_dev->dev, "I2C_M_IGNORE_NAK next send\n");
+- i2c_dev->cmd_err = 0;
+ } else {
+ dev_dbg(i2c_dev->dev, "NAK error\n");
+- i2c_dev->cmd_err = AST_I2CD_INTR_STS_TX_NAK;
++ i2c_dev->cmd_err |= AST_I2CD_INTR_STS_TX_NAK;
+ }
+ complete(&i2c_dev->cmd_complete);
+ }
+@@ -1270,7 +1315,7 @@ static irqreturn_t i2c_ast_handler(int this_irq, void *dev_id)
+ dev_dbg(i2c_dev->dev, "M clear isr: AST_I2CD_INTR_STS_TX_NAK| AST_I2CD_INTR_STS_NORMAL_STOP = %x\n",sts);
+ ast_i2c_write(i2c_dev, AST_I2CD_INTR_STS_TX_NAK | AST_I2CD_INTR_STS_NORMAL_STOP, I2C_INTR_STS_REG);
+ dev_dbg(i2c_dev->dev, "M TX NAK | NORMAL STOP \n");
+- i2c_dev->cmd_err = AST_I2CD_INTR_STS_TX_NAK | AST_I2CD_INTR_STS_NORMAL_STOP;
++ i2c_dev->cmd_err |= AST_I2CD_INTR_STS_TX_NAK | AST_I2CD_INTR_STS_NORMAL_STOP;
+ complete(&i2c_dev->cmd_complete);
+ }
+ break;
+@@ -1316,39 +1361,34 @@ static irqreturn_t i2c_ast_handler(int this_irq, void *dev_id)
+ } else {
+ dev_dbg(i2c_dev->dev, "M clear isr: AST_I2CD_INTR_STS_NORMAL_STOP = %x\n",sts);
+ ast_i2c_write(i2c_dev, AST_I2CD_INTR_STS_NORMAL_STOP, I2C_INTR_STS_REG);
+- i2c_dev->cmd_err = 0;
++ i2c_dev->cmd_err |= AST_I2CD_INTR_STS_NORMAL_STOP;
+ complete(&i2c_dev->cmd_complete);
+ }
+ break;
+ case (AST_I2CD_INTR_STS_RX_DOWN | AST_I2CD_INTR_STS_NORMAL_STOP):
+- if((i2c_dev->xfer_last == 1) && (i2c_dev->slave_operation == 0)) {
++ /* Whether or not we're done, the hardware thinks we're done, so bail. */
++ if(i2c_dev->slave_operation == 0) {
+ dev_dbg(i2c_dev->dev, "M clear isr: AST_I2CD_INTR_STS_RX_DOWN | AST_I2CD_INTR_STS_NORMAL_STOP = %x\n",sts);
+ ast_i2c_write(i2c_dev, AST_I2CD_INTR_STS_RX_DOWN | AST_I2CD_INTR_STS_NORMAL_STOP, I2C_INTR_STS_REG);
+ //take care
+ ast_i2c_write(i2c_dev, ast_i2c_read(i2c_dev,I2C_INTR_CTRL_REG) |
+ AST_I2CD_RX_DOWN_INTR_EN, I2C_INTR_CTRL_REG);
+ ast_i2c_master_xfer_done(i2c_dev);
+- } else {
+- printk("TODO .. .. ..\n");
+ }
+ break;
+ case AST_I2CD_INTR_STS_ARBIT_LOSS:
+ dev_dbg(i2c_dev->dev, "M clear isr: AST_I2CD_INTR_STS_ARBIT_LOSS = %x\n",sts);
+ ast_i2c_write(i2c_dev, AST_I2CD_INTR_STS_ARBIT_LOSS, I2C_INTR_STS_REG);
+- i2c_dev->cmd_err = AST_I2CD_INTR_STS_ARBIT_LOSS;
+- complete(&i2c_dev->cmd_complete);
+- break;
+- case AST_I2CD_INTR_STS_ABNORMAL:
+- i2c_dev->cmd_err = AST_I2CD_INTR_STS_ABNORMAL;
++ i2c_dev->cmd_err |= AST_I2CD_INTR_STS_ARBIT_LOSS;
+ complete(&i2c_dev->cmd_complete);
+ break;
+ case AST_I2CD_INTR_STS_SCL_TO:
+- i2c_dev->cmd_err = AST_I2CD_INTR_STS_SCL_TO;
++ i2c_dev->cmd_err |= AST_I2CD_INTR_STS_SCL_TO;
+ complete(&i2c_dev->cmd_complete);
+
+ break;
+ case AST_I2CD_INTR_STS_GCALL_ADDR:
+- i2c_dev->cmd_err = AST_I2CD_INTR_STS_GCALL_ADDR;
++ i2c_dev->cmd_err |= AST_I2CD_INTR_STS_GCALL_ADDR;
+ complete(&i2c_dev->cmd_complete);
+
+ break;
+@@ -1365,7 +1405,6 @@ static irqreturn_t i2c_ast_handler(int this_irq, void *dev_id)
+ case AST_I2CD_INTR_STS_BUS_RECOVER:
+ dev_dbg(i2c_dev->dev, "M clear isr: AST_I2CD_INTR_STS_BUS_RECOVER= %x\n",sts);
+ ast_i2c_write(i2c_dev, AST_I2CD_INTR_STS_BUS_RECOVER, I2C_INTR_STS_REG);
+- i2c_dev->cmd_err = 0;
+ complete(&i2c_dev->cmd_complete);
+ break;
+ default:
+@@ -1382,6 +1421,9 @@ static int ast_i2c_do_msgs_xfer(struct ast_i2c_dev *i2c_dev, struct i2c_msg *msg
+ {
+ int i;
+ int ret = 1;
++ unsigned long flags;
++
++ spin_lock_irqsave(&g_master_lock, flags);
+
+ //request
+ if(i2c_dev->ast_i2c_data->master_dma == BYTE_MODE)
+@@ -1407,6 +1449,7 @@ static int ast_i2c_do_msgs_xfer(struct ast_i2c_dev *i2c_dev, struct i2c_msg *msg
+
+ i2c_dev->blk_r_flag = 0;
+ init_completion(&i2c_dev->cmd_complete);
++ i2c_dev->cmd_err = 0;
+
+ if(i2c_dev->master_msgs->flags & I2C_M_NOSTART)
+ i2c_dev->master_xfer_cnt = 0;
+@@ -1415,31 +1458,43 @@ static int ast_i2c_do_msgs_xfer(struct ast_i2c_dev *i2c_dev, struct i2c_msg *msg
+
+ i2c_dev->do_master_xfer(i2c_dev);
+
++ spin_unlock_irqrestore(&g_master_lock, flags);
++
+ ret = wait_for_completion_interruptible_timeout(&i2c_dev->cmd_complete,
+ i2c_dev->adap.timeout*HZ);
+
++ spin_lock_irqsave(&g_master_lock, flags);
++ i2c_dev->master_msgs = NULL;
++
+ if (ret == 0) {
+ dev_dbg(i2c_dev->dev, "controller timed out\n");
+ i2c_dev->state = (ast_i2c_read(i2c_dev,I2C_CMD_REG) >> 19) & 0xf;
+ // printk("sts [%x], isr sts [%x] \n",i2c_dev->state, ast_i2c_read(i2c_dev,I2C_INTR_STS_REG));
+ ret = -ETIMEDOUT;
++ spin_unlock_irqrestore(&g_master_lock, flags);
+ goto stop;
+ }
+
+- if(i2c_dev->cmd_err != 0) {
++ if(i2c_dev->cmd_err != 0 &&
++ i2c_dev->cmd_err != AST_I2CD_INTR_STS_NORMAL_STOP) {
+ ret = -EAGAIN;
++ spin_unlock_irqrestore(&g_master_lock, flags);
+ goto stop;
+ }
+-
+ }
+
+- if(i2c_dev->cmd_err == 0) {
++ spin_unlock_irqrestore(&g_master_lock, flags);
++
++ if(i2c_dev->cmd_err == 0 ||
++ i2c_dev->cmd_err == AST_I2CD_INTR_STS_NORMAL_STOP) {
+ ret = num;
+ goto out;
+
+ }
+ stop:
+ init_completion(&i2c_dev->cmd_complete);
++ if(i2c_dev->cmd_err & AST_I2CD_INTR_STS_NORMAL_STOP)
++ goto out;
+ ast_i2c_write(i2c_dev, AST_I2CD_M_STOP_CMD, I2C_CMD_REG);
+ wait_for_completion_interruptible_timeout(&i2c_dev->cmd_complete,
+ i2c_dev->adap.timeout*HZ);
+@@ -1610,6 +1665,8 @@ static int ast_i2c_probe(struct platform_device *pdev)
+ i2c_dev->blk_r_flag = 0;
+ i2c_dev->adap.algo = &i2c_ast_algorithm;
+
++ ast_i2c_dev_init(i2c_dev);
++
+ ret = request_irq(i2c_dev->irq, i2c_ast_handler, IRQF_SHARED,
+ i2c_dev->adap.name, i2c_dev);
+ if (ret) {
+@@ -1617,8 +1674,6 @@ static int ast_i2c_probe(struct platform_device *pdev)
+ goto ereqirq;
+ }
+
+- ast_i2c_dev_init(i2c_dev);
+-
+ #ifdef CONFIG_AST_I2C_SLAVE_RDWR
+ ast_i2c_slave_buff_init(i2c_dev);
+ #endif
+diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c
+index 5ced92c..c8e3cf6 100644
+--- a/drivers/i2c/i2c-core.c
++++ b/drivers/i2c/i2c-core.c
+@@ -1842,8 +1842,8 @@ static s32 i2c_smbus_xfer_emulated(struct i2c_adapter * adapter, u16 addr,
+ need to use only one message; when reading, we need two. We initialize
+ most things with sane defaults, to keep the code below somewhat
+ simpler. */
+- unsigned char msgbuf0[I2C_SMBUS_BLOCK_MAX+3];
+- unsigned char msgbuf1[I2C_SMBUS_BLOCK_MAX+2];
++ unsigned char msgbuf0[I2C_SMBUS_BLOCK_LARGE_MAX+3];
++ unsigned char msgbuf1[I2C_SMBUS_BLOCK_LARGE_MAX+2];
+ int num = read_write == I2C_SMBUS_READ?2:1;
+ struct i2c_msg msg[2] = { { addr, flags, 1, msgbuf0 },
+ { addr, flags | I2C_M_RD, 0, msgbuf1 }
+@@ -1910,6 +1910,23 @@ static s32 i2c_smbus_xfer_emulated(struct i2c_adapter * adapter, u16 addr,
+ msgbuf0[i] = data->block[i-1];
+ }
+ break;
++ case I2C_SMBUS_BLOCK_LARGE_DATA:
++ if (read_write == I2C_SMBUS_READ) {
++ msg[1].flags |= I2C_M_RECV_LEN;
++ msg[1].len = 1; /* block length will be added by
++ the underlying bus driver */
++ } else {
++ msg[0].len = data->block[0] + 2;
++ if (msg[0].len > I2C_SMBUS_BLOCK_LARGE_MAX + 2) {
++ dev_err(&adapter->dev,
++ "Invalid large block write size %d\n",
++ data->block[0]);
++ return -EINVAL;
++ }
++ for (i = 1; i < msg[0].len; i++)
++ msgbuf0[i] = data->block[i-1];
++ }
++ break;
+ case I2C_SMBUS_BLOCK_PROC_CALL:
+ num = 2; /* Another special case */
+ read_write = I2C_SMBUS_READ;
+@@ -1989,6 +2006,7 @@ static s32 i2c_smbus_xfer_emulated(struct i2c_adapter * adapter, u16 addr,
+ data->block[i+1] = msgbuf1[i];
+ break;
+ case I2C_SMBUS_BLOCK_DATA:
++ case I2C_SMBUS_BLOCK_LARGE_DATA:
+ case I2C_SMBUS_BLOCK_PROC_CALL:
+ for (i = 0; i < msgbuf1[0] + 1; i++)
+ data->block[i] = msgbuf1[i];
+diff --git a/drivers/i2c/i2c-dev.c b/drivers/i2c/i2c-dev.c
+index 7d1f7e9..07f393d 100644
+--- a/drivers/i2c/i2c-dev.c
++++ b/drivers/i2c/i2c-dev.c
+@@ -245,8 +245,7 @@ static noinline int i2cdev_ioctl_rdrw(struct i2c_client *client,
+ for (i = 0; i < rdwr_arg.nmsgs; i++) {
+ /* Limit the size of the message to a sane amount;
+ * and don't let length change either. */
+- if ((rdwr_pa[i].len > 8192) ||
+- (rdwr_pa[i].flags & I2C_M_RECV_LEN)) {
++ if (rdwr_pa[i].len > 8192) {
+ res = -EINVAL;
+ break;
+ }
+@@ -262,6 +261,31 @@ static noinline int i2cdev_ioctl_rdrw(struct i2c_client *client,
+ res = -EFAULT;
+ break;
+ }
++
++ /* From Linux 3.5: */
++ /*
++ * If the message length is received from the slave (similar
++ * to SMBus block read), we must ensure that the buffer will
++ * be large enough to cope with a message length of
++ * I2C_SMBUS_BLOCK_MAX as this is the maximum underlying bus
++ * drivers allow. The first byte in the buffer must be
++ * pre-filled with the number of extra bytes, which must be
++ * at least one to hold the message length, but can be
++ * greater (for example to account for a checksum byte at
++ * the end of the message.)
++ */
++ if (rdwr_pa[i].flags & I2C_M_RECV_LEN) {
++ if (!(rdwr_pa[i].flags & I2C_M_RD) ||
++ rdwr_pa[i].buf[0] < 1 ||
++ rdwr_pa[i].len < rdwr_pa[i].buf[0] +
++ I2C_SMBUS_BLOCK_MAX) {
++ res = -EINVAL;
++ break;
++ }
++
++ rdwr_pa[i].len = rdwr_pa[i].buf[0];
++ }
++
+ }
+ if (res < 0) {
+ int j;
+@@ -290,7 +314,7 @@ static noinline int i2cdev_ioctl_smbus(struct i2c_client *client,
+ unsigned long arg)
+ {
+ struct i2c_smbus_ioctl_data data_arg;
+- union i2c_smbus_data temp;
++ union i2c_smbus_large_data temp;
+ int datasize, res;
+
+ if (copy_from_user(&data_arg,
+@@ -303,6 +327,7 @@ static noinline int i2cdev_ioctl_smbus(struct i2c_client *client,
+ (data_arg.size != I2C_SMBUS_WORD_DATA) &&
+ (data_arg.size != I2C_SMBUS_PROC_CALL) &&
+ (data_arg.size != I2C_SMBUS_BLOCK_DATA) &&
++ (data_arg.size != I2C_SMBUS_BLOCK_LARGE_DATA) &&
+ (data_arg.size != I2C_SMBUS_I2C_BLOCK_BROKEN) &&
+ (data_arg.size != I2C_SMBUS_I2C_BLOCK_DATA) &&
+ (data_arg.size != I2C_SMBUS_BLOCK_PROC_CALL)) {
+@@ -343,6 +368,8 @@ static noinline int i2cdev_ioctl_smbus(struct i2c_client *client,
+ else if ((data_arg.size == I2C_SMBUS_WORD_DATA) ||
+ (data_arg.size == I2C_SMBUS_PROC_CALL))
+ datasize = sizeof(data_arg.data->word);
++ else if (data_arg.size == I2C_SMBUS_BLOCK_LARGE_DATA)
++ datasize = sizeof(union i2c_smbus_large_data);
+ else /* size == smbus block, i2c block, or block proc. call */
+ datasize = sizeof(data_arg.data->block);
+
+diff --git a/drivers/mtd/devices/m25p80.c b/drivers/mtd/devices/m25p80.c
+index 45cb05a..10450cd 100644
+--- a/drivers/mtd/devices/m25p80.c
++++ b/drivers/mtd/devices/m25p80.c
+@@ -503,15 +503,6 @@ static struct flash_info __devinitdata m25p_data [] = {
+ { "at26df161a", 0x1f4601, 0, 64 * 1024, 32, SECT_4K, },
+ { "at26df321", 0x1f4701, 0, 64 * 1024, 64, SECT_4K, },
+
+- /* Macronix */
+- { "mx25l4005a", 0xc22013, 0, 64 * 1024, 8, SECT_4K },
+- { "mx25l3205d", 0xc22016, 0, 64 * 1024, 64, 0 },
+- { "mx25l6405d", 0xc22017, 0, 64 * 1024, 128, 0 },
+- { "mx25l12805d", 0xc22018, 0, 64 * 1024, 256, 0 },
+-
+- { "mx25l12855e", 0xc22618, 0, 64 * 1024, 256, 0 },
+- { "mx25l25635e", 0xc22019, 0, 64 * 1024, 512, 0 },
+-
+ /* Spansion -- single (large) sector size only, at least
+ * for the chips listed here (without boot sectors).
+ */
+@@ -637,7 +628,12 @@ static int __devinit m25p_probe(struct spi_device *spi)
+ dev_warn(&spi->dev, "found %s, expected %s\n",
+ chip ? chip->name : "UNKNOWN",
+ info->name);
+- info = NULL;
++ if (chip) {
++ dev_warn(&spi->dev, "Use %s instead\n", chip->name);
++ info = chip;
++ } else {
++ dev_warn(&spi->dev, "Force to use %s\n", info->name);
++ }
+ }
+ }
+ } else
+diff --git a/drivers/net/ftgmac100_26.c b/drivers/net/ftgmac100_26.c
+index 8575293..fdc77fc 100644
+--- a/drivers/net/ftgmac100_26.c
++++ b/drivers/net/ftgmac100_26.c
+@@ -120,6 +120,8 @@
+ #err "Not define include for GMAC"
+ #endif
+
++#define PHY_DEFAULT_ADDR 0x1F
++
+ /*------------------------------------------------------------------------
+ .
+ . Configuration options, for the experienced user to change.
+@@ -269,9 +271,11 @@ no_phy_access:
+ if (out->miiPhyId == 0xFFFF) { //Realtek PHY at address 1
+ out->phyAddr = 1;
+ }
++#if 0
+ if (out->miiPhyId == 0x0362) {
+ out->phyAddr = 1;
+ }
++#endif
+ out->miiPhyId = ftgmac100_read_phy_register(dev->base_addr, out->phyAddr, 0x02);
+ out->miiPhyId = (out->miiPhyId & 0xffff) << 16;
+ out->miiPhyId |= ftgmac100_read_phy_register(dev->base_addr, out->phyAddr, 0x03) & 0xffff;
+@@ -280,7 +284,7 @@ no_phy_access:
+ case 0x0040: // Broadcom
+ case 0x0141: // Marvell
+ case 0x001c: // Realtek
+- case 0x0362: // BCM54612
++ case 0x0362: // BCM54612, BCM54616
+ break;
+
+ default:
+@@ -334,7 +338,8 @@ static void ftgmac100_reset( struct net_device* dev )
+ speed = (tmp & PHY_SPEED_mask)>>14;
+ netif_carrier_on(dev);
+ }
+- else if (priv->ids.miiPhyId == PHYID_BCM54612E) {
++ else if (priv->ids.miiPhyId == PHYID_BCM54612E
++ || priv->ids.miiPhyId == PHYID_BCM54616S) {
+ // Get link status
+ // First Switch shadow register selector
+ ftgmac100_write_phy_register(dev->base_addr, priv->ids.phyAddr, 0x1C, 0x2000);
+@@ -558,7 +563,8 @@ Re_Get_Link_Status:
+ ,dev->base_addr + IER_REG
+ );
+ }
+- else if (priv->ids.miiPhyId == PHYID_BCM54612E) {
++ else if (priv->ids.miiPhyId == PHYID_BCM54612E
++ || priv->ids.miiPhyId == PHYID_BCM54616S) {
+ outl(
+ // no link PHY link status pin PHYSTS_CHG_bit |
+ AHB_ERR_bit |
+@@ -612,7 +618,8 @@ static void aspeed_mac_timer(unsigned long data)
+ duplex = (tmp & PHY_DUPLEX_mask)>>13;
+ speed = (tmp & PHY_SPEED_mask)>>14;
+ }
+- else if (priv->ids.miiPhyId == PHYID_BCM54612E) {
++ else if (priv->ids.miiPhyId == PHYID_BCM54612E
++ || priv->ids.miiPhyId == PHYID_BCM54616S) {
+ // Get link status
+ // First Switch shadow register selector
+ ftgmac100_write_phy_register(dev->base_addr, priv->ids.phyAddr, 0x1C, 0x2000);
+@@ -913,6 +920,7 @@ static void ftgmac100_phy_configure(struct net_device* dev)
+ case PHYID_VENDOR_BROADCOM:
+ switch (priv->ids.miiPhyId) {
+ case PHYID_BCM54612E:
++ case PHYID_BCM54616S:
+ ftgmac100_write_phy_register(ioaddr, priv->ids.phyAddr, 0x1C, 0x8C00); // Disable GTXCLK Clock Delay Enable
+ ftgmac100_write_phy_register(ioaddr, priv->ids.phyAddr, 0x18, 0xF0E7); // Disable RGMII RXD to RXC Skew
+ break;
+@@ -1303,7 +1311,8 @@ static irqreturn_t ftgmac100_interrupt(int irq, void * dev_id, struct pt_regs *
+ // Bits [3:1] are {duplex, speed, link} change interrupts.
+ tmp &= 0x000e;
+ }
+- else if (priv->ids.miiPhyId == PHYID_BCM54612E) {
++ else if (priv->ids.miiPhyId == PHYID_BCM54612E
++ || priv->ids.miiPhyId == PHYID_BCM54616S) {
+ tmp = ftgmac100_read_phy_register(ioaddr, priv->ids.phyAddr, 0x1A);
+ PRINTK("%s: PHY interrupt status, read_phy_reg(0x1A) = 0x%04x\n",
+ dev->name, tmp);
+@@ -1644,7 +1653,8 @@ static int ftgmac100_open(struct net_device *netdev)
+
+ if (((priv->ids.miiPhyId & PHYID_VENDOR_MASK) == PHYID_VENDOR_BROADCOM) ||
+ ((priv->ids.miiPhyId & PHYID_VENDOR_MODEL_MASK) == PHYID_RTL8201EL) ||
+- (priv->ids.miiPhyId == PHYID_BCM54612E)) {
++ (priv->ids.miiPhyId == PHYID_BCM54612E) ||
++ (priv->ids.miiPhyId == PHYID_BCM54616S)) {
+
+ init_timer(&priv->timer);
+ priv->timer.data = (unsigned long)netdev;
+diff --git a/drivers/net/ftgmac100_26.h b/drivers/net/ftgmac100_26.h
+index f145b05..0d47024 100644
+--- a/drivers/net/ftgmac100_26.h
++++ b/drivers/net/ftgmac100_26.h
+@@ -62,7 +62,7 @@
+
+
+ // --------------------------------------------------------------------
+-// ISR_REG ¤Î IMR_REG
++// ISR_REG / IMR_REG
+ // --------------------------------------------------------------------
+ #define HPTXBUF_UNAVA_bit (1UL<<10)
+ #define PHYSTS_CHG_bit (1UL<<9)
+@@ -473,6 +473,7 @@ typedef struct
+ #define PHYID_RTL8211 0x001cc910
+ #define PHYID_RTL8211E 0x001cc915
+ #define PHYID_BCM54612E 0x03625E6A
++#define PHYID_BCM54616S 0x03625D12
+
+
+ /* store this information for the driver.. */
+diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig
+index dd4cd5a..6c7fe6b 100644
+--- a/drivers/usb/gadget/Kconfig
++++ b/drivers/usb/gadget/Kconfig
+@@ -419,6 +419,18 @@ config USB_GOKU
+ default USB_GADGET
+ select USB_GADGET_SELECTED
+
++config USB_GADGET_ASPEED_AST
++ boolean "ASPEED AST Virtual Hub"
++ select USB_GADGET_DUALSPEED
++ depends on ARCH_ASPEED
++ help
++ USB device controller for ASPEED AST
++
++config USB_ASPEED_AST
++ tristate
++ depends on USB_GADGET_ASPEED_AST
++ default USB_GADGET
++ select USB_GADGET_SELECTED
+
+ #
+ # LAST -- dummy/emulated controller
+diff --git a/drivers/usb/gadget/Makefile b/drivers/usb/gadget/Makefile
+index bd4041b..a061332 100644
+--- a/drivers/usb/gadget/Makefile
++++ b/drivers/usb/gadget/Makefile
+@@ -19,6 +19,7 @@ obj-$(CONFIG_USB_ATMEL_USBA) += atmel_usba_udc.o
+ obj-$(CONFIG_USB_FSL_USB2) += fsl_usb2_udc.o
+ obj-$(CONFIG_USB_M66592) += m66592-udc.o
+ obj-$(CONFIG_USB_FSL_QE) += fsl_qe_udc.o
++obj-$(CONFIG_USB_ASPEED_AST) += aspeed_udc.o
+
+ #
+ # USB gadget drivers
+diff --git a/drivers/usb/gadget/aspeed_udc.c b/drivers/usb/gadget/aspeed_udc.c
+new file mode 100644
+index 0000000..a65e52a
+--- /dev/null
++++ b/drivers/usb/gadget/aspeed_udc.c
+@@ -0,0 +1,1043 @@
++/*
++ * aspeed_udc - Driver for Aspeed virtual hub (usb gadget)
++ *
++ * Copyright 2014-present Facebook. All Rights Reserved.
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
++ */
++
++//#define DEBUG
++//#define VERBOSE_DEBUG
++
++#include <linux/kernel.h>
++#include <linux/module.h>
++#include <linux/platform_device.h>
++#include <linux/delay.h>
++#include <linux/ioport.h>
++#include <linux/slab.h>
++#include <linux/errno.h>
++#include <linux/init.h>
++#include <linux/list.h>
++#include <linux/interrupt.h>
++#include <linux/proc_fs.h>
++#include <linux/clk.h>
++#include <linux/usb/ch9.h>
++#include <linux/usb/gadget.h>
++#include <linux/dmapool.h>
++#include <linux/dma-mapping.h>
++
++#include <asm/byteorder.h>
++#include <mach/hardware.h>
++#include <asm/io.h>
++#include <asm/irq.h>
++#include <asm/system.h>
++#include <asm/cacheflush.h>
++
++#include "aspeed_udc.h"
++
++#define NUM_ENDPOINTS 14
++#define AST_UDC_EP0_MAXPACKET 64
++
++struct ast_ep *eps;
++static const struct usb_ep_ops ast_ep_ops;
++static int ast_ep_queue(struct usb_ep* _ep, struct usb_request *_rq, gfp_t gfp_flags);
++static void ep_dequeue_all(struct ast_ep* ep, int status);
++static void ep_txrx_check_done(struct ast_ep* ep);
++static void enable_upstream_port(void);
++static void disable_upstream_port(void);
++static int ast_udc_pullup(struct usb_gadget* gadget, int on);
++
++static inline const char* ast_udc_dir2str(u8 dir) {
++ return (dir & USB_DIR_IN) ? "IN" : "OUT";
++}
++
++static int ast_udc_get_frame(struct usb_gadget* gadget) {
++ return -EOPNOTSUPP;
++}
++
++static struct usb_gadget_ops ast_gadget_ops = {
++ .get_frame = ast_udc_get_frame,
++ .pullup = ast_udc_pullup,
++};
++
++static void norelease(struct device *dev) {
++}
++
++static struct aspeed_udc udc = {
++ .gadget = {
++ .ops = &ast_gadget_ops,
++ .ep_list = LIST_HEAD_INIT(udc.gadget.ep_list),
++ .is_dualspeed = 1,
++ .name = "aspeed_udc",
++ .dev = {
++ .bus_id = "gadget",
++ .release = norelease,
++ },
++ },
++ .pullup_on = 1,
++ .ep0_stage = EP0_STAGE_SETUP,
++ .ep0_dir = USB_DIR_IN,
++};
++
++static inline struct ast_usb_request *to_ast_req(struct usb_request* rq)
++{
++ return container_of(rq, struct ast_usb_request, req);
++}
++
++static inline struct ast_ep *to_ast_ep(struct usb_ep* ep)
++{
++ return container_of(ep, struct ast_ep, ep);
++}
++
++static void* ast_alloc_dma_memory(int sz, enum dma_data_direction dir,
++ dma_addr_t *phys)
++{
++ void* mem;
++ mem = kmalloc(sz, GFP_KERNEL | GFP_DMA);
++ if (!mem) {
++ return NULL;
++ }
++
++ *phys = dma_map_single(udc.gadget.dev.parent, mem, sz, dir);
++ return mem;
++}
++
++static void ast_free_dma_memory(int sz, enum dma_data_direction dir,
++ void *mem, dma_addr_t phys)
++{
++ if (phys) {
++ dma_unmap_single(udc.gadget.dev.parent, phys, sz, dir);
++ }
++ if (mem) {
++ kfree(mem);
++ }
++}
++
++static int ast_udc_pullup(struct usb_gadget* gadget, int on) {
++ if(on) {
++ enable_upstream_port();
++ } else {
++ disable_upstream_port();
++ }
++ udc.pullup_on = on;
++ return 0;
++}
++
++static struct ast_ep ep0_ep = {
++ .ep_regs = NULL,
++ .ep = {
++ .name = "ep0",
++ .ops = &ast_ep_ops,
++ .maxpacket = AST_UDC_EP0_MAXPACKET,
++ },
++ .queue = LIST_HEAD_INIT(ep0_ep.queue),
++ .lock = SPIN_LOCK_UNLOCKED,
++ .dma_busy = 0,
++};
++
++static void clear_isr(u32 flag) {
++ ast_hwritel(&udc, ISR, flag);
++}
++
++static void ep0_stall_ready(void) {
++ ast_hwritel(&udc, EP0_STATUS, AST_EP0_STALL);
++}
++
++static void ep0_out_ready(void) {
++ ast_hwritel(&udc, EP0_STATUS, AST_EP0_OUT_READY);
++}
++
++static void ep0_in_ready(size_t size) {
++ ast_hwritel(&udc, EP0_STATUS, (size << 8));
++ ast_hwritel(&udc, EP0_STATUS, (size << 8) | AST_EP0_IN_READY);
++}
++
++static void enable_upstream_port(void) {
++ ast_hwritel(&udc, STATUS, ast_hreadl(&udc, STATUS) | 0x5);
++}
++
++static void disable_upstream_port(void) {
++ ast_hwritel(&udc, STATUS, ast_hreadl(&udc, STATUS) &~ 0x5);
++}
++
++struct ast_usb_request empty_rq = {
++ .req = {
++ .buf = "",
++ .length = 0,
++ },
++ .queue = LIST_HEAD_INIT(empty_rq.queue),
++ .in_transit = 0,
++};
++
++struct ast_ep* ep_by_addr(int addr) {
++ unsigned long flags;
++ int i;
++ struct ast_ep* ep = NULL;
++ for(i = 0; i < NUM_ENDPOINTS && ep == NULL; i++) {
++ struct ast_ep* test = &eps[i];
++ spin_lock_irqsave(&test->lock, flags);
++ if(test->active && test->addr == addr) {
++ ep = test;
++ }
++ spin_unlock_irqrestore(&test->lock, flags);
++ }
++ return ep;
++}
++
++static inline void ep0_init_stage(void)
++{
++ /* expect SETUP after */
++ udc.ep0_stage = EP0_STAGE_SETUP;
++ udc.ep0_dir = USB_DIR_IN;
++}
++
++static void ep0_stall(void) {
++ pr_debug("Prepare for EP0 stall, Reset EP0 stage to SETUP\n");
++ /* reply stall on next pkt */
++ ep0_stall_ready();
++ ep0_init_stage();
++}
++
++static void ep0_next_stage(int has_data_phase, u8 data_dir) {
++#ifdef DEBUG
++ int prev_stage = udc.ep0_stage;
++ int prev_dir = udc.ep0_dir;
++#endif
++
++ switch (udc.ep0_stage) {
++ case EP0_STAGE_SETUP:
++ if (has_data_phase) {
++ udc.ep0_stage = EP0_STAGE_DATA;
++ udc.ep0_dir = (data_dir == USB_DIR_IN) ? USB_DIR_IN : USB_DIR_OUT;
++ } else {
++ udc.ep0_stage = EP0_STAGE_STATUS;
++ udc.ep0_dir = USB_DIR_IN;
++ }
++ break;
++ case EP0_STAGE_DATA:
++ udc.ep0_stage = EP0_STAGE_STATUS;
++ udc.ep0_dir = (udc.ep0_dir == USB_DIR_IN) ? USB_DIR_OUT : USB_DIR_IN;
++ break;
++ case EP0_STAGE_STATUS:
++ udc.ep0_stage = EP0_STAGE_SETUP;
++ udc.ep0_dir = USB_DIR_IN;
++ break;
++ default:
++ pr_err("Wrong EP0 stage %d\n", udc.ep0_stage);
++ break;
++ }
++
++#ifdef DEBUG
++ pr_debug("EP0 stage is changed from %d (%s) to %d (%s)\n",
++ prev_stage, ast_udc_dir2str(prev_dir),
++ udc.ep0_stage, ast_udc_dir2str(udc.ep0_dir));
++#endif
++}
++
++static void ep0_queue_run(void) {
++ struct ast_ep *ep = &ep0_ep;
++
++ /* if ep0 is still doing DMA or no request pending, nothing to do */
++ if (ep->dma_busy || list_empty(&ep->queue)) {
++ return;
++ }
++
++ if (udc.ep0_dir == USB_DIR_OUT) {
++ /* just tell HW we are ready for OUT */
++ ep0_out_ready();
++ } else {
++ size_t sendable;
++ struct ast_usb_request *req;
++
++ req = list_entry(ep->queue.next, struct ast_usb_request, queue);
++ sendable = req->req.length - req->req.actual;
++ if (sendable > AST_UDC_EP0_MAXPACKET) {
++ sendable = AST_UDC_EP0_MAXPACKET;
++ }
++ if (sendable) {
++ memcpy(udc.ep0_dma_virt, req->req.buf + req->req.actual, sendable);
++ }
++ dma_sync_single_for_device(udc.gadget.dev.parent, udc.ep0_dma_phys,
++ AST_UDC_EP0_MAXPACKET, DMA_TO_DEVICE);
++ ep0_in_ready(sendable);
++ req->lastpacket = sendable;
++ }
++ ep->dma_busy = 1;
++}
++
++static int ep0_enqueue(struct usb_ep* _ep, struct usb_request *_rq,
++ gfp_t gfp_flags) {
++ struct ast_usb_request *req = to_ast_req(_rq);
++ struct ast_ep *ep = to_ast_ep(_ep);
++ unsigned long flags;
++ int rc = 0;
++
++ _rq->status = -EINPROGRESS;
++ req->req.actual = 0;
++
++ pr_debug("EP0 enqueue %d bytes at stage %d, %s\n",
++ req->req.length, udc.ep0_stage, ast_udc_dir2str(udc.ep0_dir));
++
++ spin_lock_irqsave(&ep->lock, flags);
++
++ /* shall only happen when in data or status stage */
++ if (udc.ep0_stage != EP0_STAGE_DATA && udc.ep0_stage != EP0_STAGE_STATUS) {
++ pr_err("EP0 enqueue happens at wrong stage %d\n", udc.ep0_stage);
++ rc = -EINPROGRESS;
++ goto out;
++ }
++
++ /* ep0 shall only have one pending request a time */
++ if (!list_empty(&ep->queue)) {
++ pr_err("EP0 enqueue happens with an existing entry on queue\n");
++ } else {
++ list_add_tail(&req->queue, &ep->queue);
++ ep0_queue_run();
++ }
++
++ out:
++ if (rc < 0) {
++ ep0_stall();
++ }
++ spin_unlock_irqrestore(&ep->lock, flags);
++ return rc;
++}
++
++static void ep0_cancel_current(void)
++{
++ struct ast_ep *ep = &ep0_ep;
++ unsigned long flags;
++ ep_dequeue_all(ep, -ECONNRESET);
++ spin_lock_irqsave(&ep->lock, flags);
++ ep0_init_stage();
++ spin_unlock_irqrestore(&ep->lock, flags);
++}
++
++static int ep0_handle_setup(void) {
++ struct ast_ep *ep = &ep0_ep;
++ struct usb_ctrlrequest crq;
++ int rc = 0;
++ u16 val, idx, len;
++ unsigned long flags;
++
++ /* make sure we are expecting setup packet */
++ if (udc.ep0_stage != EP0_STAGE_SETUP) {
++ /*
++ * with g_cdc, we are seeing this message pretty often. could be an
++ * issue on g_cdc. make the log message as debug now
++ */
++ pr_debug("Received SETUP pkt on wrong stage %d. Cancelling "
++ "the current SETUP\n", udc.ep0_stage);
++ ep0_cancel_current();
++ }
++
++ memcpy_fromio(&crq, udc.regs + AST_HUB_ROOT_SETUP_BUFFER, sizeof(crq));
++ val = le16_to_cpu(crq.wValue);
++ idx = le16_to_cpu(crq.wIndex);
++ len = le16_to_cpu(crq.wLength);
++
++ pr_debug("request=%d, reqType=0x%x val=0x%x idx=%d len=%d %s\n",
++ crq.bRequest, crq.bRequestType, val, idx, len,
++ ast_udc_dir2str(crq.bRequestType));
++
++ spin_lock_irqsave(&ep->lock, flags);
++ ep0_next_stage(
++ len, (crq.bRequestType & USB_DIR_IN) ? USB_DIR_IN : USB_DIR_OUT);
++ spin_unlock_irqrestore(&ep->lock, flags);
++
++ switch (crq.bRequest) {
++ case USB_REQ_SET_ADDRESS:
++ udc.hub_address = val;
++ ast_hwritel(&udc, ROOT_CONFIG, udc.hub_address);
++ // reply with an empty pkt for STATUS
++ ep0_enqueue(&ep0_ep.ep, &empty_rq.req, GFP_KERNEL);
++ break;
++
++ case USB_REQ_CLEAR_FEATURE:
++ case USB_REQ_SET_FEATURE:
++ if ((crq.bRequestType & USB_TYPE_MASK) != USB_TYPE_STANDARD)
++ break;
++ if ((crq.bRequestType & USB_RECIP_MASK) == USB_RECIP_ENDPOINT) {
++ int epaddr = idx & USB_ENDPOINT_NUMBER_MASK;
++ struct ast_ep *ep2;
++ if(val != 0 || len != 0 || epaddr > 15) {
++ ep0_stall();
++ break;
++ }
++ ep2 = ep_by_addr(epaddr);
++ if (ep2) {
++ if(crq.bRequest == USB_REQ_SET_FEATURE) {
++ usb_ep_set_halt(&ep2->ep);
++ } else {
++ usb_ep_clear_halt(&ep2->ep);
++ }
++ }
++ }
++ // reply with an empty pkt for STATUS
++ ep0_enqueue(&ep0_ep.ep, &empty_rq.req, GFP_KERNEL);
++ break;
++
++ default:
++ rc = udc.driver->setup(&udc.gadget, &crq);
++ if (rc < 0) {
++ printk("req %02x, %02x; fail: %d\n", crq.bRequestType,
++ crq.bRequest, rc);
++ ep0_stall();
++ }
++ break;
++ }
++
++ return rc;
++}
++
++static void ep0_handle_ack(void) {
++ struct ast_usb_request *req;
++ struct ast_ep *ep = &ep0_ep;
++ unsigned long status;
++ unsigned long flags;
++ int done = 0;
++
++ spin_lock_irqsave(&ep->lock, flags);
++
++ if (!ep->dma_busy) {
++ goto out;
++ }
++
++ status = ast_hreadl(&udc, EP0_STATUS);
++
++ pr_debug("Check done with status 0x%lx: stage=%d %s\n", status,
++ udc.ep0_stage, ast_udc_dir2str((udc.ep0_dir)));
++
++ if (list_empty(&ep->queue)) {
++ /* we requested DMA but no request */
++ ep->dma_busy = 0;
++ pr_debug("Empty request queue with ep0 status: 0x%lx\n", status);
++ goto out;
++ }
++
++ if ((udc.ep0_dir == USB_DIR_IN && (!(status & AST_EP0_IN_READY)))
++ || (udc.ep0_dir == USB_DIR_OUT && (!(status & AST_EP0_OUT_READY)))) {
++ /* something is ready */
++ ep->dma_busy = 0;
++ req = container_of(ep->queue.next, struct ast_usb_request, queue);
++ req->in_transit = 0;
++ if (udc.ep0_dir == USB_DIR_OUT) {
++ req->lastpacket = (status >> 16) & 0x3F;
++ __cpuc_flush_kern_all();
++ if (req->lastpacket) {
++ memcpy(req->req.buf + req->req.actual, udc.ep0_dma_virt,
++ req->lastpacket);
++ }
++ }
++ req->req.actual += req->lastpacket;
++ pr_debug("EP0 req actual=%d length=%d lastpacket=%d\n",
++ req->req.actual, req->req.length, req->lastpacket);
++ if (req->req.actual >= req->req.length
++ || req->lastpacket < AST_UDC_EP0_MAXPACKET) {
++ list_del_init(&req->queue);
++ done = 1;
++ ep0_next_stage(0, 0);
++ } else {
++ /* the request is not done yet, restart the queue */
++ ep0_queue_run();
++ }
++ }
++
++ out:
++
++ spin_unlock_irqrestore(&ep->lock, flags);
++
++ if (done) {
++ req->req.status = 0;
++ if (req->req.complete) {
++ req->req.complete(&ep->ep, &req->req);
++ }
++ }
++}
++
++static void ep0_handle_status(void) {
++ struct ast_ep *ep = &ep0_ep;
++ unsigned long flags;
++
++ spin_lock_irqsave(&ep->lock, flags);
++
++ /*
++ * If we expect a STATUS from host (OUT), enqueue a reqeust to get it going.
++ * For STATUS to host (IN), the SETUP packet handler needs to enqueue a
++ * STATUS message, therefore, no need to handle it here.
++ */
++ if (udc.ep0_stage == EP0_STAGE_STATUS && udc.ep0_dir == USB_DIR_OUT) {
++ // request with an empty pkt for STATUS from host
++ ep0_enqueue(&ep0_ep.ep, &empty_rq.req, GFP_KERNEL);
++ }
++
++ spin_unlock_irqrestore(&ep->lock, flags);
++}
++
++static struct usb_request *ast_alloc_request(struct usb_ep *ep, gfp_t gfp_flags) {
++ struct ast_usb_request *req;
++ (void) ep;
++ req = kzalloc(sizeof(*req), gfp_flags);
++ INIT_LIST_HEAD(&req->queue);
++ if(!req)
++ return NULL;
++
++ return &req->req;
++}
++
++static void ast_free_request(struct usb_ep *ep, struct usb_request *_req) {
++ struct ast_usb_request *req = to_ast_req(_req);
++ (void) ep;
++ kfree(req);
++}
++
++static int ast_ep_enable(struct usb_ep* _ep, const struct usb_endpoint_descriptor *desc) {
++ struct ast_ep *ep = to_ast_ep(_ep);
++ size_t maxpacket = le16_to_cpu(desc->wMaxPacketSize);
++ int eptype = 0;
++ if(ep->active) {
++ pr_err("Enable an already enabled ep: %s\n", ep->ep.name);
++ return -EBUSY;
++ }
++ ep->ep.maxpacket = maxpacket;
++ pr_debug("Enabling endpoint %s (%p), maxpacket %d: ",
++ ep->ep.name, ep->ep_regs, ep->ep.maxpacket);
++ if (desc->bEndpointAddress & USB_DIR_IN) {
++ ep->to_host = 1;
++ switch (desc->bmAttributes) {
++ case USB_ENDPOINT_XFER_BULK:
++ pr_debug("bulk to host\n");
++ eptype = AST_EP_TYPE_BULK_IN;
++ break;
++ case USB_ENDPOINT_XFER_INT:
++ pr_debug("int to host\n");
++ eptype = AST_EP_TYPE_BULK_IN;
++ break;
++ case USB_ENDPOINT_XFER_ISOC:
++ pr_debug("isoc to host\n");
++ eptype = AST_EP_TYPE_ISO_IN;
++ break;
++ }
++ } else {
++ ep->to_host = 0;
++ switch (desc->bmAttributes) {
++ case USB_ENDPOINT_XFER_BULK:
++ pr_debug("bulk from host\n");
++ eptype = AST_EP_TYPE_BULK_OUT;
++ break;
++ case USB_ENDPOINT_XFER_INT:
++ pr_debug("int from host\n");
++ eptype = AST_EP_TYPE_INT_OUT;
++ break;
++ case USB_ENDPOINT_XFER_ISOC:
++ pr_debug("isoc from host\n");
++ eptype = AST_EP_TYPE_ISO_OUT;
++ break;
++ }
++ }
++
++ ep_hwritel(ep, DMA_CONTROL, AST_EP_DL_RESET);
++ ep_hwritel(ep, DMA_CONTROL, AST_EP_SINGLE_STAGE);
++
++ ep->txbuf = ast_alloc_dma_memory(
++ ep->ep.maxpacket, ep->to_host ? DMA_TO_DEVICE : DMA_FROM_DEVICE,
++ &ep->txbuf_phys);
++
++ if (maxpacket == 1024)
++ maxpacket = 0;
++ ep_hwritel(ep, CONFIG, (maxpacket << 16) | (ep->addr << 8) | (eptype << 4) | AST_EP_ENABLED);
++
++ ep_hwritel(ep, DESC_BASE, ep->txbuf_phys);
++ ep_hwritel(ep, DESC_STATUS, 0);
++
++ ast_hwritel(&udc, EP_ACK_INT_ENABLE, 0x7fff);
++ ep->active = 1;
++ return 0;
++}
++
++static void ep_dequeue_locked(struct ast_ep* ep, struct ast_usb_request *req) {
++ // Cancel in-progress transfer
++ req->req.status = -ECONNRESET;
++ if(req->in_transit) {
++ req->in_transit = 0;
++ ep->dma_busy = 0;
++ ep_hwritel(ep, DESC_STATUS, 0);
++ }
++ list_del_init(&req->queue);
++}
++
++static void ep_dequeue_all(struct ast_ep* ep, int status) {
++ struct ast_usb_request *req;
++ struct ast_usb_request *n;
++ unsigned long flags;
++ spin_lock_irqsave(&ep->lock, flags);
++ list_for_each_entry_safe(req, n, &ep->queue, queue) {
++ ep_dequeue_locked(ep, req);
++ req->req.status = status;
++ if(req->req.complete) {
++ spin_unlock_irqrestore(&ep->lock, flags);
++ req->req.complete(&ep->ep, &req->req);
++ spin_lock_irqsave(&ep->lock, flags);
++ }
++ }
++ spin_unlock_irqrestore(&ep->lock, flags);
++}
++
++static int ast_ep_dequeue(struct usb_ep* _ep, struct usb_request *_rq) {
++ struct ast_usb_request *req = to_ast_req(_rq);
++ struct ast_ep *ep = to_ast_ep(_ep);
++ unsigned long flags;
++ pr_debug("Dequeue a request (%d bytes) from %s\n",
++ req->req.length, ep->ep.name);
++ spin_lock_irqsave(&ep->lock, flags);
++ ep_dequeue_locked(ep, req);
++ if(req->req.complete) {
++ req->req.complete(&ep->ep, &req->req);
++ }
++ spin_unlock_irqrestore(&ep->lock, flags);
++ return 0;
++}
++
++static int ast_ep_disable(struct usb_ep* _ep) {
++ struct ast_ep *ep = to_ast_ep(_ep);
++ unsigned long flags;
++ pr_debug("Disable %s\n", ep->ep.name);
++ if (!ep->active)
++ return 0;
++ ep_dequeue_all(ep, -ESHUTDOWN);
++ spin_lock_irqsave(&ep->lock, flags);
++ ast_free_dma_memory(ep->ep.maxpacket,
++ ep->to_host ? DMA_TO_DEVICE : DMA_FROM_DEVICE,
++ ep->txbuf, ep->txbuf_phys);
++ ep->txbuf_phys = 0;
++ ep->txbuf = NULL;
++ ep->active = 0;
++ ep->ep.maxpacket = 1024;
++ ep_hwritel(ep, CONFIG, 0);
++ spin_unlock_irqrestore(&ep->lock, flags);
++ return 0;
++}
++
++static void disable_all_endpoints(void) {
++ int i;
++ for(i = 0; i < NUM_ENDPOINTS; i++) {
++ if(eps[i].active) {
++ ast_ep_disable(&eps[i].ep);
++ }
++ }
++}
++
++static void ep_txrx(struct ast_ep* ep, void* buf, size_t len) {
++ if(ep->to_host) {
++ memcpy(ep->txbuf, buf, len);
++ }
++ ep_hwritel(ep, DESC_STATUS, len << 16);
++ ep_hwritel(ep, DESC_STATUS, (len << 16) | 1);
++}
++
++static void ep_txrx_check_done(struct ast_ep* ep) {
++ struct ast_usb_request *req;
++ unsigned long flags;
++ u32 status;
++ spin_lock_irqsave(&ep->lock, flags);
++ status = ep_hreadl(ep, DESC_STATUS);
++ // if txrx complete;
++ if(!(status & 0xff) &&
++ !list_empty(&ep->queue)) {
++ req = list_entry(ep->queue.next, struct ast_usb_request, queue);
++ if(!req->in_transit) {
++ spin_unlock_irqrestore(&ep->lock, flags);
++ return;
++ }
++ //head rq completed
++ req->in_transit = 0;
++ ep->dma_busy = 0;
++ if(!ep->to_host) {
++ req->lastpacket = (status >> 16) & 0x3ff;
++ __cpuc_flush_kern_all();
++ memcpy(req->req.buf + req->req.actual, ep->txbuf, req->lastpacket);
++ //print_hex_dump(KERN_DEBUG, "epXrx: ", DUMP_PREFIX_OFFSET, 16, 1, ep->txbuf, req->lastpacket, 0);
++ }
++ req->req.actual += req->lastpacket;
++ if(req->req.actual == req->req.length ||
++ req->lastpacket < ep->ep.maxpacket) {
++ list_del_init(&req->queue);
++ spin_unlock_irqrestore(&ep->lock, flags);
++ //printk("rq done ep%d\n", ep->addr);
++ req->req.status = 0;
++ if(req->req.complete) {
++ req->req.complete(&ep->ep, &req->req);
++ }
++ } else {
++ //printk("rq partial ep%d %d/%d\n", ep->addr, req->req.actual, req->req.length);
++ spin_unlock_irqrestore(&ep->lock, flags);
++ }
++ }
++}
++
++static int ast_ep_queue_run(struct ast_ep* ep) {
++ struct ast_usb_request *req;
++ unsigned long flags;
++ spin_lock_irqsave(&ep->lock, flags);
++ if(ep->active && !ep->dma_busy) {
++ //ep isn't busy..
++ if(list_empty(&ep->queue)) {
++ // nothing
++ } else {
++ req = list_entry(ep->queue.next, struct ast_usb_request, queue);
++ req->lastpacket = req->req.length - req->req.actual;
++ if (req->lastpacket > ep->ep.maxpacket) {
++ req->lastpacket = ep->ep.maxpacket;
++ }
++ //printk("ep%d%sx:%d-%d/%d\n",
++ // ep->addr,
++ // ep->to_host ? "t" : "r",
++ // req->req.actual,
++ // req->req.actual + req->lastpacket,
++ // req->req.length);
++ ep_txrx(ep, req->req.buf + req->req.actual, req->lastpacket);
++ req->in_transit = 1;
++ ep->dma_busy = 1;
++ }
++ }
++ spin_unlock_irqrestore(&ep->lock, flags);
++ return 0;
++}
++
++static void run_all_ep_queues(unsigned long data) {
++ int i;
++ unsigned long flags;
++ spin_lock_irqsave(&udc.lock, flags);
++
++ for(i = 0; i < NUM_ENDPOINTS; i++) {
++ if(eps[i].active) {
++ ep_txrx_check_done(&eps[i]);
++ ast_ep_queue_run(&eps[i]);
++ }
++ }
++
++ spin_unlock_irqrestore(&udc.lock, flags);
++}
++
++DECLARE_TASKLET(check_ep_queues, run_all_ep_queues, 0);
++
++static int ast_ep_queue(struct usb_ep* _ep, struct usb_request *_rq, gfp_t gfp_flags) {
++ struct ast_usb_request *req = to_ast_req(_rq);
++ struct ast_ep *ep = to_ast_ep(_ep);
++ unsigned long flags;
++
++ if (ep == &ep0_ep) {
++ return ep0_enqueue(_ep, _rq, gfp_flags);
++ }
++
++ _rq->status = -EINPROGRESS;
++ spin_lock_irqsave(&ep->lock, flags);
++ list_add_tail(&req->queue, &ep->queue);
++ req->req.actual = 0;
++ spin_unlock_irqrestore(&ep->lock, flags);
++ ast_ep_queue_run(ep);
++
++ return 0;
++}
++
++static int ast_ep_set_halt(struct usb_ep* _ep, int value) {
++ struct ast_ep *ep = to_ast_ep(_ep);
++ unsigned long flags;
++ if (ep == &ep0_ep) {
++ /* cannot halt ep0, just return */
++ return 0;
++ }
++ spin_lock_irqsave(&ep->lock, flags);
++ if(value) {
++ ep_hwritel(ep, CONFIG, ep_hreadl(ep, CONFIG) | AST_EP_STALL_ENABLED);
++ } else {
++ ep_hwritel(ep, CONFIG, ep_hreadl(ep, CONFIG) &~ AST_EP_STALL_ENABLED);
++ }
++ spin_unlock_irqrestore(&ep->lock, flags);
++ return 0;
++}
++
++static const struct usb_ep_ops ast_ep_ops = {
++ .enable = ast_ep_enable,
++ .disable = ast_ep_disable,
++ .queue = ast_ep_queue,
++ .dequeue = ast_ep_dequeue,
++ .set_halt = ast_ep_set_halt,
++ .alloc_request = ast_alloc_request,
++ .free_request = ast_free_request,
++};
++
++static irqreturn_t ast_vhub_udc_irq(int irq, void* devid) {
++ irqreturn_t status = IRQ_NONE;
++ u32 istatus;
++ (void) devid;
++
++ istatus = ast_hreadl(&udc, ISR);
++
++ /*
++ * Must handle IN/OUT ACK first.
++ * For example, in the case of SETUP request DATA IN, after we send out data,
++ * we enqueue a request for STATUS ack from host, and stage will be
++ * STATUS(IN). When host receives the data, it sends out the STATUS msg
++ * and then a new SETUP. In this case, if we process the SETUP first,
++ * that will confuse the stage state machine, as it expects STATUS msg
++ * for now.
++ */
++ if(istatus & AST_IRQ_EP0_OUT_ACK) {
++ clear_isr(AST_IRQ_EP0_OUT_ACK);
++ ep0_handle_ack();
++ status = IRQ_HANDLED;
++ }
++
++ if(istatus & AST_IRQ_EP0_IN_ACK) {
++ clear_isr(AST_IRQ_EP0_IN_ACK);
++ ep0_handle_ack();
++ status = IRQ_HANDLED;
++ }
++
++ if(istatus & AST_IRQ_EP0_SETUP) {
++ clear_isr(AST_IRQ_EP0_SETUP);
++ ep0_handle_setup();
++ status = IRQ_HANDLED;
++ }
++
++ if(istatus & AST_IRQ_EP_POOL_ACK) {
++ u32 acked = ast_hreadl(&udc, EP_ACK_ISR);
++ ast_hwritel(&udc, EP_ACK_ISR, acked);
++ clear_isr(AST_IRQ_EP_POOL_ACK);
++ status = IRQ_HANDLED;
++ tasklet_schedule(&check_ep_queues);
++ }
++
++ if(istatus & AST_IRQ_EP_POOL_NAK) {
++ clear_isr(AST_IRQ_EP_POOL_NAK);
++ printk("Got NAK on the EP pool");
++ status = IRQ_HANDLED;
++ }
++
++ if (status != IRQ_HANDLED) {
++ printk("vhub: unhandled interrupts! ISR: %08x\n", istatus);
++ } else {
++ ep0_handle_status();
++ }
++
++ return status;
++}
++
++int usb_gadget_register_driver(struct usb_gadget_driver *driver) {
++ int err = 0;
++ unsigned long flags;
++ printk("gadget register driver: %s\n", driver->driver.name);
++ if(!udc.pdev)
++ return -ENODEV;
++
++ spin_lock_irqsave(&udc.lock, flags);
++ udc.pullup_on = 1;
++ if (udc.driver) {
++ err = -EBUSY;
++ goto err;
++ }
++ udc.driver = driver;
++ udc.gadget.dev.driver = &driver->driver;
++err:
++ spin_unlock_irqrestore(&udc.lock, flags);
++ if(err == 0) {
++ //ok so far
++ err = driver->bind(&udc.gadget);
++ }
++ if(err == 0) {
++ if(udc.pullup_on) {
++ enable_upstream_port();
++ }
++ printk("vhub: driver registered, port on!\n");
++ } else {
++ printk("vhub: driver failed to register: %d\n", err);
++ spin_lock_irqsave(&udc.lock, flags);
++ udc.driver = NULL;
++ udc.gadget.dev.driver = NULL;
++ spin_unlock_irqrestore(&udc.lock, flags);
++ }
++ return err;
++}
++EXPORT_SYMBOL(usb_gadget_register_driver);
++
++int usb_gadget_unregister_driver(struct usb_gadget_driver *driver) {
++ int err = 0;
++ unsigned long flags;
++ if(!udc.pdev)
++ return -ENODEV;
++ if(driver != udc.driver || !driver->unbind) {
++ return -EINVAL;
++ }
++
++ spin_lock_irqsave(&udc.lock, flags);
++
++ // disappear from the host
++ ast_udc_pullup(&udc.gadget, 0);
++ if(udc.driver->disconnect) {
++ udc.driver->disconnect(&udc.gadget);
++ }
++
++ driver->unbind(&udc.gadget);
++ // turn off the EPs
++ disable_all_endpoints();
++
++ udc.gadget.dev.driver = NULL;
++ udc.driver = NULL;
++
++ spin_unlock_irqrestore(&udc.lock, flags);
++ return err;
++}
++EXPORT_SYMBOL(usb_gadget_unregister_driver);
++
++static int __init ast_vhub_udc_probe(struct platform_device *pdev) {
++ struct resource *res;
++ int err = -ENODEV;
++ int irq;
++ int i;
++
++ udc.regs = NULL;
++ irq = platform_get_irq(pdev, 0);
++ if(irq < 0)
++ return irq;
++ udc.irq = irq;
++
++ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
++
++ spin_lock_init(&udc.lock);
++ err = -ENOMEM;
++ udc.regs = ioremap(res->start, res->end - res->start + 1);
++ if(!udc.regs) {
++ dev_err(&pdev->dev, "Couldn't map I/O memory!\n");
++ goto error;
++ }
++
++ dev_info(&pdev->dev, "aspeed_udc at 0x%08lx mapped at %p\n",
++ (unsigned long)res->start, udc.regs);
++ platform_set_drvdata(pdev, &udc);
++ device_initialize(&udc.gadget.dev);
++
++ udc.gadget.dev.parent = &pdev->dev;
++ udc.gadget.dev.dma_mask = pdev->dev.dma_mask;
++
++ /* disable all interrupts first */
++ ast_hwritel(&udc, INTERRUPT_ENABLE, 0);
++
++ ast_hwritel(&udc, ISR, 0x1ffff);
++ err = request_irq(irq, ast_vhub_udc_irq, 0, "aspeed_udc", &udc);
++
++ if(err) {
++ dev_err(&pdev->dev, "failed to get irq %d: %d\n", irq, err);
++ goto error;
++ }
++
++ udc.ep0_dma_virt = ast_alloc_dma_memory(
++ AST_UDC_EP0_MAXPACKET, DMA_BIDIRECTIONAL, &udc.ep0_dma_phys);
++ if (!udc.ep0_dma_virt) {
++ printk("vhub fatal: Couldn't get DMA memory!\n");
++ goto error;
++ }
++ ast_hwritel(&udc, EP0_DMA_ADDR, udc.ep0_dma_phys);
++
++ printk("virthub init...\n");
++ ast_hwritel(&udc, SOFTRESET_ENABLE, 0x33f);
++ ast_hwritel(&udc, SOFTRESET_ENABLE, 0x0);
++ ast_hwritel(&udc, ISR, 0x1ffff);
++ ast_hwritel(&udc, EP_ACK_ISR, 0xffffffff);
++ ast_hwritel(&udc, EP_NAK_ISR, 0xffffffff);
++
++ ast_hwritel(&udc, EP1_STATUS, 0x1);
++ ast_hwritel(&udc, STATUS, AST_HUB_RESET_DISABLE);
++
++ udc.pdev = pdev;
++
++ INIT_LIST_HEAD(&ep0_ep.ep.ep_list);
++ udc.gadget.ep0 = &ep0_ep.ep;
++
++ eps = kzalloc(sizeof(struct ast_ep) * 14, GFP_KERNEL);
++ if(!eps) {
++ goto error;
++ }
++
++ for (i = 0; i < NUM_ENDPOINTS; i++) {
++ struct ast_ep* ep = &eps[i];
++ ep->ep_regs = udc.regs + 0x200 + (i * 0x10);
++ INIT_LIST_HEAD(&ep->queue);
++ ep->ep.ops = &ast_ep_ops;
++ ep->index = i;
++ // i+2, Can't use EP1 as the 'virtual hub' has it built in
++ // when using the root device.
++ ep->addr = i+2;
++ snprintf(ep->epname, 7, "ep%d", ep->addr);
++ ep->ep.name = ep->epname;
++ ep->ep.maxpacket = 1024;
++ spin_lock_init(&ep->lock);
++ list_add_tail(&ep->ep.ep_list, &udc.gadget.ep_list);
++ }
++
++ /* enable interrupts */
++ ast_hwritel(&udc, INTERRUPT_ENABLE,
++ AST_INT_EP_POOL_ACK
++ | AST_INT_EP0_IN_ACK
++ | AST_INT_EP0_OUT_ACK
++ | AST_INT_EP0_SETUP_ACK);
++
++ err = device_add(&udc.gadget.dev);
++ if(err) {
++ dev_dbg(&pdev->dev, "Could not add gadget: %d\n", err);
++ goto error;
++ }
++ return 0;
++error:
++ if(udc.regs)
++ iounmap(udc.regs);
++ platform_set_drvdata(pdev, NULL);
++ return err;
++}
++
++static int ast_vhub_udc_remove(struct platform_device *pdev) {
++ if(udc.regs)
++ iounmap(udc.regs);
++ if(udc.irq)
++ free_irq(udc.irq, &udc);
++ platform_set_drvdata(pdev, NULL);
++ return 0;
++}
++
++static struct platform_driver ast_vhub_udc_driver = {
++ .probe = ast_vhub_udc_probe,
++ .remove = ast_vhub_udc_remove,
++ .driver = {
++ .name = "aspeed_udc",
++ .owner = THIS_MODULE,
++ },
++};
++
++static int __init ast_udc_init(void) {
++ return platform_driver_probe(&ast_vhub_udc_driver, ast_vhub_udc_probe);
++}
++module_init(ast_udc_init);
++
++static void __exit ast_udc_exit(void) {
++ ast_free_dma_memory(AST_UDC_EP0_MAXPACKET, DMA_BIDIRECTIONAL,
++ udc.ep0_dma_virt, udc.ep0_dma_phys);
++ platform_driver_unregister(&ast_vhub_udc_driver);
++}
++module_exit(ast_udc_exit);
++
++MODULE_DESCRIPTION("AST2400/1250 USB UDC Driver");
++MODULE_AUTHOR("");
++MODULE_LICENSE("GPL");
++MODULE_ALIAS("platform:aspeed_udc");
+diff --git a/drivers/usb/gadget/aspeed_udc.h b/drivers/usb/gadget/aspeed_udc.h
+new file mode 100644
+index 0000000..5494afd
+--- /dev/null
++++ b/drivers/usb/gadget/aspeed_udc.h
+@@ -0,0 +1,161 @@
++/*
++ * Copyright 2014-present Facebook. All Rights Reserved.
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
++ */
++
++#ifndef __LINUX_USB_GADGET_ASPEED_UDC_H
++#define __LINUX_USB_GADGET_ASPEED_UDC_H
++
++#define AST_INT_EP_POOL_NAK (1 << 17)
++#define AST_INT_EP_POOL_ACK (1 << 16)
++#define AST_INT_DEV5_CONTROLLER (1 << 13)
++#define AST_INT_DEV4_CONTROLLER (1 << 12)
++#define AST_INT_DEV3_CONTROLLER (1 << 11)
++#define AST_INT_DEV2_CONTROLLER (1 << 10)
++#define AST_INT_DEV1_CONTROLLER (1 << 9)
++
++/* Interrupt control bits */
++#define AST_INT_EP1_IN_ACK (1 << 5)
++#define AST_INT_EP0_IN_NAK (1 << 4)
++#define AST_INT_EP0_IN_ACK (1 << 3)
++#define AST_INT_EP0_OUT_NAK (1 << 2)
++#define AST_INT_EP0_OUT_ACK (1 << 1)
++#define AST_INT_EP0_SETUP_ACK (1 << 0)
++
++/* Interrupt status bits */
++#define AST_IRQ_EP_POOL_NAK (1 << 17)
++#define AST_IRQ_EP_POOL_ACK (1 << 16)
++#define AST_IRQ_EP0_SETUP (1 << 0)
++#define AST_IRQ_EP0_OUT_ACK (1 << 1)
++#define AST_IRQ_EP0_OUT_NAK (1 << 2)
++#define AST_IRQ_EP0_IN_ACK (1 << 3)
++#define AST_IRQ_EP0_IN_NAK (1 << 4)
++#define AST_IRQ_EP1_IN_ACK (1 << 5)
++
++#define AST_HUB_RESET_DISABLE (1 << 11)
++
++#define AST_HUB_BASE_ADDR 0x1e6a0000
++#define AST_HUB_STATUS 0x00
++#define AST_HUB_ISR 0x0c
++#define AST_HUB_EP_ACK_ISR 0x18
++#define AST_HUB_EP_NAK_ISR 0x1C
++#define AST_HUB_SOFTRESET_ENABLE 0x20
++#define AST_HUB_INTERRUPT_ENABLE 0x08
++#define AST_HUB_EP0_STATUS 0x30
++#define AST_HUB_EP1_STATUS 0x38
++#define AST_HUB_EP0_DMA_ADDR 0x34
++#define AST_HUB_ROOT_CONFIG 0x04
++#define AST_HUB_EP_ACK_INT_ENABLE 0x10
++#define AST_HUB_EP_NAK_INT_ENABLE 0x14
++
++#define AST_HUB_ROOT_SETUP_BUFFER 0x80
++
++#define AST_EP0_OUT_READY (1 << 2)
++#define AST_EP0_IN_READY (1 << 1)
++#define AST_EP0_STALL (1 << 0)
++
++#define AST_EP_REG_SIZE 0x10
++#define AST_EP_BASE(i) (0x200 + (i) * 0x10)
++
++#define AST_EP_CONFIG 0x00
++#define AST_EP_DMA_CONTROL 0x04
++#define AST_EP_DESC_BASE 0x08
++#define AST_EP_DESC_STATUS 0x0C
++
++#define AST_EP_DL_RESET (1 << 2)
++#define AST_EP_SINGLE_STAGE (1 << 1)
++#define AST_EP_STALL_ENABLED (1 << 12)
++
++#define AST_EP_TYPE_DISABLED 0
++#define AST_EP_TYPE_BULK_IN 2
++#define AST_EP_TYPE_BULK_OUT 3
++#define AST_EP_TYPE_INT_IN 4
++#define AST_EP_TYPE_INT_OUT 5
++#define AST_EP_TYPE_ISO_IN 6
++#define AST_EP_TYPE_ISO_OUT 7
++
++#define AST_EP_ENABLED 1
++
++#define ep_set_type(type, config) \
++ (config | (AST_EP_TYPE_##type << 4))
++
++#define ast_hreadl(udcp, reg) \
++ ioread32((udcp)->regs + AST_HUB_##reg)
++
++#define ast_hwritel(udcp, reg, value) \
++ iowrite32(value, (udcp)->regs + AST_HUB_##reg)
++
++#define ep_hreadl(ep, reg) \
++ ioread32((ep)->ep_regs + AST_EP_##reg)
++
++#define ep_hwritel(ep, reg, value) \
++ iowrite32(value, (ep)->ep_regs + AST_EP_##reg)
++
++
++struct aspeed_udc {
++ spinlock_t lock;
++
++ void __iomem *regs;
++ struct usb_gadget gadget;
++ struct usb_gadget_driver *driver;
++ struct platform_device *pdev;
++
++ struct dma_pool *pool;
++
++ void* ep0_dma_virt;
++ dma_addr_t ep0_dma_phys;
++
++ u16 hub_address;
++ int irq;
++ unsigned int pullup_on;
++
++ enum {
++ EP0_STAGE_SETUP,
++ EP0_STAGE_DATA,
++ EP0_STAGE_STATUS,
++ } ep0_stage;
++ /* either USB_DIR_OUT or USB_DIR_IN, valid if it is in data or status stage */
++ u8 ep0_dir;
++};
++
++struct ast_usb_request {
++ struct usb_request req;
++ struct list_head queue;
++ size_t lastpacket;
++
++ unsigned int in_transit:1;
++};
++
++struct ast_ep {
++ struct usb_ep ep;
++ u8 addr;
++ u8 index;
++ char epname[7];
++ void __iomem *ep_regs;
++
++ spinlock_t lock;
++ struct list_head queue;
++ void *txbuf;
++ dma_addr_t txbuf_phys;
++
++ unsigned int dma_busy:1;
++ unsigned int to_host:1;
++ unsigned int active:1;
++ // const struct usb_endpoint_descriptor *desc;
++};
++
++
++#endif /* __LINUX_USB_GADGET_ASPEED_UDC_H */
+diff --git a/drivers/usb/gadget/epautoconf.c b/drivers/usb/gadget/epautoconf.c
+index 9462e30..b631931 100644
+--- a/drivers/usb/gadget/epautoconf.c
++++ b/drivers/usb/gadget/epautoconf.c
+@@ -182,6 +182,9 @@ ep_matches (
+ /* min() doesn't work on bitfields with gcc-3.5 */
+ if (size > 64)
+ size = 64;
++ if (gadget->is_dualspeed) {
++ size = 512;
++ }
+ desc->wMaxPacketSize = cpu_to_le16(size);
+ }
+ return 1;
+diff --git a/drivers/usb/gadget/gadget_chips.h b/drivers/usb/gadget/gadget_chips.h
+index 4e3107d..1f05142 100644
+--- a/drivers/usb/gadget/gadget_chips.h
++++ b/drivers/usb/gadget/gadget_chips.h
+@@ -158,6 +158,13 @@
+ #define gadget_is_fsl_qe(g) 0
+ #endif
+
++/* ASPEED BMC Support */
++#ifdef CONFIG_USB_GADGET_ASPEED_AST
++#define gadget_is_aspeed(g) !strcmp("aspeed_udc", (g)->name)
++#else
++#define gadget_is_aspeed(g) 0
++#endif
++
+
+ // CONFIG_USB_GADGET_SX2
+ // CONFIG_USB_GADGET_AU1X00
+@@ -225,6 +232,8 @@ static inline int usb_gadget_controller_number(struct usb_gadget *gadget)
+ return 0x21;
+ else if (gadget_is_fsl_qe(gadget))
+ return 0x22;
++ else if (gadget_is_aspeed(gadget))
++ return 0x23;
+ return -ENOENT;
+ }
+
+diff --git a/drivers/watchdog/ast_wdt.c b/drivers/watchdog/ast_wdt.c
+index 845f1db..9e7e84f 100644
+--- a/drivers/watchdog/ast_wdt.c
++++ b/drivers/watchdog/ast_wdt.c
+@@ -78,6 +78,17 @@ typedef unsigned char bool_T;
+ #define WDT_Clr (WDT_BASE_VA+0x14)
+ #define WDT_RstWd (WDT_BASE_VA+0x18)
+
++#define WDT_CTRL_B_SECOND_BOOT (0x1 << 7)
++#define WDT_CTRL_B_RESET_SOC (0x00 << 5) /* yes, 0x00 */
++#define WDT_CTRL_B_RESET_FULL (0x01 << 5)
++#define WDT_CTRL_B_RESET_ARM (0x2 << 5)
++#define WDT_CTRL_B_RESET_MASK (0x3 << 5)
++#define WDT_CTRL_B_1MCLK (0x1 << 4)
++#define WDT_CTRL_B_EXT (0x1 << 3)
++#define WDT_CTRL_B_INTR (0x1 << 2)
++#define WDT_CTRL_B_CLEAR_AFTER (0x1 << 1)
++#define WDT_CTRL_B_ENABLE (0x1 << 0)
++
+
+ #define AST_READ_REG(r) (*((volatile unsigned int *) (r)))
+ #define AST_WRITE_REG(r,v) (*((volatile unsigned int *) (r)) = ((unsigned int) (v)))
+@@ -87,17 +98,24 @@ typedef unsigned char bool_T;
+ #define WDT_CLK_SRC_PCLK 1
+
+ //Global Variables
+-#define WD_TIMO 6 /* Default heartbeat = 6 seconds */
++#define WDT_TIMO 30 /* Default heartbeat = 30 seconds */
++
++#define WDT_INITIAL_TIMO (8*60) /* Initial timeout, 8m */
++#define WDT_TIMO2TICKS(t) (TICKS_PER_uSEC * 1000000 * (t))
+
+-static int heartbeat = WD_TIMO;
++static int heartbeat = WDT_TIMO;
+ module_param(heartbeat, int, 0);
+-MODULE_PARM_DESC(heartbeat, "Watchdog heartbeat in seconds. (0<heartbeat<65536, default=" __MODULE_STRING(WD_TIMO) ")");
++MODULE_PARM_DESC(heartbeat, "Watchdog heartbeat in seconds. (0<heartbeat<65536, default=" __MODULE_STRING(WDT_TIMO) ")");
+
+ static int nowayout = WATCHDOG_NOWAYOUT;
+ module_param(nowayout, int, 0);
+ MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)");
+
+-static unsigned long wdt_is_open;
++static int force_disable = 0; // setting this to 1 will disable the wdt timer
++module_param(force_disable, int, 0);
++MODULE_PARM_DESC(force_disable, "Disable watchdog by default "
++ "(default=0, enable watchdog)");
++
+ static char expect_close;
+
+ //Function Declaration
+@@ -117,7 +135,7 @@ void wdt_disable(void)
+
+ /* reset WDT_Ctrl[0] as 0 */
+ regVal = AST_READ_REG(WDT_Ctrl);
+- regVal &= 0xFFFFFFFE;
++ regVal &= ~(WDT_CTRL_B_ENABLE);
+ AST_WRITE_REG(WDT_Ctrl, regVal);
+ }
+
+@@ -129,17 +147,18 @@ void wdt_sel_clk_src(unsigned char sourceClk)
+ if (sourceClk == WDT_CLK_SRC_PCLK)
+ {
+ /* reset WDT_Ctrl[4] as 0 */
+- regVal &= 0xFFFFFFEF;
++ regVal &= ~(WDT_CTRL_B_1MCLK);
+ }
+ else
+ {
+ /* set WDT_Ctrl[4] as 1 */
+- regVal |= 0x00000010;
++ regVal |= WDT_CTRL_B_1MCLK;
+ }
+ AST_WRITE_REG(WDT_Ctrl, regVal);
+ }
+
+-void wdt_set_timeout_action(bool_T bResetOut, bool_T bIntrSys, bool_T bResetSys)
++void wdt_set_timeout_action(bool_T bResetOut, bool_T bIntrSys,
++ bool_T bClrAfter, bool_T bResetARMOnly)
+ {
+ register unsigned int regVal;
+
+@@ -148,70 +167,102 @@ void wdt_set_timeout_action(bool_T bResetOut, bool_T bIntrSys, bool_T bResetSys)
+ if (bResetOut)
+ {
+ /* set WDT_Ctrl[3] = 1 */
+- regVal |= 0x00000008;
++ regVal |= WDT_CTRL_B_EXT;
+ }
+ else
+ {
+ /* reset WDT_Ctrl[3] = 0 */
+- regVal &= 0xFFFFFFF7;
++ regVal &= ~WDT_CTRL_B_EXT;
+ }
+
+ if (bIntrSys)
+ {
+ /* set WDT_Ctrl[2] = 1 */
+- regVal |= 0x00000004;
++ regVal |= WDT_CTRL_B_INTR;
+ }
+ else
+ {
+ /* reset WDT_Ctrl[2] = 0 */
+- regVal &= 0xFFFFFFFB;
++ regVal &= ~WDT_CTRL_B_INTR;
+ }
+
+- if (bResetSys)
++ if (bClrAfter)
+ {
+ /* set WDT_Ctrl[1] = 1 */
+- regVal |= 0x00000002;
++ regVal |= WDT_CTRL_B_CLEAR_AFTER;
+ }
+ else
+ {
+ /* reset WDT_Ctrl[1] = 0 */
+- regVal &= 0xFFFFFFFD;
++ regVal &= ~WDT_CTRL_B_CLEAR_AFTER;
++ }
++
++ if (bResetARMOnly)
++ {
++ /* set WDT_Ctrl[6..5] = 10 ie, reset ARM only */
++ regVal &= ~WDT_CTRL_B_RESET_MASK;
++ regVal |= WDT_CTRL_B_RESET_ARM;
++ }
++ else
++ {
++ /* reset WDT_CTrl[6..5] = 01, full chip */
++ regVal &= ~WDT_CTRL_B_RESET_MASK;
++ regVal |= WDT_CTRL_B_RESET_FULL;
+ }
++
+
+ AST_WRITE_REG(WDT_Ctrl, regVal);
+ }
+
+ void wdt_enable(void)
+ {
+- register unsigned int regVal;
++ if (!force_disable) {
++ register unsigned int regVal;
++
++ /* set WDT_Ctrl[0] as 1 */
++ regVal = AST_READ_REG(WDT_Ctrl);
++ regVal |= WDT_CTRL_B_ENABLE;
++ AST_WRITE_REG(WDT_Ctrl, regVal);
++ }
++}
+
+- /* set WDT_Ctrl[0] as 1 */
+- regVal = AST_READ_REG(WDT_Ctrl);
+- regVal |= 1;
+- AST_WRITE_REG(WDT_Ctrl, regVal);
++bool_T wdt_is_enabled(void)
++{
++ unsigned int reg;
++ reg = AST_READ_REG(WDT_Ctrl);
++ return reg & WDT_CTRL_B_ENABLE;
+ }
+
+-void wdt_restart_new(unsigned int nPeriod, int sourceClk, bool_T bResetOut, bool_T bIntrSys, bool_T bResetSys, bool_T bUpdated)
++
++void wdt_restart_new(unsigned int nPeriod, int sourceClk, bool_T bResetOut,
++ bool_T bIntrSys, bool_T bClrAfter, bool_T bResetARMOnly)
+ {
+- wdt_disable();
++ bool_T enabled = wdt_is_enabled();
++
++ if (enabled) {
++ wdt_disable();
++ }
+
+ AST_WRITE_REG(WDT_Reload, nPeriod);
+
+ wdt_sel_clk_src(sourceClk);
+
+- wdt_set_timeout_action(bResetOut, bIntrSys, bResetSys);
++ wdt_set_timeout_action(bResetOut, bIntrSys, bClrAfter, bResetARMOnly);
+
+ AST_WRITE_REG(WDT_Restart, 0x4755); /* reload! */
+
+- if (!bUpdated)
++ if (enabled) {
+ wdt_enable();
++ }
+ }
+
+ void wdt_restart(void)
+ {
+- wdt_disable();
+- AST_WRITE_REG(WDT_Restart, 0x4755); /* reload! */
+- wdt_enable();
++ if (!force_disable) {
++ wdt_disable();
++ AST_WRITE_REG(WDT_Restart, 0x4755); /* reload! */
++ wdt_enable();
++ }
+ }
+
+
+@@ -230,7 +281,9 @@ static int wdt_set_heartbeat(int t)
+
+ heartbeat=t;
+
+- wdt_restart_new(TICKS_PER_uSEC*1000000*t, WDT_CLK_SRC_EXT, FALSE, TRUE, FALSE, FALSE);
++ wdt_restart_new(WDT_TIMO2TICKS(t), WDT_CLK_SRC_EXT,
++ /* No Ext, No intr, Self clear, Full chip reset */
++ FALSE, FALSE, TRUE, FALSE);
+ return 0;
+ }
+
+@@ -245,8 +298,11 @@ static int wdt_set_heartbeat(int t)
+ * @count: count of bytes
+ * @ppos: pointer to the position to write. No seeks allowed
+ *
+- * A write to a watchdog device is defined as a keepalive signal. Any
+- * write of data will do, as we we don't define content meaning.
++ * A write to a watchdog device is defined as a keepalive signal.
++ * Any data will do, except for the reserved letters 'V' (to enable
++ * magic close), the letter 'X' (to override the current watchdog
++ * settings and disable it), or the letter 'x' (to turn off override
++ * and restore its old settings).
+ */
+
+ static ssize_t ast_wdt_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos)
+@@ -265,8 +321,20 @@ static int wdt_set_heartbeat(int t)
+ char c;
+ if (get_user(c, buf + i))
+ return -EFAULT;
+- if (c == 'V')
+- expect_close = 42;
++ switch(c) {
++ case 'V':
++ expect_close = 42;
++ break;
++ case 'X':
++ force_disable = 1;
++ wdt_disable();
++ break;
++ case 'x':
++ force_disable = 0;
++ break;
++ default:
++ break;
++ }
+ }
+ }
+ wdt_restart();
+@@ -338,8 +406,6 @@ static int ast_wdt_ioctl(struct inode *inode, struct file *file, unsigned int cm
+
+ static int ast_wdt_open(struct inode *inode, struct file *file)
+ {
+- if(test_and_set_bit(0, &wdt_is_open))
+- return -EBUSY;
+ /*
+ * Activate
+ */
+@@ -362,14 +428,23 @@ static int ast_wdt_open(struct inode *inode, struct file *file)
+
+ static int ast_wdt_release(struct inode *inode, struct file *file)
+ {
+- if (expect_close == 42 || !nowayout)
++ if (expect_close != 42 || !nowayout)
+ {
++ /* handles the case where the device is closed without the "magic
++ * close" character (anything that is not 'V' qualifies -- see the
++ * original Linux watchdog spec for more about this). closing the
++ * device in this case must disable the timer too, so automatic
++ * restarts are inhibited.
++ */
++
+ wdt_disable();
+- clear_bit(0, &wdt_is_open);
+ }
+ else
+ {
+- printk(KERN_CRIT "wdt: WDT device closed unexpectedly. WDT will not stop!\n");
++ /* handles the case where the kernel is compiled with nowayout, or
++ * if the user specifies that the watchdog should continue ticking
++ * after device closure (by writing a 'V' before closing the device)
++ */
+ wdt_restart();
+ }
+ expect_close = 0;
+@@ -398,14 +473,23 @@ static int ast_wdt_notify_sys(struct notifier_block *this, unsigned long code, v
+ return NOTIFY_DONE;
+ }
+
+-extern void ast_soc_wdt_reset(void)
++extern void ast_soc_reset_soc(void)
+ {
+- writel(0x10 , WDT_BASE_VA+0x04);
+- writel(0x4755, WDT_BASE_VA+0x08);
+- writel(0x3, WDT_BASE_VA+0x0c);
++ writel(0x10 , WDT_Reload);
++ writel(0x4755, WDT_Restart);
++ writel(WDT_CTRL_B_RESET_SOC|WDT_CTRL_B_CLEAR_AFTER|WDT_CTRL_B_ENABLE,
++ WDT_Ctrl);
+ }
++EXPORT_SYMBOL(ast_soc_reset_soc);
+
+-EXPORT_SYMBOL(ast_soc_wdt_reset);
++extern void ast_wdt_reset_full(void)
++{
++ writel(0x10 , WDT_Reload);
++ writel(0x4755, WDT_Restart);
++ writel(WDT_CTRL_B_RESET_FULL|WDT_CTRL_B_CLEAR_AFTER|WDT_CTRL_B_ENABLE,
++ WDT_Ctrl);
++}
++EXPORT_SYMBOL(ast_wdt_reset_full);
+
+ static struct file_operations ast_wdt_fops =
+ {
+@@ -433,10 +517,6 @@ static int ast_wdt_probe(struct platform_device *pdev)
+ {
+ int ret;
+
+- wdt_disable();
+- wdt_sel_clk_src(WDT_CLK_SRC_EXT);
+- wdt_set_timeout_action(FALSE, FALSE, FALSE);
+-
+ /* register ISR */
+ if (request_irq(IRQ_WDT, (void *)wdt_isr, IRQF_DISABLED, "WDT", NULL))
+ {
+@@ -463,9 +543,22 @@ static int ast_wdt_probe(struct platform_device *pdev)
+ }
+
+ /* interrupt the system while WDT timeout */
+- wdt_restart_new(TICKS_PER_uSEC*1000000*heartbeat, WDT_CLK_SRC_EXT, FALSE, TRUE, FALSE, TRUE);
++ wdt_restart_new(WDT_TIMO2TICKS(WDT_INITIAL_TIMO), WDT_CLK_SRC_EXT,
++ /* No Ext, No intr, Self clear, Full chip reset */
++ FALSE, FALSE, TRUE, FALSE);
+
+- printk(KERN_INFO "AST WDT is installed.(irq = %d, heartbeat = %d secs, nowayout = %d)\n",IRQ_WDT,heartbeat,nowayout);
++ /* enable it by default */
++ if (!force_disable) {
++ wdt_enable();
++ }
++
++ /* change the reload value back to regular */
++ AST_WRITE_REG(WDT_Reload, WDT_TIMO2TICKS(heartbeat));
++
++ printk(KERN_INFO "UMVP2500 WDT is installed. (irq:%d, initial timeout:%ds, "
++ "timeout:%ds nowayout:%d enabled:%s)\n",
++ IRQ_WDT, WDT_INITIAL_TIMO, heartbeat, nowayout,
++ wdt_is_enabled() ? "yes" : "no");
+
+ return (0);
+ }
+diff --git a/include/linux/i2c.h b/include/linux/i2c.h
+index 33a5992..59167e2 100644
+--- a/include/linux/i2c.h
++++ b/include/linux/i2c.h
+@@ -576,6 +576,17 @@ union i2c_smbus_data {
+ /* and one more for user-space compatibility */
+ };
+
++/*
++ * Large SMBus block data io, which is not defined in the SMBus standard,
++ * but used by some NIC (i.e. Intel I354) sideband SMBus interface.
++ */
++#define I2C_SMBUS_BLOCK_LARGE_MAX 240 /* extra large block size */
++union i2c_smbus_large_data {
++ union i2c_smbus_data data;
++ __u8 block[I2C_SMBUS_BLOCK_LARGE_MAX + 2]; /* block[0] is used for length */
++ /* and one more for PEC */
++};
++
+ /* i2c_smbus_xfer read or write markers */
+ #define I2C_SMBUS_READ 1
+ #define I2C_SMBUS_WRITE 0
+@@ -591,6 +602,7 @@ union i2c_smbus_data {
+ #define I2C_SMBUS_I2C_BLOCK_BROKEN 6
+ #define I2C_SMBUS_BLOCK_PROC_CALL 7 /* SMBus 2.0 */
+ #define I2C_SMBUS_I2C_BLOCK_DATA 8
++#define I2C_SMBUS_BLOCK_LARGE_DATA 9
+
+
+ #ifdef __KERNEL__
+diff --git a/include/linux/i2c/pmbus.h b/include/linux/i2c/pmbus.h
+new file mode 100644
+index 0000000..69280db
+--- /dev/null
++++ b/include/linux/i2c/pmbus.h
+@@ -0,0 +1,45 @@
++/*
++ * Hardware monitoring driver for PMBus devices
++ *
++ * Copyright (c) 2010, 2011 Ericsson AB.
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
++ */
++
++#ifndef _PMBUS_H_
++#define _PMBUS_H_
++
++/* flags */
++
++/*
++ * PMBUS_SKIP_STATUS_CHECK
++ *
++ * During register detection, skip checking the status register for
++ * communication or command errors.
++ *
++ * Some PMBus chips respond with valid data when trying to read an unsupported
++ * register. For such chips, checking the status register is mandatory when
++ * trying to determine if a chip register exists or not.
++ * Other PMBus chips don't support the STATUS_CML register, or report
++ * communication errors for no explicable reason. For such chips, checking
++ * the status register must be disabled.
++ */
++#define PMBUS_SKIP_STATUS_CHECK (1 << 0)
++
++struct pmbus_platform_data {
++ u32 flags; /* Device specific flags */
++};
++
++#endif /* _PMBUS_H_ */
+diff --git a/tools/.gitignore b/tools/.gitignore
+new file mode 100644
+index 0000000..e4e5f6c
+--- /dev/null
++++ b/tools/.gitignore
+@@ -0,0 +1 @@
++*~
+\ No newline at end of file
diff --git a/meta-aspeed/recipes-kernel/linux/files/patch-2.6.28.9/0001-MTD-fix-m25p80-64-bit-divisions.patch b/meta-aspeed/recipes-kernel/linux/files/patch-2.6.28.9/0001-MTD-fix-m25p80-64-bit-divisions.patch
new file mode 100644
index 0000000..c7f3d4e
--- /dev/null
+++ b/meta-aspeed/recipes-kernel/linux/files/patch-2.6.28.9/0001-MTD-fix-m25p80-64-bit-divisions.patch
@@ -0,0 +1,129 @@
+From d85316ac459f1cdd14ea1828eebeac1f1028e167 Mon Sep 17 00:00:00 2001
+From: Artem Bityutskiy <Artem.Bityutskiy@nokia.com>
+Date: Thu, 18 Dec 2008 14:10:05 +0200
+Subject: [PATCH 001/130] [MTD] fix m25p80 64-bit divisions
+
+MTD has recently been upgraded for 64-bit support, see commit
+number 69423d99fc182a81f3c5db3eb5c140acc6fc64be in the
+mtd-2.6.git tree (git://git.infradead.org/mtd-2.6.git)
+or see this URL:
+http://git.infradead.org/mtd-2.6.git?a=commit;h=69423d99fc182a81f3c5db3eb5c140acc6fc64be
+
+Some variables in MTD data structures which were 32-bit
+became 64-bit. Namely, the 'size' field in 'struct mtd_info'
+and the 'addr'/'len' fields in 'struct erase_info'. This
+means we have to use 'do_div' to divide them.
+
+This patch fixes the following linking error:
+ERROR: "__umoddi3" [drivers/mtd/devices/m25p80.ko] undefined!
+
+This patch changes divisions of 64-bit variable so that they use
+'do_div'. This patch also change some print placeholders to
+get rid of gcc warnings.
+
+Signed-off-by: Artem Bityutskiy <Artem.Bityutskiy@nokia.com>
+Signed-off-by: David Woodhouse <David.Woodhouse@intel.com>
+---
+ drivers/mtd/devices/m25p80.c | 37 +++++++++++++++++++------------------
+ 1 file changed, 19 insertions(+), 18 deletions(-)
+
+diff --git a/drivers/mtd/devices/m25p80.c b/drivers/mtd/devices/m25p80.c
+index 6659b22..9be0229 100644
+--- a/drivers/mtd/devices/m25p80.c
++++ b/drivers/mtd/devices/m25p80.c
+@@ -20,6 +20,7 @@
+ #include <linux/device.h>
+ #include <linux/interrupt.h>
+ #include <linux/mutex.h>
++#include <linux/math64.h>
+
+ #include <linux/mtd/mtd.h>
+ #include <linux/mtd/partitions.h>
+@@ -169,9 +170,9 @@ static int wait_till_ready(struct m25p *flash)
+ */
+ static int erase_chip(struct m25p *flash)
+ {
+- DEBUG(MTD_DEBUG_LEVEL3, "%s: %s %dKiB\n",
++ DEBUG(MTD_DEBUG_LEVEL3, "%s: %s %lldKiB\n",
+ flash->spi->dev.bus_id, __func__,
+- flash->mtd.size / 1024);
++ (long long)(flash->mtd.size >> 10));
+
+ /* Wait until finished previous write command. */
+ if (wait_till_ready(flash))
+@@ -232,18 +233,18 @@ static int m25p80_erase(struct mtd_info *mtd, struct erase_info *instr)
+ {
+ struct m25p *flash = mtd_to_m25p(mtd);
+ u32 addr,len;
++ uint32_t rem;
+
+- DEBUG(MTD_DEBUG_LEVEL2, "%s: %s %s 0x%08x, len %d\n",
++ DEBUG(MTD_DEBUG_LEVEL2, "%s: %s %s 0x%llx, len %lld\n",
+ flash->spi->dev.bus_id, __func__, "at",
+- (u32)instr->addr, instr->len);
++ (long long)instr->addr, (long long)instr->len);
+
+ /* sanity checks */
+ if (instr->addr + instr->len > flash->mtd.size)
+ return -EINVAL;
+- if ((instr->addr % mtd->erasesize) != 0
+- || (instr->len % mtd->erasesize) != 0) {
++ div_u64_rem(instr->len, mtd->erasesize, &rem);
++ if (rem)
+ return -EINVAL;
+- }
+
+ addr = instr->addr;
+ len = instr->len;
+@@ -677,24 +678,24 @@ static int __devinit m25p_probe(struct spi_device *spi)
+ flash->mtd.erasesize = info->sector_size;
+ }
+
+- dev_info(&spi->dev, "%s (%d Kbytes)\n", info->name,
+- flash->mtd.size / 1024);
++ dev_info(&spi->dev, "%s (%lld Kbytes)\n", info->name,
++ (long long)flash->mtd.size >> 10);
+
+ DEBUG(MTD_DEBUG_LEVEL2,
+- "mtd .name = %s, .size = 0x%.8x (%uMiB) "
++ "mtd .name = %s, .size = 0x%llx (%lldMiB) "
+ ".erasesize = 0x%.8x (%uKiB) .numeraseregions = %d\n",
+ flash->mtd.name,
+- flash->mtd.size, flash->mtd.size / (1024*1024),
++ (long long)flash->mtd.size, (long long)(flash->mtd.size >> 20),
+ flash->mtd.erasesize, flash->mtd.erasesize / 1024,
+ flash->mtd.numeraseregions);
+
+ if (flash->mtd.numeraseregions)
+ for (i = 0; i < flash->mtd.numeraseregions; i++)
+ DEBUG(MTD_DEBUG_LEVEL2,
+- "mtd.eraseregions[%d] = { .offset = 0x%.8x, "
++ "mtd.eraseregions[%d] = { .offset = 0x%llx, "
+ ".erasesize = 0x%.8x (%uKiB), "
+ ".numblocks = %d }\n",
+- i, flash->mtd.eraseregions[i].offset,
++ i, (long long)flash->mtd.eraseregions[i].offset,
+ flash->mtd.eraseregions[i].erasesize,
+ flash->mtd.eraseregions[i].erasesize / 1024,
+ flash->mtd.eraseregions[i].numblocks);
+@@ -722,12 +723,12 @@ static int __devinit m25p_probe(struct spi_device *spi)
+ if (nr_parts > 0) {
+ for (i = 0; i < nr_parts; i++) {
+ DEBUG(MTD_DEBUG_LEVEL2, "partitions[%d] = "
+- "{.name = %s, .offset = 0x%.8x, "
+- ".size = 0x%.8x (%uKiB) }\n",
++ "{.name = %s, .offset = 0x%llx, "
++ ".size = 0x%llx (%lldKiB) }\n",
+ i, parts[i].name,
+- parts[i].offset,
+- parts[i].size,
+- parts[i].size / 1024);
++ (long long)parts[i].offset,
++ (long long)parts[i].size,
++ (long long)(parts[i].size >> 10));
+ }
+ flash->partitioned = 1;
+ return add_mtd_partitions(&flash->mtd, parts, nr_parts);
+--
+1.8.1
+
diff --git a/meta-aspeed/recipes-kernel/linux/files/patch-2.6.28.9/0001-bzip2-lzma-library-support-for-gzip-bzip2-and-lzma-d.patch b/meta-aspeed/recipes-kernel/linux/files/patch-2.6.28.9/0001-bzip2-lzma-library-support-for-gzip-bzip2-and-lzma-d.patch
new file mode 100644
index 0000000..ffe1082
--- /dev/null
+++ b/meta-aspeed/recipes-kernel/linux/files/patch-2.6.28.9/0001-bzip2-lzma-library-support-for-gzip-bzip2-and-lzma-d.patch
@@ -0,0 +1,1876 @@
+From 8b368d36bf46357a115da164ffe0e12d881b3503 Mon Sep 17 00:00:00 2001
+From: Alain Knaff <alain@knaff.lu>
+Date: Sun, 4 Jan 2009 22:46:16 +0100
+Subject: bzip2/lzma: library support for gzip, bzip2 and lzma decompression
+
+Impact: Replaces inflate.c with a wrapper around zlib_inflate; new library code
+
+This is the first part of the bzip2/lzma patch
+
+The bzip patch is based on an idea by Christian Ludwig, includes support for
+compressing the kernel with bzip2 or lzma rather than gzip. Both
+compressors give smaller sizes than gzip. Lzma's decompresses faster
+than bzip2.
+
+It also supports ramdisks and initramfs' compressed using these two
+compressors.
+
+The functionality has been successfully used for a couple of years by
+the udpcast project
+
+This version applies to "tip" kernel 2.6.28
+
+This part contains:
+- changed inflate.c to accomodate rest of patch
+- implementation of bzip2 compression (not used at this stage yet)
+- implementation of lzma compression (not used at this stage yet)
+- Makefile routines to support bzip2 and lzma kernel compression
+
+Signed-off-by: Alain Knaff <alain@knaff.lu>
+Signed-off-by: H. Peter Anvin <hpa@zytor.com>
+---
+ .../include/linux/decompress/bunzip2.h | 10 +
+ .../include/linux/decompress/generic.h | 30 +
+ .../include/linux/decompress/inflate.h | 13 +
+ .../include/linux/decompress/mm.h | 87 +++
+ .../include/linux/decompress/unlzma.h | 12 +
+ .../linux-aspeed-2.6.28.9/lib/decompress_bunzip2.c | 735 +++++++++++++++++++++
+ .../linux-aspeed-2.6.28.9/lib/decompress_inflate.c | 167 +++++
+ .../linux-aspeed-2.6.28.9/lib/decompress_unlzma.c | 647 ++++++++++++++++++
+ .../lib/zlib_inflate/inflate.h | 4 +
+ .../lib/zlib_inflate/inftrees.h | 4 +
+ .../linux-aspeed-2.6.28.9/scripts/Makefile.lib | 14 +
+ .../files/linux-aspeed-2.6.28.9/scripts/bin_size | 10 +
+ 12 files changed, 1733 insertions(+)
+ create mode 100644 include/linux/decompress/bunzip2.h
+ create mode 100644 include/linux/decompress/generic.h
+ create mode 100644 include/linux/decompress/inflate.h
+ create mode 100644 include/linux/decompress/mm.h
+ create mode 100644 include/linux/decompress/unlzma.h
+ create mode 100644 lib/decompress_bunzip2.c
+ create mode 100644 lib/decompress_inflate.c
+ create mode 100644 lib/decompress_unlzma.c
+ create mode 100644 scripts/bin_size
+
+diff --git a/include/linux/decompress/bunzip2.h
+new file mode 100644
+index 0000000..1152721
+--- /dev/null
++++ b/include/linux/decompress/bunzip2.h
+@@ -0,0 +1,10 @@
++#ifndef DECOMPRESS_BUNZIP2_H
++#define DECOMPRESS_BUNZIP2_H
++
++int bunzip2(unsigned char *inbuf, int len,
++ int(*fill)(void*, unsigned int),
++ int(*flush)(void*, unsigned int),
++ unsigned char *output,
++ int *pos,
++ void(*error)(char *x));
++#endif
+diff --git a/include/linux/decompress/generic.h
+new file mode 100644
+index 0000000..f847f51
+--- /dev/null
++++ b/include/linux/decompress/generic.h
+@@ -0,0 +1,30 @@
++#ifndef DECOMPRESS_GENERIC_H
++#define DECOMPRESS_GENERIC_H
++
++/* Minimal chunksize to be read.
++ *Bzip2 prefers at least 4096
++ *Lzma prefers 0x10000 */
++#define COMPR_IOBUF_SIZE 4096
++
++typedef int (*decompress_fn) (unsigned char *inbuf, int len,
++ int(*fill)(void*, unsigned int),
++ int(*writebb)(void*, unsigned int),
++ unsigned char *output,
++ int *posp,
++ void(*error)(char *x));
++
++/* inbuf - input buffer
++ *len - len of pre-read data in inbuf
++ *fill - function to fill inbuf if empty
++ *writebb - function to write out outbug
++ *posp - if non-null, input position (number of bytes read) will be
++ * returned here
++ *
++ *If len != 0, the inbuf is initialized (with as much data), and fill
++ *should not be called
++ *If len = 0, the inbuf is allocated, but empty. Its size is IOBUF_SIZE
++ *fill should be called (repeatedly...) to read data, at most IOBUF_SIZE
++ */
++
++
++#endif
+diff --git a/include/linux/decompress/inflate.h
+new file mode 100644
+index 0000000..f9b06cc
+--- /dev/null
++++ b/include/linux/decompress/inflate.h
+@@ -0,0 +1,13 @@
++#ifndef INFLATE_H
++#define INFLATE_H
++
++/* Other housekeeping constants */
++#define INBUFSIZ 4096
++
++int gunzip(unsigned char *inbuf, int len,
++ int(*fill)(void*, unsigned int),
++ int(*flush)(void*, unsigned int),
++ unsigned char *output,
++ int *pos,
++ void(*error_fn)(char *x));
++#endif
+diff --git a/include/linux/decompress/mm.h
+new file mode 100644
+index 0000000..12ff8c3
+--- /dev/null
++++ b/include/linux/decompress/mm.h
+@@ -0,0 +1,87 @@
++/*
++ * linux/compr_mm.h
++ *
++ * Memory management for pre-boot and ramdisk uncompressors
++ *
++ * Authors: Alain Knaff <alain@knaff.lu>
++ *
++ */
++
++#ifndef DECOMPR_MM_H
++#define DECOMPR_MM_H
++
++#ifdef STATIC
++
++/* Code active when included from pre-boot environment: */
++
++/* A trivial malloc implementation, adapted from
++ * malloc by Hannu Savolainen 1993 and Matthias Urlichs 1994
++ */
++static unsigned long malloc_ptr;
++static int malloc_count;
++
++static void *malloc(int size)
++{
++ void *p;
++
++ if (size < 0)
++ error("Malloc error");
++ if (!malloc_ptr)
++ malloc_ptr = free_mem_ptr;
++
++ malloc_ptr = (malloc_ptr + 3) & ~3; /* Align */
++
++ p = (void *)malloc_ptr;
++ malloc_ptr += size;
++
++ if (free_mem_end_ptr && malloc_ptr >= free_mem_end_ptr)
++ error("Out of memory");
++
++ malloc_count++;
++ return p;
++}
++
++static void free(void *where)
++{
++ malloc_count--;
++ if (!malloc_count)
++ malloc_ptr = free_mem_ptr;
++}
++
++#define large_malloc(a) malloc(a)
++#define large_free(a) free(a)
++
++#define set_error_fn(x)
++
++#define INIT
++
++#else /* STATIC */
++
++/* Code active when compiled standalone for use when loading ramdisk: */
++
++#include <linux/kernel.h>
++#include <linux/fs.h>
++#include <linux/string.h>
++#include <linux/vmalloc.h>
++
++/* Use defines rather than static inline in order to avoid spurious
++ * warnings when not needed (indeed large_malloc / large_free are not
++ * needed by inflate */
++
++#define malloc(a) kmalloc(a, GFP_KERNEL)
++#define free(a) kfree(a)
++
++#define large_malloc(a) vmalloc(a)
++#define large_free(a) vfree(a)
++
++static void(*error)(char *m);
++#define set_error_fn(x) error = x;
++
++#define INIT __init
++#define STATIC
++
++#include <linux/init.h>
++
++#endif /* STATIC */
++
++#endif /* DECOMPR_MM_H */
+diff --git a/include/linux/decompress/unlzma.h
+new file mode 100644
+index 0000000..7796538
+--- /dev/null
++++ b/include/linux/decompress/unlzma.h
+@@ -0,0 +1,12 @@
++#ifndef DECOMPRESS_UNLZMA_H
++#define DECOMPRESS_UNLZMA_H
++
++int unlzma(unsigned char *, int,
++ int(*fill)(void*, unsigned int),
++ int(*flush)(void*, unsigned int),
++ unsigned char *output,
++ int *posp,
++ void(*error)(char *x)
++ );
++
++#endif
+diff --git a/lib/decompress_bunzip2.c
+new file mode 100644
+index 0000000..5d3ddb5
+--- /dev/null
++++ b/lib/decompress_bunzip2.c
+@@ -0,0 +1,735 @@
++/* vi: set sw = 4 ts = 4: */
++/* Small bzip2 deflate implementation, by Rob Landley (rob@landley.net).
++
++ Based on bzip2 decompression code by Julian R Seward (jseward@acm.org),
++ which also acknowledges contributions by Mike Burrows, David Wheeler,
++ Peter Fenwick, Alistair Moffat, Radford Neal, Ian H. Witten,
++ Robert Sedgewick, and Jon L. Bentley.
++
++ This code is licensed under the LGPLv2:
++ LGPL (http://www.gnu.org/copyleft/lgpl.html
++*/
++
++/*
++ Size and speed optimizations by Manuel Novoa III (mjn3@codepoet.org).
++
++ More efficient reading of Huffman codes, a streamlined read_bunzip()
++ function, and various other tweaks. In (limited) tests, approximately
++ 20% faster than bzcat on x86 and about 10% faster on arm.
++
++ Note that about 2/3 of the time is spent in read_unzip() reversing
++ the Burrows-Wheeler transformation. Much of that time is delay
++ resulting from cache misses.
++
++ I would ask that anyone benefiting from this work, especially those
++ using it in commercial products, consider making a donation to my local
++ non-profit hospice organization in the name of the woman I loved, who
++ passed away Feb. 12, 2003.
++
++ In memory of Toni W. Hagan
++
++ Hospice of Acadiana, Inc.
++ 2600 Johnston St., Suite 200
++ Lafayette, LA 70503-3240
++
++ Phone (337) 232-1234 or 1-800-738-2226
++ Fax (337) 232-1297
++
++ http://www.hospiceacadiana.com/
++
++ Manuel
++ */
++
++/*
++ Made it fit for running in Linux Kernel by Alain Knaff (alain@knaff.lu)
++*/
++
++
++#ifndef STATIC
++#include <linux/decompress/bunzip2.h>
++#endif /* !STATIC */
++
++#include <linux/decompress/mm.h>
++
++#ifndef INT_MAX
++#define INT_MAX 0x7fffffff
++#endif
++
++/* Constants for Huffman coding */
++#define MAX_GROUPS 6
++#define GROUP_SIZE 50 /* 64 would have been more efficient */
++#define MAX_HUFCODE_BITS 20 /* Longest Huffman code allowed */
++#define MAX_SYMBOLS 258 /* 256 literals + RUNA + RUNB */
++#define SYMBOL_RUNA 0
++#define SYMBOL_RUNB 1
++
++/* Status return values */
++#define RETVAL_OK 0
++#define RETVAL_LAST_BLOCK (-1)
++#define RETVAL_NOT_BZIP_DATA (-2)
++#define RETVAL_UNEXPECTED_INPUT_EOF (-3)
++#define RETVAL_UNEXPECTED_OUTPUT_EOF (-4)
++#define RETVAL_DATA_ERROR (-5)
++#define RETVAL_OUT_OF_MEMORY (-6)
++#define RETVAL_OBSOLETE_INPUT (-7)
++
++/* Other housekeeping constants */
++#define BZIP2_IOBUF_SIZE 4096
++
++/* This is what we know about each Huffman coding group */
++struct group_data {
++ /* We have an extra slot at the end of limit[] for a sentinal value. */
++ int limit[MAX_HUFCODE_BITS+1];
++ int base[MAX_HUFCODE_BITS];
++ int permute[MAX_SYMBOLS];
++ int minLen, maxLen;
++};
++
++/* Structure holding all the housekeeping data, including IO buffers and
++ memory that persists between calls to bunzip */
++struct bunzip_data {
++ /* State for interrupting output loop */
++ int writeCopies, writePos, writeRunCountdown, writeCount, writeCurrent;
++ /* I/O tracking data (file handles, buffers, positions, etc.) */
++ int (*fill)(void*, unsigned int);
++ int inbufCount, inbufPos /*, outbufPos*/;
++ unsigned char *inbuf /*,*outbuf*/;
++ unsigned int inbufBitCount, inbufBits;
++ /* The CRC values stored in the block header and calculated from the
++ data */
++ unsigned int crc32Table[256], headerCRC, totalCRC, writeCRC;
++ /* Intermediate buffer and its size (in bytes) */
++ unsigned int *dbuf, dbufSize;
++ /* These things are a bit too big to go on the stack */
++ unsigned char selectors[32768]; /* nSelectors = 15 bits */
++ struct group_data groups[MAX_GROUPS]; /* Huffman coding tables */
++ int io_error; /* non-zero if we have IO error */
++};
++
++
++/* Return the next nnn bits of input. All reads from the compressed input
++ are done through this function. All reads are big endian */
++static unsigned int INIT get_bits(struct bunzip_data *bd, char bits_wanted)
++{
++ unsigned int bits = 0;
++
++ /* If we need to get more data from the byte buffer, do so.
++ (Loop getting one byte at a time to enforce endianness and avoid
++ unaligned access.) */
++ while (bd->inbufBitCount < bits_wanted) {
++ /* If we need to read more data from file into byte buffer, do
++ so */
++ if (bd->inbufPos == bd->inbufCount) {
++ if (bd->io_error)
++ return 0;
++ bd->inbufCount = bd->fill(bd->inbuf, BZIP2_IOBUF_SIZE);
++ if (bd->inbufCount <= 0) {
++ bd->io_error = RETVAL_UNEXPECTED_INPUT_EOF;
++ return 0;
++ }
++ bd->inbufPos = 0;
++ }
++ /* Avoid 32-bit overflow (dump bit buffer to top of output) */
++ if (bd->inbufBitCount >= 24) {
++ bits = bd->inbufBits&((1 << bd->inbufBitCount)-1);
++ bits_wanted -= bd->inbufBitCount;
++ bits <<= bits_wanted;
++ bd->inbufBitCount = 0;
++ }
++ /* Grab next 8 bits of input from buffer. */
++ bd->inbufBits = (bd->inbufBits << 8)|bd->inbuf[bd->inbufPos++];
++ bd->inbufBitCount += 8;
++ }
++ /* Calculate result */
++ bd->inbufBitCount -= bits_wanted;
++ bits |= (bd->inbufBits >> bd->inbufBitCount)&((1 << bits_wanted)-1);
++
++ return bits;
++}
++
++/* Unpacks the next block and sets up for the inverse burrows-wheeler step. */
++
++static int INIT get_next_block(struct bunzip_data *bd)
++{
++ struct group_data *hufGroup = NULL;
++ int *base = NULL;
++ int *limit = NULL;
++ int dbufCount, nextSym, dbufSize, groupCount, selector,
++ i, j, k, t, runPos, symCount, symTotal, nSelectors,
++ byteCount[256];
++ unsigned char uc, symToByte[256], mtfSymbol[256], *selectors;
++ unsigned int *dbuf, origPtr;
++
++ dbuf = bd->dbuf;
++ dbufSize = bd->dbufSize;
++ selectors = bd->selectors;
++
++ /* Read in header signature and CRC, then validate signature.
++ (last block signature means CRC is for whole file, return now) */
++ i = get_bits(bd, 24);
++ j = get_bits(bd, 24);
++ bd->headerCRC = get_bits(bd, 32);
++ if ((i == 0x177245) && (j == 0x385090))
++ return RETVAL_LAST_BLOCK;
++ if ((i != 0x314159) || (j != 0x265359))
++ return RETVAL_NOT_BZIP_DATA;
++ /* We can add support for blockRandomised if anybody complains.
++ There was some code for this in busybox 1.0.0-pre3, but nobody ever
++ noticed that it didn't actually work. */
++ if (get_bits(bd, 1))
++ return RETVAL_OBSOLETE_INPUT;
++ origPtr = get_bits(bd, 24);
++ if (origPtr > dbufSize)
++ return RETVAL_DATA_ERROR;
++ /* mapping table: if some byte values are never used (encoding things
++ like ascii text), the compression code removes the gaps to have fewer
++ symbols to deal with, and writes a sparse bitfield indicating which
++ values were present. We make a translation table to convert the
++ symbols back to the corresponding bytes. */
++ t = get_bits(bd, 16);
++ symTotal = 0;
++ for (i = 0; i < 16; i++) {
++ if (t&(1 << (15-i))) {
++ k = get_bits(bd, 16);
++ for (j = 0; j < 16; j++)
++ if (k&(1 << (15-j)))
++ symToByte[symTotal++] = (16*i)+j;
++ }
++ }
++ /* How many different Huffman coding groups does this block use? */
++ groupCount = get_bits(bd, 3);
++ if (groupCount < 2 || groupCount > MAX_GROUPS)
++ return RETVAL_DATA_ERROR;
++ /* nSelectors: Every GROUP_SIZE many symbols we select a new
++ Huffman coding group. Read in the group selector list,
++ which is stored as MTF encoded bit runs. (MTF = Move To
++ Front, as each value is used it's moved to the start of the
++ list.) */
++ nSelectors = get_bits(bd, 15);
++ if (!nSelectors)
++ return RETVAL_DATA_ERROR;
++ for (i = 0; i < groupCount; i++)
++ mtfSymbol[i] = i;
++ for (i = 0; i < nSelectors; i++) {
++ /* Get next value */
++ for (j = 0; get_bits(bd, 1); j++)
++ if (j >= groupCount)
++ return RETVAL_DATA_ERROR;
++ /* Decode MTF to get the next selector */
++ uc = mtfSymbol[j];
++ for (; j; j--)
++ mtfSymbol[j] = mtfSymbol[j-1];
++ mtfSymbol[0] = selectors[i] = uc;
++ }
++ /* Read the Huffman coding tables for each group, which code
++ for symTotal literal symbols, plus two run symbols (RUNA,
++ RUNB) */
++ symCount = symTotal+2;
++ for (j = 0; j < groupCount; j++) {
++ unsigned char length[MAX_SYMBOLS], temp[MAX_HUFCODE_BITS+1];
++ int minLen, maxLen, pp;
++ /* Read Huffman code lengths for each symbol. They're
++ stored in a way similar to mtf; record a starting
++ value for the first symbol, and an offset from the
++ previous value for everys symbol after that.
++ (Subtracting 1 before the loop and then adding it
++ back at the end is an optimization that makes the
++ test inside the loop simpler: symbol length 0
++ becomes negative, so an unsigned inequality catches
++ it.) */
++ t = get_bits(bd, 5)-1;
++ for (i = 0; i < symCount; i++) {
++ for (;;) {
++ if (((unsigned)t) > (MAX_HUFCODE_BITS-1))
++ return RETVAL_DATA_ERROR;
++
++ /* If first bit is 0, stop. Else
++ second bit indicates whether to
++ increment or decrement the value.
++ Optimization: grab 2 bits and unget
++ the second if the first was 0. */
++
++ k = get_bits(bd, 2);
++ if (k < 2) {
++ bd->inbufBitCount++;
++ break;
++ }
++ /* Add one if second bit 1, else
++ * subtract 1. Avoids if/else */
++ t += (((k+1)&2)-1);
++ }
++ /* Correct for the initial -1, to get the
++ * final symbol length */
++ length[i] = t+1;
++ }
++ /* Find largest and smallest lengths in this group */
++ minLen = maxLen = length[0];
++
++ for (i = 1; i < symCount; i++) {
++ if (length[i] > maxLen)
++ maxLen = length[i];
++ else if (length[i] < minLen)
++ minLen = length[i];
++ }
++
++ /* Calculate permute[], base[], and limit[] tables from
++ * length[].
++ *
++ * permute[] is the lookup table for converting
++ * Huffman coded symbols into decoded symbols. base[]
++ * is the amount to subtract from the value of a
++ * Huffman symbol of a given length when using
++ * permute[].
++ *
++ * limit[] indicates the largest numerical value a
++ * symbol with a given number of bits can have. This
++ * is how the Huffman codes can vary in length: each
++ * code with a value > limit[length] needs another
++ * bit.
++ */
++ hufGroup = bd->groups+j;
++ hufGroup->minLen = minLen;
++ hufGroup->maxLen = maxLen;
++ /* Note that minLen can't be smaller than 1, so we
++ adjust the base and limit array pointers so we're
++ not always wasting the first entry. We do this
++ again when using them (during symbol decoding).*/
++ base = hufGroup->base-1;
++ limit = hufGroup->limit-1;
++ /* Calculate permute[]. Concurently, initialize
++ * temp[] and limit[]. */
++ pp = 0;
++ for (i = minLen; i <= maxLen; i++) {
++ temp[i] = limit[i] = 0;
++ for (t = 0; t < symCount; t++)
++ if (length[t] == i)
++ hufGroup->permute[pp++] = t;
++ }
++ /* Count symbols coded for at each bit length */
++ for (i = 0; i < symCount; i++)
++ temp[length[i]]++;
++ /* Calculate limit[] (the largest symbol-coding value
++ *at each bit length, which is (previous limit <<
++ *1)+symbols at this level), and base[] (number of
++ *symbols to ignore at each bit length, which is limit
++ *minus the cumulative count of symbols coded for
++ *already). */
++ pp = t = 0;
++ for (i = minLen; i < maxLen; i++) {
++ pp += temp[i];
++ /* We read the largest possible symbol size
++ and then unget bits after determining how
++ many we need, and those extra bits could be
++ set to anything. (They're noise from
++ future symbols.) At each level we're
++ really only interested in the first few
++ bits, so here we set all the trailing
++ to-be-ignored bits to 1 so they don't
++ affect the value > limit[length]
++ comparison. */
++ limit[i] = (pp << (maxLen - i)) - 1;
++ pp <<= 1;
++ base[i+1] = pp-(t += temp[i]);
++ }
++ limit[maxLen+1] = INT_MAX; /* Sentinal value for
++ * reading next sym. */
++ limit[maxLen] = pp+temp[maxLen]-1;
++ base[minLen] = 0;
++ }
++ /* We've finished reading and digesting the block header. Now
++ read this block's Huffman coded symbols from the file and
++ undo the Huffman coding and run length encoding, saving the
++ result into dbuf[dbufCount++] = uc */
++
++ /* Initialize symbol occurrence counters and symbol Move To
++ * Front table */
++ for (i = 0; i < 256; i++) {
++ byteCount[i] = 0;
++ mtfSymbol[i] = (unsigned char)i;
++ }
++ /* Loop through compressed symbols. */
++ runPos = dbufCount = symCount = selector = 0;
++ for (;;) {
++ /* Determine which Huffman coding group to use. */
++ if (!(symCount--)) {
++ symCount = GROUP_SIZE-1;
++ if (selector >= nSelectors)
++ return RETVAL_DATA_ERROR;
++ hufGroup = bd->groups+selectors[selector++];
++ base = hufGroup->base-1;
++ limit = hufGroup->limit-1;
++ }
++ /* Read next Huffman-coded symbol. */
++ /* Note: It is far cheaper to read maxLen bits and
++ back up than it is to read minLen bits and then an
++ additional bit at a time, testing as we go.
++ Because there is a trailing last block (with file
++ CRC), there is no danger of the overread causing an
++ unexpected EOF for a valid compressed file. As a
++ further optimization, we do the read inline
++ (falling back to a call to get_bits if the buffer
++ runs dry). The following (up to got_huff_bits:) is
++ equivalent to j = get_bits(bd, hufGroup->maxLen);
++ */
++ while (bd->inbufBitCount < hufGroup->maxLen) {
++ if (bd->inbufPos == bd->inbufCount) {
++ j = get_bits(bd, hufGroup->maxLen);
++ goto got_huff_bits;
++ }
++ bd->inbufBits =
++ (bd->inbufBits << 8)|bd->inbuf[bd->inbufPos++];
++ bd->inbufBitCount += 8;
++ };
++ bd->inbufBitCount -= hufGroup->maxLen;
++ j = (bd->inbufBits >> bd->inbufBitCount)&
++ ((1 << hufGroup->maxLen)-1);
++got_huff_bits:
++ /* Figure how how many bits are in next symbol and
++ * unget extras */
++ i = hufGroup->minLen;
++ while (j > limit[i])
++ ++i;
++ bd->inbufBitCount += (hufGroup->maxLen - i);
++ /* Huffman decode value to get nextSym (with bounds checking) */
++ if ((i > hufGroup->maxLen)
++ || (((unsigned)(j = (j>>(hufGroup->maxLen-i))-base[i]))
++ >= MAX_SYMBOLS))
++ return RETVAL_DATA_ERROR;
++ nextSym = hufGroup->permute[j];
++ /* We have now decoded the symbol, which indicates
++ either a new literal byte, or a repeated run of the
++ most recent literal byte. First, check if nextSym
++ indicates a repeated run, and if so loop collecting
++ how many times to repeat the last literal. */
++ if (((unsigned)nextSym) <= SYMBOL_RUNB) { /* RUNA or RUNB */
++ /* If this is the start of a new run, zero out
++ * counter */
++ if (!runPos) {
++ runPos = 1;
++ t = 0;
++ }
++ /* Neat trick that saves 1 symbol: instead of
++ or-ing 0 or 1 at each bit position, add 1
++ or 2 instead. For example, 1011 is 1 << 0
++ + 1 << 1 + 2 << 2. 1010 is 2 << 0 + 2 << 1
++ + 1 << 2. You can make any bit pattern
++ that way using 1 less symbol than the basic
++ or 0/1 method (except all bits 0, which
++ would use no symbols, but a run of length 0
++ doesn't mean anything in this context).
++ Thus space is saved. */
++ t += (runPos << nextSym);
++ /* +runPos if RUNA; +2*runPos if RUNB */
++
++ runPos <<= 1;
++ continue;
++ }
++ /* When we hit the first non-run symbol after a run,
++ we now know how many times to repeat the last
++ literal, so append that many copies to our buffer
++ of decoded symbols (dbuf) now. (The last literal
++ used is the one at the head of the mtfSymbol
++ array.) */
++ if (runPos) {
++ runPos = 0;
++ if (dbufCount+t >= dbufSize)
++ return RETVAL_DATA_ERROR;
++
++ uc = symToByte[mtfSymbol[0]];
++ byteCount[uc] += t;
++ while (t--)
++ dbuf[dbufCount++] = uc;
++ }
++ /* Is this the terminating symbol? */
++ if (nextSym > symTotal)
++ break;
++ /* At this point, nextSym indicates a new literal
++ character. Subtract one to get the position in the
++ MTF array at which this literal is currently to be
++ found. (Note that the result can't be -1 or 0,
++ because 0 and 1 are RUNA and RUNB. But another
++ instance of the first symbol in the mtf array,
++ position 0, would have been handled as part of a
++ run above. Therefore 1 unused mtf position minus 2
++ non-literal nextSym values equals -1.) */
++ if (dbufCount >= dbufSize)
++ return RETVAL_DATA_ERROR;
++ i = nextSym - 1;
++ uc = mtfSymbol[i];
++ /* Adjust the MTF array. Since we typically expect to
++ *move only a small number of symbols, and are bound
++ *by 256 in any case, using memmove here would
++ *typically be bigger and slower due to function call
++ *overhead and other assorted setup costs. */
++ do {
++ mtfSymbol[i] = mtfSymbol[i-1];
++ } while (--i);
++ mtfSymbol[0] = uc;
++ uc = symToByte[uc];
++ /* We have our literal byte. Save it into dbuf. */
++ byteCount[uc]++;
++ dbuf[dbufCount++] = (unsigned int)uc;
++ }
++ /* At this point, we've read all the Huffman-coded symbols
++ (and repeated runs) for this block from the input stream,
++ and decoded them into the intermediate buffer. There are
++ dbufCount many decoded bytes in dbuf[]. Now undo the
++ Burrows-Wheeler transform on dbuf. See
++ http://dogma.net/markn/articles/bwt/bwt.htm
++ */
++ /* Turn byteCount into cumulative occurrence counts of 0 to n-1. */
++ j = 0;
++ for (i = 0; i < 256; i++) {
++ k = j+byteCount[i];
++ byteCount[i] = j;
++ j = k;
++ }
++ /* Figure out what order dbuf would be in if we sorted it. */
++ for (i = 0; i < dbufCount; i++) {
++ uc = (unsigned char)(dbuf[i] & 0xff);
++ dbuf[byteCount[uc]] |= (i << 8);
++ byteCount[uc]++;
++ }
++ /* Decode first byte by hand to initialize "previous" byte.
++ Note that it doesn't get output, and if the first three
++ characters are identical it doesn't qualify as a run (hence
++ writeRunCountdown = 5). */
++ if (dbufCount) {
++ if (origPtr >= dbufCount)
++ return RETVAL_DATA_ERROR;
++ bd->writePos = dbuf[origPtr];
++ bd->writeCurrent = (unsigned char)(bd->writePos&0xff);
++ bd->writePos >>= 8;
++ bd->writeRunCountdown = 5;
++ }
++ bd->writeCount = dbufCount;
++
++ return RETVAL_OK;
++}
++
++/* Undo burrows-wheeler transform on intermediate buffer to produce output.
++ If start_bunzip was initialized with out_fd =-1, then up to len bytes of
++ data are written to outbuf. Return value is number of bytes written or
++ error (all errors are negative numbers). If out_fd!=-1, outbuf and len
++ are ignored, data is written to out_fd and return is RETVAL_OK or error.
++*/
++
++static int INIT read_bunzip(struct bunzip_data *bd, char *outbuf, int len)
++{
++ const unsigned int *dbuf;
++ int pos, xcurrent, previous, gotcount;
++
++ /* If last read was short due to end of file, return last block now */
++ if (bd->writeCount < 0)
++ return bd->writeCount;
++
++ gotcount = 0;
++ dbuf = bd->dbuf;
++ pos = bd->writePos;
++ xcurrent = bd->writeCurrent;
++
++ /* We will always have pending decoded data to write into the output
++ buffer unless this is the very first call (in which case we haven't
++ Huffman-decoded a block into the intermediate buffer yet). */
++
++ if (bd->writeCopies) {
++ /* Inside the loop, writeCopies means extra copies (beyond 1) */
++ --bd->writeCopies;
++ /* Loop outputting bytes */
++ for (;;) {
++ /* If the output buffer is full, snapshot
++ * state and return */
++ if (gotcount >= len) {
++ bd->writePos = pos;
++ bd->writeCurrent = xcurrent;
++ bd->writeCopies++;
++ return len;
++ }
++ /* Write next byte into output buffer, updating CRC */
++ outbuf[gotcount++] = xcurrent;
++ bd->writeCRC = (((bd->writeCRC) << 8)
++ ^bd->crc32Table[((bd->writeCRC) >> 24)
++ ^xcurrent]);
++ /* Loop now if we're outputting multiple
++ * copies of this byte */
++ if (bd->writeCopies) {
++ --bd->writeCopies;
++ continue;
++ }
++decode_next_byte:
++ if (!bd->writeCount--)
++ break;
++ /* Follow sequence vector to undo
++ * Burrows-Wheeler transform */
++ previous = xcurrent;
++ pos = dbuf[pos];
++ xcurrent = pos&0xff;
++ pos >>= 8;
++ /* After 3 consecutive copies of the same
++ byte, the 4th is a repeat count. We count
++ down from 4 instead *of counting up because
++ testing for non-zero is faster */
++ if (--bd->writeRunCountdown) {
++ if (xcurrent != previous)
++ bd->writeRunCountdown = 4;
++ } else {
++ /* We have a repeated run, this byte
++ * indicates the count */
++ bd->writeCopies = xcurrent;
++ xcurrent = previous;
++ bd->writeRunCountdown = 5;
++ /* Sometimes there are just 3 bytes
++ * (run length 0) */
++ if (!bd->writeCopies)
++ goto decode_next_byte;
++ /* Subtract the 1 copy we'd output
++ * anyway to get extras */
++ --bd->writeCopies;
++ }
++ }
++ /* Decompression of this block completed successfully */
++ bd->writeCRC = ~bd->writeCRC;
++ bd->totalCRC = ((bd->totalCRC << 1) |
++ (bd->totalCRC >> 31)) ^ bd->writeCRC;
++ /* If this block had a CRC error, force file level CRC error. */
++ if (bd->writeCRC != bd->headerCRC) {
++ bd->totalCRC = bd->headerCRC+1;
++ return RETVAL_LAST_BLOCK;
++ }
++ }
++
++ /* Refill the intermediate buffer by Huffman-decoding next
++ * block of input */
++ /* (previous is just a convenient unused temp variable here) */
++ previous = get_next_block(bd);
++ if (previous) {
++ bd->writeCount = previous;
++ return (previous != RETVAL_LAST_BLOCK) ? previous : gotcount;
++ }
++ bd->writeCRC = 0xffffffffUL;
++ pos = bd->writePos;
++ xcurrent = bd->writeCurrent;
++ goto decode_next_byte;
++}
++
++static int INIT nofill(void *buf, unsigned int len)
++{
++ return -1;
++}
++
++/* Allocate the structure, read file header. If in_fd ==-1, inbuf must contain
++ a complete bunzip file (len bytes long). If in_fd!=-1, inbuf and len are
++ ignored, and data is read from file handle into temporary buffer. */
++static int INIT start_bunzip(struct bunzip_data **bdp, void *inbuf, int len,
++ int (*fill)(void*, unsigned int))
++{
++ struct bunzip_data *bd;
++ unsigned int i, j, c;
++ const unsigned int BZh0 =
++ (((unsigned int)'B') << 24)+(((unsigned int)'Z') << 16)
++ +(((unsigned int)'h') << 8)+(unsigned int)'0';
++
++ /* Figure out how much data to allocate */
++ i = sizeof(struct bunzip_data);
++
++ /* Allocate bunzip_data. Most fields initialize to zero. */
++ bd = *bdp = malloc(i);
++ memset(bd, 0, sizeof(struct bunzip_data));
++ /* Setup input buffer */
++ bd->inbuf = inbuf;
++ bd->inbufCount = len;
++ if (fill != NULL)
++ bd->fill = fill;
++ else
++ bd->fill = nofill;
++
++ /* Init the CRC32 table (big endian) */
++ for (i = 0; i < 256; i++) {
++ c = i << 24;
++ for (j = 8; j; j--)
++ c = c&0x80000000 ? (c << 1)^0x04c11db7 : (c << 1);
++ bd->crc32Table[i] = c;
++ }
++
++ /* Ensure that file starts with "BZh['1'-'9']." */
++ i = get_bits(bd, 32);
++ if (((unsigned int)(i-BZh0-1)) >= 9)
++ return RETVAL_NOT_BZIP_DATA;
++
++ /* Fourth byte (ascii '1'-'9'), indicates block size in units of 100k of
++ uncompressed data. Allocate intermediate buffer for block. */
++ bd->dbufSize = 100000*(i-BZh0);
++
++ bd->dbuf = large_malloc(bd->dbufSize * sizeof(int));
++ return RETVAL_OK;
++}
++
++/* Example usage: decompress src_fd to dst_fd. (Stops at end of bzip2 data,
++ not end of file.) */
++STATIC int INIT bunzip2(unsigned char *buf, int len,
++ int(*fill)(void*, unsigned int),
++ int(*flush)(void*, unsigned int),
++ unsigned char *outbuf,
++ int *pos,
++ void(*error_fn)(char *x))
++{
++ struct bunzip_data *bd;
++ int i = -1;
++ unsigned char *inbuf;
++
++ set_error_fn(error_fn);
++ if (flush)
++ outbuf = malloc(BZIP2_IOBUF_SIZE);
++ else
++ len -= 4; /* Uncompressed size hack active in pre-boot
++ environment */
++ if (!outbuf) {
++ error("Could not allocate output bufer");
++ return -1;
++ }
++ if (buf)
++ inbuf = buf;
++ else
++ inbuf = malloc(BZIP2_IOBUF_SIZE);
++ if (!inbuf) {
++ error("Could not allocate input bufer");
++ goto exit_0;
++ }
++ i = start_bunzip(&bd, inbuf, len, fill);
++ if (!i) {
++ for (;;) {
++ i = read_bunzip(bd, outbuf, BZIP2_IOBUF_SIZE);
++ if (i <= 0)
++ break;
++ if (!flush)
++ outbuf += i;
++ else
++ if (i != flush(outbuf, i)) {
++ i = RETVAL_UNEXPECTED_OUTPUT_EOF;
++ break;
++ }
++ }
++ }
++ /* Check CRC and release memory */
++ if (i == RETVAL_LAST_BLOCK) {
++ if (bd->headerCRC != bd->totalCRC)
++ error("Data integrity error when decompressing.");
++ else
++ i = RETVAL_OK;
++ } else if (i == RETVAL_UNEXPECTED_OUTPUT_EOF) {
++ error("Compressed file ends unexpectedly");
++ }
++ if (bd->dbuf)
++ large_free(bd->dbuf);
++ if (pos)
++ *pos = bd->inbufPos;
++ free(bd);
++ if (!buf)
++ free(inbuf);
++exit_0:
++ if (flush)
++ free(outbuf);
++ return i;
++}
++
++#define decompress bunzip2
+diff --git a/lib/decompress_inflate.c
+new file mode 100644
+index 0000000..163e66a
+--- /dev/null
++++ b/lib/decompress_inflate.c
+@@ -0,0 +1,167 @@
++#ifdef STATIC
++/* Pre-boot environment: included */
++
++/* prevent inclusion of _LINUX_KERNEL_H in pre-boot environment: lots
++ * errors about console_printk etc... on ARM */
++#define _LINUX_KERNEL_H
++
++#include "zlib_inflate/inftrees.c"
++#include "zlib_inflate/inffast.c"
++#include "zlib_inflate/inflate.c"
++
++#else /* STATIC */
++/* initramfs et al: linked */
++
++#include <linux/zutil.h>
++
++#include "zlib_inflate/inftrees.h"
++#include "zlib_inflate/inffast.h"
++#include "zlib_inflate/inflate.h"
++
++#include "zlib_inflate/infutil.h"
++
++#endif /* STATIC */
++
++#include <linux/decompress/mm.h>
++
++#define INBUF_LEN (16*1024)
++
++/* Included from initramfs et al code */
++STATIC int INIT gunzip(unsigned char *buf, int len,
++ int(*fill)(void*, unsigned int),
++ int(*flush)(void*, unsigned int),
++ unsigned char *out_buf,
++ int *pos,
++ void(*error_fn)(char *x)) {
++ u8 *zbuf;
++ struct z_stream_s *strm;
++ int rc;
++ size_t out_len;
++
++ set_error_fn(error_fn);
++ rc = -1;
++ if (flush) {
++ out_len = 0x8100; /* 32 K */
++ out_buf = malloc(out_len);
++ } else {
++ out_len = 0x7fffffff; /* no limit */
++ }
++ if (!out_buf) {
++ error("Out of memory while allocating output buffer");
++ goto gunzip_nomem1;
++ }
++
++ if (buf)
++ zbuf = buf;
++ else {
++ zbuf = malloc(INBUF_LEN);
++ len = 0;
++ }
++ if (!zbuf) {
++ error("Out of memory while allocating input buffer");
++ goto gunzip_nomem2;
++ }
++
++ strm = malloc(sizeof(*strm));
++ if (strm == NULL) {
++ error("Out of memory while allocating z_stream");
++ goto gunzip_nomem3;
++ }
++
++ strm->workspace = malloc(flush ? zlib_inflate_workspacesize() :
++ sizeof(struct inflate_state));
++ if (strm->workspace == NULL) {
++ error("Out of memory while allocating workspace");
++ goto gunzip_nomem4;
++ }
++
++ if (len == 0)
++ len = fill(zbuf, INBUF_LEN);
++
++ /* verify the gzip header */
++ if (len < 10 ||
++ zbuf[0] != 0x1f || zbuf[1] != 0x8b || zbuf[2] != 0x08) {
++ if (pos)
++ *pos = 0;
++ error("Not a gzip file");
++ goto gunzip_5;
++ }
++
++ /* skip over gzip header (1f,8b,08... 10 bytes total +
++ * possible asciz filename)
++ */
++ strm->next_in = zbuf + 10;
++ /* skip over asciz filename */
++ if (zbuf[3] & 0x8) {
++ while (strm->next_in[0])
++ strm->next_in++;
++ strm->next_in++;
++ }
++ strm->avail_in = len - 10;
++
++ strm->next_out = out_buf;
++ strm->avail_out = out_len;
++
++ rc = zlib_inflateInit2(strm, -MAX_WBITS);
++
++ if (!flush) {
++ WS(strm)->inflate_state.wsize = 0;
++ WS(strm)->inflate_state.window = NULL;
++ }
++
++ while (rc == Z_OK) {
++ if (strm->avail_in == 0) {
++ /* TODO: handle case where both pos and fill are set */
++ len = fill(zbuf, INBUF_LEN);
++ if (len < 0) {
++ rc = -1;
++ error("read error");
++ break;
++ }
++ strm->next_in = zbuf;
++ strm->avail_in = len;
++ }
++ rc = zlib_inflate(strm, 0);
++
++ /* Write any data generated */
++ if (flush && strm->next_out > out_buf) {
++ int l = strm->next_out - out_buf;
++ if (l != flush(out_buf, l)) {
++ rc = -1;
++ error("write error");
++ break;
++ }
++ strm->next_out = out_buf;
++ strm->avail_out = out_len;
++ }
++
++ /* after Z_FINISH, only Z_STREAM_END is "we unpacked it all" */
++ if (rc == Z_STREAM_END) {
++ rc = 0;
++ break;
++ } else if (rc != Z_OK) {
++ error("uncompression error");
++ rc = -1;
++ }
++ }
++
++ zlib_inflateEnd(strm);
++ if (pos)
++ /* add + 8 to skip over trailer */
++ *pos = strm->next_in - zbuf+8;
++
++gunzip_5:
++ free(strm->workspace);
++gunzip_nomem4:
++ free(strm);
++gunzip_nomem3:
++ if (!buf)
++ free(zbuf);
++gunzip_nomem2:
++ if (flush)
++ free(out_buf);
++gunzip_nomem1:
++ return rc; /* returns Z_OK (0) if successful */
++}
++
++#define decompress gunzip
+diff --git a/lib/decompress_unlzma.c
+new file mode 100644
+index 0000000..546f2f4
+--- /dev/null
++++ b/lib/decompress_unlzma.c
+@@ -0,0 +1,647 @@
++/* Lzma decompressor for Linux kernel. Shamelessly snarfed
++ *from busybox 1.1.1
++ *
++ *Linux kernel adaptation
++ *Copyright (C) 2006 Alain < alain@knaff.lu >
++ *
++ *Based on small lzma deflate implementation/Small range coder
++ *implementation for lzma.
++ *Copyright (C) 2006 Aurelien Jacobs < aurel@gnuage.org >
++ *
++ *Based on LzmaDecode.c from the LZMA SDK 4.22 (http://www.7-zip.org/)
++ *Copyright (C) 1999-2005 Igor Pavlov
++ *
++ *Copyrights of the parts, see headers below.
++ *
++ *
++ *This program is free software; you can redistribute it and/or
++ *modify it under the terms of the GNU Lesser General Public
++ *License as published by the Free Software Foundation; either
++ *version 2.1 of the License, or (at your option) any later version.
++ *
++ *This program is distributed in the hope that it will be useful,
++ *but WITHOUT ANY WARRANTY; without even the implied warranty of
++ *MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ *Lesser General Public License for more details.
++ *
++ *You should have received a copy of the GNU Lesser General Public
++ *License along with this library; if not, write to the Free Software
++ *Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ */
++
++#ifndef STATIC
++#include <linux/decompress/unlzma.h>
++#endif /* STATIC */
++
++#include <linux/decompress/mm.h>
++
++#define MIN(a, b) (((a) < (b)) ? (a) : (b))
++
++static long long INIT read_int(unsigned char *ptr, int size)
++{
++ int i;
++ long long ret = 0;
++
++ for (i = 0; i < size; i++)
++ ret = (ret << 8) | ptr[size-i-1];
++ return ret;
++}
++
++#define ENDIAN_CONVERT(x) \
++ x = (typeof(x))read_int((unsigned char *)&x, sizeof(x))
++
++
++/* Small range coder implementation for lzma.
++ *Copyright (C) 2006 Aurelien Jacobs < aurel@gnuage.org >
++ *
++ *Based on LzmaDecode.c from the LZMA SDK 4.22 (http://www.7-zip.org/)
++ *Copyright (c) 1999-2005 Igor Pavlov
++ */
++
++#include <linux/compiler.h>
++
++#define LZMA_IOBUF_SIZE 0x10000
++
++struct rc {
++ int (*fill)(void*, unsigned int);
++ uint8_t *ptr;
++ uint8_t *buffer;
++ uint8_t *buffer_end;
++ int buffer_size;
++ uint32_t code;
++ uint32_t range;
++ uint32_t bound;
++};
++
++
++#define RC_TOP_BITS 24
++#define RC_MOVE_BITS 5
++#define RC_MODEL_TOTAL_BITS 11
++
++
++/* Called twice: once at startup and once in rc_normalize() */
++static void INIT rc_read(struct rc *rc)
++{
++ rc->buffer_size = rc->fill((char *)rc->buffer, LZMA_IOBUF_SIZE);
++ if (rc->buffer_size <= 0)
++ error("unexpected EOF");
++ rc->ptr = rc->buffer;
++ rc->buffer_end = rc->buffer + rc->buffer_size;
++}
++
++/* Called once */
++static inline void INIT rc_init(struct rc *rc,
++ int (*fill)(void*, unsigned int),
++ char *buffer, int buffer_size)
++{
++ rc->fill = fill;
++ rc->buffer = (uint8_t *)buffer;
++ rc->buffer_size = buffer_size;
++ rc->buffer_end = rc->buffer + rc->buffer_size;
++ rc->ptr = rc->buffer;
++
++ rc->code = 0;
++ rc->range = 0xFFFFFFFF;
++}
++
++static inline void INIT rc_init_code(struct rc *rc)
++{
++ int i;
++
++ for (i = 0; i < 5; i++) {
++ if (rc->ptr >= rc->buffer_end)
++ rc_read(rc);
++ rc->code = (rc->code << 8) | *rc->ptr++;
++ }
++}
++
++
++/* Called once. TODO: bb_maybe_free() */
++static inline void INIT rc_free(struct rc *rc)
++{
++ free(rc->buffer);
++}
++
++/* Called twice, but one callsite is in inline'd rc_is_bit_0_helper() */
++static void INIT rc_do_normalize(struct rc *rc)
++{
++ if (rc->ptr >= rc->buffer_end)
++ rc_read(rc);
++ rc->range <<= 8;
++ rc->code = (rc->code << 8) | *rc->ptr++;
++}
++static inline void INIT rc_normalize(struct rc *rc)
++{
++ if (rc->range < (1 << RC_TOP_BITS))
++ rc_do_normalize(rc);
++}
++
++/* Called 9 times */
++/* Why rc_is_bit_0_helper exists?
++ *Because we want to always expose (rc->code < rc->bound) to optimizer
++ */
++static inline uint32_t INIT rc_is_bit_0_helper(struct rc *rc, uint16_t *p)
++{
++ rc_normalize(rc);
++ rc->bound = *p * (rc->range >> RC_MODEL_TOTAL_BITS);
++ return rc->bound;
++}
++static inline int INIT rc_is_bit_0(struct rc *rc, uint16_t *p)
++{
++ uint32_t t = rc_is_bit_0_helper(rc, p);
++ return rc->code < t;
++}
++
++/* Called ~10 times, but very small, thus inlined */
++static inline void INIT rc_update_bit_0(struct rc *rc, uint16_t *p)
++{
++ rc->range = rc->bound;
++ *p += ((1 << RC_MODEL_TOTAL_BITS) - *p) >> RC_MOVE_BITS;
++}
++static inline void rc_update_bit_1(struct rc *rc, uint16_t *p)
++{
++ rc->range -= rc->bound;
++ rc->code -= rc->bound;
++ *p -= *p >> RC_MOVE_BITS;
++}
++
++/* Called 4 times in unlzma loop */
++static int INIT rc_get_bit(struct rc *rc, uint16_t *p, int *symbol)
++{
++ if (rc_is_bit_0(rc, p)) {
++ rc_update_bit_0(rc, p);
++ *symbol *= 2;
++ return 0;
++ } else {
++ rc_update_bit_1(rc, p);
++ *symbol = *symbol * 2 + 1;
++ return 1;
++ }
++}
++
++/* Called once */
++static inline int INIT rc_direct_bit(struct rc *rc)
++{
++ rc_normalize(rc);
++ rc->range >>= 1;
++ if (rc->code >= rc->range) {
++ rc->code -= rc->range;
++ return 1;
++ }
++ return 0;
++}
++
++/* Called twice */
++static inline void INIT
++rc_bit_tree_decode(struct rc *rc, uint16_t *p, int num_levels, int *symbol)
++{
++ int i = num_levels;
++
++ *symbol = 1;
++ while (i--)
++ rc_get_bit(rc, p + *symbol, symbol);
++ *symbol -= 1 << num_levels;
++}
++
++
++/*
++ * Small lzma deflate implementation.
++ * Copyright (C) 2006 Aurelien Jacobs < aurel@gnuage.org >
++ *
++ * Based on LzmaDecode.c from the LZMA SDK 4.22 (http://www.7-zip.org/)
++ * Copyright (C) 1999-2005 Igor Pavlov
++ */
++
++
++struct lzma_header {
++ uint8_t pos;
++ uint32_t dict_size;
++ uint64_t dst_size;
++} __attribute__ ((packed)) ;
++
++
++#define LZMA_BASE_SIZE 1846
++#define LZMA_LIT_SIZE 768
++
++#define LZMA_NUM_POS_BITS_MAX 4
++
++#define LZMA_LEN_NUM_LOW_BITS 3
++#define LZMA_LEN_NUM_MID_BITS 3
++#define LZMA_LEN_NUM_HIGH_BITS 8
++
++#define LZMA_LEN_CHOICE 0
++#define LZMA_LEN_CHOICE_2 (LZMA_LEN_CHOICE + 1)
++#define LZMA_LEN_LOW (LZMA_LEN_CHOICE_2 + 1)
++#define LZMA_LEN_MID (LZMA_LEN_LOW \
++ + (1 << (LZMA_NUM_POS_BITS_MAX + LZMA_LEN_NUM_LOW_BITS)))
++#define LZMA_LEN_HIGH (LZMA_LEN_MID \
++ +(1 << (LZMA_NUM_POS_BITS_MAX + LZMA_LEN_NUM_MID_BITS)))
++#define LZMA_NUM_LEN_PROBS (LZMA_LEN_HIGH + (1 << LZMA_LEN_NUM_HIGH_BITS))
++
++#define LZMA_NUM_STATES 12
++#define LZMA_NUM_LIT_STATES 7
++
++#define LZMA_START_POS_MODEL_INDEX 4
++#define LZMA_END_POS_MODEL_INDEX 14
++#define LZMA_NUM_FULL_DISTANCES (1 << (LZMA_END_POS_MODEL_INDEX >> 1))
++
++#define LZMA_NUM_POS_SLOT_BITS 6
++#define LZMA_NUM_LEN_TO_POS_STATES 4
++
++#define LZMA_NUM_ALIGN_BITS 4
++
++#define LZMA_MATCH_MIN_LEN 2
++
++#define LZMA_IS_MATCH 0
++#define LZMA_IS_REP (LZMA_IS_MATCH + (LZMA_NUM_STATES << LZMA_NUM_POS_BITS_MAX))
++#define LZMA_IS_REP_G0 (LZMA_IS_REP + LZMA_NUM_STATES)
++#define LZMA_IS_REP_G1 (LZMA_IS_REP_G0 + LZMA_NUM_STATES)
++#define LZMA_IS_REP_G2 (LZMA_IS_REP_G1 + LZMA_NUM_STATES)
++#define LZMA_IS_REP_0_LONG (LZMA_IS_REP_G2 + LZMA_NUM_STATES)
++#define LZMA_POS_SLOT (LZMA_IS_REP_0_LONG \
++ + (LZMA_NUM_STATES << LZMA_NUM_POS_BITS_MAX))
++#define LZMA_SPEC_POS (LZMA_POS_SLOT \
++ +(LZMA_NUM_LEN_TO_POS_STATES << LZMA_NUM_POS_SLOT_BITS))
++#define LZMA_ALIGN (LZMA_SPEC_POS \
++ + LZMA_NUM_FULL_DISTANCES - LZMA_END_POS_MODEL_INDEX)
++#define LZMA_LEN_CODER (LZMA_ALIGN + (1 << LZMA_NUM_ALIGN_BITS))
++#define LZMA_REP_LEN_CODER (LZMA_LEN_CODER + LZMA_NUM_LEN_PROBS)
++#define LZMA_LITERAL (LZMA_REP_LEN_CODER + LZMA_NUM_LEN_PROBS)
++
++
++struct writer {
++ uint8_t *buffer;
++ uint8_t previous_byte;
++ size_t buffer_pos;
++ int bufsize;
++ size_t global_pos;
++ int(*flush)(void*, unsigned int);
++ struct lzma_header *header;
++};
++
++struct cstate {
++ int state;
++ uint32_t rep0, rep1, rep2, rep3;
++};
++
++static inline size_t INIT get_pos(struct writer *wr)
++{
++ return
++ wr->global_pos + wr->buffer_pos;
++}
++
++static inline uint8_t INIT peek_old_byte(struct writer *wr,
++ uint32_t offs)
++{
++ if (!wr->flush) {
++ int32_t pos;
++ while (offs > wr->header->dict_size)
++ offs -= wr->header->dict_size;
++ pos = wr->buffer_pos - offs;
++ return wr->buffer[pos];
++ } else {
++ uint32_t pos = wr->buffer_pos - offs;
++ while (pos >= wr->header->dict_size)
++ pos += wr->header->dict_size;
++ return wr->buffer[pos];
++ }
++
++}
++
++static inline void INIT write_byte(struct writer *wr, uint8_t byte)
++{
++ wr->buffer[wr->buffer_pos++] = wr->previous_byte = byte;
++ if (wr->flush && wr->buffer_pos == wr->header->dict_size) {
++ wr->buffer_pos = 0;
++ wr->global_pos += wr->header->dict_size;
++ wr->flush((char *)wr->buffer, wr->header->dict_size);
++ }
++}
++
++
++static inline void INIT copy_byte(struct writer *wr, uint32_t offs)
++{
++ write_byte(wr, peek_old_byte(wr, offs));
++}
++
++static inline void INIT copy_bytes(struct writer *wr,
++ uint32_t rep0, int len)
++{
++ do {
++ copy_byte(wr, rep0);
++ len--;
++ } while (len != 0 && wr->buffer_pos < wr->header->dst_size);
++}
++
++static inline void INIT process_bit0(struct writer *wr, struct rc *rc,
++ struct cstate *cst, uint16_t *p,
++ int pos_state, uint16_t *prob,
++ int lc, uint32_t literal_pos_mask) {
++ int mi = 1;
++ rc_update_bit_0(rc, prob);
++ prob = (p + LZMA_LITERAL +
++ (LZMA_LIT_SIZE
++ * (((get_pos(wr) & literal_pos_mask) << lc)
++ + (wr->previous_byte >> (8 - lc))))
++ );
++
++ if (cst->state >= LZMA_NUM_LIT_STATES) {
++ int match_byte = peek_old_byte(wr, cst->rep0);
++ do {
++ int bit;
++ uint16_t *prob_lit;
++
++ match_byte <<= 1;
++ bit = match_byte & 0x100;
++ prob_lit = prob + 0x100 + bit + mi;
++ if (rc_get_bit(rc, prob_lit, &mi)) {
++ if (!bit)
++ break;
++ } else {
++ if (bit)
++ break;
++ }
++ } while (mi < 0x100);
++ }
++ while (mi < 0x100) {
++ uint16_t *prob_lit = prob + mi;
++ rc_get_bit(rc, prob_lit, &mi);
++ }
++ write_byte(wr, mi);
++ if (cst->state < 4)
++ cst->state = 0;
++ else if (cst->state < 10)
++ cst->state -= 3;
++ else
++ cst->state -= 6;
++}
++
++static inline void INIT process_bit1(struct writer *wr, struct rc *rc,
++ struct cstate *cst, uint16_t *p,
++ int pos_state, uint16_t *prob) {
++ int offset;
++ uint16_t *prob_len;
++ int num_bits;
++ int len;
++
++ rc_update_bit_1(rc, prob);
++ prob = p + LZMA_IS_REP + cst->state;
++ if (rc_is_bit_0(rc, prob)) {
++ rc_update_bit_0(rc, prob);
++ cst->rep3 = cst->rep2;
++ cst->rep2 = cst->rep1;
++ cst->rep1 = cst->rep0;
++ cst->state = cst->state < LZMA_NUM_LIT_STATES ? 0 : 3;
++ prob = p + LZMA_LEN_CODER;
++ } else {
++ rc_update_bit_1(rc, prob);
++ prob = p + LZMA_IS_REP_G0 + cst->state;
++ if (rc_is_bit_0(rc, prob)) {
++ rc_update_bit_0(rc, prob);
++ prob = (p + LZMA_IS_REP_0_LONG
++ + (cst->state <<
++ LZMA_NUM_POS_BITS_MAX) +
++ pos_state);
++ if (rc_is_bit_0(rc, prob)) {
++ rc_update_bit_0(rc, prob);
++
++ cst->state = cst->state < LZMA_NUM_LIT_STATES ?
++ 9 : 11;
++ copy_byte(wr, cst->rep0);
++ return;
++ } else {
++ rc_update_bit_1(rc, prob);
++ }
++ } else {
++ uint32_t distance;
++
++ rc_update_bit_1(rc, prob);
++ prob = p + LZMA_IS_REP_G1 + cst->state;
++ if (rc_is_bit_0(rc, prob)) {
++ rc_update_bit_0(rc, prob);
++ distance = cst->rep1;
++ } else {
++ rc_update_bit_1(rc, prob);
++ prob = p + LZMA_IS_REP_G2 + cst->state;
++ if (rc_is_bit_0(rc, prob)) {
++ rc_update_bit_0(rc, prob);
++ distance = cst->rep2;
++ } else {
++ rc_update_bit_1(rc, prob);
++ distance = cst->rep3;
++ cst->rep3 = cst->rep2;
++ }
++ cst->rep2 = cst->rep1;
++ }
++ cst->rep1 = cst->rep0;
++ cst->rep0 = distance;
++ }
++ cst->state = cst->state < LZMA_NUM_LIT_STATES ? 8 : 11;
++ prob = p + LZMA_REP_LEN_CODER;
++ }
++
++ prob_len = prob + LZMA_LEN_CHOICE;
++ if (rc_is_bit_0(rc, prob_len)) {
++ rc_update_bit_0(rc, prob_len);
++ prob_len = (prob + LZMA_LEN_LOW
++ + (pos_state <<
++ LZMA_LEN_NUM_LOW_BITS));
++ offset = 0;
++ num_bits = LZMA_LEN_NUM_LOW_BITS;
++ } else {
++ rc_update_bit_1(rc, prob_len);
++ prob_len = prob + LZMA_LEN_CHOICE_2;
++ if (rc_is_bit_0(rc, prob_len)) {
++ rc_update_bit_0(rc, prob_len);
++ prob_len = (prob + LZMA_LEN_MID
++ + (pos_state <<
++ LZMA_LEN_NUM_MID_BITS));
++ offset = 1 << LZMA_LEN_NUM_LOW_BITS;
++ num_bits = LZMA_LEN_NUM_MID_BITS;
++ } else {
++ rc_update_bit_1(rc, prob_len);
++ prob_len = prob + LZMA_LEN_HIGH;
++ offset = ((1 << LZMA_LEN_NUM_LOW_BITS)
++ + (1 << LZMA_LEN_NUM_MID_BITS));
++ num_bits = LZMA_LEN_NUM_HIGH_BITS;
++ }
++ }
++
++ rc_bit_tree_decode(rc, prob_len, num_bits, &len);
++ len += offset;
++
++ if (cst->state < 4) {
++ int pos_slot;
++
++ cst->state += LZMA_NUM_LIT_STATES;
++ prob =
++ p + LZMA_POS_SLOT +
++ ((len <
++ LZMA_NUM_LEN_TO_POS_STATES ? len :
++ LZMA_NUM_LEN_TO_POS_STATES - 1)
++ << LZMA_NUM_POS_SLOT_BITS);
++ rc_bit_tree_decode(rc, prob,
++ LZMA_NUM_POS_SLOT_BITS,
++ &pos_slot);
++ if (pos_slot >= LZMA_START_POS_MODEL_INDEX) {
++ int i, mi;
++ num_bits = (pos_slot >> 1) - 1;
++ cst->rep0 = 2 | (pos_slot & 1);
++ if (pos_slot < LZMA_END_POS_MODEL_INDEX) {
++ cst->rep0 <<= num_bits;
++ prob = p + LZMA_SPEC_POS +
++ cst->rep0 - pos_slot - 1;
++ } else {
++ num_bits -= LZMA_NUM_ALIGN_BITS;
++ while (num_bits--)
++ cst->rep0 = (cst->rep0 << 1) |
++ rc_direct_bit(rc);
++ prob = p + LZMA_ALIGN;
++ cst->rep0 <<= LZMA_NUM_ALIGN_BITS;
++ num_bits = LZMA_NUM_ALIGN_BITS;
++ }
++ i = 1;
++ mi = 1;
++ while (num_bits--) {
++ if (rc_get_bit(rc, prob + mi, &mi))
++ cst->rep0 |= i;
++ i <<= 1;
++ }
++ } else
++ cst->rep0 = pos_slot;
++ if (++(cst->rep0) == 0)
++ return;
++ }
++
++ len += LZMA_MATCH_MIN_LEN;
++
++ copy_bytes(wr, cst->rep0, len);
++}
++
++
++
++STATIC inline int INIT unlzma(unsigned char *buf, int in_len,
++ int(*fill)(void*, unsigned int),
++ int(*flush)(void*, unsigned int),
++ unsigned char *output,
++ int *posp,
++ void(*error_fn)(char *x)
++ )
++{
++ struct lzma_header header;
++ int lc, pb, lp;
++ uint32_t pos_state_mask;
++ uint32_t literal_pos_mask;
++ uint16_t *p;
++ int num_probs;
++ struct rc rc;
++ int i, mi;
++ struct writer wr;
++ struct cstate cst;
++ unsigned char *inbuf;
++ int ret = -1;
++
++ set_error_fn(error_fn);
++ if (!flush)
++ in_len -= 4; /* Uncompressed size hack active in pre-boot
++ environment */
++ if (buf)
++ inbuf = buf;
++ else
++ inbuf = malloc(LZMA_IOBUF_SIZE);
++ if (!inbuf) {
++ error("Could not allocate input bufer");
++ goto exit_0;
++ }
++
++ cst.state = 0;
++ cst.rep0 = cst.rep1 = cst.rep2 = cst.rep3 = 1;
++
++ wr.header = &header;
++ wr.flush = flush;
++ wr.global_pos = 0;
++ wr.previous_byte = 0;
++ wr.buffer_pos = 0;
++
++ rc_init(&rc, fill, inbuf, in_len);
++
++ for (i = 0; i < sizeof(header); i++) {
++ if (rc.ptr >= rc.buffer_end)
++ rc_read(&rc);
++ ((unsigned char *)&header)[i] = *rc.ptr++;
++ }
++
++ if (header.pos >= (9 * 5 * 5))
++ error("bad header");
++
++ mi = 0;
++ lc = header.pos;
++ while (lc >= 9) {
++ mi++;
++ lc -= 9;
++ }
++ pb = 0;
++ lp = mi;
++ while (lp >= 5) {
++ pb++;
++ lp -= 5;
++ }
++ pos_state_mask = (1 << pb) - 1;
++ literal_pos_mask = (1 << lp) - 1;
++
++ ENDIAN_CONVERT(header.dict_size);
++ ENDIAN_CONVERT(header.dst_size);
++
++ if (header.dict_size == 0)
++ header.dict_size = 1;
++
++ if (output)
++ wr.buffer = output;
++ else {
++ wr.bufsize = MIN(header.dst_size, header.dict_size);
++ wr.buffer = large_malloc(wr.bufsize);
++ }
++ if (wr.buffer == NULL)
++ goto exit_1;
++
++ num_probs = LZMA_BASE_SIZE + (LZMA_LIT_SIZE << (lc + lp));
++ p = (uint16_t *) large_malloc(num_probs * sizeof(*p));
++ if (p == 0)
++ goto exit_2;
++ num_probs = LZMA_LITERAL + (LZMA_LIT_SIZE << (lc + lp));
++ for (i = 0; i < num_probs; i++)
++ p[i] = (1 << RC_MODEL_TOTAL_BITS) >> 1;
++
++ rc_init_code(&rc);
++
++ while (get_pos(&wr) < header.dst_size) {
++ int pos_state = get_pos(&wr) & pos_state_mask;
++ uint16_t *prob = p + LZMA_IS_MATCH +
++ (cst.state << LZMA_NUM_POS_BITS_MAX) + pos_state;
++ if (rc_is_bit_0(&rc, prob))
++ process_bit0(&wr, &rc, &cst, p, pos_state, prob,
++ lc, literal_pos_mask);
++ else {
++ process_bit1(&wr, &rc, &cst, p, pos_state, prob);
++ if (cst.rep0 == 0)
++ break;
++ }
++ }
++
++ if (posp)
++ *posp = rc.ptr-rc.buffer;
++ if (wr.flush)
++ wr.flush(wr.buffer, wr.buffer_pos);
++ ret = 0;
++ large_free(p);
++exit_2:
++ if (!output)
++ large_free(wr.buffer);
++exit_1:
++ if (!buf)
++ free(inbuf);
++exit_0:
++ return ret;
++}
++
++#define decompress unlzma
+diff --git a/lib/zlib_inflate/inflate.h
+index df8a6c9..3d17b3d 100644
+--- a/lib/zlib_inflate/inflate.h
++++ b/lib/zlib_inflate/inflate.h
+@@ -1,3 +1,6 @@
++#ifndef INFLATE_H
++#define INFLATE_H
++
+ /* inflate.h -- internal inflate state definition
+ * Copyright (C) 1995-2004 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+@@ -105,3 +108,4 @@ struct inflate_state {
+ unsigned short work[288]; /* work area for code table building */
+ code codes[ENOUGH]; /* space for code tables */
+ };
++#endif
+diff --git a/lib/zlib_inflate/inftrees.h
+index 5f5219b..b70b473 100644
+--- a/lib/zlib_inflate/inftrees.h
++++ b/lib/zlib_inflate/inftrees.h
+@@ -1,3 +1,6 @@
++#ifndef INFTREES_H
++#define INFTREES_H
++
+ /* inftrees.h -- header to use inftrees.c
+ * Copyright (C) 1995-2005 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+@@ -53,3 +56,4 @@ typedef enum {
+ extern int zlib_inflate_table (codetype type, unsigned short *lens,
+ unsigned codes, code **table,
+ unsigned *bits, unsigned short *work);
++#endif
+diff --git a/scripts/Makefile.lib
+index b4ca38a..6f6802d 100644
+--- a/scripts/Makefile.lib
++++ b/scripts/Makefile.lib
+@@ -183,3 +183,17 @@ quiet_cmd_gzip = GZIP $@
+ cmd_gzip = gzip -f -9 < $< > $@
+
+
++# Bzip2
++# ---------------------------------------------------------------------------
++
++# Bzip2 does not include size in file... so we have to fake that
++size_append=$(CONFIG_SHELL) $(srctree)/scripts/bin_size
++
++quiet_cmd_bzip2 = BZIP2 $@
++cmd_bzip2 = (bzip2 -9 < $< ; $(size_append) $<) > $@ || (rm -f $@ ; false)
++
++# Lzma
++# ---------------------------------------------------------------------------
++
++quiet_cmd_lzma = LZMA $@
++cmd_lzma = (lzma -9 -c $< ; $(size_append) $<) >$@ || (rm -f $@ ; false)
+diff --git a/scripts/bin_size
+new file mode 100644
+index 0000000..43e1b36
+--- /dev/null
++++ b/scripts/bin_size
+@@ -0,0 +1,10 @@
++#!/bin/sh
++
++if [ $# = 0 ] ; then
++ echo Usage: $0 file
++fi
++
++size_dec=`stat -c "%s" $1`
++size_hex_echo_string=`printf "%08x" $size_dec |
++ sed 's/\(..\)\(..\)\(..\)\(..\)/\\\\x\4\\\\x\3\\\\x\2\\\\x\1/g'`
++/bin/echo -ne $size_hex_echo_string
+--
+1.8.1
+
diff --git a/meta-aspeed/recipes-kernel/linux/files/patch-2.6.28.9/0002-bzip2-lzma-config-and-initramfs-support-for-bzip2-lz.patch b/meta-aspeed/recipes-kernel/linux/files/patch-2.6.28.9/0002-bzip2-lzma-config-and-initramfs-support-for-bzip2-lz.patch
new file mode 100644
index 0000000..1fca71b
--- /dev/null
+++ b/meta-aspeed/recipes-kernel/linux/files/patch-2.6.28.9/0002-bzip2-lzma-config-and-initramfs-support-for-bzip2-lz.patch
@@ -0,0 +1,585 @@
+From 46b4296ca3e989127c8646e5c115561f9a2f8fa3 Mon Sep 17 00:00:00 2001
+From: Alain Knaff <alain@knaff.lu>
+Date: Sun, 4 Jan 2009 22:46:17 +0100
+Subject: bzip2/lzma: config and initramfs support for bzip2/lzma decompression
+
+Impact: New code for initramfs decompression, new features
+
+This is the second part of the bzip2/lzma patch
+
+The bzip patch is based on an idea by Christian Ludwig, includes support for
+compressing the kernel with bzip2 or lzma rather than gzip. Both
+compressors give smaller sizes than gzip. Lzma's decompresses faster
+than bzip2.
+
+It also supports ramdisks and initramfs' compressed using these two
+compressors.
+
+The functionality has been successfully used for a couple of years by
+the udpcast project
+
+This version applies to "tip" kernel 2.6.28
+
+This part contains:
+- support for new compressions (bzip2 and lzma) in initramfs and
+old-style ramdisk
+- config dialog for kernel compression (but new kernel compressions
+not yet supported)
+
+Signed-off-by: Alain Knaff <alain@knaff.lu>
+Signed-off-by: H. Peter Anvin <hpa@zytor.com>
+---
+ .../linux-aspeed-2.6.28.9/drivers/block/Kconfig | 25 +++
+ .../linux/files/linux-aspeed-2.6.28.9/init/Kconfig | 50 ++++++
+ .../linux-aspeed-2.6.28.9/init/do_mounts_rd.c | 182 ++++++++-------------
+ .../files/linux-aspeed-2.6.28.9/init/initramfs.c | 123 +++++---------
+ .../linux/files/linux-aspeed-2.6.28.9/lib/Makefile | 3 +-
+ 5 files changed, 184 insertions(+), 199 deletions(-)
+
+diff --git a/drivers/block/Kconfig
+index 0344a8a..7955944 100644
+--- a/drivers/block/Kconfig
++++ b/drivers/block/Kconfig
+@@ -358,6 +358,31 @@ config BLK_DEV_XIP
+ will prevent RAM block device backing store memory from being
+ allocated from highmem (only a problem for highmem systems).
+
++config RD_BZIP2
++ bool "Initial ramdisk compressed using bzip2"
++ default n
++ depends on BLK_DEV_INITRD=y
++ help
++ Support loading of a bzip2 encoded initial ramdisk or cpio buffer
++ If unsure, say N.
++
++config RD_LZMA
++ bool "Initial ramdisk compressed using lzma"
++ default n
++ depends on BLK_DEV_INITRD=y
++ help
++ Support loading of a lzma encoded initial ramdisk or cpio buffer
++ If unsure, say N.
++
++config RD_GZIP
++ bool "Initial ramdisk compressed using gzip"
++ default y
++ depends on BLK_DEV_INITRD=y
++ select ZLIB_INFLATE
++ help
++ Support loading of a gzip encoded initial ramdisk or cpio buffer.
++ If unsure, say Y.
++
+ config CDROM_PKTCDVD
+ tristate "Packet writing on CD/DVD media"
+ depends on !UML
+diff --git a/init/Kconfig
+index 83b6905..d7f95fe 100644
+--- a/init/Kconfig
++++ b/init/Kconfig
+@@ -101,6 +101,56 @@ config LOCALVERSION_AUTO
+
+ which is done within the script "scripts/setlocalversion".)
+
++choice
++ prompt "Kernel compression mode"
++ default KERNEL_GZIP
++ help
++ The linux kernel is a kind of self-extracting executable.
++ Several compression algorithms are available, which differ
++ in efficiency, compression and decompression speed.
++ Compression speed is only relevant when building a kernel.
++ Decompression speed is relevant at each boot.
++
++ If you have any problems with bzip2 or lzma compressed
++ kernels, mail me (Alain Knaff) <alain@knaff.lu>. (An older
++ version of this functionality (bzip2 only), for 2.4, was
++ supplied by Christian Ludwig)
++
++ High compression options are mostly useful for users, who
++ are low on disk space (embedded systems), but for whom ram
++ size matters less.
++
++ If in doubt, select 'gzip'
++
++config KERNEL_GZIP
++ bool "Gzip"
++ help
++ The old and tried gzip compression. Its compression ratio is
++ the poorest among the 3 choices; however its speed (both
++ compression and decompression) is the fastest.
++
++config KERNEL_BZIP2
++ bool "Bzip2"
++ help
++ Its compression ratio and speed is intermediate.
++ Decompression speed is slowest among the 3.
++ The kernel size is about 10 per cent smaller with bzip2,
++ in comparison to gzip.
++ Bzip2 uses a large amount of memory. For modern kernels
++ you will need at least 8MB RAM or more for booting.
++
++config KERNEL_LZMA
++ bool "LZMA"
++ help
++ The most recent compression algorithm.
++ Its ratio is best, decompression speed is between the other
++ 2. Compression is slowest.
++ The kernel size is about 33 per cent smaller with lzma,
++ in comparison to gzip.
++
++endchoice
++
++
+ config SWAP
+ bool "Support for paging of anonymous memory (swap)"
+ depends on MMU && BLOCK
+diff --git a/init/do_mounts_rd.c
+index a7c748f..dcaeb1f 100644
+--- a/init/do_mounts_rd.c
++++ b/init/do_mounts_rd.c
+@@ -10,6 +10,12 @@
+
+ #include "do_mounts.h"
+
++#include <linux/decompress/generic.h>
++
++#include <linux/decompress/bunzip2.h>
++#include <linux/decompress/unlzma.h>
++#include <linux/decompress/inflate.h>
++
+ int __initdata rd_prompt = 1;/* 1 = prompt for RAM disk, 0 = don't prompt */
+
+ static int __init prompt_ramdisk(char *str)
+@@ -28,7 +34,7 @@ static int __init ramdisk_start_setup(char *str)
+ }
+ __setup("ramdisk_start=", ramdisk_start_setup);
+
+-static int __init crd_load(int in_fd, int out_fd);
++static int __init crd_load(int in_fd, int out_fd, decompress_fn deco);
+
+ /*
+ * This routine tries to find a RAM disk image to load, and returns the
+@@ -44,7 +50,7 @@ static int __init crd_load(int in_fd, int out_fd);
+ * gzip
+ */
+ static int __init
+-identify_ramdisk_image(int fd, int start_block)
++identify_ramdisk_image(int fd, int start_block, decompress_fn *decompressor)
+ {
+ const int size = 512;
+ struct minix_super_block *minixsb;
+@@ -70,6 +76,7 @@ identify_ramdisk_image(int fd, int start_block)
+ sys_lseek(fd, start_block * BLOCK_SIZE, 0);
+ sys_read(fd, buf, size);
+
++#ifdef CONFIG_RD_GZIP
+ /*
+ * If it matches the gzip magic numbers, return 0
+ */
+@@ -77,9 +84,39 @@ identify_ramdisk_image(int fd, int start_block)
+ printk(KERN_NOTICE
+ "RAMDISK: Compressed image found at block %d\n",
+ start_block);
++ *decompressor = gunzip;
++ nblocks = 0;
++ goto done;
++ }
++#endif
++
++#ifdef CONFIG_RD_BZIP2
++ /*
++ * If it matches the bzip2 magic numbers, return -1
++ */
++ if (buf[0] == 0x42 && (buf[1] == 0x5a)) {
++ printk(KERN_NOTICE
++ "RAMDISK: Bzipped image found at block %d\n",
++ start_block);
++ *decompressor = bunzip2;
++ nblocks = 0;
++ goto done;
++ }
++#endif
++
++#ifdef CONFIG_RD_LZMA
++ /*
++ * If it matches the lzma magic numbers, return -1
++ */
++ if (buf[0] == 0x5d && (buf[1] == 0x00)) {
++ printk(KERN_NOTICE
++ "RAMDISK: Lzma image found at block %d\n",
++ start_block);
++ *decompressor = unlzma;
+ nblocks = 0;
+ goto done;
+ }
++#endif
+
+ /* romfs is at block zero too */
+ if (romfsb->word0 == ROMSB_WORD0 &&
+@@ -143,6 +180,7 @@ int __init rd_load_image(char *from)
+ int nblocks, i, disk;
+ char *buf = NULL;
+ unsigned short rotate = 0;
++ decompress_fn decompressor = NULL;
+ #if !defined(CONFIG_S390) && !defined(CONFIG_PPC_ISERIES)
+ char rotator[4] = { '|' , '/' , '-' , '\\' };
+ #endif
+@@ -155,12 +193,12 @@ int __init rd_load_image(char *from)
+ if (in_fd < 0)
+ goto noclose_input;
+
+- nblocks = identify_ramdisk_image(in_fd, rd_image_start);
++ nblocks = identify_ramdisk_image(in_fd, rd_image_start, &decompressor);
+ if (nblocks < 0)
+ goto done;
+
+ if (nblocks == 0) {
+- if (crd_load(in_fd, out_fd) == 0)
++ if (crd_load(in_fd, out_fd, decompressor) == 0)
+ goto successful_load;
+ goto done;
+ }
+@@ -259,138 +297,48 @@ int __init rd_load_disk(int n)
+ return rd_load_image("/dev/root");
+ }
+
+-/*
+- * gzip declarations
+- */
+-
+-#define OF(args) args
+-
+-#ifndef memzero
+-#define memzero(s, n) memset ((s), 0, (n))
+-#endif
+-
+-typedef unsigned char uch;
+-typedef unsigned short ush;
+-typedef unsigned long ulg;
+-
+-#define INBUFSIZ 4096
+-#define WSIZE 0x8000 /* window size--must be a power of two, and */
+- /* at least 32K for zip's deflate method */
+-
+-static uch *inbuf;
+-static uch *window;
+-
+-static unsigned insize; /* valid bytes in inbuf */
+-static unsigned inptr; /* index of next byte to be processed in inbuf */
+-static unsigned outcnt; /* bytes in output buffer */
+ static int exit_code;
+-static int unzip_error;
+-static long bytes_out;
++static int decompress_error;
+ static int crd_infd, crd_outfd;
+
+-#define get_byte() (inptr < insize ? inbuf[inptr++] : fill_inbuf())
+-
+-/* Diagnostic functions (stubbed out) */
+-#define Assert(cond,msg)
+-#define Trace(x)
+-#define Tracev(x)
+-#define Tracevv(x)
+-#define Tracec(c,x)
+-#define Tracecv(c,x)
+-
+-#define STATIC static
+-#define INIT __init
+-
+-static int __init fill_inbuf(void);
+-static void __init flush_window(void);
+-static void __init error(char *m);
+-
+-#define NO_INFLATE_MALLOC
+-
+-#include "../lib/inflate.c"
+-
+-/* ===========================================================================
+- * Fill the input buffer. This is called only when the buffer is empty
+- * and at least one byte is really needed.
+- * Returning -1 does not guarantee that gunzip() will ever return.
+- */
+-static int __init fill_inbuf(void)
++static int __init compr_fill(void *buf, unsigned int len)
+ {
+- if (exit_code) return -1;
+-
+- insize = sys_read(crd_infd, inbuf, INBUFSIZ);
+- if (insize == 0) {
+- error("RAMDISK: ran out of compressed data");
+- return -1;
+- }
+-
+- inptr = 1;
+-
+- return inbuf[0];
++ int r = sys_read(crd_infd, buf, len);
++ if (r < 0)
++ printk(KERN_ERR "RAMDISK: error while reading compressed data");
++ else if (r == 0)
++ printk(KERN_ERR "RAMDISK: EOF while reading compressed data");
++ return r;
+ }
+
+-/* ===========================================================================
+- * Write the output window window[0..outcnt-1] and update crc and bytes_out.
+- * (Used for the decompressed data only.)
+- */
+-static void __init flush_window(void)
++static int __init compr_flush(void *window, unsigned int outcnt)
+ {
+- ulg c = crc; /* temporary variable */
+- unsigned n, written;
+- uch *in, ch;
+-
+- written = sys_write(crd_outfd, window, outcnt);
+- if (written != outcnt && unzip_error == 0) {
+- printk(KERN_ERR "RAMDISK: incomplete write (%d != %d) %ld\n",
+- written, outcnt, bytes_out);
+- unzip_error = 1;
+- }
+- in = window;
+- for (n = 0; n < outcnt; n++) {
+- ch = *in++;
+- c = crc_32_tab[((int)c ^ ch) & 0xff] ^ (c >> 8);
+- }
+- crc = c;
+- bytes_out += (ulg)outcnt;
+- outcnt = 0;
++ int written = sys_write(crd_outfd, window, outcnt);
++ if (written != outcnt) {
++ if (decompress_error == 0)
++ printk(KERN_ERR
++ "RAMDISK: incomplete write (%d != %d)\n",
++ written, outcnt);
++ decompress_error = 1;
++ return -1;
++ }
++ return outcnt;
+ }
+
+ static void __init error(char *x)
+ {
+ printk(KERN_ERR "%s\n", x);
+ exit_code = 1;
+- unzip_error = 1;
++ decompress_error = 1;
+ }
+
+-static int __init crd_load(int in_fd, int out_fd)
++static int __init crd_load(int in_fd, int out_fd, decompress_fn deco)
+ {
+ int result;
+-
+- insize = 0; /* valid bytes in inbuf */
+- inptr = 0; /* index of next byte to be processed in inbuf */
+- outcnt = 0; /* bytes in output buffer */
+- exit_code = 0;
+- bytes_out = 0;
+- crc = (ulg)0xffffffffL; /* shift register contents */
+-
+ crd_infd = in_fd;
+ crd_outfd = out_fd;
+- inbuf = kmalloc(INBUFSIZ, GFP_KERNEL);
+- if (!inbuf) {
+- printk(KERN_ERR "RAMDISK: Couldn't allocate gzip buffer\n");
+- return -1;
+- }
+- window = kmalloc(WSIZE, GFP_KERNEL);
+- if (!window) {
+- printk(KERN_ERR "RAMDISK: Couldn't allocate gzip window\n");
+- kfree(inbuf);
+- return -1;
+- }
+- makecrc();
+- result = gunzip();
+- if (unzip_error)
++ result = deco(NULL, 0, compr_fill, compr_flush, NULL, NULL, error);
++ if (decompress_error)
+ result = 1;
+- kfree(inbuf);
+- kfree(window);
+ return result;
+ }
+diff --git a/init/initramfs.c
+index 4f5ba75..40bd4fb 100644
+--- a/init/initramfs.c
++++ b/init/initramfs.c
+@@ -389,11 +389,14 @@ static int __init write_buffer(char *buf, unsigned len)
+ return len - count;
+ }
+
+-static void __init flush_buffer(char *buf, unsigned len)
++
++static int __init flush_buffer(void *bufv, unsigned len)
+ {
++ char *buf = (char *) bufv;
+ int written;
++ int origLen = len;
+ if (message)
+- return;
++ return -1;
+ while ((written = write_buffer(buf, len)) < len && !message) {
+ char c = buf[written];
+ if (c == '0') {
+@@ -407,73 +410,14 @@ static void __init flush_buffer(char *buf, unsigned len)
+ } else
+ error("junk in compressed archive");
+ }
++ return origLen;
+ }
+
+-/*
+- * gzip declarations
+- */
+-
+-#define OF(args) args
+-
+-#ifndef memzero
+-#define memzero(s, n) memset ((s), 0, (n))
+-#endif
+-
+-typedef unsigned char uch;
+-typedef unsigned short ush;
+-typedef unsigned long ulg;
+-
+-#define WSIZE 0x8000 /* window size--must be a power of two, and */
+- /* at least 32K for zip's deflate method */
+-
+-static uch *inbuf;
+-static uch *window;
+-
+-static unsigned insize; /* valid bytes in inbuf */
+-static unsigned inptr; /* index of next byte to be processed in inbuf */
+-static unsigned outcnt; /* bytes in output buffer */
+-static long bytes_out;
+-
+-#define get_byte() (inptr < insize ? inbuf[inptr++] : -1)
+-
+-/* Diagnostic functions (stubbed out) */
+-#define Assert(cond,msg)
+-#define Trace(x)
+-#define Tracev(x)
+-#define Tracevv(x)
+-#define Tracec(c,x)
+-#define Tracecv(c,x)
+-
+-#define STATIC static
+-#define INIT __init
+-
+-static void __init flush_window(void);
+-static void __init error(char *m);
+-
+-#define NO_INFLATE_MALLOC
++static unsigned my_inptr; /* index of next byte to be processed in inbuf */
+
+-#include "../lib/inflate.c"
+-
+-/* ===========================================================================
+- * Write the output window window[0..outcnt-1] and update crc and bytes_out.
+- * (Used for the decompressed data only.)
+- */
+-static void __init flush_window(void)
+-{
+- ulg c = crc; /* temporary variable */
+- unsigned n;
+- uch *in, ch;
+-
+- flush_buffer(window, outcnt);
+- in = window;
+- for (n = 0; n < outcnt; n++) {
+- ch = *in++;
+- c = crc_32_tab[((int)c ^ ch) & 0xff] ^ (c >> 8);
+- }
+- crc = c;
+- bytes_out += (ulg)outcnt;
+- outcnt = 0;
+-}
++#include <linux/decompress/bunzip2.h>
++#include <linux/decompress/unlzma.h>
++#include <linux/decompress/inflate.h>
+
+ static char * __init unpack_to_rootfs(char *buf, unsigned len, int check_only)
+ {
+@@ -482,9 +426,10 @@ static char * __init unpack_to_rootfs(char *buf, unsigned len, int check_only)
+ header_buf = kmalloc(110, GFP_KERNEL);
+ symlink_buf = kmalloc(PATH_MAX + N_ALIGN(PATH_MAX) + 1, GFP_KERNEL);
+ name_buf = kmalloc(N_ALIGN(PATH_MAX), GFP_KERNEL);
+- window = kmalloc(WSIZE, GFP_KERNEL);
+- if (!window || !header_buf || !symlink_buf || !name_buf)
++
++ if (!header_buf || !symlink_buf || !name_buf)
+ panic("can't allocate buffers");
++
+ state = Start;
+ this_header = 0;
+ message = NULL;
+@@ -504,22 +449,38 @@ static char * __init unpack_to_rootfs(char *buf, unsigned len, int check_only)
+ continue;
+ }
+ this_header = 0;
+- insize = len;
+- inbuf = buf;
+- inptr = 0;
+- outcnt = 0; /* bytes in output buffer */
+- bytes_out = 0;
+- crc = (ulg)0xffffffffL; /* shift register contents */
+- makecrc();
+- gunzip();
++ if (!gunzip(buf, len, NULL, flush_buffer, NULL,
++ &my_inptr, error) &&
++ message == NULL)
++ goto ok;
++
++#ifdef CONFIG_RD_BZIP2
++ message = NULL; /* Zero out message, or else cpio will
++ think an error has already occured */
++ if (!bunzip2(buf, len, NULL, flush_buffer, NULL,
++ &my_inptr, error) &&
++ message == NULL) {
++ goto ok;
++ }
++#endif
++
++#ifdef CONFIG_RD_LZMA
++ message = NULL; /* Zero out message, or else cpio will
++ think an error has already occured */
++ if (!unlzma(buf, len, NULL, flush_buffer, NULL,
++ &my_inptr, error) &&
++ message == NULL) {
++ goto ok;
++ }
++#endif
++ok:
+ if (state != Reset)
+- error("junk in gzipped archive");
+- this_header = saved_offset + inptr;
+- buf += inptr;
+- len -= inptr;
++ error("junk in compressed archive");
++ this_header = saved_offset + my_inptr;
++ buf += my_inptr;
++ len -= my_inptr;
+ }
+ dir_utime();
+- kfree(window);
+ kfree(name_buf);
+ kfree(symlink_buf);
+ kfree(header_buf);
+diff --git a/lib/Makefile
+index 7cb65d8..867fd9e 100644
+--- a/lib/Makefile
++++ b/lib/Makefile
+@@ -11,7 +11,8 @@ lib-y := ctype.o string.o vsprintf.o cmdline.o \
+ rbtree.o radix-tree.o dump_stack.o \
+ idr.o int_sqrt.o extable.o prio_tree.o \
+ sha1.o irq_regs.o reciprocal_div.o argv_split.o \
+- proportions.o prio_heap.o ratelimit.o show_mem.o
++ proportions.o prio_heap.o ratelimit.o show_mem.o \
++ decompress_inflate.o decompress_bunzip2.o decompress_unlzma.o
+
+ lib-$(CONFIG_MMU) += ioremap.o
+ lib-$(CONFIG_SMP) += cpumask.o
+--
+1.8.1
+
diff --git a/meta-aspeed/recipes-kernel/linux/files/patch-2.6.28.9/0005-mtd-Bug-in-m25p80.c-during-whole-chip-erase.patch b/meta-aspeed/recipes-kernel/linux/files/patch-2.6.28.9/0005-mtd-Bug-in-m25p80.c-during-whole-chip-erase.patch
new file mode 100644
index 0000000..e8dd925
--- /dev/null
+++ b/meta-aspeed/recipes-kernel/linux/files/patch-2.6.28.9/0005-mtd-Bug-in-m25p80.c-during-whole-chip-erase.patch
@@ -0,0 +1,53 @@
+From 3f33b0aaac4e208579fe5aa2964857d4e9ba10c5 Mon Sep 17 00:00:00 2001
+From: "Steven A. Falco" <sfalco@harris.com>
+Date: Mon, 27 Apr 2009 17:10:10 -0400
+Subject: [PATCH 05/16] mtd: Bug in m25p80.c during whole-chip erase
+
+There is a logic error in "whole chip erase" for the m25p80 family. If
+the whole device is successfully erased, erase_chip() will return 0, and
+the code will fall through to the "else" clause, and do sector-by-sector
+erase in addition to the whole-chip erase. This patch corrects that.
+
+Also, the MAX_READY_WAIT_COUNT is insufficient for an m25p16 connected
+to a 400 MHz powerpc. Increasing it allows me to successfully program
+the device on my board.
+
+Signed-off-by: Steven A. Falco <sfalco@harris.com>
+Signed-off-by: David Woodhouse <David.Woodhouse@intel.com>
+---
+ drivers/mtd/devices/m25p80.c | 12 +++++++-----
+ 1 file changed, 7 insertions(+), 5 deletions(-)
+
+diff --git a/drivers/mtd/devices/m25p80.c b/drivers/mtd/devices/m25p80.c
+index 8185b1f..dfadef8 100644
+--- a/drivers/mtd/devices/m25p80.c
++++ b/drivers/mtd/devices/m25p80.c
+@@ -54,7 +54,7 @@
+ #define SR_SRWD 0x80 /* SR write protect */
+
+ /* Define max times to check status register before we give up. */
+-#define MAX_READY_WAIT_COUNT 100000
++#define MAX_READY_WAIT_COUNT 1000000
+ #define CMD_SIZE 4
+
+ #ifdef CONFIG_M25PXX_USE_FAST_READ
+@@ -246,10 +246,12 @@ static int m25p80_erase(struct mtd_info *mtd, struct erase_info *instr)
+ mutex_lock(&flash->lock);
+
+ /* whole-chip erase? */
+- if (len == flash->mtd.size && erase_chip(flash)) {
+- instr->state = MTD_ERASE_FAILED;
+- mutex_unlock(&flash->lock);
+- return -EIO;
++ if (len == flash->mtd.size) {
++ if (erase_chip(flash)) {
++ instr->state = MTD_ERASE_FAILED;
++ mutex_unlock(&flash->lock);
++ return -EIO;
++ }
+
+ /* REVISIT in some cases we could speed up erasing large regions
+ * by using OPCODE_SE instead of OPCODE_BE_4K. We may have set up
+--
+1.8.1
+
diff --git a/meta-aspeed/recipes-kernel/linux/files/patch-2.6.28.9/0006-mtd-fix-timeout-in-M25P80-driver.patch b/meta-aspeed/recipes-kernel/linux/files/patch-2.6.28.9/0006-mtd-fix-timeout-in-M25P80-driver.patch
new file mode 100644
index 0000000..2bfd226
--- /dev/null
+++ b/meta-aspeed/recipes-kernel/linux/files/patch-2.6.28.9/0006-mtd-fix-timeout-in-M25P80-driver.patch
@@ -0,0 +1,63 @@
+From cd1a6de7d4a492bf3405a6c070075a4cb8c90262 Mon Sep 17 00:00:00 2001
+From: Peter Horton <zero@colonel-panic.org>
+Date: Fri, 8 May 2009 13:51:53 +0100
+Subject: [PATCH 06/16] mtd: fix timeout in M25P80 driver
+
+Extend erase timeout in M25P80 SPI Flash driver.
+
+The M25P80 drivers fails erasing sectors on a M25P128 because the ready
+wait timeout is too short. Change the timeout from a simple loop count to a
+suitable number of seconds.
+
+Signed-off-by: Peter Horton <zero@colonel-panic.org>
+Tested-by: Martin Michlmayr <tbm@cyrius.com>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: David Woodhouse <David.Woodhouse@intel.com>
+---
+ drivers/mtd/devices/m25p80.c | 16 ++++++++--------
+ 1 file changed, 8 insertions(+), 8 deletions(-)
+
+diff --git a/drivers/mtd/devices/m25p80.c b/drivers/mtd/devices/m25p80.c
+index dfadef8..cc6369e 100644
+--- a/drivers/mtd/devices/m25p80.c
++++ b/drivers/mtd/devices/m25p80.c
+@@ -54,7 +54,7 @@
+ #define SR_SRWD 0x80 /* SR write protect */
+
+ /* Define max times to check status register before we give up. */
+-#define MAX_READY_WAIT_COUNT 1000000
++#define MAX_READY_WAIT_JIFFIES (10 * HZ) /* eg. M25P128 specs 6s max sector erase */
+ #define CMD_SIZE 4
+
+ #ifdef CONFIG_M25PXX_USE_FAST_READ
+@@ -139,20 +139,20 @@ static inline int write_enable(struct m25p *flash)
+ */
+ static int wait_till_ready(struct m25p *flash)
+ {
+- int count;
++ unsigned long deadline;
+ int sr;
+
+- /* one chip guarantees max 5 msec wait here after page writes,
+- * but potentially three seconds (!) after page erase.
+- */
+- for (count = 0; count < MAX_READY_WAIT_COUNT; count++) {
++ deadline = jiffies + MAX_READY_WAIT_JIFFIES;
++
++ do {
+ if ((sr = read_sr(flash)) < 0)
+ break;
+ else if (!(sr & SR_WIP))
+ return 0;
+
+- /* REVISIT sometimes sleeping would be best */
+- }
++ cond_resched();
++
++ } while (!time_after_eq(jiffies, deadline));
+
+ return 1;
+ }
+--
+1.8.1
+
diff --git a/meta-aspeed/recipes-kernel/linux/files/patch-2.6.28.9/0009-mtd-m25p80-timeout-too-short-for-worst-case-m25p16-d.patch b/meta-aspeed/recipes-kernel/linux/files/patch-2.6.28.9/0009-mtd-m25p80-timeout-too-short-for-worst-case-m25p16-d.patch
new file mode 100644
index 0000000..809f839
--- /dev/null
+++ b/meta-aspeed/recipes-kernel/linux/files/patch-2.6.28.9/0009-mtd-m25p80-timeout-too-short-for-worst-case-m25p16-d.patch
@@ -0,0 +1,31 @@
+From 89bb871e96cdc3d78b7f69f0bacc94b21bbaccfd Mon Sep 17 00:00:00 2001
+From: "Steven A. Falco" <sfalco@harris.com>
+Date: Fri, 26 Jun 2009 12:42:47 -0400
+Subject: [PATCH 09/16] mtd: m25p80 timeout too short for worst-case m25p16
+ devices
+
+The m25p16 data sheet from numonyx lists the worst-case bulk erase time
+(tBE) as 40 seconds.
+
+Signed-off-by: Steven A. Falco <sfalco@harris.com>
+Signed-off-by: David Woodhouse <David.Woodhouse@intel.com>
+---
+ drivers/mtd/devices/m25p80.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/mtd/devices/m25p80.c b/drivers/mtd/devices/m25p80.c
+index 59c4612..ae5fe91 100644
+--- a/drivers/mtd/devices/m25p80.c
++++ b/drivers/mtd/devices/m25p80.c
+@@ -54,7 +54,7 @@
+ #define SR_SRWD 0x80 /* SR write protect */
+
+ /* Define max times to check status register before we give up. */
+-#define MAX_READY_WAIT_JIFFIES (10 * HZ) /* eg. M25P128 specs 6s max sector erase */
++#define MAX_READY_WAIT_JIFFIES (40 * HZ) /* M25P16 specs 40s max chip erase */
+ #define CMD_SIZE 4
+
+ #ifdef CONFIG_M25PXX_USE_FAST_READ
+--
+1.8.1
+
diff --git a/meta-aspeed/recipes-kernel/linux/files/patch-2.6.28.9/0010-mtd-m25p80-fix-null-pointer-dereference-bug.patch b/meta-aspeed/recipes-kernel/linux/files/patch-2.6.28.9/0010-mtd-m25p80-fix-null-pointer-dereference-bug.patch
new file mode 100644
index 0000000..7727636
--- /dev/null
+++ b/meta-aspeed/recipes-kernel/linux/files/patch-2.6.28.9/0010-mtd-m25p80-fix-null-pointer-dereference-bug.patch
@@ -0,0 +1,56 @@
+From edcb3b14863e1a6aa1923eeaa81125a00cf51a80 Mon Sep 17 00:00:00 2001
+From: Anton Vorontsov <avorontsov@ru.mvista.com>
+Date: Thu, 6 Aug 2009 15:18:37 -0700
+Subject: [PATCH 10/16] mtd: m25p80: fix null pointer dereference bug
+
+This patch fixes the following oops, observed with MTD_PARTITIONS=n:
+
+m25p80 spi32766.0: m25p80 (1024 Kbytes)
+Unable to handle kernel paging request for data at address 0x00000008
+Faulting instruction address: 0xc03a54b0
+Oops: Kernel access of bad area, sig: 11 [#1]
+Modules linked in:
+NIP: c03a54b0 LR: c03a5494 CTR: c01e98b8
+REGS: ef82bb60 TRAP: 0300 Not tainted (2.6.31-rc4-00167-g4733fd3)
+MSR: 00029000 <EE,ME,CE> CR: 24022022 XER: 20000000
+DEAR: 00000008, ESR: 00000000
+TASK = ef82c000[1] 'swapper' THREAD: ef82a000
+GPR00: 00000000 ef82bc10 ef82c000 0000002e 00001eb8 ffffffff c01e9824 00000036
+GPR08: c054ed40 c0542a08 00001eb8 00004000 22022022 1001a1a0 3ff8fd00 00000000
+GPR16: 00000000 00000001 00000000 00000000 ef82bddc c0530000 efbef500 ef8356d0
+GPR24: 00000000 ef8356d0 00000000 efbf7a00 c0530ec4 ffffffed efbf5300 c0541f98
+NIP [c03a54b0] m25p_probe+0x22c/0x354
+LR [c03a5494] m25p_probe+0x210/0x354
+Call Trace:
+[ef82bc10] [c03a5494] m25p_probe+0x210/0x354 (unreliable)
+[ef82bca0] [c024e37c] spi_drv_probe+0x2c/0x3c
+[ef82bcb0] [c01f1afc] driver_probe_device+0xa4/0x178
+[ef82bcd0] [c01f06e8] bus_for_each_drv+0x6c/0xa8
+[ef82bd00] [c01f1a34] device_attach+0x84/0xa8
+...
+
+Signed-off-by: Anton Vorontsov <avorontsov@ru.mvista.com>
+Cc: David Brownell <david-b@pacbell.net>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Artem Bityutskiy <Artem.Bityutskiy@nokia.com>
+Signed-off-by: David Woodhouse <David.Woodhouse@intel.com>
+---
+ drivers/mtd/devices/m25p80.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/mtd/devices/m25p80.c b/drivers/mtd/devices/m25p80.c
+index ae5fe91..10ed195 100644
+--- a/drivers/mtd/devices/m25p80.c
++++ b/drivers/mtd/devices/m25p80.c
+@@ -736,7 +736,7 @@ static int __devinit m25p_probe(struct spi_device *spi)
+ flash->partitioned = 1;
+ return add_mtd_partitions(&flash->mtd, parts, nr_parts);
+ }
+- } else if (data->nr_parts)
++ } else if (data && data->nr_parts)
+ dev_warn(&spi->dev, "ignoring %d default partitions on %s\n",
+ data->nr_parts, data->name);
+
+--
+1.8.1
+
diff --git a/meta-aspeed/recipes-kernel/linux/files/patch-2.6.28.9/0012-mtd-m25p80-add-support-for-AAI-programming-with-SST-.patch b/meta-aspeed/recipes-kernel/linux/files/patch-2.6.28.9/0012-mtd-m25p80-add-support-for-AAI-programming-with-SST-.patch
new file mode 100644
index 0000000..e726dc7
--- /dev/null
+++ b/meta-aspeed/recipes-kernel/linux/files/patch-2.6.28.9/0012-mtd-m25p80-add-support-for-AAI-programming-with-SST-.patch
@@ -0,0 +1,179 @@
+From 49aac4aec53c523f16343b4668a5a239b69659f1 Mon Sep 17 00:00:00 2001
+From: Graf Yang <graf.yang@analog.com>
+Date: Mon, 15 Jun 2009 08:23:41 +0000
+Subject: [PATCH 012/130] mtd: m25p80: add support for AAI programming with SST
+ SPI flashes
+
+The SST SPI flashes are a bit non-standard in that they can be programmed
+one byte at a time (including address!), or they can be written two bytes
+at a time with auto address incrementing (AAI). The latter form is
+obviously much better for performance, so let's use it when possible.
+
+Signed-off-by: Graf Yang <graf.yang@analog.com>
+Signed-off-by: Mike Frysinger <vapier@gentoo.org>
+Signed-off-by: David Woodhouse <David.Woodhouse@intel.com>
+---
+ drivers/mtd/devices/m25p80.c | 126 ++++++++++++++++++++++++++++++++++++++++++-
+ 1 file changed, 125 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/mtd/devices/m25p80.c b/drivers/mtd/devices/m25p80.c
+index 6d8d265..53de9f0 100644
+--- a/drivers/mtd/devices/m25p80.c
++++ b/drivers/mtd/devices/m25p80.c
+@@ -44,6 +44,11 @@
+ #define OPCODE_SE 0xd8 /* Sector erase (usually 64KiB) */
+ #define OPCODE_RDID 0x9f /* Read JEDEC ID */
+
++/* Used for SST flashes only. */
++#define OPCODE_BP 0x02 /* Byte program */
++#define OPCODE_WRDI 0x04 /* Write disable */
++#define OPCODE_AAI_WP 0xad /* Auto address increment word program */
++
+ /* Status Register bits. */
+ #define SR_WIP 1 /* Write in progress */
+ #define SR_WEL 2 /* Write enable latch */
+@@ -132,6 +137,15 @@ static inline int write_enable(struct m25p *flash)
+ return spi_write_then_read(flash->spi, &code, 1, NULL, 0);
+ }
+
++/*
++ * Send write disble instruction to the chip.
++ */
++static inline int write_disable(struct m25p *flash)
++{
++ u8 code = OPCODE_WRDI;
++
++ return spi_write_then_read(flash->spi, &code, 1, NULL, 0);
++}
+
+ /*
+ * Service routine to read status register until ready, or timeout occurs.
+@@ -454,6 +468,111 @@ static int m25p80_write(struct mtd_info *mtd, loff_t to, size_t len,
+ return 0;
+ }
+
++static int sst_write(struct mtd_info *mtd, loff_t to, size_t len,
++ size_t *retlen, const u_char *buf)
++{
++ struct m25p *flash = mtd_to_m25p(mtd);
++ struct spi_transfer t[2];
++ struct spi_message m;
++ size_t actual;
++ int cmd_sz, ret;
++
++ if (retlen)
++ *retlen = 0;
++
++ /* sanity checks */
++ if (!len)
++ return 0;
++
++ if (to + len > flash->mtd.size)
++ return -EINVAL;
++
++ spi_message_init(&m);
++ memset(t, 0, (sizeof t));
++
++ t[0].tx_buf = flash->command;
++ t[0].len = CMD_SIZE;
++ spi_message_add_tail(&t[0], &m);
++
++ t[1].tx_buf = buf;
++ spi_message_add_tail(&t[1], &m);
++
++ mutex_lock(&flash->lock);
++
++ /* Wait until finished previous write command. */
++ ret = wait_till_ready(flash);
++ if (ret)
++ goto time_out;
++
++ write_enable(flash);
++
++ actual = to % 2;
++ /* Start write from odd address. */
++ if (actual) {
++ flash->command[0] = OPCODE_BP;
++ flash->command[1] = to >> 16;
++ flash->command[2] = to >> 8;
++ flash->command[3] = to;
++
++ /* write one byte. */
++ t[1].len = 1;
++ spi_sync(flash->spi, &m);
++ ret = wait_till_ready(flash);
++ if (ret)
++ goto time_out;
++ *retlen += m.actual_length - CMD_SIZE;
++ }
++ to += actual;
++
++ flash->command[0] = OPCODE_AAI_WP;
++ flash->command[1] = to >> 16;
++ flash->command[2] = to >> 8;
++ flash->command[3] = to;
++
++ /* Write out most of the data here. */
++ cmd_sz = CMD_SIZE;
++ for (; actual < len - 1; actual += 2) {
++ t[0].len = cmd_sz;
++ /* write two bytes. */
++ t[1].len = 2;
++ t[1].tx_buf = buf + actual;
++
++ spi_sync(flash->spi, &m);
++ ret = wait_till_ready(flash);
++ if (ret)
++ goto time_out;
++ *retlen += m.actual_length - cmd_sz;
++ cmd_sz = 1;
++ to += 2;
++ }
++ write_disable(flash);
++ ret = wait_till_ready(flash);
++ if (ret)
++ goto time_out;
++
++ /* Write out trailing byte if it exists. */
++ if (actual != len) {
++ write_enable(flash);
++ flash->command[0] = OPCODE_BP;
++ flash->command[1] = to >> 16;
++ flash->command[2] = to >> 8;
++ flash->command[3] = to;
++ t[0].len = CMD_SIZE;
++ t[1].len = 1;
++ t[1].tx_buf = buf + actual;
++
++ spi_sync(flash->spi, &m);
++ ret = wait_till_ready(flash);
++ if (ret)
++ goto time_out;
++ *retlen += m.actual_length - CMD_SIZE;
++ write_disable(flash);
++ }
++
++time_out:
++ mutex_unlock(&flash->lock);
++ return ret;
++}
+
+ /****************************************************************************/
+
+@@ -670,7 +789,12 @@ static int __devinit m25p_probe(struct spi_device *spi)
+ flash->mtd.size = info->sector_size * info->n_sectors;
+ flash->mtd.erase = m25p80_erase;
+ flash->mtd.read = m25p80_read;
+- flash->mtd.write = m25p80_write;
++
++ /* sst flash chips use AAI word program */
++ if (info->jedec_id >> 16 == 0xbf)
++ flash->mtd.write = sst_write;
++ else
++ flash->mtd.write = m25p80_write;
+
+ /* prefer "small sector" erase if possible */
+ if (info->flags & SECT_4K) {
+--
+1.8.1
+
diff --git a/meta-aspeed/recipes-kernel/linux/files/patch-2.6.28.9/0020-mtd-m25p80-make-command-buffer-DMA-safe.patch b/meta-aspeed/recipes-kernel/linux/files/patch-2.6.28.9/0020-mtd-m25p80-make-command-buffer-DMA-safe.patch
new file mode 100644
index 0000000..d5be404
--- /dev/null
+++ b/meta-aspeed/recipes-kernel/linux/files/patch-2.6.28.9/0020-mtd-m25p80-make-command-buffer-DMA-safe.patch
@@ -0,0 +1,56 @@
+From ca811c5491b0447d917148156785330af2ec9abe Mon Sep 17 00:00:00 2001
+From: Johannes Stezenbach <js@sig21.net>
+Date: Wed, 28 Oct 2009 14:21:37 +0100
+Subject: [PATCH 20/27] mtd: m25p80: make command buffer DMA-safe
+
+spi_write() requires the buffer to be DMA-safe, kmalloc()
+it seperately to ensure this.
+
+Signed-off-by: Johannes Stezenbach <js@sig21.net>
+Signed-off-by: Artem Bityutskiy <Artem.Bityutskiy@nokia.com>
+Signed-off-by: David Woodhouse <David.Woodhouse@intel.com>
+(cherry picked from commit 61c3506c2cabe58bcdfe438d1e57b62994db1616)
+---
+ drivers/mtd/devices/m25p80.c | 11 +++++++++--
+ 1 file changed, 9 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/mtd/devices/m25p80.c b/drivers/mtd/devices/m25p80.c
+index f6b255c..7ca5ab1 100644
+--- a/drivers/mtd/devices/m25p80.c
++++ b/drivers/mtd/devices/m25p80.c
+@@ -84,7 +84,7 @@ struct m25p {
+ struct mtd_info mtd;
+ unsigned partitioned:1;
+ u8 erase_opcode;
+- u8 command[CMD_SIZE + FAST_READ_DUMMY_BYTE];
++ u8 *command;
+ };
+
+ static inline struct m25p *mtd_to_m25p(struct mtd_info *mtd)
+@@ -762,6 +762,11 @@ static int __devinit m25p_probe(struct spi_device *spi)
+ flash = kzalloc(sizeof *flash, GFP_KERNEL);
+ if (!flash)
+ return -ENOMEM;
++ flash->command = kmalloc(CMD_SIZE + FAST_READ_DUMMY_BYTE, GFP_KERNEL);
++ if (!flash->command) {
++ kfree(flash);
++ return -ENOMEM;
++ }
+
+ flash->spi = spi;
+ mutex_init(&flash->lock);
+@@ -877,8 +882,10 @@ static int __devexit m25p_remove(struct spi_device *spi)
+ status = del_mtd_partitions(&flash->mtd);
+ else
+ status = del_mtd_device(&flash->mtd);
+- if (status == 0)
++ if (status == 0) {
++ kfree(flash->command);
+ kfree(flash);
++ }
+ return 0;
+ }
+
+--
+1.8.1
+
diff --git a/meta-aspeed/recipes-kernel/linux/files/patch-2.6.28.9/0021-mtd-m25p80-Add-support-for-CAT25xxx-serial-EEPROMs.patch b/meta-aspeed/recipes-kernel/linux/files/patch-2.6.28.9/0021-mtd-m25p80-Add-support-for-CAT25xxx-serial-EEPROMs.patch
new file mode 100644
index 0000000..6f9e7be
--- /dev/null
+++ b/meta-aspeed/recipes-kernel/linux/files/patch-2.6.28.9/0021-mtd-m25p80-Add-support-for-CAT25xxx-serial-EEPROMs.patch
@@ -0,0 +1,327 @@
+From c2de6ee8dd176f1f37f67169230d3e82c020eb6e Mon Sep 17 00:00:00 2001
+From: Anton Vorontsov <avorontsov@ru.mvista.com>
+Date: Mon, 12 Oct 2009 20:24:40 +0400
+Subject: [PATCH 21/27] mtd: m25p80: Add support for CAT25xxx serial EEPROMs
+
+CAT25 chips (as manufactured by On Semiconductor, previously Catalyst
+Semiconductor) are similar to the original M25Px0 chips, except:
+
+- Address width can vary (1-2 bytes, in contrast to 3 bytes in M25P
+ chips). So, implement convenient m25p_addr2cmd() and m25p_cmdsz()
+ calls, and place address width information into flash_info struct;
+
+- Page size can vary, therefore we shouldn't hardcode it, so get rid
+ of FLASH_PAGESIZE definition, and place the page size information
+ into flash_info struct;
+
+- CAT25 EEPROMs don't need to be erased, so add NO_ERASE flag, and
+ propagate it to the mtd subsystem.
+
+[dwmw2: Fix up for conflicts with DMA safety patch]
+Signed-off-by: Anton Vorontsov <avorontsov@ru.mvista.com>
+Signed-off-by: David Woodhouse <David.Woodhouse@intel.com>
+(cherry picked from commit 837479d25e221ba616de2c734f58e1decd8cdb95)
+
+Conflicts:
+ drivers/mtd/devices/m25p80.c
+---
+ drivers/mtd/devices/m25p80.c | 124 +++++++++++++++++++++++++------------------
+ 1 file changed, 72 insertions(+), 52 deletions(-)
+
+diff --git a/drivers/mtd/devices/m25p80.c b/drivers/mtd/devices/m25p80.c
+index 7ca5ab1..4570bc3 100644
+--- a/drivers/mtd/devices/m25p80.c
++++ b/drivers/mtd/devices/m25p80.c
+@@ -28,9 +28,6 @@
+ #include <linux/spi/spi.h>
+ #include <linux/spi/flash.h>
+
+-
+-#define FLASH_PAGESIZE 256
+-
+ /* Flash opcodes. */
+ #define OPCODE_WREN 0x06 /* Write enable */
+ #define OPCODE_RDSR 0x05 /* Read status register */
+@@ -60,7 +57,7 @@
+
+ /* Define max times to check status register before we give up. */
+ #define MAX_READY_WAIT_JIFFIES (40 * HZ) /* M25P16 specs 40s max chip erase */
+-#define CMD_SIZE 4
++#define MAX_CMD_SIZE 4
+
+ #ifdef CONFIG_M25PXX_USE_FAST_READ
+ #define OPCODE_READ OPCODE_FAST_READ
+@@ -83,6 +80,8 @@ struct m25p {
+ struct mutex lock;
+ struct mtd_info mtd;
+ unsigned partitioned:1;
++ u16 page_size;
++ u16 addr_width;
+ u8 erase_opcode;
+ u8 *command;
+ };
+@@ -203,6 +202,19 @@ static int erase_chip(struct m25p *flash)
+ return 0;
+ }
+
++static void m25p_addr2cmd(struct m25p *flash, unsigned int addr, u8 *cmd)
++{
++ /* opcode is in cmd[0] */
++ cmd[1] = addr >> (flash->addr_width * 8 - 8);
++ cmd[2] = addr >> (flash->addr_width * 8 - 16);
++ cmd[3] = addr >> (flash->addr_width * 8 - 24);
++}
++
++static int m25p_cmdsz(struct m25p *flash)
++{
++ return 1 + flash->addr_width;
++}
++
+ /*
+ * Erase one sector of flash memory at offset ``offset'' which is any
+ * address within the sector which should be erased.
+@@ -224,11 +236,9 @@ static int erase_sector(struct m25p *flash, u32 offset)
+
+ /* Set up command buffer. */
+ flash->command[0] = flash->erase_opcode;
+- flash->command[1] = offset >> 16;
+- flash->command[2] = offset >> 8;
+- flash->command[3] = offset;
++ m25p_addr2cmd(flash, offset, flash->command);
+
+- spi_write(flash->spi, flash->command, CMD_SIZE);
++ spi_write(flash->spi, flash->command, m25p_cmdsz(flash));
+
+ return 0;
+ }
+@@ -330,7 +340,7 @@ static int m25p80_read(struct mtd_info *mtd, loff_t from, size_t len,
+ * Should add 1 byte DUMMY_BYTE.
+ */
+ t[0].tx_buf = flash->command;
+- t[0].len = CMD_SIZE + FAST_READ_DUMMY_BYTE;
++ t[0].len = m25p_cmdsz(flash) + FAST_READ_DUMMY_BYTE;
+ spi_message_add_tail(&t[0], &m);
+
+ t[1].rx_buf = buf;
+@@ -357,13 +367,11 @@ static int m25p80_read(struct mtd_info *mtd, loff_t from, size_t len,
+
+ /* Set up the write data buffer. */
+ flash->command[0] = OPCODE_READ;
+- flash->command[1] = from >> 16;
+- flash->command[2] = from >> 8;
+- flash->command[3] = from;
++ m25p_addr2cmd(flash, from, flash->command);
+
+ spi_sync(flash->spi, &m);
+
+- *retlen = m.actual_length - CMD_SIZE - FAST_READ_DUMMY_BYTE;
++ *retlen = m.actual_length - m25p_cmdsz(flash) - FAST_READ_DUMMY_BYTE;
+
+ mutex_unlock(&flash->lock);
+
+@@ -401,7 +409,7 @@ static int m25p80_write(struct mtd_info *mtd, loff_t to, size_t len,
+ memset(t, 0, (sizeof t));
+
+ t[0].tx_buf = flash->command;
+- t[0].len = CMD_SIZE;
++ t[0].len = m25p_cmdsz(flash);
+ spi_message_add_tail(&t[0], &m);
+
+ t[1].tx_buf = buf;
+@@ -419,41 +427,36 @@ static int m25p80_write(struct mtd_info *mtd, loff_t to, size_t len,
+
+ /* Set up the opcode in the write buffer. */
+ flash->command[0] = OPCODE_PP;
+- flash->command[1] = to >> 16;
+- flash->command[2] = to >> 8;
+- flash->command[3] = to;
++ m25p_addr2cmd(flash, to, flash->command);
+
+- /* what page do we start with? */
+- page_offset = to % FLASH_PAGESIZE;
++ page_offset = to & (flash->page_size - 1);
+
+ /* do all the bytes fit onto one page? */
+- if (page_offset + len <= FLASH_PAGESIZE) {
++ if (page_offset + len <= flash->page_size) {
+ t[1].len = len;
+
+ spi_sync(flash->spi, &m);
+
+- *retlen = m.actual_length - CMD_SIZE;
++ *retlen = m.actual_length - m25p_cmdsz(flash);
+ } else {
+ u32 i;
+
+ /* the size of data remaining on the first page */
+- page_size = FLASH_PAGESIZE - page_offset;
++ page_size = flash->page_size - page_offset;
+
+ t[1].len = page_size;
+ spi_sync(flash->spi, &m);
+
+- *retlen = m.actual_length - CMD_SIZE;
++ *retlen = m.actual_length - m25p_cmdsz(flash);
+
+- /* write everything in PAGESIZE chunks */
++ /* write everything in flash->page_size chunks */
+ for (i = page_size; i < len; i += page_size) {
+ page_size = len - i;
+- if (page_size > FLASH_PAGESIZE)
+- page_size = FLASH_PAGESIZE;
++ if (page_size > flash->page_size)
++ page_size = flash->page_size;
+
+ /* write the next page to flash */
+- flash->command[1] = (to + i) >> 16;
+- flash->command[2] = (to + i) >> 8;
+- flash->command[3] = (to + i);
++ m25p_addr2cmd(flash, to + i, flash->command);
+
+ t[1].tx_buf = buf + i;
+ t[1].len = page_size;
+@@ -465,7 +468,7 @@ static int m25p80_write(struct mtd_info *mtd, loff_t to, size_t len,
+ spi_sync(flash->spi, &m);
+
+ if (retlen)
+- *retlen += m.actual_length - CMD_SIZE;
++ *retlen += m.actual_length - m25p_cmdsz(flash);
+ }
+ }
+
+@@ -497,7 +500,7 @@ static int sst_write(struct mtd_info *mtd, loff_t to, size_t len,
+ memset(t, 0, (sizeof t));
+
+ t[0].tx_buf = flash->command;
+- t[0].len = CMD_SIZE;
++ t[0].len = m25p_cmdsz(flash);
+ spi_message_add_tail(&t[0], &m);
+
+ t[1].tx_buf = buf;
+@@ -516,9 +519,7 @@ static int sst_write(struct mtd_info *mtd, loff_t to, size_t len,
+ /* Start write from odd address. */
+ if (actual) {
+ flash->command[0] = OPCODE_BP;
+- flash->command[1] = to >> 16;
+- flash->command[2] = to >> 8;
+- flash->command[3] = to;
++ m25p_addr2cmd(flash, to, flash->command);
+
+ /* write one byte. */
+ t[1].len = 1;
+@@ -526,17 +527,15 @@ static int sst_write(struct mtd_info *mtd, loff_t to, size_t len,
+ ret = wait_till_ready(flash);
+ if (ret)
+ goto time_out;
+- *retlen += m.actual_length - CMD_SIZE;
++ *retlen += m.actual_length - m25p_cmdsz(flash);
+ }
+ to += actual;
+
+ flash->command[0] = OPCODE_AAI_WP;
+- flash->command[1] = to >> 16;
+- flash->command[2] = to >> 8;
+- flash->command[3] = to;
++ m25p_addr2cmd(flash, to, flash->command);
+
+ /* Write out most of the data here. */
+- cmd_sz = CMD_SIZE;
++ cmd_sz = m25p_cmdsz(flash);
+ for (; actual < len - 1; actual += 2) {
+ t[0].len = cmd_sz;
+ /* write two bytes. */
+@@ -560,10 +559,8 @@ static int sst_write(struct mtd_info *mtd, loff_t to, size_t len,
+ if (actual != len) {
+ write_enable(flash);
+ flash->command[0] = OPCODE_BP;
+- flash->command[1] = to >> 16;
+- flash->command[2] = to >> 8;
+- flash->command[3] = to;
+- t[0].len = CMD_SIZE;
++ m25p_addr2cmd(flash, to, flash->command);
++ t[0].len = m25p_cmdsz(flash);
+ t[1].len = 1;
+ t[1].tx_buf = buf + actual;
+
+@@ -571,7 +568,7 @@ static int sst_write(struct mtd_info *mtd, loff_t to, size_t len,
+ ret = wait_till_ready(flash);
+ if (ret)
+ goto time_out;
+- *retlen += m.actual_length - CMD_SIZE;
++ *retlen += m.actual_length - m25p_cmdsz(flash);
+ write_disable(flash);
+ }
+
+@@ -602,10 +599,19 @@ struct flash_info {
+ unsigned sector_size;
+ u16 n_sectors;
+
++ u16 page_size;
++ u16 addr_width;
++
+ u16 flags;
+ #define SECT_4K 0x01 /* OPCODE_BE_4K works uniformly */
++#define M25P_NO_ERASE 0x02 /* No erase command needed */
+ };
+
++#define INFO(_jedec_id, _ext_id, _sector_size, _n_sectors, _flags) \
++ _jedec_id, _ext_id, _sector_size, _n_sectors, 256, 3, _flags
++
++#define CAT25_INFO(_sector_size, _n_sectors, _page_size, _addr_width) \
++ 0, 0, _sector_size, _n_sectors, _page_size, _addr_width, M25P_NO_ERASE
+
+ /* NOTE: double check command sets and memory organization when you add
+ * more flash chips. This current list focusses on newer chips, which
+@@ -660,13 +666,20 @@ static struct flash_info __devinitdata m25p_data [] = {
+ { "m25pe16", 0x208015, 0, 64 * 1024, 32, SECT_4K, },
+
+ /* Winbond -- w25x "blocks" are 64K, "sectors" are 4KiB */
+- { "w25x10", 0xef3011, 0, 64 * 1024, 2, SECT_4K, },
+- { "w25x20", 0xef3012, 0, 64 * 1024, 4, SECT_4K, },
+- { "w25x40", 0xef3013, 0, 64 * 1024, 8, SECT_4K, },
+- { "w25x80", 0xef3014, 0, 64 * 1024, 16, SECT_4K, },
+- { "w25x16", 0xef3015, 0, 64 * 1024, 32, SECT_4K, },
+- { "w25x32", 0xef3016, 0, 64 * 1024, 64, SECT_4K, },
+- { "w25x64", 0xef3017, 0, 64 * 1024, 128, SECT_4K, },
++ { "w25x10", INFO(0xef3011, 0, 64 * 1024, 2, SECT_4K) },
++ { "w25x20", INFO(0xef3012, 0, 64 * 1024, 4, SECT_4K) },
++ { "w25x40", INFO(0xef3013, 0, 64 * 1024, 8, SECT_4K) },
++ { "w25x80", INFO(0xef3014, 0, 64 * 1024, 16, SECT_4K) },
++ { "w25x16", INFO(0xef3015, 0, 64 * 1024, 32, SECT_4K) },
++ { "w25x32", INFO(0xef3016, 0, 64 * 1024, 64, SECT_4K) },
++ { "w25x64", INFO(0xef3017, 0, 64 * 1024, 128, SECT_4K) },
++
++ /* Catalyst / On Semiconductor -- non-JEDEC */
++ { "cat25c11", CAT25_INFO( 16, 8, 16, 1) },
++ { "cat25c03", CAT25_INFO( 32, 8, 16, 2) },
++ { "cat25c09", CAT25_INFO( 128, 8, 32, 2) },
++ { "cat25c17", CAT25_INFO( 256, 8, 32, 2) },
++ { "cat25128", CAT25_INFO(2048, 8, 64, 2) },
+ };
+
+ static struct flash_info *__devinit jedec_probe(struct spi_device *spi)
+@@ -762,7 +776,7 @@ static int __devinit m25p_probe(struct spi_device *spi)
+ flash = kzalloc(sizeof *flash, GFP_KERNEL);
+ if (!flash)
+ return -ENOMEM;
+- flash->command = kmalloc(CMD_SIZE + FAST_READ_DUMMY_BYTE, GFP_KERNEL);
++ flash->command = kmalloc(MAX_CMD_SIZE + FAST_READ_DUMMY_BYTE, GFP_KERNEL);
+ if (!flash->command) {
+ kfree(flash);
+ return -ENOMEM;
+@@ -809,6 +823,12 @@ static int __devinit m25p_probe(struct spi_device *spi)
+ flash->mtd.erasesize = info->sector_size;
+ }
+
++ if (info->flags & M25P_NO_ERASE)
++ flash->mtd.flags |= MTD_NO_ERASE;
++
++ flash->page_size = info->page_size;
++ flash->addr_width = info->addr_width;
++
+ dev_info(&spi->dev, "%s (%lld Kbytes)\n", info->name,
+ (long long)flash->mtd.size >> 10);
+
+--
+1.8.1
+
diff --git a/meta-aspeed/recipes-kernel/linux/files/patch-2.6.28.9/0022-mtd-m25p80-Add-support-for-Macronix-MX25L25635E.patch b/meta-aspeed/recipes-kernel/linux/files/patch-2.6.28.9/0022-mtd-m25p80-Add-support-for-Macronix-MX25L25635E.patch
new file mode 100644
index 0000000..cafc35a
--- /dev/null
+++ b/meta-aspeed/recipes-kernel/linux/files/patch-2.6.28.9/0022-mtd-m25p80-Add-support-for-Macronix-MX25L25635E.patch
@@ -0,0 +1,99 @@
+From a67b440516ccdfac57df3a79f1a89234cd5e9948 Mon Sep 17 00:00:00 2001
+From: Kevin Cernekee <cernekee@gmail.com>
+Date: Sat, 30 Oct 2010 21:11:03 -0700
+Subject: [PATCH 22/27] mtd: m25p80: Add support for Macronix MX25L25635E
+
+This is a 256Mbit (32MiB) part so minor changes were made to support
+4-byte addressing.
+
+Signed-off-by: Kevin Cernekee <cernekee@gmail.com>
+Signed-off-by: Artem Bityutskiy <Artem.Bityutskiy@nokia.com>
+Signed-off-by: David Woodhouse <David.Woodhouse@intel.com>
+(cherry picked from commit 4b7f7422b0331e802f8b7c593e058ccee981cff5)
+
+Conflicts:
+ drivers/mtd/devices/m25p80.c
+---
+ drivers/mtd/devices/m25p80.c | 31 ++++++++++++++++++++++++++++---
+ 1 file changed, 28 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/mtd/devices/m25p80.c b/drivers/mtd/devices/m25p80.c
+index 4570bc3..a6a28fc 100644
+--- a/drivers/mtd/devices/m25p80.c
++++ b/drivers/mtd/devices/m25p80.c
+@@ -46,6 +46,10 @@
+ #define OPCODE_WRDI 0x04 /* Write disable */
+ #define OPCODE_AAI_WP 0xad /* Auto address increment word program */
+
++/* Used for Macronix flashes only. */
++#define OPCODE_EN4B 0xb7 /* Enter 4-byte mode */
++#define OPCODE_EX4B 0xe9 /* Exit 4-byte mode */
++
+ /* Status Register bits. */
+ #define SR_WIP 1 /* Write in progress */
+ #define SR_WEL 2 /* Write enable latch */
+@@ -57,7 +61,7 @@
+
+ /* Define max times to check status register before we give up. */
+ #define MAX_READY_WAIT_JIFFIES (40 * HZ) /* M25P16 specs 40s max chip erase */
+-#define MAX_CMD_SIZE 4
++#define MAX_CMD_SIZE 5
+
+ #ifdef CONFIG_M25PXX_USE_FAST_READ
+ #define OPCODE_READ OPCODE_FAST_READ
+@@ -153,6 +157,16 @@ static inline int write_disable(struct m25p *flash)
+ }
+
+ /*
++ * Enable/disable 4-byte addressing mode.
++ */
++static inline int set_4byte(struct m25p *flash, int enable)
++{
++ u8 code = enable ? OPCODE_EN4B : OPCODE_EX4B;
++
++ return spi_write_then_read(flash->spi, &code, 1, NULL, 0);
++}
++
++/*
+ * Service routine to read status register until ready, or timeout occurs.
+ * Returns non-zero if error.
+ */
+@@ -208,6 +222,7 @@ static void m25p_addr2cmd(struct m25p *flash, unsigned int addr, u8 *cmd)
+ cmd[1] = addr >> (flash->addr_width * 8 - 8);
+ cmd[2] = addr >> (flash->addr_width * 8 - 16);
+ cmd[3] = addr >> (flash->addr_width * 8 - 24);
++ cmd[4] = addr >> (flash->addr_width * 8 - 32);
+ }
+
+ static int m25p_cmdsz(struct m25p *flash)
+@@ -608,7 +623,7 @@ struct flash_info {
+ };
+
+ #define INFO(_jedec_id, _ext_id, _sector_size, _n_sectors, _flags) \
+- _jedec_id, _ext_id, _sector_size, _n_sectors, 256, 3, _flags
++ _jedec_id, _ext_id, _sector_size, _n_sectors, 256, _flags
+
+ #define CAT25_INFO(_sector_size, _n_sectors, _page_size, _addr_width) \
+ 0, 0, _sector_size, _n_sectors, _page_size, _addr_width, M25P_NO_ERASE
+@@ -827,7 +842,17 @@ static int __devinit m25p_probe(struct spi_device *spi)
+ flash->mtd.flags |= MTD_NO_ERASE;
+
+ flash->page_size = info->page_size;
+- flash->addr_width = info->addr_width;
++
++ if (info->addr_width)
++ flash->addr_width = info->addr_width;
++ else {
++ /* enable 4-byte addressing if the device exceeds 16MiB */
++ if (flash->mtd.size > 0x1000000) {
++ flash->addr_width = 4;
++ set_4byte(flash, 1);
++ } else
++ flash->addr_width = 3;
++ }
+
+ dev_info(&spi->dev, "%s (%lld Kbytes)\n", info->name,
+ (long long)flash->mtd.size >> 10);
+--
+1.8.1
+
diff --git a/meta-aspeed/recipes-kernel/linux/files/patch-2.6.28.9/0023-mtd-m25p80-Add-support-for-Macronix-MX25L25655E.patch b/meta-aspeed/recipes-kernel/linux/files/patch-2.6.28.9/0023-mtd-m25p80-Add-support-for-Macronix-MX25L25655E.patch
new file mode 100644
index 0000000..31aa2bb
--- /dev/null
+++ b/meta-aspeed/recipes-kernel/linux/files/patch-2.6.28.9/0023-mtd-m25p80-Add-support-for-Macronix-MX25L25655E.patch
@@ -0,0 +1,72 @@
+From 382791c9efc03015575bc1f5552ebb7004f1610f Mon Sep 17 00:00:00 2001
+From: Kevin Cernekee <cernekee@gmail.com>
+Date: Sat, 30 Oct 2010 21:11:04 -0700
+Subject: [PATCH 23/27] mtd: m25p80: Add support for Macronix MX25L25655E
+
+Untested, but expected to be compatible with MX25L25635E which I did
+test.
+
+Signed-off-by: Kevin Cernekee <cernekee@gmail.com>
+Signed-off-by: Artem Bityutskiy <Artem.Bityutskiy@nokia.com>
+Signed-off-by: David Woodhouse <David.Woodhouse@intel.com>
+(cherry picked from commit ac622f583dccb025250becd2d4e60badaf571713)
+
+Conflicts:
+ drivers/mtd/devices/m25p80.c
+---
+ drivers/mtd/devices/m25p80.c | 39 +++++++++++++++++++++++++++++----------
+ 1 file changed, 29 insertions(+), 10 deletions(-)
+
+diff --git a/drivers/mtd/devices/m25p80.c b/drivers/mtd/devices/m25p80.c
+index a6a28fc..4d8519e 100644
+--- a/drivers/mtd/devices/m25p80.c
++++ b/drivers/mtd/devices/m25p80.c
+@@ -635,16 +635,35 @@ struct flash_info {
+ static struct flash_info __devinitdata m25p_data [] = {
+
+ /* Atmel -- some are (confusingly) marketed as "DataFlash" */
+- { "at25fs010", 0x1f6601, 0, 32 * 1024, 4, SECT_4K, },
+- { "at25fs040", 0x1f6604, 0, 64 * 1024, 8, SECT_4K, },
+-
+- { "at25df041a", 0x1f4401, 0, 64 * 1024, 8, SECT_4K, },
+- { "at25df641", 0x1f4800, 0, 64 * 1024, 128, SECT_4K, },
+-
+- { "at26f004", 0x1f0400, 0, 64 * 1024, 8, SECT_4K, },
+- { "at26df081a", 0x1f4501, 0, 64 * 1024, 16, SECT_4K, },
+- { "at26df161a", 0x1f4601, 0, 64 * 1024, 32, SECT_4K, },
+- { "at26df321", 0x1f4701, 0, 64 * 1024, 64, SECT_4K, },
++ { "at25fs010", INFO(0x1f6601, 0, 32 * 1024, 4, SECT_4K) },
++ { "at25fs040", INFO(0x1f6604, 0, 64 * 1024, 8, SECT_4K) },
++
++ { "at25df041a", INFO(0x1f4401, 0, 64 * 1024, 8, SECT_4K) },
++ { "at25df641", INFO(0x1f4800, 0, 64 * 1024, 128, SECT_4K) },
++
++ { "at26f004", INFO(0x1f0400, 0, 64 * 1024, 8, SECT_4K) },
++ { "at26df081a", INFO(0x1f4501, 0, 64 * 1024, 16, SECT_4K) },
++ { "at26df161a", INFO(0x1f4601, 0, 64 * 1024, 32, SECT_4K) },
++ { "at26df321", INFO(0x1f4701, 0, 64 * 1024, 64, SECT_4K) },
++
++ /* EON -- en25pxx */
++ { "en25p32", INFO(0x1c2016, 0, 64 * 1024, 64, 0) },
++ { "en25p64", INFO(0x1c2017, 0, 64 * 1024, 128, 0) },
++
++ /* Intel/Numonyx -- xxxs33b */
++ { "160s33b", INFO(0x898911, 0, 64 * 1024, 32, 0) },
++ { "320s33b", INFO(0x898912, 0, 64 * 1024, 64, 0) },
++ { "640s33b", INFO(0x898913, 0, 64 * 1024, 128, 0) },
++
++ /* Macronix */
++ { "mx25l4005a", INFO(0xc22013, 0, 64 * 1024, 8, SECT_4K) },
++ { "mx25l8005", INFO(0xc22014, 0, 64 * 1024, 16, 0) },
++ { "mx25l3205d", INFO(0xc22016, 0, 64 * 1024, 64, 0) },
++ { "mx25l6405d", INFO(0xc22017, 0, 64 * 1024, 128, 0) },
++ { "mx25l12805d", INFO(0xc22018, 0, 64 * 1024, 256, 0) },
++ { "mx25l12855e", INFO(0xc22618, 0, 64 * 1024, 256, 0) },
++ { "mx25l25635e", INFO(0xc22019, 0, 64 * 1024, 512, 0) },
++ { "mx25l25655e", INFO(0xc22619, 0, 64 * 1024, 512, 0) },
+
+ /* Spansion -- single (large) sector size only, at least
+ * for the chips listed here (without boot sectors).
+--
+1.8.1
+
diff --git a/meta-aspeed/recipes-kernel/linux/files/patch-2.6.28.9/0024-mtd-m25p80-add-support-for-Micron-N25Q256A.patch b/meta-aspeed/recipes-kernel/linux/files/patch-2.6.28.9/0024-mtd-m25p80-add-support-for-Micron-N25Q256A.patch
new file mode 100644
index 0000000..903c70e
--- /dev/null
+++ b/meta-aspeed/recipes-kernel/linux/files/patch-2.6.28.9/0024-mtd-m25p80-add-support-for-Micron-N25Q256A.patch
@@ -0,0 +1,35 @@
+From 53700b905d75a021dae896a592aac834ef403b40 Mon Sep 17 00:00:00 2001
+From: Vivien Didelot <vivien.didelot@savoirfairelinux.com>
+Date: Tue, 14 Aug 2012 15:24:07 -0400
+Subject: [PATCH 24/27] mtd: m25p80: add support for Micron N25Q256A
+
+The manufacturer datasheet can be found on the Micron website,
+under the name n25q_256mb_3v_65nm.pdf:
+
+http://www.micron.com/search?source=ps&q=n25q_256mb_3v_65nm
+
+Signed-off-by: Vivien Didelot <vivien.didelot@savoirfairelinux.com>
+Signed-off-by: Artem Bityutskiy <artem.bityutskiy@linux.intel.com>
+Signed-off-by: David Woodhouse <David.Woodhouse@intel.com>
+(cherry picked from commit 8da28681eb1430fb6715c7aef67001acfbbbcba5)
+---
+ drivers/mtd/devices/m25p80.c | 3 +++
+ 1 file changed, 3 insertions(+)
+
+diff --git a/drivers/mtd/devices/m25p80.c b/drivers/mtd/devices/m25p80.c
+index 4d8519e..caacfb7 100644
+--- a/drivers/mtd/devices/m25p80.c
++++ b/drivers/mtd/devices/m25p80.c
+@@ -665,6 +665,9 @@ static struct flash_info __devinitdata m25p_data [] = {
+ { "mx25l25635e", INFO(0xc22019, 0, 64 * 1024, 512, 0) },
+ { "mx25l25655e", INFO(0xc22619, 0, 64 * 1024, 512, 0) },
+
++ /* Micron */
++ { "n25q256a", INFO(0x20ba19, 0, 64 * 1024, 512, SECT_4K) },
++
+ /* Spansion -- single (large) sector size only, at least
+ * for the chips listed here (without boot sectors).
+ */
+--
+1.8.1
+
diff --git a/meta-aspeed/recipes-kernel/linux/files/patch-2.6.28.9/0025-mtd-m25p80-add-support-for-Micron-N25Q128.patch b/meta-aspeed/recipes-kernel/linux/files/patch-2.6.28.9/0025-mtd-m25p80-add-support-for-Micron-N25Q128.patch
new file mode 100644
index 0000000..dd09ad3
--- /dev/null
+++ b/meta-aspeed/recipes-kernel/linux/files/patch-2.6.28.9/0025-mtd-m25p80-add-support-for-Micron-N25Q128.patch
@@ -0,0 +1,28 @@
+From ba11b987123391b8d74c6e640df22248f3404cb5 Mon Sep 17 00:00:00 2001
+From: Jan Luebbe <jlu@pengutronix.de>
+Date: Fri, 24 Aug 2012 18:23:50 +0200
+Subject: [PATCH 25/27] mtd: m25p80: add support for Micron N25Q128
+
+Signed-off-by: Jan Luebbe <jlu@pengutronix.de>
+Signed-off-by: Artem Bityutskiy <artem.bityutskiy@linux.intel.com>
+Signed-off-by: David Woodhouse <David.Woodhouse@intel.com>
+(cherry picked from commit 3105875f6b8902628caee2fd7821af43707c6bde)
+---
+ drivers/mtd/devices/m25p80.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/drivers/mtd/devices/m25p80.c b/drivers/mtd/devices/m25p80.c
+index caacfb7..380c368 100644
+--- a/drivers/mtd/devices/m25p80.c
++++ b/drivers/mtd/devices/m25p80.c
+@@ -666,6 +666,7 @@ static struct flash_info __devinitdata m25p_data [] = {
+ { "mx25l25655e", INFO(0xc22619, 0, 64 * 1024, 512, 0) },
+
+ /* Micron */
++ { "n25q128", INFO(0x20ba18, 0, 64 * 1024, 256, 0) },
+ { "n25q256a", INFO(0x20ba19, 0, 64 * 1024, 512, SECT_4K) },
+
+ /* Spansion -- single (large) sector size only, at least
+--
+1.8.1
+
diff --git a/meta-aspeed/recipes-kernel/linux/files/patch-2.6.28.9/0026-mtd-m25p80-modify-info-for-Micron-N25Q128.patch b/meta-aspeed/recipes-kernel/linux/files/patch-2.6.28.9/0026-mtd-m25p80-modify-info-for-Micron-N25Q128.patch
new file mode 100644
index 0000000..5b204dc
--- /dev/null
+++ b/meta-aspeed/recipes-kernel/linux/files/patch-2.6.28.9/0026-mtd-m25p80-modify-info-for-Micron-N25Q128.patch
@@ -0,0 +1,39 @@
+From c1fdbfe2f6ee26651b626603d47a1499c0fd87e8 Mon Sep 17 00:00:00 2001
+From: Liming Wang <walimisdev@gmail.com>
+Date: Thu, 22 Nov 2012 14:58:09 +0800
+Subject: [PATCH 26/27] mtd: m25p80: modify info for Micron N25Q128
+
+Micron N25Q128 has two types of flash:
+
+ - One is for 1.8v supply voltage, prefixed with "n25q128a11" and the jedec
+ code is 0x20bb18.
+
+ - Another is for 3v supply voltage, prefixed with "n25q128a13" and the jedec
+ code is 0x20ba18.
+
+So modify the original type info and add another type for Micron N25Q128.
+
+Signed-off-by: Liming Wang <walimisdev@gmail.com>
+Signed-off-by: Artem Bityutskiy <artem.bityutskiy@linux.intel.com>
+(cherry picked from commit 98a9e2450667e497246449f96eab06eb3fb4d24b)
+---
+ drivers/mtd/devices/m25p80.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/mtd/devices/m25p80.c b/drivers/mtd/devices/m25p80.c
+index 380c368..19a4325 100644
+--- a/drivers/mtd/devices/m25p80.c
++++ b/drivers/mtd/devices/m25p80.c
+@@ -666,7 +666,8 @@ static struct flash_info __devinitdata m25p_data [] = {
+ { "mx25l25655e", INFO(0xc22619, 0, 64 * 1024, 512, 0) },
+
+ /* Micron */
+- { "n25q128", INFO(0x20ba18, 0, 64 * 1024, 256, 0) },
++ { "n25q128a11", INFO(0x20bb18, 0, 64 * 1024, 256, 0) },
++ { "n25q128a13", INFO(0x20ba18, 0, 64 * 1024, 256, 0) },
+ { "n25q256a", INFO(0x20ba19, 0, 64 * 1024, 512, SECT_4K) },
+
+ /* Spansion -- single (large) sector size only, at least
+--
+1.8.1
+
diff --git a/meta-aspeed/recipes-kernel/linux/files/patch-2.6.28.9/0027-mtd-m25p80-n25q064-is-Micron-not-Intel-Numonyx.patch b/meta-aspeed/recipes-kernel/linux/files/patch-2.6.28.9/0027-mtd-m25p80-n25q064-is-Micron-not-Intel-Numonyx.patch
new file mode 100644
index 0000000..66ab70b
--- /dev/null
+++ b/meta-aspeed/recipes-kernel/linux/files/patch-2.6.28.9/0027-mtd-m25p80-n25q064-is-Micron-not-Intel-Numonyx.patch
@@ -0,0 +1,29 @@
+From 865453236765126bc0751c35c0c0e5ea5b56f668 Mon Sep 17 00:00:00 2001
+From: Brian Norris <computersforpeace@gmail.com>
+Date: Fri, 22 Feb 2013 14:07:22 -0800
+Subject: [PATCH 27/27] mtd: m25p80: n25q064 is Micron, not Intel/Numonyx
+
+Signed-off-by: Brian Norris <computersforpeace@gmail.com>
+Acked-by: Peter Korsgaard <jacmet@sunsite.dk>
+Signed-off-by: Artem Bityutskiy <artem.bityutskiy@linux.intel.com>
+Signed-off-by: David Woodhouse <David.Woodhouse@intel.com>
+(cherry picked from commit e66e280c36e09e4573089862e7dc2ade9e680088)
+---
+ drivers/mtd/devices/m25p80.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/drivers/mtd/devices/m25p80.c b/drivers/mtd/devices/m25p80.c
+index 19a4325..5659b62 100644
+--- a/drivers/mtd/devices/m25p80.c
++++ b/drivers/mtd/devices/m25p80.c
+@@ -666,6 +666,7 @@ static struct flash_info __devinitdata m25p_data [] = {
+ { "mx25l25655e", INFO(0xc22619, 0, 64 * 1024, 512, 0) },
+
+ /* Micron */
++ { "n25q064", INFO(0x20ba17, 0, 64 * 1024, 128, 0) },
+ { "n25q128a11", INFO(0x20bb18, 0, 64 * 1024, 256, 0) },
+ { "n25q128a13", INFO(0x20ba18, 0, 64 * 1024, 256, 0) },
+ { "n25q256a", INFO(0x20ba19, 0, 64 * 1024, 512, SECT_4K) },
+--
+1.8.1
+
diff --git a/meta-aspeed/recipes-kernel/linux/files/patch-2.6.28.9/0028-ipv6-Plug-sk_buff-leak-in-ipv6_rcv-net-ipv6-ip6_inpu.patch b/meta-aspeed/recipes-kernel/linux/files/patch-2.6.28.9/0028-ipv6-Plug-sk_buff-leak-in-ipv6_rcv-net-ipv6-ip6_inpu.patch
new file mode 100644
index 0000000..2ab10b6
--- /dev/null
+++ b/meta-aspeed/recipes-kernel/linux/files/patch-2.6.28.9/0028-ipv6-Plug-sk_buff-leak-in-ipv6_rcv-net-ipv6-ip6_inpu.patch
@@ -0,0 +1,52 @@
+From 71f6f6dfdf7c7a67462386d9ea05c1095a89c555 Mon Sep 17 00:00:00 2001
+From: Jesper Nilsson <jesper.nilsson@axis.com>
+Date: Fri, 27 Mar 2009 00:17:45 -0700
+Subject: [PATCH] ipv6: Plug sk_buff leak in ipv6_rcv (net/ipv6/ip6_input.c)
+
+Commit 778d80be52699596bf70e0eb0761cf5e1e46088d
+(ipv6: Add disable_ipv6 sysctl to disable IPv6 operaion on specific interface)
+seems to have introduced a leak of sk_buff's for ipv6 traffic,
+at least in some configurations where idev is NULL, or when ipv6
+is disabled via sysctl.
+
+The problem is that if the first condition of the if-statement
+returns non-NULL, it returns an skb with only one reference,
+and when the other conditions apply, execution jumps to the "out"
+label, which does not call kfree_skb for it.
+
+To plug this leak, change to use the "drop" label instead.
+(this relies on it being ok to call kfree_skb on NULL)
+This also allows us to avoid calling rcu_read_unlock here,
+and removes the only user of the "out" label.
+
+Signed-off-by: Jesper Nilsson <jesper.nilsson@axis.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+---
+ net/ipv6/ip6_input.c | 4 +---
+ 1 file changed, 1 insertion(+), 3 deletions(-)
+
+diff --git a/net/ipv6/ip6_input.c b/net/ipv6/ip6_input.c
+index f171e8d..8f04bd9 100644
+--- a/net/ipv6/ip6_input.c
++++ b/net/ipv6/ip6_input.c
+@@ -75,8 +75,7 @@ int ipv6_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt
+ if ((skb = skb_share_check(skb, GFP_ATOMIC)) == NULL ||
+ !idev || unlikely(idev->cnf.disable_ipv6)) {
+ IP6_INC_STATS_BH(net, idev, IPSTATS_MIB_INDISCARDS);
+- rcu_read_unlock();
+- goto out;
++ goto drop;
+ }
+
+ memset(IP6CB(skb), 0, sizeof(struct inet6_skb_parm));
+@@ -147,7 +146,6 @@ err:
+ drop:
+ rcu_read_unlock();
+ kfree_skb(skb);
+-out:
+ return 0;
+ }
+
+--
+1.8.1
+
diff --git a/meta-aspeed/recipes-kernel/linux/files/patch-2.6.28.9/README b/meta-aspeed/recipes-kernel/linux/files/patch-2.6.28.9/README
new file mode 100644
index 0000000..b237814
--- /dev/null
+++ b/meta-aspeed/recipes-kernel/linux/files/patch-2.6.28.9/README
@@ -0,0 +1 @@
+Patches cherry picked from 2.6.32.41, mostly for the erase timeout issue.
diff --git a/meta-aspeed/recipes-kernel/linux/linux-aspeed.inc b/meta-aspeed/recipes-kernel/linux/linux-aspeed.inc
new file mode 100644
index 0000000..a66c7e1
--- /dev/null
+++ b/meta-aspeed/recipes-kernel/linux/linux-aspeed.inc
@@ -0,0 +1,31 @@
+
+DESCRIPTION = "Linux Kernel for Aspeed"
+SECTION = "kernel"
+LICENSE = "GPLv2"
+LIC_FILES_CHKSUM = "file://COPYING;md5=d7810fab7487fb0aad327b76f1be7cd7"
+
+COMPATIBLE_MACHINE = "aspeed"
+
+do_compile[depends] = "libgcc:do_populate_sysroot"
+
+inherit kernel
+
+# auto load the following modules
+module_autoload_tun = "tun"
+module_autoload_at24 = "at24"
+module_autoload_ads7828 = "ads7828"
+module_autoload_pcf8574 = "pcf8574"
+module_autoload_max127 = "max127"
+module_conf_max127 = "options max127 scaling=24414"
+module_autoload_pmbus_core = "pmbus_core"
+module_autoload_pfe1100 = "pfe1100"
+module_autoload_fb_panther_plus = "fb_panther_plus"
+module_autoload_adm1275 = "adm1275"
+
+# Do not install kernel in rootfs
+do_install[postfuncs] += "remove_kernel_image_from_rootfs"
+remove_kernel_image_from_rootfs() {
+ rm -rf ${D}/boot/uImage*
+}
+pkg_postinst_kernel-image() {
+}
diff --git a/meta-aspeed/recipes-kernel/linux/linux-aspeed_2.6.28.9.bb b/meta-aspeed/recipes-kernel/linux/linux-aspeed_2.6.28.9.bb
new file mode 100644
index 0000000..077e21b
--- /dev/null
+++ b/meta-aspeed/recipes-kernel/linux/linux-aspeed_2.6.28.9.bb
@@ -0,0 +1,39 @@
+
+# This revision corresponds to the tag "v2.6.28.9"
+# We use the revision in order to avoid having to fetch it from the repo during parse
+SRCREV = "1e85856853e24e9013d142adaad38c2adc7e48ac"
+
+PV = "2.6.28.9"
+
+SRC_URI = "git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable.git;protocol=https;branch=linux-2.6.28.y \
+ file://patch-2.6.28.9/0000-linux-aspeed-064.patch \
+ file://patch-2.6.28.9/0000-linux-openbmc.patch \
+ file://patch-2.6.28.9/0001-MTD-fix-m25p80-64-bit-divisions.patch \
+ file://patch-2.6.28.9/0005-mtd-Bug-in-m25p80.c-during-whole-chip-erase.patch \
+ file://patch-2.6.28.9/0006-mtd-fix-timeout-in-M25P80-driver.patch \
+ file://patch-2.6.28.9/0009-mtd-m25p80-timeout-too-short-for-worst-case-m25p16-d.patch \
+ file://patch-2.6.28.9/0010-mtd-m25p80-fix-null-pointer-dereference-bug.patch \
+ file://patch-2.6.28.9/0012-mtd-m25p80-add-support-for-AAI-programming-with-SST-.patch \
+ file://patch-2.6.28.9/0020-mtd-m25p80-make-command-buffer-DMA-safe.patch \
+ file://patch-2.6.28.9/0021-mtd-m25p80-Add-support-for-CAT25xxx-serial-EEPROMs.patch \
+ file://patch-2.6.28.9/0022-mtd-m25p80-Add-support-for-Macronix-MX25L25635E.patch \
+ file://patch-2.6.28.9/0023-mtd-m25p80-Add-support-for-Macronix-MX25L25655E.patch \
+ file://patch-2.6.28.9/0024-mtd-m25p80-add-support-for-Micron-N25Q256A.patch \
+ file://patch-2.6.28.9/0025-mtd-m25p80-add-support-for-Micron-N25Q128.patch \
+ file://patch-2.6.28.9/0026-mtd-m25p80-modify-info-for-Micron-N25Q128.patch \
+ file://patch-2.6.28.9/0027-mtd-m25p80-n25q064-is-Micron-not-Intel-Numonyx.patch \
+ file://patch-2.6.28.9/0028-ipv6-Plug-sk_buff-leak-in-ipv6_rcv-net-ipv6-ip6_inpu.patch \
+ file://patch-2.6.28.9/0001-bzip2-lzma-library-support-for-gzip-bzip2-and-lzma-d.patch \
+ file://patch-2.6.28.9/0002-bzip2-lzma-config-and-initramfs-support-for-bzip2-lz.patch \
+ "
+
+S = "${WORKDIR}/git"
+
+LINUX_VERSION = "2.6.28.9"
+LINUX_VERSION_EXTENSION ?= "-aspeed"
+
+PR = "r1"
+
+KERNEL_CONFIG_COMMAND = "oe_runmake wedge_defconfig && oe_runmake oldconfig"
+
+include linux-aspeed.inc
diff --git a/meta-facebook/COPYING b/meta-facebook/COPYING
new file mode 100644
index 0000000..3912109
--- /dev/null
+++ b/meta-facebook/COPYING
@@ -0,0 +1,340 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+ 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it. (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.) You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must show them these terms so they know their
+rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License. The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+ 1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+ 2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) You must cause the modified files to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ b) You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any
+ part thereof, to be licensed as a whole at no charge to all third
+ parties under the terms of this License.
+
+ c) If the modified program normally reads commands interactively
+ when run, you must cause it, when started running for such
+ interactive use in the most ordinary way, to print or display an
+ announcement including an appropriate copyright notice and a
+ notice that there is no warranty (or else, saying that you provide
+ a warranty) and that users may redistribute the program under
+ these conditions, and telling the user how to view a copy of this
+ License. (Exception: if the Program itself is interactive but
+ does not normally print such an announcement, your work based on
+ the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+ a) Accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of Sections
+ 1 and 2 above on a medium customarily used for software interchange; or,
+
+ b) Accompany it with a written offer, valid for at least three
+ years, to give any third party, for a charge no more than your
+ cost of physically performing source distribution, a complete
+ machine-readable copy of the corresponding source code, to be
+ distributed under the terms of Sections 1 and 2 above on a medium
+ customarily used for software interchange; or,
+
+ c) Accompany it with the information you received as to the offer
+ to distribute corresponding source code. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form with such
+ an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it. For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable. However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License. Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+ 5. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Program or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+ 6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all. For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded. In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+ 9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+ 10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+ Gnomovision version 69, Copyright (C) year name of author
+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+ `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+ <signature of Ty Coon>, 1 April 1989
+ Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs. If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library. If this is what you want to do, use the GNU Library General
+Public License instead of this License.
diff --git a/meta-facebook/meta-wedge/conf/bblayers.conf.sample b/meta-facebook/meta-wedge/conf/bblayers.conf.sample
new file mode 100644
index 0000000..e8b572a
--- /dev/null
+++ b/meta-facebook/meta-wedge/conf/bblayers.conf.sample
@@ -0,0 +1,21 @@
+# LAYER_CONF_VERSION is increased each time build/conf/bblayers.conf
+# changes incompatibly
+LCONF_VERSION = "6"
+
+BBPATH = "${TOPDIR}"
+BBFILES ?= ""
+
+BBLAYERS ?= " \
+ ##OEROOT##/meta \
+ ##OEROOT##/meta-yocto \
+ ##OEROOT##/meta-yocto-bsp \
+ ##OEROOT##/meta-openembedded/meta-oe \
+ ##OEROOT##/meta-openembedded/meta-networking \
+ ##OEROOT##/meta-openbmc \
+ ##OEROOT##/meta-openbmc/meta-aspeed \
+ ##OEROOT##/meta-openbmc/meta-facebook/meta-wedge \
+ "
+BBLAYERS_NON_REMOVABLE ?= " \
+ ##OEROOT##/meta \
+ ##OEROOT##/meta-yocto \
+ "
diff --git a/meta-facebook/meta-wedge/conf/conf-notes.txt b/meta-facebook/meta-wedge/conf/conf-notes.txt
new file mode 100644
index 0000000..ad3d503
--- /dev/null
+++ b/meta-facebook/meta-wedge/conf/conf-notes.txt
@@ -0,0 +1,2 @@
+Common targets are:
+ wedge-image
diff --git a/meta-facebook/meta-wedge/conf/layer.conf b/meta-facebook/meta-wedge/conf/layer.conf
new file mode 100644
index 0000000..630361f
--- /dev/null
+++ b/meta-facebook/meta-wedge/conf/layer.conf
@@ -0,0 +1,10 @@
+# We have a conf and classes directory, add to BBPATH
+BBPATH .= ":${LAYERDIR}"
+
+# We have recipes-* directories, add to BBFILES
+BBFILES += "${LAYERDIR}/recipes-*/*/*.bb \
+ ${LAYERDIR}/recipes-*/*/*.bbappend"
+
+BBFILE_COLLECTIONS += "wedge"
+BBFILE_PATTERN_wedge = "^${LAYERDIR}/"
+BBFILE_PRIORITY_wedge = "8"
diff --git a/meta-facebook/meta-wedge/conf/local.conf.sample b/meta-facebook/meta-wedge/conf/local.conf.sample
new file mode 100644
index 0000000..078ba23
--- /dev/null
+++ b/meta-facebook/meta-wedge/conf/local.conf.sample
@@ -0,0 +1,140 @@
+#
+# Local configuration file for building the OpenBMC image.
+#
+
+# Always look for packages first in our own local package mirror
+SOURCE_MIRROR_URL ?= "file://${TOPDIR}/../meta-openbmc/source_mirror/"
+INHERIT += "own-mirrors"
+
+# Save local tarballs for all packages we download.
+# This can be used to update our mirror directory above.
+BB_GENERATE_MIRROR_TARBALLS = "1"
+
+# The following setting will prevent bitbake from downloading anything over the
+# network. This can be used to ensure that we get everything from a local
+# file:// mirror.
+#
+# Comment this out if you do need to download new packages from the internet.
+# However, once you have downloaded the package you should check them into our
+# mirror repository so that other developers will always get it from the mirror
+# repo.
+BB_NO_NETWORK = "fb-only"
+
+# Parallelism Options
+#
+# How many tasks bitbake should run in parallel:
+BB_NUMBER_THREADS ?= "${@oe.utils.cpu_count()}"
+# How many processes make should run in parallel:
+PARALLEL_MAKE ?= "-j ${@oe.utils.cpu_count()}"
+
+# Machine Selection
+MACHINE ??= "wedge"
+
+# Build directory locationds.
+#
+#DL_DIR ?= "${TOPDIR}/downloads"
+#SSTATE_DIR ?= "${TOPDIR}/sstate-cache"
+#TMPDIR = "${TOPDIR}/tmp"
+
+#
+# Default policy config
+# We could eventually create our own distro config if desired,
+# but for now we use the standard poky distro settings.
+#
+DISTRO ?= "poky"
+
+# Use RPM packages
+PACKAGE_CLASSES ?= "package_rpm"
+
+# Extra image features.
+# Currently we do not enable anything extra here.
+#EXTRA_IMAGE_FEATURES = ""
+
+# We build on CentOS 6.3.
+# Don't complain about it, even though it isn't in poky's default
+# list of supported distros.
+SANITY_TESTED_DISTROS_append ?= " CentOS-6.3 \n "
+
+#
+# Additional image features
+#
+# The following is a list of additional classes to use when building images which
+# enable extra features. Some available options which can be included in this variable
+# are:
+# - 'buildstats' collect build statistics
+# - 'image-mklibs' to reduce shared library files size for an image
+# - 'image-prelink' in order to prelink the filesystem image
+# - 'image-swab' to perform host system intrusion detection
+# NOTE: if listing mklibs & prelink both, then make sure mklibs is before prelink
+# NOTE: mklibs also needs to be explicitly enabled for a given image, see local.conf.extended
+USER_CLASSES ?= "buildstats image-mklibs image-prelink"
+
+#
+# Interactive shell configuration
+#
+# Under certain circumstances the system may need input from you and to do this it
+# can launch an interactive shell. It needs to do this since the build is
+# multithreaded and needs to be able to handle the case where more than one parallel
+# process may require the user's attention. The default is iterate over the available
+# terminal types to find one that works.
+#
+# Examples of the occasions this may happen are when resolving patches which cannot
+# be applied, to use the devshell or the kernel menuconfig
+#
+# Supported values are auto, gnome, xfce, rxvt, screen, konsole (KDE 3.x only), none
+# Note: currently, Konsole support only works for KDE 3.x due to the way
+# newer Konsole versions behave
+#OE_TERMINAL = "auto"
+# By default disable interactive patch resolution (tasks will just fail instead):
+PATCHRESOLVE = "noop"
+
+#
+# Disk Space Monitoring during the build
+#
+# Monitor the disk space during the build. If there is less that 1GB of space or less
+# than 100K inodes in any key build location (TMPDIR, DL_DIR, SSTATE_DIR), gracefully
+# shutdown the build. If there is less that 100MB or 1K inodes, perform a hard abort
+# of the build. The reason for this is that running completely out of space can corrupt
+# files and damages the build in ways which may not be easily recoverable.
+BB_DISKMON_DIRS = "\
+ STOPTASKS,${TMPDIR},1G,100K \
+ STOPTASKS,${DL_DIR},1G,100K \
+ STOPTASKS,${SSTATE_DIR},1G,100K \
+ ABORT,${TMPDIR},100M,1K \
+ ABORT,${DL_DIR},100M,1K \
+ ABORT,${SSTATE_DIR},100M,1K"
+
+#
+# Shared-state files from other locations
+#
+# As mentioned above, shared state files are prebuilt cache data objects which can
+# used to accelerate build time. This variable can be used to configure the system
+# to search other mirror locations for these objects before it builds the data itself.
+#
+# This can be a filesystem directory, or a remote url such as http or ftp. These
+# would contain the sstate-cache results from previous builds (possibly from other
+# machines). This variable works like fetcher MIRRORS/PREMIRRORS and points to the
+# cache locations to check for the shared objects.
+# NOTE: if the mirror uses the same structure as SSTATE_DIR, you need to add PATH
+# at the end as shown in the examples below. This will be substituted with the
+# correct path within the directory structure.
+#SSTATE_MIRRORS ?= "\
+#file://.* http://someserver.tld/share/sstate/PATH;downloadfilename=PATH \n \
+#file://.* file:///some/local/dir/sstate/PATH"
+
+
+# CONF_VERSION is increased each time build/conf/ changes incompatibly and is used to
+# track the version of this file when it was generated. This can safely be ignored if
+# this doesn't mean anything to you.
+CONF_VERSION = "1"
+
+
+# Update root password to '0penBmc' and change the root shell back to bash.
+# This default root password is used at the ODM and system integrator. It will be
+# changed during provisioning at the datacenter.
+INHERIT += "extrausers"
+
+EXTRA_USERS_PARAMS = " \
+ usermod -s /bin/bash root; \
+ usermod -p '\$1\$UGMqyqdG\$FZiylVFmRRfl9Z0Ue8G7e/' root; \
+ "
diff --git a/meta-facebook/meta-wedge/conf/machine/wedge.conf b/meta-facebook/meta-wedge/conf/machine/wedge.conf
new file mode 100644
index 0000000..69f3a90
--- /dev/null
+++ b/meta-facebook/meta-wedge/conf/machine/wedge.conf
@@ -0,0 +1,7 @@
+#@TYPE: Machine
+#@NAME: Wedge
+#@DESCRIPTION: Machine configuration for Facebook Wedge
+
+UBOOT_MACHINE_wedge = "wedge_config"
+
+require conf/machine/include/ast1250.inc
diff --git a/meta-facebook/meta-wedge/recipes-core/busybox/busybox/busybox.cfg b/meta-facebook/meta-wedge/recipes-core/busybox/busybox/busybox.cfg
new file mode 100644
index 0000000..66da117
--- /dev/null
+++ b/meta-facebook/meta-wedge/recipes-core/busybox/busybox/busybox.cfg
@@ -0,0 +1,18 @@
+CONFIG_SH_MATH_SUPPORT_64=y
+CONFIG_DEVMEM=y
+CONFIG_LSUSB=y
+CONFIG_FEATURE_PS_ADDITIONAL_COLUMNS=y
+CONFIG_RX=y
+CONFIG_FLASHCP=y
+CONFIG_FLASH_LOCK=y
+CONFIG_FLASH_UNLOCK=y
+CONFIG_FLASH_ERASEALL=y
+CONFIG_TRACEROUTE6=y
+CONFIG_VCONFIG=y
+# we use the standalone ip util
+CONFIG_IP=n
+# use dhclient, as udhcpc will flush all v6 link local addresses during renew
+CONFIG_FEATURE_IFUPDOWN_EXTERNAL_DHCP=y
+CONFIG_UDHCPD=n
+CONFIG_UDHCPC=n
+CONFIG_UDHCPC6=n
diff --git a/meta-facebook/meta-wedge/recipes-core/busybox/busybox_%.bbappend b/meta-facebook/meta-wedge/recipes-core/busybox/busybox_%.bbappend
new file mode 100644
index 0000000..b8641ee
--- /dev/null
+++ b/meta-facebook/meta-wedge/recipes-core/busybox/busybox_%.bbappend
@@ -0,0 +1,5 @@
+FILESEXTRAPATHS_prepend := "${THISDIR}/${PN}:"
+
+SRC_URI += " \
+ file://busybox.cfg \
+ " \ No newline at end of file
diff --git a/meta-facebook/meta-wedge/recipes-core/images/wedge-image.bb b/meta-facebook/meta-wedge/recipes-core/images/wedge-image.bb
new file mode 100644
index 0000000..04c31f6
--- /dev/null
+++ b/meta-facebook/meta-wedge/recipes-core/images/wedge-image.bb
@@ -0,0 +1 @@
+include wedge-image.inc
diff --git a/meta-facebook/meta-wedge/recipes-core/images/wedge-image.inc b/meta-facebook/meta-wedge/recipes-core/images/wedge-image.inc
new file mode 100644
index 0000000..15a4252
--- /dev/null
+++ b/meta-facebook/meta-wedge/recipes-core/images/wedge-image.inc
@@ -0,0 +1,77 @@
+inherit aspeed_uboot_image
+
+# /dev
+require recipes-core/images/aspeed-dev.inc
+
+# Base this image on core-image-minimal
+include recipes-core/images/core-image-minimal.bb
+
+# Changing the image compression from gz to lzma achieves 30% saving (~3M).
+# However, the current u-boot does not have lzma enabled. Stick to gz
+# until we generate a new u-boot image.
+IMAGE_FSTYPES += "cpio.lzma.u-boot"
+UBOOT_IMAGE_ENTRYPOINT = "0x40800000"
+
+PYTHON_PKGS = " \
+ python-core \
+ python-io \
+ python-json \
+ python-shell \
+ python-subprocess \
+ python-argparse \
+ python-ctypes \
+ python-datetime \
+ python-email \
+ python-threading \
+ python-mime \
+ python-pickle \
+ python-misc \
+ python-netserver \
+ "
+
+NTP_PKGS = " \
+ ntp \
+ ntp-utils \
+ sntp \
+ ntpdate \
+ "
+
+# Include modules in rootfs
+IMAGE_INSTALL += " \
+ kernel-modules \
+ u-boot \
+ u-boot-fw-utils \
+ fbutils \
+ fan-ctrl \
+ rackmon \
+ watchdog-ctrl \
+ i2c-tools \
+ sensor-setup \
+ usb-console \
+ oob-nic \
+ lmsensors-sensors \
+ wedge-eeprom \
+ sms-kcsd \
+ rest-api \
+ bottle \
+ ipmid \
+ po-eeprom \
+ bitbang \
+ ${PYTHON_PKGS} \
+ ${NTP_PKGS} \
+ iproute2 \
+ dhcp-client \
+ "
+
+IMAGE_FEATURES += " \
+ ssh-server-openssh \
+ tools-debug \
+ "
+
+DISTRO_FEATURES += " \
+ ext2 \
+ ipv6 \
+ nfs \
+ usbgadget \
+ usbhost \
+ "
diff --git a/meta-facebook/meta-wedge/recipes-core/init-ifupdown/files/interfaces b/meta-facebook/meta-wedge/recipes-core/init-ifupdown/files/interfaces
new file mode 100644
index 0000000..36e342e
--- /dev/null
+++ b/meta-facebook/meta-wedge/recipes-core/init-ifupdown/files/interfaces
@@ -0,0 +1,11 @@
+# The loopback interface
+auto lo
+iface lo inet loopback
+
+auto eth0
+iface eth0 inet dhcp
+
+auto usb0
+iface usb0 inet6 static
+ address fe80::1
+ netmask 64
diff --git a/meta-facebook/meta-wedge/recipes-core/init-ifupdown/init-ifupdown_%.bbappend b/meta-facebook/meta-wedge/recipes-core/init-ifupdown/init-ifupdown_%.bbappend
new file mode 100644
index 0000000..7d74521
--- /dev/null
+++ b/meta-facebook/meta-wedge/recipes-core/init-ifupdown/init-ifupdown_%.bbappend
@@ -0,0 +1,2 @@
+
+FILESEXTRAPATHS_prepend := "${THISDIR}/files:"
diff --git a/meta-facebook/meta-wedge/recipes-core/sysvinit/sysvinit-inittab_%.bbappend b/meta-facebook/meta-wedge/recipes-core/sysvinit/sysvinit-inittab_%.bbappend
new file mode 100644
index 0000000..0a6d604
--- /dev/null
+++ b/meta-facebook/meta-wedge/recipes-core/sysvinit/sysvinit-inittab_%.bbappend
@@ -0,0 +1,5 @@
+# ttyS0 is UART5, connected to the debug board, selected by GPIOB2
+# ttyS1 is UART1, connected to uS, selected by GPIOB2
+# ttyS2 is UART3, connected to the front panel Console port
+# ttyS3 is UART4, used as RS485 connected as rackmon
+SERIAL_CONSOLES += "57600;ttyS0 9600;ttyS2"
diff --git a/meta-facebook/meta-wedge/recipes-kernel/linux/linux-aspeed_2.6%.bbappend b/meta-facebook/meta-wedge/recipes-kernel/linux/linux-aspeed_2.6%.bbappend
new file mode 100644
index 0000000..6bf04da
--- /dev/null
+++ b/meta-facebook/meta-wedge/recipes-kernel/linux/linux-aspeed_2.6%.bbappend
@@ -0,0 +1,5 @@
+LINUX_VERSION_EXTENSION = "-wedge"
+
+COMPATIBLE_MACHINE = "wedge"
+
+KERNEL_DEFCONFIG_aspeed = "wedge_defconfig"
diff --git a/meta-facebook/meta-wedge/recipes-wedge/bitbang/bitbang_0.1.bb b/meta-facebook/meta-wedge/recipes-wedge/bitbang/bitbang_0.1.bb
new file mode 100644
index 0000000..443d81d
--- /dev/null
+++ b/meta-facebook/meta-wedge/recipes-wedge/bitbang/bitbang_0.1.bb
@@ -0,0 +1,22 @@
+# Copyright 2014-present Facebook. All Rights Reserved.
+SUMMARY = "Device driver using GPIO bitbang"
+DESCRIPTION = "Various device driver using GPIO bitbang"
+SECTION = "base"
+PR = "r1"
+LICENSE = "GPLv2"
+LIC_FILES_CHKSUM = "file://bitbang.c;beginline=4;endline=16;md5=da35978751a9d71b73679307c4d296ec"
+
+SRC_URI = "file://src \
+ "
+
+DEPENDS += "fbutils"
+
+S = "${WORKDIR}/src"
+
+do_install() {
+ install -d ${D}${bindir}
+ install -m 755 spi-bb ${D}${bindir}/spi-bb
+ install -m 755 mdio-bb ${D}${bindir}/mdio-bb
+}
+
+FILES_${PN} = "${bindir}"
diff --git a/meta-facebook/meta-wedge/recipes-wedge/bitbang/files/src/Makefile b/meta-facebook/meta-wedge/recipes-wedge/bitbang/files/src/Makefile
new file mode 100644
index 0000000..102ac4e
--- /dev/null
+++ b/meta-facebook/meta-wedge/recipes-wedge/bitbang/files/src/Makefile
@@ -0,0 +1,13 @@
+# Copyright 2014-present Facebook. All Rights Reserved.
+all: spi-bb mdio-bb
+
+spi-bb: spi_bb.o bitbang.o gpio.o
+ $(CC) -o $@ $^ $(LDFLAGS)
+
+mdio-bb: mdio_bb.o bitbang.o gpio.o
+ $(CC) -o $@ $^ $(LDFLAGS)
+
+.PHONY: clean
+
+clean:
+ rm -rf *.o spi-bb mdio-bb
diff --git a/meta-facebook/meta-wedge/recipes-wedge/bitbang/files/src/bitbang.c b/meta-facebook/meta-wedge/recipes-wedge/bitbang/files/src/bitbang.c
new file mode 100644
index 0000000..cf7dcd3
--- /dev/null
+++ b/meta-facebook/meta-wedge/recipes-wedge/bitbang/files/src/bitbang.c
@@ -0,0 +1,236 @@
+/*
+ * Copyright 2014-present Facebook. All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+//#define DEBUG
+//#define VERBOSE
+
+#include "bitbang.h"
+
+#include <errno.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <sys/ioctl.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+
+#include "facebook/log.h"
+
+#define NANOSEC_IN_SEC (1000 * 1000 * 1000)
+
+#define BITBANG_FREQ_MAX (500 * 1000 * 1000) /* 500M Hz */
+#define BITBANG_FREQ_DEFAULT (1 * 1000 * 1000) /* 1M Hz */
+
+#define MAX(a, b) (((a) > (b)) ? (a) : (b))
+
+struct bitbang_handle {
+ bitbang_init_st bbh_init;
+ uint32_t bbh_half_clk; /* ns per clock cycle */
+};
+
+void bitbang_init_default(bitbang_init_st *init)
+{
+ memset(init, sizeof(*init), 0);
+ init->bbi_clk_start = BITBANG_PIN_HIGH;
+ init->bbi_data_out = BITBANG_CLK_EDGE_FALLING;
+ init->bbi_data_in = BITBANG_CLK_EDGE_RISING;
+ init->bbi_freq = BITBANG_FREQ_DEFAULT;
+}
+
+bitbang_handle_st* bitbang_open(const bitbang_init_st *init)
+{
+ bitbang_handle_st *hdl;
+
+ if (!init || !init->bbi_pin_f
+ || !init->bbi_freq || init->bbi_freq > BITBANG_FREQ_MAX) {
+ LOG_ERR(EINVAL, "Invalid init structure");
+ return NULL;
+ }
+
+ hdl = calloc(1, sizeof(*hdl));
+ if (!hdl) {
+ return NULL;
+ }
+
+ hdl->bbh_init = *init;
+ hdl->bbh_half_clk = NANOSEC_IN_SEC / init->bbi_freq / 2;
+
+ LOG_DBG("Bitbang open with initial %s, data out at %s, data in at %s, "
+ "freq at %uHz, half clk %uns",
+ (init->bbi_clk_start == BITBANG_PIN_LOW) ? "LOW" : "HIGH",
+ (init->bbi_data_out == BITBANG_CLK_EDGE_RISING)
+ ? "RISING" : "FALLING",
+ (init->bbi_data_in == BITBANG_CLK_EDGE_RISING)
+ ? "RISING" : "FALLING",
+ init->bbi_freq, hdl->bbh_half_clk);
+
+ return hdl;
+}
+
+void bitbang_close(bitbang_handle_st *hdl)
+{
+ free(hdl);
+}
+
+/*
+ * The threshold (ns) to use spin instead of nanosleep().
+ * Before adding the high resolution timer support, either spin or nanosleep()
+ * will not bring the process wakeup within 10ms. It turns out the system time
+ * update is also controlled by HZ (100).
+ * After I added the high resolution timer support, the spin works as the
+ * system time is updated more frequently. However, nanosleep() solution is
+ * still noticable slower comparing with spin. There could be some kernel
+ * scheduling tweak missing. Did not get time on that yet.
+ * For now, use 10ms as the threshold to determine if spin or nanosleep()
+ * is used.
+ */
+#define BITBANG_SPIN_THRESHOLD (10 * 1000 * 1000)
+
+static int sleep_ns(uint32_t clk)
+{
+ struct timespec req, rem;
+ int rc = 0;
+ if (clk <= BITBANG_SPIN_THRESHOLD) {
+ struct timespec orig;
+ rc = clock_gettime(CLOCK_MONOTONIC, &req);
+ orig = req;
+ while (!rc && clk) {
+ uint32_t tmp;
+ rc = clock_gettime(CLOCK_MONOTONIC, &rem);
+ tmp = (rem.tv_sec - req.tv_sec) * NANOSEC_IN_SEC;
+ if (rem.tv_nsec >= req.tv_nsec) {
+ tmp += rem.tv_nsec - req.tv_nsec;
+ } else {
+ tmp -= req.tv_nsec - rem.tv_nsec;
+ }
+ if (tmp >= clk) {
+ break;
+ }
+ clk -= tmp;
+ req = rem;
+ }
+ } else {
+ req.tv_sec = 0;
+ req.tv_nsec = clk;
+ while ((rc = nanosleep(&req, &rem)) == -1 && errno == EINTR) {
+ req = rem;
+ }
+ }
+ if (rc == -1) {
+ rc = errno;
+ LOG_ERR(rc, "Failed to sleep %u nanoseconds", clk);
+ }
+ return rc;
+}
+
+int bitbang_io(const bitbang_handle_st *hdl, bitbang_io_st *io)
+{
+ int rc = 0;
+ uint32_t clk = hdl->bbh_half_clk;
+ const struct {
+ bitbang_pin_value_en value;
+ bitbang_clk_edge_en edge;
+ } clks[] = {
+ {BITBANG_PIN_HIGH, BITBANG_CLK_EDGE_FALLING},
+ {BITBANG_PIN_LOW, BITBANG_CLK_EDGE_RISING},
+ };
+ int clk_idx;
+ int n_clk = 0;
+ int n_bits = 0;
+ const uint8_t *dout = io->bbio_dout;
+ uint8_t *din = io->bbio_din;
+ int bit_pos = 7;
+ bitbang_pin_func pin_f = hdl->bbh_init.bbi_pin_f;
+ void *context = hdl->bbh_init.bbi_context;
+
+ if ((io->bbio_in_bits == 0 && io->bbio_din)
+ || (io->bbio_in_bits > 0 && !io->bbio_din)) {
+ rc = EINVAL;
+ LOG_ERR(rc, "Incorrect in bits and in buffer");
+ goto out;
+ }
+
+ if ((io->bbio_out_bits == 0 && io->bbio_dout)
+ || (io->bbio_out_bits > 0 && !io->bbio_dout)) {
+ rc = EINVAL;
+ LOG_ERR(rc, "Incorrect out bits and out buffer");
+ goto out;
+ }
+
+ if (io->bbio_in_bits == 0 && io->bbio_out_bits == 0) {
+ rc = EINVAL;
+ LOG_ERR(rc, "Both in and out bits are 0");
+ goto out;
+ }
+
+ if (hdl->bbh_init.bbi_clk_start == BITBANG_PIN_HIGH) {
+ clk_idx = 0;
+ } else {
+ clk_idx = 1;
+ }
+
+ /* set the CLK pin start position */
+ pin_f(BITBANG_CLK_PIN, clks[clk_idx].value, context);
+
+ /* clear the first byte of din */
+ if (din && io->bbio_in_bits) {
+ memset(din, 0, (io->bbio_in_bits + 7) / 8);
+ }
+
+ do {
+ if ((rc = sleep_ns(clk))) {
+ goto out;
+ }
+
+ /* output first */
+ if (hdl->bbh_init.bbi_data_out == clks[clk_idx].edge) {
+ if (dout && n_bits < io->bbio_out_bits) {
+ pin_f(BITBANG_DATA_OUT, (*dout >> bit_pos) & 0x1, context);
+ }
+ }
+
+ /* then, input */
+ if (hdl->bbh_init.bbi_data_in == clks[clk_idx].edge) {
+ if (din && n_bits < io->bbio_in_bits) {
+ *din |= (pin_f(BITBANG_DATA_IN, 0, context) & 0x1) << bit_pos;
+ }
+ }
+
+ if (++n_clk % 2 == 0) {
+ /* one bit for every 2 half clks */
+ n_bits ++;
+ if (bit_pos == 0) {
+ if (dout) {
+ dout++;
+ }
+ if (din) {
+ din++;
+ }
+ bit_pos = 7;
+ } else {
+ bit_pos --;
+ }
+ }
+ clk_idx = 1 - clk_idx;
+ pin_f(BITBANG_CLK_PIN, clks[clk_idx].value, context);
+ } while (n_bits < MAX(io->bbio_in_bits, io->bbio_out_bits));
+
+ out:
+
+ return -rc;
+}
diff --git a/meta-facebook/meta-wedge/recipes-wedge/bitbang/files/src/bitbang.h b/meta-facebook/meta-wedge/recipes-wedge/bitbang/files/src/bitbang.h
new file mode 100644
index 0000000..0f21a49
--- /dev/null
+++ b/meta-facebook/meta-wedge/recipes-wedge/bitbang/files/src/bitbang.h
@@ -0,0 +1,66 @@
+/*
+ * Copyright 2014-present Facebook. All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#ifndef BITBANG_H
+#define BITBANG_H
+
+#include <stdint.h>
+
+typedef enum {
+ BITBANG_CLK_PIN,
+ BITBANG_DATA_IN,
+ BITBANG_DATA_OUT,
+} bitbang_pin_type_en;
+
+typedef enum {
+ BITBANG_PIN_LOW = 0,
+ BITBANG_PIN_HIGH = 1,
+} bitbang_pin_value_en;
+
+typedef enum {
+ BITBANG_CLK_EDGE_RISING,
+ BITBANG_CLK_EDGE_FALLING,
+} bitbang_clk_edge_en;
+
+typedef bitbang_pin_value_en (* bitbang_pin_func)(
+ bitbang_pin_type_en pin, bitbang_pin_value_en value, void *context);
+
+typedef struct {
+ bitbang_pin_value_en bbi_clk_start;
+ bitbang_clk_edge_en bbi_data_out;
+ bitbang_clk_edge_en bbi_data_in;
+ uint32_t bbi_freq;
+ bitbang_pin_func bbi_pin_f;
+ void *bbi_context;
+} bitbang_init_st;
+
+typedef struct bitbang_handle bitbang_handle_st;
+
+void bitbang_init_default(bitbang_init_st *init);
+bitbang_handle_st* bitbang_open(const bitbang_init_st *init);
+void bitbang_close(bitbang_handle_st *hdl);
+
+typedef struct {
+ uint32_t bbio_in_bits;
+ uint32_t bbio_out_bits;
+ uint8_t *bbio_dout;
+ uint8_t *bbio_din;
+} bitbang_io_st;
+
+int bitbang_io(const bitbang_handle_st *hdl, bitbang_io_st *io);
+
+#endif
diff --git a/meta-facebook/meta-wedge/recipes-wedge/bitbang/files/src/gpio.c b/meta-facebook/meta-wedge/recipes-wedge/bitbang/files/src/gpio.c
new file mode 100644
index 0000000..026aebc
--- /dev/null
+++ b/meta-facebook/meta-wedge/recipes-wedge/bitbang/files/src/gpio.c
@@ -0,0 +1,107 @@
+/*
+ * Copyright 2014-present Facebook. All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+//#define DEBUG
+//#define VERBOSE
+
+#include "gpio.h"
+
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <sys/errno.h>
+
+#include "facebook/log.h"
+
+void gpio_init_default(gpio_st *g) {
+ g->gs_gpio = -1;
+ g->gs_fd = -1;
+}
+
+int gpio_open(gpio_st *g, int gpio)
+{
+ char buf[128];
+ int rc;
+
+ snprintf(buf, sizeof(buf), "/sys/class/gpio/gpio%u/value", gpio);
+ rc = open(buf, O_RDWR);
+ if (rc == -1) {
+ rc = errno;
+ LOG_ERR(rc, "Failed to open %s", buf);
+ return -rc;
+ }
+ g->gs_fd = rc;
+ g->gs_gpio = gpio;
+ return 0;
+}
+
+void gpio_close(gpio_st *g)
+{
+ if (g && g->gs_fd != -1) {
+ close(g->gs_fd);
+ }
+ gpio_init_default(g);
+}
+
+gpio_value_en gpio_read(gpio_st *g)
+{
+ char buf[32] = {0};
+ gpio_value_en v;
+ lseek(g->gs_fd, 0, SEEK_SET);
+ read(g->gs_fd, buf, sizeof(buf));
+ v = atoi(buf) ? GPIO_VALUE_HIGH : GPIO_VALUE_LOW;
+ LOG_VER("read gpio=%d value=%d %d", g->gs_gpio, atoi(buf), v);
+ return v;
+}
+
+void gpio_write(gpio_st *g, gpio_value_en v)
+{
+ lseek(g->gs_fd, 0, SEEK_SET);
+ write(g->gs_fd, (v == GPIO_VALUE_HIGH) ? "1" : "0", 1);
+ LOG_VER("write gpio=%d value=%d", g->gs_gpio, v);
+}
+
+int gpio_change_direction(gpio_st *g, gpio_direction_en dir)
+{
+ char buf[128];
+ char *val;
+ int fd = -1;
+ int rc = 0;
+
+ snprintf(buf, sizeof(buf), "/sys/class/gpio/gpio%u/direction", g->gs_gpio);
+ fd = open(buf, O_WRONLY);
+ if (fd == -1) {
+ rc = errno;
+ LOG_ERR(rc, "Failed to open %s", buf);
+ return -rc;
+ }
+
+ val = (dir == GPIO_DIRECTION_IN) ? "in" : "out";
+ write(fd, val, strlen(val));
+
+ LOG_VER("change gpio=%d direction=%s", g->gs_gpio, val);
+
+ out:
+ if (fd != -1) {
+ close(fd);
+ }
+ return -rc;
+}
diff --git a/meta-facebook/meta-wedge/recipes-wedge/bitbang/files/src/gpio.h b/meta-facebook/meta-wedge/recipes-wedge/bitbang/files/src/gpio.h
new file mode 100644
index 0000000..3303986
--- /dev/null
+++ b/meta-facebook/meta-wedge/recipes-wedge/bitbang/files/src/gpio.h
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2014-present Facebook. All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#ifndef GPIO_H
+#define GPIO_H
+
+typedef struct {
+ int gs_gpio;
+ int gs_fd;
+} gpio_st;
+
+typedef enum {
+ GPIO_DIRECTION_IN,
+ GPIO_DIRECTION_OUT,
+} gpio_direction_en;
+
+typedef enum {
+ GPIO_VALUE_LOW = 0,
+ GPIO_VALUE_HIGH = 1,
+} gpio_value_en;
+
+int gpio_open(gpio_st* g, int gpio);
+void gpio_close(gpio_st *g);
+gpio_value_en gpio_read(gpio_st *g);
+void gpio_write(gpio_st *g, gpio_value_en v);
+int gpio_change_direction(gpio_st *g, gpio_direction_en dir);
+
+#endif
diff --git a/meta-facebook/meta-wedge/recipes-wedge/bitbang/files/src/mdio_bb.c b/meta-facebook/meta-wedge/recipes-wedge/bitbang/files/src/mdio_bb.c
new file mode 100644
index 0000000..ef0c567
--- /dev/null
+++ b/meta-facebook/meta-wedge/recipes-wedge/bitbang/files/src/mdio_bb.c
@@ -0,0 +1,336 @@
+/*
+ * Copyright 2014-present Facebook. All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+//#define DEBUG
+//#define VERBOSE
+
+#include "bitbang.h"
+#include "gpio.h"
+
+#include <stdlib.h>
+#include <unistd.h>
+
+#include "facebook/log.h"
+
+
+typedef struct {
+ gpio_st m_mdc;
+ gpio_st m_mdio;
+} mdio_context_st;
+
+/*
+ * 32b preamble, 2b start of frame, 2b operation code,
+ * 5b phy addr, 5b register addr, 2b turnaround, 16b data
+ */
+#define N_BITS (32 + 2 + 2 + 5 + 5 + 2 + 16)
+#define N_BYTES (N_BITS + 7 / 8)
+
+#define START_OF_FRAME 0x1
+#define OP_READ 0x2
+#define OP_WRITE 0x1
+#define TURNAROUND 0x2 /* TA for write, for read, phy sends out TA */
+
+void usage()
+{
+ fprintf(stderr,
+ "Usage:\n"
+ "mdio-bb: -c <GPIO for MDC> [-C <HIGH|low>]\n"
+ " -d <GPIO for MDIO> [-O <rising|FALLING>]\n"
+ " [-I <RISING|falling>] [-p] [-b]\n"
+ " <read|write> <phy address> <register address>\n"
+ " [value to write]\n");
+}
+
+bitbang_pin_value_en mdio_pin_f(
+ bitbang_pin_type_en pin, bitbang_pin_value_en value, void *context)
+{
+ mdio_context_st *ctx = (mdio_context_st *)context;
+ gpio_st *gpio;
+ bitbang_pin_value_en res;
+
+ switch (pin) {
+ case BITBANG_CLK_PIN:
+ gpio = &ctx->m_mdc;
+ break;
+ case BITBANG_DATA_IN:
+ case BITBANG_DATA_OUT:
+ gpio = &ctx->m_mdio;
+ break;
+ }
+ if (pin == BITBANG_DATA_IN) {
+ res = gpio_read(gpio) ? BITBANG_PIN_HIGH : BITBANG_PIN_LOW;
+ } else {
+ res = value;
+ gpio_write(gpio, ((res == BITBANG_PIN_HIGH)
+ ? GPIO_VALUE_HIGH : GPIO_VALUE_LOW));
+ }
+ return res;
+}
+
+int main(int argc, char* const argv[])
+{
+ int opt;
+ int mdc = -1, mdio = -1;
+ bitbang_pin_value_en mdc_start = BITBANG_PIN_HIGH;
+ bitbang_clk_edge_en out_edge = BITBANG_CLK_EDGE_FALLING;
+ bitbang_clk_edge_en in_edge = BITBANG_CLK_EDGE_RISING;
+ int is_write;
+ uint32_t phy_addr;
+ uint32_t reg_addr;
+ uint32_t data; /* data to write/read*/
+ uint8_t buf[N_BYTES];
+ uint8_t *buf_p;
+ mdio_context_st ctx;
+ bitbang_init_st init;
+ bitbang_handle_st *hdl = NULL;
+ bitbang_io_st io;
+ int n_bits;
+ int i;
+ int rc = 0;
+ int preamble = 0;
+ int binary = 0;
+
+ while ((opt = getopt(argc, argv, "bc:C:d:D:p")) != -1) {
+ switch (opt) {
+ case 'b':
+ binary = 1;
+ break;
+ case 'c':
+ mdc = atoi(optarg);
+ break;
+ case 'C':
+ if (!strcasecmp(optarg, "high")) {
+ mdc_start = BITBANG_PIN_HIGH;
+ } else if (!strcasecmp(optarg, "low")) {
+ mdc_start = BITBANG_PIN_LOW;
+ } else {
+ usage();
+ exit(-1);
+ }
+ break;
+ case 'd':
+ mdio = atoi(optarg);
+ break;
+ case 'I':
+ if (!strcasecmp(optarg, "rising")) {
+ in_edge = BITBANG_CLK_EDGE_RISING;
+ } if (!strcasecmp(optarg, "falling")) {
+ in_edge = BITBANG_CLK_EDGE_FALLING;
+ } else {
+ usage();
+ exit(-1);
+ }
+ break;
+ case 'O':
+ if (!strcasecmp(optarg, "rising")) {
+ out_edge = BITBANG_CLK_EDGE_RISING;
+ } if (!strcasecmp(optarg, "falling")) {
+ out_edge = BITBANG_CLK_EDGE_FALLING;
+ } else {
+ usage();
+ exit(-1);
+ }
+ break;
+ case 'p':
+ preamble = 1;
+ break;
+ default:
+ usage();
+ exit(-1);
+ }
+ }
+
+ if (mdc < 0 || mdio < 0) {
+ usage();
+ exit(-1);
+ }
+
+ if (optind + 2 >= argc) {
+ usage();
+ exit(-1);
+ }
+
+ /* read or write */
+ if (!strcasecmp(argv[optind], "read")) {
+ is_write = 0;
+ } else if (!strcasecmp(argv[optind], "write")) {
+ is_write = 1;
+ } else {
+ usage();
+ exit(-1);
+ }
+
+ /* phy address, 5 bits only, so must be <= 0x1f */
+ phy_addr = strtoul(argv[optind + 1], NULL, 0);
+ if (phy_addr > 0x1f) {
+ usage();
+ exit(-1);
+ }
+
+ /* register address, 5 bits only, so must be <= 0x1f */
+ reg_addr = strtoul(argv[optind + 2], NULL, 0);
+ if (reg_addr > 0x1f) {
+ usage();
+ exit(-1);
+ }
+
+ /* data */
+ if (is_write) {
+ if ((!binary && (optind + 4 != argc)) ||
+ (binary && (optind + 3 != argc))) {
+ usage();
+ exit(-1);
+ }
+ if (binary) {
+ uint16_t temp = 0;
+ if (fread(&temp, sizeof(temp), 1, stdin) != 1) {
+ usage();
+ exit(-1);
+ }
+ data = htons(temp);
+ } else {
+ data = strtoul(argv[optind + 3], NULL, 0);
+ }
+ if (data > 0xFFFF) {
+ usage();
+ exit(-1);
+ }
+ } else {
+ if ((!binary && (optind + 3 != argc)) ||
+ (binary && (optind + 2 != argc))) {
+ usage();
+ exit(-1);
+ }
+ }
+
+ /* open all gpio */
+ memset(&ctx, sizeof(ctx), 0);
+ gpio_init_default(&ctx.m_mdc);
+ gpio_init_default(&ctx.m_mdio);
+ if (gpio_open(&ctx.m_mdc, mdc) || gpio_open(&ctx.m_mdio, mdio)) {
+ goto out;
+ }
+
+ if (gpio_change_direction(&ctx.m_mdc, GPIO_DIRECTION_OUT)
+ || gpio_change_direction(&ctx.m_mdio, GPIO_DIRECTION_OUT)) {
+ goto out;
+ }
+
+ bitbang_init_default(&init);
+ init.bbi_clk_start = mdc_start;
+ init.bbi_data_out = out_edge;
+ init.bbi_data_in = in_edge;
+ init.bbi_freq = 1000 * 1000; /* 1M Hz */
+ init.bbi_pin_f = mdio_pin_f;
+ init.bbi_context = &ctx;
+ hdl = bitbang_open(&init);
+ if (!hdl) {
+ goto out;
+ }
+
+ if (is_write) {
+ buf[0] = (data >> 8) & 0xFF;
+ buf[1] = data & 0xFF;
+ io.bbio_out_bits = 16;
+ io.bbio_dout = buf;
+ io.bbio_in_bits = 0;
+ io.bbio_din = NULL;
+ } else {
+ io.bbio_in_bits = 16;
+ io.bbio_din = buf;
+ io.bbio_out_bits = 0;
+ io.bbio_dout = NULL;
+ }
+
+ /* preamble, 32b */
+ buf_p = buf;
+ n_bits = 0;
+ if (preamble) {
+ /* 32 bit of 1 for preamble */
+ for (i = 0; i < 4; i++) {
+ *buf_p++ = 0xFF;
+ }
+ n_bits += 32;
+ }
+
+ /*
+ * MDIO transaction header is:
+ * 2b START, 2b OPER CODE, 5b PHY ADDR, 5b register addr, 2b TURNROUND
+ */
+ *buf_p++ = (START_OF_FRAME << 6) | (((is_write) ? OP_WRITE : OP_READ) << 4)
+ | ((phy_addr >> 1) & 0xF);
+ *buf_p++ = ((phy_addr & 0x1) << 7) | ((reg_addr & 0x1F) << 2) | TURNAROUND;
+ if (is_write) {
+ *buf_p++ = (data >> 8) & 0xFF;
+ *buf_p++ = data & 0xFF;
+ /* total # of bits is transaction header + 2 bytes to write */
+ n_bits += 2 + 2 + 5 + 5 + 2 + 16;
+ } else {
+ /* for read, master does not send TR, so, n_bits should not include TR */
+ n_bits += 2 + 2 + 5 + 5;
+ }
+
+ memset(&io, sizeof(io), 0);
+ io.bbio_out_bits = n_bits;
+ io.bbio_dout = buf;
+ io.bbio_in_bits = 0;
+ io.bbio_din = NULL;
+
+ rc = bitbang_io(hdl, &io);
+ if (rc != 0) {
+ goto out;
+ }
+
+ /* for read, need to do another io for (2b TR + 16b data) reading */
+ if (!is_write) {
+ /* first, change the MDIO to input */
+ gpio_change_direction(&ctx.m_mdio, GPIO_DIRECTION_IN);
+ /* then, run the clock for read */
+ memset(&io, sizeof(io), 0);
+ io.bbio_out_bits = 0;
+ io.bbio_dout = NULL;;
+ io.bbio_in_bits = 18;
+ io.bbio_din = buf;
+
+ rc = bitbang_io(hdl, &io);
+ if (rc != 0) {
+ goto out;
+ }
+
+ data = ((buf[0] << 2) | (buf[1] >> 6)) & 0xFF;
+ data <<= 8;
+ data |= ((buf[1] << 2) | (buf[2] >> 6)) & 0xFF;
+ }
+
+ if (binary) {
+ if (!is_write) {
+ uint16_t temp = ntohs(data);
+ fwrite(&temp, sizeof(temp), 1, stdout);
+ }
+ } else {
+ printf("%s: 0x%02x\n", (is_write) ? "Wrote" : "Read", data);
+ }
+
+ out:
+ if (hdl) {
+ bitbang_close(hdl);
+ }
+ gpio_close(&ctx.m_mdc);
+ gpio_close(&ctx.m_mdio);
+
+ return 0;
+}
diff --git a/meta-facebook/meta-wedge/recipes-wedge/bitbang/files/src/spi_bb.c b/meta-facebook/meta-wedge/recipes-wedge/bitbang/files/src/spi_bb.c
new file mode 100644
index 0000000..ce366a5
--- /dev/null
+++ b/meta-facebook/meta-wedge/recipes-wedge/bitbang/files/src/spi_bb.c
@@ -0,0 +1,317 @@
+/*
+ * Copyright 2014-present Facebook. All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+//#define DEBUG
+//#define VERBOSE
+
+#include "bitbang.h"
+#include "gpio.h"
+
+#include <stdlib.h>
+#include <unistd.h>
+
+#include "facebook/log.h"
+
+void usage()
+{
+ fprintf(stderr,
+ "Usage:\n"
+ "spi-bb: -s <GPIO for CS> [-S <HIGH|low>]\n"
+ " -c <GPIO for CLK> [-C <HIGH|low>]\n"
+ " -o <GPIO for MOSI> [-O <rising|FALLING>]\n"
+ " -i <GPIO for MISO> [-I <RISING|falling>]\n"
+ " [-b]\n"
+ " < [-r <number of bits to read>]\n"
+ " [-w <number of bits to write> <byte 1> [... byte N]>\n\n"
+ "Note: If both '-r' and '-w' are provided, 'write' will be performed\n"
+ " before 'read'.\n");
+}
+
+typedef struct {
+ gpio_st sc_clk;
+ gpio_st sc_mosi;
+ gpio_st sc_miso;
+} spi_context_st;
+
+bitbang_pin_value_en spi_pin_f(
+ bitbang_pin_type_en pin, bitbang_pin_value_en value, void *context)
+{
+ spi_context_st *ctx = (spi_context_st *)context;
+ gpio_st *gpio;
+ bitbang_pin_value_en res;
+
+ switch (pin) {
+ case BITBANG_CLK_PIN:
+ gpio = &ctx->sc_clk;
+ break;
+ case BITBANG_DATA_IN:
+ gpio = &ctx->sc_miso;
+ break;
+ case BITBANG_DATA_OUT:
+ gpio = &ctx->sc_mosi;
+ break;
+ }
+ if (pin == BITBANG_DATA_IN) {
+ res = gpio_read(gpio) ? BITBANG_PIN_HIGH : BITBANG_PIN_LOW;
+ } else {
+ res = value;
+ gpio_write(gpio, ((res == BITBANG_PIN_HIGH)
+ ? GPIO_VALUE_HIGH : GPIO_VALUE_LOW));
+ }
+ return res;
+}
+
+int main(int argc, char * const argv[])
+{
+ bitbang_init_st init;
+ bitbang_handle_st *hdl = NULL;
+ int cs = -1, clk = -1, in = -1, out = -1;
+ gpio_st cs_gpio;
+ int opt;
+ int is_write = 0;
+ int is_read = 0;
+ int read_bits = 0;
+ int write_bits = 0;
+ int read_bytes = 0;
+ int write_bytes = 0;
+ int i;
+ uint8_t *read_buf = NULL;;
+ uint8_t *write_buf = NULL;;
+ bitbang_clk_edge_en dout_edge = BITBANG_CLK_EDGE_FALLING;
+ bitbang_clk_edge_en din_edge = BITBANG_CLK_EDGE_RISING;
+ bitbang_pin_value_en clk_start = BITBANG_PIN_HIGH;
+ bitbang_pin_value_en cs_value = BITBANG_PIN_HIGH;
+ spi_context_st ctx;
+ bitbang_io_st io;
+ int rc = 0;
+ int binary = 0;
+
+ memset(&ctx, sizeof(ctx), 0);
+ gpio_init_default(&ctx.sc_clk);
+ gpio_init_default(&ctx.sc_mosi);
+ gpio_init_default(&ctx.sc_miso);
+ gpio_init_default(&cs_gpio);
+
+ while ((opt = getopt(argc, argv, "bs:S:c:C:o:O:i:I:w:r:")) != -1) {
+ switch (opt) {
+ case 'b':
+ binary = 1;
+ break;
+ case 's':
+ cs = atoi(optarg);
+ break;
+ case 'S':
+ if (!strcmp(optarg, "high")) {
+ cs_value = BITBANG_PIN_HIGH;
+ } else if (!strcmp(optarg, "low")) {
+ cs_value = BITBANG_PIN_LOW;
+ } else {
+ usage();
+ exit(-1);
+ }
+ break;
+ case 'c':
+ clk = atoi(optarg);
+ break;
+ case 'C':
+ if (!strcasecmp(optarg, "high")) {
+ clk_start = BITBANG_PIN_HIGH;
+ } else if (!strcasecmp(optarg, "low")) {
+ clk_start = BITBANG_PIN_LOW;
+ } else {
+ usage();
+ exit(-1);
+ }
+ break;
+ case 'o':
+ out = atoi(optarg);
+ break;
+ case 'O':
+ if (!strcasecmp(optarg, "rising")) {
+ dout_edge = BITBANG_CLK_EDGE_RISING;
+ } else if (!strcasecmp(optarg, "falling")) {
+ dout_edge = BITBANG_CLK_EDGE_FALLING;
+ } else {
+ usage();
+ exit(-1);
+ }
+ break;
+ case 'i':
+ in = atoi(optarg);
+ break;
+ case 'I':
+ if (!strcasecmp(optarg, "rising")) {
+ din_edge = BITBANG_CLK_EDGE_RISING;
+ } else if (!strcasecmp(optarg, "falling")) {
+ din_edge = BITBANG_CLK_EDGE_FALLING;
+ } else {
+ usage();
+ exit(-1);
+ }
+ break;
+ case 'w':
+ is_write = 1;
+ write_bits = atoi(optarg);
+ if (write_bits <= 0) {
+ usage();
+ exit(-1);
+ }
+ break;
+ case 'r':
+ is_read = 1;
+ read_bits = atoi(optarg);
+ if (read_bits <= 0) {
+ usage();
+ exit(-1);
+ }
+ break;
+ default:
+ usage();
+ exit(-1);
+ }
+ }
+
+ if (clk < 0 || in < 0 || out < 0) {
+ usage();
+ exit(-1);
+ }
+
+ if ((!is_read && !is_write)) {
+ usage();
+ exit(-1);
+ }
+
+ write_bytes = ((write_bits + 7) / 8);
+ if (write_bytes) {
+ write_buf = calloc(write_bytes, sizeof(uint8_t));
+ if (!write_buf) {
+ goto out;
+ }
+ if (binary) {
+ size_t written_bytes;
+ written_bytes = fread(write_buf, sizeof(*write_buf), write_bytes, stdin);
+ if( written_bytes != write_bytes ) {
+ goto out;
+ }
+ } else {
+ for (i = 0; i < write_bytes && i + optind < argc; i++) {
+ write_buf[i] = strtoul(argv[i + optind], NULL, 0);
+ }
+ }
+ }
+
+ read_bytes = ((read_bits + 7) / 8);
+ if (read_bytes) {
+ read_buf = calloc(read_bytes, sizeof(uint8_t));
+ if (!read_buf) {
+ goto out;
+ }
+ }
+
+ if (gpio_open(&ctx.sc_clk, clk) || gpio_open(&ctx.sc_miso, in)
+ || gpio_open(&ctx.sc_mosi, out)) {
+ goto out;
+ }
+
+ /* change GPIO directions, only MISO is input, all others are output */
+ if (gpio_change_direction(&ctx.sc_clk, GPIO_DIRECTION_OUT)
+ || gpio_change_direction(&ctx.sc_miso, GPIO_DIRECTION_IN)
+ || gpio_change_direction(&ctx.sc_mosi, GPIO_DIRECTION_OUT)) {
+ goto out;
+ }
+
+ if (cs != -1) {
+ if (gpio_open(&cs_gpio, cs)) {
+ goto out;
+ }
+ if (gpio_change_direction(&cs_gpio, GPIO_DIRECTION_OUT)) {
+ goto out;
+ }
+ }
+
+ bitbang_init_default(&init);
+ init.bbi_clk_start = clk_start;
+ init.bbi_data_out = dout_edge;
+ init.bbi_data_in = din_edge;
+ init.bbi_freq = 1000 * 1000; /* 1M Hz */
+ init.bbi_pin_f = spi_pin_f;
+ init.bbi_context = &ctx;
+
+ hdl = bitbang_open(&init);
+ if (!hdl) {
+ goto out;
+ }
+
+ if (cs != -1) {
+ /* have chip select */
+ gpio_write(&cs_gpio, ((cs_value == BITBANG_PIN_HIGH)
+ ? GPIO_VALUE_HIGH : GPIO_VALUE_LOW));
+ }
+
+ memset(&io, sizeof(io), 0);
+ io.bbio_in_bits = read_bits;
+ io.bbio_din = read_buf;
+ io.bbio_out_bits = write_bits;
+ io.bbio_dout = write_buf;
+
+ rc = bitbang_io(hdl, &io);
+ if (rc != 0) {
+ goto out;
+ }
+
+ if (binary) {
+ fwrite(read_buf, sizeof(*read_buf), read_bytes, stdout);
+ } else {
+ if (write_bits) {
+ printf("Wrote %u bits:", write_bits);
+ for (i = 0; i < write_bytes; i++) {
+ printf(" %02x", write_buf[i]);
+ }
+ printf("\n");
+ }
+
+ if (read_bits) {
+ printf("Read %u bits:", read_bits);
+ for (i = 0; i < read_bytes; i++) {
+ printf(" %02x", read_buf[i]);
+ }
+ printf("\n");
+ }
+ }
+
+ out:
+ if (hdl) {
+ bitbang_close(hdl);
+ }
+ gpio_close(&ctx.sc_clk);
+ gpio_close(&ctx.sc_miso);
+ gpio_close(&ctx.sc_mosi);
+ if (cs != -1) {
+ /* reset have chip select */
+ gpio_write(&cs_gpio, ((cs_value == BITBANG_PIN_HIGH)
+ ? GPIO_VALUE_LOW : GPIO_VALUE_HIGH));
+ gpio_close(&cs_gpio);
+ }
+
+ if (read_buf) {
+ free(read_buf);
+ }
+ if (write_buf) {
+ free(write_buf);
+ }
+ return rc;
+}
diff --git a/meta-facebook/meta-wedge/recipes-wedge/fan-ctrl/fan-ctrl/Makefile b/meta-facebook/meta-wedge/recipes-wedge/fan-ctrl/fan-ctrl/Makefile
new file mode 100644
index 0000000..fa9a8f4
--- /dev/null
+++ b/meta-facebook/meta-wedge/recipes-wedge/fan-ctrl/fan-ctrl/Makefile
@@ -0,0 +1,10 @@
+# Copyright 2014-present Facebook. All Rights Reserved.
+all: fand
+
+fand: fand.cpp watchdog.cpp
+ $(CXX) -pthread -o $@ $^ $(LDFLAGS) -lwedge_eeprom
+
+.PHONY: clean
+
+clean:
+ rm -rf *.o fand
diff --git a/meta-facebook/meta-wedge/recipes-wedge/fan-ctrl/fan-ctrl/README b/meta-facebook/meta-wedge/recipes-wedge/fan-ctrl/fan-ctrl/README
new file mode 100644
index 0000000..2a92b9d
--- /dev/null
+++ b/meta-facebook/meta-wedge/recipes-wedge/fan-ctrl/fan-ctrl/README
@@ -0,0 +1,5 @@
+The AST PWM/Tach driver is in the kernel sources at drivers/hwmon/ast_pwm_fan.c
+
+There are 7 PWM output pins. Each PWM can be configured in one of 3 types (M,
+N, or O). The clock settings for each type are configurable. See init_pwm.sh
+for more comments about how we configure the settings.
diff --git a/meta-facebook/meta-wedge/recipes-wedge/fan-ctrl/fan-ctrl/fand.cpp b/meta-facebook/meta-wedge/recipes-wedge/fan-ctrl/fan-ctrl/fand.cpp
new file mode 100644
index 0000000..24e107c
--- /dev/null
+++ b/meta-facebook/meta-wedge/recipes-wedge/fan-ctrl/fan-ctrl/fand.cpp
@@ -0,0 +1,851 @@
+/*
+ * fand
+ *
+ * Copyright 2014-present Facebook. All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * Daemon to manage the fan speed to ensure that we stay within a reasonable
+ * temperature range. We're using a simplistic algorithm to get started:
+ *
+ * If the fan is already on high, we'll move it to medium if we fall below
+ * a top temperature. If we're on medium, we'll move it to high
+ * if the temperature goes over the top value, and to low if the
+ * temperature falls to a bottom level. If the fan is on low,
+ * we'll increase the speed if the temperature rises to the top level.
+ *
+ * To ensure that we're not just turning the fans up, then back down again,
+ * we'll require an extra few degrees of temperature drop before we lower
+ * the fan speed.
+ *
+ * We check the RPM of the fans against the requested RPMs to determine
+ * whether the fans are failing, in which case we'll turn up all of
+ * the other fans and report the problem..
+ *
+ * TODO: Implement a PID algorithm to closely track the ideal temperature.
+ * TODO: Determine if the daemon is already started.
+ */
+
+/* Yeah, the file ends in .cpp, but it's a C program. Deal. */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+#include <signal.h>
+#include <syslog.h>
+#include "watchdog.h"
+
+#include "facebook/wedge_eeprom.h"
+
+/* Sensor definitions */
+
+#define INTERNAL_TEMPS(x) ((x) * 1000) // stored a C * 1000
+#define EXTERNAL_TEMPS(x) ((x) / 1000)
+
+#define I2C_BUS_3_DIR "/sys/class/i2c-adapter/i2c-3/"
+#define I2C_BUS_4_DIR "/sys/class/i2c-adapter/i2c-4/"
+
+#define INTAKE_TEMP_DEVICE I2C_BUS_3_DIR "3-0048"
+#define T2_TEMP_DEVICE I2C_BUS_3_DIR "3-0049"
+#define EXHAUST_TEMP_DEVICE I2C_BUS_3_DIR "3-004a"
+#define USERVER_TEMP_DEVICE I2C_BUS_4_DIR "4-0040"
+
+/*
+ * The sensor for the uServer CPU is not on the CPU itself, so it reads
+ * a little low. We are special casing this, but we should obviously
+ * be thinking about a way to generalize these tweaks, and perhaps
+ * the entire configuration. JSON file?
+ */
+
+#define USERVER_TEMP_FUDGE INTERNAL_TEMPS(10)
+
+#define BAD_TEMP INTERNAL_TEMPS(-60)
+
+#define BAD_READ_THRESHOLD 4 /* How many times can reads fail */
+#define FAN_FAILURE_THRESHOLD 4 /* How many times can a fan fail */
+
+#define PWM_DIR "/sys/devices/platform/ast_pwm_tacho.0"
+
+#define PWM_UNIT_MAX 96
+
+#define LARGEST_DEVICE_NAME 120
+
+#define GPIO_USERVER_POWER_DIRECTION "/sys/class/gpio/gpio25/direction"
+#define GPIO_USERVER_POWER "/sys/class/gpio/gpio25/value"
+#define GPIO_T2_POWER_DIRECTION "/sys/class/gpio/gpio41/direction"
+#define GPIO_T2_POWER "/sys/class/gpio/gpio41/value"
+
+#define GPIO_FAN0_LED "/sys/class/gpio/gpio53/value"
+#define GPIO_FAN1_LED "/sys/class/gpio/gpio54/value"
+#define GPIO_FAN2_LED "/sys/class/gpio/gpio55/value"
+#define GPIO_FAN3_LED "/sys/class/gpio/gpio72/value"
+
+const char *fan_led[] = {GPIO_FAN0_LED, GPIO_FAN1_LED,
+ GPIO_FAN2_LED, GPIO_FAN3_LED};
+
+#define FAN_LED_RED "0"
+#define FAN_LED_BLUE "1"
+
+#define GPIO_PIN_ID "/sys/class/gpio/gpio%d/value"
+#define REV_IDS 3
+#define GPIO_REV_ID_START 192
+
+#define BOARD_IDS 4
+#define GPIO_BOARD_ID_START 160
+
+/*
+ * With hardware revisions after 3, we use a different set of pins for
+ * the BOARD_ID.
+ */
+
+#define REV_ID_NEW_BOARD_ID 3
+#define GPIO_BOARD_ID_START_NEW 166
+
+#define REPORT_TEMP 720 /* Report temp every so many cycles */
+
+/* Sensor limits and tuning parameters */
+
+#define INTAKE_LIMIT INTERNAL_TEMPS(60)
+#define T2_LIMIT INTERNAL_TEMPS(95)
+#define USERVER_LIMIT INTERNAL_TEMPS(75)
+
+#define TEMP_TOP INTERNAL_TEMPS(70)
+#define TEMP_BOTTOM INTERNAL_TEMPS(40)
+
+/*
+ * Toggling the fan constantly will wear it out (and annoy anyone who
+ * can hear it), so we'll only turn down the fan after the temperature
+ * has dipped a bit below the point at which we'd otherwise switch
+ * things up.
+ */
+
+#define COOLDOWN_SLOP INTERNAL_TEMPS(6)
+
+#define FAN_LOW 35
+#define FAN_MEDIUM 50
+#define FAN_HIGH 70
+#define FAN_MAX 99
+
+/*
+ * Mapping physical to hardware addresses for fans; it's different for
+ * RPM measuring and PWM setting, naturally. Doh.
+ */
+
+int fan_to_rpm_map[] = {3, 2, 0, 1};
+int fan_to_pwm_map[] = {7, 6, 0, 1};
+
+#define FANS 4
+
+/*
+ * The measured RPM of the fans doesn't match linearly to the requested
+ * rate. In addition, there are coaxially mounted fans, so the rear fans
+ * feed into the front fans. The rear fans will run slower since they're
+ * grabbing still air, and the front fants are getting an extra boost.
+ *
+ * We'd like to measure the fan RPM and compare it to the expected RPM
+ * so that we can detect failed fans, so we have a table (derived from
+ * hardware testing):
+ */
+
+struct rpm_to_pct_map {
+ ushort pct;
+ ushort rpm;
+};
+
+struct rpm_to_pct_map rpm_front_map[] = {{30, 6150},
+ {35, 7208},
+ {40, 8195},
+ {45, 9133},
+ {50, 10017},
+ {55, 10847},
+ {60, 11612},
+ {65, 12342},
+ {70, 13057},
+ {75, 13717},
+ {80, 14305},
+ {85, 14869},
+ {90, 15384},
+ {95, 15871},
+ {100, 16095}};
+
+struct rpm_to_pct_map rpm_rear_map[] = {{30, 3911},
+ {35, 4760},
+ {40, 5587},
+ {45, 6434},
+ {50, 7295},
+ {55, 8187},
+ {60, 9093},
+ {65, 10008},
+ {70, 10949},
+ {75, 11883},
+ {80, 12822},
+ {85, 13726},
+ {90, 14690},
+ {95, 15516},
+ {100, 15897}};
+
+#define FAN_FAILURE_OFFSET 30
+
+int fan_low = FAN_LOW;
+int fan_medium = FAN_MEDIUM;
+int fan_high = FAN_HIGH;
+int fan_max = FAN_MAX;
+int total_fans = FANS;
+int fan_offset = 0;
+
+int temp_bottom = TEMP_BOTTOM;
+int temp_top = TEMP_TOP;
+
+int report_temp = REPORT_TEMP;
+bool verbose = false;
+
+void usage() {
+ fprintf(stderr,
+ "fand [-v] [-l <low-pct>] [-m <medium-pct>] "
+ "[-h <high-pct>]\n"
+ "\t[-b <temp-bottom>] [-t <temp-top>] [-r <report-temp>]\n\n"
+ "\tlow-pct defaults to %d%% fan\n"
+ "\tmedium-pct defaults to %d%% fan\n"
+ "\thigh-pct defaults to %d%% fan\n"
+ "\ttemp-bottom defaults to %dC\n"
+ "\ttemp-top defaults to %dC\n"
+ "\treport-temp defaults to every %d measurements\n\n"
+ "fand compensates for uServer temperature reading %d degrees low\n"
+ "kill with SIGUSR1 to stop watchdog\n",
+ fan_low,
+ fan_medium,
+ fan_high,
+ EXTERNAL_TEMPS(temp_bottom),
+ EXTERNAL_TEMPS(temp_top),
+ report_temp,
+ EXTERNAL_TEMPS(USERVER_TEMP_FUDGE));
+ exit(1);
+}
+
+/* We need to open the device each time to read a value */
+
+int read_device(const char *device, int *value) {
+ FILE *fp;
+ int rc;
+
+ fp = fopen(device, "r");
+ if (!fp) {
+ int err = errno;
+
+ syslog(LOG_INFO, "failed to open device %s", device);
+ return err;
+ }
+
+ rc = fscanf(fp, "%d", value);
+ fclose(fp);
+
+ if (rc != 1) {
+ syslog(LOG_INFO, "failed to read device %s", device);
+ return ENOENT;
+ } else {
+ return 0;
+ }
+}
+
+/* We need to open the device again each time to write a value */
+
+int write_device(const char *device, const char *value) {
+ FILE *fp;
+ int rc;
+
+ fp = fopen(device, "w");
+ if (!fp) {
+ int err = errno;
+
+ syslog(LOG_INFO, "failed to open device for write %s", device);
+ return err;
+ }
+
+ rc = fputs(value, fp);
+ fclose(fp);
+
+ if (rc < 0) {
+ syslog(LOG_INFO, "failed to write device %s", device);
+ return ENOENT;
+ } else {
+ return 0;
+ }
+}
+
+int read_temp(const char *device, int *value) {
+ char full_name[LARGEST_DEVICE_NAME + 1];
+
+ /* We set an impossible value to check for errors */
+ *value = BAD_TEMP;
+ snprintf(
+ full_name, LARGEST_DEVICE_NAME, "%s/temp1_input", device);
+ return read_device(full_name, value);
+}
+
+int read_gpio_value(const int id, const char *device, int *value) {
+ char full_name[LARGEST_DEVICE_NAME];
+
+ snprintf(full_name, LARGEST_DEVICE_NAME, device, id);
+ return read_device(full_name, value);
+}
+
+int read_gpio_values(const int start, const int count,
+ const char *device, int *result) {
+ int status = 0;
+ int value;
+
+ *result = 0;
+ for (int i = 0; i < count; i++) {
+ status |= read_gpio_value(start + i, GPIO_PIN_ID, &value);
+ *result |= value << i;
+ }
+ return status;
+}
+
+int read_ids(int *rev_id, int *board_id) {
+ int status = 0;
+ int value;
+
+ status = read_gpio_values(GPIO_REV_ID_START, REV_IDS, GPIO_PIN_ID, rev_id);
+ if (status != 0) {
+ syslog(LOG_INFO, "failed to read rev_id");
+ return status;
+ }
+
+ int board_id_start;
+ if (*rev_id >= REV_ID_NEW_BOARD_ID) {
+ board_id_start = GPIO_BOARD_ID_START_NEW;
+ } else {
+ board_id_start = GPIO_BOARD_ID_START;
+ }
+
+ status = read_gpio_values(board_id_start, BOARD_IDS, GPIO_PIN_ID, board_id);
+ if (status != 0) {
+ syslog(LOG_INFO, "failed to read board_id");
+ }
+ return status;
+}
+
+bool is_two_fan_board(bool verbose) {
+ struct wedge_eeprom_st eeprom;
+ /* Retrieve the board type from EEPROM */
+ if (wedge_eeprom_parse(NULL, &eeprom) == 0) {
+ /* able to parse EEPROM */
+ if (verbose) {
+ syslog(LOG_INFO, "board type is %s", eeprom.fbw_location);
+ }
+ /* only WEDGE is NOT two-fan board */
+ return strncasecmp(eeprom.fbw_location, "wedge",
+ sizeof(eeprom.fbw_location));
+ } else {
+ int status;
+ int board_id = 0;
+ int rev_id = 0;
+ /*
+ * Could not parse EEPROM. Most likely, it is an old HW without EEPROM.
+ * In this case, use board ID to distinguish if it is wedge or 6-pack.
+ */
+ status = read_ids(&rev_id, &board_id);
+ if (verbose) {
+ syslog(LOG_INFO, "rev ID %d, board id %d", rev_id, board_id);
+ }
+ if (status == 0 && board_id != 0xf) {
+ return true;
+ } else {
+ return false;
+ }
+ }
+}
+
+int read_fan_value(const int fan, const char *device, int *value) {
+ char device_name[LARGEST_DEVICE_NAME];
+ char output_value[LARGEST_DEVICE_NAME];
+ char full_name[LARGEST_DEVICE_NAME];
+
+ snprintf(device_name, LARGEST_DEVICE_NAME, device, fan);
+ snprintf(full_name, LARGEST_DEVICE_NAME, "%s/%s", PWM_DIR, device_name);
+ return read_device(full_name, value);
+}
+
+int write_fan_value(const int fan, const char *device, const int value) {
+ char full_name[LARGEST_DEVICE_NAME];
+ char device_name[LARGEST_DEVICE_NAME];
+ char output_value[LARGEST_DEVICE_NAME];
+
+ snprintf(device_name, LARGEST_DEVICE_NAME, device, fan);
+ snprintf(full_name, LARGEST_DEVICE_NAME, "%s/%s", PWM_DIR, device_name);
+ snprintf(output_value, LARGEST_DEVICE_NAME, "%d", value);
+ return write_device(full_name, output_value);
+}
+
+/* Return fan speed as a percentage of maximum -- not necessarily linear. */
+
+int fan_rpm_to_pct(const struct rpm_to_pct_map *table,
+ const int table_len,
+ int rpm) {
+ int i;
+
+ for (i = 0; i < table_len; i++) {
+ if (table[i].rpm > rpm) {
+ break;
+ }
+ }
+
+ /*
+ * If the fan RPM is lower than the lowest value in the table,
+ * we may have a problem -- fans can only go so slow, and it might
+ * have stopped. In this case, we'll return an interpolated
+ * percentage, as just returning zero is even more problematic.
+ */
+
+ if (i == 0) {
+ return (rpm * table[i].pct) / table[i].rpm;
+ } else if (i == table_len) { // Fell off the top?
+ return table[i - 1].pct;
+ }
+
+ // Interpolate the right percentage value:
+
+ int percent_diff = table[i].pct - table[i - 1].pct;
+ int rpm_diff = table[i].rpm - table[i - 1].rpm;
+ int fan_diff = table[i].rpm - rpm;
+
+ return table[i].pct - (fan_diff * percent_diff / rpm_diff);
+}
+
+int fan_speed_okay(const int fan, const int speed, const int slop) {
+ int front_fan, rear_fan;
+ int front_pct, rear_pct;
+ int real_fan;
+ int okay;
+
+ /*
+ * The hardware fan numbers are different from the physical order
+ * in the box, so we have to map them:
+ */
+
+ real_fan = fan_to_rpm_map[fan];
+
+ front_fan = 0;
+ rear_fan = 0;
+ read_fan_value(real_fan, "tacho%d_rpm", &front_fan);
+ read_fan_value(real_fan + 4, "tacho%d_rpm", &rear_fan);
+
+ front_pct =
+ fan_rpm_to_pct(rpm_front_map,
+ sizeof(rpm_front_map) / sizeof(struct rpm_to_pct_map),
+ front_fan);
+ rear_pct =
+ fan_rpm_to_pct(rpm_rear_map,
+ sizeof(rpm_rear_map) / sizeof(struct rpm_to_pct_map),
+ rear_fan);
+
+ /*
+ * If the fans are broken, the measured rate will be rather
+ * different from the requested rate, and we can turn up the
+ * rest of the fans to compensate. The slop is the percentage
+ * of error that we'll tolerate.
+ *
+ * XXX: I suppose that we should only measure negative values;
+ * running too fast isn't really a problem.
+ */
+
+ okay = (abs(front_pct - speed) * 100 / speed < slop &&
+ abs(rear_pct - speed) * 100 / speed < slop);
+
+ if (!okay || verbose) {
+ syslog(!okay ? LOG_ALERT : LOG_INFO,
+ "fan %d rear %d (%d%%), front %d (%d%%), expected %d",
+ fan,
+ rear_fan,
+ rear_pct,
+ front_fan,
+ front_pct,
+ speed);
+ }
+
+ return okay;
+}
+
+/* Set fan speed as a percentage */
+
+int write_fan_speed(const int fan, const int value) {
+ /*
+ * The hardware fan numbers for pwm control are different from
+ * both the physical order in the box, and the mapping for reading
+ * the RPMs per fan, above.
+ */
+
+ int real_fan = fan_to_pwm_map[fan];
+
+ if (value == 0) {
+ return write_fan_value(real_fan, "pwm%d_en", 0);
+ } else {
+ int unit = value * PWM_UNIT_MAX / 100;
+ int status;
+
+ if (unit == PWM_UNIT_MAX)
+ unit = 0;
+
+ if ((status = write_fan_value(real_fan, "pwm%d_type", 0)) != 0 ||
+ (status = write_fan_value(real_fan, "pwm%d_rising", 0)) != 0 ||
+ (status = write_fan_value(real_fan, "pwm%d_falling", unit)) != 0 ||
+ (status = write_fan_value(real_fan, "pwm%d_en", 1)) != 0) {
+ return status;
+ }
+ }
+}
+
+/* Set up fan LEDs */
+
+int write_fan_led(const int fan, const char *color)
+{
+ return write_device(fan_led[fan], color);
+}
+
+int server_shutdown(const char *why) {
+ int fan;
+ for (fan = 0; fan < total_fans; fan++) {
+ write_fan_speed(fan + fan_offset, fan_max);
+ }
+
+ syslog(LOG_EMERG, "Shutting down: %s", why);
+ write_device(GPIO_USERVER_POWER_DIRECTION, "out");
+ write_device(GPIO_USERVER_POWER, "0");
+ /*
+ * Putting T2 in reset generating a non-maskable interrupt to uS,
+ * the kernel running on uS might panic depending on its version.
+ * sleep 5s here to make sure uS is completely down.
+ */
+ sleep(5);
+ write_device(GPIO_T2_POWER_DIRECTION, "out");
+ write_device(GPIO_T2_POWER, "0");
+
+ /*
+ * We have to stop the watchdog, or the system will be automatically
+ * rebooted some seconds after fand exits (and stops kicking the
+ * watchdog).
+ */
+
+ stop_watchdog();
+
+ sleep(2);
+ exit(2);
+}
+
+/* Gracefully shut down on receipt of a signal */
+
+void fand_interrupt(int sig)
+{
+ int fan;
+ for (fan = 0; fan < total_fans; fan++) {
+ write_fan_speed(fan + fan_offset, fan_max);
+ }
+
+ syslog(LOG_ALERT, "Shutting down fand on signal %s", strsignal(sig));
+ if (sig == SIGUSR1) {
+ stop_watchdog();
+ }
+ exit(3);
+}
+
+int main(int argc, char **argv) {
+ /* Sensor values */
+
+ int intake_temp;
+ int exhaust_temp;
+ int t2_temp;
+ int userver_temp;
+
+ int fan_speed = FAN_HIGH;
+ int bad_reads = 0;
+ int fan_failure = 0;
+ int fan_speed_changes = 0;
+ int old_speed;
+
+ int fan_bad[FANS];
+ int fan;
+
+ unsigned log_count = 0; // How many times have we logged our temps?
+ int opt;
+ int prev_fans_bad = 0;
+
+ struct sigaction sa;
+
+ sa.sa_handler = fand_interrupt;
+ sa.sa_flags = 0;
+ sigemptyset(&sa.sa_mask);
+
+ sigaction(SIGTERM, &sa, NULL);
+ sigaction(SIGINT, &sa, NULL);
+ sigaction(SIGUSR1, &sa, NULL);
+
+ while ((opt = getopt(argc, argv, "l:m:h:b:t:r:v")) != -1) {
+ switch (opt) {
+ case 'l':
+ fan_low = atoi(optarg);
+ break;
+ case 'm':
+ fan_medium = atoi(optarg);
+ break;
+ case 'h':
+ fan_high = atoi(optarg);
+ break;
+ case 'b':
+ temp_bottom = INTERNAL_TEMPS(atoi(optarg));
+ break;
+ case 't':
+ temp_top = INTERNAL_TEMPS(atoi(optarg));
+ break;
+ case 'r':
+ report_temp = atoi(optarg);
+ break;
+ case 'v':
+ verbose = true;
+ break;
+ default:
+ usage();
+ break;
+ }
+ }
+
+ if (optind > argc) {
+ usage();
+ }
+
+ if (temp_bottom > temp_top) {
+ fprintf(stderr,
+ "Should temp-bottom (%d) be higher than "
+ "temp-top (%d)? Starting anyway.\n",
+ EXTERNAL_TEMPS(temp_bottom),
+ EXTERNAL_TEMPS(temp_top));
+ }
+
+ if (fan_low > fan_medium || fan_low > fan_high || fan_medium > fan_high) {
+ fprintf(stderr,
+ "fan RPMs not strictly increasing "
+ "-- %d, %d, %d, starting anyway\n",
+ fan_low,
+ fan_medium,
+ fan_high);
+ }
+
+ daemon(1, 0);
+ openlog("fand", LOG_CONS, LOG_DAEMON);
+
+ /* Start watchdog in manual mode */
+ start_watchdog(0);
+
+ /* Set watchdog to persistent mode so timer expiry will happen independent
+ * of this process's liveliness. */
+ set_persistent_watchdog(WATCHDOG_SET_PERSISTENT);
+
+ if (is_two_fan_board(verbose)) {
+ /* Alternate, two fan configuration */
+ total_fans = 2;
+ fan_offset = 2; /* fan 3 is the first */
+ }
+
+ for (fan = 0; fan < total_fans; fan++) {
+ fan_bad[fan] = 0;
+ write_fan_speed(fan + fan_offset, fan_speed);
+ write_fan_led(fan + fan_offset, FAN_LED_BLUE);
+ }
+
+ sleep(5); /* Give the fans time to come up to speed */
+
+ while (1) {
+ int max_temp;
+ old_speed = fan_speed;
+
+ /* Read sensors */
+
+ read_temp(INTAKE_TEMP_DEVICE, &intake_temp);
+ read_temp(EXHAUST_TEMP_DEVICE, &exhaust_temp);
+ read_temp(T2_TEMP_DEVICE, &t2_temp);
+ read_temp(USERVER_TEMP_DEVICE, &userver_temp);
+
+ /*
+ * uServer can be powered down, but all of the rest of the sensors
+ * should be readable at any time.
+ */
+
+ if ((intake_temp == BAD_TEMP || exhaust_temp == BAD_TEMP ||
+ t2_temp == BAD_TEMP)) {
+ bad_reads++;
+ }
+
+ if (bad_reads > BAD_READ_THRESHOLD) {
+ server_shutdown("Some sensors couldn't be read");
+ }
+
+ if (log_count++ % report_temp == 0) {
+ syslog(LOG_DEBUG,
+ "Temp intake %d, t2 %d, userver %d, exhaust %d, "
+ "fan speed %d, speed changes %d",
+ intake_temp,
+ t2_temp,
+ userver_temp,
+ exhaust_temp,
+ fan_speed,
+ fan_speed_changes);
+ }
+
+ /* Protection heuristics */
+
+ if (intake_temp > INTAKE_LIMIT) {
+ server_shutdown("Intake temp limit reached");
+ }
+
+ if (t2_temp > T2_LIMIT) {
+ server_shutdown("T2 temp limit reached");
+ }
+
+ if (userver_temp + USERVER_TEMP_FUDGE > USERVER_LIMIT) {
+ server_shutdown("uServer temp limit reached");
+ }
+
+ /*
+ * Calculate change needed -- we should eventually
+ * do something more sophisticated, like PID.
+ *
+ * We should use the intake temperature to adjust this
+ * as well.
+ */
+
+ if (t2_temp > userver_temp + USERVER_TEMP_FUDGE) {
+ max_temp = t2_temp;
+ } else {
+ max_temp = userver_temp + USERVER_TEMP_FUDGE;
+ }
+
+ /*
+ * If recovering from a fan problem, spin down fans gradually in case
+ * temperatures are still high. Gradual spin down also reduces wear on
+ * the fans.
+ */
+ if (fan_speed == fan_max) {
+ if (fan_failure == 0) {
+ fan_speed = fan_high;
+ }
+ } else if (fan_speed == fan_high) {
+ if (max_temp + COOLDOWN_SLOP < temp_top) {
+ fan_speed = fan_medium;
+ }
+ } else if (fan_speed == fan_medium) {
+ if (max_temp > temp_top) {
+ fan_speed = fan_high;
+ } else if (max_temp + COOLDOWN_SLOP < temp_bottom) {
+ fan_speed = fan_low;
+ }
+ } else {/* low */
+ if (max_temp > temp_bottom) {
+ fan_speed = fan_medium;
+ }
+ }
+
+ /*
+ * Update fans only if there are no failed ones. If any fans failed
+ * earlier, all remaining fans should continue to run at max speed.
+ */
+
+ if (fan_failure == 0 && fan_speed != old_speed) {
+ syslog(LOG_NOTICE,
+ "Fan speed changing from %d to %d",
+ old_speed,
+ fan_speed);
+ fan_speed_changes++;
+ for (fan = 0; fan < total_fans; fan++) {
+ write_fan_speed(fan + fan_offset, fan_speed);
+ }
+ }
+
+ /*
+ * Wait for some change. Typical I2C temperature sensors
+ * only provide a new value every second and a half, so
+ * checking again more quickly than that is a waste.
+ *
+ * We also have to wait for the fan changes to take effect
+ * before measuring them.
+ */
+
+ sleep(5);
+
+ /* Check fan RPMs */
+
+ for (fan = 0; fan < total_fans; fan++) {
+ /*
+ * Make sure that we're within some percentage
+ * of the requested speed.
+ */
+ if (fan_speed_okay(fan + fan_offset, fan_speed, FAN_FAILURE_OFFSET)) {
+ if (fan_bad[fan] > FAN_FAILURE_THRESHOLD) {
+ write_fan_led(fan + fan_offset, FAN_LED_BLUE);
+ syslog(LOG_NOTICE,
+ "Fan %d has recovered",
+ fan);
+ }
+ fan_bad[fan] = 0;
+ } else {
+ fan_bad[fan]++;
+ }
+ }
+
+ fan_failure = 0;
+ for (fan = 0; fan < total_fans; fan++) {
+ if (fan_bad[fan] > FAN_FAILURE_THRESHOLD) {
+ fan_failure++;
+ write_fan_led(fan + fan_offset, FAN_LED_RED);
+ }
+ }
+
+ if (fan_failure > 0) {
+ if (prev_fans_bad != fan_failure) {
+ syslog(LOG_ALERT, "%d fans failed", fan_failure);
+ }
+
+ /*
+ * If fans are bad, we need to blast all of the
+ * fans at 100%; we don't bother to turn off
+ * the bad fans, in case they are all that is left.
+ *
+ * Note that we have a temporary bug with setting fans to
+ * 100% so we only do fan_max = 99%.
+ */
+
+ fan_speed = fan_max;
+ for (fan = 0; fan < total_fans; fan++) {
+ write_fan_speed(fan + fan_offset, fan_speed);
+ }
+
+ /*
+ * Fans can be hot swapped and replaced; in which case the fan daemon
+ * will automatically detect the new fan and (assuming the new fan isn't
+ * itself faulty), automatically readjust the speeds for all fans down
+ * to a more suitable rpm. The fan daemon does not need to be restarted.
+ */
+ }
+
+ /* Suppress multiple warnings for similar number of fan failures. */
+ prev_fans_bad = fan_failure;
+
+ /* if everything is fine, restart the watchdog countdown. If this process
+ * is terminated, the persistent watchdog setting will cause the system
+ * to reboot after the watchdog timeout. */
+ kick_watchdog();
+ }
+}
diff --git a/meta-facebook/meta-wedge/recipes-wedge/fan-ctrl/fan-ctrl/get_fan_speed.sh b/meta-facebook/meta-wedge/recipes-wedge/fan-ctrl/fan-ctrl/get_fan_speed.sh
new file mode 100755
index 0000000..4e36a7c
--- /dev/null
+++ b/meta-facebook/meta-wedge/recipes-wedge/fan-ctrl/fan-ctrl/get_fan_speed.sh
@@ -0,0 +1,59 @@
+#!/bin/sh
+#
+# Copyright 2004-present Facebook. All Rights Reserved.
+#
+# This program file is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by the
+# Free Software Foundation; version 2 of the License.
+#
+# This program is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+# for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program in a file named COPYING; if not, write to the
+# Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor,
+# Boston, MA 02110-1301 USA
+#
+usage() {
+ echo "Usage: $0 [Fan Unit (0..3)]" >&2
+}
+
+PWM_DIR=/sys/devices/platform/ast_pwm_tacho.0
+set -e
+
+# refer to the comments in init_pwn.sh regarding
+# the fan unit and tacho mapping
+if [ "$#" -eq 0 ]; then
+ TACHOS="0:3 1:2 2:0 3:1"
+elif [ "$#" -eq 1 ]; then
+ case "$1" in
+ "0")
+ TACHOS="0:3"
+ ;;
+ "1")
+ TACHOS="1:2"
+ ;;
+ "2")
+ TACHOS="2:0"
+ ;;
+ "3")
+ TACHOS="3:1"
+ ;;
+ *)
+ usage
+ exit 1
+ ;;
+ esac
+else
+ usage
+ exit 1
+fi
+
+for fan_tacho in $TACHOS; do
+ fan=${fan_tacho%%:*}
+ tacho=${fan_tacho##*:}
+ echo "Fan $fan RPMs: $(cat $PWM_DIR/tacho${tacho}_rpm), $(cat $PWM_DIR/tacho$((tacho+4))_rpm)"
+done
diff --git a/meta-facebook/meta-wedge/recipes-wedge/fan-ctrl/fan-ctrl/init_pwm.sh b/meta-facebook/meta-wedge/recipes-wedge/fan-ctrl/fan-ctrl/init_pwm.sh
new file mode 100755
index 0000000..cf545be
--- /dev/null
+++ b/meta-facebook/meta-wedge/recipes-wedge/fan-ctrl/fan-ctrl/init_pwm.sh
@@ -0,0 +1,71 @@
+#!/bin/sh
+#
+# Copyright 2004-present Facebook. All Rights Reserved.
+#
+# This program file is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by the
+# Free Software Foundation; version 2 of the License.
+#
+# This program is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+# for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program in a file named COPYING; if not, write to the
+# Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor,
+# Boston, MA 02110-1301 USA
+#
+PWM_DIR=/sys/devices/platform/ast_pwm_tacho.0
+
+set -e
+
+# The PWM frequency is
+
+# clk_source / ((2 ^ division_) * (2 * division_l) * (unit + 1))
+#
+# Our clk_source is 24Mhz. 4-pin fans are generally supposed to be driven with
+# a 25Khz PWM control signal. Therefore we want the divisor to equal 960.
+#
+# We also want the unit to be as large as possible, since this controls the
+# granularity with which we can modulate the PWM signal. The following
+# settings allow us to set the fan from 0 to 100% in increments of 1/96th.
+#
+# The AST chip supports 3 different PWM clock configurations, but we only use
+# type M for now.
+echo 0 > $PWM_DIR/pwm_type_m_division_h
+echo 5 > $PWM_DIR/pwm_type_m_division_l
+echo 95 > $PWM_DIR/pwm_type_m_unit
+
+# On wedge, there are 4 fans connected.
+# Each fan has one PWM input and 2 tacho outputs.
+# Here is the mapping between the fan and PWN/Tacho,
+# staring from the one from the edge
+# Fan 0: PWM 7, Tacho3, Tacho7
+# Fan 1: PWM 6, Tacho2, Tacho6
+# Fan 2: PWM 0, Tacho0, Tacho4
+# Fan 3: PWM 1, Tacho1, Tacho5
+
+# For each fan, setting the type, and 100% initially
+for pwm in 0 1 6 7; do
+ echo 0 > $PWM_DIR/pwm${pwm}_type
+ echo 0 > $PWM_DIR/pwm${pwm}_rising
+ echo 0 > $PWM_DIR/pwm${pwm}_falling
+ echo 1 > $PWM_DIR/pwm${pwm}_en
+done
+
+# Enable Tach 0..7
+echo 0 > $PWM_DIR/tacho0_source
+echo 0 > $PWM_DIR/tacho4_source
+echo 1 > $PWM_DIR/tacho1_source
+echo 1 > $PWM_DIR/tacho5_source
+echo 6 > $PWM_DIR/tacho2_source
+echo 6 > $PWM_DIR/tacho6_source
+echo 7 > $PWM_DIR/tacho3_source
+echo 7 > $PWM_DIR/tacho7_source
+t=0
+while [ $t -le 7 ]; do
+ echo 1 > $PWM_DIR/tacho${t}_en
+ t=$((t+1))
+done
diff --git a/meta-facebook/meta-wedge/recipes-wedge/fan-ctrl/fan-ctrl/set_fan_speed.sh b/meta-facebook/meta-wedge/recipes-wedge/fan-ctrl/fan-ctrl/set_fan_speed.sh
new file mode 100755
index 0000000..a71850f
--- /dev/null
+++ b/meta-facebook/meta-wedge/recipes-wedge/fan-ctrl/fan-ctrl/set_fan_speed.sh
@@ -0,0 +1,85 @@
+#!/bin/sh
+#
+# Copyright 2004-present Facebook. All Rights Reserved.
+#
+# This program file is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by the
+# Free Software Foundation; version 2 of the License.
+#
+# This program is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+# for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program in a file named COPYING; if not, write to the
+# Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor,
+# Boston, MA 02110-1301 USA
+#
+usage() {
+ echo "Usage: $0 <PERCENT (0..100)> <Fan Unit (0..3)> " >&2
+}
+
+PWM_DIR=/sys/devices/platform/ast_pwm_tacho.0
+
+# The maximum unit setting.
+# This should be the value in pwm_type_m_unit plus 1
+PWM_UNIT_MAX=96
+
+set -e
+
+if [ "$#" -ne 2 ] && [ "$#" -ne 1 ]; then
+ usage
+ exit 1
+fi
+
+# refer to the comments in init_pwn.sh regarding
+# the fan unit and PWM mapping
+if [ "$#" -eq 1 ]; then
+ PWMS="0:7 1:6 2:0 3:1"
+else
+ case "$2" in
+ "0")
+ PWMS="0:7"
+ ;;
+ "1")
+ PWMS="1:6"
+ ;;
+ "2")
+ PWMS="2:0"
+ ;;
+ "3")
+ PWMS="3:1"
+ ;;
+ *)
+ usage
+ exit 1
+ ;;
+ esac
+fi
+
+# Convert the percentage to our 1/96th unit.
+unit=$(( ( $1 * $PWM_UNIT_MAX ) / 100 ))
+
+for FAN_PWM in $PWMS; do
+ FAN_N=${FAN_PWM%%:*}
+ PWM_N=${FAN_PWM##*:}
+ if [ "$unit" -eq 0 ]; then
+ # For 0%, turn off the PWM entirely
+ echo 0 > $PWM_DIR/pwm${PWM_N}_en
+ else
+ if [ "$unit" -eq $PWM_UNIT_MAX ]; then
+ # For 100%, set falling and rising to the same value
+ unit=0
+ fi
+
+ # always use type M. refer to the comments in init_pwm.sh
+ echo 0 > $PWM_DIR/pwm${PWM_N}_type
+ echo 0 > $PWM_DIR/pwm${PWM_N}_rising
+ echo "$unit" > $PWM_DIR/pwm${PWM_N}_falling
+ echo 1 > $PWM_DIR/pwm${PWM_N}_en
+ fi
+
+ echo "Successfully set fan ${FAN_N} (PWM: $PWM_N) speed to $1%"
+done
diff --git a/meta-facebook/meta-wedge/recipes-wedge/fan-ctrl/fan-ctrl/setup-fan.sh b/meta-facebook/meta-wedge/recipes-wedge/fan-ctrl/fan-ctrl/setup-fan.sh
new file mode 100644
index 0000000..0cbdb24
--- /dev/null
+++ b/meta-facebook/meta-wedge/recipes-wedge/fan-ctrl/fan-ctrl/setup-fan.sh
@@ -0,0 +1,23 @@
+#!/bin/sh
+#
+# Copyright 2014-present Facebook. All Rights Reserved.
+#
+### BEGIN INIT INFO
+# Provides: setup-fan
+# Required-Start: board-id
+# Required-Stop:
+# Default-Start: S
+# Default-Stop:
+# Short-Description: Set fan speed
+### END INIT INFO
+
+. /usr/local/fbpackages/utils/ast-functions
+
+# Enable the isolation buffer
+wedge_iso_buf_enable
+
+echo -n "Setup fan speed... "
+/usr/local/bin/init_pwm.sh
+/usr/local/bin/set_fan_speed.sh 50
+/usr/local/bin/fand
+echo "done."
diff --git a/meta-facebook/meta-wedge/recipes-wedge/fan-ctrl/fan-ctrl/watchdog.cpp b/meta-facebook/meta-wedge/recipes-wedge/fan-ctrl/fan-ctrl/watchdog.cpp
new file mode 100644
index 0000000..ebb390a
--- /dev/null
+++ b/meta-facebook/meta-wedge/recipes-wedge/fan-ctrl/fan-ctrl/watchdog.cpp
@@ -0,0 +1,201 @@
+/*
+ * watchdog
+ *
+ * Copyright 2014-present Facebook. All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include "watchdog.h"
+
+#include <errno.h>
+#include <fcntl.h>
+#include <pthread.h>
+#include <syslog.h>
+#include <unistd.h>
+
+#define WATCHDOG_START_KEY "x"
+#define WATCHDOG_STOP_KEY "X"
+/* The "magic close" character (as defined in Linux watchdog specs). */
+#define WATCHDOG_PERSISTENT_KEY "V"
+#define WATCHDOG_NON_PERSISTENT_KEY "a"
+
+static int watchdog_dev = -1;
+
+/* This is needed to prevent rapid consecutive stop/start watchdog calls from
+ * generating multiple threads. */
+static int watchdog_started = 0;
+
+static const char* watchdog_kick_key = WATCHDOG_PERSISTENT_KEY;
+static pthread_t watchdog_tid;
+static pthread_mutex_t watchdog_lock = PTHREAD_MUTEX_INITIALIZER;
+
+/* Forward declarations. */
+static void* watchdog_thread(void* args);
+static int kick_watchdog_unsafe();
+
+/*
+ * When started, this background thread will constantly reset the watchdog
+ * at every 5 second interval.
+ */
+
+static void* watchdog_thread(void* args) {
+
+ pthread_detach(pthread_self());
+
+ /* Make sure another instance of the thread hasn't already been started. */
+ pthread_mutex_lock(&watchdog_lock);
+ if (watchdog_started) {
+ goto done;
+ } else {
+ watchdog_started = 1;
+ }
+ pthread_mutex_unlock(&watchdog_lock);
+
+ /* Actual loop for refreshing the watchdog timer. */
+ while (1) {
+ pthread_mutex_lock(&watchdog_lock);
+ if (watchdog_dev != -1) {
+ kick_watchdog_unsafe();
+ } else {
+ break;
+ }
+ pthread_mutex_unlock(&watchdog_lock);
+ sleep(5);
+ }
+
+ /* Broke out of loop because watchdog was stopped. */
+ watchdog_started = 0;
+done:
+ pthread_mutex_unlock(&watchdog_lock);
+ return NULL;
+}
+
+/*
+ * Starts the watchdog timer. timer counts down and restarts the ARM chip
+ * upon timeout. use kick_watchdog() to restart the timer.
+ *
+ * Returns: 1 on success; 0 otherwise.
+ */
+
+int start_watchdog(const int auto_mode) {
+ int status;
+
+ pthread_mutex_lock(&watchdog_lock);
+
+ /* Don't start the watchdog again if it has already been started. */
+ if (watchdog_dev != -1) {
+ while ((status = write(watchdog_dev, WATCHDOG_START_KEY, 1)) == 0
+ && errno == EINTR);
+ pthread_mutex_unlock(&watchdog_lock);
+ syslog(LOG_ALERT, "system watchdog already started.\n");
+ return 0;
+ }
+
+ while (((watchdog_dev = open("/dev/watchdog", O_WRONLY)) == -1) &&
+ errno == EINTR);
+
+ /* Fail if watchdog device is invalid or if the user asked for auto
+ * mode and the thread failed to spawn. */
+ if ((watchdog_dev == -1) ||
+ (auto_mode == 1 && watchdog_started == 0 &&
+ pthread_create(&watchdog_tid, NULL, watchdog_thread, NULL) != 0)) {
+ goto fail;
+ }
+
+ while ((status = write(watchdog_dev, WATCHDOG_START_KEY, 1)) == 0
+ && errno == EINTR);
+ pthread_mutex_unlock(&watchdog_lock);
+ syslog(LOG_INFO, "system watchdog started.\n");
+ return 1;
+
+fail:
+ if (watchdog_dev != -1) {
+ close(watchdog_dev);
+ watchdog_dev = -1;
+ }
+
+ pthread_mutex_unlock(&watchdog_lock);
+ syslog(LOG_ALERT, "system watchdog failed to start!\n");
+ return 0;
+}
+
+/*
+ * Toggles between watchdog persistent modes. In persistent mode, the watchdog
+ * timer will continue to tick even after process shutdown. Under non-
+ * persistent mode, the watchdog timer will automatically be disabled when the
+ * process shuts down.
+ */
+void set_persistent_watchdog(enum watchdog_persistent_en persistent) {
+ switch (persistent) {
+ case WATCHDOG_SET_PERSISTENT:
+ watchdog_kick_key = WATCHDOG_PERSISTENT_KEY;
+ break;
+ default:
+ watchdog_kick_key = WATCHDOG_NON_PERSISTENT_KEY;
+ break;
+ }
+ kick_watchdog();
+}
+
+/*
+ * Restarts the countdown timer on the watchdog, delaying restart by another
+ * timeout period (default: 11 seconds as configured in the device driver).
+ *
+ * This function assumes the watchdog lock has already been acquired and is
+ * only used internally within the watchdog code.
+ *
+ * Returns 1 on success; 0 or -1 indicates failure (check errno).
+ */
+
+static int kick_watchdog_unsafe() {
+ int status = 0;
+ if (watchdog_dev != -1) {
+ while ((status = write(watchdog_dev, watchdog_kick_key, 1)) == 0
+ && errno == EINTR);
+ }
+ return status;
+}
+
+/*
+ * Acquires the watchdog lock and resets the watchdog atomically. For use by
+ * library users.
+ */
+
+int kick_watchdog() {
+ int result;
+ pthread_mutex_lock(&watchdog_lock);
+ result = kick_watchdog_unsafe();
+ pthread_mutex_unlock(&watchdog_lock);
+
+ return result;
+}
+
+/* Shuts down the watchdog gracefully and disables the watchdog timer so that
+ * restarts no longer happen.
+ */
+
+void stop_watchdog() {
+ int status;
+ pthread_mutex_lock(&watchdog_lock);
+ if (watchdog_dev != -1) {
+ while ((status = write(watchdog_dev, WATCHDOG_STOP_KEY, 1)) == 0
+ && errno == EINTR);
+ close(watchdog_dev);
+ watchdog_dev = -1;
+ syslog(LOG_INFO, "system watchdog stopped.\n");
+ }
+ pthread_mutex_unlock(&watchdog_lock);
+}
diff --git a/meta-facebook/meta-wedge/recipes-wedge/fan-ctrl/fan-ctrl/watchdog.h b/meta-facebook/meta-wedge/recipes-wedge/fan-ctrl/fan-ctrl/watchdog.h
new file mode 100644
index 0000000..19b9944
--- /dev/null
+++ b/meta-facebook/meta-wedge/recipes-wedge/fan-ctrl/fan-ctrl/watchdog.h
@@ -0,0 +1,60 @@
+/*
+ * watchdog
+ *
+ * Copyright 2014-present Facebook. All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * Utility library to handle the aspeed watchdog. Only one watchdog
+ * should be in use at any time throughout the entire system (multiple users
+ * will not cause adverse effects but the behavior of the watchdog becomes
+ * undefined).
+ *
+ * The watchdog can be started in either manual or automatic mode. In manual
+ * mode, the watchdog has to be constantly reset by the user via the
+ * kick_watchdog() function. Under automatic mode, the watchdog will
+ * run in a separate thread and reset the timer on its own so no intervention
+ * is required from the user.
+ *
+ * In both modes, the watchdog timer will not stop when the process is
+ * terminated, unless a call to stop_watchdog() has been made beforehand, or
+ * if the user runs in manual mode and uses a non persistent watchdog kick.
+ *
+ * The default timeout for the watchdog is 11 seconds. When this time period
+ * elapses, the ARM chip is restarted and the kernel is rebooted. Other
+ * hardware state is not reset, so this may introduce strange behavior on
+ * reboot (example: an I2C bus may be left in the open state, triggering
+ * constant interrupts). In rare cases, this could result in the kernel
+ * failing to fully restart itself and thus preclude the possibility of
+ * reinitializing the watchdog timer. Someone will then have to go over and
+ * physically restart the machine.
+ *
+ * The alternative to the soft reset is to request the watchdog device driver
+ * for a hard reset on timeout. However this will stop the fans. If the
+ * kernel fails to fully boot and restart the fan daemon, the system could
+ * overheat. For this reason, we've chosen to take the risk of a stuck soft
+ * reset instead.
+ *
+ */
+
+/* Forward declarations. */
+int start_watchdog(const int auto_mode);
+enum watchdog_persistent_en {
+ WATCHDOG_SET_PERSISTENT,
+ WATCHDOG_SET_NONPERSISTENT,
+};
+void set_persistent_watchdog(enum watchdog_persistent_en persistent);
+int kick_watchdog();
+void stop_watchdog();
diff --git a/meta-facebook/meta-wedge/recipes-wedge/fan-ctrl/fan-ctrl_0.1.bb b/meta-facebook/meta-wedge/recipes-wedge/fan-ctrl/fan-ctrl_0.1.bb
new file mode 100644
index 0000000..6e0c980
--- /dev/null
+++ b/meta-facebook/meta-wedge/recipes-wedge/fan-ctrl/fan-ctrl_0.1.bb
@@ -0,0 +1,59 @@
+# Copyright 2014-present Facebook. All Rights Reserved.
+SUMMARY = "Fan controller"
+DESCRIPTION = "The utilities to control fan."
+SECTION = "base"
+PR = "r1"
+LICENSE = "GPLv2"
+LIC_FILES_CHKSUM = "file://fand.cpp;beginline=6;endline=18;md5=da35978751a9d71b73679307c4d296ec"
+
+DEPENDS_append = "libwedge-eeprom update-rc.d-native"
+
+SRC_URI = "file://get_fan_speed.sh \
+ file://init_pwm.sh \
+ file://set_fan_speed.sh \
+ file://README \
+ file://setup-fan.sh \
+ file://Makefile \
+ file://fand.cpp \
+ file://watchdog.h \
+ file://watchdog.cpp \
+ "
+
+S = "${WORKDIR}"
+
+binfiles = "get_fan_speed.sh \
+ init_pwm.sh \
+ set_fan_speed.sh \
+ fand \
+ "
+
+otherfiles = "README"
+
+pkgdir = "fan_ctrl"
+
+do_install() {
+ dst="${D}/usr/local/fbpackages/${pkgdir}"
+ bin="${D}/usr/local/bin"
+ install -d $dst
+ install -d $bin
+ for f in ${binfiles}; do
+ install -m 755 $f ${dst}/$f
+ ln -snf ../fbpackages/${pkgdir}/$f ${bin}/$f
+ done
+ for f in ${otherfiles}; do
+ install -m 644 $f ${dst}/$f
+ done
+ install -d ${D}${sysconfdir}/init.d
+ install -d ${D}${sysconfdir}/rcS.d
+ install -m 755 setup-fan.sh ${D}${sysconfdir}/init.d/setup-fan.sh
+ update-rc.d -r ${D} setup-fan.sh start 91 S .
+}
+
+FBPACKAGEDIR = "${prefix}/local/fbpackages"
+
+FILES_${PN} = "${FBPACKAGEDIR}/fan_ctrl ${prefix}/local/bin ${sysconfdir} "
+
+# Inhibit complaints about .debug directories for the fand binary:
+
+INHIBIT_PACKAGE_DEBUG_SPLIT = "1"
+INHIBIT_PACKAGE_STRIP = "1"
diff --git a/meta-facebook/meta-wedge/recipes-wedge/fblibs/files/alert_control/Makefile b/meta-facebook/meta-wedge/recipes-wedge/fblibs/files/alert_control/Makefile
new file mode 100644
index 0000000..74ce8f3
--- /dev/null
+++ b/meta-facebook/meta-wedge/recipes-wedge/fblibs/files/alert_control/Makefile
@@ -0,0 +1,11 @@
+# Copyright 2014-present Facebook. All Rights Reserved.
+lib: libalert_control.so
+
+libalert_control.so: alert_control.c
+ $(CC) $(CCFLAGS) -fPIC -c -o alert_control.o alert_control.c
+ $(CC) -shared -o libalert_control.so alert_control.o -lc
+
+.PHONY: clean
+
+clean:
+ rm -rf *.o libalert_control.so
diff --git a/meta-facebook/meta-wedge/recipes-wedge/fblibs/files/alert_control/alert_control.c b/meta-facebook/meta-wedge/recipes-wedge/fblibs/files/alert_control/alert_control.c
new file mode 100644
index 0000000..81b0329
--- /dev/null
+++ b/meta-facebook/meta-wedge/recipes-wedge/fblibs/files/alert_control/alert_control.c
@@ -0,0 +1,117 @@
+/*
+ *
+ * Copyright 2014-present Facebook. All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <errno.h>
+#include <syslog.h>
+#include "alert_control.h"
+
+#define PATH_ALERT_STATUS "/sys/bus/i2c/drivers/panther_plus/4-0040/alert_status"
+#define PATH_ALERT_CONTROL "/sys/bus/i2c/drivers/panther_plus/4-0040/alert_control"
+
+#define MASK_ALERT_SMS_KCS 0x01
+
+/*
+ * Function to enable/disable alert signal generation for a given Function Block
+ */
+int
+alert_control(e_fbid_t id, e_flag_t cflag) {
+ FILE *fp;
+ unsigned char rbuf[5] = {0};
+ unsigned char tbuf[3] = {0};
+ int count = 0;
+
+ fp = fopen(PATH_ALERT_CONTROL, "r+");
+ if (!fp) {
+ return -1;
+ }
+
+ count = fread(rbuf, sizeof(unsigned char), sizeof(rbuf), fp);
+ if (count == 0x0) {
+ fclose(fp);
+ return -1;
+ }
+
+ // Size of the request
+ tbuf[0] = 0x02;
+
+ switch(id) {
+ case FBID_SMS_KCS:
+ if (cflag == FLAG_ENABLE)
+ tbuf[1] = rbuf[2] | (0x01 << FBID_SMS_KCS);
+ else
+ tbuf[1] = rbuf[2] & (~(0x01 << FBID_SMS_KCS));
+
+ tbuf[2] = rbuf[3];
+ break;
+ // TODO: Add logic for other Function Blocks here
+ default:
+ tbuf[0] = rbuf[2];
+ tbuf[1] = rbuf[3];
+ break;
+ }
+
+ count = fwrite(tbuf, sizeof(unsigned char), sizeof(tbuf), fp);
+ if (count != sizeof(tbuf)) {
+ fclose(fp);
+ return (-1);
+ }
+
+ fclose(fp);
+
+ return 0;
+}
+
+/*
+ * Function to check if the alert for a given Function Block is asserted or not
+ */
+bool
+is_alert_present(e_fbid_t id) {
+ FILE *fp;
+ unsigned char buf[5] = {0};
+ int count = 0;
+
+ fp = fopen(PATH_ALERT_STATUS, "r");
+
+ if (!fp) {
+ return false;
+ }
+
+ count = fread(buf, sizeof(unsigned char), sizeof(buf), fp);
+ if (count == 0x0) {
+ fclose(fp);
+ sleep(2);
+ return false;
+ }
+
+ fclose(fp);
+
+ switch(id) {
+ case FBID_SMS_KCS:
+ if (buf[2] & (0x01 << FBID_SMS_KCS))
+ return true;
+ else
+ return false;
+ //TODO: Add logic for other Function Blocks here
+ default:
+ return false;
+ }
+}
diff --git a/meta-facebook/meta-wedge/recipes-wedge/fblibs/files/alert_control/alert_control.h b/meta-facebook/meta-wedge/recipes-wedge/fblibs/files/alert_control/alert_control.h
new file mode 100644
index 0000000..ca72591
--- /dev/null
+++ b/meta-facebook/meta-wedge/recipes-wedge/fblibs/files/alert_control/alert_control.h
@@ -0,0 +1,64 @@
+/*
+ *
+ * Copyright 2014-present Facebook. All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef __ALERT_CONTROL_H__
+#define __ALERT_CONTROL_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <stdbool.h>
+
+typedef enum {
+ FLAG_DISABLE = 0x00,
+ FLAG_ENABLE,
+} e_flag_t;
+
+typedef enum {
+ FBID_SMS_KCS = 0x00,
+ FBID_SMM_KCS,
+ FBID_COM1_DATA,
+ FBID_COM2_DATA,
+ FBID_COM1_STAT_CTRL,
+ FBID_COM2_STAT_CTRL,
+ FBID_POST,
+ FBID_I2C_PROXY1_MASTER,
+ FBID_I2C_PROXY1_STAT,
+ FBID_I2C_PROXY2_MASTER,
+ FBID_I2C_PROXY2_STAT,
+ FBID_GPIO_CONFIG,
+ FBID_GPIO_OUTPUT,
+ FBID_GPIO_INPUT,
+ FBID_GPIO_INTR,
+ FBID_GPIO_EVENT,
+ FBID_REG_READ,
+ FBID_ALERT_CTRL = 0xFD,
+ FBID_AERT_STAT = 0xFE,
+ FBID_DISCOVERY = 0xFF,
+} e_fbid_t;
+
+int alert_control(e_fbid_t id, e_flag_t cflag);
+bool is_alert_present(e_fbid_t id);
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif /* __ALERT_CONTROL_H__ */
diff --git a/meta-facebook/meta-wedge/recipes-wedge/fblibs/files/ipmi/Makefile b/meta-facebook/meta-wedge/recipes-wedge/fblibs/files/ipmi/Makefile
new file mode 100644
index 0000000..8cb69e7
--- /dev/null
+++ b/meta-facebook/meta-wedge/recipes-wedge/fblibs/files/ipmi/Makefile
@@ -0,0 +1,11 @@
+# Copyright 2014-present Facebook. All Rights Reserved.
+lib: libipmi.so
+
+libipmi.so: ipmi.c
+ $(CC) $(CCFLAGS) -fPIC -c -o ipmi.o ipmi.c
+ $(CC) -shared -o libipmi.so ipmi.o -lc
+
+.PHONY: clean
+
+clean:
+ rm -rf *.o libipmi.so
diff --git a/meta-facebook/meta-wedge/recipes-wedge/fblibs/files/ipmi/ipmi.c b/meta-facebook/meta-wedge/recipes-wedge/fblibs/files/ipmi/ipmi.c
new file mode 100644
index 0000000..b5a3e19
--- /dev/null
+++ b/meta-facebook/meta-wedge/recipes-wedge/fblibs/files/ipmi/ipmi.c
@@ -0,0 +1,81 @@
+/*
+ *
+ * Copyright 2014-present Facebook. All Rights Reserved.
+ *
+ * This file contains code to support IPMI2.0 Specificaton available @
+ * http://www.intel.com/content/www/us/en/servers/ipmi/ipmi-specifications.html
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include "ipmi.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <string.h>
+#include <syslog.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+
+#define SOCK_PATH "/tmp/ipmi_socket"
+#define MAX_IPMI_RES_LEN 100
+
+/*
+ * Function to handle IPMI messages
+ */
+void
+ipmi_handle(unsigned char *request, unsigned char req_len,
+ unsigned char *response, unsigned char *res_len) {
+
+ int s, t, len;
+ struct sockaddr_un remote;
+
+ // TODO: Need to update to reuse the socket instead of creating new
+ if ((s = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) {
+ syslog(LOG_ALERT, "ipmi_handle: socket() failed\n");
+ return;
+ }
+
+ remote.sun_family = AF_UNIX;
+ strcpy(remote.sun_path, SOCK_PATH);
+ len = strlen(remote.sun_path) + sizeof(remote.sun_family);
+
+ if (connect(s, (struct sockaddr *)&remote, len) == -1) {
+ syslog(LOG_ALERT, "ipmi_handle: connect() failed\n");
+ return;
+ }
+
+ if (send(s, request, req_len, 0) == -1) {
+ syslog(LOG_ALERT, "ipmi_handle: send() failed\n");
+ return;
+ }
+
+ if ((t=recv(s, response, MAX_IPMI_RES_LEN, 0)) > 0) {
+ *res_len = t;
+ } else {
+ if (t < 0) {
+ syslog(LOG_ALERT, "ipmi_handle: recv() failed\n");
+ } else {
+ printf("Server closed connection");
+ }
+
+ return;
+ }
+
+ close(s);
+
+ return;
+}
diff --git a/meta-facebook/meta-wedge/recipes-wedge/fblibs/files/ipmi/ipmi.h b/meta-facebook/meta-wedge/recipes-wedge/fblibs/files/ipmi/ipmi.h
new file mode 100644
index 0000000..4c6ed62
--- /dev/null
+++ b/meta-facebook/meta-wedge/recipes-wedge/fblibs/files/ipmi/ipmi.h
@@ -0,0 +1,35 @@
+/*
+ *
+ * Copyright 2014-present Facebook. All Rights Reserved.
+ *
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef __IPMI_H__
+#define __IPMI_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void ipmi_handle(unsigned char *request, unsigned char req_len,
+ unsigned char *response, unsigned char *res_len);
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif /* __IPMI_H__ */
diff --git a/meta-facebook/meta-wedge/recipes-wedge/fblibs/libalert-control_0.1.bb b/meta-facebook/meta-wedge/recipes-wedge/fblibs/libalert-control_0.1.bb
new file mode 100644
index 0000000..2ae4ea7
--- /dev/null
+++ b/meta-facebook/meta-wedge/recipes-wedge/fblibs/libalert-control_0.1.bb
@@ -0,0 +1,24 @@
+# Copyright 2014-present Facebook. All Rights Reserved.
+SUMMARY = "Wedge Alert Control Library"
+DESCRIPTION = "library for Wedge Alert Control"
+SECTION = "base"
+PR = "r1"
+LICENSE = "GPLv2"
+LIC_FILES_CHKSUM = "file://alert_control.c;beginline=5;endline=17;md5=da35978751a9d71b73679307c4d296ec"
+
+SRC_URI = "file://alert_control \
+ "
+
+S = "${WORKDIR}/alert_control"
+
+do_install() {
+ install -d ${D}${libdir}
+ install -m 0644 libalert_control.so ${D}${libdir}/libalert_control.so
+
+ install -d ${D}${includedir}/facebook
+ install -m 0644 alert_control.h ${D}${includedir}/facebook/alert_control.h
+}
+
+FILES_${PN} = "${libdir}/libalert_control.so"
+FILES_${PN}-dbg = "${libdir}/.debug"
+FILES_${PN}-dev = "${includedir}/facebook/alert_control.h"
diff --git a/meta-facebook/meta-wedge/recipes-wedge/fblibs/libipmi_0.1.bb b/meta-facebook/meta-wedge/recipes-wedge/fblibs/libipmi_0.1.bb
new file mode 100644
index 0000000..0b6f3d3
--- /dev/null
+++ b/meta-facebook/meta-wedge/recipes-wedge/fblibs/libipmi_0.1.bb
@@ -0,0 +1,25 @@
+# Copyright 2014-present Facebook. All Rights Reserved.
+SUMMARY = "Wedge IPMI Client Library"
+DESCRIPTION = "library for Wedge IPMI Client"
+SECTION = "base"
+PR = "r1"
+LICENSE = "GPLv2"
+LIC_FILES_CHKSUM = "file://ipmi.c;beginline=8;endline=20;md5=da35978751a9d71b73679307c4d296ec"
+
+
+SRC_URI = "file://ipmi \
+ "
+
+S = "${WORKDIR}/ipmi"
+
+do_install() {
+ install -d ${D}${libdir}
+ install -m 0644 libipmi.so ${D}${libdir}/libipmi.so
+
+ install -d ${D}${includedir}/facebook
+ install -m 0644 ipmi.h ${D}${includedir}/facebook/ipmi.h
+}
+
+FILES_${PN} = "${libdir}/libipmi.so"
+FILES_${PN}-dbg = "${libdir}/.debug"
+FILES_${PN}-dev = "${includedir}/facebook/ipmi.h"
diff --git a/meta-facebook/meta-wedge/recipes-wedge/fbutils/fbutils_0.1.bb b/meta-facebook/meta-wedge/recipes-wedge/fbutils/fbutils_0.1.bb
new file mode 100644
index 0000000..753adbe
--- /dev/null
+++ b/meta-facebook/meta-wedge/recipes-wedge/fbutils/fbutils_0.1.bb
@@ -0,0 +1,86 @@
+# Copyright 2014-present Facebook. All Rights Reserved.
+SUMMARY = "Utilities"
+DESCRIPTION = "Various utilities"
+SECTION = "base"
+PR = "r1"
+LICENSE = "GPLv2"
+LIC_FILES_CHKSUM = "file://COPYING;md5=eb723b61539feef013de476e68b5c50a"
+
+SRC_URI = "file://ast-functions \
+ file://us_console.sh \
+ file://sol.sh \
+ file://power_led.sh \
+ file://post_led.sh \
+ file://reset_usb.sh \
+ file://setup-gpio.sh \
+ file://setup_rov.sh \
+ file://mdio.py \
+ file://bcm5396.py \
+ file://bcm5396_util.py \
+ file://mount_data0.sh \
+ file://eth0_mac_fixup.sh \
+ file://wedge_power.sh \
+ file://power-on.sh \
+ file://wedge_us_mac.sh \
+ file://setup_switch.py \
+ file://create_vlan_intf \
+ file://watch-fc.sh \
+ file://fcswitcher.sh \
+ file://rc.early \
+ file://rc.local \
+ file://src \
+ file://COPYING \
+ "
+
+pkgdir = "utils"
+
+S = "${WORKDIR}"
+
+binfiles = "us_console.sh sol.sh power_led.sh post_led.sh \
+ reset_usb.sh mdio.py setup_rov.sh wedge_power.sh wedge_us_mac.sh \
+ bcm5396.py bcm5396_util.py setup_switch.py watch-fc.sh"
+
+DEPENDS_append = "update-rc.d-native"
+
+do_install() {
+ dst="${D}/usr/local/fbpackages/${pkgdir}"
+ install -d $dst
+ install -m 644 ast-functions ${dst}/ast-functions
+ localbindir="${D}/usr/local/bin"
+ install -d ${localbindir}
+ for f in ${binfiles}; do
+ install -m 755 $f ${dst}/${f}
+ ln -s ../fbpackages/${pkgdir}/${f} ${localbindir}/${f}
+ done
+
+ # common lib and include files
+ install -d ${D}${includedir}/facebook
+ install -m 0644 src/include/log.h ${D}${includedir}/facebook/log.h
+ install -m 0644 src/include/i2c-dev.h ${D}${includedir}/facebook/i2c-dev.h
+
+ # init
+ install -d ${D}${sysconfdir}/init.d
+ install -d ${D}${sysconfdir}/rcS.d
+ # the script to mount /mnt/data
+ install -m 0755 ${WORKDIR}/mount_data0.sh ${D}${sysconfdir}/init.d/mount_data0.sh
+ update-rc.d -r ${D} mount_data0.sh start 03 S .
+ install -m 0755 ${WORKDIR}/rc.early ${D}${sysconfdir}/init.d/rc.early
+ update-rc.d -r ${D} rc.early start 04 S .
+ install -m 755 setup-gpio.sh ${D}${sysconfdir}/init.d/setup-gpio.sh
+ update-rc.d -r ${D} setup-gpio.sh start 59 S .
+ # create VLAN intf automatically
+ install -d ${D}/${sysconfdir}/network/if-up.d
+ install -m 755 create_vlan_intf ${D}${sysconfdir}/network/if-up.d/create_vlan_intf
+ # networking is done after rcS, any start level within rcS
+ # for mac fixup should work
+ install -m 755 eth0_mac_fixup.sh ${D}${sysconfdir}/init.d/eth0_mac_fixup.sh
+ update-rc.d -r ${D} eth0_mac_fixup.sh start 70 S .
+ install -m 755 power-on.sh ${D}${sysconfdir}/init.d/power-on.sh
+ update-rc.d -r ${D} power-on.sh start 85 S .
+ install -m 755 fcswitcher.sh ${D}${sysconfdir}/init.d/fcswitcher.sh
+ update-rc.d -r ${D} fcswitcher.sh start 90 S .
+ install -m 0755 ${WORKDIR}/rc.local ${D}${sysconfdir}/init.d/rc.local
+ update-rc.d -r ${D} rc.local start 99 2 3 4 5 .
+}
+
+FILES_${PN} += "/usr/local ${sysconfdir}"
diff --git a/meta-facebook/meta-wedge/recipes-wedge/fbutils/files/COPYING b/meta-facebook/meta-wedge/recipes-wedge/fbutils/files/COPYING
new file mode 100644
index 0000000..3912109
--- /dev/null
+++ b/meta-facebook/meta-wedge/recipes-wedge/fbutils/files/COPYING
@@ -0,0 +1,340 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+ 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it. (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.) You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must show them these terms so they know their
+rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License. The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+ 1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+ 2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) You must cause the modified files to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ b) You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any
+ part thereof, to be licensed as a whole at no charge to all third
+ parties under the terms of this License.
+
+ c) If the modified program normally reads commands interactively
+ when run, you must cause it, when started running for such
+ interactive use in the most ordinary way, to print or display an
+ announcement including an appropriate copyright notice and a
+ notice that there is no warranty (or else, saying that you provide
+ a warranty) and that users may redistribute the program under
+ these conditions, and telling the user how to view a copy of this
+ License. (Exception: if the Program itself is interactive but
+ does not normally print such an announcement, your work based on
+ the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+ a) Accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of Sections
+ 1 and 2 above on a medium customarily used for software interchange; or,
+
+ b) Accompany it with a written offer, valid for at least three
+ years, to give any third party, for a charge no more than your
+ cost of physically performing source distribution, a complete
+ machine-readable copy of the corresponding source code, to be
+ distributed under the terms of Sections 1 and 2 above on a medium
+ customarily used for software interchange; or,
+
+ c) Accompany it with the information you received as to the offer
+ to distribute corresponding source code. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form with such
+ an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it. For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable. However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License. Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+ 5. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Program or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+ 6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all. For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded. In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+ 9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+ 10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+ Gnomovision version 69, Copyright (C) year name of author
+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+ `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+ <signature of Ty Coon>, 1 April 1989
+ Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs. If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library. If this is what you want to do, use the GNU Library General
+Public License instead of this License.
diff --git a/meta-facebook/meta-wedge/recipes-wedge/fbutils/files/ast-functions b/meta-facebook/meta-wedge/recipes-wedge/fbutils/files/ast-functions
new file mode 100644
index 0000000..dd53ad1
--- /dev/null
+++ b/meta-facebook/meta-wedge/recipes-wedge/fbutils/files/ast-functions
@@ -0,0 +1,222 @@
+# Copyright 2014-present Facebook. All Rights Reserved.
+DEVMEM=/sbin/devmem
+
+devmem_set_bit() {
+ local addr
+ local val
+ addr=$1
+ val=$($DEVMEM $addr)
+ val=$((val | (0x1 << $2)))
+ $DEVMEM $addr 32 $val
+}
+
+devmem_clear_bit() {
+ local addr
+ local val
+ addr=$1
+ val=$($DEVMEM $addr)
+ val=$((val & ~(0x1 << $2)))
+ $DEVMEM $addr 32 $val
+}
+
+scu_addr() {
+ echo $((0x1E6E2000 + 0x$1))
+}
+
+GPIODIR="/sys/class/gpio"
+GPIOEXPORT="$GPIODIR/export"
+
+gpio_dir() {
+ echo "$GPIODIR/gpio$1"
+}
+
+gpio_name2value() {
+ local first remaining base val
+ remaining=$1
+ val=0
+ while [ -n "$remaining" ]; do
+ first=${remaining:0:1}
+ case "$first" in
+ [[:lower:]])
+ base=$(printf "%d" "'$first'")
+ base=$((base - 96))
+ val=$((val * 26 + base))
+ ;;
+ [[:upper:]])
+ base=$(printf "%d" "'$first'")
+ base=$((base - 64))
+ val=$((val * 26 + base))
+ ;;
+ *)
+ if [ $val -gt 0 ]; then
+ val=$((val-1))
+ fi
+ val=$((val * 8 + $remaining))
+ break
+ ;;
+ esac
+ remaining=${remaining:1}
+ done
+ echo "$val"
+}
+
+gpio_export() {
+ local gpio
+ gpio=$(gpio_name2value $1)
+ dir=$(gpio_dir $gpio)
+ if [ ! -d ${dir} ]; then
+ echo $gpio > $GPIOEXPORT
+ fi
+}
+
+gpio_set() {
+ local gpio
+ local val
+ gpio=$(gpio_name2value $1)
+ val=$2
+ dir=$(gpio_dir $gpio)
+ if [ ! -d ${dir} ]; then
+ echo $gpio > $GPIOEXPORT
+ fi
+ echo out > ${dir}/direction
+ echo $val > ${dir}/value
+}
+
+gpio_get() {
+ local gpio
+ local val
+ gpio=$(gpio_name2value $1)
+ dir=$(gpio_dir $gpio)
+ if [ ! -d ${dir} ]; then
+ echo $gpio > $GPIOEXPORT
+ fi
+ echo in > ${dir}/direction
+ cat ${dir}/value
+}
+
+wedge_iso_buf_enable() {
+ # GPIOC2 (18) to low, SCU90[0] and SCU90[24] must be 0
+ devmem_clear_bit $(scu_addr 90) 0
+ devmem_clear_bit $(scu_addr 90) 24
+ gpio_set 18 0
+}
+
+wedge_iso_buf_disable() {
+ # GPIOC2 (18) to low, SCU90[0] and SCU90[24] must be 0
+ devmem_clear_bit $(scu_addr 90) 0
+ devmem_clear_bit $(scu_addr 90) 24
+ gpio_set 18 1
+}
+
+wedge_is_us_on() {
+ local val n retries prog
+ if [ $# -gt 0 ]; then
+ retries="$1"
+ else
+ retries=1
+ fi
+ if [ $# -gt 1 ]; then
+ prog="$2"
+ else
+ prog=""
+ fi
+ n=1
+ while true; do
+ val=$(cat /sys/class/i2c-adapter/i2c-4/4-0040/gpio_inputs 2>/dev/null)
+ if [ -n "$val" ]; then
+ break
+ fi
+ n=$((n+1))
+ if [ $n -gt $retries ]; then
+ echo -n " failed to read GPIO. "
+ val=0
+ break
+ fi
+ echo -n "$prog"
+ sleep 1
+ done
+ if [ "$((val & (0x1 << 14)))" != "0" ]; then
+ # powered on already
+ return 0
+ else
+ return 1
+ fi
+}
+
+
+# Return the board type, 'LC', 'FC-LEFT', 'FC-RIGHT', or, 'WEDGE'
+wedge_board_type() {
+ local pn
+ pn=$(/usr/bin/weutil 2> /dev/null | grep -i '^Location on Fabric:')
+ case "$pn" in
+ *LEFT*)
+ echo 'FC-LEFT'
+ ;;
+ *RIGHT*)
+ echo 'FC-RIGHT'
+ ;;
+ *LC*)
+ echo 'LC'
+ ;;
+ *)
+ echo 'WEDGE'
+ ;;
+ esac
+}
+
+# On FC, FAB_SLOT_ID (GPIOU0), low == FC0; high == FC1
+# On LC, Wedge,
+# board rev < 3:
+# GPIOU0(ID0), GPIOU1(ID1), GPIOU2(ID2), GPIOU3(ID3)
+# else:
+# GPIOU6(ID0), GPIOU7(ID1), GPIOV0(ID2), GPIOV1(ID3)
+#
+# ID[2:0] ID3 Slot#
+# 000 0 1
+# 000 1 2
+# 001 0 3
+# 001 1 4
+# 010 0 5
+# 010 1 6
+# 011 0 7
+# 011 1 8
+
+wedge_slot_id() {
+ local type slot id3 id2 id1 id0 FC_CARD_BASE board_rev
+ FC_CARD_BASE=65
+ if [ "$1" = "FC-LEFT" ]; then
+ # fabric card left
+ slot=$(gpio_get U0)
+ slot=$((FC_CARD_BASE + slot * 2))
+ elif [ "$1" = "FC-RIGHT" ]; then
+ # fabric card right
+ slot=$(gpio_get U0)
+ slot=$((FC_CARD_BASE + slot * 2 + 1))
+ else
+ # either edge or LC
+ # need to check the board rev
+ board_rev=$(wedge_board_rev)
+ if [ $board_rev -lt 3 ]; then
+ id0=$(gpio_get U0)
+ id1=$(gpio_get U1)
+ id2=$(gpio_get U2)
+ id3=$(gpio_get U3)
+ else
+ id0=$(gpio_get U6)
+ id1=$(gpio_get U7)
+ id2=$(gpio_get V0)
+ id3=$(gpio_get V1)
+ fi
+ slot=$(((id2 * 4 + id1 * 2 + id0) * 2 + id3 + 1))
+ fi
+ echo "$slot"
+}
+
+# wedge_board_rev() is only valid after GPIO Y0, Y1, and Y2 are enabled
+wedge_board_rev() {
+ local val0 val1 val2
+ val0=$(cat /sys/class/gpio/gpio192/value 2>/dev/null)
+ val1=$(cat /sys/class/gpio/gpio193/value 2>/dev/null)
+ val2=$(cat /sys/class/gpio/gpio194/value 2>/dev/null)
+ echo $((val0 | (val1 << 1) | (val2 << 2)))
+}
diff --git a/meta-facebook/meta-wedge/recipes-wedge/fbutils/files/at93c46.py b/meta-facebook/meta-wedge/recipes-wedge/fbutils/files/at93c46.py
new file mode 100644
index 0000000..368b807
--- /dev/null
+++ b/meta-facebook/meta-wedge/recipes-wedge/fbutils/files/at93c46.py
@@ -0,0 +1,260 @@
+# Copyright 2004-present Facebook. All rights reserved.
+
+import subprocess
+import struct
+import sys
+
+class VerboseLogger:
+ def __init__(self, verbose=False):
+ self.verbose = verbose
+
+ def _verbose_print(self, caption, bytestream=None):
+ '''
+ Print a bytestream to stdout if verbose is enabled.
+ '''
+ if self.verbose:
+ if bytestream is not None:
+ sys.stderr.write("{}: {}\n".format(caption, " ".join(['{:02X}'.format(ord(x)) for x in bytestream])))
+ else:
+ sys.stderr.write("{}\n".format(caption))
+
+class AT93C46SPI(VerboseLogger):
+ '''The class to access AT93C46 through SPI intf'''
+ SPI_CMD = 'spi-bb'
+
+ def __init__(self, bus_width, gpio_cs, gpio_ck, gpio_do, gpio_di,
+ verbose=False):
+ if bus_width != 8 and bus_width != 16:
+ raise Exception("Invalid bus width for AT93C46!")
+
+ self.bus_width = bus_width
+ self.gpio_cs = gpio_cs
+ self.gpio_ck = gpio_ck
+ self.gpio_do = gpio_do
+ self.gpio_di = gpio_di
+ self.verbose = verbose
+
+ self.addr_bits = 6 if self.bus_width == 16 else 7
+ self.addr_mask = 0x3F if self.bus_width == 16 else 0x7F
+
+ def __shift(self, bytestream, value):
+ '''
+ Shift an entire byte stream by value bits.
+ '''
+ binary = "".join(['{:08b}'.format(ord(x)) for x in bytestream])
+ if value > 0:
+ binary = binary[value:] + '0' * value
+ else:
+ binary = '0' * (-value) + binary[:value]
+ return "".join([chr(int(binary[x:x+8],2)) for x in range(0, len(binary), 8)])
+
+ def __io(self, op, addr, data=None):
+ '''
+ Perform an IO operation against the EEPROM
+ '''
+ write_bits = self.addr_bits + 3
+ if data is not None:
+ # If giving data, we are doing a write command so
+ # no need to read any data.
+ write_bits = write_bits + self.bus_width
+ read_bits = 0
+ else:
+ # If not giving data, we are doing either a read
+ # command or a set command, so read the result.
+ # We pad with an extra bit due to a dummy bit introduced
+ # by a delay for address decoding on chip.
+ read_bits = self.addr_bits + 4 + self.bus_width
+
+ # Format the command itself
+ cmd_loc = 6 if self.bus_width == 16 else 7
+ instruction = addr & self.addr_mask
+ instruction = instruction | ((0x4 | (op & 0x3)) << cmd_loc)
+ if data is not None:
+ if self.bus_width == 16:
+ write_data = struct.pack(">HH", instruction, data & 0xFFFF)
+ else:
+ write_data = struct.pack(">HB", instruction, data & 0xFF)
+ else:
+ write_data = struct.pack(">H", instruction)
+ write_data = self.__shift(write_data, 16 - (cmd_loc + 3))
+
+ self._verbose_print("Write data", write_data)
+
+ # Run the command with the bitbang driver
+ if read_bits > 0:
+ data_portion = "-r {} -w {}".format(read_bits, write_bits)
+ else:
+ data_portion = "-w {}".format(write_bits)
+
+ cmd = "{} -s {} -c {} -o {} -i {} -b {}".format(
+ self.SPI_CMD, self.gpio_cs, self.gpio_ck, self.gpio_do,
+ self.gpio_di, data_portion
+ )
+
+ self._verbose_print("Command: {}".format(cmd))
+
+ out = subprocess.Popen(cmd.split(),
+ stdout=subprocess.PIPE,
+ stdin = subprocess.PIPE)\
+ .communicate(input=write_data)
+
+ # Format the response
+ read_data = self.__shift(out[0], cmd_loc + 4)
+ if self.bus_width == 16:
+ read_data = read_data[:2]
+ self._verbose_print("Read data", read_data)
+ return struct.unpack(">H", read_data)[0]
+ else:
+ read_data = read_data[:1]
+ self._verbose_print("Read data", read_data)
+ return struct.unpack(">B", read_data)[0]
+
+ def read(self, addr):
+ return self.__io(0x2, addr)
+
+ def ewen(self):
+ self.__io(0x0, 0x3 << (self.addr_bits - 2))
+
+ def erase(self, addr):
+ self.__io(0x3, addr)
+
+ def write(self, addr, data):
+ self.__io(0x1, addr, data)
+
+ def eral(self):
+ self.__io(0x0, 0x2 << (self.addr_bits - 2))
+
+ def wral(self, data):
+ self.__io(0x0, 0x1 << (self.addr_bits - 2), data)
+
+ def ewds(self):
+ self.__io(0x0, 0x0)
+
+class AT93C46(VerboseLogger):
+ '''
+ The class which handles accessing memory on the AT93C46 chip.
+ '''
+ AT93C46_MEMORY_SIZE = 128
+
+ def __init__(self, bus_width, gpio_cs, gpio_ck, gpio_do, gpio_di,
+ byte_swap, verbose=False):
+ self.bus_width = bus_width
+ self.verbose = verbose
+ self.byte_swap = byte_swap
+
+ self.spi = AT93C46SPI(bus_width=bus_width, gpio_cs=gpio_cs,
+ gpio_ck=gpio_ck, gpio_do=gpio_do,
+ gpio_di=gpio_di, verbose=verbose)
+
+ def __swap(self, value):
+ '''
+ Swap bytes for a 16-bit integer if instructed to do so.
+ '''
+ if self.bus_width == 16:
+ if self.byte_swap:
+ return ((value >> 8) & 0xFF) | ((value << 8) & 0xFF00)
+ else:
+ return value
+ else:
+ return value
+
+ def erase(self, offset=None, limit=None):
+ '''
+ Erase the chip.
+ '''
+ if offset is None:
+ offset = 0
+ if limit is None:
+ limit = self.AT93C46_MEMORY_SIZE
+
+ if offset < 0 or offset + limit > self.AT93C46_MEMORY_SIZE:
+ raise Exception("Erase would be out of bounds!")
+ if self.bus_width == 16 and \
+ ((offset & 1) != 0 or ((offset + limit) & 1) != 0):
+ raise Exception("Erase can't start or end on odd boundary in 16-bit mode!")
+
+ if offset == 0 and limit == self.AT93C46_MEMORY_SIZE:
+ # Special case when we are erasing the entire chip
+ self.spi.ewen()
+ self.spi.eral()
+ self.spi.ewds()
+
+ self._verbose_print("Erased entire chip")
+ else:
+ # Regular case
+ if self.bus_width == 16:
+ real_offset = offset / 2
+ real_limit = limit / 2
+ else:
+ real_offset = offset
+ real_limit = limit
+
+ self.spi.ewen()
+ for addr in range(real_offset, real_offset + real_limit):
+ self.spi.erase(addr)
+ self.spi.ewds()
+
+ self._verbose_print("Erased {} bytes from offset {}".format(limit, offset))
+
+ def read(self, offset=None, limit=None):
+ '''
+ Read the chip into a memory buffer.
+ '''
+ if offset is None:
+ offset = 0
+ if limit is None:
+ limit = self.AT93C46_MEMORY_SIZE
+
+ if offset < 0 or offset + limit > self.AT93C46_MEMORY_SIZE:
+ raise Exception("Read would be out of bounds!")
+ if self.bus_width == 16 and \
+ ((offset & 1) != 0 or ((offset + limit) & 1) != 0):
+ raise Exception("Read can't start or end on odd boundary in 16-bit mode!")
+
+ output = ""
+ if self.bus_width == 16:
+ real_offset = offset / 2
+ real_limit = limit / 2
+ pack_instruction = "=H"
+ else:
+ real_offset = offset
+ real_offset
+ pack_instruction = "=B"
+
+ for addr in range(real_offset, real_offset + real_limit):
+ output = output + struct.pack(pack_instruction, self.__swap(self.spi.read(addr)))
+
+ self._verbose_print("Read {} bytes from offset {}".format(limit, offset), output)
+
+ return output
+
+ def write(self, data, offset=None):
+ '''
+ Write a memory buffer to the chip.
+ '''
+ if offset is None:
+ offset = 0
+
+ if offset < 0 or offset + len(data) > self.AT93C46_MEMORY_SIZE:
+ raise Exception("Write would be out of bounds!")
+ if self.bus_width == 16 and \
+ ((offset & 1) != 0 or ((offset + len(data)) & 1) != 0):
+ raise Exception("Write can't start or end on odd boundary in 16-bit mode!")
+
+ if self.bus_width == 16:
+ offset_divisor = 2
+ pack_instruction = "=H"
+ else:
+ offset_divisor = 1
+ pack_instruction = "=B"
+
+ self.spi.ewen()
+ for addr in range(offset, offset + len(data), offset_divisor):
+ actual_addr = addr / offset_divisor
+ value = self.__swap(struct.unpack(pack_instruction, data[(addr - offset):(addr - offset) + offset_divisor])[0])
+
+ self.spi.erase(actual_addr)
+ self.spi.write(actual_addr, value)
+ self.spi.ewds()
+
+ self._verbose_print("Wrote {} bytes from offset {}".format(len(data), offset), data)
diff --git a/meta-facebook/meta-wedge/recipes-wedge/fbutils/files/at93c46_util.py b/meta-facebook/meta-wedge/recipes-wedge/fbutils/files/at93c46_util.py
new file mode 100755
index 0000000..8910002
--- /dev/null
+++ b/meta-facebook/meta-wedge/recipes-wedge/fbutils/files/at93c46_util.py
@@ -0,0 +1,178 @@
+#!/usr/bin/python -S
+# Copyright 2004-present Facebook. All rights reserved.
+
+from argparse import ArgumentParser
+from at93c46 import AT93C46, AT93C46SPI
+import sys
+
+def get_raw(args):
+ return AT93C46SPI(args.bus_width, args.cs, args.clk, args.mosi, args.miso,
+ args.verbose)
+
+def get_chip(args):
+ return AT93C46(args.bus_width, args.cs, args.clk, args.mosi, args.miso,
+ args.byte_swap, args.verbose)
+
+def access_parser(ap):
+ # Default, based on currenct HW configuration
+ SPI_CS_DEFAULT = 68
+ SPI_CLK_DEFAULT = 69
+ SPI_MOSI_DEFAULT = 70
+ SPI_MISO_DEFAULT = 71
+
+ spi_group = ap.add_argument_group('SPI Access')
+ spi_group.add_argument('--cs', type=int, default=SPI_CS_DEFAULT,
+ help='The GPIO number for SPI CS pin (default: %s)'
+ % SPI_CS_DEFAULT)
+ spi_group.add_argument('--clk', type=int, default=SPI_CLK_DEFAULT,
+ help='The GPIO number for SPI CLK pin (default: %s)'
+ % SPI_CLK_DEFAULT)
+ spi_group.add_argument('--mosi', type=int, default=SPI_MOSI_DEFAULT,
+ help='The GPIO number for SPI MOSI pin (default: %s)'
+ % SPI_MOSI_DEFAULT)
+ spi_group.add_argument('--miso', type=int, default=SPI_MISO_DEFAULT,
+ help='The GPIO number for SPI MISO pin (default: %s)'
+ % SPI_MISO_DEFAULT)
+
+def bus_width_parser(ap):
+ # Default, based on currenct HW configuration
+ AT83C46_BUS_WIDTH = 16
+
+ bus_group = ap.add_argument_group('Bus Width')
+ bus_group.add_argument('--bus-width', type=int, default=AT83C46_BUS_WIDTH,
+ help='The configured bus width (default: %s)'
+ % AT83C46_BUS_WIDTH)
+
+def read_raw(args):
+ raw = get_raw(args)
+ val = raw.read(args.address)
+
+ if args.int:
+ print "{}".format(val)
+ else:
+ if args.bus_width == 16:
+ print "0x{:04X}".format(val)
+ else:
+ print "0x{:02X}".format(val)
+
+def write_raw(args):
+ if args.value[:2] == "0x":
+ value = int(args.value, 16)
+ else:
+ value = int(args.value)
+
+ raw = get_raw(args)
+ raw.ewen()
+ raw.erase(args.address)
+ raw.write(args.address, value)
+ raw.ewds()
+
+def erase_raw(args):
+ raw = get_raw(args)
+ raw.ewen()
+ raw.erase(args.address)
+ raw.ewds()
+
+def raw_subparser(subparsers):
+ raw_parser = subparsers.add_parser('raw', help='Raw memory access')
+ raw_sub = raw_parser.add_subparsers()
+
+ read_parser = raw_sub.add_parser('read', help='Read a single memory address')
+ read_parser.add_argument('address', type=int, help='The memory address')
+ read_parser.add_argument('--int', action='store_true',
+ help='Display output as an integer')
+ read_parser.set_defaults(func=read_raw)
+
+ write_parser = raw_sub.add_parser('write', help='Write a single memory address')
+ write_parser.add_argument('address', type=int, help='The memory address')
+ write_parser.add_argument('value', type=str, help='The value to write, either integer or hex')
+ write_parser.set_defaults(func=write_raw)
+
+ erase_parser = raw_sub.add_parser('erase', help='Erase a single memory address')
+ erase_parser.add_argument('address', type=int, help='The memory address')
+ erase_parser.set_defaults(func=erase_raw)
+
+def read_chip(args):
+ chip = get_chip(args)
+ data = chip.read(args.start, args.length)
+
+ if args.file is None:
+ sys.stdout.write(data)
+ else:
+ fp = open(args.file, "wb")
+ fp.write(data)
+
+def write_chip(args):
+ chip = get_chip(args)
+
+ # Either way, limit reads to the size of the chip
+ if args.file is None:
+ data = sys.stdin.read(AT93C46.AT93C46_MEMORY_SIZE)
+ else:
+ fp = open(args.file, "rb")
+ data = fp.read(AT93C46.AT93C46_MEMORY_SIZE)
+
+ if args.length is not None:
+ # Make sure length is correct
+ if len(data) < args.length:
+ data = data + '\x00' * (args.length - len(data))
+ if len(data) > args.length:
+ data = data[:args.length]
+
+ chip.write(data, args.start)
+
+def erase_chip(args):
+ chip = get_chip(args)
+ chip.erase(args.start, args.length)
+
+def chip_subparser(subparsers):
+ chip_parser = subparsers.add_parser('chip', help='Chip-level access')
+ chip_sub = chip_parser.add_subparsers()
+
+ read_parser = chip_sub.add_parser('read', help='Read from the chip')
+ read_parser.add_argument('--start', type=int,
+ help='The memory address to start at (default: 0)')
+ read_parser.add_argument('--length', type=int,
+ help='The number of bytes to read (default: whole chip)')
+ read_parser.add_argument('--file', type=str,
+ help='File to operate on (default: stdout)')
+ read_parser.add_argument('--byte-swap', action='store_true',
+ help='Byte swap values for 16-bit reads/writes')
+ read_parser.set_defaults(func=read_chip)
+
+ write_parser = chip_sub.add_parser('write', help='Write to the chip')
+ write_parser.add_argument('--start', type=int,
+ help='The memory address to start at (default: 0)')
+ write_parser.add_argument('--length', type=int,
+ help='The number of bytes to write (default: file length)')
+ write_parser.add_argument('--file', type=str,
+ help='File to operate on (default: stdin)')
+ write_parser.add_argument('--byte-swap', action='store_true',
+ help='Byte swap values for 16-bit reads/writes')
+ write_parser.set_defaults(func=write_chip)
+
+ erase_parser = chip_sub.add_parser('erase', help='Erase the chip')
+ erase_parser.add_argument('--start', type=int,
+ help='The memory address to start at (default: 0)')
+ erase_parser.add_argument('--length', type=int,
+ help='The number of bytes to erase (default: whole chip)')
+ erase_parser.set_defaults(func=erase_chip)
+
+if __name__ == "__main__":
+ # General arguments
+ ap = ArgumentParser()
+ ap.add_argument('--verbose', action='store_true',
+ help='Print verbose debugging information')
+
+ # SPI and bus width arguments
+ access_parser(ap)
+ bus_width_parser(ap)
+
+ # Functionality
+ subparsers = ap.add_subparsers()
+ raw_subparser(subparsers)
+ chip_subparser(subparsers)
+
+ # Command runner
+ args = ap.parse_args()
+ args.func(args)
diff --git a/meta-facebook/meta-wedge/recipes-wedge/fbutils/files/bcm5396.py b/meta-facebook/meta-wedge/recipes-wedge/fbutils/files/bcm5396.py
new file mode 100644
index 0000000..e1aba47
--- /dev/null
+++ b/meta-facebook/meta-wedge/recipes-wedge/fbutils/files/bcm5396.py
@@ -0,0 +1,452 @@
+#
+# Copyright 2004-present Facebook. All rights reserved.
+#
+# This program file is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by the
+# Free Software Foundation; version 2 of the License.
+#
+# This program is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+# for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program in a file named COPYING; if not, write to the
+# Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor,
+# Boston, MA 02110-1301 USA
+#
+
+import subprocess
+import time
+
+class Bcm5396MDIO:
+ '''The class to access BCM5396 through MDIO intf'''
+ MDIO_CMD = 'mdio-bb'
+
+ PHYADDR = 0x1E
+
+ ACCESS_CTRL_REG = 16
+ IO_CTRL_REG = 17
+ STATUS_REG = 18
+ DATA0_REG = 24
+ DATA1_REG = 25
+ DATA2_REG = 26
+ DATA3_REG = 27
+
+ def __init__(self, mdc, mdio):
+ self.mdc = mdc
+ self.mdio = mdio
+ self.page = -1
+
+ def __io(self, op, reg, val=0):
+ cmd = '%s -p -c %s -d %s %s %s %s' \
+ % (self.MDIO_CMD, self.mdc, self.mdio, op, str(self.PHYADDR),
+ str(reg))
+ if op == 'write':
+ cmd += ' %s' % val
+ out = subprocess.Popen(cmd.split(), stdout=subprocess.PIPE)\
+ .communicate()[0]
+ if op == 'write':
+ return val
+ # need to parse the result for read
+ rc = 0
+ for line in out.split('\n'):
+ if not line.startswith('Read:'):
+ continue
+ rc = int(line.split(':')[1], 0)
+ return rc
+
+ def __read_mdio(self, reg):
+ return self.__io('read', reg)
+
+ def __write_mdio(self, reg, val):
+ return self.__io('write', reg, val)
+
+ def __set_page(self, page):
+ if self.page == page:
+ return
+ # Write MII register ACCESS_CTRL_REG:
+ # set bit 0 as "1" to enable MDIO access
+ # set "page number to bit 15:8
+ val = 0x1 | ((page & 0xff) << 8)
+ self.__write_mdio(self.ACCESS_CTRL_REG, val)
+ self.page = page
+
+ def __wait_for_done(self):
+ # Read MII register IO_CTRL_REG:
+ # Check op_code = "00"
+ while (self.__read_mdio(self.IO_CTRL_REG) & 0x3):
+ time.sleep(0.010) # 10ms
+
+ def read(self, page, reg, n_bytes):
+ self.__set_page(page)
+ # Write MII register IO_CTRL_REG:
+ # set "Operation Code as "00"
+ # set "Register Address" to bit 15:8
+ val = 0x00 | ((reg & 0xff) << 8)
+ self.__write_mdio(self.IO_CTRL_REG, val)
+ # Write MII register IO_CTRL_REG:
+ # set "Operation Code as "10"
+ # set "Register Address" to bit 15:8
+ val = 0x2 | ((reg & 0xff) << 8)
+ self.__write_mdio(self.IO_CTRL_REG, val)
+ self.__wait_for_done()
+ # Read MII register DATA0_REG for bit 15:0
+ val = long(self.__read_mdio(self.DATA0_REG))
+ # Read MII register DATA1_REG for bit 31:16
+ val |= self.__read_mdio(self.DATA1_REG) << 16
+ # Read MII register DATA2_REG for bit 47:32
+ val |= self.__read_mdio(self.DATA2_REG) << 32
+ # Read MII register DATA3_REG for bit 63:48
+ val |= self.__read_mdio(self.DATA3_REG) << 48
+ return val
+
+ def write(self, page, reg, val, n_bytes):
+ self.__set_page(page)
+ # Write MII register DATA0_REG for bit 15:0
+ self.__write_mdio(self.DATA0_REG, val & 0xFFFF)
+ # Write MII register DATA1_REG for bit 31:16
+ self.__write_mdio(self.DATA1_REG, (val >> 16) & 0xFFFF)
+ # Write MII register DATA2_REG for bit 47:32
+ self.__write_mdio(self.DATA2_REG, (val >> 32) & 0xFFFF)
+ # Write MII register DATA3_REG for bit 63:48
+ self.__write_mdio(self.DATA3_REG, (val >> 48) & 0xFFFF)
+ # Write MII register IO_CTRL_REG:
+ # set "Operation Code as "00"
+ # set "Register Address" to bit 15:8
+ val = 0x00 | ((reg & 0xff) << 8)
+ self.__write_mdio(self.IO_CTRL_REG, val)
+ # Write MII register IO_CTRL_REG:
+ # set "Operation Code as "01"
+ # set "Register Address" to bit 15:8
+ val = 0x1 | ((reg & 0xff) << 8)
+ self.__write_mdio(self.IO_CTRL_REG, val)
+ self.__wait_for_done()
+
+
+class Bcm5396SPI:
+ '''The class to access BCM5396 through SPI interface'''
+ SPI_CMD = 'spi-bb'
+
+ READ_CMD = 0x60
+ WRITE_CMD = 0x61
+
+ SPI_STS_DIO = 0xF0
+ SPI_STS_REG = 0xFE
+ SPI_STS_REG_RACK = 0x1 << 5
+ SPI_STS_REG_SPIF = 0x1 << 7
+ PAGE_REG = 0xFF
+
+ def __init__(self, cs, clk, mosi, miso):
+ self.cs = cs
+ self.clk = clk
+ self.mosi = mosi
+ self.miso = miso
+ self.page = -1
+
+ def __bytes2val(self, values):
+ # LSB first, MSB last
+ pos = 0
+ result = 0L
+ for byte in values:
+ if type(byte) is str:
+ byte = int(byte, 16)
+ if byte > 255:
+ raise Exception('%s is not a byte in the list %s'\
+ % (byte, values))
+ result |= byte << pos
+ pos += 8
+ return result
+
+ def __val2bytes(self, value, n):
+ result = []
+ for _ in range(n):
+ result.append(value & 0xFF)
+ value >>= 8
+ if value > 0:
+ raise Exception('Value, %s, is too large for %s bytes'
+ % (value, n))
+ return result
+
+ def __io(self, bytes_to_write, to_read=0):
+ # TODO: check parameters
+ cmd = '%s -s %s -S low -c %s -o %s -i %s '\
+ % (self.SPI_CMD, self.cs, self.clk, self.mosi, self.miso)
+ if len(bytes_to_write):
+ write_cmd = '-w %s %s '\
+ % (len(bytes_to_write) * 8,
+ ' '.join([str(byte) for byte in bytes_to_write]))
+ else:
+ write_cmd = ''
+ if to_read:
+ # spi-bb will first return the exact number of bits used for
+ # writing. So, total number of bits to read should also include
+ # the number of bits written.
+ cmd += '-r %s ' % str((len(bytes_to_write) + to_read) * 8)
+ cmd += write_cmd
+ rc = 0L
+ out = subprocess.Popen(cmd.split(), stdout=subprocess.PIPE)\
+ .communicate()[0]
+ if to_read:
+ # need to parse the result
+ for line in out.split('\n'):
+ if not line.startswith('Read'):
+ continue
+ res = line.split(':')[1]
+ rc = self.__bytes2val(res.split()[len(bytes_to_write):])
+ break
+ return rc
+
+ def __set_page(self, page):
+ page &= 0xff
+ if self.page == page:
+ return
+ self.__io([self.WRITE_CMD, self.PAGE_REG, page])
+ self.page = page
+
+ def __read_spi_reg(self, reg):
+ reg &= 0xFF
+ return self.__io([self.READ_CMD, reg], 1)
+
+ def __read_spi_sts(self):
+ return self.__read_spi_reg(self.SPI_STS_REG)
+
+ def __read_spi_dio(self):
+ return self.__read_spi_reg(self.SPI_STS_DIO)
+
+ def read(self, page, reg, n_bytes):
+ '''Read a register value from a page.'''
+ if n_bytes > 8:
+ print('TODO to support reading more than 8 bytes')
+ return 0
+ if page > 0xff or reg > 0xff:
+ print('Page and register must be <= 255')
+ return 0
+ try:
+ self.__set_page(page)
+ self.__io([self.READ_CMD, reg], 1)
+ while True:
+ # check sts
+ sts = self.__read_spi_sts()
+ if sts & self.SPI_STS_REG_RACK:
+ break
+ bytes = []
+ for _ in range(n_bytes):
+ bytes.append(self.__read_spi_dio())
+ except Exception as e:
+ print(e)
+ return self.__bytes2val(bytes)
+
+ def write(self, page, reg, val, n_bytes):
+ '''Write a value as n bytes to a register on a page.'''
+ if page > 0xff or reg > 0xff:
+ print('Page and register must be <= 255')
+ return
+ bytes = self.__val2bytes(val, n_bytes)
+ if len(bytes) > 8:
+ print('TODO to support writing more than 8 bytes')
+ return
+ bytes = [self.WRITE_CMD, reg] + bytes
+ try:
+ self.__set_page(page)
+ self.__io(bytes)
+ except Exception as e:
+ print(e)
+
+class Bcm5396:
+ '''The class for BCM5396 Switch'''
+
+ MDIO_ACCESS = 0
+ SPI_ACCESS = 1
+
+ def __init__(self, access, **kwargs):
+ if access == self.MDIO_ACCESS:
+ self.access = Bcm5396MDIO(**kwargs)
+ else:
+ self.access = Bcm5396SPI(**kwargs)
+
+ def write(self, page, reg, value, n_bytes):
+ return self.access.write(page, reg, value, n_bytes)
+
+ def read(self, page, reg, n_bytes):
+ return self.access.read(page, reg, n_bytes)
+
+ def __add_remove_vlan(self, add, vid, untag, fwd, spt):
+ VLAN_PAGE = 0x5
+ CTRL_ADDR = 0x60
+ CTRL_START_DONE = (0x1 << 7)
+ VID_ADDR = 0x61
+ ENTRY_ADDR = 0x63
+
+ fwd_map = self.__ports2portmap(fwd)
+ untag_map = self.__ports2portmap(untag)
+
+ # mark it as write and stop the previous action
+ ctrl = 0
+ self.write(VLAN_PAGE, CTRL_ADDR, ctrl, 1)
+ # write entry
+ if (add):
+ entry = 0x1L | ((spt & 0x1F) << 1) \
+ | (fwd_map << 6) | (untag_map << 23)
+ else:
+ entry = 0x0L
+ self.write(VLAN_PAGE, ENTRY_ADDR, entry, 8)
+ # write vid as the index
+ self.write(VLAN_PAGE, VID_ADDR, vid & 0xFFF, 2)
+ # start the write
+ ctrl = CTRL_START_DONE
+ self.write(VLAN_PAGE, CTRL_ADDR, ctrl, 1)
+ while True:
+ ctrl = self.read(VLAN_PAGE, CTRL_ADDR, 1)
+ if not (ctrl & CTRL_START_DONE):
+ # done
+ break
+ time.sleep(0.010) # 10ms
+
+ def add_vlan(self, vid, untag, fwd, spt=0):
+ return self.__add_remove_vlan(True, vid, untag, fwd, spt)
+
+ def remove_vlan(self, vid):
+ return self.__add_remove_vlan(False, vid, [], [], 0)
+
+ def get_vlan(self, vid):
+ VLAN_PAGE = 0x5
+ CTRL_ADDR = 0x60
+ CTRL_START_DONE = (0x1 << 7)
+ CTRL_READ = 0x1
+ VID_ADDR = 0x61
+ ENTRY_ADDR = 0x63
+
+ # mark it as read and stop the previous action
+ ctrl = CTRL_READ
+ self.write(VLAN_PAGE, CTRL_ADDR, ctrl, 1)
+ # write the vid as the index
+ self.write(VLAN_PAGE, VID_ADDR, vid & 0xFFF, 2)
+ # start the read
+ ctrl = CTRL_READ|CTRL_START_DONE
+ self.write(VLAN_PAGE, CTRL_ADDR, ctrl, 1)
+ while True:
+ ctrl = self.read(VLAN_PAGE, CTRL_ADDR, 1)
+ if not (ctrl & CTRL_START_DONE):
+ # done
+ break
+ time.sleep(0.010) # 10ms
+ entry = self.read(VLAN_PAGE, ENTRY_ADDR, 8)
+ res = {}
+ res['valid'] = True if entry & 0x1 else False
+ res['spt'] = (entry >> 1) & 0x1f
+ res['fwd'] = self.__portmap2ports((entry >> 6) & 0x1ffff)
+ res['untag'] = self.__portmap2ports((entry >> 23) & 0x1ffff)
+ return res
+
+ def __portmap2ports(self, port_map):
+ return list(set([port if port_map & (0x1 << port) else None
+ for port in range (0, 17)])
+ - set([None]))
+
+ def __ports2portmap(self, ports):
+ port_map = 0
+ for port in ports:
+ port_map |= (0x1 << port)
+ return port_map & 0x1FFFF
+
+ def __parse_arl_result(self, vid, result):
+ is_bitset = lambda bit: True if result & (0x1 << bit) else False
+ if not is_bitset(3):
+ return None
+ res = {}
+ # parse vid first
+ res['vid'] = (vid >> 48) & 0xfff
+ mac_val = vid & 0xffffffffffffL
+ mac_list = []
+ for pos in range(5, -1, -1):
+ mac_list.append('{:02x}'.format((mac_val >> (pos * 8)) & 0xff))
+ res['mac'] = ':'.join(mac_list)
+ if mac_val & (0x1 << 40):
+ res['ports'] = self.__portmap2ports((result >> 6) & 0xffff)
+ else:
+ res['ports'] = [(result >> 6) & 0xf]
+ res['static'] = is_bitset(5)
+ res['age'] = is_bitset(4)
+ res['valid'] = is_bitset(3)
+ res['priority'] = result & 0x7
+ return res
+
+ def get_all_arls(self):
+ ARL_PAGE = 0x5
+ SEARCH_CTRL_ADDR = 0x30
+ SEARCH_CTRL_START_DONE = (0x1 << 7)
+ SEARCH_CTRL_SR_VALID = (0x1)
+
+ VID0_ADDR = 0x33
+ RESULT0_ADDR = 0x3B
+ VID1_ADDR = 0x40
+ RESULT1_ADDR = 0x48
+
+ all = []
+ # write START to search control
+ ctrl = SEARCH_CTRL_START_DONE
+ self.write(ARL_PAGE, SEARCH_CTRL_ADDR, ctrl, 1)
+ while True:
+ ctrl = self.read(ARL_PAGE, SEARCH_CTRL_ADDR, 1)
+ if not (ctrl & SEARCH_CTRL_START_DONE):
+ # Done
+ break
+ if not (ctrl & SEARCH_CTRL_SR_VALID):
+ # result is not ready, sleep and retry
+ time.sleep(0.010) # 10ms
+ continue
+ for vid_addr, result_addr in [[VID1_ADDR, RESULT1_ADDR],
+ [VID0_ADDR, RESULT0_ADDR]]:
+ vid = self.read(ARL_PAGE, vid_addr, 8)
+ result = self.read(ARL_PAGE, result_addr, 4)
+ one = self.__parse_arl_result(vid, result)
+ if one:
+ all.append(one)
+ return all
+
+ def vlan_ctrl(self, enable):
+ VLAN_CTRL_PAGE = 0x34
+ VLAN_CTRL0_REG = 0x0
+ VLAN_CTRL0_B_EN_1QVLAN = 0x1 << 7
+
+ ctrl = self.read(VLAN_CTRL_PAGE, VLAN_CTRL0_REG, 1)
+ need_write = False
+ if enable:
+ if not ctrl & VLAN_CTRL0_B_EN_1QVLAN:
+ need_write = True;
+ ctrl |= VLAN_CTRL0_B_EN_1QVLAN
+ else:
+ if ctrl & VLAN_CTRL0_B_EN_1QVLAN:
+ need_write = True;
+ ctrl &= (~VLAN_CTRL0_B_EN_1QVLAN) & 0xFF
+ if need_write:
+ self.write(VLAN_CTRL_PAGE, VLAN_CTRL0_REG, ctrl, 1)
+
+ def vlan_set_port_default(self, port, vid, pri=0):
+ VLAN_PORT_PAGE = 0x34
+ VLAN_PORT_REG_BASE = 0x10
+
+ if port < 0 or port > 16:
+ raise Exception('Invalid port number %s' % port)
+ if pri < 0 or pri > 7:
+ raise Exception('Invalid priority %s' % pri)
+ if vid < 0 or vid > 0xFFF:
+ raise Exception('Invalid VLAN %s' % vid)
+ reg = VLAN_PORT_REG_BASE + port * 2
+ ctrl = (pri << 13) | vid
+ self.write(VLAN_PORT_PAGE, reg, ctrl, 2)
+
+ def vlan_get_port_default(self, port):
+ VLAN_PORT_PAGE = 0x34
+ VLAN_PORT_REG_BASE = 0x10
+
+ if port < 0 or port > 16:
+ raise Exception('Invalid port number %s' % port)
+ reg = VLAN_PORT_REG_BASE + port * 2
+ val = self.read(VLAN_PORT_PAGE, reg, 2)
+ res = {}
+ res['priority'] = (val >> 13) & 0x7
+ res['vid'] = val & 0xFFF
+ return res
diff --git a/meta-facebook/meta-wedge/recipes-wedge/fbutils/files/bcm5396_util.py b/meta-facebook/meta-wedge/recipes-wedge/fbutils/files/bcm5396_util.py
new file mode 100644
index 0000000..1496412
--- /dev/null
+++ b/meta-facebook/meta-wedge/recipes-wedge/fbutils/files/bcm5396_util.py
@@ -0,0 +1,260 @@
+#!/usr/bin/python
+# Copyright 2004-present Facebook. All rights reserved.
+#
+# This program file is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by the
+# Free Software Foundation; version 2 of the License.
+#
+# This program is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+# for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program in a file named COPYING; if not, write to the
+# Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor,
+# Boston, MA 02110-1301 USA
+#
+
+from argparse import ArgumentParser
+from bcm5396 import Bcm5396
+
+def auto_long(x):
+ return long(x, 0)
+
+def auto_int(x):
+ return int(x, 0)
+
+def get_bcm(args):
+ if args.spi:
+ return Bcm5396(Bcm5396.SPI_ACCESS, cs=args.cs, clk=args.clk,
+ mosi=args.mosi, miso=args.miso)
+ else:
+ return Bcm5396(Bcm5396.MDIO_ACCESS, mdc=args.mdc, mdio=args.mdio)
+
+
+def read_register(args):
+ bcm = get_bcm(args)
+ val = bcm.read(args.page, args.register, args.size)
+ print('Read from BCM5396 ({}:{}.{}): {}'
+ .format(hex(args.page), hex(args.register), args.size, hex(val)))
+
+def write_register(args):
+ bcm = get_bcm(args)
+ val = bcm.write(args.page, args.register, args.value, args.size)
+ print('Write to BCM5396 ({}.{}): {}'
+ .format(hex(args.page), hex(args.register), hex(args.value)))
+
+def register_parser(subparser):
+ reg_parser = subparser.add_parser('register', help='Register IO')
+ reg_sub = reg_parser.add_subparsers()
+
+ read_parser = reg_sub.add_parser('read', help='read switch register')
+ read_parser.set_defaults(func=read_register)
+ read_parser.add_argument('page', type=auto_int,
+ help='The page of the register')
+ read_parser.add_argument('register', type=auto_int,
+ help='The register to read from')
+ read_parser.add_argument('size', type=auto_int,
+ help='Number of bytes',
+ choices=range(1, 9))
+
+ write_parser = reg_sub.add_parser('write', help='write switch register')
+ write_parser.set_defaults(func=write_register)
+ write_parser.add_argument('page', type=auto_int,
+ help='The page oof the register')
+ write_parser.add_argument('register', type=auto_int,
+ help='The register to write to')
+ write_parser.add_argument('value', type=auto_long,
+ help='The value to write')
+ write_parser.add_argument('size', type=auto_int,
+ help='Number of bytes',
+ choices=range(1, 9))
+
+
+def dump_arl(args):
+ bcm = get_bcm(args)
+ arls = bcm.get_all_arls()
+ print('All ARLs are:')
+ for entry in arls:
+ print(entry)
+
+def arl_parser(subparser):
+ dump_parser = subparser.add_parser('arl', help='dump all ARL entries')
+ dump_parser.set_defaults(func=dump_arl)
+
+
+def __parse_port_list(parm):
+ '''Parse the port numbers to a list'''
+ if len(parm) == 0:
+ return []
+ ports=[]
+ for port in parm.split(','):
+ idx = port.find('-')
+ if idx == -1:
+ p = int(port)
+ if p < 0 or p > 15:
+ raise Exception('Invalid port number %s' % p)
+ # just one port
+ ports.append(p)
+ else:
+ start = int(port[:idx])
+ end = int(port[idx+1:])
+ if start > end or start < 0 or end > 15:
+ raise Exception('Invalid port range %s-%s' % (start, end))
+ ports.extend(range(start, end + 1))
+ return ports
+
+def enable_vlan(args):
+ bcm = get_bcm(args)
+ bcm.vlan_ctrl(True)
+ print('VLAN function is enabled.')
+
+def disable_vlan(args):
+ bcm = get_bcm(args)
+ bcm.vlan_ctrl(False)
+ print('VLAN function is disabled.')
+
+def add_vlan(args):
+ bcm = get_bcm(args)
+ vid = args.vid
+ fwd = sorted(__parse_port_list(args.fwd))
+ untag = sorted(__parse_port_list(args.untag))
+ spt = args.spt
+ # make sure untag is subset of fwd
+ if not set(untag).issubset(set(fwd)):
+ raise Exception('Some untagged ports, %s, are not part of forward ports'
+ % (set(untag) - set(fwd)))
+ bcm.add_vlan(vid, untag, fwd, spt)
+ print('Added VLAN: %s' % vid)
+ print('Ports in VLAN: %s' % sorted(fwd))
+ print('Ports without VLAN tag: %s' % sorted(untag))
+
+def remove_vlan(args):
+ bcm = get_bcm(args)
+ vid = args.vid
+ bcm.remove_vlan(vid)
+ print('Removed VLAN: %s' % vid)
+
+def show_vlan(args):
+ bcm = get_bcm(args)
+ vid = args.vid
+ vlan = bcm.get_vlan(vid)
+ if not vlan['valid']:
+ print('VLAN %s does not exist' % vid)
+ else:
+ print('VLAN: %s' % vid)
+ print('Spanning tree index: %s' % vlan['spt'])
+ print('Ports in VLAN: %s' % sorted(vlan['fwd']))
+ print('Untagged ports in VLAN: %s' % sorted(vlan['untag']))
+
+def set_port_vlan(args):
+ bcm = get_bcm(args)
+ bcm.vlan_set_port_default(args.port, args.vid, args.pri)
+ print('Set VLAN default for port: %s' % args.port)
+ print('Default VLAN: %s' % args.vid)
+ print('Default priority %s' % args.pri)
+
+def get_port_vlan(args):
+ bcm = get_bcm(args)
+ port = bcm.vlan_get_port_default(args.port)
+ print('Get VLAN default for port: %s' % args.port)
+ print('Default VLAN: %s' % port['vid'])
+ print('Default priority: %s' % port['priority'])
+
+def vlan_parser(subparser):
+ UNTAG_DEFAULT = ''
+ SPT_DEFAULT = 0
+ PRI_DEFAULT = 0
+
+ vlan_parser = subparser.add_parser('vlan', help='Manage vlan function')
+ vlan_sub = vlan_parser.add_subparsers()
+
+ add_parser = vlan_sub.add_parser('add', help='Add or modify a VLAN entry')
+ add_parser.add_argument('vid', type=int, help='The VLAN ID')
+ add_parser.add_argument('fwd', type=str,
+ help='Ports belonging to this VLAN. i.e. 1,4,5-8')
+ add_parser.add_argument('untag', type=str, default=UNTAG_DEFAULT, nargs='?',
+ help='Ports that do not add VLAN tag. i.e. 1,4,5-8'
+ ' (default: all ports are tagged)')
+ add_parser.add_argument('spt', type=int, default=SPT_DEFAULT, nargs='?',
+ help='Spanning tree index (default: %s)'
+ % SPT_DEFAULT)
+ add_parser.set_defaults(func=add_vlan)
+
+ remove_parser = vlan_sub.add_parser('remove', help='Remove a VLAN entry')
+ remove_parser.add_argument('vid', type=int, help='The VLAN ID')
+ remove_parser.set_defaults(func=remove_vlan)
+
+ show_parser = vlan_sub.add_parser('show', help='Show a VLAN entry')
+ show_parser.add_argument('vid', type=int, help='The VLAN ID')
+ show_parser.set_defaults(func=show_vlan)
+
+ enable_parser = vlan_sub.add_parser('enable', help='Enable VLAN function')
+ enable_parser.set_defaults(func=enable_vlan)
+
+ disable_parser = vlan_sub.add_parser('disable', help='Enable VLAN function')
+ disable_parser.set_defaults(func=disable_vlan)
+
+ port_parser = vlan_sub.add_parser('port',
+ help='Set/Get VLAN default for a port')
+ port_sub = port_parser.add_subparsers()
+ set_port = port_sub.add_parser('set', help='Set VLAN default for a port')
+ set_port.add_argument('port', type=int, help='The port number (0..16)')
+ set_port.add_argument('vid', type=int,
+ help='The default VLAN for this port')
+ set_port.add_argument('pri', type=int, default=PRI_DEFAULT, nargs='?',
+ help='The default priority for this port '
+ '(default: %s)' % PRI_DEFAULT)
+ set_port.set_defaults(func=set_port_vlan)
+
+ get_port = port_sub.add_parser('get', help='Get VLAN default for a port')
+ get_port.add_argument('port', type=int, help='The port number (0..16)')
+ get_port.set_defaults(func=get_port_vlan)
+
+def access_parser(ap):
+ SPI_CS_DEFAULT = 68
+ SPI_CLK_DEFAULT = 69
+ SPI_MOSI_DEFAULT = 70
+ SPI_MISO_DEFAULT = 71
+
+ MDIO_MDC_DEFAULT = 6
+ MDIO_MDIO_DEFAULT = 7
+
+ spi_group = ap.add_argument_group('SPI Access')
+ spi_group.add_argument('--spi', action='store_true',
+ help='Access through SPI.')
+ spi_group.add_argument('--cs', type=int, default=SPI_CS_DEFAULT,
+ help='The GPIO number for SPI CS pin (default: %s)'
+ % SPI_CS_DEFAULT)
+ spi_group.add_argument('--clk', type=int, default=SPI_CLK_DEFAULT,
+ help='The GPIO number for SPI CLK pin (default: %s)'
+ % SPI_CLK_DEFAULT)
+ spi_group.add_argument('--mosi', type=int, default=SPI_MOSI_DEFAULT,
+ help='The GPIO number for SPI MOSI pin (default: %s)'
+ % SPI_MOSI_DEFAULT)
+ spi_group.add_argument('--miso', type=int, default=SPI_MISO_DEFAULT,
+ help='The GPIO number for SPI MISO pin (default: %s)'
+ % SPI_MISO_DEFAULT)
+ mdio_group = ap.add_argument_group('MDIO Access (default)')
+ mdio_group.add_argument('--mdc', type=int, default=MDIO_MDC_DEFAULT,
+ help='The GPIO number for MDC pin (default: %s)'
+ % MDIO_MDC_DEFAULT)
+ mdio_group.add_argument('--mdio', type=int, default=MDIO_MDIO_DEFAULT,
+ help='The GPIO number for MDIO pin (default: %s)'
+ % MDIO_MDIO_DEFAULT)
+ return ap
+
+
+if __name__ == '__main__':
+ ap = ArgumentParser()
+ access_parser(ap)
+
+ subparsers = ap.add_subparsers()
+ register_parser(subparsers)
+ arl_parser(subparsers)
+ vlan_parser(subparsers)
+ args = ap.parse_args()
+
+ args.func(args)
diff --git a/meta-facebook/meta-wedge/recipes-wedge/fbutils/files/create_vlan_intf b/meta-facebook/meta-wedge/recipes-wedge/fbutils/files/create_vlan_intf
new file mode 100644
index 0000000..2cf7a9a
--- /dev/null
+++ b/meta-facebook/meta-wedge/recipes-wedge/fbutils/files/create_vlan_intf
@@ -0,0 +1,37 @@
+#!/bin/bash
+#
+# Copyright 2014-present Facebook. All Rights Reserved.
+#
+# This program file is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by the
+# Free Software Foundation; version 2 of the License.
+#
+# This program is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+# for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program in a file named COPYING; if not, write to the
+# Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor,
+# Boston, MA 02110-1301 USA
+#
+
+# only care about 'eth0' and 'oob' intf
+[ "$IFACE" != "eth0" ] && [ "$IFACE" != "oob" ] && exit 0
+
+. /usr/local/fbpackages/utils/ast-functions
+
+board=$(wedge_board_type)
+
+[ "$board" = "WEDGE" ] && exit 0
+
+vlan=4088
+intf="${IFACE}.${vlan}"
+slot=$(wedge_slot_id $board)
+
+vconfig add $IFACE $vlan
+ifconfig $intf up "fe80::$(printf "%x" $slot):1/64"
+
+exit 0
diff --git a/meta-facebook/meta-wedge/recipes-wedge/fbutils/files/eth0_mac_fixup.sh b/meta-facebook/meta-wedge/recipes-wedge/fbutils/files/eth0_mac_fixup.sh
new file mode 100644
index 0000000..1cdbcb6
--- /dev/null
+++ b/meta-facebook/meta-wedge/recipes-wedge/fbutils/files/eth0_mac_fixup.sh
@@ -0,0 +1,41 @@
+#!/bin/bash
+#
+# Copyright 2014-present Facebook. All Rights Reserved.
+#
+# This program file is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by the
+# Free Software Foundation; version 2 of the License.
+#
+# This program is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+# for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program in a file named COPYING; if not, write to the
+# Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor,
+# Boston, MA 02110-1301 USA
+#
+
+### BEGIN INIT INFO
+# Provides: eth0_mac_fixup.sh
+# Required-Start:
+# Required-Stop:
+# Default-Start: S
+# Default-Stop:
+# Short-Description: Fixup the MAC address for eth0 based on wedge EEPROM
+### END INIT INFO
+
+PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/bin
+
+mac=$(weutil 2>/dev/null | grep '^Local MAC' 2>/dev/null | cut -d' ' -f3 2>/dev/null)
+
+if [ -n "$mac" ]; then
+ ifconfig eth0 hw ether $mac
+ # compare the 'ethaddr' from u-boot env
+ ethaddr=$(fw_printenv ethaddr 2>/dev/null | cut -d'=' -f2 2>/dev/null)
+ if [ "$ethaddr" != "$mac" ]; then
+ fw_setenv "ethaddr" "$mac"
+ fi
+fi
diff --git a/meta-facebook/meta-wedge/recipes-wedge/fbutils/files/fcswitcher.sh b/meta-facebook/meta-wedge/recipes-wedge/fbutils/files/fcswitcher.sh
new file mode 100755
index 0000000..53e24f3
--- /dev/null
+++ b/meta-facebook/meta-wedge/recipes-wedge/fbutils/files/fcswitcher.sh
@@ -0,0 +1,83 @@
+#! /bin/sh
+#
+# Copyright 2014-present Facebook. All Rights Reserved.
+#
+# This program file is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by the
+# Free Software Foundation; version 2 of the License.
+#
+# This program is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+# for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program in a file named COPYING; if not, write to the
+# Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor,
+# Boston, MA 02110-1301 USA
+#
+
+### BEGIN INIT INFO
+# Provides: usbcons
+# Required-Start:
+# Required-Stop:
+# Default-Start: S
+# Default-Stop: 0 6
+# Short-Description: Creates a virtual USB serial device and starts a console
+# on it.
+#
+### END INIT INFO
+
+PATH=/sbin:/bin:/usr/sbin:/usr/bin
+NAME="FC Switcher"
+DESC="FC Failover Daemon"
+
+# source function library
+. /etc/init.d/functions
+
+. /usr/local/fbpackages/utils/ast-functions
+
+STOPPER=
+ACTION="$1"
+
+case "$ACTION" in
+ start)
+ if [ "$(wedge_board_type)" = "LC" ]; then
+ # Ability to prevent this from starting by editing cmdline in u-boot.
+ # Keeping this here until I get gadget switching working properly. (t4906522)
+ /usr/local/bin/watch-fc.sh > /dev/null 2>&1 &
+ echo "$NAME."
+ else
+ echo 'skipping watch-fc.sh: only necessary on six-pack line cards.'
+ fi
+ ;;
+ stop)
+ echo -n "Stopping $DESC: "
+ killall watch-fc.sh
+ echo "$NAME."
+ ;;
+ restart|force-reload)
+ echo -n "Restarting $DESC: "
+ killall watch-fc.sh
+ if [ "$(wedge_board_type)" = "LC" ]; then
+ sleep 1
+ /usr/local/bin/watch-fc.sh > /dev/null 2>&1 &
+ echo "$NAME."
+ else
+ echo 'skipping watch-fc.sh: only necessary on six-pack line cards.'
+ fi
+ ;;
+ status)
+ status watch-fc.sh
+ exit $?
+ ;;
+ *)
+ N=${0##*/}
+ N=${N#[SK]??}
+ echo "Usage: $N {start|stop|status|restart|force-reload}" >&2
+ exit 1
+ ;;
+esac
+
+exit 0
diff --git a/meta-facebook/meta-wedge/recipes-wedge/fbutils/files/mdio.py b/meta-facebook/meta-wedge/recipes-wedge/fbutils/files/mdio.py
new file mode 100755
index 0000000..aa7d4bf
--- /dev/null
+++ b/meta-facebook/meta-wedge/recipes-wedge/fbutils/files/mdio.py
@@ -0,0 +1,124 @@
+#!/usr/bin/python
+#
+# Copyright 2014-present Facebook. All Rights Reserved.
+#
+# This program file is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by the
+# Free Software Foundation; version 2 of the License.
+#
+# This program is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+# for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program in a file named COPYING; if not, write to the
+# Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor,
+# Boston, MA 02110-1301 USA
+#
+
+from argparse import ArgumentParser
+import subprocess
+import time
+
+IO_BASE = [ 0x1e660000, 0x1e680000 ]
+PHYCR_REG_OFFSET = 0x60
+PHYCR_READ_BIT = 0x1 << 26
+PHYCR_WRITE_BIT = 0x1 << 27
+phycr_reg = lambda mac: IO_BASE[mac - 1] + PHYCR_REG_OFFSET
+PHYDATA_REG_OFFSET = 0x64
+phydata_reg = lambda mac: IO_BASE[mac - 1] + PHYDATA_REG_OFFSET
+
+
+devmem_read_cmd = lambda reg: [ 'devmem', hex(reg) ]
+devmem_write_cmd = lambda reg, val: [ 'devmem', hex(reg), '32', hex(val)]
+
+
+def devmem_read(reg):
+ cmd = devmem_read_cmd(reg)
+ #print('Cmd: {}'.format(cmd))
+ out = subprocess.Popen(cmd, stdout=subprocess.PIPE).communicate()[0]
+ return int(out, 0)
+
+
+def devmem_write(reg, val):
+ cmd = devmem_write_cmd(reg, val)
+ #print('Cmd: {}'.format(cmd))
+ subprocess.Popen(cmd, stdout=subprocess.PIPE).communicate()[0]
+
+
+def wait_for_mdio_done(args):
+ reg = phycr_reg(args.mac)
+ while devmem_read(reg) & (PHYCR_READ_BIT|PHYCR_WRITE_BIT):
+ time.sleep(0.010) # 10ms
+
+
+def read_mdio(args):
+ reg = phycr_reg(args.mac)
+ ctrl = devmem_read(reg)
+ ctrl &= 0x3000003f
+ ctrl |= (args.phy & 0x1F) << 16
+ ctrl |= (args.register & 0x1F) << 21
+ ctrl |= PHYCR_READ_BIT
+ devmem_write(reg, ctrl)
+ wait_for_mdio_done(args)
+ val = devmem_read(phydata_reg(args.mac)) >> 16
+ print('Read from PHY ({}.{}): {}'
+ .format(hex(args.phy), hex(args.register), hex(val)))
+
+
+def write_mdio(args):
+ ctrl_reg = phycr_reg(args.mac)
+ ctrl = devmem_read(ctrl_reg)
+ ctrl &= 0x3000003f
+ ctrl |= (args.phy & 0x1F) << 16
+ ctrl |= (args.register & 0x1F) << 21
+ ctrl |= PHYCR_WRITE_BIT
+ data_reg = phydata_reg(args.mac)
+ # write data first
+ devmem_write(data_reg, args.value)
+ # then ctrl
+ devmem_write(ctrl_reg, ctrl)
+ wait_for_mdio_done(args)
+ print('Write to PHY ({}.{}): {}'
+ .format(hex(args.phy), hex(args.register), hex(args.value)))
+
+
+def auto_int(x):
+ return int(x, 0)
+
+if __name__ == '__main__':
+ ap = ArgumentParser()
+ ap.add_argument('--mac', '-m', type=int, default=2,
+ help='The MAC')
+ ap.add_argument('--phy', '-p', type=auto_int, default=0x1f,
+ help='The PHY address')
+
+ subparsers = ap.add_subparsers()
+
+ read_parser = subparsers.add_parser('read',
+ help='read MDIO')
+ read_parser.set_defaults(func=read_mdio)
+ read_parser.add_argument('register', type=auto_int,
+ help='The register to read from')
+
+ write_parser = subparsers.add_parser('write',
+ help='write MDIO')
+ write_parser.set_defaults(func=write_mdio)
+ write_parser.add_argument('register', type=auto_int,
+ help='The register to write to')
+ write_parser.add_argument('value', type=auto_int,
+ help='The value to write to')
+
+ args = ap.parse_args()
+
+ if args.mac != 2 and args.mac != 1:
+ print("MAC can only be either 1 or 2.")
+ exit(-1)
+
+ if args.phy > 0x1f:
+ printf("PHY address must be smaller than 0x1f.")
+ exit(-2)
+
+ args.func(args)
diff --git a/meta-facebook/meta-wedge/recipes-wedge/fbutils/files/mount_data0.sh b/meta-facebook/meta-wedge/recipes-wedge/fbutils/files/mount_data0.sh
new file mode 100755
index 0000000..6986be5
--- /dev/null
+++ b/meta-facebook/meta-wedge/recipes-wedge/fbutils/files/mount_data0.sh
@@ -0,0 +1,61 @@
+#!/bin/sh
+#
+# Copyright 2014-present Facebook. All Rights Reserved.
+#
+# This program file is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by the
+# Free Software Foundation; version 2 of the License.
+#
+# This program is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+# for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program in a file named COPYING; if not, write to the
+# Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor,
+# Boston, MA 02110-1301 USA
+#
+
+### BEGIN INIT INFO
+# Provides: mount_data0
+# Required-Start: mountvirtfs
+# Required-Stop:
+# Default-Start: S
+# Default-Stop:
+# Short-Description: Mount data0 partition from flash chip.
+# Description:
+### END INIT INFO
+
+. /etc/default/rcS
+
+# Find out which device maps to 'data0' on mtd
+# Note: /proc/mtd lists partitions using mtdX, where X is a number,
+# but we mount using /dev/mtdblockX. We'll do some magic here
+# to get the mtdX (char device) and mtdblockX (block device)
+# names.
+MOUNT_POINT="/mnt/data"
+DATA_CHAR_DEV=$(cat /proc/mtd | awk '{ if ($4 == "\"data0\"") print $1 }' |
+ cut -d ':' -f 1 | awk '{ print "/dev/" $1 }')
+if [ -z "$DATA_CHAR_DEV" ]
+then
+ echo "No data0 partition found. Not mounting anything to $MOUNT_POINT."
+else
+ DEVICE_ID=$(echo $DATA_CHAR_DEV | tail -c 2)
+ DATA_BLOCK_DEV=${DATA_CHAR_DEV/mtd/mtdblock}
+
+ echo "data0 partition found on $DATA_BLOCK_DEV; mounting to $MOUNT_POINT."
+ mount -t jffs2 $DATA_BLOCK_DEV $MOUNT_POINT
+
+ # if the mount failed, format the partition and remount
+ if [ $? -ne 0 ]
+ then
+ echo "Mount failed; formatting $DATA_BLOCK_DEV and remounting."
+ flash_eraseall $DATA_CHAR_DEV
+ mount -t jffs2 $DATA_BLOCK_DEV $MOUNT_POINT
+ fi
+fi
+
+: exit 0
+
diff --git a/meta-facebook/meta-wedge/recipes-wedge/fbutils/files/post_led.sh b/meta-facebook/meta-wedge/recipes-wedge/fbutils/files/post_led.sh
new file mode 100644
index 0000000..c23349f
--- /dev/null
+++ b/meta-facebook/meta-wedge/recipes-wedge/fbutils/files/post_led.sh
@@ -0,0 +1,105 @@
+#!/bin/sh
+#
+# Copyright 2004-present Facebook. All rights reserved.
+#
+# This program file is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by the
+# Free Software Foundation; version 2 of the License.
+#
+# This program is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+# for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program in a file named COPYING; if not, write to the
+# Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor,
+# Boston, MA 02110-1301 USA
+#
+
+usage() {
+ echo "Displays values onto the debug header LEDs."
+ echo "Hex and decimal accepted."
+ echo "Usage: $0 <value>"
+}
+
+. /usr/local/fbpackages/utils/ast-functions
+
+# Function to set the less significant hex digit
+display_lower() {
+ local bit0=$(expr $1 % 2)
+ local bit1=$(expr $1 / 2 % 2)
+ local bit2=$(expr $1 / 4 % 2)
+ local bit3=$(expr $1 / 8 % 2)
+
+ # Set the pins to the correct operating mode.
+ # The relevant pins are GPIOG[0...3].
+ # For GPIO bank G, SCU84[0..3] must be 0.
+ devmem_clear_bit $(scu_addr 84) 0
+ devmem_clear_bit $(scu_addr 84) 1
+ devmem_clear_bit $(scu_addr 84) 2
+ devmem_clear_bit $(scu_addr 84) 3
+
+ # Now set the GPIOs to the right binary values
+ gpio_set 48 $bit0
+ gpio_set 49 $bit1
+ gpio_set 50 $bit2
+ gpio_set 51 $bit3
+}
+
+# Function to set the more significant hex digit
+display_upper() {
+ local bit0=$(expr $1 % 2)
+ local bit1=$(expr $1 / 2 % 2)
+ local bit2=$(expr $1 / 4 % 2)
+ local bit3=$(expr $1 / 8 % 2)
+
+ # Set the pins to the correct operating mode.
+ # The relevant pins are GPIOB[4...7].
+ # GPIOB4: SCU80[12] = 0 and Strap[14] = 0
+ # GPIOB5: SCU80[13] = 0
+ # GPIOB6: SCU80[14] = 0
+ # GPIOB7: SCU80[15] = 0
+ devmem_clear_bit $(scu_addr 70) 14
+ devmem_clear_bit $(scu_addr 80) 12
+ devmem_clear_bit $(scu_addr 80) 13
+ devmem_clear_bit $(scu_addr 80) 14
+ devmem_clear_bit $(scu_addr 80) 15
+
+ gpio_set 12 $bit0
+ gpio_set 13 $bit1
+ gpio_set 14 $bit2
+ gpio_set 15 $bit3
+}
+
+# Check number of parameters
+if [ $# -ne 1 ]
+then
+ usage
+ exit 1
+fi
+
+# Make sure input is actually numeric
+DEC_VALUE=$(printf "%d" $1 2>/dev/null)
+if [ $? -eq 1 ]
+then
+ echo "Unable to parse input as numeric value."
+ exit 1
+fi
+
+# Make sure input is within proper range
+if [ $DEC_VALUE -lt 0 ] || [ $DEC_VALUE -gt 255 ]
+then
+ echo "Value $DEC_VALUE is outside of displayable range 0 - 0xff (255)."
+ exit 1
+fi
+
+# Get upper/lower decimal values
+LOWER_DEC_VALUE=$(expr $DEC_VALUE % 16)
+UPPER_DEC_VALUE=$(expr $DEC_VALUE / 16)
+
+# Display the results
+display_lower $LOWER_DEC_VALUE
+display_upper $UPPER_DEC_VALUE
+
diff --git a/meta-facebook/meta-wedge/recipes-wedge/fbutils/files/power-on.sh b/meta-facebook/meta-wedge/recipes-wedge/fbutils/files/power-on.sh
new file mode 100644
index 0000000..843b79a
--- /dev/null
+++ b/meta-facebook/meta-wedge/recipes-wedge/fbutils/files/power-on.sh
@@ -0,0 +1,72 @@
+#!/bin/sh
+#
+# Copyright 2014-present Facebook. All Rights Reserved.
+#
+# This program file is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by the
+# Free Software Foundation; version 2 of the License.
+#
+# This program is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+# for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program in a file named COPYING; if not, write to the
+# Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor,
+# Boston, MA 02110-1301 USA
+
+### BEGIN INIT INFO
+# Provides: power-on
+# Required-Start:
+# Required-Stop:
+# Default-Start: S
+# Default-Stop:
+# Short-Description: Power on micro-server
+### END INIT INFO
+. /usr/local/fbpackages/utils/ast-functions
+
+PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/bin
+
+echo -n "Checking microserver power status ... "
+if wedge_is_us_on 10 "."; then
+ echo "on"
+ on=1
+else
+ echo "off"
+ on=0
+fi
+
+if [ $on -eq 0 ]; then
+ # Reset USB hub
+ /usr/local/bin/reset_usb.sh
+ # Set up ROV
+ /usr/local/bin/setup_rov.sh
+ # Configure the management switch on LEFT side of FC.
+ # Must do so after setup_rov.sh, as setup_rov.sh might reset
+ # T2, which also resets the switch.
+ if [ "$(wedge_board_type)" = "FC-LEFT" ]; then
+ echo -n "Configure management switch ... "
+ if [ $(wedge_board_rev) -gt 1 ]; then
+ echo "skip. Need new switch setup script!!!"
+ else
+ # configure MDIO as GPIO output
+ gpio_set A6 1
+ gpio_set A7 1
+ # set the switch to be configured by CPU
+ gpio_set E2 1
+ # set the switch to be configured by CPU, then reset the switch,
+ # which also cause T2 reset in the current board
+ gpio_set E2 1
+ gpio_set C0 0
+ sleep 1
+ gpio_set C0 1
+ # configure the switch
+ setup_switch.py
+ echo "done"
+ fi
+ fi
+ # Power on now
+ wedge_power.sh on -f
+fi
diff --git a/meta-facebook/meta-wedge/recipes-wedge/fbutils/files/power_led.sh b/meta-facebook/meta-wedge/recipes-wedge/fbutils/files/power_led.sh
new file mode 100755
index 0000000..20206a1
--- /dev/null
+++ b/meta-facebook/meta-wedge/recipes-wedge/fbutils/files/power_led.sh
@@ -0,0 +1,49 @@
+#!/bin/bash
+#
+# Copyright 2014-present Facebook. All Rights Reserved.
+#
+# This program file is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by the
+# Free Software Foundation; version 2 of the License.
+#
+# This program is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+# for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program in a file named COPYING; if not, write to the
+# Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor,
+# Boston, MA 02110-1301 USA
+#
+
+usage() {
+ echo "Usage: $1 <on | off>"
+ exit -1
+}
+
+. /usr/local/fbpackages/utils/ast-functions
+
+PATH=/sbin:/bin:/usr/sbin:/usr/bin
+
+set -e
+
+if [ $# != 1 ]; then
+ usage $0
+fi
+
+if [ $1 = "on" ]; then
+ val=1
+elif [ $1 = "off" ]; then
+ val=0
+else
+ usage $0
+fi
+
+# To use GPIOE5 (37), SCU80[21], SCU8C[14], and SCU70[22] must be 0
+devmem_clear_bit $(scu_addr 80) 21
+devmem_clear_bit $(scu_addr 8C) 14
+devmem_clear_bit $(scu_addr 70) 22
+
+gpio_set 37 $val
diff --git a/meta-facebook/meta-wedge/recipes-wedge/fbutils/files/rc.early b/meta-facebook/meta-wedge/recipes-wedge/fbutils/files/rc.early
new file mode 100644
index 0000000..0f47c72
--- /dev/null
+++ b/meta-facebook/meta-wedge/recipes-wedge/fbutils/files/rc.early
@@ -0,0 +1,25 @@
+#!/bin/sh
+#
+# Copyright 2014-present Facebook. All Rights Reserved.
+#
+# This program file is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by the
+# Free Software Foundation; version 2 of the License.
+#
+# This program is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+# for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program in a file named COPYING; if not, write to the
+# Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor,
+# Boston, MA 02110-1301 USA
+#
+# This script will be executed at rcS S04 level, which is right after mount /mnt/data
+# and before almost anything else.
+
+if [ -x /mnt/data/etc/rc.early ]; then
+ /mnt/data/etc/rc.early
+fi
diff --git a/meta-facebook/meta-wedge/recipes-wedge/fbutils/files/rc.local b/meta-facebook/meta-wedge/recipes-wedge/fbutils/files/rc.local
new file mode 100644
index 0000000..36fa0f1
--- /dev/null
+++ b/meta-facebook/meta-wedge/recipes-wedge/fbutils/files/rc.local
@@ -0,0 +1,26 @@
+#!/bin/sh
+#
+# Copyright 2014-present Facebook. All Rights Reserved.
+#
+# This program file is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by the
+# Free Software Foundation; version 2 of the License.
+#
+# This program is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+# for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program in a file named COPYING; if not, write to the
+# Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor,
+# Boston, MA 02110-1301 USA
+#
+
+#
+# This script will be executed *after* all the other init scripts.
+
+if [ -x /mnt/data/etc/rc.local ]; then
+ /mnt/data/etc/rc.local
+fi
diff --git a/meta-facebook/meta-wedge/recipes-wedge/fbutils/files/reset_usb.sh b/meta-facebook/meta-wedge/recipes-wedge/fbutils/files/reset_usb.sh
new file mode 100644
index 0000000..7d1c2c6
--- /dev/null
+++ b/meta-facebook/meta-wedge/recipes-wedge/fbutils/files/reset_usb.sh
@@ -0,0 +1,36 @@
+#!/bin/sh
+#
+# Copyright 2014-present Facebook. All Rights Reserved.
+#
+# This program file is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by the
+# Free Software Foundation; version 2 of the License.
+#
+# This program is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+# for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program in a file named COPYING; if not, write to the
+# Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor,
+# Boston, MA 02110-1301 USA
+#
+
+. /usr/local/fbpackages/utils/ast-functions
+
+echo -n "Reset USB Switch ... "
+
+# To use GPIOD7 (31), SCU90[1], SCU8C[11], and SCU70[21] must be 0
+devmem_clear_bit $(scu_addr 8C) 11
+devmem_clear_bit $(scu_addr 70) 21
+devmem_clear_bit $(scu_addr 90) 1
+
+gpio_set 31 1
+sleep 1
+gpio_set 31 0
+sleep 1
+gpio_set 31 1
+
+echo "Done"
diff --git a/meta-facebook/meta-wedge/recipes-wedge/fbutils/files/setup-gpio.sh b/meta-facebook/meta-wedge/recipes-wedge/fbutils/files/setup-gpio.sh
new file mode 100755
index 0000000..9f0b543
--- /dev/null
+++ b/meta-facebook/meta-wedge/recipes-wedge/fbutils/files/setup-gpio.sh
@@ -0,0 +1,349 @@
+#!/bin/bash
+#
+# Copyright 2014-present Facebook. All Rights Reserved.
+#
+# This program file is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by the
+# Free Software Foundation; version 2 of the License.
+#
+# This program is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+# for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program in a file named COPYING; if not, write to the
+# Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor,
+# Boston, MA 02110-1301 USA
+#
+
+### BEGIN INIT INFO
+# Provides: gpio-setup
+# Required-Start:
+# Required-Stop:
+# Default-Start: S
+# Default-Stop:
+# Short-Description: Set up GPIO pins as appropriate
+### END INIT INFO
+
+# This file contains definitions for the GPIO pins that were not otherwise
+# defined in other files. We should probably move some more of the
+# definitions to this file at some point.
+
+# The commented-out sections are generally already defined elsewhere,
+# and defining them twice generates errors.
+
+# The exception to this is the definition of the GPIO H0, H1, and H2
+# pins, which seem to adversely affect the rebooting of the system.
+# When defined, the system doesn't reboot cleanly. We're still
+# investigating this.
+
+. /usr/local/fbpackages/utils/ast-functions
+
+# Set up to read the board revision pins, Y0, Y1, Y2
+devmem_set_bit $(scu_addr 70) 19
+devmem_clear_bit $(scu_addr a4) 8
+devmem_clear_bit $(scu_addr a4) 9
+devmem_clear_bit $(scu_addr a4) 10
+echo 192 > /sys/class/gpio/export
+echo 193 > /sys/class/gpio/export
+echo 194 > /sys/class/gpio/export
+
+# enabled Y0, Y1, Y2, we can use wedge_board_rev() now
+board_rev=$(wedge_board_rev)
+
+# Set up ISO_SVR_ID[0-3], GPION[2-5]
+# On wedge, these 4 GPIOs are not connected. And the corresponding
+# 4 pins from uS are strapped to low.
+# On fabic, these 4 pins are connected to uS SVR_ID pins,
+# which are used to set the uS FPGA i2c address.
+# Force all pins to low to have the same uS FPGA i2c address on wedge
+# and fabric
+# To use GPION[2-5], SCU90[4:5] must be 0, and SCU88[2-5] must be 0 also
+devmem_clear_bit $(scu_addr 90) 4
+devmem_clear_bit $(scu_addr 90) 5
+devmem_clear_bit $(scu_addr 88) 2
+devmem_clear_bit $(scu_addr 88) 3
+devmem_clear_bit $(scu_addr 88) 4
+devmem_clear_bit $(scu_addr 88) 5
+gpio_set 106 0
+gpio_set 107 0
+gpio_set 108 0
+gpio_set 109 0
+
+## CARD_EN, GPIO C3
+#devmem_clear_bit $(scu_addr 90) 0
+#devmem_clear_bit $(scu_addr 90) 24
+#echo 18 > /sys/class/gpio/export
+
+# T2_RESET_N, RESET_SEQ0, RESET_SEQ1, on GPIO C0, F2, and F3
+devmem_clear_bit $(scu_addr 90) 0
+devmem_clear_bit $(scu_addr 90) 23
+devmem_clear_bit $(scu_addr 80) 26
+devmem_clear_bit $(scu_addr a4) 13
+devmem_clear_bit $(scu_addr 80) 27
+devmem_clear_bit $(scu_addr a4) 14
+devmem_set_bit $(scu_addr 70) 19
+echo 16 > /sys/class/gpio/export
+echo 42 > /sys/class/gpio/export
+echo 43 > /sys/class/gpio/export
+# output
+
+# PANTHER_PRSNT_N, uServer presence, on GPIO E4
+devmem_clear_bit $(scu_addr 80) 20
+devmem_clear_bit $(scu_addr 8c) 14
+devmem_clear_bit $(scu_addr 70) 22
+echo 36 > /sys/class/gpio/export
+
+# MRSRVR_SYS_RST, reset the uServer, on GPIO C1
+devmem_clear_bit $(scu_addr 90) 0
+devmem_clear_bit $(scu_addr 90) 23
+echo 17 > /sys/class/gpio/export
+# output
+
+# BMC_PWR_BTN_IN_N, uServer power button in, on GPIO D0
+# BMC_PWR_BTN_OUT_N, uServer power button out, on GPIO D1
+devmem_clear_bit $(scu_addr 90) 1
+devmem_clear_bit $(scu_addr 8c) 8
+devmem_clear_bit $(scu_addr 70) 21
+echo 24 > /sys/class/gpio/export
+# we have to ensure that BMC_PWR_BTN_OUT_N is high so that
+# when we enable the isolation buffer, uS will not be powered down
+gpio_set 25 1
+
+## BMC_READY_IN, BMC signal that it's up, on GPIO P7
+# To use GPIOP7 (127), SCU88[23] must be 0
+devmem_clear_bit $(scu_addr 88) 23
+# Put GPIOP7 (127) to low so that we can control uS power now
+# This must be after 'gpio_set 25 1'
+gpio_set 127 0
+
+# PANTHER_I2C_ALERT_N, alert for uServer I2C, GPIO B0
+devmem_clear_bit $(scu_addr 80) 8
+echo 8 > /sys/class/gpio/export
+
+# MNSERV_NIC_SMBUS_ALRT, alert for uServer NIC, GPIO B1
+devmem_clear_bit $(scu_addr 80) 9
+echo 9 > /sys/class/gpio/export
+
+# LED_PWR_BLUE, blue power light, GPIO E5
+devmem_clear_bit $(scu_addr 80) 21
+devmem_clear_bit $(scu_addr 8c) 14
+devmem_clear_bit $(scu_addr 70) 22
+echo 37 > /sys/class/gpio/export
+# output
+
+# BMC_HEARTBEAT_N, heartbeat LED, GPIO Q7
+devmem_clear_bit $(scu_addr 90) 28
+echo 135 > /sys/class/gpio/export
+# output
+
+# XXX: setting those causes the system to lock up on reboot
+## T2 ROV1, ROV2, ROV3 -- voltage reading, GPIOs H0, H1, and H2
+#devmem_clear_bit $(scu_addr 90) 6
+#devmem_clear_bit $(scu_addr 90) 7
+#devmem_clear_bit $(scu_addr 70) 4
+## Do I need to set 70:1 and 70:0 to 1?
+echo 56 > /sys/class/gpio/export
+echo 57 > /sys/class/gpio/export
+echo 58 > /sys/class/gpio/export
+
+# HOTSWAP_PG, hotswap issues, GPIO L3
+devmem_clear_bit $(scu_addr 90) 5
+devmem_clear_bit $(scu_addr 90) 4
+devmem_clear_bit $(scu_addr 84) 19
+echo 99 > /sys/class/gpio/export
+
+# XXX: These interfere with i2c bus 11 (on Linux, it's 12 on the hardware)
+# which we need to talk to the power supplies on certain hardware.
+## Hardware presence pins C4 and C5
+#devmem_clear_bit $(scu_addr 90) 0
+#devmem_clear_bit $(scu_addr 90) 24
+#echo 20 > /sys/class/gpio/export
+#echo 21 > /sys/class/gpio/export
+
+# FAB_GE_SEL, uServer GE connection, GPIO A0
+devmem_clear_bit $(scu_addr 80) 0
+echo 0 > /sys/class/gpio/export
+# output
+
+# USB_OCS_N1, resettable fuse tripped, GPIO Q6
+devmem_clear_bit $(scu_addr 90) 28
+echo 136 > /sys/class/gpio/export
+
+# RX loss signal?
+
+# System SPI
+# Strap 12 must be 0 and Strape 13 must be 1
+devmem_clear_bit $(scu_addr 70) 12
+devmem_set_bit $(scu_addr 70) 13
+# GPIOQ4 is ISO_FLASH_WP, must be 1 to avoid write protection
+# GPIOQ5 is ISO_FLASH_HOLD, must be 1 to be out of reset
+# To use GPIOQ4 and GPIOQ5, SCU90[27] must be 0
+devmem_clear_bit $(scu_addr 90) 27
+gpio_set 134 1
+gpio_set 135 1
+# GPIOD6 is ISO_FL_PRG_SEL, set it to 0 so that BMC does not have control
+# on the EEPROM by default.
+# To use GPIOD6, SCU90[1] must be 0, SCU8C[21] must be 0, and Strap[21] must be 0
+devmem_clear_bit $(scu_addr 90) 1
+devmem_clear_bit $(scu_addr 8c) 8
+devmem_clear_bit $(scu_addr 70) 21
+gpio_set 30 0
+
+# DEBUG_RST_BTN_N, Debug Reset button on front panel, GPIO R2
+devmem_clear_bit $(scu_addr 88) 26
+echo 138 > /sys/class/gpio/export
+
+# DEBUG_PORT_UART_SEL_N, Debug Select button, GPIO B2
+devmem_clear_bit $(scu_addr 80) 10
+echo 10 > /sys/class/gpio/export
+
+# DEBUG_UART_SEL_0, select uServer UART to the debug header, GPIO E0
+devmem_clear_bit $(scu_addr 80) 16
+devmem_clear_bit $(scu_addr 8c) 12
+devmem_clear_bit $(scu_addr 70) 22
+echo 32 > /sys/class/gpio/export
+# output
+
+# RS485 transceiver TX/RX toggle (RTS) pin, GPIOF5
+devmem_clear_bit $(scu_addr 80) 29
+echo 45 > /sys/class/gpio/export
+gpio_set 45 0
+
+# Bloodhound GPIOs, P0-6, G4, J1-3, Y3
+# Make sure GPIOP0,1,2,3,6 are enabled.
+for i in {16..19} 22; do
+ devmem_clear_bit $(scu_addr 88) $i
+done
+# Enable GPIOY3
+devmem_clear_bit $(scu_addr a4) 11
+# GPIOG4
+devmem_clear_bit $(scu_addr 2c) 1
+# GPIOJ1
+devmem_clear_bit $(scu_addr 84) 9
+# GPIOJ2
+devmem_clear_bit $(scu_addr 84) 10
+# GPIOJ11
+devmem_clear_bit $(scu_addr 84) 11
+
+# Export all the GPIOs
+for i in {120..126} 52 {73..75} 195; do
+ echo $i > /sys/class/gpio/export
+done
+
+# Enable the isolation buffer
+wedge_iso_buf_enable
+
+# Get the board type by parsing the EEPROM.
+# This must be after enabling isolation buffer as the i2c bus
+# is isolated by the buffer
+board_type=$(wedge_board_type)
+
+case "$board_type" in
+ FC-LEFT|FC-RIGHT)
+ # On FC
+ # FAB_SLOT_ID is GPIOU0
+ # PEER_FAB_PRSNT is GPIOU1
+ devmem_set_bit $(scu_addr a0) 8
+ devmem_set_bit $(scu_addr a0) 9
+ gpio_export U0
+ gpio_export U1
+ # T2_POWER_UP is GPIOT6
+ devmem_set_bit $(scu_addr a0) 6
+ gpio_export T6
+ # HS_FAULT_N is GPIOT7
+ devmem_set_bit $(scu_addr a0) 7
+ gpio_export T7
+ if [ "$board_type" = "FC-LEFT" ]; then
+ # GPIOE2 is CPU_EEPROM_SEL, on FC-LEFT
+ devmem_clear_bit $(scu_addr 80) 18
+ devmem_clear_bit $(scu_addr 8c) 13
+ devmem_clear_bit $(scu_addr 70) 22
+ gpio_export E2
+ # GPIOA6 and GPIOA7 are MAC2 MDIO pins, we use them as
+ # GPIO for bitbang driver
+ devmem_clear_bit $(scu_addr 90) 2
+ devmem_clear_bit $(scu_addr 80) 6
+ devmem_clear_bit $(scu_addr 80) 7
+ gpio_export A6
+ gpio_export A7
+ fi
+ ;;
+ *)
+ # Set up to watch for FC presence, and switch between interfaces.
+ # GPIOC0..C7, interested in C4, C5
+ devmem_clear_bit $(scu_addr 90) 0
+ devmem_clear_bit $(scu_addr 90) 25
+ if [ $board_rev -lt 3 ]; then
+ # Prior to DVTC
+ # BP_SLOT_ID GPIO pins are U0, U1, U2, U3
+ devmem_set_bit $(scu_addr a0) 8
+ devmem_set_bit $(scu_addr a0) 9
+ devmem_set_bit $(scu_addr a0) 10
+ devmem_set_bit $(scu_addr a0) 11
+ gpio_export U0
+ gpio_export U1
+ gpio_export U2
+ gpio_export U3
+ # T2_POWER_UP is GPIOT6
+ devmem_set_bit $(scu_addr a0) 6
+ gpio_export T6
+ # HS_FAULT_N is GPIOT7
+ devmem_set_bit $(scu_addr a0) 7
+ gpio_export T7
+ else
+ # Starting from DVTC
+ # BP_SLOT_ID GPIO pins are U6, U7, V0, V1
+ devmem_set_bit $(scu_addr 70) 6
+ devmem_set_bit $(scu_addr a0) 14
+ devmem_set_bit $(scu_addr a0) 15
+ devmem_set_bit $(scu_addr a0) 16
+ devmem_set_bit $(scu_addr a0) 17
+ gpio_export U6
+ gpio_export U7
+ gpio_export V0
+ gpio_export V1
+ # T2_POWER_UP is GPIOU4
+ devmem_set_bit $(scu_addr a0) 12
+ gpio_export U4
+ # HS_FAULT_N is GPIOU5
+ devmem_set_bit $(scu_addr a0) 13
+ gpio_export U5
+ fi
+ ;;
+esac
+
+# Make it possible to turn off T2 if fand sees overheating via GPIOF1
+# Do not change the GPIO direction here as the default value of this GPIO
+# is low, which causes a Non-maskable interrupt to the uS.
+devmem_clear_bit $(scu_addr 80) 25
+devmem_clear_bit $(scu_addr a4) 12
+echo 41 > /sys/class/gpio/export
+
+# Allow us to set the fan LEDs boards.
+# This is GPIO G5, G6, G7, and J0
+
+devmem_clear_bit $(scu_addr 70) 23
+devmem_clear_bit $(scu_addr 84) 5
+devmem_clear_bit $(scu_addr 84) 6
+devmem_clear_bit $(scu_addr 84) 7
+devmem_clear_bit $(scu_addr 84) 8
+
+echo 53 > /sys/class/gpio/export
+echo 54 > /sys/class/gpio/export
+echo 55 > /sys/class/gpio/export
+echo 72 > /sys/class/gpio/export
+echo "out" > /sys/class/gpio/gpio53/direction
+echo "out" > /sys/class/gpio/gpio54/direction
+echo "out" > /sys/class/gpio/gpio55/direction
+echo "out" > /sys/class/gpio/gpio72/direction
+
+# Once we set "out", output values will be random unless we set them
+# to something
+
+echo "0" > /sys/class/gpio/gpio53/value
+echo "0" > /sys/class/gpio/gpio54/value
+echo "0" > /sys/class/gpio/gpio55/value
+echo "0" > /sys/class/gpio/gpio72/value
diff --git a/meta-facebook/meta-wedge/recipes-wedge/fbutils/files/setup_rov.sh b/meta-facebook/meta-wedge/recipes-wedge/fbutils/files/setup_rov.sh
new file mode 100755
index 0000000..749fe65
--- /dev/null
+++ b/meta-facebook/meta-wedge/recipes-wedge/fbutils/files/setup_rov.sh
@@ -0,0 +1,99 @@
+#!/bin/bash
+#
+# Copyright 2014-present Facebook. All Rights Reserved.
+#
+# This program file is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by the
+# Free Software Foundation; version 2 of the License.
+#
+# This program is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+# for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program in a file named COPYING; if not, write to the
+# Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor,
+# Boston, MA 02110-1301 USA
+#
+
+# The T2 chip can prefer different input voltages, depending, presumably
+# of manufacturing variations. We need to determine whether it wants
+# 0.95V or 1.025V, reset the T2 to reduce total power usage, set the
+# outgoing voltage on the first buck converter, and bring T2 up out of
+# reset.
+
+. /usr/local/fbpackages/utils/ast-functions
+
+# read the T2 ROV after the GPIOs are enabled
+t2_rov() {
+ local val0 val1 val2
+ # Note that the values are *not* read in order.
+ val0=$(cat /sys/class/gpio/gpio58/value 2>/dev/null)
+ val1=$(cat /sys/class/gpio/gpio56/value 2>/dev/null)
+ val2=$(cat /sys/class/gpio/gpio57/value 2>/dev/null)
+ echo $((val0 | (val1 << 1) | (val2 << 2)))
+}
+
+rov=$(t2_rov)
+
+# target_volts come from the data sheet and 18mV of loss and
+# some fudging based on actual measurements to get either 1.025V
+# or 0.95V at T2
+if [ $rov -eq 1 ]; then
+ target_volts=0x5a
+elif [ $rov -eq 2 ]; then
+ target_volts=0x65
+else
+ echo "Unrecognized T2 ROV value $rov, setting failed."
+ exit 1
+fi
+target_volts=$(( $target_volts * 1 )) # normalize to decimal
+
+# We shouldn't have to rmmod pmbus, because it hasn't been loaded yet,
+# but if the script is rerun after the system is up, it may be necessary.
+rmmod pmbus
+reload=$?
+
+# Get current voltage value
+cur_volts=$(i2cget -y 1 0x60 0x8b w)
+cur_volts=$(( $cur_volts * 1 )) # normalize to decimal
+
+# Only bounce the T2 if we actually need to modify the voltage
+if [ $cur_volts -ne $target_volts ]; then
+ # Set values before turning out output; we're using "PCIE, then MCS"
+ echo 1 > /sys/class/gpio/gpio42/value
+ echo 1 > /sys/class/gpio/gpio43/value
+ echo out > /sys/class/gpio/gpio42/direction
+ echo out > /sys/class/gpio/gpio43/direction
+ echo 0 > /sys/class/gpio/gpio16/value
+ echo out > /sys/class/gpio/gpio16/direction
+ # T2 is in reset; note that this may cause NMI messages on the uServer,
+ # which shouldn't be up anyway when this is first run.
+
+ # Set the requested value to the current value to avoid rapid shifts
+ i2cset -y 1 0x60 0x21 $cur_volts w
+ # Enable the requested voltage
+ i2cset -y 1 0x60 0xd2 0x5a
+ i2cset -y 1 0x60 0xd3 0x5a
+ sleep 1
+
+ # Set the target voltage
+ i2cset -y 1 0x60 0x21 $target_volts w
+
+ sleep 1
+
+ # Let T2 come out of reset
+ echo 1 > /sys/class/gpio/gpio16/value
+ echo "T2 ROV value set based on $rov."
+ sleep 2
+ echo 0 > /sys/class/gpio/gpio42/value
+ echo 0 > /sys/class/gpio/gpio43/value
+else
+ echo "T2 ROV already correctly set."
+fi
+# Bring back pmbus if necessary
+if [ $reload -eq 0 ]; then
+ modprobe pmbus
+fi
diff --git a/meta-facebook/meta-wedge/recipes-wedge/fbutils/files/setup_switch.py b/meta-facebook/meta-wedge/recipes-wedge/fbutils/files/setup_switch.py
new file mode 100644
index 0000000..995cec8
--- /dev/null
+++ b/meta-facebook/meta-wedge/recipes-wedge/fbutils/files/setup_switch.py
@@ -0,0 +1,49 @@
+#!/usr/bin/python
+#
+# Copyright 2004-present Facebook. All rights reserved.
+#
+# This program file is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by the
+# Free Software Foundation; version 2 of the License.
+#
+# This program is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+# for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program in a file named COPYING; if not, write to the
+# Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor,
+# Boston, MA 02110-1301 USA
+#
+# This script combines multiple switch configuration into one python script.
+# All such configuration can be done directly through bcm5396_util.py.
+# But, it turns out it took several seconds to just start the python script.
+# Involking the script 16 times (2 to create vlan, 13 to set port vlan default,
+# and 1 to enable vlan function) contributes 1 minute delay.
+
+from bcm5396 import Bcm5396
+
+MDC_GPIO = 6
+MDIO_GPIO = 7
+
+INTERNAL_VLAN = 4088
+DEFAULT_VLAN=4090
+
+INTERNAL_PORTS = [3, 10, 1, 11, 0, 8, 2, 9, 4, 12, 14, 13]
+FRONT_PORT=5
+
+if __name__ == '__main__':
+ bcm = Bcm5396(Bcm5396.MDIO_ACCESS, mdc=MDC_GPIO, mdio=MDIO_GPIO)
+ # create default VLAN including internal ports and front panel
+ # port (un-tagged)
+ bcm.add_vlan(DEFAULT_VLAN, INTERNAL_PORTS + [FRONT_PORT],
+ INTERNAL_PORTS + [FRONT_PORT], 0)
+ # set ingress vlan for internal ports and front panel port to default vlan
+ for port in INTERNAL_PORTS + [FRONT_PORT]:
+ bcm.vlan_set_port_default(port, DEFAULT_VLAN, 0)
+ # create internal vlan including internal ports only (tagged)
+ bcm.add_vlan(INTERNAL_VLAN, [], INTERNAL_PORTS, 0)
+ # enable vlan
+ bcm.vlan_ctrl(True)
diff --git a/meta-facebook/meta-wedge/recipes-wedge/fbutils/files/sol.sh b/meta-facebook/meta-wedge/recipes-wedge/fbutils/files/sol.sh
new file mode 100755
index 0000000..ccbdc61
--- /dev/null
+++ b/meta-facebook/meta-wedge/recipes-wedge/fbutils/files/sol.sh
@@ -0,0 +1,37 @@
+#!/bin/sh
+#
+# Copyright 2014-present Facebook. All Rights Reserved.
+#
+# This program file is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by the
+# Free Software Foundation; version 2 of the License.
+#
+# This program is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+# for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program in a file named COPYING; if not, write to the
+# Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor,
+# Boston, MA 02110-1301 USA
+#
+
+CONSOLE_SH=/usr/local/fbpackages/utils/us_console.sh
+
+$CONSOLE_SH connect
+
+echo "You are in SOL session."
+echo "Use ctrl-x to quit."
+echo "-----------------------"
+echo
+
+trap '"$CONSOLE_SH" disconnect' INT TERM QUIT EXIT
+
+/usr/bin/microcom -s 57600 /dev/ttyS1
+
+echo
+echo
+echo "-----------------------"
+echo "Exit from SOL session."
diff --git a/meta-facebook/meta-wedge/recipes-wedge/fbutils/files/src/include/i2c-dev.h b/meta-facebook/meta-wedge/recipes-wedge/fbutils/files/src/include/i2c-dev.h
new file mode 100644
index 0000000..eefb6e4
--- /dev/null
+++ b/meta-facebook/meta-wedge/recipes-wedge/fbutils/files/src/include/i2c-dev.h
@@ -0,0 +1,362 @@
+/*
+ i2c-dev.h - i2c-bus driver, char device interface
+
+ Copyright (C) 1995-97 Simon G. Vogl
+ Copyright (C) 1998-99 Frodo Looijaard <frodol@dds.nl>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ MA 02110-1301 USA.
+*/
+
+#ifndef _LINUX_I2C_DEV_H
+#define _LINUX_I2C_DEV_H
+
+#include <linux/types.h>
+#include <sys/ioctl.h>
+#include <stddef.h>
+#include <string.h>
+
+
+/* -- i2c.h -- */
+
+#define _I2C_MIN(a, b) (((a) <= (b)) ? (a) : (b))
+
+/*
+ * I2C Message - used for pure i2c transaction, also from /dev interface
+ */
+struct i2c_msg {
+ __u16 addr; /* slave address */
+ unsigned short flags;
+#define I2C_CLIENT_PEC 0x04 /* Use Packet Error Checking */
+#define I2C_M_TEN 0x0010 /* this is a ten bit chip address */
+#define I2C_M_RD 0x0001 /* read data, from slave to master */
+#define I2C_M_NOSTART 0x4000 /* if I2C_FUNC_PROTOCOL_MANGLING */
+#define I2C_M_REV_DIR_ADDR 0x2000 /* if I2C_FUNC_PROTOCOL_MANGLING */
+#define I2C_M_IGNORE_NAK 0x1000 /* if I2C_FUNC_PROTOCOL_MANGLING */
+#define I2C_M_NO_RD_ACK 0x0800 /* if I2C_FUNC_PROTOCOL_MANGLING */
+#define I2C_M_RECV_LEN 0x0400 /* length will be first received byte */
+ short len; /* msg length */
+ char *buf; /* pointer to msg data */
+};
+
+/* To determine what functionality is present */
+
+#define I2C_FUNC_I2C 0x00000001
+#define I2C_FUNC_10BIT_ADDR 0x00000002
+#define I2C_FUNC_PROTOCOL_MANGLING 0x00000004 /* I2C_M_{REV_DIR_ADDR,NOSTART,..} */
+#define I2C_FUNC_SMBUS_PEC 0x00000008
+#define I2C_FUNC_SMBUS_BLOCK_PROC_CALL 0x00008000 /* SMBus 2.0 */
+#define I2C_FUNC_SMBUS_QUICK 0x00010000
+#define I2C_FUNC_SMBUS_READ_BYTE 0x00020000
+#define I2C_FUNC_SMBUS_WRITE_BYTE 0x00040000
+#define I2C_FUNC_SMBUS_READ_BYTE_DATA 0x00080000
+#define I2C_FUNC_SMBUS_WRITE_BYTE_DATA 0x00100000
+#define I2C_FUNC_SMBUS_READ_WORD_DATA 0x00200000
+#define I2C_FUNC_SMBUS_WRITE_WORD_DATA 0x00400000
+#define I2C_FUNC_SMBUS_PROC_CALL 0x00800000
+#define I2C_FUNC_SMBUS_READ_BLOCK_DATA 0x01000000
+#define I2C_FUNC_SMBUS_WRITE_BLOCK_DATA 0x02000000
+#define I2C_FUNC_SMBUS_READ_I2C_BLOCK 0x04000000 /* I2C-like block xfer */
+#define I2C_FUNC_SMBUS_WRITE_I2C_BLOCK 0x08000000 /* w/ 1-byte reg. addr. */
+
+#define I2C_FUNC_SMBUS_BYTE (I2C_FUNC_SMBUS_READ_BYTE | \
+ I2C_FUNC_SMBUS_WRITE_BYTE)
+#define I2C_FUNC_SMBUS_BYTE_DATA (I2C_FUNC_SMBUS_READ_BYTE_DATA | \
+ I2C_FUNC_SMBUS_WRITE_BYTE_DATA)
+#define I2C_FUNC_SMBUS_WORD_DATA (I2C_FUNC_SMBUS_READ_WORD_DATA | \
+ I2C_FUNC_SMBUS_WRITE_WORD_DATA)
+#define I2C_FUNC_SMBUS_BLOCK_DATA (I2C_FUNC_SMBUS_READ_BLOCK_DATA | \
+ I2C_FUNC_SMBUS_WRITE_BLOCK_DATA)
+#define I2C_FUNC_SMBUS_I2C_BLOCK (I2C_FUNC_SMBUS_READ_I2C_BLOCK | \
+ I2C_FUNC_SMBUS_WRITE_I2C_BLOCK)
+
+/* Old name, for compatibility */
+#define I2C_FUNC_SMBUS_HWPEC_CALC I2C_FUNC_SMBUS_PEC
+
+/*
+ * Data for SMBus Messages
+ */
+#define I2C_SMBUS_BLOCK_MAX 32 /* As specified in SMBus standard */
+#define I2C_SMBUS_I2C_BLOCK_MAX 32 /* Not specified but we use same structure */
+union i2c_smbus_data {
+ __u8 byte;
+ __u16 word;
+ __u8 block[I2C_SMBUS_BLOCK_MAX + 2]; /* block[0] is used for length */
+ /* and one more for PEC */
+};
+
+#define I2C_SMBUS_BLOCK_LARGE_MAX 240
+union i2c_smbus_large_data {
+ union i2c_smbus_data data;
+ __u8 block[I2C_SMBUS_BLOCK_LARGE_MAX + 2]; /* block[0] is used for length */
+ /* and one more for PEC */
+};
+
+/* smbus_access read or write markers */
+#define I2C_SMBUS_READ 1
+#define I2C_SMBUS_WRITE 0
+
+/* SMBus transaction types (size parameter in the above functions)
+ Note: these no longer correspond to the (arbitrary) PIIX4 internal codes! */
+#define I2C_SMBUS_QUICK 0
+#define I2C_SMBUS_BYTE 1
+#define I2C_SMBUS_BYTE_DATA 2
+#define I2C_SMBUS_WORD_DATA 3
+#define I2C_SMBUS_PROC_CALL 4
+#define I2C_SMBUS_BLOCK_DATA 5
+#define I2C_SMBUS_I2C_BLOCK_BROKEN 6
+#define I2C_SMBUS_BLOCK_PROC_CALL 7 /* SMBus 2.0 */
+#define I2C_SMBUS_I2C_BLOCK_DATA 8
+#define I2C_SMBUS_BLOCK_LARGE_DATA 9
+
+
+/* /dev/i2c-X ioctl commands. The ioctl's parameter is always an
+ * unsigned long, except for:
+ * - I2C_FUNCS, takes pointer to an unsigned long
+ * - I2C_RDWR, takes pointer to struct i2c_rdwr_ioctl_data
+ * - I2C_SMBUS, takes pointer to struct i2c_smbus_ioctl_data
+ */
+#define I2C_RETRIES 0x0701 /* number of times a device address should
+ be polled when not acknowledging */
+#define I2C_TIMEOUT 0x0702 /* set timeout in units of 10 ms */
+
+/* NOTE: Slave address is 7 or 10 bits, but 10-bit addresses
+ * are NOT supported! (due to code brokenness)
+ */
+#define I2C_SLAVE 0x0703 /* Use this slave address */
+#define I2C_SLAVE_FORCE 0x0706 /* Use this slave address, even if it
+ is already in use by a driver! */
+#define I2C_TENBIT 0x0704 /* 0 for 7 bit addrs, != 0 for 10 bit */
+
+#define I2C_FUNCS 0x0705 /* Get the adapter functionality mask */
+
+#define I2C_RDWR 0x0707 /* Combined R/W transfer (one STOP only) */
+
+#define I2C_PEC 0x0708 /* != 0 to use PEC with SMBus */
+#define I2C_SMBUS 0x0720 /* SMBus transfer */
+
+
+/* This is the structure as used in the I2C_SMBUS ioctl call */
+struct i2c_smbus_ioctl_data {
+ __u8 read_write;
+ __u8 command;
+ __u32 size;
+ union i2c_smbus_data *data;
+};
+
+/* This is the structure as used in the I2C_RDWR ioctl call */
+struct i2c_rdwr_ioctl_data {
+ struct i2c_msg *msgs; /* pointers to i2c_msgs */
+ __u32 nmsgs; /* number of i2c_msgs */
+};
+
+#define I2C_RDRW_IOCTL_MAX_MSGS 42
+
+
+static inline __s32 i2c_smbus_access(int file, char read_write, __u8 command,
+ int size, union i2c_smbus_data *data)
+{
+ struct i2c_smbus_ioctl_data args;
+
+ args.read_write = read_write;
+ args.command = command;
+ args.size = size;
+ args.data = data;
+ return ioctl(file,I2C_SMBUS,&args);
+}
+
+
+static inline __s32 i2c_smbus_write_quick(int file, __u8 value)
+{
+ return i2c_smbus_access(file,value,0,I2C_SMBUS_QUICK,NULL);
+}
+
+static inline __s32 i2c_smbus_read_byte(int file)
+{
+ union i2c_smbus_data data;
+ if (i2c_smbus_access(file,I2C_SMBUS_READ,0,I2C_SMBUS_BYTE,&data))
+ return -1;
+ else
+ return 0x0FF & data.byte;
+}
+
+static inline __s32 i2c_smbus_write_byte(int file, __u8 value)
+{
+ return i2c_smbus_access(file,I2C_SMBUS_WRITE,value,
+ I2C_SMBUS_BYTE,NULL);
+}
+
+static inline __s32 i2c_smbus_read_byte_data(int file, __u8 command)
+{
+ union i2c_smbus_data data;
+ if (i2c_smbus_access(file,I2C_SMBUS_READ,command,
+ I2C_SMBUS_BYTE_DATA,&data))
+ return -1;
+ else
+ return 0x0FF & data.byte;
+}
+
+static inline __s32 i2c_smbus_write_byte_data(int file, __u8 command,
+ __u8 value)
+{
+ union i2c_smbus_data data;
+ data.byte = value;
+ return i2c_smbus_access(file,I2C_SMBUS_WRITE,command,
+ I2C_SMBUS_BYTE_DATA, &data);
+}
+
+static inline __s32 i2c_smbus_read_word_data(int file, __u8 command)
+{
+ union i2c_smbus_data data;
+ if (i2c_smbus_access(file,I2C_SMBUS_READ,command,
+ I2C_SMBUS_WORD_DATA,&data))
+ return -1;
+ else
+ return 0x0FFFF & data.word;
+}
+
+static inline __s32 i2c_smbus_write_word_data(int file, __u8 command,
+ __u16 value)
+{
+ union i2c_smbus_data data;
+ data.word = value;
+ return i2c_smbus_access(file,I2C_SMBUS_WRITE,command,
+ I2C_SMBUS_WORD_DATA, &data);
+}
+
+static inline __s32 i2c_smbus_process_call(int file, __u8 command, __u16 value)
+{
+ union i2c_smbus_data data;
+ data.word = value;
+ if (i2c_smbus_access(file,I2C_SMBUS_WRITE,command,
+ I2C_SMBUS_PROC_CALL,&data))
+ return -1;
+ else
+ return 0x0FFFF & data.word;
+}
+
+
+/* Returns the number of read bytes */
+static inline __s32 i2c_smbus_read_block_data(int file, __u8 command,
+ __u8 *values)
+{
+ union i2c_smbus_data data;
+ if (i2c_smbus_access(file,I2C_SMBUS_READ,command,
+ I2C_SMBUS_BLOCK_DATA,&data))
+ return -1;
+ else {
+ memcpy(values, &data.block[1], _I2C_MIN(data.block[0], I2C_SMBUS_BLOCK_MAX));
+ return data.block[0];
+ }
+}
+
+static inline __s32 i2c_smbus_write_block_data(int file, __u8 command,
+ __u8 length, const __u8 *values)
+{
+ union i2c_smbus_data data;
+ if (length > 32)
+ length = 32;
+ memcpy(&data.block[1], values, length);
+ data.block[0] = length;
+ return i2c_smbus_access(file,I2C_SMBUS_WRITE,command,
+ I2C_SMBUS_BLOCK_DATA, &data);
+}
+
+static inline __s32 i2c_smbus_read_block_large_data(int file, __u8 command,
+ __u8 *values)
+{
+ union i2c_smbus_large_data data;
+ if (i2c_smbus_access(file, I2C_SMBUS_READ, command,
+ I2C_SMBUS_BLOCK_LARGE_DATA,
+ (union i2c_smbus_data *)&data)) {
+ return -1;
+ } else {
+ /* the first byte is the length which is not copied */
+ memcpy(values, &data.block[1], _I2C_MIN(data.block[0], I2C_SMBUS_BLOCK_LARGE_MAX));
+ return data.block[0];
+ }
+}
+
+static inline __s32 i2c_smbus_write_block_large_data(int file, __u8 command,
+ __u8 length,
+ const __u8 *values)
+{
+ union i2c_smbus_large_data data;
+ if (length > I2C_SMBUS_BLOCK_LARGE_MAX) {
+ length = I2C_SMBUS_BLOCK_LARGE_MAX;
+ }
+ data.block[0] = length;
+ memcpy(&data.block[1], values, length);
+ return i2c_smbus_access(file, I2C_SMBUS_WRITE, command,
+ I2C_SMBUS_BLOCK_LARGE_DATA,
+ (union i2c_smbus_data *)&data);
+}
+
+/* Returns the number of read bytes */
+/* Until kernel 2.6.22, the length is hardcoded to 32 bytes. If you
+ ask for less than 32 bytes, your code will only work with kernels
+ 2.6.23 and later. */
+static inline __s32 i2c_smbus_read_i2c_block_data(int file, __u8 command,
+ __u8 length, __u8 *values)
+{
+ union i2c_smbus_data data;
+
+ if (length > 32)
+ length = 32;
+ data.block[0] = length;
+ if (i2c_smbus_access(file,I2C_SMBUS_READ,command,
+ length == 32 ? I2C_SMBUS_I2C_BLOCK_BROKEN :
+ I2C_SMBUS_I2C_BLOCK_DATA,&data))
+ return -1;
+ else {
+ memcpy(values, &data.block[1], _I2C_MIN(data.block[0], I2C_SMBUS_BLOCK_MAX));
+ return data.block[0];
+ }
+}
+
+static inline __s32 i2c_smbus_write_i2c_block_data(int file, __u8 command,
+ __u8 length,
+ const __u8 *values)
+{
+ union i2c_smbus_data data;
+ if (length > 32)
+ length = 32;
+ memcpy(&data.block[1], values, length);
+ data.block[0] = length;
+ return i2c_smbus_access(file,I2C_SMBUS_WRITE,command,
+ I2C_SMBUS_I2C_BLOCK_BROKEN, &data);
+}
+
+/* Returns the number of read bytes */
+static inline __s32 i2c_smbus_block_process_call(int file, __u8 command,
+ __u8 length, __u8 *values)
+{
+ union i2c_smbus_data data;
+ if (length > 32)
+ length = 32;
+ memcpy(&data.block[1], values, length);
+ data.block[0] = length;
+ if (i2c_smbus_access(file,I2C_SMBUS_WRITE,command,
+ I2C_SMBUS_BLOCK_PROC_CALL,&data))
+ return -1;
+ else {
+ memcpy(values, &data.block[1], _I2C_MIN(data.block[0], I2C_SMBUS_BLOCK_MAX));
+ return data.block[0];
+ }
+}
+
+#undef _I2C_MIN
+
+#endif /* _LINUX_I2C_DEV_H */
diff --git a/meta-facebook/meta-wedge/recipes-wedge/fbutils/files/src/include/log.h b/meta-facebook/meta-wedge/recipes-wedge/fbutils/files/src/include/log.h
new file mode 100644
index 0000000..a69d69e
--- /dev/null
+++ b/meta-facebook/meta-wedge/recipes-wedge/fbutils/files/src/include/log.h
@@ -0,0 +1,59 @@
+/*
+ * Copyright 2014-present Facebook. All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#ifndef LOG_H
+#define LOG_H
+
+#include <stdio.h>
+#include <string.h>
+
+//#define DEBUG
+//#define VERBOSE
+
+#define _LOG(dst, fmt, ...) do { \
+ fprintf(dst, "%s:%d " fmt "\n", \
+ __FUNCTION__, __LINE__, ##__VA_ARGS__); \
+ fflush(dst); \
+} while(0)
+
+#define LOG_ERR(err, fmt, ...) do { \
+ char buf[128]; \
+ strerror_r(err, buf, sizeof(buf)); \
+ _LOG(stderr, "ERROR " fmt ": %s", ##__VA_ARGS__, buf); \
+} while(0)
+
+#define LOG_INFO(fmt, ...) do { \
+ _LOG(stdout, fmt, ##__VA_ARGS__); \
+} while(0)
+
+#ifdef DEBUG
+#define LOG_DBG(fmt, ...) do { \
+ _LOG(stdout, fmt, ##__VA_ARGS__); \
+} while(0)
+#else
+#define LOG_DBG(fmt, ...)
+#endif
+
+#ifdef VERBOSE
+#define LOG_VER(fmt, ...) do { \
+ _LOG(stdout, fmt, ##__VA_ARGS__); \
+} while(0)
+#else
+#define LOG_VER(fmt, ...)
+#endif
+
+#endif
diff --git a/meta-facebook/meta-wedge/recipes-wedge/fbutils/files/us_console.sh b/meta-facebook/meta-wedge/recipes-wedge/fbutils/files/us_console.sh
new file mode 100755
index 0000000..6f445ee
--- /dev/null
+++ b/meta-facebook/meta-wedge/recipes-wedge/fbutils/files/us_console.sh
@@ -0,0 +1,47 @@
+#!/bin/sh
+#
+# Copyright 2014-present Facebook. All Rights Reserved.
+#
+# This program file is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by the
+# Free Software Foundation; version 2 of the License.
+#
+# This program is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+# for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program in a file named COPYING; if not, write to the
+# Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor,
+# Boston, MA 02110-1301 USA
+#
+
+usage() {
+ echo "$0 <connect | disconnect>"
+}
+
+. /usr/local/fbpackages/utils/ast-functions
+
+if [ $# -ne 1 ]; then
+ usage
+ exit 1
+fi
+
+if [ "$1" == "connect" ]; then
+ VALUE=1
+elif [ "$1" == "disconnect" ]; then
+ VALUE=0
+else
+ usage
+ exit 1
+fi
+
+# GPIOE0 (32) controls if uS console connects to UART1 or not.
+# To enable GPIOE0, SCU80[16], SCU8C[12], and SCU70[22] must be 0
+devmem_clear_bit $(scu_addr 80) 16
+devmem_clear_bit $(scu_addr 8C) 12
+devmem_clear_bit $(scu_addr 70) 22
+
+gpio_set 32 $VALUE
diff --git a/meta-facebook/meta-wedge/recipes-wedge/fbutils/files/watch-fc.sh b/meta-facebook/meta-wedge/recipes-wedge/fbutils/files/watch-fc.sh
new file mode 100755
index 0000000..d04b7cd
--- /dev/null
+++ b/meta-facebook/meta-wedge/recipes-wedge/fbutils/files/watch-fc.sh
@@ -0,0 +1,34 @@
+#!/bin/bash
+#
+# Copyright 2014-present Facebook. All Rights Reserved.
+#
+# This program file is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by the
+# Free Software Foundation; version 2 of the License.
+#
+# This program is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+# for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program in a file named COPYING; if not, write to the
+# Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor,
+# Boston, MA 02110-1301 USA
+#
+
+. /usr/local/fbpackages/utils/ast-functions
+
+MAC1LINK=0 # GPIOA0
+FAB0_PRES=20 # GPIOC4
+FAB1_PRES=21 # GPIOC5
+while true; do
+ # fabN_pres: active low.
+ if [ $(gpio_get $FAB0_PRES) = 0 ]; then
+ gpio_set $MAC1LINK 0
+ elif [ $(gpio_get $FAB1_PRES) = 0 ]; then
+ gpio_set $MAC1LINK 1
+ fi
+ sleep 1
+done
diff --git a/meta-facebook/meta-wedge/recipes-wedge/fbutils/files/wedge_power.sh b/meta-facebook/meta-wedge/recipes-wedge/fbutils/files/wedge_power.sh
new file mode 100644
index 0000000..5ba5311
--- /dev/null
+++ b/meta-facebook/meta-wedge/recipes-wedge/fbutils/files/wedge_power.sh
@@ -0,0 +1,201 @@
+#!/bin/bash
+#
+# Copyright 2014-present Facebook. All Rights Reserved.
+#
+# This program file is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by the
+# Free Software Foundation; version 2 of the License.
+#
+# This program is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+# for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program in a file named COPYING; if not, write to the
+# Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor,
+# Boston, MA 02110-1301 USA
+#
+
+. /usr/local/fbpackages/utils/ast-functions
+
+PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/bin
+
+prog="$0"
+
+usage() {
+ echo "Usage: $prog <command> [command options]"
+ echo
+ echo "Commands:"
+ echo " status: Get the current microserver power status"
+ echo
+ echo " on: Power on microserver if not powered on already"
+ echo " options:"
+ echo " -f: Re-do power on sequence no matter if microserver has "
+ echo " been powered on or not."
+ echo
+ echo " off: Power off microserver ungracefully"
+ echo
+ echo " reset: Power reset microserver ungracefully"
+ echo " options:"
+ echo " -s: Power reset whole wedge system ungracefully"
+ echo
+}
+
+# Because the voltage leak from uS COM pins could cause uS to struck when transitting
+# from S5 to S0, we will need to explicitely pull down uS COM pins before powering off/reset
+# and restoring COM pins after
+
+pull_down_us_com() {
+ # set GPIOL6 and GPIOL7 low
+ devmem_clear_bit $(scu_addr 84) 22
+ devmem_clear_bit $(scu_addr 84) 23
+ gpio_set 94 0
+ gpio_set 95 0
+ # now, connect uart from BMC to the uS
+ gpio_set 32 1
+}
+
+restore_us_com() {
+ devmem_set_bit $(scu_addr 84) 22
+ devmem_set_bit $(scu_addr 84) 23
+ # if sol.sh is running, keep uart from uS connected with BMC
+ if ps | grep sol.sh > /dev/null 2>&1; then
+ gpio_set 32 1
+ else
+ gpio_set 32 0
+ fi
+}
+
+do_status() {
+ echo -n "Microserver power is "
+ if wedge_is_us_on; then
+ echo "on"
+ else
+ echo "off"
+ fi
+ return 0
+}
+
+do_on() {
+ local force opt
+ force=0
+ while getopts "f" opt; do
+ case $opt in
+ f)
+ force=1
+ ;;
+ *)
+ usage
+ exit -1
+ ;;
+
+ esac
+ done
+ echo -n "Power on microserver ..."
+ if [ $force -eq 0 ]; then
+ # need to check if uS is on or not
+ if wedge_is_us_on 10 "."; then
+ echo " Already on. Skip!"
+ return 1
+ fi
+ fi
+ # first make sure, GPIOD1 (25) is high
+ gpio_set 25 1
+ # then, put GPIOP7 (127) to low
+ gpio_set 127 0
+ # generate the power on pulse
+ gpio_set 25 0
+ sleep 1
+ gpio_set 25 1
+ sleep 1
+ restore_us_com
+ # Turn on the power LED (GPIOE5)
+ /usr/local/bin/power_led.sh on
+ echo " Done"
+ return 0
+}
+
+do_off() {
+ echo -n "Power off microserver ..."
+ pull_down_us_com
+ # first make sure, GPIOD1 (25) is high
+ gpio_set 25 1
+ # then, put GPIOP7 (127) to low
+ gpio_set 127 0
+ gpio_set 25 0
+ sleep 5
+ gpio_set 25 1
+ # Turn off the power LED (GPIOE5)
+ /usr/local/bin/power_led.sh off
+ echo " Done"
+ return 0
+}
+
+do_reset() {
+ local system opt
+ system=0
+ while getopts "s" opt; do
+ case $opt in
+ s)
+ system=1
+ ;;
+ *)
+ usage
+ exit -1
+ ;;
+ esac
+ done
+ if [ $system -eq 1 ]; then
+ echo -n "Power reset whole system ..."
+ rmmod adm1275
+ i2cset -y 12 0x10 0xd9 c
+ else
+ if ! wedge_is_us_on; then
+ echo "Power resetting microserver that is powered off has no effect."
+ echo "Use '$prog on' to power the microserver on"
+ return -1
+ fi
+ echo -n "Power reset microserver ..."
+ pull_down_us_com
+ # then, put GPIOP7 (127) to low
+ gpio_set 127 0
+ gpio_set 17 0
+ sleep 1
+ gpio_set 17 1
+ sleep 1
+ restore_us_com
+ fi
+ echo " Done"
+ return 0
+}
+
+if [ $# -lt 1 ]; then
+ usage
+ exit -1
+fi
+
+command="$1"
+shift
+
+case "$command" in
+ status)
+ do_status $@
+ ;;
+ on)
+ do_on $@
+ ;;
+ off)
+ do_off $@
+ ;;
+ reset)
+ do_reset $@
+ ;;
+ *)
+ usage
+ exit -1
+ ;;
+esac
+
+exit $?
diff --git a/meta-facebook/meta-wedge/recipes-wedge/fbutils/files/wedge_us_mac.sh b/meta-facebook/meta-wedge/recipes-wedge/fbutils/files/wedge_us_mac.sh
new file mode 100644
index 0000000..34b8e59
--- /dev/null
+++ b/meta-facebook/meta-wedge/recipes-wedge/fbutils/files/wedge_us_mac.sh
@@ -0,0 +1,29 @@
+#!/bin/bash
+#
+# Copyright 2014-present Facebook. All Rights Reserved.
+#
+# This program file is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by the
+# Free Software Foundation; version 2 of the License.
+#
+# This program is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+# for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program in a file named COPYING; if not, write to the
+# Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor,
+# Boston, MA 02110-1301 USA
+#
+
+PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/bin
+
+mac=$(i2cdump -y 0x0 0x49 s 0xd4 | grep '^00: d4'| awk '{ print $3":"$4":"$5":"$6":"$7":"$8 }') 2>/dev/null
+
+if [ -n "$mac" ]; then
+ echo $mac
+else
+ echo "Cannot find out the microserver MAC" 1>&2
+fi
diff --git a/meta-facebook/meta-wedge/recipes-wedge/ipmid/files/Makefile b/meta-facebook/meta-wedge/recipes-wedge/ipmid/files/Makefile
new file mode 100644
index 0000000..8282964
--- /dev/null
+++ b/meta-facebook/meta-wedge/recipes-wedge/ipmid/files/Makefile
@@ -0,0 +1,13 @@
+# Copyright 2014-present Facebook. All Rights Reserved.
+all: ipmid
+
+ipmid: ipmid.c \
+ platform/timestamp.c platform/sel.c platform/sdr.c \
+ platform/wedge/sensor.c \
+ platform/wedge/fruid.c
+ $(CC) -pthread -lwedge_eeprom -std=c99 -o $@ $^ $(LDFLAGS)
+
+.PHONY: clean
+
+clean:
+ rm -rf *.o platform/*.o platform/wedge/*.o ipmid
diff --git a/meta-facebook/meta-wedge/recipes-wedge/ipmid/files/ipmid.c b/meta-facebook/meta-wedge/recipes-wedge/ipmid/files/ipmid.c
new file mode 100644
index 0000000..4771e15
--- /dev/null
+++ b/meta-facebook/meta-wedge/recipes-wedge/ipmid/files/ipmid.c
@@ -0,0 +1,1490 @@
+/*
+ *
+ * Copyright 2014-present Facebook. All Rights Reserved.
+ *
+ * This file contains code to support IPMI2.0 Specificaton available @
+ * http://www.intel.com/content/www/us/en/servers/ipmi/ipmi-specifications.html
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include "platform/sdr.h"
+#include "platform/sel.h"
+#include "platform/fruid.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <errno.h>
+#include <syslog.h>
+#include <string.h>
+#include <pthread.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+
+#define SOCK_PATH "/tmp/ipmi_socket"
+
+#define MAX_NUM_DIMMS 4
+#define IPMI_SEL_VERSION 0x51
+#define IPMI_SDR_VERSION 0x51
+
+#define SIZE_AUTH_ENABLES 5
+#define SIZE_IP_ADDR 4
+#define SIZE_MAC_ADDR 6
+#define SIZE_NET_MASK 4
+#define SIZE_IP_HDR 3
+#define SIZE_RMCP_PORT 2
+#define SIZE_COMMUNITY_STR 18
+#define SIZE_DEST_TYPE 4
+#define SIZE_DEST_ADDR 18
+#define SIZE_TIME_STAMP 4
+
+#define SIZE_PROC_FREQ 2
+#define SIZE_DIMM_SPEED 2
+#define SIZE_DIMM_SIZE 2
+
+#define SIZE_SYSFW_VER 17
+#define SIZE_SYS_NAME 17
+#define SIZE_OS_NAME 17
+#define SIZE_OS_VER 17
+#define SIZE_BMC_URL 17
+#define SIZE_OS_HV_URL 17
+
+#define SIZE_SEL_REC 16
+#define SIZE_IPMI_RES_HDR 3
+
+#define MAX_IPMI_MSG_SIZE 100
+
+// IPMI request Structure (IPMI/Section 9.2)
+typedef struct
+{
+ unsigned char netfn_lun;
+ unsigned char cmd;
+ unsigned char data[];
+} ipmi_req_t;
+
+// IPMI response Structure (IPMI/Section 9.3)
+typedef struct
+{
+ unsigned char netfn_lun;
+ unsigned char cmd;
+ unsigned char cc;
+ unsigned char data[];
+} ipmi_res_t;
+
+// LAN Configuration Structure (IPMI/Table 23.4)
+typedef struct
+{
+ unsigned char set_in_prog;
+ unsigned char auth_support;
+ unsigned char auth_enables[SIZE_AUTH_ENABLES];
+ unsigned char ip_addr[SIZE_IP_ADDR];
+ unsigned char ip_src;
+ unsigned char mac_addr[SIZE_MAC_ADDR];
+ unsigned char net_mask[SIZE_NET_MASK];
+ unsigned char ip_hdr[SIZE_IP_HDR];
+ unsigned char pri_rmcp_port[SIZE_RMCP_PORT];
+ unsigned char sec_rmcp_port[SIZE_RMCP_PORT];
+ unsigned char arp_ctrl;
+ unsigned char garp_interval;
+ unsigned char df_gw_ip_addr[SIZE_IP_ADDR];
+ unsigned char df_gw_mac_addr[SIZE_MAC_ADDR];
+ unsigned char back_gw_ip_addr[SIZE_IP_ADDR];
+ unsigned char back_gw_mac_addr[SIZE_MAC_ADDR];
+ unsigned char community_str[SIZE_COMMUNITY_STR];
+ unsigned char no_of_dest;
+ unsigned char dest_type[SIZE_DEST_TYPE];
+ unsigned char dest_addr[SIZE_DEST_ADDR];
+} lan_config_t;
+
+// Structure to store Processor Information
+typedef struct
+{
+ unsigned char type;
+ unsigned char freq[SIZE_PROC_FREQ];
+} proc_info_t;
+
+// Structure to store DIMM Information
+typedef struct
+{
+ unsigned char type;
+ unsigned char speed[SIZE_DIMM_SPEED];
+ unsigned char size[SIZE_DIMM_SIZE];
+} dimm_info_t;
+
+// Structure for System Info Params (IPMI/Section 22.14a)
+typedef struct
+{
+ unsigned char set_in_prog;
+ unsigned char sysfw_ver[SIZE_SYSFW_VER];
+ unsigned char sys_name[SIZE_SYS_NAME];
+ unsigned char pri_os_name[SIZE_OS_NAME];
+ unsigned char present_os_name[SIZE_OS_NAME];
+ unsigned char present_os_ver[SIZE_OS_VER];
+ unsigned char bmc_url[SIZE_BMC_URL];
+ unsigned char os_hv_url[SIZE_OS_HV_URL];
+} sys_info_param_t;
+
+// Network Function Codes (IPMI/Section 5.1)
+enum
+{
+ NETFN_CHASSIS_REQ = 0x00,
+ NETFN_CHASSIS_RES,
+ NETFN_BRIDGE_REQ,
+ NETFN_BRIDGE_RES,
+ NETFN_SENSOR_REQ,
+ NETFN_SENSOR_RES,
+ NETFN_APP_REQ,
+ NETFN_APP_RES,
+ NETFN_FIRMWARE_REQ,
+ NETFN_FIRMWARE_RES,
+ NETFN_STORAGE_REQ,
+ NETFN_STORAGE_RES,
+ NETFN_TRANSPORT_REQ,
+ NETFN_TRANSPORT_RES,
+ NETFN_OEM_REQ = 0x30,
+ NETFN_OEM_RES = 0x31,
+};
+
+// Chassis Command Codes (IPMI/Table H-1)
+enum
+{
+ CMD_CHASSIS_GET_STATUS = 0x01,
+ CMD_CHASSIS_GET_BOOT_OPTIONS = 0x09,
+};
+
+// Application Command Codes (IPMI/Table H-1)
+enum
+{
+ CMD_APP_GET_DEVICE_ID = 0x01,
+ CMD_APP_GET_SELFTEST_RESULTS = 0x04,
+ CMD_APP_GET_DEVICE_GUID = 0x08,
+ CMD_APP_RESET_WDT = 0x22,
+ CMD_APP_SET_WDT = 0x24,
+ CMD_APP_GET_WDT = 0x25,
+ CMD_APP_GET_GLOBAL_ENABLES = 0x2F,
+ CMD_APP_GET_SYSTEM_GUID = 0x37,
+ CMD_APP_SET_SYS_INFO_PARAMS = 0x58,
+ CMD_APP_GET_SYS_INFO_PARAMS = 0x59,
+};
+
+// Storage Command Codes (IPMI/Table H-1)
+enum
+{
+ CMD_STORAGE_GET_FRUID_INFO = 0x10,
+ CMD_STORAGE_READ_FRUID_DATA = 0x11,
+ CMD_STORAGE_GET_SDR_INFO = 0x20,
+ CMD_STORAGE_RSV_SDR = 0x22,
+ CMD_STORAGE_GET_SDR = 0x23,
+ CMD_STORAGE_GET_SEL_INFO = 0x40,
+ CMD_STORAGE_RSV_SEL = 0x42,
+ CMD_STORAGE_GET_SEL = 0x43,
+ CMD_STORAGE_ADD_SEL = 0x44,
+ CMD_STORAGE_CLR_SEL = 0x47,
+ CMD_STORAGE_GET_SEL_TIME = 0x48,
+ CMD_STORAGE_GET_SEL_UTC = 0x5C,
+};
+
+// Transport Command Codes (IPMI/Table H-1)
+enum
+{
+ CMD_TRANSPORT_SET_LAN_CONFIG = 0x01,
+ CMD_TRANSPORT_GET_LAN_CONFIG = 0x02,
+};
+
+// OEM Command Codes (Quanta/FB defined commands)
+enum
+{
+ CMD_OEM_SET_PROC_INFO = 0x1A,
+ CMD_OEM_SET_DIMM_INFO = 0x1C,
+ CMD_OEM_SET_POST_START = 0x73,
+ CMD_OEM_SET_POST_END = 0x74,
+};
+
+// IPMI command Completion Codes (IPMI/Section 5.2)
+enum
+{
+ CC_SUCCESS = 0x00,
+ CC_INVALID_PARAM = 0x80,
+ CC_SEL_ERASE_PROG = 0x81,
+ CC_INVALID_CMD = 0xC1,
+ CC_PARAM_OUT_OF_RANGE = 0xC9,
+ CC_UNSPECIFIED_ERROR = 0xFF,
+};
+
+// LAN Configuration parameters (IPMI/Table 23-4)
+enum
+{
+ LAN_PARAM_SET_IN_PROG,
+ LAN_PARAM_AUTH_SUPPORT,
+ LAN_PARAM_AUTH_ENABLES,
+ LAN_PARAM_IP_ADDR,
+ LAN_PARAM_IP_SRC,
+ LAN_PARAM_MAC_ADDR,
+ LAN_PARAM_NET_MASK,
+ LAN_PARAM_IP_HDR,
+ LAN_PARAM_PRI_RMCP_PORT,
+ LAN_PARAM_SEC_RMCP_PORT,
+ LAN_PARAM_ARP_CTRL,
+ LAN_PARAM_GARP_INTERVAL,
+ LAN_PARAM_DF_GW_IP_ADDR,
+ LAN_PARAM_DF_GW_MAC_ADDR,
+ LAN_PARAM_BACK_GW_IP_ADDR,
+ LAN_PARAM_BACK_GW_MAC_ADDR,
+ LAN_PARAM_COMMUNITY_STR,
+ LAN_PARAM_NO_OF_DEST,
+ LAN_PARAM_DEST_TYPE,
+ LAN_PARAM_DEST_ADDR,
+};
+
+// Boot Option Parameters (IPMI/Table 28-14)
+enum
+{
+ PARAM_SET_IN_PROG = 0x00,
+ PARAM_SVC_PART_SELECT,
+ PARAM_SVC_PART_SCAN,
+ PARAM_BOOT_FLAG_CLR,
+ PARAM_BOOT_INFO_ACK,
+ PARAM_BOOT_FLAGS,
+ PARAM_BOOT_INIT_INFO,
+};
+
+//System Info Parameters (IPMI/Table 22-16c)
+enum
+{
+ SYS_INFO_PARAM_SET_IN_PROG,
+ SYS_INFO_PARAM_SYSFW_VER,
+ SYS_INFO_PARAM_SYS_NAME,
+ SYS_INFO_PARAM_PRI_OS_NAME,
+ SYS_INFO_PARAM_PRESENT_OS_NAME,
+ SYS_INFO_PARAM_PRESENT_OS_VER,
+ SYS_INFO_PARAM_BMC_URL,
+ SYS_INFO_PARAM_OS_HV_URL,
+};
+
+// TODO: Once data storage is finalized, the following structure needs
+// to be retrieved/updated from persistant backend storage
+static lan_config_t g_lan_config = { 0 };
+static proc_info_t g_proc_info = { 0 };
+static dimm_info_t g_dimm_info[MAX_NUM_DIMMS] = { 0 };
+
+// TODO: Need to store this info after identifying proper storage
+static sys_info_param_t g_sys_info_params;
+
+// TODO: Based on performance testing results, might need fine grained locks
+// Since the global data is specific to a NetFunction, adding locs at NetFn level
+static pthread_mutex_t m_chassis;
+static pthread_mutex_t m_app;
+static pthread_mutex_t m_storage;
+static pthread_mutex_t m_transport;
+static pthread_mutex_t m_oem;
+
+/*
+ * Function(s) to handle IPMI messages with NetFn: Chassis
+ */
+// Get Chassis Status (IPMI/Section 28.2)
+static void
+chassis_get_status (unsigned char *response, unsigned char *res_len)
+{
+ ipmi_res_t *res = (ipmi_res_t *) response;
+ unsigned char *data = &res->data[0];
+
+ res->cc = CC_SUCCESS;
+
+ // TODO: Need to obtain current power state and last power event
+ // from platform and return
+ *data++ = 0x01; // Current Power State
+ *data++ = 0x00; // Last Power Event
+ *data++ = 0x40; // Misc. Chassis Status
+ *data++ = 0x00; // Front Panel Button Disable
+
+ res_len = data - &res->data[0];
+}
+
+// Get System Boot Options (IPMI/Section 28.12)
+static void
+chassis_get_boot_options (unsigned char *request, unsigned char *response,
+ unsigned char *res_len)
+{
+ ipmi_req_t *req = (ipmi_req_t *) request;
+ ipmi_res_t *res= (ipmi_res_t *) response;
+ unsigned char *data = &res->data[0];
+ unsigned char param = req->data[0];
+
+ // Fill response with default values
+ res->cc = CC_SUCCESS;
+ *data++ = 0x01; // Parameter Version
+ *data++ = req->data[0]; // Parameter
+
+ // TODO: Need to store user settings and return
+ switch (param)
+ {
+ case PARAM_SET_IN_PROG:
+ *data++ = 0x00; // Set In Progress
+ break;
+ case PARAM_SVC_PART_SELECT:
+ *data++ = 0x00; // Service Partition Selector
+ break;
+ case PARAM_SVC_PART_SCAN:
+ *data++ = 0x00; // Service Partition Scan
+ break;
+ case PARAM_BOOT_FLAG_CLR:
+ *data++ = 0x00; // BMC Boot Flag Valid Bit Clear
+ break;
+ case PARAM_BOOT_INFO_ACK:
+ *data++ = 0x00; // Write Mask
+ *data++ = 0x00; // Boot Initiator Ack Data
+ break;
+ case PARAM_BOOT_FLAGS:
+ *data++ = 0x00; // Boot Flags
+ *data++ = 0x00; // Boot Device Selector
+ *data++ = 0x00; // Firmwaer Verbosity
+ *data++ = 0x00; // BIOS Override
+ *data++ = 0x00; // Device Instance Selector
+ break;
+ case PARAM_BOOT_INIT_INFO:
+ *data++ = 0x00; // Chanel Number
+ *data++ = 0x00; // Session ID (4 bytes)
+ *data++ = 0x00;
+ *data++ = 0x00;
+ *data++ = 0x00;
+ *data++ = 0x00; // Boot Info Timestamp (4 bytes)
+ *data++ = 0x00;
+ *data++ = 0x00;
+ *data++ = 0x00;
+ break;
+ deault:
+ res->cc = CC_PARAM_OUT_OF_RANGE;
+ break;
+ }
+
+ if (res->cc == CC_SUCCESS) {
+ *res_len = data - &res->data[0];
+ }
+}
+
+// Handle Chassis Commands (IPMI/Section 28)
+static void
+ipmi_handle_chassis (unsigned char *request, unsigned char req_len,
+ unsigned char *response, unsigned char *res_len)
+{
+ ipmi_req_t *req = (ipmi_req_t *) request;
+ ipmi_res_t *res = (ipmi_res_t *) response;
+ unsigned char cmd = req->cmd;
+
+ pthread_mutex_lock(&m_chassis);
+ switch (cmd)
+ {
+ case CMD_CHASSIS_GET_STATUS:
+ chassis_get_status (response, res_len);
+ break;
+ case CMD_CHASSIS_GET_BOOT_OPTIONS:
+ chassis_get_boot_options (request, response, res_len);
+ break;
+ default:
+ res->cc = CC_INVALID_CMD;
+ break;
+ }
+ pthread_mutex_unlock(&m_chassis);
+}
+
+/*
+ * Function(s) to handle IPMI messages with NetFn: Application
+ */
+// Get Device ID (IPMI/Section 20.1)
+static void
+app_get_device_id (unsigned char *response, unsigned char *res_len)
+{
+
+ ipmi_res_t *res = (ipmi_res_t *) response;
+ unsigned char *data = &res->data[0];
+
+ res->cc = CC_SUCCESS;
+
+ //TODO: Following data needs to be updated based on platform
+ *data++ = 0x20; // Device ID
+ *data++ = 0x81; // Device Revision
+ *data++ = 0x00; // Firmware Revision Major
+ *data++ = 0x09; // Firmware Revision Minor
+ *data++ = 0x02; // IPMI Version
+ *data++ = 0xBF; // Additional Device Support
+ *data++ = 0x15; // Manufacturer ID1
+ *data++ = 0xA0; // Manufacturer ID2
+ *data++ = 0x00; // Manufacturer ID3
+ *data++ = 0x46; // Product ID1
+ *data++ = 0x31; // Product ID2
+ *data++ = 0x00; // Aux. Firmware Version1
+ *data++ = 0x00; // Aux. Firmware Version2
+ *data++ = 0x00; // Aux. Firmware Version3
+ *data++ = 0x00; // Aux. Firmware Version4
+
+ *res_len = data - &res->data[0];
+}
+
+// Get Self Test Results (IPMI/Section 20.4)
+static void
+app_get_selftest_results (unsigned char *response, unsigned char *res_len)
+{
+
+ ipmi_res_t *res = (ipmi_res_t *) response;
+ unsigned char *data = &res->data[0];
+
+ res->cc = CC_SUCCESS;
+
+ //TODO: Following data needs to be updated based on self-test results
+ *data++ = 0x55; // Self-Test result
+ *data++ = 0x00; // Extra error info in case of failure
+
+ *res_len = data - &res->data[0];
+}
+
+// Get Device GUID (IPMI/Section 20.8)
+static void
+app_get_device_guid (unsigned char *response, unsigned char *res_len)
+{
+ ipmi_res_t *res = (ipmi_res_t *) response;
+ unsigned char *data = &res->data[0];
+
+ res->cc = 0x00;
+
+ // TODO: Following data is Globaly Unique ID i.e. MAC Address..
+ *data++ = 0x0;
+ *data++ = 0x1;
+ *data++ = 0x2;
+ *data++ = 0x3;
+ *data++ = 0x4;
+ *data++ = 0x5;
+ *data++ = 0x6;
+ *data++ = 0x7;
+ *data++ = 0x8;
+ *data++ = 0x9;
+ *data++ = 0xa;
+ *data++ = 0xb;
+ *data++ = 0xc;
+ *data++ = 0xd;
+ *data++ = 0xe;
+ *data++ = 0xf;
+
+ *res_len = data - &res->data[0];
+}
+
+// Get BMC Global Enables (IPMI/Section 22.2)
+static void
+app_get_global_enables (unsigned char *response, unsigned char *res_len)
+{
+
+ ipmi_res_t *res = (ipmi_res_t *) response;
+ unsigned char *data = &res->data[0];
+
+ res->cc = CC_SUCCESS;
+
+ *data++ = 0x09; // Global Enable
+
+ *res_len = data - &res->data[0];
+}
+
+// Set System Info Params (IPMI/Section 22.14a)
+static void
+app_set_sys_info_params (unsigned char *request, unsigned char *response,
+ unsigned char *res_len)
+{
+
+ ipmi_req_t *req = (ipmi_req_t *) request;
+ ipmi_res_t *res = (ipmi_res_t *) response;
+ unsigned char param = req->data[0];
+
+ res->cc = CC_SUCCESS;
+
+ switch (param)
+ {
+ case SYS_INFO_PARAM_SET_IN_PROG:
+ g_sys_info_params.set_in_prog = req->data[1];
+ break;
+ case SYS_INFO_PARAM_SYSFW_VER:
+ memcpy(g_sys_info_params.sysfw_ver, &req->data[1], SIZE_SYSFW_VER);
+ break;
+ case SYS_INFO_PARAM_SYS_NAME:
+ memcpy(g_sys_info_params.sys_name, &req->data[1], SIZE_SYS_NAME);
+ break;
+ case SYS_INFO_PARAM_PRI_OS_NAME:
+ memcpy(g_sys_info_params.pri_os_name, &req->data[1], SIZE_OS_NAME);
+ break;
+ case SYS_INFO_PARAM_PRESENT_OS_NAME:
+ memcpy(g_sys_info_params.present_os_name, &req->data[1], SIZE_OS_NAME);
+ break;
+ case SYS_INFO_PARAM_PRESENT_OS_VER:
+ memcpy(g_sys_info_params.present_os_ver, &req->data[1], SIZE_OS_VER);
+ break;
+ case SYS_INFO_PARAM_BMC_URL:
+ memcpy(g_sys_info_params.bmc_url, &req->data[1], SIZE_BMC_URL);
+ break;
+ case SYS_INFO_PARAM_OS_HV_URL:
+ memcpy(g_sys_info_params.os_hv_url, &req->data[1], SIZE_OS_HV_URL);
+ break;
+ default:
+ res->cc = CC_INVALID_PARAM;
+ break;
+ }
+
+ return;
+}
+
+// Get System Info Params (IPMI/Section 22.14b)
+static void
+app_get_sys_info_params (unsigned char *request, unsigned char *response,
+ unsigned char *res_len)
+{
+
+ ipmi_req_t *req = (ipmi_req_t *) request;
+ ipmi_res_t *res = (ipmi_res_t *) response;
+ unsigned char *data = &res->data[0];
+ unsigned char param = req->data[1];
+
+ // Fill default return values
+ res->cc = CC_SUCCESS;
+ *data++ = 1; // Parameter revision
+
+ switch (param)
+ {
+ case SYS_INFO_PARAM_SET_IN_PROG:
+ *data++ = g_sys_info_params.set_in_prog;
+ break;
+ case SYS_INFO_PARAM_SYSFW_VER:
+ memcpy(data, g_sys_info_params.sysfw_ver, SIZE_SYSFW_VER);
+ data += SIZE_SYSFW_VER;
+ break;
+ case SYS_INFO_PARAM_SYS_NAME:
+ memcpy(data, g_sys_info_params.sys_name, SIZE_SYS_NAME);
+ data += SIZE_SYS_NAME;
+ break;
+ case SYS_INFO_PARAM_PRI_OS_NAME:
+ memcpy(data, g_sys_info_params.pri_os_name, SIZE_OS_NAME);
+ data += SIZE_OS_NAME;
+ break;
+ case SYS_INFO_PARAM_PRESENT_OS_NAME:
+ memcpy(data, g_sys_info_params.present_os_name, SIZE_OS_NAME);
+ data += SIZE_OS_NAME;
+ break;
+ case SYS_INFO_PARAM_PRESENT_OS_VER:
+ memcpy(data, g_sys_info_params.present_os_ver, SIZE_OS_VER);
+ data += SIZE_OS_VER;
+ break;
+ case SYS_INFO_PARAM_BMC_URL:
+ memcpy(data, g_sys_info_params.bmc_url, SIZE_BMC_URL);
+ data += SIZE_BMC_URL;
+ break;
+ case SYS_INFO_PARAM_OS_HV_URL:
+ memcpy(data, g_sys_info_params.os_hv_url, SIZE_OS_HV_URL);
+ data += SIZE_OS_HV_URL;
+ break;
+ default:
+ res->cc = CC_INVALID_PARAM;
+ break;
+ }
+
+ if (res->cc == CC_SUCCESS) {
+ *res_len = data - &res->data[0];
+ }
+
+ return;
+}
+
+// Handle Appliction Commands (IPMI/Section 20)
+static void
+ipmi_handle_app (unsigned char *request, unsigned char req_len,
+ unsigned char *response, unsigned char *res_len)
+{
+ ipmi_req_t *req = (ipmi_req_t *) request;
+ ipmi_res_t *res = (ipmi_res_t *) response;
+ unsigned char cmd = req->cmd;
+
+ pthread_mutex_lock(&m_app);
+ switch (cmd)
+ {
+ case CMD_APP_GET_DEVICE_ID:
+ app_get_device_id (response, res_len);
+ break;
+ case CMD_APP_GET_SELFTEST_RESULTS:
+ app_get_selftest_results (response, res_len);
+ break;
+ case CMD_APP_GET_DEVICE_GUID:
+ case CMD_APP_GET_SYSTEM_GUID:
+ // Get Device GUID and Get System GUID returns same data
+ // from IPMI stack. FYI, Get System GUID will have to be
+ // sent with in an IPMI session that includes session info
+ app_get_device_guid (response, res_len);
+ break;
+ case CMD_APP_GET_GLOBAL_ENABLES:
+ app_get_global_enables (response, res_len);
+ break;
+ case CMD_APP_SET_SYS_INFO_PARAMS:
+ app_set_sys_info_params (request, response, res_len);
+ break;
+ case CMD_APP_GET_SYS_INFO_PARAMS:
+ app_get_sys_info_params (request, response, res_len);
+ break;
+ default:
+ res->cc = CC_INVALID_CMD;
+ break;
+ }
+ pthread_mutex_unlock(&m_app);
+}
+
+/*
+ * Function(s) to handle IPMI messages with NetFn: Storage
+ */
+
+static void
+storage_get_fruid_info(unsigned char *response, unsigned char *res_len)
+{
+ ipmi_res_t *res = (ipmi_res_t *) response;
+ unsigned char *data = &res->data[0];
+ int size = plat_fruid_size();
+
+ res->cc = CC_SUCCESS;
+
+ *data++ = size & 0xFF; // FRUID size LSB
+ *data++ = (size >> 8) & 0xFF; // FRUID size MSB
+ *data++ = 0x00; // Device accessed by bytes
+
+ *res_len = data - &res->data[0];
+
+ return;
+}
+
+static void
+storage_get_fruid_data(unsigned char *request, unsigned char *response,
+ unsigned char *res_len)
+{
+ ipmi_req_t *req = (ipmi_req_t *) request;
+ ipmi_res_t *res = (ipmi_res_t *) response;
+ unsigned char *data = &res->data[0];
+
+ int offset = req->data[1] + (req->data[2] << 8);
+ int count = req->data[3];
+
+ int ret = plat_fruid_data(offset, count, &(res->data[1]));
+ if (ret) {
+ res->cc = CC_UNSPECIFIED_ERROR;
+ } else {
+ res->cc = CC_SUCCESS;
+ *data++ = count;
+ data += count;
+ }
+
+ if (res->cc == CC_SUCCESS) {
+ *res_len = data - &res->data[0];
+ }
+ return;
+}
+
+static void
+storage_get_sdr_info (unsigned char *response, unsigned char *res_len)
+{
+ ipmi_res_t *res = (ipmi_res_t *) response;
+ unsigned char *data = &res->data[0];
+ int num_entries; // number of sdr records
+ int free_space; // free space in SDR device in bytes
+ time_stamp_t ts_recent_add; // Recent Addition Timestamp
+ time_stamp_t ts_recent_erase; // Recent Erasure Timestamp
+
+ // Use platform APIs to get SDR information
+ num_entries = plat_sdr_num_entries ();
+ free_space = plat_sdr_free_space ();
+ plat_sdr_ts_recent_add (&ts_recent_add);
+ plat_sdr_ts_recent_erase (&ts_recent_erase);
+
+ res->cc = CC_SUCCESS;
+
+ *data++ = IPMI_SDR_VERSION; // SDR version
+ *data++ = num_entries & 0xFF; // number of sdr entries
+ *data++ = (num_entries >> 8) & 0xFF;
+ *data++ = free_space & 0xFF; // Free SDR Space
+ *data++ = (free_space >> 8) & 0xFF;
+
+ memcpy(data, ts_recent_add.ts, SIZE_TIME_STAMP);
+ data += SIZE_TIME_STAMP;
+
+ memcpy(data, ts_recent_erase.ts, SIZE_TIME_STAMP);
+ data += SIZE_TIME_STAMP;
+
+ *data++ = 0x02; // Operations supported
+
+ *res_len = data - &res->data[0];
+
+ return;
+}
+
+static void
+storage_rsv_sdr (unsigned char *response, unsigned char *res_len)
+{
+ ipmi_res_t *res = (ipmi_res_t *) response;
+ unsigned char *data = &res->data[0];
+ int rsv_id; // SDR reservation ID
+
+ // Use platform APIs to get a SDR reservation ID
+ rsv_id = plat_sdr_rsv_id ();
+ if (rsv_id < 0)
+ {
+ res->cc = CC_UNSPECIFIED_ERROR;
+ return;
+ }
+
+ res->cc = CC_SUCCESS;
+ *data++ = rsv_id & 0xFF; // Reservation ID
+ *data++ = (rsv_id >> 8) & 0XFF;
+
+ *res_len = data - &res->data[0];
+
+ return;
+}
+
+static void
+storage_get_sdr (unsigned char *request, unsigned char *response,
+ unsigned char *res_len)
+{
+ ipmi_req_t *req = (ipmi_req_t *) request;
+ ipmi_res_t *res = (ipmi_res_t *) response;
+ unsigned char *data = &res->data[0];
+
+ int read_rec_id; //record ID to be read
+ int next_rec_id; //record ID for the next entry
+ int rsv_id; // Reservation ID for the request
+ int rec_offset; // Read offset into the record
+ int rec_bytes; // Number of bytes to be read
+ sdr_rec_t entry; // SDR record entry
+ int ret;
+
+ rsv_id = (req->data[1] >> 8) | req->data[0];
+ read_rec_id = (req->data[3] >> 8) | req->data[2];
+ rec_offset = req->data[4];
+ rec_bytes = req->data[5];
+
+ // Use platform API to read the record Id and get next ID
+ ret = plat_sdr_get_entry (rsv_id, read_rec_id, &entry, &next_rec_id);
+ if (ret)
+ {
+ res->cc = CC_UNSPECIFIED_ERROR;
+ return;
+ }
+
+ res->cc = CC_SUCCESS;
+ *data++ = next_rec_id & 0xFF; // next record ID
+ *data++ = (next_rec_id >> 8) & 0xFF;
+
+ memcpy (data, &entry.rec[rec_offset], rec_bytes);
+ data += rec_bytes;
+
+ *res_len = data - &res->data[0];
+
+ return;
+}
+
+static void
+storage_get_sel_info (unsigned char *response, unsigned char *res_len)
+{
+ ipmi_res_t *res = (ipmi_res_t *) response;
+ unsigned char *data = &res->data[0];
+ int num_entries; // number of log entries
+ int free_space; // free space in SEL device in bytes
+ time_stamp_t ts_recent_add; // Recent Addition Timestamp
+ time_stamp_t ts_recent_erase; // Recent Erasure Timestamp
+
+ // Use platform APIs to get SEL information
+ num_entries = plat_sel_num_entries ();
+ free_space = plat_sel_free_space ();
+ plat_sel_ts_recent_add (&ts_recent_add);
+ plat_sel_ts_recent_erase (&ts_recent_erase);
+
+ res->cc = CC_SUCCESS;
+
+ *data++ = IPMI_SEL_VERSION; // SEL version
+ *data++ = num_entries & 0xFF; // number of log entries
+ *data++ = (num_entries >> 8) & 0xFF;
+ *data++ = free_space & 0xFF; // Free SEL Space
+ *data++ = (free_space >> 8) & 0xFF;
+
+ memcpy(data, ts_recent_add.ts, SIZE_TIME_STAMP);
+ data += SIZE_TIME_STAMP;
+
+ memcpy(data, ts_recent_erase.ts, SIZE_TIME_STAMP);
+ data += SIZE_TIME_STAMP;
+
+ *data++ = 0x02; // Operations supported
+
+ *res_len = data - &res->data[0];
+
+ return;
+}
+
+static void
+storage_rsv_sel (unsigned char *response, unsigned char *res_len)
+{
+ ipmi_res_t *res = (ipmi_res_t *) response;
+ unsigned char *data = &res->data[0];
+ int rsv_id; // SEL reservation ID
+
+ // Use platform APIs to get a SEL reservation ID
+ rsv_id = plat_sel_rsv_id ();
+ if (rsv_id < 0)
+ {
+ res->cc = CC_SEL_ERASE_PROG;
+ return;
+ }
+
+ res->cc = CC_SUCCESS;
+ *data++ = rsv_id & 0xFF; // Reservation ID
+ *data++ = (rsv_id >> 8) & 0XFF;
+
+ *res_len = data - &res->data[0];
+
+ return;
+}
+
+static void
+storage_get_sel (unsigned char *request, unsigned char *response,
+ unsigned char *res_len)
+{
+ ipmi_req_t *req = (ipmi_req_t *) request;
+ ipmi_res_t *res = (ipmi_res_t *) response;
+ unsigned char *data = &res->data[0];
+
+ int read_rec_id; //record ID to be read
+ int next_rec_id; //record ID for the next msg
+ sel_msg_t entry; // SEL log entry
+ int ret;
+
+ read_rec_id = (req->data[3] >> 8) | req->data[2];
+
+ // Use platform API to read the record Id and get next ID
+ ret = plat_sel_get_entry (read_rec_id, &entry, &next_rec_id);
+ if (ret)
+ {
+ res->cc = CC_UNSPECIFIED_ERROR;
+ return;
+ }
+
+ res->cc = CC_SUCCESS;
+ *data++ = next_rec_id & 0xFF; // next record ID
+ *data++ = (next_rec_id >> 8) & 0xFF;
+
+ memcpy(data, entry.msg, SIZE_SEL_REC);
+ data += SIZE_SEL_REC;
+
+ *res_len = data - &res->data[0];
+
+ return;
+}
+
+static void
+storage_add_sel (unsigned char *request, unsigned char *response,
+ unsigned char *res_len)
+{
+ ipmi_req_t *req = (ipmi_req_t *) request;
+ ipmi_res_t *res = (ipmi_res_t *) response;
+ unsigned char *data = &res->data[0];
+
+
+ int record_id; // Record ID for added entry
+ int ret;
+
+ sel_msg_t entry;
+
+ memcpy(entry.msg, req->data, SIZE_SEL_REC);
+
+ // Use platform APIs to add the new SEL entry
+ ret = plat_sel_add_entry (&entry, &record_id);
+ if (ret)
+ {
+ res->cc = CC_UNSPECIFIED_ERROR;
+ return;
+ }
+
+ res->cc = CC_SUCCESS;
+ *data++ = record_id & 0xFF;
+ *data++ = (record_id >> 8) & 0xFF;
+
+ *res_len = data - &res->data[0];
+
+ return;
+}
+
+static void
+storage_clr_sel (unsigned char *request, unsigned char *response,
+ unsigned char *res_len)
+{
+ ipmi_req_t *req = (ipmi_req_t *) request;
+ ipmi_res_t *res = (ipmi_res_t *) response;
+ unsigned char *data = &res->data[0];
+
+ sel_erase_stat_t status;
+ int ret;
+ int rsv_id;
+
+ // Verify the request to contain 'CLR' characters
+ if ((req->data[2] != 'C') || (req->data[3] != 'L') || (req->data[4] != 'R'))
+ {
+ res->cc = CC_INVALID_PARAM;
+ return;
+ }
+
+ // Populate reservation ID given in request
+ rsv_id = (req->data[1] << 8) | req->data[0];
+
+ // Use platform APIs to clear or get status
+ if (req->data[5] == IPMI_SEL_INIT_ERASE)
+ {
+ ret = plat_sel_erase (rsv_id);
+ }
+ else if (req->data[5] == IPMI_SEL_ERASE_STAT)
+ {
+ ret = plat_sel_erase_status (rsv_id, &status);
+ }
+ else
+ {
+ res->cc = CC_INVALID_PARAM;
+ return;
+ }
+
+ // Handle platform error and return
+ if (ret)
+ {
+ res->cc = CC_UNSPECIFIED_ERROR;
+ return;
+ }
+
+ res->cc = CC_SUCCESS;
+ *data++ = status;
+
+ *res_len = data - &res->data[0];
+
+ return;
+}
+
+static void
+ipmi_handle_storage (unsigned char *request, unsigned char req_len,
+ unsigned char *response, unsigned char *res_len)
+{
+ ipmi_req_t *req = (ipmi_req_t *) request;
+ ipmi_res_t *res = (ipmi_res_t *) response;
+ unsigned char cmd = req->cmd;
+
+ res->cc = CC_SUCCESS;
+ *res_len = 0;
+
+ pthread_mutex_lock(&m_storage);
+ switch (cmd)
+ {
+ case CMD_STORAGE_GET_FRUID_INFO:
+ storage_get_fruid_info (response, res_len);
+ break;
+ case CMD_STORAGE_READ_FRUID_DATA:
+ storage_get_fruid_data (request, response, res_len);
+ break;
+ case CMD_STORAGE_GET_SEL_INFO:
+ storage_get_sel_info (response, res_len);
+ break;
+ case CMD_STORAGE_RSV_SEL:
+ storage_rsv_sel (response, res_len);
+ break;
+ case CMD_STORAGE_ADD_SEL:
+ storage_add_sel (request, response, res_len);
+ break;
+ case CMD_STORAGE_GET_SEL:
+ storage_get_sel (request, response, res_len);
+ break;
+ case CMD_STORAGE_CLR_SEL:
+ storage_clr_sel (request, response, res_len);
+ break;
+ case CMD_STORAGE_GET_SDR_INFO:
+ storage_get_sdr_info (response, res_len);
+ break;
+ case CMD_STORAGE_RSV_SDR:
+ storage_rsv_sdr (response, res_len);
+ break;
+ case CMD_STORAGE_GET_SDR:
+ storage_get_sdr (request, response, res_len);
+ break;
+ default:
+ res->cc = CC_INVALID_CMD;
+ break;
+ }
+
+ pthread_mutex_unlock(&m_storage);
+ return;
+}
+
+/*
+ * Function(s) to handle IPMI messages with NetFn: Transport
+ */
+
+// Set LAN Configuration (IPMI/Section 23.1)
+static void
+transport_set_lan_config (unsigned char *request, unsigned char *response,
+ unsigned char *res_len)
+{
+ ipmi_req_t *req = (ipmi_req_t *) request;
+ ipmi_res_t *res = (ipmi_res_t *) response;
+ unsigned char param = req->data[1];
+
+ // Fill the response with default values
+ res->cc = CC_SUCCESS;
+
+ switch (param)
+ {
+ case LAN_PARAM_SET_IN_PROG:
+ g_lan_config.set_in_prog = req->data[2];
+ break;
+ case LAN_PARAM_AUTH_SUPPORT:
+ g_lan_config.auth_support = req->data[2];
+ break;
+ case LAN_PARAM_AUTH_ENABLES:
+ memcpy(g_lan_config.auth_enables, &req->data[2], SIZE_AUTH_ENABLES);
+ break;
+ case LAN_PARAM_IP_ADDR:
+ memcpy(g_lan_config.ip_addr, &req->data[2], SIZE_IP_ADDR);
+ break;
+ case LAN_PARAM_IP_SRC:
+ g_lan_config.ip_src = req->data[2];
+ break;
+ case LAN_PARAM_MAC_ADDR:
+ memcpy(g_lan_config.mac_addr, &req->data[2], SIZE_MAC_ADDR);
+ break;
+ case LAN_PARAM_NET_MASK:
+ memcpy(g_lan_config.net_mask, &req->data[2], SIZE_NET_MASK);
+ break;
+ case LAN_PARAM_IP_HDR:
+ memcpy(g_lan_config.ip_hdr, &req->data[2], SIZE_IP_HDR);
+ break;
+ case LAN_PARAM_PRI_RMCP_PORT:
+ g_lan_config.pri_rmcp_port[0] = req->data[2];
+ g_lan_config.pri_rmcp_port[1] = req->data[3];
+ break;
+ case LAN_PARAM_SEC_RMCP_PORT:
+ g_lan_config.sec_rmcp_port[0] = req->data[2];
+ g_lan_config.sec_rmcp_port[1] = req->data[3];
+ break;
+ case LAN_PARAM_ARP_CTRL:
+ g_lan_config.arp_ctrl = req->data[2];
+ break;
+ case LAN_PARAM_GARP_INTERVAL:
+ g_lan_config.garp_interval = req->data[2];
+ break;
+ case LAN_PARAM_DF_GW_IP_ADDR:
+ memcpy(g_lan_config.df_gw_ip_addr, &req->data[2], SIZE_IP_ADDR);
+ break;
+ case LAN_PARAM_DF_GW_MAC_ADDR:
+ memcpy(g_lan_config.df_gw_mac_addr, &req->data[2], SIZE_MAC_ADDR);
+ break;
+ case LAN_PARAM_BACK_GW_IP_ADDR:
+ memcpy(g_lan_config.back_gw_ip_addr, &req->data[2], SIZE_IP_ADDR);
+ break;
+ case LAN_PARAM_BACK_GW_MAC_ADDR:
+ memcpy(g_lan_config.back_gw_mac_addr, &req->data[2], SIZE_MAC_ADDR);
+ break;
+ case LAN_PARAM_COMMUNITY_STR:
+ memcpy(g_lan_config.community_str, &req->data[2], SIZE_COMMUNITY_STR);
+ break;
+ case LAN_PARAM_NO_OF_DEST:
+ g_lan_config.no_of_dest = req->data[2];
+ break;
+ case LAN_PARAM_DEST_TYPE:
+ memcpy(g_lan_config.dest_type, &req->data[2], SIZE_DEST_TYPE);
+ break;
+ case LAN_PARAM_DEST_ADDR:
+ memcpy(g_lan_config.dest_addr, &req->data[2], SIZE_DEST_ADDR);
+ break;
+ default:
+ res->cc = CC_INVALID_PARAM;
+ break;
+ }
+}
+
+// Get LAN Configuration (IPMI/Section 23.2)
+static void
+transport_get_lan_config (unsigned char *request, unsigned char *response,
+ unsigned char *res_len)
+{
+
+ ipmi_req_t *req = (ipmi_req_t *) request;
+ ipmi_res_t *res = (ipmi_res_t *) response;
+ unsigned char *data = &res->data[0];
+ unsigned char param = req->data[1];
+
+ // Fill the response with default values
+ res->cc = CC_SUCCESS;
+ *data++ = 0x01; // Parameter revision
+
+ switch (param)
+ {
+ case LAN_PARAM_SET_IN_PROG:
+ *data++ = g_lan_config.set_in_prog;
+ break;
+ case LAN_PARAM_AUTH_SUPPORT:
+ *data++ = g_lan_config.auth_support;
+ break;
+ case LAN_PARAM_AUTH_ENABLES:
+ memcpy(data, g_lan_config.auth_enables, SIZE_AUTH_ENABLES);
+ data += SIZE_AUTH_ENABLES;
+ break;
+ case LAN_PARAM_IP_ADDR:
+ memcpy(data, g_lan_config.ip_addr, SIZE_IP_ADDR);
+ data += SIZE_IP_ADDR;
+ break;
+ case LAN_PARAM_IP_SRC:
+ *data++ = g_lan_config.ip_src;
+ break;
+ case LAN_PARAM_MAC_ADDR:
+ memcpy(data, g_lan_config.mac_addr, SIZE_MAC_ADDR);
+ data += SIZE_MAC_ADDR;
+ break;
+ case LAN_PARAM_NET_MASK:
+ memcpy(data, g_lan_config.net_mask, SIZE_NET_MASK);
+ data += SIZE_NET_MASK;
+ break;
+ case LAN_PARAM_IP_HDR:
+ memcpy(data, g_lan_config.ip_hdr, SIZE_IP_HDR);
+ data += SIZE_IP_HDR;
+ break;
+ case LAN_PARAM_PRI_RMCP_PORT:
+ *data++ = g_lan_config.pri_rmcp_port[0];
+ *data++ = g_lan_config.pri_rmcp_port[1];
+ break;
+ case LAN_PARAM_SEC_RMCP_PORT:
+ *data++ = g_lan_config.sec_rmcp_port[0];
+ *data++ = g_lan_config.sec_rmcp_port[1];
+ break;
+ case LAN_PARAM_ARP_CTRL:
+ *data++ = g_lan_config.arp_ctrl;
+ break;
+ case LAN_PARAM_GARP_INTERVAL:
+ *data++ = g_lan_config.garp_interval;
+ break;
+ case LAN_PARAM_DF_GW_IP_ADDR:
+ memcpy(data, g_lan_config.df_gw_ip_addr, SIZE_IP_ADDR);
+ data += SIZE_IP_ADDR;
+ break;
+ case LAN_PARAM_DF_GW_MAC_ADDR:
+ memcpy(data, g_lan_config.df_gw_mac_addr, SIZE_MAC_ADDR);
+ data += SIZE_MAC_ADDR;
+ break;
+ case LAN_PARAM_BACK_GW_IP_ADDR:
+ memcpy(data, g_lan_config.back_gw_ip_addr, SIZE_IP_ADDR);
+ data += SIZE_IP_ADDR;
+ break;
+ case LAN_PARAM_BACK_GW_MAC_ADDR:
+ memcpy(data, g_lan_config.back_gw_mac_addr, SIZE_MAC_ADDR);
+ data += SIZE_MAC_ADDR;
+ break;
+ case LAN_PARAM_COMMUNITY_STR:
+ memcpy(data, g_lan_config.community_str, SIZE_COMMUNITY_STR);
+ data += SIZE_COMMUNITY_STR;
+ break;
+ case LAN_PARAM_NO_OF_DEST:
+ *data++ = g_lan_config.no_of_dest;
+ break;
+ case LAN_PARAM_DEST_TYPE:
+ memcpy(data, g_lan_config.dest_type, SIZE_DEST_TYPE);
+ data += SIZE_DEST_TYPE;
+ break;
+ case LAN_PARAM_DEST_ADDR:
+ memcpy(data, g_lan_config.dest_addr, SIZE_DEST_ADDR);
+ data += SIZE_DEST_ADDR;
+ break;
+ default:
+ res->cc = CC_INVALID_PARAM;
+ break;
+ }
+
+ if (res->cc == CC_SUCCESS) {
+ *res_len = data - &res->data[0];
+ }
+}
+
+// Handle Transport Commands (IPMI/Section 23)
+static void
+ipmi_handle_transport (unsigned char *request, unsigned char req_len,
+ unsigned char *response, unsigned char *res_len)
+{
+ ipmi_req_t *req = (ipmi_req_t *) request;
+ ipmi_res_t *res = (ipmi_res_t *) response;
+ unsigned char cmd = req->cmd;
+
+ pthread_mutex_lock(&m_transport);
+ switch (cmd)
+ {
+ case CMD_TRANSPORT_SET_LAN_CONFIG:
+ transport_set_lan_config (request, response, res_len);
+ break;
+ case CMD_TRANSPORT_GET_LAN_CONFIG:
+ transport_get_lan_config (request, response, res_len);
+ break;
+ default:
+ res->cc = CC_INVALID_CMD;
+ break;
+ }
+ pthread_mutex_unlock(&m_transport);
+}
+
+/*
+ * Function(s) to handle IPMI messages with NetFn: OEM
+ */
+
+static void
+oem_set_proc_info (unsigned char *request, unsigned char *response,
+ unsigned char *res_len)
+{
+ ipmi_req_t *req = (ipmi_req_t *) request;
+ ipmi_res_t *res = (ipmi_res_t *) response;
+
+ g_proc_info.type = req->data[1];
+ g_proc_info.freq[0] = req->data[2];
+ g_proc_info.freq[1] = req->data[3];
+
+ res->cc = CC_SUCCESS;
+ *res_len = 0;
+}
+
+static void
+oem_set_dimm_info (unsigned char *request, unsigned char *response,
+ unsigned char *res_len)
+{
+ ipmi_req_t *req = (ipmi_req_t *) request;
+ ipmi_res_t *res = (ipmi_res_t *) response;
+
+ unsigned char index = req->data[0];
+
+ g_dimm_info[index].type = req->data[1];
+ g_dimm_info[index].speed[0] = req->data[2];
+ g_dimm_info[index].speed[1] = req->data[3];
+ g_dimm_info[index].size[0] = req->data[4];
+ g_dimm_info[index].size[1] = req->data[5];
+
+ res->cc = CC_SUCCESS;
+ *res_len = 0;
+}
+
+static void
+oem_set_post_start (unsigned char *response, unsigned char *res_len)
+{
+
+ ipmi_res_t *res = (ipmi_res_t *) response;
+
+ // TODO: For now logging the event, need to find usage for this info
+ syslog (LOG_INFO, "POST Start Event\n");
+
+ res->cc = CC_SUCCESS;
+ *res_len = 0;
+}
+
+static void
+oem_set_post_end (unsigned char *response, unsigned char *res_len)
+{
+
+ ipmi_res_t *res = (ipmi_res_t *) response;
+
+ // TODO: For now logging the event, need to find usage for this info
+ syslog (LOG_INFO, "POST End Event\n");
+
+ res->cc = CC_SUCCESS;
+ *res_len = 0;
+}
+
+static void
+ipmi_handle_oem (unsigned char *request, unsigned char req_len,
+ unsigned char *response, unsigned char *res_len)
+{
+
+ ipmi_req_t *req = (ipmi_req_t *) request;
+ ipmi_res_t *res = (ipmi_res_t *) response;
+
+ unsigned char cmd = req->cmd;
+
+ pthread_mutex_lock(&m_oem);
+ switch (cmd)
+ {
+ case CMD_OEM_SET_PROC_INFO:
+ oem_set_proc_info (request, response, res_len);
+ break;
+ case CMD_OEM_SET_DIMM_INFO:
+ oem_set_dimm_info (request, response, res_len);
+ break;
+ case CMD_OEM_SET_POST_START:
+ oem_set_post_start (response, res_len);
+ break;
+ case CMD_OEM_SET_POST_END:
+ oem_set_post_end (response, res_len);
+ break;
+ default:
+ res->cc = CC_INVALID_CMD;
+ break;
+ }
+ pthread_mutex_unlock(&m_oem);
+}
+
+/*
+ * Function to handle all IPMI messages
+ */
+static void
+ipmi_handle (unsigned char *request, unsigned char req_len,
+ unsigned char *response, unsigned char *res_len)
+{
+
+ ipmi_req_t *req = (ipmi_req_t *) request;
+ ipmi_res_t *res = (ipmi_res_t *) response;
+ unsigned char netfn;
+
+ netfn = req->netfn_lun >> 2;
+
+ // Provide default values in the response message
+ res->cmd = req->cmd;
+ res->cc = 0xFF; // Unspecified completion code
+ *res_len = 0;
+
+ switch (netfn)
+ {
+ case NETFN_CHASSIS_REQ:
+ res->netfn_lun = NETFN_CHASSIS_RES << 2;
+ ipmi_handle_chassis (request, req_len, response, res_len);
+ break;
+ case NETFN_APP_REQ:
+ res->netfn_lun = NETFN_APP_RES << 2;
+ ipmi_handle_app (request, req_len, response, res_len);
+ break;
+ case NETFN_STORAGE_REQ:
+ res->netfn_lun = NETFN_STORAGE_RES << 2;
+ ipmi_handle_storage (request, req_len, response, res_len);
+ break;
+ case NETFN_TRANSPORT_REQ:
+ res->netfn_lun = NETFN_TRANSPORT_RES << 2;
+ ipmi_handle_transport (request, req_len, response, res_len);
+ break;
+ case NETFN_OEM_REQ:
+ res->netfn_lun = NETFN_OEM_RES << 2;
+ ipmi_handle_oem (request, req_len, response, res_len);
+ break;
+ default:
+ res->netfn_lun = (netfn + 1) << 2;
+ break;
+ }
+
+ // This header includes NetFunction, Command, and Completion Code
+ *res_len += SIZE_IPMI_RES_HDR;
+
+ return;
+}
+
+void
+*conn_handler(void *socket_desc) {
+ int sock = *(int*)socket_desc;
+ int n;
+ unsigned char req_buf[MAX_IPMI_MSG_SIZE];
+ unsigned char res_buf[MAX_IPMI_MSG_SIZE];
+ unsigned char res_len = 0;
+
+ n = recv (sock, req_buf, sizeof(req_buf), 0);
+ if (n <= 0) {
+ syslog(LOG_ALERT, "ipmid: recv() failed with %d\n", n);
+ goto conn_cleanup;
+ }
+
+ ipmi_handle(req_buf, n, res_buf, &res_len);
+
+ if (send (sock, res_buf, res_len, 0) < 0) {
+ syslog(LOG_ALERT, "ipmid: send() failed\n");
+ }
+
+conn_cleanup:
+ close(sock);
+
+ pthread_exit(NULL);
+ return 0;
+}
+
+
+int
+main (void)
+{
+ int s, s2, t, len;
+ struct sockaddr_un local, remote;
+ pthread_t tid;
+
+ daemon(1, 0);
+ openlog("ipmid", LOG_CONS, LOG_DAEMON);
+
+ plat_sel_init();
+ plat_sensor_init();
+ plat_sdr_init();
+ plat_fruid_init();
+
+ pthread_mutex_init(&m_chassis, NULL);
+ pthread_mutex_init(&m_app, NULL);
+ pthread_mutex_init(&m_storage, NULL);
+ pthread_mutex_init(&m_transport, NULL);
+ pthread_mutex_init(&m_oem, NULL);
+
+ if ((s = socket (AF_UNIX, SOCK_STREAM, 0)) == -1)
+ {
+ syslog(LOG_ALERT, "ipmid: socket() failed\n");
+ exit (1);
+ }
+
+ local.sun_family = AF_UNIX;
+ strcpy (local.sun_path, SOCK_PATH);
+ unlink (local.sun_path);
+ len = strlen (local.sun_path) + sizeof (local.sun_family);
+ if (bind (s, (struct sockaddr *) &local, len) == -1)
+ {
+ syslog(LOG_ALERT, "ipmid: bind() failed\n");
+ exit (1);
+ }
+
+ if (listen (s, 5) == -1)
+ {
+ syslog(LOG_ALERT, "ipmid: listen() failed\n");
+ exit (1);
+ }
+
+ while(1) {
+ int n;
+ t = sizeof (remote);
+ if ((s2 = accept (s, (struct sockaddr *) &remote, &t)) < 0) {
+ syslog(LOG_ALERT, "ipmid: accept() failed\n");
+ break;
+ }
+
+ // Creating a worker thread to handle the request
+ // TODO: Need to monitor the server performance with higher load and
+ // see if we need to create pre-defined number of workers and schedule
+ // the requests among them.
+ if (pthread_create(&tid, NULL, conn_handler, (void*) &s2) < 0) {
+ syslog(LOG_ALERT, "ipmid: pthread_create failed\n");
+ close(s2);
+ continue;
+ }
+
+ pthread_detach(tid);
+ }
+
+ close(s);
+
+ pthread_mutex_destroy(&m_chassis);
+ pthread_mutex_destroy(&m_app);
+ pthread_mutex_destroy(&m_storage);
+ pthread_mutex_destroy(&m_transport);
+ pthread_mutex_destroy(&m_oem);
+
+ return 0;
+}
diff --git a/meta-facebook/meta-wedge/recipes-wedge/ipmid/files/platform/fruid.h b/meta-facebook/meta-wedge/recipes-wedge/ipmid/files/platform/fruid.h
new file mode 100644
index 0000000..3580b08
--- /dev/null
+++ b/meta-facebook/meta-wedge/recipes-wedge/ipmid/files/platform/fruid.h
@@ -0,0 +1,28 @@
+/*
+ *
+ * Copyright 2015-present Facebook. All Rights Reserved.
+ *
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef __FRUID_H__
+#define __FRUID_H__
+
+int plat_fruid_size(void);
+int plat_fruid_data(int offset, int count, unsigned char *data);
+int plat_fruid_init(void);
+
+#endif /* __FRUID_H__ */
diff --git a/meta-facebook/meta-wedge/recipes-wedge/ipmid/files/platform/sdr.c b/meta-facebook/meta-wedge/recipes-wedge/ipmid/files/platform/sdr.c
new file mode 100644
index 0000000..e0a2f9a
--- /dev/null
+++ b/meta-facebook/meta-wedge/recipes-wedge/ipmid/files/platform/sdr.c
@@ -0,0 +1,412 @@
+/*
+ *
+ * Copyright 2014-present Facebook. All Rights Reserved.
+ *
+ * This file represents platform specific implementation for storing
+ * SDR record entries and acts as back-end for IPMI stack
+ *
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include "sdr.h"
+#include "sensor.h"
+#include "timestamp.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <errno.h>
+#include <syslog.h>
+#include <string.h>
+
+// SDR Header magic number
+#define SDR_HDR_MAGIC 0xFBFBFBFB
+
+// SDR Header version number
+#define SDR_HDR_VERSION 0x01
+
+// SDR reservation IDs can not be 0x00 or 0xFFFF
+#define SDR_RSVID_MIN 0x01
+#define SDR_RSVID_MAX 0xFFFE
+
+#define SDR_RECORDS_MAX 64 // to support around 64 sensors
+
+// SDR index to keep track
+#define SDR_INDEX_MIN 0
+#define SDR_INDEX_MAX (SDR_RECORDS_MAX - 1)
+
+// Record ID can not be 0x0 (IPMI/Section 31)
+#define SDR_RECID_MIN 1
+#define SDR_RECID_MAX SDR_RECORDS_MAX
+
+// Special RecID value for first and last (IPMI/Section 31)
+#define SDR_RECID_FIRST 0x0000
+#define SDR_RECID_LAST 0xFFFF
+
+#define SDR_VERSION 0x51
+#define SDR_LEN_MAX 64
+
+#define SDR_FULL_TYPE 0x01
+#define SDR_MGMT_TYPE 0x12
+#define SDR_OEM_TYPE 0xC0
+
+#define SDR_FULL_LEN 64
+#define SDR_MGMT_LEN 32
+#define SDR_OEM_LEN 64
+
+// SDR header struct to keep track of SEL Log entries
+typedef struct {
+ int magic; // Magic number to check validity
+ int version; // version number of this header
+ int begin; // index to the first SDR entry
+ int end; // index to the last SDR entry
+ time_stamp_t ts_add; // last addition time stamp
+ time_stamp_t ts_erase; // last erase time stamp
+} sdr_hdr_t;
+
+// Keep track of last Reservation ID
+static int g_rsv_id = 0x01;
+
+// SDR Header and data global structures
+static sdr_hdr_t g_sdr_hdr;
+static sdr_rec_t g_sdr_data[SDR_RECORDS_MAX];
+
+// Add a new SDR entry
+static int
+plat_sdr_add_entry(sdr_rec_t *rec, int *rec_id) {
+ // If SDR is full, return error
+ if (plat_sdr_num_entries() == SDR_RECORDS_MAX) {
+ syslog(LOG_ALERT, "plat_sdr_add_entry: SDR full\n");
+ return -1;
+ }
+
+ // Add Record ID which is array index + 1
+ rec->rec[0] = g_sdr_hdr.end+1;
+
+ // Add the enry at end
+ memcpy(g_sdr_data[g_sdr_hdr.end].rec, rec->rec, sizeof(sdr_rec_t));
+
+ // Return the newly added record ID
+ *rec_id = g_sdr_hdr.end+1;
+
+ // Increment the end pointer
+ ++g_sdr_hdr.end;
+
+ // Update timestamp for add in header
+ time_stamp_fill(g_sdr_hdr.ts_add.ts);
+
+ return 0;
+}
+
+static int
+sdr_add_mgmt_rec(sensor_mgmt_t *p_rec) {
+ int rec_id = 0;
+ sdr_rec_t sdr = { 0 };
+ sdr_mgmt_t rec = { 0 };
+
+ // Populate SDR MGMT record
+ rec.ver = SDR_VERSION;
+ rec.type = SDR_MGMT_TYPE;
+ rec.len = SDR_MGMT_LEN;
+
+ rec.slave_addr = p_rec->slave_addr;
+ rec.chan_no = p_rec->chan_no;
+
+ rec.pwr_state_init = p_rec->pwr_state_init;
+ rec.dev_caps = p_rec->dev_caps;
+ rec.ent_id = p_rec->ent_id;
+ rec.ent_inst = p_rec->ent_inst;
+ rec.oem = p_rec->oem;
+ rec.str_type_len = p_rec->str_type_len;
+ memcpy(rec.str, p_rec->str, SENSOR_STR_SIZE);
+
+ // Copy this record to generic SDR record
+ memcpy(sdr.rec, &rec, SDR_LEN_MAX);
+
+ // Add this record to SDR repo
+ if (plat_sdr_add_entry(&sdr, &rec_id)) {
+ syslog(LOG_ALERT, "sdr_add_mgmt_rec: plat_sdr_add_entry failed\n");
+ return -1;
+ }
+
+ return 0;
+}
+
+static int
+sdr_add_disc_rec(sensor_disc_t *p_rec) {
+ int rec_id = 0;
+ sdr_rec_t sdr = { 0 };
+ sdr_full_t rec = { 0 };
+
+ // Populate SDR FULL record
+ rec.ver = SDR_VERSION;
+ rec.type = SDR_FULL_TYPE;
+ rec.len = SDR_FULL_LEN;
+
+ rec.owner = p_rec->owner;
+ rec.lun = p_rec->lun;
+
+ rec.ent_id = p_rec->ent_id;
+ rec.ent_inst = p_rec->ent_inst;
+ rec.sensor_init = p_rec->sensor_init;
+ rec.sensor_caps = p_rec->sensor_caps;
+ rec.sensor_type = p_rec->sensor_type;
+ rec.evt_read_type = p_rec->evt_read_type;
+ memcpy(rec.assert_evt_mask, p_rec->assert_evt_mask, 2);
+ memcpy(rec.deassert_evt_mask, p_rec->deassert_evt_mask, 2);
+ memcpy(rec.read_evt_mask, p_rec->read_evt_mask, 2);
+ rec.oem = p_rec->oem;
+ rec.str_type_len = p_rec->str_type_len;
+ memcpy(rec.str, p_rec->str, SENSOR_STR_SIZE);
+
+ // Copy this record to generic SDR record
+ memcpy(sdr.rec, &rec, SDR_LEN_MAX);
+
+ // Add this record to SDR repo
+ if (plat_sdr_add_entry(&sdr, &rec_id)) {
+ syslog(LOG_ALERT, "sdr_add_disc_rec: plat_sdr_add_entry failed\n");
+ return -1;
+ }
+
+ return 0;
+}
+
+static int
+sdr_add_thresh_rec(sensor_thresh_t *p_rec) {
+ int rec_id = 0;
+ sdr_rec_t sdr = { 0 };
+ sdr_full_t rec = { 0 };
+
+ // Populate SDR FULL record
+ rec.ver = SDR_VERSION;
+ rec.type = SDR_FULL_TYPE;
+ rec.len = SDR_FULL_LEN;
+
+ rec.owner = p_rec->owner;
+ rec.lun = p_rec->lun;
+
+ rec.ent_id = p_rec->ent_id;
+ rec.ent_inst = p_rec->ent_inst;
+ rec.sensor_init = p_rec->sensor_init;
+ rec.sensor_caps = p_rec->sensor_caps;
+ rec.sensor_type = p_rec->sensor_type;
+ rec.evt_read_type = p_rec->evt_read_type;
+ memcpy(rec.lt_read_mask, p_rec->lt_read_mask, 2);
+ memcpy(rec.ut_read_mask, p_rec->ut_read_mask, 2);
+ memcpy(rec.set_thresh_mask, p_rec->set_thresh_mask, 2);
+ rec.sensor_units1 = p_rec->sensor_units1;
+ rec.sensor_units2 = p_rec->sensor_units2;
+ rec.sensor_units3 = p_rec->sensor_units3;
+ rec.linear = p_rec->linear;
+ rec.m_val = p_rec->m_val;
+ rec.m_tolerance = p_rec->m_tolerance;
+ rec.b_val = p_rec->b_val;
+ rec.b_accuracy = p_rec->b_accuracy;
+ rec.analog_flags = p_rec->analog_flags;
+ rec.nominal = p_rec->nominal;
+ rec.normal_max = p_rec->normal_max;
+ rec.normal_min = p_rec->normal_min;
+ rec.max_reading = p_rec->max_reading;
+ rec.min_reading = p_rec->min_reading;
+ rec.unr_thresh = p_rec->unr_thresh;
+ rec.uc_thresh = p_rec->uc_thresh;
+ rec.unc_thresh = p_rec->unc_thresh;
+ rec.lnr_thresh = p_rec->lnr_thresh;
+ rec.lc_thresh = p_rec->lc_thresh;
+ rec.lnc_thresh = p_rec->lnc_thresh;
+ rec.pos_hyst = p_rec->pos_hyst;
+ rec.neg_hyst = p_rec->neg_hyst;
+ rec.oem = p_rec->oem;
+ rec.str_type_len = p_rec->str_type_len;
+ memcpy(rec.str, p_rec->str, SENSOR_STR_SIZE);
+
+ // Copy this record to generic SDR record
+ memcpy(sdr.rec, &rec, SDR_LEN_MAX);
+
+ // Add this record to SDR repo
+ if (plat_sdr_add_entry(&sdr, &rec_id)) {
+ syslog(LOG_ALERT, "sdr_add_thresh_rec: plat_sdr_add_entry failed\n");
+ return -1;
+ }
+
+ return 0;
+}
+
+static int
+sdr_add_oem_rec(sensor_oem_t *p_rec) {
+ int rec_id = 0;
+ sdr_rec_t sdr = { 0 };
+ sdr_oem_t rec = { 0 };
+
+ // Populate SDR OEM record
+ rec.ver = SDR_VERSION;
+ rec.type = SDR_OEM_TYPE;
+ rec.len = SDR_OEM_LEN;
+
+ memcpy(rec.mfr_id, p_rec->mfr_id, 3);
+ memcpy(rec.oem_data, p_rec->oem_data, SENSOR_OEM_DATA_SIZE);
+
+ // Copy this record to generic SDR record
+ memcpy(sdr.rec, &rec, SDR_LEN_MAX);
+
+ // Add this record to SDR repo
+ if (plat_sdr_add_entry(&sdr, &rec_id)) {
+ syslog(LOG_ALERT, "sdr_add_oem_rec: plat_sdr_add_entry failed\n");
+ return -1;
+ }
+
+ return 0;
+}
+
+// Platform specific SEL API entry points
+// Retrieve time stamp for recent add operation
+void
+plat_sdr_ts_recent_add(time_stamp_t *ts) {
+ memcpy(ts->ts, g_sdr_hdr.ts_add.ts, 0x04);
+}
+
+// Retrieve time stamp for recent erase operation
+void
+plat_sdr_ts_recent_erase(time_stamp_t *ts) {
+ memcpy(ts->ts, g_sdr_hdr.ts_erase.ts, 0x04);
+}
+
+// Retrieve total number of entries in SDR repo
+int
+plat_sdr_num_entries(void) {
+ return (g_sdr_hdr.end - g_sdr_hdr.begin);
+}
+
+// Retrieve total free space available in SDR repo
+int
+plat_sdr_free_space(void) {
+ int total_space;
+ int used_space;
+
+ total_space = SDR_RECORDS_MAX * sizeof(sdr_rec_t);
+ used_space = plat_sdr_num_entries() * sizeof(sdr_rec_t);
+
+ return (total_space - used_space);
+}
+
+// Reserve an ID that will be used in later operations
+// IPMI/Section 33.11
+int
+plat_sdr_rsv_id() {
+ // Increment the current reservation ID and return
+ if (g_rsv_id++ == SDR_RSVID_MAX) {
+ g_rsv_id = SDR_RSVID_MIN;
+ }
+
+ return g_rsv_id;
+}
+
+// Get the SDR entry for a given record ID
+// IPMI/Section 33.12
+int
+plat_sdr_get_entry(int rsv_id, int read_rec_id, sdr_rec_t *rec,
+ int *next_rec_id) {
+
+ int index;
+
+ // Make sure the rsv_id matches
+ if (rsv_id != g_rsv_id) {
+ syslog(LOG_ALERT, "plat_sdr_get_entry: Reservation ID mismatch\n");
+ return -1;
+ }
+
+ // Find the index in to array based on given index
+ if (read_rec_id == SDR_RECID_FIRST) {
+ index = g_sdr_hdr.begin;
+ } else if (read_rec_id == SDR_RECID_LAST) {
+ index = g_sdr_hdr.end - 1;
+ } else {
+ index = read_rec_id - 1;
+ }
+
+ // If the SDR repo is empty return error
+ if (plat_sdr_num_entries() == 0) {
+ syslog(LOG_ALERT, "plat_sdr_get_entry: No entries\n");
+ return -1;
+ }
+
+ // Check for boundary conditions
+ if ((index < SDR_INDEX_MIN) || (index > SDR_INDEX_MAX)) {
+ syslog(LOG_ALERT, "plat_sdr_get_entry: Invalid Record ID %d\n", read_rec_id);
+ return -1;
+ }
+
+ // Check to make sure the given id is valid
+ if (index < g_sdr_hdr.begin || index >= g_sdr_hdr.end) {
+ syslog(LOG_ALERT, "plat_sdr_get_entry: Wrong Record ID %d\n", read_rec_id);
+ return -1;
+ }
+
+ memcpy(rec->rec, g_sdr_data[index].rec, sizeof(sdr_rec_t));
+
+ // Return the next record ID in the log
+ *next_rec_id = ++read_rec_id;
+
+ // If this is the last entry in the log, return 0xFFFF
+ if (*next_rec_id == g_sdr_hdr.end) {
+ *next_rec_id = SDR_RECID_LAST;
+ }
+
+ return 0;
+}
+
+
+// Initialize SDR Repo structure
+int
+plat_sdr_init(void) {
+ int num;
+ sensor_mgmt_t *p_mgmt;
+ sensor_thresh_t *p_thresh;
+ sensor_disc_t *p_disc;
+ sensor_oem_t *p_oem;
+
+ // Populate SDR Header
+ g_sdr_hdr.magic = SDR_HDR_MAGIC;
+ g_sdr_hdr.version = SDR_HDR_VERSION;
+ g_sdr_hdr.begin = SDR_INDEX_MIN;
+ g_sdr_hdr.end = SDR_INDEX_MIN;
+ memset(g_sdr_hdr.ts_add.ts, 0x0, 4);
+ memset(g_sdr_hdr.ts_erase.ts, 0x0, 4);
+
+ // Populate all mgmt control sensors
+ plat_sensor_mgmt_info(&num, &p_mgmt);
+ for (int i = 0; i < num; i++) {
+ sdr_add_mgmt_rec(&p_mgmt[i]);
+ }
+
+ // Populate all discrete sensors
+ plat_sensor_disc_info(&num, &p_disc);
+ for (int i = 0; i < num; i++) {
+ sdr_add_disc_rec(&p_disc[i]);
+ }
+
+ // Populate all threshold sensors
+ plat_sensor_thresh_info(&num, &p_thresh);
+ for (int i = 0; i < num; i++) {
+ sdr_add_thresh_rec(&p_thresh[i]);
+ }
+
+ // Populate all OEM sensors
+ plat_sensor_oem_info(&num, &p_oem);
+ for (int i = 0; i < num; i++) {
+ sdr_add_oem_rec(&p_oem[i]);
+ }
+
+ return 0;
+}
diff --git a/meta-facebook/meta-wedge/recipes-wedge/ipmid/files/platform/sdr.h b/meta-facebook/meta-wedge/recipes-wedge/ipmid/files/platform/sdr.h
new file mode 100644
index 0000000..5e2a591
--- /dev/null
+++ b/meta-facebook/meta-wedge/recipes-wedge/ipmid/files/platform/sdr.h
@@ -0,0 +1,132 @@
+/*
+ *
+ * Copyright 2014-present Facebook. All Rights Reserved.
+ *
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef __SDR_H__
+#define __SDR_H__
+
+#include "timestamp.h"
+
+typedef struct {
+ unsigned char rec[64];
+} sdr_rec_t;
+
+// Full Sensor SDR record; IPMI/Section 43.1
+typedef struct {
+ // Sensor Record Header
+ unsigned char rec_id[2];
+ unsigned char ver;
+ unsigned char type;
+ unsigned char len;
+ // Record Key Bytes
+ unsigned char owner;
+ unsigned char lun;
+ unsigned char sensor_num;
+ // Record Body Bytes
+ unsigned char ent_id;
+ unsigned char ent_inst;
+ unsigned char sensor_init;
+ unsigned char sensor_caps;
+ unsigned char sensor_type;
+ unsigned char evt_read_type;
+ union {
+ unsigned char assert_evt_mask[2];
+ unsigned char lt_read_mask[2];
+ };
+ union {
+ unsigned char deassert_evt_mask[2];
+ unsigned char ut_read_mask[2];
+ };
+ union {
+ unsigned char read_evt_mask[2];
+ unsigned char set_thresh_mask[2];
+ };
+ unsigned char sensor_units1;
+ unsigned char sensor_units2;
+ unsigned char sensor_units3;
+ unsigned char linear;
+ unsigned char m_val;
+ unsigned char m_tolerance;
+ unsigned char b_val;
+ unsigned char b_accuracy;
+ unsigned char accuracy_dir;
+ unsigned char rb_exp;
+ unsigned char analog_flags;
+ unsigned char nominal;
+ unsigned char normal_max;
+ unsigned char normal_min;
+ unsigned char max_reading;
+ unsigned char min_reading;
+ unsigned char unr_thresh;
+ unsigned char uc_thresh;
+ unsigned char unc_thresh;
+ unsigned char lnr_thresh;
+ unsigned char lc_thresh;
+ unsigned char lnc_thresh;
+ unsigned char pos_hyst;
+ unsigned char neg_hyst;
+ unsigned char rsvd[2];
+ unsigned char oem;
+ unsigned char str_type_len;
+ char str[16];
+} sdr_full_t;
+
+// Mgmt. Controller SDR record; IPMI/ Section 43.9
+typedef struct {
+ // Sensor Record Header
+ unsigned char rec_id[2];
+ unsigned char ver;
+ unsigned char type;
+ unsigned char len;
+ // Record Key Bytes
+ unsigned char slave_addr;
+ unsigned char chan_no;
+ // Record Body Bytes
+ unsigned char pwr_state_init;
+ unsigned char dev_caps;
+ unsigned char rsvd[3];
+ unsigned char ent_id;
+ unsigned char ent_inst;
+ unsigned char oem;
+ unsigned char str_type_len;
+ char str[16];
+} sdr_mgmt_t;
+
+// OEM type SDR record; IPMI/Section 43.12
+typedef struct {
+ // Sensor Record Header
+ unsigned char rec_id[2];
+ unsigned char ver;
+ unsigned char type;
+ unsigned char len;
+ // Record Body Bytes
+ unsigned char mfr_id[3];
+ unsigned char oem_data[56];
+} sdr_oem_t;
+
+void plat_sdr_ts_recent_add(time_stamp_t *ts);
+void plat_sdr_ts_recent_erase(time_stamp_t *ts);
+int plat_sdr_num_entries(void);
+int plat_sdr_free_space(void);
+int plat_sdr_rsv_id();
+int plat_sdr_get_entry(int rsv_id, int read_rec_id, sdr_rec_t *rec,
+ int *next_rec_id);
+int plat_sdr_init(void);
+
+#endif /* __SDR_H__ */
diff --git a/meta-facebook/meta-wedge/recipes-wedge/ipmid/files/platform/sel.c b/meta-facebook/meta-wedge/recipes-wedge/ipmid/files/platform/sel.c
new file mode 100644
index 0000000..a7aa78f
--- /dev/null
+++ b/meta-facebook/meta-wedge/recipes-wedge/ipmid/files/platform/sel.c
@@ -0,0 +1,438 @@
+/*
+ *
+ * Copyright 2014-present Facebook. All Rights Reserved.
+ *
+ * This file represents platform specific implementation for storing
+ * SEL logs and acts as back-end for IPMI stack
+ *
+ * TODO: Optimize the file handling to keep file open always instead of
+ * current open/seek/close
+ *
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include "sel.h"
+#include "timestamp.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <errno.h>
+#include <syslog.h>
+#include <string.h>
+
+// SEL File.
+#define SEL_LOG_FILE "/mnt/data/sel.bin"
+
+// SEL Header magic number
+#define SEL_HDR_MAGIC 0xFBFBFBFB
+
+// SEL Header version number
+#define SEL_HDR_VERSION 0x01
+
+// SEL Data offset from file beginning
+#define SEL_DATA_OFFSET 0x100
+
+// SEL reservation IDs can not be 0x00 or 0xFFFF
+#define SEL_RSVID_MIN 0x01
+#define SEL_RSVID_MAX 0xFFFE
+
+// Number of SEL records before wrap
+#define SEL_RECORDS_MAX 128 // TODO: Based on need we can make it bigger
+#define SEL_ELEMS_MAX (SEL_RECORDS_MAX+1)
+
+// Index for circular array
+#define SEL_INDEX_MIN 0x00
+#define SEL_INDEX_MAX SEL_RECORDS_MAX
+
+// Record ID can not be 0x0 (IPMI/Section 31)
+#define SEL_RECID_MIN (SEL_INDEX_MIN+1)
+#define SEL_RECID_MAX (SEL_INDEX_MAX+1)
+
+// Special RecID value for first and last (IPMI/Section 31)
+#define SEL_RECID_FIRST 0x0000
+#define SEL_RECID_LAST 0xFFFF
+
+// SEL header struct to keep track of SEL Log entries
+typedef struct {
+ int magic; // Magic number to check validity
+ int version; // version number of this header
+ int begin; // index to the begining of the log
+ int end; // index to end of the log
+ time_stamp_t ts_add; // last addition time stamp
+ time_stamp_t ts_erase; // last erase time stamp
+} sel_hdr_t;
+
+// Keep track of last Reservation ID
+static int g_rsv_id = 0x01;
+
+// Cached version of SEL Header and data
+static sel_hdr_t g_sel_hdr;
+static sel_msg_t g_sel_data[SEL_ELEMS_MAX];
+
+// Local helper functions to interact with file system
+static int
+file_get_sel_hdr(void) {
+ FILE *fp;
+
+ fp = fopen(SEL_LOG_FILE, "r");
+ if (fp == NULL) {
+ return -1;
+ }
+
+ if (fread(&g_sel_hdr, sizeof(sel_hdr_t), 1, fp) <= 0) {
+ syslog(LOG_ALERT, "file_get_sel_hdr: fread\n");
+ fclose (fp);
+ return -1;
+ }
+
+ fclose(fp);
+ return 0;
+}
+
+static int
+file_get_sel_data(void) {
+ FILE *fp;
+
+ fp = fopen(SEL_LOG_FILE, "r");
+ if (fp == NULL) {
+ syslog(LOG_ALERT, "file_get_sel_data: fopen\n");
+ return -1;
+ }
+
+ if (fseek(fp, SEL_DATA_OFFSET, SEEK_SET)) {
+ syslog(LOG_ALERT, "file_get_sel_data: fseek\n");
+ fclose(fp);
+ return -1;
+ }
+
+ unsigned char buf[SEL_ELEMS_MAX * 16];
+ if (fread(buf, 1, SEL_ELEMS_MAX * sizeof(sel_msg_t), fp) <= 0) {
+ syslog(LOG_ALERT, "file_get_sel_data: fread\n");
+ fclose(fp);
+ return -1;
+ }
+
+ fclose(fp);
+
+ for (int i = 0; i < SEL_ELEMS_MAX; i++) {
+ for (int j = 0; j < sizeof(sel_msg_t);j++) {
+ g_sel_data[i].msg[j] = buf[i*16 + j];
+ }
+ }
+
+ return 0;
+}
+
+static int
+file_store_sel_hdr(void) {
+ FILE *fp;
+
+ fp = fopen(SEL_LOG_FILE, "r+");
+ if (fp == NULL) {
+ syslog(LOG_ALERT, "file_store_sel_hdr: fopen\n");
+ return -1;
+ }
+
+ if (fwrite(&g_sel_hdr, sizeof(sel_hdr_t), 1, fp) <= 0) {
+ syslog(LOG_ALERT, "file_store_sel_hdr: fwrite\n");
+ fclose(fp);
+ return -1;
+ }
+
+ fclose(fp);
+
+ return 0;
+}
+
+static int
+file_store_sel_data(int recId, sel_msg_t *data) {
+ FILE *fp;
+ int index;
+
+ fp = fopen(SEL_LOG_FILE, "r+");
+ if (fp == NULL) {
+ syslog(LOG_ALERT, "file_store_sel_data: fopen\n");
+ return -1;
+ }
+
+ // Records are stored using zero-based index
+ index = (recId-1) * sizeof(sel_msg_t);
+
+ if (fseek(fp, SEL_DATA_OFFSET+index, SEEK_SET)) {
+ syslog(LOG_ALERT, "file_store_sel_data: fseek\n");
+ fclose(fp);
+ return -1;
+ }
+
+ if (fwrite(data->msg, sizeof(sel_msg_t), 1, fp) <= 0) {
+ syslog(LOG_ALERT, "file_store_sel_data: fwrite\n");
+ fclose(fp);
+ return -1;
+ }
+
+ fclose(fp);
+
+ return 0;
+}
+
+// Platform specific SEL API entry points
+// Retrieve time stamp for recent add operation
+void
+plat_sel_ts_recent_add(time_stamp_t *ts) {
+ memcpy(ts->ts, g_sel_hdr.ts_add.ts, 0x04);
+}
+
+// Retrieve time stamp for recent erase operation
+void
+plat_sel_ts_recent_erase(time_stamp_t *ts) {
+ memcpy(ts->ts, g_sel_hdr.ts_erase.ts, 0x04);
+}
+
+// Retrieve total number of entries in SEL log
+int
+plat_sel_num_entries(void) {
+ if (g_sel_hdr.begin <= g_sel_hdr.end) {
+ return (g_sel_hdr.end - g_sel_hdr.begin);
+ } else {
+ return (g_sel_hdr.end + (SEL_INDEX_MAX - g_sel_hdr.begin + 1));
+ }
+}
+
+// Retrieve total free space available in SEL log
+int
+plat_sel_free_space(void) {
+ int total_space;
+ int used_space;
+
+ total_space = SEL_RECORDS_MAX * sizeof(sel_msg_t);
+ used_space = plat_sel_num_entries() * sizeof(sel_msg_t);
+
+ return (total_space - used_space);
+}
+
+// Reserve an ID that will be used in later operations
+// IPMI/Section 31.4
+int
+plat_sel_rsv_id() {
+ // Increment the current reservation ID and return
+ if (g_rsv_id++ == SEL_RSVID_MAX) {
+ g_rsv_id = SEL_RSVID_MIN;
+ }
+
+ return g_rsv_id;
+}
+
+// Get the SEL entry for a given record ID
+// IPMI/Section 31.5
+int
+plat_sel_get_entry(int read_rec_id, sel_msg_t *msg, int *next_rec_id) {
+
+ int index;
+
+ // Find the index in to array based on given index
+ if (read_rec_id == SEL_RECID_FIRST) {
+ index = g_sel_hdr.begin;
+ } else if (read_rec_id == SEL_RECID_LAST) {
+ if (g_sel_hdr.end) {
+ index = g_sel_hdr.end - 1;
+ } else {
+ index = SEL_INDEX_MAX;
+ }
+ } else {
+ index = read_rec_id - 1;
+ }
+
+ // If the log is empty return error
+ if (plat_sel_num_entries() == 0) {
+ syslog(LOG_ALERT, "plat_sel_get_entry: No entries\n");
+ return -1;
+ }
+
+ // Check for boundary conditions
+ if ((index < SEL_INDEX_MIN) || (index > SEL_INDEX_MAX)) {
+ syslog(LOG_ALERT, "plat_sel_get_entry: Invalid Record ID %d\n", read_rec_id);
+ return -1;
+ }
+
+ // If begin < end, check to make sure the given id falls between
+ if (g_sel_hdr.begin < g_sel_hdr.end) {
+ if (index < g_sel_hdr.begin || index >= g_sel_hdr.end) {
+ syslog(LOG_ALERT, "plat_sel_get_entry: Wrong Record ID %d\n", read_rec_id);
+ return -1;
+ }
+ }
+
+ // If end < begin, check to make sure the given id is valid
+ if (g_sel_hdr.begin > g_sel_hdr.end) {
+ if (index >= g_sel_hdr.end && index < g_sel_hdr.begin) {
+ syslog(LOG_ALERT, "plat_sel_get_entry: Wrong Record ID2 %d\n", read_rec_id);
+ return -1;
+ }
+ }
+
+ memcpy(msg->msg, g_sel_data[index].msg, sizeof(sel_msg_t));
+
+ // Return the next record ID in the log
+ *next_rec_id = read_rec_id++;
+ if (*next_rec_id > SEL_INDEX_MAX) {
+ *next_rec_id = SEL_INDEX_MIN;
+ }
+
+ // If this is the last entry in the log, return 0xFFFF
+ if (*next_rec_id == g_sel_hdr.end) {
+ *next_rec_id = SEL_RECID_LAST;
+ }
+
+ return 0;
+}
+
+// Add a new entry in to SEL log
+// IPMI/Section 31.6
+int
+plat_sel_add_entry(sel_msg_t *msg, int *rec_id) {
+ // If the SEL if full, roll over. To keep track of empty condition, use
+ // one empty location less than the max records.
+ if (plat_sel_num_entries() == SEL_RECORDS_MAX) {
+ syslog(LOG_ALERT, "plat_sel_add_entry: SEL rollover\n");
+ if (++g_sel_hdr.begin > SEL_INDEX_MAX) {
+ g_sel_hdr.begin = SEL_INDEX_MIN;
+ }
+ }
+
+ // Update message's time stamp starting at byte 4
+ time_stamp_fill(&msg->msg[3]);
+
+ // Add the enry at end
+ memcpy(g_sel_data[g_sel_hdr.end].msg, msg->msg, sizeof(sel_msg_t));
+
+ // Return the newly added record ID
+ *rec_id = g_sel_hdr.end+1;
+
+ if (file_store_sel_data(*rec_id, msg)) {
+ syslog(LOG_ALERT, "plat_sel_add_entry: file_store_sel_data\n");
+ return -1;
+ }
+
+ // Increment the end pointer
+ if (++g_sel_hdr.end > SEL_INDEX_MAX) {
+ g_sel_hdr.end = SEL_INDEX_MIN;
+ }
+
+ // Update timestamp for add in header
+ time_stamp_fill(g_sel_hdr.ts_add.ts);
+
+ // Store the structure persistently
+ if (file_store_sel_hdr()) {
+ syslog(LOG_ALERT, "plat_sel_add_entry: file_store_sel_hdr\n");
+ return -1;
+ }
+
+ return 0;
+}
+
+// Erase the SEL completely
+// IPMI/Section 31.9
+// Note: To reduce wear/tear, instead of erasing, manipulating the metadata
+int
+plat_sel_erase(int rsv_id) {
+ if (rsv_id != g_rsv_id) {
+ return -1;
+ }
+
+ // Erase SEL Logs
+ g_sel_hdr.begin = SEL_INDEX_MIN;
+ g_sel_hdr.end = SEL_INDEX_MIN;
+
+ // Update timestamp for erase in header
+ time_stamp_fill(g_sel_hdr.ts_erase.ts);
+
+ // Store the structure persistently
+ if (file_store_sel_hdr()) {
+ syslog(LOG_ALERT, "plat_sel_erase: file_store_sel_hdr\n");
+ return -1;
+ }
+
+ return 0;
+}
+
+// To get the erase status while erase happens
+// IPMI/Section 31.2
+// Note: Since we are not doing offline erasing, need not return in-progress state
+int
+plat_sel_erase_status(int rsv_id, sel_erase_stat_t *status) {
+ if (rsv_id != g_rsv_id) {
+ return -1;
+ }
+
+ // Since we do not do any offline erasing, always return erase done
+ *status = SEL_ERASE_DONE;
+
+ return 0;
+}
+
+// Initialize SEL log file
+int
+plat_sel_init(void) {
+ FILE *fp;
+
+ // Check if the file exists or not
+ if (access(SEL_LOG_FILE, F_OK) == 0) {
+ // Since file is present, fetch all the contents to cache
+ if (file_get_sel_hdr()) {
+ syslog(LOG_ALERT, "plat_init_sel: file_get_sel_hdr\n");
+ return -1;
+ }
+
+ if (file_get_sel_data()) {
+ syslog(LOG_ALERT, "plat_init_sel: file_get_sel_data\n");
+ return -1;
+ }
+
+ return 0;
+ }
+
+ // File not present, so create the file
+ fp = fopen(SEL_LOG_FILE, "w+");
+ if (fp == NULL) {
+ syslog(LOG_ALERT, "plat_init_sel: fopen\n");
+ return -1;
+ }
+
+ fclose (fp);
+
+ // Populate SEL Header in to the file
+ g_sel_hdr.magic = SEL_HDR_MAGIC;
+ g_sel_hdr.version = SEL_HDR_VERSION;
+ g_sel_hdr.begin = SEL_INDEX_MIN;
+ g_sel_hdr.end = SEL_INDEX_MIN;
+ memset(g_sel_hdr.ts_add.ts, 0x0, 4);
+ memset(g_sel_hdr.ts_erase.ts, 0x0, 4);
+
+ if (file_store_sel_hdr()) {
+ syslog(LOG_ALERT, "plat_init_sel: file_store_sel_hdr\n");
+ return -1;
+ }
+
+ // Populate SEL Data in to the file
+ for (int i = 1; i <= SEL_RECORDS_MAX; i++) {
+ sel_msg_t msg = {0};
+ if (file_store_sel_data(i, &msg)) {
+ syslog(LOG_ALERT, "plat_init_sel: file_store_sel_data\n");
+ return -1;
+ }
+ }
+
+ return 0;
+}
diff --git a/meta-facebook/meta-wedge/recipes-wedge/ipmid/files/platform/sel.h b/meta-facebook/meta-wedge/recipes-wedge/ipmid/files/platform/sel.h
new file mode 100644
index 0000000..81dbcdf
--- /dev/null
+++ b/meta-facebook/meta-wedge/recipes-wedge/ipmid/files/platform/sel.h
@@ -0,0 +1,51 @@
+/*
+ *
+ * Copyright 2014-present Facebook. All Rights Reserved.
+ *
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef __SEL_H__
+#define __SEL_H__
+
+#include "timestamp.h"
+
+enum {
+ IPMI_SEL_INIT_ERASE = 0xAA,
+ IPMI_SEL_ERASE_STAT = 0x00,
+};
+
+typedef enum {
+ SEL_ERASE_IN_PROG = 0x00,
+ SEL_ERASE_DONE = 0x01,
+} sel_erase_stat_t;
+
+typedef struct {
+ unsigned char msg[16];
+} sel_msg_t;
+
+void plat_sel_ts_recent_add(time_stamp_t *ts);
+void plat_sel_ts_recent_erase(time_stamp_t *ts);
+int plat_sel_num_entries(void);
+int plat_sel_free_space(void);
+int plat_sel_rsv_id();
+int plat_sel_get_entry(int read_rec_id, sel_msg_t *msg, int *next_rec_id);
+int plat_sel_add_entry(sel_msg_t *msg, int *rec_id);
+int plat_sel_erase(int rsv_id);
+int plat_sel_erase_status(int rsv_id, sel_erase_stat_t *status);
+int plat_sel_init(void);
+
+#endif /* __SEL_H__ */
diff --git a/meta-facebook/meta-wedge/recipes-wedge/ipmid/files/platform/sensor.h b/meta-facebook/meta-wedge/recipes-wedge/ipmid/files/platform/sensor.h
new file mode 100644
index 0000000..5d8c11a
--- /dev/null
+++ b/meta-facebook/meta-wedge/recipes-wedge/ipmid/files/platform/sensor.h
@@ -0,0 +1,117 @@
+/*
+ *
+ * Copyright 2014-present Facebook. All Rights Reserved.
+ *
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef __SENSOR_H__
+#define __SENSOR_H__
+
+#include "timestamp.h"
+
+#define IANA_ID_SIZE 3
+#define SENSOR_STR_SIZE 16
+#define SENSOR_OEM_DATA_SIZE 56
+
+// Threshold Sensor Descriptor
+typedef struct {
+ unsigned char owner;
+ unsigned char lun;
+ unsigned char sensor_num;
+ unsigned char ent_id;
+ unsigned char ent_inst;
+ unsigned char sensor_init;
+ unsigned char sensor_caps;
+ unsigned char sensor_type;
+ unsigned char evt_read_type;
+ unsigned char lt_read_mask[2];
+ unsigned char ut_read_mask[2];
+ unsigned char set_thresh_mask[2];
+ unsigned char sensor_units1;
+ unsigned char sensor_units2;
+ unsigned char sensor_units3;
+ unsigned char linear;
+ unsigned char m_val;
+ unsigned char m_tolerance;
+ unsigned char b_val;
+ unsigned char b_accuracy;
+ unsigned char accuracy_dir;
+ unsigned char rb_exp;
+ unsigned char analog_flags;
+ unsigned char nominal;
+ unsigned char normal_max;
+ unsigned char normal_min;
+ unsigned char max_reading;
+ unsigned char min_reading;
+ unsigned char unr_thresh;
+ unsigned char uc_thresh;
+ unsigned char unc_thresh;
+ unsigned char lnr_thresh;
+ unsigned char lc_thresh;
+ unsigned char lnc_thresh;
+ unsigned char pos_hyst;
+ unsigned char neg_hyst;
+ unsigned char oem;
+ unsigned char str_type_len;
+ char str[SENSOR_STR_SIZE];
+} sensor_thresh_t;
+
+// Discrete Sensor Descriptor
+typedef struct {
+ unsigned char owner;
+ unsigned char lun;
+ unsigned char sensor_num;
+ unsigned char ent_id;
+ unsigned char ent_inst;
+ unsigned char sensor_init;
+ unsigned char sensor_caps;
+ unsigned char sensor_type;
+ unsigned char evt_read_type;
+ unsigned char assert_evt_mask[2];
+ unsigned char deassert_evt_mask[2];
+ unsigned char read_evt_mask[2];
+ unsigned char oem;
+ unsigned char str_type_len;
+ char str[SENSOR_STR_SIZE];
+} sensor_disc_t;
+
+// Mgmt. Controller Sensor Descriptor
+typedef struct {
+ unsigned char slave_addr;
+ unsigned char chan_no;
+ unsigned char pwr_state_init;
+ unsigned char dev_caps;
+ unsigned char ent_id;
+ unsigned char ent_inst;
+ unsigned char oem;
+ unsigned char str_type_len;
+ char str[SENSOR_STR_SIZE];
+} sensor_mgmt_t;
+
+// OEM type Sensor Descriptor
+typedef struct {
+ unsigned char mfr_id[IANA_ID_SIZE];
+ unsigned char oem_data[SENSOR_OEM_DATA_SIZE];
+} sensor_oem_t;
+
+void plat_sensor_mgmt_info(int *num, sensor_mgmt_t **p_sensor);
+void plat_sensor_disc_info(int *num, sensor_disc_t **p_sensor);
+void plat_sensor_thresh_info(int *num, sensor_thresh_t **p_sensor);
+void plat_sensor_oem_info(int *num, sensor_oem_t **p_sensor);
+int plat_sensor_init(void);
+
+#endif /* __SENSOR_H__ */
diff --git a/meta-facebook/meta-wedge/recipes-wedge/ipmid/files/platform/timestamp.c b/meta-facebook/meta-wedge/recipes-wedge/ipmid/files/platform/timestamp.c
new file mode 100644
index 0000000..11ac03e
--- /dev/null
+++ b/meta-facebook/meta-wedge/recipes-wedge/ipmid/files/platform/timestamp.c
@@ -0,0 +1,46 @@
+/*
+ *
+ * Copyright 2014-present Facebook. All Rights Reserved.
+ *
+ * This file is a helper file to fill timestamps from platform
+ * used by SEL Logs, SDR records etc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <errno.h>
+#include <syslog.h>
+#include <string.h>
+#include <sys/time.h>
+#include <time.h>
+
+// Local helper function to fill time stamp
+void
+time_stamp_fill(unsigned char *ts) {
+ unsigned int time;
+ struct timeval tv;
+
+ gettimeofday(&tv, NULL);
+
+ time = tv.tv_sec;
+ ts[0] = time & 0xFF;
+ ts[1] = (time >> 8) & 0xFF;
+ ts[2] = (time >> 16) & 0xFF;
+ ts[3] = (time >> 24) & 0xFF;
+
+ return;
+}
diff --git a/meta-facebook/meta-wedge/recipes-wedge/ipmid/files/platform/timestamp.h b/meta-facebook/meta-wedge/recipes-wedge/ipmid/files/platform/timestamp.h
new file mode 100644
index 0000000..430dd23
--- /dev/null
+++ b/meta-facebook/meta-wedge/recipes-wedge/ipmid/files/platform/timestamp.h
@@ -0,0 +1,30 @@
+/*
+ *
+ * Copyright 2014-present Facebook. All Rights Reserved.
+ *
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef __TIMESTAMP_H__
+#define __TIMESTAMP_H__
+
+typedef struct {
+ unsigned char ts[4];
+} time_stamp_t;
+
+void time_stamp_fill(unsigned char *ts);
+
+#endif /* __TIMESTAMP_H__ */
diff --git a/meta-facebook/meta-wedge/recipes-wedge/ipmid/files/platform/wedge/fruid.c b/meta-facebook/meta-wedge/recipes-wedge/ipmid/files/platform/wedge/fruid.c
new file mode 100644
index 0000000..1d9ddda
--- /dev/null
+++ b/meta-facebook/meta-wedge/recipes-wedge/ipmid/files/platform/wedge/fruid.c
@@ -0,0 +1,183 @@
+/*
+ *
+ * Copyright 2015-present Facebook. All Rights Reserved.
+ *
+ * This file provides platform specific implementation of FRUID information
+ *
+ * FRUID specification can be found at
+ * www.intel.com/content/dam/www/public/us/en/documents/product-briefs/platform-management-fru-document-rev-1-2-feb-2013.pdf
+ *
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include "../fruid.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <errno.h>
+#include <syslog.h>
+#include <string.h>
+#include <facebook/wedge_eeprom.h>
+
+#define WEDGE_FRUID_SIZE 0x100
+
+#define COMMON_HDR_VER 1
+#define PROD_INFO_VER 1
+
+#define PROD_INFO_AREA_OFFSET 0x10
+#define PROD_INFO_CKSUM_OFFSET (PROD_INFO_AREA_OFFSET + 1)
+#define LANG_CODE_ENGLISH 25
+#define TYPE_STR 0xC0
+#define TYPE_LAST 0xC1
+#define ZERO_CKSUM_CONST 0x100
+#define LEN_BYTE_SIZE 8
+
+typedef struct _fruid_common_hdr_t {
+ unsigned char ver;
+ unsigned char internal_use_area_offset;
+ unsigned char chassis_info_area_offset;
+ unsigned char board_info_area_offset;
+ unsigned char prod_info_area_offset;
+ unsigned char multi_record_area_offset;
+ unsigned char padding;
+ unsigned char cksum;
+} fruid_common_hdr_t;
+
+// Global structures
+static unsigned char g_fruid[WEDGE_FRUID_SIZE] = {0};
+
+static void
+populate_fruid(void) {
+
+ memset(&g_fruid, sizeof(g_fruid), 0);
+
+ fruid_common_hdr_t *chdr = g_fruid;
+
+ // Set Common Header version
+ chdr->ver = COMMON_HDR_VER;
+
+ // Product Info Area offset in multiples of 8 bytes
+ chdr->prod_info_area_offset = PROD_INFO_AREA_OFFSET/LEN_BYTE_SIZE;
+
+ // Calculate zero checksum
+ chdr->cksum = chdr->ver + chdr->prod_info_area_offset;
+ chdr->cksum = ZERO_CKSUM_CONST - chdr->cksum;
+
+ // Retrieve Wedge EEPROM content
+ struct wedge_eeprom_st eeprom;
+ int rc = 0;
+ rc = wedge_eeprom_parse(NULL, &eeprom);
+ if (rc)
+ {
+ syslog(LOG_ALERT, "populate_fruid: wedge_eeprom_parse returns %d\n", rc);
+ return;
+ }
+
+ // Start index at beginning of product info area
+ int i = PROD_INFO_AREA_OFFSET;
+ g_fruid[i++] = PROD_INFO_VER;
+ g_fruid[i++] = 0x00; // prod area length; filled at end
+ g_fruid[i++] = LANG_CODE_ENGLISH;
+
+#define _APPEND_STR_VALUE(name) do { \
+ if (sizeof(name) < 1 || i + 1 + sizeof(name) >= sizeof(g_fruid)) { \
+ break; \
+ } \
+ g_fruid[i++] = TYPE_STR + sizeof(name); \
+ memcpy(&g_fruid[i], name, sizeof(name)); \
+ i += sizeof(name); \
+} while(0)
+
+ // Fill system manufacturer field
+
+ _APPEND_STR_VALUE(eeprom.fbw_system_manufacturer);
+
+ // Fill product name field
+ _APPEND_STR_VALUE(eeprom.fbw_product_name);
+
+ // Fill product number field
+ _APPEND_STR_VALUE(eeprom.fbw_product_number);
+
+ // convert product version to string and fill
+ char vbuf[5] = {0};
+ snprintf(vbuf, sizeof(vbuf), "%0X", eeprom.fbw_product_version);
+ _APPEND_STR_VALUE(vbuf);
+
+ // Fill product serial number field
+ _APPEND_STR_VALUE(eeprom.fbw_product_serial);
+
+ // Fill product asset tag field
+ _APPEND_STR_VALUE(eeprom.fbw_product_asset);
+
+ // Fill fruid file with dummy file name
+ char fruid_file_name[] = "fruid_1.0";
+ _APPEND_STR_VALUE(fruid_file_name);
+
+ // Field to indicate the last entry
+ g_fruid[i++] = TYPE_LAST;
+
+ // length of the area in multiples of 8 bytes
+ int len = i-PROD_INFO_AREA_OFFSET+1;
+ if (len % LEN_BYTE_SIZE){
+ // For non-multiple of 8 bytes, add one for partial data
+ g_fruid[PROD_INFO_CKSUM_OFFSET] = len/LEN_BYTE_SIZE + 1;
+ // And also increment index to keep checksum byte
+ i += (len % LEN_BYTE_SIZE);
+ } else {
+ g_fruid[PROD_INFO_CKSUM_OFFSET] = len/LEN_BYTE_SIZE;
+ }
+
+ // Calculate zero checksum by adding all the values in product info area
+ for (int j = PROD_INFO_AREA_OFFSET; j < i; j++) {
+ g_fruid[i] += g_fruid[j];
+ }
+
+ // Calculate final cksum by subtraction
+ g_fruid[i] = ZERO_CKSUM_CONST - g_fruid[i];
+
+#undef _APPEND_STR_VALUE
+
+ return;
+}
+
+// Access functions for FRUID
+int
+plat_fruid_size(void) {
+ return WEDGE_FRUID_SIZE;
+}
+
+int
+plat_fruid_data(int offset, int count, unsigned char *data) {
+ // Check for the boundary condition
+ if ((offset + count) > WEDGE_FRUID_SIZE) {
+ return -1;
+ }
+
+ // Copy the FRUID content from the global structure
+ memcpy(data, &(g_fruid[offset]), count);
+
+ return 0;
+}
+
+// Initialize FRUID
+int
+plat_fruid_init(void) {
+
+ // Populate FRUID global structure
+ populate_fruid();
+
+ return 0;
+}
diff --git a/meta-facebook/meta-wedge/recipes-wedge/ipmid/files/platform/wedge/sensor.c b/meta-facebook/meta-wedge/recipes-wedge/ipmid/files/platform/wedge/sensor.c
new file mode 100644
index 0000000..ce3d4fb
--- /dev/null
+++ b/meta-facebook/meta-wedge/recipes-wedge/ipmid/files/platform/wedge/sensor.c
@@ -0,0 +1,371 @@
+/*
+ *
+ * Copyright 2014-present Facebook. All Rights Reserved.
+ *
+ * This file provides platform specific implementation of sensor information
+ *
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include "../sensor.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <errno.h>
+#include <syslog.h>
+#include <string.h>
+
+#define SENSOR_MGMT_MAX 1
+#define SENSOR_DISC_MAX 8
+#define SENSOR_THRESH_MAX 1
+#define SENSOR_OEM_MAX 1
+
+#define BMC_SLAVE_ADDR 0x20
+
+typedef struct {
+ unsigned char num;
+ sensor_mgmt_t sensor[SENSOR_MGMT_MAX];
+} sensor_mgmt_info_t;
+
+typedef struct {
+ unsigned char num;
+ sensor_disc_t sensor[SENSOR_DISC_MAX];
+} sensor_disc_info_t;
+
+typedef struct {
+ unsigned char num;
+ sensor_thresh_t sensor[SENSOR_THRESH_MAX];
+} sensor_thresh_info_t;
+
+typedef struct {
+ unsigned char num;
+ sensor_oem_t sensor[SENSOR_OEM_MAX];
+} sensor_oem_info_t;
+
+// Global structures
+static sensor_mgmt_info_t g_sensor_mgmt = {0};
+static sensor_disc_info_t g_sensor_disc = {0};
+static sensor_thresh_info_t g_sensor_thresh = {0};
+static sensor_oem_info_t g_sensor_oem = {0};
+
+static void
+populate_mgmt_sensors(void) {
+ sensor_mgmt_t sensor = {0};
+
+ // Add record for the AST2100 BMC
+ sensor.slave_addr = BMC_SLAVE_ADDR;
+ sensor.chan_no = 0x0; // Primary BMC controller
+
+ // Init Agent = false
+ sensor.pwr_state_init = 0x00;
+
+ // FRUID = true, SEL = true, SDR = true, Sensor = true
+ sensor.dev_caps = 0x0F;
+
+ // Device ID string
+ // Type - 0xC0: ASCII, Length - 0x09
+ sensor.str_type_len = 0xC0 + 0x09;
+ strncpy(sensor.str, "Wedge-BMC", 0x09);
+
+ // Add this sensor to the global table
+ if (g_sensor_mgmt.num >= SENSOR_MGMT_MAX) {
+ syslog(LOG_ALERT, "populate_mgmt_sensors: num exceeded\n");
+ return;
+ }
+
+ memcpy(&g_sensor_mgmt.sensor[g_sensor_mgmt.num], &sensor, sizeof(sensor_mgmt_t));
+
+ g_sensor_mgmt.num++;
+
+ return;
+}
+
+static void
+populate_disc_sensors(void) {
+
+ sensor_disc_t sensor = {0};
+
+ // Sensor uS Status
+ // Sensor# 0x10
+ // EntitiyId# 0xD0, EntityInst# 0x00
+ // Sensor Type# Chassis 0x18
+ // Event Read/Type# OEM 0x70
+ sensor.owner= BMC_SLAVE_ADDR;
+ sensor.lun = 0x00;
+ sensor.sensor_num = 0x10;
+
+ sensor.ent_id = 0xD0;
+ sensor.ent_inst = 0x00;
+ // Enable Scanning, Enable Events
+ sensor.sensor_init = 0x63;
+ // Supports Auto Re-Arm
+ sensor.sensor_caps = 0x40;
+ sensor.sensor_type = 0x18;
+ sensor.evt_read_type = 0x70;
+ // 1-bit for CPU0 Thermal Trip
+ sensor.assert_evt_mask[0] = 0x04;
+ sensor.deassert_evt_mask[0] = 0x00;
+ sensor.read_evt_mask[0] = 0x04;
+
+ // Device ID string
+ // Type - 0xC0: ASCII, Length - 12
+ sensor.str_type_len = 0xC0 + 9;
+ strncpy(sensor.str, "uS-Status", 9);
+
+ // Add this sensor to the global table
+ if (g_sensor_disc.num >= SENSOR_DISC_MAX) {
+ syslog(LOG_ALERT, "populate_disc_sensors: num exceeded\n");
+ return;
+ }
+
+ memcpy(&g_sensor_disc.sensor[g_sensor_disc.num], &sensor, sizeof(sensor_disc_t));
+
+ g_sensor_disc.num++;
+
+ // Sensor SEL Status
+ // Sensor# 0x5F
+ // EntitiyId# 0xD0, EntityInst# 0x02
+ // Sensor Type# OEM: 0xC0
+ // Event Read/Type# Sensor Specific: 0x6F
+ sensor.owner= BMC_SLAVE_ADDR;
+ sensor.lun = 0x00;
+ sensor.sensor_num = 0x5F;
+
+ sensor.ent_id = 0xD0;
+ sensor.ent_inst = 0x02;
+ // Enable Scanning, Enable Events
+ sensor.sensor_init = 0x63;
+ // Supports Auto Re-Arm
+ sensor.sensor_caps = 0x40;
+ sensor.sensor_type = 0xC0;
+ sensor.evt_read_type = 0x6F;
+ // SEL Clear(bit1), SEL Rollover(bit8)
+ sensor.assert_evt_mask[0] = 0x02;
+ sensor.assert_evt_mask[1] = 0x01;
+ sensor.deassert_evt_mask[0] = 0x00;
+ sensor.deassert_evt_mask[1] = 0x00;
+ sensor.read_evt_mask[0] = 0x02;
+ sensor.read_evt_mask[1] = 0x01;
+
+ // Device ID string
+ // Type - 0xC0: ASCII, Length - 12
+ sensor.str_type_len = 0xC0 + 10;
+ strncpy(sensor.str, "SEL-Status", 10);
+
+ // Add this sensor to the global table
+ if (g_sensor_disc.num >= SENSOR_DISC_MAX) {
+ syslog(LOG_ALERT, "populate_disc_sensors: num exceeded\n");
+ return;
+ }
+
+ memcpy(&g_sensor_disc.sensor[g_sensor_disc.num], &sensor, sizeof(sensor_disc_t));
+
+ g_sensor_disc.num++;
+
+
+ // Sensor WDT
+ // Sensor# 0x60
+ // EntitiyId# 0xD0, EntityInst# 0x03
+ // Sensor Type# WDT2: 0x23
+ // Event Read/Type# Sensor Specific: 0x6F
+ sensor.owner= BMC_SLAVE_ADDR;
+ sensor.lun = 0x00;
+ sensor.sensor_num = 0x60;
+
+ sensor.ent_id = 0xD0;
+ sensor.ent_inst = 0x03;
+ // Enable Scanning, Enable Events
+ sensor.sensor_init = 0x63;
+ // Supports Auto Re-Arm
+ sensor.sensor_caps = 0x40;
+ sensor.sensor_type = 0x23;
+ sensor.evt_read_type = 0x6F;
+ // 5 bits for expiry, reset, pwrdown, pwrcycle, timer
+ sensor.assert_evt_mask[0] = 0x0F;
+ sensor.assert_evt_mask[1] = 0x01;
+ sensor.deassert_evt_mask[0] = 0x00;
+ sensor.deassert_evt_mask[1] = 0x00;
+ sensor.read_evt_mask[0] = 0x0F;
+ sensor.read_evt_mask[1] = 0x01;
+
+ // Device ID string
+ // Type - 0xC0: ASCII, Length - 12
+ sensor.str_type_len = 0xC0 + 3;
+ strncpy(sensor.str, "WDT", 3);
+
+ // Add this sensor to the global table
+ if (g_sensor_disc.num >= SENSOR_DISC_MAX) {
+ syslog(LOG_ALERT, "populate_disc_sensors: num exceeded\n");
+ return;
+ }
+
+ memcpy(&g_sensor_disc.sensor[g_sensor_disc.num], &sensor, sizeof(sensor_disc_t));
+
+ g_sensor_disc.num++;
+
+
+ // Sensor Chassis Pwr Sts
+ // Sensor# 0x70
+ // EntitiyId# 0x15, EntityInst# 0x00
+ // Sensor Type# OEM: 0xC8
+ // Event Read/Type# Sensor Specific: 0x6F
+ sensor.owner= BMC_SLAVE_ADDR;
+ sensor.lun = 0x00;
+ sensor.sensor_num = 0x70;
+
+ sensor.ent_id = 0x15;
+ sensor.ent_inst = 0x00;
+ // Enable Scanning, Enable Events
+ sensor.sensor_init = 0x63;
+ // Supports Auto Re-Arm
+ sensor.sensor_caps = 0x40;
+ sensor.sensor_type = 0xC8;
+ sensor.evt_read_type = 0x6F;
+ // 6 bits for pwroff, pwrcycle, pwron, softdown, ac-lost, hard-reset
+ sensor.assert_evt_mask[0] = 0x3F;
+ sensor.deassert_evt_mask[0] = 0x00;
+ sensor.read_evt_mask[0] = 0x3F;
+
+ // Device ID string
+ // Type - 0xC0: ASCII, Length - 12
+ sensor.str_type_len = 0xC0 + 13;
+ strncpy(sensor.str, "CH-Pwr-Status", 13);
+
+ // Add this sensor to the global table
+ if (g_sensor_disc.num >= SENSOR_DISC_MAX) {
+ syslog(LOG_ALERT, "populate_disc_sensors: num exceeded\n");
+ return;
+ }
+
+ memcpy(&g_sensor_disc.sensor[g_sensor_disc.num], &sensor, sizeof(sensor_disc_t));
+
+ g_sensor_disc.num++;
+
+ // Sensor CPU DIMM Hot
+ // Sensor# 0xB3
+ // EntitiyId# 0xD0, EntityInst# 0x05
+ // Sensor Type# OEM 0xC6
+ // Event Read/Type# Sensor Specific 6Fh
+ sensor.owner= BMC_SLAVE_ADDR;
+ sensor.lun = 0x00;
+ sensor.sensor_num = 0xB3;
+
+ sensor.ent_id = 0xD0;
+ sensor.ent_inst = 0x05;
+ // Enable Scanning, Enable Events
+ sensor.sensor_init = 0x63;
+ // Supports Auto Re-Arm
+ sensor.sensor_caps = 0x40;
+ sensor.sensor_type = 0xC6;
+ sensor.evt_read_type = 0x6F;
+ // Two bits for CPU Hot, DIMM Hot
+ sensor.assert_evt_mask[0] = 0x05;
+ sensor.deassert_evt_mask[0] = 0x05;
+ sensor.read_evt_mask[0] = 0x05;
+
+ // Device ID string
+ // Type - 0xC0: ASCII, Length - 12
+ sensor.str_type_len = 0xC0 + 12;
+ strncpy(sensor.str, "CPU_DIMM_HOT", 12);
+
+ // Add this sensor to the global table
+ if (g_sensor_disc.num >= SENSOR_DISC_MAX) {
+ syslog(LOG_ALERT, "populate_disc_sensors: num exceeded\n");
+ return;
+ }
+
+ memcpy(&g_sensor_disc.sensor[g_sensor_disc.num], &sensor, sizeof(sensor_disc_t));
+
+ g_sensor_disc.num++;
+
+ // Sensor PMBus Status Word Low
+ // Sensor PMBus Status Word High
+ // Sensor PMBus Status MFR
+ // Sensor PMBus Status Input
+ // Sensor NTP Status
+ // Sensor# 0xED
+ // EntitiyId# 0x35, EntityInst# 0x00
+ // Sensor Type# OEM 0xC7
+ // Event Read/Type# Sensor Specific 6Fh
+ sensor.owner= BMC_SLAVE_ADDR;
+ sensor.lun = 0x00;
+ sensor.sensor_num = 0xED;
+
+ sensor.ent_id = 0x35;
+ sensor.ent_inst = 0x00;
+ // Enable Scanning, Enable Events
+ sensor.sensor_init = 0x63;
+ // Supports Auto Re-Arm
+ sensor.sensor_caps = 0x40;
+ sensor.sensor_type = 0xC7;
+ sensor.evt_read_type = 0x6F;
+ // 1-bit for date/time sync failed
+ sensor.assert_evt_mask[0] = 0x01;
+ sensor.deassert_evt_mask[0] = 0x00;
+ sensor.read_evt_mask[0] = 0x01;
+
+ // Device ID string
+ // Type - 0xC0: ASCII, Length - 10
+ sensor.str_type_len = 0xC0 + 12;
+ strncpy(sensor.str, "NTP-Status", 10);
+
+ // Add this sensor to the global table
+ if (g_sensor_disc.num >= SENSOR_DISC_MAX) {
+ syslog(LOG_ALERT, "populate_disc_sensors: num exceeded\n");
+ return;
+ }
+
+ memcpy(&g_sensor_disc.sensor[g_sensor_disc.num], &sensor, sizeof(sensor_disc_t));
+
+ g_sensor_disc.num++;
+
+ return;
+}
+
+// Access functions for Sensor Table
+void
+plat_sensor_mgmt_info(int *p_num, sensor_mgmt_t **p_sensor) {
+ *p_num = g_sensor_mgmt.num;
+ *p_sensor = g_sensor_mgmt.sensor;
+}
+
+void
+plat_sensor_disc_info(int *p_num, sensor_disc_t **p_sensor) {
+ *p_num = g_sensor_disc.num;
+ *p_sensor = g_sensor_disc.sensor;
+}
+
+void
+plat_sensor_thresh_info(int *p_num, sensor_thresh_t **p_sensor) {
+ *p_num = g_sensor_thresh.num;
+ *p_sensor = g_sensor_thresh.sensor;
+}
+
+void
+plat_sensor_oem_info(int *p_num, sensor_oem_t **p_sensor) {
+ *p_num = g_sensor_oem.num;
+ *p_sensor = g_sensor_oem.sensor;
+}
+
+// Initialize Sensor Table
+int
+plat_sensor_init(void) {
+
+ // Populate all Sensors
+ populate_mgmt_sensors();
+ populate_disc_sensors();
+
+ return 0;
+}
diff --git a/meta-facebook/meta-wedge/recipes-wedge/ipmid/files/setup-ipmid.sh b/meta-facebook/meta-wedge/recipes-wedge/ipmid/files/setup-ipmid.sh
new file mode 100644
index 0000000..b1fbbb1
--- /dev/null
+++ b/meta-facebook/meta-wedge/recipes-wedge/ipmid/files/setup-ipmid.sh
@@ -0,0 +1,16 @@
+#!/bin/sh
+#
+# Copyright 2014-present Facebook. All Rights Reserved.
+#
+### BEGIN INIT INFO
+# Provides: setup-ipmid
+# Required-Start:
+# Required-Stop:
+# Default-Start: S
+# Default-Stop:
+# Short-Description: Set IPMI Message handler
+### END INIT INFO
+
+echo -n "Setup IPMI message handler... "
+/usr/local/bin/ipmid
+echo "done."
diff --git a/meta-facebook/meta-wedge/recipes-wedge/ipmid/ipmid_0.1.bb b/meta-facebook/meta-wedge/recipes-wedge/ipmid/ipmid_0.1.bb
new file mode 100644
index 0000000..3f9c4a7
--- /dev/null
+++ b/meta-facebook/meta-wedge/recipes-wedge/ipmid/ipmid_0.1.bb
@@ -0,0 +1,54 @@
+# Copyright 2014-present Facebook. All Rights Reserved.
+
+SUMMARY = "IPMI Daemon"
+DESCRIPTION = "Daemon to handle IPMI Messages."
+SECTION = "base"
+PR = "r1"
+LICENSE = "GPLv2"
+LIC_FILES_CHKSUM = "file://ipmid.c;beginline=8;endline=20;md5=da35978751a9d71b73679307c4d296ec"
+
+
+DEPENDS_append = "libwedge-eeprom update-rc.d-native"
+
+SRC_URI = "file://Makefile \
+ file://setup-ipmid.sh \
+ file://ipmid.c \
+ file://platform/timestamp.c \
+ file://platform/timestamp.h \
+ file://platform/sel.c \
+ file://platform/sel.h \
+ file://platform/sdr.c \
+ file://platform/sdr.h \
+ file://platform/sensor.h \
+ file://platform/fruid.h \
+ file://platform/wedge/sensor.c \
+ file://platform/wedge/fruid.c \
+ "
+
+S = "${WORKDIR}"
+
+binfiles = "ipmid"
+
+pkgdir = "ipmid"
+
+do_install() {
+ dst="${D}/usr/local/fbpackages/${pkgdir}"
+ bin="${D}/usr/local/bin"
+ install -d $dst
+ install -d $bin
+ install -m 755 ipmid ${dst}/ipmid
+ ln -snf ../fbpackages/${pkgdir}/ipmid ${bin}/ipmid
+ install -d ${D}${sysconfdir}/init.d
+ install -d ${D}${sysconfdir}/rcS.d
+ install -m 755 setup-ipmid.sh ${D}${sysconfdir}/init.d/setup-ipmid.sh
+ update-rc.d -r ${D} setup-ipmid.sh start 64 S .
+}
+
+FBPACKAGEDIR = "${prefix}/local/fbpackages"
+
+FILES_${PN} = "${FBPACKAGEDIR}/ipmid ${prefix}/local/bin ${sysconfdir} "
+
+# Inhibit complaints about .debug directories for the fand binary:
+
+INHIBIT_PACKAGE_DEBUG_SPLIT = "1"
+INHIBIT_PACKAGE_STRIP = "1"
diff --git a/meta-facebook/meta-wedge/recipes-wedge/lm_sensors/files/wedge.conf b/meta-facebook/meta-wedge/recipes-wedge/lm_sensors/files/wedge.conf
new file mode 100644
index 0000000..44b6595
--- /dev/null
+++ b/meta-facebook/meta-wedge/recipes-wedge/lm_sensors/files/wedge.conf
@@ -0,0 +1,71 @@
+
+bus "i2c-3" "ast_i2c.3"
+
+bus "i2c-4" "ast_i2c.4"
+
+bus "i2c-6" "ast_i2c.6"
+
+chip "tmp75-i2c-3-48"
+ label temp1 "Inlet Temp"
+
+chip "tmp75-i2c-3-49"
+ label temp1 "Switch Temp"
+
+chip "tmp75-i2c-3-4a"
+ label temp1 "Outlet Temp"
+
+chip "tmp75-i2c-4-4c"
+ label temp1 "Microserver Ambient Temp"
+
+chip "max127-i2c-6-28"
+ label in0 "+1 Voltage"
+ label in1 "+2.5 Voltage"
+ ignore in2
+ label in3 "+1 Voltage"
+ ignore in4
+ label in5 "+3.3 Voltage"
+ label in6 "+5 Voltage"
+ ignore in7
+
+chip "ast_pwm-*"
+ label fan1 "Fan 2 front"
+ label fan2 "Fan 3 front"
+ label fan3 "Fan 1 front"
+ label fan4 "Fan 0 front"
+ label fan5 "Fan 2 rear"
+ label fan6 "Fan 3 rear"
+ label fan7 "Fan 1 rear"
+ label fan8 "Fan 0 rear"
+ ignore fan9
+ ignore fan10
+ ignore fan11
+ ignore fan12
+ ignore fan13
+ ignore fan14
+ ignore fan15
+ ignore fan16
+
+chip "fb_panther_plus-*"
+ label temp1 "CPU Temp"
+ label temp2 "DIMM0 Temp"
+ ignore temp3
+ ignore temp4
+ ignore temp5
+
+chip "ast_adc-isa-0000"
+ ignore in0
+ ignore in1
+ ignore in2
+ ignore in3
+ ignore in4
+ label in5 "+1 Core Voltage"
+ label in6 "+1 Analog Voltage"
+ label in7 "+5 Voltage"
+ label in8 "+3.3 Voltage"
+ label in9 "+2.5 Voltage"
+ ignore in10
+ ignore in11
+ ignore in12
+ ignore in13
+ ignore in14
+ ignore in15
diff --git a/meta-facebook/meta-wedge/recipes-wedge/lm_sensors/lmsensors_%.bbappend b/meta-facebook/meta-wedge/recipes-wedge/lm_sensors/lmsensors_%.bbappend
new file mode 100644
index 0000000..35433ae
--- /dev/null
+++ b/meta-facebook/meta-wedge/recipes-wedge/lm_sensors/lmsensors_%.bbappend
@@ -0,0 +1,10 @@
+
+FILESEXTRAPATHS_prepend := "${THISDIR}/files:"
+
+SRC_URI += "file://wedge.conf \
+ "
+
+do_install_append() {
+ install -d ${D}${sysconfdir}/sensors.d
+ install -m 644 ../wedge.conf ${D}${sysconfdir}/sensors.d/wedge.conf
+}
diff --git a/meta-facebook/meta-wedge/recipes-wedge/oob-nic/oob-nic/src/Makefile b/meta-facebook/meta-wedge/recipes-wedge/oob-nic/oob-nic/src/Makefile
new file mode 100644
index 0000000..0c9f49f
--- /dev/null
+++ b/meta-facebook/meta-wedge/recipes-wedge/oob-nic/oob-nic/src/Makefile
@@ -0,0 +1,13 @@
+# Copyright 2014-present Facebook. All Rights Reserved.
+all: oob-nic i2craw
+
+oob-nic: main.o nic.o intf.o ll_map.o libnetlink.o
+ $(CC) -o $@ $^ $(LDFLAGS) -lwedge_eeprom
+
+i2craw: i2craw.o
+ $(CC) -o $@ $^ $(LDFLAGS)
+
+.PHONY: clean
+
+clean:
+ rm -rf *.o oob-nic i2craw
diff --git a/meta-facebook/meta-wedge/recipes-wedge/oob-nic/oob-nic/src/README b/meta-facebook/meta-wedge/recipes-wedge/oob-nic/oob-nic/src/README
new file mode 100644
index 0000000..f46971f
--- /dev/null
+++ b/meta-facebook/meta-wedge/recipes-wedge/oob-nic/oob-nic/src/README
@@ -0,0 +1,10 @@
+
+TODO:
+
+1. Currently, we poll the SMbus instead of rely on the ALERT. The kernel does not handle the ALERT either other than just a print out.
+
+2. Maximum fragment is 32
+
+3. We use libnetlink for bring interface up and setting MAC. That increases the binary by about 50k and also we copied about 5 files from iproute2 here for that. We might be able to get away this by using some non-iproute2 API
+
+4. The dependency in the Makefile does not consider .h
diff --git a/meta-facebook/meta-wedge/recipes-wedge/oob-nic/oob-nic/src/etc/oob-nic.sh b/meta-facebook/meta-wedge/recipes-wedge/oob-nic/oob-nic/src/etc/oob-nic.sh
new file mode 100644
index 0000000..35e1a2a
--- /dev/null
+++ b/meta-facebook/meta-wedge/recipes-wedge/oob-nic/oob-nic/src/etc/oob-nic.sh
@@ -0,0 +1,103 @@
+#! /bin/sh
+#
+# Copyright 2014-present Facebook. All Rights Reserved.
+#
+# This program file is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by the
+# Free Software Foundation; version 2 of the License.
+#
+# This program is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+# for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program in a file named COPYING; if not, write to the
+# Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor,
+# Boston, MA 02110-1301 USA
+#
+
+### BEGIN INIT INFO
+# Provides: oob-nic
+# Required-Start:
+# Required-Stop:
+# Default-Start: S
+# Default-Stop: 0 6
+# Short-Description: One of the first scripts to be executed. Starts or stops
+# the OOB NIC.
+#
+### END INIT INFO
+
+PATH=/sbin:/bin:/usr/sbin:/usr/bin
+DAEMON=/usr/sbin/oob-nic
+NAME=oob-nic
+DESC="OOB NIC Driver"
+
+# source function library
+. /etc/init.d/functions
+
+test -f $DAEMON || exit 0
+
+# enable the isolation buffer
+. /usr/local/fbpackages/utils/ast-functions
+wedge_iso_buf_enable
+
+fix_etc_interfaces() {
+ local intf_conf rev
+ intf_conf="/etc/network/interfaces"
+ rev=$(wedge_board_rev)
+ if [ $rev -lt 3 ]; then
+ if ! grep oob $intf_conf > /dev/null 2>&1; then
+ echo >> $intf_conf
+ echo "auto oob" >> $intf_conf
+ echo "iface oob inet dhcp" >> $intf_conf
+ fi
+ fi
+}
+
+STOPPER=
+ACTION="$1"
+
+case "$ACTION" in
+ start)
+ echo -n "Starting $DESC: "
+ if [ ! -d /dev/net ]
+ then
+ mkdir /dev/net
+ fi
+ if [ ! -f /dev/net/tun ]
+ then
+ mknod /dev/net/tun c 10 200
+ chmod 666 /dev/net/tun
+ fi
+ fix_etc_interfaces
+ $DAEMON > /dev/null 2>&1 &
+ echo "$NAME."
+ ;;
+ stop)
+ echo -n "Stopping $DESC: "
+ start-stop-daemon --stop --quiet --exec $DAEMON
+ echo "$NAME."
+ ;;
+ restart|force-reload)
+ echo -n "Restarting $DESC: "
+ start-stop-daemon --stop --quiet --exec $DAEMON
+ sleep 1
+ fix_etc_interfaces
+ $DAEMON > /dev/null 2>&1 &
+ echo "$NAME."
+ ;;
+ status)
+ status $DAEMON
+ exit $?
+ ;;
+ *)
+ N=${0##*/}
+ N=${N#[SK]??}
+ echo "Usage: $N {start|stop|status|restart|force-reload}" >&2
+ exit 1
+ ;;
+esac
+
+exit 0
diff --git a/meta-facebook/meta-wedge/recipes-wedge/oob-nic/oob-nic/src/hlist.h b/meta-facebook/meta-wedge/recipes-wedge/oob-nic/oob-nic/src/hlist.h
new file mode 100644
index 0000000..5e89765
--- /dev/null
+++ b/meta-facebook/meta-wedge/recipes-wedge/oob-nic/oob-nic/src/hlist.h
@@ -0,0 +1,73 @@
+/*
+ * Note: Original file from iproute2 package
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#ifndef __HLIST_H__
+#define __HLIST_H__ 1
+/* Hash list stuff from kernel */
+
+#include <stddef.h>
+
+#define container_of(ptr, type, member) ({ \
+ const typeof( ((type *)0)->member ) *__mptr = (ptr); \
+ (type *)( (char *)__mptr - offsetof(type,member) );})
+
+struct hlist_head {
+ struct hlist_node *first;
+};
+
+struct hlist_node {
+ struct hlist_node *next, **pprev;
+};
+
+static inline void hlist_del(struct hlist_node *n)
+{
+ struct hlist_node *next = n->next;
+ struct hlist_node **pprev = n->pprev;
+ *pprev = next;
+ if (next)
+ next->pprev = pprev;
+}
+
+static inline void hlist_add_head(struct hlist_node *n, struct hlist_head *h)
+{
+ struct hlist_node *first = h->first;
+ n->next = first;
+ if (first)
+ first->pprev = &n->next;
+ h->first = n;
+ n->pprev = &h->first;
+}
+
+#define hlist_for_each(pos, head) \
+ for (pos = (head)->first; pos ; pos = pos->next)
+
+
+#define hlist_for_each_safe(pos, n, head) \
+ for (pos = (head)->first; pos && ({ n = pos->next; 1; }); \
+ pos = n)
+
+#define hlist_entry_safe(ptr, type, member) \
+ ({ typeof(ptr) ____ptr = (ptr); \
+ ____ptr ? hlist_entry(____ptr, type, member) : NULL; \
+ })
+
+#define hlist_for_each_entry(pos, head, member) \
+ for (pos = hlist_entry_safe((head)->first, typeof(*(pos)), member);\
+ pos; \
+ pos = hlist_entry_safe((pos)->member.next, typeof(*(pos)), member))
+
+#endif /* __HLIST_H__ */
diff --git a/meta-facebook/meta-wedge/recipes-wedge/oob-nic/oob-nic/src/i2craw.c b/meta-facebook/meta-wedge/recipes-wedge/oob-nic/oob-nic/src/i2craw.c
new file mode 100644
index 0000000..f9d499b
--- /dev/null
+++ b/meta-facebook/meta-wedge/recipes-wedge/oob-nic/oob-nic/src/i2craw.c
@@ -0,0 +1,245 @@
+/*
+ * Copyright 2004-present Facebook. All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <errno.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/ioctl.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <stdint.h>
+
+#include "facebook/i2c-dev.h"
+#include "facebook/log.h"
+
+void usage(const char *prog) {
+ printf("Usage: %s [options] <bus number> <slave address>\n", prog);
+ printf("\n Options:\n"
+ "\n\t-w 'bytes to write':\n"
+ "\t\t i2c write\n"
+ "\n\t-r <number of bytes to read>:\n"
+ "\t\t if 0 is provided, the first byte of read is used to determine\n"
+ "\t\t how many bytes more to read\n"
+ "\n\t-p:\n"
+ "\t\t Use PEC\n"
+ "\n\t-h:\n"
+ "\t\t Print this help\n"
+ "\n Note: if both '-w' and '-r' are specified, write will be"
+ "\n performed first, followed by read\n");
+}
+
+#define MAX_BYTES 255
+
+int g_use_pec = 0;
+int g_has_write = 0;
+int g_n_write = 0;
+uint8_t g_write_bytes[MAX_BYTES];
+int g_has_read = 0;
+int g_n_read = -1;
+uint8_t g_read_bytes[MAX_BYTES];
+uint8_t g_bus = -1;
+uint8_t g_slave_addr = 0xff;
+
+static int parse_byte_string(const char *str) {
+ const char *startptr = str;
+ char *endptr;
+ int total = 0;
+ unsigned long val;
+
+ do {
+ val = strtoul(startptr, &endptr, 0);
+ if (startptr == endptr) {
+ printf("'%s' is invalid\n", str);
+ return -1;
+ }
+ if (val > MAX_BYTES) {
+ printf("'%s' is invalid\n", str);
+ return -1;
+ }
+ g_write_bytes[total++] = val;
+ if (*endptr == '\0') {
+ break;
+ }
+ if (total >= MAX_BYTES) {
+ printf("'%s' is invalid\n", str);
+ return -1;
+ }
+ startptr = endptr;
+ } while(1);
+
+ return total;
+}
+
+static int i2c_open() {
+ int fd;
+ char fn[32];
+ int rc;
+
+ snprintf(fn, sizeof(fn), "/dev/i2c-%d", g_bus);
+ fd = open(fn, O_RDWR);
+ if (fd == -1) {
+ LOG_ERR(errno, "Failed to open i2c device %s", fn);
+ return -1;
+ }
+
+ rc = ioctl(fd, I2C_SLAVE, g_slave_addr);
+ if (rc < 0) {
+ LOG_ERR(errno, "Failed to open slave @ address 0x%x", g_slave_addr);
+ close(fd);
+ }
+
+ return fd;
+}
+
+static int i2c_io(int fd) {
+ struct i2c_rdwr_ioctl_data data;
+ struct i2c_msg msg[2];
+ int n_msg = 0;
+ int rc;
+
+ memset(&msg, 0, sizeof(msg));
+
+ if (g_has_write) {
+ msg[n_msg].addr = g_slave_addr;
+ msg[n_msg].flags = (g_use_pec) ? I2C_CLIENT_PEC : 0;
+ msg[n_msg].len = g_n_write;
+ msg[n_msg].buf = g_write_bytes;
+ n_msg++;
+ }
+
+ if (g_has_read) {
+ msg[n_msg].addr = g_slave_addr;
+ msg[n_msg].flags = I2C_M_RD
+ | ((g_use_pec) ? I2C_CLIENT_PEC : 0)
+ | ((g_n_read == 0) ? I2C_M_RECV_LEN : 0);
+ /*
+ * In case of g_n_read is 0, block length will be added by
+ * the underlying bus driver.
+ */
+ msg[n_msg].len = (g_n_read) ? g_n_read : 256;
+ msg[n_msg].buf = g_read_bytes;
+ if (g_n_read == 0) {
+ /* If we're using variable length block reads, we have to set the
+ * first byte of the buffer to at least one or the kernel complains.
+ */
+ g_read_bytes[0] = 1;
+ }
+ n_msg++;
+ }
+
+ data.msgs = msg;
+ data.nmsgs = n_msg;
+
+ rc = ioctl(fd, I2C_RDWR, &data);
+ if (rc < 0) {
+ LOG_ERR(errno, "Failed to do raw io");
+ return -1;
+ }
+
+ return 0;
+}
+
+int main(int argc, char * const argv[]) {
+ int i;
+ int fd;
+ int opt;
+ while ((opt = getopt(argc, argv, "hpw:r:")) != -1) {
+ switch (opt) {
+ case 'h':
+ usage(argv[0]);
+ return 0;
+ case 'p':
+ g_use_pec = 1;
+ break;
+ case 'w':
+ g_has_write = 1;
+ if ((g_n_write = parse_byte_string(optarg)) <= 0) {
+ usage(argv[0]);
+ return -1;
+ }
+ break;
+ case 'r':
+ g_has_read = 1;
+ g_n_read = atoi(optarg);
+ break;
+ default:
+ usage(argv[0]);
+ return -1;
+ }
+ }
+
+ /* make sure we still have arguments for bus and slave address */
+ if (optind + 2 != argc) {
+ printf("Bus or slave address is missing\n");
+ usage(argv[0]);
+ return -1;
+ }
+
+ g_bus = atoi(argv[optind]);
+ g_slave_addr = strtoul(argv[optind + 1], NULL, 0);
+ if ((g_slave_addr & 0x80)) {
+ printf("Slave address must be 7-bit\n");
+ return -1;
+ }
+
+ if (!g_has_write && !g_has_read) {
+ /* by default, read, first byte read is the length */
+ g_has_read = 1;
+ g_n_read = 0;
+ }
+
+ printf("Bus: %d\nDevice address: 0x%x\n", g_bus, g_slave_addr);
+ if (g_has_write) {
+ printf("To write %d bytes:", g_n_write);
+ for (i = 0; i < g_n_write; i++) {
+ printf(" 0x%x", g_write_bytes[i]);
+ }
+ printf("\n");
+ }
+ if (g_has_read) {
+ if (g_n_read) {
+ printf("To read %d bytes.\n", g_n_read);
+ } else {
+ printf("To read data.\n");
+ }
+ }
+
+ fd = i2c_open();
+ if (fd < 0) {
+ return -1;
+ }
+
+ if (i2c_io(fd) < 0) {
+ return -1;
+ }
+
+ if (g_has_read) {
+ printf("Received:\n ");
+ if (g_n_read == 0) {
+ g_n_read = g_read_bytes[0] + 1;
+ }
+ for (i = 0; i < g_n_read; i++) {
+ printf(" 0x%x", g_read_bytes[i]);
+ }
+ printf("\n");
+ }
+
+ return 0;
+}
diff --git a/meta-facebook/meta-wedge/recipes-wedge/oob-nic/oob-nic/src/intf.c b/meta-facebook/meta-wedge/recipes-wedge/oob-nic/oob-nic/src/intf.c
new file mode 100644
index 0000000..5bf8480
--- /dev/null
+++ b/meta-facebook/meta-wedge/recipes-wedge/oob-nic/oob-nic/src/intf.c
@@ -0,0 +1,254 @@
+/*
+ * Copyright 2014-present Facebook. All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include "intf.h"
+
+#include <errno.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/ioctl.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <linux/rtnetlink.h>
+#include <linux/if.h>
+#include <linux/if_tun.h>
+#include <linux/fib_rules.h>
+
+#include "facebook/log.h"
+#include "libnetlink.h"
+#include "ll_map.h"
+
+struct oob_intf_t {
+ char oi_name[32];
+ int oi_fd;
+ int oi_ifidx;
+ uint8_t oi_mac[6];
+ struct rtnl_handle oi_rth;
+};
+
+#define TUN_DEVICE "/dev/net/tun"
+
+static int oob_intf_set_mac(oob_intf *intf, const uint8_t mac[6]) {
+ int rc;
+ struct {
+ struct nlmsghdr n;
+ struct ifinfomsg ifi;
+ char buf[256];
+ } req;
+
+ memset(&req, 0, sizeof(req));
+ req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg));
+ req.n.nlmsg_type = RTM_NEWLINK;
+ req.n.nlmsg_flags = NLM_F_REQUEST;
+ req.ifi.ifi_family = AF_UNSPEC;
+ req.ifi.ifi_index = intf->oi_ifidx;
+ memcpy(intf->oi_mac, mac, sizeof(intf->oi_mac));
+ addattr_l(&req.n, sizeof(req), IFLA_ADDRESS,
+ intf->oi_mac, sizeof(intf->oi_mac));
+ rc = rtnl_talk(&intf->oi_rth, &req.n, 0, 0, NULL);
+ if (rc < 0) {
+ rc = errno;
+ LOG_ERR(rc, "Failed to set mac to interface %s @ index %d",
+ intf->oi_name, intf->oi_ifidx);
+ return -rc;
+ }
+
+ LOG_INFO("Set interface %s @ index %d mac to %x:%x:%x:%x:%x:%x",
+ intf->oi_name, intf->oi_ifidx,
+ intf->oi_mac[0], intf->oi_mac[1], intf->oi_mac[2],
+ intf->oi_mac[3], intf->oi_mac[4], intf->oi_mac[5]);
+
+ return 0;
+}
+
+static int oob_intf_bring_up(oob_intf *intf) {
+ int rc;
+ struct {
+ struct nlmsghdr n;
+ struct ifinfomsg ifi;
+ char buf[256];
+ } req;
+
+ memset(&req, 0, sizeof(req));
+ req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg));
+ req.n.nlmsg_type = RTM_NEWLINK;
+ req.n.nlmsg_flags = NLM_F_REQUEST;
+ req.ifi.ifi_family = AF_UNSPEC;
+ req.ifi.ifi_change |= IFF_UP;
+ req.ifi.ifi_flags |= IFF_UP;
+ req.ifi.ifi_index = intf->oi_ifidx;
+ rc = rtnl_talk(&intf->oi_rth, &req.n, 0, 0, NULL);
+ if (rc < 0) {
+ rc = errno;
+ LOG_ERR(rc, "Failed to bring up interface %s @ index %d",
+ intf->oi_name, intf->oi_ifidx);
+ return -rc;
+ }
+
+ LOG_INFO("Brought up interface %s @ index %d", intf->oi_name, intf->oi_ifidx);
+
+ return 0;
+}
+
+oob_intf* oob_intf_create(const char *name, const uint8_t mac[6]) {
+
+ int rc;
+ int flags;
+ struct ifreq ifr;
+ oob_intf *intf = NULL;
+
+#define _CHECK_RC(fmt, ...) do { \
+ if (rc < 0) { \
+ rc = errno; \
+ LOG_ERR(rc, fmt, ##__VA_ARGS__); \
+ goto err_out; \
+ } \
+} while(0)
+
+ intf = malloc(sizeof(*intf));
+ if (!intf) {
+ rc = ENOMEM;
+ LOG_ERR(rc, "Failed to allocate memory for interface");
+ goto err_out;
+ }
+ memset(intf, 0, sizeof(*intf));
+ strncpy(intf->oi_name, name, sizeof(intf->oi_name));
+ intf->oi_name[sizeof(intf->oi_name) - 1] = '\0';
+ intf->oi_fd = -1;
+
+ rc = rtnl_open(&intf->oi_rth, 0);
+ _CHECK_RC("Failed to open rth_handler");
+
+ rc = open(TUN_DEVICE, O_RDWR);
+ _CHECK_RC("Failed to open %s", TUN_DEVICE);
+ intf->oi_fd = rc;
+
+ memset(&ifr, 0, sizeof(ifr));
+ /*
+ * IFF_TAP: TAP interface
+ * IFF_NO_PI: Do not provide pracket information
+ */
+ ifr.ifr_flags = IFF_TAP|IFF_NO_PI;
+ strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
+ ifr.ifr_name[sizeof(ifr.ifr_name) - 1] = '\0';
+
+ rc = ioctl(intf->oi_fd, TUNSETIFF, (void *) &ifr);
+ _CHECK_RC("Failed to create tap interface %s", ifr.ifr_name);
+
+ /* make fd non-blocking */
+ rc = fcntl(intf->oi_fd, F_GETFL);
+ _CHECK_RC("Failed to get flags from fd ", intf->oi_fd);
+ flags = rc | O_NONBLOCK;
+ rc = fcntl(intf->oi_fd, F_SETFL, rc);
+ _CHECK_RC("Failed to set non-blocking flags ", flags,
+ " to fd ", intf->oi_fd);
+
+ /* set CLOEXEC */
+ rc = fcntl(intf->oi_fd, F_GETFD);
+ _CHECK_RC("Failed to get flags from fd ", intf->oi_fd);
+ flags = rc | FD_CLOEXEC;
+ rc = fcntl(intf->oi_fd, F_SETFD, flags);
+ _CHECK_RC("Failed to set close-on-exec flags ", flags,
+ " to fd ", intf->oi_fd);
+
+ // TODO: if needed, we can adjust send buffer size, TUNSETSNDBUF
+ intf->oi_ifidx = ll_name_to_index(intf->oi_name);
+
+ /* now set the mac address */
+ oob_intf_set_mac(intf, mac);
+
+#if 0
+ /* make it persistent */
+ rc = ioctl(intf->oi_fd, TUNSETPERSIST, 0);
+ _CHECK_RC("Failed to make the tap interface %s persistent", intf->oi_name);
+#endif
+
+ LOG_INFO("Create/attach to tap interface %s @ fd %d, index %d",
+ intf->oi_name, intf->oi_fd, intf->oi_ifidx);
+
+ //oob_intf_bring_up(intf);
+
+ return intf;
+
+ err_out:
+ if (intf) {
+ rtnl_close(&intf->oi_rth);
+ if (intf->oi_fd != -1) {
+ close(intf->oi_fd);
+ }
+ free(intf);
+ }
+
+ return NULL;
+}
+
+int oob_intf_get_fd(const oob_intf *intf) {
+ return intf->oi_fd;
+}
+
+int oob_intf_receive(const oob_intf *intf, char *buf, int len) {
+ int rc;
+ do {
+ rc = read(intf->oi_fd, buf, len);
+ } while (rc == -1 && errno == EINTR);
+ if (rc < 0) {
+ rc = errno;
+ if (rc != EAGAIN) {
+ LOG_ERR(rc, "Failed to read on interface fd %d", intf->oi_fd);
+ return -rc;
+ } else {
+ /* nothing is available */
+ return 0;
+ }
+ } else if (rc == 0) {
+ // Nothing to read. It shall not happen as the fd is non-blocking.
+ // Just add this case to be safe.
+ return 0;
+ } else if (rc > len) {
+ // The pkt is larger than the buffer. We don't have complete packet.
+ // It shall not happen unless the MTU is mis-match. Drop the packet.
+ LOG_ERR(ENOSPC, "Received a too large packet (%d bytes > %d) from the "
+ "tap interface. Drop it...", rc, len);
+ return -ENOSPC;
+ } else {
+ LOG_VER("Recv a packet of %d bytes from %s", rc, intf->oi_name);
+ return rc;
+ }
+}
+
+int oob_intf_send(const oob_intf *intf, const char *buf, int len) {
+ int rc;
+ do {
+ rc = write(intf->oi_fd, buf, len);
+ } while (rc == -1 && errno == EINTR);
+ if (rc < 0) {
+ rc = errno;
+ LOG_ERR(rc, "Failed to send on interface fd %d", intf->oi_fd);
+ return -rc;
+ } else if (rc < len) {
+ LOG_ERR(EIO, "Failed to send the full packet (%d bytes > %d) for fd %d",
+ len, rc, intf->oi_fd);
+ return -EIO;
+ } else {
+ LOG_VER("Sent a packet of %d bytes to %s", rc, intf->oi_name);
+ return rc;
+ }
+}
diff --git a/meta-facebook/meta-wedge/recipes-wedge/oob-nic/oob-nic/src/intf.h b/meta-facebook/meta-wedge/recipes-wedge/oob-nic/oob-nic/src/intf.h
new file mode 100644
index 0000000..6ea7af1
--- /dev/null
+++ b/meta-facebook/meta-wedge/recipes-wedge/oob-nic/oob-nic/src/intf.h
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2014-present Facebook. All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#ifndef INTF_H
+#define INTF_H
+
+#include <stdint.h>
+
+typedef struct oob_intf_t oob_intf;
+
+oob_intf* oob_intf_create(const char *name, const uint8_t mac[6]);
+int oob_intf_get_fd(const oob_intf *intf);
+
+int oob_intf_receive(const oob_intf *intf, char *buf, int len);
+int oob_intf_send(const oob_intf *intf, const char *buf, int len);
+
+#endif
diff --git a/meta-facebook/meta-wedge/recipes-wedge/oob-nic/oob-nic/src/libnetlink.c b/meta-facebook/meta-wedge/recipes-wedge/oob-nic/oob-nic/src/libnetlink.c
new file mode 100644
index 0000000..019e2c8
--- /dev/null
+++ b/meta-facebook/meta-wedge/recipes-wedge/oob-nic/oob-nic/src/libnetlink.c
@@ -0,0 +1,717 @@
+/*
+ * Note: Original file from iproute2 package
+ *
+ * libnetlink.c RTnetlink service routines.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ *
+ * Authors: Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru>
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <syslog.h>
+#include <fcntl.h>
+#include <net/if_arp.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <string.h>
+#include <errno.h>
+#include <time.h>
+#include <sys/uio.h>
+
+#include "libnetlink.h"
+
+int rcvbuf = 1024 * 1024;
+
+void rtnl_close(struct rtnl_handle *rth)
+{
+ if (rth->fd >= 0) {
+ close(rth->fd);
+ rth->fd = -1;
+ }
+}
+
+int rtnl_open_byproto(struct rtnl_handle *rth, unsigned subscriptions,
+ int protocol)
+{
+ socklen_t addr_len;
+ int sndbuf = 32768;
+
+ memset(rth, 0, sizeof(*rth));
+
+ rth->fd = socket(AF_NETLINK, SOCK_RAW | SOCK_CLOEXEC, protocol);
+ if (rth->fd < 0) {
+ perror("Cannot open netlink socket");
+ return -1;
+ }
+
+ if (setsockopt(rth->fd,SOL_SOCKET,SO_SNDBUF,&sndbuf,sizeof(sndbuf)) < 0) {
+ perror("SO_SNDBUF");
+ return -1;
+ }
+
+ if (setsockopt(rth->fd,SOL_SOCKET,SO_RCVBUF,&rcvbuf,sizeof(rcvbuf)) < 0) {
+ perror("SO_RCVBUF");
+ return -1;
+ }
+
+ memset(&rth->local, 0, sizeof(rth->local));
+ rth->local.nl_family = AF_NETLINK;
+ rth->local.nl_groups = subscriptions;
+
+ if (bind(rth->fd, (struct sockaddr*)&rth->local, sizeof(rth->local)) < 0) {
+ perror("Cannot bind netlink socket");
+ return -1;
+ }
+ addr_len = sizeof(rth->local);
+ if (getsockname(rth->fd, (struct sockaddr*)&rth->local, &addr_len) < 0) {
+ perror("Cannot getsockname");
+ return -1;
+ }
+ if (addr_len != sizeof(rth->local)) {
+ fprintf(stderr, "Wrong address length %d\n", addr_len);
+ return -1;
+ }
+ if (rth->local.nl_family != AF_NETLINK) {
+ fprintf(stderr, "Wrong address family %d\n", rth->local.nl_family);
+ return -1;
+ }
+ rth->seq = time(NULL);
+ return 0;
+}
+
+int rtnl_open(struct rtnl_handle *rth, unsigned subscriptions)
+{
+ return rtnl_open_byproto(rth, subscriptions, NETLINK_ROUTE);
+}
+
+int rtnl_wilddump_request(struct rtnl_handle *rth, int family, int type)
+{
+ return rtnl_wilddump_req_filter(rth, family, type, RTEXT_FILTER_VF);
+}
+
+int rtnl_wilddump_req_filter(struct rtnl_handle *rth, int family, int type,
+ __u32 filt_mask)
+{
+ struct {
+ struct nlmsghdr nlh;
+ struct ifinfomsg ifm;
+ /* attribute has to be NLMSG aligned */
+ struct rtattr ext_req __attribute__ ((aligned(NLMSG_ALIGNTO)));
+ __u32 ext_filter_mask;
+ } req;
+
+ memset(&req, 0, sizeof(req));
+ req.nlh.nlmsg_len = sizeof(req);
+ req.nlh.nlmsg_type = type;
+ req.nlh.nlmsg_flags = NLM_F_DUMP|NLM_F_REQUEST;
+ req.nlh.nlmsg_pid = 0;
+ req.nlh.nlmsg_seq = rth->dump = ++rth->seq;
+ req.ifm.ifi_family = family;
+
+ req.ext_req.rta_type = IFLA_EXT_MASK;
+ req.ext_req.rta_len = RTA_LENGTH(sizeof(__u32));
+ req.ext_filter_mask = filt_mask;
+
+ return send(rth->fd, (void*)&req, sizeof(req), 0);
+}
+
+int rtnl_send(struct rtnl_handle *rth, const void *buf, int len)
+{
+ return send(rth->fd, buf, len, 0);
+}
+
+int rtnl_send_check(struct rtnl_handle *rth, const void *buf, int len)
+{
+ struct nlmsghdr *h;
+ int status;
+ char resp[1024];
+
+ status = send(rth->fd, buf, len, 0);
+ if (status < 0)
+ return status;
+
+ /* Check for immediate errors */
+ status = recv(rth->fd, resp, sizeof(resp), MSG_DONTWAIT|MSG_PEEK);
+ if (status < 0) {
+ if (errno == EAGAIN)
+ return 0;
+ return -1;
+ }
+
+ for (h = (struct nlmsghdr *)resp; NLMSG_OK(h, status);
+ h = NLMSG_NEXT(h, status)) {
+ if (h->nlmsg_type == NLMSG_ERROR) {
+ struct nlmsgerr *err = (struct nlmsgerr*)NLMSG_DATA(h);
+ if (h->nlmsg_len < NLMSG_LENGTH(sizeof(struct nlmsgerr)))
+ fprintf(stderr, "ERROR truncated\n");
+ else
+ errno = -err->error;
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
+int rtnl_dump_request(struct rtnl_handle *rth, int type, void *req, int len)
+{
+ struct nlmsghdr nlh;
+ struct sockaddr_nl nladdr = { .nl_family = AF_NETLINK };
+ struct iovec iov[2] = {
+ { .iov_base = &nlh, .iov_len = sizeof(nlh) },
+ { .iov_base = req, .iov_len = len }
+ };
+ struct msghdr msg = {
+ .msg_name = &nladdr,
+ .msg_namelen = sizeof(nladdr),
+ .msg_iov = iov,
+ .msg_iovlen = 2,
+ };
+
+ nlh.nlmsg_len = NLMSG_LENGTH(len);
+ nlh.nlmsg_type = type;
+ nlh.nlmsg_flags = NLM_F_DUMP|NLM_F_REQUEST;
+ nlh.nlmsg_pid = 0;
+ nlh.nlmsg_seq = rth->dump = ++rth->seq;
+
+ return sendmsg(rth->fd, &msg, 0);
+}
+
+int rtnl_dump_filter_l(struct rtnl_handle *rth,
+ const struct rtnl_dump_filter_arg *arg)
+{
+ struct sockaddr_nl nladdr;
+ struct iovec iov;
+ struct msghdr msg = {
+ .msg_name = &nladdr,
+ .msg_namelen = sizeof(nladdr),
+ .msg_iov = &iov,
+ .msg_iovlen = 1,
+ };
+ char buf[16384];
+ int dump_intr = 0;
+
+ iov.iov_base = buf;
+ while (1) {
+ int status;
+ const struct rtnl_dump_filter_arg *a;
+ int found_done = 0;
+ int msglen = 0;
+
+ iov.iov_len = sizeof(buf);
+ status = recvmsg(rth->fd, &msg, 0);
+
+ if (status < 0) {
+ if (errno == EINTR || errno == EAGAIN)
+ continue;
+ fprintf(stderr, "netlink receive error %s (%d)\n",
+ strerror(errno), errno);
+ return -1;
+ }
+
+ if (status == 0) {
+ fprintf(stderr, "EOF on netlink\n");
+ return -1;
+ }
+
+ for (a = arg; a->filter; a++) {
+ struct nlmsghdr *h = (struct nlmsghdr*)buf;
+ msglen = status;
+
+ while (NLMSG_OK(h, msglen)) {
+ int err;
+
+ if (nladdr.nl_pid != 0 ||
+ h->nlmsg_pid != rth->local.nl_pid ||
+ h->nlmsg_seq != rth->dump)
+ goto skip_it;
+
+ if (h->nlmsg_flags & NLM_F_DUMP_INTR)
+ dump_intr = 1;
+
+ if (h->nlmsg_type == NLMSG_DONE) {
+ found_done = 1;
+ break; /* process next filter */
+ }
+ if (h->nlmsg_type == NLMSG_ERROR) {
+ struct nlmsgerr *err = (struct nlmsgerr*)NLMSG_DATA(h);
+ if (h->nlmsg_len < NLMSG_LENGTH(sizeof(struct nlmsgerr))) {
+ fprintf(stderr,
+ "ERROR truncated\n");
+ } else {
+ errno = -err->error;
+ perror("RTNETLINK answers");
+ }
+ return -1;
+ }
+ err = a->filter(&nladdr, h, a->arg1);
+ if (err < 0)
+ return err;
+
+skip_it:
+ h = NLMSG_NEXT(h, msglen);
+ }
+ }
+
+ if (found_done) {
+ if (dump_intr)
+ fprintf(stderr,
+ "Dump was interrupted and may be inconsistent.\n");
+ return 0;
+ }
+
+ if (msg.msg_flags & MSG_TRUNC) {
+ fprintf(stderr, "Message truncated\n");
+ continue;
+ }
+ if (msglen) {
+ fprintf(stderr, "!!!Remnant of size %d\n", msglen);
+ exit(1);
+ }
+ }
+}
+
+int rtnl_dump_filter(struct rtnl_handle *rth,
+ rtnl_filter_t filter,
+ void *arg1)
+{
+ const struct rtnl_dump_filter_arg a[2] = {
+ { .filter = filter, .arg1 = arg1, },
+ { .filter = NULL, .arg1 = NULL, },
+ };
+
+ return rtnl_dump_filter_l(rth, a);
+}
+
+int rtnl_talk(struct rtnl_handle *rtnl, struct nlmsghdr *n, pid_t peer,
+ unsigned groups, struct nlmsghdr *answer)
+{
+ int status;
+ unsigned seq;
+ struct nlmsghdr *h;
+ struct sockaddr_nl nladdr;
+ struct iovec iov = {
+ .iov_base = (void*) n,
+ .iov_len = n->nlmsg_len
+ };
+ struct msghdr msg = {
+ .msg_name = &nladdr,
+ .msg_namelen = sizeof(nladdr),
+ .msg_iov = &iov,
+ .msg_iovlen = 1,
+ };
+ char buf[16384];
+
+ memset(&nladdr, 0, sizeof(nladdr));
+ nladdr.nl_family = AF_NETLINK;
+ nladdr.nl_pid = peer;
+ nladdr.nl_groups = groups;
+
+ n->nlmsg_seq = seq = ++rtnl->seq;
+
+ if (answer == NULL)
+ n->nlmsg_flags |= NLM_F_ACK;
+
+ status = sendmsg(rtnl->fd, &msg, 0);
+
+ if (status < 0) {
+ perror("Cannot talk to rtnetlink");
+ return -1;
+ }
+
+ memset(buf,0,sizeof(buf));
+
+ iov.iov_base = buf;
+
+ while (1) {
+ iov.iov_len = sizeof(buf);
+ status = recvmsg(rtnl->fd, &msg, 0);
+
+ if (status < 0) {
+ if (errno == EINTR || errno == EAGAIN)
+ continue;
+ fprintf(stderr, "netlink receive error %s (%d)\n",
+ strerror(errno), errno);
+ return -1;
+ }
+ if (status == 0) {
+ fprintf(stderr, "EOF on netlink\n");
+ return -1;
+ }
+ if (msg.msg_namelen != sizeof(nladdr)) {
+ fprintf(stderr, "sender address length == %d\n", msg.msg_namelen);
+ exit(1);
+ }
+ for (h = (struct nlmsghdr*)buf; status >= sizeof(*h); ) {
+ int len = h->nlmsg_len;
+ int l = len - sizeof(*h);
+
+ if (l < 0 || len>status) {
+ if (msg.msg_flags & MSG_TRUNC) {
+ fprintf(stderr, "Truncated message\n");
+ return -1;
+ }
+ fprintf(stderr, "!!!malformed message: len=%d\n", len);
+ exit(1);
+ }
+
+ if (nladdr.nl_pid != peer ||
+ h->nlmsg_pid != rtnl->local.nl_pid ||
+ h->nlmsg_seq != seq) {
+ /* Don't forget to skip that message. */
+ status -= NLMSG_ALIGN(len);
+ h = (struct nlmsghdr*)((char*)h + NLMSG_ALIGN(len));
+ continue;
+ }
+
+ if (h->nlmsg_type == NLMSG_ERROR) {
+ struct nlmsgerr *err = (struct nlmsgerr*)NLMSG_DATA(h);
+ if (l < sizeof(struct nlmsgerr)) {
+ fprintf(stderr, "ERROR truncated\n");
+ } else {
+ if (!err->error) {
+ if (answer)
+ memcpy(answer, h, h->nlmsg_len);
+ return 0;
+ }
+
+ fprintf(stderr, "RTNETLINK answers: %s\n", strerror(-err->error));
+ errno = -err->error;
+ }
+ return -1;
+ }
+ if (answer) {
+ memcpy(answer, h, h->nlmsg_len);
+ return 0;
+ }
+
+ fprintf(stderr, "Unexpected reply!!!\n");
+
+ status -= NLMSG_ALIGN(len);
+ h = (struct nlmsghdr*)((char*)h + NLMSG_ALIGN(len));
+ }
+ if (msg.msg_flags & MSG_TRUNC) {
+ fprintf(stderr, "Message truncated\n");
+ continue;
+ }
+ if (status) {
+ fprintf(stderr, "!!!Remnant of size %d\n", status);
+ exit(1);
+ }
+ }
+}
+
+int rtnl_listen(struct rtnl_handle *rtnl,
+ rtnl_filter_t handler,
+ void *jarg)
+{
+ int status;
+ struct nlmsghdr *h;
+ struct sockaddr_nl nladdr;
+ struct iovec iov;
+ struct msghdr msg = {
+ .msg_name = &nladdr,
+ .msg_namelen = sizeof(nladdr),
+ .msg_iov = &iov,
+ .msg_iovlen = 1,
+ };
+ char buf[8192];
+
+ memset(&nladdr, 0, sizeof(nladdr));
+ nladdr.nl_family = AF_NETLINK;
+ nladdr.nl_pid = 0;
+ nladdr.nl_groups = 0;
+
+ iov.iov_base = buf;
+ while (1) {
+ iov.iov_len = sizeof(buf);
+ status = recvmsg(rtnl->fd, &msg, 0);
+
+ if (status < 0) {
+ if (errno == EINTR || errno == EAGAIN)
+ continue;
+ fprintf(stderr, "netlink receive error %s (%d)\n",
+ strerror(errno), errno);
+ if (errno == ENOBUFS)
+ continue;
+ return -1;
+ }
+ if (status == 0) {
+ fprintf(stderr, "EOF on netlink\n");
+ return -1;
+ }
+ if (msg.msg_namelen != sizeof(nladdr)) {
+ fprintf(stderr, "Sender address length == %d\n", msg.msg_namelen);
+ exit(1);
+ }
+ for (h = (struct nlmsghdr*)buf; status >= sizeof(*h); ) {
+ int err;
+ int len = h->nlmsg_len;
+ int l = len - sizeof(*h);
+
+ if (l<0 || len>status) {
+ if (msg.msg_flags & MSG_TRUNC) {
+ fprintf(stderr, "Truncated message\n");
+ return -1;
+ }
+ fprintf(stderr, "!!!malformed message: len=%d\n", len);
+ exit(1);
+ }
+
+ err = handler(&nladdr, h, jarg);
+ if (err < 0)
+ return err;
+
+ status -= NLMSG_ALIGN(len);
+ h = (struct nlmsghdr*)((char*)h + NLMSG_ALIGN(len));
+ }
+ if (msg.msg_flags & MSG_TRUNC) {
+ fprintf(stderr, "Message truncated\n");
+ continue;
+ }
+ if (status) {
+ fprintf(stderr, "!!!Remnant of size %d\n", status);
+ exit(1);
+ }
+ }
+}
+
+int rtnl_from_file(FILE *rtnl, rtnl_filter_t handler,
+ void *jarg)
+{
+ int status;
+ struct sockaddr_nl nladdr;
+ char buf[8192];
+ struct nlmsghdr *h = (void*)buf;
+
+ memset(&nladdr, 0, sizeof(nladdr));
+ nladdr.nl_family = AF_NETLINK;
+ nladdr.nl_pid = 0;
+ nladdr.nl_groups = 0;
+
+ while (1) {
+ int err, len;
+ int l;
+
+ status = fread(&buf, 1, sizeof(*h), rtnl);
+
+ if (status < 0) {
+ if (errno == EINTR)
+ continue;
+ perror("rtnl_from_file: fread");
+ return -1;
+ }
+ if (status == 0)
+ return 0;
+
+ len = h->nlmsg_len;
+ l = len - sizeof(*h);
+
+ if (l<0 || len>sizeof(buf)) {
+ fprintf(stderr, "!!!malformed message: len=%d @%lu\n",
+ len, ftell(rtnl));
+ return -1;
+ }
+
+ status = fread(NLMSG_DATA(h), 1, NLMSG_ALIGN(l), rtnl);
+
+ if (status < 0) {
+ perror("rtnl_from_file: fread");
+ return -1;
+ }
+ if (status < l) {
+ fprintf(stderr, "rtnl-from_file: truncated message\n");
+ return -1;
+ }
+
+ err = handler(&nladdr, h, jarg);
+ if (err < 0)
+ return err;
+ }
+}
+
+int addattr(struct nlmsghdr *n, int maxlen, int type)
+{
+ return addattr_l(n, maxlen, type, NULL, 0);
+}
+
+int addattr8(struct nlmsghdr *n, int maxlen, int type, __u8 data)
+{
+ return addattr_l(n, maxlen, type, &data, sizeof(__u8));
+}
+
+int addattr16(struct nlmsghdr *n, int maxlen, int type, __u16 data)
+{
+ return addattr_l(n, maxlen, type, &data, sizeof(__u16));
+}
+
+int addattr32(struct nlmsghdr *n, int maxlen, int type, __u32 data)
+{
+ return addattr_l(n, maxlen, type, &data, sizeof(__u32));
+}
+
+int addattr64(struct nlmsghdr *n, int maxlen, int type, __u64 data)
+{
+ return addattr_l(n, maxlen, type, &data, sizeof(__u64));
+}
+
+int addattrstrz(struct nlmsghdr *n, int maxlen, int type, const char *str)
+{
+ return addattr_l(n, maxlen, type, str, strlen(str)+1);
+}
+
+int addattr_l(struct nlmsghdr *n, int maxlen, int type, const void *data,
+ int alen)
+{
+ int len = RTA_LENGTH(alen);
+ struct rtattr *rta;
+
+ if (NLMSG_ALIGN(n->nlmsg_len) + RTA_ALIGN(len) > maxlen) {
+ fprintf(stderr, "addattr_l ERROR: message exceeded bound of %d\n",maxlen);
+ return -1;
+ }
+ rta = NLMSG_TAIL(n);
+ rta->rta_type = type;
+ rta->rta_len = len;
+ memcpy(RTA_DATA(rta), data, alen);
+ n->nlmsg_len = NLMSG_ALIGN(n->nlmsg_len) + RTA_ALIGN(len);
+ return 0;
+}
+
+int addraw_l(struct nlmsghdr *n, int maxlen, const void *data, int len)
+{
+ if (NLMSG_ALIGN(n->nlmsg_len) + NLMSG_ALIGN(len) > maxlen) {
+ fprintf(stderr, "addraw_l ERROR: message exceeded bound of %d\n",maxlen);
+ return -1;
+ }
+
+ memcpy(NLMSG_TAIL(n), data, len);
+ memset((void *) NLMSG_TAIL(n) + len, 0, NLMSG_ALIGN(len) - len);
+ n->nlmsg_len = NLMSG_ALIGN(n->nlmsg_len) + NLMSG_ALIGN(len);
+ return 0;
+}
+
+struct rtattr *addattr_nest(struct nlmsghdr *n, int maxlen, int type)
+{
+ struct rtattr *nest = NLMSG_TAIL(n);
+
+ addattr_l(n, maxlen, type, NULL, 0);
+ return nest;
+}
+
+int addattr_nest_end(struct nlmsghdr *n, struct rtattr *nest)
+{
+ nest->rta_len = (void *)NLMSG_TAIL(n) - (void *)nest;
+ return n->nlmsg_len;
+}
+
+struct rtattr *addattr_nest_compat(struct nlmsghdr *n, int maxlen, int type,
+ const void *data, int len)
+{
+ struct rtattr *start = NLMSG_TAIL(n);
+
+ addattr_l(n, maxlen, type, data, len);
+ addattr_nest(n, maxlen, type);
+ return start;
+}
+
+int addattr_nest_compat_end(struct nlmsghdr *n, struct rtattr *start)
+{
+ struct rtattr *nest = (void *)start + NLMSG_ALIGN(start->rta_len);
+
+ start->rta_len = (void *)NLMSG_TAIL(n) - (void *)start;
+ addattr_nest_end(n, nest);
+ return n->nlmsg_len;
+}
+
+int rta_addattr32(struct rtattr *rta, int maxlen, int type, __u32 data)
+{
+ int len = RTA_LENGTH(4);
+ struct rtattr *subrta;
+
+ if (RTA_ALIGN(rta->rta_len) + len > maxlen) {
+ fprintf(stderr,"rta_addattr32: Error! max allowed bound %d exceeded\n",maxlen);
+ return -1;
+ }
+ subrta = (struct rtattr*)(((char*)rta) + RTA_ALIGN(rta->rta_len));
+ subrta->rta_type = type;
+ subrta->rta_len = len;
+ memcpy(RTA_DATA(subrta), &data, 4);
+ rta->rta_len = NLMSG_ALIGN(rta->rta_len) + len;
+ return 0;
+}
+
+int rta_addattr_l(struct rtattr *rta, int maxlen, int type,
+ const void *data, int alen)
+{
+ struct rtattr *subrta;
+ int len = RTA_LENGTH(alen);
+
+ if (RTA_ALIGN(rta->rta_len) + RTA_ALIGN(len) > maxlen) {
+ fprintf(stderr,"rta_addattr_l: Error! max allowed bound %d exceeded\n",maxlen);
+ return -1;
+ }
+ subrta = (struct rtattr*)(((char*)rta) + RTA_ALIGN(rta->rta_len));
+ subrta->rta_type = type;
+ subrta->rta_len = len;
+ memcpy(RTA_DATA(subrta), data, alen);
+ rta->rta_len = NLMSG_ALIGN(rta->rta_len) + RTA_ALIGN(len);
+ return 0;
+}
+
+int parse_rtattr(struct rtattr *tb[], int max, struct rtattr *rta, int len)
+{
+ return parse_rtattr_flags(tb, max, rta, len, 0);
+}
+
+int parse_rtattr_flags(struct rtattr *tb[], int max, struct rtattr *rta,
+ int len, unsigned short flags)
+{
+ unsigned short type;
+
+ memset(tb, 0, sizeof(struct rtattr *) * (max + 1));
+ while (RTA_OK(rta, len)) {
+ type = rta->rta_type & ~flags;
+ if ((type <= max) && (!tb[type]))
+ tb[type] = rta;
+ rta = RTA_NEXT(rta,len);
+ }
+ if (len)
+ fprintf(stderr, "!!!Deficit %d, rta_len=%d\n", len, rta->rta_len);
+ return 0;
+}
+
+int parse_rtattr_byindex(struct rtattr *tb[], int max, struct rtattr *rta, int len)
+{
+ int i = 0;
+
+ memset(tb, 0, sizeof(struct rtattr *) * max);
+ while (RTA_OK(rta, len)) {
+ if (rta->rta_type <= max && i < max)
+ tb[i++] = rta;
+ rta = RTA_NEXT(rta,len);
+ }
+ if (len)
+ fprintf(stderr, "!!!Deficit %d, rta_len=%d\n", len, rta->rta_len);
+ return i;
+}
+
+int __parse_rtattr_nested_compat(struct rtattr *tb[], int max, struct rtattr *rta,
+ int len)
+{
+ if (RTA_PAYLOAD(rta) < len)
+ return -1;
+ if (RTA_PAYLOAD(rta) >= RTA_ALIGN(len) + sizeof(struct rtattr)) {
+ rta = RTA_DATA(rta) + RTA_ALIGN(len);
+ return parse_rtattr_nested(tb, max, rta);
+ }
+ memset(tb, 0, sizeof(struct rtattr *) * (max + 1));
+ return 0;
+}
diff --git a/meta-facebook/meta-wedge/recipes-wedge/oob-nic/oob-nic/src/libnetlink.h b/meta-facebook/meta-wedge/recipes-wedge/oob-nic/oob-nic/src/libnetlink.h
new file mode 100644
index 0000000..9e72692
--- /dev/null
+++ b/meta-facebook/meta-wedge/recipes-wedge/oob-nic/oob-nic/src/libnetlink.h
@@ -0,0 +1,161 @@
+/*
+ * Note: Original file from iproute2 package
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#ifndef __LIBNETLINK_H__
+#define __LIBNETLINK_H__ 1
+
+#include <stdio.h>
+#include <string.h>
+#include <asm/types.h>
+#include <linux/netlink.h>
+#include <linux/rtnetlink.h>
+#include <linux/if_link.h>
+#include <linux/if_addr.h>
+#include <linux/neighbour.h>
+#include <linux/netconf.h>
+
+struct rtnl_handle
+{
+ int fd;
+ struct sockaddr_nl local;
+ struct sockaddr_nl peer;
+ __u32 seq;
+ __u32 dump;
+};
+
+extern int rcvbuf;
+
+extern int rtnl_open(struct rtnl_handle *rth, unsigned subscriptions);
+extern int rtnl_open_byproto(struct rtnl_handle *rth, unsigned subscriptions, int protocol);
+extern void rtnl_close(struct rtnl_handle *rth);
+extern int rtnl_wilddump_request(struct rtnl_handle *rth, int fam, int type);
+extern int rtnl_wilddump_req_filter(struct rtnl_handle *rth, int fam, int type,
+ __u32 filt_mask);
+extern int rtnl_dump_request(struct rtnl_handle *rth, int type, void *req, int len);
+
+typedef int (*rtnl_filter_t)(const struct sockaddr_nl *,
+ struct nlmsghdr *n, void *);
+
+struct rtnl_dump_filter_arg
+{
+ rtnl_filter_t filter;
+ void *arg1;
+};
+
+extern int rtnl_dump_filter_l(struct rtnl_handle *rth,
+ const struct rtnl_dump_filter_arg *arg);
+extern int rtnl_dump_filter(struct rtnl_handle *rth, rtnl_filter_t filter,
+ void *arg);
+extern int rtnl_talk(struct rtnl_handle *rtnl, struct nlmsghdr *n, pid_t peer,
+ unsigned groups, struct nlmsghdr *answer);
+extern int rtnl_send(struct rtnl_handle *rth, const void *buf, int);
+extern int rtnl_send_check(struct rtnl_handle *rth, const void *buf, int);
+
+extern int addattr(struct nlmsghdr *n, int maxlen, int type);
+extern int addattr8(struct nlmsghdr *n, int maxlen, int type, __u8 data);
+extern int addattr16(struct nlmsghdr *n, int maxlen, int type, __u16 data);
+extern int addattr32(struct nlmsghdr *n, int maxlen, int type, __u32 data);
+extern int addattr64(struct nlmsghdr *n, int maxlen, int type, __u64 data);
+extern int addattrstrz(struct nlmsghdr *n, int maxlen, int type, const char *data);
+
+extern int addattr_l(struct nlmsghdr *n, int maxlen, int type, const void *data, int alen);
+extern int addraw_l(struct nlmsghdr *n, int maxlen, const void *data, int len);
+extern struct rtattr *addattr_nest(struct nlmsghdr *n, int maxlen, int type);
+extern int addattr_nest_end(struct nlmsghdr *n, struct rtattr *nest);
+extern struct rtattr *addattr_nest_compat(struct nlmsghdr *n, int maxlen, int type, const void *data, int len);
+extern int addattr_nest_compat_end(struct nlmsghdr *n, struct rtattr *nest);
+extern int rta_addattr32(struct rtattr *rta, int maxlen, int type, __u32 data);
+extern int rta_addattr_l(struct rtattr *rta, int maxlen, int type, const void *data, int alen);
+
+extern int parse_rtattr(struct rtattr *tb[], int max, struct rtattr *rta, int len);
+extern int parse_rtattr_flags(struct rtattr *tb[], int max, struct rtattr *rta,
+ int len, unsigned short flags);
+extern int parse_rtattr_byindex(struct rtattr *tb[], int max, struct rtattr *rta, int len);
+extern int __parse_rtattr_nested_compat(struct rtattr *tb[], int max, struct rtattr *rta, int len);
+
+#define parse_rtattr_nested(tb, max, rta) \
+ (parse_rtattr((tb), (max), RTA_DATA(rta), RTA_PAYLOAD(rta)))
+
+#define parse_rtattr_nested_compat(tb, max, rta, data, len) \
+ ({ data = RTA_PAYLOAD(rta) >= len ? RTA_DATA(rta) : NULL; \
+ __parse_rtattr_nested_compat(tb, max, rta, len); })
+
+static inline __u8 rta_getattr_u8(const struct rtattr *rta)
+{
+ return *(__u8 *)RTA_DATA(rta);
+}
+static inline __u16 rta_getattr_u16(const struct rtattr *rta)
+{
+ return *(__u16 *)RTA_DATA(rta);
+}
+static inline __u32 rta_getattr_u32(const struct rtattr *rta)
+{
+ return *(__u32 *)RTA_DATA(rta);
+}
+static inline __u64 rta_getattr_u64(const struct rtattr *rta)
+{
+ __u64 tmp;
+ memcpy(&tmp, RTA_DATA(rta), sizeof(__u64));
+ return tmp;
+}
+static inline const char *rta_getattr_str(const struct rtattr *rta)
+{
+ return (const char *)RTA_DATA(rta);
+}
+
+extern int rtnl_listen(struct rtnl_handle *, rtnl_filter_t handler,
+ void *jarg);
+extern int rtnl_from_file(FILE *, rtnl_filter_t handler,
+ void *jarg);
+
+#define NLMSG_TAIL(nmsg) \
+ ((struct rtattr *) (((void *) (nmsg)) + NLMSG_ALIGN((nmsg)->nlmsg_len)))
+
+#ifndef IFA_RTA
+#define IFA_RTA(r) \
+ ((struct rtattr*)(((char*)(r)) + NLMSG_ALIGN(sizeof(struct ifaddrmsg))))
+#endif
+#ifndef IFA_PAYLOAD
+#define IFA_PAYLOAD(n) NLMSG_PAYLOAD(n,sizeof(struct ifaddrmsg))
+#endif
+
+#ifndef IFLA_RTA
+#define IFLA_RTA(r) \
+ ((struct rtattr*)(((char*)(r)) + NLMSG_ALIGN(sizeof(struct ifinfomsg))))
+#endif
+#ifndef IFLA_PAYLOAD
+#define IFLA_PAYLOAD(n) NLMSG_PAYLOAD(n,sizeof(struct ifinfomsg))
+#endif
+
+#ifndef NDA_RTA
+#define NDA_RTA(r) \
+ ((struct rtattr*)(((char*)(r)) + NLMSG_ALIGN(sizeof(struct ndmsg))))
+#endif
+#ifndef NDA_PAYLOAD
+#define NDA_PAYLOAD(n) NLMSG_PAYLOAD(n,sizeof(struct ndmsg))
+#endif
+
+#ifndef NDTA_RTA
+#define NDTA_RTA(r) \
+ ((struct rtattr*)(((char*)(r)) + NLMSG_ALIGN(sizeof(struct ndtmsg))))
+#endif
+#ifndef NDTA_PAYLOAD
+#define NDTA_PAYLOAD(n) NLMSG_PAYLOAD(n,sizeof(struct ndtmsg))
+#endif
+
+#endif /* __LIBNETLINK_H__ */
+
diff --git a/meta-facebook/meta-wedge/recipes-wedge/oob-nic/oob-nic/src/ll_map.c b/meta-facebook/meta-wedge/recipes-wedge/oob-nic/oob-nic/src/ll_map.c
new file mode 100644
index 0000000..64e5069
--- /dev/null
+++ b/meta-facebook/meta-wedge/recipes-wedge/oob-nic/oob-nic/src/ll_map.c
@@ -0,0 +1,225 @@
+/*
+ * Note: Original file from iproute2 package
+ *
+ * ll_map.c
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ *
+ * Authors: Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru>
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <syslog.h>
+#include <fcntl.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <string.h>
+#include <net/if.h>
+
+#include "libnetlink.h"
+#include "ll_map.h"
+#include "hlist.h"
+
+struct ll_cache {
+ struct hlist_node idx_hash;
+ struct hlist_node name_hash;
+ unsigned flags;
+ int index;
+ unsigned short type;
+ char name[IFNAMSIZ];
+};
+
+#define IDXMAP_SIZE 1024
+static struct hlist_head idx_head[IDXMAP_SIZE];
+static struct hlist_head name_head[IDXMAP_SIZE];
+
+static struct ll_cache *ll_get_by_index(unsigned index)
+{
+ struct hlist_node *n;
+ unsigned h = index & (IDXMAP_SIZE - 1);
+
+ hlist_for_each(n, &idx_head[h]) {
+ struct ll_cache *im
+ = container_of(n, struct ll_cache, idx_hash);
+ if (im->index == index)
+ return im;
+ }
+
+ return NULL;
+}
+
+static unsigned namehash(const char *str)
+{
+ unsigned hash = 5381;
+
+ while (*str)
+ hash = ((hash << 5) + hash) + *str++; /* hash * 33 + c */
+
+ return hash;
+}
+
+static struct ll_cache *ll_get_by_name(const char *name)
+{
+ struct hlist_node *n;
+ unsigned h = namehash(name) & (IDXMAP_SIZE - 1);
+
+ hlist_for_each(n, &name_head[h]) {
+ struct ll_cache *im
+ = container_of(n, struct ll_cache, name_hash);
+
+ if (strncmp(im->name, name, IFNAMSIZ) == 0)
+ return im;
+ }
+
+ return NULL;
+}
+
+int ll_remember_index(const struct sockaddr_nl *who,
+ struct nlmsghdr *n, void *arg)
+{
+ unsigned int h;
+ const char *ifname;
+ struct ifinfomsg *ifi = NLMSG_DATA(n);
+ struct ll_cache *im;
+ struct rtattr *tb[IFLA_MAX+1];
+
+ if (n->nlmsg_type != RTM_NEWLINK && n->nlmsg_type != RTM_DELLINK)
+ return 0;
+
+ if (n->nlmsg_len < NLMSG_LENGTH(sizeof(ifi)))
+ return -1;
+
+ im = ll_get_by_index(ifi->ifi_index);
+ if (n->nlmsg_type == RTM_DELLINK) {
+ if (im) {
+ hlist_del(&im->name_hash);
+ hlist_del(&im->idx_hash);
+ free(im);
+ }
+ return 0;
+ }
+
+ memset(tb, 0, sizeof(tb));
+ parse_rtattr(tb, IFLA_MAX, IFLA_RTA(ifi), IFLA_PAYLOAD(n));
+ ifname = rta_getattr_str(tb[IFLA_IFNAME]);
+ if (ifname == NULL)
+ return 0;
+
+ if (im) {
+ /* change to existing entry */
+ if (strcmp(im->name, ifname) != 0) {
+ hlist_del(&im->name_hash);
+ h = namehash(ifname) & (IDXMAP_SIZE - 1);
+ hlist_add_head(&im->name_hash, &name_head[h]);
+ }
+
+ im->flags = ifi->ifi_flags;
+ return 0;
+ }
+
+ im = malloc(sizeof(*im));
+ if (im == NULL)
+ return 0;
+ im->index = ifi->ifi_index;
+ strcpy(im->name, ifname);
+ im->type = ifi->ifi_type;
+ im->flags = ifi->ifi_flags;
+
+ h = ifi->ifi_index & (IDXMAP_SIZE - 1);
+ hlist_add_head(&im->idx_hash, &idx_head[h]);
+
+ h = namehash(ifname) & (IDXMAP_SIZE - 1);
+ hlist_add_head(&im->name_hash, &name_head[h]);
+
+ return 0;
+}
+
+const char *ll_idx_n2a(unsigned idx, char *buf)
+{
+ const struct ll_cache *im;
+
+ if (idx == 0)
+ return "*";
+
+ im = ll_get_by_index(idx);
+ if (im)
+ return im->name;
+
+ if (if_indextoname(idx, buf) == NULL)
+ snprintf(buf, IFNAMSIZ, "if%d", idx);
+
+ return buf;
+}
+
+const char *ll_index_to_name(unsigned idx)
+{
+ static char nbuf[IFNAMSIZ];
+
+ return ll_idx_n2a(idx, nbuf);
+}
+
+int ll_index_to_type(unsigned idx)
+{
+ const struct ll_cache *im;
+
+ if (idx == 0)
+ return -1;
+
+ im = ll_get_by_index(idx);
+ return im ? im->type : -1;
+}
+
+unsigned ll_index_to_flags(unsigned idx)
+{
+ const struct ll_cache *im;
+
+ if (idx == 0)
+ return 0;
+
+ im = ll_get_by_index(idx);
+ return im ? im->flags : -1;
+}
+
+unsigned ll_name_to_index(const char *name)
+{
+ const struct ll_cache *im;
+ unsigned idx;
+
+ if (name == NULL)
+ return 0;
+
+ im = ll_get_by_name(name);
+ if (im)
+ return im->index;
+
+ idx = if_nametoindex(name);
+ if (idx == 0)
+ sscanf(name, "if%u", &idx);
+ return idx;
+}
+
+void ll_init_map(struct rtnl_handle *rth)
+{
+ static int initialized;
+
+ if (initialized)
+ return;
+
+ if (rtnl_wilddump_request(rth, AF_UNSPEC, RTM_GETLINK) < 0) {
+ perror("Cannot send dump request");
+ exit(1);
+ }
+
+ if (rtnl_dump_filter(rth, ll_remember_index, NULL) < 0) {
+ fprintf(stderr, "Dump terminated\n");
+ exit(1);
+ }
+
+ initialized = 1;
+}
diff --git a/meta-facebook/meta-wedge/recipes-wedge/oob-nic/oob-nic/src/ll_map.h b/meta-facebook/meta-wedge/recipes-wedge/oob-nic/oob-nic/src/ll_map.h
new file mode 100644
index 0000000..d74a46f
--- /dev/null
+++ b/meta-facebook/meta-wedge/recipes-wedge/oob-nic/oob-nic/src/ll_map.h
@@ -0,0 +1,32 @@
+/*
+ * Note: Original file from iproute2 package
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef __LL_MAP_H__
+#define __LL_MAP_H__ 1
+
+extern int ll_remember_index(const struct sockaddr_nl *who,
+ struct nlmsghdr *n, void *arg);
+
+extern void ll_init_map(struct rtnl_handle *rth);
+extern unsigned ll_name_to_index(const char *name);
+extern const char *ll_index_to_name(unsigned idx);
+extern const char *ll_idx_n2a(unsigned idx, char *buf);
+extern int ll_index_to_type(unsigned idx);
+extern unsigned ll_index_to_flags(unsigned idx);
+
+#endif /* __LL_MAP_H__ */
diff --git a/meta-facebook/meta-wedge/recipes-wedge/oob-nic/oob-nic/src/main.c b/meta-facebook/meta-wedge/recipes-wedge/oob-nic/oob-nic/src/main.c
new file mode 100644
index 0000000..4312402
--- /dev/null
+++ b/meta-facebook/meta-wedge/recipes-wedge/oob-nic/oob-nic/src/main.c
@@ -0,0 +1,192 @@
+/*
+ * Copyright 2014-present Facebook. All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <stdio.h>
+#include <unistd.h>
+#include <sys/select.h>
+#include <sys/time.h>
+#include <sys/errno.h>
+
+#include "nic.h"
+#include "intf.h"
+
+#include "facebook/log.h"
+#include "facebook/wedge_eeprom.h"
+
+#define WAIT4PACKET_TIMEOUT 10000 /* 10ms */
+#define NO_RCV_CHECK_THRESHOLD 100 /* if not receiving pkt for 100 times (1s),
+ * check the NIC status
+ */
+
+static void io_loop(oob_nic *nic, oob_intf *intf, const uint8_t mac[6]) {
+
+ fd_set rfds;
+ int fd = oob_intf_get_fd(intf);
+ struct timeval timeout;
+ int rc;
+ int n_fds;
+ int n_io;
+ char buf[NIC_PKT_SIZE_MAX];
+ int no_rcv = 0;
+ struct oob_nic_status_t sts;
+
+ while (1) {
+ memset(&timeout, 0, sizeof(timeout));
+ timeout.tv_sec = 0;
+ timeout.tv_usec = WAIT4PACKET_TIMEOUT;
+
+ FD_ZERO(&rfds);
+ FD_SET(fd, &rfds);
+
+ n_fds = select(fd + 1, &rfds, NULL, NULL, &timeout);
+ if (n_fds < 0) {
+ rc = errno;
+ LOG_ERR(rc, "Failed to select");
+ continue;
+ }
+
+ /*
+ * no matter what, receive packet from nic first, as the nic
+ * has small amount of memory. Without read, the sending could
+ * fail due to OOM.
+ *
+ * TODO: We might want to do something smart here to prevent attack or
+ * just rx flooding. Disable the Receive Enable first, drain the buffer
+ * with oob_nic_receive(), then Tx, and enable Receive Enable after.
+ */
+ for (n_io = 0; n_io < 16; n_io++) {
+ rc = oob_nic_receive(nic, buf, sizeof(buf));
+ if (rc <= 0) {
+ no_rcv++;
+ break;
+ }
+ oob_intf_send(intf, buf, rc);
+ no_rcv = 0;
+ }
+
+ /*
+ * if we didn't receive any packet for NO_RCV_CHECK_THRESHOLD times,
+ * check the nic status
+ */
+ if (no_rcv >= NO_RCV_CHECK_THRESHOLD) {
+ while(oob_nic_get_status(nic, &sts)) {
+ usleep(1000);
+ }
+ LOG_INFO("Failed to receive packets for %d times. NIC status is "
+ "%x.%x", NO_RCV_CHECK_THRESHOLD, sts.ons_byte1, sts.ons_byte2);
+ /*
+ * if the NIC went through initialization, or not set force up, need to
+ * re-program the filters by calling oob_nic_start().
+ */
+ if ((sts.ons_byte1 & NIC_STATUS_D1_INIT)
+ || !(sts.ons_byte1 & NIC_STATUS_D1_FORCE_UP)) {
+ while(oob_nic_start(nic, mac)) {
+ usleep(1000);
+ }
+ }
+ no_rcv = 0;
+ }
+
+ if (n_fds > 0 && FD_ISSET(fd, &rfds)) {
+ for (n_io = 0; n_io < 1; n_io++) {
+ rc = oob_intf_receive(intf, buf, sizeof(buf));
+ if (rc <= 0) {
+ break;
+ }
+ oob_nic_send(nic, buf, rc);
+ }
+ }
+ }
+}
+
+int main(int argc, const char **argv) {
+
+ uint8_t mac[6];
+ oob_nic *nic;
+ oob_intf *intf;
+ struct wedge_eeprom_st eeprom;
+ int rc;
+ int from_eeprom = 0;
+
+ nic = oob_nic_open(0, 0x49);
+ if (!nic) {
+ return -1;
+ }
+
+ /* read EEPROM for the MAC */
+ if (wedge_eeprom_parse(NULL, &eeprom) == 0) {
+ if (eeprom.fbw_mac_size <= 0) {
+ LOG_ERR(EFAULT, "Invalid extended MAC size: %d", eeprom.fbw_mac_size);
+ } else {
+ uint16_t carry;
+ int pos;
+ /* use the last MAC address from the extended MAC range */
+ memcpy(mac, eeprom.fbw_mac_base, sizeof(mac));
+ if (eeprom.fbw_mac_size > 128) {
+ LOG_ERR(EFAULT, "Extended MAC size (%d) is too large.",
+ eeprom.fbw_mac_size);
+ carry = 127;
+ } else {
+ /*
+ * hack around bug device which have the same MAC address on
+ * left and right.
+ */
+ if (strncmp(eeprom.fbw_location, "LEFT", FBW_EEPROM_F_LOCATION) == 0) {
+ carry = eeprom.fbw_mac_size - 2;
+ } else {
+ carry = eeprom.fbw_mac_size - 1;
+ }
+ }
+ for (pos = sizeof(mac) - 1; pos >= 0 && carry; pos--) {
+ uint16_t tmp = mac[pos] + carry;
+ mac[pos] = tmp & 0xFF;
+ carry = tmp >> 8;
+ }
+ from_eeprom = 1;
+ }
+ }
+
+ if (!from_eeprom) {
+ while (oob_nic_get_mac(nic, mac)) {
+ usleep(1000);
+ }
+ /*
+ * increase the last byte of the mac by 1 and turn on the
+ * local administered bit to use it as the oob nic mac
+ */
+ mac[0] |= 0x2;
+ mac[5]++;
+ }
+
+ LOG_INFO("Retrieve MAC %x:%x:%x:%x:%x:%x from %s",
+ mac[0], mac[1], mac[2], mac[3], mac[4], mac[5],
+ (from_eeprom) ? "EEPROM" : "NIC");
+
+ /* create the tap interface */
+ intf = oob_intf_create("oob", mac);
+ if (!intf) {
+ return -1;
+ }
+
+ while (oob_nic_start(nic, mac)) {
+ usleep(1000);
+ }
+
+ io_loop(nic, intf, mac);
+
+ return 0;
+}
diff --git a/meta-facebook/meta-wedge/recipes-wedge/oob-nic/oob-nic/src/nic.c b/meta-facebook/meta-wedge/recipes-wedge/oob-nic/oob-nic/src/nic.c
new file mode 100644
index 0000000..a4dc071
--- /dev/null
+++ b/meta-facebook/meta-wedge/recipes-wedge/oob-nic/oob-nic/src/nic.c
@@ -0,0 +1,487 @@
+/*
+ * Copyright 2014-present Facebook. All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include "nic.h"
+
+#include <errno.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/ioctl.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+
+#include "facebook/i2c-dev.h"
+#include "facebook/log.h"
+
+struct oob_nic_t {
+ int on_bus;
+ uint8_t on_addr;
+ int on_file; /* the file descriptor */
+ uint8_t on_mac[6]; /* the mac address assigned to this NIC */
+};
+
+oob_nic* oob_nic_open(int bus, uint8_t addr) {
+ oob_nic *dev = NULL;
+ char fn[32];
+ int rc;
+
+ /* address must be 7 bits maximum */
+ if ((addr & 0x80)) {
+ LOG_ERR(EINVAL, "Address 0x%x has the 8th bit", addr);
+ return NULL;
+ }
+
+ dev = calloc(1, sizeof(*dev));
+ if (!dev) {
+ return NULL;
+ }
+ dev->on_bus = bus;
+ dev->on_addr = addr;
+
+ /* construct the device file name */
+ snprintf(fn, sizeof(fn), "/dev/i2c-%d", bus);
+ dev->on_file = open(fn, O_RDWR);
+ if (dev->on_file == -1) {
+ LOG_ERR(errno, "Failed to open i2c device %s", fn);
+ goto err_out;
+ }
+
+ /* assign the device address */
+ rc = ioctl(dev->on_file, I2C_SLAVE, dev->on_addr);
+ if (rc < 0) {
+ LOG_ERR(errno, "Failed to open slave @ address 0x%x", dev->on_addr);
+ goto err_out;
+ }
+
+ return dev;
+
+ err_out:
+ oob_nic_close(dev);
+ return NULL;
+}
+
+void oob_nic_close(oob_nic *dev) {
+ if (!dev) {
+ return;
+ }
+ if (dev->on_file != -1) {
+ close(dev->on_file);
+ }
+ free(dev);
+}
+
+int oob_nic_get_mac(oob_nic *dev, uint8_t mac[6]) {
+ int rc;
+ uint8_t buf[64];
+
+ rc = i2c_smbus_read_block_data(dev->on_file, NIC_READ_MAC_CMD, buf);
+ if (rc < 0) {
+ rc = errno;
+ LOG_ERR(rc, "Failed to get MAC on %d-%x",
+ dev->on_bus, dev->on_addr);
+ return -rc;
+ }
+
+ if (rc != NIC_READ_MAC_RES_LEN) {
+ LOG_ERR(EFAULT, "Unexpected response len (%d) for get MAC on %d-%x",
+ rc, dev->on_bus, dev->on_addr);
+ return -EFAULT;
+ }
+
+ if (buf[0] != NIC_READ_MAC_RES_OPT) {
+ LOG_ERR(EFAULT, "Unexpected response opt code (0x%x) get MAC on %d-%x",
+ buf[0], dev->on_bus, dev->on_addr);
+ return -EFAULT;
+ }
+
+ memcpy(mac, &buf[1], 6);
+
+ LOG_DBG("Get MAC on %d-%x: %x:%x:%x:%x:%x:%x", dev->on_bus, dev->on_addr,
+ mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
+ return 0;
+}
+
+int oob_nic_get_status(oob_nic *dev, oob_nic_status *status) {
+ int rc;
+ uint8_t buf[64];
+
+ rc = i2c_smbus_read_block_data(dev->on_file, NIC_READ_STATUS_CMD, buf);
+ if (rc < 0) {
+ rc = errno;
+ LOG_ERR(rc, "Failed to get status on %d-%x",
+ dev->on_bus, dev->on_addr);
+ return -rc;
+ }
+
+ if (rc != NIC_READ_STATUS_RES_LEN) {
+ LOG_ERR(EFAULT, "Unexpected response len (%d) for get status on %d-%x",
+ rc, dev->on_bus, dev->on_addr);
+ return -EFAULT;
+ }
+
+ if (buf[0] != NIC_READ_STATUS_RES_OPT) {
+ LOG_ERR(EFAULT, "Unexpected response opt code (0x%x) get status on %d-%x",
+ buf[0], dev->on_bus, dev->on_addr);
+ return -EFAULT;
+ }
+
+ memset(status, 0, sizeof(*status));
+ status->ons_byte1 = buf[1];
+ status->ons_byte2 = buf[2];
+
+ LOG_VER("Get status on %d-%x: byte1:0x%x byte2:0x%x",
+ dev->on_bus, dev->on_addr,
+ status->ons_byte1, status->ons_byte2);
+ return 0;
+}
+
+int oob_nic_receive(oob_nic *dev, uint8_t *buf, int len) {
+
+ int rc = 0;
+ uint8_t pkt[I2C_SMBUS_BLOCK_LARGE_MAX];
+ uint8_t opt;
+ int copied = 0;
+ int to_copy;
+ int expect_first = 1;
+ int n_frags = 0;
+
+#define _COPY_DATA(n, data) do { \
+ int to_copy; \
+ if (copied >= len) { \
+ break; \
+ } \
+ to_copy = (n < len - copied) ? n : len - copied; \
+ if (to_copy) { \
+ memcpy(buf + copied, data, to_copy); \
+ } \
+ copied += to_copy; \
+} while(0)
+
+ do {
+ rc = i2c_smbus_read_block_large_data(dev->on_file, NIC_READ_PKT_CMD, pkt);
+ if (rc < 0) {
+ rc = errno;
+ LOG_ERR(rc, "Failed to get packet on %d-%x",
+ dev->on_bus, dev->on_addr);
+ goto err_out;
+ }
+ if (rc > I2C_SMBUS_BLOCK_LARGE_MAX) {
+ LOG_ERR(EFAULT, "Too large i2c block (%d) received on %d-%x",
+ rc, dev->on_bus, dev->on_addr);
+ rc = EFAULT;
+ goto err_out;
+ }
+ opt = pkt[0];
+ switch (opt) {
+ case NIC_READ_PKT_RES_FIRST_OPT:
+ if (!expect_first) {
+ rc = EFAULT;
+ LOG_ERR(rc, "Received more than one buffer with FIRST set");
+ goto err_out;
+ }
+ expect_first = 0;
+ n_frags++;
+ _COPY_DATA(rc - 1, &pkt[1]);
+ break;
+ case NIC_READ_PKT_RES_MIDDLE_OPT:
+ if (expect_first) {
+ rc = EFAULT;
+ LOG_ERR(rc, "Received MIDDLE before getting FIRST");
+ goto err_out;
+ }
+ _COPY_DATA(rc - 1, &pkt[1]);
+ n_frags++;
+ break;
+ case NIC_READ_PKT_RES_LAST_OPT:
+ if (expect_first) {
+ rc = EFAULT;
+ LOG_ERR(rc, "Received LAST before getting FIRST");
+ goto err_out;
+ }
+ if (rc != NIC_READ_PKT_RES_LAST_LEN) {
+ LOG_ERR(EFAULT, "Expect %d bytes (got %d) for LAST segement",
+ NIC_READ_PKT_RES_LAST_LEN, rc);
+ rc = EFAULT;
+ goto err_out;
+ }
+ /* TODO: pkt status???? */
+ break;
+ case NIC_READ_STATUS_RES_OPT:
+ /* that means no pkt available */
+ if (!expect_first) {
+ rc = EFAULT;
+ LOG_ERR(rc, "Received STATUS in the middle of packet");
+ goto err_out;
+ }
+ //LOG_VER("Received STATUS when receiving the packet");
+ return 0;
+ default:
+ rc = EFAULT;
+ LOG_ERR(rc, "Unexpected opt code 0x%x", opt);
+ goto err_out;
+ }
+ } while (opt != NIC_READ_PKT_RES_LAST_OPT);
+
+ LOG_VER("Received a packet with %d bytes in %d fragments", copied, n_frags);
+ return copied;
+
+ err_out:
+ return -rc;
+#undef _COPY_DATA
+}
+
+int oob_nic_send(oob_nic *dev, const uint8_t *data, int len) {
+
+ int rc;
+ uint8_t to_send;
+ int has_sent = 0;
+ int is_first = 1;
+ uint8_t cmd;
+ int n_frags = 0;
+
+ if (len <= 0 || len > NIC_PKT_SIZE_MAX) {
+ rc = EINVAL;
+ LOG_ERR(rc, "Invalid packet length %d", len);
+ return -rc;
+ }
+
+ while (len) {
+ to_send = (len < OOB_NIC_PKT_FRAGMENT_SIZE)
+ ? len : OOB_NIC_PKT_FRAGMENT_SIZE;
+
+ if (is_first) {
+ if (to_send >= len) {
+ /* this is the last pkt also */
+ cmd = NIC_WRITE_PKT_SINGLE_CMD;
+ } else {
+ cmd = NIC_WRITE_PKT_FIRST_CMD;
+ }
+ is_first = 0;
+ } else {
+ if (to_send >= len) {
+ /* this is the last pkt */
+ cmd = NIC_WRITE_PKT_LAST_CMD;
+ } else {
+ cmd = NIC_WRITE_PKT_MIDDLE_CMD;
+ }
+ }
+
+ rc = i2c_smbus_write_block_large_data(dev->on_file, cmd,
+ to_send, data + has_sent);
+ if (rc < 0) {
+ rc = errno;
+ LOG_ERR(rc, "Failed to sent packet with cmd 0x%x, has_sent=%d "
+ "to_send=%d", cmd, has_sent, to_send);
+ return -rc;
+ }
+
+ has_sent += to_send;
+ len -= to_send;
+ n_frags++;
+ }
+
+ LOG_VER("Sent a packet with %d bytes in %d fragments", has_sent, n_frags);
+
+ return has_sent;
+}
+
+static int oob_nic_set_mng_ctrl(oob_nic *dev, const uint8_t *data, int len) {
+ int rc;
+
+ if (len <= 0) {
+ rc = EINVAL;
+ LOG_ERR(rc, "Invalid data length: %d", len);
+ return -rc;
+ }
+
+ rc = i2c_smbus_write_block_data(dev->on_file, NIC_WRITE_MNG_CTRL_CMD,
+ len, data);
+ if (rc < 0) {
+ rc = errno;
+ LOG_ERR(rc, "Failed to send management control command for parameter # %d",
+ data[0]);
+ return -rc;
+ }
+
+ return 0;
+}
+
+static int oob_nic_set_force_up(oob_nic *dev, int enable) {
+ uint8_t cmd[2];
+
+ cmd[0] = NIC_MNG_CTRL_KEEP_LINK_UP_NUM;
+ cmd[1] = enable
+ ? NIC_MNG_CTRL_KEEP_LINK_UP_ENABLE : NIC_MNG_CTRL_KEEP_LINK_UP_DISABLE;
+
+ LOG_DBG("Turn %s link force up", enable ? "on" : "off");
+ return oob_nic_set_mng_ctrl(dev, cmd, sizeof(cmd));
+}
+
+static int oob_nic_setup_filters(oob_nic *dev, const uint8_t mac[6]) {
+ int rc;
+ int i;
+ uint32_t cmd32;
+ uint8_t buf[32];
+ uint8_t *cmd;
+
+ /*
+ * Command to set MAC filter
+ * Seven bytes are required to load the MAC address filters.
+ * Data 2—MAC address filters pair number (3:0).
+ * Data 3—MSB of MAC address.
+ * ...
+ * Data 8: LSB of MAC address.
+ */
+ /* set MAC filter to pair 0 */
+ cmd = buf;
+ *cmd++ = NIC_FILTER_MAC_NUM;
+ *cmd++ = NIC_FILTER_MAC_PAIR0; /* pair 0 */
+ for (i = 0; i < 6; i++) {
+ *cmd++ = mac[i];
+ }
+ rc = i2c_smbus_write_block_data(dev->on_file, NIC_WRITE_FILTER_CMD,
+ cmd - buf, buf);
+ if (rc < 0) {
+ rc = errno;
+ LOG_ERR(rc, "Failed to set MAC filter");
+ return -rc;
+ }
+
+ /*
+ * Command to enable filter
+ *
+ * 9 bytes to load the extended decision filters (MDEF_EXT & MDEF)
+ * Data 2—MDEF filter index (valid values are 0...6)
+ * Data 3—MSB of MDEF_EXT (DecisionFilter0)
+ * ....
+ * Data 6—LSB of MDEF_EXT (DecisionFilter0)
+ * Data 7—MSB of MDEF (DecisionFilter0)
+ * ....
+ * Data 10—LSB of MDEF (DecisionFilter0)
+ */
+
+ /* enable MAC filter pair 0 on filter 0 */
+ cmd = buf;
+ *cmd++ = NIC_FILTER_DECISION_EXT_NUM;
+ *cmd++ = NIC_FILTER_MDEF0;
+ /* enable filter for traffic from network and host */
+ cmd32 = NIC_FILTER_MDEF_BIT(NIC_FILTER_MDEF_EXT_NET_EN_OFFSET)
+ | NIC_FILTER_MDEF_BIT(NIC_FILTER_MDEF_EXT_HOST_EN_OFFSET);
+ for (i = 0; i < sizeof(cmd32); i++) {
+ *cmd++ = (cmd32 >> (24 - 8 * i)) & 0xFF;
+ }
+ /* enable mac pair 0 */
+ cmd32 = NIC_FILTER_MDEF_BIT_VAL(NIC_FILTER_MDEF_MAC_AND_OFFSET,
+ NIC_FILTER_MAC_PAIR0);
+ for (i = 0; i < sizeof(cmd32); i++) {
+ *cmd++ = (cmd32 >> (24 - 8 * i)) & 0xFF;
+ }
+ rc = i2c_smbus_write_block_data(dev->on_file, NIC_WRITE_FILTER_CMD,
+ cmd - buf, buf);
+ if (rc < 0) {
+ rc = errno;
+ LOG_ERR(rc, "Failed to set MAC filter to MDEF 0");
+ return -rc;
+ }
+ /* enable ARP and ND on filter 1*/
+ cmd = buf;
+ *cmd++ = NIC_FILTER_DECISION_EXT_NUM;
+ *cmd++ = NIC_FILTER_MDEF1;
+ /* enable filter for traffic from network and host */
+ cmd32 = NIC_FILTER_MDEF_BIT(NIC_FILTER_MDEF_EXT_NET_EN_OFFSET)
+ | NIC_FILTER_MDEF_BIT(NIC_FILTER_MDEF_EXT_HOST_EN_OFFSET);
+ for (i = 0; i < sizeof(cmd32); i++) {
+ *cmd++ = (cmd32 >> (24 - 8 * i)) & 0xFF;
+ }
+ /* enable ARP and ND */
+ cmd32 = NIC_FILTER_MDEF_BIT(NIC_FILTER_MDEF_ARP_REQ_OR_OFFSET)
+ | NIC_FILTER_MDEF_BIT(NIC_FILTER_MDEF_ARP_RES_OR_OFFSET)
+ | NIC_FILTER_MDEF_BIT(NIC_FILTER_MDEF_NBG_OR_OFFSET);
+ for (i = 0; i < sizeof(cmd32); i++) {
+ *cmd++ = (cmd32 >> (24 - 8 * i)) & 0xFF;
+ }
+ rc = i2c_smbus_write_block_data(dev->on_file, NIC_WRITE_FILTER_CMD,
+ cmd - buf, buf);
+ if (rc < 0) {
+ rc = errno;
+ LOG_ERR(rc, "Failed to set ARP and ND filter to MDEF 1");
+ return -rc;
+ }
+
+ /* make filter 0, matching MAC, to be mng only */
+ cmd = buf;
+ *cmd++ = NIC_FILTER_MNG_ONLY_NUM;
+ cmd32 = NIC_FILTER_MNG_ONLY_FILTER0;
+ for (i = 0; i < sizeof(cmd32); i++) {
+ *cmd++ = (cmd32 >> (24 - 8 * i)) & 0xFF;
+ }
+ rc = i2c_smbus_write_block_data(dev->on_file, NIC_WRITE_FILTER_CMD,
+ cmd - buf, buf);
+ if (rc < 0) {
+ rc = errno;
+ LOG_ERR(rc, "Failed to enabled management only filter");
+ return -rc;
+ }
+
+ return 0;
+}
+
+int oob_nic_start(oob_nic *dev, const uint8_t mac[6]) {
+ int rc;
+ uint8_t cmd;
+
+ /* force the link up, no matter what the status of the main link */
+ rc = oob_nic_set_force_up(dev, 1);
+ if (rc != 0) {
+ return rc;
+ }
+
+ oob_nic_setup_filters(dev, mac);
+
+ /* first byte is the control */
+ cmd = NIC_WRITE_RECV_ENABLE_EN
+ | NIC_WRITE_RECV_ENABLE_STA
+ | NIC_WRITE_RECV_ENABLE_NM_UNSUPP /* TODO, to support ALERT */
+ | NIC_WRITE_RECV_ENABLE_RESERVED;
+
+ rc = i2c_smbus_write_block_data(dev->on_file, NIC_WRITE_RECV_ENABLE_CMD,
+ 1, &cmd);
+ if (rc < 0) {
+ rc = errno;
+ LOG_ERR(rc, "Failed to start receive function");
+ return -rc;
+ }
+ LOG_DBG("Started receive function");
+ return 0;
+}
+
+int oob_nic_stop(oob_nic *dev) {
+ int rc;
+ uint8_t ctrl;
+ /* don't set any enable bits, which turns off the receive func */
+ ctrl = NIC_WRITE_RECV_ENABLE_RESERVED;
+ rc = i2c_smbus_write_block_data(dev->on_file, NIC_WRITE_RECV_ENABLE_CMD,
+ 1, &ctrl);
+ if (rc < 0) {
+ rc = errno;
+ LOG_ERR(rc, "Failed to stop receive function");
+ return -rc;
+ }
+ LOG_DBG("Stopped receive function");
+ return 0;
+}
diff --git a/meta-facebook/meta-wedge/recipes-wedge/oob-nic/oob-nic/src/nic.h b/meta-facebook/meta-wedge/recipes-wedge/oob-nic/oob-nic/src/nic.h
new file mode 100644
index 0000000..1ac7ff8
--- /dev/null
+++ b/meta-facebook/meta-wedge/recipes-wedge/oob-nic/oob-nic/src/nic.h
@@ -0,0 +1,44 @@
+/*
+ * Copyright 2014-present Facebook. All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#ifndef NIC_H
+#define NIC_H
+
+#include <stdint.h>
+
+#include "nic_defs.h"
+
+typedef struct oob_nic_t oob_nic;
+
+oob_nic* oob_nic_open(int bus, uint8_t addr);
+void oob_nic_close(oob_nic* dev);
+
+/* MAC */
+int oob_nic_get_mac(oob_nic *dev, uint8_t mac[6]);
+
+/* Status */
+typedef struct oob_nic_status_t oob_nic_status;
+int oob_nic_get_status(oob_nic *dev, oob_nic_status *status);
+
+int oob_nic_start(oob_nic *dev, const uint8_t mac[6]);
+int oob_nic_stop(oob_nic *dev);
+
+int oob_nic_send(oob_nic *dev, const uint8_t *data, int len);
+
+int oob_nic_receive(oob_nic *dev, uint8_t *buf, int len);
+
+#endif
diff --git a/meta-facebook/meta-wedge/recipes-wedge/oob-nic/oob-nic/src/nic_defs.h b/meta-facebook/meta-wedge/recipes-wedge/oob-nic/oob-nic/src/nic_defs.h
new file mode 100644
index 0000000..1ae8721
--- /dev/null
+++ b/meta-facebook/meta-wedge/recipes-wedge/oob-nic/oob-nic/src/nic_defs.h
@@ -0,0 +1,143 @@
+/*
+ * Copyright 2014-present Facebook. All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#ifndef NIC_DEFS_H
+#define NIC_DEFS_H
+
+#include <stdint.h>
+
+#define OOB_NIC_PKT_FRAGMENT_SIZE 240
+#define NIC_PKT_SIZE_MAX 1536
+
+/** Get System MAC Address */
+#define NIC_READ_MAC_CMD 0xD4
+#define NIC_READ_MAC_RES_OPT 0xD4
+#define NIC_READ_MAC_RES_LEN 7
+
+/** Read Status */
+#define NIC_READ_STATUS_CMD 0xDE
+#define NIC_READ_STATUS_RES_OPT 0xDD
+#define NIC_READ_STATUS_RES_LEN 3
+
+struct oob_nic_status_t {
+ uint8_t ons_byte1;
+ uint8_t ons_byte2;
+};
+
+#define NIC_STATUS_D1_POWER_DR 0x00
+#define NIC_STATUS_D1_POWER_D0U 0x01
+#define NIC_STATUS_D1_POWER_D0 0x10
+#define NIC_STATUS_D1_POWER_D3 0x11
+#define NIC_STATUS_D1_PORT_MSB (0x1 << 2)
+#define NIC_STATUS_D1_INIT (0x1 << 3)
+#define NIC_STATUS_D1_FORCE_UP (0x1 << 4)
+#define NIC_STATUS_D1_LINK (0x1 << 5)
+#define NIC_STATUS_D1_TCO_CMD_ABORT (0x1 << 6)
+#define NIC_STATUS_D1_PORT_LSB (0x1 << 7)
+
+#define NIC_STATUS_D2_ICR (0x1 << 1)
+#define NIC_STATUS_D2_IPI (0x1 << 2)
+#define NIC_STATUS_D2_DRV_VALID (0x1 << 3)
+
+/** Receive TCO Packet */
+#define NIC_READ_PKT_CMD 0xC0
+#define NIC_READ_PKT_RES_FIRST_OPT 0x90
+#define NIC_READ_PKT_RES_MIDDLE_OPT 0x10
+#define NIC_READ_PKT_RES_LAST_OPT 0x50
+#define NIC_READ_PKT_RES_LAST_LEN 17
+
+/** Transmit Packet */
+#define NIC_WRITE_PKT_SINGLE_CMD 0xC4
+#define NIC_WRITE_PKT_FIRST_CMD 0x84
+#define NIC_WRITE_PKT_MIDDLE_CMD 0x04
+#define NIC_WRITE_PKT_LAST_CMD 0x44
+
+/** Management Control */
+#define NIC_WRITE_MNG_CTRL_CMD 0xC1
+
+#define NIC_MNG_CTRL_KEEP_LINK_UP_NUM 0x00
+#define NIC_MNG_CTRL_KEEP_LINK_UP_ENABLE 0x01
+#define NIC_MNG_CTRL_KEEP_LINK_UP_DISABLE 0x00
+
+/** Update MNG RCV Filter Parameters */
+#define NIC_WRITE_FILTER_CMD 0xCC
+
+#define NIC_FILTER_MAC_NUM 0x66
+#define NIC_FILTER_MAC_PAIR0 0
+#define NIC_FILTER_MAC_PAIR1 1
+#define NIC_FILTER_MAC_PAIR2 2
+#define NIC_FILTER_MAC_PAIR3 3
+
+#define NIC_FILTER_MNG_ONLY_NUM 0xF
+#define NIC_FILTER_MNG_ONLY_FILTER0 (0x1)
+#define NIC_FILTER_MNG_ONLY_FILTER1 (0x1 << 1)
+#define NIC_FILTER_MNG_ONLY_FILTER2 (0x1 << 2)
+#define NIC_FILTER_MNG_ONLY_FILTER3 (0x1 << 3)
+#define NIC_FILTER_MNG_ONLY_FILTER4 (0x1 << 4)
+
+#define NIC_FILTER_DECISION_EXT_NUM 0x68
+#define NIC_FILTER_MDEF0 0 /* index 0 */
+#define NIC_FILTER_MDEF1 1 /* index 1 */
+#define NIC_FILTER_MDEF2 2 /* index 2 */
+#define NIC_FILTER_MDEF3 3 /* index 3 */
+#define NIC_FILTER_MDEF4 4 /* index 4 */
+#define NIC_FILTER_MDEF5 5 /* index 5 */
+#define NIC_FILTER_MDEF6 6 /* index 6 */
+#define NIC_FILTER_MDEF7 7 /* index 7 */
+
+#define NIC_FILTER_MDEF_MAC_AND_OFFSET 0
+#define NIC_FILTER_MDEF_BCAST_AND_OFFSET 4
+#define NIC_FILTER_MDEF_VLAN_AND_OFFSET 5
+#define NIC_FILTER_MDEF_IPV4_AND_OFFSET 13
+#define NIC_FILTER_MDEF_IPV6_AND_OFFSET 17
+#define NIC_FILTER_MDEF_MAC_OR_OFFSET 21
+#define NIC_FILTER_MDEF_BCAST_OR_OFFSET 25
+#define NIC_FILTER_MDEF_MCAST_AND_OFFSET 26
+#define NIC_FILTER_MDEF_ARP_REQ_OR_OFFSET 27
+#define NIC_FILTER_MDEF_ARP_RES_OR_OFFSET 28
+#define NIC_FILTER_MDEF_NBG_OR_OFFSET 29
+#define NIC_FILTER_MDEF_PORT298_OR_OFFSET 30
+#define NIC_FILTER_MDEF_PORT26F_OR_OFFSET 31
+
+#define NIC_FILTER_MDEF_EXT_ETHTYPE_AND_OFFSET 0
+#define NIC_FILTER_MDEF_EXT_ETHTYPE_OR_OFFSET 8
+#define NIC_FILTER_MDEF_EXT_FLEX_PORT_OR_OFFSET 16
+#define NIC_FILTER_MDEF_EXT_FLEX_TCO_OR_OFFSET 24
+#define NIC_FILTER_MDEF_EXT_NCSI_DISABLE_OFFSET 28
+#define NIC_FILTER_MDEF_EXT_FLOW_CONTROL_DISCARD_OFFSET 29
+#define NIC_FILTER_MDEF_EXT_NET_EN_OFFSET 30
+#define NIC_FILTER_MDEF_EXT_HOST_EN_OFFSET 31
+
+#define NIC_FILTER_MDEF_BIT(offset) ((0x1) << (offset))
+#define NIC_FILTER_MDEF_BIT_VAL(offset, val) ((0x1) << ((offset) + (val)))
+
+/** Receive Enable */
+#define NIC_WRITE_RECV_ENABLE_CMD 0xCA
+#define NIC_WRITE_RECV_ENABLE_LEN_MAX 14
+
+#define NIC_WRITE_RECV_ENABLE_EN 0x1
+#define NIC_WRITE_RECV_ENABLE_ALL (0x1 << 1)
+#define NIC_WRITE_RECV_ENABLE_STA (0x1 << 2)
+#define NIC_WRITE_RECV_ENABLE_ARP_RES (0x1 << 3)
+#define NIC_WRITE_RECV_ENABLE_NM_ALERT (0x00 << 4)
+#define NIC_WRITE_RECV_ENABLE_NM_ASYNC (0x01 << 4)
+#define NIC_WRITE_RECV_ENABLE_NM_DIRECT (0x02 << 4)
+#define NIC_WRITE_RECV_ENABLE_NM_UNSUPP (0x03 << 4)
+#define NIC_WRITE_RECV_ENABLE_RESERVED (0x1 << 6)
+#define NIC_WRITE_RECV_ENABLE_CBDM (0x1 << 7)
+
+#endif
diff --git a/meta-facebook/meta-wedge/recipes-wedge/oob-nic/oob-nic_0.1.bb b/meta-facebook/meta-wedge/recipes-wedge/oob-nic/oob-nic_0.1.bb
new file mode 100644
index 0000000..1df83dc
--- /dev/null
+++ b/meta-facebook/meta-wedge/recipes-wedge/oob-nic/oob-nic_0.1.bb
@@ -0,0 +1,29 @@
+# Copyright 2014-present Facebook. All Rights Reserved.
+
+SUMMARY = "OOB Shared NIC driver"
+DESCRIPTION = "The shared-nic driver"
+SECTION = "base"
+PR = "r2"
+LICENSE = "GPLv2"
+LIC_FILES_CHKSUM = "file://main.c;beginline=4;endline=16;md5=da35978751a9d71b73679307c4d296ec"
+
+SRC_URI = "file://src \
+ "
+
+S = "${WORKDIR}/src"
+
+DEPENDS += "fbutils libwedge-eeprom"
+
+RDEPENDS_${PN} += "libwedge-eeprom"
+
+do_install() {
+ install -d ${D}${sbindir}
+ install -m 755 oob-nic ${D}${sbindir}/oob-nic
+ install -m 755 i2craw ${D}${sbindir}/i2craw
+ install -d ${D}${sysconfdir}/init.d
+ install -d ${D}${sysconfdir}/rcS.d
+ install -m 755 etc/oob-nic.sh ${D}${sysconfdir}/init.d/oob-nic.sh
+ update-rc.d -r ${D} oob-nic.sh start 80 S .
+}
+
+FILES_${PN} = " ${sbindir} ${sysconfdir} "
diff --git a/meta-facebook/meta-wedge/recipes-wedge/po-eeprom/files/Makefile b/meta-facebook/meta-wedge/recipes-wedge/po-eeprom/files/Makefile
new file mode 100644
index 0000000..408de95
--- /dev/null
+++ b/meta-facebook/meta-wedge/recipes-wedge/po-eeprom/files/Makefile
@@ -0,0 +1,10 @@
+# Copyright 2014-present Facebook. All Rights Reserved.
+all: po-eeprom
+
+po-eeprom: po-eeprom.o
+ $(CC) -o $@ $^ $(LDFLAGS)
+
+.PHONY: clean
+
+clean:
+ rm -rf *.o po-eeprom
diff --git a/meta-facebook/meta-wedge/recipes-wedge/po-eeprom/files/po-eeprom.c b/meta-facebook/meta-wedge/recipes-wedge/po-eeprom/files/po-eeprom.c
new file mode 100644
index 0000000..46debee
--- /dev/null
+++ b/meta-facebook/meta-wedge/recipes-wedge/po-eeprom/files/po-eeprom.c
@@ -0,0 +1,80 @@
+/*
+ * Copyright 2014-present Facebook. All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <sys/types.h>
+
+#define SERIAL_LEN 17
+
+usage()
+{
+ fprintf(stderr, "Usage: po-eeprom filename [filename...]\n"
+ "\twhere filename is the location of the PowerOne EEPROM, likely\n"
+ "\t/sys/bus/i2c/drivers/at24/7-0051/eeprom or\n"
+ "\t/sys/bus/i2c/drivers/at24/7-0052/eeprom\n");
+ exit(2);
+}
+
+int safe_read(int fd, void *buf, size_t size, char *msg)
+{
+ if (read(fd, buf, size) != size) {
+ perror(msg);
+ exit(3);
+ }
+}
+
+int main(int argc, char **argv)
+{
+ int fd;
+ int file = 1;
+ uint8_t size;
+ uint8_t junk;
+ uint16_t crc;
+ char serial[SERIAL_LEN + 1];
+
+ if (argc < 2)
+ usage();
+
+ while (file < argc) {
+ fd = open(argv[file], O_RDONLY);
+ if (fd < 0) {
+ fprintf(stderr, "Couldn't open %s for EEPROM reading\n", argv[1]);
+ exit(1);
+ }
+
+ safe_read(fd, &size, sizeof(size), "read size");
+ safe_read(fd, &junk, sizeof(junk), "read junk");
+ /*
+ * Should probably check CRC here, PowerOne provided some code where
+ * it looks like a pretty standard CCITT CRC16.
+ */
+ safe_read(fd, &crc, sizeof(crc), "read CRC len");
+ safe_read(fd, serial, SERIAL_LEN, "read serial number");
+
+ serial[SERIAL_LEN] = 0;
+ printf("Serial number: %s\n", serial);
+ close(fd);
+ file++;
+ }
+}
diff --git a/meta-facebook/meta-wedge/recipes-wedge/po-eeprom/po-eeprom_0.1.bb b/meta-facebook/meta-wedge/recipes-wedge/po-eeprom/po-eeprom_0.1.bb
new file mode 100644
index 0000000..e1d8b32
--- /dev/null
+++ b/meta-facebook/meta-wedge/recipes-wedge/po-eeprom/po-eeprom_0.1.bb
@@ -0,0 +1,25 @@
+# Copyright 2014-present Facebook. All Rights Reserved.
+SUMMARY = "PowerOne EEPROM Utilities"
+DESCRIPTION = "Util for PowerOne eeprom"
+SECTION = "base"
+PR = "r1"
+LICENSE = "GPLv2"
+LIC_FILES_CHKSUM = "file://po-eeprom.c;beginline=4;endline=16;md5=da35978751a9d71b73679307c4d296ec"
+
+SRC_URI = "file://po-eeprom.c \
+ file://Makefile \
+ "
+
+S = "${WORKDIR}"
+
+do_install() {
+ install -d ${D}${bindir}
+ install -m 0755 po-eeprom ${D}${bindir}/po-eeprom
+}
+
+FILES_${PN} = "${bindir}"
+
+# Inhibit complaints about .debug directories
+
+INHIBIT_PACKAGE_DEBUG_SPLIT = "1"
+INHIBIT_PACKAGE_STRIP = "1"
diff --git a/meta-facebook/meta-wedge/recipes-wedge/rackmon/rackmon/Makefile b/meta-facebook/meta-wedge/recipes-wedge/rackmon/rackmon/Makefile
new file mode 100644
index 0000000..4a3c25d
--- /dev/null
+++ b/meta-facebook/meta-wedge/recipes-wedge/rackmon/rackmon/Makefile
@@ -0,0 +1,16 @@
+# Copyright 2014-present Facebook. All Rights Reserved.
+all: modbuscmd gpiowatch modbussim
+
+modbuscmd: modbuscmd.c modbus.c
+ $(CC) -D_BSD_SOURCE -Wall -Werror -std=c99 -o $@ $^ $(LDFLAGS)
+
+modbussim: modbussim.c modbus.c
+ $(CC) -D_BSD_SOURCE -Wall -Werror -std=c99 -o $@ $^ $(LDFLAGS)
+
+gpiowatch: gpiowatch.c
+ $(CC) -D_BSD_SOURCE -Wall -Werror -std=c99 -o $@ $^ $(LDFLAGS)
+
+.PHONY: clean
+
+clean:
+ rm -rf *.o modbuscmd gpiowatch modbussim
diff --git a/meta-facebook/meta-wedge/recipes-wedge/rackmon/rackmon/gpiowatch.c b/meta-facebook/meta-wedge/recipes-wedge/rackmon/rackmon/gpiowatch.c
new file mode 100644
index 0000000..11b5471
--- /dev/null
+++ b/meta-facebook/meta-wedge/recipes-wedge/rackmon/rackmon/gpiowatch.c
@@ -0,0 +1,93 @@
+/*
+ * Copyright 2014-present Facebook. All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <fcntl.h>
+
+#define CHECK(x) { if((x) < 0) { \
+ error = x; \
+ goto cleanup; \
+} }
+
+#define CHECKNULL(x) { if((x) == NULL) { \
+ error = -1; \
+ goto cleanup; \
+} }
+
+typedef struct {
+ int fd;
+ int gpio;
+ char value;
+} wgpio;
+
+int main(int argc, char **argv) {
+ int error = 0;
+ int nfds = argc - 1;
+ int i = 0;
+ int polliv = 10000;
+ wgpio* wgpios = NULL;
+
+ if(argc < 2) {
+ fprintf(stderr, "Usage: %s <gpio num> [gpio num] [gpio num...]\n", argv[0]);
+ exit(1);
+ }
+ if(getenv("POLL_US")) {
+ polliv = atoi(getenv("POLL_US"));
+ }
+
+ wgpios = calloc(nfds, sizeof(wgpio));
+ CHECKNULL(wgpios)
+
+ fprintf(stderr, "Watching %d gpios:", nfds);
+ for(i = 1; i < argc; i++) {
+ char filename[255];
+ int gpio_num = atoi(argv[i]);
+ wgpios[i - 1].gpio = gpio_num;
+ snprintf(filename, 255, "/sys/class/gpio/gpio%d/value", gpio_num);
+ wgpios[i - 1].fd = open(filename, O_RDONLY);
+ CHECK(wgpios[i - 1].fd);
+ CHECK(read(wgpios[i - 1].fd, &(wgpios[i - 1].value), 1));
+ fprintf(stderr, " %d (currently: %c)", gpio_num, wgpios[i - 1].value);
+ }
+ fprintf(stderr, "\n");
+
+ do {
+ usleep(polliv);
+ for(i = 0; i < nfds; i++) {
+ wgpio* w = &wgpios[i];
+ char value;
+ lseek(w->fd, 0, SEEK_SET);
+ CHECK(read(w->fd, &value, 1));
+ if(value != w->value) {
+ printf("GPIO%d: %c -> %c\n", w->gpio, w->value, value);
+ w->value = value;
+ }
+ }
+ } while (1);
+
+cleanup:
+ if(error != 0) {
+ fprintf(stderr, "Error %d: %s\n", errno, strerror(errno));
+ error = 1;
+ }
+ return error;
+}
diff --git a/meta-facebook/meta-wedge/recipes-wedge/rackmon/rackmon/modbus.c b/meta-facebook/meta-wedge/recipes-wedge/rackmon/rackmon/modbus.c
new file mode 100644
index 0000000..46618a9
--- /dev/null
+++ b/meta-facebook/meta-wedge/recipes-wedge/rackmon/rackmon/modbus.c
@@ -0,0 +1,183 @@
+/*
+ * Copyright 2014-present Facebook. All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include "modbus.h"
+#include <termios.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <sys/ioctl.h>
+
+static int loops = 0;
+void waitfd(int fd) {
+ while(1) {
+ int lsr;
+ int ret = ioctl(fd, TIOCSERGETLSR, &lsr);
+ if(ret == -1) {
+ fprintf(stderr, "Error checking ioctl: %s\n", strerror(errno));
+ break;
+ }
+ if(lsr & TIOCSER_TEMT) break;
+ loops++;
+ }
+}
+
+void gpio_on(int fd) {
+ lseek(fd, 0, SEEK_SET);
+ write(fd, "1", 1);
+}
+
+void gpio_off(int fd) {
+ lseek(fd, 0, SEEK_SET);
+ write(fd, "0", 1);
+}
+
+void decode_hex_in_place(char* buf, size_t* len) {
+ for(int i = 0; i < *len; i+=2) {
+ sscanf(buf + i, "%2hhx", buf + (i / 2));
+ }
+ *len = *len / 2;
+}
+
+void append_modbus_crc16(char* buf, size_t* len) {
+ uint16_t crc = modbus_crc16(buf, *len);
+ if (verbose)
+ fprintf(stderr, "[*] Append Modbus CRC16 %04x\n", crc);
+ buf[(*len)++] = crc >> 8;
+ buf[(*len)++] = crc & 0x00FF;
+}
+
+void print_hex(FILE* f, char* buf, size_t len) {
+ for(int i = 0; i < len; i++)
+ fprintf(f, "%02x ", buf[i]);
+}
+
+size_t read_wait(int fd, char* dst, size_t maxlen, int mdelay_us) {
+ fd_set fdset;
+ struct timeval timeout;
+ char read_buf[16];
+ size_t read_size = 0;
+ size_t pos = 0;
+ memset(dst, 0, maxlen);
+ for(;;) {
+ FD_ZERO(&fdset);
+ FD_SET(fd, &fdset);
+ timeout.tv_sec = 0;
+ timeout.tv_usec = mdelay_us;
+ int rv = select(fd + 1, &fdset, NULL, NULL, &timeout);
+ if(rv == -1) {
+ perror("select()");
+ } else if (rv == 0) {
+ break;
+ }
+ read_size = read(fd, read_buf, 16);
+ if(read_size < 0) {
+ if(errno == EAGAIN) continue;
+ fprintf(stderr, "read error: %s\n", strerror(errno));
+ exit(1);
+ }
+ if((pos + read_size) < maxlen) {
+ memcpy(dst + pos, read_buf, read_size);
+ pos += read_size;
+ } else {
+ fprintf(stderr, "Response buffer overflowed!\n");
+ }
+ }
+ return pos;
+}
+
+/* From libmodbus, https://github.com/stephane/libmodbus
+ * Under LGPL. */
+/* Table of CRC values for high-order byte */
+static const uint8_t table_crc_hi[] = {
+ 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,
+ 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
+ 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,
+ 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
+ 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1,
+ 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
+ 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1,
+ 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
+ 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,
+ 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40,
+ 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1,
+ 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
+ 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,
+ 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40,
+ 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,
+ 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
+ 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,
+ 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
+ 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,
+ 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
+ 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,
+ 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40,
+ 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1,
+ 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
+ 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,
+ 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40
+};
+
+/* Table of CRC values for low-order byte */
+static const uint8_t table_crc_lo[] = {
+ 0x00, 0xC0, 0xC1, 0x01, 0xC3, 0x03, 0x02, 0xC2, 0xC6, 0x06,
+ 0x07, 0xC7, 0x05, 0xC5, 0xC4, 0x04, 0xCC, 0x0C, 0x0D, 0xCD,
+ 0x0F, 0xCF, 0xCE, 0x0E, 0x0A, 0xCA, 0xCB, 0x0B, 0xC9, 0x09,
+ 0x08, 0xC8, 0xD8, 0x18, 0x19, 0xD9, 0x1B, 0xDB, 0xDA, 0x1A,
+ 0x1E, 0xDE, 0xDF, 0x1F, 0xDD, 0x1D, 0x1C, 0xDC, 0x14, 0xD4,
+ 0xD5, 0x15, 0xD7, 0x17, 0x16, 0xD6, 0xD2, 0x12, 0x13, 0xD3,
+ 0x11, 0xD1, 0xD0, 0x10, 0xF0, 0x30, 0x31, 0xF1, 0x33, 0xF3,
+ 0xF2, 0x32, 0x36, 0xF6, 0xF7, 0x37, 0xF5, 0x35, 0x34, 0xF4,
+ 0x3C, 0xFC, 0xFD, 0x3D, 0xFF, 0x3F, 0x3E, 0xFE, 0xFA, 0x3A,
+ 0x3B, 0xFB, 0x39, 0xF9, 0xF8, 0x38, 0x28, 0xE8, 0xE9, 0x29,
+ 0xEB, 0x2B, 0x2A, 0xEA, 0xEE, 0x2E, 0x2F, 0xEF, 0x2D, 0xED,
+ 0xEC, 0x2C, 0xE4, 0x24, 0x25, 0xE5, 0x27, 0xE7, 0xE6, 0x26,
+ 0x22, 0xE2, 0xE3, 0x23, 0xE1, 0x21, 0x20, 0xE0, 0xA0, 0x60,
+ 0x61, 0xA1, 0x63, 0xA3, 0xA2, 0x62, 0x66, 0xA6, 0xA7, 0x67,
+ 0xA5, 0x65, 0x64, 0xA4, 0x6C, 0xAC, 0xAD, 0x6D, 0xAF, 0x6F,
+ 0x6E, 0xAE, 0xAA, 0x6A, 0x6B, 0xAB, 0x69, 0xA9, 0xA8, 0x68,
+ 0x78, 0xB8, 0xB9, 0x79, 0xBB, 0x7B, 0x7A, 0xBA, 0xBE, 0x7E,
+ 0x7F, 0xBF, 0x7D, 0xBD, 0xBC, 0x7C, 0xB4, 0x74, 0x75, 0xB5,
+ 0x77, 0xB7, 0xB6, 0x76, 0x72, 0xB2, 0xB3, 0x73, 0xB1, 0x71,
+ 0x70, 0xB0, 0x50, 0x90, 0x91, 0x51, 0x93, 0x53, 0x52, 0x92,
+ 0x96, 0x56, 0x57, 0x97, 0x55, 0x95, 0x94, 0x54, 0x9C, 0x5C,
+ 0x5D, 0x9D, 0x5F, 0x9F, 0x9E, 0x5E, 0x5A, 0x9A, 0x9B, 0x5B,
+ 0x99, 0x59, 0x58, 0x98, 0x88, 0x48, 0x49, 0x89, 0x4B, 0x8B,
+ 0x8A, 0x4A, 0x4E, 0x8E, 0x8F, 0x4F, 0x8D, 0x4D, 0x4C, 0x8C,
+ 0x44, 0x84, 0x85, 0x45, 0x87, 0x47, 0x46, 0x86, 0x82, 0x42,
+ 0x43, 0x83, 0x41, 0x81, 0x80, 0x40
+};
+
+uint16_t modbus_crc16(char* buffer, size_t buffer_length) {
+ uint8_t crc_hi = 0xFF; /* high CRC byte initialized */
+ uint8_t crc_lo = 0xFF; /* low CRC byte initialized */
+ unsigned int i; /* will index into CRC lookup */
+
+ /* pass through message buffer */
+ while (buffer_length--) {
+ i = crc_hi ^ *((uint8_t*)(buffer++)); /* calculate the CRC */
+ crc_hi = crc_lo ^ table_crc_hi[i];
+ crc_lo = table_crc_lo[i];
+ }
+
+ return (crc_hi << 8 | crc_lo);
+}
diff --git a/meta-facebook/meta-wedge/recipes-wedge/rackmon/rackmon/modbus.h b/meta-facebook/meta-wedge/recipes-wedge/rackmon/rackmon/modbus.h
new file mode 100644
index 0000000..435d518
--- /dev/null
+++ b/meta-facebook/meta-wedge/recipes-wedge/rackmon/rackmon/modbus.h
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2014-present Facebook. All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef MODBUS_H_
+#define MODBUS_H_
+#include <stddef.h>
+#include <stdint.h>
+#include <stdio.h>
+uint16_t modbus_crc16(char* buffer, size_t length);
+
+#define DEFAULT_TTY "/dev/ttyS3"
+#define DEFAULT_GPIO 45
+
+#define CHECK(x) { if((x) < 0) { \
+ error = x; \
+ goto cleanup; \
+} }
+
+void waitfd(int fd);
+void gpio_on(int fd);
+void gpio_off(int fd);
+void decode_hex_in_place(char* buf, size_t* len);
+void append_modbus_crc16(char* buf, size_t* len);
+void print_hex(FILE* f, char* buf, size_t len);
+
+// Read until maxlen bytes or no bytes in mdelay_us microseconds
+size_t read_wait(int fd, char* dst, size_t maxlen, int mdelay_us);
+
+extern int verbose;
+
+#endif
diff --git a/meta-facebook/meta-wedge/recipes-wedge/rackmon/rackmon/modbuscmd.c b/meta-facebook/meta-wedge/recipes-wedge/rackmon/rackmon/modbuscmd.c
new file mode 100644
index 0000000..2d33039
--- /dev/null
+++ b/meta-facebook/meta-wedge/recipes-wedge/rackmon/rackmon/modbuscmd.c
@@ -0,0 +1,163 @@
+/*
+ * Copyright 2014-present Facebook. All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <termios.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <sys/ioctl.h>
+#include <getopt.h>
+#include "modbus.h"
+
+int verbose;
+
+void usage() {
+ fprintf(stderr,
+ "modbuscmd [-v] [-t <tty>] [-g <gpio>] modbus_command\n"
+ "\ttty defaults to %s\n"
+ "\tgpio defaults to %d\n"
+ "\tmodbus command should be specified in hex\n"
+ "\teg:\ta40300000008\n",
+ DEFAULT_TTY, DEFAULT_GPIO);
+ exit(1);
+}
+
+int main(int argc, char **argv) {
+ int error = 0;
+ int fd;
+ struct termios tio;
+ char gpio_filename[255];
+ int gpio_fd = 0;
+ int gpio_n = DEFAULT_GPIO;
+ char *tty = DEFAULT_TTY;
+ char *modbus_cmd = NULL;
+ size_t cmd_len = 0;
+ verbose = 0;
+
+ int opt;
+ while((opt = getopt(argc, argv, "t:g:v")) != -1) {
+ switch (opt) {
+ case 't':
+ tty = optarg;
+ break;
+ case 'g':
+ gpio_n = atoi(optarg);
+ break;
+ case 'v':
+ verbose = 1;
+ break;
+ default:
+ usage();
+ break;
+ }
+ }
+ if(optind < argc) {
+ modbus_cmd = argv[optind];
+ }
+ if(modbus_cmd == NULL) {
+ usage();
+ }
+
+ if (verbose)
+ fprintf(stderr, "[*] Opening TTY\n");
+ fd = open(tty, O_RDWR | O_NOCTTY);
+ CHECK(fd);
+
+ if (verbose)
+ fprintf(stderr, "[*] Opening GPIO %d\n", gpio_n);
+ snprintf(gpio_filename, 255, "/sys/class/gpio/gpio%d/value", gpio_n);
+ gpio_fd = open(gpio_filename, O_WRONLY | O_SYNC);
+ CHECK(gpio_fd);
+
+ if (verbose)
+ fprintf(stderr, "[*] Setting TTY flags!\n");
+ memset(&tio, 0, sizeof(tio));
+ cfsetspeed(&tio,B19200);
+ tio.c_cflag |= PARENB;
+ tio.c_cflag |= CLOCAL;
+ tio.c_cflag |= CS8;
+ tio.c_iflag |= INPCK;
+ tio.c_cc[VMIN] = 1;
+ tio.c_cc[VTIME] = 0;
+ CHECK(tcsetattr(fd,TCSANOW,&tio));
+
+ //convert hex to bytes
+ cmd_len = strlen(modbus_cmd);
+ if(cmd_len < 4) {
+ fprintf(stderr, "Modbus command too short!\n");
+ exit(1);
+ }
+ decode_hex_in_place(modbus_cmd, &cmd_len);
+ append_modbus_crc16(modbus_cmd, &cmd_len);
+ // print command as sent
+ if (verbose) {
+ fprintf(stderr, "Will send: ");
+ print_hex(stderr, modbus_cmd, cmd_len);
+ fprintf(stderr, "\n");
+ }
+
+ if (verbose)
+ fprintf(stderr, "[*] Writing!\n");
+
+ // gpio on, write, wait, gpio off
+ gpio_on(gpio_fd);
+ write(fd, modbus_cmd, cmd_len);
+ waitfd(fd);
+ gpio_off(gpio_fd);
+
+ // Enable UART read
+ tio.c_cflag |= CREAD;
+ CHECK(tcsetattr(fd,TCSANOW,&tio));
+
+ if(verbose)
+ fprintf(stderr, "[*] reading any response...\n");
+ // Read back response
+ char modbus_buf[255];
+ size_t mb_pos = 0;
+ memset(modbus_buf, 0, sizeof(modbus_buf));
+ mb_pos = read_wait(fd, modbus_buf, sizeof(modbus_buf), 90000);
+ if(mb_pos >= 4) {
+ uint16_t crc = modbus_crc16(modbus_buf, mb_pos - 2);
+ if(verbose)
+ fprintf(stderr, "Modbus response CRC: %04X\n ", crc);
+ if((modbus_buf[mb_pos - 2] == (crc >> 8)) &&
+ (modbus_buf[mb_pos - 1] == (crc & 0x00FF))) {
+ if(verbose)
+ fprintf(stderr, "CRC OK!\n");
+ print_hex(stdout, modbus_buf, mb_pos);
+ printf("\n");
+ } else {
+ fprintf(stderr, "BAD CRC :(\n");
+ return 5;
+ }
+ } else {
+ fprintf(stderr, "No response :(\n");
+ return 4;
+ }
+
+cleanup:
+ if(error != 0) {
+ error = 1;
+ fprintf(stderr, "%s\n", strerror(errno));
+ }
+ return error;
+}
diff --git a/meta-facebook/meta-wedge/recipes-wedge/rackmon/rackmon/modbussim.c b/meta-facebook/meta-wedge/recipes-wedge/rackmon/rackmon/modbussim.c
new file mode 100644
index 0000000..bf8c6c8
--- /dev/null
+++ b/meta-facebook/meta-wedge/recipes-wedge/rackmon/rackmon/modbussim.c
@@ -0,0 +1,183 @@
+/*
+ * Copyright 2014-present Facebook. All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <termios.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <sys/ioctl.h>
+#include <getopt.h>
+#include "modbus.h"
+
+int verbose = 0;
+
+void usage() {
+ fprintf(stderr,
+ "modbussim [-v] [-t <tty>] [-g <gpio>] modbus_request modbus_reply\n"
+ "\ttty defaults to %s\n"
+ "\tgpio defaults to %d\n"
+ "\tmodbus request/reply should be specified in hex\n"
+ "\teg:\ta40300000008\n",
+ DEFAULT_TTY, DEFAULT_GPIO);
+ exit(1);
+}
+
+int main(int argc, char **argv) {
+ int error = 0;
+ int fd;
+ struct termios tio;
+ char gpio_filename[255];
+ int gpio_fd = 0;
+ int gpio_n = DEFAULT_GPIO;
+ char *tty = DEFAULT_TTY;
+ char *modbus_cmd = NULL;
+ char *modbus_reply = NULL;
+ size_t cmd_len = 0;
+ size_t reply_len = 0;
+ verbose = 0;
+
+ int opt;
+ while((opt = getopt(argc, argv, "t:g:v"))) {
+ if (opt == -1) break;
+ switch (opt) {
+ case 't':
+ tty = optarg;
+ break;
+ case 'g':
+ gpio_n = atoi(optarg);
+ break;
+ case 'v':
+ verbose = 1;
+ break;
+ default:
+ usage();
+ break;
+ }
+ }
+ if(optind < argc) {
+ modbus_cmd = argv[optind++];
+ modbus_reply = argv[optind++];
+ }
+ if(modbus_cmd == NULL || modbus_reply == NULL) {
+ usage();
+ }
+
+ if (verbose)
+ fprintf(stderr, "[*] Opening TTY\n");
+ fd = open(tty, O_RDWR | O_NOCTTY);
+ CHECK(fd);
+
+ if (verbose)
+ fprintf(stderr, "[*] Opening GPIO %d\n", gpio_n);
+ snprintf(gpio_filename, 255, "/sys/class/gpio/gpio%d/value", gpio_n);
+ gpio_fd = open(gpio_filename, O_WRONLY | O_SYNC);
+ CHECK(gpio_fd);
+
+ if (verbose)
+ fprintf(stderr, "[*] Setting TTY flags!\n");
+ memset(&tio, 0, sizeof(tio));
+ cfsetspeed(&tio,B19200);
+ tio.c_cflag |= PARENB;
+ tio.c_cflag |= CLOCAL;
+ tio.c_cflag |= CS8;
+ tio.c_iflag |= INPCK;
+ tio.c_cc[VMIN] = 1;
+ tio.c_cc[VTIME] = 0;
+ CHECK(tcsetattr(fd,TCSANOW,&tio));
+
+ //convert hex to bytes
+ cmd_len = strlen(modbus_cmd);
+ if(cmd_len < 2) {
+ fprintf(stderr, "Command too short!\n");
+ exit(1);
+ }
+ decode_hex_in_place(modbus_cmd, &cmd_len);
+ append_modbus_crc16(modbus_cmd, &cmd_len);
+ if (verbose) {
+ fprintf(stderr, "expect: ");
+ print_hex(stderr, modbus_cmd, cmd_len);
+ fprintf(stderr, "\n");
+ }
+ reply_len = strlen(modbus_reply);
+ decode_hex_in_place(modbus_reply, &reply_len);
+ append_modbus_crc16(modbus_reply, &reply_len);
+ // print full expected reply
+ if (verbose) {
+ fprintf(stderr, "reply: ");
+ print_hex(stderr, modbus_reply, reply_len);
+ fprintf(stderr, "\n");
+ }
+
+ // Enable UART read
+ tio.c_cflag |= CREAD;
+ CHECK(tcsetattr(fd,TCSANOW,&tio));
+ gpio_off(gpio_fd);
+
+ if(verbose)
+ fprintf(stderr, "[*] Wait for matching command...\n");
+
+ char modbus_buf[255];
+ size_t mb_pos;
+wait_for_command:
+ mb_pos = read_wait(fd, modbus_buf, sizeof(modbus_buf), 30000);
+ if(mb_pos >= 4) {
+ printf("Received: ");
+ print_hex(stdout, modbus_buf, mb_pos);
+ uint16_t crc = modbus_crc16(modbus_buf, mb_pos - 2);
+ if((modbus_buf[mb_pos - 2] == (crc >> 8)) &&
+ (modbus_buf[mb_pos - 1] == (crc & 0x00FF))) {
+ if(verbose)
+ fprintf(stderr, "CRC OK!\n");
+ if(memcmp(modbus_buf, modbus_cmd, cmd_len) == 0) {
+ fprintf(stderr, "Command matched!\n");
+ } else {
+ fprintf(stderr, "Got modbus cmd that didn't match.\n");
+ goto wait_for_command;
+ }
+ } else {
+ fprintf(stderr, "Got data that failed modbus CRC.\n");
+ goto wait_for_command;
+ }
+ } else {
+ goto wait_for_command;
+ }
+
+
+ if (verbose)
+ fprintf(stderr, "[*] Writing reply!\n");
+
+ // Disable UART read
+ tio.c_cflag &= ~CREAD;
+ CHECK(tcsetattr(fd,TCSANOW,&tio));
+ // gpio on, write, wait, gpio off
+ gpio_on(gpio_fd);
+ write(fd, modbus_reply, reply_len);
+ waitfd(fd);
+ gpio_off(gpio_fd);
+
+cleanup:
+ if(error != 0) {
+ error = 1;
+ fprintf(stderr, "%s\n", strerror(errno));
+ }
+ return error;
+}
diff --git a/meta-facebook/meta-wedge/recipes-wedge/rackmon/rackmon_0.1.bb b/meta-facebook/meta-wedge/recipes-wedge/rackmon/rackmon_0.1.bb
new file mode 100644
index 0000000..d3e79e4
--- /dev/null
+++ b/meta-facebook/meta-wedge/recipes-wedge/rackmon/rackmon_0.1.bb
@@ -0,0 +1,48 @@
+# Copyright 2014-present Facebook. All Rights Reserved.
+SUMMARY = "Rackmon Functionality"
+DESCRIPTION = "Rackmon Functionality"
+SECTION = "base"
+PR = "r1"
+LICENSE = "GPLv2"
+LIC_FILES_CHKSUM = "file://modbus.c;beginline=4;endline=16;md5=da35978751a9d71b73679307c4d296ec"
+
+#DEPENDS_append = " update-rc.d-native"
+
+SRC_URI = "file://Makefile \
+ file://modbuscmd.c \
+ file://modbussim.c \
+ file://modbus.c \
+ file://modbus.h \
+ file://gpiowatch.c \
+ "
+
+S = "${WORKDIR}"
+
+binfiles = "modbuscmd \
+ modbussim \
+ gpiowatch \
+ "
+
+#otherfiles = "README"
+
+pkgdir = "rackmon"
+
+do_install() {
+ dst="${D}/usr/local/fbpackages/${pkgdir}"
+ bin="${D}/usr/local/bin"
+ install -d $dst
+ install -d $bin
+ for f in ${binfiles}; do
+ install -m 755 $f ${dst}/$f
+ ln -snf ../fbpackages/${pkgdir}/$f ${bin}/$f
+ done
+}
+
+FBPACKAGEDIR = "${prefix}/local/fbpackages"
+
+FILES_${PN} = "${FBPACKAGEDIR}/rackmon ${prefix}/local/bin ${sysconfdir} "
+
+# Inhibit complaints about .debug directories for the rackmon binaries:
+
+INHIBIT_PACKAGE_DEBUG_SPLIT = "1"
+INHIBIT_PACKAGE_STRIP = "1"
diff --git a/meta-facebook/meta-wedge/recipes-wedge/rest-api/files/rest.py b/meta-facebook/meta-wedge/recipes-wedge/rest-api/files/rest.py
new file mode 100644
index 0000000..6d59fd6
--- /dev/null
+++ b/meta-facebook/meta-wedge/recipes-wedge/rest-api/files/rest.py
@@ -0,0 +1,102 @@
+#!/usr/bin/env python
+#
+# Copyright 2014-present Facebook. All Rights Reserved.
+#
+# This program file is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by the
+# Free Software Foundation; version 2 of the License.
+#
+# This program is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+# for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program in a file named COPYING; if not, write to the
+# Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor,
+# Boston, MA 02110-1301 USA
+#
+
+
+from ctypes import *
+from bottle import route, run, template, request, response
+from bottle import abort
+import json
+from rest_fruid import *
+from rest_server import *
+from rest_sensors import *
+from rest_bmc import *
+from rest_gpios import *
+
+# Handler for root resource endpoint
+@route('/api')
+def rest_api():
+ result = {
+ "Information": {
+ "Description": "Wedge RESTful API Entry",
+ },
+ "Actions": [],
+ "Resources": [ "sys"],
+ }
+
+ return result
+
+# Handler for sys resource endpoint
+@route('/api/sys')
+def rest_sys():
+ result = {
+ "Information": {
+ "Description": "Wedge System",
+ },
+ "Actions": [],
+ "Resources": [ "mb", "bmc", "server", "sensors", "gpios"],
+ }
+
+ return result
+
+# Handler for sys/mb resource endpoint
+@route('/api/sys/mb')
+def rest_sys():
+ result = {
+ "Information": {
+ "Description": "System Motherboard",
+ },
+ "Actions": [],
+ "Resources": [ "fruid"],
+ }
+
+ return result
+
+# Handler for sys/mb/fruid resource endpoint
+@route('/api/sys/mb/fruid')
+def rest_fruid():
+ return get_fruid()
+
+# Handler for sys/bmc resource endpoint
+@route('/api/sys/bmc')
+def rest_bmc():
+ return get_bmc()
+
+# Handler for sys/server resource endpoint
+@route('/api/sys/server')
+def rest_bmc():
+ return get_server()
+
+# Handler for uServer resource endpoint
+@route('/api/sys/server', method='POST')
+def rest_server():
+ data = json.load(request.body)
+ return server_action(data)
+
+# Handler for sensors resource endpoint
+@route('/api/sys/sensors')
+def rest_sensors():
+ return get_sensors()
+
+# Handler for sensors resource endpoint
+@route('/api/sys/gpios')
+def rest_gpios():
+ return get_gpios()
+
+run(host = "::", port = 8080)
diff --git a/meta-facebook/meta-wedge/recipes-wedge/rest-api/files/rest_bmc.py b/meta-facebook/meta-wedge/recipes-wedge/rest-api/files/rest_bmc.py
new file mode 100644
index 0000000..d9600ae
--- /dev/null
+++ b/meta-facebook/meta-wedge/recipes-wedge/rest-api/files/rest_bmc.py
@@ -0,0 +1,67 @@
+#!/usr/bin/env python
+#
+# Copyright 2014-present Facebook. All Rights Reserved.
+#
+# This program file is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by the
+# Free Software Foundation; version 2 of the License.
+#
+# This program is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+# for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program in a file named COPYING; if not, write to the
+# Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor,
+# Boston, MA 02110-1301 USA
+#
+
+
+from subprocess import *
+
+# Handler for FRUID resource endpoint
+def get_bmc():
+ # Get BMC Reset Reason
+ wdt_counter = Popen('devmem 0x1e785010', \
+ shell=True, stdout=PIPE).stdout.read()
+ wdt_counter = int(wdt_counter, 0)
+
+ wdt_counter &= 0xff00
+
+ if wdt_counter:
+ por_flag = 0
+ else:
+ por_flag = 1
+
+ if por_flag:
+ reset_reason = "Power ON Reset"
+ else:
+ reset_reason = "User Initiated Reset or WDT Reset"
+
+ # Get BMC's Up Time
+ uptime = Popen('uptime', \
+ shell=True, stdout=PIPE).stdout.read()
+
+ # Get Usage information
+ data = Popen('top -b n1', \
+ shell=True, stdout=PIPE).stdout.read()
+ adata = data.split('\n')
+ mem_usage = adata[0]
+ cpu_usage = adata[1]
+
+ result = {
+ "Information": {
+ "Description": "Wedge BMC",
+ "Reset Reason": reset_reason,
+ "Uptime": uptime,
+ "Memory Usage": mem_usage,
+ "CPU Usage": cpu_usage,
+ },
+ "Actions": [],
+ "Resources": [],
+ }
+
+ return result;
+
diff --git a/meta-facebook/meta-wedge/recipes-wedge/rest-api/files/rest_fruid.py b/meta-facebook/meta-wedge/recipes-wedge/rest-api/files/rest_fruid.py
new file mode 100644
index 0000000..167e1fa
--- /dev/null
+++ b/meta-facebook/meta-wedge/recipes-wedge/rest-api/files/rest_fruid.py
@@ -0,0 +1,87 @@
+#!/usr/bin/env python
+#
+# Copyright 2014-present Facebook. All Rights Reserved.
+#
+# This program file is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by the
+# Free Software Foundation; version 2 of the License.
+#
+# This program is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+# for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program in a file named COPYING; if not, write to the
+# Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor,
+# Boston, MA 02110-1301 USA
+#
+
+
+from ctypes import *
+
+# Handler for FRUID resource endpoint
+fru = CDLL("libwedge_eeprom.so")
+
+class FRU(Structure):
+ _fields_ = [ ("fbw_version", c_ubyte),
+ ("fbw_product_name", c_char * 13),
+ ("fbw_product_number", c_char * 10),
+ ("fbw_assembly_number", c_char * 15),
+ ("fbw_facebook_pcb_number", c_char * 15),
+ ("fbw_odm_pcb_number", c_char * 14),
+ ("fbw_odm_pcb_serial", c_char * 13),
+ ("fbw_production_state", c_ubyte),
+ ("fbw_product_version", c_ubyte),
+ ("fbw_product_subversion", c_ubyte),
+ ("fbw_product_serial", c_char * 13),
+ ("fbw_product_asset", c_char * 13),
+ ("fbw_system_manufacturer", c_char * 9),
+ ("fbw_system_manufacturing_date", c_char * 10),
+ ("fbw_pcb_manufacturer", c_char * 9),
+ ("fbw_assembled", c_char * 9),
+ ("fbw_local_mac", c_ubyte * 6),
+ ("fbw_mac_base", c_ubyte * 6),
+ ("fbw_dummy", c_char),
+ ("fbw_mac_size", c_ushort),
+ ("fbw_location", c_char * 9),
+ ("fbw_crc8", c_ubyte) ]
+
+def get_fruid():
+ myfru = FRU()
+ p_myfru = pointer(myfru)
+ fru.wedge_eeprom_parse(None, p_myfru)
+
+ mac2str = lambda mac: ':'.join(['{:02X}'.format(b) for b in mac])
+
+ fruinfo = { "Version": myfru.fbw_version,
+ "Product Name": myfru.fbw_product_name,
+ "Product Part Number": myfru.fbw_product_number,
+ "System Assembly Part Number": myfru.fbw_assembly_number,
+ "Facebook PCB Part Number": myfru.fbw_facebook_pcb_number,
+ "ODM PCB Part Number": myfru.fbw_odm_pcb_number,
+ "ODM PCB Serial Number": myfru.fbw_odm_pcb_serial,
+ "Product Production State": myfru.fbw_production_state,
+ "Product Version": myfru.fbw_product_version,
+ "Product Sub-Version": myfru.fbw_product_subversion,
+ "Product Serial Number": myfru.fbw_product_serial,
+ "Product Asset Tag": myfru.fbw_product_asset,
+ "System Manufacturer": myfru.fbw_system_manufacturer,
+ "System Manufacturing Date": myfru.fbw_system_manufacturing_date,
+ "PCB Manufacturer": myfru.fbw_pcb_manufacturer,
+ "Assembled At": myfru.fbw_assembled,
+ "Local MAC": mac2str(myfru.fbw_local_mac),
+ "Extended MAC Base": mac2str(myfru.fbw_mac_base),
+ "Extended MAC Address Size": myfru.fbw_mac_size,
+ "Location on Fabric": myfru.fbw_location,
+ "CRC8": hex((myfru.fbw_crc8))
+ }
+
+ result = {
+ "Information": fruinfo,
+ "Actions": [],
+ "Resources": [],
+ }
+
+ return result
diff --git a/meta-facebook/meta-wedge/recipes-wedge/rest-api/files/rest_gpios.py b/meta-facebook/meta-wedge/recipes-wedge/rest-api/files/rest_gpios.py
new file mode 100644
index 0000000..340c5c3
--- /dev/null
+++ b/meta-facebook/meta-wedge/recipes-wedge/rest-api/files/rest_gpios.py
@@ -0,0 +1,56 @@
+#!/usr/bin/env python
+#
+# Copyright 2014-present Facebook. All Rights Reserved.
+#
+# This program file is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by the
+# Free Software Foundation; version 2 of the License.
+#
+# This program is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+# for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program in a file named COPYING; if not, write to the
+# Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor,
+# Boston, MA 02110-1301 USA
+#
+
+from rest_fruid import get_fruid
+
+WEDGES = ["Wedge-AC-F", "Wedge-DC-F"]
+
+
+def read_gpio_sysfs(gpio):
+ with open('/sys/class/gpio/gpio%d/value' % gpio, 'r') as f:
+ val_string = f.read()
+ if val_string == '1\n':
+ return 1
+ if val_string == '0\n':
+ return 0
+ return None
+
+
+def read_wedge_back_ports():
+ bhinfo = { "port_1": { "pin_1": read_gpio_sysfs(120),
+ "pin_2": read_gpio_sysfs(121),
+ "pin_3": read_gpio_sysfs(122),
+ "pin_4": read_gpio_sysfs(123)
+ },
+ "port_2": { "pin_1": read_gpio_sysfs(124),
+ "pin_2": read_gpio_sysfs(125),
+ "pin_3": read_gpio_sysfs(126),
+ "pin_4": read_gpio_sysfs(52)
+ }
+ }
+ return bhinfo
+
+
+def get_gpios():
+ fruinfo = get_fruid()
+ gpioinfo = {}
+ if fruinfo["Information"]["Product Name"] in WEDGES:
+ gpioinfo["back_ports"] = read_wedge_back_ports()
+ return gpioinfo
diff --git a/meta-facebook/meta-wedge/recipes-wedge/rest-api/files/rest_sensors.py b/meta-facebook/meta-wedge/recipes-wedge/rest-api/files/rest_sensors.py
new file mode 100644
index 0000000..f4f83d3
--- /dev/null
+++ b/meta-facebook/meta-wedge/recipes-wedge/rest-api/files/rest_sensors.py
@@ -0,0 +1,50 @@
+#!/usr/bin/env python
+#
+# Copyright 2014-present Facebook. All Rights Reserved.
+#
+# This program file is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by the
+# Free Software Foundation; version 2 of the License.
+#
+# This program is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+# for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program in a file named COPYING; if not, write to the
+# Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor,
+# Boston, MA 02110-1301 USA
+#
+
+
+import json
+import os
+import re
+
+# Handler for sensors resource endpoint
+def get_sensors():
+ result = []
+ data = os.popen('sensors').read()
+ data = re.sub(r'\(.+?\)', '', data)
+ for edata in data.split('\n\n'):
+ adata = edata.split('\n', 1)
+ sresult = {}
+ if (len(adata) < 2):
+ break;
+ sresult['name'] = adata[0]
+ for sdata in adata[1].split('\n'):
+ tdata = sdata.split(':')
+ if (len(tdata) < 2):
+ continue
+ sresult[tdata[0].strip()] = tdata[1].strip()
+ result.append(sresult)
+
+ fresult = {
+ "Information": result,
+ "Actions": [],
+ "Resources": [],
+ }
+
+ return fresult
diff --git a/meta-facebook/meta-wedge/recipes-wedge/rest-api/files/rest_server.py b/meta-facebook/meta-wedge/recipes-wedge/rest-api/files/rest_server.py
new file mode 100644
index 0000000..0acba27
--- /dev/null
+++ b/meta-facebook/meta-wedge/recipes-wedge/rest-api/files/rest_server.py
@@ -0,0 +1,68 @@
+#!/usr/bin/env python
+#
+# Copyright 2014-present Facebook. All Rights Reserved.
+#
+# This program file is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by the
+# Free Software Foundation; version 2 of the License.
+#
+# This program is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+# for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program in a file named COPYING; if not, write to the
+# Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor,
+# Boston, MA 02110-1301 USA
+#
+
+
+import os
+from subprocess import *
+
+# Handler for uServer resource endpoint
+def get_server():
+ ret = Popen('/usr/local/bin/wedge_power.sh status', \
+ shell=True, stdout=PIPE).stdout.read()
+ status = ret.rsplit()[-1]
+
+ result = {
+ "Information": { "status": status },
+ "Actions": ["power-on", "power-off", "power-reset"],
+ "Resources": [],
+ }
+
+ return result
+
+def server_action(data):
+ if data["action"] == 'power-on':
+ ret = Popen('/usr/local/bin/wedge_power.sh status', \
+ shell=True, stdout=PIPE).stdout.read()
+ status = ret.rsplit()[-1]
+ if status == 'on':
+ res = 'failure'
+ reason = 'already on'
+ else:
+ ret = Popen('/usr/local/bin/wedge_power.sh on', \
+ shell=True, stdout=PIPE).stdout.read()
+ res = "success"
+ elif data["action"] == 'power-off':
+ ret = Popen('/usr/local/bin/wedge_power.sh off', \
+ shell=True, stdout=PIPE).stdout.read()
+ res = "success"
+ elif data["action"] == 'power-reset':
+ ret = Popen('/usr/local/bin/wedge_power.sh reset', \
+ shell=True, stdout=PIPE).stdout.read()
+ res = "success"
+ else:
+ res = 'failure'
+ reason = 'invalid action'
+
+ if res == 'failure':
+ result = { "result": res, "reason": reason}
+ else:
+ result = { "result": res }
+
+ return result
diff --git a/meta-facebook/meta-wedge/recipes-wedge/rest-api/files/setup-rest-api.sh b/meta-facebook/meta-wedge/recipes-wedge/rest-api/files/setup-rest-api.sh
new file mode 100644
index 0000000..fe01c23
--- /dev/null
+++ b/meta-facebook/meta-wedge/recipes-wedge/rest-api/files/setup-rest-api.sh
@@ -0,0 +1,16 @@
+#!/bin/sh
+#
+# Copyright 2014-present Facebook. All Rights Reserved.
+#
+### BEGIN INIT INFO
+# Provides: setup-rest-api
+# Required-Start:
+# Required-Stop:
+# Default-Start: S
+# Default-Stop:
+# Short-Description: Set REST API handler
+### END INIT INFO
+
+echo -n "Setup REST API handler... "
+/usr/local/bin/rest.py > /tmp/rest.log 2>&1 &
+echo "done."
diff --git a/meta-facebook/meta-wedge/recipes-wedge/rest-api/rest-api_0.1.bb b/meta-facebook/meta-wedge/recipes-wedge/rest-api/rest-api_0.1.bb
new file mode 100644
index 0000000..2753f30
--- /dev/null
+++ b/meta-facebook/meta-wedge/recipes-wedge/rest-api/rest-api_0.1.bb
@@ -0,0 +1,52 @@
+# Copyright 2014-present Facebook. All Rights Reserved.
+SUMMARY = "Rest API Daemon"
+DESCRIPTION = "Daemon to handle RESTful interface."
+SECTION = "base"
+PR = "r1"
+LICENSE = "GPLv2"
+LIC_FILES_CHKSUM = "file://rest.py;beginline=5;endline=18;md5=0b1ee7d6f844d472fa306b2fee2167e0"
+
+
+DEPENDS_append = " update-rc.d-native"
+
+SRC_URI = "file://setup-rest-api.sh \
+ file://rest.py \
+ file://rest_bmc.py \
+ file://rest_fruid.py \
+ file://rest_gpios.py \
+ file://rest_server.py \
+ file://rest_sensors.py \
+ "
+
+S = "${WORKDIR}"
+
+binfiles = "rest.py rest_bmc.py rest_fruid.py rest_gpios.py rest_server.py rest_sensors.py setup-rest-api.sh"
+
+pkgdir = "rest-api"
+
+do_install() {
+ dst="${D}/usr/local/fbpackages/${pkgdir}"
+ bin="${D}/usr/local/bin"
+ install -d $dst
+ install -d $bin
+ for f in ${binfiles}; do
+ install -m 755 $f ${dst}/$f
+ ln -snf ../fbpackages/${pkgdir}/$f ${bin}/$f
+ done
+ for f in ${otherfiles}; do
+ install -m 644 $f ${dst}/$f
+ done
+ install -d ${D}${sysconfdir}/init.d
+ install -d ${D}${sysconfdir}/rcS.d
+ install -m 755 setup-rest-api.sh ${D}${sysconfdir}/init.d/setup-rest-api.sh
+ update-rc.d -r ${D} setup-rest-api.sh start 95 2 3 4 5 .
+}
+
+FBPACKAGEDIR = "${prefix}/local/fbpackages"
+
+FILES_${PN} = "${FBPACKAGEDIR}/rest-api ${prefix}/local/bin ${sysconfdir} "
+
+# Inhibit complaints about .debug directories for the fand binary:
+
+INHIBIT_PACKAGE_DEBUG_SPLIT = "1"
+INHIBIT_PACKAGE_STRIP = "1"
diff --git a/meta-facebook/meta-wedge/recipes-wedge/sensor-setup/files/sensor-setup.sh b/meta-facebook/meta-wedge/recipes-wedge/sensor-setup/files/sensor-setup.sh
new file mode 100644
index 0000000..0027828
--- /dev/null
+++ b/meta-facebook/meta-wedge/recipes-wedge/sensor-setup/files/sensor-setup.sh
@@ -0,0 +1,52 @@
+#!/bin/sh
+#
+# Copyright 2014-present Facebook. All Rights Reserved.
+#
+# This program file is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by the
+# Free Software Foundation; version 2 of the License.
+#
+# This program is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+# for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program in a file named COPYING; if not, write to the
+# Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor,
+# Boston, MA 02110-1301 USA
+#
+
+### BEGIN INIT INFO
+# Provides: sensor-setup
+# Required-Start: power-on
+# Required-Stop:
+# Default-Start: S
+# Default-Stop:
+# Short-Description: Power on micro-server
+### END INIT INFO
+
+# Eventually, this will be used to configure the various (mostly
+# i2c-based) sensors, once we have a kernel version that supports
+# doing this more dynamically.
+#
+# For now, we're using it to install the lm75 and pmbus module so that it
+# can detect the fourth temperature sensor, which is located
+# on the uServer, which doesn't get power until power-on executes.
+#
+# Similarly, the pmbus sensor seems to have an easier time of
+# detecting the NCP4200 buck converters after poweron. This has not
+# been carefully explored.
+
+modprobe lm75
+modprobe pmbus
+
+# Enable the ADC inputs; adc5 - adc9 should be connected to
+# 1V, 1.03V, 5V, 3.3V, and 2.5V.
+
+echo 1 > /sys/devices/platform/ast_adc.0/adc5_en
+echo 1 > /sys/devices/platform/ast_adc.0/adc6_en
+echo 1 > /sys/devices/platform/ast_adc.0/adc7_en
+echo 1 > /sys/devices/platform/ast_adc.0/adc8_en
+echo 1 > /sys/devices/platform/ast_adc.0/adc9_en
diff --git a/meta-facebook/meta-wedge/recipes-wedge/sensor-setup/sensor-setup_0.1.bb b/meta-facebook/meta-wedge/recipes-wedge/sensor-setup/sensor-setup_0.1.bb
new file mode 100644
index 0000000..ad6bb0c
--- /dev/null
+++ b/meta-facebook/meta-wedge/recipes-wedge/sensor-setup/sensor-setup_0.1.bb
@@ -0,0 +1,23 @@
+# Copyright 2014-present Facebook. All Rights Reserved.
+SUMMARY = "Configure the sensors"
+DESCRIPTION = "The script configure sensors"
+SECTION = "base"
+PR = "r1"
+LICENSE = "GPLv2"
+LIC_FILES_CHKSUM = "file://sensor-setup.sh;beginline=5;endline=18;md5=0b1ee7d6f844d472fa306b2fee2167e0"
+
+DEPENDS_append = " update-rc.d-native"
+
+SRC_URI = "file://sensor-setup.sh \
+ "
+
+S = "${WORKDIR}"
+
+do_install() {
+ install -d ${D}${sysconfdir}/init.d
+ install -d ${D}${sysconfdir}/rcS.d
+ install -m 755 sensor-setup.sh ${D}${sysconfdir}/init.d/sensor-setup.sh
+ update-rc.d -r ${D} sensor-setup.sh start 90 S .
+}
+
+FILES_${PN} = " ${sysconfdir} "
diff --git a/meta-facebook/meta-wedge/recipes-wedge/sms-kcsd/sms-kcsd/Makefile b/meta-facebook/meta-wedge/recipes-wedge/sms-kcsd/sms-kcsd/Makefile
new file mode 100644
index 0000000..6425261
--- /dev/null
+++ b/meta-facebook/meta-wedge/recipes-wedge/sms-kcsd/sms-kcsd/Makefile
@@ -0,0 +1,10 @@
+# Copyright 2014-present Facebook. All Rights Reserved.
+all: sms-kcsd
+
+sms-kcsd: sms-kcsd.c
+ $(CC) -pthread -lalert_control -lipmi -std=c99 -o $@ $^ $(LDFLAGS)
+
+.PHONY: clean
+
+clean:
+ rm -rf *.o sms-kcsd
diff --git a/meta-facebook/meta-wedge/recipes-wedge/sms-kcsd/sms-kcsd/setup-sms-kcs.sh b/meta-facebook/meta-wedge/recipes-wedge/sms-kcsd/sms-kcsd/setup-sms-kcs.sh
new file mode 100644
index 0000000..d369f5c
--- /dev/null
+++ b/meta-facebook/meta-wedge/recipes-wedge/sms-kcsd/sms-kcsd/setup-sms-kcs.sh
@@ -0,0 +1,16 @@
+#!/bin/sh
+#
+# Copyright 2014-present Facebook. All Rights Reserved.
+#
+### BEGIN INIT INFO
+# Provides: setup-sms-kcs
+# Required-Start:
+# Required-Stop:
+# Default-Start: S
+# Default-Stop:
+# Short-Description: Set SMS KCS handler
+### END INIT INFO
+
+echo -n "Setup SMS KCS message handler... "
+/usr/local/bin/sms-kcsd
+echo "done."
diff --git a/meta-facebook/meta-wedge/recipes-wedge/sms-kcsd/sms-kcsd/sms-kcsd.c b/meta-facebook/meta-wedge/recipes-wedge/sms-kcsd/sms-kcsd/sms-kcsd.c
new file mode 100644
index 0000000..a264fb7
--- /dev/null
+++ b/meta-facebook/meta-wedge/recipes-wedge/sms-kcsd/sms-kcsd/sms-kcsd.c
@@ -0,0 +1,144 @@
+/*
+ * sms-kcsd
+ *
+ * Copyright 2014-present Facebook. All Rights Reserved.
+ *
+ * Daemon to monitor traffic coming from sms-kcs interface
+ * and respond to the command using IPMI stack
+ *
+ * TODO: Determine if the daemon is already started.
+ * TODO: Cache the file descriptors instead of fopen/fclose everytime
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <errno.h>
+#include <syslog.h>
+#include <facebook/alert_control.h>
+#include <facebook/ipmi.h>
+
+
+#define PATH_SMS_KCS "/sys/bus/i2c/drivers/panther_plus/4-0040/sms_kcs"
+#define MAX_ALERT_CONTROL_RETRIES 3
+
+typedef struct {
+ unsigned char fbid;
+ unsigned char length;
+ unsigned char buf[];
+} kcs_msg_t;
+
+/*
+ * Function to check if there is any new KCS message available
+ * TODO: Will be replaced by interrupt-driven approach
+ */
+static bool
+is_new_kcs_msg(void) {
+ return is_alert_present(FBID_SMS_KCS);
+}
+
+/*
+ * KCS Message Handler:
+ * - Reads the incoming request on KCS channel
+ * - Invokes IPMI handler to provide response
+ * - Writes reply back to KCS channel
+ */
+static int
+handle_kcs_msg(void) {
+ FILE *fp;
+ kcs_msg_t *msg;
+ unsigned char rbuf[256] = {0};
+ unsigned char tbuf[256] = {0};
+ unsigned char tlen = 0;
+ int count = 0;
+ int i = 0;
+
+ // Reads incoming request
+ fp = fopen(PATH_SMS_KCS, "r");
+ if (!fp) {
+ syslog(LOG_ALERT, "failed to open file %s\n", PATH_SMS_KCS);
+ return -1;
+ }
+
+ count = fread(rbuf, sizeof(unsigned char), sizeof(rbuf), fp);
+ if (count == 0) {
+ syslog(LOG_INFO, "fread returns zero bytes\n");
+ fclose(fp);
+ return -1;
+ }
+
+ fclose(fp);
+
+ msg = (kcs_msg_t*)rbuf;
+
+ // Invoke IPMI handler
+ ipmi_handle(msg->buf, msg->length, &tbuf[1], &tlen);
+
+ // Fill the length as returned by IPMI stack
+ tbuf[0] = tlen;
+
+ //Write Reply back to KCS channel
+ fp = fopen(PATH_SMS_KCS, "w");
+ if (!fp) {
+ syslog(LOG_ALERT, "failed to open file %s\n", PATH_SMS_KCS);
+ return -1;
+ }
+
+ count = fwrite(tbuf, sizeof(unsigned char), tlen+1, fp);
+ if (count != tlen+1) {
+ syslog(LOG_ALERT, "fwrite returns: %d, expected: %d\n", count, tlen+1);
+ fclose(fp);
+ return -1;
+ }
+
+ fclose(fp);
+
+ return 0;
+}
+
+/*
+ * Daemon Main loop
+ */
+int main(int argc, char **argv) {
+ int i;
+ int ret;
+ daemon(1, 0);
+ openlog("sms-kcs", LOG_CONS, LOG_DAEMON);
+
+ // Enable alert for SMS KCS Function Block
+ for (i = 0; i < MAX_ALERT_CONTROL_RETRIES; i++) {
+ ret = alert_control(FBID_SMS_KCS, FLAG_ENABLE);
+ if (!ret) {
+ break;
+ }
+ sleep(2);
+ }
+
+ // Exit with error in case we can not set the Alert
+ if(ret) {
+ syslog(LOG_ALERT, "Can not enable SMS KCS Alert\n");
+ exit(-1);
+ }
+
+ // Forever loop to poll and process KCS messages
+ while (1) {
+ if (is_new_kcs_msg()) {
+ handle_kcs_msg();
+ }
+ sleep(1);
+ }
+}
diff --git a/meta-facebook/meta-wedge/recipes-wedge/sms-kcsd/sms-kcsd_0.1.bb b/meta-facebook/meta-wedge/recipes-wedge/sms-kcsd/sms-kcsd_0.1.bb
new file mode 100644
index 0000000..1f3ea08
--- /dev/null
+++ b/meta-facebook/meta-wedge/recipes-wedge/sms-kcsd/sms-kcsd_0.1.bb
@@ -0,0 +1,46 @@
+# Copyright 2014-present Facebook. All Rights Reserved.
+SUMMARY = "SMS KCS Daemon"
+DESCRIPTION = "Daemon to handle SMS KCS interface."
+SECTION = "base"
+PR = "r1"
+LICENSE = "GPLv2"
+LIC_FILES_CHKSUM = "file://sms-kcsd.c;beginline=12;endline=24;md5=da35978751a9d71b73679307c4d296ec"
+
+
+DEPENDS_append = " update-rc.d-native"
+
+DEPENDS += "libalert-control"
+DEPENDS += "libipmi"
+
+SRC_URI = "file://Makefile \
+ file://setup-sms-kcs.sh \
+ file://sms-kcsd.c \
+ "
+
+S = "${WORKDIR}"
+
+binfiles = "sms-kcsd"
+
+pkgdir = "sms-kcsd"
+
+do_install() {
+ dst="${D}/usr/local/fbpackages/${pkgdir}"
+ bin="${D}/usr/local/bin"
+ install -d $dst
+ install -d $bin
+ install -m 755 sms-kcsd ${dst}/sms-kcsd
+ ln -snf ../fbpackages/${pkgdir}/sms-kcsd ${bin}/sms-kcsd
+ install -d ${D}${sysconfdir}/init.d
+ install -d ${D}${sysconfdir}/rcS.d
+ install -m 755 setup-sms-kcs.sh ${D}${sysconfdir}/init.d/setup-sms-kcs.sh
+ update-rc.d -r ${D} setup-sms-kcs.sh start 65 S .
+}
+
+FBPACKAGEDIR = "${prefix}/local/fbpackages"
+
+FILES_${PN} = "${FBPACKAGEDIR}/sms-kcsd ${prefix}/local/bin ${sysconfdir} "
+
+# Inhibit complaints about .debug directories for the fand binary:
+
+INHIBIT_PACKAGE_DEBUG_SPLIT = "1"
+INHIBIT_PACKAGE_STRIP = "1"
diff --git a/meta-facebook/meta-wedge/recipes-wedge/usb-console/files/usbcons.sh b/meta-facebook/meta-wedge/recipes-wedge/usb-console/files/usbcons.sh
new file mode 100755
index 0000000..de284bb
--- /dev/null
+++ b/meta-facebook/meta-wedge/recipes-wedge/usb-console/files/usbcons.sh
@@ -0,0 +1,80 @@
+#! /bin/sh
+#
+# Copyright 2014-present Facebook. All Rights Reserved.
+#
+# This program file is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by the
+# Free Software Foundation; version 2 of the License.
+#
+# This program is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+# for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program in a file named COPYING; if not, write to the
+# Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor,
+# Boston, MA 02110-1301 USA
+#
+
+### BEGIN INIT INFO
+# Provides: usbcons
+# Required-Start:
+# Required-Stop:
+# Default-Start: S
+# Default-Stop: 0 6
+# Short-Description: Creates a virtual USB serial device and starts a console
+# on it.
+#
+### END INIT INFO
+
+PATH=/sbin:/bin:/usr/sbin:/usr/bin
+NAME=usbcons
+PIDFILE=/run/usbcons.pid
+DESC="USB Serial Console"
+
+# source function library
+. /etc/init.d/functions
+
+STOPPER=
+ACTION="$1"
+
+case "$ACTION" in
+ start)
+ # Ability to prevent this from starting by editing cmdline in u-boot.
+ # Keeping this here until I get gadget switching working properly. (t4906522)
+ if grep "nousbcons" /proc/cmdline > /dev/null 2>&1
+ then
+ echo "USB Console Disabled."
+ exit 0
+ fi
+ echo -n "Starting $DESC: "
+ /usr/local/bin/usbmon.sh > /dev/null 2>&1 &
+ echo "$NAME."
+ ;;
+ stop)
+ echo -n "Stopping $DESC: "
+ killall usbmon.sh
+ echo "$NAME."
+ ;;
+ restart|force-reload)
+ echo -n "Restarting $DESC: "
+ killall usbmon.sh
+ sleep 1
+ /usr/local/bin/usbmon.sh > /dev/null 2>&1 &
+ echo "$NAME."
+ ;;
+ status)
+ status $DAEMON
+ exit $?
+ ;;
+ *)
+ N=${0##*/}
+ N=${N#[SK]??}
+ echo "Usage: $N {start|stop|status|restart|force-reload}" >&2
+ exit 1
+ ;;
+esac
+
+exit 0
diff --git a/meta-facebook/meta-wedge/recipes-wedge/usb-console/files/usbmon.sh b/meta-facebook/meta-wedge/recipes-wedge/usb-console/files/usbmon.sh
new file mode 100755
index 0000000..0030775
--- /dev/null
+++ b/meta-facebook/meta-wedge/recipes-wedge/usb-console/files/usbmon.sh
@@ -0,0 +1,25 @@
+#!/bin/sh
+#
+# Copyright 2014-present Facebook. All Rights Reserved.
+#
+# This program file is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by the
+# Free Software Foundation; version 2 of the License.
+#
+# This program is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+# for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program in a file named COPYING; if not, write to the
+# Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor,
+# Boston, MA 02110-1301 USA
+#
+
+modprobe g_cdc host_addr=02:00:00:00:00:02 dev_addr=02:00:00:00:00:01
+while true; do
+ getty /dev/ttyGS0 57600
+ sleep 1
+done
diff --git a/meta-facebook/meta-wedge/recipes-wedge/usb-console/usb-console_0.1.bb b/meta-facebook/meta-wedge/recipes-wedge/usb-console/usb-console_0.1.bb
new file mode 100644
index 0000000..f92511c
--- /dev/null
+++ b/meta-facebook/meta-wedge/recipes-wedge/usb-console/usb-console_0.1.bb
@@ -0,0 +1,27 @@
+# Copyright 2014-present Facebook. All Rights Reserved.
+SUMMARY = "Set up a USB serial console"
+DESCRIPTION = "Sets up a USB serial console"
+SECTION = "base"
+PR = "r1"
+LICENSE = "GPLv2"
+LIC_FILES_CHKSUM = "file://usbcons.sh;beginline=5;endline=18;md5=0b1ee7d6f844d472fa306b2fee2167e0"
+
+DEPENDS_append = " update-rc.d-native"
+
+SRC_URI = "file://usbcons.sh \
+ file://usbmon.sh \
+ "
+
+S = "${WORKDIR}"
+
+do_install() {
+ install -d ${D}${sysconfdir}/init.d
+ install -d ${D}${sysconfdir}/rcS.d
+ install -m 755 usbcons.sh ${D}${sysconfdir}/init.d/usbcons.sh
+ update-rc.d -r ${D} usbcons.sh start 90 S .
+ localbindir="${D}/usr/local/bin"
+ install -d ${localbindir}
+ install -m 755 usbmon.sh ${localbindir}/usbmon.sh
+}
+
+FILES_${PN} = " ${sysconfdir} /usr/local"
diff --git a/meta-facebook/meta-wedge/recipes-wedge/wedge-eeprom/files/lib/Makefile b/meta-facebook/meta-wedge/recipes-wedge/wedge-eeprom/files/lib/Makefile
new file mode 100644
index 0000000..0264efe
--- /dev/null
+++ b/meta-facebook/meta-wedge/recipes-wedge/wedge-eeprom/files/lib/Makefile
@@ -0,0 +1,11 @@
+# Copyright 2014-present Facebook. All Rights Reserved.
+lib: libwedge_eeprom.so
+
+libwedge_eeprom.so: wedge_eeprom.c
+ $(CC) $(CCFLAGS) -fPIC -c -o wedge_eeprom.o wedge_eeprom.c
+ $(CC) -shared -o libwedge_eeprom.so wedge_eeprom.o -lc
+
+.PHONY: clean
+
+clean:
+ rm -rf *.o libwedge_eeprom.so
diff --git a/meta-facebook/meta-wedge/recipes-wedge/wedge-eeprom/files/lib/wedge_eeprom.c b/meta-facebook/meta-wedge/recipes-wedge/wedge-eeprom/files/lib/wedge_eeprom.c
new file mode 100644
index 0000000..44f708d
--- /dev/null
+++ b/meta-facebook/meta-wedge/recipes-wedge/wedge-eeprom/files/lib/wedge_eeprom.c
@@ -0,0 +1,403 @@
+/*
+ * Copyright 2014-present Facebook. All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include "wedge_eeprom.h"
+
+#include <assert.h>
+#include <errno.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <facebook/log.h>
+
+#define FBW_EEPROM_FILE "/sys/class/i2c-adapter/i2c-6/6-0050/eeprom"
+
+#define FBW_EEPROM_VERSION 0
+#define FBW_EEPROM_V0_SIZE 162
+
+/*
+ * The eeprom size is 8K, we only use 157 bytes for v1 format.
+ * Read 256 for now.
+ */
+#define FBW_EEPROM_SIZE 256
+
+
+static inline uint8_t fbw_crc8(uint8_t crc, uint8_t data)
+{
+ /* donot verify crc now, always return 0 */
+ return 0;
+}
+
+static uint8_t fbw_crc8_buf(const uint8_t *buf, int len)
+{
+ uint8_t crc = 0;
+ int i;
+
+ for (i = 0, crc = 0; i < len; i++) {
+ crc = fbw_crc8(crc, buf[i]);
+ }
+
+ return crc;
+}
+
+static inline void fbw_copy_uint8(uint8_t *val, const uint8_t** src,
+ int src_len)
+{
+ assert(src_len >= sizeof(*val));
+ *val = **src;
+ (*src) += src_len;
+}
+
+static inline void fbw_copy_uint16(uint16_t *val, const uint8_t** src,
+ int src_len)
+{
+ assert(src_len >= sizeof(*val));
+ *val = (**src) | ((*(*src + 1)) << 8);
+ (*src) += src_len;
+}
+
+static inline void fbw_copy_uint32(uint32_t *val, const uint8_t** src,
+ int src_len)
+{
+ assert(src_len >= sizeof(*val));
+ *val = (**src)
+ | ((*(*src + 1)) << 8)
+ | ((*(*src + 2)) << 16)
+ | ((*(*src + 3)) << 24);
+ (*src) += src_len;
+}
+
+static inline void fbw_strcpy(char *dst, int dst_len,
+ const uint8_t **src, int src_len)
+{
+ assert(dst_len >= src_len + 1); /* larger because of '\0' */
+ strncpy(dst, (char *)*src, src_len);
+ dst[src_len + 1] = '\0';
+ (*src) += src_len;
+}
+
+static inline void fbw_copy_product_number(
+ char *dst, int dst_len, const uint8_t **src, int src_len)
+{
+ int i;
+ const uint8_t *cur = *src;
+ /* 8 letter in the format of XX-XXXXXX, 2 additional letters */
+ assert(dst_len >= src_len + 2);
+ for (i = 0; i < 2; i++) {
+ *dst++ = *cur++;
+ }
+ *dst++ = '-';
+ for (i = 0; i < 6; i++) {
+ *dst++ = *cur++;
+ }
+ *dst = '\0';
+ (*src) += src_len;
+}
+
+static inline void fbw_copy_assembly_number(
+ char *dst, int dst_len, const uint8_t **src, int src_len)
+{
+ int i;
+ const uint8_t *cur = *src;
+ /* 11 letter in the format of XXX-XXXXXX-XX, 3 additional letters */
+ assert(dst_len >= src_len + 3);
+ for (i = 0; i < 3; i++) {
+ *dst++ = *cur++;
+ }
+ *dst++ = '-';
+ for (i = 0; i < 6; i++) {
+ *dst++ = *cur++;
+ }
+ *dst++ = '-';
+ for (i = 0; i < 2; i++) {
+ *dst++ = *cur++;
+ }
+ *dst = '\0';
+ (*src) += src_len;
+}
+
+static inline void fbw_copy_facebook_pcb_part(
+ char *dst, int dst_len, const uint8_t **src, int src_len)
+{
+ int i;
+ const uint8_t *cur = *src;
+ /* 11 letter in the format of XXX-XXXXXX-XX, 3 additional letters */
+ assert(dst_len >= src_len + 3);
+ for (i = 0; i < 3; i++) {
+ *dst++ = *cur++;
+ }
+ *dst++ = '-';
+ for (i = 0; i < 6; i++) {
+ *dst++ = *cur++;
+ }
+ *dst++ = '-';
+ for (i = 0; i < 2; i++) {
+ *dst++ = *cur++;
+ }
+ *dst = '\0';
+ (*src) += src_len;
+}
+
+static inline void fbw_copy_date(
+ char *dst, int dst_len, const uint8_t **src, int src_len)
+{
+ const uint8_t *cur = *src;
+ uint16_t year;
+ uint8_t month;
+ uint8_t day;
+ /* mm-dd-yy in output */
+ assert(dst_len >= 9);
+ /* input is 4 bytes YY YY MM DD */
+ assert(src_len >= 4);
+ fbw_copy_uint16(&year, &cur, 2);
+ fbw_copy_uint8(&month, &cur, 1);
+ fbw_copy_uint8(&day, &cur, 1);
+ snprintf(dst, dst_len, "%02d-%02d-%02d", month % 13, day % 32, year % 100);
+ (*src) += src_len;
+}
+
+static inline uint8_t _a2v(const uint8_t *a)
+{
+ uint8_t v = *a;
+ if ('0' <= v && v <= '9') {
+ return v - '0';
+ }
+ if ('a' <= v && v <= 'z') {
+ return v - 'a' + 10;
+ }
+ if ('A' <= v && v <= 'Z') {
+ return v - 'A' + 10;
+ }
+ return 0;
+}
+
+static inline void fbw_copy_mac(
+ uint8_t* dst, int dst_len, const uint8_t **src, int src_len)
+{
+ int i;
+ const uint8_t *cur = *src;
+
+ assert(dst_len >= 6);
+ assert(src_len >= 12);
+
+ for (i = 0; i < 6; i++) {
+ *dst = (_a2v(cur) << 4) | _a2v(cur + 1);
+ dst++;
+ cur +=2 ;
+ }
+ (*src) += src_len;
+}
+
+static int fbw_parse_buffer(
+ const uint8_t *buf, int len, struct wedge_eeprom_st *eeprom) {
+ int rc = 0;
+ const uint8_t* cur = buf;
+ uint16_t magic;
+ int crc_len;
+ uint8_t crc8;
+
+ memset(eeprom, 0, sizeof(*eeprom));
+
+ /* make sure the magic number */
+ fbw_copy_uint16(&magic, &cur, FBW_EEPROM_F_MAGIC);
+ if (magic != 0xfbfb) {
+ rc = EFAULT;
+ LOG_ERR(rc, "Unexpected magic word 0x%x", magic);
+ goto out;
+ }
+
+ /* confirm the version number, only version is supported */
+ fbw_copy_uint8(&eeprom->fbw_version, &cur, FBW_EEPROM_F_VERSION);
+ if (eeprom->fbw_version != FBW_EEPROM_VERSION) {
+ rc = EFAULT;
+ LOG_ERR(rc, "Unsupported version number %u", eeprom->fbw_version);
+ goto out;
+ } else {
+ crc_len = FBW_EEPROM_V0_SIZE;
+ assert(crc_len <= len);
+ }
+
+ /* check CRC */
+ crc8 = fbw_crc8_buf(buf, crc_len);
+ if (crc8 != 0) {
+ rc = EFAULT;
+ LOG_ERR(rc, "CRC check failed");
+ goto out;
+ }
+
+ /* Product name: ASCII for 12 characters */
+ fbw_strcpy(eeprom->fbw_product_name,
+ sizeof(eeprom->fbw_product_name),
+ &cur, FBW_EEPROM_F_PRODUCT_NAME);
+
+ /* Product Part #: 8 byte data shown as XX-XXXXXXX */
+ fbw_copy_product_number(eeprom->fbw_product_number,
+ sizeof(eeprom->fbw_product_number),
+ &cur, FBW_EEPROM_F_PRODUCT_NUMBER);
+
+ /* System Assembly Part Number: XXX-XXXXXX-XX */
+ fbw_copy_assembly_number(eeprom->fbw_assembly_number,
+ sizeof(eeprom->fbw_assembly_number),
+ &cur, FBW_EEPROM_F_ASSEMBLY_NUMBER);
+
+ /* Facebook PCB Part Number: XXX-XXXXXXX-XX */
+ fbw_copy_facebook_pcb_part(eeprom->fbw_facebook_pcb_number,
+ sizeof(eeprom->fbw_facebook_pcb_number),
+ &cur, FBW_EEPROM_F_FACEBOOK_PCB_NUMBER);
+
+ /* ODM PCB Part Number: XXXXXXXXXXXX */
+ fbw_strcpy(eeprom->fbw_odm_pcb_number,
+ sizeof(eeprom->fbw_odm_pcb_number),
+ &cur, FBW_EEPROM_F_ODM_PCB_NUMBER);
+
+ /* ODM PCB Serial Number: XXXXXXXXXXXX */
+ fbw_strcpy(eeprom->fbw_odm_pcb_serial,
+ sizeof(eeprom->fbw_odm_pcb_serial),
+ &cur, FBW_EEPROM_F_ODM_PCB_SERIAL);
+
+ /* Product Production State */
+ fbw_copy_uint8(&eeprom->fbw_production_state,
+ &cur, FBW_EEPROM_F_PRODUCT_STATE);
+
+ /* Product Version */
+ fbw_copy_uint8(&eeprom->fbw_product_version,
+ &cur, FBW_EEPROM_F_PRODUCT_VERSION);
+
+ /* Product Sub Version */
+ fbw_copy_uint8(&eeprom->fbw_product_subversion,
+ &cur, FBW_EEPROM_F_PRODUCT_SUBVERSION);
+
+ /* Product Serial Number: XXXXXXXX */
+ fbw_strcpy(eeprom->fbw_product_serial,
+ sizeof(eeprom->fbw_product_serial),
+ &cur, FBW_EEPROM_F_PRODUCT_SERIAL);
+
+ /* Product Assert Tag: XXXXXXXX */
+ fbw_strcpy(eeprom->fbw_product_asset,
+ sizeof(eeprom->fbw_product_asset),
+ &cur, FBW_EEPROM_F_PRODUCT_ASSET);
+
+ /* System Manufacturer: XXXXXXXX */
+ fbw_strcpy(eeprom->fbw_system_manufacturer,
+ sizeof(eeprom->fbw_system_manufacturer),
+ &cur, FBW_EEPROM_F_SYSTEM_MANUFACTURER);
+
+ /* System Manufacturing Date: mm-dd-yy */
+ fbw_copy_date(eeprom->fbw_system_manufacturing_date,
+ sizeof(eeprom->fbw_system_manufacturing_date),
+ &cur, FBW_EEPROM_F_SYSTEM_MANU_DATE);
+
+ /* PCB Manufacturer: XXXXXXXXX */
+ fbw_strcpy(eeprom->fbw_pcb_manufacturer,
+ sizeof(eeprom->fbw_pcb_manufacturer),
+ &cur, FBW_EEPROM_F_PCB_MANUFACTURER);
+
+ /* Assembled At: XXXXXXXX */
+ fbw_strcpy(eeprom->fbw_assembled,
+ sizeof(eeprom->fbw_assembled),
+ &cur, FBW_EEPROM_F_ASSEMBLED);
+
+ /* Local MAC Address */
+ fbw_copy_mac(eeprom->fbw_local_mac,
+ sizeof(eeprom->fbw_local_mac),
+ &cur, FBW_EEPROM_F_LOCAL_MAC);
+
+ /* Extended MAC Address */
+ fbw_copy_mac(eeprom->fbw_mac_base,
+ sizeof(eeprom->fbw_mac_base),
+ &cur, FBW_EEPROM_F_EXT_MAC_BASE);
+
+ /* Extended MAC Address Size */
+ fbw_copy_uint16(&eeprom->fbw_mac_size,
+ &cur,FBW_EEPROM_F_EXT_MAC_SIZE);
+
+ /* Location on Fabric: "LEFT"/"RIGHT", "WEDGE", "LC" */
+ fbw_strcpy(eeprom->fbw_location,
+ sizeof(eeprom->fbw_location),
+ &cur, FBW_EEPROM_F_LOCATION);
+
+ /* CRC8 */
+ fbw_copy_uint8(&eeprom->fbw_crc8,
+ &cur, FBW_EEPROM_F_CRC8);
+
+ assert((cur - buf) <= len);
+
+ out:
+ return rc;
+}
+
+int wedge_eeprom_parse(const char *fn, struct wedge_eeprom_st *eeprom)
+{
+ int rc = 0;
+ uint32_t len;
+ FILE *fin;
+ char buf[FBW_EEPROM_SIZE];
+
+ if (!eeprom) {
+ return -EINVAL;
+ }
+
+ if (!fn) {
+ fn = FBW_EEPROM_FILE;
+ }
+
+ fin = fopen(fn, "r");
+ if (fin == NULL) {
+ rc = errno;
+ LOG_ERR(rc, "Failed to open %s", FBW_EEPROM_FILE);
+ goto out;
+ }
+
+ /* check the file size */
+ rc = fseek(fin, 0, SEEK_END);
+ if (rc) {
+ rc = errno;
+ LOG_ERR(rc, "Failed to seek to the end of %s", FBW_EEPROM_FILE);
+ goto out;
+ }
+
+ len = ftell(fin);
+ if (len < FBW_EEPROM_SIZE) {
+ rc = ENOSPC;
+ LOG_ERR(rc, "File '%s' is too small (%u < %u)", FBW_EEPROM_FILE,
+ len, FBW_EEPROM_SIZE);
+ goto out;
+ }
+
+ /* go back to the beginning of the file */
+ rewind(fin);
+
+ rc = fread(buf, 1, sizeof(buf), fin);
+ if (rc < sizeof(buf)) {
+ LOG_ERR(ENOSPC, "Failed to complete the read. Only got %d", rc);
+ rc = ENOSPC;
+ goto out;
+ }
+
+ rc = fbw_parse_buffer((const uint8_t *)buf, sizeof(buf), eeprom);
+ if (rc) {
+ goto out;
+ }
+
+ out:
+ if (fin) {
+ fclose(fin);
+ }
+
+ return -rc;
+}
diff --git a/meta-facebook/meta-wedge/recipes-wedge/wedge-eeprom/files/lib/wedge_eeprom.h b/meta-facebook/meta-wedge/recipes-wedge/wedge-eeprom/files/lib/wedge_eeprom.h
new file mode 100644
index 0000000..2c4f39e
--- /dev/null
+++ b/meta-facebook/meta-wedge/recipes-wedge/wedge-eeprom/files/lib/wedge_eeprom.h
@@ -0,0 +1,121 @@
+/*
+ * Copyright 2014-present Facebook. All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#ifndef FBW_EEPROM_H
+#define FBW_EEPROM_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <stdint.h>
+
+#define FBW_EEPROM_F_MAGIC 2
+#define FBW_EEPROM_F_VERSION 1
+#define FBW_EEPROM_F_PRODUCT_NAME 12
+#define FBW_EEPROM_F_PRODUCT_NUMBER 8
+#define FBW_EEPROM_F_ASSEMBLY_NUMBER 12
+#define FBW_EEPROM_F_FACEBOOK_PCB_NUMBER 12
+#define FBW_EEPROM_F_ODM_PCB_NUMBER 13
+#define FBW_EEPROM_F_ODM_PCB_SERIAL 12
+#define FBW_EEPROM_F_PRODUCT_STATE 1
+#define FBW_EEPROM_F_PRODUCT_VERSION 1
+#define FBW_EEPROM_F_PRODUCT_SUBVERSION 1
+#define FBW_EEPROM_F_PRODUCT_SERIAL 12
+#define FBW_EEPROM_F_PRODUCT_ASSET 12
+#define FBW_EEPROM_F_SYSTEM_MANUFACTURER 8
+#define FBW_EEPROM_F_SYSTEM_MANU_DATE 4
+#define FBW_EEPROM_F_PCB_MANUFACTURER 8
+#define FBW_EEPROM_F_ASSEMBLED 8
+#define FBW_EEPROM_F_LOCAL_MAC 12
+#define FBW_EEPROM_F_EXT_MAC_BASE 12
+#define FBW_EEPROM_F_EXT_MAC_SIZE 2
+#define FBW_EEPROM_F_LOCATION 8
+#define FBW_EEPROM_F_CRC8 1
+
+struct wedge_eeprom_st {
+ /* version number of the eeprom. Must be the first element */
+ uint8_t fbw_version;
+
+ /* Product Name */
+ char fbw_product_name[FBW_EEPROM_F_PRODUCT_NAME + 1];
+
+ /* Top Level 20 - Product Part Number: XX-XXXXXX */
+ char fbw_product_number[FBW_EEPROM_F_PRODUCT_NUMBER + 2];
+
+ /* System Assembly Part Number XXX-XXXXXX-XX */
+ char fbw_assembly_number[FBW_EEPROM_F_ASSEMBLY_NUMBER + 3];
+
+ /* Facebook PCB Part Number: XXX-XXXXXXX-XX */
+ char fbw_facebook_pcb_number[FBW_EEPROM_F_FACEBOOK_PCB_NUMBER + 3];
+
+ /* ODM PCB Part Number: XXXXXXXXXXXX */
+ char fbw_odm_pcb_number[FBW_EEPROM_F_ODM_PCB_NUMBER + 1];
+
+ /* ODM PCB Serial Number: XXXXXXXXXXXX */
+ char fbw_odm_pcb_serial[FBW_EEPROM_F_ODM_PCB_SERIAL + 1];
+
+ /* Product Production State */
+ uint8_t fbw_production_state;
+
+ /* Product Version */
+ uint8_t fbw_product_version;
+
+ /* Product Sub Version */
+ uint8_t fbw_product_subversion;
+
+ /* Product Serial Number: XXXXXXXX */
+ char fbw_product_serial[FBW_EEPROM_F_PRODUCT_SERIAL + 1];
+
+ /* Product Asset Tag: XXXXXXXX */
+ char fbw_product_asset[FBW_EEPROM_F_PRODUCT_ASSET + 1];
+
+ /* System Manufacturer: XXXXXXXX */
+ char fbw_system_manufacturer[FBW_EEPROM_F_SYSTEM_MANUFACTURER + 1];
+
+ /* System Manufacturing Date: mm-dd-yy */
+ char fbw_system_manufacturing_date[10];
+
+ /* PCB Manufacturer: XXXXXXXXX */
+ char fbw_pcb_manufacturer[FBW_EEPROM_F_PCB_MANUFACTURER + 1];
+
+ /* Assembled At: XXXXXXXX */
+ char fbw_assembled[FBW_EEPROM_F_ASSEMBLED + 1];
+
+ /* Local MAC Address */
+ uint8_t fbw_local_mac[6];
+
+ /* Extended MAC Address */
+ uint8_t fbw_mac_base[6];
+
+ /* Extended MAC Address Size */
+ uint16_t fbw_mac_size;
+
+ /* Location on Fabric: "LEFT"/"RIGHT", "WEDGE", "LC" */
+ char fbw_location[FBW_EEPROM_F_LOCATION + 1];
+
+ /* CRC8 */
+ uint8_t fbw_crc8;
+};
+
+int wedge_eeprom_parse(const char *fn, struct wedge_eeprom_st *eeprom);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/meta-facebook/meta-wedge/recipes-wedge/wedge-eeprom/files/utils/Makefile b/meta-facebook/meta-wedge/recipes-wedge/wedge-eeprom/files/utils/Makefile
new file mode 100644
index 0000000..30aac75
--- /dev/null
+++ b/meta-facebook/meta-wedge/recipes-wedge/wedge-eeprom/files/utils/Makefile
@@ -0,0 +1,10 @@
+# Copyright 2014-present Facebook. All Rights Reserved.
+utils: weutil
+
+weutil: weutil.o
+ $(CC) $(LDFLAGS) -o $@ $^ -lwedge_eeprom
+
+.PHONY: clean
+
+clean:
+ rm -rf *.o weutil
diff --git a/meta-facebook/meta-wedge/recipes-wedge/wedge-eeprom/files/utils/weutil.c b/meta-facebook/meta-wedge/recipes-wedge/wedge-eeprom/files/utils/weutil.c
new file mode 100644
index 0000000..9e932aa
--- /dev/null
+++ b/meta-facebook/meta-wedge/recipes-wedge/wedge-eeprom/files/utils/weutil.c
@@ -0,0 +1,74 @@
+/*
+ * Copyright 2014-present Facebook. All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <errno.h>
+#include <stdio.h>
+
+#include <facebook/wedge_eeprom.h>
+#include <facebook/log.h>
+
+int main(int argc, const char *argv[])
+{
+ const char *fn;
+ struct wedge_eeprom_st eeprom;
+ int rc;
+
+ if (argc >= 2) {
+ fn = argv[1];
+ } else {
+ fn = NULL;
+ }
+
+ rc = wedge_eeprom_parse(fn, &eeprom);
+ if (rc) {
+ fprintf(stderr, "Failed to parse %s EEPROM\n", fn ? fn : "default");
+ return -1;
+ }
+
+ printf("Wedge EEPROM %s:\n", fn ? fn : "");
+ printf("Version: %d\n", eeprom.fbw_version);
+ printf("Product Name: %s\n", eeprom.fbw_product_name);
+ printf("Product Part Number: %s\n", eeprom.fbw_product_number);
+ printf("System Assembly Part Number: %s\n", eeprom.fbw_assembly_number);
+ printf("Facebook PCB Part Number: %s\n", eeprom.fbw_facebook_pcb_number);
+ printf("ODM PCB Part Number: %s\n", eeprom.fbw_odm_pcb_number);
+ printf("ODM PCB Serial Number: %s\n", eeprom.fbw_odm_pcb_serial);
+ printf("Product Production State: %d\n", eeprom.fbw_production_state);
+ printf("Product Version: %d\n", eeprom.fbw_product_version);
+ printf("Product Sub-Version: %d\n", eeprom.fbw_product_subversion);
+ printf("Product Serial Number: %s\n", eeprom.fbw_product_serial);
+ printf("Product Asset Tag: %s\n", eeprom.fbw_product_asset);
+ printf("System Manufacturer: %s\n", eeprom.fbw_system_manufacturer);
+ printf("System Manufacturing Date: %s\n",
+ eeprom.fbw_system_manufacturing_date);
+ printf("PCB Manufacturer: %s\n", eeprom.fbw_pcb_manufacturer);
+ printf("Assembled At: %s\n", eeprom.fbw_assembled);
+ printf("Local MAC: %X:%X:%X:%X:%X:%X\n",
+ eeprom.fbw_local_mac[0], eeprom.fbw_local_mac[1],
+ eeprom.fbw_local_mac[2], eeprom.fbw_local_mac[3],
+ eeprom.fbw_local_mac[4], eeprom.fbw_local_mac[5]);
+ printf("Extended MAC Base: %X:%X:%X:%X:%X:%X\n",
+ eeprom.fbw_mac_base[0], eeprom.fbw_mac_base[1],
+ eeprom.fbw_mac_base[2], eeprom.fbw_mac_base[3],
+ eeprom.fbw_mac_base[4], eeprom.fbw_mac_base[5]);
+ printf("Extended MAC Address Size: %d\n", eeprom.fbw_mac_size);
+ printf("Location on Fabric: %s\n", eeprom.fbw_location);
+ printf("CRC8: 0x%x\n", eeprom.fbw_crc8);
+
+ return 0;
+}
diff --git a/meta-facebook/meta-wedge/recipes-wedge/wedge-eeprom/libwedge-eeprom_0.1.bb b/meta-facebook/meta-wedge/recipes-wedge/wedge-eeprom/libwedge-eeprom_0.1.bb
new file mode 100644
index 0000000..781cf76
--- /dev/null
+++ b/meta-facebook/meta-wedge/recipes-wedge/wedge-eeprom/libwedge-eeprom_0.1.bb
@@ -0,0 +1,26 @@
+# Copyright 2014-present Facebook. All Rights Reserved.
+SUMMARY = "Wedge EEPROM Library"
+DESCRIPTION = "library for wedge eeprom"
+SECTION = "base"
+PR = "r1"
+LICENSE = "GPLv2"
+LIC_FILES_CHKSUM = "file://wedge_eeprom.c;beginline=4;endline=16;md5=da35978751a9d71b73679307c4d296ec"
+
+SRC_URI = "file://lib \
+ "
+
+DEPENDS += "fbutils"
+
+S = "${WORKDIR}/lib"
+
+do_install() {
+ install -d ${D}${libdir}
+ install -m 0644 libwedge_eeprom.so ${D}${libdir}/libwedge_eeprom.so
+
+ install -d ${D}${includedir}/facebook
+ install -m 0644 wedge_eeprom.h ${D}${includedir}/facebook/wedge_eeprom.h
+}
+
+FILES_${PN} = "${libdir}/libwedge_eeprom.so"
+FILES_${PN}-dbg = "${libdir}/.debug"
+FILES_${PN}-dev = "${includedir}/facebook/wedge_eeprom.h"
diff --git a/meta-facebook/meta-wedge/recipes-wedge/wedge-eeprom/wedge-eeprom_0.1.bb b/meta-facebook/meta-wedge/recipes-wedge/wedge-eeprom/wedge-eeprom_0.1.bb
new file mode 100644
index 0000000..51bdbb9
--- /dev/null
+++ b/meta-facebook/meta-wedge/recipes-wedge/wedge-eeprom/wedge-eeprom_0.1.bb
@@ -0,0 +1,21 @@
+# Copyright 2014-present Facebook. All Rights Reserved.
+SUMMARY = "Wedge EEPROM Utilities"
+DESCRIPTION = "Util for wedge eeprom"
+SECTION = "base"
+PR = "r1"
+LICENSE = "GPLv2"
+LIC_FILES_CHKSUM = "file://weutil.c;beginline=4;endline=16;md5=da35978751a9d71b73679307c4d296ec"
+
+SRC_URI = "file://utils \
+ "
+
+S = "${WORKDIR}/utils"
+
+do_install() {
+ install -d ${D}${bindir}
+ install -m 0755 weutil ${D}${bindir}/weutil
+}
+
+DEPENDS += "libwedge-eeprom"
+
+FILES_${PN} = "${bindir}"
OpenPOWER on IntegriCloud