[PATCH 4/4] ARM: support for CPO Science DataCollector II

Darren Garnier dgarnier at reinrag.net
Mon Sep 2 22:22:58 EDT 2013


Signed-off-by: Darren Garnier <dgarnier at reinrag.net>
---
arch/arm/boards/Makefile                  |   1 +
arch/arm/boards/cpodc2/Makefile           |   4 +
arch/arm/boards/cpodc2/env/boot/dataflash |  10 +
arch/arm/boards/cpodc2/env/boot/net-usb   |  22 ++
arch/arm/boards/cpodc2/env/config-board   |   6 +
arch/arm/boards/cpodc2/env/dfu.png        | Bin 0 -> 1669 bytes
arch/arm/boards/cpodc2/env/init/automount |  12 +
arch/arm/boards/cpodc2/env/init/msp430    |  10 +
arch/arm/boards/cpodc2/env/init/mtdparts  |  19 ++
arch/arm/boards/cpodc2/env/init/splash    |   8 +
arch/arm/boards/cpodc2/env/init/usb       |  55 ++++
arch/arm/boards/cpodc2/env/splash.png     | Bin 0 -> 1356 bytes
arch/arm/boards/cpodc2/env/usb.png        | Bin 0 -> 339 bytes
arch/arm/boards/cpodc2/init.c             | 364 +++++++++++++++++++++
arch/arm/boards/cpodc2/lowlevel_init.c    | 108 +++++++
arch/arm/boards/cpodc2/msp430.c           | 513 ++++++++++++++++++++++++++++++
arch/arm/boards/cpodc2/msp430.h           |  23 ++
arch/arm/configs/cpodc2_defconfig         |  96 ++++++
arch/arm/mach-at91/Kconfig                |  24 ++
19 files changed, 1275 insertions(+)
create mode 100644 arch/arm/boards/cpodc2/Makefile
create mode 100755 arch/arm/boards/cpodc2/env/boot/dataflash
create mode 100755 arch/arm/boards/cpodc2/env/boot/net-usb
create mode 100755 arch/arm/boards/cpodc2/env/config-board
create mode 100644 arch/arm/boards/cpodc2/env/dfu.png
create mode 100755 arch/arm/boards/cpodc2/env/init/automount
create mode 100644 arch/arm/boards/cpodc2/env/init/msp430
create mode 100755 arch/arm/boards/cpodc2/env/init/mtdparts
create mode 100755 arch/arm/boards/cpodc2/env/init/splash
create mode 100755 arch/arm/boards/cpodc2/env/init/usb
create mode 100644 arch/arm/boards/cpodc2/env/splash.png
create mode 100644 arch/arm/boards/cpodc2/env/usb.png
create mode 100644 arch/arm/boards/cpodc2/init.c
create mode 100644 arch/arm/boards/cpodc2/lowlevel_init.c
create mode 100644 arch/arm/boards/cpodc2/msp430.c
create mode 100644 arch/arm/boards/cpodc2/msp430.h
create mode 100644 arch/arm/configs/cpodc2_defconfig

diff --git a/arch/arm/boards/Makefile b/arch/arm/boards/Makefile
index 38ef512..0c93187 100644
--- a/arch/arm/boards/Makefile
+++ b/arch/arm/boards/Makefile
@@ -16,6 +16,7 @@ obj-$(CONFIG_MACH_CCMX51)			+= ccxmx51/
obj-$(CONFIG_MACH_CFA10036)			+= crystalfontz-cfa10036/
obj-$(CONFIG_MACH_CHUMBY)			+= chumby_falconwing/
obj-$(CONFIG_MACH_CLEP7212)			+= clep7212/
+obj-$(CONFIG_MACH_CPODC2)			+= cpodc2/
obj-$(CONFIG_MACH_DFI_FS700_M60)		+= dfi-fs700-m60/
obj-$(CONFIG_MACH_DSS11)			+= dss11/
obj-$(CONFIG_MACH_EDB93012)			+= edb93xx/
diff --git a/arch/arm/boards/cpodc2/Makefile b/arch/arm/boards/cpodc2/Makefile
new file mode 100644
index 0000000..2bfa4fa
--- /dev/null
+++ b/arch/arm/boards/cpodc2/Makefile
@@ -0,0 +1,4 @@
+obj-y += init.o
+obj-$(CONFIG_CPODC2_MSP430) += msp430.o
+
+lwl-$(CONFIG_HAVE_AT91_LOWLEVEL_INIT) += lowlevel_init.o
diff --git a/arch/arm/boards/cpodc2/env/boot/dataflash b/arch/arm/boards/cpodc2/env/boot/dataflash
new file mode 100755
index 0000000..bc59750
--- /dev/null
+++ b/arch/arm/boards/cpodc2/env/boot/dataflash
@@ -0,0 +1,10 @@
+#!/bin/sh
+
+if [ "$1" = menu ]; then
+	boot-menu-add-entry "$0" "dataflash"
+	exit
+fi
+
+global.bootm.image="/dev/dataflash0.kernel"
+#global.bootm.oftree="/env/oftree"
+global.linux.bootargs.dyn.root="root=ubi0:rootfs ubi.mtd=nand0.root rootfstype=ubifs"
diff --git a/arch/arm/boards/cpodc2/env/boot/net-usb b/arch/arm/boards/cpodc2/env/boot/net-usb
new file mode 100755
index 0000000..6e341a0
--- /dev/null
+++ b/arch/arm/boards/cpodc2/env/boot/net-usb
@@ -0,0 +1,22 @@
+#!/bin/sh
+
+if [ "$1" = menu ]; then
+	boot-menu-add-entry "$0" "network (tftp, nfs) (usb ethernet)"
+	exit
+fi
+
+usb -f
+ethact eth1
+
+if [ $? -ne 0 ]; then
+	echo "ERROR: usb ethernet not found"
+	exit 1
+fi
+
+path="/mnt/tftp"
+
+global.bootm.image="${path}/${global.user}-linux-${global.hostname}"
+#global.bootm.oftree="${path}/${global.user}-oftree-${global.hostname}"
+nfsroot="/home/${global.user}/nfsroot/${global.hostname}"
+bootargs-ip
+global.linux.bootargs.dyn.root="root=/dev/nfs nfsroot=$nfsroot,v3,tcp"
diff --git a/arch/arm/boards/cpodc2/env/config-board b/arch/arm/boards/cpodc2/env/config-board
new file mode 100755
index 0000000..8ee2290
--- /dev/null
+++ b/arch/arm/boards/cpodc2/env/config-board
@@ -0,0 +1,6 @@
+#!/bin/sh
+
+global.hostname=cpodc2
+global.user=cpodc2
+global.autoboot_timeout=1
+global.boot.default=dataflash
diff --git a/arch/arm/boards/cpodc2/env/dfu.png b/arch/arm/boards/cpodc2/env/dfu.png
new file mode 100644
index 0000000000000000000000000000000000000000..a8f2cdd96c739efb4d8985a51f76499f31c6a05e
GIT binary patch
literal 1669
zcmZ`)XH-*Z5PcF at l_o{1peRL}lH>_uSy2c|389EeixSW$2nig6^csQ~60xD?xki_;
zB%p|j5k&+M5GetLAP9lu>Y4y5EKLYfvTxn9$3MGsX6Al#=g!Q}kKseur>1PE3;=+d
zyBp3AK`9btD^N%dNHEDpAj=2u?~0&YE{9<l1VN!t2tg14Aq5N|_4fc^2!MqU2qFy-
z0FXW`L^=op00<ys2n!<AcZFPzh#&|Cg~&Jr%V9u>=pYbA_Q8-`j+{XDK`_EVfE>99
zK|$V*!vLW4%pJGKKe2z56PdEcN;MPXoWCP*YsVWSFA=$ata4HA6kDaKN_{*?erl5D
zj?K<YFf+ at VV&%wQ;V3*;fhntnE%(F+R&}tE7e8}E;lgy{Pv<cPm;Ux`g=mX#EM&^|
z$S>Z6_W{Kx`cx&*L4Uo1JF&OSg$@hx7b?`Ko5L$L$mZc#MEYMIPt_GDJYb-N$L{9n
zqV--C1<$Q^{W at -tHzAJnQKIGiFv*)&n)=@l|8xF-^8=J{Mh^EV$L-nHwvs3#ulu||
zPBXXPd*dk7vCFc$l!jYZP_X~ZTF0E>tbgI&54$edy)!kvsQ5tZ?a}xYiRHT+oSHPz
zW=Xutjfy~mXJq at _lCX8YQWjrLtWPDdy<qC2nrg9O#}MyM)uKxqM at k=k07A?tYJwhG
zDTGL595f{hEH2MX@?H#79{I+udk_VWOP8SI+8(0#r*o<4OOd@#9*yndL{-JCotknF
zbG~SQ$G6_MM-gXbzQK0dnyez4DUln{9vYU=WQEe|15CT-qA2YT;=Y2$zQbFUy{Lm)
z=j#1!j`ZawE85H$XL$Z<gZBDu(|Tjer`9~@KkheG2|8%Y%bv5yZF)HC)B||8{MyDU
z);85`#q$;z`+42x at 0cS4(O0M|sfmfnhAWC^{TG4JRDz;N6&GUT>VA*e({Y9FWjUrY
z5u21W;^-@(+;Smu1$kB){+QdCej at 7{<tyKbqinEOPT?jpBHNXc6fq)~9i$znjPJir
z_+ZK!YZ}yR*k2dd)EIqwWCZ8RZftbi-ZfoVk6m8zZION+{}vTNKGseQRfY at dpLB(E
z<*P#%tZtSF^$W9V?TYNzaWS6>9tyGJBbrdEmS!nyU at w^d?1oWkBPFfZoJV0T at iX3r
z`rXcGjwA=oTFeeg-Y>l;jVGN5gC)z}p3KK|R(Um3VQw|F1;qOw^I0A?pe4%IS2h_o
z#ha<D>b6vGZmIj^qMfXF$sRxLsUAH(YfADFT$384Y^*#dexZ=E6|6k1==(fwDYsh}
zk|}7LDK&g$Q?_>=GCs_37lhj?X^D1w*lr*v8)0mLKu2vhHaNiXWYA~{`s#5W#vQ0^
z*1?}?>efo;=1riO3+qh+b+OM5zO<F9outE5SMgf)T$1koi?4A*E*Q>>Y}t*Yn|QAH
zBCVG$d at Qqcp^oicURQ8R*wFj(Zf;kEXfA{|ca;6`D*Di~YzI<T?(eY6BYXVNO{cSS
zGMNn9Xfo-^wq`JH?F+5P@|gD!S~AhL{#!Ui06y`Vgs5ytLnEpzklMcz&zi$Y*Fypa
zreWt$dqZ2BMlLsPcpyIs7qVhc0F!trifTlYqQkwIuvP4JA1pOIF95}<vp9Id;+J9?
z=8f+gy26%1y5X6g1DOH5HIuSd{-M6YXssqqNmiNcl3k|Pgt6zc6 at l$XnLE#UUs-<t
z<JH<pR0Rp|IT)jZE>K0+Pp at nxSWrx(?{DnUN%8Ak(2l=e_-#@r_;Ae2?d3sVavUoB
zz8uprVMLIQ6jp at Ukth)~?hbxHU{2T1ZT#}M1T`~;+n=?IbDM_-8qW$#N;tNIZPsc2
zYBrXrM+4m+vvh;8(uMQ3Gq-B^G?>Rde<eL5V?p0><md<mv~F!V8_*xqy&7yEKGK=y
zX0DGORPQB+l2W%1znXV8X<miyEH_GVB3iI(b0*K8$SXn#zi=bzIb4okznch!$G$HU
z+w&iLs<qm*M7Hc1pD^}zxYiqzFt8BQ{KDkPh0mXvYb~8pACCc3GxM{-l~8chRM@))
z1)X`ZSl!W%k`W+e*4*6`^iY}}ld<qnUIWixj+n2bH*sd-KCWvb+N)5NLYE=G0^sgS
Kz?D0P(*6Q%7!#@h

literal 0
HcmV?d00001

diff --git a/arch/arm/boards/cpodc2/env/init/automount b/arch/arm/boards/cpodc2/env/init/automount
new file mode 100755
index 0000000..3227619
--- /dev/null
+++ b/arch/arm/boards/cpodc2/env/init/automount
@@ -0,0 +1,12 @@
+#!/bin/sh
+
+if [ "$1" = menu ]; then
+	init-menu-add-entry "$0" "Automountpoints"
+	exit
+fi
+
+mkdir -p /mnt/tftp
+automount /mnt/tftp 'ifup eth0 && mount -t tftp $eth0.serverip /mnt/tftp'
+
+mkdir -p /mnt/fat
+automount -d /mnt/fat 'usb && [ -e /dev/disk0.0 ] && mount /dev/disk0.0 /mnt/fat'
diff --git a/arch/arm/boards/cpodc2/env/init/msp430 b/arch/arm/boards/cpodc2/env/init/msp430
new file mode 100644
index 0000000..0639313
--- /dev/null
+++ b/arch/arm/boards/cpodc2/env/init/msp430
@@ -0,0 +1,10 @@
+#!/bin/sh
+# reset it if it needs it
+msp430 -r
+# wait a moment for it to recover
+msleep 500
+
+msp430 -i -M msp_fw_major -m msp_fw_minor -S msp_serial -T msp_boardtype
+
+msp430 -b on
+
diff --git a/arch/arm/boards/cpodc2/env/init/mtdparts b/arch/arm/boards/cpodc2/env/init/mtdparts
new file mode 100755
index 0000000..81c18b4
--- /dev/null
+++ b/arch/arm/boards/cpodc2/env/init/mtdparts
@@ -0,0 +1,19 @@
+#!/bin/sh
+
+if [ "$1" = menu ]; then
+	init-menu-add-entry "$0" "MTD Partitions"
+	exit
+fi
+
+mtdparts="0x4200(dataflash0.bootstrap),0x4200(dataflash0.bareboxenv),0x39C00(dataflash0.barebox),0x1BE000(dataflash0.kernel)"
+mtdparts-add -d dataflash0 -p ${mtdparts}
+
+# mtdparts broken for - partitions
+mtdparts="256M(nand0.root)"
+kernelname="atmel_nand"
+# we don't really need this unless doing dfu...
+#mtdparts-add -b -d nand0 -p ${mtdparts} -k ${kernelname}
+
+mtdparts="-(nand0.root)"
+global linux.mtdparts.nand0
+global.linux.mtdparts.nand0="${kernelname}:${mtdparts}"
diff --git a/arch/arm/boards/cpodc2/env/init/splash b/arch/arm/boards/cpodc2/env/init/splash
new file mode 100755
index 0000000..18e74df
--- /dev/null
+++ b/arch/arm/boards/cpodc2/env/init/splash
@@ -0,0 +1,8 @@
+#!/bin/sh
+
+splash=/env/splash.png
+
+if [ -f ${splash} -a -e /dev/fb0 ]; then
+	splash -o ${splash}
+	fb0.enable=1
+fi
diff --git a/arch/arm/boards/cpodc2/env/init/usb b/arch/arm/boards/cpodc2/env/init/usb
new file mode 100755
index 0000000..ca7f017
--- /dev/null
+++ b/arch/arm/boards/cpodc2/env/init/usb
@@ -0,0 +1,55 @@
+#!/bin/sh
+
+pre_wait=2
+post_wait=3
+polarity=1
+
+dfu_config="/dev/dataflash0.bootstrap(bootstrap)sr,/dev/dataflash0.bareboxenv(bareboxenv)sr,/dev/dataflash0.barebox(barebox)sr,/dev/dataflash0.kernel(kernel)sr,/dev/nand0.root.bb(root)r"
+
+echo
+
+if [ $at91_udc0.vbus != 1 ]; then
+	echo "No USB Device cable plugged, normal boot"
+	exit
+fi
+
+splash=/env/usb.png
+if [ -f ${splash} -a -e /dev/fb0 ]; then
+	splash -y 20 -x 280 ${splash} 
+	fb0.enable=1
+fi
+
+timeout -s -a ${pre_wait} 
+
+gpio_get_value ${dfu_button}
+if [ $? = ${polarity} ]; then
+	echo "dfu_button detected wait ${post_wait}s"
+	timeout -s -a ${post_wait}
+
+	if [ $at91_udc0.vbus != 1 ]; then
+		echo "No USB Device cable plugged, normal boot"
+		exit
+	fi
+
+	gpio_get_value ${dfu_button}
+	if [ $? = ${polarity} ]; then
+		echo "Start DFU Mode"
+		splash=/env/dfu.png
+		if [ -f ${splash} -a -e /dev/fb0 ]; then
+			splash -o -b 0 ${splash}
+		fi
+		# mount mtd for dfu writing...
+		mtdparts="256M(nand0.root)"
+		mtdparts-add -b -d nand0 -p ${mtdparts}
+
+		#Use NetChip's donated numbers
+		dfu ${dfu_config} -P 0xFFFF -V 0x0525 -m "CPO Science" -p "DataCollector (DFU mode)"
+		#if the dfu works.. we want to reboot
+		reset
+		#exit
+	fi
+fi
+
+global.autoboot_timeout=16
+echo "enable tty over USB Device, waiting ${global.autoboot_timeout}s"
+usbserial
diff --git a/arch/arm/boards/cpodc2/env/splash.png b/arch/arm/boards/cpodc2/env/splash.png
new file mode 100644
index 0000000000000000000000000000000000000000..36e8ed1d9849a36d763dbc6750ad953cc35a0a68
GIT binary patch
literal 1356
zcmV-S1+)5zP)<h;3K|Lk000e1NJLTq008g+002M;0{{R36F~~q0001BP)t-s0096n
z4kR2M8&DKXE-MvEBOM7dO)M at eLqkB6CXW(WcT`pbi9{+eUoTQrQ3i3c at IW?YXJo-!
zNPd5Pg@=S8rrR^KZ}gECqNJgay*9qUy~)eS)z{SD;@<x90R8{`0k=xK000E1Nkl<Z
zXx{CZ>vp3c5P&V)Msl;AVpA3+y#HIS+y_KWPj}DusPiWY0-2AwVpZ+3%Pza at vdiY=
za5^3Ax2Ipn<J0PSU$q$Gr=ym&6CVultNwblvJK#aH}LWJYn`Cv^l>5)n5-W7L(9R(
z at cLc)WPnf3#HVWYNy`F%q=RcNOC(r$D^f7<>Km-XMo6!>+jUEpCAZtQh_4#>wgWG?
z#US|eUkWfM at W@{=rM~3S4Od1uEbOX;)@AsVU(#N$R9^#@DhjW^4~&x*MVm|dV}OOW
zZ!3&i;`_i+gi55Ze+V!Os|SPh<Zl6!Ugbi67;sg!OEz8vzMh{G`wA1h(9QbK{{z;<
zEVa`DaQ6K7AkR at 1)l?{)#ni$n;Ig-oIbbqBe*|20XgwIG><1eW!SzZZwAw<rEvQYw
z?eNo$T{W;xS-B6Bj)(8HUC7BCaBBlU(T*^i2D#lBg!vg1YVA*d$}p%}HTc*Iz%-gT
z<eaW1Mi1f#?EXB&W>dMb2+T$<TvsWI7B&e?OOYQJ+O1ilP@|&4VcTZp^BM4fDZ at X4
zHwSn<kV{Kn#+ZKY4nYH(Fa2b2CCRLx0OmN?@lw{8Bm;&~di0OmSzwPOqkWoq at DZ5D
zqc;f7tDapA#)_7Tm9*X%EtLRUW3>R*g&TYbf=iD9(tMQ~-nm3)k5fkAHtQ~OV6aFW
zyAq6nYaAIQ0((IYTjl!?O6%FR at Gv7_8RCHmKSpB~)Pqfyv<y0ggW>)mo6pi_Ut$#I
zNh-^M+ay5w<G{uOwLdiL)HyK3Id&)T9Db1HSsGBZb2nJ7S!G~I3D^iYO?~unVEmv(
znqgo)E`5*Rxdp+3#X8*L5OPylv8<O}I;*#&0Gwf1;Pd@{o&|0ca{t;nX%5`wEgEwr
zV!H8=`2V>5!HT_3IcYJ~r9ck?-|voCPGsrS%~YzH2UZ1OIuD%GFBZ4ui@?&wyZjz-
zTl7E|YdG1JEG$hLM*_|p<}C~b3oimUb{(XfLjjm3F7NB`{r)?8YqE#!jtD*oHW9;o
zR6KJVj)0RTD25k-r9(?2kdJ_QvQ-=6 at _feSRwU(@dS!Za7ncQKrp9&7r1!8N&4C%p
z;rJYvfCZ}Z1SjDfm?p<v(9fD!I%9(L3Zb4;cx#X9Fgh&WHMoHL;}&^Jh&OJ)b$A|F
zw*ovkX*kYW7CNn=1+8)OM2h)X>&TeEt+Q>8TGqzias+IiNd}E6N`2$+HJX6gl|4;?
z!9SIu*_;9vuHcCz&(ur3bnmY_!&r-eUoMwX|DU|%!M$|%NH5(__0mbwFZa at X_MKMp
z;;HUK%S%ZCnAj+_T_6Jf{QSJ&8Oi-7Q(R2mmKa(X%66CYCRL8-7pw)~p0hLw61T%}
z-z@?Az*K@(2>5vb{tPpMiUK!g_M)wPbQbT!wL6v`#tR2;FO_vF(%TW6yueIK4M1ln
zG_1*oqJ`azK}M5EVc|$96edxCW^M`m^B3E>gc#ms&2o9$n3><+-d=X#-KE!u{k|<T
zzr4R+wg#*%OfDDml9JN(BNNw&Xl_a=*@mH=g~=8yyvr`T?6S))56T}~&+3n?60v9i
O0000<MNUMnLSTZ8qK35q

literal 0
HcmV?d00001

diff --git a/arch/arm/boards/cpodc2/env/usb.png b/arch/arm/boards/cpodc2/env/usb.png
new file mode 100644
index 0000000000000000000000000000000000000000..6eed849142f96d404c82be3a1aa5ee9363839223
GIT binary patch
literal 339
zcmV-Z0j&OsP)<h;3K|Lk000e1NJLTq001BW002M)0{{R3iJ)km0000OP)t-s0RaIi
zDJf1)PIh*7k&%(Hv9Zm~&HViQd&z7Y0002?Nkl<ZILoEeJr9B~5C&jM`B=e0R-9ao
ziz}O}gNd`oz^a0M|GuTP(7Qwp%GM`^d)qsL;N6pPxUjW+GAK||*yBdl0-*0iHELQ%
zDqiJB$n!k&K>|4Z3E}r0`al)Uft5LW=|GrU5)CQ>3D6QK%w>Iol)s|$oh?Y1(-&Q4
zp%`u{ZEX&L2L;zX2X4a%V|y)(8yrmix6sG4(3worfW$D+db80-M>Vx^r!o!xwCIAg
z*=uYl2q-oVOB at xSN(PdHF3lj}5X~RUNYPOb8(e8sf0~AN(jO-7!T-rp1JxWz_%}=y
llJ%tFPLk^lH2Y#}*DoRUUl?ijBf9_q002ovPDHLkV1fr|kBtBT

literal 0
HcmV?d00001

diff --git a/arch/arm/boards/cpodc2/init.c b/arch/arm/boards/cpodc2/init.c
new file mode 100644
index 0000000..7bad587
--- /dev/null
+++ b/arch/arm/boards/cpodc2/init.c
@@ -0,0 +1,364 @@
+/*
+ * Copyright (C) 2007 Sascha Hauer, Pengutronix
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the 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 <common.h>
+#include <net.h>
+#include <init.h>
+#include <environment.h>
+#include <asm/armlinux.h>
+#include <generated/mach-types.h>
+#include <partition.h>
+#include <fs.h>
+#include <fcntl.h>
+#include <io.h>
+#include <asm/hardware.h>
+#include <nand.h>
+#include <sizes.h>
+#include <linux/mtd/nand.h>
+#include <mach/cpu.h>
+#include <mach/at91_pmc.h>
+#include <mach/board.h>
+#include <gpio.h>
+#include <mach/io.h>
+#include <mach/iomux.h>
+#include <mach/at91sam9_smc.h>
+#include <dm9000.h>
+#include <gpio_keys.h>
+#include <readkey.h>
+#include <led.h>
+#include <spi/spi.h>
+
+#ifdef CONFIG_CPODC2_MSP430
+#include "msp430.h"
+#endif
+
+static struct atmel_nand_data nand_pdata = {
+	.ale		= 22,
+	.cle		= 21,
+	.det_pin	= -EINVAL,
+	.rdy_pin	= AT91_PIN_PC15,
+	.enable_pin	= AT91_PIN_PC14,
+#if defined(CONFIG_MTD_NAND_ATMEL_BUSWIDTH_16)
+	.bus_width_16	= 1,
+#else
+	.bus_width_16	= 0,
+#endif
+	.on_flash_bbt	= 1,
+};
+
+static struct sam9_smc_config dc_nand_smc_config = {
+	.ncs_read_setup		= 0,
+	.nrd_setup		= 1,
+	.ncs_write_setup	= 0,
+	.nwe_setup		= 1,
+
+	.ncs_read_pulse		= 3,
+	.nrd_pulse		= 3,
+	.ncs_write_pulse	= 3,
+	.nwe_pulse		= 3,
+
+	.read_cycle		= 5,
+	.write_cycle		= 5,
+
+	.mode			= AT91_SMC_READMODE | AT91_SMC_WRITEMODE | AT91_SMC_EXNWMODE_DISABLE,
+	.tdf_cycles		= 2,
+};
+
+static void dc_add_device_nand(void)
+{
+	/* setup bus-width (8 or 16) */
+	if (nand_pdata.bus_width_16)
+		dc_nand_smc_config.mode |= AT91_SMC_DBW_16;
+	else
+		dc_nand_smc_config.mode |= AT91_SMC_DBW_8;
+
+	/* configure chip-select 3 (NAND) */
+	sam9_smc_configure(0, 3, &dc_nand_smc_config);
+
+	at91_add_device_nand(&nand_pdata);
+}
+
+/*
+ * USB OHCI Host port
+ */
+#ifdef CONFIG_USB_OHCI_AT91
+static struct at91_usbh_data  __initdata usbh_data = {
+	.ports		= 1,
+	//.vbus_pin	= { AT91_PIN_PD0,  -EINVAL },
+};
+
+static void __init dc_add_device_usbh(void)
+{
+	if (cpu_is_at91sam9g10())  // add it just for boards with 9g10
+		at91_add_device_usbh_ohci(&usbh_data);
+}
+#else
+static void __init dc_add_device_usbh(void) {}
+#endif
+
+
+#if defined(CONFIG_USB_GADGET_DRIVER_AT91)
+/*
+ * USB Device port
+ */
+static struct at91_udc_data __initdata dc_udc_data = {
+	.vbus_pin	= AT91_PIN_PB29,
+	.pullup_pin	= 0,
+};
+
+static void dc_add_device_udc(void)
+{
+	at91_add_device_udc(&dc_udc_data);
+}
+#else
+static void dc_add_device_udc(void) {}
+#endif
+
+/*
+ * LCD Controller
+ */
+#if defined(CONFIG_DRIVER_VIDEO_ATMEL)
+static int dc_gpio_request_output(int gpio, const char *name)
+{
+	int ret;
+
+	ret = gpio_request(gpio, name);
+	if (ret) {
+		pr_err("%s: can not request gpio %d (%d)\n", name, gpio, ret);
+		return ret;
+	}
+
+	ret = gpio_direction_output(gpio, 1);
+	if (ret)
+		pr_err("%s: can not configure gpio %d as output (%d)\n", name, gpio, ret);
+	return ret;
+}
+
+/* TFT */
+static struct fb_videomode at91_tft_vga_modes[] = {
+	{
+		.name		= "320x240 at 60",
+		.refresh	= 60,
+		.xres		= 320,		.yres		= 240,
+		.pixclock	= KHZ2PICOS(6210),
+
+		.left_margin	= 62,		.right_margin	= 14,
+		.upper_margin	= 18,		.lower_margin	= 3,
+		.hsync_len	= 5,		.vsync_len	= 1,
+
+		.sync		= FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+		.vmode		= FB_VMODE_NONINTERLACED,
+	},
+};
+
+#define AT91SAM9261_DEFAULT_TFT_LCDCON2	(ATMEL_LCDC_MEMOR_LITTLE \
+					| ATMEL_LCDC_DISTYPE_TFT \
+					| ATMEL_LCDC_CLKMOD_ALWAYSACTIVE \
+					| ATMEL_LCDC_INVVD_INVERTED \
+					| ATMEL_LCDC_INVFRAME_INVERTED \
+					| ATMEL_LCDC_INVLINE_INVERTED \
+					| ATMEL_LCDC_INVCLK_INVERTED \
+					| ATMEL_LCDC_INVDVAL_INVERTED \
+					)
+
+static void at91_lcdc_tft_power_control(int on)
+{
+	if (on)
+		gpio_set_value(AT91_PIN_PA12, 0);	/* power up */
+	else
+		gpio_set_value(AT91_PIN_PA12, 1);	/* power down */
+}
+
+static struct atmel_lcdfb_platform_data dc_lcdc_data = {
+	.lcdcon_is_backlight	= false,
+	.default_bpp			= 16,
+	.default_dmacon			= ATMEL_LCDC_DMAEN,
+	.default_lcdcon2		= AT91SAM9261_DEFAULT_TFT_LCDCON2,
+	.guard_time			= 1,
+	.atmel_lcdfb_power_control	= at91_lcdc_tft_power_control,
+	.mode_list			= at91_tft_vga_modes,
+	.num_modes			= ARRAY_SIZE(at91_tft_vga_modes),
+};
+
+static int at91_lcdc_gpio(void)
+{
+	return dc_gpio_request_output(AT91_PIN_PA12, "lcdc_tft_power");
+}
+
+static void dc_add_device_lcdc(void)
+{
+	if (at91_lcdc_gpio())
+		return;
+
+	dc_lcdc_data.have_intensity_bit = cpu_is_at91sam9261();
+	
+	dc_lcdc_data.lcd_wiring_mode = cpu_is_at91sam9261() ? ATMEL_LCDC_WIRING_RGB
+	                                                    : ATMEL_LCDC_WIRING_BGR;
+
+	at91_add_device_lcdc(&dc_lcdc_data);
+}
+
+#else
+static void dc_add_device_lcdc(void) {}
+#endif
+
+static void __init dc_add_device_buttons(void)
+{
+	// this first call is necessary to turn on clocks for gpio...
+	gpio_request(AT91_PIN_PB30,"go_button");
+	gpio_direction_input(AT91_PIN_PB30);
+	// don't use pullup here.. so don't need this hack.
+	at91_set_gpio_input(AT91_PIN_PB30, 0);
+	//at91_set_deglitch(AT91_PIN_PB30, 1);
+
+	gpio_request(AT91_PIN_PC2, "ts_pen");
+	gpio_direction_input(AT91_PIN_PC2);
+	at91_set_gpio_input (AT91_PIN_PC2, 1); // pullup
+	at91_set_deglitch   (AT91_PIN_PC2, 1);
+	
+	export_env_ull("dfu_button", AT91_PIN_PB30);
+}
+
+/*
+ * SPI related devices
+ */
+#if defined(CONFIG_DRIVER_SPI_ATMEL)
+static struct spi_board_info dc_spi_devices[] = {
+	{	/* DataFlash chip */
+		.name		= "mtd_dataflash",
+		.chip_select	= 0,
+		.max_speed_hz	= 15 * 1000 * 1000,
+		.bus_num	= 0,
+	},
+};
+
+static unsigned spi0_standard_cs[] = { AT91_PIN_PA3, AT91_PIN_PA6};
+static struct at91_spi_platform_data spi_pdata = {
+	.chipselect = spi0_standard_cs,
+	.num_chipselect = ARRAY_SIZE(spi0_standard_cs),
+};
+
+static void dc_add_device_spi(void)
+{
+	spi_register_board_info(dc_spi_devices,
+				ARRAY_SIZE(dc_spi_devices));
+	at91_add_device_spi(0, &spi_pdata);
+}
+#else
+static void dc_add_device_spi(void) {}
+#endif
+
+static int cpodc2_mem_init(void)
+{
+	at91_add_device_sdram(0);
+
+	return 0;
+}
+mem_initcall(cpodc2_mem_init);
+
+static int __init main_clock(void)
+{
+	int tmp;
+	static int main_clock = 0;
+
+	// this works for both boards, but only if at91boostrap was used first to setup the PLL lock.
+	if (!main_clock) {
+		do { // wait for PLL lock..
+			tmp = at91_pmc_read(AT91_CKGR_MCFR);
+		} while (!(tmp & AT91_PMC_MAINRDY));
+		tmp = (tmp & AT91_PMC_MAINF) * (AT91_SLOW_CLOCK / 16);
+		main_clock = (tmp > 19500000) ? 20000000 : 18432000;
+	}
+
+	return main_clock;
+}
+
+static int cpodc2_devices_init(void)
+{
+	u32 board_revision = 0;
+
+	dc_add_device_spi();
+	dc_add_device_nand();
+	dc_add_device_udc();
+	dc_add_device_usbh();
+	dc_add_device_buttons();
+	dc_add_device_lcdc();
+
+	if (! IS_ENABLED(CONFIG_MTD_DATAFLASH)) {
+		if (IS_ENABLED(CONFIG_AT91_LOAD_BAREBOX_SRAM)) {
+			devfs_add_partition("nand0", 0, SZ_256K + SZ_128K, DEVFS_PARTITION_FIXED, "self_raw");
+			export_env_ull("borebox_first_stage", 1);
+		} else {
+			devfs_add_partition("nand0", 0x00000, SZ_128K, DEVFS_PARTITION_FIXED, "bootstrap_raw");
+			dev_add_bb_dev("bootstrap_raw","bootstrap");
+			devfs_add_partition("nand0", SZ_128K, SZ_256K, DEVFS_PARTITION_FIXED, "self_raw");
+		}
+		dev_add_bb_dev("self_raw", "self0");
+		devfs_add_partition("nand0", SZ_256K + SZ_128K, SZ_128K, DEVFS_PARTITION_FIXED, "env_raw");
+		dev_add_bb_dev("env_raw", "env0");
+		devfs_add_partition("nand0", SZ_512K, SZ_128K, DEVFS_PARTITION_FIXED, "env_raw1");
+		dev_add_bb_dev("env_raw1", "env1");
+	} else { // dataflash partitions
+		devfs_add_partition("dataflash0", 0x00000, 0x4200,  DEVFS_PARTITION_FIXED, "bootstrap");
+		devfs_add_partition("dataflash0", 0x04200, 0x4200,  DEVFS_PARTITION_FIXED, "env0");
+		devfs_add_partition("dataflash0", 0x08400, 0x39C00, DEVFS_PARTITION_FIXED, "self0");
+	}
+
+	// we should probably also get revision data from the msp430
+	// but it takes a while to load...
+	// just fix based on whether CPU is 9g10
+	
+	if (nand_pdata.bus_width_16)
+		board_revision |= (1<<31);
+
+	if (cpu_is_at91sam9g10())
+		board_revision |= (0x01<<8);
+
+	if (main_clock() > 19500000)
+		board_revision |= (0x01<<10);
+
+	armlinux_set_revision(board_revision);
+	armlinux_set_bootparams((void *)(AT91_CHIPSELECT_1 + 0x100));
+	armlinux_set_architecture(MACH_TYPE_CPODC2);
+
+	return 0;
+}
+device_initcall(cpodc2_devices_init);
+
+static int cpodc2_console_init(void)
+{
+	barebox_set_model("CPO Science DataCollector II");
+	barebox_set_hostname("cpodc2");
+	
+	at91_register_uart(0, 0);
+#ifdef CONFIG_CPODC2_MSP430
+	at91_register_uart(1, 0);
+	// deactivate console and use it for the msp command
+	cpodc2_msp430_init_console("atmel_usart1");
+#endif
+	return 0;
+}
+console_initcall(cpodc2_console_init);
+
+static int cpodc2_main_clock(void)
+{
+	// bootloader should have set the frequency:
+	at91_set_main_clock(main_clock());
+	
+	return 0;
+}
+pure_initcall(cpodc2_main_clock);
+
diff --git a/arch/arm/boards/cpodc2/lowlevel_init.c b/arch/arm/boards/cpodc2/lowlevel_init.c
new file mode 100644
index 0000000..0565841
--- /dev/null
+++ b/arch/arm/boards/cpodc2/lowlevel_init.c
@@ -0,0 +1,108 @@
+/*
+ * Copyright (C) 2009-2011 Jean-Christophe PLAGNIOL-VILLARD <plagnioj at jcrosoft.com>
+ *
+ * Under GPLv2
+ */
+
+#include <common.h>
+#include <init.h>
+#include <mach/hardware.h>
+#include <mach/at91_rstc.h>
+#include <mach/at91_wdt.h>
+#include <mach/at91_pmc.h>
+#include <mach/at91sam9_smc.h>
+#include <mach/at91sam9_sdramc.h>
+#include <mach/at91sam9_matrix.h>
+#include <mach/at91_lowlevel_init.h>
+
+#define MASTER_CLOCK		200
+
+#if MASTER_CLOCK == 200
+#define MASTER_PLL_MUL		162
+#define MASTER_PLL_DIV		15
+#elif MASTER_CLOCK == 239
+#define MASTER_PLL_MUL		13
+#define MASTER_PLL_DIV		1
+#endif
+
+void __bare_init at91sam926x_lowlevel_board_config(struct at91sam926x_lowlevel_cfg *cfg)
+{
+	/* Disable Watchdog */
+	cfg->wdt_mr =
+		AT91_WDT_WDIDLEHLT | AT91_WDT_WDDBGHLT |
+		AT91_WDT_WDV |
+		AT91_WDT_WDDIS |
+		AT91_WDT_WDD;
+
+	/* define PDC[31:16] as DATA[31:16] */
+	cfg->ebi_pio_pdr = 0xFFFF0000;
+	/* no pull-up for D[31:16] */
+	cfg->ebi_pio_ppudr = 0xFFFF0000;
+	/* EBI0_CSA, CS1 SDRAM, CS3 NAND Flash, 3.3V memories */
+	cfg->ebi_csa =
+		AT91_MATRIX_DBPUC | AT91_MATRIX_CS1A_SDRAMC;
+
+	cfg->smc_cs = 3;
+	cfg->smc_mode =
+		AT91_SMC_READMODE | AT91_SMC_WRITEMODE |
+		AT91_SMC_DBW_8 |
+		AT91_SMC_EXNWMODE_DISABLE |
+		AT91_SMC_TDF_(2);
+	cfg->smc_cycle =
+		AT91_SMC_NWECYCLE_(5) | AT91_SMC_NRDCYCLE_(5);
+	cfg->smc_pulse =
+		AT91_SMC_NWEPULSE_(3) | AT91_SMC_NCS_WRPULSE_(3) |
+		AT91_SMC_NRDPULSE_(3) | AT91_SMC_NCS_RDPULSE_(3);
+	cfg->smc_setup =
+		AT91_SMC_NWESETUP_(1) | AT91_SMC_NCS_WRSETUP_(0) |
+		AT91_SMC_NRDSETUP_(1) | AT91_SMC_NCS_RDSETUP_(0);
+
+	cfg->pmc_mor =
+		AT91_PMC_MOSCEN |
+		(255 << 8);		/* Main Oscillator Start-up Time */
+	cfg->pmc_pllar =
+		AT91_PMC_PLLA_WR_ERRATA | /* Bit 29 must be 1 when prog */
+		AT91_PMC_OUT |
+		((MASTER_PLL_MUL - 1) << 16) | (MASTER_PLL_DIV);
+	/* PCK/2 = MCK Master Clock from PLLA */
+	cfg->pmc_mckr1 =
+		AT91_PMC_CSS_SLOW |
+		AT91_PMC_PRES_1 |
+		AT91SAM9_PMC_MDIV_2 |
+		AT91_PMC_PDIV_1;
+	/* PCK/2 = MCK Master Clock from PLLA */
+	cfg->pmc_mckr2 =
+		AT91_PMC_CSS_PLLA |
+		AT91_PMC_PRES_1 |
+		AT91SAM9_PMC_MDIV_2 |
+		AT91_PMC_PDIV_1;
+
+	/* SDRAM */
+	/* SDRAMC_TR - Refresh Timer register */
+	cfg->sdrc_tr1 = 0x13C;
+	/* SDRAMC_CR - Configuration register*/
+	cfg->sdrc_cr =
+		AT91_SDRAMC_NC_9 |
+		AT91_SDRAMC_NR_13 |
+		AT91_SDRAMC_NB_4 |
+		AT91_SDRAMC_CAS_2 |
+		AT91_SDRAMC_DBW_32 |
+		(2 <<  8) |		/* Write Recovery Delay */
+		(7 << 12) |		/* Row Cycle Delay */
+		(2 << 16) |		/* Row Precharge Delay */
+		(2 << 20) |		/* Row to Column Delay */
+		(5 << 24) |		/* Active to Precharge Delay */
+		(8 << 28);		/* Exit Self Refresh to Active Delay */
+
+	/* Memory Device Register -> SDRAM */
+	cfg->sdrc_mdr = AT91_SDRAMC_MD_SDRAM;
+	/* SDRAM_TR */
+	cfg->sdrc_tr2 = (MASTER_CLOCK * 7);
+
+	/* user reset enable */
+	cfg->rstc_rmr =
+		AT91_RSTC_KEY |
+		AT91_RSTC_PROCRST |
+		AT91_RSTC_RSTTYP_WAKEUP |
+		AT91_RSTC_RSTTYP_WATCHDOG;
+}
diff --git a/arch/arm/boards/cpodc2/msp430.c b/arch/arm/boards/cpodc2/msp430.c
new file mode 100644
index 0000000..1c46528
--- /dev/null
+++ b/arch/arm/boards/cpodc2/msp430.c
@@ -0,0 +1,513 @@
+/*
+ * (C) Copyright 2013
+ * Darren Garnier <dgarnier at reinrag.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
+ */
+
+//#define DEBUG 1
+
+#include <common.h>
+#include <environment.h>
+#include <getopt.h>
+#include <errno.h>
+#include <crc.h>
+#include <clock.h>
+#include <console.h>
+#include <stdio.h>
+#include <string.h>
+#include <fcntl.h>
+#include <fs.h>
+#include <kfifo.h>
+#include <xfuncs.h>
+#include <command.h>
+#include <complete.h>
+
+#include "msp430.h"
+
+/* some info from protocol.h */
+#define kCmdResetSoft    "$0100*\r\n"
+#define kCmdDeviceInfo   "$07*\r\n"
+#define kCmdSerialNumber "$0E0000*\r\n"
+#define kCmdBacklightOn  "$0C00FF01*\r\n"
+#define kCmdBacklightOff "$0C00FF00*\r\n"
+
+enum DCResponses {
+    kRspStatus = 0x00,
+    kRspDevice = 0x03,
+    kRspBacklight = 0x09,
+    kRspSerialNumber = 0x0A,
+};
+
+typedef uint8_t	        _uint8;
+typedef uint16_t	    _uint16;
+typedef uint32_t        _uint32;
+typedef int8_t	        _int8;
+typedef int16_t	        _int16;
+typedef int32_t	        _int32;
+typedef float           _float32;
+
+#ifndef PACK 
+#define PACK __attribute__((packed))
+#endif
+
+struct sRspDevice {
+	_uint8         rsp;              // = kRspDevice
+	_uint8         boardType;        // enum eBoardTypeID
+	_uint8         freqUnits;        // tFreqData is  Hz << freqUnits
+	_uint8         pluggedCutoff;    // in Hz
+	_uint16        fwVersionMajor;
+	_uint16        fwVersionMinor;
+	_uint32        serialNumber;
+	_float32       ticsPerSec;       // time ticks/second
+	_uint16        intervalDataQLen; // length of DC interval data queue
+	_uint16        meterDataQLen;    // length of DC meter data queue
+	_float32       scaleA1;          // analog cals
+	_float32       scaleA2;
+	_int16         offsetA1;
+	_int16         offsetA2;
+	_uint32        statusRate;       // ticks period
+	_int16         resistorA1;       // pullup on A1 connector pin 3
+	_int16         resistorA2;       //           A2
+	_float32       vX2;              // what we're pulling up with (~5V)
+	_uint16        temperature;
+	_uint16        vccHalf;
+	_float32       scaleA1H;          // analog HiRes cals
+	_float32       scaleA2H;
+	_int16         offsetA1H;
+	_int16         offsetA2H;
+} PACK; // 60
+
+struct sRspBacklight {
+	_uint8            rsp;
+	_uint8            cmd;
+	union {
+		_uint16        value;
+		struct {
+			_uint8      current;      // value to set the current when on
+			_uint8      on;           // on or off
+		} PACK         settings;
+	} PACK            backlight;
+} PACK; // 4
+
+struct sRspSerialNumber {
+	_uint8         rsp;      // kRspSerialNumber
+	char           pad[3];
+	_uint32        sn;
+	char           fullSN[];
+} PACK;
+
+// raw data
+struct sRspRaw {
+	_uint8         rsp;              // = ?
+	_uint8         raw[63];
+} PACK; // 64
+
+#define FULLSNLENGTH 20
+#define INPUT_FIFO_SIZE 512
+#define TIMEOUT_FLUSH    100 * MSECOND
+#define TIMEOUT_RESPONSE 200 * MSECOND
+
+struct msp430_device {
+	struct console_device *	cdev;
+	struct kfifo *			fifo;
+	unsigned char 			fullSN[FULLSNLENGTH];
+	uint8_t					boardtype;
+	uint16_t				major;
+	uint16_t				minor;
+	uint8_t					bl_current;
+	uint8_t					bl_on;
+};
+
+static struct msp430_device *g_msp = NULL;
+
+static int input_fifo_fill(struct console_device *cdev, struct kfifo *fifo)
+{
+	while (cdev->tstc(cdev) && (kfifo_len(fifo) < INPUT_FIFO_SIZE))
+		kfifo_putc(fifo, (unsigned char)(cdev->getc(cdev)));
+	return kfifo_len(fifo);
+}
+
+// get line ending in \n or \r 
+static int msp_getline(struct msp430_device *msp,
+		      unsigned char *buf, int len, uint64_t timeout)
+{
+	int i;
+	unsigned char c;
+	uint64_t start = get_time_ns();
+
+	for (i = 0; i < len-1; ) {
+		if (is_timeout(start, timeout)) {
+			i = -ETIMEDOUT;
+			break;
+		}
+		if (input_fifo_fill(msp->cdev, msp->fifo)) {
+			kfifo_getc(msp->fifo, &c);
+			buf[i++] = c;
+			if (c == '\n' || c == '\r') {
+				if (--i) break;
+			}
+		}
+	}
+	buf[i]='\0';
+
+	return i;
+}
+
+static void msp_puts(struct msp430_device *msp, const unsigned char *s)
+{
+	// check for characters coming in while sending them out....
+	unsigned char c;
+	while((c = *s++)) {
+		input_fifo_fill(msp->cdev, msp->fifo);
+		msp->cdev->putc(msp->cdev, c);		
+	}
+}
+
+static void msp_flush(struct msp430_device *msp)
+{
+	uint64_t start;
+	struct console_device *cdev = msp->cdev;
+
+	start = get_time_ns();
+	while (cdev->tstc(cdev) &&
+		!is_timeout(start, TIMEOUT_FLUSH))
+			cdev->getc(cdev);
+	kfifo_reset(msp->fifo);
+}
+
+static struct console_device *get_console_from_device_name(const char *dname)
+{
+	struct console_device *cdev;
+	const char *target;
+
+	for_each_console(cdev) {
+		// lookup by device driver, not by console number
+		// so we can be sure to get the atmel serial port
+		target = dev_id(cdev->dev);
+		if (!strcmp(dname, target))
+			return cdev;
+	}
+	return NULL;
+}
+
+int __init cpodc2_msp430_init_console(const char *dname)
+{
+	struct console_device *cdev;
+	
+	cdev = get_console_from_device_name(dname);
+	if (cdev == NULL) return -1;
+	
+	// deactivate the console in case it was activated...
+	dev_set_param(&cdev->class_dev, "active", "");
+	// now that we turned it off.. we can "print" again..
+	
+	// lets set the baud rate ... (defaults already to 8-N-1)
+	cdev->setbrg(cdev,38400);
+	dev_set_param(&cdev->class_dev, "baudrate", "38400");
+	
+	g_msp = xzalloc(sizeof(struct msp430_device));
+	
+	g_msp->cdev = cdev; // keep the pointer
+	g_msp->fifo = kfifo_alloc(INPUT_FIFO_SIZE);
+	
+	// let init script do a reset...
+	// msp_reset(g_msp);
+	
+	return 0;
+}
+
+
+static int unwrap_response(char *buff, char *resp)
+{
+	char *b, *bend, *rend, *u, i;
+	int complete=0;
+
+	bend = buff + INPUT_FIFO_SIZE;
+	rend = resp + sizeof(struct sRspRaw);
+
+	u = resp; b = buff;
+	
+	/* search for beginning of packet */
+	while(*b != 0) {
+		if (*b == '$') {
+			pr_debug("> $");
+			if (++b == bend) b=buff;
+			break;
+		}
+		if (++b == bend) b=buff; /* eat all before $ */
+	}
+	
+	/* packet is begun, maybe */
+	while( *b != 0 ) {
+		if (*b >= '0' && *b <= '9') {
+			i = *b - '0';
+		} else if (*b >= 'A' && *b <= 'F') {
+			i = *b - 'A' + 10;
+		} else if (*b == '*') {
+			complete=1;
+			if (++b == bend) b = buff; /* circular buffer */
+			pr_debug("*\n");
+			break;
+		} else {
+			pr_debug("\n unexpected char %c\n ", *b);
+			if (++b == bend) b = buff; // skip it
+			break;
+		}
+		if (u == rend) {
+			pr_debug("Unwrap would overrun!\n");
+			break;
+		}
+		i=i<<4;
+		if (++b == bend) b = buff; /* circular buffer */
+		if (*b >= '0' && *b <= '9') {
+			i += *b - '0';
+		} else if (*b >= 'A' && *b <= 'F') {
+			i += *b - 'A' + 10;
+		} else if (*b == 0) {
+			/* back up */
+			if (b == buff) {
+				b = bend -1;
+			} else b--;
+			break;
+		} else {
+			pr_debug("unexpected char %c", *b);
+			if (++b == bend) b = buff; // skip it
+			break;
+		}
+		pr_debug("%02X",i);
+		*u++ = i;
+
+		if (++b == bend) b = buff; /* circular buffer */
+	}
+
+	return complete;
+}
+
+static int msp_wait_parse_response(struct msp430_device *msp)
+{
+	unsigned char line[INPUT_FIFO_SIZE];
+	int len;
+	struct sRspRaw rsp;
+	struct sRspDevice *rd = (struct sRspDevice *) &rsp;
+	struct sRspBacklight *bl = (struct sRspBacklight *) &rsp;
+
+	len = msp_getline(msp, line, INPUT_FIFO_SIZE, TIMEOUT_RESPONSE);
+	if (len == 0) {
+		pr_debug(" 0 length line.\n");
+		return -1;
+	}
+	if (len < 0)
+		return len;
+
+	pr_debug("Got a response:\n< %s\n",line);
+
+	if (unwrap_response(line, (char *) &rsp)) {
+		// got a response...
+		switch (rsp.rsp) {
+		case kRspStatus:
+			pr_debug("got MSP status packet.\n");
+			break;
+		case kRspDevice:
+			pr_debug("got device response.\n");
+			msp->major= rd->fwVersionMajor;
+			msp->minor= rd->fwVersionMinor;
+			msp->boardtype = rd->boardType;
+			break;
+		case kRspBacklight:
+			pr_debug("got backlight response.\n");
+			msp->bl_current = bl->backlight.settings.current;
+			msp->bl_on		= bl->backlight.settings.on;
+			break;
+		case kRspSerialNumber:
+			pr_debug("got serial number response.\n");
+			strlcpy(msp->fullSN, ((struct sRspSerialNumber *)&rsp)->fullSN, FULLSNLENGTH);
+			break;
+		default:
+			pr_warning("unexpected msp response (0x%02x)\n", rsp.rsp);
+		}
+	} else {
+		pr_err("Couldn't parse: %s\n", line);
+		return -1;
+	}
+
+	return rsp.rsp;
+}
+
+static int msp430_read_device(struct msp430_device *msp)
+{
+	int try, rsp;
+
+	for (try=0; try<3; try++) {
+
+		msp_puts(msp, kCmdDeviceInfo);
+
+		do {
+			rsp = msp_wait_parse_response(msp);
+			if (rsp == kRspDevice) {
+				pr_debug("got device bt = %02x, fw = %02d.%02d\n", msp->boardtype, msp->major, msp->minor);
+				return 0;
+			}
+		} while (rsp != -ETIMEDOUT);
+
+		// timed out.. perhaps needs a "flush"
+		msp_flush(msp);
+	}
+	return rsp;
+}
+
+static int msp430_read_serial(struct msp430_device *msp)
+{
+	int try, rsp;
+		
+	for (try=0; try<3; try++) {
+
+		msp_puts(msp, kCmdSerialNumber);
+
+		do {
+			rsp = msp_wait_parse_response(msp);
+			if (rsp == kRspSerialNumber) {
+				pr_debug("got the serial number %s\n",msp->fullSN);
+				return 0;
+			}
+		} while (rsp != -ETIMEDOUT);
+		msp_flush(msp);
+	}
+	return rsp;
+}
+
+static int msp430_backlight(struct msp430_device *msp, int on)
+{
+	int ret;
+	if (on) {
+		msp_puts(msp, kCmdBacklightOn);
+	} else {
+		msp_puts(msp, kCmdBacklightOff);
+	}
+	ret = msp_wait_parse_response(msp);
+	if (ret > 0) return 0;
+	return ret;
+}
+
+static int msp430_reset(struct msp430_device *msp)
+{	
+	msp_puts(msp,kCmdResetSoft);
+
+#ifdef DEBUG
+	if (kfifo_len(msp->fifo)) {
+		unsigned char c;
+		int i;
+		pr_debug("%d characters in buffer after reset: ", kfifo_len(msp->fifo));
+		i = 40;
+		while ( (kfifo_getc(msp->fifo, &c)==0) && (i--) )
+			pr_debug("%c",c);
+		pr_debug("\n");
+	}
+#endif
+	msp_flush(msp);
+	return 0;
+}
+
+static int do_msp430(int argc, char *argv[])
+{
+	int opt, ret = 0, info = 0;
+	
+	if (!g_msp) return -EINVAL;
+	
+	while ((opt = getopt(argc, argv, "irb:M:m:S:T:")) > 0)
+		switch (opt) {
+		case 'r':
+			if ((ret = msp430_reset(g_msp))) 
+				return ret;
+			break;
+		case 'b':
+			if (strcmp(optarg, "on") == 0) {
+				msp430_backlight(g_msp, 1);
+			} else 
+			if (strcmp(optarg, "off") == 0) {
+				msp430_backlight(g_msp, 0);
+			}
+			break;
+		case 'i':
+			info=1;
+			break;
+		case 'M':
+		case 'm':
+		case 'T':
+			if (!g_msp->major) {
+				if ((ret = msp430_read_device(g_msp)))
+					break;
+			}
+			if (optarg) {
+				if (opt == 'M')
+					export_env_ull(optarg, g_msp->major);
+				else if (opt == 'm')
+					export_env_ull(optarg, g_msp->minor);
+				else
+					export_env_ull(optarg, g_msp->boardtype);
+			}
+			break;
+		case 'S':
+			if (g_msp->fullSN[0] == '\0') {
+				if ((ret = msp430_read_serial(g_msp)))
+					break;
+			}
+			setenv(optarg,g_msp->fullSN);
+			break;
+		default:
+			pr_err("unexpected option 0x%02x (%c)\n", opt,opt);
+			return -EINVAL;
+		}
+
+		if (info) {
+			printf("MSP430 MCU:");
+			if (g_msp->major) {
+				printf(" Boardtype: 0x%02X,", g_msp->boardtype);
+				printf(" Firmware : %d.%02d,", g_msp->major, g_msp->minor);
+			}
+			if (g_msp->fullSN[0]) {
+				printf(" Serial # : %s", g_msp->fullSN);
+			}
+			printf("\n");
+		}
+
+	return ret;
+}
+
+BAREBOX_CMD_HELP_START(msp430)
+BAREBOX_CMD_HELP_USAGE("msp430 [OPTIONS]\n")
+BAREBOX_CMD_HELP_SHORT("Communicate with MSP430 MCU.\n")
+BAREBOX_CMD_HELP_OPT  ("-r          ", "Do a soft reset of the controller\n")
+BAREBOX_CMD_HELP_OPT  ("-b [on, off]", "Control backlight\n")
+BAREBOX_CMD_HELP_OPT  ("-M MAJOR    ", "Read Major FW version and store into $MAJOR\n")
+BAREBOX_CMD_HELP_OPT  ("-m MINOR    ", "Read Minor FW version and store into $MINOR\n")
+BAREBOX_CMD_HELP_OPT  ("-S SERIAL   ", "Read Serial Number and store into $SERIAL\n")
+BAREBOX_CMD_HELP_OPT  ("-T TYPE     ", "Read board type and store into $TYPE\n")
+BAREBOX_CMD_HELP_OPT  ("-i          ", "Print info about board.\n")
+	
+BAREBOX_CMD_HELP_END
+
+BAREBOX_CMD_START(msp430)
+	.cmd		= do_msp430,
+	.usage		= "Communicate with MSP430 MCU.",
+	BAREBOX_CMD_HELP(cmd_msp430_help)
+	BAREBOX_CMD_COMPLETE(empty_complete)
+BAREBOX_CMD_END
+
+
+
+
+
diff --git a/arch/arm/boards/cpodc2/msp430.h b/arch/arm/boards/cpodc2/msp430.h
new file mode 100644
index 0000000..3573e30
--- /dev/null
+++ b/arch/arm/boards/cpodc2/msp430.h
@@ -0,0 +1,23 @@
+/*
+ * (C) Copyright 2013
+ * Darren Garnier <dgarnier at reinrag.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
+ */
+
+
+int cpodc2_msp430_init_console(const char *dname);
+
diff --git a/arch/arm/configs/cpodc2_defconfig b/arch/arm/configs/cpodc2_defconfig
new file mode 100644
index 0000000..092ef63
--- /dev/null
+++ b/arch/arm/configs/cpodc2_defconfig
@@ -0,0 +1,96 @@
+CONFIG_ARCH_AT91SAM9261=y
+CONFIG_MACH_CPODC2_9261=y
+CONFIG_MACH_CPODC2=y
+CONFIG_AEABI=y
+# CONFIG_CMD_ARM_CPUINFO is not set
+# CONFIG_AT91SAM9_LOWLEVEL_INIT is not set
+CONFIG_MTD_NAND_ATMEL_BUSWIDTH_16=y
+CONFIG_ARM_OPTIMZED_STRING_FUNCTIONS=y
+CONFIG_ARM_BOARD_APPEND_ATAG=y
+CONFIG_CPODC2_MSP430=y
+CONFIG_MMU=y
+CONFIG_BAREBOX_MAX_IMAGE_SIZE=0x39C00
+CONFIG_PBL_IMAGE=y
+CONFIG_EXPERIMENTAL=y
+CONFIG_MALLOC_TLSF=y
+CONFIG_PROMPT="CPODC_2.0:"
+CONFIG_LONGHELP=y
+CONFIG_GLOB=y
+CONFIG_HUSH_FANCY_PROMPT=y
+CONFIG_CMDLINE_EDITING=y
+CONFIG_AUTO_COMPLETE=y
+# CONFIG_MENU is not set
+# CONFIG_CONSOLE_ACTIVATE_FIRST is not set
+CONFIG_CONSOLE_ACTIVATE_ALL=y
+CONFIG_DEFAULT_ENVIRONMENT=y
+CONFIG_DEFAULT_ENVIRONMENT_GENERIC_NEW=y
+CONFIG_DEFAULT_ENVIRONMENT_PATH="arch/arm/boards/cpodc2/env"
+CONFIG_CMD_EDIT=y
+CONFIG_CMD_SLEEP=y
+CONFIG_CMD_SAVEENV=y
+CONFIG_CMD_EXPORT=y
+CONFIG_CMD_PRINTENV=y
+CONFIG_CMD_READLINE=y
+# CONFIG_CMD_MENU is not set
+# CONFIG_CMD_PASSWD=y
+CONFIG_CMD_CLEAR=y
+CONFIG_CMD_ECHO_E=y
+CONFIG_CMD_LOADB=y
+CONFIG_CMD_MEMINFO=y
+CONFIG_CMD_MTEST=y
+CONFIG_CMD_MSLEEP=y
+CONFIG_CMD_FLASH=y
+CONFIG_CMD_BOOTM_SHOW_TYPE=y
+CONFIG_CMD_BOOTM_INITRD=y
+CONFIG_CMD_UIMAGE=y
+# CONFIG_CMD_BOOTU is not set
+CONFIG_CMD_RESET=y
+CONFIG_CMD_GO=y
+CONFIG_CMD_TIMEOUT=y
+CONFIG_CMD_PARTITION=y
+CONFIG_CMD_GPIO=y
+CONFIG_CMD_MAGICVAR=y
+# CONFIG_CMD_LED is not set
+# CONFIG_CMD_LED_TRIGGER is not set
+# CONFIG_NET is not set
+# CONFIG_NET_DHCP is not set
+# CONFIG_NET_NFS is not set
+# CONFIG_NET_PING is not set 
+# CONFIG_NET_TFTP is not set
+# CONFIG_NET_TFTP_PUSH is not set
+# CONFIG_NET_RESOLV is not set
+# CONFIG_DRIVER_NET_DM9K is not set
+CONFIG_SPI=y
+CONFIG_DRIVER_SPI_ATMEL=y
+CONFIG_CMD_SPI=y
+CONFIG_MTD=y
+CONFIG_MTD_DATAFLASH=y
+# CONFIG_MTD_OOB_DEVICE is not set
+CONFIG_NAND=y
+# CONFIG_NAND_ECC_HW is not set
+# CONFIG_NAND_ECC_HW_SYNDROME is not set
+# CONFIG_NAND_ECC_HW_NONE is not set
+CONFIG_NAND_ATMEL=y
+# CONFIG_UBI is not set
+# CONFIG_CMD_UBIFORMAT is not set
+CONFIG_USB=y
+# CONFIG_USB_OHCI is not set
+# CONFIG_USB_OHCI_AT91 is not set
+CONFIG_USB_STORAGE=y
+CONFIG_USB_HAVE_GADGET_DRIVER=y
+CONFIG_USB_GADGET=y
+CONFIG_USB_GADGET_DUALSPEED=y
+CONFIG_USB_GADGET_DRIVER_AT91=y
+CONFIG_USB_GADGET_DFU=y
+CONFIG_USB_GADGET_SERIAL=y
+# CONFIG_LED=y
+# CONFIG_LED_GPIO=y
+# CONFIG_LED_TRIGGERS=y
+# CONFIG_KEYBOARD_GPIO=y
+CONFIG_GPIO_GENERIC=y
+CONFIG_GPIO_GENERIC_PLATFORM=y
+CONFIG_VIDEO=y
+CONFIG_DRIVER_VIDEO_ATMEL=y
+CONFIG_CMD_SPLASH=y
+CONFIG_PNG=y
+CONFIG_LODEPNG=y
diff --git a/arch/arm/mach-at91/Kconfig b/arch/arm/mach-at91/Kconfig
index 5fb3ead..2701a98 100644
--- a/arch/arm/mach-at91/Kconfig
+++ b/arch/arm/mach-at91/Kconfig
@@ -271,6 +271,11 @@ config MACH_AT91SAM9261EK
	  Select this if you are using Atmel's AT91SAM9261-EK Evaluation Kit.
	  <http://www.atmel.com/dyn/products/tools_card.asp?tool_id=3820>

+config MACH_CPODC2_9261
+    bool "CPO Science DataCollector II v2.0"
+    select MACH_CPODC2
+    select HAVE_NAND_ATMEL_BUSWIDTH_16
+
config MACH_PM9261
	bool "Ronetix PM9261"
	select HAS_DM9000
@@ -297,12 +302,27 @@ config MACH_AT91SAM9G10EK
	  Select this if you are using Atmel's AT91SAM9G10-EK Evaluation Kit.
	  <http://www.atmel.com/dyn/products/tools_card.asp?tool_id=4588>

+config MACH_CPODC2_9G10
+    bool "CPO Science DataCollector II v2.1"
+    select HAVE_NAND_ATMEL_BUSWIDTH_16
+    select MACH_CPODC2
+
endchoice

endif

# ----------------------------------------------------------

+if SOC_AT91SAM9261
+
+config MACH_CPODC2
+    bool
+    depends on MACH_CPODC2_9261 || MACH_CPODC2_9G10
+
+endif
+
+# ----------------------------------------------------------
+
if ARCH_AT91SAM9G20

choice
@@ -525,6 +545,10 @@ config CALAO_MB_QIL_A9260
	bool "MB-QIL A9260 Motherboard Board support"
	depends on MACH_QIL_A9260 || MACH_QIL_A9G20

+config CPODC2_MSP430
+	bool "CPODC2 MSP430 controller support"
+	depends on MACH_CPODC2
+
if COMMAND_SUPPORT

config CMD_AT91MUX
-- 
1.8.3.1




More information about the barebox mailing list