* [PATCH 0/6] RFC: patches I plan to push
@ 2011-04-02 14:18 Petr Štetiar
2011-04-02 14:18 ` [PATCH 1/6] zeromq: add new recipe for version 2.1.1 Petr Štetiar
` (6 more replies)
0 siblings, 7 replies; 10+ messages in thread
From: Petr Štetiar @ 2011-04-02 14:18 UTC (permalink / raw)
To: openembedded-devel
Hi,
I plan to push few patches, so I'm posting them for the review first to get some
feedback (if any). Thanks.
-- ynezz
Petr Štetiar (6):
zeromq: add new recipe for version 2.1.1
lua-lanes: add recipe for version 2.1.0 and delete the old one
librs232: add version 1.0.1 and remove the old one
lua-rs232: add recipe for version 1.0.1, remove old package and fix
stripping
linux-2.6.36: remove ts72xx support because 2.6.38 is now default
linux-2.6.38: add support for ts72xx and make it default
recipes/librs232/librs232_1.0.0.bb | 10 -
recipes/librs232/librs232_1.0.1.bb | 10 +
.../linux-2.6.36/ts72xx/0001-ts72xx_base.patch | 450 --
.../ts72xx/0002-ts72xx_force_machine-id.patch | 49 -
.../linux-2.6.36/ts72xx/0003-ep93xx_cpuinfo.patch | 36 -
.../linux-2.6.36/ts72xx/0004-ep93xx_eth.patch | 555 ---
.../ts72xx/0005-ep93xx-m2m-DMA-support.patch | 886 ----
.../linux-2.6.36/ts72xx/0006-ts72xx_rs485.patch | 223 -
.../linux-2.6.36/ts72xx/0007-ts72xx_ts_ser1.patch | 264 --
.../ts72xx/0008-ts72xx_ts_eth100.patch | 278 --
.../linux-2.6.36/ts72xx/0009-ts72xx_pata.patch | 437 --
.../linux-2.6.36/ts72xx/0010-ts72xx_gpio_i2c.patch | 63 -
.../ts72xx/0011-ts72xx_dio_keypad.patch | 311 --
.../linux-2.6.36/ts72xx/0012-ts72xx_sbcinfo.patch | 267 --
.../linux-2.6.36/ts72xx/0013-ts72xx_max197.patch | 356 --
.../ts72xx/0014-ts7200_nor_flash.patch | 181 -
.../linux-2.6.36/ts72xx/0015-ts72xx_sdcard.patch | 3298 --------------
.../ts72xx/0016-ts72xx_spi_tmp124.patch | 305 --
.../0017-ts72xx-use-CPLD-watchdog-for-reset.patch | 53 -
.../ts72xx/0018-ethoc-ts7300-fixes.patch | 93 -
.../ts72xx/0019-ts7300-add-ethernet-support.patch | 87 -
.../ts72xx/0023-ts72xx-add-lcd-linux-driver.patch | 4569 -------------------
.../ts72xx/0024-ts72xx-add-GPIO-keys.patch | 100 -
recipes/linux/linux-2.6.36/ts72xx/defconfig | 2127 ---------
.../linux-2.6.38/ts72xx/0001-ts72xx_base.patch | 451 ++
.../ts72xx/0002-ts72xx_force_machine-id.patch | 49 +
.../linux-2.6.38/ts72xx/0003-ep93xx_cpuinfo.patch | 36 +
.../linux-2.6.38/ts72xx/0004-ep93xx_eth.patch | 553 +++
.../ts72xx/0005-ep93xx-m2m-DMA-support.patch | 870 ++++
.../linux-2.6.38/ts72xx/0006-ts72xx_rs485.patch | 221 +
.../linux-2.6.38/ts72xx/0007-ts72xx_ts_ser1.patch | 264 ++
.../ts72xx/0008-ts72xx_ts_eth100.patch | 278 ++
.../linux-2.6.38/ts72xx/0009-ts72xx_pata.patch | 437 ++
.../linux-2.6.38/ts72xx/0010-ts72xx_gpio_i2c.patch | 63 +
.../ts72xx/0011-ts72xx_dio_keypad.patch | 311 ++
.../linux-2.6.38/ts72xx/0012-ts72xx_sbcinfo.patch | 267 ++
.../linux-2.6.38/ts72xx/0013-ts72xx_max197.patch | 356 ++
.../ts72xx/0014-ts7200_nor_flash.patch | 181 +
.../linux-2.6.38/ts72xx/0015-ts72xx_sdcard.patch | 3299 ++++++++++++++
.../ts72xx/0016-ts72xx_spi_tmp124.patch | 305 ++
.../0017-ts72xx-use-CPLD-watchdog-for-reset.patch | 53 +
.../ts72xx/0018-ethoc-ts7300-fixes.patch | 72 +
.../ts72xx/0019-ts7300-add-ethernet-support.patch | 87 +
.../ts72xx/0020-ts72xx-add-lcd-linux-driver.patch | 4572 ++++++++++++++++++++
.../ts72xx/0021-TS-72XX-LCD-console-driver.patch | 528 +++
...M-ep93xx-Fix-inverted-RTS-and-DTR-signals.patch | 38 +
recipes/linux/linux-2.6.38/ts72xx/defconfig | 2214 ++++++++++
recipes/linux/linux_2.6.36.bb | 25 -
recipes/linux/linux_2.6.38.bb | 26 +
.../0001-fix-LanesTimer-inifinite-thread-GC.patch | 31 -
recipes/lua/lua-lanes-2.0.6/makefile.patch | 207 -
recipes/lua/lua-lanes-2.0.6/uclibc.patch | 13 -
recipes/lua/lua-lanes-2.1.0/makefile.patch | 207 +
recipes/lua/lua-lanes-2.1.0/uclibc.patch | 13 +
recipes/lua/lua-lanes_2.0.6.bb | 33 -
recipes/lua/lua-lanes_2.1.0.bb | 34 +
recipes/lua/lua-rs232_1.0.0.bb | 28 -
recipes/lua/lua-rs232_1.0.1.bb | 28 +
recipes/zeromq/zeromq_2.1.1.bb | 20 +
59 files changed, 15843 insertions(+), 15335 deletions(-)
delete mode 100644 recipes/librs232/librs232_1.0.0.bb
create mode 100644 recipes/librs232/librs232_1.0.1.bb
delete mode 100644 recipes/linux/linux-2.6.36/ts72xx/0001-ts72xx_base.patch
delete mode 100644 recipes/linux/linux-2.6.36/ts72xx/0002-ts72xx_force_machine-id.patch
delete mode 100644 recipes/linux/linux-2.6.36/ts72xx/0003-ep93xx_cpuinfo.patch
delete mode 100644 recipes/linux/linux-2.6.36/ts72xx/0004-ep93xx_eth.patch
delete mode 100644 recipes/linux/linux-2.6.36/ts72xx/0005-ep93xx-m2m-DMA-support.patch
delete mode 100644 recipes/linux/linux-2.6.36/ts72xx/0006-ts72xx_rs485.patch
delete mode 100644 recipes/linux/linux-2.6.36/ts72xx/0007-ts72xx_ts_ser1.patch
delete mode 100644 recipes/linux/linux-2.6.36/ts72xx/0008-ts72xx_ts_eth100.patch
delete mode 100644 recipes/linux/linux-2.6.36/ts72xx/0009-ts72xx_pata.patch
delete mode 100644 recipes/linux/linux-2.6.36/ts72xx/0010-ts72xx_gpio_i2c.patch
delete mode 100644 recipes/linux/linux-2.6.36/ts72xx/0011-ts72xx_dio_keypad.patch
delete mode 100644 recipes/linux/linux-2.6.36/ts72xx/0012-ts72xx_sbcinfo.patch
delete mode 100644 recipes/linux/linux-2.6.36/ts72xx/0013-ts72xx_max197.patch
delete mode 100644 recipes/linux/linux-2.6.36/ts72xx/0014-ts7200_nor_flash.patch
delete mode 100644 recipes/linux/linux-2.6.36/ts72xx/0015-ts72xx_sdcard.patch
delete mode 100644 recipes/linux/linux-2.6.36/ts72xx/0016-ts72xx_spi_tmp124.patch
delete mode 100644 recipes/linux/linux-2.6.36/ts72xx/0017-ts72xx-use-CPLD-watchdog-for-reset.patch
delete mode 100644 recipes/linux/linux-2.6.36/ts72xx/0018-ethoc-ts7300-fixes.patch
delete mode 100644 recipes/linux/linux-2.6.36/ts72xx/0019-ts7300-add-ethernet-support.patch
delete mode 100644 recipes/linux/linux-2.6.36/ts72xx/0023-ts72xx-add-lcd-linux-driver.patch
delete mode 100644 recipes/linux/linux-2.6.36/ts72xx/0024-ts72xx-add-GPIO-keys.patch
delete mode 100644 recipes/linux/linux-2.6.36/ts72xx/defconfig
create mode 100644 recipes/linux/linux-2.6.38/ts72xx/0001-ts72xx_base.patch
create mode 100644 recipes/linux/linux-2.6.38/ts72xx/0002-ts72xx_force_machine-id.patch
create mode 100644 recipes/linux/linux-2.6.38/ts72xx/0003-ep93xx_cpuinfo.patch
create mode 100644 recipes/linux/linux-2.6.38/ts72xx/0004-ep93xx_eth.patch
create mode 100644 recipes/linux/linux-2.6.38/ts72xx/0005-ep93xx-m2m-DMA-support.patch
create mode 100644 recipes/linux/linux-2.6.38/ts72xx/0006-ts72xx_rs485.patch
create mode 100644 recipes/linux/linux-2.6.38/ts72xx/0007-ts72xx_ts_ser1.patch
create mode 100644 recipes/linux/linux-2.6.38/ts72xx/0008-ts72xx_ts_eth100.patch
create mode 100644 recipes/linux/linux-2.6.38/ts72xx/0009-ts72xx_pata.patch
create mode 100644 recipes/linux/linux-2.6.38/ts72xx/0010-ts72xx_gpio_i2c.patch
create mode 100644 recipes/linux/linux-2.6.38/ts72xx/0011-ts72xx_dio_keypad.patch
create mode 100644 recipes/linux/linux-2.6.38/ts72xx/0012-ts72xx_sbcinfo.patch
create mode 100644 recipes/linux/linux-2.6.38/ts72xx/0013-ts72xx_max197.patch
create mode 100644 recipes/linux/linux-2.6.38/ts72xx/0014-ts7200_nor_flash.patch
create mode 100644 recipes/linux/linux-2.6.38/ts72xx/0015-ts72xx_sdcard.patch
create mode 100644 recipes/linux/linux-2.6.38/ts72xx/0016-ts72xx_spi_tmp124.patch
create mode 100644 recipes/linux/linux-2.6.38/ts72xx/0017-ts72xx-use-CPLD-watchdog-for-reset.patch
create mode 100644 recipes/linux/linux-2.6.38/ts72xx/0018-ethoc-ts7300-fixes.patch
create mode 100644 recipes/linux/linux-2.6.38/ts72xx/0019-ts7300-add-ethernet-support.patch
create mode 100644 recipes/linux/linux-2.6.38/ts72xx/0020-ts72xx-add-lcd-linux-driver.patch
create mode 100644 recipes/linux/linux-2.6.38/ts72xx/0021-TS-72XX-LCD-console-driver.patch
create mode 100644 recipes/linux/linux-2.6.38/ts72xx/0024-ARM-ep93xx-Fix-inverted-RTS-and-DTR-signals.patch
create mode 100644 recipes/linux/linux-2.6.38/ts72xx/defconfig
delete mode 100644 recipes/lua/lua-lanes-2.0.6/0001-fix-LanesTimer-inifinite-thread-GC.patch
delete mode 100644 recipes/lua/lua-lanes-2.0.6/makefile.patch
delete mode 100644 recipes/lua/lua-lanes-2.0.6/uclibc.patch
create mode 100644 recipes/lua/lua-lanes-2.1.0/makefile.patch
create mode 100644 recipes/lua/lua-lanes-2.1.0/uclibc.patch
delete mode 100644 recipes/lua/lua-lanes_2.0.6.bb
create mode 100644 recipes/lua/lua-lanes_2.1.0.bb
delete mode 100644 recipes/lua/lua-rs232_1.0.0.bb
create mode 100644 recipes/lua/lua-rs232_1.0.1.bb
create mode 100644 recipes/zeromq/zeromq_2.1.1.bb
^ permalink raw reply [flat|nested] 10+ messages in thread
* [PATCH 1/6] zeromq: add new recipe for version 2.1.1
2011-04-02 14:18 [PATCH 0/6] RFC: patches I plan to push Petr Štetiar
@ 2011-04-02 14:18 ` Petr Štetiar
2011-04-02 14:18 ` [PATCH 2/6] lua-lanes: add recipe for version 2.1.0 and delete the old one Petr Štetiar
` (5 subsequent siblings)
6 siblings, 0 replies; 10+ messages in thread
From: Petr Štetiar @ 2011-04-02 14:18 UTC (permalink / raw)
To: openembedded-devel
Tested-by: Craig Swank <craigswank@gmail.com>
Signed-off-by: Petr Štetiar <ynezz@true.cz>
---
recipes/zeromq/zeromq_2.1.1.bb | 20 ++++++++++++++++++++
1 files changed, 20 insertions(+), 0 deletions(-)
create mode 100644 recipes/zeromq/zeromq_2.1.1.bb
diff --git a/recipes/zeromq/zeromq_2.1.1.bb b/recipes/zeromq/zeromq_2.1.1.bb
new file mode 100644
index 0000000..a73ceda
--- /dev/null
+++ b/recipes/zeromq/zeromq_2.1.1.bb
@@ -0,0 +1,20 @@
+DESCRIPTION = "ZeroMQ looks like an embeddable networking library but acts like a concurrency framework"
+HOMEPAGE = "http://www.zeromq.org"
+LICENSE = "LGPLv3"
+
+PR = "r0"
+
+DEPENDS += "util-linux-ng"
+
+S = "${WORKDIR}/zeromq-${PV}"
+
+SRC_URI = "http://download.zeromq.org/zeromq-${PV}.tar.gz"
+
+inherit autotools
+
+do_configure_prepend() {
+ ./autogen.sh
+}
+
+SRC_URI[md5sum] = "987079513e4816979e4e3bd52ac4b0a7"
+SRC_URI[sha256sum] = "963844dcc2bd7b3c9104343d17c2b21125864edb9d953ae2b9ee844ea07b39ce"
--
1.7.1
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [PATCH 2/6] lua-lanes: add recipe for version 2.1.0 and delete the old one
2011-04-02 14:18 [PATCH 0/6] RFC: patches I plan to push Petr Štetiar
2011-04-02 14:18 ` [PATCH 1/6] zeromq: add new recipe for version 2.1.1 Petr Štetiar
@ 2011-04-02 14:18 ` Petr Štetiar
2011-04-02 14:18 ` [PATCH 3/6] librs232: add version 1.0.1 and remove " Petr Štetiar
` (4 subsequent siblings)
6 siblings, 0 replies; 10+ messages in thread
From: Petr Štetiar @ 2011-04-02 14:18 UTC (permalink / raw)
To: openembedded-devel
I'm removing the old version 2.0.6, because it shouldn't have been commited
anyway. It was quite buggy and untested version.
Signed-off-by: Petr Štetiar <ynezz@true.cz>
---
.../0001-fix-LanesTimer-inifinite-thread-GC.patch | 31 ---
recipes/lua/lua-lanes-2.0.6/makefile.patch | 207 --------------------
recipes/lua/lua-lanes-2.0.6/uclibc.patch | 13 --
recipes/lua/lua-lanes-2.1.0/makefile.patch | 207 ++++++++++++++++++++
recipes/lua/lua-lanes-2.1.0/uclibc.patch | 13 ++
recipes/lua/lua-lanes_2.0.6.bb | 33 ---
recipes/lua/lua-lanes_2.1.0.bb | 34 ++++
7 files changed, 254 insertions(+), 284 deletions(-)
delete mode 100644 recipes/lua/lua-lanes-2.0.6/0001-fix-LanesTimer-inifinite-thread-GC.patch
delete mode 100644 recipes/lua/lua-lanes-2.0.6/makefile.patch
delete mode 100644 recipes/lua/lua-lanes-2.0.6/uclibc.patch
create mode 100644 recipes/lua/lua-lanes-2.1.0/makefile.patch
create mode 100644 recipes/lua/lua-lanes-2.1.0/uclibc.patch
delete mode 100644 recipes/lua/lua-lanes_2.0.6.bb
create mode 100644 recipes/lua/lua-lanes_2.1.0.bb
diff --git a/recipes/lua/lua-lanes-2.0.6/0001-fix-LanesTimer-inifinite-thread-GC.patch b/recipes/lua/lua-lanes-2.0.6/0001-fix-LanesTimer-inifinite-thread-GC.patch
deleted file mode 100644
index 18fb36b..0000000
--- a/recipes/lua/lua-lanes-2.0.6/0001-fix-LanesTimer-inifinite-thread-GC.patch
+++ /dev/null
@@ -1,31 +0,0 @@
-From 69583ec6fc6cd18a0248d1233193bb2407dbda04 Mon Sep 17 00:00:00 2001
-From: =?UTF-8?q?Petr=20=C5=A0tetiar?= <ynezz@true.cz>
-Date: Sun, 31 Oct 2010 23:02:49 +0100
-Subject: [PATCH] fix LanesTimer inifinite thread GC
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-threading.c 394: pthread_cond_destroy(ref) failed, 16 EBUSY
-
-Signed-off-by: Petr Štetiar <ynezz@true.cz>
----
- src/lanes.c | 2 +-
- 1 files changed, 1 insertions(+), 1 deletions(-)
-
-diff --git a/src/lanes.c b/src/lanes.c
-index c02c540..54cfa7a 100644
---- a/src/lanes.c
-+++ b/src/lanes.c
-@@ -1559,7 +1559,7 @@ LUAG_FUNC( thread_gc ) {
-
- // We can read 's->status' without locks, but not wait for it
- //
-- if (s->status < DONE) {
-+ if (s->status < DONE && strcmp(s->threadName, "LanesTimer")) {
- //
- selfdestruct_add(s);
- assert( s->selfdestruct_next );
---
-1.7.0.4
-
diff --git a/recipes/lua/lua-lanes-2.0.6/makefile.patch b/recipes/lua/lua-lanes-2.0.6/makefile.patch
deleted file mode 100644
index 6807010..0000000
--- a/recipes/lua/lua-lanes-2.0.6/makefile.patch
+++ /dev/null
@@ -1,207 +0,0 @@
-Index: lanes-2.0.6/src/Makefile
-===================================================================
---- lanes-2.0.6.orig/src/Makefile 2009-01-22 07:32:18.000000000 +0100
-+++ lanes-2.0.6/src/Makefile 2010-10-17 22:00:16.000000000 +0200
-@@ -11,123 +11,21 @@
-
- OBJ=$(SRC:.c=.o)
-
--# LuaRocks gives 'LIBFLAG' from the outside
--#
--LIBFLAG=-shared
--
--OPT_FLAGS=-O2
-- # -O0 -g
--
- LUA=lua
- LUAC=luac
-
--_SO=.so
--ifeq "$(findstring MINGW32,$(shell uname -s))" "MINGW32"
-- _SO=.dll
--endif
--
--ifeq "$(LUAROCKS)" ""
-- ifeq "$(findstring MINGW32,$(shell uname -s))" "MINGW32"
-- # MinGW MSYS on Windows
-- #
-- # - 'lua' and 'luac' expected to be on the path
-- # - %LUA_DEV% must lead to include files and libraries (Lua for Windows >= 5.1.3.14)
-- # - %MSCVR80% must be the full pathname of 'msvcr80.dll'
-- #
-- ifeq "$(LUA_DEV)" ""
-- $(error LUA_DEV not defined - try i.e. 'make LUA_DEV=/c/Program\ Files/Lua/5.1')
-- endif
-- ifeq "$(MSVCR80)" ""
-- MSVCR80:=$(LUA_DEV)/install/support/Microsoft.VC80.CRT.SP1/MSVCR80.DLL
-- ifneq '$(shell test -f "$(MSVCR80)" && echo found)' 'found'
-- $(error MSVCR80 not defined - set it to full path of msvcr80.dll')
-- endif
-- $(warning MSVCR80=$(MSVCR80))
-- endif
-- LUA_FLAGS:=-I "$(LUA_DEV)/include"
-- LUA_LIBS:="$(LUA_DEV)/lua5.1.dll" -lgcc -lmsvcr80 "$(MSVCR80)"
-- LIBFLAG=-shared -Wl,-Map,lanes.map
-- else
-- # Autodetect LUA_FLAGS and/or LUA_LIBS
-- #
-- ifneq "$(shell which pkg-config)" ""
-- ifeq "$(shell pkg-config --exists lua5.1 && echo 1)" "1"
-- LUA_FLAGS:=$(shell pkg-config --cflags lua5.1)
-- LUA_LIBS:=$(shell pkg-config --libs lua5.1)
-- #
-- # Ubuntu: -I/usr/include/lua5.1
-- # -llua5.1
-- else
-- ifeq "$(shell pkg-config --exists lua && echo 1)" "1"
-- LUA_FLAGS:=$(shell pkg-config --cflags lua)
-- LUA_LIBS:=$(shell pkg-config --libs lua)
-- #
-- # OS X fink with pkg-config:
-- # -I/sw/include
-- # -L/sw/lib -llua -lm
-- else
-- $(warning *** 'pkg-config' existed but did not know of 'lua[5.1]' - Good luck!)
-- LUA_FLAGS:=
-- LUA_LIBS:=-llua
-- endif
-- endif
-- else
-- # No 'pkg-config'; try defaults
-- #
-- ifeq "$(shell uname -s)" "Darwin"
-- $(warning *** Assuming 'fink' at default path)
-- LUA_FLAGS:=-I/sw/include
-- LUA_LIBS:=-L/sw/lib -llua
-- else
-- $(warning *** Assuming an arbitrary Lua installation; try installing 'pkg-config')
-- LUA_FLAGS:=
-- LUA_LIBS:=-llua
-- endif
-- endif
-- endif
--
-- ifeq "$(shell uname -s)" "Darwin"
-- # Some machines need 'MACOSX_DEPLOYMENT_TARGET=10.3' for using '-undefined dynamic_lookup'
-- # (at least PowerPC running 10.4.11); does not harm the others
-- #
-- CC = MACOSX_DEPLOYMENT_TARGET=10.3 gcc
-- LIBFLAG = -bundle -undefined dynamic_lookup
-- endif
--
-- CFLAGS=-Wall -Werror $(OPT_FLAGS) $(LUA_FLAGS)
-- LIBS=$(LUA_LIBS)
--endif
--
- #---
--# PThread platform specifics
--#
--ifeq "$(shell uname -s)" "Linux"
-- # -D_GNU_SOURCE needed for 'pthread_mutexattr_settype'
-- CFLAGS += -D_GNU_SOURCE -fPIC
--
-- # Use of -DUSE_PTHREAD_TIMEDJOIN is possible, but not recommended (slower & keeps threads
-- # unreleased somewhat longer)
-- #CFLAGS += -DUSE_PTHREAD_TIMEDJOIN
--
-- LIBS += -lpthread
--endif
--
--ifeq "$(shell uname -s)" "BSD"
-- LIBS += -lpthread
--endif
--
--#---
--all: lua51-$(MODULE)$(_SO)
-+all: lua51-$(MODULE).so
-
- %.o: %.c *.h Makefile
-
- # Note: Don't put $(LUA_LIBS) ahead of $^; MSYS will not like that (I think)
- #
--lua51-$(MODULE)$(_SO): $(OBJ)
-- $(CC) $(LIBFLAG) $(LIBS) $^ $(LUA_LIBS) -o $@
-+lua51-$(MODULE).so: $(OBJ)
-+ $(CC) -shared -fPIC -lpthread -D_GNU_SOURCE `pkg-config --cflags --libs lua5.1` $(MYFLAGS) $^ -o $@
-
- clean:
-- -rm -rf lua51-$(MODULE)$(_SO) *.lch *.o *.tmp *.map
-+ -rm -rf lua51-$(MODULE).so *.lch *.o *.tmp *.map
-
- lanes.o: keeper.lch
-
-@@ -139,38 +37,5 @@
- $(LUA) ../tools/bin2c.lua $@.tmp -o $@
- -rm $@.tmp
-
--#---
--# NSLU2 "slug" Linux ARM
--#
--nslu2:
-- $(MAKE) all CFLAGS="$(CFLAGS) -I/opt/include -L/opt/lib -D_GNU_SOURCE -lpthread"
--
--#---
--# Cross compiling to Win32 (MinGW on OS X Intel)
--#
--# Point WIN32_LUA51 to an extraction of LuaBinaries dll8 and dev packages.
--#
--# Note: Only works on platforms with same endianess (i.e. not from PowerPC OS X,
--# since 'luac' uses the host endianess)
--#
--# EXPERIMENTAL; NOT TESTED OF LATE.
--#
--MINGW_GCC=mingw32-gcc
-- # i686-pc-mingw32-gcc
--
--win32: $(WIN32_LUA51)/include/lua.h
-- $(MAKE) build CC=$(MINGW_GCC) \
-- LUA_FLAGS=-I$(WIN32_LUA51)/include \
-- LUA_LIBS="-L$(WIN32_LUA51) -llua51" \
-- _SO=.dll \
-- SO_FLAGS=-shared \
-- LUA=lua51 \
-- LUAC=luac51
--
--$(WIN32_LUA51)/include/lua.h:
-- @echo "Usage: make win32 WIN32_LUA51=<path of extracted LuaBinaries dll8 and dev packages>"
-- @echo " [MINGW_GCC=...mingw32-gcc]"
-- @false
--
--.PROXY: all clean nslu2 win32
-+.PROXY: all clean
-
-Index: lanes-2.0.6/Makefile
-===================================================================
---- lanes-2.0.6.orig/Makefile 2010-07-27 11:39:00.000000000 +0200
-+++ lanes-2.0.6/Makefile 2010-10-17 22:14:20.000000000 +0200
-@@ -32,8 +32,10 @@
- else
- # Autodetect LUA & LUAC
- #
-- LUA=$(word 1,$(shell which lua5.1) $(shell which lua51) lua)
-- LUAC=$(word 1,$(shell which luac5.1) $(shell which luac51) luac)
-+ #LUA=$(word 1,$(shell which lua5.1) $(shell which lua51) lua)
-+ #LUAC=$(word 1,$(shell which luac5.1) $(shell which luac51) luac)
-+ LUA=lua
-+ LUAC=luac
- endif
-
- _PREFIX=LUA_CPATH=./src/?$(_SO) LUA_PATH="src/?.lua;./tests/?.lua"
-@@ -42,7 +44,7 @@
- all: $(_TARGET_SO)
-
- $(_TARGET_SO): src/*.lua src/*.c src/*.h
-- cd src && $(MAKE) LUA=$(LUA) LUAC=$(LUAC)
-+ cd src && $(MAKE) LUA=$(LUA) LUAC=$(LUAC) MYFLAGS='$(MYFLAGS)'
-
- clean:
- cd src && $(MAKE) clean
-@@ -183,7 +185,7 @@
- #
- install: $(_TARGET_SO) src/lanes.lua
- mkdir -p $(LUA_LIBDIR) $(LUA_SHAREDIR)
-- install -m 644 $(_TARGET_SO) $(LUA_LIBDIR)
-+ install $(_TARGET_SO) $(LUA_LIBDIR)
- cp -p src/lanes.lua $(LUA_SHAREDIR)
-
-
diff --git a/recipes/lua/lua-lanes-2.0.6/uclibc.patch b/recipes/lua/lua-lanes-2.0.6/uclibc.patch
deleted file mode 100644
index b3d1f83..0000000
--- a/recipes/lua/lua-lanes-2.0.6/uclibc.patch
+++ /dev/null
@@ -1,13 +0,0 @@
-Index: lanes-2.0.6/src/threading.h
-===================================================================
---- lanes-2.0.6.orig/src/threading.h 2010-10-10 09:35:20.000000000 +0200
-+++ lanes-2.0.6/src/threading.h 2010-10-10 09:35:32.000000000 +0200
-@@ -112,7 +112,7 @@
- #ifdef PLATFORM_OSX
- #define YIELD() pthread_yield_np()
- #else
-- #define YIELD() pthread_yield()
-+ #define YIELD() sched_yield()
- #endif
- #endif
-
diff --git a/recipes/lua/lua-lanes-2.1.0/makefile.patch b/recipes/lua/lua-lanes-2.1.0/makefile.patch
new file mode 100644
index 0000000..6807010
--- /dev/null
+++ b/recipes/lua/lua-lanes-2.1.0/makefile.patch
@@ -0,0 +1,207 @@
+Index: lanes-2.0.6/src/Makefile
+===================================================================
+--- lanes-2.0.6.orig/src/Makefile 2009-01-22 07:32:18.000000000 +0100
++++ lanes-2.0.6/src/Makefile 2010-10-17 22:00:16.000000000 +0200
+@@ -11,123 +11,21 @@
+
+ OBJ=$(SRC:.c=.o)
+
+-# LuaRocks gives 'LIBFLAG' from the outside
+-#
+-LIBFLAG=-shared
+-
+-OPT_FLAGS=-O2
+- # -O0 -g
+-
+ LUA=lua
+ LUAC=luac
+
+-_SO=.so
+-ifeq "$(findstring MINGW32,$(shell uname -s))" "MINGW32"
+- _SO=.dll
+-endif
+-
+-ifeq "$(LUAROCKS)" ""
+- ifeq "$(findstring MINGW32,$(shell uname -s))" "MINGW32"
+- # MinGW MSYS on Windows
+- #
+- # - 'lua' and 'luac' expected to be on the path
+- # - %LUA_DEV% must lead to include files and libraries (Lua for Windows >= 5.1.3.14)
+- # - %MSCVR80% must be the full pathname of 'msvcr80.dll'
+- #
+- ifeq "$(LUA_DEV)" ""
+- $(error LUA_DEV not defined - try i.e. 'make LUA_DEV=/c/Program\ Files/Lua/5.1')
+- endif
+- ifeq "$(MSVCR80)" ""
+- MSVCR80:=$(LUA_DEV)/install/support/Microsoft.VC80.CRT.SP1/MSVCR80.DLL
+- ifneq '$(shell test -f "$(MSVCR80)" && echo found)' 'found'
+- $(error MSVCR80 not defined - set it to full path of msvcr80.dll')
+- endif
+- $(warning MSVCR80=$(MSVCR80))
+- endif
+- LUA_FLAGS:=-I "$(LUA_DEV)/include"
+- LUA_LIBS:="$(LUA_DEV)/lua5.1.dll" -lgcc -lmsvcr80 "$(MSVCR80)"
+- LIBFLAG=-shared -Wl,-Map,lanes.map
+- else
+- # Autodetect LUA_FLAGS and/or LUA_LIBS
+- #
+- ifneq "$(shell which pkg-config)" ""
+- ifeq "$(shell pkg-config --exists lua5.1 && echo 1)" "1"
+- LUA_FLAGS:=$(shell pkg-config --cflags lua5.1)
+- LUA_LIBS:=$(shell pkg-config --libs lua5.1)
+- #
+- # Ubuntu: -I/usr/include/lua5.1
+- # -llua5.1
+- else
+- ifeq "$(shell pkg-config --exists lua && echo 1)" "1"
+- LUA_FLAGS:=$(shell pkg-config --cflags lua)
+- LUA_LIBS:=$(shell pkg-config --libs lua)
+- #
+- # OS X fink with pkg-config:
+- # -I/sw/include
+- # -L/sw/lib -llua -lm
+- else
+- $(warning *** 'pkg-config' existed but did not know of 'lua[5.1]' - Good luck!)
+- LUA_FLAGS:=
+- LUA_LIBS:=-llua
+- endif
+- endif
+- else
+- # No 'pkg-config'; try defaults
+- #
+- ifeq "$(shell uname -s)" "Darwin"
+- $(warning *** Assuming 'fink' at default path)
+- LUA_FLAGS:=-I/sw/include
+- LUA_LIBS:=-L/sw/lib -llua
+- else
+- $(warning *** Assuming an arbitrary Lua installation; try installing 'pkg-config')
+- LUA_FLAGS:=
+- LUA_LIBS:=-llua
+- endif
+- endif
+- endif
+-
+- ifeq "$(shell uname -s)" "Darwin"
+- # Some machines need 'MACOSX_DEPLOYMENT_TARGET=10.3' for using '-undefined dynamic_lookup'
+- # (at least PowerPC running 10.4.11); does not harm the others
+- #
+- CC = MACOSX_DEPLOYMENT_TARGET=10.3 gcc
+- LIBFLAG = -bundle -undefined dynamic_lookup
+- endif
+-
+- CFLAGS=-Wall -Werror $(OPT_FLAGS) $(LUA_FLAGS)
+- LIBS=$(LUA_LIBS)
+-endif
+-
+ #---
+-# PThread platform specifics
+-#
+-ifeq "$(shell uname -s)" "Linux"
+- # -D_GNU_SOURCE needed for 'pthread_mutexattr_settype'
+- CFLAGS += -D_GNU_SOURCE -fPIC
+-
+- # Use of -DUSE_PTHREAD_TIMEDJOIN is possible, but not recommended (slower & keeps threads
+- # unreleased somewhat longer)
+- #CFLAGS += -DUSE_PTHREAD_TIMEDJOIN
+-
+- LIBS += -lpthread
+-endif
+-
+-ifeq "$(shell uname -s)" "BSD"
+- LIBS += -lpthread
+-endif
+-
+-#---
+-all: lua51-$(MODULE)$(_SO)
++all: lua51-$(MODULE).so
+
+ %.o: %.c *.h Makefile
+
+ # Note: Don't put $(LUA_LIBS) ahead of $^; MSYS will not like that (I think)
+ #
+-lua51-$(MODULE)$(_SO): $(OBJ)
+- $(CC) $(LIBFLAG) $(LIBS) $^ $(LUA_LIBS) -o $@
++lua51-$(MODULE).so: $(OBJ)
++ $(CC) -shared -fPIC -lpthread -D_GNU_SOURCE `pkg-config --cflags --libs lua5.1` $(MYFLAGS) $^ -o $@
+
+ clean:
+- -rm -rf lua51-$(MODULE)$(_SO) *.lch *.o *.tmp *.map
++ -rm -rf lua51-$(MODULE).so *.lch *.o *.tmp *.map
+
+ lanes.o: keeper.lch
+
+@@ -139,38 +37,5 @@
+ $(LUA) ../tools/bin2c.lua $@.tmp -o $@
+ -rm $@.tmp
+
+-#---
+-# NSLU2 "slug" Linux ARM
+-#
+-nslu2:
+- $(MAKE) all CFLAGS="$(CFLAGS) -I/opt/include -L/opt/lib -D_GNU_SOURCE -lpthread"
+-
+-#---
+-# Cross compiling to Win32 (MinGW on OS X Intel)
+-#
+-# Point WIN32_LUA51 to an extraction of LuaBinaries dll8 and dev packages.
+-#
+-# Note: Only works on platforms with same endianess (i.e. not from PowerPC OS X,
+-# since 'luac' uses the host endianess)
+-#
+-# EXPERIMENTAL; NOT TESTED OF LATE.
+-#
+-MINGW_GCC=mingw32-gcc
+- # i686-pc-mingw32-gcc
+-
+-win32: $(WIN32_LUA51)/include/lua.h
+- $(MAKE) build CC=$(MINGW_GCC) \
+- LUA_FLAGS=-I$(WIN32_LUA51)/include \
+- LUA_LIBS="-L$(WIN32_LUA51) -llua51" \
+- _SO=.dll \
+- SO_FLAGS=-shared \
+- LUA=lua51 \
+- LUAC=luac51
+-
+-$(WIN32_LUA51)/include/lua.h:
+- @echo "Usage: make win32 WIN32_LUA51=<path of extracted LuaBinaries dll8 and dev packages>"
+- @echo " [MINGW_GCC=...mingw32-gcc]"
+- @false
+-
+-.PROXY: all clean nslu2 win32
++.PROXY: all clean
+
+Index: lanes-2.0.6/Makefile
+===================================================================
+--- lanes-2.0.6.orig/Makefile 2010-07-27 11:39:00.000000000 +0200
++++ lanes-2.0.6/Makefile 2010-10-17 22:14:20.000000000 +0200
+@@ -32,8 +32,10 @@
+ else
+ # Autodetect LUA & LUAC
+ #
+- LUA=$(word 1,$(shell which lua5.1) $(shell which lua51) lua)
+- LUAC=$(word 1,$(shell which luac5.1) $(shell which luac51) luac)
++ #LUA=$(word 1,$(shell which lua5.1) $(shell which lua51) lua)
++ #LUAC=$(word 1,$(shell which luac5.1) $(shell which luac51) luac)
++ LUA=lua
++ LUAC=luac
+ endif
+
+ _PREFIX=LUA_CPATH=./src/?$(_SO) LUA_PATH="src/?.lua;./tests/?.lua"
+@@ -42,7 +44,7 @@
+ all: $(_TARGET_SO)
+
+ $(_TARGET_SO): src/*.lua src/*.c src/*.h
+- cd src && $(MAKE) LUA=$(LUA) LUAC=$(LUAC)
++ cd src && $(MAKE) LUA=$(LUA) LUAC=$(LUAC) MYFLAGS='$(MYFLAGS)'
+
+ clean:
+ cd src && $(MAKE) clean
+@@ -183,7 +185,7 @@
+ #
+ install: $(_TARGET_SO) src/lanes.lua
+ mkdir -p $(LUA_LIBDIR) $(LUA_SHAREDIR)
+- install -m 644 $(_TARGET_SO) $(LUA_LIBDIR)
++ install $(_TARGET_SO) $(LUA_LIBDIR)
+ cp -p src/lanes.lua $(LUA_SHAREDIR)
+
+
diff --git a/recipes/lua/lua-lanes-2.1.0/uclibc.patch b/recipes/lua/lua-lanes-2.1.0/uclibc.patch
new file mode 100644
index 0000000..b3d1f83
--- /dev/null
+++ b/recipes/lua/lua-lanes-2.1.0/uclibc.patch
@@ -0,0 +1,13 @@
+Index: lanes-2.0.6/src/threading.h
+===================================================================
+--- lanes-2.0.6.orig/src/threading.h 2010-10-10 09:35:20.000000000 +0200
++++ lanes-2.0.6/src/threading.h 2010-10-10 09:35:32.000000000 +0200
+@@ -112,7 +112,7 @@
+ #ifdef PLATFORM_OSX
+ #define YIELD() pthread_yield_np()
+ #else
+- #define YIELD() pthread_yield()
++ #define YIELD() sched_yield()
+ #endif
+ #endif
+
diff --git a/recipes/lua/lua-lanes_2.0.6.bb b/recipes/lua/lua-lanes_2.0.6.bb
deleted file mode 100644
index dc9a60d..0000000
--- a/recipes/lua/lua-lanes_2.0.6.bb
+++ /dev/null
@@ -1,33 +0,0 @@
-DESCRIPTION = "Lua Lanes is a Lua extension library providing the possibility to run multiple Lua states in parallel."
-LICENSE = "MIT"
-HOMEPAGE = "http://kotisivu.dnainternet.net/askok/bin/lanes/index.html"
-
-DEPENDS += "lua5.1-native"
-RDEPENDS_${PN} += "lua5.1"
-
-PR = "r1"
-S = "${WORKDIR}/lanes-${PV}"
-
-SRC_URI = "http://luaforge.net/frs/download.php/4652/lanes-2.0.6.tgz \
- file://makefile.patch \
- file://0001-fix-LanesTimer-inifinite-thread-GC.patch \
- "
-
-UCLIBC_PATCHES = "file://uclibc.patch"
-SRC_URI_append_libc-uclibc = "${UCLIBC_PATCHES}"
-
-LUA_LIB_DIR = "${libdir}/lua/5.1"
-LUA_SHARE_DIR = "${datadir}/lua/5.1"
-
-PACKAGES = "${PN} ${PN}-dbg"
-FILES_${PN} = "${LUA_LIB_DIR}/lua51-lanes.so ${LUA_SHARE_DIR}/lanes.lua"
-FILES_${PN}-dbg = "${LUA_LIB_DIR}/.debug/lua51-lanes.so"
-
-EXTRA_OEMAKE = "MYFLAGS='${CFLAGS} ${LDFLAGS}'"
-
-do_install() {
- oe_runmake install DESTDIR='${D}/usr'
-}
-
-SRC_URI[md5sum] = "1716bdf138fcc65b7069aaad864da677"
-SRC_URI[sha256sum] = "7b07fa1c21749981ec0addcf8e9e85acfca91efe8d3f64982a6ac0bc6a615e70"
diff --git a/recipes/lua/lua-lanes_2.1.0.bb b/recipes/lua/lua-lanes_2.1.0.bb
new file mode 100644
index 0000000..bf5b3e6
--- /dev/null
+++ b/recipes/lua/lua-lanes_2.1.0.bb
@@ -0,0 +1,34 @@
+DESCRIPTION = "Lua Lanes is a Lua extension library providing the possibility to run multiple Lua states in parallel."
+LICENSE = "MIT"
+HOMEPAGE = "http://kotisivu.dnainternet.net/askok/bin/lanes/index.html"
+
+DEPENDS += "lua5.1-native"
+RDEPENDS_${PN} += "lua5.1"
+
+PR = "r0"
+
+S = "${WORKDIR}/git/"
+SRCREV = "5499ec1a61be9797c57834618a49731952b1d212"
+
+SRC_URI = "git://github.com/LuaLanes/lanes.git;protocol=git \
+ file://makefile.patch \
+ "
+
+UCLIBC_PATCHES = "file://uclibc.patch"
+SRC_URI_append_libc-uclibc = "${UCLIBC_PATCHES}"
+
+LUA_LIB_DIR = "${libdir}/lua/5.1"
+LUA_SHARE_DIR = "${datadir}/lua/5.1"
+
+PACKAGES = "${PN} ${PN}-dbg"
+FILES_${PN} = "${LUA_LIB_DIR}/lua51-lanes.so ${LUA_SHARE_DIR}/lanes.lua"
+FILES_${PN}-dbg = "${LUA_LIB_DIR}/.debug/lua51-lanes.so"
+
+EXTRA_OEMAKE = "MYFLAGS='${CFLAGS} ${LDFLAGS}'"
+
+do_install() {
+ oe_runmake install DESTDIR='${D}/usr'
+}
+
+SRC_URI[md5sum] = "1716bdf138fcc65b7069aaad864da677"
+SRC_URI[sha256sum] = "7b07fa1c21749981ec0addcf8e9e85acfca91efe8d3f64982a6ac0bc6a615e70"
--
1.7.1
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [PATCH 3/6] librs232: add version 1.0.1 and remove the old one
2011-04-02 14:18 [PATCH 0/6] RFC: patches I plan to push Petr Štetiar
2011-04-02 14:18 ` [PATCH 1/6] zeromq: add new recipe for version 2.1.1 Petr Štetiar
2011-04-02 14:18 ` [PATCH 2/6] lua-lanes: add recipe for version 2.1.0 and delete the old one Petr Štetiar
@ 2011-04-02 14:18 ` Petr Štetiar
2011-04-02 14:18 ` [PATCH 4/6] lua-rs232: add recipe for version 1.0.1, remove old package and fix stripping Petr Štetiar
` (3 subsequent siblings)
6 siblings, 0 replies; 10+ messages in thread
From: Petr Štetiar @ 2011-04-02 14:18 UTC (permalink / raw)
To: openembedded-devel
Signed-off-by: Petr Štetiar <ynezz@true.cz>
---
recipes/librs232/librs232_1.0.0.bb | 10 ----------
recipes/librs232/librs232_1.0.1.bb | 10 ++++++++++
2 files changed, 10 insertions(+), 10 deletions(-)
delete mode 100644 recipes/librs232/librs232_1.0.0.bb
create mode 100644 recipes/librs232/librs232_1.0.1.bb
diff --git a/recipes/librs232/librs232_1.0.0.bb b/recipes/librs232/librs232_1.0.0.bb
deleted file mode 100644
index f9114e7..0000000
--- a/recipes/librs232/librs232_1.0.0.bb
+++ /dev/null
@@ -1,10 +0,0 @@
-DESCRIPTION = "librs232 - library for serial communications over RS-232 (serial port)"
-HOMEPAGE = "http://github.com/ynezz/librs232"
-LICENSE = "MIT"
-
-SRC_URI = "git://github.com/ynezz/librs232.git;protocol=git"
-
-SRCREV = "ecad1e03104bc9bf348e0c5e571660f270c86421"
-S = "${WORKDIR}/git/"
-
-inherit autotools
diff --git a/recipes/librs232/librs232_1.0.1.bb b/recipes/librs232/librs232_1.0.1.bb
new file mode 100644
index 0000000..c81ce4e
--- /dev/null
+++ b/recipes/librs232/librs232_1.0.1.bb
@@ -0,0 +1,10 @@
+DESCRIPTION = "librs232 - library for serial communications over RS-232 (serial port)"
+HOMEPAGE = "http://github.com/ynezz/librs232"
+LICENSE = "MIT"
+
+SRC_URI = "git://github.com/ynezz/librs232.git;protocol=git"
+
+SRCREV = "cd9811207ee08f0bd83354b609c13f56e39d5f6c"
+S = "${WORKDIR}/git/"
+
+inherit autotools
--
1.7.1
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [PATCH 4/6] lua-rs232: add recipe for version 1.0.1, remove old package and fix stripping
2011-04-02 14:18 [PATCH 0/6] RFC: patches I plan to push Petr Štetiar
` (2 preceding siblings ...)
2011-04-02 14:18 ` [PATCH 3/6] librs232: add version 1.0.1 and remove " Petr Štetiar
@ 2011-04-02 14:18 ` Petr Štetiar
2011-04-02 14:18 ` [PATCH 5/6] linux-2.6.36: remove ts72xx support because 2.6.38 is now default Petr Štetiar
` (2 subsequent siblings)
6 siblings, 0 replies; 10+ messages in thread
From: Petr Štetiar @ 2011-04-02 14:18 UTC (permalink / raw)
To: openembedded-devel
This patch adds recipe for the version 1.0.1 of the package, removes the old
recipe and fixes the stripping of the shared library - we install the shared
library with chmod 0755 now, otherwise the do_runstrip() function doesn't
strip the library and the result is, that the library is packaged unstripped.
Signed-off-by: Petr Štetiar <ynezz@true.cz>
---
recipes/lua/lua-rs232_1.0.0.bb | 28 ----------------------------
recipes/lua/lua-rs232_1.0.1.bb | 28 ++++++++++++++++++++++++++++
2 files changed, 28 insertions(+), 28 deletions(-)
delete mode 100644 recipes/lua/lua-rs232_1.0.0.bb
create mode 100644 recipes/lua/lua-rs232_1.0.1.bb
diff --git a/recipes/lua/lua-rs232_1.0.0.bb b/recipes/lua/lua-rs232_1.0.0.bb
deleted file mode 100644
index d8de225..0000000
--- a/recipes/lua/lua-rs232_1.0.0.bb
+++ /dev/null
@@ -1,28 +0,0 @@
-DESCRIPTION = "Lua bindings for librs232 - library for serial communications over RS-232 (serial port)"
-HOMEPAGE = "http://github.com/ynezz/librs232"
-LICENSE = "MIT"
-
-PR = "r1"
-
-DEPENDS += "lua5.1"
-RDEPENDS_${PN} += "librs232"
-
-SRC_URI = "git://github.com/ynezz/librs232.git;protocol=git"
-
-SRCREV = "ecad1e03104bc9bf348e0c5e571660f270c86421"
-S = "${WORKDIR}/git/"
-
-inherit autotools
-
-LUA_LIB_DIR = "${libdir}/lua/5.1"
-LUA_LIB = "luars232.so"
-
-PACKAGES = "${PN} ${PN}-dbg"
-FILES_${PN} = "${LUA_LIB_DIR}/${LUA_LIB}"
-FILES_${PN}-dbg = "${LUA_LIB_DIR}/.debug/${LUA_LIB}"
-
-do_install_append() {
- install -d ${D}${LUA_LIB_DIR}/.debug
- install -m 0644 ${D}${libdir}/${LUA_LIB} ${D}${LUA_LIB_DIR}/${LUA_LIB}
- install -m 0644 ${D}${libdir}/${LUA_LIB} ${D}${LUA_LIB_DIR}/.debug/${LUA_LIB}
-}
diff --git a/recipes/lua/lua-rs232_1.0.1.bb b/recipes/lua/lua-rs232_1.0.1.bb
new file mode 100644
index 0000000..21c850d
--- /dev/null
+++ b/recipes/lua/lua-rs232_1.0.1.bb
@@ -0,0 +1,28 @@
+DESCRIPTION = "Lua bindings for librs232 - library for serial communications over RS-232 (serial port)"
+HOMEPAGE = "http://github.com/ynezz/librs232"
+LICENSE = "MIT"
+
+PR = "r1"
+
+DEPENDS += "lua5.1"
+RDEPENDS_${PN} += "librs232"
+
+SRC_URI = "git://github.com/ynezz/librs232.git;protocol=git"
+
+SRCREV = "cd9811207ee08f0bd83354b609c13f56e39d5f6c"
+S = "${WORKDIR}/git/"
+
+inherit autotools
+
+LUA_LIB_DIR = "${libdir}/lua/5.1"
+LUA_LIB = "luars232.so"
+
+PACKAGES = "${PN} ${PN}-dbg"
+FILES_${PN} = "${LUA_LIB_DIR}/${LUA_LIB}"
+FILES_${PN}-dbg = "${LUA_LIB_DIR}/.debug/${LUA_LIB}"
+
+do_install_append() {
+ install -d ${D}${LUA_LIB_DIR}/.debug
+ install -m 0755 ${D}${libdir}/${LUA_LIB} ${D}${LUA_LIB_DIR}/${LUA_LIB}
+ install -m 0755 ${D}${libdir}/${LUA_LIB} ${D}${LUA_LIB_DIR}/.debug/${LUA_LIB}
+}
--
1.7.1
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [PATCH 5/6] linux-2.6.36: remove ts72xx support because 2.6.38 is now default
2011-04-02 14:18 [PATCH 0/6] RFC: patches I plan to push Petr Štetiar
` (3 preceding siblings ...)
2011-04-02 14:18 ` [PATCH 4/6] lua-rs232: add recipe for version 1.0.1, remove old package and fix stripping Petr Štetiar
@ 2011-04-02 14:18 ` Petr Štetiar
2011-04-02 16:08 ` Koen Kooi
2011-04-02 14:18 ` [PATCH 6/6] linux-2.6.38: add support for ts72xx and make it default Petr Štetiar
2011-04-10 1:57 ` [PATCH 0/6] RFC: patches I plan to push Khem Raj
6 siblings, 1 reply; 10+ messages in thread
From: Petr Štetiar @ 2011-04-02 14:18 UTC (permalink / raw)
To: openembedded-devel
Signed-off-by: Petr Štetiar <ynezz@true.cz>
---
.../linux-2.6.36/ts72xx/0001-ts72xx_base.patch | 450 --
.../ts72xx/0002-ts72xx_force_machine-id.patch | 49 -
.../linux-2.6.36/ts72xx/0003-ep93xx_cpuinfo.patch | 36 -
.../linux-2.6.36/ts72xx/0004-ep93xx_eth.patch | 555 ---
.../ts72xx/0005-ep93xx-m2m-DMA-support.patch | 886 ----
.../linux-2.6.36/ts72xx/0006-ts72xx_rs485.patch | 223 -
.../linux-2.6.36/ts72xx/0007-ts72xx_ts_ser1.patch | 264 --
.../ts72xx/0008-ts72xx_ts_eth100.patch | 278 --
.../linux-2.6.36/ts72xx/0009-ts72xx_pata.patch | 437 --
.../linux-2.6.36/ts72xx/0010-ts72xx_gpio_i2c.patch | 63 -
.../ts72xx/0011-ts72xx_dio_keypad.patch | 311 --
.../linux-2.6.36/ts72xx/0012-ts72xx_sbcinfo.patch | 267 --
.../linux-2.6.36/ts72xx/0013-ts72xx_max197.patch | 356 --
.../ts72xx/0014-ts7200_nor_flash.patch | 181 -
.../linux-2.6.36/ts72xx/0015-ts72xx_sdcard.patch | 3298 --------------
.../ts72xx/0016-ts72xx_spi_tmp124.patch | 305 --
.../0017-ts72xx-use-CPLD-watchdog-for-reset.patch | 53 -
.../ts72xx/0018-ethoc-ts7300-fixes.patch | 93 -
.../ts72xx/0019-ts7300-add-ethernet-support.patch | 87 -
.../ts72xx/0023-ts72xx-add-lcd-linux-driver.patch | 4569 --------------------
.../ts72xx/0024-ts72xx-add-GPIO-keys.patch | 100 -
recipes/linux/linux-2.6.36/ts72xx/defconfig | 2127 ---------
recipes/linux/linux_2.6.36.bb | 25 -
23 files changed, 0 insertions(+), 15013 deletions(-)
delete mode 100644 recipes/linux/linux-2.6.36/ts72xx/0001-ts72xx_base.patch
delete mode 100644 recipes/linux/linux-2.6.36/ts72xx/0002-ts72xx_force_machine-id.patch
delete mode 100644 recipes/linux/linux-2.6.36/ts72xx/0003-ep93xx_cpuinfo.patch
delete mode 100644 recipes/linux/linux-2.6.36/ts72xx/0004-ep93xx_eth.patch
delete mode 100644 recipes/linux/linux-2.6.36/ts72xx/0005-ep93xx-m2m-DMA-support.patch
delete mode 100644 recipes/linux/linux-2.6.36/ts72xx/0006-ts72xx_rs485.patch
delete mode 100644 recipes/linux/linux-2.6.36/ts72xx/0007-ts72xx_ts_ser1.patch
delete mode 100644 recipes/linux/linux-2.6.36/ts72xx/0008-ts72xx_ts_eth100.patch
delete mode 100644 recipes/linux/linux-2.6.36/ts72xx/0009-ts72xx_pata.patch
delete mode 100644 recipes/linux/linux-2.6.36/ts72xx/0010-ts72xx_gpio_i2c.patch
delete mode 100644 recipes/linux/linux-2.6.36/ts72xx/0011-ts72xx_dio_keypad.patch
delete mode 100644 recipes/linux/linux-2.6.36/ts72xx/0012-ts72xx_sbcinfo.patch
delete mode 100644 recipes/linux/linux-2.6.36/ts72xx/0013-ts72xx_max197.patch
delete mode 100644 recipes/linux/linux-2.6.36/ts72xx/0014-ts7200_nor_flash.patch
delete mode 100644 recipes/linux/linux-2.6.36/ts72xx/0015-ts72xx_sdcard.patch
delete mode 100644 recipes/linux/linux-2.6.36/ts72xx/0016-ts72xx_spi_tmp124.patch
delete mode 100644 recipes/linux/linux-2.6.36/ts72xx/0017-ts72xx-use-CPLD-watchdog-for-reset.patch
delete mode 100644 recipes/linux/linux-2.6.36/ts72xx/0018-ethoc-ts7300-fixes.patch
delete mode 100644 recipes/linux/linux-2.6.36/ts72xx/0019-ts7300-add-ethernet-support.patch
delete mode 100644 recipes/linux/linux-2.6.36/ts72xx/0023-ts72xx-add-lcd-linux-driver.patch
delete mode 100644 recipes/linux/linux-2.6.36/ts72xx/0024-ts72xx-add-GPIO-keys.patch
delete mode 100644 recipes/linux/linux-2.6.36/ts72xx/defconfig
diff --git a/recipes/linux/linux-2.6.36/ts72xx/0001-ts72xx_base.patch b/recipes/linux/linux-2.6.36/ts72xx/0001-ts72xx_base.patch
deleted file mode 100644
index 3e04afc..0000000
--- a/recipes/linux/linux-2.6.36/ts72xx/0001-ts72xx_base.patch
+++ /dev/null
@@ -1,450 +0,0 @@
-From f05911e053a51d9a5aa0c8632b442354a7486f45 Mon Sep 17 00:00:00 2001
-From: Matthieu Crapet <mcrapet@gmail.com>
-Date: Thu, 10 Jun 2010 10:43:24 +0200
-Subject: [PATCH 01/24] ts72xx_base
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-- patch: allow to force nF bit in control reg
-- register pwm1
-
-Signed-off-by: Petr Štetiar <ynezz@true.cz>
----
- arch/arm/Kconfig | 3 +
- arch/arm/mach-ep93xx/Kconfig | 9 ++
- arch/arm/mach-ep93xx/include/mach/ep93xx-regs.h | 7 +
- arch/arm/mach-ep93xx/include/mach/memory.h | 28 +++++
- arch/arm/mach-ep93xx/include/mach/ts72xx.h | 145 +++++++++++++++++++++--
- arch/arm/mach-ep93xx/ts72xx.c | 41 ++++++-
- arch/arm/mm/proc-arm920.S | 5 +-
- scripts/Makefile.fwinst | 2 +-
- 8 files changed, 223 insertions(+), 17 deletions(-)
-
-diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
-index 9c26ba7..8e6c85d 100644
---- a/arch/arm/Kconfig
-+++ b/arch/arm/Kconfig
-@@ -327,6 +327,9 @@ config ARCH_EP93XX
- select CPU_ARM920T
- select ARM_AMBA
- select ARM_VIC
-+ select ARCH_SPARSEMEM_ENABLE
-+ select GENERIC_GPIO
-+ select HAVE_CLK
- select COMMON_CLKDEV
- select ARCH_REQUIRE_GPIOLIB
- select ARCH_HAS_HOLES_MEMORYMODEL
-diff --git a/arch/arm/mach-ep93xx/Kconfig b/arch/arm/mach-ep93xx/Kconfig
-index 3a08b18..b6be37e 100644
---- a/arch/arm/mach-ep93xx/Kconfig
-+++ b/arch/arm/mach-ep93xx/Kconfig
-@@ -7,6 +7,15 @@ config CRUNCH
- help
- Enable kernel support for MaverickCrunch.
-
-+config CR1_NFBIT
-+ bool "Turn on nF bit in ControlRegister 1"
-+ help
-+ Say 'Y' here to force the nF bit on. Usually this is set
-+ by the bootrom. If it is not set, then the CPU core will
-+ run from HCLK instead of FCLK, and performance will suffer.
-+ If you see BogoMIPS of about 1/4 of your CPU clock, try
-+ turning this on; your performance should double.
-+
- comment "EP93xx Platforms"
-
- choice
-diff --git a/arch/arm/mach-ep93xx/include/mach/ep93xx-regs.h b/arch/arm/mach-ep93xx/include/mach/ep93xx-regs.h
-index c54b3e5..db351cc 100644
---- a/arch/arm/mach-ep93xx/include/mach/ep93xx-regs.h
-+++ b/arch/arm/mach-ep93xx/include/mach/ep93xx-regs.h
-@@ -83,6 +83,7 @@
-
- #define EP93XX_BOOT_ROM_BASE EP93XX_AHB_IOMEM(0x00090000)
-
-+#define EP93XX_IDE_PHYS_BASE EP93XX_AHB_PHYS(0x000a0000)
- #define EP93XX_IDE_BASE EP93XX_AHB_IOMEM(0x000a0000)
-
- #define EP93XX_VIC1_BASE EP93XX_AHB_IOMEM(0x000b0000)
-@@ -97,12 +98,17 @@
- #define EP93XX_I2S_BASE EP93XX_APB_IOMEM(0x00020000)
-
- #define EP93XX_SECURITY_BASE EP93XX_APB_IOMEM(0x00030000)
-+#define EP93XX_SECURITY_REG(x) (EP93XX_SECURITY_BASE + (x))
-+#define EP93XX_SECURITY_UNIQID EP93XX_SECURITY_REG(0x2440)
-
- #define EP93XX_GPIO_BASE EP93XX_APB_IOMEM(0x00040000)
- #define EP93XX_GPIO_REG(x) (EP93XX_GPIO_BASE + (x))
- #define EP93XX_GPIO_F_INT_STATUS EP93XX_GPIO_REG(0x5c)
-+#define EP93XX_GPIO_F_INT_DEBOUNCE EP93XX_GPIO_REG(0x64)
- #define EP93XX_GPIO_A_INT_STATUS EP93XX_GPIO_REG(0xa0)
-+#define EP93XX_GPIO_A_INT_DEBOUNCE EP93XX_GPIO_REG(0xa8)
- #define EP93XX_GPIO_B_INT_STATUS EP93XX_GPIO_REG(0xbc)
-+#define EP93XX_GPIO_B_INT_DEBOUNCE EP93XX_GPIO_REG(0xc4)
- #define EP93XX_GPIO_EEDRIVE EP93XX_GPIO_REG(0xc8)
-
- #define EP93XX_AAC_BASE EP93XX_APB_IOMEM(0x00080000)
-@@ -220,6 +226,7 @@
- #define EP93XX_SYSCON_SYSCFG_LEECLK (1<<3)
- #define EP93XX_SYSCON_SYSCFG_LCSN2 (1<<1)
- #define EP93XX_SYSCON_SYSCFG_LCSN1 (1<<0)
-+#define EP93XX_SYSCON_CHIPID EP93XX_SYSCON_REG(0x94)
- #define EP93XX_SYSCON_SWLOCK EP93XX_SYSCON_REG(0xc0)
-
- #define EP93XX_WATCHDOG_BASE EP93XX_APB_IOMEM(0x00140000)
-diff --git a/arch/arm/mach-ep93xx/include/mach/memory.h b/arch/arm/mach-ep93xx/include/mach/memory.h
-index 554064e..78eaacf 100644
---- a/arch/arm/mach-ep93xx/include/mach/memory.h
-+++ b/arch/arm/mach-ep93xx/include/mach/memory.h
-@@ -19,4 +19,32 @@
- #error "Kconfig bug: No EP93xx PHYS_OFFSET set"
- #endif
-
-+/*
-+ * Non-linear mapping like so:
-+ * phys => virt
-+ * 0x00000000 => 0xc0000000
-+ * 0x01000000 => 0xc1000000
-+ * 0x04000000 => 0xc4000000
-+ * 0x05000000 => 0xc5000000
-+ * 0xe0000000 => 0xc8000000
-+ * 0xe1000000 => 0xc9000000
-+ * 0xe4000000 => 0xcc000000
-+ * 0xe5000000 => 0xcd000000
-+ *
-+ * As suggested here: http://marc.info/?l=linux-arm&m=122754446724900&w=2
-+ *
-+ * Note that static inline functions won't work here because
-+ * arch/arm/include/asm/memory.h uses "#ifndef __virt_to_phys" to check whether to
-+ * use generic functions or not.
-+ */
-+
-+#define __phys_to_virt(p) \
-+ (((p) & 0x07ffffff) | (((p) & 0xe0000000) ? 0x08000000 : 0) | PAGE_OFFSET)
-+
-+#define __virt_to_phys(v) \
-+ (((v) & 0x07ffffff) | (((v) & 0x08000000) ? 0xe0000000 : 0 ))
-+
-+#define SECTION_SIZE_BITS 24
-+#define MAX_PHYSMEM_BITS 32
-+
- #endif
-diff --git a/arch/arm/mach-ep93xx/include/mach/ts72xx.h b/arch/arm/mach-ep93xx/include/mach/ts72xx.h
-index 0eabec6..1d50dec 100644
---- a/arch/arm/mach-ep93xx/include/mach/ts72xx.h
-+++ b/arch/arm/mach-ep93xx/include/mach/ts72xx.h
-@@ -8,36 +8,41 @@
- * virt phys size
- * febff000 22000000 4K model number register
- * febfe000 22400000 4K options register
-- * febfd000 22800000 4K options register #2
-+ * febfd000 22800000 4K options register #2 (JP6 and TS-9420 flags)
-+ * febfc000 [67]0000000 4K NAND data register
-+ * febfb000 [67]0400000 4K NAND control register
-+ * febfa000 [67]0800000 4K NAND busy register
- * febf9000 10800000 4K TS-5620 RTC index register
- * febf8000 11700000 4K TS-5620 RTC data register
-+ * febf7000 23400000 4K PLD version (3 bits)
-+ * febf6000 22c00000 4K RS-485 control register
-+ * febf5000 23000000 4K RS-485 mode register
- */
-
- #define TS72XX_MODEL_PHYS_BASE 0x22000000
- #define TS72XX_MODEL_VIRT_BASE 0xfebff000
- #define TS72XX_MODEL_SIZE 0x00001000
-
--#define TS72XX_MODEL_TS7200 0x00
--#define TS72XX_MODEL_TS7250 0x01
--#define TS72XX_MODEL_TS7260 0x02
-+#define TS7XXX_MODEL_TS7200 0x00
-+#define TS7XXX_MODEL_TS7250 0x01
-+#define TS7XXX_MODEL_TS7260 0x02
-+#define TS7XXX_MODEL_TS7300 0x03
-+#define TS7XXX_MODEL_TS7400 0x04
-+#define TS7XXX_MODEL_MASK 0x07
-
-
- #define TS72XX_OPTIONS_PHYS_BASE 0x22400000
- #define TS72XX_OPTIONS_VIRT_BASE 0xfebfe000
- #define TS72XX_OPTIONS_SIZE 0x00001000
--
- #define TS72XX_OPTIONS_COM2_RS485 0x02
- #define TS72XX_OPTIONS_MAX197 0x01
-
--
- #define TS72XX_OPTIONS2_PHYS_BASE 0x22800000
- #define TS72XX_OPTIONS2_VIRT_BASE 0xfebfd000
- #define TS72XX_OPTIONS2_SIZE 0x00001000
--
- #define TS72XX_OPTIONS2_TS9420 0x04
- #define TS72XX_OPTIONS2_TS9420_BOOT 0x02
-
--
- #define TS72XX_RTC_INDEX_VIRT_BASE 0xfebf9000
- #define TS72XX_RTC_INDEX_PHYS_BASE 0x10800000
- #define TS72XX_RTC_INDEX_SIZE 0x00001000
-@@ -49,32 +54,146 @@
- #define TS72XX_WDT_CONTROL_PHYS_BASE 0x23800000
- #define TS72XX_WDT_FEED_PHYS_BASE 0x23c00000
-
-+#define TS72XX_PLD_VERSION_VIRT_BASE 0xfebf7000
-+#define TS72XX_PLD_VERSION_PHYS_BASE 0x23400000
-+#define TS72XX_PLD_VERSION_SIZE 0x00001000
-+
-+#define TS72XX_JUMPERS_MAX197_PHYS_BASE 0x10800000 // jumpers/max197 busy bit/COM1 dcd register (8-bit, read only)
-+#define TS72XX_MAX197_SAMPLE_PHYS_BASE 0x10f00000 // max197 sample/control register (16-bit read/8-bit write)
-+
-+/*
-+ * RS485 option
-+ */
-+#define TS72XX_RS485_CONTROL_VIRT_BASE 0xfebf6000
-+#define TS72XX_RS485_CONTROL_PHYS_BASE 0x22c00000
-+#define TS72XX_RS485_CONTROL_SIZE 0x00001000
-+
-+#define TS72XX_RS485_MODE_VIRT_BASE 0xfebf5000
-+#define TS72XX_RS485_MODE_PHYS_BASE 0x23000000
-+#define TS72XX_RS485_MODE_SIZE 0x00001000
-+
-+#define TS72XX_RS485_AUTO485FD 1
-+#define TS72XX_RS485_AUTO485HD 2
-+#define TS72XX_RS485_MODE_RS232 0x00
-+#define TS72XX_RS485_MODE_FD 0x01
-+#define TS72XX_RS485_MODE_9600_HD 0x04
-+#define TS72XX_RS485_MODE_19200_HD 0x05
-+#define TS72XX_RS485_MODE_57600_HD 0x06
-+#define TS72XX_RS485_MODE_115200_HD 0x07
-+
-+/*
-+ * PC/104 8-bit & 16-bit bus
-+ *
-+ * virt phys size
-+ * febf0000 11e00000 4K PC/104 8-bit I/O
-+ * febef000 21e00000 4K PC/104 16-bit I/O
-+ * fea00000 11a00000 1MB PC/104 8-bit memory
-+ * fe900000 21a00000 1MB PC/104 16-bit memory
-+ */
-+#define TS72XX_PC104_8BIT_IO_VIRT_BASE 0xfebf0000
-+#define TS72XX_PC104_8BIT_IO_PHYS_BASE 0x11e00000
-+#define TS72XX_PC104_8BIT_IO_SIZE 0x00001000
-+#define TS72XX_PC104_8BIT_MEM_VIRT_BASE 0xfea00000
-+#define TS72XX_PC104_8BIT_MEM_PHYS_BASE 0x11a00000
-+#define TS72XX_PC104_8BIT_MEM_SIZE 0x00100000
-+
-+#define TS72XX_PC104_16BIT_IO_VIRT_BASE 0xfebef000
-+#define TS72XX_PC104_16BIT_IO_PHYS_BASE 0x21e00000
-+#define TS72XX_PC104_16BIT_IO_SIZE 0x00001000
-+#define TS72XX_PC104_16BIT_MEM_VIRT_BASE 0xfe900000
-+#define TS72XX_PC104_16BIT_MEM_PHYS_BASE 0x21a00000
-+#define TS72XX_PC104_16BIT_MEM_SIZE 0x00100000
-+
-+/*
-+ * TS7200 specific : CompactFlash memory map
-+ *
-+ * phys size description
-+ * 11000000 7 CF registers (8-bit each), starting at 11000001
-+ * 10400006 2 CF aux registers (8-bit)
-+ * 21000000 2 CF data register (16-bit)
-+ */
-+#define TS7200_CF_CMD_PHYS_BASE 0x11000000
-+#define TS7200_CF_AUX_PHYS_BASE 0x10400006
-+#define TS7200_CF_DATA_PHYS_BASE 0x21000000
-+
-+/*
-+ * TS7260 specific : SD card & Power Management
-+ *
-+ * phys size description
-+ * 12000000 4K Power management register (8-bit)
-+ * 13000000 4K SD card registers (4 x 8-bit)
-+ */
-+#define TS7260_POWER_MANAGEMENT_PHYS_BASE 0x12000000
-+#define TS7260_PM_RS232_LEVEL_CONVERTER 0x01
-+#define TS7260_PM_USB 0x02
-+#define TS7260_PM_LCD 0x04
-+#define TS7260_PM_5V_SWITCHER 0x08
-+#define TS7260_PM_PC104_CLOCK 0x10
-+#define TS7260_PM_PC104_FAST_STROBES 0x20
-+#define TS7260_PM_TTL_UART_ENABLE 0x40
-+#define TS7260_PM_SCRATCH_BIT 0x80
-+
-+#define TS7260_SDCARD_PHYS_BASE 0x13000000
-+
- #ifndef __ASSEMBLY__
-
- static inline int board_is_ts7200(void)
- {
-- return __raw_readb(TS72XX_MODEL_VIRT_BASE) == TS72XX_MODEL_TS7200;
-+ return (__raw_readb(TS72XX_MODEL_VIRT_BASE) &
-+ TS7XXX_MODEL_MASK) == TS7XXX_MODEL_TS7200;
- }
-
- static inline int board_is_ts7250(void)
- {
-- return __raw_readb(TS72XX_MODEL_VIRT_BASE) == TS72XX_MODEL_TS7250;
-+ return (__raw_readb(TS72XX_MODEL_VIRT_BASE) &
-+ TS7XXX_MODEL_MASK) == TS7XXX_MODEL_TS7250;
- }
-
- static inline int board_is_ts7260(void)
- {
-- return __raw_readb(TS72XX_MODEL_VIRT_BASE) == TS72XX_MODEL_TS7260;
-+ return (__raw_readb(TS72XX_MODEL_VIRT_BASE) &
-+ TS7XXX_MODEL_MASK) == TS7XXX_MODEL_TS7260;
-+}
-+
-+static inline int board_is_ts7300(void)
-+{
-+ return (__raw_readb(TS72XX_MODEL_VIRT_BASE) &
-+ TS7XXX_MODEL_MASK) == TS7XXX_MODEL_TS7300;
-+}
-+
-+static inline int board_is_ts7400(void)
-+{
-+ return (__raw_readb(TS72XX_MODEL_VIRT_BASE) &
-+ TS7XXX_MODEL_MASK) == TS7XXX_MODEL_TS7400;
- }
-
- static inline int is_max197_installed(void)
- {
- return !!(__raw_readb(TS72XX_OPTIONS_VIRT_BASE) &
-- TS72XX_OPTIONS_MAX197);
-+ TS72XX_OPTIONS_MAX197);
- }
-
- static inline int is_ts9420_installed(void)
- {
- return !!(__raw_readb(TS72XX_OPTIONS2_VIRT_BASE) &
-- TS72XX_OPTIONS2_TS9420);
-+ TS72XX_OPTIONS2_TS9420);
- }
-+
-+static inline int is_rs485_installed(void)
-+{
-+ return !!(__raw_readb(TS72XX_OPTIONS_VIRT_BASE) &
-+ TS72XX_OPTIONS_COM2_RS485);
-+}
-+
-+static inline int get_ts72xx_pld_version(void)
-+{
-+ return (__raw_readb(TS72XX_PLD_VERSION_VIRT_BASE) & 0x7);
-+}
-+
-+/* User jumper */
-+static inline int is_jp6_set(void)
-+{
-+ return (__raw_readb(TS72XX_OPTIONS2_VIRT_BASE) & 0x1);
-+}
-+
- #endif
-diff --git a/arch/arm/mach-ep93xx/ts72xx.c b/arch/arm/mach-ep93xx/ts72xx.c
-index 93aeab8..345ce18 100644
---- a/arch/arm/mach-ep93xx/ts72xx.c
-+++ b/arch/arm/mach-ep93xx/ts72xx.c
-@@ -54,7 +54,36 @@ static struct map_desc ts72xx_io_desc[] __initdata = {
- .pfn = __phys_to_pfn(TS72XX_RTC_DATA_PHYS_BASE),
- .length = TS72XX_RTC_DATA_SIZE,
- .type = MT_DEVICE,
-- }
-+ },
-+ /* Use this for debug only. Each device will map its own PC/104 address space */
-+ ///* PC/104 (8-bit) I/O bus */
-+ //{
-+ // .virtual = TS72XX_PC104_8BIT_IO_VIRT_BASE,
-+ // .pfn = __phys_to_pfn(TS72XX_PC104_8BIT_IO_PHYS_BASE),
-+ // .length = TS72XX_PC104_8BIT_IO_SIZE,
-+ // .type = MT_DEVICE,
-+ //},
-+ ///* PC/104 (16-bit) I/O bus */
-+ //{
-+ // .virtual = TS72XX_PC104_16BIT_IO_VIRT_BASE,
-+ // .pfn = __phys_to_pfn(TS72XX_PC104_16BIT_IO_PHYS_BASE),
-+ // .length = TS72XX_PC104_16BIT_IO_SIZE,
-+ // .type = MT_DEVICE,
-+ //},
-+ ///* PC/104 (8-bit) MEM bus */
-+ //{
-+ // .virtual = TS72XX_PC104_8BIT_MEM_VIRT_BASE,
-+ // .pfn = __phys_to_pfn(TS72XX_PC104_8BIT_MEM_PHYS_BASE),
-+ // .length = TS72XX_PC104_8BIT_MEM_SIZE,
-+ // .type = MT_DEVICE,
-+ //},
-+ ///* PC/104 (16-bit) MEM bus */
-+ //{
-+ // .virtual = TS72XX_PC104_16BIT_MEM_VIRT_BASE,
-+ // .pfn = __phys_to_pfn(TS72XX_PC104_16BIT_MEM_PHYS_BASE),
-+ // .length = TS72XX_PC104_16BIT_MEM_SIZE,
-+ // .type = MT_DEVICE,
-+ //}
- };
-
- static void __init ts72xx_map_io(void)
-@@ -194,7 +223,9 @@ static void __init ts72xx_register_flash(void)
- }
- }
-
--
-+/*************************************************************************
-+ * RTC
-+ *************************************************************************/
- static unsigned char ts72xx_rtc_readbyte(unsigned long addr)
- {
- __raw_writeb(addr, TS72XX_RTC_INDEX_VIRT_BASE);
-@@ -242,6 +273,9 @@ static struct platform_device ts72xx_wdt_device = {
- };
-
- static struct ep93xx_eth_data __initdata ts72xx_eth_data = {
-+/*************************************************************************
-+ * Ethernet
-+ *************************************************************************/
- .phy_id = 1,
- };
-
-@@ -253,6 +287,9 @@ static void __init ts72xx_init_machine(void)
- platform_device_register(&ts72xx_wdt_device);
-
- ep93xx_register_eth(&ts72xx_eth_data, 1);
-+
-+ /* PWM1 is DIO_6 on TS-72xx header */
-+ ep93xx_register_pwm(0, 1);
- }
-
- MACHINE_START(TS72XX, "Technologic Systems TS-72xx SBC")
-diff --git a/arch/arm/mm/proc-arm920.S b/arch/arm/mm/proc-arm920.S
-index 86f80aa..11ea759 100644
---- a/arch/arm/mm/proc-arm920.S
-+++ b/arch/arm/mm/proc-arm920.S
-@@ -190,7 +190,7 @@ ENTRY(arm920_coherent_kern_range)
- */
- ENTRY(arm920_coherent_user_range)
- bic r0, r0, #CACHE_DLINESIZE - 1
--1: mcr p15, 0, r0, c7, c10, 1 @ clean D entry
-+1: mcr p15, 0, r0, c7, c14, 1 @ clean+invalidate D entry
- mcr p15, 0, r0, c7, c5, 1 @ invalidate I entry
- add r0, r0, #CACHE_DLINESIZE
- cmp r0, r1
-@@ -390,6 +390,9 @@ __arm920_setup:
- mrc p15, 0, r0, c1, c0 @ get control register v4
- bic r0, r0, r5
- orr r0, r0, r6
-+#ifdef CONFIG_CR1_NFBIT
-+ orr r0, r0, #0x40000000 @ set nF
-+#endif
- mov pc, lr
- .size __arm920_setup, . - __arm920_setup
-
-diff --git a/scripts/Makefile.fwinst b/scripts/Makefile.fwinst
-index 6bf8e87..fb20532 100644
---- a/scripts/Makefile.fwinst
-+++ b/scripts/Makefile.fwinst
-@@ -37,7 +37,7 @@ install-all-dirs: $(installed-fw-dirs)
- @true
-
- quiet_cmd_install = INSTALL $(subst $(srctree)/,,$@)
-- cmd_install = $(INSTALL) -m0644 $< $@
-+ cmd_install = $(INSTALL) -m 0644 $< $@
-
- $(installed-fw-dirs):
- $(call cmd,mkdir)
---
-1.7.0.4
-
diff --git a/recipes/linux/linux-2.6.36/ts72xx/0002-ts72xx_force_machine-id.patch b/recipes/linux/linux-2.6.36/ts72xx/0002-ts72xx_force_machine-id.patch
deleted file mode 100644
index 4b90ec6..0000000
--- a/recipes/linux/linux-2.6.36/ts72xx/0002-ts72xx_force_machine-id.patch
+++ /dev/null
@@ -1,49 +0,0 @@
-From 841896f3124d3493f5bb1b98370a1d5fcdcaedb4 Mon Sep 17 00:00:00 2001
-From: Matthieu Crapet <mcrapet@gmail.com>
-Date: Thu, 10 Jun 2010 10:51:39 +0200
-Subject: [PATCH 02/24] ts72xx_force_machine-id
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-Signed-off-by: Petr Štetiar <ynezz@true.cz>
----
- arch/arm/kernel/head.S | 3 +++
- arch/arm/mach-ep93xx/Kconfig | 7 +++++++
- 2 files changed, 10 insertions(+), 0 deletions(-)
-
-diff --git a/arch/arm/kernel/head.S b/arch/arm/kernel/head.S
-index eb62bf9..543eccf 100644
---- a/arch/arm/kernel/head.S
-+++ b/arch/arm/kernel/head.S
-@@ -82,6 +82,9 @@ ENTRY(stext)
- bl __lookup_processor_type @ r5=procinfo r9=cpuid
- movs r10, r5 @ invalid processor (r5=0)?
- beq __error_p @ yes, error 'p'
-+#ifdef CONFIG_MACH_TS72XX_FORCE_MACHINEID
-+ ldr r1, =0x2a1
-+#endif
- bl __lookup_machine_type @ r5=machinfo
- movs r8, r5 @ invalid machine (r5=0)?
- beq __error_a @ yes, error 'a'
-diff --git a/arch/arm/mach-ep93xx/Kconfig b/arch/arm/mach-ep93xx/Kconfig
-index b6be37e..bd463a0 100644
---- a/arch/arm/mach-ep93xx/Kconfig
-+++ b/arch/arm/mach-ep93xx/Kconfig
-@@ -205,6 +205,13 @@ config EP93XX_EARLY_UART3
-
- endchoice
-
-+config MACH_TS72XX_FORCE_MACHINEID
-+ bool "Force Machine ID"
-+ depends on MACH_TS72XX
-+ help
-+ Say 'Y' here to force Machine ID to 0x2A1 (MACH_TYPE_TS72XX legacy value)
-+ In early days Technologic Systems fixed the 0x163 value in redboot.
-+
- endmenu
-
- endif
---
-1.7.0.4
-
diff --git a/recipes/linux/linux-2.6.36/ts72xx/0003-ep93xx_cpuinfo.patch b/recipes/linux/linux-2.6.36/ts72xx/0003-ep93xx_cpuinfo.patch
deleted file mode 100644
index 61a9c18..0000000
--- a/recipes/linux/linux-2.6.36/ts72xx/0003-ep93xx_cpuinfo.patch
+++ /dev/null
@@ -1,36 +0,0 @@
-From 31727a8a72dc85dc4dc0eeeb27f7f9313c74914b Mon Sep 17 00:00:00 2001
-From: Matthieu Crapet <mcrapet@gmail.com>
-Date: Thu, 10 Jun 2010 10:59:31 +0200
-Subject: [PATCH 03/24] ep93xx_cpuinfo
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-Signed-off-by: Petr Štetiar <ynezz@true.cz>
----
- arch/arm/kernel/setup.c | 9 +++++++++
- 1 files changed, 9 insertions(+), 0 deletions(-)
-
-diff --git a/arch/arm/kernel/setup.c b/arch/arm/kernel/setup.c
-index d5231ae..a47ad88 100644
---- a/arch/arm/kernel/setup.c
-+++ b/arch/arm/kernel/setup.c
-@@ -953,6 +953,15 @@ static int c_show(struct seq_file *m, void *v)
- seq_puts(m, "\n");
-
- seq_printf(m, "Hardware\t: %s\n", machine_name);
-+
-+ #if defined(CONFIG_ARCH_EP93XX)
-+ #include <mach/io.h>
-+ #include <mach/ep93xx-regs.h>
-+ system_rev = *((unsigned int *)EP93XX_SYSCON_CHIPID) >> 28;
-+ system_serial_low = *((unsigned int *)EP93XX_SECURITY_UNIQID);
-+ system_serial_high = 0;
-+ #endif
-+
- seq_printf(m, "Revision\t: %04x\n", system_rev);
- seq_printf(m, "Serial\t\t: %08x%08x\n",
- system_serial_high, system_serial_low);
---
-1.7.0.4
-
diff --git a/recipes/linux/linux-2.6.36/ts72xx/0004-ep93xx_eth.patch b/recipes/linux/linux-2.6.36/ts72xx/0004-ep93xx_eth.patch
deleted file mode 100644
index 734fb93..0000000
--- a/recipes/linux/linux-2.6.36/ts72xx/0004-ep93xx_eth.patch
+++ /dev/null
@@ -1,555 +0,0 @@
-From 802fa6d7ec0d57684912b39f0fb0341698cda4e3 Mon Sep 17 00:00:00 2001
-From: Matthieu Crapet <mcrapet@gmail.com>
-Date: Thu, 10 Jun 2010 13:34:14 +0200
-Subject: [PATCH 04/24] ep93xx_eth
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-Signed-off-by: Petr Štetiar <ynezz@true.cz>
----
- drivers/net/arm/Kconfig | 1 +
- drivers/net/arm/ep93xx_eth.c | 346 ++++++++++++++++++++++++++++++++++--------
- 2 files changed, 280 insertions(+), 67 deletions(-)
-
-diff --git a/drivers/net/arm/Kconfig b/drivers/net/arm/Kconfig
-index 39e1c0d..55c0dd4 100644
---- a/drivers/net/arm/Kconfig
-+++ b/drivers/net/arm/Kconfig
-@@ -52,6 +52,7 @@ config EP93XX_ETH
- tristate "EP93xx Ethernet support"
- depends on ARM && ARCH_EP93XX
- select MII
-+ select PHYLIB
- help
- This is a driver for the ethernet hardware included in EP93xx CPUs.
- Say Y if you are building a kernel for EP93xx based devices.
-diff --git a/drivers/net/arm/ep93xx_eth.c b/drivers/net/arm/ep93xx_eth.c
-index 4a5ec94..7e60c4d 100644
---- a/drivers/net/arm/ep93xx_eth.c
-+++ b/drivers/net/arm/ep93xx_eth.c
-@@ -2,6 +2,7 @@
- * EP93xx ethernet network device driver
- * Copyright (C) 2006 Lennert Buytenhek <buytenh@wantstofly.org>
- * Dedicated to Marija Kulikova.
-+ * Copyright (C) 2007 Herbert Valerio Riedel <hvr@gnu.org>
- *
- * 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
-@@ -16,6 +17,7 @@
- #include <linux/kernel.h>
- #include <linux/netdevice.h>
- #include <linux/mii.h>
-+#include <linux/phy.h>
- #include <linux/etherdevice.h>
- #include <linux/ethtool.h>
- #include <linux/init.h>
-@@ -27,8 +29,8 @@
-
- #include <mach/hardware.h>
-
--#define DRV_MODULE_NAME "ep93xx-eth"
--#define DRV_MODULE_VERSION "0.1"
-+#define DRV_NAME "ep93xx-eth"
-+#define DRV_VERSION "0.13"
-
- #define RX_QUEUE_ENTRIES 64
- #define TX_QUEUE_ENTRIES 8
-@@ -40,6 +42,8 @@
- #define REG_RXCTL_DEFAULT 0x00073800
- #define REG_TXCTL 0x0004
- #define REG_TXCTL_ENABLE 0x00000001
-+#define REG_TESTCTL 0x0008
-+#define REG_TESTCTL_MFDX 0x00000040
- #define REG_MIICMD 0x0010
- #define REG_MIICMD_READ 0x00008000
- #define REG_MIICMD_WRITE 0x00004000
-@@ -48,6 +52,9 @@
- #define REG_MIISTS_BUSY 0x00000001
- #define REG_SELFCTL 0x0020
- #define REG_SELFCTL_RESET 0x00000001
-+#define REG_SELFCTL_MDCDIV_MSK 0x00007e00
-+#define REG_SELFCTL_MDCDIV_OFS 9
-+#define REG_SELFCTL_PSPRS 0x00000100
- #define REG_INTEN 0x0024
- #define REG_INTEN_TX 0x00000008
- #define REG_INTEN_RX 0x00000007
-@@ -177,8 +184,14 @@ struct ep93xx_priv
-
- struct net_device_stats stats;
-
-- struct mii_if_info mii;
- u8 mdc_divisor;
-+ int phy_supports_mfps:1;
-+
-+ struct mii_bus mii_bus;
-+ struct phy_device *phy_dev;
-+ int speed;
-+ int duplex;
-+ int link;
- };
-
- #define rdb(ep, off) __raw_readb((ep)->base_addr + (off))
-@@ -188,46 +201,78 @@ struct ep93xx_priv
- #define wrw(ep, off, val) __raw_writew((val), (ep)->base_addr + (off))
- #define wrl(ep, off, val) __raw_writel((val), (ep)->base_addr + (off))
-
--static int ep93xx_mdio_read(struct net_device *dev, int phy_id, int reg)
-+/* common MII transactions should take < 100 iterations */
-+#define EP93XX_PHY_TIMEOUT 2000
-+
-+static int ep93xx_mdio_wait(struct mii_bus *bus)
- {
-- struct ep93xx_priv *ep = netdev_priv(dev);
-- int data;
-- int i;
-+ struct ep93xx_priv *ep = bus->priv;
-+ unsigned int timeout = EP93XX_PHY_TIMEOUT;
-
-- wrl(ep, REG_MIICMD, REG_MIICMD_READ | (phy_id << 5) | reg);
-+ while ((rdl(ep, REG_MIISTS) & REG_MIISTS_BUSY)
-+ && timeout--)
-+ cpu_relax();
-
-- for (i = 0; i < 10; i++) {
-- if ((rdl(ep, REG_MIISTS) & REG_MIISTS_BUSY) == 0)
-- break;
-- msleep(1);
-+ if (timeout <= 0) {
-+ dev_err(&bus->dev, "MII operation timed out\n");
-+ return -ETIMEDOUT;
- }
-
-- if (i == 10) {
-- pr_info("mdio read timed out\n");
-- data = 0xffff;
-- } else {
-- data = rdl(ep, REG_MIIDATA);
-- }
-+ return 0;
-+}
-+
-+static int ep93xx_mdio_read(struct mii_bus *bus, int mii_id, int reg)
-+{
-+ struct ep93xx_priv *ep = bus->priv;
-+ u32 selfctl;
-+ u32 data;
-+
-+ if (ep93xx_mdio_wait(bus) < 0)
-+ return -ETIMEDOUT;
-+
-+ selfctl = rdl(ep, REG_SELFCTL);
-
-- return data;
-+ if (ep->phy_supports_mfps)
-+ wrl(ep, REG_SELFCTL, selfctl | REG_SELFCTL_PSPRS);
-+ else
-+ wrl(ep, REG_SELFCTL, selfctl & ~REG_SELFCTL_PSPRS);
-+
-+ wrl(ep, REG_MIICMD, REG_MIICMD_READ | (mii_id << 5) | reg);
-+
-+ if (ep93xx_mdio_wait(bus) < 0)
-+ return -ETIMEDOUT;
-+
-+ data = rdl(ep, REG_MIIDATA);
-+
-+ wrl(ep, REG_SELFCTL, selfctl);
-+
-+ return data;
- }
-
--static void ep93xx_mdio_write(struct net_device *dev, int phy_id, int reg, int data)
-+static int ep93xx_mdio_write(struct mii_bus *bus, int mii_id, int reg, u16 data)
- {
-- struct ep93xx_priv *ep = netdev_priv(dev);
-- int i;
-+ struct ep93xx_priv *ep = bus->priv;
-+ u32 selfctl;
-+
-+ if (ep93xx_mdio_wait(bus) < 0)
-+ return -ETIMEDOUT;
-+
-+ selfctl = rdl(ep, REG_SELFCTL);
-+
-+ if (ep->phy_supports_mfps)
-+ wrl(ep, REG_SELFCTL, selfctl | REG_SELFCTL_PSPRS);
-+ else
-+ wrl(ep, REG_SELFCTL, selfctl & ~REG_SELFCTL_PSPRS);
-
- wrl(ep, REG_MIIDATA, data);
-- wrl(ep, REG_MIICMD, REG_MIICMD_WRITE | (phy_id << 5) | reg);
-+ wrl(ep, REG_MIICMD, REG_MIICMD_WRITE | (mii_id << 5) | reg);
-
-- for (i = 0; i < 10; i++) {
-- if ((rdl(ep, REG_MIISTS) & REG_MIISTS_BUSY) == 0)
-- break;
-- msleep(1);
-- }
-+ if (ep93xx_mdio_wait(bus) < 0)
-+ return -ETIMEDOUT;
-
-- if (i == 10)
-- pr_info("mdio write timed out\n");
-+ wrl(ep, REG_SELFCTL, selfctl);
-+
-+ return 0;
- }
-
- static struct net_device_stats *ep93xx_get_stats(struct net_device *dev)
-@@ -557,6 +602,22 @@ err:
- return 1;
- }
-
-+static int ep93xx_mdio_reset(struct mii_bus *bus)
-+{
-+ struct ep93xx_priv *ep = bus->priv;
-+
-+ u32 selfctl = rdl(ep, REG_SELFCTL);
-+
-+ selfctl &= ~(REG_SELFCTL_MDCDIV_MSK | REG_SELFCTL_PSPRS);
-+
-+ selfctl |= (ep->mdc_divisor - 1) << REG_SELFCTL_MDCDIV_OFS;
-+ selfctl |= REG_SELFCTL_PSPRS;
-+
-+ wrl(ep, REG_SELFCTL, selfctl);
-+
-+ return 0;
-+}
-+
- static int ep93xx_start_hw(struct net_device *dev)
- {
- struct ep93xx_priv *ep = netdev_priv(dev);
-@@ -575,11 +636,8 @@ static int ep93xx_start_hw(struct net_device *dev)
- return 1;
- }
-
-- wrl(ep, REG_SELFCTL, ((ep->mdc_divisor - 1) << 9));
--
-- /* Does the PHY support preamble suppress? */
-- if ((ep93xx_mdio_read(dev, ep->mii.phy_id, MII_BMSR) & 0x0040) != 0)
-- wrl(ep, REG_SELFCTL, ((ep->mdc_divisor - 1) << 9) | (1 << 8));
-+ /* The reset cleared REG_SELFCTL, so set the MDC divisor again */
-+ ep93xx_mdio_reset(&ep->mii_bus);
-
- /* Receive descriptor ring. */
- addr = ep->descs_dma_addr + offsetof(struct ep93xx_descs, rdesc);
-@@ -688,6 +746,8 @@ static int ep93xx_open(struct net_device *dev)
-
- wrl(ep, REG_GIINTMSK, REG_GIINTMSK_ENABLE);
-
-+ phy_start(ep->phy_dev);
-+
- netif_start_queue(dev);
-
- return 0;
-@@ -700,6 +760,9 @@ static int ep93xx_close(struct net_device *dev)
- napi_disable(&ep->napi);
- netif_stop_queue(dev);
-
-+ if (ep->phy_dev)
-+ phy_stop(ep->phy_dev);
-+
- wrl(ep, REG_GIINTMSK, 0);
- free_irq(ep->irq, dev);
- ep93xx_stop_hw(dev);
-@@ -711,47 +774,44 @@ static int ep93xx_close(struct net_device *dev)
- static int ep93xx_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
- {
- struct ep93xx_priv *ep = netdev_priv(dev);
-- struct mii_ioctl_data *data = if_mii(ifr);
-
-- return generic_mii_ioctl(&ep->mii, data, cmd, NULL);
-+ return phy_mii_ioctl(ep->phy_dev, ifr, cmd);
- }
-
- static void ep93xx_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
- {
-- strcpy(info->driver, DRV_MODULE_NAME);
-- strcpy(info->version, DRV_MODULE_VERSION);
-+ strlcpy(info->driver, DRV_NAME, sizeof(info->driver));
-+ strlcpy(info->version, DRV_VERSION, sizeof(info->version));
-+ strlcpy(info->bus_info, dev_name(dev->dev.parent), sizeof(info->bus_info));
- }
-
- static int ep93xx_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
- {
- struct ep93xx_priv *ep = netdev_priv(dev);
-- return mii_ethtool_gset(&ep->mii, cmd);
-+ struct phy_device *phydev = ep->phy_dev;
-+
-+ if (!phydev)
-+ return -ENODEV;
-+
-+ return phy_ethtool_gset(phydev, cmd);
- }
-
- static int ep93xx_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
- {
- struct ep93xx_priv *ep = netdev_priv(dev);
-- return mii_ethtool_sset(&ep->mii, cmd);
--}
-+ struct phy_device *phydev = ep->phy_dev;
-
--static int ep93xx_nway_reset(struct net_device *dev)
--{
-- struct ep93xx_priv *ep = netdev_priv(dev);
-- return mii_nway_restart(&ep->mii);
--}
-+ if (!phydev)
-+ return -ENODEV;
-
--static u32 ep93xx_get_link(struct net_device *dev)
--{
-- struct ep93xx_priv *ep = netdev_priv(dev);
-- return mii_link_ok(&ep->mii);
-+ return phy_ethtool_sset(phydev, cmd);
- }
-
- static const struct ethtool_ops ep93xx_ethtool_ops = {
- .get_drvinfo = ep93xx_get_drvinfo,
- .get_settings = ep93xx_get_settings,
- .set_settings = ep93xx_set_settings,
-- .nway_reset = ep93xx_nway_reset,
-- .get_link = ep93xx_get_link,
-+ .get_link = ethtool_op_get_link,
- };
-
- static const struct net_device_ops ep93xx_netdev_ops = {
-@@ -813,6 +873,113 @@ static int ep93xx_eth_remove(struct platform_device *pdev)
- return 0;
- }
-
-+static void ep93xx_adjust_link(struct net_device *dev)
-+{
-+ struct ep93xx_priv *ep = netdev_priv(dev);
-+ struct phy_device *phydev = ep->phy_dev;
-+
-+ int status_change = 0;
-+
-+ if (phydev->link) {
-+ if ((ep->speed != phydev->speed) ||
-+ (ep->duplex != phydev->duplex)) {
-+ /* speed and/or duplex state changed */
-+ u32 testctl = rdl(ep, REG_TESTCTL);
-+
-+ if (DUPLEX_FULL == phydev->duplex)
-+ testctl |= REG_TESTCTL_MFDX;
-+ else
-+ testctl &= ~(REG_TESTCTL_MFDX);
-+
-+ wrl(ep, REG_TESTCTL, testctl);
-+
-+ ep->speed = phydev->speed;
-+ ep->duplex = phydev->duplex;
-+ status_change = 1;
-+ }
-+ }
-+
-+ /* test for online/offline link transition */
-+ if (phydev->link != ep->link) {
-+ if (phydev->link) /* link went online */
-+ netif_tx_schedule_all(dev);
-+ else { /* link went offline */
-+ ep->speed = 0;
-+ ep->duplex = -1;
-+ }
-+ ep->link = phydev->link;
-+
-+ status_change = 1;
-+ }
-+
-+ if (status_change)
-+ phy_print_status(phydev);
-+}
-+
-+static int ep93xx_mii_probe(struct net_device *dev, int phy_addr)
-+{
-+ struct ep93xx_priv *ep = netdev_priv(dev);
-+ struct phy_device *phydev = NULL;
-+ int val;
-+
-+ if (phy_addr >= 0 && phy_addr < PHY_MAX_ADDR)
-+ phydev = ep->mii_bus.phy_map[phy_addr];
-+
-+ if (!phydev) {
-+ pr_info("PHY not found at specified address,"
-+ " trying autodetection\n");
-+
-+ /* find the first phy */
-+ for (phy_addr = 0; phy_addr < PHY_MAX_ADDR; phy_addr++) {
-+ if (ep->mii_bus.phy_map[phy_addr]) {
-+ phydev = ep->mii_bus.phy_map[phy_addr];
-+ break;
-+ }
-+ }
-+ }
-+
-+ if (!phydev) {
-+ pr_err("no PHY found\n");
-+ return -ENODEV;
-+ }
-+
-+ phydev = phy_connect(dev, dev_name(&phydev->dev),
-+ ep93xx_adjust_link, 0, PHY_INTERFACE_MODE_MII);
-+
-+ if (IS_ERR(phydev)) {
-+ pr_err("Could not attach to PHY\n");
-+ return PTR_ERR(phydev);
-+ }
-+
-+ ep->phy_supports_mfps = 0;
-+
-+ val = phy_read(phydev, MII_BMSR);
-+ if (val < 0) {
-+ pr_err("failed to read MII register\n");
-+ return val;
-+ }
-+
-+ if (val & 0x0040) {
-+ pr_info("PHY supports MII frame preamble suppression\n");
-+ ep->phy_supports_mfps = 1;
-+ }
-+
-+ phydev->supported &= PHY_BASIC_FEATURES;
-+
-+ phydev->advertising = phydev->supported;
-+
-+ ep->link = 0;
-+ ep->speed = 0;
-+ ep->duplex = -1;
-+ ep->phy_dev = phydev;
-+
-+ pr_info("attached PHY driver [%s] "
-+ "(mii_bus:phy_addr=%s, irq=%d)\n",
-+ phydev->drv->name, dev_name(&phydev->dev), phydev->irq);
-+
-+ return 0;
-+}
-+
- static int ep93xx_eth_probe(struct platform_device *pdev)
- {
- struct ep93xx_eth_data *data;
-@@ -820,7 +987,7 @@ static int ep93xx_eth_probe(struct platform_device *pdev)
- struct ep93xx_priv *ep;
- struct resource *mem;
- int irq;
-- int err;
-+ int err, i;
-
- if (pdev == NULL)
- return -ENODEV;
-@@ -847,24 +1014,43 @@ static int ep93xx_eth_probe(struct platform_device *pdev)
- if (ep->res == NULL) {
- dev_err(&pdev->dev, "Could not reserve memory region\n");
- err = -ENOMEM;
-- goto err_out;
-+ goto err_out_request_mem_region;
- }
-
- ep->base_addr = ioremap(mem->start, resource_size(mem));
- if (ep->base_addr == NULL) {
- dev_err(&pdev->dev, "Failed to ioremap ethernet registers\n");
- err = -EIO;
-- goto err_out;
-+ goto err_out_ioremap;
- }
- ep->irq = irq;
-
-- ep->mii.phy_id = data->phy_id;
-- ep->mii.phy_id_mask = 0x1f;
-- ep->mii.reg_num_mask = 0x1f;
-- ep->mii.dev = dev;
-- ep->mii.mdio_read = ep93xx_mdio_read;
-- ep->mii.mdio_write = ep93xx_mdio_write;
-+ /* mdio/mii bus */
-+ ep->mii_bus.state = MDIOBUS_ALLOCATED; /* see mdiobus_alloc */
-+ ep->mii_bus.name = "ep93xx_mii_bus";
-+ snprintf(ep->mii_bus.id, MII_BUS_ID_SIZE, "0");
-+
-+ ep->mii_bus.read = ep93xx_mdio_read;
-+ ep->mii_bus.write = ep93xx_mdio_write;
-+ ep->mii_bus.reset = ep93xx_mdio_reset;
-+
-+ ep->mii_bus.phy_mask = 0;
-+
-+ ep->mii_bus.priv = ep;
-+ ep->mii_bus.dev = dev->dev;
-+
-+ ep->mii_bus.irq = kmalloc(sizeof(int)*PHY_MAX_ADDR, GFP_KERNEL);
-+ if (NULL == ep->mii_bus.irq) {
-+ dev_err(&pdev->dev, "Could not allocate memory\n");
-+ err = -ENOMEM;
-+ goto err_out_mii_bus_irq_kmalloc;
-+ }
-+
-+ for (i = 0; i < PHY_MAX_ADDR; i++)
-+ ep->mii_bus.irq[i] = PHY_POLL;
-+
- ep->mdc_divisor = 40; /* Max HCLK 100 MHz, min MDIO clk 2.5 MHz. */
-+ ep->phy_supports_mfps = 0; /* probe without preamble suppression */
-
- if (is_zero_ether_addr(dev->dev_addr))
- random_ether_addr(dev->dev_addr);
-@@ -872,14 +1058,39 @@ static int ep93xx_eth_probe(struct platform_device *pdev)
- err = register_netdev(dev);
- if (err) {
- dev_err(&pdev->dev, "Failed to register netdev\n");
-- goto err_out;
-+ goto err_out_register_netdev;
-+ }
-+
-+ err = mdiobus_register(&ep->mii_bus);
-+ if (err) {
-+ dev_err(&dev->dev, "Could not register MII bus\n");
-+ goto err_out_mdiobus_register;
-+ }
-+
-+ err = ep93xx_mii_probe(dev, data->phy_id);
-+ if (err) {
-+ dev_err(&dev->dev, "failed to probe MII bus\n");
-+ goto err_out_mii_probe;
- }
-
-- printk(KERN_INFO "%s: ep93xx on-chip ethernet, IRQ %d, %pM\n",
-- dev->name, ep->irq, dev->dev_addr);
-+ dev_info(&dev->dev, "ep93xx on-chip ethernet, IRQ %d, %pM\n",
-+ ep->irq, dev->dev_addr);
-
- return 0;
-
-+err_out_mii_probe:
-+ mdiobus_unregister(&ep->mii_bus);
-+err_out_mdiobus_register:
-+ unregister_netdev(dev);
-+err_out_register_netdev:
-+ kfree(ep->mii_bus.irq);
-+err_out_mii_bus_irq_kmalloc:
-+ iounmap(ep->base_addr);
-+err_out_ioremap:
-+ release_resource(ep->res);
-+ kfree(ep->res);
-+err_out_request_mem_region:
-+ free_netdev(dev);
- err_out:
- ep93xx_eth_remove(pdev);
- return err;
-@@ -897,7 +1108,6 @@ static struct platform_driver ep93xx_eth_driver = {
-
- static int __init ep93xx_eth_init_module(void)
- {
-- printk(KERN_INFO DRV_MODULE_NAME " version " DRV_MODULE_VERSION " loading\n");
- return platform_driver_register(&ep93xx_eth_driver);
- }
-
-@@ -908,5 +1118,7 @@ static void __exit ep93xx_eth_cleanup_module(void)
-
- module_init(ep93xx_eth_init_module);
- module_exit(ep93xx_eth_cleanup_module);
-+
- MODULE_LICENSE("GPL");
--MODULE_ALIAS("platform:ep93xx-eth");
-+MODULE_DESCRIPTION("EP93XX Ethernet driver");
-+MODULE_ALIAS("platform:" DRV_NAME);
---
-1.7.0.4
-
diff --git a/recipes/linux/linux-2.6.36/ts72xx/0005-ep93xx-m2m-DMA-support.patch b/recipes/linux/linux-2.6.36/ts72xx/0005-ep93xx-m2m-DMA-support.patch
deleted file mode 100644
index 0a81782..0000000
--- a/recipes/linux/linux-2.6.36/ts72xx/0005-ep93xx-m2m-DMA-support.patch
+++ /dev/null
@@ -1,886 +0,0 @@
-From 619f5711bc905176dc23de3e646686bee36f1601 Mon Sep 17 00:00:00 2001
-From: Matthieu Crapet <mcrapet@gmail.com>
-Date: Thu, 10 Jun 2010 16:40:16 +0200
-Subject: [PATCH 05/24] ep93xx: m2m DMA support
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-Signed-off-by: Petr Štetiar <ynezz@true.cz>
----
- arch/arm/mach-ep93xx/Makefile | 2 +-
- arch/arm/mach-ep93xx/dma-m2m.c | 753 +++++++++++++++++++++++++++++++
- arch/arm/mach-ep93xx/include/mach/dma.h | 65 +++
- 3 files changed, 819 insertions(+), 1 deletions(-)
- create mode 100644 arch/arm/mach-ep93xx/dma-m2m.c
-
-diff --git a/arch/arm/mach-ep93xx/Makefile b/arch/arm/mach-ep93xx/Makefile
-index 33ee2c8..ea652c2 100644
---- a/arch/arm/mach-ep93xx/Makefile
-+++ b/arch/arm/mach-ep93xx/Makefile
-@@ -1,7 +1,7 @@
- #
- # Makefile for the linux kernel.
- #
--obj-y := core.o clock.o dma-m2p.o gpio.o
-+obj-y := core.o clock.o dma-m2p.o dma-m2m.o gpio.o
- obj-m :=
- obj-n :=
- obj- :=
-diff --git a/arch/arm/mach-ep93xx/dma-m2m.c b/arch/arm/mach-ep93xx/dma-m2m.c
-new file mode 100644
-index 0000000..8b0d720
---- /dev/null
-+++ b/arch/arm/mach-ep93xx/dma-m2m.c
-@@ -0,0 +1,753 @@
-+/*
-+ * arch/arm/mach-ep93xx/dma-m2m.c
-+ * M2M DMA handling for Cirrus EP93xx chips.
-+ * Copyright (C) 2007 Metasoft <prylowski@xxxxxxxxxxx>
-+ *
-+ * Based on dma-m2p.c by:
-+ * Copyright (C) 2006 Lennert Buytenhek <buytenh@xxxxxxxxxxxxxx>
-+ * Copyright (C) 2006 Applied Data Systems
-+ *
-+ * 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.
-+ */
-+
-+#define pr_fmt(fmt) "ep93xx " KBUILD_MODNAME ": " fmt
-+
-+#include <linux/kernel.h>
-+#include <linux/clk.h>
-+#include <linux/err.h>
-+#include <linux/interrupt.h>
-+#include <linux/module.h>
-+#include <linux/string.h>
-+#include <linux/io.h>
-+
-+#include <mach/dma.h>
-+#include <mach/hardware.h>
-+
-+/* TEMP */
-+#define DPRINTK(fmt, args...)
-+
-+#define M2M_CONTROL 0x00
-+#define M2M_INTERRUPT 0x04
-+#define M2M_STATUS 0x0c
-+#define M2M_BCR0 0x10
-+#define M2M_BCR1 0x14
-+#define M2M_SAR_BASE0 0x18
-+#define M2M_SAR_BASE1 0x1c
-+#define M2M_SAR_CURR0 0x24
-+#define M2M_SAR_CURR1 0x28
-+#define M2M_DAR_BASE0 0x2c
-+#define M2M_DAR_BASE1 0x30
-+#define M2M_DAR_CURR0 0x34
-+#define M2M_DAR_CURR1 0x3c
-+
-+
-+/* control register bits */
-+#define CTRL_STALL_INT_EN 0x00000001 /* stall interrupt enable */
-+#define CTRL_SCT 0x00000002 /* source copy transfer
-+ (1 elem. from source fills
-+ destination block */
-+#define CTRL_DONE_INT_EN 0x00000004 /* done interrupt enable */
-+#define CTRL_ENABLE 0x00000008 /* channel enable / disable,
-+ should be set after
-+ write to SAR/DAR/BCR
-+ registers */
-+#define CTRL_NFB_INT_EN 0x00200000 /* nfb (next frame buffer)
-+ interrupt enable */
-+
-+
-+#define CTRL_START 0x00000010 /* software triggered
-+ dma start, not used
-+ for M2P/P2M/IDE/SSP */
-+#define CTRL_BWC_MASK 0x000001e0 /* bandwidth control (number
-+ of bytes in a block
-+ transfer, only M2M */
-+#define CTRL_BWC_SHIFT 5
-+
-+#define BWC_FULL 0x0 /* full bandwidth utilized */
-+#define BWC_16 0x1 /* 16 bytes per block */
-+#define BWC_32 0x5
-+#define BWC_64 0x6
-+#define BWC_128 0x7
-+#define BWC_256 0x8
-+#define BWC_512 0x9
-+#define BWC_1024 0xa
-+#define BWC_2048 0xb
-+#define BWC_4096 0xc
-+#define BWC_8192 0xd
-+#define BWC_16384 0xe
-+#define BWC_32768 0xf
-+
-+#define CTRL_PW_MASK 0x00000600 /* peripheral width,
-+ only M2P/P2M */
-+#define CTRL_PW_SHIFT 9
-+
-+#define PW_BYTE 0x0 /* one byte width */
-+#define PW_HALFWORD 0x1 /* 16 bits */
-+#define PW_WORD 0x2 /* 32 bits */
-+#define PW_NOT_USED 0x3
-+
-+#define CTRL_DAH 0x00000800 /* destination address
-+ hold, for M2P */
-+#define CTRL_SAH 0x00001000 /* source address
-+ hold, for P2M */
-+#define CTRL_TM_MASK 0x00006000 /* transfer mode */
-+#define CTRL_TM_SHIFT 13
-+
-+#define TM_M2M 0x0 /* software initiated M2M transfer */
-+#define TM_M2P 0x1 /* memory to ext. peripheral
-+ or IDE/SSP */
-+#define TM_P2M 0x2 /* ext. peripheral or IDE/SSP
-+ to memory */
-+#define TM_NOT_USED 0x3
-+
-+#define CTRL_ETDP_MASK 0x00018000 /* end of transfer/terminal
-+ count pin direction
-+ & polarity */
-+#define CTRL_ETDP_SHIFT 15
-+
-+#define ETDP_ACT_LOW_EOT 0x0 /* pin programmed as active
-+ * low end-of-transfer input */
-+#define ETDP_ACT_HIGH_EOT 0x1 /* active high eot input */
-+#define ETDP_ACT_LOW_TC 0x2 /* active low terminal count output */
-+#define ETDP_ACT_HIGH_TC 0x3 /* active high tc output */
-+
-+#define CTRL_DACKP 0x00020000 /* dma acknowledge pin
-+ polarity */
-+#define CTRL_DREQP_MASK 0x00180000 /* dma request pin polarity */
-+#define CTRL_DREQP_SHIFT 19
-+
-+#define DREQP_ACT_LOW_LEVEL 0x0 /* DREQ is active low, level
-+ sensitive */
-+#define DREQP_ACT_HIGH_LEVEL 0x1 /* active high, level sensitive */
-+#define DREQP_ACT_LOW_EDGE 0x2 /* active low, edge sensitive */
-+#define DREQP_ACT_HIGH_EDGE 0x3 /* active high, edge sensitive */
-+
-+
-+#define CTRL_RSS_MASK 0x00c00000 /* request source selection */
-+#define CTRL_RSS_SHIFT 22
-+
-+#define RSS_EXT 0x0 /* external dma request */
-+#define RSS_SSP_RX 0x1 /* internal SSPRx */
-+#define RSS_SSP_TX 0x2 /* internal SSPTx */
-+#define RSS_IDE 0x3 /* internal IDE */
-+
-+#define CTRL_NO_HDSK 0x01000000 /* no handshake, required for
-+ SSP/IDE, optional for
-+ ext. M2P/P2M */
-+
-+/* interrupt register bits */
-+#define INTR_STALL 0x1
-+#define INTR_DONE 0x2
-+#define INTR_NFB 0x4
-+#define INTR_ALL 0x7
-+
-+/* status register bits */
-+#define STAT_STALL 0x0001 /* waiting for software start
-+ or device request */
-+#define STAT_CTL_STATE_MASK 0x000e /* control fsm state */
-+#define STAT_CTL_STATE_SHIFT 1
-+
-+#define CTL_STATE_IDLE 0x0
-+#define CTL_STATE_STALL 0x1
-+#define CTL_STATE_MEM_RD 0x2
-+#define CTL_STATE_MEM_WR 0x3
-+#define CTL_STATE_BWC_WAIT 0x4
-+
-+#define STAT_BUF_STATE_MASK 0x0030 /* buffer fsm state */
-+#define STAT_BUF_STATE_SHIFT 4
-+
-+#define BUF_STATE_NO_BUF 0x0
-+#define BUF_STATE_BUF_ON 0x1
-+#define BUF_STATE_BUF_NEXT 0x2
-+
-+#define STAT_DONE 0x0040 /* transfer completed successfully
-+ (by device or BCR is 0) */
-+
-+#define STAT_TCS_MASK 0x0018 /* terminal count status */
-+#define STAT_TCS_SHIFT 7
-+
-+#define TCS_NONE 0x0 /* terminal count not reached
-+ for buffer0 and buffer1 */
-+#define TCS_BUF0 0x1 /* terminal count reached
-+ for buffer0 */
-+#define TCS_BUF1 0x2
-+#define TCS_BOTH 0x3 /* terminal count reached
-+ for both buffers */
-+
-+#define STAT_EOTS_MASK 0x0060 /* end of transfer status */
-+#define STAT_EOTS_SHIFT 9
-+
-+#define EOTS_NONE 0x0 /* end of transfer has not been
-+ requested by ext. periph. for
-++ any buffer */
-+#define EOTS_BUF0 0x1 /* eot requested for buffer0 */
-+#define EOTS_BUF1 0x2
-+#define EOTS_BOTH 0x3 /* eot requested for both buffers */
-+
-+#define STAT_NFB 0x0800 /* next frame buffer interrupt */
-+#define STAT_NB 0x1000 /* next buffer status, inform which
-+ buffer is free for update */
-+#define STAT_DREQS 0x2000 /* status of dma request signal from
-+ ext. periph or IDE/SSP request */
-+
-+/* IDE/SSP support */
-+#define IDE_UDMA_DATAOUT 0x20
-+#define IDE_UDMA_DATAIN 0x24
-+
-+#ifndef SSPDR
-+#define SSPDR 0x08
-+#endif
-+
-+struct m2m_channel {
-+ char *name;
-+ void __iomem *base;
-+ int irq;
-+
-+ struct clk *clk;
-+ spinlock_t lock;
-+
-+ void *client;
-+ unsigned next_slot:1;
-+ struct ep93xx_dma_buffer *buffer_xfer;
-+ struct ep93xx_dma_buffer *buffer_next;
-+ struct list_head buffers_pending;
-+};
-+
-+static struct m2m_channel m2m_rxtx[] = {
-+ {"m2m0", EP93XX_DMA_BASE + 0x0100, IRQ_EP93XX_DMAM2M0},
-+ {"m2m1", EP93XX_DMA_BASE + 0x0140, IRQ_EP93XX_DMAM2M1},
-+ {NULL},
-+};
-+
-+
-+static void feed_buf(struct m2m_channel *ch, struct ep93xx_dma_buffer *buf)
-+{
-+ struct ep93xx_dma_m2m_client *cl = ch->client;
-+ u32 src_addr, dst_addr;
-+
-+ if ((cl->flags & EP93XX_DMA_M2M_DIR_MASK) == EP93XX_DMA_M2M_TX) {
-+ src_addr = buf->bus_addr;
-+ switch (cl->flags & EP93XX_DMA_M2M_DEV_MASK) {
-+ case EP93XX_DMA_M2M_DEV_IDE:
-+ dst_addr = EP93XX_IDE_PHYS_BASE + IDE_UDMA_DATAOUT;
-+ break;
-+ case EP93XX_DMA_M2M_DEV_SSP:
-+ dst_addr = EP93XX_SPI_PHYS_BASE + SSPDR;
-+ break;
-+ default:
-+ dst_addr = buf->bus_addr2;
-+ break;
-+ }
-+ } else {
-+ switch (cl->flags & EP93XX_DMA_M2M_DEV_MASK) {
-+ case EP93XX_DMA_M2M_DEV_IDE:
-+ src_addr = EP93XX_IDE_PHYS_BASE + IDE_UDMA_DATAIN;
-+ break;
-+ case EP93XX_DMA_M2M_DEV_SSP:
-+ src_addr = EP93XX_SPI_PHYS_BASE + SSPDR;
-+ break;
-+ default:
-+ src_addr = buf->bus_addr2;
-+ break;
-+ }
-+ dst_addr = buf->bus_addr;
-+ }
-+
-+ if (ch->next_slot == 0) {
-+ DPRINTK("Writing src_addr: %08x\n", src_addr);
-+ DPRINTK("Writing dest_addr: %08x\n", dst_addr);
-+ DPRINTK("Writing size: %08x\n", buf->size);
-+ writel(src_addr, ch->base + M2M_SAR_BASE0);
-+ writel(dst_addr, ch->base + M2M_DAR_BASE0);
-+ writel(buf->size, ch->base + M2M_BCR0);
-+ } else {
-+ writel(src_addr, ch->base + M2M_SAR_BASE1);
-+ writel(dst_addr, ch->base + M2M_DAR_BASE1);
-+ writel(buf->size, ch->base + M2M_BCR1);
-+ }
-+ ch->next_slot ^= 1;
-+ DPRINTK("data size = %d, slot %d\n", buf->size, ch->next_slot ^ 1);
-+}
-+
-+static void choose_buffer_xfer(struct m2m_channel *ch)
-+{
-+ struct ep93xx_dma_buffer *buf;
-+
-+ ch->buffer_xfer = NULL;
-+ if (!list_empty(&ch->buffers_pending)) {
-+ buf = list_entry(ch->buffers_pending.next,
-+ struct ep93xx_dma_buffer, list);
-+ list_del(&buf->list);
-+ feed_buf(ch, buf);
-+ ch->buffer_xfer = buf;
-+ }
-+}
-+
-+static void choose_buffer_next(struct m2m_channel *ch)
-+{
-+ struct ep93xx_dma_buffer *buf;
-+
-+ ch->buffer_next = NULL;
-+ if (!list_empty(&ch->buffers_pending)) {
-+ buf = list_entry(ch->buffers_pending.next,
-+ struct ep93xx_dma_buffer, list);
-+ list_del(&buf->list);
-+ feed_buf(ch, buf);
-+ ch->buffer_next = buf;
-+ }
-+}
-+
-+static irqreturn_t m2m_irq(int irq, void *dev_id)
-+{
-+ struct m2m_channel *ch = dev_id;
-+ struct ep93xx_dma_m2m_client *cl;
-+ u32 irq_status, dma_state, buf_state, ctl_state;
-+
-+ spin_lock(&ch->lock);
-+ irq_status = readl(ch->base + M2M_INTERRUPT);
-+ /*if ((irq_status & INTR_ALL) == 0) {
-+ spin_unlock(&ch->lock);
-+ return IRQ_NONE;
-+ }*/
-+ dma_state = readl(ch->base + M2M_STATUS);
-+ cl = ch->client;
-+
-+ //printk("intr status: %08x, dma state: %08x\n", irq_status, dma_state);
-+
-+ DPRINTK("intr status %d, dma state %x\n",
-+ irq_status, dma_state);
-+
-+ buf_state = (dma_state & STAT_BUF_STATE_MASK) >> STAT_BUF_STATE_SHIFT;
-+ ctl_state = (dma_state & STAT_CTL_STATE_MASK) >> STAT_CTL_STATE_SHIFT;
-+ /*printk("STAT_CTL_STATE: %d, STAT_BUF_STATE: %d\n",
-+ * ctl_state, buf_state);*/
-+ if (ctl_state == CTL_STATE_STALL &&
-+ buf_state == BUF_STATE_NO_BUF &&
-+ dma_state & STAT_DONE) {
-+ /* transfer completed successfully (done) */
-+
-+
-+ /* send client the done command */
-+ if (cl->buffer_finished) {
-+ cl->buffer_finished(cl->cookie, ch->buffer_xfer, ch->buffer_xfer->size, 0);
-+ }
-+
-+ writel(0, ch->base + M2M_INTERRUPT);
-+ choose_buffer_xfer(ch);
-+ choose_buffer_next(ch);
-+ if (ch->buffer_xfer != NULL) {
-+ /* retrigger if more buffers exist */
-+ if ((cl->flags & EP93XX_DMA_M2M_DEV_MASK) ==
-+ EP93XX_DMA_M2M_DEV_MEM) {
-+ DPRINTK("Writing start1 to M2M control\n");
-+ writel(readl(ch->base + M2M_CONTROL) |
-+ CTRL_START, ch->base + M2M_CONTROL);
-+ readl(ch->base + M2M_CONTROL);
-+ }
-+ } else {
-+ DPRINTK("DISABLING DMA: dreqs state: %d\n", dma_state & STAT_DREQS);
-+
-+ writel(readl(ch->base + M2M_CONTROL)
-+ & ~CTRL_ENABLE, ch->base + M2M_CONTROL);
-+ readl(ch->base + M2M_CONTROL);
-+ }
-+ } else if (ctl_state == CTL_STATE_MEM_RD &&
-+ buf_state == BUF_STATE_BUF_ON &&
-+ dma_state & STAT_NFB) {
-+ /* next frame buffer */
-+ if (cl->buffer_finished) {
-+ cl->buffer_finished(cl->cookie, ch->buffer_xfer, 0, 0);
-+ }
-+ ch->buffer_xfer = ch->buffer_next;
-+ choose_buffer_next(ch);
-+ }
-+
-+ if (cl->buffer_started && ch->buffer_xfer != NULL) {
-+ cl->buffer_started(cl->cookie, ch->buffer_xfer);
-+ }
-+
-+ spin_unlock(&ch->lock);
-+ return IRQ_HANDLED;
-+}
-+
-+static struct m2m_channel *find_free_channel(struct ep93xx_dma_m2m_client *cl, int channel_spec)
-+{
-+ struct m2m_channel *ch = m2m_rxtx;
-+ int i;
-+
-+#if 0
-+ /* BMS: This code isn't particularly clear; look like it asserts
-+ * that a requested channel must not share the same data direction
-+ * as a previously requested channel - which makes sense for the SSP,
-+ * but not at all for direct hardware transferrs
-+ */
-+ for (i = 0; ch[i].base; i++) {
-+ struct ep93xx_dma_m2m_client *cl2;
-+
-+ cl2 = ch[i].client;
-+ if (cl2 != NULL) {
-+ int port;
-+
-+ /* two the same devices in the same direction
-+ are not allowed
-+ (two "memory devices" should be allowed) */
-+ port = cl2->flags & (EP93XX_DMA_M2M_DEV_MASK |
-+ EP93XX_DMA_M2M_DIR_MASK);
-+ if (port == (cl->flags & (EP93XX_DMA_M2M_DEV_MASK |
-+ EP93XX_DMA_M2M_DIR_MASK)))
-+ return NULL;
-+ }
-+ }
-+#endif
-+
-+ if (channel_spec == EP93XX_DMA_M2M_REQUIRES_CH_ANY) {
-+ for (i = 0; ch[i].base; i++) {
-+ if (ch[i].client == NULL)
-+ return ch + i;
-+ }
-+ } else if (channel_spec == EP93XX_DMA_M2M_REQUIRES_CH_0) {
-+ if (ch[0].client == NULL) {
-+ return &(ch[0]);
-+ }
-+ } else if (channel_spec == EP93XX_DMA_M2M_REQUIRES_CH_1) {
-+ if (ch[1].client == NULL) {
-+ return &(ch[1]);
-+ }
-+ } else {
-+ printk(KERN_ERR "ep93xx-m2m dma channel request: unknown channel spec\n");
-+ }
-+ return NULL;
-+}
-+
-+static u32 set_direction_reg(u32 outv, u32 flags)
-+{
-+ switch (flags & EP93XX_DMA_M2M_DEV_MASK) {
-+ case EP93XX_DMA_M2M_DEV_EXT:
-+ outv &= ~(CTRL_SAH | CTRL_DAH | CTRL_TM_MASK);
-+
-+ if (flags & EP93XX_DMA_M2M_EXT_FIFO)
-+ outv |= (flags & EP93XX_DMA_M2M_DIR_MASK) ==
-+ EP93XX_DMA_M2M_TX ? CTRL_DAH : CTRL_SAH;
-+
-+ outv |= (((flags & EP93XX_DMA_M2M_DIR_MASK) ==
-+ EP93XX_DMA_M2M_TX) ? TM_M2P : TM_P2M) <<
-+ CTRL_TM_SHIFT;
-+
-+ break;
-+ case EP93XX_DMA_M2M_DEV_IDE:
-+ outv &= ~(CTRL_SAH | CTRL_DAH | CTRL_TM_MASK | CTRL_PWSC_MASK);
-+ if ((flags & EP93XX_DMA_M2M_DIR_MASK) == EP93XX_DMA_M2M_TX) {
-+ outv |= (2 << CTRL_PWSC_SHIFT) & CTRL_PWSC_MASK;
-+ outv |= CTRL_DAH;
-+ outv |= TM_M2P << CTRL_TM_SHIFT;
-+ } else {
-+ outv |= (1 << CTRL_PWSC_SHIFT) & CTRL_PWSC_MASK;
-+ outv |= CTRL_SAH;
-+ outv |= TM_P2M << CTRL_TM_SHIFT;
-+ }
-+ break;
-+ case EP93XX_DMA_M2M_DEV_SSP:
-+ outv &= ~(CTRL_SAH | CTRL_DAH | CTRL_TM_MASK | CTRL_RSS_MASK);
-+ if ((flags & EP93XX_DMA_M2M_DIR_MASK) == EP93XX_DMA_M2M_TX) {
-+ outv |= TM_M2P << CTRL_TM_SHIFT;
-+ outv |= CTRL_DAH;
-+ outv |= RSS_SSP_TX << CTRL_RSS_SHIFT;
-+ } else {
-+ outv |= TM_P2M << CTRL_TM_SHIFT;
-+ outv |= CTRL_SAH;
-+ outv |= RSS_SSP_RX << CTRL_RSS_SHIFT;
-+ }
-+ break;
-+ case EP93XX_DMA_M2M_DEV_MEM:
-+ break;
-+ }
-+ return outv;
-+}
-+
-+static void channel_enable(struct m2m_channel *ch)
-+{
-+ struct ep93xx_dma_m2m_client *cl = ch->client;
-+ u32 outv = 0;
-+
-+ clk_enable(ch->clk);
-+
-+ /* set peripheral wait state mask - IFF specified in control word */
-+ outv |= (cl->flags & CTRL_PWSC_MASK);
-+ outv |= (cl->flags & EP93XX_DREQ_MASK);
-+
-+ DPRINTK("Set outv to: %08x\n",outv);
-+
-+ switch (cl->flags & EP93XX_DMA_M2M_DEV_MASK) {
-+ case EP93XX_DMA_M2M_DEV_EXT:
-+ switch (cl->flags & EP93XX_DMA_M2M_EXT_WIDTH_MASK) {
-+ case EP93XX_DMA_M2M_EXT_WIDTH_BYTE:
-+ outv |= PW_BYTE << CTRL_PW_SHIFT;
-+ break;
-+ case EP93XX_DMA_M2M_EXT_WIDTH_2BYTES:
-+ outv |= PW_HALFWORD << CTRL_PW_SHIFT;
-+ break;
-+ case EP93XX_DMA_M2M_EXT_WIDTH_4BYTES:
-+ outv |= PW_WORD << CTRL_PW_SHIFT;
-+ break;
-+ }
-+ /* if NO_HDSK then PWSC, if not, then DREQ, DACK, TC/DEOT */
-+ if (cl->flags & EP93XX_DMA_M2M_EXT_NO_HDSK) {
-+ outv |= CTRL_NO_HDSK;
-+ /* TODO: wait states */
-+ } else {
-+ /* TODO: regular handshaking */
-+ }
-+ outv |= RSS_EXT << CTRL_RSS_SHIFT;
-+ break;
-+ case EP93XX_DMA_M2M_DEV_IDE:
-+ /* NO_HDSK, PWSC, PW, SAH, DAH */
-+ outv |= CTRL_NO_HDSK;
-+ outv |= PW_WORD << CTRL_PW_SHIFT;
-+ /* PWSC = 1 for read, PWSC = 2 for write in UDMA */
-+ outv |= RSS_IDE << CTRL_RSS_SHIFT;
-+ break;
-+ case EP93XX_DMA_M2M_DEV_SSP:
-+ outv |= CTRL_NO_HDSK;
-+ outv |= PW_HALFWORD << CTRL_PW_SHIFT;
-+ outv |= (8 << CTRL_PWSC_SHIFT) & CTRL_PWSC_MASK;
-+ break;
-+ case EP93XX_DMA_M2M_DEV_MEM:
-+ switch (cl->flags & EP93XX_DMA_M2M_MEM_SPEED_MASK) {
-+ case EP93XX_DMA_M2M_MEM_SPEED_FULL:
-+ outv |= BWC_FULL << CTRL_BWC_SHIFT;
-+ break;
-+ case EP93XX_DMA_M2M_MEM_SPEED_HALF:
-+ outv |= BWC_32768 << CTRL_BWC_SHIFT;
-+ break;
-+ case EP93XX_DMA_M2M_MEM_SPEED_QUART:
-+ outv |= BWC_16384 << CTRL_BWC_SHIFT;
-+ break;
-+ case EP93XX_DMA_M2M_MEM_SPEED_SLOW:
-+ outv |= BWC_16 << CTRL_BWC_SHIFT;
-+ break;
-+ }
-+ outv |= (cl->flags & EP93XX_DMA_M2M_MEM_FILL) ? CTRL_SCT : 0;
-+ outv |= TM_M2M << CTRL_TM_SHIFT;
-+ break;
-+ }
-+
-+ // debug code
-+ DPRINTK("PRE-Enable, status is: %08x\n", readl(ch->base+M2M_STATUS));
-+
-+ outv = set_direction_reg(outv, cl->flags);
-+ /* STALL interrupt must be enabled */
-+ outv |= CTRL_NFB_INT_EN | CTRL_DONE_INT_EN | CTRL_STALL_INT_EN;
-+
-+ writel(outv, ch->base + M2M_CONTROL);
-+ outv = readl(ch->base + M2M_CONTROL);
-+ DPRINTK("channel enable, writing control reg = %08x\n", outv);
-+}
-+
-+static void channel_disable(struct m2m_channel *ch)
-+{
-+ u32 v;
-+
-+ DPRINTK("Disabling channel\n");
-+ v = readl(ch->base + M2M_CONTROL);
-+
-+ writel(v & ~(CTRL_NFB_INT_EN | CTRL_DONE_INT_EN | CTRL_STALL_INT_EN),
-+ ch->base + M2M_CONTROL);
-+
-+ v = readl(ch->base + M2M_CONTROL);
-+
-+ while (readl(ch->base + M2M_STATUS) & STAT_NFB) {
-+ cpu_relax();
-+ }
-+
-+ writel(0, ch->base + M2M_CONTROL);
-+
-+ v = readl(ch->base + M2M_CONTROL);
-+
-+ while (readl(ch->base + M2M_STATUS) & STAT_STALL) {
-+ cpu_relax();
-+ }
-+
-+ clk_disable(ch->clk);
-+}
-+
-+void ep93xx_dma_m2m_set_direction(struct ep93xx_dma_m2m_client *cl,
-+ int direction)
-+{
-+ struct m2m_channel *ch = cl->channel;
-+ u32 outv;
-+ unsigned long flags;
-+
-+ direction &= EP93XX_DMA_M2M_DIR_MASK;
-+
-+ spin_lock_irqsave(&ch->lock, flags);
-+
-+ cl->flags &= ~EP93XX_DMA_M2M_DIR_MASK;
-+ cl->flags |= direction;
-+
-+ outv = readl(ch->base + M2M_CONTROL);
-+ outv = set_direction_reg(outv, cl->flags);
-+ writel(outv, ch->base + M2M_CONTROL);
-+ outv = readl(ch->base + M2M_CONTROL);
-+ DPRINTK("set_direction: configured control reg = %08x\n", outv);
-+
-+ spin_unlock_irqrestore(&ch->lock, flags);
-+}
-+EXPORT_SYMBOL_GPL(ep93xx_dma_m2m_set_direction);
-+
-+int ep93xx_dma_m2m_client_register(struct ep93xx_dma_m2m_client *cl, int channel_spec)
-+{
-+ struct m2m_channel *ch;
-+ int err;
-+
-+ ch = find_free_channel(cl, channel_spec);
-+ if (ch == NULL)
-+ return -1;
-+
-+ err = request_irq(ch->irq, m2m_irq, IRQF_DISABLED, cl->name ? : "dma-m2m", ch);
-+ if (err)
-+ return err;
-+
-+ ch->client = cl;
-+ ch->next_slot = 0;
-+ ch->buffer_xfer = NULL;
-+ ch->buffer_next = NULL;
-+ INIT_LIST_HEAD(&ch->buffers_pending);
-+
-+ cl->channel = ch;
-+
-+ channel_enable(ch);
-+
-+ return 0;
-+}
-+EXPORT_SYMBOL_GPL(ep93xx_dma_m2m_client_register);
-+
-+void ep93xx_dma_m2m_client_unregister(struct ep93xx_dma_m2m_client *cl)
-+{
-+ struct m2m_channel *ch = cl->channel;
-+
-+ channel_disable(ch);
-+ free_irq(ch->irq, ch);
-+ ch->client = NULL;
-+}
-+EXPORT_SYMBOL_GPL(ep93xx_dma_m2m_client_unregister);
-+
-+void ep93xx_dma_m2m_submit(struct ep93xx_dma_m2m_client *cl,
-+ struct ep93xx_dma_buffer *buf)
-+{
-+ struct m2m_channel *ch = cl->channel;
-+ unsigned long flags;
-+
-+ spin_lock_irqsave(&ch->lock, flags);
-+
-+ if (ch->buffer_xfer == NULL) {
-+ ch->buffer_xfer = buf;
-+ feed_buf(ch, buf);
-+ if (readl(ch->base + M2M_CONTROL) & CTRL_ENABLE) {
-+ DPRINTK("CTRL_ENABLE\n");
-+ if ((cl->flags & EP93XX_DMA_M2M_DEV_MASK) ==
-+ EP93XX_DMA_M2M_DEV_MEM) {
-+ DPRINTK("WRITING START2 TO M2M control\n");
-+ writel(readl(ch->base + M2M_CONTROL) |
-+ CTRL_START, ch->base + M2M_CONTROL);
-+ readl(ch->base + M2M_CONTROL);
-+ }
-+ }
-+ } else if (ch->buffer_next == NULL) {
-+ ch->buffer_next = buf;
-+ feed_buf(ch, buf);
-+ } else
-+ list_add_tail(&buf->list, &ch->buffers_pending);
-+ spin_unlock_irqrestore(&ch->lock, flags);
-+}
-+EXPORT_SYMBOL_GPL(ep93xx_dma_m2m_submit);
-+
-+void ep93xx_dma_m2m_start(struct ep93xx_dma_m2m_client *cl)
-+{
-+ struct m2m_channel *ch = cl->channel;
-+ u32 v;
-+
-+ unsigned long flags;
-+
-+ spin_lock_irqsave(&ch->lock, flags);
-+
-+ writel(readl(ch->base + M2M_STATUS), ch->base+M2M_STATUS);
-+ //printk("At start, status is: %08x\n", readl(ch->base + M2M_STATUS));
-+
-+ v = readl(ch->base + M2M_CONTROL) | CTRL_ENABLE;
-+ writel(v, ch->base + M2M_CONTROL);
-+ v = readl(ch->base + M2M_CONTROL);
-+ if (ch->buffer_xfer != NULL) {
-+ if (((cl->flags & EP93XX_DMA_M2M_DEV_MASK) ==
-+ EP93XX_DMA_M2M_DEV_MEM)) {
-+ DPRINTK("WRITING START3 to M2M controller\n");
-+ v |= CTRL_START;
-+ writel(v, ch->base + M2M_CONTROL);
-+ v = readl(ch->base + M2M_CONTROL);
-+ }
-+ }
-+
-+ spin_unlock_irqrestore(&ch->lock, flags);
-+}
-+EXPORT_SYMBOL_GPL(ep93xx_dma_m2m_start);
-+
-+void ep93xx_dma_m2m_stop(struct ep93xx_dma_m2m_client *cl)
-+{
-+ struct m2m_channel *ch = cl->channel;
-+ u32 v;
-+ unsigned long flags;
-+
-+ spin_lock_irqsave(&ch->lock, flags);
-+
-+ DPRINTK("Stopping DMA by disabling CTRL_ENABLE\n");
-+ v = readl(ch->base + M2M_CONTROL) & ~CTRL_ENABLE;
-+ writel(v, ch->base + M2M_CONTROL);
-+ readl(ch->base + M2M_CONTROL);
-+ DPRINTK("configured control reg = %08x\n", v);
-+
-+ spin_unlock_irqrestore(&ch->lock, flags);
-+}
-+EXPORT_SYMBOL_GPL(ep93xx_dma_m2m_stop);
-+
-+void ep93xx_dma_m2m_flush(struct ep93xx_dma_m2m_client *cl)
-+{
-+ struct m2m_channel *ch = cl->channel;
-+
-+ channel_disable(ch);
-+ ch->next_slot = 0;
-+ ch->buffer_xfer = NULL;
-+ ch->buffer_next = NULL;
-+ INIT_LIST_HEAD(&ch->buffers_pending);
-+ channel_enable(ch);
-+}
-+EXPORT_SYMBOL_GPL(ep93xx_dma_m2m_flush);
-+
-+static int init_channel(struct m2m_channel *ch)
-+{
-+ ch->clk = clk_get(NULL, ch->name);
-+ if (IS_ERR(ch->clk))
-+ return PTR_ERR(ch->clk);
-+
-+ spin_lock_init(&ch->lock);
-+ ch->client = NULL;
-+
-+ return 0;
-+}
-+
-+static int __init ep93xx_dma_m2m_init(void)
-+{
-+ int i;
-+ int ret;
-+
-+ for (i = 0; m2m_rxtx[i].base; i++) {
-+ ret = init_channel(m2m_rxtx + i);
-+ if (ret)
-+ return ret;
-+ }
-+
-+ pr_info("M2M DMA subsystem initialized\n");
-+ return 0;
-+}
-+arch_initcall(ep93xx_dma_m2m_init);
-diff --git a/arch/arm/mach-ep93xx/include/mach/dma.h b/arch/arm/mach-ep93xx/include/mach/dma.h
-index 3a5961d..6a3552b 100644
---- a/arch/arm/mach-ep93xx/include/mach/dma.h
-+++ b/arch/arm/mach-ep93xx/include/mach/dma.h
-@@ -11,6 +11,7 @@
- struct ep93xx_dma_buffer {
- struct list_head list;
- u32 bus_addr;
-+ u32 bus_addr2; /* only used by M2M */
- u16 size;
- };
-
-@@ -28,6 +29,7 @@ struct ep93xx_dma_m2p_client {
- void *channel;
- };
-
-+/* flags (m2p client) */
- #define EP93XX_DMA_M2P_PORT_I2S1 0x00
- #define EP93XX_DMA_M2P_PORT_I2S2 0x01
- #define EP93XX_DMA_M2P_PORT_AAC1 0x02
-@@ -45,6 +47,58 @@ struct ep93xx_dma_m2p_client {
- #define EP93XX_DMA_M2P_IGNORE_ERROR 0x40
- #define EP93XX_DMA_M2P_ERROR_MASK 0x60
-
-+
-+struct ep93xx_dma_m2m_client {
-+ char *name;
-+ u32 flags;
-+ void *cookie;
-+ void (*buffer_started)(void *cookie,
-+ struct ep93xx_dma_buffer *buf);
-+ void (*buffer_finished)(void *cookie,
-+ struct ep93xx_dma_buffer *buf,
-+ int bytes, int error);
-+
-+ /* Internal to the DMA code. */
-+ void *channel;
-+};
-+
-+/* flags (m2m client) */
-+#define EP93XX_DMA_M2M_RX 0x000 /* read from periph./memory */
-+#define EP93XX_DMA_M2M_TX 0x004 /* write to periph./memory */
-+#define EP93XX_DMA_M2M_DIR_MASK 0x004 /* direction mask */
-+#define EP93XX_DMA_M2M_DEV_EXT 0x000 /* external peripheral */
-+#define EP93XX_DMA_M2M_DEV_SSP 0x001 /* internal SSP */
-+#define EP93XX_DMA_M2M_DEV_IDE 0x002 /* internal IDE */
-+#define EP93XX_DMA_M2M_DEV_MEM 0x003 /* memory to memory transfer */
-+#define EP93XX_DMA_M2M_DEV_MASK 0x003 /* device mask */
-+#define EP93XX_DMA_M2M_EXT_FIFO 0x008 /* external peripheral is one location fifo */
-+#define EP93XX_DMA_M2M_EXT_NO_HDSK 0x010 /* external peripheral doesn't require regular handshaking protocol */
-+#define EP93XX_DMA_M2M_EXT_WIDTH_MASK 0x300
-+#define EP93XX_DMA_M2M_EXT_WIDTH_BYTE 0x000 /* external peripheral transfer is one byte width */
-+#define EP93XX_DMA_M2M_EXT_WIDTH_2BYTES 0x100
-+#define EP93XX_DMA_M2M_EXT_WIDTH_4BYTES 0x200
-+#define EP93XX_DMA_M2M_MEM_SPEED_FULL 0x000 /* M2M bandwidth control */
-+#define EP93XX_DMA_M2M_MEM_SPEED_HALF 0x040 /* half bus bandwidth */
-+#define EP93XX_DMA_M2M_MEM_SPEED_QUART 0x080 /* quarter bus bandwidth */
-+#define EP93XX_DMA_M2M_MEM_SPEED_SLOW 0x0c0 /* slowest speed */
-+#define EP93XX_DMA_M2M_MEM_SPEED_MASK 0x0c0 /* memory speed mask */
-+#define EP93XX_DMA_M2M_MEM_FILL 0x020 /* M2M is one location to block fill */
-+
-+/* FIXME */
-+#define CTRL_PWSC_MASK 0xfe000000 /* peripheral wait states count */
-+#define CTRL_PWSC_SHIFT 25
-+#define EP93XX_DREQ_SHIFT 19
-+#define EP93XX_DREQ_MASK 0x00180000
-+#define EP93XX_DMA_M2M_DREQ_LS_L (00 << EP93XX_DREQ_SHIFT)
-+#define EP93XX_DMA_M2M_DREQ_LS_H (01 << EP93XX_DREQ_SHIFT)
-+#define EP93XX_DMA_M2M_DREQ_ES_L (10 << EP93XX_DREQ_SHIFT)
-+#define EP93XX_DMA_M2M_DREQ_ES_H (11 << EP93XX_DREQ_SHIFT)
-+
-+/* See ep93xx_dma_m2m_client_register (channel_spec) */
-+#define EP93XX_DMA_M2M_REQUIRES_CH_ANY 0
-+#define EP93XX_DMA_M2M_REQUIRES_CH_0 1
-+#define EP93XX_DMA_M2M_REQUIRES_CH_1 2
-+
- int ep93xx_dma_m2p_client_register(struct ep93xx_dma_m2p_client *m2p);
- void ep93xx_dma_m2p_client_unregister(struct ep93xx_dma_m2p_client *m2p);
- void ep93xx_dma_m2p_submit(struct ep93xx_dma_m2p_client *m2p,
-@@ -53,4 +107,15 @@ void ep93xx_dma_m2p_submit_recursive(struct ep93xx_dma_m2p_client *m2p,
- struct ep93xx_dma_buffer *buf);
- void ep93xx_dma_m2p_flush(struct ep93xx_dma_m2p_client *m2p);
-
-+int ep93xx_dma_m2m_client_register(struct ep93xx_dma_m2m_client *m2m,
-+ int channel_spec);
-+void ep93xx_dma_m2m_client_unregister(struct ep93xx_dma_m2m_client *m2m);
-+void ep93xx_dma_m2m_submit(struct ep93xx_dma_m2m_client *m2m,
-+ struct ep93xx_dma_buffer *buf);
-+void ep93xx_dma_m2m_flush(struct ep93xx_dma_m2m_client *m2m);
-+void ep93xx_dma_m2m_start(struct ep93xx_dma_m2m_client *m2m);
-+void ep93xx_dma_m2m_stop(struct ep93xx_dma_m2m_client *m2m);
-+void ep93xx_dma_m2m_set_direction(struct ep93xx_dma_m2m_client *m2m,
-+ int direction);
-+
- #endif /* __ASM_ARCH_DMA_H */
---
-1.7.0.4
-
diff --git a/recipes/linux/linux-2.6.36/ts72xx/0006-ts72xx_rs485.patch b/recipes/linux/linux-2.6.36/ts72xx/0006-ts72xx_rs485.patch
deleted file mode 100644
index e7ab169..0000000
--- a/recipes/linux/linux-2.6.36/ts72xx/0006-ts72xx_rs485.patch
+++ /dev/null
@@ -1,223 +0,0 @@
-From 42019ca5561ebd18d47d8811cf06d3cae77ca982 Mon Sep 17 00:00:00 2001
-From: Matthieu Crapet <mcrapet@gmail.com>
-Date: Thu, 10 Jun 2010 17:00:12 +0200
-Subject: [PATCH 06/24] ts72xx_rs485
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-Crude hack...
-
-Signed-off-by: Petr Štetiar <ynezz@true.cz>
----
- arch/arm/include/asm/ioctls.h | 3 +
- drivers/serial/Kconfig | 8 +++
- drivers/serial/amba-pl010.c | 124 ++++++++++++++++++++++++++++++++++++++++-
- 3 files changed, 134 insertions(+), 1 deletions(-)
-
-diff --git a/arch/arm/include/asm/ioctls.h b/arch/arm/include/asm/ioctls.h
-index 0b30894..a0d7401 100644
---- a/arch/arm/include/asm/ioctls.h
-+++ b/arch/arm/include/asm/ioctls.h
-@@ -74,6 +74,9 @@
- #define TIOCGICOUNT 0x545D /* read serial port inline interrupt counts */
- #define FIOQSIZE 0x545E
-
-+#define TIOC_SBCC485 0x545F /* TS72xx RTS/485 mode clear */
-+#define TIOC_SBCS485 0x5460 /* TS72xx RTS/485 mode set */
-+
- /* Used for packet mode */
- #define TIOCPKT_DATA 0
- #define TIOCPKT_FLUSHREAD 1
-diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig
-index 12900f7..d1bff25 100644
---- a/drivers/serial/Kconfig
-+++ b/drivers/serial/Kconfig
-@@ -296,6 +296,14 @@ config SERIAL_AMBA_PL010_CONSOLE
- your boot loader (lilo or loadlin) about how to pass options to the
- kernel at boot time.)
-
-+config SERIAL_AMBA_PL010_TS72XX
-+ bool "Support for RS-485 on AMBA serial port (for TS-72XX SBC)"
-+ depends on SERIAL_AMBA_PL010 != n && MACH_TS72XX
-+ help
-+ This add support for RS-485 on some Technologic System SBC.
-+
-+ If unsure, say N.
-+
- config SERIAL_AMBA_PL011
- tristate "ARM AMBA PL011 serial port support"
- depends on ARM_AMBA
-diff --git a/drivers/serial/amba-pl010.c b/drivers/serial/amba-pl010.c
-index 2904aa0..9135233 100644
---- a/drivers/serial/amba-pl010.c
-+++ b/drivers/serial/amba-pl010.c
-@@ -51,6 +51,10 @@
-
- #include <asm/io.h>
-
-+#if defined(CONFIG_SERIAL_AMBA_PL010_TS72XX)
-+#include <mach/ts72xx.h>
-+#endif
-+
- #define UART_NR 8
-
- #define SERIAL_AMBA_MAJOR 204
-@@ -65,6 +69,11 @@
- #define UART_DUMMY_RSR_RX 256
- #define UART_PORT_SIZE 64
-
-+#if defined(CONFIG_SERIAL_AMBA_PL010_TS72XX)
-+static void __iomem *ts_rs485_data9_register;
-+static void __iomem *ts_rs485_control_register;
-+#endif
-+
- /*
- * We wrap our port structure around the generic uart_port.
- */
-@@ -386,7 +395,7 @@ pl010_set_termios(struct uart_port *port, struct ktermios *termios,
- /*
- * Ask the core to calculate the divisor for us.
- */
-- baud = uart_get_baud_rate(port, termios, old, 0, uap->port.uartclk/16);
-+ baud = uart_get_baud_rate(port, termios, old, 0, uap->port.uartclk/16);
- quot = uart_get_divisor(port, baud);
-
- switch (termios->c_cflag & CSIZE) {
-@@ -529,6 +538,105 @@ static int pl010_verify_port(struct uart_port *port, struct serial_struct *ser)
- return ret;
- }
-
-+
-+#if defined(CONFIG_SERIAL_AMBA_PL010_TS72XX)
-+static int ts72xx_rs485_init(void)
-+{
-+ ts_rs485_data9_register = ioremap(TS72XX_RS485_MODE_PHYS_BASE, 4096);
-+ if (ts_rs485_data9_register == NULL) {
-+ return -1;
-+ }
-+
-+ ts_rs485_control_register = ioremap(TS72XX_RS485_CONTROL_PHYS_BASE, 4096);
-+ if (ts_rs485_control_register == NULL) {
-+ iounmap(ts_rs485_data9_register);
-+ return -1;
-+ }
-+
-+ return 0;
-+}
-+
-+static int ts72xx_auto485(struct uart_port *port, unsigned int cmd, unsigned long *arg)
-+{
-+ int baud, cflag, mode;
-+ int datalength;
-+
-+ mode = (int)*arg;
-+ if (!is_rs485_installed()) {
-+ printk("amba-pl010.c: this board does not support RS485 auto mode\n");
-+ return -EINVAL;
-+ }
-+
-+ if (port->line != 1) {
-+ printk("amba-pl010.c: auto RS485 mode is only supported on second port (/dev/ttyAM1)\n");
-+ return -EINVAL;
-+ }
-+
-+ datalength = 8;
-+ cflag = port->state->port.tty->termios->c_cflag;
-+ if (cflag & PARENB)
-+ datalength++;
-+
-+ if (cflag & CSTOPB)
-+ datalength++;
-+
-+ baud = tty_get_baud_rate(port->state->port.tty);
-+
-+ switch (cmd) {
-+ case TIOC_SBCC485:
-+ if ((mode & TS72XX_RS485_AUTO485FD) || (mode & TS72XX_RS485_AUTO485HD)) {
-+ printk("amba-pl010.c: unsetting auto RS485 mode\n");
-+ __raw_writew(TS72XX_RS485_MODE_RS232, ts_rs485_control_register);
-+ __raw_writew(TS72XX_RS485_MODE_RS232, ts_rs485_data9_register);
-+ }
-+ break;
-+ case TIOC_SBCS485:
-+ if (mode & TS72XX_RS485_AUTO485FD) {
-+ printk ("amba-pl010.c: setting FULL duplex auto RS485 mode\n");
-+ __raw_writew(TS72XX_RS485_MODE_FD, ts_rs485_control_register);
-+ if (datalength > 8)
-+ __raw_writew(TS72XX_RS485_MODE_FD, ts_rs485_data9_register);
-+ } else if (mode & TS72XX_RS485_AUTO485HD) {
-+ printk("amba-pl010.c: setting HALF DUPLEX auto RS485 mode\n");
-+ switch (baud) {
-+ case 9600:
-+ __raw_writew(TS72XX_RS485_MODE_9600_HD, ts_rs485_control_register);
-+ break;
-+ case 19200:
-+ __raw_writew(TS72XX_RS485_MODE_19200_HD, ts_rs485_control_register);
-+ break;
-+ case 57600:
-+ __raw_writew(TS72XX_RS485_MODE_57600_HD, ts_rs485_control_register);
-+ break;
-+ case 115200:
-+ __raw_writew(TS72XX_RS485_MODE_115200_HD, ts_rs485_control_register);
-+ break;
-+ default:
-+ printk("amba-pl010.c: %d baud rate is not supported for auto RS485 mode\n", baud);
-+ return -1;
-+ }
-+ if (datalength > 8)
-+ __raw_writew(TS72XX_RS485_MODE_FD, ts_rs485_data9_register);
-+ }
-+ break;
-+ }
-+
-+ return 0;
-+}
-+
-+static int pl010_ioctl(struct uart_port *port, unsigned int cmd, unsigned long arg)
-+{
-+ switch (cmd) {
-+ case TIOC_SBCC485:
-+ case TIOC_SBCS485:
-+ return ts72xx_auto485(port, cmd, (unsigned long *)arg);
-+ }
-+
-+ return -ENOIOCTLCMD;
-+}
-+#endif /* CONFIG_SERIAL_AMBA_PL010_TS72XX */
-+
-+
- static struct uart_ops amba_pl010_pops = {
- .tx_empty = pl010_tx_empty,
- .set_mctrl = pl010_set_mctrl,
-@@ -547,6 +655,9 @@ static struct uart_ops amba_pl010_pops = {
- .request_port = pl010_request_port,
- .config_port = pl010_config_port,
- .verify_port = pl010_verify_port,
-+#if defined(CONFIG_SERIAL_AMBA_PL010_TS72XX)
-+ .ioctl = pl010_ioctl,
-+#endif
- };
-
- static struct uart_amba_port *amba_ports[UART_NR];
-@@ -805,6 +916,17 @@ static int __init pl010_init(void)
- ret = uart_register_driver(&amba_reg);
- if (ret == 0) {
- ret = amba_driver_register(&pl010_driver);
-+
-+ #if defined(CONFIG_SERIAL_AMBA_PL010_TS72XX)
-+ if (!ret && is_rs485_installed()) {
-+ ret = ts72xx_rs485_init();
-+ if (ret)
-+ printk("amba-pl010.c: ts72xx_rs485_init() failed\n");
-+ else
-+ printk("amba-pl010.c: auto RS485 mode initialized\n");
-+ }
-+ #endif
-+
- if (ret)
- uart_unregister_driver(&amba_reg);
- }
---
-1.7.0.4
-
diff --git a/recipes/linux/linux-2.6.36/ts72xx/0007-ts72xx_ts_ser1.patch b/recipes/linux/linux-2.6.36/ts72xx/0007-ts72xx_ts_ser1.patch
deleted file mode 100644
index 570009b..0000000
--- a/recipes/linux/linux-2.6.36/ts72xx/0007-ts72xx_ts_ser1.patch
+++ /dev/null
@@ -1,264 +0,0 @@
-From be2d6dfb434c137187d2572d8bf9264748720ece Mon Sep 17 00:00:00 2001
-From: Matthieu Crapet <mcrapet@gmail.com>
-Date: Wed, 16 Jun 2010 14:44:44 +0200
-Subject: [PATCH 07/24] ts72xx_ts_ser1
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-TS-SER1 - Serial Port PC/104 peripheral
-
-Signed-off-by: Petr Štetiar <ynezz@true.cz>
----
- drivers/serial/8250_ts_ser1.c | 197 +++++++++++++++++++++++++++++++++++++++++
- drivers/serial/Kconfig | 17 ++++
- drivers/serial/Makefile | 1 +
- 3 files changed, 215 insertions(+), 0 deletions(-)
- create mode 100644 drivers/serial/8250_ts_ser1.c
-
-diff --git a/drivers/serial/8250_ts_ser1.c b/drivers/serial/8250_ts_ser1.c
-new file mode 100644
-index 0000000..e5fe616
---- /dev/null
-+++ b/drivers/serial/8250_ts_ser1.c
-@@ -0,0 +1,197 @@
-+/*
-+ * linux/drivers/serial/8250_ts_ser1.c
-+ * Technologic Systems TS-SER1 support.
-+ *
-+ * (c) Copyright 2006-2008 Matthieu Crapet <mcrapet@gmail.com>
-+ * Data taken from include/asm-i386/serial.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.
-+ *
-+ * Pin Number:
-+ * 1 DCD
-+ * 2 Receive data
-+ * 3 Trasmit data
-+ * 4 DTR
-+ * 5 Signal Ground
-+ * 6 DSR
-+ * 7 RTS
-+ * 8 CTS
-+ * 9 RI
-+ */
-+
-+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-+
-+#include <linux/module.h>
-+#include <linux/init.h>
-+#include <linux/serial_8250.h>
-+#include <linux/irq.h>
-+#include <linux/io.h>
-+#include <mach/hardware.h>
-+#include <mach/ts72xx.h>
-+#include <mach/gpio.h>
-+
-+#define TS72XX_SER1_IO_PHYS_BASE (TS72XX_PC104_8BIT_IO_PHYS_BASE)
-+#define TS72XX_SER1_IO_SIZE (TS72XX_PC104_8BIT_IO_SIZE)
-+
-+#define TS_SER1_PORT_COM3 0x3E8
-+#define TS_SER1_PORT_COM4 0x2E8
-+#define TS_SER1_PORT_COM5 0x3A8
-+
-+/* Value to write in 16550A scratch register */
-+#define MARKER_BYTE 0xAA /* or 0x55 */
-+
-+#define PORT(_base,_irq) \
-+{ \
-+ .iobase = _base, \
-+ .membase = (void __iomem *)0, \
-+ .irq = _irq, \
-+ .uartclk = 1843200, \
-+ .iotype = UPIO_PORT, \
-+ .flags = UPF_BOOT_AUTOCONF, \
-+}
-+/* Note: IRQ can be shared (see CONFIG_SERIAL_8250_SHARE_IRQ) */
-+
-+
-+static struct plat_serial8250_port ts72xx_ser1_data_com3[] = {
-+ PORT(TS_SER1_PORT_COM3, 0),
-+ { },
-+};
-+
-+static struct plat_serial8250_port ts72xx_ser1_data_com4[] = {
-+ PORT(TS_SER1_PORT_COM4, 0),
-+ { },
-+};
-+
-+static struct plat_serial8250_port ts72xx_ser1_data_com5[] = {
-+ PORT(TS_SER1_PORT_COM5, 0),
-+ { },
-+};
-+
-+
-+static int ts_ser1_irq = CONFIG_SERIAL_8250_TS_SER1_IRQ; // 5, 6 or 7
-+static struct platform_device *serial8250_ts_ser1_dev;
-+
-+
-+static int __init ts_ser1_init(void)
-+{
-+ struct plat_serial8250_port *comX = NULL;
-+ void __iomem *iomem;
-+
-+ int ret = -ENODEV;
-+ int n = 0; // COM number as printed on TS-SER1 pcb
-+
-+ iomem = ioremap(TS72XX_SER1_IO_PHYS_BASE, TS72XX_SER1_IO_SIZE);
-+
-+ if (iomem != NULL) {
-+ __raw_writeb(MARKER_BYTE, iomem + TS_SER1_PORT_COM3 + 7);
-+ if (__raw_readb(iomem + TS_SER1_PORT_COM3 + 7) == MARKER_BYTE) {
-+ comX = ts72xx_ser1_data_com3;
-+ n = 3;
-+ } else {
-+ __raw_writeb(MARKER_BYTE, iomem + TS_SER1_PORT_COM4 + 7);
-+ if (__raw_readb(iomem + TS_SER1_PORT_COM4 + 7) == MARKER_BYTE) {
-+ comX = ts72xx_ser1_data_com4;
-+ n = 4;
-+ } else {
-+ __raw_writeb(MARKER_BYTE, iomem + TS_SER1_PORT_COM5 + 7);
-+ if (__raw_readb(iomem + TS_SER1_PORT_COM5 + 7) == MARKER_BYTE) {
-+ comX = ts72xx_ser1_data_com5;
-+ n = 5;
-+ }
-+ }
-+ }
-+
-+ if (comX) {
-+ switch (ts_ser1_irq) {
-+ case 5:
-+ ret = gpio_request(EP93XX_GPIO_LINE_F(3), "TS-SER1");
-+ if (ret < 0) {
-+ pr_err("gpio_request failed, try another irq\n");
-+ goto init_error;
-+ }
-+ gpio_direction_input(EP93XX_GPIO_LINE_F(3));
-+ comX->irq = gpio_to_irq(EP93XX_GPIO_LINE_F(3));
-+ set_irq_type(comX->irq, IRQ_TYPE_EDGE_RISING);
-+ break;
-+ case 6:
-+ comX->irq = IRQ_EP93XX_EXT1;
-+ break;
-+ case 7:
-+ comX->irq = IRQ_EP93XX_EXT3;
-+ break;
-+ default:
-+ pr_err("wrong specified irq\n");
-+ goto init_error;
-+ }
-+
-+ comX->iobase += (unsigned long)iomem; // virtual address
-+
-+ } else {
-+ pr_err("can't detect COM number\n");
-+ goto init_error;
-+ }
-+
-+ /* create platform_device structure */
-+ serial8250_ts_ser1_dev = platform_device_alloc("serial8250", n);
-+ if (!serial8250_ts_ser1_dev) {
-+ ret = -ENOMEM;
-+ goto init_error;
-+ }
-+
-+ ret = platform_device_add_data(serial8250_ts_ser1_dev, comX,
-+ 2 * sizeof(struct plat_serial8250_port));
-+ if (ret) {
-+ platform_device_put(serial8250_ts_ser1_dev);
-+ goto init_error;
-+ }
-+
-+ ret = platform_device_add(serial8250_ts_ser1_dev);
-+ if (ret) {
-+ platform_device_put(serial8250_ts_ser1_dev);
-+ goto init_error;
-+ }
-+
-+ platform_set_drvdata(serial8250_ts_ser1_dev, iomem);
-+ return 0;
-+ }
-+
-+init_error:
-+ if (iomem) {
-+ iounmap(iomem);
-+ iomem = NULL;
-+ }
-+ return ret;
-+}
-+
-+static void __exit ts_ser1_exit(void)
-+{
-+ struct platform_device *pdev = serial8250_ts_ser1_dev;
-+ void __iomem *iomem = platform_get_drvdata(pdev);
-+
-+ serial8250_ts_ser1_dev = NULL;
-+
-+ platform_device_unregister(pdev);
-+
-+ iounmap(iomem);
-+ if (ts_ser1_irq == 5)
-+ gpio_free(EP93XX_GPIO_LINE_F(3));
-+}
-+
-+module_init(ts_ser1_init);
-+module_exit(ts_ser1_exit);
-+
-+module_param(ts_ser1_irq, int, 0);
-+MODULE_PARM_DESC(ts_ser1_irq, "TS-SER1 IRQ, default=" __MODULE_STRING(CONFIG_SERIAL_8250_TS_SER1_IRQ) ")");
-+
-+MODULE_AUTHOR("Matthieu Crapet <mcrapet@gmail.com>");
-+MODULE_DESCRIPTION("8250 serial probe module for TS-SER1 (TS-72xx)");
-+MODULE_LICENSE("GPL");
-+MODULE_VERSION("0.5");
-diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig
-index d1bff25..5667462 100644
---- a/drivers/serial/Kconfig
-+++ b/drivers/serial/Kconfig
-@@ -267,6 +267,23 @@ config SERIAL_8250_RM9K
- port hardware found on MIPS RM9122 and similar processors.
- If unsure, say N.
-
-+config SERIAL_8250_TS_SER1
-+ tristate "Support TS-SER1 (for TS-72XX SBC)"
-+ depends on SERIAL_8250 != n && MACH_TS72XX
-+ help
-+ Say Y here if you have a TS-SER1 PC/104 peripheral.
-+ COM number will be configured automaticaly.
-+
-+ To compile this driver as a module, choose M here: the module
-+ will be called 8250_ts_ser1.
-+
-+config SERIAL_8250_TS_SER1_IRQ
-+ int "Selected IRQ (5, 6 or 7)"
-+ depends on SERIAL_8250_TS_SER1
-+ default "5"
-+ help
-+ Enter jumper IRQ configuration
-+
- comment "Non-8250 serial port support"
-
- config SERIAL_AMBA_PL010
-diff --git a/drivers/serial/Makefile b/drivers/serial/Makefile
-index 1ca4fd5..e379ab4 100644
---- a/drivers/serial/Makefile
-+++ b/drivers/serial/Makefile
-@@ -28,6 +28,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_8250_TS_SER1) += 8250_ts_ser1.o
- obj-$(CONFIG_SERIAL_AMBA_PL010) += amba-pl010.o
- obj-$(CONFIG_SERIAL_AMBA_PL011) += amba-pl011.o
- obj-$(CONFIG_SERIAL_CLPS711X) += clps711x.o
---
-1.7.0.4
-
diff --git a/recipes/linux/linux-2.6.36/ts72xx/0008-ts72xx_ts_eth100.patch b/recipes/linux/linux-2.6.36/ts72xx/0008-ts72xx_ts_eth100.patch
deleted file mode 100644
index b2fb7d2..0000000
--- a/recipes/linux/linux-2.6.36/ts72xx/0008-ts72xx_ts_eth100.patch
+++ /dev/null
@@ -1,278 +0,0 @@
-From 4c63820dec1699305f30a4096a0baa550d273a87 Mon Sep 17 00:00:00 2001
-From: Matthieu Crapet <mcrapet@gmail.com>
-Date: Fri, 18 Jun 2010 17:39:09 +0200
-Subject: [PATCH 08/24] ts72xx_ts_eth100
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-TS-ETH100 - 10/100 Ethernet PC/104 peripheral
-
-Signed-off-by: Petr Štetiar <ynezz@true.cz>
----
- drivers/net/Kconfig | 10 ++
- drivers/net/Makefile | 1 +
- drivers/net/ax88796.c | 8 ++-
- drivers/net/ax88796_ts_eth100.c | 190 +++++++++++++++++++++++++++++++++++++++
- 4 files changed, 208 insertions(+), 1 deletions(-)
- create mode 100644 drivers/net/ax88796_ts_eth100.c
-
-diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
-index 5db667c..448c823 100644
---- a/drivers/net/Kconfig
-+++ b/drivers/net/Kconfig
-@@ -248,6 +248,16 @@ config AX88796_93CX6
- help
- Select this if your platform comes with an external 93CX6 eeprom.
-
-+config AX88796_TS_ETH100
-+ tristate "Support for TS-ETH100 (TS-72XX SBC)"
-+ depends on AX88796 && MACH_TS72XX
-+ help
-+ Say Y here if you have a TS-ETH100 PC/104 peripheral.
-+ IRQ numbers and I/O address will be configurated automatically.
-+
-+ To compile this driver as a module, choose M here: the module
-+ will be called ax88796_ts_eth100.
-+
- config MACE
- tristate "MACE (Power Mac ethernet) support"
- depends on PPC_PMAC && PPC32
-diff --git a/drivers/net/Makefile b/drivers/net/Makefile
-index 3e8f150..eb4765b 100644
---- a/drivers/net/Makefile
-+++ b/drivers/net/Makefile
-@@ -143,6 +143,7 @@ obj-$(CONFIG_B44) += b44.o
- obj-$(CONFIG_FORCEDETH) += forcedeth.o
- obj-$(CONFIG_NE_H8300) += ne-h8300.o 8390.o
- obj-$(CONFIG_AX88796) += ax88796.o
-+obj-$(CONFIG_AX88796_TS_ETH100) += ax88796_ts_eth100.o
- obj-$(CONFIG_BCM63XX_ENET) += bcm63xx_enet.o
-
- obj-$(CONFIG_TSI108_ETH) += tsi108_eth.o
-diff --git a/drivers/net/ax88796.c b/drivers/net/ax88796.c
-index 20e946b..33527f7 100644
---- a/drivers/net/ax88796.c
-+++ b/drivers/net/ax88796.c
-@@ -810,7 +810,9 @@ static int ax_remove(struct platform_device *_dev)
- ax = to_ax_dev(dev);
-
- unregister_netdev(dev);
-- free_irq(dev->irq, dev);
-+ if (ax->running) { // already freed in ax_close?
-+ free_irq(dev->irq, dev);
-+ }
-
- iounmap(ei_status.mem);
- release_resource(ax->mem);
-@@ -936,7 +938,11 @@ static int ax_probe(struct platform_device *pdev)
- goto exit_mem2;
- }
-
-+ #if defined(CONFIG_AX88796_TS_ETH100) || defined(CONFIG_AX88796_TS_ETH100_MODULE)
-+ ei_status.reg_offset[0x10] = ax->map2 - ei_status.mem + 0x10; /* don't know why, but +0x20 works too */
-+ #else
- ei_status.reg_offset[0x1f] = ax->map2 - ei_status.mem;
-+ #endif
- }
-
- /* got resources, now initialise and register device */
-diff --git a/drivers/net/ax88796_ts_eth100.c b/drivers/net/ax88796_ts_eth100.c
-new file mode 100644
-index 0000000..448b3e3
---- /dev/null
-+++ b/drivers/net/ax88796_ts_eth100.c
-@@ -0,0 +1,190 @@
-+/*
-+ * linux/drivers/net/ax88796_ts_eth100.c
-+ * Technologic Systems TS-ETH100 support.
-+ *
-+ * (c) Copyright 2008 Matthieu Crapet <mcrapet@gmail.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.
-+ */
-+
-+#include <linux/module.h>
-+#include <linux/init.h>
-+#include <linux/platform_device.h>
-+#include <linux/irq.h>
-+#include <linux/io.h>
-+#include <net/ax88796.h>
-+#include <mach/ts72xx.h>
-+#include <mach/gpio.h>
-+
-+#define TS72XX_ETH100_IO8_PHYS_BASE (TS72XX_PC104_8BIT_IO_PHYS_BASE)
-+#define TS72XX_ETH100_IO8_SIZE (TS72XX_PC104_8BIT_IO_SIZE)
-+#define TS72XX_ETH100_IO16_PHYS_BASE (TS72XX_PC104_16BIT_IO_PHYS_BASE)
-+#define TS72XX_ETH100_IO16_SIZE (TS72XX_PC104_16BIT_IO_SIZE)
-+
-+/* Technologic systems I/O space */
-+#define TS_ETH100_PLD_0 0x100
-+#define TS_ETH100_PLD_1 0x110
-+#define TS_ETH100_PLD_2 0x120
-+#define TS_ETH100_PLD_3 0x130
-+
-+/* NE2000 I/O space */
-+#define TS_ETH100_MAC_0 0x200
-+#define TS_ETH100_MAC_1 0x240
-+#define TS_ETH100_MAC_2 0x300
-+#define TS_ETH100_MAC_3 0x340
-+
-+/* Board identifier must be 5 ; PLD revision should be 1 */
-+#define is_eth100_present(__iomem, __offset) \
-+ (((__raw_readb(__iomem + __offset) & 0xF) == 0x5) && \
-+ ((__raw_readb(__iomem + __offset + 4) & 0xF) == 0x1))
-+
-+/* Jumpers status (SRAM control register) */
-+#define read_irq(__iomem, __offset) \
-+ (__raw_readb(__iomem + __offset + 8) & 0xE)
-+
-+
-+static u32 offsets[0x20] = {
-+ 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
-+};
-+
-+static struct ax_plat_data ts72xx_eth100_asix_data = {
-+ .flags = AXFLG_HAS_93CX6,
-+ .wordlength = 2,
-+ .dcr_val = 0x48,
-+ .rcr_val = 0x40,
-+ .reg_offsets = offsets,
-+};
-+
-+static struct resource ts72xx_eth100_resource[] = {
-+ [0] = {
-+ .start = TS72XX_ETH100_IO8_PHYS_BASE,
-+ .end = TS72XX_ETH100_IO8_PHYS_BASE + 0x40 - 1,
-+ .flags = IORESOURCE_MEM
-+ },
-+ [1] = { /* 0x10 is NE_DATAPORT is 16-bit access */
-+ .start = TS72XX_ETH100_IO16_PHYS_BASE,
-+ .end = TS72XX_ETH100_IO16_PHYS_BASE + 0x40 - 1,
-+ .flags = IORESOURCE_MEM
-+ },
-+ [2] = {
-+ .start = IRQ_EP93XX_EXT1,
-+ .end = IRQ_EP93XX_EXT1,
-+ .flags = IORESOURCE_IRQ
-+ }
-+};
-+
-+static int ts_eth100_irq; // 2 [IRQ 5], 4 [IRQ 6] or 8 [IRQ 7] (jumper configuration)
-+
-+
-+static void ts72xx_eth100_release(struct device *dev)
-+{
-+ /* nothing to do (no kfree) because we have static struct */
-+}
-+
-+static struct platform_device ts72xx_eth100_device_asix = {
-+ .name = "ax88796",
-+ .id = 0,
-+ .num_resources = ARRAY_SIZE(ts72xx_eth100_resource),
-+ .resource = ts72xx_eth100_resource,
-+ .dev = {
-+ .platform_data = &ts72xx_eth100_asix_data,
-+ .release = ts72xx_eth100_release,
-+ }
-+};
-+
-+static int __init ts_eth100_init(void)
-+{
-+ void __iomem *iomem;
-+ struct platform_device *ethX = NULL;
-+
-+ iomem = ioremap(TS72XX_ETH100_IO8_PHYS_BASE, TS72XX_ETH100_IO8_SIZE);
-+ if (iomem != NULL) {
-+ ethX = &ts72xx_eth100_device_asix;
-+
-+ if (is_eth100_present(iomem, TS_ETH100_PLD_0)) {
-+ ethX->resource[0].start += TS_ETH100_MAC_0;
-+ ethX->resource[0].end += TS_ETH100_MAC_0;
-+ ethX->resource[1].start += TS_ETH100_MAC_0;
-+ ethX->resource[1].end += TS_ETH100_MAC_0;
-+ ts_eth100_irq = read_irq(iomem, TS_ETH100_PLD_0);
-+ } else if(is_eth100_present(iomem, TS_ETH100_PLD_1)) {
-+ ethX->resource[0].start += TS_ETH100_MAC_1;
-+ ethX->resource[0].end += TS_ETH100_MAC_1;
-+ ethX->resource[1].start += TS_ETH100_MAC_1;
-+ ethX->resource[1].end += TS_ETH100_MAC_1;
-+ ts_eth100_irq = read_irq(iomem, TS_ETH100_PLD_1);
-+ } else if(is_eth100_present(iomem, TS_ETH100_PLD_2)) {
-+ ethX->resource[0].start += TS_ETH100_MAC_2;
-+ ethX->resource[0].end += TS_ETH100_MAC_2;
-+ ethX->resource[1].start += TS_ETH100_MAC_2;
-+ ethX->resource[1].end += TS_ETH100_MAC_2;
-+ ts_eth100_irq = read_irq(iomem, TS_ETH100_PLD_2);
-+ } else if(is_eth100_present(iomem, TS_ETH100_PLD_3)) {
-+ ethX->resource[0].start += TS_ETH100_MAC_3;
-+ ethX->resource[0].end += TS_ETH100_MAC_3;
-+ ethX->resource[1].start += TS_ETH100_MAC_3;
-+ ethX->resource[1].end += TS_ETH100_MAC_3;
-+ ts_eth100_irq = read_irq(iomem, TS_ETH100_PLD_3);
-+ } else {
-+ ethX = NULL;
-+ }
-+
-+ /* Translate IRQ number */
-+ if (ethX != NULL) {
-+ int ret, irq = 0;
-+ switch (ts_eth100_irq) {
-+ case 0x2: /* IRQ5 */
-+ irq = gpio_to_irq(EP93XX_GPIO_LINE_F(3));
-+ ret = gpio_request(irq, "TS-ETH100");
-+ if (ret < 0) {
-+ ethX = NULL;
-+ goto init_error;
-+ } else {
-+ gpio_direction_input(irq);
-+ set_irq_type(irq, IRQ_TYPE_EDGE_RISING);
-+ }
-+ break;
-+ case 0x4: /* IRQ6 */
-+ irq = IRQ_EP93XX_EXT1;
-+ break;
-+ case 0x8: /* IRQ7 */
-+ default:
-+ irq = IRQ_EP93XX_EXT3;
-+ }
-+ ethX->resource[2].start = irq;
-+ ethX->resource[2].end = irq;
-+ }
-+init_error:
-+ iounmap(iomem);
-+ }
-+
-+ return ((ethX == NULL) ? -ENODEV :
-+ platform_device_register(&ts72xx_eth100_device_asix));
-+}
-+
-+
-+static void __exit ts_eth100_exit(void)
-+{
-+ platform_device_unregister(&ts72xx_eth100_device_asix);
-+ if (ts_eth100_irq == 2)
-+ gpio_free(EP93XX_GPIO_LINE_F(3));
-+}
-+
-+module_init(ts_eth100_init);
-+module_exit(ts_eth100_exit);
-+
-+MODULE_AUTHOR("Matthieu Crapet <mcrapet@gmail.com>");
-+MODULE_DESCRIPTION("Asix 88796 ethernet probe module for TS-ETH100 (TS-72xx)");
-+MODULE_LICENSE("GPL");
-+MODULE_VERSION("0.21");
---
-1.7.0.4
-
diff --git a/recipes/linux/linux-2.6.36/ts72xx/0009-ts72xx_pata.patch b/recipes/linux/linux-2.6.36/ts72xx/0009-ts72xx_pata.patch
deleted file mode 100644
index fb891d0..0000000
--- a/recipes/linux/linux-2.6.36/ts72xx/0009-ts72xx_pata.patch
+++ /dev/null
@@ -1,437 +0,0 @@
-From dca6d3223e20806a2ec22704a6909d72c9ba3ef5 Mon Sep 17 00:00:00 2001
-From: =?UTF-8?q?Petr=20=C5=A0tetiar?= <ynezz@true.cz>
-Date: Sat, 23 Oct 2010 19:08:37 +0200
-Subject: [PATCH 09/24] ts72xx_pata
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-Support:
-TS-7200 - Compact flash
-TS-9600 - IDE interface PC/104 peripheral
-
-Signed-off-by: Petr Štetiar <ynezz@true.cz>
----
- drivers/ata/Kconfig | 20 +++++
- drivers/ata/Makefile | 3 +
- drivers/ata/pata_ts7200_cf.c | 92 ++++++++++++++++++++++++
- drivers/ata/pata_ts72xx.c | 161 ++++++++++++++++++++++++++++++++++++++++++
- drivers/ata/pata_ts9600.c | 95 +++++++++++++++++++++++++
- 5 files changed, 371 insertions(+), 0 deletions(-)
- create mode 100644 drivers/ata/pata_ts7200_cf.c
- create mode 100644 drivers/ata/pata_ts72xx.c
- create mode 100644 drivers/ata/pata_ts9600.c
-
-diff --git a/drivers/ata/Kconfig b/drivers/ata/Kconfig
-index 11ec911..6c84389 100644
---- a/drivers/ata/Kconfig
-+++ b/drivers/ata/Kconfig
-@@ -862,5 +862,25 @@ config PATA_LEGACY
-
- If unsure, say N.
-
-+config PATA_TS72XX
-+ bool "TS72XX ATA support"
-+ depends on ARCH_EP93XX && MACH_TS72XX
-+ help
-+ This option enables support for ATA devices on Technologic Systems SBC.
-+
-+config PATA_TS7200_CF
-+ tristate "TS-7200 Compact Flash support"
-+ depends on PATA_TS72XX
-+ help
-+ This option enables support for the compact flash control on
-+ Technologic System TS-7200 SBC.
-+
-+config PATA_TS9600
-+ tristate "TS-9600 IDE interface support"
-+ depends on PATA_TS72XX && BLK_DEV_IDE_TS9600 != y
-+ help
-+ This option enables support for Technologic Systems TS-9600 PC/104 IDE interface.
-+
- endif # ATA_SFF
-+
- endif # ATA
-diff --git a/drivers/ata/Makefile b/drivers/ata/Makefile
-index d5df04a..eb36415 100644
---- a/drivers/ata/Makefile
-+++ b/drivers/ata/Makefile
-@@ -91,6 +91,9 @@ obj-$(CONFIG_PATA_RZ1000) += pata_rz1000.o
- obj-$(CONFIG_PATA_SAMSUNG_CF) += pata_samsung_cf.o
-
- obj-$(CONFIG_PATA_PXA) += pata_pxa.o
-+obj-$(CONFIG_PATA_TS72XX) += pata_ts72xx.o
-+obj-$(CONFIG_PATA_TS7200_CF) += pata_ts7200_cf.o
-+obj-$(CONFIG_PATA_TS9600) += pata_ts9600.o
-
- # Should be last but two libata driver
- obj-$(CONFIG_PATA_ACPI) += pata_acpi.o
-diff --git a/drivers/ata/pata_ts7200_cf.c b/drivers/ata/pata_ts7200_cf.c
-new file mode 100644
-index 0000000..4126682
---- /dev/null
-+++ b/drivers/ata/pata_ts7200_cf.c
-@@ -0,0 +1,92 @@
-+/*
-+ * Technologic Systems TS-7200 Compact Flash PATA device driver.
-+ *
-+ * (c) Copyright 2008 Matthieu Crapet <mcrapet@gmail.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.
-+ *
-+ */
-+
-+#include <linux/kernel.h>
-+#include <linux/module.h>
-+#include <linux/libata.h>
-+#include <scsi/scsi_host.h>
-+#include <linux/platform_device.h>
-+#include <linux/dma-mapping.h>
-+
-+#include <asm/io.h>
-+#include <asm/irq.h>
-+#include <mach/ts72xx.h>
-+
-+#define DRV_NAME "pata_ts7200_cf"
-+#define DRV_VERSION "0.21"
-+
-+
-+static void pata_ts7200_cf_release(struct device *dev)
-+{
-+ /* nothing to do (no kfree) because we have static struct */
-+}
-+
-+static struct resource ts7200_cf_resources[] = {
-+ [0] = {
-+ .start = TS7200_CF_CMD_PHYS_BASE,
-+ .end = TS7200_CF_CMD_PHYS_BASE + 8,
-+ .flags = IORESOURCE_MEM,
-+ },
-+ [1] = {
-+ .start = TS7200_CF_AUX_PHYS_BASE,
-+ .end = TS7200_CF_AUX_PHYS_BASE + 1,
-+ .flags = IORESOURCE_MEM,
-+ },
-+ [2] = {
-+ .start = TS7200_CF_DATA_PHYS_BASE,
-+ .end = TS7200_CF_DATA_PHYS_BASE + 2,
-+ .flags = IORESOURCE_MEM,
-+ },
-+ [3] = {
-+ .start = IRQ_EP93XX_EXT0, /* pin 103 of EP9301 */
-+ .end = IRQ_EP93XX_EXT0,
-+ .flags = IORESOURCE_IRQ,
-+ }
-+};
-+
-+
-+static struct platform_device ts7200_cf_device = {
-+ .name = "ts72xx-ide",
-+ .id = 0,
-+ .dev = {
-+ .dma_mask = &ts7200_cf_device.dev.coherent_dma_mask,
-+ .coherent_dma_mask = DMA_BIT_MASK(32),
-+ .release = pata_ts7200_cf_release,
-+ },
-+ .num_resources = ARRAY_SIZE(ts7200_cf_resources),
-+ .resource = ts7200_cf_resources,
-+};
-+
-+
-+static __init int pata_ts7200_cf_init(void)
-+{
-+ return (board_is_ts7200()) ? \
-+ platform_device_register(&ts7200_cf_device) : -ENODEV;
-+}
-+
-+static __exit void pata_ts7200_cf_exit(void)
-+{
-+ platform_device_unregister(&ts7200_cf_device);
-+}
-+
-+module_init(pata_ts7200_cf_init);
-+module_exit(pata_ts7200_cf_exit);
-+
-+MODULE_AUTHOR("Matthieu Crapet <mcrapet@gmail.com>");
-+MODULE_DESCRIPTION("TS-7200 CF PATA device driver");
-+MODULE_LICENSE("GPL");
-+MODULE_VERSION(DRV_VERSION);
-diff --git a/drivers/ata/pata_ts72xx.c b/drivers/ata/pata_ts72xx.c
-new file mode 100644
-index 0000000..d540029
---- /dev/null
-+++ b/drivers/ata/pata_ts72xx.c
-@@ -0,0 +1,161 @@
-+/*
-+ * TS-72XX PATA driver for Technologic Systems boards.
-+ *
-+ * Based on pata_platform.c by Paul Mundt &
-+ * Alessandro Zummo <a.zummo@towertech.it>
-+ * and old pata-ts72xx.c by Alessandro Zummo <a.zummo@towertech.it>
-+ *
-+ * (c) Copyright 2008 Matthieu Crapet <mcrapet@gmail.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.
-+ *
-+ */
-+
-+#include <linux/kernel.h>
-+#include <linux/module.h>
-+#include <linux/platform_device.h>
-+#include <linux/interrupt.h>
-+#include <scsi/scsi_host.h>
-+#include <linux/ata.h>
-+#include <linux/libata.h>
-+
-+#define DRV_NAME "pata_ts72xx"
-+#define DRV_VERSION "2.01"
-+
-+
-+/*
-+ * Provide our own set_mode() as we don't want to change anything that has
-+ * already been configured..
-+ */
-+static int ts72xx_set_mode(struct ata_link *link, struct ata_device **unused)
-+{
-+ struct ata_device *dev;
-+
-+ ata_for_each_dev(dev, link, ENABLED) {
-+ if (ata_dev_enabled(dev)) {
-+ /* We don't really care */
-+ dev->pio_mode = dev->xfer_mode = XFER_PIO_0;
-+ dev->xfer_shift = ATA_SHIFT_PIO;
-+ dev->flags |= ATA_DFLAG_PIO;
-+ ata_dev_printk(dev, KERN_INFO, "configured for PIO\n");
-+ }
-+ }
-+ return 0;
-+}
-+
-+static struct scsi_host_template ts72xx_sht = {
-+ ATA_PIO_SHT(DRV_NAME),
-+};
-+
-+static struct ata_port_operations ts72xx_port_ops = {
-+ .inherits = &ata_sff_port_ops,
-+ .set_mode = ts72xx_set_mode,
-+};
-+
-+static __devinit int ts72xx_pata_probe(struct platform_device *pdev)
-+{
-+ struct ata_host *host;
-+ struct ata_port *ap;
-+ int irq;
-+
-+ struct resource *pata_cmd = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-+ struct resource *pata_aux = platform_get_resource(pdev, IORESOURCE_MEM, 1);
-+ struct resource *pata_data = platform_get_resource(pdev, IORESOURCE_MEM, 2);
-+
-+ if (!pata_cmd || !pata_aux || !pata_data) {
-+ dev_err(&pdev->dev, "missing resource(s)\n");
-+ return -EINVAL;
-+ }
-+
-+ irq = platform_get_irq(pdev, 0);
-+ if (irq < 0)
-+ irq = 0; /* no irq */
-+
-+ /*
-+ * Now that that's out of the way, wire up the port
-+ */
-+ host = ata_host_alloc(&pdev->dev, 1);
-+ if (!host)
-+ return -ENOMEM;
-+ ap = host->ports[0];
-+
-+ ap->ops = &ts72xx_port_ops;
-+ ap->pio_mask = 0x1f; /* PIO0-4 */
-+ ap->flags |= ATA_FLAG_SLAVE_POSS;
-+
-+ /*
-+ * Use polling mode if there's no IRQ
-+ */
-+ if (!irq) {
-+ ap->flags |= ATA_FLAG_PIO_POLLING;
-+ ata_port_desc(ap, "no IRQ, using PIO polling");
-+ }
-+
-+ ap->ioaddr.cmd_addr = devm_ioremap(&pdev->dev, pata_cmd->start,
-+ pata_cmd->end - pata_cmd->start + 1);
-+ ap->ioaddr.ctl_addr = devm_ioremap(&pdev->dev, pata_aux->start,
-+ pata_aux->end - pata_aux->start + 1);
-+
-+ if (!ap->ioaddr.cmd_addr || !ap->ioaddr.ctl_addr) {
-+ dev_err(&pdev->dev, "failed to map IO/CTL base\n");
-+ return -ENOMEM;
-+ }
-+
-+ ap->ioaddr.altstatus_addr = ap->ioaddr.ctl_addr;
-+
-+ ata_sff_std_ports(&ap->ioaddr);
-+ ap->ioaddr.data_addr = devm_ioremap(&pdev->dev, pata_data->start,
-+ pata_data->end - pata_data->start + 1);
-+
-+ ata_port_desc(ap, "mmio cmd 0x%llx ctl 0x%llx",
-+ (unsigned long long)pata_cmd->start,
-+ (unsigned long long)pata_aux->start);
-+
-+ return ata_host_activate(host, irq, irq ? ata_sff_interrupt : NULL,
-+ 0 /* irq flags */, &ts72xx_sht);
-+}
-+
-+static __devexit int ts72xx_pata_remove(struct platform_device *pdev)
-+{
-+ struct device *dev = &pdev->dev;
-+ struct ata_host *host = dev_get_drvdata(dev);
-+
-+ ata_host_detach(host);
-+
-+ return 0;
-+}
-+
-+static struct platform_driver ts72xx_pata_platform_driver = {
-+ .probe = ts72xx_pata_probe,
-+ .remove = __devexit_p(ts72xx_pata_remove),
-+ .driver = {
-+ .name = "ts72xx-ide",
-+ .owner = THIS_MODULE,
-+ },
-+};
-+
-+static int __init ts72xx_pata_init(void)
-+{
-+ return platform_driver_register(&ts72xx_pata_platform_driver);
-+}
-+
-+static void __exit ts72xx_pata_exit(void)
-+{
-+ platform_driver_unregister(&ts72xx_pata_platform_driver);
-+}
-+
-+MODULE_AUTHOR("Matthieu Crapet <mcrapet@gmail.com>");
-+MODULE_DESCRIPTION("low-level driver for TS-72xx device PATA");
-+MODULE_LICENSE("GPL");
-+MODULE_VERSION(DRV_VERSION);
-+
-+module_init(ts72xx_pata_init);
-+module_exit(ts72xx_pata_exit);
-diff --git a/drivers/ata/pata_ts9600.c b/drivers/ata/pata_ts9600.c
-new file mode 100644
-index 0000000..7a70550
---- /dev/null
-+++ b/drivers/ata/pata_ts9600.c
-@@ -0,0 +1,95 @@
-+/*
-+ * Technologic Systems TS-9600 PATA device driver.
-+ *
-+ * (c) Copyright 2008 Matthieu Crapet <mcrapet@gmail.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.
-+ *
-+ */
-+
-+#include <linux/kernel.h>
-+#include <linux/module.h>
-+#include <linux/libata.h>
-+#include <scsi/scsi_host.h>
-+#include <linux/platform_device.h>
-+#include <linux/dma-mapping.h>
-+
-+#include <asm/io.h>
-+#include <asm/irq.h>
-+#include <mach/ts72xx.h>
-+
-+#define DRV_NAME "pata_ts9600"
-+#define DRV_VERSION "0.21"
-+
-+#define TS9600_IDE_IO (TS72XX_PC104_8BIT_IO_PHYS_BASE + 0x1F0)
-+#define TS9600_IDE_DATA (TS72XX_PC104_16BIT_IO_PHYS_BASE + 0x1F0)
-+#define TS9600_IDE_IRQ IRQ_EP93XX_EXT3 // IRQ7 (no other possibility for arm)
-+
-+
-+static void pata_ts9600_release(struct device *dev)
-+{
-+ /* nothing to do (no kfree) because we have static struct */
-+}
-+
-+static struct resource ts9600_resources[] = {
-+ [0] = {
-+ .start = TS9600_IDE_IO,
-+ .end = TS9600_IDE_IO + 8,
-+ .flags = IORESOURCE_MEM,
-+ },
-+ [1] = {
-+ .start = TS9600_IDE_IO + 0x206,
-+ .end = TS9600_IDE_IO + 0x206 + 1,
-+ .flags = IORESOURCE_MEM,
-+ },
-+ [2] = {
-+ .start = TS9600_IDE_DATA,
-+ .end = TS9600_IDE_DATA + 2,
-+ .flags = IORESOURCE_MEM,
-+ },
-+ [3] = {
-+ .start = TS9600_IDE_IRQ,
-+ .end = TS9600_IDE_IRQ,
-+ .flags = IORESOURCE_IRQ,
-+ }
-+};
-+
-+
-+static struct platform_device ts9600_device = {
-+ .name = "ts72xx-ide",
-+ .id = 9600,
-+ .dev = {
-+ .dma_mask = &ts9600_device.dev.coherent_dma_mask,
-+ .coherent_dma_mask = DMA_BIT_MASK(32),
-+ .release = pata_ts9600_release,
-+ },
-+ .num_resources = ARRAY_SIZE(ts9600_resources),
-+ .resource = ts9600_resources,
-+};
-+
-+
-+static __init int pata_ts9600_init(void)
-+{
-+ return platform_device_register(&ts9600_device);
-+}
-+
-+static __exit void pata_ts9600_exit(void)
-+{
-+ platform_device_unregister(&ts9600_device);
-+}
-+
-+module_init(pata_ts9600_init);
-+module_exit(pata_ts9600_exit);
-+
-+MODULE_AUTHOR("Matthieu Crapet <mcrapet@gmail.com>");
-+MODULE_DESCRIPTION("TS-9600 PATA device driver");
-+MODULE_LICENSE("GPL");
-+MODULE_VERSION(DRV_VERSION);
---
-1.7.0.4
-
diff --git a/recipes/linux/linux-2.6.36/ts72xx/0010-ts72xx_gpio_i2c.patch b/recipes/linux/linux-2.6.36/ts72xx/0010-ts72xx_gpio_i2c.patch
deleted file mode 100644
index 7dee3af..0000000
--- a/recipes/linux/linux-2.6.36/ts72xx/0010-ts72xx_gpio_i2c.patch
+++ /dev/null
@@ -1,63 +0,0 @@
-From 675ef8ec55abd042e7d725bb5a7963ac6e715acb Mon Sep 17 00:00:00 2001
-From: Matthieu Crapet <mcrapet@gmail.com>
-Date: Sat, 19 Jun 2010 11:45:39 +0200
-Subject: [PATCH 10/24] ts72xx_gpio_i2c
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-Signed-off-by: Petr Štetiar <ynezz@true.cz>
----
- arch/arm/mach-ep93xx/ts72xx.c | 22 ++++++++++++++++++++++
- 1 files changed, 22 insertions(+), 0 deletions(-)
-
-diff --git a/arch/arm/mach-ep93xx/ts72xx.c b/arch/arm/mach-ep93xx/ts72xx.c
-index 345ce18..e8a2489 100644
---- a/arch/arm/mach-ep93xx/ts72xx.c
-+++ b/arch/arm/mach-ep93xx/ts72xx.c
-@@ -19,6 +19,10 @@
- #include <linux/m48t86.h>
- #include <linux/mtd/nand.h>
- #include <linux/mtd/partitions.h>
-+#include <linux/mtd/physmap.h>
-+#include <linux/gpio.h>
-+#include <linux/i2c.h>
-+#include <linux/i2c-gpio.h>
-
- #include <mach/hardware.h>
- #include <mach/ts72xx.h>
-@@ -279,6 +283,21 @@ static struct ep93xx_eth_data __initdata ts72xx_eth_data = {
- .phy_id = 1,
- };
-
-+/*************************************************************************
-+ * I2C (make access through TS-72XX "DIO" 2x8 header)
-+ *************************************************************************/
-+static struct i2c_gpio_platform_data ts72xx_i2c_gpio_data = {
-+ .sda_pin = EP93XX_GPIO_LINE_EGPIO14, // DIO_6
-+ .sda_is_open_drain = 0,
-+ .scl_pin = EP93XX_GPIO_LINE_EGPIO15, // DIO_7
-+ .scl_is_open_drain = 0,
-+ .udelay = 0, /* default is 100 kHz */
-+ .timeout = 0, /* default is 100 ms */
-+};
-+
-+static struct i2c_board_info __initdata ts72xx_i2c_board_info[] = {
-+};
-+
- static void __init ts72xx_init_machine(void)
- {
- ep93xx_init_devices();
-@@ -287,6 +306,9 @@ static void __init ts72xx_init_machine(void)
- platform_device_register(&ts72xx_wdt_device);
-
- ep93xx_register_eth(&ts72xx_eth_data, 1);
-+ ep93xx_register_i2c(&ts72xx_i2c_gpio_data,
-+ ts72xx_i2c_board_info,
-+ ARRAY_SIZE(ts72xx_i2c_board_info));
-
- /* PWM1 is DIO_6 on TS-72xx header */
- ep93xx_register_pwm(0, 1);
---
-1.7.0.4
-
diff --git a/recipes/linux/linux-2.6.36/ts72xx/0011-ts72xx_dio_keypad.patch b/recipes/linux/linux-2.6.36/ts72xx/0011-ts72xx_dio_keypad.patch
deleted file mode 100644
index df0924e..0000000
--- a/recipes/linux/linux-2.6.36/ts72xx/0011-ts72xx_dio_keypad.patch
+++ /dev/null
@@ -1,311 +0,0 @@
-From 75385f54792d2ed6dc59005972cf54dbedea9897 Mon Sep 17 00:00:00 2001
-From: Matthieu Crapet <mcrapet@gmail.com>
-Date: Sat, 19 Jun 2010 14:44:32 +0200
-Subject: [PATCH 11/24] ts72xx_dio_keypad
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-Depends of "matrix-keypad" driver.
-
-Signed-off-by: Petr Štetiar <ynezz@true.cz>
----
- drivers/input/keyboard/Kconfig | 30 ++++++++
- drivers/input/keyboard/Makefile | 2 +
- drivers/input/keyboard/ts72xx_dio_3x4.c | 110 +++++++++++++++++++++++++++++
- drivers/input/keyboard/ts72xx_dio_4x4.c | 115 +++++++++++++++++++++++++++++++
- 4 files changed, 257 insertions(+), 0 deletions(-)
- create mode 100644 drivers/input/keyboard/ts72xx_dio_3x4.c
- create mode 100644 drivers/input/keyboard/ts72xx_dio_4x4.c
-
-diff --git a/drivers/input/keyboard/Kconfig b/drivers/input/keyboard/Kconfig
-index 9cc488d..81860f4 100644
---- a/drivers/input/keyboard/Kconfig
-+++ b/drivers/input/keyboard/Kconfig
-@@ -204,6 +204,36 @@ config KEYBOARD_MATRIX
- To compile this driver as a module, choose M here: the
- module will be called matrix_keypad.
-
-+if KEYBOARD_MATRIX
-+
-+choice
-+ prompt "Keypad type"
-+ default TS72XX_DIO_4X4_KEYPAD
-+
-+config TS72XX_DIO_3X4_KEYPAD
-+ tristate "TS-72xx 3x4 matrix keypad"
-+ depends on MACH_TS72XX
-+ help
-+ This a 12 keys (4 rows, 3 cols using DIO_0-6) keypad with the following layout:
-+ 1 2 3
-+ 4 5 6
-+ 7 8 9
-+ * 0 #
-+
-+config TS72XX_DIO_4X4_KEYPAD
-+ tristate "TS-72xx 4x4 matrix keypad"
-+ depends on MACH_TS72XX
-+ help
-+ This a 16 keys (4 rows, 4 cols using DIO_0-7) keypad with the following layout:
-+ 7 8 9 F
-+ 4 5 6 E
-+ 1 2 3 D
-+ A 0 B C
-+
-+endchoice
-+
-+endif # KEYBOARD_MATRIX
-+
- config KEYBOARD_HIL_OLD
- tristate "HP HIL keyboard support (simple driver)"
- depends on GSC || HP300
-diff --git a/drivers/input/keyboard/Makefile b/drivers/input/keyboard/Makefile
-index 504b591..cb18981 100644
---- a/drivers/input/keyboard/Makefile
-+++ b/drivers/input/keyboard/Makefile
-@@ -41,3 +41,5 @@ obj-$(CONFIG_KEYBOARD_SUNKBD) += sunkbd.o
- obj-$(CONFIG_KEYBOARD_TWL4030) += twl4030_keypad.o
- obj-$(CONFIG_KEYBOARD_XTKBD) += xtkbd.o
- obj-$(CONFIG_KEYBOARD_W90P910) += w90p910_keypad.o
-+obj-$(CONFIG_TS72XX_DIO_3X4_KEYPAD) += ts72xx_dio_3x4.o
-+obj-$(CONFIG_TS72XX_DIO_4X4_KEYPAD) += ts72xx_dio_4x4.o
-diff --git a/drivers/input/keyboard/ts72xx_dio_3x4.c b/drivers/input/keyboard/ts72xx_dio_3x4.c
-new file mode 100644
-index 0000000..e214335
---- /dev/null
-+++ b/drivers/input/keyboard/ts72xx_dio_3x4.c
-@@ -0,0 +1,110 @@
-+/*
-+ * TS-72xx (3x4) keypad device driver for DIO1 header (DIO_0 thru DIO_6)
-+ *
-+ * (c) Copyright 2010 Matthieu Crapet <mcrapet@gmail.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.
-+ *
-+ */
-+
-+#include <linux/module.h>
-+#include <linux/kernel.h>
-+#include <linux/init.h>
-+#include <linux/platform_device.h>
-+#include <linux/input/matrix_keypad.h>
-+#include <mach/gpio.h>
-+
-+static const uint32_t ts72xx_kbd_keymap[] = {
-+ KEY(0, 0, KEY_1),
-+ KEY(0, 1, KEY_2),
-+ KEY(0, 2, KEY_3),
-+
-+ KEY(1, 0, KEY_4),
-+ KEY(1, 1, KEY_5),
-+ KEY(1, 2, KEY_6),
-+
-+ KEY(2, 0, KEY_7),
-+ KEY(2, 1, KEY_8),
-+ KEY(2, 2, KEY_9),
-+
-+ KEY(3, 0, KEY_KPASTERISK),
-+ KEY(3, 1, KEY_0),
-+ KEY(3, 2, KEY_ENTER),
-+};
-+
-+static struct matrix_keymap_data ts72xx_kbd_keymap_data = {
-+ .keymap = ts72xx_kbd_keymap,
-+ .keymap_size = ARRAY_SIZE(ts72xx_kbd_keymap),
-+};
-+
-+static const int ts72xx_kbd_row_gpios[] = {
-+ EP93XX_GPIO_LINE_EGPIO14, // DIO_6 (row0)
-+ EP93XX_GPIO_LINE_EGPIO13,
-+ EP93XX_GPIO_LINE_EGPIO12,
-+ EP93XX_GPIO_LINE_EGPIO11,
-+};
-+
-+static const int ts72xx_kbd_col_gpios[] = {
-+ EP93XX_GPIO_LINE_EGPIO10, // DIO_2 (col0)
-+ EP93XX_GPIO_LINE_EGPIO9,
-+ EP93XX_GPIO_LINE_EGPIO8,
-+};
-+
-+static struct matrix_keypad_platform_data ts72xx_kbd_pdata = {
-+ .keymap_data = &ts72xx_kbd_keymap_data,
-+ .row_gpios = ts72xx_kbd_row_gpios,
-+ .col_gpios = ts72xx_kbd_col_gpios,
-+ .num_row_gpios = ARRAY_SIZE(ts72xx_kbd_row_gpios),
-+ .num_col_gpios = ARRAY_SIZE(ts72xx_kbd_col_gpios),
-+ .col_scan_delay_us = 20,
-+ .debounce_ms = 20,
-+ .wakeup = 1,
-+ .active_low = 1,
-+ //.no_autorep = 1,
-+};
-+
-+static void ts72xx_kbd_release(struct device *dev)
-+{
-+}
-+
-+static struct platform_device ts72xx_kbd_device = {
-+ .name = "matrix-keypad",
-+ .id = -1,
-+ .dev = {
-+ .platform_data = &ts72xx_kbd_pdata,
-+ .release = ts72xx_kbd_release,
-+ },
-+};
-+
-+static int __init ts72xx_dio_init(void)
-+{
-+ int i;
-+
-+ for (i = 0; i < ARRAY_SIZE(ts72xx_kbd_row_gpios); i++) {
-+ int irq = gpio_to_irq(ts72xx_kbd_row_gpios[i]);
-+
-+ ep93xx_gpio_int_debounce(irq, 1);
-+ }
-+
-+ return platform_device_register(&ts72xx_kbd_device);
-+}
-+
-+static void __exit ts72xx_dio_exit(void)
-+{
-+ platform_device_unregister(&ts72xx_kbd_device);
-+}
-+
-+module_init(ts72xx_dio_init);
-+module_exit(ts72xx_dio_exit);
-+
-+MODULE_AUTHOR("Matthieu Crapet <mcrapet@gmail.com>");
-+MODULE_DESCRIPTION("Platform device 3x4 keypad");
-+MODULE_LICENSE("GPL");
-diff --git a/drivers/input/keyboard/ts72xx_dio_4x4.c b/drivers/input/keyboard/ts72xx_dio_4x4.c
-new file mode 100644
-index 0000000..790abd5
---- /dev/null
-+++ b/drivers/input/keyboard/ts72xx_dio_4x4.c
-@@ -0,0 +1,115 @@
-+/*
-+ * TS-72xx (4x4) keypad device driver for DIO1 header (DIO_0 thru DIO_7)
-+ *
-+ * (c) Copyright 2010 Matthieu Crapet <mcrapet@gmail.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.
-+ *
-+ */
-+
-+#include <linux/module.h>
-+#include <linux/kernel.h>
-+#include <linux/init.h>
-+#include <linux/platform_device.h>
-+#include <linux/input/matrix_keypad.h>
-+#include <mach/gpio.h>
-+
-+static const uint32_t ts72xx_kbd_keymap[] = {
-+ KEY(0, 0, KEY_7),
-+ KEY(0, 1, KEY_8),
-+ KEY(0, 2, KEY_9),
-+ KEY(0, 3, KEY_F),
-+
-+ KEY(1, 0, KEY_4),
-+ KEY(1, 1, KEY_5),
-+ KEY(1, 2, KEY_6),
-+ KEY(1, 3, KEY_E),
-+
-+ KEY(2, 0, KEY_1),
-+ KEY(2, 1, KEY_2),
-+ KEY(2, 2, KEY_3),
-+ KEY(2, 3, KEY_D),
-+
-+ KEY(3, 0, KEY_A),
-+ KEY(3, 1, KEY_0),
-+ KEY(3, 2, KEY_B),
-+ KEY(3, 3, KEY_C),
-+};
-+
-+static struct matrix_keymap_data ts72xx_kbd_keymap_data = {
-+ .keymap = ts72xx_kbd_keymap,
-+ .keymap_size = ARRAY_SIZE(ts72xx_kbd_keymap),
-+};
-+
-+static const int ts72xx_kbd_row_gpios[] = {
-+ EP93XX_GPIO_LINE_EGPIO8, // DIO_0 (row0)
-+ EP93XX_GPIO_LINE_EGPIO9,
-+ EP93XX_GPIO_LINE_EGPIO12,
-+ EP93XX_GPIO_LINE_EGPIO14,
-+};
-+
-+static const int ts72xx_kbd_col_gpios[] = {
-+ EP93XX_GPIO_LINE_EGPIO15, // DIO_7 (col0)
-+ EP93XX_GPIO_LINE_EGPIO13,
-+ EP93XX_GPIO_LINE_EGPIO11,
-+ EP93XX_GPIO_LINE_EGPIO10,
-+};
-+
-+static struct matrix_keypad_platform_data ts72xx_kbd_pdata = {
-+ .keymap_data = &ts72xx_kbd_keymap_data,
-+ .row_gpios = ts72xx_kbd_row_gpios,
-+ .col_gpios = ts72xx_kbd_col_gpios,
-+ .num_row_gpios = ARRAY_SIZE(ts72xx_kbd_row_gpios),
-+ .num_col_gpios = ARRAY_SIZE(ts72xx_kbd_col_gpios),
-+ .col_scan_delay_us = 20,
-+ .debounce_ms = 20,
-+ .wakeup = 1,
-+ .active_low = 1,
-+ //.no_autorep = 1,
-+};
-+
-+static void ts72xx_kbd_release(struct device *dev)
-+{
-+}
-+
-+static struct platform_device ts72xx_kbd_device = {
-+ .name = "matrix-keypad",
-+ .id = -1,
-+ .dev = {
-+ .platform_data = &ts72xx_kbd_pdata,
-+ .release = ts72xx_kbd_release,
-+ },
-+};
-+
-+static int __init ts72xx_dio_init(void)
-+{
-+ int i;
-+
-+ for (i = 0; i < ARRAY_SIZE(ts72xx_kbd_row_gpios); i++) {
-+ int irq = gpio_to_irq(ts72xx_kbd_row_gpios[i]);
-+
-+ ep93xx_gpio_int_debounce(irq, 1);
-+ }
-+
-+ return platform_device_register(&ts72xx_kbd_device);
-+}
-+
-+static void __exit ts72xx_dio_exit(void)
-+{
-+ platform_device_unregister(&ts72xx_kbd_device);
-+}
-+
-+module_init(ts72xx_dio_init);
-+module_exit(ts72xx_dio_exit);
-+
-+MODULE_AUTHOR("Matthieu Crapet <mcrapet@gmail.com>");
-+MODULE_DESCRIPTION("Platform device 4x4 keypad");
-+MODULE_LICENSE("GPL");
---
-1.7.0.4
-
diff --git a/recipes/linux/linux-2.6.36/ts72xx/0012-ts72xx_sbcinfo.patch b/recipes/linux/linux-2.6.36/ts72xx/0012-ts72xx_sbcinfo.patch
deleted file mode 100644
index f744a66..0000000
--- a/recipes/linux/linux-2.6.36/ts72xx/0012-ts72xx_sbcinfo.patch
+++ /dev/null
@@ -1,267 +0,0 @@
-From c4f068cc743be6e79c333a0de38e1cef91e05786 Mon Sep 17 00:00:00 2001
-From: Matthieu Crapet <mcrapet@gmail.com>
-Date: Sat, 19 Jun 2010 15:08:58 +0200
-Subject: [PATCH 12/24] ts72xx_sbcinfo
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-Signed-off-by: Petr Štetiar <ynezz@true.cz>
----
- arch/arm/mach-ep93xx/Kconfig | 7 +
- arch/arm/mach-ep93xx/Makefile | 1 +
- arch/arm/mach-ep93xx/ts72xx.c | 5 +
- arch/arm/mach-ep93xx/ts72xx_sbcinfo.c | 198 +++++++++++++++++++++++++++++++++
- 4 files changed, 211 insertions(+), 0 deletions(-)
- create mode 100644 arch/arm/mach-ep93xx/ts72xx_sbcinfo.c
-
-diff --git a/arch/arm/mach-ep93xx/Kconfig b/arch/arm/mach-ep93xx/Kconfig
-index bd463a0..2bfb01e 100644
---- a/arch/arm/mach-ep93xx/Kconfig
-+++ b/arch/arm/mach-ep93xx/Kconfig
-@@ -212,6 +212,13 @@ config MACH_TS72XX_FORCE_MACHINEID
- Say 'Y' here to force Machine ID to 0x2A1 (MACH_TYPE_TS72XX legacy value)
- In early days Technologic Systems fixed the 0x163 value in redboot.
-
-+config MACH_TS72XX_SBCINFO
-+ tristate "Add procfs /proc/driver/sbcinfo"
-+ depends on MACH_TS72XX
-+ help
-+ Say 'Y' to add a procfs entry containing some information
-+ related to Technologic Systems TS-72xx SBC.
-+
- endmenu
-
- endif
-diff --git a/arch/arm/mach-ep93xx/Makefile b/arch/arm/mach-ep93xx/Makefile
-index ea652c2..c38d1e2 100644
---- a/arch/arm/mach-ep93xx/Makefile
-+++ b/arch/arm/mach-ep93xx/Makefile
-@@ -13,3 +13,4 @@ obj-$(CONFIG_MACH_MICRO9) += micro9.o
- obj-$(CONFIG_MACH_SIM_ONE) += simone.o
- obj-$(CONFIG_MACH_SNAPPER_CL15) += snappercl15.o
- obj-$(CONFIG_MACH_TS72XX) += ts72xx.o
-+obj-$(CONFIG_MACH_TS72XX_SBCINFO) += ts72xx_sbcinfo.o
-diff --git a/arch/arm/mach-ep93xx/ts72xx.c b/arch/arm/mach-ep93xx/ts72xx.c
-index e8a2489..9b707a5 100644
---- a/arch/arm/mach-ep93xx/ts72xx.c
-+++ b/arch/arm/mach-ep93xx/ts72xx.c
-@@ -39,6 +39,11 @@ static struct map_desc ts72xx_io_desc[] __initdata = {
- .length = TS72XX_MODEL_SIZE,
- .type = MT_DEVICE,
- }, {
-+ .virtual = TS72XX_PLD_VERSION_VIRT_BASE,
-+ .pfn = __phys_to_pfn(TS72XX_PLD_VERSION_PHYS_BASE),
-+ .length = TS72XX_PLD_VERSION_SIZE,
-+ .type = MT_DEVICE,
-+ }, {
- .virtual = TS72XX_OPTIONS_VIRT_BASE,
- .pfn = __phys_to_pfn(TS72XX_OPTIONS_PHYS_BASE),
- .length = TS72XX_OPTIONS_SIZE,
-diff --git a/arch/arm/mach-ep93xx/ts72xx_sbcinfo.c b/arch/arm/mach-ep93xx/ts72xx_sbcinfo.c
-new file mode 100644
-index 0000000..cbb485f
---- /dev/null
-+++ b/arch/arm/mach-ep93xx/ts72xx_sbcinfo.c
-@@ -0,0 +1,198 @@
-+/*
-+ * Technologic Systems TS-72XX sbc /proc/driver/sbcinfo entry.
-+ *
-+ * Original idea by Liberty Young (Technologic Systems).
-+ *
-+ * (c) Copyright 2008 Matthieu Crapet <mcrapet@gmail.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.
-+ */
-+
-+#include <linux/module.h>
-+#include <linux/kernel.h>
-+#include <linux/init.h>
-+#include <linux/io.h>
-+#include <linux/proc_fs.h>
-+#include <mach/hardware.h>
-+#include <mach/ts72xx.h>
-+
-+struct infos {
-+ const char *cpu_rev;
-+ int model, pld, wdt;
-+ int option_ad;
-+ int option_rs485;
-+ unsigned char jumpers[6]; // 0=off,1=on,2=error
-+
-+ /* Power management : TS-7260 only */
-+ int pm;
-+};
-+
-+static const char *revisions[] = { "A", "B", "C", "D0", "D1", "E0", "E1", "E2", "??" };
-+
-+
-+static void get_sbcinfo(struct infos *data)
-+{
-+ void __iomem *p;
-+ short rev;
-+
-+ /* CPU revision */
-+ rev = __raw_readl(EP93XX_SYSCON_CHIPID) >> 28;
-+ if (rev > ARRAY_SIZE(revisions))
-+ rev = ARRAY_SIZE(revisions) - 1;
-+ data->cpu_rev = revisions[rev];
-+
-+ /* Board model */
-+ if (board_is_ts7200())
-+ data->model = 7200;
-+ else if (board_is_ts7250())
-+ data->model = 7250;
-+ else if (board_is_ts7260())
-+ data->model = 7260;
-+ else if (board_is_ts7400())
-+ data->model = 7400;
-+ else
-+ data->model = 0;
-+
-+ data->pld = get_ts72xx_pld_version();
-+
-+ /* A/D converter (8 x 12-bit channels) */
-+ if (data->model == 7200 || data->model == 7250) {
-+ data->option_ad = is_max197_installed();
-+ } else {
-+ data->option_ad = 0;
-+ }
-+
-+ /* COM2 RS-485 */
-+ if (is_rs485_installed()) {
-+ data->option_rs485 = 1;
-+ } else {
-+ data->option_rs485 = 0;
-+ }
-+
-+ /* jumpers */
-+ p = ioremap(TS72XX_JUMPERS_MAX197_PHYS_BASE, SZ_4K - 1);
-+ if (p) {
-+ unsigned char c = __raw_readb(p);
-+
-+ data->jumpers[0] = 2; // JP1 (bootstrap)
-+ data->jumpers[1] = !!(c & 0x01); // JP2 (enable serial console)
-+ data->jumpers[2] = !!(c & 0x02); // JP3 (flash write enable)
-+ data->jumpers[3] = !(c & 0x08); // JP4 (console on COM2)
-+ data->jumpers[4] = !(c & 0x10); // JP5 (test)
-+ data->jumpers[5] = !!(is_jp6_set()); // JP6 (user jumper)
-+
-+ iounmap(p);
-+ } else {
-+ data->jumpers[0] = data->jumpers[1] = data->jumpers[2] = 2;
-+ data->jumpers[3] = data->jumpers[4] = data->jumpers[5] = 2;
-+ }
-+
-+ /* cpld watchdog */
-+ p = ioremap(TS72XX_WDT_CONTROL_PHYS_BASE, SZ_4K - 1);
-+ if (p) {
-+ data->wdt = __raw_readb(p) & 0x7;
-+ iounmap(p);
-+ } else {
-+ data->wdt = 8;
-+ }
-+
-+ /* power management */
-+ data->pm = -1;
-+ if (data->model == 7260) {
-+ p = ioremap(TS7260_POWER_MANAGEMENT_PHYS_BASE, SZ_4K - 1);
-+ if (p) {
-+ data->pm = __raw_readb(p);
-+ iounmap(p);
-+ }
-+ }
-+}
-+
-+static char *get_pm_string(int reg, char *buffer, size_t size)
-+{
-+ static const char *pm_state = "rs232=%d usb=%d lcd=%d pc104=%d ttl=%d";
-+
-+ if (reg < 0) {
-+ strncpy(buffer, "n/a", size);
-+ } else {
-+ /* 1 means on/enabled */
-+ snprintf(buffer, size, pm_state,
-+ reg & TS7260_PM_RS232_LEVEL_CONVERTER,
-+ !!(reg & TS7260_PM_USB),
-+ !!(reg & TS7260_PM_LCD),
-+ !(reg & TS7260_PM_PC104_CLOCK),
-+ !!(reg & TS7260_PM_TTL_UART_ENABLE));
-+ }
-+ return buffer;
-+}
-+
-+static int ts72xx_sbcinfo_read_proc(char *buffer, char **start, off_t offset,
-+ int count, int *eof, void *data)
-+{
-+ int len, size = count;
-+ char *p = buffer;
-+ char temp[64];
-+ struct infos nfo;
-+
-+ static const char jpc[3] = { 'n', 'y', '?' };
-+ static const char *wdt[9] = { "disabled", "250ms", "500ms", "1s", "reserved", "2s", "4s", "8s", "n/a" };
-+
-+ get_sbcinfo(&nfo);
-+ len = scnprintf(p, size,
-+ "Model : TS-%d (CPU rev %s) (PLD rev %c)\n"
-+ "Option max197 A/D : %s\n"
-+ "Option RS-485 : %s\n"
-+ "Jumpers : JP2=%c JP3=%c JP4=%c JP5=%c JP6=%c\n"
-+ "CPLD Watchdog : %s\n"
-+ "Power management : %s\n",
-+ nfo.model, nfo.cpu_rev, nfo.pld + 0x40,
-+ (nfo.option_ad ? "yes" : "no"),
-+ (nfo.option_rs485 ? "yes" : "no"),
-+ jpc[nfo.jumpers[1]], jpc[nfo.jumpers[2]], jpc[nfo.jumpers[3]], jpc[nfo.jumpers[4]],
-+ jpc[nfo.jumpers[5]], wdt[nfo.wdt],
-+ get_pm_string(nfo.pm, &temp[0], sizeof(temp)));
-+
-+ if (len <= offset + count)
-+ *eof = 1;
-+
-+ *start = buffer + offset;
-+ len -= offset;
-+
-+ if (len > count)
-+ len = count;
-+ if (len < 0)
-+ len = 0;
-+
-+ return len;
-+}
-+
-+static int __init ts72xx_sbcinfo_init(void)
-+{
-+ struct proc_dir_entry *entry;
-+ int ret = 0;
-+
-+ entry = create_proc_read_entry("driver/sbcinfo", 0,
-+ NULL, ts72xx_sbcinfo_read_proc, NULL);
-+
-+ if (!entry) {
-+ printk(KERN_ERR "sbcinfo: can't create /proc/driver/sbcinfo\n");
-+ ret = -ENOMEM;
-+ }
-+
-+ return ret;
-+}
-+
-+static void __exit ts72xx_sbcinfo_exit(void)
-+{
-+ remove_proc_entry("driver/sbcinfo", NULL);
-+}
-+
-+module_init(ts72xx_sbcinfo_init);
-+module_exit(ts72xx_sbcinfo_exit);
-+
-+MODULE_AUTHOR("Matthieu Crapet <mcrapet@gmail.com>");
-+MODULE_DESCRIPTION("Show information of Technologic Systems TS-72XX sbc");
-+MODULE_LICENSE("GPL");
-+MODULE_VERSION("1.04");
---
-1.7.0.4
-
diff --git a/recipes/linux/linux-2.6.36/ts72xx/0013-ts72xx_max197.patch b/recipes/linux/linux-2.6.36/ts72xx/0013-ts72xx_max197.patch
deleted file mode 100644
index 6837e55..0000000
--- a/recipes/linux/linux-2.6.36/ts72xx/0013-ts72xx_max197.patch
+++ /dev/null
@@ -1,356 +0,0 @@
-From 4d67c12c77e2095db542e84a78086cb1be02ff71 Mon Sep 17 00:00:00 2001
-From: Matthieu Crapet <mcrapet@gmail.com>
-Date: Sat, 19 Jun 2010 15:49:34 +0200
-Subject: [PATCH 13/24] ts72xx_max197
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-Signed-off-by: Petr Štetiar <ynezz@true.cz>
----
- arch/arm/mach-ep93xx/ts72xx.c | 32 ++++++-
- drivers/misc/Kconfig | 21 ++++
- drivers/misc/Makefile | 1 +
- drivers/misc/ts72xx_max197.c | 235 +++++++++++++++++++++++++++++++++++++++++
- 4 files changed, 288 insertions(+), 1 deletions(-)
- create mode 100644 drivers/misc/ts72xx_max197.c
-
-diff --git a/arch/arm/mach-ep93xx/ts72xx.c b/arch/arm/mach-ep93xx/ts72xx.c
-index 9b707a5..96a4d54 100644
---- a/arch/arm/mach-ep93xx/ts72xx.c
-+++ b/arch/arm/mach-ep93xx/ts72xx.c
-@@ -281,10 +281,36 @@ static struct platform_device ts72xx_wdt_device = {
- .resource = ts72xx_wdt_resources,
- };
-
--static struct ep93xx_eth_data __initdata ts72xx_eth_data = {
-+/*************************************************************************
-+ * MAX197 (8 * 12-bit A/D converter) option
-+ *************************************************************************/
-+static struct resource ts72xx_max197_resources[] = {
-+ [0] = { /* sample/control register */
-+ .start = TS72XX_MAX197_SAMPLE_PHYS_BASE,
-+ .end = TS72XX_MAX197_SAMPLE_PHYS_BASE + SZ_4K - 1,
-+ .flags = IORESOURCE_MEM,
-+ },
-+ [1] = { /* busy bit */
-+ .start = TS72XX_JUMPERS_MAX197_PHYS_BASE,
-+ .end = TS72XX_JUMPERS_MAX197_PHYS_BASE + SZ_4K - 1,
-+ .flags = IORESOURCE_MEM,
-+ }
-+};
-+
-+static struct platform_device ts72xx_max197_device = {
-+ .name = "ts72xx-max197",
-+ .id = -1,
-+ .dev = {
-+ .platform_data = NULL,
-+ },
-+ .num_resources = ARRAY_SIZE(ts72xx_max197_resources),
-+ .resource = ts72xx_max197_resources,
-+};
-+
- /*************************************************************************
- * Ethernet
- *************************************************************************/
-+static struct ep93xx_eth_data __initdata ts72xx_eth_data = {
- .phy_id = 1,
- };
-
-@@ -315,6 +341,10 @@ static void __init ts72xx_init_machine(void)
- ts72xx_i2c_board_info,
- ARRAY_SIZE(ts72xx_i2c_board_info));
-
-+ if (is_max197_installed()) {
-+ platform_device_register(&ts72xx_max197_device);
-+ }
-+
- /* PWM1 is DIO_6 on TS-72xx header */
- ep93xx_register_pwm(0, 1);
- }
-diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
-index b743312..89026bf 100644
---- a/drivers/misc/Kconfig
-+++ b/drivers/misc/Kconfig
-@@ -395,4 +395,25 @@ source "drivers/misc/eeprom/Kconfig"
- source "drivers/misc/cb710/Kconfig"
- source "drivers/misc/iwmc3200top/Kconfig"
-
-+config TS72XX_MAX197
-+ tristate "TS-72xx MAX197 support"
-+ depends on ARCH_EP93XX && MACH_TS72XX && SYSFS
-+ help
-+ Say Y here if to include support for the MAX197 A/D converter
-+ optionally included on Technologic Systems SBCs.
-+ Default acquisition range is [0..5V].
-+
-+ To compile this driver as a module, choose M here: the
-+ module will be called ts72xx_max197.
-+
-+if TS72XX_MAX197
-+
-+config TS72XX_MAX197_AVERAGE
-+ bool "Average measurement"
-+ help
-+ Say Y here to enable making average measurement. Default is 1.
-+ See /sys/module/ts72xx_max197/parameters/average file.
-+
-+endif # TS72XX_MAX197
-+
- endif # MISC_DEVICES
-diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile
-index 42eab95..431ef19 100644
---- a/drivers/misc/Makefile
-+++ b/drivers/misc/Makefile
-@@ -26,6 +26,7 @@ obj-$(CONFIG_HP_ILO) += hpilo.o
- obj-$(CONFIG_ISL29003) += isl29003.o
- obj-$(CONFIG_SENSORS_TSL2550) += tsl2550.o
- obj-$(CONFIG_EP93XX_PWM) += ep93xx_pwm.o
-+obj-$(CONFIG_TS72XX_MAX197) += ts72xx_max197.o
- obj-$(CONFIG_DS1682) += ds1682.o
- obj-$(CONFIG_TI_DAC7512) += ti_dac7512.o
- obj-$(CONFIG_C2PORT) += c2port/
-diff --git a/drivers/misc/ts72xx_max197.c b/drivers/misc/ts72xx_max197.c
-new file mode 100644
-index 0000000..4121ae5
---- /dev/null
-+++ b/drivers/misc/ts72xx_max197.c
-@@ -0,0 +1,235 @@
-+/*
-+ * TS-72XX max197 driver for Technologic Systems boards.
-+ *
-+ * Voltage conversion is taken from adc_logger from Jim Jackson.
-+ * (c) Copyright 2008 Matthieu Crapet <mcrapet@gmail.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.
-+ */
-+
-+#include <linux/kernel.h>
-+#include <linux/module.h>
-+#include <linux/platform_device.h>
-+#include <asm/io.h>
-+
-+#define DRV_VERSION "0.2"
-+#define PFX "ts72xx_max197: "
-+
-+#define MAX197_RANGE_5_5 1 // [- 5V + 5V]
-+#define MAX197_RANGE_10_10 3 // [-10V +10V]
-+#define MAX197_RANGE_0_5 0 // [ 0V + 5V]
-+#define MAX197_RANGE_0_10 2 // [ 0V +10V]
-+
-+#define MAX197_RESET_CHANNEL_CONF(x) (~(3 << (2*(x))))
-+#define MAX197_SET_CHANNEL_CONF(x, range) ((range) << (2*(x)))
-+#define MAX197_GET_CHANNEL_CONF(x, conf) (((conf) >> (2*(x))) & 3)
-+
-+struct max197_config
-+{
-+ void __iomem *control_and_data_register;
-+ void __iomem *busy_bit_register;
-+ unsigned int channels; // two bits per channels
-+};
-+
-+static struct max197_config conf;
-+#ifdef CONFIG_TS72XX_MAX197_AVERAGE
-+static ushort average = 1;
-+#endif
-+
-+static ssize_t max197_acquire(struct device *dev,
-+ struct device_attribute *attr, char *buf)
-+{
-+ int range, n;
-+ signed short val;
-+#ifdef CONFIG_TS72XX_MAX197_AVERAGE
-+ int i, total;
-+#endif
-+
-+ n = attr->attr.name[2] - 0x31;
-+ range = MAX197_GET_CHANNEL_CONF(n, conf.channels);
-+
-+#ifdef CONFIG_TS72XX_MAX197_AVERAGE
-+ val = 0; total = 0;
-+ for (i = 0; i < average; i++) {
-+#endif
-+
-+ __raw_writeb(((range << 3) | n | 0x40) & 0xFF,
-+ conf.control_and_data_register);
-+ while (__raw_readb(conf.busy_bit_register) & 0x80);
-+ val = __raw_readw(conf.control_and_data_register);
-+
-+ //printk(PFX "%hd/%hd: 0x%04X\n", i+1, average, val);
-+
-+#ifdef CONFIG_TS72XX_MAX197_AVERAGE
-+ total += val;
-+ }
-+ total /= average;
-+ val = (signed short)total;
-+#endif
-+
-+ /* We want three digit precision */
-+ switch (range) {
-+ case MAX197_RANGE_0_5:
-+ val = ((val * 50000/4096)+5)/10;
-+ break;
-+ case MAX197_RANGE_5_5:
-+ case MAX197_RANGE_0_10:
-+ val = ((val * 100000/4096)+5)/10;
-+ break;
-+ case MAX197_RANGE_10_10:
-+ val = ((val * 200000/4096)+5)/10;
-+ break;
-+ }
-+
-+ return sprintf(buf, "%d.%03ld\n", val/1000, abs(val%1000));
-+}
-+
-+static ssize_t max197_configure(struct device *dev,
-+ struct device_attribute *attr, const char *buf, size_t len)
-+{
-+ int n = attr->attr.name[2] - 0x31;
-+
-+ long val = simple_strtol(buf, NULL, 10);
-+ switch (val) {
-+ case 10:
-+ conf.channels &= MAX197_RESET_CHANNEL_CONF(n);
-+ conf.channels |= MAX197_SET_CHANNEL_CONF(n, MAX197_RANGE_0_10);
-+ break;
-+ case 5:
-+ conf.channels &= MAX197_RESET_CHANNEL_CONF(n);
-+ conf.channels |= MAX197_SET_CHANNEL_CONF(n, MAX197_RANGE_0_5);
-+ break;
-+ case -10:
-+ conf.channels &= MAX197_RESET_CHANNEL_CONF(n);
-+ conf.channels |= MAX197_SET_CHANNEL_CONF(n, MAX197_RANGE_10_10);
-+ break;
-+ case -5:
-+ conf.channels &= MAX197_RESET_CHANNEL_CONF(n);
-+ conf.channels |= MAX197_SET_CHANNEL_CONF(n, MAX197_RANGE_5_5);
-+ break;
-+
-+ default:
-+ return -EINVAL;
-+ }
-+
-+ return len;
-+}
-+
-+static DEVICE_ATTR(ch1, S_IWUSR | S_IRUGO, max197_acquire, max197_configure);
-+static DEVICE_ATTR(ch2, S_IWUSR | S_IRUGO, max197_acquire, max197_configure);
-+static DEVICE_ATTR(ch3, S_IWUSR | S_IRUGO, max197_acquire, max197_configure);
-+static DEVICE_ATTR(ch4, S_IWUSR | S_IRUGO, max197_acquire, max197_configure);
-+static DEVICE_ATTR(ch5, S_IWUSR | S_IRUGO, max197_acquire, max197_configure);
-+static DEVICE_ATTR(ch6, S_IWUSR | S_IRUGO, max197_acquire, max197_configure);
-+static DEVICE_ATTR(ch7, S_IWUSR | S_IRUGO, max197_acquire, max197_configure);
-+static DEVICE_ATTR(ch8, S_IWUSR | S_IRUGO, max197_acquire, max197_configure);
-+
-+static struct attribute *max197_attributes[] = {
-+ &dev_attr_ch1.attr,
-+ &dev_attr_ch2.attr,
-+ &dev_attr_ch3.attr,
-+ &dev_attr_ch4.attr,
-+ &dev_attr_ch5.attr,
-+ &dev_attr_ch6.attr,
-+ &dev_attr_ch7.attr,
-+ &dev_attr_ch8.attr,
-+ NULL
-+};
-+
-+static struct attribute_group max197_group = {
-+ .attrs = max197_attributes,
-+ //.name = "channels",
-+};
-+
-+static __devinit int ts72xx_max197_probe(struct platform_device *pdev)
-+{
-+ int err = 0;
-+ struct resource *r_data, *r_busy;
-+
-+ r_data = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-+ r_busy = platform_get_resource(pdev, IORESOURCE_MEM, 1);
-+
-+ if (!r_data || !r_busy) {
-+ dev_err(&pdev->dev, "missing resource(s)\n");
-+ return -EINVAL;
-+ }
-+
-+ conf.control_and_data_register = ioremap(r_data->start, r_data->end - r_data->start + 1);
-+ if (!conf.control_and_data_register) {
-+ err = -ENODEV;
-+ goto exit;
-+ }
-+
-+ conf.busy_bit_register = ioremap(r_busy->start, r_busy->end - r_busy->start + 1);
-+ if (!conf.busy_bit_register) {
-+ err = -ENODEV;
-+ goto exit_unmap1;
-+ }
-+
-+ conf.channels =
-+ MAX197_SET_CHANNEL_CONF(0, MAX197_RANGE_0_5) |
-+ MAX197_SET_CHANNEL_CONF(1, MAX197_RANGE_0_5) |
-+ MAX197_SET_CHANNEL_CONF(2, MAX197_RANGE_0_5) |
-+ MAX197_SET_CHANNEL_CONF(3, MAX197_RANGE_0_5) |
-+ MAX197_SET_CHANNEL_CONF(4, MAX197_RANGE_0_5) |
-+ MAX197_SET_CHANNEL_CONF(5, MAX197_RANGE_0_5) |
-+ MAX197_SET_CHANNEL_CONF(6, MAX197_RANGE_0_5) |
-+ MAX197_SET_CHANNEL_CONF(7, MAX197_RANGE_0_5);
-+
-+ /* Register sysfs hooks */
-+ if ((err = sysfs_create_group(&pdev->dev.kobj, &max197_group)))
-+ goto exit_unmap2;
-+
-+ printk(PFX "TS-72xx max197 driver, v%s\n", DRV_VERSION);
-+ return 0;
-+
-+exit_unmap2:
-+ iounmap(conf.busy_bit_register);
-+exit_unmap1:
-+ iounmap(conf.control_and_data_register);
-+exit:
-+ return err;
-+}
-+
-+static int __devexit ts72xx_max197_remove(struct platform_device *pdev)
-+{
-+ sysfs_remove_group(&pdev->dev.kobj, &max197_group);
-+ iounmap(conf.busy_bit_register);
-+ iounmap(conf.control_and_data_register);
-+ return 0;
-+}
-+
-+static struct platform_driver ts72xx_max197_platform_driver = {
-+ .probe = ts72xx_max197_probe,
-+ .remove = __devexit_p(ts72xx_max197_remove),
-+ .driver = {
-+ .name = "ts72xx-max197",
-+ .owner = THIS_MODULE,
-+ },
-+};
-+
-+static int __init ts72xx_max197_init(void)
-+{
-+ return platform_driver_register(&ts72xx_max197_platform_driver);
-+}
-+
-+static void __exit ts72xx_max197_exit(void)
-+{
-+ platform_driver_unregister(&ts72xx_max197_platform_driver);
-+}
-+
-+#ifdef CONFIG_TS72XX_MAX197_AVERAGE
-+module_param(average, ushort, S_IWUSR | S_IRUGO);
-+MODULE_PARM_DESC(average, "Allow average measurement (default=1)");
-+#endif
-+
-+MODULE_AUTHOR("Matthieu Crapet <mcrapet@gmail.com>");
-+MODULE_DESCRIPTION("TS-72xx max197 driver");
-+MODULE_LICENSE("GPL");
-+MODULE_VERSION(DRV_VERSION);
-+
-+module_init(ts72xx_max197_init);
-+module_exit(ts72xx_max197_exit);
---
-1.7.0.4
-
diff --git a/recipes/linux/linux-2.6.36/ts72xx/0014-ts7200_nor_flash.patch b/recipes/linux/linux-2.6.36/ts72xx/0014-ts7200_nor_flash.patch
deleted file mode 100644
index e49e52a..0000000
--- a/recipes/linux/linux-2.6.36/ts72xx/0014-ts7200_nor_flash.patch
+++ /dev/null
@@ -1,181 +0,0 @@
-From 57271199c60faf7f9b7fab8bd8c34b0936df0bfa Mon Sep 17 00:00:00 2001
-From: Matthieu Crapet <mcrapet@gmail.com>
-Date: Sat, 19 Jun 2010 16:56:48 +0200
-Subject: [PATCH 14/24] ts7200_nor_flash
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-Deal with 8mb or 16mb NOR Flash (TS-7200 only)
-
-Signed-off-by: Petr Štetiar <ynezz@true.cz>
----
- drivers/mtd/maps/Kconfig | 15 +++++
- drivers/mtd/maps/Makefile | 1 +
- drivers/mtd/maps/ts7200_flash.c | 116 +++++++++++++++++++++++++++++++++++++++
- 3 files changed, 132 insertions(+), 0 deletions(-)
- create mode 100644 drivers/mtd/maps/ts7200_flash.c
-
-diff --git a/drivers/mtd/maps/Kconfig b/drivers/mtd/maps/Kconfig
-index 701d942..c7fd9e7 100644
---- a/drivers/mtd/maps/Kconfig
-+++ b/drivers/mtd/maps/Kconfig
-@@ -414,6 +414,21 @@ config MTD_H720X
- This enables access to the flash chips on the Hynix evaluation boards.
- If you have such a board, say 'Y'.
-
-+config MTD_TS7200_NOR
-+ tristate "CFI Flash device mapped on TS-7200"
-+ depends on MTD_CFI && MACH_TS72XX
-+ help
-+ This provides a map driver for the on-board flash of the Technologic
-+ System's TS-7200 board. The 8MB (or 16MB) flash is splitted into 3 partitions
-+ which are accessed as separate MTD devices.
-+
-+config MTD_TS7200_NOR_SIZE
-+ int "Flash size (8 or 16mb)"
-+ depends on MTD_TS7200_NOR
-+ default "8"
-+ help
-+ Enter the NOR Flash size of your TS-7200 board. Can be 8 or 16.
-+
- # This needs CFI or JEDEC, depending on the cards found.
- config MTD_PCI
- tristate "PCI MTD driver"
-diff --git a/drivers/mtd/maps/Makefile b/drivers/mtd/maps/Makefile
-index f216bb5..21f9bd8 100644
---- a/drivers/mtd/maps/Makefile
-+++ b/drivers/mtd/maps/Makefile
-@@ -55,6 +55,7 @@ obj-$(CONFIG_MTD_DMV182) += dmv182.o
- obj-$(CONFIG_MTD_PLATRAM) += plat-ram.o
- obj-$(CONFIG_MTD_INTEL_VR_NOR) += intel_vr_nor.o
- obj-$(CONFIG_MTD_BFIN_ASYNC) += bfin-async-flash.o
-+obj-$(CONFIG_MTD_TS7200_NOR) += ts7200_flash.o
- obj-$(CONFIG_MTD_RBTX4939) += rbtx4939-flash.o
- obj-$(CONFIG_MTD_VMU) += vmu-flash.o
- obj-$(CONFIG_MTD_GPIO_ADDR) += gpio-addr-flash.o
-diff --git a/drivers/mtd/maps/ts7200_flash.c b/drivers/mtd/maps/ts7200_flash.c
-new file mode 100644
-index 0000000..94fb4f4
---- /dev/null
-+++ b/drivers/mtd/maps/ts7200_flash.c
-@@ -0,0 +1,116 @@
-+/*
-+ * ts7200_flash.c - mapping for TS-7200 SBCs (8mb NOR flash)
-+ * No platform_device resource is used here. All is hardcoded.
-+ *
-+ * (c) Copyright 2006-2010 Matthieu Crapet <mcrapet@gmail.com>
-+ * Based on ts5500_flash.c by Sean Young <sean@mess.org>
-+ *
-+ * 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/module.h>
-+#include <linux/types.h>
-+#include <linux/kernel.h>
-+#include <linux/init.h>
-+#include <asm/io.h>
-+#include <asm/sizes.h>
-+#include <linux/mtd/mtd.h>
-+#include <linux/mtd/map.h>
-+#include <linux/mtd/partitions.h>
-+#include <mach/ep93xx-regs.h>
-+
-+
-+static struct mtd_info *mymtd;
-+
-+static struct map_info ts7200nor_map = {
-+ .name = "Full TS-7200 NOR flash",
-+ .size = 0, /* filled in later */
-+ .bankwidth = 2,
-+ .phys = EP93XX_CS6_PHYS_BASE,
-+};
-+
-+/*
-+ * MTD partitioning stuff
-+ */
-+#ifdef CONFIG_MTD_PARTITIONS
-+
-+#define TS7200_BOOTROM_PART_SIZE (SZ_128K)
-+#define TS7200_REDBOOT_PART_SIZE (15*SZ_128K)
-+
-+static struct mtd_partition ts7200_nor_parts[] =
-+{
-+ {
-+ .name = "TS-BOOTROM",
-+ .offset = 0,
-+ .size = TS7200_BOOTROM_PART_SIZE,
-+ .mask_flags = MTD_WRITEABLE, /* force read-only */
-+ },
-+ {
-+ .name = "RootFS",
-+ .offset = MTDPART_OFS_APPEND,
-+ .size = 0, /* filled in later */
-+ },
-+ {
-+ .name = "Redboot",
-+ .offset = MTDPART_OFS_APPEND,
-+ .size = MTDPART_SIZ_FULL, /* up to the end */
-+ }
-+};
-+#endif
-+
-+static int __init ts7200_nor_init(void)
-+{
-+ if (CONFIG_MTD_TS7200_NOR_SIZE <= 8)
-+ ts7200nor_map.size = SZ_8M;
-+ else
-+ ts7200nor_map.size = SZ_16M;
-+
-+ printk(KERN_NOTICE "TS-7200 flash mapping: %ldmo at 0x%x\n",
-+ ts7200nor_map.size / SZ_1M, ts7200nor_map.phys);
-+
-+ ts7200nor_map.virt = ioremap(ts7200nor_map.phys, ts7200nor_map.size - 1);
-+ if (!ts7200nor_map.virt) {
-+ printk("ts7200_flash: failed to ioremap\n");
-+ return -EIO;
-+ }
-+
-+ simple_map_init(&ts7200nor_map);
-+ mymtd = do_map_probe("cfi_probe", &ts7200nor_map);
-+ if (mymtd) {
-+ mymtd->owner = THIS_MODULE;
-+ add_mtd_device(mymtd);
-+ #ifdef CONFIG_MTD_PARTITIONS
-+ ts7200_nor_parts[1].size = ts7200nor_map.size - TS7200_REDBOOT_PART_SIZE;
-+ return add_mtd_partitions(mymtd, ts7200_nor_parts, ARRAY_SIZE(ts7200_nor_parts));
-+ #else
-+ return 0;
-+ #endif
-+ }
-+
-+ iounmap(ts7200nor_map.virt);
-+ return -ENXIO;
-+}
-+
-+static void __exit ts7200_nor_exit(void)
-+{
-+ if (mymtd) {
-+ del_mtd_device(mymtd);
-+ map_destroy(mymtd);
-+ mymtd = NULL;
-+ }
-+ if (ts7200nor_map.virt) {
-+ iounmap(ts7200nor_map.virt);
-+ ts7200nor_map.virt = 0;
-+ }
-+}
-+
-+module_init(ts7200_nor_init);
-+module_exit(ts7200_nor_exit);
-+
-+MODULE_LICENSE("GPL");
-+MODULE_AUTHOR("Matthieu Crapet <mcrapet@gmail.com>");
-+MODULE_DESCRIPTION("MTD map driver for TS-7200 board");
-+MODULE_VERSION("0.1");
---
-1.7.0.4
-
diff --git a/recipes/linux/linux-2.6.36/ts72xx/0015-ts72xx_sdcard.patch b/recipes/linux/linux-2.6.36/ts72xx/0015-ts72xx_sdcard.patch
deleted file mode 100644
index c290172..0000000
--- a/recipes/linux/linux-2.6.36/ts72xx/0015-ts72xx_sdcard.patch
+++ /dev/null
@@ -1,3298 +0,0 @@
-From 66c9687c9f4530e301fb8ba14b657b3f4ee3c9c6 Mon Sep 17 00:00:00 2001
-From: Matthieu Crapet <mcrapet@gmail.com>
-Date: Sun, 20 Jun 2010 10:46:15 +0200
-Subject: [PATCH 15/24] ts72xx_sdcard
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-SD Card support for TS-7260. Device name is "tssda".
-Patch based on work of Breton Saunders:
-http://tech.groups.yahoo.com/group/ts-7000/message/15787
-http://tech.groups.yahoo.com/group/ts-7000/message/16028
-
-Signed-off-by: Petr Štetiar <ynezz@true.cz>
----
- arch/arm/mach-ep93xx/ts72xx.c | 24 +
- drivers/block/Kconfig | 7 +
- drivers/block/Makefile | 2 +
- drivers/block/sdcore2.c | 2391 +++++++++++++++++++++++++++++++++++++++++
- drivers/block/sdcore2.h | 372 +++++++
- drivers/block/tssdcard.c | 415 +++++++
- 6 files changed, 3211 insertions(+), 0 deletions(-)
- create mode 100644 drivers/block/sdcore2.c
- create mode 100644 drivers/block/sdcore2.h
- create mode 100644 drivers/block/tssdcard.c
-
-diff --git a/arch/arm/mach-ep93xx/ts72xx.c b/arch/arm/mach-ep93xx/ts72xx.c
-index 96a4d54..c99f112 100644
---- a/arch/arm/mach-ep93xx/ts72xx.c
-+++ b/arch/arm/mach-ep93xx/ts72xx.c
-@@ -233,6 +233,29 @@ static void __init ts72xx_register_flash(void)
- }
-
- /*************************************************************************
-+ * SD Card (TS-7260 only)
-+ *************************************************************************/
-+
-+static struct resource ts72xx_sdcard_resource = {
-+ .start = TS7260_SDCARD_PHYS_BASE,
-+ .end = TS7260_SDCARD_PHYS_BASE + 0x20,
-+ .flags = IORESOURCE_MEM,
-+};
-+
-+static struct platform_device ts72xx_sdcard = {
-+ .name = "ts72xx-sdcard",
-+ .id = 0,
-+ .num_resources = 1,
-+ .resource = &ts72xx_sdcard_resource,
-+};
-+
-+static void __init ts72xx_register_sdcard(void)
-+{
-+ if (board_is_ts7260() || board_is_ts7400() || board_is_ts7300())
-+ platform_device_register(&ts72xx_sdcard);
-+}
-+
-+/*************************************************************************
- * RTC
- *************************************************************************/
- static unsigned char ts72xx_rtc_readbyte(unsigned long addr)
-@@ -333,6 +356,7 @@ static void __init ts72xx_init_machine(void)
- {
- ep93xx_init_devices();
- ts72xx_register_flash();
-+ ts72xx_register_sdcard();
- platform_device_register(&ts72xx_rtc_device);
- platform_device_register(&ts72xx_wdt_device);
-
-diff --git a/drivers/block/Kconfig b/drivers/block/Kconfig
-index de27768..80985f8 100644
---- a/drivers/block/Kconfig
-+++ b/drivers/block/Kconfig
-@@ -488,4 +488,11 @@ config BLK_DEV_HD
-
- If unsure, say N.
-
-+config BLK_DEV_TS72XX_SDCARD
-+ tristate "TS-72XX SD Card support"
-+ depends on ARCH_EP93XX && MACH_TS72XX
-+ help
-+ This option enables support SD Card control on Technologic Systems
-+ TS-7260 SBC.
-+
- endif # BLK_DEV
-diff --git a/drivers/block/Makefile b/drivers/block/Makefile
-index aff5ac9..a4d0579 100644
---- a/drivers/block/Makefile
-+++ b/drivers/block/Makefile
-@@ -34,8 +34,10 @@ obj-$(CONFIG_VIODASD) += viodasd.o
- obj-$(CONFIG_BLK_DEV_SX8) += sx8.o
- obj-$(CONFIG_BLK_DEV_UB) += ub.o
- obj-$(CONFIG_BLK_DEV_HD) += hd.o
-+obj-$(CONFIG_BLK_DEV_TS72XX_SDCARD) += ts72xx_sdcard.o
-
- obj-$(CONFIG_XEN_BLKDEV_FRONTEND) += xen-blkfront.o
- obj-$(CONFIG_BLK_DEV_DRBD) += drbd/
-
- swim_mod-objs := swim.o swim_asm.o
-+ts72xx_sdcard-objs := tssdcard.o sdcore2.o
-diff --git a/drivers/block/sdcore2.c b/drivers/block/sdcore2.c
-new file mode 100644
-index 0000000..6dadee1
---- /dev/null
-+++ b/drivers/block/sdcore2.c
-@@ -0,0 +1,2391 @@
-+/*
-+ * Copyright (c) 2006-2009, Technologic Systems
-+ * All rights reserved.
-+ */
-+
-+/*
-+ * This code is 100% operating system/CPU independent-- not a single global
-+ * reference, external symbol, or #include is required. Centric upon one data
-+ * structure "struct sdcore". OS-specific callbacks for things like DMA
-+ * acceleration and sleeping are defined by function pointers to OS-specific
-+ * code in the struct sdcore. Minimally requires the os_sleep() callback to be
-+ * implemented for proper SD card initialization and a pointer to start
-+ * of SD card registers. Auto-determines TS SD core version. All other
-+ * callback functions may be left NULL-- they are only to allow speed/CPU
-+ * utilization improvements.
-+ *
-+ * 3 main public functions - sdreset(), sdread() and sdwrite(). sdreset()
-+ * returns card size. OS specific shim is required to turn this
-+ * simple API into the complicated, constantly changing, hacker "designed"
-+ * horrible excuses for abstraction, block driver APIs required in other
-+ * "modern" operating systems.
-+ *
-+ * Not all SD cards over the years have followed spec perfectly -- many
-+ * don't even check CRC's on the CMD or DAT busses and some have problems
-+ * (lock up) when reading/writing the last sectors with SD read/write multiple
-+ * commands.
-+ *
-+ * The TS SD hardware cores are not much more than GPIO bit-bang cores with
-+ * a few well-placed hardware optimizations to achieve reasonable
-+ * performance goals. In the roughly 2000 lines of code that follow, there
-+ * is support for all distinct TS hardware SD cores on PPC and ARM platforms,
-+ * a generic (private) SD command layer, sdcmd(), and SD flash card
-+ * (public) routines for initialization + read/write + some SD security
-+ * features.
-+ *
-+ */
-+
-+/* Register offset definitions. TS-SDCORE is 4 regs total. */
-+#define SDCMD 0
-+#define SDGPIO 0 /* version 2 register */
-+#define SDDAT 1
-+#define SDSTAT2 1
-+#define SDSTATE 2
-+#define SDCTRL 3
-+#define SDDAT2 4
-+#define SDCMD2 8
-+#define SDCTRL2 12
-+#define SDLUN2 2
-+
-+struct sdcore {
-+ /* virtual address of SD block register start, to be filled in
-+ * by client code before calling any sdcore functions.
-+ */
-+ unsigned int sd_regstart;
-+
-+ /* public bits for sd_state bitfield, can be read from client code.
-+ * Do not write! Other bits are used internally.
-+ */
-+ #define SDDAT_RX (1<<0)
-+ #define SDDAT_TX (1<<1)
-+ #define SDCMD_RX (1<<2)
-+ #define SDCMD_TX (1<<3)
-+ unsigned int sd_state;
-+
-+ /* Erase hint for subsequent sdwrite() call, used to optimize
-+ * write throughput on multi-sector writes by pre-erasing this
-+ * many sectors. XXX: this doesn't have much benefit on most SDs
-+ */
-+ unsigned int sd_erasehint;
-+
-+ /* Following this comment are 3 function pointer declarations to
-+ * OS helper functions. The 'os_arg' member is passed as the
-+ * first argument to the helpers and should be set by
-+ * client code before issueing sdreset()
-+ *
-+ * os_dmastream(os_arg, buf, buflen)
-+ * This function should look at sd_state and set up and run an
-+ * appropriate DMA transfer. If buf is NULL, callee doesn't care
-+ * about the actual data sent/received and helper function
-+ * can do whatever it wants. Should return 0 when DMA transfer was
-+ * run and completed successfully. If this function pointer is
-+ * NULL, PIO methods of transfer will be used instead of DMA.
-+ *
-+ * os_dmaprep(os_arg, buf, buflen)
-+ * This function is used to prepare an area of memory for a possible
-+ * DMA transfer. This function is called once per distinct buffer
-+ * passed in. After this function is called, os_dmastream() may be
-+ * called one or more times (for sequential addresses) on subregions
-+ * of the address range passed here. Should write-back or invalidate
-+ * L1 cache lines and possibly look up physical addresses for buf
-+ * passed in if I/O buffers. If 'os_dmaprep' is set to NULL, function
-+ * call will not happen. (though os_dmastream() calls may still)
-+ *
-+ * os_delay(os_arg, microseconds)
-+ * This function is supposed to delay or stall the processor for
-+ * the passed in value number of microseconds.
-+ */
-+ void *os_arg;
-+ int (*os_dmastream)(void *, unsigned char *, unsigned int);
-+ void (*os_dmaprep)(void *, unsigned char *, unsigned int);
-+ void (*os_delay)(void *, unsigned int);
-+ void (*os_irqwait)(void *, unsigned int);
-+ int (*os_powerok)(void *);
-+ int (*os_timeout)(void *);
-+ int (*os_reset_timeout)(void *);
-+
-+ /* If the SD card last successfully reset is write protected, this
-+ * member will be non-zero.
-+ */
-+ unsigned int sd_wprot;
-+
-+ /* If this card may have been already initialized by TS-SDBOOT, place
-+ * the magic token it placed in the EP93xx SYSCON ScratchReg1 here
-+ * to avoid re-initialization.
-+ */
-+ unsigned int sdboot_token;
-+
-+ /* CRC hint for subsequent sdwrite() call, used to optimize
-+ * write throughput while using DMA by pre-calculating CRC's for
-+ * next write
-+ */
-+ unsigned char *sd_crchint;
-+
-+ /* The block size of the memory device. Normally 512, but can be 1024
-+ * for larger cards
-+ */
-+ unsigned int sd_blocksize;
-+
-+ /* Password for auto-unlocking in sdreset()
-+ */
-+ unsigned char *sd_pwd;
-+
-+ /* If the SD card was password locked, this will be non-zero.
-+ */
-+ unsigned int sd_locked;
-+
-+ /* Whether or not writes can be parked.
-+ */
-+ unsigned int sd_writeparking;
-+
-+ /* Logical unit number. Some SD cores will have multiple card slots.
-+ */
-+ unsigned int sd_lun;
-+
-+ /* The rest of these members are for private internal use and should
-+ * not be of interest to client code.
-+ */
-+ unsigned int sd_rcaarg;
-+ unsigned int sd_csd[17];
-+ unsigned int sd_crcseq;
-+ unsigned short sd_crcs[4];
-+ unsigned int sd_crctmp[4];
-+ unsigned int sd_timeout;
-+ unsigned int parked_sector;
-+ unsigned int hw_version;
-+ unsigned char sd_scr[8];
-+ unsigned int sd_sz;
-+};
-+
-+/* For sdreadv() / sdwritev() */
-+struct sdiov {
-+ unsigned char *sdiov_base;
-+ unsigned int sdiov_nsect;
-+};
-+
-+int sdreset(struct sdcore *);
-+int sdread(struct sdcore *, unsigned int, unsigned char *, int);
-+int sdwrite(struct sdcore *, unsigned int, unsigned char *, int);
-+int sdreadv(struct sdcore *, unsigned int, struct sdiov *, int);
-+int sdwritev(struct sdcore *, unsigned int, struct sdiov *, int);
-+int sdsetwprot(struct sdcore *, unsigned int);
-+#define SDLOCK_UNLOCK 0
-+#define SDLOCK_SETPWD 1
-+#define SDLOCK_CLRPWD 2
-+#define SDLOCK_ERASE 8
-+#ifndef SD_NOLOCKSUPPORT
-+int sdlockctl(struct sdcore *, unsigned int, unsigned char *, unsigned char *);
-+#endif
-+
-+/*
-+ * Everything below here is secret! This code shouldn't have to change
-+ * even for different OS.
-+ */
-+
-+const static unsigned short crc16tbl[256] = {
-+ 0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7,
-+ 0x8108, 0x9129, 0xa14a, 0xb16b, 0xc18c, 0xd1ad, 0xe1ce, 0xf1ef,
-+ 0x1231, 0x0210, 0x3273, 0x2252, 0x52b5, 0x4294, 0x72f7, 0x62d6,
-+ 0x9339, 0x8318, 0xb37b, 0xa35a, 0xd3bd, 0xc39c, 0xf3ff, 0xe3de,
-+ 0x2462, 0x3443, 0x0420, 0x1401, 0x64e6, 0x74c7, 0x44a4, 0x5485,
-+ 0xa56a, 0xb54b, 0x8528, 0x9509, 0xe5ee, 0xf5cf, 0xc5ac, 0xd58d,
-+ 0x3653, 0x2672, 0x1611, 0x0630, 0x76d7, 0x66f6, 0x5695, 0x46b4,
-+ 0xb75b, 0xa77a, 0x9719, 0x8738, 0xf7df, 0xe7fe, 0xd79d, 0xc7bc,
-+ 0x48c4, 0x58e5, 0x6886, 0x78a7, 0x0840, 0x1861, 0x2802, 0x3823,
-+ 0xc9cc, 0xd9ed, 0xe98e, 0xf9af, 0x8948, 0x9969, 0xa90a, 0xb92b,
-+ 0x5af5, 0x4ad4, 0x7ab7, 0x6a96, 0x1a71, 0x0a50, 0x3a33, 0x2a12,
-+ 0xdbfd, 0xcbdc, 0xfbbf, 0xeb9e, 0x9b79, 0x8b58, 0xbb3b, 0xab1a,
-+ 0x6ca6, 0x7c87, 0x4ce4, 0x5cc5, 0x2c22, 0x3c03, 0x0c60, 0x1c41,
-+ 0xedae, 0xfd8f, 0xcdec, 0xddcd, 0xad2a, 0xbd0b, 0x8d68, 0x9d49,
-+ 0x7e97, 0x6eb6, 0x5ed5, 0x4ef4, 0x3e13, 0x2e32, 0x1e51, 0x0e70,
-+ 0xff9f, 0xefbe, 0xdfdd, 0xcffc, 0xbf1b, 0xaf3a, 0x9f59, 0x8f78,
-+ 0x9188, 0x81a9, 0xb1ca, 0xa1eb, 0xd10c, 0xc12d, 0xf14e, 0xe16f,
-+ 0x1080, 0x00a1, 0x30c2, 0x20e3, 0x5004, 0x4025, 0x7046, 0x6067,
-+ 0x83b9, 0x9398, 0xa3fb, 0xb3da, 0xc33d, 0xd31c, 0xe37f, 0xf35e,
-+ 0x02b1, 0x1290, 0x22f3, 0x32d2, 0x4235, 0x5214, 0x6277, 0x7256,
-+ 0xb5ea, 0xa5cb, 0x95a8, 0x8589, 0xf56e, 0xe54f, 0xd52c, 0xc50d,
-+ 0x34e2, 0x24c3, 0x14a0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405,
-+ 0xa7db, 0xb7fa, 0x8799, 0x97b8, 0xe75f, 0xf77e, 0xc71d, 0xd73c,
-+ 0x26d3, 0x36f2, 0x0691, 0x16b0, 0x6657, 0x7676, 0x4615, 0x5634,
-+ 0xd94c, 0xc96d, 0xf90e, 0xe92f, 0x99c8, 0x89e9, 0xb98a, 0xa9ab,
-+ 0x5844, 0x4865, 0x7806, 0x6827, 0x18c0, 0x08e1, 0x3882, 0x28a3,
-+ 0xcb7d, 0xdb5c, 0xeb3f, 0xfb1e, 0x8bf9, 0x9bd8, 0xabbb, 0xbb9a,
-+ 0x4a75, 0x5a54, 0x6a37, 0x7a16, 0x0af1, 0x1ad0, 0x2ab3, 0x3a92,
-+ 0xfd2e, 0xed0f, 0xdd6c, 0xcd4d, 0xbdaa, 0xad8b, 0x9de8, 0x8dc9,
-+ 0x7c26, 0x6c07, 0x5c64, 0x4c45, 0x3ca2, 0x2c83, 0x1ce0, 0x0cc1,
-+ 0xef1f, 0xff3e, 0xcf5d, 0xdf7c, 0xaf9b, 0xbfba, 0x8fd9, 0x9ff8,
-+ 0x6e17, 0x7e36, 0x4e55, 0x5e74, 0x2e93, 0x3eb2, 0x0ed1, 0x1ef0,
-+};
-+
-+const static unsigned char destagger[256] = {
-+ 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1,
-+ 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3,
-+ 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1,
-+ 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3,
-+ 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1,
-+ 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3,
-+ 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1,
-+ 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3,
-+ 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1,
-+ 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3,
-+ 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1,
-+ 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3,
-+ 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1,
-+ 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3,
-+ 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1,
-+ 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3,
-+};
-+
-+#ifndef MAX_SDCORES
-+#define MAX_SDCORES 64
-+#endif
-+static struct sdcore *sdcores[MAX_SDCORES];
-+
-+static unsigned int crc7(unsigned int, const unsigned int *, unsigned int);
-+static int sdreset2(struct sdcore *);
-+static int version(struct sdcore *);
-+static int sdfastinit(struct sdcore *sd);
-+static int sdcmd2(struct sdcore *, unsigned short, unsigned int,
-+ unsigned int *, unsigned char **);
-+static int sdcmd(struct sdcore *, unsigned short, unsigned int,
-+ unsigned int *, unsigned char **);
-+static void mkcommand(unsigned int, unsigned int, unsigned int *);
-+static int stop(struct sdcore *);
-+static int stop2(struct sdcore *);
-+static int sdread2(struct sdcore *, unsigned int, unsigned char *, int)
-+ __attribute__ ((unused));
-+static int do_read2(struct sdcore *, unsigned int, struct sdiov *,
-+ unsigned int);
-+static int do_read(struct sdcore *, unsigned int, struct sdiov *,
-+ unsigned int);
-+static int do_write(struct sdcore *, unsigned int, struct sdiov *,
-+ unsigned int);
-+static int do_write2(struct sdcore *, unsigned int, struct sdiov *,
-+ unsigned int);
-+static int sdsetwprot2(struct sdcore *, unsigned int);
-+#ifndef SD_NOLOCKSUPPORT
-+static int sdlockctl2(struct sdcore *, unsigned int, unsigned char *,
-+ unsigned char *);
-+#endif
-+
-+#ifndef SDPOKE8
-+# define SDPOKE8(sd, x, y) \
-+ *(volatile unsigned char *)((sd)->sd_regstart + (x)) = (y)
-+#endif
-+#ifndef SDPOKE32
-+# define SDPOKE32(sd, x, y) \
-+ *(volatile unsigned int *)((sd)->sd_regstart + (x)) = (y)
-+#endif
-+#ifndef SDPOKE16
-+# define SDPOKE16(sd, x, y) \
-+ *(volatile unsigned short *)((sd)->sd_regstart + (x)) = (y)
-+#endif
-+#ifndef SDPEEK8
-+# define SDPEEK8(sd, x) *(volatile unsigned char *)((sd)->sd_regstart + (x))
-+#endif
-+#ifndef SDPEEK32
-+# define SDPEEK32(sd, x) *(volatile unsigned int *)((sd)->sd_regstart + (x))
-+#endif
-+#ifndef SDPEEK16
-+# define SDPEEK16(sd, x) *(volatile unsigned short *)((sd)->sd_regstart + (x))
-+#endif
-+
-+#define S_DUMMY_CLK 0
-+#define S_SEND_CMD 1
-+#define S_WAIT_RESP 2
-+#define S_RX_RESP 3
-+#define S_WAIT_BUSY 4
-+#define S_TX_WRITE 5
-+#define S_CRC_CHECK 6
-+#define S_OFF 7
-+
-+#define TYPE_SHORTRESP 2
-+#define TYPE_LONGRESP 3
-+#define TYPE_BSYRESP 4
-+#define TYPE_NORESP 1
-+#define TYPE_RXDAT 0
-+#define TYPE_TXDAT 5
-+#define TYPE_ABORT 6
-+#define TYPE_RXDAT_IGNRESP 7
-+
-+#define CMD(idx, type) (0x40 | (idx) | ((type)<<8))
-+
-+#define CMD_GO_IDLE_STATE CMD(0, TYPE_NORESP)
-+#define CMD_ALL_SEND_CID CMD(2, TYPE_LONGRESP)
-+#define CMD_SEND_RELATIVE_ADDR CMD(3, TYPE_SHORTRESP)
-+#define CMD_SWITCH_FUNC CMD(6, TYPE_RXDAT)
-+#define CMD_SWITCH_FUNC2 CMD(6, TYPE_RXDAT_IGNRESP)
-+#define CMD_SELECT_CARD CMD(7, TYPE_BSYRESP)
-+#define CMD_DESELECT_CARD CMD(7, TYPE_NORESP)
-+#define CMD_SEND_IF_COND CMD(8, TYPE_SHORTRESP)
-+#define CMD_SEND_CSD CMD(9, TYPE_LONGRESP)
-+#define CMD_PROGRAM_CSD CMD(27, TYPE_TXDAT)
-+#define CMD_SET_BLOCKLEN CMD(16, TYPE_SHORTRESP)
-+#define CMD_LOCK_UNLOCK CMD(42, TYPE_TXDAT)
-+#define CMD_APP_CMD CMD(55, TYPE_SHORTRESP)
-+#define CMD_READ_SINGLE_BLOCK CMD(17, TYPE_RXDAT)
-+#define CMD_READ_MULTIPLE_BLOCK CMD(18, TYPE_RXDAT)
-+#define CMD_READ_MULTIPLE_BLOCK2 CMD(18, TYPE_RXDAT_IGNRESP)
-+#define CMD_STOP_TRANSMISSION CMD(12, TYPE_ABORT)
-+#define CMD_SEND_STATUS CMD(13, TYPE_SHORTRESP)
-+#define CMD_WRITE_BLOCK CMD(24, TYPE_TXDAT)
-+#define CMD_WRITE_MULTIPLE_BLOCK CMD(25, TYPE_TXDAT)
-+
-+#define ACMD_SD_SEND_OP_COND CMD(41, TYPE_SHORTRESP)
-+#define ACMD_SET_CLR_CARD_DETECT CMD(42, TYPE_SHORTRESP)
-+#define ACMD_SET_BUS_WIDTH CMD(6, TYPE_SHORTRESP)
-+#define ACMD_SET_WR_BLK_ERASE_COUNT CMD(23, TYPE_SHORTRESP)
-+#define ACMD_SEND_NUM_WR_BLOCKS CMD(22, TYPE_RXDAT)
-+#define ACMD_SEND_SCR CMD(51, TYPE_RXDAT)
-+#define ACMD_SEND_SCR2 CMD(51, TYPE_RXDAT_IGNRESP)
-+
-+/* Private bits for struct sdcore, sd_state member */
-+#define DATSSP_NOCRC (1<<4)
-+#define DATSSP_4BIT (1<<5)
-+#define SD_HC (1<<6)
-+#define SD_HISPEED (1<<7)
-+#define SD_LOSPEED (1<<8)
-+#define SD_SELECTED (1<<9)
-+#define SD_RESET (1<<10)
-+
-+#define NULL ((void *)0)
-+
-+static void remember_sdcore(struct sdcore *sd) {
-+ int i, newlun = 0;
-+
-+ for (i = 0; i < sizeof(sdcores); i++) {
-+ if (sdcores[i] == NULL) {
-+ /* new core, first reset */
-+ sdcores[i] = sd;
-+ /* core was almost definitely power-cycled on prev lun
-+ * sdreset2(), so we don't need to have the sdreset2()
-+ * do it again.
-+ */
-+ if (newlun) sd->sd_state = SD_RESET;
-+ break;
-+ } else if (sdcores[i]->sd_regstart == sd->sd_regstart) {
-+ newlun = 1;
-+ if (sdcores[i]->sd_lun == sd->sd_lun) {
-+ sdcores[i] = sd;
-+ break;
-+ }
-+ }
-+ }
-+}
-+
-+static int activate(struct sdcore *sd) {
-+ int i;
-+
-+ /* Are we already selected? */
-+ if ((sd->sd_state & (SD_SELECTED|SD_RESET)) == SD_SELECTED)
-+ return 0;
-+
-+ /* Find currently activated SD slot for this HW core */
-+ for (i = 0; i < sizeof(sdcores); i++) {
-+ if (sdcores[i] == NULL) break;
-+ if (sdcores[i]->sd_regstart == sd->sd_regstart &&
-+ sdcores[i]->sd_state & SD_SELECTED) break;
-+ }
-+
-+ /* Stop whatever parked transfer it has going on. */
-+ if (sdcores[i]) {
-+ stop2(sdcores[i]);
-+ sdcores[i]->sd_state &= ~SD_SELECTED;
-+ }
-+
-+ /* Change clock routing, mark us as selected */
-+#ifdef BIGENDIAN
-+ SDPOKE16(sd, SDLUN2, sd->sd_lun << 8);
-+#else
-+ SDPOKE16(sd, SDLUN2, sd->sd_lun);
-+#endif
-+
-+ /* Change clock frequency */
-+ if (sd->sd_state & SD_HISPEED) SDPOKE8(sd, SDSTAT2, 0x38);
-+ else SDPOKE8(sd, SDSTAT2, 0x18);
-+
-+ sd->sd_state |= SD_SELECTED;
-+ if (sd->sd_state & SD_RESET) return 1;
-+ else return 0;
-+
-+}
-+
-+inline static unsigned short
-+crc16_acc(unsigned short crc, unsigned int b)
-+{
-+ return (crc << 8) ^ crc16tbl[(crc >> 8) ^ b];
-+}
-+
-+static void sd_initcrc(struct sdcore *sd)
-+{
-+ int i;
-+
-+ for (i = 0; i < 4; i++) {
-+ sd->sd_crctmp[i] = 0;
-+ sd->sd_crcs[i] = 0;
-+ }
-+ sd->sd_crcseq = 6;
-+}
-+
-+static void sd_1bit_feedcrc(struct sdcore *sd, unsigned int dat)
-+{
-+ sd->sd_crcs[0] = crc16_acc(sd->sd_crcs[0], dat);
-+}
-+
-+static void sd_4bit_feedcrc(struct sdcore *sd, unsigned int dat)
-+{
-+ unsigned int a = 0, b = 0, c = 0, d = 0;
-+ unsigned int shift = (sd->sd_crcseq & 0x7);
-+
-+ a = sd->sd_crctmp[0];
-+ b = sd->sd_crctmp[1];
-+ c = sd->sd_crctmp[2];
-+ d = sd->sd_crctmp[3];
-+
-+ a |= destagger[dat] << shift;
-+ dat >>= 1;
-+ b |= destagger[dat] << shift;
-+ dat >>= 1;
-+ c |= destagger[dat] << shift;
-+ dat >>= 1;
-+ d |= destagger[dat] << shift;
-+
-+ if (shift == 0) {
-+ sd->sd_crcs[0] = crc16_acc(sd->sd_crcs[0], a);
-+ sd->sd_crcs[1] = crc16_acc(sd->sd_crcs[1], b);
-+ sd->sd_crcs[2] = crc16_acc(sd->sd_crcs[2], c);
-+ sd->sd_crcs[3] = crc16_acc(sd->sd_crcs[3], d);
-+ a = b = c = d = 0;
-+ }
-+
-+ sd->sd_crcseq -= 2;
-+ sd->sd_crctmp[0] = a;
-+ sd->sd_crctmp[1] = b;
-+ sd->sd_crctmp[2] = c;
-+ sd->sd_crctmp[3] = d;
-+}
-+
-+/* This should be called 8 times to get the full 8 bytes of CRC generated */
-+static unsigned int sd_4bit_getcrc(struct sdcore *sd)
-+{
-+ static const unsigned char restaggertbl[4] = { 0x0, 0x1, 0x10, 0x11 };
-+ static const unsigned char restaggertbl_lsl1[4] =
-+ { 0x0, 0x2, 0x20, 0x22 };
-+ static const unsigned char restaggertbl_lsl2[4] =
-+ { 0x0, 0x4, 0x40, 0x44 };
-+ static const unsigned char restaggertbl_lsl3[4] =
-+ { 0x0, 0x8, 0x80, 0x88 };
-+ unsigned int ret;
-+
-+ ret = restaggertbl[sd->sd_crcs[0] >> 14];
-+ sd->sd_crcs[0] <<= 2;
-+ ret |= restaggertbl_lsl1[sd->sd_crcs[1] >> 14];
-+ sd->sd_crcs[1] <<= 2;
-+ ret |= restaggertbl_lsl2[sd->sd_crcs[2] >> 14];
-+ sd->sd_crcs[2] <<= 2;
-+ ret |= restaggertbl_lsl3[sd->sd_crcs[3] >> 14];
-+ sd->sd_crcs[3] <<= 2;
-+
-+ return ret;
-+}
-+
-+/* This should be called 2 times to get the full 2 bytes of CRC generated */
-+static unsigned int sd_1bit_getcrc(struct sdcore *sd)
-+{
-+ unsigned int ret;
-+
-+ ret = sd->sd_crcs[0] >> 8;
-+ sd->sd_crcs[0] = (sd->sd_crcs[0] & 0xff) << 8;
-+ return ret;
-+}
-+
-+static inline void datssp_feedcrc(struct sdcore *sd, unsigned int dat)
-+{
-+ if (!(sd->sd_state & DATSSP_NOCRC)) {
-+ if (sd->sd_state & DATSSP_4BIT) sd_4bit_feedcrc(sd, dat);
-+ else sd_1bit_feedcrc(sd, dat);
-+ }
-+}
-+
-+static inline unsigned int datssp_getcrc(struct sdcore *sd)
-+{
-+ unsigned int ret = 0;
-+
-+ if (!(sd->sd_state & DATSSP_NOCRC)) {
-+ if (sd->sd_state & DATSSP_4BIT) ret = sd_4bit_getcrc(sd);
-+ else ret = sd_1bit_getcrc(sd);
-+ }
-+ return ret;
-+}
-+
-+static inline unsigned int
-+crc7(unsigned int crc, const unsigned int *pc, unsigned int len)
-+{
-+ unsigned int i;
-+ unsigned char ibit;
-+ unsigned char c;
-+
-+ for (i = 0; i < len; i++, pc++) {
-+ c = *pc;
-+ for (ibit = 0; ibit < 8; ibit++) {
-+ crc <<= 1;
-+ if ((c ^ crc) & 0x80) crc ^= 0x09;
-+
-+ c <<= 1;
-+ }
-+
-+ crc &= 0x7F;
-+ }
-+
-+ return crc;
-+}
-+
-+static inline void
-+mkcommand(unsigned int cmdidx, unsigned int arg, unsigned int *retcmd)
-+{
-+ retcmd[0] = cmdidx;
-+ retcmd[1] = arg >> 24;
-+ retcmd[2] = arg >> 16;
-+ retcmd[3] = arg >> 8;
-+ retcmd[4] = arg;
-+ retcmd[5] = (0x1 | (crc7(0, retcmd, 5) << 1));
-+}
-+
-+static inline void reset_timeout(struct sdcore *sd) {
-+ sd->sd_timeout = 0;
-+ if (sd->os_reset_timeout) sd->os_reset_timeout(sd);
-+}
-+
-+static inline int timeout(struct sdcore *sd) {
-+ if (sd->sd_timeout > 1000000) return 1;
-+ else if (sd->os_timeout) return sd->os_timeout(sd);
-+ else sd->sd_timeout++;
-+ return 0;
-+}
-+
-+static
-+unsigned int sdsize(struct sdcore *sd)
-+{
-+ unsigned int csize, csize_mult, rd_bl_len;
-+
-+ if (sd->sd_sz != 0) return sd->sd_sz;
-+
-+ if (sd->sd_csd[1] & 0xc0) {
-+ csize = (sd->sd_csd[10] | (sd->sd_csd[9] << 8));
-+ sd->sd_sz = (csize + 1) * 1024;
-+ } else {
-+ rd_bl_len = 1 << ((sd->sd_csd[6] & 0xf) - 9);
-+ csize = ((sd->sd_csd[7] & 0x03) << 10) |
-+ ((sd->sd_csd[8] << 2) | ((sd->sd_csd[9] & 0xc0) >> 6));
-+ csize_mult = ((sd->sd_csd[10] & 0x03) << 1) |
-+ ((sd->sd_csd[11] & 0x80) >> 7);
-+ sd->sd_sz = (csize + 1) * (1 << (csize_mult + 2)) * rd_bl_len;
-+ }
-+ return sd->sd_sz;
-+}
-+
-+static unsigned int tend_ssp(struct sdcore *sd, unsigned int **cmdresp,
-+ unsigned char **dat) {
-+ unsigned int d;
-+ unsigned int s = SDPEEK8(sd, SDSTATE);
-+
-+ if (s & 0x8) {
-+ if (sd->sd_state & SDCMD_RX) {
-+ d = SDPEEK8(sd, SDCMD);
-+ if (cmdresp) {
-+ **cmdresp = d;
-+ *cmdresp = *cmdresp + 1;
-+ reset_timeout(sd);
-+ }
-+ } else if (sd->sd_state & SDCMD_TX) {
-+ SDPOKE8(sd, SDCMD, **cmdresp);
-+ *cmdresp = *cmdresp + 1;
-+ reset_timeout(sd);
-+ }
-+ }
-+
-+ if (s & 0x10) {
-+ if (sd->sd_state & SDDAT_RX) {
-+ d = SDPEEK8(sd, SDDAT);
-+ if (dat) {
-+ **dat = d;
-+ *dat = *dat + 1;
-+ reset_timeout(sd);
-+ }
-+ } else if (sd->sd_state & SDDAT_TX) {
-+ reset_timeout(sd);
-+ if (dat) {
-+ d = **dat;
-+ *dat = *dat + 1;
-+ SDPOKE8(sd, SDDAT, d);
-+ datssp_feedcrc(sd, d);
-+ } else {
-+ d = datssp_getcrc(sd);
-+ SDPOKE8(sd, SDDAT, d);
-+ }
-+ }
-+ }
-+
-+ return s;
-+}
-+
-+static int
-+error(unsigned int *resp, unsigned short req)
-+{
-+ unsigned int crc, status;
-+
-+ if ((req & 0x3f) != resp[0]) return 1;
-+
-+ crc = (0x1 | (crc7(0, resp, 5) << 1));
-+ if (crc != resp[5]) return 1;
-+
-+ status = resp[1] << 24;
-+ status |= resp[2] << 16;
-+ status |= resp[3] << 8;
-+ status |= resp[4];
-+
-+ return status & 0xfdf90008;
-+}
-+
-+static int
-+sdcmd2(struct sdcore *sd, unsigned short req, unsigned int arg,
-+ unsigned int *resp, unsigned char **dat)
-+{
-+ unsigned int i, j, s, cmdresp[17];
-+ unsigned int resplen;
-+ unsigned int type = (req >> 8);
-+ unsigned int cmdidx = req;
-+ unsigned int *cmdptr = cmdresp;
-+ unsigned int *respptr;
-+ unsigned int dly;
-+ int ok32 = (sd->hw_version == 2);
-+ int ok16 = (ok32 || (sd->hw_version == 3));
-+ int sddat2_8;
-+
-+ // If no space for response provided by caller, use local buffer
-+ if (resp == NULL) resp = cmdresp;
-+ respptr = resp;
-+
-+ if (activate(sd)) return 1;
-+
-+ dly = sd->sd_state & SD_LOSPEED;
-+
-+ if (!dly) {
-+ unsigned int x;
-+ SDPOKE8(sd, SDGPIO, 0xbf);
-+#ifdef BIGENDIAN
-+ x = (cmdidx & 0xff);
-+ x |= ((arg >> 24) & 0xff) << 8;
-+ x |= ((arg >> 16) & 0xff) << 16;
-+ x |= ((arg >> 8) & 0xff) << 24;
-+ if (ok32) SDPOKE32(sd, SDCMD2, x);
-+ else if (ok16) {
-+ SDPOKE16(sd, SDCMD2, x);
-+ SDPOKE16(sd, SDCMD2, x >> 16);
-+ } else {
-+ SDPOKE8(sd, SDCMD2, x);
-+ SDPOKE8(sd, SDCMD2, x >> 8);
-+ SDPOKE8(sd, SDCMD2, x >> 16);
-+ SDPOKE8(sd, SDCMD2, x >> 24);
-+ }
-+#else
-+ x = (cmdidx & 0xff) << 24;
-+ x |= ((arg >> 24) & 0xff) << 16;
-+ x |= ((arg >> 16) & 0xff) << 8;
-+ x |= ((arg >> 8) & 0xff);
-+ if (ok32) SDPOKE32(sd, SDCMD2, x);
-+ else if (ok16) {
-+ SDPOKE16(sd, SDCMD2, x >> 16);
-+ SDPOKE16(sd, SDCMD2, x);
-+ } else {
-+ SDPOKE8(sd, SDCMD2, x >> 24);
-+ SDPOKE8(sd, SDCMD2, x >> 16);
-+ SDPOKE8(sd, SDCMD2, x >> 8);
-+ SDPOKE8(sd, SDCMD2, x);
-+ }
-+#endif
-+ SDPOKE8(sd, SDCMD2, arg);
-+ } else {
-+ // Build command packet
-+ mkcommand(cmdidx, arg, cmdptr);
-+
-+ // Send command
-+ for (i = 0; i < 6; i++) {
-+ unsigned int b = *cmdptr++;
-+ unsigned int x;
-+
-+ if (timeout(sd)) break;
-+ for (j = 0; j < 8; j++) {
-+ x = 0x8f | ((b & 0x80) >> 3);
-+ b = b << 1;
-+ SDPOKE8(sd, SDGPIO, x); // clk negedge
-+ SDPEEK8(sd, SDGPIO); // delay
-+ SDPEEK8(sd, SDGPIO); // delay
-+ x |= 0x20;
-+ SDPOKE8(sd, SDGPIO, x); // clk posedge
-+ SDPEEK8(sd, SDGPIO); // delay
-+ SDPEEK8(sd, SDGPIO); // delay
-+ }
-+ }
-+ }
-+
-+ if (type == TYPE_NORESP) goto done;
-+ else if (type == TYPE_RXDAT_IGNRESP) goto ignresp;
-+ else if (type == TYPE_LONGRESP) resplen = 17;
-+ else resplen = 6;
-+
-+ // clock until start bit on CMD pin
-+ while(1) {
-+ if (timeout(sd)) {
-+ goto done;
-+ }
-+ if (req == CMD_SEND_IF_COND) sd->sd_timeout += 100000;
-+ SDPOKE8(sd, SDGPIO, 0xdf); // clk negedge
-+ if (dly) SDPEEK8(sd, SDGPIO); // delay
-+ s = SDPEEK8(sd, SDGPIO); // sample
-+ if ((s & 0x10) == 0x0) break;
-+ SDPOKE8(sd, SDGPIO, 0xff); // clk posedge
-+ if (dly) SDPEEK8(sd, SDGPIO); // delay
-+ }
-+ reset_timeout(sd);
-+
-+ // Next we receive the response.
-+ if (ok16 && !ok32) sddat2_8 = SDDAT2 + 1;
-+ else sddat2_8 = SDDAT2;
-+ if (dly) for (i = 0; i < resplen; i++) {
-+ unsigned int r = 0;
-+
-+ for (j = 0; j < 8; j++) {
-+ SDPOKE8(sd, SDGPIO, 0xdf); // clk negedge
-+ SDPEEK8(sd, SDGPIO); // delay
-+ s = SDPEEK8(sd, SDGPIO); // sample
-+ SDPOKE8(sd, SDGPIO, 0xff); // clk posedge
-+ SDPEEK8(sd, SDGPIO); // delay
-+ SDPEEK8(sd, SDGPIO); // delay
-+ r = r << 1;
-+ r |= ((s & 0x10) >> 4);
-+ }
-+
-+ *respptr++ = r;
-+ } else while (resplen > 0) {
-+ unsigned int r;
-+
-+#ifdef BIGENDIAN
-+ if (ok32 && resplen >= 4) {
-+ r = SDPEEK32(sd, SDCMD2);
-+ *respptr++ = r & 0xff;
-+ *respptr++ = (r >> 8) & 0xff;
-+ *respptr++ = (r >> 16) & 0xff;
-+ *respptr++ = (r >> 24);
-+ resplen -= 4;
-+ } else if (ok16 && resplen >= 2) {
-+ r = SDPEEK16(sd, SDCMD2);
-+ *respptr++ = r & 0xff;
-+ *respptr++ = (r >> 8) & 0xff;
-+
-+ resplen -= 2;
-+ } else {
-+ *respptr++ = SDPEEK8(sd, sddat2_8);
-+ resplen--;
-+ }
-+#else
-+ if (ok32 && resplen >= 4) {
-+ r = SDPEEK32(sd, SDCMD2);
-+ *respptr++ = (r >> 24);
-+ *respptr++ = (r >> 16) & 0xff;
-+ *respptr++ = (r >> 8) & 0xff;
-+ *respptr++ = r & 0xff;
-+ resplen -= 4;
-+ } else if (ok16 && resplen >= 2) {
-+ r = SDPEEK16(sd, SDCMD2);
-+ *respptr++ = (r >> 8) & 0xff;
-+ *respptr++ = r & 0xff;
-+ resplen -= 2;
-+ } else {
-+ *respptr++ = SDPEEK8(sd, sddat2_8);
-+ resplen--;
-+ }
-+#endif
-+ }
-+ if (type == TYPE_BSYRESP) {
-+ s = 0;
-+ while ((s & 0x7) != 0x7) {
-+ if (timeout(sd)) break;
-+ SDPOKE8(sd, SDGPIO, 0x9f); // clk negedge
-+ if (dly) SDPEEK8(sd, SDGPIO); // delay
-+ s = s << 1;
-+ s |= SDPEEK8(sd, SDGPIO) & 0x1;
-+ SDPOKE8(sd, SDGPIO, 0xbf);
-+ if (dly) SDPEEK8(sd, SDGPIO);
-+ }
-+ }
-+
-+ignresp:
-+
-+ if (type == TYPE_ABORT)
-+ sd->sd_state &= ~(SDDAT_RX|SDDAT_TX);
-+
-+#ifndef SD_READONLYDMA
-+ if (type == TYPE_TXDAT) {
-+ sd->sd_state |= SDDAT_TX;
-+ /* 2 clocks for nWR */
-+ SDPOKE8(sd, SDGPIO, 0xdf); // clk negedge
-+ if (dly) SDPEEK8(sd, SDGPIO); // delay
-+ if (dly) SDPEEK8(sd, SDGPIO); // delay
-+ SDPOKE8(sd, SDGPIO, 0xff); // clk posedge
-+ if (dly) SDPEEK8(sd, SDGPIO); // delay
-+ if (dly) SDPEEK8(sd, SDGPIO); // delay
-+ SDPOKE8(sd, SDGPIO, 0xdf); // clk negedge
-+ if (dly) SDPEEK8(sd, SDGPIO); // delay
-+ if (dly) SDPEEK8(sd, SDGPIO); // delay
-+ SDPOKE8(sd, SDGPIO, 0xff); // clk posedge
-+ if (dly) SDPEEK8(sd, SDGPIO); // delay
-+ if (dly) SDPEEK8(sd, SDGPIO); // delay
-+ if (sd->sd_state & DATSSP_4BIT)
-+ SDPOKE8(sd, SDGPIO, 0x10); // assert start, clk negedge
-+ else
-+ SDPOKE8(sd, SDGPIO, 0x1e);
-+ if (dly) SDPEEK8(sd, SDGPIO); // delay
-+ if (dly) SDPEEK8(sd, SDGPIO); // delay
-+ if (sd->sd_state & DATSSP_4BIT)
-+ SDPOKE8(sd, SDGPIO, 0x30); // clk posedge
-+ else
-+ SDPOKE8(sd, SDGPIO, 0x3e);
-+ if (dly) SDPEEK8(sd, SDGPIO); // delay
-+ if (dly) SDPEEK8(sd, SDGPIO); // delay
-+ }
-+#endif
-+
-+ if (type == TYPE_RXDAT || type == TYPE_RXDAT_IGNRESP)
-+ sd->sd_state |= SDDAT_RX;
-+
-+done:
-+ // 8 clocks before stopping
-+ if (!(sd->sd_state & (SDDAT_TX|SDDAT_RX))) {
-+ if (dly) for (i = 0; i < 8; i++) {
-+ SDPOKE8(sd, SDGPIO, 0xdf);
-+ SDPEEK8(sd, SDGPIO); // delay
-+ SDPEEK8(sd, SDGPIO); // delay
-+ SDPOKE8(sd, SDGPIO, 0xff);
-+ SDPEEK8(sd, SDGPIO); // delay
-+ SDPEEK8(sd, SDGPIO); // delay
-+ } else {
-+ SDPOKE8(sd, SDGPIO, 0xff);
-+ SDPOKE8(sd, SDCMD2, 0xff);
-+ }
-+ }
-+ if (timeout(sd)) return 1;
-+ else return 0;
-+
-+}
-+
-+
-+static int
-+sdcmd(struct sdcore *sd, unsigned short req, unsigned int arg,
-+ unsigned int *resp, unsigned char **dat)
-+{
-+ unsigned int s, cmdresp[17];
-+ unsigned int resplen;
-+ unsigned int type = (req >> 8);
-+ unsigned int cmdidx = req;
-+ unsigned int *cmdptr = cmdresp;
-+ unsigned int *cmd = cmdresp;
-+ unsigned int *respptr;
-+ unsigned int ndat;
-+
-+ if (sd->hw_version != 0) return sdcmd2(sd, req, arg, resp, dat);
-+
-+ // If no space for response provided by caller, use local buffer
-+ if (resp == NULL) resp = cmdresp;
-+ respptr = resp;
-+
-+ // Before continuing, we must wait for the FSM to get to the
-+ // S_SEND_CMD state. After a previous command, we may still be
-+ // in S_DUMMY_CLK or in case of an ABORT, we may be in the middle of
-+ // clocking a byte for TX or RX.
-+ s = SDPEEK8(sd, SDSTATE);
-+ while ((s & 0x7) != S_SEND_CMD) {
-+ if (timeout(sd)) break;
-+ s = SDPEEK8(sd, SDSTATE);
-+ }
-+
-+ // We know we're in S_SEND_CMD, but we may need to change the
-+ // command type. This won't cause a state change.
-+ if ((s & 0xe7) != (S_SEND_CMD | (type << 5)))
-+ SDPOKE8(sd, SDSTATE, S_SEND_CMD | (type << 5));
-+
-+ // Build command packet
-+ mkcommand(cmdidx, arg, cmdptr);
-+
-+ // Next, we loop while tending the SSPs until we get our last
-+ // byte of command data out. We may get a few bytes from the DAT
-+ // SSP if we are aborting a previous data transfer command. If we do
-+ // those get placed in a buffer or thrown away based on the callers
-+ // "dat" parameter.
-+ sd->sd_state |= SDCMD_TX;
-+ while ((cmdptr - cmd) != 6) {
-+ if (timeout(sd)) break;
-+ s = tend_ssp(sd, &cmdptr, dat);
-+ }
-+ sd->sd_state &= ~SDCMD_TX;
-+
-+ // If we got out of sync with the hardware, that would be bad.
-+ // The hardware should still be in S_SEND_CMD for the last CMDSSP
-+ // byte.
-+ if ((s & 0x7) != S_SEND_CMD) {
-+ SDPOKE8(sd, SDSTATE, S_OFF);
-+ return 1;
-+ }
-+
-+ if (type == TYPE_NORESP) goto done;
-+ else if (type == TYPE_LONGRESP) resplen = 17;
-+ else resplen = 6;
-+
-+ // Next state should be S_WAIT_RESP or S_RX_RESP. We may get
-+ // more bytes from the DATSSP while shifting out our last bits of cmd
-+ while (((s & 0x7) != S_WAIT_RESP) && ((s & 0x7) != S_RX_RESP)) {
-+ if (timeout(sd)) break;
-+ if (req == CMD_SEND_IF_COND) sd->sd_timeout += 1000;
-+ s = tend_ssp(sd, NULL, dat);
-+ }
-+
-+ // Once we're in S_WAIT_RESP or S_RX_RESP though, the DATSSP is only
-+ // active for 2 more clocks at the beginning of the S_WAIT_RESP state.
-+ // This is enough for one more byte in 4-bit mode, though we may have
-+ // 2 bytes already in our DATSSP.
-+ if (sd->sd_state & (SDDAT_RX|SDDAT_TX)) {
-+ do {
-+ if (timeout(sd)) break;
-+ s = tend_ssp(sd, NULL, dat);
-+ } while (!(s & 0x18));
-+
-+ // We've now read/wrote one more byte to the DATSSP
-+ // which should allow our FSM to advance to the RX_RESP state.
-+ // If we pick up more than 2 more DATSSP bytes, something is
-+ // wrong.
-+ ndat = 0;
-+ while ((s & 0x7) != S_RX_RESP) {
-+ if (timeout(sd) || ndat > 2) break;
-+ s = tend_ssp(sd, NULL, dat);
-+ if (s & 0x10) ndat++;
-+ }
-+
-+ if (ndat > 2) {
-+ SDPOKE8(sd, SDSTATE, S_OFF);
-+ return 1;
-+ }
-+ }
-+
-+ // We're now done with whatever business we had remaining with the
-+ // previous command's DATSSP transfer since we've either just got our
-+ // first byte of response or our last byte of data
-+ sd->sd_state &= ~(SDDAT_RX|SDDAT_TX);
-+ if (type == TYPE_RXDAT) sd->sd_state |= SDDAT_RX;
-+
-+ // Next we receive the response. If this is TYPE_RXDAT command,
-+ // or an abortion of a previous TYPE_RXDAT command, we may get a
-+ // few bytes from the DAT SSP also.
-+ sd->sd_state |= SDCMD_RX;
-+ while ((respptr - resp) != resplen) {
-+ if (timeout(sd)) break;
-+ s = tend_ssp(sd, &respptr, dat);
-+ if ((s & 0x10) && (resp == respptr)) {
-+ SDPOKE8(sd, SDSTATE, S_OFF);
-+ sd->sd_state &= ~(SDCMD_RX|SDDAT_RX);
-+ return 1;
-+ }
-+ }
-+ sd->sd_state &= ~SDCMD_RX;
-+
-+ if (type == TYPE_ABORT)
-+ sd->sd_state &= ~(SDDAT_RX|SDDAT_TX);
-+
-+ if (type == TYPE_TXDAT) sd->sd_state |= SDDAT_TX;
-+
-+done:
-+ if (timeout(sd)) return 1;
-+ else return 0;
-+
-+}
-+
-+static int datssp_stream2(struct sdcore *sd, unsigned char **dat,
-+ unsigned int buflen)
-+{
-+ unsigned char *d;
-+ int ret;
-+#ifndef SD_READONLYDMA
-+ int ok32;
-+ int ok16;
-+ int sddat2_8;
-+ unsigned int x;
-+#endif
-+
-+ if (sd->os_dmastream /* && (sd->sd_state & SDDAT_RX) */) {
-+ d = dat ? *dat : NULL;
-+ ret = sd->os_dmastream(sd->os_arg, d, buflen);
-+ if (!ret && d) *dat += buflen;
-+ return ret;
-+ }
-+
-+#ifndef SD_READONLYDMA
-+ d = *dat;
-+
-+ while (buflen > 512) {
-+ datssp_stream2(sd, dat, 512);
-+ if (sd->os_irqwait) sd->os_irqwait(sd->os_arg, 1);
-+ buflen -= 512;
-+ d = *dat;
-+ }
-+
-+ ok32 = (sd->hw_version == 2);
-+ ok16 = (ok32 || (sd->hw_version == 3));
-+ if (ok16 && !ok32) sddat2_8 = SDDAT2 + 1;
-+ else sddat2_8 = SDDAT2;
-+
-+ if (sd->sd_state & SDDAT_RX) {
-+
-+ while (((int)d & 0x1) || buflen == 1) {
-+ *d++ = SDPEEK8(sd, sddat2_8);
-+ buflen--;
-+ }
-+
-+ if (((int)d & 0x2) && buflen >= 2) {
-+ if (ok16) *(unsigned short *)(d) = SDPEEK16(sd, SDDAT2);
-+ else {
-+#ifdef BIGENDIAN
-+ x = SDPEEK8(sd, sddat2_8) << 8;
-+ x |= SDPEEK8(sd, sddat2_8);
-+#else
-+ x = SDPEEK8(sd, sddat2_8);
-+ x |= SDPEEK8(sd, sddat2_8) << 8;
-+#endif
-+ *(unsigned short *)(d) = x;
-+ }
-+ buflen -= 2;
-+ d += 2;
-+ }
-+
-+ if (ok32) while (buflen >= 4) {
-+ *(unsigned int *)(d) = SDPEEK32(sd, SDDAT2);
-+ buflen -= 4;
-+ d += 4;
-+ } else if (ok16) while (buflen >= 4) {
-+#ifdef BIGENDIAN
-+ x = SDPEEK16(sd, SDDAT2) << 16;
-+ x |= SDPEEK16(sd, SDDAT2);
-+#else
-+ x = SDPEEK16(sd, SDDAT2);
-+ x |= SDPEEK16(sd, SDDAT2) << 16;
-+#endif
-+ buflen -= 4;
-+ *(unsigned int *)(d) = x;
-+ d += 4;
-+ } else while (buflen >= 4) {
-+#ifdef BIGENDIAN
-+ x = SDPEEK8(sd, sddat2_8) << 24;
-+ x |= SDPEEK8(sd, sddat2_8) << 16;
-+ x |= SDPEEK8(sd, sddat2_8) << 8;
-+ x |= SDPEEK8(sd, sddat2_8);
-+#else
-+ x = SDPEEK8(sd, sddat2_8);
-+ x |= SDPEEK8(sd, sddat2_8) << 8;
-+ x |= SDPEEK8(sd, sddat2_8) << 16;
-+ x |= SDPEEK8(sd, sddat2_8) << 24;
-+#endif
-+ buflen -= 4;
-+ *(unsigned int *)(d) = x;
-+ d += 4;
-+ }
-+ } else {
-+ while (((int)d & 0x1) || buflen == 1) {
-+ SDPOKE8(sd, SDDAT2, *d++);
-+ buflen--;
-+ }
-+
-+ if (((int)d & 0x2) && buflen >= 2) {
-+ if (ok16) SDPOKE16(sd, SDDAT2, *(unsigned short *)(d));
-+ else {
-+ x = *(unsigned short *)(d);
-+#ifdef BIGENDIAN
-+ SDPOKE8(sd, SDDAT2, x >> 8);
-+ SDPOKE8(sd, SDDAT2, x);
-+#else
-+ SDPOKE8(sd, SDDAT2, x);
-+ SDPOKE8(sd, SDDAT2, x >> 8);
-+#endif
-+ }
-+ buflen -= 2;
-+ d += 2;
-+ }
-+
-+ if (ok32) while (buflen >= 4) {
-+ SDPOKE32(sd, SDDAT2, *(unsigned int *)(d));
-+ buflen -= 4;
-+ d += 4;
-+ } else if (ok16) while (buflen >= 4) {
-+ x = *(unsigned int *)(d);
-+ buflen -= 4;
-+ d += 4;
-+#ifdef BIGENDIAN
-+ SDPOKE16(sd, SDDAT2, x >> 16);
-+ SDPOKE16(sd, SDDAT2, x);
-+#else
-+ SDPOKE16(sd, SDDAT2, x);
-+ SDPOKE16(sd, SDDAT2, x >> 16);
-+#endif
-+ } else while (buflen >= 4) {
-+ x = *(unsigned int *)(d);
-+ buflen -= 4;
-+ d += 4;
-+#ifdef BIGENDIAN
-+ SDPOKE8(sd, SDDAT2, x >> 24);
-+ SDPOKE8(sd, SDDAT2, x >> 16);
-+ SDPOKE8(sd, SDDAT2, x >> 8);
-+ SDPOKE8(sd, SDDAT2, x);
-+#else
-+ SDPOKE8(sd, SDDAT2, x);
-+ SDPOKE8(sd, SDDAT2, x >> 8);
-+ SDPOKE8(sd, SDDAT2, x >> 16);
-+ SDPOKE8(sd, SDDAT2, x >> 24);
-+#endif
-+ }
-+ }
-+
-+ *dat = d;
-+
-+ if (buflen > 0) return datssp_stream2(sd, dat, buflen);
-+ else return 0;
-+#else
-+ return 0;
-+#endif
-+}
-+
-+static int datssp_stream(struct sdcore *sd, unsigned char **dat,
-+ unsigned int buflen)
-+{
-+ unsigned int s, t, byte = 0;
-+ unsigned char *d;
-+
-+ if (((sd->sd_state & SDDAT_RX) && sd->os_dmastream) /* ||
-+ ((sd->sd_state & SDDAT_TX) && sd->os_dmastream && dat) */ ) {
-+ unsigned char *d = dat ? *dat : NULL;
-+ int ret = sd->os_dmastream(sd->os_arg, d, buflen);
-+ if (!ret && d) *dat += buflen;
-+ return ret;
-+ }
-+
-+ if (sd->hw_version > 0) return datssp_stream2(sd, dat, buflen);
-+
-+ while (buflen) {
-+ if (timeout(sd)) return 1;
-+ s = tend_ssp(sd, NULL, dat);
-+ if (s & 0x10) {
-+ buflen--;
-+ if (byte++ > 7) {
-+ if (sd->sd_state & SDDAT_RX)
-+ goto fastrx;
-+ else goto fasttx;
-+ }
-+ }
-+ }
-+
-+ // Now we can go faster (PIO)
-+fastrx:
-+ if (dat) {
-+ d = *dat;
-+ while (buflen) {
-+ s = SDPEEK8(sd, SDDAT);
-+ *d = s;
-+ buflen--;
-+ d++;
-+ }
-+ *dat = d;
-+ } else {
-+ while (buflen--) SDPEEK8(sd, SDDAT);
-+ }
-+ return 0;
-+
-+fasttx:
-+ if (dat) {
-+ d = *dat;
-+ while (buflen) {
-+ t = *d;
-+ SDPOKE8(sd, SDDAT, t);
-+ buflen--;
-+ d++;
-+ datssp_feedcrc(sd, t);
-+ }
-+ *dat = d;
-+ } else {
-+ while (buflen--) SDPOKE8(sd, SDDAT, datssp_getcrc(sd));
-+ }
-+ return 0;
-+}
-+
-+static int stop(struct sdcore *sd)
-+{
-+ int ret;
-+ unsigned int resp[6];
-+
-+ if (sd->hw_version) return stop2(sd);
-+
-+ if (sd->parked_sector) {
-+ if (sd->sd_state & SDDAT_TX) {
-+ /* wait to get out of S_WAIT_BUSY */
-+ while ((SDPEEK8(sd, SDSTATE) & 0x7) != S_TX_WRITE)
-+ if (timeout(sd)) break;
-+
-+ /* abort parked write */
-+ SDPOKE8(sd, SDSTATE, S_SEND_CMD | (TYPE_ABORT << 5));
-+ sd->sd_state &= ~SDDAT_TX;
-+ sd->sd_state |= SDDAT_RX;
-+ ret = sdcmd(sd, CMD_STOP_TRANSMISSION, 0, resp, NULL);
-+ sd->sd_state &= ~SDDAT_RX;
-+ SDPOKE8(sd, SDSTATE, S_WAIT_BUSY | (TYPE_BSYRESP << 5));
-+ } else {
-+ /* abort parked read */
-+ SDPOKE8(sd, SDSTATE, S_SEND_CMD | (TYPE_ABORT << 5));
-+ ret = sdcmd(sd, CMD_STOP_TRANSMISSION, 0, resp, NULL);
-+ }
-+ sd->parked_sector = 0;
-+ if (ret || error(resp, CMD_STOP_TRANSMISSION) || timeout(sd))
-+ return 1;
-+ }
-+ return 0;
-+}
-+
-+static int stop2(struct sdcore *sd)
-+{
-+ int ret;
-+ unsigned int resp[6];
-+
-+ if (sd->parked_sector) {
-+ if (sd->os_irqwait) sd->os_irqwait(sd->os_arg, 0);
-+ if (sd->sd_state & SDDAT_TX) {
-+ /* abort parked write */
-+ ret = sdcmd2(sd, CMD_STOP_TRANSMISSION, 0, resp, NULL);
-+ SDPOKE8(sd, SDCTRL2, 0x0);
-+ if (sd->os_irqwait) sd->os_irqwait(sd->os_arg, 5);
-+ SDPOKE8(sd, SDGPIO, 0xff);
-+
-+ /*
-+ while ((SDPEEK8(sd, SDGPIO) & 0xf) != 0xf) {
-+ sd->os_delay(sd->os_arg, 1);
-+ SDPOKE8(sd, SDGPIO, 0xdf);
-+ SDPOKE8(sd, SDGPIO, 0xff);
-+ if (timeout(sd)) return 1;
-+ }
-+ */
-+ reset_timeout(sd);
-+ } else {
-+ /* abort parked read */
-+ ret = sdcmd2(sd, CMD_STOP_TRANSMISSION, 0, resp, NULL);
-+ }
-+ sd->parked_sector = 0;
-+ if (ret || error(resp, CMD_STOP_TRANSMISSION) || timeout(sd)) {
-+ return 1;
-+ }
-+ }
-+ return 0;
-+}
-+
-+static int do_read2(struct sdcore *sd, unsigned int sector, struct sdiov *iov,
-+ unsigned int iovcnt)
-+{
-+ unsigned int ret, n, s, sz;
-+ unsigned char *datptr, *dat;
-+
-+ if (iovcnt == 0) return 0;
-+
-+ if (activate(sd)) return 1;
-+
-+ n = iov->sdiov_nsect;
-+ datptr = dat = iov->sdiov_base;
-+ sz = sdsize(sd);
-+ if (sector >= sz) return 0;
-+
-+ if (sd->parked_sector) {
-+ if (!(sd->sd_state & SDDAT_TX) && sd->parked_sector == sector) {
-+ if (sd->os_irqwait && !sd->os_dmastream)
-+ sd->os_irqwait(sd->os_arg, 3);
-+ goto receive;
-+ }
-+
-+ stop2(sd);
-+ }
-+
-+ if (sd->sd_state & SD_HC)
-+ ret = sdcmd2(sd, CMD_READ_MULTIPLE_BLOCK2, sector, NULL, NULL);
-+ else
-+ ret = sdcmd2(sd, CMD_READ_MULTIPLE_BLOCK2, sector * 512, NULL, NULL);
-+
-+ do {
-+ if (timeout(sd)) return 1;;
-+ SDPOKE8(sd, SDGPIO, 0xdf);
-+ s = SDPEEK8(sd, SDGPIO);
-+ SDPOKE8(sd, SDGPIO, 0xff);
-+ } while ((s & 0xf) != 0x0);
-+ reset_timeout(sd);
-+
-+receive:
-+ if (sd->os_dmaprep && sd->os_dmastream)
-+ sd->os_dmaprep(sd->os_arg, datptr, n * 512);
-+
-+ SDPOKE8(sd, SDGPIO, 0xdf);
-+ sd->parked_sector = sector + n;
-+
-+nextiov:
-+ if (sd->parked_sector > sz) {
-+ n -= sd->parked_sector - sz;
-+ sd->parked_sector = sz;
-+ }
-+ datssp_stream2(sd, &datptr, n * 512);
-+
-+ if (--iovcnt) {
-+ ++iov;
-+ n = iov->sdiov_nsect;
-+ datptr = iov->sdiov_base;
-+ sd->parked_sector += n;
-+ if (sd->os_dmaprep && sd->os_dmastream)
-+ sd->os_dmaprep(sd->os_arg, datptr, n * 512);
-+ goto nextiov;
-+ }
-+
-+ /* s = SDPEEK8(sd, SDSTAT2);
-+ if (s & 0x44) {
-+ sd->sd_timeout = 1000001;
-+ return 1;
-+ }
-+ else */ return 0;
-+}
-+
-+static int do_read(struct sdcore *sd, unsigned int sector, struct sdiov *iov,
-+ unsigned int iovcnt)
-+{
-+ unsigned int resp[6], ret, n, sz;
-+ unsigned char *datptr, *dat;
-+
-+ if (iovcnt == 0) return 0;
-+
-+ n = iov->sdiov_nsect;
-+ datptr = dat = iov->sdiov_base;
-+ sz = sdsize(sd);
-+ if (sector >= sz) return 0;
-+
-+ if (sd->parked_sector) {
-+ if (!(sd->sd_state & SDDAT_TX) && sd->parked_sector == sector)
-+ goto receive;
-+
-+ stop(sd);
-+ }
-+
-+ if (sd->sd_state & SD_HC)
-+ ret = sdcmd(sd, CMD_READ_MULTIPLE_BLOCK, sector, resp, &datptr);
-+ else
-+ ret = sdcmd(sd, CMD_READ_MULTIPLE_BLOCK, sector * 512, resp, &datptr);
-+ if (ret || error(resp, CMD_READ_MULTIPLE_BLOCK)) return 1;
-+
-+receive:
-+ if (sd->os_dmaprep && sd->os_dmastream)
-+ sd->os_dmaprep(sd->os_arg, datptr, n * 512 - (datptr - dat));
-+
-+ datssp_stream(sd, &datptr, 512 - (datptr - dat));
-+ datssp_stream(sd, NULL, 6);
-+
-+ sd->parked_sector = sector + n;
-+ if (sd->parked_sector > sz) {
-+ n -= sd->parked_sector - sz;
-+ sd->parked_sector = sz;
-+ }
-+ n--;
-+
-+nextiov:
-+ while (n--) {
-+ SDPOKE8(sd, SDSTATE, S_WAIT_RESP | (TYPE_RXDAT << 5));
-+ datssp_stream(sd, NULL, 2); // last part of prev CRC
-+ datssp_stream(sd, &datptr, 512);
-+ datssp_stream(sd, NULL, 6); // first part of CRC
-+ }
-+
-+ if (--iovcnt) {
-+ ++iov;
-+ n = iov->sdiov_nsect;
-+ datptr = iov->sdiov_base;
-+ sd->parked_sector += n;
-+ if (sd->parked_sector > sz) {
-+ n -= sd->parked_sector - sz;
-+ sd->parked_sector = sz;
-+ }
-+ if (sd->os_dmaprep && sd->os_dmastream && n > 0)
-+ sd->os_dmaprep(sd->os_arg, datptr, n * 512);
-+ goto nextiov;
-+ }
-+
-+ SDPOKE8(sd, SDSTATE, S_WAIT_RESP | (TYPE_RXDAT << 5));
-+ datssp_stream(sd, NULL, 2); // last part of prev CRC
-+ return 0;
-+}
-+
-+static int do_write2(struct sdcore *sd, unsigned int sector, struct sdiov *iov,
-+ unsigned int iovcnt)
-+{
-+ unsigned char *datptr;
-+ unsigned int resp[6], ret, n, s, sz, ss;
-+
-+ if (sd->sd_wprot) return 1;
-+
-+ if (iovcnt == 0) return 0;
-+
-+ if (activate(sd)) return 1;
-+
-+ sz = sdsize(sd);
-+ if (sector >= sz) return 0;
-+
-+ if (sd->os_powerok) {
-+ int ok = sd->os_powerok(sd);
-+ if (!ok && sd->parked_sector) {
-+ stop2(sd);
-+ return 1;
-+ } else if (!ok) return 1;
-+ }
-+
-+ if (sd->parked_sector) {
-+ if ((sd->sd_state & SDDAT_TX) && sd->parked_sector == sector)
-+ goto transmit;
-+
-+ stop2(sd);
-+ }
-+
-+ if (sd->sd_erasehint) {
-+ sdcmd2(sd, CMD_APP_CMD, sd->sd_rcaarg, NULL, NULL);
-+ sdcmd2(sd, ACMD_SET_WR_BLK_ERASE_COUNT, sd->sd_erasehint,
-+ NULL, NULL);
-+ sd->sd_erasehint = 0;
-+ }
-+
-+ if (sd->sd_state & SD_HC)
-+ ret = sdcmd2(sd, CMD_WRITE_MULTIPLE_BLOCK, sector, resp, NULL);
-+ else
-+ ret = sdcmd2(sd, CMD_WRITE_MULTIPLE_BLOCK, sector * 512, resp, NULL);
-+ if (ret || error(resp, CMD_WRITE_MULTIPLE_BLOCK)) {
-+ return 1;
-+ }
-+ sd->parked_sector = sector;
-+ ss = SDPEEK8(sd, SDSTAT2);
-+
-+transmit:
-+ while (iovcnt--) {
-+ datptr = iov->sdiov_base;
-+ n = iov->sdiov_nsect;
-+ sd->parked_sector += n;
-+ if (sd->parked_sector > sz) {
-+ n -= sd->parked_sector - sz;
-+ sd->parked_sector = sz;
-+ }
-+ datssp_stream2(sd, &datptr, n * 512);
-+ iov++;
-+ }
-+
-+ if (!sd->sd_writeparking) {
-+ ret = stop2(sd);
-+ if (ret) return ret;
-+ }
-+
-+ if (sd->os_irqwait) sd->os_irqwait(sd->os_arg, 2);
-+
-+ s = SDPEEK8(sd, SDSTAT2);
-+ if (s & 0x44) {
-+ sd->sd_timeout = 1000001;
-+ return 1;
-+ } else {
-+ reset_timeout(sd);
-+ return 0;
-+ }
-+}
-+
-+static int do_write(struct sdcore *sd, unsigned int sector, struct sdiov *iov,
-+ unsigned int iovcnt)
-+{
-+ unsigned char *datptr, *crcptr, **crcptrptr;
-+ unsigned int resp[6], ret, n, sz;
-+
-+ if (sd->sd_wprot) return 1;
-+
-+ if (iovcnt == 0) return 0;
-+
-+ sz = sdsize(sd);
-+ if (sector >= sz) return 0;
-+
-+ if (0 /* sd->sd_crchint */) {
-+ // CRC is pre-calculated so don't recalculate
-+ crcptr = sd->sd_crchint;
-+ crcptrptr = &crcptr;
-+ sd->sd_state |= DATSSP_NOCRC;
-+ sd->sd_crchint = NULL;
-+ } else {
-+ crcptrptr = NULL;
-+ sd->sd_state &= ~DATSSP_NOCRC;
-+ }
-+
-+ if (sd->parked_sector) {
-+ if ((sd->sd_state & SDDAT_TX) && sd->parked_sector == sector)
-+ goto transmit;
-+
-+ stop(sd);
-+ }
-+
-+ if (sd->sd_erasehint) {
-+ sdcmd(sd, CMD_APP_CMD, sd->sd_rcaarg, NULL, NULL);
-+ sdcmd(sd, ACMD_SET_WR_BLK_ERASE_COUNT, sd->sd_erasehint,
-+ NULL, NULL);
-+ sd->sd_erasehint = 0;
-+ }
-+
-+ if (sd->sd_state & SD_HC)
-+ ret = sdcmd(sd, CMD_WRITE_MULTIPLE_BLOCK, sector, resp, NULL);
-+ else
-+ ret = sdcmd(sd, CMD_WRITE_MULTIPLE_BLOCK, sector * 512, resp, NULL);
-+ if (ret || error(resp, CMD_WRITE_MULTIPLE_BLOCK)) {
-+ return 1;
-+ }
-+ sd->parked_sector = sector;
-+
-+transmit:
-+ while (iovcnt--) {
-+ datptr = iov->sdiov_base;
-+ n = iov->sdiov_nsect;
-+ sd->parked_sector += n;
-+ if (sd->parked_sector > sz) {
-+ n -= sd->parked_sector - sz;
-+ sd->parked_sector = sz;
-+ }
-+ while (n--) {
-+ datssp_stream(sd, &datptr, 512);
-+ datssp_stream(sd, crcptrptr, 8); // CRC bytes
-+ SDPOKE8(sd, SDSTATE, S_CRC_CHECK | (TYPE_TXDAT << 5));
-+ }
-+ iov++;
-+ }
-+
-+ if (!sd->sd_writeparking) {
-+ stop(sd);
-+ }
-+
-+ return 0;
-+}
-+
-+static
-+int sdfastinit(struct sdcore *sd)
-+{
-+ SDPOKE8(sd, SDCTRL, 0x40);
-+ sd->sd_state = DATSSP_4BIT;
-+
-+ sd->sd_rcaarg = ~sd->sdboot_token;
-+ sdcmd(sd, CMD_DESELECT_CARD, ~sd->sd_rcaarg, NULL, NULL);
-+ sdcmd(sd, CMD_SEND_CSD, sd->sd_rcaarg, sd->sd_csd, NULL);
-+ sdcmd(sd, CMD_SELECT_CARD, sd->sd_rcaarg, NULL, NULL);
-+
-+ if (sd->os_dmastream) SDPOKE8(sd, SDCTRL, 0x42);
-+ if ((SDPEEK8(sd, SDCTRL) & 0x80) || (sd->sd_csd[15] & 0x30))
-+ sd->sd_wprot = 1;
-+ sd->sd_blocksize = 1 << ((sd->sd_csd[6] & 0xf));
-+ if (timeout(sd)) return 0;
-+ else return sdsize(sd);
-+}
-+
-+static
-+int sdreset2(struct sdcore *sd)
-+{
-+ unsigned int rca, s, i, x;
-+ unsigned int resp[17];
-+
-+ reset_timeout(sd);
-+ sd_initcrc(sd);
-+ sd->parked_sector = 0;
-+ sd->sd_wprot = 0;
-+ sd->sd_blocksize = 0;
-+ sd->sd_sz = 0;
-+ if (sd->hw_version == 0) sd->hw_version = version(sd);
-+ if (sd->hw_version == 0) return 0;
-+ sd->sd_state &= SD_RESET;
-+ remember_sdcore(sd);
-+ activate(sd);
-+ sd->sd_state |= SD_LOSPEED;
-+
-+ if (!(sd->sd_state & SD_RESET) && (SDPEEK8(sd, SDGPIO) != 0x0)) {
-+ SDPOKE8(sd, SDGPIO, 0x0);
-+#ifdef BIGENDIAN
-+ for (i = 0; i < 8; i++) SDPOKE16(sd, SDLUN2, i << 8);
-+#else
-+ for (i = 0; i < 8; i++) SDPOKE16(sd, SDLUN2, i);
-+#endif
-+ sd->os_delay(sd->os_arg, 100000);
-+
-+ /* this was a global reset, so let the other luns know */
-+ for (i = 0; i < sizeof(sdcores); i++) {
-+ if (sdcores[i] == NULL) break;
-+ if (sdcores[i]->sd_regstart == sd->sd_regstart)
-+ sdcores[i]->sd_state |= SD_RESET;
-+ }
-+#ifdef BIGENDIAN
-+ SDPOKE16(sd, SDLUN2, sd->sd_lun << 8);
-+#else
-+ SDPOKE16(sd, SDLUN2, sd->sd_lun);
-+#endif
-+ }
-+ sd->sd_state &= ~SD_RESET;
-+
-+ // gratuitous clocks
-+ SDPOKE8(sd, SDGPIO, 0xff);
-+ sd->os_delay(sd->os_arg, 5000);
-+ for (i = 0; i < 750; i++) {
-+ SDPOKE8(sd, SDGPIO, 0xff);
-+ SDPEEK8(sd, SDGPIO); /* delay */
-+ SDPEEK8(sd, SDGPIO); /* delay */
-+ SDPOKE8(sd, SDGPIO, 0xdf);
-+ SDPEEK8(sd, SDGPIO); /* delay */
-+ SDPEEK8(sd, SDGPIO); /* delay */
-+ }
-+
-+ SDPEEK8(sd, SDSTAT2); /* reset any timeout/crc conditions */
-+ SDPOKE8(sd, SDSTAT2, 0x18);
-+ s = sdcmd2(sd, CMD_SEND_IF_COND, 0x1aa, resp, NULL);
-+ if (s) {
-+ reset_timeout(sd);
-+ x = 0x00ff0000;
-+ } else {
-+ x = 0x40ff0000;
-+ }
-+
-+ do {
-+ sdcmd2(sd, CMD_APP_CMD, 0, NULL, NULL);
-+ sdcmd2(sd, ACMD_SD_SEND_OP_COND, x, resp, NULL);
-+ if (timeout(sd)) break;
-+ // TODO: check for valid result or limit # of loops,
-+ // otherwise we may loop forever on malfunctioning cards.
-+ } while (((resp[1] & 0x80) == 0x0));
-+
-+ if ((x & 0x40000000) && (resp[1] & 0x40)) {
-+ sd->sd_state |= SD_HC;
-+ }
-+
-+ sdcmd2(sd, CMD_ALL_SEND_CID, 0, resp, NULL);
-+ sdcmd2(sd, CMD_SEND_RELATIVE_ADDR, 0, resp, NULL);
-+ rca = resp[1] << 8 | resp[2];
-+ sd->sd_rcaarg = (rca & 0xff00) << 16 | (rca & 0xff) << 16;
-+ sd->sdboot_token = ~sd->sd_rcaarg;
-+
-+ sdcmd2(sd, CMD_SEND_CSD, sd->sd_rcaarg, sd->sd_csd, NULL);
-+ sdcmd2(sd, CMD_SELECT_CARD, sd->sd_rcaarg, resp, NULL);
-+
-+ if ((resp[1] & 0x2)) {
-+ unsigned int ret = 1;
-+ sd->sd_locked = 1;
-+#ifndef SD_NOLOCKSUPPORT
-+ if (sd->sd_pwd)
-+ ret = sdlockctl2(sd, SDLOCK_UNLOCK, sd->sd_pwd, NULL);
-+#endif
-+ if (ret != 0) return 0;
-+ } else sd->sd_locked = 0;
-+
-+ sdcmd2(sd, CMD_APP_CMD, sd->sd_rcaarg, NULL, NULL);
-+ sdcmd2(sd, ACMD_SET_CLR_CARD_DETECT, 0, NULL, NULL);
-+ sdcmd2(sd, CMD_SET_BLOCKLEN, 512, NULL, NULL);
-+ sdcmd2(sd, CMD_APP_CMD, sd->sd_rcaarg, NULL, NULL);
-+ sdcmd2(sd, ACMD_SET_BUS_WIDTH, 2, resp, NULL);
-+ sd->sd_state |= DATSSP_4BIT;
-+ sd->sd_state &= ~SD_LOSPEED;
-+
-+ sdcmd2(sd, CMD_APP_CMD, sd->sd_rcaarg, NULL, NULL);
-+ sdcmd2(sd, ACMD_SEND_SCR2, 0, NULL, NULL);
-+ do {
-+ if (timeout(sd)) break;
-+ SDPOKE8(sd, SDGPIO, 0xdf);
-+ SDPEEK8(sd, SDGPIO);
-+ s = SDPEEK8(sd, SDGPIO);
-+ SDPOKE8(sd, SDGPIO, 0xff);
-+ SDPEEK8(sd, SDGPIO);
-+ } while ((s & 0xf) != 0x0);
-+ for (i = 0; i < 16; i++) {
-+ SDPOKE8(sd, SDGPIO, 0xdf);
-+ SDPEEK8(sd, SDGPIO);
-+ s = (SDPEEK8(sd, SDGPIO) & 0xf) << 4;
-+ SDPOKE8(sd, SDGPIO, 0xff);
-+ SDPEEK8(sd, SDGPIO);
-+ SDPOKE8(sd, SDGPIO, 0xdf);
-+ SDPEEK8(sd, SDGPIO);
-+ s |= (SDPEEK8(sd, SDGPIO) & 0xf);
-+ SDPOKE8(sd, SDGPIO, 0xff);
-+ SDPEEK8(sd, SDGPIO);
-+ if (i < 8) sd->sd_scr[i] = s;
-+ }
-+ for (i = 0; i < 8; i++) {
-+ SDPOKE8(sd, SDGPIO, 0xdf);
-+ SDPEEK8(sd, SDGPIO);
-+ SDPEEK8(sd, SDGPIO);
-+ SDPOKE8(sd, SDGPIO, 0xff);
-+ SDPEEK8(sd, SDGPIO);
-+ }
-+ sd->sd_state &= ~SDDAT_RX;
-+
-+#ifndef SD_NOHIGHSPEED
-+ if ((sd->sd_scr[0] & 0xf) >= 1) { // SD version >= 1.10
-+ unsigned char dat[64];
-+ sdcmd2(sd, CMD_SWITCH_FUNC2, 0x80fffff1, NULL, NULL);
-+ do {
-+ if (timeout(sd)) break;
-+ SDPOKE8(sd, SDGPIO, 0xdf);
-+ SDPEEK8(sd, SDGPIO);
-+ s = SDPEEK8(sd, SDGPIO);
-+ SDPOKE8(sd, SDGPIO, 0xff);
-+ SDPEEK8(sd, SDGPIO);
-+ } while ((s & 0xf) != 0x0);
-+ for (i = 0; i < 72; i++) {
-+ SDPOKE8(sd, SDGPIO, 0xdf);
-+ SDPEEK8(sd, SDGPIO);
-+ s = (SDPEEK8(sd, SDGPIO) & 0xf) << 4;
-+ SDPOKE8(sd, SDGPIO, 0xff);
-+ SDPEEK8(sd, SDGPIO);
-+ SDPOKE8(sd, SDGPIO, 0xdf);
-+ SDPEEK8(sd, SDGPIO);
-+ s |= (SDPEEK8(sd, SDGPIO) & 0xf);
-+ SDPOKE8(sd, SDGPIO, 0xff);
-+ SDPEEK8(sd, SDGPIO);
-+ if (i < 64) dat[i] = s;
-+ }
-+ for (i = 0; i < 8; i++) {
-+ SDPOKE8(sd, SDGPIO, 0xdf);
-+ SDPEEK8(sd, SDGPIO);
-+ SDPEEK8(sd, SDGPIO);
-+ SDPOKE8(sd, SDGPIO, 0xff);
-+ SDPEEK8(sd, SDGPIO);
-+ }
-+ sd->sd_state &= ~SDDAT_RX;
-+ if (dat[0] | dat[1]) {
-+ SDPOKE8(sd, SDSTAT2, 0x38);
-+ sd->sd_state |= SD_HISPEED;
-+ }
-+ }
-+#endif
-+
-+#ifdef BIGENDIAN
-+ if ((sd->sd_csd[15] & 0x30) || (SDPEEK16(sd, SDGPIO) & 0x2))
-+#else
-+ if ((sd->sd_csd[15] & 0x30) || (SDPEEK16(sd, SDGPIO) & 0x200))
-+#endif
-+ sd->sd_wprot = 1;
-+ sd->sd_blocksize = 1 << ((sd->sd_csd[6] & 0xf));
-+ if (timeout(sd)) return 0;
-+ else {
-+ reset_timeout(sd);
-+ return sdsize(sd);
-+ }
-+}
-+
-+/*
-+ * return 0 : 8 bit TS-SDCORE v1
-+ * return 1 : 8 bit 4x8 TS-SDCORE v2
-+ * return 2 : 32 bit 4x32 TS-SDCORE v2
-+ * return 3 : 16 bit 4x32 TS-SDCORE v2
-+ * return 4 : 8 bit 4x32 TS-SDCORE v2
-+ */
-+static int version(struct sdcore *sd)
-+{
-+ int a, b, i;
-+
-+
-+#ifdef SD_FORCEVERSION
-+ return SD_FORCEVERSION;
-+#endif
-+ for (i = 0; i < sizeof(sdcores); i++) {
-+ if (sdcores[i] == NULL) break;
-+ if (sdcores[i]->sd_regstart == sd->sd_regstart)
-+ return sdcores[i]->hw_version;
-+ }
-+
-+ a = SDPEEK8(sd, 3);
-+ SDPOKE8(sd, 3, (a ^ 0x40));
-+ b = SDPEEK8(sd, 3);
-+ SDPOKE8(sd, 3, a);
-+ if ((a & 0x40) ^ (b & 0x40)) return 0;
-+ else if (a & 0x40) return 1;
-+ /* either 2, 3, or 4 */
-+ a = SDPEEK32(sd, 12);
-+ b = SDPEEK16(sd, 12);
-+#ifdef BIGENDIAN
-+ if ((a & 0x40000000) && (b & 0x4000)) return 2;
-+#else
-+ if ((a & 0x40) && (b & 0x40)) return 2;
-+#endif
-+ a = SDPEEK8(sd, 12);
-+ if (a & 0x40) return 3;
-+ else return 4;
-+}
-+
-+int sdreset(struct sdcore *sd)
-+{
-+ unsigned int rca, s, x;
-+ unsigned int resp[17];
-+
-+ reset_timeout(sd);
-+ sd_initcrc(sd);
-+ sd->parked_sector = 0;
-+ sd->sd_wprot = 0;
-+ sd->sd_blocksize = 0;
-+ sd->sd_sz = 0;
-+
-+ sd->hw_version = version(sd);
-+ if (sd->hw_version >= 2) return sdreset2(sd);
-+
-+ // check for no SD card present
-+ if (SDPEEK8(sd, SDCTRL) & 0x8) return 0;
-+
-+ if (sd->sdboot_token) {
-+ int ret = sdfastinit(sd);
-+ sd->sdboot_token = 0;
-+ if (ret) return ret;
-+ }
-+
-+ // set controller for 1-bit mode, slow clock
-+ SDPOKE8(sd, SDCTRL, 0x20);
-+
-+ SDPOKE8(sd, SDSTATE, S_DUMMY_CLK);
-+ sd->sd_state = SDCMD_RX|SDDAT_RX;
-+ s = SDPEEK8(sd, SDSTATE);
-+ while ((s & 0x7) != S_SEND_CMD) {
-+ // If we timeout here, it would be VERY BAD as we have no
-+ // further recourse to set things right if we can't turn
-+ // the SD off.
-+ if (timeout(sd)) return 0;
-+ sd->os_delay(sd->os_arg, 10000);
-+ sd->sd_timeout += 10000;
-+
-+ // We won't be able to change state until both SSPs are empty
-+ s = tend_ssp(sd, NULL, NULL);
-+ }
-+ SDPOKE8(sd, SDSTATE, S_OFF);
-+ sd->sd_state = 0;
-+
-+ sd->os_delay(sd->os_arg, 50000);
-+
-+ SDPOKE8(sd, SDSTATE, S_DUMMY_CLK);
-+ sd->os_delay(sd->os_arg, 100000);
-+ if ((SDPEEK8(sd, SDSTATE) & 0x7) == S_OFF) {
-+ // No card present
-+ return 0;
-+ }
-+
-+ SDPOKE8(sd, SDSTATE, S_WAIT_RESP);
-+ // clock will freerun waiting for a response that will never come
-+ sd->os_delay(sd->os_arg, 50000);
-+
-+ SDPOKE8(sd, SDSTATE, S_DUMMY_CLK);
-+
-+ s = sdcmd(sd, CMD_SEND_IF_COND, 0x1aa, resp, NULL);
-+ if (s) {
-+ reset_timeout(sd);
-+ SDPOKE8(sd, SDSTATE, S_DUMMY_CLK);
-+ x = 0x00ff0000;
-+ } else {
-+ x = 0x40ff0000;
-+ }
-+
-+ do {
-+ sdcmd(sd, CMD_APP_CMD, 0, NULL, NULL);
-+ sdcmd(sd, ACMD_SD_SEND_OP_COND, x, resp, NULL);
-+ if (timeout(sd)) break;
-+ } while (((resp[1] & 0x80) == 0x0));
-+
-+ if ((x & 0x40000000) && (resp[1] & 0x40)) sd->sd_state |= SD_HC;
-+
-+ sdcmd(sd, CMD_ALL_SEND_CID, 0, resp, NULL);
-+ sdcmd(sd, CMD_SEND_RELATIVE_ADDR, 0, resp, NULL);
-+ rca = resp[1] << 8 | resp[2];
-+ sd->sd_rcaarg = (rca & 0xff00) << 16 | (rca & 0xff) << 16;
-+ sd->sdboot_token = ~sd->sd_rcaarg;
-+
-+ sdcmd(sd, CMD_SEND_CSD, sd->sd_rcaarg, sd->sd_csd, NULL);
-+ sdcmd(sd, CMD_SELECT_CARD, sd->sd_rcaarg, resp, NULL);
-+
-+ if ((resp[1] & 0x2)) {
-+ unsigned int ret = 1;
-+ sd->sd_locked = 1;
-+#ifndef SD_NOLOCKSUPPORT
-+ if (sd->sd_pwd)
-+ ret = sdlockctl(sd, SDLOCK_UNLOCK, sd->sd_pwd, NULL);
-+#endif
-+ if (ret != 0) return 0;
-+ } else sd->sd_locked = 0;
-+
-+ sdcmd(sd, CMD_APP_CMD, sd->sd_rcaarg, NULL, NULL);
-+ sdcmd(sd, ACMD_SET_CLR_CARD_DETECT, 0, NULL, NULL);
-+ /*
-+ sdcmd(sd, CMD_APP_CMD, sd->sd_rcaarg, NULL, NULL);
-+ sdcmd(sd, ACMD_SEND_SCR, 0, NULL, &datptr);
-+ while ((datptr - sd->sd_scr) != 8) {
-+ if (timeout(sd)) return 1;
-+ tend_ssp(sd, NULL, &datptr);
-+ }
-+ datssp_stream(sd, NULL, 3);
-+ SDPOKE8(sd, SDSTATE, (TYPE_ABORT << 5) | S_SEND_CMD);
-+ sd->sd_state |= SDCMD_RX|SDDAT_RX;
-+ while ((SDPEEK8(sd, SDSTATE) & 0x17) != S_SEND_CMD) {
-+ if (timeout(sd)) break;
-+ tend_ssp(sd, NULL, NULL);
-+ }
-+ sd->sd_state &= ~(SDCMD_RX|SDDAT_RX);
-+ if ((sd->sd_scr[0] & 0xf) >= 1) { // SD version >= 1.10
-+ unsigned char dat[64];
-+ datptr = dat;
-+ sdcmd(sd, CMD_SWITCH_FUNC, 0x80fffff1, NULL, &datptr);
-+ while ((datptr - dat) != 64) {
-+ if (timeout(sd)) break;
-+ tend_ssp(sd, NULL, &datptr);
-+ }
-+ datssp_stream(sd, NULL, 3);
-+ SDPOKE8(sd, SDSTATE, (TYPE_ABORT << 5) | S_SEND_CMD);
-+ sd->sd_state |= SDCMD_RX|SDDAT_RX;
-+ while ((SDPEEK8(sd, SDSTATE) & 0x7) != S_SEND_CMD) {
-+ if (timeout(sd)) break;
-+ tend_ssp(sd, NULL, NULL);
-+ }
-+ sd->sd_state &= ~(SDCMD_RX|SDDAT_RX);
-+ }
-+ */
-+
-+ sdcmd(sd, CMD_SET_BLOCKLEN, 512, NULL, NULL);
-+ sdcmd(sd, CMD_APP_CMD, sd->sd_rcaarg, NULL, NULL);
-+ sdcmd(sd, ACMD_SET_BUS_WIDTH, 2, resp, NULL);
-+
-+ // set controller for 4-bit mode, fast clock
-+ SDPOKE8(sd, SDCTRL, (0x40 | (sd->os_dmastream ? 0x2 : 0x0)));
-+ sd->sd_state |= DATSSP_4BIT;
-+
-+ /*
-+ sdcmd(sd, CMD_APP_CMD, sd->sd_rcaarg, NULL, NULL);
-+ sdcmd(sd, ACMD_SEND_SCR, 0, NULL, &datptr);
-+ while ((datptr - sd->sd_scr) != 8) {
-+ if (timeout(sd)) break;
-+ tend_ssp(sd, NULL, &datptr);
-+ }
-+ datssp_stream(sd, NULL, 6);
-+ SDPOKE8(sd, SDSTATE, S_DUMMY_CLK | (TYPE_SHORTRESP << 5));
-+ bzero(resp, 6 * 4);
-+ sdcmd(sd, CMD_SEND_STATUS, 0, resp, NULL);
-+ */
-+
-+ if ((SDPEEK8(sd, SDCTRL) & 0x80) || (sd->sd_csd[15] & 0x30))
-+ sd->sd_wprot = 1;
-+ sd->sd_blocksize = 1 << ((sd->sd_csd[6] & 0xf));
-+ if (timeout(sd) || error(resp, ACMD_SET_BUS_WIDTH)) return 0;
-+ else return sdsize(sd);
-+}
-+
-+static
-+int sdread2(struct sdcore *sd, unsigned int sector, unsigned char *dat,
-+ int nsectors)
-+{
-+ struct sdiov iov;
-+ int ret;
-+
-+ iov.sdiov_base = dat;
-+ iov.sdiov_nsect = nsectors;
-+ ret = do_read2(sd, sector, &iov, 1);
-+ return ret;
-+}
-+
-+int sdread(struct sdcore *sd, unsigned int sector, unsigned char *dat,
-+ int nsectors)
-+{
-+ struct sdiov iov;
-+ int ret;
-+
-+ iov.sdiov_base = dat;
-+ iov.sdiov_nsect = nsectors;
-+ if (sd->hw_version == 0) ret = do_read(sd, sector, &iov, 1);
-+ else ret = do_read2(sd, sector, &iov, 1);
-+ return ret;
-+}
-+
-+int sdwrite(struct sdcore *sd, unsigned int sector, unsigned char *dat,
-+ int nsectors)
-+{
-+ struct sdiov iov;
-+ unsigned int ret;
-+
-+ iov.sdiov_base = dat;
-+ iov.sdiov_nsect = nsectors;
-+ if (sd->hw_version == 0) ret = do_write(sd, sector, &iov, 1);
-+ else ret = do_write2(sd, sector, &iov, 1);
-+ return ret;
-+
-+}
-+
-+int sdreadv(struct sdcore *sd, unsigned int sector, struct sdiov *iov,
-+ int niov)
-+{
-+ if (sd->hw_version == 0) return do_read(sd, sector, iov, niov);
-+ else return do_read2(sd, sector, iov, niov);
-+}
-+
-+int sdwritev(struct sdcore *sd, unsigned int sector, struct sdiov *iov,
-+ int niov)
-+{
-+ if (sd->hw_version == 0) return do_write(sd, sector, iov, niov);
-+ else return do_write2(sd, sector, iov, niov);
-+}
-+
-+static
-+int sdsetwprot2(struct sdcore *sd, unsigned int perm)
-+{
-+ int i, ret, s;
-+ unsigned int csd[16], resp[6];
-+ unsigned char csdchars[16];
-+ unsigned char *csdptr = csdchars;
-+
-+ stop2(sd);
-+
-+ perm = perm ? 0x3 : 0x1;
-+ for (i = 0; i < 16; i++) csd[i] = sd->sd_csd[i + 1];
-+ csd[14] &= ~(0x3 << 4);
-+ csd[14] |= (perm << 4);
-+ csd[15] = 0x1 | crc7(0, csd, 15) << 1;
-+ for (i = 0; i < 16; i++) csdchars[i] = csd[i];
-+
-+ ret = sdcmd2(sd, CMD_PROGRAM_CSD, 0, resp, NULL);
-+ if (ret || error(resp, CMD_PROGRAM_CSD)) return 1;
-+ for (i = 0; i < 16; i++) {
-+ s = *csdptr++;
-+ sd_4bit_feedcrc(sd, s);
-+ SDPOKE8(sd, SDGPIO, (0x10|((s & 0xf0) >> 4)));
-+ SDPEEK8(sd, SDGPIO);
-+ SDPEEK8(sd, SDGPIO);
-+ SDPOKE8(sd, SDGPIO, (0x30|((s & 0xf0) >> 4)));
-+ SDPEEK8(sd, SDGPIO);
-+ SDPOKE8(sd, SDGPIO, (0x10|(s & 0xf)));
-+ SDPEEK8(sd, SDGPIO);
-+ SDPEEK8(sd, SDGPIO);
-+ SDPOKE8(sd, SDGPIO, (0x30|(s & 0xf)));
-+ SDPEEK8(sd, SDGPIO);
-+ }
-+ for (i = 0; i < 8; i++) {
-+ s = sd_4bit_getcrc(sd);
-+ SDPOKE8(sd, SDGPIO, (0x10|((s & 0xf0) >> 4)));
-+ SDPEEK8(sd, SDGPIO);
-+ SDPEEK8(sd, SDGPIO);
-+ SDPOKE8(sd, SDGPIO, (0x30|((s & 0xf0) >> 4)));
-+ SDPEEK8(sd, SDGPIO);
-+ SDPOKE8(sd, SDGPIO, (0x10|(s & 0xf)));
-+ SDPEEK8(sd, SDGPIO);
-+ SDPEEK8(sd, SDGPIO);
-+ SDPOKE8(sd, SDGPIO, (0x30|(s & 0xf)));
-+ SDPEEK8(sd, SDGPIO);
-+ }
-+ // End bit
-+ SDPOKE8(sd, SDGPIO, 0x1f);
-+ SDPEEK8(sd, SDGPIO);
-+ SDPEEK8(sd, SDGPIO);
-+ SDPOKE8(sd, SDGPIO, 0x3f);
-+ SDPEEK8(sd, SDGPIO);
-+ SDPOKE8(sd, SDGPIO, 0xbf); // tristate dat
-+ // CRC ack
-+ s = 0;
-+ for (i = 0; i < 7; i++) {
-+ SDPOKE8(sd, SDGPIO, 0x9f); // clk negedge
-+ SDPEEK8(sd, SDGPIO); // delay
-+ s = s << 1;
-+ s |= (SDPEEK8(sd, SDGPIO) & 0x1);
-+ SDPOKE8(sd, SDGPIO, 0xbf); // clk posedge
-+ }
-+ if ((s & 0xf) != 0x5) return 1;
-+ // wait for unbusy
-+ s = 0;
-+ while ((s & 0x7) != 0x7) {
-+ if (timeout(sd)) break;
-+ SDPOKE8(sd, SDGPIO, 0x9f); // clk negedge
-+ SDPEEK8(sd, SDGPIO); // delay
-+ s = s << 1;
-+ s |= SDPEEK8(sd, SDGPIO) & 0x1;
-+ SDPOKE8(sd, SDGPIO, 0xbf);
-+ }
-+ for (i = 0; i < 8; i++) {
-+ SDPOKE8(sd, SDGPIO, 0x9f);
-+ SDPEEK8(sd, SDGPIO);
-+ SDPEEK8(sd, SDGPIO);
-+ SDPOKE8(sd, SDGPIO, 0xbf);
-+ SDPEEK8(sd, SDGPIO);
-+ }
-+ sd->sd_state &= ~SDDAT_TX;
-+
-+ sdcmd2(sd, CMD_DESELECT_CARD, ~sd->sd_rcaarg, NULL, NULL);
-+ ret = sdcmd2(sd, CMD_SEND_CSD, sd->sd_rcaarg, sd->sd_csd, NULL);
-+ if (ret || sd->sd_csd[15] != csd[14]) {
-+ return 1;
-+ }
-+ sdcmd2(sd, CMD_SELECT_CARD, sd->sd_rcaarg, resp, NULL);
-+
-+ sd->sd_wprot = 1;
-+ return 0;
-+}
-+
-+int sdsetwprot(struct sdcore *sd, unsigned int perm)
-+{
-+ int i, ret;
-+ unsigned int csd[16], resp[6];
-+ unsigned char csdchars[16];
-+ unsigned char *csdptr = csdchars;
-+
-+ if (sd->hw_version) return sdsetwprot2(sd, perm);
-+
-+ if (stop(sd)) return 1;
-+
-+ perm = perm ? 0x3 : 0x1;
-+ for (i = 0; i < 16; i++) csd[i] = sd->sd_csd[i + 1];
-+ csd[14] &= ~(0x3 << 4);
-+ csd[14] |= (perm << 4);
-+ csd[15] = 0x1 | crc7(0, csd, 15) << 1;
-+ for (i = 0; i < 16; i++) csdchars[i] = csd[i];
-+
-+ ret = sdcmd(sd, CMD_PROGRAM_CSD, 0, resp, NULL);
-+ if (ret || error(resp, CMD_PROGRAM_CSD)) return 1;
-+ datssp_stream(sd, &csdptr, 16);
-+ datssp_stream(sd, NULL, 8);
-+ SDPOKE8(sd, SDSTATE, S_CRC_CHECK | (TYPE_BSYRESP << 5));
-+ sd->sd_state &= ~SDDAT_TX;
-+
-+ sdcmd(sd, CMD_DESELECT_CARD, ~sd->sd_rcaarg, NULL, NULL);
-+ ret = sdcmd(sd, CMD_SEND_CSD, sd->sd_rcaarg, sd->sd_csd, NULL);
-+ if (ret || sd->sd_csd[15] != csd[14]) {
-+ return 1;
-+ }
-+ sdcmd(sd, CMD_SELECT_CARD, sd->sd_rcaarg, resp, NULL);
-+
-+ sd->sd_wprot = 1;
-+ return 0;
-+}
-+
-+#ifndef SD_NOLOCKSUPPORT
-+int sdlockctl(struct sdcore *sd, unsigned int cmd, unsigned char *pwd,
-+ unsigned char *sdbootdat)
-+{
-+ unsigned char pwddat[18];
-+ unsigned char *pwdptr = pwddat;
-+ unsigned int resp[6];
-+ int ret, i, len;
-+ int ccc = (sd->sd_csd[5] << 4) | (sd->sd_csd[6] >> 4);
-+
-+ if (sd->hw_version) return sdlockctl2(sd, cmd, pwd, sdbootdat);
-+
-+ if (!(ccc & 0x80)) return 1; // Class 7 is lock-unlock commands
-+
-+ if (pwd == NULL && cmd != SDLOCK_ERASE) return 1;
-+
-+ if (stop(sd)) return 1;
-+
-+ if (sd->sd_state & DATSSP_4BIT) {
-+ int oldctrl = SDPEEK8(sd, SDCTRL);
-+ int ret;
-+
-+ sdcmd(sd, CMD_APP_CMD, sd->sd_rcaarg, NULL, NULL);
-+ sdcmd(sd, ACMD_SET_BUS_WIDTH, 0, NULL, NULL);
-+ SDPOKE8(sd, SDCTRL, 0x20);
-+ sd->sd_state &= ~DATSSP_4BIT;
-+ ret = sdlockctl(sd, cmd, pwd, sdbootdat);
-+ sdcmd(sd, CMD_APP_CMD, sd->sd_rcaarg, NULL, NULL);
-+ sdcmd(sd, ACMD_SET_BUS_WIDTH, 2, NULL, NULL);
-+ sd->sd_state |= DATSSP_4BIT;
-+ SDPOKE8(sd, SDCTRL, oldctrl);
-+ return ret;
-+ }
-+
-+ pwddat[0] = cmd;
-+ if (cmd != SDLOCK_ERASE) {
-+ pwddat[1] = 16; // length
-+ for (i = 0; i < 16; i++) {
-+ pwddat[2 + i] = pwd[i];
-+ }
-+ }
-+
-+ if (cmd == SDLOCK_ERASE) len = 1; else len = 18;
-+ ret = sdcmd(sd, CMD_SET_BLOCKLEN, len, resp, NULL);
-+ if (ret || error(resp, CMD_SET_BLOCKLEN)) return 1;
-+ ret = sdcmd(sd, CMD_LOCK_UNLOCK, 0, resp, NULL);
-+ if (ret || error(resp, CMD_LOCK_UNLOCK)) return 1;
-+
-+ while ((pwdptr - pwddat) != len) {
-+ if (timeout(sd)) return 1;
-+ tend_ssp(sd, NULL, &pwdptr);
-+ }
-+
-+ if (sd->sd_state & DATSSP_4BIT) datssp_stream(sd, NULL, 8);
-+ else datssp_stream(sd, NULL, 2);
-+
-+ SDPOKE8(sd, SDSTATE, S_CRC_CHECK | (TYPE_BSYRESP << 5));
-+ sd->sd_state &= ~SDDAT_TX;
-+ ret = sdcmd(sd, CMD_SET_BLOCKLEN, 512, resp, NULL);
-+ if (ret || error(resp, CMD_SET_BLOCKLEN)) return 1;
-+ ret = sdcmd(sd, CMD_SEND_STATUS, sd->sd_rcaarg, resp, NULL);
-+ if (ret || error(resp, CMD_SEND_STATUS)) return 1;
-+
-+ if ((cmd == SDLOCK_ERASE || cmd == SDLOCK_UNLOCK ||
-+ cmd == SDLOCK_CLRPWD) && (resp[1] & 0x2)) {
-+ return 1;
-+ }
-+
-+ if (sdbootdat) {
-+ sdbootdat[0] = SDLOCK_UNLOCK;
-+ for (i = 1; i < 18; i++) {
-+ sdbootdat[i] = pwddat[i];
-+ sd_1bit_feedcrc(sd, pwddat[i]);
-+ }
-+ sdbootdat[18] = sd_1bit_getcrc(sd);
-+ sdbootdat[19] = sd_1bit_getcrc(sd);
-+ }
-+
-+ return 0;
-+}
-+
-+static
-+int sdlockctl2(struct sdcore *sd, unsigned int cmd, unsigned char *pwd,
-+ unsigned char *sdbootdat)
-+{
-+ unsigned char pwddat[18];
-+ unsigned char *pwdptr = pwddat;
-+ unsigned int resp[6];
-+ int ret, i, j, len, s;
-+ int ccc = (sd->sd_csd[5] << 4) | (sd->sd_csd[6] >> 4);
-+
-+ if (!(ccc & 0x80)) return 1; // Class 7 is lock-unlock commands
-+
-+ if (pwd == NULL && cmd != SDLOCK_ERASE) return 1;
-+
-+ stop2(sd);
-+
-+ if (sd->sd_state & DATSSP_4BIT) {
-+ int ret;
-+
-+ sdcmd2(sd, CMD_APP_CMD, sd->sd_rcaarg, NULL, NULL);
-+ sdcmd2(sd, ACMD_SET_BUS_WIDTH, 0, NULL, NULL);
-+ sd->sd_state &= ~DATSSP_4BIT;
-+ ret = sdlockctl2(sd, cmd, pwd, sdbootdat);
-+ sdcmd2(sd, CMD_APP_CMD, sd->sd_rcaarg, NULL, NULL);
-+ sdcmd2(sd, ACMD_SET_BUS_WIDTH, 2, NULL, NULL);
-+ sd->sd_state |= DATSSP_4BIT;
-+ return ret;
-+ }
-+
-+ pwddat[0] = cmd;
-+ if (cmd != SDLOCK_ERASE) {
-+ pwddat[1] = 16; // length
-+ for (i = 0; i < 16; i++) {
-+ pwddat[2 + i] = pwd[i];
-+ }
-+ }
-+
-+ if (cmd == SDLOCK_ERASE) len = 1; else len = 18;
-+ ret = sdcmd2(sd, CMD_SET_BLOCKLEN, len, resp, NULL);
-+ if (ret || error(resp, CMD_SET_BLOCKLEN)) return 1;
-+ ret = sdcmd2(sd, CMD_LOCK_UNLOCK, 0, resp, NULL);
-+ if (ret || error(resp, CMD_LOCK_UNLOCK)) return 1;
-+
-+ for (i = 0; i < len; i++) {
-+ unsigned int b = *pwdptr++;
-+ unsigned int x;
-+
-+ sd_1bit_feedcrc(sd, b);
-+ for (j = 0; j < 8; j++) {
-+ x = 0x1e | ((b >> 7) & 0x1);
-+ b = b << 1;
-+ SDPOKE8(sd, SDGPIO, x); // clk negedge
-+ SDPEEK8(sd, SDGPIO);
-+ SDPEEK8(sd, SDGPIO);
-+ x |= 0x20;
-+ SDPOKE8(sd, SDGPIO, x); // clk posedge
-+ SDPEEK8(sd, SDGPIO);
-+ }
-+ }
-+ for (i = 0; i < 2; i++) {
-+ unsigned int b = sd_1bit_getcrc(sd);
-+ unsigned int x;
-+
-+ for (j = 0; j < 8; j++) {
-+ x = 0x1e | ((b >> 7) & 0x1);
-+ b = b << 1;
-+ SDPOKE8(sd, SDGPIO, x); // clk negedge
-+ SDPEEK8(sd, SDGPIO);
-+ SDPEEK8(sd, SDGPIO);
-+ x |= 0x20;
-+ SDPOKE8(sd, SDGPIO, x); // clk posedge
-+ SDPEEK8(sd, SDGPIO);
-+ }
-+ }
-+ // End bit
-+ SDPOKE8(sd, SDGPIO, 0x1f); // clk negedge
-+ SDPEEK8(sd, SDGPIO);
-+ SDPOKE8(sd, SDGPIO, 0xbf); // clk posedge, tristate dat
-+ // CRC ack
-+ s = 0;
-+ for (i = 0; i < 7; i++) {
-+ SDPOKE8(sd, SDGPIO, 0x9f); // clk negedge
-+ SDPEEK8(sd, SDGPIO); // delay
-+ s = s << 1;
-+ s |= SDPEEK8(sd, SDGPIO) & 0x1;
-+ SDPOKE8(sd, SDGPIO, 0xbf); // clk posedge
-+ SDPEEK8(sd, SDGPIO);
-+ }
-+ if ((s & 0xf) != 0x5) return 1;
-+
-+ // wait for unbusy
-+ s = 0;
-+ while ((s & 0x7) != 0x7) {
-+ if (timeout(sd)) break;
-+ SDPOKE8(sd, SDGPIO, 0x9f); // clk negedge
-+ SDPEEK8(sd, SDGPIO); // delay
-+ s = s << 1;
-+ s |= SDPEEK8(sd, SDGPIO) & 0x1;
-+ SDPOKE8(sd, SDGPIO, 0xbf);
-+ SDPEEK8(sd, SDGPIO);
-+ }
-+ for (i = 0; i < 8; i++) {
-+ SDPOKE8(sd, SDGPIO, 0x9f);
-+ SDPEEK8(sd, SDGPIO);
-+ SDPEEK8(sd, SDGPIO);
-+ SDPOKE8(sd, SDGPIO, 0xbf);
-+ SDPEEK8(sd, SDGPIO);
-+ }
-+
-+ sd->sd_state &= ~SDDAT_TX;
-+ ret = sdcmd2(sd, CMD_SET_BLOCKLEN, 512, resp, NULL);
-+ if (ret || error(resp, CMD_SET_BLOCKLEN)) {
-+ return 1;
-+ }
-+ ret = sdcmd2(sd, CMD_SEND_STATUS, sd->sd_rcaarg, resp, NULL);
-+ if (ret || error(resp, CMD_SEND_STATUS)) {
-+ return 1;
-+ }
-+
-+ if ((cmd == SDLOCK_ERASE || cmd == SDLOCK_UNLOCK ||
-+ cmd == SDLOCK_CLRPWD) && (resp[1] & 0x2)) {
-+ return 1;
-+ }
-+
-+ if (sdbootdat) {
-+ sdbootdat[0] = SDLOCK_UNLOCK;
-+ for (i = 1; i < 18; i++) {
-+ sdbootdat[i] = pwddat[i];
-+ sd_1bit_feedcrc(sd, pwddat[i]);
-+ }
-+ sdbootdat[18] = sd_1bit_getcrc(sd);
-+ sdbootdat[19] = sd_1bit_getcrc(sd);
-+ }
-+
-+ for (i = 0; i < 8; i++) {
-+ SDPOKE8(sd, SDGPIO, 0x9f);
-+ SDPEEK8(sd, SDGPIO);
-+ SDPEEK8(sd, SDGPIO);
-+ SDPOKE8(sd, SDGPIO, 0xbf);
-+ SDPEEK8(sd, SDGPIO);
-+ }
-+ return 0;
-+}
-+#endif
-diff --git a/drivers/block/sdcore2.h b/drivers/block/sdcore2.h
-new file mode 100644
-index 0000000..38d5b96
---- /dev/null
-+++ b/drivers/block/sdcore2.h
-@@ -0,0 +1,372 @@
-+/*
-+ * Copyright (c) 2006-2008, Technologic Systems
-+ * All rights reserved.
-+ */
-+
-+#ifndef _SDCORE_H_
-+#define _SDCORE_H_
-+
-+// Additional missing defs
-+#define SDCMD 0 // cmd register
-+#define SDDAT 1 // data register
-+#define SDSTATE 2 // state register
-+#define SDCTRL 3 // ctrl register
-+
-+
-+// this bit is set when no card inserted
-+#define SDCTRL_CARD_ABSENT 0x08
-+
-+
-+
-+/* public bits for sd_state bitfield, can be read from client code.
-+ * Do not write! Other bits are used internally.
-+ */
-+#define SDDAT_RX (1<<0)
-+#define SDDAT_TX (1<<1)
-+#define SDCMD_RX (1<<2)
-+#define SDCMD_TX (1<<3)
-+
-+// used to disable CRC calculations in write mode
-+#define SDCRC_DISABLE (1 << 4)
-+
-+
-+
-+// used to choose between 4 bit crc mode and 1 bit crc mode
-+
-+// note - likely set in sdreset when configuring interface bit width
-+#define SDSSP_4BIT_MODE (1 << 5)
-+
-+// SD_ADDRESSING_DIRECT means that sd card addresses
-+// will be communicated in read/write mode using
-+// full offsets, not 512 byte block offsets.
-+// the core will mulitply the address by 512 if this
-+// bit is cleared
-+#define SD_ADDRESSING_DIRECT (1 << 6)
-+
-+
-+/* These structs should start intialized to all 0's (bzero()'ed). Proper
-+ * operation can be assured by setting sd_regstart, and the os_delay
-+ * callback. sdreset() should be called to initialize the core, then
-+ * sdread() and sdwrite() can be used.
-+ */
-+struct sdcore {
-+ /* virtual address of SD block register start, to be filled in
-+ * by client code before calling any sdcore functions.
-+ */
-+ // 0-3
-+ unsigned char* sd_regstart;
-+
-+
-+
-+ // 4-7
-+ unsigned int sd_state;
-+
-+ /* Erase hint for subsequent sdwrite() call, used to optimize
-+ * write throughput on multi-sector writes by pre-erasing this
-+ * many sectors.
-+ */
-+ // 8-11
-+ unsigned int sd_erasehint;
-+
-+ /* Following this comment are 5 function pointer declarations to
-+ * OS helper functions. The 'os_arg' member is passed as the
-+ * first argument to the helpers and should be set by
-+ * client code before issueing sdreset()
-+ *
-+ * os_dmastream(os_arg, buf, buflen)
-+ * This function should look at sd_state and set up and run an
-+ * appropriate DMA transfer. If buf is NULL, callee doesn't care
-+ * about the actual data sent/received and helper function
-+ * can do whatever it wants. Should return 0 when DMA transfer was
-+ * run and completed successfully. If this function pointer is
-+ * NULL, PIO methods of transfer will be used instead of DMA.
-+ *
-+ * os_dmaprep(os_arg, buf, buflen)
-+ * This function is used to prepare an area of memory for a possible
-+ * DMA transfer. This function is called once per distinct buffer
-+ * passed in. After this function is called, os_dmastream() may be
-+ * called one or more times (for sequential addresses) on subregions
-+ * of the address range passed here. Should write-back or invalidate
-+ * L1 cache lines and possibly look up physical addresses for buf
-+ * passed in if I/O buffers. If 'os_dmaprep' is set to NULL, function
-+ * call will not happen. (though os_dmastream() calls may still)
-+ *
-+ * os_delay(os_arg, microseconds)
-+ * This function is supposed to delay or stall the processor for
-+ * the passed in value number of microseconds.
-+ *
-+ * os_irqwait(os_arg, type)
-+ * Called at certain times to request to be put to sleep/block until
-+ * an SD interrupt occurs. It is not critical to set this function.
-+ * When NULL, the sdcore routines simply busy-wait.
-+ *
-+ * os_powerok(os_arg)
-+ * Experimental callback function -- set to NULL for now.
-+ */
-+ // 12-15
-+ void *os_arg;
-+ // 16-19
-+ int (*os_dmastream)(void *, unsigned char *, unsigned int);
-+ // 20-23
-+ void (*os_dmaprep)(void *, unsigned char *, unsigned int);
-+ // 24-27
-+ void (*os_delay)(void *, unsigned int);
-+ // 28-31
-+ void (*os_irqwait)(void *, unsigned int);
-+ // 32-35
-+ int (*os_powerok)(void *);
-+
-+ int (*os_timeout)(void *);
-+ int (*os_reset_timeout)(void *);
-+
-+ /* If the SD card last successfully reset is write protected, this
-+ * member will be non-zero.
-+ */
-+ // 36-39
-+ unsigned int sd_wprot;
-+
-+ /* If this card may have been already initialized by TS-SDBOOT, place
-+ * the magic token it placed in the EP93xx SYSCON ScratchReg1 here
-+ * before calling sdreset() to avoid re-initialization.
-+ */
-+ // 40-43
-+ unsigned int sdboot_token;
-+
-+ /* CRC hint for subsequent sdwrite() call, used to optimize
-+ * write throughput while using DMA by pre-calculating CRC's for
-+ * next write. NULL means no hint supplied.
-+ */
-+ // 44-47
-+ unsigned char *sd_crchint;
-+
-+ /* The block size of the memory device. Normally 512, but can be 1024
-+ * for larger cards. Read-only member and actually not very useful.
-+ */
-+ // 48-51
-+ unsigned int sd_blocksize;
-+
-+ /* Password for auto-unlocking in sdreset()
-+ */
-+ // 52-55
-+ unsigned char *sd_pwd;
-+
-+ /* If the SD card was password locked, this will be non-zero after
-+ * unsuccessful sdreset().
-+ */
-+ // 56-59
-+ unsigned int sd_locked;
-+
-+ /* Whether or not writes can be parked. Definitely should be set to 1
-+ * as writes are very slow without it.
-+ */
-+ // 60-63
-+ unsigned int sd_writeparking;
-+
-+ /* Logical unit number. Some SD cores will have multiple card slots.
-+ * LUN #0 is the first.
-+ */
-+ // 64-67
-+ unsigned int sd_lun;
-+
-+ /* The rest of these members are for private internal use and should
-+ * not be of interest to client code.
-+ */
-+
-+
-+ // 68-71
-+ unsigned int rca; // relative card address
-+
-+
-+ unsigned int sd_csd[17];
-+ /*
-+
-+
-+ // 72 -75 0
-+ unsigned int unknown72; // one of the csds?
-+
-+ // 76 -79 1
-+ unsigned int unknown76; // csd 0x00
-+ // 80 -83 2
-+ unsigned int unknown04; // csd 0x01
-+ // 84 - 87 3
-+ unsigned int unknown05; // csd 0x02
-+ // 88 - 91 4
-+ unsigned int unknown06; // csd 0x03
-+ // 92 - 95 5
-+ unsigned int unknown92; // csd 0x04
-+ // 96 - 100 6
-+ unsigned int unknown96; // csd 0x05
-+ // 100 - 103 7
-+ unsigned int unknown100; // csd 0x06
-+ // 104 - 107 8
-+ unsigned int unknown104; // csd 0x07
-+ // 108 - 111 9
-+ unsigned int unknown108; // csd 0x08
-+ // 112 - 115 10
-+ unsigned int unknown112; // csd 0x09
-+ // 116 - 119 11
-+ unsigned int unknown116; // csd 0x0a
-+ // 120 12
-+ unsigned int unknown24; // csd 0x0b
-+ // 124 13
-+ unsigned int unknown25; // csd 0x0c
-+ // 128 14
-+ unsigned int unknown26; // csd 0x0d
-+ // 132 15
-+ unsigned int unknown132; // csd 0x0e
-+ // 136 16
-+ unsigned int unknown28; // csd 0x0f
-+ */
-+
-+
-+ // 140
-+ unsigned int sd_crc_shift;
-+
-+ // 144 + 4 + 4
-+ unsigned short s_crc_table[4]; // 4 shorts
-+ // 152 + 4 + 4 + 4 + 4
-+ unsigned int l_crc_table[4]; // 4 longs
-+
-+ // 168
-+ unsigned int sd_timeout; // used to busy wait
-+
-+ // 172
-+ unsigned int sd_cur_sector; // stop indicator - if zero , then stop procedure will be skipped
-+
-+ // 176
-+ unsigned int sdcore_version; // hardware version
-+ // 180
-+ unsigned int unknown39;
-+ // 184
-+ unsigned int unknown40;
-+ // 188
-+ unsigned int sdcore_sdsize;
-+
-+
-+
-+ unsigned int unknown42;
-+ unsigned int unknown43;
-+ unsigned int unknown44;
-+ unsigned int unknown45;
-+ unsigned int unknown46;
-+ unsigned int unknown47;
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+};
-+
-+/* I believe sdcores is a table mapping
-+ id -> sdcore struct. The table is
-+ 64 long, meaning that one could build a ts device with
-+ 64 sdcores on it.
-+*/
-+//extern unsigned char sdcores[256];
-+
-+
-+
-+
-+/* For sdreadv() / sdwritev() */
-+struct sdiov {
-+ unsigned char *sdiov_base;
-+ unsigned int sdiov_nsect;
-+};
-+
-+
-+
-+
-+int sdreset(struct sdcore *);
-+
-+int sdsize(struct sdcore* sdcore);
-+
-+
-+int sdread(struct sdcore* sdcore,
-+ unsigned int sector,
-+ unsigned char* buffer,
-+ int nsect);
-+
-+int sdwrite(struct sdcore *, unsigned int, unsigned char *, int);
-+
-+
-+// same signature as do_read
-+int do_read(struct sdcore*, unsigned int, struct sdiov*, int);
-+int sdreadv(struct sdcore * sdcore,
-+ unsigned int sector,
-+ struct sdiov * sdiov,
-+ int nsdiov);
-+
-+// same signature as do_write
-+int do_write(struct sdcore* sdcore,
-+ unsigned int sector,
-+ struct sdiov* sdiov,
-+ int nsdiov);
-+
-+int sdwritev(struct sdcore *, unsigned int, struct sdiov *, int);
-+
-+
-+void sd_1bit_feedcrc(struct sdcore*, unsigned int);
-+void sd_4bit_feedcrc(struct sdcore*, unsigned int);
-+
-+unsigned char sd_1bit_getcrc(struct sdcore*);
-+unsigned char sd_4bit_getcrc(struct sdcore*);
-+
-+/** stop takes only sdcore parameters */
-+int stop(struct sdcore*);
-+
-+
-+int tend_ssp(struct sdcore* sdcore,
-+ unsigned int** unknown_r1, // r1
-+ unsigned char** unknown_r2);
-+
-+
-+int datssp_stream(struct sdcore* sdcore,
-+ unsigned char** data,
-+ int count);
-+
-+/*
-+ * @param cmd is the command - I believe that the lower byte is the command, and
-+ * the upper one is the crc
-+ *
-+ * @param data is a character buffer for data received in the ssp dat register, as
-+ * a result of a command execution.
-+ */
-+
-+int sdcmd(struct sdcore* sdcore,
-+ unsigned short cmd,
-+ unsigned int sdargs,
-+ unsigned int* response,
-+ unsigned char** data); // command response buffer?
-+
-+
-+/**
-+ * Error tests if a sdcommand error has been received.
-+ * It does this by checking that the command was
-+ * correctly returned by the card (the first byte in buffer),
-+ * and that a CRC error has not occurred. IF one has occurred
-+ * it will attempt a 1bit fix. (suspected)
-+ */
-+int error(unsigned int* buffer, unsigned int cmd);
-+
-+
-+
-+int sdsetwprot(struct sdcore *, unsigned int);
-+#define SDLOCK_UNLOCK 0
-+#define SDLOCK_SETPWD 1
-+#define SDLOCK_CLRPWD 2
-+#define SDLOCK_ERASE 8
-+
-+int sdlockctl(struct sdcore *,
-+ unsigned int, // op code
-+ unsigned char *,
-+ unsigned char *);
-+
-+#endif
-diff --git a/drivers/block/tssdcard.c b/drivers/block/tssdcard.c
-new file mode 100644
-index 0000000..c76d9a7
---- /dev/null
-+++ b/drivers/block/tssdcard.c
-@@ -0,0 +1,415 @@
-+/*
-+ * TS SD Card device driver
-+ *
-+ * (c) Copyright 2010 Matthieu Crapet <mcrapet@gmail.com>
-+ * Based on Technologic Systems & Breton M. Saunders work
-+ *
-+ * 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.
-+ *
-+ * Notes:
-+ * - request processing method is: no request queue
-+ * - no M2M DMA is used
-+ */
-+
-+#include <linux/kernel.h>
-+#include <linux/init.h>
-+#include <linux/module.h>
-+#include <linux/moduleparam.h>
-+#include <linux/major.h>
-+#include <linux/blkdev.h>
-+#include <linux/bio.h>
-+#include <linux/delay.h>
-+#include <linux/hdreg.h>
-+#include <linux/slab.h>
-+#include <linux/platform_device.h>
-+
-+#include "sdcore2.h"
-+
-+#define SDCARD_DEV_NAME "tssd" /* will appear in /proc/partitions & /sys/class/block */
-+#define SD_SHIFT 4 /* max 16 partitions = 1 << 4 */
-+
-+#define KERN_SECTOR_SIZE 512 /* in bytes */
-+#define HARD_SECTOR_SIZE 512 /* in bytes */
-+#define HARD_2_KERN_SECTOR_RATIO 1 /* 1 kernel sector = 1 hardware sector */
-+
-+
-+struct ts72xx_sdcard_device {
-+ struct sdcore tssdcore; /* Physical core layer */
-+ void __iomem *mmio_base;
-+ long size; /* Device size in (hardware) sectors */
-+ int id;
-+ int media_change;
-+ int users;
-+
-+ spinlock_t lock;
-+ struct device *dev;
-+ struct request_queue *queue;
-+ struct gendisk *disk;
-+};
-+
-+
-+/*
-+ * Low level function to handle an I/O request
-+ */
-+static inline int sdcard_ll_transfer(struct ts72xx_sdcard_device *dev,
-+ unsigned long sector, unsigned long nsect, char *buffer, int rw)
-+{
-+ int ret;
-+
-+ //spin_unlock(&dev->lock); // ???
-+
-+ if ((sector + nsect) > (dev->size * HARD_2_KERN_SECTOR_RATIO)) {
-+ dev_err(dev->dev, "tranfer: beyond-end write (%ld %ld)\n", sector, nsect);
-+ //spin_lock(&dev->lock); // ???
-+ return -1;
-+ }
-+
-+ switch (rw) {
-+ case WRITE:
-+ ret = sdwrite(&dev->tssdcore, sector, buffer, nsect);
-+ if (ret && !dev->tssdcore.sd_wprot) {
-+ sdreset(&dev->tssdcore);
-+ ret = sdwrite(&dev->tssdcore, sector, buffer, nsect);
-+ }
-+ break;
-+
-+ case READ:
-+ case READA:
-+ ret = sdread(&dev->tssdcore, sector, buffer, nsect);
-+ if (ret) {
-+ // SDCARD RESET may be printed when the core determines that the SD card has
-+ // f*ed up.this is not handled correctly yet; and should likely be inside a while loop
-+ dev_err(dev->dev, "transfer: SDCARD RESET\n");
-+ sdreset(&dev->tssdcore);
-+ ret = sdread(&dev->tssdcore, sector, buffer, nsect);
-+ }
-+ break;
-+ }
-+
-+ //spin_lock(&dev->lock); // ???
-+ return 0;
-+}
-+
-+/*
-+ * The direct make request version.
-+ */
-+static int sdcard_make_request(struct request_queue *q, struct bio *bio)
-+{
-+ struct ts72xx_sdcard_device *dev = q->queuedata;
-+
-+ struct bio_vec *bvec;
-+ sector_t sector;
-+ int i, rw;
-+ int err = -EIO;
-+
-+ /* handle bio */
-+ sector = bio->bi_sector;
-+ rw = bio_rw(bio);
-+
-+ bio_for_each_segment(bvec, bio, i) {
-+ char *buffer = __bio_kmap_atomic(bio, i, KM_USER0);
-+ unsigned int len = bvec->bv_len / HARD_SECTOR_SIZE;
-+
-+ //printk("bvec: len=%d offt=%d page=%p\n", bvec->bv_len, bvec->bv_offset, bvec->bv_page);
-+
-+ err = sdcard_ll_transfer(dev, sector, len, buffer, rw);
-+ if (err)
-+ break;
-+
-+ sector += len;
-+ __bio_kunmap_atomic(bio, KM_USER0);
-+ }
-+ bio_endio(bio, err);
-+
-+ return 0;
-+}
-+
-+static void sdcard_delay(void *arg, unsigned int us)
-+{
-+ udelay(us);
-+}
-+
-+static int sdcard_open(struct block_device *bdev, fmode_t mode)
-+{
-+ struct ts72xx_sdcard_device *dev = bdev->bd_disk->private_data;
-+ unsigned long flags;
-+
-+ dev_dbg(dev->dev, "open() users=%i\n", dev->users + 1);
-+
-+ spin_lock_irqsave(&dev->lock, flags);
-+ dev->users++;
-+ spin_unlock_irqrestore(&dev->lock, flags);
-+
-+ check_disk_change(bdev);
-+ return 0;
-+};
-+
-+static int sdcard_release(struct gendisk *disk, fmode_t mode)
-+{
-+ struct ts72xx_sdcard_device *dev = disk->private_data;
-+ unsigned long flags;
-+
-+ dev_dbg(dev->dev, "release() users=%i\n", dev->users - 1);
-+
-+ spin_lock_irqsave(&dev->lock, flags);
-+ dev->users--;
-+ spin_unlock_irqrestore(&dev->lock, flags);
-+
-+ return 0;
-+}
-+
-+static int sdcard_media_changed(struct gendisk *disk)
-+{
-+ struct ts72xx_sdcard_device *dev = disk->private_data;
-+
-+ char buf[HARD_SECTOR_SIZE];
-+ dev->media_change = sdread(&dev->tssdcore, 1, buf, 1);
-+
-+ dev_dbg(dev->dev, "media_changed() %i\n", dev->media_change);
-+ return dev->media_change;
-+}
-+
-+static int sdcard_revalidate(struct gendisk *disk)
-+{
-+ struct ts72xx_sdcard_device *dev = disk->private_data;
-+ int ret = 0;
-+
-+ dev_dbg(dev->dev, "revalidate() %i\n", dev->media_change);
-+ if (dev->media_change) {
-+ dev->size = sdreset(&dev->tssdcore);
-+ set_disk_ro(dev->disk, !!(dev->tssdcore.sd_wprot));
-+ if (dev->size > 0) {
-+ set_capacity(dev->disk, dev->size * HARD_2_KERN_SECTOR_RATIO);
-+ dev->media_change = 0;
-+ } else {
-+ dev_err(dev->dev, "revalidate() no card found\n");
-+ ret = -1;
-+ }
-+ }
-+ return ret;
-+}
-+
-+static int sdcard_getgeo(struct block_device *bdev, struct hd_geometry *geo)
-+{
-+ struct gendisk *disk = bdev->bd_disk;
-+ struct ts72xx_sdcard_device *dev = disk->private_data;
-+
-+ /* We don't have real geometry info, but let's at least return
-+ * values consistent with the size of the device */
-+ geo->heads = 16;
-+ geo->sectors = 32;
-+ geo->cylinders = get_capacity(disk) / (16 * 32);
-+
-+ dev_dbg(dev->dev, "getgeo() %d heads, %d sectors, %d cylinders\n",
-+ geo->heads, geo->sectors, geo->cylinders);
-+ return 0;
-+}
-+
-+/*
-+ * The device operations structure.
-+ */
-+static struct block_device_operations ts72xx_sdcard_ops = {
-+ .owner = THIS_MODULE,
-+ .open = sdcard_open,
-+ .release = sdcard_release,
-+ .media_changed = sdcard_media_changed,
-+ .revalidate_disk = sdcard_revalidate,
-+ .getgeo = sdcard_getgeo
-+};
-+
-+static int sdcard_major;
-+
-+/* ---------------------------------------------------------------------
-+ * Device setup
-+ */
-+
-+static int ts72xx_sdcard_setup(const char *name, struct ts72xx_sdcard_device *dev)
-+{
-+ int rc;
-+
-+ spin_lock_init(&dev->lock);
-+
-+ /*
-+ * Initialize the request queue
-+ */
-+ dev->queue = blk_alloc_queue(GFP_KERNEL);
-+ if (!dev->queue)
-+ goto err_alloc_queue;
-+
-+ dev->queue->queuedata = dev;
-+ blk_queue_make_request(dev->queue, sdcard_make_request);
-+ blk_queue_logical_block_size(dev->queue, HARD_SECTOR_SIZE);
-+
-+ dev->tssdcore.sd_regstart = (unsigned char *)dev->mmio_base;
-+ dev->tssdcore.os_arg = dev;
-+ dev->tssdcore.os_delay = sdcard_delay;
-+ dev->tssdcore.os_dmastream = NULL;
-+ dev->tssdcore.os_dmaprep = NULL;
-+
-+ // don't want to write park
-+ dev->tssdcore.sd_writeparking = 1;
-+ // I do want to pre-erase blocks - 8 blocks pre-erase
-+ dev->tssdcore.sd_erasehint = 8;
-+ dev->tssdcore.sdboot_token = 0;
-+
-+ dev->disk = alloc_disk(1 << SD_SHIFT);
-+ if (!dev->disk) {
-+ goto err_alloc_disk;
-+ }
-+
-+ dev->disk->major = sdcard_major;
-+ dev->disk->first_minor = dev->id << SD_SHIFT;
-+ dev->disk->flags = GENHD_FL_REMOVABLE;
-+ dev->disk->fops = &ts72xx_sdcard_ops;
-+ dev->disk->queue = dev->queue;
-+ dev->disk->private_data = dev;
-+ snprintf(dev->disk->disk_name, 32, SDCARD_DEV_NAME "%c", dev->id + 'a');
-+
-+ /* SD Card size and Reset
-+ * (set_disk_ro, set_capacity will be called) */
-+ dev->media_change = 1;
-+ rc = sdcard_revalidate(dev->disk);
-+ if (rc) {
-+ dev_info(dev->dev, "No SD card detected!\n");
-+ goto err_alloc_disk;
-+ }
-+
-+ dev_info(dev->dev, "SD card hardware revision: %08x\n",
-+ dev->tssdcore.sdcore_version);
-+ dev_info(dev->dev, "block device major number = %d\n",
-+ sdcard_major);
-+ dev_info(dev->dev, "New SD card detected, name=%s size=%ld (sectors)\n",
-+ dev->disk->disk_name, dev->size);
-+
-+ /* Make the sysace device 'live' */
-+ add_disk(dev->disk);
-+
-+ return 0;
-+
-+err_alloc_disk:
-+ blk_cleanup_queue(dev->queue);
-+err_alloc_queue:
-+ return -ENOMEM;
-+}
-+
-+
-+/* ---------------------------------------------------------------------
-+ * Platform drivers functons
-+ */
-+
-+static int __init ts72xx_sdcard_probe(struct platform_device *pdev)
-+{
-+ struct ts72xx_sdcard_device *dev;
-+ struct resource *res;
-+ int rc;
-+
-+ dev = kzalloc(sizeof(struct ts72xx_sdcard_device), GFP_KERNEL);
-+ if (!dev) {
-+ rc = -ENOMEM;
-+ goto fail_no_mem;
-+ }
-+
-+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-+ if (res == NULL) {
-+ rc = -ENXIO;
-+ goto fail_no_mem_resource;
-+ }
-+
-+ res = request_mem_region(res->start, resource_size(res), pdev->name);
-+ if (res == NULL) {
-+ rc = -EBUSY;
-+ goto fail_no_mem_resource;
-+ }
-+
-+ dev->mmio_base = ioremap(res->start, resource_size(res));
-+ if (dev->mmio_base == NULL) {
-+ rc = -ENXIO;
-+ goto fail_no_ioremap;
-+ }
-+
-+ dev->dev = &pdev->dev;
-+ dev->id = pdev->id;
-+ platform_set_drvdata(pdev, dev);
-+
-+ rc = ts72xx_sdcard_setup(SDCARD_DEV_NAME, dev);
-+ if (rc) {
-+ dev_err(dev->dev, "ts72xx_sdcard_setup failed\n");
-+ goto fail_sdcard_setup;
-+ }
-+
-+ return 0;
-+
-+fail_sdcard_setup:
-+ iounmap(dev->mmio_base);
-+fail_no_ioremap:
-+ release_mem_region(res->start, resource_size(res));
-+fail_no_mem_resource:
-+ kfree(dev);
-+fail_no_mem:
-+ return rc;
-+}
-+
-+static int __exit ts72xx_sdcard_remove(struct platform_device *pdev)
-+{
-+ struct ts72xx_sdcard_device *dev = platform_get_drvdata(pdev);
-+ struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-+
-+ platform_set_drvdata(pdev, NULL);
-+ iounmap(dev->mmio_base);
-+ release_mem_region(res->start, resource_size(res));
-+ blk_cleanup_queue(dev->queue);
-+ del_gendisk(dev->disk);
-+ put_disk(dev->disk);
-+ kfree(dev);
-+
-+ return 0;
-+}
-+
-+static struct platform_driver ts72xx_sdcard_driver = {
-+ .driver = {
-+ .name = "ts72xx-sdcard",
-+ .owner = THIS_MODULE,
-+ },
-+ .remove = __exit_p(ts72xx_sdcard_remove),
-+};
-+
-+
-+/* ---------------------------------------------------------------------
-+ * Module init/exit routines
-+ */
-+
-+static int __init ts72xx_sdcard_init(void)
-+{
-+ int rc;
-+
-+ sdcard_major = rc = register_blkdev(sdcard_major, SDCARD_DEV_NAME);
-+ if (rc <= 0) {
-+ printk(KERN_ERR "%s:%u: register_blkdev failed %d\n", __func__,
-+ __LINE__, rc);
-+ return rc;
-+ }
-+
-+ rc = platform_driver_probe(&ts72xx_sdcard_driver, ts72xx_sdcard_probe);
-+ if (rc)
-+ unregister_blkdev(sdcard_major, SDCARD_DEV_NAME);
-+
-+ return rc;
-+}
-+
-+static void __exit ts72xx_sdcard_exit(void)
-+{
-+ unregister_blkdev(sdcard_major, SDCARD_DEV_NAME);
-+ platform_driver_unregister(&ts72xx_sdcard_driver);
-+}
-+
-+module_init(ts72xx_sdcard_init);
-+module_exit(ts72xx_sdcard_exit);
-+
-+MODULE_AUTHOR("Matthieu Crapet <mcrapet@gmail.com>");
-+MODULE_DESCRIPTION("TS72xx SD Card block driver");
-+MODULE_LICENSE("GPL");
-+MODULE_ALIAS_BLOCKDEV_MAJOR(SCSI_DISK0_MAJOR);
-+MODULE_ALIAS("tssd");
---
-1.7.0.4
-
diff --git a/recipes/linux/linux-2.6.36/ts72xx/0016-ts72xx_spi_tmp124.patch b/recipes/linux/linux-2.6.36/ts72xx/0016-ts72xx_spi_tmp124.patch
deleted file mode 100644
index 0099c91..0000000
--- a/recipes/linux/linux-2.6.36/ts72xx/0016-ts72xx_spi_tmp124.patch
+++ /dev/null
@@ -1,305 +0,0 @@
-From 6e1298e3647a7eea65fe323ee0181ab2373fd78d Mon Sep 17 00:00:00 2001
-From: Matthieu Crapet <mcrapet@gmail.com>
-Date: Tue, 22 Jun 2010 15:48:27 +0200
-Subject: [PATCH 16/24] ts72xx_spi_tmp124
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-It's an option. A 3-wire spi temperature sensor can be populated on TS-72XX sbc.
-
-Signed-off-by: Petr Štetiar <ynezz@true.cz>
----
- arch/arm/mach-ep93xx/ts72xx.c | 63 ++++++++++++++++
- drivers/spi/Kconfig | 7 ++
- drivers/spi/Makefile | 1 +
- drivers/spi/tmp124.c | 158 +++++++++++++++++++++++++++++++++++++++++
- 4 files changed, 229 insertions(+), 0 deletions(-)
- create mode 100644 drivers/spi/tmp124.c
-
-diff --git a/arch/arm/mach-ep93xx/ts72xx.c b/arch/arm/mach-ep93xx/ts72xx.c
-index c99f112..941eeac 100644
---- a/arch/arm/mach-ep93xx/ts72xx.c
-+++ b/arch/arm/mach-ep93xx/ts72xx.c
-@@ -23,7 +23,11 @@
- #include <linux/gpio.h>
- #include <linux/i2c.h>
- #include <linux/i2c-gpio.h>
-+#include <linux/mtd/nand.h>
-+#include <linux/mtd/partitions.h>
-+#include <linux/spi/spi.h>
-
-+#include <mach/ep93xx_spi.h>
- #include <mach/hardware.h>
- #include <mach/ts72xx.h>
-
-@@ -352,6 +356,60 @@ static struct i2c_gpio_platform_data ts72xx_i2c_gpio_data = {
- static struct i2c_board_info __initdata ts72xx_i2c_board_info[] = {
- };
-
-+/*************************************************************************
-+ * SPI
-+ *************************************************************************/
-+#if defined(CONFIG_SPI_TMP124) || defined(CONFIG_SPI_TMP124_MODULE)
-+
-+/* this is our GPIO line used for chip select */
-+#define TMP124_CHIP_SELECT_GPIO EP93XX_GPIO_LINE_MCCD2
-+
-+static int ts72xx_tmp124_setup(struct spi_device *spi)
-+{
-+ int err;
-+
-+ err = gpio_request(TMP124_CHIP_SELECT_GPIO, spi->modalias);
-+ if (err)
-+ return err;
-+
-+ gpio_direction_output(TMP124_CHIP_SELECT_GPIO, 1);
-+
-+ return 0;
-+}
-+
-+static void ts72xx_tmp124_cleanup(struct spi_device *spi)
-+{
-+ gpio_set_value(TMP124_CHIP_SELECT_GPIO, 1);
-+ gpio_direction_input(TMP124_CHIP_SELECT_GPIO);
-+ gpio_free(TMP124_CHIP_SELECT_GPIO);
-+}
-+
-+static void ts72xx_tmp124_cs_control(struct spi_device *spi, int value)
-+{
-+ gpio_set_value(TMP124_CHIP_SELECT_GPIO, value);
-+}
-+
-+static struct ep93xx_spi_chip_ops ts72xx_tmp124_ops = {
-+ .setup = ts72xx_tmp124_setup,
-+ .cleanup = ts72xx_tmp124_cleanup,
-+ .cs_control = ts72xx_tmp124_cs_control,
-+};
-+
-+static struct spi_board_info ts72xx_spi_devices[] = {
-+ {
-+ .modalias = "tmp124",
-+ .max_speed_hz = 2 * 1000 * 1000,
-+ .bus_num = 0,
-+ .chip_select = 0,
-+ .controller_data = &ts72xx_tmp124_ops,
-+ },
-+};
-+
-+static struct ep93xx_spi_info ts72xx_spi_info = {
-+ .num_chipselect = ARRAY_SIZE(ts72xx_spi_devices),
-+};
-+#endif
-+
- static void __init ts72xx_init_machine(void)
- {
- ep93xx_init_devices();
-@@ -365,6 +423,11 @@ static void __init ts72xx_init_machine(void)
- ts72xx_i2c_board_info,
- ARRAY_SIZE(ts72xx_i2c_board_info));
-
-+ #if defined(CONFIG_SPI_TMP124) || defined(CONFIG_SPI_TMP124_MODULE)
-+ ep93xx_register_spi(&ts72xx_spi_info, ts72xx_spi_devices,
-+ ARRAY_SIZE(ts72xx_spi_devices));
-+ #endif
-+
- if (is_max197_installed()) {
- platform_device_register(&ts72xx_max197_device);
- }
-diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
-index 91c2f4f..05b78ca 100644
---- a/drivers/spi/Kconfig
-+++ b/drivers/spi/Kconfig
-@@ -379,6 +379,13 @@ config SPI_TLE62X0
- sysfs interface, with each line presented as a kind of GPIO
- exposing both switch control and diagnostic feedback.
-
-+config SPI_TMP124
-+ tristate "Texas Instruments TMP1224, TMP124"
-+ depends on SPI_MASTER && SYSFS
-+ help
-+ SPI driver for TMP12X temperature sensor chips.
-+ This provides a sysfs entry for temperature reading (2�C accurate).
-+
- #
- # Add new SPI protocol masters in alphabetical order above this line
- #
-diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile
-index e9cbd18..c8f85ea 100644
---- a/drivers/spi/Makefile
-+++ b/drivers/spi/Makefile
-@@ -57,6 +57,7 @@ spi_s3c24xx_hw-$(CONFIG_SPI_S3C24XX_FIQ) += spi_s3c24xx_fiq.o
- # SPI protocol drivers (device/link on bus)
- obj-$(CONFIG_SPI_SPIDEV) += spidev.o
- obj-$(CONFIG_SPI_TLE62X0) += tle62x0.o
-+obj-$(CONFIG_SPI_TMP124) += tmp124.o
- # ... add above this line ...
-
- # SPI slave controller drivers (upstream link)
-diff --git a/drivers/spi/tmp124.c b/drivers/spi/tmp124.c
-new file mode 100644
-index 0000000..e41ec8c
---- /dev/null
-+++ b/drivers/spi/tmp124.c
-@@ -0,0 +1,158 @@
-+/*
-+ * TMP124 SPI protocol driver
-+ *
-+ * (c) Copyright 2008-2010 Matthieu Crapet <mcrapet@gmail.com>
-+ * Based on tle62x0.c by Ben Dooks, <ben@simtec.co.uk>
-+ *
-+ * 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.
-+ *
-+ * Note: The chip uses a '3-wire SPI' (miso and mosi are the same pin).
-+ */
-+
-+#include <linux/module.h>
-+#include <linux/kernel.h>
-+#include <linux/init.h>
-+#include <linux/spi/spi.h>
-+#include <linux/slab.h>
-+#include <linux/sched.h>
-+
-+struct tmp124_state {
-+ struct spi_device *bus;
-+ u8 tx_buff[2];
-+ u8 rx_buff[2];
-+};
-+
-+static inline int tmp124_write_then_read(struct tmp124_state *st)
-+{
-+ struct spi_message msg;
-+ struct spi_transfer xfer[2] = {
-+ {
-+ .tx_buf = st->tx_buff,
-+ .rx_buf = NULL,
-+ .len = 2,
-+ }, {
-+ .tx_buf = NULL,
-+ .rx_buf = st->rx_buff,
-+ .len = 2,
-+ }
-+ };
-+
-+ spi_message_init(&msg);
-+ spi_message_add_tail(&xfer[0], &msg);
-+ spi_sync(st->bus, &msg);
-+
-+ /* SPI_3WIRE is not handled by ep93xx_spi, the 2 messages must be
-+ * splitted. We must wait to not confuse driver with read/write. */
-+ schedule_timeout(usecs_to_jiffies(1000));
-+
-+ spi_message_init(&msg);
-+ spi_message_add_tail(&xfer[1], &msg);
-+ return spi_sync(st->bus, &msg);
-+}
-+
-+static ssize_t tmp124_temperature_show(struct device *dev,
-+ struct device_attribute *attr, char *buf)
-+{
-+ struct tmp124_state *st = dev_get_drvdata(dev);
-+ int ret;
-+
-+ ((short *)st->tx_buff)[0] = 0x8000;
-+
-+ ret = tmp124_write_then_read(st);
-+ if (ret < 0) {
-+ dev_err(&st->bus->dev, "tmp124_write_then_read\n");
-+ ret = 0;
-+ } else {
-+ signed long val = ((short *)st->rx_buff)[0];
-+
-+ val = val >> 3;
-+
-+ /* 2 digit precision (0.0625*100) */
-+ val = (val * 50) / 8;
-+ ret = snprintf(buf, PAGE_SIZE, "%ld.%02ld\n", val/100, abs(val%100));
-+ }
-+ return ret;
-+}
-+
-+static DEVICE_ATTR(temperature, S_IRUGO, tmp124_temperature_show, NULL);
-+
-+static int __devinit tmp124_probe(struct spi_device *spi)
-+{
-+ struct tmp124_state *st;
-+ int ret;
-+
-+ st = kzalloc(sizeof(struct tmp124_state), GFP_KERNEL);
-+ if (st == NULL) {
-+ dev_err(&spi->dev, "no memory for device state\n");
-+ return -ENOMEM;
-+ }
-+
-+ /* required config */
-+ spi->bits_per_word = 16;
-+ spi->mode = SPI_MODE_0;
-+
-+ ret = spi_setup(spi);
-+ if (ret) {
-+ dev_err(&spi->dev, "setup device\n");
-+ goto err;
-+ }
-+
-+ ret = device_create_file(&spi->dev, &dev_attr_temperature);
-+ if (ret) {
-+ dev_err(&spi->dev, "cannot create temperature attribute\n");
-+ goto err;
-+ }
-+
-+ st->bus = spi;
-+ spi_set_drvdata(spi, st);
-+ return 0;
-+
-+err:
-+ kfree(st);
-+ return ret;
-+}
-+
-+static int __devexit tmp124_remove(struct spi_device *spi)
-+{
-+ struct tmp124_state *st = spi_get_drvdata(spi);
-+
-+ device_remove_file(&spi->dev, &dev_attr_temperature);
-+ kfree(st);
-+ return 0;
-+}
-+
-+static struct spi_driver tmp124_driver = {
-+ .driver = {
-+ .name = "tmp124",
-+ .owner = THIS_MODULE,
-+ },
-+ .probe = tmp124_probe,
-+ .remove = __devexit_p(tmp124_remove),
-+};
-+
-+static __init int tmp124_init(void)
-+{
-+ return spi_register_driver(&tmp124_driver);
-+}
-+
-+static __exit void tmp124_exit(void)
-+{
-+ spi_unregister_driver(&tmp124_driver);
-+}
-+
-+module_init(tmp124_init);
-+module_exit(tmp124_exit);
-+
-+MODULE_AUTHOR("Matthieu Crapet <mcrapet@gmail.com>");
-+MODULE_DESCRIPTION("TMP124 SPI Protocol Driver");
-+MODULE_LICENSE("GPL");
-+MODULE_ALIAS("spi:tmp124");
-+MODULE_VERSION("0.2");
---
-1.7.0.4
-
diff --git a/recipes/linux/linux-2.6.36/ts72xx/0017-ts72xx-use-CPLD-watchdog-for-reset.patch b/recipes/linux/linux-2.6.36/ts72xx/0017-ts72xx-use-CPLD-watchdog-for-reset.patch
deleted file mode 100644
index 0d844bf..0000000
--- a/recipes/linux/linux-2.6.36/ts72xx/0017-ts72xx-use-CPLD-watchdog-for-reset.patch
+++ /dev/null
@@ -1,53 +0,0 @@
-From dc31543df131eeeadf4f36fbca25b89eeda1de53 Mon Sep 17 00:00:00 2001
-From: =?UTF-8?q?Petr=20=C5=A0tetiar?= <ynezz@true.cz>
-Date: Thu, 21 Oct 2010 20:00:49 +0200
-Subject: [PATCH 17/24] ts72xx: use CPLD watchdog for reset
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-
-Signed-off-by: Petr Štetiar <ynezz@true.cz>
----
- arch/arm/mach-ep93xx/include/mach/system.h | 13 +++++++++++++
- 1 files changed, 13 insertions(+), 0 deletions(-)
-
-diff --git a/arch/arm/mach-ep93xx/include/mach/system.h b/arch/arm/mach-ep93xx/include/mach/system.h
-index 6d661fe..b657a9a 100644
---- a/arch/arm/mach-ep93xx/include/mach/system.h
-+++ b/arch/arm/mach-ep93xx/include/mach/system.h
-@@ -3,6 +3,10 @@
- */
-
- #include <mach/hardware.h>
-+#ifdef CONFIG_MACH_TS72XX
-+#include <linux/io.h>
-+#include <mach/ts72xx.h>
-+#endif
-
- static inline void arch_idle(void)
- {
-@@ -13,11 +17,20 @@ static inline void arch_reset(char mode, const char *cmd)
- {
- local_irq_disable();
-
-+#ifdef CONFIG_MACH_TS72XX
-+ /* It's more reliable to use CPLD watchdog to perform reset */
-+ if (board_is_ts7200() || board_is_ts7250() || board_is_ts7260() ||
-+ board_is_ts7300() || board_is_ts7400()) {
-+ __raw_writeb(0x5, TS72XX_WDT_FEED_PHYS_BASE);
-+ __raw_writeb(0x1, TS72XX_WDT_CONTROL_PHYS_BASE);
-+ }
-+#else
- /*
- * Set then clear the SWRST bit to initiate a software reset
- */
- ep93xx_devcfg_set_bits(EP93XX_SYSCON_DEVCFG_SWRST);
- ep93xx_devcfg_clear_bits(EP93XX_SYSCON_DEVCFG_SWRST);
-+#endif
-
- while (1)
- ;
---
-1.7.0.4
-
diff --git a/recipes/linux/linux-2.6.36/ts72xx/0018-ethoc-ts7300-fixes.patch b/recipes/linux/linux-2.6.36/ts72xx/0018-ethoc-ts7300-fixes.patch
deleted file mode 100644
index 3d5fd84..0000000
--- a/recipes/linux/linux-2.6.36/ts72xx/0018-ethoc-ts7300-fixes.patch
+++ /dev/null
@@ -1,93 +0,0 @@
-From 65cd401ec17f4a9791297e413e5954f25c71b2b0 Mon Sep 17 00:00:00 2001
-From: =?UTF-8?q?Petr=20=C5=A0tetiar?= <ynezz@true.cz>
-Date: Sat, 23 Oct 2010 19:49:21 +0200
-Subject: [PATCH 18/24] ethoc: ts7300 fixes
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-Signed-off-by: Ian Thompson <ian.thompson@pgs.com>
-Signed-off-by: Petr Štetiar <ynezz@true.cz>
----
- drivers/net/ethoc.c | 27 ++++++++++++++++++++-------
- 1 files changed, 20 insertions(+), 7 deletions(-)
-
-diff --git a/drivers/net/ethoc.c b/drivers/net/ethoc.c
-index 6d653c4..a0f62eb 100644
---- a/drivers/net/ethoc.c
-+++ b/drivers/net/ethoc.c
-@@ -21,7 +21,11 @@
- #include <linux/slab.h>
- #include <net/ethoc.h>
-
-+#ifndef CONFIG_MACH_TS72XX
- static int buffer_size = 0x8000; /* 32 KBytes */
-+#else
-+static int buffer_size = 0x2000; /* 8 KBytes */
-+#endif
- module_param(buffer_size, int, 0);
- MODULE_PARM_DESC(buffer_size, "DMA buffer allocation size");
-
-@@ -525,11 +529,6 @@ static irqreturn_t ethoc_interrupt(int irq, void *dev_id)
-
- ethoc_ack_irq(priv, pending);
-
-- if (pending & INT_MASK_BUSY) {
-- dev_err(&dev->dev, "packet dropped\n");
-- dev->stats.rx_dropped++;
-- }
--
- if (pending & INT_MASK_RX) {
- if (napi_schedule_prep(&priv->napi))
- __napi_schedule(&priv->napi);
-@@ -834,10 +833,10 @@ static netdev_tx_t ethoc_start_xmit(struct sk_buff *skb, struct net_device *dev)
- bd.stat &= ~TX_BD_PAD;
-
- dest = priv->vma[entry];
-- memcpy_toio(dest, skb->data, skb->len);
-+ memcpy_toio(dest, skb->data, skb->len + 2);
-
- bd.stat &= ~(TX_BD_STATS | TX_BD_LEN_MASK);
-- bd.stat |= TX_BD_LEN(skb->len);
-+ bd.stat |= TX_BD_LEN(skb->len + 2);
- ethoc_write_bd(priv, entry, &bd);
-
- bd.stat |= TX_BD_READY;
-@@ -992,6 +991,8 @@ static int __devinit ethoc_probe(struct platform_device *pdev)
- (struct ethoc_platform_data *)pdev->dev.platform_data;
- memcpy(netdev->dev_addr, pdata->hwaddr, IFHWADDRLEN);
- priv->phy_id = pdata->phy_id;
-+ } else {
-+ priv->phy_id = 1;
- }
-
- /* Check that the given MAC address is valid. If it isn't, read the
-@@ -1004,6 +1005,17 @@ static int __devinit ethoc_probe(struct platform_device *pdev)
- if (!is_valid_ether_addr(netdev->dev_addr))
- random_ether_addr(netdev->dev_addr);
-
-+ /* take this out for more general usage */
-+ netdev->dev_addr[0] = 0x00;
-+ netdev->dev_addr[1] = 0x88;
-+ netdev->dev_addr[2] = 0x88;
-+ netdev->dev_addr[3] = 0x88;
-+ netdev->dev_addr[4] = 0x88;
-+ netdev->dev_addr[5] = 0x01;
-+
-+ printk("ethoc: setting MAC address to %2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x\n",netdev->dev_addr[0],
-+ netdev->dev_addr[1],netdev->dev_addr[2],netdev->dev_addr[3],netdev->dev_addr[4],
-+ netdev->dev_addr[5]);
- ethoc_set_mac_address(netdev, netdev->dev_addr);
-
- /* register MII bus */
-@@ -1131,6 +1143,7 @@ static struct platform_driver ethoc_driver = {
-
- static int __init ethoc_init(void)
- {
-+ printk("ethoc driver with ts73xx fixes initialized\n");
- return platform_driver_register(ðoc_driver);
- }
-
---
-1.7.0.4
-
diff --git a/recipes/linux/linux-2.6.36/ts72xx/0019-ts7300-add-ethernet-support.patch b/recipes/linux/linux-2.6.36/ts72xx/0019-ts7300-add-ethernet-support.patch
deleted file mode 100644
index 3895966..0000000
--- a/recipes/linux/linux-2.6.36/ts72xx/0019-ts7300-add-ethernet-support.patch
+++ /dev/null
@@ -1,87 +0,0 @@
-From 0945e8b61f170da6b5d249863f46eda5fdce3a7c Mon Sep 17 00:00:00 2001
-From: =?UTF-8?q?Petr=20=C5=A0tetiar?= <ynezz@true.cz>
-Date: Thu, 21 Oct 2010 11:51:44 +0200
-Subject: [PATCH 19/24] ts7300: add ethernet support
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-Signed-off-by: Ian Thompson <ian.thompson@pgs.com>
-Signed-off-by: Petr Štetiar <ynezz@true.cz>
----
- arch/arm/mach-ep93xx/include/mach/ts72xx.h | 3 ++
- arch/arm/mach-ep93xx/ts72xx.c | 30 ++++++++++++++++++++++++++++
- 2 files changed, 33 insertions(+), 0 deletions(-)
-
-diff --git a/arch/arm/mach-ep93xx/include/mach/ts72xx.h b/arch/arm/mach-ep93xx/include/mach/ts72xx.h
-index 1d50dec..beb3e3c 100644
---- a/arch/arm/mach-ep93xx/include/mach/ts72xx.h
-+++ b/arch/arm/mach-ep93xx/include/mach/ts72xx.h
-@@ -135,6 +135,9 @@
-
- #define TS7260_SDCARD_PHYS_BASE 0x13000000
-
-+#define TS7300_ETHOC_PHYS_BASE 0x72100000
-+#define TS7300_ETHOC_IO_BASE 0x72102000
-+
- #ifndef __ASSEMBLY__
-
- static inline int board_is_ts7200(void)
-diff --git a/arch/arm/mach-ep93xx/ts72xx.c b/arch/arm/mach-ep93xx/ts72xx.c
-index 941eeac..0c07bd8 100644
---- a/arch/arm/mach-ep93xx/ts72xx.c
-+++ b/arch/arm/mach-ep93xx/ts72xx.c
-@@ -30,6 +30,7 @@
- #include <mach/ep93xx_spi.h>
- #include <mach/hardware.h>
- #include <mach/ts72xx.h>
-+#include <mach/irqs.h>
-
- #include <asm/mach-types.h>
- #include <asm/mach/map.h>
-@@ -341,6 +342,32 @@ static struct ep93xx_eth_data __initdata ts72xx_eth_data = {
- .phy_id = 1,
- };
-
-+static struct resource ts7300_ethoc_resources[] = {
-+ [0] = {
-+ .start = TS7300_ETHOC_IO_BASE,
-+ .end = TS7300_ETHOC_IO_BASE + 0x3FF,
-+ .flags = IORESOURCE_MEM,
-+ },
-+ [1] = {
-+ .start = TS7300_ETHOC_PHYS_BASE,
-+ .end = TS7300_ETHOC_PHYS_BASE + 0x1FFF,
-+ .flags = IORESOURCE_MEM,
-+ },
-+ [2] = {
-+ .start = IRQ_EP93XX_EXT3,
-+ .end = IRQ_EP93XX_EXT3,
-+ .flags = IORESOURCE_IRQ,
-+ },
-+};
-+
-+static struct platform_device ts7300_ethoc_device = {
-+ .name = "ethoc",
-+ .id = 0,
-+ .num_resources = 3,
-+ .resource = ts7300_ethoc_resources,
-+};
-+
-+
- /*************************************************************************
- * I2C (make access through TS-72XX "DIO" 2x8 header)
- *************************************************************************/
-@@ -432,6 +459,9 @@ static void __init ts72xx_init_machine(void)
- platform_device_register(&ts72xx_max197_device);
- }
-
-+ if (board_is_ts7300())
-+ platform_device_register(&ts7300_ethoc_device);
-+
- /* PWM1 is DIO_6 on TS-72xx header */
- ep93xx_register_pwm(0, 1);
- }
---
-1.7.0.4
-
diff --git a/recipes/linux/linux-2.6.36/ts72xx/0023-ts72xx-add-lcd-linux-driver.patch b/recipes/linux/linux-2.6.36/ts72xx/0023-ts72xx-add-lcd-linux-driver.patch
deleted file mode 100644
index 5fb3b01..0000000
--- a/recipes/linux/linux-2.6.36/ts72xx/0023-ts72xx-add-lcd-linux-driver.patch
+++ /dev/null
@@ -1,4569 +0,0 @@
-From 0e934482ba53c9d73dcbd3727da8f39da5dfa5ce Mon Sep 17 00:00:00 2001
-From: =?UTF-8?q?Petr=20=C5=A0tetiar?= <ynezz@true.cz>
-Date: Sun, 7 Nov 2010 14:41:41 +0100
-Subject: [PATCH 23/24] ts72xx: add lcd-linux driver
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-- based on LCD-Linux v0.13.9 (latest stable release)
-- supports only hd44780 compatible display
-- LCD in 8-bit mode operation only (D0-D7) connected to LCD connector
-
-Signed-off-by: Petr Štetiar <ynezz@true.cz>
----
- arch/arm/Kconfig | 2 +
- drivers/Makefile | 1 +
- drivers/lcd-linux/Config.in | 8 +
- drivers/lcd-linux/Kconfig | 33 +
- drivers/lcd-linux/Makefile | 8 +
- drivers/lcd-linux/cgram/default.h | 37 +
- drivers/lcd-linux/cgram/swedish.h | 33 +
- drivers/lcd-linux/charmap.h | 79 +
- drivers/lcd-linux/commands.h | 77 +
- drivers/lcd-linux/config.h | 73 +
- drivers/lcd-linux/hd44780.c | 854 +++++++++++
- drivers/lcd-linux/lcd-linux.c | 3023 +++++++++++++++++++++++++++++++++++++
- include/linux/hd44780.h | 47 +
- include/linux/lcd-linux.h | 158 ++
- 14 files changed, 4433 insertions(+), 0 deletions(-)
- create mode 100644 drivers/lcd-linux/Config.in
- create mode 100644 drivers/lcd-linux/Kconfig
- create mode 100644 drivers/lcd-linux/Makefile
- create mode 100644 drivers/lcd-linux/cgram/default.h
- create mode 100644 drivers/lcd-linux/cgram/swedish.h
- create mode 100644 drivers/lcd-linux/charmap.h
- create mode 100644 drivers/lcd-linux/commands.h
- create mode 100644 drivers/lcd-linux/config.h
- create mode 100644 drivers/lcd-linux/hd44780.c
- create mode 100644 drivers/lcd-linux/lcd-linux.c
- create mode 100644 include/linux/hd44780.h
- create mode 100644 include/linux/lcd-linux.h
-
-diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
-index 8e6c85d..f1e0c4a 100644
---- a/arch/arm/Kconfig
-+++ b/arch/arm/Kconfig
-@@ -1802,6 +1802,8 @@ source "net/Kconfig"
-
- source "drivers/Kconfig"
-
-+source "drivers/lcd-linux/Kconfig"
-+
- source "fs/Kconfig"
-
- source "arch/arm/Kconfig.debug"
-diff --git a/drivers/Makefile b/drivers/Makefile
-index a2aea53..848a6f2 100644
---- a/drivers/Makefile
-+++ b/drivers/Makefile
-@@ -115,3 +115,4 @@ obj-$(CONFIG_VLYNQ) += vlynq/
- obj-$(CONFIG_STAGING) += staging/
- obj-y += platform/
- obj-y += ieee802154/
-+obj-$(CONFIG_LCD_LINUX) += lcd-linux/
-diff --git a/drivers/lcd-linux/Config.in b/drivers/lcd-linux/Config.in
-new file mode 100644
-index 0000000..4a38801
---- /dev/null
-+++ b/drivers/lcd-linux/Config.in
-@@ -0,0 +1,8 @@
-+if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
-+ mainmenu_option next_comment
-+ comment 'LCD support'
-+
-+ tristate 'LCD-Linux layer' CONFIG_LCD_LINUX
-+ dep_tristate ' HD44780 controller' CONFIG_LCD_HD44780 $CONFIG_LCD_LINUX
-+ endmenu
-+fi
-diff --git a/drivers/lcd-linux/Kconfig b/drivers/lcd-linux/Kconfig
-new file mode 100644
-index 0000000..a102fc5
---- /dev/null
-+++ b/drivers/lcd-linux/Kconfig
-@@ -0,0 +1,33 @@
-+menu "LCD support"
-+ depends on EXPERIMENTAL
-+
-+config LCD_LINUX
-+ tristate "LCD-Linux layer"
-+ default n
-+ help
-+ LCD-Linux provides an easy way to drive LCD displays under
-+ Linux by creating a character which can be read or written.
-+ It features complete VT102 emulation and recognizes
-+ many escape sequences. If you want to use it you must also
-+ choose an appropriate driver, otherwise it will not be
-+ very useful. For more information see
-+ http://lcd-linux.sourceforge.net/
-+
-+ To compile LCD-Linux as a module, choose M here:
-+ the module will be called lcd-linux.
-+
-+config LCD_HD44780
-+ tristate "HD44780 controller"
-+ depends on LCD_LINUX && MACH_TS72XX
-+ default n
-+ help
-+ This is a LCD-Linux driver for LCD displays based on the
-+ Hitachi HD44780 (and compatible) controllers connected
-+ to LCD port on the TS72xx boards.
-+
-+ To compile this driver as a module, choose M here:
-+ the module will be called hd44780.
-+
-+ If unsure, say N.
-+
-+endmenu
-diff --git a/drivers/lcd-linux/Makefile b/drivers/lcd-linux/Makefile
-new file mode 100644
-index 0000000..079aa79
---- /dev/null
-+++ b/drivers/lcd-linux/Makefile
-@@ -0,0 +1,8 @@
-+# $Id: Makefile-2.6,v 1.3 2006/12/13 15:53:00 mjona Exp $
-+#
-+# Standard Makefile to statically compile LCD-Linux into the kernel
-+# Linux 2.6
-+
-+obj-$(CONFIG_LCD_LINUX) += lcd-linux.o
-+obj-$(CONFIG_LCD_HD44780) += hd44780.o
-+
-diff --git a/drivers/lcd-linux/cgram/default.h b/drivers/lcd-linux/cgram/default.h
-new file mode 100644
-index 0000000..635146a
---- /dev/null
-+++ b/drivers/lcd-linux/cgram/default.h
-@@ -0,0 +1,37 @@
-+/* default.h
-+ *
-+ * $Id: default.h,v 1.1.1.1 2005/08/23 13:30:14 mjona Exp $
-+ *
-+ * Default user defined characters for lcdmod.
-+ *
-+ * Copyright (C) by Michael McLellan (mikey@cs.auckland.ac.nz)
-+ *
-+ * 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 init_charmap(void)
-+{
-+}
-+
-+static unsigned char cg0[] = { 0x1f, 0x1f, 0x11, 0x0f, 0x11, 0x1e, 0x01, 0x1f };
-+static unsigned char cg1[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f };
-+static unsigned char cg2[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x1f };
-+static unsigned char cg3[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x1f, 0x1f };
-+static unsigned char cg4[] = { 0x00, 0x00, 0x00, 0x00, 0x1f, 0x1f, 0x1f, 0x1f };
-+static unsigned char cg5[] = { 0x00, 0x00, 0x00, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f };
-+static unsigned char cg6[] = { 0x00, 0x00, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f };
-+static unsigned char cg7[] = { 0x00, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f };
-diff --git a/drivers/lcd-linux/cgram/swedish.h b/drivers/lcd-linux/cgram/swedish.h
-new file mode 100644
-index 0000000..a92c31c
---- /dev/null
-+++ b/drivers/lcd-linux/cgram/swedish.h
-@@ -0,0 +1,33 @@
-+/* swedish.h
-+ *
-+ * $Id: swedish.h,v 1.2 2006/12/12 16:04:03 mjona Exp $
-+ *
-+ * Swedish characters for lcdmod
-+ *
-+ * Thanks to Erik Zetterberg <mr.z@linux.se>
-+ *
-+ * Description: Adds support for the last three last letters in the
-+ * swedish alphabet (a/A with ring above, a/A with diaeresis and o/O
-+ * with diaeresis). And maps the location of where they should be
-+ * according to the ISO-8859-1 character set to their location in CGRAM.
-+ *
-+ */
-+
-+static void init_charmap(void)
-+{
-+ charmap[ 0xe5 ] = 0;
-+ charmap[ 0xe4 ] = 1;
-+ charmap[ 0xf6 ] = 2;
-+ charmap[ 0xc5 ] = 3;
-+ charmap[ 0xc4 ] = 4;
-+ charmap[ 0xd6 ] = 5;
-+}
-+
-+static unsigned char cg0[] = { 0x04, 0x00, 0x0e, 0x01, 0x0f, 0x11, 0x0f, 0x00 };
-+static unsigned char cg1[] = { 0x0a, 0x00, 0x0e, 0x01, 0x0f, 0x11, 0x0f, 0x00 };
-+static unsigned char cg2[] = { 0x0a, 0x00, 0x0e, 0x11, 0x11, 0x11, 0x0e, 0x00 };
-+static unsigned char cg3[] = { 0x04, 0x00, 0x0e, 0x11, 0x1f, 0x11, 0x11, 0x00 };
-+static unsigned char cg4[] = { 0x0a, 0x00, 0x0e, 0x11, 0x1f, 0x11, 0x11, 0x00 };
-+static unsigned char cg5[] = { 0x0a, 0x00, 0x0e, 0x11, 0x11, 0x11, 0x0e, 0x00 };
-+static unsigned char cg6[] = { 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f };
-+static unsigned char cg7[] = { 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f };
-diff --git a/drivers/lcd-linux/charmap.h b/drivers/lcd-linux/charmap.h
-new file mode 100644
-index 0000000..376b04d
---- /dev/null
-+++ b/drivers/lcd-linux/charmap.h
-@@ -0,0 +1,79 @@
-+/* charmap.h
-+ *
-+ * $Id: charmap.h,v 1.1.1.1 2005/08/23 13:30:14 mjona Exp $
-+ *
-+ * Character mapping for HD44780 devices by Mark Haemmerling <mail@markh.de>.
-+ *
-+ * Translates ISO 8859-1 to HD44780 charset.
-+ * HD44780 charset reference: http://markh.de/hd44780-charset.png
-+ *
-+ * Initial table taken from lcd.o Linux kernel driver by
-+ * Nils Faerber <nilsf@users.sourceforge.net>. Thanks!
-+ *
-+ * This file is released under the GNU General Public License. Refer to the
-+ * COPYING file distributed with this package.
-+ *
-+ * Following translations are being performed:
-+ * - maps umlaut accent characters to the corresponding umlaut characters
-+ * - maps other accent characters to the characters without accents
-+ * - maps beta (=ringel-S), micro and Yen
-+ *
-+ * Alternative mappings:
-+ * - #112 ("p") -> #240 (large "p"), orig. mapped -> #112
-+ * - #113 ("q") -> #241 (large "q"), orig. mapped -> #113
-+ *
-+ * HD44780 misses backslash
-+ *
-+ */
-+
-+static unsigned char charmap[] = {
-+
-+/* 0 - 31 */
-+ 0, 1, 2, 3, 4, 5, 6, 7,
-+ 8, 9, 10, 11, 12, 13, 14, 15,
-+ 16, 17, 18, 19, 20, 21, 22, 23,
-+ 24, 25, 26, 27, 28, 29, 30, 31,
-+
-+/* 32 - 63 */
-+ 32, 33, 34, 35, 36, 37, 38, 39,
-+ 40, 41, 42, 43, 44, 45, 46, 47,
-+ 48, 49, 50, 51, 52, 53, 54, 55,
-+ 56, 57, 58, 59, 60, 61, 62, 63,
-+
-+/* 64 - 95 */
-+ 64, 65, 66, 67, 68, 69, 70, 71,
-+ 72, 73, 74, 75, 76, 77, 78, 79,
-+ 80, 81, 82, 83, 84, 85, 86, 87,
-+ 88, 89, 90, 91, 47, 93, 94, 95,
-+
-+/* 96 - 127 */
-+ 96, 97, 98, 99, 100, 101, 102, 103,
-+104, 105, 106, 107, 108, 109, 110, 111,
-+112, 113, 114, 115, 116, 117, 118, 119,
-+120, 121, 122, 123, 124, 125, 126, 127,
-+
-+/* 128 - 159 */
-+128, 129, 130, 131, 132, 133, 134, 135,
-+136, 137, 138, 139, 140, 141, 142, 143,
-+144, 145, 146, 147, 148, 149, 150, 151,
-+152, 153, 154, 155, 156, 157, 158, 159,
-+
-+/* 160 - 191 */
-+160, 33, 236, 237, 164, 92, 124, 167,
-+ 34, 169, 170, 171, 172, 173, 174, 175,
-+223, 177, 178, 179, 39, 249, 247, 165,
-+ 44, 185, 186, 187, 188, 189, 190, 63,
-+
-+/* 192 - 223 */
-+ 65, 65, 65, 65, 225, 65, 65, 67,
-+ 69, 69, 69, 69, 73, 73, 73, 73,
-+ 68, 78, 79, 79, 79, 79, 239, 120,
-+ 48, 85, 85, 85, 245, 89, 240, 226,
-+
-+/* 224 - 255 */
-+ 97, 97, 97, 97, 225, 97, 97, 99,
-+101, 101, 101, 101, 105, 105, 105, 105,
-+111, 110, 111, 111, 111, 111, 239, 253,
-+ 48, 117, 117, 117, 245, 121, 240, 255
-+
-+};
-diff --git a/drivers/lcd-linux/commands.h b/drivers/lcd-linux/commands.h
-new file mode 100644
-index 0000000..6567836
---- /dev/null
-+++ b/drivers/lcd-linux/commands.h
-@@ -0,0 +1,77 @@
-+/* commands.h
-+ *
-+ * $Id: commands.h,v 1.2 2009/03/09 17:59:22 mjona Exp $
-+ *
-+ * LCD-Linux:
-+ * Driver for HD44780 compatible displays connected to the parallel port.
-+ *
-+ * HD44780 commands.
-+ *
-+ * Copyright (C) 2004 - 2009 Mattia Jona-Lasinio (mjona@users.sourceforge.net)
-+ *
-+ * 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 HD44780_COMMANDS_H
-+#define HD44780_COMMANDS_H
-+
-+/*** HD44780 Command Set ***/
-+
-+/* Clear Display*/
-+#define CLR_DISP 0x01 /* Clear entire display; cursor at row 0, column 0 */
-+
-+/* Return Home */
-+#define RET_HOME 0x02 /* Cursor at row 0, column 0; display content doesn't change */
-+
-+/* Entry Mode Set */
-+#define ENTRY_MODE_SET 0x04
-+#define DISP_SHIFT_ON (ENTRY_MODE_SET | 0x01) /* Shift display, not cursor after data write */
-+#define DISP_SHIFT_OFF (ENTRY_MODE_SET | 0x00) /* Shift cursor, not display after data write */
-+#define CURS_INC (ENTRY_MODE_SET | 0x02) /* Shift on the right after data read/write */
-+#define CURS_DEC (ENTRY_MODE_SET | 0x00) /* Shift on the left after data read/write */
-+
-+/* Display on/off Control */
-+#define DISP_ONOFF_CNTR 0x08
-+#define BLINK_ON (DISP_ONOFF_CNTR | 0x01) /* Cursor blinking on */
-+#define BLINK_OFF (DISP_ONOFF_CNTR | 0x00) /* Cursor blinking off */
-+#define CURS_ON (DISP_ONOFF_CNTR | 0x02) /* Display Cursor */
-+#define CURS_OFF (DISP_ONOFF_CNTR | 0x00) /* Hide Cursor */
-+#define DISP_ON (DISP_ONOFF_CNTR | 0x04) /* Turn on display updating */
-+#define DISP_OFF (DISP_ONOFF_CNTR | 0x00) /* Freeze display content */
-+
-+/* Cursor or Display Shift */
-+#define CURS_DISP_SHIFT 0x10
-+#define SHIFT_RIGHT (CURS_DISP_SHIFT | 0x04) /* Shift on the right */
-+#define SHIFT_LEFT (CURS_DISP_SHIFT | 0x00) /* Shift on the left */
-+#define SHIFT_DISP (CURS_DISP_SHIFT | 0x08) /* Shift display */
-+#define SHIFT_CURS (CURS_DISP_SHIFT | 0x00) /* Shift cursor */
-+
-+/* Function Set */
-+#define FUNC_SET 0x20
-+#define FONT_5X10 (FUNC_SET | 0x04) /* Select 5x10 dots font */
-+#define FONT_5X8 (FUNC_SET | 0x00) /* Select 5x8 dots font */
-+#define DISP_2_LINES (FUNC_SET | 0x08) /* Select 2 lines display (only 5x8 font allowed) */
-+#define DISP_1_LINE (FUNC_SET | 0x00) /* Select 1 line display */
-+#define BUS_8_BITS (FUNC_SET | 0x10) /* Set 8 data bits */
-+#define BUS_4_BITS (FUNC_SET | 0x00) /* Set 4 data bits */
-+
-+/* Set CGRAM Address */
-+#define CGRAM_IO 0x40 /* Base CGRAM address */
-+
-+/* Set DDRAM Address */
-+#define DDRAM_IO 0x80 /* Base DDRAM address */
-+
-+#endif /* commands included */
-diff --git a/drivers/lcd-linux/config.h b/drivers/lcd-linux/config.h
-new file mode 100644
-index 0000000..face191
---- /dev/null
-+++ b/drivers/lcd-linux/config.h
-@@ -0,0 +1,73 @@
-+/* config.h
-+ *
-+ * $Id: config.h,v 1.16 2009/09/27 21:27:03 mjona Exp $
-+ *
-+ * Configure file for LCD-Linux. Here you must specify your hardware setup and
-+ * timings constants. The default values will probably be right for you.
-+ *
-+ * Copyright (C) 2005 - 2009 Mattia Jona-Lasinio (mjona@users.sourceforge.net)
-+ *
-+ * 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
-+ *
-+ *
-+ */
-+
-+/* Setup the default user defined characters in CGRAM */
-+#include "cgram/default.h"
-+/* #include "cgram/swedish.h" */
-+/* #include "cgram/cgram.h" */
-+
-+/* Don't modify the default timing constants
-+ * unless you know what you are doing.
-+ */
-+
-+/* In case of a 4 bit bus, indicate your
-+ * wiring configuration for the data bits
-+ *
-+ * 0 -> D3, D2, D1, D0
-+ * 1 -> D4, D3, D2, D1
-+ * 2 -> D5, D4, D3, D2
-+ * 3 -> D6, D5, D4, D3
-+ * 4 -> D7, D6, D5, D4
-+ */
-+#define SETUP 4
-+
-+#define HIGH_NIBBLE_WRITE(x) (((x) >> (4-SETUP)) & (0x0f << SETUP))
-+#define LOW_NIBBLE_WRITE(x) (((x) << SETUP) & (0x0f << SETUP))
-+#define HIGH_NIBBLE_READ(x) (((x) & (0x0f << SETUP)) << (4-SETUP))
-+#define LOW_NIBBLE_READ(x) (((x) & (0x0f << SETUP)) >> SETUP)
-+
-+/* Execution times (in microseconds) */
-+#define T_READ 60 /* Read execution time (min 43 us) */
-+#define T_WRITE 60 /* Write execution time (min 43 us) */
-+#define T_BF 4 /* Busy flag polling time (min 1 us) */
-+
-+/* Timings in nanoseconds */
-+#define T_AS 200 /* Address set-up time (min 140 ns) */
-+#define T_EH 500 /* Enable high time (min 450 ns) */
-+#define T_EL 800 /* Enable low time (min 500 ns) */
-+
-+/* Various constants */
-+#define DFLT_NUM_CNTR 1 /* Default number of controllers the display has */
-+#define DFLT_CNTR_ROWS 4 /* Default number of rows per controller */
-+#define DFLT_CNTR_COLS 20 /* Default number of columns the display has */
-+#define DFLT_VS_ROWS 25 /* Default number of rows for the virtual screen */
-+#define DFLT_VS_COLS 80 /* Default number of columns for the virtual screen */
-+#define DFLT_TABSTOP 4 /* Default length of tabs */
-+#define DFLT_FLAGS HD44780_CHECK_BF /* Default flags: check BF and 8 bit bus */
-+
-+#define MAX_NUM_CNTR 7 /* We support up to 7 controllers */
-+#define MAX_CNTR_ROWS 4 /* The HD44780 supports up to 4 lines as a fake 2 lines mode */
-+#define MAX_CNTR_COLS 80 /* The HD44780 supports up to 80 characters (1*80; 2*40; etc) */
-diff --git a/drivers/lcd-linux/hd44780.c b/drivers/lcd-linux/hd44780.c
-new file mode 100644
-index 0000000..0b1af6b
---- /dev/null
-+++ b/drivers/lcd-linux/hd44780.c
-@@ -0,0 +1,854 @@
-+/* hd44780.c
-+ *
-+ * $Id: hd44780.c,v 1.181 2010/03/03 14:56:22 mjona Exp $
-+ *
-+ * LCD-Linux:
-+ * Driver for HD44780 compatible displays connected to the parallel port.
-+ *
-+ * Copyright (C) 2005 - 2009 Mattia Jona-Lasinio (mjona@users.sourceforge.net)
-+ * Based on the code for Sim.One Hardware by Nuccio Raciti (raciti.nuccio@gmail.com)
-+ * Modified for ts72xx hardware by Petr Stetiar (ynezz@true.cz)
-+ * (Only 8-bit mode supported for now.)
-+ *
-+ * 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
-+ *
-+ */
-+
-+#ifdef CONFIG_PROC_FS
-+#define USE_PROC
-+#else
-+#undef USE_PROC
-+#endif
-+
-+#include <linux/bitops.h>
-+#include <linux/kernel.h>
-+#include <linux/module.h>
-+
-+#include <linux/delay.h>
-+#include <linux/fs.h>
-+
-+#include <asm/uaccess.h>
-+#include <asm/gpio.h>
-+#include <asm/io.h>
-+#include <linux/init.h>
-+#include <linux/ioport.h>
-+
-+#ifdef USE_PROC
-+#include <linux/proc_fs.h>
-+#endif
-+
-+#define LCD_LINUX_MAIN
-+#include <linux/hd44780.h>
-+
-+#include "charmap.h"
-+#include "commands.h"
-+#include "config.h"
-+
-+#define LCD_EN EP93XX_GPIO_LINE_H(3)
-+#define LCD_RS EP93XX_GPIO_LINE_H(4)
-+#define LCD_WR EP93XX_GPIO_LINE_H(5)
-+#define LCD_DATA0 EP93XX_GPIO_LINE_A(0)
-+#define LCD_DATA1 EP93XX_GPIO_LINE_A(1)
-+#define LCD_DATA2 EP93XX_GPIO_LINE_A(2)
-+#define LCD_DATA3 EP93XX_GPIO_LINE_A(3)
-+#define LCD_DATA4 EP93XX_GPIO_LINE_A(4)
-+#define LCD_DATA5 EP93XX_GPIO_LINE_A(5)
-+#define LCD_DATA6 EP93XX_GPIO_LINE_A(6)
-+#define LCD_DATA7 EP93XX_GPIO_LINE_A(7)
-+
-+static struct gpio lcd_gpios[] = {
-+ { LCD_EN, GPIOF_OUT_INIT_LOW, "LCD enable" },
-+ { LCD_RS, GPIOF_OUT_INIT_LOW, "LCD data" },
-+ { LCD_WR, GPIOF_OUT_INIT_LOW, "LCD r/w" },
-+ { LCD_DATA0, GPIOF_OUT_INIT_LOW, "LCD data0" },
-+ { LCD_DATA1, GPIOF_OUT_INIT_LOW, "LCD data1" },
-+ { LCD_DATA2, GPIOF_OUT_INIT_LOW, "LCD data2" },
-+ { LCD_DATA3, GPIOF_OUT_INIT_LOW, "LCD data3" },
-+ { LCD_DATA4, GPIOF_OUT_INIT_LOW, "LCD data4" },
-+ { LCD_DATA5, GPIOF_OUT_INIT_LOW, "LCD data5" },
-+ { LCD_DATA6, GPIOF_OUT_INIT_LOW, "LCD data6" },
-+ { LCD_DATA7, GPIOF_OUT_INIT_LOW, "LCD data7" },
-+};
-+
-+/** Function prototypes **/
-+static void read_display(unsigned char *byte, unsigned char bitmask);
-+static void write_display(unsigned char byte, unsigned char bitmask);
-+
-+/* Initialization */
-+static int hd44780_validate_driver(void);
-+static int hd44780_init_port(void);
-+static int hd44780_cleanup_port(void);
-+static int hd44780_init_display(void);
-+static int hd44780_cleanup_display(void);
-+
-+/* Write */
-+static void hd44780_address_mode(int);
-+static void hd44780_clear_display(void);
-+static void hd44780_write_char(unsigned int, unsigned short);
-+static void hd44780_write_cgram_char(unsigned char, unsigned char *);
-+
-+/* Read */
-+static void check_bf(unsigned char);
-+static void hd44780_read_char(unsigned int, unsigned short *);
-+static void hd44780_read_cgram_char(unsigned char, unsigned char *);
-+
-+/* Input handling */
-+static int hd44780_handle_custom_char(unsigned int);
-+static int hd44780_handle_custom_ioctl(unsigned int, unsigned long, unsigned int);
-+
-+/* Proc operations */
-+#ifdef USE_PROC
-+static void create_proc_entries(void);
-+static void remove_proc_entries(void);
-+#endif
-+
-+/* hd44780_flags */
-+#define _CHECK_BF 0 /* Do busy-flag checking */
-+#define _4BITS_BUS 1 /* The bus is 4 bits long */
-+#define _5X10_FONT 2 /* Use 5x10 font */
-+#define CURSOR_BLINK 3 /* Make the cursor blinking */
-+#define SHOW_CURSOR 4 /* Make the cursor visible */
-+#define DISPLAY_ON 5 /* Display status: on or off */
-+#define INC_ADDR 6 /* Increment address after data read/write */
-+#define BACKLIGHT 7 /* Display backlight: on or off */
-+#define CGRAM_STATE 9 /* Controller status bitmask (bits 9->15): DDRAM or CGRAM access */
-+
-+/* hd44780 access */
-+#define ACCESS_TO_READ 0
-+#define ACCESS_TO_WRITE 1
-+#define ACCESS_TO_DATA 2
-+
-+#define ESC_MASK 0x00ff0000
-+#define PROC_MASK 0x0f000000
-+
-+#define SET_STATE(state, mask) (hd44780_flags = (hd44780_flags & ~(mask)) | ((state) & (mask)))
-+#define SET_ESC_STATE(state) SET_STATE((state) << 16, ESC_MASK)
-+#define SET_PROC_LEVEL(level) SET_STATE((level) << 24, PROC_MASK)
-+#define ESC_STATE ((hd44780_flags & ESC_MASK) >> 16)
-+#define PROC_LEVEL ((hd44780_flags & PROC_MASK) >> 24)
-+
-+/* globals */
-+static unsigned int disp_size; /* Display size (rows*columns) */
-+static unsigned int disp_offset[1]; /* Physical cursor position on the display */
-+static unsigned long hd44780_flags; /* Driver flags for internal use only */
-+
-+static struct lcd_parameters par = {
-+ .name = HD44780_STRING,
-+ .minor = HD44780_MINOR,
-+ .flags = DFLT_FLAGS,
-+ .tabstop = DFLT_TABSTOP,
-+ .num_cntr = 1,
-+ .cntr_rows = DFLT_CNTR_ROWS,
-+ .cntr_cols = DFLT_CNTR_COLS,
-+ .vs_rows = DFLT_VS_ROWS,
-+ .vs_cols = DFLT_VS_COLS,
-+ .cgram_chars = 8,
-+ .cgram_bytes = 8,
-+ .cgram_char0 = 0,
-+};
-+/* End of globals */
-+
-+#ifdef MODULE
-+#include <linux/device.h>
-+MODULE_ALIAS_CHARDEV(LCD_MAJOR, HD44780_MINOR);
-+#include <linux/kmod.h>
-+
-+static unsigned short flags = DFLT_FLAGS;
-+static unsigned short tabstop = DFLT_TABSTOP;
-+static unsigned short cntr_rows = DFLT_CNTR_ROWS;
-+static unsigned short cntr_cols = DFLT_CNTR_COLS;
-+static unsigned short vs_rows = DFLT_VS_ROWS;
-+static unsigned short vs_cols = DFLT_VS_COLS;
-+static unsigned short minor = HD44780_MINOR;
-+
-+MODULE_DESCRIPTION("LCD ts72xx driver for HD44780 compatible controllers.");
-+MODULE_AUTHOR("Petr Stetiar <ynezz@true.cz>");
-+#ifdef MODULE_LICENSE
-+MODULE_LICENSE("GPL");
-+#endif
-+module_param(flags, ushort, 0444);
-+module_param(cntr_rows, ushort, 0444);
-+module_param(cntr_cols, ushort, 0444);
-+module_param(vs_rows, ushort, 0444);
-+module_param(vs_cols, ushort, 0444);
-+module_param(tabstop, ushort, 0444);
-+module_param(minor, ushort, 0444);
-+MODULE_PARM_DESC(flags, "Various flags (see Documentation)");
-+MODULE_PARM_DESC(cntr_rows, "Number of rows per controller on the LCD: 1, 2, 4 (default: " string(DFLT_CNTR_ROWS) ")");
-+MODULE_PARM_DESC(cntr_cols, "Number of columns on the LCD (default: " string(DFLT_CNTR_COLS) ", max: " string(MAX_CNTR_COLS) ")");
-+MODULE_PARM_DESC(vs_rows, "Number of rows of the virtual screen (default: " string(DFLT_VS_ROWS) ")");
-+MODULE_PARM_DESC(vs_cols, "Number of columns of the virtual screen (default: " string(DFLT_VS_COLS) ")");
-+MODULE_PARM_DESC(tabstop, "Tab character length (default: " string(DFLT_TABSTOP) ")");
-+MODULE_PARM_DESC(minor, "Assigned minor number (default: " string(HD44780_MINOR) ")");
-+#else
-+
-+/*
-+ * Parse boot command line
-+ *
-+ * hd44780=cntr_rows,cntr_cols,vs_rows,vs_cols,flags,minor,tabstop
-+ */
-+static int __init hd44780_boot_init(char *cmdline)
-+{
-+ char *str = cmdline;
-+ int idx = 0;
-+ unsigned short *args[] = {
-+ &par.cntr_rows,
-+ &par.cntr_cols,
-+ &par.vs_rows,
-+ &par.vs_cols,
-+ (ushort *) &par.flags,
-+ &par.num_cntr,
-+ &par.minor,
-+ &par.tabstop,
-+ };
-+
-+ while (*cmdline && idx < (sizeof(args)/sizeof(unsigned short *))) {
-+ switch (*str) {
-+ case ',':
-+ *str++ = 0;
-+ case 0:
-+ if (strlen(cmdline))
-+ *args[idx] = simple_strtoul(cmdline, NULL, 0);
-+ ++idx;
-+ cmdline = str;
-+ break;
-+ default:
-+ ++str;
-+ break;
-+ }
-+ }
-+
-+ return (1);
-+}
-+
-+__setup("hd44780=", hd44780_boot_init);
-+#endif /* MODULE */
-+
-+/* Macros for iterator handling */
-+static inline unsigned int iterator_inc_(unsigned int iterator, const unsigned int module)
-+{
-+ return ((++iterator)%module);
-+}
-+
-+static inline unsigned int iterator_dec_(unsigned int iterator, const unsigned int module)
-+{
-+ return (iterator ? --iterator : module-1);
-+}
-+
-+#define iterator_inc(iterator, module) (iterator = iterator_inc_(iterator, module))
-+#define iterator_dec(iterator, module) (iterator = iterator_dec_(iterator, module))
-+
-+static inline void set_lines(unsigned char bitmask)
-+{
-+ gpio_set_value(LCD_EN, 0); /* Disable */
-+
-+ if (bitmask & ACCESS_TO_WRITE ) {
-+ gpio_direction_output(LCD_DATA0, 0);
-+ gpio_direction_output(LCD_DATA1, 0);
-+ gpio_direction_output(LCD_DATA2, 0);
-+ gpio_direction_output(LCD_DATA3, 0);
-+ gpio_direction_output(LCD_DATA4, 0);
-+ gpio_direction_output(LCD_DATA5, 0);
-+ gpio_direction_output(LCD_DATA6, 0);
-+ gpio_direction_output(LCD_DATA7, 0);
-+ gpio_set_value(LCD_WR, 0); /* Write */
-+ } else {
-+ gpio_direction_input(LCD_DATA0);
-+ gpio_direction_input(LCD_DATA1);
-+ gpio_direction_input(LCD_DATA2);
-+ gpio_direction_input(LCD_DATA3);
-+ gpio_direction_input(LCD_DATA4);
-+ gpio_direction_input(LCD_DATA5);
-+ gpio_direction_input(LCD_DATA6);
-+ gpio_direction_input(LCD_DATA7);
-+ gpio_set_value(LCD_WR, 1); /* Read */
-+ }
-+
-+ if (bitmask & ACCESS_TO_DATA )
-+ gpio_set_value(LCD_RS, 1); /* Data */
-+ else
-+ gpio_set_value(LCD_RS, 0); /* Cmds*/
-+}
-+
-+static inline void read_display(unsigned char *byte, unsigned char bitmask)
-+{
-+ unsigned char ret;
-+ if (bitmask)
-+ check_bf(bitmask);
-+
-+ set_lines(bitmask);
-+
-+ ndelay(T_AS); /* Address set-up time */
-+ gpio_set_value(LCD_EN, 1); /* Enable */
-+ ndelay(T_EH); /* Enable high time */
-+
-+ ret = (gpio_get_value(LCD_DATA0) << 0);
-+ ret |= (gpio_get_value(LCD_DATA1) << 1);
-+ ret |= (gpio_get_value(LCD_DATA2) << 2);
-+ ret |= (gpio_get_value(LCD_DATA3) << 3);
-+ ret |= (gpio_get_value(LCD_DATA4) << 4);
-+ ret |= (gpio_get_value(LCD_DATA5) << 5);
-+ ret |= (gpio_get_value(LCD_DATA6) << 6);
-+ ret |= (gpio_get_value(LCD_DATA7) << 7);
-+
-+ gpio_set_value(LCD_EN, 0); /* Disable */
-+ ndelay(T_EL); /* Enable low time */
-+ *byte = ret;
-+}
-+
-+/* Low level write to the display */
-+static inline void write_display(unsigned char data, unsigned char bitmask)
-+{
-+ check_bf(bitmask);
-+ set_lines(bitmask);
-+
-+ gpio_set_value(LCD_DATA0, (data >> 0) & 1);
-+ gpio_set_value(LCD_DATA1, (data >> 1) & 1);
-+ gpio_set_value(LCD_DATA2, (data >> 2) & 1);
-+ gpio_set_value(LCD_DATA3, (data >> 3) & 1);
-+ gpio_set_value(LCD_DATA4, (data >> 4) & 1);
-+ gpio_set_value(LCD_DATA5, (data >> 5) & 1);
-+ gpio_set_value(LCD_DATA6, (data >> 6) & 1);
-+ gpio_set_value(LCD_DATA7, (data >> 7) & 1);
-+
-+ ndelay(T_AS); /* Address set-up time */
-+ gpio_set_value(LCD_EN, 1);
-+ ndelay(T_EH); /* Enable high time */
-+
-+ gpio_set_value(LCD_EN, 0); /* Disable */
-+ ndelay(T_EL); /* Enable low time */
-+}
-+
-+/* Read Address Counter AC from the display */
-+static unsigned char read_ac(unsigned char bitmask)
-+{
-+ unsigned char byte;
-+
-+ read_display(&byte, bitmask);
-+
-+ return (byte);
-+}
-+
-+static void check_bf(unsigned char bitmask)
-+{
-+ unsigned int timeout = 20;
-+ static unsigned char do_check_bf = 5;
-+
-+ gpio_set_value(LCD_EN, 0); /* Disable */
-+
-+ gpio_direction_input(LCD_DATA0);
-+ gpio_direction_input(LCD_DATA1);
-+ gpio_direction_input(LCD_DATA2);
-+ gpio_direction_input(LCD_DATA3);
-+ gpio_direction_input(LCD_DATA4);
-+ gpio_direction_input(LCD_DATA5);
-+ gpio_direction_input(LCD_DATA6);
-+ gpio_direction_input(LCD_DATA7);
-+
-+ gpio_set_value(LCD_WR, 1); /* Read */
-+ gpio_set_value(LCD_RS, 0); /* Instru */
-+
-+ ndelay(T_AS); /* Address set-up time */
-+ gpio_set_value(LCD_EN, 1); /* Enable */
-+ ndelay(T_EH); /* Enable high time */
-+
-+ do {
-+ udelay(T_BF);
-+ } while (gpio_get_value(LCD_DATA7) && --timeout);
-+
-+ if (!timeout) {
-+ if (!--do_check_bf) {
-+ printk(KERN_NOTICE "hd44780 error: is LCD connected?\n");
-+ }
-+ }
-+
-+ gpio_set_value(LCD_EN, 0); /* Disable */
-+ ndelay(T_EL); /* Enable low time */
-+}
-+
-+/* Send commands to the display */
-+static void write_command(unsigned char command)
-+{
-+ write_display(command, ACCESS_TO_WRITE);
-+
-+ if (command <= 0x03)
-+ mdelay(2);
-+}
-+
-+static inline void set_cursor(unsigned int offset)
-+{
-+ unsigned int disp_number = offset/disp_size;
-+ unsigned int local_offset = offset%disp_size;
-+
-+ if (disp_offset[disp_number] != local_offset || test_bit(CGRAM_STATE+disp_number, &hd44780_flags)) {
-+ unsigned int disp_row = local_offset/par.cntr_cols;
-+ unsigned int disp_column = local_offset%par.cntr_cols;
-+
-+ write_command(DDRAM_IO | ((disp_row%2)*0x40) | (((disp_row >= 2)*par.cntr_cols)+disp_column));
-+ clear_bit(CGRAM_STATE+disp_number, &hd44780_flags);
-+ disp_offset[disp_number] = local_offset;
-+ }
-+}
-+
-+/* HD44780 DDRAM addresses are consecutive only when
-+ * the cursor moves on the same row of the display.
-+ * Every time the row of the cursor changes we invalidate
-+ * the cursor position to force hardware cursor repositioning.
-+ */
-+static inline void mov_cursor(unsigned int disp_number)
-+{
-+ if (test_bit(INC_ADDR, &hd44780_flags)) {
-+ iterator_inc(disp_offset[disp_number], disp_size);
-+ if (disp_offset[disp_number]%par.cntr_cols == 0)
-+ disp_offset[disp_number] = disp_size;
-+ } else {
-+ iterator_dec(disp_offset[disp_number], disp_size);
-+ if (disp_offset[disp_number]%par.cntr_cols == par.cntr_cols-1)
-+ disp_offset[disp_number] = disp_size;
-+ }
-+}
-+
-+static struct lcd_driver hd44780 = {
-+ .read_char = hd44780_read_char,
-+ .read_cgram_char = hd44780_read_cgram_char,
-+ .write_char = hd44780_write_char,
-+ .write_cgram_char = hd44780_write_cgram_char,
-+ .address_mode = hd44780_address_mode,
-+ .clear_display = hd44780_clear_display,
-+ .validate_driver = hd44780_validate_driver,
-+ .init_display = hd44780_init_display,
-+ .cleanup_display = hd44780_cleanup_display,
-+ .init_port = hd44780_init_port,
-+ .cleanup_port = hd44780_cleanup_port,
-+ .handle_custom_char = hd44780_handle_custom_char,
-+ .handle_custom_ioctl = hd44780_handle_custom_ioctl,
-+
-+ .charmap = charmap,
-+};
-+
-+static void hd44780_read_char(unsigned int offset, unsigned short *data)
-+{
-+ unsigned int disp_number = offset/disp_size;
-+ unsigned char tmp;
-+
-+ set_cursor(offset);
-+ read_display(&tmp, ACCESS_TO_DATA);
-+ *data = tmp;
-+ mov_cursor(disp_number);
-+}
-+
-+static void hd44780_read_cgram_char(unsigned char index, unsigned char *pixels)
-+{
-+ unsigned int i;
-+
-+ write_command(CGRAM_IO | (index << 3));
-+ set_bit(CGRAM_STATE+0, &hd44780_flags);
-+
-+ for (i = 0; i < 8; ++i) {
-+ read_display(pixels+i, ACCESS_TO_DATA);
-+ pixels[i] &= 0x1f;
-+ }
-+
-+}
-+
-+static void hd44780_write_char(unsigned int offset, unsigned short data)
-+{
-+ unsigned int disp_number = offset/disp_size;
-+
-+ set_cursor(offset);
-+ write_display(data & 0xff, ACCESS_TO_WRITE | ACCESS_TO_DATA);
-+ mov_cursor(disp_number);
-+}
-+
-+static void hd44780_write_cgram_char(unsigned char index, unsigned char *pixels)
-+{
-+ unsigned int i;
-+
-+ /* Move address pointer to index in CGRAM */
-+ write_command(CGRAM_IO | (index << 3));
-+ set_bit(CGRAM_STATE+0, &hd44780_flags);
-+
-+ for (i = 0; i < 8; ++i) {
-+ pixels[i] &= 0x1f;
-+ write_display(pixels[i], ACCESS_TO_WRITE | ACCESS_TO_DATA );
-+ }
-+}
-+
-+/* Increment/decrement address mode after a data read/write */
-+static void hd44780_address_mode(int mode)
-+{
-+ if (mode > 0 && ! test_bit(INC_ADDR, &hd44780_flags)) {
-+ write_command(CURS_INC | DISP_SHIFT_OFF);
-+ set_bit(INC_ADDR, &hd44780_flags);
-+ } else if (mode < 0 && test_bit(INC_ADDR, &hd44780_flags)) {
-+ write_command(CURS_DEC | DISP_SHIFT_OFF);
-+ clear_bit(INC_ADDR, &hd44780_flags);
-+ }
-+}
-+
-+static void hd44780_clear_display(void)
-+{
-+ write_command(CLR_DISP);
-+ if (! test_bit(INC_ADDR, &hd44780_flags))
-+ write_command(CURS_DEC | DISP_SHIFT_OFF);
-+ memset(disp_offset, 0, sizeof(disp_offset));
-+}
-+
-+static int hd44780_validate_driver(void)
-+{
-+ if (par.cntr_rows != 1 && par.cntr_rows != 2 && par.cntr_rows != 4)
-+ par.cntr_rows = DFLT_CNTR_ROWS;
-+
-+ if (par.cntr_rows != 1)
-+ par.flags &= ~HD44780_5X10_FONT;
-+
-+ if (! par.cntr_cols || par.cntr_cols > MAX_CNTR_COLS/par.cntr_rows)
-+ par.cntr_cols = MAX_CNTR_COLS/par.cntr_rows;
-+
-+ disp_size = par.cntr_rows*par.cntr_cols;
-+
-+ /* These parameters depend on the hardware and cannot be changed */
-+ par.cgram_chars = 8;
-+ par.cgram_bytes = 8;
-+ par.cgram_char0 = 0;
-+
-+ return (0);
-+}
-+
-+/* Send init commands to the display */
-+static void write_init_command(void)
-+{
-+ unsigned char command;
-+ command = BUS_8_BITS;
-+ command |= ((par.cntr_rows == 1) ? DISP_1_LINE : DISP_2_LINES);
-+ command |= (test_bit(_5X10_FONT, &hd44780_flags) ? FONT_5X10 : FONT_5X8);
-+
-+ write_display(command, ACCESS_TO_WRITE);
-+ mdelay(20); /* Wait more than 4.1 ms */
-+
-+ write_display(command, ACCESS_TO_WRITE);
-+ udelay(200); /* Wait more than 100 us */
-+
-+ write_display(command, ACCESS_TO_WRITE);
-+ udelay(200); /* Wait more than 100 us */
-+
-+ write_command(command);
-+}
-+
-+static int hd44780_init_display(void)
-+{
-+ if (par.flags & HD44780_CHECK_BF)
-+ set_bit(_CHECK_BF, &hd44780_flags);
-+ else
-+ clear_bit(_CHECK_BF, &hd44780_flags);
-+
-+ if (par.flags & HD44780_4BITS_BUS)
-+ set_bit(_4BITS_BUS, &hd44780_flags);
-+ else
-+ clear_bit(_4BITS_BUS, &hd44780_flags);
-+
-+ if (par.flags & HD44780_5X10_FONT)
-+ set_bit(_5X10_FONT, &hd44780_flags);
-+ else
-+ clear_bit(_5X10_FONT, &hd44780_flags);
-+
-+ write_init_command();
-+ hd44780_address_mode(1);
-+ hd44780_clear_display();
-+ write_command(DISP_ON | CURS_OFF | BLINK_OFF);
-+ set_bit(DISPLAY_ON, &hd44780_flags);
-+ clear_bit(SHOW_CURSOR, &hd44780_flags);
-+ clear_bit(CURSOR_BLINK, &hd44780_flags);
-+
-+ /* Set the CGRAM to default values */
-+ hd44780_write_cgram_char(0, cg0);
-+ hd44780_write_cgram_char(1, cg1);
-+ hd44780_write_cgram_char(2, cg2);
-+ hd44780_write_cgram_char(3, cg3);
-+ hd44780_write_cgram_char(4, cg4);
-+ hd44780_write_cgram_char(5, cg5);
-+ hd44780_write_cgram_char(6, cg6);
-+ hd44780_write_cgram_char(7, cg7);
-+ init_charmap();
-+
-+ return (0);
-+}
-+
-+static int hd44780_cleanup_display(void)
-+{
-+ hd44780_clear_display();
-+
-+ return (0);
-+}
-+
-+static int hd44780_init_port(void)
-+{
-+ int err = gpio_request_array(lcd_gpios, ARRAY_SIZE(lcd_gpios));
-+ if (err) {
-+ printk(KERN_ERR "hd44780: error while requesting GPIO pins\n");
-+ return 1;
-+ }
-+
-+ return 0;
-+}
-+
-+static int hd44780_cleanup_port(void)
-+{
-+ gpio_direction_input(LCD_RS);
-+ gpio_direction_input(LCD_EN);
-+ gpio_direction_input(LCD_DATA0);
-+ gpio_direction_input(LCD_DATA1);
-+ gpio_direction_input(LCD_DATA2);
-+ gpio_direction_input(LCD_DATA3);
-+ gpio_direction_input(LCD_DATA4);
-+ gpio_direction_input(LCD_DATA5);
-+ gpio_direction_input(LCD_DATA6);
-+ gpio_direction_input(LCD_DATA7);
-+
-+ gpio_free_array(lcd_gpios, ARRAY_SIZE(lcd_gpios));
-+
-+ return 0;
-+}
-+
-+static void display_attr(unsigned char input)
-+{
-+ unsigned char command;
-+
-+ switch (ESC_STATE) {
-+ case 'a': /* Turn on/off the display cursor */
-+ if (input == '1')
-+ set_bit(SHOW_CURSOR, &hd44780_flags);
-+ else if (input == '0')
-+ clear_bit(SHOW_CURSOR, &hd44780_flags);
-+ break;
-+ case 'b': /* Turn on/off the display cursor blinking */
-+ if (input == '1')
-+ set_bit(CURSOR_BLINK, &hd44780_flags);
-+ else if (input == '0')
-+ clear_bit(CURSOR_BLINK, &hd44780_flags);
-+ break;
-+ case 'h': /* Turn on/off the display */
-+ if (input == '1')
-+ set_bit(DISPLAY_ON, &hd44780_flags);
-+ else if (input == '0')
-+ clear_bit(DISPLAY_ON, &hd44780_flags);
-+ break;
-+ }
-+
-+ command = (test_bit(DISPLAY_ON, &hd44780_flags) ? DISP_ON : DISP_OFF);
-+ command |= (test_bit(SHOW_CURSOR, &hd44780_flags) ? CURS_ON : CURS_OFF);
-+ command |= (test_bit(CURSOR_BLINK, &hd44780_flags) ? BLINK_ON : BLINK_OFF);
-+
-+ if (ESC_STATE == 'h')
-+ write_command(command);
-+}
-+
-+static int hd44780_handle_custom_char(unsigned int _input)
-+{
-+ unsigned char input = _input & 0xff;
-+
-+ if (_input & (~0xff)) {
-+ switch (ESC_STATE) {
-+ case 'a': /* Turn on/off the display cursor */
-+ case 'b': /* Turn on/off the display cursor blinking */
-+ case 'h': /* Turn on/off the the display */
-+ display_attr(input);
-+ return (0);
-+ case 'l': /* Turn on/off the backlight */
-+ if (input == '1')
-+ set_bit(BACKLIGHT, &hd44780_flags);
-+ else if (input == '0')
-+ clear_bit(BACKLIGHT, &hd44780_flags);
-+ read_ac(ACCESS_TO_READ);
-+ return (0);
-+ }
-+ }
-+
-+ switch (input) {
-+ case 'a': /* Turn on/off the display cursor */
-+ case 'b': /* Turn on/off the display cursor blinking */
-+ case 'h': /* Turn on/off the display */
-+ case 'l': /* Turn on/off the backlight */
-+ SET_ESC_STATE(input);
-+ return (1);
-+ case 'd': /* Shift display cursor Right */
-+ write_command(SHIFT_CURS | SHIFT_RIGHT);
-+ return (0);
-+ case 'e': /* Shift display cursor Left */
-+ write_command(SHIFT_CURS | SHIFT_LEFT);
-+ return (0);
-+ case 'f': /* Shift display Right */
-+ write_command(SHIFT_DISP | SHIFT_RIGHT);
-+ return (0);
-+ case 'g': /* Shift display Left */
-+ write_command(SHIFT_DISP | SHIFT_LEFT);
-+ return (0);
-+ }
-+
-+ return (-1);
-+}
-+
-+static int hd44780_handle_custom_ioctl(unsigned int num, unsigned long arg, unsigned int user_space)
-+{
-+ unsigned char *buffer = (unsigned char *)arg;
-+
-+ if (num != HD44780_READ_AC)
-+ return (-ENOIOCTLCMD);
-+
-+ if (user_space)
-+ put_user(read_ac(ACCESS_TO_READ), buffer);
-+ else
-+ buffer[0] = read_ac(ACCESS_TO_READ);
-+
-+ return (0);
-+}
-+
-+#ifdef USE_PROC
-+static int hd44780_proc_status(char *buffer, char **start, off_t offset, int size, int *eof, void *data)
-+{
-+ char *temp = buffer;
-+
-+ /* Print display configuration */
-+ temp += sprintf(temp,
-+ "Interface:\t%u bits\n"
-+ "Display rows:\t%d\n"
-+ "Display cols:\t%d\n"
-+ "Screen rows:\t%d\n"
-+ "Screen cols:\t%d\n"
-+ "Read:\t\t%sabled\n"
-+ "Busy flag chk:\t%sabled\n"
-+ "Assigned minor:\t%u\n",
-+ (test_bit(_4BITS_BUS, &hd44780_flags) ? 4 : 8),
-+ par.cntr_rows, par.cntr_cols,
-+ par.vs_rows, par.vs_cols,
-+ (hd44780.read_char ? "En" : "Dis"),
-+ (test_bit(_CHECK_BF, &hd44780_flags) ? "En" : "Dis"),
-+ par.minor);
-+
-+ return (temp-buffer);
-+}
-+
-+static int hd44780_proc_cgram(char *buffer, char **start, off_t offset, int size, int *eof, void *data)
-+{
-+ char *temp = buffer;
-+ unsigned int i;
-+
-+ temp += sprintf(temp, "static void init_charmap(void)\n{\n"
-+ "\t/*\n"
-+ "\t * charmap[char mapped to cg0] = 0;\n"
-+ "\t * charmap[char mapped to cg1] = 1;\n"
-+ "\t * charmap[char mapped to cg2] = 2;\n"
-+ "\t * charmap[char mapped to cg3] = 3;\n"
-+ "\t * charmap[char mapped to cg4] = 4;\n"
-+ "\t * charmap[char mapped to cg5] = 5;\n"
-+ "\t * charmap[char mapped to cg6] = 6;\n"
-+ "\t * charmap[char mapped to cg7] = 7;\n"
-+ "\t */\n"
-+ "}\n\n");
-+
-+ for (i = 0; i < 8; ++i) {
-+ unsigned int j;
-+ unsigned char cgram_buffer[8];
-+
-+ temp += sprintf(temp, "static unsigned char cg%u[] = { ", i);
-+ hd44780_read_cgram_char(i, cgram_buffer);
-+ for (j = 0; j < 8; ++j)
-+ temp += sprintf(temp, "0x%.2x%s", cgram_buffer[j], (j == 7 ? " };\n" : ", "));
-+ }
-+
-+ return (temp-buffer);
-+}
-+
-+static void create_proc_entries(void)
-+{
-+ SET_PROC_LEVEL(0);
-+ if (create_proc_read_entry("status", 0, hd44780.driver_proc_root, hd44780_proc_status, NULL) == NULL) {
-+ printk(KERN_ERR "hd44780: cannot create /proc/lcd/%s/status\n", par.name);
-+ return;
-+ }
-+ SET_PROC_LEVEL(1);
-+ if (create_proc_read_entry("cgram.h", 0, hd44780.driver_proc_root, hd44780_proc_cgram, NULL) == NULL) {
-+ printk(KERN_ERR "hd44780: cannot create /proc/lcd/%s/cgram.h\n", par.name);
-+ return;
-+ }
-+ SET_PROC_LEVEL(2);
-+}
-+
-+static void remove_proc_entries(void)
-+{
-+ switch (PROC_LEVEL) {
-+ case 2:
-+ remove_proc_entry("cgram.h", hd44780.driver_proc_root);
-+ case 1:
-+ remove_proc_entry("status", hd44780.driver_proc_root);
-+ }
-+ SET_PROC_LEVEL(0);
-+}
-+#endif
-+
-+/* Initialization */
-+static int __init hd44780_init_module(void)
-+{
-+ int ret;
-+
-+#ifdef MODULE
-+ if ((ret = request_module("lcd-linux"))) {
-+ printk(KERN_ERR "hd44780: request_module() returned %d\n", ret);
-+ if (ret < 0) {
-+ if (ret != -ENOSYS) {
-+ printk(KERN_ERR "hd44780: failure while loading module lcd-linux\n");
-+ return (ret);
-+ }
-+ printk(KERN_ERR "hd44780: your kernel does not have kmod or kerneld support;\n");
-+ printk(KERN_ERR "hd44780: remember to load the lcd-linux module before\n");
-+ printk(KERN_ERR "hd44780: loading the hd44780 module\n");
-+ }
-+ }
-+
-+ if (flags != DFLT_FLAGS) par.flags = flags;
-+ if (tabstop != DFLT_TABSTOP) par.tabstop = tabstop;
-+ if (cntr_rows != DFLT_CNTR_ROWS) par.cntr_rows = cntr_rows;
-+ if (cntr_cols != DFLT_CNTR_COLS) par.cntr_cols = cntr_cols;
-+ if (vs_rows != DFLT_VS_ROWS) par.vs_rows = vs_rows;
-+ if (vs_cols != DFLT_VS_COLS) par.vs_cols = vs_cols;
-+ if (minor != HD44780_MINOR) par.minor = minor;
-+#endif
-+
-+ lcd_driver_setup(&hd44780);
-+ if ((ret = lcd_register_driver(&hd44780, &par)))
-+ return (ret);
-+
-+#ifdef USE_PROC
-+ if (hd44780.driver_proc_root)
-+ create_proc_entries();
-+#endif
-+
-+ printk(KERN_INFO "hd44780: ts72xx driver loaded\n" );
-+
-+ return (0);
-+}
-+
-+static void __exit hd44780_cleanup_module(void)
-+{
-+#ifdef USE_PROC
-+ if (hd44780.driver_proc_root)
-+ remove_proc_entries();
-+#endif
-+
-+ lcd_unregister_driver(&hd44780, &par);
-+}
-+
-+module_init(hd44780_init_module)
-+module_exit(hd44780_cleanup_module)
-diff --git a/drivers/lcd-linux/lcd-linux.c b/drivers/lcd-linux/lcd-linux.c
-new file mode 100644
-index 0000000..8f9bc38
---- /dev/null
-+++ b/drivers/lcd-linux/lcd-linux.c
-@@ -0,0 +1,3023 @@
-+/* lcd-linux.c
-+ *
-+ * $Id: lcd-linux.c,v 1.308 2010/03/03 14:56:22 mjona Exp $
-+ *
-+ * Software layer to drive LCD displays under Linux.
-+ *
-+ * Copyright (C) 2005 - 2009 Mattia Jona-Lasinio (mjona@users.sourceforge.net)
-+ *
-+ * 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/version.h>
-+
-+#ifndef KERNEL_VERSION
-+#define KERNEL_VERSION(a, b, c) (((a) << 16) + ((b) << 8) + (c))
-+#endif
-+
-+#ifndef LINUX_VERSION_CODE
-+#error - LINUX_VERSION_CODE undefined in 'linux/version.h'
-+#endif
-+
-+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 33)
-+#include <generated/autoconf.h>
-+#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0)
-+#include <linux/autoconf.h>
-+#else
-+#include <linux/config.h>
-+#endif
-+
-+#ifdef CONFIG_PROC_FS
-+#define USE_PROC
-+#else
-+#undef USE_PROC
-+#endif
-+
-+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26)
-+#include <linux/semaphore.h>
-+#else
-+#include <asm/semaphore.h>
-+#endif
-+
-+#include <linux/bitops.h>
-+
-+#include <linux/kernel.h>
-+#include <linux/module.h>
-+#include <linux/sched.h>
-+
-+#include <linux/fs.h>
-+
-+#include <asm/uaccess.h>
-+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0)
-+#include <linux/device.h>
-+#endif
-+#include <linux/init.h>
-+#include <linux/list.h>
-+#include <linux/slab.h>
-+#include <linux/selection.h>
-+#include <linux/vmalloc.h>
-+
-+#ifdef USE_PROC
-+#include <linux/proc_fs.h>
-+#endif
-+
-+#define LCD_LINUX_MAIN
-+#include <linux/lcd-linux.h>
-+
-+static inline void __set_br(unsigned long *x, unsigned long val, unsigned long start, unsigned long len)
-+{
-+ unsigned long mask = (1 << len)-1;
-+
-+ if (val <= mask) {
-+ mask <<= start;
-+ val <<= start;
-+ *x = (*x & ~mask) | val;
-+ }
-+}
-+
-+static inline unsigned long __get_br(unsigned long x, unsigned long start, unsigned long len)
-+{
-+ return ((x >> start) & ((1 << len)-1));
-+}
-+
-+/*** struct_flags ***/
-+
-+/* internal flags: bits [0:15] of struct_flags (16 flags allowed) */
-+#define NEED_WRAP 0 /* Next char will trigger a newline */
-+#define DECIM 1 /* Insert mode */
-+#define DECOM 2 /* Row origin of cursor: absolute or relative to scrolling region */
-+#define DECAWM 3 /* Autowrap */
-+#define DECSCNM 4 /* Inverted screen */
-+#define CRLF 5 /* Follow lf, vt, ff, with a cr */
-+#define INC_CURS_POS 6 /* Increment cursor position after data read/write */
-+#define QUES 7 /* CSI Esc sequence contains a question mark */
-+#define USER_SPACE 8 /* If set, the buffer pointed by arg in do_lcd_ioctl() is
-+ * assumed to be in user space otherwise it is in kernel space */
-+#define NULL_CHARMAP 9 /* The driver doesn't provide a charmap so the
-+ * lcd-linux layer provides one*/
-+#define CAN_DO_COLOR 10 /* The display is color capable */
-+#define WITH_ATTR 11 /* If set, the void * buffer in do_lcd_read/write() contains
-+ * attributes and therefore is an unsigned short * otherwise it
-+ * is an unsigned char *
-+ */
-+
-+/* input states: bits [24:27] of struct_flags (16 states allowed) */
-+#define NORMAL 0 /* Normal mode */
-+#define RAW 1 /* Raw mode (console emulation disabled) */
-+#define SYN 2 /* Synchronous Idle mode */
-+#define ESC 3 /* Escape mode */
-+#define CSI 4 /* CSI escape mode */
-+#define ESC_G0 5 /* G0 character set */
-+#define ESC_G1 6 /* G1 character set */
-+#define ESC_HASH 7 /* ESC # escape sequence */
-+#define ESC_PERCENT 8 /* ESC % escape sequence */
-+#define ARG 9 /* Waiting for arguments for the lcd-linux layer */
-+#define ARG_DRIVER 10 /* Waiting for arguments for the display driver */
-+
-+#define SET_ESC_STATE(p, x) __set_br(&(p)->struct_flags, x, 16, 8)
-+#define SET_INPUT_STATE(p, x) __set_br(&(p)->struct_flags, x, 24, 4)
-+#define SET_INIT_LEVEL(p, x) __set_br(&(p)->struct_flags, x, 28, 2)
-+#define SET_PROC_LEVEL(p, x) __set_br(&(p)->struct_flags, x, 30, 2)
-+#define ESC_STATE(p) __get_br((p)->struct_flags, 16, 8)
-+#define INPUT_STATE(p) __get_br((p)->struct_flags, 24, 4)
-+#define INIT_LEVEL(p) __get_br((p)->struct_flags, 28, 2)
-+#define PROC_LEVEL(p) __get_br((p)->struct_flags, 30, 2)
-+
-+/*** attributes ***/
-+#define I_MASK 0x03 /* Intensity (0 = low, 1 = normal, 2 = bright) */
-+#define ULINE 0x04 /* Underlined text */
-+#define REVERSE 0x08 /* Reversed video text */
-+#define BLINK 0x80 /* Blinking text */
-+
-+/*** Color attributes ***/
-+#define FG_COLOR 0x07 /* Foreground color mask */
-+#define FG_BRIGHT 0x08 /* Foreground bright color */
-+#define FG_MASK (FG_BRIGHT | FG_COLOR) /* Foreground mask */
-+#define BG_COLOR 0x70 /* Background color mask */
-+#define BG_BRIGHT 0x80 /* Background bright color */
-+#define BG_MASK (BG_BRIGHT | BG_COLOR) /* Background mask */
-+
-+#define NPAR 16 /* Max number of parameters in CSI escape sequence */
-+#define FLIP_BUF_SIZE (1 << 6) /* Flip buffer size (64 bytes) MUST be a power of 2 */
-+
-+struct lcd_struct {
-+ struct list_head lcd_list; /* Doubly linked list */
-+ struct semaphore lcd_sem; /* Locks this structure */
-+ struct lcd_driver *driver; /* The driver associated to this struct */
-+ struct lcd_parameters *par; /* The parameters associated to this struct */
-+ unsigned long struct_flags; /* Flags for internal use only */
-+ unsigned int refcount; /* Number of references to this struct */
-+
-+ unsigned short *display; /* The display buffer */
-+
-+ unsigned short *fb; /* The virtual screen framebuffer */
-+ unsigned int fb_size; /* Size of the framebuffer */
-+ unsigned int frame_base; /* Offset of row 0, column 0 of a frame in fb */
-+ unsigned int frame_size; /* Size of the frame */
-+
-+ unsigned int row; /* Current row in virtual screen */
-+ unsigned int col; /* Current column in virtual screen */
-+ unsigned int s_offset; /* Saved cursor position in virtual screen */
-+
-+ unsigned int top; /* Top scroll row in virtual screen */
-+ unsigned int bot; /* Bottom scroll row in virtual screen */
-+
-+ int esc_args; /* Number of arguments for a normal escape sequence */
-+ unsigned int csi_args[NPAR]; /* CSI parameters */
-+ unsigned int index; /* Index in csi_args and counter for cgram characters generation */
-+ unsigned char cgram_index; /* Index of the cgram character to be created */
-+ unsigned char *cgram_buffer; /* Buffer for cgram operations in this driver */
-+
-+ unsigned short erase_char; /* Character to be used when erasing */
-+ unsigned char attr; /* Current attributes */
-+ unsigned char color; /* Color for normal intensity mode */
-+ unsigned char s_color; /* Saved color for normal intensity mode */
-+ unsigned char defcolor; /* Default color for normal intensity mode */
-+ unsigned char ulcolor; /* Color for underline mode */
-+ unsigned char halfcolor; /* Color for low intensity mode */
-+ unsigned char attributes; /* Packed attributes */
-+ unsigned char s_attributes; /* Saved packed attributes */
-+
-+ unsigned char *s_charmap; /* Saved character map for this driver */
-+ unsigned char *flip_buf; /* High speed flip buffer */
-+};
-+
-+/** Function prototypes **/
-+
-+/* Init/Cleanup the driver */
-+static int init_driver(struct lcd_struct *);
-+static int cleanup_driver(struct lcd_struct *);
-+
-+/* Read from/Write to the driver */
-+static void read_data(struct lcd_struct *, unsigned short *);
-+static void read_cgram(struct lcd_struct *, unsigned char, unsigned char *);
-+static void write_data(struct lcd_struct *, unsigned short);
-+static void write_cgram(struct lcd_struct *, unsigned char, unsigned char *);
-+
-+/* Input handlers */
-+static void cr(struct lcd_struct *);
-+static void lf(struct lcd_struct *);
-+static void control_char(struct lcd_struct *, unsigned char);
-+static void handle_csi(struct lcd_struct *, unsigned char);
-+static int handle_custom_esc(struct lcd_struct *, unsigned int);
-+static int handle_esc(struct lcd_struct *, unsigned char);
-+static void handle_input(struct lcd_struct *, unsigned short);
-+
-+/* Low level file operations */
-+static ssize_t do_lcd_read(struct lcd_struct *, void *, size_t);
-+static ssize_t do_lcd_write(struct lcd_struct *, const void *, size_t);
-+static int do_lcd_open(struct lcd_struct *);
-+static int do_lcd_release(struct lcd_struct *);
-+static int do_lcd_ioctl(struct lcd_struct *, unsigned int, unsigned long);
-+
-+/* Proc functions */
-+#ifdef USE_PROC
-+static void create_driver_proc_entries(struct lcd_struct *);
-+static void remove_driver_proc_entries(struct lcd_struct *);
-+#endif
-+
-+/* globals */
-+static unsigned int major = LCD_MAJOR; /* Major number for LCD-Linux device */
-+static unsigned short minors = LCD_MINORS; /* Minor numbers allocated for LCD-Linux */
-+static LIST_HEAD(lcd_drivers); /* Registered lcd drivers */
-+static struct semaphore drivers_sem; /* Locks the lcd_drivers list */
-+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 13)
-+static struct class *lcd_linux_class;
-+#endif
-+#ifdef USE_PROC
-+static struct proc_dir_entry *lcd_proc_root;
-+#endif
-+/* End of globals */
-+
-+#ifdef MODULE
-+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0)
-+#include <linux/device.h>
-+MODULE_ALIAS_CHARDEV_MAJOR(LCD_MAJOR);
-+#endif
-+MODULE_DESCRIPTION("Software layer to drive LCD displays under Linux.");
-+MODULE_AUTHOR("Mattia Jona-Lasinio <mjona@users.sourceforge.net>");
-+#ifdef MODULE_LICENSE
-+MODULE_LICENSE("GPL");
-+#endif
-+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0)
-+module_param(minors, ushort, 0444);
-+#else
-+MODULE_PARM(minors, "h");
-+#endif
-+MODULE_PARM_DESC(minors, "Minor numbers allocated for LCD-Linux (default: " string(LCD_MINORS) ")");
-+#else
-+
-+/*
-+ * Parse boot command line
-+ *
-+ * lcd=minors
-+ */
-+static int __init lcd_linux_boot_init(char *cmdline)
-+{
-+ unsigned short args;
-+
-+ if ((args = simple_strtoul(cmdline, NULL, 0)))
-+ minors = args;
-+
-+ return (1);
-+}
-+
-+__setup("lcd=", lcd_linux_boot_init);
-+#endif /* MODULE */
-+
-+/* Macros for iterator handling */
-+static inline unsigned int iterator_inc_(unsigned int iterator, const unsigned int module)
-+{
-+ return ((++iterator)%module);
-+}
-+
-+static inline unsigned int iterator_dec_(unsigned int iterator, const unsigned int module)
-+{
-+ return (iterator ? --iterator : module-1);
-+}
-+
-+#define iterator_inc(iterator, module) (iterator = iterator_inc_(iterator, module))
-+#define iterator_dec(iterator, module) (iterator = iterator_dec_(iterator, module))
-+
-+/* Uncomment the following two lines
-+ * for non-atomic set_bit and clear_bit
-+ */
-+//#define set_bit __set_bit
-+//#define clear_bit __clear_bit
-+
-+/************************************
-+ * Low level routines and utilities *
-+ ************************************/
-+/*
-+ * Set whether the address counter should be incremented
-+ * or decremented after a Read/Write
-+ */
-+static void address_mode(struct lcd_struct *p, int mode)
-+{
-+ struct lcd_driver *driver = p->driver;
-+
-+ if (mode > 0 && ! test_bit(INC_CURS_POS, &p->struct_flags)) {
-+ if (driver->address_mode)
-+ driver->address_mode(mode);
-+ set_bit(INC_CURS_POS, &p->struct_flags);
-+ } else if (mode < 0 && test_bit(INC_CURS_POS, &p->struct_flags)) {
-+ if (driver->address_mode)
-+ driver->address_mode(mode);
-+ clear_bit(INC_CURS_POS, &p->struct_flags);
-+ }
-+}
-+
-+/* WARNING!! This function returns an int because if iterator is not
-+ * within the visible area of the frame it returns -1
-+ */
-+static inline int vs_to_frame_(struct lcd_struct *p, unsigned int iterator)
-+{
-+ unsigned int vs_rows = p->par->vs_rows;
-+ unsigned int vs_cols = p->par->vs_cols;
-+ unsigned int row = iterator/vs_cols;
-+ unsigned int col = iterator%vs_cols;
-+ unsigned int frame_base_row = p->frame_base/vs_cols;
-+ unsigned int frame_base_col = p->frame_base%vs_cols;
-+ unsigned int frame_rows = p->par->cntr_rows*p->par->num_cntr;
-+ unsigned int frame_cols = p->par->cntr_cols;
-+
-+ if (vs_rows == frame_rows && vs_cols == frame_cols)
-+ return (iterator);
-+
-+ if (row < frame_base_row || row >= frame_base_row+frame_rows)
-+ return (-1);
-+ if (col < frame_base_col || col >= frame_base_col+frame_cols)
-+ return (-1);
-+
-+ return ((row-frame_base_row)*frame_cols+(col-frame_base_col));
-+}
-+
-+/* Given 'iterator' in vs, returns the offset in vs corresponding to the nearest
-+ * visible offset in vs, or returns 'iterator' if it is already visible.
-+ */
-+static unsigned int round_vs_(struct lcd_struct *p, unsigned int iterator)
-+{
-+ unsigned int vs_rows = p->par->vs_rows;
-+ unsigned int vs_cols = p->par->vs_cols;
-+ unsigned int row = iterator/vs_cols;
-+ unsigned int col = iterator%vs_cols;
-+ unsigned int frame_base_row = p->frame_base/vs_cols;
-+ unsigned int frame_base_col = p->frame_base%vs_cols;
-+ unsigned int frame_rows = p->par->cntr_rows*p->par->num_cntr;
-+ unsigned int frame_cols = p->par->cntr_cols;
-+
-+ if (vs_rows == frame_rows && vs_cols == frame_cols)
-+ return (iterator);
-+
-+ if (row < frame_base_row)
-+ row = frame_base_row;
-+ else if (row >= frame_base_row+frame_rows)
-+ row = frame_base_row+(frame_rows-1);
-+
-+ if (col < frame_base_col)
-+ col = frame_base_col;
-+ else if (col >= frame_base_col+frame_cols)
-+ col = frame_base_col+(frame_cols-1);
-+
-+ return ((row*vs_cols)+col);
-+}
-+
-+#define round_vs(p, iterator) (iterator = round_vs_(p, iterator))
-+
-+/*
-+ * Sync the frame area starting at offset s, ending at offset e with fb content.
-+ */
-+static void redraw_screen(struct lcd_struct *p, unsigned int s, unsigned int e)
-+{
-+ unsigned int len;
-+ unsigned int row = p->row, col = p->col;
-+ unsigned int inc_set = test_bit(INC_CURS_POS, &p->struct_flags);
-+ unsigned int frame_cols = p->par->cntr_cols;
-+ unsigned int vs_cols = p->par->vs_cols;
-+ unsigned long flags;
-+
-+ if (s >= p->fb_size || e >= p->fb_size || e < s || e < p->frame_base)
-+ return;
-+
-+ round_vs(p, s);
-+ round_vs(p, e);
-+
-+ len = 1+e-s;
-+
-+ if (! inc_set)
-+ s = e;
-+
-+ p->row = s/vs_cols;
-+ p->col = s%vs_cols;
-+
-+ flags = p->struct_flags;
-+ clear_bit(NEED_WRAP, &p->struct_flags);
-+ clear_bit(DECIM, &p->struct_flags);
-+ set_bit(DECAWM, &p->struct_flags);
-+ SET_INPUT_STATE(p, RAW);
-+ if (inc_set)
-+ while (len--)
-+ if (vs_to_frame_(p, (p->row*vs_cols)+p->col) < 0) {
-+ s += vs_cols-frame_cols;
-+ len -= vs_cols-frame_cols-1;
-+ p->row = s/vs_cols;
-+ p->col = s%vs_cols;
-+ } else {
-+ write_data(p, p->fb[s++]);
-+ if (test_bit(NEED_WRAP, &p->struct_flags)) {
-+ cr(p);
-+ lf(p);
-+ }
-+ }
-+ else
-+ while (len--)
-+ if (vs_to_frame_(p, (p->row*vs_cols)+p->col) < 0) {
-+ s -= vs_cols-frame_cols;
-+ len -= vs_cols-frame_cols-1;
-+ p->row = s/vs_cols;
-+ p->col = s%vs_cols;
-+ } else {
-+ write_data(p, p->fb[s--]);
-+ if (test_bit(NEED_WRAP, &p->struct_flags)) {
-+ cr(p);
-+ lf(p);
-+ }
-+ }
-+ p->struct_flags = flags;
-+
-+ p->row = row; p->col = col;
-+}
-+
-+static int show_cursor(struct lcd_struct *p)
-+{
-+ unsigned int vs_rows = p->par->vs_rows;
-+ unsigned int vs_cols = p->par->vs_cols;
-+ unsigned int frame_base, frame_base_row, frame_base_col;
-+ unsigned int frame_rows = p->par->cntr_rows*p->par->num_cntr;
-+ unsigned int frame_cols = p->par->cntr_cols;
-+ unsigned int tmp = frame_cols/2;
-+
-+ if (vs_rows == frame_rows && vs_cols == frame_cols)
-+ return (0);
-+
-+ if (test_bit(INC_CURS_POS, &p->struct_flags)) {
-+ /* cursor always on the lowest row of the display */
-+ frame_base_row = 0;
-+ frame_base_col = 0;
-+ if (p->row >= frame_rows)
-+ frame_base_row = p->row-(frame_rows-1);
-+ if (p->col >= frame_cols) {
-+ frame_base_col = p->col-(frame_cols-1);
-+ if (tmp) {
-+ tmp = (tmp-(frame_base_col%tmp))%tmp;
-+ if (frame_base_col+tmp <= vs_cols-frame_cols)
-+ frame_base_col += tmp;
-+ }
-+ }
-+ } else {
-+ /* cursor always on the uppermost row of the display */
-+ frame_base_row = vs_rows-frame_rows;
-+ frame_base_col = vs_cols-frame_cols;
-+ if (p->row < vs_rows-frame_rows)
-+ frame_base_row = p->row;
-+ if (p->col < vs_cols-frame_cols) {
-+ frame_base_col = p->col;
-+ if (tmp) {
-+ tmp = frame_base_col%tmp;
-+ if (frame_base_col >= tmp)
-+ frame_base_col -= tmp;
-+ }
-+ }
-+ }
-+
-+ frame_base = p->frame_base;
-+ p->frame_base = (frame_base_row*vs_cols)+frame_base_col;
-+
-+ return (frame_base != p->frame_base);
-+}
-+
-+/*
-+ * Move the visible screen area at user's wish
-+ */
-+static void browse_screen(struct lcd_struct *p, unsigned char dir)
-+{
-+ unsigned int vs_rows = p->par->vs_rows;
-+ unsigned int vs_cols = p->par->vs_cols;
-+ unsigned int frame_base_row = p->frame_base/vs_cols;
-+ unsigned int frame_base_col = p->frame_base%vs_cols;
-+ unsigned int frame_rows = p->par->cntr_rows*p->par->num_cntr;
-+ unsigned int frame_cols = p->par->cntr_cols;
-+
-+ switch (dir) {
-+ case '1': /* Up */
-+ if (! frame_base_row)
-+ return;
-+ --frame_base_row;
-+ break;
-+ case '2': /* Down */
-+ if (frame_base_row >= vs_rows-frame_rows)
-+ return;
-+ ++frame_base_row;
-+ break;
-+ case '3': /* Left */
-+ if (! frame_base_col)
-+ return;
-+ --frame_base_col;
-+ break;
-+ case '4': /* Right */
-+ if (frame_base_col >= vs_cols-frame_cols)
-+ return;
-+ ++frame_base_col;
-+ break;
-+ default:
-+ return;
-+ }
-+
-+ p->frame_base = (frame_base_row*vs_cols)+frame_base_col;
-+ redraw_screen(p, 0, p->fb_size-1);
-+}
-+
-+static inline void __memset_short(unsigned short *buf, unsigned short c, unsigned int len)
-+{
-+ while (len--)
-+ *buf++ = c;
-+}
-+
-+/*
-+ * A memset implementation writing to LCD instead of memory locations.
-+ */
-+static void lcd_memset(struct lcd_struct *p, unsigned int d, unsigned short c, unsigned int len)
-+{
-+ unsigned int inc_set = test_bit(INC_CURS_POS, &p->struct_flags);
-+
-+ if (! len || d >= p->fb_size)
-+ return;
-+
-+ if (inc_set && d+len > p->fb_size)
-+ len = p->fb_size-d;
-+ else if (! inc_set && len > d+1)
-+ len = d+1;
-+
-+ if (! inc_set)
-+ d -= len-1;
-+ __memset_short(p->fb+d, c, len);
-+
-+ if (show_cursor(p))
-+ redraw_screen(p, 0, p->fb_size-1);
-+ else
-+ redraw_screen(p, d, d+(len-1));
-+}
-+
-+static inline void __memcpy_short(unsigned short *d, unsigned short *s, unsigned int len, int dir)
-+{
-+ if (dir > 0)
-+ while (len--)
-+ *d++ = *s++;
-+ else
-+ while (len--)
-+ *d-- = *s--;
-+}
-+
-+/*
-+ * A memmove implementation writing to LCD instead of memory locations.
-+ * Copy is done in a non destructive way. Display regions may overlap.
-+ */
-+static void lcd_memmove(struct lcd_struct *p, unsigned int d, unsigned int s, unsigned int len)
-+{
-+ if (! len || d == s || d >= p->fb_size || s >= p->fb_size)
-+ return;
-+
-+ if (d < s) {
-+ if (test_bit(INC_CURS_POS, &p->struct_flags)) {
-+ if (s+len > p->fb_size)
-+ len = p->fb_size-s;
-+ } else {
-+ if (len > d+1)
-+ len = d+1;
-+ d -= len-1;
-+ s -= len-1;
-+ }
-+ __memcpy_short(p->fb+d, p->fb+s, len, 1);
-+ if (show_cursor(p))
-+ redraw_screen(p, 0, p->fb_size-1);
-+ else
-+ redraw_screen(p, d, d+(len-1));
-+ } else {
-+ if (test_bit(INC_CURS_POS, &p->struct_flags)) {
-+ if (d+len > p->fb_size)
-+ len = p->fb_size-d;
-+ d += len-1;
-+ s += len-1;
-+ } else {
-+ if (len > s+1)
-+ len = s+1;
-+ }
-+ __memcpy_short(p->fb+d, p->fb+s, len, -1);
-+ if (show_cursor(p))
-+ redraw_screen(p, 0, p->fb_size-1);
-+ else
-+ redraw_screen(p, d-(len-1), d);
-+ }
-+}
-+
-+static void scrup(struct lcd_struct *p, unsigned int t, unsigned int b, unsigned int nr)
-+{
-+ unsigned int vs_rows = p->par->vs_rows;
-+ unsigned int vs_cols = p->par->vs_cols;
-+ unsigned int d, s;
-+
-+ if (t+nr >= b)
-+ nr = b-t-1;
-+ if (b > vs_rows || t >= b || nr < 1)
-+ return;
-+ d = t*vs_cols;
-+ s = (t+nr)*vs_cols;
-+ if (test_bit(INC_CURS_POS, &p->struct_flags)) {
-+ lcd_memmove(p, d, s, (b-t-nr)*vs_cols);
-+ lcd_memset(p, d+(b-t-nr)*vs_cols, p->erase_char, nr*vs_cols);
-+ } else {
-+ lcd_memmove(p, d+(b-t-nr)*vs_cols-1, s+(b-t-nr)*vs_cols-1, (b-t-nr)*vs_cols);
-+ lcd_memset(p, d+(b-t)*vs_cols-1, p->erase_char, nr*vs_cols);
-+ }
-+}
-+
-+static void scrdown(struct lcd_struct *p, unsigned int t, unsigned int b, unsigned int nr)
-+{
-+ unsigned int vs_rows = p->par->vs_rows;
-+ unsigned int vs_cols = p->par->vs_cols;
-+ unsigned int d, s;
-+
-+ if (t+nr >= b)
-+ nr = b-t-1;
-+ if (b > vs_rows || t >= b || nr < 1)
-+ return;
-+ s = t*vs_cols;
-+ d = (t+nr)*vs_cols;
-+ if (test_bit(INC_CURS_POS, &p->struct_flags)) {
-+ lcd_memmove(p, d, s, (b-t-nr)*vs_cols);
-+ lcd_memset(p, s, p->erase_char, nr*vs_cols);
-+ } else {
-+ lcd_memmove(p, d+(b-t-nr)*vs_cols-1, s+(b-t-nr)*vs_cols-1, (b-t-nr)*vs_cols);
-+ lcd_memset(p, s+nr*vs_cols-1, p->erase_char, nr*vs_cols);
-+ }
-+}
-+
-+static void lcd_insert_char(struct lcd_struct *p, unsigned int nr)
-+{
-+ unsigned int vs_cols = p->par->vs_cols;
-+ unsigned int pos = (p->row*vs_cols)+p->col;
-+
-+ clear_bit(NEED_WRAP, &p->struct_flags);
-+ if (test_bit(INC_CURS_POS, &p->struct_flags))
-+ lcd_memmove(p, pos+nr, pos, vs_cols-p->col-nr);
-+ else
-+ lcd_memmove(p, pos-nr, pos, p->col-(nr-1));
-+ lcd_memset(p, pos, p->erase_char, nr);
-+}
-+
-+static void lcd_delete_char(struct lcd_struct *p, unsigned int nr)
-+{
-+ unsigned int vs_cols = p->par->vs_cols;
-+ unsigned int pos = (p->row*vs_cols)+p->col;
-+
-+ clear_bit(NEED_WRAP, &p->struct_flags);
-+ if (test_bit(INC_CURS_POS, &p->struct_flags)) {
-+ lcd_memmove(p, pos, pos+nr, vs_cols-(p->col+nr));
-+ lcd_memset(p, (p->row+1)*vs_cols-nr, p->erase_char, nr);
-+ } else {
-+ lcd_memmove(p, pos, pos-nr, p->col-(nr-1));
-+ lcd_memset(p, (p->row*vs_cols)+(nr-1), p->erase_char, nr);
-+ }
-+}
-+
-+
-+
-+
-+
-+/******************************************************************************
-+ ************************* VT 102 Emulation *************************
-+ ******************************************************************************/
-+
-+/**********************
-+ * Control characters *
-+ **********************/
-+static void bs(struct lcd_struct *p)
-+{
-+ clear_bit(NEED_WRAP, &p->struct_flags);
-+ if (test_bit(INC_CURS_POS, &p->struct_flags)) {
-+ if (p->col)
-+ --p->col;
-+ } else {
-+ if (p->col+1 < p->par->vs_cols)
-+ ++p->col;
-+ }
-+}
-+
-+static void cr(struct lcd_struct *p)
-+{
-+ clear_bit(NEED_WRAP, &p->struct_flags);
-+ p->col = (test_bit(INC_CURS_POS, &p->struct_flags) ? 0 : p->par->vs_cols-1);
-+}
-+
-+static void lf(struct lcd_struct *p)
-+{
-+ clear_bit(NEED_WRAP, &p->struct_flags);
-+ if (test_bit(INC_CURS_POS, &p->struct_flags)) {
-+ if (p->row+1 < p->bot)
-+ ++p->row;
-+ else if (INPUT_STATE(p) != RAW) {
-+ show_cursor(p);
-+ scrup(p, p->top, p->bot, 1);
-+ }
-+ } else {
-+ if (p->row > p->top)
-+ --p->row;
-+ else if (INPUT_STATE(p) != RAW) {
-+ show_cursor(p);
-+ scrdown(p, p->top, p->bot, 1);
-+ }
-+ }
-+}
-+
-+static void ri(struct lcd_struct *p)
-+{
-+ clear_bit(NEED_WRAP, &p->struct_flags);
-+ if (test_bit(INC_CURS_POS, &p->struct_flags)) {
-+ if (p->row > p->top)
-+ --p->row;
-+ else {
-+ show_cursor(p);
-+ scrdown(p, p->top, p->bot, 1);
-+ }
-+ } else {
-+ if (p->row+1 < p->bot)
-+ ++p->row;
-+ else {
-+ show_cursor(p);
-+ scrup(p, p->top, p->bot, 1);
-+ }
-+ }
-+}
-+
-+static void ff(struct lcd_struct *p)
-+{
-+ unsigned int vs_rows = p->par->vs_rows;
-+ unsigned int vs_cols = p->par->vs_cols;
-+
-+ clear_bit(NEED_WRAP, &p->struct_flags);
-+ if (p->driver->clear_display) {
-+ p->driver->clear_display();
-+ __memset_short(p->fb, p->erase_char, p->fb_size);
-+ __memset_short(p->display, p->erase_char, p->frame_size);
-+ p->frame_base = 0;
-+ } else if (test_bit(INC_CURS_POS, &p->struct_flags))
-+ lcd_memset(p, 0, p->erase_char, p->fb_size);
-+ else
-+ lcd_memset(p, p->fb_size-1, p->erase_char, p->fb_size);
-+
-+ if (test_bit(INC_CURS_POS, &p->struct_flags))
-+ p->row = p->col = 0;
-+ else {
-+ p->row = vs_rows-1;
-+ p->col = vs_cols-1;
-+ }
-+}
-+
-+static void tab(struct lcd_struct *p)
-+{
-+ struct lcd_parameters *par = p->par;
-+ unsigned int i, vs_cols = par->vs_cols;
-+
-+ clear_bit(NEED_WRAP, &p->struct_flags);
-+
-+ if (! par->tabstop)
-+ return;
-+
-+ if (test_bit(INC_CURS_POS, &p->struct_flags)) {
-+ i = par->tabstop-(p->col%par->tabstop);
-+ if (p->col+i < vs_cols)
-+ p->col += i;
-+ } else {
-+ i = p->col%par->tabstop;
-+ i = (i == 0 ? par->tabstop : i);
-+ if (p->col >= i)
-+ p->col -= i;
-+ }
-+}
-+
-+/*
-+ * Control character handler.
-+ */
-+static void control_char(struct lcd_struct *p, unsigned char val)
-+{
-+ switch (val) {
-+ case 0x08: /* BS: Back Space (^H) */
-+ case 0x7f: /* DEL: Delete */
-+ bs(p);
-+ return;
-+
-+ case 0x09: /* HT: Horizontal Tab (^I) */
-+ tab(p);
-+ return;
-+
-+ case 0x0c: /* FF: Form Feed (^L) */
-+ ff(p);
-+ return;
-+
-+ case 0x0a: /* LF: Line Feed (^J) */
-+ case 0x0b: /* VT: Vertical Tab (^K) */
-+ lf(p);
-+ if (! test_bit(CRLF, &p->struct_flags))
-+ return;
-+
-+ case 0x0d: /* CR: Carriage Return (^M) */
-+ cr(p);
-+ return;
-+
-+ case 0x16: /* SYN: Synchronous Idle (^V) */
-+ SET_INPUT_STATE(p, SYN);
-+ return;
-+
-+ case 0x1b: /* ESC: Start of escape sequence */
-+ SET_INPUT_STATE(p, ESC);
-+ return;
-+
-+ case 0x9b: /* CSI: Start of CSI escape sequence */
-+ memset(p->csi_args, 0, sizeof(p->csi_args));
-+ p->index = 0;
-+ SET_INPUT_STATE(p, CSI);
-+ return;
-+ }
-+}
-+
-+static void gotoxy(struct lcd_struct *p, int new_col, int new_row)
-+{
-+ unsigned int vs_rows = p->par->vs_rows;
-+ unsigned int vs_cols = p->par->vs_cols;
-+ int min_row, max_row;
-+
-+ clear_bit(NEED_WRAP, &p->struct_flags);
-+ if (test_bit(DECOM, &p->struct_flags)) {
-+ min_row = p->top;
-+ max_row = p->bot;
-+ } else {
-+ min_row = 0;
-+ max_row = vs_rows;
-+ }
-+
-+ if (new_row < min_row)
-+ p->row = min_row;
-+ else if (new_row >= max_row)
-+ p->row = max_row-1;
-+ else
-+ p->row = new_row;
-+
-+ if (new_col < 0)
-+ p->col = 0;
-+ else if (new_col >= vs_cols)
-+ p->col = vs_cols-1;
-+ else
-+ p->col = new_col;
-+
-+ if (show_cursor(p))
-+ redraw_screen(p, 0, p->fb_size-1);
-+}
-+
-+static void gotoxay(struct lcd_struct *p, int new_col, int new_row)
-+{
-+ gotoxy(p, new_col, test_bit(DECOM, &p->struct_flags) ? (p->top+new_row) : new_row);
-+}
-+
-+
-+/******************************
-+ * ECMA-48 CSI ESC- sequences *
-+ ******************************/
-+static void csi_at(struct lcd_struct *p, unsigned int nr)
-+{
-+ unsigned int vs_cols = p->par->vs_cols;
-+
-+ if (p->col+nr > vs_cols)
-+ nr = vs_cols-p->col;
-+ else if (! nr)
-+ ++nr;
-+ lcd_insert_char(p, nr);
-+}
-+
-+static void csi_J(struct lcd_struct *p, unsigned int action)
-+{
-+ unsigned int vs_cols = p->par->vs_cols;
-+ unsigned int pos = (p->row*vs_cols)+p->col;
-+
-+ clear_bit(NEED_WRAP, &p->struct_flags);
-+ switch (action) {
-+ case 0: /* From cursor to end of display */
-+ lcd_memset(p, pos, p->erase_char, p->fb_size-pos);
-+ return;
-+
-+ case 1: /* From start of display to cursor */
-+ lcd_memset(p, 0, p->erase_char, pos+1);
-+ return;
-+
-+ case 2: /* Whole display */
-+ lcd_memset(p, 0, p->erase_char, p->fb_size);
-+ return;
-+ }
-+}
-+
-+static void csi_K(struct lcd_struct *p, unsigned int action)
-+{
-+ unsigned int vs_cols = p->par->vs_cols;
-+ unsigned int row_start = p->row*vs_cols;
-+
-+ clear_bit(NEED_WRAP, &p->struct_flags);
-+ switch (action) {
-+ case 0: /* From cursor to end of line */
-+ lcd_memset(p, row_start+p->col, p->erase_char, vs_cols-p->col);
-+ return;
-+
-+ case 1: /* From start of line to cursor */
-+ lcd_memset(p, row_start, p->erase_char, p->col+1);
-+ return;
-+
-+ case 2: /* Whole line */
-+ lcd_memset(p, row_start, p->erase_char, vs_cols);
-+ return;
-+ }
-+}
-+
-+static void csi_L(struct lcd_struct *p, unsigned int nr)
-+{
-+ unsigned int vs_rows = p->par->vs_rows;
-+ unsigned int vs_cols = p->par->vs_cols;
-+
-+ clear_bit(NEED_WRAP, &p->struct_flags);
-+ if (p->row+nr > vs_rows)
-+ nr = vs_rows-p->row;
-+ else if (! nr)
-+ ++nr;;
-+ lcd_memmove(p, (p->row+nr)*vs_cols, p->row*vs_cols, (vs_rows-p->row-nr)*vs_cols);
-+ lcd_memset(p, p->row*vs_cols, p->erase_char, nr*vs_cols);
-+}
-+
-+static void csi_M(struct lcd_struct *p, unsigned int nr)
-+{
-+ unsigned int vs_rows = p->par->vs_rows;
-+ unsigned int vs_cols = p->par->vs_cols;
-+
-+ clear_bit(NEED_WRAP, &p->struct_flags);
-+ if (p->row+nr > vs_rows)
-+ nr = vs_rows-p->row;
-+ else if (! nr)
-+ ++nr;;
-+ lcd_memmove(p, p->row*vs_cols, (p->row+nr)*vs_cols, (vs_rows-p->row-nr)*vs_cols);
-+ lcd_memset(p, (vs_rows-nr)*vs_cols, p->erase_char, nr*vs_cols);
-+}
-+
-+static void csi_P(struct lcd_struct *p, unsigned int nr)
-+{
-+ unsigned int vs_cols = p->par->vs_cols;
-+
-+ if (p->col+nr > vs_cols)
-+ nr = vs_cols-p->col;
-+ else if (! nr)
-+ ++nr;
-+ lcd_delete_char(p, nr);
-+}
-+
-+static void csi_X(struct lcd_struct *p, unsigned int nr)
-+{
-+ unsigned int vs_cols = p->par->vs_cols;
-+
-+ clear_bit(NEED_WRAP, &p->struct_flags);
-+ if (p->col+nr > vs_cols)
-+ nr = vs_cols-p->col;
-+ else if (! nr)
-+ ++nr;
-+ lcd_memset(p, (p->row*vs_cols)+p->col, p->erase_char, nr);
-+}
-+
-+static void csi_su(struct lcd_struct *p, unsigned char input)
-+{
-+ unsigned int vs_cols = p->par->vs_cols;
-+
-+ clear_bit(NEED_WRAP, &p->struct_flags);
-+ if (input == 'u') {
-+ p->row = p->s_offset/vs_cols;
-+ p->col = p->s_offset%vs_cols;
-+ p->color = p->s_color;
-+ p->attributes = p->s_attributes;
-+ return;
-+ }
-+ p->s_offset = (p->row*vs_cols)+p->col;
-+ p->s_color = p->color;
-+ p->s_attributes = p->attributes;
-+}
-+
-+static inline unsigned char reverse_color_attr(unsigned char attr)
-+{
-+ return ((attr & (BG_BRIGHT | FG_BRIGHT)) | ((attr & BG_COLOR) >> 4) | ((attr & FG_COLOR) << 4));
-+}
-+
-+static unsigned char build_attr(struct lcd_struct *p, unsigned char color, unsigned char intensity,
-+ unsigned char blink, unsigned char underline, unsigned char reverse)
-+{
-+ unsigned char attr;
-+
-+ if (test_bit(CAN_DO_COLOR, &p->struct_flags)) {
-+ attr = color;
-+ if (underline)
-+ attr = (attr & BG_MASK) | p->ulcolor;
-+ else if (intensity == 0)
-+ attr = (attr & BG_MASK) | p->halfcolor;
-+ if (reverse)
-+ attr = reverse_color_attr(attr);
-+ if (blink)
-+ attr ^= BG_BRIGHT;
-+ if (intensity == 2)
-+ attr ^= FG_BRIGHT;
-+ } else {
-+ attr = intensity;
-+ attr |= (underline ? ULINE : 0x00);
-+ attr |= (reverse ? REVERSE : 0x00);
-+ attr |= (blink ? BLINK : 0x00);
-+ }
-+
-+ return (attr);
-+}
-+
-+static void update_attr(struct lcd_struct *p)
-+{
-+ unsigned char intensity = p->attributes & I_MASK;
-+ unsigned char underline = (p->attributes & ULINE) ? 0x01 : 0x00;
-+ unsigned char reverse = (p->attributes & REVERSE) ? 0x01 : 0x00;
-+ unsigned char blink = (p->attributes & BLINK) ? 0x01 : 0x00;
-+ unsigned char decscnm = test_bit(DECSCNM, &p->struct_flags) ? 0x01 : 0x00;
-+
-+ p->attr = build_attr(p, p->color, intensity, blink, underline, reverse ^ decscnm);
-+ p->erase_char = (build_attr(p, p->color, 1, blink, 0, decscnm) << 8) | ' ';
-+}
-+
-+static void default_attr(struct lcd_struct *p)
-+{
-+ p->attributes = 0x01;
-+ p->color = p->defcolor;
-+}
-+
-+static void lcd_invert_screen(struct lcd_struct *p, unsigned int s, unsigned int len)
-+{
-+ unsigned int l, inc_set = test_bit(INC_CURS_POS, &p->struct_flags);
-+
-+ if (! len || s >= p->fb_size)
-+ return;
-+ if (inc_set && s+len > p->fb_size)
-+ len = p->fb_size-s;
-+ else if (! inc_set && len > s+1)
-+ len = s+1;
-+
-+ l = len;
-+ if (test_bit(CAN_DO_COLOR, &p->struct_flags))
-+ while (l--) {
-+ p->fb[s] = (reverse_color_attr(p->fb[s] >> 8) << 8) | (p->fb[s] & 0xff);
-+ ++s;
-+ }
-+ else
-+ while (l--) {
-+ p->fb[s] ^= REVERSE << 8;
-+ ++s;
-+ }
-+
-+ if (show_cursor(p))
-+ redraw_screen(p, 0, p->fb_size-1);
-+ else
-+ redraw_screen(p, s, s+(len-1));
-+}
-+
-+static void csi_m(struct lcd_struct *p, unsigned int n)
-+{
-+ int i, arg;
-+
-+ for (i = 0; i <= n; ++i)
-+ switch ((arg = p->csi_args[i]))
-+ {
-+ case 0:
-+ default_attr(p);
-+ break;
-+
-+ case 1:
-+ p->attributes = (p->attributes & ~I_MASK) | 2;
-+ break;
-+
-+ case 2:
-+ p->attributes = (p->attributes & ~I_MASK) | 0;
-+ break;
-+
-+ case 4:
-+ p->attributes |= ULINE;
-+ break;
-+
-+ case 5:
-+ p->attributes |= BLINK;
-+ break;
-+
-+ case 7:
-+ p->attributes |= REVERSE;
-+ break;
-+
-+ case 21: case 22:
-+ p->attributes = (p->attributes & ~I_MASK) | 1;
-+ break;
-+
-+ case 24:
-+ p->attributes &= ~ULINE;
-+ break;
-+
-+ case 25:
-+ p->attributes &= ~BLINK;
-+ break;
-+
-+ case 27:
-+ p->attributes &= ~REVERSE;
-+ break;
-+
-+ case 38:
-+ p->attributes |= ULINE;
-+ p->color = (p->color & BG_MASK) | (p->defcolor & FG_MASK);
-+ break;
-+
-+ case 39:
-+ p->attributes &= ~ULINE;
-+ p->color = (p->color & BG_MASK) | (p->defcolor & FG_MASK);
-+ break;
-+
-+ case 49:
-+ p->color = (p->defcolor & BG_MASK) | (p->color & FG_MASK);
-+ break;
-+
-+ default:
-+ if (arg >= 30 && arg <= 37)
-+ p->color = (p->color & BG_MASK) | color_table[arg-30];
-+ else if (arg >= 40 && arg <= 47)
-+ p->color = (p->color & FG_MASK) | (color_table[arg-40] << 4);
-+ break;
-+ }
-+
-+ update_attr(p);
-+}
-+
-+static void csi_h(struct lcd_struct *p, unsigned char n)
-+{
-+ switch (n) {
-+ case 4: /* Set insert mode */
-+ set_bit(DECIM, &p->struct_flags);
-+ return;
-+
-+ case 5: /* Inverted screen mode */
-+ if (test_bit(QUES, &p->struct_flags) && ! test_bit(DECSCNM, &p->struct_flags)) {
-+ lcd_invert_screen(p, 0, p->fb_size);
-+ set_bit(DECSCNM, &p->struct_flags);
-+ update_attr(p);
-+ }
-+ return;
-+
-+ case 6: /* Cursor addressing origin: relative to scrolling region */
-+ if (test_bit(QUES, &p->struct_flags)) {
-+ set_bit(DECOM, &p->struct_flags);
-+ gotoxay(p, 0, 0);
-+ }
-+ return;
-+
-+ case 7: /* Set autowrap */
-+ if (test_bit(QUES, &p->struct_flags))
-+ set_bit(DECAWM, &p->struct_flags);
-+ return;
-+
-+ case 20: /* Set cr lf */
-+ set_bit(CRLF, &p->struct_flags);
-+ return;
-+ }
-+}
-+
-+static void csi_l(struct lcd_struct *p, unsigned char n)
-+{
-+ switch (n) {
-+ case 4: /* Reset insert mode */
-+ clear_bit(DECIM, &p->struct_flags);
-+ return;
-+
-+ case 5: /* Normal screen mode */
-+ if (test_bit(QUES, &p->struct_flags) && test_bit(DECSCNM, &p->struct_flags)) {
-+ lcd_invert_screen(p, 0, p->fb_size);
-+ clear_bit(DECSCNM, &p->struct_flags);
-+ update_attr(p);
-+ }
-+ return;
-+
-+ case 6: /* Cursor addressing origin: absolute origin */
-+ if (test_bit(QUES, &p->struct_flags)) {
-+ clear_bit(DECOM, &p->struct_flags);
-+ gotoxay(p, 0, 0);
-+ }
-+ return;
-+
-+ case 7: /* Reset autowrap */
-+ if (test_bit(QUES, &p->struct_flags))
-+ clear_bit(DECAWM, &p->struct_flags);
-+ return;
-+
-+ case 20: /* Reset cr lf */
-+ clear_bit(CRLF, &p->struct_flags);
-+ return;
-+ }
-+}
-+
-+static void csi_linux(struct lcd_struct *p)
-+{
-+ switch (p->csi_args[0]) {
-+ case 1:
-+ if (test_bit(CAN_DO_COLOR, &p->struct_flags) && p->csi_args[1] < 16) {
-+ p->ulcolor = color_table[p->csi_args[1]];
-+ if (p->attributes & ULINE)
-+ update_attr(p);
-+ }
-+ return;
-+
-+ case 2:
-+ if (test_bit(CAN_DO_COLOR, &p->struct_flags) && p->csi_args[1] < 16) {
-+ p->halfcolor = color_table[p->csi_args[1]];
-+ if ((p->attributes & I_MASK) == 0)
-+ update_attr(p);
-+ }
-+ return;
-+
-+ case 8:
-+ p->defcolor = p->color;
-+ default_attr(p);
-+ update_attr(p);
-+ return;
-+ }
-+}
-+
-+static void csi_r(struct lcd_struct *p, unsigned int top, unsigned int bot)
-+{
-+ /* Minimum allowed region is 2 lines */
-+ if (top < bot) {
-+ p->top = top-1;
-+ p->bot = bot;
-+ gotoxay(p, 0, 0);
-+ }
-+}
-+
-+/*
-+ * ECMA-48 CSI ESC- sequence handler.
-+ */
-+static void handle_csi(struct lcd_struct *p, unsigned char input)
-+{
-+ if (p->index >= NPAR) {
-+ SET_INPUT_STATE(p, NORMAL);
-+ printk(KERN_NOTICE "LCD: too many parameters in CSI escape sequence\n");
-+ } else if (input == '?') {
-+ set_bit(QUES, &p->struct_flags);
-+ } else if (input == ';') {
-+ ++p->index;
-+ } else if (input >= '0' && input <= '9') {
-+ p->csi_args[p->index] = (p->csi_args[p->index]*10)+(input-'0');
-+ } else {
-+ SET_INPUT_STATE(p, NORMAL);
-+ if (! test_bit(INC_CURS_POS, &p->struct_flags))
-+ return;
-+ switch (input) {
-+ case 'h': /* DECSET sequences and mode switches */
-+ csi_h(p, p->csi_args[0]);
-+ clear_bit(QUES, &p->struct_flags);
-+ return;
-+
-+ case 'l': /* DECRST sequences and mode switches */
-+ csi_l(p, p->csi_args[0]);
-+ clear_bit(QUES, &p->struct_flags);
-+ return;
-+ }
-+ clear_bit(QUES, &p->struct_flags);
-+ switch (input) {
-+ case '@': /* Insert # Blank character */
-+ csi_at(p, p->csi_args[0]);
-+ return;
-+
-+ case 'G': case '`': /* Cursor to indicated column in current row */
-+ if (p->csi_args[0])
-+ --p->csi_args[0];
-+ gotoxy(p, p->csi_args[0], p->row);
-+ return;
-+
-+ case 'A': /* Cursor # rows Up */
-+ if (! p->csi_args[0])
-+ ++p->csi_args[0];
-+ gotoxy(p, p->col, p->row-p->csi_args[0]);
-+ return;
-+
-+ case 'B': case 'e': /* Cursor # rows Down */
-+ if (! p->csi_args[0])
-+ ++p->csi_args[0];
-+ gotoxy(p, p->col, p->row+p->csi_args[0]);
-+ return;
-+
-+ case 'C': case 'a': /* Cursor # columns Right */
-+ if (! p->csi_args[0])
-+ ++p->csi_args[0];
-+ gotoxy(p, p->col+p->csi_args[0], p->row);
-+ return;
-+
-+ case 'D': /* Cursor # columns Left */
-+ if (! p->csi_args[0])
-+ ++p->csi_args[0];
-+ gotoxy(p, p->col-p->csi_args[0], p->row);
-+ return;
-+
-+ case 'E': /* Cursor # rows Down, column 1 */
-+ if (! p->csi_args[0])
-+ ++p->csi_args[0];
-+ gotoxy(p, 0, p->row+p->csi_args[0]);
-+ return;
-+
-+ case 'F': /* Cursor # rows Up, column 1 */
-+ if (! p->csi_args[0])
-+ ++p->csi_args[0];
-+ gotoxy(p, 0, p->row-p->csi_args[0]);
-+ return;
-+
-+ case 'd': /* Cursor to indicated row in current column */
-+ if (p->csi_args[0])
-+ --p->csi_args[0];
-+ gotoxay(p, p->col, p->csi_args[0]);
-+ return;
-+
-+ case 'H': case 'f': /* Cursor to indicated row, column (origin 1, 1) */
-+ if (p->csi_args[0])
-+ --p->csi_args[0];
-+ if (p->csi_args[1])
-+ --p->csi_args[1];
-+ gotoxay(p, p->csi_args[1], p->csi_args[0]);
-+ return;
-+
-+ case 'J': /* Erase display */
-+ csi_J(p, p->csi_args[0]);
-+ return;
-+
-+ case 'K': /* Erase line */
-+ csi_K(p, p->csi_args[0]);
-+ return;
-+
-+ case 'L': /* Insert # blank lines */
-+ csi_L(p, p->csi_args[0]);
-+ return;
-+
-+ case 'M': /* Delete # blank lines */
-+ csi_M(p, p->csi_args[0]);
-+ return;
-+
-+ case 'P': /* Delete # characters on the current line */
-+ csi_P(p, p->csi_args[0]);
-+ return;
-+
-+ case 'X': /* Erase # characters on the current line */
-+ csi_X(p, p->csi_args[0]);
-+ return;
-+
-+ case 'm': /* Set video attributes */
-+ csi_m(p, p->index);
-+ return;
-+
-+ case 's': /* Save cursor position */
-+ case 'u': /* Restore cursor position */
-+ csi_su(p, input);
-+ return;
-+
-+ case ']': /* Linux private ESC [ ] sequence */
-+ csi_linux(p);
-+ return;
-+
-+ case 'r': /* Set the scrolling region */
-+ if (! p->csi_args[0])
-+ ++p->csi_args[0];
-+ if (! p->csi_args[1] || p->csi_args[1] > p->par->vs_rows)
-+ p->csi_args[1] = p->par->vs_rows;
-+ csi_r(p, p->csi_args[0], p->csi_args[1]);
-+ return;
-+
-+ /* Ignored escape sequences */
-+ case 'c':
-+ case 'g':
-+ case 'n':
-+ case 'q':
-+ return;
-+
-+ default:
-+ printk(KERN_NOTICE "LCD: unrecognized CSI escape sequence: ESC [ %u\n", input);
-+ return;
-+ }
-+ }
-+}
-+
-+/*
-+ * Custom ESC- sequence handler.
-+ */
-+static int handle_custom_esc(struct lcd_struct *p, unsigned int _input)
-+{
-+ unsigned char input = _input & 0xff;
-+ struct lcd_parameters *par = p->par;
-+
-+ if (_input & (~0xff)) {
-+ switch (ESC_STATE(p)) {
-+ case 's':
-+ if (p->index++) {
-+ unsigned char *cgbuf = p->cgram_buffer-par->cgram_bytes;
-+
-+ cgbuf[p->index-2] = input;
-+ if (p->index == par->cgram_bytes+1)
-+ write_cgram(p, p->cgram_index, cgbuf);
-+ } else {
-+ if (! p->driver->write_cgram_char) {
-+ printk(KERN_ERR "LCD: %s: missing function to write to CGRAM\n", p->par->name);
-+ return (-1);
-+ }
-+ if (input >= par->cgram_char0 && input < par->cgram_char0+par->cgram_chars)
-+ p->cgram_index = input;
-+ else {
-+ printk(KERN_NOTICE "LCD: bad CGRAM index\n");
-+ return (-1);
-+ }
-+ }
-+ return (0);
-+
-+ case 'G':
-+ if (input >= par->cgram_char0 && input < par->cgram_char0+par->cgram_chars)
-+ write_data(p, (p->attr << 8) | p->driver->charmap[input]);
-+ else {
-+ SET_INPUT_STATE(p, NORMAL);
-+ handle_input(p, (p->attr << 8) | input);
-+ }
-+ return (0);
-+
-+ case 'r':
-+ if (input == '1')
-+ address_mode(p, -1);
-+ else if (input == '0')
-+ address_mode(p, 1);
-+ return (0);
-+
-+ case 'A':
-+ scrup(p, p->top, p->bot, input);
-+ return (0);
-+
-+ case 'B':
-+ scrdown(p, p->top, p->bot, input);
-+ return (0);
-+
-+ case 'C':
-+ browse_screen(p, input);
-+ return (0);
-+ }
-+ }
-+
-+ /* These are the custom ESC- sequences */
-+ switch (input) {
-+ case 's': /* CGRAM select */
-+ if (p->cgram_buffer) {
-+ SET_ESC_STATE(p, input);
-+ p->index = 0;
-+ return (par->cgram_bytes+1);
-+ } else {
-+ printk(KERN_NOTICE "LCD: driver %s does not support CGRAM chars\n", par->name);
-+ return (0);
-+ }
-+
-+ case 'A': /* Scroll up */
-+ case 'B': /* Scroll down */
-+ case 'C': /* Browse screen */
-+ case 'G': /* Enter cgram mode */
-+ case 'r': /* Decrement counter after data read/write */
-+ SET_ESC_STATE(p, input);
-+ return (1);
-+ }
-+
-+ return (-1);
-+}
-+
-+/*
-+ * ESC- but not CSI sequence handler.
-+ */
-+static int handle_esc(struct lcd_struct *p, unsigned char input)
-+{
-+ int ret;
-+
-+ SET_INPUT_STATE(p, NORMAL);
-+ switch (input) {
-+ case 'c': /* Reset */
-+ set_bit(DECAWM, &p->struct_flags);
-+ set_bit(INC_CURS_POS, &p->struct_flags);
-+ ff(p);
-+ return (0);
-+
-+ case 'D': /* Line Feed */
-+ lf(p);
-+ return (0);
-+
-+ case 'E': /* New Line */
-+ cr(p);
-+ lf(p);
-+ return (0);
-+
-+ case 'M': /* Reverse Line Feed */
-+ ri(p);
-+ return (0);
-+
-+ case '7':
-+ case '8':
-+ csi_su(p, (input == '7' ? 's' : 'u'));
-+ return (0);
-+
-+ /* CSI: Start of CSI escape sequence */
-+ case '[':
-+ memset(p->csi_args, 0, sizeof(p->csi_args));
-+ p->index = 0;
-+ SET_INPUT_STATE(p, CSI);
-+ return (0);
-+
-+ /* Ignored escape sequences */
-+ case '(':
-+ SET_INPUT_STATE(p, ESC_G0);
-+ return (1);
-+
-+ case ')':
-+ SET_INPUT_STATE(p, ESC_G1);
-+ return (1);
-+
-+ case '#':
-+ SET_INPUT_STATE(p, ESC_HASH);
-+ return (1);
-+
-+ case '%':
-+ SET_INPUT_STATE(p, ESC_PERCENT);
-+ return (1);
-+
-+ case 'H':
-+ case 'Z':
-+ case '>':
-+ case '=':
-+ case ']':
-+ return (0);
-+ }
-+
-+ /* These are the custom ESC- sequences */
-+ if ((ret = handle_custom_esc(p, input)) > 0) {
-+ SET_INPUT_STATE(p, ARG);
-+ return (ret);
-+ }
-+
-+ if (ret < 0 && p->driver->handle_custom_char)
-+ if ((ret = p->driver->handle_custom_char(input)) > 0) {
-+ SET_INPUT_STATE(p, ARG_DRIVER);
-+ return (ret);
-+ }
-+
-+ if (ret < 0)
-+ printk(KERN_NOTICE "LCD: unrecognized escape sequence: ESC %u\n", input);
-+
-+ return (0);
-+}
-+
-+/*
-+ * Main input handler.
-+ */
-+static void handle_input(struct lcd_struct *p, unsigned short _input)
-+{
-+ unsigned char input = _input & 0xff;
-+ struct lcd_driver *driver = p->driver;
-+
-+ switch (INPUT_STATE(p)) {
-+ case NORMAL:
-+ if (input < 0x20 || input == 0x9b)
-+ control_char(p, input);
-+ else
-+ write_data(p, (_input & 0xff00) | driver->charmap[input]);
-+ return;
-+
-+ case RAW:
-+ write_data(p, (_input & 0xff00) | driver->charmap[input]);
-+ return;
-+
-+ case SYN:
-+ write_data(p, _input);
-+ SET_INPUT_STATE(p, NORMAL);
-+ return;
-+
-+ case ESC:
-+ p->esc_args = handle_esc(p, input);
-+ return;
-+
-+ case ESC_G0:
-+ case ESC_G1:
-+ case ESC_HASH:
-+ case ESC_PERCENT:
-+ if (! --p->esc_args)
-+ SET_INPUT_STATE(p, NORMAL);
-+ return;
-+
-+ case CSI:
-+ handle_csi(p, input);
-+ return;
-+
-+ case ARG:
-+ if (handle_custom_esc(p, 0x100 | input) || ! --p->esc_args)
-+ SET_INPUT_STATE(p, NORMAL);
-+ return;
-+
-+ case ARG_DRIVER:
-+ if (driver->handle_custom_char(0x100 | input) || ! --p->esc_args)
-+ SET_INPUT_STATE(p, NORMAL);
-+ return;
-+ }
-+}
-+
-+
-+
-+
-+
-+/***************************************
-+ * Read from/Write to display routines *
-+ ***************************************/
-+
-+/*
-+ * Write character data to the display.
-+ */
-+static void write_data(struct lcd_struct *p, unsigned short data)
-+{
-+ unsigned int vs_cols = p->par->vs_cols;
-+ unsigned int pos;
-+ int frame_pos;
-+
-+ if (test_bit(NEED_WRAP, &p->struct_flags)) {
-+ cr(p);
-+ lf(p);
-+ }
-+
-+ if (test_bit(DECIM, &p->struct_flags))
-+ lcd_insert_char(p, 1);
-+
-+ pos = (p->row*vs_cols)+p->col;
-+ if ((frame_pos = vs_to_frame_(p, pos)) < 0) {
-+ show_cursor(p);
-+ redraw_screen(p, 0, p->fb_size-1);
-+ frame_pos = vs_to_frame_(p, pos);
-+ }
-+
-+ if (p->display[frame_pos] != data) {
-+ p->driver->write_char(frame_pos, data);
-+ p->display[frame_pos] = data;
-+ }
-+
-+ p->fb[pos] = data;
-+
-+ if (test_bit(INC_CURS_POS, &p->struct_flags)) {
-+ if (p->col+1 < vs_cols)
-+ iterator_inc(p->col, vs_cols);
-+ else if (test_bit(DECAWM, &p->struct_flags))
-+ set_bit(NEED_WRAP, &p->struct_flags);
-+ } else {
-+ if (p->col)
-+ iterator_dec(p->col, vs_cols);
-+ else if (test_bit(DECAWM, &p->struct_flags))
-+ set_bit(NEED_WRAP, &p->struct_flags);
-+ }
-+}
-+
-+/*
-+ * Write an entire CGRAM character to the display.
-+ */
-+static void write_cgram(struct lcd_struct *p, unsigned char index, unsigned char *pixels)
-+{
-+ struct lcd_parameters *par = p->par;
-+ unsigned int inc_set = test_bit(INC_CURS_POS, &p->struct_flags);
-+ unsigned char *cgbuf = p->cgram_buffer+(index-par->cgram_char0)*par->cgram_bytes;
-+
-+ if (! strncmp(cgbuf, pixels, par->cgram_bytes))
-+ return;
-+
-+ if (! inc_set)
-+ address_mode(p, 1);
-+
-+ p->driver->write_cgram_char(index, pixels);
-+ memcpy(cgbuf, pixels, par->cgram_bytes);
-+
-+ if (! inc_set)
-+ address_mode(p, -1);
-+}
-+
-+/*
-+ * Read character data from the display.
-+ */
-+static void read_data(struct lcd_struct *p, unsigned short *data)
-+{
-+ unsigned int vs_rows = p->par->vs_rows;
-+ unsigned int vs_cols = p->par->vs_cols;
-+ unsigned int pos = (p->row*vs_cols)+p->col;
-+ int frame_pos;
-+
-+ if ((frame_pos = vs_to_frame_(p, pos)) < 0) {
-+ show_cursor(p);
-+ redraw_screen(p, 0, p->fb_size-1);
-+ frame_pos = vs_to_frame_(p, pos);
-+ }
-+
-+ if (p->driver->read_char)
-+ p->driver->read_char(frame_pos, data);
-+ else
-+ *data = p->fb[pos];
-+
-+ if (test_bit(INC_CURS_POS, &p->struct_flags)) {
-+ iterator_inc(p->col, vs_cols);
-+ if (! p->col) {
-+ if (p->row+1 < vs_rows)
-+ ++p->row;
-+ }
-+ } else {
-+ iterator_dec(p->col, vs_cols);
-+ if (p->col+1 == vs_cols) {
-+ if (p->row)
-+ --p->row;
-+ }
-+ }
-+}
-+
-+/*
-+ * Read an entire CGRAM character from the display.
-+ */
-+static void read_cgram(struct lcd_struct *p, unsigned char index, unsigned char *pixels)
-+{
-+ struct lcd_parameters *par = p->par;
-+ unsigned int inc_set = test_bit(INC_CURS_POS, &p->struct_flags);
-+ unsigned char *cgbuf = p->cgram_buffer+(index-par->cgram_char0)*par->cgram_bytes;
-+
-+ if (! p->driver->read_cgram_char) {
-+ memcpy(pixels, cgbuf, par->cgram_bytes);
-+ return;
-+ }
-+
-+ if (! inc_set)
-+ address_mode(p, 1);
-+
-+ p->driver->read_cgram_char(index, pixels);
-+
-+ if (! inc_set)
-+ address_mode(p, -1);
-+}
-+
-+
-+
-+
-+
-+/****************************
-+ * Proc filesystem routines *
-+ ****************************/
-+#ifdef USE_PROC
-+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 4, 0)
-+/* create_proc_read_entry is missing in 2.2.x kernels */
-+static struct proc_dir_entry *create_proc_read_entry(const char *name, mode_t mode,
-+ struct proc_dir_entry *parent, read_proc_t *read_proc, void *data)
-+{
-+ struct proc_dir_entry *res = create_proc_entry(name, mode, parent);
-+
-+ if (res) {
-+ res->read_proc = read_proc;
-+ res->data = data;
-+ }
-+
-+ return (res);
-+}
-+#endif
-+
-+static int proc_fb_read(char *buffer, char **start, off_t offset, int size, int *eof, void *data)
-+{
-+ char *temp = buffer;
-+ struct lcd_struct *p = (struct lcd_struct *)data;
-+ unsigned int vs_cols;
-+ static unsigned int nr, need_wrap;
-+ static off_t _offset;
-+
-+ down(&p->lcd_sem);
-+ if (! offset)
-+ _offset = 0;
-+ if ((*eof = (_offset >= p->fb_size))) {
-+ up(&p->lcd_sem);
-+ return (0);
-+ }
-+ vs_cols = p->par->vs_cols;
-+ if (size && need_wrap) {
-+ need_wrap = 0;
-+ temp += sprintf(temp, "\n");
-+ --size;
-+ }
-+ if (! nr)
-+ nr = vs_cols;
-+ *start = (char *)0;
-+ while (size && nr) {
-+ unsigned char c = (p->fb[_offset] & 0xff);
-+
-+ temp += sprintf(temp, "%c", (c < 0x20 ? '?' : c));
-+ --size;
-+ --nr;
-+ ++*start;
-+ ++_offset;
-+ }
-+ if (! nr) {
-+ if (size) {
-+ temp += sprintf(temp, "\n");
-+ --size;
-+ } else
-+ need_wrap = 1;
-+ }
-+ up(&p->lcd_sem);
-+
-+ return (temp-buffer);
-+}
-+
-+static int proc_display_read(char *buffer, char **start, off_t offset, int size, int *eof, void *data)
-+{
-+ char *temp = buffer;
-+ struct lcd_struct *p = (struct lcd_struct *)data;
-+ unsigned int i, frame_cols;
-+ int frame_pos;
-+
-+ down(&p->lcd_sem);
-+ frame_cols = p->par->cntr_cols;
-+ frame_pos = vs_to_frame_(p, (p->row*p->par->vs_cols)+p->col);
-+ temp += sprintf(temp, " ");
-+ for (i = 2; i <= frame_cols; i += 2)
-+ temp += sprintf(temp, " %d", i%10);
-+ temp += sprintf(temp, "\n");
-+
-+ temp += sprintf(temp, " +");
-+ for (i = 0; i < frame_cols; ++i)
-+ temp += sprintf(temp, "-");
-+ temp += sprintf(temp, "+\n");
-+
-+ for (i = 0; i < p->frame_size; ++i) {
-+ unsigned char c = (p->display[i] & 0xff);
-+
-+ if (! (i%frame_cols))
-+ temp += sprintf(temp, "%2d |", 1+i/frame_cols);
-+ if (frame_pos--)
-+ temp += sprintf(temp, "%c", (c < 0x20 ? '?' : c));
-+ else
-+ temp += sprintf(temp, "_");
-+ if (! ((i+1)%frame_cols))
-+ temp += sprintf(temp, "|\n");
-+ }
-+
-+ temp += sprintf(temp, " +");
-+ for (i = 0; i < frame_cols; ++i)
-+ temp += sprintf(temp, "-");
-+ temp += sprintf(temp, "+\n");
-+ up(&p->lcd_sem);
-+
-+ return (temp-buffer);
-+}
-+
-+static int proc_charmap_read(char *buffer, char **start, off_t offset, int size, int *eof, void *data)
-+{
-+ char *temp = buffer;
-+ struct lcd_struct *p = (struct lcd_struct *)data;
-+ unsigned char *charmap;
-+ unsigned int i;
-+
-+ down(&p->lcd_sem);
-+ charmap = p->driver->charmap;
-+ temp += sprintf(temp, "static unsigned char charmap[] = {");
-+ for (i = 0; i < 255; ++i) {
-+ if (! (i & 7)) {
-+ temp += sprintf(temp, "\n");
-+ if (! (i & 31))
-+ temp += sprintf(temp, "\n/* %d - %d */\n", i, i+31);
-+ }
-+ temp += sprintf(temp, "0x%.2x, ", *charmap++);
-+ }
-+ temp += sprintf(temp, "0x%.2x\n\n};\n", *charmap);
-+ up(&p->lcd_sem);
-+
-+ return (temp-buffer);
-+}
-+
-+static int proc_registered_drivers(char *buffer, char **start, off_t offset, int size, int *eof, void *data)
-+{
-+ char *temp = buffer;
-+ struct list_head *entry;
-+
-+ down(&drivers_sem);
-+ temp += sprintf(temp, "Registered drivers:\n");
-+ list_for_each(entry, &lcd_drivers) {
-+ struct lcd_struct *p = list_entry(entry, struct lcd_struct, lcd_list);
-+
-+ down(&p->lcd_sem);
-+ temp += sprintf(temp, "%3d %s\n", p->par->minor, p->par->name);
-+ up(&p->lcd_sem);
-+ }
-+ up(&drivers_sem);
-+
-+ return (temp-buffer);
-+}
-+
-+static void create_driver_proc_entries(struct lcd_struct *p)
-+{
-+ struct proc_dir_entry *driver_proc_root = p->driver->driver_proc_root;
-+
-+ SET_PROC_LEVEL(p, 0);
-+ if (create_proc_read_entry("framebuffer", 0, driver_proc_root, proc_fb_read, p) == NULL) {
-+ printk(KERN_ERR "LCD: cannot create /proc/lcd/%s/framebuffer\n", p->par->name);
-+ return;
-+ }
-+ SET_PROC_LEVEL(p, 1);
-+ if (create_proc_read_entry("display", 0, driver_proc_root, proc_display_read, p) == NULL) {
-+ printk(KERN_ERR "LCD: cannot create /proc/lcd/%s/display\n", p->par->name);
-+ return;
-+ }
-+ SET_PROC_LEVEL(p, 2);
-+ if (create_proc_read_entry("charmap.h", 0, driver_proc_root, proc_charmap_read, p) == NULL) {
-+ printk(KERN_ERR "LCD: cannot create /proc/lcd/%s/charmap.h\n", p->par->name);
-+ return;
-+ }
-+ SET_PROC_LEVEL(p, 3);
-+}
-+
-+static void remove_driver_proc_entries(struct lcd_struct *p)
-+{
-+ struct proc_dir_entry *driver_proc_root = p->driver->driver_proc_root;
-+
-+ switch (PROC_LEVEL(p)) {
-+ case 3:
-+ remove_proc_entry("charmap.h", driver_proc_root);
-+ case 2:
-+ remove_proc_entry("display", driver_proc_root);
-+ case 1:
-+ remove_proc_entry("framebuffer", driver_proc_root);
-+ }
-+ SET_PROC_LEVEL(p, 0);
-+}
-+#endif
-+
-+
-+
-+
-+
-+/*****************************
-+ * Low level file operations *
-+ *****************************/
-+static ssize_t do_lcd_read(struct lcd_struct *p, void *buffer, size_t length)
-+{
-+ unsigned int i;
-+ unsigned short tmp;
-+
-+ if (! p->refcount)
-+ return (-ENXIO);
-+
-+ if (test_bit(WITH_ATTR, &p->struct_flags))
-+ for (i = 0; i < length; ++i) {
-+ read_data(p, &tmp);
-+ ((unsigned short *)buffer)[i] = tmp;
-+ }
-+ else
-+ for (i = 0; i < length; ++i) {
-+ read_data(p, &tmp);
-+ ((unsigned char *)buffer)[i] = tmp & 0xff;
-+ }
-+
-+ return (length);
-+}
-+
-+static ssize_t do_lcd_write(struct lcd_struct *p, const void *buffer, size_t length)
-+{
-+ unsigned int i;
-+
-+ if (! p->refcount)
-+ return (-ENXIO);
-+
-+ if (test_bit(WITH_ATTR, &p->struct_flags))
-+ for (i = 0; i < length; ++i)
-+ handle_input(p, ((const unsigned short *)buffer)[i]);
-+ else
-+ for (i = 0; i < length; ++i)
-+ handle_input(p, (p->attr << 8) | ((const unsigned char *)buffer)[i]);
-+
-+ return (length);
-+}
-+
-+static int do_lcd_open(struct lcd_struct *p)
-+{
-+ if (! p->refcount) {
-+ if (p->driver->driver_module) {
-+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0)
-+ if (! try_module_get(p->driver->driver_module))
-+ return (-EBUSY);
-+#else
-+ if (__MOD_IN_USE(p->driver->driver_module))
-+ return (-EBUSY);
-+
-+ __MOD_INC_USE_COUNT(p->driver->driver_module);
-+#endif
-+ }
-+ }
-+
-+ ++p->refcount;
-+
-+ return (0);
-+}
-+
-+static int do_lcd_release(struct lcd_struct *p)
-+{
-+ if (! p->refcount)
-+ return (0);
-+
-+ if (p->refcount == 1) {
-+ if (p->driver->driver_module)
-+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0)
-+ module_put(p->driver->driver_module);
-+#else
-+ __MOD_DEC_USE_COUNT(p->driver->driver_module);
-+#endif
-+ }
-+
-+ --p->refcount;
-+
-+ return (0);
-+}
-+
-+static int cgram_ioctl(struct lcd_struct *p, unsigned int cmd, unsigned char *argp)
-+{
-+ struct lcd_parameters *par = p->par;
-+ unsigned int length = par->cgram_bytes;
-+ unsigned char index = argp[0];
-+ unsigned char *buffer = argp+1;
-+ unsigned char *cgbuf = p->cgram_buffer-length;
-+
-+ if (index < par->cgram_char0 || index >= par->cgram_char0+par->cgram_chars)
-+ return (-EINVAL);
-+
-+ if (! p->driver->write_cgram_char) {
-+ printk(KERN_ERR "LCD: %s: missing function to write to CGRAM\n", p->par->name);
-+ return (-ENOSYS);
-+ }
-+
-+ if (cmd == LCDL_SET_CGRAM_CHAR) {
-+ if (test_bit(USER_SPACE, &p->struct_flags)) {
-+ if (copy_from_user(cgbuf, buffer, length))
-+ return (-EFAULT);
-+ } else
-+ memcpy(cgbuf, buffer, length);
-+ write_cgram(p, index, cgbuf);
-+ } else {
-+ read_cgram(p, index, cgbuf);
-+ if (test_bit(USER_SPACE, &p->struct_flags)) {
-+ if (copy_to_user(buffer, cgbuf, length))
-+ return (-EFAULT);
-+ } else
-+ memcpy(buffer, cgbuf, length);
-+ }
-+
-+ return (0);
-+}
-+
-+static int do_lcd_ioctl(struct lcd_struct *p, unsigned int cmd, unsigned long arg)
-+{
-+ int i;
-+ struct lcd_driver *driver = p->driver;
-+ struct lcd_parameters *par = p->par;
-+ unsigned char *argp = (unsigned char *)arg;
-+
-+ if (! p->refcount)
-+ return (-ENXIO);
-+
-+ switch (cmd) {
-+ case LCDL_SET_PARAM:
-+ if (argp == NULL)
-+ return (-EFAULT);
-+ if ((i = cleanup_driver(p)))
-+ return (i);
-+ i = par->minor;
-+ if (test_bit(USER_SPACE, &p->struct_flags)) {
-+ if (copy_from_user(par, argp, sizeof(struct lcd_parameters)))
-+ return (-EFAULT);
-+ } else
-+ memcpy(par, argp, sizeof(struct lcd_parameters));
-+ par->minor = i;
-+ return (init_driver(p));
-+
-+ case LCDL_GET_PARAM:
-+ if (argp == NULL)
-+ return (-EFAULT);
-+ if (test_bit(USER_SPACE, &p->struct_flags)) {
-+ if (copy_to_user(argp, par, sizeof(struct lcd_parameters)))
-+ return (-EFAULT);
-+ } else
-+ memcpy(argp, par, sizeof(struct lcd_parameters));
-+ return (0);
-+
-+ case LCDL_RESET_CHARMAP:
-+ for (i = 0; i < 256; ++i)
-+ driver->charmap[i] = i;
-+ return (0);
-+
-+ case LCDL_CHARSUBST:
-+ if (argp == NULL)
-+ return (-EFAULT);
-+ if (test_bit(USER_SPACE, &p->struct_flags)) {
-+ get_user(i, argp);
-+ get_user(driver->charmap[i], argp+1);
-+ } else {
-+ i = argp[0];
-+ driver->charmap[i] = argp[1];
-+ }
-+ return (0);
-+
-+ case LCDL_SAVE_CHARMAP:
-+ memcpy(p->s_charmap, driver->charmap, 256);
-+ return (0);
-+
-+ case LCDL_RESTORE_CHARMAP:
-+ memcpy(driver->charmap, p->s_charmap, 256);
-+ return (0);
-+
-+ case LCDL_SWAP_CHARMAP:
-+ {
-+ unsigned char *tmp;
-+
-+ tmp = driver->charmap;
-+ driver->charmap = p->s_charmap;
-+ p->s_charmap = tmp;
-+ }
-+ return (0);
-+
-+ case LCDL_RAW_MODE:
-+ if (arg) {
-+ clear_bit(NEED_WRAP, &p->struct_flags);
-+ clear_bit(DECIM, &p->struct_flags);
-+ clear_bit(DECAWM, &p->struct_flags);
-+ SET_INPUT_STATE(p, RAW);
-+ } else {
-+ set_bit(DECAWM, &p->struct_flags);
-+ SET_INPUT_STATE(p, NORMAL);
-+ }
-+ return (0);
-+
-+ case LCDL_IOATTR:
-+ if (arg)
-+ set_bit(WITH_ATTR, &p->struct_flags);
-+ else
-+ clear_bit(WITH_ATTR, &p->struct_flags);
-+ return (0);
-+
-+ case LCDL_CLEAR_DISP:
-+ ff(p);
-+ return (0);
-+
-+ case LCDL_SET_CGRAM_CHAR:
-+ case LCDL_GET_CGRAM_CHAR:
-+ if (argp == NULL)
-+ return (-EFAULT);
-+ if (p->cgram_buffer)
-+ return (cgram_ioctl(p, cmd, argp));
-+ else
-+ printk(KERN_NOTICE "LCD: driver %s does not support CGRAM chars\n", par->name);
-+ return (0);
-+
-+ case LCDL_SET_CHARMAP:
-+ if (argp == NULL)
-+ return (-EFAULT);
-+ if (test_bit(USER_SPACE, &p->struct_flags)) {
-+ if (copy_from_user(driver->charmap, argp, 256))
-+ return (-EFAULT);
-+ } else
-+ memcpy(driver->charmap, argp, 256);
-+ return (0);
-+
-+ case LCDL_GET_CHARMAP:
-+ if (argp == NULL)
-+ return (-EFAULT);
-+ if (test_bit(USER_SPACE, &p->struct_flags)) {
-+ if (copy_to_user(argp, driver->charmap, 256))
-+ return (-EFAULT);
-+ } else
-+ memcpy(argp, driver->charmap, 256);
-+ return (0);
-+
-+ case LCDL_MEMSET:
-+ case LCDL_MEMMOVE:
-+ {
-+ int buf[3];
-+
-+ if (argp == NULL)
-+ return (-EFAULT);
-+ if (test_bit(USER_SPACE, &p->struct_flags)) {
-+ if (copy_from_user(buf, argp, sizeof(buf)))
-+ return (-EFAULT);
-+ } else
-+ memcpy(buf, argp, sizeof(buf));
-+
-+ if (cmd == LCDL_MEMSET)
-+ lcd_memset(p, buf[0], buf[1], buf[2]);
-+ else
-+ lcd_memmove(p, buf[0], buf[1], buf[2]);
-+
-+ return (0);
-+ }
-+
-+ default:
-+ if (driver->handle_custom_ioctl)
-+ return (driver->handle_custom_ioctl(cmd, arg, test_bit(USER_SPACE, &p->struct_flags)));
-+ }
-+
-+ return (-ENOIOCTLCMD);
-+}
-+
-+
-+
-+
-+
-+/**************************************************
-+ * Kernel register/unregister lcd driver routines *
-+ **************************************************/
-+/*
-+ * Find a driver in lcd_drivers linked list
-+ */
-+static struct lcd_struct *find_lcd_struct(unsigned short minor)
-+{
-+ struct list_head *entry;
-+
-+ list_for_each(entry, &lcd_drivers) {
-+ struct lcd_struct *p = list_entry(entry, struct lcd_struct, lcd_list);
-+
-+ if (p->par->minor == minor)
-+ return (p);
-+ }
-+
-+ return (NULL);
-+}
-+
-+static void list_add_sorted(struct list_head *new)
-+{
-+ struct list_head *entry;
-+ unsigned short new_minor = (list_entry(new, struct lcd_struct, lcd_list))->par->minor;
-+
-+ list_for_each(entry, &lcd_drivers) {
-+ struct lcd_struct *p = list_entry(entry, struct lcd_struct, lcd_list);
-+
-+ if (p->par->minor > new_minor)
-+ break;
-+ }
-+ list_add_tail(new, entry);
-+}
-+
-+/* Exported function */
-+int lcd_register_driver(struct lcd_driver *driver, struct lcd_parameters *par)
-+{
-+ int ret;
-+ struct lcd_struct *p;
-+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 19)
-+ struct device *lcd_device;
-+#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 13)
-+ struct class_device *lcd_device;
-+#endif
-+
-+ if (! driver || ! par || par->minor >= minors)
-+ return (-EINVAL);
-+ if (! driver->write_char || ! driver->init_port || ! driver->cleanup_port) {
-+ printk(KERN_ERR "LCD: missing functions\n");
-+ return (-EINVAL);
-+ }
-+
-+ down(&drivers_sem);
-+
-+ if (find_lcd_struct(par->minor)) {
-+ up(&drivers_sem);
-+ return (-EBUSY);
-+ }
-+
-+ if ((p = (struct lcd_struct *)kmalloc(sizeof(struct lcd_struct), GFP_KERNEL)) == NULL) {
-+ printk(KERN_ERR "LCD: memory allocation failed (kmalloc)\n");
-+ up(&drivers_sem);
-+ return (-ENOMEM);
-+ }
-+ memset(p, 0, sizeof(struct lcd_struct));
-+
-+ p->driver = driver;
-+ p->par = par;
-+ p->refcount = 0;
-+ SET_INIT_LEVEL(p, 0);
-+ SET_INPUT_STATE(p, NORMAL);
-+ set_bit(DECAWM, &p->struct_flags);
-+ set_bit(INC_CURS_POS, &p->struct_flags);
-+
-+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 13)
-+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)
-+ lcd_device = device_create(lcd_linux_class, NULL, MKDEV(major, par->minor), NULL, "%s", par->name);
-+#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 19)
-+ lcd_device = device_create(lcd_linux_class, NULL, MKDEV(major, par->minor), "%s", par->name);
-+#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 15)
-+ lcd_device = class_device_create(lcd_linux_class, NULL, MKDEV(major, par->minor), NULL, "%s", par->name);
-+#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 13)
-+ lcd_device = class_device_create(lcd_linux_class, MKDEV(major, par->minor), NULL, "%s", par->name);
-+#endif
-+ if (IS_ERR(lcd_device)) {
-+ kfree(p);
-+ up(&drivers_sem);
-+ return (PTR_ERR(lcd_device));
-+ }
-+#endif
-+
-+#ifdef USE_PROC
-+ if (lcd_proc_root && (driver->driver_proc_root = proc_mkdir(par->name, lcd_proc_root)) == NULL)
-+ printk(KERN_ERR "LCD: cannot create /proc/lcd/%s/\n", par->name);
-+#endif
-+
-+ if ((ret = init_driver(p))) {
-+#ifdef USE_PROC
-+ if (driver->driver_proc_root)
-+ remove_proc_entry(p->par->name, lcd_proc_root);
-+#endif
-+
-+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 19)
-+ device_destroy(lcd_linux_class, MKDEV(major, par->minor));
-+#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 13)
-+ class_device_destroy(lcd_linux_class, MKDEV(major, par->minor));
-+#endif
-+
-+ kfree(p);
-+ up(&drivers_sem);
-+ return (ret);
-+ }
-+
-+ init_MUTEX(&p->lcd_sem);
-+
-+ list_add_sorted(&p->lcd_list);
-+
-+ up(&drivers_sem);
-+
-+#ifdef MODULE
-+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0)
-+ try_module_get(THIS_MODULE);
-+#else
-+ MOD_INC_USE_COUNT;
-+#endif
-+#endif
-+
-+ return (0);
-+}
-+EXPORT_SYMBOL(lcd_register_driver);
-+
-+/* Exported function */
-+int lcd_unregister_driver(struct lcd_driver *driver, struct lcd_parameters *par)
-+{
-+ int ret;
-+ struct lcd_struct *p;
-+
-+ if (! driver || ! par || par->minor >= minors)
-+ return (-EINVAL);
-+
-+ down(&drivers_sem);
-+
-+ if ((p = find_lcd_struct(par->minor)) == NULL || p->driver != driver) {
-+ printk(KERN_ERR "LCD: driver not found; lcd_unregister_driver failed\n");
-+ up(&drivers_sem);
-+ return (-ENODEV);
-+ }
-+
-+ down(&p->lcd_sem);
-+
-+ if (p->refcount) {
-+ printk(KERN_ERR "LCD: driver busy; lcd_unregister_driver failed\n");
-+ up(&p->lcd_sem);
-+ up(&drivers_sem);
-+ return (-EBUSY);
-+ }
-+
-+ if ((ret = cleanup_driver(p))) {
-+ up(&p->lcd_sem);
-+ up(&drivers_sem);
-+ return (ret);
-+ }
-+
-+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 19)
-+ device_destroy(lcd_linux_class, MKDEV(major, par->minor));
-+#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 13)
-+ class_device_destroy(lcd_linux_class, MKDEV(major, par->minor));
-+#endif
-+
-+#ifdef USE_PROC
-+ if (p->driver->driver_proc_root)
-+ remove_proc_entry(p->par->name, lcd_proc_root);
-+#endif
-+
-+ list_del(&p->lcd_list);
-+ kfree(p);
-+
-+ up(&drivers_sem);
-+
-+#ifdef MODULE
-+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0)
-+ module_put(THIS_MODULE);
-+#else
-+ MOD_DEC_USE_COUNT;
-+#endif
-+#endif
-+
-+ return (0);
-+}
-+EXPORT_SYMBOL(lcd_unregister_driver);
-+
-+
-+
-+
-+
-+/************************
-+ * Kernel I/O interface *
-+ ************************/
-+/* Exported function */
-+int lcd_open(unsigned short minor, struct lcd_struct **pp)
-+{
-+ int ret;
-+ struct lcd_struct *p;
-+
-+ down(&drivers_sem);
-+
-+ if (minor >= minors || (*pp = p = find_lcd_struct(minor)) == NULL) {
-+ printk(KERN_ERR "LCD: lcd_open failed. Device not found.\n");
-+ up(&drivers_sem);
-+ return (-ENODEV);
-+ }
-+
-+ down(&p->lcd_sem);
-+ up(&drivers_sem);
-+
-+ ret = do_lcd_open(p);
-+
-+ up(&p->lcd_sem);
-+
-+ return (ret);
-+}
-+EXPORT_SYMBOL(lcd_open);
-+
-+/* Exported function */
-+int lcd_close(struct lcd_struct **pp)
-+{
-+ int ret;
-+ struct lcd_struct *p;
-+
-+ if (! pp || ! (p = *pp)) {
-+ printk(KERN_ERR "LCD: NULL pointer in lcd_close\n");
-+ return (-ENODEV);
-+ }
-+
-+ down(&p->lcd_sem);
-+
-+ if (! (ret = do_lcd_release(p)))
-+ *pp = NULL;
-+
-+ up(&p->lcd_sem);
-+
-+ return (ret);
-+}
-+EXPORT_SYMBOL(lcd_close);
-+
-+static inline loff_t offset_to_row_col(struct lcd_struct *p, loff_t offset)
-+{
-+ unsigned long _offset = offset;
-+ unsigned int vs_cols = p->par->vs_cols;
-+
-+ gotoxy(p, _offset%vs_cols, _offset/vs_cols);
-+
-+ return ((p->row*vs_cols)+p->col);
-+}
-+
-+/* Exported function */
-+ssize_t lcd_read(struct lcd_struct *p, void *bufp, size_t length, loff_t offset, unsigned int with_attr)
-+{
-+ ssize_t ret = 0;
-+
-+ if (! p) {
-+ printk(KERN_ERR "LCD: NULL pointer in lcd_read\n");
-+ return (-ENODEV);
-+ }
-+ if (! bufp)
-+ return (-EFAULT);
-+ if (offset < 0 || offset >= p->fb_size)
-+ return (-EINVAL);
-+
-+ if (length+offset > p->fb_size)
-+ length = p->fb_size-offset;
-+
-+ if (with_attr)
-+ set_bit(WITH_ATTR, &p->struct_flags);
-+
-+ offset_to_row_col(p, offset);
-+ ret = do_lcd_read(p, bufp, length);
-+
-+ if (with_attr)
-+ clear_bit(WITH_ATTR, &p->struct_flags);
-+
-+ return (ret);
-+}
-+EXPORT_SYMBOL(lcd_read);
-+
-+/* Exported function */
-+ssize_t lcd_write(struct lcd_struct *p, const void *bufp, size_t length, loff_t offset, unsigned int with_attr)
-+{
-+ ssize_t ret;
-+
-+ if (! p) {
-+ printk(KERN_ERR "LCD: NULL pointer in lcd_write\n");
-+ return (-ENODEV);
-+ }
-+ if (! bufp)
-+ return (-EFAULT);
-+ if (offset < 0 || offset >= p->fb_size)
-+ return (-EINVAL);
-+
-+ if (with_attr)
-+ set_bit(WITH_ATTR, &p->struct_flags);
-+
-+ offset_to_row_col(p, offset);
-+ ret = do_lcd_write(p, bufp, length);
-+
-+ if (with_attr)
-+ clear_bit(WITH_ATTR, &p->struct_flags);
-+
-+ return (ret);
-+}
-+EXPORT_SYMBOL(lcd_write);
-+
-+/* Exported function */
-+int lcd_ioctl(struct lcd_struct *p, unsigned int cmd, ...)
-+{
-+ int ret;
-+ unsigned long arg;
-+ va_list ap;
-+
-+ if (! p) {
-+ printk(KERN_ERR "LCD: NULL pointer in lcd_ioctl\n");
-+ return (-ENODEV);
-+ }
-+
-+ down(&p->lcd_sem);
-+ va_start(ap, cmd);
-+ arg = va_arg(ap, unsigned long);
-+ ret = do_lcd_ioctl(p, cmd, arg);
-+ va_end(ap);
-+ up(&p->lcd_sem);
-+
-+ return (ret);
-+}
-+EXPORT_SYMBOL(lcd_ioctl);
-+
-+
-+
-+
-+
-+/*******************
-+ * File operations *
-+ *******************/
-+static loff_t lcd_fops_llseek(struct file *filp, loff_t offset, int orig)
-+{
-+ struct lcd_struct *p;
-+
-+ if (! (p = filp->private_data))
-+ return (-ENODEV);
-+
-+ down(&p->lcd_sem);
-+
-+ switch (orig) {
-+ case 0:
-+ break;
-+
-+ case 1:
-+ offset += filp->f_pos;
-+ break;
-+
-+ default:
-+ up(&p->lcd_sem);
-+ return (-EINVAL); /* SEEK_END not supported */
-+ }
-+
-+ if (offset >= 0 && offset < p->fb_size)
-+ filp->f_pos = offset_to_row_col(p, offset);
-+ else
-+ offset = -EINVAL;
-+
-+ up(&p->lcd_sem);
-+
-+ return (offset);
-+}
-+
-+static ssize_t lcd_fops_read(struct file *filp, char *buffer, size_t length, loff_t *offp)
-+{
-+ ssize_t ret = 0;
-+ char *bufp = buffer;
-+ struct lcd_struct *p;
-+
-+ if (! bufp)
-+ return (-EFAULT);
-+ if (! (p = filp->private_data))
-+ return (-ENODEV);
-+
-+ down(&p->lcd_sem);
-+
-+ if (*offp < 0 || *offp >= p->fb_size) {
-+ up(&p->lcd_sem);
-+ return (-EINVAL);
-+ }
-+
-+ if (test_bit(WITH_ATTR, &p->struct_flags) && (length & 0x01))
-+ length &= ~0x01;
-+
-+ if (length+(*offp) > p->fb_size)
-+ length = p->fb_size-(*offp);
-+
-+ while (length) {
-+ ret = (length > FLIP_BUF_SIZE ? FLIP_BUF_SIZE : length);
-+ if (test_bit(WITH_ATTR, &p->struct_flags))
-+ ret /= sizeof(unsigned short);
-+ if ((ret = do_lcd_read(p, p->flip_buf, ret)) < 0)
-+ break;
-+ if (test_bit(WITH_ATTR, &p->struct_flags))
-+ ret *= sizeof(unsigned short);
-+ *offp = (p->row*p->par->vs_cols)+p->col;
-+ if (copy_to_user(bufp, p->flip_buf, ret)) {
-+ ret = -EFAULT;
-+ break;
-+ }
-+ length -= ret;
-+ bufp += ret;
-+ ret = bufp-buffer;
-+ if (length)
-+ schedule();
-+ }
-+
-+ up(&p->lcd_sem);
-+
-+ return (ret);
-+}
-+
-+static ssize_t lcd_fops_write(struct file *filp, const char *buffer, size_t length, loff_t *offp)
-+{
-+ ssize_t ret = 0;
-+ const char *bufp = buffer;
-+ struct lcd_struct *p;
-+
-+ if (! bufp)
-+ return (-EFAULT);
-+ if (! (p = filp->private_data))
-+ return (-ENODEV);
-+
-+ down(&p->lcd_sem);
-+
-+ if (*offp < 0 || *offp >= p->fb_size) {
-+ up(&p->lcd_sem);
-+ return (-EINVAL);
-+ }
-+
-+ if (test_bit(WITH_ATTR, &p->struct_flags) && (length & 0x01))
-+ length &= ~0x01;
-+
-+ while (length) {
-+ ret = (length > FLIP_BUF_SIZE ? FLIP_BUF_SIZE : length);
-+ if (copy_from_user(p->flip_buf, bufp, ret)) {
-+ ret = -EFAULT;
-+ break;
-+ }
-+ if (test_bit(WITH_ATTR, &p->struct_flags))
-+ ret /= sizeof(unsigned short);
-+ if ((ret = do_lcd_write(p, p->flip_buf, ret)) < 0)
-+ break;
-+ if (test_bit(WITH_ATTR, &p->struct_flags))
-+ ret *= sizeof(unsigned short);
-+ *offp = (p->row*p->par->vs_cols)+p->col;
-+ length -= ret;
-+ bufp += ret;
-+ ret = bufp-buffer;
-+ if (length)
-+ schedule();
-+ }
-+
-+ up(&p->lcd_sem);
-+
-+ return (ret);
-+}
-+
-+static int lcd_fops_open(struct inode *inop, struct file *filp)
-+{
-+ unsigned short minor;
-+ int ret;
-+ struct lcd_struct *p;
-+
-+ down(&drivers_sem);
-+
-+ if ((minor = MINOR(inop->i_rdev)) >= minors || (filp->private_data = p = find_lcd_struct(minor)) == NULL) {
-+ up(&drivers_sem);
-+ return (-ENODEV);
-+ }
-+
-+ down(&p->lcd_sem);
-+ up(&drivers_sem);
-+
-+ ret = do_lcd_open(p);
-+
-+ up(&p->lcd_sem);
-+
-+ return (ret);
-+}
-+
-+static int lcd_fops_release(struct inode *inop, struct file *filp)
-+{
-+ struct lcd_struct *p;
-+ int ret;
-+
-+ if (! (p = filp->private_data))
-+ return (-ENODEV);
-+
-+ down(&p->lcd_sem);
-+
-+ if (! (ret = do_lcd_release(p)))
-+ filp->private_data = NULL;
-+
-+ up(&p->lcd_sem);
-+
-+ return (ret);
-+}
-+
-+static long lcd_fops_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
-+{
-+ struct lcd_struct *p;
-+ int ret;
-+
-+ if (! (p = filp->private_data))
-+ return (-ENODEV);
-+
-+ down(&p->lcd_sem);
-+
-+ set_bit(USER_SPACE, &p->struct_flags);
-+ ret = do_lcd_ioctl(p, cmd, arg);
-+ clear_bit(USER_SPACE, &p->struct_flags);
-+
-+ up(&p->lcd_sem);
-+
-+ return (ret);
-+}
-+
-+static struct file_operations lcd_linux_fops = {
-+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 4, 0)
-+ .owner = THIS_MODULE,
-+#endif
-+ .llseek = lcd_fops_llseek,
-+ .read = lcd_fops_read,
-+ .write = lcd_fops_write,
-+ .open = lcd_fops_open,
-+ .release = lcd_fops_release,
-+ .unlocked_ioctl = lcd_fops_ioctl,
-+};
-+
-+
-+
-+
-+
-+/********************************
-+ * Init/Cleanup driver routines *
-+ ********************************/
-+static int do_init_driver(struct lcd_struct *p)
-+{
-+ int ret;
-+ struct lcd_driver *driver = p->driver;
-+ struct lcd_parameters *par = p->par;
-+ unsigned int frame_rows = par->cntr_rows*par->num_cntr;
-+ unsigned int frame_cols = par->cntr_cols;
-+
-+ switch (INIT_LEVEL(p)) {
-+ case 0:
-+ if (frame_rows == 0 || frame_cols == 0 || ! par->name) {
-+ printk(KERN_ERR "LCD: wrong lcd parameters\n");
-+ return (-EINVAL);
-+ }
-+ if (driver->validate_driver) {
-+ if ((ret = driver->validate_driver()) < 0) {
-+ printk(KERN_ERR "LCD: validate_driver failed\n");
-+ return (-EINVAL);
-+ } else if (ret > 0) {
-+ set_bit(CAN_DO_COLOR, &p->struct_flags);
-+ p->defcolor = 0x07;
-+ p->ulcolor = 0x0f;
-+ p->halfcolor = 0x08;
-+ }
-+ }
-+ default_attr(p);
-+ update_attr(p);
-+ p->frame_size = frame_rows*frame_cols;
-+ if (par->vs_rows < frame_rows)
-+ par->vs_rows = frame_rows;
-+ if (par->vs_cols < frame_cols)
-+ par->vs_cols = frame_cols;
-+ p->fb_size = par->vs_rows*par->vs_cols;
-+
-+ ret = sizeof(short)*p->fb_size;
-+ ret += sizeof(short)*p->frame_size;
-+ ret += FLIP_BUF_SIZE;
-+ ret += (p->driver->charmap ? 256 : 512);
-+ if (par->cgram_chars*par->cgram_bytes)
-+ ret += (1+par->cgram_chars)*par->cgram_bytes;
-+ if ((p->fb = (unsigned short *)vmalloc(ret)) == NULL) {
-+ printk(KERN_ERR "LCD: memory allocation failed (vmalloc)\n");
-+ return (-ENOMEM);
-+ }
-+ __memset_short(p->fb, p->erase_char, p->fb_size+p->frame_size);
-+
-+ p->display = p->fb+p->fb_size;
-+ p->flip_buf = (unsigned char *)(p->display+p->frame_size);
-+
-+ if (! p->driver->charmap) {
-+ set_bit(NULL_CHARMAP, &p->struct_flags);
-+ p->driver->charmap = p->flip_buf+FLIP_BUF_SIZE;
-+ for (ret = 0; ret < 256; ++ret)
-+ p->driver->charmap[ret] = ret;
-+ p->s_charmap = p->driver->charmap+256;
-+ } else
-+ p->s_charmap = p->flip_buf+FLIP_BUF_SIZE;
-+ memset(p->s_charmap, 0, 256);
-+
-+ if (par->cgram_chars*par->cgram_bytes) {
-+ p->cgram_buffer = p->s_charmap+256+par->cgram_bytes;
-+ memset(p->cgram_buffer, 0xff, par->cgram_chars*par->cgram_bytes);
-+ } else
-+ p->cgram_buffer = NULL;
-+ p->driver->cgram_buffer = p->cgram_buffer;
-+
-+ p->frame_base = 0;
-+ p->row = p->col = 0;
-+ p->top = 0;
-+ p->bot = par->vs_rows;
-+ SET_INIT_LEVEL(p, 1);
-+
-+ case 1:
-+ /* Initialize the communication port */
-+ if ((ret = driver->init_port())) {
-+ printk(KERN_ERR "LCD: failure while initializing the communication port\n");
-+ return (ret);
-+ }
-+ SET_INIT_LEVEL(p, 2);
-+
-+ case 2:
-+ /* Initialize LCD display */
-+ if (driver->init_display && (ret = driver->init_display())) {
-+ printk(KERN_ERR "LCD: failure while initializing the display\n");
-+ return (ret);
-+ }
-+
-+#ifdef USE_PROC
-+ /* Create entries in /proc/lcd/"driver" */
-+ if (driver->driver_proc_root)
-+ create_driver_proc_entries(p);
-+#endif
-+ SET_INIT_LEVEL(p, 3);
-+ }
-+
-+ return (0);
-+}
-+
-+static int do_cleanup_driver(struct lcd_struct *p)
-+{
-+ int ret;
-+ struct lcd_driver *driver = p->driver;
-+
-+ switch (INIT_LEVEL(p)) {
-+ case 3:
-+#ifdef USE_PROC
-+ if (driver->driver_proc_root)
-+ remove_driver_proc_entries(p);
-+#endif
-+ if (driver->cleanup_display && (ret = driver->cleanup_display())) {
-+ printk(KERN_ERR "LCD: failure while cleaning the display\n");
-+ return (ret);
-+ }
-+ SET_INIT_LEVEL(p, 2);
-+
-+ case 2:
-+ if ((ret = driver->cleanup_port())) {
-+ printk(KERN_ERR "LCD: failure while cleaning the communication port\n");
-+ return (ret);
-+ }
-+ SET_INIT_LEVEL(p, 1);
-+
-+ case 1:
-+ if (test_bit(NULL_CHARMAP, &p->struct_flags)) {
-+ p->driver->charmap = NULL;
-+ clear_bit(NULL_CHARMAP, &p->struct_flags);
-+ }
-+ vfree(p->fb);
-+ p->fb = NULL;
-+ SET_INIT_LEVEL(p, 0);
-+ }
-+
-+ return (0);
-+}
-+
-+static int init_driver(struct lcd_struct *p)
-+{
-+ int ret;
-+
-+ if ((ret = do_init_driver(p))) {
-+ do_cleanup_driver(p);
-+ printk(KERN_ERR "LCD: init_driver failed\n");
-+ }
-+
-+ return (ret);
-+}
-+
-+static int cleanup_driver(struct lcd_struct *p)
-+{
-+ int ret;
-+
-+ if ((ret = do_cleanup_driver(p))) {
-+ do_init_driver(p);
-+ printk(KERN_ERR "LCD: cleanup_driver failed\n");
-+ }
-+
-+ return (ret);
-+}
-+
-+
-+
-+
-+
-+/********************************
-+ * Init/Cleanup module routines *
-+ ********************************/
-+static int __init lcd_linux_init_module(void)
-+{
-+ int ret;
-+
-+ if (! minors || minors > 256)
-+ minors = LCD_MINORS;
-+
-+ init_MUTEX(&drivers_sem);
-+
-+ if ((ret = register_chrdev(major, LCD_LINUX_STRING, &lcd_linux_fops)) < 0) {
-+ printk(KERN_ERR "LCD: register_chrdev failed\n");
-+ return (ret);
-+ }
-+ if (major == 0)
-+ major = ret;
-+
-+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 13)
-+ if (IS_ERR((lcd_linux_class = class_create(THIS_MODULE, "lcd")))) {
-+ ret = PTR_ERR(lcd_linux_class);
-+ unregister_chrdev(major, LCD_LINUX_STRING);
-+ return (ret);
-+ }
-+#endif
-+
-+#ifdef USE_PROC
-+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26)
-+ if ((lcd_proc_root = proc_mkdir("lcd", NULL)) == NULL)
-+#else
-+ if ((lcd_proc_root = proc_mkdir("lcd", &proc_root)) == NULL)
-+#endif
-+ printk(KERN_ERR "LCD: cannot create /proc/lcd/\n");
-+ else if (create_proc_read_entry("drivers", 0, lcd_proc_root, proc_registered_drivers, NULL) == NULL)
-+ printk(KERN_ERR "LCD: cannot create /proc/lcd/drivers\n");
-+#endif
-+
-+ printk(KERN_INFO "LCD: --> LCD-Linux " LCD_LINUX_VERSION " <--\n");
-+ printk(KERN_INFO "LCD: --> Mattia Jona-Lasinio <mjona@users.sourceforge.net> <--\n" );
-+
-+
-+ return (0);
-+}
-+
-+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 4, 0)
-+static void __exit lcd_linux_cleanup_module(void)
-+#else
-+/* __exit is not defined in 2.2.x kernels */
-+static void lcd_linux_cleanup_module(void)
-+#endif
-+{
-+#ifdef USE_PROC
-+ if (lcd_proc_root) {
-+ remove_proc_entry("drivers", lcd_proc_root);
-+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26)
-+ remove_proc_entry("lcd", NULL);
-+#else
-+ remove_proc_entry("lcd", &proc_root);
-+#endif
-+ }
-+#endif
-+
-+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 13)
-+ class_destroy(lcd_linux_class);
-+#endif
-+
-+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 23)
-+ unregister_chrdev(major, LCD_LINUX_STRING);
-+#else
-+ if (unregister_chrdev(major, LCD_LINUX_STRING))
-+ printk(KERN_ERR "LCD: unregister_chrdev failed\n");
-+#endif
-+}
-+
-+module_init(lcd_linux_init_module)
-+module_exit(lcd_linux_cleanup_module)
-diff --git a/include/linux/hd44780.h b/include/linux/hd44780.h
-new file mode 100644
-index 0000000..9033d44
---- /dev/null
-+++ b/include/linux/hd44780.h
-@@ -0,0 +1,47 @@
-+/* hd44780.h
-+ *
-+ * $Id: hd44780.h,v 1.15 2009/03/09 17:59:23 mjona Exp $
-+ *
-+ * LCD-Linux:
-+ * Driver for HD44780 compatible displays connected to the parallel port.
-+ *
-+ * HD44780 header file.
-+ *
-+ * Copyright (C) 2004 - 2009 Mattia Jona-Lasinio (mjona@users.sourceforge.net)
-+ *
-+ * 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 HD44780_H
-+#define HD44780_H
-+
-+#include <linux/lcd-linux.h>
-+
-+#define HD44780_VERSION LCD_LINUX_VERSION /* Version number */
-+#define HD44780_STRING "hd44780"
-+
-+#define HD44780_MINOR 0 /* Minor number for the hd44780 driver */
-+
-+
-+/* flags */
-+#define HD44780_CHECK_BF 0x00000001 /* Do busy flag checking */
-+#define HD44780_4BITS_BUS 0x00000002 /* Set the bus length to 4 bits */
-+#define HD44780_5X10_FONT 0x00000004 /* Use 5x10 dots fonts */
-+
-+/* IOCTLs */
-+#define HD44780_READ_AC _IOR(LCD_MAJOR, 0x00, unsigned char *)
-+
-+#endif /* HD44780 included */
-diff --git a/include/linux/lcd-linux.h b/include/linux/lcd-linux.h
-new file mode 100644
-index 0000000..1756107
---- /dev/null
-+++ b/include/linux/lcd-linux.h
-@@ -0,0 +1,158 @@
-+/* lcd-linux.h
-+ *
-+ * $Id: lcd-linux.h,v 1.68 2010/07/04 16:02:02 mjona Exp $
-+ *
-+ * Software layer to drive LCD displays under Linux.
-+ *
-+ * External interface header file.
-+ *
-+ * Copyright (C) 2005 - 2009 Mattia Jona-Lasinio (mjona@users.sourceforge.net)
-+ *
-+ * 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 LCD_LINUX_H
-+#define LCD_LINUX_H
-+
-+#ifndef LCD_LINUX_MAIN
-+#warning
-+#warning LCD-Linux is still in development stage and
-+#warning aims at speed and optimization. For these
-+#warning reasons there is no guarantee of backward
-+#warning compatibility between different LCD-Linux
-+#warning versions. Be sure to use the lcd-linux.h
-+#warning file of the same version as the module.
-+#warning "http://lcd-linux.sourceforge.net/"
-+#warning
-+#endif
-+
-+#define LCD_LINUX_VERSION "0.13.9" /* Version number */
-+#define LCD_LINUX_STRING "lcd"
-+
-+#define LCD_MAJOR 120 /* Major number for this device
-+ * Set this to 0 for dynamic allocation
-+ */
-+#define LCD_MINORS 8 /* Minors allocated for LCD-Linux*/
-+
-+#include <linux/types.h>
-+
-+#define str(s) #s
-+#define string(s) str(s)
-+
-+struct lcd_parameters {
-+ const char *name; /* Driver's name */
-+ unsigned long flags; /* Flags (see documentation) */
-+ unsigned short minor; /* Minor number of the char device */
-+ unsigned short tabstop; /* Tab character length */
-+ unsigned short num_cntr; /* Controllers to drive */
-+ unsigned short cntr_rows; /* Rows per controller */
-+ unsigned short cntr_cols; /* Display columns */
-+ unsigned short vs_rows; /* Virtual screen rows */
-+ unsigned short vs_cols; /* Virtual screen columns */
-+ unsigned short cgram_chars; /* Number of user definable characters */
-+ unsigned short cgram_bytes; /* Number of bytes required to define a
-+ * user definable character */
-+ unsigned char cgram_char0; /* Ascii of first user definable character */
-+};
-+
-+/* IOCTLs */
-+#include <asm/ioctl.h>
-+#define LCDL_SET_PARAM _IOW(LCD_MAJOR, 0x80, struct lcd_parameters *)
-+#define LCDL_GET_PARAM _IOR(LCD_MAJOR, 0x81, struct lcd_parameters *)
-+#define LCDL_CHARSUBST _IOW(LCD_MAJOR, 0x82, unsigned char *)
-+#define LCDL_RAW_MODE _IOW(LCD_MAJOR, 0x83, unsigned int)
-+#define LCDL_RESET_CHARMAP _IO(LCD_MAJOR, 0x84)
-+#define LCDL_SAVE_CHARMAP _IO(LCD_MAJOR, 0x85)
-+#define LCDL_RESTORE_CHARMAP _IO(LCD_MAJOR, 0x86)
-+#define LCDL_SWAP_CHARMAP _IO(LCD_MAJOR, 0x87)
-+#define LCDL_CLEAR_DISP _IO(LCD_MAJOR, 0x88)
-+#define LCDL_SET_CGRAM_CHAR _IOW(LCD_MAJOR, 0x89, unsigned char *)
-+#define LCDL_GET_CGRAM_CHAR _IOR(LCD_MAJOR, 0x8a, unsigned char *)
-+#define LCDL_SET_CHARMAP _IOW(LCD_MAJOR, 0x8b, unsigned char *)
-+#define LCDL_GET_CHARMAP _IOR(LCD_MAJOR, 0x8c, unsigned char *)
-+#define LCDL_MEMSET _IOW(LCD_MAJOR, 0x8d, unsigned int *)
-+#define LCDL_MEMMOVE _IOW(LCD_MAJOR, 0x8e, unsigned int *)
-+#define LCDL_IOATTR _IOW(LCD_MAJOR, 0x8f, unsigned int)
-+
-+
-+
-+#ifdef __KERNEL__ /* The rest is for kernel only */
-+
-+#include <linux/kernel.h>
-+#include <linux/module.h>
-+
-+
-+struct lcd_driver {
-+ void (*read_char)(unsigned int offset, unsigned short *data);
-+ void (*read_cgram_char)(unsigned char index, unsigned char *pixmap);
-+ void (*write_char)(unsigned int offset, unsigned short data);
-+ void (*write_cgram_char)(unsigned char index, unsigned char *pixmap);
-+ void (*clear_display)(void);
-+ void (*address_mode)(int mode);
-+ int (*validate_driver)(void);
-+ int (*init_display)(void);
-+ int (*cleanup_display)(void);
-+ int (*init_port)(void);
-+ int (*cleanup_port)(void);
-+ int (*handle_custom_char)(unsigned int data);
-+ int (*handle_custom_ioctl)(unsigned int cmd, unsigned long arg, unsigned int arg_in_userspace);
-+
-+ /* The character map to be used */
-+ unsigned char *charmap;
-+
-+ /* Buffer for CGRAM operations.
-+ * Will be filled by the lcd-linux layer.
-+ */
-+ unsigned char *cgram_buffer;
-+
-+ /* The root where the driver can create its own proc files.
-+ * Will be filled by the lcd-linux layer.
-+ */
-+ struct proc_dir_entry *driver_proc_root;
-+
-+ /* Set this field to 'driver_module_init' or call lcd_driver_setup
-+ * just before registering the driver with lcd_register_driver.
-+ */
-+ struct module *driver_module;
-+};
-+
-+#ifdef MODULE
-+#define driver_module_init THIS_MODULE
-+#else
-+#define driver_module_init NULL
-+#endif
-+
-+/* Always call lcd_driver_setup just before registering the driver
-+ * with lcd_register_driver.
-+ */
-+static inline void lcd_driver_setup(struct lcd_driver *p)
-+{
-+ p->driver_module = driver_module_init;
-+}
-+
-+/* External interface */
-+struct lcd_struct;
-+int lcd_register_driver(struct lcd_driver *drv, struct lcd_parameters *par);
-+int lcd_unregister_driver(struct lcd_driver *drv, struct lcd_parameters *par);
-+int lcd_open(unsigned short minor, struct lcd_struct **lcd);
-+int lcd_close(struct lcd_struct **lcd);
-+int lcd_ioctl(struct lcd_struct *lcd, unsigned int cmd, ...);
-+ssize_t lcd_write(struct lcd_struct *lcd, const void *buffer, size_t length, loff_t offset, unsigned int with_attr);
-+ssize_t lcd_read(struct lcd_struct *lcd, void *buffer, size_t length, loff_t offset, unsigned int with_attr);
-+
-+#endif /* __KERNEL__ */
-+
-+#endif /* External interface included */
---
-1.7.0.4
-
diff --git a/recipes/linux/linux-2.6.36/ts72xx/0024-ts72xx-add-GPIO-keys.patch b/recipes/linux/linux-2.6.36/ts72xx/0024-ts72xx-add-GPIO-keys.patch
deleted file mode 100644
index dc345fa..0000000
--- a/recipes/linux/linux-2.6.36/ts72xx/0024-ts72xx-add-GPIO-keys.patch
+++ /dev/null
@@ -1,100 +0,0 @@
-From f483d4e7564786a26343900277ee9ebd2405217e Mon Sep 17 00:00:00 2001
-From: =?UTF-8?q?Petr=20=C5=A0tetiar?= <ynezz@true.cz>
-Date: Sun, 7 Nov 2010 18:34:39 +0100
-Subject: [PATCH 24/24] ts72xx: add GPIO keys
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-Signed-off-by: Petr Štetiar <ynezz@true.cz>
----
- arch/arm/mach-ep93xx/Kconfig | 6 ++++++
- arch/arm/mach-ep93xx/ts72xx.c | 36 ++++++++++++++++++++++++++++++++++++
- 2 files changed, 42 insertions(+), 0 deletions(-)
-
-diff --git a/arch/arm/mach-ep93xx/Kconfig b/arch/arm/mach-ep93xx/Kconfig
-index 2bfb01e..185c5a9 100644
---- a/arch/arm/mach-ep93xx/Kconfig
-+++ b/arch/arm/mach-ep93xx/Kconfig
-@@ -219,6 +219,12 @@ config MACH_TS72XX_SBCINFO
- Say 'Y' to add a procfs entry containing some information
- related to Technologic Systems TS-72xx SBC.
-
-+config MACH_TS72XX_GPIO_KEYS
-+ bool "Enable GPIO keys"
-+ depends on MACH_TS72XX
-+ help
-+ Say 'Y' here to enable GPIO keys on DIO connector.
-+ Current config is KEY_UP for DIO_1 and KEY_DOWN for DIO_2.
- endmenu
-
- endif
-diff --git a/arch/arm/mach-ep93xx/ts72xx.c b/arch/arm/mach-ep93xx/ts72xx.c
-index 0c07bd8..f7b82dd 100644
---- a/arch/arm/mach-ep93xx/ts72xx.c
-+++ b/arch/arm/mach-ep93xx/ts72xx.c
-@@ -21,11 +21,13 @@
- #include <linux/mtd/partitions.h>
- #include <linux/mtd/physmap.h>
- #include <linux/gpio.h>
-+#include <linux/gpio_keys.h>
- #include <linux/i2c.h>
- #include <linux/i2c-gpio.h>
- #include <linux/mtd/nand.h>
- #include <linux/mtd/partitions.h>
- #include <linux/spi/spi.h>
-+#include <linux/input.h>
-
- #include <mach/ep93xx_spi.h>
- #include <mach/hardware.h>
-@@ -437,6 +439,36 @@ static struct ep93xx_spi_info ts72xx_spi_info = {
- };
- #endif
-
-+#if defined(CONFIG_MACH_TS72XX_GPIO_KEYS)
-+#define INIT_KEY(_code, _gpio, _desc) \
-+ { \
-+ .code = KEY_##_code, \
-+ .gpio = _gpio, \
-+ .desc = _desc, \
-+ .wakeup = 1, \
-+ .active_low = 1, \
-+ .type = EV_KEY, \
-+ }
-+
-+static struct gpio_keys_button ts72xx_button_table[] = {
-+ INIT_KEY(UP, EP93XX_GPIO_LINE_EGPIO11, "Up button - DIO_2"),
-+ INIT_KEY(DOWN, EP93XX_GPIO_LINE_EGPIO12, "Down button - DIO_3"),
-+};
-+
-+static struct gpio_keys_platform_data gpio_keys_data = {
-+ .buttons = ts72xx_button_table,
-+ .nbuttons = ARRAY_SIZE(ts72xx_button_table),
-+};
-+
-+static struct platform_device ts72xx_gpio_keys = {
-+ .name = "gpio-keys",
-+ .dev = {
-+ .platform_data = &gpio_keys_data,
-+ },
-+ .id = -1,
-+};
-+#endif
-+
- static void __init ts72xx_init_machine(void)
- {
- ep93xx_init_devices();
-@@ -445,6 +477,10 @@ static void __init ts72xx_init_machine(void)
- platform_device_register(&ts72xx_rtc_device);
- platform_device_register(&ts72xx_wdt_device);
-
-+#if defined(CONFIG_MACH_TS72XX_GPIO_KEYS)
-+ platform_device_register(&ts72xx_gpio_keys);
-+#endif
-+
- ep93xx_register_eth(&ts72xx_eth_data, 1);
- ep93xx_register_i2c(&ts72xx_i2c_gpio_data,
- ts72xx_i2c_board_info,
---
-1.7.0.4
-
diff --git a/recipes/linux/linux-2.6.36/ts72xx/defconfig b/recipes/linux/linux-2.6.36/ts72xx/defconfig
deleted file mode 100644
index 37f95f6..0000000
--- a/recipes/linux/linux-2.6.36/ts72xx/defconfig
+++ /dev/null
@@ -1,2127 +0,0 @@
-#
-# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.36
-# Thu Nov 18 20:05:41 2010
-#
-CONFIG_ARM=y
-CONFIG_SYS_SUPPORTS_APM_EMULATION=y
-CONFIG_GENERIC_GPIO=y
-CONFIG_ARCH_USES_GETTIMEOFFSET=y
-CONFIG_HAVE_PROC_CPU=y
-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_GENERIC_HWEIGHT=y
-CONFIG_GENERIC_CALIBRATE_DELAY=y
-CONFIG_NEED_DMA_MAP_STATE=y
-CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
-CONFIG_VECTORS_BASE=0xffff0000
-CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
-CONFIG_CONSTRUCTORS=y
-
-#
-# General setup
-#
-CONFIG_EXPERIMENTAL=y
-CONFIG_BROKEN_ON_SMP=y
-CONFIG_LOCK_KERNEL=y
-CONFIG_INIT_ENV_ARG_LIMIT=32
-CONFIG_CROSS_COMPILE=""
-CONFIG_LOCALVERSION=""
-# CONFIG_LOCALVERSION_AUTO is not set
-CONFIG_HAVE_KERNEL_GZIP=y
-CONFIG_HAVE_KERNEL_LZMA=y
-CONFIG_HAVE_KERNEL_LZO=y
-CONFIG_KERNEL_GZIP=y
-# CONFIG_KERNEL_LZMA is not set
-# CONFIG_KERNEL_LZO is not set
-CONFIG_SWAP=y
-CONFIG_SYSVIPC=y
-CONFIG_SYSVIPC_SYSCTL=y
-CONFIG_POSIX_MQUEUE=y
-CONFIG_POSIX_MQUEUE_SYSCTL=y
-# CONFIG_BSD_PROCESS_ACCT is not set
-# CONFIG_TASKSTATS is not set
-# CONFIG_AUDIT is not set
-
-#
-# RCU Subsystem
-#
-CONFIG_TREE_RCU=y
-# CONFIG_TREE_PREEMPT_RCU is not set
-# CONFIG_TINY_RCU is not set
-# CONFIG_RCU_TRACE is not set
-CONFIG_RCU_FANOUT=32
-# CONFIG_RCU_FANOUT_EXACT is not set
-# CONFIG_TREE_RCU_TRACE is not set
-CONFIG_IKCONFIG=y
-CONFIG_IKCONFIG_PROC=y
-CONFIG_LOG_BUF_SHIFT=16
-# CONFIG_CGROUPS is not set
-# CONFIG_SYSFS_DEPRECATED_V2 is not set
-CONFIG_RELAY=y
-CONFIG_NAMESPACES=y
-# CONFIG_UTS_NS is not set
-CONFIG_IPC_NS=y
-# CONFIG_USER_NS is not set
-# CONFIG_PID_NS is not set
-# CONFIG_NET_NS is not set
-# CONFIG_BLK_DEV_INITRD is not set
-# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-CONFIG_SYSCTL=y
-CONFIG_ANON_INODES=y
-CONFIG_EMBEDDED=y
-CONFIG_UID16=y
-CONFIG_SYSCTL_SYSCALL=y
-CONFIG_KALLSYMS=y
-# CONFIG_KALLSYMS_EXTRA_PASS is not set
-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_HAVE_PERF_EVENTS=y
-CONFIG_PERF_USE_VMALLOC=y
-
-#
-# Kernel Performance Events And Counters
-#
-# CONFIG_PERF_EVENTS is not set
-# CONFIG_PERF_COUNTERS is not set
-CONFIG_VM_EVENT_COUNTERS=y
-# CONFIG_COMPAT_BRK is not set
-CONFIG_SLAB=y
-# CONFIG_SLUB is not set
-# CONFIG_SLOB is not set
-# CONFIG_PROFILING is not set
-CONFIG_HAVE_OPROFILE=y
-# CONFIG_KPROBES is not set
-CONFIG_HAVE_KPROBES=y
-CONFIG_HAVE_KRETPROBES=y
-CONFIG_HAVE_REGS_AND_STACK_ACCESS_API=y
-CONFIG_HAVE_CLK=y
-
-#
-# GCOV-based kernel profiling
-#
-CONFIG_HAVE_GENERIC_DMA_COHERENT=y
-CONFIG_SLABINFO=y
-CONFIG_RT_MUTEXES=y
-CONFIG_BASE_SMALL=0
-CONFIG_MODULES=y
-# CONFIG_MODULE_FORCE_LOAD is not set
-CONFIG_MODULE_UNLOAD=y
-CONFIG_MODULE_FORCE_UNLOAD=y
-CONFIG_MODVERSIONS=y
-# CONFIG_MODULE_SRCVERSION_ALL is not set
-CONFIG_BLOCK=y
-CONFIG_LBDAF=y
-CONFIG_BLK_DEV_BSG=y
-# CONFIG_BLK_DEV_INTEGRITY is not set
-
-#
-# IO Schedulers
-#
-CONFIG_IOSCHED_NOOP=y
-CONFIG_IOSCHED_DEADLINE=m
-CONFIG_IOSCHED_CFQ=y
-CONFIG_DEFAULT_CFQ=y
-# CONFIG_DEFAULT_NOOP is not set
-CONFIG_DEFAULT_IOSCHED="cfq"
-# CONFIG_INLINE_SPIN_TRYLOCK is not set
-# CONFIG_INLINE_SPIN_TRYLOCK_BH is not set
-# CONFIG_INLINE_SPIN_LOCK is not set
-# CONFIG_INLINE_SPIN_LOCK_BH is not set
-# CONFIG_INLINE_SPIN_LOCK_IRQ is not set
-# CONFIG_INLINE_SPIN_LOCK_IRQSAVE is not set
-# CONFIG_INLINE_SPIN_UNLOCK is not set
-# CONFIG_INLINE_SPIN_UNLOCK_BH is not set
-# CONFIG_INLINE_SPIN_UNLOCK_IRQ is not set
-# CONFIG_INLINE_SPIN_UNLOCK_IRQRESTORE is not set
-# CONFIG_INLINE_READ_TRYLOCK is not set
-# CONFIG_INLINE_READ_LOCK is not set
-# CONFIG_INLINE_READ_LOCK_BH is not set
-# CONFIG_INLINE_READ_LOCK_IRQ is not set
-# CONFIG_INLINE_READ_LOCK_IRQSAVE is not set
-# CONFIG_INLINE_READ_UNLOCK is not set
-# CONFIG_INLINE_READ_UNLOCK_BH is not set
-# CONFIG_INLINE_READ_UNLOCK_IRQ is not set
-# CONFIG_INLINE_READ_UNLOCK_IRQRESTORE is not set
-# CONFIG_INLINE_WRITE_TRYLOCK is not set
-# CONFIG_INLINE_WRITE_LOCK is not set
-# CONFIG_INLINE_WRITE_LOCK_BH is not set
-# CONFIG_INLINE_WRITE_LOCK_IRQ is not set
-# CONFIG_INLINE_WRITE_LOCK_IRQSAVE is not set
-# CONFIG_INLINE_WRITE_UNLOCK is not set
-# CONFIG_INLINE_WRITE_UNLOCK_BH is not set
-# CONFIG_INLINE_WRITE_UNLOCK_IRQ is not set
-# CONFIG_INLINE_WRITE_UNLOCK_IRQRESTORE is not set
-# CONFIG_MUTEX_SPIN_ON_OWNER is not set
-# CONFIG_FREEZER is not set
-
-#
-# System Type
-#
-CONFIG_MMU=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_VEXPRESS is not set
-# CONFIG_ARCH_AT91 is not set
-# CONFIG_ARCH_BCMRING is not set
-# CONFIG_ARCH_CLPS711X is not set
-# CONFIG_ARCH_CNS3XXX is not set
-# CONFIG_ARCH_GEMINI is not set
-# CONFIG_ARCH_EBSA110 is not set
-CONFIG_ARCH_EP93XX=y
-# CONFIG_ARCH_FOOTBRIDGE is not set
-# CONFIG_ARCH_MXC is not set
-# CONFIG_ARCH_STMP3XXX is not set
-# CONFIG_ARCH_NETX is not set
-# CONFIG_ARCH_H720X 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_DOVE is not set
-# CONFIG_ARCH_KIRKWOOD is not set
-# CONFIG_ARCH_LOKI is not set
-# CONFIG_ARCH_LPC32XX is not set
-# CONFIG_ARCH_MV78XX0 is not set
-# CONFIG_ARCH_ORION5X is not set
-# CONFIG_ARCH_MMP is not set
-# CONFIG_ARCH_KS8695 is not set
-# CONFIG_ARCH_NS9XXX is not set
-# CONFIG_ARCH_W90X900 is not set
-# CONFIG_ARCH_NUC93X is not set
-# CONFIG_ARCH_TEGRA is not set
-# CONFIG_ARCH_PNX4008 is not set
-# CONFIG_ARCH_PXA is not set
-# CONFIG_ARCH_MSM is not set
-# CONFIG_ARCH_SHMOBILE is not set
-# CONFIG_ARCH_RPC is not set
-# CONFIG_ARCH_SA1100 is not set
-# CONFIG_ARCH_S3C2410 is not set
-# CONFIG_ARCH_S3C64XX is not set
-# CONFIG_ARCH_S5P6440 is not set
-# CONFIG_ARCH_S5P6442 is not set
-# CONFIG_ARCH_S5PC100 is not set
-# CONFIG_ARCH_S5PV210 is not set
-# CONFIG_ARCH_S5PV310 is not set
-# CONFIG_ARCH_SHARK is not set
-# CONFIG_ARCH_LH7A40X is not set
-# CONFIG_ARCH_U300 is not set
-# CONFIG_ARCH_U8500 is not set
-# CONFIG_ARCH_NOMADIK is not set
-# CONFIG_ARCH_DAVINCI is not set
-# CONFIG_ARCH_OMAP is not set
-# CONFIG_PLAT_SPEAR is not set
-
-#
-# Cirrus EP93xx Implementation Options
-#
-# CONFIG_CRUNCH is not set
-CONFIG_CR1_NFBIT=y
-
-#
-# EP93xx Platforms
-#
-CONFIG_EP93XX_SDCE3_SYNC_PHYS_OFFSET=y
-# CONFIG_EP93XX_SDCE0_PHYS_OFFSET is not set
-# CONFIG_EP93XX_SDCE1_PHYS_OFFSET is not set
-# CONFIG_EP93XX_SDCE2_PHYS_OFFSET is not set
-# CONFIG_EP93XX_SDCE3_ASYNC_PHYS_OFFSET is not set
-# CONFIG_MACH_ADSSPHERE is not set
-# CONFIG_MACH_EDB9301 is not set
-# CONFIG_MACH_EDB9302 is not set
-# CONFIG_MACH_EDB9307 is not set
-# CONFIG_MACH_EDB9312 is not set
-# CONFIG_MACH_EDB9315 is not set
-# CONFIG_MACH_GESBC9312 is not set
-# CONFIG_MACH_MICRO9H is not set
-# CONFIG_MACH_MICRO9L is not set
-CONFIG_MACH_TS72XX=y
-CONFIG_EP93XX_EARLY_UART1=y
-# CONFIG_EP93XX_EARLY_UART2 is not set
-# CONFIG_EP93XX_EARLY_UART3 is not set
-CONFIG_MACH_TS72XX_FORCE_MACHINEID=y
-CONFIG_MACH_TS72XX_SBCINFO=m
-CONFIG_MACH_TS72XX_GPIO_KEYS=y
-
-#
-# Processor Type
-#
-CONFIG_CPU_ARM920T=y
-CONFIG_CPU_32v4T=y
-CONFIG_CPU_ABRT_EV4T=y
-CONFIG_CPU_PABRT_LEGACY=y
-CONFIG_CPU_CACHE_V4WT=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_ARM_L1_CACHE_SHIFT=5
-CONFIG_ARM_VIC=y
-CONFIG_ARM_VIC_NR=2
-CONFIG_COMMON_CLKDEV=y
-
-#
-# 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_NONE is not set
-# CONFIG_PREEMPT_VOLUNTARY is not set
-CONFIG_PREEMPT=y
-CONFIG_HZ=100
-CONFIG_AEABI=y
-# CONFIG_OABI_COMPAT is not set
-CONFIG_ARCH_HAS_HOLES_MEMORYMODEL=y
-CONFIG_ARCH_SPARSEMEM_ENABLE=y
-CONFIG_ARCH_SPARSEMEM_DEFAULT=y
-CONFIG_ARCH_SELECT_MEMORY_MODEL=y
-# CONFIG_HIGHMEM is not set
-# CONFIG_SPARSE_IRQ is not set
-CONFIG_SELECT_MEMORY_MODEL=y
-CONFIG_SPARSEMEM_MANUAL=y
-CONFIG_SPARSEMEM=y
-CONFIG_HAVE_MEMORY_PRESENT=y
-CONFIG_SPARSEMEM_EXTREME=y
-CONFIG_HAVE_MEMBLOCK=y
-CONFIG_SPLIT_PTLOCK_CPUS=999999
-# CONFIG_PHYS_ADDR_T_64BIT is not set
-CONFIG_ZONE_DMA_FLAG=0
-CONFIG_VIRT_TO_BUS=y
-# CONFIG_KSM is not set
-CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
-CONFIG_FORCE_MAX_ZONEORDER=11
-CONFIG_ALIGNMENT_TRAP=y
-# CONFIG_UACCESS_WITH_MEMCPY is not set
-# CONFIG_CC_STACKPROTECTOR is not set
-# CONFIG_DEPRECATED_PARAM_STRUCT is not set
-
-#
-# Boot options
-#
-CONFIG_ZBOOT_ROM_TEXT=0
-CONFIG_ZBOOT_ROM_BSS=0
-CONFIG_CMDLINE=" debug "
-# CONFIG_CMDLINE_FORCE is not set
-# CONFIG_XIP_KERNEL is not set
-CONFIG_KEXEC=y
-CONFIG_ATAGS_PROC=y
-# CONFIG_AUTO_ZRELADDR is not set
-
-#
-# CPU Power Management
-#
-# CONFIG_CPU_IDLE is not set
-
-#
-# Floating point emulation
-#
-
-#
-# At least one emulation must be selected
-#
-
-#
-# Userspace binary formats
-#
-CONFIG_BINFMT_ELF=y
-# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
-CONFIG_HAVE_AOUT=y
-# CONFIG_BINFMT_AOUT is not set
-CONFIG_BINFMT_MISC=m
-
-#
-# Power management options
-#
-# CONFIG_PM is not set
-CONFIG_ARCH_SUSPEND_POSSIBLE=y
-CONFIG_NET=y
-
-#
-# Networking options
-#
-CONFIG_PACKET=y
-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=m
-# CONFIG_NET_KEY_MIGRATE is not set
-CONFIG_INET=y
-# CONFIG_IP_MULTICAST is not set
-CONFIG_IP_ADVANCED_ROUTER=y
-CONFIG_ASK_IP_FIB_HASH=y
-# CONFIG_IP_FIB_TRIE is not set
-CONFIG_IP_FIB_HASH=y
-# CONFIG_IP_MULTIPLE_TABLES is not set
-# CONFIG_IP_ROUTE_MULTIPATH is not set
-CONFIG_IP_ROUTE_VERBOSE=y
-CONFIG_IP_PNP=y
-CONFIG_IP_PNP_DHCP=y
-# CONFIG_IP_PNP_BOOTP is not set
-# CONFIG_IP_PNP_RARP is not set
-CONFIG_NET_IPIP=m
-CONFIG_NET_IPGRE=m
-# CONFIG_ARPD is not set
-CONFIG_SYN_COOKIES=y
-CONFIG_INET_AH=m
-CONFIG_INET_ESP=m
-CONFIG_INET_IPCOMP=m
-CONFIG_INET_XFRM_TUNNEL=m
-CONFIG_INET_TUNNEL=m
-CONFIG_INET_XFRM_MODE_TRANSPORT=m
-CONFIG_INET_XFRM_MODE_TUNNEL=m
-CONFIG_INET_XFRM_MODE_BEET=m
-# CONFIG_INET_LRO is not set
-# CONFIG_INET_DIAG is not set
-# 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 is not set
-CONFIG_IPV6_SIT=m
-# CONFIG_IPV6_SIT_6RD is not set
-CONFIG_IPV6_NDISC_NODETYPE=y
-CONFIG_IPV6_TUNNEL=m
-# CONFIG_IPV6_MULTIPLE_TABLES is not set
-# CONFIG_IPV6_MROUTE is not set
-# CONFIG_NETLABEL is not set
-CONFIG_NETWORK_SECMARK=y
-# CONFIG_NETWORK_PHY_TIMESTAMPING is not set
-CONFIG_NETFILTER=y
-# CONFIG_NETFILTER_DEBUG is not set
-CONFIG_NETFILTER_ADVANCED=y
-
-#
-# Core Netfilter Configuration
-#
-CONFIG_NETFILTER_NETLINK=m
-CONFIG_NETFILTER_NETLINK_QUEUE=m
-CONFIG_NETFILTER_NETLINK_LOG=m
-CONFIG_NF_CONNTRACK=m
-CONFIG_NF_CONNTRACK_MARK=y
-CONFIG_NF_CONNTRACK_SECMARK=y
-CONFIG_NF_CONNTRACK_ZONES=y
-CONFIG_NF_CONNTRACK_EVENTS=y
-CONFIG_NF_CT_PROTO_DCCP=m
-CONFIG_NF_CT_PROTO_GRE=m
-CONFIG_NF_CT_PROTO_SCTP=m
-CONFIG_NF_CT_PROTO_UDPLITE=m
-CONFIG_NF_CONNTRACK_AMANDA=m
-CONFIG_NF_CONNTRACK_FTP=m
-CONFIG_NF_CONNTRACK_H323=m
-CONFIG_NF_CONNTRACK_IRC=m
-CONFIG_NF_CONNTRACK_NETBIOS_NS=m
-CONFIG_NF_CONNTRACK_PPTP=m
-CONFIG_NF_CONNTRACK_SANE=m
-CONFIG_NF_CONNTRACK_SIP=m
-CONFIG_NF_CONNTRACK_TFTP=m
-CONFIG_NF_CT_NETLINK=m
-# CONFIG_NETFILTER_TPROXY is not set
-CONFIG_NETFILTER_XTABLES=m
-
-#
-# Xtables combined modules
-#
-CONFIG_NETFILTER_XT_MARK=m
-CONFIG_NETFILTER_XT_CONNMARK=m
-
-#
-# Xtables targets
-#
-# CONFIG_NETFILTER_XT_TARGET_CHECKSUM is not set
-CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m
-CONFIG_NETFILTER_XT_TARGET_CONNMARK=m
-CONFIG_NETFILTER_XT_TARGET_CONNSECMARK=m
-CONFIG_NETFILTER_XT_TARGET_CT=m
-CONFIG_NETFILTER_XT_TARGET_DSCP=m
-CONFIG_NETFILTER_XT_TARGET_HL=m
-# CONFIG_NETFILTER_XT_TARGET_IDLETIMER is not set
-CONFIG_NETFILTER_XT_TARGET_LED=m
-CONFIG_NETFILTER_XT_TARGET_MARK=m
-CONFIG_NETFILTER_XT_TARGET_NFLOG=m
-CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m
-CONFIG_NETFILTER_XT_TARGET_NOTRACK=m
-CONFIG_NETFILTER_XT_TARGET_RATEEST=m
-# CONFIG_NETFILTER_XT_TARGET_TEE is not set
-CONFIG_NETFILTER_XT_TARGET_TRACE=m
-CONFIG_NETFILTER_XT_TARGET_SECMARK=m
-CONFIG_NETFILTER_XT_TARGET_TCPMSS=m
-CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP=m
-
-#
-# Xtables matches
-#
-CONFIG_NETFILTER_XT_MATCH_CLUSTER=m
-CONFIG_NETFILTER_XT_MATCH_COMMENT=m
-CONFIG_NETFILTER_XT_MATCH_CONNBYTES=m
-CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=m
-CONFIG_NETFILTER_XT_MATCH_CONNMARK=m
-CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m
-# CONFIG_NETFILTER_XT_MATCH_CPU is not set
-CONFIG_NETFILTER_XT_MATCH_DCCP=m
-CONFIG_NETFILTER_XT_MATCH_DSCP=m
-CONFIG_NETFILTER_XT_MATCH_ESP=m
-CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=m
-CONFIG_NETFILTER_XT_MATCH_HELPER=m
-CONFIG_NETFILTER_XT_MATCH_HL=m
-CONFIG_NETFILTER_XT_MATCH_IPRANGE=m
-CONFIG_NETFILTER_XT_MATCH_LENGTH=m
-CONFIG_NETFILTER_XT_MATCH_LIMIT=m
-CONFIG_NETFILTER_XT_MATCH_MAC=m
-CONFIG_NETFILTER_XT_MATCH_MARK=m
-CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m
-CONFIG_NETFILTER_XT_MATCH_OSF=m
-CONFIG_NETFILTER_XT_MATCH_OWNER=m
-CONFIG_NETFILTER_XT_MATCH_POLICY=m
-CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m
-CONFIG_NETFILTER_XT_MATCH_QUOTA=m
-CONFIG_NETFILTER_XT_MATCH_RATEEST=m
-CONFIG_NETFILTER_XT_MATCH_REALM=m
-CONFIG_NETFILTER_XT_MATCH_RECENT=m
-CONFIG_NETFILTER_XT_MATCH_SCTP=m
-CONFIG_NETFILTER_XT_MATCH_STATE=m
-CONFIG_NETFILTER_XT_MATCH_STATISTIC=m
-CONFIG_NETFILTER_XT_MATCH_STRING=m
-CONFIG_NETFILTER_XT_MATCH_TCPMSS=m
-CONFIG_NETFILTER_XT_MATCH_TIME=m
-CONFIG_NETFILTER_XT_MATCH_U32=m
-# CONFIG_IP_VS is not set
-
-#
-# IP: Netfilter Configuration
-#
-CONFIG_NF_DEFRAG_IPV4=m
-CONFIG_NF_CONNTRACK_IPV4=m
-CONFIG_NF_CONNTRACK_PROC_COMPAT=y
-CONFIG_IP_NF_QUEUE=m
-CONFIG_IP_NF_IPTABLES=m
-CONFIG_IP_NF_MATCH_ADDRTYPE=m
-CONFIG_IP_NF_MATCH_AH=m
-CONFIG_IP_NF_MATCH_ECN=m
-CONFIG_IP_NF_MATCH_TTL=m
-CONFIG_IP_NF_FILTER=m
-CONFIG_IP_NF_TARGET_REJECT=m
-CONFIG_IP_NF_TARGET_LOG=m
-CONFIG_IP_NF_TARGET_ULOG=m
-CONFIG_NF_NAT=m
-CONFIG_NF_NAT_NEEDED=y
-CONFIG_IP_NF_TARGET_MASQUERADE=m
-CONFIG_IP_NF_TARGET_NETMAP=m
-CONFIG_IP_NF_TARGET_REDIRECT=m
-CONFIG_NF_NAT_SNMP_BASIC=m
-CONFIG_NF_NAT_PROTO_DCCP=m
-CONFIG_NF_NAT_PROTO_GRE=m
-CONFIG_NF_NAT_PROTO_UDPLITE=m
-CONFIG_NF_NAT_PROTO_SCTP=m
-CONFIG_NF_NAT_FTP=m
-CONFIG_NF_NAT_IRC=m
-CONFIG_NF_NAT_TFTP=m
-CONFIG_NF_NAT_AMANDA=m
-CONFIG_NF_NAT_PPTP=m
-CONFIG_NF_NAT_H323=m
-CONFIG_NF_NAT_SIP=m
-CONFIG_IP_NF_MANGLE=m
-CONFIG_IP_NF_TARGET_CLUSTERIP=m
-CONFIG_IP_NF_TARGET_ECN=m
-CONFIG_IP_NF_TARGET_TTL=m
-CONFIG_IP_NF_RAW=m
-CONFIG_IP_NF_SECURITY=m
-CONFIG_IP_NF_ARPTABLES=m
-CONFIG_IP_NF_ARPFILTER=m
-CONFIG_IP_NF_ARP_MANGLE=m
-
-#
-# IPv6: Netfilter Configuration
-#
-CONFIG_NF_CONNTRACK_IPV6=m
-CONFIG_IP6_NF_QUEUE=m
-CONFIG_IP6_NF_IPTABLES=m
-CONFIG_IP6_NF_MATCH_AH=m
-CONFIG_IP6_NF_MATCH_EUI64=m
-CONFIG_IP6_NF_MATCH_FRAG=m
-CONFIG_IP6_NF_MATCH_OPTS=m
-CONFIG_IP6_NF_MATCH_HL=m
-CONFIG_IP6_NF_MATCH_IPV6HEADER=m
-CONFIG_IP6_NF_MATCH_MH=m
-CONFIG_IP6_NF_MATCH_RT=m
-CONFIG_IP6_NF_TARGET_HL=m
-CONFIG_IP6_NF_TARGET_LOG=m
-CONFIG_IP6_NF_FILTER=m
-CONFIG_IP6_NF_TARGET_REJECT=m
-CONFIG_IP6_NF_MANGLE=m
-CONFIG_IP6_NF_RAW=m
-CONFIG_IP6_NF_SECURITY=m
-# CONFIG_IP_DCCP is not set
-# CONFIG_IP_SCTP is not set
-# CONFIG_RDS is not set
-# CONFIG_TIPC is not set
-# CONFIG_ATM is not set
-# CONFIG_L2TP 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 is not set
-# CONFIG_PHONET is not set
-# CONFIG_IEEE802154 is not set
-# CONFIG_NET_SCHED is not set
-CONFIG_NET_CLS_ROUTE=y
-# CONFIG_DCB is not set
-CONFIG_DNS_RESOLVER=y
-
-#
-# 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_WIRELESS=y
-CONFIG_WIRELESS_EXT=y
-CONFIG_WEXT_CORE=y
-CONFIG_WEXT_PROC=y
-CONFIG_WEXT_SPY=y
-CONFIG_WEXT_PRIV=y
-CONFIG_CFG80211=m
-# CONFIG_NL80211_TESTMODE is not set
-# CONFIG_CFG80211_DEVELOPER_WARNINGS is not set
-# CONFIG_CFG80211_REG_DEBUG is not set
-CONFIG_CFG80211_DEFAULT_PS=y
-# CONFIG_CFG80211_INTERNAL_REGDB is not set
-CONFIG_CFG80211_WEXT=y
-CONFIG_WIRELESS_EXT_SYSFS=y
-CONFIG_LIB80211=m
-CONFIG_LIB80211_CRYPT_WEP=m
-CONFIG_LIB80211_CRYPT_CCMP=m
-CONFIG_LIB80211_CRYPT_TKIP=m
-# CONFIG_LIB80211_DEBUG is not set
-CONFIG_MAC80211=m
-CONFIG_MAC80211_HAS_RC=y
-CONFIG_MAC80211_RC_PID=y
-# CONFIG_MAC80211_RC_MINSTREL is not set
-CONFIG_MAC80211_RC_DEFAULT_PID=y
-CONFIG_MAC80211_RC_DEFAULT="pid"
-# CONFIG_MAC80211_MESH is not set
-CONFIG_MAC80211_LEDS=y
-# CONFIG_MAC80211_DEBUG_MENU is not set
-# CONFIG_WIMAX is not set
-# CONFIG_RFKILL is not set
-# CONFIG_NET_9P is not set
-# CONFIG_CAIF is not set
-
-#
-# Device Drivers
-#
-
-#
-# Generic Driver Options
-#
-CONFIG_UEVENT_HELPER_PATH=""
-CONFIG_DEVTMPFS=y
-CONFIG_DEVTMPFS_MOUNT=y
-CONFIG_STANDALONE=y
-CONFIG_PREVENT_FIRMWARE_BUILD=y
-CONFIG_FW_LOADER=m
-CONFIG_FIRMWARE_IN_KERNEL=y
-CONFIG_EXTRA_FIRMWARE=""
-# CONFIG_SYS_HYPERVISOR is not set
-CONFIG_CONNECTOR=m
-CONFIG_MTD=y
-# CONFIG_MTD_DEBUG is not set
-# CONFIG_MTD_TESTS is not set
-# CONFIG_MTD_CONCAT is not set
-CONFIG_MTD_PARTITIONS=y
-CONFIG_MTD_REDBOOT_PARTS=y
-CONFIG_MTD_REDBOOT_DIRECTORY_BLOCK=-1
-# CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED is not set
-# CONFIG_MTD_REDBOOT_PARTS_READONLY 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_SM_FTL 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 is not set
-# CONFIG_MTD_M25P80 is not set
-# CONFIG_MTD_SST25L is not set
-# 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_ECC=y
-# CONFIG_MTD_NAND_ECC_SMC is not set
-CONFIG_MTD_NAND=y
-# CONFIG_MTD_NAND_VERIFY_WRITE is not set
-# CONFIG_MTD_SM_COMMON is not set
-# CONFIG_MTD_NAND_MUSEUM_IDS is not set
-# 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=y
-# CONFIG_MTD_ALAUDA is not set
-# CONFIG_MTD_ONENAND is not set
-
-#
-# LPDDR flash memory drivers
-#
-# CONFIG_MTD_LPDDR is not set
-
-#
-# UBI - Unsorted block images
-#
-CONFIG_MTD_UBI=y
-CONFIG_MTD_UBI_WL_THRESHOLD=4096
-CONFIG_MTD_UBI_BEB_RESERVE=1
-# CONFIG_MTD_UBI_GLUEBI is not set
-
-#
-# UBI debugging options
-#
-# CONFIG_MTD_UBI_DEBUG 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=m
-# CONFIG_BLK_DEV_DRBD is not set
-CONFIG_BLK_DEV_NBD=m
-# CONFIG_BLK_DEV_UB is not set
-CONFIG_BLK_DEV_RAM=m
-CONFIG_BLK_DEV_RAM_COUNT=16
-CONFIG_BLK_DEV_RAM_SIZE=65536
-# CONFIG_BLK_DEV_XIP is not set
-# CONFIG_CDROM_PKTCDVD is not set
-# CONFIG_ATA_OVER_ETH is not set
-# CONFIG_MG_DISK is not set
-CONFIG_BLK_DEV_TS72XX_SDCARD=y
-CONFIG_MISC_DEVICES=y
-# CONFIG_AD525X_DPOT is not set
-# CONFIG_ICS932S401 is not set
-# CONFIG_ENCLOSURE_SERVICES is not set
-# CONFIG_ISL29003 is not set
-# CONFIG_SENSORS_TSL2550 is not set
-# CONFIG_SENSORS_BH1780 is not set
-# CONFIG_HMC6352 is not set
-CONFIG_EP93XX_PWM=m
-# CONFIG_DS1682 is not set
-# CONFIG_TI_DAC7512 is not set
-# CONFIG_BMP085 is not set
-# CONFIG_C2PORT is not set
-
-#
-# EEPROM support
-#
-# CONFIG_EEPROM_AT24 is not set
-# CONFIG_EEPROM_AT25 is not set
-# CONFIG_EEPROM_LEGACY is not set
-# CONFIG_EEPROM_MAX6875 is not set
-CONFIG_EEPROM_93CX6=m
-# CONFIG_IWMC3200TOP is not set
-CONFIG_TS72XX_MAX197=m
-CONFIG_TS72XX_MAX197_AVERAGE=y
-CONFIG_HAVE_IDE=y
-# CONFIG_IDE is not set
-
-#
-# SCSI device support
-#
-CONFIG_SCSI_MOD=m
-# CONFIG_RAID_ATTRS is not set
-CONFIG_SCSI=m
-CONFIG_SCSI_DMA=y
-CONFIG_SCSI_TGT=m
-# CONFIG_SCSI_NETLINK is not set
-CONFIG_SCSI_PROC_FS=y
-
-#
-# SCSI support type (disk, tape, CD-ROM)
-#
-CONFIG_BLK_DEV_SD=m
-# 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=m
-# CONFIG_CHR_DEV_SCH is not set
-# CONFIG_SCSI_MULTI_LUN is not set
-# CONFIG_SCSI_CONSTANTS is not set
-# CONFIG_SCSI_LOGGING is not set
-# CONFIG_SCSI_SCAN_ASYNC is not set
-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 is not set
-# CONFIG_SCSI_SAS_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_SCSI_OSD_INITIATOR is not set
-CONFIG_ATA=m
-# CONFIG_ATA_NONSTANDARD is not set
-# CONFIG_ATA_VERBOSE_ERROR is not set
-# CONFIG_SATA_PMP is not set
-
-#
-# Controllers with non-SFF native interface
-#
-# CONFIG_SATA_AHCI_PLATFORM is not set
-CONFIG_ATA_SFF=y
-
-#
-# SFF controllers with custom DMA interface
-#
-CONFIG_ATA_BMDMA=y
-
-#
-# SATA SFF controllers with BMDMA
-#
-# CONFIG_SATA_MV is not set
-
-#
-# PATA SFF controllers with BMDMA
-#
-
-#
-# PIO-only SFF controllers
-#
-# CONFIG_PATA_PLATFORM is not set
-
-#
-# Generic fallback / legacy drivers
-#
-CONFIG_PATA_TS72XX=y
-CONFIG_PATA_TS7200_CF=m
-CONFIG_PATA_TS9600=m
-# 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_PHYLIB=y
-
-#
-# MII PHY device drivers
-#
-# CONFIG_MARVELL_PHY is not set
-# CONFIG_DAVICOM_PHY is not set
-# CONFIG_QSEMI_PHY is not set
-# CONFIG_LXT_PHY is not set
-# CONFIG_CICADA_PHY is not set
-# CONFIG_VITESSE_PHY is not set
-# CONFIG_SMSC_PHY is not set
-# CONFIG_BROADCOM_PHY is not set
-# CONFIG_ICPLUS_PHY is not set
-# CONFIG_REALTEK_PHY is not set
-# CONFIG_NATIONAL_PHY is not set
-# CONFIG_STE10XP is not set
-# CONFIG_LSI_ET1011C_PHY is not set
-# CONFIG_MICREL_PHY is not set
-# CONFIG_FIXED_PHY is not set
-# CONFIG_MDIO_BITBANG is not set
-CONFIG_NET_ETHERNET=y
-CONFIG_MII=y
-CONFIG_EP93XX_ETH=y
-CONFIG_AX88796=m
-CONFIG_AX88796_93CX6=y
-CONFIG_AX88796_TS_ETH100=m
-# CONFIG_SMC91X is not set
-# CONFIG_DM9000 is not set
-# CONFIG_ENC28J60 is not set
-CONFIG_ETHOC=m
-# CONFIG_SMC911X is not set
-# CONFIG_SMSC911X is not set
-# CONFIG_DNET is not set
-# CONFIG_IBM_NEW_EMAC_ZMII is not set
-# CONFIG_IBM_NEW_EMAC_RGMII is not set
-# CONFIG_IBM_NEW_EMAC_TAH is not set
-# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
-# CONFIG_IBM_NEW_EMAC_NO_FLOW_CTRL is not set
-# CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set
-# CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
-# CONFIG_B44 is not set
-# CONFIG_KS8851 is not set
-# CONFIG_KS8851_MLL is not set
-# CONFIG_NETDEV_1000 is not set
-# CONFIG_NETDEV_10000 is not set
-CONFIG_WLAN=y
-CONFIG_LIBERTAS_THINFIRM=m
-# CONFIG_LIBERTAS_THINFIRM_DEBUG is not set
-CONFIG_LIBERTAS_THINFIRM_USB=m
-CONFIG_AT76C50X_USB=m
-CONFIG_USB_ZD1201=m
-CONFIG_USB_NET_RNDIS_WLAN=m
-CONFIG_RTL8187=m
-CONFIG_RTL8187_LEDS=y
-CONFIG_MAC80211_HWSIM=m
-CONFIG_ATH_COMMON=m
-# CONFIG_ATH_DEBUG is not set
-CONFIG_ATH9K_HW=m
-CONFIG_ATH9K_COMMON=m
-CONFIG_ATH9K_HTC=m
-CONFIG_AR9170_USB=m
-CONFIG_AR9170_LEDS=y
-CONFIG_B43=m
-# CONFIG_B43_SDIO is not set
-CONFIG_B43_PIO=y
-CONFIG_B43_PHY_LP=y
-CONFIG_B43_LEDS=y
-CONFIG_B43_HWRNG=y
-# CONFIG_B43_DEBUG is not set
-CONFIG_B43LEGACY=m
-CONFIG_B43LEGACY_LEDS=y
-CONFIG_B43LEGACY_HWRNG=y
-CONFIG_B43LEGACY_DEBUG=y
-CONFIG_B43LEGACY_DMA=y
-CONFIG_B43LEGACY_PIO=y
-CONFIG_B43LEGACY_DMA_AND_PIO_MODE=y
-# CONFIG_B43LEGACY_DMA_MODE is not set
-# CONFIG_B43LEGACY_PIO_MODE is not set
-CONFIG_HOSTAP=m
-# CONFIG_HOSTAP_FIRMWARE is not set
-# CONFIG_IWM is not set
-CONFIG_LIBERTAS=m
-CONFIG_LIBERTAS_USB=m
-# CONFIG_LIBERTAS_SDIO is not set
-# CONFIG_LIBERTAS_SPI is not set
-# CONFIG_LIBERTAS_DEBUG is not set
-# CONFIG_LIBERTAS_MESH is not set
-CONFIG_P54_COMMON=m
-CONFIG_P54_USB=m
-# CONFIG_P54_SPI is not set
-CONFIG_P54_LEDS=y
-CONFIG_RT2X00=m
-CONFIG_RT2500USB=m
-CONFIG_RT73USB=m
-CONFIG_RT2800USB=m
-# CONFIG_RT2800USB_RT30XX is not set
-# CONFIG_RT2800USB_RT35XX is not set
-# CONFIG_RT2800USB_UNKNOWN is not set
-CONFIG_RT2800_LIB=m
-CONFIG_RT2X00_LIB_USB=m
-CONFIG_RT2X00_LIB=m
-CONFIG_RT2X00_LIB_HT=y
-CONFIG_RT2X00_LIB_FIRMWARE=y
-CONFIG_RT2X00_LIB_CRYPTO=y
-CONFIG_RT2X00_LIB_LEDS=y
-# CONFIG_RT2X00_DEBUG is not set
-CONFIG_WL12XX=m
-# CONFIG_WL1251 is not set
-# CONFIG_WL1271 is not set
-CONFIG_ZD1211RW=m
-# CONFIG_ZD1211RW_DEBUG is not set
-
-#
-# Enable WiMAX (Networking options) to see the WiMAX drivers
-#
-
-#
-# USB Network Adapters
-#
-CONFIG_USB_CATC=m
-CONFIG_USB_KAWETH=m
-CONFIG_USB_PEGASUS=m
-CONFIG_USB_RTL8150=m
-CONFIG_USB_USBNET=m
-CONFIG_USB_NET_AX8817X=m
-CONFIG_USB_NET_CDCETHER=m
-CONFIG_USB_NET_CDC_EEM=m
-CONFIG_USB_NET_DM9601=m
-CONFIG_USB_NET_SMSC75XX=m
-CONFIG_USB_NET_SMSC95XX=m
-CONFIG_USB_NET_GL620A=m
-CONFIG_USB_NET_NET1080=m
-CONFIG_USB_NET_PLUSB=m
-CONFIG_USB_NET_MCS7830=m
-CONFIG_USB_NET_RNDIS_HOST=m
-CONFIG_USB_NET_CDC_SUBSET=m
-CONFIG_USB_ALI_M5632=y
-CONFIG_USB_AN2720=y
-CONFIG_USB_BELKIN=y
-CONFIG_USB_ARMLINUX=y
-CONFIG_USB_EPSON2888=y
-CONFIG_USB_KC2190=y
-CONFIG_USB_NET_ZAURUS=m
-CONFIG_USB_NET_INT51X1=m
-CONFIG_USB_IPHETH=m
-CONFIG_USB_SIERRA_NET=m
-# CONFIG_WAN is not set
-
-#
-# CAIF transport drivers
-#
-CONFIG_PPP=m
-CONFIG_PPP_MULTILINK=y
-CONFIG_PPP_FILTER=y
-CONFIG_PPP_ASYNC=m
-CONFIG_PPP_SYNC_TTY=m
-CONFIG_PPP_DEFLATE=m
-CONFIG_PPP_BSDCOMP=m
-CONFIG_PPP_MPPE=m
-CONFIG_PPPOE=m
-# CONFIG_SLIP is not set
-CONFIG_SLHC=m
-# CONFIG_NETCONSOLE is not set
-# CONFIG_NETPOLL is not set
-# CONFIG_NET_POLL_CONTROLLER is not set
-# CONFIG_ISDN is not set
-# CONFIG_PHONE is not set
-
-#
-# Input device support
-#
-CONFIG_INPUT=y
-CONFIG_INPUT_FF_MEMLESS=m
-CONFIG_INPUT_POLLDEV=m
-# CONFIG_INPUT_SPARSEKMAP is not set
-
-#
-# Userland interfaces
-#
-CONFIG_INPUT_MOUSEDEV=m
-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=m
-# CONFIG_INPUT_EVBUG is not set
-
-#
-# Input Device Drivers
-#
-CONFIG_INPUT_KEYBOARD=y
-# CONFIG_KEYBOARD_ADP5588 is not set
-CONFIG_KEYBOARD_ATKBD=y
-# CONFIG_KEYBOARD_QT2160 is not set
-# CONFIG_KEYBOARD_LKKBD is not set
-CONFIG_KEYBOARD_EP93XX=m
-CONFIG_KEYBOARD_GPIO=m
-# CONFIG_KEYBOARD_TCA6416 is not set
-CONFIG_KEYBOARD_MATRIX=m
-CONFIG_TS72XX_DIO_3X4_KEYPAD=m
-CONFIG_TS72XX_DIO_4X4_KEYPAD=m
-# CONFIG_KEYBOARD_LM8323 is not set
-# CONFIG_KEYBOARD_MAX7359 is not set
-# CONFIG_KEYBOARD_MCS is not set
-# CONFIG_KEYBOARD_NEWTON is not set
-# CONFIG_KEYBOARD_OPENCORES is not set
-# CONFIG_KEYBOARD_STOWAWAY is not set
-# CONFIG_KEYBOARD_SUNKBD is not set
-# CONFIG_KEYBOARD_XTKBD is not set
-CONFIG_INPUT_MOUSE=y
-CONFIG_MOUSE_PS2=m
-CONFIG_MOUSE_PS2_ALPS=y
-CONFIG_MOUSE_PS2_LOGIPS2PP=y
-CONFIG_MOUSE_PS2_SYNAPTICS=y
-CONFIG_MOUSE_PS2_TRACKPOINT=y
-# CONFIG_MOUSE_PS2_ELANTECH is not set
-# CONFIG_MOUSE_PS2_SENTELIC is not set
-# CONFIG_MOUSE_PS2_TOUCHKIT is not set
-CONFIG_MOUSE_SERIAL=m
-# 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_MOUSE_SYNAPTICS_I2C is not set
-# CONFIG_INPUT_JOYSTICK is not set
-# CONFIG_INPUT_TABLET is not set
-# CONFIG_INPUT_TOUCHSCREEN is not set
-CONFIG_INPUT_MISC=y
-# CONFIG_INPUT_AD714X is not set
-# CONFIG_INPUT_ATI_REMOTE is not set
-# CONFIG_INPUT_ATI_REMOTE2 is not set
-# CONFIG_INPUT_KEYSPAN_REMOTE is not set
-# CONFIG_INPUT_POWERMATE is not set
-# CONFIG_INPUT_YEALINK is not set
-# CONFIG_INPUT_CM109 is not set
-CONFIG_INPUT_UINPUT=m
-# CONFIG_INPUT_PCF8574 is not set
-# CONFIG_INPUT_GPIO_ROTARY_ENCODER is not set
-# CONFIG_INPUT_ADXL34X is not set
-
-#
-# Hardware I/O ports
-#
-CONFIG_SERIO=y
-# CONFIG_SERIO_SERPORT is not set
-# CONFIG_SERIO_AMBAKMI is not set
-CONFIG_SERIO_LIBPS2=y
-# CONFIG_SERIO_RAW is not set
-# CONFIG_SERIO_ALTERA_PS2 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=y
-# CONFIG_DEVKMEM is not set
-# CONFIG_SERIAL_NONSTANDARD is not set
-# CONFIG_N_GSM is not set
-
-#
-# Serial drivers
-#
-CONFIG_SERIAL_8250=m
-CONFIG_SERIAL_8250_NR_UARTS=4
-CONFIG_SERIAL_8250_RUNTIME_UARTS=4
-# CONFIG_SERIAL_8250_EXTENDED is not set
-CONFIG_SERIAL_8250_TS_SER1=m
-CONFIG_SERIAL_8250_TS_SER1_IRQ=5
-
-#
-# Non-8250 serial port support
-#
-CONFIG_SERIAL_AMBA_PL010=y
-CONFIG_SERIAL_AMBA_PL010_CONSOLE=y
-CONFIG_SERIAL_AMBA_PL010_TS72XX=y
-# CONFIG_SERIAL_AMBA_PL011 is not set
-# CONFIG_SERIAL_MAX3100 is not set
-# CONFIG_SERIAL_MAX3107 is not set
-CONFIG_SERIAL_CORE=y
-CONFIG_SERIAL_CORE_CONSOLE=y
-# CONFIG_SERIAL_TIMBERDALE is not set
-# CONFIG_SERIAL_ALTERA_JTAGUART is not set
-# CONFIG_SERIAL_ALTERA_UART is not set
-CONFIG_UNIX98_PTYS=y
-# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
-# CONFIG_LEGACY_PTYS is not set
-# CONFIG_IPMI_HANDLER is not set
-CONFIG_HW_RANDOM=m
-# CONFIG_HW_RANDOM_TIMERIOMEM is not set
-# CONFIG_R3964 is not set
-# CONFIG_RAW_DRIVER is not set
-# CONFIG_TCG_TPM is not set
-# CONFIG_RAMOOPS is not set
-CONFIG_I2C=m
-CONFIG_I2C_BOARDINFO=y
-CONFIG_I2C_COMPAT=y
-# CONFIG_I2C_CHARDEV is not set
-# CONFIG_I2C_MUX is not set
-CONFIG_I2C_HELPER_AUTO=y
-CONFIG_I2C_ALGOBIT=m
-
-#
-# I2C Hardware Bus support
-#
-
-#
-# I2C system bus drivers (mostly embedded / system-on-chip)
-#
-# CONFIG_I2C_DESIGNWARE is not set
-CONFIG_I2C_GPIO=m
-# CONFIG_I2C_OCORES is not set
-# CONFIG_I2C_PCA_PLATFORM is not set
-# CONFIG_I2C_SIMTEC is not set
-# CONFIG_I2C_XILINX 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_STUB 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_SPI=y
-CONFIG_SPI_MASTER=y
-
-#
-# SPI Master Controller Drivers
-#
-CONFIG_SPI_BITBANG=m
-# CONFIG_SPI_EP93XX is not set
-CONFIG_SPI_GPIO=m
-# CONFIG_SPI_PL022 is not set
-# CONFIG_SPI_XILINX is not set
-# CONFIG_SPI_DESIGNWARE is not set
-
-#
-# SPI Protocol Masters
-#
-CONFIG_SPI_SPIDEV=m
-# CONFIG_SPI_TLE62X0 is not set
-# CONFIG_SPI_TMP124 is not set
-
-#
-# PPS support
-#
-# CONFIG_PPS is not set
-CONFIG_ARCH_REQUIRE_GPIOLIB=y
-CONFIG_GPIOLIB=y
-CONFIG_GPIO_SYSFS=y
-
-#
-# Memory mapped GPIO expanders:
-#
-# CONFIG_GPIO_IT8761E is not set
-# CONFIG_GPIO_PL061 is not set
-
-#
-# I2C GPIO expanders:
-#
-# CONFIG_GPIO_MAX7300 is not set
-# CONFIG_GPIO_MAX732X is not set
-# CONFIG_GPIO_PCA953X is not set
-# CONFIG_GPIO_PCF857X is not set
-# CONFIG_GPIO_ADP5588 is not set
-
-#
-# PCI GPIO expanders:
-#
-
-#
-# SPI GPIO expanders:
-#
-# CONFIG_GPIO_MAX7301 is not set
-# CONFIG_GPIO_MCP23S08 is not set
-# CONFIG_GPIO_MC33880 is not set
-
-#
-# AC97 GPIO expanders:
-#
-
-#
-# MODULbus GPIO expanders:
-#
-# CONFIG_W1 is not set
-# CONFIG_POWER_SUPPLY is not set
-# CONFIG_HWMON is not set
-# CONFIG_THERMAL is not set
-CONFIG_WATCHDOG=y
-# CONFIG_WATCHDOG_NOWAYOUT is not set
-
-#
-# Watchdog Device Drivers
-#
-# CONFIG_SOFT_WATCHDOG is not set
-# CONFIG_ARM_SP805_WATCHDOG is not set
-CONFIG_EP93XX_WATCHDOG=m
-CONFIG_TS72XX_WATCHDOG=y
-# CONFIG_MAX63XX_WATCHDOG is not set
-
-#
-# USB-based Watchdog Cards
-#
-# CONFIG_USBPCWATCHDOG is not set
-CONFIG_SSB_POSSIBLE=y
-
-#
-# Sonics Silicon Backplane
-#
-CONFIG_SSB=m
-CONFIG_SSB_BLOCKIO=y
-CONFIG_SSB_SDIOHOST_POSSIBLE=y
-# CONFIG_SSB_SDIOHOST is not set
-# CONFIG_SSB_SILENT is not set
-# CONFIG_SSB_DEBUG is not set
-CONFIG_MFD_SUPPORT=y
-# 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_TPS65010 is not set
-# CONFIG_TPS6507X is not set
-# CONFIG_MFD_TMIO is not set
-# CONFIG_MFD_T7L66XB is not set
-# CONFIG_MFD_TC6387XB is not set
-# CONFIG_MFD_TC6393XB is not set
-# CONFIG_MFD_WM8400 is not set
-# CONFIG_MFD_PCF50633 is not set
-# CONFIG_MFD_MC13783 is not set
-# CONFIG_ABX500_CORE is not set
-# CONFIG_EZX_PCAP is not set
-# CONFIG_AB8500_CORE is not set
-# CONFIG_MFD_TPS6586X is not set
-# CONFIG_REGULATOR is not set
-# CONFIG_MEDIA_SUPPORT is not set
-
-#
-# Graphics support
-#
-# CONFIG_DRM is not set
-# 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_DUMMY_CONSOLE=y
-# CONFIG_SOUND is not set
-CONFIG_HID_SUPPORT=y
-CONFIG_HID=y
-# CONFIG_HIDRAW is not set
-
-#
-# USB Input Devices
-#
-CONFIG_USB_HID=m
-# CONFIG_HID_PID is not set
-# CONFIG_USB_HIDDEV is not set
-
-#
-# USB HID Boot Protocol drivers
-#
-# CONFIG_USB_KBD is not set
-# CONFIG_USB_MOUSE is not set
-
-#
-# Special HID drivers
-#
-# CONFIG_HID_3M_PCT is not set
-# CONFIG_HID_A4TECH is not set
-# CONFIG_HID_ACRUX_FF is not set
-# CONFIG_HID_APPLE is not set
-# CONFIG_HID_BELKIN is not set
-# CONFIG_HID_CANDO is not set
-# CONFIG_HID_CHERRY is not set
-# CONFIG_HID_CHICONY is not set
-# CONFIG_HID_CYPRESS is not set
-# CONFIG_HID_DRAGONRISE is not set
-# CONFIG_HID_EGALAX is not set
-# CONFIG_HID_EZKEY is not set
-# CONFIG_HID_KYE is not set
-# CONFIG_HID_GYRATION is not set
-# CONFIG_HID_TWINHAN is not set
-# CONFIG_HID_KENSINGTON is not set
-# CONFIG_HID_LOGITECH is not set
-# CONFIG_HID_MICROSOFT is not set
-# CONFIG_HID_MOSART is not set
-# CONFIG_HID_MONTEREY is not set
-# CONFIG_HID_NTRIG is not set
-# CONFIG_HID_ORTEK is not set
-# CONFIG_HID_PANTHERLORD is not set
-# CONFIG_HID_PETALYNX is not set
-# CONFIG_HID_PICOLCD is not set
-# CONFIG_HID_QUANTA is not set
-# CONFIG_HID_ROCCAT is not set
-# CONFIG_HID_ROCCAT_KONE is not set
-# CONFIG_HID_SAMSUNG is not set
-# CONFIG_HID_SONY is not set
-# CONFIG_HID_STANTUM is not set
-# CONFIG_HID_SUNPLUS is not set
-# CONFIG_HID_GREENASIA is not set
-# CONFIG_HID_SMARTJOYPLUS is not set
-# CONFIG_HID_TOPSEED is not set
-# CONFIG_HID_THRUSTMASTER is not set
-# CONFIG_HID_ZEROPLUS is not set
-# CONFIG_HID_ZYDACRON is not set
-CONFIG_USB_SUPPORT=y
-CONFIG_USB_ARCH_HAS_HCD=y
-CONFIG_USB_ARCH_HAS_OHCI=y
-# CONFIG_USB_ARCH_HAS_EHCI is not set
-CONFIG_USB=m
-# CONFIG_USB_DEBUG is not set
-CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
-
-#
-# Miscellaneous USB options
-#
-# CONFIG_USB_DEVICEFS is not set
-CONFIG_USB_DEVICE_CLASS=y
-# CONFIG_USB_DYNAMIC_MINORS is not set
-# CONFIG_USB_OTG_WHITELIST is not set
-# CONFIG_USB_OTG_BLACKLIST_HUB is not set
-CONFIG_USB_MON=m
-# 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_OXU210HP_HCD is not set
-# CONFIG_USB_ISP116X_HCD is not set
-# CONFIG_USB_ISP1760_HCD is not set
-# CONFIG_USB_ISP1362_HCD is not set
-CONFIG_USB_OHCI_HCD=m
-# CONFIG_USB_OHCI_HCD_SSB is not set
-# CONFIG_USB_OHCI_BIG_ENDIAN_DESC is not set
-# CONFIG_USB_OHCI_BIG_ENDIAN_MMIO is not set
-CONFIG_USB_OHCI_LITTLE_ENDIAN=y
-# CONFIG_USB_SL811_HCD is not set
-# CONFIG_USB_R8A66597_HCD is not set
-# CONFIG_USB_HWA_HCD is not set
-# CONFIG_USB_MUSB_HDRC is not set
-
-#
-# USB Device Class drivers
-#
-CONFIG_USB_ACM=m
-# 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 info
-#
-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_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=m
-# CONFIG_USB_EZUSB is not set
-CONFIG_USB_SERIAL_GENERIC=y
-# CONFIG_USB_SERIAL_AIRCABLE is not set
-# CONFIG_USB_SERIAL_ARK3116 is not set
-# CONFIG_USB_SERIAL_BELKIN is not set
-# CONFIG_USB_SERIAL_CH341 is not set
-# CONFIG_USB_SERIAL_WHITEHEAT is not set
-# CONFIG_USB_SERIAL_DIGI_ACCELEPORT is not set
-# CONFIG_USB_SERIAL_CP210X is not set
-# CONFIG_USB_SERIAL_CYPRESS_M8 is not set
-# CONFIG_USB_SERIAL_EMPEG is not set
-CONFIG_USB_SERIAL_FTDI_SIO=m
-# CONFIG_USB_SERIAL_FUNSOFT is not set
-# CONFIG_USB_SERIAL_VISOR is not set
-# CONFIG_USB_SERIAL_IPAQ is not set
-# CONFIG_USB_SERIAL_IR is not set
-# CONFIG_USB_SERIAL_EDGEPORT is not set
-# CONFIG_USB_SERIAL_EDGEPORT_TI is not set
-# CONFIG_USB_SERIAL_GARMIN is not set
-# CONFIG_USB_SERIAL_IPW is not set
-# CONFIG_USB_SERIAL_IUU is not set
-# CONFIG_USB_SERIAL_KEYSPAN_PDA is not set
-# CONFIG_USB_SERIAL_KEYSPAN is not set
-# CONFIG_USB_SERIAL_KLSI is not set
-# CONFIG_USB_SERIAL_KOBIL_SCT is not set
-# CONFIG_USB_SERIAL_MCT_U232 is not set
-# CONFIG_USB_SERIAL_MOS7720 is not set
-# CONFIG_USB_SERIAL_MOS7840 is not set
-# CONFIG_USB_SERIAL_MOTOROLA is not set
-# CONFIG_USB_SERIAL_NAVMAN is not set
-CONFIG_USB_SERIAL_PL2303=m
-# CONFIG_USB_SERIAL_OTI6858 is not set
-# CONFIG_USB_SERIAL_QCAUX is not set
-# CONFIG_USB_SERIAL_QUALCOMM is not set
-# CONFIG_USB_SERIAL_SPCP8X5 is not set
-# CONFIG_USB_SERIAL_HP4X is not set
-# CONFIG_USB_SERIAL_SAFE is not set
-# CONFIG_USB_SERIAL_SIEMENS_MPI is not set
-# CONFIG_USB_SERIAL_SIERRAWIRELESS is not set
-# CONFIG_USB_SERIAL_SYMBOL is not set
-# CONFIG_USB_SERIAL_TI is not set
-# CONFIG_USB_SERIAL_CYBERJACK is not set
-# CONFIG_USB_SERIAL_XIRCOM is not set
-CONFIG_USB_SERIAL_WWAN=m
-CONFIG_USB_SERIAL_OPTION=m
-# CONFIG_USB_SERIAL_OMNINET is not set
-# CONFIG_USB_SERIAL_OPTICON is not set
-# CONFIG_USB_SERIAL_VIVOPAY_SERIAL is not set
-# CONFIG_USB_SERIAL_ZIO is not set
-# CONFIG_USB_SERIAL_SSU100 is not set
-# CONFIG_USB_SERIAL_DEBUG 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_LED is not set
-# CONFIG_USB_CYPRESS_CY7C63 is not set
-# CONFIG_USB_CYTHERM 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_GADGET=m
-# CONFIG_USB_GADGET_DEBUG_FILES is not set
-CONFIG_USB_GADGET_VBUS_DRAW=2
-CONFIG_USB_GADGET_SELECTED=y
-CONFIG_USB_GADGET_R8A66597=y
-CONFIG_USB_R8A66597=m
-# CONFIG_USB_GADGET_M66592 is not set
-# CONFIG_USB_GADGET_DUMMY_HCD is not set
-CONFIG_USB_GADGET_DUALSPEED=y
-# CONFIG_USB_ZERO is not set
-CONFIG_USB_ETH=m
-CONFIG_USB_ETH_RNDIS=y
-CONFIG_USB_ETH_EEM=y
-CONFIG_USB_GADGETFS=m
-# CONFIG_USB_FUNCTIONFS is not set
-CONFIG_USB_FILE_STORAGE=m
-# CONFIG_USB_FILE_STORAGE_TEST is not set
-CONFIG_USB_MASS_STORAGE=m
-CONFIG_USB_G_SERIAL=m
-CONFIG_USB_G_PRINTER=m
-CONFIG_USB_CDC_COMPOSITE=m
-CONFIG_USB_G_MULTI=m
-CONFIG_USB_G_MULTI_RNDIS=y
-CONFIG_USB_G_MULTI_CDC=y
-# CONFIG_USB_G_HID is not set
-# CONFIG_USB_G_DBGP is not set
-
-#
-# OTG and related infrastructure
-#
-# CONFIG_USB_GPIO_VBUS is not set
-# CONFIG_USB_ULPI is not set
-# CONFIG_NOP_USB_XCEIV is not set
-CONFIG_MMC=m
-# CONFIG_MMC_DEBUG is not set
-# CONFIG_MMC_UNSAFE_RESUME is not set
-
-#
-# MMC/SD/SDIO Card Drivers
-#
-CONFIG_MMC_BLOCK=m
-CONFIG_MMC_BLOCK_BOUNCE=y
-CONFIG_SDIO_UART=m
-# CONFIG_MMC_TEST is not set
-
-#
-# MMC/SD/SDIO Host Controller Drivers
-#
-CONFIG_MMC_ARMMMCI=m
-CONFIG_MMC_SDHCI=m
-# CONFIG_MMC_SDHCI_PLTFM is not set
-# CONFIG_MMC_SPI is not set
-# CONFIG_MEMSTICK is not set
-CONFIG_NEW_LEDS=y
-CONFIG_LEDS_CLASS=y
-
-#
-# LED drivers
-#
-# CONFIG_LEDS_PCA9532 is not set
-CONFIG_LEDS_GPIO=y
-CONFIG_LEDS_GPIO_PLATFORM=y
-# CONFIG_LEDS_LP3944 is not set
-# CONFIG_LEDS_PCA955X is not set
-# CONFIG_LEDS_DAC124S085 is not set
-# CONFIG_LEDS_BD2802 is not set
-# CONFIG_LEDS_LT3593 is not set
-CONFIG_LEDS_TRIGGERS=y
-
-#
-# LED Triggers
-#
-CONFIG_LEDS_TRIGGER_TIMER=y
-CONFIG_LEDS_TRIGGER_HEARTBEAT=y
-CONFIG_LEDS_TRIGGER_BACKLIGHT=y
-CONFIG_LEDS_TRIGGER_GPIO=y
-CONFIG_LEDS_TRIGGER_DEFAULT_ON=m
-
-#
-# iptables trigger is under Netfilter config (LED target)
-#
-# CONFIG_ACCESSIBILITY is not set
-CONFIG_RTC_LIB=y
-CONFIG_RTC_CLASS=m
-
-#
-# 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_DS3232 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_ISL12022 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_BQ32K is not set
-# CONFIG_RTC_DRV_S35390A is not set
-# CONFIG_RTC_DRV_FM3130 is not set
-# CONFIG_RTC_DRV_RX8581 is not set
-# CONFIG_RTC_DRV_RX8025 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
-# CONFIG_RTC_DRV_PCF2123 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=m
-# CONFIG_RTC_DRV_M48T35 is not set
-# CONFIG_RTC_DRV_M48T59 is not set
-# CONFIG_RTC_DRV_MSM6242 is not set
-# CONFIG_RTC_DRV_BQ4802 is not set
-# CONFIG_RTC_DRV_RP5C01 is not set
-# CONFIG_RTC_DRV_V3020 is not set
-
-#
-# on-CPU RTC drivers
-#
-CONFIG_RTC_DRV_EP93XX=m
-# CONFIG_RTC_DRV_PL030 is not set
-# CONFIG_RTC_DRV_PL031 is not set
-# CONFIG_DMADEVICES is not set
-# CONFIG_AUXDISPLAY is not set
-CONFIG_UIO=m
-CONFIG_UIO_PDRV=m
-CONFIG_UIO_PDRV_GENIRQ=m
-# CONFIG_STAGING is not set
-
-#
-# LCD support
-#
-CONFIG_LCD_LINUX=y
-CONFIG_LCD_HD44780=y
-
-#
-# File systems
-#
-CONFIG_EXT2_FS=m
-# CONFIG_EXT2_FS_XATTR is not set
-# CONFIG_EXT2_FS_XIP is not set
-CONFIG_EXT3_FS=m
-# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
-CONFIG_EXT3_FS_XATTR=y
-# CONFIG_EXT3_FS_POSIX_ACL is not set
-# CONFIG_EXT3_FS_SECURITY is not set
-CONFIG_EXT4_FS=m
-# CONFIG_EXT4_FS_XATTR is not set
-# CONFIG_EXT4_DEBUG is not set
-CONFIG_JBD=m
-CONFIG_JBD2=m
-CONFIG_FS_MBCACHE=m
-# CONFIG_REISERFS_FS is not set
-# CONFIG_JFS_FS is not set
-CONFIG_FS_POSIX_ACL=y
-# CONFIG_XFS_FS is not set
-# CONFIG_GFS2_FS is not set
-# CONFIG_OCFS2_FS is not set
-# CONFIG_BTRFS_FS is not set
-# CONFIG_NILFS2_FS is not set
-CONFIG_FILE_LOCKING=y
-CONFIG_FSNOTIFY=y
-CONFIG_DNOTIFY=y
-CONFIG_INOTIFY_USER=y
-# CONFIG_QUOTA is not set
-# CONFIG_AUTOFS_FS is not set
-CONFIG_AUTOFS4_FS=m
-CONFIG_FUSE_FS=m
-# CONFIG_CUSE is not set
-CONFIG_GENERIC_ACL=y
-
-#
-# Caches
-#
-# CONFIG_FSCACHE is not set
-
-#
-# CD-ROM/DVD Filesystems
-#
-CONFIG_ISO9660_FS=m
-CONFIG_JOLIET=y
-CONFIG_ZISOFS=y
-CONFIG_UDF_FS=m
-CONFIG_UDF_NLS=y
-
-#
-# DOS/FAT/NT Filesystems
-#
-CONFIG_FAT_FS=m
-CONFIG_MSDOS_FS=m
-CONFIG_VFAT_FS=m
-CONFIG_FAT_DEFAULT_CODEPAGE=437
-CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
-CONFIG_NTFS_FS=m
-# 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
-CONFIG_MISC_FILESYSTEMS=y
-# CONFIG_ADFS_FS is not set
-# CONFIG_AFFS_FS is not set
-# CONFIG_ECRYPT_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_JFFS2_FS=m
-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_UBIFS_FS=y
-CONFIG_UBIFS_FS_XATTR=y
-CONFIG_UBIFS_FS_ADVANCED_COMPR=y
-CONFIG_UBIFS_FS_LZO=y
-CONFIG_UBIFS_FS_ZLIB=y
-# CONFIG_UBIFS_FS_DEBUG is not set
-# CONFIG_LOGFS is not set
-# CONFIG_CRAMFS is not set
-CONFIG_SQUASHFS=m
-# CONFIG_SQUASHFS_XATTR is not set
-# CONFIG_SQUASHFS_LZO is not set
-# CONFIG_SQUASHFS_EMBEDDED is not set
-CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE=3
-# 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=y
-# CONFIG_NFS_V4_1 is not set
-CONFIG_ROOT_NFS=y
-# CONFIG_NFS_USE_LEGACY_DNS is not set
-CONFIG_NFS_USE_KERNEL_DNS=y
-CONFIG_NFSD=m
-CONFIG_NFSD_V2_ACL=y
-CONFIG_NFSD_V3=y
-CONFIG_NFSD_V3_ACL=y
-CONFIG_NFSD_V4=y
-CONFIG_LOCKD=y
-CONFIG_LOCKD_V4=y
-CONFIG_EXPORTFS=m
-CONFIG_NFS_ACL_SUPPORT=m
-CONFIG_NFS_COMMON=y
-CONFIG_SUNRPC=y
-CONFIG_SUNRPC_GSS=y
-CONFIG_RPCSEC_GSS_KRB5=y
-# CONFIG_RPCSEC_GSS_SPKM3 is not set
-# CONFIG_SMB_FS is not set
-# CONFIG_CEPH_FS is not set
-CONFIG_CIFS=m
-# CONFIG_CIFS_STATS is not set
-# CONFIG_CIFS_WEAK_PW_HASH is not set
-CONFIG_CIFS_UPCALL=y
-# CONFIG_CIFS_XATTR is not set
-# CONFIG_CIFS_DEBUG2 is not set
-# CONFIG_CIFS_DFS_UPCALL is not set
-# CONFIG_CIFS_EXPERIMENTAL 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="iso8859-1"
-CONFIG_NLS_CODEPAGE_437=m
-CONFIG_NLS_CODEPAGE_737=m
-CONFIG_NLS_CODEPAGE_775=m
-CONFIG_NLS_CODEPAGE_850=m
-CONFIG_NLS_CODEPAGE_852=m
-CONFIG_NLS_CODEPAGE_855=m
-CONFIG_NLS_CODEPAGE_857=m
-CONFIG_NLS_CODEPAGE_860=m
-CONFIG_NLS_CODEPAGE_861=m
-CONFIG_NLS_CODEPAGE_862=m
-CONFIG_NLS_CODEPAGE_863=m
-CONFIG_NLS_CODEPAGE_864=m
-CONFIG_NLS_CODEPAGE_865=m
-CONFIG_NLS_CODEPAGE_866=m
-CONFIG_NLS_CODEPAGE_869=m
-CONFIG_NLS_CODEPAGE_936=m
-CONFIG_NLS_CODEPAGE_950=m
-CONFIG_NLS_CODEPAGE_932=m
-CONFIG_NLS_CODEPAGE_949=m
-CONFIG_NLS_CODEPAGE_874=m
-CONFIG_NLS_ISO8859_8=m
-CONFIG_NLS_CODEPAGE_1250=m
-CONFIG_NLS_CODEPAGE_1251=m
-CONFIG_NLS_ASCII=m
-CONFIG_NLS_ISO8859_1=m
-CONFIG_NLS_ISO8859_2=m
-CONFIG_NLS_ISO8859_3=m
-CONFIG_NLS_ISO8859_4=m
-CONFIG_NLS_ISO8859_5=m
-CONFIG_NLS_ISO8859_6=m
-CONFIG_NLS_ISO8859_7=m
-CONFIG_NLS_ISO8859_9=m
-CONFIG_NLS_ISO8859_13=m
-CONFIG_NLS_ISO8859_14=m
-CONFIG_NLS_ISO8859_15=m
-CONFIG_NLS_KOI8_R=m
-CONFIG_NLS_KOI8_U=m
-CONFIG_NLS_UTF8=m
-# CONFIG_DLM is not set
-
-#
-# Kernel hacking
-#
-CONFIG_PRINTK_TIME=y
-# CONFIG_ENABLE_WARN_DEPRECATED is not set
-# CONFIG_ENABLE_MUST_CHECK is not set
-CONFIG_FRAME_WARN=2048
-# CONFIG_MAGIC_SYSRQ is not set
-# CONFIG_STRIP_ASM_SYMS is not set
-# 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_HARDLOCKUP_DETECTOR is not set
-CONFIG_DEBUG_BUGVERBOSE=y
-# CONFIG_DEBUG_MEMORY_INIT is not set
-# CONFIG_RCU_CPU_STALL_DETECTOR is not set
-CONFIG_SYSCTL_SYSCALL_CHECK=y
-CONFIG_HAVE_FUNCTION_TRACER=y
-CONFIG_TRACING_SUPPORT=y
-# CONFIG_FTRACE is not set
-# CONFIG_ATOMIC64_SELFTEST is not set
-# CONFIG_SAMPLES is not set
-CONFIG_HAVE_ARCH_KGDB=y
-CONFIG_ARM_UNWIND=y
-# CONFIG_DEBUG_USER is not set
-# CONFIG_OC_ETM is not set
-
-#
-# Security options
-#
-CONFIG_KEYS=y
-# CONFIG_KEYS_DEBUG_PROC_KEYS is not set
-CONFIG_SECURITY=y
-# CONFIG_SECURITYFS is not set
-CONFIG_SECURITY_NETWORK=y
-# CONFIG_SECURITY_NETWORK_XFRM is not set
-# CONFIG_SECURITY_PATH is not set
-# CONFIG_SECURITY_TOMOYO is not set
-# CONFIG_SECURITY_APPARMOR is not set
-# CONFIG_IMA is not set
-CONFIG_DEFAULT_SECURITY_DAC=y
-CONFIG_DEFAULT_SECURITY=""
-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_RNG=m
-CONFIG_CRYPTO_RNG2=y
-CONFIG_CRYPTO_PCOMP=m
-CONFIG_CRYPTO_PCOMP2=y
-CONFIG_CRYPTO_MANAGER=y
-CONFIG_CRYPTO_MANAGER2=y
-CONFIG_CRYPTO_MANAGER_DISABLE_TESTS=y
-CONFIG_CRYPTO_GF128MUL=m
-CONFIG_CRYPTO_NULL=m
-CONFIG_CRYPTO_WORKQUEUE=y
-CONFIG_CRYPTO_CRYPTD=m
-CONFIG_CRYPTO_AUTHENC=m
-CONFIG_CRYPTO_TEST=m
-
-#
-# Authenticated Encryption with Associated Data
-#
-CONFIG_CRYPTO_CCM=m
-CONFIG_CRYPTO_GCM=m
-CONFIG_CRYPTO_SEQIV=m
-
-#
-# Block modes
-#
-CONFIG_CRYPTO_CBC=y
-CONFIG_CRYPTO_CTR=m
-CONFIG_CRYPTO_CTS=m
-CONFIG_CRYPTO_ECB=m
-CONFIG_CRYPTO_LRW=m
-CONFIG_CRYPTO_PCBC=m
-CONFIG_CRYPTO_XTS=m
-
-#
-# Hash modes
-#
-CONFIG_CRYPTO_HMAC=m
-CONFIG_CRYPTO_XCBC=m
-CONFIG_CRYPTO_VMAC=m
-
-#
-# Digest
-#
-CONFIG_CRYPTO_CRC32C=m
-CONFIG_CRYPTO_GHASH=m
-CONFIG_CRYPTO_MD4=m
-CONFIG_CRYPTO_MD5=y
-CONFIG_CRYPTO_MICHAEL_MIC=m
-CONFIG_CRYPTO_RMD128=m
-CONFIG_CRYPTO_RMD160=m
-CONFIG_CRYPTO_RMD256=m
-CONFIG_CRYPTO_RMD320=m
-CONFIG_CRYPTO_SHA1=m
-CONFIG_CRYPTO_SHA256=m
-CONFIG_CRYPTO_SHA512=m
-CONFIG_CRYPTO_TGR192=m
-CONFIG_CRYPTO_WP512=m
-
-#
-# Ciphers
-#
-CONFIG_CRYPTO_AES=m
-CONFIG_CRYPTO_ANUBIS=m
-CONFIG_CRYPTO_ARC4=m
-CONFIG_CRYPTO_BLOWFISH=m
-CONFIG_CRYPTO_CAMELLIA=m
-CONFIG_CRYPTO_CAST5=m
-CONFIG_CRYPTO_CAST6=m
-CONFIG_CRYPTO_DES=y
-CONFIG_CRYPTO_FCRYPT=m
-CONFIG_CRYPTO_KHAZAD=m
-CONFIG_CRYPTO_SALSA20=m
-CONFIG_CRYPTO_SEED=m
-CONFIG_CRYPTO_SERPENT=m
-CONFIG_CRYPTO_TEA=m
-CONFIG_CRYPTO_TWOFISH=m
-CONFIG_CRYPTO_TWOFISH_COMMON=m
-
-#
-# Compression
-#
-CONFIG_CRYPTO_DEFLATE=y
-CONFIG_CRYPTO_ZLIB=m
-CONFIG_CRYPTO_LZO=y
-
-#
-# Random Number Generation
-#
-CONFIG_CRYPTO_ANSI_CPRNG=m
-# CONFIG_CRYPTO_HW is not set
-# CONFIG_BINARY_PRINTF is not set
-
-#
-# Library routines
-#
-CONFIG_BITREVERSE=y
-CONFIG_GENERIC_FIND_LAST_BIT=y
-CONFIG_CRC_CCITT=m
-CONFIG_CRC16=y
-CONFIG_CRC_T10DIF=m
-CONFIG_CRC_ITU_T=m
-CONFIG_CRC32=y
-CONFIG_CRC7=m
-CONFIG_LIBCRC32C=m
-CONFIG_ZLIB_INFLATE=y
-CONFIG_ZLIB_DEFLATE=y
-CONFIG_LZO_COMPRESS=y
-CONFIG_LZO_DECOMPRESS=y
-CONFIG_TEXTSEARCH=y
-CONFIG_TEXTSEARCH_KMP=m
-CONFIG_TEXTSEARCH_BM=m
-CONFIG_TEXTSEARCH_FSM=m
-CONFIG_HAS_IOMEM=y
-CONFIG_HAS_IOPORT=y
-CONFIG_HAS_DMA=y
-CONFIG_NLATTR=y
-CONFIG_GENERIC_ATOMIC64=y
diff --git a/recipes/linux/linux_2.6.36.bb b/recipes/linux/linux_2.6.36.bb
index 10692b9..aea17dd 100644
--- a/recipes/linux/linux_2.6.36.bb
+++ b/recipes/linux/linux_2.6.36.bb
@@ -5,7 +5,6 @@ PR = "r2"
# Mark archs/machines that this kernel supports
DEFAULT_PREFERENCE = "-1"
DEFAULT_PREFERENCE_mx31ads = "1"
-DEFAULT_PREFERENCE_ts72xx = "1"
SRC_URI = "${KERNELORG_MIRROR}/pub/linux/kernel/v2.6/${P}.tar.bz2;name=kernel \
${KERNELORG_MIRROR}/pub/linux/kernel/v2.6/patch-${PV}.1.bz2;apply=yes;name=stablepatch \
@@ -13,30 +12,6 @@ SRC_URI = "${KERNELORG_MIRROR}/pub/linux/kernel/v2.6/${P}.tar.bz2;name=kernel \
SRC_URI_append_mx31ads = "file://0001-add-missing-include.patch"
-SRC_URI_append_ts72xx = " \
- file://0001-ts72xx_base.patch \
- file://0002-ts72xx_force_machine-id.patch \
- file://0003-ep93xx_cpuinfo.patch \
- file://0004-ep93xx_eth.patch \
- file://0005-ep93xx-m2m-DMA-support.patch \
- file://0006-ts72xx_rs485.patch \
- file://0007-ts72xx_ts_ser1.patch \
- file://0008-ts72xx_ts_eth100.patch \
- file://0009-ts72xx_pata.patch \
- file://0010-ts72xx_gpio_i2c.patch \
- file://0011-ts72xx_dio_keypad.patch \
- file://0012-ts72xx_sbcinfo.patch \
- file://0013-ts72xx_max197.patch \
- file://0014-ts7200_nor_flash.patch \
- file://0015-ts72xx_sdcard.patch \
- file://0016-ts72xx_spi_tmp124.patch \
- file://0017-ts72xx-use-CPLD-watchdog-for-reset.patch \
- file://0018-ethoc-ts7300-fixes.patch \
- file://0019-ts7300-add-ethernet-support.patch \
- file://0023-ts72xx-add-lcd-linux-driver.patch \
- file://0024-ts72xx-add-GPIO-keys.patch \
- "
-
SRC_URI[kernel.md5sum] = "61f3739a73afb6914cb007f37fb09b62"
SRC_URI[kernel.sha256sum] = "15a076d1a435a6bf8e92834eba4b390b4ec094ce06d47f89d071ca9e5788ce04"
SRC_URI[stablepatch.md5sum] = "dd38a6caf08df2822f93541ee95aed7d"
--
1.7.1
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [PATCH 6/6] linux-2.6.38: add support for ts72xx and make it default
2011-04-02 14:18 [PATCH 0/6] RFC: patches I plan to push Petr Štetiar
` (4 preceding siblings ...)
2011-04-02 14:18 ` [PATCH 5/6] linux-2.6.36: remove ts72xx support because 2.6.38 is now default Petr Štetiar
@ 2011-04-02 14:18 ` Petr Štetiar
2011-04-10 1:57 ` [PATCH 0/6] RFC: patches I plan to push Khem Raj
6 siblings, 0 replies; 10+ messages in thread
From: Petr Štetiar @ 2011-04-02 14:18 UTC (permalink / raw)
To: openembedded-devel
Signed-off-by: Petr Štetiar <ynezz@true.cz>
---
.../linux-2.6.38/ts72xx/0001-ts72xx_base.patch | 451 ++
.../ts72xx/0002-ts72xx_force_machine-id.patch | 49 +
.../linux-2.6.38/ts72xx/0003-ep93xx_cpuinfo.patch | 36 +
.../linux-2.6.38/ts72xx/0004-ep93xx_eth.patch | 553 +++
.../ts72xx/0005-ep93xx-m2m-DMA-support.patch | 870 ++++
.../linux-2.6.38/ts72xx/0006-ts72xx_rs485.patch | 221 +
.../linux-2.6.38/ts72xx/0007-ts72xx_ts_ser1.patch | 264 ++
.../ts72xx/0008-ts72xx_ts_eth100.patch | 278 ++
.../linux-2.6.38/ts72xx/0009-ts72xx_pata.patch | 437 ++
.../linux-2.6.38/ts72xx/0010-ts72xx_gpio_i2c.patch | 63 +
.../ts72xx/0011-ts72xx_dio_keypad.patch | 311 ++
.../linux-2.6.38/ts72xx/0012-ts72xx_sbcinfo.patch | 267 ++
.../linux-2.6.38/ts72xx/0013-ts72xx_max197.patch | 356 ++
.../ts72xx/0014-ts7200_nor_flash.patch | 181 +
.../linux-2.6.38/ts72xx/0015-ts72xx_sdcard.patch | 3299 ++++++++++++++
.../ts72xx/0016-ts72xx_spi_tmp124.patch | 305 ++
.../0017-ts72xx-use-CPLD-watchdog-for-reset.patch | 53 +
.../ts72xx/0018-ethoc-ts7300-fixes.patch | 72 +
.../ts72xx/0019-ts7300-add-ethernet-support.patch | 87 +
.../ts72xx/0020-ts72xx-add-lcd-linux-driver.patch | 4572 ++++++++++++++++++++
.../ts72xx/0021-TS-72XX-LCD-console-driver.patch | 528 +++
...M-ep93xx-Fix-inverted-RTS-and-DTR-signals.patch | 38 +
recipes/linux/linux-2.6.38/ts72xx/defconfig | 2214 ++++++++++
recipes/linux/linux_2.6.38.bb | 26 +
24 files changed, 15531 insertions(+), 0 deletions(-)
create mode 100644 recipes/linux/linux-2.6.38/ts72xx/0001-ts72xx_base.patch
create mode 100644 recipes/linux/linux-2.6.38/ts72xx/0002-ts72xx_force_machine-id.patch
create mode 100644 recipes/linux/linux-2.6.38/ts72xx/0003-ep93xx_cpuinfo.patch
create mode 100644 recipes/linux/linux-2.6.38/ts72xx/0004-ep93xx_eth.patch
create mode 100644 recipes/linux/linux-2.6.38/ts72xx/0005-ep93xx-m2m-DMA-support.patch
create mode 100644 recipes/linux/linux-2.6.38/ts72xx/0006-ts72xx_rs485.patch
create mode 100644 recipes/linux/linux-2.6.38/ts72xx/0007-ts72xx_ts_ser1.patch
create mode 100644 recipes/linux/linux-2.6.38/ts72xx/0008-ts72xx_ts_eth100.patch
create mode 100644 recipes/linux/linux-2.6.38/ts72xx/0009-ts72xx_pata.patch
create mode 100644 recipes/linux/linux-2.6.38/ts72xx/0010-ts72xx_gpio_i2c.patch
create mode 100644 recipes/linux/linux-2.6.38/ts72xx/0011-ts72xx_dio_keypad.patch
create mode 100644 recipes/linux/linux-2.6.38/ts72xx/0012-ts72xx_sbcinfo.patch
create mode 100644 recipes/linux/linux-2.6.38/ts72xx/0013-ts72xx_max197.patch
create mode 100644 recipes/linux/linux-2.6.38/ts72xx/0014-ts7200_nor_flash.patch
create mode 100644 recipes/linux/linux-2.6.38/ts72xx/0015-ts72xx_sdcard.patch
create mode 100644 recipes/linux/linux-2.6.38/ts72xx/0016-ts72xx_spi_tmp124.patch
create mode 100644 recipes/linux/linux-2.6.38/ts72xx/0017-ts72xx-use-CPLD-watchdog-for-reset.patch
create mode 100644 recipes/linux/linux-2.6.38/ts72xx/0018-ethoc-ts7300-fixes.patch
create mode 100644 recipes/linux/linux-2.6.38/ts72xx/0019-ts7300-add-ethernet-support.patch
create mode 100644 recipes/linux/linux-2.6.38/ts72xx/0020-ts72xx-add-lcd-linux-driver.patch
create mode 100644 recipes/linux/linux-2.6.38/ts72xx/0021-TS-72XX-LCD-console-driver.patch
create mode 100644 recipes/linux/linux-2.6.38/ts72xx/0024-ARM-ep93xx-Fix-inverted-RTS-and-DTR-signals.patch
create mode 100644 recipes/linux/linux-2.6.38/ts72xx/defconfig
diff --git a/recipes/linux/linux-2.6.38/ts72xx/0001-ts72xx_base.patch b/recipes/linux/linux-2.6.38/ts72xx/0001-ts72xx_base.patch
new file mode 100644
index 0000000..87fb5fc
--- /dev/null
+++ b/recipes/linux/linux-2.6.38/ts72xx/0001-ts72xx_base.patch
@@ -0,0 +1,451 @@
+From 1cadb91bccdc6edd3c4e6fba08c417861586f190 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Petr=20=C5=A0tetiar?= <ynezz@true.cz>
+Date: Sun, 13 Mar 2011 23:47:13 +0100
+Subject: [PATCH 01/24] ts72xx_base
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+- patch: allow to force nF bit in control reg
+- register pwm1
+
+Signed-off-by: Petr Štetiar <ynezz@true.cz>
+---
+ arch/arm/Kconfig | 4 +
+ arch/arm/mach-ep93xx/Kconfig | 9 ++
+ arch/arm/mach-ep93xx/include/mach/ep93xx-regs.h | 7 +
+ arch/arm/mach-ep93xx/include/mach/memory.h | 28 +++++
+ arch/arm/mach-ep93xx/include/mach/ts72xx.h | 145 +++++++++++++++++++++--
+ arch/arm/mach-ep93xx/ts72xx.c | 41 ++++++-
+ arch/arm/mm/proc-arm920.S | 5 +-
+ scripts/Makefile.fwinst | 2 +-
+ 8 files changed, 224 insertions(+), 17 deletions(-)
+
+diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
+index 166efa2..31ad31d 100644
+--- a/arch/arm/Kconfig
++++ b/arch/arm/Kconfig
+@@ -336,6 +336,10 @@ config ARCH_EP93XX
+ select ARM_AMBA
+ select ARM_VIC
+ select CLKDEV_LOOKUP
++ select ARCH_SPARSEMEM_ENABLE
++ select GENERIC_GPIO
++ select HAVE_CLK
++ select COMMON_CLKDEV
+ select ARCH_REQUIRE_GPIOLIB
+ select ARCH_HAS_HOLES_MEMORYMODEL
+ select ARCH_USES_GETTIMEOFFSET
+diff --git a/arch/arm/mach-ep93xx/Kconfig b/arch/arm/mach-ep93xx/Kconfig
+index 3a08b18..b6be37e 100644
+--- a/arch/arm/mach-ep93xx/Kconfig
++++ b/arch/arm/mach-ep93xx/Kconfig
+@@ -7,6 +7,15 @@ config CRUNCH
+ help
+ Enable kernel support for MaverickCrunch.
+
++config CR1_NFBIT
++ bool "Turn on nF bit in ControlRegister 1"
++ help
++ Say 'Y' here to force the nF bit on. Usually this is set
++ by the bootrom. If it is not set, then the CPU core will
++ run from HCLK instead of FCLK, and performance will suffer.
++ If you see BogoMIPS of about 1/4 of your CPU clock, try
++ turning this on; your performance should double.
++
+ comment "EP93xx Platforms"
+
+ choice
+diff --git a/arch/arm/mach-ep93xx/include/mach/ep93xx-regs.h b/arch/arm/mach-ep93xx/include/mach/ep93xx-regs.h
+index 9ac4d10..87a5bfe 100644
+--- a/arch/arm/mach-ep93xx/include/mach/ep93xx-regs.h
++++ b/arch/arm/mach-ep93xx/include/mach/ep93xx-regs.h
+@@ -83,6 +83,7 @@
+
+ #define EP93XX_BOOT_ROM_BASE EP93XX_AHB_IOMEM(0x00090000)
+
++#define EP93XX_IDE_PHYS_BASE EP93XX_AHB_PHYS(0x000a0000)
+ #define EP93XX_IDE_BASE EP93XX_AHB_IOMEM(0x000a0000)
+
+ #define EP93XX_VIC1_BASE EP93XX_AHB_IOMEM(0x000b0000)
+@@ -97,12 +98,17 @@
+ #define EP93XX_I2S_BASE EP93XX_APB_IOMEM(0x00020000)
+
+ #define EP93XX_SECURITY_BASE EP93XX_APB_IOMEM(0x00030000)
++#define EP93XX_SECURITY_REG(x) (EP93XX_SECURITY_BASE + (x))
++#define EP93XX_SECURITY_UNIQID EP93XX_SECURITY_REG(0x2440)
+
+ #define EP93XX_GPIO_BASE EP93XX_APB_IOMEM(0x00040000)
+ #define EP93XX_GPIO_REG(x) (EP93XX_GPIO_BASE + (x))
+ #define EP93XX_GPIO_F_INT_STATUS EP93XX_GPIO_REG(0x5c)
++#define EP93XX_GPIO_F_INT_DEBOUNCE EP93XX_GPIO_REG(0x64)
+ #define EP93XX_GPIO_A_INT_STATUS EP93XX_GPIO_REG(0xa0)
++#define EP93XX_GPIO_A_INT_DEBOUNCE EP93XX_GPIO_REG(0xa8)
+ #define EP93XX_GPIO_B_INT_STATUS EP93XX_GPIO_REG(0xbc)
++#define EP93XX_GPIO_B_INT_DEBOUNCE EP93XX_GPIO_REG(0xc4)
+ #define EP93XX_GPIO_EEDRIVE EP93XX_GPIO_REG(0xc8)
+
+ #define EP93XX_AAC_PHYS_BASE EP93XX_APB_PHYS(0x00080000)
+@@ -221,6 +227,7 @@
+ #define EP93XX_SYSCON_SYSCFG_LEECLK (1<<3)
+ #define EP93XX_SYSCON_SYSCFG_LCSN2 (1<<1)
+ #define EP93XX_SYSCON_SYSCFG_LCSN1 (1<<0)
++#define EP93XX_SYSCON_CHIPID EP93XX_SYSCON_REG(0x94)
+ #define EP93XX_SYSCON_SWLOCK EP93XX_SYSCON_REG(0xc0)
+
+ #define EP93XX_WATCHDOG_BASE EP93XX_APB_IOMEM(0x00140000)
+diff --git a/arch/arm/mach-ep93xx/include/mach/memory.h b/arch/arm/mach-ep93xx/include/mach/memory.h
+index 554064e..78eaacf 100644
+--- a/arch/arm/mach-ep93xx/include/mach/memory.h
++++ b/arch/arm/mach-ep93xx/include/mach/memory.h
+@@ -19,4 +19,32 @@
+ #error "Kconfig bug: No EP93xx PHYS_OFFSET set"
+ #endif
+
++/*
++ * Non-linear mapping like so:
++ * phys => virt
++ * 0x00000000 => 0xc0000000
++ * 0x01000000 => 0xc1000000
++ * 0x04000000 => 0xc4000000
++ * 0x05000000 => 0xc5000000
++ * 0xe0000000 => 0xc8000000
++ * 0xe1000000 => 0xc9000000
++ * 0xe4000000 => 0xcc000000
++ * 0xe5000000 => 0xcd000000
++ *
++ * As suggested here: http://marc.info/?l=linux-arm&m=122754446724900&w=2
++ *
++ * Note that static inline functions won't work here because
++ * arch/arm/include/asm/memory.h uses "#ifndef __virt_to_phys" to check whether to
++ * use generic functions or not.
++ */
++
++#define __phys_to_virt(p) \
++ (((p) & 0x07ffffff) | (((p) & 0xe0000000) ? 0x08000000 : 0) | PAGE_OFFSET)
++
++#define __virt_to_phys(v) \
++ (((v) & 0x07ffffff) | (((v) & 0x08000000) ? 0xe0000000 : 0 ))
++
++#define SECTION_SIZE_BITS 24
++#define MAX_PHYSMEM_BITS 32
++
+ #endif
+diff --git a/arch/arm/mach-ep93xx/include/mach/ts72xx.h b/arch/arm/mach-ep93xx/include/mach/ts72xx.h
+index 0eabec6..1d50dec 100644
+--- a/arch/arm/mach-ep93xx/include/mach/ts72xx.h
++++ b/arch/arm/mach-ep93xx/include/mach/ts72xx.h
+@@ -8,36 +8,41 @@
+ * virt phys size
+ * febff000 22000000 4K model number register
+ * febfe000 22400000 4K options register
+- * febfd000 22800000 4K options register #2
++ * febfd000 22800000 4K options register #2 (JP6 and TS-9420 flags)
++ * febfc000 [67]0000000 4K NAND data register
++ * febfb000 [67]0400000 4K NAND control register
++ * febfa000 [67]0800000 4K NAND busy register
+ * febf9000 10800000 4K TS-5620 RTC index register
+ * febf8000 11700000 4K TS-5620 RTC data register
++ * febf7000 23400000 4K PLD version (3 bits)
++ * febf6000 22c00000 4K RS-485 control register
++ * febf5000 23000000 4K RS-485 mode register
+ */
+
+ #define TS72XX_MODEL_PHYS_BASE 0x22000000
+ #define TS72XX_MODEL_VIRT_BASE 0xfebff000
+ #define TS72XX_MODEL_SIZE 0x00001000
+
+-#define TS72XX_MODEL_TS7200 0x00
+-#define TS72XX_MODEL_TS7250 0x01
+-#define TS72XX_MODEL_TS7260 0x02
++#define TS7XXX_MODEL_TS7200 0x00
++#define TS7XXX_MODEL_TS7250 0x01
++#define TS7XXX_MODEL_TS7260 0x02
++#define TS7XXX_MODEL_TS7300 0x03
++#define TS7XXX_MODEL_TS7400 0x04
++#define TS7XXX_MODEL_MASK 0x07
+
+
+ #define TS72XX_OPTIONS_PHYS_BASE 0x22400000
+ #define TS72XX_OPTIONS_VIRT_BASE 0xfebfe000
+ #define TS72XX_OPTIONS_SIZE 0x00001000
+-
+ #define TS72XX_OPTIONS_COM2_RS485 0x02
+ #define TS72XX_OPTIONS_MAX197 0x01
+
+-
+ #define TS72XX_OPTIONS2_PHYS_BASE 0x22800000
+ #define TS72XX_OPTIONS2_VIRT_BASE 0xfebfd000
+ #define TS72XX_OPTIONS2_SIZE 0x00001000
+-
+ #define TS72XX_OPTIONS2_TS9420 0x04
+ #define TS72XX_OPTIONS2_TS9420_BOOT 0x02
+
+-
+ #define TS72XX_RTC_INDEX_VIRT_BASE 0xfebf9000
+ #define TS72XX_RTC_INDEX_PHYS_BASE 0x10800000
+ #define TS72XX_RTC_INDEX_SIZE 0x00001000
+@@ -49,32 +54,146 @@
+ #define TS72XX_WDT_CONTROL_PHYS_BASE 0x23800000
+ #define TS72XX_WDT_FEED_PHYS_BASE 0x23c00000
+
++#define TS72XX_PLD_VERSION_VIRT_BASE 0xfebf7000
++#define TS72XX_PLD_VERSION_PHYS_BASE 0x23400000
++#define TS72XX_PLD_VERSION_SIZE 0x00001000
++
++#define TS72XX_JUMPERS_MAX197_PHYS_BASE 0x10800000 // jumpers/max197 busy bit/COM1 dcd register (8-bit, read only)
++#define TS72XX_MAX197_SAMPLE_PHYS_BASE 0x10f00000 // max197 sample/control register (16-bit read/8-bit write)
++
++/*
++ * RS485 option
++ */
++#define TS72XX_RS485_CONTROL_VIRT_BASE 0xfebf6000
++#define TS72XX_RS485_CONTROL_PHYS_BASE 0x22c00000
++#define TS72XX_RS485_CONTROL_SIZE 0x00001000
++
++#define TS72XX_RS485_MODE_VIRT_BASE 0xfebf5000
++#define TS72XX_RS485_MODE_PHYS_BASE 0x23000000
++#define TS72XX_RS485_MODE_SIZE 0x00001000
++
++#define TS72XX_RS485_AUTO485FD 1
++#define TS72XX_RS485_AUTO485HD 2
++#define TS72XX_RS485_MODE_RS232 0x00
++#define TS72XX_RS485_MODE_FD 0x01
++#define TS72XX_RS485_MODE_9600_HD 0x04
++#define TS72XX_RS485_MODE_19200_HD 0x05
++#define TS72XX_RS485_MODE_57600_HD 0x06
++#define TS72XX_RS485_MODE_115200_HD 0x07
++
++/*
++ * PC/104 8-bit & 16-bit bus
++ *
++ * virt phys size
++ * febf0000 11e00000 4K PC/104 8-bit I/O
++ * febef000 21e00000 4K PC/104 16-bit I/O
++ * fea00000 11a00000 1MB PC/104 8-bit memory
++ * fe900000 21a00000 1MB PC/104 16-bit memory
++ */
++#define TS72XX_PC104_8BIT_IO_VIRT_BASE 0xfebf0000
++#define TS72XX_PC104_8BIT_IO_PHYS_BASE 0x11e00000
++#define TS72XX_PC104_8BIT_IO_SIZE 0x00001000
++#define TS72XX_PC104_8BIT_MEM_VIRT_BASE 0xfea00000
++#define TS72XX_PC104_8BIT_MEM_PHYS_BASE 0x11a00000
++#define TS72XX_PC104_8BIT_MEM_SIZE 0x00100000
++
++#define TS72XX_PC104_16BIT_IO_VIRT_BASE 0xfebef000
++#define TS72XX_PC104_16BIT_IO_PHYS_BASE 0x21e00000
++#define TS72XX_PC104_16BIT_IO_SIZE 0x00001000
++#define TS72XX_PC104_16BIT_MEM_VIRT_BASE 0xfe900000
++#define TS72XX_PC104_16BIT_MEM_PHYS_BASE 0x21a00000
++#define TS72XX_PC104_16BIT_MEM_SIZE 0x00100000
++
++/*
++ * TS7200 specific : CompactFlash memory map
++ *
++ * phys size description
++ * 11000000 7 CF registers (8-bit each), starting at 11000001
++ * 10400006 2 CF aux registers (8-bit)
++ * 21000000 2 CF data register (16-bit)
++ */
++#define TS7200_CF_CMD_PHYS_BASE 0x11000000
++#define TS7200_CF_AUX_PHYS_BASE 0x10400006
++#define TS7200_CF_DATA_PHYS_BASE 0x21000000
++
++/*
++ * TS7260 specific : SD card & Power Management
++ *
++ * phys size description
++ * 12000000 4K Power management register (8-bit)
++ * 13000000 4K SD card registers (4 x 8-bit)
++ */
++#define TS7260_POWER_MANAGEMENT_PHYS_BASE 0x12000000
++#define TS7260_PM_RS232_LEVEL_CONVERTER 0x01
++#define TS7260_PM_USB 0x02
++#define TS7260_PM_LCD 0x04
++#define TS7260_PM_5V_SWITCHER 0x08
++#define TS7260_PM_PC104_CLOCK 0x10
++#define TS7260_PM_PC104_FAST_STROBES 0x20
++#define TS7260_PM_TTL_UART_ENABLE 0x40
++#define TS7260_PM_SCRATCH_BIT 0x80
++
++#define TS7260_SDCARD_PHYS_BASE 0x13000000
++
+ #ifndef __ASSEMBLY__
+
+ static inline int board_is_ts7200(void)
+ {
+- return __raw_readb(TS72XX_MODEL_VIRT_BASE) == TS72XX_MODEL_TS7200;
++ return (__raw_readb(TS72XX_MODEL_VIRT_BASE) &
++ TS7XXX_MODEL_MASK) == TS7XXX_MODEL_TS7200;
+ }
+
+ static inline int board_is_ts7250(void)
+ {
+- return __raw_readb(TS72XX_MODEL_VIRT_BASE) == TS72XX_MODEL_TS7250;
++ return (__raw_readb(TS72XX_MODEL_VIRT_BASE) &
++ TS7XXX_MODEL_MASK) == TS7XXX_MODEL_TS7250;
+ }
+
+ static inline int board_is_ts7260(void)
+ {
+- return __raw_readb(TS72XX_MODEL_VIRT_BASE) == TS72XX_MODEL_TS7260;
++ return (__raw_readb(TS72XX_MODEL_VIRT_BASE) &
++ TS7XXX_MODEL_MASK) == TS7XXX_MODEL_TS7260;
++}
++
++static inline int board_is_ts7300(void)
++{
++ return (__raw_readb(TS72XX_MODEL_VIRT_BASE) &
++ TS7XXX_MODEL_MASK) == TS7XXX_MODEL_TS7300;
++}
++
++static inline int board_is_ts7400(void)
++{
++ return (__raw_readb(TS72XX_MODEL_VIRT_BASE) &
++ TS7XXX_MODEL_MASK) == TS7XXX_MODEL_TS7400;
+ }
+
+ static inline int is_max197_installed(void)
+ {
+ return !!(__raw_readb(TS72XX_OPTIONS_VIRT_BASE) &
+- TS72XX_OPTIONS_MAX197);
++ TS72XX_OPTIONS_MAX197);
+ }
+
+ static inline int is_ts9420_installed(void)
+ {
+ return !!(__raw_readb(TS72XX_OPTIONS2_VIRT_BASE) &
+- TS72XX_OPTIONS2_TS9420);
++ TS72XX_OPTIONS2_TS9420);
+ }
++
++static inline int is_rs485_installed(void)
++{
++ return !!(__raw_readb(TS72XX_OPTIONS_VIRT_BASE) &
++ TS72XX_OPTIONS_COM2_RS485);
++}
++
++static inline int get_ts72xx_pld_version(void)
++{
++ return (__raw_readb(TS72XX_PLD_VERSION_VIRT_BASE) & 0x7);
++}
++
++/* User jumper */
++static inline int is_jp6_set(void)
++{
++ return (__raw_readb(TS72XX_OPTIONS2_VIRT_BASE) & 0x1);
++}
++
+ #endif
+diff --git a/arch/arm/mach-ep93xx/ts72xx.c b/arch/arm/mach-ep93xx/ts72xx.c
+index c2d2cf4..a23a184 100644
+--- a/arch/arm/mach-ep93xx/ts72xx.c
++++ b/arch/arm/mach-ep93xx/ts72xx.c
+@@ -54,7 +54,36 @@ static struct map_desc ts72xx_io_desc[] __initdata = {
+ .pfn = __phys_to_pfn(TS72XX_RTC_DATA_PHYS_BASE),
+ .length = TS72XX_RTC_DATA_SIZE,
+ .type = MT_DEVICE,
+- }
++ },
++ /* Use this for debug only. Each device will map its own PC/104 address space */
++ ///* PC/104 (8-bit) I/O bus */
++ //{
++ // .virtual = TS72XX_PC104_8BIT_IO_VIRT_BASE,
++ // .pfn = __phys_to_pfn(TS72XX_PC104_8BIT_IO_PHYS_BASE),
++ // .length = TS72XX_PC104_8BIT_IO_SIZE,
++ // .type = MT_DEVICE,
++ //},
++ ///* PC/104 (16-bit) I/O bus */
++ //{
++ // .virtual = TS72XX_PC104_16BIT_IO_VIRT_BASE,
++ // .pfn = __phys_to_pfn(TS72XX_PC104_16BIT_IO_PHYS_BASE),
++ // .length = TS72XX_PC104_16BIT_IO_SIZE,
++ // .type = MT_DEVICE,
++ //},
++ ///* PC/104 (8-bit) MEM bus */
++ //{
++ // .virtual = TS72XX_PC104_8BIT_MEM_VIRT_BASE,
++ // .pfn = __phys_to_pfn(TS72XX_PC104_8BIT_MEM_PHYS_BASE),
++ // .length = TS72XX_PC104_8BIT_MEM_SIZE,
++ // .type = MT_DEVICE,
++ //},
++ ///* PC/104 (16-bit) MEM bus */
++ //{
++ // .virtual = TS72XX_PC104_16BIT_MEM_VIRT_BASE,
++ // .pfn = __phys_to_pfn(TS72XX_PC104_16BIT_MEM_PHYS_BASE),
++ // .length = TS72XX_PC104_16BIT_MEM_SIZE,
++ // .type = MT_DEVICE,
++ //}
+ };
+
+ static void __init ts72xx_map_io(void)
+@@ -194,7 +223,9 @@ static void __init ts72xx_register_flash(void)
+ }
+ }
+
+-
++/*************************************************************************
++ * RTC
++ *************************************************************************/
+ static unsigned char ts72xx_rtc_readbyte(unsigned long addr)
+ {
+ __raw_writeb(addr, TS72XX_RTC_INDEX_VIRT_BASE);
+@@ -242,6 +273,9 @@ static struct platform_device ts72xx_wdt_device = {
+ };
+
+ static struct ep93xx_eth_data __initdata ts72xx_eth_data = {
++/*************************************************************************
++ * Ethernet
++ *************************************************************************/
+ .phy_id = 1,
+ };
+
+@@ -253,6 +287,9 @@ static void __init ts72xx_init_machine(void)
+ platform_device_register(&ts72xx_wdt_device);
+
+ ep93xx_register_eth(&ts72xx_eth_data, 1);
++
++ /* PWM1 is DIO_6 on TS-72xx header */
++ ep93xx_register_pwm(0, 1);
+ }
+
+ MACHINE_START(TS72XX, "Technologic Systems TS-72xx SBC")
+diff --git a/arch/arm/mm/proc-arm920.S b/arch/arm/mm/proc-arm920.S
+index 6109f27..2b1d028 100644
+--- a/arch/arm/mm/proc-arm920.S
++++ b/arch/arm/mm/proc-arm920.S
+@@ -201,7 +201,7 @@ ENTRY(arm920_coherent_kern_range)
+ */
+ ENTRY(arm920_coherent_user_range)
+ bic r0, r0, #CACHE_DLINESIZE - 1
+-1: mcr p15, 0, r0, c7, c10, 1 @ clean D entry
++1: mcr p15, 0, r0, c7, c14, 1 @ clean+invalidate D entry
+ mcr p15, 0, r0, c7, c5, 1 @ invalidate I entry
+ add r0, r0, #CACHE_DLINESIZE
+ cmp r0, r1
+@@ -402,6 +402,9 @@ __arm920_setup:
+ mrc p15, 0, r0, c1, c0 @ get control register v4
+ bic r0, r0, r5
+ orr r0, r0, r6
++#ifdef CONFIG_CR1_NFBIT
++ orr r0, r0, #0x40000000 @ set nF
++#endif
+ mov pc, lr
+ .size __arm920_setup, . - __arm920_setup
+
+diff --git a/scripts/Makefile.fwinst b/scripts/Makefile.fwinst
+index 6bf8e87..fb20532 100644
+--- a/scripts/Makefile.fwinst
++++ b/scripts/Makefile.fwinst
+@@ -37,7 +37,7 @@ install-all-dirs: $(installed-fw-dirs)
+ @true
+
+ quiet_cmd_install = INSTALL $(subst $(srctree)/,,$@)
+- cmd_install = $(INSTALL) -m0644 $< $@
++ cmd_install = $(INSTALL) -m 0644 $< $@
+
+ $(installed-fw-dirs):
+ $(call cmd,mkdir)
+--
+1.7.1
+
diff --git a/recipes/linux/linux-2.6.38/ts72xx/0002-ts72xx_force_machine-id.patch b/recipes/linux/linux-2.6.38/ts72xx/0002-ts72xx_force_machine-id.patch
new file mode 100644
index 0000000..058c555
--- /dev/null
+++ b/recipes/linux/linux-2.6.38/ts72xx/0002-ts72xx_force_machine-id.patch
@@ -0,0 +1,49 @@
+From 06f63df8cea59ba0903c3decb15e1b4118352982 Mon Sep 17 00:00:00 2001
+From: Matthieu Crapet <mcrapet@gmail.com>
+Date: Thu, 10 Jun 2010 10:51:39 +0200
+Subject: [PATCH 02/24] ts72xx_force_machine-id
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Signed-off-by: Petr Štetiar <ynezz@true.cz>
+---
+ arch/arm/kernel/head.S | 3 +++
+ arch/arm/mach-ep93xx/Kconfig | 7 +++++++
+ 2 files changed, 10 insertions(+), 0 deletions(-)
+
+diff --git a/arch/arm/kernel/head.S b/arch/arm/kernel/head.S
+index f06ff9f..45ff97e 100644
+--- a/arch/arm/kernel/head.S
++++ b/arch/arm/kernel/head.S
+@@ -87,6 +87,9 @@ ENTRY(stext)
+ movs r10, r5 @ invalid processor (r5=0)?
+ THUMB( it eq ) @ force fixup-able long branch encoding
+ beq __error_p @ yes, error 'p'
++#ifdef CONFIG_MACH_TS72XX_FORCE_MACHINEID
++ ldr r1, =0x2a1
++#endif
+ bl __lookup_machine_type @ r5=machinfo
+ movs r8, r5 @ invalid machine (r5=0)?
+ THUMB( it eq ) @ force fixup-able long branch encoding
+diff --git a/arch/arm/mach-ep93xx/Kconfig b/arch/arm/mach-ep93xx/Kconfig
+index b6be37e..bd463a0 100644
+--- a/arch/arm/mach-ep93xx/Kconfig
++++ b/arch/arm/mach-ep93xx/Kconfig
+@@ -205,6 +205,13 @@ config EP93XX_EARLY_UART3
+
+ endchoice
+
++config MACH_TS72XX_FORCE_MACHINEID
++ bool "Force Machine ID"
++ depends on MACH_TS72XX
++ help
++ Say 'Y' here to force Machine ID to 0x2A1 (MACH_TYPE_TS72XX legacy value)
++ In early days Technologic Systems fixed the 0x163 value in redboot.
++
+ endmenu
+
+ endif
+--
+1.7.1
+
diff --git a/recipes/linux/linux-2.6.38/ts72xx/0003-ep93xx_cpuinfo.patch b/recipes/linux/linux-2.6.38/ts72xx/0003-ep93xx_cpuinfo.patch
new file mode 100644
index 0000000..c9bb6d0
--- /dev/null
+++ b/recipes/linux/linux-2.6.38/ts72xx/0003-ep93xx_cpuinfo.patch
@@ -0,0 +1,36 @@
+From a05609ce0126b285e632dcdb569dd46670d3bd4a Mon Sep 17 00:00:00 2001
+From: Matthieu Crapet <mcrapet@gmail.com>
+Date: Thu, 10 Jun 2010 10:59:31 +0200
+Subject: [PATCH 03/24] ep93xx_cpuinfo
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Signed-off-by: Petr Štetiar <ynezz@true.cz>
+---
+ arch/arm/kernel/setup.c | 9 +++++++++
+ 1 files changed, 9 insertions(+), 0 deletions(-)
+
+diff --git a/arch/arm/kernel/setup.c b/arch/arm/kernel/setup.c
+index 5ea4fb7..e47448f 100644
+--- a/arch/arm/kernel/setup.c
++++ b/arch/arm/kernel/setup.c
+@@ -986,6 +986,15 @@ static int c_show(struct seq_file *m, void *v)
+ seq_puts(m, "\n");
+
+ seq_printf(m, "Hardware\t: %s\n", machine_name);
++
++ #if defined(CONFIG_ARCH_EP93XX)
++ #include <mach/io.h>
++ #include <mach/ep93xx-regs.h>
++ system_rev = *((unsigned int *)EP93XX_SYSCON_CHIPID) >> 28;
++ system_serial_low = *((unsigned int *)EP93XX_SECURITY_UNIQID);
++ system_serial_high = 0;
++ #endif
++
+ seq_printf(m, "Revision\t: %04x\n", system_rev);
+ seq_printf(m, "Serial\t\t: %08x%08x\n",
+ system_serial_high, system_serial_low);
+--
+1.7.1
+
diff --git a/recipes/linux/linux-2.6.38/ts72xx/0004-ep93xx_eth.patch b/recipes/linux/linux-2.6.38/ts72xx/0004-ep93xx_eth.patch
new file mode 100644
index 0000000..88bfd66
--- /dev/null
+++ b/recipes/linux/linux-2.6.38/ts72xx/0004-ep93xx_eth.patch
@@ -0,0 +1,553 @@
+From f3a085dcaaeaccbc229b00050144a91a2d566c15 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Petr=20=C5=A0tetiar?= <ynezz@true.cz>
+Date: Sun, 13 Mar 2011 20:15:59 +0100
+Subject: [PATCH 04/24] ep93xx_eth
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Signed-off-by: Petr Štetiar <ynezz@true.cz>
+---
+ drivers/net/arm/Kconfig | 1 +
+ drivers/net/arm/ep93xx_eth.c | 345 ++++++++++++++++++++++++++++++++++--------
+ 2 files changed, 280 insertions(+), 66 deletions(-)
+
+diff --git a/drivers/net/arm/Kconfig b/drivers/net/arm/Kconfig
+index 39e1c0d..55c0dd4 100644
+--- a/drivers/net/arm/Kconfig
++++ b/drivers/net/arm/Kconfig
+@@ -52,6 +52,7 @@ config EP93XX_ETH
+ tristate "EP93xx Ethernet support"
+ depends on ARM && ARCH_EP93XX
+ select MII
++ select PHYLIB
+ help
+ This is a driver for the ethernet hardware included in EP93xx CPUs.
+ Say Y if you are building a kernel for EP93xx based devices.
+diff --git a/drivers/net/arm/ep93xx_eth.c b/drivers/net/arm/ep93xx_eth.c
+index 5a77001..f2f3a0b 100644
+--- a/drivers/net/arm/ep93xx_eth.c
++++ b/drivers/net/arm/ep93xx_eth.c
+@@ -2,6 +2,7 @@
+ * EP93xx ethernet network device driver
+ * Copyright (C) 2006 Lennert Buytenhek <buytenh@wantstofly.org>
+ * Dedicated to Marija Kulikova.
++ * Copyright (C) 2007 Herbert Valerio Riedel <hvr@gnu.org>
+ *
+ * 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
+@@ -16,6 +17,7 @@
+ #include <linux/kernel.h>
+ #include <linux/netdevice.h>
+ #include <linux/mii.h>
++#include <linux/phy.h>
+ #include <linux/etherdevice.h>
+ #include <linux/ethtool.h>
+ #include <linux/init.h>
+@@ -27,8 +29,8 @@
+
+ #include <mach/hardware.h>
+
+-#define DRV_MODULE_NAME "ep93xx-eth"
+-#define DRV_MODULE_VERSION "0.1"
++#define DRV_NAME "ep93xx-eth"
++#define DRV_VERSION "0.13"
+
+ #define RX_QUEUE_ENTRIES 64
+ #define TX_QUEUE_ENTRIES 8
+@@ -40,6 +42,8 @@
+ #define REG_RXCTL_DEFAULT 0x00073800
+ #define REG_TXCTL 0x0004
+ #define REG_TXCTL_ENABLE 0x00000001
++#define REG_TESTCTL 0x0008
++#define REG_TESTCTL_MFDX 0x00000040
+ #define REG_MIICMD 0x0010
+ #define REG_MIICMD_READ 0x00008000
+ #define REG_MIICMD_WRITE 0x00004000
+@@ -48,6 +52,9 @@
+ #define REG_MIISTS_BUSY 0x00000001
+ #define REG_SELFCTL 0x0020
+ #define REG_SELFCTL_RESET 0x00000001
++#define REG_SELFCTL_MDCDIV_MSK 0x00007e00
++#define REG_SELFCTL_MDCDIV_OFS 9
++#define REG_SELFCTL_PSPRS 0x00000100
+ #define REG_INTEN 0x0024
+ #define REG_INTEN_TX 0x00000008
+ #define REG_INTEN_RX 0x00000007
+@@ -177,6 +184,13 @@ struct ep93xx_priv
+
+ struct mii_if_info mii;
+ u8 mdc_divisor;
++ int phy_supports_mfps:1;
++
++ struct mii_bus mii_bus;
++ struct phy_device *phy_dev;
++ int speed;
++ int duplex;
++ int link;
+ };
+
+ #define rdb(ep, off) __raw_readb((ep)->base_addr + (off))
+@@ -186,46 +200,78 @@ struct ep93xx_priv
+ #define wrw(ep, off, val) __raw_writew((val), (ep)->base_addr + (off))
+ #define wrl(ep, off, val) __raw_writel((val), (ep)->base_addr + (off))
+
+-static int ep93xx_mdio_read(struct net_device *dev, int phy_id, int reg)
++/* common MII transactions should take < 100 iterations */
++#define EP93XX_PHY_TIMEOUT 2000
++
++static int ep93xx_mdio_wait(struct mii_bus *bus)
+ {
+- struct ep93xx_priv *ep = netdev_priv(dev);
+- int data;
+- int i;
++ struct ep93xx_priv *ep = bus->priv;
++ unsigned int timeout = EP93XX_PHY_TIMEOUT;
+
+- wrl(ep, REG_MIICMD, REG_MIICMD_READ | (phy_id << 5) | reg);
++ while ((rdl(ep, REG_MIISTS) & REG_MIISTS_BUSY)
++ && timeout--)
++ cpu_relax();
+
+- for (i = 0; i < 10; i++) {
+- if ((rdl(ep, REG_MIISTS) & REG_MIISTS_BUSY) == 0)
+- break;
+- msleep(1);
++ if (timeout <= 0) {
++ dev_err(&bus->dev, "MII operation timed out\n");
++ return -ETIMEDOUT;
+ }
+
+- if (i == 10) {
+- pr_info("mdio read timed out\n");
+- data = 0xffff;
+- } else {
+- data = rdl(ep, REG_MIIDATA);
+- }
++ return 0;
++}
++
++static int ep93xx_mdio_read(struct mii_bus *bus, int mii_id, int reg)
++{
++ struct ep93xx_priv *ep = bus->priv;
++ u32 selfctl;
++ u32 data;
++
++ if (ep93xx_mdio_wait(bus) < 0)
++ return -ETIMEDOUT;
++
++ selfctl = rdl(ep, REG_SELFCTL);
+
+- return data;
++ if (ep->phy_supports_mfps)
++ wrl(ep, REG_SELFCTL, selfctl | REG_SELFCTL_PSPRS);
++ else
++ wrl(ep, REG_SELFCTL, selfctl & ~REG_SELFCTL_PSPRS);
++
++ wrl(ep, REG_MIICMD, REG_MIICMD_READ | (mii_id << 5) | reg);
++
++ if (ep93xx_mdio_wait(bus) < 0)
++ return -ETIMEDOUT;
++
++ data = rdl(ep, REG_MIIDATA);
++
++ wrl(ep, REG_SELFCTL, selfctl);
++
++ return data;
+ }
+
+-static void ep93xx_mdio_write(struct net_device *dev, int phy_id, int reg, int data)
++static int ep93xx_mdio_write(struct mii_bus *bus, int mii_id, int reg, u16 data)
+ {
+- struct ep93xx_priv *ep = netdev_priv(dev);
+- int i;
++ struct ep93xx_priv *ep = bus->priv;
++ u32 selfctl;
++
++ if (ep93xx_mdio_wait(bus) < 0)
++ return -ETIMEDOUT;
++
++ selfctl = rdl(ep, REG_SELFCTL);
++
++ if (ep->phy_supports_mfps)
++ wrl(ep, REG_SELFCTL, selfctl | REG_SELFCTL_PSPRS);
++ else
++ wrl(ep, REG_SELFCTL, selfctl & ~REG_SELFCTL_PSPRS);
+
+ wrl(ep, REG_MIIDATA, data);
+- wrl(ep, REG_MIICMD, REG_MIICMD_WRITE | (phy_id << 5) | reg);
++ wrl(ep, REG_MIICMD, REG_MIICMD_WRITE | (mii_id << 5) | reg);
+
+- for (i = 0; i < 10; i++) {
+- if ((rdl(ep, REG_MIISTS) & REG_MIISTS_BUSY) == 0)
+- break;
+- msleep(1);
+- }
++ if (ep93xx_mdio_wait(bus) < 0)
++ return -ETIMEDOUT;
+
+- if (i == 10)
+- pr_info("mdio write timed out\n");
++ wrl(ep, REG_SELFCTL, selfctl);
++
++ return 0;
+ }
+
+ static int ep93xx_rx(struct net_device *dev, int processed, int budget)
+@@ -549,6 +595,22 @@ err:
+ return 1;
+ }
+
++static int ep93xx_mdio_reset(struct mii_bus *bus)
++{
++ struct ep93xx_priv *ep = bus->priv;
++
++ u32 selfctl = rdl(ep, REG_SELFCTL);
++
++ selfctl &= ~(REG_SELFCTL_MDCDIV_MSK | REG_SELFCTL_PSPRS);
++
++ selfctl |= (ep->mdc_divisor - 1) << REG_SELFCTL_MDCDIV_OFS;
++ selfctl |= REG_SELFCTL_PSPRS;
++
++ wrl(ep, REG_SELFCTL, selfctl);
++
++ return 0;
++}
++
+ static int ep93xx_start_hw(struct net_device *dev)
+ {
+ struct ep93xx_priv *ep = netdev_priv(dev);
+@@ -567,11 +629,8 @@ static int ep93xx_start_hw(struct net_device *dev)
+ return 1;
+ }
+
+- wrl(ep, REG_SELFCTL, ((ep->mdc_divisor - 1) << 9));
+-
+- /* Does the PHY support preamble suppress? */
+- if ((ep93xx_mdio_read(dev, ep->mii.phy_id, MII_BMSR) & 0x0040) != 0)
+- wrl(ep, REG_SELFCTL, ((ep->mdc_divisor - 1) << 9) | (1 << 8));
++ /* The reset cleared REG_SELFCTL, so set the MDC divisor again */
++ ep93xx_mdio_reset(&ep->mii_bus);
+
+ /* Receive descriptor ring. */
+ addr = ep->descs_dma_addr + offsetof(struct ep93xx_descs, rdesc);
+@@ -680,6 +739,8 @@ static int ep93xx_open(struct net_device *dev)
+
+ wrl(ep, REG_GIINTMSK, REG_GIINTMSK_ENABLE);
+
++ phy_start(ep->phy_dev);
++
+ netif_start_queue(dev);
+
+ return 0;
+@@ -692,6 +753,9 @@ static int ep93xx_close(struct net_device *dev)
+ napi_disable(&ep->napi);
+ netif_stop_queue(dev);
+
++ if (ep->phy_dev)
++ phy_stop(ep->phy_dev);
++
+ wrl(ep, REG_GIINTMSK, 0);
+ free_irq(ep->irq, dev);
+ ep93xx_stop_hw(dev);
+@@ -703,47 +767,44 @@ static int ep93xx_close(struct net_device *dev)
+ static int ep93xx_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
+ {
+ struct ep93xx_priv *ep = netdev_priv(dev);
+- struct mii_ioctl_data *data = if_mii(ifr);
+
+- return generic_mii_ioctl(&ep->mii, data, cmd, NULL);
++ return phy_mii_ioctl(ep->phy_dev, ifr, cmd);
+ }
+
+ static void ep93xx_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
+ {
+- strcpy(info->driver, DRV_MODULE_NAME);
+- strcpy(info->version, DRV_MODULE_VERSION);
++ strlcpy(info->driver, DRV_NAME, sizeof(info->driver));
++ strlcpy(info->version, DRV_VERSION, sizeof(info->version));
++ strlcpy(info->bus_info, dev_name(dev->dev.parent), sizeof(info->bus_info));
+ }
+
+ static int ep93xx_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
+ {
+ struct ep93xx_priv *ep = netdev_priv(dev);
+- return mii_ethtool_gset(&ep->mii, cmd);
++ struct phy_device *phydev = ep->phy_dev;
++
++ if (!phydev)
++ return -ENODEV;
++
++ return phy_ethtool_gset(phydev, cmd);
+ }
+
+ static int ep93xx_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
+ {
+ struct ep93xx_priv *ep = netdev_priv(dev);
+- return mii_ethtool_sset(&ep->mii, cmd);
+-}
++ struct phy_device *phydev = ep->phy_dev;
+
+-static int ep93xx_nway_reset(struct net_device *dev)
+-{
+- struct ep93xx_priv *ep = netdev_priv(dev);
+- return mii_nway_restart(&ep->mii);
+-}
++ if (!phydev)
++ return -ENODEV;
+
+-static u32 ep93xx_get_link(struct net_device *dev)
+-{
+- struct ep93xx_priv *ep = netdev_priv(dev);
+- return mii_link_ok(&ep->mii);
++ return phy_ethtool_sset(phydev, cmd);
+ }
+
+ static const struct ethtool_ops ep93xx_ethtool_ops = {
+ .get_drvinfo = ep93xx_get_drvinfo,
+ .get_settings = ep93xx_get_settings,
+ .set_settings = ep93xx_set_settings,
+- .nway_reset = ep93xx_nway_reset,
+- .get_link = ep93xx_get_link,
++ .get_link = ethtool_op_get_link,
+ };
+
+ static const struct net_device_ops ep93xx_netdev_ops = {
+@@ -804,6 +865,113 @@ static int ep93xx_eth_remove(struct platform_device *pdev)
+ return 0;
+ }
+
++static void ep93xx_adjust_link(struct net_device *dev)
++{
++ struct ep93xx_priv *ep = netdev_priv(dev);
++ struct phy_device *phydev = ep->phy_dev;
++
++ int status_change = 0;
++
++ if (phydev->link) {
++ if ((ep->speed != phydev->speed) ||
++ (ep->duplex != phydev->duplex)) {
++ /* speed and/or duplex state changed */
++ u32 testctl = rdl(ep, REG_TESTCTL);
++
++ if (DUPLEX_FULL == phydev->duplex)
++ testctl |= REG_TESTCTL_MFDX;
++ else
++ testctl &= ~(REG_TESTCTL_MFDX);
++
++ wrl(ep, REG_TESTCTL, testctl);
++
++ ep->speed = phydev->speed;
++ ep->duplex = phydev->duplex;
++ status_change = 1;
++ }
++ }
++
++ /* test for online/offline link transition */
++ if (phydev->link != ep->link) {
++ if (phydev->link) /* link went online */
++ netif_tx_schedule_all(dev);
++ else { /* link went offline */
++ ep->speed = 0;
++ ep->duplex = -1;
++ }
++ ep->link = phydev->link;
++
++ status_change = 1;
++ }
++
++ if (status_change)
++ phy_print_status(phydev);
++}
++
++static int ep93xx_mii_probe(struct net_device *dev, int phy_addr)
++{
++ struct ep93xx_priv *ep = netdev_priv(dev);
++ struct phy_device *phydev = NULL;
++ int val;
++
++ if (phy_addr >= 0 && phy_addr < PHY_MAX_ADDR)
++ phydev = ep->mii_bus.phy_map[phy_addr];
++
++ if (!phydev) {
++ pr_info("PHY not found at specified address,"
++ " trying autodetection\n");
++
++ /* find the first phy */
++ for (phy_addr = 0; phy_addr < PHY_MAX_ADDR; phy_addr++) {
++ if (ep->mii_bus.phy_map[phy_addr]) {
++ phydev = ep->mii_bus.phy_map[phy_addr];
++ break;
++ }
++ }
++ }
++
++ if (!phydev) {
++ pr_err("no PHY found\n");
++ return -ENODEV;
++ }
++
++ phydev = phy_connect(dev, dev_name(&phydev->dev),
++ ep93xx_adjust_link, 0, PHY_INTERFACE_MODE_MII);
++
++ if (IS_ERR(phydev)) {
++ pr_err("Could not attach to PHY\n");
++ return PTR_ERR(phydev);
++ }
++
++ ep->phy_supports_mfps = 0;
++
++ val = phy_read(phydev, MII_BMSR);
++ if (val < 0) {
++ pr_err("failed to read MII register\n");
++ return val;
++ }
++
++ if (val & 0x0040) {
++ pr_info("PHY supports MII frame preamble suppression\n");
++ ep->phy_supports_mfps = 1;
++ }
++
++ phydev->supported &= PHY_BASIC_FEATURES;
++
++ phydev->advertising = phydev->supported;
++
++ ep->link = 0;
++ ep->speed = 0;
++ ep->duplex = -1;
++ ep->phy_dev = phydev;
++
++ pr_info("attached PHY driver [%s] "
++ "(mii_bus:phy_addr=%s, irq=%d)\n",
++ phydev->drv->name, dev_name(&phydev->dev), phydev->irq);
++
++ return 0;
++}
++
+ static int ep93xx_eth_probe(struct platform_device *pdev)
+ {
+ struct ep93xx_eth_data *data;
+@@ -811,7 +979,7 @@ static int ep93xx_eth_probe(struct platform_device *pdev)
+ struct ep93xx_priv *ep;
+ struct resource *mem;
+ int irq;
+- int err;
++ int err, i;
+
+ if (pdev == NULL)
+ return -ENODEV;
+@@ -838,24 +1006,43 @@ static int ep93xx_eth_probe(struct platform_device *pdev)
+ if (ep->res == NULL) {
+ dev_err(&pdev->dev, "Could not reserve memory region\n");
+ err = -ENOMEM;
+- goto err_out;
++ goto err_out_request_mem_region;
+ }
+
+ ep->base_addr = ioremap(mem->start, resource_size(mem));
+ if (ep->base_addr == NULL) {
+ dev_err(&pdev->dev, "Failed to ioremap ethernet registers\n");
+ err = -EIO;
+- goto err_out;
++ goto err_out_ioremap;
+ }
+ ep->irq = irq;
+
+- ep->mii.phy_id = data->phy_id;
+- ep->mii.phy_id_mask = 0x1f;
+- ep->mii.reg_num_mask = 0x1f;
+- ep->mii.dev = dev;
+- ep->mii.mdio_read = ep93xx_mdio_read;
+- ep->mii.mdio_write = ep93xx_mdio_write;
++ /* mdio/mii bus */
++ ep->mii_bus.state = MDIOBUS_ALLOCATED; /* see mdiobus_alloc */
++ ep->mii_bus.name = "ep93xx_mii_bus";
++ snprintf(ep->mii_bus.id, MII_BUS_ID_SIZE, "0");
++
++ ep->mii_bus.read = ep93xx_mdio_read;
++ ep->mii_bus.write = ep93xx_mdio_write;
++ ep->mii_bus.reset = ep93xx_mdio_reset;
++
++ ep->mii_bus.phy_mask = 0;
++
++ ep->mii_bus.priv = ep;
++ ep->mii_bus.dev = dev->dev;
++
++ ep->mii_bus.irq = kmalloc(sizeof(int)*PHY_MAX_ADDR, GFP_KERNEL);
++ if (NULL == ep->mii_bus.irq) {
++ dev_err(&pdev->dev, "Could not allocate memory\n");
++ err = -ENOMEM;
++ goto err_out_mii_bus_irq_kmalloc;
++ }
++
++ for (i = 0; i < PHY_MAX_ADDR; i++)
++ ep->mii_bus.irq[i] = PHY_POLL;
++
+ ep->mdc_divisor = 40; /* Max HCLK 100 MHz, min MDIO clk 2.5 MHz. */
++ ep->phy_supports_mfps = 0; /* probe without preamble suppression */
+
+ if (is_zero_ether_addr(dev->dev_addr))
+ random_ether_addr(dev->dev_addr);
+@@ -863,14 +1050,39 @@ static int ep93xx_eth_probe(struct platform_device *pdev)
+ err = register_netdev(dev);
+ if (err) {
+ dev_err(&pdev->dev, "Failed to register netdev\n");
+- goto err_out;
++ goto err_out_register_netdev;
++ }
++
++ err = mdiobus_register(&ep->mii_bus);
++ if (err) {
++ dev_err(&dev->dev, "Could not register MII bus\n");
++ goto err_out_mdiobus_register;
++ }
++
++ err = ep93xx_mii_probe(dev, data->phy_id);
++ if (err) {
++ dev_err(&dev->dev, "failed to probe MII bus\n");
++ goto err_out_mii_probe;
+ }
+
+- printk(KERN_INFO "%s: ep93xx on-chip ethernet, IRQ %d, %pM\n",
+- dev->name, ep->irq, dev->dev_addr);
++ dev_info(&dev->dev, "ep93xx on-chip ethernet, IRQ %d, %pM\n",
++ ep->irq, dev->dev_addr);
+
+ return 0;
+
++err_out_mii_probe:
++ mdiobus_unregister(&ep->mii_bus);
++err_out_mdiobus_register:
++ unregister_netdev(dev);
++err_out_register_netdev:
++ kfree(ep->mii_bus.irq);
++err_out_mii_bus_irq_kmalloc:
++ iounmap(ep->base_addr);
++err_out_ioremap:
++ release_resource(ep->res);
++ kfree(ep->res);
++err_out_request_mem_region:
++ free_netdev(dev);
+ err_out:
+ ep93xx_eth_remove(pdev);
+ return err;
+@@ -888,7 +1100,6 @@ static struct platform_driver ep93xx_eth_driver = {
+
+ static int __init ep93xx_eth_init_module(void)
+ {
+- printk(KERN_INFO DRV_MODULE_NAME " version " DRV_MODULE_VERSION " loading\n");
+ return platform_driver_register(&ep93xx_eth_driver);
+ }
+
+@@ -899,5 +1110,7 @@ static void __exit ep93xx_eth_cleanup_module(void)
+
+ module_init(ep93xx_eth_init_module);
+ module_exit(ep93xx_eth_cleanup_module);
++
+ MODULE_LICENSE("GPL");
+-MODULE_ALIAS("platform:ep93xx-eth");
++MODULE_DESCRIPTION("EP93XX Ethernet driver");
++MODULE_ALIAS("platform:" DRV_NAME);
+--
+1.7.1
+
diff --git a/recipes/linux/linux-2.6.38/ts72xx/0005-ep93xx-m2m-DMA-support.patch b/recipes/linux/linux-2.6.38/ts72xx/0005-ep93xx-m2m-DMA-support.patch
new file mode 100644
index 0000000..85a9d22
--- /dev/null
+++ b/recipes/linux/linux-2.6.38/ts72xx/0005-ep93xx-m2m-DMA-support.patch
@@ -0,0 +1,870 @@
+From b4c071550b2f78fd8e80c8ae30076e896a9489c1 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Petr=20=C5=A0tetiar?= <ynezz@true.cz>
+Date: Sun, 13 Mar 2011 20:29:56 +0100
+Subject: [PATCH 05/24] ep93xx: m2m DMA support
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Signed-off-by: Petr Štetiar <ynezz@true.cz>
+---
+ arch/arm/mach-ep93xx/Makefile | 2 +-
+ arch/arm/mach-ep93xx/dma-m2m.c | 753 +++++++++++++++++++++++++++++++
+ arch/arm/mach-ep93xx/include/mach/dma.h | 63 +++
+ 3 files changed, 817 insertions(+), 1 deletions(-)
+ create mode 100644 arch/arm/mach-ep93xx/dma-m2m.c
+
+diff --git a/arch/arm/mach-ep93xx/Makefile b/arch/arm/mach-ep93xx/Makefile
+index 33ee2c8..ea652c2 100644
+--- a/arch/arm/mach-ep93xx/Makefile
++++ b/arch/arm/mach-ep93xx/Makefile
+@@ -1,7 +1,7 @@
+ #
+ # Makefile for the linux kernel.
+ #
+-obj-y := core.o clock.o dma-m2p.o gpio.o
++obj-y := core.o clock.o dma-m2p.o dma-m2m.o gpio.o
+ obj-m :=
+ obj-n :=
+ obj- :=
+diff --git a/arch/arm/mach-ep93xx/dma-m2m.c b/arch/arm/mach-ep93xx/dma-m2m.c
+new file mode 100644
+index 0000000..8b0d720
+--- /dev/null
++++ b/arch/arm/mach-ep93xx/dma-m2m.c
+@@ -0,0 +1,753 @@
++/*
++ * arch/arm/mach-ep93xx/dma-m2m.c
++ * M2M DMA handling for Cirrus EP93xx chips.
++ * Copyright (C) 2007 Metasoft <prylowski@xxxxxxxxxxx>
++ *
++ * Based on dma-m2p.c by:
++ * Copyright (C) 2006 Lennert Buytenhek <buytenh@xxxxxxxxxxxxxx>
++ * Copyright (C) 2006 Applied Data Systems
++ *
++ * 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.
++ */
++
++#define pr_fmt(fmt) "ep93xx " KBUILD_MODNAME ": " fmt
++
++#include <linux/kernel.h>
++#include <linux/clk.h>
++#include <linux/err.h>
++#include <linux/interrupt.h>
++#include <linux/module.h>
++#include <linux/string.h>
++#include <linux/io.h>
++
++#include <mach/dma.h>
++#include <mach/hardware.h>
++
++/* TEMP */
++#define DPRINTK(fmt, args...)
++
++#define M2M_CONTROL 0x00
++#define M2M_INTERRUPT 0x04
++#define M2M_STATUS 0x0c
++#define M2M_BCR0 0x10
++#define M2M_BCR1 0x14
++#define M2M_SAR_BASE0 0x18
++#define M2M_SAR_BASE1 0x1c
++#define M2M_SAR_CURR0 0x24
++#define M2M_SAR_CURR1 0x28
++#define M2M_DAR_BASE0 0x2c
++#define M2M_DAR_BASE1 0x30
++#define M2M_DAR_CURR0 0x34
++#define M2M_DAR_CURR1 0x3c
++
++
++/* control register bits */
++#define CTRL_STALL_INT_EN 0x00000001 /* stall interrupt enable */
++#define CTRL_SCT 0x00000002 /* source copy transfer
++ (1 elem. from source fills
++ destination block */
++#define CTRL_DONE_INT_EN 0x00000004 /* done interrupt enable */
++#define CTRL_ENABLE 0x00000008 /* channel enable / disable,
++ should be set after
++ write to SAR/DAR/BCR
++ registers */
++#define CTRL_NFB_INT_EN 0x00200000 /* nfb (next frame buffer)
++ interrupt enable */
++
++
++#define CTRL_START 0x00000010 /* software triggered
++ dma start, not used
++ for M2P/P2M/IDE/SSP */
++#define CTRL_BWC_MASK 0x000001e0 /* bandwidth control (number
++ of bytes in a block
++ transfer, only M2M */
++#define CTRL_BWC_SHIFT 5
++
++#define BWC_FULL 0x0 /* full bandwidth utilized */
++#define BWC_16 0x1 /* 16 bytes per block */
++#define BWC_32 0x5
++#define BWC_64 0x6
++#define BWC_128 0x7
++#define BWC_256 0x8
++#define BWC_512 0x9
++#define BWC_1024 0xa
++#define BWC_2048 0xb
++#define BWC_4096 0xc
++#define BWC_8192 0xd
++#define BWC_16384 0xe
++#define BWC_32768 0xf
++
++#define CTRL_PW_MASK 0x00000600 /* peripheral width,
++ only M2P/P2M */
++#define CTRL_PW_SHIFT 9
++
++#define PW_BYTE 0x0 /* one byte width */
++#define PW_HALFWORD 0x1 /* 16 bits */
++#define PW_WORD 0x2 /* 32 bits */
++#define PW_NOT_USED 0x3
++
++#define CTRL_DAH 0x00000800 /* destination address
++ hold, for M2P */
++#define CTRL_SAH 0x00001000 /* source address
++ hold, for P2M */
++#define CTRL_TM_MASK 0x00006000 /* transfer mode */
++#define CTRL_TM_SHIFT 13
++
++#define TM_M2M 0x0 /* software initiated M2M transfer */
++#define TM_M2P 0x1 /* memory to ext. peripheral
++ or IDE/SSP */
++#define TM_P2M 0x2 /* ext. peripheral or IDE/SSP
++ to memory */
++#define TM_NOT_USED 0x3
++
++#define CTRL_ETDP_MASK 0x00018000 /* end of transfer/terminal
++ count pin direction
++ & polarity */
++#define CTRL_ETDP_SHIFT 15
++
++#define ETDP_ACT_LOW_EOT 0x0 /* pin programmed as active
++ * low end-of-transfer input */
++#define ETDP_ACT_HIGH_EOT 0x1 /* active high eot input */
++#define ETDP_ACT_LOW_TC 0x2 /* active low terminal count output */
++#define ETDP_ACT_HIGH_TC 0x3 /* active high tc output */
++
++#define CTRL_DACKP 0x00020000 /* dma acknowledge pin
++ polarity */
++#define CTRL_DREQP_MASK 0x00180000 /* dma request pin polarity */
++#define CTRL_DREQP_SHIFT 19
++
++#define DREQP_ACT_LOW_LEVEL 0x0 /* DREQ is active low, level
++ sensitive */
++#define DREQP_ACT_HIGH_LEVEL 0x1 /* active high, level sensitive */
++#define DREQP_ACT_LOW_EDGE 0x2 /* active low, edge sensitive */
++#define DREQP_ACT_HIGH_EDGE 0x3 /* active high, edge sensitive */
++
++
++#define CTRL_RSS_MASK 0x00c00000 /* request source selection */
++#define CTRL_RSS_SHIFT 22
++
++#define RSS_EXT 0x0 /* external dma request */
++#define RSS_SSP_RX 0x1 /* internal SSPRx */
++#define RSS_SSP_TX 0x2 /* internal SSPTx */
++#define RSS_IDE 0x3 /* internal IDE */
++
++#define CTRL_NO_HDSK 0x01000000 /* no handshake, required for
++ SSP/IDE, optional for
++ ext. M2P/P2M */
++
++/* interrupt register bits */
++#define INTR_STALL 0x1
++#define INTR_DONE 0x2
++#define INTR_NFB 0x4
++#define INTR_ALL 0x7
++
++/* status register bits */
++#define STAT_STALL 0x0001 /* waiting for software start
++ or device request */
++#define STAT_CTL_STATE_MASK 0x000e /* control fsm state */
++#define STAT_CTL_STATE_SHIFT 1
++
++#define CTL_STATE_IDLE 0x0
++#define CTL_STATE_STALL 0x1
++#define CTL_STATE_MEM_RD 0x2
++#define CTL_STATE_MEM_WR 0x3
++#define CTL_STATE_BWC_WAIT 0x4
++
++#define STAT_BUF_STATE_MASK 0x0030 /* buffer fsm state */
++#define STAT_BUF_STATE_SHIFT 4
++
++#define BUF_STATE_NO_BUF 0x0
++#define BUF_STATE_BUF_ON 0x1
++#define BUF_STATE_BUF_NEXT 0x2
++
++#define STAT_DONE 0x0040 /* transfer completed successfully
++ (by device or BCR is 0) */
++
++#define STAT_TCS_MASK 0x0018 /* terminal count status */
++#define STAT_TCS_SHIFT 7
++
++#define TCS_NONE 0x0 /* terminal count not reached
++ for buffer0 and buffer1 */
++#define TCS_BUF0 0x1 /* terminal count reached
++ for buffer0 */
++#define TCS_BUF1 0x2
++#define TCS_BOTH 0x3 /* terminal count reached
++ for both buffers */
++
++#define STAT_EOTS_MASK 0x0060 /* end of transfer status */
++#define STAT_EOTS_SHIFT 9
++
++#define EOTS_NONE 0x0 /* end of transfer has not been
++ requested by ext. periph. for
+++ any buffer */
++#define EOTS_BUF0 0x1 /* eot requested for buffer0 */
++#define EOTS_BUF1 0x2
++#define EOTS_BOTH 0x3 /* eot requested for both buffers */
++
++#define STAT_NFB 0x0800 /* next frame buffer interrupt */
++#define STAT_NB 0x1000 /* next buffer status, inform which
++ buffer is free for update */
++#define STAT_DREQS 0x2000 /* status of dma request signal from
++ ext. periph or IDE/SSP request */
++
++/* IDE/SSP support */
++#define IDE_UDMA_DATAOUT 0x20
++#define IDE_UDMA_DATAIN 0x24
++
++#ifndef SSPDR
++#define SSPDR 0x08
++#endif
++
++struct m2m_channel {
++ char *name;
++ void __iomem *base;
++ int irq;
++
++ struct clk *clk;
++ spinlock_t lock;
++
++ void *client;
++ unsigned next_slot:1;
++ struct ep93xx_dma_buffer *buffer_xfer;
++ struct ep93xx_dma_buffer *buffer_next;
++ struct list_head buffers_pending;
++};
++
++static struct m2m_channel m2m_rxtx[] = {
++ {"m2m0", EP93XX_DMA_BASE + 0x0100, IRQ_EP93XX_DMAM2M0},
++ {"m2m1", EP93XX_DMA_BASE + 0x0140, IRQ_EP93XX_DMAM2M1},
++ {NULL},
++};
++
++
++static void feed_buf(struct m2m_channel *ch, struct ep93xx_dma_buffer *buf)
++{
++ struct ep93xx_dma_m2m_client *cl = ch->client;
++ u32 src_addr, dst_addr;
++
++ if ((cl->flags & EP93XX_DMA_M2M_DIR_MASK) == EP93XX_DMA_M2M_TX) {
++ src_addr = buf->bus_addr;
++ switch (cl->flags & EP93XX_DMA_M2M_DEV_MASK) {
++ case EP93XX_DMA_M2M_DEV_IDE:
++ dst_addr = EP93XX_IDE_PHYS_BASE + IDE_UDMA_DATAOUT;
++ break;
++ case EP93XX_DMA_M2M_DEV_SSP:
++ dst_addr = EP93XX_SPI_PHYS_BASE + SSPDR;
++ break;
++ default:
++ dst_addr = buf->bus_addr2;
++ break;
++ }
++ } else {
++ switch (cl->flags & EP93XX_DMA_M2M_DEV_MASK) {
++ case EP93XX_DMA_M2M_DEV_IDE:
++ src_addr = EP93XX_IDE_PHYS_BASE + IDE_UDMA_DATAIN;
++ break;
++ case EP93XX_DMA_M2M_DEV_SSP:
++ src_addr = EP93XX_SPI_PHYS_BASE + SSPDR;
++ break;
++ default:
++ src_addr = buf->bus_addr2;
++ break;
++ }
++ dst_addr = buf->bus_addr;
++ }
++
++ if (ch->next_slot == 0) {
++ DPRINTK("Writing src_addr: %08x\n", src_addr);
++ DPRINTK("Writing dest_addr: %08x\n", dst_addr);
++ DPRINTK("Writing size: %08x\n", buf->size);
++ writel(src_addr, ch->base + M2M_SAR_BASE0);
++ writel(dst_addr, ch->base + M2M_DAR_BASE0);
++ writel(buf->size, ch->base + M2M_BCR0);
++ } else {
++ writel(src_addr, ch->base + M2M_SAR_BASE1);
++ writel(dst_addr, ch->base + M2M_DAR_BASE1);
++ writel(buf->size, ch->base + M2M_BCR1);
++ }
++ ch->next_slot ^= 1;
++ DPRINTK("data size = %d, slot %d\n", buf->size, ch->next_slot ^ 1);
++}
++
++static void choose_buffer_xfer(struct m2m_channel *ch)
++{
++ struct ep93xx_dma_buffer *buf;
++
++ ch->buffer_xfer = NULL;
++ if (!list_empty(&ch->buffers_pending)) {
++ buf = list_entry(ch->buffers_pending.next,
++ struct ep93xx_dma_buffer, list);
++ list_del(&buf->list);
++ feed_buf(ch, buf);
++ ch->buffer_xfer = buf;
++ }
++}
++
++static void choose_buffer_next(struct m2m_channel *ch)
++{
++ struct ep93xx_dma_buffer *buf;
++
++ ch->buffer_next = NULL;
++ if (!list_empty(&ch->buffers_pending)) {
++ buf = list_entry(ch->buffers_pending.next,
++ struct ep93xx_dma_buffer, list);
++ list_del(&buf->list);
++ feed_buf(ch, buf);
++ ch->buffer_next = buf;
++ }
++}
++
++static irqreturn_t m2m_irq(int irq, void *dev_id)
++{
++ struct m2m_channel *ch = dev_id;
++ struct ep93xx_dma_m2m_client *cl;
++ u32 irq_status, dma_state, buf_state, ctl_state;
++
++ spin_lock(&ch->lock);
++ irq_status = readl(ch->base + M2M_INTERRUPT);
++ /*if ((irq_status & INTR_ALL) == 0) {
++ spin_unlock(&ch->lock);
++ return IRQ_NONE;
++ }*/
++ dma_state = readl(ch->base + M2M_STATUS);
++ cl = ch->client;
++
++ //printk("intr status: %08x, dma state: %08x\n", irq_status, dma_state);
++
++ DPRINTK("intr status %d, dma state %x\n",
++ irq_status, dma_state);
++
++ buf_state = (dma_state & STAT_BUF_STATE_MASK) >> STAT_BUF_STATE_SHIFT;
++ ctl_state = (dma_state & STAT_CTL_STATE_MASK) >> STAT_CTL_STATE_SHIFT;
++ /*printk("STAT_CTL_STATE: %d, STAT_BUF_STATE: %d\n",
++ * ctl_state, buf_state);*/
++ if (ctl_state == CTL_STATE_STALL &&
++ buf_state == BUF_STATE_NO_BUF &&
++ dma_state & STAT_DONE) {
++ /* transfer completed successfully (done) */
++
++
++ /* send client the done command */
++ if (cl->buffer_finished) {
++ cl->buffer_finished(cl->cookie, ch->buffer_xfer, ch->buffer_xfer->size, 0);
++ }
++
++ writel(0, ch->base + M2M_INTERRUPT);
++ choose_buffer_xfer(ch);
++ choose_buffer_next(ch);
++ if (ch->buffer_xfer != NULL) {
++ /* retrigger if more buffers exist */
++ if ((cl->flags & EP93XX_DMA_M2M_DEV_MASK) ==
++ EP93XX_DMA_M2M_DEV_MEM) {
++ DPRINTK("Writing start1 to M2M control\n");
++ writel(readl(ch->base + M2M_CONTROL) |
++ CTRL_START, ch->base + M2M_CONTROL);
++ readl(ch->base + M2M_CONTROL);
++ }
++ } else {
++ DPRINTK("DISABLING DMA: dreqs state: %d\n", dma_state & STAT_DREQS);
++
++ writel(readl(ch->base + M2M_CONTROL)
++ & ~CTRL_ENABLE, ch->base + M2M_CONTROL);
++ readl(ch->base + M2M_CONTROL);
++ }
++ } else if (ctl_state == CTL_STATE_MEM_RD &&
++ buf_state == BUF_STATE_BUF_ON &&
++ dma_state & STAT_NFB) {
++ /* next frame buffer */
++ if (cl->buffer_finished) {
++ cl->buffer_finished(cl->cookie, ch->buffer_xfer, 0, 0);
++ }
++ ch->buffer_xfer = ch->buffer_next;
++ choose_buffer_next(ch);
++ }
++
++ if (cl->buffer_started && ch->buffer_xfer != NULL) {
++ cl->buffer_started(cl->cookie, ch->buffer_xfer);
++ }
++
++ spin_unlock(&ch->lock);
++ return IRQ_HANDLED;
++}
++
++static struct m2m_channel *find_free_channel(struct ep93xx_dma_m2m_client *cl, int channel_spec)
++{
++ struct m2m_channel *ch = m2m_rxtx;
++ int i;
++
++#if 0
++ /* BMS: This code isn't particularly clear; look like it asserts
++ * that a requested channel must not share the same data direction
++ * as a previously requested channel - which makes sense for the SSP,
++ * but not at all for direct hardware transferrs
++ */
++ for (i = 0; ch[i].base; i++) {
++ struct ep93xx_dma_m2m_client *cl2;
++
++ cl2 = ch[i].client;
++ if (cl2 != NULL) {
++ int port;
++
++ /* two the same devices in the same direction
++ are not allowed
++ (two "memory devices" should be allowed) */
++ port = cl2->flags & (EP93XX_DMA_M2M_DEV_MASK |
++ EP93XX_DMA_M2M_DIR_MASK);
++ if (port == (cl->flags & (EP93XX_DMA_M2M_DEV_MASK |
++ EP93XX_DMA_M2M_DIR_MASK)))
++ return NULL;
++ }
++ }
++#endif
++
++ if (channel_spec == EP93XX_DMA_M2M_REQUIRES_CH_ANY) {
++ for (i = 0; ch[i].base; i++) {
++ if (ch[i].client == NULL)
++ return ch + i;
++ }
++ } else if (channel_spec == EP93XX_DMA_M2M_REQUIRES_CH_0) {
++ if (ch[0].client == NULL) {
++ return &(ch[0]);
++ }
++ } else if (channel_spec == EP93XX_DMA_M2M_REQUIRES_CH_1) {
++ if (ch[1].client == NULL) {
++ return &(ch[1]);
++ }
++ } else {
++ printk(KERN_ERR "ep93xx-m2m dma channel request: unknown channel spec\n");
++ }
++ return NULL;
++}
++
++static u32 set_direction_reg(u32 outv, u32 flags)
++{
++ switch (flags & EP93XX_DMA_M2M_DEV_MASK) {
++ case EP93XX_DMA_M2M_DEV_EXT:
++ outv &= ~(CTRL_SAH | CTRL_DAH | CTRL_TM_MASK);
++
++ if (flags & EP93XX_DMA_M2M_EXT_FIFO)
++ outv |= (flags & EP93XX_DMA_M2M_DIR_MASK) ==
++ EP93XX_DMA_M2M_TX ? CTRL_DAH : CTRL_SAH;
++
++ outv |= (((flags & EP93XX_DMA_M2M_DIR_MASK) ==
++ EP93XX_DMA_M2M_TX) ? TM_M2P : TM_P2M) <<
++ CTRL_TM_SHIFT;
++
++ break;
++ case EP93XX_DMA_M2M_DEV_IDE:
++ outv &= ~(CTRL_SAH | CTRL_DAH | CTRL_TM_MASK | CTRL_PWSC_MASK);
++ if ((flags & EP93XX_DMA_M2M_DIR_MASK) == EP93XX_DMA_M2M_TX) {
++ outv |= (2 << CTRL_PWSC_SHIFT) & CTRL_PWSC_MASK;
++ outv |= CTRL_DAH;
++ outv |= TM_M2P << CTRL_TM_SHIFT;
++ } else {
++ outv |= (1 << CTRL_PWSC_SHIFT) & CTRL_PWSC_MASK;
++ outv |= CTRL_SAH;
++ outv |= TM_P2M << CTRL_TM_SHIFT;
++ }
++ break;
++ case EP93XX_DMA_M2M_DEV_SSP:
++ outv &= ~(CTRL_SAH | CTRL_DAH | CTRL_TM_MASK | CTRL_RSS_MASK);
++ if ((flags & EP93XX_DMA_M2M_DIR_MASK) == EP93XX_DMA_M2M_TX) {
++ outv |= TM_M2P << CTRL_TM_SHIFT;
++ outv |= CTRL_DAH;
++ outv |= RSS_SSP_TX << CTRL_RSS_SHIFT;
++ } else {
++ outv |= TM_P2M << CTRL_TM_SHIFT;
++ outv |= CTRL_SAH;
++ outv |= RSS_SSP_RX << CTRL_RSS_SHIFT;
++ }
++ break;
++ case EP93XX_DMA_M2M_DEV_MEM:
++ break;
++ }
++ return outv;
++}
++
++static void channel_enable(struct m2m_channel *ch)
++{
++ struct ep93xx_dma_m2m_client *cl = ch->client;
++ u32 outv = 0;
++
++ clk_enable(ch->clk);
++
++ /* set peripheral wait state mask - IFF specified in control word */
++ outv |= (cl->flags & CTRL_PWSC_MASK);
++ outv |= (cl->flags & EP93XX_DREQ_MASK);
++
++ DPRINTK("Set outv to: %08x\n",outv);
++
++ switch (cl->flags & EP93XX_DMA_M2M_DEV_MASK) {
++ case EP93XX_DMA_M2M_DEV_EXT:
++ switch (cl->flags & EP93XX_DMA_M2M_EXT_WIDTH_MASK) {
++ case EP93XX_DMA_M2M_EXT_WIDTH_BYTE:
++ outv |= PW_BYTE << CTRL_PW_SHIFT;
++ break;
++ case EP93XX_DMA_M2M_EXT_WIDTH_2BYTES:
++ outv |= PW_HALFWORD << CTRL_PW_SHIFT;
++ break;
++ case EP93XX_DMA_M2M_EXT_WIDTH_4BYTES:
++ outv |= PW_WORD << CTRL_PW_SHIFT;
++ break;
++ }
++ /* if NO_HDSK then PWSC, if not, then DREQ, DACK, TC/DEOT */
++ if (cl->flags & EP93XX_DMA_M2M_EXT_NO_HDSK) {
++ outv |= CTRL_NO_HDSK;
++ /* TODO: wait states */
++ } else {
++ /* TODO: regular handshaking */
++ }
++ outv |= RSS_EXT << CTRL_RSS_SHIFT;
++ break;
++ case EP93XX_DMA_M2M_DEV_IDE:
++ /* NO_HDSK, PWSC, PW, SAH, DAH */
++ outv |= CTRL_NO_HDSK;
++ outv |= PW_WORD << CTRL_PW_SHIFT;
++ /* PWSC = 1 for read, PWSC = 2 for write in UDMA */
++ outv |= RSS_IDE << CTRL_RSS_SHIFT;
++ break;
++ case EP93XX_DMA_M2M_DEV_SSP:
++ outv |= CTRL_NO_HDSK;
++ outv |= PW_HALFWORD << CTRL_PW_SHIFT;
++ outv |= (8 << CTRL_PWSC_SHIFT) & CTRL_PWSC_MASK;
++ break;
++ case EP93XX_DMA_M2M_DEV_MEM:
++ switch (cl->flags & EP93XX_DMA_M2M_MEM_SPEED_MASK) {
++ case EP93XX_DMA_M2M_MEM_SPEED_FULL:
++ outv |= BWC_FULL << CTRL_BWC_SHIFT;
++ break;
++ case EP93XX_DMA_M2M_MEM_SPEED_HALF:
++ outv |= BWC_32768 << CTRL_BWC_SHIFT;
++ break;
++ case EP93XX_DMA_M2M_MEM_SPEED_QUART:
++ outv |= BWC_16384 << CTRL_BWC_SHIFT;
++ break;
++ case EP93XX_DMA_M2M_MEM_SPEED_SLOW:
++ outv |= BWC_16 << CTRL_BWC_SHIFT;
++ break;
++ }
++ outv |= (cl->flags & EP93XX_DMA_M2M_MEM_FILL) ? CTRL_SCT : 0;
++ outv |= TM_M2M << CTRL_TM_SHIFT;
++ break;
++ }
++
++ // debug code
++ DPRINTK("PRE-Enable, status is: %08x\n", readl(ch->base+M2M_STATUS));
++
++ outv = set_direction_reg(outv, cl->flags);
++ /* STALL interrupt must be enabled */
++ outv |= CTRL_NFB_INT_EN | CTRL_DONE_INT_EN | CTRL_STALL_INT_EN;
++
++ writel(outv, ch->base + M2M_CONTROL);
++ outv = readl(ch->base + M2M_CONTROL);
++ DPRINTK("channel enable, writing control reg = %08x\n", outv);
++}
++
++static void channel_disable(struct m2m_channel *ch)
++{
++ u32 v;
++
++ DPRINTK("Disabling channel\n");
++ v = readl(ch->base + M2M_CONTROL);
++
++ writel(v & ~(CTRL_NFB_INT_EN | CTRL_DONE_INT_EN | CTRL_STALL_INT_EN),
++ ch->base + M2M_CONTROL);
++
++ v = readl(ch->base + M2M_CONTROL);
++
++ while (readl(ch->base + M2M_STATUS) & STAT_NFB) {
++ cpu_relax();
++ }
++
++ writel(0, ch->base + M2M_CONTROL);
++
++ v = readl(ch->base + M2M_CONTROL);
++
++ while (readl(ch->base + M2M_STATUS) & STAT_STALL) {
++ cpu_relax();
++ }
++
++ clk_disable(ch->clk);
++}
++
++void ep93xx_dma_m2m_set_direction(struct ep93xx_dma_m2m_client *cl,
++ int direction)
++{
++ struct m2m_channel *ch = cl->channel;
++ u32 outv;
++ unsigned long flags;
++
++ direction &= EP93XX_DMA_M2M_DIR_MASK;
++
++ spin_lock_irqsave(&ch->lock, flags);
++
++ cl->flags &= ~EP93XX_DMA_M2M_DIR_MASK;
++ cl->flags |= direction;
++
++ outv = readl(ch->base + M2M_CONTROL);
++ outv = set_direction_reg(outv, cl->flags);
++ writel(outv, ch->base + M2M_CONTROL);
++ outv = readl(ch->base + M2M_CONTROL);
++ DPRINTK("set_direction: configured control reg = %08x\n", outv);
++
++ spin_unlock_irqrestore(&ch->lock, flags);
++}
++EXPORT_SYMBOL_GPL(ep93xx_dma_m2m_set_direction);
++
++int ep93xx_dma_m2m_client_register(struct ep93xx_dma_m2m_client *cl, int channel_spec)
++{
++ struct m2m_channel *ch;
++ int err;
++
++ ch = find_free_channel(cl, channel_spec);
++ if (ch == NULL)
++ return -1;
++
++ err = request_irq(ch->irq, m2m_irq, IRQF_DISABLED, cl->name ? : "dma-m2m", ch);
++ if (err)
++ return err;
++
++ ch->client = cl;
++ ch->next_slot = 0;
++ ch->buffer_xfer = NULL;
++ ch->buffer_next = NULL;
++ INIT_LIST_HEAD(&ch->buffers_pending);
++
++ cl->channel = ch;
++
++ channel_enable(ch);
++
++ return 0;
++}
++EXPORT_SYMBOL_GPL(ep93xx_dma_m2m_client_register);
++
++void ep93xx_dma_m2m_client_unregister(struct ep93xx_dma_m2m_client *cl)
++{
++ struct m2m_channel *ch = cl->channel;
++
++ channel_disable(ch);
++ free_irq(ch->irq, ch);
++ ch->client = NULL;
++}
++EXPORT_SYMBOL_GPL(ep93xx_dma_m2m_client_unregister);
++
++void ep93xx_dma_m2m_submit(struct ep93xx_dma_m2m_client *cl,
++ struct ep93xx_dma_buffer *buf)
++{
++ struct m2m_channel *ch = cl->channel;
++ unsigned long flags;
++
++ spin_lock_irqsave(&ch->lock, flags);
++
++ if (ch->buffer_xfer == NULL) {
++ ch->buffer_xfer = buf;
++ feed_buf(ch, buf);
++ if (readl(ch->base + M2M_CONTROL) & CTRL_ENABLE) {
++ DPRINTK("CTRL_ENABLE\n");
++ if ((cl->flags & EP93XX_DMA_M2M_DEV_MASK) ==
++ EP93XX_DMA_M2M_DEV_MEM) {
++ DPRINTK("WRITING START2 TO M2M control\n");
++ writel(readl(ch->base + M2M_CONTROL) |
++ CTRL_START, ch->base + M2M_CONTROL);
++ readl(ch->base + M2M_CONTROL);
++ }
++ }
++ } else if (ch->buffer_next == NULL) {
++ ch->buffer_next = buf;
++ feed_buf(ch, buf);
++ } else
++ list_add_tail(&buf->list, &ch->buffers_pending);
++ spin_unlock_irqrestore(&ch->lock, flags);
++}
++EXPORT_SYMBOL_GPL(ep93xx_dma_m2m_submit);
++
++void ep93xx_dma_m2m_start(struct ep93xx_dma_m2m_client *cl)
++{
++ struct m2m_channel *ch = cl->channel;
++ u32 v;
++
++ unsigned long flags;
++
++ spin_lock_irqsave(&ch->lock, flags);
++
++ writel(readl(ch->base + M2M_STATUS), ch->base+M2M_STATUS);
++ //printk("At start, status is: %08x\n", readl(ch->base + M2M_STATUS));
++
++ v = readl(ch->base + M2M_CONTROL) | CTRL_ENABLE;
++ writel(v, ch->base + M2M_CONTROL);
++ v = readl(ch->base + M2M_CONTROL);
++ if (ch->buffer_xfer != NULL) {
++ if (((cl->flags & EP93XX_DMA_M2M_DEV_MASK) ==
++ EP93XX_DMA_M2M_DEV_MEM)) {
++ DPRINTK("WRITING START3 to M2M controller\n");
++ v |= CTRL_START;
++ writel(v, ch->base + M2M_CONTROL);
++ v = readl(ch->base + M2M_CONTROL);
++ }
++ }
++
++ spin_unlock_irqrestore(&ch->lock, flags);
++}
++EXPORT_SYMBOL_GPL(ep93xx_dma_m2m_start);
++
++void ep93xx_dma_m2m_stop(struct ep93xx_dma_m2m_client *cl)
++{
++ struct m2m_channel *ch = cl->channel;
++ u32 v;
++ unsigned long flags;
++
++ spin_lock_irqsave(&ch->lock, flags);
++
++ DPRINTK("Stopping DMA by disabling CTRL_ENABLE\n");
++ v = readl(ch->base + M2M_CONTROL) & ~CTRL_ENABLE;
++ writel(v, ch->base + M2M_CONTROL);
++ readl(ch->base + M2M_CONTROL);
++ DPRINTK("configured control reg = %08x\n", v);
++
++ spin_unlock_irqrestore(&ch->lock, flags);
++}
++EXPORT_SYMBOL_GPL(ep93xx_dma_m2m_stop);
++
++void ep93xx_dma_m2m_flush(struct ep93xx_dma_m2m_client *cl)
++{
++ struct m2m_channel *ch = cl->channel;
++
++ channel_disable(ch);
++ ch->next_slot = 0;
++ ch->buffer_xfer = NULL;
++ ch->buffer_next = NULL;
++ INIT_LIST_HEAD(&ch->buffers_pending);
++ channel_enable(ch);
++}
++EXPORT_SYMBOL_GPL(ep93xx_dma_m2m_flush);
++
++static int init_channel(struct m2m_channel *ch)
++{
++ ch->clk = clk_get(NULL, ch->name);
++ if (IS_ERR(ch->clk))
++ return PTR_ERR(ch->clk);
++
++ spin_lock_init(&ch->lock);
++ ch->client = NULL;
++
++ return 0;
++}
++
++static int __init ep93xx_dma_m2m_init(void)
++{
++ int i;
++ int ret;
++
++ for (i = 0; m2m_rxtx[i].base; i++) {
++ ret = init_channel(m2m_rxtx + i);
++ if (ret)
++ return ret;
++ }
++
++ pr_info("M2M DMA subsystem initialized\n");
++ return 0;
++}
++arch_initcall(ep93xx_dma_m2m_init);
+diff --git a/arch/arm/mach-ep93xx/include/mach/dma.h b/arch/arm/mach-ep93xx/include/mach/dma.h
+index 5e31b2b..9560bc9 100644
+--- a/arch/arm/mach-ep93xx/include/mach/dma.h
++++ b/arch/arm/mach-ep93xx/include/mach/dma.h
+@@ -27,6 +27,7 @@
+ struct ep93xx_dma_buffer {
+ struct list_head list;
+ u32 bus_addr;
++ u32 bus_addr2; /* only used by M2M */
+ u16 size;
+ };
+
+@@ -146,4 +147,66 @@ void ep93xx_dma_m2p_submit_recursive(struct ep93xx_dma_m2p_client *m2p,
+ */
+ void ep93xx_dma_m2p_flush(struct ep93xx_dma_m2p_client *m2p);
+
++struct ep93xx_dma_m2m_client {
++ char *name;
++ u32 flags;
++ void *cookie;
++ void (*buffer_started)(void *cookie,
++ struct ep93xx_dma_buffer *buf);
++ void (*buffer_finished)(void *cookie,
++ struct ep93xx_dma_buffer *buf,
++ int bytes, int error);
++
++ /* Internal to the DMA code. */
++ void *channel;
++};
++
++/* flags (m2m client) */
++#define EP93XX_DMA_M2M_RX 0x000 /* read from periph./memory */
++#define EP93XX_DMA_M2M_TX 0x004 /* write to periph./memory */
++#define EP93XX_DMA_M2M_DIR_MASK 0x004 /* direction mask */
++#define EP93XX_DMA_M2M_DEV_EXT 0x000 /* external peripheral */
++#define EP93XX_DMA_M2M_DEV_SSP 0x001 /* internal SSP */
++#define EP93XX_DMA_M2M_DEV_IDE 0x002 /* internal IDE */
++#define EP93XX_DMA_M2M_DEV_MEM 0x003 /* memory to memory transfer */
++#define EP93XX_DMA_M2M_DEV_MASK 0x003 /* device mask */
++#define EP93XX_DMA_M2M_EXT_FIFO 0x008 /* external peripheral is one location fifo */
++#define EP93XX_DMA_M2M_EXT_NO_HDSK 0x010 /* external peripheral doesn't require regular handshaking protocol */
++#define EP93XX_DMA_M2M_EXT_WIDTH_MASK 0x300
++#define EP93XX_DMA_M2M_EXT_WIDTH_BYTE 0x000 /* external peripheral transfer is one byte width */
++#define EP93XX_DMA_M2M_EXT_WIDTH_2BYTES 0x100
++#define EP93XX_DMA_M2M_EXT_WIDTH_4BYTES 0x200
++#define EP93XX_DMA_M2M_MEM_SPEED_FULL 0x000 /* M2M bandwidth control */
++#define EP93XX_DMA_M2M_MEM_SPEED_HALF 0x040 /* half bus bandwidth */
++#define EP93XX_DMA_M2M_MEM_SPEED_QUART 0x080 /* quarter bus bandwidth */
++#define EP93XX_DMA_M2M_MEM_SPEED_SLOW 0x0c0 /* slowest speed */
++#define EP93XX_DMA_M2M_MEM_SPEED_MASK 0x0c0 /* memory speed mask */
++#define EP93XX_DMA_M2M_MEM_FILL 0x020 /* M2M is one location to block fill */
++
++/* FIXME */
++#define CTRL_PWSC_MASK 0xfe000000 /* peripheral wait states count */
++#define CTRL_PWSC_SHIFT 25
++#define EP93XX_DREQ_SHIFT 19
++#define EP93XX_DREQ_MASK 0x00180000
++#define EP93XX_DMA_M2M_DREQ_LS_L (00 << EP93XX_DREQ_SHIFT)
++#define EP93XX_DMA_M2M_DREQ_LS_H (01 << EP93XX_DREQ_SHIFT)
++#define EP93XX_DMA_M2M_DREQ_ES_L (10 << EP93XX_DREQ_SHIFT)
++#define EP93XX_DMA_M2M_DREQ_ES_H (11 << EP93XX_DREQ_SHIFT)
++
++/* See ep93xx_dma_m2m_client_register (channel_spec) */
++#define EP93XX_DMA_M2M_REQUIRES_CH_ANY 0
++#define EP93XX_DMA_M2M_REQUIRES_CH_0 1
++#define EP93XX_DMA_M2M_REQUIRES_CH_1 2
++
++int ep93xx_dma_m2m_client_register(struct ep93xx_dma_m2m_client *m2m,
++ int channel_spec);
++void ep93xx_dma_m2m_client_unregister(struct ep93xx_dma_m2m_client *m2m);
++void ep93xx_dma_m2m_submit(struct ep93xx_dma_m2m_client *m2m,
++ struct ep93xx_dma_buffer *buf);
++void ep93xx_dma_m2m_flush(struct ep93xx_dma_m2m_client *m2m);
++void ep93xx_dma_m2m_start(struct ep93xx_dma_m2m_client *m2m);
++void ep93xx_dma_m2m_stop(struct ep93xx_dma_m2m_client *m2m);
++void ep93xx_dma_m2m_set_direction(struct ep93xx_dma_m2m_client *m2m,
++ int direction);
++
+ #endif /* __ASM_ARCH_DMA_H */
+--
+1.7.1
+
diff --git a/recipes/linux/linux-2.6.38/ts72xx/0006-ts72xx_rs485.patch b/recipes/linux/linux-2.6.38/ts72xx/0006-ts72xx_rs485.patch
new file mode 100644
index 0000000..5dc0989
--- /dev/null
+++ b/recipes/linux/linux-2.6.38/ts72xx/0006-ts72xx_rs485.patch
@@ -0,0 +1,221 @@
+From c5aac99ff75683937b3543b8fa14fe7a8a30e646 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Petr=20=C5=A0tetiar?= <ynezz@true.cz>
+Date: Sun, 13 Mar 2011 23:53:10 +0100
+Subject: [PATCH 06/24] ts72xx_rs485
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Crude hack...
+
+Signed-off-by: Petr Štetiar <ynezz@true.cz>
+---
+ arch/arm/include/asm/ioctls.h | 3 +
+ drivers/tty/serial/Kconfig | 8 +++
+ drivers/tty/serial/amba-pl010.c | 124 ++++++++++++++++++++++++++++++++++++++-
+ 3 files changed, 134 insertions(+), 1 deletions(-)
+
+diff --git a/arch/arm/include/asm/ioctls.h b/arch/arm/include/asm/ioctls.h
+index 9c96298..849e8bb 100644
+--- a/arch/arm/include/asm/ioctls.h
++++ b/arch/arm/include/asm/ioctls.h
+@@ -5,4 +5,7 @@
+
+ #include <asm-generic/ioctls.h>
+
++#define TIOC_SBCC485 0x545F /* TS72xx RTS/485 mode clear */
++#define TIOC_SBCS485 0x5460 /* TS72xx RTS/485 mode set */
++
+ #endif
+diff --git a/drivers/tty/serial/Kconfig b/drivers/tty/serial/Kconfig
+index 2b83346..1a32706 100644
+--- a/drivers/tty/serial/Kconfig
++++ b/drivers/tty/serial/Kconfig
+@@ -280,6 +280,14 @@ config SERIAL_AMBA_PL010
+
+ If unsure, say N.
+
++config SERIAL_AMBA_PL010_TS72XX
++ bool "Support for RS-485 on AMBA serial port (for TS-72XX SBC)"
++ depends on SERIAL_AMBA_PL010 != n && MACH_TS72XX
++ help
++ This add support for RS-485 on some Technologic System SBC.
++
++ If unsure, say N.
++
+ config SERIAL_AMBA_PL010_CONSOLE
+ bool "Support for console on AMBA serial port"
+ depends on SERIAL_AMBA_PL010=y
+diff --git a/drivers/tty/serial/amba-pl010.c b/drivers/tty/serial/amba-pl010.c
+index 2904aa0..9135233 100644
+--- a/drivers/tty/serial/amba-pl010.c
++++ b/drivers/tty/serial/amba-pl010.c
+@@ -51,6 +51,10 @@
+
+ #include <asm/io.h>
+
++#if defined(CONFIG_SERIAL_AMBA_PL010_TS72XX)
++#include <mach/ts72xx.h>
++#endif
++
+ #define UART_NR 8
+
+ #define SERIAL_AMBA_MAJOR 204
+@@ -65,6 +69,11 @@
+ #define UART_DUMMY_RSR_RX 256
+ #define UART_PORT_SIZE 64
+
++#if defined(CONFIG_SERIAL_AMBA_PL010_TS72XX)
++static void __iomem *ts_rs485_data9_register;
++static void __iomem *ts_rs485_control_register;
++#endif
++
+ /*
+ * We wrap our port structure around the generic uart_port.
+ */
+@@ -386,7 +395,7 @@ pl010_set_termios(struct uart_port *port, struct ktermios *termios,
+ /*
+ * Ask the core to calculate the divisor for us.
+ */
+- baud = uart_get_baud_rate(port, termios, old, 0, uap->port.uartclk/16);
++ baud = uart_get_baud_rate(port, termios, old, 0, uap->port.uartclk/16);
+ quot = uart_get_divisor(port, baud);
+
+ switch (termios->c_cflag & CSIZE) {
+@@ -529,6 +538,105 @@ static int pl010_verify_port(struct uart_port *port, struct serial_struct *ser)
+ return ret;
+ }
+
++
++#if defined(CONFIG_SERIAL_AMBA_PL010_TS72XX)
++static int ts72xx_rs485_init(void)
++{
++ ts_rs485_data9_register = ioremap(TS72XX_RS485_MODE_PHYS_BASE, 4096);
++ if (ts_rs485_data9_register == NULL) {
++ return -1;
++ }
++
++ ts_rs485_control_register = ioremap(TS72XX_RS485_CONTROL_PHYS_BASE, 4096);
++ if (ts_rs485_control_register == NULL) {
++ iounmap(ts_rs485_data9_register);
++ return -1;
++ }
++
++ return 0;
++}
++
++static int ts72xx_auto485(struct uart_port *port, unsigned int cmd, unsigned long *arg)
++{
++ int baud, cflag, mode;
++ int datalength;
++
++ mode = (int)*arg;
++ if (!is_rs485_installed()) {
++ printk("amba-pl010.c: this board does not support RS485 auto mode\n");
++ return -EINVAL;
++ }
++
++ if (port->line != 1) {
++ printk("amba-pl010.c: auto RS485 mode is only supported on second port (/dev/ttyAM1)\n");
++ return -EINVAL;
++ }
++
++ datalength = 8;
++ cflag = port->state->port.tty->termios->c_cflag;
++ if (cflag & PARENB)
++ datalength++;
++
++ if (cflag & CSTOPB)
++ datalength++;
++
++ baud = tty_get_baud_rate(port->state->port.tty);
++
++ switch (cmd) {
++ case TIOC_SBCC485:
++ if ((mode & TS72XX_RS485_AUTO485FD) || (mode & TS72XX_RS485_AUTO485HD)) {
++ printk("amba-pl010.c: unsetting auto RS485 mode\n");
++ __raw_writew(TS72XX_RS485_MODE_RS232, ts_rs485_control_register);
++ __raw_writew(TS72XX_RS485_MODE_RS232, ts_rs485_data9_register);
++ }
++ break;
++ case TIOC_SBCS485:
++ if (mode & TS72XX_RS485_AUTO485FD) {
++ printk ("amba-pl010.c: setting FULL duplex auto RS485 mode\n");
++ __raw_writew(TS72XX_RS485_MODE_FD, ts_rs485_control_register);
++ if (datalength > 8)
++ __raw_writew(TS72XX_RS485_MODE_FD, ts_rs485_data9_register);
++ } else if (mode & TS72XX_RS485_AUTO485HD) {
++ printk("amba-pl010.c: setting HALF DUPLEX auto RS485 mode\n");
++ switch (baud) {
++ case 9600:
++ __raw_writew(TS72XX_RS485_MODE_9600_HD, ts_rs485_control_register);
++ break;
++ case 19200:
++ __raw_writew(TS72XX_RS485_MODE_19200_HD, ts_rs485_control_register);
++ break;
++ case 57600:
++ __raw_writew(TS72XX_RS485_MODE_57600_HD, ts_rs485_control_register);
++ break;
++ case 115200:
++ __raw_writew(TS72XX_RS485_MODE_115200_HD, ts_rs485_control_register);
++ break;
++ default:
++ printk("amba-pl010.c: %d baud rate is not supported for auto RS485 mode\n", baud);
++ return -1;
++ }
++ if (datalength > 8)
++ __raw_writew(TS72XX_RS485_MODE_FD, ts_rs485_data9_register);
++ }
++ break;
++ }
++
++ return 0;
++}
++
++static int pl010_ioctl(struct uart_port *port, unsigned int cmd, unsigned long arg)
++{
++ switch (cmd) {
++ case TIOC_SBCC485:
++ case TIOC_SBCS485:
++ return ts72xx_auto485(port, cmd, (unsigned long *)arg);
++ }
++
++ return -ENOIOCTLCMD;
++}
++#endif /* CONFIG_SERIAL_AMBA_PL010_TS72XX */
++
++
+ static struct uart_ops amba_pl010_pops = {
+ .tx_empty = pl010_tx_empty,
+ .set_mctrl = pl010_set_mctrl,
+@@ -547,6 +655,9 @@ static struct uart_ops amba_pl010_pops = {
+ .request_port = pl010_request_port,
+ .config_port = pl010_config_port,
+ .verify_port = pl010_verify_port,
++#if defined(CONFIG_SERIAL_AMBA_PL010_TS72XX)
++ .ioctl = pl010_ioctl,
++#endif
+ };
+
+ static struct uart_amba_port *amba_ports[UART_NR];
+@@ -805,6 +916,17 @@ static int __init pl010_init(void)
+ ret = uart_register_driver(&amba_reg);
+ if (ret == 0) {
+ ret = amba_driver_register(&pl010_driver);
++
++ #if defined(CONFIG_SERIAL_AMBA_PL010_TS72XX)
++ if (!ret && is_rs485_installed()) {
++ ret = ts72xx_rs485_init();
++ if (ret)
++ printk("amba-pl010.c: ts72xx_rs485_init() failed\n");
++ else
++ printk("amba-pl010.c: auto RS485 mode initialized\n");
++ }
++ #endif
++
+ if (ret)
+ uart_unregister_driver(&amba_reg);
+ }
+--
+1.7.1
+
diff --git a/recipes/linux/linux-2.6.38/ts72xx/0007-ts72xx_ts_ser1.patch b/recipes/linux/linux-2.6.38/ts72xx/0007-ts72xx_ts_ser1.patch
new file mode 100644
index 0000000..6decf0a
--- /dev/null
+++ b/recipes/linux/linux-2.6.38/ts72xx/0007-ts72xx_ts_ser1.patch
@@ -0,0 +1,264 @@
+From 11734bcfcc65d589449e4d38c295b6dbc4f38752 Mon Sep 17 00:00:00 2001
+From: Matthieu Crapet <mcrapet@gmail.com>
+Date: Wed, 16 Jun 2010 14:44:44 +0200
+Subject: [PATCH 07/24] ts72xx_ts_ser1
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+TS-SER1 - Serial Port PC/104 peripheral
+
+Signed-off-by: Petr Štetiar <ynezz@true.cz>
+---
+ drivers/tty/serial/8250_ts_ser1.c | 197 +++++++++++++++++++++++++++++++++++++
+ drivers/tty/serial/Kconfig | 17 +++
+ drivers/tty/serial/Makefile | 1 +
+ 3 files changed, 215 insertions(+), 0 deletions(-)
+ create mode 100644 drivers/tty/serial/8250_ts_ser1.c
+
+diff --git a/drivers/tty/serial/8250_ts_ser1.c b/drivers/tty/serial/8250_ts_ser1.c
+new file mode 100644
+index 0000000..e5fe616
+--- /dev/null
++++ b/drivers/tty/serial/8250_ts_ser1.c
+@@ -0,0 +1,197 @@
++/*
++ * linux/drivers/serial/8250_ts_ser1.c
++ * Technologic Systems TS-SER1 support.
++ *
++ * (c) Copyright 2006-2008 Matthieu Crapet <mcrapet@gmail.com>
++ * Data taken from include/asm-i386/serial.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.
++ *
++ * Pin Number:
++ * 1 DCD
++ * 2 Receive data
++ * 3 Trasmit data
++ * 4 DTR
++ * 5 Signal Ground
++ * 6 DSR
++ * 7 RTS
++ * 8 CTS
++ * 9 RI
++ */
++
++#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
++
++#include <linux/module.h>
++#include <linux/init.h>
++#include <linux/serial_8250.h>
++#include <linux/irq.h>
++#include <linux/io.h>
++#include <mach/hardware.h>
++#include <mach/ts72xx.h>
++#include <mach/gpio.h>
++
++#define TS72XX_SER1_IO_PHYS_BASE (TS72XX_PC104_8BIT_IO_PHYS_BASE)
++#define TS72XX_SER1_IO_SIZE (TS72XX_PC104_8BIT_IO_SIZE)
++
++#define TS_SER1_PORT_COM3 0x3E8
++#define TS_SER1_PORT_COM4 0x2E8
++#define TS_SER1_PORT_COM5 0x3A8
++
++/* Value to write in 16550A scratch register */
++#define MARKER_BYTE 0xAA /* or 0x55 */
++
++#define PORT(_base,_irq) \
++{ \
++ .iobase = _base, \
++ .membase = (void __iomem *)0, \
++ .irq = _irq, \
++ .uartclk = 1843200, \
++ .iotype = UPIO_PORT, \
++ .flags = UPF_BOOT_AUTOCONF, \
++}
++/* Note: IRQ can be shared (see CONFIG_SERIAL_8250_SHARE_IRQ) */
++
++
++static struct plat_serial8250_port ts72xx_ser1_data_com3[] = {
++ PORT(TS_SER1_PORT_COM3, 0),
++ { },
++};
++
++static struct plat_serial8250_port ts72xx_ser1_data_com4[] = {
++ PORT(TS_SER1_PORT_COM4, 0),
++ { },
++};
++
++static struct plat_serial8250_port ts72xx_ser1_data_com5[] = {
++ PORT(TS_SER1_PORT_COM5, 0),
++ { },
++};
++
++
++static int ts_ser1_irq = CONFIG_SERIAL_8250_TS_SER1_IRQ; // 5, 6 or 7
++static struct platform_device *serial8250_ts_ser1_dev;
++
++
++static int __init ts_ser1_init(void)
++{
++ struct plat_serial8250_port *comX = NULL;
++ void __iomem *iomem;
++
++ int ret = -ENODEV;
++ int n = 0; // COM number as printed on TS-SER1 pcb
++
++ iomem = ioremap(TS72XX_SER1_IO_PHYS_BASE, TS72XX_SER1_IO_SIZE);
++
++ if (iomem != NULL) {
++ __raw_writeb(MARKER_BYTE, iomem + TS_SER1_PORT_COM3 + 7);
++ if (__raw_readb(iomem + TS_SER1_PORT_COM3 + 7) == MARKER_BYTE) {
++ comX = ts72xx_ser1_data_com3;
++ n = 3;
++ } else {
++ __raw_writeb(MARKER_BYTE, iomem + TS_SER1_PORT_COM4 + 7);
++ if (__raw_readb(iomem + TS_SER1_PORT_COM4 + 7) == MARKER_BYTE) {
++ comX = ts72xx_ser1_data_com4;
++ n = 4;
++ } else {
++ __raw_writeb(MARKER_BYTE, iomem + TS_SER1_PORT_COM5 + 7);
++ if (__raw_readb(iomem + TS_SER1_PORT_COM5 + 7) == MARKER_BYTE) {
++ comX = ts72xx_ser1_data_com5;
++ n = 5;
++ }
++ }
++ }
++
++ if (comX) {
++ switch (ts_ser1_irq) {
++ case 5:
++ ret = gpio_request(EP93XX_GPIO_LINE_F(3), "TS-SER1");
++ if (ret < 0) {
++ pr_err("gpio_request failed, try another irq\n");
++ goto init_error;
++ }
++ gpio_direction_input(EP93XX_GPIO_LINE_F(3));
++ comX->irq = gpio_to_irq(EP93XX_GPIO_LINE_F(3));
++ set_irq_type(comX->irq, IRQ_TYPE_EDGE_RISING);
++ break;
++ case 6:
++ comX->irq = IRQ_EP93XX_EXT1;
++ break;
++ case 7:
++ comX->irq = IRQ_EP93XX_EXT3;
++ break;
++ default:
++ pr_err("wrong specified irq\n");
++ goto init_error;
++ }
++
++ comX->iobase += (unsigned long)iomem; // virtual address
++
++ } else {
++ pr_err("can't detect COM number\n");
++ goto init_error;
++ }
++
++ /* create platform_device structure */
++ serial8250_ts_ser1_dev = platform_device_alloc("serial8250", n);
++ if (!serial8250_ts_ser1_dev) {
++ ret = -ENOMEM;
++ goto init_error;
++ }
++
++ ret = platform_device_add_data(serial8250_ts_ser1_dev, comX,
++ 2 * sizeof(struct plat_serial8250_port));
++ if (ret) {
++ platform_device_put(serial8250_ts_ser1_dev);
++ goto init_error;
++ }
++
++ ret = platform_device_add(serial8250_ts_ser1_dev);
++ if (ret) {
++ platform_device_put(serial8250_ts_ser1_dev);
++ goto init_error;
++ }
++
++ platform_set_drvdata(serial8250_ts_ser1_dev, iomem);
++ return 0;
++ }
++
++init_error:
++ if (iomem) {
++ iounmap(iomem);
++ iomem = NULL;
++ }
++ return ret;
++}
++
++static void __exit ts_ser1_exit(void)
++{
++ struct platform_device *pdev = serial8250_ts_ser1_dev;
++ void __iomem *iomem = platform_get_drvdata(pdev);
++
++ serial8250_ts_ser1_dev = NULL;
++
++ platform_device_unregister(pdev);
++
++ iounmap(iomem);
++ if (ts_ser1_irq == 5)
++ gpio_free(EP93XX_GPIO_LINE_F(3));
++}
++
++module_init(ts_ser1_init);
++module_exit(ts_ser1_exit);
++
++module_param(ts_ser1_irq, int, 0);
++MODULE_PARM_DESC(ts_ser1_irq, "TS-SER1 IRQ, default=" __MODULE_STRING(CONFIG_SERIAL_8250_TS_SER1_IRQ) ")");
++
++MODULE_AUTHOR("Matthieu Crapet <mcrapet@gmail.com>");
++MODULE_DESCRIPTION("8250 serial probe module for TS-SER1 (TS-72xx)");
++MODULE_LICENSE("GPL");
++MODULE_VERSION("0.5");
+diff --git a/drivers/tty/serial/Kconfig b/drivers/tty/serial/Kconfig
+index 1a32706..0d846d6 100644
+--- a/drivers/tty/serial/Kconfig
++++ b/drivers/tty/serial/Kconfig
+@@ -267,6 +267,23 @@ config SERIAL_8250_RM9K
+ port hardware found on MIPS RM9122 and similar processors.
+ If unsure, say N.
+
++config SERIAL_8250_TS_SER1
++ tristate "Support TS-SER1 (for TS-72XX SBC)"
++ depends on SERIAL_8250 != n && MACH_TS72XX
++ help
++ Say Y here if you have a TS-SER1 PC/104 peripheral.
++ COM number will be configured automaticaly.
++
++ To compile this driver as a module, choose M here: the module
++ will be called 8250_ts_ser1.
++
++config SERIAL_8250_TS_SER1_IRQ
++ int "Selected IRQ (5, 6 or 7)"
++ depends on SERIAL_8250_TS_SER1
++ default "5"
++ help
++ Enter jumper IRQ configuration
++
+ comment "Non-8250 serial port support"
+
+ config SERIAL_AMBA_PL010
+diff --git a/drivers/tty/serial/Makefile b/drivers/tty/serial/Makefile
+index 8ea92e9..e5c6d0f 100644
+--- a/drivers/tty/serial/Makefile
++++ b/drivers/tty/serial/Makefile
+@@ -28,6 +28,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_8250_TS_SER1) += 8250_ts_ser1.o
+ obj-$(CONFIG_SERIAL_AMBA_PL010) += amba-pl010.o
+ obj-$(CONFIG_SERIAL_AMBA_PL011) += amba-pl011.o
+ obj-$(CONFIG_SERIAL_CLPS711X) += clps711x.o
+--
+1.7.1
+
diff --git a/recipes/linux/linux-2.6.38/ts72xx/0008-ts72xx_ts_eth100.patch b/recipes/linux/linux-2.6.38/ts72xx/0008-ts72xx_ts_eth100.patch
new file mode 100644
index 0000000..f8ea669
--- /dev/null
+++ b/recipes/linux/linux-2.6.38/ts72xx/0008-ts72xx_ts_eth100.patch
@@ -0,0 +1,278 @@
+From 2e0740a01341ddff65c2337989d41d9620a5b3a2 Mon Sep 17 00:00:00 2001
+From: Matthieu Crapet <mcrapet@gmail.com>
+Date: Fri, 18 Jun 2010 17:39:09 +0200
+Subject: [PATCH 08/24] ts72xx_ts_eth100
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+TS-ETH100 - 10/100 Ethernet PC/104 peripheral
+
+Signed-off-by: Petr Štetiar <ynezz@true.cz>
+---
+ drivers/net/Kconfig | 10 ++
+ drivers/net/Makefile | 1 +
+ drivers/net/ax88796.c | 8 ++-
+ drivers/net/ax88796_ts_eth100.c | 190 +++++++++++++++++++++++++++++++++++++++
+ 4 files changed, 208 insertions(+), 1 deletions(-)
+ create mode 100644 drivers/net/ax88796_ts_eth100.c
+
+diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
+index 0382332..5b72bda 100644
+--- a/drivers/net/Kconfig
++++ b/drivers/net/Kconfig
+@@ -251,6 +251,16 @@ config AX88796_93CX6
+ help
+ Select this if your platform comes with an external 93CX6 eeprom.
+
++config AX88796_TS_ETH100
++ tristate "Support for TS-ETH100 (TS-72XX SBC)"
++ depends on AX88796 && MACH_TS72XX
++ help
++ Say Y here if you have a TS-ETH100 PC/104 peripheral.
++ IRQ numbers and I/O address will be configurated automatically.
++
++ To compile this driver as a module, choose M here: the module
++ will be called ax88796_ts_eth100.
++
+ config MACE
+ tristate "MACE (Power Mac ethernet) support"
+ depends on PPC_PMAC && PPC32
+diff --git a/drivers/net/Makefile b/drivers/net/Makefile
+index b90738d..0b57d6c 100644
+--- a/drivers/net/Makefile
++++ b/drivers/net/Makefile
+@@ -146,6 +146,7 @@ obj-$(CONFIG_B44) += b44.o
+ obj-$(CONFIG_FORCEDETH) += forcedeth.o
+ obj-$(CONFIG_NE_H8300) += ne-h8300.o 8390.o
+ obj-$(CONFIG_AX88796) += ax88796.o
++obj-$(CONFIG_AX88796_TS_ETH100) += ax88796_ts_eth100.o
+ obj-$(CONFIG_BCM63XX_ENET) += bcm63xx_enet.o
+
+ obj-$(CONFIG_TSI108_ETH) += tsi108_eth.o
+diff --git a/drivers/net/ax88796.c b/drivers/net/ax88796.c
+index 4bebff3..26c758e 100644
+--- a/drivers/net/ax88796.c
++++ b/drivers/net/ax88796.c
+@@ -810,7 +810,9 @@ static int ax_remove(struct platform_device *_dev)
+ ax = to_ax_dev(dev);
+
+ unregister_netdev(dev);
+- free_irq(dev->irq, dev);
++ if (ax->running) { // already freed in ax_close?
++ free_irq(dev->irq, dev);
++ }
+
+ iounmap(ei_status.mem);
+ release_resource(ax->mem);
+@@ -937,7 +939,11 @@ static int ax_probe(struct platform_device *pdev)
+ goto exit_mem2;
+ }
+
++ #if defined(CONFIG_AX88796_TS_ETH100) || defined(CONFIG_AX88796_TS_ETH100_MODULE)
++ ei_status.reg_offset[0x10] = ax->map2 - ei_status.mem + 0x10; /* don't know why, but +0x20 works too */
++ #else
+ ei_status.reg_offset[0x1f] = ax->map2 - ei_status.mem;
++ #endif
+ }
+
+ /* got resources, now initialise and register device */
+diff --git a/drivers/net/ax88796_ts_eth100.c b/drivers/net/ax88796_ts_eth100.c
+new file mode 100644
+index 0000000..448b3e3
+--- /dev/null
++++ b/drivers/net/ax88796_ts_eth100.c
+@@ -0,0 +1,190 @@
++/*
++ * linux/drivers/net/ax88796_ts_eth100.c
++ * Technologic Systems TS-ETH100 support.
++ *
++ * (c) Copyright 2008 Matthieu Crapet <mcrapet@gmail.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.
++ */
++
++#include <linux/module.h>
++#include <linux/init.h>
++#include <linux/platform_device.h>
++#include <linux/irq.h>
++#include <linux/io.h>
++#include <net/ax88796.h>
++#include <mach/ts72xx.h>
++#include <mach/gpio.h>
++
++#define TS72XX_ETH100_IO8_PHYS_BASE (TS72XX_PC104_8BIT_IO_PHYS_BASE)
++#define TS72XX_ETH100_IO8_SIZE (TS72XX_PC104_8BIT_IO_SIZE)
++#define TS72XX_ETH100_IO16_PHYS_BASE (TS72XX_PC104_16BIT_IO_PHYS_BASE)
++#define TS72XX_ETH100_IO16_SIZE (TS72XX_PC104_16BIT_IO_SIZE)
++
++/* Technologic systems I/O space */
++#define TS_ETH100_PLD_0 0x100
++#define TS_ETH100_PLD_1 0x110
++#define TS_ETH100_PLD_2 0x120
++#define TS_ETH100_PLD_3 0x130
++
++/* NE2000 I/O space */
++#define TS_ETH100_MAC_0 0x200
++#define TS_ETH100_MAC_1 0x240
++#define TS_ETH100_MAC_2 0x300
++#define TS_ETH100_MAC_3 0x340
++
++/* Board identifier must be 5 ; PLD revision should be 1 */
++#define is_eth100_present(__iomem, __offset) \
++ (((__raw_readb(__iomem + __offset) & 0xF) == 0x5) && \
++ ((__raw_readb(__iomem + __offset + 4) & 0xF) == 0x1))
++
++/* Jumpers status (SRAM control register) */
++#define read_irq(__iomem, __offset) \
++ (__raw_readb(__iomem + __offset + 8) & 0xE)
++
++
++static u32 offsets[0x20] = {
++ 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
++};
++
++static struct ax_plat_data ts72xx_eth100_asix_data = {
++ .flags = AXFLG_HAS_93CX6,
++ .wordlength = 2,
++ .dcr_val = 0x48,
++ .rcr_val = 0x40,
++ .reg_offsets = offsets,
++};
++
++static struct resource ts72xx_eth100_resource[] = {
++ [0] = {
++ .start = TS72XX_ETH100_IO8_PHYS_BASE,
++ .end = TS72XX_ETH100_IO8_PHYS_BASE + 0x40 - 1,
++ .flags = IORESOURCE_MEM
++ },
++ [1] = { /* 0x10 is NE_DATAPORT is 16-bit access */
++ .start = TS72XX_ETH100_IO16_PHYS_BASE,
++ .end = TS72XX_ETH100_IO16_PHYS_BASE + 0x40 - 1,
++ .flags = IORESOURCE_MEM
++ },
++ [2] = {
++ .start = IRQ_EP93XX_EXT1,
++ .end = IRQ_EP93XX_EXT1,
++ .flags = IORESOURCE_IRQ
++ }
++};
++
++static int ts_eth100_irq; // 2 [IRQ 5], 4 [IRQ 6] or 8 [IRQ 7] (jumper configuration)
++
++
++static void ts72xx_eth100_release(struct device *dev)
++{
++ /* nothing to do (no kfree) because we have static struct */
++}
++
++static struct platform_device ts72xx_eth100_device_asix = {
++ .name = "ax88796",
++ .id = 0,
++ .num_resources = ARRAY_SIZE(ts72xx_eth100_resource),
++ .resource = ts72xx_eth100_resource,
++ .dev = {
++ .platform_data = &ts72xx_eth100_asix_data,
++ .release = ts72xx_eth100_release,
++ }
++};
++
++static int __init ts_eth100_init(void)
++{
++ void __iomem *iomem;
++ struct platform_device *ethX = NULL;
++
++ iomem = ioremap(TS72XX_ETH100_IO8_PHYS_BASE, TS72XX_ETH100_IO8_SIZE);
++ if (iomem != NULL) {
++ ethX = &ts72xx_eth100_device_asix;
++
++ if (is_eth100_present(iomem, TS_ETH100_PLD_0)) {
++ ethX->resource[0].start += TS_ETH100_MAC_0;
++ ethX->resource[0].end += TS_ETH100_MAC_0;
++ ethX->resource[1].start += TS_ETH100_MAC_0;
++ ethX->resource[1].end += TS_ETH100_MAC_0;
++ ts_eth100_irq = read_irq(iomem, TS_ETH100_PLD_0);
++ } else if(is_eth100_present(iomem, TS_ETH100_PLD_1)) {
++ ethX->resource[0].start += TS_ETH100_MAC_1;
++ ethX->resource[0].end += TS_ETH100_MAC_1;
++ ethX->resource[1].start += TS_ETH100_MAC_1;
++ ethX->resource[1].end += TS_ETH100_MAC_1;
++ ts_eth100_irq = read_irq(iomem, TS_ETH100_PLD_1);
++ } else if(is_eth100_present(iomem, TS_ETH100_PLD_2)) {
++ ethX->resource[0].start += TS_ETH100_MAC_2;
++ ethX->resource[0].end += TS_ETH100_MAC_2;
++ ethX->resource[1].start += TS_ETH100_MAC_2;
++ ethX->resource[1].end += TS_ETH100_MAC_2;
++ ts_eth100_irq = read_irq(iomem, TS_ETH100_PLD_2);
++ } else if(is_eth100_present(iomem, TS_ETH100_PLD_3)) {
++ ethX->resource[0].start += TS_ETH100_MAC_3;
++ ethX->resource[0].end += TS_ETH100_MAC_3;
++ ethX->resource[1].start += TS_ETH100_MAC_3;
++ ethX->resource[1].end += TS_ETH100_MAC_3;
++ ts_eth100_irq = read_irq(iomem, TS_ETH100_PLD_3);
++ } else {
++ ethX = NULL;
++ }
++
++ /* Translate IRQ number */
++ if (ethX != NULL) {
++ int ret, irq = 0;
++ switch (ts_eth100_irq) {
++ case 0x2: /* IRQ5 */
++ irq = gpio_to_irq(EP93XX_GPIO_LINE_F(3));
++ ret = gpio_request(irq, "TS-ETH100");
++ if (ret < 0) {
++ ethX = NULL;
++ goto init_error;
++ } else {
++ gpio_direction_input(irq);
++ set_irq_type(irq, IRQ_TYPE_EDGE_RISING);
++ }
++ break;
++ case 0x4: /* IRQ6 */
++ irq = IRQ_EP93XX_EXT1;
++ break;
++ case 0x8: /* IRQ7 */
++ default:
++ irq = IRQ_EP93XX_EXT3;
++ }
++ ethX->resource[2].start = irq;
++ ethX->resource[2].end = irq;
++ }
++init_error:
++ iounmap(iomem);
++ }
++
++ return ((ethX == NULL) ? -ENODEV :
++ platform_device_register(&ts72xx_eth100_device_asix));
++}
++
++
++static void __exit ts_eth100_exit(void)
++{
++ platform_device_unregister(&ts72xx_eth100_device_asix);
++ if (ts_eth100_irq == 2)
++ gpio_free(EP93XX_GPIO_LINE_F(3));
++}
++
++module_init(ts_eth100_init);
++module_exit(ts_eth100_exit);
++
++MODULE_AUTHOR("Matthieu Crapet <mcrapet@gmail.com>");
++MODULE_DESCRIPTION("Asix 88796 ethernet probe module for TS-ETH100 (TS-72xx)");
++MODULE_LICENSE("GPL");
++MODULE_VERSION("0.21");
+--
+1.7.1
+
diff --git a/recipes/linux/linux-2.6.38/ts72xx/0009-ts72xx_pata.patch b/recipes/linux/linux-2.6.38/ts72xx/0009-ts72xx_pata.patch
new file mode 100644
index 0000000..1d8cc07
--- /dev/null
+++ b/recipes/linux/linux-2.6.38/ts72xx/0009-ts72xx_pata.patch
@@ -0,0 +1,437 @@
+From 5630b1f5f24c2d63959a77069e095f287eb128da Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Petr=20=C5=A0tetiar?= <ynezz@true.cz>
+Date: Sat, 23 Oct 2010 19:08:37 +0200
+Subject: [PATCH 09/24] ts72xx_pata
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Support:
+TS-7200 - Compact flash
+TS-9600 - IDE interface PC/104 peripheral
+
+Signed-off-by: Petr Štetiar <ynezz@true.cz>
+---
+ drivers/ata/Kconfig | 20 +++++
+ drivers/ata/Makefile | 3 +
+ drivers/ata/pata_ts7200_cf.c | 92 ++++++++++++++++++++++++
+ drivers/ata/pata_ts72xx.c | 161 ++++++++++++++++++++++++++++++++++++++++++
+ drivers/ata/pata_ts9600.c | 95 +++++++++++++++++++++++++
+ 5 files changed, 371 insertions(+), 0 deletions(-)
+ create mode 100644 drivers/ata/pata_ts7200_cf.c
+ create mode 100644 drivers/ata/pata_ts72xx.c
+ create mode 100644 drivers/ata/pata_ts9600.c
+
+diff --git a/drivers/ata/Kconfig b/drivers/ata/Kconfig
+index c2328ae..1302eca 100644
+--- a/drivers/ata/Kconfig
++++ b/drivers/ata/Kconfig
+@@ -870,5 +870,25 @@ config PATA_LEGACY
+
+ If unsure, say N.
+
++config PATA_TS72XX
++ bool "TS72XX ATA support"
++ depends on ARCH_EP93XX && MACH_TS72XX
++ help
++ This option enables support for ATA devices on Technologic Systems SBC.
++
++config PATA_TS7200_CF
++ tristate "TS-7200 Compact Flash support"
++ depends on PATA_TS72XX
++ help
++ This option enables support for the compact flash control on
++ Technologic System TS-7200 SBC.
++
++config PATA_TS9600
++ tristate "TS-9600 IDE interface support"
++ depends on PATA_TS72XX && BLK_DEV_IDE_TS9600 != y
++ help
++ This option enables support for Technologic Systems TS-9600 PC/104 IDE interface.
++
+ endif # ATA_SFF
++
+ endif # ATA
+diff --git a/drivers/ata/Makefile b/drivers/ata/Makefile
+index 27291aa..34fde34 100644
+--- a/drivers/ata/Makefile
++++ b/drivers/ata/Makefile
+@@ -92,6 +92,9 @@ obj-$(CONFIG_PATA_RZ1000) += pata_rz1000.o
+ obj-$(CONFIG_PATA_SAMSUNG_CF) += pata_samsung_cf.o
+
+ obj-$(CONFIG_PATA_PXA) += pata_pxa.o
++obj-$(CONFIG_PATA_TS72XX) += pata_ts72xx.o
++obj-$(CONFIG_PATA_TS7200_CF) += pata_ts7200_cf.o
++obj-$(CONFIG_PATA_TS9600) += pata_ts9600.o
+
+ # Should be last but two libata driver
+ obj-$(CONFIG_PATA_ACPI) += pata_acpi.o
+diff --git a/drivers/ata/pata_ts7200_cf.c b/drivers/ata/pata_ts7200_cf.c
+new file mode 100644
+index 0000000..4126682
+--- /dev/null
++++ b/drivers/ata/pata_ts7200_cf.c
+@@ -0,0 +1,92 @@
++/*
++ * Technologic Systems TS-7200 Compact Flash PATA device driver.
++ *
++ * (c) Copyright 2008 Matthieu Crapet <mcrapet@gmail.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.
++ *
++ */
++
++#include <linux/kernel.h>
++#include <linux/module.h>
++#include <linux/libata.h>
++#include <scsi/scsi_host.h>
++#include <linux/platform_device.h>
++#include <linux/dma-mapping.h>
++
++#include <asm/io.h>
++#include <asm/irq.h>
++#include <mach/ts72xx.h>
++
++#define DRV_NAME "pata_ts7200_cf"
++#define DRV_VERSION "0.21"
++
++
++static void pata_ts7200_cf_release(struct device *dev)
++{
++ /* nothing to do (no kfree) because we have static struct */
++}
++
++static struct resource ts7200_cf_resources[] = {
++ [0] = {
++ .start = TS7200_CF_CMD_PHYS_BASE,
++ .end = TS7200_CF_CMD_PHYS_BASE + 8,
++ .flags = IORESOURCE_MEM,
++ },
++ [1] = {
++ .start = TS7200_CF_AUX_PHYS_BASE,
++ .end = TS7200_CF_AUX_PHYS_BASE + 1,
++ .flags = IORESOURCE_MEM,
++ },
++ [2] = {
++ .start = TS7200_CF_DATA_PHYS_BASE,
++ .end = TS7200_CF_DATA_PHYS_BASE + 2,
++ .flags = IORESOURCE_MEM,
++ },
++ [3] = {
++ .start = IRQ_EP93XX_EXT0, /* pin 103 of EP9301 */
++ .end = IRQ_EP93XX_EXT0,
++ .flags = IORESOURCE_IRQ,
++ }
++};
++
++
++static struct platform_device ts7200_cf_device = {
++ .name = "ts72xx-ide",
++ .id = 0,
++ .dev = {
++ .dma_mask = &ts7200_cf_device.dev.coherent_dma_mask,
++ .coherent_dma_mask = DMA_BIT_MASK(32),
++ .release = pata_ts7200_cf_release,
++ },
++ .num_resources = ARRAY_SIZE(ts7200_cf_resources),
++ .resource = ts7200_cf_resources,
++};
++
++
++static __init int pata_ts7200_cf_init(void)
++{
++ return (board_is_ts7200()) ? \
++ platform_device_register(&ts7200_cf_device) : -ENODEV;
++}
++
++static __exit void pata_ts7200_cf_exit(void)
++{
++ platform_device_unregister(&ts7200_cf_device);
++}
++
++module_init(pata_ts7200_cf_init);
++module_exit(pata_ts7200_cf_exit);
++
++MODULE_AUTHOR("Matthieu Crapet <mcrapet@gmail.com>");
++MODULE_DESCRIPTION("TS-7200 CF PATA device driver");
++MODULE_LICENSE("GPL");
++MODULE_VERSION(DRV_VERSION);
+diff --git a/drivers/ata/pata_ts72xx.c b/drivers/ata/pata_ts72xx.c
+new file mode 100644
+index 0000000..d540029
+--- /dev/null
++++ b/drivers/ata/pata_ts72xx.c
+@@ -0,0 +1,161 @@
++/*
++ * TS-72XX PATA driver for Technologic Systems boards.
++ *
++ * Based on pata_platform.c by Paul Mundt &
++ * Alessandro Zummo <a.zummo@towertech.it>
++ * and old pata-ts72xx.c by Alessandro Zummo <a.zummo@towertech.it>
++ *
++ * (c) Copyright 2008 Matthieu Crapet <mcrapet@gmail.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.
++ *
++ */
++
++#include <linux/kernel.h>
++#include <linux/module.h>
++#include <linux/platform_device.h>
++#include <linux/interrupt.h>
++#include <scsi/scsi_host.h>
++#include <linux/ata.h>
++#include <linux/libata.h>
++
++#define DRV_NAME "pata_ts72xx"
++#define DRV_VERSION "2.01"
++
++
++/*
++ * Provide our own set_mode() as we don't want to change anything that has
++ * already been configured..
++ */
++static int ts72xx_set_mode(struct ata_link *link, struct ata_device **unused)
++{
++ struct ata_device *dev;
++
++ ata_for_each_dev(dev, link, ENABLED) {
++ if (ata_dev_enabled(dev)) {
++ /* We don't really care */
++ dev->pio_mode = dev->xfer_mode = XFER_PIO_0;
++ dev->xfer_shift = ATA_SHIFT_PIO;
++ dev->flags |= ATA_DFLAG_PIO;
++ ata_dev_printk(dev, KERN_INFO, "configured for PIO\n");
++ }
++ }
++ return 0;
++}
++
++static struct scsi_host_template ts72xx_sht = {
++ ATA_PIO_SHT(DRV_NAME),
++};
++
++static struct ata_port_operations ts72xx_port_ops = {
++ .inherits = &ata_sff_port_ops,
++ .set_mode = ts72xx_set_mode,
++};
++
++static __devinit int ts72xx_pata_probe(struct platform_device *pdev)
++{
++ struct ata_host *host;
++ struct ata_port *ap;
++ int irq;
++
++ struct resource *pata_cmd = platform_get_resource(pdev, IORESOURCE_MEM, 0);
++ struct resource *pata_aux = platform_get_resource(pdev, IORESOURCE_MEM, 1);
++ struct resource *pata_data = platform_get_resource(pdev, IORESOURCE_MEM, 2);
++
++ if (!pata_cmd || !pata_aux || !pata_data) {
++ dev_err(&pdev->dev, "missing resource(s)\n");
++ return -EINVAL;
++ }
++
++ irq = platform_get_irq(pdev, 0);
++ if (irq < 0)
++ irq = 0; /* no irq */
++
++ /*
++ * Now that that's out of the way, wire up the port
++ */
++ host = ata_host_alloc(&pdev->dev, 1);
++ if (!host)
++ return -ENOMEM;
++ ap = host->ports[0];
++
++ ap->ops = &ts72xx_port_ops;
++ ap->pio_mask = 0x1f; /* PIO0-4 */
++ ap->flags |= ATA_FLAG_SLAVE_POSS;
++
++ /*
++ * Use polling mode if there's no IRQ
++ */
++ if (!irq) {
++ ap->flags |= ATA_FLAG_PIO_POLLING;
++ ata_port_desc(ap, "no IRQ, using PIO polling");
++ }
++
++ ap->ioaddr.cmd_addr = devm_ioremap(&pdev->dev, pata_cmd->start,
++ pata_cmd->end - pata_cmd->start + 1);
++ ap->ioaddr.ctl_addr = devm_ioremap(&pdev->dev, pata_aux->start,
++ pata_aux->end - pata_aux->start + 1);
++
++ if (!ap->ioaddr.cmd_addr || !ap->ioaddr.ctl_addr) {
++ dev_err(&pdev->dev, "failed to map IO/CTL base\n");
++ return -ENOMEM;
++ }
++
++ ap->ioaddr.altstatus_addr = ap->ioaddr.ctl_addr;
++
++ ata_sff_std_ports(&ap->ioaddr);
++ ap->ioaddr.data_addr = devm_ioremap(&pdev->dev, pata_data->start,
++ pata_data->end - pata_data->start + 1);
++
++ ata_port_desc(ap, "mmio cmd 0x%llx ctl 0x%llx",
++ (unsigned long long)pata_cmd->start,
++ (unsigned long long)pata_aux->start);
++
++ return ata_host_activate(host, irq, irq ? ata_sff_interrupt : NULL,
++ 0 /* irq flags */, &ts72xx_sht);
++}
++
++static __devexit int ts72xx_pata_remove(struct platform_device *pdev)
++{
++ struct device *dev = &pdev->dev;
++ struct ata_host *host = dev_get_drvdata(dev);
++
++ ata_host_detach(host);
++
++ return 0;
++}
++
++static struct platform_driver ts72xx_pata_platform_driver = {
++ .probe = ts72xx_pata_probe,
++ .remove = __devexit_p(ts72xx_pata_remove),
++ .driver = {
++ .name = "ts72xx-ide",
++ .owner = THIS_MODULE,
++ },
++};
++
++static int __init ts72xx_pata_init(void)
++{
++ return platform_driver_register(&ts72xx_pata_platform_driver);
++}
++
++static void __exit ts72xx_pata_exit(void)
++{
++ platform_driver_unregister(&ts72xx_pata_platform_driver);
++}
++
++MODULE_AUTHOR("Matthieu Crapet <mcrapet@gmail.com>");
++MODULE_DESCRIPTION("low-level driver for TS-72xx device PATA");
++MODULE_LICENSE("GPL");
++MODULE_VERSION(DRV_VERSION);
++
++module_init(ts72xx_pata_init);
++module_exit(ts72xx_pata_exit);
+diff --git a/drivers/ata/pata_ts9600.c b/drivers/ata/pata_ts9600.c
+new file mode 100644
+index 0000000..7a70550
+--- /dev/null
++++ b/drivers/ata/pata_ts9600.c
+@@ -0,0 +1,95 @@
++/*
++ * Technologic Systems TS-9600 PATA device driver.
++ *
++ * (c) Copyright 2008 Matthieu Crapet <mcrapet@gmail.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.
++ *
++ */
++
++#include <linux/kernel.h>
++#include <linux/module.h>
++#include <linux/libata.h>
++#include <scsi/scsi_host.h>
++#include <linux/platform_device.h>
++#include <linux/dma-mapping.h>
++
++#include <asm/io.h>
++#include <asm/irq.h>
++#include <mach/ts72xx.h>
++
++#define DRV_NAME "pata_ts9600"
++#define DRV_VERSION "0.21"
++
++#define TS9600_IDE_IO (TS72XX_PC104_8BIT_IO_PHYS_BASE + 0x1F0)
++#define TS9600_IDE_DATA (TS72XX_PC104_16BIT_IO_PHYS_BASE + 0x1F0)
++#define TS9600_IDE_IRQ IRQ_EP93XX_EXT3 // IRQ7 (no other possibility for arm)
++
++
++static void pata_ts9600_release(struct device *dev)
++{
++ /* nothing to do (no kfree) because we have static struct */
++}
++
++static struct resource ts9600_resources[] = {
++ [0] = {
++ .start = TS9600_IDE_IO,
++ .end = TS9600_IDE_IO + 8,
++ .flags = IORESOURCE_MEM,
++ },
++ [1] = {
++ .start = TS9600_IDE_IO + 0x206,
++ .end = TS9600_IDE_IO + 0x206 + 1,
++ .flags = IORESOURCE_MEM,
++ },
++ [2] = {
++ .start = TS9600_IDE_DATA,
++ .end = TS9600_IDE_DATA + 2,
++ .flags = IORESOURCE_MEM,
++ },
++ [3] = {
++ .start = TS9600_IDE_IRQ,
++ .end = TS9600_IDE_IRQ,
++ .flags = IORESOURCE_IRQ,
++ }
++};
++
++
++static struct platform_device ts9600_device = {
++ .name = "ts72xx-ide",
++ .id = 9600,
++ .dev = {
++ .dma_mask = &ts9600_device.dev.coherent_dma_mask,
++ .coherent_dma_mask = DMA_BIT_MASK(32),
++ .release = pata_ts9600_release,
++ },
++ .num_resources = ARRAY_SIZE(ts9600_resources),
++ .resource = ts9600_resources,
++};
++
++
++static __init int pata_ts9600_init(void)
++{
++ return platform_device_register(&ts9600_device);
++}
++
++static __exit void pata_ts9600_exit(void)
++{
++ platform_device_unregister(&ts9600_device);
++}
++
++module_init(pata_ts9600_init);
++module_exit(pata_ts9600_exit);
++
++MODULE_AUTHOR("Matthieu Crapet <mcrapet@gmail.com>");
++MODULE_DESCRIPTION("TS-9600 PATA device driver");
++MODULE_LICENSE("GPL");
++MODULE_VERSION(DRV_VERSION);
+--
+1.7.1
+
diff --git a/recipes/linux/linux-2.6.38/ts72xx/0010-ts72xx_gpio_i2c.patch b/recipes/linux/linux-2.6.38/ts72xx/0010-ts72xx_gpio_i2c.patch
new file mode 100644
index 0000000..15902fb
--- /dev/null
+++ b/recipes/linux/linux-2.6.38/ts72xx/0010-ts72xx_gpio_i2c.patch
@@ -0,0 +1,63 @@
+From e2e91e5a5c6ffae882ff6b9c4fda9391853dc0b8 Mon Sep 17 00:00:00 2001
+From: Matthieu Crapet <mcrapet@gmail.com>
+Date: Sat, 19 Jun 2010 11:45:39 +0200
+Subject: [PATCH 10/24] ts72xx_gpio_i2c
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Signed-off-by: Petr Štetiar <ynezz@true.cz>
+---
+ arch/arm/mach-ep93xx/ts72xx.c | 22 ++++++++++++++++++++++
+ 1 files changed, 22 insertions(+), 0 deletions(-)
+
+diff --git a/arch/arm/mach-ep93xx/ts72xx.c b/arch/arm/mach-ep93xx/ts72xx.c
+index a23a184..771ac02 100644
+--- a/arch/arm/mach-ep93xx/ts72xx.c
++++ b/arch/arm/mach-ep93xx/ts72xx.c
+@@ -19,6 +19,10 @@
+ #include <linux/m48t86.h>
+ #include <linux/mtd/nand.h>
+ #include <linux/mtd/partitions.h>
++#include <linux/mtd/physmap.h>
++#include <linux/gpio.h>
++#include <linux/i2c.h>
++#include <linux/i2c-gpio.h>
+
+ #include <mach/hardware.h>
+ #include <mach/ts72xx.h>
+@@ -279,6 +283,21 @@ static struct ep93xx_eth_data __initdata ts72xx_eth_data = {
+ .phy_id = 1,
+ };
+
++/*************************************************************************
++ * I2C (make access through TS-72XX "DIO" 2x8 header)
++ *************************************************************************/
++static struct i2c_gpio_platform_data ts72xx_i2c_gpio_data = {
++ .sda_pin = EP93XX_GPIO_LINE_EGPIO14, // DIO_6
++ .sda_is_open_drain = 0,
++ .scl_pin = EP93XX_GPIO_LINE_EGPIO15, // DIO_7
++ .scl_is_open_drain = 0,
++ .udelay = 0, /* default is 100 kHz */
++ .timeout = 0, /* default is 100 ms */
++};
++
++static struct i2c_board_info __initdata ts72xx_i2c_board_info[] = {
++};
++
+ static void __init ts72xx_init_machine(void)
+ {
+ ep93xx_init_devices();
+@@ -287,6 +306,9 @@ static void __init ts72xx_init_machine(void)
+ platform_device_register(&ts72xx_wdt_device);
+
+ ep93xx_register_eth(&ts72xx_eth_data, 1);
++ ep93xx_register_i2c(&ts72xx_i2c_gpio_data,
++ ts72xx_i2c_board_info,
++ ARRAY_SIZE(ts72xx_i2c_board_info));
+
+ /* PWM1 is DIO_6 on TS-72xx header */
+ ep93xx_register_pwm(0, 1);
+--
+1.7.1
+
diff --git a/recipes/linux/linux-2.6.38/ts72xx/0011-ts72xx_dio_keypad.patch b/recipes/linux/linux-2.6.38/ts72xx/0011-ts72xx_dio_keypad.patch
new file mode 100644
index 0000000..52f7627
--- /dev/null
+++ b/recipes/linux/linux-2.6.38/ts72xx/0011-ts72xx_dio_keypad.patch
@@ -0,0 +1,311 @@
+From 93b754cbd3b03d3de7f23902d452f3e36b085eaf Mon Sep 17 00:00:00 2001
+From: Matthieu Crapet <mcrapet@gmail.com>
+Date: Sat, 19 Jun 2010 14:44:32 +0200
+Subject: [PATCH 11/24] ts72xx_dio_keypad
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Depends of "matrix-keypad" driver.
+
+Signed-off-by: Petr Štetiar <ynezz@true.cz>
+---
+ drivers/input/keyboard/Kconfig | 30 ++++++++
+ drivers/input/keyboard/Makefile | 2 +
+ drivers/input/keyboard/ts72xx_dio_3x4.c | 110 +++++++++++++++++++++++++++++
+ drivers/input/keyboard/ts72xx_dio_4x4.c | 115 +++++++++++++++++++++++++++++++
+ 4 files changed, 257 insertions(+), 0 deletions(-)
+ create mode 100644 drivers/input/keyboard/ts72xx_dio_3x4.c
+ create mode 100644 drivers/input/keyboard/ts72xx_dio_4x4.c
+
+diff --git a/drivers/input/keyboard/Kconfig b/drivers/input/keyboard/Kconfig
+index c7a9202..9699164 100644
+--- a/drivers/input/keyboard/Kconfig
++++ b/drivers/input/keyboard/Kconfig
+@@ -210,6 +210,36 @@ config KEYBOARD_MATRIX
+ To compile this driver as a module, choose M here: the
+ module will be called matrix_keypad.
+
++if KEYBOARD_MATRIX
++
++choice
++ prompt "Keypad type"
++ default TS72XX_DIO_4X4_KEYPAD
++
++config TS72XX_DIO_3X4_KEYPAD
++ tristate "TS-72xx 3x4 matrix keypad"
++ depends on MACH_TS72XX
++ help
++ This a 12 keys (4 rows, 3 cols using DIO_0-6) keypad with the following layout:
++ 1 2 3
++ 4 5 6
++ 7 8 9
++ * 0 #
++
++config TS72XX_DIO_4X4_KEYPAD
++ tristate "TS-72xx 4x4 matrix keypad"
++ depends on MACH_TS72XX
++ help
++ This a 16 keys (4 rows, 4 cols using DIO_0-7) keypad with the following layout:
++ 7 8 9 F
++ 4 5 6 E
++ 1 2 3 D
++ A 0 B C
++
++endchoice
++
++endif # KEYBOARD_MATRIX
++
+ config KEYBOARD_HIL_OLD
+ tristate "HP HIL keyboard support (simple driver)"
+ depends on GSC || HP300
+diff --git a/drivers/input/keyboard/Makefile b/drivers/input/keyboard/Makefile
+index 468c627..144c078 100644
+--- a/drivers/input/keyboard/Makefile
++++ b/drivers/input/keyboard/Makefile
+@@ -47,3 +47,5 @@ obj-$(CONFIG_KEYBOARD_TNETV107X) += tnetv107x-keypad.o
+ obj-$(CONFIG_KEYBOARD_TWL4030) += twl4030_keypad.o
+ obj-$(CONFIG_KEYBOARD_XTKBD) += xtkbd.o
+ obj-$(CONFIG_KEYBOARD_W90P910) += w90p910_keypad.o
++obj-$(CONFIG_TS72XX_DIO_3X4_KEYPAD) += ts72xx_dio_3x4.o
++obj-$(CONFIG_TS72XX_DIO_4X4_KEYPAD) += ts72xx_dio_4x4.o
+diff --git a/drivers/input/keyboard/ts72xx_dio_3x4.c b/drivers/input/keyboard/ts72xx_dio_3x4.c
+new file mode 100644
+index 0000000..e214335
+--- /dev/null
++++ b/drivers/input/keyboard/ts72xx_dio_3x4.c
+@@ -0,0 +1,110 @@
++/*
++ * TS-72xx (3x4) keypad device driver for DIO1 header (DIO_0 thru DIO_6)
++ *
++ * (c) Copyright 2010 Matthieu Crapet <mcrapet@gmail.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.
++ *
++ */
++
++#include <linux/module.h>
++#include <linux/kernel.h>
++#include <linux/init.h>
++#include <linux/platform_device.h>
++#include <linux/input/matrix_keypad.h>
++#include <mach/gpio.h>
++
++static const uint32_t ts72xx_kbd_keymap[] = {
++ KEY(0, 0, KEY_1),
++ KEY(0, 1, KEY_2),
++ KEY(0, 2, KEY_3),
++
++ KEY(1, 0, KEY_4),
++ KEY(1, 1, KEY_5),
++ KEY(1, 2, KEY_6),
++
++ KEY(2, 0, KEY_7),
++ KEY(2, 1, KEY_8),
++ KEY(2, 2, KEY_9),
++
++ KEY(3, 0, KEY_KPASTERISK),
++ KEY(3, 1, KEY_0),
++ KEY(3, 2, KEY_ENTER),
++};
++
++static struct matrix_keymap_data ts72xx_kbd_keymap_data = {
++ .keymap = ts72xx_kbd_keymap,
++ .keymap_size = ARRAY_SIZE(ts72xx_kbd_keymap),
++};
++
++static const int ts72xx_kbd_row_gpios[] = {
++ EP93XX_GPIO_LINE_EGPIO14, // DIO_6 (row0)
++ EP93XX_GPIO_LINE_EGPIO13,
++ EP93XX_GPIO_LINE_EGPIO12,
++ EP93XX_GPIO_LINE_EGPIO11,
++};
++
++static const int ts72xx_kbd_col_gpios[] = {
++ EP93XX_GPIO_LINE_EGPIO10, // DIO_2 (col0)
++ EP93XX_GPIO_LINE_EGPIO9,
++ EP93XX_GPIO_LINE_EGPIO8,
++};
++
++static struct matrix_keypad_platform_data ts72xx_kbd_pdata = {
++ .keymap_data = &ts72xx_kbd_keymap_data,
++ .row_gpios = ts72xx_kbd_row_gpios,
++ .col_gpios = ts72xx_kbd_col_gpios,
++ .num_row_gpios = ARRAY_SIZE(ts72xx_kbd_row_gpios),
++ .num_col_gpios = ARRAY_SIZE(ts72xx_kbd_col_gpios),
++ .col_scan_delay_us = 20,
++ .debounce_ms = 20,
++ .wakeup = 1,
++ .active_low = 1,
++ //.no_autorep = 1,
++};
++
++static void ts72xx_kbd_release(struct device *dev)
++{
++}
++
++static struct platform_device ts72xx_kbd_device = {
++ .name = "matrix-keypad",
++ .id = -1,
++ .dev = {
++ .platform_data = &ts72xx_kbd_pdata,
++ .release = ts72xx_kbd_release,
++ },
++};
++
++static int __init ts72xx_dio_init(void)
++{
++ int i;
++
++ for (i = 0; i < ARRAY_SIZE(ts72xx_kbd_row_gpios); i++) {
++ int irq = gpio_to_irq(ts72xx_kbd_row_gpios[i]);
++
++ ep93xx_gpio_int_debounce(irq, 1);
++ }
++
++ return platform_device_register(&ts72xx_kbd_device);
++}
++
++static void __exit ts72xx_dio_exit(void)
++{
++ platform_device_unregister(&ts72xx_kbd_device);
++}
++
++module_init(ts72xx_dio_init);
++module_exit(ts72xx_dio_exit);
++
++MODULE_AUTHOR("Matthieu Crapet <mcrapet@gmail.com>");
++MODULE_DESCRIPTION("Platform device 3x4 keypad");
++MODULE_LICENSE("GPL");
+diff --git a/drivers/input/keyboard/ts72xx_dio_4x4.c b/drivers/input/keyboard/ts72xx_dio_4x4.c
+new file mode 100644
+index 0000000..790abd5
+--- /dev/null
++++ b/drivers/input/keyboard/ts72xx_dio_4x4.c
+@@ -0,0 +1,115 @@
++/*
++ * TS-72xx (4x4) keypad device driver for DIO1 header (DIO_0 thru DIO_7)
++ *
++ * (c) Copyright 2010 Matthieu Crapet <mcrapet@gmail.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.
++ *
++ */
++
++#include <linux/module.h>
++#include <linux/kernel.h>
++#include <linux/init.h>
++#include <linux/platform_device.h>
++#include <linux/input/matrix_keypad.h>
++#include <mach/gpio.h>
++
++static const uint32_t ts72xx_kbd_keymap[] = {
++ KEY(0, 0, KEY_7),
++ KEY(0, 1, KEY_8),
++ KEY(0, 2, KEY_9),
++ KEY(0, 3, KEY_F),
++
++ KEY(1, 0, KEY_4),
++ KEY(1, 1, KEY_5),
++ KEY(1, 2, KEY_6),
++ KEY(1, 3, KEY_E),
++
++ KEY(2, 0, KEY_1),
++ KEY(2, 1, KEY_2),
++ KEY(2, 2, KEY_3),
++ KEY(2, 3, KEY_D),
++
++ KEY(3, 0, KEY_A),
++ KEY(3, 1, KEY_0),
++ KEY(3, 2, KEY_B),
++ KEY(3, 3, KEY_C),
++};
++
++static struct matrix_keymap_data ts72xx_kbd_keymap_data = {
++ .keymap = ts72xx_kbd_keymap,
++ .keymap_size = ARRAY_SIZE(ts72xx_kbd_keymap),
++};
++
++static const int ts72xx_kbd_row_gpios[] = {
++ EP93XX_GPIO_LINE_EGPIO8, // DIO_0 (row0)
++ EP93XX_GPIO_LINE_EGPIO9,
++ EP93XX_GPIO_LINE_EGPIO12,
++ EP93XX_GPIO_LINE_EGPIO14,
++};
++
++static const int ts72xx_kbd_col_gpios[] = {
++ EP93XX_GPIO_LINE_EGPIO15, // DIO_7 (col0)
++ EP93XX_GPIO_LINE_EGPIO13,
++ EP93XX_GPIO_LINE_EGPIO11,
++ EP93XX_GPIO_LINE_EGPIO10,
++};
++
++static struct matrix_keypad_platform_data ts72xx_kbd_pdata = {
++ .keymap_data = &ts72xx_kbd_keymap_data,
++ .row_gpios = ts72xx_kbd_row_gpios,
++ .col_gpios = ts72xx_kbd_col_gpios,
++ .num_row_gpios = ARRAY_SIZE(ts72xx_kbd_row_gpios),
++ .num_col_gpios = ARRAY_SIZE(ts72xx_kbd_col_gpios),
++ .col_scan_delay_us = 20,
++ .debounce_ms = 20,
++ .wakeup = 1,
++ .active_low = 1,
++ //.no_autorep = 1,
++};
++
++static void ts72xx_kbd_release(struct device *dev)
++{
++}
++
++static struct platform_device ts72xx_kbd_device = {
++ .name = "matrix-keypad",
++ .id = -1,
++ .dev = {
++ .platform_data = &ts72xx_kbd_pdata,
++ .release = ts72xx_kbd_release,
++ },
++};
++
++static int __init ts72xx_dio_init(void)
++{
++ int i;
++
++ for (i = 0; i < ARRAY_SIZE(ts72xx_kbd_row_gpios); i++) {
++ int irq = gpio_to_irq(ts72xx_kbd_row_gpios[i]);
++
++ ep93xx_gpio_int_debounce(irq, 1);
++ }
++
++ return platform_device_register(&ts72xx_kbd_device);
++}
++
++static void __exit ts72xx_dio_exit(void)
++{
++ platform_device_unregister(&ts72xx_kbd_device);
++}
++
++module_init(ts72xx_dio_init);
++module_exit(ts72xx_dio_exit);
++
++MODULE_AUTHOR("Matthieu Crapet <mcrapet@gmail.com>");
++MODULE_DESCRIPTION("Platform device 4x4 keypad");
++MODULE_LICENSE("GPL");
+--
+1.7.1
+
diff --git a/recipes/linux/linux-2.6.38/ts72xx/0012-ts72xx_sbcinfo.patch b/recipes/linux/linux-2.6.38/ts72xx/0012-ts72xx_sbcinfo.patch
new file mode 100644
index 0000000..33f787c
--- /dev/null
+++ b/recipes/linux/linux-2.6.38/ts72xx/0012-ts72xx_sbcinfo.patch
@@ -0,0 +1,267 @@
+From d9a3ab74ee030c606f9a9935fc8d08366b170da9 Mon Sep 17 00:00:00 2001
+From: Matthieu Crapet <mcrapet@gmail.com>
+Date: Sat, 19 Jun 2010 15:08:58 +0200
+Subject: [PATCH 12/24] ts72xx_sbcinfo
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Signed-off-by: Petr Štetiar <ynezz@true.cz>
+---
+ arch/arm/mach-ep93xx/Kconfig | 7 +
+ arch/arm/mach-ep93xx/Makefile | 1 +
+ arch/arm/mach-ep93xx/ts72xx.c | 5 +
+ arch/arm/mach-ep93xx/ts72xx_sbcinfo.c | 198 +++++++++++++++++++++++++++++++++
+ 4 files changed, 211 insertions(+), 0 deletions(-)
+ create mode 100644 arch/arm/mach-ep93xx/ts72xx_sbcinfo.c
+
+diff --git a/arch/arm/mach-ep93xx/Kconfig b/arch/arm/mach-ep93xx/Kconfig
+index bd463a0..2bfb01e 100644
+--- a/arch/arm/mach-ep93xx/Kconfig
++++ b/arch/arm/mach-ep93xx/Kconfig
+@@ -212,6 +212,13 @@ config MACH_TS72XX_FORCE_MACHINEID
+ Say 'Y' here to force Machine ID to 0x2A1 (MACH_TYPE_TS72XX legacy value)
+ In early days Technologic Systems fixed the 0x163 value in redboot.
+
++config MACH_TS72XX_SBCINFO
++ tristate "Add procfs /proc/driver/sbcinfo"
++ depends on MACH_TS72XX
++ help
++ Say 'Y' to add a procfs entry containing some information
++ related to Technologic Systems TS-72xx SBC.
++
+ endmenu
+
+ endif
+diff --git a/arch/arm/mach-ep93xx/Makefile b/arch/arm/mach-ep93xx/Makefile
+index ea652c2..c38d1e2 100644
+--- a/arch/arm/mach-ep93xx/Makefile
++++ b/arch/arm/mach-ep93xx/Makefile
+@@ -13,3 +13,4 @@ obj-$(CONFIG_MACH_MICRO9) += micro9.o
+ obj-$(CONFIG_MACH_SIM_ONE) += simone.o
+ obj-$(CONFIG_MACH_SNAPPER_CL15) += snappercl15.o
+ obj-$(CONFIG_MACH_TS72XX) += ts72xx.o
++obj-$(CONFIG_MACH_TS72XX_SBCINFO) += ts72xx_sbcinfo.o
+diff --git a/arch/arm/mach-ep93xx/ts72xx.c b/arch/arm/mach-ep93xx/ts72xx.c
+index 771ac02..c33cb2c 100644
+--- a/arch/arm/mach-ep93xx/ts72xx.c
++++ b/arch/arm/mach-ep93xx/ts72xx.c
+@@ -39,6 +39,11 @@ static struct map_desc ts72xx_io_desc[] __initdata = {
+ .length = TS72XX_MODEL_SIZE,
+ .type = MT_DEVICE,
+ }, {
++ .virtual = TS72XX_PLD_VERSION_VIRT_BASE,
++ .pfn = __phys_to_pfn(TS72XX_PLD_VERSION_PHYS_BASE),
++ .length = TS72XX_PLD_VERSION_SIZE,
++ .type = MT_DEVICE,
++ }, {
+ .virtual = TS72XX_OPTIONS_VIRT_BASE,
+ .pfn = __phys_to_pfn(TS72XX_OPTIONS_PHYS_BASE),
+ .length = TS72XX_OPTIONS_SIZE,
+diff --git a/arch/arm/mach-ep93xx/ts72xx_sbcinfo.c b/arch/arm/mach-ep93xx/ts72xx_sbcinfo.c
+new file mode 100644
+index 0000000..cbb485f
+--- /dev/null
++++ b/arch/arm/mach-ep93xx/ts72xx_sbcinfo.c
+@@ -0,0 +1,198 @@
++/*
++ * Technologic Systems TS-72XX sbc /proc/driver/sbcinfo entry.
++ *
++ * Original idea by Liberty Young (Technologic Systems).
++ *
++ * (c) Copyright 2008 Matthieu Crapet <mcrapet@gmail.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.
++ */
++
++#include <linux/module.h>
++#include <linux/kernel.h>
++#include <linux/init.h>
++#include <linux/io.h>
++#include <linux/proc_fs.h>
++#include <mach/hardware.h>
++#include <mach/ts72xx.h>
++
++struct infos {
++ const char *cpu_rev;
++ int model, pld, wdt;
++ int option_ad;
++ int option_rs485;
++ unsigned char jumpers[6]; // 0=off,1=on,2=error
++
++ /* Power management : TS-7260 only */
++ int pm;
++};
++
++static const char *revisions[] = { "A", "B", "C", "D0", "D1", "E0", "E1", "E2", "??" };
++
++
++static void get_sbcinfo(struct infos *data)
++{
++ void __iomem *p;
++ short rev;
++
++ /* CPU revision */
++ rev = __raw_readl(EP93XX_SYSCON_CHIPID) >> 28;
++ if (rev > ARRAY_SIZE(revisions))
++ rev = ARRAY_SIZE(revisions) - 1;
++ data->cpu_rev = revisions[rev];
++
++ /* Board model */
++ if (board_is_ts7200())
++ data->model = 7200;
++ else if (board_is_ts7250())
++ data->model = 7250;
++ else if (board_is_ts7260())
++ data->model = 7260;
++ else if (board_is_ts7400())
++ data->model = 7400;
++ else
++ data->model = 0;
++
++ data->pld = get_ts72xx_pld_version();
++
++ /* A/D converter (8 x 12-bit channels) */
++ if (data->model == 7200 || data->model == 7250) {
++ data->option_ad = is_max197_installed();
++ } else {
++ data->option_ad = 0;
++ }
++
++ /* COM2 RS-485 */
++ if (is_rs485_installed()) {
++ data->option_rs485 = 1;
++ } else {
++ data->option_rs485 = 0;
++ }
++
++ /* jumpers */
++ p = ioremap(TS72XX_JUMPERS_MAX197_PHYS_BASE, SZ_4K - 1);
++ if (p) {
++ unsigned char c = __raw_readb(p);
++
++ data->jumpers[0] = 2; // JP1 (bootstrap)
++ data->jumpers[1] = !!(c & 0x01); // JP2 (enable serial console)
++ data->jumpers[2] = !!(c & 0x02); // JP3 (flash write enable)
++ data->jumpers[3] = !(c & 0x08); // JP4 (console on COM2)
++ data->jumpers[4] = !(c & 0x10); // JP5 (test)
++ data->jumpers[5] = !!(is_jp6_set()); // JP6 (user jumper)
++
++ iounmap(p);
++ } else {
++ data->jumpers[0] = data->jumpers[1] = data->jumpers[2] = 2;
++ data->jumpers[3] = data->jumpers[4] = data->jumpers[5] = 2;
++ }
++
++ /* cpld watchdog */
++ p = ioremap(TS72XX_WDT_CONTROL_PHYS_BASE, SZ_4K - 1);
++ if (p) {
++ data->wdt = __raw_readb(p) & 0x7;
++ iounmap(p);
++ } else {
++ data->wdt = 8;
++ }
++
++ /* power management */
++ data->pm = -1;
++ if (data->model == 7260) {
++ p = ioremap(TS7260_POWER_MANAGEMENT_PHYS_BASE, SZ_4K - 1);
++ if (p) {
++ data->pm = __raw_readb(p);
++ iounmap(p);
++ }
++ }
++}
++
++static char *get_pm_string(int reg, char *buffer, size_t size)
++{
++ static const char *pm_state = "rs232=%d usb=%d lcd=%d pc104=%d ttl=%d";
++
++ if (reg < 0) {
++ strncpy(buffer, "n/a", size);
++ } else {
++ /* 1 means on/enabled */
++ snprintf(buffer, size, pm_state,
++ reg & TS7260_PM_RS232_LEVEL_CONVERTER,
++ !!(reg & TS7260_PM_USB),
++ !!(reg & TS7260_PM_LCD),
++ !(reg & TS7260_PM_PC104_CLOCK),
++ !!(reg & TS7260_PM_TTL_UART_ENABLE));
++ }
++ return buffer;
++}
++
++static int ts72xx_sbcinfo_read_proc(char *buffer, char **start, off_t offset,
++ int count, int *eof, void *data)
++{
++ int len, size = count;
++ char *p = buffer;
++ char temp[64];
++ struct infos nfo;
++
++ static const char jpc[3] = { 'n', 'y', '?' };
++ static const char *wdt[9] = { "disabled", "250ms", "500ms", "1s", "reserved", "2s", "4s", "8s", "n/a" };
++
++ get_sbcinfo(&nfo);
++ len = scnprintf(p, size,
++ "Model : TS-%d (CPU rev %s) (PLD rev %c)\n"
++ "Option max197 A/D : %s\n"
++ "Option RS-485 : %s\n"
++ "Jumpers : JP2=%c JP3=%c JP4=%c JP5=%c JP6=%c\n"
++ "CPLD Watchdog : %s\n"
++ "Power management : %s\n",
++ nfo.model, nfo.cpu_rev, nfo.pld + 0x40,
++ (nfo.option_ad ? "yes" : "no"),
++ (nfo.option_rs485 ? "yes" : "no"),
++ jpc[nfo.jumpers[1]], jpc[nfo.jumpers[2]], jpc[nfo.jumpers[3]], jpc[nfo.jumpers[4]],
++ jpc[nfo.jumpers[5]], wdt[nfo.wdt],
++ get_pm_string(nfo.pm, &temp[0], sizeof(temp)));
++
++ if (len <= offset + count)
++ *eof = 1;
++
++ *start = buffer + offset;
++ len -= offset;
++
++ if (len > count)
++ len = count;
++ if (len < 0)
++ len = 0;
++
++ return len;
++}
++
++static int __init ts72xx_sbcinfo_init(void)
++{
++ struct proc_dir_entry *entry;
++ int ret = 0;
++
++ entry = create_proc_read_entry("driver/sbcinfo", 0,
++ NULL, ts72xx_sbcinfo_read_proc, NULL);
++
++ if (!entry) {
++ printk(KERN_ERR "sbcinfo: can't create /proc/driver/sbcinfo\n");
++ ret = -ENOMEM;
++ }
++
++ return ret;
++}
++
++static void __exit ts72xx_sbcinfo_exit(void)
++{
++ remove_proc_entry("driver/sbcinfo", NULL);
++}
++
++module_init(ts72xx_sbcinfo_init);
++module_exit(ts72xx_sbcinfo_exit);
++
++MODULE_AUTHOR("Matthieu Crapet <mcrapet@gmail.com>");
++MODULE_DESCRIPTION("Show information of Technologic Systems TS-72XX sbc");
++MODULE_LICENSE("GPL");
++MODULE_VERSION("1.04");
+--
+1.7.1
+
diff --git a/recipes/linux/linux-2.6.38/ts72xx/0013-ts72xx_max197.patch b/recipes/linux/linux-2.6.38/ts72xx/0013-ts72xx_max197.patch
new file mode 100644
index 0000000..2305853
--- /dev/null
+++ b/recipes/linux/linux-2.6.38/ts72xx/0013-ts72xx_max197.patch
@@ -0,0 +1,356 @@
+From 2f2812bf0dee574b580b44863f53feca9b49ae60 Mon Sep 17 00:00:00 2001
+From: Matthieu Crapet <mcrapet@gmail.com>
+Date: Sat, 19 Jun 2010 15:49:34 +0200
+Subject: [PATCH 13/24] ts72xx_max197
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Signed-off-by: Petr Štetiar <ynezz@true.cz>
+---
+ arch/arm/mach-ep93xx/ts72xx.c | 32 ++++++-
+ drivers/misc/Kconfig | 21 ++++
+ drivers/misc/Makefile | 1 +
+ drivers/misc/ts72xx_max197.c | 235 +++++++++++++++++++++++++++++++++++++++++
+ 4 files changed, 288 insertions(+), 1 deletions(-)
+ create mode 100644 drivers/misc/ts72xx_max197.c
+
+diff --git a/arch/arm/mach-ep93xx/ts72xx.c b/arch/arm/mach-ep93xx/ts72xx.c
+index c33cb2c..419646a 100644
+--- a/arch/arm/mach-ep93xx/ts72xx.c
++++ b/arch/arm/mach-ep93xx/ts72xx.c
+@@ -281,10 +281,36 @@ static struct platform_device ts72xx_wdt_device = {
+ .resource = ts72xx_wdt_resources,
+ };
+
+-static struct ep93xx_eth_data __initdata ts72xx_eth_data = {
++/*************************************************************************
++ * MAX197 (8 * 12-bit A/D converter) option
++ *************************************************************************/
++static struct resource ts72xx_max197_resources[] = {
++ [0] = { /* sample/control register */
++ .start = TS72XX_MAX197_SAMPLE_PHYS_BASE,
++ .end = TS72XX_MAX197_SAMPLE_PHYS_BASE + SZ_4K - 1,
++ .flags = IORESOURCE_MEM,
++ },
++ [1] = { /* busy bit */
++ .start = TS72XX_JUMPERS_MAX197_PHYS_BASE,
++ .end = TS72XX_JUMPERS_MAX197_PHYS_BASE + SZ_4K - 1,
++ .flags = IORESOURCE_MEM,
++ }
++};
++
++static struct platform_device ts72xx_max197_device = {
++ .name = "ts72xx-max197",
++ .id = -1,
++ .dev = {
++ .platform_data = NULL,
++ },
++ .num_resources = ARRAY_SIZE(ts72xx_max197_resources),
++ .resource = ts72xx_max197_resources,
++};
++
+ /*************************************************************************
+ * Ethernet
+ *************************************************************************/
++static struct ep93xx_eth_data __initdata ts72xx_eth_data = {
+ .phy_id = 1,
+ };
+
+@@ -315,6 +341,10 @@ static void __init ts72xx_init_machine(void)
+ ts72xx_i2c_board_info,
+ ARRAY_SIZE(ts72xx_i2c_board_info));
+
++ if (is_max197_installed()) {
++ platform_device_register(&ts72xx_max197_device);
++ }
++
+ /* PWM1 is DIO_6 on TS-72xx header */
+ ep93xx_register_pwm(0, 1);
+ }
+diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
+index cc8e49d..ad84ed6 100644
+--- a/drivers/misc/Kconfig
++++ b/drivers/misc/Kconfig
+@@ -458,4 +458,25 @@ source "drivers/misc/cb710/Kconfig"
+ source "drivers/misc/iwmc3200top/Kconfig"
+ source "drivers/misc/ti-st/Kconfig"
+
++config TS72XX_MAX197
++ tristate "TS-72xx MAX197 support"
++ depends on ARCH_EP93XX && MACH_TS72XX && SYSFS
++ help
++ Say Y here if to include support for the MAX197 A/D converter
++ optionally included on Technologic Systems SBCs.
++ Default acquisition range is [0..5V].
++
++ To compile this driver as a module, choose M here: the
++ module will be called ts72xx_max197.
++
++if TS72XX_MAX197
++
++config TS72XX_MAX197_AVERAGE
++ bool "Average measurement"
++ help
++ Say Y here to enable making average measurement. Default is 1.
++ See /sys/module/ts72xx_max197/parameters/average file.
++
++endif # TS72XX_MAX197
++
+ endif # MISC_DEVICES
+diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile
+index 98009cc..bec11b4 100644
+--- a/drivers/misc/Makefile
++++ b/drivers/misc/Makefile
+@@ -30,6 +30,7 @@ obj-$(CONFIG_ISL29003) += isl29003.o
+ obj-$(CONFIG_ISL29020) += isl29020.o
+ obj-$(CONFIG_SENSORS_TSL2550) += tsl2550.o
+ obj-$(CONFIG_EP93XX_PWM) += ep93xx_pwm.o
++obj-$(CONFIG_TS72XX_MAX197) += ts72xx_max197.o
+ obj-$(CONFIG_DS1682) += ds1682.o
+ obj-$(CONFIG_TI_DAC7512) += ti_dac7512.o
+ obj-$(CONFIG_C2PORT) += c2port/
+diff --git a/drivers/misc/ts72xx_max197.c b/drivers/misc/ts72xx_max197.c
+new file mode 100644
+index 0000000..4121ae5
+--- /dev/null
++++ b/drivers/misc/ts72xx_max197.c
+@@ -0,0 +1,235 @@
++/*
++ * TS-72XX max197 driver for Technologic Systems boards.
++ *
++ * Voltage conversion is taken from adc_logger from Jim Jackson.
++ * (c) Copyright 2008 Matthieu Crapet <mcrapet@gmail.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.
++ */
++
++#include <linux/kernel.h>
++#include <linux/module.h>
++#include <linux/platform_device.h>
++#include <asm/io.h>
++
++#define DRV_VERSION "0.2"
++#define PFX "ts72xx_max197: "
++
++#define MAX197_RANGE_5_5 1 // [- 5V + 5V]
++#define MAX197_RANGE_10_10 3 // [-10V +10V]
++#define MAX197_RANGE_0_5 0 // [ 0V + 5V]
++#define MAX197_RANGE_0_10 2 // [ 0V +10V]
++
++#define MAX197_RESET_CHANNEL_CONF(x) (~(3 << (2*(x))))
++#define MAX197_SET_CHANNEL_CONF(x, range) ((range) << (2*(x)))
++#define MAX197_GET_CHANNEL_CONF(x, conf) (((conf) >> (2*(x))) & 3)
++
++struct max197_config
++{
++ void __iomem *control_and_data_register;
++ void __iomem *busy_bit_register;
++ unsigned int channels; // two bits per channels
++};
++
++static struct max197_config conf;
++#ifdef CONFIG_TS72XX_MAX197_AVERAGE
++static ushort average = 1;
++#endif
++
++static ssize_t max197_acquire(struct device *dev,
++ struct device_attribute *attr, char *buf)
++{
++ int range, n;
++ signed short val;
++#ifdef CONFIG_TS72XX_MAX197_AVERAGE
++ int i, total;
++#endif
++
++ n = attr->attr.name[2] - 0x31;
++ range = MAX197_GET_CHANNEL_CONF(n, conf.channels);
++
++#ifdef CONFIG_TS72XX_MAX197_AVERAGE
++ val = 0; total = 0;
++ for (i = 0; i < average; i++) {
++#endif
++
++ __raw_writeb(((range << 3) | n | 0x40) & 0xFF,
++ conf.control_and_data_register);
++ while (__raw_readb(conf.busy_bit_register) & 0x80);
++ val = __raw_readw(conf.control_and_data_register);
++
++ //printk(PFX "%hd/%hd: 0x%04X\n", i+1, average, val);
++
++#ifdef CONFIG_TS72XX_MAX197_AVERAGE
++ total += val;
++ }
++ total /= average;
++ val = (signed short)total;
++#endif
++
++ /* We want three digit precision */
++ switch (range) {
++ case MAX197_RANGE_0_5:
++ val = ((val * 50000/4096)+5)/10;
++ break;
++ case MAX197_RANGE_5_5:
++ case MAX197_RANGE_0_10:
++ val = ((val * 100000/4096)+5)/10;
++ break;
++ case MAX197_RANGE_10_10:
++ val = ((val * 200000/4096)+5)/10;
++ break;
++ }
++
++ return sprintf(buf, "%d.%03ld\n", val/1000, abs(val%1000));
++}
++
++static ssize_t max197_configure(struct device *dev,
++ struct device_attribute *attr, const char *buf, size_t len)
++{
++ int n = attr->attr.name[2] - 0x31;
++
++ long val = simple_strtol(buf, NULL, 10);
++ switch (val) {
++ case 10:
++ conf.channels &= MAX197_RESET_CHANNEL_CONF(n);
++ conf.channels |= MAX197_SET_CHANNEL_CONF(n, MAX197_RANGE_0_10);
++ break;
++ case 5:
++ conf.channels &= MAX197_RESET_CHANNEL_CONF(n);
++ conf.channels |= MAX197_SET_CHANNEL_CONF(n, MAX197_RANGE_0_5);
++ break;
++ case -10:
++ conf.channels &= MAX197_RESET_CHANNEL_CONF(n);
++ conf.channels |= MAX197_SET_CHANNEL_CONF(n, MAX197_RANGE_10_10);
++ break;
++ case -5:
++ conf.channels &= MAX197_RESET_CHANNEL_CONF(n);
++ conf.channels |= MAX197_SET_CHANNEL_CONF(n, MAX197_RANGE_5_5);
++ break;
++
++ default:
++ return -EINVAL;
++ }
++
++ return len;
++}
++
++static DEVICE_ATTR(ch1, S_IWUSR | S_IRUGO, max197_acquire, max197_configure);
++static DEVICE_ATTR(ch2, S_IWUSR | S_IRUGO, max197_acquire, max197_configure);
++static DEVICE_ATTR(ch3, S_IWUSR | S_IRUGO, max197_acquire, max197_configure);
++static DEVICE_ATTR(ch4, S_IWUSR | S_IRUGO, max197_acquire, max197_configure);
++static DEVICE_ATTR(ch5, S_IWUSR | S_IRUGO, max197_acquire, max197_configure);
++static DEVICE_ATTR(ch6, S_IWUSR | S_IRUGO, max197_acquire, max197_configure);
++static DEVICE_ATTR(ch7, S_IWUSR | S_IRUGO, max197_acquire, max197_configure);
++static DEVICE_ATTR(ch8, S_IWUSR | S_IRUGO, max197_acquire, max197_configure);
++
++static struct attribute *max197_attributes[] = {
++ &dev_attr_ch1.attr,
++ &dev_attr_ch2.attr,
++ &dev_attr_ch3.attr,
++ &dev_attr_ch4.attr,
++ &dev_attr_ch5.attr,
++ &dev_attr_ch6.attr,
++ &dev_attr_ch7.attr,
++ &dev_attr_ch8.attr,
++ NULL
++};
++
++static struct attribute_group max197_group = {
++ .attrs = max197_attributes,
++ //.name = "channels",
++};
++
++static __devinit int ts72xx_max197_probe(struct platform_device *pdev)
++{
++ int err = 0;
++ struct resource *r_data, *r_busy;
++
++ r_data = platform_get_resource(pdev, IORESOURCE_MEM, 0);
++ r_busy = platform_get_resource(pdev, IORESOURCE_MEM, 1);
++
++ if (!r_data || !r_busy) {
++ dev_err(&pdev->dev, "missing resource(s)\n");
++ return -EINVAL;
++ }
++
++ conf.control_and_data_register = ioremap(r_data->start, r_data->end - r_data->start + 1);
++ if (!conf.control_and_data_register) {
++ err = -ENODEV;
++ goto exit;
++ }
++
++ conf.busy_bit_register = ioremap(r_busy->start, r_busy->end - r_busy->start + 1);
++ if (!conf.busy_bit_register) {
++ err = -ENODEV;
++ goto exit_unmap1;
++ }
++
++ conf.channels =
++ MAX197_SET_CHANNEL_CONF(0, MAX197_RANGE_0_5) |
++ MAX197_SET_CHANNEL_CONF(1, MAX197_RANGE_0_5) |
++ MAX197_SET_CHANNEL_CONF(2, MAX197_RANGE_0_5) |
++ MAX197_SET_CHANNEL_CONF(3, MAX197_RANGE_0_5) |
++ MAX197_SET_CHANNEL_CONF(4, MAX197_RANGE_0_5) |
++ MAX197_SET_CHANNEL_CONF(5, MAX197_RANGE_0_5) |
++ MAX197_SET_CHANNEL_CONF(6, MAX197_RANGE_0_5) |
++ MAX197_SET_CHANNEL_CONF(7, MAX197_RANGE_0_5);
++
++ /* Register sysfs hooks */
++ if ((err = sysfs_create_group(&pdev->dev.kobj, &max197_group)))
++ goto exit_unmap2;
++
++ printk(PFX "TS-72xx max197 driver, v%s\n", DRV_VERSION);
++ return 0;
++
++exit_unmap2:
++ iounmap(conf.busy_bit_register);
++exit_unmap1:
++ iounmap(conf.control_and_data_register);
++exit:
++ return err;
++}
++
++static int __devexit ts72xx_max197_remove(struct platform_device *pdev)
++{
++ sysfs_remove_group(&pdev->dev.kobj, &max197_group);
++ iounmap(conf.busy_bit_register);
++ iounmap(conf.control_and_data_register);
++ return 0;
++}
++
++static struct platform_driver ts72xx_max197_platform_driver = {
++ .probe = ts72xx_max197_probe,
++ .remove = __devexit_p(ts72xx_max197_remove),
++ .driver = {
++ .name = "ts72xx-max197",
++ .owner = THIS_MODULE,
++ },
++};
++
++static int __init ts72xx_max197_init(void)
++{
++ return platform_driver_register(&ts72xx_max197_platform_driver);
++}
++
++static void __exit ts72xx_max197_exit(void)
++{
++ platform_driver_unregister(&ts72xx_max197_platform_driver);
++}
++
++#ifdef CONFIG_TS72XX_MAX197_AVERAGE
++module_param(average, ushort, S_IWUSR | S_IRUGO);
++MODULE_PARM_DESC(average, "Allow average measurement (default=1)");
++#endif
++
++MODULE_AUTHOR("Matthieu Crapet <mcrapet@gmail.com>");
++MODULE_DESCRIPTION("TS-72xx max197 driver");
++MODULE_LICENSE("GPL");
++MODULE_VERSION(DRV_VERSION);
++
++module_init(ts72xx_max197_init);
++module_exit(ts72xx_max197_exit);
+--
+1.7.1
+
diff --git a/recipes/linux/linux-2.6.38/ts72xx/0014-ts7200_nor_flash.patch b/recipes/linux/linux-2.6.38/ts72xx/0014-ts7200_nor_flash.patch
new file mode 100644
index 0000000..f1930bf
--- /dev/null
+++ b/recipes/linux/linux-2.6.38/ts72xx/0014-ts7200_nor_flash.patch
@@ -0,0 +1,181 @@
+From 6189929a30b1da2589a68447f2e411611dd04dc4 Mon Sep 17 00:00:00 2001
+From: Matthieu Crapet <mcrapet@gmail.com>
+Date: Sat, 19 Jun 2010 16:56:48 +0200
+Subject: [PATCH 14/24] ts7200_nor_flash
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Deal with 8mb or 16mb NOR Flash (TS-7200 only)
+
+Signed-off-by: Petr Štetiar <ynezz@true.cz>
+---
+ drivers/mtd/maps/Kconfig | 15 +++++
+ drivers/mtd/maps/Makefile | 1 +
+ drivers/mtd/maps/ts7200_flash.c | 116 +++++++++++++++++++++++++++++++++++++++
+ 3 files changed, 132 insertions(+), 0 deletions(-)
+ create mode 100644 drivers/mtd/maps/ts7200_flash.c
+
+diff --git a/drivers/mtd/maps/Kconfig b/drivers/mtd/maps/Kconfig
+index 5d37d31..4125f75 100644
+--- a/drivers/mtd/maps/Kconfig
++++ b/drivers/mtd/maps/Kconfig
+@@ -423,6 +423,21 @@ config MTD_H720X
+ This enables access to the flash chips on the Hynix evaluation boards.
+ If you have such a board, say 'Y'.
+
++config MTD_TS7200_NOR
++ tristate "CFI Flash device mapped on TS-7200"
++ depends on MTD_CFI && MACH_TS72XX
++ help
++ This provides a map driver for the on-board flash of the Technologic
++ System's TS-7200 board. The 8MB (or 16MB) flash is splitted into 3 partitions
++ which are accessed as separate MTD devices.
++
++config MTD_TS7200_NOR_SIZE
++ int "Flash size (8 or 16mb)"
++ depends on MTD_TS7200_NOR
++ default "8"
++ help
++ Enter the NOR Flash size of your TS-7200 board. Can be 8 or 16.
++
+ # This needs CFI or JEDEC, depending on the cards found.
+ config MTD_PCI
+ tristate "PCI MTD driver"
+diff --git a/drivers/mtd/maps/Makefile b/drivers/mtd/maps/Makefile
+index c7869c7..544efa4 100644
+--- a/drivers/mtd/maps/Makefile
++++ b/drivers/mtd/maps/Makefile
+@@ -55,6 +55,7 @@ obj-$(CONFIG_MTD_DMV182) += dmv182.o
+ obj-$(CONFIG_MTD_PLATRAM) += plat-ram.o
+ obj-$(CONFIG_MTD_INTEL_VR_NOR) += intel_vr_nor.o
+ obj-$(CONFIG_MTD_BFIN_ASYNC) += bfin-async-flash.o
++obj-$(CONFIG_MTD_TS7200_NOR) += ts7200_flash.o
+ obj-$(CONFIG_MTD_RBTX4939) += rbtx4939-flash.o
+ obj-$(CONFIG_MTD_VMU) += vmu-flash.o
+ obj-$(CONFIG_MTD_GPIO_ADDR) += gpio-addr-flash.o
+diff --git a/drivers/mtd/maps/ts7200_flash.c b/drivers/mtd/maps/ts7200_flash.c
+new file mode 100644
+index 0000000..94fb4f4
+--- /dev/null
++++ b/drivers/mtd/maps/ts7200_flash.c
+@@ -0,0 +1,116 @@
++/*
++ * ts7200_flash.c - mapping for TS-7200 SBCs (8mb NOR flash)
++ * No platform_device resource is used here. All is hardcoded.
++ *
++ * (c) Copyright 2006-2010 Matthieu Crapet <mcrapet@gmail.com>
++ * Based on ts5500_flash.c by Sean Young <sean@mess.org>
++ *
++ * 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/module.h>
++#include <linux/types.h>
++#include <linux/kernel.h>
++#include <linux/init.h>
++#include <asm/io.h>
++#include <asm/sizes.h>
++#include <linux/mtd/mtd.h>
++#include <linux/mtd/map.h>
++#include <linux/mtd/partitions.h>
++#include <mach/ep93xx-regs.h>
++
++
++static struct mtd_info *mymtd;
++
++static struct map_info ts7200nor_map = {
++ .name = "Full TS-7200 NOR flash",
++ .size = 0, /* filled in later */
++ .bankwidth = 2,
++ .phys = EP93XX_CS6_PHYS_BASE,
++};
++
++/*
++ * MTD partitioning stuff
++ */
++#ifdef CONFIG_MTD_PARTITIONS
++
++#define TS7200_BOOTROM_PART_SIZE (SZ_128K)
++#define TS7200_REDBOOT_PART_SIZE (15*SZ_128K)
++
++static struct mtd_partition ts7200_nor_parts[] =
++{
++ {
++ .name = "TS-BOOTROM",
++ .offset = 0,
++ .size = TS7200_BOOTROM_PART_SIZE,
++ .mask_flags = MTD_WRITEABLE, /* force read-only */
++ },
++ {
++ .name = "RootFS",
++ .offset = MTDPART_OFS_APPEND,
++ .size = 0, /* filled in later */
++ },
++ {
++ .name = "Redboot",
++ .offset = MTDPART_OFS_APPEND,
++ .size = MTDPART_SIZ_FULL, /* up to the end */
++ }
++};
++#endif
++
++static int __init ts7200_nor_init(void)
++{
++ if (CONFIG_MTD_TS7200_NOR_SIZE <= 8)
++ ts7200nor_map.size = SZ_8M;
++ else
++ ts7200nor_map.size = SZ_16M;
++
++ printk(KERN_NOTICE "TS-7200 flash mapping: %ldmo at 0x%x\n",
++ ts7200nor_map.size / SZ_1M, ts7200nor_map.phys);
++
++ ts7200nor_map.virt = ioremap(ts7200nor_map.phys, ts7200nor_map.size - 1);
++ if (!ts7200nor_map.virt) {
++ printk("ts7200_flash: failed to ioremap\n");
++ return -EIO;
++ }
++
++ simple_map_init(&ts7200nor_map);
++ mymtd = do_map_probe("cfi_probe", &ts7200nor_map);
++ if (mymtd) {
++ mymtd->owner = THIS_MODULE;
++ add_mtd_device(mymtd);
++ #ifdef CONFIG_MTD_PARTITIONS
++ ts7200_nor_parts[1].size = ts7200nor_map.size - TS7200_REDBOOT_PART_SIZE;
++ return add_mtd_partitions(mymtd, ts7200_nor_parts, ARRAY_SIZE(ts7200_nor_parts));
++ #else
++ return 0;
++ #endif
++ }
++
++ iounmap(ts7200nor_map.virt);
++ return -ENXIO;
++}
++
++static void __exit ts7200_nor_exit(void)
++{
++ if (mymtd) {
++ del_mtd_device(mymtd);
++ map_destroy(mymtd);
++ mymtd = NULL;
++ }
++ if (ts7200nor_map.virt) {
++ iounmap(ts7200nor_map.virt);
++ ts7200nor_map.virt = 0;
++ }
++}
++
++module_init(ts7200_nor_init);
++module_exit(ts7200_nor_exit);
++
++MODULE_LICENSE("GPL");
++MODULE_AUTHOR("Matthieu Crapet <mcrapet@gmail.com>");
++MODULE_DESCRIPTION("MTD map driver for TS-7200 board");
++MODULE_VERSION("0.1");
+--
+1.7.1
+
diff --git a/recipes/linux/linux-2.6.38/ts72xx/0015-ts72xx_sdcard.patch b/recipes/linux/linux-2.6.38/ts72xx/0015-ts72xx_sdcard.patch
new file mode 100644
index 0000000..c18cccf
--- /dev/null
+++ b/recipes/linux/linux-2.6.38/ts72xx/0015-ts72xx_sdcard.patch
@@ -0,0 +1,3299 @@
+From e1251fe05f31bd0505093560a7e76769ad90905e Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Petr=20=C5=A0tetiar?= <ynezz@true.cz>
+Date: Mon, 14 Mar 2011 00:10:44 +0100
+Subject: [PATCH 15/24] ts72xx_sdcard
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+SD Card support for TS-7260. Device name is "tssda".
+Patch based on work of Breton Saunders:
+http://tech.groups.yahoo.com/group/ts-7000/message/15787
+http://tech.groups.yahoo.com/group/ts-7000/message/16028
+
+Signed-off-by: Petr Štetiar <ynezz@true.cz>
+---
+ arch/arm/mach-ep93xx/ts72xx.c | 24 +
+ drivers/block/Kconfig | 7 +
+ drivers/block/Makefile | 2 +
+ drivers/block/sdcore2.c | 2391 +++++++++++++++++++++++++++++++++++++++++
+ drivers/block/sdcore2.h | 372 +++++++
+ drivers/block/tssdcard.c | 415 +++++++
+ 6 files changed, 3211 insertions(+), 0 deletions(-)
+ create mode 100644 drivers/block/sdcore2.c
+ create mode 100644 drivers/block/sdcore2.h
+ create mode 100644 drivers/block/tssdcard.c
+
+diff --git a/arch/arm/mach-ep93xx/ts72xx.c b/arch/arm/mach-ep93xx/ts72xx.c
+index 419646a..63b2f4f 100644
+--- a/arch/arm/mach-ep93xx/ts72xx.c
++++ b/arch/arm/mach-ep93xx/ts72xx.c
+@@ -233,6 +233,29 @@ static void __init ts72xx_register_flash(void)
+ }
+
+ /*************************************************************************
++ * SD Card (TS-7260 only)
++ *************************************************************************/
++
++static struct resource ts72xx_sdcard_resource = {
++ .start = TS7260_SDCARD_PHYS_BASE,
++ .end = TS7260_SDCARD_PHYS_BASE + 0x20,
++ .flags = IORESOURCE_MEM,
++};
++
++static struct platform_device ts72xx_sdcard = {
++ .name = "ts72xx-sdcard",
++ .id = 0,
++ .num_resources = 1,
++ .resource = &ts72xx_sdcard_resource,
++};
++
++static void __init ts72xx_register_sdcard(void)
++{
++ if (board_is_ts7260() || board_is_ts7400() || board_is_ts7300())
++ platform_device_register(&ts72xx_sdcard);
++}
++
++/*************************************************************************
+ * RTC
+ *************************************************************************/
+ static unsigned char ts72xx_rtc_readbyte(unsigned long addr)
+@@ -333,6 +356,7 @@ static void __init ts72xx_init_machine(void)
+ {
+ ep93xx_init_devices();
+ ts72xx_register_flash();
++ ts72xx_register_sdcard();
+ platform_device_register(&ts72xx_rtc_device);
+ platform_device_register(&ts72xx_wdt_device);
+
+diff --git a/drivers/block/Kconfig b/drivers/block/Kconfig
+index 83c32cb..71776c9 100644
+--- a/drivers/block/Kconfig
++++ b/drivers/block/Kconfig
+@@ -506,4 +506,11 @@ config BLK_DEV_RBD
+
+ If unsure, say N.
+
++config BLK_DEV_TS72XX_SDCARD
++ tristate "TS-72XX SD Card support"
++ depends on ARCH_EP93XX && MACH_TS72XX
++ help
++ This option enables support SD Card control on Technologic Systems
++ TS-7260 SBC.
++
+ endif # BLK_DEV
+diff --git a/drivers/block/Makefile b/drivers/block/Makefile
+index 40528ba..68ff50c 100644
+--- a/drivers/block/Makefile
++++ b/drivers/block/Makefile
+@@ -34,9 +34,11 @@ obj-$(CONFIG_VIODASD) += viodasd.o
+ obj-$(CONFIG_BLK_DEV_SX8) += sx8.o
+ obj-$(CONFIG_BLK_DEV_UB) += ub.o
+ obj-$(CONFIG_BLK_DEV_HD) += hd.o
++obj-$(CONFIG_BLK_DEV_TS72XX_SDCARD) += ts72xx_sdcard.o
+
+ obj-$(CONFIG_XEN_BLKDEV_FRONTEND) += xen-blkfront.o
+ obj-$(CONFIG_BLK_DEV_DRBD) += drbd/
+ obj-$(CONFIG_BLK_DEV_RBD) += rbd.o
+
+ swim_mod-y := swim.o swim_asm.o
++ts72xx_sdcard-objs := tssdcard.o sdcore2.o
+diff --git a/drivers/block/sdcore2.c b/drivers/block/sdcore2.c
+new file mode 100644
+index 0000000..6dadee1
+--- /dev/null
++++ b/drivers/block/sdcore2.c
+@@ -0,0 +1,2391 @@
++/*
++ * Copyright (c) 2006-2009, Technologic Systems
++ * All rights reserved.
++ */
++
++/*
++ * This code is 100% operating system/CPU independent-- not a single global
++ * reference, external symbol, or #include is required. Centric upon one data
++ * structure "struct sdcore". OS-specific callbacks for things like DMA
++ * acceleration and sleeping are defined by function pointers to OS-specific
++ * code in the struct sdcore. Minimally requires the os_sleep() callback to be
++ * implemented for proper SD card initialization and a pointer to start
++ * of SD card registers. Auto-determines TS SD core version. All other
++ * callback functions may be left NULL-- they are only to allow speed/CPU
++ * utilization improvements.
++ *
++ * 3 main public functions - sdreset(), sdread() and sdwrite(). sdreset()
++ * returns card size. OS specific shim is required to turn this
++ * simple API into the complicated, constantly changing, hacker "designed"
++ * horrible excuses for abstraction, block driver APIs required in other
++ * "modern" operating systems.
++ *
++ * Not all SD cards over the years have followed spec perfectly -- many
++ * don't even check CRC's on the CMD or DAT busses and some have problems
++ * (lock up) when reading/writing the last sectors with SD read/write multiple
++ * commands.
++ *
++ * The TS SD hardware cores are not much more than GPIO bit-bang cores with
++ * a few well-placed hardware optimizations to achieve reasonable
++ * performance goals. In the roughly 2000 lines of code that follow, there
++ * is support for all distinct TS hardware SD cores on PPC and ARM platforms,
++ * a generic (private) SD command layer, sdcmd(), and SD flash card
++ * (public) routines for initialization + read/write + some SD security
++ * features.
++ *
++ */
++
++/* Register offset definitions. TS-SDCORE is 4 regs total. */
++#define SDCMD 0
++#define SDGPIO 0 /* version 2 register */
++#define SDDAT 1
++#define SDSTAT2 1
++#define SDSTATE 2
++#define SDCTRL 3
++#define SDDAT2 4
++#define SDCMD2 8
++#define SDCTRL2 12
++#define SDLUN2 2
++
++struct sdcore {
++ /* virtual address of SD block register start, to be filled in
++ * by client code before calling any sdcore functions.
++ */
++ unsigned int sd_regstart;
++
++ /* public bits for sd_state bitfield, can be read from client code.
++ * Do not write! Other bits are used internally.
++ */
++ #define SDDAT_RX (1<<0)
++ #define SDDAT_TX (1<<1)
++ #define SDCMD_RX (1<<2)
++ #define SDCMD_TX (1<<3)
++ unsigned int sd_state;
++
++ /* Erase hint for subsequent sdwrite() call, used to optimize
++ * write throughput on multi-sector writes by pre-erasing this
++ * many sectors. XXX: this doesn't have much benefit on most SDs
++ */
++ unsigned int sd_erasehint;
++
++ /* Following this comment are 3 function pointer declarations to
++ * OS helper functions. The 'os_arg' member is passed as the
++ * first argument to the helpers and should be set by
++ * client code before issueing sdreset()
++ *
++ * os_dmastream(os_arg, buf, buflen)
++ * This function should look at sd_state and set up and run an
++ * appropriate DMA transfer. If buf is NULL, callee doesn't care
++ * about the actual data sent/received and helper function
++ * can do whatever it wants. Should return 0 when DMA transfer was
++ * run and completed successfully. If this function pointer is
++ * NULL, PIO methods of transfer will be used instead of DMA.
++ *
++ * os_dmaprep(os_arg, buf, buflen)
++ * This function is used to prepare an area of memory for a possible
++ * DMA transfer. This function is called once per distinct buffer
++ * passed in. After this function is called, os_dmastream() may be
++ * called one or more times (for sequential addresses) on subregions
++ * of the address range passed here. Should write-back or invalidate
++ * L1 cache lines and possibly look up physical addresses for buf
++ * passed in if I/O buffers. If 'os_dmaprep' is set to NULL, function
++ * call will not happen. (though os_dmastream() calls may still)
++ *
++ * os_delay(os_arg, microseconds)
++ * This function is supposed to delay or stall the processor for
++ * the passed in value number of microseconds.
++ */
++ void *os_arg;
++ int (*os_dmastream)(void *, unsigned char *, unsigned int);
++ void (*os_dmaprep)(void *, unsigned char *, unsigned int);
++ void (*os_delay)(void *, unsigned int);
++ void (*os_irqwait)(void *, unsigned int);
++ int (*os_powerok)(void *);
++ int (*os_timeout)(void *);
++ int (*os_reset_timeout)(void *);
++
++ /* If the SD card last successfully reset is write protected, this
++ * member will be non-zero.
++ */
++ unsigned int sd_wprot;
++
++ /* If this card may have been already initialized by TS-SDBOOT, place
++ * the magic token it placed in the EP93xx SYSCON ScratchReg1 here
++ * to avoid re-initialization.
++ */
++ unsigned int sdboot_token;
++
++ /* CRC hint for subsequent sdwrite() call, used to optimize
++ * write throughput while using DMA by pre-calculating CRC's for
++ * next write
++ */
++ unsigned char *sd_crchint;
++
++ /* The block size of the memory device. Normally 512, but can be 1024
++ * for larger cards
++ */
++ unsigned int sd_blocksize;
++
++ /* Password for auto-unlocking in sdreset()
++ */
++ unsigned char *sd_pwd;
++
++ /* If the SD card was password locked, this will be non-zero.
++ */
++ unsigned int sd_locked;
++
++ /* Whether or not writes can be parked.
++ */
++ unsigned int sd_writeparking;
++
++ /* Logical unit number. Some SD cores will have multiple card slots.
++ */
++ unsigned int sd_lun;
++
++ /* The rest of these members are for private internal use and should
++ * not be of interest to client code.
++ */
++ unsigned int sd_rcaarg;
++ unsigned int sd_csd[17];
++ unsigned int sd_crcseq;
++ unsigned short sd_crcs[4];
++ unsigned int sd_crctmp[4];
++ unsigned int sd_timeout;
++ unsigned int parked_sector;
++ unsigned int hw_version;
++ unsigned char sd_scr[8];
++ unsigned int sd_sz;
++};
++
++/* For sdreadv() / sdwritev() */
++struct sdiov {
++ unsigned char *sdiov_base;
++ unsigned int sdiov_nsect;
++};
++
++int sdreset(struct sdcore *);
++int sdread(struct sdcore *, unsigned int, unsigned char *, int);
++int sdwrite(struct sdcore *, unsigned int, unsigned char *, int);
++int sdreadv(struct sdcore *, unsigned int, struct sdiov *, int);
++int sdwritev(struct sdcore *, unsigned int, struct sdiov *, int);
++int sdsetwprot(struct sdcore *, unsigned int);
++#define SDLOCK_UNLOCK 0
++#define SDLOCK_SETPWD 1
++#define SDLOCK_CLRPWD 2
++#define SDLOCK_ERASE 8
++#ifndef SD_NOLOCKSUPPORT
++int sdlockctl(struct sdcore *, unsigned int, unsigned char *, unsigned char *);
++#endif
++
++/*
++ * Everything below here is secret! This code shouldn't have to change
++ * even for different OS.
++ */
++
++const static unsigned short crc16tbl[256] = {
++ 0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7,
++ 0x8108, 0x9129, 0xa14a, 0xb16b, 0xc18c, 0xd1ad, 0xe1ce, 0xf1ef,
++ 0x1231, 0x0210, 0x3273, 0x2252, 0x52b5, 0x4294, 0x72f7, 0x62d6,
++ 0x9339, 0x8318, 0xb37b, 0xa35a, 0xd3bd, 0xc39c, 0xf3ff, 0xe3de,
++ 0x2462, 0x3443, 0x0420, 0x1401, 0x64e6, 0x74c7, 0x44a4, 0x5485,
++ 0xa56a, 0xb54b, 0x8528, 0x9509, 0xe5ee, 0xf5cf, 0xc5ac, 0xd58d,
++ 0x3653, 0x2672, 0x1611, 0x0630, 0x76d7, 0x66f6, 0x5695, 0x46b4,
++ 0xb75b, 0xa77a, 0x9719, 0x8738, 0xf7df, 0xe7fe, 0xd79d, 0xc7bc,
++ 0x48c4, 0x58e5, 0x6886, 0x78a7, 0x0840, 0x1861, 0x2802, 0x3823,
++ 0xc9cc, 0xd9ed, 0xe98e, 0xf9af, 0x8948, 0x9969, 0xa90a, 0xb92b,
++ 0x5af5, 0x4ad4, 0x7ab7, 0x6a96, 0x1a71, 0x0a50, 0x3a33, 0x2a12,
++ 0xdbfd, 0xcbdc, 0xfbbf, 0xeb9e, 0x9b79, 0x8b58, 0xbb3b, 0xab1a,
++ 0x6ca6, 0x7c87, 0x4ce4, 0x5cc5, 0x2c22, 0x3c03, 0x0c60, 0x1c41,
++ 0xedae, 0xfd8f, 0xcdec, 0xddcd, 0xad2a, 0xbd0b, 0x8d68, 0x9d49,
++ 0x7e97, 0x6eb6, 0x5ed5, 0x4ef4, 0x3e13, 0x2e32, 0x1e51, 0x0e70,
++ 0xff9f, 0xefbe, 0xdfdd, 0xcffc, 0xbf1b, 0xaf3a, 0x9f59, 0x8f78,
++ 0x9188, 0x81a9, 0xb1ca, 0xa1eb, 0xd10c, 0xc12d, 0xf14e, 0xe16f,
++ 0x1080, 0x00a1, 0x30c2, 0x20e3, 0x5004, 0x4025, 0x7046, 0x6067,
++ 0x83b9, 0x9398, 0xa3fb, 0xb3da, 0xc33d, 0xd31c, 0xe37f, 0xf35e,
++ 0x02b1, 0x1290, 0x22f3, 0x32d2, 0x4235, 0x5214, 0x6277, 0x7256,
++ 0xb5ea, 0xa5cb, 0x95a8, 0x8589, 0xf56e, 0xe54f, 0xd52c, 0xc50d,
++ 0x34e2, 0x24c3, 0x14a0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405,
++ 0xa7db, 0xb7fa, 0x8799, 0x97b8, 0xe75f, 0xf77e, 0xc71d, 0xd73c,
++ 0x26d3, 0x36f2, 0x0691, 0x16b0, 0x6657, 0x7676, 0x4615, 0x5634,
++ 0xd94c, 0xc96d, 0xf90e, 0xe92f, 0x99c8, 0x89e9, 0xb98a, 0xa9ab,
++ 0x5844, 0x4865, 0x7806, 0x6827, 0x18c0, 0x08e1, 0x3882, 0x28a3,
++ 0xcb7d, 0xdb5c, 0xeb3f, 0xfb1e, 0x8bf9, 0x9bd8, 0xabbb, 0xbb9a,
++ 0x4a75, 0x5a54, 0x6a37, 0x7a16, 0x0af1, 0x1ad0, 0x2ab3, 0x3a92,
++ 0xfd2e, 0xed0f, 0xdd6c, 0xcd4d, 0xbdaa, 0xad8b, 0x9de8, 0x8dc9,
++ 0x7c26, 0x6c07, 0x5c64, 0x4c45, 0x3ca2, 0x2c83, 0x1ce0, 0x0cc1,
++ 0xef1f, 0xff3e, 0xcf5d, 0xdf7c, 0xaf9b, 0xbfba, 0x8fd9, 0x9ff8,
++ 0x6e17, 0x7e36, 0x4e55, 0x5e74, 0x2e93, 0x3eb2, 0x0ed1, 0x1ef0,
++};
++
++const static unsigned char destagger[256] = {
++ 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1,
++ 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3,
++ 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1,
++ 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3,
++ 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1,
++ 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3,
++ 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1,
++ 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3,
++ 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1,
++ 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3,
++ 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1,
++ 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3,
++ 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1,
++ 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3,
++ 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1,
++ 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3,
++};
++
++#ifndef MAX_SDCORES
++#define MAX_SDCORES 64
++#endif
++static struct sdcore *sdcores[MAX_SDCORES];
++
++static unsigned int crc7(unsigned int, const unsigned int *, unsigned int);
++static int sdreset2(struct sdcore *);
++static int version(struct sdcore *);
++static int sdfastinit(struct sdcore *sd);
++static int sdcmd2(struct sdcore *, unsigned short, unsigned int,
++ unsigned int *, unsigned char **);
++static int sdcmd(struct sdcore *, unsigned short, unsigned int,
++ unsigned int *, unsigned char **);
++static void mkcommand(unsigned int, unsigned int, unsigned int *);
++static int stop(struct sdcore *);
++static int stop2(struct sdcore *);
++static int sdread2(struct sdcore *, unsigned int, unsigned char *, int)
++ __attribute__ ((unused));
++static int do_read2(struct sdcore *, unsigned int, struct sdiov *,
++ unsigned int);
++static int do_read(struct sdcore *, unsigned int, struct sdiov *,
++ unsigned int);
++static int do_write(struct sdcore *, unsigned int, struct sdiov *,
++ unsigned int);
++static int do_write2(struct sdcore *, unsigned int, struct sdiov *,
++ unsigned int);
++static int sdsetwprot2(struct sdcore *, unsigned int);
++#ifndef SD_NOLOCKSUPPORT
++static int sdlockctl2(struct sdcore *, unsigned int, unsigned char *,
++ unsigned char *);
++#endif
++
++#ifndef SDPOKE8
++# define SDPOKE8(sd, x, y) \
++ *(volatile unsigned char *)((sd)->sd_regstart + (x)) = (y)
++#endif
++#ifndef SDPOKE32
++# define SDPOKE32(sd, x, y) \
++ *(volatile unsigned int *)((sd)->sd_regstart + (x)) = (y)
++#endif
++#ifndef SDPOKE16
++# define SDPOKE16(sd, x, y) \
++ *(volatile unsigned short *)((sd)->sd_regstart + (x)) = (y)
++#endif
++#ifndef SDPEEK8
++# define SDPEEK8(sd, x) *(volatile unsigned char *)((sd)->sd_regstart + (x))
++#endif
++#ifndef SDPEEK32
++# define SDPEEK32(sd, x) *(volatile unsigned int *)((sd)->sd_regstart + (x))
++#endif
++#ifndef SDPEEK16
++# define SDPEEK16(sd, x) *(volatile unsigned short *)((sd)->sd_regstart + (x))
++#endif
++
++#define S_DUMMY_CLK 0
++#define S_SEND_CMD 1
++#define S_WAIT_RESP 2
++#define S_RX_RESP 3
++#define S_WAIT_BUSY 4
++#define S_TX_WRITE 5
++#define S_CRC_CHECK 6
++#define S_OFF 7
++
++#define TYPE_SHORTRESP 2
++#define TYPE_LONGRESP 3
++#define TYPE_BSYRESP 4
++#define TYPE_NORESP 1
++#define TYPE_RXDAT 0
++#define TYPE_TXDAT 5
++#define TYPE_ABORT 6
++#define TYPE_RXDAT_IGNRESP 7
++
++#define CMD(idx, type) (0x40 | (idx) | ((type)<<8))
++
++#define CMD_GO_IDLE_STATE CMD(0, TYPE_NORESP)
++#define CMD_ALL_SEND_CID CMD(2, TYPE_LONGRESP)
++#define CMD_SEND_RELATIVE_ADDR CMD(3, TYPE_SHORTRESP)
++#define CMD_SWITCH_FUNC CMD(6, TYPE_RXDAT)
++#define CMD_SWITCH_FUNC2 CMD(6, TYPE_RXDAT_IGNRESP)
++#define CMD_SELECT_CARD CMD(7, TYPE_BSYRESP)
++#define CMD_DESELECT_CARD CMD(7, TYPE_NORESP)
++#define CMD_SEND_IF_COND CMD(8, TYPE_SHORTRESP)
++#define CMD_SEND_CSD CMD(9, TYPE_LONGRESP)
++#define CMD_PROGRAM_CSD CMD(27, TYPE_TXDAT)
++#define CMD_SET_BLOCKLEN CMD(16, TYPE_SHORTRESP)
++#define CMD_LOCK_UNLOCK CMD(42, TYPE_TXDAT)
++#define CMD_APP_CMD CMD(55, TYPE_SHORTRESP)
++#define CMD_READ_SINGLE_BLOCK CMD(17, TYPE_RXDAT)
++#define CMD_READ_MULTIPLE_BLOCK CMD(18, TYPE_RXDAT)
++#define CMD_READ_MULTIPLE_BLOCK2 CMD(18, TYPE_RXDAT_IGNRESP)
++#define CMD_STOP_TRANSMISSION CMD(12, TYPE_ABORT)
++#define CMD_SEND_STATUS CMD(13, TYPE_SHORTRESP)
++#define CMD_WRITE_BLOCK CMD(24, TYPE_TXDAT)
++#define CMD_WRITE_MULTIPLE_BLOCK CMD(25, TYPE_TXDAT)
++
++#define ACMD_SD_SEND_OP_COND CMD(41, TYPE_SHORTRESP)
++#define ACMD_SET_CLR_CARD_DETECT CMD(42, TYPE_SHORTRESP)
++#define ACMD_SET_BUS_WIDTH CMD(6, TYPE_SHORTRESP)
++#define ACMD_SET_WR_BLK_ERASE_COUNT CMD(23, TYPE_SHORTRESP)
++#define ACMD_SEND_NUM_WR_BLOCKS CMD(22, TYPE_RXDAT)
++#define ACMD_SEND_SCR CMD(51, TYPE_RXDAT)
++#define ACMD_SEND_SCR2 CMD(51, TYPE_RXDAT_IGNRESP)
++
++/* Private bits for struct sdcore, sd_state member */
++#define DATSSP_NOCRC (1<<4)
++#define DATSSP_4BIT (1<<5)
++#define SD_HC (1<<6)
++#define SD_HISPEED (1<<7)
++#define SD_LOSPEED (1<<8)
++#define SD_SELECTED (1<<9)
++#define SD_RESET (1<<10)
++
++#define NULL ((void *)0)
++
++static void remember_sdcore(struct sdcore *sd) {
++ int i, newlun = 0;
++
++ for (i = 0; i < sizeof(sdcores); i++) {
++ if (sdcores[i] == NULL) {
++ /* new core, first reset */
++ sdcores[i] = sd;
++ /* core was almost definitely power-cycled on prev lun
++ * sdreset2(), so we don't need to have the sdreset2()
++ * do it again.
++ */
++ if (newlun) sd->sd_state = SD_RESET;
++ break;
++ } else if (sdcores[i]->sd_regstart == sd->sd_regstart) {
++ newlun = 1;
++ if (sdcores[i]->sd_lun == sd->sd_lun) {
++ sdcores[i] = sd;
++ break;
++ }
++ }
++ }
++}
++
++static int activate(struct sdcore *sd) {
++ int i;
++
++ /* Are we already selected? */
++ if ((sd->sd_state & (SD_SELECTED|SD_RESET)) == SD_SELECTED)
++ return 0;
++
++ /* Find currently activated SD slot for this HW core */
++ for (i = 0; i < sizeof(sdcores); i++) {
++ if (sdcores[i] == NULL) break;
++ if (sdcores[i]->sd_regstart == sd->sd_regstart &&
++ sdcores[i]->sd_state & SD_SELECTED) break;
++ }
++
++ /* Stop whatever parked transfer it has going on. */
++ if (sdcores[i]) {
++ stop2(sdcores[i]);
++ sdcores[i]->sd_state &= ~SD_SELECTED;
++ }
++
++ /* Change clock routing, mark us as selected */
++#ifdef BIGENDIAN
++ SDPOKE16(sd, SDLUN2, sd->sd_lun << 8);
++#else
++ SDPOKE16(sd, SDLUN2, sd->sd_lun);
++#endif
++
++ /* Change clock frequency */
++ if (sd->sd_state & SD_HISPEED) SDPOKE8(sd, SDSTAT2, 0x38);
++ else SDPOKE8(sd, SDSTAT2, 0x18);
++
++ sd->sd_state |= SD_SELECTED;
++ if (sd->sd_state & SD_RESET) return 1;
++ else return 0;
++
++}
++
++inline static unsigned short
++crc16_acc(unsigned short crc, unsigned int b)
++{
++ return (crc << 8) ^ crc16tbl[(crc >> 8) ^ b];
++}
++
++static void sd_initcrc(struct sdcore *sd)
++{
++ int i;
++
++ for (i = 0; i < 4; i++) {
++ sd->sd_crctmp[i] = 0;
++ sd->sd_crcs[i] = 0;
++ }
++ sd->sd_crcseq = 6;
++}
++
++static void sd_1bit_feedcrc(struct sdcore *sd, unsigned int dat)
++{
++ sd->sd_crcs[0] = crc16_acc(sd->sd_crcs[0], dat);
++}
++
++static void sd_4bit_feedcrc(struct sdcore *sd, unsigned int dat)
++{
++ unsigned int a = 0, b = 0, c = 0, d = 0;
++ unsigned int shift = (sd->sd_crcseq & 0x7);
++
++ a = sd->sd_crctmp[0];
++ b = sd->sd_crctmp[1];
++ c = sd->sd_crctmp[2];
++ d = sd->sd_crctmp[3];
++
++ a |= destagger[dat] << shift;
++ dat >>= 1;
++ b |= destagger[dat] << shift;
++ dat >>= 1;
++ c |= destagger[dat] << shift;
++ dat >>= 1;
++ d |= destagger[dat] << shift;
++
++ if (shift == 0) {
++ sd->sd_crcs[0] = crc16_acc(sd->sd_crcs[0], a);
++ sd->sd_crcs[1] = crc16_acc(sd->sd_crcs[1], b);
++ sd->sd_crcs[2] = crc16_acc(sd->sd_crcs[2], c);
++ sd->sd_crcs[3] = crc16_acc(sd->sd_crcs[3], d);
++ a = b = c = d = 0;
++ }
++
++ sd->sd_crcseq -= 2;
++ sd->sd_crctmp[0] = a;
++ sd->sd_crctmp[1] = b;
++ sd->sd_crctmp[2] = c;
++ sd->sd_crctmp[3] = d;
++}
++
++/* This should be called 8 times to get the full 8 bytes of CRC generated */
++static unsigned int sd_4bit_getcrc(struct sdcore *sd)
++{
++ static const unsigned char restaggertbl[4] = { 0x0, 0x1, 0x10, 0x11 };
++ static const unsigned char restaggertbl_lsl1[4] =
++ { 0x0, 0x2, 0x20, 0x22 };
++ static const unsigned char restaggertbl_lsl2[4] =
++ { 0x0, 0x4, 0x40, 0x44 };
++ static const unsigned char restaggertbl_lsl3[4] =
++ { 0x0, 0x8, 0x80, 0x88 };
++ unsigned int ret;
++
++ ret = restaggertbl[sd->sd_crcs[0] >> 14];
++ sd->sd_crcs[0] <<= 2;
++ ret |= restaggertbl_lsl1[sd->sd_crcs[1] >> 14];
++ sd->sd_crcs[1] <<= 2;
++ ret |= restaggertbl_lsl2[sd->sd_crcs[2] >> 14];
++ sd->sd_crcs[2] <<= 2;
++ ret |= restaggertbl_lsl3[sd->sd_crcs[3] >> 14];
++ sd->sd_crcs[3] <<= 2;
++
++ return ret;
++}
++
++/* This should be called 2 times to get the full 2 bytes of CRC generated */
++static unsigned int sd_1bit_getcrc(struct sdcore *sd)
++{
++ unsigned int ret;
++
++ ret = sd->sd_crcs[0] >> 8;
++ sd->sd_crcs[0] = (sd->sd_crcs[0] & 0xff) << 8;
++ return ret;
++}
++
++static inline void datssp_feedcrc(struct sdcore *sd, unsigned int dat)
++{
++ if (!(sd->sd_state & DATSSP_NOCRC)) {
++ if (sd->sd_state & DATSSP_4BIT) sd_4bit_feedcrc(sd, dat);
++ else sd_1bit_feedcrc(sd, dat);
++ }
++}
++
++static inline unsigned int datssp_getcrc(struct sdcore *sd)
++{
++ unsigned int ret = 0;
++
++ if (!(sd->sd_state & DATSSP_NOCRC)) {
++ if (sd->sd_state & DATSSP_4BIT) ret = sd_4bit_getcrc(sd);
++ else ret = sd_1bit_getcrc(sd);
++ }
++ return ret;
++}
++
++static inline unsigned int
++crc7(unsigned int crc, const unsigned int *pc, unsigned int len)
++{
++ unsigned int i;
++ unsigned char ibit;
++ unsigned char c;
++
++ for (i = 0; i < len; i++, pc++) {
++ c = *pc;
++ for (ibit = 0; ibit < 8; ibit++) {
++ crc <<= 1;
++ if ((c ^ crc) & 0x80) crc ^= 0x09;
++
++ c <<= 1;
++ }
++
++ crc &= 0x7F;
++ }
++
++ return crc;
++}
++
++static inline void
++mkcommand(unsigned int cmdidx, unsigned int arg, unsigned int *retcmd)
++{
++ retcmd[0] = cmdidx;
++ retcmd[1] = arg >> 24;
++ retcmd[2] = arg >> 16;
++ retcmd[3] = arg >> 8;
++ retcmd[4] = arg;
++ retcmd[5] = (0x1 | (crc7(0, retcmd, 5) << 1));
++}
++
++static inline void reset_timeout(struct sdcore *sd) {
++ sd->sd_timeout = 0;
++ if (sd->os_reset_timeout) sd->os_reset_timeout(sd);
++}
++
++static inline int timeout(struct sdcore *sd) {
++ if (sd->sd_timeout > 1000000) return 1;
++ else if (sd->os_timeout) return sd->os_timeout(sd);
++ else sd->sd_timeout++;
++ return 0;
++}
++
++static
++unsigned int sdsize(struct sdcore *sd)
++{
++ unsigned int csize, csize_mult, rd_bl_len;
++
++ if (sd->sd_sz != 0) return sd->sd_sz;
++
++ if (sd->sd_csd[1] & 0xc0) {
++ csize = (sd->sd_csd[10] | (sd->sd_csd[9] << 8));
++ sd->sd_sz = (csize + 1) * 1024;
++ } else {
++ rd_bl_len = 1 << ((sd->sd_csd[6] & 0xf) - 9);
++ csize = ((sd->sd_csd[7] & 0x03) << 10) |
++ ((sd->sd_csd[8] << 2) | ((sd->sd_csd[9] & 0xc0) >> 6));
++ csize_mult = ((sd->sd_csd[10] & 0x03) << 1) |
++ ((sd->sd_csd[11] & 0x80) >> 7);
++ sd->sd_sz = (csize + 1) * (1 << (csize_mult + 2)) * rd_bl_len;
++ }
++ return sd->sd_sz;
++}
++
++static unsigned int tend_ssp(struct sdcore *sd, unsigned int **cmdresp,
++ unsigned char **dat) {
++ unsigned int d;
++ unsigned int s = SDPEEK8(sd, SDSTATE);
++
++ if (s & 0x8) {
++ if (sd->sd_state & SDCMD_RX) {
++ d = SDPEEK8(sd, SDCMD);
++ if (cmdresp) {
++ **cmdresp = d;
++ *cmdresp = *cmdresp + 1;
++ reset_timeout(sd);
++ }
++ } else if (sd->sd_state & SDCMD_TX) {
++ SDPOKE8(sd, SDCMD, **cmdresp);
++ *cmdresp = *cmdresp + 1;
++ reset_timeout(sd);
++ }
++ }
++
++ if (s & 0x10) {
++ if (sd->sd_state & SDDAT_RX) {
++ d = SDPEEK8(sd, SDDAT);
++ if (dat) {
++ **dat = d;
++ *dat = *dat + 1;
++ reset_timeout(sd);
++ }
++ } else if (sd->sd_state & SDDAT_TX) {
++ reset_timeout(sd);
++ if (dat) {
++ d = **dat;
++ *dat = *dat + 1;
++ SDPOKE8(sd, SDDAT, d);
++ datssp_feedcrc(sd, d);
++ } else {
++ d = datssp_getcrc(sd);
++ SDPOKE8(sd, SDDAT, d);
++ }
++ }
++ }
++
++ return s;
++}
++
++static int
++error(unsigned int *resp, unsigned short req)
++{
++ unsigned int crc, status;
++
++ if ((req & 0x3f) != resp[0]) return 1;
++
++ crc = (0x1 | (crc7(0, resp, 5) << 1));
++ if (crc != resp[5]) return 1;
++
++ status = resp[1] << 24;
++ status |= resp[2] << 16;
++ status |= resp[3] << 8;
++ status |= resp[4];
++
++ return status & 0xfdf90008;
++}
++
++static int
++sdcmd2(struct sdcore *sd, unsigned short req, unsigned int arg,
++ unsigned int *resp, unsigned char **dat)
++{
++ unsigned int i, j, s, cmdresp[17];
++ unsigned int resplen;
++ unsigned int type = (req >> 8);
++ unsigned int cmdidx = req;
++ unsigned int *cmdptr = cmdresp;
++ unsigned int *respptr;
++ unsigned int dly;
++ int ok32 = (sd->hw_version == 2);
++ int ok16 = (ok32 || (sd->hw_version == 3));
++ int sddat2_8;
++
++ // If no space for response provided by caller, use local buffer
++ if (resp == NULL) resp = cmdresp;
++ respptr = resp;
++
++ if (activate(sd)) return 1;
++
++ dly = sd->sd_state & SD_LOSPEED;
++
++ if (!dly) {
++ unsigned int x;
++ SDPOKE8(sd, SDGPIO, 0xbf);
++#ifdef BIGENDIAN
++ x = (cmdidx & 0xff);
++ x |= ((arg >> 24) & 0xff) << 8;
++ x |= ((arg >> 16) & 0xff) << 16;
++ x |= ((arg >> 8) & 0xff) << 24;
++ if (ok32) SDPOKE32(sd, SDCMD2, x);
++ else if (ok16) {
++ SDPOKE16(sd, SDCMD2, x);
++ SDPOKE16(sd, SDCMD2, x >> 16);
++ } else {
++ SDPOKE8(sd, SDCMD2, x);
++ SDPOKE8(sd, SDCMD2, x >> 8);
++ SDPOKE8(sd, SDCMD2, x >> 16);
++ SDPOKE8(sd, SDCMD2, x >> 24);
++ }
++#else
++ x = (cmdidx & 0xff) << 24;
++ x |= ((arg >> 24) & 0xff) << 16;
++ x |= ((arg >> 16) & 0xff) << 8;
++ x |= ((arg >> 8) & 0xff);
++ if (ok32) SDPOKE32(sd, SDCMD2, x);
++ else if (ok16) {
++ SDPOKE16(sd, SDCMD2, x >> 16);
++ SDPOKE16(sd, SDCMD2, x);
++ } else {
++ SDPOKE8(sd, SDCMD2, x >> 24);
++ SDPOKE8(sd, SDCMD2, x >> 16);
++ SDPOKE8(sd, SDCMD2, x >> 8);
++ SDPOKE8(sd, SDCMD2, x);
++ }
++#endif
++ SDPOKE8(sd, SDCMD2, arg);
++ } else {
++ // Build command packet
++ mkcommand(cmdidx, arg, cmdptr);
++
++ // Send command
++ for (i = 0; i < 6; i++) {
++ unsigned int b = *cmdptr++;
++ unsigned int x;
++
++ if (timeout(sd)) break;
++ for (j = 0; j < 8; j++) {
++ x = 0x8f | ((b & 0x80) >> 3);
++ b = b << 1;
++ SDPOKE8(sd, SDGPIO, x); // clk negedge
++ SDPEEK8(sd, SDGPIO); // delay
++ SDPEEK8(sd, SDGPIO); // delay
++ x |= 0x20;
++ SDPOKE8(sd, SDGPIO, x); // clk posedge
++ SDPEEK8(sd, SDGPIO); // delay
++ SDPEEK8(sd, SDGPIO); // delay
++ }
++ }
++ }
++
++ if (type == TYPE_NORESP) goto done;
++ else if (type == TYPE_RXDAT_IGNRESP) goto ignresp;
++ else if (type == TYPE_LONGRESP) resplen = 17;
++ else resplen = 6;
++
++ // clock until start bit on CMD pin
++ while(1) {
++ if (timeout(sd)) {
++ goto done;
++ }
++ if (req == CMD_SEND_IF_COND) sd->sd_timeout += 100000;
++ SDPOKE8(sd, SDGPIO, 0xdf); // clk negedge
++ if (dly) SDPEEK8(sd, SDGPIO); // delay
++ s = SDPEEK8(sd, SDGPIO); // sample
++ if ((s & 0x10) == 0x0) break;
++ SDPOKE8(sd, SDGPIO, 0xff); // clk posedge
++ if (dly) SDPEEK8(sd, SDGPIO); // delay
++ }
++ reset_timeout(sd);
++
++ // Next we receive the response.
++ if (ok16 && !ok32) sddat2_8 = SDDAT2 + 1;
++ else sddat2_8 = SDDAT2;
++ if (dly) for (i = 0; i < resplen; i++) {
++ unsigned int r = 0;
++
++ for (j = 0; j < 8; j++) {
++ SDPOKE8(sd, SDGPIO, 0xdf); // clk negedge
++ SDPEEK8(sd, SDGPIO); // delay
++ s = SDPEEK8(sd, SDGPIO); // sample
++ SDPOKE8(sd, SDGPIO, 0xff); // clk posedge
++ SDPEEK8(sd, SDGPIO); // delay
++ SDPEEK8(sd, SDGPIO); // delay
++ r = r << 1;
++ r |= ((s & 0x10) >> 4);
++ }
++
++ *respptr++ = r;
++ } else while (resplen > 0) {
++ unsigned int r;
++
++#ifdef BIGENDIAN
++ if (ok32 && resplen >= 4) {
++ r = SDPEEK32(sd, SDCMD2);
++ *respptr++ = r & 0xff;
++ *respptr++ = (r >> 8) & 0xff;
++ *respptr++ = (r >> 16) & 0xff;
++ *respptr++ = (r >> 24);
++ resplen -= 4;
++ } else if (ok16 && resplen >= 2) {
++ r = SDPEEK16(sd, SDCMD2);
++ *respptr++ = r & 0xff;
++ *respptr++ = (r >> 8) & 0xff;
++
++ resplen -= 2;
++ } else {
++ *respptr++ = SDPEEK8(sd, sddat2_8);
++ resplen--;
++ }
++#else
++ if (ok32 && resplen >= 4) {
++ r = SDPEEK32(sd, SDCMD2);
++ *respptr++ = (r >> 24);
++ *respptr++ = (r >> 16) & 0xff;
++ *respptr++ = (r >> 8) & 0xff;
++ *respptr++ = r & 0xff;
++ resplen -= 4;
++ } else if (ok16 && resplen >= 2) {
++ r = SDPEEK16(sd, SDCMD2);
++ *respptr++ = (r >> 8) & 0xff;
++ *respptr++ = r & 0xff;
++ resplen -= 2;
++ } else {
++ *respptr++ = SDPEEK8(sd, sddat2_8);
++ resplen--;
++ }
++#endif
++ }
++ if (type == TYPE_BSYRESP) {
++ s = 0;
++ while ((s & 0x7) != 0x7) {
++ if (timeout(sd)) break;
++ SDPOKE8(sd, SDGPIO, 0x9f); // clk negedge
++ if (dly) SDPEEK8(sd, SDGPIO); // delay
++ s = s << 1;
++ s |= SDPEEK8(sd, SDGPIO) & 0x1;
++ SDPOKE8(sd, SDGPIO, 0xbf);
++ if (dly) SDPEEK8(sd, SDGPIO);
++ }
++ }
++
++ignresp:
++
++ if (type == TYPE_ABORT)
++ sd->sd_state &= ~(SDDAT_RX|SDDAT_TX);
++
++#ifndef SD_READONLYDMA
++ if (type == TYPE_TXDAT) {
++ sd->sd_state |= SDDAT_TX;
++ /* 2 clocks for nWR */
++ SDPOKE8(sd, SDGPIO, 0xdf); // clk negedge
++ if (dly) SDPEEK8(sd, SDGPIO); // delay
++ if (dly) SDPEEK8(sd, SDGPIO); // delay
++ SDPOKE8(sd, SDGPIO, 0xff); // clk posedge
++ if (dly) SDPEEK8(sd, SDGPIO); // delay
++ if (dly) SDPEEK8(sd, SDGPIO); // delay
++ SDPOKE8(sd, SDGPIO, 0xdf); // clk negedge
++ if (dly) SDPEEK8(sd, SDGPIO); // delay
++ if (dly) SDPEEK8(sd, SDGPIO); // delay
++ SDPOKE8(sd, SDGPIO, 0xff); // clk posedge
++ if (dly) SDPEEK8(sd, SDGPIO); // delay
++ if (dly) SDPEEK8(sd, SDGPIO); // delay
++ if (sd->sd_state & DATSSP_4BIT)
++ SDPOKE8(sd, SDGPIO, 0x10); // assert start, clk negedge
++ else
++ SDPOKE8(sd, SDGPIO, 0x1e);
++ if (dly) SDPEEK8(sd, SDGPIO); // delay
++ if (dly) SDPEEK8(sd, SDGPIO); // delay
++ if (sd->sd_state & DATSSP_4BIT)
++ SDPOKE8(sd, SDGPIO, 0x30); // clk posedge
++ else
++ SDPOKE8(sd, SDGPIO, 0x3e);
++ if (dly) SDPEEK8(sd, SDGPIO); // delay
++ if (dly) SDPEEK8(sd, SDGPIO); // delay
++ }
++#endif
++
++ if (type == TYPE_RXDAT || type == TYPE_RXDAT_IGNRESP)
++ sd->sd_state |= SDDAT_RX;
++
++done:
++ // 8 clocks before stopping
++ if (!(sd->sd_state & (SDDAT_TX|SDDAT_RX))) {
++ if (dly) for (i = 0; i < 8; i++) {
++ SDPOKE8(sd, SDGPIO, 0xdf);
++ SDPEEK8(sd, SDGPIO); // delay
++ SDPEEK8(sd, SDGPIO); // delay
++ SDPOKE8(sd, SDGPIO, 0xff);
++ SDPEEK8(sd, SDGPIO); // delay
++ SDPEEK8(sd, SDGPIO); // delay
++ } else {
++ SDPOKE8(sd, SDGPIO, 0xff);
++ SDPOKE8(sd, SDCMD2, 0xff);
++ }
++ }
++ if (timeout(sd)) return 1;
++ else return 0;
++
++}
++
++
++static int
++sdcmd(struct sdcore *sd, unsigned short req, unsigned int arg,
++ unsigned int *resp, unsigned char **dat)
++{
++ unsigned int s, cmdresp[17];
++ unsigned int resplen;
++ unsigned int type = (req >> 8);
++ unsigned int cmdidx = req;
++ unsigned int *cmdptr = cmdresp;
++ unsigned int *cmd = cmdresp;
++ unsigned int *respptr;
++ unsigned int ndat;
++
++ if (sd->hw_version != 0) return sdcmd2(sd, req, arg, resp, dat);
++
++ // If no space for response provided by caller, use local buffer
++ if (resp == NULL) resp = cmdresp;
++ respptr = resp;
++
++ // Before continuing, we must wait for the FSM to get to the
++ // S_SEND_CMD state. After a previous command, we may still be
++ // in S_DUMMY_CLK or in case of an ABORT, we may be in the middle of
++ // clocking a byte for TX or RX.
++ s = SDPEEK8(sd, SDSTATE);
++ while ((s & 0x7) != S_SEND_CMD) {
++ if (timeout(sd)) break;
++ s = SDPEEK8(sd, SDSTATE);
++ }
++
++ // We know we're in S_SEND_CMD, but we may need to change the
++ // command type. This won't cause a state change.
++ if ((s & 0xe7) != (S_SEND_CMD | (type << 5)))
++ SDPOKE8(sd, SDSTATE, S_SEND_CMD | (type << 5));
++
++ // Build command packet
++ mkcommand(cmdidx, arg, cmdptr);
++
++ // Next, we loop while tending the SSPs until we get our last
++ // byte of command data out. We may get a few bytes from the DAT
++ // SSP if we are aborting a previous data transfer command. If we do
++ // those get placed in a buffer or thrown away based on the callers
++ // "dat" parameter.
++ sd->sd_state |= SDCMD_TX;
++ while ((cmdptr - cmd) != 6) {
++ if (timeout(sd)) break;
++ s = tend_ssp(sd, &cmdptr, dat);
++ }
++ sd->sd_state &= ~SDCMD_TX;
++
++ // If we got out of sync with the hardware, that would be bad.
++ // The hardware should still be in S_SEND_CMD for the last CMDSSP
++ // byte.
++ if ((s & 0x7) != S_SEND_CMD) {
++ SDPOKE8(sd, SDSTATE, S_OFF);
++ return 1;
++ }
++
++ if (type == TYPE_NORESP) goto done;
++ else if (type == TYPE_LONGRESP) resplen = 17;
++ else resplen = 6;
++
++ // Next state should be S_WAIT_RESP or S_RX_RESP. We may get
++ // more bytes from the DATSSP while shifting out our last bits of cmd
++ while (((s & 0x7) != S_WAIT_RESP) && ((s & 0x7) != S_RX_RESP)) {
++ if (timeout(sd)) break;
++ if (req == CMD_SEND_IF_COND) sd->sd_timeout += 1000;
++ s = tend_ssp(sd, NULL, dat);
++ }
++
++ // Once we're in S_WAIT_RESP or S_RX_RESP though, the DATSSP is only
++ // active for 2 more clocks at the beginning of the S_WAIT_RESP state.
++ // This is enough for one more byte in 4-bit mode, though we may have
++ // 2 bytes already in our DATSSP.
++ if (sd->sd_state & (SDDAT_RX|SDDAT_TX)) {
++ do {
++ if (timeout(sd)) break;
++ s = tend_ssp(sd, NULL, dat);
++ } while (!(s & 0x18));
++
++ // We've now read/wrote one more byte to the DATSSP
++ // which should allow our FSM to advance to the RX_RESP state.
++ // If we pick up more than 2 more DATSSP bytes, something is
++ // wrong.
++ ndat = 0;
++ while ((s & 0x7) != S_RX_RESP) {
++ if (timeout(sd) || ndat > 2) break;
++ s = tend_ssp(sd, NULL, dat);
++ if (s & 0x10) ndat++;
++ }
++
++ if (ndat > 2) {
++ SDPOKE8(sd, SDSTATE, S_OFF);
++ return 1;
++ }
++ }
++
++ // We're now done with whatever business we had remaining with the
++ // previous command's DATSSP transfer since we've either just got our
++ // first byte of response or our last byte of data
++ sd->sd_state &= ~(SDDAT_RX|SDDAT_TX);
++ if (type == TYPE_RXDAT) sd->sd_state |= SDDAT_RX;
++
++ // Next we receive the response. If this is TYPE_RXDAT command,
++ // or an abortion of a previous TYPE_RXDAT command, we may get a
++ // few bytes from the DAT SSP also.
++ sd->sd_state |= SDCMD_RX;
++ while ((respptr - resp) != resplen) {
++ if (timeout(sd)) break;
++ s = tend_ssp(sd, &respptr, dat);
++ if ((s & 0x10) && (resp == respptr)) {
++ SDPOKE8(sd, SDSTATE, S_OFF);
++ sd->sd_state &= ~(SDCMD_RX|SDDAT_RX);
++ return 1;
++ }
++ }
++ sd->sd_state &= ~SDCMD_RX;
++
++ if (type == TYPE_ABORT)
++ sd->sd_state &= ~(SDDAT_RX|SDDAT_TX);
++
++ if (type == TYPE_TXDAT) sd->sd_state |= SDDAT_TX;
++
++done:
++ if (timeout(sd)) return 1;
++ else return 0;
++
++}
++
++static int datssp_stream2(struct sdcore *sd, unsigned char **dat,
++ unsigned int buflen)
++{
++ unsigned char *d;
++ int ret;
++#ifndef SD_READONLYDMA
++ int ok32;
++ int ok16;
++ int sddat2_8;
++ unsigned int x;
++#endif
++
++ if (sd->os_dmastream /* && (sd->sd_state & SDDAT_RX) */) {
++ d = dat ? *dat : NULL;
++ ret = sd->os_dmastream(sd->os_arg, d, buflen);
++ if (!ret && d) *dat += buflen;
++ return ret;
++ }
++
++#ifndef SD_READONLYDMA
++ d = *dat;
++
++ while (buflen > 512) {
++ datssp_stream2(sd, dat, 512);
++ if (sd->os_irqwait) sd->os_irqwait(sd->os_arg, 1);
++ buflen -= 512;
++ d = *dat;
++ }
++
++ ok32 = (sd->hw_version == 2);
++ ok16 = (ok32 || (sd->hw_version == 3));
++ if (ok16 && !ok32) sddat2_8 = SDDAT2 + 1;
++ else sddat2_8 = SDDAT2;
++
++ if (sd->sd_state & SDDAT_RX) {
++
++ while (((int)d & 0x1) || buflen == 1) {
++ *d++ = SDPEEK8(sd, sddat2_8);
++ buflen--;
++ }
++
++ if (((int)d & 0x2) && buflen >= 2) {
++ if (ok16) *(unsigned short *)(d) = SDPEEK16(sd, SDDAT2);
++ else {
++#ifdef BIGENDIAN
++ x = SDPEEK8(sd, sddat2_8) << 8;
++ x |= SDPEEK8(sd, sddat2_8);
++#else
++ x = SDPEEK8(sd, sddat2_8);
++ x |= SDPEEK8(sd, sddat2_8) << 8;
++#endif
++ *(unsigned short *)(d) = x;
++ }
++ buflen -= 2;
++ d += 2;
++ }
++
++ if (ok32) while (buflen >= 4) {
++ *(unsigned int *)(d) = SDPEEK32(sd, SDDAT2);
++ buflen -= 4;
++ d += 4;
++ } else if (ok16) while (buflen >= 4) {
++#ifdef BIGENDIAN
++ x = SDPEEK16(sd, SDDAT2) << 16;
++ x |= SDPEEK16(sd, SDDAT2);
++#else
++ x = SDPEEK16(sd, SDDAT2);
++ x |= SDPEEK16(sd, SDDAT2) << 16;
++#endif
++ buflen -= 4;
++ *(unsigned int *)(d) = x;
++ d += 4;
++ } else while (buflen >= 4) {
++#ifdef BIGENDIAN
++ x = SDPEEK8(sd, sddat2_8) << 24;
++ x |= SDPEEK8(sd, sddat2_8) << 16;
++ x |= SDPEEK8(sd, sddat2_8) << 8;
++ x |= SDPEEK8(sd, sddat2_8);
++#else
++ x = SDPEEK8(sd, sddat2_8);
++ x |= SDPEEK8(sd, sddat2_8) << 8;
++ x |= SDPEEK8(sd, sddat2_8) << 16;
++ x |= SDPEEK8(sd, sddat2_8) << 24;
++#endif
++ buflen -= 4;
++ *(unsigned int *)(d) = x;
++ d += 4;
++ }
++ } else {
++ while (((int)d & 0x1) || buflen == 1) {
++ SDPOKE8(sd, SDDAT2, *d++);
++ buflen--;
++ }
++
++ if (((int)d & 0x2) && buflen >= 2) {
++ if (ok16) SDPOKE16(sd, SDDAT2, *(unsigned short *)(d));
++ else {
++ x = *(unsigned short *)(d);
++#ifdef BIGENDIAN
++ SDPOKE8(sd, SDDAT2, x >> 8);
++ SDPOKE8(sd, SDDAT2, x);
++#else
++ SDPOKE8(sd, SDDAT2, x);
++ SDPOKE8(sd, SDDAT2, x >> 8);
++#endif
++ }
++ buflen -= 2;
++ d += 2;
++ }
++
++ if (ok32) while (buflen >= 4) {
++ SDPOKE32(sd, SDDAT2, *(unsigned int *)(d));
++ buflen -= 4;
++ d += 4;
++ } else if (ok16) while (buflen >= 4) {
++ x = *(unsigned int *)(d);
++ buflen -= 4;
++ d += 4;
++#ifdef BIGENDIAN
++ SDPOKE16(sd, SDDAT2, x >> 16);
++ SDPOKE16(sd, SDDAT2, x);
++#else
++ SDPOKE16(sd, SDDAT2, x);
++ SDPOKE16(sd, SDDAT2, x >> 16);
++#endif
++ } else while (buflen >= 4) {
++ x = *(unsigned int *)(d);
++ buflen -= 4;
++ d += 4;
++#ifdef BIGENDIAN
++ SDPOKE8(sd, SDDAT2, x >> 24);
++ SDPOKE8(sd, SDDAT2, x >> 16);
++ SDPOKE8(sd, SDDAT2, x >> 8);
++ SDPOKE8(sd, SDDAT2, x);
++#else
++ SDPOKE8(sd, SDDAT2, x);
++ SDPOKE8(sd, SDDAT2, x >> 8);
++ SDPOKE8(sd, SDDAT2, x >> 16);
++ SDPOKE8(sd, SDDAT2, x >> 24);
++#endif
++ }
++ }
++
++ *dat = d;
++
++ if (buflen > 0) return datssp_stream2(sd, dat, buflen);
++ else return 0;
++#else
++ return 0;
++#endif
++}
++
++static int datssp_stream(struct sdcore *sd, unsigned char **dat,
++ unsigned int buflen)
++{
++ unsigned int s, t, byte = 0;
++ unsigned char *d;
++
++ if (((sd->sd_state & SDDAT_RX) && sd->os_dmastream) /* ||
++ ((sd->sd_state & SDDAT_TX) && sd->os_dmastream && dat) */ ) {
++ unsigned char *d = dat ? *dat : NULL;
++ int ret = sd->os_dmastream(sd->os_arg, d, buflen);
++ if (!ret && d) *dat += buflen;
++ return ret;
++ }
++
++ if (sd->hw_version > 0) return datssp_stream2(sd, dat, buflen);
++
++ while (buflen) {
++ if (timeout(sd)) return 1;
++ s = tend_ssp(sd, NULL, dat);
++ if (s & 0x10) {
++ buflen--;
++ if (byte++ > 7) {
++ if (sd->sd_state & SDDAT_RX)
++ goto fastrx;
++ else goto fasttx;
++ }
++ }
++ }
++
++ // Now we can go faster (PIO)
++fastrx:
++ if (dat) {
++ d = *dat;
++ while (buflen) {
++ s = SDPEEK8(sd, SDDAT);
++ *d = s;
++ buflen--;
++ d++;
++ }
++ *dat = d;
++ } else {
++ while (buflen--) SDPEEK8(sd, SDDAT);
++ }
++ return 0;
++
++fasttx:
++ if (dat) {
++ d = *dat;
++ while (buflen) {
++ t = *d;
++ SDPOKE8(sd, SDDAT, t);
++ buflen--;
++ d++;
++ datssp_feedcrc(sd, t);
++ }
++ *dat = d;
++ } else {
++ while (buflen--) SDPOKE8(sd, SDDAT, datssp_getcrc(sd));
++ }
++ return 0;
++}
++
++static int stop(struct sdcore *sd)
++{
++ int ret;
++ unsigned int resp[6];
++
++ if (sd->hw_version) return stop2(sd);
++
++ if (sd->parked_sector) {
++ if (sd->sd_state & SDDAT_TX) {
++ /* wait to get out of S_WAIT_BUSY */
++ while ((SDPEEK8(sd, SDSTATE) & 0x7) != S_TX_WRITE)
++ if (timeout(sd)) break;
++
++ /* abort parked write */
++ SDPOKE8(sd, SDSTATE, S_SEND_CMD | (TYPE_ABORT << 5));
++ sd->sd_state &= ~SDDAT_TX;
++ sd->sd_state |= SDDAT_RX;
++ ret = sdcmd(sd, CMD_STOP_TRANSMISSION, 0, resp, NULL);
++ sd->sd_state &= ~SDDAT_RX;
++ SDPOKE8(sd, SDSTATE, S_WAIT_BUSY | (TYPE_BSYRESP << 5));
++ } else {
++ /* abort parked read */
++ SDPOKE8(sd, SDSTATE, S_SEND_CMD | (TYPE_ABORT << 5));
++ ret = sdcmd(sd, CMD_STOP_TRANSMISSION, 0, resp, NULL);
++ }
++ sd->parked_sector = 0;
++ if (ret || error(resp, CMD_STOP_TRANSMISSION) || timeout(sd))
++ return 1;
++ }
++ return 0;
++}
++
++static int stop2(struct sdcore *sd)
++{
++ int ret;
++ unsigned int resp[6];
++
++ if (sd->parked_sector) {
++ if (sd->os_irqwait) sd->os_irqwait(sd->os_arg, 0);
++ if (sd->sd_state & SDDAT_TX) {
++ /* abort parked write */
++ ret = sdcmd2(sd, CMD_STOP_TRANSMISSION, 0, resp, NULL);
++ SDPOKE8(sd, SDCTRL2, 0x0);
++ if (sd->os_irqwait) sd->os_irqwait(sd->os_arg, 5);
++ SDPOKE8(sd, SDGPIO, 0xff);
++
++ /*
++ while ((SDPEEK8(sd, SDGPIO) & 0xf) != 0xf) {
++ sd->os_delay(sd->os_arg, 1);
++ SDPOKE8(sd, SDGPIO, 0xdf);
++ SDPOKE8(sd, SDGPIO, 0xff);
++ if (timeout(sd)) return 1;
++ }
++ */
++ reset_timeout(sd);
++ } else {
++ /* abort parked read */
++ ret = sdcmd2(sd, CMD_STOP_TRANSMISSION, 0, resp, NULL);
++ }
++ sd->parked_sector = 0;
++ if (ret || error(resp, CMD_STOP_TRANSMISSION) || timeout(sd)) {
++ return 1;
++ }
++ }
++ return 0;
++}
++
++static int do_read2(struct sdcore *sd, unsigned int sector, struct sdiov *iov,
++ unsigned int iovcnt)
++{
++ unsigned int ret, n, s, sz;
++ unsigned char *datptr, *dat;
++
++ if (iovcnt == 0) return 0;
++
++ if (activate(sd)) return 1;
++
++ n = iov->sdiov_nsect;
++ datptr = dat = iov->sdiov_base;
++ sz = sdsize(sd);
++ if (sector >= sz) return 0;
++
++ if (sd->parked_sector) {
++ if (!(sd->sd_state & SDDAT_TX) && sd->parked_sector == sector) {
++ if (sd->os_irqwait && !sd->os_dmastream)
++ sd->os_irqwait(sd->os_arg, 3);
++ goto receive;
++ }
++
++ stop2(sd);
++ }
++
++ if (sd->sd_state & SD_HC)
++ ret = sdcmd2(sd, CMD_READ_MULTIPLE_BLOCK2, sector, NULL, NULL);
++ else
++ ret = sdcmd2(sd, CMD_READ_MULTIPLE_BLOCK2, sector * 512, NULL, NULL);
++
++ do {
++ if (timeout(sd)) return 1;;
++ SDPOKE8(sd, SDGPIO, 0xdf);
++ s = SDPEEK8(sd, SDGPIO);
++ SDPOKE8(sd, SDGPIO, 0xff);
++ } while ((s & 0xf) != 0x0);
++ reset_timeout(sd);
++
++receive:
++ if (sd->os_dmaprep && sd->os_dmastream)
++ sd->os_dmaprep(sd->os_arg, datptr, n * 512);
++
++ SDPOKE8(sd, SDGPIO, 0xdf);
++ sd->parked_sector = sector + n;
++
++nextiov:
++ if (sd->parked_sector > sz) {
++ n -= sd->parked_sector - sz;
++ sd->parked_sector = sz;
++ }
++ datssp_stream2(sd, &datptr, n * 512);
++
++ if (--iovcnt) {
++ ++iov;
++ n = iov->sdiov_nsect;
++ datptr = iov->sdiov_base;
++ sd->parked_sector += n;
++ if (sd->os_dmaprep && sd->os_dmastream)
++ sd->os_dmaprep(sd->os_arg, datptr, n * 512);
++ goto nextiov;
++ }
++
++ /* s = SDPEEK8(sd, SDSTAT2);
++ if (s & 0x44) {
++ sd->sd_timeout = 1000001;
++ return 1;
++ }
++ else */ return 0;
++}
++
++static int do_read(struct sdcore *sd, unsigned int sector, struct sdiov *iov,
++ unsigned int iovcnt)
++{
++ unsigned int resp[6], ret, n, sz;
++ unsigned char *datptr, *dat;
++
++ if (iovcnt == 0) return 0;
++
++ n = iov->sdiov_nsect;
++ datptr = dat = iov->sdiov_base;
++ sz = sdsize(sd);
++ if (sector >= sz) return 0;
++
++ if (sd->parked_sector) {
++ if (!(sd->sd_state & SDDAT_TX) && sd->parked_sector == sector)
++ goto receive;
++
++ stop(sd);
++ }
++
++ if (sd->sd_state & SD_HC)
++ ret = sdcmd(sd, CMD_READ_MULTIPLE_BLOCK, sector, resp, &datptr);
++ else
++ ret = sdcmd(sd, CMD_READ_MULTIPLE_BLOCK, sector * 512, resp, &datptr);
++ if (ret || error(resp, CMD_READ_MULTIPLE_BLOCK)) return 1;
++
++receive:
++ if (sd->os_dmaprep && sd->os_dmastream)
++ sd->os_dmaprep(sd->os_arg, datptr, n * 512 - (datptr - dat));
++
++ datssp_stream(sd, &datptr, 512 - (datptr - dat));
++ datssp_stream(sd, NULL, 6);
++
++ sd->parked_sector = sector + n;
++ if (sd->parked_sector > sz) {
++ n -= sd->parked_sector - sz;
++ sd->parked_sector = sz;
++ }
++ n--;
++
++nextiov:
++ while (n--) {
++ SDPOKE8(sd, SDSTATE, S_WAIT_RESP | (TYPE_RXDAT << 5));
++ datssp_stream(sd, NULL, 2); // last part of prev CRC
++ datssp_stream(sd, &datptr, 512);
++ datssp_stream(sd, NULL, 6); // first part of CRC
++ }
++
++ if (--iovcnt) {
++ ++iov;
++ n = iov->sdiov_nsect;
++ datptr = iov->sdiov_base;
++ sd->parked_sector += n;
++ if (sd->parked_sector > sz) {
++ n -= sd->parked_sector - sz;
++ sd->parked_sector = sz;
++ }
++ if (sd->os_dmaprep && sd->os_dmastream && n > 0)
++ sd->os_dmaprep(sd->os_arg, datptr, n * 512);
++ goto nextiov;
++ }
++
++ SDPOKE8(sd, SDSTATE, S_WAIT_RESP | (TYPE_RXDAT << 5));
++ datssp_stream(sd, NULL, 2); // last part of prev CRC
++ return 0;
++}
++
++static int do_write2(struct sdcore *sd, unsigned int sector, struct sdiov *iov,
++ unsigned int iovcnt)
++{
++ unsigned char *datptr;
++ unsigned int resp[6], ret, n, s, sz, ss;
++
++ if (sd->sd_wprot) return 1;
++
++ if (iovcnt == 0) return 0;
++
++ if (activate(sd)) return 1;
++
++ sz = sdsize(sd);
++ if (sector >= sz) return 0;
++
++ if (sd->os_powerok) {
++ int ok = sd->os_powerok(sd);
++ if (!ok && sd->parked_sector) {
++ stop2(sd);
++ return 1;
++ } else if (!ok) return 1;
++ }
++
++ if (sd->parked_sector) {
++ if ((sd->sd_state & SDDAT_TX) && sd->parked_sector == sector)
++ goto transmit;
++
++ stop2(sd);
++ }
++
++ if (sd->sd_erasehint) {
++ sdcmd2(sd, CMD_APP_CMD, sd->sd_rcaarg, NULL, NULL);
++ sdcmd2(sd, ACMD_SET_WR_BLK_ERASE_COUNT, sd->sd_erasehint,
++ NULL, NULL);
++ sd->sd_erasehint = 0;
++ }
++
++ if (sd->sd_state & SD_HC)
++ ret = sdcmd2(sd, CMD_WRITE_MULTIPLE_BLOCK, sector, resp, NULL);
++ else
++ ret = sdcmd2(sd, CMD_WRITE_MULTIPLE_BLOCK, sector * 512, resp, NULL);
++ if (ret || error(resp, CMD_WRITE_MULTIPLE_BLOCK)) {
++ return 1;
++ }
++ sd->parked_sector = sector;
++ ss = SDPEEK8(sd, SDSTAT2);
++
++transmit:
++ while (iovcnt--) {
++ datptr = iov->sdiov_base;
++ n = iov->sdiov_nsect;
++ sd->parked_sector += n;
++ if (sd->parked_sector > sz) {
++ n -= sd->parked_sector - sz;
++ sd->parked_sector = sz;
++ }
++ datssp_stream2(sd, &datptr, n * 512);
++ iov++;
++ }
++
++ if (!sd->sd_writeparking) {
++ ret = stop2(sd);
++ if (ret) return ret;
++ }
++
++ if (sd->os_irqwait) sd->os_irqwait(sd->os_arg, 2);
++
++ s = SDPEEK8(sd, SDSTAT2);
++ if (s & 0x44) {
++ sd->sd_timeout = 1000001;
++ return 1;
++ } else {
++ reset_timeout(sd);
++ return 0;
++ }
++}
++
++static int do_write(struct sdcore *sd, unsigned int sector, struct sdiov *iov,
++ unsigned int iovcnt)
++{
++ unsigned char *datptr, *crcptr, **crcptrptr;
++ unsigned int resp[6], ret, n, sz;
++
++ if (sd->sd_wprot) return 1;
++
++ if (iovcnt == 0) return 0;
++
++ sz = sdsize(sd);
++ if (sector >= sz) return 0;
++
++ if (0 /* sd->sd_crchint */) {
++ // CRC is pre-calculated so don't recalculate
++ crcptr = sd->sd_crchint;
++ crcptrptr = &crcptr;
++ sd->sd_state |= DATSSP_NOCRC;
++ sd->sd_crchint = NULL;
++ } else {
++ crcptrptr = NULL;
++ sd->sd_state &= ~DATSSP_NOCRC;
++ }
++
++ if (sd->parked_sector) {
++ if ((sd->sd_state & SDDAT_TX) && sd->parked_sector == sector)
++ goto transmit;
++
++ stop(sd);
++ }
++
++ if (sd->sd_erasehint) {
++ sdcmd(sd, CMD_APP_CMD, sd->sd_rcaarg, NULL, NULL);
++ sdcmd(sd, ACMD_SET_WR_BLK_ERASE_COUNT, sd->sd_erasehint,
++ NULL, NULL);
++ sd->sd_erasehint = 0;
++ }
++
++ if (sd->sd_state & SD_HC)
++ ret = sdcmd(sd, CMD_WRITE_MULTIPLE_BLOCK, sector, resp, NULL);
++ else
++ ret = sdcmd(sd, CMD_WRITE_MULTIPLE_BLOCK, sector * 512, resp, NULL);
++ if (ret || error(resp, CMD_WRITE_MULTIPLE_BLOCK)) {
++ return 1;
++ }
++ sd->parked_sector = sector;
++
++transmit:
++ while (iovcnt--) {
++ datptr = iov->sdiov_base;
++ n = iov->sdiov_nsect;
++ sd->parked_sector += n;
++ if (sd->parked_sector > sz) {
++ n -= sd->parked_sector - sz;
++ sd->parked_sector = sz;
++ }
++ while (n--) {
++ datssp_stream(sd, &datptr, 512);
++ datssp_stream(sd, crcptrptr, 8); // CRC bytes
++ SDPOKE8(sd, SDSTATE, S_CRC_CHECK | (TYPE_TXDAT << 5));
++ }
++ iov++;
++ }
++
++ if (!sd->sd_writeparking) {
++ stop(sd);
++ }
++
++ return 0;
++}
++
++static
++int sdfastinit(struct sdcore *sd)
++{
++ SDPOKE8(sd, SDCTRL, 0x40);
++ sd->sd_state = DATSSP_4BIT;
++
++ sd->sd_rcaarg = ~sd->sdboot_token;
++ sdcmd(sd, CMD_DESELECT_CARD, ~sd->sd_rcaarg, NULL, NULL);
++ sdcmd(sd, CMD_SEND_CSD, sd->sd_rcaarg, sd->sd_csd, NULL);
++ sdcmd(sd, CMD_SELECT_CARD, sd->sd_rcaarg, NULL, NULL);
++
++ if (sd->os_dmastream) SDPOKE8(sd, SDCTRL, 0x42);
++ if ((SDPEEK8(sd, SDCTRL) & 0x80) || (sd->sd_csd[15] & 0x30))
++ sd->sd_wprot = 1;
++ sd->sd_blocksize = 1 << ((sd->sd_csd[6] & 0xf));
++ if (timeout(sd)) return 0;
++ else return sdsize(sd);
++}
++
++static
++int sdreset2(struct sdcore *sd)
++{
++ unsigned int rca, s, i, x;
++ unsigned int resp[17];
++
++ reset_timeout(sd);
++ sd_initcrc(sd);
++ sd->parked_sector = 0;
++ sd->sd_wprot = 0;
++ sd->sd_blocksize = 0;
++ sd->sd_sz = 0;
++ if (sd->hw_version == 0) sd->hw_version = version(sd);
++ if (sd->hw_version == 0) return 0;
++ sd->sd_state &= SD_RESET;
++ remember_sdcore(sd);
++ activate(sd);
++ sd->sd_state |= SD_LOSPEED;
++
++ if (!(sd->sd_state & SD_RESET) && (SDPEEK8(sd, SDGPIO) != 0x0)) {
++ SDPOKE8(sd, SDGPIO, 0x0);
++#ifdef BIGENDIAN
++ for (i = 0; i < 8; i++) SDPOKE16(sd, SDLUN2, i << 8);
++#else
++ for (i = 0; i < 8; i++) SDPOKE16(sd, SDLUN2, i);
++#endif
++ sd->os_delay(sd->os_arg, 100000);
++
++ /* this was a global reset, so let the other luns know */
++ for (i = 0; i < sizeof(sdcores); i++) {
++ if (sdcores[i] == NULL) break;
++ if (sdcores[i]->sd_regstart == sd->sd_regstart)
++ sdcores[i]->sd_state |= SD_RESET;
++ }
++#ifdef BIGENDIAN
++ SDPOKE16(sd, SDLUN2, sd->sd_lun << 8);
++#else
++ SDPOKE16(sd, SDLUN2, sd->sd_lun);
++#endif
++ }
++ sd->sd_state &= ~SD_RESET;
++
++ // gratuitous clocks
++ SDPOKE8(sd, SDGPIO, 0xff);
++ sd->os_delay(sd->os_arg, 5000);
++ for (i = 0; i < 750; i++) {
++ SDPOKE8(sd, SDGPIO, 0xff);
++ SDPEEK8(sd, SDGPIO); /* delay */
++ SDPEEK8(sd, SDGPIO); /* delay */
++ SDPOKE8(sd, SDGPIO, 0xdf);
++ SDPEEK8(sd, SDGPIO); /* delay */
++ SDPEEK8(sd, SDGPIO); /* delay */
++ }
++
++ SDPEEK8(sd, SDSTAT2); /* reset any timeout/crc conditions */
++ SDPOKE8(sd, SDSTAT2, 0x18);
++ s = sdcmd2(sd, CMD_SEND_IF_COND, 0x1aa, resp, NULL);
++ if (s) {
++ reset_timeout(sd);
++ x = 0x00ff0000;
++ } else {
++ x = 0x40ff0000;
++ }
++
++ do {
++ sdcmd2(sd, CMD_APP_CMD, 0, NULL, NULL);
++ sdcmd2(sd, ACMD_SD_SEND_OP_COND, x, resp, NULL);
++ if (timeout(sd)) break;
++ // TODO: check for valid result or limit # of loops,
++ // otherwise we may loop forever on malfunctioning cards.
++ } while (((resp[1] & 0x80) == 0x0));
++
++ if ((x & 0x40000000) && (resp[1] & 0x40)) {
++ sd->sd_state |= SD_HC;
++ }
++
++ sdcmd2(sd, CMD_ALL_SEND_CID, 0, resp, NULL);
++ sdcmd2(sd, CMD_SEND_RELATIVE_ADDR, 0, resp, NULL);
++ rca = resp[1] << 8 | resp[2];
++ sd->sd_rcaarg = (rca & 0xff00) << 16 | (rca & 0xff) << 16;
++ sd->sdboot_token = ~sd->sd_rcaarg;
++
++ sdcmd2(sd, CMD_SEND_CSD, sd->sd_rcaarg, sd->sd_csd, NULL);
++ sdcmd2(sd, CMD_SELECT_CARD, sd->sd_rcaarg, resp, NULL);
++
++ if ((resp[1] & 0x2)) {
++ unsigned int ret = 1;
++ sd->sd_locked = 1;
++#ifndef SD_NOLOCKSUPPORT
++ if (sd->sd_pwd)
++ ret = sdlockctl2(sd, SDLOCK_UNLOCK, sd->sd_pwd, NULL);
++#endif
++ if (ret != 0) return 0;
++ } else sd->sd_locked = 0;
++
++ sdcmd2(sd, CMD_APP_CMD, sd->sd_rcaarg, NULL, NULL);
++ sdcmd2(sd, ACMD_SET_CLR_CARD_DETECT, 0, NULL, NULL);
++ sdcmd2(sd, CMD_SET_BLOCKLEN, 512, NULL, NULL);
++ sdcmd2(sd, CMD_APP_CMD, sd->sd_rcaarg, NULL, NULL);
++ sdcmd2(sd, ACMD_SET_BUS_WIDTH, 2, resp, NULL);
++ sd->sd_state |= DATSSP_4BIT;
++ sd->sd_state &= ~SD_LOSPEED;
++
++ sdcmd2(sd, CMD_APP_CMD, sd->sd_rcaarg, NULL, NULL);
++ sdcmd2(sd, ACMD_SEND_SCR2, 0, NULL, NULL);
++ do {
++ if (timeout(sd)) break;
++ SDPOKE8(sd, SDGPIO, 0xdf);
++ SDPEEK8(sd, SDGPIO);
++ s = SDPEEK8(sd, SDGPIO);
++ SDPOKE8(sd, SDGPIO, 0xff);
++ SDPEEK8(sd, SDGPIO);
++ } while ((s & 0xf) != 0x0);
++ for (i = 0; i < 16; i++) {
++ SDPOKE8(sd, SDGPIO, 0xdf);
++ SDPEEK8(sd, SDGPIO);
++ s = (SDPEEK8(sd, SDGPIO) & 0xf) << 4;
++ SDPOKE8(sd, SDGPIO, 0xff);
++ SDPEEK8(sd, SDGPIO);
++ SDPOKE8(sd, SDGPIO, 0xdf);
++ SDPEEK8(sd, SDGPIO);
++ s |= (SDPEEK8(sd, SDGPIO) & 0xf);
++ SDPOKE8(sd, SDGPIO, 0xff);
++ SDPEEK8(sd, SDGPIO);
++ if (i < 8) sd->sd_scr[i] = s;
++ }
++ for (i = 0; i < 8; i++) {
++ SDPOKE8(sd, SDGPIO, 0xdf);
++ SDPEEK8(sd, SDGPIO);
++ SDPEEK8(sd, SDGPIO);
++ SDPOKE8(sd, SDGPIO, 0xff);
++ SDPEEK8(sd, SDGPIO);
++ }
++ sd->sd_state &= ~SDDAT_RX;
++
++#ifndef SD_NOHIGHSPEED
++ if ((sd->sd_scr[0] & 0xf) >= 1) { // SD version >= 1.10
++ unsigned char dat[64];
++ sdcmd2(sd, CMD_SWITCH_FUNC2, 0x80fffff1, NULL, NULL);
++ do {
++ if (timeout(sd)) break;
++ SDPOKE8(sd, SDGPIO, 0xdf);
++ SDPEEK8(sd, SDGPIO);
++ s = SDPEEK8(sd, SDGPIO);
++ SDPOKE8(sd, SDGPIO, 0xff);
++ SDPEEK8(sd, SDGPIO);
++ } while ((s & 0xf) != 0x0);
++ for (i = 0; i < 72; i++) {
++ SDPOKE8(sd, SDGPIO, 0xdf);
++ SDPEEK8(sd, SDGPIO);
++ s = (SDPEEK8(sd, SDGPIO) & 0xf) << 4;
++ SDPOKE8(sd, SDGPIO, 0xff);
++ SDPEEK8(sd, SDGPIO);
++ SDPOKE8(sd, SDGPIO, 0xdf);
++ SDPEEK8(sd, SDGPIO);
++ s |= (SDPEEK8(sd, SDGPIO) & 0xf);
++ SDPOKE8(sd, SDGPIO, 0xff);
++ SDPEEK8(sd, SDGPIO);
++ if (i < 64) dat[i] = s;
++ }
++ for (i = 0; i < 8; i++) {
++ SDPOKE8(sd, SDGPIO, 0xdf);
++ SDPEEK8(sd, SDGPIO);
++ SDPEEK8(sd, SDGPIO);
++ SDPOKE8(sd, SDGPIO, 0xff);
++ SDPEEK8(sd, SDGPIO);
++ }
++ sd->sd_state &= ~SDDAT_RX;
++ if (dat[0] | dat[1]) {
++ SDPOKE8(sd, SDSTAT2, 0x38);
++ sd->sd_state |= SD_HISPEED;
++ }
++ }
++#endif
++
++#ifdef BIGENDIAN
++ if ((sd->sd_csd[15] & 0x30) || (SDPEEK16(sd, SDGPIO) & 0x2))
++#else
++ if ((sd->sd_csd[15] & 0x30) || (SDPEEK16(sd, SDGPIO) & 0x200))
++#endif
++ sd->sd_wprot = 1;
++ sd->sd_blocksize = 1 << ((sd->sd_csd[6] & 0xf));
++ if (timeout(sd)) return 0;
++ else {
++ reset_timeout(sd);
++ return sdsize(sd);
++ }
++}
++
++/*
++ * return 0 : 8 bit TS-SDCORE v1
++ * return 1 : 8 bit 4x8 TS-SDCORE v2
++ * return 2 : 32 bit 4x32 TS-SDCORE v2
++ * return 3 : 16 bit 4x32 TS-SDCORE v2
++ * return 4 : 8 bit 4x32 TS-SDCORE v2
++ */
++static int version(struct sdcore *sd)
++{
++ int a, b, i;
++
++
++#ifdef SD_FORCEVERSION
++ return SD_FORCEVERSION;
++#endif
++ for (i = 0; i < sizeof(sdcores); i++) {
++ if (sdcores[i] == NULL) break;
++ if (sdcores[i]->sd_regstart == sd->sd_regstart)
++ return sdcores[i]->hw_version;
++ }
++
++ a = SDPEEK8(sd, 3);
++ SDPOKE8(sd, 3, (a ^ 0x40));
++ b = SDPEEK8(sd, 3);
++ SDPOKE8(sd, 3, a);
++ if ((a & 0x40) ^ (b & 0x40)) return 0;
++ else if (a & 0x40) return 1;
++ /* either 2, 3, or 4 */
++ a = SDPEEK32(sd, 12);
++ b = SDPEEK16(sd, 12);
++#ifdef BIGENDIAN
++ if ((a & 0x40000000) && (b & 0x4000)) return 2;
++#else
++ if ((a & 0x40) && (b & 0x40)) return 2;
++#endif
++ a = SDPEEK8(sd, 12);
++ if (a & 0x40) return 3;
++ else return 4;
++}
++
++int sdreset(struct sdcore *sd)
++{
++ unsigned int rca, s, x;
++ unsigned int resp[17];
++
++ reset_timeout(sd);
++ sd_initcrc(sd);
++ sd->parked_sector = 0;
++ sd->sd_wprot = 0;
++ sd->sd_blocksize = 0;
++ sd->sd_sz = 0;
++
++ sd->hw_version = version(sd);
++ if (sd->hw_version >= 2) return sdreset2(sd);
++
++ // check for no SD card present
++ if (SDPEEK8(sd, SDCTRL) & 0x8) return 0;
++
++ if (sd->sdboot_token) {
++ int ret = sdfastinit(sd);
++ sd->sdboot_token = 0;
++ if (ret) return ret;
++ }
++
++ // set controller for 1-bit mode, slow clock
++ SDPOKE8(sd, SDCTRL, 0x20);
++
++ SDPOKE8(sd, SDSTATE, S_DUMMY_CLK);
++ sd->sd_state = SDCMD_RX|SDDAT_RX;
++ s = SDPEEK8(sd, SDSTATE);
++ while ((s & 0x7) != S_SEND_CMD) {
++ // If we timeout here, it would be VERY BAD as we have no
++ // further recourse to set things right if we can't turn
++ // the SD off.
++ if (timeout(sd)) return 0;
++ sd->os_delay(sd->os_arg, 10000);
++ sd->sd_timeout += 10000;
++
++ // We won't be able to change state until both SSPs are empty
++ s = tend_ssp(sd, NULL, NULL);
++ }
++ SDPOKE8(sd, SDSTATE, S_OFF);
++ sd->sd_state = 0;
++
++ sd->os_delay(sd->os_arg, 50000);
++
++ SDPOKE8(sd, SDSTATE, S_DUMMY_CLK);
++ sd->os_delay(sd->os_arg, 100000);
++ if ((SDPEEK8(sd, SDSTATE) & 0x7) == S_OFF) {
++ // No card present
++ return 0;
++ }
++
++ SDPOKE8(sd, SDSTATE, S_WAIT_RESP);
++ // clock will freerun waiting for a response that will never come
++ sd->os_delay(sd->os_arg, 50000);
++
++ SDPOKE8(sd, SDSTATE, S_DUMMY_CLK);
++
++ s = sdcmd(sd, CMD_SEND_IF_COND, 0x1aa, resp, NULL);
++ if (s) {
++ reset_timeout(sd);
++ SDPOKE8(sd, SDSTATE, S_DUMMY_CLK);
++ x = 0x00ff0000;
++ } else {
++ x = 0x40ff0000;
++ }
++
++ do {
++ sdcmd(sd, CMD_APP_CMD, 0, NULL, NULL);
++ sdcmd(sd, ACMD_SD_SEND_OP_COND, x, resp, NULL);
++ if (timeout(sd)) break;
++ } while (((resp[1] & 0x80) == 0x0));
++
++ if ((x & 0x40000000) && (resp[1] & 0x40)) sd->sd_state |= SD_HC;
++
++ sdcmd(sd, CMD_ALL_SEND_CID, 0, resp, NULL);
++ sdcmd(sd, CMD_SEND_RELATIVE_ADDR, 0, resp, NULL);
++ rca = resp[1] << 8 | resp[2];
++ sd->sd_rcaarg = (rca & 0xff00) << 16 | (rca & 0xff) << 16;
++ sd->sdboot_token = ~sd->sd_rcaarg;
++
++ sdcmd(sd, CMD_SEND_CSD, sd->sd_rcaarg, sd->sd_csd, NULL);
++ sdcmd(sd, CMD_SELECT_CARD, sd->sd_rcaarg, resp, NULL);
++
++ if ((resp[1] & 0x2)) {
++ unsigned int ret = 1;
++ sd->sd_locked = 1;
++#ifndef SD_NOLOCKSUPPORT
++ if (sd->sd_pwd)
++ ret = sdlockctl(sd, SDLOCK_UNLOCK, sd->sd_pwd, NULL);
++#endif
++ if (ret != 0) return 0;
++ } else sd->sd_locked = 0;
++
++ sdcmd(sd, CMD_APP_CMD, sd->sd_rcaarg, NULL, NULL);
++ sdcmd(sd, ACMD_SET_CLR_CARD_DETECT, 0, NULL, NULL);
++ /*
++ sdcmd(sd, CMD_APP_CMD, sd->sd_rcaarg, NULL, NULL);
++ sdcmd(sd, ACMD_SEND_SCR, 0, NULL, &datptr);
++ while ((datptr - sd->sd_scr) != 8) {
++ if (timeout(sd)) return 1;
++ tend_ssp(sd, NULL, &datptr);
++ }
++ datssp_stream(sd, NULL, 3);
++ SDPOKE8(sd, SDSTATE, (TYPE_ABORT << 5) | S_SEND_CMD);
++ sd->sd_state |= SDCMD_RX|SDDAT_RX;
++ while ((SDPEEK8(sd, SDSTATE) & 0x17) != S_SEND_CMD) {
++ if (timeout(sd)) break;
++ tend_ssp(sd, NULL, NULL);
++ }
++ sd->sd_state &= ~(SDCMD_RX|SDDAT_RX);
++ if ((sd->sd_scr[0] & 0xf) >= 1) { // SD version >= 1.10
++ unsigned char dat[64];
++ datptr = dat;
++ sdcmd(sd, CMD_SWITCH_FUNC, 0x80fffff1, NULL, &datptr);
++ while ((datptr - dat) != 64) {
++ if (timeout(sd)) break;
++ tend_ssp(sd, NULL, &datptr);
++ }
++ datssp_stream(sd, NULL, 3);
++ SDPOKE8(sd, SDSTATE, (TYPE_ABORT << 5) | S_SEND_CMD);
++ sd->sd_state |= SDCMD_RX|SDDAT_RX;
++ while ((SDPEEK8(sd, SDSTATE) & 0x7) != S_SEND_CMD) {
++ if (timeout(sd)) break;
++ tend_ssp(sd, NULL, NULL);
++ }
++ sd->sd_state &= ~(SDCMD_RX|SDDAT_RX);
++ }
++ */
++
++ sdcmd(sd, CMD_SET_BLOCKLEN, 512, NULL, NULL);
++ sdcmd(sd, CMD_APP_CMD, sd->sd_rcaarg, NULL, NULL);
++ sdcmd(sd, ACMD_SET_BUS_WIDTH, 2, resp, NULL);
++
++ // set controller for 4-bit mode, fast clock
++ SDPOKE8(sd, SDCTRL, (0x40 | (sd->os_dmastream ? 0x2 : 0x0)));
++ sd->sd_state |= DATSSP_4BIT;
++
++ /*
++ sdcmd(sd, CMD_APP_CMD, sd->sd_rcaarg, NULL, NULL);
++ sdcmd(sd, ACMD_SEND_SCR, 0, NULL, &datptr);
++ while ((datptr - sd->sd_scr) != 8) {
++ if (timeout(sd)) break;
++ tend_ssp(sd, NULL, &datptr);
++ }
++ datssp_stream(sd, NULL, 6);
++ SDPOKE8(sd, SDSTATE, S_DUMMY_CLK | (TYPE_SHORTRESP << 5));
++ bzero(resp, 6 * 4);
++ sdcmd(sd, CMD_SEND_STATUS, 0, resp, NULL);
++ */
++
++ if ((SDPEEK8(sd, SDCTRL) & 0x80) || (sd->sd_csd[15] & 0x30))
++ sd->sd_wprot = 1;
++ sd->sd_blocksize = 1 << ((sd->sd_csd[6] & 0xf));
++ if (timeout(sd) || error(resp, ACMD_SET_BUS_WIDTH)) return 0;
++ else return sdsize(sd);
++}
++
++static
++int sdread2(struct sdcore *sd, unsigned int sector, unsigned char *dat,
++ int nsectors)
++{
++ struct sdiov iov;
++ int ret;
++
++ iov.sdiov_base = dat;
++ iov.sdiov_nsect = nsectors;
++ ret = do_read2(sd, sector, &iov, 1);
++ return ret;
++}
++
++int sdread(struct sdcore *sd, unsigned int sector, unsigned char *dat,
++ int nsectors)
++{
++ struct sdiov iov;
++ int ret;
++
++ iov.sdiov_base = dat;
++ iov.sdiov_nsect = nsectors;
++ if (sd->hw_version == 0) ret = do_read(sd, sector, &iov, 1);
++ else ret = do_read2(sd, sector, &iov, 1);
++ return ret;
++}
++
++int sdwrite(struct sdcore *sd, unsigned int sector, unsigned char *dat,
++ int nsectors)
++{
++ struct sdiov iov;
++ unsigned int ret;
++
++ iov.sdiov_base = dat;
++ iov.sdiov_nsect = nsectors;
++ if (sd->hw_version == 0) ret = do_write(sd, sector, &iov, 1);
++ else ret = do_write2(sd, sector, &iov, 1);
++ return ret;
++
++}
++
++int sdreadv(struct sdcore *sd, unsigned int sector, struct sdiov *iov,
++ int niov)
++{
++ if (sd->hw_version == 0) return do_read(sd, sector, iov, niov);
++ else return do_read2(sd, sector, iov, niov);
++}
++
++int sdwritev(struct sdcore *sd, unsigned int sector, struct sdiov *iov,
++ int niov)
++{
++ if (sd->hw_version == 0) return do_write(sd, sector, iov, niov);
++ else return do_write2(sd, sector, iov, niov);
++}
++
++static
++int sdsetwprot2(struct sdcore *sd, unsigned int perm)
++{
++ int i, ret, s;
++ unsigned int csd[16], resp[6];
++ unsigned char csdchars[16];
++ unsigned char *csdptr = csdchars;
++
++ stop2(sd);
++
++ perm = perm ? 0x3 : 0x1;
++ for (i = 0; i < 16; i++) csd[i] = sd->sd_csd[i + 1];
++ csd[14] &= ~(0x3 << 4);
++ csd[14] |= (perm << 4);
++ csd[15] = 0x1 | crc7(0, csd, 15) << 1;
++ for (i = 0; i < 16; i++) csdchars[i] = csd[i];
++
++ ret = sdcmd2(sd, CMD_PROGRAM_CSD, 0, resp, NULL);
++ if (ret || error(resp, CMD_PROGRAM_CSD)) return 1;
++ for (i = 0; i < 16; i++) {
++ s = *csdptr++;
++ sd_4bit_feedcrc(sd, s);
++ SDPOKE8(sd, SDGPIO, (0x10|((s & 0xf0) >> 4)));
++ SDPEEK8(sd, SDGPIO);
++ SDPEEK8(sd, SDGPIO);
++ SDPOKE8(sd, SDGPIO, (0x30|((s & 0xf0) >> 4)));
++ SDPEEK8(sd, SDGPIO);
++ SDPOKE8(sd, SDGPIO, (0x10|(s & 0xf)));
++ SDPEEK8(sd, SDGPIO);
++ SDPEEK8(sd, SDGPIO);
++ SDPOKE8(sd, SDGPIO, (0x30|(s & 0xf)));
++ SDPEEK8(sd, SDGPIO);
++ }
++ for (i = 0; i < 8; i++) {
++ s = sd_4bit_getcrc(sd);
++ SDPOKE8(sd, SDGPIO, (0x10|((s & 0xf0) >> 4)));
++ SDPEEK8(sd, SDGPIO);
++ SDPEEK8(sd, SDGPIO);
++ SDPOKE8(sd, SDGPIO, (0x30|((s & 0xf0) >> 4)));
++ SDPEEK8(sd, SDGPIO);
++ SDPOKE8(sd, SDGPIO, (0x10|(s & 0xf)));
++ SDPEEK8(sd, SDGPIO);
++ SDPEEK8(sd, SDGPIO);
++ SDPOKE8(sd, SDGPIO, (0x30|(s & 0xf)));
++ SDPEEK8(sd, SDGPIO);
++ }
++ // End bit
++ SDPOKE8(sd, SDGPIO, 0x1f);
++ SDPEEK8(sd, SDGPIO);
++ SDPEEK8(sd, SDGPIO);
++ SDPOKE8(sd, SDGPIO, 0x3f);
++ SDPEEK8(sd, SDGPIO);
++ SDPOKE8(sd, SDGPIO, 0xbf); // tristate dat
++ // CRC ack
++ s = 0;
++ for (i = 0; i < 7; i++) {
++ SDPOKE8(sd, SDGPIO, 0x9f); // clk negedge
++ SDPEEK8(sd, SDGPIO); // delay
++ s = s << 1;
++ s |= (SDPEEK8(sd, SDGPIO) & 0x1);
++ SDPOKE8(sd, SDGPIO, 0xbf); // clk posedge
++ }
++ if ((s & 0xf) != 0x5) return 1;
++ // wait for unbusy
++ s = 0;
++ while ((s & 0x7) != 0x7) {
++ if (timeout(sd)) break;
++ SDPOKE8(sd, SDGPIO, 0x9f); // clk negedge
++ SDPEEK8(sd, SDGPIO); // delay
++ s = s << 1;
++ s |= SDPEEK8(sd, SDGPIO) & 0x1;
++ SDPOKE8(sd, SDGPIO, 0xbf);
++ }
++ for (i = 0; i < 8; i++) {
++ SDPOKE8(sd, SDGPIO, 0x9f);
++ SDPEEK8(sd, SDGPIO);
++ SDPEEK8(sd, SDGPIO);
++ SDPOKE8(sd, SDGPIO, 0xbf);
++ SDPEEK8(sd, SDGPIO);
++ }
++ sd->sd_state &= ~SDDAT_TX;
++
++ sdcmd2(sd, CMD_DESELECT_CARD, ~sd->sd_rcaarg, NULL, NULL);
++ ret = sdcmd2(sd, CMD_SEND_CSD, sd->sd_rcaarg, sd->sd_csd, NULL);
++ if (ret || sd->sd_csd[15] != csd[14]) {
++ return 1;
++ }
++ sdcmd2(sd, CMD_SELECT_CARD, sd->sd_rcaarg, resp, NULL);
++
++ sd->sd_wprot = 1;
++ return 0;
++}
++
++int sdsetwprot(struct sdcore *sd, unsigned int perm)
++{
++ int i, ret;
++ unsigned int csd[16], resp[6];
++ unsigned char csdchars[16];
++ unsigned char *csdptr = csdchars;
++
++ if (sd->hw_version) return sdsetwprot2(sd, perm);
++
++ if (stop(sd)) return 1;
++
++ perm = perm ? 0x3 : 0x1;
++ for (i = 0; i < 16; i++) csd[i] = sd->sd_csd[i + 1];
++ csd[14] &= ~(0x3 << 4);
++ csd[14] |= (perm << 4);
++ csd[15] = 0x1 | crc7(0, csd, 15) << 1;
++ for (i = 0; i < 16; i++) csdchars[i] = csd[i];
++
++ ret = sdcmd(sd, CMD_PROGRAM_CSD, 0, resp, NULL);
++ if (ret || error(resp, CMD_PROGRAM_CSD)) return 1;
++ datssp_stream(sd, &csdptr, 16);
++ datssp_stream(sd, NULL, 8);
++ SDPOKE8(sd, SDSTATE, S_CRC_CHECK | (TYPE_BSYRESP << 5));
++ sd->sd_state &= ~SDDAT_TX;
++
++ sdcmd(sd, CMD_DESELECT_CARD, ~sd->sd_rcaarg, NULL, NULL);
++ ret = sdcmd(sd, CMD_SEND_CSD, sd->sd_rcaarg, sd->sd_csd, NULL);
++ if (ret || sd->sd_csd[15] != csd[14]) {
++ return 1;
++ }
++ sdcmd(sd, CMD_SELECT_CARD, sd->sd_rcaarg, resp, NULL);
++
++ sd->sd_wprot = 1;
++ return 0;
++}
++
++#ifndef SD_NOLOCKSUPPORT
++int sdlockctl(struct sdcore *sd, unsigned int cmd, unsigned char *pwd,
++ unsigned char *sdbootdat)
++{
++ unsigned char pwddat[18];
++ unsigned char *pwdptr = pwddat;
++ unsigned int resp[6];
++ int ret, i, len;
++ int ccc = (sd->sd_csd[5] << 4) | (sd->sd_csd[6] >> 4);
++
++ if (sd->hw_version) return sdlockctl2(sd, cmd, pwd, sdbootdat);
++
++ if (!(ccc & 0x80)) return 1; // Class 7 is lock-unlock commands
++
++ if (pwd == NULL && cmd != SDLOCK_ERASE) return 1;
++
++ if (stop(sd)) return 1;
++
++ if (sd->sd_state & DATSSP_4BIT) {
++ int oldctrl = SDPEEK8(sd, SDCTRL);
++ int ret;
++
++ sdcmd(sd, CMD_APP_CMD, sd->sd_rcaarg, NULL, NULL);
++ sdcmd(sd, ACMD_SET_BUS_WIDTH, 0, NULL, NULL);
++ SDPOKE8(sd, SDCTRL, 0x20);
++ sd->sd_state &= ~DATSSP_4BIT;
++ ret = sdlockctl(sd, cmd, pwd, sdbootdat);
++ sdcmd(sd, CMD_APP_CMD, sd->sd_rcaarg, NULL, NULL);
++ sdcmd(sd, ACMD_SET_BUS_WIDTH, 2, NULL, NULL);
++ sd->sd_state |= DATSSP_4BIT;
++ SDPOKE8(sd, SDCTRL, oldctrl);
++ return ret;
++ }
++
++ pwddat[0] = cmd;
++ if (cmd != SDLOCK_ERASE) {
++ pwddat[1] = 16; // length
++ for (i = 0; i < 16; i++) {
++ pwddat[2 + i] = pwd[i];
++ }
++ }
++
++ if (cmd == SDLOCK_ERASE) len = 1; else len = 18;
++ ret = sdcmd(sd, CMD_SET_BLOCKLEN, len, resp, NULL);
++ if (ret || error(resp, CMD_SET_BLOCKLEN)) return 1;
++ ret = sdcmd(sd, CMD_LOCK_UNLOCK, 0, resp, NULL);
++ if (ret || error(resp, CMD_LOCK_UNLOCK)) return 1;
++
++ while ((pwdptr - pwddat) != len) {
++ if (timeout(sd)) return 1;
++ tend_ssp(sd, NULL, &pwdptr);
++ }
++
++ if (sd->sd_state & DATSSP_4BIT) datssp_stream(sd, NULL, 8);
++ else datssp_stream(sd, NULL, 2);
++
++ SDPOKE8(sd, SDSTATE, S_CRC_CHECK | (TYPE_BSYRESP << 5));
++ sd->sd_state &= ~SDDAT_TX;
++ ret = sdcmd(sd, CMD_SET_BLOCKLEN, 512, resp, NULL);
++ if (ret || error(resp, CMD_SET_BLOCKLEN)) return 1;
++ ret = sdcmd(sd, CMD_SEND_STATUS, sd->sd_rcaarg, resp, NULL);
++ if (ret || error(resp, CMD_SEND_STATUS)) return 1;
++
++ if ((cmd == SDLOCK_ERASE || cmd == SDLOCK_UNLOCK ||
++ cmd == SDLOCK_CLRPWD) && (resp[1] & 0x2)) {
++ return 1;
++ }
++
++ if (sdbootdat) {
++ sdbootdat[0] = SDLOCK_UNLOCK;
++ for (i = 1; i < 18; i++) {
++ sdbootdat[i] = pwddat[i];
++ sd_1bit_feedcrc(sd, pwddat[i]);
++ }
++ sdbootdat[18] = sd_1bit_getcrc(sd);
++ sdbootdat[19] = sd_1bit_getcrc(sd);
++ }
++
++ return 0;
++}
++
++static
++int sdlockctl2(struct sdcore *sd, unsigned int cmd, unsigned char *pwd,
++ unsigned char *sdbootdat)
++{
++ unsigned char pwddat[18];
++ unsigned char *pwdptr = pwddat;
++ unsigned int resp[6];
++ int ret, i, j, len, s;
++ int ccc = (sd->sd_csd[5] << 4) | (sd->sd_csd[6] >> 4);
++
++ if (!(ccc & 0x80)) return 1; // Class 7 is lock-unlock commands
++
++ if (pwd == NULL && cmd != SDLOCK_ERASE) return 1;
++
++ stop2(sd);
++
++ if (sd->sd_state & DATSSP_4BIT) {
++ int ret;
++
++ sdcmd2(sd, CMD_APP_CMD, sd->sd_rcaarg, NULL, NULL);
++ sdcmd2(sd, ACMD_SET_BUS_WIDTH, 0, NULL, NULL);
++ sd->sd_state &= ~DATSSP_4BIT;
++ ret = sdlockctl2(sd, cmd, pwd, sdbootdat);
++ sdcmd2(sd, CMD_APP_CMD, sd->sd_rcaarg, NULL, NULL);
++ sdcmd2(sd, ACMD_SET_BUS_WIDTH, 2, NULL, NULL);
++ sd->sd_state |= DATSSP_4BIT;
++ return ret;
++ }
++
++ pwddat[0] = cmd;
++ if (cmd != SDLOCK_ERASE) {
++ pwddat[1] = 16; // length
++ for (i = 0; i < 16; i++) {
++ pwddat[2 + i] = pwd[i];
++ }
++ }
++
++ if (cmd == SDLOCK_ERASE) len = 1; else len = 18;
++ ret = sdcmd2(sd, CMD_SET_BLOCKLEN, len, resp, NULL);
++ if (ret || error(resp, CMD_SET_BLOCKLEN)) return 1;
++ ret = sdcmd2(sd, CMD_LOCK_UNLOCK, 0, resp, NULL);
++ if (ret || error(resp, CMD_LOCK_UNLOCK)) return 1;
++
++ for (i = 0; i < len; i++) {
++ unsigned int b = *pwdptr++;
++ unsigned int x;
++
++ sd_1bit_feedcrc(sd, b);
++ for (j = 0; j < 8; j++) {
++ x = 0x1e | ((b >> 7) & 0x1);
++ b = b << 1;
++ SDPOKE8(sd, SDGPIO, x); // clk negedge
++ SDPEEK8(sd, SDGPIO);
++ SDPEEK8(sd, SDGPIO);
++ x |= 0x20;
++ SDPOKE8(sd, SDGPIO, x); // clk posedge
++ SDPEEK8(sd, SDGPIO);
++ }
++ }
++ for (i = 0; i < 2; i++) {
++ unsigned int b = sd_1bit_getcrc(sd);
++ unsigned int x;
++
++ for (j = 0; j < 8; j++) {
++ x = 0x1e | ((b >> 7) & 0x1);
++ b = b << 1;
++ SDPOKE8(sd, SDGPIO, x); // clk negedge
++ SDPEEK8(sd, SDGPIO);
++ SDPEEK8(sd, SDGPIO);
++ x |= 0x20;
++ SDPOKE8(sd, SDGPIO, x); // clk posedge
++ SDPEEK8(sd, SDGPIO);
++ }
++ }
++ // End bit
++ SDPOKE8(sd, SDGPIO, 0x1f); // clk negedge
++ SDPEEK8(sd, SDGPIO);
++ SDPOKE8(sd, SDGPIO, 0xbf); // clk posedge, tristate dat
++ // CRC ack
++ s = 0;
++ for (i = 0; i < 7; i++) {
++ SDPOKE8(sd, SDGPIO, 0x9f); // clk negedge
++ SDPEEK8(sd, SDGPIO); // delay
++ s = s << 1;
++ s |= SDPEEK8(sd, SDGPIO) & 0x1;
++ SDPOKE8(sd, SDGPIO, 0xbf); // clk posedge
++ SDPEEK8(sd, SDGPIO);
++ }
++ if ((s & 0xf) != 0x5) return 1;
++
++ // wait for unbusy
++ s = 0;
++ while ((s & 0x7) != 0x7) {
++ if (timeout(sd)) break;
++ SDPOKE8(sd, SDGPIO, 0x9f); // clk negedge
++ SDPEEK8(sd, SDGPIO); // delay
++ s = s << 1;
++ s |= SDPEEK8(sd, SDGPIO) & 0x1;
++ SDPOKE8(sd, SDGPIO, 0xbf);
++ SDPEEK8(sd, SDGPIO);
++ }
++ for (i = 0; i < 8; i++) {
++ SDPOKE8(sd, SDGPIO, 0x9f);
++ SDPEEK8(sd, SDGPIO);
++ SDPEEK8(sd, SDGPIO);
++ SDPOKE8(sd, SDGPIO, 0xbf);
++ SDPEEK8(sd, SDGPIO);
++ }
++
++ sd->sd_state &= ~SDDAT_TX;
++ ret = sdcmd2(sd, CMD_SET_BLOCKLEN, 512, resp, NULL);
++ if (ret || error(resp, CMD_SET_BLOCKLEN)) {
++ return 1;
++ }
++ ret = sdcmd2(sd, CMD_SEND_STATUS, sd->sd_rcaarg, resp, NULL);
++ if (ret || error(resp, CMD_SEND_STATUS)) {
++ return 1;
++ }
++
++ if ((cmd == SDLOCK_ERASE || cmd == SDLOCK_UNLOCK ||
++ cmd == SDLOCK_CLRPWD) && (resp[1] & 0x2)) {
++ return 1;
++ }
++
++ if (sdbootdat) {
++ sdbootdat[0] = SDLOCK_UNLOCK;
++ for (i = 1; i < 18; i++) {
++ sdbootdat[i] = pwddat[i];
++ sd_1bit_feedcrc(sd, pwddat[i]);
++ }
++ sdbootdat[18] = sd_1bit_getcrc(sd);
++ sdbootdat[19] = sd_1bit_getcrc(sd);
++ }
++
++ for (i = 0; i < 8; i++) {
++ SDPOKE8(sd, SDGPIO, 0x9f);
++ SDPEEK8(sd, SDGPIO);
++ SDPEEK8(sd, SDGPIO);
++ SDPOKE8(sd, SDGPIO, 0xbf);
++ SDPEEK8(sd, SDGPIO);
++ }
++ return 0;
++}
++#endif
+diff --git a/drivers/block/sdcore2.h b/drivers/block/sdcore2.h
+new file mode 100644
+index 0000000..38d5b96
+--- /dev/null
++++ b/drivers/block/sdcore2.h
+@@ -0,0 +1,372 @@
++/*
++ * Copyright (c) 2006-2008, Technologic Systems
++ * All rights reserved.
++ */
++
++#ifndef _SDCORE_H_
++#define _SDCORE_H_
++
++// Additional missing defs
++#define SDCMD 0 // cmd register
++#define SDDAT 1 // data register
++#define SDSTATE 2 // state register
++#define SDCTRL 3 // ctrl register
++
++
++// this bit is set when no card inserted
++#define SDCTRL_CARD_ABSENT 0x08
++
++
++
++/* public bits for sd_state bitfield, can be read from client code.
++ * Do not write! Other bits are used internally.
++ */
++#define SDDAT_RX (1<<0)
++#define SDDAT_TX (1<<1)
++#define SDCMD_RX (1<<2)
++#define SDCMD_TX (1<<3)
++
++// used to disable CRC calculations in write mode
++#define SDCRC_DISABLE (1 << 4)
++
++
++
++// used to choose between 4 bit crc mode and 1 bit crc mode
++
++// note - likely set in sdreset when configuring interface bit width
++#define SDSSP_4BIT_MODE (1 << 5)
++
++// SD_ADDRESSING_DIRECT means that sd card addresses
++// will be communicated in read/write mode using
++// full offsets, not 512 byte block offsets.
++// the core will mulitply the address by 512 if this
++// bit is cleared
++#define SD_ADDRESSING_DIRECT (1 << 6)
++
++
++/* These structs should start intialized to all 0's (bzero()'ed). Proper
++ * operation can be assured by setting sd_regstart, and the os_delay
++ * callback. sdreset() should be called to initialize the core, then
++ * sdread() and sdwrite() can be used.
++ */
++struct sdcore {
++ /* virtual address of SD block register start, to be filled in
++ * by client code before calling any sdcore functions.
++ */
++ // 0-3
++ unsigned char* sd_regstart;
++
++
++
++ // 4-7
++ unsigned int sd_state;
++
++ /* Erase hint for subsequent sdwrite() call, used to optimize
++ * write throughput on multi-sector writes by pre-erasing this
++ * many sectors.
++ */
++ // 8-11
++ unsigned int sd_erasehint;
++
++ /* Following this comment are 5 function pointer declarations to
++ * OS helper functions. The 'os_arg' member is passed as the
++ * first argument to the helpers and should be set by
++ * client code before issueing sdreset()
++ *
++ * os_dmastream(os_arg, buf, buflen)
++ * This function should look at sd_state and set up and run an
++ * appropriate DMA transfer. If buf is NULL, callee doesn't care
++ * about the actual data sent/received and helper function
++ * can do whatever it wants. Should return 0 when DMA transfer was
++ * run and completed successfully. If this function pointer is
++ * NULL, PIO methods of transfer will be used instead of DMA.
++ *
++ * os_dmaprep(os_arg, buf, buflen)
++ * This function is used to prepare an area of memory for a possible
++ * DMA transfer. This function is called once per distinct buffer
++ * passed in. After this function is called, os_dmastream() may be
++ * called one or more times (for sequential addresses) on subregions
++ * of the address range passed here. Should write-back or invalidate
++ * L1 cache lines and possibly look up physical addresses for buf
++ * passed in if I/O buffers. If 'os_dmaprep' is set to NULL, function
++ * call will not happen. (though os_dmastream() calls may still)
++ *
++ * os_delay(os_arg, microseconds)
++ * This function is supposed to delay or stall the processor for
++ * the passed in value number of microseconds.
++ *
++ * os_irqwait(os_arg, type)
++ * Called at certain times to request to be put to sleep/block until
++ * an SD interrupt occurs. It is not critical to set this function.
++ * When NULL, the sdcore routines simply busy-wait.
++ *
++ * os_powerok(os_arg)
++ * Experimental callback function -- set to NULL for now.
++ */
++ // 12-15
++ void *os_arg;
++ // 16-19
++ int (*os_dmastream)(void *, unsigned char *, unsigned int);
++ // 20-23
++ void (*os_dmaprep)(void *, unsigned char *, unsigned int);
++ // 24-27
++ void (*os_delay)(void *, unsigned int);
++ // 28-31
++ void (*os_irqwait)(void *, unsigned int);
++ // 32-35
++ int (*os_powerok)(void *);
++
++ int (*os_timeout)(void *);
++ int (*os_reset_timeout)(void *);
++
++ /* If the SD card last successfully reset is write protected, this
++ * member will be non-zero.
++ */
++ // 36-39
++ unsigned int sd_wprot;
++
++ /* If this card may have been already initialized by TS-SDBOOT, place
++ * the magic token it placed in the EP93xx SYSCON ScratchReg1 here
++ * before calling sdreset() to avoid re-initialization.
++ */
++ // 40-43
++ unsigned int sdboot_token;
++
++ /* CRC hint for subsequent sdwrite() call, used to optimize
++ * write throughput while using DMA by pre-calculating CRC's for
++ * next write. NULL means no hint supplied.
++ */
++ // 44-47
++ unsigned char *sd_crchint;
++
++ /* The block size of the memory device. Normally 512, but can be 1024
++ * for larger cards. Read-only member and actually not very useful.
++ */
++ // 48-51
++ unsigned int sd_blocksize;
++
++ /* Password for auto-unlocking in sdreset()
++ */
++ // 52-55
++ unsigned char *sd_pwd;
++
++ /* If the SD card was password locked, this will be non-zero after
++ * unsuccessful sdreset().
++ */
++ // 56-59
++ unsigned int sd_locked;
++
++ /* Whether or not writes can be parked. Definitely should be set to 1
++ * as writes are very slow without it.
++ */
++ // 60-63
++ unsigned int sd_writeparking;
++
++ /* Logical unit number. Some SD cores will have multiple card slots.
++ * LUN #0 is the first.
++ */
++ // 64-67
++ unsigned int sd_lun;
++
++ /* The rest of these members are for private internal use and should
++ * not be of interest to client code.
++ */
++
++
++ // 68-71
++ unsigned int rca; // relative card address
++
++
++ unsigned int sd_csd[17];
++ /*
++
++
++ // 72 -75 0
++ unsigned int unknown72; // one of the csds?
++
++ // 76 -79 1
++ unsigned int unknown76; // csd 0x00
++ // 80 -83 2
++ unsigned int unknown04; // csd 0x01
++ // 84 - 87 3
++ unsigned int unknown05; // csd 0x02
++ // 88 - 91 4
++ unsigned int unknown06; // csd 0x03
++ // 92 - 95 5
++ unsigned int unknown92; // csd 0x04
++ // 96 - 100 6
++ unsigned int unknown96; // csd 0x05
++ // 100 - 103 7
++ unsigned int unknown100; // csd 0x06
++ // 104 - 107 8
++ unsigned int unknown104; // csd 0x07
++ // 108 - 111 9
++ unsigned int unknown108; // csd 0x08
++ // 112 - 115 10
++ unsigned int unknown112; // csd 0x09
++ // 116 - 119 11
++ unsigned int unknown116; // csd 0x0a
++ // 120 12
++ unsigned int unknown24; // csd 0x0b
++ // 124 13
++ unsigned int unknown25; // csd 0x0c
++ // 128 14
++ unsigned int unknown26; // csd 0x0d
++ // 132 15
++ unsigned int unknown132; // csd 0x0e
++ // 136 16
++ unsigned int unknown28; // csd 0x0f
++ */
++
++
++ // 140
++ unsigned int sd_crc_shift;
++
++ // 144 + 4 + 4
++ unsigned short s_crc_table[4]; // 4 shorts
++ // 152 + 4 + 4 + 4 + 4
++ unsigned int l_crc_table[4]; // 4 longs
++
++ // 168
++ unsigned int sd_timeout; // used to busy wait
++
++ // 172
++ unsigned int sd_cur_sector; // stop indicator - if zero , then stop procedure will be skipped
++
++ // 176
++ unsigned int sdcore_version; // hardware version
++ // 180
++ unsigned int unknown39;
++ // 184
++ unsigned int unknown40;
++ // 188
++ unsigned int sdcore_sdsize;
++
++
++
++ unsigned int unknown42;
++ unsigned int unknown43;
++ unsigned int unknown44;
++ unsigned int unknown45;
++ unsigned int unknown46;
++ unsigned int unknown47;
++
++
++
++
++
++
++
++
++
++
++
++
++
++};
++
++/* I believe sdcores is a table mapping
++ id -> sdcore struct. The table is
++ 64 long, meaning that one could build a ts device with
++ 64 sdcores on it.
++*/
++//extern unsigned char sdcores[256];
++
++
++
++
++/* For sdreadv() / sdwritev() */
++struct sdiov {
++ unsigned char *sdiov_base;
++ unsigned int sdiov_nsect;
++};
++
++
++
++
++int sdreset(struct sdcore *);
++
++int sdsize(struct sdcore* sdcore);
++
++
++int sdread(struct sdcore* sdcore,
++ unsigned int sector,
++ unsigned char* buffer,
++ int nsect);
++
++int sdwrite(struct sdcore *, unsigned int, unsigned char *, int);
++
++
++// same signature as do_read
++int do_read(struct sdcore*, unsigned int, struct sdiov*, int);
++int sdreadv(struct sdcore * sdcore,
++ unsigned int sector,
++ struct sdiov * sdiov,
++ int nsdiov);
++
++// same signature as do_write
++int do_write(struct sdcore* sdcore,
++ unsigned int sector,
++ struct sdiov* sdiov,
++ int nsdiov);
++
++int sdwritev(struct sdcore *, unsigned int, struct sdiov *, int);
++
++
++void sd_1bit_feedcrc(struct sdcore*, unsigned int);
++void sd_4bit_feedcrc(struct sdcore*, unsigned int);
++
++unsigned char sd_1bit_getcrc(struct sdcore*);
++unsigned char sd_4bit_getcrc(struct sdcore*);
++
++/** stop takes only sdcore parameters */
++int stop(struct sdcore*);
++
++
++int tend_ssp(struct sdcore* sdcore,
++ unsigned int** unknown_r1, // r1
++ unsigned char** unknown_r2);
++
++
++int datssp_stream(struct sdcore* sdcore,
++ unsigned char** data,
++ int count);
++
++/*
++ * @param cmd is the command - I believe that the lower byte is the command, and
++ * the upper one is the crc
++ *
++ * @param data is a character buffer for data received in the ssp dat register, as
++ * a result of a command execution.
++ */
++
++int sdcmd(struct sdcore* sdcore,
++ unsigned short cmd,
++ unsigned int sdargs,
++ unsigned int* response,
++ unsigned char** data); // command response buffer?
++
++
++/**
++ * Error tests if a sdcommand error has been received.
++ * It does this by checking that the command was
++ * correctly returned by the card (the first byte in buffer),
++ * and that a CRC error has not occurred. IF one has occurred
++ * it will attempt a 1bit fix. (suspected)
++ */
++int error(unsigned int* buffer, unsigned int cmd);
++
++
++
++int sdsetwprot(struct sdcore *, unsigned int);
++#define SDLOCK_UNLOCK 0
++#define SDLOCK_SETPWD 1
++#define SDLOCK_CLRPWD 2
++#define SDLOCK_ERASE 8
++
++int sdlockctl(struct sdcore *,
++ unsigned int, // op code
++ unsigned char *,
++ unsigned char *);
++
++#endif
+diff --git a/drivers/block/tssdcard.c b/drivers/block/tssdcard.c
+new file mode 100644
+index 0000000..c76d9a7
+--- /dev/null
++++ b/drivers/block/tssdcard.c
+@@ -0,0 +1,415 @@
++/*
++ * TS SD Card device driver
++ *
++ * (c) Copyright 2010 Matthieu Crapet <mcrapet@gmail.com>
++ * Based on Technologic Systems & Breton M. Saunders work
++ *
++ * 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.
++ *
++ * Notes:
++ * - request processing method is: no request queue
++ * - no M2M DMA is used
++ */
++
++#include <linux/kernel.h>
++#include <linux/init.h>
++#include <linux/module.h>
++#include <linux/moduleparam.h>
++#include <linux/major.h>
++#include <linux/blkdev.h>
++#include <linux/bio.h>
++#include <linux/delay.h>
++#include <linux/hdreg.h>
++#include <linux/slab.h>
++#include <linux/platform_device.h>
++
++#include "sdcore2.h"
++
++#define SDCARD_DEV_NAME "tssd" /* will appear in /proc/partitions & /sys/class/block */
++#define SD_SHIFT 4 /* max 16 partitions = 1 << 4 */
++
++#define KERN_SECTOR_SIZE 512 /* in bytes */
++#define HARD_SECTOR_SIZE 512 /* in bytes */
++#define HARD_2_KERN_SECTOR_RATIO 1 /* 1 kernel sector = 1 hardware sector */
++
++
++struct ts72xx_sdcard_device {
++ struct sdcore tssdcore; /* Physical core layer */
++ void __iomem *mmio_base;
++ long size; /* Device size in (hardware) sectors */
++ int id;
++ int media_change;
++ int users;
++
++ spinlock_t lock;
++ struct device *dev;
++ struct request_queue *queue;
++ struct gendisk *disk;
++};
++
++
++/*
++ * Low level function to handle an I/O request
++ */
++static inline int sdcard_ll_transfer(struct ts72xx_sdcard_device *dev,
++ unsigned long sector, unsigned long nsect, char *buffer, int rw)
++{
++ int ret;
++
++ //spin_unlock(&dev->lock); // ???
++
++ if ((sector + nsect) > (dev->size * HARD_2_KERN_SECTOR_RATIO)) {
++ dev_err(dev->dev, "tranfer: beyond-end write (%ld %ld)\n", sector, nsect);
++ //spin_lock(&dev->lock); // ???
++ return -1;
++ }
++
++ switch (rw) {
++ case WRITE:
++ ret = sdwrite(&dev->tssdcore, sector, buffer, nsect);
++ if (ret && !dev->tssdcore.sd_wprot) {
++ sdreset(&dev->tssdcore);
++ ret = sdwrite(&dev->tssdcore, sector, buffer, nsect);
++ }
++ break;
++
++ case READ:
++ case READA:
++ ret = sdread(&dev->tssdcore, sector, buffer, nsect);
++ if (ret) {
++ // SDCARD RESET may be printed when the core determines that the SD card has
++ // f*ed up.this is not handled correctly yet; and should likely be inside a while loop
++ dev_err(dev->dev, "transfer: SDCARD RESET\n");
++ sdreset(&dev->tssdcore);
++ ret = sdread(&dev->tssdcore, sector, buffer, nsect);
++ }
++ break;
++ }
++
++ //spin_lock(&dev->lock); // ???
++ return 0;
++}
++
++/*
++ * The direct make request version.
++ */
++static int sdcard_make_request(struct request_queue *q, struct bio *bio)
++{
++ struct ts72xx_sdcard_device *dev = q->queuedata;
++
++ struct bio_vec *bvec;
++ sector_t sector;
++ int i, rw;
++ int err = -EIO;
++
++ /* handle bio */
++ sector = bio->bi_sector;
++ rw = bio_rw(bio);
++
++ bio_for_each_segment(bvec, bio, i) {
++ char *buffer = __bio_kmap_atomic(bio, i, KM_USER0);
++ unsigned int len = bvec->bv_len / HARD_SECTOR_SIZE;
++
++ //printk("bvec: len=%d offt=%d page=%p\n", bvec->bv_len, bvec->bv_offset, bvec->bv_page);
++
++ err = sdcard_ll_transfer(dev, sector, len, buffer, rw);
++ if (err)
++ break;
++
++ sector += len;
++ __bio_kunmap_atomic(bio, KM_USER0);
++ }
++ bio_endio(bio, err);
++
++ return 0;
++}
++
++static void sdcard_delay(void *arg, unsigned int us)
++{
++ udelay(us);
++}
++
++static int sdcard_open(struct block_device *bdev, fmode_t mode)
++{
++ struct ts72xx_sdcard_device *dev = bdev->bd_disk->private_data;
++ unsigned long flags;
++
++ dev_dbg(dev->dev, "open() users=%i\n", dev->users + 1);
++
++ spin_lock_irqsave(&dev->lock, flags);
++ dev->users++;
++ spin_unlock_irqrestore(&dev->lock, flags);
++
++ check_disk_change(bdev);
++ return 0;
++};
++
++static int sdcard_release(struct gendisk *disk, fmode_t mode)
++{
++ struct ts72xx_sdcard_device *dev = disk->private_data;
++ unsigned long flags;
++
++ dev_dbg(dev->dev, "release() users=%i\n", dev->users - 1);
++
++ spin_lock_irqsave(&dev->lock, flags);
++ dev->users--;
++ spin_unlock_irqrestore(&dev->lock, flags);
++
++ return 0;
++}
++
++static int sdcard_media_changed(struct gendisk *disk)
++{
++ struct ts72xx_sdcard_device *dev = disk->private_data;
++
++ char buf[HARD_SECTOR_SIZE];
++ dev->media_change = sdread(&dev->tssdcore, 1, buf, 1);
++
++ dev_dbg(dev->dev, "media_changed() %i\n", dev->media_change);
++ return dev->media_change;
++}
++
++static int sdcard_revalidate(struct gendisk *disk)
++{
++ struct ts72xx_sdcard_device *dev = disk->private_data;
++ int ret = 0;
++
++ dev_dbg(dev->dev, "revalidate() %i\n", dev->media_change);
++ if (dev->media_change) {
++ dev->size = sdreset(&dev->tssdcore);
++ set_disk_ro(dev->disk, !!(dev->tssdcore.sd_wprot));
++ if (dev->size > 0) {
++ set_capacity(dev->disk, dev->size * HARD_2_KERN_SECTOR_RATIO);
++ dev->media_change = 0;
++ } else {
++ dev_err(dev->dev, "revalidate() no card found\n");
++ ret = -1;
++ }
++ }
++ return ret;
++}
++
++static int sdcard_getgeo(struct block_device *bdev, struct hd_geometry *geo)
++{
++ struct gendisk *disk = bdev->bd_disk;
++ struct ts72xx_sdcard_device *dev = disk->private_data;
++
++ /* We don't have real geometry info, but let's at least return
++ * values consistent with the size of the device */
++ geo->heads = 16;
++ geo->sectors = 32;
++ geo->cylinders = get_capacity(disk) / (16 * 32);
++
++ dev_dbg(dev->dev, "getgeo() %d heads, %d sectors, %d cylinders\n",
++ geo->heads, geo->sectors, geo->cylinders);
++ return 0;
++}
++
++/*
++ * The device operations structure.
++ */
++static struct block_device_operations ts72xx_sdcard_ops = {
++ .owner = THIS_MODULE,
++ .open = sdcard_open,
++ .release = sdcard_release,
++ .media_changed = sdcard_media_changed,
++ .revalidate_disk = sdcard_revalidate,
++ .getgeo = sdcard_getgeo
++};
++
++static int sdcard_major;
++
++/* ---------------------------------------------------------------------
++ * Device setup
++ */
++
++static int ts72xx_sdcard_setup(const char *name, struct ts72xx_sdcard_device *dev)
++{
++ int rc;
++
++ spin_lock_init(&dev->lock);
++
++ /*
++ * Initialize the request queue
++ */
++ dev->queue = blk_alloc_queue(GFP_KERNEL);
++ if (!dev->queue)
++ goto err_alloc_queue;
++
++ dev->queue->queuedata = dev;
++ blk_queue_make_request(dev->queue, sdcard_make_request);
++ blk_queue_logical_block_size(dev->queue, HARD_SECTOR_SIZE);
++
++ dev->tssdcore.sd_regstart = (unsigned char *)dev->mmio_base;
++ dev->tssdcore.os_arg = dev;
++ dev->tssdcore.os_delay = sdcard_delay;
++ dev->tssdcore.os_dmastream = NULL;
++ dev->tssdcore.os_dmaprep = NULL;
++
++ // don't want to write park
++ dev->tssdcore.sd_writeparking = 1;
++ // I do want to pre-erase blocks - 8 blocks pre-erase
++ dev->tssdcore.sd_erasehint = 8;
++ dev->tssdcore.sdboot_token = 0;
++
++ dev->disk = alloc_disk(1 << SD_SHIFT);
++ if (!dev->disk) {
++ goto err_alloc_disk;
++ }
++
++ dev->disk->major = sdcard_major;
++ dev->disk->first_minor = dev->id << SD_SHIFT;
++ dev->disk->flags = GENHD_FL_REMOVABLE;
++ dev->disk->fops = &ts72xx_sdcard_ops;
++ dev->disk->queue = dev->queue;
++ dev->disk->private_data = dev;
++ snprintf(dev->disk->disk_name, 32, SDCARD_DEV_NAME "%c", dev->id + 'a');
++
++ /* SD Card size and Reset
++ * (set_disk_ro, set_capacity will be called) */
++ dev->media_change = 1;
++ rc = sdcard_revalidate(dev->disk);
++ if (rc) {
++ dev_info(dev->dev, "No SD card detected!\n");
++ goto err_alloc_disk;
++ }
++
++ dev_info(dev->dev, "SD card hardware revision: %08x\n",
++ dev->tssdcore.sdcore_version);
++ dev_info(dev->dev, "block device major number = %d\n",
++ sdcard_major);
++ dev_info(dev->dev, "New SD card detected, name=%s size=%ld (sectors)\n",
++ dev->disk->disk_name, dev->size);
++
++ /* Make the sysace device 'live' */
++ add_disk(dev->disk);
++
++ return 0;
++
++err_alloc_disk:
++ blk_cleanup_queue(dev->queue);
++err_alloc_queue:
++ return -ENOMEM;
++}
++
++
++/* ---------------------------------------------------------------------
++ * Platform drivers functons
++ */
++
++static int __init ts72xx_sdcard_probe(struct platform_device *pdev)
++{
++ struct ts72xx_sdcard_device *dev;
++ struct resource *res;
++ int rc;
++
++ dev = kzalloc(sizeof(struct ts72xx_sdcard_device), GFP_KERNEL);
++ if (!dev) {
++ rc = -ENOMEM;
++ goto fail_no_mem;
++ }
++
++ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
++ if (res == NULL) {
++ rc = -ENXIO;
++ goto fail_no_mem_resource;
++ }
++
++ res = request_mem_region(res->start, resource_size(res), pdev->name);
++ if (res == NULL) {
++ rc = -EBUSY;
++ goto fail_no_mem_resource;
++ }
++
++ dev->mmio_base = ioremap(res->start, resource_size(res));
++ if (dev->mmio_base == NULL) {
++ rc = -ENXIO;
++ goto fail_no_ioremap;
++ }
++
++ dev->dev = &pdev->dev;
++ dev->id = pdev->id;
++ platform_set_drvdata(pdev, dev);
++
++ rc = ts72xx_sdcard_setup(SDCARD_DEV_NAME, dev);
++ if (rc) {
++ dev_err(dev->dev, "ts72xx_sdcard_setup failed\n");
++ goto fail_sdcard_setup;
++ }
++
++ return 0;
++
++fail_sdcard_setup:
++ iounmap(dev->mmio_base);
++fail_no_ioremap:
++ release_mem_region(res->start, resource_size(res));
++fail_no_mem_resource:
++ kfree(dev);
++fail_no_mem:
++ return rc;
++}
++
++static int __exit ts72xx_sdcard_remove(struct platform_device *pdev)
++{
++ struct ts72xx_sdcard_device *dev = platform_get_drvdata(pdev);
++ struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
++
++ platform_set_drvdata(pdev, NULL);
++ iounmap(dev->mmio_base);
++ release_mem_region(res->start, resource_size(res));
++ blk_cleanup_queue(dev->queue);
++ del_gendisk(dev->disk);
++ put_disk(dev->disk);
++ kfree(dev);
++
++ return 0;
++}
++
++static struct platform_driver ts72xx_sdcard_driver = {
++ .driver = {
++ .name = "ts72xx-sdcard",
++ .owner = THIS_MODULE,
++ },
++ .remove = __exit_p(ts72xx_sdcard_remove),
++};
++
++
++/* ---------------------------------------------------------------------
++ * Module init/exit routines
++ */
++
++static int __init ts72xx_sdcard_init(void)
++{
++ int rc;
++
++ sdcard_major = rc = register_blkdev(sdcard_major, SDCARD_DEV_NAME);
++ if (rc <= 0) {
++ printk(KERN_ERR "%s:%u: register_blkdev failed %d\n", __func__,
++ __LINE__, rc);
++ return rc;
++ }
++
++ rc = platform_driver_probe(&ts72xx_sdcard_driver, ts72xx_sdcard_probe);
++ if (rc)
++ unregister_blkdev(sdcard_major, SDCARD_DEV_NAME);
++
++ return rc;
++}
++
++static void __exit ts72xx_sdcard_exit(void)
++{
++ unregister_blkdev(sdcard_major, SDCARD_DEV_NAME);
++ platform_driver_unregister(&ts72xx_sdcard_driver);
++}
++
++module_init(ts72xx_sdcard_init);
++module_exit(ts72xx_sdcard_exit);
++
++MODULE_AUTHOR("Matthieu Crapet <mcrapet@gmail.com>");
++MODULE_DESCRIPTION("TS72xx SD Card block driver");
++MODULE_LICENSE("GPL");
++MODULE_ALIAS_BLOCKDEV_MAJOR(SCSI_DISK0_MAJOR);
++MODULE_ALIAS("tssd");
+--
+1.7.1
+
diff --git a/recipes/linux/linux-2.6.38/ts72xx/0016-ts72xx_spi_tmp124.patch b/recipes/linux/linux-2.6.38/ts72xx/0016-ts72xx_spi_tmp124.patch
new file mode 100644
index 0000000..e66a027
--- /dev/null
+++ b/recipes/linux/linux-2.6.38/ts72xx/0016-ts72xx_spi_tmp124.patch
@@ -0,0 +1,305 @@
+From dbf0756902097a3a2deb7bc3c76650e20fe8730f Mon Sep 17 00:00:00 2001
+From: Matthieu Crapet <mcrapet@gmail.com>
+Date: Tue, 22 Jun 2010 15:48:27 +0200
+Subject: [PATCH 16/24] ts72xx_spi_tmp124
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+It's an option. A 3-wire spi temperature sensor can be populated on TS-72XX sbc.
+
+Signed-off-by: Petr Štetiar <ynezz@true.cz>
+---
+ arch/arm/mach-ep93xx/ts72xx.c | 63 ++++++++++++++++
+ drivers/spi/Kconfig | 7 ++
+ drivers/spi/Makefile | 1 +
+ drivers/spi/tmp124.c | 158 +++++++++++++++++++++++++++++++++++++++++
+ 4 files changed, 229 insertions(+), 0 deletions(-)
+ create mode 100644 drivers/spi/tmp124.c
+
+diff --git a/arch/arm/mach-ep93xx/ts72xx.c b/arch/arm/mach-ep93xx/ts72xx.c
+index 63b2f4f..a209112 100644
+--- a/arch/arm/mach-ep93xx/ts72xx.c
++++ b/arch/arm/mach-ep93xx/ts72xx.c
+@@ -23,7 +23,11 @@
+ #include <linux/gpio.h>
+ #include <linux/i2c.h>
+ #include <linux/i2c-gpio.h>
++#include <linux/mtd/nand.h>
++#include <linux/mtd/partitions.h>
++#include <linux/spi/spi.h>
+
++#include <mach/ep93xx_spi.h>
+ #include <mach/hardware.h>
+ #include <mach/ts72xx.h>
+
+@@ -352,6 +356,60 @@ static struct i2c_gpio_platform_data ts72xx_i2c_gpio_data = {
+ static struct i2c_board_info __initdata ts72xx_i2c_board_info[] = {
+ };
+
++/*************************************************************************
++ * SPI
++ *************************************************************************/
++#if defined(CONFIG_SPI_TMP124) || defined(CONFIG_SPI_TMP124_MODULE)
++
++/* this is our GPIO line used for chip select */
++#define TMP124_CHIP_SELECT_GPIO EP93XX_GPIO_LINE_MCCD2
++
++static int ts72xx_tmp124_setup(struct spi_device *spi)
++{
++ int err;
++
++ err = gpio_request(TMP124_CHIP_SELECT_GPIO, spi->modalias);
++ if (err)
++ return err;
++
++ gpio_direction_output(TMP124_CHIP_SELECT_GPIO, 1);
++
++ return 0;
++}
++
++static void ts72xx_tmp124_cleanup(struct spi_device *spi)
++{
++ gpio_set_value(TMP124_CHIP_SELECT_GPIO, 1);
++ gpio_direction_input(TMP124_CHIP_SELECT_GPIO);
++ gpio_free(TMP124_CHIP_SELECT_GPIO);
++}
++
++static void ts72xx_tmp124_cs_control(struct spi_device *spi, int value)
++{
++ gpio_set_value(TMP124_CHIP_SELECT_GPIO, value);
++}
++
++static struct ep93xx_spi_chip_ops ts72xx_tmp124_ops = {
++ .setup = ts72xx_tmp124_setup,
++ .cleanup = ts72xx_tmp124_cleanup,
++ .cs_control = ts72xx_tmp124_cs_control,
++};
++
++static struct spi_board_info ts72xx_spi_devices[] = {
++ {
++ .modalias = "tmp124",
++ .max_speed_hz = 2 * 1000 * 1000,
++ .bus_num = 0,
++ .chip_select = 0,
++ .controller_data = &ts72xx_tmp124_ops,
++ },
++};
++
++static struct ep93xx_spi_info ts72xx_spi_info = {
++ .num_chipselect = ARRAY_SIZE(ts72xx_spi_devices),
++};
++#endif
++
+ static void __init ts72xx_init_machine(void)
+ {
+ ep93xx_init_devices();
+@@ -365,6 +423,11 @@ static void __init ts72xx_init_machine(void)
+ ts72xx_i2c_board_info,
+ ARRAY_SIZE(ts72xx_i2c_board_info));
+
++ #if defined(CONFIG_SPI_TMP124) || defined(CONFIG_SPI_TMP124_MODULE)
++ ep93xx_register_spi(&ts72xx_spi_info, ts72xx_spi_devices,
++ ARRAY_SIZE(ts72xx_spi_devices));
++ #endif
++
+ if (is_max197_installed()) {
+ platform_device_register(&ts72xx_max197_device);
+ }
+diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
+index bb233a9..069c0fe 100644
+--- a/drivers/spi/Kconfig
++++ b/drivers/spi/Kconfig
+@@ -428,6 +428,13 @@ config SPI_TLE62X0
+ sysfs interface, with each line presented as a kind of GPIO
+ exposing both switch control and diagnostic feedback.
+
++config SPI_TMP124
++ tristate "Texas Instruments TMP1224, TMP124"
++ depends on SPI_MASTER && SYSFS
++ help
++ SPI driver for TMP12X temperature sensor chips.
++ This provides a sysfs entry for temperature reading (2�C accurate).
++
+ #
+ # Add new SPI protocol masters in alphabetical order above this line
+ #
+diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile
+index 86d1b5f..57d7abc 100644
+--- a/drivers/spi/Makefile
++++ b/drivers/spi/Makefile
+@@ -60,6 +60,7 @@ spi_s3c24xx_hw-$(CONFIG_SPI_S3C24XX_FIQ) += spi_s3c24xx_fiq.o
+ # SPI protocol drivers (device/link on bus)
+ obj-$(CONFIG_SPI_SPIDEV) += spidev.o
+ obj-$(CONFIG_SPI_TLE62X0) += tle62x0.o
++obj-$(CONFIG_SPI_TMP124) += tmp124.o
+ # ... add above this line ...
+
+ # SPI slave controller drivers (upstream link)
+diff --git a/drivers/spi/tmp124.c b/drivers/spi/tmp124.c
+new file mode 100644
+index 0000000..e41ec8c
+--- /dev/null
++++ b/drivers/spi/tmp124.c
+@@ -0,0 +1,158 @@
++/*
++ * TMP124 SPI protocol driver
++ *
++ * (c) Copyright 2008-2010 Matthieu Crapet <mcrapet@gmail.com>
++ * Based on tle62x0.c by Ben Dooks, <ben@simtec.co.uk>
++ *
++ * 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.
++ *
++ * Note: The chip uses a '3-wire SPI' (miso and mosi are the same pin).
++ */
++
++#include <linux/module.h>
++#include <linux/kernel.h>
++#include <linux/init.h>
++#include <linux/spi/spi.h>
++#include <linux/slab.h>
++#include <linux/sched.h>
++
++struct tmp124_state {
++ struct spi_device *bus;
++ u8 tx_buff[2];
++ u8 rx_buff[2];
++};
++
++static inline int tmp124_write_then_read(struct tmp124_state *st)
++{
++ struct spi_message msg;
++ struct spi_transfer xfer[2] = {
++ {
++ .tx_buf = st->tx_buff,
++ .rx_buf = NULL,
++ .len = 2,
++ }, {
++ .tx_buf = NULL,
++ .rx_buf = st->rx_buff,
++ .len = 2,
++ }
++ };
++
++ spi_message_init(&msg);
++ spi_message_add_tail(&xfer[0], &msg);
++ spi_sync(st->bus, &msg);
++
++ /* SPI_3WIRE is not handled by ep93xx_spi, the 2 messages must be
++ * splitted. We must wait to not confuse driver with read/write. */
++ schedule_timeout(usecs_to_jiffies(1000));
++
++ spi_message_init(&msg);
++ spi_message_add_tail(&xfer[1], &msg);
++ return spi_sync(st->bus, &msg);
++}
++
++static ssize_t tmp124_temperature_show(struct device *dev,
++ struct device_attribute *attr, char *buf)
++{
++ struct tmp124_state *st = dev_get_drvdata(dev);
++ int ret;
++
++ ((short *)st->tx_buff)[0] = 0x8000;
++
++ ret = tmp124_write_then_read(st);
++ if (ret < 0) {
++ dev_err(&st->bus->dev, "tmp124_write_then_read\n");
++ ret = 0;
++ } else {
++ signed long val = ((short *)st->rx_buff)[0];
++
++ val = val >> 3;
++
++ /* 2 digit precision (0.0625*100) */
++ val = (val * 50) / 8;
++ ret = snprintf(buf, PAGE_SIZE, "%ld.%02ld\n", val/100, abs(val%100));
++ }
++ return ret;
++}
++
++static DEVICE_ATTR(temperature, S_IRUGO, tmp124_temperature_show, NULL);
++
++static int __devinit tmp124_probe(struct spi_device *spi)
++{
++ struct tmp124_state *st;
++ int ret;
++
++ st = kzalloc(sizeof(struct tmp124_state), GFP_KERNEL);
++ if (st == NULL) {
++ dev_err(&spi->dev, "no memory for device state\n");
++ return -ENOMEM;
++ }
++
++ /* required config */
++ spi->bits_per_word = 16;
++ spi->mode = SPI_MODE_0;
++
++ ret = spi_setup(spi);
++ if (ret) {
++ dev_err(&spi->dev, "setup device\n");
++ goto err;
++ }
++
++ ret = device_create_file(&spi->dev, &dev_attr_temperature);
++ if (ret) {
++ dev_err(&spi->dev, "cannot create temperature attribute\n");
++ goto err;
++ }
++
++ st->bus = spi;
++ spi_set_drvdata(spi, st);
++ return 0;
++
++err:
++ kfree(st);
++ return ret;
++}
++
++static int __devexit tmp124_remove(struct spi_device *spi)
++{
++ struct tmp124_state *st = spi_get_drvdata(spi);
++
++ device_remove_file(&spi->dev, &dev_attr_temperature);
++ kfree(st);
++ return 0;
++}
++
++static struct spi_driver tmp124_driver = {
++ .driver = {
++ .name = "tmp124",
++ .owner = THIS_MODULE,
++ },
++ .probe = tmp124_probe,
++ .remove = __devexit_p(tmp124_remove),
++};
++
++static __init int tmp124_init(void)
++{
++ return spi_register_driver(&tmp124_driver);
++}
++
++static __exit void tmp124_exit(void)
++{
++ spi_unregister_driver(&tmp124_driver);
++}
++
++module_init(tmp124_init);
++module_exit(tmp124_exit);
++
++MODULE_AUTHOR("Matthieu Crapet <mcrapet@gmail.com>");
++MODULE_DESCRIPTION("TMP124 SPI Protocol Driver");
++MODULE_LICENSE("GPL");
++MODULE_ALIAS("spi:tmp124");
++MODULE_VERSION("0.2");
+--
+1.7.1
+
diff --git a/recipes/linux/linux-2.6.38/ts72xx/0017-ts72xx-use-CPLD-watchdog-for-reset.patch b/recipes/linux/linux-2.6.38/ts72xx/0017-ts72xx-use-CPLD-watchdog-for-reset.patch
new file mode 100644
index 0000000..5e0bb70
--- /dev/null
+++ b/recipes/linux/linux-2.6.38/ts72xx/0017-ts72xx-use-CPLD-watchdog-for-reset.patch
@@ -0,0 +1,53 @@
+From 4ad55b5b1684b1f840360fc9cdfafedc09e521fc Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Petr=20=C5=A0tetiar?= <ynezz@true.cz>
+Date: Thu, 21 Oct 2010 20:00:49 +0200
+Subject: [PATCH 17/24] ts72xx: use CPLD watchdog for reset
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+
+Signed-off-by: Petr Štetiar <ynezz@true.cz>
+---
+ arch/arm/mach-ep93xx/include/mach/system.h | 13 +++++++++++++
+ 1 files changed, 13 insertions(+), 0 deletions(-)
+
+diff --git a/arch/arm/mach-ep93xx/include/mach/system.h b/arch/arm/mach-ep93xx/include/mach/system.h
+index 6d661fe..b657a9a 100644
+--- a/arch/arm/mach-ep93xx/include/mach/system.h
++++ b/arch/arm/mach-ep93xx/include/mach/system.h
+@@ -3,6 +3,10 @@
+ */
+
+ #include <mach/hardware.h>
++#ifdef CONFIG_MACH_TS72XX
++#include <linux/io.h>
++#include <mach/ts72xx.h>
++#endif
+
+ static inline void arch_idle(void)
+ {
+@@ -13,11 +17,20 @@ static inline void arch_reset(char mode, const char *cmd)
+ {
+ local_irq_disable();
+
++#ifdef CONFIG_MACH_TS72XX
++ /* It's more reliable to use CPLD watchdog to perform reset */
++ if (board_is_ts7200() || board_is_ts7250() || board_is_ts7260() ||
++ board_is_ts7300() || board_is_ts7400()) {
++ __raw_writeb(0x5, TS72XX_WDT_FEED_PHYS_BASE);
++ __raw_writeb(0x1, TS72XX_WDT_CONTROL_PHYS_BASE);
++ }
++#else
+ /*
+ * Set then clear the SWRST bit to initiate a software reset
+ */
+ ep93xx_devcfg_set_bits(EP93XX_SYSCON_DEVCFG_SWRST);
+ ep93xx_devcfg_clear_bits(EP93XX_SYSCON_DEVCFG_SWRST);
++#endif
+
+ while (1)
+ ;
+--
+1.7.1
+
diff --git a/recipes/linux/linux-2.6.38/ts72xx/0018-ethoc-ts7300-fixes.patch b/recipes/linux/linux-2.6.38/ts72xx/0018-ethoc-ts7300-fixes.patch
new file mode 100644
index 0000000..9e5b12c
--- /dev/null
+++ b/recipes/linux/linux-2.6.38/ts72xx/0018-ethoc-ts7300-fixes.patch
@@ -0,0 +1,72 @@
+From 27e285eed0f3c287c4673da192707fd3a61076ff Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Petr=20=C5=A0tetiar?= <ynezz@true.cz>
+Date: Mon, 14 Mar 2011 00:14:39 +0100
+Subject: [PATCH 18/24] ethoc: ts7300 fixes
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Signed-off-by: Ian Thompson <ian.thompson@pgs.com>
+Signed-off-by: Petr Štetiar <ynezz@true.cz>
+---
+ drivers/net/ethoc.c | 20 ++++++++++++++++++--
+ 1 files changed, 18 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/net/ethoc.c b/drivers/net/ethoc.c
+index b79d7e1..01ec980 100644
+--- a/drivers/net/ethoc.c
++++ b/drivers/net/ethoc.c
+@@ -22,7 +22,11 @@
+ #include <linux/of.h>
+ #include <net/ethoc.h>
+
++#ifndef CONFIG_MACH_TS72XX
+ static int buffer_size = 0x8000; /* 32 KBytes */
++#else
++static int buffer_size = 0x2000; /* 8 KBytes */
++#endif
+ module_param(buffer_size, int, 0);
+ MODULE_PARM_DESC(buffer_size, "DMA buffer allocation size");
+
+@@ -859,10 +863,10 @@ static netdev_tx_t ethoc_start_xmit(struct sk_buff *skb, struct net_device *dev)
+ bd.stat &= ~TX_BD_PAD;
+
+ dest = priv->vma[entry];
+- memcpy_toio(dest, skb->data, skb->len);
++ memcpy_toio(dest, skb->data, skb->len + 2);
+
+ bd.stat &= ~(TX_BD_STATS | TX_BD_LEN_MASK);
+- bd.stat |= TX_BD_LEN(skb->len);
++ bd.stat |= TX_BD_LEN(skb->len + 2);
+ ethoc_write_bd(priv, entry, &bd);
+
+ bd.stat |= TX_BD_READY;
+@@ -1049,6 +1053,17 @@ static int __devinit ethoc_probe(struct platform_device *pdev)
+ if (!is_valid_ether_addr(netdev->dev_addr))
+ random_ether_addr(netdev->dev_addr);
+
++ /* take this out for more general usage */
++ netdev->dev_addr[0] = 0x00;
++ netdev->dev_addr[1] = 0x88;
++ netdev->dev_addr[2] = 0x88;
++ netdev->dev_addr[3] = 0x88;
++ netdev->dev_addr[4] = 0x88;
++ netdev->dev_addr[5] = 0x01;
++
++ printk("ethoc: setting MAC address to %2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x\n",netdev->dev_addr[0],
++ netdev->dev_addr[1],netdev->dev_addr[2],netdev->dev_addr[3],netdev->dev_addr[4],
++ netdev->dev_addr[5]);
+ ethoc_set_mac_address(netdev, netdev->dev_addr);
+
+ /* register MII bus */
+@@ -1189,6 +1204,7 @@ static struct platform_driver ethoc_driver = {
+
+ static int __init ethoc_init(void)
+ {
++ printk("ethoc driver with ts73xx fixes initialized\n");
+ return platform_driver_register(ðoc_driver);
+ }
+
+--
+1.7.1
+
diff --git a/recipes/linux/linux-2.6.38/ts72xx/0019-ts7300-add-ethernet-support.patch b/recipes/linux/linux-2.6.38/ts72xx/0019-ts7300-add-ethernet-support.patch
new file mode 100644
index 0000000..6409f9e
--- /dev/null
+++ b/recipes/linux/linux-2.6.38/ts72xx/0019-ts7300-add-ethernet-support.patch
@@ -0,0 +1,87 @@
+From 512af56eeb7d054334146df483076d9fdec136ed Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Petr=20=C5=A0tetiar?= <ynezz@true.cz>
+Date: Thu, 21 Oct 2010 11:51:44 +0200
+Subject: [PATCH 19/24] ts7300: add ethernet support
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Signed-off-by: Ian Thompson <ian.thompson@pgs.com>
+Signed-off-by: Petr Štetiar <ynezz@true.cz>
+---
+ arch/arm/mach-ep93xx/include/mach/ts72xx.h | 3 ++
+ arch/arm/mach-ep93xx/ts72xx.c | 30 ++++++++++++++++++++++++++++
+ 2 files changed, 33 insertions(+), 0 deletions(-)
+
+diff --git a/arch/arm/mach-ep93xx/include/mach/ts72xx.h b/arch/arm/mach-ep93xx/include/mach/ts72xx.h
+index 1d50dec..beb3e3c 100644
+--- a/arch/arm/mach-ep93xx/include/mach/ts72xx.h
++++ b/arch/arm/mach-ep93xx/include/mach/ts72xx.h
+@@ -135,6 +135,9 @@
+
+ #define TS7260_SDCARD_PHYS_BASE 0x13000000
+
++#define TS7300_ETHOC_PHYS_BASE 0x72100000
++#define TS7300_ETHOC_IO_BASE 0x72102000
++
+ #ifndef __ASSEMBLY__
+
+ static inline int board_is_ts7200(void)
+diff --git a/arch/arm/mach-ep93xx/ts72xx.c b/arch/arm/mach-ep93xx/ts72xx.c
+index a209112..1cdf5a3 100644
+--- a/arch/arm/mach-ep93xx/ts72xx.c
++++ b/arch/arm/mach-ep93xx/ts72xx.c
+@@ -30,6 +30,7 @@
+ #include <mach/ep93xx_spi.h>
+ #include <mach/hardware.h>
+ #include <mach/ts72xx.h>
++#include <mach/irqs.h>
+
+ #include <asm/mach-types.h>
+ #include <asm/mach/map.h>
+@@ -341,6 +342,32 @@ static struct ep93xx_eth_data __initdata ts72xx_eth_data = {
+ .phy_id = 1,
+ };
+
++static struct resource ts7300_ethoc_resources[] = {
++ [0] = {
++ .start = TS7300_ETHOC_IO_BASE,
++ .end = TS7300_ETHOC_IO_BASE + 0x3FF,
++ .flags = IORESOURCE_MEM,
++ },
++ [1] = {
++ .start = TS7300_ETHOC_PHYS_BASE,
++ .end = TS7300_ETHOC_PHYS_BASE + 0x1FFF,
++ .flags = IORESOURCE_MEM,
++ },
++ [2] = {
++ .start = IRQ_EP93XX_EXT3,
++ .end = IRQ_EP93XX_EXT3,
++ .flags = IORESOURCE_IRQ,
++ },
++};
++
++static struct platform_device ts7300_ethoc_device = {
++ .name = "ethoc",
++ .id = 0,
++ .num_resources = 3,
++ .resource = ts7300_ethoc_resources,
++};
++
++
+ /*************************************************************************
+ * I2C (make access through TS-72XX "DIO" 2x8 header)
+ *************************************************************************/
+@@ -432,6 +459,9 @@ static void __init ts72xx_init_machine(void)
+ platform_device_register(&ts72xx_max197_device);
+ }
+
++ if (board_is_ts7300())
++ platform_device_register(&ts7300_ethoc_device);
++
+ /* PWM1 is DIO_6 on TS-72xx header */
+ ep93xx_register_pwm(0, 1);
+ }
+--
+1.7.1
+
diff --git a/recipes/linux/linux-2.6.38/ts72xx/0020-ts72xx-add-lcd-linux-driver.patch b/recipes/linux/linux-2.6.38/ts72xx/0020-ts72xx-add-lcd-linux-driver.patch
new file mode 100644
index 0000000..774c8c9
--- /dev/null
+++ b/recipes/linux/linux-2.6.38/ts72xx/0020-ts72xx-add-lcd-linux-driver.patch
@@ -0,0 +1,4572 @@
+From 8edba7cb987db30acc16e69652caffe8c488b1ae Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Petr=20=C5=A0tetiar?= <ynezz@true.cz>
+Date: Mon, 14 Mar 2011 00:16:24 +0100
+Subject: [PATCH 20/24] ts72xx: add lcd-linux driver
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+- based on LCD-Linux v0.13.9 (latest stable release)
+- supports only hd44780 compatible display
+- LCD in 8-bit mode operation only (D0-D7) connected to LCD connector
+
+Signed-off-by: Petr Štetiar <ynezz@true.cz>
+---
+ arch/arm/Kconfig | 2 +
+ drivers/Makefile | 1 +
+ drivers/lcd-linux/Config.in | 8 +
+ drivers/lcd-linux/Kconfig | 33 +
+ drivers/lcd-linux/Makefile | 8 +
+ drivers/lcd-linux/cgram/default.h | 37 +
+ drivers/lcd-linux/cgram/swedish.h | 33 +
+ drivers/lcd-linux/charmap.h | 79 +
+ drivers/lcd-linux/commands.h | 77 +
+ drivers/lcd-linux/config.h | 73 +
+ drivers/lcd-linux/hd44780.c | 854 +++++++++++
+ drivers/lcd-linux/lcd-linux.c | 3026 +++++++++++++++++++++++++++++++++++++
+ include/linux/hd44780.h | 47 +
+ include/linux/lcd-linux.h | 158 ++
+ 14 files changed, 4436 insertions(+), 0 deletions(-)
+ create mode 100644 drivers/lcd-linux/Config.in
+ create mode 100644 drivers/lcd-linux/Kconfig
+ create mode 100644 drivers/lcd-linux/Makefile
+ create mode 100644 drivers/lcd-linux/cgram/default.h
+ create mode 100644 drivers/lcd-linux/cgram/swedish.h
+ create mode 100644 drivers/lcd-linux/charmap.h
+ create mode 100644 drivers/lcd-linux/commands.h
+ create mode 100644 drivers/lcd-linux/config.h
+ create mode 100644 drivers/lcd-linux/hd44780.c
+ create mode 100644 drivers/lcd-linux/lcd-linux.c
+ create mode 100644 include/linux/hd44780.h
+ create mode 100644 include/linux/lcd-linux.h
+
+diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
+index 31ad31d..e4512d3 100644
+--- a/arch/arm/Kconfig
++++ b/arch/arm/Kconfig
+@@ -1934,6 +1934,8 @@ source "net/Kconfig"
+
+ source "drivers/Kconfig"
+
++source "drivers/lcd-linux/Kconfig"
++
+ source "fs/Kconfig"
+
+ source "arch/arm/Kconfig.debug"
+diff --git a/drivers/Makefile b/drivers/Makefile
+index b423bb1..40663a8 100644
+--- a/drivers/Makefile
++++ b/drivers/Makefile
+@@ -117,3 +117,4 @@ obj-y += platform/
+ obj-y += ieee802154/
+ #common clk code
+ obj-y += clk/
++obj-$(CONFIG_LCD_LINUX) += lcd-linux/
+diff --git a/drivers/lcd-linux/Config.in b/drivers/lcd-linux/Config.in
+new file mode 100644
+index 0000000..4a38801
+--- /dev/null
++++ b/drivers/lcd-linux/Config.in
+@@ -0,0 +1,8 @@
++if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
++ mainmenu_option next_comment
++ comment 'LCD support'
++
++ tristate 'LCD-Linux layer' CONFIG_LCD_LINUX
++ dep_tristate ' HD44780 controller' CONFIG_LCD_HD44780 $CONFIG_LCD_LINUX
++ endmenu
++fi
+diff --git a/drivers/lcd-linux/Kconfig b/drivers/lcd-linux/Kconfig
+new file mode 100644
+index 0000000..a102fc5
+--- /dev/null
++++ b/drivers/lcd-linux/Kconfig
+@@ -0,0 +1,33 @@
++menu "LCD support"
++ depends on EXPERIMENTAL
++
++config LCD_LINUX
++ tristate "LCD-Linux layer"
++ default n
++ help
++ LCD-Linux provides an easy way to drive LCD displays under
++ Linux by creating a character which can be read or written.
++ It features complete VT102 emulation and recognizes
++ many escape sequences. If you want to use it you must also
++ choose an appropriate driver, otherwise it will not be
++ very useful. For more information see
++ http://lcd-linux.sourceforge.net/
++
++ To compile LCD-Linux as a module, choose M here:
++ the module will be called lcd-linux.
++
++config LCD_HD44780
++ tristate "HD44780 controller"
++ depends on LCD_LINUX && MACH_TS72XX
++ default n
++ help
++ This is a LCD-Linux driver for LCD displays based on the
++ Hitachi HD44780 (and compatible) controllers connected
++ to LCD port on the TS72xx boards.
++
++ To compile this driver as a module, choose M here:
++ the module will be called hd44780.
++
++ If unsure, say N.
++
++endmenu
+diff --git a/drivers/lcd-linux/Makefile b/drivers/lcd-linux/Makefile
+new file mode 100644
+index 0000000..079aa79
+--- /dev/null
++++ b/drivers/lcd-linux/Makefile
+@@ -0,0 +1,8 @@
++# $Id: Makefile-2.6,v 1.3 2006/12/13 15:53:00 mjona Exp $
++#
++# Standard Makefile to statically compile LCD-Linux into the kernel
++# Linux 2.6
++
++obj-$(CONFIG_LCD_LINUX) += lcd-linux.o
++obj-$(CONFIG_LCD_HD44780) += hd44780.o
++
+diff --git a/drivers/lcd-linux/cgram/default.h b/drivers/lcd-linux/cgram/default.h
+new file mode 100644
+index 0000000..635146a
+--- /dev/null
++++ b/drivers/lcd-linux/cgram/default.h
+@@ -0,0 +1,37 @@
++/* default.h
++ *
++ * $Id: default.h,v 1.1.1.1 2005/08/23 13:30:14 mjona Exp $
++ *
++ * Default user defined characters for lcdmod.
++ *
++ * Copyright (C) by Michael McLellan (mikey@cs.auckland.ac.nz)
++ *
++ * 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 init_charmap(void)
++{
++}
++
++static unsigned char cg0[] = { 0x1f, 0x1f, 0x11, 0x0f, 0x11, 0x1e, 0x01, 0x1f };
++static unsigned char cg1[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f };
++static unsigned char cg2[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x1f };
++static unsigned char cg3[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x1f, 0x1f };
++static unsigned char cg4[] = { 0x00, 0x00, 0x00, 0x00, 0x1f, 0x1f, 0x1f, 0x1f };
++static unsigned char cg5[] = { 0x00, 0x00, 0x00, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f };
++static unsigned char cg6[] = { 0x00, 0x00, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f };
++static unsigned char cg7[] = { 0x00, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f };
+diff --git a/drivers/lcd-linux/cgram/swedish.h b/drivers/lcd-linux/cgram/swedish.h
+new file mode 100644
+index 0000000..a92c31c
+--- /dev/null
++++ b/drivers/lcd-linux/cgram/swedish.h
+@@ -0,0 +1,33 @@
++/* swedish.h
++ *
++ * $Id: swedish.h,v 1.2 2006/12/12 16:04:03 mjona Exp $
++ *
++ * Swedish characters for lcdmod
++ *
++ * Thanks to Erik Zetterberg <mr.z@linux.se>
++ *
++ * Description: Adds support for the last three last letters in the
++ * swedish alphabet (a/A with ring above, a/A with diaeresis and o/O
++ * with diaeresis). And maps the location of where they should be
++ * according to the ISO-8859-1 character set to their location in CGRAM.
++ *
++ */
++
++static void init_charmap(void)
++{
++ charmap[ 0xe5 ] = 0;
++ charmap[ 0xe4 ] = 1;
++ charmap[ 0xf6 ] = 2;
++ charmap[ 0xc5 ] = 3;
++ charmap[ 0xc4 ] = 4;
++ charmap[ 0xd6 ] = 5;
++}
++
++static unsigned char cg0[] = { 0x04, 0x00, 0x0e, 0x01, 0x0f, 0x11, 0x0f, 0x00 };
++static unsigned char cg1[] = { 0x0a, 0x00, 0x0e, 0x01, 0x0f, 0x11, 0x0f, 0x00 };
++static unsigned char cg2[] = { 0x0a, 0x00, 0x0e, 0x11, 0x11, 0x11, 0x0e, 0x00 };
++static unsigned char cg3[] = { 0x04, 0x00, 0x0e, 0x11, 0x1f, 0x11, 0x11, 0x00 };
++static unsigned char cg4[] = { 0x0a, 0x00, 0x0e, 0x11, 0x1f, 0x11, 0x11, 0x00 };
++static unsigned char cg5[] = { 0x0a, 0x00, 0x0e, 0x11, 0x11, 0x11, 0x0e, 0x00 };
++static unsigned char cg6[] = { 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f };
++static unsigned char cg7[] = { 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f };
+diff --git a/drivers/lcd-linux/charmap.h b/drivers/lcd-linux/charmap.h
+new file mode 100644
+index 0000000..376b04d
+--- /dev/null
++++ b/drivers/lcd-linux/charmap.h
+@@ -0,0 +1,79 @@
++/* charmap.h
++ *
++ * $Id: charmap.h,v 1.1.1.1 2005/08/23 13:30:14 mjona Exp $
++ *
++ * Character mapping for HD44780 devices by Mark Haemmerling <mail@markh.de>.
++ *
++ * Translates ISO 8859-1 to HD44780 charset.
++ * HD44780 charset reference: http://markh.de/hd44780-charset.png
++ *
++ * Initial table taken from lcd.o Linux kernel driver by
++ * Nils Faerber <nilsf@users.sourceforge.net>. Thanks!
++ *
++ * This file is released under the GNU General Public License. Refer to the
++ * COPYING file distributed with this package.
++ *
++ * Following translations are being performed:
++ * - maps umlaut accent characters to the corresponding umlaut characters
++ * - maps other accent characters to the characters without accents
++ * - maps beta (=ringel-S), micro and Yen
++ *
++ * Alternative mappings:
++ * - #112 ("p") -> #240 (large "p"), orig. mapped -> #112
++ * - #113 ("q") -> #241 (large "q"), orig. mapped -> #113
++ *
++ * HD44780 misses backslash
++ *
++ */
++
++static unsigned char charmap[] = {
++
++/* 0 - 31 */
++ 0, 1, 2, 3, 4, 5, 6, 7,
++ 8, 9, 10, 11, 12, 13, 14, 15,
++ 16, 17, 18, 19, 20, 21, 22, 23,
++ 24, 25, 26, 27, 28, 29, 30, 31,
++
++/* 32 - 63 */
++ 32, 33, 34, 35, 36, 37, 38, 39,
++ 40, 41, 42, 43, 44, 45, 46, 47,
++ 48, 49, 50, 51, 52, 53, 54, 55,
++ 56, 57, 58, 59, 60, 61, 62, 63,
++
++/* 64 - 95 */
++ 64, 65, 66, 67, 68, 69, 70, 71,
++ 72, 73, 74, 75, 76, 77, 78, 79,
++ 80, 81, 82, 83, 84, 85, 86, 87,
++ 88, 89, 90, 91, 47, 93, 94, 95,
++
++/* 96 - 127 */
++ 96, 97, 98, 99, 100, 101, 102, 103,
++104, 105, 106, 107, 108, 109, 110, 111,
++112, 113, 114, 115, 116, 117, 118, 119,
++120, 121, 122, 123, 124, 125, 126, 127,
++
++/* 128 - 159 */
++128, 129, 130, 131, 132, 133, 134, 135,
++136, 137, 138, 139, 140, 141, 142, 143,
++144, 145, 146, 147, 148, 149, 150, 151,
++152, 153, 154, 155, 156, 157, 158, 159,
++
++/* 160 - 191 */
++160, 33, 236, 237, 164, 92, 124, 167,
++ 34, 169, 170, 171, 172, 173, 174, 175,
++223, 177, 178, 179, 39, 249, 247, 165,
++ 44, 185, 186, 187, 188, 189, 190, 63,
++
++/* 192 - 223 */
++ 65, 65, 65, 65, 225, 65, 65, 67,
++ 69, 69, 69, 69, 73, 73, 73, 73,
++ 68, 78, 79, 79, 79, 79, 239, 120,
++ 48, 85, 85, 85, 245, 89, 240, 226,
++
++/* 224 - 255 */
++ 97, 97, 97, 97, 225, 97, 97, 99,
++101, 101, 101, 101, 105, 105, 105, 105,
++111, 110, 111, 111, 111, 111, 239, 253,
++ 48, 117, 117, 117, 245, 121, 240, 255
++
++};
+diff --git a/drivers/lcd-linux/commands.h b/drivers/lcd-linux/commands.h
+new file mode 100644
+index 0000000..6567836
+--- /dev/null
++++ b/drivers/lcd-linux/commands.h
+@@ -0,0 +1,77 @@
++/* commands.h
++ *
++ * $Id: commands.h,v 1.2 2009/03/09 17:59:22 mjona Exp $
++ *
++ * LCD-Linux:
++ * Driver for HD44780 compatible displays connected to the parallel port.
++ *
++ * HD44780 commands.
++ *
++ * Copyright (C) 2004 - 2009 Mattia Jona-Lasinio (mjona@users.sourceforge.net)
++ *
++ * 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 HD44780_COMMANDS_H
++#define HD44780_COMMANDS_H
++
++/*** HD44780 Command Set ***/
++
++/* Clear Display*/
++#define CLR_DISP 0x01 /* Clear entire display; cursor at row 0, column 0 */
++
++/* Return Home */
++#define RET_HOME 0x02 /* Cursor at row 0, column 0; display content doesn't change */
++
++/* Entry Mode Set */
++#define ENTRY_MODE_SET 0x04
++#define DISP_SHIFT_ON (ENTRY_MODE_SET | 0x01) /* Shift display, not cursor after data write */
++#define DISP_SHIFT_OFF (ENTRY_MODE_SET | 0x00) /* Shift cursor, not display after data write */
++#define CURS_INC (ENTRY_MODE_SET | 0x02) /* Shift on the right after data read/write */
++#define CURS_DEC (ENTRY_MODE_SET | 0x00) /* Shift on the left after data read/write */
++
++/* Display on/off Control */
++#define DISP_ONOFF_CNTR 0x08
++#define BLINK_ON (DISP_ONOFF_CNTR | 0x01) /* Cursor blinking on */
++#define BLINK_OFF (DISP_ONOFF_CNTR | 0x00) /* Cursor blinking off */
++#define CURS_ON (DISP_ONOFF_CNTR | 0x02) /* Display Cursor */
++#define CURS_OFF (DISP_ONOFF_CNTR | 0x00) /* Hide Cursor */
++#define DISP_ON (DISP_ONOFF_CNTR | 0x04) /* Turn on display updating */
++#define DISP_OFF (DISP_ONOFF_CNTR | 0x00) /* Freeze display content */
++
++/* Cursor or Display Shift */
++#define CURS_DISP_SHIFT 0x10
++#define SHIFT_RIGHT (CURS_DISP_SHIFT | 0x04) /* Shift on the right */
++#define SHIFT_LEFT (CURS_DISP_SHIFT | 0x00) /* Shift on the left */
++#define SHIFT_DISP (CURS_DISP_SHIFT | 0x08) /* Shift display */
++#define SHIFT_CURS (CURS_DISP_SHIFT | 0x00) /* Shift cursor */
++
++/* Function Set */
++#define FUNC_SET 0x20
++#define FONT_5X10 (FUNC_SET | 0x04) /* Select 5x10 dots font */
++#define FONT_5X8 (FUNC_SET | 0x00) /* Select 5x8 dots font */
++#define DISP_2_LINES (FUNC_SET | 0x08) /* Select 2 lines display (only 5x8 font allowed) */
++#define DISP_1_LINE (FUNC_SET | 0x00) /* Select 1 line display */
++#define BUS_8_BITS (FUNC_SET | 0x10) /* Set 8 data bits */
++#define BUS_4_BITS (FUNC_SET | 0x00) /* Set 4 data bits */
++
++/* Set CGRAM Address */
++#define CGRAM_IO 0x40 /* Base CGRAM address */
++
++/* Set DDRAM Address */
++#define DDRAM_IO 0x80 /* Base DDRAM address */
++
++#endif /* commands included */
+diff --git a/drivers/lcd-linux/config.h b/drivers/lcd-linux/config.h
+new file mode 100644
+index 0000000..face191
+--- /dev/null
++++ b/drivers/lcd-linux/config.h
+@@ -0,0 +1,73 @@
++/* config.h
++ *
++ * $Id: config.h,v 1.16 2009/09/27 21:27:03 mjona Exp $
++ *
++ * Configure file for LCD-Linux. Here you must specify your hardware setup and
++ * timings constants. The default values will probably be right for you.
++ *
++ * Copyright (C) 2005 - 2009 Mattia Jona-Lasinio (mjona@users.sourceforge.net)
++ *
++ * 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
++ *
++ *
++ */
++
++/* Setup the default user defined characters in CGRAM */
++#include "cgram/default.h"
++/* #include "cgram/swedish.h" */
++/* #include "cgram/cgram.h" */
++
++/* Don't modify the default timing constants
++ * unless you know what you are doing.
++ */
++
++/* In case of a 4 bit bus, indicate your
++ * wiring configuration for the data bits
++ *
++ * 0 -> D3, D2, D1, D0
++ * 1 -> D4, D3, D2, D1
++ * 2 -> D5, D4, D3, D2
++ * 3 -> D6, D5, D4, D3
++ * 4 -> D7, D6, D5, D4
++ */
++#define SETUP 4
++
++#define HIGH_NIBBLE_WRITE(x) (((x) >> (4-SETUP)) & (0x0f << SETUP))
++#define LOW_NIBBLE_WRITE(x) (((x) << SETUP) & (0x0f << SETUP))
++#define HIGH_NIBBLE_READ(x) (((x) & (0x0f << SETUP)) << (4-SETUP))
++#define LOW_NIBBLE_READ(x) (((x) & (0x0f << SETUP)) >> SETUP)
++
++/* Execution times (in microseconds) */
++#define T_READ 60 /* Read execution time (min 43 us) */
++#define T_WRITE 60 /* Write execution time (min 43 us) */
++#define T_BF 4 /* Busy flag polling time (min 1 us) */
++
++/* Timings in nanoseconds */
++#define T_AS 200 /* Address set-up time (min 140 ns) */
++#define T_EH 500 /* Enable high time (min 450 ns) */
++#define T_EL 800 /* Enable low time (min 500 ns) */
++
++/* Various constants */
++#define DFLT_NUM_CNTR 1 /* Default number of controllers the display has */
++#define DFLT_CNTR_ROWS 4 /* Default number of rows per controller */
++#define DFLT_CNTR_COLS 20 /* Default number of columns the display has */
++#define DFLT_VS_ROWS 25 /* Default number of rows for the virtual screen */
++#define DFLT_VS_COLS 80 /* Default number of columns for the virtual screen */
++#define DFLT_TABSTOP 4 /* Default length of tabs */
++#define DFLT_FLAGS HD44780_CHECK_BF /* Default flags: check BF and 8 bit bus */
++
++#define MAX_NUM_CNTR 7 /* We support up to 7 controllers */
++#define MAX_CNTR_ROWS 4 /* The HD44780 supports up to 4 lines as a fake 2 lines mode */
++#define MAX_CNTR_COLS 80 /* The HD44780 supports up to 80 characters (1*80; 2*40; etc) */
+diff --git a/drivers/lcd-linux/hd44780.c b/drivers/lcd-linux/hd44780.c
+new file mode 100644
+index 0000000..0b1af6b
+--- /dev/null
++++ b/drivers/lcd-linux/hd44780.c
+@@ -0,0 +1,854 @@
++/* hd44780.c
++ *
++ * $Id: hd44780.c,v 1.181 2010/03/03 14:56:22 mjona Exp $
++ *
++ * LCD-Linux:
++ * Driver for HD44780 compatible displays connected to the parallel port.
++ *
++ * Copyright (C) 2005 - 2009 Mattia Jona-Lasinio (mjona@users.sourceforge.net)
++ * Based on the code for Sim.One Hardware by Nuccio Raciti (raciti.nuccio@gmail.com)
++ * Modified for ts72xx hardware by Petr Stetiar (ynezz@true.cz)
++ * (Only 8-bit mode supported for now.)
++ *
++ * 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
++ *
++ */
++
++#ifdef CONFIG_PROC_FS
++#define USE_PROC
++#else
++#undef USE_PROC
++#endif
++
++#include <linux/bitops.h>
++#include <linux/kernel.h>
++#include <linux/module.h>
++
++#include <linux/delay.h>
++#include <linux/fs.h>
++
++#include <asm/uaccess.h>
++#include <asm/gpio.h>
++#include <asm/io.h>
++#include <linux/init.h>
++#include <linux/ioport.h>
++
++#ifdef USE_PROC
++#include <linux/proc_fs.h>
++#endif
++
++#define LCD_LINUX_MAIN
++#include <linux/hd44780.h>
++
++#include "charmap.h"
++#include "commands.h"
++#include "config.h"
++
++#define LCD_EN EP93XX_GPIO_LINE_H(3)
++#define LCD_RS EP93XX_GPIO_LINE_H(4)
++#define LCD_WR EP93XX_GPIO_LINE_H(5)
++#define LCD_DATA0 EP93XX_GPIO_LINE_A(0)
++#define LCD_DATA1 EP93XX_GPIO_LINE_A(1)
++#define LCD_DATA2 EP93XX_GPIO_LINE_A(2)
++#define LCD_DATA3 EP93XX_GPIO_LINE_A(3)
++#define LCD_DATA4 EP93XX_GPIO_LINE_A(4)
++#define LCD_DATA5 EP93XX_GPIO_LINE_A(5)
++#define LCD_DATA6 EP93XX_GPIO_LINE_A(6)
++#define LCD_DATA7 EP93XX_GPIO_LINE_A(7)
++
++static struct gpio lcd_gpios[] = {
++ { LCD_EN, GPIOF_OUT_INIT_LOW, "LCD enable" },
++ { LCD_RS, GPIOF_OUT_INIT_LOW, "LCD data" },
++ { LCD_WR, GPIOF_OUT_INIT_LOW, "LCD r/w" },
++ { LCD_DATA0, GPIOF_OUT_INIT_LOW, "LCD data0" },
++ { LCD_DATA1, GPIOF_OUT_INIT_LOW, "LCD data1" },
++ { LCD_DATA2, GPIOF_OUT_INIT_LOW, "LCD data2" },
++ { LCD_DATA3, GPIOF_OUT_INIT_LOW, "LCD data3" },
++ { LCD_DATA4, GPIOF_OUT_INIT_LOW, "LCD data4" },
++ { LCD_DATA5, GPIOF_OUT_INIT_LOW, "LCD data5" },
++ { LCD_DATA6, GPIOF_OUT_INIT_LOW, "LCD data6" },
++ { LCD_DATA7, GPIOF_OUT_INIT_LOW, "LCD data7" },
++};
++
++/** Function prototypes **/
++static void read_display(unsigned char *byte, unsigned char bitmask);
++static void write_display(unsigned char byte, unsigned char bitmask);
++
++/* Initialization */
++static int hd44780_validate_driver(void);
++static int hd44780_init_port(void);
++static int hd44780_cleanup_port(void);
++static int hd44780_init_display(void);
++static int hd44780_cleanup_display(void);
++
++/* Write */
++static void hd44780_address_mode(int);
++static void hd44780_clear_display(void);
++static void hd44780_write_char(unsigned int, unsigned short);
++static void hd44780_write_cgram_char(unsigned char, unsigned char *);
++
++/* Read */
++static void check_bf(unsigned char);
++static void hd44780_read_char(unsigned int, unsigned short *);
++static void hd44780_read_cgram_char(unsigned char, unsigned char *);
++
++/* Input handling */
++static int hd44780_handle_custom_char(unsigned int);
++static int hd44780_handle_custom_ioctl(unsigned int, unsigned long, unsigned int);
++
++/* Proc operations */
++#ifdef USE_PROC
++static void create_proc_entries(void);
++static void remove_proc_entries(void);
++#endif
++
++/* hd44780_flags */
++#define _CHECK_BF 0 /* Do busy-flag checking */
++#define _4BITS_BUS 1 /* The bus is 4 bits long */
++#define _5X10_FONT 2 /* Use 5x10 font */
++#define CURSOR_BLINK 3 /* Make the cursor blinking */
++#define SHOW_CURSOR 4 /* Make the cursor visible */
++#define DISPLAY_ON 5 /* Display status: on or off */
++#define INC_ADDR 6 /* Increment address after data read/write */
++#define BACKLIGHT 7 /* Display backlight: on or off */
++#define CGRAM_STATE 9 /* Controller status bitmask (bits 9->15): DDRAM or CGRAM access */
++
++/* hd44780 access */
++#define ACCESS_TO_READ 0
++#define ACCESS_TO_WRITE 1
++#define ACCESS_TO_DATA 2
++
++#define ESC_MASK 0x00ff0000
++#define PROC_MASK 0x0f000000
++
++#define SET_STATE(state, mask) (hd44780_flags = (hd44780_flags & ~(mask)) | ((state) & (mask)))
++#define SET_ESC_STATE(state) SET_STATE((state) << 16, ESC_MASK)
++#define SET_PROC_LEVEL(level) SET_STATE((level) << 24, PROC_MASK)
++#define ESC_STATE ((hd44780_flags & ESC_MASK) >> 16)
++#define PROC_LEVEL ((hd44780_flags & PROC_MASK) >> 24)
++
++/* globals */
++static unsigned int disp_size; /* Display size (rows*columns) */
++static unsigned int disp_offset[1]; /* Physical cursor position on the display */
++static unsigned long hd44780_flags; /* Driver flags for internal use only */
++
++static struct lcd_parameters par = {
++ .name = HD44780_STRING,
++ .minor = HD44780_MINOR,
++ .flags = DFLT_FLAGS,
++ .tabstop = DFLT_TABSTOP,
++ .num_cntr = 1,
++ .cntr_rows = DFLT_CNTR_ROWS,
++ .cntr_cols = DFLT_CNTR_COLS,
++ .vs_rows = DFLT_VS_ROWS,
++ .vs_cols = DFLT_VS_COLS,
++ .cgram_chars = 8,
++ .cgram_bytes = 8,
++ .cgram_char0 = 0,
++};
++/* End of globals */
++
++#ifdef MODULE
++#include <linux/device.h>
++MODULE_ALIAS_CHARDEV(LCD_MAJOR, HD44780_MINOR);
++#include <linux/kmod.h>
++
++static unsigned short flags = DFLT_FLAGS;
++static unsigned short tabstop = DFLT_TABSTOP;
++static unsigned short cntr_rows = DFLT_CNTR_ROWS;
++static unsigned short cntr_cols = DFLT_CNTR_COLS;
++static unsigned short vs_rows = DFLT_VS_ROWS;
++static unsigned short vs_cols = DFLT_VS_COLS;
++static unsigned short minor = HD44780_MINOR;
++
++MODULE_DESCRIPTION("LCD ts72xx driver for HD44780 compatible controllers.");
++MODULE_AUTHOR("Petr Stetiar <ynezz@true.cz>");
++#ifdef MODULE_LICENSE
++MODULE_LICENSE("GPL");
++#endif
++module_param(flags, ushort, 0444);
++module_param(cntr_rows, ushort, 0444);
++module_param(cntr_cols, ushort, 0444);
++module_param(vs_rows, ushort, 0444);
++module_param(vs_cols, ushort, 0444);
++module_param(tabstop, ushort, 0444);
++module_param(minor, ushort, 0444);
++MODULE_PARM_DESC(flags, "Various flags (see Documentation)");
++MODULE_PARM_DESC(cntr_rows, "Number of rows per controller on the LCD: 1, 2, 4 (default: " string(DFLT_CNTR_ROWS) ")");
++MODULE_PARM_DESC(cntr_cols, "Number of columns on the LCD (default: " string(DFLT_CNTR_COLS) ", max: " string(MAX_CNTR_COLS) ")");
++MODULE_PARM_DESC(vs_rows, "Number of rows of the virtual screen (default: " string(DFLT_VS_ROWS) ")");
++MODULE_PARM_DESC(vs_cols, "Number of columns of the virtual screen (default: " string(DFLT_VS_COLS) ")");
++MODULE_PARM_DESC(tabstop, "Tab character length (default: " string(DFLT_TABSTOP) ")");
++MODULE_PARM_DESC(minor, "Assigned minor number (default: " string(HD44780_MINOR) ")");
++#else
++
++/*
++ * Parse boot command line
++ *
++ * hd44780=cntr_rows,cntr_cols,vs_rows,vs_cols,flags,minor,tabstop
++ */
++static int __init hd44780_boot_init(char *cmdline)
++{
++ char *str = cmdline;
++ int idx = 0;
++ unsigned short *args[] = {
++ &par.cntr_rows,
++ &par.cntr_cols,
++ &par.vs_rows,
++ &par.vs_cols,
++ (ushort *) &par.flags,
++ &par.num_cntr,
++ &par.minor,
++ &par.tabstop,
++ };
++
++ while (*cmdline && idx < (sizeof(args)/sizeof(unsigned short *))) {
++ switch (*str) {
++ case ',':
++ *str++ = 0;
++ case 0:
++ if (strlen(cmdline))
++ *args[idx] = simple_strtoul(cmdline, NULL, 0);
++ ++idx;
++ cmdline = str;
++ break;
++ default:
++ ++str;
++ break;
++ }
++ }
++
++ return (1);
++}
++
++__setup("hd44780=", hd44780_boot_init);
++#endif /* MODULE */
++
++/* Macros for iterator handling */
++static inline unsigned int iterator_inc_(unsigned int iterator, const unsigned int module)
++{
++ return ((++iterator)%module);
++}
++
++static inline unsigned int iterator_dec_(unsigned int iterator, const unsigned int module)
++{
++ return (iterator ? --iterator : module-1);
++}
++
++#define iterator_inc(iterator, module) (iterator = iterator_inc_(iterator, module))
++#define iterator_dec(iterator, module) (iterator = iterator_dec_(iterator, module))
++
++static inline void set_lines(unsigned char bitmask)
++{
++ gpio_set_value(LCD_EN, 0); /* Disable */
++
++ if (bitmask & ACCESS_TO_WRITE ) {
++ gpio_direction_output(LCD_DATA0, 0);
++ gpio_direction_output(LCD_DATA1, 0);
++ gpio_direction_output(LCD_DATA2, 0);
++ gpio_direction_output(LCD_DATA3, 0);
++ gpio_direction_output(LCD_DATA4, 0);
++ gpio_direction_output(LCD_DATA5, 0);
++ gpio_direction_output(LCD_DATA6, 0);
++ gpio_direction_output(LCD_DATA7, 0);
++ gpio_set_value(LCD_WR, 0); /* Write */
++ } else {
++ gpio_direction_input(LCD_DATA0);
++ gpio_direction_input(LCD_DATA1);
++ gpio_direction_input(LCD_DATA2);
++ gpio_direction_input(LCD_DATA3);
++ gpio_direction_input(LCD_DATA4);
++ gpio_direction_input(LCD_DATA5);
++ gpio_direction_input(LCD_DATA6);
++ gpio_direction_input(LCD_DATA7);
++ gpio_set_value(LCD_WR, 1); /* Read */
++ }
++
++ if (bitmask & ACCESS_TO_DATA )
++ gpio_set_value(LCD_RS, 1); /* Data */
++ else
++ gpio_set_value(LCD_RS, 0); /* Cmds*/
++}
++
++static inline void read_display(unsigned char *byte, unsigned char bitmask)
++{
++ unsigned char ret;
++ if (bitmask)
++ check_bf(bitmask);
++
++ set_lines(bitmask);
++
++ ndelay(T_AS); /* Address set-up time */
++ gpio_set_value(LCD_EN, 1); /* Enable */
++ ndelay(T_EH); /* Enable high time */
++
++ ret = (gpio_get_value(LCD_DATA0) << 0);
++ ret |= (gpio_get_value(LCD_DATA1) << 1);
++ ret |= (gpio_get_value(LCD_DATA2) << 2);
++ ret |= (gpio_get_value(LCD_DATA3) << 3);
++ ret |= (gpio_get_value(LCD_DATA4) << 4);
++ ret |= (gpio_get_value(LCD_DATA5) << 5);
++ ret |= (gpio_get_value(LCD_DATA6) << 6);
++ ret |= (gpio_get_value(LCD_DATA7) << 7);
++
++ gpio_set_value(LCD_EN, 0); /* Disable */
++ ndelay(T_EL); /* Enable low time */
++ *byte = ret;
++}
++
++/* Low level write to the display */
++static inline void write_display(unsigned char data, unsigned char bitmask)
++{
++ check_bf(bitmask);
++ set_lines(bitmask);
++
++ gpio_set_value(LCD_DATA0, (data >> 0) & 1);
++ gpio_set_value(LCD_DATA1, (data >> 1) & 1);
++ gpio_set_value(LCD_DATA2, (data >> 2) & 1);
++ gpio_set_value(LCD_DATA3, (data >> 3) & 1);
++ gpio_set_value(LCD_DATA4, (data >> 4) & 1);
++ gpio_set_value(LCD_DATA5, (data >> 5) & 1);
++ gpio_set_value(LCD_DATA6, (data >> 6) & 1);
++ gpio_set_value(LCD_DATA7, (data >> 7) & 1);
++
++ ndelay(T_AS); /* Address set-up time */
++ gpio_set_value(LCD_EN, 1);
++ ndelay(T_EH); /* Enable high time */
++
++ gpio_set_value(LCD_EN, 0); /* Disable */
++ ndelay(T_EL); /* Enable low time */
++}
++
++/* Read Address Counter AC from the display */
++static unsigned char read_ac(unsigned char bitmask)
++{
++ unsigned char byte;
++
++ read_display(&byte, bitmask);
++
++ return (byte);
++}
++
++static void check_bf(unsigned char bitmask)
++{
++ unsigned int timeout = 20;
++ static unsigned char do_check_bf = 5;
++
++ gpio_set_value(LCD_EN, 0); /* Disable */
++
++ gpio_direction_input(LCD_DATA0);
++ gpio_direction_input(LCD_DATA1);
++ gpio_direction_input(LCD_DATA2);
++ gpio_direction_input(LCD_DATA3);
++ gpio_direction_input(LCD_DATA4);
++ gpio_direction_input(LCD_DATA5);
++ gpio_direction_input(LCD_DATA6);
++ gpio_direction_input(LCD_DATA7);
++
++ gpio_set_value(LCD_WR, 1); /* Read */
++ gpio_set_value(LCD_RS, 0); /* Instru */
++
++ ndelay(T_AS); /* Address set-up time */
++ gpio_set_value(LCD_EN, 1); /* Enable */
++ ndelay(T_EH); /* Enable high time */
++
++ do {
++ udelay(T_BF);
++ } while (gpio_get_value(LCD_DATA7) && --timeout);
++
++ if (!timeout) {
++ if (!--do_check_bf) {
++ printk(KERN_NOTICE "hd44780 error: is LCD connected?\n");
++ }
++ }
++
++ gpio_set_value(LCD_EN, 0); /* Disable */
++ ndelay(T_EL); /* Enable low time */
++}
++
++/* Send commands to the display */
++static void write_command(unsigned char command)
++{
++ write_display(command, ACCESS_TO_WRITE);
++
++ if (command <= 0x03)
++ mdelay(2);
++}
++
++static inline void set_cursor(unsigned int offset)
++{
++ unsigned int disp_number = offset/disp_size;
++ unsigned int local_offset = offset%disp_size;
++
++ if (disp_offset[disp_number] != local_offset || test_bit(CGRAM_STATE+disp_number, &hd44780_flags)) {
++ unsigned int disp_row = local_offset/par.cntr_cols;
++ unsigned int disp_column = local_offset%par.cntr_cols;
++
++ write_command(DDRAM_IO | ((disp_row%2)*0x40) | (((disp_row >= 2)*par.cntr_cols)+disp_column));
++ clear_bit(CGRAM_STATE+disp_number, &hd44780_flags);
++ disp_offset[disp_number] = local_offset;
++ }
++}
++
++/* HD44780 DDRAM addresses are consecutive only when
++ * the cursor moves on the same row of the display.
++ * Every time the row of the cursor changes we invalidate
++ * the cursor position to force hardware cursor repositioning.
++ */
++static inline void mov_cursor(unsigned int disp_number)
++{
++ if (test_bit(INC_ADDR, &hd44780_flags)) {
++ iterator_inc(disp_offset[disp_number], disp_size);
++ if (disp_offset[disp_number]%par.cntr_cols == 0)
++ disp_offset[disp_number] = disp_size;
++ } else {
++ iterator_dec(disp_offset[disp_number], disp_size);
++ if (disp_offset[disp_number]%par.cntr_cols == par.cntr_cols-1)
++ disp_offset[disp_number] = disp_size;
++ }
++}
++
++static struct lcd_driver hd44780 = {
++ .read_char = hd44780_read_char,
++ .read_cgram_char = hd44780_read_cgram_char,
++ .write_char = hd44780_write_char,
++ .write_cgram_char = hd44780_write_cgram_char,
++ .address_mode = hd44780_address_mode,
++ .clear_display = hd44780_clear_display,
++ .validate_driver = hd44780_validate_driver,
++ .init_display = hd44780_init_display,
++ .cleanup_display = hd44780_cleanup_display,
++ .init_port = hd44780_init_port,
++ .cleanup_port = hd44780_cleanup_port,
++ .handle_custom_char = hd44780_handle_custom_char,
++ .handle_custom_ioctl = hd44780_handle_custom_ioctl,
++
++ .charmap = charmap,
++};
++
++static void hd44780_read_char(unsigned int offset, unsigned short *data)
++{
++ unsigned int disp_number = offset/disp_size;
++ unsigned char tmp;
++
++ set_cursor(offset);
++ read_display(&tmp, ACCESS_TO_DATA);
++ *data = tmp;
++ mov_cursor(disp_number);
++}
++
++static void hd44780_read_cgram_char(unsigned char index, unsigned char *pixels)
++{
++ unsigned int i;
++
++ write_command(CGRAM_IO | (index << 3));
++ set_bit(CGRAM_STATE+0, &hd44780_flags);
++
++ for (i = 0; i < 8; ++i) {
++ read_display(pixels+i, ACCESS_TO_DATA);
++ pixels[i] &= 0x1f;
++ }
++
++}
++
++static void hd44780_write_char(unsigned int offset, unsigned short data)
++{
++ unsigned int disp_number = offset/disp_size;
++
++ set_cursor(offset);
++ write_display(data & 0xff, ACCESS_TO_WRITE | ACCESS_TO_DATA);
++ mov_cursor(disp_number);
++}
++
++static void hd44780_write_cgram_char(unsigned char index, unsigned char *pixels)
++{
++ unsigned int i;
++
++ /* Move address pointer to index in CGRAM */
++ write_command(CGRAM_IO | (index << 3));
++ set_bit(CGRAM_STATE+0, &hd44780_flags);
++
++ for (i = 0; i < 8; ++i) {
++ pixels[i] &= 0x1f;
++ write_display(pixels[i], ACCESS_TO_WRITE | ACCESS_TO_DATA );
++ }
++}
++
++/* Increment/decrement address mode after a data read/write */
++static void hd44780_address_mode(int mode)
++{
++ if (mode > 0 && ! test_bit(INC_ADDR, &hd44780_flags)) {
++ write_command(CURS_INC | DISP_SHIFT_OFF);
++ set_bit(INC_ADDR, &hd44780_flags);
++ } else if (mode < 0 && test_bit(INC_ADDR, &hd44780_flags)) {
++ write_command(CURS_DEC | DISP_SHIFT_OFF);
++ clear_bit(INC_ADDR, &hd44780_flags);
++ }
++}
++
++static void hd44780_clear_display(void)
++{
++ write_command(CLR_DISP);
++ if (! test_bit(INC_ADDR, &hd44780_flags))
++ write_command(CURS_DEC | DISP_SHIFT_OFF);
++ memset(disp_offset, 0, sizeof(disp_offset));
++}
++
++static int hd44780_validate_driver(void)
++{
++ if (par.cntr_rows != 1 && par.cntr_rows != 2 && par.cntr_rows != 4)
++ par.cntr_rows = DFLT_CNTR_ROWS;
++
++ if (par.cntr_rows != 1)
++ par.flags &= ~HD44780_5X10_FONT;
++
++ if (! par.cntr_cols || par.cntr_cols > MAX_CNTR_COLS/par.cntr_rows)
++ par.cntr_cols = MAX_CNTR_COLS/par.cntr_rows;
++
++ disp_size = par.cntr_rows*par.cntr_cols;
++
++ /* These parameters depend on the hardware and cannot be changed */
++ par.cgram_chars = 8;
++ par.cgram_bytes = 8;
++ par.cgram_char0 = 0;
++
++ return (0);
++}
++
++/* Send init commands to the display */
++static void write_init_command(void)
++{
++ unsigned char command;
++ command = BUS_8_BITS;
++ command |= ((par.cntr_rows == 1) ? DISP_1_LINE : DISP_2_LINES);
++ command |= (test_bit(_5X10_FONT, &hd44780_flags) ? FONT_5X10 : FONT_5X8);
++
++ write_display(command, ACCESS_TO_WRITE);
++ mdelay(20); /* Wait more than 4.1 ms */
++
++ write_display(command, ACCESS_TO_WRITE);
++ udelay(200); /* Wait more than 100 us */
++
++ write_display(command, ACCESS_TO_WRITE);
++ udelay(200); /* Wait more than 100 us */
++
++ write_command(command);
++}
++
++static int hd44780_init_display(void)
++{
++ if (par.flags & HD44780_CHECK_BF)
++ set_bit(_CHECK_BF, &hd44780_flags);
++ else
++ clear_bit(_CHECK_BF, &hd44780_flags);
++
++ if (par.flags & HD44780_4BITS_BUS)
++ set_bit(_4BITS_BUS, &hd44780_flags);
++ else
++ clear_bit(_4BITS_BUS, &hd44780_flags);
++
++ if (par.flags & HD44780_5X10_FONT)
++ set_bit(_5X10_FONT, &hd44780_flags);
++ else
++ clear_bit(_5X10_FONT, &hd44780_flags);
++
++ write_init_command();
++ hd44780_address_mode(1);
++ hd44780_clear_display();
++ write_command(DISP_ON | CURS_OFF | BLINK_OFF);
++ set_bit(DISPLAY_ON, &hd44780_flags);
++ clear_bit(SHOW_CURSOR, &hd44780_flags);
++ clear_bit(CURSOR_BLINK, &hd44780_flags);
++
++ /* Set the CGRAM to default values */
++ hd44780_write_cgram_char(0, cg0);
++ hd44780_write_cgram_char(1, cg1);
++ hd44780_write_cgram_char(2, cg2);
++ hd44780_write_cgram_char(3, cg3);
++ hd44780_write_cgram_char(4, cg4);
++ hd44780_write_cgram_char(5, cg5);
++ hd44780_write_cgram_char(6, cg6);
++ hd44780_write_cgram_char(7, cg7);
++ init_charmap();
++
++ return (0);
++}
++
++static int hd44780_cleanup_display(void)
++{
++ hd44780_clear_display();
++
++ return (0);
++}
++
++static int hd44780_init_port(void)
++{
++ int err = gpio_request_array(lcd_gpios, ARRAY_SIZE(lcd_gpios));
++ if (err) {
++ printk(KERN_ERR "hd44780: error while requesting GPIO pins\n");
++ return 1;
++ }
++
++ return 0;
++}
++
++static int hd44780_cleanup_port(void)
++{
++ gpio_direction_input(LCD_RS);
++ gpio_direction_input(LCD_EN);
++ gpio_direction_input(LCD_DATA0);
++ gpio_direction_input(LCD_DATA1);
++ gpio_direction_input(LCD_DATA2);
++ gpio_direction_input(LCD_DATA3);
++ gpio_direction_input(LCD_DATA4);
++ gpio_direction_input(LCD_DATA5);
++ gpio_direction_input(LCD_DATA6);
++ gpio_direction_input(LCD_DATA7);
++
++ gpio_free_array(lcd_gpios, ARRAY_SIZE(lcd_gpios));
++
++ return 0;
++}
++
++static void display_attr(unsigned char input)
++{
++ unsigned char command;
++
++ switch (ESC_STATE) {
++ case 'a': /* Turn on/off the display cursor */
++ if (input == '1')
++ set_bit(SHOW_CURSOR, &hd44780_flags);
++ else if (input == '0')
++ clear_bit(SHOW_CURSOR, &hd44780_flags);
++ break;
++ case 'b': /* Turn on/off the display cursor blinking */
++ if (input == '1')
++ set_bit(CURSOR_BLINK, &hd44780_flags);
++ else if (input == '0')
++ clear_bit(CURSOR_BLINK, &hd44780_flags);
++ break;
++ case 'h': /* Turn on/off the display */
++ if (input == '1')
++ set_bit(DISPLAY_ON, &hd44780_flags);
++ else if (input == '0')
++ clear_bit(DISPLAY_ON, &hd44780_flags);
++ break;
++ }
++
++ command = (test_bit(DISPLAY_ON, &hd44780_flags) ? DISP_ON : DISP_OFF);
++ command |= (test_bit(SHOW_CURSOR, &hd44780_flags) ? CURS_ON : CURS_OFF);
++ command |= (test_bit(CURSOR_BLINK, &hd44780_flags) ? BLINK_ON : BLINK_OFF);
++
++ if (ESC_STATE == 'h')
++ write_command(command);
++}
++
++static int hd44780_handle_custom_char(unsigned int _input)
++{
++ unsigned char input = _input & 0xff;
++
++ if (_input & (~0xff)) {
++ switch (ESC_STATE) {
++ case 'a': /* Turn on/off the display cursor */
++ case 'b': /* Turn on/off the display cursor blinking */
++ case 'h': /* Turn on/off the the display */
++ display_attr(input);
++ return (0);
++ case 'l': /* Turn on/off the backlight */
++ if (input == '1')
++ set_bit(BACKLIGHT, &hd44780_flags);
++ else if (input == '0')
++ clear_bit(BACKLIGHT, &hd44780_flags);
++ read_ac(ACCESS_TO_READ);
++ return (0);
++ }
++ }
++
++ switch (input) {
++ case 'a': /* Turn on/off the display cursor */
++ case 'b': /* Turn on/off the display cursor blinking */
++ case 'h': /* Turn on/off the display */
++ case 'l': /* Turn on/off the backlight */
++ SET_ESC_STATE(input);
++ return (1);
++ case 'd': /* Shift display cursor Right */
++ write_command(SHIFT_CURS | SHIFT_RIGHT);
++ return (0);
++ case 'e': /* Shift display cursor Left */
++ write_command(SHIFT_CURS | SHIFT_LEFT);
++ return (0);
++ case 'f': /* Shift display Right */
++ write_command(SHIFT_DISP | SHIFT_RIGHT);
++ return (0);
++ case 'g': /* Shift display Left */
++ write_command(SHIFT_DISP | SHIFT_LEFT);
++ return (0);
++ }
++
++ return (-1);
++}
++
++static int hd44780_handle_custom_ioctl(unsigned int num, unsigned long arg, unsigned int user_space)
++{
++ unsigned char *buffer = (unsigned char *)arg;
++
++ if (num != HD44780_READ_AC)
++ return (-ENOIOCTLCMD);
++
++ if (user_space)
++ put_user(read_ac(ACCESS_TO_READ), buffer);
++ else
++ buffer[0] = read_ac(ACCESS_TO_READ);
++
++ return (0);
++}
++
++#ifdef USE_PROC
++static int hd44780_proc_status(char *buffer, char **start, off_t offset, int size, int *eof, void *data)
++{
++ char *temp = buffer;
++
++ /* Print display configuration */
++ temp += sprintf(temp,
++ "Interface:\t%u bits\n"
++ "Display rows:\t%d\n"
++ "Display cols:\t%d\n"
++ "Screen rows:\t%d\n"
++ "Screen cols:\t%d\n"
++ "Read:\t\t%sabled\n"
++ "Busy flag chk:\t%sabled\n"
++ "Assigned minor:\t%u\n",
++ (test_bit(_4BITS_BUS, &hd44780_flags) ? 4 : 8),
++ par.cntr_rows, par.cntr_cols,
++ par.vs_rows, par.vs_cols,
++ (hd44780.read_char ? "En" : "Dis"),
++ (test_bit(_CHECK_BF, &hd44780_flags) ? "En" : "Dis"),
++ par.minor);
++
++ return (temp-buffer);
++}
++
++static int hd44780_proc_cgram(char *buffer, char **start, off_t offset, int size, int *eof, void *data)
++{
++ char *temp = buffer;
++ unsigned int i;
++
++ temp += sprintf(temp, "static void init_charmap(void)\n{\n"
++ "\t/*\n"
++ "\t * charmap[char mapped to cg0] = 0;\n"
++ "\t * charmap[char mapped to cg1] = 1;\n"
++ "\t * charmap[char mapped to cg2] = 2;\n"
++ "\t * charmap[char mapped to cg3] = 3;\n"
++ "\t * charmap[char mapped to cg4] = 4;\n"
++ "\t * charmap[char mapped to cg5] = 5;\n"
++ "\t * charmap[char mapped to cg6] = 6;\n"
++ "\t * charmap[char mapped to cg7] = 7;\n"
++ "\t */\n"
++ "}\n\n");
++
++ for (i = 0; i < 8; ++i) {
++ unsigned int j;
++ unsigned char cgram_buffer[8];
++
++ temp += sprintf(temp, "static unsigned char cg%u[] = { ", i);
++ hd44780_read_cgram_char(i, cgram_buffer);
++ for (j = 0; j < 8; ++j)
++ temp += sprintf(temp, "0x%.2x%s", cgram_buffer[j], (j == 7 ? " };\n" : ", "));
++ }
++
++ return (temp-buffer);
++}
++
++static void create_proc_entries(void)
++{
++ SET_PROC_LEVEL(0);
++ if (create_proc_read_entry("status", 0, hd44780.driver_proc_root, hd44780_proc_status, NULL) == NULL) {
++ printk(KERN_ERR "hd44780: cannot create /proc/lcd/%s/status\n", par.name);
++ return;
++ }
++ SET_PROC_LEVEL(1);
++ if (create_proc_read_entry("cgram.h", 0, hd44780.driver_proc_root, hd44780_proc_cgram, NULL) == NULL) {
++ printk(KERN_ERR "hd44780: cannot create /proc/lcd/%s/cgram.h\n", par.name);
++ return;
++ }
++ SET_PROC_LEVEL(2);
++}
++
++static void remove_proc_entries(void)
++{
++ switch (PROC_LEVEL) {
++ case 2:
++ remove_proc_entry("cgram.h", hd44780.driver_proc_root);
++ case 1:
++ remove_proc_entry("status", hd44780.driver_proc_root);
++ }
++ SET_PROC_LEVEL(0);
++}
++#endif
++
++/* Initialization */
++static int __init hd44780_init_module(void)
++{
++ int ret;
++
++#ifdef MODULE
++ if ((ret = request_module("lcd-linux"))) {
++ printk(KERN_ERR "hd44780: request_module() returned %d\n", ret);
++ if (ret < 0) {
++ if (ret != -ENOSYS) {
++ printk(KERN_ERR "hd44780: failure while loading module lcd-linux\n");
++ return (ret);
++ }
++ printk(KERN_ERR "hd44780: your kernel does not have kmod or kerneld support;\n");
++ printk(KERN_ERR "hd44780: remember to load the lcd-linux module before\n");
++ printk(KERN_ERR "hd44780: loading the hd44780 module\n");
++ }
++ }
++
++ if (flags != DFLT_FLAGS) par.flags = flags;
++ if (tabstop != DFLT_TABSTOP) par.tabstop = tabstop;
++ if (cntr_rows != DFLT_CNTR_ROWS) par.cntr_rows = cntr_rows;
++ if (cntr_cols != DFLT_CNTR_COLS) par.cntr_cols = cntr_cols;
++ if (vs_rows != DFLT_VS_ROWS) par.vs_rows = vs_rows;
++ if (vs_cols != DFLT_VS_COLS) par.vs_cols = vs_cols;
++ if (minor != HD44780_MINOR) par.minor = minor;
++#endif
++
++ lcd_driver_setup(&hd44780);
++ if ((ret = lcd_register_driver(&hd44780, &par)))
++ return (ret);
++
++#ifdef USE_PROC
++ if (hd44780.driver_proc_root)
++ create_proc_entries();
++#endif
++
++ printk(KERN_INFO "hd44780: ts72xx driver loaded\n" );
++
++ return (0);
++}
++
++static void __exit hd44780_cleanup_module(void)
++{
++#ifdef USE_PROC
++ if (hd44780.driver_proc_root)
++ remove_proc_entries();
++#endif
++
++ lcd_unregister_driver(&hd44780, &par);
++}
++
++module_init(hd44780_init_module)
++module_exit(hd44780_cleanup_module)
+diff --git a/drivers/lcd-linux/lcd-linux.c b/drivers/lcd-linux/lcd-linux.c
+new file mode 100644
+index 0000000..f4cb1da
+--- /dev/null
++++ b/drivers/lcd-linux/lcd-linux.c
+@@ -0,0 +1,3026 @@
++/* lcd-linux.c
++ *
++ * $Id: lcd-linux.c,v 1.308 2010/03/03 14:56:22 mjona Exp $
++ *
++ * Software layer to drive LCD displays under Linux.
++ *
++ * Copyright (C) 2005 - 2009 Mattia Jona-Lasinio (mjona@users.sourceforge.net)
++ *
++ * 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/version.h>
++
++#ifndef KERNEL_VERSION
++#define KERNEL_VERSION(a, b, c) (((a) << 16) + ((b) << 8) + (c))
++#endif
++
++#ifndef LINUX_VERSION_CODE
++#error - LINUX_VERSION_CODE undefined in 'linux/version.h'
++#endif
++
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 33)
++#include <generated/autoconf.h>
++#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0)
++#include <linux/autoconf.h>
++#else
++#include <linux/config.h>
++#endif
++
++#ifdef CONFIG_PROC_FS
++#define USE_PROC
++#else
++#undef USE_PROC
++#endif
++
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26)
++#include <linux/semaphore.h>
++#ifndef init_MUTEX
++#define init_MUTEX(x) sema_init(x, 1)
++#endif
++#else
++#include <asm/semaphore.h>
++#endif
++
++#include <linux/bitops.h>
++
++#include <linux/kernel.h>
++#include <linux/module.h>
++#include <linux/sched.h>
++
++#include <linux/fs.h>
++
++#include <asm/uaccess.h>
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0)
++#include <linux/device.h>
++#endif
++#include <linux/init.h>
++#include <linux/list.h>
++#include <linux/slab.h>
++#include <linux/selection.h>
++#include <linux/vmalloc.h>
++
++#ifdef USE_PROC
++#include <linux/proc_fs.h>
++#endif
++
++#define LCD_LINUX_MAIN
++#include <linux/lcd-linux.h>
++
++static inline void __set_br(unsigned long *x, unsigned long val, unsigned long start, unsigned long len)
++{
++ unsigned long mask = (1 << len)-1;
++
++ if (val <= mask) {
++ mask <<= start;
++ val <<= start;
++ *x = (*x & ~mask) | val;
++ }
++}
++
++static inline unsigned long __get_br(unsigned long x, unsigned long start, unsigned long len)
++{
++ return ((x >> start) & ((1 << len)-1));
++}
++
++/*** struct_flags ***/
++
++/* internal flags: bits [0:15] of struct_flags (16 flags allowed) */
++#define NEED_WRAP 0 /* Next char will trigger a newline */
++#define DECIM 1 /* Insert mode */
++#define DECOM 2 /* Row origin of cursor: absolute or relative to scrolling region */
++#define DECAWM 3 /* Autowrap */
++#define DECSCNM 4 /* Inverted screen */
++#define CRLF 5 /* Follow lf, vt, ff, with a cr */
++#define INC_CURS_POS 6 /* Increment cursor position after data read/write */
++#define QUES 7 /* CSI Esc sequence contains a question mark */
++#define USER_SPACE 8 /* If set, the buffer pointed by arg in do_lcd_ioctl() is
++ * assumed to be in user space otherwise it is in kernel space */
++#define NULL_CHARMAP 9 /* The driver doesn't provide a charmap so the
++ * lcd-linux layer provides one*/
++#define CAN_DO_COLOR 10 /* The display is color capable */
++#define WITH_ATTR 11 /* If set, the void * buffer in do_lcd_read/write() contains
++ * attributes and therefore is an unsigned short * otherwise it
++ * is an unsigned char *
++ */
++
++/* input states: bits [24:27] of struct_flags (16 states allowed) */
++#define NORMAL 0 /* Normal mode */
++#define RAW 1 /* Raw mode (console emulation disabled) */
++#define SYN 2 /* Synchronous Idle mode */
++#define ESC 3 /* Escape mode */
++#define CSI 4 /* CSI escape mode */
++#define ESC_G0 5 /* G0 character set */
++#define ESC_G1 6 /* G1 character set */
++#define ESC_HASH 7 /* ESC # escape sequence */
++#define ESC_PERCENT 8 /* ESC % escape sequence */
++#define ARG 9 /* Waiting for arguments for the lcd-linux layer */
++#define ARG_DRIVER 10 /* Waiting for arguments for the display driver */
++
++#define SET_ESC_STATE(p, x) __set_br(&(p)->struct_flags, x, 16, 8)
++#define SET_INPUT_STATE(p, x) __set_br(&(p)->struct_flags, x, 24, 4)
++#define SET_INIT_LEVEL(p, x) __set_br(&(p)->struct_flags, x, 28, 2)
++#define SET_PROC_LEVEL(p, x) __set_br(&(p)->struct_flags, x, 30, 2)
++#define ESC_STATE(p) __get_br((p)->struct_flags, 16, 8)
++#define INPUT_STATE(p) __get_br((p)->struct_flags, 24, 4)
++#define INIT_LEVEL(p) __get_br((p)->struct_flags, 28, 2)
++#define PROC_LEVEL(p) __get_br((p)->struct_flags, 30, 2)
++
++/*** attributes ***/
++#define I_MASK 0x03 /* Intensity (0 = low, 1 = normal, 2 = bright) */
++#define ULINE 0x04 /* Underlined text */
++#define REVERSE 0x08 /* Reversed video text */
++#define BLINK 0x80 /* Blinking text */
++
++/*** Color attributes ***/
++#define FG_COLOR 0x07 /* Foreground color mask */
++#define FG_BRIGHT 0x08 /* Foreground bright color */
++#define FG_MASK (FG_BRIGHT | FG_COLOR) /* Foreground mask */
++#define BG_COLOR 0x70 /* Background color mask */
++#define BG_BRIGHT 0x80 /* Background bright color */
++#define BG_MASK (BG_BRIGHT | BG_COLOR) /* Background mask */
++
++#define NPAR 16 /* Max number of parameters in CSI escape sequence */
++#define FLIP_BUF_SIZE (1 << 6) /* Flip buffer size (64 bytes) MUST be a power of 2 */
++
++struct lcd_struct {
++ struct list_head lcd_list; /* Doubly linked list */
++ struct semaphore lcd_sem; /* Locks this structure */
++ struct lcd_driver *driver; /* The driver associated to this struct */
++ struct lcd_parameters *par; /* The parameters associated to this struct */
++ unsigned long struct_flags; /* Flags for internal use only */
++ unsigned int refcount; /* Number of references to this struct */
++
++ unsigned short *display; /* The display buffer */
++
++ unsigned short *fb; /* The virtual screen framebuffer */
++ unsigned int fb_size; /* Size of the framebuffer */
++ unsigned int frame_base; /* Offset of row 0, column 0 of a frame in fb */
++ unsigned int frame_size; /* Size of the frame */
++
++ unsigned int row; /* Current row in virtual screen */
++ unsigned int col; /* Current column in virtual screen */
++ unsigned int s_offset; /* Saved cursor position in virtual screen */
++
++ unsigned int top; /* Top scroll row in virtual screen */
++ unsigned int bot; /* Bottom scroll row in virtual screen */
++
++ int esc_args; /* Number of arguments for a normal escape sequence */
++ unsigned int csi_args[NPAR]; /* CSI parameters */
++ unsigned int index; /* Index in csi_args and counter for cgram characters generation */
++ unsigned char cgram_index; /* Index of the cgram character to be created */
++ unsigned char *cgram_buffer; /* Buffer for cgram operations in this driver */
++
++ unsigned short erase_char; /* Character to be used when erasing */
++ unsigned char attr; /* Current attributes */
++ unsigned char color; /* Color for normal intensity mode */
++ unsigned char s_color; /* Saved color for normal intensity mode */
++ unsigned char defcolor; /* Default color for normal intensity mode */
++ unsigned char ulcolor; /* Color for underline mode */
++ unsigned char halfcolor; /* Color for low intensity mode */
++ unsigned char attributes; /* Packed attributes */
++ unsigned char s_attributes; /* Saved packed attributes */
++
++ unsigned char *s_charmap; /* Saved character map for this driver */
++ unsigned char *flip_buf; /* High speed flip buffer */
++};
++
++/** Function prototypes **/
++
++/* Init/Cleanup the driver */
++static int init_driver(struct lcd_struct *);
++static int cleanup_driver(struct lcd_struct *);
++
++/* Read from/Write to the driver */
++static void read_data(struct lcd_struct *, unsigned short *);
++static void read_cgram(struct lcd_struct *, unsigned char, unsigned char *);
++static void write_data(struct lcd_struct *, unsigned short);
++static void write_cgram(struct lcd_struct *, unsigned char, unsigned char *);
++
++/* Input handlers */
++static void cr(struct lcd_struct *);
++static void lf(struct lcd_struct *);
++static void control_char(struct lcd_struct *, unsigned char);
++static void handle_csi(struct lcd_struct *, unsigned char);
++static int handle_custom_esc(struct lcd_struct *, unsigned int);
++static int handle_esc(struct lcd_struct *, unsigned char);
++static void handle_input(struct lcd_struct *, unsigned short);
++
++/* Low level file operations */
++static ssize_t do_lcd_read(struct lcd_struct *, void *, size_t);
++static ssize_t do_lcd_write(struct lcd_struct *, const void *, size_t);
++static int do_lcd_open(struct lcd_struct *);
++static int do_lcd_release(struct lcd_struct *);
++static int do_lcd_ioctl(struct lcd_struct *, unsigned int, unsigned long);
++
++/* Proc functions */
++#ifdef USE_PROC
++static void create_driver_proc_entries(struct lcd_struct *);
++static void remove_driver_proc_entries(struct lcd_struct *);
++#endif
++
++/* globals */
++static unsigned int major = LCD_MAJOR; /* Major number for LCD-Linux device */
++static unsigned short minors = LCD_MINORS; /* Minor numbers allocated for LCD-Linux */
++static LIST_HEAD(lcd_drivers); /* Registered lcd drivers */
++static struct semaphore drivers_sem; /* Locks the lcd_drivers list */
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 13)
++static struct class *lcd_linux_class;
++#endif
++#ifdef USE_PROC
++static struct proc_dir_entry *lcd_proc_root;
++#endif
++/* End of globals */
++
++#ifdef MODULE
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0)
++#include <linux/device.h>
++MODULE_ALIAS_CHARDEV_MAJOR(LCD_MAJOR);
++#endif
++MODULE_DESCRIPTION("Software layer to drive LCD displays under Linux.");
++MODULE_AUTHOR("Mattia Jona-Lasinio <mjona@users.sourceforge.net>");
++#ifdef MODULE_LICENSE
++MODULE_LICENSE("GPL");
++#endif
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0)
++module_param(minors, ushort, 0444);
++#else
++MODULE_PARM(minors, "h");
++#endif
++MODULE_PARM_DESC(minors, "Minor numbers allocated for LCD-Linux (default: " string(LCD_MINORS) ")");
++#else
++
++/*
++ * Parse boot command line
++ *
++ * lcd=minors
++ */
++static int __init lcd_linux_boot_init(char *cmdline)
++{
++ unsigned short args;
++
++ if ((args = simple_strtoul(cmdline, NULL, 0)))
++ minors = args;
++
++ return (1);
++}
++
++__setup("lcd=", lcd_linux_boot_init);
++#endif /* MODULE */
++
++/* Macros for iterator handling */
++static inline unsigned int iterator_inc_(unsigned int iterator, const unsigned int module)
++{
++ return ((++iterator)%module);
++}
++
++static inline unsigned int iterator_dec_(unsigned int iterator, const unsigned int module)
++{
++ return (iterator ? --iterator : module-1);
++}
++
++#define iterator_inc(iterator, module) (iterator = iterator_inc_(iterator, module))
++#define iterator_dec(iterator, module) (iterator = iterator_dec_(iterator, module))
++
++/* Uncomment the following two lines
++ * for non-atomic set_bit and clear_bit
++ */
++//#define set_bit __set_bit
++//#define clear_bit __clear_bit
++
++/************************************
++ * Low level routines and utilities *
++ ************************************/
++/*
++ * Set whether the address counter should be incremented
++ * or decremented after a Read/Write
++ */
++static void address_mode(struct lcd_struct *p, int mode)
++{
++ struct lcd_driver *driver = p->driver;
++
++ if (mode > 0 && ! test_bit(INC_CURS_POS, &p->struct_flags)) {
++ if (driver->address_mode)
++ driver->address_mode(mode);
++ set_bit(INC_CURS_POS, &p->struct_flags);
++ } else if (mode < 0 && test_bit(INC_CURS_POS, &p->struct_flags)) {
++ if (driver->address_mode)
++ driver->address_mode(mode);
++ clear_bit(INC_CURS_POS, &p->struct_flags);
++ }
++}
++
++/* WARNING!! This function returns an int because if iterator is not
++ * within the visible area of the frame it returns -1
++ */
++static inline int vs_to_frame_(struct lcd_struct *p, unsigned int iterator)
++{
++ unsigned int vs_rows = p->par->vs_rows;
++ unsigned int vs_cols = p->par->vs_cols;
++ unsigned int row = iterator/vs_cols;
++ unsigned int col = iterator%vs_cols;
++ unsigned int frame_base_row = p->frame_base/vs_cols;
++ unsigned int frame_base_col = p->frame_base%vs_cols;
++ unsigned int frame_rows = p->par->cntr_rows*p->par->num_cntr;
++ unsigned int frame_cols = p->par->cntr_cols;
++
++ if (vs_rows == frame_rows && vs_cols == frame_cols)
++ return (iterator);
++
++ if (row < frame_base_row || row >= frame_base_row+frame_rows)
++ return (-1);
++ if (col < frame_base_col || col >= frame_base_col+frame_cols)
++ return (-1);
++
++ return ((row-frame_base_row)*frame_cols+(col-frame_base_col));
++}
++
++/* Given 'iterator' in vs, returns the offset in vs corresponding to the nearest
++ * visible offset in vs, or returns 'iterator' if it is already visible.
++ */
++static unsigned int round_vs_(struct lcd_struct *p, unsigned int iterator)
++{
++ unsigned int vs_rows = p->par->vs_rows;
++ unsigned int vs_cols = p->par->vs_cols;
++ unsigned int row = iterator/vs_cols;
++ unsigned int col = iterator%vs_cols;
++ unsigned int frame_base_row = p->frame_base/vs_cols;
++ unsigned int frame_base_col = p->frame_base%vs_cols;
++ unsigned int frame_rows = p->par->cntr_rows*p->par->num_cntr;
++ unsigned int frame_cols = p->par->cntr_cols;
++
++ if (vs_rows == frame_rows && vs_cols == frame_cols)
++ return (iterator);
++
++ if (row < frame_base_row)
++ row = frame_base_row;
++ else if (row >= frame_base_row+frame_rows)
++ row = frame_base_row+(frame_rows-1);
++
++ if (col < frame_base_col)
++ col = frame_base_col;
++ else if (col >= frame_base_col+frame_cols)
++ col = frame_base_col+(frame_cols-1);
++
++ return ((row*vs_cols)+col);
++}
++
++#define round_vs(p, iterator) (iterator = round_vs_(p, iterator))
++
++/*
++ * Sync the frame area starting at offset s, ending at offset e with fb content.
++ */
++static void redraw_screen(struct lcd_struct *p, unsigned int s, unsigned int e)
++{
++ unsigned int len;
++ unsigned int row = p->row, col = p->col;
++ unsigned int inc_set = test_bit(INC_CURS_POS, &p->struct_flags);
++ unsigned int frame_cols = p->par->cntr_cols;
++ unsigned int vs_cols = p->par->vs_cols;
++ unsigned long flags;
++
++ if (s >= p->fb_size || e >= p->fb_size || e < s || e < p->frame_base)
++ return;
++
++ round_vs(p, s);
++ round_vs(p, e);
++
++ len = 1+e-s;
++
++ if (! inc_set)
++ s = e;
++
++ p->row = s/vs_cols;
++ p->col = s%vs_cols;
++
++ flags = p->struct_flags;
++ clear_bit(NEED_WRAP, &p->struct_flags);
++ clear_bit(DECIM, &p->struct_flags);
++ set_bit(DECAWM, &p->struct_flags);
++ SET_INPUT_STATE(p, RAW);
++ if (inc_set)
++ while (len--)
++ if (vs_to_frame_(p, (p->row*vs_cols)+p->col) < 0) {
++ s += vs_cols-frame_cols;
++ len -= vs_cols-frame_cols-1;
++ p->row = s/vs_cols;
++ p->col = s%vs_cols;
++ } else {
++ write_data(p, p->fb[s++]);
++ if (test_bit(NEED_WRAP, &p->struct_flags)) {
++ cr(p);
++ lf(p);
++ }
++ }
++ else
++ while (len--)
++ if (vs_to_frame_(p, (p->row*vs_cols)+p->col) < 0) {
++ s -= vs_cols-frame_cols;
++ len -= vs_cols-frame_cols-1;
++ p->row = s/vs_cols;
++ p->col = s%vs_cols;
++ } else {
++ write_data(p, p->fb[s--]);
++ if (test_bit(NEED_WRAP, &p->struct_flags)) {
++ cr(p);
++ lf(p);
++ }
++ }
++ p->struct_flags = flags;
++
++ p->row = row; p->col = col;
++}
++
++static int show_cursor(struct lcd_struct *p)
++{
++ unsigned int vs_rows = p->par->vs_rows;
++ unsigned int vs_cols = p->par->vs_cols;
++ unsigned int frame_base, frame_base_row, frame_base_col;
++ unsigned int frame_rows = p->par->cntr_rows*p->par->num_cntr;
++ unsigned int frame_cols = p->par->cntr_cols;
++ unsigned int tmp = frame_cols/2;
++
++ if (vs_rows == frame_rows && vs_cols == frame_cols)
++ return (0);
++
++ if (test_bit(INC_CURS_POS, &p->struct_flags)) {
++ /* cursor always on the lowest row of the display */
++ frame_base_row = 0;
++ frame_base_col = 0;
++ if (p->row >= frame_rows)
++ frame_base_row = p->row-(frame_rows-1);
++ if (p->col >= frame_cols) {
++ frame_base_col = p->col-(frame_cols-1);
++ if (tmp) {
++ tmp = (tmp-(frame_base_col%tmp))%tmp;
++ if (frame_base_col+tmp <= vs_cols-frame_cols)
++ frame_base_col += tmp;
++ }
++ }
++ } else {
++ /* cursor always on the uppermost row of the display */
++ frame_base_row = vs_rows-frame_rows;
++ frame_base_col = vs_cols-frame_cols;
++ if (p->row < vs_rows-frame_rows)
++ frame_base_row = p->row;
++ if (p->col < vs_cols-frame_cols) {
++ frame_base_col = p->col;
++ if (tmp) {
++ tmp = frame_base_col%tmp;
++ if (frame_base_col >= tmp)
++ frame_base_col -= tmp;
++ }
++ }
++ }
++
++ frame_base = p->frame_base;
++ p->frame_base = (frame_base_row*vs_cols)+frame_base_col;
++
++ return (frame_base != p->frame_base);
++}
++
++/*
++ * Move the visible screen area at user's wish
++ */
++static void browse_screen(struct lcd_struct *p, unsigned char dir)
++{
++ unsigned int vs_rows = p->par->vs_rows;
++ unsigned int vs_cols = p->par->vs_cols;
++ unsigned int frame_base_row = p->frame_base/vs_cols;
++ unsigned int frame_base_col = p->frame_base%vs_cols;
++ unsigned int frame_rows = p->par->cntr_rows*p->par->num_cntr;
++ unsigned int frame_cols = p->par->cntr_cols;
++
++ switch (dir) {
++ case '1': /* Up */
++ if (! frame_base_row)
++ return;
++ --frame_base_row;
++ break;
++ case '2': /* Down */
++ if (frame_base_row >= vs_rows-frame_rows)
++ return;
++ ++frame_base_row;
++ break;
++ case '3': /* Left */
++ if (! frame_base_col)
++ return;
++ --frame_base_col;
++ break;
++ case '4': /* Right */
++ if (frame_base_col >= vs_cols-frame_cols)
++ return;
++ ++frame_base_col;
++ break;
++ default:
++ return;
++ }
++
++ p->frame_base = (frame_base_row*vs_cols)+frame_base_col;
++ redraw_screen(p, 0, p->fb_size-1);
++}
++
++static inline void __memset_short(unsigned short *buf, unsigned short c, unsigned int len)
++{
++ while (len--)
++ *buf++ = c;
++}
++
++/*
++ * A memset implementation writing to LCD instead of memory locations.
++ */
++static void lcd_memset(struct lcd_struct *p, unsigned int d, unsigned short c, unsigned int len)
++{
++ unsigned int inc_set = test_bit(INC_CURS_POS, &p->struct_flags);
++
++ if (! len || d >= p->fb_size)
++ return;
++
++ if (inc_set && d+len > p->fb_size)
++ len = p->fb_size-d;
++ else if (! inc_set && len > d+1)
++ len = d+1;
++
++ if (! inc_set)
++ d -= len-1;
++ __memset_short(p->fb+d, c, len);
++
++ if (show_cursor(p))
++ redraw_screen(p, 0, p->fb_size-1);
++ else
++ redraw_screen(p, d, d+(len-1));
++}
++
++static inline void __memcpy_short(unsigned short *d, unsigned short *s, unsigned int len, int dir)
++{
++ if (dir > 0)
++ while (len--)
++ *d++ = *s++;
++ else
++ while (len--)
++ *d-- = *s--;
++}
++
++/*
++ * A memmove implementation writing to LCD instead of memory locations.
++ * Copy is done in a non destructive way. Display regions may overlap.
++ */
++static void lcd_memmove(struct lcd_struct *p, unsigned int d, unsigned int s, unsigned int len)
++{
++ if (! len || d == s || d >= p->fb_size || s >= p->fb_size)
++ return;
++
++ if (d < s) {
++ if (test_bit(INC_CURS_POS, &p->struct_flags)) {
++ if (s+len > p->fb_size)
++ len = p->fb_size-s;
++ } else {
++ if (len > d+1)
++ len = d+1;
++ d -= len-1;
++ s -= len-1;
++ }
++ __memcpy_short(p->fb+d, p->fb+s, len, 1);
++ if (show_cursor(p))
++ redraw_screen(p, 0, p->fb_size-1);
++ else
++ redraw_screen(p, d, d+(len-1));
++ } else {
++ if (test_bit(INC_CURS_POS, &p->struct_flags)) {
++ if (d+len > p->fb_size)
++ len = p->fb_size-d;
++ d += len-1;
++ s += len-1;
++ } else {
++ if (len > s+1)
++ len = s+1;
++ }
++ __memcpy_short(p->fb+d, p->fb+s, len, -1);
++ if (show_cursor(p))
++ redraw_screen(p, 0, p->fb_size-1);
++ else
++ redraw_screen(p, d-(len-1), d);
++ }
++}
++
++static void scrup(struct lcd_struct *p, unsigned int t, unsigned int b, unsigned int nr)
++{
++ unsigned int vs_rows = p->par->vs_rows;
++ unsigned int vs_cols = p->par->vs_cols;
++ unsigned int d, s;
++
++ if (t+nr >= b)
++ nr = b-t-1;
++ if (b > vs_rows || t >= b || nr < 1)
++ return;
++ d = t*vs_cols;
++ s = (t+nr)*vs_cols;
++ if (test_bit(INC_CURS_POS, &p->struct_flags)) {
++ lcd_memmove(p, d, s, (b-t-nr)*vs_cols);
++ lcd_memset(p, d+(b-t-nr)*vs_cols, p->erase_char, nr*vs_cols);
++ } else {
++ lcd_memmove(p, d+(b-t-nr)*vs_cols-1, s+(b-t-nr)*vs_cols-1, (b-t-nr)*vs_cols);
++ lcd_memset(p, d+(b-t)*vs_cols-1, p->erase_char, nr*vs_cols);
++ }
++}
++
++static void scrdown(struct lcd_struct *p, unsigned int t, unsigned int b, unsigned int nr)
++{
++ unsigned int vs_rows = p->par->vs_rows;
++ unsigned int vs_cols = p->par->vs_cols;
++ unsigned int d, s;
++
++ if (t+nr >= b)
++ nr = b-t-1;
++ if (b > vs_rows || t >= b || nr < 1)
++ return;
++ s = t*vs_cols;
++ d = (t+nr)*vs_cols;
++ if (test_bit(INC_CURS_POS, &p->struct_flags)) {
++ lcd_memmove(p, d, s, (b-t-nr)*vs_cols);
++ lcd_memset(p, s, p->erase_char, nr*vs_cols);
++ } else {
++ lcd_memmove(p, d+(b-t-nr)*vs_cols-1, s+(b-t-nr)*vs_cols-1, (b-t-nr)*vs_cols);
++ lcd_memset(p, s+nr*vs_cols-1, p->erase_char, nr*vs_cols);
++ }
++}
++
++static void lcd_insert_char(struct lcd_struct *p, unsigned int nr)
++{
++ unsigned int vs_cols = p->par->vs_cols;
++ unsigned int pos = (p->row*vs_cols)+p->col;
++
++ clear_bit(NEED_WRAP, &p->struct_flags);
++ if (test_bit(INC_CURS_POS, &p->struct_flags))
++ lcd_memmove(p, pos+nr, pos, vs_cols-p->col-nr);
++ else
++ lcd_memmove(p, pos-nr, pos, p->col-(nr-1));
++ lcd_memset(p, pos, p->erase_char, nr);
++}
++
++static void lcd_delete_char(struct lcd_struct *p, unsigned int nr)
++{
++ unsigned int vs_cols = p->par->vs_cols;
++ unsigned int pos = (p->row*vs_cols)+p->col;
++
++ clear_bit(NEED_WRAP, &p->struct_flags);
++ if (test_bit(INC_CURS_POS, &p->struct_flags)) {
++ lcd_memmove(p, pos, pos+nr, vs_cols-(p->col+nr));
++ lcd_memset(p, (p->row+1)*vs_cols-nr, p->erase_char, nr);
++ } else {
++ lcd_memmove(p, pos, pos-nr, p->col-(nr-1));
++ lcd_memset(p, (p->row*vs_cols)+(nr-1), p->erase_char, nr);
++ }
++}
++
++
++
++
++
++/******************************************************************************
++ ************************* VT 102 Emulation *************************
++ ******************************************************************************/
++
++/**********************
++ * Control characters *
++ **********************/
++static void bs(struct lcd_struct *p)
++{
++ clear_bit(NEED_WRAP, &p->struct_flags);
++ if (test_bit(INC_CURS_POS, &p->struct_flags)) {
++ if (p->col)
++ --p->col;
++ } else {
++ if (p->col+1 < p->par->vs_cols)
++ ++p->col;
++ }
++}
++
++static void cr(struct lcd_struct *p)
++{
++ clear_bit(NEED_WRAP, &p->struct_flags);
++ p->col = (test_bit(INC_CURS_POS, &p->struct_flags) ? 0 : p->par->vs_cols-1);
++}
++
++static void lf(struct lcd_struct *p)
++{
++ clear_bit(NEED_WRAP, &p->struct_flags);
++ if (test_bit(INC_CURS_POS, &p->struct_flags)) {
++ if (p->row+1 < p->bot)
++ ++p->row;
++ else if (INPUT_STATE(p) != RAW) {
++ show_cursor(p);
++ scrup(p, p->top, p->bot, 1);
++ }
++ } else {
++ if (p->row > p->top)
++ --p->row;
++ else if (INPUT_STATE(p) != RAW) {
++ show_cursor(p);
++ scrdown(p, p->top, p->bot, 1);
++ }
++ }
++}
++
++static void ri(struct lcd_struct *p)
++{
++ clear_bit(NEED_WRAP, &p->struct_flags);
++ if (test_bit(INC_CURS_POS, &p->struct_flags)) {
++ if (p->row > p->top)
++ --p->row;
++ else {
++ show_cursor(p);
++ scrdown(p, p->top, p->bot, 1);
++ }
++ } else {
++ if (p->row+1 < p->bot)
++ ++p->row;
++ else {
++ show_cursor(p);
++ scrup(p, p->top, p->bot, 1);
++ }
++ }
++}
++
++static void ff(struct lcd_struct *p)
++{
++ unsigned int vs_rows = p->par->vs_rows;
++ unsigned int vs_cols = p->par->vs_cols;
++
++ clear_bit(NEED_WRAP, &p->struct_flags);
++ if (p->driver->clear_display) {
++ p->driver->clear_display();
++ __memset_short(p->fb, p->erase_char, p->fb_size);
++ __memset_short(p->display, p->erase_char, p->frame_size);
++ p->frame_base = 0;
++ } else if (test_bit(INC_CURS_POS, &p->struct_flags))
++ lcd_memset(p, 0, p->erase_char, p->fb_size);
++ else
++ lcd_memset(p, p->fb_size-1, p->erase_char, p->fb_size);
++
++ if (test_bit(INC_CURS_POS, &p->struct_flags))
++ p->row = p->col = 0;
++ else {
++ p->row = vs_rows-1;
++ p->col = vs_cols-1;
++ }
++}
++
++static void tab(struct lcd_struct *p)
++{
++ struct lcd_parameters *par = p->par;
++ unsigned int i, vs_cols = par->vs_cols;
++
++ clear_bit(NEED_WRAP, &p->struct_flags);
++
++ if (! par->tabstop)
++ return;
++
++ if (test_bit(INC_CURS_POS, &p->struct_flags)) {
++ i = par->tabstop-(p->col%par->tabstop);
++ if (p->col+i < vs_cols)
++ p->col += i;
++ } else {
++ i = p->col%par->tabstop;
++ i = (i == 0 ? par->tabstop : i);
++ if (p->col >= i)
++ p->col -= i;
++ }
++}
++
++/*
++ * Control character handler.
++ */
++static void control_char(struct lcd_struct *p, unsigned char val)
++{
++ switch (val) {
++ case 0x08: /* BS: Back Space (^H) */
++ case 0x7f: /* DEL: Delete */
++ bs(p);
++ return;
++
++ case 0x09: /* HT: Horizontal Tab (^I) */
++ tab(p);
++ return;
++
++ case 0x0c: /* FF: Form Feed (^L) */
++ ff(p);
++ return;
++
++ case 0x0a: /* LF: Line Feed (^J) */
++ case 0x0b: /* VT: Vertical Tab (^K) */
++ lf(p);
++ if (! test_bit(CRLF, &p->struct_flags))
++ return;
++
++ case 0x0d: /* CR: Carriage Return (^M) */
++ cr(p);
++ return;
++
++ case 0x16: /* SYN: Synchronous Idle (^V) */
++ SET_INPUT_STATE(p, SYN);
++ return;
++
++ case 0x1b: /* ESC: Start of escape sequence */
++ SET_INPUT_STATE(p, ESC);
++ return;
++
++ case 0x9b: /* CSI: Start of CSI escape sequence */
++ memset(p->csi_args, 0, sizeof(p->csi_args));
++ p->index = 0;
++ SET_INPUT_STATE(p, CSI);
++ return;
++ }
++}
++
++static void gotoxy(struct lcd_struct *p, int new_col, int new_row)
++{
++ unsigned int vs_rows = p->par->vs_rows;
++ unsigned int vs_cols = p->par->vs_cols;
++ int min_row, max_row;
++
++ clear_bit(NEED_WRAP, &p->struct_flags);
++ if (test_bit(DECOM, &p->struct_flags)) {
++ min_row = p->top;
++ max_row = p->bot;
++ } else {
++ min_row = 0;
++ max_row = vs_rows;
++ }
++
++ if (new_row < min_row)
++ p->row = min_row;
++ else if (new_row >= max_row)
++ p->row = max_row-1;
++ else
++ p->row = new_row;
++
++ if (new_col < 0)
++ p->col = 0;
++ else if (new_col >= vs_cols)
++ p->col = vs_cols-1;
++ else
++ p->col = new_col;
++
++ if (show_cursor(p))
++ redraw_screen(p, 0, p->fb_size-1);
++}
++
++static void gotoxay(struct lcd_struct *p, int new_col, int new_row)
++{
++ gotoxy(p, new_col, test_bit(DECOM, &p->struct_flags) ? (p->top+new_row) : new_row);
++}
++
++
++/******************************
++ * ECMA-48 CSI ESC- sequences *
++ ******************************/
++static void csi_at(struct lcd_struct *p, unsigned int nr)
++{
++ unsigned int vs_cols = p->par->vs_cols;
++
++ if (p->col+nr > vs_cols)
++ nr = vs_cols-p->col;
++ else if (! nr)
++ ++nr;
++ lcd_insert_char(p, nr);
++}
++
++static void csi_J(struct lcd_struct *p, unsigned int action)
++{
++ unsigned int vs_cols = p->par->vs_cols;
++ unsigned int pos = (p->row*vs_cols)+p->col;
++
++ clear_bit(NEED_WRAP, &p->struct_flags);
++ switch (action) {
++ case 0: /* From cursor to end of display */
++ lcd_memset(p, pos, p->erase_char, p->fb_size-pos);
++ return;
++
++ case 1: /* From start of display to cursor */
++ lcd_memset(p, 0, p->erase_char, pos+1);
++ return;
++
++ case 2: /* Whole display */
++ lcd_memset(p, 0, p->erase_char, p->fb_size);
++ return;
++ }
++}
++
++static void csi_K(struct lcd_struct *p, unsigned int action)
++{
++ unsigned int vs_cols = p->par->vs_cols;
++ unsigned int row_start = p->row*vs_cols;
++
++ clear_bit(NEED_WRAP, &p->struct_flags);
++ switch (action) {
++ case 0: /* From cursor to end of line */
++ lcd_memset(p, row_start+p->col, p->erase_char, vs_cols-p->col);
++ return;
++
++ case 1: /* From start of line to cursor */
++ lcd_memset(p, row_start, p->erase_char, p->col+1);
++ return;
++
++ case 2: /* Whole line */
++ lcd_memset(p, row_start, p->erase_char, vs_cols);
++ return;
++ }
++}
++
++static void csi_L(struct lcd_struct *p, unsigned int nr)
++{
++ unsigned int vs_rows = p->par->vs_rows;
++ unsigned int vs_cols = p->par->vs_cols;
++
++ clear_bit(NEED_WRAP, &p->struct_flags);
++ if (p->row+nr > vs_rows)
++ nr = vs_rows-p->row;
++ else if (! nr)
++ ++nr;;
++ lcd_memmove(p, (p->row+nr)*vs_cols, p->row*vs_cols, (vs_rows-p->row-nr)*vs_cols);
++ lcd_memset(p, p->row*vs_cols, p->erase_char, nr*vs_cols);
++}
++
++static void csi_M(struct lcd_struct *p, unsigned int nr)
++{
++ unsigned int vs_rows = p->par->vs_rows;
++ unsigned int vs_cols = p->par->vs_cols;
++
++ clear_bit(NEED_WRAP, &p->struct_flags);
++ if (p->row+nr > vs_rows)
++ nr = vs_rows-p->row;
++ else if (! nr)
++ ++nr;;
++ lcd_memmove(p, p->row*vs_cols, (p->row+nr)*vs_cols, (vs_rows-p->row-nr)*vs_cols);
++ lcd_memset(p, (vs_rows-nr)*vs_cols, p->erase_char, nr*vs_cols);
++}
++
++static void csi_P(struct lcd_struct *p, unsigned int nr)
++{
++ unsigned int vs_cols = p->par->vs_cols;
++
++ if (p->col+nr > vs_cols)
++ nr = vs_cols-p->col;
++ else if (! nr)
++ ++nr;
++ lcd_delete_char(p, nr);
++}
++
++static void csi_X(struct lcd_struct *p, unsigned int nr)
++{
++ unsigned int vs_cols = p->par->vs_cols;
++
++ clear_bit(NEED_WRAP, &p->struct_flags);
++ if (p->col+nr > vs_cols)
++ nr = vs_cols-p->col;
++ else if (! nr)
++ ++nr;
++ lcd_memset(p, (p->row*vs_cols)+p->col, p->erase_char, nr);
++}
++
++static void csi_su(struct lcd_struct *p, unsigned char input)
++{
++ unsigned int vs_cols = p->par->vs_cols;
++
++ clear_bit(NEED_WRAP, &p->struct_flags);
++ if (input == 'u') {
++ p->row = p->s_offset/vs_cols;
++ p->col = p->s_offset%vs_cols;
++ p->color = p->s_color;
++ p->attributes = p->s_attributes;
++ return;
++ }
++ p->s_offset = (p->row*vs_cols)+p->col;
++ p->s_color = p->color;
++ p->s_attributes = p->attributes;
++}
++
++static inline unsigned char reverse_color_attr(unsigned char attr)
++{
++ return ((attr & (BG_BRIGHT | FG_BRIGHT)) | ((attr & BG_COLOR) >> 4) | ((attr & FG_COLOR) << 4));
++}
++
++static unsigned char build_attr(struct lcd_struct *p, unsigned char color, unsigned char intensity,
++ unsigned char blink, unsigned char underline, unsigned char reverse)
++{
++ unsigned char attr;
++
++ if (test_bit(CAN_DO_COLOR, &p->struct_flags)) {
++ attr = color;
++ if (underline)
++ attr = (attr & BG_MASK) | p->ulcolor;
++ else if (intensity == 0)
++ attr = (attr & BG_MASK) | p->halfcolor;
++ if (reverse)
++ attr = reverse_color_attr(attr);
++ if (blink)
++ attr ^= BG_BRIGHT;
++ if (intensity == 2)
++ attr ^= FG_BRIGHT;
++ } else {
++ attr = intensity;
++ attr |= (underline ? ULINE : 0x00);
++ attr |= (reverse ? REVERSE : 0x00);
++ attr |= (blink ? BLINK : 0x00);
++ }
++
++ return (attr);
++}
++
++static void update_attr(struct lcd_struct *p)
++{
++ unsigned char intensity = p->attributes & I_MASK;
++ unsigned char underline = (p->attributes & ULINE) ? 0x01 : 0x00;
++ unsigned char reverse = (p->attributes & REVERSE) ? 0x01 : 0x00;
++ unsigned char blink = (p->attributes & BLINK) ? 0x01 : 0x00;
++ unsigned char decscnm = test_bit(DECSCNM, &p->struct_flags) ? 0x01 : 0x00;
++
++ p->attr = build_attr(p, p->color, intensity, blink, underline, reverse ^ decscnm);
++ p->erase_char = (build_attr(p, p->color, 1, blink, 0, decscnm) << 8) | ' ';
++}
++
++static void default_attr(struct lcd_struct *p)
++{
++ p->attributes = 0x01;
++ p->color = p->defcolor;
++}
++
++static void lcd_invert_screen(struct lcd_struct *p, unsigned int s, unsigned int len)
++{
++ unsigned int l, inc_set = test_bit(INC_CURS_POS, &p->struct_flags);
++
++ if (! len || s >= p->fb_size)
++ return;
++ if (inc_set && s+len > p->fb_size)
++ len = p->fb_size-s;
++ else if (! inc_set && len > s+1)
++ len = s+1;
++
++ l = len;
++ if (test_bit(CAN_DO_COLOR, &p->struct_flags))
++ while (l--) {
++ p->fb[s] = (reverse_color_attr(p->fb[s] >> 8) << 8) | (p->fb[s] & 0xff);
++ ++s;
++ }
++ else
++ while (l--) {
++ p->fb[s] ^= REVERSE << 8;
++ ++s;
++ }
++
++ if (show_cursor(p))
++ redraw_screen(p, 0, p->fb_size-1);
++ else
++ redraw_screen(p, s, s+(len-1));
++}
++
++static void csi_m(struct lcd_struct *p, unsigned int n)
++{
++ int i, arg;
++
++ for (i = 0; i <= n; ++i)
++ switch ((arg = p->csi_args[i]))
++ {
++ case 0:
++ default_attr(p);
++ break;
++
++ case 1:
++ p->attributes = (p->attributes & ~I_MASK) | 2;
++ break;
++
++ case 2:
++ p->attributes = (p->attributes & ~I_MASK) | 0;
++ break;
++
++ case 4:
++ p->attributes |= ULINE;
++ break;
++
++ case 5:
++ p->attributes |= BLINK;
++ break;
++
++ case 7:
++ p->attributes |= REVERSE;
++ break;
++
++ case 21: case 22:
++ p->attributes = (p->attributes & ~I_MASK) | 1;
++ break;
++
++ case 24:
++ p->attributes &= ~ULINE;
++ break;
++
++ case 25:
++ p->attributes &= ~BLINK;
++ break;
++
++ case 27:
++ p->attributes &= ~REVERSE;
++ break;
++
++ case 38:
++ p->attributes |= ULINE;
++ p->color = (p->color & BG_MASK) | (p->defcolor & FG_MASK);
++ break;
++
++ case 39:
++ p->attributes &= ~ULINE;
++ p->color = (p->color & BG_MASK) | (p->defcolor & FG_MASK);
++ break;
++
++ case 49:
++ p->color = (p->defcolor & BG_MASK) | (p->color & FG_MASK);
++ break;
++
++ default:
++ if (arg >= 30 && arg <= 37)
++ p->color = (p->color & BG_MASK) | color_table[arg-30];
++ else if (arg >= 40 && arg <= 47)
++ p->color = (p->color & FG_MASK) | (color_table[arg-40] << 4);
++ break;
++ }
++
++ update_attr(p);
++}
++
++static void csi_h(struct lcd_struct *p, unsigned char n)
++{
++ switch (n) {
++ case 4: /* Set insert mode */
++ set_bit(DECIM, &p->struct_flags);
++ return;
++
++ case 5: /* Inverted screen mode */
++ if (test_bit(QUES, &p->struct_flags) && ! test_bit(DECSCNM, &p->struct_flags)) {
++ lcd_invert_screen(p, 0, p->fb_size);
++ set_bit(DECSCNM, &p->struct_flags);
++ update_attr(p);
++ }
++ return;
++
++ case 6: /* Cursor addressing origin: relative to scrolling region */
++ if (test_bit(QUES, &p->struct_flags)) {
++ set_bit(DECOM, &p->struct_flags);
++ gotoxay(p, 0, 0);
++ }
++ return;
++
++ case 7: /* Set autowrap */
++ if (test_bit(QUES, &p->struct_flags))
++ set_bit(DECAWM, &p->struct_flags);
++ return;
++
++ case 20: /* Set cr lf */
++ set_bit(CRLF, &p->struct_flags);
++ return;
++ }
++}
++
++static void csi_l(struct lcd_struct *p, unsigned char n)
++{
++ switch (n) {
++ case 4: /* Reset insert mode */
++ clear_bit(DECIM, &p->struct_flags);
++ return;
++
++ case 5: /* Normal screen mode */
++ if (test_bit(QUES, &p->struct_flags) && test_bit(DECSCNM, &p->struct_flags)) {
++ lcd_invert_screen(p, 0, p->fb_size);
++ clear_bit(DECSCNM, &p->struct_flags);
++ update_attr(p);
++ }
++ return;
++
++ case 6: /* Cursor addressing origin: absolute origin */
++ if (test_bit(QUES, &p->struct_flags)) {
++ clear_bit(DECOM, &p->struct_flags);
++ gotoxay(p, 0, 0);
++ }
++ return;
++
++ case 7: /* Reset autowrap */
++ if (test_bit(QUES, &p->struct_flags))
++ clear_bit(DECAWM, &p->struct_flags);
++ return;
++
++ case 20: /* Reset cr lf */
++ clear_bit(CRLF, &p->struct_flags);
++ return;
++ }
++}
++
++static void csi_linux(struct lcd_struct *p)
++{
++ switch (p->csi_args[0]) {
++ case 1:
++ if (test_bit(CAN_DO_COLOR, &p->struct_flags) && p->csi_args[1] < 16) {
++ p->ulcolor = color_table[p->csi_args[1]];
++ if (p->attributes & ULINE)
++ update_attr(p);
++ }
++ return;
++
++ case 2:
++ if (test_bit(CAN_DO_COLOR, &p->struct_flags) && p->csi_args[1] < 16) {
++ p->halfcolor = color_table[p->csi_args[1]];
++ if ((p->attributes & I_MASK) == 0)
++ update_attr(p);
++ }
++ return;
++
++ case 8:
++ p->defcolor = p->color;
++ default_attr(p);
++ update_attr(p);
++ return;
++ }
++}
++
++static void csi_r(struct lcd_struct *p, unsigned int top, unsigned int bot)
++{
++ /* Minimum allowed region is 2 lines */
++ if (top < bot) {
++ p->top = top-1;
++ p->bot = bot;
++ gotoxay(p, 0, 0);
++ }
++}
++
++/*
++ * ECMA-48 CSI ESC- sequence handler.
++ */
++static void handle_csi(struct lcd_struct *p, unsigned char input)
++{
++ if (p->index >= NPAR) {
++ SET_INPUT_STATE(p, NORMAL);
++ printk(KERN_NOTICE "LCD: too many parameters in CSI escape sequence\n");
++ } else if (input == '?') {
++ set_bit(QUES, &p->struct_flags);
++ } else if (input == ';') {
++ ++p->index;
++ } else if (input >= '0' && input <= '9') {
++ p->csi_args[p->index] = (p->csi_args[p->index]*10)+(input-'0');
++ } else {
++ SET_INPUT_STATE(p, NORMAL);
++ if (! test_bit(INC_CURS_POS, &p->struct_flags))
++ return;
++ switch (input) {
++ case 'h': /* DECSET sequences and mode switches */
++ csi_h(p, p->csi_args[0]);
++ clear_bit(QUES, &p->struct_flags);
++ return;
++
++ case 'l': /* DECRST sequences and mode switches */
++ csi_l(p, p->csi_args[0]);
++ clear_bit(QUES, &p->struct_flags);
++ return;
++ }
++ clear_bit(QUES, &p->struct_flags);
++ switch (input) {
++ case '@': /* Insert # Blank character */
++ csi_at(p, p->csi_args[0]);
++ return;
++
++ case 'G': case '`': /* Cursor to indicated column in current row */
++ if (p->csi_args[0])
++ --p->csi_args[0];
++ gotoxy(p, p->csi_args[0], p->row);
++ return;
++
++ case 'A': /* Cursor # rows Up */
++ if (! p->csi_args[0])
++ ++p->csi_args[0];
++ gotoxy(p, p->col, p->row-p->csi_args[0]);
++ return;
++
++ case 'B': case 'e': /* Cursor # rows Down */
++ if (! p->csi_args[0])
++ ++p->csi_args[0];
++ gotoxy(p, p->col, p->row+p->csi_args[0]);
++ return;
++
++ case 'C': case 'a': /* Cursor # columns Right */
++ if (! p->csi_args[0])
++ ++p->csi_args[0];
++ gotoxy(p, p->col+p->csi_args[0], p->row);
++ return;
++
++ case 'D': /* Cursor # columns Left */
++ if (! p->csi_args[0])
++ ++p->csi_args[0];
++ gotoxy(p, p->col-p->csi_args[0], p->row);
++ return;
++
++ case 'E': /* Cursor # rows Down, column 1 */
++ if (! p->csi_args[0])
++ ++p->csi_args[0];
++ gotoxy(p, 0, p->row+p->csi_args[0]);
++ return;
++
++ case 'F': /* Cursor # rows Up, column 1 */
++ if (! p->csi_args[0])
++ ++p->csi_args[0];
++ gotoxy(p, 0, p->row-p->csi_args[0]);
++ return;
++
++ case 'd': /* Cursor to indicated row in current column */
++ if (p->csi_args[0])
++ --p->csi_args[0];
++ gotoxay(p, p->col, p->csi_args[0]);
++ return;
++
++ case 'H': case 'f': /* Cursor to indicated row, column (origin 1, 1) */
++ if (p->csi_args[0])
++ --p->csi_args[0];
++ if (p->csi_args[1])
++ --p->csi_args[1];
++ gotoxay(p, p->csi_args[1], p->csi_args[0]);
++ return;
++
++ case 'J': /* Erase display */
++ csi_J(p, p->csi_args[0]);
++ return;
++
++ case 'K': /* Erase line */
++ csi_K(p, p->csi_args[0]);
++ return;
++
++ case 'L': /* Insert # blank lines */
++ csi_L(p, p->csi_args[0]);
++ return;
++
++ case 'M': /* Delete # blank lines */
++ csi_M(p, p->csi_args[0]);
++ return;
++
++ case 'P': /* Delete # characters on the current line */
++ csi_P(p, p->csi_args[0]);
++ return;
++
++ case 'X': /* Erase # characters on the current line */
++ csi_X(p, p->csi_args[0]);
++ return;
++
++ case 'm': /* Set video attributes */
++ csi_m(p, p->index);
++ return;
++
++ case 's': /* Save cursor position */
++ case 'u': /* Restore cursor position */
++ csi_su(p, input);
++ return;
++
++ case ']': /* Linux private ESC [ ] sequence */
++ csi_linux(p);
++ return;
++
++ case 'r': /* Set the scrolling region */
++ if (! p->csi_args[0])
++ ++p->csi_args[0];
++ if (! p->csi_args[1] || p->csi_args[1] > p->par->vs_rows)
++ p->csi_args[1] = p->par->vs_rows;
++ csi_r(p, p->csi_args[0], p->csi_args[1]);
++ return;
++
++ /* Ignored escape sequences */
++ case 'c':
++ case 'g':
++ case 'n':
++ case 'q':
++ return;
++
++ default:
++ printk(KERN_NOTICE "LCD: unrecognized CSI escape sequence: ESC [ %u\n", input);
++ return;
++ }
++ }
++}
++
++/*
++ * Custom ESC- sequence handler.
++ */
++static int handle_custom_esc(struct lcd_struct *p, unsigned int _input)
++{
++ unsigned char input = _input & 0xff;
++ struct lcd_parameters *par = p->par;
++
++ if (_input & (~0xff)) {
++ switch (ESC_STATE(p)) {
++ case 's':
++ if (p->index++) {
++ unsigned char *cgbuf = p->cgram_buffer-par->cgram_bytes;
++
++ cgbuf[p->index-2] = input;
++ if (p->index == par->cgram_bytes+1)
++ write_cgram(p, p->cgram_index, cgbuf);
++ } else {
++ if (! p->driver->write_cgram_char) {
++ printk(KERN_ERR "LCD: %s: missing function to write to CGRAM\n", p->par->name);
++ return (-1);
++ }
++ if (input >= par->cgram_char0 && input < par->cgram_char0+par->cgram_chars)
++ p->cgram_index = input;
++ else {
++ printk(KERN_NOTICE "LCD: bad CGRAM index\n");
++ return (-1);
++ }
++ }
++ return (0);
++
++ case 'G':
++ if (input >= par->cgram_char0 && input < par->cgram_char0+par->cgram_chars)
++ write_data(p, (p->attr << 8) | p->driver->charmap[input]);
++ else {
++ SET_INPUT_STATE(p, NORMAL);
++ handle_input(p, (p->attr << 8) | input);
++ }
++ return (0);
++
++ case 'r':
++ if (input == '1')
++ address_mode(p, -1);
++ else if (input == '0')
++ address_mode(p, 1);
++ return (0);
++
++ case 'A':
++ scrup(p, p->top, p->bot, input);
++ return (0);
++
++ case 'B':
++ scrdown(p, p->top, p->bot, input);
++ return (0);
++
++ case 'C':
++ browse_screen(p, input);
++ return (0);
++ }
++ }
++
++ /* These are the custom ESC- sequences */
++ switch (input) {
++ case 's': /* CGRAM select */
++ if (p->cgram_buffer) {
++ SET_ESC_STATE(p, input);
++ p->index = 0;
++ return (par->cgram_bytes+1);
++ } else {
++ printk(KERN_NOTICE "LCD: driver %s does not support CGRAM chars\n", par->name);
++ return (0);
++ }
++
++ case 'A': /* Scroll up */
++ case 'B': /* Scroll down */
++ case 'C': /* Browse screen */
++ case 'G': /* Enter cgram mode */
++ case 'r': /* Decrement counter after data read/write */
++ SET_ESC_STATE(p, input);
++ return (1);
++ }
++
++ return (-1);
++}
++
++/*
++ * ESC- but not CSI sequence handler.
++ */
++static int handle_esc(struct lcd_struct *p, unsigned char input)
++{
++ int ret;
++
++ SET_INPUT_STATE(p, NORMAL);
++ switch (input) {
++ case 'c': /* Reset */
++ set_bit(DECAWM, &p->struct_flags);
++ set_bit(INC_CURS_POS, &p->struct_flags);
++ ff(p);
++ return (0);
++
++ case 'D': /* Line Feed */
++ lf(p);
++ return (0);
++
++ case 'E': /* New Line */
++ cr(p);
++ lf(p);
++ return (0);
++
++ case 'M': /* Reverse Line Feed */
++ ri(p);
++ return (0);
++
++ case '7':
++ case '8':
++ csi_su(p, (input == '7' ? 's' : 'u'));
++ return (0);
++
++ /* CSI: Start of CSI escape sequence */
++ case '[':
++ memset(p->csi_args, 0, sizeof(p->csi_args));
++ p->index = 0;
++ SET_INPUT_STATE(p, CSI);
++ return (0);
++
++ /* Ignored escape sequences */
++ case '(':
++ SET_INPUT_STATE(p, ESC_G0);
++ return (1);
++
++ case ')':
++ SET_INPUT_STATE(p, ESC_G1);
++ return (1);
++
++ case '#':
++ SET_INPUT_STATE(p, ESC_HASH);
++ return (1);
++
++ case '%':
++ SET_INPUT_STATE(p, ESC_PERCENT);
++ return (1);
++
++ case 'H':
++ case 'Z':
++ case '>':
++ case '=':
++ case ']':
++ return (0);
++ }
++
++ /* These are the custom ESC- sequences */
++ if ((ret = handle_custom_esc(p, input)) > 0) {
++ SET_INPUT_STATE(p, ARG);
++ return (ret);
++ }
++
++ if (ret < 0 && p->driver->handle_custom_char)
++ if ((ret = p->driver->handle_custom_char(input)) > 0) {
++ SET_INPUT_STATE(p, ARG_DRIVER);
++ return (ret);
++ }
++
++ if (ret < 0)
++ printk(KERN_NOTICE "LCD: unrecognized escape sequence: ESC %u\n", input);
++
++ return (0);
++}
++
++/*
++ * Main input handler.
++ */
++static void handle_input(struct lcd_struct *p, unsigned short _input)
++{
++ unsigned char input = _input & 0xff;
++ struct lcd_driver *driver = p->driver;
++
++ switch (INPUT_STATE(p)) {
++ case NORMAL:
++ if (input < 0x20 || input == 0x9b)
++ control_char(p, input);
++ else
++ write_data(p, (_input & 0xff00) | driver->charmap[input]);
++ return;
++
++ case RAW:
++ write_data(p, (_input & 0xff00) | driver->charmap[input]);
++ return;
++
++ case SYN:
++ write_data(p, _input);
++ SET_INPUT_STATE(p, NORMAL);
++ return;
++
++ case ESC:
++ p->esc_args = handle_esc(p, input);
++ return;
++
++ case ESC_G0:
++ case ESC_G1:
++ case ESC_HASH:
++ case ESC_PERCENT:
++ if (! --p->esc_args)
++ SET_INPUT_STATE(p, NORMAL);
++ return;
++
++ case CSI:
++ handle_csi(p, input);
++ return;
++
++ case ARG:
++ if (handle_custom_esc(p, 0x100 | input) || ! --p->esc_args)
++ SET_INPUT_STATE(p, NORMAL);
++ return;
++
++ case ARG_DRIVER:
++ if (driver->handle_custom_char(0x100 | input) || ! --p->esc_args)
++ SET_INPUT_STATE(p, NORMAL);
++ return;
++ }
++}
++
++
++
++
++
++/***************************************
++ * Read from/Write to display routines *
++ ***************************************/
++
++/*
++ * Write character data to the display.
++ */
++static void write_data(struct lcd_struct *p, unsigned short data)
++{
++ unsigned int vs_cols = p->par->vs_cols;
++ unsigned int pos;
++ int frame_pos;
++
++ if (test_bit(NEED_WRAP, &p->struct_flags)) {
++ cr(p);
++ lf(p);
++ }
++
++ if (test_bit(DECIM, &p->struct_flags))
++ lcd_insert_char(p, 1);
++
++ pos = (p->row*vs_cols)+p->col;
++ if ((frame_pos = vs_to_frame_(p, pos)) < 0) {
++ show_cursor(p);
++ redraw_screen(p, 0, p->fb_size-1);
++ frame_pos = vs_to_frame_(p, pos);
++ }
++
++ if (p->display[frame_pos] != data) {
++ p->driver->write_char(frame_pos, data);
++ p->display[frame_pos] = data;
++ }
++
++ p->fb[pos] = data;
++
++ if (test_bit(INC_CURS_POS, &p->struct_flags)) {
++ if (p->col+1 < vs_cols)
++ iterator_inc(p->col, vs_cols);
++ else if (test_bit(DECAWM, &p->struct_flags))
++ set_bit(NEED_WRAP, &p->struct_flags);
++ } else {
++ if (p->col)
++ iterator_dec(p->col, vs_cols);
++ else if (test_bit(DECAWM, &p->struct_flags))
++ set_bit(NEED_WRAP, &p->struct_flags);
++ }
++}
++
++/*
++ * Write an entire CGRAM character to the display.
++ */
++static void write_cgram(struct lcd_struct *p, unsigned char index, unsigned char *pixels)
++{
++ struct lcd_parameters *par = p->par;
++ unsigned int inc_set = test_bit(INC_CURS_POS, &p->struct_flags);
++ unsigned char *cgbuf = p->cgram_buffer+(index-par->cgram_char0)*par->cgram_bytes;
++
++ if (! strncmp(cgbuf, pixels, par->cgram_bytes))
++ return;
++
++ if (! inc_set)
++ address_mode(p, 1);
++
++ p->driver->write_cgram_char(index, pixels);
++ memcpy(cgbuf, pixels, par->cgram_bytes);
++
++ if (! inc_set)
++ address_mode(p, -1);
++}
++
++/*
++ * Read character data from the display.
++ */
++static void read_data(struct lcd_struct *p, unsigned short *data)
++{
++ unsigned int vs_rows = p->par->vs_rows;
++ unsigned int vs_cols = p->par->vs_cols;
++ unsigned int pos = (p->row*vs_cols)+p->col;
++ int frame_pos;
++
++ if ((frame_pos = vs_to_frame_(p, pos)) < 0) {
++ show_cursor(p);
++ redraw_screen(p, 0, p->fb_size-1);
++ frame_pos = vs_to_frame_(p, pos);
++ }
++
++ if (p->driver->read_char)
++ p->driver->read_char(frame_pos, data);
++ else
++ *data = p->fb[pos];
++
++ if (test_bit(INC_CURS_POS, &p->struct_flags)) {
++ iterator_inc(p->col, vs_cols);
++ if (! p->col) {
++ if (p->row+1 < vs_rows)
++ ++p->row;
++ }
++ } else {
++ iterator_dec(p->col, vs_cols);
++ if (p->col+1 == vs_cols) {
++ if (p->row)
++ --p->row;
++ }
++ }
++}
++
++/*
++ * Read an entire CGRAM character from the display.
++ */
++static void read_cgram(struct lcd_struct *p, unsigned char index, unsigned char *pixels)
++{
++ struct lcd_parameters *par = p->par;
++ unsigned int inc_set = test_bit(INC_CURS_POS, &p->struct_flags);
++ unsigned char *cgbuf = p->cgram_buffer+(index-par->cgram_char0)*par->cgram_bytes;
++
++ if (! p->driver->read_cgram_char) {
++ memcpy(pixels, cgbuf, par->cgram_bytes);
++ return;
++ }
++
++ if (! inc_set)
++ address_mode(p, 1);
++
++ p->driver->read_cgram_char(index, pixels);
++
++ if (! inc_set)
++ address_mode(p, -1);
++}
++
++
++
++
++
++/****************************
++ * Proc filesystem routines *
++ ****************************/
++#ifdef USE_PROC
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 4, 0)
++/* create_proc_read_entry is missing in 2.2.x kernels */
++static struct proc_dir_entry *create_proc_read_entry(const char *name, mode_t mode,
++ struct proc_dir_entry *parent, read_proc_t *read_proc, void *data)
++{
++ struct proc_dir_entry *res = create_proc_entry(name, mode, parent);
++
++ if (res) {
++ res->read_proc = read_proc;
++ res->data = data;
++ }
++
++ return (res);
++}
++#endif
++
++static int proc_fb_read(char *buffer, char **start, off_t offset, int size, int *eof, void *data)
++{
++ char *temp = buffer;
++ struct lcd_struct *p = (struct lcd_struct *)data;
++ unsigned int vs_cols;
++ static unsigned int nr, need_wrap;
++ static off_t _offset;
++
++ down(&p->lcd_sem);
++ if (! offset)
++ _offset = 0;
++ if ((*eof = (_offset >= p->fb_size))) {
++ up(&p->lcd_sem);
++ return (0);
++ }
++ vs_cols = p->par->vs_cols;
++ if (size && need_wrap) {
++ need_wrap = 0;
++ temp += sprintf(temp, "\n");
++ --size;
++ }
++ if (! nr)
++ nr = vs_cols;
++ *start = (char *)0;
++ while (size && nr) {
++ unsigned char c = (p->fb[_offset] & 0xff);
++
++ temp += sprintf(temp, "%c", (c < 0x20 ? '?' : c));
++ --size;
++ --nr;
++ ++*start;
++ ++_offset;
++ }
++ if (! nr) {
++ if (size) {
++ temp += sprintf(temp, "\n");
++ --size;
++ } else
++ need_wrap = 1;
++ }
++ up(&p->lcd_sem);
++
++ return (temp-buffer);
++}
++
++static int proc_display_read(char *buffer, char **start, off_t offset, int size, int *eof, void *data)
++{
++ char *temp = buffer;
++ struct lcd_struct *p = (struct lcd_struct *)data;
++ unsigned int i, frame_cols;
++ int frame_pos;
++
++ down(&p->lcd_sem);
++ frame_cols = p->par->cntr_cols;
++ frame_pos = vs_to_frame_(p, (p->row*p->par->vs_cols)+p->col);
++ temp += sprintf(temp, " ");
++ for (i = 2; i <= frame_cols; i += 2)
++ temp += sprintf(temp, " %d", i%10);
++ temp += sprintf(temp, "\n");
++
++ temp += sprintf(temp, " +");
++ for (i = 0; i < frame_cols; ++i)
++ temp += sprintf(temp, "-");
++ temp += sprintf(temp, "+\n");
++
++ for (i = 0; i < p->frame_size; ++i) {
++ unsigned char c = (p->display[i] & 0xff);
++
++ if (! (i%frame_cols))
++ temp += sprintf(temp, "%2d |", 1+i/frame_cols);
++ if (frame_pos--)
++ temp += sprintf(temp, "%c", (c < 0x20 ? '?' : c));
++ else
++ temp += sprintf(temp, "_");
++ if (! ((i+1)%frame_cols))
++ temp += sprintf(temp, "|\n");
++ }
++
++ temp += sprintf(temp, " +");
++ for (i = 0; i < frame_cols; ++i)
++ temp += sprintf(temp, "-");
++ temp += sprintf(temp, "+\n");
++ up(&p->lcd_sem);
++
++ return (temp-buffer);
++}
++
++static int proc_charmap_read(char *buffer, char **start, off_t offset, int size, int *eof, void *data)
++{
++ char *temp = buffer;
++ struct lcd_struct *p = (struct lcd_struct *)data;
++ unsigned char *charmap;
++ unsigned int i;
++
++ down(&p->lcd_sem);
++ charmap = p->driver->charmap;
++ temp += sprintf(temp, "static unsigned char charmap[] = {");
++ for (i = 0; i < 255; ++i) {
++ if (! (i & 7)) {
++ temp += sprintf(temp, "\n");
++ if (! (i & 31))
++ temp += sprintf(temp, "\n/* %d - %d */\n", i, i+31);
++ }
++ temp += sprintf(temp, "0x%.2x, ", *charmap++);
++ }
++ temp += sprintf(temp, "0x%.2x\n\n};\n", *charmap);
++ up(&p->lcd_sem);
++
++ return (temp-buffer);
++}
++
++static int proc_registered_drivers(char *buffer, char **start, off_t offset, int size, int *eof, void *data)
++{
++ char *temp = buffer;
++ struct list_head *entry;
++
++ down(&drivers_sem);
++ temp += sprintf(temp, "Registered drivers:\n");
++ list_for_each(entry, &lcd_drivers) {
++ struct lcd_struct *p = list_entry(entry, struct lcd_struct, lcd_list);
++
++ down(&p->lcd_sem);
++ temp += sprintf(temp, "%3d %s\n", p->par->minor, p->par->name);
++ up(&p->lcd_sem);
++ }
++ up(&drivers_sem);
++
++ return (temp-buffer);
++}
++
++static void create_driver_proc_entries(struct lcd_struct *p)
++{
++ struct proc_dir_entry *driver_proc_root = p->driver->driver_proc_root;
++
++ SET_PROC_LEVEL(p, 0);
++ if (create_proc_read_entry("framebuffer", 0, driver_proc_root, proc_fb_read, p) == NULL) {
++ printk(KERN_ERR "LCD: cannot create /proc/lcd/%s/framebuffer\n", p->par->name);
++ return;
++ }
++ SET_PROC_LEVEL(p, 1);
++ if (create_proc_read_entry("display", 0, driver_proc_root, proc_display_read, p) == NULL) {
++ printk(KERN_ERR "LCD: cannot create /proc/lcd/%s/display\n", p->par->name);
++ return;
++ }
++ SET_PROC_LEVEL(p, 2);
++ if (create_proc_read_entry("charmap.h", 0, driver_proc_root, proc_charmap_read, p) == NULL) {
++ printk(KERN_ERR "LCD: cannot create /proc/lcd/%s/charmap.h\n", p->par->name);
++ return;
++ }
++ SET_PROC_LEVEL(p, 3);
++}
++
++static void remove_driver_proc_entries(struct lcd_struct *p)
++{
++ struct proc_dir_entry *driver_proc_root = p->driver->driver_proc_root;
++
++ switch (PROC_LEVEL(p)) {
++ case 3:
++ remove_proc_entry("charmap.h", driver_proc_root);
++ case 2:
++ remove_proc_entry("display", driver_proc_root);
++ case 1:
++ remove_proc_entry("framebuffer", driver_proc_root);
++ }
++ SET_PROC_LEVEL(p, 0);
++}
++#endif
++
++
++
++
++
++/*****************************
++ * Low level file operations *
++ *****************************/
++static ssize_t do_lcd_read(struct lcd_struct *p, void *buffer, size_t length)
++{
++ unsigned int i;
++ unsigned short tmp;
++
++ if (! p->refcount)
++ return (-ENXIO);
++
++ if (test_bit(WITH_ATTR, &p->struct_flags))
++ for (i = 0; i < length; ++i) {
++ read_data(p, &tmp);
++ ((unsigned short *)buffer)[i] = tmp;
++ }
++ else
++ for (i = 0; i < length; ++i) {
++ read_data(p, &tmp);
++ ((unsigned char *)buffer)[i] = tmp & 0xff;
++ }
++
++ return (length);
++}
++
++static ssize_t do_lcd_write(struct lcd_struct *p, const void *buffer, size_t length)
++{
++ unsigned int i;
++
++ if (! p->refcount)
++ return (-ENXIO);
++
++ if (test_bit(WITH_ATTR, &p->struct_flags))
++ for (i = 0; i < length; ++i)
++ handle_input(p, ((const unsigned short *)buffer)[i]);
++ else
++ for (i = 0; i < length; ++i)
++ handle_input(p, (p->attr << 8) | ((const unsigned char *)buffer)[i]);
++
++ return (length);
++}
++
++static int do_lcd_open(struct lcd_struct *p)
++{
++ if (! p->refcount) {
++ if (p->driver->driver_module) {
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0)
++ if (! try_module_get(p->driver->driver_module))
++ return (-EBUSY);
++#else
++ if (__MOD_IN_USE(p->driver->driver_module))
++ return (-EBUSY);
++
++ __MOD_INC_USE_COUNT(p->driver->driver_module);
++#endif
++ }
++ }
++
++ ++p->refcount;
++
++ return (0);
++}
++
++static int do_lcd_release(struct lcd_struct *p)
++{
++ if (! p->refcount)
++ return (0);
++
++ if (p->refcount == 1) {
++ if (p->driver->driver_module)
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0)
++ module_put(p->driver->driver_module);
++#else
++ __MOD_DEC_USE_COUNT(p->driver->driver_module);
++#endif
++ }
++
++ --p->refcount;
++
++ return (0);
++}
++
++static int cgram_ioctl(struct lcd_struct *p, unsigned int cmd, unsigned char *argp)
++{
++ struct lcd_parameters *par = p->par;
++ unsigned int length = par->cgram_bytes;
++ unsigned char index = argp[0];
++ unsigned char *buffer = argp+1;
++ unsigned char *cgbuf = p->cgram_buffer-length;
++
++ if (index < par->cgram_char0 || index >= par->cgram_char0+par->cgram_chars)
++ return (-EINVAL);
++
++ if (! p->driver->write_cgram_char) {
++ printk(KERN_ERR "LCD: %s: missing function to write to CGRAM\n", p->par->name);
++ return (-ENOSYS);
++ }
++
++ if (cmd == LCDL_SET_CGRAM_CHAR) {
++ if (test_bit(USER_SPACE, &p->struct_flags)) {
++ if (copy_from_user(cgbuf, buffer, length))
++ return (-EFAULT);
++ } else
++ memcpy(cgbuf, buffer, length);
++ write_cgram(p, index, cgbuf);
++ } else {
++ read_cgram(p, index, cgbuf);
++ if (test_bit(USER_SPACE, &p->struct_flags)) {
++ if (copy_to_user(buffer, cgbuf, length))
++ return (-EFAULT);
++ } else
++ memcpy(buffer, cgbuf, length);
++ }
++
++ return (0);
++}
++
++static int do_lcd_ioctl(struct lcd_struct *p, unsigned int cmd, unsigned long arg)
++{
++ int i;
++ struct lcd_driver *driver = p->driver;
++ struct lcd_parameters *par = p->par;
++ unsigned char *argp = (unsigned char *)arg;
++
++ if (! p->refcount)
++ return (-ENXIO);
++
++ switch (cmd) {
++ case LCDL_SET_PARAM:
++ if (argp == NULL)
++ return (-EFAULT);
++ if ((i = cleanup_driver(p)))
++ return (i);
++ i = par->minor;
++ if (test_bit(USER_SPACE, &p->struct_flags)) {
++ if (copy_from_user(par, argp, sizeof(struct lcd_parameters)))
++ return (-EFAULT);
++ } else
++ memcpy(par, argp, sizeof(struct lcd_parameters));
++ par->minor = i;
++ return (init_driver(p));
++
++ case LCDL_GET_PARAM:
++ if (argp == NULL)
++ return (-EFAULT);
++ if (test_bit(USER_SPACE, &p->struct_flags)) {
++ if (copy_to_user(argp, par, sizeof(struct lcd_parameters)))
++ return (-EFAULT);
++ } else
++ memcpy(argp, par, sizeof(struct lcd_parameters));
++ return (0);
++
++ case LCDL_RESET_CHARMAP:
++ for (i = 0; i < 256; ++i)
++ driver->charmap[i] = i;
++ return (0);
++
++ case LCDL_CHARSUBST:
++ if (argp == NULL)
++ return (-EFAULT);
++ if (test_bit(USER_SPACE, &p->struct_flags)) {
++ get_user(i, argp);
++ get_user(driver->charmap[i], argp+1);
++ } else {
++ i = argp[0];
++ driver->charmap[i] = argp[1];
++ }
++ return (0);
++
++ case LCDL_SAVE_CHARMAP:
++ memcpy(p->s_charmap, driver->charmap, 256);
++ return (0);
++
++ case LCDL_RESTORE_CHARMAP:
++ memcpy(driver->charmap, p->s_charmap, 256);
++ return (0);
++
++ case LCDL_SWAP_CHARMAP:
++ {
++ unsigned char *tmp;
++
++ tmp = driver->charmap;
++ driver->charmap = p->s_charmap;
++ p->s_charmap = tmp;
++ }
++ return (0);
++
++ case LCDL_RAW_MODE:
++ if (arg) {
++ clear_bit(NEED_WRAP, &p->struct_flags);
++ clear_bit(DECIM, &p->struct_flags);
++ clear_bit(DECAWM, &p->struct_flags);
++ SET_INPUT_STATE(p, RAW);
++ } else {
++ set_bit(DECAWM, &p->struct_flags);
++ SET_INPUT_STATE(p, NORMAL);
++ }
++ return (0);
++
++ case LCDL_IOATTR:
++ if (arg)
++ set_bit(WITH_ATTR, &p->struct_flags);
++ else
++ clear_bit(WITH_ATTR, &p->struct_flags);
++ return (0);
++
++ case LCDL_CLEAR_DISP:
++ ff(p);
++ return (0);
++
++ case LCDL_SET_CGRAM_CHAR:
++ case LCDL_GET_CGRAM_CHAR:
++ if (argp == NULL)
++ return (-EFAULT);
++ if (p->cgram_buffer)
++ return (cgram_ioctl(p, cmd, argp));
++ else
++ printk(KERN_NOTICE "LCD: driver %s does not support CGRAM chars\n", par->name);
++ return (0);
++
++ case LCDL_SET_CHARMAP:
++ if (argp == NULL)
++ return (-EFAULT);
++ if (test_bit(USER_SPACE, &p->struct_flags)) {
++ if (copy_from_user(driver->charmap, argp, 256))
++ return (-EFAULT);
++ } else
++ memcpy(driver->charmap, argp, 256);
++ return (0);
++
++ case LCDL_GET_CHARMAP:
++ if (argp == NULL)
++ return (-EFAULT);
++ if (test_bit(USER_SPACE, &p->struct_flags)) {
++ if (copy_to_user(argp, driver->charmap, 256))
++ return (-EFAULT);
++ } else
++ memcpy(argp, driver->charmap, 256);
++ return (0);
++
++ case LCDL_MEMSET:
++ case LCDL_MEMMOVE:
++ {
++ int buf[3];
++
++ if (argp == NULL)
++ return (-EFAULT);
++ if (test_bit(USER_SPACE, &p->struct_flags)) {
++ if (copy_from_user(buf, argp, sizeof(buf)))
++ return (-EFAULT);
++ } else
++ memcpy(buf, argp, sizeof(buf));
++
++ if (cmd == LCDL_MEMSET)
++ lcd_memset(p, buf[0], buf[1], buf[2]);
++ else
++ lcd_memmove(p, buf[0], buf[1], buf[2]);
++
++ return (0);
++ }
++
++ default:
++ if (driver->handle_custom_ioctl)
++ return (driver->handle_custom_ioctl(cmd, arg, test_bit(USER_SPACE, &p->struct_flags)));
++ }
++
++ return (-ENOIOCTLCMD);
++}
++
++
++
++
++
++/**************************************************
++ * Kernel register/unregister lcd driver routines *
++ **************************************************/
++/*
++ * Find a driver in lcd_drivers linked list
++ */
++static struct lcd_struct *find_lcd_struct(unsigned short minor)
++{
++ struct list_head *entry;
++
++ list_for_each(entry, &lcd_drivers) {
++ struct lcd_struct *p = list_entry(entry, struct lcd_struct, lcd_list);
++
++ if (p->par->minor == minor)
++ return (p);
++ }
++
++ return (NULL);
++}
++
++static void list_add_sorted(struct list_head *new)
++{
++ struct list_head *entry;
++ unsigned short new_minor = (list_entry(new, struct lcd_struct, lcd_list))->par->minor;
++
++ list_for_each(entry, &lcd_drivers) {
++ struct lcd_struct *p = list_entry(entry, struct lcd_struct, lcd_list);
++
++ if (p->par->minor > new_minor)
++ break;
++ }
++ list_add_tail(new, entry);
++}
++
++/* Exported function */
++int lcd_register_driver(struct lcd_driver *driver, struct lcd_parameters *par)
++{
++ int ret;
++ struct lcd_struct *p;
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 19)
++ struct device *lcd_device;
++#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 13)
++ struct class_device *lcd_device;
++#endif
++
++ if (! driver || ! par || par->minor >= minors)
++ return (-EINVAL);
++ if (! driver->write_char || ! driver->init_port || ! driver->cleanup_port) {
++ printk(KERN_ERR "LCD: missing functions\n");
++ return (-EINVAL);
++ }
++
++ down(&drivers_sem);
++
++ if (find_lcd_struct(par->minor)) {
++ up(&drivers_sem);
++ return (-EBUSY);
++ }
++
++ if ((p = (struct lcd_struct *)kmalloc(sizeof(struct lcd_struct), GFP_KERNEL)) == NULL) {
++ printk(KERN_ERR "LCD: memory allocation failed (kmalloc)\n");
++ up(&drivers_sem);
++ return (-ENOMEM);
++ }
++ memset(p, 0, sizeof(struct lcd_struct));
++
++ p->driver = driver;
++ p->par = par;
++ p->refcount = 0;
++ SET_INIT_LEVEL(p, 0);
++ SET_INPUT_STATE(p, NORMAL);
++ set_bit(DECAWM, &p->struct_flags);
++ set_bit(INC_CURS_POS, &p->struct_flags);
++
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 13)
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)
++ lcd_device = device_create(lcd_linux_class, NULL, MKDEV(major, par->minor), NULL, "%s", par->name);
++#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 19)
++ lcd_device = device_create(lcd_linux_class, NULL, MKDEV(major, par->minor), "%s", par->name);
++#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 15)
++ lcd_device = class_device_create(lcd_linux_class, NULL, MKDEV(major, par->minor), NULL, "%s", par->name);
++#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 13)
++ lcd_device = class_device_create(lcd_linux_class, MKDEV(major, par->minor), NULL, "%s", par->name);
++#endif
++ if (IS_ERR(lcd_device)) {
++ kfree(p);
++ up(&drivers_sem);
++ return (PTR_ERR(lcd_device));
++ }
++#endif
++
++#ifdef USE_PROC
++ if (lcd_proc_root && (driver->driver_proc_root = proc_mkdir(par->name, lcd_proc_root)) == NULL)
++ printk(KERN_ERR "LCD: cannot create /proc/lcd/%s/\n", par->name);
++#endif
++
++ if ((ret = init_driver(p))) {
++#ifdef USE_PROC
++ if (driver->driver_proc_root)
++ remove_proc_entry(p->par->name, lcd_proc_root);
++#endif
++
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 19)
++ device_destroy(lcd_linux_class, MKDEV(major, par->minor));
++#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 13)
++ class_device_destroy(lcd_linux_class, MKDEV(major, par->minor));
++#endif
++
++ kfree(p);
++ up(&drivers_sem);
++ return (ret);
++ }
++
++ init_MUTEX(&p->lcd_sem);
++
++ list_add_sorted(&p->lcd_list);
++
++ up(&drivers_sem);
++
++#ifdef MODULE
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0)
++ try_module_get(THIS_MODULE);
++#else
++ MOD_INC_USE_COUNT;
++#endif
++#endif
++
++ return (0);
++}
++EXPORT_SYMBOL(lcd_register_driver);
++
++/* Exported function */
++int lcd_unregister_driver(struct lcd_driver *driver, struct lcd_parameters *par)
++{
++ int ret;
++ struct lcd_struct *p;
++
++ if (! driver || ! par || par->minor >= minors)
++ return (-EINVAL);
++
++ down(&drivers_sem);
++
++ if ((p = find_lcd_struct(par->minor)) == NULL || p->driver != driver) {
++ printk(KERN_ERR "LCD: driver not found; lcd_unregister_driver failed\n");
++ up(&drivers_sem);
++ return (-ENODEV);
++ }
++
++ down(&p->lcd_sem);
++
++ if (p->refcount) {
++ printk(KERN_ERR "LCD: driver busy; lcd_unregister_driver failed\n");
++ up(&p->lcd_sem);
++ up(&drivers_sem);
++ return (-EBUSY);
++ }
++
++ if ((ret = cleanup_driver(p))) {
++ up(&p->lcd_sem);
++ up(&drivers_sem);
++ return (ret);
++ }
++
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 19)
++ device_destroy(lcd_linux_class, MKDEV(major, par->minor));
++#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 13)
++ class_device_destroy(lcd_linux_class, MKDEV(major, par->minor));
++#endif
++
++#ifdef USE_PROC
++ if (p->driver->driver_proc_root)
++ remove_proc_entry(p->par->name, lcd_proc_root);
++#endif
++
++ list_del(&p->lcd_list);
++ kfree(p);
++
++ up(&drivers_sem);
++
++#ifdef MODULE
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0)
++ module_put(THIS_MODULE);
++#else
++ MOD_DEC_USE_COUNT;
++#endif
++#endif
++
++ return (0);
++}
++EXPORT_SYMBOL(lcd_unregister_driver);
++
++
++
++
++
++/************************
++ * Kernel I/O interface *
++ ************************/
++/* Exported function */
++int lcd_open(unsigned short minor, struct lcd_struct **pp)
++{
++ int ret;
++ struct lcd_struct *p;
++
++ down(&drivers_sem);
++
++ if (minor >= minors || (*pp = p = find_lcd_struct(minor)) == NULL) {
++ printk(KERN_ERR "LCD: lcd_open failed. Device not found.\n");
++ up(&drivers_sem);
++ return (-ENODEV);
++ }
++
++ down(&p->lcd_sem);
++ up(&drivers_sem);
++
++ ret = do_lcd_open(p);
++
++ up(&p->lcd_sem);
++
++ return (ret);
++}
++EXPORT_SYMBOL(lcd_open);
++
++/* Exported function */
++int lcd_close(struct lcd_struct **pp)
++{
++ int ret;
++ struct lcd_struct *p;
++
++ if (! pp || ! (p = *pp)) {
++ printk(KERN_ERR "LCD: NULL pointer in lcd_close\n");
++ return (-ENODEV);
++ }
++
++ down(&p->lcd_sem);
++
++ if (! (ret = do_lcd_release(p)))
++ *pp = NULL;
++
++ up(&p->lcd_sem);
++
++ return (ret);
++}
++EXPORT_SYMBOL(lcd_close);
++
++static inline loff_t offset_to_row_col(struct lcd_struct *p, loff_t offset)
++{
++ unsigned long _offset = offset;
++ unsigned int vs_cols = p->par->vs_cols;
++
++ gotoxy(p, _offset%vs_cols, _offset/vs_cols);
++
++ return ((p->row*vs_cols)+p->col);
++}
++
++/* Exported function */
++ssize_t lcd_read(struct lcd_struct *p, void *bufp, size_t length, loff_t offset, unsigned int with_attr)
++{
++ ssize_t ret = 0;
++
++ if (! p) {
++ printk(KERN_ERR "LCD: NULL pointer in lcd_read\n");
++ return (-ENODEV);
++ }
++ if (! bufp)
++ return (-EFAULT);
++ if (offset < 0 || offset >= p->fb_size)
++ return (-EINVAL);
++
++ if (length+offset > p->fb_size)
++ length = p->fb_size-offset;
++
++ if (with_attr)
++ set_bit(WITH_ATTR, &p->struct_flags);
++
++ offset_to_row_col(p, offset);
++ ret = do_lcd_read(p, bufp, length);
++
++ if (with_attr)
++ clear_bit(WITH_ATTR, &p->struct_flags);
++
++ return (ret);
++}
++EXPORT_SYMBOL(lcd_read);
++
++/* Exported function */
++ssize_t lcd_write(struct lcd_struct *p, const void *bufp, size_t length, loff_t offset, unsigned int with_attr)
++{
++ ssize_t ret;
++
++ if (! p) {
++ printk(KERN_ERR "LCD: NULL pointer in lcd_write\n");
++ return (-ENODEV);
++ }
++ if (! bufp)
++ return (-EFAULT);
++ if (offset < 0 || offset >= p->fb_size)
++ return (-EINVAL);
++
++ if (with_attr)
++ set_bit(WITH_ATTR, &p->struct_flags);
++
++ offset_to_row_col(p, offset);
++ ret = do_lcd_write(p, bufp, length);
++
++ if (with_attr)
++ clear_bit(WITH_ATTR, &p->struct_flags);
++
++ return (ret);
++}
++EXPORT_SYMBOL(lcd_write);
++
++/* Exported function */
++int lcd_ioctl(struct lcd_struct *p, unsigned int cmd, ...)
++{
++ int ret;
++ unsigned long arg;
++ va_list ap;
++
++ if (! p) {
++ printk(KERN_ERR "LCD: NULL pointer in lcd_ioctl\n");
++ return (-ENODEV);
++ }
++
++ down(&p->lcd_sem);
++ va_start(ap, cmd);
++ arg = va_arg(ap, unsigned long);
++ ret = do_lcd_ioctl(p, cmd, arg);
++ va_end(ap);
++ up(&p->lcd_sem);
++
++ return (ret);
++}
++EXPORT_SYMBOL(lcd_ioctl);
++
++
++
++
++
++/*******************
++ * File operations *
++ *******************/
++static loff_t lcd_fops_llseek(struct file *filp, loff_t offset, int orig)
++{
++ struct lcd_struct *p;
++
++ if (! (p = filp->private_data))
++ return (-ENODEV);
++
++ down(&p->lcd_sem);
++
++ switch (orig) {
++ case 0:
++ break;
++
++ case 1:
++ offset += filp->f_pos;
++ break;
++
++ default:
++ up(&p->lcd_sem);
++ return (-EINVAL); /* SEEK_END not supported */
++ }
++
++ if (offset >= 0 && offset < p->fb_size)
++ filp->f_pos = offset_to_row_col(p, offset);
++ else
++ offset = -EINVAL;
++
++ up(&p->lcd_sem);
++
++ return (offset);
++}
++
++static ssize_t lcd_fops_read(struct file *filp, char *buffer, size_t length, loff_t *offp)
++{
++ ssize_t ret = 0;
++ char *bufp = buffer;
++ struct lcd_struct *p;
++
++ if (! bufp)
++ return (-EFAULT);
++ if (! (p = filp->private_data))
++ return (-ENODEV);
++
++ down(&p->lcd_sem);
++
++ if (*offp < 0 || *offp >= p->fb_size) {
++ up(&p->lcd_sem);
++ return (-EINVAL);
++ }
++
++ if (test_bit(WITH_ATTR, &p->struct_flags) && (length & 0x01))
++ length &= ~0x01;
++
++ if (length+(*offp) > p->fb_size)
++ length = p->fb_size-(*offp);
++
++ while (length) {
++ ret = (length > FLIP_BUF_SIZE ? FLIP_BUF_SIZE : length);
++ if (test_bit(WITH_ATTR, &p->struct_flags))
++ ret /= sizeof(unsigned short);
++ if ((ret = do_lcd_read(p, p->flip_buf, ret)) < 0)
++ break;
++ if (test_bit(WITH_ATTR, &p->struct_flags))
++ ret *= sizeof(unsigned short);
++ *offp = (p->row*p->par->vs_cols)+p->col;
++ if (copy_to_user(bufp, p->flip_buf, ret)) {
++ ret = -EFAULT;
++ break;
++ }
++ length -= ret;
++ bufp += ret;
++ ret = bufp-buffer;
++ if (length)
++ schedule();
++ }
++
++ up(&p->lcd_sem);
++
++ return (ret);
++}
++
++static ssize_t lcd_fops_write(struct file *filp, const char *buffer, size_t length, loff_t *offp)
++{
++ ssize_t ret = 0;
++ const char *bufp = buffer;
++ struct lcd_struct *p;
++
++ if (! bufp)
++ return (-EFAULT);
++ if (! (p = filp->private_data))
++ return (-ENODEV);
++
++ down(&p->lcd_sem);
++
++ if (*offp < 0 || *offp >= p->fb_size) {
++ up(&p->lcd_sem);
++ return (-EINVAL);
++ }
++
++ if (test_bit(WITH_ATTR, &p->struct_flags) && (length & 0x01))
++ length &= ~0x01;
++
++ while (length) {
++ ret = (length > FLIP_BUF_SIZE ? FLIP_BUF_SIZE : length);
++ if (copy_from_user(p->flip_buf, bufp, ret)) {
++ ret = -EFAULT;
++ break;
++ }
++ if (test_bit(WITH_ATTR, &p->struct_flags))
++ ret /= sizeof(unsigned short);
++ if ((ret = do_lcd_write(p, p->flip_buf, ret)) < 0)
++ break;
++ if (test_bit(WITH_ATTR, &p->struct_flags))
++ ret *= sizeof(unsigned short);
++ *offp = (p->row*p->par->vs_cols)+p->col;
++ length -= ret;
++ bufp += ret;
++ ret = bufp-buffer;
++ if (length)
++ schedule();
++ }
++
++ up(&p->lcd_sem);
++
++ return (ret);
++}
++
++static int lcd_fops_open(struct inode *inop, struct file *filp)
++{
++ unsigned short minor;
++ int ret;
++ struct lcd_struct *p;
++
++ down(&drivers_sem);
++
++ if ((minor = MINOR(inop->i_rdev)) >= minors || (filp->private_data = p = find_lcd_struct(minor)) == NULL) {
++ up(&drivers_sem);
++ return (-ENODEV);
++ }
++
++ down(&p->lcd_sem);
++ up(&drivers_sem);
++
++ ret = do_lcd_open(p);
++
++ up(&p->lcd_sem);
++
++ return (ret);
++}
++
++static int lcd_fops_release(struct inode *inop, struct file *filp)
++{
++ struct lcd_struct *p;
++ int ret;
++
++ if (! (p = filp->private_data))
++ return (-ENODEV);
++
++ down(&p->lcd_sem);
++
++ if (! (ret = do_lcd_release(p)))
++ filp->private_data = NULL;
++
++ up(&p->lcd_sem);
++
++ return (ret);
++}
++
++static long lcd_fops_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
++{
++ struct lcd_struct *p;
++ int ret;
++
++ if (! (p = filp->private_data))
++ return (-ENODEV);
++
++ down(&p->lcd_sem);
++
++ set_bit(USER_SPACE, &p->struct_flags);
++ ret = do_lcd_ioctl(p, cmd, arg);
++ clear_bit(USER_SPACE, &p->struct_flags);
++
++ up(&p->lcd_sem);
++
++ return (ret);
++}
++
++static struct file_operations lcd_linux_fops = {
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 4, 0)
++ .owner = THIS_MODULE,
++#endif
++ .llseek = lcd_fops_llseek,
++ .read = lcd_fops_read,
++ .write = lcd_fops_write,
++ .open = lcd_fops_open,
++ .release = lcd_fops_release,
++ .unlocked_ioctl = lcd_fops_ioctl,
++};
++
++
++
++
++
++/********************************
++ * Init/Cleanup driver routines *
++ ********************************/
++static int do_init_driver(struct lcd_struct *p)
++{
++ int ret;
++ struct lcd_driver *driver = p->driver;
++ struct lcd_parameters *par = p->par;
++ unsigned int frame_rows = par->cntr_rows*par->num_cntr;
++ unsigned int frame_cols = par->cntr_cols;
++
++ switch (INIT_LEVEL(p)) {
++ case 0:
++ if (frame_rows == 0 || frame_cols == 0 || ! par->name) {
++ printk(KERN_ERR "LCD: wrong lcd parameters\n");
++ return (-EINVAL);
++ }
++ if (driver->validate_driver) {
++ if ((ret = driver->validate_driver()) < 0) {
++ printk(KERN_ERR "LCD: validate_driver failed\n");
++ return (-EINVAL);
++ } else if (ret > 0) {
++ set_bit(CAN_DO_COLOR, &p->struct_flags);
++ p->defcolor = 0x07;
++ p->ulcolor = 0x0f;
++ p->halfcolor = 0x08;
++ }
++ }
++ default_attr(p);
++ update_attr(p);
++ p->frame_size = frame_rows*frame_cols;
++ if (par->vs_rows < frame_rows)
++ par->vs_rows = frame_rows;
++ if (par->vs_cols < frame_cols)
++ par->vs_cols = frame_cols;
++ p->fb_size = par->vs_rows*par->vs_cols;
++
++ ret = sizeof(short)*p->fb_size;
++ ret += sizeof(short)*p->frame_size;
++ ret += FLIP_BUF_SIZE;
++ ret += (p->driver->charmap ? 256 : 512);
++ if (par->cgram_chars*par->cgram_bytes)
++ ret += (1+par->cgram_chars)*par->cgram_bytes;
++ if ((p->fb = (unsigned short *)vmalloc(ret)) == NULL) {
++ printk(KERN_ERR "LCD: memory allocation failed (vmalloc)\n");
++ return (-ENOMEM);
++ }
++ __memset_short(p->fb, p->erase_char, p->fb_size+p->frame_size);
++
++ p->display = p->fb+p->fb_size;
++ p->flip_buf = (unsigned char *)(p->display+p->frame_size);
++
++ if (! p->driver->charmap) {
++ set_bit(NULL_CHARMAP, &p->struct_flags);
++ p->driver->charmap = p->flip_buf+FLIP_BUF_SIZE;
++ for (ret = 0; ret < 256; ++ret)
++ p->driver->charmap[ret] = ret;
++ p->s_charmap = p->driver->charmap+256;
++ } else
++ p->s_charmap = p->flip_buf+FLIP_BUF_SIZE;
++ memset(p->s_charmap, 0, 256);
++
++ if (par->cgram_chars*par->cgram_bytes) {
++ p->cgram_buffer = p->s_charmap+256+par->cgram_bytes;
++ memset(p->cgram_buffer, 0xff, par->cgram_chars*par->cgram_bytes);
++ } else
++ p->cgram_buffer = NULL;
++ p->driver->cgram_buffer = p->cgram_buffer;
++
++ p->frame_base = 0;
++ p->row = p->col = 0;
++ p->top = 0;
++ p->bot = par->vs_rows;
++ SET_INIT_LEVEL(p, 1);
++
++ case 1:
++ /* Initialize the communication port */
++ if ((ret = driver->init_port())) {
++ printk(KERN_ERR "LCD: failure while initializing the communication port\n");
++ return (ret);
++ }
++ SET_INIT_LEVEL(p, 2);
++
++ case 2:
++ /* Initialize LCD display */
++ if (driver->init_display && (ret = driver->init_display())) {
++ printk(KERN_ERR "LCD: failure while initializing the display\n");
++ return (ret);
++ }
++
++#ifdef USE_PROC
++ /* Create entries in /proc/lcd/"driver" */
++ if (driver->driver_proc_root)
++ create_driver_proc_entries(p);
++#endif
++ SET_INIT_LEVEL(p, 3);
++ }
++
++ return (0);
++}
++
++static int do_cleanup_driver(struct lcd_struct *p)
++{
++ int ret;
++ struct lcd_driver *driver = p->driver;
++
++ switch (INIT_LEVEL(p)) {
++ case 3:
++#ifdef USE_PROC
++ if (driver->driver_proc_root)
++ remove_driver_proc_entries(p);
++#endif
++ if (driver->cleanup_display && (ret = driver->cleanup_display())) {
++ printk(KERN_ERR "LCD: failure while cleaning the display\n");
++ return (ret);
++ }
++ SET_INIT_LEVEL(p, 2);
++
++ case 2:
++ if ((ret = driver->cleanup_port())) {
++ printk(KERN_ERR "LCD: failure while cleaning the communication port\n");
++ return (ret);
++ }
++ SET_INIT_LEVEL(p, 1);
++
++ case 1:
++ if (test_bit(NULL_CHARMAP, &p->struct_flags)) {
++ p->driver->charmap = NULL;
++ clear_bit(NULL_CHARMAP, &p->struct_flags);
++ }
++ vfree(p->fb);
++ p->fb = NULL;
++ SET_INIT_LEVEL(p, 0);
++ }
++
++ return (0);
++}
++
++static int init_driver(struct lcd_struct *p)
++{
++ int ret;
++
++ if ((ret = do_init_driver(p))) {
++ do_cleanup_driver(p);
++ printk(KERN_ERR "LCD: init_driver failed\n");
++ }
++
++ return (ret);
++}
++
++static int cleanup_driver(struct lcd_struct *p)
++{
++ int ret;
++
++ if ((ret = do_cleanup_driver(p))) {
++ do_init_driver(p);
++ printk(KERN_ERR "LCD: cleanup_driver failed\n");
++ }
++
++ return (ret);
++}
++
++
++
++
++
++/********************************
++ * Init/Cleanup module routines *
++ ********************************/
++static int __init lcd_linux_init_module(void)
++{
++ int ret;
++
++ if (! minors || minors > 256)
++ minors = LCD_MINORS;
++
++ init_MUTEX(&drivers_sem);
++
++ if ((ret = register_chrdev(major, LCD_LINUX_STRING, &lcd_linux_fops)) < 0) {
++ printk(KERN_ERR "LCD: register_chrdev failed\n");
++ return (ret);
++ }
++ if (major == 0)
++ major = ret;
++
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 13)
++ if (IS_ERR((lcd_linux_class = class_create(THIS_MODULE, "lcd")))) {
++ ret = PTR_ERR(lcd_linux_class);
++ unregister_chrdev(major, LCD_LINUX_STRING);
++ return (ret);
++ }
++#endif
++
++#ifdef USE_PROC
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26)
++ if ((lcd_proc_root = proc_mkdir("lcd", NULL)) == NULL)
++#else
++ if ((lcd_proc_root = proc_mkdir("lcd", &proc_root)) == NULL)
++#endif
++ printk(KERN_ERR "LCD: cannot create /proc/lcd/\n");
++ else if (create_proc_read_entry("drivers", 0, lcd_proc_root, proc_registered_drivers, NULL) == NULL)
++ printk(KERN_ERR "LCD: cannot create /proc/lcd/drivers\n");
++#endif
++
++ printk(KERN_INFO "LCD: --> LCD-Linux " LCD_LINUX_VERSION " <--\n");
++ printk(KERN_INFO "LCD: --> Mattia Jona-Lasinio <mjona@users.sourceforge.net> <--\n" );
++
++
++ return (0);
++}
++
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 4, 0)
++static void __exit lcd_linux_cleanup_module(void)
++#else
++/* __exit is not defined in 2.2.x kernels */
++static void lcd_linux_cleanup_module(void)
++#endif
++{
++#ifdef USE_PROC
++ if (lcd_proc_root) {
++ remove_proc_entry("drivers", lcd_proc_root);
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26)
++ remove_proc_entry("lcd", NULL);
++#else
++ remove_proc_entry("lcd", &proc_root);
++#endif
++ }
++#endif
++
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 13)
++ class_destroy(lcd_linux_class);
++#endif
++
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 23)
++ unregister_chrdev(major, LCD_LINUX_STRING);
++#else
++ if (unregister_chrdev(major, LCD_LINUX_STRING))
++ printk(KERN_ERR "LCD: unregister_chrdev failed\n");
++#endif
++}
++
++module_init(lcd_linux_init_module)
++module_exit(lcd_linux_cleanup_module)
+diff --git a/include/linux/hd44780.h b/include/linux/hd44780.h
+new file mode 100644
+index 0000000..9033d44
+--- /dev/null
++++ b/include/linux/hd44780.h
+@@ -0,0 +1,47 @@
++/* hd44780.h
++ *
++ * $Id: hd44780.h,v 1.15 2009/03/09 17:59:23 mjona Exp $
++ *
++ * LCD-Linux:
++ * Driver for HD44780 compatible displays connected to the parallel port.
++ *
++ * HD44780 header file.
++ *
++ * Copyright (C) 2004 - 2009 Mattia Jona-Lasinio (mjona@users.sourceforge.net)
++ *
++ * 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 HD44780_H
++#define HD44780_H
++
++#include <linux/lcd-linux.h>
++
++#define HD44780_VERSION LCD_LINUX_VERSION /* Version number */
++#define HD44780_STRING "hd44780"
++
++#define HD44780_MINOR 0 /* Minor number for the hd44780 driver */
++
++
++/* flags */
++#define HD44780_CHECK_BF 0x00000001 /* Do busy flag checking */
++#define HD44780_4BITS_BUS 0x00000002 /* Set the bus length to 4 bits */
++#define HD44780_5X10_FONT 0x00000004 /* Use 5x10 dots fonts */
++
++/* IOCTLs */
++#define HD44780_READ_AC _IOR(LCD_MAJOR, 0x00, unsigned char *)
++
++#endif /* HD44780 included */
+diff --git a/include/linux/lcd-linux.h b/include/linux/lcd-linux.h
+new file mode 100644
+index 0000000..1756107
+--- /dev/null
++++ b/include/linux/lcd-linux.h
+@@ -0,0 +1,158 @@
++/* lcd-linux.h
++ *
++ * $Id: lcd-linux.h,v 1.68 2010/07/04 16:02:02 mjona Exp $
++ *
++ * Software layer to drive LCD displays under Linux.
++ *
++ * External interface header file.
++ *
++ * Copyright (C) 2005 - 2009 Mattia Jona-Lasinio (mjona@users.sourceforge.net)
++ *
++ * 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 LCD_LINUX_H
++#define LCD_LINUX_H
++
++#ifndef LCD_LINUX_MAIN
++#warning
++#warning LCD-Linux is still in development stage and
++#warning aims at speed and optimization. For these
++#warning reasons there is no guarantee of backward
++#warning compatibility between different LCD-Linux
++#warning versions. Be sure to use the lcd-linux.h
++#warning file of the same version as the module.
++#warning "http://lcd-linux.sourceforge.net/"
++#warning
++#endif
++
++#define LCD_LINUX_VERSION "0.13.9" /* Version number */
++#define LCD_LINUX_STRING "lcd"
++
++#define LCD_MAJOR 120 /* Major number for this device
++ * Set this to 0 for dynamic allocation
++ */
++#define LCD_MINORS 8 /* Minors allocated for LCD-Linux*/
++
++#include <linux/types.h>
++
++#define str(s) #s
++#define string(s) str(s)
++
++struct lcd_parameters {
++ const char *name; /* Driver's name */
++ unsigned long flags; /* Flags (see documentation) */
++ unsigned short minor; /* Minor number of the char device */
++ unsigned short tabstop; /* Tab character length */
++ unsigned short num_cntr; /* Controllers to drive */
++ unsigned short cntr_rows; /* Rows per controller */
++ unsigned short cntr_cols; /* Display columns */
++ unsigned short vs_rows; /* Virtual screen rows */
++ unsigned short vs_cols; /* Virtual screen columns */
++ unsigned short cgram_chars; /* Number of user definable characters */
++ unsigned short cgram_bytes; /* Number of bytes required to define a
++ * user definable character */
++ unsigned char cgram_char0; /* Ascii of first user definable character */
++};
++
++/* IOCTLs */
++#include <asm/ioctl.h>
++#define LCDL_SET_PARAM _IOW(LCD_MAJOR, 0x80, struct lcd_parameters *)
++#define LCDL_GET_PARAM _IOR(LCD_MAJOR, 0x81, struct lcd_parameters *)
++#define LCDL_CHARSUBST _IOW(LCD_MAJOR, 0x82, unsigned char *)
++#define LCDL_RAW_MODE _IOW(LCD_MAJOR, 0x83, unsigned int)
++#define LCDL_RESET_CHARMAP _IO(LCD_MAJOR, 0x84)
++#define LCDL_SAVE_CHARMAP _IO(LCD_MAJOR, 0x85)
++#define LCDL_RESTORE_CHARMAP _IO(LCD_MAJOR, 0x86)
++#define LCDL_SWAP_CHARMAP _IO(LCD_MAJOR, 0x87)
++#define LCDL_CLEAR_DISP _IO(LCD_MAJOR, 0x88)
++#define LCDL_SET_CGRAM_CHAR _IOW(LCD_MAJOR, 0x89, unsigned char *)
++#define LCDL_GET_CGRAM_CHAR _IOR(LCD_MAJOR, 0x8a, unsigned char *)
++#define LCDL_SET_CHARMAP _IOW(LCD_MAJOR, 0x8b, unsigned char *)
++#define LCDL_GET_CHARMAP _IOR(LCD_MAJOR, 0x8c, unsigned char *)
++#define LCDL_MEMSET _IOW(LCD_MAJOR, 0x8d, unsigned int *)
++#define LCDL_MEMMOVE _IOW(LCD_MAJOR, 0x8e, unsigned int *)
++#define LCDL_IOATTR _IOW(LCD_MAJOR, 0x8f, unsigned int)
++
++
++
++#ifdef __KERNEL__ /* The rest is for kernel only */
++
++#include <linux/kernel.h>
++#include <linux/module.h>
++
++
++struct lcd_driver {
++ void (*read_char)(unsigned int offset, unsigned short *data);
++ void (*read_cgram_char)(unsigned char index, unsigned char *pixmap);
++ void (*write_char)(unsigned int offset, unsigned short data);
++ void (*write_cgram_char)(unsigned char index, unsigned char *pixmap);
++ void (*clear_display)(void);
++ void (*address_mode)(int mode);
++ int (*validate_driver)(void);
++ int (*init_display)(void);
++ int (*cleanup_display)(void);
++ int (*init_port)(void);
++ int (*cleanup_port)(void);
++ int (*handle_custom_char)(unsigned int data);
++ int (*handle_custom_ioctl)(unsigned int cmd, unsigned long arg, unsigned int arg_in_userspace);
++
++ /* The character map to be used */
++ unsigned char *charmap;
++
++ /* Buffer for CGRAM operations.
++ * Will be filled by the lcd-linux layer.
++ */
++ unsigned char *cgram_buffer;
++
++ /* The root where the driver can create its own proc files.
++ * Will be filled by the lcd-linux layer.
++ */
++ struct proc_dir_entry *driver_proc_root;
++
++ /* Set this field to 'driver_module_init' or call lcd_driver_setup
++ * just before registering the driver with lcd_register_driver.
++ */
++ struct module *driver_module;
++};
++
++#ifdef MODULE
++#define driver_module_init THIS_MODULE
++#else
++#define driver_module_init NULL
++#endif
++
++/* Always call lcd_driver_setup just before registering the driver
++ * with lcd_register_driver.
++ */
++static inline void lcd_driver_setup(struct lcd_driver *p)
++{
++ p->driver_module = driver_module_init;
++}
++
++/* External interface */
++struct lcd_struct;
++int lcd_register_driver(struct lcd_driver *drv, struct lcd_parameters *par);
++int lcd_unregister_driver(struct lcd_driver *drv, struct lcd_parameters *par);
++int lcd_open(unsigned short minor, struct lcd_struct **lcd);
++int lcd_close(struct lcd_struct **lcd);
++int lcd_ioctl(struct lcd_struct *lcd, unsigned int cmd, ...);
++ssize_t lcd_write(struct lcd_struct *lcd, const void *buffer, size_t length, loff_t offset, unsigned int with_attr);
++ssize_t lcd_read(struct lcd_struct *lcd, void *buffer, size_t length, loff_t offset, unsigned int with_attr);
++
++#endif /* __KERNEL__ */
++
++#endif /* External interface included */
+--
+1.7.1
+
diff --git a/recipes/linux/linux-2.6.38/ts72xx/0021-TS-72XX-LCD-console-driver.patch b/recipes/linux/linux-2.6.38/ts72xx/0021-TS-72XX-LCD-console-driver.patch
new file mode 100644
index 0000000..466d251
--- /dev/null
+++ b/recipes/linux/linux-2.6.38/ts72xx/0021-TS-72XX-LCD-console-driver.patch
@@ -0,0 +1,528 @@
+From 25924a9f5136cbcb4ec3d4ea65a6c0814662b333 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Petr=20=C5=A0tetiar?= <ynezz@true.cz>
+Date: Sun, 13 Mar 2011 21:15:10 +0100
+Subject: [PATCH 21/24] TS-72XX LCD console driver
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Signed-off-by: Petr Štetiar <ynezz@true.cz>
+---
+ arch/arm/mach-ep93xx/include/mach/ep93xx-regs.h | 4 +
+ drivers/video/console/Kconfig | 21 +
+ drivers/video/console/Makefile | 2 +
+ drivers/video/console/ts72xx_con.c | 442 +++++++++++++++++++++++
+ 4 files changed, 469 insertions(+), 0 deletions(-)
+ create mode 100644 drivers/video/console/ts72xx_con.c
+
+diff --git a/arch/arm/mach-ep93xx/include/mach/ep93xx-regs.h b/arch/arm/mach-ep93xx/include/mach/ep93xx-regs.h
+index 87a5bfe..39e5b5a 100644
+--- a/arch/arm/mach-ep93xx/include/mach/ep93xx-regs.h
++++ b/arch/arm/mach-ep93xx/include/mach/ep93xx-regs.h
+@@ -111,6 +111,10 @@
+ #define EP93XX_GPIO_B_INT_DEBOUNCE EP93XX_GPIO_REG(0xc4)
+ #define EP93XX_GPIO_EEDRIVE EP93XX_GPIO_REG(0xc8)
+
++/* ts72xx lcd console driver quick "hack" */
++#define EP93XX_GPIO_A_DATA EP93XX_GPIO_REG(0x00)
++#define EP93XX_GPIO_A_DIRECTION EP93XX_GPIO_REG(0x10)
++
+ #define EP93XX_AAC_PHYS_BASE EP93XX_APB_PHYS(0x00080000)
+ #define EP93XX_AAC_BASE EP93XX_APB_IOMEM(0x00080000)
+
+diff --git a/drivers/video/console/Kconfig b/drivers/video/console/Kconfig
+index 2209e35..8afef58 100644
+--- a/drivers/video/console/Kconfig
++++ b/drivers/video/console/Kconfig
+@@ -89,6 +89,27 @@ config DUMMY_CONSOLE_ROWS
+ The default value is 64, which should fit a 1280x1024 monitor.
+ Select 25 if you use a 640x480 resolution by default.
+
++config TS72XX_CONSOLE
++ tristate "TS-72xx text LCD console"
++ depends on ARCH_EP93XX && MACH_TS72XX
++ help
++ Say Y to build a console driver for TS-72xx LCD (2x7) header.
++ LCD display must be compatible with HD44780 controller.
++
++config TS72XX_CONSOLE_COLUMNS
++ int "Initial number of console screen columns"
++ depends on TS72XX_CONSOLE
++ default "20"
++ help
++ Dependant to your text LCD, 16 or 20 are legacy values.
++
++config TS72XX_CONSOLE_ROWS
++ int "Initial number of console screen rows"
++ depends on TS72XX_CONSOLE
++ default "4"
++ help
++ Dependant to your text LCD, 2 or 4 are legacy values.
++
+ config FRAMEBUFFER_CONSOLE
+ tristate "Framebuffer Console support"
+ depends on FB
+diff --git a/drivers/video/console/Makefile b/drivers/video/console/Makefile
+index a862e91..e0f9269 100644
+--- a/drivers/video/console/Makefile
++++ b/drivers/video/console/Makefile
+@@ -25,6 +25,8 @@ obj-$(CONFIG_SGI_NEWPORT_CONSOLE) += newport_con.o font.o
+ obj-$(CONFIG_STI_CONSOLE) += sticon.o sticore.o font.o
+ obj-$(CONFIG_VGA_CONSOLE) += vgacon.o
+ obj-$(CONFIG_MDA_CONSOLE) += mdacon.o
++obj-$(CONFIG_TS72XX_CONSOLE) += ts72xx_con.o
++
+ obj-$(CONFIG_FRAMEBUFFER_CONSOLE) += fbcon.o bitblit.o font.o softcursor.o
+ ifeq ($(CONFIG_FB_TILEBLITTING),y)
+ obj-$(CONFIG_FRAMEBUFFER_CONSOLE) += tileblit.o
+diff --git a/drivers/video/console/ts72xx_con.c b/drivers/video/console/ts72xx_con.c
+new file mode 100644
+index 0000000..a6ac61d
+--- /dev/null
++++ b/drivers/video/console/ts72xx_con.c
+@@ -0,0 +1,442 @@
++/*
++ * TS-72XX lcd console driver for Technologic Systems boards.
++ *
++ * (c) Copyright 2008 Matthieu Crapet <mcrapet@gmail.com>
++ * Based on linux/drivers/video/console/dummycon.c
++ * Thanks to Jim Jackson (lcdd-0.2beta)
++ *
++ * 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.
++ *
++ * Note: Port H (LCD_EN, LCD_RS, LCD_WR) uses the new generic GPIO API.
++ * Port A is used manually used. To fix in future.
++ */
++
++#include <linux/kernel.h>
++#include <linux/module.h>
++#include <linux/console.h>
++#include <linux/vt_kern.h>
++#include <linux/delay.h>
++#include <mach/hardware.h>
++#include <mach/gpio.h>
++#include <asm/io.h>
++
++#define DRV_VERSION "0.3"
++#define PFX "ts72xx_con: "
++
++#define LCD_COLUMNS CONFIG_TS72XX_CONSOLE_COLUMNS
++#define LCD_ROWS CONFIG_TS72XX_CONSOLE_ROWS
++
++/* HD44780 instruction set */
++#define CMD_CLEAR (0x01)
++#define CMD_CURSOR_HOME (0x02)
++#define CMD_ENTRY_MODE(cursor_dir, display_shift) (0x04|(2*cursor_dir)|display_shift)
++#define CMD_DISPLAY_ONOFF(dis_on, cur_on, cur_blink_on) (0x08|(4*dis_on)|(2*cur_on)|cur_blink_on)
++#define CMD_FUNCTION_SET(intf_8bit, n, f) (0x20|(16*intf_8bit)|(8*n)|(4*f))
++#define CMD_DDRAM_ADDR(a) (0x80|(a))
++
++/* Port H, bit 3:5 */
++#define LCD_EN EP93XX_GPIO_LINE_H(3)
++#define LCD_RS EP93XX_GPIO_LINE_H(4)
++#define LCD_WR EP93XX_GPIO_LINE_H(5)
++
++static struct gpio lcd_gpios[] = {
++ { LCD_EN, GPIOF_OUT_INIT_LOW, "LCD enable" },
++ { LCD_RS, GPIOF_OUT_INIT_LOW, "LCD data" },
++ { LCD_WR, GPIOF_OUT_INIT_LOW, "LCD r/w" },
++};
++
++/* Timings */
++#define SETUP_TIME 200
++#define ENABLE_TIME 800
++#define HOLD_TIME 200
++
++void hd44780_delay(int i)
++{
++ ndelay(i);
++}
++
++/* Prototypes */
++static void hd44780_wait(void);
++static void hd44780_send_data(unsigned char data);
++static void hd44780_send_command(unsigned char command);
++static void hd44780_init(void);
++static void hd44780_deinit(void);
++static int hd44780_gotoxy(int x, int y);
++
++
++/* HD44780 controller */
++
++static void hd44780_wait(void)
++{
++ int i;
++ int b = 0;
++ unsigned char c;
++
++ __raw_writeb(0x00, EP93XX_GPIO_A_DIRECTION); // bus input
++ gpio_set_value(LCD_RS, 0); // low for control registers
++ gpio_set_value(LCD_WR, 1); // read command
++
++ do {
++ i = SETUP_TIME;
++ hd44780_delay(i);
++
++ gpio_set_value(LCD_EN, 1);
++
++ i = ENABLE_TIME;
++ hd44780_delay(i);
++
++ c = __raw_readb(EP93XX_GPIO_A_DATA);
++ gpio_set_value(LCD_EN, 0);
++
++ b++;
++ } while (c & 0x80); // busy flag
++
++ i = HOLD_TIME;
++ hd44780_delay(i);
++}
++
++
++static void hd44780_send_data(unsigned char data)
++{
++ int i;
++
++ __raw_writeb(0xFF, EP93XX_GPIO_A_DIRECTION); // bus output
++ gpio_set_value(LCD_RS, 1); // high for data
++ gpio_set_value(LCD_WR, 0); // write data
++
++ i = SETUP_TIME;
++ hd44780_delay(i);
++
++ __raw_writeb(data, EP93XX_GPIO_A_DATA);
++ gpio_set_value(LCD_EN, 1);
++
++ i = ENABLE_TIME;
++ hd44780_delay(i);
++
++ gpio_set_value(LCD_EN, 0);
++
++ i = HOLD_TIME;
++ hd44780_delay(i);
++}
++
++
++static void hd44780_send_command(unsigned char command)
++{
++ int i;
++
++ __raw_writeb(0xFF, EP93XX_GPIO_A_DIRECTION); // bus output
++ gpio_set_value(LCD_RS, 0); // low for control registers
++ gpio_set_value(LCD_WR, 0); // write command
++
++ i = SETUP_TIME;
++ hd44780_delay(i);
++
++ __raw_writeb(command, EP93XX_GPIO_A_DATA);
++ gpio_set_value(LCD_EN, 1);
++
++ i = ENABLE_TIME;
++ hd44780_delay(i);
++
++ gpio_set_value(LCD_EN, 0);
++
++ i = HOLD_TIME;
++ hd44780_delay(i);
++}
++
++static void hd44780_deinit()
++{
++ gpio_free_array(lcd_gpios, ARRAY_SIZE(lcd_gpios));
++}
++
++static void hd44780_init(void)
++{
++ int i;
++ int err;
++
++ err = gpio_request_array(lcd_gpios, ARRAY_SIZE(lcd_gpios));
++ if (err) {
++ printk(KERN_ERR PFX "error while requesting GPIO pins\n");
++ return;
++ }
++
++ /* Port A (8 bits) is data bus */
++ __raw_writeb(0x00, EP93XX_GPIO_A_DATA);
++ __raw_writeb(0x00, EP93XX_GPIO_A_DIRECTION);
++
++ /* 8-bit mode, double line, 5x7 dot character format */
++ hd44780_send_command(CMD_FUNCTION_SET(1,1,1));
++ i = 5000;
++ hd44780_delay(i);
++
++ /* Display on and blink cursor on */
++ hd44780_send_command(CMD_DISPLAY_ONOFF(1,1,1));
++ hd44780_wait();
++
++ /* Cursor in increment position and shift is invisible */
++ hd44780_send_command(CMD_ENTRY_MODE(0,0));
++ hd44780_wait();
++
++ /* Clean display and return cursor to home position */
++ hd44780_send_command(CMD_CLEAR);
++ hd44780_wait();
++}
++
++
++static int hd44780_gotoxy(int x, int y)
++{
++ const unsigned char lines[4] = { 0x00, 0x40, 0x14, 0x54 };
++
++ if ((x == 0) && (y == 0)) {
++ hd44780_send_command(CMD_CURSOR_HOME);
++ hd44780_wait();
++ } else if (y < 4) {
++ hd44780_send_command(CMD_DDRAM_ADDR(lines[y]+x));
++ hd44780_wait();
++ }
++
++ return 0;
++}
++
++
++/* Console operation functions */
++
++static const char *lcdcon_startup(void)
++{
++ return "ts72xx lcd console";
++}
++
++
++static void lcdcon_init(struct vc_data *vc, int init)
++{
++ hd44780_init();
++
++ vc->vc_can_do_color = 0;
++ vc->vc_video_erase_char = 0x20;
++
++ if (init) {
++ vc->vc_cols = LCD_COLUMNS;
++ vc->vc_rows = LCD_ROWS;
++ } else
++ vc_resize(vc, LCD_COLUMNS, LCD_ROWS);
++
++}
++
++
++static void lcdcon_deinit(struct vc_data *vc)
++{
++ hd44780_deinit();
++}
++
++
++static void lcdcon_clear(struct vc_data *vc, int sy, int sx,
++ int height, int width)
++{
++ int i, j;
++
++ if (!height || !width)
++ return;
++
++ for (i = 0; i < height; i++) {
++ hd44780_gotoxy(sx, sy + i);
++ for (j = 0; j < width; j++) {
++ hd44780_send_data((unsigned char)vc->vc_video_erase_char);
++ hd44780_wait();
++ }
++ }
++
++}
++
++
++static int lcdcon_blank(struct vc_data *vc, int blank, int mode_switch)
++{
++ unsigned char c;
++
++ if (blank == 0) {
++ c = CMD_DISPLAY_ONOFF(1,1,1); /* Display on */
++ } else {
++ c = CMD_DISPLAY_ONOFF(0,1,1); /* Display off */
++ }
++
++ hd44780_send_command(c);
++ hd44780_wait();
++
++ return 1;
++}
++
++
++static int lcdcon_set_palette(struct vc_data *vc, unsigned char *table)
++{
++ return -EINVAL;
++}
++
++
++static void lcdcon_putc(struct vc_data *vc, int c, int y, int x)
++{
++ if (vc->vc_mode != KD_TEXT)
++ return;
++
++ hd44780_gotoxy(x, y);
++ hd44780_send_data((unsigned char)c);
++ hd44780_wait();
++}
++
++
++static void lcdcon_putcs(struct vc_data *vc, const unsigned short *s,
++ int count, int y, int x)
++{
++ if (vc->vc_mode != KD_TEXT)
++ return;
++
++ hd44780_gotoxy(x, y);
++ while (count--) {
++ hd44780_send_data((unsigned char)(*s));
++ hd44780_wait();
++ s++;
++ }
++
++}
++
++
++static void lcdcon_cursor(struct vc_data *vc, int mode)
++{
++ hd44780_gotoxy(vc->vc_x, vc->vc_y);
++
++ switch (mode) {
++ case CM_ERASE:
++ hd44780_send_command(CMD_DISPLAY_ONOFF(1,0,0)); // Cursor off
++ hd44780_wait();
++ break;
++
++ case CM_DRAW:
++ hd44780_send_command(CMD_DISPLAY_ONOFF(1,1,1)); // Cursor on, Blinking on
++ hd44780_wait();
++ break;
++
++ case CM_MOVE:
++ printk(KERN_NOTICE PFX "lcdcon_cursor CM_MOVE not implemented\n");
++ break;
++ }
++
++}
++
++
++static int lcdcon_scroll(struct vc_data *vc, int t, int b, int dir, int count)
++{
++ int i;
++
++ if (!count)
++ return 0;
++
++ /* Special case */
++ //if (t || b != vc->vc_rows)
++ // scroll area
++
++ switch (dir) {
++ case SM_UP:
++ if (count > vc->vc_rows)
++ count = vc->vc_rows;
++
++ for (i = 0; i < (vc->vc_rows - count); i++) {
++ lcdcon_putcs(vc, vc->vc_screenbuf + (vc->vc_y - i)*vc->vc_cols,
++ vc->vc_cols, vc->vc_y - i -1, 0);
++ }
++
++ /* Clear last line */
++ hd44780_gotoxy(0, vc->vc_y);
++ for (i = 0; i < vc->vc_cols; i++) {
++ hd44780_send_data((unsigned char)vc->vc_video_erase_char);
++ hd44780_wait();
++ }
++ break;
++
++ case SM_DOWN:
++ printk(KERN_NOTICE PFX "lcdcon_scroll DOWN (t=%d b=%d count=%d) not implemtented\n", t,b,count);
++ break;
++ }
++
++ return 0;
++}
++
++
++static void lcdcon_bmove(struct vc_data *vc, int sy, int sx,
++ int dy, int dx, int height, int width)
++{
++ int i, j;
++
++ if (!height || !width)
++ return;
++
++ for (i = 0; i < height; i++) {
++ hd44780_gotoxy(dx, dy + i);
++ for (j = 0; j < width; j++) {
++ hd44780_send_data((unsigned char)(*(vc->vc_screenbuf +
++ (sy+i)*vc->vc_cols + (sx+j) )));
++ hd44780_wait();
++ }
++ }
++}
++
++
++static int lcdcon_dummy(void)
++{
++ return 0;
++}
++
++#define DUMMY (void *)lcdcon_dummy
++
++
++/* Main structure */
++const struct consw ts72xx_lcd_con = {
++ .owner = THIS_MODULE,
++ .con_startup = lcdcon_startup,
++ .con_init = lcdcon_init,
++ .con_deinit = lcdcon_deinit,
++ .con_clear = lcdcon_clear,
++ .con_putc = lcdcon_putc,
++ .con_putcs = lcdcon_putcs,
++ .con_cursor = lcdcon_cursor,
++ .con_scroll = lcdcon_scroll,
++ .con_bmove = lcdcon_bmove,
++ .con_switch = DUMMY,
++ .con_blank = lcdcon_blank,
++
++ /* We cannot change color, fonts on character LCD */
++ .con_font_set = DUMMY,
++ .con_font_get = DUMMY,
++ .con_font_default = DUMMY,
++ .con_font_copy = DUMMY,
++ .con_set_palette = lcdcon_set_palette,
++
++ //.con_scrolldelta = lcdcon_scrolldelta,
++ //.con_set_origin = DUMMY,
++ //.con_save_screen = lcdcon_save_screen,
++ //.con_build_attr = lcdcon_build_attr,
++ //.con_invert_region = lcdcon_invert_region,
++ //.con_screen_pos = lcdcon_screen_pos,
++ //.con_getxy = lcdcon_getxy,
++};
++
++/* Module functions */
++
++static int __init ts72xx_lcd_init(void)
++{
++ printk(KERN_NOTICE "TS-72xx lcd console driver v" DRV_VERSION " loaded\n");
++ return take_over_console(&ts72xx_lcd_con, 0, MAX_NR_CONSOLES-1, 1);
++}
++
++static void __exit ts72xx_lcd_exit(void)
++{
++ printk(KERN_NOTICE "TS-72xx lcd console driver v" DRV_VERSION " unloaded\n");
++ unregister_con_driver(&ts72xx_lcd_con);
++}
++
++MODULE_AUTHOR("Matthieu Crapet <mcrapet@gmail.com>");
++MODULE_DESCRIPTION("TS-72xx lcd console driver");
++MODULE_LICENSE("GPL");
++MODULE_VERSION(DRV_VERSION);
++
++module_init(ts72xx_lcd_init);
++module_exit(ts72xx_lcd_exit);
+--
+1.7.1
+
diff --git a/recipes/linux/linux-2.6.38/ts72xx/0024-ARM-ep93xx-Fix-inverted-RTS-and-DTR-signals.patch b/recipes/linux/linux-2.6.38/ts72xx/0024-ARM-ep93xx-Fix-inverted-RTS-and-DTR-signals.patch
new file mode 100644
index 0000000..cb6e812
--- /dev/null
+++ b/recipes/linux/linux-2.6.38/ts72xx/0024-ARM-ep93xx-Fix-inverted-RTS-and-DTR-signals.patch
@@ -0,0 +1,38 @@
+From f9daae0b2163448360b3a49750e35871fb35237d Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Petr=20=C5=A0tetiar?= <ynezz@true.cz>
+Date: Mon, 14 Mar 2011 20:02:58 +0100
+Subject: [PATCH 24/24] ARM: ep93xx: Fix inverted RTS and DTR signals
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+It was discovered by Roberto Bergo, that RTS/DTR signals are inverted after
+the boot, because it was causing him problems with hardware controlled modem
+connected on ttyAM0. Todd Valentic came with this patch for the issue.
+
+Signed-off-by: Todd Valentic <todd.valentic@sri.com>
+Tested-by: Roberto Bergo <roberto.bergo@robson.it>
+Signed-off-by: Petr Štetiar <ynezz@true.cz>
+---
+ arch/arm/mach-ep93xx/core.c | 4 ++--
+ 1 files changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/arch/arm/mach-ep93xx/core.c b/arch/arm/mach-ep93xx/core.c
+index 8207954..cf1ce32 100644
+--- a/arch/arm/mach-ep93xx/core.c
++++ b/arch/arm/mach-ep93xx/core.c
+@@ -251,9 +251,9 @@ static void ep93xx_uart_set_mctrl(struct amba_device *dev,
+ unsigned int mcr;
+
+ mcr = 0;
+- if (!(mctrl & TIOCM_RTS))
++ if (mctrl & TIOCM_RTS)
+ mcr |= 2;
+- if (!(mctrl & TIOCM_DTR))
++ if (mctrl & TIOCM_DTR)
+ mcr |= 1;
+
+ __raw_writel(mcr, base + EP93XX_UART_MCR_OFFSET);
+--
+1.7.1
+
diff --git a/recipes/linux/linux-2.6.38/ts72xx/defconfig b/recipes/linux/linux-2.6.38/ts72xx/defconfig
new file mode 100644
index 0000000..bc434c6
--- /dev/null
+++ b/recipes/linux/linux-2.6.38/ts72xx/defconfig
@@ -0,0 +1,2214 @@
+#
+# Automatically generated make config: don't edit
+# Linux/arm 2.6.38 Kernel Configuration
+# Wed Mar 16 21:28:58 2011
+#
+CONFIG_ARM=y
+CONFIG_SYS_SUPPORTS_APM_EMULATION=y
+CONFIG_GENERIC_GPIO=y
+CONFIG_ARCH_USES_GETTIMEOFFSET=y
+CONFIG_HAVE_PROC_CPU=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_CPU_IDLE_WAIT=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_NEED_DMA_MAP_STATE=y
+CONFIG_VECTORS_BASE=0xffff0000
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+CONFIG_CONSTRUCTORS=y
+CONFIG_HAVE_IRQ_WORK=y
+
+#
+# General setup
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_LOCK_KERNEL=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+CONFIG_CROSS_COMPILE=""
+CONFIG_LOCALVERSION=""
+# CONFIG_LOCALVERSION_AUTO is not set
+CONFIG_HAVE_KERNEL_GZIP=y
+CONFIG_HAVE_KERNEL_LZMA=y
+CONFIG_HAVE_KERNEL_LZO=y
+CONFIG_KERNEL_GZIP=y
+# CONFIG_KERNEL_LZMA is not set
+# CONFIG_KERNEL_LZO is not set
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+CONFIG_SYSVIPC_SYSCTL=y
+CONFIG_POSIX_MQUEUE=y
+CONFIG_POSIX_MQUEUE_SYSCTL=y
+# CONFIG_BSD_PROCESS_ACCT is not set
+# CONFIG_TASKSTATS is not set
+# CONFIG_AUDIT is not set
+CONFIG_HAVE_GENERIC_HARDIRQS=y
+
+#
+# IRQ subsystem
+#
+CONFIG_GENERIC_HARDIRQS=y
+# CONFIG_GENERIC_HARDIRQS_NO_DEPRECATED is not set
+CONFIG_HAVE_SPARSE_IRQ=y
+# CONFIG_GENERIC_PENDING_IRQ is not set
+# CONFIG_AUTO_IRQ_AFFINITY is not set
+# CONFIG_IRQ_PER_CPU is not set
+# CONFIG_SPARSE_IRQ is not set
+
+#
+# RCU Subsystem
+#
+CONFIG_TREE_PREEMPT_RCU=y
+# CONFIG_TINY_RCU is not set
+# CONFIG_TINY_PREEMPT_RCU is not set
+CONFIG_PREEMPT_RCU=y
+# CONFIG_RCU_TRACE is not set
+CONFIG_RCU_FANOUT=32
+# CONFIG_RCU_FANOUT_EXACT is not set
+# CONFIG_TREE_RCU_TRACE is not set
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_LOG_BUF_SHIFT=16
+# CONFIG_CGROUPS is not set
+CONFIG_NAMESPACES=y
+# CONFIG_UTS_NS is not set
+CONFIG_IPC_NS=y
+# CONFIG_USER_NS is not set
+# CONFIG_PID_NS is not set
+# CONFIG_NET_NS is not set
+# CONFIG_SCHED_AUTOGROUP is not set
+# CONFIG_SYSFS_DEPRECATED is not set
+CONFIG_RELAY=y
+# CONFIG_BLK_DEV_INITRD is not set
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SYSCTL=y
+CONFIG_ANON_INODES=y
+CONFIG_EXPERT=y
+CONFIG_EMBEDDED=y
+CONFIG_UID16=y
+CONFIG_SYSCTL_SYSCALL=y
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+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_HAVE_PERF_EVENTS=y
+CONFIG_PERF_USE_VMALLOC=y
+
+#
+# Kernel Performance Events And Counters
+#
+# CONFIG_PERF_EVENTS is not set
+# CONFIG_PERF_COUNTERS is not set
+CONFIG_VM_EVENT_COUNTERS=y
+# CONFIG_COMPAT_BRK is not set
+CONFIG_SLAB=y
+# CONFIG_SLUB is not set
+# CONFIG_SLOB is not set
+# CONFIG_PROFILING is not set
+CONFIG_HAVE_OPROFILE=y
+# CONFIG_KPROBES is not set
+CONFIG_HAVE_KPROBES=y
+CONFIG_HAVE_KRETPROBES=y
+CONFIG_HAVE_REGS_AND_STACK_ACCESS_API=y
+CONFIG_HAVE_CLK=y
+CONFIG_HAVE_DMA_API_DEBUG=y
+
+#
+# GCOV-based kernel profiling
+#
+CONFIG_HAVE_GENERIC_DMA_COHERENT=y
+CONFIG_SLABINFO=y
+CONFIG_RT_MUTEXES=y
+CONFIG_BASE_SMALL=0
+CONFIG_MODULES=y
+# CONFIG_MODULE_FORCE_LOAD is not set
+CONFIG_MODULE_UNLOAD=y
+CONFIG_MODULE_FORCE_UNLOAD=y
+CONFIG_MODVERSIONS=y
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+CONFIG_BLOCK=y
+CONFIG_LBDAF=y
+CONFIG_BLK_DEV_BSG=y
+# CONFIG_BLK_DEV_INTEGRITY is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_DEADLINE=m
+CONFIG_IOSCHED_CFQ=y
+CONFIG_DEFAULT_CFQ=y
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="cfq"
+# CONFIG_INLINE_SPIN_TRYLOCK is not set
+# CONFIG_INLINE_SPIN_TRYLOCK_BH is not set
+# CONFIG_INLINE_SPIN_LOCK is not set
+# CONFIG_INLINE_SPIN_LOCK_BH is not set
+# CONFIG_INLINE_SPIN_LOCK_IRQ is not set
+# CONFIG_INLINE_SPIN_LOCK_IRQSAVE is not set
+# CONFIG_INLINE_SPIN_UNLOCK is not set
+# CONFIG_INLINE_SPIN_UNLOCK_BH is not set
+# CONFIG_INLINE_SPIN_UNLOCK_IRQ is not set
+# CONFIG_INLINE_SPIN_UNLOCK_IRQRESTORE is not set
+# CONFIG_INLINE_READ_TRYLOCK is not set
+# CONFIG_INLINE_READ_LOCK is not set
+# CONFIG_INLINE_READ_LOCK_BH is not set
+# CONFIG_INLINE_READ_LOCK_IRQ is not set
+# CONFIG_INLINE_READ_LOCK_IRQSAVE is not set
+# CONFIG_INLINE_READ_UNLOCK is not set
+# CONFIG_INLINE_READ_UNLOCK_BH is not set
+# CONFIG_INLINE_READ_UNLOCK_IRQ is not set
+# CONFIG_INLINE_READ_UNLOCK_IRQRESTORE is not set
+# CONFIG_INLINE_WRITE_TRYLOCK is not set
+# CONFIG_INLINE_WRITE_LOCK is not set
+# CONFIG_INLINE_WRITE_LOCK_BH is not set
+# CONFIG_INLINE_WRITE_LOCK_IRQ is not set
+# CONFIG_INLINE_WRITE_LOCK_IRQSAVE is not set
+# CONFIG_INLINE_WRITE_UNLOCK is not set
+# CONFIG_INLINE_WRITE_UNLOCK_BH is not set
+# CONFIG_INLINE_WRITE_UNLOCK_IRQ is not set
+# CONFIG_INLINE_WRITE_UNLOCK_IRQRESTORE is not set
+# CONFIG_MUTEX_SPIN_ON_OWNER is not set
+# CONFIG_FREEZER is not set
+
+#
+# System Type
+#
+CONFIG_MMU=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_VEXPRESS is not set
+# CONFIG_ARCH_AT91 is not set
+# CONFIG_ARCH_BCMRING is not set
+# CONFIG_ARCH_CLPS711X is not set
+# CONFIG_ARCH_CNS3XXX is not set
+# CONFIG_ARCH_GEMINI is not set
+# CONFIG_ARCH_EBSA110 is not set
+CONFIG_ARCH_EP93XX=y
+# CONFIG_ARCH_FOOTBRIDGE is not set
+# CONFIG_ARCH_MXC is not set
+# CONFIG_ARCH_MXS is not set
+# CONFIG_ARCH_STMP3XXX is not set
+# CONFIG_ARCH_NETX is not set
+# CONFIG_ARCH_H720X 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_DOVE is not set
+# CONFIG_ARCH_KIRKWOOD is not set
+# CONFIG_ARCH_LOKI is not set
+# CONFIG_ARCH_LPC32XX is not set
+# CONFIG_ARCH_MV78XX0 is not set
+# CONFIG_ARCH_ORION5X is not set
+# CONFIG_ARCH_MMP is not set
+# CONFIG_ARCH_KS8695 is not set
+# CONFIG_ARCH_NS9XXX is not set
+# CONFIG_ARCH_W90X900 is not set
+# CONFIG_ARCH_NUC93X is not set
+# CONFIG_ARCH_TEGRA is not set
+# CONFIG_ARCH_PNX4008 is not set
+# CONFIG_ARCH_PXA is not set
+# CONFIG_ARCH_MSM is not set
+# CONFIG_ARCH_SHMOBILE is not set
+# CONFIG_ARCH_RPC is not set
+# CONFIG_ARCH_SA1100 is not set
+# CONFIG_ARCH_S3C2410 is not set
+# CONFIG_ARCH_S3C64XX is not set
+# CONFIG_ARCH_S5P64X0 is not set
+# CONFIG_ARCH_S5P6442 is not set
+# CONFIG_ARCH_S5PC100 is not set
+# CONFIG_ARCH_S5PV210 is not set
+# CONFIG_ARCH_S5PV310 is not set
+# CONFIG_ARCH_SHARK is not set
+# CONFIG_ARCH_TCC_926 is not set
+# CONFIG_ARCH_LH7A40X is not set
+# CONFIG_ARCH_U300 is not set
+# CONFIG_ARCH_U8500 is not set
+# CONFIG_ARCH_NOMADIK is not set
+# CONFIG_ARCH_DAVINCI is not set
+# CONFIG_ARCH_OMAP is not set
+# CONFIG_PLAT_SPEAR is not set
+# CONFIG_GPIO_PCA953X is not set
+# CONFIG_KEYBOARD_GPIO_POLLED is not set
+
+#
+# Cirrus EP93xx Implementation Options
+#
+# CONFIG_CRUNCH is not set
+CONFIG_CR1_NFBIT=y
+
+#
+# EP93xx Platforms
+#
+CONFIG_EP93XX_SDCE3_SYNC_PHYS_OFFSET=y
+# CONFIG_EP93XX_SDCE0_PHYS_OFFSET is not set
+# CONFIG_EP93XX_SDCE1_PHYS_OFFSET is not set
+# CONFIG_EP93XX_SDCE2_PHYS_OFFSET is not set
+# CONFIG_EP93XX_SDCE3_ASYNC_PHYS_OFFSET is not set
+# CONFIG_MACH_ADSSPHERE is not set
+# CONFIG_MACH_EDB9301 is not set
+# CONFIG_MACH_EDB9302 is not set
+# CONFIG_MACH_EDB9307 is not set
+# CONFIG_MACH_EDB9312 is not set
+# CONFIG_MACH_EDB9315 is not set
+# CONFIG_MACH_GESBC9312 is not set
+# CONFIG_MACH_MICRO9H is not set
+# CONFIG_MACH_MICRO9L is not set
+CONFIG_MACH_TS72XX=y
+CONFIG_EP93XX_EARLY_UART1=y
+# CONFIG_EP93XX_EARLY_UART2 is not set
+# CONFIG_EP93XX_EARLY_UART3 is not set
+CONFIG_MACH_TS72XX_FORCE_MACHINEID=y
+CONFIG_MACH_TS72XX_SBCINFO=m
+# CONFIG_MACH_TS72XX_GPIO_KEYS is not set
+
+#
+# System MMU
+#
+
+#
+# Processor Type
+#
+CONFIG_CPU_ARM920T=y
+CONFIG_CPU_32v4T=y
+CONFIG_CPU_ABRT_EV4T=y
+CONFIG_CPU_PABRT_LEGACY=y
+CONFIG_CPU_CACHE_V4WT=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
+CONFIG_CPU_USE_DOMAINS=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_ARM_L1_CACHE_SHIFT=5
+CONFIG_ARM_VIC=y
+CONFIG_ARM_VIC_NR=2
+
+#
+# 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_NONE is not set
+# CONFIG_PREEMPT_VOLUNTARY is not set
+CONFIG_PREEMPT=y
+CONFIG_HZ=100
+CONFIG_AEABI=y
+# CONFIG_OABI_COMPAT is not set
+CONFIG_ARCH_HAS_HOLES_MEMORYMODEL=y
+CONFIG_ARCH_SPARSEMEM_ENABLE=y
+CONFIG_ARCH_SPARSEMEM_DEFAULT=y
+CONFIG_ARCH_SELECT_MEMORY_MODEL=y
+# CONFIG_HIGHMEM is not set
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_SPARSEMEM_MANUAL=y
+CONFIG_SPARSEMEM=y
+CONFIG_HAVE_MEMORY_PRESENT=y
+CONFIG_SPARSEMEM_EXTREME=y
+CONFIG_HAVE_MEMBLOCK=y
+CONFIG_SPLIT_PTLOCK_CPUS=999999
+# CONFIG_COMPACTION is not set
+# CONFIG_PHYS_ADDR_T_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=0
+CONFIG_VIRT_TO_BUS=y
+# CONFIG_KSM is not set
+CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
+CONFIG_NEED_PER_CPU_KM=y
+CONFIG_FORCE_MAX_ZONEORDER=11
+CONFIG_ALIGNMENT_TRAP=y
+# CONFIG_UACCESS_WITH_MEMCPY is not set
+# CONFIG_SECCOMP is not set
+# CONFIG_CC_STACKPROTECTOR is not set
+# CONFIG_DEPRECATED_PARAM_STRUCT is not set
+
+#
+# Boot options
+#
+CONFIG_ZBOOT_ROM_TEXT=0
+CONFIG_ZBOOT_ROM_BSS=0
+CONFIG_CMDLINE=" debug"
+# CONFIG_CMDLINE_FORCE is not set
+# CONFIG_XIP_KERNEL is not set
+CONFIG_KEXEC=y
+CONFIG_ATAGS_PROC=y
+# CONFIG_CRASH_DUMP is not set
+# CONFIG_AUTO_ZRELADDR is not set
+
+#
+# CPU Power Management
+#
+# CONFIG_CPU_IDLE is not set
+
+#
+# Floating point emulation
+#
+
+#
+# At least one emulation must be selected
+#
+
+#
+# Userspace binary formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+CONFIG_HAVE_AOUT=y
+# CONFIG_BINFMT_AOUT is not set
+CONFIG_BINFMT_MISC=m
+
+#
+# Power management options
+#
+# CONFIG_PM is not set
+CONFIG_ARCH_SUSPEND_POSSIBLE=y
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+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=m
+# CONFIG_NET_KEY_MIGRATE is not set
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+CONFIG_IP_ADVANCED_ROUTER=y
+CONFIG_ASK_IP_FIB_HASH=y
+# CONFIG_IP_FIB_TRIE is not set
+CONFIG_IP_FIB_HASH=y
+# CONFIG_IP_MULTIPLE_TABLES is not set
+# CONFIG_IP_ROUTE_MULTIPATH is not set
+CONFIG_IP_ROUTE_VERBOSE=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+# CONFIG_IP_PNP_BOOTP is not set
+# CONFIG_IP_PNP_RARP is not set
+CONFIG_NET_IPIP=m
+# CONFIG_NET_IPGRE_DEMUX is not set
+# CONFIG_ARPD is not set
+CONFIG_SYN_COOKIES=y
+CONFIG_INET_AH=m
+CONFIG_INET_ESP=m
+CONFIG_INET_IPCOMP=m
+CONFIG_INET_XFRM_TUNNEL=m
+CONFIG_INET_TUNNEL=m
+CONFIG_INET_XFRM_MODE_TRANSPORT=m
+CONFIG_INET_XFRM_MODE_TUNNEL=m
+CONFIG_INET_XFRM_MODE_BEET=m
+# CONFIG_INET_LRO is not set
+# CONFIG_INET_DIAG is not set
+# 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 is not set
+CONFIG_IPV6_SIT=m
+# CONFIG_IPV6_SIT_6RD is not set
+CONFIG_IPV6_NDISC_NODETYPE=y
+CONFIG_IPV6_TUNNEL=m
+# CONFIG_IPV6_MULTIPLE_TABLES is not set
+# CONFIG_IPV6_MROUTE is not set
+# CONFIG_NETLABEL is not set
+CONFIG_NETWORK_SECMARK=y
+# CONFIG_NETWORK_PHY_TIMESTAMPING is not set
+CONFIG_NETFILTER=y
+# CONFIG_NETFILTER_DEBUG is not set
+CONFIG_NETFILTER_ADVANCED=y
+
+#
+# Core Netfilter Configuration
+#
+CONFIG_NETFILTER_NETLINK=m
+CONFIG_NETFILTER_NETLINK_QUEUE=m
+CONFIG_NETFILTER_NETLINK_LOG=m
+CONFIG_NF_CONNTRACK=m
+CONFIG_NF_CONNTRACK_MARK=y
+CONFIG_NF_CONNTRACK_SECMARK=y
+CONFIG_NF_CONNTRACK_ZONES=y
+CONFIG_NF_CONNTRACK_EVENTS=y
+CONFIG_NF_CT_PROTO_DCCP=m
+CONFIG_NF_CT_PROTO_GRE=m
+CONFIG_NF_CT_PROTO_SCTP=m
+CONFIG_NF_CT_PROTO_UDPLITE=m
+CONFIG_NF_CONNTRACK_AMANDA=m
+CONFIG_NF_CONNTRACK_FTP=m
+CONFIG_NF_CONNTRACK_H323=m
+CONFIG_NF_CONNTRACK_IRC=m
+CONFIG_NF_CONNTRACK_NETBIOS_NS=m
+CONFIG_NF_CONNTRACK_PPTP=m
+CONFIG_NF_CONNTRACK_SANE=m
+CONFIG_NF_CONNTRACK_SIP=m
+CONFIG_NF_CONNTRACK_TFTP=m
+CONFIG_NF_CT_NETLINK=m
+# CONFIG_NETFILTER_TPROXY is not set
+CONFIG_NETFILTER_XTABLES=m
+
+#
+# Xtables combined modules
+#
+CONFIG_NETFILTER_XT_MARK=m
+CONFIG_NETFILTER_XT_CONNMARK=m
+
+#
+# Xtables targets
+#
+# CONFIG_NETFILTER_XT_TARGET_CHECKSUM is not set
+CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m
+CONFIG_NETFILTER_XT_TARGET_CONNMARK=m
+CONFIG_NETFILTER_XT_TARGET_CONNSECMARK=m
+CONFIG_NETFILTER_XT_TARGET_CT=m
+CONFIG_NETFILTER_XT_TARGET_DSCP=m
+CONFIG_NETFILTER_XT_TARGET_HL=m
+# CONFIG_NETFILTER_XT_TARGET_IDLETIMER is not set
+CONFIG_NETFILTER_XT_TARGET_LED=m
+CONFIG_NETFILTER_XT_TARGET_MARK=m
+CONFIG_NETFILTER_XT_TARGET_NFLOG=m
+CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m
+CONFIG_NETFILTER_XT_TARGET_NOTRACK=m
+CONFIG_NETFILTER_XT_TARGET_RATEEST=m
+# CONFIG_NETFILTER_XT_TARGET_TEE is not set
+CONFIG_NETFILTER_XT_TARGET_TRACE=m
+CONFIG_NETFILTER_XT_TARGET_SECMARK=m
+CONFIG_NETFILTER_XT_TARGET_TCPMSS=m
+CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP=m
+
+#
+# Xtables matches
+#
+CONFIG_NETFILTER_XT_MATCH_CLUSTER=m
+CONFIG_NETFILTER_XT_MATCH_COMMENT=m
+CONFIG_NETFILTER_XT_MATCH_CONNBYTES=m
+CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=m
+CONFIG_NETFILTER_XT_MATCH_CONNMARK=m
+CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m
+# CONFIG_NETFILTER_XT_MATCH_CPU is not set
+CONFIG_NETFILTER_XT_MATCH_DCCP=m
+CONFIG_NETFILTER_XT_MATCH_DSCP=m
+CONFIG_NETFILTER_XT_MATCH_ESP=m
+CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=m
+CONFIG_NETFILTER_XT_MATCH_HELPER=m
+CONFIG_NETFILTER_XT_MATCH_HL=m
+CONFIG_NETFILTER_XT_MATCH_IPRANGE=m
+CONFIG_NETFILTER_XT_MATCH_LENGTH=m
+CONFIG_NETFILTER_XT_MATCH_LIMIT=m
+CONFIG_NETFILTER_XT_MATCH_MAC=m
+CONFIG_NETFILTER_XT_MATCH_MARK=m
+CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m
+CONFIG_NETFILTER_XT_MATCH_OSF=m
+CONFIG_NETFILTER_XT_MATCH_OWNER=m
+CONFIG_NETFILTER_XT_MATCH_POLICY=m
+CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m
+CONFIG_NETFILTER_XT_MATCH_QUOTA=m
+CONFIG_NETFILTER_XT_MATCH_RATEEST=m
+CONFIG_NETFILTER_XT_MATCH_REALM=m
+CONFIG_NETFILTER_XT_MATCH_RECENT=m
+CONFIG_NETFILTER_XT_MATCH_SCTP=m
+CONFIG_NETFILTER_XT_MATCH_STATE=m
+CONFIG_NETFILTER_XT_MATCH_STATISTIC=m
+CONFIG_NETFILTER_XT_MATCH_STRING=m
+CONFIG_NETFILTER_XT_MATCH_TCPMSS=m
+CONFIG_NETFILTER_XT_MATCH_TIME=m
+CONFIG_NETFILTER_XT_MATCH_U32=m
+# CONFIG_IP_VS is not set
+
+#
+# IP: Netfilter Configuration
+#
+CONFIG_NF_DEFRAG_IPV4=m
+CONFIG_NF_CONNTRACK_IPV4=m
+CONFIG_NF_CONNTRACK_PROC_COMPAT=y
+CONFIG_IP_NF_QUEUE=m
+CONFIG_IP_NF_IPTABLES=m
+CONFIG_IP_NF_MATCH_ADDRTYPE=m
+CONFIG_IP_NF_MATCH_AH=m
+CONFIG_IP_NF_MATCH_ECN=m
+CONFIG_IP_NF_MATCH_TTL=m
+CONFIG_IP_NF_FILTER=m
+CONFIG_IP_NF_TARGET_REJECT=m
+CONFIG_IP_NF_TARGET_LOG=m
+CONFIG_IP_NF_TARGET_ULOG=m
+CONFIG_NF_NAT=m
+CONFIG_NF_NAT_NEEDED=y
+CONFIG_IP_NF_TARGET_MASQUERADE=m
+CONFIG_IP_NF_TARGET_NETMAP=m
+CONFIG_IP_NF_TARGET_REDIRECT=m
+CONFIG_NF_NAT_SNMP_BASIC=m
+CONFIG_NF_NAT_PROTO_DCCP=m
+CONFIG_NF_NAT_PROTO_GRE=m
+CONFIG_NF_NAT_PROTO_UDPLITE=m
+CONFIG_NF_NAT_PROTO_SCTP=m
+CONFIG_NF_NAT_FTP=m
+CONFIG_NF_NAT_IRC=m
+CONFIG_NF_NAT_TFTP=m
+CONFIG_NF_NAT_AMANDA=m
+CONFIG_NF_NAT_PPTP=m
+CONFIG_NF_NAT_H323=m
+CONFIG_NF_NAT_SIP=m
+CONFIG_IP_NF_MANGLE=m
+CONFIG_IP_NF_TARGET_CLUSTERIP=m
+CONFIG_IP_NF_TARGET_ECN=m
+CONFIG_IP_NF_TARGET_TTL=m
+CONFIG_IP_NF_RAW=m
+CONFIG_IP_NF_SECURITY=m
+CONFIG_IP_NF_ARPTABLES=m
+CONFIG_IP_NF_ARPFILTER=m
+CONFIG_IP_NF_ARP_MANGLE=m
+
+#
+# IPv6: Netfilter Configuration
+#
+CONFIG_NF_DEFRAG_IPV6=m
+CONFIG_NF_CONNTRACK_IPV6=m
+CONFIG_IP6_NF_QUEUE=m
+CONFIG_IP6_NF_IPTABLES=m
+CONFIG_IP6_NF_MATCH_AH=m
+CONFIG_IP6_NF_MATCH_EUI64=m
+CONFIG_IP6_NF_MATCH_FRAG=m
+CONFIG_IP6_NF_MATCH_OPTS=m
+CONFIG_IP6_NF_MATCH_HL=m
+CONFIG_IP6_NF_MATCH_IPV6HEADER=m
+CONFIG_IP6_NF_MATCH_MH=m
+CONFIG_IP6_NF_MATCH_RT=m
+CONFIG_IP6_NF_TARGET_HL=m
+CONFIG_IP6_NF_TARGET_LOG=m
+CONFIG_IP6_NF_FILTER=m
+CONFIG_IP6_NF_TARGET_REJECT=m
+CONFIG_IP6_NF_MANGLE=m
+CONFIG_IP6_NF_RAW=m
+CONFIG_IP6_NF_SECURITY=m
+# CONFIG_IP_DCCP is not set
+# CONFIG_IP_SCTP is not set
+# CONFIG_RDS is not set
+# CONFIG_TIPC is not set
+# CONFIG_ATM is not set
+# CONFIG_L2TP 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 is not set
+# CONFIG_PHONET is not set
+# CONFIG_IEEE802154 is not set
+# CONFIG_NET_SCHED is not set
+CONFIG_NET_CLS_ROUTE=y
+# CONFIG_DCB is not set
+CONFIG_DNS_RESOLVER=y
+# CONFIG_BATMAN_ADV 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_WIRELESS=y
+CONFIG_WIRELESS_EXT=y
+CONFIG_WEXT_CORE=y
+CONFIG_WEXT_PROC=y
+CONFIG_WEXT_SPY=y
+CONFIG_WEXT_PRIV=y
+CONFIG_CFG80211=m
+# CONFIG_NL80211_TESTMODE is not set
+# CONFIG_CFG80211_DEVELOPER_WARNINGS is not set
+# CONFIG_CFG80211_REG_DEBUG is not set
+CONFIG_CFG80211_DEFAULT_PS=y
+# CONFIG_CFG80211_INTERNAL_REGDB is not set
+CONFIG_CFG80211_WEXT=y
+CONFIG_WIRELESS_EXT_SYSFS=y
+CONFIG_LIB80211=m
+CONFIG_LIB80211_CRYPT_WEP=m
+CONFIG_LIB80211_CRYPT_CCMP=m
+CONFIG_LIB80211_CRYPT_TKIP=m
+# CONFIG_LIB80211_DEBUG is not set
+CONFIG_MAC80211=m
+CONFIG_MAC80211_HAS_RC=y
+CONFIG_MAC80211_RC_PID=y
+# CONFIG_MAC80211_RC_MINSTREL is not set
+CONFIG_MAC80211_RC_DEFAULT_PID=y
+CONFIG_MAC80211_RC_DEFAULT="pid"
+# CONFIG_MAC80211_MESH is not set
+CONFIG_MAC80211_LEDS=y
+# CONFIG_MAC80211_DEBUG_MENU is not set
+# CONFIG_WIMAX is not set
+# CONFIG_RFKILL is not set
+# CONFIG_NET_9P is not set
+# CONFIG_CAIF is not set
+# CONFIG_CEPH_LIB is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_UEVENT_HELPER_PATH=""
+CONFIG_DEVTMPFS=y
+CONFIG_DEVTMPFS_MOUNT=y
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+CONFIG_FW_LOADER=m
+CONFIG_FIRMWARE_IN_KERNEL=y
+CONFIG_EXTRA_FIRMWARE=""
+# CONFIG_SYS_HYPERVISOR is not set
+CONFIG_CONNECTOR=m
+CONFIG_MTD=y
+# CONFIG_MTD_DEBUG is not set
+# CONFIG_MTD_TESTS is not set
+# CONFIG_MTD_CONCAT is not set
+CONFIG_MTD_PARTITIONS=y
+CONFIG_MTD_REDBOOT_PARTS=y
+CONFIG_MTD_REDBOOT_DIRECTORY_BLOCK=-1
+# CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED is not set
+# CONFIG_MTD_REDBOOT_PARTS_READONLY 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_SM_FTL 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 is not set
+# CONFIG_MTD_M25P80 is not set
+# CONFIG_MTD_SST25L is not set
+# 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_ECC=y
+# CONFIG_MTD_NAND_ECC_SMC is not set
+CONFIG_MTD_NAND=y
+# CONFIG_MTD_NAND_VERIFY_WRITE is not set
+# CONFIG_MTD_SM_COMMON is not set
+# CONFIG_MTD_NAND_MUSEUM_IDS is not set
+# 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=y
+# CONFIG_MTD_ALAUDA is not set
+# CONFIG_MTD_ONENAND is not set
+
+#
+# LPDDR flash memory drivers
+#
+# CONFIG_MTD_LPDDR is not set
+CONFIG_MTD_UBI=y
+CONFIG_MTD_UBI_WL_THRESHOLD=4096
+CONFIG_MTD_UBI_BEB_RESERVE=1
+# CONFIG_MTD_UBI_GLUEBI is not set
+
+#
+# UBI debugging options
+#
+# CONFIG_MTD_UBI_DEBUG 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=m
+# CONFIG_BLK_DEV_DRBD is not set
+CONFIG_BLK_DEV_NBD=m
+# CONFIG_BLK_DEV_UB is not set
+CONFIG_BLK_DEV_RAM=m
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=65536
+# CONFIG_BLK_DEV_XIP is not set
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
+# CONFIG_MG_DISK is not set
+# CONFIG_BLK_DEV_RBD is not set
+CONFIG_BLK_DEV_TS72XX_SDCARD=y
+CONFIG_MISC_DEVICES=y
+# CONFIG_AD525X_DPOT is not set
+# CONFIG_ICS932S401 is not set
+# CONFIG_ENCLOSURE_SERVICES is not set
+# CONFIG_APDS9802ALS is not set
+# CONFIG_ISL29003 is not set
+# CONFIG_ISL29020 is not set
+# CONFIG_SENSORS_TSL2550 is not set
+# CONFIG_SENSORS_BH1780 is not set
+# CONFIG_SENSORS_BH1770 is not set
+# CONFIG_SENSORS_APDS990X is not set
+# CONFIG_HMC6352 is not set
+CONFIG_EP93XX_PWM=m
+# CONFIG_DS1682 is not set
+# CONFIG_TI_DAC7512 is not set
+# CONFIG_BMP085 is not set
+# CONFIG_C2PORT is not set
+
+#
+# EEPROM support
+#
+# CONFIG_EEPROM_AT24 is not set
+# CONFIG_EEPROM_AT25 is not set
+# CONFIG_EEPROM_LEGACY is not set
+# CONFIG_EEPROM_MAX6875 is not set
+CONFIG_EEPROM_93CX6=m
+# CONFIG_IWMC3200TOP is not set
+
+#
+# Texas Instruments shared transport line discipline
+#
+CONFIG_TS72XX_MAX197=m
+CONFIG_TS72XX_MAX197_AVERAGE=y
+CONFIG_HAVE_IDE=y
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+CONFIG_SCSI_MOD=m
+# CONFIG_RAID_ATTRS is not set
+CONFIG_SCSI=m
+CONFIG_SCSI_DMA=y
+CONFIG_SCSI_TGT=m
+# CONFIG_SCSI_NETLINK is not set
+CONFIG_SCSI_PROC_FS=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=m
+# 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=m
+# CONFIG_CHR_DEV_SCH is not set
+# CONFIG_SCSI_MULTI_LUN is not set
+# CONFIG_SCSI_CONSTANTS is not set
+# CONFIG_SCSI_LOGGING is not set
+# CONFIG_SCSI_SCAN_ASYNC is not set
+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 is not set
+# CONFIG_SCSI_SAS_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_SCSI_OSD_INITIATOR is not set
+CONFIG_ATA=m
+# CONFIG_ATA_NONSTANDARD is not set
+# CONFIG_ATA_VERBOSE_ERROR is not set
+# CONFIG_SATA_PMP is not set
+
+#
+# Controllers with non-SFF native interface
+#
+# CONFIG_SATA_AHCI_PLATFORM is not set
+CONFIG_ATA_SFF=y
+
+#
+# SFF controllers with custom DMA interface
+#
+CONFIG_ATA_BMDMA=y
+
+#
+# SATA SFF controllers with BMDMA
+#
+# CONFIG_SATA_MV is not set
+
+#
+# PATA SFF controllers with BMDMA
+#
+
+#
+# PIO-only SFF controllers
+#
+# CONFIG_PATA_PLATFORM is not set
+
+#
+# Generic fallback / legacy drivers
+#
+CONFIG_PATA_TS72XX=y
+CONFIG_PATA_TS7200_CF=m
+CONFIG_PATA_TS9600=m
+# CONFIG_MD is not set
+# CONFIG_TARGET_CORE 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_MII=y
+CONFIG_PHYLIB=y
+
+#
+# MII PHY device drivers
+#
+# CONFIG_MARVELL_PHY is not set
+# CONFIG_DAVICOM_PHY is not set
+# CONFIG_QSEMI_PHY is not set
+# CONFIG_LXT_PHY is not set
+# CONFIG_CICADA_PHY is not set
+# CONFIG_VITESSE_PHY is not set
+# CONFIG_SMSC_PHY is not set
+# CONFIG_BROADCOM_PHY is not set
+# CONFIG_BCM63XX_PHY is not set
+# CONFIG_ICPLUS_PHY is not set
+# CONFIG_REALTEK_PHY is not set
+# CONFIG_NATIONAL_PHY is not set
+# CONFIG_STE10XP is not set
+# CONFIG_LSI_ET1011C_PHY is not set
+# CONFIG_MICREL_PHY is not set
+# CONFIG_FIXED_PHY is not set
+# CONFIG_MDIO_BITBANG is not set
+CONFIG_NET_ETHERNET=y
+CONFIG_EP93XX_ETH=y
+CONFIG_AX88796=m
+CONFIG_AX88796_93CX6=y
+CONFIG_AX88796_TS_ETH100=m
+# CONFIG_SMC91X is not set
+# CONFIG_DM9000 is not set
+# CONFIG_ENC28J60 is not set
+CONFIG_ETHOC=m
+# CONFIG_SMC911X is not set
+# CONFIG_SMSC911X is not set
+# CONFIG_DNET is not set
+# CONFIG_IBM_NEW_EMAC_ZMII is not set
+# CONFIG_IBM_NEW_EMAC_RGMII is not set
+# CONFIG_IBM_NEW_EMAC_TAH is not set
+# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
+# CONFIG_IBM_NEW_EMAC_NO_FLOW_CTRL is not set
+# CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set
+# CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
+# CONFIG_B44 is not set
+# CONFIG_KS8851 is not set
+# CONFIG_KS8851_MLL is not set
+# CONFIG_NETDEV_1000 is not set
+# CONFIG_NETDEV_10000 is not set
+CONFIG_WLAN=y
+CONFIG_LIBERTAS_THINFIRM=m
+# CONFIG_LIBERTAS_THINFIRM_DEBUG is not set
+CONFIG_LIBERTAS_THINFIRM_USB=m
+CONFIG_AT76C50X_USB=m
+CONFIG_USB_ZD1201=m
+CONFIG_USB_NET_RNDIS_WLAN=m
+CONFIG_RTL8187=m
+CONFIG_RTL8187_LEDS=y
+CONFIG_MAC80211_HWSIM=m
+CONFIG_ATH_COMMON=m
+# CONFIG_ATH_DEBUG is not set
+CONFIG_ATH9K_HW=m
+CONFIG_ATH9K_COMMON=m
+CONFIG_ATH9K_HTC=m
+CONFIG_AR9170_USB=m
+CONFIG_AR9170_LEDS=y
+# CONFIG_CARL9170 is not set
+CONFIG_B43=m
+# CONFIG_B43_SDIO is not set
+CONFIG_B43_PIO=y
+# CONFIG_B43_PHY_N is not set
+CONFIG_B43_PHY_LP=y
+CONFIG_B43_LEDS=y
+CONFIG_B43_HWRNG=y
+# CONFIG_B43_DEBUG is not set
+CONFIG_B43LEGACY=m
+CONFIG_B43LEGACY_LEDS=y
+CONFIG_B43LEGACY_HWRNG=y
+CONFIG_B43LEGACY_DEBUG=y
+CONFIG_B43LEGACY_DMA=y
+CONFIG_B43LEGACY_PIO=y
+CONFIG_B43LEGACY_DMA_AND_PIO_MODE=y
+# CONFIG_B43LEGACY_DMA_MODE is not set
+# CONFIG_B43LEGACY_PIO_MODE is not set
+CONFIG_HOSTAP=m
+# CONFIG_HOSTAP_FIRMWARE is not set
+# CONFIG_IWM is not set
+CONFIG_LIBERTAS=m
+CONFIG_LIBERTAS_USB=m
+# CONFIG_LIBERTAS_SDIO is not set
+# CONFIG_LIBERTAS_SPI is not set
+# CONFIG_LIBERTAS_DEBUG is not set
+# CONFIG_LIBERTAS_MESH is not set
+CONFIG_P54_COMMON=m
+CONFIG_P54_USB=m
+# CONFIG_P54_SPI is not set
+CONFIG_P54_LEDS=y
+CONFIG_RT2X00=m
+CONFIG_RT2500USB=m
+CONFIG_RT73USB=m
+CONFIG_RT2800USB=m
+# CONFIG_RT2800USB_RT33XX is not set
+# CONFIG_RT2800USB_RT35XX is not set
+# CONFIG_RT2800USB_UNKNOWN is not set
+CONFIG_RT2800_LIB=m
+CONFIG_RT2X00_LIB_USB=m
+CONFIG_RT2X00_LIB=m
+CONFIG_RT2X00_LIB_HT=y
+CONFIG_RT2X00_LIB_FIRMWARE=y
+CONFIG_RT2X00_LIB_CRYPTO=y
+CONFIG_RT2X00_LIB_LEDS=y
+# CONFIG_RT2X00_DEBUG is not set
+# CONFIG_RTL8192CE is not set
+# CONFIG_WL1251 is not set
+# CONFIG_WL12XX_MENU is not set
+CONFIG_ZD1211RW=m
+# CONFIG_ZD1211RW_DEBUG is not set
+
+#
+# Enable WiMAX (Networking options) to see the WiMAX drivers
+#
+
+#
+# USB Network Adapters
+#
+CONFIG_USB_CATC=m
+CONFIG_USB_KAWETH=m
+CONFIG_USB_PEGASUS=m
+CONFIG_USB_RTL8150=m
+CONFIG_USB_USBNET=m
+CONFIG_USB_NET_AX8817X=m
+CONFIG_USB_NET_CDCETHER=m
+CONFIG_USB_NET_CDC_EEM=m
+CONFIG_USB_NET_CDC_NCM=m
+CONFIG_USB_NET_DM9601=m
+CONFIG_USB_NET_SMSC75XX=m
+CONFIG_USB_NET_SMSC95XX=m
+CONFIG_USB_NET_GL620A=m
+CONFIG_USB_NET_NET1080=m
+CONFIG_USB_NET_PLUSB=m
+CONFIG_USB_NET_MCS7830=m
+CONFIG_USB_NET_RNDIS_HOST=m
+CONFIG_USB_NET_CDC_SUBSET=m
+CONFIG_USB_ALI_M5632=y
+CONFIG_USB_AN2720=y
+CONFIG_USB_BELKIN=y
+CONFIG_USB_ARMLINUX=y
+CONFIG_USB_EPSON2888=y
+CONFIG_USB_KC2190=y
+CONFIG_USB_NET_ZAURUS=m
+# CONFIG_USB_NET_CX82310_ETH is not set
+CONFIG_USB_NET_INT51X1=m
+CONFIG_USB_IPHETH=m
+CONFIG_USB_SIERRA_NET=m
+# CONFIG_WAN is not set
+
+#
+# CAIF transport drivers
+#
+CONFIG_PPP=m
+CONFIG_PPP_MULTILINK=y
+CONFIG_PPP_FILTER=y
+CONFIG_PPP_ASYNC=m
+CONFIG_PPP_SYNC_TTY=m
+CONFIG_PPP_DEFLATE=m
+CONFIG_PPP_BSDCOMP=m
+CONFIG_PPP_MPPE=m
+CONFIG_PPPOE=m
+# CONFIG_SLIP is not set
+CONFIG_SLHC=m
+# CONFIG_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+# CONFIG_ISDN is not set
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+CONFIG_INPUT_FF_MEMLESS=m
+CONFIG_INPUT_POLLDEV=m
+# CONFIG_INPUT_SPARSEKMAP is not set
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=m
+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=m
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+CONFIG_INPUT_KEYBOARD=y
+# CONFIG_KEYBOARD_ADP5588 is not set
+CONFIG_KEYBOARD_ATKBD=y
+# CONFIG_KEYBOARD_QT2160 is not set
+# CONFIG_KEYBOARD_LKKBD is not set
+CONFIG_KEYBOARD_EP93XX=m
+CONFIG_KEYBOARD_GPIO=m
+# CONFIG_KEYBOARD_TCA6416 is not set
+CONFIG_KEYBOARD_MATRIX=m
+CONFIG_TS72XX_DIO_3X4_KEYPAD=m
+CONFIG_TS72XX_DIO_4X4_KEYPAD=m
+# CONFIG_KEYBOARD_LM8323 is not set
+# CONFIG_KEYBOARD_MAX7359 is not set
+# CONFIG_KEYBOARD_MCS is not set
+# CONFIG_KEYBOARD_NEWTON is not set
+# CONFIG_KEYBOARD_OPENCORES is not set
+# CONFIG_KEYBOARD_STOWAWAY is not set
+# CONFIG_KEYBOARD_SUNKBD is not set
+# CONFIG_KEYBOARD_XTKBD is not set
+CONFIG_INPUT_MOUSE=y
+CONFIG_MOUSE_PS2=m
+CONFIG_MOUSE_PS2_ALPS=y
+CONFIG_MOUSE_PS2_LOGIPS2PP=y
+CONFIG_MOUSE_PS2_SYNAPTICS=y
+CONFIG_MOUSE_PS2_TRACKPOINT=y
+# CONFIG_MOUSE_PS2_ELANTECH is not set
+# CONFIG_MOUSE_PS2_SENTELIC is not set
+# CONFIG_MOUSE_PS2_TOUCHKIT is not set
+CONFIG_MOUSE_SERIAL=m
+# 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_MOUSE_SYNAPTICS_I2C is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TABLET is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+CONFIG_INPUT_MISC=y
+# CONFIG_INPUT_AD714X is not set
+# CONFIG_INPUT_ATI_REMOTE is not set
+# CONFIG_INPUT_ATI_REMOTE2 is not set
+# CONFIG_INPUT_KEYSPAN_REMOTE is not set
+# CONFIG_INPUT_POWERMATE is not set
+# CONFIG_INPUT_YEALINK is not set
+# CONFIG_INPUT_CM109 is not set
+CONFIG_INPUT_UINPUT=m
+# CONFIG_INPUT_PCF8574 is not set
+# CONFIG_INPUT_GPIO_ROTARY_ENCODER is not set
+# CONFIG_INPUT_ADXL34X is not set
+# CONFIG_INPUT_CMA3000 is not set
+
+#
+# Hardware I/O ports
+#
+CONFIG_SERIO=y
+# CONFIG_SERIO_SERPORT is not set
+# CONFIG_SERIO_AMBAKMI is not set
+CONFIG_SERIO_LIBPS2=y
+# CONFIG_SERIO_RAW is not set
+# CONFIG_SERIO_ALTERA_PS2 is not set
+# CONFIG_SERIO_PS2MULT 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=y
+# CONFIG_DEVKMEM is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+# CONFIG_N_GSM is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=m
+CONFIG_SERIAL_8250_NR_UARTS=4
+CONFIG_SERIAL_8250_RUNTIME_UARTS=4
+# CONFIG_SERIAL_8250_EXTENDED is not set
+CONFIG_SERIAL_8250_TS_SER1=m
+CONFIG_SERIAL_8250_TS_SER1_IRQ=5
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_AMBA_PL010=y
+CONFIG_SERIAL_AMBA_PL010_TS72XX=y
+CONFIG_SERIAL_AMBA_PL010_CONSOLE=y
+# CONFIG_SERIAL_AMBA_PL011 is not set
+# CONFIG_SERIAL_MAX3100 is not set
+# CONFIG_SERIAL_MAX3107 is not set
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+# CONFIG_SERIAL_TIMBERDALE is not set
+# CONFIG_SERIAL_ALTERA_JTAGUART is not set
+# CONFIG_SERIAL_ALTERA_UART is not set
+# CONFIG_SERIAL_IFX6X60 is not set
+CONFIG_UNIX98_PTYS=y
+# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
+# CONFIG_LEGACY_PTYS is not set
+# CONFIG_TTY_PRINTK is not set
+# CONFIG_HVC_DCC is not set
+# CONFIG_IPMI_HANDLER is not set
+CONFIG_HW_RANDOM=m
+# CONFIG_HW_RANDOM_TIMERIOMEM is not set
+# CONFIG_R3964 is not set
+# CONFIG_RAW_DRIVER is not set
+# CONFIG_TCG_TPM is not set
+# CONFIG_RAMOOPS is not set
+CONFIG_I2C=m
+CONFIG_I2C_BOARDINFO=y
+CONFIG_I2C_COMPAT=y
+# CONFIG_I2C_CHARDEV is not set
+# CONFIG_I2C_MUX is not set
+CONFIG_I2C_HELPER_AUTO=y
+CONFIG_I2C_ALGOBIT=m
+
+#
+# I2C Hardware Bus support
+#
+
+#
+# I2C system bus drivers (mostly embedded / system-on-chip)
+#
+# CONFIG_I2C_DESIGNWARE is not set
+CONFIG_I2C_GPIO=m
+# CONFIG_I2C_OCORES is not set
+# CONFIG_I2C_PCA_PLATFORM is not set
+# CONFIG_I2C_SIMTEC is not set
+# CONFIG_I2C_XILINX 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_STUB 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_SPI=y
+CONFIG_SPI_MASTER=y
+
+#
+# SPI Master Controller Drivers
+#
+CONFIG_SPI_BITBANG=m
+# CONFIG_SPI_EP93XX is not set
+CONFIG_SPI_GPIO=m
+# CONFIG_SPI_PL022 is not set
+# CONFIG_SPI_PXA2XX_PCI is not set
+# CONFIG_SPI_XILINX is not set
+# CONFIG_SPI_DESIGNWARE is not set
+
+#
+# SPI Protocol Masters
+#
+CONFIG_SPI_SPIDEV=m
+# CONFIG_SPI_TLE62X0 is not set
+# CONFIG_SPI_TMP124 is not set
+
+#
+# PPS support
+#
+# CONFIG_PPS is not set
+
+#
+# PPS generators support
+#
+CONFIG_ARCH_REQUIRE_GPIOLIB=y
+CONFIG_GPIOLIB=y
+CONFIG_GPIO_SYSFS=y
+
+#
+# Memory mapped GPIO expanders:
+#
+# CONFIG_GPIO_BASIC_MMIO is not set
+# CONFIG_GPIO_IT8761E is not set
+# CONFIG_GPIO_PL061 is not set
+
+#
+# I2C GPIO expanders:
+#
+# CONFIG_GPIO_MAX7300 is not set
+# CONFIG_GPIO_MAX732X is not set
+# CONFIG_GPIO_PCF857X is not set
+# CONFIG_GPIO_ADP5588 is not set
+
+#
+# PCI GPIO expanders:
+#
+
+#
+# SPI GPIO expanders:
+#
+# CONFIG_GPIO_MAX7301 is not set
+# CONFIG_GPIO_MCP23S08 is not set
+# CONFIG_GPIO_MC33880 is not set
+# CONFIG_GPIO_74X164 is not set
+
+#
+# AC97 GPIO expanders:
+#
+
+#
+# MODULbus GPIO expanders:
+#
+# CONFIG_W1 is not set
+# CONFIG_POWER_SUPPLY is not set
+# CONFIG_HWMON is not set
+# CONFIG_THERMAL is not set
+CONFIG_WATCHDOG=y
+# CONFIG_WATCHDOG_NOWAYOUT is not set
+
+#
+# Watchdog Device Drivers
+#
+# CONFIG_SOFT_WATCHDOG is not set
+# CONFIG_ARM_SP805_WATCHDOG is not set
+CONFIG_EP93XX_WATCHDOG=m
+CONFIG_TS72XX_WATCHDOG=y
+# CONFIG_MAX63XX_WATCHDOG is not set
+
+#
+# USB-based Watchdog Cards
+#
+# CONFIG_USBPCWATCHDOG is not set
+CONFIG_SSB_POSSIBLE=y
+
+#
+# Sonics Silicon Backplane
+#
+CONFIG_SSB=m
+CONFIG_SSB_BLOCKIO=y
+CONFIG_SSB_SDIOHOST_POSSIBLE=y
+# CONFIG_SSB_SDIOHOST is not set
+# CONFIG_SSB_SILENT is not set
+# CONFIG_SSB_DEBUG is not set
+CONFIG_MFD_SUPPORT=y
+# 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_TPS65010 is not set
+# CONFIG_TPS6507X is not set
+# CONFIG_MFD_TMIO is not set
+# CONFIG_MFD_T7L66XB is not set
+# CONFIG_MFD_TC6387XB is not set
+# CONFIG_MFD_TC6393XB is not set
+# CONFIG_MFD_WM8400 is not set
+# CONFIG_MFD_WM831X_SPI is not set
+# CONFIG_MFD_PCF50633 is not set
+# CONFIG_MFD_MC13XXX is not set
+# CONFIG_ABX500_CORE is not set
+# CONFIG_EZX_PCAP is not set
+# CONFIG_MFD_WL1273_CORE is not set
+# CONFIG_REGULATOR is not set
+# CONFIG_MEDIA_SUPPORT is not set
+
+#
+# Graphics support
+#
+# CONFIG_DRM is not set
+# 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_DUMMY_CONSOLE=y
+# CONFIG_TS72XX_CONSOLE is not set
+# CONFIG_SOUND is not set
+CONFIG_HID_SUPPORT=y
+CONFIG_HID=y
+# CONFIG_HIDRAW is not set
+
+#
+# USB Input Devices
+#
+CONFIG_USB_HID=m
+# CONFIG_HID_PID is not set
+# CONFIG_USB_HIDDEV is not set
+
+#
+# USB HID Boot Protocol drivers
+#
+# CONFIG_USB_KBD is not set
+# CONFIG_USB_MOUSE is not set
+
+#
+# Special HID drivers
+#
+# CONFIG_HID_3M_PCT is not set
+# CONFIG_HID_A4TECH is not set
+# CONFIG_HID_ACRUX_FF is not set
+# CONFIG_HID_APPLE is not set
+# CONFIG_HID_BELKIN is not set
+# CONFIG_HID_CANDO is not set
+# CONFIG_HID_CHERRY is not set
+# CONFIG_HID_CHICONY is not set
+# CONFIG_HID_CYPRESS is not set
+# CONFIG_HID_DRAGONRISE is not set
+# CONFIG_HID_EMS_FF is not set
+# CONFIG_HID_EGALAX is not set
+# CONFIG_HID_EZKEY is not set
+# CONFIG_HID_KYE is not set
+# CONFIG_HID_UCLOGIC is not set
+# CONFIG_HID_WALTOP is not set
+# CONFIG_HID_GYRATION is not set
+# CONFIG_HID_TWINHAN is not set
+# CONFIG_HID_KENSINGTON is not set
+# CONFIG_HID_LOGITECH is not set
+# CONFIG_HID_MICROSOFT is not set
+# CONFIG_HID_MOSART is not set
+# CONFIG_HID_MONTEREY is not set
+# CONFIG_HID_MULTITOUCH is not set
+# CONFIG_HID_NTRIG is not set
+# CONFIG_HID_ORTEK is not set
+# CONFIG_HID_PANTHERLORD is not set
+# CONFIG_HID_PETALYNX is not set
+# CONFIG_HID_PICOLCD is not set
+# CONFIG_HID_QUANTA is not set
+# CONFIG_HID_ROCCAT is not set
+# CONFIG_HID_ROCCAT_KONE is not set
+# CONFIG_HID_ROCCAT_KONEPLUS is not set
+# CONFIG_HID_ROCCAT_PYRA is not set
+# CONFIG_HID_SAMSUNG is not set
+# CONFIG_HID_SONY is not set
+# CONFIG_HID_STANTUM is not set
+# CONFIG_HID_SUNPLUS is not set
+# CONFIG_HID_GREENASIA is not set
+# CONFIG_HID_SMARTJOYPLUS is not set
+# CONFIG_HID_TOPSEED is not set
+# CONFIG_HID_THRUSTMASTER is not set
+# CONFIG_HID_ZEROPLUS is not set
+# CONFIG_HID_ZYDACRON is not set
+CONFIG_USB_SUPPORT=y
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+# CONFIG_USB_ARCH_HAS_EHCI is not set
+CONFIG_USB=m
+# CONFIG_USB_DEBUG is not set
+CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
+
+#
+# Miscellaneous USB options
+#
+CONFIG_USB_DEVICEFS=y
+CONFIG_USB_DEVICE_CLASS=y
+# CONFIG_USB_DYNAMIC_MINORS is not set
+# CONFIG_USB_OTG_WHITELIST is not set
+# CONFIG_USB_OTG_BLACKLIST_HUB is not set
+CONFIG_USB_MON=m
+# 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_OXU210HP_HCD is not set
+# CONFIG_USB_ISP116X_HCD is not set
+# CONFIG_USB_ISP1760_HCD is not set
+# CONFIG_USB_ISP1362_HCD is not set
+CONFIG_USB_OHCI_HCD=m
+# CONFIG_USB_OHCI_HCD_SSB is not set
+# CONFIG_USB_OHCI_BIG_ENDIAN_DESC is not set
+# CONFIG_USB_OHCI_BIG_ENDIAN_MMIO is not set
+CONFIG_USB_OHCI_LITTLE_ENDIAN=y
+# CONFIG_USB_SL811_HCD is not set
+# CONFIG_USB_R8A66597_HCD is not set
+# CONFIG_USB_HWA_HCD is not set
+# CONFIG_USB_MUSB_HDRC is not set
+
+#
+# USB Device Class drivers
+#
+CONFIG_USB_ACM=m
+# 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 info
+#
+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_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_UAS 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=m
+# CONFIG_USB_EZUSB is not set
+CONFIG_USB_SERIAL_GENERIC=y
+# CONFIG_USB_SERIAL_AIRCABLE is not set
+# CONFIG_USB_SERIAL_ARK3116 is not set
+# CONFIG_USB_SERIAL_BELKIN is not set
+# CONFIG_USB_SERIAL_CH341 is not set
+# CONFIG_USB_SERIAL_WHITEHEAT is not set
+# CONFIG_USB_SERIAL_DIGI_ACCELEPORT is not set
+# CONFIG_USB_SERIAL_CP210X is not set
+# CONFIG_USB_SERIAL_CYPRESS_M8 is not set
+# CONFIG_USB_SERIAL_EMPEG is not set
+CONFIG_USB_SERIAL_FTDI_SIO=m
+# CONFIG_USB_SERIAL_FUNSOFT is not set
+# CONFIG_USB_SERIAL_VISOR is not set
+# CONFIG_USB_SERIAL_IPAQ is not set
+# CONFIG_USB_SERIAL_IR is not set
+# CONFIG_USB_SERIAL_EDGEPORT is not set
+# CONFIG_USB_SERIAL_EDGEPORT_TI is not set
+# CONFIG_USB_SERIAL_GARMIN is not set
+# CONFIG_USB_SERIAL_IPW is not set
+# CONFIG_USB_SERIAL_IUU is not set
+# CONFIG_USB_SERIAL_KEYSPAN_PDA is not set
+# CONFIG_USB_SERIAL_KEYSPAN is not set
+# CONFIG_USB_SERIAL_KLSI is not set
+# CONFIG_USB_SERIAL_KOBIL_SCT is not set
+# CONFIG_USB_SERIAL_MCT_U232 is not set
+# CONFIG_USB_SERIAL_MOS7720 is not set
+# CONFIG_USB_SERIAL_MOS7840 is not set
+# CONFIG_USB_SERIAL_MOTOROLA is not set
+# CONFIG_USB_SERIAL_NAVMAN is not set
+CONFIG_USB_SERIAL_PL2303=m
+# CONFIG_USB_SERIAL_OTI6858 is not set
+# CONFIG_USB_SERIAL_QCAUX is not set
+# CONFIG_USB_SERIAL_QUALCOMM is not set
+# CONFIG_USB_SERIAL_SPCP8X5 is not set
+# CONFIG_USB_SERIAL_HP4X is not set
+# CONFIG_USB_SERIAL_SAFE is not set
+# CONFIG_USB_SERIAL_SAMBA is not set
+# CONFIG_USB_SERIAL_SIEMENS_MPI is not set
+# CONFIG_USB_SERIAL_SIERRAWIRELESS is not set
+# CONFIG_USB_SERIAL_SYMBOL is not set
+# CONFIG_USB_SERIAL_TI is not set
+# CONFIG_USB_SERIAL_CYBERJACK is not set
+# CONFIG_USB_SERIAL_XIRCOM is not set
+CONFIG_USB_SERIAL_WWAN=m
+CONFIG_USB_SERIAL_OPTION=m
+# CONFIG_USB_SERIAL_OMNINET is not set
+# CONFIG_USB_SERIAL_OPTICON is not set
+# CONFIG_USB_SERIAL_VIVOPAY_SERIAL is not set
+# CONFIG_USB_SERIAL_ZIO is not set
+# CONFIG_USB_SERIAL_SSU100 is not set
+# CONFIG_USB_SERIAL_DEBUG 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_LED is not set
+# CONFIG_USB_CYPRESS_CY7C63 is not set
+# CONFIG_USB_CYTHERM 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_YUREX is not set
+CONFIG_USB_GADGET=m
+# CONFIG_USB_GADGET_DEBUG_FILES is not set
+CONFIG_USB_GADGET_VBUS_DRAW=2
+CONFIG_USB_GADGET_SELECTED=y
+CONFIG_USB_GADGET_R8A66597=y
+CONFIG_USB_R8A66597=m
+# CONFIG_USB_GADGET_PXA_U2O is not set
+# CONFIG_USB_GADGET_M66592 is not set
+# CONFIG_USB_GADGET_DUMMY_HCD is not set
+CONFIG_USB_GADGET_DUALSPEED=y
+# CONFIG_USB_ZERO is not set
+CONFIG_USB_ETH=m
+CONFIG_USB_ETH_RNDIS=y
+CONFIG_USB_ETH_EEM=y
+# CONFIG_USB_G_NCM is not set
+CONFIG_USB_GADGETFS=m
+# CONFIG_USB_FUNCTIONFS is not set
+CONFIG_USB_FILE_STORAGE=m
+# CONFIG_USB_FILE_STORAGE_TEST is not set
+CONFIG_USB_MASS_STORAGE=m
+CONFIG_USB_G_SERIAL=m
+CONFIG_USB_G_PRINTER=m
+CONFIG_USB_CDC_COMPOSITE=m
+CONFIG_USB_G_MULTI=m
+CONFIG_USB_G_MULTI_RNDIS=y
+CONFIG_USB_G_MULTI_CDC=y
+# CONFIG_USB_G_HID is not set
+# CONFIG_USB_G_DBGP is not set
+
+#
+# OTG and related infrastructure
+#
+# CONFIG_USB_GPIO_VBUS is not set
+# CONFIG_USB_ULPI is not set
+# CONFIG_NOP_USB_XCEIV is not set
+CONFIG_MMC=m
+# CONFIG_MMC_DEBUG is not set
+# CONFIG_MMC_UNSAFE_RESUME is not set
+# CONFIG_MMC_CLKGATE is not set
+
+#
+# MMC/SD/SDIO Card Drivers
+#
+CONFIG_MMC_BLOCK=m
+CONFIG_MMC_BLOCK_MINORS=8
+CONFIG_MMC_BLOCK_BOUNCE=y
+CONFIG_SDIO_UART=m
+# CONFIG_MMC_TEST is not set
+
+#
+# MMC/SD/SDIO Host Controller Drivers
+#
+CONFIG_MMC_ARMMMCI=m
+CONFIG_MMC_SDHCI=m
+# CONFIG_MMC_SDHCI_PLTFM is not set
+# CONFIG_MMC_SPI is not set
+# CONFIG_MMC_DW is not set
+# CONFIG_MMC_USHC is not set
+# CONFIG_MEMSTICK is not set
+CONFIG_NEW_LEDS=y
+CONFIG_LEDS_CLASS=y
+
+#
+# LED drivers
+#
+# CONFIG_LEDS_PCA9532 is not set
+CONFIG_LEDS_GPIO=y
+CONFIG_LEDS_GPIO_PLATFORM=y
+# CONFIG_LEDS_LP3944 is not set
+# CONFIG_LEDS_LP5521 is not set
+# CONFIG_LEDS_LP5523 is not set
+# CONFIG_LEDS_PCA955X is not set
+# CONFIG_LEDS_DAC124S085 is not set
+# CONFIG_LEDS_BD2802 is not set
+# CONFIG_LEDS_LT3593 is not set
+CONFIG_LEDS_TRIGGERS=y
+
+#
+# LED Triggers
+#
+CONFIG_LEDS_TRIGGER_TIMER=y
+CONFIG_LEDS_TRIGGER_HEARTBEAT=y
+CONFIG_LEDS_TRIGGER_BACKLIGHT=y
+CONFIG_LEDS_TRIGGER_GPIO=y
+CONFIG_LEDS_TRIGGER_DEFAULT_ON=m
+
+#
+# iptables trigger is under Netfilter config (LED target)
+#
+# CONFIG_NFC_DEVICES is not set
+# CONFIG_ACCESSIBILITY is not set
+CONFIG_RTC_LIB=y
+CONFIG_RTC_CLASS=m
+
+#
+# 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_DS3232 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_ISL12022 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_BQ32K is not set
+# CONFIG_RTC_DRV_S35390A is not set
+# CONFIG_RTC_DRV_FM3130 is not set
+# CONFIG_RTC_DRV_RX8581 is not set
+# CONFIG_RTC_DRV_RX8025 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
+# CONFIG_RTC_DRV_PCF2123 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=m
+# CONFIG_RTC_DRV_M48T35 is not set
+# CONFIG_RTC_DRV_M48T59 is not set
+# CONFIG_RTC_DRV_MSM6242 is not set
+# CONFIG_RTC_DRV_BQ4802 is not set
+# CONFIG_RTC_DRV_RP5C01 is not set
+# CONFIG_RTC_DRV_V3020 is not set
+
+#
+# on-CPU RTC drivers
+#
+CONFIG_RTC_DRV_EP93XX=m
+# CONFIG_RTC_DRV_PL030 is not set
+# CONFIG_RTC_DRV_PL031 is not set
+# CONFIG_DMADEVICES is not set
+# CONFIG_AUXDISPLAY is not set
+CONFIG_UIO=m
+CONFIG_UIO_PDRV=m
+CONFIG_UIO_PDRV_GENIRQ=m
+# CONFIG_STAGING is not set
+CONFIG_CLKDEV_LOOKUP=y
+
+#
+# LCD support
+#
+CONFIG_LCD_LINUX=m
+CONFIG_LCD_HD44780=m
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=m
+# CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT2_FS_XIP is not set
+CONFIG_EXT3_FS=m
+# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
+CONFIG_EXT3_FS_XATTR=y
+# CONFIG_EXT3_FS_POSIX_ACL is not set
+# CONFIG_EXT3_FS_SECURITY is not set
+CONFIG_EXT4_FS=m
+# CONFIG_EXT4_FS_XATTR is not set
+# CONFIG_EXT4_DEBUG is not set
+CONFIG_JBD=m
+CONFIG_JBD2=m
+CONFIG_FS_MBCACHE=m
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_GFS2_FS is not set
+# CONFIG_OCFS2_FS is not set
+# CONFIG_BTRFS_FS is not set
+# CONFIG_NILFS2_FS is not set
+CONFIG_FS_POSIX_ACL=y
+CONFIG_EXPORTFS=m
+CONFIG_FILE_LOCKING=y
+CONFIG_FSNOTIFY=y
+CONFIG_DNOTIFY=y
+CONFIG_INOTIFY_USER=y
+# CONFIG_FANOTIFY is not set
+# CONFIG_QUOTA is not set
+# CONFIG_QUOTACTL is not set
+CONFIG_AUTOFS4_FS=m
+CONFIG_FUSE_FS=m
+# CONFIG_CUSE is not set
+CONFIG_GENERIC_ACL=y
+
+#
+# Caches
+#
+# CONFIG_FSCACHE is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+CONFIG_ISO9660_FS=m
+CONFIG_JOLIET=y
+CONFIG_ZISOFS=y
+CONFIG_UDF_FS=m
+CONFIG_UDF_NLS=y
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=m
+CONFIG_MSDOS_FS=m
+CONFIG_VFAT_FS=m
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
+CONFIG_NTFS_FS=m
+# 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
+CONFIG_MISC_FILESYSTEMS=y
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_ECRYPT_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_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_UBIFS_FS=y
+CONFIG_UBIFS_FS_XATTR=y
+CONFIG_UBIFS_FS_ADVANCED_COMPR=y
+CONFIG_UBIFS_FS_LZO=y
+CONFIG_UBIFS_FS_ZLIB=y
+# CONFIG_UBIFS_FS_DEBUG is not set
+# CONFIG_LOGFS is not set
+# CONFIG_CRAMFS is not set
+CONFIG_SQUASHFS=m
+# CONFIG_SQUASHFS_XATTR is not set
+# CONFIG_SQUASHFS_LZO is not set
+# CONFIG_SQUASHFS_XZ is not set
+# CONFIG_SQUASHFS_EMBEDDED is not set
+CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE=3
+# 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=y
+# CONFIG_NFS_V4_1 is not set
+CONFIG_ROOT_NFS=y
+# CONFIG_NFS_USE_LEGACY_DNS is not set
+CONFIG_NFS_USE_KERNEL_DNS=y
+# CONFIG_NFS_USE_NEW_IDMAPPER is not set
+CONFIG_NFSD=m
+CONFIG_NFSD_DEPRECATED=y
+CONFIG_NFSD_V2_ACL=y
+CONFIG_NFSD_V3=y
+CONFIG_NFSD_V3_ACL=y
+CONFIG_NFSD_V4=y
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+CONFIG_NFS_ACL_SUPPORT=m
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=y
+CONFIG_SUNRPC_GSS=y
+CONFIG_RPCSEC_GSS_KRB5=y
+# CONFIG_CEPH_FS is not set
+CONFIG_CIFS=m
+# CONFIG_CIFS_STATS is not set
+# CONFIG_CIFS_WEAK_PW_HASH is not set
+CONFIG_CIFS_UPCALL=y
+# CONFIG_CIFS_XATTR is not set
+# CONFIG_CIFS_DEBUG2 is not set
+# CONFIG_CIFS_DFS_UPCALL is not set
+# CONFIG_CIFS_EXPERIMENTAL 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="iso8859-1"
+CONFIG_NLS_CODEPAGE_437=m
+CONFIG_NLS_CODEPAGE_737=m
+CONFIG_NLS_CODEPAGE_775=m
+CONFIG_NLS_CODEPAGE_850=m
+CONFIG_NLS_CODEPAGE_852=m
+CONFIG_NLS_CODEPAGE_855=m
+CONFIG_NLS_CODEPAGE_857=m
+CONFIG_NLS_CODEPAGE_860=m
+CONFIG_NLS_CODEPAGE_861=m
+CONFIG_NLS_CODEPAGE_862=m
+CONFIG_NLS_CODEPAGE_863=m
+CONFIG_NLS_CODEPAGE_864=m
+CONFIG_NLS_CODEPAGE_865=m
+CONFIG_NLS_CODEPAGE_866=m
+CONFIG_NLS_CODEPAGE_869=m
+CONFIG_NLS_CODEPAGE_936=m
+CONFIG_NLS_CODEPAGE_950=m
+CONFIG_NLS_CODEPAGE_932=m
+CONFIG_NLS_CODEPAGE_949=m
+CONFIG_NLS_CODEPAGE_874=m
+CONFIG_NLS_ISO8859_8=m
+CONFIG_NLS_CODEPAGE_1250=m
+CONFIG_NLS_CODEPAGE_1251=m
+CONFIG_NLS_ASCII=m
+CONFIG_NLS_ISO8859_1=m
+CONFIG_NLS_ISO8859_2=m
+CONFIG_NLS_ISO8859_3=m
+CONFIG_NLS_ISO8859_4=m
+CONFIG_NLS_ISO8859_5=m
+CONFIG_NLS_ISO8859_6=m
+CONFIG_NLS_ISO8859_7=m
+CONFIG_NLS_ISO8859_9=m
+CONFIG_NLS_ISO8859_13=m
+CONFIG_NLS_ISO8859_14=m
+CONFIG_NLS_ISO8859_15=m
+CONFIG_NLS_KOI8_R=m
+CONFIG_NLS_KOI8_U=m
+CONFIG_NLS_UTF8=m
+# CONFIG_DLM is not set
+
+#
+# Kernel hacking
+#
+CONFIG_PRINTK_TIME=y
+# CONFIG_ENABLE_WARN_DEPRECATED is not set
+# CONFIG_ENABLE_MUST_CHECK is not set
+CONFIG_FRAME_WARN=2048
+# CONFIG_MAGIC_SYSRQ is not set
+# CONFIG_STRIP_ASM_SYMS is not set
+# 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_HARDLOCKUP_DETECTOR is not set
+CONFIG_BKL=y
+# CONFIG_SPARSE_RCU_POINTER is not set
+CONFIG_DEBUG_BUGVERBOSE=y
+# CONFIG_DEBUG_MEMORY_INIT is not set
+# CONFIG_RCU_CPU_STALL_DETECTOR is not set
+CONFIG_SYSCTL_SYSCALL_CHECK=y
+CONFIG_HAVE_FUNCTION_TRACER=y
+CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y
+CONFIG_HAVE_DYNAMIC_FTRACE=y
+CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
+CONFIG_HAVE_C_RECORDMCOUNT=y
+CONFIG_TRACING_SUPPORT=y
+# CONFIG_FTRACE is not set
+# CONFIG_DMA_API_DEBUG is not set
+# CONFIG_ATOMIC64_SELFTEST is not set
+# CONFIG_SAMPLES is not set
+CONFIG_HAVE_ARCH_KGDB=y
+# CONFIG_STRICT_DEVMEM is not set
+CONFIG_ARM_UNWIND=y
+# CONFIG_DEBUG_USER is not set
+# CONFIG_OC_ETM is not set
+
+#
+# Security options
+#
+CONFIG_KEYS=y
+# CONFIG_KEYS_DEBUG_PROC_KEYS is not set
+# CONFIG_SECURITY_DMESG_RESTRICT is not set
+CONFIG_SECURITY=y
+# CONFIG_SECURITYFS is not set
+CONFIG_SECURITY_NETWORK=y
+# CONFIG_SECURITY_NETWORK_XFRM is not set
+# CONFIG_SECURITY_PATH is not set
+# CONFIG_SECURITY_TOMOYO is not set
+# CONFIG_SECURITY_APPARMOR is not set
+# CONFIG_IMA is not set
+CONFIG_DEFAULT_SECURITY_DAC=y
+CONFIG_DEFAULT_SECURITY=""
+CONFIG_CRYPTO=y
+
+#
+# Crypto core or helper
+#
+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_RNG=m
+CONFIG_CRYPTO_RNG2=y
+CONFIG_CRYPTO_PCOMP=m
+CONFIG_CRYPTO_PCOMP2=y
+CONFIG_CRYPTO_MANAGER=y
+CONFIG_CRYPTO_MANAGER2=y
+CONFIG_CRYPTO_MANAGER_DISABLE_TESTS=y
+CONFIG_CRYPTO_GF128MUL=m
+CONFIG_CRYPTO_NULL=m
+CONFIG_CRYPTO_WORKQUEUE=y
+CONFIG_CRYPTO_CRYPTD=m
+CONFIG_CRYPTO_AUTHENC=m
+CONFIG_CRYPTO_TEST=m
+
+#
+# Authenticated Encryption with Associated Data
+#
+CONFIG_CRYPTO_CCM=m
+CONFIG_CRYPTO_GCM=m
+CONFIG_CRYPTO_SEQIV=m
+
+#
+# Block modes
+#
+CONFIG_CRYPTO_CBC=y
+CONFIG_CRYPTO_CTR=m
+CONFIG_CRYPTO_CTS=m
+CONFIG_CRYPTO_ECB=m
+CONFIG_CRYPTO_LRW=m
+CONFIG_CRYPTO_PCBC=m
+CONFIG_CRYPTO_XTS=m
+
+#
+# Hash modes
+#
+CONFIG_CRYPTO_HMAC=m
+CONFIG_CRYPTO_XCBC=m
+CONFIG_CRYPTO_VMAC=m
+
+#
+# Digest
+#
+CONFIG_CRYPTO_CRC32C=m
+CONFIG_CRYPTO_GHASH=m
+CONFIG_CRYPTO_MD4=m
+CONFIG_CRYPTO_MD5=y
+CONFIG_CRYPTO_MICHAEL_MIC=m
+CONFIG_CRYPTO_RMD128=m
+CONFIG_CRYPTO_RMD160=m
+CONFIG_CRYPTO_RMD256=m
+CONFIG_CRYPTO_RMD320=m
+CONFIG_CRYPTO_SHA1=m
+CONFIG_CRYPTO_SHA256=m
+CONFIG_CRYPTO_SHA512=m
+CONFIG_CRYPTO_TGR192=m
+CONFIG_CRYPTO_WP512=m
+
+#
+# Ciphers
+#
+CONFIG_CRYPTO_AES=m
+CONFIG_CRYPTO_ANUBIS=m
+CONFIG_CRYPTO_ARC4=m
+CONFIG_CRYPTO_BLOWFISH=m
+CONFIG_CRYPTO_CAMELLIA=m
+CONFIG_CRYPTO_CAST5=m
+CONFIG_CRYPTO_CAST6=m
+CONFIG_CRYPTO_DES=y
+CONFIG_CRYPTO_FCRYPT=m
+CONFIG_CRYPTO_KHAZAD=m
+CONFIG_CRYPTO_SALSA20=m
+CONFIG_CRYPTO_SEED=m
+CONFIG_CRYPTO_SERPENT=m
+CONFIG_CRYPTO_TEA=m
+CONFIG_CRYPTO_TWOFISH=m
+CONFIG_CRYPTO_TWOFISH_COMMON=m
+
+#
+# Compression
+#
+CONFIG_CRYPTO_DEFLATE=y
+CONFIG_CRYPTO_ZLIB=m
+CONFIG_CRYPTO_LZO=y
+
+#
+# Random Number Generation
+#
+CONFIG_CRYPTO_ANSI_CPRNG=m
+# CONFIG_CRYPTO_USER_API_HASH is not set
+# CONFIG_CRYPTO_USER_API_SKCIPHER is not set
+# CONFIG_CRYPTO_HW is not set
+# CONFIG_BINARY_PRINTF is not set
+
+#
+# Library routines
+#
+CONFIG_BITREVERSE=y
+CONFIG_GENERIC_FIND_LAST_BIT=y
+CONFIG_CRC_CCITT=m
+CONFIG_CRC16=y
+CONFIG_CRC_T10DIF=m
+CONFIG_CRC_ITU_T=m
+CONFIG_CRC32=y
+CONFIG_CRC7=m
+CONFIG_LIBCRC32C=m
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y
+CONFIG_LZO_COMPRESS=y
+CONFIG_LZO_DECOMPRESS=y
+# CONFIG_XZ_DEC is not set
+# CONFIG_XZ_DEC_BCJ is not set
+CONFIG_TEXTSEARCH=y
+CONFIG_TEXTSEARCH_KMP=m
+CONFIG_TEXTSEARCH_BM=m
+CONFIG_TEXTSEARCH_FSM=m
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
+CONFIG_HAS_DMA=y
+CONFIG_NLATTR=y
+CONFIG_GENERIC_ATOMIC64=y
+CONFIG_AVERAGE=y
diff --git a/recipes/linux/linux_2.6.38.bb b/recipes/linux/linux_2.6.38.bb
index 802ebf3..e102f9c 100644
--- a/recipes/linux/linux_2.6.38.bb
+++ b/recipes/linux/linux_2.6.38.bb
@@ -11,6 +11,7 @@ DEFAULT_PREFERENCE_collie = "1"
DEFAULT_PREFERENCE_poodle = "1"
DEFAULT_PREFERENCE_spitz = "1"
DEFAULT_PREFERENCE_tosa = "1"
+DEFAULT_PREFERENCE_ts72xx = "1"
SRC_URI = "${KERNELORG_MIRROR}/pub/linux/kernel/v2.6/linux-${PV}.tar.bz2;name=kernel \
${KERNELORG_MIRROR}/pub/linux/kernel/v2.6/patch-${PV}.2.bz2;apply=yes;name=stablepatch \
@@ -23,6 +24,31 @@ SRC_URI_append_poodle = " file://${LOGO_SIZE}/logo_linux_clut224.ppm.bz2 "
SRC_URI_append_tosa = " file://${LOGO_SIZE}/logo_linux_clut224.ppm.bz2 "
SRC_URI_append_spitz = " file://${LOGO_SIZE}/logo_linux_clut224.ppm.bz2 "
+SRC_URI_append_ts72xx = " \
+ file://0001-ts72xx_base.patch \
+ file://0002-ts72xx_force_machine-id.patch \
+ file://0003-ep93xx_cpuinfo.patch \
+ file://0004-ep93xx_eth.patch \
+ file://0005-ep93xx-m2m-DMA-support.patch \
+ file://0006-ts72xx_rs485.patch \
+ file://0007-ts72xx_ts_ser1.patch \
+ file://0008-ts72xx_ts_eth100.patch \
+ file://0009-ts72xx_pata.patch \
+ file://0010-ts72xx_gpio_i2c.patch \
+ file://0011-ts72xx_dio_keypad.patch \
+ file://0012-ts72xx_sbcinfo.patch \
+ file://0013-ts72xx_max197.patch \
+ file://0014-ts7200_nor_flash.patch \
+ file://0015-ts72xx_sdcard.patch \
+ file://0016-ts72xx_spi_tmp124.patch \
+ file://0017-ts72xx-use-CPLD-watchdog-for-reset.patch \
+ file://0018-ethoc-ts7300-fixes.patch \
+ file://0019-ts7300-add-ethernet-support.patch \
+ file://0020-ts72xx-add-lcd-linux-driver.patch \
+ file://0021-TS-72XX-LCD-console-driver.patch \
+ file://0024-ARM-ep93xx-Fix-inverted-RTS-and-DTR-signals.patch \
+ "
+
SRC_URI[kernel.md5sum] = "7d471477bfa67546f902da62227fa976"
SRC_URI[kernel.sha256sum] = "72f0cfaefb8dc86b219d5a742dd0375332627641ecbdf5badd3158e2127b9304"
SRC_URI[stablepatch.md5sum] = "599badab31c4920d4122133208c810d7"
--
1.7.1
^ permalink raw reply related [flat|nested] 10+ messages in thread
* Re: [PATCH 5/6] linux-2.6.36: remove ts72xx support because 2.6.38 is now default
2011-04-02 14:18 ` [PATCH 5/6] linux-2.6.36: remove ts72xx support because 2.6.38 is now default Petr Štetiar
@ 2011-04-02 16:08 ` Koen Kooi
2011-04-02 16:31 ` Petr Štetiar
0 siblings, 1 reply; 10+ messages in thread
From: Koen Kooi @ 2011-04-02 16:08 UTC (permalink / raw)
To: openembedded-devel
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1
Is it really necessary to remove it from .36 instead of DP+1;ing .38?
On 02-04-11 16:18, Petr Štetiar wrote:
> Signed-off-by: Petr Štetiar <ynezz@true.cz>
> ---
> .../linux-2.6.36/ts72xx/0001-ts72xx_base.patch | 450 --
> .../ts72xx/0002-ts72xx_force_machine-id.patch | 49 -
> .../linux-2.6.36/ts72xx/0003-ep93xx_cpuinfo.patch | 36 -
> .../linux-2.6.36/ts72xx/0004-ep93xx_eth.patch | 555 ---
> .../ts72xx/0005-ep93xx-m2m-DMA-support.patch | 886 ----
> .../linux-2.6.36/ts72xx/0006-ts72xx_rs485.patch | 223 -
> .../linux-2.6.36/ts72xx/0007-ts72xx_ts_ser1.patch | 264 --
> .../ts72xx/0008-ts72xx_ts_eth100.patch | 278 --
> .../linux-2.6.36/ts72xx/0009-ts72xx_pata.patch | 437 --
> .../linux-2.6.36/ts72xx/0010-ts72xx_gpio_i2c.patch | 63 -
> .../ts72xx/0011-ts72xx_dio_keypad.patch | 311 --
> .../linux-2.6.36/ts72xx/0012-ts72xx_sbcinfo.patch | 267 --
> .../linux-2.6.36/ts72xx/0013-ts72xx_max197.patch | 356 --
> .../ts72xx/0014-ts7200_nor_flash.patch | 181 -
> .../linux-2.6.36/ts72xx/0015-ts72xx_sdcard.patch | 3298 --------------
> .../ts72xx/0016-ts72xx_spi_tmp124.patch | 305 --
> .../0017-ts72xx-use-CPLD-watchdog-for-reset.patch | 53 -
> .../ts72xx/0018-ethoc-ts7300-fixes.patch | 93 -
> .../ts72xx/0019-ts7300-add-ethernet-support.patch | 87 -
> .../ts72xx/0023-ts72xx-add-lcd-linux-driver.patch | 4569 --------------------
> .../ts72xx/0024-ts72xx-add-GPIO-keys.patch | 100 -
> recipes/linux/linux-2.6.36/ts72xx/defconfig | 2127 ---------
> recipes/linux/linux_2.6.36.bb | 25 -
> 23 files changed, 0 insertions(+), 15013 deletions(-)
> delete mode 100644 recipes/linux/linux-2.6.36/ts72xx/0001-ts72xx_base.patch
> delete mode 100644 recipes/linux/linux-2.6.36/ts72xx/0002-ts72xx_force_machine-id.patch
> delete mode 100644 recipes/linux/linux-2.6.36/ts72xx/0003-ep93xx_cpuinfo.patch
> delete mode 100644 recipes/linux/linux-2.6.36/ts72xx/0004-ep93xx_eth.patch
> delete mode 100644 recipes/linux/linux-2.6.36/ts72xx/0005-ep93xx-m2m-DMA-support.patch
> delete mode 100644 recipes/linux/linux-2.6.36/ts72xx/0006-ts72xx_rs485.patch
> delete mode 100644 recipes/linux/linux-2.6.36/ts72xx/0007-ts72xx_ts_ser1.patch
> delete mode 100644 recipes/linux/linux-2.6.36/ts72xx/0008-ts72xx_ts_eth100.patch
> delete mode 100644 recipes/linux/linux-2.6.36/ts72xx/0009-ts72xx_pata.patch
> delete mode 100644 recipes/linux/linux-2.6.36/ts72xx/0010-ts72xx_gpio_i2c.patch
> delete mode 100644 recipes/linux/linux-2.6.36/ts72xx/0011-ts72xx_dio_keypad.patch
> delete mode 100644 recipes/linux/linux-2.6.36/ts72xx/0012-ts72xx_sbcinfo.patch
> delete mode 100644 recipes/linux/linux-2.6.36/ts72xx/0013-ts72xx_max197.patch
> delete mode 100644 recipes/linux/linux-2.6.36/ts72xx/0014-ts7200_nor_flash.patch
> delete mode 100644 recipes/linux/linux-2.6.36/ts72xx/0015-ts72xx_sdcard.patch
> delete mode 100644 recipes/linux/linux-2.6.36/ts72xx/0016-ts72xx_spi_tmp124.patch
> delete mode 100644 recipes/linux/linux-2.6.36/ts72xx/0017-ts72xx-use-CPLD-watchdog-for-reset.patch
> delete mode 100644 recipes/linux/linux-2.6.36/ts72xx/0018-ethoc-ts7300-fixes.patch
> delete mode 100644 recipes/linux/linux-2.6.36/ts72xx/0019-ts7300-add-ethernet-support.patch
> delete mode 100644 recipes/linux/linux-2.6.36/ts72xx/0023-ts72xx-add-lcd-linux-driver.patch
> delete mode 100644 recipes/linux/linux-2.6.36/ts72xx/0024-ts72xx-add-GPIO-keys.patch
> delete mode 100644 recipes/linux/linux-2.6.36/ts72xx/defconfig
>
> diff --git a/recipes/linux/linux-2.6.36/ts72xx/0001-ts72xx_base.patch b/recipes/linux/linux-2.6.36/ts72xx/0001-ts72xx_base.patch
> deleted file mode 100644
> index 3e04afc..0000000
> --- a/recipes/linux/linux-2.6.36/ts72xx/0001-ts72xx_base.patch
> +++ /dev/null
> @@ -1,450 +0,0 @@
> -From f05911e053a51d9a5aa0c8632b442354a7486f45 Mon Sep 17 00:00:00 2001
> -From: Matthieu Crapet <mcrapet@gmail.com>
> -Date: Thu, 10 Jun 2010 10:43:24 +0200
> -Subject: [PATCH 01/24] ts72xx_base
> -MIME-Version: 1.0
> -Content-Type: text/plain; charset=UTF-8
> -Content-Transfer-Encoding: 8bit
> -
> -- patch: allow to force nF bit in control reg
> -- register pwm1
> -
> -Signed-off-by: Petr Štetiar <ynezz@true.cz>
> ----
> - arch/arm/Kconfig | 3 +
> - arch/arm/mach-ep93xx/Kconfig | 9 ++
> - arch/arm/mach-ep93xx/include/mach/ep93xx-regs.h | 7 +
> - arch/arm/mach-ep93xx/include/mach/memory.h | 28 +++++
> - arch/arm/mach-ep93xx/include/mach/ts72xx.h | 145 +++++++++++++++++++++--
> - arch/arm/mach-ep93xx/ts72xx.c | 41 ++++++-
> - arch/arm/mm/proc-arm920.S | 5 +-
> - scripts/Makefile.fwinst | 2 +-
> - 8 files changed, 223 insertions(+), 17 deletions(-)
> -
> -diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
> -index 9c26ba7..8e6c85d 100644
> ---- a/arch/arm/Kconfig
> -+++ b/arch/arm/Kconfig
> -@@ -327,6 +327,9 @@ config ARCH_EP93XX
> - select CPU_ARM920T
> - select ARM_AMBA
> - select ARM_VIC
> -+ select ARCH_SPARSEMEM_ENABLE
> -+ select GENERIC_GPIO
> -+ select HAVE_CLK
> - select COMMON_CLKDEV
> - select ARCH_REQUIRE_GPIOLIB
> - select ARCH_HAS_HOLES_MEMORYMODEL
> -diff --git a/arch/arm/mach-ep93xx/Kconfig b/arch/arm/mach-ep93xx/Kconfig
> -index 3a08b18..b6be37e 100644
> ---- a/arch/arm/mach-ep93xx/Kconfig
> -+++ b/arch/arm/mach-ep93xx/Kconfig
> -@@ -7,6 +7,15 @@ config CRUNCH
> - help
> - Enable kernel support for MaverickCrunch.
> -
> -+config CR1_NFBIT
> -+ bool "Turn on nF bit in ControlRegister 1"
> -+ help
> -+ Say 'Y' here to force the nF bit on. Usually this is set
> -+ by the bootrom. If it is not set, then the CPU core will
> -+ run from HCLK instead of FCLK, and performance will suffer.
> -+ If you see BogoMIPS of about 1/4 of your CPU clock, try
> -+ turning this on; your performance should double.
> -+
> - comment "EP93xx Platforms"
> -
> - choice
> -diff --git a/arch/arm/mach-ep93xx/include/mach/ep93xx-regs.h b/arch/arm/mach-ep93xx/include/mach/ep93xx-regs.h
> -index c54b3e5..db351cc 100644
> ---- a/arch/arm/mach-ep93xx/include/mach/ep93xx-regs.h
> -+++ b/arch/arm/mach-ep93xx/include/mach/ep93xx-regs.h
> -@@ -83,6 +83,7 @@
> -
> - #define EP93XX_BOOT_ROM_BASE EP93XX_AHB_IOMEM(0x00090000)
> -
> -+#define EP93XX_IDE_PHYS_BASE EP93XX_AHB_PHYS(0x000a0000)
> - #define EP93XX_IDE_BASE EP93XX_AHB_IOMEM(0x000a0000)
> -
> - #define EP93XX_VIC1_BASE EP93XX_AHB_IOMEM(0x000b0000)
> -@@ -97,12 +98,17 @@
> - #define EP93XX_I2S_BASE EP93XX_APB_IOMEM(0x00020000)
> -
> - #define EP93XX_SECURITY_BASE EP93XX_APB_IOMEM(0x00030000)
> -+#define EP93XX_SECURITY_REG(x) (EP93XX_SECURITY_BASE + (x))
> -+#define EP93XX_SECURITY_UNIQID EP93XX_SECURITY_REG(0x2440)
> -
> - #define EP93XX_GPIO_BASE EP93XX_APB_IOMEM(0x00040000)
> - #define EP93XX_GPIO_REG(x) (EP93XX_GPIO_BASE + (x))
> - #define EP93XX_GPIO_F_INT_STATUS EP93XX_GPIO_REG(0x5c)
> -+#define EP93XX_GPIO_F_INT_DEBOUNCE EP93XX_GPIO_REG(0x64)
> - #define EP93XX_GPIO_A_INT_STATUS EP93XX_GPIO_REG(0xa0)
> -+#define EP93XX_GPIO_A_INT_DEBOUNCE EP93XX_GPIO_REG(0xa8)
> - #define EP93XX_GPIO_B_INT_STATUS EP93XX_GPIO_REG(0xbc)
> -+#define EP93XX_GPIO_B_INT_DEBOUNCE EP93XX_GPIO_REG(0xc4)
> - #define EP93XX_GPIO_EEDRIVE EP93XX_GPIO_REG(0xc8)
> -
> - #define EP93XX_AAC_BASE EP93XX_APB_IOMEM(0x00080000)
> -@@ -220,6 +226,7 @@
> - #define EP93XX_SYSCON_SYSCFG_LEECLK (1<<3)
> - #define EP93XX_SYSCON_SYSCFG_LCSN2 (1<<1)
> - #define EP93XX_SYSCON_SYSCFG_LCSN1 (1<<0)
> -+#define EP93XX_SYSCON_CHIPID EP93XX_SYSCON_REG(0x94)
> - #define EP93XX_SYSCON_SWLOCK EP93XX_SYSCON_REG(0xc0)
> -
> - #define EP93XX_WATCHDOG_BASE EP93XX_APB_IOMEM(0x00140000)
> -diff --git a/arch/arm/mach-ep93xx/include/mach/memory.h b/arch/arm/mach-ep93xx/include/mach/memory.h
> -index 554064e..78eaacf 100644
> ---- a/arch/arm/mach-ep93xx/include/mach/memory.h
> -+++ b/arch/arm/mach-ep93xx/include/mach/memory.h
> -@@ -19,4 +19,32 @@
> - #error "Kconfig bug: No EP93xx PHYS_OFFSET set"
> - #endif
> -
> -+/*
> -+ * Non-linear mapping like so:
> -+ * phys => virt
> -+ * 0x00000000 => 0xc0000000
> -+ * 0x01000000 => 0xc1000000
> -+ * 0x04000000 => 0xc4000000
> -+ * 0x05000000 => 0xc5000000
> -+ * 0xe0000000 => 0xc8000000
> -+ * 0xe1000000 => 0xc9000000
> -+ * 0xe4000000 => 0xcc000000
> -+ * 0xe5000000 => 0xcd000000
> -+ *
> -+ * As suggested here: http://marc.info/?l=linux-arm&m=122754446724900&w=2
> -+ *
> -+ * Note that static inline functions won't work here because
> -+ * arch/arm/include/asm/memory.h uses "#ifndef __virt_to_phys" to check whether to
> -+ * use generic functions or not.
> -+ */
> -+
> -+#define __phys_to_virt(p) \
> -+ (((p) & 0x07ffffff) | (((p) & 0xe0000000) ? 0x08000000 : 0) | PAGE_OFFSET)
> -+
> -+#define __virt_to_phys(v) \
> -+ (((v) & 0x07ffffff) | (((v) & 0x08000000) ? 0xe0000000 : 0 ))
> -+
> -+#define SECTION_SIZE_BITS 24
> -+#define MAX_PHYSMEM_BITS 32
> -+
> - #endif
> -diff --git a/arch/arm/mach-ep93xx/include/mach/ts72xx.h b/arch/arm/mach-ep93xx/include/mach/ts72xx.h
> -index 0eabec6..1d50dec 100644
> ---- a/arch/arm/mach-ep93xx/include/mach/ts72xx.h
> -+++ b/arch/arm/mach-ep93xx/include/mach/ts72xx.h
> -@@ -8,36 +8,41 @@
> - * virt phys size
> - * febff000 22000000 4K model number register
> - * febfe000 22400000 4K options register
> -- * febfd000 22800000 4K options register #2
> -+ * febfd000 22800000 4K options register #2 (JP6 and TS-9420 flags)
> -+ * febfc000 [67]0000000 4K NAND data register
> -+ * febfb000 [67]0400000 4K NAND control register
> -+ * febfa000 [67]0800000 4K NAND busy register
> - * febf9000 10800000 4K TS-5620 RTC index register
> - * febf8000 11700000 4K TS-5620 RTC data register
> -+ * febf7000 23400000 4K PLD version (3 bits)
> -+ * febf6000 22c00000 4K RS-485 control register
> -+ * febf5000 23000000 4K RS-485 mode register
> - */
> -
> - #define TS72XX_MODEL_PHYS_BASE 0x22000000
> - #define TS72XX_MODEL_VIRT_BASE 0xfebff000
> - #define TS72XX_MODEL_SIZE 0x00001000
> -
> --#define TS72XX_MODEL_TS7200 0x00
> --#define TS72XX_MODEL_TS7250 0x01
> --#define TS72XX_MODEL_TS7260 0x02
> -+#define TS7XXX_MODEL_TS7200 0x00
> -+#define TS7XXX_MODEL_TS7250 0x01
> -+#define TS7XXX_MODEL_TS7260 0x02
> -+#define TS7XXX_MODEL_TS7300 0x03
> -+#define TS7XXX_MODEL_TS7400 0x04
> -+#define TS7XXX_MODEL_MASK 0x07
> -
> -
> - #define TS72XX_OPTIONS_PHYS_BASE 0x22400000
> - #define TS72XX_OPTIONS_VIRT_BASE 0xfebfe000
> - #define TS72XX_OPTIONS_SIZE 0x00001000
> --
> - #define TS72XX_OPTIONS_COM2_RS485 0x02
> - #define TS72XX_OPTIONS_MAX197 0x01
> -
> --
> - #define TS72XX_OPTIONS2_PHYS_BASE 0x22800000
> - #define TS72XX_OPTIONS2_VIRT_BASE 0xfebfd000
> - #define TS72XX_OPTIONS2_SIZE 0x00001000
> --
> - #define TS72XX_OPTIONS2_TS9420 0x04
> - #define TS72XX_OPTIONS2_TS9420_BOOT 0x02
> -
> --
> - #define TS72XX_RTC_INDEX_VIRT_BASE 0xfebf9000
> - #define TS72XX_RTC_INDEX_PHYS_BASE 0x10800000
> - #define TS72XX_RTC_INDEX_SIZE 0x00001000
> -@@ -49,32 +54,146 @@
> - #define TS72XX_WDT_CONTROL_PHYS_BASE 0x23800000
> - #define TS72XX_WDT_FEED_PHYS_BASE 0x23c00000
> -
> -+#define TS72XX_PLD_VERSION_VIRT_BASE 0xfebf7000
> -+#define TS72XX_PLD_VERSION_PHYS_BASE 0x23400000
> -+#define TS72XX_PLD_VERSION_SIZE 0x00001000
> -+
> -+#define TS72XX_JUMPERS_MAX197_PHYS_BASE 0x10800000 // jumpers/max197 busy bit/COM1 dcd register (8-bit, read only)
> -+#define TS72XX_MAX197_SAMPLE_PHYS_BASE 0x10f00000 // max197 sample/control register (16-bit read/8-bit write)
> -+
> -+/*
> -+ * RS485 option
> -+ */
> -+#define TS72XX_RS485_CONTROL_VIRT_BASE 0xfebf6000
> -+#define TS72XX_RS485_CONTROL_PHYS_BASE 0x22c00000
> -+#define TS72XX_RS485_CONTROL_SIZE 0x00001000
> -+
> -+#define TS72XX_RS485_MODE_VIRT_BASE 0xfebf5000
> -+#define TS72XX_RS485_MODE_PHYS_BASE 0x23000000
> -+#define TS72XX_RS485_MODE_SIZE 0x00001000
> -+
> -+#define TS72XX_RS485_AUTO485FD 1
> -+#define TS72XX_RS485_AUTO485HD 2
> -+#define TS72XX_RS485_MODE_RS232 0x00
> -+#define TS72XX_RS485_MODE_FD 0x01
> -+#define TS72XX_RS485_MODE_9600_HD 0x04
> -+#define TS72XX_RS485_MODE_19200_HD 0x05
> -+#define TS72XX_RS485_MODE_57600_HD 0x06
> -+#define TS72XX_RS485_MODE_115200_HD 0x07
> -+
> -+/*
> -+ * PC/104 8-bit & 16-bit bus
> -+ *
> -+ * virt phys size
> -+ * febf0000 11e00000 4K PC/104 8-bit I/O
> -+ * febef000 21e00000 4K PC/104 16-bit I/O
> -+ * fea00000 11a00000 1MB PC/104 8-bit memory
> -+ * fe900000 21a00000 1MB PC/104 16-bit memory
> -+ */
> -+#define TS72XX_PC104_8BIT_IO_VIRT_BASE 0xfebf0000
> -+#define TS72XX_PC104_8BIT_IO_PHYS_BASE 0x11e00000
> -+#define TS72XX_PC104_8BIT_IO_SIZE 0x00001000
> -+#define TS72XX_PC104_8BIT_MEM_VIRT_BASE 0xfea00000
> -+#define TS72XX_PC104_8BIT_MEM_PHYS_BASE 0x11a00000
> -+#define TS72XX_PC104_8BIT_MEM_SIZE 0x00100000
> -+
> -+#define TS72XX_PC104_16BIT_IO_VIRT_BASE 0xfebef000
> -+#define TS72XX_PC104_16BIT_IO_PHYS_BASE 0x21e00000
> -+#define TS72XX_PC104_16BIT_IO_SIZE 0x00001000
> -+#define TS72XX_PC104_16BIT_MEM_VIRT_BASE 0xfe900000
> -+#define TS72XX_PC104_16BIT_MEM_PHYS_BASE 0x21a00000
> -+#define TS72XX_PC104_16BIT_MEM_SIZE 0x00100000
> -+
> -+/*
> -+ * TS7200 specific : CompactFlash memory map
> -+ *
> -+ * phys size description
> -+ * 11000000 7 CF registers (8-bit each), starting at 11000001
> -+ * 10400006 2 CF aux registers (8-bit)
> -+ * 21000000 2 CF data register (16-bit)
> -+ */
> -+#define TS7200_CF_CMD_PHYS_BASE 0x11000000
> -+#define TS7200_CF_AUX_PHYS_BASE 0x10400006
> -+#define TS7200_CF_DATA_PHYS_BASE 0x21000000
> -+
> -+/*
> -+ * TS7260 specific : SD card & Power Management
> -+ *
> -+ * phys size description
> -+ * 12000000 4K Power management register (8-bit)
> -+ * 13000000 4K SD card registers (4 x 8-bit)
> -+ */
> -+#define TS7260_POWER_MANAGEMENT_PHYS_BASE 0x12000000
> -+#define TS7260_PM_RS232_LEVEL_CONVERTER 0x01
> -+#define TS7260_PM_USB 0x02
> -+#define TS7260_PM_LCD 0x04
> -+#define TS7260_PM_5V_SWITCHER 0x08
> -+#define TS7260_PM_PC104_CLOCK 0x10
> -+#define TS7260_PM_PC104_FAST_STROBES 0x20
> -+#define TS7260_PM_TTL_UART_ENABLE 0x40
> -+#define TS7260_PM_SCRATCH_BIT 0x80
> -+
> -+#define TS7260_SDCARD_PHYS_BASE 0x13000000
> -+
> - #ifndef __ASSEMBLY__
> -
> - static inline int board_is_ts7200(void)
> - {
> -- return __raw_readb(TS72XX_MODEL_VIRT_BASE) == TS72XX_MODEL_TS7200;
> -+ return (__raw_readb(TS72XX_MODEL_VIRT_BASE) &
> -+ TS7XXX_MODEL_MASK) == TS7XXX_MODEL_TS7200;
> - }
> -
> - static inline int board_is_ts7250(void)
> - {
> -- return __raw_readb(TS72XX_MODEL_VIRT_BASE) == TS72XX_MODEL_TS7250;
> -+ return (__raw_readb(TS72XX_MODEL_VIRT_BASE) &
> -+ TS7XXX_MODEL_MASK) == TS7XXX_MODEL_TS7250;
> - }
> -
> - static inline int board_is_ts7260(void)
> - {
> -- return __raw_readb(TS72XX_MODEL_VIRT_BASE) == TS72XX_MODEL_TS7260;
> -+ return (__raw_readb(TS72XX_MODEL_VIRT_BASE) &
> -+ TS7XXX_MODEL_MASK) == TS7XXX_MODEL_TS7260;
> -+}
> -+
> -+static inline int board_is_ts7300(void)
> -+{
> -+ return (__raw_readb(TS72XX_MODEL_VIRT_BASE) &
> -+ TS7XXX_MODEL_MASK) == TS7XXX_MODEL_TS7300;
> -+}
> -+
> -+static inline int board_is_ts7400(void)
> -+{
> -+ return (__raw_readb(TS72XX_MODEL_VIRT_BASE) &
> -+ TS7XXX_MODEL_MASK) == TS7XXX_MODEL_TS7400;
> - }
> -
> - static inline int is_max197_installed(void)
> - {
> - return !!(__raw_readb(TS72XX_OPTIONS_VIRT_BASE) &
> -- TS72XX_OPTIONS_MAX197);
> -+ TS72XX_OPTIONS_MAX197);
> - }
> -
> - static inline int is_ts9420_installed(void)
> - {
> - return !!(__raw_readb(TS72XX_OPTIONS2_VIRT_BASE) &
> -- TS72XX_OPTIONS2_TS9420);
> -+ TS72XX_OPTIONS2_TS9420);
> - }
> -+
> -+static inline int is_rs485_installed(void)
> -+{
> -+ return !!(__raw_readb(TS72XX_OPTIONS_VIRT_BASE) &
> -+ TS72XX_OPTIONS_COM2_RS485);
> -+}
> -+
> -+static inline int get_ts72xx_pld_version(void)
> -+{
> -+ return (__raw_readb(TS72XX_PLD_VERSION_VIRT_BASE) & 0x7);
> -+}
> -+
> -+/* User jumper */
> -+static inline int is_jp6_set(void)
> -+{
> -+ return (__raw_readb(TS72XX_OPTIONS2_VIRT_BASE) & 0x1);
> -+}
> -+
> - #endif
> -diff --git a/arch/arm/mach-ep93xx/ts72xx.c b/arch/arm/mach-ep93xx/ts72xx.c
> -index 93aeab8..345ce18 100644
> ---- a/arch/arm/mach-ep93xx/ts72xx.c
> -+++ b/arch/arm/mach-ep93xx/ts72xx.c
> -@@ -54,7 +54,36 @@ static struct map_desc ts72xx_io_desc[] __initdata = {
> - .pfn = __phys_to_pfn(TS72XX_RTC_DATA_PHYS_BASE),
> - .length = TS72XX_RTC_DATA_SIZE,
> - .type = MT_DEVICE,
> -- }
> -+ },
> -+ /* Use this for debug only. Each device will map its own PC/104 address space */
> -+ ///* PC/104 (8-bit) I/O bus */
> -+ //{
> -+ // .virtual = TS72XX_PC104_8BIT_IO_VIRT_BASE,
> -+ // .pfn = __phys_to_pfn(TS72XX_PC104_8BIT_IO_PHYS_BASE),
> -+ // .length = TS72XX_PC104_8BIT_IO_SIZE,
> -+ // .type = MT_DEVICE,
> -+ //},
> -+ ///* PC/104 (16-bit) I/O bus */
> -+ //{
> -+ // .virtual = TS72XX_PC104_16BIT_IO_VIRT_BASE,
> -+ // .pfn = __phys_to_pfn(TS72XX_PC104_16BIT_IO_PHYS_BASE),
> -+ // .length = TS72XX_PC104_16BIT_IO_SIZE,
> -+ // .type = MT_DEVICE,
> -+ //},
> -+ ///* PC/104 (8-bit) MEM bus */
> -+ //{
> -+ // .virtual = TS72XX_PC104_8BIT_MEM_VIRT_BASE,
> -+ // .pfn = __phys_to_pfn(TS72XX_PC104_8BIT_MEM_PHYS_BASE),
> -+ // .length = TS72XX_PC104_8BIT_MEM_SIZE,
> -+ // .type = MT_DEVICE,
> -+ //},
> -+ ///* PC/104 (16-bit) MEM bus */
> -+ //{
> -+ // .virtual = TS72XX_PC104_16BIT_MEM_VIRT_BASE,
> -+ // .pfn = __phys_to_pfn(TS72XX_PC104_16BIT_MEM_PHYS_BASE),
> -+ // .length = TS72XX_PC104_16BIT_MEM_SIZE,
> -+ // .type = MT_DEVICE,
> -+ //}
> - };
> -
> - static void __init ts72xx_map_io(void)
> -@@ -194,7 +223,9 @@ static void __init ts72xx_register_flash(void)
> - }
> - }
> -
> --
> -+/*************************************************************************
> -+ * RTC
> -+ *************************************************************************/
> - static unsigned char ts72xx_rtc_readbyte(unsigned long addr)
> - {
> - __raw_writeb(addr, TS72XX_RTC_INDEX_VIRT_BASE);
> -@@ -242,6 +273,9 @@ static struct platform_device ts72xx_wdt_device = {
> - };
> -
> - static struct ep93xx_eth_data __initdata ts72xx_eth_data = {
> -+/*************************************************************************
> -+ * Ethernet
> -+ *************************************************************************/
> - .phy_id = 1,
> - };
> -
> -@@ -253,6 +287,9 @@ static void __init ts72xx_init_machine(void)
> - platform_device_register(&ts72xx_wdt_device);
> -
> - ep93xx_register_eth(&ts72xx_eth_data, 1);
> -+
> -+ /* PWM1 is DIO_6 on TS-72xx header */
> -+ ep93xx_register_pwm(0, 1);
> - }
> -
> - MACHINE_START(TS72XX, "Technologic Systems TS-72xx SBC")
> -diff --git a/arch/arm/mm/proc-arm920.S b/arch/arm/mm/proc-arm920.S
> -index 86f80aa..11ea759 100644
> ---- a/arch/arm/mm/proc-arm920.S
> -+++ b/arch/arm/mm/proc-arm920.S
> -@@ -190,7 +190,7 @@ ENTRY(arm920_coherent_kern_range)
> - */
> - ENTRY(arm920_coherent_user_range)
> - bic r0, r0, #CACHE_DLINESIZE - 1
> --1: mcr p15, 0, r0, c7, c10, 1 @ clean D entry
> -+1: mcr p15, 0, r0, c7, c14, 1 @ clean+invalidate D entry
> - mcr p15, 0, r0, c7, c5, 1 @ invalidate I entry
> - add r0, r0, #CACHE_DLINESIZE
> - cmp r0, r1
> -@@ -390,6 +390,9 @@ __arm920_setup:
> - mrc p15, 0, r0, c1, c0 @ get control register v4
> - bic r0, r0, r5
> - orr r0, r0, r6
> -+#ifdef CONFIG_CR1_NFBIT
> -+ orr r0, r0, #0x40000000 @ set nF
> -+#endif
> - mov pc, lr
> - .size __arm920_setup, . - __arm920_setup
> -
> -diff --git a/scripts/Makefile.fwinst b/scripts/Makefile.fwinst
> -index 6bf8e87..fb20532 100644
> ---- a/scripts/Makefile.fwinst
> -+++ b/scripts/Makefile.fwinst
> -@@ -37,7 +37,7 @@ install-all-dirs: $(installed-fw-dirs)
> - @true
> -
> - quiet_cmd_install = INSTALL $(subst $(srctree)/,,$@)
> -- cmd_install = $(INSTALL) -m0644 $< $@
> -+ cmd_install = $(INSTALL) -m 0644 $< $@
> -
> - $(installed-fw-dirs):
> - $(call cmd,mkdir)
> ---
> -1.7.0.4
> -
> diff --git a/recipes/linux/linux-2.6.36/ts72xx/0002-ts72xx_force_machine-id.patch b/recipes/linux/linux-2.6.36/ts72xx/0002-ts72xx_force_machine-id.patch
> deleted file mode 100644
> index 4b90ec6..0000000
> --- a/recipes/linux/linux-2.6.36/ts72xx/0002-ts72xx_force_machine-id.patch
> +++ /dev/null
> @@ -1,49 +0,0 @@
> -From 841896f3124d3493f5bb1b98370a1d5fcdcaedb4 Mon Sep 17 00:00:00 2001
> -From: Matthieu Crapet <mcrapet@gmail.com>
> -Date: Thu, 10 Jun 2010 10:51:39 +0200
> -Subject: [PATCH 02/24] ts72xx_force_machine-id
> -MIME-Version: 1.0
> -Content-Type: text/plain; charset=UTF-8
> -Content-Transfer-Encoding: 8bit
> -
> -Signed-off-by: Petr Štetiar <ynezz@true.cz>
> ----
> - arch/arm/kernel/head.S | 3 +++
> - arch/arm/mach-ep93xx/Kconfig | 7 +++++++
> - 2 files changed, 10 insertions(+), 0 deletions(-)
> -
> -diff --git a/arch/arm/kernel/head.S b/arch/arm/kernel/head.S
> -index eb62bf9..543eccf 100644
> ---- a/arch/arm/kernel/head.S
> -+++ b/arch/arm/kernel/head.S
> -@@ -82,6 +82,9 @@ ENTRY(stext)
> - bl __lookup_processor_type @ r5=procinfo r9=cpuid
> - movs r10, r5 @ invalid processor (r5=0)?
> - beq __error_p @ yes, error 'p'
> -+#ifdef CONFIG_MACH_TS72XX_FORCE_MACHINEID
> -+ ldr r1, =0x2a1
> -+#endif
> - bl __lookup_machine_type @ r5=machinfo
> - movs r8, r5 @ invalid machine (r5=0)?
> - beq __error_a @ yes, error 'a'
> -diff --git a/arch/arm/mach-ep93xx/Kconfig b/arch/arm/mach-ep93xx/Kconfig
> -index b6be37e..bd463a0 100644
> ---- a/arch/arm/mach-ep93xx/Kconfig
> -+++ b/arch/arm/mach-ep93xx/Kconfig
> -@@ -205,6 +205,13 @@ config EP93XX_EARLY_UART3
> -
> - endchoice
> -
> -+config MACH_TS72XX_FORCE_MACHINEID
> -+ bool "Force Machine ID"
> -+ depends on MACH_TS72XX
> -+ help
> -+ Say 'Y' here to force Machine ID to 0x2A1 (MACH_TYPE_TS72XX legacy value)
> -+ In early days Technologic Systems fixed the 0x163 value in redboot.
> -+
> - endmenu
> -
> - endif
> ---
> -1.7.0.4
> -
> diff --git a/recipes/linux/linux-2.6.36/ts72xx/0003-ep93xx_cpuinfo.patch b/recipes/linux/linux-2.6.36/ts72xx/0003-ep93xx_cpuinfo.patch
> deleted file mode 100644
> index 61a9c18..0000000
> --- a/recipes/linux/linux-2.6.36/ts72xx/0003-ep93xx_cpuinfo.patch
> +++ /dev/null
> @@ -1,36 +0,0 @@
> -From 31727a8a72dc85dc4dc0eeeb27f7f9313c74914b Mon Sep 17 00:00:00 2001
> -From: Matthieu Crapet <mcrapet@gmail.com>
> -Date: Thu, 10 Jun 2010 10:59:31 +0200
> -Subject: [PATCH 03/24] ep93xx_cpuinfo
> -MIME-Version: 1.0
> -Content-Type: text/plain; charset=UTF-8
> -Content-Transfer-Encoding: 8bit
> -
> -Signed-off-by: Petr Štetiar <ynezz@true.cz>
> ----
> - arch/arm/kernel/setup.c | 9 +++++++++
> - 1 files changed, 9 insertions(+), 0 deletions(-)
> -
> -diff --git a/arch/arm/kernel/setup.c b/arch/arm/kernel/setup.c
> -index d5231ae..a47ad88 100644
> ---- a/arch/arm/kernel/setup.c
> -+++ b/arch/arm/kernel/setup.c
> -@@ -953,6 +953,15 @@ static int c_show(struct seq_file *m, void *v)
> - seq_puts(m, "\n");
> -
> - seq_printf(m, "Hardware\t: %s\n", machine_name);
> -+
> -+ #if defined(CONFIG_ARCH_EP93XX)
> -+ #include <mach/io.h>
> -+ #include <mach/ep93xx-regs.h>
> -+ system_rev = *((unsigned int *)EP93XX_SYSCON_CHIPID) >> 28;
> -+ system_serial_low = *((unsigned int *)EP93XX_SECURITY_UNIQID);
> -+ system_serial_high = 0;
> -+ #endif
> -+
> - seq_printf(m, "Revision\t: %04x\n", system_rev);
> - seq_printf(m, "Serial\t\t: %08x%08x\n",
> - system_serial_high, system_serial_low);
> ---
> -1.7.0.4
> -
> diff --git a/recipes/linux/linux-2.6.36/ts72xx/0004-ep93xx_eth.patch b/recipes/linux/linux-2.6.36/ts72xx/0004-ep93xx_eth.patch
> deleted file mode 100644
> index 734fb93..0000000
> --- a/recipes/linux/linux-2.6.36/ts72xx/0004-ep93xx_eth.patch
> +++ /dev/null
> @@ -1,555 +0,0 @@
> -From 802fa6d7ec0d57684912b39f0fb0341698cda4e3 Mon Sep 17 00:00:00 2001
> -From: Matthieu Crapet <mcrapet@gmail.com>
> -Date: Thu, 10 Jun 2010 13:34:14 +0200
> -Subject: [PATCH 04/24] ep93xx_eth
> -MIME-Version: 1.0
> -Content-Type: text/plain; charset=UTF-8
> -Content-Transfer-Encoding: 8bit
> -
> -Signed-off-by: Petr Štetiar <ynezz@true.cz>
> ----
> - drivers/net/arm/Kconfig | 1 +
> - drivers/net/arm/ep93xx_eth.c | 346 ++++++++++++++++++++++++++++++++++--------
> - 2 files changed, 280 insertions(+), 67 deletions(-)
> -
> -diff --git a/drivers/net/arm/Kconfig b/drivers/net/arm/Kconfig
> -index 39e1c0d..55c0dd4 100644
> ---- a/drivers/net/arm/Kconfig
> -+++ b/drivers/net/arm/Kconfig
> -@@ -52,6 +52,7 @@ config EP93XX_ETH
> - tristate "EP93xx Ethernet support"
> - depends on ARM && ARCH_EP93XX
> - select MII
> -+ select PHYLIB
> - help
> - This is a driver for the ethernet hardware included in EP93xx CPUs.
> - Say Y if you are building a kernel for EP93xx based devices.
> -diff --git a/drivers/net/arm/ep93xx_eth.c b/drivers/net/arm/ep93xx_eth.c
> -index 4a5ec94..7e60c4d 100644
> ---- a/drivers/net/arm/ep93xx_eth.c
> -+++ b/drivers/net/arm/ep93xx_eth.c
> -@@ -2,6 +2,7 @@
> - * EP93xx ethernet network device driver
> - * Copyright (C) 2006 Lennert Buytenhek <buytenh@wantstofly.org>
> - * Dedicated to Marija Kulikova.
> -+ * Copyright (C) 2007 Herbert Valerio Riedel <hvr@gnu.org>
> - *
> - * 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
> -@@ -16,6 +17,7 @@
> - #include <linux/kernel.h>
> - #include <linux/netdevice.h>
> - #include <linux/mii.h>
> -+#include <linux/phy.h>
> - #include <linux/etherdevice.h>
> - #include <linux/ethtool.h>
> - #include <linux/init.h>
> -@@ -27,8 +29,8 @@
> -
> - #include <mach/hardware.h>
> -
> --#define DRV_MODULE_NAME "ep93xx-eth"
> --#define DRV_MODULE_VERSION "0.1"
> -+#define DRV_NAME "ep93xx-eth"
> -+#define DRV_VERSION "0.13"
> -
> - #define RX_QUEUE_ENTRIES 64
> - #define TX_QUEUE_ENTRIES 8
> -@@ -40,6 +42,8 @@
> - #define REG_RXCTL_DEFAULT 0x00073800
> - #define REG_TXCTL 0x0004
> - #define REG_TXCTL_ENABLE 0x00000001
> -+#define REG_TESTCTL 0x0008
> -+#define REG_TESTCTL_MFDX 0x00000040
> - #define REG_MIICMD 0x0010
> - #define REG_MIICMD_READ 0x00008000
> - #define REG_MIICMD_WRITE 0x00004000
> -@@ -48,6 +52,9 @@
> - #define REG_MIISTS_BUSY 0x00000001
> - #define REG_SELFCTL 0x0020
> - #define REG_SELFCTL_RESET 0x00000001
> -+#define REG_SELFCTL_MDCDIV_MSK 0x00007e00
> -+#define REG_SELFCTL_MDCDIV_OFS 9
> -+#define REG_SELFCTL_PSPRS 0x00000100
> - #define REG_INTEN 0x0024
> - #define REG_INTEN_TX 0x00000008
> - #define REG_INTEN_RX 0x00000007
> -@@ -177,8 +184,14 @@ struct ep93xx_priv
> -
> - struct net_device_stats stats;
> -
> -- struct mii_if_info mii;
> - u8 mdc_divisor;
> -+ int phy_supports_mfps:1;
> -+
> -+ struct mii_bus mii_bus;
> -+ struct phy_device *phy_dev;
> -+ int speed;
> -+ int duplex;
> -+ int link;
> - };
> -
> - #define rdb(ep, off) __raw_readb((ep)->base_addr + (off))
> -@@ -188,46 +201,78 @@ struct ep93xx_priv
> - #define wrw(ep, off, val) __raw_writew((val), (ep)->base_addr + (off))
> - #define wrl(ep, off, val) __raw_writel((val), (ep)->base_addr + (off))
> -
> --static int ep93xx_mdio_read(struct net_device *dev, int phy_id, int reg)
> -+/* common MII transactions should take < 100 iterations */
> -+#define EP93XX_PHY_TIMEOUT 2000
> -+
> -+static int ep93xx_mdio_wait(struct mii_bus *bus)
> - {
> -- struct ep93xx_priv *ep = netdev_priv(dev);
> -- int data;
> -- int i;
> -+ struct ep93xx_priv *ep = bus->priv;
> -+ unsigned int timeout = EP93XX_PHY_TIMEOUT;
> -
> -- wrl(ep, REG_MIICMD, REG_MIICMD_READ | (phy_id << 5) | reg);
> -+ while ((rdl(ep, REG_MIISTS) & REG_MIISTS_BUSY)
> -+ && timeout--)
> -+ cpu_relax();
> -
> -- for (i = 0; i < 10; i++) {
> -- if ((rdl(ep, REG_MIISTS) & REG_MIISTS_BUSY) == 0)
> -- break;
> -- msleep(1);
> -+ if (timeout <= 0) {
> -+ dev_err(&bus->dev, "MII operation timed out\n");
> -+ return -ETIMEDOUT;
> - }
> -
> -- if (i == 10) {
> -- pr_info("mdio read timed out\n");
> -- data = 0xffff;
> -- } else {
> -- data = rdl(ep, REG_MIIDATA);
> -- }
> -+ return 0;
> -+}
> -+
> -+static int ep93xx_mdio_read(struct mii_bus *bus, int mii_id, int reg)
> -+{
> -+ struct ep93xx_priv *ep = bus->priv;
> -+ u32 selfctl;
> -+ u32 data;
> -+
> -+ if (ep93xx_mdio_wait(bus) < 0)
> -+ return -ETIMEDOUT;
> -+
> -+ selfctl = rdl(ep, REG_SELFCTL);
> -
> -- return data;
> -+ if (ep->phy_supports_mfps)
> -+ wrl(ep, REG_SELFCTL, selfctl | REG_SELFCTL_PSPRS);
> -+ else
> -+ wrl(ep, REG_SELFCTL, selfctl & ~REG_SELFCTL_PSPRS);
> -+
> -+ wrl(ep, REG_MIICMD, REG_MIICMD_READ | (mii_id << 5) | reg);
> -+
> -+ if (ep93xx_mdio_wait(bus) < 0)
> -+ return -ETIMEDOUT;
> -+
> -+ data = rdl(ep, REG_MIIDATA);
> -+
> -+ wrl(ep, REG_SELFCTL, selfctl);
> -+
> -+ return data;
> - }
> -
> --static void ep93xx_mdio_write(struct net_device *dev, int phy_id, int reg, int data)
> -+static int ep93xx_mdio_write(struct mii_bus *bus, int mii_id, int reg, u16 data)
> - {
> -- struct ep93xx_priv *ep = netdev_priv(dev);
> -- int i;
> -+ struct ep93xx_priv *ep = bus->priv;
> -+ u32 selfctl;
> -+
> -+ if (ep93xx_mdio_wait(bus) < 0)
> -+ return -ETIMEDOUT;
> -+
> -+ selfctl = rdl(ep, REG_SELFCTL);
> -+
> -+ if (ep->phy_supports_mfps)
> -+ wrl(ep, REG_SELFCTL, selfctl | REG_SELFCTL_PSPRS);
> -+ else
> -+ wrl(ep, REG_SELFCTL, selfctl & ~REG_SELFCTL_PSPRS);
> -
> - wrl(ep, REG_MIIDATA, data);
> -- wrl(ep, REG_MIICMD, REG_MIICMD_WRITE | (phy_id << 5) | reg);
> -+ wrl(ep, REG_MIICMD, REG_MIICMD_WRITE | (mii_id << 5) | reg);
> -
> -- for (i = 0; i < 10; i++) {
> -- if ((rdl(ep, REG_MIISTS) & REG_MIISTS_BUSY) == 0)
> -- break;
> -- msleep(1);
> -- }
> -+ if (ep93xx_mdio_wait(bus) < 0)
> -+ return -ETIMEDOUT;
> -
> -- if (i == 10)
> -- pr_info("mdio write timed out\n");
> -+ wrl(ep, REG_SELFCTL, selfctl);
> -+
> -+ return 0;
> - }
> -
> - static struct net_device_stats *ep93xx_get_stats(struct net_device *dev)
> -@@ -557,6 +602,22 @@ err:
> - return 1;
> - }
> -
> -+static int ep93xx_mdio_reset(struct mii_bus *bus)
> -+{
> -+ struct ep93xx_priv *ep = bus->priv;
> -+
> -+ u32 selfctl = rdl(ep, REG_SELFCTL);
> -+
> -+ selfctl &= ~(REG_SELFCTL_MDCDIV_MSK | REG_SELFCTL_PSPRS);
> -+
> -+ selfctl |= (ep->mdc_divisor - 1) << REG_SELFCTL_MDCDIV_OFS;
> -+ selfctl |= REG_SELFCTL_PSPRS;
> -+
> -+ wrl(ep, REG_SELFCTL, selfctl);
> -+
> -+ return 0;
> -+}
> -+
> - static int ep93xx_start_hw(struct net_device *dev)
> - {
> - struct ep93xx_priv *ep = netdev_priv(dev);
> -@@ -575,11 +636,8 @@ static int ep93xx_start_hw(struct net_device *dev)
> - return 1;
> - }
> -
> -- wrl(ep, REG_SELFCTL, ((ep->mdc_divisor - 1) << 9));
> --
> -- /* Does the PHY support preamble suppress? */
> -- if ((ep93xx_mdio_read(dev, ep->mii.phy_id, MII_BMSR) & 0x0040) != 0)
> -- wrl(ep, REG_SELFCTL, ((ep->mdc_divisor - 1) << 9) | (1 << 8));
> -+ /* The reset cleared REG_SELFCTL, so set the MDC divisor again */
> -+ ep93xx_mdio_reset(&ep->mii_bus);
> -
> - /* Receive descriptor ring. */
> - addr = ep->descs_dma_addr + offsetof(struct ep93xx_descs, rdesc);
> -@@ -688,6 +746,8 @@ static int ep93xx_open(struct net_device *dev)
> -
> - wrl(ep, REG_GIINTMSK, REG_GIINTMSK_ENABLE);
> -
> -+ phy_start(ep->phy_dev);
> -+
> - netif_start_queue(dev);
> -
> - return 0;
> -@@ -700,6 +760,9 @@ static int ep93xx_close(struct net_device *dev)
> - napi_disable(&ep->napi);
> - netif_stop_queue(dev);
> -
> -+ if (ep->phy_dev)
> -+ phy_stop(ep->phy_dev);
> -+
> - wrl(ep, REG_GIINTMSK, 0);
> - free_irq(ep->irq, dev);
> - ep93xx_stop_hw(dev);
> -@@ -711,47 +774,44 @@ static int ep93xx_close(struct net_device *dev)
> - static int ep93xx_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
> - {
> - struct ep93xx_priv *ep = netdev_priv(dev);
> -- struct mii_ioctl_data *data = if_mii(ifr);
> -
> -- return generic_mii_ioctl(&ep->mii, data, cmd, NULL);
> -+ return phy_mii_ioctl(ep->phy_dev, ifr, cmd);
> - }
> -
> - static void ep93xx_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
> - {
> -- strcpy(info->driver, DRV_MODULE_NAME);
> -- strcpy(info->version, DRV_MODULE_VERSION);
> -+ strlcpy(info->driver, DRV_NAME, sizeof(info->driver));
> -+ strlcpy(info->version, DRV_VERSION, sizeof(info->version));
> -+ strlcpy(info->bus_info, dev_name(dev->dev.parent), sizeof(info->bus_info));
> - }
> -
> - static int ep93xx_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
> - {
> - struct ep93xx_priv *ep = netdev_priv(dev);
> -- return mii_ethtool_gset(&ep->mii, cmd);
> -+ struct phy_device *phydev = ep->phy_dev;
> -+
> -+ if (!phydev)
> -+ return -ENODEV;
> -+
> -+ return phy_ethtool_gset(phydev, cmd);
> - }
> -
> - static int ep93xx_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
> - {
> - struct ep93xx_priv *ep = netdev_priv(dev);
> -- return mii_ethtool_sset(&ep->mii, cmd);
> --}
> -+ struct phy_device *phydev = ep->phy_dev;
> -
> --static int ep93xx_nway_reset(struct net_device *dev)
> --{
> -- struct ep93xx_priv *ep = netdev_priv(dev);
> -- return mii_nway_restart(&ep->mii);
> --}
> -+ if (!phydev)
> -+ return -ENODEV;
> -
> --static u32 ep93xx_get_link(struct net_device *dev)
> --{
> -- struct ep93xx_priv *ep = netdev_priv(dev);
> -- return mii_link_ok(&ep->mii);
> -+ return phy_ethtool_sset(phydev, cmd);
> - }
> -
> - static const struct ethtool_ops ep93xx_ethtool_ops = {
> - .get_drvinfo = ep93xx_get_drvinfo,
> - .get_settings = ep93xx_get_settings,
> - .set_settings = ep93xx_set_settings,
> -- .nway_reset = ep93xx_nway_reset,
> -- .get_link = ep93xx_get_link,
> -+ .get_link = ethtool_op_get_link,
> - };
> -
> - static const struct net_device_ops ep93xx_netdev_ops = {
> -@@ -813,6 +873,113 @@ static int ep93xx_eth_remove(struct platform_device *pdev)
> - return 0;
> - }
> -
> -+static void ep93xx_adjust_link(struct net_device *dev)
> -+{
> -+ struct ep93xx_priv *ep = netdev_priv(dev);
> -+ struct phy_device *phydev = ep->phy_dev;
> -+
> -+ int status_change = 0;
> -+
> -+ if (phydev->link) {
> -+ if ((ep->speed != phydev->speed) ||
> -+ (ep->duplex != phydev->duplex)) {
> -+ /* speed and/or duplex state changed */
> -+ u32 testctl = rdl(ep, REG_TESTCTL);
> -+
> -+ if (DUPLEX_FULL == phydev->duplex)
> -+ testctl |= REG_TESTCTL_MFDX;
> -+ else
> -+ testctl &= ~(REG_TESTCTL_MFDX);
> -+
> -+ wrl(ep, REG_TESTCTL, testctl);
> -+
> -+ ep->speed = phydev->speed;
> -+ ep->duplex = phydev->duplex;
> -+ status_change = 1;
> -+ }
> -+ }
> -+
> -+ /* test for online/offline link transition */
> -+ if (phydev->link != ep->link) {
> -+ if (phydev->link) /* link went online */
> -+ netif_tx_schedule_all(dev);
> -+ else { /* link went offline */
> -+ ep->speed = 0;
> -+ ep->duplex = -1;
> -+ }
> -+ ep->link = phydev->link;
> -+
> -+ status_change = 1;
> -+ }
> -+
> -+ if (status_change)
> -+ phy_print_status(phydev);
> -+}
> -+
> -+static int ep93xx_mii_probe(struct net_device *dev, int phy_addr)
> -+{
> -+ struct ep93xx_priv *ep = netdev_priv(dev);
> -+ struct phy_device *phydev = NULL;
> -+ int val;
> -+
> -+ if (phy_addr >= 0 && phy_addr < PHY_MAX_ADDR)
> -+ phydev = ep->mii_bus.phy_map[phy_addr];
> -+
> -+ if (!phydev) {
> -+ pr_info("PHY not found at specified address,"
> -+ " trying autodetection\n");
> -+
> -+ /* find the first phy */
> -+ for (phy_addr = 0; phy_addr < PHY_MAX_ADDR; phy_addr++) {
> -+ if (ep->mii_bus.phy_map[phy_addr]) {
> -+ phydev = ep->mii_bus.phy_map[phy_addr];
> -+ break;
> -+ }
> -+ }
> -+ }
> -+
> -+ if (!phydev) {
> -+ pr_err("no PHY found\n");
> -+ return -ENODEV;
> -+ }
> -+
> -+ phydev = phy_connect(dev, dev_name(&phydev->dev),
> -+ ep93xx_adjust_link, 0, PHY_INTERFACE_MODE_MII);
> -+
> -+ if (IS_ERR(phydev)) {
> -+ pr_err("Could not attach to PHY\n");
> -+ return PTR_ERR(phydev);
> -+ }
> -+
> -+ ep->phy_supports_mfps = 0;
> -+
> -+ val = phy_read(phydev, MII_BMSR);
> -+ if (val < 0) {
> -+ pr_err("failed to read MII register\n");
> -+ return val;
> -+ }
> -+
> -+ if (val & 0x0040) {
> -+ pr_info("PHY supports MII frame preamble suppression\n");
> -+ ep->phy_supports_mfps = 1;
> -+ }
> -+
> -+ phydev->supported &= PHY_BASIC_FEATURES;
> -+
> -+ phydev->advertising = phydev->supported;
> -+
> -+ ep->link = 0;
> -+ ep->speed = 0;
> -+ ep->duplex = -1;
> -+ ep->phy_dev = phydev;
> -+
> -+ pr_info("attached PHY driver [%s] "
> -+ "(mii_bus:phy_addr=%s, irq=%d)\n",
> -+ phydev->drv->name, dev_name(&phydev->dev), phydev->irq);
> -+
> -+ return 0;
> -+}
> -+
> - static int ep93xx_eth_probe(struct platform_device *pdev)
> - {
> - struct ep93xx_eth_data *data;
> -@@ -820,7 +987,7 @@ static int ep93xx_eth_probe(struct platform_device *pdev)
> - struct ep93xx_priv *ep;
> - struct resource *mem;
> - int irq;
> -- int err;
> -+ int err, i;
> -
> - if (pdev == NULL)
> - return -ENODEV;
> -@@ -847,24 +1014,43 @@ static int ep93xx_eth_probe(struct platform_device *pdev)
> - if (ep->res == NULL) {
> - dev_err(&pdev->dev, "Could not reserve memory region\n");
> - err = -ENOMEM;
> -- goto err_out;
> -+ goto err_out_request_mem_region;
> - }
> -
> - ep->base_addr = ioremap(mem->start, resource_size(mem));
> - if (ep->base_addr == NULL) {
> - dev_err(&pdev->dev, "Failed to ioremap ethernet registers\n");
> - err = -EIO;
> -- goto err_out;
> -+ goto err_out_ioremap;
> - }
> - ep->irq = irq;
> -
> -- ep->mii.phy_id = data->phy_id;
> -- ep->mii.phy_id_mask = 0x1f;
> -- ep->mii.reg_num_mask = 0x1f;
> -- ep->mii.dev = dev;
> -- ep->mii.mdio_read = ep93xx_mdio_read;
> -- ep->mii.mdio_write = ep93xx_mdio_write;
> -+ /* mdio/mii bus */
> -+ ep->mii_bus.state = MDIOBUS_ALLOCATED; /* see mdiobus_alloc */
> -+ ep->mii_bus.name = "ep93xx_mii_bus";
> -+ snprintf(ep->mii_bus.id, MII_BUS_ID_SIZE, "0");
> -+
> -+ ep->mii_bus.read = ep93xx_mdio_read;
> -+ ep->mii_bus.write = ep93xx_mdio_write;
> -+ ep->mii_bus.reset = ep93xx_mdio_reset;
> -+
> -+ ep->mii_bus.phy_mask = 0;
> -+
> -+ ep->mii_bus.priv = ep;
> -+ ep->mii_bus.dev = dev->dev;
> -+
> -+ ep->mii_bus.irq = kmalloc(sizeof(int)*PHY_MAX_ADDR, GFP_KERNEL);
> -+ if (NULL == ep->mii_bus.irq) {
> -+ dev_err(&pdev->dev, "Could not allocate memory\n");
> -+ err = -ENOMEM;
> -+ goto err_out_mii_bus_irq_kmalloc;
> -+ }
> -+
> -+ for (i = 0; i < PHY_MAX_ADDR; i++)
> -+ ep->mii_bus.irq[i] = PHY_POLL;
> -+
> - ep->mdc_divisor = 40; /* Max HCLK 100 MHz, min MDIO clk 2.5 MHz. */
> -+ ep->phy_supports_mfps = 0; /* probe without preamble suppression */
> -
> - if (is_zero_ether_addr(dev->dev_addr))
> - random_ether_addr(dev->dev_addr);
> -@@ -872,14 +1058,39 @@ static int ep93xx_eth_probe(struct platform_device *pdev)
> - err = register_netdev(dev);
> - if (err) {
> - dev_err(&pdev->dev, "Failed to register netdev\n");
> -- goto err_out;
> -+ goto err_out_register_netdev;
> -+ }
> -+
> -+ err = mdiobus_register(&ep->mii_bus);
> -+ if (err) {
> -+ dev_err(&dev->dev, "Could not register MII bus\n");
> -+ goto err_out_mdiobus_register;
> -+ }
> -+
> -+ err = ep93xx_mii_probe(dev, data->phy_id);
> -+ if (err) {
> -+ dev_err(&dev->dev, "failed to probe MII bus\n");
> -+ goto err_out_mii_probe;
> - }
> -
> -- printk(KERN_INFO "%s: ep93xx on-chip ethernet, IRQ %d, %pM\n",
> -- dev->name, ep->irq, dev->dev_addr);
> -+ dev_info(&dev->dev, "ep93xx on-chip ethernet, IRQ %d, %pM\n",
> -+ ep->irq, dev->dev_addr);
> -
> - return 0;
> -
> -+err_out_mii_probe:
> -+ mdiobus_unregister(&ep->mii_bus);
> -+err_out_mdiobus_register:
> -+ unregister_netdev(dev);
> -+err_out_register_netdev:
> -+ kfree(ep->mii_bus.irq);
> -+err_out_mii_bus_irq_kmalloc:
> -+ iounmap(ep->base_addr);
> -+err_out_ioremap:
> -+ release_resource(ep->res);
> -+ kfree(ep->res);
> -+err_out_request_mem_region:
> -+ free_netdev(dev);
> - err_out:
> - ep93xx_eth_remove(pdev);
> - return err;
> -@@ -897,7 +1108,6 @@ static struct platform_driver ep93xx_eth_driver = {
> -
> - static int __init ep93xx_eth_init_module(void)
> - {
> -- printk(KERN_INFO DRV_MODULE_NAME " version " DRV_MODULE_VERSION " loading\n");
> - return platform_driver_register(&ep93xx_eth_driver);
> - }
> -
> -@@ -908,5 +1118,7 @@ static void __exit ep93xx_eth_cleanup_module(void)
> -
> - module_init(ep93xx_eth_init_module);
> - module_exit(ep93xx_eth_cleanup_module);
> -+
> - MODULE_LICENSE("GPL");
> --MODULE_ALIAS("platform:ep93xx-eth");
> -+MODULE_DESCRIPTION("EP93XX Ethernet driver");
> -+MODULE_ALIAS("platform:" DRV_NAME);
> ---
> -1.7.0.4
> -
> diff --git a/recipes/linux/linux-2.6.36/ts72xx/0005-ep93xx-m2m-DMA-support.patch b/recipes/linux/linux-2.6.36/ts72xx/0005-ep93xx-m2m-DMA-support.patch
> deleted file mode 100644
> index 0a81782..0000000
> --- a/recipes/linux/linux-2.6.36/ts72xx/0005-ep93xx-m2m-DMA-support.patch
> +++ /dev/null
> @@ -1,886 +0,0 @@
> -From 619f5711bc905176dc23de3e646686bee36f1601 Mon Sep 17 00:00:00 2001
> -From: Matthieu Crapet <mcrapet@gmail.com>
> -Date: Thu, 10 Jun 2010 16:40:16 +0200
> -Subject: [PATCH 05/24] ep93xx: m2m DMA support
> -MIME-Version: 1.0
> -Content-Type: text/plain; charset=UTF-8
> -Content-Transfer-Encoding: 8bit
> -
> -Signed-off-by: Petr Štetiar <ynezz@true.cz>
> ----
> - arch/arm/mach-ep93xx/Makefile | 2 +-
> - arch/arm/mach-ep93xx/dma-m2m.c | 753 +++++++++++++++++++++++++++++++
> - arch/arm/mach-ep93xx/include/mach/dma.h | 65 +++
> - 3 files changed, 819 insertions(+), 1 deletions(-)
> - create mode 100644 arch/arm/mach-ep93xx/dma-m2m.c
> -
> -diff --git a/arch/arm/mach-ep93xx/Makefile b/arch/arm/mach-ep93xx/Makefile
> -index 33ee2c8..ea652c2 100644
> ---- a/arch/arm/mach-ep93xx/Makefile
> -+++ b/arch/arm/mach-ep93xx/Makefile
> -@@ -1,7 +1,7 @@
> - #
> - # Makefile for the linux kernel.
> - #
> --obj-y := core.o clock.o dma-m2p.o gpio.o
> -+obj-y := core.o clock.o dma-m2p.o dma-m2m.o gpio.o
> - obj-m :=
> - obj-n :=
> - obj- :=
> -diff --git a/arch/arm/mach-ep93xx/dma-m2m.c b/arch/arm/mach-ep93xx/dma-m2m.c
> -new file mode 100644
> -index 0000000..8b0d720
> ---- /dev/null
> -+++ b/arch/arm/mach-ep93xx/dma-m2m.c
> -@@ -0,0 +1,753 @@
> -+/*
> -+ * arch/arm/mach-ep93xx/dma-m2m.c
> -+ * M2M DMA handling for Cirrus EP93xx chips.
> -+ * Copyright (C) 2007 Metasoft <prylowski@xxxxxxxxxxx>
> -+ *
> -+ * Based on dma-m2p.c by:
> -+ * Copyright (C) 2006 Lennert Buytenhek <buytenh@xxxxxxxxxxxxxx>
> -+ * Copyright (C) 2006 Applied Data Systems
> -+ *
> -+ * 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.
> -+ */
> -+
> -+#define pr_fmt(fmt) "ep93xx " KBUILD_MODNAME ": " fmt
> -+
> -+#include <linux/kernel.h>
> -+#include <linux/clk.h>
> -+#include <linux/err.h>
> -+#include <linux/interrupt.h>
> -+#include <linux/module.h>
> -+#include <linux/string.h>
> -+#include <linux/io.h>
> -+
> -+#include <mach/dma.h>
> -+#include <mach/hardware.h>
> -+
> -+/* TEMP */
> -+#define DPRINTK(fmt, args...)
> -+
> -+#define M2M_CONTROL 0x00
> -+#define M2M_INTERRUPT 0x04
> -+#define M2M_STATUS 0x0c
> -+#define M2M_BCR0 0x10
> -+#define M2M_BCR1 0x14
> -+#define M2M_SAR_BASE0 0x18
> -+#define M2M_SAR_BASE1 0x1c
> -+#define M2M_SAR_CURR0 0x24
> -+#define M2M_SAR_CURR1 0x28
> -+#define M2M_DAR_BASE0 0x2c
> -+#define M2M_DAR_BASE1 0x30
> -+#define M2M_DAR_CURR0 0x34
> -+#define M2M_DAR_CURR1 0x3c
> -+
> -+
> -+/* control register bits */
> -+#define CTRL_STALL_INT_EN 0x00000001 /* stall interrupt enable */
> -+#define CTRL_SCT 0x00000002 /* source copy transfer
> -+ (1 elem. from source fills
> -+ destination block */
> -+#define CTRL_DONE_INT_EN 0x00000004 /* done interrupt enable */
> -+#define CTRL_ENABLE 0x00000008 /* channel enable / disable,
> -+ should be set after
> -+ write to SAR/DAR/BCR
> -+ registers */
> -+#define CTRL_NFB_INT_EN 0x00200000 /* nfb (next frame buffer)
> -+ interrupt enable */
> -+
> -+
> -+#define CTRL_START 0x00000010 /* software triggered
> -+ dma start, not used
> -+ for M2P/P2M/IDE/SSP */
> -+#define CTRL_BWC_MASK 0x000001e0 /* bandwidth control (number
> -+ of bytes in a block
> -+ transfer, only M2M */
> -+#define CTRL_BWC_SHIFT 5
> -+
> -+#define BWC_FULL 0x0 /* full bandwidth utilized */
> -+#define BWC_16 0x1 /* 16 bytes per block */
> -+#define BWC_32 0x5
> -+#define BWC_64 0x6
> -+#define BWC_128 0x7
> -+#define BWC_256 0x8
> -+#define BWC_512 0x9
> -+#define BWC_1024 0xa
> -+#define BWC_2048 0xb
> -+#define BWC_4096 0xc
> -+#define BWC_8192 0xd
> -+#define BWC_16384 0xe
> -+#define BWC_32768 0xf
> -+
> -+#define CTRL_PW_MASK 0x00000600 /* peripheral width,
> -+ only M2P/P2M */
> -+#define CTRL_PW_SHIFT 9
> -+
> -+#define PW_BYTE 0x0 /* one byte width */
> -+#define PW_HALFWORD 0x1 /* 16 bits */
> -+#define PW_WORD 0x2 /* 32 bits */
> -+#define PW_NOT_USED 0x3
> -+
> -+#define CTRL_DAH 0x00000800 /* destination address
> -+ hold, for M2P */
> -+#define CTRL_SAH 0x00001000 /* source address
> -+ hold, for P2M */
> -+#define CTRL_TM_MASK 0x00006000 /* transfer mode */
> -+#define CTRL_TM_SHIFT 13
> -+
> -+#define TM_M2M 0x0 /* software initiated M2M transfer */
> -+#define TM_M2P 0x1 /* memory to ext. peripheral
> -+ or IDE/SSP */
> -+#define TM_P2M 0x2 /* ext. peripheral or IDE/SSP
> -+ to memory */
> -+#define TM_NOT_USED 0x3
> -+
> -+#define CTRL_ETDP_MASK 0x00018000 /* end of transfer/terminal
> -+ count pin direction
> -+ & polarity */
> -+#define CTRL_ETDP_SHIFT 15
> -+
> -+#define ETDP_ACT_LOW_EOT 0x0 /* pin programmed as active
> -+ * low end-of-transfer input */
> -+#define ETDP_ACT_HIGH_EOT 0x1 /* active high eot input */
> -+#define ETDP_ACT_LOW_TC 0x2 /* active low terminal count output */
> -+#define ETDP_ACT_HIGH_TC 0x3 /* active high tc output */
> -+
> -+#define CTRL_DACKP 0x00020000 /* dma acknowledge pin
> -+ polarity */
> -+#define CTRL_DREQP_MASK 0x00180000 /* dma request pin polarity */
> -+#define CTRL_DREQP_SHIFT 19
> -+
> -+#define DREQP_ACT_LOW_LEVEL 0x0 /* DREQ is active low, level
> -+ sensitive */
> -+#define DREQP_ACT_HIGH_LEVEL 0x1 /* active high, level sensitive */
> -+#define DREQP_ACT_LOW_EDGE 0x2 /* active low, edge sensitive */
> -+#define DREQP_ACT_HIGH_EDGE 0x3 /* active high, edge sensitive */
> -+
> -+
> -+#define CTRL_RSS_MASK 0x00c00000 /* request source selection */
> -+#define CTRL_RSS_SHIFT 22
> -+
> -+#define RSS_EXT 0x0 /* external dma request */
> -+#define RSS_SSP_RX 0x1 /* internal SSPRx */
> -+#define RSS_SSP_TX 0x2 /* internal SSPTx */
> -+#define RSS_IDE 0x3 /* internal IDE */
> -+
> -+#define CTRL_NO_HDSK 0x01000000 /* no handshake, required for
> -+ SSP/IDE, optional for
> -+ ext. M2P/P2M */
> -+
> -+/* interrupt register bits */
> -+#define INTR_STALL 0x1
> -+#define INTR_DONE 0x2
> -+#define INTR_NFB 0x4
> -+#define INTR_ALL 0x7
> -+
> -+/* status register bits */
> -+#define STAT_STALL 0x0001 /* waiting for software start
> -+ or device request */
> -+#define STAT_CTL_STATE_MASK 0x000e /* control fsm state */
> -+#define STAT_CTL_STATE_SHIFT 1
> -+
> -+#define CTL_STATE_IDLE 0x0
> -+#define CTL_STATE_STALL 0x1
> -+#define CTL_STATE_MEM_RD 0x2
> -+#define CTL_STATE_MEM_WR 0x3
> -+#define CTL_STATE_BWC_WAIT 0x4
> -+
> -+#define STAT_BUF_STATE_MASK 0x0030 /* buffer fsm state */
> -+#define STAT_BUF_STATE_SHIFT 4
> -+
> -+#define BUF_STATE_NO_BUF 0x0
> -+#define BUF_STATE_BUF_ON 0x1
> -+#define BUF_STATE_BUF_NEXT 0x2
> -+
> -+#define STAT_DONE 0x0040 /* transfer completed successfully
> -+ (by device or BCR is 0) */
> -+
> -+#define STAT_TCS_MASK 0x0018 /* terminal count status */
> -+#define STAT_TCS_SHIFT 7
> -+
> -+#define TCS_NONE 0x0 /* terminal count not reached
> -+ for buffer0 and buffer1 */
> -+#define TCS_BUF0 0x1 /* terminal count reached
> -+ for buffer0 */
> -+#define TCS_BUF1 0x2
> -+#define TCS_BOTH 0x3 /* terminal count reached
> -+ for both buffers */
> -+
> -+#define STAT_EOTS_MASK 0x0060 /* end of transfer status */
> -+#define STAT_EOTS_SHIFT 9
> -+
> -+#define EOTS_NONE 0x0 /* end of transfer has not been
> -+ requested by ext. periph. for
> -++ any buffer */
> -+#define EOTS_BUF0 0x1 /* eot requested for buffer0 */
> -+#define EOTS_BUF1 0x2
> -+#define EOTS_BOTH 0x3 /* eot requested for both buffers */
> -+
> -+#define STAT_NFB 0x0800 /* next frame buffer interrupt */
> -+#define STAT_NB 0x1000 /* next buffer status, inform which
> -+ buffer is free for update */
> -+#define STAT_DREQS 0x2000 /* status of dma request signal from
> -+ ext. periph or IDE/SSP request */
> -+
> -+/* IDE/SSP support */
> -+#define IDE_UDMA_DATAOUT 0x20
> -+#define IDE_UDMA_DATAIN 0x24
> -+
> -+#ifndef SSPDR
> -+#define SSPDR 0x08
> -+#endif
> -+
> -+struct m2m_channel {
> -+ char *name;
> -+ void __iomem *base;
> -+ int irq;
> -+
> -+ struct clk *clk;
> -+ spinlock_t lock;
> -+
> -+ void *client;
> -+ unsigned next_slot:1;
> -+ struct ep93xx_dma_buffer *buffer_xfer;
> -+ struct ep93xx_dma_buffer *buffer_next;
> -+ struct list_head buffers_pending;
> -+};
> -+
> -+static struct m2m_channel m2m_rxtx[] = {
> -+ {"m2m0", EP93XX_DMA_BASE + 0x0100, IRQ_EP93XX_DMAM2M0},
> -+ {"m2m1", EP93XX_DMA_BASE + 0x0140, IRQ_EP93XX_DMAM2M1},
> -+ {NULL},
> -+};
> -+
> -+
> -+static void feed_buf(struct m2m_channel *ch, struct ep93xx_dma_buffer *buf)
> -+{
> -+ struct ep93xx_dma_m2m_client *cl = ch->client;
> -+ u32 src_addr, dst_addr;
> -+
> -+ if ((cl->flags & EP93XX_DMA_M2M_DIR_MASK) == EP93XX_DMA_M2M_TX) {
> -+ src_addr = buf->bus_addr;
> -+ switch (cl->flags & EP93XX_DMA_M2M_DEV_MASK) {
> -+ case EP93XX_DMA_M2M_DEV_IDE:
> -+ dst_addr = EP93XX_IDE_PHYS_BASE + IDE_UDMA_DATAOUT;
> -+ break;
> -+ case EP93XX_DMA_M2M_DEV_SSP:
> -+ dst_addr = EP93XX_SPI_PHYS_BASE + SSPDR;
> -+ break;
> -+ default:
> -+ dst_addr = buf->bus_addr2;
> -+ break;
> -+ }
> -+ } else {
> -+ switch (cl->flags & EP93XX_DMA_M2M_DEV_MASK) {
> -+ case EP93XX_DMA_M2M_DEV_IDE:
> -+ src_addr = EP93XX_IDE_PHYS_BASE + IDE_UDMA_DATAIN;
> -+ break;
> -+ case EP93XX_DMA_M2M_DEV_SSP:
> -+ src_addr = EP93XX_SPI_PHYS_BASE + SSPDR;
> -+ break;
> -+ default:
> -+ src_addr = buf->bus_addr2;
> -+ break;
> -+ }
> -+ dst_addr = buf->bus_addr;
> -+ }
> -+
> -+ if (ch->next_slot == 0) {
> -+ DPRINTK("Writing src_addr: %08x\n", src_addr);
> -+ DPRINTK("Writing dest_addr: %08x\n", dst_addr);
> -+ DPRINTK("Writing size: %08x\n", buf->size);
> -+ writel(src_addr, ch->base + M2M_SAR_BASE0);
> -+ writel(dst_addr, ch->base + M2M_DAR_BASE0);
> -+ writel(buf->size, ch->base + M2M_BCR0);
> -+ } else {
> -+ writel(src_addr, ch->base + M2M_SAR_BASE1);
> -+ writel(dst_addr, ch->base + M2M_DAR_BASE1);
> -+ writel(buf->size, ch->base + M2M_BCR1);
> -+ }
> -+ ch->next_slot ^= 1;
> -+ DPRINTK("data size = %d, slot %d\n", buf->size, ch->next_slot ^ 1);
> -+}
> -+
> -+static void choose_buffer_xfer(struct m2m_channel *ch)
> -+{
> -+ struct ep93xx_dma_buffer *buf;
> -+
> -+ ch->buffer_xfer = NULL;
> -+ if (!list_empty(&ch->buffers_pending)) {
> -+ buf = list_entry(ch->buffers_pending.next,
> -+ struct ep93xx_dma_buffer, list);
> -+ list_del(&buf->list);
> -+ feed_buf(ch, buf);
> -+ ch->buffer_xfer = buf;
> -+ }
> -+}
> -+
> -+static void choose_buffer_next(struct m2m_channel *ch)
> -+{
> -+ struct ep93xx_dma_buffer *buf;
> -+
> -+ ch->buffer_next = NULL;
> -+ if (!list_empty(&ch->buffers_pending)) {
> -+ buf = list_entry(ch->buffers_pending.next,
> -+ struct ep93xx_dma_buffer, list);
> -+ list_del(&buf->list);
> -+ feed_buf(ch, buf);
> -+ ch->buffer_next = buf;
> -+ }
> -+}
> -+
> -+static irqreturn_t m2m_irq(int irq, void *dev_id)
> -+{
> -+ struct m2m_channel *ch = dev_id;
> -+ struct ep93xx_dma_m2m_client *cl;
> -+ u32 irq_status, dma_state, buf_state, ctl_state;
> -+
> -+ spin_lock(&ch->lock);
> -+ irq_status = readl(ch->base + M2M_INTERRUPT);
> -+ /*if ((irq_status & INTR_ALL) == 0) {
> -+ spin_unlock(&ch->lock);
> -+ return IRQ_NONE;
> -+ }*/
> -+ dma_state = readl(ch->base + M2M_STATUS);
> -+ cl = ch->client;
> -+
> -+ //printk("intr status: %08x, dma state: %08x\n", irq_status, dma_state);
> -+
> -+ DPRINTK("intr status %d, dma state %x\n",
> -+ irq_status, dma_state);
> -+
> -+ buf_state = (dma_state & STAT_BUF_STATE_MASK) >> STAT_BUF_STATE_SHIFT;
> -+ ctl_state = (dma_state & STAT_CTL_STATE_MASK) >> STAT_CTL_STATE_SHIFT;
> -+ /*printk("STAT_CTL_STATE: %d, STAT_BUF_STATE: %d\n",
> -+ * ctl_state, buf_state);*/
> -+ if (ctl_state == CTL_STATE_STALL &&
> -+ buf_state == BUF_STATE_NO_BUF &&
> -+ dma_state & STAT_DONE) {
> -+ /* transfer completed successfully (done) */
> -+
> -+
> -+ /* send client the done command */
> -+ if (cl->buffer_finished) {
> -+ cl->buffer_finished(cl->cookie, ch->buffer_xfer, ch->buffer_xfer->size, 0);
> -+ }
> -+
> -+ writel(0, ch->base + M2M_INTERRUPT);
> -+ choose_buffer_xfer(ch);
> -+ choose_buffer_next(ch);
> -+ if (ch->buffer_xfer != NULL) {
> -+ /* retrigger if more buffers exist */
> -+ if ((cl->flags & EP93XX_DMA_M2M_DEV_MASK) ==
> -+ EP93XX_DMA_M2M_DEV_MEM) {
> -+ DPRINTK("Writing start1 to M2M control\n");
> -+ writel(readl(ch->base + M2M_CONTROL) |
> -+ CTRL_START, ch->base + M2M_CONTROL);
> -+ readl(ch->base + M2M_CONTROL);
> -+ }
> -+ } else {
> -+ DPRINTK("DISABLING DMA: dreqs state: %d\n", dma_state & STAT_DREQS);
> -+
> -+ writel(readl(ch->base + M2M_CONTROL)
> -+ & ~CTRL_ENABLE, ch->base + M2M_CONTROL);
> -+ readl(ch->base + M2M_CONTROL);
> -+ }
> -+ } else if (ctl_state == CTL_STATE_MEM_RD &&
> -+ buf_state == BUF_STATE_BUF_ON &&
> -+ dma_state & STAT_NFB) {
> -+ /* next frame buffer */
> -+ if (cl->buffer_finished) {
> -+ cl->buffer_finished(cl->cookie, ch->buffer_xfer, 0, 0);
> -+ }
> -+ ch->buffer_xfer = ch->buffer_next;
> -+ choose_buffer_next(ch);
> -+ }
> -+
> -+ if (cl->buffer_started && ch->buffer_xfer != NULL) {
> -+ cl->buffer_started(cl->cookie, ch->buffer_xfer);
> -+ }
> -+
> -+ spin_unlock(&ch->lock);
> -+ return IRQ_HANDLED;
> -+}
> -+
> -+static struct m2m_channel *find_free_channel(struct ep93xx_dma_m2m_client *cl, int channel_spec)
> -+{
> -+ struct m2m_channel *ch = m2m_rxtx;
> -+ int i;
> -+
> -+#if 0
> -+ /* BMS: This code isn't particularly clear; look like it asserts
> -+ * that a requested channel must not share the same data direction
> -+ * as a previously requested channel - which makes sense for the SSP,
> -+ * but not at all for direct hardware transferrs
> -+ */
> -+ for (i = 0; ch[i].base; i++) {
> -+ struct ep93xx_dma_m2m_client *cl2;
> -+
> -+ cl2 = ch[i].client;
> -+ if (cl2 != NULL) {
> -+ int port;
> -+
> -+ /* two the same devices in the same direction
> -+ are not allowed
> -+ (two "memory devices" should be allowed) */
> -+ port = cl2->flags & (EP93XX_DMA_M2M_DEV_MASK |
> -+ EP93XX_DMA_M2M_DIR_MASK);
> -+ if (port == (cl->flags & (EP93XX_DMA_M2M_DEV_MASK |
> -+ EP93XX_DMA_M2M_DIR_MASK)))
> -+ return NULL;
> -+ }
> -+ }
> -+#endif
> -+
> -+ if (channel_spec == EP93XX_DMA_M2M_REQUIRES_CH_ANY) {
> -+ for (i = 0; ch[i].base; i++) {
> -+ if (ch[i].client == NULL)
> -+ return ch + i;
> -+ }
> -+ } else if (channel_spec == EP93XX_DMA_M2M_REQUIRES_CH_0) {
> -+ if (ch[0].client == NULL) {
> -+ return &(ch[0]);
> -+ }
> -+ } else if (channel_spec == EP93XX_DMA_M2M_REQUIRES_CH_1) {
> -+ if (ch[1].client == NULL) {
> -+ return &(ch[1]);
> -+ }
> -+ } else {
> -+ printk(KERN_ERR "ep93xx-m2m dma channel request: unknown channel spec\n");
> -+ }
> -+ return NULL;
> -+}
> -+
> -+static u32 set_direction_reg(u32 outv, u32 flags)
> -+{
> -+ switch (flags & EP93XX_DMA_M2M_DEV_MASK) {
> -+ case EP93XX_DMA_M2M_DEV_EXT:
> -+ outv &= ~(CTRL_SAH | CTRL_DAH | CTRL_TM_MASK);
> -+
> -+ if (flags & EP93XX_DMA_M2M_EXT_FIFO)
> -+ outv |= (flags & EP93XX_DMA_M2M_DIR_MASK) ==
> -+ EP93XX_DMA_M2M_TX ? CTRL_DAH : CTRL_SAH;
> -+
> -+ outv |= (((flags & EP93XX_DMA_M2M_DIR_MASK) ==
> -+ EP93XX_DMA_M2M_TX) ? TM_M2P : TM_P2M) <<
> -+ CTRL_TM_SHIFT;
> -+
> -+ break;
> -+ case EP93XX_DMA_M2M_DEV_IDE:
> -+ outv &= ~(CTRL_SAH | CTRL_DAH | CTRL_TM_MASK | CTRL_PWSC_MASK);
> -+ if ((flags & EP93XX_DMA_M2M_DIR_MASK) == EP93XX_DMA_M2M_TX) {
> -+ outv |= (2 << CTRL_PWSC_SHIFT) & CTRL_PWSC_MASK;
> -+ outv |= CTRL_DAH;
> -+ outv |= TM_M2P << CTRL_TM_SHIFT;
> -+ } else {
> -+ outv |= (1 << CTRL_PWSC_SHIFT) & CTRL_PWSC_MASK;
> -+ outv |= CTRL_SAH;
> -+ outv |= TM_P2M << CTRL_TM_SHIFT;
> -+ }
> -+ break;
> -+ case EP93XX_DMA_M2M_DEV_SSP:
> -+ outv &= ~(CTRL_SAH | CTRL_DAH | CTRL_TM_MASK | CTRL_RSS_MASK);
> -+ if ((flags & EP93XX_DMA_M2M_DIR_MASK) == EP93XX_DMA_M2M_TX) {
> -+ outv |= TM_M2P << CTRL_TM_SHIFT;
> -+ outv |= CTRL_DAH;
> -+ outv |= RSS_SSP_TX << CTRL_RSS_SHIFT;
> -+ } else {
> -+ outv |= TM_P2M << CTRL_TM_SHIFT;
> -+ outv |= CTRL_SAH;
> -+ outv |= RSS_SSP_RX << CTRL_RSS_SHIFT;
> -+ }
> -+ break;
> -+ case EP93XX_DMA_M2M_DEV_MEM:
> -+ break;
> -+ }
> -+ return outv;
> -+}
> -+
> -+static void channel_enable(struct m2m_channel *ch)
> -+{
> -+ struct ep93xx_dma_m2m_client *cl = ch->client;
> -+ u32 outv = 0;
> -+
> -+ clk_enable(ch->clk);
> -+
> -+ /* set peripheral wait state mask - IFF specified in control word */
> -+ outv |= (cl->flags & CTRL_PWSC_MASK);
> -+ outv |= (cl->flags & EP93XX_DREQ_MASK);
> -+
> -+ DPRINTK("Set outv to: %08x\n",outv);
> -+
> -+ switch (cl->flags & EP93XX_DMA_M2M_DEV_MASK) {
> -+ case EP93XX_DMA_M2M_DEV_EXT:
> -+ switch (cl->flags & EP93XX_DMA_M2M_EXT_WIDTH_MASK) {
> -+ case EP93XX_DMA_M2M_EXT_WIDTH_BYTE:
> -+ outv |= PW_BYTE << CTRL_PW_SHIFT;
> -+ break;
> -+ case EP93XX_DMA_M2M_EXT_WIDTH_2BYTES:
> -+ outv |= PW_HALFWORD << CTRL_PW_SHIFT;
> -+ break;
> -+ case EP93XX_DMA_M2M_EXT_WIDTH_4BYTES:
> -+ outv |= PW_WORD << CTRL_PW_SHIFT;
> -+ break;
> -+ }
> -+ /* if NO_HDSK then PWSC, if not, then DREQ, DACK, TC/DEOT */
> -+ if (cl->flags & EP93XX_DMA_M2M_EXT_NO_HDSK) {
> -+ outv |= CTRL_NO_HDSK;
> -+ /* TODO: wait states */
> -+ } else {
> -+ /* TODO: regular handshaking */
> -+ }
> -+ outv |= RSS_EXT << CTRL_RSS_SHIFT;
> -+ break;
> -+ case EP93XX_DMA_M2M_DEV_IDE:
> -+ /* NO_HDSK, PWSC, PW, SAH, DAH */
> -+ outv |= CTRL_NO_HDSK;
> -+ outv |= PW_WORD << CTRL_PW_SHIFT;
> -+ /* PWSC = 1 for read, PWSC = 2 for write in UDMA */
> -+ outv |= RSS_IDE << CTRL_RSS_SHIFT;
> -+ break;
> -+ case EP93XX_DMA_M2M_DEV_SSP:
> -+ outv |= CTRL_NO_HDSK;
> -+ outv |= PW_HALFWORD << CTRL_PW_SHIFT;
> -+ outv |= (8 << CTRL_PWSC_SHIFT) & CTRL_PWSC_MASK;
> -+ break;
> -+ case EP93XX_DMA_M2M_DEV_MEM:
> -+ switch (cl->flags & EP93XX_DMA_M2M_MEM_SPEED_MASK) {
> -+ case EP93XX_DMA_M2M_MEM_SPEED_FULL:
> -+ outv |= BWC_FULL << CTRL_BWC_SHIFT;
> -+ break;
> -+ case EP93XX_DMA_M2M_MEM_SPEED_HALF:
> -+ outv |= BWC_32768 << CTRL_BWC_SHIFT;
> -+ break;
> -+ case EP93XX_DMA_M2M_MEM_SPEED_QUART:
> -+ outv |= BWC_16384 << CTRL_BWC_SHIFT;
> -+ break;
> -+ case EP93XX_DMA_M2M_MEM_SPEED_SLOW:
> -+ outv |= BWC_16 << CTRL_BWC_SHIFT;
> -+ break;
> -+ }
> -+ outv |= (cl->flags & EP93XX_DMA_M2M_MEM_FILL) ? CTRL_SCT : 0;
> -+ outv |= TM_M2M << CTRL_TM_SHIFT;
> -+ break;
> -+ }
> -+
> -+ // debug code
> -+ DPRINTK("PRE-Enable, status is: %08x\n", readl(ch->base+M2M_STATUS));
> -+
> -+ outv = set_direction_reg(outv, cl->flags);
> -+ /* STALL interrupt must be enabled */
> -+ outv |= CTRL_NFB_INT_EN | CTRL_DONE_INT_EN | CTRL_STALL_INT_EN;
> -+
> -+ writel(outv, ch->base + M2M_CONTROL);
> -+ outv = readl(ch->base + M2M_CONTROL);
> -+ DPRINTK("channel enable, writing control reg = %08x\n", outv);
> -+}
> -+
> -+static void channel_disable(struct m2m_channel *ch)
> -+{
> -+ u32 v;
> -+
> -+ DPRINTK("Disabling channel\n");
> -+ v = readl(ch->base + M2M_CONTROL);
> -+
> -+ writel(v & ~(CTRL_NFB_INT_EN | CTRL_DONE_INT_EN | CTRL_STALL_INT_EN),
> -+ ch->base + M2M_CONTROL);
> -+
> -+ v = readl(ch->base + M2M_CONTROL);
> -+
> -+ while (readl(ch->base + M2M_STATUS) & STAT_NFB) {
> -+ cpu_relax();
> -+ }
> -+
> -+ writel(0, ch->base + M2M_CONTROL);
> -+
> -+ v = readl(ch->base + M2M_CONTROL);
> -+
> -+ while (readl(ch->base + M2M_STATUS) & STAT_STALL) {
> -+ cpu_relax();
> -+ }
> -+
> -+ clk_disable(ch->clk);
> -+}
> -+
> -+void ep93xx_dma_m2m_set_direction(struct ep93xx_dma_m2m_client *cl,
> -+ int direction)
> -+{
> -+ struct m2m_channel *ch = cl->channel;
> -+ u32 outv;
> -+ unsigned long flags;
> -+
> -+ direction &= EP93XX_DMA_M2M_DIR_MASK;
> -+
> -+ spin_lock_irqsave(&ch->lock, flags);
> -+
> -+ cl->flags &= ~EP93XX_DMA_M2M_DIR_MASK;
> -+ cl->flags |= direction;
> -+
> -+ outv = readl(ch->base + M2M_CONTROL);
> -+ outv = set_direction_reg(outv, cl->flags);
> -+ writel(outv, ch->base + M2M_CONTROL);
> -+ outv = readl(ch->base + M2M_CONTROL);
> -+ DPRINTK("set_direction: configured control reg = %08x\n", outv);
> -+
> -+ spin_unlock_irqrestore(&ch->lock, flags);
> -+}
> -+EXPORT_SYMBOL_GPL(ep93xx_dma_m2m_set_direction);
> -+
> -+int ep93xx_dma_m2m_client_register(struct ep93xx_dma_m2m_client *cl, int channel_spec)
> -+{
> -+ struct m2m_channel *ch;
> -+ int err;
> -+
> -+ ch = find_free_channel(cl, channel_spec);
> -+ if (ch == NULL)
> -+ return -1;
> -+
> -+ err = request_irq(ch->irq, m2m_irq, IRQF_DISABLED, cl->name ? : "dma-m2m", ch);
> -+ if (err)
> -+ return err;
> -+
> -+ ch->client = cl;
> -+ ch->next_slot = 0;
> -+ ch->buffer_xfer = NULL;
> -+ ch->buffer_next = NULL;
> -+ INIT_LIST_HEAD(&ch->buffers_pending);
> -+
> -+ cl->channel = ch;
> -+
> -+ channel_enable(ch);
> -+
> -+ return 0;
> -+}
> -+EXPORT_SYMBOL_GPL(ep93xx_dma_m2m_client_register);
> -+
> -+void ep93xx_dma_m2m_client_unregister(struct ep93xx_dma_m2m_client *cl)
> -+{
> -+ struct m2m_channel *ch = cl->channel;
> -+
> -+ channel_disable(ch);
> -+ free_irq(ch->irq, ch);
> -+ ch->client = NULL;
> -+}
> -+EXPORT_SYMBOL_GPL(ep93xx_dma_m2m_client_unregister);
> -+
> -+void ep93xx_dma_m2m_submit(struct ep93xx_dma_m2m_client *cl,
> -+ struct ep93xx_dma_buffer *buf)
> -+{
> -+ struct m2m_channel *ch = cl->channel;
> -+ unsigned long flags;
> -+
> -+ spin_lock_irqsave(&ch->lock, flags);
> -+
> -+ if (ch->buffer_xfer == NULL) {
> -+ ch->buffer_xfer = buf;
> -+ feed_buf(ch, buf);
> -+ if (readl(ch->base + M2M_CONTROL) & CTRL_ENABLE) {
> -+ DPRINTK("CTRL_ENABLE\n");
> -+ if ((cl->flags & EP93XX_DMA_M2M_DEV_MASK) ==
> -+ EP93XX_DMA_M2M_DEV_MEM) {
> -+ DPRINTK("WRITING START2 TO M2M control\n");
> -+ writel(readl(ch->base + M2M_CONTROL) |
> -+ CTRL_START, ch->base + M2M_CONTROL);
> -+ readl(ch->base + M2M_CONTROL);
> -+ }
> -+ }
> -+ } else if (ch->buffer_next == NULL) {
> -+ ch->buffer_next = buf;
> -+ feed_buf(ch, buf);
> -+ } else
> -+ list_add_tail(&buf->list, &ch->buffers_pending);
> -+ spin_unlock_irqrestore(&ch->lock, flags);
> -+}
> -+EXPORT_SYMBOL_GPL(ep93xx_dma_m2m_submit);
> -+
> -+void ep93xx_dma_m2m_start(struct ep93xx_dma_m2m_client *cl)
> -+{
> -+ struct m2m_channel *ch = cl->channel;
> -+ u32 v;
> -+
> -+ unsigned long flags;
> -+
> -+ spin_lock_irqsave(&ch->lock, flags);
> -+
> -+ writel(readl(ch->base + M2M_STATUS), ch->base+M2M_STATUS);
> -+ //printk("At start, status is: %08x\n", readl(ch->base + M2M_STATUS));
> -+
> -+ v = readl(ch->base + M2M_CONTROL) | CTRL_ENABLE;
> -+ writel(v, ch->base + M2M_CONTROL);
> -+ v = readl(ch->base + M2M_CONTROL);
> -+ if (ch->buffer_xfer != NULL) {
> -+ if (((cl->flags & EP93XX_DMA_M2M_DEV_MASK) ==
> -+ EP93XX_DMA_M2M_DEV_MEM)) {
> -+ DPRINTK("WRITING START3 to M2M controller\n");
> -+ v |= CTRL_START;
> -+ writel(v, ch->base + M2M_CONTROL);
> -+ v = readl(ch->base + M2M_CONTROL);
> -+ }
> -+ }
> -+
> -+ spin_unlock_irqrestore(&ch->lock, flags);
> -+}
> -+EXPORT_SYMBOL_GPL(ep93xx_dma_m2m_start);
> -+
> -+void ep93xx_dma_m2m_stop(struct ep93xx_dma_m2m_client *cl)
> -+{
> -+ struct m2m_channel *ch = cl->channel;
> -+ u32 v;
> -+ unsigned long flags;
> -+
> -+ spin_lock_irqsave(&ch->lock, flags);
> -+
> -+ DPRINTK("Stopping DMA by disabling CTRL_ENABLE\n");
> -+ v = readl(ch->base + M2M_CONTROL) & ~CTRL_ENABLE;
> -+ writel(v, ch->base + M2M_CONTROL);
> -+ readl(ch->base + M2M_CONTROL);
> -+ DPRINTK("configured control reg = %08x\n", v);
> -+
> -+ spin_unlock_irqrestore(&ch->lock, flags);
> -+}
> -+EXPORT_SYMBOL_GPL(ep93xx_dma_m2m_stop);
> -+
> -+void ep93xx_dma_m2m_flush(struct ep93xx_dma_m2m_client *cl)
> -+{
> -+ struct m2m_channel *ch = cl->channel;
> -+
> -+ channel_disable(ch);
> -+ ch->next_slot = 0;
> -+ ch->buffer_xfer = NULL;
> -+ ch->buffer_next = NULL;
> -+ INIT_LIST_HEAD(&ch->buffers_pending);
> -+ channel_enable(ch);
> -+}
> -+EXPORT_SYMBOL_GPL(ep93xx_dma_m2m_flush);
> -+
> -+static int init_channel(struct m2m_channel *ch)
> -+{
> -+ ch->clk = clk_get(NULL, ch->name);
> -+ if (IS_ERR(ch->clk))
> -+ return PTR_ERR(ch->clk);
> -+
> -+ spin_lock_init(&ch->lock);
> -+ ch->client = NULL;
> -+
> -+ return 0;
> -+}
> -+
> -+static int __init ep93xx_dma_m2m_init(void)
> -+{
> -+ int i;
> -+ int ret;
> -+
> -+ for (i = 0; m2m_rxtx[i].base; i++) {
> -+ ret = init_channel(m2m_rxtx + i);
> -+ if (ret)
> -+ return ret;
> -+ }
> -+
> -+ pr_info("M2M DMA subsystem initialized\n");
> -+ return 0;
> -+}
> -+arch_initcall(ep93xx_dma_m2m_init);
> -diff --git a/arch/arm/mach-ep93xx/include/mach/dma.h b/arch/arm/mach-ep93xx/include/mach/dma.h
> -index 3a5961d..6a3552b 100644
> ---- a/arch/arm/mach-ep93xx/include/mach/dma.h
> -+++ b/arch/arm/mach-ep93xx/include/mach/dma.h
> -@@ -11,6 +11,7 @@
> - struct ep93xx_dma_buffer {
> - struct list_head list;
> - u32 bus_addr;
> -+ u32 bus_addr2; /* only used by M2M */
> - u16 size;
> - };
> -
> -@@ -28,6 +29,7 @@ struct ep93xx_dma_m2p_client {
> - void *channel;
> - };
> -
> -+/* flags (m2p client) */
> - #define EP93XX_DMA_M2P_PORT_I2S1 0x00
> - #define EP93XX_DMA_M2P_PORT_I2S2 0x01
> - #define EP93XX_DMA_M2P_PORT_AAC1 0x02
> -@@ -45,6 +47,58 @@ struct ep93xx_dma_m2p_client {
> - #define EP93XX_DMA_M2P_IGNORE_ERROR 0x40
> - #define EP93XX_DMA_M2P_ERROR_MASK 0x60
> -
> -+
> -+struct ep93xx_dma_m2m_client {
> -+ char *name;
> -+ u32 flags;
> -+ void *cookie;
> -+ void (*buffer_started)(void *cookie,
> -+ struct ep93xx_dma_buffer *buf);
> -+ void (*buffer_finished)(void *cookie,
> -+ struct ep93xx_dma_buffer *buf,
> -+ int bytes, int error);
> -+
> -+ /* Internal to the DMA code. */
> -+ void *channel;
> -+};
> -+
> -+/* flags (m2m client) */
> -+#define EP93XX_DMA_M2M_RX 0x000 /* read from periph./memory */
> -+#define EP93XX_DMA_M2M_TX 0x004 /* write to periph./memory */
> -+#define EP93XX_DMA_M2M_DIR_MASK 0x004 /* direction mask */
> -+#define EP93XX_DMA_M2M_DEV_EXT 0x000 /* external peripheral */
> -+#define EP93XX_DMA_M2M_DEV_SSP 0x001 /* internal SSP */
> -+#define EP93XX_DMA_M2M_DEV_IDE 0x002 /* internal IDE */
> -+#define EP93XX_DMA_M2M_DEV_MEM 0x003 /* memory to memory transfer */
> -+#define EP93XX_DMA_M2M_DEV_MASK 0x003 /* device mask */
> -+#define EP93XX_DMA_M2M_EXT_FIFO 0x008 /* external peripheral is one location fifo */
> -+#define EP93XX_DMA_M2M_EXT_NO_HDSK 0x010 /* external peripheral doesn't require regular handshaking protocol */
> -+#define EP93XX_DMA_M2M_EXT_WIDTH_MASK 0x300
> -+#define EP93XX_DMA_M2M_EXT_WIDTH_BYTE 0x000 /* external peripheral transfer is one byte width */
> -+#define EP93XX_DMA_M2M_EXT_WIDTH_2BYTES 0x100
> -+#define EP93XX_DMA_M2M_EXT_WIDTH_4BYTES 0x200
> -+#define EP93XX_DMA_M2M_MEM_SPEED_FULL 0x000 /* M2M bandwidth control */
> -+#define EP93XX_DMA_M2M_MEM_SPEED_HALF 0x040 /* half bus bandwidth */
> -+#define EP93XX_DMA_M2M_MEM_SPEED_QUART 0x080 /* quarter bus bandwidth */
> -+#define EP93XX_DMA_M2M_MEM_SPEED_SLOW 0x0c0 /* slowest speed */
> -+#define EP93XX_DMA_M2M_MEM_SPEED_MASK 0x0c0 /* memory speed mask */
> -+#define EP93XX_DMA_M2M_MEM_FILL 0x020 /* M2M is one location to block fill */
> -+
> -+/* FIXME */
> -+#define CTRL_PWSC_MASK 0xfe000000 /* peripheral wait states count */
> -+#define CTRL_PWSC_SHIFT 25
> -+#define EP93XX_DREQ_SHIFT 19
> -+#define EP93XX_DREQ_MASK 0x00180000
> -+#define EP93XX_DMA_M2M_DREQ_LS_L (00 << EP93XX_DREQ_SHIFT)
> -+#define EP93XX_DMA_M2M_DREQ_LS_H (01 << EP93XX_DREQ_SHIFT)
> -+#define EP93XX_DMA_M2M_DREQ_ES_L (10 << EP93XX_DREQ_SHIFT)
> -+#define EP93XX_DMA_M2M_DREQ_ES_H (11 << EP93XX_DREQ_SHIFT)
> -+
> -+/* See ep93xx_dma_m2m_client_register (channel_spec) */
> -+#define EP93XX_DMA_M2M_REQUIRES_CH_ANY 0
> -+#define EP93XX_DMA_M2M_REQUIRES_CH_0 1
> -+#define EP93XX_DMA_M2M_REQUIRES_CH_1 2
> -+
> - int ep93xx_dma_m2p_client_register(struct ep93xx_dma_m2p_client *m2p);
> - void ep93xx_dma_m2p_client_unregister(struct ep93xx_dma_m2p_client *m2p);
> - void ep93xx_dma_m2p_submit(struct ep93xx_dma_m2p_client *m2p,
> -@@ -53,4 +107,15 @@ void ep93xx_dma_m2p_submit_recursive(struct ep93xx_dma_m2p_client *m2p,
> - struct ep93xx_dma_buffer *buf);
> - void ep93xx_dma_m2p_flush(struct ep93xx_dma_m2p_client *m2p);
> -
> -+int ep93xx_dma_m2m_client_register(struct ep93xx_dma_m2m_client *m2m,
> -+ int channel_spec);
> -+void ep93xx_dma_m2m_client_unregister(struct ep93xx_dma_m2m_client *m2m);
> -+void ep93xx_dma_m2m_submit(struct ep93xx_dma_m2m_client *m2m,
> -+ struct ep93xx_dma_buffer *buf);
> -+void ep93xx_dma_m2m_flush(struct ep93xx_dma_m2m_client *m2m);
> -+void ep93xx_dma_m2m_start(struct ep93xx_dma_m2m_client *m2m);
> -+void ep93xx_dma_m2m_stop(struct ep93xx_dma_m2m_client *m2m);
> -+void ep93xx_dma_m2m_set_direction(struct ep93xx_dma_m2m_client *m2m,
> -+ int direction);
> -+
> - #endif /* __ASM_ARCH_DMA_H */
> ---
> -1.7.0.4
> -
> diff --git a/recipes/linux/linux-2.6.36/ts72xx/0006-ts72xx_rs485.patch b/recipes/linux/linux-2.6.36/ts72xx/0006-ts72xx_rs485.patch
> deleted file mode 100644
> index e7ab169..0000000
> --- a/recipes/linux/linux-2.6.36/ts72xx/0006-ts72xx_rs485.patch
> +++ /dev/null
> @@ -1,223 +0,0 @@
> -From 42019ca5561ebd18d47d8811cf06d3cae77ca982 Mon Sep 17 00:00:00 2001
> -From: Matthieu Crapet <mcrapet@gmail.com>
> -Date: Thu, 10 Jun 2010 17:00:12 +0200
> -Subject: [PATCH 06/24] ts72xx_rs485
> -MIME-Version: 1.0
> -Content-Type: text/plain; charset=UTF-8
> -Content-Transfer-Encoding: 8bit
> -
> -Crude hack...
> -
> -Signed-off-by: Petr Štetiar <ynezz@true.cz>
> ----
> - arch/arm/include/asm/ioctls.h | 3 +
> - drivers/serial/Kconfig | 8 +++
> - drivers/serial/amba-pl010.c | 124 ++++++++++++++++++++++++++++++++++++++++-
> - 3 files changed, 134 insertions(+), 1 deletions(-)
> -
> -diff --git a/arch/arm/include/asm/ioctls.h b/arch/arm/include/asm/ioctls.h
> -index 0b30894..a0d7401 100644
> ---- a/arch/arm/include/asm/ioctls.h
> -+++ b/arch/arm/include/asm/ioctls.h
> -@@ -74,6 +74,9 @@
> - #define TIOCGICOUNT 0x545D /* read serial port inline interrupt counts */
> - #define FIOQSIZE 0x545E
> -
> -+#define TIOC_SBCC485 0x545F /* TS72xx RTS/485 mode clear */
> -+#define TIOC_SBCS485 0x5460 /* TS72xx RTS/485 mode set */
> -+
> - /* Used for packet mode */
> - #define TIOCPKT_DATA 0
> - #define TIOCPKT_FLUSHREAD 1
> -diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig
> -index 12900f7..d1bff25 100644
> ---- a/drivers/serial/Kconfig
> -+++ b/drivers/serial/Kconfig
> -@@ -296,6 +296,14 @@ config SERIAL_AMBA_PL010_CONSOLE
> - your boot loader (lilo or loadlin) about how to pass options to the
> - kernel at boot time.)
> -
> -+config SERIAL_AMBA_PL010_TS72XX
> -+ bool "Support for RS-485 on AMBA serial port (for TS-72XX SBC)"
> -+ depends on SERIAL_AMBA_PL010 != n && MACH_TS72XX
> -+ help
> -+ This add support for RS-485 on some Technologic System SBC.
> -+
> -+ If unsure, say N.
> -+
> - config SERIAL_AMBA_PL011
> - tristate "ARM AMBA PL011 serial port support"
> - depends on ARM_AMBA
> -diff --git a/drivers/serial/amba-pl010.c b/drivers/serial/amba-pl010.c
> -index 2904aa0..9135233 100644
> ---- a/drivers/serial/amba-pl010.c
> -+++ b/drivers/serial/amba-pl010.c
> -@@ -51,6 +51,10 @@
> -
> - #include <asm/io.h>
> -
> -+#if defined(CONFIG_SERIAL_AMBA_PL010_TS72XX)
> -+#include <mach/ts72xx.h>
> -+#endif
> -+
> - #define UART_NR 8
> -
> - #define SERIAL_AMBA_MAJOR 204
> -@@ -65,6 +69,11 @@
> - #define UART_DUMMY_RSR_RX 256
> - #define UART_PORT_SIZE 64
> -
> -+#if defined(CONFIG_SERIAL_AMBA_PL010_TS72XX)
> -+static void __iomem *ts_rs485_data9_register;
> -+static void __iomem *ts_rs485_control_register;
> -+#endif
> -+
> - /*
> - * We wrap our port structure around the generic uart_port.
> - */
> -@@ -386,7 +395,7 @@ pl010_set_termios(struct uart_port *port, struct ktermios *termios,
> - /*
> - * Ask the core to calculate the divisor for us.
> - */
> -- baud = uart_get_baud_rate(port, termios, old, 0, uap->port.uartclk/16);
> -+ baud = uart_get_baud_rate(port, termios, old, 0, uap->port.uartclk/16);
> - quot = uart_get_divisor(port, baud);
> -
> - switch (termios->c_cflag & CSIZE) {
> -@@ -529,6 +538,105 @@ static int pl010_verify_port(struct uart_port *port, struct serial_struct *ser)
> - return ret;
> - }
> -
> -+
> -+#if defined(CONFIG_SERIAL_AMBA_PL010_TS72XX)
> -+static int ts72xx_rs485_init(void)
> -+{
> -+ ts_rs485_data9_register = ioremap(TS72XX_RS485_MODE_PHYS_BASE, 4096);
> -+ if (ts_rs485_data9_register == NULL) {
> -+ return -1;
> -+ }
> -+
> -+ ts_rs485_control_register = ioremap(TS72XX_RS485_CONTROL_PHYS_BASE, 4096);
> -+ if (ts_rs485_control_register == NULL) {
> -+ iounmap(ts_rs485_data9_register);
> -+ return -1;
> -+ }
> -+
> -+ return 0;
> -+}
> -+
> -+static int ts72xx_auto485(struct uart_port *port, unsigned int cmd, unsigned long *arg)
> -+{
> -+ int baud, cflag, mode;
> -+ int datalength;
> -+
> -+ mode = (int)*arg;
> -+ if (!is_rs485_installed()) {
> -+ printk("amba-pl010.c: this board does not support RS485 auto mode\n");
> -+ return -EINVAL;
> -+ }
> -+
> -+ if (port->line != 1) {
> -+ printk("amba-pl010.c: auto RS485 mode is only supported on second port (/dev/ttyAM1)\n");
> -+ return -EINVAL;
> -+ }
> -+
> -+ datalength = 8;
> -+ cflag = port->state->port.tty->termios->c_cflag;
> -+ if (cflag & PARENB)
> -+ datalength++;
> -+
> -+ if (cflag & CSTOPB)
> -+ datalength++;
> -+
> -+ baud = tty_get_baud_rate(port->state->port.tty);
> -+
> -+ switch (cmd) {
> -+ case TIOC_SBCC485:
> -+ if ((mode & TS72XX_RS485_AUTO485FD) || (mode & TS72XX_RS485_AUTO485HD)) {
> -+ printk("amba-pl010.c: unsetting auto RS485 mode\n");
> -+ __raw_writew(TS72XX_RS485_MODE_RS232, ts_rs485_control_register);
> -+ __raw_writew(TS72XX_RS485_MODE_RS232, ts_rs485_data9_register);
> -+ }
> -+ break;
> -+ case TIOC_SBCS485:
> -+ if (mode & TS72XX_RS485_AUTO485FD) {
> -+ printk ("amba-pl010.c: setting FULL duplex auto RS485 mode\n");
> -+ __raw_writew(TS72XX_RS485_MODE_FD, ts_rs485_control_register);
> -+ if (datalength > 8)
> -+ __raw_writew(TS72XX_RS485_MODE_FD, ts_rs485_data9_register);
> -+ } else if (mode & TS72XX_RS485_AUTO485HD) {
> -+ printk("amba-pl010.c: setting HALF DUPLEX auto RS485 mode\n");
> -+ switch (baud) {
> -+ case 9600:
> -+ __raw_writew(TS72XX_RS485_MODE_9600_HD, ts_rs485_control_register);
> -+ break;
> -+ case 19200:
> -+ __raw_writew(TS72XX_RS485_MODE_19200_HD, ts_rs485_control_register);
> -+ break;
> -+ case 57600:
> -+ __raw_writew(TS72XX_RS485_MODE_57600_HD, ts_rs485_control_register);
> -+ break;
> -+ case 115200:
> -+ __raw_writew(TS72XX_RS485_MODE_115200_HD, ts_rs485_control_register);
> -+ break;
> -+ default:
> -+ printk("amba-pl010.c: %d baud rate is not supported for auto RS485 mode\n", baud);
> -+ return -1;
> -+ }
> -+ if (datalength > 8)
> -+ __raw_writew(TS72XX_RS485_MODE_FD, ts_rs485_data9_register);
> -+ }
> -+ break;
> -+ }
> -+
> -+ return 0;
> -+}
> -+
> -+static int pl010_ioctl(struct uart_port *port, unsigned int cmd, unsigned long arg)
> -+{
> -+ switch (cmd) {
> -+ case TIOC_SBCC485:
> -+ case TIOC_SBCS485:
> -+ return ts72xx_auto485(port, cmd, (unsigned long *)arg);
> -+ }
> -+
> -+ return -ENOIOCTLCMD;
> -+}
> -+#endif /* CONFIG_SERIAL_AMBA_PL010_TS72XX */
> -+
> -+
> - static struct uart_ops amba_pl010_pops = {
> - .tx_empty = pl010_tx_empty,
> - .set_mctrl = pl010_set_mctrl,
> -@@ -547,6 +655,9 @@ static struct uart_ops amba_pl010_pops = {
> - .request_port = pl010_request_port,
> - .config_port = pl010_config_port,
> - .verify_port = pl010_verify_port,
> -+#if defined(CONFIG_SERIAL_AMBA_PL010_TS72XX)
> -+ .ioctl = pl010_ioctl,
> -+#endif
> - };
> -
> - static struct uart_amba_port *amba_ports[UART_NR];
> -@@ -805,6 +916,17 @@ static int __init pl010_init(void)
> - ret = uart_register_driver(&amba_reg);
> - if (ret == 0) {
> - ret = amba_driver_register(&pl010_driver);
> -+
> -+ #if defined(CONFIG_SERIAL_AMBA_PL010_TS72XX)
> -+ if (!ret && is_rs485_installed()) {
> -+ ret = ts72xx_rs485_init();
> -+ if (ret)
> -+ printk("amba-pl010.c: ts72xx_rs485_init() failed\n");
> -+ else
> -+ printk("amba-pl010.c: auto RS485 mode initialized\n");
> -+ }
> -+ #endif
> -+
> - if (ret)
> - uart_unregister_driver(&amba_reg);
> - }
> ---
> -1.7.0.4
> -
> diff --git a/recipes/linux/linux-2.6.36/ts72xx/0007-ts72xx_ts_ser1.patch b/recipes/linux/linux-2.6.36/ts72xx/0007-ts72xx_ts_ser1.patch
> deleted file mode 100644
> index 570009b..0000000
> --- a/recipes/linux/linux-2.6.36/ts72xx/0007-ts72xx_ts_ser1.patch
> +++ /dev/null
> @@ -1,264 +0,0 @@
> -From be2d6dfb434c137187d2572d8bf9264748720ece Mon Sep 17 00:00:00 2001
> -From: Matthieu Crapet <mcrapet@gmail.com>
> -Date: Wed, 16 Jun 2010 14:44:44 +0200
> -Subject: [PATCH 07/24] ts72xx_ts_ser1
> -MIME-Version: 1.0
> -Content-Type: text/plain; charset=UTF-8
> -Content-Transfer-Encoding: 8bit
> -
> -TS-SER1 - Serial Port PC/104 peripheral
> -
> -Signed-off-by: Petr Štetiar <ynezz@true.cz>
> ----
> - drivers/serial/8250_ts_ser1.c | 197 +++++++++++++++++++++++++++++++++++++++++
> - drivers/serial/Kconfig | 17 ++++
> - drivers/serial/Makefile | 1 +
> - 3 files changed, 215 insertions(+), 0 deletions(-)
> - create mode 100644 drivers/serial/8250_ts_ser1.c
> -
> -diff --git a/drivers/serial/8250_ts_ser1.c b/drivers/serial/8250_ts_ser1.c
> -new file mode 100644
> -index 0000000..e5fe616
> ---- /dev/null
> -+++ b/drivers/serial/8250_ts_ser1.c
> -@@ -0,0 +1,197 @@
> -+/*
> -+ * linux/drivers/serial/8250_ts_ser1.c
> -+ * Technologic Systems TS-SER1 support.
> -+ *
> -+ * (c) Copyright 2006-2008 Matthieu Crapet <mcrapet@gmail.com>
> -+ * Data taken from include/asm-i386/serial.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.
> -+ *
> -+ * Pin Number:
> -+ * 1 DCD
> -+ * 2 Receive data
> -+ * 3 Trasmit data
> -+ * 4 DTR
> -+ * 5 Signal Ground
> -+ * 6 DSR
> -+ * 7 RTS
> -+ * 8 CTS
> -+ * 9 RI
> -+ */
> -+
> -+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
> -+
> -+#include <linux/module.h>
> -+#include <linux/init.h>
> -+#include <linux/serial_8250.h>
> -+#include <linux/irq.h>
> -+#include <linux/io.h>
> -+#include <mach/hardware.h>
> -+#include <mach/ts72xx.h>
> -+#include <mach/gpio.h>
> -+
> -+#define TS72XX_SER1_IO_PHYS_BASE (TS72XX_PC104_8BIT_IO_PHYS_BASE)
> -+#define TS72XX_SER1_IO_SIZE (TS72XX_PC104_8BIT_IO_SIZE)
> -+
> -+#define TS_SER1_PORT_COM3 0x3E8
> -+#define TS_SER1_PORT_COM4 0x2E8
> -+#define TS_SER1_PORT_COM5 0x3A8
> -+
> -+/* Value to write in 16550A scratch register */
> -+#define MARKER_BYTE 0xAA /* or 0x55 */
> -+
> -+#define PORT(_base,_irq) \
> -+{ \
> -+ .iobase = _base, \
> -+ .membase = (void __iomem *)0, \
> -+ .irq = _irq, \
> -+ .uartclk = 1843200, \
> -+ .iotype = UPIO_PORT, \
> -+ .flags = UPF_BOOT_AUTOCONF, \
> -+}
> -+/* Note: IRQ can be shared (see CONFIG_SERIAL_8250_SHARE_IRQ) */
> -+
> -+
> -+static struct plat_serial8250_port ts72xx_ser1_data_com3[] = {
> -+ PORT(TS_SER1_PORT_COM3, 0),
> -+ { },
> -+};
> -+
> -+static struct plat_serial8250_port ts72xx_ser1_data_com4[] = {
> -+ PORT(TS_SER1_PORT_COM4, 0),
> -+ { },
> -+};
> -+
> -+static struct plat_serial8250_port ts72xx_ser1_data_com5[] = {
> -+ PORT(TS_SER1_PORT_COM5, 0),
> -+ { },
> -+};
> -+
> -+
> -+static int ts_ser1_irq = CONFIG_SERIAL_8250_TS_SER1_IRQ; // 5, 6 or 7
> -+static struct platform_device *serial8250_ts_ser1_dev;
> -+
> -+
> -+static int __init ts_ser1_init(void)
> -+{
> -+ struct plat_serial8250_port *comX = NULL;
> -+ void __iomem *iomem;
> -+
> -+ int ret = -ENODEV;
> -+ int n = 0; // COM number as printed on TS-SER1 pcb
> -+
> -+ iomem = ioremap(TS72XX_SER1_IO_PHYS_BASE, TS72XX_SER1_IO_SIZE);
> -+
> -+ if (iomem != NULL) {
> -+ __raw_writeb(MARKER_BYTE, iomem + TS_SER1_PORT_COM3 + 7);
> -+ if (__raw_readb(iomem + TS_SER1_PORT_COM3 + 7) == MARKER_BYTE) {
> -+ comX = ts72xx_ser1_data_com3;
> -+ n = 3;
> -+ } else {
> -+ __raw_writeb(MARKER_BYTE, iomem + TS_SER1_PORT_COM4 + 7);
> -+ if (__raw_readb(iomem + TS_SER1_PORT_COM4 + 7) == MARKER_BYTE) {
> -+ comX = ts72xx_ser1_data_com4;
> -+ n = 4;
> -+ } else {
> -+ __raw_writeb(MARKER_BYTE, iomem + TS_SER1_PORT_COM5 + 7);
> -+ if (__raw_readb(iomem + TS_SER1_PORT_COM5 + 7) == MARKER_BYTE) {
> -+ comX = ts72xx_ser1_data_com5;
> -+ n = 5;
> -+ }
> -+ }
> -+ }
> -+
> -+ if (comX) {
> -+ switch (ts_ser1_irq) {
> -+ case 5:
> -+ ret = gpio_request(EP93XX_GPIO_LINE_F(3), "TS-SER1");
> -+ if (ret < 0) {
> -+ pr_err("gpio_request failed, try another irq\n");
> -+ goto init_error;
> -+ }
> -+ gpio_direction_input(EP93XX_GPIO_LINE_F(3));
> -+ comX->irq = gpio_to_irq(EP93XX_GPIO_LINE_F(3));
> -+ set_irq_type(comX->irq, IRQ_TYPE_EDGE_RISING);
> -+ break;
> -+ case 6:
> -+ comX->irq = IRQ_EP93XX_EXT1;
> -+ break;
> -+ case 7:
> -+ comX->irq = IRQ_EP93XX_EXT3;
> -+ break;
> -+ default:
> -+ pr_err("wrong specified irq\n");
> -+ goto init_error;
> -+ }
> -+
> -+ comX->iobase += (unsigned long)iomem; // virtual address
> -+
> -+ } else {
> -+ pr_err("can't detect COM number\n");
> -+ goto init_error;
> -+ }
> -+
> -+ /* create platform_device structure */
> -+ serial8250_ts_ser1_dev = platform_device_alloc("serial8250", n);
> -+ if (!serial8250_ts_ser1_dev) {
> -+ ret = -ENOMEM;
> -+ goto init_error;
> -+ }
> -+
> -+ ret = platform_device_add_data(serial8250_ts_ser1_dev, comX,
> -+ 2 * sizeof(struct plat_serial8250_port));
> -+ if (ret) {
> -+ platform_device_put(serial8250_ts_ser1_dev);
> -+ goto init_error;
> -+ }
> -+
> -+ ret = platform_device_add(serial8250_ts_ser1_dev);
> -+ if (ret) {
> -+ platform_device_put(serial8250_ts_ser1_dev);
> -+ goto init_error;
> -+ }
> -+
> -+ platform_set_drvdata(serial8250_ts_ser1_dev, iomem);
> -+ return 0;
> -+ }
> -+
> -+init_error:
> -+ if (iomem) {
> -+ iounmap(iomem);
> -+ iomem = NULL;
> -+ }
> -+ return ret;
> -+}
> -+
> -+static void __exit ts_ser1_exit(void)
> -+{
> -+ struct platform_device *pdev = serial8250_ts_ser1_dev;
> -+ void __iomem *iomem = platform_get_drvdata(pdev);
> -+
> -+ serial8250_ts_ser1_dev = NULL;
> -+
> -+ platform_device_unregister(pdev);
> -+
> -+ iounmap(iomem);
> -+ if (ts_ser1_irq == 5)
> -+ gpio_free(EP93XX_GPIO_LINE_F(3));
> -+}
> -+
> -+module_init(ts_ser1_init);
> -+module_exit(ts_ser1_exit);
> -+
> -+module_param(ts_ser1_irq, int, 0);
> -+MODULE_PARM_DESC(ts_ser1_irq, "TS-SER1 IRQ, default=" __MODULE_STRING(CONFIG_SERIAL_8250_TS_SER1_IRQ) ")");
> -+
> -+MODULE_AUTHOR("Matthieu Crapet <mcrapet@gmail.com>");
> -+MODULE_DESCRIPTION("8250 serial probe module for TS-SER1 (TS-72xx)");
> -+MODULE_LICENSE("GPL");
> -+MODULE_VERSION("0.5");
> -diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig
> -index d1bff25..5667462 100644
> ---- a/drivers/serial/Kconfig
> -+++ b/drivers/serial/Kconfig
> -@@ -267,6 +267,23 @@ config SERIAL_8250_RM9K
> - port hardware found on MIPS RM9122 and similar processors.
> - If unsure, say N.
> -
> -+config SERIAL_8250_TS_SER1
> -+ tristate "Support TS-SER1 (for TS-72XX SBC)"
> -+ depends on SERIAL_8250 != n && MACH_TS72XX
> -+ help
> -+ Say Y here if you have a TS-SER1 PC/104 peripheral.
> -+ COM number will be configured automaticaly.
> -+
> -+ To compile this driver as a module, choose M here: the module
> -+ will be called 8250_ts_ser1.
> -+
> -+config SERIAL_8250_TS_SER1_IRQ
> -+ int "Selected IRQ (5, 6 or 7)"
> -+ depends on SERIAL_8250_TS_SER1
> -+ default "5"
> -+ help
> -+ Enter jumper IRQ configuration
> -+
> - comment "Non-8250 serial port support"
> -
> - config SERIAL_AMBA_PL010
> -diff --git a/drivers/serial/Makefile b/drivers/serial/Makefile
> -index 1ca4fd5..e379ab4 100644
> ---- a/drivers/serial/Makefile
> -+++ b/drivers/serial/Makefile
> -@@ -28,6 +28,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_8250_TS_SER1) += 8250_ts_ser1.o
> - obj-$(CONFIG_SERIAL_AMBA_PL010) += amba-pl010.o
> - obj-$(CONFIG_SERIAL_AMBA_PL011) += amba-pl011.o
> - obj-$(CONFIG_SERIAL_CLPS711X) += clps711x.o
> ---
> -1.7.0.4
> -
> diff --git a/recipes/linux/linux-2.6.36/ts72xx/0008-ts72xx_ts_eth100.patch b/recipes/linux/linux-2.6.36/ts72xx/0008-ts72xx_ts_eth100.patch
> deleted file mode 100644
> index b2fb7d2..0000000
> --- a/recipes/linux/linux-2.6.36/ts72xx/0008-ts72xx_ts_eth100.patch
> +++ /dev/null
> @@ -1,278 +0,0 @@
> -From 4c63820dec1699305f30a4096a0baa550d273a87 Mon Sep 17 00:00:00 2001
> -From: Matthieu Crapet <mcrapet@gmail.com>
> -Date: Fri, 18 Jun 2010 17:39:09 +0200
> -Subject: [PATCH 08/24] ts72xx_ts_eth100
> -MIME-Version: 1.0
> -Content-Type: text/plain; charset=UTF-8
> -Content-Transfer-Encoding: 8bit
> -
> -TS-ETH100 - 10/100 Ethernet PC/104 peripheral
> -
> -Signed-off-by: Petr Štetiar <ynezz@true.cz>
> ----
> - drivers/net/Kconfig | 10 ++
> - drivers/net/Makefile | 1 +
> - drivers/net/ax88796.c | 8 ++-
> - drivers/net/ax88796_ts_eth100.c | 190 +++++++++++++++++++++++++++++++++++++++
> - 4 files changed, 208 insertions(+), 1 deletions(-)
> - create mode 100644 drivers/net/ax88796_ts_eth100.c
> -
> -diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
> -index 5db667c..448c823 100644
> ---- a/drivers/net/Kconfig
> -+++ b/drivers/net/Kconfig
> -@@ -248,6 +248,16 @@ config AX88796_93CX6
> - help
> - Select this if your platform comes with an external 93CX6 eeprom.
> -
> -+config AX88796_TS_ETH100
> -+ tristate "Support for TS-ETH100 (TS-72XX SBC)"
> -+ depends on AX88796 && MACH_TS72XX
> -+ help
> -+ Say Y here if you have a TS-ETH100 PC/104 peripheral.
> -+ IRQ numbers and I/O address will be configurated automatically.
> -+
> -+ To compile this driver as a module, choose M here: the module
> -+ will be called ax88796_ts_eth100.
> -+
> - config MACE
> - tristate "MACE (Power Mac ethernet) support"
> - depends on PPC_PMAC && PPC32
> -diff --git a/drivers/net/Makefile b/drivers/net/Makefile
> -index 3e8f150..eb4765b 100644
> ---- a/drivers/net/Makefile
> -+++ b/drivers/net/Makefile
> -@@ -143,6 +143,7 @@ obj-$(CONFIG_B44) += b44.o
> - obj-$(CONFIG_FORCEDETH) += forcedeth.o
> - obj-$(CONFIG_NE_H8300) += ne-h8300.o 8390.o
> - obj-$(CONFIG_AX88796) += ax88796.o
> -+obj-$(CONFIG_AX88796_TS_ETH100) += ax88796_ts_eth100.o
> - obj-$(CONFIG_BCM63XX_ENET) += bcm63xx_enet.o
> -
> - obj-$(CONFIG_TSI108_ETH) += tsi108_eth.o
> -diff --git a/drivers/net/ax88796.c b/drivers/net/ax88796.c
> -index 20e946b..33527f7 100644
> ---- a/drivers/net/ax88796.c
> -+++ b/drivers/net/ax88796.c
> -@@ -810,7 +810,9 @@ static int ax_remove(struct platform_device *_dev)
> - ax = to_ax_dev(dev);
> -
> - unregister_netdev(dev);
> -- free_irq(dev->irq, dev);
> -+ if (ax->running) { // already freed in ax_close?
> -+ free_irq(dev->irq, dev);
> -+ }
> -
> - iounmap(ei_status.mem);
> - release_resource(ax->mem);
> -@@ -936,7 +938,11 @@ static int ax_probe(struct platform_device *pdev)
> - goto exit_mem2;
> - }
> -
> -+ #if defined(CONFIG_AX88796_TS_ETH100) || defined(CONFIG_AX88796_TS_ETH100_MODULE)
> -+ ei_status.reg_offset[0x10] = ax->map2 - ei_status.mem + 0x10; /* don't know why, but +0x20 works too */
> -+ #else
> - ei_status.reg_offset[0x1f] = ax->map2 - ei_status.mem;
> -+ #endif
> - }
> -
> - /* got resources, now initialise and register device */
> -diff --git a/drivers/net/ax88796_ts_eth100.c b/drivers/net/ax88796_ts_eth100.c
> -new file mode 100644
> -index 0000000..448b3e3
> ---- /dev/null
> -+++ b/drivers/net/ax88796_ts_eth100.c
> -@@ -0,0 +1,190 @@
> -+/*
> -+ * linux/drivers/net/ax88796_ts_eth100.c
> -+ * Technologic Systems TS-ETH100 support.
> -+ *
> -+ * (c) Copyright 2008 Matthieu Crapet <mcrapet@gmail.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.
> -+ */
> -+
> -+#include <linux/module.h>
> -+#include <linux/init.h>
> -+#include <linux/platform_device.h>
> -+#include <linux/irq.h>
> -+#include <linux/io.h>
> -+#include <net/ax88796.h>
> -+#include <mach/ts72xx.h>
> -+#include <mach/gpio.h>
> -+
> -+#define TS72XX_ETH100_IO8_PHYS_BASE (TS72XX_PC104_8BIT_IO_PHYS_BASE)
> -+#define TS72XX_ETH100_IO8_SIZE (TS72XX_PC104_8BIT_IO_SIZE)
> -+#define TS72XX_ETH100_IO16_PHYS_BASE (TS72XX_PC104_16BIT_IO_PHYS_BASE)
> -+#define TS72XX_ETH100_IO16_SIZE (TS72XX_PC104_16BIT_IO_SIZE)
> -+
> -+/* Technologic systems I/O space */
> -+#define TS_ETH100_PLD_0 0x100
> -+#define TS_ETH100_PLD_1 0x110
> -+#define TS_ETH100_PLD_2 0x120
> -+#define TS_ETH100_PLD_3 0x130
> -+
> -+/* NE2000 I/O space */
> -+#define TS_ETH100_MAC_0 0x200
> -+#define TS_ETH100_MAC_1 0x240
> -+#define TS_ETH100_MAC_2 0x300
> -+#define TS_ETH100_MAC_3 0x340
> -+
> -+/* Board identifier must be 5 ; PLD revision should be 1 */
> -+#define is_eth100_present(__iomem, __offset) \
> -+ (((__raw_readb(__iomem + __offset) & 0xF) == 0x5) && \
> -+ ((__raw_readb(__iomem + __offset + 4) & 0xF) == 0x1))
> -+
> -+/* Jumpers status (SRAM control register) */
> -+#define read_irq(__iomem, __offset) \
> -+ (__raw_readb(__iomem + __offset + 8) & 0xE)
> -+
> -+
> -+static u32 offsets[0x20] = {
> -+ 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
> -+};
> -+
> -+static struct ax_plat_data ts72xx_eth100_asix_data = {
> -+ .flags = AXFLG_HAS_93CX6,
> -+ .wordlength = 2,
> -+ .dcr_val = 0x48,
> -+ .rcr_val = 0x40,
> -+ .reg_offsets = offsets,
> -+};
> -+
> -+static struct resource ts72xx_eth100_resource[] = {
> -+ [0] = {
> -+ .start = TS72XX_ETH100_IO8_PHYS_BASE,
> -+ .end = TS72XX_ETH100_IO8_PHYS_BASE + 0x40 - 1,
> -+ .flags = IORESOURCE_MEM
> -+ },
> -+ [1] = { /* 0x10 is NE_DATAPORT is 16-bit access */
> -+ .start = TS72XX_ETH100_IO16_PHYS_BASE,
> -+ .end = TS72XX_ETH100_IO16_PHYS_BASE + 0x40 - 1,
> -+ .flags = IORESOURCE_MEM
> -+ },
> -+ [2] = {
> -+ .start = IRQ_EP93XX_EXT1,
> -+ .end = IRQ_EP93XX_EXT1,
> -+ .flags = IORESOURCE_IRQ
> -+ }
> -+};
> -+
> -+static int ts_eth100_irq; // 2 [IRQ 5], 4 [IRQ 6] or 8 [IRQ 7] (jumper configuration)
> -+
> -+
> -+static void ts72xx_eth100_release(struct device *dev)
> -+{
> -+ /* nothing to do (no kfree) because we have static struct */
> -+}
> -+
> -+static struct platform_device ts72xx_eth100_device_asix = {
> -+ .name = "ax88796",
> -+ .id = 0,
> -+ .num_resources = ARRAY_SIZE(ts72xx_eth100_resource),
> -+ .resource = ts72xx_eth100_resource,
> -+ .dev = {
> -+ .platform_data = &ts72xx_eth100_asix_data,
> -+ .release = ts72xx_eth100_release,
> -+ }
> -+};
> -+
> -+static int __init ts_eth100_init(void)
> -+{
> -+ void __iomem *iomem;
> -+ struct platform_device *ethX = NULL;
> -+
> -+ iomem = ioremap(TS72XX_ETH100_IO8_PHYS_BASE, TS72XX_ETH100_IO8_SIZE);
> -+ if (iomem != NULL) {
> -+ ethX = &ts72xx_eth100_device_asix;
> -+
> -+ if (is_eth100_present(iomem, TS_ETH100_PLD_0)) {
> -+ ethX->resource[0].start += TS_ETH100_MAC_0;
> -+ ethX->resource[0].end += TS_ETH100_MAC_0;
> -+ ethX->resource[1].start += TS_ETH100_MAC_0;
> -+ ethX->resource[1].end += TS_ETH100_MAC_0;
> -+ ts_eth100_irq = read_irq(iomem, TS_ETH100_PLD_0);
> -+ } else if(is_eth100_present(iomem, TS_ETH100_PLD_1)) {
> -+ ethX->resource[0].start += TS_ETH100_MAC_1;
> -+ ethX->resource[0].end += TS_ETH100_MAC_1;
> -+ ethX->resource[1].start += TS_ETH100_MAC_1;
> -+ ethX->resource[1].end += TS_ETH100_MAC_1;
> -+ ts_eth100_irq = read_irq(iomem, TS_ETH100_PLD_1);
> -+ } else if(is_eth100_present(iomem, TS_ETH100_PLD_2)) {
> -+ ethX->resource[0].start += TS_ETH100_MAC_2;
> -+ ethX->resource[0].end += TS_ETH100_MAC_2;
> -+ ethX->resource[1].start += TS_ETH100_MAC_2;
> -+ ethX->resource[1].end += TS_ETH100_MAC_2;
> -+ ts_eth100_irq = read_irq(iomem, TS_ETH100_PLD_2);
> -+ } else if(is_eth100_present(iomem, TS_ETH100_PLD_3)) {
> -+ ethX->resource[0].start += TS_ETH100_MAC_3;
> -+ ethX->resource[0].end += TS_ETH100_MAC_3;
> -+ ethX->resource[1].start += TS_ETH100_MAC_3;
> -+ ethX->resource[1].end += TS_ETH100_MAC_3;
> -+ ts_eth100_irq = read_irq(iomem, TS_ETH100_PLD_3);
> -+ } else {
> -+ ethX = NULL;
> -+ }
> -+
> -+ /* Translate IRQ number */
> -+ if (ethX != NULL) {
> -+ int ret, irq = 0;
> -+ switch (ts_eth100_irq) {
> -+ case 0x2: /* IRQ5 */
> -+ irq = gpio_to_irq(EP93XX_GPIO_LINE_F(3));
> -+ ret = gpio_request(irq, "TS-ETH100");
> -+ if (ret < 0) {
> -+ ethX = NULL;
> -+ goto init_error;
> -+ } else {
> -+ gpio_direction_input(irq);
> -+ set_irq_type(irq, IRQ_TYPE_EDGE_RISING);
> -+ }
> -+ break;
> -+ case 0x4: /* IRQ6 */
> -+ irq = IRQ_EP93XX_EXT1;
> -+ break;
> -+ case 0x8: /* IRQ7 */
> -+ default:
> -+ irq = IRQ_EP93XX_EXT3;
> -+ }
> -+ ethX->resource[2].start = irq;
> -+ ethX->resource[2].end = irq;
> -+ }
> -+init_error:
> -+ iounmap(iomem);
> -+ }
> -+
> -+ return ((ethX == NULL) ? -ENODEV :
> -+ platform_device_register(&ts72xx_eth100_device_asix));
> -+}
> -+
> -+
> -+static void __exit ts_eth100_exit(void)
> -+{
> -+ platform_device_unregister(&ts72xx_eth100_device_asix);
> -+ if (ts_eth100_irq == 2)
> -+ gpio_free(EP93XX_GPIO_LINE_F(3));
> -+}
> -+
> -+module_init(ts_eth100_init);
> -+module_exit(ts_eth100_exit);
> -+
> -+MODULE_AUTHOR("Matthieu Crapet <mcrapet@gmail.com>");
> -+MODULE_DESCRIPTION("Asix 88796 ethernet probe module for TS-ETH100 (TS-72xx)");
> -+MODULE_LICENSE("GPL");
> -+MODULE_VERSION("0.21");
> ---
> -1.7.0.4
> -
> diff --git a/recipes/linux/linux-2.6.36/ts72xx/0009-ts72xx_pata.patch b/recipes/linux/linux-2.6.36/ts72xx/0009-ts72xx_pata.patch
> deleted file mode 100644
> index fb891d0..0000000
> --- a/recipes/linux/linux-2.6.36/ts72xx/0009-ts72xx_pata.patch
> +++ /dev/null
> @@ -1,437 +0,0 @@
> -From dca6d3223e20806a2ec22704a6909d72c9ba3ef5 Mon Sep 17 00:00:00 2001
> -From: =?UTF-8?q?Petr=20=C5=A0tetiar?= <ynezz@true.cz>
> -Date: Sat, 23 Oct 2010 19:08:37 +0200
> -Subject: [PATCH 09/24] ts72xx_pata
> -MIME-Version: 1.0
> -Content-Type: text/plain; charset=UTF-8
> -Content-Transfer-Encoding: 8bit
> -
> -Support:
> -TS-7200 - Compact flash
> -TS-9600 - IDE interface PC/104 peripheral
> -
> -Signed-off-by: Petr Štetiar <ynezz@true.cz>
> ----
> - drivers/ata/Kconfig | 20 +++++
> - drivers/ata/Makefile | 3 +
> - drivers/ata/pata_ts7200_cf.c | 92 ++++++++++++++++++++++++
> - drivers/ata/pata_ts72xx.c | 161 ++++++++++++++++++++++++++++++++++++++++++
> - drivers/ata/pata_ts9600.c | 95 +++++++++++++++++++++++++
> - 5 files changed, 371 insertions(+), 0 deletions(-)
> - create mode 100644 drivers/ata/pata_ts7200_cf.c
> - create mode 100644 drivers/ata/pata_ts72xx.c
> - create mode 100644 drivers/ata/pata_ts9600.c
> -
> -diff --git a/drivers/ata/Kconfig b/drivers/ata/Kconfig
> -index 11ec911..6c84389 100644
> ---- a/drivers/ata/Kconfig
> -+++ b/drivers/ata/Kconfig
> -@@ -862,5 +862,25 @@ config PATA_LEGACY
> -
> - If unsure, say N.
> -
> -+config PATA_TS72XX
> -+ bool "TS72XX ATA support"
> -+ depends on ARCH_EP93XX && MACH_TS72XX
> -+ help
> -+ This option enables support for ATA devices on Technologic Systems SBC.
> -+
> -+config PATA_TS7200_CF
> -+ tristate "TS-7200 Compact Flash support"
> -+ depends on PATA_TS72XX
> -+ help
> -+ This option enables support for the compact flash control on
> -+ Technologic System TS-7200 SBC.
> -+
> -+config PATA_TS9600
> -+ tristate "TS-9600 IDE interface support"
> -+ depends on PATA_TS72XX && BLK_DEV_IDE_TS9600 != y
> -+ help
> -+ This option enables support for Technologic Systems TS-9600 PC/104 IDE interface.
> -+
> - endif # ATA_SFF
> -+
> - endif # ATA
> -diff --git a/drivers/ata/Makefile b/drivers/ata/Makefile
> -index d5df04a..eb36415 100644
> ---- a/drivers/ata/Makefile
> -+++ b/drivers/ata/Makefile
> -@@ -91,6 +91,9 @@ obj-$(CONFIG_PATA_RZ1000) += pata_rz1000.o
> - obj-$(CONFIG_PATA_SAMSUNG_CF) += pata_samsung_cf.o
> -
> - obj-$(CONFIG_PATA_PXA) += pata_pxa.o
> -+obj-$(CONFIG_PATA_TS72XX) += pata_ts72xx.o
> -+obj-$(CONFIG_PATA_TS7200_CF) += pata_ts7200_cf.o
> -+obj-$(CONFIG_PATA_TS9600) += pata_ts9600.o
> -
> - # Should be last but two libata driver
> - obj-$(CONFIG_PATA_ACPI) += pata_acpi.o
> -diff --git a/drivers/ata/pata_ts7200_cf.c b/drivers/ata/pata_ts7200_cf.c
> -new file mode 100644
> -index 0000000..4126682
> ---- /dev/null
> -+++ b/drivers/ata/pata_ts7200_cf.c
> -@@ -0,0 +1,92 @@
> -+/*
> -+ * Technologic Systems TS-7200 Compact Flash PATA device driver.
> -+ *
> -+ * (c) Copyright 2008 Matthieu Crapet <mcrapet@gmail.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.
> -+ *
> -+ */
> -+
> -+#include <linux/kernel.h>
> -+#include <linux/module.h>
> -+#include <linux/libata.h>
> -+#include <scsi/scsi_host.h>
> -+#include <linux/platform_device.h>
> -+#include <linux/dma-mapping.h>
> -+
> -+#include <asm/io.h>
> -+#include <asm/irq.h>
> -+#include <mach/ts72xx.h>
> -+
> -+#define DRV_NAME "pata_ts7200_cf"
> -+#define DRV_VERSION "0.21"
> -+
> -+
> -+static void pata_ts7200_cf_release(struct device *dev)
> -+{
> -+ /* nothing to do (no kfree) because we have static struct */
> -+}
> -+
> -+static struct resource ts7200_cf_resources[] = {
> -+ [0] = {
> -+ .start = TS7200_CF_CMD_PHYS_BASE,
> -+ .end = TS7200_CF_CMD_PHYS_BASE + 8,
> -+ .flags = IORESOURCE_MEM,
> -+ },
> -+ [1] = {
> -+ .start = TS7200_CF_AUX_PHYS_BASE,
> -+ .end = TS7200_CF_AUX_PHYS_BASE + 1,
> -+ .flags = IORESOURCE_MEM,
> -+ },
> -+ [2] = {
> -+ .start = TS7200_CF_DATA_PHYS_BASE,
> -+ .end = TS7200_CF_DATA_PHYS_BASE + 2,
> -+ .flags = IORESOURCE_MEM,
> -+ },
> -+ [3] = {
> -+ .start = IRQ_EP93XX_EXT0, /* pin 103 of EP9301 */
> -+ .end = IRQ_EP93XX_EXT0,
> -+ .flags = IORESOURCE_IRQ,
> -+ }
> -+};
> -+
> -+
> -+static struct platform_device ts7200_cf_device = {
> -+ .name = "ts72xx-ide",
> -+ .id = 0,
> -+ .dev = {
> -+ .dma_mask = &ts7200_cf_device.dev.coherent_dma_mask,
> -+ .coherent_dma_mask = DMA_BIT_MASK(32),
> -+ .release = pata_ts7200_cf_release,
> -+ },
> -+ .num_resources = ARRAY_SIZE(ts7200_cf_resources),
> -+ .resource = ts7200_cf_resources,
> -+};
> -+
> -+
> -+static __init int pata_ts7200_cf_init(void)
> -+{
> -+ return (board_is_ts7200()) ? \
> -+ platform_device_register(&ts7200_cf_device) : -ENODEV;
> -+}
> -+
> -+static __exit void pata_ts7200_cf_exit(void)
> -+{
> -+ platform_device_unregister(&ts7200_cf_device);
> -+}
> -+
> -+module_init(pata_ts7200_cf_init);
> -+module_exit(pata_ts7200_cf_exit);
> -+
> -+MODULE_AUTHOR("Matthieu Crapet <mcrapet@gmail.com>");
> -+MODULE_DESCRIPTION("TS-7200 CF PATA device driver");
> -+MODULE_LICENSE("GPL");
> -+MODULE_VERSION(DRV_VERSION);
> -diff --git a/drivers/ata/pata_ts72xx.c b/drivers/ata/pata_ts72xx.c
> -new file mode 100644
> -index 0000000..d540029
> ---- /dev/null
> -+++ b/drivers/ata/pata_ts72xx.c
> -@@ -0,0 +1,161 @@
> -+/*
> -+ * TS-72XX PATA driver for Technologic Systems boards.
> -+ *
> -+ * Based on pata_platform.c by Paul Mundt &
> -+ * Alessandro Zummo <a.zummo@towertech.it>
> -+ * and old pata-ts72xx.c by Alessandro Zummo <a.zummo@towertech.it>
> -+ *
> -+ * (c) Copyright 2008 Matthieu Crapet <mcrapet@gmail.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.
> -+ *
> -+ */
> -+
> -+#include <linux/kernel.h>
> -+#include <linux/module.h>
> -+#include <linux/platform_device.h>
> -+#include <linux/interrupt.h>
> -+#include <scsi/scsi_host.h>
> -+#include <linux/ata.h>
> -+#include <linux/libata.h>
> -+
> -+#define DRV_NAME "pata_ts72xx"
> -+#define DRV_VERSION "2.01"
> -+
> -+
> -+/*
> -+ * Provide our own set_mode() as we don't want to change anything that has
> -+ * already been configured..
> -+ */
> -+static int ts72xx_set_mode(struct ata_link *link, struct ata_device **unused)
> -+{
> -+ struct ata_device *dev;
> -+
> -+ ata_for_each_dev(dev, link, ENABLED) {
> -+ if (ata_dev_enabled(dev)) {
> -+ /* We don't really care */
> -+ dev->pio_mode = dev->xfer_mode = XFER_PIO_0;
> -+ dev->xfer_shift = ATA_SHIFT_PIO;
> -+ dev->flags |= ATA_DFLAG_PIO;
> -+ ata_dev_printk(dev, KERN_INFO, "configured for PIO\n");
> -+ }
> -+ }
> -+ return 0;
> -+}
> -+
> -+static struct scsi_host_template ts72xx_sht = {
> -+ ATA_PIO_SHT(DRV_NAME),
> -+};
> -+
> -+static struct ata_port_operations ts72xx_port_ops = {
> -+ .inherits = &ata_sff_port_ops,
> -+ .set_mode = ts72xx_set_mode,
> -+};
> -+
> -+static __devinit int ts72xx_pata_probe(struct platform_device *pdev)
> -+{
> -+ struct ata_host *host;
> -+ struct ata_port *ap;
> -+ int irq;
> -+
> -+ struct resource *pata_cmd = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> -+ struct resource *pata_aux = platform_get_resource(pdev, IORESOURCE_MEM, 1);
> -+ struct resource *pata_data = platform_get_resource(pdev, IORESOURCE_MEM, 2);
> -+
> -+ if (!pata_cmd || !pata_aux || !pata_data) {
> -+ dev_err(&pdev->dev, "missing resource(s)\n");
> -+ return -EINVAL;
> -+ }
> -+
> -+ irq = platform_get_irq(pdev, 0);
> -+ if (irq < 0)
> -+ irq = 0; /* no irq */
> -+
> -+ /*
> -+ * Now that that's out of the way, wire up the port
> -+ */
> -+ host = ata_host_alloc(&pdev->dev, 1);
> -+ if (!host)
> -+ return -ENOMEM;
> -+ ap = host->ports[0];
> -+
> -+ ap->ops = &ts72xx_port_ops;
> -+ ap->pio_mask = 0x1f; /* PIO0-4 */
> -+ ap->flags |= ATA_FLAG_SLAVE_POSS;
> -+
> -+ /*
> -+ * Use polling mode if there's no IRQ
> -+ */
> -+ if (!irq) {
> -+ ap->flags |= ATA_FLAG_PIO_POLLING;
> -+ ata_port_desc(ap, "no IRQ, using PIO polling");
> -+ }
> -+
> -+ ap->ioaddr.cmd_addr = devm_ioremap(&pdev->dev, pata_cmd->start,
> -+ pata_cmd->end - pata_cmd->start + 1);
> -+ ap->ioaddr.ctl_addr = devm_ioremap(&pdev->dev, pata_aux->start,
> -+ pata_aux->end - pata_aux->start + 1);
> -+
> -+ if (!ap->ioaddr.cmd_addr || !ap->ioaddr.ctl_addr) {
> -+ dev_err(&pdev->dev, "failed to map IO/CTL base\n");
> -+ return -ENOMEM;
> -+ }
> -+
> -+ ap->ioaddr.altstatus_addr = ap->ioaddr.ctl_addr;
> -+
> -+ ata_sff_std_ports(&ap->ioaddr);
> -+ ap->ioaddr.data_addr = devm_ioremap(&pdev->dev, pata_data->start,
> -+ pata_data->end - pata_data->start + 1);
> -+
> -+ ata_port_desc(ap, "mmio cmd 0x%llx ctl 0x%llx",
> -+ (unsigned long long)pata_cmd->start,
> -+ (unsigned long long)pata_aux->start);
> -+
> -+ return ata_host_activate(host, irq, irq ? ata_sff_interrupt : NULL,
> -+ 0 /* irq flags */, &ts72xx_sht);
> -+}
> -+
> -+static __devexit int ts72xx_pata_remove(struct platform_device *pdev)
> -+{
> -+ struct device *dev = &pdev->dev;
> -+ struct ata_host *host = dev_get_drvdata(dev);
> -+
> -+ ata_host_detach(host);
> -+
> -+ return 0;
> -+}
> -+
> -+static struct platform_driver ts72xx_pata_platform_driver = {
> -+ .probe = ts72xx_pata_probe,
> -+ .remove = __devexit_p(ts72xx_pata_remove),
> -+ .driver = {
> -+ .name = "ts72xx-ide",
> -+ .owner = THIS_MODULE,
> -+ },
> -+};
> -+
> -+static int __init ts72xx_pata_init(void)
> -+{
> -+ return platform_driver_register(&ts72xx_pata_platform_driver);
> -+}
> -+
> -+static void __exit ts72xx_pata_exit(void)
> -+{
> -+ platform_driver_unregister(&ts72xx_pata_platform_driver);
> -+}
> -+
> -+MODULE_AUTHOR("Matthieu Crapet <mcrapet@gmail.com>");
> -+MODULE_DESCRIPTION("low-level driver for TS-72xx device PATA");
> -+MODULE_LICENSE("GPL");
> -+MODULE_VERSION(DRV_VERSION);
> -+
> -+module_init(ts72xx_pata_init);
> -+module_exit(ts72xx_pata_exit);
> -diff --git a/drivers/ata/pata_ts9600.c b/drivers/ata/pata_ts9600.c
> -new file mode 100644
> -index 0000000..7a70550
> ---- /dev/null
> -+++ b/drivers/ata/pata_ts9600.c
> -@@ -0,0 +1,95 @@
> -+/*
> -+ * Technologic Systems TS-9600 PATA device driver.
> -+ *
> -+ * (c) Copyright 2008 Matthieu Crapet <mcrapet@gmail.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.
> -+ *
> -+ */
> -+
> -+#include <linux/kernel.h>
> -+#include <linux/module.h>
> -+#include <linux/libata.h>
> -+#include <scsi/scsi_host.h>
> -+#include <linux/platform_device.h>
> -+#include <linux/dma-mapping.h>
> -+
> -+#include <asm/io.h>
> -+#include <asm/irq.h>
> -+#include <mach/ts72xx.h>
> -+
> -+#define DRV_NAME "pata_ts9600"
> -+#define DRV_VERSION "0.21"
> -+
> -+#define TS9600_IDE_IO (TS72XX_PC104_8BIT_IO_PHYS_BASE + 0x1F0)
> -+#define TS9600_IDE_DATA (TS72XX_PC104_16BIT_IO_PHYS_BASE + 0x1F0)
> -+#define TS9600_IDE_IRQ IRQ_EP93XX_EXT3 // IRQ7 (no other possibility for arm)
> -+
> -+
> -+static void pata_ts9600_release(struct device *dev)
> -+{
> -+ /* nothing to do (no kfree) because we have static struct */
> -+}
> -+
> -+static struct resource ts9600_resources[] = {
> -+ [0] = {
> -+ .start = TS9600_IDE_IO,
> -+ .end = TS9600_IDE_IO + 8,
> -+ .flags = IORESOURCE_MEM,
> -+ },
> -+ [1] = {
> -+ .start = TS9600_IDE_IO + 0x206,
> -+ .end = TS9600_IDE_IO + 0x206 + 1,
> -+ .flags = IORESOURCE_MEM,
> -+ },
> -+ [2] = {
> -+ .start = TS9600_IDE_DATA,
> -+ .end = TS9600_IDE_DATA + 2,
> -+ .flags = IORESOURCE_MEM,
> -+ },
> -+ [3] = {
> -+ .start = TS9600_IDE_IRQ,
> -+ .end = TS9600_IDE_IRQ,
> -+ .flags = IORESOURCE_IRQ,
> -+ }
> -+};
> -+
> -+
> -+static struct platform_device ts9600_device = {
> -+ .name = "ts72xx-ide",
> -+ .id = 9600,
> -+ .dev = {
> -+ .dma_mask = &ts9600_device.dev.coherent_dma_mask,
> -+ .coherent_dma_mask = DMA_BIT_MASK(32),
> -+ .release = pata_ts9600_release,
> -+ },
> -+ .num_resources = ARRAY_SIZE(ts9600_resources),
> -+ .resource = ts9600_resources,
> -+};
> -+
> -+
> -+static __init int pata_ts9600_init(void)
> -+{
> -+ return platform_device_register(&ts9600_device);
> -+}
> -+
> -+static __exit void pata_ts9600_exit(void)
> -+{
> -+ platform_device_unregister(&ts9600_device);
> -+}
> -+
> -+module_init(pata_ts9600_init);
> -+module_exit(pata_ts9600_exit);
> -+
> -+MODULE_AUTHOR("Matthieu Crapet <mcrapet@gmail.com>");
> -+MODULE_DESCRIPTION("TS-9600 PATA device driver");
> -+MODULE_LICENSE("GPL");
> -+MODULE_VERSION(DRV_VERSION);
> ---
> -1.7.0.4
> -
> diff --git a/recipes/linux/linux-2.6.36/ts72xx/0010-ts72xx_gpio_i2c.patch b/recipes/linux/linux-2.6.36/ts72xx/0010-ts72xx_gpio_i2c.patch
> deleted file mode 100644
> index 7dee3af..0000000
> --- a/recipes/linux/linux-2.6.36/ts72xx/0010-ts72xx_gpio_i2c.patch
> +++ /dev/null
> @@ -1,63 +0,0 @@
> -From 675ef8ec55abd042e7d725bb5a7963ac6e715acb Mon Sep 17 00:00:00 2001
> -From: Matthieu Crapet <mcrapet@gmail.com>
> -Date: Sat, 19 Jun 2010 11:45:39 +0200
> -Subject: [PATCH 10/24] ts72xx_gpio_i2c
> -MIME-Version: 1.0
> -Content-Type: text/plain; charset=UTF-8
> -Content-Transfer-Encoding: 8bit
> -
> -Signed-off-by: Petr Štetiar <ynezz@true.cz>
> ----
> - arch/arm/mach-ep93xx/ts72xx.c | 22 ++++++++++++++++++++++
> - 1 files changed, 22 insertions(+), 0 deletions(-)
> -
> -diff --git a/arch/arm/mach-ep93xx/ts72xx.c b/arch/arm/mach-ep93xx/ts72xx.c
> -index 345ce18..e8a2489 100644
> ---- a/arch/arm/mach-ep93xx/ts72xx.c
> -+++ b/arch/arm/mach-ep93xx/ts72xx.c
> -@@ -19,6 +19,10 @@
> - #include <linux/m48t86.h>
> - #include <linux/mtd/nand.h>
> - #include <linux/mtd/partitions.h>
> -+#include <linux/mtd/physmap.h>
> -+#include <linux/gpio.h>
> -+#include <linux/i2c.h>
> -+#include <linux/i2c-gpio.h>
> -
> - #include <mach/hardware.h>
> - #include <mach/ts72xx.h>
> -@@ -279,6 +283,21 @@ static struct ep93xx_eth_data __initdata ts72xx_eth_data = {
> - .phy_id = 1,
> - };
> -
> -+/*************************************************************************
> -+ * I2C (make access through TS-72XX "DIO" 2x8 header)
> -+ *************************************************************************/
> -+static struct i2c_gpio_platform_data ts72xx_i2c_gpio_data = {
> -+ .sda_pin = EP93XX_GPIO_LINE_EGPIO14, // DIO_6
> -+ .sda_is_open_drain = 0,
> -+ .scl_pin = EP93XX_GPIO_LINE_EGPIO15, // DIO_7
> -+ .scl_is_open_drain = 0,
> -+ .udelay = 0, /* default is 100 kHz */
> -+ .timeout = 0, /* default is 100 ms */
> -+};
> -+
> -+static struct i2c_board_info __initdata ts72xx_i2c_board_info[] = {
> -+};
> -+
> - static void __init ts72xx_init_machine(void)
> - {
> - ep93xx_init_devices();
> -@@ -287,6 +306,9 @@ static void __init ts72xx_init_machine(void)
> - platform_device_register(&ts72xx_wdt_device);
> -
> - ep93xx_register_eth(&ts72xx_eth_data, 1);
> -+ ep93xx_register_i2c(&ts72xx_i2c_gpio_data,
> -+ ts72xx_i2c_board_info,
> -+ ARRAY_SIZE(ts72xx_i2c_board_info));
> -
> - /* PWM1 is DIO_6 on TS-72xx header */
> - ep93xx_register_pwm(0, 1);
> ---
> -1.7.0.4
> -
> diff --git a/recipes/linux/linux-2.6.36/ts72xx/0011-ts72xx_dio_keypad.patch b/recipes/linux/linux-2.6.36/ts72xx/0011-ts72xx_dio_keypad.patch
> deleted file mode 100644
> index df0924e..0000000
> --- a/recipes/linux/linux-2.6.36/ts72xx/0011-ts72xx_dio_keypad.patch
> +++ /dev/null
> @@ -1,311 +0,0 @@
> -From 75385f54792d2ed6dc59005972cf54dbedea9897 Mon Sep 17 00:00:00 2001
> -From: Matthieu Crapet <mcrapet@gmail.com>
> -Date: Sat, 19 Jun 2010 14:44:32 +0200
> -Subject: [PATCH 11/24] ts72xx_dio_keypad
> -MIME-Version: 1.0
> -Content-Type: text/plain; charset=UTF-8
> -Content-Transfer-Encoding: 8bit
> -
> -Depends of "matrix-keypad" driver.
> -
> -Signed-off-by: Petr Štetiar <ynezz@true.cz>
> ----
> - drivers/input/keyboard/Kconfig | 30 ++++++++
> - drivers/input/keyboard/Makefile | 2 +
> - drivers/input/keyboard/ts72xx_dio_3x4.c | 110 +++++++++++++++++++++++++++++
> - drivers/input/keyboard/ts72xx_dio_4x4.c | 115 +++++++++++++++++++++++++++++++
> - 4 files changed, 257 insertions(+), 0 deletions(-)
> - create mode 100644 drivers/input/keyboard/ts72xx_dio_3x4.c
> - create mode 100644 drivers/input/keyboard/ts72xx_dio_4x4.c
> -
> -diff --git a/drivers/input/keyboard/Kconfig b/drivers/input/keyboard/Kconfig
> -index 9cc488d..81860f4 100644
> ---- a/drivers/input/keyboard/Kconfig
> -+++ b/drivers/input/keyboard/Kconfig
> -@@ -204,6 +204,36 @@ config KEYBOARD_MATRIX
> - To compile this driver as a module, choose M here: the
> - module will be called matrix_keypad.
> -
> -+if KEYBOARD_MATRIX
> -+
> -+choice
> -+ prompt "Keypad type"
> -+ default TS72XX_DIO_4X4_KEYPAD
> -+
> -+config TS72XX_DIO_3X4_KEYPAD
> -+ tristate "TS-72xx 3x4 matrix keypad"
> -+ depends on MACH_TS72XX
> -+ help
> -+ This a 12 keys (4 rows, 3 cols using DIO_0-6) keypad with the following layout:
> -+ 1 2 3
> -+ 4 5 6
> -+ 7 8 9
> -+ * 0 #
> -+
> -+config TS72XX_DIO_4X4_KEYPAD
> -+ tristate "TS-72xx 4x4 matrix keypad"
> -+ depends on MACH_TS72XX
> -+ help
> -+ This a 16 keys (4 rows, 4 cols using DIO_0-7) keypad with the following layout:
> -+ 7 8 9 F
> -+ 4 5 6 E
> -+ 1 2 3 D
> -+ A 0 B C
> -+
> -+endchoice
> -+
> -+endif # KEYBOARD_MATRIX
> -+
> - config KEYBOARD_HIL_OLD
> - tristate "HP HIL keyboard support (simple driver)"
> - depends on GSC || HP300
> -diff --git a/drivers/input/keyboard/Makefile b/drivers/input/keyboard/Makefile
> -index 504b591..cb18981 100644
> ---- a/drivers/input/keyboard/Makefile
> -+++ b/drivers/input/keyboard/Makefile
> -@@ -41,3 +41,5 @@ obj-$(CONFIG_KEYBOARD_SUNKBD) += sunkbd.o
> - obj-$(CONFIG_KEYBOARD_TWL4030) += twl4030_keypad.o
> - obj-$(CONFIG_KEYBOARD_XTKBD) += xtkbd.o
> - obj-$(CONFIG_KEYBOARD_W90P910) += w90p910_keypad.o
> -+obj-$(CONFIG_TS72XX_DIO_3X4_KEYPAD) += ts72xx_dio_3x4.o
> -+obj-$(CONFIG_TS72XX_DIO_4X4_KEYPAD) += ts72xx_dio_4x4.o
> -diff --git a/drivers/input/keyboard/ts72xx_dio_3x4.c b/drivers/input/keyboard/ts72xx_dio_3x4.c
> -new file mode 100644
> -index 0000000..e214335
> ---- /dev/null
> -+++ b/drivers/input/keyboard/ts72xx_dio_3x4.c
> -@@ -0,0 +1,110 @@
> -+/*
> -+ * TS-72xx (3x4) keypad device driver for DIO1 header (DIO_0 thru DIO_6)
> -+ *
> -+ * (c) Copyright 2010 Matthieu Crapet <mcrapet@gmail.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.
> -+ *
> -+ */
> -+
> -+#include <linux/module.h>
> -+#include <linux/kernel.h>
> -+#include <linux/init.h>
> -+#include <linux/platform_device.h>
> -+#include <linux/input/matrix_keypad.h>
> -+#include <mach/gpio.h>
> -+
> -+static const uint32_t ts72xx_kbd_keymap[] = {
> -+ KEY(0, 0, KEY_1),
> -+ KEY(0, 1, KEY_2),
> -+ KEY(0, 2, KEY_3),
> -+
> -+ KEY(1, 0, KEY_4),
> -+ KEY(1, 1, KEY_5),
> -+ KEY(1, 2, KEY_6),
> -+
> -+ KEY(2, 0, KEY_7),
> -+ KEY(2, 1, KEY_8),
> -+ KEY(2, 2, KEY_9),
> -+
> -+ KEY(3, 0, KEY_KPASTERISK),
> -+ KEY(3, 1, KEY_0),
> -+ KEY(3, 2, KEY_ENTER),
> -+};
> -+
> -+static struct matrix_keymap_data ts72xx_kbd_keymap_data = {
> -+ .keymap = ts72xx_kbd_keymap,
> -+ .keymap_size = ARRAY_SIZE(ts72xx_kbd_keymap),
> -+};
> -+
> -+static const int ts72xx_kbd_row_gpios[] = {
> -+ EP93XX_GPIO_LINE_EGPIO14, // DIO_6 (row0)
> -+ EP93XX_GPIO_LINE_EGPIO13,
> -+ EP93XX_GPIO_LINE_EGPIO12,
> -+ EP93XX_GPIO_LINE_EGPIO11,
> -+};
> -+
> -+static const int ts72xx_kbd_col_gpios[] = {
> -+ EP93XX_GPIO_LINE_EGPIO10, // DIO_2 (col0)
> -+ EP93XX_GPIO_LINE_EGPIO9,
> -+ EP93XX_GPIO_LINE_EGPIO8,
> -+};
> -+
> -+static struct matrix_keypad_platform_data ts72xx_kbd_pdata = {
> -+ .keymap_data = &ts72xx_kbd_keymap_data,
> -+ .row_gpios = ts72xx_kbd_row_gpios,
> -+ .col_gpios = ts72xx_kbd_col_gpios,
> -+ .num_row_gpios = ARRAY_SIZE(ts72xx_kbd_row_gpios),
> -+ .num_col_gpios = ARRAY_SIZE(ts72xx_kbd_col_gpios),
> -+ .col_scan_delay_us = 20,
> -+ .debounce_ms = 20,
> -+ .wakeup = 1,
> -+ .active_low = 1,
> -+ //.no_autorep = 1,
> -+};
> -+
> -+static void ts72xx_kbd_release(struct device *dev)
> -+{
> -+}
> -+
> -+static struct platform_device ts72xx_kbd_device = {
> -+ .name = "matrix-keypad",
> -+ .id = -1,
> -+ .dev = {
> -+ .platform_data = &ts72xx_kbd_pdata,
> -+ .release = ts72xx_kbd_release,
> -+ },
> -+};
> -+
> -+static int __init ts72xx_dio_init(void)
> -+{
> -+ int i;
> -+
> -+ for (i = 0; i < ARRAY_SIZE(ts72xx_kbd_row_gpios); i++) {
> -+ int irq = gpio_to_irq(ts72xx_kbd_row_gpios[i]);
> -+
> -+ ep93xx_gpio_int_debounce(irq, 1);
> -+ }
> -+
> -+ return platform_device_register(&ts72xx_kbd_device);
> -+}
> -+
> -+static void __exit ts72xx_dio_exit(void)
> -+{
> -+ platform_device_unregister(&ts72xx_kbd_device);
> -+}
> -+
> -+module_init(ts72xx_dio_init);
> -+module_exit(ts72xx_dio_exit);
> -+
> -+MODULE_AUTHOR("Matthieu Crapet <mcrapet@gmail.com>");
> -+MODULE_DESCRIPTION("Platform device 3x4 keypad");
> -+MODULE_LICENSE("GPL");
> -diff --git a/drivers/input/keyboard/ts72xx_dio_4x4.c b/drivers/input/keyboard/ts72xx_dio_4x4.c
> -new file mode 100644
> -index 0000000..790abd5
> ---- /dev/null
> -+++ b/drivers/input/keyboard/ts72xx_dio_4x4.c
> -@@ -0,0 +1,115 @@
> -+/*
> -+ * TS-72xx (4x4) keypad device driver for DIO1 header (DIO_0 thru DIO_7)
> -+ *
> -+ * (c) Copyright 2010 Matthieu Crapet <mcrapet@gmail.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.
> -+ *
> -+ */
> -+
> -+#include <linux/module.h>
> -+#include <linux/kernel.h>
> -+#include <linux/init.h>
> -+#include <linux/platform_device.h>
> -+#include <linux/input/matrix_keypad.h>
> -+#include <mach/gpio.h>
> -+
> -+static const uint32_t ts72xx_kbd_keymap[] = {
> -+ KEY(0, 0, KEY_7),
> -+ KEY(0, 1, KEY_8),
> -+ KEY(0, 2, KEY_9),
> -+ KEY(0, 3, KEY_F),
> -+
> -+ KEY(1, 0, KEY_4),
> -+ KEY(1, 1, KEY_5),
> -+ KEY(1, 2, KEY_6),
> -+ KEY(1, 3, KEY_E),
> -+
> -+ KEY(2, 0, KEY_1),
> -+ KEY(2, 1, KEY_2),
> -+ KEY(2, 2, KEY_3),
> -+ KEY(2, 3, KEY_D),
> -+
> -+ KEY(3, 0, KEY_A),
> -+ KEY(3, 1, KEY_0),
> -+ KEY(3, 2, KEY_B),
> -+ KEY(3, 3, KEY_C),
> -+};
> -+
> -+static struct matrix_keymap_data ts72xx_kbd_keymap_data = {
> -+ .keymap = ts72xx_kbd_keymap,
> -+ .keymap_size = ARRAY_SIZE(ts72xx_kbd_keymap),
> -+};
> -+
> -+static const int ts72xx_kbd_row_gpios[] = {
> -+ EP93XX_GPIO_LINE_EGPIO8, // DIO_0 (row0)
> -+ EP93XX_GPIO_LINE_EGPIO9,
> -+ EP93XX_GPIO_LINE_EGPIO12,
> -+ EP93XX_GPIO_LINE_EGPIO14,
> -+};
> -+
> -+static const int ts72xx_kbd_col_gpios[] = {
> -+ EP93XX_GPIO_LINE_EGPIO15, // DIO_7 (col0)
> -+ EP93XX_GPIO_LINE_EGPIO13,
> -+ EP93XX_GPIO_LINE_EGPIO11,
> -+ EP93XX_GPIO_LINE_EGPIO10,
> -+};
> -+
> -+static struct matrix_keypad_platform_data ts72xx_kbd_pdata = {
> -+ .keymap_data = &ts72xx_kbd_keymap_data,
> -+ .row_gpios = ts72xx_kbd_row_gpios,
> -+ .col_gpios = ts72xx_kbd_col_gpios,
> -+ .num_row_gpios = ARRAY_SIZE(ts72xx_kbd_row_gpios),
> -+ .num_col_gpios = ARRAY_SIZE(ts72xx_kbd_col_gpios),
> -+ .col_scan_delay_us = 20,
> -+ .debounce_ms = 20,
> -+ .wakeup = 1,
> -+ .active_low = 1,
> -+ //.no_autorep = 1,
> -+};
> -+
> -+static void ts72xx_kbd_release(struct device *dev)
> -+{
> -+}
> -+
> -+static struct platform_device ts72xx_kbd_device = {
> -+ .name = "matrix-keypad",
> -+ .id = -1,
> -+ .dev = {
> -+ .platform_data = &ts72xx_kbd_pdata,
> -+ .release = ts72xx_kbd_release,
> -+ },
> -+};
> -+
> -+static int __init ts72xx_dio_init(void)
> -+{
> -+ int i;
> -+
> -+ for (i = 0; i < ARRAY_SIZE(ts72xx_kbd_row_gpios); i++) {
> -+ int irq = gpio_to_irq(ts72xx_kbd_row_gpios[i]);
> -+
> -+ ep93xx_gpio_int_debounce(irq, 1);
> -+ }
> -+
> -+ return platform_device_register(&ts72xx_kbd_device);
> -+}
> -+
> -+static void __exit ts72xx_dio_exit(void)
> -+{
> -+ platform_device_unregister(&ts72xx_kbd_device);
> -+}
> -+
> -+module_init(ts72xx_dio_init);
> -+module_exit(ts72xx_dio_exit);
> -+
> -+MODULE_AUTHOR("Matthieu Crapet <mcrapet@gmail.com>");
> -+MODULE_DESCRIPTION("Platform device 4x4 keypad");
> -+MODULE_LICENSE("GPL");
> ---
> -1.7.0.4
> -
> diff --git a/recipes/linux/linux-2.6.36/ts72xx/0012-ts72xx_sbcinfo.patch b/recipes/linux/linux-2.6.36/ts72xx/0012-ts72xx_sbcinfo.patch
> deleted file mode 100644
> index f744a66..0000000
> --- a/recipes/linux/linux-2.6.36/ts72xx/0012-ts72xx_sbcinfo.patch
> +++ /dev/null
> @@ -1,267 +0,0 @@
> -From c4f068cc743be6e79c333a0de38e1cef91e05786 Mon Sep 17 00:00:00 2001
> -From: Matthieu Crapet <mcrapet@gmail.com>
> -Date: Sat, 19 Jun 2010 15:08:58 +0200
> -Subject: [PATCH 12/24] ts72xx_sbcinfo
> -MIME-Version: 1.0
> -Content-Type: text/plain; charset=UTF-8
> -Content-Transfer-Encoding: 8bit
> -
> -Signed-off-by: Petr Štetiar <ynezz@true.cz>
> ----
> - arch/arm/mach-ep93xx/Kconfig | 7 +
> - arch/arm/mach-ep93xx/Makefile | 1 +
> - arch/arm/mach-ep93xx/ts72xx.c | 5 +
> - arch/arm/mach-ep93xx/ts72xx_sbcinfo.c | 198 +++++++++++++++++++++++++++++++++
> - 4 files changed, 211 insertions(+), 0 deletions(-)
> - create mode 100644 arch/arm/mach-ep93xx/ts72xx_sbcinfo.c
> -
> -diff --git a/arch/arm/mach-ep93xx/Kconfig b/arch/arm/mach-ep93xx/Kconfig
> -index bd463a0..2bfb01e 100644
> ---- a/arch/arm/mach-ep93xx/Kconfig
> -+++ b/arch/arm/mach-ep93xx/Kconfig
> -@@ -212,6 +212,13 @@ config MACH_TS72XX_FORCE_MACHINEID
> - Say 'Y' here to force Machine ID to 0x2A1 (MACH_TYPE_TS72XX legacy value)
> - In early days Technologic Systems fixed the 0x163 value in redboot.
> -
> -+config MACH_TS72XX_SBCINFO
> -+ tristate "Add procfs /proc/driver/sbcinfo"
> -+ depends on MACH_TS72XX
> -+ help
> -+ Say 'Y' to add a procfs entry containing some information
> -+ related to Technologic Systems TS-72xx SBC.
> -+
> - endmenu
> -
> - endif
> -diff --git a/arch/arm/mach-ep93xx/Makefile b/arch/arm/mach-ep93xx/Makefile
> -index ea652c2..c38d1e2 100644
> ---- a/arch/arm/mach-ep93xx/Makefile
> -+++ b/arch/arm/mach-ep93xx/Makefile
> -@@ -13,3 +13,4 @@ obj-$(CONFIG_MACH_MICRO9) += micro9.o
> - obj-$(CONFIG_MACH_SIM_ONE) += simone.o
> - obj-$(CONFIG_MACH_SNAPPER_CL15) += snappercl15.o
> - obj-$(CONFIG_MACH_TS72XX) += ts72xx.o
> -+obj-$(CONFIG_MACH_TS72XX_SBCINFO) += ts72xx_sbcinfo.o
> -diff --git a/arch/arm/mach-ep93xx/ts72xx.c b/arch/arm/mach-ep93xx/ts72xx.c
> -index e8a2489..9b707a5 100644
> ---- a/arch/arm/mach-ep93xx/ts72xx.c
> -+++ b/arch/arm/mach-ep93xx/ts72xx.c
> -@@ -39,6 +39,11 @@ static struct map_desc ts72xx_io_desc[] __initdata = {
> - .length = TS72XX_MODEL_SIZE,
> - .type = MT_DEVICE,
> - }, {
> -+ .virtual = TS72XX_PLD_VERSION_VIRT_BASE,
> -+ .pfn = __phys_to_pfn(TS72XX_PLD_VERSION_PHYS_BASE),
> -+ .length = TS72XX_PLD_VERSION_SIZE,
> -+ .type = MT_DEVICE,
> -+ }, {
> - .virtual = TS72XX_OPTIONS_VIRT_BASE,
> - .pfn = __phys_to_pfn(TS72XX_OPTIONS_PHYS_BASE),
> - .length = TS72XX_OPTIONS_SIZE,
> -diff --git a/arch/arm/mach-ep93xx/ts72xx_sbcinfo.c b/arch/arm/mach-ep93xx/ts72xx_sbcinfo.c
> -new file mode 100644
> -index 0000000..cbb485f
> ---- /dev/null
> -+++ b/arch/arm/mach-ep93xx/ts72xx_sbcinfo.c
> -@@ -0,0 +1,198 @@
> -+/*
> -+ * Technologic Systems TS-72XX sbc /proc/driver/sbcinfo entry.
> -+ *
> -+ * Original idea by Liberty Young (Technologic Systems).
> -+ *
> -+ * (c) Copyright 2008 Matthieu Crapet <mcrapet@gmail.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.
> -+ */
> -+
> -+#include <linux/module.h>
> -+#include <linux/kernel.h>
> -+#include <linux/init.h>
> -+#include <linux/io.h>
> -+#include <linux/proc_fs.h>
> -+#include <mach/hardware.h>
> -+#include <mach/ts72xx.h>
> -+
> -+struct infos {
> -+ const char *cpu_rev;
> -+ int model, pld, wdt;
> -+ int option_ad;
> -+ int option_rs485;
> -+ unsigned char jumpers[6]; // 0=off,1=on,2=error
> -+
> -+ /* Power management : TS-7260 only */
> -+ int pm;
> -+};
> -+
> -+static const char *revisions[] = { "A", "B", "C", "D0", "D1", "E0", "E1", "E2", "??" };
> -+
> -+
> -+static void get_sbcinfo(struct infos *data)
> -+{
> -+ void __iomem *p;
> -+ short rev;
> -+
> -+ /* CPU revision */
> -+ rev = __raw_readl(EP93XX_SYSCON_CHIPID) >> 28;
> -+ if (rev > ARRAY_SIZE(revisions))
> -+ rev = ARRAY_SIZE(revisions) - 1;
> -+ data->cpu_rev = revisions[rev];
> -+
> -+ /* Board model */
> -+ if (board_is_ts7200())
> -+ data->model = 7200;
> -+ else if (board_is_ts7250())
> -+ data->model = 7250;
> -+ else if (board_is_ts7260())
> -+ data->model = 7260;
> -+ else if (board_is_ts7400())
> -+ data->model = 7400;
> -+ else
> -+ data->model = 0;
> -+
> -+ data->pld = get_ts72xx_pld_version();
> -+
> -+ /* A/D converter (8 x 12-bit channels) */
> -+ if (data->model == 7200 || data->model == 7250) {
> -+ data->option_ad = is_max197_installed();
> -+ } else {
> -+ data->option_ad = 0;
> -+ }
> -+
> -+ /* COM2 RS-485 */
> -+ if (is_rs485_installed()) {
> -+ data->option_rs485 = 1;
> -+ } else {
> -+ data->option_rs485 = 0;
> -+ }
> -+
> -+ /* jumpers */
> -+ p = ioremap(TS72XX_JUMPERS_MAX197_PHYS_BASE, SZ_4K - 1);
> -+ if (p) {
> -+ unsigned char c = __raw_readb(p);
> -+
> -+ data->jumpers[0] = 2; // JP1 (bootstrap)
> -+ data->jumpers[1] = !!(c & 0x01); // JP2 (enable serial console)
> -+ data->jumpers[2] = !!(c & 0x02); // JP3 (flash write enable)
> -+ data->jumpers[3] = !(c & 0x08); // JP4 (console on COM2)
> -+ data->jumpers[4] = !(c & 0x10); // JP5 (test)
> -+ data->jumpers[5] = !!(is_jp6_set()); // JP6 (user jumper)
> -+
> -+ iounmap(p);
> -+ } else {
> -+ data->jumpers[0] = data->jumpers[1] = data->jumpers[2] = 2;
> -+ data->jumpers[3] = data->jumpers[4] = data->jumpers[5] = 2;
> -+ }
> -+
> -+ /* cpld watchdog */
> -+ p = ioremap(TS72XX_WDT_CONTROL_PHYS_BASE, SZ_4K - 1);
> -+ if (p) {
> -+ data->wdt = __raw_readb(p) & 0x7;
> -+ iounmap(p);
> -+ } else {
> -+ data->wdt = 8;
> -+ }
> -+
> -+ /* power management */
> -+ data->pm = -1;
> -+ if (data->model == 7260) {
> -+ p = ioremap(TS7260_POWER_MANAGEMENT_PHYS_BASE, SZ_4K - 1);
> -+ if (p) {
> -+ data->pm = __raw_readb(p);
> -+ iounmap(p);
> -+ }
> -+ }
> -+}
> -+
> -+static char *get_pm_string(int reg, char *buffer, size_t size)
> -+{
> -+ static const char *pm_state = "rs232=%d usb=%d lcd=%d pc104=%d ttl=%d";
> -+
> -+ if (reg < 0) {
> -+ strncpy(buffer, "n/a", size);
> -+ } else {
> -+ /* 1 means on/enabled */
> -+ snprintf(buffer, size, pm_state,
> -+ reg & TS7260_PM_RS232_LEVEL_CONVERTER,
> -+ !!(reg & TS7260_PM_USB),
> -+ !!(reg & TS7260_PM_LCD),
> -+ !(reg & TS7260_PM_PC104_CLOCK),
> -+ !!(reg & TS7260_PM_TTL_UART_ENABLE));
> -+ }
> -+ return buffer;
> -+}
> -+
> -+static int ts72xx_sbcinfo_read_proc(char *buffer, char **start, off_t offset,
> -+ int count, int *eof, void *data)
> -+{
> -+ int len, size = count;
> -+ char *p = buffer;
> -+ char temp[64];
> -+ struct infos nfo;
> -+
> -+ static const char jpc[3] = { 'n', 'y', '?' };
> -+ static const char *wdt[9] = { "disabled", "250ms", "500ms", "1s", "reserved", "2s", "4s", "8s", "n/a" };
> -+
> -+ get_sbcinfo(&nfo);
> -+ len = scnprintf(p, size,
> -+ "Model : TS-%d (CPU rev %s) (PLD rev %c)\n"
> -+ "Option max197 A/D : %s\n"
> -+ "Option RS-485 : %s\n"
> -+ "Jumpers : JP2=%c JP3=%c JP4=%c JP5=%c JP6=%c\n"
> -+ "CPLD Watchdog : %s\n"
> -+ "Power management : %s\n",
> -+ nfo.model, nfo.cpu_rev, nfo.pld + 0x40,
> -+ (nfo.option_ad ? "yes" : "no"),
> -+ (nfo.option_rs485 ? "yes" : "no"),
> -+ jpc[nfo.jumpers[1]], jpc[nfo.jumpers[2]], jpc[nfo.jumpers[3]], jpc[nfo.jumpers[4]],
> -+ jpc[nfo.jumpers[5]], wdt[nfo.wdt],
> -+ get_pm_string(nfo.pm, &temp[0], sizeof(temp)));
> -+
> -+ if (len <= offset + count)
> -+ *eof = 1;
> -+
> -+ *start = buffer + offset;
> -+ len -= offset;
> -+
> -+ if (len > count)
> -+ len = count;
> -+ if (len < 0)
> -+ len = 0;
> -+
> -+ return len;
> -+}
> -+
> -+static int __init ts72xx_sbcinfo_init(void)
> -+{
> -+ struct proc_dir_entry *entry;
> -+ int ret = 0;
> -+
> -+ entry = create_proc_read_entry("driver/sbcinfo", 0,
> -+ NULL, ts72xx_sbcinfo_read_proc, NULL);
> -+
> -+ if (!entry) {
> -+ printk(KERN_ERR "sbcinfo: can't create /proc/driver/sbcinfo\n");
> -+ ret = -ENOMEM;
> -+ }
> -+
> -+ return ret;
> -+}
> -+
> -+static void __exit ts72xx_sbcinfo_exit(void)
> -+{
> -+ remove_proc_entry("driver/sbcinfo", NULL);
> -+}
> -+
> -+module_init(ts72xx_sbcinfo_init);
> -+module_exit(ts72xx_sbcinfo_exit);
> -+
> -+MODULE_AUTHOR("Matthieu Crapet <mcrapet@gmail.com>");
> -+MODULE_DESCRIPTION("Show information of Technologic Systems TS-72XX sbc");
> -+MODULE_LICENSE("GPL");
> -+MODULE_VERSION("1.04");
> ---
> -1.7.0.4
> -
> diff --git a/recipes/linux/linux-2.6.36/ts72xx/0013-ts72xx_max197.patch b/recipes/linux/linux-2.6.36/ts72xx/0013-ts72xx_max197.patch
> deleted file mode 100644
> index 6837e55..0000000
> --- a/recipes/linux/linux-2.6.36/ts72xx/0013-ts72xx_max197.patch
> +++ /dev/null
> @@ -1,356 +0,0 @@
> -From 4d67c12c77e2095db542e84a78086cb1be02ff71 Mon Sep 17 00:00:00 2001
> -From: Matthieu Crapet <mcrapet@gmail.com>
> -Date: Sat, 19 Jun 2010 15:49:34 +0200
> -Subject: [PATCH 13/24] ts72xx_max197
> -MIME-Version: 1.0
> -Content-Type: text/plain; charset=UTF-8
> -Content-Transfer-Encoding: 8bit
> -
> -Signed-off-by: Petr Štetiar <ynezz@true.cz>
> ----
> - arch/arm/mach-ep93xx/ts72xx.c | 32 ++++++-
> - drivers/misc/Kconfig | 21 ++++
> - drivers/misc/Makefile | 1 +
> - drivers/misc/ts72xx_max197.c | 235 +++++++++++++++++++++++++++++++++++++++++
> - 4 files changed, 288 insertions(+), 1 deletions(-)
> - create mode 100644 drivers/misc/ts72xx_max197.c
> -
> -diff --git a/arch/arm/mach-ep93xx/ts72xx.c b/arch/arm/mach-ep93xx/ts72xx.c
> -index 9b707a5..96a4d54 100644
> ---- a/arch/arm/mach-ep93xx/ts72xx.c
> -+++ b/arch/arm/mach-ep93xx/ts72xx.c
> -@@ -281,10 +281,36 @@ static struct platform_device ts72xx_wdt_device = {
> - .resource = ts72xx_wdt_resources,
> - };
> -
> --static struct ep93xx_eth_data __initdata ts72xx_eth_data = {
> -+/*************************************************************************
> -+ * MAX197 (8 * 12-bit A/D converter) option
> -+ *************************************************************************/
> -+static struct resource ts72xx_max197_resources[] = {
> -+ [0] = { /* sample/control register */
> -+ .start = TS72XX_MAX197_SAMPLE_PHYS_BASE,
> -+ .end = TS72XX_MAX197_SAMPLE_PHYS_BASE + SZ_4K - 1,
> -+ .flags = IORESOURCE_MEM,
> -+ },
> -+ [1] = { /* busy bit */
> -+ .start = TS72XX_JUMPERS_MAX197_PHYS_BASE,
> -+ .end = TS72XX_JUMPERS_MAX197_PHYS_BASE + SZ_4K - 1,
> -+ .flags = IORESOURCE_MEM,
> -+ }
> -+};
> -+
> -+static struct platform_device ts72xx_max197_device = {
> -+ .name = "ts72xx-max197",
> -+ .id = -1,
> -+ .dev = {
> -+ .platform_data = NULL,
> -+ },
> -+ .num_resources = ARRAY_SIZE(ts72xx_max197_resources),
> -+ .resource = ts72xx_max197_resources,
> -+};
> -+
> - /*************************************************************************
> - * Ethernet
> - *************************************************************************/
> -+static struct ep93xx_eth_data __initdata ts72xx_eth_data = {
> - .phy_id = 1,
> - };
> -
> -@@ -315,6 +341,10 @@ static void __init ts72xx_init_machine(void)
> - ts72xx_i2c_board_info,
> - ARRAY_SIZE(ts72xx_i2c_board_info));
> -
> -+ if (is_max197_installed()) {
> -+ platform_device_register(&ts72xx_max197_device);
> -+ }
> -+
> - /* PWM1 is DIO_6 on TS-72xx header */
> - ep93xx_register_pwm(0, 1);
> - }
> -diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
> -index b743312..89026bf 100644
> ---- a/drivers/misc/Kconfig
> -+++ b/drivers/misc/Kconfig
> -@@ -395,4 +395,25 @@ source "drivers/misc/eeprom/Kconfig"
> - source "drivers/misc/cb710/Kconfig"
> - source "drivers/misc/iwmc3200top/Kconfig"
> -
> -+config TS72XX_MAX197
> -+ tristate "TS-72xx MAX197 support"
> -+ depends on ARCH_EP93XX && MACH_TS72XX && SYSFS
> -+ help
> -+ Say Y here if to include support for the MAX197 A/D converter
> -+ optionally included on Technologic Systems SBCs.
> -+ Default acquisition range is [0..5V].
> -+
> -+ To compile this driver as a module, choose M here: the
> -+ module will be called ts72xx_max197.
> -+
> -+if TS72XX_MAX197
> -+
> -+config TS72XX_MAX197_AVERAGE
> -+ bool "Average measurement"
> -+ help
> -+ Say Y here to enable making average measurement. Default is 1.
> -+ See /sys/module/ts72xx_max197/parameters/average file.
> -+
> -+endif # TS72XX_MAX197
> -+
> - endif # MISC_DEVICES
> -diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile
> -index 42eab95..431ef19 100644
> ---- a/drivers/misc/Makefile
> -+++ b/drivers/misc/Makefile
> -@@ -26,6 +26,7 @@ obj-$(CONFIG_HP_ILO) += hpilo.o
> - obj-$(CONFIG_ISL29003) += isl29003.o
> - obj-$(CONFIG_SENSORS_TSL2550) += tsl2550.o
> - obj-$(CONFIG_EP93XX_PWM) += ep93xx_pwm.o
> -+obj-$(CONFIG_TS72XX_MAX197) += ts72xx_max197.o
> - obj-$(CONFIG_DS1682) += ds1682.o
> - obj-$(CONFIG_TI_DAC7512) += ti_dac7512.o
> - obj-$(CONFIG_C2PORT) += c2port/
> -diff --git a/drivers/misc/ts72xx_max197.c b/drivers/misc/ts72xx_max197.c
> -new file mode 100644
> -index 0000000..4121ae5
> ---- /dev/null
> -+++ b/drivers/misc/ts72xx_max197.c
> -@@ -0,0 +1,235 @@
> -+/*
> -+ * TS-72XX max197 driver for Technologic Systems boards.
> -+ *
> -+ * Voltage conversion is taken from adc_logger from Jim Jackson.
> -+ * (c) Copyright 2008 Matthieu Crapet <mcrapet@gmail.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.
> -+ */
> -+
> -+#include <linux/kernel.h>
> -+#include <linux/module.h>
> -+#include <linux/platform_device.h>
> -+#include <asm/io.h>
> -+
> -+#define DRV_VERSION "0.2"
> -+#define PFX "ts72xx_max197: "
> -+
> -+#define MAX197_RANGE_5_5 1 // [- 5V + 5V]
> -+#define MAX197_RANGE_10_10 3 // [-10V +10V]
> -+#define MAX197_RANGE_0_5 0 // [ 0V + 5V]
> -+#define MAX197_RANGE_0_10 2 // [ 0V +10V]
> -+
> -+#define MAX197_RESET_CHANNEL_CONF(x) (~(3 << (2*(x))))
> -+#define MAX197_SET_CHANNEL_CONF(x, range) ((range) << (2*(x)))
> -+#define MAX197_GET_CHANNEL_CONF(x, conf) (((conf) >> (2*(x))) & 3)
> -+
> -+struct max197_config
> -+{
> -+ void __iomem *control_and_data_register;
> -+ void __iomem *busy_bit_register;
> -+ unsigned int channels; // two bits per channels
> -+};
> -+
> -+static struct max197_config conf;
> -+#ifdef CONFIG_TS72XX_MAX197_AVERAGE
> -+static ushort average = 1;
> -+#endif
> -+
> -+static ssize_t max197_acquire(struct device *dev,
> -+ struct device_attribute *attr, char *buf)
> -+{
> -+ int range, n;
> -+ signed short val;
> -+#ifdef CONFIG_TS72XX_MAX197_AVERAGE
> -+ int i, total;
> -+#endif
> -+
> -+ n = attr->attr.name[2] - 0x31;
> -+ range = MAX197_GET_CHANNEL_CONF(n, conf.channels);
> -+
> -+#ifdef CONFIG_TS72XX_MAX197_AVERAGE
> -+ val = 0; total = 0;
> -+ for (i = 0; i < average; i++) {
> -+#endif
> -+
> -+ __raw_writeb(((range << 3) | n | 0x40) & 0xFF,
> -+ conf.control_and_data_register);
> -+ while (__raw_readb(conf.busy_bit_register) & 0x80);
> -+ val = __raw_readw(conf.control_and_data_register);
> -+
> -+ //printk(PFX "%hd/%hd: 0x%04X\n", i+1, average, val);
> -+
> -+#ifdef CONFIG_TS72XX_MAX197_AVERAGE
> -+ total += val;
> -+ }
> -+ total /= average;
> -+ val = (signed short)total;
> -+#endif
> -+
> -+ /* We want three digit precision */
> -+ switch (range) {
> -+ case MAX197_RANGE_0_5:
> -+ val = ((val * 50000/4096)+5)/10;
> -+ break;
> -+ case MAX197_RANGE_5_5:
> -+ case MAX197_RANGE_0_10:
> -+ val = ((val * 100000/4096)+5)/10;
> -+ break;
> -+ case MAX197_RANGE_10_10:
> -+ val = ((val * 200000/4096)+5)/10;
> -+ break;
> -+ }
> -+
> -+ return sprintf(buf, "%d.%03ld\n", val/1000, abs(val%1000));
> -+}
> -+
> -+static ssize_t max197_configure(struct device *dev,
> -+ struct device_attribute *attr, const char *buf, size_t len)
> -+{
> -+ int n = attr->attr.name[2] - 0x31;
> -+
> -+ long val = simple_strtol(buf, NULL, 10);
> -+ switch (val) {
> -+ case 10:
> -+ conf.channels &= MAX197_RESET_CHANNEL_CONF(n);
> -+ conf.channels |= MAX197_SET_CHANNEL_CONF(n, MAX197_RANGE_0_10);
> -+ break;
> -+ case 5:
> -+ conf.channels &= MAX197_RESET_CHANNEL_CONF(n);
> -+ conf.channels |= MAX197_SET_CHANNEL_CONF(n, MAX197_RANGE_0_5);
> -+ break;
> -+ case -10:
> -+ conf.channels &= MAX197_RESET_CHANNEL_CONF(n);
> -+ conf.channels |= MAX197_SET_CHANNEL_CONF(n, MAX197_RANGE_10_10);
> -+ break;
> -+ case -5:
> -+ conf.channels &= MAX197_RESET_CHANNEL_CONF(n);
> -+ conf.channels |= MAX197_SET_CHANNEL_CONF(n, MAX197_RANGE_5_5);
> -+ break;
> -+
> -+ default:
> -+ return -EINVAL;
> -+ }
> -+
> -+ return len;
> -+}
> -+
> -+static DEVICE_ATTR(ch1, S_IWUSR | S_IRUGO, max197_acquire, max197_configure);
> -+static DEVICE_ATTR(ch2, S_IWUSR | S_IRUGO, max197_acquire, max197_configure);
> -+static DEVICE_ATTR(ch3, S_IWUSR | S_IRUGO, max197_acquire, max197_configure);
> -+static DEVICE_ATTR(ch4, S_IWUSR | S_IRUGO, max197_acquire, max197_configure);
> -+static DEVICE_ATTR(ch5, S_IWUSR | S_IRUGO, max197_acquire, max197_configure);
> -+static DEVICE_ATTR(ch6, S_IWUSR | S_IRUGO, max197_acquire, max197_configure);
> -+static DEVICE_ATTR(ch7, S_IWUSR | S_IRUGO, max197_acquire, max197_configure);
> -+static DEVICE_ATTR(ch8, S_IWUSR | S_IRUGO, max197_acquire, max197_configure);
> -+
> -+static struct attribute *max197_attributes[] = {
> -+ &dev_attr_ch1.attr,
> -+ &dev_attr_ch2.attr,
> -+ &dev_attr_ch3.attr,
> -+ &dev_attr_ch4.attr,
> -+ &dev_attr_ch5.attr,
> -+ &dev_attr_ch6.attr,
> -+ &dev_attr_ch7.attr,
> -+ &dev_attr_ch8.attr,
> -+ NULL
> -+};
> -+
> -+static struct attribute_group max197_group = {
> -+ .attrs = max197_attributes,
> -+ //.name = "channels",
> -+};
> -+
> -+static __devinit int ts72xx_max197_probe(struct platform_device *pdev)
> -+{
> -+ int err = 0;
> -+ struct resource *r_data, *r_busy;
> -+
> -+ r_data = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> -+ r_busy = platform_get_resource(pdev, IORESOURCE_MEM, 1);
> -+
> -+ if (!r_data || !r_busy) {
> -+ dev_err(&pdev->dev, "missing resource(s)\n");
> -+ return -EINVAL;
> -+ }
> -+
> -+ conf.control_and_data_register = ioremap(r_data->start, r_data->end - r_data->start + 1);
> -+ if (!conf.control_and_data_register) {
> -+ err = -ENODEV;
> -+ goto exit;
> -+ }
> -+
> -+ conf.busy_bit_register = ioremap(r_busy->start, r_busy->end - r_busy->start + 1);
> -+ if (!conf.busy_bit_register) {
> -+ err = -ENODEV;
> -+ goto exit_unmap1;
> -+ }
> -+
> -+ conf.channels =
> -+ MAX197_SET_CHANNEL_CONF(0, MAX197_RANGE_0_5) |
> -+ MAX197_SET_CHANNEL_CONF(1, MAX197_RANGE_0_5) |
> -+ MAX197_SET_CHANNEL_CONF(2, MAX197_RANGE_0_5) |
> -+ MAX197_SET_CHANNEL_CONF(3, MAX197_RANGE_0_5) |
> -+ MAX197_SET_CHANNEL_CONF(4, MAX197_RANGE_0_5) |
> -+ MAX197_SET_CHANNEL_CONF(5, MAX197_RANGE_0_5) |
> -+ MAX197_SET_CHANNEL_CONF(6, MAX197_RANGE_0_5) |
> -+ MAX197_SET_CHANNEL_CONF(7, MAX197_RANGE_0_5);
> -+
> -+ /* Register sysfs hooks */
> -+ if ((err = sysfs_create_group(&pdev->dev.kobj, &max197_group)))
> -+ goto exit_unmap2;
> -+
> -+ printk(PFX "TS-72xx max197 driver, v%s\n", DRV_VERSION);
> -+ return 0;
> -+
> -+exit_unmap2:
> -+ iounmap(conf.busy_bit_register);
> -+exit_unmap1:
> -+ iounmap(conf.control_and_data_register);
> -+exit:
> -+ return err;
> -+}
> -+
> -+static int __devexit ts72xx_max197_remove(struct platform_device *pdev)
> -+{
> -+ sysfs_remove_group(&pdev->dev.kobj, &max197_group);
> -+ iounmap(conf.busy_bit_register);
> -+ iounmap(conf.control_and_data_register);
> -+ return 0;
> -+}
> -+
> -+static struct platform_driver ts72xx_max197_platform_driver = {
> -+ .probe = ts72xx_max197_probe,
> -+ .remove = __devexit_p(ts72xx_max197_remove),
> -+ .driver = {
> -+ .name = "ts72xx-max197",
> -+ .owner = THIS_MODULE,
> -+ },
> -+};
> -+
> -+static int __init ts72xx_max197_init(void)
> -+{
> -+ return platform_driver_register(&ts72xx_max197_platform_driver);
> -+}
> -+
> -+static void __exit ts72xx_max197_exit(void)
> -+{
> -+ platform_driver_unregister(&ts72xx_max197_platform_driver);
> -+}
> -+
> -+#ifdef CONFIG_TS72XX_MAX197_AVERAGE
> -+module_param(average, ushort, S_IWUSR | S_IRUGO);
> -+MODULE_PARM_DESC(average, "Allow average measurement (default=1)");
> -+#endif
> -+
> -+MODULE_AUTHOR("Matthieu Crapet <mcrapet@gmail.com>");
> -+MODULE_DESCRIPTION("TS-72xx max197 driver");
> -+MODULE_LICENSE("GPL");
> -+MODULE_VERSION(DRV_VERSION);
> -+
> -+module_init(ts72xx_max197_init);
> -+module_exit(ts72xx_max197_exit);
> ---
> -1.7.0.4
> -
> diff --git a/recipes/linux/linux-2.6.36/ts72xx/0014-ts7200_nor_flash.patch b/recipes/linux/linux-2.6.36/ts72xx/0014-ts7200_nor_flash.patch
> deleted file mode 100644
> index e49e52a..0000000
> --- a/recipes/linux/linux-2.6.36/ts72xx/0014-ts7200_nor_flash.patch
> +++ /dev/null
> @@ -1,181 +0,0 @@
> -From 57271199c60faf7f9b7fab8bd8c34b0936df0bfa Mon Sep 17 00:00:00 2001
> -From: Matthieu Crapet <mcrapet@gmail.com>
> -Date: Sat, 19 Jun 2010 16:56:48 +0200
> -Subject: [PATCH 14/24] ts7200_nor_flash
> -MIME-Version: 1.0
> -Content-Type: text/plain; charset=UTF-8
> -Content-Transfer-Encoding: 8bit
> -
> -Deal with 8mb or 16mb NOR Flash (TS-7200 only)
> -
> -Signed-off-by: Petr Štetiar <ynezz@true.cz>
> ----
> - drivers/mtd/maps/Kconfig | 15 +++++
> - drivers/mtd/maps/Makefile | 1 +
> - drivers/mtd/maps/ts7200_flash.c | 116 +++++++++++++++++++++++++++++++++++++++
> - 3 files changed, 132 insertions(+), 0 deletions(-)
> - create mode 100644 drivers/mtd/maps/ts7200_flash.c
> -
> -diff --git a/drivers/mtd/maps/Kconfig b/drivers/mtd/maps/Kconfig
> -index 701d942..c7fd9e7 100644
> ---- a/drivers/mtd/maps/Kconfig
> -+++ b/drivers/mtd/maps/Kconfig
> -@@ -414,6 +414,21 @@ config MTD_H720X
> - This enables access to the flash chips on the Hynix evaluation boards.
> - If you have such a board, say 'Y'.
> -
> -+config MTD_TS7200_NOR
> -+ tristate "CFI Flash device mapped on TS-7200"
> -+ depends on MTD_CFI && MACH_TS72XX
> -+ help
> -+ This provides a map driver for the on-board flash of the Technologic
> -+ System's TS-7200 board. The 8MB (or 16MB) flash is splitted into 3 partitions
> -+ which are accessed as separate MTD devices.
> -+
> -+config MTD_TS7200_NOR_SIZE
> -+ int "Flash size (8 or 16mb)"
> -+ depends on MTD_TS7200_NOR
> -+ default "8"
> -+ help
> -+ Enter the NOR Flash size of your TS-7200 board. Can be 8 or 16.
> -+
> - # This needs CFI or JEDEC, depending on the cards found.
> - config MTD_PCI
> - tristate "PCI MTD driver"
> -diff --git a/drivers/mtd/maps/Makefile b/drivers/mtd/maps/Makefile
> -index f216bb5..21f9bd8 100644
> ---- a/drivers/mtd/maps/Makefile
> -+++ b/drivers/mtd/maps/Makefile
> -@@ -55,6 +55,7 @@ obj-$(CONFIG_MTD_DMV182) += dmv182.o
> - obj-$(CONFIG_MTD_PLATRAM) += plat-ram.o
> - obj-$(CONFIG_MTD_INTEL_VR_NOR) += intel_vr_nor.o
> - obj-$(CONFIG_MTD_BFIN_ASYNC) += bfin-async-flash.o
> -+obj-$(CONFIG_MTD_TS7200_NOR) += ts7200_flash.o
> - obj-$(CONFIG_MTD_RBTX4939) += rbtx4939-flash.o
> - obj-$(CONFIG_MTD_VMU) += vmu-flash.o
> - obj-$(CONFIG_MTD_GPIO_ADDR) += gpio-addr-flash.o
> -diff --git a/drivers/mtd/maps/ts7200_flash.c b/drivers/mtd/maps/ts7200_flash.c
> -new file mode 100644
> -index 0000000..94fb4f4
> ---- /dev/null
> -+++ b/drivers/mtd/maps/ts7200_flash.c
> -@@ -0,0 +1,116 @@
> -+/*
> -+ * ts7200_flash.c - mapping for TS-7200 SBCs (8mb NOR flash)
> -+ * No platform_device resource is used here. All is hardcoded.
> -+ *
> -+ * (c) Copyright 2006-2010 Matthieu Crapet <mcrapet@gmail.com>
> -+ * Based on ts5500_flash.c by Sean Young <sean@mess.org>
> -+ *
> -+ * 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/module.h>
> -+#include <linux/types.h>
> -+#include <linux/kernel.h>
> -+#include <linux/init.h>
> -+#include <asm/io.h>
> -+#include <asm/sizes.h>
> -+#include <linux/mtd/mtd.h>
> -+#include <linux/mtd/map.h>
> -+#include <linux/mtd/partitions.h>
> -+#include <mach/ep93xx-regs.h>
> -+
> -+
> -+static struct mtd_info *mymtd;
> -+
> -+static struct map_info ts7200nor_map = {
> -+ .name = "Full TS-7200 NOR flash",
> -+ .size = 0, /* filled in later */
> -+ .bankwidth = 2,
> -+ .phys = EP93XX_CS6_PHYS_BASE,
> -+};
> -+
> -+/*
> -+ * MTD partitioning stuff
> -+ */
> -+#ifdef CONFIG_MTD_PARTITIONS
> -+
> -+#define TS7200_BOOTROM_PART_SIZE (SZ_128K)
> -+#define TS7200_REDBOOT_PART_SIZE (15*SZ_128K)
> -+
> -+static struct mtd_partition ts7200_nor_parts[] =
> -+{
> -+ {
> -+ .name = "TS-BOOTROM",
> -+ .offset = 0,
> -+ .size = TS7200_BOOTROM_PART_SIZE,
> -+ .mask_flags = MTD_WRITEABLE, /* force read-only */
> -+ },
> -+ {
> -+ .name = "RootFS",
> -+ .offset = MTDPART_OFS_APPEND,
> -+ .size = 0, /* filled in later */
> -+ },
> -+ {
> -+ .name = "Redboot",
> -+ .offset = MTDPART_OFS_APPEND,
> -+ .size = MTDPART_SIZ_FULL, /* up to the end */
> -+ }
> -+};
> -+#endif
> -+
> -+static int __init ts7200_nor_init(void)
> -+{
> -+ if (CONFIG_MTD_TS7200_NOR_SIZE <= 8)
> -+ ts7200nor_map.size = SZ_8M;
> -+ else
> -+ ts7200nor_map.size = SZ_16M;
> -+
> -+ printk(KERN_NOTICE "TS-7200 flash mapping: %ldmo at 0x%x\n",
> -+ ts7200nor_map.size / SZ_1M, ts7200nor_map.phys);
> -+
> -+ ts7200nor_map.virt = ioremap(ts7200nor_map.phys, ts7200nor_map.size - 1);
> -+ if (!ts7200nor_map.virt) {
> -+ printk("ts7200_flash: failed to ioremap\n");
> -+ return -EIO;
> -+ }
> -+
> -+ simple_map_init(&ts7200nor_map);
> -+ mymtd = do_map_probe("cfi_probe", &ts7200nor_map);
> -+ if (mymtd) {
> -+ mymtd->owner = THIS_MODULE;
> -+ add_mtd_device(mymtd);
> -+ #ifdef CONFIG_MTD_PARTITIONS
> -+ ts7200_nor_parts[1].size = ts7200nor_map.size - TS7200_REDBOOT_PART_SIZE;
> -+ return add_mtd_partitions(mymtd, ts7200_nor_parts, ARRAY_SIZE(ts7200_nor_parts));
> -+ #else
> -+ return 0;
> -+ #endif
> -+ }
> -+
> -+ iounmap(ts7200nor_map.virt);
> -+ return -ENXIO;
> -+}
> -+
> -+static void __exit ts7200_nor_exit(void)
> -+{
> -+ if (mymtd) {
> -+ del_mtd_device(mymtd);
> -+ map_destroy(mymtd);
> -+ mymtd = NULL;
> -+ }
> -+ if (ts7200nor_map.virt) {
> -+ iounmap(ts7200nor_map.virt);
> -+ ts7200nor_map.virt = 0;
> -+ }
> -+}
> -+
> -+module_init(ts7200_nor_init);
> -+module_exit(ts7200_nor_exit);
> -+
> -+MODULE_LICENSE("GPL");
> -+MODULE_AUTHOR("Matthieu Crapet <mcrapet@gmail.com>");
> -+MODULE_DESCRIPTION("MTD map driver for TS-7200 board");
> -+MODULE_VERSION("0.1");
> ---
> -1.7.0.4
> -
> diff --git a/recipes/linux/linux-2.6.36/ts72xx/0015-ts72xx_sdcard.patch b/recipes/linux/linux-2.6.36/ts72xx/0015-ts72xx_sdcard.patch
> deleted file mode 100644
> index c290172..0000000
> --- a/recipes/linux/linux-2.6.36/ts72xx/0015-ts72xx_sdcard.patch
> +++ /dev/null
> @@ -1,3298 +0,0 @@
> -From 66c9687c9f4530e301fb8ba14b657b3f4ee3c9c6 Mon Sep 17 00:00:00 2001
> -From: Matthieu Crapet <mcrapet@gmail.com>
> -Date: Sun, 20 Jun 2010 10:46:15 +0200
> -Subject: [PATCH 15/24] ts72xx_sdcard
> -MIME-Version: 1.0
> -Content-Type: text/plain; charset=UTF-8
> -Content-Transfer-Encoding: 8bit
> -
> -SD Card support for TS-7260. Device name is "tssda".
> -Patch based on work of Breton Saunders:
> -http://tech.groups.yahoo.com/group/ts-7000/message/15787
> -http://tech.groups.yahoo.com/group/ts-7000/message/16028
> -
> -Signed-off-by: Petr Štetiar <ynezz@true.cz>
> ----
> - arch/arm/mach-ep93xx/ts72xx.c | 24 +
> - drivers/block/Kconfig | 7 +
> - drivers/block/Makefile | 2 +
> - drivers/block/sdcore2.c | 2391 +++++++++++++++++++++++++++++++++++++++++
> - drivers/block/sdcore2.h | 372 +++++++
> - drivers/block/tssdcard.c | 415 +++++++
> - 6 files changed, 3211 insertions(+), 0 deletions(-)
> - create mode 100644 drivers/block/sdcore2.c
> - create mode 100644 drivers/block/sdcore2.h
> - create mode 100644 drivers/block/tssdcard.c
> -
> -diff --git a/arch/arm/mach-ep93xx/ts72xx.c b/arch/arm/mach-ep93xx/ts72xx.c
> -index 96a4d54..c99f112 100644
> ---- a/arch/arm/mach-ep93xx/ts72xx.c
> -+++ b/arch/arm/mach-ep93xx/ts72xx.c
> -@@ -233,6 +233,29 @@ static void __init ts72xx_register_flash(void)
> - }
> -
> - /*************************************************************************
> -+ * SD Card (TS-7260 only)
> -+ *************************************************************************/
> -+
> -+static struct resource ts72xx_sdcard_resource = {
> -+ .start = TS7260_SDCARD_PHYS_BASE,
> -+ .end = TS7260_SDCARD_PHYS_BASE + 0x20,
> -+ .flags = IORESOURCE_MEM,
> -+};
> -+
> -+static struct platform_device ts72xx_sdcard = {
> -+ .name = "ts72xx-sdcard",
> -+ .id = 0,
> -+ .num_resources = 1,
> -+ .resource = &ts72xx_sdcard_resource,
> -+};
> -+
> -+static void __init ts72xx_register_sdcard(void)
> -+{
> -+ if (board_is_ts7260() || board_is_ts7400() || board_is_ts7300())
> -+ platform_device_register(&ts72xx_sdcard);
> -+}
> -+
> -+/*************************************************************************
> - * RTC
> - *************************************************************************/
> - static unsigned char ts72xx_rtc_readbyte(unsigned long addr)
> -@@ -333,6 +356,7 @@ static void __init ts72xx_init_machine(void)
> - {
> - ep93xx_init_devices();
> - ts72xx_register_flash();
> -+ ts72xx_register_sdcard();
> - platform_device_register(&ts72xx_rtc_device);
> - platform_device_register(&ts72xx_wdt_device);
> -
> -diff --git a/drivers/block/Kconfig b/drivers/block/Kconfig
> -index de27768..80985f8 100644
> ---- a/drivers/block/Kconfig
> -+++ b/drivers/block/Kconfig
> -@@ -488,4 +488,11 @@ config BLK_DEV_HD
> -
> - If unsure, say N.
> -
> -+config BLK_DEV_TS72XX_SDCARD
> -+ tristate "TS-72XX SD Card support"
> -+ depends on ARCH_EP93XX && MACH_TS72XX
> -+ help
> -+ This option enables support SD Card control on Technologic Systems
> -+ TS-7260 SBC.
> -+
> - endif # BLK_DEV
> -diff --git a/drivers/block/Makefile b/drivers/block/Makefile
> -index aff5ac9..a4d0579 100644
> ---- a/drivers/block/Makefile
> -+++ b/drivers/block/Makefile
> -@@ -34,8 +34,10 @@ obj-$(CONFIG_VIODASD) += viodasd.o
> - obj-$(CONFIG_BLK_DEV_SX8) += sx8.o
> - obj-$(CONFIG_BLK_DEV_UB) += ub.o
> - obj-$(CONFIG_BLK_DEV_HD) += hd.o
> -+obj-$(CONFIG_BLK_DEV_TS72XX_SDCARD) += ts72xx_sdcard.o
> -
> - obj-$(CONFIG_XEN_BLKDEV_FRONTEND) += xen-blkfront.o
> - obj-$(CONFIG_BLK_DEV_DRBD) += drbd/
> -
> - swim_mod-objs := swim.o swim_asm.o
> -+ts72xx_sdcard-objs := tssdcard.o sdcore2.o
> -diff --git a/drivers/block/sdcore2.c b/drivers/block/sdcore2.c
> -new file mode 100644
> -index 0000000..6dadee1
> ---- /dev/null
> -+++ b/drivers/block/sdcore2.c
> -@@ -0,0 +1,2391 @@
> -+/*
> -+ * Copyright (c) 2006-2009, Technologic Systems
> -+ * All rights reserved.
> -+ */
> -+
> -+/*
> -+ * This code is 100% operating system/CPU independent-- not a single global
> -+ * reference, external symbol, or #include is required. Centric upon one data
> -+ * structure "struct sdcore". OS-specific callbacks for things like DMA
> -+ * acceleration and sleeping are defined by function pointers to OS-specific
> -+ * code in the struct sdcore. Minimally requires the os_sleep() callback to be
> -+ * implemented for proper SD card initialization and a pointer to start
> -+ * of SD card registers. Auto-determines TS SD core version. All other
> -+ * callback functions may be left NULL-- they are only to allow speed/CPU
> -+ * utilization improvements.
> -+ *
> -+ * 3 main public functions - sdreset(), sdread() and sdwrite(). sdreset()
> -+ * returns card size. OS specific shim is required to turn this
> -+ * simple API into the complicated, constantly changing, hacker "designed"
> -+ * horrible excuses for abstraction, block driver APIs required in other
> -+ * "modern" operating systems.
> -+ *
> -+ * Not all SD cards over the years have followed spec perfectly -- many
> -+ * don't even check CRC's on the CMD or DAT busses and some have problems
> -+ * (lock up) when reading/writing the last sectors with SD read/write multiple
> -+ * commands.
> -+ *
> -+ * The TS SD hardware cores are not much more than GPIO bit-bang cores with
> -+ * a few well-placed hardware optimizations to achieve reasonable
> -+ * performance goals. In the roughly 2000 lines of code that follow, there
> -+ * is support for all distinct TS hardware SD cores on PPC and ARM platforms,
> -+ * a generic (private) SD command layer, sdcmd(), and SD flash card
> -+ * (public) routines for initialization + read/write + some SD security
> -+ * features.
> -+ *
> -+ */
> -+
> -+/* Register offset definitions. TS-SDCORE is 4 regs total. */
> -+#define SDCMD 0
> -+#define SDGPIO 0 /* version 2 register */
> -+#define SDDAT 1
> -+#define SDSTAT2 1
> -+#define SDSTATE 2
> -+#define SDCTRL 3
> -+#define SDDAT2 4
> -+#define SDCMD2 8
> -+#define SDCTRL2 12
> -+#define SDLUN2 2
> -+
> -+struct sdcore {
> -+ /* virtual address of SD block register start, to be filled in
> -+ * by client code before calling any sdcore functions.
> -+ */
> -+ unsigned int sd_regstart;
> -+
> -+ /* public bits for sd_state bitfield, can be read from client code.
> -+ * Do not write! Other bits are used internally.
> -+ */
> -+ #define SDDAT_RX (1<<0)
> -+ #define SDDAT_TX (1<<1)
> -+ #define SDCMD_RX (1<<2)
> -+ #define SDCMD_TX (1<<3)
> -+ unsigned int sd_state;
> -+
> -+ /* Erase hint for subsequent sdwrite() call, used to optimize
> -+ * write throughput on multi-sector writes by pre-erasing this
> -+ * many sectors. XXX: this doesn't have much benefit on most SDs
> -+ */
> -+ unsigned int sd_erasehint;
> -+
> -+ /* Following this comment are 3 function pointer declarations to
> -+ * OS helper functions. The 'os_arg' member is passed as the
> -+ * first argument to the helpers and should be set by
> -+ * client code before issueing sdreset()
> -+ *
> -+ * os_dmastream(os_arg, buf, buflen)
> -+ * This function should look at sd_state and set up and run an
> -+ * appropriate DMA transfer. If buf is NULL, callee doesn't care
> -+ * about the actual data sent/received and helper function
> -+ * can do whatever it wants. Should return 0 when DMA transfer was
> -+ * run and completed successfully. If this function pointer is
> -+ * NULL, PIO methods of transfer will be used instead of DMA.
> -+ *
> -+ * os_dmaprep(os_arg, buf, buflen)
> -+ * This function is used to prepare an area of memory for a possible
> -+ * DMA transfer. This function is called once per distinct buffer
> -+ * passed in. After this function is called, os_dmastream() may be
> -+ * called one or more times (for sequential addresses) on subregions
> -+ * of the address range passed here. Should write-back or invalidate
> -+ * L1 cache lines and possibly look up physical addresses for buf
> -+ * passed in if I/O buffers. If 'os_dmaprep' is set to NULL, function
> -+ * call will not happen. (though os_dmastream() calls may still)
> -+ *
> -+ * os_delay(os_arg, microseconds)
> -+ * This function is supposed to delay or stall the processor for
> -+ * the passed in value number of microseconds.
> -+ */
> -+ void *os_arg;
> -+ int (*os_dmastream)(void *, unsigned char *, unsigned int);
> -+ void (*os_dmaprep)(void *, unsigned char *, unsigned int);
> -+ void (*os_delay)(void *, unsigned int);
> -+ void (*os_irqwait)(void *, unsigned int);
> -+ int (*os_powerok)(void *);
> -+ int (*os_timeout)(void *);
> -+ int (*os_reset_timeout)(void *);
> -+
> -+ /* If the SD card last successfully reset is write protected, this
> -+ * member will be non-zero.
> -+ */
> -+ unsigned int sd_wprot;
> -+
> -+ /* If this card may have been already initialized by TS-SDBOOT, place
> -+ * the magic token it placed in the EP93xx SYSCON ScratchReg1 here
> -+ * to avoid re-initialization.
> -+ */
> -+ unsigned int sdboot_token;
> -+
> -+ /* CRC hint for subsequent sdwrite() call, used to optimize
> -+ * write throughput while using DMA by pre-calculating CRC's for
> -+ * next write
> -+ */
> -+ unsigned char *sd_crchint;
> -+
> -+ /* The block size of the memory device. Normally 512, but can be 1024
> -+ * for larger cards
> -+ */
> -+ unsigned int sd_blocksize;
> -+
> -+ /* Password for auto-unlocking in sdreset()
> -+ */
> -+ unsigned char *sd_pwd;
> -+
> -+ /* If the SD card was password locked, this will be non-zero.
> -+ */
> -+ unsigned int sd_locked;
> -+
> -+ /* Whether or not writes can be parked.
> -+ */
> -+ unsigned int sd_writeparking;
> -+
> -+ /* Logical unit number. Some SD cores will have multiple card slots.
> -+ */
> -+ unsigned int sd_lun;
> -+
> -+ /* The rest of these members are for private internal use and should
> -+ * not be of interest to client code.
> -+ */
> -+ unsigned int sd_rcaarg;
> -+ unsigned int sd_csd[17];
> -+ unsigned int sd_crcseq;
> -+ unsigned short sd_crcs[4];
> -+ unsigned int sd_crctmp[4];
> -+ unsigned int sd_timeout;
> -+ unsigned int parked_sector;
> -+ unsigned int hw_version;
> -+ unsigned char sd_scr[8];
> -+ unsigned int sd_sz;
> -+};
> -+
> -+/* For sdreadv() / sdwritev() */
> -+struct sdiov {
> -+ unsigned char *sdiov_base;
> -+ unsigned int sdiov_nsect;
> -+};
> -+
> -+int sdreset(struct sdcore *);
> -+int sdread(struct sdcore *, unsigned int, unsigned char *, int);
> -+int sdwrite(struct sdcore *, unsigned int, unsigned char *, int);
> -+int sdreadv(struct sdcore *, unsigned int, struct sdiov *, int);
> -+int sdwritev(struct sdcore *, unsigned int, struct sdiov *, int);
> -+int sdsetwprot(struct sdcore *, unsigned int);
> -+#define SDLOCK_UNLOCK 0
> -+#define SDLOCK_SETPWD 1
> -+#define SDLOCK_CLRPWD 2
> -+#define SDLOCK_ERASE 8
> -+#ifndef SD_NOLOCKSUPPORT
> -+int sdlockctl(struct sdcore *, unsigned int, unsigned char *, unsigned char *);
> -+#endif
> -+
> -+/*
> -+ * Everything below here is secret! This code shouldn't have to change
> -+ * even for different OS.
> -+ */
> -+
> -+const static unsigned short crc16tbl[256] = {
> -+ 0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7,
> -+ 0x8108, 0x9129, 0xa14a, 0xb16b, 0xc18c, 0xd1ad, 0xe1ce, 0xf1ef,
> -+ 0x1231, 0x0210, 0x3273, 0x2252, 0x52b5, 0x4294, 0x72f7, 0x62d6,
> -+ 0x9339, 0x8318, 0xb37b, 0xa35a, 0xd3bd, 0xc39c, 0xf3ff, 0xe3de,
> -+ 0x2462, 0x3443, 0x0420, 0x1401, 0x64e6, 0x74c7, 0x44a4, 0x5485,
> -+ 0xa56a, 0xb54b, 0x8528, 0x9509, 0xe5ee, 0xf5cf, 0xc5ac, 0xd58d,
> -+ 0x3653, 0x2672, 0x1611, 0x0630, 0x76d7, 0x66f6, 0x5695, 0x46b4,
> -+ 0xb75b, 0xa77a, 0x9719, 0x8738, 0xf7df, 0xe7fe, 0xd79d, 0xc7bc,
> -+ 0x48c4, 0x58e5, 0x6886, 0x78a7, 0x0840, 0x1861, 0x2802, 0x3823,
> -+ 0xc9cc, 0xd9ed, 0xe98e, 0xf9af, 0x8948, 0x9969, 0xa90a, 0xb92b,
> -+ 0x5af5, 0x4ad4, 0x7ab7, 0x6a96, 0x1a71, 0x0a50, 0x3a33, 0x2a12,
> -+ 0xdbfd, 0xcbdc, 0xfbbf, 0xeb9e, 0x9b79, 0x8b58, 0xbb3b, 0xab1a,
> -+ 0x6ca6, 0x7c87, 0x4ce4, 0x5cc5, 0x2c22, 0x3c03, 0x0c60, 0x1c41,
> -+ 0xedae, 0xfd8f, 0xcdec, 0xddcd, 0xad2a, 0xbd0b, 0x8d68, 0x9d49,
> -+ 0x7e97, 0x6eb6, 0x5ed5, 0x4ef4, 0x3e13, 0x2e32, 0x1e51, 0x0e70,
> -+ 0xff9f, 0xefbe, 0xdfdd, 0xcffc, 0xbf1b, 0xaf3a, 0x9f59, 0x8f78,
> -+ 0x9188, 0x81a9, 0xb1ca, 0xa1eb, 0xd10c, 0xc12d, 0xf14e, 0xe16f,
> -+ 0x1080, 0x00a1, 0x30c2, 0x20e3, 0x5004, 0x4025, 0x7046, 0x6067,
> -+ 0x83b9, 0x9398, 0xa3fb, 0xb3da, 0xc33d, 0xd31c, 0xe37f, 0xf35e,
> -+ 0x02b1, 0x1290, 0x22f3, 0x32d2, 0x4235, 0x5214, 0x6277, 0x7256,
> -+ 0xb5ea, 0xa5cb, 0x95a8, 0x8589, 0xf56e, 0xe54f, 0xd52c, 0xc50d,
> -+ 0x34e2, 0x24c3, 0x14a0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405,
> -+ 0xa7db, 0xb7fa, 0x8799, 0x97b8, 0xe75f, 0xf77e, 0xc71d, 0xd73c,
> -+ 0x26d3, 0x36f2, 0x0691, 0x16b0, 0x6657, 0x7676, 0x4615, 0x5634,
> -+ 0xd94c, 0xc96d, 0xf90e, 0xe92f, 0x99c8, 0x89e9, 0xb98a, 0xa9ab,
> -+ 0x5844, 0x4865, 0x7806, 0x6827, 0x18c0, 0x08e1, 0x3882, 0x28a3,
> -+ 0xcb7d, 0xdb5c, 0xeb3f, 0xfb1e, 0x8bf9, 0x9bd8, 0xabbb, 0xbb9a,
> -+ 0x4a75, 0x5a54, 0x6a37, 0x7a16, 0x0af1, 0x1ad0, 0x2ab3, 0x3a92,
> -+ 0xfd2e, 0xed0f, 0xdd6c, 0xcd4d, 0xbdaa, 0xad8b, 0x9de8, 0x8dc9,
> -+ 0x7c26, 0x6c07, 0x5c64, 0x4c45, 0x3ca2, 0x2c83, 0x1ce0, 0x0cc1,
> -+ 0xef1f, 0xff3e, 0xcf5d, 0xdf7c, 0xaf9b, 0xbfba, 0x8fd9, 0x9ff8,
> -+ 0x6e17, 0x7e36, 0x4e55, 0x5e74, 0x2e93, 0x3eb2, 0x0ed1, 0x1ef0,
> -+};
> -+
> -+const static unsigned char destagger[256] = {
> -+ 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1,
> -+ 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3,
> -+ 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1,
> -+ 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3,
> -+ 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1,
> -+ 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3,
> -+ 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1,
> -+ 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3,
> -+ 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1,
> -+ 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3,
> -+ 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1,
> -+ 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3,
> -+ 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1,
> -+ 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3,
> -+ 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1,
> -+ 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3,
> -+};
> -+
> -+#ifndef MAX_SDCORES
> -+#define MAX_SDCORES 64
> -+#endif
> -+static struct sdcore *sdcores[MAX_SDCORES];
> -+
> -+static unsigned int crc7(unsigned int, const unsigned int *, unsigned int);
> -+static int sdreset2(struct sdcore *);
> -+static int version(struct sdcore *);
> -+static int sdfastinit(struct sdcore *sd);
> -+static int sdcmd2(struct sdcore *, unsigned short, unsigned int,
> -+ unsigned int *, unsigned char **);
> -+static int sdcmd(struct sdcore *, unsigned short, unsigned int,
> -+ unsigned int *, unsigned char **);
> -+static void mkcommand(unsigned int, unsigned int, unsigned int *);
> -+static int stop(struct sdcore *);
> -+static int stop2(struct sdcore *);
> -+static int sdread2(struct sdcore *, unsigned int, unsigned char *, int)
> -+ __attribute__ ((unused));
> -+static int do_read2(struct sdcore *, unsigned int, struct sdiov *,
> -+ unsigned int);
> -+static int do_read(struct sdcore *, unsigned int, struct sdiov *,
> -+ unsigned int);
> -+static int do_write(struct sdcore *, unsigned int, struct sdiov *,
> -+ unsigned int);
> -+static int do_write2(struct sdcore *, unsigned int, struct sdiov *,
> -+ unsigned int);
> -+static int sdsetwprot2(struct sdcore *, unsigned int);
> -+#ifndef SD_NOLOCKSUPPORT
> -+static int sdlockctl2(struct sdcore *, unsigned int, unsigned char *,
> -+ unsigned char *);
> -+#endif
> -+
> -+#ifndef SDPOKE8
> -+# define SDPOKE8(sd, x, y) \
> -+ *(volatile unsigned char *)((sd)->sd_regstart + (x)) = (y)
> -+#endif
> -+#ifndef SDPOKE32
> -+# define SDPOKE32(sd, x, y) \
> -+ *(volatile unsigned int *)((sd)->sd_regstart + (x)) = (y)
> -+#endif
> -+#ifndef SDPOKE16
> -+# define SDPOKE16(sd, x, y) \
> -+ *(volatile unsigned short *)((sd)->sd_regstart + (x)) = (y)
> -+#endif
> -+#ifndef SDPEEK8
> -+# define SDPEEK8(sd, x) *(volatile unsigned char *)((sd)->sd_regstart + (x))
> -+#endif
> -+#ifndef SDPEEK32
> -+# define SDPEEK32(sd, x) *(volatile unsigned int *)((sd)->sd_regstart + (x))
> -+#endif
> -+#ifndef SDPEEK16
> -+# define SDPEEK16(sd, x) *(volatile unsigned short *)((sd)->sd_regstart + (x))
> -+#endif
> -+
> -+#define S_DUMMY_CLK 0
> -+#define S_SEND_CMD 1
> -+#define S_WAIT_RESP 2
> -+#define S_RX_RESP 3
> -+#define S_WAIT_BUSY 4
> -+#define S_TX_WRITE 5
> -+#define S_CRC_CHECK 6
> -+#define S_OFF 7
> -+
> -+#define TYPE_SHORTRESP 2
> -+#define TYPE_LONGRESP 3
> -+#define TYPE_BSYRESP 4
> -+#define TYPE_NORESP 1
> -+#define TYPE_RXDAT 0
> -+#define TYPE_TXDAT 5
> -+#define TYPE_ABORT 6
> -+#define TYPE_RXDAT_IGNRESP 7
> -+
> -+#define CMD(idx, type) (0x40 | (idx) | ((type)<<8))
> -+
> -+#define CMD_GO_IDLE_STATE CMD(0, TYPE_NORESP)
> -+#define CMD_ALL_SEND_CID CMD(2, TYPE_LONGRESP)
> -+#define CMD_SEND_RELATIVE_ADDR CMD(3, TYPE_SHORTRESP)
> -+#define CMD_SWITCH_FUNC CMD(6, TYPE_RXDAT)
> -+#define CMD_SWITCH_FUNC2 CMD(6, TYPE_RXDAT_IGNRESP)
> -+#define CMD_SELECT_CARD CMD(7, TYPE_BSYRESP)
> -+#define CMD_DESELECT_CARD CMD(7, TYPE_NORESP)
> -+#define CMD_SEND_IF_COND CMD(8, TYPE_SHORTRESP)
> -+#define CMD_SEND_CSD CMD(9, TYPE_LONGRESP)
> -+#define CMD_PROGRAM_CSD CMD(27, TYPE_TXDAT)
> -+#define CMD_SET_BLOCKLEN CMD(16, TYPE_SHORTRESP)
> -+#define CMD_LOCK_UNLOCK CMD(42, TYPE_TXDAT)
> -+#define CMD_APP_CMD CMD(55, TYPE_SHORTRESP)
> -+#define CMD_READ_SINGLE_BLOCK CMD(17, TYPE_RXDAT)
> -+#define CMD_READ_MULTIPLE_BLOCK CMD(18, TYPE_RXDAT)
> -+#define CMD_READ_MULTIPLE_BLOCK2 CMD(18, TYPE_RXDAT_IGNRESP)
> -+#define CMD_STOP_TRANSMISSION CMD(12, TYPE_ABORT)
> -+#define CMD_SEND_STATUS CMD(13, TYPE_SHORTRESP)
> -+#define CMD_WRITE_BLOCK CMD(24, TYPE_TXDAT)
> -+#define CMD_WRITE_MULTIPLE_BLOCK CMD(25, TYPE_TXDAT)
> -+
> -+#define ACMD_SD_SEND_OP_COND CMD(41, TYPE_SHORTRESP)
> -+#define ACMD_SET_CLR_CARD_DETECT CMD(42, TYPE_SHORTRESP)
> -+#define ACMD_SET_BUS_WIDTH CMD(6, TYPE_SHORTRESP)
> -+#define ACMD_SET_WR_BLK_ERASE_COUNT CMD(23, TYPE_SHORTRESP)
> -+#define ACMD_SEND_NUM_WR_BLOCKS CMD(22, TYPE_RXDAT)
> -+#define ACMD_SEND_SCR CMD(51, TYPE_RXDAT)
> -+#define ACMD_SEND_SCR2 CMD(51, TYPE_RXDAT_IGNRESP)
> -+
> -+/* Private bits for struct sdcore, sd_state member */
> -+#define DATSSP_NOCRC (1<<4)
> -+#define DATSSP_4BIT (1<<5)
> -+#define SD_HC (1<<6)
> -+#define SD_HISPEED (1<<7)
> -+#define SD_LOSPEED (1<<8)
> -+#define SD_SELECTED (1<<9)
> -+#define SD_RESET (1<<10)
> -+
> -+#define NULL ((void *)0)
> -+
> -+static void remember_sdcore(struct sdcore *sd) {
> -+ int i, newlun = 0;
> -+
> -+ for (i = 0; i < sizeof(sdcores); i++) {
> -+ if (sdcores[i] == NULL) {
> -+ /* new core, first reset */
> -+ sdcores[i] = sd;
> -+ /* core was almost definitely power-cycled on prev lun
> -+ * sdreset2(), so we don't need to have the sdreset2()
> -+ * do it again.
> -+ */
> -+ if (newlun) sd->sd_state = SD_RESET;
> -+ break;
> -+ } else if (sdcores[i]->sd_regstart == sd->sd_regstart) {
> -+ newlun = 1;
> -+ if (sdcores[i]->sd_lun == sd->sd_lun) {
> -+ sdcores[i] = sd;
> -+ break;
> -+ }
> -+ }
> -+ }
> -+}
> -+
> -+static int activate(struct sdcore *sd) {
> -+ int i;
> -+
> -+ /* Are we already selected? */
> -+ if ((sd->sd_state & (SD_SELECTED|SD_RESET)) == SD_SELECTED)
> -+ return 0;
> -+
> -+ /* Find currently activated SD slot for this HW core */
> -+ for (i = 0; i < sizeof(sdcores); i++) {
> -+ if (sdcores[i] == NULL) break;
> -+ if (sdcores[i]->sd_regstart == sd->sd_regstart &&
> -+ sdcores[i]->sd_state & SD_SELECTED) break;
> -+ }
> -+
> -+ /* Stop whatever parked transfer it has going on. */
> -+ if (sdcores[i]) {
> -+ stop2(sdcores[i]);
> -+ sdcores[i]->sd_state &= ~SD_SELECTED;
> -+ }
> -+
> -+ /* Change clock routing, mark us as selected */
> -+#ifdef BIGENDIAN
> -+ SDPOKE16(sd, SDLUN2, sd->sd_lun << 8);
> -+#else
> -+ SDPOKE16(sd, SDLUN2, sd->sd_lun);
> -+#endif
> -+
> -+ /* Change clock frequency */
> -+ if (sd->sd_state & SD_HISPEED) SDPOKE8(sd, SDSTAT2, 0x38);
> -+ else SDPOKE8(sd, SDSTAT2, 0x18);
> -+
> -+ sd->sd_state |= SD_SELECTED;
> -+ if (sd->sd_state & SD_RESET) return 1;
> -+ else return 0;
> -+
> -+}
> -+
> -+inline static unsigned short
> -+crc16_acc(unsigned short crc, unsigned int b)
> -+{
> -+ return (crc << 8) ^ crc16tbl[(crc >> 8) ^ b];
> -+}
> -+
> -+static void sd_initcrc(struct sdcore *sd)
> -+{
> -+ int i;
> -+
> -+ for (i = 0; i < 4; i++) {
> -+ sd->sd_crctmp[i] = 0;
> -+ sd->sd_crcs[i] = 0;
> -+ }
> -+ sd->sd_crcseq = 6;
> -+}
> -+
> -+static void sd_1bit_feedcrc(struct sdcore *sd, unsigned int dat)
> -+{
> -+ sd->sd_crcs[0] = crc16_acc(sd->sd_crcs[0], dat);
> -+}
> -+
> -+static void sd_4bit_feedcrc(struct sdcore *sd, unsigned int dat)
> -+{
> -+ unsigned int a = 0, b = 0, c = 0, d = 0;
> -+ unsigned int shift = (sd->sd_crcseq & 0x7);
> -+
> -+ a = sd->sd_crctmp[0];
> -+ b = sd->sd_crctmp[1];
> -+ c = sd->sd_crctmp[2];
> -+ d = sd->sd_crctmp[3];
> -+
> -+ a |= destagger[dat] << shift;
> -+ dat >>= 1;
> -+ b |= destagger[dat] << shift;
> -+ dat >>= 1;
> -+ c |= destagger[dat] << shift;
> -+ dat >>= 1;
> -+ d |= destagger[dat] << shift;
> -+
> -+ if (shift == 0) {
> -+ sd->sd_crcs[0] = crc16_acc(sd->sd_crcs[0], a);
> -+ sd->sd_crcs[1] = crc16_acc(sd->sd_crcs[1], b);
> -+ sd->sd_crcs[2] = crc16_acc(sd->sd_crcs[2], c);
> -+ sd->sd_crcs[3] = crc16_acc(sd->sd_crcs[3], d);
> -+ a = b = c = d = 0;
> -+ }
> -+
> -+ sd->sd_crcseq -= 2;
> -+ sd->sd_crctmp[0] = a;
> -+ sd->sd_crctmp[1] = b;
> -+ sd->sd_crctmp[2] = c;
> -+ sd->sd_crctmp[3] = d;
> -+}
> -+
> -+/* This should be called 8 times to get the full 8 bytes of CRC generated */
> -+static unsigned int sd_4bit_getcrc(struct sdcore *sd)
> -+{
> -+ static const unsigned char restaggertbl[4] = { 0x0, 0x1, 0x10, 0x11 };
> -+ static const unsigned char restaggertbl_lsl1[4] =
> -+ { 0x0, 0x2, 0x20, 0x22 };
> -+ static const unsigned char restaggertbl_lsl2[4] =
> -+ { 0x0, 0x4, 0x40, 0x44 };
> -+ static const unsigned char restaggertbl_lsl3[4] =
> -+ { 0x0, 0x8, 0x80, 0x88 };
> -+ unsigned int ret;
> -+
> -+ ret = restaggertbl[sd->sd_crcs[0] >> 14];
> -+ sd->sd_crcs[0] <<= 2;
> -+ ret |= restaggertbl_lsl1[sd->sd_crcs[1] >> 14];
> -+ sd->sd_crcs[1] <<= 2;
> -+ ret |= restaggertbl_lsl2[sd->sd_crcs[2] >> 14];
> -+ sd->sd_crcs[2] <<= 2;
> -+ ret |= restaggertbl_lsl3[sd->sd_crcs[3] >> 14];
> -+ sd->sd_crcs[3] <<= 2;
> -+
> -+ return ret;
> -+}
> -+
> -+/* This should be called 2 times to get the full 2 bytes of CRC generated */
> -+static unsigned int sd_1bit_getcrc(struct sdcore *sd)
> -+{
> -+ unsigned int ret;
> -+
> -+ ret = sd->sd_crcs[0] >> 8;
> -+ sd->sd_crcs[0] = (sd->sd_crcs[0] & 0xff) << 8;
> -+ return ret;
> -+}
> -+
> -+static inline void datssp_feedcrc(struct sdcore *sd, unsigned int dat)
> -+{
> -+ if (!(sd->sd_state & DATSSP_NOCRC)) {
> -+ if (sd->sd_state & DATSSP_4BIT) sd_4bit_feedcrc(sd, dat);
> -+ else sd_1bit_feedcrc(sd, dat);
> -+ }
> -+}
> -+
> -+static inline unsigned int datssp_getcrc(struct sdcore *sd)
> -+{
> -+ unsigned int ret = 0;
> -+
> -+ if (!(sd->sd_state & DATSSP_NOCRC)) {
> -+ if (sd->sd_state & DATSSP_4BIT) ret = sd_4bit_getcrc(sd);
> -+ else ret = sd_1bit_getcrc(sd);
> -+ }
> -+ return ret;
> -+}
> -+
> -+static inline unsigned int
> -+crc7(unsigned int crc, const unsigned int *pc, unsigned int len)
> -+{
> -+ unsigned int i;
> -+ unsigned char ibit;
> -+ unsigned char c;
> -+
> -+ for (i = 0; i < len; i++, pc++) {
> -+ c = *pc;
> -+ for (ibit = 0; ibit < 8; ibit++) {
> -+ crc <<= 1;
> -+ if ((c ^ crc) & 0x80) crc ^= 0x09;
> -+
> -+ c <<= 1;
> -+ }
> -+
> -+ crc &= 0x7F;
> -+ }
> -+
> -+ return crc;
> -+}
> -+
> -+static inline void
> -+mkcommand(unsigned int cmdidx, unsigned int arg, unsigned int *retcmd)
> -+{
> -+ retcmd[0] = cmdidx;
> -+ retcmd[1] = arg >> 24;
> -+ retcmd[2] = arg >> 16;
> -+ retcmd[3] = arg >> 8;
> -+ retcmd[4] = arg;
> -+ retcmd[5] = (0x1 | (crc7(0, retcmd, 5) << 1));
> -+}
> -+
> -+static inline void reset_timeout(struct sdcore *sd) {
> -+ sd->sd_timeout = 0;
> -+ if (sd->os_reset_timeout) sd->os_reset_timeout(sd);
> -+}
> -+
> -+static inline int timeout(struct sdcore *sd) {
> -+ if (sd->sd_timeout > 1000000) return 1;
> -+ else if (sd->os_timeout) return sd->os_timeout(sd);
> -+ else sd->sd_timeout++;
> -+ return 0;
> -+}
> -+
> -+static
> -+unsigned int sdsize(struct sdcore *sd)
> -+{
> -+ unsigned int csize, csize_mult, rd_bl_len;
> -+
> -+ if (sd->sd_sz != 0) return sd->sd_sz;
> -+
> -+ if (sd->sd_csd[1] & 0xc0) {
> -+ csize = (sd->sd_csd[10] | (sd->sd_csd[9] << 8));
> -+ sd->sd_sz = (csize + 1) * 1024;
> -+ } else {
> -+ rd_bl_len = 1 << ((sd->sd_csd[6] & 0xf) - 9);
> -+ csize = ((sd->sd_csd[7] & 0x03) << 10) |
> -+ ((sd->sd_csd[8] << 2) | ((sd->sd_csd[9] & 0xc0) >> 6));
> -+ csize_mult = ((sd->sd_csd[10] & 0x03) << 1) |
> -+ ((sd->sd_csd[11] & 0x80) >> 7);
> -+ sd->sd_sz = (csize + 1) * (1 << (csize_mult + 2)) * rd_bl_len;
> -+ }
> -+ return sd->sd_sz;
> -+}
> -+
> -+static unsigned int tend_ssp(struct sdcore *sd, unsigned int **cmdresp,
> -+ unsigned char **dat) {
> -+ unsigned int d;
> -+ unsigned int s = SDPEEK8(sd, SDSTATE);
> -+
> -+ if (s & 0x8) {
> -+ if (sd->sd_state & SDCMD_RX) {
> -+ d = SDPEEK8(sd, SDCMD);
> -+ if (cmdresp) {
> -+ **cmdresp = d;
> -+ *cmdresp = *cmdresp + 1;
> -+ reset_timeout(sd);
> -+ }
> -+ } else if (sd->sd_state & SDCMD_TX) {
> -+ SDPOKE8(sd, SDCMD, **cmdresp);
> -+ *cmdresp = *cmdresp + 1;
> -+ reset_timeout(sd);
> -+ }
> -+ }
> -+
> -+ if (s & 0x10) {
> -+ if (sd->sd_state & SDDAT_RX) {
> -+ d = SDPEEK8(sd, SDDAT);
> -+ if (dat) {
> -+ **dat = d;
> -+ *dat = *dat + 1;
> -+ reset_timeout(sd);
> -+ }
> -+ } else if (sd->sd_state & SDDAT_TX) {
> -+ reset_timeout(sd);
> -+ if (dat) {
> -+ d = **dat;
> -+ *dat = *dat + 1;
> -+ SDPOKE8(sd, SDDAT, d);
> -+ datssp_feedcrc(sd, d);
> -+ } else {
> -+ d = datssp_getcrc(sd);
> -+ SDPOKE8(sd, SDDAT, d);
> -+ }
> -+ }
> -+ }
> -+
> -+ return s;
> -+}
> -+
> -+static int
> -+error(unsigned int *resp, unsigned short req)
> -+{
> -+ unsigned int crc, status;
> -+
> -+ if ((req & 0x3f) != resp[0]) return 1;
> -+
> -+ crc = (0x1 | (crc7(0, resp, 5) << 1));
> -+ if (crc != resp[5]) return 1;
> -+
> -+ status = resp[1] << 24;
> -+ status |= resp[2] << 16;
> -+ status |= resp[3] << 8;
> -+ status |= resp[4];
> -+
> -+ return status & 0xfdf90008;
> -+}
> -+
> -+static int
> -+sdcmd2(struct sdcore *sd, unsigned short req, unsigned int arg,
> -+ unsigned int *resp, unsigned char **dat)
> -+{
> -+ unsigned int i, j, s, cmdresp[17];
> -+ unsigned int resplen;
> -+ unsigned int type = (req >> 8);
> -+ unsigned int cmdidx = req;
> -+ unsigned int *cmdptr = cmdresp;
> -+ unsigned int *respptr;
> -+ unsigned int dly;
> -+ int ok32 = (sd->hw_version == 2);
> -+ int ok16 = (ok32 || (sd->hw_version == 3));
> -+ int sddat2_8;
> -+
> -+ // If no space for response provided by caller, use local buffer
> -+ if (resp == NULL) resp = cmdresp;
> -+ respptr = resp;
> -+
> -+ if (activate(sd)) return 1;
> -+
> -+ dly = sd->sd_state & SD_LOSPEED;
> -+
> -+ if (!dly) {
> -+ unsigned int x;
> -+ SDPOKE8(sd, SDGPIO, 0xbf);
> -+#ifdef BIGENDIAN
> -+ x = (cmdidx & 0xff);
> -+ x |= ((arg >> 24) & 0xff) << 8;
> -+ x |= ((arg >> 16) & 0xff) << 16;
> -+ x |= ((arg >> 8) & 0xff) << 24;
> -+ if (ok32) SDPOKE32(sd, SDCMD2, x);
> -+ else if (ok16) {
> -+ SDPOKE16(sd, SDCMD2, x);
> -+ SDPOKE16(sd, SDCMD2, x >> 16);
> -+ } else {
> -+ SDPOKE8(sd, SDCMD2, x);
> -+ SDPOKE8(sd, SDCMD2, x >> 8);
> -+ SDPOKE8(sd, SDCMD2, x >> 16);
> -+ SDPOKE8(sd, SDCMD2, x >> 24);
> -+ }
> -+#else
> -+ x = (cmdidx & 0xff) << 24;
> -+ x |= ((arg >> 24) & 0xff) << 16;
> -+ x |= ((arg >> 16) & 0xff) << 8;
> -+ x |= ((arg >> 8) & 0xff);
> -+ if (ok32) SDPOKE32(sd, SDCMD2, x);
> -+ else if (ok16) {
> -+ SDPOKE16(sd, SDCMD2, x >> 16);
> -+ SDPOKE16(sd, SDCMD2, x);
> -+ } else {
> -+ SDPOKE8(sd, SDCMD2, x >> 24);
> -+ SDPOKE8(sd, SDCMD2, x >> 16);
> -+ SDPOKE8(sd, SDCMD2, x >> 8);
> -+ SDPOKE8(sd, SDCMD2, x);
> -+ }
> -+#endif
> -+ SDPOKE8(sd, SDCMD2, arg);
> -+ } else {
> -+ // Build command packet
> -+ mkcommand(cmdidx, arg, cmdptr);
> -+
> -+ // Send command
> -+ for (i = 0; i < 6; i++) {
> -+ unsigned int b = *cmdptr++;
> -+ unsigned int x;
> -+
> -+ if (timeout(sd)) break;
> -+ for (j = 0; j < 8; j++) {
> -+ x = 0x8f | ((b & 0x80) >> 3);
> -+ b = b << 1;
> -+ SDPOKE8(sd, SDGPIO, x); // clk negedge
> -+ SDPEEK8(sd, SDGPIO); // delay
> -+ SDPEEK8(sd, SDGPIO); // delay
> -+ x |= 0x20;
> -+ SDPOKE8(sd, SDGPIO, x); // clk posedge
> -+ SDPEEK8(sd, SDGPIO); // delay
> -+ SDPEEK8(sd, SDGPIO); // delay
> -+ }
> -+ }
> -+ }
> -+
> -+ if (type == TYPE_NORESP) goto done;
> -+ else if (type == TYPE_RXDAT_IGNRESP) goto ignresp;
> -+ else if (type == TYPE_LONGRESP) resplen = 17;
> -+ else resplen = 6;
> -+
> -+ // clock until start bit on CMD pin
> -+ while(1) {
> -+ if (timeout(sd)) {
> -+ goto done;
> -+ }
> -+ if (req == CMD_SEND_IF_COND) sd->sd_timeout += 100000;
> -+ SDPOKE8(sd, SDGPIO, 0xdf); // clk negedge
> -+ if (dly) SDPEEK8(sd, SDGPIO); // delay
> -+ s = SDPEEK8(sd, SDGPIO); // sample
> -+ if ((s & 0x10) == 0x0) break;
> -+ SDPOKE8(sd, SDGPIO, 0xff); // clk posedge
> -+ if (dly) SDPEEK8(sd, SDGPIO); // delay
> -+ }
> -+ reset_timeout(sd);
> -+
> -+ // Next we receive the response.
> -+ if (ok16 && !ok32) sddat2_8 = SDDAT2 + 1;
> -+ else sddat2_8 = SDDAT2;
> -+ if (dly) for (i = 0; i < resplen; i++) {
> -+ unsigned int r = 0;
> -+
> -+ for (j = 0; j < 8; j++) {
> -+ SDPOKE8(sd, SDGPIO, 0xdf); // clk negedge
> -+ SDPEEK8(sd, SDGPIO); // delay
> -+ s = SDPEEK8(sd, SDGPIO); // sample
> -+ SDPOKE8(sd, SDGPIO, 0xff); // clk posedge
> -+ SDPEEK8(sd, SDGPIO); // delay
> -+ SDPEEK8(sd, SDGPIO); // delay
> -+ r = r << 1;
> -+ r |= ((s & 0x10) >> 4);
> -+ }
> -+
> -+ *respptr++ = r;
> -+ } else while (resplen > 0) {
> -+ unsigned int r;
> -+
> -+#ifdef BIGENDIAN
> -+ if (ok32 && resplen >= 4) {
> -+ r = SDPEEK32(sd, SDCMD2);
> -+ *respptr++ = r & 0xff;
> -+ *respptr++ = (r >> 8) & 0xff;
> -+ *respptr++ = (r >> 16) & 0xff;
> -+ *respptr++ = (r >> 24);
> -+ resplen -= 4;
> -+ } else if (ok16 && resplen >= 2) {
> -+ r = SDPEEK16(sd, SDCMD2);
> -+ *respptr++ = r & 0xff;
> -+ *respptr++ = (r >> 8) & 0xff;
> -+
> -+ resplen -= 2;
> -+ } else {
> -+ *respptr++ = SDPEEK8(sd, sddat2_8);
> -+ resplen--;
> -+ }
> -+#else
> -+ if (ok32 && resplen >= 4) {
> -+ r = SDPEEK32(sd, SDCMD2);
> -+ *respptr++ = (r >> 24);
> -+ *respptr++ = (r >> 16) & 0xff;
> -+ *respptr++ = (r >> 8) & 0xff;
> -+ *respptr++ = r & 0xff;
> -+ resplen -= 4;
> -+ } else if (ok16 && resplen >= 2) {
> -+ r = SDPEEK16(sd, SDCMD2);
> -+ *respptr++ = (r >> 8) & 0xff;
> -+ *respptr++ = r & 0xff;
> -+ resplen -= 2;
> -+ } else {
> -+ *respptr++ = SDPEEK8(sd, sddat2_8);
> -+ resplen--;
> -+ }
> -+#endif
> -+ }
> -+ if (type == TYPE_BSYRESP) {
> -+ s = 0;
> -+ while ((s & 0x7) != 0x7) {
> -+ if (timeout(sd)) break;
> -+ SDPOKE8(sd, SDGPIO, 0x9f); // clk negedge
> -+ if (dly) SDPEEK8(sd, SDGPIO); // delay
> -+ s = s << 1;
> -+ s |= SDPEEK8(sd, SDGPIO) & 0x1;
> -+ SDPOKE8(sd, SDGPIO, 0xbf);
> -+ if (dly) SDPEEK8(sd, SDGPIO);
> -+ }
> -+ }
> -+
> -+ignresp:
> -+
> -+ if (type == TYPE_ABORT)
> -+ sd->sd_state &= ~(SDDAT_RX|SDDAT_TX);
> -+
> -+#ifndef SD_READONLYDMA
> -+ if (type == TYPE_TXDAT) {
> -+ sd->sd_state |= SDDAT_TX;
> -+ /* 2 clocks for nWR */
> -+ SDPOKE8(sd, SDGPIO, 0xdf); // clk negedge
> -+ if (dly) SDPEEK8(sd, SDGPIO); // delay
> -+ if (dly) SDPEEK8(sd, SDGPIO); // delay
> -+ SDPOKE8(sd, SDGPIO, 0xff); // clk posedge
> -+ if (dly) SDPEEK8(sd, SDGPIO); // delay
> -+ if (dly) SDPEEK8(sd, SDGPIO); // delay
> -+ SDPOKE8(sd, SDGPIO, 0xdf); // clk negedge
> -+ if (dly) SDPEEK8(sd, SDGPIO); // delay
> -+ if (dly) SDPEEK8(sd, SDGPIO); // delay
> -+ SDPOKE8(sd, SDGPIO, 0xff); // clk posedge
> -+ if (dly) SDPEEK8(sd, SDGPIO); // delay
> -+ if (dly) SDPEEK8(sd, SDGPIO); // delay
> -+ if (sd->sd_state & DATSSP_4BIT)
> -+ SDPOKE8(sd, SDGPIO, 0x10); // assert start, clk negedge
> -+ else
> -+ SDPOKE8(sd, SDGPIO, 0x1e);
> -+ if (dly) SDPEEK8(sd, SDGPIO); // delay
> -+ if (dly) SDPEEK8(sd, SDGPIO); // delay
> -+ if (sd->sd_state & DATSSP_4BIT)
> -+ SDPOKE8(sd, SDGPIO, 0x30); // clk posedge
> -+ else
> -+ SDPOKE8(sd, SDGPIO, 0x3e);
> -+ if (dly) SDPEEK8(sd, SDGPIO); // delay
> -+ if (dly) SDPEEK8(sd, SDGPIO); // delay
> -+ }
> -+#endif
> -+
> -+ if (type == TYPE_RXDAT || type == TYPE_RXDAT_IGNRESP)
> -+ sd->sd_state |= SDDAT_RX;
> -+
> -+done:
> -+ // 8 clocks before stopping
> -+ if (!(sd->sd_state & (SDDAT_TX|SDDAT_RX))) {
> -+ if (dly) for (i = 0; i < 8; i++) {
> -+ SDPOKE8(sd, SDGPIO, 0xdf);
> -+ SDPEEK8(sd, SDGPIO); // delay
> -+ SDPEEK8(sd, SDGPIO); // delay
> -+ SDPOKE8(sd, SDGPIO, 0xff);
> -+ SDPEEK8(sd, SDGPIO); // delay
> -+ SDPEEK8(sd, SDGPIO); // delay
> -+ } else {
> -+ SDPOKE8(sd, SDGPIO, 0xff);
> -+ SDPOKE8(sd, SDCMD2, 0xff);
> -+ }
> -+ }
> -+ if (timeout(sd)) return 1;
> -+ else return 0;
> -+
> -+}
> -+
> -+
> -+static int
> -+sdcmd(struct sdcore *sd, unsigned short req, unsigned int arg,
> -+ unsigned int *resp, unsigned char **dat)
> -+{
> -+ unsigned int s, cmdresp[17];
> -+ unsigned int resplen;
> -+ unsigned int type = (req >> 8);
> -+ unsigned int cmdidx = req;
> -+ unsigned int *cmdptr = cmdresp;
> -+ unsigned int *cmd = cmdresp;
> -+ unsigned int *respptr;
> -+ unsigned int ndat;
> -+
> -+ if (sd->hw_version != 0) return sdcmd2(sd, req, arg, resp, dat);
> -+
> -+ // If no space for response provided by caller, use local buffer
> -+ if (resp == NULL) resp = cmdresp;
> -+ respptr = resp;
> -+
> -+ // Before continuing, we must wait for the FSM to get to the
> -+ // S_SEND_CMD state. After a previous command, we may still be
> -+ // in S_DUMMY_CLK or in case of an ABORT, we may be in the middle of
> -+ // clocking a byte for TX or RX.
> -+ s = SDPEEK8(sd, SDSTATE);
> -+ while ((s & 0x7) != S_SEND_CMD) {
> -+ if (timeout(sd)) break;
> -+ s = SDPEEK8(sd, SDSTATE);
> -+ }
> -+
> -+ // We know we're in S_SEND_CMD, but we may need to change the
> -+ // command type. This won't cause a state change.
> -+ if ((s & 0xe7) != (S_SEND_CMD | (type << 5)))
> -+ SDPOKE8(sd, SDSTATE, S_SEND_CMD | (type << 5));
> -+
> -+ // Build command packet
> -+ mkcommand(cmdidx, arg, cmdptr);
> -+
> -+ // Next, we loop while tending the SSPs until we get our last
> -+ // byte of command data out. We may get a few bytes from the DAT
> -+ // SSP if we are aborting a previous data transfer command. If we do
> -+ // those get placed in a buffer or thrown away based on the callers
> -+ // "dat" parameter.
> -+ sd->sd_state |= SDCMD_TX;
> -+ while ((cmdptr - cmd) != 6) {
> -+ if (timeout(sd)) break;
> -+ s = tend_ssp(sd, &cmdptr, dat);
> -+ }
> -+ sd->sd_state &= ~SDCMD_TX;
> -+
> -+ // If we got out of sync with the hardware, that would be bad.
> -+ // The hardware should still be in S_SEND_CMD for the last CMDSSP
> -+ // byte.
> -+ if ((s & 0x7) != S_SEND_CMD) {
> -+ SDPOKE8(sd, SDSTATE, S_OFF);
> -+ return 1;
> -+ }
> -+
> -+ if (type == TYPE_NORESP) goto done;
> -+ else if (type == TYPE_LONGRESP) resplen = 17;
> -+ else resplen = 6;
> -+
> -+ // Next state should be S_WAIT_RESP or S_RX_RESP. We may get
> -+ // more bytes from the DATSSP while shifting out our last bits of cmd
> -+ while (((s & 0x7) != S_WAIT_RESP) && ((s & 0x7) != S_RX_RESP)) {
> -+ if (timeout(sd)) break;
> -+ if (req == CMD_SEND_IF_COND) sd->sd_timeout += 1000;
> -+ s = tend_ssp(sd, NULL, dat);
> -+ }
> -+
> -+ // Once we're in S_WAIT_RESP or S_RX_RESP though, the DATSSP is only
> -+ // active for 2 more clocks at the beginning of the S_WAIT_RESP state.
> -+ // This is enough for one more byte in 4-bit mode, though we may have
> -+ // 2 bytes already in our DATSSP.
> -+ if (sd->sd_state & (SDDAT_RX|SDDAT_TX)) {
> -+ do {
> -+ if (timeout(sd)) break;
> -+ s = tend_ssp(sd, NULL, dat);
> -+ } while (!(s & 0x18));
> -+
> -+ // We've now read/wrote one more byte to the DATSSP
> -+ // which should allow our FSM to advance to the RX_RESP state.
> -+ // If we pick up more than 2 more DATSSP bytes, something is
> -+ // wrong.
> -+ ndat = 0;
> -+ while ((s & 0x7) != S_RX_RESP) {
> -+ if (timeout(sd) || ndat > 2) break;
> -+ s = tend_ssp(sd, NULL, dat);
> -+ if (s & 0x10) ndat++;
> -+ }
> -+
> -+ if (ndat > 2) {
> -+ SDPOKE8(sd, SDSTATE, S_OFF);
> -+ return 1;
> -+ }
> -+ }
> -+
> -+ // We're now done with whatever business we had remaining with the
> -+ // previous command's DATSSP transfer since we've either just got our
> -+ // first byte of response or our last byte of data
> -+ sd->sd_state &= ~(SDDAT_RX|SDDAT_TX);
> -+ if (type == TYPE_RXDAT) sd->sd_state |= SDDAT_RX;
> -+
> -+ // Next we receive the response. If this is TYPE_RXDAT command,
> -+ // or an abortion of a previous TYPE_RXDAT command, we may get a
> -+ // few bytes from the DAT SSP also.
> -+ sd->sd_state |= SDCMD_RX;
> -+ while ((respptr - resp) != resplen) {
> -+ if (timeout(sd)) break;
> -+ s = tend_ssp(sd, &respptr, dat);
> -+ if ((s & 0x10) && (resp == respptr)) {
> -+ SDPOKE8(sd, SDSTATE, S_OFF);
> -+ sd->sd_state &= ~(SDCMD_RX|SDDAT_RX);
> -+ return 1;
> -+ }
> -+ }
> -+ sd->sd_state &= ~SDCMD_RX;
> -+
> -+ if (type == TYPE_ABORT)
> -+ sd->sd_state &= ~(SDDAT_RX|SDDAT_TX);
> -+
> -+ if (type == TYPE_TXDAT) sd->sd_state |= SDDAT_TX;
> -+
> -+done:
> -+ if (timeout(sd)) return 1;
> -+ else return 0;
> -+
> -+}
> -+
> -+static int datssp_stream2(struct sdcore *sd, unsigned char **dat,
> -+ unsigned int buflen)
> -+{
> -+ unsigned char *d;
> -+ int ret;
> -+#ifndef SD_READONLYDMA
> -+ int ok32;
> -+ int ok16;
> -+ int sddat2_8;
> -+ unsigned int x;
> -+#endif
> -+
> -+ if (sd->os_dmastream /* && (sd->sd_state & SDDAT_RX) */) {
> -+ d = dat ? *dat : NULL;
> -+ ret = sd->os_dmastream(sd->os_arg, d, buflen);
> -+ if (!ret && d) *dat += buflen;
> -+ return ret;
> -+ }
> -+
> -+#ifndef SD_READONLYDMA
> -+ d = *dat;
> -+
> -+ while (buflen > 512) {
> -+ datssp_stream2(sd, dat, 512);
> -+ if (sd->os_irqwait) sd->os_irqwait(sd->os_arg, 1);
> -+ buflen -= 512;
> -+ d = *dat;
> -+ }
> -+
> -+ ok32 = (sd->hw_version == 2);
> -+ ok16 = (ok32 || (sd->hw_version == 3));
> -+ if (ok16 && !ok32) sddat2_8 = SDDAT2 + 1;
> -+ else sddat2_8 = SDDAT2;
> -+
> -+ if (sd->sd_state & SDDAT_RX) {
> -+
> -+ while (((int)d & 0x1) || buflen == 1) {
> -+ *d++ = SDPEEK8(sd, sddat2_8);
> -+ buflen--;
> -+ }
> -+
> -+ if (((int)d & 0x2) && buflen >= 2) {
> -+ if (ok16) *(unsigned short *)(d) = SDPEEK16(sd, SDDAT2);
> -+ else {
> -+#ifdef BIGENDIAN
> -+ x = SDPEEK8(sd, sddat2_8) << 8;
> -+ x |= SDPEEK8(sd, sddat2_8);
> -+#else
> -+ x = SDPEEK8(sd, sddat2_8);
> -+ x |= SDPEEK8(sd, sddat2_8) << 8;
> -+#endif
> -+ *(unsigned short *)(d) = x;
> -+ }
> -+ buflen -= 2;
> -+ d += 2;
> -+ }
> -+
> -+ if (ok32) while (buflen >= 4) {
> -+ *(unsigned int *)(d) = SDPEEK32(sd, SDDAT2);
> -+ buflen -= 4;
> -+ d += 4;
> -+ } else if (ok16) while (buflen >= 4) {
> -+#ifdef BIGENDIAN
> -+ x = SDPEEK16(sd, SDDAT2) << 16;
> -+ x |= SDPEEK16(sd, SDDAT2);
> -+#else
> -+ x = SDPEEK16(sd, SDDAT2);
> -+ x |= SDPEEK16(sd, SDDAT2) << 16;
> -+#endif
> -+ buflen -= 4;
> -+ *(unsigned int *)(d) = x;
> -+ d += 4;
> -+ } else while (buflen >= 4) {
> -+#ifdef BIGENDIAN
> -+ x = SDPEEK8(sd, sddat2_8) << 24;
> -+ x |= SDPEEK8(sd, sddat2_8) << 16;
> -+ x |= SDPEEK8(sd, sddat2_8) << 8;
> -+ x |= SDPEEK8(sd, sddat2_8);
> -+#else
> -+ x = SDPEEK8(sd, sddat2_8);
> -+ x |= SDPEEK8(sd, sddat2_8) << 8;
> -+ x |= SDPEEK8(sd, sddat2_8) << 16;
> -+ x |= SDPEEK8(sd, sddat2_8) << 24;
> -+#endif
> -+ buflen -= 4;
> -+ *(unsigned int *)(d) = x;
> -+ d += 4;
> -+ }
> -+ } else {
> -+ while (((int)d & 0x1) || buflen == 1) {
> -+ SDPOKE8(sd, SDDAT2, *d++);
> -+ buflen--;
> -+ }
> -+
> -+ if (((int)d & 0x2) && buflen >= 2) {
> -+ if (ok16) SDPOKE16(sd, SDDAT2, *(unsigned short *)(d));
> -+ else {
> -+ x = *(unsigned short *)(d);
> -+#ifdef BIGENDIAN
> -+ SDPOKE8(sd, SDDAT2, x >> 8);
> -+ SDPOKE8(sd, SDDAT2, x);
> -+#else
> -+ SDPOKE8(sd, SDDAT2, x);
> -+ SDPOKE8(sd, SDDAT2, x >> 8);
> -+#endif
> -+ }
> -+ buflen -= 2;
> -+ d += 2;
> -+ }
> -+
> -+ if (ok32) while (buflen >= 4) {
> -+ SDPOKE32(sd, SDDAT2, *(unsigned int *)(d));
> -+ buflen -= 4;
> -+ d += 4;
> -+ } else if (ok16) while (buflen >= 4) {
> -+ x = *(unsigned int *)(d);
> -+ buflen -= 4;
> -+ d += 4;
> -+#ifdef BIGENDIAN
> -+ SDPOKE16(sd, SDDAT2, x >> 16);
> -+ SDPOKE16(sd, SDDAT2, x);
> -+#else
> -+ SDPOKE16(sd, SDDAT2, x);
> -+ SDPOKE16(sd, SDDAT2, x >> 16);
> -+#endif
> -+ } else while (buflen >= 4) {
> -+ x = *(unsigned int *)(d);
> -+ buflen -= 4;
> -+ d += 4;
> -+#ifdef BIGENDIAN
> -+ SDPOKE8(sd, SDDAT2, x >> 24);
> -+ SDPOKE8(sd, SDDAT2, x >> 16);
> -+ SDPOKE8(sd, SDDAT2, x >> 8);
> -+ SDPOKE8(sd, SDDAT2, x);
> -+#else
> -+ SDPOKE8(sd, SDDAT2, x);
> -+ SDPOKE8(sd, SDDAT2, x >> 8);
> -+ SDPOKE8(sd, SDDAT2, x >> 16);
> -+ SDPOKE8(sd, SDDAT2, x >> 24);
> -+#endif
> -+ }
> -+ }
> -+
> -+ *dat = d;
> -+
> -+ if (buflen > 0) return datssp_stream2(sd, dat, buflen);
> -+ else return 0;
> -+#else
> -+ return 0;
> -+#endif
> -+}
> -+
> -+static int datssp_stream(struct sdcore *sd, unsigned char **dat,
> -+ unsigned int buflen)
> -+{
> -+ unsigned int s, t, byte = 0;
> -+ unsigned char *d;
> -+
> -+ if (((sd->sd_state & SDDAT_RX) && sd->os_dmastream) /* ||
> -+ ((sd->sd_state & SDDAT_TX) && sd->os_dmastream && dat) */ ) {
> -+ unsigned char *d = dat ? *dat : NULL;
> -+ int ret = sd->os_dmastream(sd->os_arg, d, buflen);
> -+ if (!ret && d) *dat += buflen;
> -+ return ret;
> -+ }
> -+
> -+ if (sd->hw_version > 0) return datssp_stream2(sd, dat, buflen);
> -+
> -+ while (buflen) {
> -+ if (timeout(sd)) return 1;
> -+ s = tend_ssp(sd, NULL, dat);
> -+ if (s & 0x10) {
> -+ buflen--;
> -+ if (byte++ > 7) {
> -+ if (sd->sd_state & SDDAT_RX)
> -+ goto fastrx;
> -+ else goto fasttx;
> -+ }
> -+ }
> -+ }
> -+
> -+ // Now we can go faster (PIO)
> -+fastrx:
> -+ if (dat) {
> -+ d = *dat;
> -+ while (buflen) {
> -+ s = SDPEEK8(sd, SDDAT);
> -+ *d = s;
> -+ buflen--;
> -+ d++;
> -+ }
> -+ *dat = d;
> -+ } else {
> -+ while (buflen--) SDPEEK8(sd, SDDAT);
> -+ }
> -+ return 0;
> -+
> -+fasttx:
> -+ if (dat) {
> -+ d = *dat;
> -+ while (buflen) {
> -+ t = *d;
> -+ SDPOKE8(sd, SDDAT, t);
> -+ buflen--;
> -+ d++;
> -+ datssp_feedcrc(sd, t);
> -+ }
> -+ *dat = d;
> -+ } else {
> -+ while (buflen--) SDPOKE8(sd, SDDAT, datssp_getcrc(sd));
> -+ }
> -+ return 0;
> -+}
> -+
> -+static int stop(struct sdcore *sd)
> -+{
> -+ int ret;
> -+ unsigned int resp[6];
> -+
> -+ if (sd->hw_version) return stop2(sd);
> -+
> -+ if (sd->parked_sector) {
> -+ if (sd->sd_state & SDDAT_TX) {
> -+ /* wait to get out of S_WAIT_BUSY */
> -+ while ((SDPEEK8(sd, SDSTATE) & 0x7) != S_TX_WRITE)
> -+ if (timeout(sd)) break;
> -+
> -+ /* abort parked write */
> -+ SDPOKE8(sd, SDSTATE, S_SEND_CMD | (TYPE_ABORT << 5));
> -+ sd->sd_state &= ~SDDAT_TX;
> -+ sd->sd_state |= SDDAT_RX;
> -+ ret = sdcmd(sd, CMD_STOP_TRANSMISSION, 0, resp, NULL);
> -+ sd->sd_state &= ~SDDAT_RX;
> -+ SDPOKE8(sd, SDSTATE, S_WAIT_BUSY | (TYPE_BSYRESP << 5));
> -+ } else {
> -+ /* abort parked read */
> -+ SDPOKE8(sd, SDSTATE, S_SEND_CMD | (TYPE_ABORT << 5));
> -+ ret = sdcmd(sd, CMD_STOP_TRANSMISSION, 0, resp, NULL);
> -+ }
> -+ sd->parked_sector = 0;
> -+ if (ret || error(resp, CMD_STOP_TRANSMISSION) || timeout(sd))
> -+ return 1;
> -+ }
> -+ return 0;
> -+}
> -+
> -+static int stop2(struct sdcore *sd)
> -+{
> -+ int ret;
> -+ unsigned int resp[6];
> -+
> -+ if (sd->parked_sector) {
> -+ if (sd->os_irqwait) sd->os_irqwait(sd->os_arg, 0);
> -+ if (sd->sd_state & SDDAT_TX) {
> -+ /* abort parked write */
> -+ ret = sdcmd2(sd, CMD_STOP_TRANSMISSION, 0, resp, NULL);
> -+ SDPOKE8(sd, SDCTRL2, 0x0);
> -+ if (sd->os_irqwait) sd->os_irqwait(sd->os_arg, 5);
> -+ SDPOKE8(sd, SDGPIO, 0xff);
> -+
> -+ /*
> -+ while ((SDPEEK8(sd, SDGPIO) & 0xf) != 0xf) {
> -+ sd->os_delay(sd->os_arg, 1);
> -+ SDPOKE8(sd, SDGPIO, 0xdf);
> -+ SDPOKE8(sd, SDGPIO, 0xff);
> -+ if (timeout(sd)) return 1;
> -+ }
> -+ */
> -+ reset_timeout(sd);
> -+ } else {
> -+ /* abort parked read */
> -+ ret = sdcmd2(sd, CMD_STOP_TRANSMISSION, 0, resp, NULL);
> -+ }
> -+ sd->parked_sector = 0;
> -+ if (ret || error(resp, CMD_STOP_TRANSMISSION) || timeout(sd)) {
> -+ return 1;
> -+ }
> -+ }
> -+ return 0;
> -+}
> -+
> -+static int do_read2(struct sdcore *sd, unsigned int sector, struct sdiov *iov,
> -+ unsigned int iovcnt)
> -+{
> -+ unsigned int ret, n, s, sz;
> -+ unsigned char *datptr, *dat;
> -+
> -+ if (iovcnt == 0) return 0;
> -+
> -+ if (activate(sd)) return 1;
> -+
> -+ n = iov->sdiov_nsect;
> -+ datptr = dat = iov->sdiov_base;
> -+ sz = sdsize(sd);
> -+ if (sector >= sz) return 0;
> -+
> -+ if (sd->parked_sector) {
> -+ if (!(sd->sd_state & SDDAT_TX) && sd->parked_sector == sector) {
> -+ if (sd->os_irqwait && !sd->os_dmastream)
> -+ sd->os_irqwait(sd->os_arg, 3);
> -+ goto receive;
> -+ }
> -+
> -+ stop2(sd);
> -+ }
> -+
> -+ if (sd->sd_state & SD_HC)
> -+ ret = sdcmd2(sd, CMD_READ_MULTIPLE_BLOCK2, sector, NULL, NULL);
> -+ else
> -+ ret = sdcmd2(sd, CMD_READ_MULTIPLE_BLOCK2, sector * 512, NULL, NULL);
> -+
> -+ do {
> -+ if (timeout(sd)) return 1;;
> -+ SDPOKE8(sd, SDGPIO, 0xdf);
> -+ s = SDPEEK8(sd, SDGPIO);
> -+ SDPOKE8(sd, SDGPIO, 0xff);
> -+ } while ((s & 0xf) != 0x0);
> -+ reset_timeout(sd);
> -+
> -+receive:
> -+ if (sd->os_dmaprep && sd->os_dmastream)
> -+ sd->os_dmaprep(sd->os_arg, datptr, n * 512);
> -+
> -+ SDPOKE8(sd, SDGPIO, 0xdf);
> -+ sd->parked_sector = sector + n;
> -+
> -+nextiov:
> -+ if (sd->parked_sector > sz) {
> -+ n -= sd->parked_sector - sz;
> -+ sd->parked_sector = sz;
> -+ }
> -+ datssp_stream2(sd, &datptr, n * 512);
> -+
> -+ if (--iovcnt) {
> -+ ++iov;
> -+ n = iov->sdiov_nsect;
> -+ datptr = iov->sdiov_base;
> -+ sd->parked_sector += n;
> -+ if (sd->os_dmaprep && sd->os_dmastream)
> -+ sd->os_dmaprep(sd->os_arg, datptr, n * 512);
> -+ goto nextiov;
> -+ }
> -+
> -+ /* s = SDPEEK8(sd, SDSTAT2);
> -+ if (s & 0x44) {
> -+ sd->sd_timeout = 1000001;
> -+ return 1;
> -+ }
> -+ else */ return 0;
> -+}
> -+
> -+static int do_read(struct sdcore *sd, unsigned int sector, struct sdiov *iov,
> -+ unsigned int iovcnt)
> -+{
> -+ unsigned int resp[6], ret, n, sz;
> -+ unsigned char *datptr, *dat;
> -+
> -+ if (iovcnt == 0) return 0;
> -+
> -+ n = iov->sdiov_nsect;
> -+ datptr = dat = iov->sdiov_base;
> -+ sz = sdsize(sd);
> -+ if (sector >= sz) return 0;
> -+
> -+ if (sd->parked_sector) {
> -+ if (!(sd->sd_state & SDDAT_TX) && sd->parked_sector == sector)
> -+ goto receive;
> -+
> -+ stop(sd);
> -+ }
> -+
> -+ if (sd->sd_state & SD_HC)
> -+ ret = sdcmd(sd, CMD_READ_MULTIPLE_BLOCK, sector, resp, &datptr);
> -+ else
> -+ ret = sdcmd(sd, CMD_READ_MULTIPLE_BLOCK, sector * 512, resp, &datptr);
> -+ if (ret || error(resp, CMD_READ_MULTIPLE_BLOCK)) return 1;
> -+
> -+receive:
> -+ if (sd->os_dmaprep && sd->os_dmastream)
> -+ sd->os_dmaprep(sd->os_arg, datptr, n * 512 - (datptr - dat));
> -+
> -+ datssp_stream(sd, &datptr, 512 - (datptr - dat));
> -+ datssp_stream(sd, NULL, 6);
> -+
> -+ sd->parked_sector = sector + n;
> -+ if (sd->parked_sector > sz) {
> -+ n -= sd->parked_sector - sz;
> -+ sd->parked_sector = sz;
> -+ }
> -+ n--;
> -+
> -+nextiov:
> -+ while (n--) {
> -+ SDPOKE8(sd, SDSTATE, S_WAIT_RESP | (TYPE_RXDAT << 5));
> -+ datssp_stream(sd, NULL, 2); // last part of prev CRC
> -+ datssp_stream(sd, &datptr, 512);
> -+ datssp_stream(sd, NULL, 6); // first part of CRC
> -+ }
> -+
> -+ if (--iovcnt) {
> -+ ++iov;
> -+ n = iov->sdiov_nsect;
> -+ datptr = iov->sdiov_base;
> -+ sd->parked_sector += n;
> -+ if (sd->parked_sector > sz) {
> -+ n -= sd->parked_sector - sz;
> -+ sd->parked_sector = sz;
> -+ }
> -+ if (sd->os_dmaprep && sd->os_dmastream && n > 0)
> -+ sd->os_dmaprep(sd->os_arg, datptr, n * 512);
> -+ goto nextiov;
> -+ }
> -+
> -+ SDPOKE8(sd, SDSTATE, S_WAIT_RESP | (TYPE_RXDAT << 5));
> -+ datssp_stream(sd, NULL, 2); // last part of prev CRC
> -+ return 0;
> -+}
> -+
> -+static int do_write2(struct sdcore *sd, unsigned int sector, struct sdiov *iov,
> -+ unsigned int iovcnt)
> -+{
> -+ unsigned char *datptr;
> -+ unsigned int resp[6], ret, n, s, sz, ss;
> -+
> -+ if (sd->sd_wprot) return 1;
> -+
> -+ if (iovcnt == 0) return 0;
> -+
> -+ if (activate(sd)) return 1;
> -+
> -+ sz = sdsize(sd);
> -+ if (sector >= sz) return 0;
> -+
> -+ if (sd->os_powerok) {
> -+ int ok = sd->os_powerok(sd);
> -+ if (!ok && sd->parked_sector) {
> -+ stop2(sd);
> -+ return 1;
> -+ } else if (!ok) return 1;
> -+ }
> -+
> -+ if (sd->parked_sector) {
> -+ if ((sd->sd_state & SDDAT_TX) && sd->parked_sector == sector)
> -+ goto transmit;
> -+
> -+ stop2(sd);
> -+ }
> -+
> -+ if (sd->sd_erasehint) {
> -+ sdcmd2(sd, CMD_APP_CMD, sd->sd_rcaarg, NULL, NULL);
> -+ sdcmd2(sd, ACMD_SET_WR_BLK_ERASE_COUNT, sd->sd_erasehint,
> -+ NULL, NULL);
> -+ sd->sd_erasehint = 0;
> -+ }
> -+
> -+ if (sd->sd_state & SD_HC)
> -+ ret = sdcmd2(sd, CMD_WRITE_MULTIPLE_BLOCK, sector, resp, NULL);
> -+ else
> -+ ret = sdcmd2(sd, CMD_WRITE_MULTIPLE_BLOCK, sector * 512, resp, NULL);
> -+ if (ret || error(resp, CMD_WRITE_MULTIPLE_BLOCK)) {
> -+ return 1;
> -+ }
> -+ sd->parked_sector = sector;
> -+ ss = SDPEEK8(sd, SDSTAT2);
> -+
> -+transmit:
> -+ while (iovcnt--) {
> -+ datptr = iov->sdiov_base;
> -+ n = iov->sdiov_nsect;
> -+ sd->parked_sector += n;
> -+ if (sd->parked_sector > sz) {
> -+ n -= sd->parked_sector - sz;
> -+ sd->parked_sector = sz;
> -+ }
> -+ datssp_stream2(sd, &datptr, n * 512);
> -+ iov++;
> -+ }
> -+
> -+ if (!sd->sd_writeparking) {
> -+ ret = stop2(sd);
> -+ if (ret) return ret;
> -+ }
> -+
> -+ if (sd->os_irqwait) sd->os_irqwait(sd->os_arg, 2);
> -+
> -+ s = SDPEEK8(sd, SDSTAT2);
> -+ if (s & 0x44) {
> -+ sd->sd_timeout = 1000001;
> -+ return 1;
> -+ } else {
> -+ reset_timeout(sd);
> -+ return 0;
> -+ }
> -+}
> -+
> -+static int do_write(struct sdcore *sd, unsigned int sector, struct sdiov *iov,
> -+ unsigned int iovcnt)
> -+{
> -+ unsigned char *datptr, *crcptr, **crcptrptr;
> -+ unsigned int resp[6], ret, n, sz;
> -+
> -+ if (sd->sd_wprot) return 1;
> -+
> -+ if (iovcnt == 0) return 0;
> -+
> -+ sz = sdsize(sd);
> -+ if (sector >= sz) return 0;
> -+
> -+ if (0 /* sd->sd_crchint */) {
> -+ // CRC is pre-calculated so don't recalculate
> -+ crcptr = sd->sd_crchint;
> -+ crcptrptr = &crcptr;
> -+ sd->sd_state |= DATSSP_NOCRC;
> -+ sd->sd_crchint = NULL;
> -+ } else {
> -+ crcptrptr = NULL;
> -+ sd->sd_state &= ~DATSSP_NOCRC;
> -+ }
> -+
> -+ if (sd->parked_sector) {
> -+ if ((sd->sd_state & SDDAT_TX) && sd->parked_sector == sector)
> -+ goto transmit;
> -+
> -+ stop(sd);
> -+ }
> -+
> -+ if (sd->sd_erasehint) {
> -+ sdcmd(sd, CMD_APP_CMD, sd->sd_rcaarg, NULL, NULL);
> -+ sdcmd(sd, ACMD_SET_WR_BLK_ERASE_COUNT, sd->sd_erasehint,
> -+ NULL, NULL);
> -+ sd->sd_erasehint = 0;
> -+ }
> -+
> -+ if (sd->sd_state & SD_HC)
> -+ ret = sdcmd(sd, CMD_WRITE_MULTIPLE_BLOCK, sector, resp, NULL);
> -+ else
> -+ ret = sdcmd(sd, CMD_WRITE_MULTIPLE_BLOCK, sector * 512, resp, NULL);
> -+ if (ret || error(resp, CMD_WRITE_MULTIPLE_BLOCK)) {
> -+ return 1;
> -+ }
> -+ sd->parked_sector = sector;
> -+
> -+transmit:
> -+ while (iovcnt--) {
> -+ datptr = iov->sdiov_base;
> -+ n = iov->sdiov_nsect;
> -+ sd->parked_sector += n;
> -+ if (sd->parked_sector > sz) {
> -+ n -= sd->parked_sector - sz;
> -+ sd->parked_sector = sz;
> -+ }
> -+ while (n--) {
> -+ datssp_stream(sd, &datptr, 512);
> -+ datssp_stream(sd, crcptrptr, 8); // CRC bytes
> -+ SDPOKE8(sd, SDSTATE, S_CRC_CHECK | (TYPE_TXDAT << 5));
> -+ }
> -+ iov++;
> -+ }
> -+
> -+ if (!sd->sd_writeparking) {
> -+ stop(sd);
> -+ }
> -+
> -+ return 0;
> -+}
> -+
> -+static
> -+int sdfastinit(struct sdcore *sd)
> -+{
> -+ SDPOKE8(sd, SDCTRL, 0x40);
> -+ sd->sd_state = DATSSP_4BIT;
> -+
> -+ sd->sd_rcaarg = ~sd->sdboot_token;
> -+ sdcmd(sd, CMD_DESELECT_CARD, ~sd->sd_rcaarg, NULL, NULL);
> -+ sdcmd(sd, CMD_SEND_CSD, sd->sd_rcaarg, sd->sd_csd, NULL);
> -+ sdcmd(sd, CMD_SELECT_CARD, sd->sd_rcaarg, NULL, NULL);
> -+
> -+ if (sd->os_dmastream) SDPOKE8(sd, SDCTRL, 0x42);
> -+ if ((SDPEEK8(sd, SDCTRL) & 0x80) || (sd->sd_csd[15] & 0x30))
> -+ sd->sd_wprot = 1;
> -+ sd->sd_blocksize = 1 << ((sd->sd_csd[6] & 0xf));
> -+ if (timeout(sd)) return 0;
> -+ else return sdsize(sd);
> -+}
> -+
> -+static
> -+int sdreset2(struct sdcore *sd)
> -+{
> -+ unsigned int rca, s, i, x;
> -+ unsigned int resp[17];
> -+
> -+ reset_timeout(sd);
> -+ sd_initcrc(sd);
> -+ sd->parked_sector = 0;
> -+ sd->sd_wprot = 0;
> -+ sd->sd_blocksize = 0;
> -+ sd->sd_sz = 0;
> -+ if (sd->hw_version == 0) sd->hw_version = version(sd);
> -+ if (sd->hw_version == 0) return 0;
> -+ sd->sd_state &= SD_RESET;
> -+ remember_sdcore(sd);
> -+ activate(sd);
> -+ sd->sd_state |= SD_LOSPEED;
> -+
> -+ if (!(sd->sd_state & SD_RESET) && (SDPEEK8(sd, SDGPIO) != 0x0)) {
> -+ SDPOKE8(sd, SDGPIO, 0x0);
> -+#ifdef BIGENDIAN
> -+ for (i = 0; i < 8; i++) SDPOKE16(sd, SDLUN2, i << 8);
> -+#else
> -+ for (i = 0; i < 8; i++) SDPOKE16(sd, SDLUN2, i);
> -+#endif
> -+ sd->os_delay(sd->os_arg, 100000);
> -+
> -+ /* this was a global reset, so let the other luns know */
> -+ for (i = 0; i < sizeof(sdcores); i++) {
> -+ if (sdcores[i] == NULL) break;
> -+ if (sdcores[i]->sd_regstart == sd->sd_regstart)
> -+ sdcores[i]->sd_state |= SD_RESET;
> -+ }
> -+#ifdef BIGENDIAN
> -+ SDPOKE16(sd, SDLUN2, sd->sd_lun << 8);
> -+#else
> -+ SDPOKE16(sd, SDLUN2, sd->sd_lun);
> -+#endif
> -+ }
> -+ sd->sd_state &= ~SD_RESET;
> -+
> -+ // gratuitous clocks
> -+ SDPOKE8(sd, SDGPIO, 0xff);
> -+ sd->os_delay(sd->os_arg, 5000);
> -+ for (i = 0; i < 750; i++) {
> -+ SDPOKE8(sd, SDGPIO, 0xff);
> -+ SDPEEK8(sd, SDGPIO); /* delay */
> -+ SDPEEK8(sd, SDGPIO); /* delay */
> -+ SDPOKE8(sd, SDGPIO, 0xdf);
> -+ SDPEEK8(sd, SDGPIO); /* delay */
> -+ SDPEEK8(sd, SDGPIO); /* delay */
> -+ }
> -+
> -+ SDPEEK8(sd, SDSTAT2); /* reset any timeout/crc conditions */
> -+ SDPOKE8(sd, SDSTAT2, 0x18);
> -+ s = sdcmd2(sd, CMD_SEND_IF_COND, 0x1aa, resp, NULL);
> -+ if (s) {
> -+ reset_timeout(sd);
> -+ x = 0x00ff0000;
> -+ } else {
> -+ x = 0x40ff0000;
> -+ }
> -+
> -+ do {
> -+ sdcmd2(sd, CMD_APP_CMD, 0, NULL, NULL);
> -+ sdcmd2(sd, ACMD_SD_SEND_OP_COND, x, resp, NULL);
> -+ if (timeout(sd)) break;
> -+ // TODO: check for valid result or limit # of loops,
> -+ // otherwise we may loop forever on malfunctioning cards.
> -+ } while (((resp[1] & 0x80) == 0x0));
> -+
> -+ if ((x & 0x40000000) && (resp[1] & 0x40)) {
> -+ sd->sd_state |= SD_HC;
> -+ }
> -+
> -+ sdcmd2(sd, CMD_ALL_SEND_CID, 0, resp, NULL);
> -+ sdcmd2(sd, CMD_SEND_RELATIVE_ADDR, 0, resp, NULL);
> -+ rca = resp[1] << 8 | resp[2];
> -+ sd->sd_rcaarg = (rca & 0xff00) << 16 | (rca & 0xff) << 16;
> -+ sd->sdboot_token = ~sd->sd_rcaarg;
> -+
> -+ sdcmd2(sd, CMD_SEND_CSD, sd->sd_rcaarg, sd->sd_csd, NULL);
> -+ sdcmd2(sd, CMD_SELECT_CARD, sd->sd_rcaarg, resp, NULL);
> -+
> -+ if ((resp[1] & 0x2)) {
> -+ unsigned int ret = 1;
> -+ sd->sd_locked = 1;
> -+#ifndef SD_NOLOCKSUPPORT
> -+ if (sd->sd_pwd)
> -+ ret = sdlockctl2(sd, SDLOCK_UNLOCK, sd->sd_pwd, NULL);
> -+#endif
> -+ if (ret != 0) return 0;
> -+ } else sd->sd_locked = 0;
> -+
> -+ sdcmd2(sd, CMD_APP_CMD, sd->sd_rcaarg, NULL, NULL);
> -+ sdcmd2(sd, ACMD_SET_CLR_CARD_DETECT, 0, NULL, NULL);
> -+ sdcmd2(sd, CMD_SET_BLOCKLEN, 512, NULL, NULL);
> -+ sdcmd2(sd, CMD_APP_CMD, sd->sd_rcaarg, NULL, NULL);
> -+ sdcmd2(sd, ACMD_SET_BUS_WIDTH, 2, resp, NULL);
> -+ sd->sd_state |= DATSSP_4BIT;
> -+ sd->sd_state &= ~SD_LOSPEED;
> -+
> -+ sdcmd2(sd, CMD_APP_CMD, sd->sd_rcaarg, NULL, NULL);
> -+ sdcmd2(sd, ACMD_SEND_SCR2, 0, NULL, NULL);
> -+ do {
> -+ if (timeout(sd)) break;
> -+ SDPOKE8(sd, SDGPIO, 0xdf);
> -+ SDPEEK8(sd, SDGPIO);
> -+ s = SDPEEK8(sd, SDGPIO);
> -+ SDPOKE8(sd, SDGPIO, 0xff);
> -+ SDPEEK8(sd, SDGPIO);
> -+ } while ((s & 0xf) != 0x0);
> -+ for (i = 0; i < 16; i++) {
> -+ SDPOKE8(sd, SDGPIO, 0xdf);
> -+ SDPEEK8(sd, SDGPIO);
> -+ s = (SDPEEK8(sd, SDGPIO) & 0xf) << 4;
> -+ SDPOKE8(sd, SDGPIO, 0xff);
> -+ SDPEEK8(sd, SDGPIO);
> -+ SDPOKE8(sd, SDGPIO, 0xdf);
> -+ SDPEEK8(sd, SDGPIO);
> -+ s |= (SDPEEK8(sd, SDGPIO) & 0xf);
> -+ SDPOKE8(sd, SDGPIO, 0xff);
> -+ SDPEEK8(sd, SDGPIO);
> -+ if (i < 8) sd->sd_scr[i] = s;
> -+ }
> -+ for (i = 0; i < 8; i++) {
> -+ SDPOKE8(sd, SDGPIO, 0xdf);
> -+ SDPEEK8(sd, SDGPIO);
> -+ SDPEEK8(sd, SDGPIO);
> -+ SDPOKE8(sd, SDGPIO, 0xff);
> -+ SDPEEK8(sd, SDGPIO);
> -+ }
> -+ sd->sd_state &= ~SDDAT_RX;
> -+
> -+#ifndef SD_NOHIGHSPEED
> -+ if ((sd->sd_scr[0] & 0xf) >= 1) { // SD version >= 1.10
> -+ unsigned char dat[64];
> -+ sdcmd2(sd, CMD_SWITCH_FUNC2, 0x80fffff1, NULL, NULL);
> -+ do {
> -+ if (timeout(sd)) break;
> -+ SDPOKE8(sd, SDGPIO, 0xdf);
> -+ SDPEEK8(sd, SDGPIO);
> -+ s = SDPEEK8(sd, SDGPIO);
> -+ SDPOKE8(sd, SDGPIO, 0xff);
> -+ SDPEEK8(sd, SDGPIO);
> -+ } while ((s & 0xf) != 0x0);
> -+ for (i = 0; i < 72; i++) {
> -+ SDPOKE8(sd, SDGPIO, 0xdf);
> -+ SDPEEK8(sd, SDGPIO);
> -+ s = (SDPEEK8(sd, SDGPIO) & 0xf) << 4;
> -+ SDPOKE8(sd, SDGPIO, 0xff);
> -+ SDPEEK8(sd, SDGPIO);
> -+ SDPOKE8(sd, SDGPIO, 0xdf);
> -+ SDPEEK8(sd, SDGPIO);
> -+ s |= (SDPEEK8(sd, SDGPIO) & 0xf);
> -+ SDPOKE8(sd, SDGPIO, 0xff);
> -+ SDPEEK8(sd, SDGPIO);
> -+ if (i < 64) dat[i] = s;
> -+ }
> -+ for (i = 0; i < 8; i++) {
> -+ SDPOKE8(sd, SDGPIO, 0xdf);
> -+ SDPEEK8(sd, SDGPIO);
> -+ SDPEEK8(sd, SDGPIO);
> -+ SDPOKE8(sd, SDGPIO, 0xff);
> -+ SDPEEK8(sd, SDGPIO);
> -+ }
> -+ sd->sd_state &= ~SDDAT_RX;
> -+ if (dat[0] | dat[1]) {
> -+ SDPOKE8(sd, SDSTAT2, 0x38);
> -+ sd->sd_state |= SD_HISPEED;
> -+ }
> -+ }
> -+#endif
> -+
> -+#ifdef BIGENDIAN
> -+ if ((sd->sd_csd[15] & 0x30) || (SDPEEK16(sd, SDGPIO) & 0x2))
> -+#else
> -+ if ((sd->sd_csd[15] & 0x30) || (SDPEEK16(sd, SDGPIO) & 0x200))
> -+#endif
> -+ sd->sd_wprot = 1;
> -+ sd->sd_blocksize = 1 << ((sd->sd_csd[6] & 0xf));
> -+ if (timeout(sd)) return 0;
> -+ else {
> -+ reset_timeout(sd);
> -+ return sdsize(sd);
> -+ }
> -+}
> -+
> -+/*
> -+ * return 0 : 8 bit TS-SDCORE v1
> -+ * return 1 : 8 bit 4x8 TS-SDCORE v2
> -+ * return 2 : 32 bit 4x32 TS-SDCORE v2
> -+ * return 3 : 16 bit 4x32 TS-SDCORE v2
> -+ * return 4 : 8 bit 4x32 TS-SDCORE v2
> -+ */
> -+static int version(struct sdcore *sd)
> -+{
> -+ int a, b, i;
> -+
> -+
> -+#ifdef SD_FORCEVERSION
> -+ return SD_FORCEVERSION;
> -+#endif
> -+ for (i = 0; i < sizeof(sdcores); i++) {
> -+ if (sdcores[i] == NULL) break;
> -+ if (sdcores[i]->sd_regstart == sd->sd_regstart)
> -+ return sdcores[i]->hw_version;
> -+ }
> -+
> -+ a = SDPEEK8(sd, 3);
> -+ SDPOKE8(sd, 3, (a ^ 0x40));
> -+ b = SDPEEK8(sd, 3);
> -+ SDPOKE8(sd, 3, a);
> -+ if ((a & 0x40) ^ (b & 0x40)) return 0;
> -+ else if (a & 0x40) return 1;
> -+ /* either 2, 3, or 4 */
> -+ a = SDPEEK32(sd, 12);
> -+ b = SDPEEK16(sd, 12);
> -+#ifdef BIGENDIAN
> -+ if ((a & 0x40000000) && (b & 0x4000)) return 2;
> -+#else
> -+ if ((a & 0x40) && (b & 0x40)) return 2;
> -+#endif
> -+ a = SDPEEK8(sd, 12);
> -+ if (a & 0x40) return 3;
> -+ else return 4;
> -+}
> -+
> -+int sdreset(struct sdcore *sd)
> -+{
> -+ unsigned int rca, s, x;
> -+ unsigned int resp[17];
> -+
> -+ reset_timeout(sd);
> -+ sd_initcrc(sd);
> -+ sd->parked_sector = 0;
> -+ sd->sd_wprot = 0;
> -+ sd->sd_blocksize = 0;
> -+ sd->sd_sz = 0;
> -+
> -+ sd->hw_version = version(sd);
> -+ if (sd->hw_version >= 2) return sdreset2(sd);
> -+
> -+ // check for no SD card present
> -+ if (SDPEEK8(sd, SDCTRL) & 0x8) return 0;
> -+
> -+ if (sd->sdboot_token) {
> -+ int ret = sdfastinit(sd);
> -+ sd->sdboot_token = 0;
> -+ if (ret) return ret;
> -+ }
> -+
> -+ // set controller for 1-bit mode, slow clock
> -+ SDPOKE8(sd, SDCTRL, 0x20);
> -+
> -+ SDPOKE8(sd, SDSTATE, S_DUMMY_CLK);
> -+ sd->sd_state = SDCMD_RX|SDDAT_RX;
> -+ s = SDPEEK8(sd, SDSTATE);
> -+ while ((s & 0x7) != S_SEND_CMD) {
> -+ // If we timeout here, it would be VERY BAD as we have no
> -+ // further recourse to set things right if we can't turn
> -+ // the SD off.
> -+ if (timeout(sd)) return 0;
> -+ sd->os_delay(sd->os_arg, 10000);
> -+ sd->sd_timeout += 10000;
> -+
> -+ // We won't be able to change state until both SSPs are empty
> -+ s = tend_ssp(sd, NULL, NULL);
> -+ }
> -+ SDPOKE8(sd, SDSTATE, S_OFF);
> -+ sd->sd_state = 0;
> -+
> -+ sd->os_delay(sd->os_arg, 50000);
> -+
> -+ SDPOKE8(sd, SDSTATE, S_DUMMY_CLK);
> -+ sd->os_delay(sd->os_arg, 100000);
> -+ if ((SDPEEK8(sd, SDSTATE) & 0x7) == S_OFF) {
> -+ // No card present
> -+ return 0;
> -+ }
> -+
> -+ SDPOKE8(sd, SDSTATE, S_WAIT_RESP);
> -+ // clock will freerun waiting for a response that will never come
> -+ sd->os_delay(sd->os_arg, 50000);
> -+
> -+ SDPOKE8(sd, SDSTATE, S_DUMMY_CLK);
> -+
> -+ s = sdcmd(sd, CMD_SEND_IF_COND, 0x1aa, resp, NULL);
> -+ if (s) {
> -+ reset_timeout(sd);
> -+ SDPOKE8(sd, SDSTATE, S_DUMMY_CLK);
> -+ x = 0x00ff0000;
> -+ } else {
> -+ x = 0x40ff0000;
> -+ }
> -+
> -+ do {
> -+ sdcmd(sd, CMD_APP_CMD, 0, NULL, NULL);
> -+ sdcmd(sd, ACMD_SD_SEND_OP_COND, x, resp, NULL);
> -+ if (timeout(sd)) break;
> -+ } while (((resp[1] & 0x80) == 0x0));
> -+
> -+ if ((x & 0x40000000) && (resp[1] & 0x40)) sd->sd_state |= SD_HC;
> -+
> -+ sdcmd(sd, CMD_ALL_SEND_CID, 0, resp, NULL);
> -+ sdcmd(sd, CMD_SEND_RELATIVE_ADDR, 0, resp, NULL);
> -+ rca = resp[1] << 8 | resp[2];
> -+ sd->sd_rcaarg = (rca & 0xff00) << 16 | (rca & 0xff) << 16;
> -+ sd->sdboot_token = ~sd->sd_rcaarg;
> -+
> -+ sdcmd(sd, CMD_SEND_CSD, sd->sd_rcaarg, sd->sd_csd, NULL);
> -+ sdcmd(sd, CMD_SELECT_CARD, sd->sd_rcaarg, resp, NULL);
> -+
> -+ if ((resp[1] & 0x2)) {
> -+ unsigned int ret = 1;
> -+ sd->sd_locked = 1;
> -+#ifndef SD_NOLOCKSUPPORT
> -+ if (sd->sd_pwd)
> -+ ret = sdlockctl(sd, SDLOCK_UNLOCK, sd->sd_pwd, NULL);
> -+#endif
> -+ if (ret != 0) return 0;
> -+ } else sd->sd_locked = 0;
> -+
> -+ sdcmd(sd, CMD_APP_CMD, sd->sd_rcaarg, NULL, NULL);
> -+ sdcmd(sd, ACMD_SET_CLR_CARD_DETECT, 0, NULL, NULL);
> -+ /*
> -+ sdcmd(sd, CMD_APP_CMD, sd->sd_rcaarg, NULL, NULL);
> -+ sdcmd(sd, ACMD_SEND_SCR, 0, NULL, &datptr);
> -+ while ((datptr - sd->sd_scr) != 8) {
> -+ if (timeout(sd)) return 1;
> -+ tend_ssp(sd, NULL, &datptr);
> -+ }
> -+ datssp_stream(sd, NULL, 3);
> -+ SDPOKE8(sd, SDSTATE, (TYPE_ABORT << 5) | S_SEND_CMD);
> -+ sd->sd_state |= SDCMD_RX|SDDAT_RX;
> -+ while ((SDPEEK8(sd, SDSTATE) & 0x17) != S_SEND_CMD) {
> -+ if (timeout(sd)) break;
> -+ tend_ssp(sd, NULL, NULL);
> -+ }
> -+ sd->sd_state &= ~(SDCMD_RX|SDDAT_RX);
> -+ if ((sd->sd_scr[0] & 0xf) >= 1) { // SD version >= 1.10
> -+ unsigned char dat[64];
> -+ datptr = dat;
> -+ sdcmd(sd, CMD_SWITCH_FUNC, 0x80fffff1, NULL, &datptr);
> -+ while ((datptr - dat) != 64) {
> -+ if (timeout(sd)) break;
> -+ tend_ssp(sd, NULL, &datptr);
> -+ }
> -+ datssp_stream(sd, NULL, 3);
> -+ SDPOKE8(sd, SDSTATE, (TYPE_ABORT << 5) | S_SEND_CMD);
> -+ sd->sd_state |= SDCMD_RX|SDDAT_RX;
> -+ while ((SDPEEK8(sd, SDSTATE) & 0x7) != S_SEND_CMD) {
> -+ if (timeout(sd)) break;
> -+ tend_ssp(sd, NULL, NULL);
> -+ }
> -+ sd->sd_state &= ~(SDCMD_RX|SDDAT_RX);
> -+ }
> -+ */
> -+
> -+ sdcmd(sd, CMD_SET_BLOCKLEN, 512, NULL, NULL);
> -+ sdcmd(sd, CMD_APP_CMD, sd->sd_rcaarg, NULL, NULL);
> -+ sdcmd(sd, ACMD_SET_BUS_WIDTH, 2, resp, NULL);
> -+
> -+ // set controller for 4-bit mode, fast clock
> -+ SDPOKE8(sd, SDCTRL, (0x40 | (sd->os_dmastream ? 0x2 : 0x0)));
> -+ sd->sd_state |= DATSSP_4BIT;
> -+
> -+ /*
> -+ sdcmd(sd, CMD_APP_CMD, sd->sd_rcaarg, NULL, NULL);
> -+ sdcmd(sd, ACMD_SEND_SCR, 0, NULL, &datptr);
> -+ while ((datptr - sd->sd_scr) != 8) {
> -+ if (timeout(sd)) break;
> -+ tend_ssp(sd, NULL, &datptr);
> -+ }
> -+ datssp_stream(sd, NULL, 6);
> -+ SDPOKE8(sd, SDSTATE, S_DUMMY_CLK | (TYPE_SHORTRESP << 5));
> -+ bzero(resp, 6 * 4);
> -+ sdcmd(sd, CMD_SEND_STATUS, 0, resp, NULL);
> -+ */
> -+
> -+ if ((SDPEEK8(sd, SDCTRL) & 0x80) || (sd->sd_csd[15] & 0x30))
> -+ sd->sd_wprot = 1;
> -+ sd->sd_blocksize = 1 << ((sd->sd_csd[6] & 0xf));
> -+ if (timeout(sd) || error(resp, ACMD_SET_BUS_WIDTH)) return 0;
> -+ else return sdsize(sd);
> -+}
> -+
> -+static
> -+int sdread2(struct sdcore *sd, unsigned int sector, unsigned char *dat,
> -+ int nsectors)
> -+{
> -+ struct sdiov iov;
> -+ int ret;
> -+
> -+ iov.sdiov_base = dat;
> -+ iov.sdiov_nsect = nsectors;
> -+ ret = do_read2(sd, sector, &iov, 1);
> -+ return ret;
> -+}
> -+
> -+int sdread(struct sdcore *sd, unsigned int sector, unsigned char *dat,
> -+ int nsectors)
> -+{
> -+ struct sdiov iov;
> -+ int ret;
> -+
> -+ iov.sdiov_base = dat;
> -+ iov.sdiov_nsect = nsectors;
> -+ if (sd->hw_version == 0) ret = do_read(sd, sector, &iov, 1);
> -+ else ret = do_read2(sd, sector, &iov, 1);
> -+ return ret;
> -+}
> -+
> -+int sdwrite(struct sdcore *sd, unsigned int sector, unsigned char *dat,
> -+ int nsectors)
> -+{
> -+ struct sdiov iov;
> -+ unsigned int ret;
> -+
> -+ iov.sdiov_base = dat;
> -+ iov.sdiov_nsect = nsectors;
> -+ if (sd->hw_version == 0) ret = do_write(sd, sector, &iov, 1);
> -+ else ret = do_write2(sd, sector, &iov, 1);
> -+ return ret;
> -+
> -+}
> -+
> -+int sdreadv(struct sdcore *sd, unsigned int sector, struct sdiov *iov,
> -+ int niov)
> -+{
> -+ if (sd->hw_version == 0) return do_read(sd, sector, iov, niov);
> -+ else return do_read2(sd, sector, iov, niov);
> -+}
> -+
> -+int sdwritev(struct sdcore *sd, unsigned int sector, struct sdiov *iov,
> -+ int niov)
> -+{
> -+ if (sd->hw_version == 0) return do_write(sd, sector, iov, niov);
> -+ else return do_write2(sd, sector, iov, niov);
> -+}
> -+
> -+static
> -+int sdsetwprot2(struct sdcore *sd, unsigned int perm)
> -+{
> -+ int i, ret, s;
> -+ unsigned int csd[16], resp[6];
> -+ unsigned char csdchars[16];
> -+ unsigned char *csdptr = csdchars;
> -+
> -+ stop2(sd);
> -+
> -+ perm = perm ? 0x3 : 0x1;
> -+ for (i = 0; i < 16; i++) csd[i] = sd->sd_csd[i + 1];
> -+ csd[14] &= ~(0x3 << 4);
> -+ csd[14] |= (perm << 4);
> -+ csd[15] = 0x1 | crc7(0, csd, 15) << 1;
> -+ for (i = 0; i < 16; i++) csdchars[i] = csd[i];
> -+
> -+ ret = sdcmd2(sd, CMD_PROGRAM_CSD, 0, resp, NULL);
> -+ if (ret || error(resp, CMD_PROGRAM_CSD)) return 1;
> -+ for (i = 0; i < 16; i++) {
> -+ s = *csdptr++;
> -+ sd_4bit_feedcrc(sd, s);
> -+ SDPOKE8(sd, SDGPIO, (0x10|((s & 0xf0) >> 4)));
> -+ SDPEEK8(sd, SDGPIO);
> -+ SDPEEK8(sd, SDGPIO);
> -+ SDPOKE8(sd, SDGPIO, (0x30|((s & 0xf0) >> 4)));
> -+ SDPEEK8(sd, SDGPIO);
> -+ SDPOKE8(sd, SDGPIO, (0x10|(s & 0xf)));
> -+ SDPEEK8(sd, SDGPIO);
> -+ SDPEEK8(sd, SDGPIO);
> -+ SDPOKE8(sd, SDGPIO, (0x30|(s & 0xf)));
> -+ SDPEEK8(sd, SDGPIO);
> -+ }
> -+ for (i = 0; i < 8; i++) {
> -+ s = sd_4bit_getcrc(sd);
> -+ SDPOKE8(sd, SDGPIO, (0x10|((s & 0xf0) >> 4)));
> -+ SDPEEK8(sd, SDGPIO);
> -+ SDPEEK8(sd, SDGPIO);
> -+ SDPOKE8(sd, SDGPIO, (0x30|((s & 0xf0) >> 4)));
> -+ SDPEEK8(sd, SDGPIO);
> -+ SDPOKE8(sd, SDGPIO, (0x10|(s & 0xf)));
> -+ SDPEEK8(sd, SDGPIO);
> -+ SDPEEK8(sd, SDGPIO);
> -+ SDPOKE8(sd, SDGPIO, (0x30|(s & 0xf)));
> -+ SDPEEK8(sd, SDGPIO);
> -+ }
> -+ // End bit
> -+ SDPOKE8(sd, SDGPIO, 0x1f);
> -+ SDPEEK8(sd, SDGPIO);
> -+ SDPEEK8(sd, SDGPIO);
> -+ SDPOKE8(sd, SDGPIO, 0x3f);
> -+ SDPEEK8(sd, SDGPIO);
> -+ SDPOKE8(sd, SDGPIO, 0xbf); // tristate dat
> -+ // CRC ack
> -+ s = 0;
> -+ for (i = 0; i < 7; i++) {
> -+ SDPOKE8(sd, SDGPIO, 0x9f); // clk negedge
> -+ SDPEEK8(sd, SDGPIO); // delay
> -+ s = s << 1;
> -+ s |= (SDPEEK8(sd, SDGPIO) & 0x1);
> -+ SDPOKE8(sd, SDGPIO, 0xbf); // clk posedge
> -+ }
> -+ if ((s & 0xf) != 0x5) return 1;
> -+ // wait for unbusy
> -+ s = 0;
> -+ while ((s & 0x7) != 0x7) {
> -+ if (timeout(sd)) break;
> -+ SDPOKE8(sd, SDGPIO, 0x9f); // clk negedge
> -+ SDPEEK8(sd, SDGPIO); // delay
> -+ s = s << 1;
> -+ s |= SDPEEK8(sd, SDGPIO) & 0x1;
> -+ SDPOKE8(sd, SDGPIO, 0xbf);
> -+ }
> -+ for (i = 0; i < 8; i++) {
> -+ SDPOKE8(sd, SDGPIO, 0x9f);
> -+ SDPEEK8(sd, SDGPIO);
> -+ SDPEEK8(sd, SDGPIO);
> -+ SDPOKE8(sd, SDGPIO, 0xbf);
> -+ SDPEEK8(sd, SDGPIO);
> -+ }
> -+ sd->sd_state &= ~SDDAT_TX;
> -+
> -+ sdcmd2(sd, CMD_DESELECT_CARD, ~sd->sd_rcaarg, NULL, NULL);
> -+ ret = sdcmd2(sd, CMD_SEND_CSD, sd->sd_rcaarg, sd->sd_csd, NULL);
> -+ if (ret || sd->sd_csd[15] != csd[14]) {
> -+ return 1;
> -+ }
> -+ sdcmd2(sd, CMD_SELECT_CARD, sd->sd_rcaarg, resp, NULL);
> -+
> -+ sd->sd_wprot = 1;
> -+ return 0;
> -+}
> -+
> -+int sdsetwprot(struct sdcore *sd, unsigned int perm)
> -+{
> -+ int i, ret;
> -+ unsigned int csd[16], resp[6];
> -+ unsigned char csdchars[16];
> -+ unsigned char *csdptr = csdchars;
> -+
> -+ if (sd->hw_version) return sdsetwprot2(sd, perm);
> -+
> -+ if (stop(sd)) return 1;
> -+
> -+ perm = perm ? 0x3 : 0x1;
> -+ for (i = 0; i < 16; i++) csd[i] = sd->sd_csd[i + 1];
> -+ csd[14] &= ~(0x3 << 4);
> -+ csd[14] |= (perm << 4);
> -+ csd[15] = 0x1 | crc7(0, csd, 15) << 1;
> -+ for (i = 0; i < 16; i++) csdchars[i] = csd[i];
> -+
> -+ ret = sdcmd(sd, CMD_PROGRAM_CSD, 0, resp, NULL);
> -+ if (ret || error(resp, CMD_PROGRAM_CSD)) return 1;
> -+ datssp_stream(sd, &csdptr, 16);
> -+ datssp_stream(sd, NULL, 8);
> -+ SDPOKE8(sd, SDSTATE, S_CRC_CHECK | (TYPE_BSYRESP << 5));
> -+ sd->sd_state &= ~SDDAT_TX;
> -+
> -+ sdcmd(sd, CMD_DESELECT_CARD, ~sd->sd_rcaarg, NULL, NULL);
> -+ ret = sdcmd(sd, CMD_SEND_CSD, sd->sd_rcaarg, sd->sd_csd, NULL);
> -+ if (ret || sd->sd_csd[15] != csd[14]) {
> -+ return 1;
> -+ }
> -+ sdcmd(sd, CMD_SELECT_CARD, sd->sd_rcaarg, resp, NULL);
> -+
> -+ sd->sd_wprot = 1;
> -+ return 0;
> -+}
> -+
> -+#ifndef SD_NOLOCKSUPPORT
> -+int sdlockctl(struct sdcore *sd, unsigned int cmd, unsigned char *pwd,
> -+ unsigned char *sdbootdat)
> -+{
> -+ unsigned char pwddat[18];
> -+ unsigned char *pwdptr = pwddat;
> -+ unsigned int resp[6];
> -+ int ret, i, len;
> -+ int ccc = (sd->sd_csd[5] << 4) | (sd->sd_csd[6] >> 4);
> -+
> -+ if (sd->hw_version) return sdlockctl2(sd, cmd, pwd, sdbootdat);
> -+
> -+ if (!(ccc & 0x80)) return 1; // Class 7 is lock-unlock commands
> -+
> -+ if (pwd == NULL && cmd != SDLOCK_ERASE) return 1;
> -+
> -+ if (stop(sd)) return 1;
> -+
> -+ if (sd->sd_state & DATSSP_4BIT) {
> -+ int oldctrl = SDPEEK8(sd, SDCTRL);
> -+ int ret;
> -+
> -+ sdcmd(sd, CMD_APP_CMD, sd->sd_rcaarg, NULL, NULL);
> -+ sdcmd(sd, ACMD_SET_BUS_WIDTH, 0, NULL, NULL);
> -+ SDPOKE8(sd, SDCTRL, 0x20);
> -+ sd->sd_state &= ~DATSSP_4BIT;
> -+ ret = sdlockctl(sd, cmd, pwd, sdbootdat);
> -+ sdcmd(sd, CMD_APP_CMD, sd->sd_rcaarg, NULL, NULL);
> -+ sdcmd(sd, ACMD_SET_BUS_WIDTH, 2, NULL, NULL);
> -+ sd->sd_state |= DATSSP_4BIT;
> -+ SDPOKE8(sd, SDCTRL, oldctrl);
> -+ return ret;
> -+ }
> -+
> -+ pwddat[0] = cmd;
> -+ if (cmd != SDLOCK_ERASE) {
> -+ pwddat[1] = 16; // length
> -+ for (i = 0; i < 16; i++) {
> -+ pwddat[2 + i] = pwd[i];
> -+ }
> -+ }
> -+
> -+ if (cmd == SDLOCK_ERASE) len = 1; else len = 18;
> -+ ret = sdcmd(sd, CMD_SET_BLOCKLEN, len, resp, NULL);
> -+ if (ret || error(resp, CMD_SET_BLOCKLEN)) return 1;
> -+ ret = sdcmd(sd, CMD_LOCK_UNLOCK, 0, resp, NULL);
> -+ if (ret || error(resp, CMD_LOCK_UNLOCK)) return 1;
> -+
> -+ while ((pwdptr - pwddat) != len) {
> -+ if (timeout(sd)) return 1;
> -+ tend_ssp(sd, NULL, &pwdptr);
> -+ }
> -+
> -+ if (sd->sd_state & DATSSP_4BIT) datssp_stream(sd, NULL, 8);
> -+ else datssp_stream(sd, NULL, 2);
> -+
> -+ SDPOKE8(sd, SDSTATE, S_CRC_CHECK | (TYPE_BSYRESP << 5));
> -+ sd->sd_state &= ~SDDAT_TX;
> -+ ret = sdcmd(sd, CMD_SET_BLOCKLEN, 512, resp, NULL);
> -+ if (ret || error(resp, CMD_SET_BLOCKLEN)) return 1;
> -+ ret = sdcmd(sd, CMD_SEND_STATUS, sd->sd_rcaarg, resp, NULL);
> -+ if (ret || error(resp, CMD_SEND_STATUS)) return 1;
> -+
> -+ if ((cmd == SDLOCK_ERASE || cmd == SDLOCK_UNLOCK ||
> -+ cmd == SDLOCK_CLRPWD) && (resp[1] & 0x2)) {
> -+ return 1;
> -+ }
> -+
> -+ if (sdbootdat) {
> -+ sdbootdat[0] = SDLOCK_UNLOCK;
> -+ for (i = 1; i < 18; i++) {
> -+ sdbootdat[i] = pwddat[i];
> -+ sd_1bit_feedcrc(sd, pwddat[i]);
> -+ }
> -+ sdbootdat[18] = sd_1bit_getcrc(sd);
> -+ sdbootdat[19] = sd_1bit_getcrc(sd);
> -+ }
> -+
> -+ return 0;
> -+}
> -+
> -+static
> -+int sdlockctl2(struct sdcore *sd, unsigned int cmd, unsigned char *pwd,
> -+ unsigned char *sdbootdat)
> -+{
> -+ unsigned char pwddat[18];
> -+ unsigned char *pwdptr = pwddat;
> -+ unsigned int resp[6];
> -+ int ret, i, j, len, s;
> -+ int ccc = (sd->sd_csd[5] << 4) | (sd->sd_csd[6] >> 4);
> -+
> -+ if (!(ccc & 0x80)) return 1; // Class 7 is lock-unlock commands
> -+
> -+ if (pwd == NULL && cmd != SDLOCK_ERASE) return 1;
> -+
> -+ stop2(sd);
> -+
> -+ if (sd->sd_state & DATSSP_4BIT) {
> -+ int ret;
> -+
> -+ sdcmd2(sd, CMD_APP_CMD, sd->sd_rcaarg, NULL, NULL);
> -+ sdcmd2(sd, ACMD_SET_BUS_WIDTH, 0, NULL, NULL);
> -+ sd->sd_state &= ~DATSSP_4BIT;
> -+ ret = sdlockctl2(sd, cmd, pwd, sdbootdat);
> -+ sdcmd2(sd, CMD_APP_CMD, sd->sd_rcaarg, NULL, NULL);
> -+ sdcmd2(sd, ACMD_SET_BUS_WIDTH, 2, NULL, NULL);
> -+ sd->sd_state |= DATSSP_4BIT;
> -+ return ret;
> -+ }
> -+
> -+ pwddat[0] = cmd;
> -+ if (cmd != SDLOCK_ERASE) {
> -+ pwddat[1] = 16; // length
> -+ for (i = 0; i < 16; i++) {
> -+ pwddat[2 + i] = pwd[i];
> -+ }
> -+ }
> -+
> -+ if (cmd == SDLOCK_ERASE) len = 1; else len = 18;
> -+ ret = sdcmd2(sd, CMD_SET_BLOCKLEN, len, resp, NULL);
> -+ if (ret || error(resp, CMD_SET_BLOCKLEN)) return 1;
> -+ ret = sdcmd2(sd, CMD_LOCK_UNLOCK, 0, resp, NULL);
> -+ if (ret || error(resp, CMD_LOCK_UNLOCK)) return 1;
> -+
> -+ for (i = 0; i < len; i++) {
> -+ unsigned int b = *pwdptr++;
> -+ unsigned int x;
> -+
> -+ sd_1bit_feedcrc(sd, b);
> -+ for (j = 0; j < 8; j++) {
> -+ x = 0x1e | ((b >> 7) & 0x1);
> -+ b = b << 1;
> -+ SDPOKE8(sd, SDGPIO, x); // clk negedge
> -+ SDPEEK8(sd, SDGPIO);
> -+ SDPEEK8(sd, SDGPIO);
> -+ x |= 0x20;
> -+ SDPOKE8(sd, SDGPIO, x); // clk posedge
> -+ SDPEEK8(sd, SDGPIO);
> -+ }
> -+ }
> -+ for (i = 0; i < 2; i++) {
> -+ unsigned int b = sd_1bit_getcrc(sd);
> -+ unsigned int x;
> -+
> -+ for (j = 0; j < 8; j++) {
> -+ x = 0x1e | ((b >> 7) & 0x1);
> -+ b = b << 1;
> -+ SDPOKE8(sd, SDGPIO, x); // clk negedge
> -+ SDPEEK8(sd, SDGPIO);
> -+ SDPEEK8(sd, SDGPIO);
> -+ x |= 0x20;
> -+ SDPOKE8(sd, SDGPIO, x); // clk posedge
> -+ SDPEEK8(sd, SDGPIO);
> -+ }
> -+ }
> -+ // End bit
> -+ SDPOKE8(sd, SDGPIO, 0x1f); // clk negedge
> -+ SDPEEK8(sd, SDGPIO);
> -+ SDPOKE8(sd, SDGPIO, 0xbf); // clk posedge, tristate dat
> -+ // CRC ack
> -+ s = 0;
> -+ for (i = 0; i < 7; i++) {
> -+ SDPOKE8(sd, SDGPIO, 0x9f); // clk negedge
> -+ SDPEEK8(sd, SDGPIO); // delay
> -+ s = s << 1;
> -+ s |= SDPEEK8(sd, SDGPIO) & 0x1;
> -+ SDPOKE8(sd, SDGPIO, 0xbf); // clk posedge
> -+ SDPEEK8(sd, SDGPIO);
> -+ }
> -+ if ((s & 0xf) != 0x5) return 1;
> -+
> -+ // wait for unbusy
> -+ s = 0;
> -+ while ((s & 0x7) != 0x7) {
> -+ if (timeout(sd)) break;
> -+ SDPOKE8(sd, SDGPIO, 0x9f); // clk negedge
> -+ SDPEEK8(sd, SDGPIO); // delay
> -+ s = s << 1;
> -+ s |= SDPEEK8(sd, SDGPIO) & 0x1;
> -+ SDPOKE8(sd, SDGPIO, 0xbf);
> -+ SDPEEK8(sd, SDGPIO);
> -+ }
> -+ for (i = 0; i < 8; i++) {
> -+ SDPOKE8(sd, SDGPIO, 0x9f);
> -+ SDPEEK8(sd, SDGPIO);
> -+ SDPEEK8(sd, SDGPIO);
> -+ SDPOKE8(sd, SDGPIO, 0xbf);
> -+ SDPEEK8(sd, SDGPIO);
> -+ }
> -+
> -+ sd->sd_state &= ~SDDAT_TX;
> -+ ret = sdcmd2(sd, CMD_SET_BLOCKLEN, 512, resp, NULL);
> -+ if (ret || error(resp, CMD_SET_BLOCKLEN)) {
> -+ return 1;
> -+ }
> -+ ret = sdcmd2(sd, CMD_SEND_STATUS, sd->sd_rcaarg, resp, NULL);
> -+ if (ret || error(resp, CMD_SEND_STATUS)) {
> -+ return 1;
> -+ }
> -+
> -+ if ((cmd == SDLOCK_ERASE || cmd == SDLOCK_UNLOCK ||
> -+ cmd == SDLOCK_CLRPWD) && (resp[1] & 0x2)) {
> -+ return 1;
> -+ }
> -+
> -+ if (sdbootdat) {
> -+ sdbootdat[0] = SDLOCK_UNLOCK;
> -+ for (i = 1; i < 18; i++) {
> -+ sdbootdat[i] = pwddat[i];
> -+ sd_1bit_feedcrc(sd, pwddat[i]);
> -+ }
> -+ sdbootdat[18] = sd_1bit_getcrc(sd);
> -+ sdbootdat[19] = sd_1bit_getcrc(sd);
> -+ }
> -+
> -+ for (i = 0; i < 8; i++) {
> -+ SDPOKE8(sd, SDGPIO, 0x9f);
> -+ SDPEEK8(sd, SDGPIO);
> -+ SDPEEK8(sd, SDGPIO);
> -+ SDPOKE8(sd, SDGPIO, 0xbf);
> -+ SDPEEK8(sd, SDGPIO);
> -+ }
> -+ return 0;
> -+}
> -+#endif
> -diff --git a/drivers/block/sdcore2.h b/drivers/block/sdcore2.h
> -new file mode 100644
> -index 0000000..38d5b96
> ---- /dev/null
> -+++ b/drivers/block/sdcore2.h
> -@@ -0,0 +1,372 @@
> -+/*
> -+ * Copyright (c) 2006-2008, Technologic Systems
> -+ * All rights reserved.
> -+ */
> -+
> -+#ifndef _SDCORE_H_
> -+#define _SDCORE_H_
> -+
> -+// Additional missing defs
> -+#define SDCMD 0 // cmd register
> -+#define SDDAT 1 // data register
> -+#define SDSTATE 2 // state register
> -+#define SDCTRL 3 // ctrl register
> -+
> -+
> -+// this bit is set when no card inserted
> -+#define SDCTRL_CARD_ABSENT 0x08
> -+
> -+
> -+
> -+/* public bits for sd_state bitfield, can be read from client code.
> -+ * Do not write! Other bits are used internally.
> -+ */
> -+#define SDDAT_RX (1<<0)
> -+#define SDDAT_TX (1<<1)
> -+#define SDCMD_RX (1<<2)
> -+#define SDCMD_TX (1<<3)
> -+
> -+// used to disable CRC calculations in write mode
> -+#define SDCRC_DISABLE (1 << 4)
> -+
> -+
> -+
> -+// used to choose between 4 bit crc mode and 1 bit crc mode
> -+
> -+// note - likely set in sdreset when configuring interface bit width
> -+#define SDSSP_4BIT_MODE (1 << 5)
> -+
> -+// SD_ADDRESSING_DIRECT means that sd card addresses
> -+// will be communicated in read/write mode using
> -+// full offsets, not 512 byte block offsets.
> -+// the core will mulitply the address by 512 if this
> -+// bit is cleared
> -+#define SD_ADDRESSING_DIRECT (1 << 6)
> -+
> -+
> -+/* These structs should start intialized to all 0's (bzero()'ed). Proper
> -+ * operation can be assured by setting sd_regstart, and the os_delay
> -+ * callback. sdreset() should be called to initialize the core, then
> -+ * sdread() and sdwrite() can be used.
> -+ */
> -+struct sdcore {
> -+ /* virtual address of SD block register start, to be filled in
> -+ * by client code before calling any sdcore functions.
> -+ */
> -+ // 0-3
> -+ unsigned char* sd_regstart;
> -+
> -+
> -+
> -+ // 4-7
> -+ unsigned int sd_state;
> -+
> -+ /* Erase hint for subsequent sdwrite() call, used to optimize
> -+ * write throughput on multi-sector writes by pre-erasing this
> -+ * many sectors.
> -+ */
> -+ // 8-11
> -+ unsigned int sd_erasehint;
> -+
> -+ /* Following this comment are 5 function pointer declarations to
> -+ * OS helper functions. The 'os_arg' member is passed as the
> -+ * first argument to the helpers and should be set by
> -+ * client code before issueing sdreset()
> -+ *
> -+ * os_dmastream(os_arg, buf, buflen)
> -+ * This function should look at sd_state and set up and run an
> -+ * appropriate DMA transfer. If buf is NULL, callee doesn't care
> -+ * about the actual data sent/received and helper function
> -+ * can do whatever it wants. Should return 0 when DMA transfer was
> -+ * run and completed successfully. If this function pointer is
> -+ * NULL, PIO methods of transfer will be used instead of DMA.
> -+ *
> -+ * os_dmaprep(os_arg, buf, buflen)
> -+ * This function is used to prepare an area of memory for a possible
> -+ * DMA transfer. This function is called once per distinct buffer
> -+ * passed in. After this function is called, os_dmastream() may be
> -+ * called one or more times (for sequential addresses) on subregions
> -+ * of the address range passed here. Should write-back or invalidate
> -+ * L1 cache lines and possibly look up physical addresses for buf
> -+ * passed in if I/O buffers. If 'os_dmaprep' is set to NULL, function
> -+ * call will not happen. (though os_dmastream() calls may still)
> -+ *
> -+ * os_delay(os_arg, microseconds)
> -+ * This function is supposed to delay or stall the processor for
> -+ * the passed in value number of microseconds.
> -+ *
> -+ * os_irqwait(os_arg, type)
> -+ * Called at certain times to request to be put to sleep/block until
> -+ * an SD interrupt occurs. It is not critical to set this function.
> -+ * When NULL, the sdcore routines simply busy-wait.
> -+ *
> -+ * os_powerok(os_arg)
> -+ * Experimental callback function -- set to NULL for now.
> -+ */
> -+ // 12-15
> -+ void *os_arg;
> -+ // 16-19
> -+ int (*os_dmastream)(void *, unsigned char *, unsigned int);
> -+ // 20-23
> -+ void (*os_dmaprep)(void *, unsigned char *, unsigned int);
> -+ // 24-27
> -+ void (*os_delay)(void *, unsigned int);
> -+ // 28-31
> -+ void (*os_irqwait)(void *, unsigned int);
> -+ // 32-35
> -+ int (*os_powerok)(void *);
> -+
> -+ int (*os_timeout)(void *);
> -+ int (*os_reset_timeout)(void *);
> -+
> -+ /* If the SD card last successfully reset is write protected, this
> -+ * member will be non-zero.
> -+ */
> -+ // 36-39
> -+ unsigned int sd_wprot;
> -+
> -+ /* If this card may have been already initialized by TS-SDBOOT, place
> -+ * the magic token it placed in the EP93xx SYSCON ScratchReg1 here
> -+ * before calling sdreset() to avoid re-initialization.
> -+ */
> -+ // 40-43
> -+ unsigned int sdboot_token;
> -+
> -+ /* CRC hint for subsequent sdwrite() call, used to optimize
> -+ * write throughput while using DMA by pre-calculating CRC's for
> -+ * next write. NULL means no hint supplied.
> -+ */
> -+ // 44-47
> -+ unsigned char *sd_crchint;
> -+
> -+ /* The block size of the memory device. Normally 512, but can be 1024
> -+ * for larger cards. Read-only member and actually not very useful.
> -+ */
> -+ // 48-51
> -+ unsigned int sd_blocksize;
> -+
> -+ /* Password for auto-unlocking in sdreset()
> -+ */
> -+ // 52-55
> -+ unsigned char *sd_pwd;
> -+
> -+ /* If the SD card was password locked, this will be non-zero after
> -+ * unsuccessful sdreset().
> -+ */
> -+ // 56-59
> -+ unsigned int sd_locked;
> -+
> -+ /* Whether or not writes can be parked. Definitely should be set to 1
> -+ * as writes are very slow without it.
> -+ */
> -+ // 60-63
> -+ unsigned int sd_writeparking;
> -+
> -+ /* Logical unit number. Some SD cores will have multiple card slots.
> -+ * LUN #0 is the first.
> -+ */
> -+ // 64-67
> -+ unsigned int sd_lun;
> -+
> -+ /* The rest of these members are for private internal use and should
> -+ * not be of interest to client code.
> -+ */
> -+
> -+
> -+ // 68-71
> -+ unsigned int rca; // relative card address
> -+
> -+
> -+ unsigned int sd_csd[17];
> -+ /*
> -+
> -+
> -+ // 72 -75 0
> -+ unsigned int unknown72; // one of the csds?
> -+
> -+ // 76 -79 1
> -+ unsigned int unknown76; // csd 0x00
> -+ // 80 -83 2
> -+ unsigned int unknown04; // csd 0x01
> -+ // 84 - 87 3
> -+ unsigned int unknown05; // csd 0x02
> -+ // 88 - 91 4
> -+ unsigned int unknown06; // csd 0x03
> -+ // 92 - 95 5
> -+ unsigned int unknown92; // csd 0x04
> -+ // 96 - 100 6
> -+ unsigned int unknown96; // csd 0x05
> -+ // 100 - 103 7
> -+ unsigned int unknown100; // csd 0x06
> -+ // 104 - 107 8
> -+ unsigned int unknown104; // csd 0x07
> -+ // 108 - 111 9
> -+ unsigned int unknown108; // csd 0x08
> -+ // 112 - 115 10
> -+ unsigned int unknown112; // csd 0x09
> -+ // 116 - 119 11
> -+ unsigned int unknown116; // csd 0x0a
> -+ // 120 12
> -+ unsigned int unknown24; // csd 0x0b
> -+ // 124 13
> -+ unsigned int unknown25; // csd 0x0c
> -+ // 128 14
> -+ unsigned int unknown26; // csd 0x0d
> -+ // 132 15
> -+ unsigned int unknown132; // csd 0x0e
> -+ // 136 16
> -+ unsigned int unknown28; // csd 0x0f
> -+ */
> -+
> -+
> -+ // 140
> -+ unsigned int sd_crc_shift;
> -+
> -+ // 144 + 4 + 4
> -+ unsigned short s_crc_table[4]; // 4 shorts
> -+ // 152 + 4 + 4 + 4 + 4
> -+ unsigned int l_crc_table[4]; // 4 longs
> -+
> -+ // 168
> -+ unsigned int sd_timeout; // used to busy wait
> -+
> -+ // 172
> -+ unsigned int sd_cur_sector; // stop indicator - if zero , then stop procedure will be skipped
> -+
> -+ // 176
> -+ unsigned int sdcore_version; // hardware version
> -+ // 180
> -+ unsigned int unknown39;
> -+ // 184
> -+ unsigned int unknown40;
> -+ // 188
> -+ unsigned int sdcore_sdsize;
> -+
> -+
> -+
> -+ unsigned int unknown42;
> -+ unsigned int unknown43;
> -+ unsigned int unknown44;
> -+ unsigned int unknown45;
> -+ unsigned int unknown46;
> -+ unsigned int unknown47;
> -+
> -+
> -+
> -+
> -+
> -+
> -+
> -+
> -+
> -+
> -+
> -+
> -+
> -+};
> -+
> -+/* I believe sdcores is a table mapping
> -+ id -> sdcore struct. The table is
> -+ 64 long, meaning that one could build a ts device with
> -+ 64 sdcores on it.
> -+*/
> -+//extern unsigned char sdcores[256];
> -+
> -+
> -+
> -+
> -+/* For sdreadv() / sdwritev() */
> -+struct sdiov {
> -+ unsigned char *sdiov_base;
> -+ unsigned int sdiov_nsect;
> -+};
> -+
> -+
> -+
> -+
> -+int sdreset(struct sdcore *);
> -+
> -+int sdsize(struct sdcore* sdcore);
> -+
> -+
> -+int sdread(struct sdcore* sdcore,
> -+ unsigned int sector,
> -+ unsigned char* buffer,
> -+ int nsect);
> -+
> -+int sdwrite(struct sdcore *, unsigned int, unsigned char *, int);
> -+
> -+
> -+// same signature as do_read
> -+int do_read(struct sdcore*, unsigned int, struct sdiov*, int);
> -+int sdreadv(struct sdcore * sdcore,
> -+ unsigned int sector,
> -+ struct sdiov * sdiov,
> -+ int nsdiov);
> -+
> -+// same signature as do_write
> -+int do_write(struct sdcore* sdcore,
> -+ unsigned int sector,
> -+ struct sdiov* sdiov,
> -+ int nsdiov);
> -+
> -+int sdwritev(struct sdcore *, unsigned int, struct sdiov *, int);
> -+
> -+
> -+void sd_1bit_feedcrc(struct sdcore*, unsigned int);
> -+void sd_4bit_feedcrc(struct sdcore*, unsigned int);
> -+
> -+unsigned char sd_1bit_getcrc(struct sdcore*);
> -+unsigned char sd_4bit_getcrc(struct sdcore*);
> -+
> -+/** stop takes only sdcore parameters */
> -+int stop(struct sdcore*);
> -+
> -+
> -+int tend_ssp(struct sdcore* sdcore,
> -+ unsigned int** unknown_r1, // r1
> -+ unsigned char** unknown_r2);
> -+
> -+
> -+int datssp_stream(struct sdcore* sdcore,
> -+ unsigned char** data,
> -+ int count);
> -+
> -+/*
> -+ * @param cmd is the command - I believe that the lower byte is the command, and
> -+ * the upper one is the crc
> -+ *
> -+ * @param data is a character buffer for data received in the ssp dat register, as
> -+ * a result of a command execution.
> -+ */
> -+
> -+int sdcmd(struct sdcore* sdcore,
> -+ unsigned short cmd,
> -+ unsigned int sdargs,
> -+ unsigned int* response,
> -+ unsigned char** data); // command response buffer?
> -+
> -+
> -+/**
> -+ * Error tests if a sdcommand error has been received.
> -+ * It does this by checking that the command was
> -+ * correctly returned by the card (the first byte in buffer),
> -+ * and that a CRC error has not occurred. IF one has occurred
> -+ * it will attempt a 1bit fix. (suspected)
> -+ */
> -+int error(unsigned int* buffer, unsigned int cmd);
> -+
> -+
> -+
> -+int sdsetwprot(struct sdcore *, unsigned int);
> -+#define SDLOCK_UNLOCK 0
> -+#define SDLOCK_SETPWD 1
> -+#define SDLOCK_CLRPWD 2
> -+#define SDLOCK_ERASE 8
> -+
> -+int sdlockctl(struct sdcore *,
> -+ unsigned int, // op code
> -+ unsigned char *,
> -+ unsigned char *);
> -+
> -+#endif
> -diff --git a/drivers/block/tssdcard.c b/drivers/block/tssdcard.c
> -new file mode 100644
> -index 0000000..c76d9a7
> ---- /dev/null
> -+++ b/drivers/block/tssdcard.c
> -@@ -0,0 +1,415 @@
> -+/*
> -+ * TS SD Card device driver
> -+ *
> -+ * (c) Copyright 2010 Matthieu Crapet <mcrapet@gmail.com>
> -+ * Based on Technologic Systems & Breton M. Saunders work
> -+ *
> -+ * 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.
> -+ *
> -+ * Notes:
> -+ * - request processing method is: no request queue
> -+ * - no M2M DMA is used
> -+ */
> -+
> -+#include <linux/kernel.h>
> -+#include <linux/init.h>
> -+#include <linux/module.h>
> -+#include <linux/moduleparam.h>
> -+#include <linux/major.h>
> -+#include <linux/blkdev.h>
> -+#include <linux/bio.h>
> -+#include <linux/delay.h>
> -+#include <linux/hdreg.h>
> -+#include <linux/slab.h>
> -+#include <linux/platform_device.h>
> -+
> -+#include "sdcore2.h"
> -+
> -+#define SDCARD_DEV_NAME "tssd" /* will appear in /proc/partitions & /sys/class/block */
> -+#define SD_SHIFT 4 /* max 16 partitions = 1 << 4 */
> -+
> -+#define KERN_SECTOR_SIZE 512 /* in bytes */
> -+#define HARD_SECTOR_SIZE 512 /* in bytes */
> -+#define HARD_2_KERN_SECTOR_RATIO 1 /* 1 kernel sector = 1 hardware sector */
> -+
> -+
> -+struct ts72xx_sdcard_device {
> -+ struct sdcore tssdcore; /* Physical core layer */
> -+ void __iomem *mmio_base;
> -+ long size; /* Device size in (hardware) sectors */
> -+ int id;
> -+ int media_change;
> -+ int users;
> -+
> -+ spinlock_t lock;
> -+ struct device *dev;
> -+ struct request_queue *queue;
> -+ struct gendisk *disk;
> -+};
> -+
> -+
> -+/*
> -+ * Low level function to handle an I/O request
> -+ */
> -+static inline int sdcard_ll_transfer(struct ts72xx_sdcard_device *dev,
> -+ unsigned long sector, unsigned long nsect, char *buffer, int rw)
> -+{
> -+ int ret;
> -+
> -+ //spin_unlock(&dev->lock); // ???
> -+
> -+ if ((sector + nsect) > (dev->size * HARD_2_KERN_SECTOR_RATIO)) {
> -+ dev_err(dev->dev, "tranfer: beyond-end write (%ld %ld)\n", sector, nsect);
> -+ //spin_lock(&dev->lock); // ???
> -+ return -1;
> -+ }
> -+
> -+ switch (rw) {
> -+ case WRITE:
> -+ ret = sdwrite(&dev->tssdcore, sector, buffer, nsect);
> -+ if (ret && !dev->tssdcore.sd_wprot) {
> -+ sdreset(&dev->tssdcore);
> -+ ret = sdwrite(&dev->tssdcore, sector, buffer, nsect);
> -+ }
> -+ break;
> -+
> -+ case READ:
> -+ case READA:
> -+ ret = sdread(&dev->tssdcore, sector, buffer, nsect);
> -+ if (ret) {
> -+ // SDCARD RESET may be printed when the core determines that the SD card has
> -+ // f*ed up.this is not handled correctly yet; and should likely be inside a while loop
> -+ dev_err(dev->dev, "transfer: SDCARD RESET\n");
> -+ sdreset(&dev->tssdcore);
> -+ ret = sdread(&dev->tssdcore, sector, buffer, nsect);
> -+ }
> -+ break;
> -+ }
> -+
> -+ //spin_lock(&dev->lock); // ???
> -+ return 0;
> -+}
> -+
> -+/*
> -+ * The direct make request version.
> -+ */
> -+static int sdcard_make_request(struct request_queue *q, struct bio *bio)
> -+{
> -+ struct ts72xx_sdcard_device *dev = q->queuedata;
> -+
> -+ struct bio_vec *bvec;
> -+ sector_t sector;
> -+ int i, rw;
> -+ int err = -EIO;
> -+
> -+ /* handle bio */
> -+ sector = bio->bi_sector;
> -+ rw = bio_rw(bio);
> -+
> -+ bio_for_each_segment(bvec, bio, i) {
> -+ char *buffer = __bio_kmap_atomic(bio, i, KM_USER0);
> -+ unsigned int len = bvec->bv_len / HARD_SECTOR_SIZE;
> -+
> -+ //printk("bvec: len=%d offt=%d page=%p\n", bvec->bv_len, bvec->bv_offset, bvec->bv_page);
> -+
> -+ err = sdcard_ll_transfer(dev, sector, len, buffer, rw);
> -+ if (err)
> -+ break;
> -+
> -+ sector += len;
> -+ __bio_kunmap_atomic(bio, KM_USER0);
> -+ }
> -+ bio_endio(bio, err);
> -+
> -+ return 0;
> -+}
> -+
> -+static void sdcard_delay(void *arg, unsigned int us)
> -+{
> -+ udelay(us);
> -+}
> -+
> -+static int sdcard_open(struct block_device *bdev, fmode_t mode)
> -+{
> -+ struct ts72xx_sdcard_device *dev = bdev->bd_disk->private_data;
> -+ unsigned long flags;
> -+
> -+ dev_dbg(dev->dev, "open() users=%i\n", dev->users + 1);
> -+
> -+ spin_lock_irqsave(&dev->lock, flags);
> -+ dev->users++;
> -+ spin_unlock_irqrestore(&dev->lock, flags);
> -+
> -+ check_disk_change(bdev);
> -+ return 0;
> -+};
> -+
> -+static int sdcard_release(struct gendisk *disk, fmode_t mode)
> -+{
> -+ struct ts72xx_sdcard_device *dev = disk->private_data;
> -+ unsigned long flags;
> -+
> -+ dev_dbg(dev->dev, "release() users=%i\n", dev->users - 1);
> -+
> -+ spin_lock_irqsave(&dev->lock, flags);
> -+ dev->users--;
> -+ spin_unlock_irqrestore(&dev->lock, flags);
> -+
> -+ return 0;
> -+}
> -+
> -+static int sdcard_media_changed(struct gendisk *disk)
> -+{
> -+ struct ts72xx_sdcard_device *dev = disk->private_data;
> -+
> -+ char buf[HARD_SECTOR_SIZE];
> -+ dev->media_change = sdread(&dev->tssdcore, 1, buf, 1);
> -+
> -+ dev_dbg(dev->dev, "media_changed() %i\n", dev->media_change);
> -+ return dev->media_change;
> -+}
> -+
> -+static int sdcard_revalidate(struct gendisk *disk)
> -+{
> -+ struct ts72xx_sdcard_device *dev = disk->private_data;
> -+ int ret = 0;
> -+
> -+ dev_dbg(dev->dev, "revalidate() %i\n", dev->media_change);
> -+ if (dev->media_change) {
> -+ dev->size = sdreset(&dev->tssdcore);
> -+ set_disk_ro(dev->disk, !!(dev->tssdcore.sd_wprot));
> -+ if (dev->size > 0) {
> -+ set_capacity(dev->disk, dev->size * HARD_2_KERN_SECTOR_RATIO);
> -+ dev->media_change = 0;
> -+ } else {
> -+ dev_err(dev->dev, "revalidate() no card found\n");
> -+ ret = -1;
> -+ }
> -+ }
> -+ return ret;
> -+}
> -+
> -+static int sdcard_getgeo(struct block_device *bdev, struct hd_geometry *geo)
> -+{
> -+ struct gendisk *disk = bdev->bd_disk;
> -+ struct ts72xx_sdcard_device *dev = disk->private_data;
> -+
> -+ /* We don't have real geometry info, but let's at least return
> -+ * values consistent with the size of the device */
> -+ geo->heads = 16;
> -+ geo->sectors = 32;
> -+ geo->cylinders = get_capacity(disk) / (16 * 32);
> -+
> -+ dev_dbg(dev->dev, "getgeo() %d heads, %d sectors, %d cylinders\n",
> -+ geo->heads, geo->sectors, geo->cylinders);
> -+ return 0;
> -+}
> -+
> -+/*
> -+ * The device operations structure.
> -+ */
> -+static struct block_device_operations ts72xx_sdcard_ops = {
> -+ .owner = THIS_MODULE,
> -+ .open = sdcard_open,
> -+ .release = sdcard_release,
> -+ .media_changed = sdcard_media_changed,
> -+ .revalidate_disk = sdcard_revalidate,
> -+ .getgeo = sdcard_getgeo
> -+};
> -+
> -+static int sdcard_major;
> -+
> -+/* ---------------------------------------------------------------------
> -+ * Device setup
> -+ */
> -+
> -+static int ts72xx_sdcard_setup(const char *name, struct ts72xx_sdcard_device *dev)
> -+{
> -+ int rc;
> -+
> -+ spin_lock_init(&dev->lock);
> -+
> -+ /*
> -+ * Initialize the request queue
> -+ */
> -+ dev->queue = blk_alloc_queue(GFP_KERNEL);
> -+ if (!dev->queue)
> -+ goto err_alloc_queue;
> -+
> -+ dev->queue->queuedata = dev;
> -+ blk_queue_make_request(dev->queue, sdcard_make_request);
> -+ blk_queue_logical_block_size(dev->queue, HARD_SECTOR_SIZE);
> -+
> -+ dev->tssdcore.sd_regstart = (unsigned char *)dev->mmio_base;
> -+ dev->tssdcore.os_arg = dev;
> -+ dev->tssdcore.os_delay = sdcard_delay;
> -+ dev->tssdcore.os_dmastream = NULL;
> -+ dev->tssdcore.os_dmaprep = NULL;
> -+
> -+ // don't want to write park
> -+ dev->tssdcore.sd_writeparking = 1;
> -+ // I do want to pre-erase blocks - 8 blocks pre-erase
> -+ dev->tssdcore.sd_erasehint = 8;
> -+ dev->tssdcore.sdboot_token = 0;
> -+
> -+ dev->disk = alloc_disk(1 << SD_SHIFT);
> -+ if (!dev->disk) {
> -+ goto err_alloc_disk;
> -+ }
> -+
> -+ dev->disk->major = sdcard_major;
> -+ dev->disk->first_minor = dev->id << SD_SHIFT;
> -+ dev->disk->flags = GENHD_FL_REMOVABLE;
> -+ dev->disk->fops = &ts72xx_sdcard_ops;
> -+ dev->disk->queue = dev->queue;
> -+ dev->disk->private_data = dev;
> -+ snprintf(dev->disk->disk_name, 32, SDCARD_DEV_NAME "%c", dev->id + 'a');
> -+
> -+ /* SD Card size and Reset
> -+ * (set_disk_ro, set_capacity will be called) */
> -+ dev->media_change = 1;
> -+ rc = sdcard_revalidate(dev->disk);
> -+ if (rc) {
> -+ dev_info(dev->dev, "No SD card detected!\n");
> -+ goto err_alloc_disk;
> -+ }
> -+
> -+ dev_info(dev->dev, "SD card hardware revision: %08x\n",
> -+ dev->tssdcore.sdcore_version);
> -+ dev_info(dev->dev, "block device major number = %d\n",
> -+ sdcard_major);
> -+ dev_info(dev->dev, "New SD card detected, name=%s size=%ld (sectors)\n",
> -+ dev->disk->disk_name, dev->size);
> -+
> -+ /* Make the sysace device 'live' */
> -+ add_disk(dev->disk);
> -+
> -+ return 0;
> -+
> -+err_alloc_disk:
> -+ blk_cleanup_queue(dev->queue);
> -+err_alloc_queue:
> -+ return -ENOMEM;
> -+}
> -+
> -+
> -+/* ---------------------------------------------------------------------
> -+ * Platform drivers functons
> -+ */
> -+
> -+static int __init ts72xx_sdcard_probe(struct platform_device *pdev)
> -+{
> -+ struct ts72xx_sdcard_device *dev;
> -+ struct resource *res;
> -+ int rc;
> -+
> -+ dev = kzalloc(sizeof(struct ts72xx_sdcard_device), GFP_KERNEL);
> -+ if (!dev) {
> -+ rc = -ENOMEM;
> -+ goto fail_no_mem;
> -+ }
> -+
> -+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> -+ if (res == NULL) {
> -+ rc = -ENXIO;
> -+ goto fail_no_mem_resource;
> -+ }
> -+
> -+ res = request_mem_region(res->start, resource_size(res), pdev->name);
> -+ if (res == NULL) {
> -+ rc = -EBUSY;
> -+ goto fail_no_mem_resource;
> -+ }
> -+
> -+ dev->mmio_base = ioremap(res->start, resource_size(res));
> -+ if (dev->mmio_base == NULL) {
> -+ rc = -ENXIO;
> -+ goto fail_no_ioremap;
> -+ }
> -+
> -+ dev->dev = &pdev->dev;
> -+ dev->id = pdev->id;
> -+ platform_set_drvdata(pdev, dev);
> -+
> -+ rc = ts72xx_sdcard_setup(SDCARD_DEV_NAME, dev);
> -+ if (rc) {
> -+ dev_err(dev->dev, "ts72xx_sdcard_setup failed\n");
> -+ goto fail_sdcard_setup;
> -+ }
> -+
> -+ return 0;
> -+
> -+fail_sdcard_setup:
> -+ iounmap(dev->mmio_base);
> -+fail_no_ioremap:
> -+ release_mem_region(res->start, resource_size(res));
> -+fail_no_mem_resource:
> -+ kfree(dev);
> -+fail_no_mem:
> -+ return rc;
> -+}
> -+
> -+static int __exit ts72xx_sdcard_remove(struct platform_device *pdev)
> -+{
> -+ struct ts72xx_sdcard_device *dev = platform_get_drvdata(pdev);
> -+ struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> -+
> -+ platform_set_drvdata(pdev, NULL);
> -+ iounmap(dev->mmio_base);
> -+ release_mem_region(res->start, resource_size(res));
> -+ blk_cleanup_queue(dev->queue);
> -+ del_gendisk(dev->disk);
> -+ put_disk(dev->disk);
> -+ kfree(dev);
> -+
> -+ return 0;
> -+}
> -+
> -+static struct platform_driver ts72xx_sdcard_driver = {
> -+ .driver = {
> -+ .name = "ts72xx-sdcard",
> -+ .owner = THIS_MODULE,
> -+ },
> -+ .remove = __exit_p(ts72xx_sdcard_remove),
> -+};
> -+
> -+
> -+/* ---------------------------------------------------------------------
> -+ * Module init/exit routines
> -+ */
> -+
> -+static int __init ts72xx_sdcard_init(void)
> -+{
> -+ int rc;
> -+
> -+ sdcard_major = rc = register_blkdev(sdcard_major, SDCARD_DEV_NAME);
> -+ if (rc <= 0) {
> -+ printk(KERN_ERR "%s:%u: register_blkdev failed %d\n", __func__,
> -+ __LINE__, rc);
> -+ return rc;
> -+ }
> -+
> -+ rc = platform_driver_probe(&ts72xx_sdcard_driver, ts72xx_sdcard_probe);
> -+ if (rc)
> -+ unregister_blkdev(sdcard_major, SDCARD_DEV_NAME);
> -+
> -+ return rc;
> -+}
> -+
> -+static void __exit ts72xx_sdcard_exit(void)
> -+{
> -+ unregister_blkdev(sdcard_major, SDCARD_DEV_NAME);
> -+ platform_driver_unregister(&ts72xx_sdcard_driver);
> -+}
> -+
> -+module_init(ts72xx_sdcard_init);
> -+module_exit(ts72xx_sdcard_exit);
> -+
> -+MODULE_AUTHOR("Matthieu Crapet <mcrapet@gmail.com>");
> -+MODULE_DESCRIPTION("TS72xx SD Card block driver");
> -+MODULE_LICENSE("GPL");
> -+MODULE_ALIAS_BLOCKDEV_MAJOR(SCSI_DISK0_MAJOR);
> -+MODULE_ALIAS("tssd");
> ---
> -1.7.0.4
> -
> diff --git a/recipes/linux/linux-2.6.36/ts72xx/0016-ts72xx_spi_tmp124.patch b/recipes/linux/linux-2.6.36/ts72xx/0016-ts72xx_spi_tmp124.patch
> deleted file mode 100644
> index 0099c91..0000000
> --- a/recipes/linux/linux-2.6.36/ts72xx/0016-ts72xx_spi_tmp124.patch
> +++ /dev/null
> @@ -1,305 +0,0 @@
> -From 6e1298e3647a7eea65fe323ee0181ab2373fd78d Mon Sep 17 00:00:00 2001
> -From: Matthieu Crapet <mcrapet@gmail.com>
> -Date: Tue, 22 Jun 2010 15:48:27 +0200
> -Subject: [PATCH 16/24] ts72xx_spi_tmp124
> -MIME-Version: 1.0
> -Content-Type: text/plain; charset=UTF-8
> -Content-Transfer-Encoding: 8bit
> -
> -It's an option. A 3-wire spi temperature sensor can be populated on TS-72XX sbc.
> -
> -Signed-off-by: Petr Štetiar <ynezz@true.cz>
> ----
> - arch/arm/mach-ep93xx/ts72xx.c | 63 ++++++++++++++++
> - drivers/spi/Kconfig | 7 ++
> - drivers/spi/Makefile | 1 +
> - drivers/spi/tmp124.c | 158 +++++++++++++++++++++++++++++++++++++++++
> - 4 files changed, 229 insertions(+), 0 deletions(-)
> - create mode 100644 drivers/spi/tmp124.c
> -
> -diff --git a/arch/arm/mach-ep93xx/ts72xx.c b/arch/arm/mach-ep93xx/ts72xx.c
> -index c99f112..941eeac 100644
> ---- a/arch/arm/mach-ep93xx/ts72xx.c
> -+++ b/arch/arm/mach-ep93xx/ts72xx.c
> -@@ -23,7 +23,11 @@
> - #include <linux/gpio.h>
> - #include <linux/i2c.h>
> - #include <linux/i2c-gpio.h>
> -+#include <linux/mtd/nand.h>
> -+#include <linux/mtd/partitions.h>
> -+#include <linux/spi/spi.h>
> -
> -+#include <mach/ep93xx_spi.h>
> - #include <mach/hardware.h>
> - #include <mach/ts72xx.h>
> -
> -@@ -352,6 +356,60 @@ static struct i2c_gpio_platform_data ts72xx_i2c_gpio_data = {
> - static struct i2c_board_info __initdata ts72xx_i2c_board_info[] = {
> - };
> -
> -+/*************************************************************************
> -+ * SPI
> -+ *************************************************************************/
> -+#if defined(CONFIG_SPI_TMP124) || defined(CONFIG_SPI_TMP124_MODULE)
> -+
> -+/* this is our GPIO line used for chip select */
> -+#define TMP124_CHIP_SELECT_GPIO EP93XX_GPIO_LINE_MCCD2
> -+
> -+static int ts72xx_tmp124_setup(struct spi_device *spi)
> -+{
> -+ int err;
> -+
> -+ err = gpio_request(TMP124_CHIP_SELECT_GPIO, spi->modalias);
> -+ if (err)
> -+ return err;
> -+
> -+ gpio_direction_output(TMP124_CHIP_SELECT_GPIO, 1);
> -+
> -+ return 0;
> -+}
> -+
> -+static void ts72xx_tmp124_cleanup(struct spi_device *spi)
> -+{
> -+ gpio_set_value(TMP124_CHIP_SELECT_GPIO, 1);
> -+ gpio_direction_input(TMP124_CHIP_SELECT_GPIO);
> -+ gpio_free(TMP124_CHIP_SELECT_GPIO);
> -+}
> -+
> -+static void ts72xx_tmp124_cs_control(struct spi_device *spi, int value)
> -+{
> -+ gpio_set_value(TMP124_CHIP_SELECT_GPIO, value);
> -+}
> -+
> -+static struct ep93xx_spi_chip_ops ts72xx_tmp124_ops = {
> -+ .setup = ts72xx_tmp124_setup,
> -+ .cleanup = ts72xx_tmp124_cleanup,
> -+ .cs_control = ts72xx_tmp124_cs_control,
> -+};
> -+
> -+static struct spi_board_info ts72xx_spi_devices[] = {
> -+ {
> -+ .modalias = "tmp124",
> -+ .max_speed_hz = 2 * 1000 * 1000,
> -+ .bus_num = 0,
> -+ .chip_select = 0,
> -+ .controller_data = &ts72xx_tmp124_ops,
> -+ },
> -+};
> -+
> -+static struct ep93xx_spi_info ts72xx_spi_info = {
> -+ .num_chipselect = ARRAY_SIZE(ts72xx_spi_devices),
> -+};
> -+#endif
> -+
> - static void __init ts72xx_init_machine(void)
> - {
> - ep93xx_init_devices();
> -@@ -365,6 +423,11 @@ static void __init ts72xx_init_machine(void)
> - ts72xx_i2c_board_info,
> - ARRAY_SIZE(ts72xx_i2c_board_info));
> -
> -+ #if defined(CONFIG_SPI_TMP124) || defined(CONFIG_SPI_TMP124_MODULE)
> -+ ep93xx_register_spi(&ts72xx_spi_info, ts72xx_spi_devices,
> -+ ARRAY_SIZE(ts72xx_spi_devices));
> -+ #endif
> -+
> - if (is_max197_installed()) {
> - platform_device_register(&ts72xx_max197_device);
> - }
> -diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
> -index 91c2f4f..05b78ca 100644
> ---- a/drivers/spi/Kconfig
> -+++ b/drivers/spi/Kconfig
> -@@ -379,6 +379,13 @@ config SPI_TLE62X0
> - sysfs interface, with each line presented as a kind of GPIO
> - exposing both switch control and diagnostic feedback.
> -
> -+config SPI_TMP124
> -+ tristate "Texas Instruments TMP1224, TMP124"
> -+ depends on SPI_MASTER && SYSFS
> -+ help
> -+ SPI driver for TMP12X temperature sensor chips.
> -+ This provides a sysfs entry for temperature reading (2�C accurate).
> -+
> - #
> - # Add new SPI protocol masters in alphabetical order above this line
> - #
> -diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile
> -index e9cbd18..c8f85ea 100644
> ---- a/drivers/spi/Makefile
> -+++ b/drivers/spi/Makefile
> -@@ -57,6 +57,7 @@ spi_s3c24xx_hw-$(CONFIG_SPI_S3C24XX_FIQ) += spi_s3c24xx_fiq.o
> - # SPI protocol drivers (device/link on bus)
> - obj-$(CONFIG_SPI_SPIDEV) += spidev.o
> - obj-$(CONFIG_SPI_TLE62X0) += tle62x0.o
> -+obj-$(CONFIG_SPI_TMP124) += tmp124.o
> - # ... add above this line ...
> -
> - # SPI slave controller drivers (upstream link)
> -diff --git a/drivers/spi/tmp124.c b/drivers/spi/tmp124.c
> -new file mode 100644
> -index 0000000..e41ec8c
> ---- /dev/null
> -+++ b/drivers/spi/tmp124.c
> -@@ -0,0 +1,158 @@
> -+/*
> -+ * TMP124 SPI protocol driver
> -+ *
> -+ * (c) Copyright 2008-2010 Matthieu Crapet <mcrapet@gmail.com>
> -+ * Based on tle62x0.c by Ben Dooks, <ben@simtec.co.uk>
> -+ *
> -+ * 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.
> -+ *
> -+ * Note: The chip uses a '3-wire SPI' (miso and mosi are the same pin).
> -+ */
> -+
> -+#include <linux/module.h>
> -+#include <linux/kernel.h>
> -+#include <linux/init.h>
> -+#include <linux/spi/spi.h>
> -+#include <linux/slab.h>
> -+#include <linux/sched.h>
> -+
> -+struct tmp124_state {
> -+ struct spi_device *bus;
> -+ u8 tx_buff[2];
> -+ u8 rx_buff[2];
> -+};
> -+
> -+static inline int tmp124_write_then_read(struct tmp124_state *st)
> -+{
> -+ struct spi_message msg;
> -+ struct spi_transfer xfer[2] = {
> -+ {
> -+ .tx_buf = st->tx_buff,
> -+ .rx_buf = NULL,
> -+ .len = 2,
> -+ }, {
> -+ .tx_buf = NULL,
> -+ .rx_buf = st->rx_buff,
> -+ .len = 2,
> -+ }
> -+ };
> -+
> -+ spi_message_init(&msg);
> -+ spi_message_add_tail(&xfer[0], &msg);
> -+ spi_sync(st->bus, &msg);
> -+
> -+ /* SPI_3WIRE is not handled by ep93xx_spi, the 2 messages must be
> -+ * splitted. We must wait to not confuse driver with read/write. */
> -+ schedule_timeout(usecs_to_jiffies(1000));
> -+
> -+ spi_message_init(&msg);
> -+ spi_message_add_tail(&xfer[1], &msg);
> -+ return spi_sync(st->bus, &msg);
> -+}
> -+
> -+static ssize_t tmp124_temperature_show(struct device *dev,
> -+ struct device_attribute *attr, char *buf)
> -+{
> -+ struct tmp124_state *st = dev_get_drvdata(dev);
> -+ int ret;
> -+
> -+ ((short *)st->tx_buff)[0] = 0x8000;
> -+
> -+ ret = tmp124_write_then_read(st);
> -+ if (ret < 0) {
> -+ dev_err(&st->bus->dev, "tmp124_write_then_read\n");
> -+ ret = 0;
> -+ } else {
> -+ signed long val = ((short *)st->rx_buff)[0];
> -+
> -+ val = val >> 3;
> -+
> -+ /* 2 digit precision (0.0625*100) */
> -+ val = (val * 50) / 8;
> -+ ret = snprintf(buf, PAGE_SIZE, "%ld.%02ld\n", val/100, abs(val%100));
> -+ }
> -+ return ret;
> -+}
> -+
> -+static DEVICE_ATTR(temperature, S_IRUGO, tmp124_temperature_show, NULL);
> -+
> -+static int __devinit tmp124_probe(struct spi_device *spi)
> -+{
> -+ struct tmp124_state *st;
> -+ int ret;
> -+
> -+ st = kzalloc(sizeof(struct tmp124_state), GFP_KERNEL);
> -+ if (st == NULL) {
> -+ dev_err(&spi->dev, "no memory for device state\n");
> -+ return -ENOMEM;
> -+ }
> -+
> -+ /* required config */
> -+ spi->bits_per_word = 16;
> -+ spi->mode = SPI_MODE_0;
> -+
> -+ ret = spi_setup(spi);
> -+ if (ret) {
> -+ dev_err(&spi->dev, "setup device\n");
> -+ goto err;
> -+ }
> -+
> -+ ret = device_create_file(&spi->dev, &dev_attr_temperature);
> -+ if (ret) {
> -+ dev_err(&spi->dev, "cannot create temperature attribute\n");
> -+ goto err;
> -+ }
> -+
> -+ st->bus = spi;
> -+ spi_set_drvdata(spi, st);
> -+ return 0;
> -+
> -+err:
> -+ kfree(st);
> -+ return ret;
> -+}
> -+
> -+static int __devexit tmp124_remove(struct spi_device *spi)
> -+{
> -+ struct tmp124_state *st = spi_get_drvdata(spi);
> -+
> -+ device_remove_file(&spi->dev, &dev_attr_temperature);
> -+ kfree(st);
> -+ return 0;
> -+}
> -+
> -+static struct spi_driver tmp124_driver = {
> -+ .driver = {
> -+ .name = "tmp124",
> -+ .owner = THIS_MODULE,
> -+ },
> -+ .probe = tmp124_probe,
> -+ .remove = __devexit_p(tmp124_remove),
> -+};
> -+
> -+static __init int tmp124_init(void)
> -+{
> -+ return spi_register_driver(&tmp124_driver);
> -+}
> -+
> -+static __exit void tmp124_exit(void)
> -+{
> -+ spi_unregister_driver(&tmp124_driver);
> -+}
> -+
> -+module_init(tmp124_init);
> -+module_exit(tmp124_exit);
> -+
> -+MODULE_AUTHOR("Matthieu Crapet <mcrapet@gmail.com>");
> -+MODULE_DESCRIPTION("TMP124 SPI Protocol Driver");
> -+MODULE_LICENSE("GPL");
> -+MODULE_ALIAS("spi:tmp124");
> -+MODULE_VERSION("0.2");
> ---
> -1.7.0.4
> -
> diff --git a/recipes/linux/linux-2.6.36/ts72xx/0017-ts72xx-use-CPLD-watchdog-for-reset.patch b/recipes/linux/linux-2.6.36/ts72xx/0017-ts72xx-use-CPLD-watchdog-for-reset.patch
> deleted file mode 100644
> index 0d844bf..0000000
> --- a/recipes/linux/linux-2.6.36/ts72xx/0017-ts72xx-use-CPLD-watchdog-for-reset.patch
> +++ /dev/null
> @@ -1,53 +0,0 @@
> -From dc31543df131eeeadf4f36fbca25b89eeda1de53 Mon Sep 17 00:00:00 2001
> -From: =?UTF-8?q?Petr=20=C5=A0tetiar?= <ynezz@true.cz>
> -Date: Thu, 21 Oct 2010 20:00:49 +0200
> -Subject: [PATCH 17/24] ts72xx: use CPLD watchdog for reset
> -MIME-Version: 1.0
> -Content-Type: text/plain; charset=UTF-8
> -Content-Transfer-Encoding: 8bit
> -
> -
> -Signed-off-by: Petr Štetiar <ynezz@true.cz>
> ----
> - arch/arm/mach-ep93xx/include/mach/system.h | 13 +++++++++++++
> - 1 files changed, 13 insertions(+), 0 deletions(-)
> -
> -diff --git a/arch/arm/mach-ep93xx/include/mach/system.h b/arch/arm/mach-ep93xx/include/mach/system.h
> -index 6d661fe..b657a9a 100644
> ---- a/arch/arm/mach-ep93xx/include/mach/system.h
> -+++ b/arch/arm/mach-ep93xx/include/mach/system.h
> -@@ -3,6 +3,10 @@
> - */
> -
> - #include <mach/hardware.h>
> -+#ifdef CONFIG_MACH_TS72XX
> -+#include <linux/io.h>
> -+#include <mach/ts72xx.h>
> -+#endif
> -
> - static inline void arch_idle(void)
> - {
> -@@ -13,11 +17,20 @@ static inline void arch_reset(char mode, const char *cmd)
> - {
> - local_irq_disable();
> -
> -+#ifdef CONFIG_MACH_TS72XX
> -+ /* It's more reliable to use CPLD watchdog to perform reset */
> -+ if (board_is_ts7200() || board_is_ts7250() || board_is_ts7260() ||
> -+ board_is_ts7300() || board_is_ts7400()) {
> -+ __raw_writeb(0x5, TS72XX_WDT_FEED_PHYS_BASE);
> -+ __raw_writeb(0x1, TS72XX_WDT_CONTROL_PHYS_BASE);
> -+ }
> -+#else
> - /*
> - * Set then clear the SWRST bit to initiate a software reset
> - */
> - ep93xx_devcfg_set_bits(EP93XX_SYSCON_DEVCFG_SWRST);
> - ep93xx_devcfg_clear_bits(EP93XX_SYSCON_DEVCFG_SWRST);
> -+#endif
> -
> - while (1)
> - ;
> ---
> -1.7.0.4
> -
> diff --git a/recipes/linux/linux-2.6.36/ts72xx/0018-ethoc-ts7300-fixes.patch b/recipes/linux/linux-2.6.36/ts72xx/0018-ethoc-ts7300-fixes.patch
> deleted file mode 100644
> index 3d5fd84..0000000
> --- a/recipes/linux/linux-2.6.36/ts72xx/0018-ethoc-ts7300-fixes.patch
> +++ /dev/null
> @@ -1,93 +0,0 @@
> -From 65cd401ec17f4a9791297e413e5954f25c71b2b0 Mon Sep 17 00:00:00 2001
> -From: =?UTF-8?q?Petr=20=C5=A0tetiar?= <ynezz@true.cz>
> -Date: Sat, 23 Oct 2010 19:49:21 +0200
> -Subject: [PATCH 18/24] ethoc: ts7300 fixes
> -MIME-Version: 1.0
> -Content-Type: text/plain; charset=UTF-8
> -Content-Transfer-Encoding: 8bit
> -
> -Signed-off-by: Ian Thompson <ian.thompson@pgs.com>
> -Signed-off-by: Petr Štetiar <ynezz@true.cz>
> ----
> - drivers/net/ethoc.c | 27 ++++++++++++++++++++-------
> - 1 files changed, 20 insertions(+), 7 deletions(-)
> -
> -diff --git a/drivers/net/ethoc.c b/drivers/net/ethoc.c
> -index 6d653c4..a0f62eb 100644
> ---- a/drivers/net/ethoc.c
> -+++ b/drivers/net/ethoc.c
> -@@ -21,7 +21,11 @@
> - #include <linux/slab.h>
> - #include <net/ethoc.h>
> -
> -+#ifndef CONFIG_MACH_TS72XX
> - static int buffer_size = 0x8000; /* 32 KBytes */
> -+#else
> -+static int buffer_size = 0x2000; /* 8 KBytes */
> -+#endif
> - module_param(buffer_size, int, 0);
> - MODULE_PARM_DESC(buffer_size, "DMA buffer allocation size");
> -
> -@@ -525,11 +529,6 @@ static irqreturn_t ethoc_interrupt(int irq, void *dev_id)
> -
> - ethoc_ack_irq(priv, pending);
> -
> -- if (pending & INT_MASK_BUSY) {
> -- dev_err(&dev->dev, "packet dropped\n");
> -- dev->stats.rx_dropped++;
> -- }
> --
> - if (pending & INT_MASK_RX) {
> - if (napi_schedule_prep(&priv->napi))
> - __napi_schedule(&priv->napi);
> -@@ -834,10 +833,10 @@ static netdev_tx_t ethoc_start_xmit(struct sk_buff *skb, struct net_device *dev)
> - bd.stat &= ~TX_BD_PAD;
> -
> - dest = priv->vma[entry];
> -- memcpy_toio(dest, skb->data, skb->len);
> -+ memcpy_toio(dest, skb->data, skb->len + 2);
> -
> - bd.stat &= ~(TX_BD_STATS | TX_BD_LEN_MASK);
> -- bd.stat |= TX_BD_LEN(skb->len);
> -+ bd.stat |= TX_BD_LEN(skb->len + 2);
> - ethoc_write_bd(priv, entry, &bd);
> -
> - bd.stat |= TX_BD_READY;
> -@@ -992,6 +991,8 @@ static int __devinit ethoc_probe(struct platform_device *pdev)
> - (struct ethoc_platform_data *)pdev->dev.platform_data;
> - memcpy(netdev->dev_addr, pdata->hwaddr, IFHWADDRLEN);
> - priv->phy_id = pdata->phy_id;
> -+ } else {
> -+ priv->phy_id = 1;
> - }
> -
> - /* Check that the given MAC address is valid. If it isn't, read the
> -@@ -1004,6 +1005,17 @@ static int __devinit ethoc_probe(struct platform_device *pdev)
> - if (!is_valid_ether_addr(netdev->dev_addr))
> - random_ether_addr(netdev->dev_addr);
> -
> -+ /* take this out for more general usage */
> -+ netdev->dev_addr[0] = 0x00;
> -+ netdev->dev_addr[1] = 0x88;
> -+ netdev->dev_addr[2] = 0x88;
> -+ netdev->dev_addr[3] = 0x88;
> -+ netdev->dev_addr[4] = 0x88;
> -+ netdev->dev_addr[5] = 0x01;
> -+
> -+ printk("ethoc: setting MAC address to %2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x\n",netdev->dev_addr[0],
> -+ netdev->dev_addr[1],netdev->dev_addr[2],netdev->dev_addr[3],netdev->dev_addr[4],
> -+ netdev->dev_addr[5]);
> - ethoc_set_mac_address(netdev, netdev->dev_addr);
> -
> - /* register MII bus */
> -@@ -1131,6 +1143,7 @@ static struct platform_driver ethoc_driver = {
> -
> - static int __init ethoc_init(void)
> - {
> -+ printk("ethoc driver with ts73xx fixes initialized\n");
> - return platform_driver_register(ðoc_driver);
> - }
> -
> ---
> -1.7.0.4
> -
> diff --git a/recipes/linux/linux-2.6.36/ts72xx/0019-ts7300-add-ethernet-support.patch b/recipes/linux/linux-2.6.36/ts72xx/0019-ts7300-add-ethernet-support.patch
> deleted file mode 100644
> index 3895966..0000000
> --- a/recipes/linux/linux-2.6.36/ts72xx/0019-ts7300-add-ethernet-support.patch
> +++ /dev/null
> @@ -1,87 +0,0 @@
> -From 0945e8b61f170da6b5d249863f46eda5fdce3a7c Mon Sep 17 00:00:00 2001
> -From: =?UTF-8?q?Petr=20=C5=A0tetiar?= <ynezz@true.cz>
> -Date: Thu, 21 Oct 2010 11:51:44 +0200
> -Subject: [PATCH 19/24] ts7300: add ethernet support
> -MIME-Version: 1.0
> -Content-Type: text/plain; charset=UTF-8
> -Content-Transfer-Encoding: 8bit
> -
> -Signed-off-by: Ian Thompson <ian.thompson@pgs.com>
> -Signed-off-by: Petr Štetiar <ynezz@true.cz>
> ----
> - arch/arm/mach-ep93xx/include/mach/ts72xx.h | 3 ++
> - arch/arm/mach-ep93xx/ts72xx.c | 30 ++++++++++++++++++++++++++++
> - 2 files changed, 33 insertions(+), 0 deletions(-)
> -
> -diff --git a/arch/arm/mach-ep93xx/include/mach/ts72xx.h b/arch/arm/mach-ep93xx/include/mach/ts72xx.h
> -index 1d50dec..beb3e3c 100644
> ---- a/arch/arm/mach-ep93xx/include/mach/ts72xx.h
> -+++ b/arch/arm/mach-ep93xx/include/mach/ts72xx.h
> -@@ -135,6 +135,9 @@
> -
> - #define TS7260_SDCARD_PHYS_BASE 0x13000000
> -
> -+#define TS7300_ETHOC_PHYS_BASE 0x72100000
> -+#define TS7300_ETHOC_IO_BASE 0x72102000
> -+
> - #ifndef __ASSEMBLY__
> -
> - static inline int board_is_ts7200(void)
> -diff --git a/arch/arm/mach-ep93xx/ts72xx.c b/arch/arm/mach-ep93xx/ts72xx.c
> -index 941eeac..0c07bd8 100644
> ---- a/arch/arm/mach-ep93xx/ts72xx.c
> -+++ b/arch/arm/mach-ep93xx/ts72xx.c
> -@@ -30,6 +30,7 @@
> - #include <mach/ep93xx_spi.h>
> - #include <mach/hardware.h>
> - #include <mach/ts72xx.h>
> -+#include <mach/irqs.h>
> -
> - #include <asm/mach-types.h>
> - #include <asm/mach/map.h>
> -@@ -341,6 +342,32 @@ static struct ep93xx_eth_data __initdata ts72xx_eth_data = {
> - .phy_id = 1,
> - };
> -
> -+static struct resource ts7300_ethoc_resources[] = {
> -+ [0] = {
> -+ .start = TS7300_ETHOC_IO_BASE,
> -+ .end = TS7300_ETHOC_IO_BASE + 0x3FF,
> -+ .flags = IORESOURCE_MEM,
> -+ },
> -+ [1] = {
> -+ .start = TS7300_ETHOC_PHYS_BASE,
> -+ .end = TS7300_ETHOC_PHYS_BASE + 0x1FFF,
> -+ .flags = IORESOURCE_MEM,
> -+ },
> -+ [2] = {
> -+ .start = IRQ_EP93XX_EXT3,
> -+ .end = IRQ_EP93XX_EXT3,
> -+ .flags = IORESOURCE_IRQ,
> -+ },
> -+};
> -+
> -+static struct platform_device ts7300_ethoc_device = {
> -+ .name = "ethoc",
> -+ .id = 0,
> -+ .num_resources = 3,
> -+ .resource = ts7300_ethoc_resources,
> -+};
> -+
> -+
> - /*************************************************************************
> - * I2C (make access through TS-72XX "DIO" 2x8 header)
> - *************************************************************************/
> -@@ -432,6 +459,9 @@ static void __init ts72xx_init_machine(void)
> - platform_device_register(&ts72xx_max197_device);
> - }
> -
> -+ if (board_is_ts7300())
> -+ platform_device_register(&ts7300_ethoc_device);
> -+
> - /* PWM1 is DIO_6 on TS-72xx header */
> - ep93xx_register_pwm(0, 1);
> - }
> ---
> -1.7.0.4
> -
> diff --git a/recipes/linux/linux-2.6.36/ts72xx/0023-ts72xx-add-lcd-linux-driver.patch b/recipes/linux/linux-2.6.36/ts72xx/0023-ts72xx-add-lcd-linux-driver.patch
> deleted file mode 100644
> index 5fb3b01..0000000
> --- a/recipes/linux/linux-2.6.36/ts72xx/0023-ts72xx-add-lcd-linux-driver.patch
> +++ /dev/null
> @@ -1,4569 +0,0 @@
> -From 0e934482ba53c9d73dcbd3727da8f39da5dfa5ce Mon Sep 17 00:00:00 2001
> -From: =?UTF-8?q?Petr=20=C5=A0tetiar?= <ynezz@true.cz>
> -Date: Sun, 7 Nov 2010 14:41:41 +0100
> -Subject: [PATCH 23/24] ts72xx: add lcd-linux driver
> -MIME-Version: 1.0
> -Content-Type: text/plain; charset=UTF-8
> -Content-Transfer-Encoding: 8bit
> -
> -- based on LCD-Linux v0.13.9 (latest stable release)
> -- supports only hd44780 compatible display
> -- LCD in 8-bit mode operation only (D0-D7) connected to LCD connector
> -
> -Signed-off-by: Petr Štetiar <ynezz@true.cz>
> ----
> - arch/arm/Kconfig | 2 +
> - drivers/Makefile | 1 +
> - drivers/lcd-linux/Config.in | 8 +
> - drivers/lcd-linux/Kconfig | 33 +
> - drivers/lcd-linux/Makefile | 8 +
> - drivers/lcd-linux/cgram/default.h | 37 +
> - drivers/lcd-linux/cgram/swedish.h | 33 +
> - drivers/lcd-linux/charmap.h | 79 +
> - drivers/lcd-linux/commands.h | 77 +
> - drivers/lcd-linux/config.h | 73 +
> - drivers/lcd-linux/hd44780.c | 854 +++++++++++
> - drivers/lcd-linux/lcd-linux.c | 3023 +++++++++++++++++++++++++++++++++++++
> - include/linux/hd44780.h | 47 +
> - include/linux/lcd-linux.h | 158 ++
> - 14 files changed, 4433 insertions(+), 0 deletions(-)
> - create mode 100644 drivers/lcd-linux/Config.in
> - create mode 100644 drivers/lcd-linux/Kconfig
> - create mode 100644 drivers/lcd-linux/Makefile
> - create mode 100644 drivers/lcd-linux/cgram/default.h
> - create mode 100644 drivers/lcd-linux/cgram/swedish.h
> - create mode 100644 drivers/lcd-linux/charmap.h
> - create mode 100644 drivers/lcd-linux/commands.h
> - create mode 100644 drivers/lcd-linux/config.h
> - create mode 100644 drivers/lcd-linux/hd44780.c
> - create mode 100644 drivers/lcd-linux/lcd-linux.c
> - create mode 100644 include/linux/hd44780.h
> - create mode 100644 include/linux/lcd-linux.h
> -
> -diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
> -index 8e6c85d..f1e0c4a 100644
> ---- a/arch/arm/Kconfig
> -+++ b/arch/arm/Kconfig
> -@@ -1802,6 +1802,8 @@ source "net/Kconfig"
> -
> - source "drivers/Kconfig"
> -
> -+source "drivers/lcd-linux/Kconfig"
> -+
> - source "fs/Kconfig"
> -
> - source "arch/arm/Kconfig.debug"
> -diff --git a/drivers/Makefile b/drivers/Makefile
> -index a2aea53..848a6f2 100644
> ---- a/drivers/Makefile
> -+++ b/drivers/Makefile
> -@@ -115,3 +115,4 @@ obj-$(CONFIG_VLYNQ) += vlynq/
> - obj-$(CONFIG_STAGING) += staging/
> - obj-y += platform/
> - obj-y += ieee802154/
> -+obj-$(CONFIG_LCD_LINUX) += lcd-linux/
> -diff --git a/drivers/lcd-linux/Config.in b/drivers/lcd-linux/Config.in
> -new file mode 100644
> -index 0000000..4a38801
> ---- /dev/null
> -+++ b/drivers/lcd-linux/Config.in
> -@@ -0,0 +1,8 @@
> -+if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
> -+ mainmenu_option next_comment
> -+ comment 'LCD support'
> -+
> -+ tristate 'LCD-Linux layer' CONFIG_LCD_LINUX
> -+ dep_tristate ' HD44780 controller' CONFIG_LCD_HD44780 $CONFIG_LCD_LINUX
> -+ endmenu
> -+fi
> -diff --git a/drivers/lcd-linux/Kconfig b/drivers/lcd-linux/Kconfig
> -new file mode 100644
> -index 0000000..a102fc5
> ---- /dev/null
> -+++ b/drivers/lcd-linux/Kconfig
> -@@ -0,0 +1,33 @@
> -+menu "LCD support"
> -+ depends on EXPERIMENTAL
> -+
> -+config LCD_LINUX
> -+ tristate "LCD-Linux layer"
> -+ default n
> -+ help
> -+ LCD-Linux provides an easy way to drive LCD displays under
> -+ Linux by creating a character which can be read or written.
> -+ It features complete VT102 emulation and recognizes
> -+ many escape sequences. If you want to use it you must also
> -+ choose an appropriate driver, otherwise it will not be
> -+ very useful. For more information see
> -+ http://lcd-linux.sourceforge.net/
> -+
> -+ To compile LCD-Linux as a module, choose M here:
> -+ the module will be called lcd-linux.
> -+
> -+config LCD_HD44780
> -+ tristate "HD44780 controller"
> -+ depends on LCD_LINUX && MACH_TS72XX
> -+ default n
> -+ help
> -+ This is a LCD-Linux driver for LCD displays based on the
> -+ Hitachi HD44780 (and compatible) controllers connected
> -+ to LCD port on the TS72xx boards.
> -+
> -+ To compile this driver as a module, choose M here:
> -+ the module will be called hd44780.
> -+
> -+ If unsure, say N.
> -+
> -+endmenu
> -diff --git a/drivers/lcd-linux/Makefile b/drivers/lcd-linux/Makefile
> -new file mode 100644
> -index 0000000..079aa79
> ---- /dev/null
> -+++ b/drivers/lcd-linux/Makefile
> -@@ -0,0 +1,8 @@
> -+# $Id: Makefile-2.6,v 1.3 2006/12/13 15:53:00 mjona Exp $
> -+#
> -+# Standard Makefile to statically compile LCD-Linux into the kernel
> -+# Linux 2.6
> -+
> -+obj-$(CONFIG_LCD_LINUX) += lcd-linux.o
> -+obj-$(CONFIG_LCD_HD44780) += hd44780.o
> -+
> -diff --git a/drivers/lcd-linux/cgram/default.h b/drivers/lcd-linux/cgram/default.h
> -new file mode 100644
> -index 0000000..635146a
> ---- /dev/null
> -+++ b/drivers/lcd-linux/cgram/default.h
> -@@ -0,0 +1,37 @@
> -+/* default.h
> -+ *
> -+ * $Id: default.h,v 1.1.1.1 2005/08/23 13:30:14 mjona Exp $
> -+ *
> -+ * Default user defined characters for lcdmod.
> -+ *
> -+ * Copyright (C) by Michael McLellan (mikey@cs.auckland.ac.nz)
> -+ *
> -+ * 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 init_charmap(void)
> -+{
> -+}
> -+
> -+static unsigned char cg0[] = { 0x1f, 0x1f, 0x11, 0x0f, 0x11, 0x1e, 0x01, 0x1f };
> -+static unsigned char cg1[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f };
> -+static unsigned char cg2[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x1f };
> -+static unsigned char cg3[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x1f, 0x1f };
> -+static unsigned char cg4[] = { 0x00, 0x00, 0x00, 0x00, 0x1f, 0x1f, 0x1f, 0x1f };
> -+static unsigned char cg5[] = { 0x00, 0x00, 0x00, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f };
> -+static unsigned char cg6[] = { 0x00, 0x00, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f };
> -+static unsigned char cg7[] = { 0x00, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f };
> -diff --git a/drivers/lcd-linux/cgram/swedish.h b/drivers/lcd-linux/cgram/swedish.h
> -new file mode 100644
> -index 0000000..a92c31c
> ---- /dev/null
> -+++ b/drivers/lcd-linux/cgram/swedish.h
> -@@ -0,0 +1,33 @@
> -+/* swedish.h
> -+ *
> -+ * $Id: swedish.h,v 1.2 2006/12/12 16:04:03 mjona Exp $
> -+ *
> -+ * Swedish characters for lcdmod
> -+ *
> -+ * Thanks to Erik Zetterberg <mr.z@linux.se>
> -+ *
> -+ * Description: Adds support for the last three last letters in the
> -+ * swedish alphabet (a/A with ring above, a/A with diaeresis and o/O
> -+ * with diaeresis). And maps the location of where they should be
> -+ * according to the ISO-8859-1 character set to their location in CGRAM.
> -+ *
> -+ */
> -+
> -+static void init_charmap(void)
> -+{
> -+ charmap[ 0xe5 ] = 0;
> -+ charmap[ 0xe4 ] = 1;
> -+ charmap[ 0xf6 ] = 2;
> -+ charmap[ 0xc5 ] = 3;
> -+ charmap[ 0xc4 ] = 4;
> -+ charmap[ 0xd6 ] = 5;
> -+}
> -+
> -+static unsigned char cg0[] = { 0x04, 0x00, 0x0e, 0x01, 0x0f, 0x11, 0x0f, 0x00 };
> -+static unsigned char cg1[] = { 0x0a, 0x00, 0x0e, 0x01, 0x0f, 0x11, 0x0f, 0x00 };
> -+static unsigned char cg2[] = { 0x0a, 0x00, 0x0e, 0x11, 0x11, 0x11, 0x0e, 0x00 };
> -+static unsigned char cg3[] = { 0x04, 0x00, 0x0e, 0x11, 0x1f, 0x11, 0x11, 0x00 };
> -+static unsigned char cg4[] = { 0x0a, 0x00, 0x0e, 0x11, 0x1f, 0x11, 0x11, 0x00 };
> -+static unsigned char cg5[] = { 0x0a, 0x00, 0x0e, 0x11, 0x11, 0x11, 0x0e, 0x00 };
> -+static unsigned char cg6[] = { 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f };
> -+static unsigned char cg7[] = { 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f };
> -diff --git a/drivers/lcd-linux/charmap.h b/drivers/lcd-linux/charmap.h
> -new file mode 100644
> -index 0000000..376b04d
> ---- /dev/null
> -+++ b/drivers/lcd-linux/charmap.h
> -@@ -0,0 +1,79 @@
> -+/* charmap.h
> -+ *
> -+ * $Id: charmap.h,v 1.1.1.1 2005/08/23 13:30:14 mjona Exp $
> -+ *
> -+ * Character mapping for HD44780 devices by Mark Haemmerling <mail@markh.de>.
> -+ *
> -+ * Translates ISO 8859-1 to HD44780 charset.
> -+ * HD44780 charset reference: http://markh.de/hd44780-charset.png
> -+ *
> -+ * Initial table taken from lcd.o Linux kernel driver by
> -+ * Nils Faerber <nilsf@users.sourceforge.net>. Thanks!
> -+ *
> -+ * This file is released under the GNU General Public License. Refer to the
> -+ * COPYING file distributed with this package.
> -+ *
> -+ * Following translations are being performed:
> -+ * - maps umlaut accent characters to the corresponding umlaut characters
> -+ * - maps other accent characters to the characters without accents
> -+ * - maps beta (=ringel-S), micro and Yen
> -+ *
> -+ * Alternative mappings:
> -+ * - #112 ("p") -> #240 (large "p"), orig. mapped -> #112
> -+ * - #113 ("q") -> #241 (large "q"), orig. mapped -> #113
> -+ *
> -+ * HD44780 misses backslash
> -+ *
> -+ */
> -+
> -+static unsigned char charmap[] = {
> -+
> -+/* 0 - 31 */
> -+ 0, 1, 2, 3, 4, 5, 6, 7,
> -+ 8, 9, 10, 11, 12, 13, 14, 15,
> -+ 16, 17, 18, 19, 20, 21, 22, 23,
> -+ 24, 25, 26, 27, 28, 29, 30, 31,
> -+
> -+/* 32 - 63 */
> -+ 32, 33, 34, 35, 36, 37, 38, 39,
> -+ 40, 41, 42, 43, 44, 45, 46, 47,
> -+ 48, 49, 50, 51, 52, 53, 54, 55,
> -+ 56, 57, 58, 59, 60, 61, 62, 63,
> -+
> -+/* 64 - 95 */
> -+ 64, 65, 66, 67, 68, 69, 70, 71,
> -+ 72, 73, 74, 75, 76, 77, 78, 79,
> -+ 80, 81, 82, 83, 84, 85, 86, 87,
> -+ 88, 89, 90, 91, 47, 93, 94, 95,
> -+
> -+/* 96 - 127 */
> -+ 96, 97, 98, 99, 100, 101, 102, 103,
> -+104, 105, 106, 107, 108, 109, 110, 111,
> -+112, 113, 114, 115, 116, 117, 118, 119,
> -+120, 121, 122, 123, 124, 125, 126, 127,
> -+
> -+/* 128 - 159 */
> -+128, 129, 130, 131, 132, 133, 134, 135,
> -+136, 137, 138, 139, 140, 141, 142, 143,
> -+144, 145, 146, 147, 148, 149, 150, 151,
> -+152, 153, 154, 155, 156, 157, 158, 159,
> -+
> -+/* 160 - 191 */
> -+160, 33, 236, 237, 164, 92, 124, 167,
> -+ 34, 169, 170, 171, 172, 173, 174, 175,
> -+223, 177, 178, 179, 39, 249, 247, 165,
> -+ 44, 185, 186, 187, 188, 189, 190, 63,
> -+
> -+/* 192 - 223 */
> -+ 65, 65, 65, 65, 225, 65, 65, 67,
> -+ 69, 69, 69, 69, 73, 73, 73, 73,
> -+ 68, 78, 79, 79, 79, 79, 239, 120,
> -+ 48, 85, 85, 85, 245, 89, 240, 226,
> -+
> -+/* 224 - 255 */
> -+ 97, 97, 97, 97, 225, 97, 97, 99,
> -+101, 101, 101, 101, 105, 105, 105, 105,
> -+111, 110, 111, 111, 111, 111, 239, 253,
> -+ 48, 117, 117, 117, 245, 121, 240, 255
> -+
> -+};
> -diff --git a/drivers/lcd-linux/commands.h b/drivers/lcd-linux/commands.h
> -new file mode 100644
> -index 0000000..6567836
> ---- /dev/null
> -+++ b/drivers/lcd-linux/commands.h
> -@@ -0,0 +1,77 @@
> -+/* commands.h
> -+ *
> -+ * $Id: commands.h,v 1.2 2009/03/09 17:59:22 mjona Exp $
> -+ *
> -+ * LCD-Linux:
> -+ * Driver for HD44780 compatible displays connected to the parallel port.
> -+ *
> -+ * HD44780 commands.
> -+ *
> -+ * Copyright (C) 2004 - 2009 Mattia Jona-Lasinio (mjona@users.sourceforge.net)
> -+ *
> -+ * 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 HD44780_COMMANDS_H
> -+#define HD44780_COMMANDS_H
> -+
> -+/*** HD44780 Command Set ***/
> -+
> -+/* Clear Display*/
> -+#define CLR_DISP 0x01 /* Clear entire display; cursor at row 0, column 0 */
> -+
> -+/* Return Home */
> -+#define RET_HOME 0x02 /* Cursor at row 0, column 0; display content doesn't change */
> -+
> -+/* Entry Mode Set */
> -+#define ENTRY_MODE_SET 0x04
> -+#define DISP_SHIFT_ON (ENTRY_MODE_SET | 0x01) /* Shift display, not cursor after data write */
> -+#define DISP_SHIFT_OFF (ENTRY_MODE_SET | 0x00) /* Shift cursor, not display after data write */
> -+#define CURS_INC (ENTRY_MODE_SET | 0x02) /* Shift on the right after data read/write */
> -+#define CURS_DEC (ENTRY_MODE_SET | 0x00) /* Shift on the left after data read/write */
> -+
> -+/* Display on/off Control */
> -+#define DISP_ONOFF_CNTR 0x08
> -+#define BLINK_ON (DISP_ONOFF_CNTR | 0x01) /* Cursor blinking on */
> -+#define BLINK_OFF (DISP_ONOFF_CNTR | 0x00) /* Cursor blinking off */
> -+#define CURS_ON (DISP_ONOFF_CNTR | 0x02) /* Display Cursor */
> -+#define CURS_OFF (DISP_ONOFF_CNTR | 0x00) /* Hide Cursor */
> -+#define DISP_ON (DISP_ONOFF_CNTR | 0x04) /* Turn on display updating */
> -+#define DISP_OFF (DISP_ONOFF_CNTR | 0x00) /* Freeze display content */
> -+
> -+/* Cursor or Display Shift */
> -+#define CURS_DISP_SHIFT 0x10
> -+#define SHIFT_RIGHT (CURS_DISP_SHIFT | 0x04) /* Shift on the right */
> -+#define SHIFT_LEFT (CURS_DISP_SHIFT | 0x00) /* Shift on the left */
> -+#define SHIFT_DISP (CURS_DISP_SHIFT | 0x08) /* Shift display */
> -+#define SHIFT_CURS (CURS_DISP_SHIFT | 0x00) /* Shift cursor */
> -+
> -+/* Function Set */
> -+#define FUNC_SET 0x20
> -+#define FONT_5X10 (FUNC_SET | 0x04) /* Select 5x10 dots font */
> -+#define FONT_5X8 (FUNC_SET | 0x00) /* Select 5x8 dots font */
> -+#define DISP_2_LINES (FUNC_SET | 0x08) /* Select 2 lines display (only 5x8 font allowed) */
> -+#define DISP_1_LINE (FUNC_SET | 0x00) /* Select 1 line display */
> -+#define BUS_8_BITS (FUNC_SET | 0x10) /* Set 8 data bits */
> -+#define BUS_4_BITS (FUNC_SET | 0x00) /* Set 4 data bits */
> -+
> -+/* Set CGRAM Address */
> -+#define CGRAM_IO 0x40 /* Base CGRAM address */
> -+
> -+/* Set DDRAM Address */
> -+#define DDRAM_IO 0x80 /* Base DDRAM address */
> -+
> -+#endif /* commands included */
> -diff --git a/drivers/lcd-linux/config.h b/drivers/lcd-linux/config.h
> -new file mode 100644
> -index 0000000..face191
> ---- /dev/null
> -+++ b/drivers/lcd-linux/config.h
> -@@ -0,0 +1,73 @@
> -+/* config.h
> -+ *
> -+ * $Id: config.h,v 1.16 2009/09/27 21:27:03 mjona Exp $
> -+ *
> -+ * Configure file for LCD-Linux. Here you must specify your hardware setup and
> -+ * timings constants. The default values will probably be right for you.
> -+ *
> -+ * Copyright (C) 2005 - 2009 Mattia Jona-Lasinio (mjona@users.sourceforge.net)
> -+ *
> -+ * 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
> -+ *
> -+ *
> -+ */
> -+
> -+/* Setup the default user defined characters in CGRAM */
> -+#include "cgram/default.h"
> -+/* #include "cgram/swedish.h" */
> -+/* #include "cgram/cgram.h" */
> -+
> -+/* Don't modify the default timing constants
> -+ * unless you know what you are doing.
> -+ */
> -+
> -+/* In case of a 4 bit bus, indicate your
> -+ * wiring configuration for the data bits
> -+ *
> -+ * 0 -> D3, D2, D1, D0
> -+ * 1 -> D4, D3, D2, D1
> -+ * 2 -> D5, D4, D3, D2
> -+ * 3 -> D6, D5, D4, D3
> -+ * 4 -> D7, D6, D5, D4
> -+ */
> -+#define SETUP 4
> -+
> -+#define HIGH_NIBBLE_WRITE(x) (((x) >> (4-SETUP)) & (0x0f << SETUP))
> -+#define LOW_NIBBLE_WRITE(x) (((x) << SETUP) & (0x0f << SETUP))
> -+#define HIGH_NIBBLE_READ(x) (((x) & (0x0f << SETUP)) << (4-SETUP))
> -+#define LOW_NIBBLE_READ(x) (((x) & (0x0f << SETUP)) >> SETUP)
> -+
> -+/* Execution times (in microseconds) */
> -+#define T_READ 60 /* Read execution time (min 43 us) */
> -+#define T_WRITE 60 /* Write execution time (min 43 us) */
> -+#define T_BF 4 /* Busy flag polling time (min 1 us) */
> -+
> -+/* Timings in nanoseconds */
> -+#define T_AS 200 /* Address set-up time (min 140 ns) */
> -+#define T_EH 500 /* Enable high time (min 450 ns) */
> -+#define T_EL 800 /* Enable low time (min 500 ns) */
> -+
> -+/* Various constants */
> -+#define DFLT_NUM_CNTR 1 /* Default number of controllers the display has */
> -+#define DFLT_CNTR_ROWS 4 /* Default number of rows per controller */
> -+#define DFLT_CNTR_COLS 20 /* Default number of columns the display has */
> -+#define DFLT_VS_ROWS 25 /* Default number of rows for the virtual screen */
> -+#define DFLT_VS_COLS 80 /* Default number of columns for the virtual screen */
> -+#define DFLT_TABSTOP 4 /* Default length of tabs */
> -+#define DFLT_FLAGS HD44780_CHECK_BF /* Default flags: check BF and 8 bit bus */
> -+
> -+#define MAX_NUM_CNTR 7 /* We support up to 7 controllers */
> -+#define MAX_CNTR_ROWS 4 /* The HD44780 supports up to 4 lines as a fake 2 lines mode */
> -+#define MAX_CNTR_COLS 80 /* The HD44780 supports up to 80 characters (1*80; 2*40; etc) */
> -diff --git a/drivers/lcd-linux/hd44780.c b/drivers/lcd-linux/hd44780.c
> -new file mode 100644
> -index 0000000..0b1af6b
> ---- /dev/null
> -+++ b/drivers/lcd-linux/hd44780.c
> -@@ -0,0 +1,854 @@
> -+/* hd44780.c
> -+ *
> -+ * $Id: hd44780.c,v 1.181 2010/03/03 14:56:22 mjona Exp $
> -+ *
> -+ * LCD-Linux:
> -+ * Driver for HD44780 compatible displays connected to the parallel port.
> -+ *
> -+ * Copyright (C) 2005 - 2009 Mattia Jona-Lasinio (mjona@users.sourceforge.net)
> -+ * Based on the code for Sim.One Hardware by Nuccio Raciti (raciti.nuccio@gmail.com)
> -+ * Modified for ts72xx hardware by Petr Stetiar (ynezz@true.cz)
> -+ * (Only 8-bit mode supported for now.)
> -+ *
> -+ * 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
> -+ *
> -+ */
> -+
> -+#ifdef CONFIG_PROC_FS
> -+#define USE_PROC
> -+#else
> -+#undef USE_PROC
> -+#endif
> -+
> -+#include <linux/bitops.h>
> -+#include <linux/kernel.h>
> -+#include <linux/module.h>
> -+
> -+#include <linux/delay.h>
> -+#include <linux/fs.h>
> -+
> -+#include <asm/uaccess.h>
> -+#include <asm/gpio.h>
> -+#include <asm/io.h>
> -+#include <linux/init.h>
> -+#include <linux/ioport.h>
> -+
> -+#ifdef USE_PROC
> -+#include <linux/proc_fs.h>
> -+#endif
> -+
> -+#define LCD_LINUX_MAIN
> -+#include <linux/hd44780.h>
> -+
> -+#include "charmap.h"
> -+#include "commands.h"
> -+#include "config.h"
> -+
> -+#define LCD_EN EP93XX_GPIO_LINE_H(3)
> -+#define LCD_RS EP93XX_GPIO_LINE_H(4)
> -+#define LCD_WR EP93XX_GPIO_LINE_H(5)
> -+#define LCD_DATA0 EP93XX_GPIO_LINE_A(0)
> -+#define LCD_DATA1 EP93XX_GPIO_LINE_A(1)
> -+#define LCD_DATA2 EP93XX_GPIO_LINE_A(2)
> -+#define LCD_DATA3 EP93XX_GPIO_LINE_A(3)
> -+#define LCD_DATA4 EP93XX_GPIO_LINE_A(4)
> -+#define LCD_DATA5 EP93XX_GPIO_LINE_A(5)
> -+#define LCD_DATA6 EP93XX_GPIO_LINE_A(6)
> -+#define LCD_DATA7 EP93XX_GPIO_LINE_A(7)
> -+
> -+static struct gpio lcd_gpios[] = {
> -+ { LCD_EN, GPIOF_OUT_INIT_LOW, "LCD enable" },
> -+ { LCD_RS, GPIOF_OUT_INIT_LOW, "LCD data" },
> -+ { LCD_WR, GPIOF_OUT_INIT_LOW, "LCD r/w" },
> -+ { LCD_DATA0, GPIOF_OUT_INIT_LOW, "LCD data0" },
> -+ { LCD_DATA1, GPIOF_OUT_INIT_LOW, "LCD data1" },
> -+ { LCD_DATA2, GPIOF_OUT_INIT_LOW, "LCD data2" },
> -+ { LCD_DATA3, GPIOF_OUT_INIT_LOW, "LCD data3" },
> -+ { LCD_DATA4, GPIOF_OUT_INIT_LOW, "LCD data4" },
> -+ { LCD_DATA5, GPIOF_OUT_INIT_LOW, "LCD data5" },
> -+ { LCD_DATA6, GPIOF_OUT_INIT_LOW, "LCD data6" },
> -+ { LCD_DATA7, GPIOF_OUT_INIT_LOW, "LCD data7" },
> -+};
> -+
> -+/** Function prototypes **/
> -+static void read_display(unsigned char *byte, unsigned char bitmask);
> -+static void write_display(unsigned char byte, unsigned char bitmask);
> -+
> -+/* Initialization */
> -+static int hd44780_validate_driver(void);
> -+static int hd44780_init_port(void);
> -+static int hd44780_cleanup_port(void);
> -+static int hd44780_init_display(void);
> -+static int hd44780_cleanup_display(void);
> -+
> -+/* Write */
> -+static void hd44780_address_mode(int);
> -+static void hd44780_clear_display(void);
> -+static void hd44780_write_char(unsigned int, unsigned short);
> -+static void hd44780_write_cgram_char(unsigned char, unsigned char *);
> -+
> -+/* Read */
> -+static void check_bf(unsigned char);
> -+static void hd44780_read_char(unsigned int, unsigned short *);
> -+static void hd44780_read_cgram_char(unsigned char, unsigned char *);
> -+
> -+/* Input handling */
> -+static int hd44780_handle_custom_char(unsigned int);
> -+static int hd44780_handle_custom_ioctl(unsigned int, unsigned long, unsigned int);
> -+
> -+/* Proc operations */
> -+#ifdef USE_PROC
> -+static void create_proc_entries(void);
> -+static void remove_proc_entries(void);
> -+#endif
> -+
> -+/* hd44780_flags */
> -+#define _CHECK_BF 0 /* Do busy-flag checking */
> -+#define _4BITS_BUS 1 /* The bus is 4 bits long */
> -+#define _5X10_FONT 2 /* Use 5x10 font */
> -+#define CURSOR_BLINK 3 /* Make the cursor blinking */
> -+#define SHOW_CURSOR 4 /* Make the cursor visible */
> -+#define DISPLAY_ON 5 /* Display status: on or off */
> -+#define INC_ADDR 6 /* Increment address after data read/write */
> -+#define BACKLIGHT 7 /* Display backlight: on or off */
> -+#define CGRAM_STATE 9 /* Controller status bitmask (bits 9->15): DDRAM or CGRAM access */
> -+
> -+/* hd44780 access */
> -+#define ACCESS_TO_READ 0
> -+#define ACCESS_TO_WRITE 1
> -+#define ACCESS_TO_DATA 2
> -+
> -+#define ESC_MASK 0x00ff0000
> -+#define PROC_MASK 0x0f000000
> -+
> -+#define SET_STATE(state, mask) (hd44780_flags = (hd44780_flags & ~(mask)) | ((state) & (mask)))
> -+#define SET_ESC_STATE(state) SET_STATE((state) << 16, ESC_MASK)
> -+#define SET_PROC_LEVEL(level) SET_STATE((level) << 24, PROC_MASK)
> -+#define ESC_STATE ((hd44780_flags & ESC_MASK) >> 16)
> -+#define PROC_LEVEL ((hd44780_flags & PROC_MASK) >> 24)
> -+
> -+/* globals */
> -+static unsigned int disp_size; /* Display size (rows*columns) */
> -+static unsigned int disp_offset[1]; /* Physical cursor position on the display */
> -+static unsigned long hd44780_flags; /* Driver flags for internal use only */
> -+
> -+static struct lcd_parameters par = {
> -+ .name = HD44780_STRING,
> -+ .minor = HD44780_MINOR,
> -+ .flags = DFLT_FLAGS,
> -+ .tabstop = DFLT_TABSTOP,
> -+ .num_cntr = 1,
> -+ .cntr_rows = DFLT_CNTR_ROWS,
> -+ .cntr_cols = DFLT_CNTR_COLS,
> -+ .vs_rows = DFLT_VS_ROWS,
> -+ .vs_cols = DFLT_VS_COLS,
> -+ .cgram_chars = 8,
> -+ .cgram_bytes = 8,
> -+ .cgram_char0 = 0,
> -+};
> -+/* End of globals */
> -+
> -+#ifdef MODULE
> -+#include <linux/device.h>
> -+MODULE_ALIAS_CHARDEV(LCD_MAJOR, HD44780_MINOR);
> -+#include <linux/kmod.h>
> -+
> -+static unsigned short flags = DFLT_FLAGS;
> -+static unsigned short tabstop = DFLT_TABSTOP;
> -+static unsigned short cntr_rows = DFLT_CNTR_ROWS;
> -+static unsigned short cntr_cols = DFLT_CNTR_COLS;
> -+static unsigned short vs_rows = DFLT_VS_ROWS;
> -+static unsigned short vs_cols = DFLT_VS_COLS;
> -+static unsigned short minor = HD44780_MINOR;
> -+
> -+MODULE_DESCRIPTION("LCD ts72xx driver for HD44780 compatible controllers.");
> -+MODULE_AUTHOR("Petr Stetiar <ynezz@true.cz>");
> -+#ifdef MODULE_LICENSE
> -+MODULE_LICENSE("GPL");
> -+#endif
> -+module_param(flags, ushort, 0444);
> -+module_param(cntr_rows, ushort, 0444);
> -+module_param(cntr_cols, ushort, 0444);
> -+module_param(vs_rows, ushort, 0444);
> -+module_param(vs_cols, ushort, 0444);
> -+module_param(tabstop, ushort, 0444);
> -+module_param(minor, ushort, 0444);
> -+MODULE_PARM_DESC(flags, "Various flags (see Documentation)");
> -+MODULE_PARM_DESC(cntr_rows, "Number of rows per controller on the LCD: 1, 2, 4 (default: " string(DFLT_CNTR_ROWS) ")");
> -+MODULE_PARM_DESC(cntr_cols, "Number of columns on the LCD (default: " string(DFLT_CNTR_COLS) ", max: " string(MAX_CNTR_COLS) ")");
> -+MODULE_PARM_DESC(vs_rows, "Number of rows of the virtual screen (default: " string(DFLT_VS_ROWS) ")");
> -+MODULE_PARM_DESC(vs_cols, "Number of columns of the virtual screen (default: " string(DFLT_VS_COLS) ")");
> -+MODULE_PARM_DESC(tabstop, "Tab character length (default: " string(DFLT_TABSTOP) ")");
> -+MODULE_PARM_DESC(minor, "Assigned minor number (default: " string(HD44780_MINOR) ")");
> -+#else
> -+
> -+/*
> -+ * Parse boot command line
> -+ *
> -+ * hd44780=cntr_rows,cntr_cols,vs_rows,vs_cols,flags,minor,tabstop
> -+ */
> -+static int __init hd44780_boot_init(char *cmdline)
> -+{
> -+ char *str = cmdline;
> -+ int idx = 0;
> -+ unsigned short *args[] = {
> -+ &par.cntr_rows,
> -+ &par.cntr_cols,
> -+ &par.vs_rows,
> -+ &par.vs_cols,
> -+ (ushort *) &par.flags,
> -+ &par.num_cntr,
> -+ &par.minor,
> -+ &par.tabstop,
> -+ };
> -+
> -+ while (*cmdline && idx < (sizeof(args)/sizeof(unsigned short *))) {
> -+ switch (*str) {
> -+ case ',':
> -+ *str++ = 0;
> -+ case 0:
> -+ if (strlen(cmdline))
> -+ *args[idx] = simple_strtoul(cmdline, NULL, 0);
> -+ ++idx;
> -+ cmdline = str;
> -+ break;
> -+ default:
> -+ ++str;
> -+ break;
> -+ }
> -+ }
> -+
> -+ return (1);
> -+}
> -+
> -+__setup("hd44780=", hd44780_boot_init);
> -+#endif /* MODULE */
> -+
> -+/* Macros for iterator handling */
> -+static inline unsigned int iterator_inc_(unsigned int iterator, const unsigned int module)
> -+{
> -+ return ((++iterator)%module);
> -+}
> -+
> -+static inline unsigned int iterator_dec_(unsigned int iterator, const unsigned int module)
> -+{
> -+ return (iterator ? --iterator : module-1);
> -+}
> -+
> -+#define iterator_inc(iterator, module) (iterator = iterator_inc_(iterator, module))
> -+#define iterator_dec(iterator, module) (iterator = iterator_dec_(iterator, module))
> -+
> -+static inline void set_lines(unsigned char bitmask)
> -+{
> -+ gpio_set_value(LCD_EN, 0); /* Disable */
> -+
> -+ if (bitmask & ACCESS_TO_WRITE ) {
> -+ gpio_direction_output(LCD_DATA0, 0);
> -+ gpio_direction_output(LCD_DATA1, 0);
> -+ gpio_direction_output(LCD_DATA2, 0);
> -+ gpio_direction_output(LCD_DATA3, 0);
> -+ gpio_direction_output(LCD_DATA4, 0);
> -+ gpio_direction_output(LCD_DATA5, 0);
> -+ gpio_direction_output(LCD_DATA6, 0);
> -+ gpio_direction_output(LCD_DATA7, 0);
> -+ gpio_set_value(LCD_WR, 0); /* Write */
> -+ } else {
> -+ gpio_direction_input(LCD_DATA0);
> -+ gpio_direction_input(LCD_DATA1);
> -+ gpio_direction_input(LCD_DATA2);
> -+ gpio_direction_input(LCD_DATA3);
> -+ gpio_direction_input(LCD_DATA4);
> -+ gpio_direction_input(LCD_DATA5);
> -+ gpio_direction_input(LCD_DATA6);
> -+ gpio_direction_input(LCD_DATA7);
> -+ gpio_set_value(LCD_WR, 1); /* Read */
> -+ }
> -+
> -+ if (bitmask & ACCESS_TO_DATA )
> -+ gpio_set_value(LCD_RS, 1); /* Data */
> -+ else
> -+ gpio_set_value(LCD_RS, 0); /* Cmds*/
> -+}
> -+
> -+static inline void read_display(unsigned char *byte, unsigned char bitmask)
> -+{
> -+ unsigned char ret;
> -+ if (bitmask)
> -+ check_bf(bitmask);
> -+
> -+ set_lines(bitmask);
> -+
> -+ ndelay(T_AS); /* Address set-up time */
> -+ gpio_set_value(LCD_EN, 1); /* Enable */
> -+ ndelay(T_EH); /* Enable high time */
> -+
> -+ ret = (gpio_get_value(LCD_DATA0) << 0);
> -+ ret |= (gpio_get_value(LCD_DATA1) << 1);
> -+ ret |= (gpio_get_value(LCD_DATA2) << 2);
> -+ ret |= (gpio_get_value(LCD_DATA3) << 3);
> -+ ret |= (gpio_get_value(LCD_DATA4) << 4);
> -+ ret |= (gpio_get_value(LCD_DATA5) << 5);
> -+ ret |= (gpio_get_value(LCD_DATA6) << 6);
> -+ ret |= (gpio_get_value(LCD_DATA7) << 7);
> -+
> -+ gpio_set_value(LCD_EN, 0); /* Disable */
> -+ ndelay(T_EL); /* Enable low time */
> -+ *byte = ret;
> -+}
> -+
> -+/* Low level write to the display */
> -+static inline void write_display(unsigned char data, unsigned char bitmask)
> -+{
> -+ check_bf(bitmask);
> -+ set_lines(bitmask);
> -+
> -+ gpio_set_value(LCD_DATA0, (data >> 0) & 1);
> -+ gpio_set_value(LCD_DATA1, (data >> 1) & 1);
> -+ gpio_set_value(LCD_DATA2, (data >> 2) & 1);
> -+ gpio_set_value(LCD_DATA3, (data >> 3) & 1);
> -+ gpio_set_value(LCD_DATA4, (data >> 4) & 1);
> -+ gpio_set_value(LCD_DATA5, (data >> 5) & 1);
> -+ gpio_set_value(LCD_DATA6, (data >> 6) & 1);
> -+ gpio_set_value(LCD_DATA7, (data >> 7) & 1);
> -+
> -+ ndelay(T_AS); /* Address set-up time */
> -+ gpio_set_value(LCD_EN, 1);
> -+ ndelay(T_EH); /* Enable high time */
> -+
> -+ gpio_set_value(LCD_EN, 0); /* Disable */
> -+ ndelay(T_EL); /* Enable low time */
> -+}
> -+
> -+/* Read Address Counter AC from the display */
> -+static unsigned char read_ac(unsigned char bitmask)
> -+{
> -+ unsigned char byte;
> -+
> -+ read_display(&byte, bitmask);
> -+
> -+ return (byte);
> -+}
> -+
> -+static void check_bf(unsigned char bitmask)
> -+{
> -+ unsigned int timeout = 20;
> -+ static unsigned char do_check_bf = 5;
> -+
> -+ gpio_set_value(LCD_EN, 0); /* Disable */
> -+
> -+ gpio_direction_input(LCD_DATA0);
> -+ gpio_direction_input(LCD_DATA1);
> -+ gpio_direction_input(LCD_DATA2);
> -+ gpio_direction_input(LCD_DATA3);
> -+ gpio_direction_input(LCD_DATA4);
> -+ gpio_direction_input(LCD_DATA5);
> -+ gpio_direction_input(LCD_DATA6);
> -+ gpio_direction_input(LCD_DATA7);
> -+
> -+ gpio_set_value(LCD_WR, 1); /* Read */
> -+ gpio_set_value(LCD_RS, 0); /* Instru */
> -+
> -+ ndelay(T_AS); /* Address set-up time */
> -+ gpio_set_value(LCD_EN, 1); /* Enable */
> -+ ndelay(T_EH); /* Enable high time */
> -+
> -+ do {
> -+ udelay(T_BF);
> -+ } while (gpio_get_value(LCD_DATA7) && --timeout);
> -+
> -+ if (!timeout) {
> -+ if (!--do_check_bf) {
> -+ printk(KERN_NOTICE "hd44780 error: is LCD connected?\n");
> -+ }
> -+ }
> -+
> -+ gpio_set_value(LCD_EN, 0); /* Disable */
> -+ ndelay(T_EL); /* Enable low time */
> -+}
> -+
> -+/* Send commands to the display */
> -+static void write_command(unsigned char command)
> -+{
> -+ write_display(command, ACCESS_TO_WRITE);
> -+
> -+ if (command <= 0x03)
> -+ mdelay(2);
> -+}
> -+
> -+static inline void set_cursor(unsigned int offset)
> -+{
> -+ unsigned int disp_number = offset/disp_size;
> -+ unsigned int local_offset = offset%disp_size;
> -+
> -+ if (disp_offset[disp_number] != local_offset || test_bit(CGRAM_STATE+disp_number, &hd44780_flags)) {
> -+ unsigned int disp_row = local_offset/par.cntr_cols;
> -+ unsigned int disp_column = local_offset%par.cntr_cols;
> -+
> -+ write_command(DDRAM_IO | ((disp_row%2)*0x40) | (((disp_row >= 2)*par.cntr_cols)+disp_column));
> -+ clear_bit(CGRAM_STATE+disp_number, &hd44780_flags);
> -+ disp_offset[disp_number] = local_offset;
> -+ }
> -+}
> -+
> -+/* HD44780 DDRAM addresses are consecutive only when
> -+ * the cursor moves on the same row of the display.
> -+ * Every time the row of the cursor changes we invalidate
> -+ * the cursor position to force hardware cursor repositioning.
> -+ */
> -+static inline void mov_cursor(unsigned int disp_number)
> -+{
> -+ if (test_bit(INC_ADDR, &hd44780_flags)) {
> -+ iterator_inc(disp_offset[disp_number], disp_size);
> -+ if (disp_offset[disp_number]%par.cntr_cols == 0)
> -+ disp_offset[disp_number] = disp_size;
> -+ } else {
> -+ iterator_dec(disp_offset[disp_number], disp_size);
> -+ if (disp_offset[disp_number]%par.cntr_cols == par.cntr_cols-1)
> -+ disp_offset[disp_number] = disp_size;
> -+ }
> -+}
> -+
> -+static struct lcd_driver hd44780 = {
> -+ .read_char = hd44780_read_char,
> -+ .read_cgram_char = hd44780_read_cgram_char,
> -+ .write_char = hd44780_write_char,
> -+ .write_cgram_char = hd44780_write_cgram_char,
> -+ .address_mode = hd44780_address_mode,
> -+ .clear_display = hd44780_clear_display,
> -+ .validate_driver = hd44780_validate_driver,
> -+ .init_display = hd44780_init_display,
> -+ .cleanup_display = hd44780_cleanup_display,
> -+ .init_port = hd44780_init_port,
> -+ .cleanup_port = hd44780_cleanup_port,
> -+ .handle_custom_char = hd44780_handle_custom_char,
> -+ .handle_custom_ioctl = hd44780_handle_custom_ioctl,
> -+
> -+ .charmap = charmap,
> -+};
> -+
> -+static void hd44780_read_char(unsigned int offset, unsigned short *data)
> -+{
> -+ unsigned int disp_number = offset/disp_size;
> -+ unsigned char tmp;
> -+
> -+ set_cursor(offset);
> -+ read_display(&tmp, ACCESS_TO_DATA);
> -+ *data = tmp;
> -+ mov_cursor(disp_number);
> -+}
> -+
> -+static void hd44780_read_cgram_char(unsigned char index, unsigned char *pixels)
> -+{
> -+ unsigned int i;
> -+
> -+ write_command(CGRAM_IO | (index << 3));
> -+ set_bit(CGRAM_STATE+0, &hd44780_flags);
> -+
> -+ for (i = 0; i < 8; ++i) {
> -+ read_display(pixels+i, ACCESS_TO_DATA);
> -+ pixels[i] &= 0x1f;
> -+ }
> -+
> -+}
> -+
> -+static void hd44780_write_char(unsigned int offset, unsigned short data)
> -+{
> -+ unsigned int disp_number = offset/disp_size;
> -+
> -+ set_cursor(offset);
> -+ write_display(data & 0xff, ACCESS_TO_WRITE | ACCESS_TO_DATA);
> -+ mov_cursor(disp_number);
> -+}
> -+
> -+static void hd44780_write_cgram_char(unsigned char index, unsigned char *pixels)
> -+{
> -+ unsigned int i;
> -+
> -+ /* Move address pointer to index in CGRAM */
> -+ write_command(CGRAM_IO | (index << 3));
> -+ set_bit(CGRAM_STATE+0, &hd44780_flags);
> -+
> -+ for (i = 0; i < 8; ++i) {
> -+ pixels[i] &= 0x1f;
> -+ write_display(pixels[i], ACCESS_TO_WRITE | ACCESS_TO_DATA );
> -+ }
> -+}
> -+
> -+/* Increment/decrement address mode after a data read/write */
> -+static void hd44780_address_mode(int mode)
> -+{
> -+ if (mode > 0 && ! test_bit(INC_ADDR, &hd44780_flags)) {
> -+ write_command(CURS_INC | DISP_SHIFT_OFF);
> -+ set_bit(INC_ADDR, &hd44780_flags);
> -+ } else if (mode < 0 && test_bit(INC_ADDR, &hd44780_flags)) {
> -+ write_command(CURS_DEC | DISP_SHIFT_OFF);
> -+ clear_bit(INC_ADDR, &hd44780_flags);
> -+ }
> -+}
> -+
> -+static void hd44780_clear_display(void)
> -+{
> -+ write_command(CLR_DISP);
> -+ if (! test_bit(INC_ADDR, &hd44780_flags))
> -+ write_command(CURS_DEC | DISP_SHIFT_OFF);
> -+ memset(disp_offset, 0, sizeof(disp_offset));
> -+}
> -+
> -+static int hd44780_validate_driver(void)
> -+{
> -+ if (par.cntr_rows != 1 && par.cntr_rows != 2 && par.cntr_rows != 4)
> -+ par.cntr_rows = DFLT_CNTR_ROWS;
> -+
> -+ if (par.cntr_rows != 1)
> -+ par.flags &= ~HD44780_5X10_FONT;
> -+
> -+ if (! par.cntr_cols || par.cntr_cols > MAX_CNTR_COLS/par.cntr_rows)
> -+ par.cntr_cols = MAX_CNTR_COLS/par.cntr_rows;
> -+
> -+ disp_size = par.cntr_rows*par.cntr_cols;
> -+
> -+ /* These parameters depend on the hardware and cannot be changed */
> -+ par.cgram_chars = 8;
> -+ par.cgram_bytes = 8;
> -+ par.cgram_char0 = 0;
> -+
> -+ return (0);
> -+}
> -+
> -+/* Send init commands to the display */
> -+static void write_init_command(void)
> -+{
> -+ unsigned char command;
> -+ command = BUS_8_BITS;
> -+ command |= ((par.cntr_rows == 1) ? DISP_1_LINE : DISP_2_LINES);
> -+ command |= (test_bit(_5X10_FONT, &hd44780_flags) ? FONT_5X10 : FONT_5X8);
> -+
> -+ write_display(command, ACCESS_TO_WRITE);
> -+ mdelay(20); /* Wait more than 4.1 ms */
> -+
> -+ write_display(command, ACCESS_TO_WRITE);
> -+ udelay(200); /* Wait more than 100 us */
> -+
> -+ write_display(command, ACCESS_TO_WRITE);
> -+ udelay(200); /* Wait more than 100 us */
> -+
> -+ write_command(command);
> -+}
> -+
> -+static int hd44780_init_display(void)
> -+{
> -+ if (par.flags & HD44780_CHECK_BF)
> -+ set_bit(_CHECK_BF, &hd44780_flags);
> -+ else
> -+ clear_bit(_CHECK_BF, &hd44780_flags);
> -+
> -+ if (par.flags & HD44780_4BITS_BUS)
> -+ set_bit(_4BITS_BUS, &hd44780_flags);
> -+ else
> -+ clear_bit(_4BITS_BUS, &hd44780_flags);
> -+
> -+ if (par.flags & HD44780_5X10_FONT)
> -+ set_bit(_5X10_FONT, &hd44780_flags);
> -+ else
> -+ clear_bit(_5X10_FONT, &hd44780_flags);
> -+
> -+ write_init_command();
> -+ hd44780_address_mode(1);
> -+ hd44780_clear_display();
> -+ write_command(DISP_ON | CURS_OFF | BLINK_OFF);
> -+ set_bit(DISPLAY_ON, &hd44780_flags);
> -+ clear_bit(SHOW_CURSOR, &hd44780_flags);
> -+ clear_bit(CURSOR_BLINK, &hd44780_flags);
> -+
> -+ /* Set the CGRAM to default values */
> -+ hd44780_write_cgram_char(0, cg0);
> -+ hd44780_write_cgram_char(1, cg1);
> -+ hd44780_write_cgram_char(2, cg2);
> -+ hd44780_write_cgram_char(3, cg3);
> -+ hd44780_write_cgram_char(4, cg4);
> -+ hd44780_write_cgram_char(5, cg5);
> -+ hd44780_write_cgram_char(6, cg6);
> -+ hd44780_write_cgram_char(7, cg7);
> -+ init_charmap();
> -+
> -+ return (0);
> -+}
> -+
> -+static int hd44780_cleanup_display(void)
> -+{
> -+ hd44780_clear_display();
> -+
> -+ return (0);
> -+}
> -+
> -+static int hd44780_init_port(void)
> -+{
> -+ int err = gpio_request_array(lcd_gpios, ARRAY_SIZE(lcd_gpios));
> -+ if (err) {
> -+ printk(KERN_ERR "hd44780: error while requesting GPIO pins\n");
> -+ return 1;
> -+ }
> -+
> -+ return 0;
> -+}
> -+
> -+static int hd44780_cleanup_port(void)
> -+{
> -+ gpio_direction_input(LCD_RS);
> -+ gpio_direction_input(LCD_EN);
> -+ gpio_direction_input(LCD_DATA0);
> -+ gpio_direction_input(LCD_DATA1);
> -+ gpio_direction_input(LCD_DATA2);
> -+ gpio_direction_input(LCD_DATA3);
> -+ gpio_direction_input(LCD_DATA4);
> -+ gpio_direction_input(LCD_DATA5);
> -+ gpio_direction_input(LCD_DATA6);
> -+ gpio_direction_input(LCD_DATA7);
> -+
> -+ gpio_free_array(lcd_gpios, ARRAY_SIZE(lcd_gpios));
> -+
> -+ return 0;
> -+}
> -+
> -+static void display_attr(unsigned char input)
> -+{
> -+ unsigned char command;
> -+
> -+ switch (ESC_STATE) {
> -+ case 'a': /* Turn on/off the display cursor */
> -+ if (input == '1')
> -+ set_bit(SHOW_CURSOR, &hd44780_flags);
> -+ else if (input == '0')
> -+ clear_bit(SHOW_CURSOR, &hd44780_flags);
> -+ break;
> -+ case 'b': /* Turn on/off the display cursor blinking */
> -+ if (input == '1')
> -+ set_bit(CURSOR_BLINK, &hd44780_flags);
> -+ else if (input == '0')
> -+ clear_bit(CURSOR_BLINK, &hd44780_flags);
> -+ break;
> -+ case 'h': /* Turn on/off the display */
> -+ if (input == '1')
> -+ set_bit(DISPLAY_ON, &hd44780_flags);
> -+ else if (input == '0')
> -+ clear_bit(DISPLAY_ON, &hd44780_flags);
> -+ break;
> -+ }
> -+
> -+ command = (test_bit(DISPLAY_ON, &hd44780_flags) ? DISP_ON : DISP_OFF);
> -+ command |= (test_bit(SHOW_CURSOR, &hd44780_flags) ? CURS_ON : CURS_OFF);
> -+ command |= (test_bit(CURSOR_BLINK, &hd44780_flags) ? BLINK_ON : BLINK_OFF);
> -+
> -+ if (ESC_STATE == 'h')
> -+ write_command(command);
> -+}
> -+
> -+static int hd44780_handle_custom_char(unsigned int _input)
> -+{
> -+ unsigned char input = _input & 0xff;
> -+
> -+ if (_input & (~0xff)) {
> -+ switch (ESC_STATE) {
> -+ case 'a': /* Turn on/off the display cursor */
> -+ case 'b': /* Turn on/off the display cursor blinking */
> -+ case 'h': /* Turn on/off the the display */
> -+ display_attr(input);
> -+ return (0);
> -+ case 'l': /* Turn on/off the backlight */
> -+ if (input == '1')
> -+ set_bit(BACKLIGHT, &hd44780_flags);
> -+ else if (input == '0')
> -+ clear_bit(BACKLIGHT, &hd44780_flags);
> -+ read_ac(ACCESS_TO_READ);
> -+ return (0);
> -+ }
> -+ }
> -+
> -+ switch (input) {
> -+ case 'a': /* Turn on/off the display cursor */
> -+ case 'b': /* Turn on/off the display cursor blinking */
> -+ case 'h': /* Turn on/off the display */
> -+ case 'l': /* Turn on/off the backlight */
> -+ SET_ESC_STATE(input);
> -+ return (1);
> -+ case 'd': /* Shift display cursor Right */
> -+ write_command(SHIFT_CURS | SHIFT_RIGHT);
> -+ return (0);
> -+ case 'e': /* Shift display cursor Left */
> -+ write_command(SHIFT_CURS | SHIFT_LEFT);
> -+ return (0);
> -+ case 'f': /* Shift display Right */
> -+ write_command(SHIFT_DISP | SHIFT_RIGHT);
> -+ return (0);
> -+ case 'g': /* Shift display Left */
> -+ write_command(SHIFT_DISP | SHIFT_LEFT);
> -+ return (0);
> -+ }
> -+
> -+ return (-1);
> -+}
> -+
> -+static int hd44780_handle_custom_ioctl(unsigned int num, unsigned long arg, unsigned int user_space)
> -+{
> -+ unsigned char *buffer = (unsigned char *)arg;
> -+
> -+ if (num != HD44780_READ_AC)
> -+ return (-ENOIOCTLCMD);
> -+
> -+ if (user_space)
> -+ put_user(read_ac(ACCESS_TO_READ), buffer);
> -+ else
> -+ buffer[0] = read_ac(ACCESS_TO_READ);
> -+
> -+ return (0);
> -+}
> -+
> -+#ifdef USE_PROC
> -+static int hd44780_proc_status(char *buffer, char **start, off_t offset, int size, int *eof, void *data)
> -+{
> -+ char *temp = buffer;
> -+
> -+ /* Print display configuration */
> -+ temp += sprintf(temp,
> -+ "Interface:\t%u bits\n"
> -+ "Display rows:\t%d\n"
> -+ "Display cols:\t%d\n"
> -+ "Screen rows:\t%d\n"
> -+ "Screen cols:\t%d\n"
> -+ "Read:\t\t%sabled\n"
> -+ "Busy flag chk:\t%sabled\n"
> -+ "Assigned minor:\t%u\n",
> -+ (test_bit(_4BITS_BUS, &hd44780_flags) ? 4 : 8),
> -+ par.cntr_rows, par.cntr_cols,
> -+ par.vs_rows, par.vs_cols,
> -+ (hd44780.read_char ? "En" : "Dis"),
> -+ (test_bit(_CHECK_BF, &hd44780_flags) ? "En" : "Dis"),
> -+ par.minor);
> -+
> -+ return (temp-buffer);
> -+}
> -+
> -+static int hd44780_proc_cgram(char *buffer, char **start, off_t offset, int size, int *eof, void *data)
> -+{
> -+ char *temp = buffer;
> -+ unsigned int i;
> -+
> -+ temp += sprintf(temp, "static void init_charmap(void)\n{\n"
> -+ "\t/*\n"
> -+ "\t * charmap[char mapped to cg0] = 0;\n"
> -+ "\t * charmap[char mapped to cg1] = 1;\n"
> -+ "\t * charmap[char mapped to cg2] = 2;\n"
> -+ "\t * charmap[char mapped to cg3] = 3;\n"
> -+ "\t * charmap[char mapped to cg4] = 4;\n"
> -+ "\t * charmap[char mapped to cg5] = 5;\n"
> -+ "\t * charmap[char mapped to cg6] = 6;\n"
> -+ "\t * charmap[char mapped to cg7] = 7;\n"
> -+ "\t */\n"
> -+ "}\n\n");
> -+
> -+ for (i = 0; i < 8; ++i) {
> -+ unsigned int j;
> -+ unsigned char cgram_buffer[8];
> -+
> -+ temp += sprintf(temp, "static unsigned char cg%u[] = { ", i);
> -+ hd44780_read_cgram_char(i, cgram_buffer);
> -+ for (j = 0; j < 8; ++j)
> -+ temp += sprintf(temp, "0x%.2x%s", cgram_buffer[j], (j == 7 ? " };\n" : ", "));
> -+ }
> -+
> -+ return (temp-buffer);
> -+}
> -+
> -+static void create_proc_entries(void)
> -+{
> -+ SET_PROC_LEVEL(0);
> -+ if (create_proc_read_entry("status", 0, hd44780.driver_proc_root, hd44780_proc_status, NULL) == NULL) {
> -+ printk(KERN_ERR "hd44780: cannot create /proc/lcd/%s/status\n", par.name);
> -+ return;
> -+ }
> -+ SET_PROC_LEVEL(1);
> -+ if (create_proc_read_entry("cgram.h", 0, hd44780.driver_proc_root, hd44780_proc_cgram, NULL) == NULL) {
> -+ printk(KERN_ERR "hd44780: cannot create /proc/lcd/%s/cgram.h\n", par.name);
> -+ return;
> -+ }
> -+ SET_PROC_LEVEL(2);
> -+}
> -+
> -+static void remove_proc_entries(void)
> -+{
> -+ switch (PROC_LEVEL) {
> -+ case 2:
> -+ remove_proc_entry("cgram.h", hd44780.driver_proc_root);
> -+ case 1:
> -+ remove_proc_entry("status", hd44780.driver_proc_root);
> -+ }
> -+ SET_PROC_LEVEL(0);
> -+}
> -+#endif
> -+
> -+/* Initialization */
> -+static int __init hd44780_init_module(void)
> -+{
> -+ int ret;
> -+
> -+#ifdef MODULE
> -+ if ((ret = request_module("lcd-linux"))) {
> -+ printk(KERN_ERR "hd44780: request_module() returned %d\n", ret);
> -+ if (ret < 0) {
> -+ if (ret != -ENOSYS) {
> -+ printk(KERN_ERR "hd44780: failure while loading module lcd-linux\n");
> -+ return (ret);
> -+ }
> -+ printk(KERN_ERR "hd44780: your kernel does not have kmod or kerneld support;\n");
> -+ printk(KERN_ERR "hd44780: remember to load the lcd-linux module before\n");
> -+ printk(KERN_ERR "hd44780: loading the hd44780 module\n");
> -+ }
> -+ }
> -+
> -+ if (flags != DFLT_FLAGS) par.flags = flags;
> -+ if (tabstop != DFLT_TABSTOP) par.tabstop = tabstop;
> -+ if (cntr_rows != DFLT_CNTR_ROWS) par.cntr_rows = cntr_rows;
> -+ if (cntr_cols != DFLT_CNTR_COLS) par.cntr_cols = cntr_cols;
> -+ if (vs_rows != DFLT_VS_ROWS) par.vs_rows = vs_rows;
> -+ if (vs_cols != DFLT_VS_COLS) par.vs_cols = vs_cols;
> -+ if (minor != HD44780_MINOR) par.minor = minor;
> -+#endif
> -+
> -+ lcd_driver_setup(&hd44780);
> -+ if ((ret = lcd_register_driver(&hd44780, &par)))
> -+ return (ret);
> -+
> -+#ifdef USE_PROC
> -+ if (hd44780.driver_proc_root)
> -+ create_proc_entries();
> -+#endif
> -+
> -+ printk(KERN_INFO "hd44780: ts72xx driver loaded\n" );
> -+
> -+ return (0);
> -+}
> -+
> -+static void __exit hd44780_cleanup_module(void)
> -+{
> -+#ifdef USE_PROC
> -+ if (hd44780.driver_proc_root)
> -+ remove_proc_entries();
> -+#endif
> -+
> -+ lcd_unregister_driver(&hd44780, &par);
> -+}
> -+
> -+module_init(hd44780_init_module)
> -+module_exit(hd44780_cleanup_module)
> -diff --git a/drivers/lcd-linux/lcd-linux.c b/drivers/lcd-linux/lcd-linux.c
> -new file mode 100644
> -index 0000000..8f9bc38
> ---- /dev/null
> -+++ b/drivers/lcd-linux/lcd-linux.c
> -@@ -0,0 +1,3023 @@
> -+/* lcd-linux.c
> -+ *
> -+ * $Id: lcd-linux.c,v 1.308 2010/03/03 14:56:22 mjona Exp $
> -+ *
> -+ * Software layer to drive LCD displays under Linux.
> -+ *
> -+ * Copyright (C) 2005 - 2009 Mattia Jona-Lasinio (mjona@users.sourceforge.net)
> -+ *
> -+ * 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/version.h>
> -+
> -+#ifndef KERNEL_VERSION
> -+#define KERNEL_VERSION(a, b, c) (((a) << 16) + ((b) << 8) + (c))
> -+#endif
> -+
> -+#ifndef LINUX_VERSION_CODE
> -+#error - LINUX_VERSION_CODE undefined in 'linux/version.h'
> -+#endif
> -+
> -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 33)
> -+#include <generated/autoconf.h>
> -+#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0)
> -+#include <linux/autoconf.h>
> -+#else
> -+#include <linux/config.h>
> -+#endif
> -+
> -+#ifdef CONFIG_PROC_FS
> -+#define USE_PROC
> -+#else
> -+#undef USE_PROC
> -+#endif
> -+
> -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26)
> -+#include <linux/semaphore.h>
> -+#else
> -+#include <asm/semaphore.h>
> -+#endif
> -+
> -+#include <linux/bitops.h>
> -+
> -+#include <linux/kernel.h>
> -+#include <linux/module.h>
> -+#include <linux/sched.h>
> -+
> -+#include <linux/fs.h>
> -+
> -+#include <asm/uaccess.h>
> -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0)
> -+#include <linux/device.h>
> -+#endif
> -+#include <linux/init.h>
> -+#include <linux/list.h>
> -+#include <linux/slab.h>
> -+#include <linux/selection.h>
> -+#include <linux/vmalloc.h>
> -+
> -+#ifdef USE_PROC
> -+#include <linux/proc_fs.h>
> -+#endif
> -+
> -+#define LCD_LINUX_MAIN
> -+#include <linux/lcd-linux.h>
> -+
> -+static inline void __set_br(unsigned long *x, unsigned long val, unsigned long start, unsigned long len)
> -+{
> -+ unsigned long mask = (1 << len)-1;
> -+
> -+ if (val <= mask) {
> -+ mask <<= start;
> -+ val <<= start;
> -+ *x = (*x & ~mask) | val;
> -+ }
> -+}
> -+
> -+static inline unsigned long __get_br(unsigned long x, unsigned long start, unsigned long len)
> -+{
> -+ return ((x >> start) & ((1 << len)-1));
> -+}
> -+
> -+/*** struct_flags ***/
> -+
> -+/* internal flags: bits [0:15] of struct_flags (16 flags allowed) */
> -+#define NEED_WRAP 0 /* Next char will trigger a newline */
> -+#define DECIM 1 /* Insert mode */
> -+#define DECOM 2 /* Row origin of cursor: absolute or relative to scrolling region */
> -+#define DECAWM 3 /* Autowrap */
> -+#define DECSCNM 4 /* Inverted screen */
> -+#define CRLF 5 /* Follow lf, vt, ff, with a cr */
> -+#define INC_CURS_POS 6 /* Increment cursor position after data read/write */
> -+#define QUES 7 /* CSI Esc sequence contains a question mark */
> -+#define USER_SPACE 8 /* If set, the buffer pointed by arg in do_lcd_ioctl() is
> -+ * assumed to be in user space otherwise it is in kernel space */
> -+#define NULL_CHARMAP 9 /* The driver doesn't provide a charmap so the
> -+ * lcd-linux layer provides one*/
> -+#define CAN_DO_COLOR 10 /* The display is color capable */
> -+#define WITH_ATTR 11 /* If set, the void * buffer in do_lcd_read/write() contains
> -+ * attributes and therefore is an unsigned short * otherwise it
> -+ * is an unsigned char *
> -+ */
> -+
> -+/* input states: bits [24:27] of struct_flags (16 states allowed) */
> -+#define NORMAL 0 /* Normal mode */
> -+#define RAW 1 /* Raw mode (console emulation disabled) */
> -+#define SYN 2 /* Synchronous Idle mode */
> -+#define ESC 3 /* Escape mode */
> -+#define CSI 4 /* CSI escape mode */
> -+#define ESC_G0 5 /* G0 character set */
> -+#define ESC_G1 6 /* G1 character set */
> -+#define ESC_HASH 7 /* ESC # escape sequence */
> -+#define ESC_PERCENT 8 /* ESC % escape sequence */
> -+#define ARG 9 /* Waiting for arguments for the lcd-linux layer */
> -+#define ARG_DRIVER 10 /* Waiting for arguments for the display driver */
> -+
> -+#define SET_ESC_STATE(p, x) __set_br(&(p)->struct_flags, x, 16, 8)
> -+#define SET_INPUT_STATE(p, x) __set_br(&(p)->struct_flags, x, 24, 4)
> -+#define SET_INIT_LEVEL(p, x) __set_br(&(p)->struct_flags, x, 28, 2)
> -+#define SET_PROC_LEVEL(p, x) __set_br(&(p)->struct_flags, x, 30, 2)
> -+#define ESC_STATE(p) __get_br((p)->struct_flags, 16, 8)
> -+#define INPUT_STATE(p) __get_br((p)->struct_flags, 24, 4)
> -+#define INIT_LEVEL(p) __get_br((p)->struct_flags, 28, 2)
> -+#define PROC_LEVEL(p) __get_br((p)->struct_flags, 30, 2)
> -+
> -+/*** attributes ***/
> -+#define I_MASK 0x03 /* Intensity (0 = low, 1 = normal, 2 = bright) */
> -+#define ULINE 0x04 /* Underlined text */
> -+#define REVERSE 0x08 /* Reversed video text */
> -+#define BLINK 0x80 /* Blinking text */
> -+
> -+/*** Color attributes ***/
> -+#define FG_COLOR 0x07 /* Foreground color mask */
> -+#define FG_BRIGHT 0x08 /* Foreground bright color */
> -+#define FG_MASK (FG_BRIGHT | FG_COLOR) /* Foreground mask */
> -+#define BG_COLOR 0x70 /* Background color mask */
> -+#define BG_BRIGHT 0x80 /* Background bright color */
> -+#define BG_MASK (BG_BRIGHT | BG_COLOR) /* Background mask */
> -+
> -+#define NPAR 16 /* Max number of parameters in CSI escape sequence */
> -+#define FLIP_BUF_SIZE (1 << 6) /* Flip buffer size (64 bytes) MUST be a power of 2 */
> -+
> -+struct lcd_struct {
> -+ struct list_head lcd_list; /* Doubly linked list */
> -+ struct semaphore lcd_sem; /* Locks this structure */
> -+ struct lcd_driver *driver; /* The driver associated to this struct */
> -+ struct lcd_parameters *par; /* The parameters associated to this struct */
> -+ unsigned long struct_flags; /* Flags for internal use only */
> -+ unsigned int refcount; /* Number of references to this struct */
> -+
> -+ unsigned short *display; /* The display buffer */
> -+
> -+ unsigned short *fb; /* The virtual screen framebuffer */
> -+ unsigned int fb_size; /* Size of the framebuffer */
> -+ unsigned int frame_base; /* Offset of row 0, column 0 of a frame in fb */
> -+ unsigned int frame_size; /* Size of the frame */
> -+
> -+ unsigned int row; /* Current row in virtual screen */
> -+ unsigned int col; /* Current column in virtual screen */
> -+ unsigned int s_offset; /* Saved cursor position in virtual screen */
> -+
> -+ unsigned int top; /* Top scroll row in virtual screen */
> -+ unsigned int bot; /* Bottom scroll row in virtual screen */
> -+
> -+ int esc_args; /* Number of arguments for a normal escape sequence */
> -+ unsigned int csi_args[NPAR]; /* CSI parameters */
> -+ unsigned int index; /* Index in csi_args and counter for cgram characters generation */
> -+ unsigned char cgram_index; /* Index of the cgram character to be created */
> -+ unsigned char *cgram_buffer; /* Buffer for cgram operations in this driver */
> -+
> -+ unsigned short erase_char; /* Character to be used when erasing */
> -+ unsigned char attr; /* Current attributes */
> -+ unsigned char color; /* Color for normal intensity mode */
> -+ unsigned char s_color; /* Saved color for normal intensity mode */
> -+ unsigned char defcolor; /* Default color for normal intensity mode */
> -+ unsigned char ulcolor; /* Color for underline mode */
> -+ unsigned char halfcolor; /* Color for low intensity mode */
> -+ unsigned char attributes; /* Packed attributes */
> -+ unsigned char s_attributes; /* Saved packed attributes */
> -+
> -+ unsigned char *s_charmap; /* Saved character map for this driver */
> -+ unsigned char *flip_buf; /* High speed flip buffer */
> -+};
> -+
> -+/** Function prototypes **/
> -+
> -+/* Init/Cleanup the driver */
> -+static int init_driver(struct lcd_struct *);
> -+static int cleanup_driver(struct lcd_struct *);
> -+
> -+/* Read from/Write to the driver */
> -+static void read_data(struct lcd_struct *, unsigned short *);
> -+static void read_cgram(struct lcd_struct *, unsigned char, unsigned char *);
> -+static void write_data(struct lcd_struct *, unsigned short);
> -+static void write_cgram(struct lcd_struct *, unsigned char, unsigned char *);
> -+
> -+/* Input handlers */
> -+static void cr(struct lcd_struct *);
> -+static void lf(struct lcd_struct *);
> -+static void control_char(struct lcd_struct *, unsigned char);
> -+static void handle_csi(struct lcd_struct *, unsigned char);
> -+static int handle_custom_esc(struct lcd_struct *, unsigned int);
> -+static int handle_esc(struct lcd_struct *, unsigned char);
> -+static void handle_input(struct lcd_struct *, unsigned short);
> -+
> -+/* Low level file operations */
> -+static ssize_t do_lcd_read(struct lcd_struct *, void *, size_t);
> -+static ssize_t do_lcd_write(struct lcd_struct *, const void *, size_t);
> -+static int do_lcd_open(struct lcd_struct *);
> -+static int do_lcd_release(struct lcd_struct *);
> -+static int do_lcd_ioctl(struct lcd_struct *, unsigned int, unsigned long);
> -+
> -+/* Proc functions */
> -+#ifdef USE_PROC
> -+static void create_driver_proc_entries(struct lcd_struct *);
> -+static void remove_driver_proc_entries(struct lcd_struct *);
> -+#endif
> -+
> -+/* globals */
> -+static unsigned int major = LCD_MAJOR; /* Major number for LCD-Linux device */
> -+static unsigned short minors = LCD_MINORS; /* Minor numbers allocated for LCD-Linux */
> -+static LIST_HEAD(lcd_drivers); /* Registered lcd drivers */
> -+static struct semaphore drivers_sem; /* Locks the lcd_drivers list */
> -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 13)
> -+static struct class *lcd_linux_class;
> -+#endif
> -+#ifdef USE_PROC
> -+static struct proc_dir_entry *lcd_proc_root;
> -+#endif
> -+/* End of globals */
> -+
> -+#ifdef MODULE
> -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0)
> -+#include <linux/device.h>
> -+MODULE_ALIAS_CHARDEV_MAJOR(LCD_MAJOR);
> -+#endif
> -+MODULE_DESCRIPTION("Software layer to drive LCD displays under Linux.");
> -+MODULE_AUTHOR("Mattia Jona-Lasinio <mjona@users.sourceforge.net>");
> -+#ifdef MODULE_LICENSE
> -+MODULE_LICENSE("GPL");
> -+#endif
> -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0)
> -+module_param(minors, ushort, 0444);
> -+#else
> -+MODULE_PARM(minors, "h");
> -+#endif
> -+MODULE_PARM_DESC(minors, "Minor numbers allocated for LCD-Linux (default: " string(LCD_MINORS) ")");
> -+#else
> -+
> -+/*
> -+ * Parse boot command line
> -+ *
> -+ * lcd=minors
> -+ */
> -+static int __init lcd_linux_boot_init(char *cmdline)
> -+{
> -+ unsigned short args;
> -+
> -+ if ((args = simple_strtoul(cmdline, NULL, 0)))
> -+ minors = args;
> -+
> -+ return (1);
> -+}
> -+
> -+__setup("lcd=", lcd_linux_boot_init);
> -+#endif /* MODULE */
> -+
> -+/* Macros for iterator handling */
> -+static inline unsigned int iterator_inc_(unsigned int iterator, const unsigned int module)
> -+{
> -+ return ((++iterator)%module);
> -+}
> -+
> -+static inline unsigned int iterator_dec_(unsigned int iterator, const unsigned int module)
> -+{
> -+ return (iterator ? --iterator : module-1);
> -+}
> -+
> -+#define iterator_inc(iterator, module) (iterator = iterator_inc_(iterator, module))
> -+#define iterator_dec(iterator, module) (iterator = iterator_dec_(iterator, module))
> -+
> -+/* Uncomment the following two lines
> -+ * for non-atomic set_bit and clear_bit
> -+ */
> -+//#define set_bit __set_bit
> -+//#define clear_bit __clear_bit
> -+
> -+/************************************
> -+ * Low level routines and utilities *
> -+ ************************************/
> -+/*
> -+ * Set whether the address counter should be incremented
> -+ * or decremented after a Read/Write
> -+ */
> -+static void address_mode(struct lcd_struct *p, int mode)
> -+{
> -+ struct lcd_driver *driver = p->driver;
> -+
> -+ if (mode > 0 && ! test_bit(INC_CURS_POS, &p->struct_flags)) {
> -+ if (driver->address_mode)
> -+ driver->address_mode(mode);
> -+ set_bit(INC_CURS_POS, &p->struct_flags);
> -+ } else if (mode < 0 && test_bit(INC_CURS_POS, &p->struct_flags)) {
> -+ if (driver->address_mode)
> -+ driver->address_mode(mode);
> -+ clear_bit(INC_CURS_POS, &p->struct_flags);
> -+ }
> -+}
> -+
> -+/* WARNING!! This function returns an int because if iterator is not
> -+ * within the visible area of the frame it returns -1
> -+ */
> -+static inline int vs_to_frame_(struct lcd_struct *p, unsigned int iterator)
> -+{
> -+ unsigned int vs_rows = p->par->vs_rows;
> -+ unsigned int vs_cols = p->par->vs_cols;
> -+ unsigned int row = iterator/vs_cols;
> -+ unsigned int col = iterator%vs_cols;
> -+ unsigned int frame_base_row = p->frame_base/vs_cols;
> -+ unsigned int frame_base_col = p->frame_base%vs_cols;
> -+ unsigned int frame_rows = p->par->cntr_rows*p->par->num_cntr;
> -+ unsigned int frame_cols = p->par->cntr_cols;
> -+
> -+ if (vs_rows == frame_rows && vs_cols == frame_cols)
> -+ return (iterator);
> -+
> -+ if (row < frame_base_row || row >= frame_base_row+frame_rows)
> -+ return (-1);
> -+ if (col < frame_base_col || col >= frame_base_col+frame_cols)
> -+ return (-1);
> -+
> -+ return ((row-frame_base_row)*frame_cols+(col-frame_base_col));
> -+}
> -+
> -+/* Given 'iterator' in vs, returns the offset in vs corresponding to the nearest
> -+ * visible offset in vs, or returns 'iterator' if it is already visible.
> -+ */
> -+static unsigned int round_vs_(struct lcd_struct *p, unsigned int iterator)
> -+{
> -+ unsigned int vs_rows = p->par->vs_rows;
> -+ unsigned int vs_cols = p->par->vs_cols;
> -+ unsigned int row = iterator/vs_cols;
> -+ unsigned int col = iterator%vs_cols;
> -+ unsigned int frame_base_row = p->frame_base/vs_cols;
> -+ unsigned int frame_base_col = p->frame_base%vs_cols;
> -+ unsigned int frame_rows = p->par->cntr_rows*p->par->num_cntr;
> -+ unsigned int frame_cols = p->par->cntr_cols;
> -+
> -+ if (vs_rows == frame_rows && vs_cols == frame_cols)
> -+ return (iterator);
> -+
> -+ if (row < frame_base_row)
> -+ row = frame_base_row;
> -+ else if (row >= frame_base_row+frame_rows)
> -+ row = frame_base_row+(frame_rows-1);
> -+
> -+ if (col < frame_base_col)
> -+ col = frame_base_col;
> -+ else if (col >= frame_base_col+frame_cols)
> -+ col = frame_base_col+(frame_cols-1);
> -+
> -+ return ((row*vs_cols)+col);
> -+}
> -+
> -+#define round_vs(p, iterator) (iterator = round_vs_(p, iterator))
> -+
> -+/*
> -+ * Sync the frame area starting at offset s, ending at offset e with fb content.
> -+ */
> -+static void redraw_screen(struct lcd_struct *p, unsigned int s, unsigned int e)
> -+{
> -+ unsigned int len;
> -+ unsigned int row = p->row, col = p->col;
> -+ unsigned int inc_set = test_bit(INC_CURS_POS, &p->struct_flags);
> -+ unsigned int frame_cols = p->par->cntr_cols;
> -+ unsigned int vs_cols = p->par->vs_cols;
> -+ unsigned long flags;
> -+
> -+ if (s >= p->fb_size || e >= p->fb_size || e < s || e < p->frame_base)
> -+ return;
> -+
> -+ round_vs(p, s);
> -+ round_vs(p, e);
> -+
> -+ len = 1+e-s;
> -+
> -+ if (! inc_set)
> -+ s = e;
> -+
> -+ p->row = s/vs_cols;
> -+ p->col = s%vs_cols;
> -+
> -+ flags = p->struct_flags;
> -+ clear_bit(NEED_WRAP, &p->struct_flags);
> -+ clear_bit(DECIM, &p->struct_flags);
> -+ set_bit(DECAWM, &p->struct_flags);
> -+ SET_INPUT_STATE(p, RAW);
> -+ if (inc_set)
> -+ while (len--)
> -+ if (vs_to_frame_(p, (p->row*vs_cols)+p->col) < 0) {
> -+ s += vs_cols-frame_cols;
> -+ len -= vs_cols-frame_cols-1;
> -+ p->row = s/vs_cols;
> -+ p->col = s%vs_cols;
> -+ } else {
> -+ write_data(p, p->fb[s++]);
> -+ if (test_bit(NEED_WRAP, &p->struct_flags)) {
> -+ cr(p);
> -+ lf(p);
> -+ }
> -+ }
> -+ else
> -+ while (len--)
> -+ if (vs_to_frame_(p, (p->row*vs_cols)+p->col) < 0) {
> -+ s -= vs_cols-frame_cols;
> -+ len -= vs_cols-frame_cols-1;
> -+ p->row = s/vs_cols;
> -+ p->col = s%vs_cols;
> -+ } else {
> -+ write_data(p, p->fb[s--]);
> -+ if (test_bit(NEED_WRAP, &p->struct_flags)) {
> -+ cr(p);
> -+ lf(p);
> -+ }
> -+ }
> -+ p->struct_flags = flags;
> -+
> -+ p->row = row; p->col = col;
> -+}
> -+
> -+static int show_cursor(struct lcd_struct *p)
> -+{
> -+ unsigned int vs_rows = p->par->vs_rows;
> -+ unsigned int vs_cols = p->par->vs_cols;
> -+ unsigned int frame_base, frame_base_row, frame_base_col;
> -+ unsigned int frame_rows = p->par->cntr_rows*p->par->num_cntr;
> -+ unsigned int frame_cols = p->par->cntr_cols;
> -+ unsigned int tmp = frame_cols/2;
> -+
> -+ if (vs_rows == frame_rows && vs_cols == frame_cols)
> -+ return (0);
> -+
> -+ if (test_bit(INC_CURS_POS, &p->struct_flags)) {
> -+ /* cursor always on the lowest row of the display */
> -+ frame_base_row = 0;
> -+ frame_base_col = 0;
> -+ if (p->row >= frame_rows)
> -+ frame_base_row = p->row-(frame_rows-1);
> -+ if (p->col >= frame_cols) {
> -+ frame_base_col = p->col-(frame_cols-1);
> -+ if (tmp) {
> -+ tmp = (tmp-(frame_base_col%tmp))%tmp;
> -+ if (frame_base_col+tmp <= vs_cols-frame_cols)
> -+ frame_base_col += tmp;
> -+ }
> -+ }
> -+ } else {
> -+ /* cursor always on the uppermost row of the display */
> -+ frame_base_row = vs_rows-frame_rows;
> -+ frame_base_col = vs_cols-frame_cols;
> -+ if (p->row < vs_rows-frame_rows)
> -+ frame_base_row = p->row;
> -+ if (p->col < vs_cols-frame_cols) {
> -+ frame_base_col = p->col;
> -+ if (tmp) {
> -+ tmp = frame_base_col%tmp;
> -+ if (frame_base_col >= tmp)
> -+ frame_base_col -= tmp;
> -+ }
> -+ }
> -+ }
> -+
> -+ frame_base = p->frame_base;
> -+ p->frame_base = (frame_base_row*vs_cols)+frame_base_col;
> -+
> -+ return (frame_base != p->frame_base);
> -+}
> -+
> -+/*
> -+ * Move the visible screen area at user's wish
> -+ */
> -+static void browse_screen(struct lcd_struct *p, unsigned char dir)
> -+{
> -+ unsigned int vs_rows = p->par->vs_rows;
> -+ unsigned int vs_cols = p->par->vs_cols;
> -+ unsigned int frame_base_row = p->frame_base/vs_cols;
> -+ unsigned int frame_base_col = p->frame_base%vs_cols;
> -+ unsigned int frame_rows = p->par->cntr_rows*p->par->num_cntr;
> -+ unsigned int frame_cols = p->par->cntr_cols;
> -+
> -+ switch (dir) {
> -+ case '1': /* Up */
> -+ if (! frame_base_row)
> -+ return;
> -+ --frame_base_row;
> -+ break;
> -+ case '2': /* Down */
> -+ if (frame_base_row >= vs_rows-frame_rows)
> -+ return;
> -+ ++frame_base_row;
> -+ break;
> -+ case '3': /* Left */
> -+ if (! frame_base_col)
> -+ return;
> -+ --frame_base_col;
> -+ break;
> -+ case '4': /* Right */
> -+ if (frame_base_col >= vs_cols-frame_cols)
> -+ return;
> -+ ++frame_base_col;
> -+ break;
> -+ default:
> -+ return;
> -+ }
> -+
> -+ p->frame_base = (frame_base_row*vs_cols)+frame_base_col;
> -+ redraw_screen(p, 0, p->fb_size-1);
> -+}
> -+
> -+static inline void __memset_short(unsigned short *buf, unsigned short c, unsigned int len)
> -+{
> -+ while (len--)
> -+ *buf++ = c;
> -+}
> -+
> -+/*
> -+ * A memset implementation writing to LCD instead of memory locations.
> -+ */
> -+static void lcd_memset(struct lcd_struct *p, unsigned int d, unsigned short c, unsigned int len)
> -+{
> -+ unsigned int inc_set = test_bit(INC_CURS_POS, &p->struct_flags);
> -+
> -+ if (! len || d >= p->fb_size)
> -+ return;
> -+
> -+ if (inc_set && d+len > p->fb_size)
> -+ len = p->fb_size-d;
> -+ else if (! inc_set && len > d+1)
> -+ len = d+1;
> -+
> -+ if (! inc_set)
> -+ d -= len-1;
> -+ __memset_short(p->fb+d, c, len);
> -+
> -+ if (show_cursor(p))
> -+ redraw_screen(p, 0, p->fb_size-1);
> -+ else
> -+ redraw_screen(p, d, d+(len-1));
> -+}
> -+
> -+static inline void __memcpy_short(unsigned short *d, unsigned short *s, unsigned int len, int dir)
> -+{
> -+ if (dir > 0)
> -+ while (len--)
> -+ *d++ = *s++;
> -+ else
> -+ while (len--)
> -+ *d-- = *s--;
> -+}
> -+
> -+/*
> -+ * A memmove implementation writing to LCD instead of memory locations.
> -+ * Copy is done in a non destructive way. Display regions may overlap.
> -+ */
> -+static void lcd_memmove(struct lcd_struct *p, unsigned int d, unsigned int s, unsigned int len)
> -+{
> -+ if (! len || d == s || d >= p->fb_size || s >= p->fb_size)
> -+ return;
> -+
> -+ if (d < s) {
> -+ if (test_bit(INC_CURS_POS, &p->struct_flags)) {
> -+ if (s+len > p->fb_size)
> -+ len = p->fb_size-s;
> -+ } else {
> -+ if (len > d+1)
> -+ len = d+1;
> -+ d -= len-1;
> -+ s -= len-1;
> -+ }
> -+ __memcpy_short(p->fb+d, p->fb+s, len, 1);
> -+ if (show_cursor(p))
> -+ redraw_screen(p, 0, p->fb_size-1);
> -+ else
> -+ redraw_screen(p, d, d+(len-1));
> -+ } else {
> -+ if (test_bit(INC_CURS_POS, &p->struct_flags)) {
> -+ if (d+len > p->fb_size)
> -+ len = p->fb_size-d;
> -+ d += len-1;
> -+ s += len-1;
> -+ } else {
> -+ if (len > s+1)
> -+ len = s+1;
> -+ }
> -+ __memcpy_short(p->fb+d, p->fb+s, len, -1);
> -+ if (show_cursor(p))
> -+ redraw_screen(p, 0, p->fb_size-1);
> -+ else
> -+ redraw_screen(p, d-(len-1), d);
> -+ }
> -+}
> -+
> -+static void scrup(struct lcd_struct *p, unsigned int t, unsigned int b, unsigned int nr)
> -+{
> -+ unsigned int vs_rows = p->par->vs_rows;
> -+ unsigned int vs_cols = p->par->vs_cols;
> -+ unsigned int d, s;
> -+
> -+ if (t+nr >= b)
> -+ nr = b-t-1;
> -+ if (b > vs_rows || t >= b || nr < 1)
> -+ return;
> -+ d = t*vs_cols;
> -+ s = (t+nr)*vs_cols;
> -+ if (test_bit(INC_CURS_POS, &p->struct_flags)) {
> -+ lcd_memmove(p, d, s, (b-t-nr)*vs_cols);
> -+ lcd_memset(p, d+(b-t-nr)*vs_cols, p->erase_char, nr*vs_cols);
> -+ } else {
> -+ lcd_memmove(p, d+(b-t-nr)*vs_cols-1, s+(b-t-nr)*vs_cols-1, (b-t-nr)*vs_cols);
> -+ lcd_memset(p, d+(b-t)*vs_cols-1, p->erase_char, nr*vs_cols);
> -+ }
> -+}
> -+
> -+static void scrdown(struct lcd_struct *p, unsigned int t, unsigned int b, unsigned int nr)
> -+{
> -+ unsigned int vs_rows = p->par->vs_rows;
> -+ unsigned int vs_cols = p->par->vs_cols;
> -+ unsigned int d, s;
> -+
> -+ if (t+nr >= b)
> -+ nr = b-t-1;
> -+ if (b > vs_rows || t >= b || nr < 1)
> -+ return;
> -+ s = t*vs_cols;
> -+ d = (t+nr)*vs_cols;
> -+ if (test_bit(INC_CURS_POS, &p->struct_flags)) {
> -+ lcd_memmove(p, d, s, (b-t-nr)*vs_cols);
> -+ lcd_memset(p, s, p->erase_char, nr*vs_cols);
> -+ } else {
> -+ lcd_memmove(p, d+(b-t-nr)*vs_cols-1, s+(b-t-nr)*vs_cols-1, (b-t-nr)*vs_cols);
> -+ lcd_memset(p, s+nr*vs_cols-1, p->erase_char, nr*vs_cols);
> -+ }
> -+}
> -+
> -+static void lcd_insert_char(struct lcd_struct *p, unsigned int nr)
> -+{
> -+ unsigned int vs_cols = p->par->vs_cols;
> -+ unsigned int pos = (p->row*vs_cols)+p->col;
> -+
> -+ clear_bit(NEED_WRAP, &p->struct_flags);
> -+ if (test_bit(INC_CURS_POS, &p->struct_flags))
> -+ lcd_memmove(p, pos+nr, pos, vs_cols-p->col-nr);
> -+ else
> -+ lcd_memmove(p, pos-nr, pos, p->col-(nr-1));
> -+ lcd_memset(p, pos, p->erase_char, nr);
> -+}
> -+
> -+static void lcd_delete_char(struct lcd_struct *p, unsigned int nr)
> -+{
> -+ unsigned int vs_cols = p->par->vs_cols;
> -+ unsigned int pos = (p->row*vs_cols)+p->col;
> -+
> -+ clear_bit(NEED_WRAP, &p->struct_flags);
> -+ if (test_bit(INC_CURS_POS, &p->struct_flags)) {
> -+ lcd_memmove(p, pos, pos+nr, vs_cols-(p->col+nr));
> -+ lcd_memset(p, (p->row+1)*vs_cols-nr, p->erase_char, nr);
> -+ } else {
> -+ lcd_memmove(p, pos, pos-nr, p->col-(nr-1));
> -+ lcd_memset(p, (p->row*vs_cols)+(nr-1), p->erase_char, nr);
> -+ }
> -+}
> -+
> -+
> -+
> -+
> -+
> -+/******************************************************************************
> -+ ************************* VT 102 Emulation *************************
> -+ ******************************************************************************/
> -+
> -+/**********************
> -+ * Control characters *
> -+ **********************/
> -+static void bs(struct lcd_struct *p)
> -+{
> -+ clear_bit(NEED_WRAP, &p->struct_flags);
> -+ if (test_bit(INC_CURS_POS, &p->struct_flags)) {
> -+ if (p->col)
> -+ --p->col;
> -+ } else {
> -+ if (p->col+1 < p->par->vs_cols)
> -+ ++p->col;
> -+ }
> -+}
> -+
> -+static void cr(struct lcd_struct *p)
> -+{
> -+ clear_bit(NEED_WRAP, &p->struct_flags);
> -+ p->col = (test_bit(INC_CURS_POS, &p->struct_flags) ? 0 : p->par->vs_cols-1);
> -+}
> -+
> -+static void lf(struct lcd_struct *p)
> -+{
> -+ clear_bit(NEED_WRAP, &p->struct_flags);
> -+ if (test_bit(INC_CURS_POS, &p->struct_flags)) {
> -+ if (p->row+1 < p->bot)
> -+ ++p->row;
> -+ else if (INPUT_STATE(p) != RAW) {
> -+ show_cursor(p);
> -+ scrup(p, p->top, p->bot, 1);
> -+ }
> -+ } else {
> -+ if (p->row > p->top)
> -+ --p->row;
> -+ else if (INPUT_STATE(p) != RAW) {
> -+ show_cursor(p);
> -+ scrdown(p, p->top, p->bot, 1);
> -+ }
> -+ }
> -+}
> -+
> -+static void ri(struct lcd_struct *p)
> -+{
> -+ clear_bit(NEED_WRAP, &p->struct_flags);
> -+ if (test_bit(INC_CURS_POS, &p->struct_flags)) {
> -+ if (p->row > p->top)
> -+ --p->row;
> -+ else {
> -+ show_cursor(p);
> -+ scrdown(p, p->top, p->bot, 1);
> -+ }
> -+ } else {
> -+ if (p->row+1 < p->bot)
> -+ ++p->row;
> -+ else {
> -+ show_cursor(p);
> -+ scrup(p, p->top, p->bot, 1);
> -+ }
> -+ }
> -+}
> -+
> -+static void ff(struct lcd_struct *p)
> -+{
> -+ unsigned int vs_rows = p->par->vs_rows;
> -+ unsigned int vs_cols = p->par->vs_cols;
> -+
> -+ clear_bit(NEED_WRAP, &p->struct_flags);
> -+ if (p->driver->clear_display) {
> -+ p->driver->clear_display();
> -+ __memset_short(p->fb, p->erase_char, p->fb_size);
> -+ __memset_short(p->display, p->erase_char, p->frame_size);
> -+ p->frame_base = 0;
> -+ } else if (test_bit(INC_CURS_POS, &p->struct_flags))
> -+ lcd_memset(p, 0, p->erase_char, p->fb_size);
> -+ else
> -+ lcd_memset(p, p->fb_size-1, p->erase_char, p->fb_size);
> -+
> -+ if (test_bit(INC_CURS_POS, &p->struct_flags))
> -+ p->row = p->col = 0;
> -+ else {
> -+ p->row = vs_rows-1;
> -+ p->col = vs_cols-1;
> -+ }
> -+}
> -+
> -+static void tab(struct lcd_struct *p)
> -+{
> -+ struct lcd_parameters *par = p->par;
> -+ unsigned int i, vs_cols = par->vs_cols;
> -+
> -+ clear_bit(NEED_WRAP, &p->struct_flags);
> -+
> -+ if (! par->tabstop)
> -+ return;
> -+
> -+ if (test_bit(INC_CURS_POS, &p->struct_flags)) {
> -+ i = par->tabstop-(p->col%par->tabstop);
> -+ if (p->col+i < vs_cols)
> -+ p->col += i;
> -+ } else {
> -+ i = p->col%par->tabstop;
> -+ i = (i == 0 ? par->tabstop : i);
> -+ if (p->col >= i)
> -+ p->col -= i;
> -+ }
> -+}
> -+
> -+/*
> -+ * Control character handler.
> -+ */
> -+static void control_char(struct lcd_struct *p, unsigned char val)
> -+{
> -+ switch (val) {
> -+ case 0x08: /* BS: Back Space (^H) */
> -+ case 0x7f: /* DEL: Delete */
> -+ bs(p);
> -+ return;
> -+
> -+ case 0x09: /* HT: Horizontal Tab (^I) */
> -+ tab(p);
> -+ return;
> -+
> -+ case 0x0c: /* FF: Form Feed (^L) */
> -+ ff(p);
> -+ return;
> -+
> -+ case 0x0a: /* LF: Line Feed (^J) */
> -+ case 0x0b: /* VT: Vertical Tab (^K) */
> -+ lf(p);
> -+ if (! test_bit(CRLF, &p->struct_flags))
> -+ return;
> -+
> -+ case 0x0d: /* CR: Carriage Return (^M) */
> -+ cr(p);
> -+ return;
> -+
> -+ case 0x16: /* SYN: Synchronous Idle (^V) */
> -+ SET_INPUT_STATE(p, SYN);
> -+ return;
> -+
> -+ case 0x1b: /* ESC: Start of escape sequence */
> -+ SET_INPUT_STATE(p, ESC);
> -+ return;
> -+
> -+ case 0x9b: /* CSI: Start of CSI escape sequence */
> -+ memset(p->csi_args, 0, sizeof(p->csi_args));
> -+ p->index = 0;
> -+ SET_INPUT_STATE(p, CSI);
> -+ return;
> -+ }
> -+}
> -+
> -+static void gotoxy(struct lcd_struct *p, int new_col, int new_row)
> -+{
> -+ unsigned int vs_rows = p->par->vs_rows;
> -+ unsigned int vs_cols = p->par->vs_cols;
> -+ int min_row, max_row;
> -+
> -+ clear_bit(NEED_WRAP, &p->struct_flags);
> -+ if (test_bit(DECOM, &p->struct_flags)) {
> -+ min_row = p->top;
> -+ max_row = p->bot;
> -+ } else {
> -+ min_row = 0;
> -+ max_row = vs_rows;
> -+ }
> -+
> -+ if (new_row < min_row)
> -+ p->row = min_row;
> -+ else if (new_row >= max_row)
> -+ p->row = max_row-1;
> -+ else
> -+ p->row = new_row;
> -+
> -+ if (new_col < 0)
> -+ p->col = 0;
> -+ else if (new_col >= vs_cols)
> -+ p->col = vs_cols-1;
> -+ else
> -+ p->col = new_col;
> -+
> -+ if (show_cursor(p))
> -+ redraw_screen(p, 0, p->fb_size-1);
> -+}
> -+
> -+static void gotoxay(struct lcd_struct *p, int new_col, int new_row)
> -+{
> -+ gotoxy(p, new_col, test_bit(DECOM, &p->struct_flags) ? (p->top+new_row) : new_row);
> -+}
> -+
> -+
> -+/******************************
> -+ * ECMA-48 CSI ESC- sequences *
> -+ ******************************/
> -+static void csi_at(struct lcd_struct *p, unsigned int nr)
> -+{
> -+ unsigned int vs_cols = p->par->vs_cols;
> -+
> -+ if (p->col+nr > vs_cols)
> -+ nr = vs_cols-p->col;
> -+ else if (! nr)
> -+ ++nr;
> -+ lcd_insert_char(p, nr);
> -+}
> -+
> -+static void csi_J(struct lcd_struct *p, unsigned int action)
> -+{
> -+ unsigned int vs_cols = p->par->vs_cols;
> -+ unsigned int pos = (p->row*vs_cols)+p->col;
> -+
> -+ clear_bit(NEED_WRAP, &p->struct_flags);
> -+ switch (action) {
> -+ case 0: /* From cursor to end of display */
> -+ lcd_memset(p, pos, p->erase_char, p->fb_size-pos);
> -+ return;
> -+
> -+ case 1: /* From start of display to cursor */
> -+ lcd_memset(p, 0, p->erase_char, pos+1);
> -+ return;
> -+
> -+ case 2: /* Whole display */
> -+ lcd_memset(p, 0, p->erase_char, p->fb_size);
> -+ return;
> -+ }
> -+}
> -+
> -+static void csi_K(struct lcd_struct *p, unsigned int action)
> -+{
> -+ unsigned int vs_cols = p->par->vs_cols;
> -+ unsigned int row_start = p->row*vs_cols;
> -+
> -+ clear_bit(NEED_WRAP, &p->struct_flags);
> -+ switch (action) {
> -+ case 0: /* From cursor to end of line */
> -+ lcd_memset(p, row_start+p->col, p->erase_char, vs_cols-p->col);
> -+ return;
> -+
> -+ case 1: /* From start of line to cursor */
> -+ lcd_memset(p, row_start, p->erase_char, p->col+1);
> -+ return;
> -+
> -+ case 2: /* Whole line */
> -+ lcd_memset(p, row_start, p->erase_char, vs_cols);
> -+ return;
> -+ }
> -+}
> -+
> -+static void csi_L(struct lcd_struct *p, unsigned int nr)
> -+{
> -+ unsigned int vs_rows = p->par->vs_rows;
> -+ unsigned int vs_cols = p->par->vs_cols;
> -+
> -+ clear_bit(NEED_WRAP, &p->struct_flags);
> -+ if (p->row+nr > vs_rows)
> -+ nr = vs_rows-p->row;
> -+ else if (! nr)
> -+ ++nr;;
> -+ lcd_memmove(p, (p->row+nr)*vs_cols, p->row*vs_cols, (vs_rows-p->row-nr)*vs_cols);
> -+ lcd_memset(p, p->row*vs_cols, p->erase_char, nr*vs_cols);
> -+}
> -+
> -+static void csi_M(struct lcd_struct *p, unsigned int nr)
> -+{
> -+ unsigned int vs_rows = p->par->vs_rows;
> -+ unsigned int vs_cols = p->par->vs_cols;
> -+
> -+ clear_bit(NEED_WRAP, &p->struct_flags);
> -+ if (p->row+nr > vs_rows)
> -+ nr = vs_rows-p->row;
> -+ else if (! nr)
> -+ ++nr;;
> -+ lcd_memmove(p, p->row*vs_cols, (p->row+nr)*vs_cols, (vs_rows-p->row-nr)*vs_cols);
> -+ lcd_memset(p, (vs_rows-nr)*vs_cols, p->erase_char, nr*vs_cols);
> -+}
> -+
> -+static void csi_P(struct lcd_struct *p, unsigned int nr)
> -+{
> -+ unsigned int vs_cols = p->par->vs_cols;
> -+
> -+ if (p->col+nr > vs_cols)
> -+ nr = vs_cols-p->col;
> -+ else if (! nr)
> -+ ++nr;
> -+ lcd_delete_char(p, nr);
> -+}
> -+
> -+static void csi_X(struct lcd_struct *p, unsigned int nr)
> -+{
> -+ unsigned int vs_cols = p->par->vs_cols;
> -+
> -+ clear_bit(NEED_WRAP, &p->struct_flags);
> -+ if (p->col+nr > vs_cols)
> -+ nr = vs_cols-p->col;
> -+ else if (! nr)
> -+ ++nr;
> -+ lcd_memset(p, (p->row*vs_cols)+p->col, p->erase_char, nr);
> -+}
> -+
> -+static void csi_su(struct lcd_struct *p, unsigned char input)
> -+{
> -+ unsigned int vs_cols = p->par->vs_cols;
> -+
> -+ clear_bit(NEED_WRAP, &p->struct_flags);
> -+ if (input == 'u') {
> -+ p->row = p->s_offset/vs_cols;
> -+ p->col = p->s_offset%vs_cols;
> -+ p->color = p->s_color;
> -+ p->attributes = p->s_attributes;
> -+ return;
> -+ }
> -+ p->s_offset = (p->row*vs_cols)+p->col;
> -+ p->s_color = p->color;
> -+ p->s_attributes = p->attributes;
> -+}
> -+
> -+static inline unsigned char reverse_color_attr(unsigned char attr)
> -+{
> -+ return ((attr & (BG_BRIGHT | FG_BRIGHT)) | ((attr & BG_COLOR) >> 4) | ((attr & FG_COLOR) << 4));
> -+}
> -+
> -+static unsigned char build_attr(struct lcd_struct *p, unsigned char color, unsigned char intensity,
> -+ unsigned char blink, unsigned char underline, unsigned char reverse)
> -+{
> -+ unsigned char attr;
> -+
> -+ if (test_bit(CAN_DO_COLOR, &p->struct_flags)) {
> -+ attr = color;
> -+ if (underline)
> -+ attr = (attr & BG_MASK) | p->ulcolor;
> -+ else if (intensity == 0)
> -+ attr = (attr & BG_MASK) | p->halfcolor;
> -+ if (reverse)
> -+ attr = reverse_color_attr(attr);
> -+ if (blink)
> -+ attr ^= BG_BRIGHT;
> -+ if (intensity == 2)
> -+ attr ^= FG_BRIGHT;
> -+ } else {
> -+ attr = intensity;
> -+ attr |= (underline ? ULINE : 0x00);
> -+ attr |= (reverse ? REVERSE : 0x00);
> -+ attr |= (blink ? BLINK : 0x00);
> -+ }
> -+
> -+ return (attr);
> -+}
> -+
> -+static void update_attr(struct lcd_struct *p)
> -+{
> -+ unsigned char intensity = p->attributes & I_MASK;
> -+ unsigned char underline = (p->attributes & ULINE) ? 0x01 : 0x00;
> -+ unsigned char reverse = (p->attributes & REVERSE) ? 0x01 : 0x00;
> -+ unsigned char blink = (p->attributes & BLINK) ? 0x01 : 0x00;
> -+ unsigned char decscnm = test_bit(DECSCNM, &p->struct_flags) ? 0x01 : 0x00;
> -+
> -+ p->attr = build_attr(p, p->color, intensity, blink, underline, reverse ^ decscnm);
> -+ p->erase_char = (build_attr(p, p->color, 1, blink, 0, decscnm) << 8) | ' ';
> -+}
> -+
> -+static void default_attr(struct lcd_struct *p)
> -+{
> -+ p->attributes = 0x01;
> -+ p->color = p->defcolor;
> -+}
> -+
> -+static void lcd_invert_screen(struct lcd_struct *p, unsigned int s, unsigned int len)
> -+{
> -+ unsigned int l, inc_set = test_bit(INC_CURS_POS, &p->struct_flags);
> -+
> -+ if (! len || s >= p->fb_size)
> -+ return;
> -+ if (inc_set && s+len > p->fb_size)
> -+ len = p->fb_size-s;
> -+ else if (! inc_set && len > s+1)
> -+ len = s+1;
> -+
> -+ l = len;
> -+ if (test_bit(CAN_DO_COLOR, &p->struct_flags))
> -+ while (l--) {
> -+ p->fb[s] = (reverse_color_attr(p->fb[s] >> 8) << 8) | (p->fb[s] & 0xff);
> -+ ++s;
> -+ }
> -+ else
> -+ while (l--) {
> -+ p->fb[s] ^= REVERSE << 8;
> -+ ++s;
> -+ }
> -+
> -+ if (show_cursor(p))
> -+ redraw_screen(p, 0, p->fb_size-1);
> -+ else
> -+ redraw_screen(p, s, s+(len-1));
> -+}
> -+
> -+static void csi_m(struct lcd_struct *p, unsigned int n)
> -+{
> -+ int i, arg;
> -+
> -+ for (i = 0; i <= n; ++i)
> -+ switch ((arg = p->csi_args[i]))
> -+ {
> -+ case 0:
> -+ default_attr(p);
> -+ break;
> -+
> -+ case 1:
> -+ p->attributes = (p->attributes & ~I_MASK) | 2;
> -+ break;
> -+
> -+ case 2:
> -+ p->attributes = (p->attributes & ~I_MASK) | 0;
> -+ break;
> -+
> -+ case 4:
> -+ p->attributes |= ULINE;
> -+ break;
> -+
> -+ case 5:
> -+ p->attributes |= BLINK;
> -+ break;
> -+
> -+ case 7:
> -+ p->attributes |= REVERSE;
> -+ break;
> -+
> -+ case 21: case 22:
> -+ p->attributes = (p->attributes & ~I_MASK) | 1;
> -+ break;
> -+
> -+ case 24:
> -+ p->attributes &= ~ULINE;
> -+ break;
> -+
> -+ case 25:
> -+ p->attributes &= ~BLINK;
> -+ break;
> -+
> -+ case 27:
> -+ p->attributes &= ~REVERSE;
> -+ break;
> -+
> -+ case 38:
> -+ p->attributes |= ULINE;
> -+ p->color = (p->color & BG_MASK) | (p->defcolor & FG_MASK);
> -+ break;
> -+
> -+ case 39:
> -+ p->attributes &= ~ULINE;
> -+ p->color = (p->color & BG_MASK) | (p->defcolor & FG_MASK);
> -+ break;
> -+
> -+ case 49:
> -+ p->color = (p->defcolor & BG_MASK) | (p->color & FG_MASK);
> -+ break;
> -+
> -+ default:
> -+ if (arg >= 30 && arg <= 37)
> -+ p->color = (p->color & BG_MASK) | color_table[arg-30];
> -+ else if (arg >= 40 && arg <= 47)
> -+ p->color = (p->color & FG_MASK) | (color_table[arg-40] << 4);
> -+ break;
> -+ }
> -+
> -+ update_attr(p);
> -+}
> -+
> -+static void csi_h(struct lcd_struct *p, unsigned char n)
> -+{
> -+ switch (n) {
> -+ case 4: /* Set insert mode */
> -+ set_bit(DECIM, &p->struct_flags);
> -+ return;
> -+
> -+ case 5: /* Inverted screen mode */
> -+ if (test_bit(QUES, &p->struct_flags) && ! test_bit(DECSCNM, &p->struct_flags)) {
> -+ lcd_invert_screen(p, 0, p->fb_size);
> -+ set_bit(DECSCNM, &p->struct_flags);
> -+ update_attr(p);
> -+ }
> -+ return;
> -+
> -+ case 6: /* Cursor addressing origin: relative to scrolling region */
> -+ if (test_bit(QUES, &p->struct_flags)) {
> -+ set_bit(DECOM, &p->struct_flags);
> -+ gotoxay(p, 0, 0);
> -+ }
> -+ return;
> -+
> -+ case 7: /* Set autowrap */
> -+ if (test_bit(QUES, &p->struct_flags))
> -+ set_bit(DECAWM, &p->struct_flags);
> -+ return;
> -+
> -+ case 20: /* Set cr lf */
> -+ set_bit(CRLF, &p->struct_flags);
> -+ return;
> -+ }
> -+}
> -+
> -+static void csi_l(struct lcd_struct *p, unsigned char n)
> -+{
> -+ switch (n) {
> -+ case 4: /* Reset insert mode */
> -+ clear_bit(DECIM, &p->struct_flags);
> -+ return;
> -+
> -+ case 5: /* Normal screen mode */
> -+ if (test_bit(QUES, &p->struct_flags) && test_bit(DECSCNM, &p->struct_flags)) {
> -+ lcd_invert_screen(p, 0, p->fb_size);
> -+ clear_bit(DECSCNM, &p->struct_flags);
> -+ update_attr(p);
> -+ }
> -+ return;
> -+
> -+ case 6: /* Cursor addressing origin: absolute origin */
> -+ if (test_bit(QUES, &p->struct_flags)) {
> -+ clear_bit(DECOM, &p->struct_flags);
> -+ gotoxay(p, 0, 0);
> -+ }
> -+ return;
> -+
> -+ case 7: /* Reset autowrap */
> -+ if (test_bit(QUES, &p->struct_flags))
> -+ clear_bit(DECAWM, &p->struct_flags);
> -+ return;
> -+
> -+ case 20: /* Reset cr lf */
> -+ clear_bit(CRLF, &p->struct_flags);
> -+ return;
> -+ }
> -+}
> -+
> -+static void csi_linux(struct lcd_struct *p)
> -+{
> -+ switch (p->csi_args[0]) {
> -+ case 1:
> -+ if (test_bit(CAN_DO_COLOR, &p->struct_flags) && p->csi_args[1] < 16) {
> -+ p->ulcolor = color_table[p->csi_args[1]];
> -+ if (p->attributes & ULINE)
> -+ update_attr(p);
> -+ }
> -+ return;
> -+
> -+ case 2:
> -+ if (test_bit(CAN_DO_COLOR, &p->struct_flags) && p->csi_args[1] < 16) {
> -+ p->halfcolor = color_table[p->csi_args[1]];
> -+ if ((p->attributes & I_MASK) == 0)
> -+ update_attr(p);
> -+ }
> -+ return;
> -+
> -+ case 8:
> -+ p->defcolor = p->color;
> -+ default_attr(p);
> -+ update_attr(p);
> -+ return;
> -+ }
> -+}
> -+
> -+static void csi_r(struct lcd_struct *p, unsigned int top, unsigned int bot)
> -+{
> -+ /* Minimum allowed region is 2 lines */
> -+ if (top < bot) {
> -+ p->top = top-1;
> -+ p->bot = bot;
> -+ gotoxay(p, 0, 0);
> -+ }
> -+}
> -+
> -+/*
> -+ * ECMA-48 CSI ESC- sequence handler.
> -+ */
> -+static void handle_csi(struct lcd_struct *p, unsigned char input)
> -+{
> -+ if (p->index >= NPAR) {
> -+ SET_INPUT_STATE(p, NORMAL);
> -+ printk(KERN_NOTICE "LCD: too many parameters in CSI escape sequence\n");
> -+ } else if (input == '?') {
> -+ set_bit(QUES, &p->struct_flags);
> -+ } else if (input == ';') {
> -+ ++p->index;
> -+ } else if (input >= '0' && input <= '9') {
> -+ p->csi_args[p->index] = (p->csi_args[p->index]*10)+(input-'0');
> -+ } else {
> -+ SET_INPUT_STATE(p, NORMAL);
> -+ if (! test_bit(INC_CURS_POS, &p->struct_flags))
> -+ return;
> -+ switch (input) {
> -+ case 'h': /* DECSET sequences and mode switches */
> -+ csi_h(p, p->csi_args[0]);
> -+ clear_bit(QUES, &p->struct_flags);
> -+ return;
> -+
> -+ case 'l': /* DECRST sequences and mode switches */
> -+ csi_l(p, p->csi_args[0]);
> -+ clear_bit(QUES, &p->struct_flags);
> -+ return;
> -+ }
> -+ clear_bit(QUES, &p->struct_flags);
> -+ switch (input) {
> -+ case '@': /* Insert # Blank character */
> -+ csi_at(p, p->csi_args[0]);
> -+ return;
> -+
> -+ case 'G': case '`': /* Cursor to indicated column in current row */
> -+ if (p->csi_args[0])
> -+ --p->csi_args[0];
> -+ gotoxy(p, p->csi_args[0], p->row);
> -+ return;
> -+
> -+ case 'A': /* Cursor # rows Up */
> -+ if (! p->csi_args[0])
> -+ ++p->csi_args[0];
> -+ gotoxy(p, p->col, p->row-p->csi_args[0]);
> -+ return;
> -+
> -+ case 'B': case 'e': /* Cursor # rows Down */
> -+ if (! p->csi_args[0])
> -+ ++p->csi_args[0];
> -+ gotoxy(p, p->col, p->row+p->csi_args[0]);
> -+ return;
> -+
> -+ case 'C': case 'a': /* Cursor # columns Right */
> -+ if (! p->csi_args[0])
> -+ ++p->csi_args[0];
> -+ gotoxy(p, p->col+p->csi_args[0], p->row);
> -+ return;
> -+
> -+ case 'D': /* Cursor # columns Left */
> -+ if (! p->csi_args[0])
> -+ ++p->csi_args[0];
> -+ gotoxy(p, p->col-p->csi_args[0], p->row);
> -+ return;
> -+
> -+ case 'E': /* Cursor # rows Down, column 1 */
> -+ if (! p->csi_args[0])
> -+ ++p->csi_args[0];
> -+ gotoxy(p, 0, p->row+p->csi_args[0]);
> -+ return;
> -+
> -+ case 'F': /* Cursor # rows Up, column 1 */
> -+ if (! p->csi_args[0])
> -+ ++p->csi_args[0];
> -+ gotoxy(p, 0, p->row-p->csi_args[0]);
> -+ return;
> -+
> -+ case 'd': /* Cursor to indicated row in current column */
> -+ if (p->csi_args[0])
> -+ --p->csi_args[0];
> -+ gotoxay(p, p->col, p->csi_args[0]);
> -+ return;
> -+
> -+ case 'H': case 'f': /* Cursor to indicated row, column (origin 1, 1) */
> -+ if (p->csi_args[0])
> -+ --p->csi_args[0];
> -+ if (p->csi_args[1])
> -+ --p->csi_args[1];
> -+ gotoxay(p, p->csi_args[1], p->csi_args[0]);
> -+ return;
> -+
> -+ case 'J': /* Erase display */
> -+ csi_J(p, p->csi_args[0]);
> -+ return;
> -+
> -+ case 'K': /* Erase line */
> -+ csi_K(p, p->csi_args[0]);
> -+ return;
> -+
> -+ case 'L': /* Insert # blank lines */
> -+ csi_L(p, p->csi_args[0]);
> -+ return;
> -+
> -+ case 'M': /* Delete # blank lines */
> -+ csi_M(p, p->csi_args[0]);
> -+ return;
> -+
> -+ case 'P': /* Delete # characters on the current line */
> -+ csi_P(p, p->csi_args[0]);
> -+ return;
> -+
> -+ case 'X': /* Erase # characters on the current line */
> -+ csi_X(p, p->csi_args[0]);
> -+ return;
> -+
> -+ case 'm': /* Set video attributes */
> -+ csi_m(p, p->index);
> -+ return;
> -+
> -+ case 's': /* Save cursor position */
> -+ case 'u': /* Restore cursor position */
> -+ csi_su(p, input);
> -+ return;
> -+
> -+ case ']': /* Linux private ESC [ ] sequence */
> -+ csi_linux(p);
> -+ return;
> -+
> -+ case 'r': /* Set the scrolling region */
> -+ if (! p->csi_args[0])
> -+ ++p->csi_args[0];
> -+ if (! p->csi_args[1] || p->csi_args[1] > p->par->vs_rows)
> -+ p->csi_args[1] = p->par->vs_rows;
> -+ csi_r(p, p->csi_args[0], p->csi_args[1]);
> -+ return;
> -+
> -+ /* Ignored escape sequences */
> -+ case 'c':
> -+ case 'g':
> -+ case 'n':
> -+ case 'q':
> -+ return;
> -+
> -+ default:
> -+ printk(KERN_NOTICE "LCD: unrecognized CSI escape sequence: ESC [ %u\n", input);
> -+ return;
> -+ }
> -+ }
> -+}
> -+
> -+/*
> -+ * Custom ESC- sequence handler.
> -+ */
> -+static int handle_custom_esc(struct lcd_struct *p, unsigned int _input)
> -+{
> -+ unsigned char input = _input & 0xff;
> -+ struct lcd_parameters *par = p->par;
> -+
> -+ if (_input & (~0xff)) {
> -+ switch (ESC_STATE(p)) {
> -+ case 's':
> -+ if (p->index++) {
> -+ unsigned char *cgbuf = p->cgram_buffer-par->cgram_bytes;
> -+
> -+ cgbuf[p->index-2] = input;
> -+ if (p->index == par->cgram_bytes+1)
> -+ write_cgram(p, p->cgram_index, cgbuf);
> -+ } else {
> -+ if (! p->driver->write_cgram_char) {
> -+ printk(KERN_ERR "LCD: %s: missing function to write to CGRAM\n", p->par->name);
> -+ return (-1);
> -+ }
> -+ if (input >= par->cgram_char0 && input < par->cgram_char0+par->cgram_chars)
> -+ p->cgram_index = input;
> -+ else {
> -+ printk(KERN_NOTICE "LCD: bad CGRAM index\n");
> -+ return (-1);
> -+ }
> -+ }
> -+ return (0);
> -+
> -+ case 'G':
> -+ if (input >= par->cgram_char0 && input < par->cgram_char0+par->cgram_chars)
> -+ write_data(p, (p->attr << 8) | p->driver->charmap[input]);
> -+ else {
> -+ SET_INPUT_STATE(p, NORMAL);
> -+ handle_input(p, (p->attr << 8) | input);
> -+ }
> -+ return (0);
> -+
> -+ case 'r':
> -+ if (input == '1')
> -+ address_mode(p, -1);
> -+ else if (input == '0')
> -+ address_mode(p, 1);
> -+ return (0);
> -+
> -+ case 'A':
> -+ scrup(p, p->top, p->bot, input);
> -+ return (0);
> -+
> -+ case 'B':
> -+ scrdown(p, p->top, p->bot, input);
> -+ return (0);
> -+
> -+ case 'C':
> -+ browse_screen(p, input);
> -+ return (0);
> -+ }
> -+ }
> -+
> -+ /* These are the custom ESC- sequences */
> -+ switch (input) {
> -+ case 's': /* CGRAM select */
> -+ if (p->cgram_buffer) {
> -+ SET_ESC_STATE(p, input);
> -+ p->index = 0;
> -+ return (par->cgram_bytes+1);
> -+ } else {
> -+ printk(KERN_NOTICE "LCD: driver %s does not support CGRAM chars\n", par->name);
> -+ return (0);
> -+ }
> -+
> -+ case 'A': /* Scroll up */
> -+ case 'B': /* Scroll down */
> -+ case 'C': /* Browse screen */
> -+ case 'G': /* Enter cgram mode */
> -+ case 'r': /* Decrement counter after data read/write */
> -+ SET_ESC_STATE(p, input);
> -+ return (1);
> -+ }
> -+
> -+ return (-1);
> -+}
> -+
> -+/*
> -+ * ESC- but not CSI sequence handler.
> -+ */
> -+static int handle_esc(struct lcd_struct *p, unsigned char input)
> -+{
> -+ int ret;
> -+
> -+ SET_INPUT_STATE(p, NORMAL);
> -+ switch (input) {
> -+ case 'c': /* Reset */
> -+ set_bit(DECAWM, &p->struct_flags);
> -+ set_bit(INC_CURS_POS, &p->struct_flags);
> -+ ff(p);
> -+ return (0);
> -+
> -+ case 'D': /* Line Feed */
> -+ lf(p);
> -+ return (0);
> -+
> -+ case 'E': /* New Line */
> -+ cr(p);
> -+ lf(p);
> -+ return (0);
> -+
> -+ case 'M': /* Reverse Line Feed */
> -+ ri(p);
> -+ return (0);
> -+
> -+ case '7':
> -+ case '8':
> -+ csi_su(p, (input == '7' ? 's' : 'u'));
> -+ return (0);
> -+
> -+ /* CSI: Start of CSI escape sequence */
> -+ case '[':
> -+ memset(p->csi_args, 0, sizeof(p->csi_args));
> -+ p->index = 0;
> -+ SET_INPUT_STATE(p, CSI);
> -+ return (0);
> -+
> -+ /* Ignored escape sequences */
> -+ case '(':
> -+ SET_INPUT_STATE(p, ESC_G0);
> -+ return (1);
> -+
> -+ case ')':
> -+ SET_INPUT_STATE(p, ESC_G1);
> -+ return (1);
> -+
> -+ case '#':
> -+ SET_INPUT_STATE(p, ESC_HASH);
> -+ return (1);
> -+
> -+ case '%':
> -+ SET_INPUT_STATE(p, ESC_PERCENT);
> -+ return (1);
> -+
> -+ case 'H':
> -+ case 'Z':
> -+ case '>':
> -+ case '=':
> -+ case ']':
> -+ return (0);
> -+ }
> -+
> -+ /* These are the custom ESC- sequences */
> -+ if ((ret = handle_custom_esc(p, input)) > 0) {
> -+ SET_INPUT_STATE(p, ARG);
> -+ return (ret);
> -+ }
> -+
> -+ if (ret < 0 && p->driver->handle_custom_char)
> -+ if ((ret = p->driver->handle_custom_char(input)) > 0) {
> -+ SET_INPUT_STATE(p, ARG_DRIVER);
> -+ return (ret);
> -+ }
> -+
> -+ if (ret < 0)
> -+ printk(KERN_NOTICE "LCD: unrecognized escape sequence: ESC %u\n", input);
> -+
> -+ return (0);
> -+}
> -+
> -+/*
> -+ * Main input handler.
> -+ */
> -+static void handle_input(struct lcd_struct *p, unsigned short _input)
> -+{
> -+ unsigned char input = _input & 0xff;
> -+ struct lcd_driver *driver = p->driver;
> -+
> -+ switch (INPUT_STATE(p)) {
> -+ case NORMAL:
> -+ if (input < 0x20 || input == 0x9b)
> -+ control_char(p, input);
> -+ else
> -+ write_data(p, (_input & 0xff00) | driver->charmap[input]);
> -+ return;
> -+
> -+ case RAW:
> -+ write_data(p, (_input & 0xff00) | driver->charmap[input]);
> -+ return;
> -+
> -+ case SYN:
> -+ write_data(p, _input);
> -+ SET_INPUT_STATE(p, NORMAL);
> -+ return;
> -+
> -+ case ESC:
> -+ p->esc_args = handle_esc(p, input);
> -+ return;
> -+
> -+ case ESC_G0:
> -+ case ESC_G1:
> -+ case ESC_HASH:
> -+ case ESC_PERCENT:
> -+ if (! --p->esc_args)
> -+ SET_INPUT_STATE(p, NORMAL);
> -+ return;
> -+
> -+ case CSI:
> -+ handle_csi(p, input);
> -+ return;
> -+
> -+ case ARG:
> -+ if (handle_custom_esc(p, 0x100 | input) || ! --p->esc_args)
> -+ SET_INPUT_STATE(p, NORMAL);
> -+ return;
> -+
> -+ case ARG_DRIVER:
> -+ if (driver->handle_custom_char(0x100 | input) || ! --p->esc_args)
> -+ SET_INPUT_STATE(p, NORMAL);
> -+ return;
> -+ }
> -+}
> -+
> -+
> -+
> -+
> -+
> -+/***************************************
> -+ * Read from/Write to display routines *
> -+ ***************************************/
> -+
> -+/*
> -+ * Write character data to the display.
> -+ */
> -+static void write_data(struct lcd_struct *p, unsigned short data)
> -+{
> -+ unsigned int vs_cols = p->par->vs_cols;
> -+ unsigned int pos;
> -+ int frame_pos;
> -+
> -+ if (test_bit(NEED_WRAP, &p->struct_flags)) {
> -+ cr(p);
> -+ lf(p);
> -+ }
> -+
> -+ if (test_bit(DECIM, &p->struct_flags))
> -+ lcd_insert_char(p, 1);
> -+
> -+ pos = (p->row*vs_cols)+p->col;
> -+ if ((frame_pos = vs_to_frame_(p, pos)) < 0) {
> -+ show_cursor(p);
> -+ redraw_screen(p, 0, p->fb_size-1);
> -+ frame_pos = vs_to_frame_(p, pos);
> -+ }
> -+
> -+ if (p->display[frame_pos] != data) {
> -+ p->driver->write_char(frame_pos, data);
> -+ p->display[frame_pos] = data;
> -+ }
> -+
> -+ p->fb[pos] = data;
> -+
> -+ if (test_bit(INC_CURS_POS, &p->struct_flags)) {
> -+ if (p->col+1 < vs_cols)
> -+ iterator_inc(p->col, vs_cols);
> -+ else if (test_bit(DECAWM, &p->struct_flags))
> -+ set_bit(NEED_WRAP, &p->struct_flags);
> -+ } else {
> -+ if (p->col)
> -+ iterator_dec(p->col, vs_cols);
> -+ else if (test_bit(DECAWM, &p->struct_flags))
> -+ set_bit(NEED_WRAP, &p->struct_flags);
> -+ }
> -+}
> -+
> -+/*
> -+ * Write an entire CGRAM character to the display.
> -+ */
> -+static void write_cgram(struct lcd_struct *p, unsigned char index, unsigned char *pixels)
> -+{
> -+ struct lcd_parameters *par = p->par;
> -+ unsigned int inc_set = test_bit(INC_CURS_POS, &p->struct_flags);
> -+ unsigned char *cgbuf = p->cgram_buffer+(index-par->cgram_char0)*par->cgram_bytes;
> -+
> -+ if (! strncmp(cgbuf, pixels, par->cgram_bytes))
> -+ return;
> -+
> -+ if (! inc_set)
> -+ address_mode(p, 1);
> -+
> -+ p->driver->write_cgram_char(index, pixels);
> -+ memcpy(cgbuf, pixels, par->cgram_bytes);
> -+
> -+ if (! inc_set)
> -+ address_mode(p, -1);
> -+}
> -+
> -+/*
> -+ * Read character data from the display.
> -+ */
> -+static void read_data(struct lcd_struct *p, unsigned short *data)
> -+{
> -+ unsigned int vs_rows = p->par->vs_rows;
> -+ unsigned int vs_cols = p->par->vs_cols;
> -+ unsigned int pos = (p->row*vs_cols)+p->col;
> -+ int frame_pos;
> -+
> -+ if ((frame_pos = vs_to_frame_(p, pos)) < 0) {
> -+ show_cursor(p);
> -+ redraw_screen(p, 0, p->fb_size-1);
> -+ frame_pos = vs_to_frame_(p, pos);
> -+ }
> -+
> -+ if (p->driver->read_char)
> -+ p->driver->read_char(frame_pos, data);
> -+ else
> -+ *data = p->fb[pos];
> -+
> -+ if (test_bit(INC_CURS_POS, &p->struct_flags)) {
> -+ iterator_inc(p->col, vs_cols);
> -+ if (! p->col) {
> -+ if (p->row+1 < vs_rows)
> -+ ++p->row;
> -+ }
> -+ } else {
> -+ iterator_dec(p->col, vs_cols);
> -+ if (p->col+1 == vs_cols) {
> -+ if (p->row)
> -+ --p->row;
> -+ }
> -+ }
> -+}
> -+
> -+/*
> -+ * Read an entire CGRAM character from the display.
> -+ */
> -+static void read_cgram(struct lcd_struct *p, unsigned char index, unsigned char *pixels)
> -+{
> -+ struct lcd_parameters *par = p->par;
> -+ unsigned int inc_set = test_bit(INC_CURS_POS, &p->struct_flags);
> -+ unsigned char *cgbuf = p->cgram_buffer+(index-par->cgram_char0)*par->cgram_bytes;
> -+
> -+ if (! p->driver->read_cgram_char) {
> -+ memcpy(pixels, cgbuf, par->cgram_bytes);
> -+ return;
> -+ }
> -+
> -+ if (! inc_set)
> -+ address_mode(p, 1);
> -+
> -+ p->driver->read_cgram_char(index, pixels);
> -+
> -+ if (! inc_set)
> -+ address_mode(p, -1);
> -+}
> -+
> -+
> -+
> -+
> -+
> -+/****************************
> -+ * Proc filesystem routines *
> -+ ****************************/
> -+#ifdef USE_PROC
> -+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 4, 0)
> -+/* create_proc_read_entry is missing in 2.2.x kernels */
> -+static struct proc_dir_entry *create_proc_read_entry(const char *name, mode_t mode,
> -+ struct proc_dir_entry *parent, read_proc_t *read_proc, void *data)
> -+{
> -+ struct proc_dir_entry *res = create_proc_entry(name, mode, parent);
> -+
> -+ if (res) {
> -+ res->read_proc = read_proc;
> -+ res->data = data;
> -+ }
> -+
> -+ return (res);
> -+}
> -+#endif
> -+
> -+static int proc_fb_read(char *buffer, char **start, off_t offset, int size, int *eof, void *data)
> -+{
> -+ char *temp = buffer;
> -+ struct lcd_struct *p = (struct lcd_struct *)data;
> -+ unsigned int vs_cols;
> -+ static unsigned int nr, need_wrap;
> -+ static off_t _offset;
> -+
> -+ down(&p->lcd_sem);
> -+ if (! offset)
> -+ _offset = 0;
> -+ if ((*eof = (_offset >= p->fb_size))) {
> -+ up(&p->lcd_sem);
> -+ return (0);
> -+ }
> -+ vs_cols = p->par->vs_cols;
> -+ if (size && need_wrap) {
> -+ need_wrap = 0;
> -+ temp += sprintf(temp, "\n");
> -+ --size;
> -+ }
> -+ if (! nr)
> -+ nr = vs_cols;
> -+ *start = (char *)0;
> -+ while (size && nr) {
> -+ unsigned char c = (p->fb[_offset] & 0xff);
> -+
> -+ temp += sprintf(temp, "%c", (c < 0x20 ? '?' : c));
> -+ --size;
> -+ --nr;
> -+ ++*start;
> -+ ++_offset;
> -+ }
> -+ if (! nr) {
> -+ if (size) {
> -+ temp += sprintf(temp, "\n");
> -+ --size;
> -+ } else
> -+ need_wrap = 1;
> -+ }
> -+ up(&p->lcd_sem);
> -+
> -+ return (temp-buffer);
> -+}
> -+
> -+static int proc_display_read(char *buffer, char **start, off_t offset, int size, int *eof, void *data)
> -+{
> -+ char *temp = buffer;
> -+ struct lcd_struct *p = (struct lcd_struct *)data;
> -+ unsigned int i, frame_cols;
> -+ int frame_pos;
> -+
> -+ down(&p->lcd_sem);
> -+ frame_cols = p->par->cntr_cols;
> -+ frame_pos = vs_to_frame_(p, (p->row*p->par->vs_cols)+p->col);
> -+ temp += sprintf(temp, " ");
> -+ for (i = 2; i <= frame_cols; i += 2)
> -+ temp += sprintf(temp, " %d", i%10);
> -+ temp += sprintf(temp, "\n");
> -+
> -+ temp += sprintf(temp, " +");
> -+ for (i = 0; i < frame_cols; ++i)
> -+ temp += sprintf(temp, "-");
> -+ temp += sprintf(temp, "+\n");
> -+
> -+ for (i = 0; i < p->frame_size; ++i) {
> -+ unsigned char c = (p->display[i] & 0xff);
> -+
> -+ if (! (i%frame_cols))
> -+ temp += sprintf(temp, "%2d |", 1+i/frame_cols);
> -+ if (frame_pos--)
> -+ temp += sprintf(temp, "%c", (c < 0x20 ? '?' : c));
> -+ else
> -+ temp += sprintf(temp, "_");
> -+ if (! ((i+1)%frame_cols))
> -+ temp += sprintf(temp, "|\n");
> -+ }
> -+
> -+ temp += sprintf(temp, " +");
> -+ for (i = 0; i < frame_cols; ++i)
> -+ temp += sprintf(temp, "-");
> -+ temp += sprintf(temp, "+\n");
> -+ up(&p->lcd_sem);
> -+
> -+ return (temp-buffer);
> -+}
> -+
> -+static int proc_charmap_read(char *buffer, char **start, off_t offset, int size, int *eof, void *data)
> -+{
> -+ char *temp = buffer;
> -+ struct lcd_struct *p = (struct lcd_struct *)data;
> -+ unsigned char *charmap;
> -+ unsigned int i;
> -+
> -+ down(&p->lcd_sem);
> -+ charmap = p->driver->charmap;
> -+ temp += sprintf(temp, "static unsigned char charmap[] = {");
> -+ for (i = 0; i < 255; ++i) {
> -+ if (! (i & 7)) {
> -+ temp += sprintf(temp, "\n");
> -+ if (! (i & 31))
> -+ temp += sprintf(temp, "\n/* %d - %d */\n", i, i+31);
> -+ }
> -+ temp += sprintf(temp, "0x%.2x, ", *charmap++);
> -+ }
> -+ temp += sprintf(temp, "0x%.2x\n\n};\n", *charmap);
> -+ up(&p->lcd_sem);
> -+
> -+ return (temp-buffer);
> -+}
> -+
> -+static int proc_registered_drivers(char *buffer, char **start, off_t offset, int size, int *eof, void *data)
> -+{
> -+ char *temp = buffer;
> -+ struct list_head *entry;
> -+
> -+ down(&drivers_sem);
> -+ temp += sprintf(temp, "Registered drivers:\n");
> -+ list_for_each(entry, &lcd_drivers) {
> -+ struct lcd_struct *p = list_entry(entry, struct lcd_struct, lcd_list);
> -+
> -+ down(&p->lcd_sem);
> -+ temp += sprintf(temp, "%3d %s\n", p->par->minor, p->par->name);
> -+ up(&p->lcd_sem);
> -+ }
> -+ up(&drivers_sem);
> -+
> -+ return (temp-buffer);
> -+}
> -+
> -+static void create_driver_proc_entries(struct lcd_struct *p)
> -+{
> -+ struct proc_dir_entry *driver_proc_root = p->driver->driver_proc_root;
> -+
> -+ SET_PROC_LEVEL(p, 0);
> -+ if (create_proc_read_entry("framebuffer", 0, driver_proc_root, proc_fb_read, p) == NULL) {
> -+ printk(KERN_ERR "LCD: cannot create /proc/lcd/%s/framebuffer\n", p->par->name);
> -+ return;
> -+ }
> -+ SET_PROC_LEVEL(p, 1);
> -+ if (create_proc_read_entry("display", 0, driver_proc_root, proc_display_read, p) == NULL) {
> -+ printk(KERN_ERR "LCD: cannot create /proc/lcd/%s/display\n", p->par->name);
> -+ return;
> -+ }
> -+ SET_PROC_LEVEL(p, 2);
> -+ if (create_proc_read_entry("charmap.h", 0, driver_proc_root, proc_charmap_read, p) == NULL) {
> -+ printk(KERN_ERR "LCD: cannot create /proc/lcd/%s/charmap.h\n", p->par->name);
> -+ return;
> -+ }
> -+ SET_PROC_LEVEL(p, 3);
> -+}
> -+
> -+static void remove_driver_proc_entries(struct lcd_struct *p)
> -+{
> -+ struct proc_dir_entry *driver_proc_root = p->driver->driver_proc_root;
> -+
> -+ switch (PROC_LEVEL(p)) {
> -+ case 3:
> -+ remove_proc_entry("charmap.h", driver_proc_root);
> -+ case 2:
> -+ remove_proc_entry("display", driver_proc_root);
> -+ case 1:
> -+ remove_proc_entry("framebuffer", driver_proc_root);
> -+ }
> -+ SET_PROC_LEVEL(p, 0);
> -+}
> -+#endif
> -+
> -+
> -+
> -+
> -+
> -+/*****************************
> -+ * Low level file operations *
> -+ *****************************/
> -+static ssize_t do_lcd_read(struct lcd_struct *p, void *buffer, size_t length)
> -+{
> -+ unsigned int i;
> -+ unsigned short tmp;
> -+
> -+ if (! p->refcount)
> -+ return (-ENXIO);
> -+
> -+ if (test_bit(WITH_ATTR, &p->struct_flags))
> -+ for (i = 0; i < length; ++i) {
> -+ read_data(p, &tmp);
> -+ ((unsigned short *)buffer)[i] = tmp;
> -+ }
> -+ else
> -+ for (i = 0; i < length; ++i) {
> -+ read_data(p, &tmp);
> -+ ((unsigned char *)buffer)[i] = tmp & 0xff;
> -+ }
> -+
> -+ return (length);
> -+}
> -+
> -+static ssize_t do_lcd_write(struct lcd_struct *p, const void *buffer, size_t length)
> -+{
> -+ unsigned int i;
> -+
> -+ if (! p->refcount)
> -+ return (-ENXIO);
> -+
> -+ if (test_bit(WITH_ATTR, &p->struct_flags))
> -+ for (i = 0; i < length; ++i)
> -+ handle_input(p, ((const unsigned short *)buffer)[i]);
> -+ else
> -+ for (i = 0; i < length; ++i)
> -+ handle_input(p, (p->attr << 8) | ((const unsigned char *)buffer)[i]);
> -+
> -+ return (length);
> -+}
> -+
> -+static int do_lcd_open(struct lcd_struct *p)
> -+{
> -+ if (! p->refcount) {
> -+ if (p->driver->driver_module) {
> -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0)
> -+ if (! try_module_get(p->driver->driver_module))
> -+ return (-EBUSY);
> -+#else
> -+ if (__MOD_IN_USE(p->driver->driver_module))
> -+ return (-EBUSY);
> -+
> -+ __MOD_INC_USE_COUNT(p->driver->driver_module);
> -+#endif
> -+ }
> -+ }
> -+
> -+ ++p->refcount;
> -+
> -+ return (0);
> -+}
> -+
> -+static int do_lcd_release(struct lcd_struct *p)
> -+{
> -+ if (! p->refcount)
> -+ return (0);
> -+
> -+ if (p->refcount == 1) {
> -+ if (p->driver->driver_module)
> -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0)
> -+ module_put(p->driver->driver_module);
> -+#else
> -+ __MOD_DEC_USE_COUNT(p->driver->driver_module);
> -+#endif
> -+ }
> -+
> -+ --p->refcount;
> -+
> -+ return (0);
> -+}
> -+
> -+static int cgram_ioctl(struct lcd_struct *p, unsigned int cmd, unsigned char *argp)
> -+{
> -+ struct lcd_parameters *par = p->par;
> -+ unsigned int length = par->cgram_bytes;
> -+ unsigned char index = argp[0];
> -+ unsigned char *buffer = argp+1;
> -+ unsigned char *cgbuf = p->cgram_buffer-length;
> -+
> -+ if (index < par->cgram_char0 || index >= par->cgram_char0+par->cgram_chars)
> -+ return (-EINVAL);
> -+
> -+ if (! p->driver->write_cgram_char) {
> -+ printk(KERN_ERR "LCD: %s: missing function to write to CGRAM\n", p->par->name);
> -+ return (-ENOSYS);
> -+ }
> -+
> -+ if (cmd == LCDL_SET_CGRAM_CHAR) {
> -+ if (test_bit(USER_SPACE, &p->struct_flags)) {
> -+ if (copy_from_user(cgbuf, buffer, length))
> -+ return (-EFAULT);
> -+ } else
> -+ memcpy(cgbuf, buffer, length);
> -+ write_cgram(p, index, cgbuf);
> -+ } else {
> -+ read_cgram(p, index, cgbuf);
> -+ if (test_bit(USER_SPACE, &p->struct_flags)) {
> -+ if (copy_to_user(buffer, cgbuf, length))
> -+ return (-EFAULT);
> -+ } else
> -+ memcpy(buffer, cgbuf, length);
> -+ }
> -+
> -+ return (0);
> -+}
> -+
> -+static int do_lcd_ioctl(struct lcd_struct *p, unsigned int cmd, unsigned long arg)
> -+{
> -+ int i;
> -+ struct lcd_driver *driver = p->driver;
> -+ struct lcd_parameters *par = p->par;
> -+ unsigned char *argp = (unsigned char *)arg;
> -+
> -+ if (! p->refcount)
> -+ return (-ENXIO);
> -+
> -+ switch (cmd) {
> -+ case LCDL_SET_PARAM:
> -+ if (argp == NULL)
> -+ return (-EFAULT);
> -+ if ((i = cleanup_driver(p)))
> -+ return (i);
> -+ i = par->minor;
> -+ if (test_bit(USER_SPACE, &p->struct_flags)) {
> -+ if (copy_from_user(par, argp, sizeof(struct lcd_parameters)))
> -+ return (-EFAULT);
> -+ } else
> -+ memcpy(par, argp, sizeof(struct lcd_parameters));
> -+ par->minor = i;
> -+ return (init_driver(p));
> -+
> -+ case LCDL_GET_PARAM:
> -+ if (argp == NULL)
> -+ return (-EFAULT);
> -+ if (test_bit(USER_SPACE, &p->struct_flags)) {
> -+ if (copy_to_user(argp, par, sizeof(struct lcd_parameters)))
> -+ return (-EFAULT);
> -+ } else
> -+ memcpy(argp, par, sizeof(struct lcd_parameters));
> -+ return (0);
> -+
> -+ case LCDL_RESET_CHARMAP:
> -+ for (i = 0; i < 256; ++i)
> -+ driver->charmap[i] = i;
> -+ return (0);
> -+
> -+ case LCDL_CHARSUBST:
> -+ if (argp == NULL)
> -+ return (-EFAULT);
> -+ if (test_bit(USER_SPACE, &p->struct_flags)) {
> -+ get_user(i, argp);
> -+ get_user(driver->charmap[i], argp+1);
> -+ } else {
> -+ i = argp[0];
> -+ driver->charmap[i] = argp[1];
> -+ }
> -+ return (0);
> -+
> -+ case LCDL_SAVE_CHARMAP:
> -+ memcpy(p->s_charmap, driver->charmap, 256);
> -+ return (0);
> -+
> -+ case LCDL_RESTORE_CHARMAP:
> -+ memcpy(driver->charmap, p->s_charmap, 256);
> -+ return (0);
> -+
> -+ case LCDL_SWAP_CHARMAP:
> -+ {
> -+ unsigned char *tmp;
> -+
> -+ tmp = driver->charmap;
> -+ driver->charmap = p->s_charmap;
> -+ p->s_charmap = tmp;
> -+ }
> -+ return (0);
> -+
> -+ case LCDL_RAW_MODE:
> -+ if (arg) {
> -+ clear_bit(NEED_WRAP, &p->struct_flags);
> -+ clear_bit(DECIM, &p->struct_flags);
> -+ clear_bit(DECAWM, &p->struct_flags);
> -+ SET_INPUT_STATE(p, RAW);
> -+ } else {
> -+ set_bit(DECAWM, &p->struct_flags);
> -+ SET_INPUT_STATE(p, NORMAL);
> -+ }
> -+ return (0);
> -+
> -+ case LCDL_IOATTR:
> -+ if (arg)
> -+ set_bit(WITH_ATTR, &p->struct_flags);
> -+ else
> -+ clear_bit(WITH_ATTR, &p->struct_flags);
> -+ return (0);
> -+
> -+ case LCDL_CLEAR_DISP:
> -+ ff(p);
> -+ return (0);
> -+
> -+ case LCDL_SET_CGRAM_CHAR:
> -+ case LCDL_GET_CGRAM_CHAR:
> -+ if (argp == NULL)
> -+ return (-EFAULT);
> -+ if (p->cgram_buffer)
> -+ return (cgram_ioctl(p, cmd, argp));
> -+ else
> -+ printk(KERN_NOTICE "LCD: driver %s does not support CGRAM chars\n", par->name);
> -+ return (0);
> -+
> -+ case LCDL_SET_CHARMAP:
> -+ if (argp == NULL)
> -+ return (-EFAULT);
> -+ if (test_bit(USER_SPACE, &p->struct_flags)) {
> -+ if (copy_from_user(driver->charmap, argp, 256))
> -+ return (-EFAULT);
> -+ } else
> -+ memcpy(driver->charmap, argp, 256);
> -+ return (0);
> -+
> -+ case LCDL_GET_CHARMAP:
> -+ if (argp == NULL)
> -+ return (-EFAULT);
> -+ if (test_bit(USER_SPACE, &p->struct_flags)) {
> -+ if (copy_to_user(argp, driver->charmap, 256))
> -+ return (-EFAULT);
> -+ } else
> -+ memcpy(argp, driver->charmap, 256);
> -+ return (0);
> -+
> -+ case LCDL_MEMSET:
> -+ case LCDL_MEMMOVE:
> -+ {
> -+ int buf[3];
> -+
> -+ if (argp == NULL)
> -+ return (-EFAULT);
> -+ if (test_bit(USER_SPACE, &p->struct_flags)) {
> -+ if (copy_from_user(buf, argp, sizeof(buf)))
> -+ return (-EFAULT);
> -+ } else
> -+ memcpy(buf, argp, sizeof(buf));
> -+
> -+ if (cmd == LCDL_MEMSET)
> -+ lcd_memset(p, buf[0], buf[1], buf[2]);
> -+ else
> -+ lcd_memmove(p, buf[0], buf[1], buf[2]);
> -+
> -+ return (0);
> -+ }
> -+
> -+ default:
> -+ if (driver->handle_custom_ioctl)
> -+ return (driver->handle_custom_ioctl(cmd, arg, test_bit(USER_SPACE, &p->struct_flags)));
> -+ }
> -+
> -+ return (-ENOIOCTLCMD);
> -+}
> -+
> -+
> -+
> -+
> -+
> -+/**************************************************
> -+ * Kernel register/unregister lcd driver routines *
> -+ **************************************************/
> -+/*
> -+ * Find a driver in lcd_drivers linked list
> -+ */
> -+static struct lcd_struct *find_lcd_struct(unsigned short minor)
> -+{
> -+ struct list_head *entry;
> -+
> -+ list_for_each(entry, &lcd_drivers) {
> -+ struct lcd_struct *p = list_entry(entry, struct lcd_struct, lcd_list);
> -+
> -+ if (p->par->minor == minor)
> -+ return (p);
> -+ }
> -+
> -+ return (NULL);
> -+}
> -+
> -+static void list_add_sorted(struct list_head *new)
> -+{
> -+ struct list_head *entry;
> -+ unsigned short new_minor = (list_entry(new, struct lcd_struct, lcd_list))->par->minor;
> -+
> -+ list_for_each(entry, &lcd_drivers) {
> -+ struct lcd_struct *p = list_entry(entry, struct lcd_struct, lcd_list);
> -+
> -+ if (p->par->minor > new_minor)
> -+ break;
> -+ }
> -+ list_add_tail(new, entry);
> -+}
> -+
> -+/* Exported function */
> -+int lcd_register_driver(struct lcd_driver *driver, struct lcd_parameters *par)
> -+{
> -+ int ret;
> -+ struct lcd_struct *p;
> -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 19)
> -+ struct device *lcd_device;
> -+#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 13)
> -+ struct class_device *lcd_device;
> -+#endif
> -+
> -+ if (! driver || ! par || par->minor >= minors)
> -+ return (-EINVAL);
> -+ if (! driver->write_char || ! driver->init_port || ! driver->cleanup_port) {
> -+ printk(KERN_ERR "LCD: missing functions\n");
> -+ return (-EINVAL);
> -+ }
> -+
> -+ down(&drivers_sem);
> -+
> -+ if (find_lcd_struct(par->minor)) {
> -+ up(&drivers_sem);
> -+ return (-EBUSY);
> -+ }
> -+
> -+ if ((p = (struct lcd_struct *)kmalloc(sizeof(struct lcd_struct), GFP_KERNEL)) == NULL) {
> -+ printk(KERN_ERR "LCD: memory allocation failed (kmalloc)\n");
> -+ up(&drivers_sem);
> -+ return (-ENOMEM);
> -+ }
> -+ memset(p, 0, sizeof(struct lcd_struct));
> -+
> -+ p->driver = driver;
> -+ p->par = par;
> -+ p->refcount = 0;
> -+ SET_INIT_LEVEL(p, 0);
> -+ SET_INPUT_STATE(p, NORMAL);
> -+ set_bit(DECAWM, &p->struct_flags);
> -+ set_bit(INC_CURS_POS, &p->struct_flags);
> -+
> -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 13)
> -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)
> -+ lcd_device = device_create(lcd_linux_class, NULL, MKDEV(major, par->minor), NULL, "%s", par->name);
> -+#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 19)
> -+ lcd_device = device_create(lcd_linux_class, NULL, MKDEV(major, par->minor), "%s", par->name);
> -+#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 15)
> -+ lcd_device = class_device_create(lcd_linux_class, NULL, MKDEV(major, par->minor), NULL, "%s", par->name);
> -+#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 13)
> -+ lcd_device = class_device_create(lcd_linux_class, MKDEV(major, par->minor), NULL, "%s", par->name);
> -+#endif
> -+ if (IS_ERR(lcd_device)) {
> -+ kfree(p);
> -+ up(&drivers_sem);
> -+ return (PTR_ERR(lcd_device));
> -+ }
> -+#endif
> -+
> -+#ifdef USE_PROC
> -+ if (lcd_proc_root && (driver->driver_proc_root = proc_mkdir(par->name, lcd_proc_root)) == NULL)
> -+ printk(KERN_ERR "LCD: cannot create /proc/lcd/%s/\n", par->name);
> -+#endif
> -+
> -+ if ((ret = init_driver(p))) {
> -+#ifdef USE_PROC
> -+ if (driver->driver_proc_root)
> -+ remove_proc_entry(p->par->name, lcd_proc_root);
> -+#endif
> -+
> -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 19)
> -+ device_destroy(lcd_linux_class, MKDEV(major, par->minor));
> -+#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 13)
> -+ class_device_destroy(lcd_linux_class, MKDEV(major, par->minor));
> -+#endif
> -+
> -+ kfree(p);
> -+ up(&drivers_sem);
> -+ return (ret);
> -+ }
> -+
> -+ init_MUTEX(&p->lcd_sem);
> -+
> -+ list_add_sorted(&p->lcd_list);
> -+
> -+ up(&drivers_sem);
> -+
> -+#ifdef MODULE
> -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0)
> -+ try_module_get(THIS_MODULE);
> -+#else
> -+ MOD_INC_USE_COUNT;
> -+#endif
> -+#endif
> -+
> -+ return (0);
> -+}
> -+EXPORT_SYMBOL(lcd_register_driver);
> -+
> -+/* Exported function */
> -+int lcd_unregister_driver(struct lcd_driver *driver, struct lcd_parameters *par)
> -+{
> -+ int ret;
> -+ struct lcd_struct *p;
> -+
> -+ if (! driver || ! par || par->minor >= minors)
> -+ return (-EINVAL);
> -+
> -+ down(&drivers_sem);
> -+
> -+ if ((p = find_lcd_struct(par->minor)) == NULL || p->driver != driver) {
> -+ printk(KERN_ERR "LCD: driver not found; lcd_unregister_driver failed\n");
> -+ up(&drivers_sem);
> -+ return (-ENODEV);
> -+ }
> -+
> -+ down(&p->lcd_sem);
> -+
> -+ if (p->refcount) {
> -+ printk(KERN_ERR "LCD: driver busy; lcd_unregister_driver failed\n");
> -+ up(&p->lcd_sem);
> -+ up(&drivers_sem);
> -+ return (-EBUSY);
> -+ }
> -+
> -+ if ((ret = cleanup_driver(p))) {
> -+ up(&p->lcd_sem);
> -+ up(&drivers_sem);
> -+ return (ret);
> -+ }
> -+
> -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 19)
> -+ device_destroy(lcd_linux_class, MKDEV(major, par->minor));
> -+#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 13)
> -+ class_device_destroy(lcd_linux_class, MKDEV(major, par->minor));
> -+#endif
> -+
> -+#ifdef USE_PROC
> -+ if (p->driver->driver_proc_root)
> -+ remove_proc_entry(p->par->name, lcd_proc_root);
> -+#endif
> -+
> -+ list_del(&p->lcd_list);
> -+ kfree(p);
> -+
> -+ up(&drivers_sem);
> -+
> -+#ifdef MODULE
> -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0)
> -+ module_put(THIS_MODULE);
> -+#else
> -+ MOD_DEC_USE_COUNT;
> -+#endif
> -+#endif
> -+
> -+ return (0);
> -+}
> -+EXPORT_SYMBOL(lcd_unregister_driver);
> -+
> -+
> -+
> -+
> -+
> -+/************************
> -+ * Kernel I/O interface *
> -+ ************************/
> -+/* Exported function */
> -+int lcd_open(unsigned short minor, struct lcd_struct **pp)
> -+{
> -+ int ret;
> -+ struct lcd_struct *p;
> -+
> -+ down(&drivers_sem);
> -+
> -+ if (minor >= minors || (*pp = p = find_lcd_struct(minor)) == NULL) {
> -+ printk(KERN_ERR "LCD: lcd_open failed. Device not found.\n");
> -+ up(&drivers_sem);
> -+ return (-ENODEV);
> -+ }
> -+
> -+ down(&p->lcd_sem);
> -+ up(&drivers_sem);
> -+
> -+ ret = do_lcd_open(p);
> -+
> -+ up(&p->lcd_sem);
> -+
> -+ return (ret);
> -+}
> -+EXPORT_SYMBOL(lcd_open);
> -+
> -+/* Exported function */
> -+int lcd_close(struct lcd_struct **pp)
> -+{
> -+ int ret;
> -+ struct lcd_struct *p;
> -+
> -+ if (! pp || ! (p = *pp)) {
> -+ printk(KERN_ERR "LCD: NULL pointer in lcd_close\n");
> -+ return (-ENODEV);
> -+ }
> -+
> -+ down(&p->lcd_sem);
> -+
> -+ if (! (ret = do_lcd_release(p)))
> -+ *pp = NULL;
> -+
> -+ up(&p->lcd_sem);
> -+
> -+ return (ret);
> -+}
> -+EXPORT_SYMBOL(lcd_close);
> -+
> -+static inline loff_t offset_to_row_col(struct lcd_struct *p, loff_t offset)
> -+{
> -+ unsigned long _offset = offset;
> -+ unsigned int vs_cols = p->par->vs_cols;
> -+
> -+ gotoxy(p, _offset%vs_cols, _offset/vs_cols);
> -+
> -+ return ((p->row*vs_cols)+p->col);
> -+}
> -+
> -+/* Exported function */
> -+ssize_t lcd_read(struct lcd_struct *p, void *bufp, size_t length, loff_t offset, unsigned int with_attr)
> -+{
> -+ ssize_t ret = 0;
> -+
> -+ if (! p) {
> -+ printk(KERN_ERR "LCD: NULL pointer in lcd_read\n");
> -+ return (-ENODEV);
> -+ }
> -+ if (! bufp)
> -+ return (-EFAULT);
> -+ if (offset < 0 || offset >= p->fb_size)
> -+ return (-EINVAL);
> -+
> -+ if (length+offset > p->fb_size)
> -+ length = p->fb_size-offset;
> -+
> -+ if (with_attr)
> -+ set_bit(WITH_ATTR, &p->struct_flags);
> -+
> -+ offset_to_row_col(p, offset);
> -+ ret = do_lcd_read(p, bufp, length);
> -+
> -+ if (with_attr)
> -+ clear_bit(WITH_ATTR, &p->struct_flags);
> -+
> -+ return (ret);
> -+}
> -+EXPORT_SYMBOL(lcd_read);
> -+
> -+/* Exported function */
> -+ssize_t lcd_write(struct lcd_struct *p, const void *bufp, size_t length, loff_t offset, unsigned int with_attr)
> -+{
> -+ ssize_t ret;
> -+
> -+ if (! p) {
> -+ printk(KERN_ERR "LCD: NULL pointer in lcd_write\n");
> -+ return (-ENODEV);
> -+ }
> -+ if (! bufp)
> -+ return (-EFAULT);
> -+ if (offset < 0 || offset >= p->fb_size)
> -+ return (-EINVAL);
> -+
> -+ if (with_attr)
> -+ set_bit(WITH_ATTR, &p->struct_flags);
> -+
> -+ offset_to_row_col(p, offset);
> -+ ret = do_lcd_write(p, bufp, length);
> -+
> -+ if (with_attr)
> -+ clear_bit(WITH_ATTR, &p->struct_flags);
> -+
> -+ return (ret);
> -+}
> -+EXPORT_SYMBOL(lcd_write);
> -+
> -+/* Exported function */
> -+int lcd_ioctl(struct lcd_struct *p, unsigned int cmd, ...)
> -+{
> -+ int ret;
> -+ unsigned long arg;
> -+ va_list ap;
> -+
> -+ if (! p) {
> -+ printk(KERN_ERR "LCD: NULL pointer in lcd_ioctl\n");
> -+ return (-ENODEV);
> -+ }
> -+
> -+ down(&p->lcd_sem);
> -+ va_start(ap, cmd);
> -+ arg = va_arg(ap, unsigned long);
> -+ ret = do_lcd_ioctl(p, cmd, arg);
> -+ va_end(ap);
> -+ up(&p->lcd_sem);
> -+
> -+ return (ret);
> -+}
> -+EXPORT_SYMBOL(lcd_ioctl);
> -+
> -+
> -+
> -+
> -+
> -+/*******************
> -+ * File operations *
> -+ *******************/
> -+static loff_t lcd_fops_llseek(struct file *filp, loff_t offset, int orig)
> -+{
> -+ struct lcd_struct *p;
> -+
> -+ if (! (p = filp->private_data))
> -+ return (-ENODEV);
> -+
> -+ down(&p->lcd_sem);
> -+
> -+ switch (orig) {
> -+ case 0:
> -+ break;
> -+
> -+ case 1:
> -+ offset += filp->f_pos;
> -+ break;
> -+
> -+ default:
> -+ up(&p->lcd_sem);
> -+ return (-EINVAL); /* SEEK_END not supported */
> -+ }
> -+
> -+ if (offset >= 0 && offset < p->fb_size)
> -+ filp->f_pos = offset_to_row_col(p, offset);
> -+ else
> -+ offset = -EINVAL;
> -+
> -+ up(&p->lcd_sem);
> -+
> -+ return (offset);
> -+}
> -+
> -+static ssize_t lcd_fops_read(struct file *filp, char *buffer, size_t length, loff_t *offp)
> -+{
> -+ ssize_t ret = 0;
> -+ char *bufp = buffer;
> -+ struct lcd_struct *p;
> -+
> -+ if (! bufp)
> -+ return (-EFAULT);
> -+ if (! (p = filp->private_data))
> -+ return (-ENODEV);
> -+
> -+ down(&p->lcd_sem);
> -+
> -+ if (*offp < 0 || *offp >= p->fb_size) {
> -+ up(&p->lcd_sem);
> -+ return (-EINVAL);
> -+ }
> -+
> -+ if (test_bit(WITH_ATTR, &p->struct_flags) && (length & 0x01))
> -+ length &= ~0x01;
> -+
> -+ if (length+(*offp) > p->fb_size)
> -+ length = p->fb_size-(*offp);
> -+
> -+ while (length) {
> -+ ret = (length > FLIP_BUF_SIZE ? FLIP_BUF_SIZE : length);
> -+ if (test_bit(WITH_ATTR, &p->struct_flags))
> -+ ret /= sizeof(unsigned short);
> -+ if ((ret = do_lcd_read(p, p->flip_buf, ret)) < 0)
> -+ break;
> -+ if (test_bit(WITH_ATTR, &p->struct_flags))
> -+ ret *= sizeof(unsigned short);
> -+ *offp = (p->row*p->par->vs_cols)+p->col;
> -+ if (copy_to_user(bufp, p->flip_buf, ret)) {
> -+ ret = -EFAULT;
> -+ break;
> -+ }
> -+ length -= ret;
> -+ bufp += ret;
> -+ ret = bufp-buffer;
> -+ if (length)
> -+ schedule();
> -+ }
> -+
> -+ up(&p->lcd_sem);
> -+
> -+ return (ret);
> -+}
> -+
> -+static ssize_t lcd_fops_write(struct file *filp, const char *buffer, size_t length, loff_t *offp)
> -+{
> -+ ssize_t ret = 0;
> -+ const char *bufp = buffer;
> -+ struct lcd_struct *p;
> -+
> -+ if (! bufp)
> -+ return (-EFAULT);
> -+ if (! (p = filp->private_data))
> -+ return (-ENODEV);
> -+
> -+ down(&p->lcd_sem);
> -+
> -+ if (*offp < 0 || *offp >= p->fb_size) {
> -+ up(&p->lcd_sem);
> -+ return (-EINVAL);
> -+ }
> -+
> -+ if (test_bit(WITH_ATTR, &p->struct_flags) && (length & 0x01))
> -+ length &= ~0x01;
> -+
> -+ while (length) {
> -+ ret = (length > FLIP_BUF_SIZE ? FLIP_BUF_SIZE : length);
> -+ if (copy_from_user(p->flip_buf, bufp, ret)) {
> -+ ret = -EFAULT;
> -+ break;
> -+ }
> -+ if (test_bit(WITH_ATTR, &p->struct_flags))
> -+ ret /= sizeof(unsigned short);
> -+ if ((ret = do_lcd_write(p, p->flip_buf, ret)) < 0)
> -+ break;
> -+ if (test_bit(WITH_ATTR, &p->struct_flags))
> -+ ret *= sizeof(unsigned short);
> -+ *offp = (p->row*p->par->vs_cols)+p->col;
> -+ length -= ret;
> -+ bufp += ret;
> -+ ret = bufp-buffer;
> -+ if (length)
> -+ schedule();
> -+ }
> -+
> -+ up(&p->lcd_sem);
> -+
> -+ return (ret);
> -+}
> -+
> -+static int lcd_fops_open(struct inode *inop, struct file *filp)
> -+{
> -+ unsigned short minor;
> -+ int ret;
> -+ struct lcd_struct *p;
> -+
> -+ down(&drivers_sem);
> -+
> -+ if ((minor = MINOR(inop->i_rdev)) >= minors || (filp->private_data = p = find_lcd_struct(minor)) == NULL) {
> -+ up(&drivers_sem);
> -+ return (-ENODEV);
> -+ }
> -+
> -+ down(&p->lcd_sem);
> -+ up(&drivers_sem);
> -+
> -+ ret = do_lcd_open(p);
> -+
> -+ up(&p->lcd_sem);
> -+
> -+ return (ret);
> -+}
> -+
> -+static int lcd_fops_release(struct inode *inop, struct file *filp)
> -+{
> -+ struct lcd_struct *p;
> -+ int ret;
> -+
> -+ if (! (p = filp->private_data))
> -+ return (-ENODEV);
> -+
> -+ down(&p->lcd_sem);
> -+
> -+ if (! (ret = do_lcd_release(p)))
> -+ filp->private_data = NULL;
> -+
> -+ up(&p->lcd_sem);
> -+
> -+ return (ret);
> -+}
> -+
> -+static long lcd_fops_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
> -+{
> -+ struct lcd_struct *p;
> -+ int ret;
> -+
> -+ if (! (p = filp->private_data))
> -+ return (-ENODEV);
> -+
> -+ down(&p->lcd_sem);
> -+
> -+ set_bit(USER_SPACE, &p->struct_flags);
> -+ ret = do_lcd_ioctl(p, cmd, arg);
> -+ clear_bit(USER_SPACE, &p->struct_flags);
> -+
> -+ up(&p->lcd_sem);
> -+
> -+ return (ret);
> -+}
> -+
> -+static struct file_operations lcd_linux_fops = {
> -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 4, 0)
> -+ .owner = THIS_MODULE,
> -+#endif
> -+ .llseek = lcd_fops_llseek,
> -+ .read = lcd_fops_read,
> -+ .write = lcd_fops_write,
> -+ .open = lcd_fops_open,
> -+ .release = lcd_fops_release,
> -+ .unlocked_ioctl = lcd_fops_ioctl,
> -+};
> -+
> -+
> -+
> -+
> -+
> -+/********************************
> -+ * Init/Cleanup driver routines *
> -+ ********************************/
> -+static int do_init_driver(struct lcd_struct *p)
> -+{
> -+ int ret;
> -+ struct lcd_driver *driver = p->driver;
> -+ struct lcd_parameters *par = p->par;
> -+ unsigned int frame_rows = par->cntr_rows*par->num_cntr;
> -+ unsigned int frame_cols = par->cntr_cols;
> -+
> -+ switch (INIT_LEVEL(p)) {
> -+ case 0:
> -+ if (frame_rows == 0 || frame_cols == 0 || ! par->name) {
> -+ printk(KERN_ERR "LCD: wrong lcd parameters\n");
> -+ return (-EINVAL);
> -+ }
> -+ if (driver->validate_driver) {
> -+ if ((ret = driver->validate_driver()) < 0) {
> -+ printk(KERN_ERR "LCD: validate_driver failed\n");
> -+ return (-EINVAL);
> -+ } else if (ret > 0) {
> -+ set_bit(CAN_DO_COLOR, &p->struct_flags);
> -+ p->defcolor = 0x07;
> -+ p->ulcolor = 0x0f;
> -+ p->halfcolor = 0x08;
> -+ }
> -+ }
> -+ default_attr(p);
> -+ update_attr(p);
> -+ p->frame_size = frame_rows*frame_cols;
> -+ if (par->vs_rows < frame_rows)
> -+ par->vs_rows = frame_rows;
> -+ if (par->vs_cols < frame_cols)
> -+ par->vs_cols = frame_cols;
> -+ p->fb_size = par->vs_rows*par->vs_cols;
> -+
> -+ ret = sizeof(short)*p->fb_size;
> -+ ret += sizeof(short)*p->frame_size;
> -+ ret += FLIP_BUF_SIZE;
> -+ ret += (p->driver->charmap ? 256 : 512);
> -+ if (par->cgram_chars*par->cgram_bytes)
> -+ ret += (1+par->cgram_chars)*par->cgram_bytes;
> -+ if ((p->fb = (unsigned short *)vmalloc(ret)) == NULL) {
> -+ printk(KERN_ERR "LCD: memory allocation failed (vmalloc)\n");
> -+ return (-ENOMEM);
> -+ }
> -+ __memset_short(p->fb, p->erase_char, p->fb_size+p->frame_size);
> -+
> -+ p->display = p->fb+p->fb_size;
> -+ p->flip_buf = (unsigned char *)(p->display+p->frame_size);
> -+
> -+ if (! p->driver->charmap) {
> -+ set_bit(NULL_CHARMAP, &p->struct_flags);
> -+ p->driver->charmap = p->flip_buf+FLIP_BUF_SIZE;
> -+ for (ret = 0; ret < 256; ++ret)
> -+ p->driver->charmap[ret] = ret;
> -+ p->s_charmap = p->driver->charmap+256;
> -+ } else
> -+ p->s_charmap = p->flip_buf+FLIP_BUF_SIZE;
> -+ memset(p->s_charmap, 0, 256);
> -+
> -+ if (par->cgram_chars*par->cgram_bytes) {
> -+ p->cgram_buffer = p->s_charmap+256+par->cgram_bytes;
> -+ memset(p->cgram_buffer, 0xff, par->cgram_chars*par->cgram_bytes);
> -+ } else
> -+ p->cgram_buffer = NULL;
> -+ p->driver->cgram_buffer = p->cgram_buffer;
> -+
> -+ p->frame_base = 0;
> -+ p->row = p->col = 0;
> -+ p->top = 0;
> -+ p->bot = par->vs_rows;
> -+ SET_INIT_LEVEL(p, 1);
> -+
> -+ case 1:
> -+ /* Initialize the communication port */
> -+ if ((ret = driver->init_port())) {
> -+ printk(KERN_ERR "LCD: failure while initializing the communication port\n");
> -+ return (ret);
> -+ }
> -+ SET_INIT_LEVEL(p, 2);
> -+
> -+ case 2:
> -+ /* Initialize LCD display */
> -+ if (driver->init_display && (ret = driver->init_display())) {
> -+ printk(KERN_ERR "LCD: failure while initializing the display\n");
> -+ return (ret);
> -+ }
> -+
> -+#ifdef USE_PROC
> -+ /* Create entries in /proc/lcd/"driver" */
> -+ if (driver->driver_proc_root)
> -+ create_driver_proc_entries(p);
> -+#endif
> -+ SET_INIT_LEVEL(p, 3);
> -+ }
> -+
> -+ return (0);
> -+}
> -+
> -+static int do_cleanup_driver(struct lcd_struct *p)
> -+{
> -+ int ret;
> -+ struct lcd_driver *driver = p->driver;
> -+
> -+ switch (INIT_LEVEL(p)) {
> -+ case 3:
> -+#ifdef USE_PROC
> -+ if (driver->driver_proc_root)
> -+ remove_driver_proc_entries(p);
> -+#endif
> -+ if (driver->cleanup_display && (ret = driver->cleanup_display())) {
> -+ printk(KERN_ERR "LCD: failure while cleaning the display\n");
> -+ return (ret);
> -+ }
> -+ SET_INIT_LEVEL(p, 2);
> -+
> -+ case 2:
> -+ if ((ret = driver->cleanup_port())) {
> -+ printk(KERN_ERR "LCD: failure while cleaning the communication port\n");
> -+ return (ret);
> -+ }
> -+ SET_INIT_LEVEL(p, 1);
> -+
> -+ case 1:
> -+ if (test_bit(NULL_CHARMAP, &p->struct_flags)) {
> -+ p->driver->charmap = NULL;
> -+ clear_bit(NULL_CHARMAP, &p->struct_flags);
> -+ }
> -+ vfree(p->fb);
> -+ p->fb = NULL;
> -+ SET_INIT_LEVEL(p, 0);
> -+ }
> -+
> -+ return (0);
> -+}
> -+
> -+static int init_driver(struct lcd_struct *p)
> -+{
> -+ int ret;
> -+
> -+ if ((ret = do_init_driver(p))) {
> -+ do_cleanup_driver(p);
> -+ printk(KERN_ERR "LCD: init_driver failed\n");
> -+ }
> -+
> -+ return (ret);
> -+}
> -+
> -+static int cleanup_driver(struct lcd_struct *p)
> -+{
> -+ int ret;
> -+
> -+ if ((ret = do_cleanup_driver(p))) {
> -+ do_init_driver(p);
> -+ printk(KERN_ERR "LCD: cleanup_driver failed\n");
> -+ }
> -+
> -+ return (ret);
> -+}
> -+
> -+
> -+
> -+
> -+
> -+/********************************
> -+ * Init/Cleanup module routines *
> -+ ********************************/
> -+static int __init lcd_linux_init_module(void)
> -+{
> -+ int ret;
> -+
> -+ if (! minors || minors > 256)
> -+ minors = LCD_MINORS;
> -+
> -+ init_MUTEX(&drivers_sem);
> -+
> -+ if ((ret = register_chrdev(major, LCD_LINUX_STRING, &lcd_linux_fops)) < 0) {
> -+ printk(KERN_ERR "LCD: register_chrdev failed\n");
> -+ return (ret);
> -+ }
> -+ if (major == 0)
> -+ major = ret;
> -+
> -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 13)
> -+ if (IS_ERR((lcd_linux_class = class_create(THIS_MODULE, "lcd")))) {
> -+ ret = PTR_ERR(lcd_linux_class);
> -+ unregister_chrdev(major, LCD_LINUX_STRING);
> -+ return (ret);
> -+ }
> -+#endif
> -+
> -+#ifdef USE_PROC
> -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26)
> -+ if ((lcd_proc_root = proc_mkdir("lcd", NULL)) == NULL)
> -+#else
> -+ if ((lcd_proc_root = proc_mkdir("lcd", &proc_root)) == NULL)
> -+#endif
> -+ printk(KERN_ERR "LCD: cannot create /proc/lcd/\n");
> -+ else if (create_proc_read_entry("drivers", 0, lcd_proc_root, proc_registered_drivers, NULL) == NULL)
> -+ printk(KERN_ERR "LCD: cannot create /proc/lcd/drivers\n");
> -+#endif
> -+
> -+ printk(KERN_INFO "LCD: --> LCD-Linux " LCD_LINUX_VERSION " <--\n");
> -+ printk(KERN_INFO "LCD: --> Mattia Jona-Lasinio <mjona@users.sourceforge.net> <--\n" );
> -+
> -+
> -+ return (0);
> -+}
> -+
> -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 4, 0)
> -+static void __exit lcd_linux_cleanup_module(void)
> -+#else
> -+/* __exit is not defined in 2.2.x kernels */
> -+static void lcd_linux_cleanup_module(void)
> -+#endif
> -+{
> -+#ifdef USE_PROC
> -+ if (lcd_proc_root) {
> -+ remove_proc_entry("drivers", lcd_proc_root);
> -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26)
> -+ remove_proc_entry("lcd", NULL);
> -+#else
> -+ remove_proc_entry("lcd", &proc_root);
> -+#endif
> -+ }
> -+#endif
> -+
> -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 13)
> -+ class_destroy(lcd_linux_class);
> -+#endif
> -+
> -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 23)
> -+ unregister_chrdev(major, LCD_LINUX_STRING);
> -+#else
> -+ if (unregister_chrdev(major, LCD_LINUX_STRING))
> -+ printk(KERN_ERR "LCD: unregister_chrdev failed\n");
> -+#endif
> -+}
> -+
> -+module_init(lcd_linux_init_module)
> -+module_exit(lcd_linux_cleanup_module)
> -diff --git a/include/linux/hd44780.h b/include/linux/hd44780.h
> -new file mode 100644
> -index 0000000..9033d44
> ---- /dev/null
> -+++ b/include/linux/hd44780.h
> -@@ -0,0 +1,47 @@
> -+/* hd44780.h
> -+ *
> -+ * $Id: hd44780.h,v 1.15 2009/03/09 17:59:23 mjona Exp $
> -+ *
> -+ * LCD-Linux:
> -+ * Driver for HD44780 compatible displays connected to the parallel port.
> -+ *
> -+ * HD44780 header file.
> -+ *
> -+ * Copyright (C) 2004 - 2009 Mattia Jona-Lasinio (mjona@users.sourceforge.net)
> -+ *
> -+ * 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 HD44780_H
> -+#define HD44780_H
> -+
> -+#include <linux/lcd-linux.h>
> -+
> -+#define HD44780_VERSION LCD_LINUX_VERSION /* Version number */
> -+#define HD44780_STRING "hd44780"
> -+
> -+#define HD44780_MINOR 0 /* Minor number for the hd44780 driver */
> -+
> -+
> -+/* flags */
> -+#define HD44780_CHECK_BF 0x00000001 /* Do busy flag checking */
> -+#define HD44780_4BITS_BUS 0x00000002 /* Set the bus length to 4 bits */
> -+#define HD44780_5X10_FONT 0x00000004 /* Use 5x10 dots fonts */
> -+
> -+/* IOCTLs */
> -+#define HD44780_READ_AC _IOR(LCD_MAJOR, 0x00, unsigned char *)
> -+
> -+#endif /* HD44780 included */
> -diff --git a/include/linux/lcd-linux.h b/include/linux/lcd-linux.h
> -new file mode 100644
> -index 0000000..1756107
> ---- /dev/null
> -+++ b/include/linux/lcd-linux.h
> -@@ -0,0 +1,158 @@
> -+/* lcd-linux.h
> -+ *
> -+ * $Id: lcd-linux.h,v 1.68 2010/07/04 16:02:02 mjona Exp $
> -+ *
> -+ * Software layer to drive LCD displays under Linux.
> -+ *
> -+ * External interface header file.
> -+ *
> -+ * Copyright (C) 2005 - 2009 Mattia Jona-Lasinio (mjona@users.sourceforge.net)
> -+ *
> -+ * 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 LCD_LINUX_H
> -+#define LCD_LINUX_H
> -+
> -+#ifndef LCD_LINUX_MAIN
> -+#warning
> -+#warning LCD-Linux is still in development stage and
> -+#warning aims at speed and optimization. For these
> -+#warning reasons there is no guarantee of backward
> -+#warning compatibility between different LCD-Linux
> -+#warning versions. Be sure to use the lcd-linux.h
> -+#warning file of the same version as the module.
> -+#warning "http://lcd-linux.sourceforge.net/"
> -+#warning
> -+#endif
> -+
> -+#define LCD_LINUX_VERSION "0.13.9" /* Version number */
> -+#define LCD_LINUX_STRING "lcd"
> -+
> -+#define LCD_MAJOR 120 /* Major number for this device
> -+ * Set this to 0 for dynamic allocation
> -+ */
> -+#define LCD_MINORS 8 /* Minors allocated for LCD-Linux*/
> -+
> -+#include <linux/types.h>
> -+
> -+#define str(s) #s
> -+#define string(s) str(s)
> -+
> -+struct lcd_parameters {
> -+ const char *name; /* Driver's name */
> -+ unsigned long flags; /* Flags (see documentation) */
> -+ unsigned short minor; /* Minor number of the char device */
> -+ unsigned short tabstop; /* Tab character length */
> -+ unsigned short num_cntr; /* Controllers to drive */
> -+ unsigned short cntr_rows; /* Rows per controller */
> -+ unsigned short cntr_cols; /* Display columns */
> -+ unsigned short vs_rows; /* Virtual screen rows */
> -+ unsigned short vs_cols; /* Virtual screen columns */
> -+ unsigned short cgram_chars; /* Number of user definable characters */
> -+ unsigned short cgram_bytes; /* Number of bytes required to define a
> -+ * user definable character */
> -+ unsigned char cgram_char0; /* Ascii of first user definable character */
> -+};
> -+
> -+/* IOCTLs */
> -+#include <asm/ioctl.h>
> -+#define LCDL_SET_PARAM _IOW(LCD_MAJOR, 0x80, struct lcd_parameters *)
> -+#define LCDL_GET_PARAM _IOR(LCD_MAJOR, 0x81, struct lcd_parameters *)
> -+#define LCDL_CHARSUBST _IOW(LCD_MAJOR, 0x82, unsigned char *)
> -+#define LCDL_RAW_MODE _IOW(LCD_MAJOR, 0x83, unsigned int)
> -+#define LCDL_RESET_CHARMAP _IO(LCD_MAJOR, 0x84)
> -+#define LCDL_SAVE_CHARMAP _IO(LCD_MAJOR, 0x85)
> -+#define LCDL_RESTORE_CHARMAP _IO(LCD_MAJOR, 0x86)
> -+#define LCDL_SWAP_CHARMAP _IO(LCD_MAJOR, 0x87)
> -+#define LCDL_CLEAR_DISP _IO(LCD_MAJOR, 0x88)
> -+#define LCDL_SET_CGRAM_CHAR _IOW(LCD_MAJOR, 0x89, unsigned char *)
> -+#define LCDL_GET_CGRAM_CHAR _IOR(LCD_MAJOR, 0x8a, unsigned char *)
> -+#define LCDL_SET_CHARMAP _IOW(LCD_MAJOR, 0x8b, unsigned char *)
> -+#define LCDL_GET_CHARMAP _IOR(LCD_MAJOR, 0x8c, unsigned char *)
> -+#define LCDL_MEMSET _IOW(LCD_MAJOR, 0x8d, unsigned int *)
> -+#define LCDL_MEMMOVE _IOW(LCD_MAJOR, 0x8e, unsigned int *)
> -+#define LCDL_IOATTR _IOW(LCD_MAJOR, 0x8f, unsigned int)
> -+
> -+
> -+
> -+#ifdef __KERNEL__ /* The rest is for kernel only */
> -+
> -+#include <linux/kernel.h>
> -+#include <linux/module.h>
> -+
> -+
> -+struct lcd_driver {
> -+ void (*read_char)(unsigned int offset, unsigned short *data);
> -+ void (*read_cgram_char)(unsigned char index, unsigned char *pixmap);
> -+ void (*write_char)(unsigned int offset, unsigned short data);
> -+ void (*write_cgram_char)(unsigned char index, unsigned char *pixmap);
> -+ void (*clear_display)(void);
> -+ void (*address_mode)(int mode);
> -+ int (*validate_driver)(void);
> -+ int (*init_display)(void);
> -+ int (*cleanup_display)(void);
> -+ int (*init_port)(void);
> -+ int (*cleanup_port)(void);
> -+ int (*handle_custom_char)(unsigned int data);
> -+ int (*handle_custom_ioctl)(unsigned int cmd, unsigned long arg, unsigned int arg_in_userspace);
> -+
> -+ /* The character map to be used */
> -+ unsigned char *charmap;
> -+
> -+ /* Buffer for CGRAM operations.
> -+ * Will be filled by the lcd-linux layer.
> -+ */
> -+ unsigned char *cgram_buffer;
> -+
> -+ /* The root where the driver can create its own proc files.
> -+ * Will be filled by the lcd-linux layer.
> -+ */
> -+ struct proc_dir_entry *driver_proc_root;
> -+
> -+ /* Set this field to 'driver_module_init' or call lcd_driver_setup
> -+ * just before registering the driver with lcd_register_driver.
> -+ */
> -+ struct module *driver_module;
> -+};
> -+
> -+#ifdef MODULE
> -+#define driver_module_init THIS_MODULE
> -+#else
> -+#define driver_module_init NULL
> -+#endif
> -+
> -+/* Always call lcd_driver_setup just before registering the driver
> -+ * with lcd_register_driver.
> -+ */
> -+static inline void lcd_driver_setup(struct lcd_driver *p)
> -+{
> -+ p->driver_module = driver_module_init;
> -+}
> -+
> -+/* External interface */
> -+struct lcd_struct;
> -+int lcd_register_driver(struct lcd_driver *drv, struct lcd_parameters *par);
> -+int lcd_unregister_driver(struct lcd_driver *drv, struct lcd_parameters *par);
> -+int lcd_open(unsigned short minor, struct lcd_struct **lcd);
> -+int lcd_close(struct lcd_struct **lcd);
> -+int lcd_ioctl(struct lcd_struct *lcd, unsigned int cmd, ...);
> -+ssize_t lcd_write(struct lcd_struct *lcd, const void *buffer, size_t length, loff_t offset, unsigned int with_attr);
> -+ssize_t lcd_read(struct lcd_struct *lcd, void *buffer, size_t length, loff_t offset, unsigned int with_attr);
> -+
> -+#endif /* __KERNEL__ */
> -+
> -+#endif /* External interface included */
> ---
> -1.7.0.4
> -
> diff --git a/recipes/linux/linux-2.6.36/ts72xx/0024-ts72xx-add-GPIO-keys.patch b/recipes/linux/linux-2.6.36/ts72xx/0024-ts72xx-add-GPIO-keys.patch
> deleted file mode 100644
> index dc345fa..0000000
> --- a/recipes/linux/linux-2.6.36/ts72xx/0024-ts72xx-add-GPIO-keys.patch
> +++ /dev/null
> @@ -1,100 +0,0 @@
> -From f483d4e7564786a26343900277ee9ebd2405217e Mon Sep 17 00:00:00 2001
> -From: =?UTF-8?q?Petr=20=C5=A0tetiar?= <ynezz@true.cz>
> -Date: Sun, 7 Nov 2010 18:34:39 +0100
> -Subject: [PATCH 24/24] ts72xx: add GPIO keys
> -MIME-Version: 1.0
> -Content-Type: text/plain; charset=UTF-8
> -Content-Transfer-Encoding: 8bit
> -
> -Signed-off-by: Petr Štetiar <ynezz@true.cz>
> ----
> - arch/arm/mach-ep93xx/Kconfig | 6 ++++++
> - arch/arm/mach-ep93xx/ts72xx.c | 36 ++++++++++++++++++++++++++++++++++++
> - 2 files changed, 42 insertions(+), 0 deletions(-)
> -
> -diff --git a/arch/arm/mach-ep93xx/Kconfig b/arch/arm/mach-ep93xx/Kconfig
> -index 2bfb01e..185c5a9 100644
> ---- a/arch/arm/mach-ep93xx/Kconfig
> -+++ b/arch/arm/mach-ep93xx/Kconfig
> -@@ -219,6 +219,12 @@ config MACH_TS72XX_SBCINFO
> - Say 'Y' to add a procfs entry containing some information
> - related to Technologic Systems TS-72xx SBC.
> -
> -+config MACH_TS72XX_GPIO_KEYS
> -+ bool "Enable GPIO keys"
> -+ depends on MACH_TS72XX
> -+ help
> -+ Say 'Y' here to enable GPIO keys on DIO connector.
> -+ Current config is KEY_UP for DIO_1 and KEY_DOWN for DIO_2.
> - endmenu
> -
> - endif
> -diff --git a/arch/arm/mach-ep93xx/ts72xx.c b/arch/arm/mach-ep93xx/ts72xx.c
> -index 0c07bd8..f7b82dd 100644
> ---- a/arch/arm/mach-ep93xx/ts72xx.c
> -+++ b/arch/arm/mach-ep93xx/ts72xx.c
> -@@ -21,11 +21,13 @@
> - #include <linux/mtd/partitions.h>
> - #include <linux/mtd/physmap.h>
> - #include <linux/gpio.h>
> -+#include <linux/gpio_keys.h>
> - #include <linux/i2c.h>
> - #include <linux/i2c-gpio.h>
> - #include <linux/mtd/nand.h>
> - #include <linux/mtd/partitions.h>
> - #include <linux/spi/spi.h>
> -+#include <linux/input.h>
> -
> - #include <mach/ep93xx_spi.h>
> - #include <mach/hardware.h>
> -@@ -437,6 +439,36 @@ static struct ep93xx_spi_info ts72xx_spi_info = {
> - };
> - #endif
> -
> -+#if defined(CONFIG_MACH_TS72XX_GPIO_KEYS)
> -+#define INIT_KEY(_code, _gpio, _desc) \
> -+ { \
> -+ .code = KEY_##_code, \
> -+ .gpio = _gpio, \
> -+ .desc = _desc, \
> -+ .wakeup = 1, \
> -+ .active_low = 1, \
> -+ .type = EV_KEY, \
> -+ }
> -+
> -+static struct gpio_keys_button ts72xx_button_table[] = {
> -+ INIT_KEY(UP, EP93XX_GPIO_LINE_EGPIO11, "Up button - DIO_2"),
> -+ INIT_KEY(DOWN, EP93XX_GPIO_LINE_EGPIO12, "Down button - DIO_3"),
> -+};
> -+
> -+static struct gpio_keys_platform_data gpio_keys_data = {
> -+ .buttons = ts72xx_button_table,
> -+ .nbuttons = ARRAY_SIZE(ts72xx_button_table),
> -+};
> -+
> -+static struct platform_device ts72xx_gpio_keys = {
> -+ .name = "gpio-keys",
> -+ .dev = {
> -+ .platform_data = &gpio_keys_data,
> -+ },
> -+ .id = -1,
> -+};
> -+#endif
> -+
> - static void __init ts72xx_init_machine(void)
> - {
> - ep93xx_init_devices();
> -@@ -445,6 +477,10 @@ static void __init ts72xx_init_machine(void)
> - platform_device_register(&ts72xx_rtc_device);
> - platform_device_register(&ts72xx_wdt_device);
> -
> -+#if defined(CONFIG_MACH_TS72XX_GPIO_KEYS)
> -+ platform_device_register(&ts72xx_gpio_keys);
> -+#endif
> -+
> - ep93xx_register_eth(&ts72xx_eth_data, 1);
> - ep93xx_register_i2c(&ts72xx_i2c_gpio_data,
> - ts72xx_i2c_board_info,
> ---
> -1.7.0.4
> -
> diff --git a/recipes/linux/linux-2.6.36/ts72xx/defconfig b/recipes/linux/linux-2.6.36/ts72xx/defconfig
> deleted file mode 100644
> index 37f95f6..0000000
> --- a/recipes/linux/linux-2.6.36/ts72xx/defconfig
> +++ /dev/null
> @@ -1,2127 +0,0 @@
> -#
> -# Automatically generated make config: don't edit
> -# Linux kernel version: 2.6.36
> -# Thu Nov 18 20:05:41 2010
> -#
> -CONFIG_ARM=y
> -CONFIG_SYS_SUPPORTS_APM_EMULATION=y
> -CONFIG_GENERIC_GPIO=y
> -CONFIG_ARCH_USES_GETTIMEOFFSET=y
> -CONFIG_HAVE_PROC_CPU=y
> -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_GENERIC_HWEIGHT=y
> -CONFIG_GENERIC_CALIBRATE_DELAY=y
> -CONFIG_NEED_DMA_MAP_STATE=y
> -CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
> -CONFIG_VECTORS_BASE=0xffff0000
> -CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
> -CONFIG_CONSTRUCTORS=y
> -
> -#
> -# General setup
> -#
> -CONFIG_EXPERIMENTAL=y
> -CONFIG_BROKEN_ON_SMP=y
> -CONFIG_LOCK_KERNEL=y
> -CONFIG_INIT_ENV_ARG_LIMIT=32
> -CONFIG_CROSS_COMPILE=""
> -CONFIG_LOCALVERSION=""
> -# CONFIG_LOCALVERSION_AUTO is not set
> -CONFIG_HAVE_KERNEL_GZIP=y
> -CONFIG_HAVE_KERNEL_LZMA=y
> -CONFIG_HAVE_KERNEL_LZO=y
> -CONFIG_KERNEL_GZIP=y
> -# CONFIG_KERNEL_LZMA is not set
> -# CONFIG_KERNEL_LZO is not set
> -CONFIG_SWAP=y
> -CONFIG_SYSVIPC=y
> -CONFIG_SYSVIPC_SYSCTL=y
> -CONFIG_POSIX_MQUEUE=y
> -CONFIG_POSIX_MQUEUE_SYSCTL=y
> -# CONFIG_BSD_PROCESS_ACCT is not set
> -# CONFIG_TASKSTATS is not set
> -# CONFIG_AUDIT is not set
> -
> -#
> -# RCU Subsystem
> -#
> -CONFIG_TREE_RCU=y
> -# CONFIG_TREE_PREEMPT_RCU is not set
> -# CONFIG_TINY_RCU is not set
> -# CONFIG_RCU_TRACE is not set
> -CONFIG_RCU_FANOUT=32
> -# CONFIG_RCU_FANOUT_EXACT is not set
> -# CONFIG_TREE_RCU_TRACE is not set
> -CONFIG_IKCONFIG=y
> -CONFIG_IKCONFIG_PROC=y
> -CONFIG_LOG_BUF_SHIFT=16
> -# CONFIG_CGROUPS is not set
> -# CONFIG_SYSFS_DEPRECATED_V2 is not set
> -CONFIG_RELAY=y
> -CONFIG_NAMESPACES=y
> -# CONFIG_UTS_NS is not set
> -CONFIG_IPC_NS=y
> -# CONFIG_USER_NS is not set
> -# CONFIG_PID_NS is not set
> -# CONFIG_NET_NS is not set
> -# CONFIG_BLK_DEV_INITRD is not set
> -# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
> -CONFIG_SYSCTL=y
> -CONFIG_ANON_INODES=y
> -CONFIG_EMBEDDED=y
> -CONFIG_UID16=y
> -CONFIG_SYSCTL_SYSCALL=y
> -CONFIG_KALLSYMS=y
> -# CONFIG_KALLSYMS_EXTRA_PASS is not set
> -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_HAVE_PERF_EVENTS=y
> -CONFIG_PERF_USE_VMALLOC=y
> -
> -#
> -# Kernel Performance Events And Counters
> -#
> -# CONFIG_PERF_EVENTS is not set
> -# CONFIG_PERF_COUNTERS is not set
> -CONFIG_VM_EVENT_COUNTERS=y
> -# CONFIG_COMPAT_BRK is not set
> -CONFIG_SLAB=y
> -# CONFIG_SLUB is not set
> -# CONFIG_SLOB is not set
> -# CONFIG_PROFILING is not set
> -CONFIG_HAVE_OPROFILE=y
> -# CONFIG_KPROBES is not set
> -CONFIG_HAVE_KPROBES=y
> -CONFIG_HAVE_KRETPROBES=y
> -CONFIG_HAVE_REGS_AND_STACK_ACCESS_API=y
> -CONFIG_HAVE_CLK=y
> -
> -#
> -# GCOV-based kernel profiling
> -#
> -CONFIG_HAVE_GENERIC_DMA_COHERENT=y
> -CONFIG_SLABINFO=y
> -CONFIG_RT_MUTEXES=y
> -CONFIG_BASE_SMALL=0
> -CONFIG_MODULES=y
> -# CONFIG_MODULE_FORCE_LOAD is not set
> -CONFIG_MODULE_UNLOAD=y
> -CONFIG_MODULE_FORCE_UNLOAD=y
> -CONFIG_MODVERSIONS=y
> -# CONFIG_MODULE_SRCVERSION_ALL is not set
> -CONFIG_BLOCK=y
> -CONFIG_LBDAF=y
> -CONFIG_BLK_DEV_BSG=y
> -# CONFIG_BLK_DEV_INTEGRITY is not set
> -
> -#
> -# IO Schedulers
> -#
> -CONFIG_IOSCHED_NOOP=y
> -CONFIG_IOSCHED_DEADLINE=m
> -CONFIG_IOSCHED_CFQ=y
> -CONFIG_DEFAULT_CFQ=y
> -# CONFIG_DEFAULT_NOOP is not set
> -CONFIG_DEFAULT_IOSCHED="cfq"
> -# CONFIG_INLINE_SPIN_TRYLOCK is not set
> -# CONFIG_INLINE_SPIN_TRYLOCK_BH is not set
> -# CONFIG_INLINE_SPIN_LOCK is not set
> -# CONFIG_INLINE_SPIN_LOCK_BH is not set
> -# CONFIG_INLINE_SPIN_LOCK_IRQ is not set
> -# CONFIG_INLINE_SPIN_LOCK_IRQSAVE is not set
> -# CONFIG_INLINE_SPIN_UNLOCK is not set
> -# CONFIG_INLINE_SPIN_UNLOCK_BH is not set
> -# CONFIG_INLINE_SPIN_UNLOCK_IRQ is not set
> -# CONFIG_INLINE_SPIN_UNLOCK_IRQRESTORE is not set
> -# CONFIG_INLINE_READ_TRYLOCK is not set
> -# CONFIG_INLINE_READ_LOCK is not set
> -# CONFIG_INLINE_READ_LOCK_BH is not set
> -# CONFIG_INLINE_READ_LOCK_IRQ is not set
> -# CONFIG_INLINE_READ_LOCK_IRQSAVE is not set
> -# CONFIG_INLINE_READ_UNLOCK is not set
> -# CONFIG_INLINE_READ_UNLOCK_BH is not set
> -# CONFIG_INLINE_READ_UNLOCK_IRQ is not set
> -# CONFIG_INLINE_READ_UNLOCK_IRQRESTORE is not set
> -# CONFIG_INLINE_WRITE_TRYLOCK is not set
> -# CONFIG_INLINE_WRITE_LOCK is not set
> -# CONFIG_INLINE_WRITE_LOCK_BH is not set
> -# CONFIG_INLINE_WRITE_LOCK_IRQ is not set
> -# CONFIG_INLINE_WRITE_LOCK_IRQSAVE is not set
> -# CONFIG_INLINE_WRITE_UNLOCK is not set
> -# CONFIG_INLINE_WRITE_UNLOCK_BH is not set
> -# CONFIG_INLINE_WRITE_UNLOCK_IRQ is not set
> -# CONFIG_INLINE_WRITE_UNLOCK_IRQRESTORE is not set
> -# CONFIG_MUTEX_SPIN_ON_OWNER is not set
> -# CONFIG_FREEZER is not set
> -
> -#
> -# System Type
> -#
> -CONFIG_MMU=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_VEXPRESS is not set
> -# CONFIG_ARCH_AT91 is not set
> -# CONFIG_ARCH_BCMRING is not set
> -# CONFIG_ARCH_CLPS711X is not set
> -# CONFIG_ARCH_CNS3XXX is not set
> -# CONFIG_ARCH_GEMINI is not set
> -# CONFIG_ARCH_EBSA110 is not set
> -CONFIG_ARCH_EP93XX=y
> -# CONFIG_ARCH_FOOTBRIDGE is not set
> -# CONFIG_ARCH_MXC is not set
> -# CONFIG_ARCH_STMP3XXX is not set
> -# CONFIG_ARCH_NETX is not set
> -# CONFIG_ARCH_H720X 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_DOVE is not set
> -# CONFIG_ARCH_KIRKWOOD is not set
> -# CONFIG_ARCH_LOKI is not set
> -# CONFIG_ARCH_LPC32XX is not set
> -# CONFIG_ARCH_MV78XX0 is not set
> -# CONFIG_ARCH_ORION5X is not set
> -# CONFIG_ARCH_MMP is not set
> -# CONFIG_ARCH_KS8695 is not set
> -# CONFIG_ARCH_NS9XXX is not set
> -# CONFIG_ARCH_W90X900 is not set
> -# CONFIG_ARCH_NUC93X is not set
> -# CONFIG_ARCH_TEGRA is not set
> -# CONFIG_ARCH_PNX4008 is not set
> -# CONFIG_ARCH_PXA is not set
> -# CONFIG_ARCH_MSM is not set
> -# CONFIG_ARCH_SHMOBILE is not set
> -# CONFIG_ARCH_RPC is not set
> -# CONFIG_ARCH_SA1100 is not set
> -# CONFIG_ARCH_S3C2410 is not set
> -# CONFIG_ARCH_S3C64XX is not set
> -# CONFIG_ARCH_S5P6440 is not set
> -# CONFIG_ARCH_S5P6442 is not set
> -# CONFIG_ARCH_S5PC100 is not set
> -# CONFIG_ARCH_S5PV210 is not set
> -# CONFIG_ARCH_S5PV310 is not set
> -# CONFIG_ARCH_SHARK is not set
> -# CONFIG_ARCH_LH7A40X is not set
> -# CONFIG_ARCH_U300 is not set
> -# CONFIG_ARCH_U8500 is not set
> -# CONFIG_ARCH_NOMADIK is not set
> -# CONFIG_ARCH_DAVINCI is not set
> -# CONFIG_ARCH_OMAP is not set
> -# CONFIG_PLAT_SPEAR is not set
> -
> -#
> -# Cirrus EP93xx Implementation Options
> -#
> -# CONFIG_CRUNCH is not set
> -CONFIG_CR1_NFBIT=y
> -
> -#
> -# EP93xx Platforms
> -#
> -CONFIG_EP93XX_SDCE3_SYNC_PHYS_OFFSET=y
> -# CONFIG_EP93XX_SDCE0_PHYS_OFFSET is not set
> -# CONFIG_EP93XX_SDCE1_PHYS_OFFSET is not set
> -# CONFIG_EP93XX_SDCE2_PHYS_OFFSET is not set
> -# CONFIG_EP93XX_SDCE3_ASYNC_PHYS_OFFSET is not set
> -# CONFIG_MACH_ADSSPHERE is not set
> -# CONFIG_MACH_EDB9301 is not set
> -# CONFIG_MACH_EDB9302 is not set
> -# CONFIG_MACH_EDB9307 is not set
> -# CONFIG_MACH_EDB9312 is not set
> -# CONFIG_MACH_EDB9315 is not set
> -# CONFIG_MACH_GESBC9312 is not set
> -# CONFIG_MACH_MICRO9H is not set
> -# CONFIG_MACH_MICRO9L is not set
> -CONFIG_MACH_TS72XX=y
> -CONFIG_EP93XX_EARLY_UART1=y
> -# CONFIG_EP93XX_EARLY_UART2 is not set
> -# CONFIG_EP93XX_EARLY_UART3 is not set
> -CONFIG_MACH_TS72XX_FORCE_MACHINEID=y
> -CONFIG_MACH_TS72XX_SBCINFO=m
> -CONFIG_MACH_TS72XX_GPIO_KEYS=y
> -
> -#
> -# Processor Type
> -#
> -CONFIG_CPU_ARM920T=y
> -CONFIG_CPU_32v4T=y
> -CONFIG_CPU_ABRT_EV4T=y
> -CONFIG_CPU_PABRT_LEGACY=y
> -CONFIG_CPU_CACHE_V4WT=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_ARM_L1_CACHE_SHIFT=5
> -CONFIG_ARM_VIC=y
> -CONFIG_ARM_VIC_NR=2
> -CONFIG_COMMON_CLKDEV=y
> -
> -#
> -# 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_NONE is not set
> -# CONFIG_PREEMPT_VOLUNTARY is not set
> -CONFIG_PREEMPT=y
> -CONFIG_HZ=100
> -CONFIG_AEABI=y
> -# CONFIG_OABI_COMPAT is not set
> -CONFIG_ARCH_HAS_HOLES_MEMORYMODEL=y
> -CONFIG_ARCH_SPARSEMEM_ENABLE=y
> -CONFIG_ARCH_SPARSEMEM_DEFAULT=y
> -CONFIG_ARCH_SELECT_MEMORY_MODEL=y
> -# CONFIG_HIGHMEM is not set
> -# CONFIG_SPARSE_IRQ is not set
> -CONFIG_SELECT_MEMORY_MODEL=y
> -CONFIG_SPARSEMEM_MANUAL=y
> -CONFIG_SPARSEMEM=y
> -CONFIG_HAVE_MEMORY_PRESENT=y
> -CONFIG_SPARSEMEM_EXTREME=y
> -CONFIG_HAVE_MEMBLOCK=y
> -CONFIG_SPLIT_PTLOCK_CPUS=999999
> -# CONFIG_PHYS_ADDR_T_64BIT is not set
> -CONFIG_ZONE_DMA_FLAG=0
> -CONFIG_VIRT_TO_BUS=y
> -# CONFIG_KSM is not set
> -CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
> -CONFIG_FORCE_MAX_ZONEORDER=11
> -CONFIG_ALIGNMENT_TRAP=y
> -# CONFIG_UACCESS_WITH_MEMCPY is not set
> -# CONFIG_CC_STACKPROTECTOR is not set
> -# CONFIG_DEPRECATED_PARAM_STRUCT is not set
> -
> -#
> -# Boot options
> -#
> -CONFIG_ZBOOT_ROM_TEXT=0
> -CONFIG_ZBOOT_ROM_BSS=0
> -CONFIG_CMDLINE=" debug "
> -# CONFIG_CMDLINE_FORCE is not set
> -# CONFIG_XIP_KERNEL is not set
> -CONFIG_KEXEC=y
> -CONFIG_ATAGS_PROC=y
> -# CONFIG_AUTO_ZRELADDR is not set
> -
> -#
> -# CPU Power Management
> -#
> -# CONFIG_CPU_IDLE is not set
> -
> -#
> -# Floating point emulation
> -#
> -
> -#
> -# At least one emulation must be selected
> -#
> -
> -#
> -# Userspace binary formats
> -#
> -CONFIG_BINFMT_ELF=y
> -# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
> -CONFIG_HAVE_AOUT=y
> -# CONFIG_BINFMT_AOUT is not set
> -CONFIG_BINFMT_MISC=m
> -
> -#
> -# Power management options
> -#
> -# CONFIG_PM is not set
> -CONFIG_ARCH_SUSPEND_POSSIBLE=y
> -CONFIG_NET=y
> -
> -#
> -# Networking options
> -#
> -CONFIG_PACKET=y
> -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=m
> -# CONFIG_NET_KEY_MIGRATE is not set
> -CONFIG_INET=y
> -# CONFIG_IP_MULTICAST is not set
> -CONFIG_IP_ADVANCED_ROUTER=y
> -CONFIG_ASK_IP_FIB_HASH=y
> -# CONFIG_IP_FIB_TRIE is not set
> -CONFIG_IP_FIB_HASH=y
> -# CONFIG_IP_MULTIPLE_TABLES is not set
> -# CONFIG_IP_ROUTE_MULTIPATH is not set
> -CONFIG_IP_ROUTE_VERBOSE=y
> -CONFIG_IP_PNP=y
> -CONFIG_IP_PNP_DHCP=y
> -# CONFIG_IP_PNP_BOOTP is not set
> -# CONFIG_IP_PNP_RARP is not set
> -CONFIG_NET_IPIP=m
> -CONFIG_NET_IPGRE=m
> -# CONFIG_ARPD is not set
> -CONFIG_SYN_COOKIES=y
> -CONFIG_INET_AH=m
> -CONFIG_INET_ESP=m
> -CONFIG_INET_IPCOMP=m
> -CONFIG_INET_XFRM_TUNNEL=m
> -CONFIG_INET_TUNNEL=m
> -CONFIG_INET_XFRM_MODE_TRANSPORT=m
> -CONFIG_INET_XFRM_MODE_TUNNEL=m
> -CONFIG_INET_XFRM_MODE_BEET=m
> -# CONFIG_INET_LRO is not set
> -# CONFIG_INET_DIAG is not set
> -# 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 is not set
> -CONFIG_IPV6_SIT=m
> -# CONFIG_IPV6_SIT_6RD is not set
> -CONFIG_IPV6_NDISC_NODETYPE=y
> -CONFIG_IPV6_TUNNEL=m
> -# CONFIG_IPV6_MULTIPLE_TABLES is not set
> -# CONFIG_IPV6_MROUTE is not set
> -# CONFIG_NETLABEL is not set
> -CONFIG_NETWORK_SECMARK=y
> -# CONFIG_NETWORK_PHY_TIMESTAMPING is not set
> -CONFIG_NETFILTER=y
> -# CONFIG_NETFILTER_DEBUG is not set
> -CONFIG_NETFILTER_ADVANCED=y
> -
> -#
> -# Core Netfilter Configuration
> -#
> -CONFIG_NETFILTER_NETLINK=m
> -CONFIG_NETFILTER_NETLINK_QUEUE=m
> -CONFIG_NETFILTER_NETLINK_LOG=m
> -CONFIG_NF_CONNTRACK=m
> -CONFIG_NF_CONNTRACK_MARK=y
> -CONFIG_NF_CONNTRACK_SECMARK=y
> -CONFIG_NF_CONNTRACK_ZONES=y
> -CONFIG_NF_CONNTRACK_EVENTS=y
> -CONFIG_NF_CT_PROTO_DCCP=m
> -CONFIG_NF_CT_PROTO_GRE=m
> -CONFIG_NF_CT_PROTO_SCTP=m
> -CONFIG_NF_CT_PROTO_UDPLITE=m
> -CONFIG_NF_CONNTRACK_AMANDA=m
> -CONFIG_NF_CONNTRACK_FTP=m
> -CONFIG_NF_CONNTRACK_H323=m
> -CONFIG_NF_CONNTRACK_IRC=m
> -CONFIG_NF_CONNTRACK_NETBIOS_NS=m
> -CONFIG_NF_CONNTRACK_PPTP=m
> -CONFIG_NF_CONNTRACK_SANE=m
> -CONFIG_NF_CONNTRACK_SIP=m
> -CONFIG_NF_CONNTRACK_TFTP=m
> -CONFIG_NF_CT_NETLINK=m
> -# CONFIG_NETFILTER_TPROXY is not set
> -CONFIG_NETFILTER_XTABLES=m
> -
> -#
> -# Xtables combined modules
> -#
> -CONFIG_NETFILTER_XT_MARK=m
> -CONFIG_NETFILTER_XT_CONNMARK=m
> -
> -#
> -# Xtables targets
> -#
> -# CONFIG_NETFILTER_XT_TARGET_CHECKSUM is not set
> -CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m
> -CONFIG_NETFILTER_XT_TARGET_CONNMARK=m
> -CONFIG_NETFILTER_XT_TARGET_CONNSECMARK=m
> -CONFIG_NETFILTER_XT_TARGET_CT=m
> -CONFIG_NETFILTER_XT_TARGET_DSCP=m
> -CONFIG_NETFILTER_XT_TARGET_HL=m
> -# CONFIG_NETFILTER_XT_TARGET_IDLETIMER is not set
> -CONFIG_NETFILTER_XT_TARGET_LED=m
> -CONFIG_NETFILTER_XT_TARGET_MARK=m
> -CONFIG_NETFILTER_XT_TARGET_NFLOG=m
> -CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m
> -CONFIG_NETFILTER_XT_TARGET_NOTRACK=m
> -CONFIG_NETFILTER_XT_TARGET_RATEEST=m
> -# CONFIG_NETFILTER_XT_TARGET_TEE is not set
> -CONFIG_NETFILTER_XT_TARGET_TRACE=m
> -CONFIG_NETFILTER_XT_TARGET_SECMARK=m
> -CONFIG_NETFILTER_XT_TARGET_TCPMSS=m
> -CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP=m
> -
> -#
> -# Xtables matches
> -#
> -CONFIG_NETFILTER_XT_MATCH_CLUSTER=m
> -CONFIG_NETFILTER_XT_MATCH_COMMENT=m
> -CONFIG_NETFILTER_XT_MATCH_CONNBYTES=m
> -CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=m
> -CONFIG_NETFILTER_XT_MATCH_CONNMARK=m
> -CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m
> -# CONFIG_NETFILTER_XT_MATCH_CPU is not set
> -CONFIG_NETFILTER_XT_MATCH_DCCP=m
> -CONFIG_NETFILTER_XT_MATCH_DSCP=m
> -CONFIG_NETFILTER_XT_MATCH_ESP=m
> -CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=m
> -CONFIG_NETFILTER_XT_MATCH_HELPER=m
> -CONFIG_NETFILTER_XT_MATCH_HL=m
> -CONFIG_NETFILTER_XT_MATCH_IPRANGE=m
> -CONFIG_NETFILTER_XT_MATCH_LENGTH=m
> -CONFIG_NETFILTER_XT_MATCH_LIMIT=m
> -CONFIG_NETFILTER_XT_MATCH_MAC=m
> -CONFIG_NETFILTER_XT_MATCH_MARK=m
> -CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m
> -CONFIG_NETFILTER_XT_MATCH_OSF=m
> -CONFIG_NETFILTER_XT_MATCH_OWNER=m
> -CONFIG_NETFILTER_XT_MATCH_POLICY=m
> -CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m
> -CONFIG_NETFILTER_XT_MATCH_QUOTA=m
> -CONFIG_NETFILTER_XT_MATCH_RATEEST=m
> -CONFIG_NETFILTER_XT_MATCH_REALM=m
> -CONFIG_NETFILTER_XT_MATCH_RECENT=m
> -CONFIG_NETFILTER_XT_MATCH_SCTP=m
> -CONFIG_NETFILTER_XT_MATCH_STATE=m
> -CONFIG_NETFILTER_XT_MATCH_STATISTIC=m
> -CONFIG_NETFILTER_XT_MATCH_STRING=m
> -CONFIG_NETFILTER_XT_MATCH_TCPMSS=m
> -CONFIG_NETFILTER_XT_MATCH_TIME=m
> -CONFIG_NETFILTER_XT_MATCH_U32=m
> -# CONFIG_IP_VS is not set
> -
> -#
> -# IP: Netfilter Configuration
> -#
> -CONFIG_NF_DEFRAG_IPV4=m
> -CONFIG_NF_CONNTRACK_IPV4=m
> -CONFIG_NF_CONNTRACK_PROC_COMPAT=y
> -CONFIG_IP_NF_QUEUE=m
> -CONFIG_IP_NF_IPTABLES=m
> -CONFIG_IP_NF_MATCH_ADDRTYPE=m
> -CONFIG_IP_NF_MATCH_AH=m
> -CONFIG_IP_NF_MATCH_ECN=m
> -CONFIG_IP_NF_MATCH_TTL=m
> -CONFIG_IP_NF_FILTER=m
> -CONFIG_IP_NF_TARGET_REJECT=m
> -CONFIG_IP_NF_TARGET_LOG=m
> -CONFIG_IP_NF_TARGET_ULOG=m
> -CONFIG_NF_NAT=m
> -CONFIG_NF_NAT_NEEDED=y
> -CONFIG_IP_NF_TARGET_MASQUERADE=m
> -CONFIG_IP_NF_TARGET_NETMAP=m
> -CONFIG_IP_NF_TARGET_REDIRECT=m
> -CONFIG_NF_NAT_SNMP_BASIC=m
> -CONFIG_NF_NAT_PROTO_DCCP=m
> -CONFIG_NF_NAT_PROTO_GRE=m
> -CONFIG_NF_NAT_PROTO_UDPLITE=m
> -CONFIG_NF_NAT_PROTO_SCTP=m
> -CONFIG_NF_NAT_FTP=m
> -CONFIG_NF_NAT_IRC=m
> -CONFIG_NF_NAT_TFTP=m
> -CONFIG_NF_NAT_AMANDA=m
> -CONFIG_NF_NAT_PPTP=m
> -CONFIG_NF_NAT_H323=m
> -CONFIG_NF_NAT_SIP=m
> -CONFIG_IP_NF_MANGLE=m
> -CONFIG_IP_NF_TARGET_CLUSTERIP=m
> -CONFIG_IP_NF_TARGET_ECN=m
> -CONFIG_IP_NF_TARGET_TTL=m
> -CONFIG_IP_NF_RAW=m
> -CONFIG_IP_NF_SECURITY=m
> -CONFIG_IP_NF_ARPTABLES=m
> -CONFIG_IP_NF_ARPFILTER=m
> -CONFIG_IP_NF_ARP_MANGLE=m
> -
> -#
> -# IPv6: Netfilter Configuration
> -#
> -CONFIG_NF_CONNTRACK_IPV6=m
> -CONFIG_IP6_NF_QUEUE=m
> -CONFIG_IP6_NF_IPTABLES=m
> -CONFIG_IP6_NF_MATCH_AH=m
> -CONFIG_IP6_NF_MATCH_EUI64=m
> -CONFIG_IP6_NF_MATCH_FRAG=m
> -CONFIG_IP6_NF_MATCH_OPTS=m
> -CONFIG_IP6_NF_MATCH_HL=m
> -CONFIG_IP6_NF_MATCH_IPV6HEADER=m
> -CONFIG_IP6_NF_MATCH_MH=m
> -CONFIG_IP6_NF_MATCH_RT=m
> -CONFIG_IP6_NF_TARGET_HL=m
> -CONFIG_IP6_NF_TARGET_LOG=m
> -CONFIG_IP6_NF_FILTER=m
> -CONFIG_IP6_NF_TARGET_REJECT=m
> -CONFIG_IP6_NF_MANGLE=m
> -CONFIG_IP6_NF_RAW=m
> -CONFIG_IP6_NF_SECURITY=m
> -# CONFIG_IP_DCCP is not set
> -# CONFIG_IP_SCTP is not set
> -# CONFIG_RDS is not set
> -# CONFIG_TIPC is not set
> -# CONFIG_ATM is not set
> -# CONFIG_L2TP 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 is not set
> -# CONFIG_PHONET is not set
> -# CONFIG_IEEE802154 is not set
> -# CONFIG_NET_SCHED is not set
> -CONFIG_NET_CLS_ROUTE=y
> -# CONFIG_DCB is not set
> -CONFIG_DNS_RESOLVER=y
> -
> -#
> -# 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_WIRELESS=y
> -CONFIG_WIRELESS_EXT=y
> -CONFIG_WEXT_CORE=y
> -CONFIG_WEXT_PROC=y
> -CONFIG_WEXT_SPY=y
> -CONFIG_WEXT_PRIV=y
> -CONFIG_CFG80211=m
> -# CONFIG_NL80211_TESTMODE is not set
> -# CONFIG_CFG80211_DEVELOPER_WARNINGS is not set
> -# CONFIG_CFG80211_REG_DEBUG is not set
> -CONFIG_CFG80211_DEFAULT_PS=y
> -# CONFIG_CFG80211_INTERNAL_REGDB is not set
> -CONFIG_CFG80211_WEXT=y
> -CONFIG_WIRELESS_EXT_SYSFS=y
> -CONFIG_LIB80211=m
> -CONFIG_LIB80211_CRYPT_WEP=m
> -CONFIG_LIB80211_CRYPT_CCMP=m
> -CONFIG_LIB80211_CRYPT_TKIP=m
> -# CONFIG_LIB80211_DEBUG is not set
> -CONFIG_MAC80211=m
> -CONFIG_MAC80211_HAS_RC=y
> -CONFIG_MAC80211_RC_PID=y
> -# CONFIG_MAC80211_RC_MINSTREL is not set
> -CONFIG_MAC80211_RC_DEFAULT_PID=y
> -CONFIG_MAC80211_RC_DEFAULT="pid"
> -# CONFIG_MAC80211_MESH is not set
> -CONFIG_MAC80211_LEDS=y
> -# CONFIG_MAC80211_DEBUG_MENU is not set
> -# CONFIG_WIMAX is not set
> -# CONFIG_RFKILL is not set
> -# CONFIG_NET_9P is not set
> -# CONFIG_CAIF is not set
> -
> -#
> -# Device Drivers
> -#
> -
> -#
> -# Generic Driver Options
> -#
> -CONFIG_UEVENT_HELPER_PATH=""
> -CONFIG_DEVTMPFS=y
> -CONFIG_DEVTMPFS_MOUNT=y
> -CONFIG_STANDALONE=y
> -CONFIG_PREVENT_FIRMWARE_BUILD=y
> -CONFIG_FW_LOADER=m
> -CONFIG_FIRMWARE_IN_KERNEL=y
> -CONFIG_EXTRA_FIRMWARE=""
> -# CONFIG_SYS_HYPERVISOR is not set
> -CONFIG_CONNECTOR=m
> -CONFIG_MTD=y
> -# CONFIG_MTD_DEBUG is not set
> -# CONFIG_MTD_TESTS is not set
> -# CONFIG_MTD_CONCAT is not set
> -CONFIG_MTD_PARTITIONS=y
> -CONFIG_MTD_REDBOOT_PARTS=y
> -CONFIG_MTD_REDBOOT_DIRECTORY_BLOCK=-1
> -# CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED is not set
> -# CONFIG_MTD_REDBOOT_PARTS_READONLY 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_SM_FTL 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 is not set
> -# CONFIG_MTD_M25P80 is not set
> -# CONFIG_MTD_SST25L is not set
> -# 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_ECC=y
> -# CONFIG_MTD_NAND_ECC_SMC is not set
> -CONFIG_MTD_NAND=y
> -# CONFIG_MTD_NAND_VERIFY_WRITE is not set
> -# CONFIG_MTD_SM_COMMON is not set
> -# CONFIG_MTD_NAND_MUSEUM_IDS is not set
> -# 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=y
> -# CONFIG_MTD_ALAUDA is not set
> -# CONFIG_MTD_ONENAND is not set
> -
> -#
> -# LPDDR flash memory drivers
> -#
> -# CONFIG_MTD_LPDDR is not set
> -
> -#
> -# UBI - Unsorted block images
> -#
> -CONFIG_MTD_UBI=y
> -CONFIG_MTD_UBI_WL_THRESHOLD=4096
> -CONFIG_MTD_UBI_BEB_RESERVE=1
> -# CONFIG_MTD_UBI_GLUEBI is not set
> -
> -#
> -# UBI debugging options
> -#
> -# CONFIG_MTD_UBI_DEBUG 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=m
> -# CONFIG_BLK_DEV_DRBD is not set
> -CONFIG_BLK_DEV_NBD=m
> -# CONFIG_BLK_DEV_UB is not set
> -CONFIG_BLK_DEV_RAM=m
> -CONFIG_BLK_DEV_RAM_COUNT=16
> -CONFIG_BLK_DEV_RAM_SIZE=65536
> -# CONFIG_BLK_DEV_XIP is not set
> -# CONFIG_CDROM_PKTCDVD is not set
> -# CONFIG_ATA_OVER_ETH is not set
> -# CONFIG_MG_DISK is not set
> -CONFIG_BLK_DEV_TS72XX_SDCARD=y
> -CONFIG_MISC_DEVICES=y
> -# CONFIG_AD525X_DPOT is not set
> -# CONFIG_ICS932S401 is not set
> -# CONFIG_ENCLOSURE_SERVICES is not set
> -# CONFIG_ISL29003 is not set
> -# CONFIG_SENSORS_TSL2550 is not set
> -# CONFIG_SENSORS_BH1780 is not set
> -# CONFIG_HMC6352 is not set
> -CONFIG_EP93XX_PWM=m
> -# CONFIG_DS1682 is not set
> -# CONFIG_TI_DAC7512 is not set
> -# CONFIG_BMP085 is not set
> -# CONFIG_C2PORT is not set
> -
> -#
> -# EEPROM support
> -#
> -# CONFIG_EEPROM_AT24 is not set
> -# CONFIG_EEPROM_AT25 is not set
> -# CONFIG_EEPROM_LEGACY is not set
> -# CONFIG_EEPROM_MAX6875 is not set
> -CONFIG_EEPROM_93CX6=m
> -# CONFIG_IWMC3200TOP is not set
> -CONFIG_TS72XX_MAX197=m
> -CONFIG_TS72XX_MAX197_AVERAGE=y
> -CONFIG_HAVE_IDE=y
> -# CONFIG_IDE is not set
> -
> -#
> -# SCSI device support
> -#
> -CONFIG_SCSI_MOD=m
> -# CONFIG_RAID_ATTRS is not set
> -CONFIG_SCSI=m
> -CONFIG_SCSI_DMA=y
> -CONFIG_SCSI_TGT=m
> -# CONFIG_SCSI_NETLINK is not set
> -CONFIG_SCSI_PROC_FS=y
> -
> -#
> -# SCSI support type (disk, tape, CD-ROM)
> -#
> -CONFIG_BLK_DEV_SD=m
> -# 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=m
> -# CONFIG_CHR_DEV_SCH is not set
> -# CONFIG_SCSI_MULTI_LUN is not set
> -# CONFIG_SCSI_CONSTANTS is not set
> -# CONFIG_SCSI_LOGGING is not set
> -# CONFIG_SCSI_SCAN_ASYNC is not set
> -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 is not set
> -# CONFIG_SCSI_SAS_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_SCSI_OSD_INITIATOR is not set
> -CONFIG_ATA=m
> -# CONFIG_ATA_NONSTANDARD is not set
> -# CONFIG_ATA_VERBOSE_ERROR is not set
> -# CONFIG_SATA_PMP is not set
> -
> -#
> -# Controllers with non-SFF native interface
> -#
> -# CONFIG_SATA_AHCI_PLATFORM is not set
> -CONFIG_ATA_SFF=y
> -
> -#
> -# SFF controllers with custom DMA interface
> -#
> -CONFIG_ATA_BMDMA=y
> -
> -#
> -# SATA SFF controllers with BMDMA
> -#
> -# CONFIG_SATA_MV is not set
> -
> -#
> -# PATA SFF controllers with BMDMA
> -#
> -
> -#
> -# PIO-only SFF controllers
> -#
> -# CONFIG_PATA_PLATFORM is not set
> -
> -#
> -# Generic fallback / legacy drivers
> -#
> -CONFIG_PATA_TS72XX=y
> -CONFIG_PATA_TS7200_CF=m
> -CONFIG_PATA_TS9600=m
> -# 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_PHYLIB=y
> -
> -#
> -# MII PHY device drivers
> -#
> -# CONFIG_MARVELL_PHY is not set
> -# CONFIG_DAVICOM_PHY is not set
> -# CONFIG_QSEMI_PHY is not set
> -# CONFIG_LXT_PHY is not set
> -# CONFIG_CICADA_PHY is not set
> -# CONFIG_VITESSE_PHY is not set
> -# CONFIG_SMSC_PHY is not set
> -# CONFIG_BROADCOM_PHY is not set
> -# CONFIG_ICPLUS_PHY is not set
> -# CONFIG_REALTEK_PHY is not set
> -# CONFIG_NATIONAL_PHY is not set
> -# CONFIG_STE10XP is not set
> -# CONFIG_LSI_ET1011C_PHY is not set
> -# CONFIG_MICREL_PHY is not set
> -# CONFIG_FIXED_PHY is not set
> -# CONFIG_MDIO_BITBANG is not set
> -CONFIG_NET_ETHERNET=y
> -CONFIG_MII=y
> -CONFIG_EP93XX_ETH=y
> -CONFIG_AX88796=m
> -CONFIG_AX88796_93CX6=y
> -CONFIG_AX88796_TS_ETH100=m
> -# CONFIG_SMC91X is not set
> -# CONFIG_DM9000 is not set
> -# CONFIG_ENC28J60 is not set
> -CONFIG_ETHOC=m
> -# CONFIG_SMC911X is not set
> -# CONFIG_SMSC911X is not set
> -# CONFIG_DNET is not set
> -# CONFIG_IBM_NEW_EMAC_ZMII is not set
> -# CONFIG_IBM_NEW_EMAC_RGMII is not set
> -# CONFIG_IBM_NEW_EMAC_TAH is not set
> -# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
> -# CONFIG_IBM_NEW_EMAC_NO_FLOW_CTRL is not set
> -# CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set
> -# CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
> -# CONFIG_B44 is not set
> -# CONFIG_KS8851 is not set
> -# CONFIG_KS8851_MLL is not set
> -# CONFIG_NETDEV_1000 is not set
> -# CONFIG_NETDEV_10000 is not set
> -CONFIG_WLAN=y
> -CONFIG_LIBERTAS_THINFIRM=m
> -# CONFIG_LIBERTAS_THINFIRM_DEBUG is not set
> -CONFIG_LIBERTAS_THINFIRM_USB=m
> -CONFIG_AT76C50X_USB=m
> -CONFIG_USB_ZD1201=m
> -CONFIG_USB_NET_RNDIS_WLAN=m
> -CONFIG_RTL8187=m
> -CONFIG_RTL8187_LEDS=y
> -CONFIG_MAC80211_HWSIM=m
> -CONFIG_ATH_COMMON=m
> -# CONFIG_ATH_DEBUG is not set
> -CONFIG_ATH9K_HW=m
> -CONFIG_ATH9K_COMMON=m
> -CONFIG_ATH9K_HTC=m
> -CONFIG_AR9170_USB=m
> -CONFIG_AR9170_LEDS=y
> -CONFIG_B43=m
> -# CONFIG_B43_SDIO is not set
> -CONFIG_B43_PIO=y
> -CONFIG_B43_PHY_LP=y
> -CONFIG_B43_LEDS=y
> -CONFIG_B43_HWRNG=y
> -# CONFIG_B43_DEBUG is not set
> -CONFIG_B43LEGACY=m
> -CONFIG_B43LEGACY_LEDS=y
> -CONFIG_B43LEGACY_HWRNG=y
> -CONFIG_B43LEGACY_DEBUG=y
> -CONFIG_B43LEGACY_DMA=y
> -CONFIG_B43LEGACY_PIO=y
> -CONFIG_B43LEGACY_DMA_AND_PIO_MODE=y
> -# CONFIG_B43LEGACY_DMA_MODE is not set
> -# CONFIG_B43LEGACY_PIO_MODE is not set
> -CONFIG_HOSTAP=m
> -# CONFIG_HOSTAP_FIRMWARE is not set
> -# CONFIG_IWM is not set
> -CONFIG_LIBERTAS=m
> -CONFIG_LIBERTAS_USB=m
> -# CONFIG_LIBERTAS_SDIO is not set
> -# CONFIG_LIBERTAS_SPI is not set
> -# CONFIG_LIBERTAS_DEBUG is not set
> -# CONFIG_LIBERTAS_MESH is not set
> -CONFIG_P54_COMMON=m
> -CONFIG_P54_USB=m
> -# CONFIG_P54_SPI is not set
> -CONFIG_P54_LEDS=y
> -CONFIG_RT2X00=m
> -CONFIG_RT2500USB=m
> -CONFIG_RT73USB=m
> -CONFIG_RT2800USB=m
> -# CONFIG_RT2800USB_RT30XX is not set
> -# CONFIG_RT2800USB_RT35XX is not set
> -# CONFIG_RT2800USB_UNKNOWN is not set
> -CONFIG_RT2800_LIB=m
> -CONFIG_RT2X00_LIB_USB=m
> -CONFIG_RT2X00_LIB=m
> -CONFIG_RT2X00_LIB_HT=y
> -CONFIG_RT2X00_LIB_FIRMWARE=y
> -CONFIG_RT2X00_LIB_CRYPTO=y
> -CONFIG_RT2X00_LIB_LEDS=y
> -# CONFIG_RT2X00_DEBUG is not set
> -CONFIG_WL12XX=m
> -# CONFIG_WL1251 is not set
> -# CONFIG_WL1271 is not set
> -CONFIG_ZD1211RW=m
> -# CONFIG_ZD1211RW_DEBUG is not set
> -
> -#
> -# Enable WiMAX (Networking options) to see the WiMAX drivers
> -#
> -
> -#
> -# USB Network Adapters
> -#
> -CONFIG_USB_CATC=m
> -CONFIG_USB_KAWETH=m
> -CONFIG_USB_PEGASUS=m
> -CONFIG_USB_RTL8150=m
> -CONFIG_USB_USBNET=m
> -CONFIG_USB_NET_AX8817X=m
> -CONFIG_USB_NET_CDCETHER=m
> -CONFIG_USB_NET_CDC_EEM=m
> -CONFIG_USB_NET_DM9601=m
> -CONFIG_USB_NET_SMSC75XX=m
> -CONFIG_USB_NET_SMSC95XX=m
> -CONFIG_USB_NET_GL620A=m
> -CONFIG_USB_NET_NET1080=m
> -CONFIG_USB_NET_PLUSB=m
> -CONFIG_USB_NET_MCS7830=m
> -CONFIG_USB_NET_RNDIS_HOST=m
> -CONFIG_USB_NET_CDC_SUBSET=m
> -CONFIG_USB_ALI_M5632=y
> -CONFIG_USB_AN2720=y
> -CONFIG_USB_BELKIN=y
> -CONFIG_USB_ARMLINUX=y
> -CONFIG_USB_EPSON2888=y
> -CONFIG_USB_KC2190=y
> -CONFIG_USB_NET_ZAURUS=m
> -CONFIG_USB_NET_INT51X1=m
> -CONFIG_USB_IPHETH=m
> -CONFIG_USB_SIERRA_NET=m
> -# CONFIG_WAN is not set
> -
> -#
> -# CAIF transport drivers
> -#
> -CONFIG_PPP=m
> -CONFIG_PPP_MULTILINK=y
> -CONFIG_PPP_FILTER=y
> -CONFIG_PPP_ASYNC=m
> -CONFIG_PPP_SYNC_TTY=m
> -CONFIG_PPP_DEFLATE=m
> -CONFIG_PPP_BSDCOMP=m
> -CONFIG_PPP_MPPE=m
> -CONFIG_PPPOE=m
> -# CONFIG_SLIP is not set
> -CONFIG_SLHC=m
> -# CONFIG_NETCONSOLE is not set
> -# CONFIG_NETPOLL is not set
> -# CONFIG_NET_POLL_CONTROLLER is not set
> -# CONFIG_ISDN is not set
> -# CONFIG_PHONE is not set
> -
> -#
> -# Input device support
> -#
> -CONFIG_INPUT=y
> -CONFIG_INPUT_FF_MEMLESS=m
> -CONFIG_INPUT_POLLDEV=m
> -# CONFIG_INPUT_SPARSEKMAP is not set
> -
> -#
> -# Userland interfaces
> -#
> -CONFIG_INPUT_MOUSEDEV=m
> -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=m
> -# CONFIG_INPUT_EVBUG is not set
> -
> -#
> -# Input Device Drivers
> -#
> -CONFIG_INPUT_KEYBOARD=y
> -# CONFIG_KEYBOARD_ADP5588 is not set
> -CONFIG_KEYBOARD_ATKBD=y
> -# CONFIG_KEYBOARD_QT2160 is not set
> -# CONFIG_KEYBOARD_LKKBD is not set
> -CONFIG_KEYBOARD_EP93XX=m
> -CONFIG_KEYBOARD_GPIO=m
> -# CONFIG_KEYBOARD_TCA6416 is not set
> -CONFIG_KEYBOARD_MATRIX=m
> -CONFIG_TS72XX_DIO_3X4_KEYPAD=m
> -CONFIG_TS72XX_DIO_4X4_KEYPAD=m
> -# CONFIG_KEYBOARD_LM8323 is not set
> -# CONFIG_KEYBOARD_MAX7359 is not set
> -# CONFIG_KEYBOARD_MCS is not set
> -# CONFIG_KEYBOARD_NEWTON is not set
> -# CONFIG_KEYBOARD_OPENCORES is not set
> -# CONFIG_KEYBOARD_STOWAWAY is not set
> -# CONFIG_KEYBOARD_SUNKBD is not set
> -# CONFIG_KEYBOARD_XTKBD is not set
> -CONFIG_INPUT_MOUSE=y
> -CONFIG_MOUSE_PS2=m
> -CONFIG_MOUSE_PS2_ALPS=y
> -CONFIG_MOUSE_PS2_LOGIPS2PP=y
> -CONFIG_MOUSE_PS2_SYNAPTICS=y
> -CONFIG_MOUSE_PS2_TRACKPOINT=y
> -# CONFIG_MOUSE_PS2_ELANTECH is not set
> -# CONFIG_MOUSE_PS2_SENTELIC is not set
> -# CONFIG_MOUSE_PS2_TOUCHKIT is not set
> -CONFIG_MOUSE_SERIAL=m
> -# 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_MOUSE_SYNAPTICS_I2C is not set
> -# CONFIG_INPUT_JOYSTICK is not set
> -# CONFIG_INPUT_TABLET is not set
> -# CONFIG_INPUT_TOUCHSCREEN is not set
> -CONFIG_INPUT_MISC=y
> -# CONFIG_INPUT_AD714X is not set
> -# CONFIG_INPUT_ATI_REMOTE is not set
> -# CONFIG_INPUT_ATI_REMOTE2 is not set
> -# CONFIG_INPUT_KEYSPAN_REMOTE is not set
> -# CONFIG_INPUT_POWERMATE is not set
> -# CONFIG_INPUT_YEALINK is not set
> -# CONFIG_INPUT_CM109 is not set
> -CONFIG_INPUT_UINPUT=m
> -# CONFIG_INPUT_PCF8574 is not set
> -# CONFIG_INPUT_GPIO_ROTARY_ENCODER is not set
> -# CONFIG_INPUT_ADXL34X is not set
> -
> -#
> -# Hardware I/O ports
> -#
> -CONFIG_SERIO=y
> -# CONFIG_SERIO_SERPORT is not set
> -# CONFIG_SERIO_AMBAKMI is not set
> -CONFIG_SERIO_LIBPS2=y
> -# CONFIG_SERIO_RAW is not set
> -# CONFIG_SERIO_ALTERA_PS2 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=y
> -# CONFIG_DEVKMEM is not set
> -# CONFIG_SERIAL_NONSTANDARD is not set
> -# CONFIG_N_GSM is not set
> -
> -#
> -# Serial drivers
> -#
> -CONFIG_SERIAL_8250=m
> -CONFIG_SERIAL_8250_NR_UARTS=4
> -CONFIG_SERIAL_8250_RUNTIME_UARTS=4
> -# CONFIG_SERIAL_8250_EXTENDED is not set
> -CONFIG_SERIAL_8250_TS_SER1=m
> -CONFIG_SERIAL_8250_TS_SER1_IRQ=5
> -
> -#
> -# Non-8250 serial port support
> -#
> -CONFIG_SERIAL_AMBA_PL010=y
> -CONFIG_SERIAL_AMBA_PL010_CONSOLE=y
> -CONFIG_SERIAL_AMBA_PL010_TS72XX=y
> -# CONFIG_SERIAL_AMBA_PL011 is not set
> -# CONFIG_SERIAL_MAX3100 is not set
> -# CONFIG_SERIAL_MAX3107 is not set
> -CONFIG_SERIAL_CORE=y
> -CONFIG_SERIAL_CORE_CONSOLE=y
> -# CONFIG_SERIAL_TIMBERDALE is not set
> -# CONFIG_SERIAL_ALTERA_JTAGUART is not set
> -# CONFIG_SERIAL_ALTERA_UART is not set
> -CONFIG_UNIX98_PTYS=y
> -# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
> -# CONFIG_LEGACY_PTYS is not set
> -# CONFIG_IPMI_HANDLER is not set
> -CONFIG_HW_RANDOM=m
> -# CONFIG_HW_RANDOM_TIMERIOMEM is not set
> -# CONFIG_R3964 is not set
> -# CONFIG_RAW_DRIVER is not set
> -# CONFIG_TCG_TPM is not set
> -# CONFIG_RAMOOPS is not set
> -CONFIG_I2C=m
> -CONFIG_I2C_BOARDINFO=y
> -CONFIG_I2C_COMPAT=y
> -# CONFIG_I2C_CHARDEV is not set
> -# CONFIG_I2C_MUX is not set
> -CONFIG_I2C_HELPER_AUTO=y
> -CONFIG_I2C_ALGOBIT=m
> -
> -#
> -# I2C Hardware Bus support
> -#
> -
> -#
> -# I2C system bus drivers (mostly embedded / system-on-chip)
> -#
> -# CONFIG_I2C_DESIGNWARE is not set
> -CONFIG_I2C_GPIO=m
> -# CONFIG_I2C_OCORES is not set
> -# CONFIG_I2C_PCA_PLATFORM is not set
> -# CONFIG_I2C_SIMTEC is not set
> -# CONFIG_I2C_XILINX 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_STUB 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_SPI=y
> -CONFIG_SPI_MASTER=y
> -
> -#
> -# SPI Master Controller Drivers
> -#
> -CONFIG_SPI_BITBANG=m
> -# CONFIG_SPI_EP93XX is not set
> -CONFIG_SPI_GPIO=m
> -# CONFIG_SPI_PL022 is not set
> -# CONFIG_SPI_XILINX is not set
> -# CONFIG_SPI_DESIGNWARE is not set
> -
> -#
> -# SPI Protocol Masters
> -#
> -CONFIG_SPI_SPIDEV=m
> -# CONFIG_SPI_TLE62X0 is not set
> -# CONFIG_SPI_TMP124 is not set
> -
> -#
> -# PPS support
> -#
> -# CONFIG_PPS is not set
> -CONFIG_ARCH_REQUIRE_GPIOLIB=y
> -CONFIG_GPIOLIB=y
> -CONFIG_GPIO_SYSFS=y
> -
> -#
> -# Memory mapped GPIO expanders:
> -#
> -# CONFIG_GPIO_IT8761E is not set
> -# CONFIG_GPIO_PL061 is not set
> -
> -#
> -# I2C GPIO expanders:
> -#
> -# CONFIG_GPIO_MAX7300 is not set
> -# CONFIG_GPIO_MAX732X is not set
> -# CONFIG_GPIO_PCA953X is not set
> -# CONFIG_GPIO_PCF857X is not set
> -# CONFIG_GPIO_ADP5588 is not set
> -
> -#
> -# PCI GPIO expanders:
> -#
> -
> -#
> -# SPI GPIO expanders:
> -#
> -# CONFIG_GPIO_MAX7301 is not set
> -# CONFIG_GPIO_MCP23S08 is not set
> -# CONFIG_GPIO_MC33880 is not set
> -
> -#
> -# AC97 GPIO expanders:
> -#
> -
> -#
> -# MODULbus GPIO expanders:
> -#
> -# CONFIG_W1 is not set
> -# CONFIG_POWER_SUPPLY is not set
> -# CONFIG_HWMON is not set
> -# CONFIG_THERMAL is not set
> -CONFIG_WATCHDOG=y
> -# CONFIG_WATCHDOG_NOWAYOUT is not set
> -
> -#
> -# Watchdog Device Drivers
> -#
> -# CONFIG_SOFT_WATCHDOG is not set
> -# CONFIG_ARM_SP805_WATCHDOG is not set
> -CONFIG_EP93XX_WATCHDOG=m
> -CONFIG_TS72XX_WATCHDOG=y
> -# CONFIG_MAX63XX_WATCHDOG is not set
> -
> -#
> -# USB-based Watchdog Cards
> -#
> -# CONFIG_USBPCWATCHDOG is not set
> -CONFIG_SSB_POSSIBLE=y
> -
> -#
> -# Sonics Silicon Backplane
> -#
> -CONFIG_SSB=m
> -CONFIG_SSB_BLOCKIO=y
> -CONFIG_SSB_SDIOHOST_POSSIBLE=y
> -# CONFIG_SSB_SDIOHOST is not set
> -# CONFIG_SSB_SILENT is not set
> -# CONFIG_SSB_DEBUG is not set
> -CONFIG_MFD_SUPPORT=y
> -# 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_TPS65010 is not set
> -# CONFIG_TPS6507X is not set
> -# CONFIG_MFD_TMIO is not set
> -# CONFIG_MFD_T7L66XB is not set
> -# CONFIG_MFD_TC6387XB is not set
> -# CONFIG_MFD_TC6393XB is not set
> -# CONFIG_MFD_WM8400 is not set
> -# CONFIG_MFD_PCF50633 is not set
> -# CONFIG_MFD_MC13783 is not set
> -# CONFIG_ABX500_CORE is not set
> -# CONFIG_EZX_PCAP is not set
> -# CONFIG_AB8500_CORE is not set
> -# CONFIG_MFD_TPS6586X is not set
> -# CONFIG_REGULATOR is not set
> -# CONFIG_MEDIA_SUPPORT is not set
> -
> -#
> -# Graphics support
> -#
> -# CONFIG_DRM is not set
> -# 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_DUMMY_CONSOLE=y
> -# CONFIG_SOUND is not set
> -CONFIG_HID_SUPPORT=y
> -CONFIG_HID=y
> -# CONFIG_HIDRAW is not set
> -
> -#
> -# USB Input Devices
> -#
> -CONFIG_USB_HID=m
> -# CONFIG_HID_PID is not set
> -# CONFIG_USB_HIDDEV is not set
> -
> -#
> -# USB HID Boot Protocol drivers
> -#
> -# CONFIG_USB_KBD is not set
> -# CONFIG_USB_MOUSE is not set
> -
> -#
> -# Special HID drivers
> -#
> -# CONFIG_HID_3M_PCT is not set
> -# CONFIG_HID_A4TECH is not set
> -# CONFIG_HID_ACRUX_FF is not set
> -# CONFIG_HID_APPLE is not set
> -# CONFIG_HID_BELKIN is not set
> -# CONFIG_HID_CANDO is not set
> -# CONFIG_HID_CHERRY is not set
> -# CONFIG_HID_CHICONY is not set
> -# CONFIG_HID_CYPRESS is not set
> -# CONFIG_HID_DRAGONRISE is not set
> -# CONFIG_HID_EGALAX is not set
> -# CONFIG_HID_EZKEY is not set
> -# CONFIG_HID_KYE is not set
> -# CONFIG_HID_GYRATION is not set
> -# CONFIG_HID_TWINHAN is not set
> -# CONFIG_HID_KENSINGTON is not set
> -# CONFIG_HID_LOGITECH is not set
> -# CONFIG_HID_MICROSOFT is not set
> -# CONFIG_HID_MOSART is not set
> -# CONFIG_HID_MONTEREY is not set
> -# CONFIG_HID_NTRIG is not set
> -# CONFIG_HID_ORTEK is not set
> -# CONFIG_HID_PANTHERLORD is not set
> -# CONFIG_HID_PETALYNX is not set
> -# CONFIG_HID_PICOLCD is not set
> -# CONFIG_HID_QUANTA is not set
> -# CONFIG_HID_ROCCAT is not set
> -# CONFIG_HID_ROCCAT_KONE is not set
> -# CONFIG_HID_SAMSUNG is not set
> -# CONFIG_HID_SONY is not set
> -# CONFIG_HID_STANTUM is not set
> -# CONFIG_HID_SUNPLUS is not set
> -# CONFIG_HID_GREENASIA is not set
> -# CONFIG_HID_SMARTJOYPLUS is not set
> -# CONFIG_HID_TOPSEED is not set
> -# CONFIG_HID_THRUSTMASTER is not set
> -# CONFIG_HID_ZEROPLUS is not set
> -# CONFIG_HID_ZYDACRON is not set
> -CONFIG_USB_SUPPORT=y
> -CONFIG_USB_ARCH_HAS_HCD=y
> -CONFIG_USB_ARCH_HAS_OHCI=y
> -# CONFIG_USB_ARCH_HAS_EHCI is not set
> -CONFIG_USB=m
> -# CONFIG_USB_DEBUG is not set
> -CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
> -
> -#
> -# Miscellaneous USB options
> -#
> -# CONFIG_USB_DEVICEFS is not set
> -CONFIG_USB_DEVICE_CLASS=y
> -# CONFIG_USB_DYNAMIC_MINORS is not set
> -# CONFIG_USB_OTG_WHITELIST is not set
> -# CONFIG_USB_OTG_BLACKLIST_HUB is not set
> -CONFIG_USB_MON=m
> -# 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_OXU210HP_HCD is not set
> -# CONFIG_USB_ISP116X_HCD is not set
> -# CONFIG_USB_ISP1760_HCD is not set
> -# CONFIG_USB_ISP1362_HCD is not set
> -CONFIG_USB_OHCI_HCD=m
> -# CONFIG_USB_OHCI_HCD_SSB is not set
> -# CONFIG_USB_OHCI_BIG_ENDIAN_DESC is not set
> -# CONFIG_USB_OHCI_BIG_ENDIAN_MMIO is not set
> -CONFIG_USB_OHCI_LITTLE_ENDIAN=y
> -# CONFIG_USB_SL811_HCD is not set
> -# CONFIG_USB_R8A66597_HCD is not set
> -# CONFIG_USB_HWA_HCD is not set
> -# CONFIG_USB_MUSB_HDRC is not set
> -
> -#
> -# USB Device Class drivers
> -#
> -CONFIG_USB_ACM=m
> -# 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 info
> -#
> -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_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=m
> -# CONFIG_USB_EZUSB is not set
> -CONFIG_USB_SERIAL_GENERIC=y
> -# CONFIG_USB_SERIAL_AIRCABLE is not set
> -# CONFIG_USB_SERIAL_ARK3116 is not set
> -# CONFIG_USB_SERIAL_BELKIN is not set
> -# CONFIG_USB_SERIAL_CH341 is not set
> -# CONFIG_USB_SERIAL_WHITEHEAT is not set
> -# CONFIG_USB_SERIAL_DIGI_ACCELEPORT is not set
> -# CONFIG_USB_SERIAL_CP210X is not set
> -# CONFIG_USB_SERIAL_CYPRESS_M8 is not set
> -# CONFIG_USB_SERIAL_EMPEG is not set
> -CONFIG_USB_SERIAL_FTDI_SIO=m
> -# CONFIG_USB_SERIAL_FUNSOFT is not set
> -# CONFIG_USB_SERIAL_VISOR is not set
> -# CONFIG_USB_SERIAL_IPAQ is not set
> -# CONFIG_USB_SERIAL_IR is not set
> -# CONFIG_USB_SERIAL_EDGEPORT is not set
> -# CONFIG_USB_SERIAL_EDGEPORT_TI is not set
> -# CONFIG_USB_SERIAL_GARMIN is not set
> -# CONFIG_USB_SERIAL_IPW is not set
> -# CONFIG_USB_SERIAL_IUU is not set
> -# CONFIG_USB_SERIAL_KEYSPAN_PDA is not set
> -# CONFIG_USB_SERIAL_KEYSPAN is not set
> -# CONFIG_USB_SERIAL_KLSI is not set
> -# CONFIG_USB_SERIAL_KOBIL_SCT is not set
> -# CONFIG_USB_SERIAL_MCT_U232 is not set
> -# CONFIG_USB_SERIAL_MOS7720 is not set
> -# CONFIG_USB_SERIAL_MOS7840 is not set
> -# CONFIG_USB_SERIAL_MOTOROLA is not set
> -# CONFIG_USB_SERIAL_NAVMAN is not set
> -CONFIG_USB_SERIAL_PL2303=m
> -# CONFIG_USB_SERIAL_OTI6858 is not set
> -# CONFIG_USB_SERIAL_QCAUX is not set
> -# CONFIG_USB_SERIAL_QUALCOMM is not set
> -# CONFIG_USB_SERIAL_SPCP8X5 is not set
> -# CONFIG_USB_SERIAL_HP4X is not set
> -# CONFIG_USB_SERIAL_SAFE is not set
> -# CONFIG_USB_SERIAL_SIEMENS_MPI is not set
> -# CONFIG_USB_SERIAL_SIERRAWIRELESS is not set
> -# CONFIG_USB_SERIAL_SYMBOL is not set
> -# CONFIG_USB_SERIAL_TI is not set
> -# CONFIG_USB_SERIAL_CYBERJACK is not set
> -# CONFIG_USB_SERIAL_XIRCOM is not set
> -CONFIG_USB_SERIAL_WWAN=m
> -CONFIG_USB_SERIAL_OPTION=m
> -# CONFIG_USB_SERIAL_OMNINET is not set
> -# CONFIG_USB_SERIAL_OPTICON is not set
> -# CONFIG_USB_SERIAL_VIVOPAY_SERIAL is not set
> -# CONFIG_USB_SERIAL_ZIO is not set
> -# CONFIG_USB_SERIAL_SSU100 is not set
> -# CONFIG_USB_SERIAL_DEBUG 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_LED is not set
> -# CONFIG_USB_CYPRESS_CY7C63 is not set
> -# CONFIG_USB_CYTHERM 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_GADGET=m
> -# CONFIG_USB_GADGET_DEBUG_FILES is not set
> -CONFIG_USB_GADGET_VBUS_DRAW=2
> -CONFIG_USB_GADGET_SELECTED=y
> -CONFIG_USB_GADGET_R8A66597=y
> -CONFIG_USB_R8A66597=m
> -# CONFIG_USB_GADGET_M66592 is not set
> -# CONFIG_USB_GADGET_DUMMY_HCD is not set
> -CONFIG_USB_GADGET_DUALSPEED=y
> -# CONFIG_USB_ZERO is not set
> -CONFIG_USB_ETH=m
> -CONFIG_USB_ETH_RNDIS=y
> -CONFIG_USB_ETH_EEM=y
> -CONFIG_USB_GADGETFS=m
> -# CONFIG_USB_FUNCTIONFS is not set
> -CONFIG_USB_FILE_STORAGE=m
> -# CONFIG_USB_FILE_STORAGE_TEST is not set
> -CONFIG_USB_MASS_STORAGE=m
> -CONFIG_USB_G_SERIAL=m
> -CONFIG_USB_G_PRINTER=m
> -CONFIG_USB_CDC_COMPOSITE=m
> -CONFIG_USB_G_MULTI=m
> -CONFIG_USB_G_MULTI_RNDIS=y
> -CONFIG_USB_G_MULTI_CDC=y
> -# CONFIG_USB_G_HID is not set
> -# CONFIG_USB_G_DBGP is not set
> -
> -#
> -# OTG and related infrastructure
> -#
> -# CONFIG_USB_GPIO_VBUS is not set
> -# CONFIG_USB_ULPI is not set
> -# CONFIG_NOP_USB_XCEIV is not set
> -CONFIG_MMC=m
> -# CONFIG_MMC_DEBUG is not set
> -# CONFIG_MMC_UNSAFE_RESUME is not set
> -
> -#
> -# MMC/SD/SDIO Card Drivers
> -#
> -CONFIG_MMC_BLOCK=m
> -CONFIG_MMC_BLOCK_BOUNCE=y
> -CONFIG_SDIO_UART=m
> -# CONFIG_MMC_TEST is not set
> -
> -#
> -# MMC/SD/SDIO Host Controller Drivers
> -#
> -CONFIG_MMC_ARMMMCI=m
> -CONFIG_MMC_SDHCI=m
> -# CONFIG_MMC_SDHCI_PLTFM is not set
> -# CONFIG_MMC_SPI is not set
> -# CONFIG_MEMSTICK is not set
> -CONFIG_NEW_LEDS=y
> -CONFIG_LEDS_CLASS=y
> -
> -#
> -# LED drivers
> -#
> -# CONFIG_LEDS_PCA9532 is not set
> -CONFIG_LEDS_GPIO=y
> -CONFIG_LEDS_GPIO_PLATFORM=y
> -# CONFIG_LEDS_LP3944 is not set
> -# CONFIG_LEDS_PCA955X is not set
> -# CONFIG_LEDS_DAC124S085 is not set
> -# CONFIG_LEDS_BD2802 is not set
> -# CONFIG_LEDS_LT3593 is not set
> -CONFIG_LEDS_TRIGGERS=y
> -
> -#
> -# LED Triggers
> -#
> -CONFIG_LEDS_TRIGGER_TIMER=y
> -CONFIG_LEDS_TRIGGER_HEARTBEAT=y
> -CONFIG_LEDS_TRIGGER_BACKLIGHT=y
> -CONFIG_LEDS_TRIGGER_GPIO=y
> -CONFIG_LEDS_TRIGGER_DEFAULT_ON=m
> -
> -#
> -# iptables trigger is under Netfilter config (LED target)
> -#
> -# CONFIG_ACCESSIBILITY is not set
> -CONFIG_RTC_LIB=y
> -CONFIG_RTC_CLASS=m
> -
> -#
> -# 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_DS3232 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_ISL12022 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_BQ32K is not set
> -# CONFIG_RTC_DRV_S35390A is not set
> -# CONFIG_RTC_DRV_FM3130 is not set
> -# CONFIG_RTC_DRV_RX8581 is not set
> -# CONFIG_RTC_DRV_RX8025 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
> -# CONFIG_RTC_DRV_PCF2123 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=m
> -# CONFIG_RTC_DRV_M48T35 is not set
> -# CONFIG_RTC_DRV_M48T59 is not set
> -# CONFIG_RTC_DRV_MSM6242 is not set
> -# CONFIG_RTC_DRV_BQ4802 is not set
> -# CONFIG_RTC_DRV_RP5C01 is not set
> -# CONFIG_RTC_DRV_V3020 is not set
> -
> -#
> -# on-CPU RTC drivers
> -#
> -CONFIG_RTC_DRV_EP93XX=m
> -# CONFIG_RTC_DRV_PL030 is not set
> -# CONFIG_RTC_DRV_PL031 is not set
> -# CONFIG_DMADEVICES is not set
> -# CONFIG_AUXDISPLAY is not set
> -CONFIG_UIO=m
> -CONFIG_UIO_PDRV=m
> -CONFIG_UIO_PDRV_GENIRQ=m
> -# CONFIG_STAGING is not set
> -
> -#
> -# LCD support
> -#
> -CONFIG_LCD_LINUX=y
> -CONFIG_LCD_HD44780=y
> -
> -#
> -# File systems
> -#
> -CONFIG_EXT2_FS=m
> -# CONFIG_EXT2_FS_XATTR is not set
> -# CONFIG_EXT2_FS_XIP is not set
> -CONFIG_EXT3_FS=m
> -# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
> -CONFIG_EXT3_FS_XATTR=y
> -# CONFIG_EXT3_FS_POSIX_ACL is not set
> -# CONFIG_EXT3_FS_SECURITY is not set
> -CONFIG_EXT4_FS=m
> -# CONFIG_EXT4_FS_XATTR is not set
> -# CONFIG_EXT4_DEBUG is not set
> -CONFIG_JBD=m
> -CONFIG_JBD2=m
> -CONFIG_FS_MBCACHE=m
> -# CONFIG_REISERFS_FS is not set
> -# CONFIG_JFS_FS is not set
> -CONFIG_FS_POSIX_ACL=y
> -# CONFIG_XFS_FS is not set
> -# CONFIG_GFS2_FS is not set
> -# CONFIG_OCFS2_FS is not set
> -# CONFIG_BTRFS_FS is not set
> -# CONFIG_NILFS2_FS is not set
> -CONFIG_FILE_LOCKING=y
> -CONFIG_FSNOTIFY=y
> -CONFIG_DNOTIFY=y
> -CONFIG_INOTIFY_USER=y
> -# CONFIG_QUOTA is not set
> -# CONFIG_AUTOFS_FS is not set
> -CONFIG_AUTOFS4_FS=m
> -CONFIG_FUSE_FS=m
> -# CONFIG_CUSE is not set
> -CONFIG_GENERIC_ACL=y
> -
> -#
> -# Caches
> -#
> -# CONFIG_FSCACHE is not set
> -
> -#
> -# CD-ROM/DVD Filesystems
> -#
> -CONFIG_ISO9660_FS=m
> -CONFIG_JOLIET=y
> -CONFIG_ZISOFS=y
> -CONFIG_UDF_FS=m
> -CONFIG_UDF_NLS=y
> -
> -#
> -# DOS/FAT/NT Filesystems
> -#
> -CONFIG_FAT_FS=m
> -CONFIG_MSDOS_FS=m
> -CONFIG_VFAT_FS=m
> -CONFIG_FAT_DEFAULT_CODEPAGE=437
> -CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
> -CONFIG_NTFS_FS=m
> -# 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
> -CONFIG_MISC_FILESYSTEMS=y
> -# CONFIG_ADFS_FS is not set
> -# CONFIG_AFFS_FS is not set
> -# CONFIG_ECRYPT_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_JFFS2_FS=m
> -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_UBIFS_FS=y
> -CONFIG_UBIFS_FS_XATTR=y
> -CONFIG_UBIFS_FS_ADVANCED_COMPR=y
> -CONFIG_UBIFS_FS_LZO=y
> -CONFIG_UBIFS_FS_ZLIB=y
> -# CONFIG_UBIFS_FS_DEBUG is not set
> -# CONFIG_LOGFS is not set
> -# CONFIG_CRAMFS is not set
> -CONFIG_SQUASHFS=m
> -# CONFIG_SQUASHFS_XATTR is not set
> -# CONFIG_SQUASHFS_LZO is not set
> -# CONFIG_SQUASHFS_EMBEDDED is not set
> -CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE=3
> -# 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=y
> -# CONFIG_NFS_V4_1 is not set
> -CONFIG_ROOT_NFS=y
> -# CONFIG_NFS_USE_LEGACY_DNS is not set
> -CONFIG_NFS_USE_KERNEL_DNS=y
> -CONFIG_NFSD=m
> -CONFIG_NFSD_V2_ACL=y
> -CONFIG_NFSD_V3=y
> -CONFIG_NFSD_V3_ACL=y
> -CONFIG_NFSD_V4=y
> -CONFIG_LOCKD=y
> -CONFIG_LOCKD_V4=y
> -CONFIG_EXPORTFS=m
> -CONFIG_NFS_ACL_SUPPORT=m
> -CONFIG_NFS_COMMON=y
> -CONFIG_SUNRPC=y
> -CONFIG_SUNRPC_GSS=y
> -CONFIG_RPCSEC_GSS_KRB5=y
> -# CONFIG_RPCSEC_GSS_SPKM3 is not set
> -# CONFIG_SMB_FS is not set
> -# CONFIG_CEPH_FS is not set
> -CONFIG_CIFS=m
> -# CONFIG_CIFS_STATS is not set
> -# CONFIG_CIFS_WEAK_PW_HASH is not set
> -CONFIG_CIFS_UPCALL=y
> -# CONFIG_CIFS_XATTR is not set
> -# CONFIG_CIFS_DEBUG2 is not set
> -# CONFIG_CIFS_DFS_UPCALL is not set
> -# CONFIG_CIFS_EXPERIMENTAL 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="iso8859-1"
> -CONFIG_NLS_CODEPAGE_437=m
> -CONFIG_NLS_CODEPAGE_737=m
> -CONFIG_NLS_CODEPAGE_775=m
> -CONFIG_NLS_CODEPAGE_850=m
> -CONFIG_NLS_CODEPAGE_852=m
> -CONFIG_NLS_CODEPAGE_855=m
> -CONFIG_NLS_CODEPAGE_857=m
> -CONFIG_NLS_CODEPAGE_860=m
> -CONFIG_NLS_CODEPAGE_861=m
> -CONFIG_NLS_CODEPAGE_862=m
> -CONFIG_NLS_CODEPAGE_863=m
> -CONFIG_NLS_CODEPAGE_864=m
> -CONFIG_NLS_CODEPAGE_865=m
> -CONFIG_NLS_CODEPAGE_866=m
> -CONFIG_NLS_CODEPAGE_869=m
> -CONFIG_NLS_CODEPAGE_936=m
> -CONFIG_NLS_CODEPAGE_950=m
> -CONFIG_NLS_CODEPAGE_932=m
> -CONFIG_NLS_CODEPAGE_949=m
> -CONFIG_NLS_CODEPAGE_874=m
> -CONFIG_NLS_ISO8859_8=m
> -CONFIG_NLS_CODEPAGE_1250=m
> -CONFIG_NLS_CODEPAGE_1251=m
> -CONFIG_NLS_ASCII=m
> -CONFIG_NLS_ISO8859_1=m
> -CONFIG_NLS_ISO8859_2=m
> -CONFIG_NLS_ISO8859_3=m
> -CONFIG_NLS_ISO8859_4=m
> -CONFIG_NLS_ISO8859_5=m
> -CONFIG_NLS_ISO8859_6=m
> -CONFIG_NLS_ISO8859_7=m
> -CONFIG_NLS_ISO8859_9=m
> -CONFIG_NLS_ISO8859_13=m
> -CONFIG_NLS_ISO8859_14=m
> -CONFIG_NLS_ISO8859_15=m
> -CONFIG_NLS_KOI8_R=m
> -CONFIG_NLS_KOI8_U=m
> -CONFIG_NLS_UTF8=m
> -# CONFIG_DLM is not set
> -
> -#
> -# Kernel hacking
> -#
> -CONFIG_PRINTK_TIME=y
> -# CONFIG_ENABLE_WARN_DEPRECATED is not set
> -# CONFIG_ENABLE_MUST_CHECK is not set
> -CONFIG_FRAME_WARN=2048
> -# CONFIG_MAGIC_SYSRQ is not set
> -# CONFIG_STRIP_ASM_SYMS is not set
> -# 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_HARDLOCKUP_DETECTOR is not set
> -CONFIG_DEBUG_BUGVERBOSE=y
> -# CONFIG_DEBUG_MEMORY_INIT is not set
> -# CONFIG_RCU_CPU_STALL_DETECTOR is not set
> -CONFIG_SYSCTL_SYSCALL_CHECK=y
> -CONFIG_HAVE_FUNCTION_TRACER=y
> -CONFIG_TRACING_SUPPORT=y
> -# CONFIG_FTRACE is not set
> -# CONFIG_ATOMIC64_SELFTEST is not set
> -# CONFIG_SAMPLES is not set
> -CONFIG_HAVE_ARCH_KGDB=y
> -CONFIG_ARM_UNWIND=y
> -# CONFIG_DEBUG_USER is not set
> -# CONFIG_OC_ETM is not set
> -
> -#
> -# Security options
> -#
> -CONFIG_KEYS=y
> -# CONFIG_KEYS_DEBUG_PROC_KEYS is not set
> -CONFIG_SECURITY=y
> -# CONFIG_SECURITYFS is not set
> -CONFIG_SECURITY_NETWORK=y
> -# CONFIG_SECURITY_NETWORK_XFRM is not set
> -# CONFIG_SECURITY_PATH is not set
> -# CONFIG_SECURITY_TOMOYO is not set
> -# CONFIG_SECURITY_APPARMOR is not set
> -# CONFIG_IMA is not set
> -CONFIG_DEFAULT_SECURITY_DAC=y
> -CONFIG_DEFAULT_SECURITY=""
> -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_RNG=m
> -CONFIG_CRYPTO_RNG2=y
> -CONFIG_CRYPTO_PCOMP=m
> -CONFIG_CRYPTO_PCOMP2=y
> -CONFIG_CRYPTO_MANAGER=y
> -CONFIG_CRYPTO_MANAGER2=y
> -CONFIG_CRYPTO_MANAGER_DISABLE_TESTS=y
> -CONFIG_CRYPTO_GF128MUL=m
> -CONFIG_CRYPTO_NULL=m
> -CONFIG_CRYPTO_WORKQUEUE=y
> -CONFIG_CRYPTO_CRYPTD=m
> -CONFIG_CRYPTO_AUTHENC=m
> -CONFIG_CRYPTO_TEST=m
> -
> -#
> -# Authenticated Encryption with Associated Data
> -#
> -CONFIG_CRYPTO_CCM=m
> -CONFIG_CRYPTO_GCM=m
> -CONFIG_CRYPTO_SEQIV=m
> -
> -#
> -# Block modes
> -#
> -CONFIG_CRYPTO_CBC=y
> -CONFIG_CRYPTO_CTR=m
> -CONFIG_CRYPTO_CTS=m
> -CONFIG_CRYPTO_ECB=m
> -CONFIG_CRYPTO_LRW=m
> -CONFIG_CRYPTO_PCBC=m
> -CONFIG_CRYPTO_XTS=m
> -
> -#
> -# Hash modes
> -#
> -CONFIG_CRYPTO_HMAC=m
> -CONFIG_CRYPTO_XCBC=m
> -CONFIG_CRYPTO_VMAC=m
> -
> -#
> -# Digest
> -#
> -CONFIG_CRYPTO_CRC32C=m
> -CONFIG_CRYPTO_GHASH=m
> -CONFIG_CRYPTO_MD4=m
> -CONFIG_CRYPTO_MD5=y
> -CONFIG_CRYPTO_MICHAEL_MIC=m
> -CONFIG_CRYPTO_RMD128=m
> -CONFIG_CRYPTO_RMD160=m
> -CONFIG_CRYPTO_RMD256=m
> -CONFIG_CRYPTO_RMD320=m
> -CONFIG_CRYPTO_SHA1=m
> -CONFIG_CRYPTO_SHA256=m
> -CONFIG_CRYPTO_SHA512=m
> -CONFIG_CRYPTO_TGR192=m
> -CONFIG_CRYPTO_WP512=m
> -
> -#
> -# Ciphers
> -#
> -CONFIG_CRYPTO_AES=m
> -CONFIG_CRYPTO_ANUBIS=m
> -CONFIG_CRYPTO_ARC4=m
> -CONFIG_CRYPTO_BLOWFISH=m
> -CONFIG_CRYPTO_CAMELLIA=m
> -CONFIG_CRYPTO_CAST5=m
> -CONFIG_CRYPTO_CAST6=m
> -CONFIG_CRYPTO_DES=y
> -CONFIG_CRYPTO_FCRYPT=m
> -CONFIG_CRYPTO_KHAZAD=m
> -CONFIG_CRYPTO_SALSA20=m
> -CONFIG_CRYPTO_SEED=m
> -CONFIG_CRYPTO_SERPENT=m
> -CONFIG_CRYPTO_TEA=m
> -CONFIG_CRYPTO_TWOFISH=m
> -CONFIG_CRYPTO_TWOFISH_COMMON=m
> -
> -#
> -# Compression
> -#
> -CONFIG_CRYPTO_DEFLATE=y
> -CONFIG_CRYPTO_ZLIB=m
> -CONFIG_CRYPTO_LZO=y
> -
> -#
> -# Random Number Generation
> -#
> -CONFIG_CRYPTO_ANSI_CPRNG=m
> -# CONFIG_CRYPTO_HW is not set
> -# CONFIG_BINARY_PRINTF is not set
> -
> -#
> -# Library routines
> -#
> -CONFIG_BITREVERSE=y
> -CONFIG_GENERIC_FIND_LAST_BIT=y
> -CONFIG_CRC_CCITT=m
> -CONFIG_CRC16=y
> -CONFIG_CRC_T10DIF=m
> -CONFIG_CRC_ITU_T=m
> -CONFIG_CRC32=y
> -CONFIG_CRC7=m
> -CONFIG_LIBCRC32C=m
> -CONFIG_ZLIB_INFLATE=y
> -CONFIG_ZLIB_DEFLATE=y
> -CONFIG_LZO_COMPRESS=y
> -CONFIG_LZO_DECOMPRESS=y
> -CONFIG_TEXTSEARCH=y
> -CONFIG_TEXTSEARCH_KMP=m
> -CONFIG_TEXTSEARCH_BM=m
> -CONFIG_TEXTSEARCH_FSM=m
> -CONFIG_HAS_IOMEM=y
> -CONFIG_HAS_IOPORT=y
> -CONFIG_HAS_DMA=y
> -CONFIG_NLATTR=y
> -CONFIG_GENERIC_ATOMIC64=y
> diff --git a/recipes/linux/linux_2.6.36.bb b/recipes/linux/linux_2.6.36.bb
> index 10692b9..aea17dd 100644
> --- a/recipes/linux/linux_2.6.36.bb
> +++ b/recipes/linux/linux_2.6.36.bb
> @@ -5,7 +5,6 @@ PR = "r2"
> # Mark archs/machines that this kernel supports
> DEFAULT_PREFERENCE = "-1"
> DEFAULT_PREFERENCE_mx31ads = "1"
> -DEFAULT_PREFERENCE_ts72xx = "1"
>
> SRC_URI = "${KERNELORG_MIRROR}/pub/linux/kernel/v2.6/${P}.tar.bz2;name=kernel \
> ${KERNELORG_MIRROR}/pub/linux/kernel/v2.6/patch-${PV}.1.bz2;apply=yes;name=stablepatch \
> @@ -13,30 +12,6 @@ SRC_URI = "${KERNELORG_MIRROR}/pub/linux/kernel/v2.6/${P}.tar.bz2;name=kernel \
>
> SRC_URI_append_mx31ads = "file://0001-add-missing-include.patch"
>
> -SRC_URI_append_ts72xx = " \
> - file://0001-ts72xx_base.patch \
> - file://0002-ts72xx_force_machine-id.patch \
> - file://0003-ep93xx_cpuinfo.patch \
> - file://0004-ep93xx_eth.patch \
> - file://0005-ep93xx-m2m-DMA-support.patch \
> - file://0006-ts72xx_rs485.patch \
> - file://0007-ts72xx_ts_ser1.patch \
> - file://0008-ts72xx_ts_eth100.patch \
> - file://0009-ts72xx_pata.patch \
> - file://0010-ts72xx_gpio_i2c.patch \
> - file://0011-ts72xx_dio_keypad.patch \
> - file://0012-ts72xx_sbcinfo.patch \
> - file://0013-ts72xx_max197.patch \
> - file://0014-ts7200_nor_flash.patch \
> - file://0015-ts72xx_sdcard.patch \
> - file://0016-ts72xx_spi_tmp124.patch \
> - file://0017-ts72xx-use-CPLD-watchdog-for-reset.patch \
> - file://0018-ethoc-ts7300-fixes.patch \
> - file://0019-ts7300-add-ethernet-support.patch \
> - file://0023-ts72xx-add-lcd-linux-driver.patch \
> - file://0024-ts72xx-add-GPIO-keys.patch \
> - "
> -
> SRC_URI[kernel.md5sum] = "61f3739a73afb6914cb007f37fb09b62"
> SRC_URI[kernel.sha256sum] = "15a076d1a435a6bf8e92834eba4b390b4ec094ce06d47f89d071ca9e5788ce04"
> SRC_URI[stablepatch.md5sum] = "dd38a6caf08df2822f93541ee95aed7d"
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.5 (Darwin)
iD8DBQFNl0niMkyGM64RGpERAlM4AJ44b/PdxftNHT4jm/ofdbd4FFHM0gCffqem
D+lK+yUDwdr56dSv3Ebu89w=
=VQig
-----END PGP SIGNATURE-----
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH 5/6] linux-2.6.36: remove ts72xx support because 2.6.38 is now default
2011-04-02 16:08 ` Koen Kooi
@ 2011-04-02 16:31 ` Petr Štetiar
0 siblings, 0 replies; 10+ messages in thread
From: Petr Štetiar @ 2011-04-02 16:31 UTC (permalink / raw)
To: openembedded-devel
Koen Kooi <koen@dominion.thruhere.net> [2011-04-02 18:08:48]:
> Is it really necessary to remove it from .36 instead of DP+1;ing .38?
It's not, but wouldn't it be better to remove the patches from the unsupported
kernel version? It's just a start, RFC and if it's ok I would like to remove
the references of ts72xx in all older and unsupported kernel versions. What's
a point of keeping them in oe-dev branch, anyway?
-- ynezz
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH 0/6] RFC: patches I plan to push
2011-04-02 14:18 [PATCH 0/6] RFC: patches I plan to push Petr Štetiar
` (5 preceding siblings ...)
2011-04-02 14:18 ` [PATCH 6/6] linux-2.6.38: add support for ts72xx and make it default Petr Štetiar
@ 2011-04-10 1:57 ` Khem Raj
6 siblings, 0 replies; 10+ messages in thread
From: Khem Raj @ 2011-04-10 1:57 UTC (permalink / raw)
To: openembedded-devel
On 4/2/2011 7:18 AM, Petr Štetiar wrote:
> Hi,
>
> I plan to push few patches, so I'm posting them for the review first to get some
> feedback (if any). Thanks.
looks ok
>
> -- ynezz
>
> Petr Štetiar (6):
> zeromq: add new recipe for version 2.1.1
> lua-lanes: add recipe for version 2.1.0 and delete the old one
> librs232: add version 1.0.1 and remove the old one
> lua-rs232: add recipe for version 1.0.1, remove old package and fix
> stripping
> linux-2.6.36: remove ts72xx support because 2.6.38 is now default
> linux-2.6.38: add support for ts72xx and make it default
>
> recipes/librs232/librs232_1.0.0.bb | 10 -
> recipes/librs232/librs232_1.0.1.bb | 10 +
> .../linux-2.6.36/ts72xx/0001-ts72xx_base.patch | 450 --
> .../ts72xx/0002-ts72xx_force_machine-id.patch | 49 -
> .../linux-2.6.36/ts72xx/0003-ep93xx_cpuinfo.patch | 36 -
> .../linux-2.6.36/ts72xx/0004-ep93xx_eth.patch | 555 ---
> .../ts72xx/0005-ep93xx-m2m-DMA-support.patch | 886 ----
> .../linux-2.6.36/ts72xx/0006-ts72xx_rs485.patch | 223 -
> .../linux-2.6.36/ts72xx/0007-ts72xx_ts_ser1.patch | 264 --
> .../ts72xx/0008-ts72xx_ts_eth100.patch | 278 --
> .../linux-2.6.36/ts72xx/0009-ts72xx_pata.patch | 437 --
> .../linux-2.6.36/ts72xx/0010-ts72xx_gpio_i2c.patch | 63 -
> .../ts72xx/0011-ts72xx_dio_keypad.patch | 311 --
> .../linux-2.6.36/ts72xx/0012-ts72xx_sbcinfo.patch | 267 --
> .../linux-2.6.36/ts72xx/0013-ts72xx_max197.patch | 356 --
> .../ts72xx/0014-ts7200_nor_flash.patch | 181 -
> .../linux-2.6.36/ts72xx/0015-ts72xx_sdcard.patch | 3298 --------------
> .../ts72xx/0016-ts72xx_spi_tmp124.patch | 305 --
> .../0017-ts72xx-use-CPLD-watchdog-for-reset.patch | 53 -
> .../ts72xx/0018-ethoc-ts7300-fixes.patch | 93 -
> .../ts72xx/0019-ts7300-add-ethernet-support.patch | 87 -
> .../ts72xx/0023-ts72xx-add-lcd-linux-driver.patch | 4569 -------------------
> .../ts72xx/0024-ts72xx-add-GPIO-keys.patch | 100 -
> recipes/linux/linux-2.6.36/ts72xx/defconfig | 2127 ---------
> .../linux-2.6.38/ts72xx/0001-ts72xx_base.patch | 451 ++
> .../ts72xx/0002-ts72xx_force_machine-id.patch | 49 +
> .../linux-2.6.38/ts72xx/0003-ep93xx_cpuinfo.patch | 36 +
> .../linux-2.6.38/ts72xx/0004-ep93xx_eth.patch | 553 +++
> .../ts72xx/0005-ep93xx-m2m-DMA-support.patch | 870 ++++
> .../linux-2.6.38/ts72xx/0006-ts72xx_rs485.patch | 221 +
> .../linux-2.6.38/ts72xx/0007-ts72xx_ts_ser1.patch | 264 ++
> .../ts72xx/0008-ts72xx_ts_eth100.patch | 278 ++
> .../linux-2.6.38/ts72xx/0009-ts72xx_pata.patch | 437 ++
> .../linux-2.6.38/ts72xx/0010-ts72xx_gpio_i2c.patch | 63 +
> .../ts72xx/0011-ts72xx_dio_keypad.patch | 311 ++
> .../linux-2.6.38/ts72xx/0012-ts72xx_sbcinfo.patch | 267 ++
> .../linux-2.6.38/ts72xx/0013-ts72xx_max197.patch | 356 ++
> .../ts72xx/0014-ts7200_nor_flash.patch | 181 +
> .../linux-2.6.38/ts72xx/0015-ts72xx_sdcard.patch | 3299 ++++++++++++++
> .../ts72xx/0016-ts72xx_spi_tmp124.patch | 305 ++
> .../0017-ts72xx-use-CPLD-watchdog-for-reset.patch | 53 +
> .../ts72xx/0018-ethoc-ts7300-fixes.patch | 72 +
> .../ts72xx/0019-ts7300-add-ethernet-support.patch | 87 +
> .../ts72xx/0020-ts72xx-add-lcd-linux-driver.patch | 4572 ++++++++++++++++++++
> .../ts72xx/0021-TS-72XX-LCD-console-driver.patch | 528 +++
> ...M-ep93xx-Fix-inverted-RTS-and-DTR-signals.patch | 38 +
> recipes/linux/linux-2.6.38/ts72xx/defconfig | 2214 ++++++++++
> recipes/linux/linux_2.6.36.bb | 25 -
> recipes/linux/linux_2.6.38.bb | 26 +
> .../0001-fix-LanesTimer-inifinite-thread-GC.patch | 31 -
> recipes/lua/lua-lanes-2.0.6/makefile.patch | 207 -
> recipes/lua/lua-lanes-2.0.6/uclibc.patch | 13 -
> recipes/lua/lua-lanes-2.1.0/makefile.patch | 207 +
> recipes/lua/lua-lanes-2.1.0/uclibc.patch | 13 +
> recipes/lua/lua-lanes_2.0.6.bb | 33 -
> recipes/lua/lua-lanes_2.1.0.bb | 34 +
> recipes/lua/lua-rs232_1.0.0.bb | 28 -
> recipes/lua/lua-rs232_1.0.1.bb | 28 +
> recipes/zeromq/zeromq_2.1.1.bb | 20 +
> 59 files changed, 15843 insertions(+), 15335 deletions(-)
> delete mode 100644 recipes/librs232/librs232_1.0.0.bb
> create mode 100644 recipes/librs232/librs232_1.0.1.bb
> delete mode 100644 recipes/linux/linux-2.6.36/ts72xx/0001-ts72xx_base.patch
> delete mode 100644 recipes/linux/linux-2.6.36/ts72xx/0002-ts72xx_force_machine-id.patch
> delete mode 100644 recipes/linux/linux-2.6.36/ts72xx/0003-ep93xx_cpuinfo.patch
> delete mode 100644 recipes/linux/linux-2.6.36/ts72xx/0004-ep93xx_eth.patch
> delete mode 100644 recipes/linux/linux-2.6.36/ts72xx/0005-ep93xx-m2m-DMA-support.patch
> delete mode 100644 recipes/linux/linux-2.6.36/ts72xx/0006-ts72xx_rs485.patch
> delete mode 100644 recipes/linux/linux-2.6.36/ts72xx/0007-ts72xx_ts_ser1.patch
> delete mode 100644 recipes/linux/linux-2.6.36/ts72xx/0008-ts72xx_ts_eth100.patch
> delete mode 100644 recipes/linux/linux-2.6.36/ts72xx/0009-ts72xx_pata.patch
> delete mode 100644 recipes/linux/linux-2.6.36/ts72xx/0010-ts72xx_gpio_i2c.patch
> delete mode 100644 recipes/linux/linux-2.6.36/ts72xx/0011-ts72xx_dio_keypad.patch
> delete mode 100644 recipes/linux/linux-2.6.36/ts72xx/0012-ts72xx_sbcinfo.patch
> delete mode 100644 recipes/linux/linux-2.6.36/ts72xx/0013-ts72xx_max197.patch
> delete mode 100644 recipes/linux/linux-2.6.36/ts72xx/0014-ts7200_nor_flash.patch
> delete mode 100644 recipes/linux/linux-2.6.36/ts72xx/0015-ts72xx_sdcard.patch
> delete mode 100644 recipes/linux/linux-2.6.36/ts72xx/0016-ts72xx_spi_tmp124.patch
> delete mode 100644 recipes/linux/linux-2.6.36/ts72xx/0017-ts72xx-use-CPLD-watchdog-for-reset.patch
> delete mode 100644 recipes/linux/linux-2.6.36/ts72xx/0018-ethoc-ts7300-fixes.patch
> delete mode 100644 recipes/linux/linux-2.6.36/ts72xx/0019-ts7300-add-ethernet-support.patch
> delete mode 100644 recipes/linux/linux-2.6.36/ts72xx/0023-ts72xx-add-lcd-linux-driver.patch
> delete mode 100644 recipes/linux/linux-2.6.36/ts72xx/0024-ts72xx-add-GPIO-keys.patch
> delete mode 100644 recipes/linux/linux-2.6.36/ts72xx/defconfig
> create mode 100644 recipes/linux/linux-2.6.38/ts72xx/0001-ts72xx_base.patch
> create mode 100644 recipes/linux/linux-2.6.38/ts72xx/0002-ts72xx_force_machine-id.patch
> create mode 100644 recipes/linux/linux-2.6.38/ts72xx/0003-ep93xx_cpuinfo.patch
> create mode 100644 recipes/linux/linux-2.6.38/ts72xx/0004-ep93xx_eth.patch
> create mode 100644 recipes/linux/linux-2.6.38/ts72xx/0005-ep93xx-m2m-DMA-support.patch
> create mode 100644 recipes/linux/linux-2.6.38/ts72xx/0006-ts72xx_rs485.patch
> create mode 100644 recipes/linux/linux-2.6.38/ts72xx/0007-ts72xx_ts_ser1.patch
> create mode 100644 recipes/linux/linux-2.6.38/ts72xx/0008-ts72xx_ts_eth100.patch
> create mode 100644 recipes/linux/linux-2.6.38/ts72xx/0009-ts72xx_pata.patch
> create mode 100644 recipes/linux/linux-2.6.38/ts72xx/0010-ts72xx_gpio_i2c.patch
> create mode 100644 recipes/linux/linux-2.6.38/ts72xx/0011-ts72xx_dio_keypad.patch
> create mode 100644 recipes/linux/linux-2.6.38/ts72xx/0012-ts72xx_sbcinfo.patch
> create mode 100644 recipes/linux/linux-2.6.38/ts72xx/0013-ts72xx_max197.patch
> create mode 100644 recipes/linux/linux-2.6.38/ts72xx/0014-ts7200_nor_flash.patch
> create mode 100644 recipes/linux/linux-2.6.38/ts72xx/0015-ts72xx_sdcard.patch
> create mode 100644 recipes/linux/linux-2.6.38/ts72xx/0016-ts72xx_spi_tmp124.patch
> create mode 100644 recipes/linux/linux-2.6.38/ts72xx/0017-ts72xx-use-CPLD-watchdog-for-reset.patch
> create mode 100644 recipes/linux/linux-2.6.38/ts72xx/0018-ethoc-ts7300-fixes.patch
> create mode 100644 recipes/linux/linux-2.6.38/ts72xx/0019-ts7300-add-ethernet-support.patch
> create mode 100644 recipes/linux/linux-2.6.38/ts72xx/0020-ts72xx-add-lcd-linux-driver.patch
> create mode 100644 recipes/linux/linux-2.6.38/ts72xx/0021-TS-72XX-LCD-console-driver.patch
> create mode 100644 recipes/linux/linux-2.6.38/ts72xx/0024-ARM-ep93xx-Fix-inverted-RTS-and-DTR-signals.patch
> create mode 100644 recipes/linux/linux-2.6.38/ts72xx/defconfig
> delete mode 100644 recipes/lua/lua-lanes-2.0.6/0001-fix-LanesTimer-inifinite-thread-GC.patch
> delete mode 100644 recipes/lua/lua-lanes-2.0.6/makefile.patch
> delete mode 100644 recipes/lua/lua-lanes-2.0.6/uclibc.patch
> create mode 100644 recipes/lua/lua-lanes-2.1.0/makefile.patch
> create mode 100644 recipes/lua/lua-lanes-2.1.0/uclibc.patch
> delete mode 100644 recipes/lua/lua-lanes_2.0.6.bb
> create mode 100644 recipes/lua/lua-lanes_2.1.0.bb
> delete mode 100644 recipes/lua/lua-rs232_1.0.0.bb
> create mode 100644 recipes/lua/lua-rs232_1.0.1.bb
> create mode 100644 recipes/zeromq/zeromq_2.1.1.bb
>
>
> _______________________________________________
> Openembedded-devel mailing list
> Openembedded-devel@lists.openembedded.org
> http://lists.linuxtogo.org/cgi-bin/mailman/listinfo/openembedded-devel
^ permalink raw reply [flat|nested] 10+ messages in thread
end of thread, other threads:[~2011-04-10 1:59 UTC | newest]
Thread overview: 10+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2011-04-02 14:18 [PATCH 0/6] RFC: patches I plan to push Petr Štetiar
2011-04-02 14:18 ` [PATCH 1/6] zeromq: add new recipe for version 2.1.1 Petr Štetiar
2011-04-02 14:18 ` [PATCH 2/6] lua-lanes: add recipe for version 2.1.0 and delete the old one Petr Štetiar
2011-04-02 14:18 ` [PATCH 3/6] librs232: add version 1.0.1 and remove " Petr Štetiar
2011-04-02 14:18 ` [PATCH 4/6] lua-rs232: add recipe for version 1.0.1, remove old package and fix stripping Petr Štetiar
2011-04-02 14:18 ` [PATCH 5/6] linux-2.6.36: remove ts72xx support because 2.6.38 is now default Petr Štetiar
2011-04-02 16:08 ` Koen Kooi
2011-04-02 16:31 ` Petr Štetiar
2011-04-02 14:18 ` [PATCH 6/6] linux-2.6.38: add support for ts72xx and make it default Petr Štetiar
2011-04-10 1:57 ` [PATCH 0/6] RFC: patches I plan to push Khem Raj
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.