From 287f11c7a8c56f09a394bb413856333c41717584 Mon Sep 17 00:00:00 2001 From: Matthew Allum Date: Thu, 31 Aug 2006 17:00:20 +0000 Subject: [PATCH] Add compulab modified 2.6.16 kernel git-svn-id: https://svn.o-hand.com/repos/poky/trunk@689 311d38ba-8fff-0310-9ca6-ca027cbcb966 --- .../linux/linux-cmx270-2.6.16/CL_FlashDrv | Bin 0 -> 173090 bytes .../linux-cmx270-2.6.16/diff-2.6.16-cm-x270 | 9154 +++++++++++++++++ meta/packages/linux/linux-cmx270-rp_2.6.17.bb | 2 + meta/packages/linux/linux-cmx270_2.6.16.bb | 34 + meta/packages/linux/linux-cmx270_2.6.17.bb | 2 + 5 files changed, 9192 insertions(+) create mode 100644 meta/packages/linux/linux-cmx270-2.6.16/CL_FlashDrv create mode 100644 meta/packages/linux/linux-cmx270-2.6.16/diff-2.6.16-cm-x270 create mode 100644 meta/packages/linux/linux-cmx270_2.6.16.bb diff --git a/meta/packages/linux/linux-cmx270-2.6.16/CL_FlashDrv b/meta/packages/linux/linux-cmx270-2.6.16/CL_FlashDrv new file mode 100644 index 0000000000000000000000000000000000000000..4c35c9e71d9fe84ecb80396f51997f3fb333e797 GIT binary patch literal 173090 zcmeFa3!GHfedl>@J-VCfqA6Yy0tB~tHqep^XxSLGq(Wc|Ti7W9lCechBWM|7B((u~ zr9}1=G)P#>Xwb`1WRfl?N}^~r36Y%{jaGI_24sa%93);6gOyuVx+w*FW=P^qluQ!l z`#bmE?&{`YlyP?V^V#LY>H9j5|M{Q)`#kF3e0~z^-!RvO+mtD3%)m}2$JzgOFzt)@(|+-A)9e?EKm$I9z;eWEhVJ?S@P zPx`6MNx#{g^kW^pWoJQe*>sXJTa&%powuAlH2EN zJQ`?A<0Kph<7J7-I1M4q{CPdi9QHG%!}fo?3#yuKS;g*20R zxE$Y8EH|y*UEb3=!;9yN7Z2x6+^x2S(Rt=&f#s@n3Y;}@zE*&+}))~gl z(vcm%fR18A=qP*m)0L4~=*TW9DD_Y98{dDl9DDH5avWOC^SqKgP0(r_x?RO{3RxFR7s|<%z0@_qALACQN$5EK z#_lrwRb5bO_LrGv|4Aq1EurqEwA0=-!S8ZHxkvw(P)@w}C2%zi+=$nf@=p02>T|M- zD@!Q1l=8#ecaVkez~k>A3*Y&fvM{3OMrczqETZS=`D`Xt(YWjRQ$y%k?-tQkBm+M+ zuIL~WW7HF;jKg>6`5k28JIKO!{Fy`G86*o$zPiLTC(%L3zYF(4@JU`pwAe}B>uJLj zke?lom;Wz#K>QAk$4$OiRU1zBwSQfS3(5_Z$@9rGkA6xHE`tu@$Y3Ya?TLp}cMNIDau0cqSz_CqPhFj~f4zAJn%Gr|wH3>0=>Y0Y?)RDaLl3p{s3nwc|ub<7t`gvP2P45Z)YIKgP^SC;PU47XJMP_^@(>a*_!- zN&Wz0t1 ziqc7c9Cqb+Y&ZD=6U_O20ohd%oS8bAAvjwp=TgTM`Z$&H{rUjCST9?C7A}OdsEt8> z(2zP`2M#!QD|=WK1Q8u4ep3J6*-NbRM#)>||$D{$a$e(ow&K z-}0jMTb35fzXq+zcgdK(WF|v$`;yev9F22eWg3%+^wPf~oxL5>*~$L}I*Vldh3HK3 zQ8?E3pC_HkUl`AL%3qk^4e=Lx9=861Y@YwG)7!O)OQW}jh~C0jOF?!}9=`@(W}%CZ zj6XBV3w)ZVW^bu9B7=-utcq7;&l-5_ z0pJ-E>+{EqB25W=cKLN@i0k}n_6{rmzm|~wjQ`HNVeWB!iR1VZ$B}!-2g!u<*&JOV zy~)qLp0b^kmAsQId7{zr6fY4y>bt%vPyP2rb+(7{EFw=N_x=xHKW`cMy}sVVb#hI0 zw9Cyy^^|Z!7;aVP1}CAd-Jc=rPTM;(XbVCM8?tQ_GK@vWoh0R=1Ut znE-CnR4ltBQ<8tSx_nvEJfF<&uEgD=wRDE$9;hWtyFGo2XAaa_lIGyqcj7#Ah~^odGXJOk3Y1PTcXE$xDkJ zMKPoQyW@_Gk=5PLbNyLy$7vxUJCR%+6nFgDvFa#Jt(f)DSoPl48D8V+LU~Lfuo;~_ z#p-_!>F7@*In0qKO7w)caUAgW1T4tCe=?Lxs${;2FDZ=VO+XCj{V_c(yPK);^zj%AHX}bv8wv9 z1~YyYG3iyrq*sM8>1#^?4D+)miQk>{Ev&>vq(A>TVSd~M?DEBbRzB$p<%?*mKNk5; z7}G``UY|YccbY&?$MWE$V^6tt7jm)(e(x$)*MXm8miZ4CT}``9nPT}5lIF)w_Mr-~ z(DK=?c%>lO+*2G)Ui95jbmUR1cjM;v@`?ttQ1GAmy+CfBiQ1;E>$ArO+6I=PZ9hia zYR|R}42o^3ZMExUXrDI8V|nZm@;bCFe~|m}w(iU^zmVHe5!`_fd)FXeowBDpf#G`h zn18m*sVJ}XzTnUk2pDo^nu7rOzH~I0#fVOUK4Ed0`F3FW^O(0{ed?^I{VURD@ zrbEVDjQ(V&*W01GucyCA<~v;vRh-PWN@VLw-`C53J^!!L;>G+r$!z&_>XUdwc0>j~ ziC|azKaUuK@F5u&wQ(_B^g6hT@?EU$dOLd{ez0pGet_&lM%Tp;W}X{AK#u>OrNz&l z6F;yr8Cr;F@n7uEVOQI^TXS3B&pp^%J_F6kpOc+!+`<0be+8bOIDP(4Mv_|3@6Y{p z+|uw-lw}@9(;<3u9c_Whtu=Le5i>2M2~~~)zF8N z|0bO!A1;xpr>jfz;V#y8JzZH|ulL^!G)1i3K@U1v7kXMb$bY-BNpdY;UB}h>YWR}i z)%t3V_0{razC9n54}7;ZP3C3!}npxlh+xsK;xDS1*oNB!h(aNV)H+)O*m$eWt>b-PZb5xA4UD;kYudzrYr-Rh1QV^L~izG%$X z%Z=l<*>}l_+wAyYPnMZqDkp~p@XgHxV=|9^2^S9dSKDm`#*25Vdp7S4<2=U$f7pGo zj$J`tX-8wb7FJIqxpEv z@n1u}7&u?Tw`JtlIGAa>%L}+_?os1uX@h6YE!cR@8{oT+Hqt%Ck$2JeEcMQ%oq3sK z(6;KOPbv>C(v1CW(9kgQH1Rz}zGm{s9*!|ShOu$XZaa77b`lRE?&2cbuE`#R-VXX# zXAb)9=AfMm#Rsn%*Q?Iwy}q|A59w-BmUnYW^GFfi+o2)RpXj&%3=VNt&Es{@rv>z> zlke${?d2TrmhjF1bJLz<(BLuOf$maW$9&PD@-*j;4WhpW=r1vd{yuAUu;{OA81&ci z^>PFCC6@Kt_X*yM7V2?jO2zU}e8q|N2(Rg4apd>Ft>&AY?2?$1T{dcJd$Bx~c;8fF zM#90|4E;6qo&KxO?clE+{I!F>`Mk6EAWyb5fD_r}k{!~&f@hX{%x`0CW-~T|XO0;> zeu>s6YE3=pg4W(zJ?!Vgy|Vo4;JAsphEZpV`kG4vb)}IF4bZq#c(@`yYNCC?^4s7l zqVXthmLQIsBxc*-9rhbbhy6syPOIb7oln>pOqF(w`(`bAueo*6r}&Y@0x9V?#mQLA zP=1^G6_XqqH0!A&`k>3 zYKCr_x(@no&q2SHG=(&k6c6i?uA7xT=(jK@7X-N&}bVpG>1B7Lkn}D1qU4( zM|U=?WjzOaQ{!&sVlG%Oa!u}_KcBkWxn4!Onv~^vE@>Vq(trJ9lm&MDZ1w9GQ_#W& zD`!vl;~~_OP12L}a~O2kgsx0^&}8nIp9Y>5;7I_BVhoDWcI0+ew6>DDF1sd5^8{MI zWC~t2Q7o4KUCKN!yeS6o#xV2avnEsRrR@YVJ&8P*%xgr>@NRqq@7j?mF`f^SXAn=A z0iKY2l$_u8nH|v7?Z}uNmHSfWWwl}Pqd5p-M5$cS`AzEaQs(qU>)P{m>iJw*^^y0G z>Kg=eCR6za@Hx5v?o?qvlIQR$IK3_BxFCD0z;XZDN zlY_G-n}`cR6Ot$5c`FmM6a2Hq#>&hc0Za|pWX3(5Vt73#{dm_&Uvb(d=s(GNyGGXEB;W%FxJCO7@Ix9{&+ds=MEh6o3h1!j7Z*R( z&*%SIGUnMe!#&8XF4j*V+fB}^c6Mp)U$g&<&E|QHm3+vEZ*FZC-yDZ;f;pom_=I=x z&GCM|d5S!P;+$s4{5raP+dU82_L`y1#m(mB$WIl`VizYnyCx(zQ_mkaYfa3#>z!o_ zM0QFjPs>?gR=t!tqy;sH^n~> zG@EBimVZ{3UnP%YwpM8`wIjR3OTj;FL;0t$-zVQ`t+`6N$n?xNp`(YqM)aL{MQQ7z zK7Z@0q%!GN=n+{i8SSGp{kPbe!kowM6DPd~>`O@!_z!4|(Fn z*mb>?rfhFz3UEwmB0=j;u2@aL%Sp4}Zz%2e9V}3&yGSKqmF~6~Z4D2~(c`^l0Ho%ijAx}2Szsxaq;5OEUT3w6l>uC(G3+chiK4L5NaEN9V3yY;#<3YXgB79zmRXXy8N@vqzA4}n`a#J6}=1QziHDTBNYdaW#lgfK4&E3 z8#6mm13^E8Q>}NmJ`rV7H(ryB|nREl4D*ekl z04UtB!N;XO!e#iYUWv45^@EM1#p8e-BUpJi$d1`V9@!NRb;_>ztq5PhAv(*1@supFHDC%dpqB+fXN-L`<{B(XHksD z>0f3@oTR;U*uM(gSeQIu${)tIJnUc7br^f|u-}9(RLn&&odmqsz}^VqPWE6D9GGIj zd#z8)RxVb@4>#jyxrgzW4&yH!CblxrH^Gy{H;zy3^|rUJ^I~(?dGTz)>&W$58!V#R zb;AeSjKgS$cNW*lSD`K1*_VB-+=kqlh5VVFIqAF^iy{56zu48`coRv<-*&yz27Lm=)G1>z|&b^oC~a4 zCpCXaKG8FMfo9OSZeG5a%n%G;BhODwpa0Vgwq1J^Uk-RO`CHHqes1sFZhS{l z&knBxpI7{+xkO6`U75S^|4f$U0Z=p5O5_A#4^^EobN!CO@Y0vrO9{m_3_tL7fr+Q_J zNws0~&dOuwV(VU&IZnTh)34+7>p1^AOqGp@uh77#}oR~(rnz7!|Vv=%$Q=fp9H302d`nBgi< zSu1~`l^a?_C&+kcgnJuvk^ddlH=p{XPa~f^!c*%eY%k(etp`Z&bH9YNig;AEMExZ{ z=9T<-SIJN2O874&-(*UD!Y%pd^lg3t9_#YrPM6m@yigfIAELIh;h40R4zrH!us_8M zbkS79J|}2Kv}b+&^b_UQ)dR33pq0%n=2MQh`iO3+ww4Z1#{qw8o_K!dfIlt! zeLqWIrz*ZrY9&n}>0P}pRNI00>F}Lc*nO|)g zbvZOezGv8@THQUN=zNRhxW^h_=wQDC`yew@ryw=Z)$YN@2v29iaq7Tlk$#oDHre0s z1#@GUVw5Y&OdgDHq)*1BpUBVEb0w?LHSjY&+o(p`JKkbWN)|h;opanNq*z7topxWX zO?@3Z7aBh*`erOm_EE(-(N)LZE8$nDOxm46jPBi<GHkCgY%fWB z4Yb$9`$pQ64PD>fFxq>YJ{an4q>Y>F>J*Pv-nr^C8a)ZI+o!+D>k?%_k~ zZlUf!rY|miap^}4-c)_oevuETHoqLqF(@8b-SL+)?`1+nr!4#^_3Ck^xk=lUEvAFWmWaNz-GF7`G(Jm&X1wv ziMoT_Kx)054;KZA=K~Wg(nnfO9NxUe5c=fb;SpaE>d0 zuUKC)J*qDW?Zqc#OzOr7*87$c|U)i@ZB3!APNy%~ zIkGRA4Es~x563+Le!(kt+EDyn1%BIQm#oAus>ACv+MXK1F+GH1DsW5#jv2h44jeOv zz%dgzzQY>r?_~Ot@Q%gnrNR-7v&J}n>)JOo1$qm(W1R1QWVy4GkJV_ume4zwYvx$3UPitNe>%f<;+qvJn?iY< zz=w6N2;|x7`Sg|f=46UEk$bR~=XoW0w@n6DJTKu{*Ian*)V1qiZ9#bL2(Q`j+8$op z!t1o~>W0^e;dNYi9TQ$N;Z?Y~5}um~&rO2oCWkWZr|e6KVrDV=KJ|@(dE!%&i^#-y z=3wn8_l!mDu&$+pwJhWMI%Q{LkH-oJYbEYg{>G8a)i73uI9fDUQ!hKO!jEi+zxPm& z_C_j}s`?*Pz3xG1m$Es^Qb%0lj(^_8x5!85U2P@LitDr+bS2{ygT@v6iRkG@`0)mK z@Pcqm>@DAbe7_O-9$)f!xe1xugzRmCC!e8Tdx)=J#rJkA`;XNgi%pgQ`s@njNjAR=kHQI=2&eP_ZDvYQs6$?i%y?w znh&;dTlCBbkM_=hU-P-D=7B`h?d~lV?St+cX%0D;EA9~NHFB80`zElr^G)`k+Ejk; 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 + dmac_clean_range(ptr, ptr + size); + } ++ local_irq_restore(flags); + free_safe_buffer(device_info, buf); + } ++ else ++ local_irq_restore(flags); + } + + static inline void +@@ -424,18 +430,12 @@ void + dma_unmap_single(struct device *dev, dma_addr_t dma_addr, size_t size, + enum dma_data_direction dir) + { +- unsigned long flags; +- + dev_dbg(dev, "%s(ptr=%p,size=%d,dir=%x)\n", + __func__, (void *) dma_addr, size, dir); + + BUG_ON(dir == DMA_NONE); + +- local_irq_save(flags); +- + unmap_single(dev, dma_addr, size, dir); +- +- local_irq_restore(flags); + } + + int +@@ -471,7 +471,6 @@ void + dma_unmap_sg(struct device *dev, struct scatterlist *sg, int nents, + enum dma_data_direction dir) + { +- unsigned long flags; + int i; + + dev_dbg(dev, "%s(sg=%p,nents=%d,dir=%x)\n", +@@ -479,16 +478,12 @@ dma_unmap_sg(struct device *dev, struct + + BUG_ON(dir == DMA_NONE); + +- local_irq_save(flags); +- + for (i = 0; i < nents; i++, sg++) { + dma_addr_t dma_addr = sg->dma_address; + unsigned int length = sg->length; + + unmap_single(dev, dma_addr, length, dir); + } +- +- local_irq_restore(flags); + } + + void +@@ -632,7 +627,7 @@ #endif + list_add(&device_info->node, &dmabounce_devs); + + printk(KERN_INFO "dmabounce: registered device %s on %s bus\n", +- dev->bus_id, dev->bus->name); ++ dev->bus_id, dev->bus ? dev->bus->name : "no"); + + return 0; + +@@ -677,7 +672,7 @@ #endif + kfree(device_info); + + printk(KERN_INFO "dmabounce: device %s on %s bus unregistered\n", +- dev->bus_id, dev->bus->name); ++ dev->bus_id, dev->bus ? dev->bus->name : "no"); + } + + +diff --git a/arch/arm/configs/cm_x270_defconfig b/arch/arm/configs/cm_x270_defconfig +new file mode 100644 +index 0000000..7f6d1f7 +--- /dev/null ++++ b/arch/arm/configs/cm_x270_defconfig +@@ -0,0 +1,1311 @@ ++# ++# Automatically generated make config: don't edit ++# Linux kernel version: 2.6.16 ++# Wed Jun 14 17:50:29 2006 ++# ++CONFIG_ARM=y ++CONFIG_MMU=y ++CONFIG_RWSEM_GENERIC_SPINLOCK=y ++CONFIG_GENERIC_CALIBRATE_DELAY=y ++CONFIG_ARCH_MTD_XIP=y ++ ++# ++# Code maturity level options ++# ++CONFIG_EXPERIMENTAL=y ++CONFIG_BROKEN_ON_SMP=y ++CONFIG_INIT_ENV_ARG_LIMIT=32 ++ ++# ++# General setup ++# ++CONFIG_LOCALVERSION="-cm-x270" ++# CONFIG_LOCALVERSION_AUTO is not set ++CONFIG_SWAP=y ++CONFIG_SYSVIPC=y ++# CONFIG_POSIX_MQUEUE is not set ++# CONFIG_BSD_PROCESS_ACCT is not set ++CONFIG_SYSCTL=y ++# CONFIG_AUDIT is not set ++CONFIG_IKCONFIG=y ++CONFIG_IKCONFIG_PROC=y ++CONFIG_INITRAMFS_SOURCE="" ++CONFIG_UID16=y ++CONFIG_CC_OPTIMIZE_FOR_SIZE=y ++CONFIG_EMBEDDED=y ++CONFIG_KALLSYMS=y ++# CONFIG_KALLSYMS_ALL is not set ++# 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_SHMEM=y ++CONFIG_CC_ALIGN_FUNCTIONS=0 ++CONFIG_CC_ALIGN_LABELS=0 ++CONFIG_CC_ALIGN_LOOPS=0 ++CONFIG_CC_ALIGN_JUMPS=0 ++CONFIG_SLAB=y ++# CONFIG_TINY_SHMEM is not set ++CONFIG_BASE_SMALL=0 ++# CONFIG_SLOB is not set ++ ++# ++# Loadable module support ++# ++CONFIG_MODULES=y ++CONFIG_MODULE_UNLOAD=y ++CONFIG_MODULE_FORCE_UNLOAD=y ++CONFIG_OBSOLETE_MODPARM=y ++# CONFIG_MODVERSIONS is not set ++# CONFIG_MODULE_SRCVERSION_ALL is not set ++CONFIG_KMOD=y ++ ++# ++# Block layer ++# ++ ++# ++# IO Schedulers ++# ++CONFIG_IOSCHED_NOOP=y ++CONFIG_IOSCHED_AS=y ++CONFIG_IOSCHED_DEADLINE=y ++CONFIG_IOSCHED_CFQ=y ++CONFIG_DEFAULT_AS=y ++# CONFIG_DEFAULT_DEADLINE is not set ++# CONFIG_DEFAULT_CFQ is not set ++# CONFIG_DEFAULT_NOOP is not set ++CONFIG_DEFAULT_IOSCHED="anticipatory" ++ ++# ++# System Type ++# ++# CONFIG_ARCH_CLPS7500 is not set ++# CONFIG_ARCH_CLPS711X is not set ++# CONFIG_ARCH_CO285 is not set ++# CONFIG_ARCH_EBSA110 is not set ++# CONFIG_ARCH_FOOTBRIDGE is not set ++# CONFIG_ARCH_INTEGRATOR is not set ++# CONFIG_ARCH_IOP3XX is not set ++# CONFIG_ARCH_IXP4XX is not set ++# CONFIG_ARCH_IXP2000 is not set ++# CONFIG_ARCH_L7200 is not set ++CONFIG_ARCH_PXA=y ++# CONFIG_ARCH_RPC is not set ++# CONFIG_ARCH_SA1100 is not set ++# CONFIG_ARCH_S3C2410 is not set ++# CONFIG_ARCH_SHARK is not set ++# CONFIG_ARCH_LH7A40X is not set ++# CONFIG_ARCH_OMAP is not set ++# CONFIG_ARCH_VERSATILE is not set ++# CONFIG_ARCH_REALVIEW is not set ++# CONFIG_ARCH_IMX is not set ++# CONFIG_ARCH_H720X is not set ++# CONFIG_ARCH_AAEC2000 is not set ++# CONFIG_ARCH_AT91RM9200 is not set ++ ++# ++# Intel PXA2xx Implementations ++# ++# CONFIG_ARCH_LUBBOCK is not set ++# CONFIG_MACH_MAINSTONE is not set ++CONFIG_MACH_ARMCORE=y ++# CONFIG_ARCH_PXA_IDP is not set ++# CONFIG_PXA_SHARPSL is not set ++CONFIG_ARMCORE_ATXBASE=y ++# CONFIG_ARMCORE_SB270 is not set ++CONFIG_ARMCORE_REV12=y ++# CONFIG_ARMCORE_REV11 is not set ++CONFIG_PXA27x=y ++CONFIG_IWMMXT=y ++ ++# ++# Processor Type ++# ++CONFIG_CPU_32=y ++CONFIG_CPU_XSCALE=y ++CONFIG_CPU_32v5=y ++CONFIG_CPU_ABRT_EV5T=y ++CONFIG_CPU_CACHE_VIVT=y ++CONFIG_CPU_TLB_V4WBI=y ++ ++# ++# Processor Features ++# ++CONFIG_ARM_THUMB=y ++CONFIG_XSCALE_PMU=y ++CONFIG_DMABOUNCE=y ++ ++# ++# Bus support ++# ++CONFIG_PCI=y ++CONFIG_PCI_HOST_ITE8152=y ++# CONFIG_PCI_LEGACY_PROC is not set ++# CONFIG_PCI_DEBUG is not set ++ ++# ++# PCCARD (PCMCIA/CardBus) support ++# ++CONFIG_PCCARD=y ++# CONFIG_PCMCIA_DEBUG is not set ++CONFIG_PCMCIA=y ++# CONFIG_PCMCIA_LOAD_CIS is not set ++CONFIG_PCMCIA_IOCTL=y ++CONFIG_CARDBUS=y ++ ++# ++# PC-card bridges ++# ++CONFIG_YENTA=m ++CONFIG_YENTA_O2=y ++CONFIG_YENTA_RICOH=y ++CONFIG_YENTA_TI=y ++CONFIG_YENTA_ENE_TUNE=y ++CONFIG_YENTA_TOSHIBA=y ++# CONFIG_PD6729 is not set ++# CONFIG_I82092 is not set ++CONFIG_PCMCIA_PXA2XX=m ++CONFIG_PCCARD_NONSTATIC=m ++ ++# ++# Kernel Features ++# ++# CONFIG_PREEMPT is not set ++# CONFIG_NO_IDLE_HZ is not set ++# CONFIG_AEABI is not set ++# CONFIG_ARCH_DISCONTIGMEM_ENABLE is not set ++CONFIG_SELECT_MEMORY_MODEL=y ++CONFIG_FLATMEM_MANUAL=y ++# CONFIG_DISCONTIGMEM_MANUAL is not set ++# CONFIG_SPARSEMEM_MANUAL is not set ++CONFIG_FLATMEM=y ++CONFIG_FLAT_NODE_MEM_MAP=y ++# CONFIG_SPARSEMEM_STATIC is not set ++CONFIG_SPLIT_PTLOCK_CPUS=4096 ++CONFIG_LEDS=y ++CONFIG_LEDS_TIMER=y ++CONFIG_LEDS_CPU=y ++CONFIG_ALIGNMENT_TRAP=y ++ ++# ++# Boot options ++# ++CONFIG_ZBOOT_ROM_TEXT=0x0 ++CONFIG_ZBOOT_ROM_BSS=0x0 ++CONFIG_CMDLINE="" ++# CONFIG_XIP_KERNEL is not set ++ ++# ++# Floating point emulation ++# ++ ++# ++# At least one emulation must be selected ++# ++CONFIG_FPE_NWFPE=y ++# CONFIG_FPE_NWFPE_XP is not set ++# CONFIG_FPE_FASTFPE is not set ++ ++# ++# Userspace binary formats ++# ++CONFIG_BINFMT_ELF=y ++# CONFIG_BINFMT_AOUT is not set ++# CONFIG_BINFMT_MISC is not set ++# CONFIG_ARTHUR is not set ++ ++# ++# Power management options ++# ++CONFIG_PM=y ++CONFIG_PM_LEGACY=y ++# CONFIG_PM_DEBUG is not set ++# CONFIG_APM is not set ++ ++# ++# Networking ++# ++CONFIG_NET=y ++ ++# ++# Networking options ++# ++# CONFIG_NETDEBUG is not set ++CONFIG_PACKET=y ++# CONFIG_PACKET_MMAP is not set ++CONFIG_UNIX=y ++# CONFIG_NET_KEY is not set ++CONFIG_INET=y ++# CONFIG_IP_MULTICAST is not set ++# CONFIG_IP_ADVANCED_ROUTER is not set ++CONFIG_IP_FIB_HASH=y ++CONFIG_IP_PNP=y ++CONFIG_IP_PNP_DHCP=y ++CONFIG_IP_PNP_BOOTP=y ++# CONFIG_IP_PNP_RARP is not set ++# CONFIG_NET_IPIP is not set ++# CONFIG_NET_IPGRE is not set ++# CONFIG_ARPD is not set ++# CONFIG_SYN_COOKIES is not set ++# CONFIG_INET_AH is not set ++# CONFIG_INET_ESP is not set ++# CONFIG_INET_IPCOMP is not set ++# CONFIG_INET_TUNNEL is not set ++CONFIG_INET_DIAG=y ++CONFIG_INET_TCP_DIAG=y ++# CONFIG_TCP_CONG_ADVANCED is not set ++CONFIG_TCP_CONG_BIC=y ++# CONFIG_IPV6 is not set ++# CONFIG_NETFILTER is not set ++ ++# ++# DCCP Configuration (EXPERIMENTAL) ++# ++# CONFIG_IP_DCCP is not set ++ ++# ++# SCTP Configuration (EXPERIMENTAL) ++# ++# CONFIG_IP_SCTP is not set ++ ++# ++# TIPC Configuration (EXPERIMENTAL) ++# ++# CONFIG_TIPC is not set ++# CONFIG_ATM is not set ++# CONFIG_BRIDGE 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_NET_DIVERT is not set ++# CONFIG_ECONET is not set ++# CONFIG_WAN_ROUTER is not set ++ ++# ++# QoS and/or fair queueing ++# ++# CONFIG_NET_SCHED is not set ++ ++# ++# Network testing ++# ++# CONFIG_NET_PKTGEN is not set ++# CONFIG_HAMRADIO is not set ++# CONFIG_IRDA is not set ++# CONFIG_BT is not set ++CONFIG_IEEE80211=m ++# CONFIG_IEEE80211_DEBUG is not set ++CONFIG_IEEE80211_CRYPT_WEP=m ++CONFIG_IEEE80211_CRYPT_CCMP=m ++# CONFIG_IEEE80211_CRYPT_TKIP is not set ++ ++# ++# Device Drivers ++# ++ ++# ++# Generic Driver Options ++# ++CONFIG_STANDALONE=y ++CONFIG_PREVENT_FIRMWARE_BUILD=y ++CONFIG_FW_LOADER=y ++# CONFIG_DEBUG_DRIVER is not set ++ ++# ++# Connector - unified userspace <-> kernelspace linker ++# ++# CONFIG_CONNECTOR is not set ++ ++# ++# Memory Technology Devices (MTD) ++# ++# CONFIG_MTD is not set ++ ++# ++# Parallel port support ++# ++# CONFIG_PARPORT is not set ++ ++# ++# Plug and Play support ++# ++ ++# ++# Block devices ++# ++# CONFIG_BLK_CPQ_DA is not set ++# CONFIG_BLK_CPQ_CISS_DA is not set ++# CONFIG_BLK_DEV_DAC960 is not set ++# CONFIG_BLK_DEV_UMEM is not set ++# CONFIG_BLK_DEV_COW_COMMON is not set ++CONFIG_BLK_DEV_LOOP=y ++# CONFIG_BLK_DEV_CRYPTOLOOP is not set ++# CONFIG_BLK_DEV_NBD is not set ++# CONFIG_BLK_DEV_SX8 is not set ++# CONFIG_BLK_DEV_UB is not set ++CONFIG_BLK_DEV_RAM=y ++CONFIG_BLK_DEV_RAM_COUNT=16 ++CONFIG_BLK_DEV_RAM_SIZE=12000 ++CONFIG_BLK_DEV_INITRD=y ++# CONFIG_CDROM_PKTCDVD is not set ++# CONFIG_ATA_OVER_ETH is not set ++CONFIG_ARMCORE_FLASH=y ++# CONFIG_ARMCORE_NOR is not set ++CONFIG_ARMCORE_NAND=y ++ ++# ++# ATA/ATAPI/MFM/RLL support ++# ++CONFIG_IDE=y ++CONFIG_BLK_DEV_IDE=y ++ ++# ++# Please see Documentation/ide.txt for help/info on IDE drives ++# ++# CONFIG_BLK_DEV_IDE_SATA is not set ++CONFIG_BLK_DEV_IDEDISK=y ++# CONFIG_IDEDISK_MULTI_MODE is not set ++CONFIG_BLK_DEV_IDECS=y ++CONFIG_BLK_DEV_IDECD=y ++# CONFIG_BLK_DEV_IDETAPE is not set ++# CONFIG_BLK_DEV_IDEFLOPPY is not set ++CONFIG_BLK_DEV_IDESCSI=y ++# CONFIG_IDE_TASK_IOCTL is not set ++ ++# ++# IDE chipset support/bugfixes ++# ++CONFIG_IDE_GENERIC=y ++# CONFIG_BLK_DEV_IDEPCI is not set ++# CONFIG_IDE_ARM is not set ++CONFIG_BLK_DEV_IDE_CM_X270=m ++# CONFIG_BLK_DEV_IDEDMA is not set ++# CONFIG_IDEDMA_AUTO is not set ++# CONFIG_BLK_DEV_HD is not set ++ ++# ++# SCSI device support ++# ++# CONFIG_RAID_ATTRS is not set ++CONFIG_SCSI=y ++# CONFIG_SCSI_PROC_FS is not set ++ ++# ++# SCSI support type (disk, tape, CD-ROM) ++# ++CONFIG_BLK_DEV_SD=y ++# CONFIG_CHR_DEV_ST is not set ++# CONFIG_CHR_DEV_OSST is not set ++# CONFIG_BLK_DEV_SR is not set ++# CONFIG_CHR_DEV_SG is not set ++# CONFIG_CHR_DEV_SCH is not set ++ ++# ++# Some SCSI devices (e.g. CD jukebox) support multiple LUNs ++# ++# CONFIG_SCSI_MULTI_LUN is not set ++# CONFIG_SCSI_CONSTANTS is not set ++# CONFIG_SCSI_LOGGING is not set ++ ++# ++# SCSI Transport Attributes ++# ++# 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 ++ ++# ++# SCSI low-level drivers ++# ++# CONFIG_ISCSI_TCP is not set ++# CONFIG_BLK_DEV_3W_XXXX_RAID is not set ++# CONFIG_SCSI_3W_9XXX is not set ++# CONFIG_SCSI_ACARD is not set ++# CONFIG_SCSI_AACRAID is not set ++# CONFIG_SCSI_AIC7XXX is not set ++# CONFIG_SCSI_AIC7XXX_OLD is not set ++# CONFIG_SCSI_AIC79XX is not set ++# CONFIG_SCSI_DPT_I2O is not set ++# CONFIG_MEGARAID_NEWGEN is not set ++# CONFIG_MEGARAID_LEGACY is not set ++# CONFIG_MEGARAID_SAS is not set ++# CONFIG_SCSI_SATA is not set ++# CONFIG_SCSI_DMX3191D is not set ++# CONFIG_SCSI_FUTURE_DOMAIN is not set ++# CONFIG_SCSI_IPS is not set ++# CONFIG_SCSI_INITIO is not set ++# CONFIG_SCSI_INIA100 is not set ++# CONFIG_SCSI_SYM53C8XX_2 is not set ++# CONFIG_SCSI_IPR is not set ++# CONFIG_SCSI_QLOGIC_FC is not set ++# CONFIG_SCSI_QLOGIC_1280 is not set ++# CONFIG_SCSI_QLA_FC is not set ++# CONFIG_SCSI_LPFC is not set ++# CONFIG_SCSI_DC395x is not set ++# CONFIG_SCSI_DC390T is not set ++# CONFIG_SCSI_NSP32 is not set ++# CONFIG_SCSI_DEBUG is not set ++ ++# ++# PCMCIA SCSI adapter support ++# ++# CONFIG_PCMCIA_AHA152X is not set ++# CONFIG_PCMCIA_FDOMAIN is not set ++# CONFIG_PCMCIA_NINJA_SCSI is not set ++# CONFIG_PCMCIA_QLOGIC is not set ++# CONFIG_PCMCIA_SYM53C500 is not set ++ ++# ++# Multi-device support (RAID and LVM) ++# ++# CONFIG_MD is not set ++ ++# ++# Fusion MPT device support ++# ++# CONFIG_FUSION is not set ++# CONFIG_FUSION_SPI is not set ++# CONFIG_FUSION_FC is not set ++# CONFIG_FUSION_SAS is not set ++ ++# ++# IEEE 1394 (FireWire) support ++# ++# CONFIG_IEEE1394 is not set ++ ++# ++# I2O device support ++# ++# CONFIG_I2O is not set ++ ++# ++# Network device support ++# ++CONFIG_NETDEVICES=y ++# CONFIG_DUMMY is not set ++# CONFIG_BONDING is not set ++# CONFIG_EQUALIZER is not set ++# CONFIG_TUN is not set ++ ++# ++# ARCnet devices ++# ++# CONFIG_ARCNET is not set ++ ++# ++# PHY device support ++# ++# CONFIG_PHYLIB is not set ++ ++# ++# Ethernet (10 or 100Mbit) ++# ++CONFIG_NET_ETHERNET=y ++CONFIG_MII=y ++# CONFIG_HAPPYMEAL is not set ++# CONFIG_SUNGEM is not set ++# CONFIG_CASSINI is not set ++# CONFIG_NET_VENDOR_3COM is not set ++# CONFIG_SMC91X is not set ++CONFIG_DM9000=y ++CONFIG_DM9000_NOEPROM=y ++ ++# ++# Tulip family network device support ++# ++# CONFIG_NET_TULIP is not set ++# CONFIG_HP100 is not set ++CONFIG_NET_PCI=y ++# CONFIG_PCNET32 is not set ++# CONFIG_AMD8111_ETH is not set ++# CONFIG_ADAPTEC_STARFIRE is not set ++# CONFIG_B44 is not set ++# CONFIG_FORCEDETH is not set ++# CONFIG_DGRS is not set ++# CONFIG_EEPRO100 is not set ++# CONFIG_E100 is not set ++# CONFIG_FEALNX is not set ++# CONFIG_NATSEMI is not set ++# CONFIG_NE2K_PCI is not set ++# CONFIG_8139CP is not set ++CONFIG_8139TOO=m ++# CONFIG_8139TOO_PIO is not set ++# CONFIG_8139TOO_TUNE_TWISTER is not set ++# CONFIG_8139TOO_8129 is not set ++# CONFIG_8139_OLD_RX_RESET is not set ++# CONFIG_SIS900 is not set ++# CONFIG_EPIC100 is not set ++# CONFIG_SUNDANCE is not set ++# CONFIG_TLAN is not set ++# CONFIG_VIA_RHINE is not set ++ ++# ++# Ethernet (1000 Mbit) ++# ++# CONFIG_ACENIC is not set ++# CONFIG_DL2K is not set ++# CONFIG_E1000 is not set ++# CONFIG_NS83820 is not set ++# CONFIG_HAMACHI is not set ++# CONFIG_YELLOWFIN is not set ++# CONFIG_R8169 is not set ++# CONFIG_SIS190 is not set ++# CONFIG_SKGE is not set ++# CONFIG_SKY2 is not set ++# CONFIG_SK98LIN is not set ++# CONFIG_VIA_VELOCITY is not set ++# CONFIG_TIGON3 is not set ++# CONFIG_BNX2 is not set ++ ++# ++# Ethernet (10000 Mbit) ++# ++# CONFIG_CHELSIO_T1 is not set ++# CONFIG_IXGB is not set ++# CONFIG_S2IO is not set ++ ++# ++# Token Ring devices ++# ++# CONFIG_TR is not set ++ ++# ++# Wireless LAN (non-hamradio) ++# ++CONFIG_NET_RADIO=y ++ ++# ++# Obsolete Wireless cards support (pre-802.11) ++# ++# CONFIG_STRIP is not set ++# CONFIG_PCMCIA_WAVELAN is not set ++# CONFIG_PCMCIA_NETWAVE is not set ++ ++# ++# Wireless 802.11 Frequency Hopping cards support ++# ++# CONFIG_PCMCIA_RAYCS is not set ++ ++# ++# Wireless 802.11b ISA/PCI cards support ++# ++# CONFIG_IPW2100 is not set ++# CONFIG_IPW2200 is not set ++# CONFIG_HERMES is not set ++# CONFIG_ATMEL is not set ++ ++# ++# Wireless 802.11b Pcmcia/Cardbus cards support ++# ++# CONFIG_AIRO_CS is not set ++# CONFIG_PCMCIA_WL3501 is not set ++ ++# ++# Prism GT/Duette 802.11(a/b/g) PCI/Cardbus support ++# ++# CONFIG_PRISM54 is not set ++# CONFIG_HOSTAP is not set ++CONFIG_NET_WIRELESS=y ++ ++# ++# PCMCIA network device support ++# ++CONFIG_NET_PCMCIA=y ++# CONFIG_PCMCIA_3C589 is not set ++# CONFIG_PCMCIA_3C574 is not set ++# CONFIG_PCMCIA_FMVJ18X is not set ++CONFIG_PCMCIA_PCNET=y ++# CONFIG_PCMCIA_NMCLAN is not set ++# CONFIG_PCMCIA_SMC91C92 is not set ++# CONFIG_PCMCIA_XIRC2PS is not set ++# CONFIG_PCMCIA_AXNET is not set ++ ++# ++# Wan interfaces ++# ++# CONFIG_WAN is not set ++# CONFIG_FDDI is not set ++# CONFIG_HIPPI is not set ++# CONFIG_PPP is not set ++# CONFIG_SLIP is not set ++# CONFIG_NET_FC is not set ++# CONFIG_SHAPER is not set ++# CONFIG_NETCONSOLE is not set ++# CONFIG_NETPOLL is not set ++# CONFIG_NET_POLL_CONTROLLER is not set ++ ++# ++# ISDN subsystem ++# ++# CONFIG_ISDN is not set ++ ++# ++# Input device support ++# ++CONFIG_INPUT=y ++ ++# ++# Userland interfaces ++# ++CONFIG_INPUT_MOUSEDEV=y ++CONFIG_INPUT_MOUSEDEV_PSAUX=y ++CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 ++CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 ++# CONFIG_INPUT_JOYDEV is not set ++# CONFIG_INPUT_TSDEV is not set ++CONFIG_INPUT_EVDEV=y ++# CONFIG_INPUT_EVBUG is not set ++ ++# ++# Input Device Drivers ++# ++# CONFIG_INPUT_KEYBOARD is not set ++# CONFIG_INPUT_MOUSE is not set ++# CONFIG_INPUT_JOYSTICK is not set ++# CONFIG_INPUT_TOUCHSCREEN is not set ++# CONFIG_INPUT_MISC is not set ++ ++# ++# Hardware I/O ports ++# ++CONFIG_SERIO=y ++# CONFIG_SERIO_SERPORT is not set ++# CONFIG_SERIO_PCIPS2 is not set ++CONFIG_SERIO_LIBPS2=y ++# CONFIG_SERIO_RAW is not set ++# CONFIG_GAMEPORT is not set ++ ++# ++# Character devices ++# ++CONFIG_VT=y ++CONFIG_VT_CONSOLE=y ++CONFIG_HW_CONSOLE=y ++# CONFIG_SERIAL_NONSTANDARD is not set ++ ++# ++# Serial drivers ++# ++CONFIG_SERIAL_8250=y ++# CONFIG_SERIAL_8250_CONSOLE is not set ++# CONFIG_SERIAL_8250_CS is not set ++CONFIG_SERIAL_8250_NR_UARTS=4 ++CONFIG_SERIAL_8250_RUNTIME_UARTS=4 ++# CONFIG_SERIAL_8250_EXTENDED is not set ++ ++# ++# Non-8250 serial port support ++# ++CONFIG_SERIAL_PXA=y ++CONFIG_SERIAL_PXA_CONSOLE=y ++CONFIG_SERIAL_CORE=y ++CONFIG_SERIAL_CORE_CONSOLE=y ++# CONFIG_SERIAL_JSM is not set ++CONFIG_UNIX98_PTYS=y ++CONFIG_LEGACY_PTYS=y ++CONFIG_LEGACY_PTY_COUNT=256 ++ ++# ++# IPMI ++# ++# CONFIG_IPMI_HANDLER is not set ++ ++# ++# Watchdog Cards ++# ++# CONFIG_WATCHDOG is not set ++# CONFIG_NVRAM is not set ++# CONFIG_RTC is not set ++# CONFIG_DTLK is not set ++# CONFIG_R3964 is not set ++# CONFIG_APPLICOM is not set ++ ++# ++# Ftape, the floppy tape device driver ++# ++# CONFIG_DRM is not set ++ ++# ++# PCMCIA character devices ++# ++# CONFIG_SYNCLINK_CS is not set ++# CONFIG_CARDMAN_4000 is not set ++# CONFIG_CARDMAN_4040 is not set ++# CONFIG_RAW_DRIVER is not set ++ ++# ++# TPM devices ++# ++# CONFIG_TCG_TPM is not set ++# CONFIG_TELCLOCK is not set ++CONFIG_EMV3020_RTC=y ++ ++# ++# I2C support ++# ++# CONFIG_I2C is not set ++ ++# ++# SPI support ++# ++# CONFIG_SPI is not set ++# CONFIG_SPI_MASTER is not set ++ ++# ++# Dallas's 1-wire bus ++# ++# CONFIG_W1 is not set ++ ++# ++# Hardware Monitoring support ++# ++# CONFIG_HWMON is not set ++# CONFIG_HWMON_VID is not set ++ ++# ++# Misc devices ++# ++ ++# ++# Multimedia Capabilities Port drivers ++# ++CONFIG_UCB1400=m ++CONFIG_UCB1400_TS=m ++ ++# ++# Multimedia devices ++# ++# CONFIG_VIDEO_DEV is not set ++ ++# ++# Digital Video Broadcasting Devices ++# ++# CONFIG_DVB is not set ++ ++# ++# Graphics support ++# ++CONFIG_FB=y ++CONFIG_FB_CFB_FILLRECT=y ++CONFIG_FB_CFB_COPYAREA=y ++CONFIG_FB_CFB_IMAGEBLIT=y ++# CONFIG_FB_MACMODES is not set ++# CONFIG_FB_MODE_HELPERS is not set ++# CONFIG_FB_TILEBLITTING is not set ++# CONFIG_FB_CIRRUS is not set ++# CONFIG_FB_PM2 is not set ++# CONFIG_FB_CYBER2000 is not set ++# CONFIG_FB_ASILIANT is not set ++# CONFIG_FB_IMSTT is not set ++# CONFIG_FB_S1D13XXX is not set ++# CONFIG_FB_NVIDIA is not set ++# CONFIG_FB_RIVA is not set ++# CONFIG_FB_MATROX is not set ++# CONFIG_FB_RADEON_OLD is not set ++# CONFIG_FB_RADEON is not set ++# CONFIG_FB_ATY128 is not set ++# CONFIG_FB_ATY is not set ++# CONFIG_FB_SAVAGE is not set ++# CONFIG_FB_SIS is not set ++# CONFIG_FB_NEOMAGIC is not set ++# CONFIG_FB_KYRO is not set ++# CONFIG_FB_3DFX is not set ++# CONFIG_FB_VOODOO1 is not set ++# CONFIG_FB_TRIDENT is not set ++CONFIG_FB_PXA=y ++# CONFIG_FB_PXA_PARAMETERS is not set ++CONFIG_FB_MBX=m ++# CONFIG_FB_VIRTUAL is not set ++ ++# ++# Console display driver support ++# ++# CONFIG_VGA_CONSOLE is not set ++CONFIG_DUMMY_CONSOLE=y ++CONFIG_FRAMEBUFFER_CONSOLE=y ++# CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set ++# CONFIG_FONTS is not set ++CONFIG_FONT_8x8=y ++CONFIG_FONT_8x16=y ++ ++# ++# Logo configuration ++# ++CONFIG_LOGO=y ++CONFIG_LOGO_LINUX_MONO=y ++CONFIG_LOGO_LINUX_VGA16=y ++CONFIG_LOGO_LINUX_CLUT224=y ++# CONFIG_BACKLIGHT_LCD_SUPPORT is not set ++ ++# ++# Sound ++# ++CONFIG_SOUND=y ++ ++# ++# Advanced Linux Sound Architecture ++# ++CONFIG_SND=y ++CONFIG_SND_TIMER=y ++CONFIG_SND_PCM=y ++# CONFIG_SND_SEQUENCER is not set ++CONFIG_SND_OSSEMUL=y ++CONFIG_SND_MIXER_OSS=y ++CONFIG_SND_PCM_OSS=y ++# CONFIG_SND_DYNAMIC_MINORS is not set ++CONFIG_SND_SUPPORT_OLD_API=y ++# CONFIG_SND_VERBOSE_PRINTK is not set ++# CONFIG_SND_DEBUG is not set ++ ++# ++# Generic devices ++# ++CONFIG_SND_AC97_CODEC=y ++CONFIG_SND_AC97_BUS=y ++# CONFIG_SND_DUMMY is not set ++# CONFIG_SND_MTPAV is not set ++# CONFIG_SND_SERIAL_U16550 is not set ++# CONFIG_SND_MPU401 is not set ++ ++# ++# PCI devices ++# ++# CONFIG_SND_AD1889 is not set ++# CONFIG_SND_ALI5451 is not set ++# CONFIG_SND_ATIIXP is not set ++# CONFIG_SND_ATIIXP_MODEM is not set ++# CONFIG_SND_AU8810 is not set ++# CONFIG_SND_AU8820 is not set ++# CONFIG_SND_AU8830 is not set ++# CONFIG_SND_AZT3328 is not set ++# CONFIG_SND_BT87X is not set ++# CONFIG_SND_CA0106 is not set ++# CONFIG_SND_CMIPCI is not set ++# CONFIG_SND_CS4281 is not set ++# CONFIG_SND_CS46XX is not set ++# CONFIG_SND_EMU10K1 is not set ++# CONFIG_SND_EMU10K1X is not set ++# CONFIG_SND_ENS1370 is not set ++# CONFIG_SND_ENS1371 is not set ++# CONFIG_SND_ES1938 is not set ++# CONFIG_SND_ES1968 is not set ++# CONFIG_SND_FM801 is not set ++# CONFIG_SND_HDA_INTEL is not set ++# CONFIG_SND_HDSP is not set ++# CONFIG_SND_HDSPM is not set ++# CONFIG_SND_ICE1712 is not set ++# CONFIG_SND_ICE1724 is not set ++# CONFIG_SND_INTEL8X0 is not set ++# CONFIG_SND_INTEL8X0M is not set ++# CONFIG_SND_KORG1212 is not set ++# CONFIG_SND_MAESTRO3 is not set ++# CONFIG_SND_MIXART is not set ++# CONFIG_SND_NM256 is not set ++# CONFIG_SND_PCXHR is not set ++# CONFIG_SND_RME32 is not set ++# CONFIG_SND_RME96 is not set ++# CONFIG_SND_RME9652 is not set ++# CONFIG_SND_SONICVIBES is not set ++# CONFIG_SND_TRIDENT is not set ++# CONFIG_SND_VIA82XX is not set ++# CONFIG_SND_VIA82XX_MODEM is not set ++# CONFIG_SND_VX222 is not set ++# CONFIG_SND_YMFPCI is not set ++ ++# ++# ALSA ARM devices ++# ++CONFIG_SND_PXA2XX_PCM=y ++CONFIG_SND_PXA2XX_AC97=y ++ ++# ++# USB devices ++# ++# CONFIG_SND_USB_AUDIO is not set ++ ++# ++# PCMCIA devices ++# ++ ++# ++# Open Sound System ++# ++# CONFIG_SOUND_PRIME is not set ++ ++# ++# USB support ++# ++CONFIG_USB_ARCH_HAS_HCD=y ++CONFIG_USB_ARCH_HAS_OHCI=y ++CONFIG_USB=y ++# CONFIG_USB_DEBUG is not set ++ ++# ++# Miscellaneous USB options ++# ++CONFIG_USB_DEVICEFS=y ++# CONFIG_USB_BANDWIDTH is not set ++# CONFIG_USB_DYNAMIC_MINORS is not set ++# CONFIG_USB_SUSPEND is not set ++# CONFIG_USB_OTG is not set ++ ++# ++# USB Host Controller Drivers ++# ++# CONFIG_USB_EHCI_HCD is not set ++# CONFIG_USB_ISP116X_HCD is not set ++CONFIG_USB_OHCI_HCD=y ++# CONFIG_USB_OHCI_BIG_ENDIAN is not set ++CONFIG_USB_OHCI_LITTLE_ENDIAN=y ++# CONFIG_USB_UHCI_HCD is not set ++# CONFIG_USB_SL811_HCD is not set ++ ++# ++# USB Device Class drivers ++# ++# CONFIG_OBSOLETE_OSS_USB_DRIVER is not set ++# CONFIG_USB_ACM is not set ++# CONFIG_USB_PRINTER is not set ++ ++# ++# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' ++# ++ ++# ++# may also be needed; see USB_STORAGE Help for more information ++# ++CONFIG_USB_STORAGE=y ++# CONFIG_USB_STORAGE_DEBUG is not set ++# CONFIG_USB_STORAGE_DATAFAB is not set ++# CONFIG_USB_STORAGE_FREECOM is not set ++# CONFIG_USB_STORAGE_ISD200 is not set ++# CONFIG_USB_STORAGE_DPCM is not set ++# CONFIG_USB_STORAGE_USBAT is not set ++# CONFIG_USB_STORAGE_SDDR09 is not set ++# CONFIG_USB_STORAGE_SDDR55 is not set ++# CONFIG_USB_STORAGE_JUMPSHOT is not set ++# CONFIG_USB_STORAGE_ALAUDA is not set ++# CONFIG_USB_LIBUSUAL is not set ++ ++# ++# USB Input Devices ++# ++CONFIG_USB_HID=y ++CONFIG_USB_HIDINPUT=y ++# CONFIG_USB_HIDINPUT_POWERBOOK is not set ++# CONFIG_HID_FF is not set ++# CONFIG_USB_HIDDEV is not set ++# CONFIG_USB_AIPTEK is not set ++# CONFIG_USB_WACOM is not set ++# CONFIG_USB_ACECAD is not set ++# CONFIG_USB_KBTAB is not set ++# CONFIG_USB_POWERMATE is not set ++# CONFIG_USB_MTOUCH is not set ++# CONFIG_USB_ITMTOUCH is not set ++# CONFIG_USB_EGALAX is not set ++# CONFIG_USB_YEALINK is not set ++# CONFIG_USB_XPAD is not set ++# CONFIG_USB_ATI_REMOTE is not set ++# CONFIG_USB_ATI_REMOTE2 is not set ++# CONFIG_USB_KEYSPAN_REMOTE is not set ++# CONFIG_USB_APPLETOUCH is not set ++ ++# ++# USB Imaging devices ++# ++# CONFIG_USB_MDC800 is not set ++# CONFIG_USB_MICROTEK is not set ++ ++# ++# USB Multimedia devices ++# ++# CONFIG_USB_DABUSB is not set ++ ++# ++# Video4Linux support is needed for USB Multimedia device support ++# ++ ++# ++# USB Network Adapters ++# ++# CONFIG_USB_CATC is not set ++# CONFIG_USB_KAWETH is not set ++# CONFIG_USB_PEGASUS is not set ++# CONFIG_USB_RTL8150 is not set ++# CONFIG_USB_USBNET is not set ++# CONFIG_USB_ZD1201 is not set ++CONFIG_USB_MON=y ++ ++# ++# USB port drivers ++# ++ ++# ++# USB Serial Converter support ++# ++# CONFIG_USB_SERIAL is not set ++ ++# ++# USB Miscellaneous drivers ++# ++# CONFIG_USB_EMI62 is not set ++# CONFIG_USB_EMI26 is not set ++# CONFIG_USB_AUERSWALD 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_CYTHERM is not set ++# CONFIG_USB_PHIDGETKIT is not set ++# CONFIG_USB_PHIDGETSERVO is not set ++# CONFIG_USB_IDMOUSE is not set ++# CONFIG_USB_LD is not set ++# CONFIG_USB_TEST is not set ++ ++# ++# USB DSL modem support ++# ++ ++# ++# USB Gadget Support ++# ++# CONFIG_USB_GADGET is not set ++ ++# ++# MMC/SD Card support ++# ++# CONFIG_MMC is not set ++ ++# ++# File systems ++# ++CONFIG_EXT2_FS=y ++# CONFIG_EXT2_FS_XATTR is not set ++# CONFIG_EXT2_FS_XIP is not set ++CONFIG_EXT3_FS=y ++CONFIG_EXT3_FS_XATTR=y ++# CONFIG_EXT3_FS_POSIX_ACL is not set ++# CONFIG_EXT3_FS_SECURITY is not set ++CONFIG_JBD=y ++# CONFIG_JBD_DEBUG is not set ++CONFIG_FS_MBCACHE=y ++# CONFIG_REISERFS_FS is not set ++# CONFIG_JFS_FS is not set ++# CONFIG_FS_POSIX_ACL is not set ++# CONFIG_XFS_FS is not set ++# CONFIG_OCFS2_FS is not set ++# CONFIG_MINIX_FS is not set ++# CONFIG_ROMFS_FS is not set ++CONFIG_INOTIFY=y ++# CONFIG_QUOTA is not set ++CONFIG_DNOTIFY=y ++# CONFIG_AUTOFS_FS is not set ++# CONFIG_AUTOFS4_FS is not set ++# CONFIG_FUSE_FS is not set ++ ++# ++# CD-ROM/DVD Filesystems ++# ++# CONFIG_ISO9660_FS is not set ++# CONFIG_UDF_FS is not set ++ ++# ++# DOS/FAT/NT Filesystems ++# ++CONFIG_FAT_FS=y ++CONFIG_MSDOS_FS=y ++CONFIG_VFAT_FS=y ++CONFIG_FAT_DEFAULT_CODEPAGE=437 ++CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1" ++# CONFIG_NTFS_FS is not set ++ ++# ++# Pseudo filesystems ++# ++CONFIG_PROC_FS=y ++CONFIG_SYSFS=y ++CONFIG_TMPFS=y ++# CONFIG_HUGETLB_PAGE is not set ++CONFIG_RAMFS=y ++# CONFIG_RELAYFS_FS is not set ++# CONFIG_CONFIGFS_FS is not set ++ ++# ++# Miscellaneous filesystems ++# ++# CONFIG_ADFS_FS is not set ++# CONFIG_AFFS_FS is not set ++# CONFIG_HFS_FS is not set ++# CONFIG_HFSPLUS_FS is not set ++# CONFIG_BEFS_FS is not set ++# CONFIG_BFS_FS is not set ++# CONFIG_EFS_FS is not set ++# CONFIG_CRAMFS is not set ++# CONFIG_VXFS_FS is not set ++# CONFIG_HPFS_FS is not set ++# CONFIG_QNX4FS_FS is not set ++# CONFIG_SYSV_FS is not set ++# CONFIG_UFS_FS is not set ++ ++# ++# Network File Systems ++# ++CONFIG_NFS_FS=y ++CONFIG_NFS_V3=y ++# CONFIG_NFS_V3_ACL is not set ++# CONFIG_NFS_V4 is not set ++# CONFIG_NFS_DIRECTIO is not set ++# CONFIG_NFSD is not set ++CONFIG_ROOT_NFS=y ++CONFIG_LOCKD=y ++CONFIG_LOCKD_V4=y ++CONFIG_NFS_COMMON=y ++CONFIG_SUNRPC=y ++# CONFIG_RPCSEC_GSS_KRB5 is not set ++# CONFIG_RPCSEC_GSS_SPKM3 is not set ++CONFIG_SMB_FS=y ++# CONFIG_SMB_NLS_DEFAULT is not set ++# CONFIG_CIFS is not set ++# CONFIG_NCP_FS is not set ++# CONFIG_CODA_FS is not set ++# CONFIG_AFS_FS is not set ++# CONFIG_9P_FS is not set ++ ++# ++# Partition Types ++# ++# CONFIG_PARTITION_ADVANCED is not set ++CONFIG_MSDOS_PARTITION=y ++ ++# ++# Native Language Support ++# ++CONFIG_NLS=y ++CONFIG_NLS_DEFAULT="iso8859-1" ++CONFIG_NLS_CODEPAGE_437=y ++# CONFIG_NLS_CODEPAGE_737 is not set ++# CONFIG_NLS_CODEPAGE_775 is not set ++# CONFIG_NLS_CODEPAGE_850 is not set ++# CONFIG_NLS_CODEPAGE_852 is not set ++# CONFIG_NLS_CODEPAGE_855 is not set ++# CONFIG_NLS_CODEPAGE_857 is not set ++# CONFIG_NLS_CODEPAGE_860 is not set ++# CONFIG_NLS_CODEPAGE_861 is not set ++# CONFIG_NLS_CODEPAGE_862 is not set ++# CONFIG_NLS_CODEPAGE_863 is not set ++# CONFIG_NLS_CODEPAGE_864 is not set ++# CONFIG_NLS_CODEPAGE_865 is not set ++# CONFIG_NLS_CODEPAGE_866 is not set ++# CONFIG_NLS_CODEPAGE_869 is not set ++# CONFIG_NLS_CODEPAGE_936 is not set ++# CONFIG_NLS_CODEPAGE_950 is not set ++# CONFIG_NLS_CODEPAGE_932 is not set ++# CONFIG_NLS_CODEPAGE_949 is not set ++# CONFIG_NLS_CODEPAGE_874 is not set ++# CONFIG_NLS_ISO8859_8 is not set ++# CONFIG_NLS_CODEPAGE_1250 is not set ++# CONFIG_NLS_CODEPAGE_1251 is not set ++# CONFIG_NLS_ASCII is not set ++CONFIG_NLS_ISO8859_1=y ++# CONFIG_NLS_ISO8859_2 is not set ++# CONFIG_NLS_ISO8859_3 is not set ++# CONFIG_NLS_ISO8859_4 is not set ++# CONFIG_NLS_ISO8859_5 is not set ++# CONFIG_NLS_ISO8859_6 is not set ++# CONFIG_NLS_ISO8859_7 is not set ++# CONFIG_NLS_ISO8859_9 is not set ++# CONFIG_NLS_ISO8859_13 is not set ++# CONFIG_NLS_ISO8859_14 is not set ++# CONFIG_NLS_ISO8859_15 is not set ++# CONFIG_NLS_KOI8_R is not set ++# CONFIG_NLS_KOI8_U is not set ++# CONFIG_NLS_UTF8 is not set ++ ++# ++# Profiling support ++# ++# CONFIG_PROFILING is not set ++ ++# ++# Kernel hacking ++# ++# CONFIG_PRINTK_TIME is not set ++CONFIG_MAGIC_SYSRQ=y ++CONFIG_DEBUG_KERNEL=y ++CONFIG_LOG_BUF_SHIFT=17 ++# CONFIG_DETECT_SOFTLOCKUP is not set ++# CONFIG_SCHEDSTATS is not set ++# CONFIG_DEBUG_SLAB is not set ++# CONFIG_DEBUG_MUTEXES is not set ++# CONFIG_DEBUG_SPINLOCK is not set ++# CONFIG_DEBUG_SPINLOCK_SLEEP is not set ++# CONFIG_DEBUG_KOBJECT is not set ++# CONFIG_DEBUG_BUGVERBOSE is not set ++CONFIG_DEBUG_INFO=y ++# CONFIG_DEBUG_FS is not set ++# CONFIG_DEBUG_VM is not set ++CONFIG_FRAME_POINTER=y ++CONFIG_FORCED_INLINING=y ++# CONFIG_RCU_TORTURE_TEST is not set ++CONFIG_DEBUG_USER=y ++# CONFIG_DEBUG_WAITQ is not set ++CONFIG_DEBUG_ERRORS=y ++CONFIG_DEBUG_LL=y ++# CONFIG_DEBUG_ICEDCC is not set ++ ++# ++# Security options ++# ++# CONFIG_KEYS is not set ++# CONFIG_SECURITY is not set ++ ++# ++# Cryptographic options ++# ++CONFIG_CRYPTO=y ++# CONFIG_CRYPTO_HMAC is not set ++# CONFIG_CRYPTO_NULL is not set ++# CONFIG_CRYPTO_MD4 is not set ++# CONFIG_CRYPTO_MD5 is not set ++# CONFIG_CRYPTO_SHA1 is not set ++# CONFIG_CRYPTO_SHA256 is not set ++# CONFIG_CRYPTO_SHA512 is not set ++# CONFIG_CRYPTO_WP512 is not set ++# CONFIG_CRYPTO_TGR192 is not set ++# CONFIG_CRYPTO_DES is not set ++# CONFIG_CRYPTO_BLOWFISH is not set ++# CONFIG_CRYPTO_TWOFISH is not set ++# CONFIG_CRYPTO_SERPENT is not set ++CONFIG_CRYPTO_AES=m ++# CONFIG_CRYPTO_CAST5 is not set ++# CONFIG_CRYPTO_CAST6 is not set ++# CONFIG_CRYPTO_TEA is not set ++CONFIG_CRYPTO_ARC4=m ++# CONFIG_CRYPTO_KHAZAD is not set ++# CONFIG_CRYPTO_ANUBIS is not set ++# CONFIG_CRYPTO_DEFLATE is not set ++# CONFIG_CRYPTO_MICHAEL_MIC is not set ++# CONFIG_CRYPTO_CRC32C is not set ++# CONFIG_CRYPTO_TEST is not set ++ ++# ++# Hardware crypto devices ++# ++ ++# ++# Library routines ++# ++# CONFIG_CRC_CCITT is not set ++# CONFIG_CRC16 is not set ++CONFIG_CRC32=y ++# CONFIG_LIBCRC32C is not set +diff --git a/arch/arm/kernel/bios32.c b/arch/arm/kernel/bios32.c +index c4923fa..4ff2a62 100644 +--- a/arch/arm/kernel/bios32.c ++++ b/arch/arm/kernel/bios32.c +@@ -280,6 +280,34 @@ static void __devinit pci_fixup_cy82c693 + } + DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_CONTAQ, PCI_DEVICE_ID_CONTAQ_82C693, pci_fixup_cy82c693); + ++static void __init pci_fixup_it8152(struct pci_dev *dev) ++{ ++ int i; ++ if ((dev->class >> 8) == PCI_CLASS_BRIDGE_HOST) { ++ for (i = 0; i < PCI_NUM_RESOURCES; i++) { ++ dev->resource[i].start = 0; ++ dev->resource[i].end = 0; ++ dev->resource[i].flags = 0; ++ } ++ } ++ if (dev->class == 0x68000) { ++ for (i = 0; i < PCI_NUM_RESOURCES; i++) { ++ dev->resource[i].start = 0; ++ dev->resource[i].end = 0; ++ dev->resource[i].flags = 0; ++ } ++ } ++ if (dev->class == 0x80103) { ++ for (i = 0; i < PCI_NUM_RESOURCES; i++) { ++ dev->resource[i].start = 0; ++ dev->resource[i].end = 0; ++ dev->resource[i].flags = 0; ++ } ++ } ++} ++DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_ITE, PCI_DEVICE_ID_ITE_IT8152, pci_fixup_it8152); ++ ++ + void __devinit pcibios_update_irq(struct pci_dev *dev, int irq) + { + if (debug_pci) +@@ -293,9 +321,11 @@ void __devinit pcibios_update_irq(struct + */ + static inline int pdev_bad_for_parity(struct pci_dev *dev) + { +- return (dev->vendor == PCI_VENDOR_ID_INTERG && +- (dev->device == PCI_DEVICE_ID_INTERG_2000 || +- dev->device == PCI_DEVICE_ID_INTERG_2010)); ++ return ((dev->vendor == PCI_VENDOR_ID_INTERG && ++ (dev->device == PCI_DEVICE_ID_INTERG_2000 || ++ dev->device == PCI_DEVICE_ID_INTERG_2010)) || ++ (dev->vendor == PCI_VENDOR_ID_ITE && ++ dev->device == PCI_DEVICE_ID_ITE_IT8152)); + } + + /* +diff --git a/arch/arm/kernel/vmlinux.lds.S b/arch/arm/kernel/vmlinux.lds.S +index 2b254e8..310ccf5 100644 +--- a/arch/arm/kernel/vmlinux.lds.S ++++ b/arch/arm/kernel/vmlinux.lds.S +@@ -175,5 +175,5 @@ #endif + * If you have to comment these two assert statements out, your + * binutils is too old (for other reasons as well) + */ +-ASSERT((__proc_info_end - __proc_info_begin), "missing CPU support") +-ASSERT((__arch_info_end - __arch_info_begin), "no machine record defined") ++/* ASSERT((__proc_info_end - __proc_info_begin), "missing CPU support") */ ++/* ASSERT((__arch_info_end - __arch_info_begin), "no machine record defined") */ +diff --git a/arch/arm/mach-pxa/Kconfig b/arch/arm/mach-pxa/Kconfig +index c1d77f5..c240211 100644 +--- a/arch/arm/mach-pxa/Kconfig ++++ b/arch/arm/mach-pxa/Kconfig +@@ -15,6 +15,11 @@ config MACH_MAINSTONE + select PXA27x + select IWMMXT + ++config MACH_ARMCORE ++ bool "CompuLab CM-X270 modules" ++ select PXA27x ++ select IWMMXT ++ + config ARCH_PXA_IDP + bool "Accelent Xscale IDP" + select PXA25x +@@ -50,6 +55,25 @@ endchoice + + endif + ++if MACH_ARMCORE ++choice ++ prompt "Select CM-X270 base board" ++ config ARMCORE_ATXBASE ++ bool "ATX-X270 base board" ++ config ARMCORE_SB270 ++ bool "SB-270 base board" ++endchoice ++ ++choice ++ prompt "Select CM-X270 revision" ++ config ARMCORE_REV12 ++ bool "CM-X270 revision 1.2" ++ config ARMCORE_REV11 ++ bool "CM-X270 revision 1.1" ++endchoice ++ ++endif ++ + endmenu + + config MACH_POODLE +diff --git a/arch/arm/mach-pxa/Makefile b/arch/arm/mach-pxa/Makefile +index 32526a0..d78d061 100644 +--- a/arch/arm/mach-pxa/Makefile ++++ b/arch/arm/mach-pxa/Makefile +@@ -16,12 +16,14 @@ obj-$(CONFIG_PXA_SHARP_Cxx00) += spitz.o + obj-$(CONFIG_MACH_AKITA) += akita-ioexp.o + obj-$(CONFIG_MACH_POODLE) += poodle.o + obj-$(CONFIG_MACH_TOSA) += tosa.o ++obj-$(CONFIG_MACH_ARMCORE) += cm-x270.o + + # Support for blinky lights + led-y := leds.o + led-$(CONFIG_ARCH_LUBBOCK) += leds-lubbock.o + led-$(CONFIG_MACH_MAINSTONE) += leds-mainstone.o + led-$(CONFIG_ARCH_PXA_IDP) += leds-idp.o ++led-$(CONFIG_MACH_ARMCORE) += leds-cm-x270.o + + obj-$(CONFIG_LEDS) += $(led-y) + +@@ -32,3 +34,10 @@ obj-$(CONFIG_PXA_SSP) += ssp.o + ifeq ($(CONFIG_PXA27x),y) + obj-$(CONFIG_PM) += standby.o + endif ++ ++# PCI support on CM-X270 ++obj-$(CONFIG_PCI_HOST_ITE8152) += it8152.o ++ ++ifeq ($(CONFIG_PCI),y) ++obj-$(CONFIG_MACH_ARMCORE) += cm-x270-pci.o ++endif +diff --git a/arch/arm/mach-pxa/cm-x270-pci.c b/arch/arm/mach-pxa/cm-x270-pci.c +new file mode 100644 +index 0000000..73243d3 +--- /dev/null ++++ b/arch/arm/mach-pxa/cm-x270-pci.c +@@ -0,0 +1,152 @@ ++/* ++ * arch/arm/kernel/cm-x270-pci.c ++ * ++ * PCI bios-type initialisation for PCI machines ++ * ++ * Bits taken from various places. ++ * ++ * Copyright (C) 2006 Compulab, Ltd. ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 as ++ * published by the Free Software Foundation. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++ ++#include ++ ++unsigned long armcore_pcibios_min_mem = 0x10000000; ++unsigned long armcore_pcibios_min_io = CMX270_IT8152_VIRT + 0x03e00000 + 0x120000; ++unsigned long it8152_base_address = CMX270_IT8152_VIRT; ++ ++/* these symbols needed for CardBus driver (yenta_socket) */ ++EXPORT_SYMBOL(armcore_pcibios_min_io); ++EXPORT_SYMBOL(armcore_pcibios_min_mem); ++ ++static u8 __init cmx270_pci_swizzle(struct pci_dev *dev, u8 *pin) ++{ ++ return PCI_SLOT(dev->devfn); ++} ++ ++/* Platform specific IRQ mapping */ ++static int __init cmx270_pci_map_irq(struct pci_dev *dev, u8 slot, u8 pin) ++{ ++ if((dev->vendor==0x1283) && (dev->device==0x8152) && ++ ((dev->class >> 8)==0x801)) return(CDMA_INT); ++ if((dev->vendor==0x1283) && (dev->device==0x0801) && ++ ((dev->class >> 8)==0x401)) return(AUDIO_INT); ++ if((dev->vendor==0x1283) && (dev->device==0x8152) && ++ ((dev->class >> 8)==0xc03)) return(USB_INT); ++ ++ /* ATXBASE PCI slot */ ++ if ( slot == 7 ) ++ return(PCI_INTA); ++ ++ /* ATXBASE/SB-X270 CardBus */ ++ if ( (slot == 8) || (slot == 0) ) ++ return(PCI_INTB); ++ ++ /* ATXBASE ETH */ ++ if ( slot == 9 ) ++ return(PCI_INTA); ++ ++ /* ARMCore onboard ETH */ ++ if ( slot == 15 ) ++ return(PCI_INTC); ++ ++ /* ARMBase ETH */ ++ if ( slot == 16 ) ++ return(PCI_INTA); ++ ++ /* PC104+ interrupt routing */ ++ if ( (slot == 17) || (slot == 19) ) ++ return(PCI_INTA); ++ if ( (slot == 18) || (slot == 20) ) ++ return(PCI_INTB); ++ ++ return(0); ++} ++ ++extern int it8152_pci_setup(int nr, struct pci_sys_data *sys); ++extern struct pci_bus * it8152_pci_scan_bus(int nr, struct pci_sys_data *sys); ++ ++static struct pci_bus* __init cmx270_pci_scan_bus(int nr, struct pci_sys_data *sys) ++{ ++ IT8152_PCI_CFG_ADDR = 0x800; ++ if(IT8152_PCI_CFG_DATA == 0x81521283) { ++ printk("PCI Bridge found.\n"); ++ ++ IT8152_GPIO_GPLR=0x20; ++ ++/*********** CardBus Controller on ATXBASE configuration ********/ ++ IT8152_PCI_CFG_ADDR = 0x4000; ++ if(IT8152_PCI_CFG_DATA == 0xAC51104C) { ++ unsigned int temp; ++ printk("CardBus Bridge found.\n"); ++ ++ // Configure socket 0 ++ IT8152_PCI_CFG_ADDR = 0x408C; ++ IT8152_PCI_CFG_DATA = 0x1022; ++ ++ IT8152_PCI_CFG_ADDR = 0x4080; ++ IT8152_PCI_CFG_DATA = 0x3844d060; ++ ++ IT8152_PCI_CFG_ADDR = 0x4090; ++ temp = IT8152_PCI_CFG_DATA; ++ temp = temp & 0xFFFF; ++ temp = temp | (0x60440000); ++ IT8152_PCI_CFG_ADDR = 0x4090; ++ IT8152_PCI_CFG_DATA = temp; ++ ++ IT8152_PCI_CFG_ADDR = 0x4018; ++ IT8152_PCI_CFG_DATA = 0xb0000000; ++ ++ // Configure socket 1 ++ IT8152_PCI_CFG_ADDR = 0x418C; ++ IT8152_PCI_CFG_DATA = 0x1022; ++ ++ IT8152_PCI_CFG_ADDR = 0x4180; ++ IT8152_PCI_CFG_DATA = 0x3844d060; ++ ++ IT8152_PCI_CFG_ADDR = 0x4190; ++ temp = IT8152_PCI_CFG_DATA; ++ temp = temp & 0xFFFF; ++ temp = temp | (0x60440000); ++ IT8152_PCI_CFG_ADDR = 0x4190; ++ IT8152_PCI_CFG_DATA = temp; ++ ++ IT8152_PCI_CFG_ADDR = 0x4118; ++ IT8152_PCI_CFG_DATA = 0xb0000000; ++ } ++/*********** End of CardBus controller configuration **************/ ++ } ++ return it8152_pci_scan_bus(nr, sys); ++} ++ ++static struct hw_pci cmx270_pci __initdata = { ++ .swizzle = cmx270_pci_swizzle, ++ .map_irq = cmx270_pci_map_irq, ++ .nr_controllers = 1, ++ .setup = it8152_pci_setup, ++ .scan = cmx270_pci_scan_bus, ++}; ++ ++static int __init cmx270_init_pci(void) ++{ ++ if (machine_is_armcore()) { ++ pci_common_init(&cmx270_pci); ++ } ++ return 0; ++} ++ ++subsys_initcall(cmx270_init_pci); +diff --git a/arch/arm/mach-pxa/cm-x270.c b/arch/arm/mach-pxa/cm-x270.c +new file mode 100644 +index 0000000..6157135 +--- /dev/null ++++ b/arch/arm/mach-pxa/cm-x270.c +@@ -0,0 +1,887 @@ ++/* ++ * linux/arch/arm/mach-pxa/cm-x270.c ++ * ++ * Copyright (C) 2006 CompuLab, Ltd. ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 as ++ * published by the Free Software Foundation. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++ ++#include "generic.h" ++ ++#define RTC_PHYS_BASE (PXA_CS1_PHYS + (5 << 22)) ++#define DM9000_PHYS_BASE (PXA_CS1_PHYS + (6 << 22)) ++ ++static struct resource cmx270_dm9k_resource[] = { ++ [0] = { ++ .start = DM9000_PHYS_BASE, ++ .end = DM9000_PHYS_BASE + 4, ++ .flags = IORESOURCE_MEM, ++ }, ++ [1] = { ++ .start = DM9000_PHYS_BASE + 8, ++ .end = DM9000_PHYS_BASE + 8 + 500, ++ .flags = IORESOURCE_MEM, ++ }, ++ [2] = { ++ .start = CMX270_ETHIRQ, ++ .end = CMX270_ETHIRQ, ++ .flags = IORESOURCE_IRQ, ++ } ++}; ++ ++/* for the moment we limit ourselves to 32bit IO until some ++ * better IO routines can be written and tested ++ */ ++static struct dm9000_plat_data cmx270_dm9k_platdata = { ++ .flags = DM9000_PLATF_32BITONLY, ++}; ++ ++/* Ethernet device */ ++static struct platform_device cmx270_device_dm9k = { ++ .name = "dm9000", ++ .id = 0, ++ .num_resources = ARRAY_SIZE(cmx270_dm9k_resource), ++ .resource = cmx270_dm9k_resource, ++ .dev = { ++ .platform_data = &cmx270_dm9k_platdata, ++ } ++}; ++ ++/* audio device */ ++static struct platform_device cmx270_audio_device = { ++ .name = "pxa2xx-ac97", ++ .id = -1, ++}; ++ ++/* touchscreen controller */ ++static struct platform_device cmx270_ts_device = { ++ .name = "ucb1x00", ++ .id = -1, ++}; ++ ++/* RTC */ ++static struct resource cmx270_v3020_resource[] = { ++ [0] = { ++ .start = RTC_PHYS_BASE, ++ .end = RTC_PHYS_BASE + 4, ++ .flags = IORESOURCE_MEM, ++ }, ++}; ++ ++static struct platform_device cmx270_rtc_device = { ++ .name = "emv3020-rtc", ++ .num_resources = ARRAY_SIZE(cmx270_v3020_resource), ++ .resource = cmx270_v3020_resource, ++ .id = -1, ++}; ++ ++/* UART on the ITE8152 chip */ ++#ifdef CONFIG_PCI ++static struct plat_serial8250_port ite_uart_port[] = { ++ { ++ .irq = IRQ_ITESER, /* interrupt number */ ++ .uartclk = 115200 * 16, /* UART clock rate */ ++ .iotype = UPIO_MEM, /* UPIO_* */ ++ .flags = UPF_BOOT_AUTOCONF, ++ }, ++ {} ++}; ++ ++static struct platform_device iteuart_device = { ++ .name = "serial8250", ++ .id = PLAT8250_DEV_PLATFORM, ++ .dev = { ++ .platform_data = ite_uart_port, ++ }, ++}; ++#endif ++ ++/* 2700G graphics */ ++static u64 fb_dma_mask = ~(u64)0; ++ ++static struct resource cmx270_2700G_resource[] = { ++ /* frame buffer memory including ODFB and External SDRAM */ ++ [0] = { ++ .start = MARATHON_PHYS, ++ .end = MARATHON_PHYS + 0x02000000, ++ .flags = IORESOURCE_MEM, ++ }, ++ /* Marathon registers */ ++ [1] = { ++ .start = MARATHON_PHYS + 0x03fe0000, ++ .end = MARATHON_PHYS + 0x03ffffff, ++ .flags = IORESOURCE_MEM, ++ }, ++}; ++ ++static unsigned long save_lcd_regs[10]; ++ ++#define LB_TROTTLE_OFF (PXA_CS1_PHYS | (1 << 25)) ++#define LB_TROTTLE_MAX (PXA_CS1_PHYS | (1 << 25) | (1 << 22)) ++static int cmx270_marathon_probe(struct fb_info *fb) ++{ ++ volatile unsigned long *cpld; ++ ++ cpld = (volatile unsigned long*)ioremap(LB_TROTTLE_OFF, 4); ++ ++ if ( !cpld ) { ++ return -ENODEV; ++ } ++ *cpld = 0; ++ iounmap((void*)cpld); ++ ++ ++ /* save PXA-270 pin settings before enabling 2700G */ ++ save_lcd_regs[0] = GPDR1; ++ save_lcd_regs[1] = GPDR2; ++ save_lcd_regs[2] = GAFR1_U; ++ save_lcd_regs[3] = GAFR2_L; ++ save_lcd_regs[4] = GAFR2_U; ++ ++ /* Disable PXA-270 on-chip controller driving pins */ ++ GPDR1 &= ~(0xfc000000); ++ GPDR2 &= ~(0x00c03fff); ++ GAFR1_U &= ~(0xfff00000); ++ GAFR2_L &= ~(0x0fffffff); ++ GAFR2_U &= ~(0x0000f000); ++ return 0; ++} ++ ++static int cmx270_marathon_remove(struct fb_info *fb) ++{ ++ volatile unsigned long *cpld; ++ ++ cpld = (volatile unsigned long*)ioremap(LB_TROTTLE_MAX, 4); ++ ++ if ( !cpld ) { ++ return -ENODEV; ++ } ++ *cpld = 0; ++ iounmap((void*)cpld); ++ ++ GPDR1 = save_lcd_regs[0]; ++ GPDR2 = save_lcd_regs[1]; ++ GAFR1_U = save_lcd_regs[2]; ++ GAFR2_L = save_lcd_regs[3]; ++ GAFR2_U = save_lcd_regs[4]; ++ return 0; ++} ++ ++static struct mbxfb_platform_data cmx270_2700G_data = { ++ .xres = { ++ .min = 240, ++ .max = 1200, ++ .defval = 640, ++ }, ++ .yres = { ++ .min = 240, ++ .max = 1200, ++ .defval = 480, ++ }, ++ .bpp = { ++ .min = 16, ++ .max = 32, ++ .defval = 16, ++ }, ++ .memsize = 8*1024*1024, ++ .probe = cmx270_marathon_probe, ++ .remove = cmx270_marathon_remove, ++}; ++ ++static struct platform_device cmx270_2700G = { ++ .name = "mbx-fb", ++ .dev = { ++ .platform_data = &cmx270_2700G_data, ++ .dma_mask = &fb_dma_mask, ++ .coherent_dma_mask = 0xffffffff, ++ }, ++ .num_resources = ARRAY_SIZE(cmx270_2700G_resource), ++ .resource = cmx270_2700G_resource, ++ .id = -1, ++}; ++ ++/* platform devices */ ++static struct platform_device *platform_devices[] __initdata = { ++ &cmx270_device_dm9k, ++ &cmx270_audio_device, ++ &cmx270_ts_device, ++ &cmx270_rtc_device, ++ &cmx270_2700G, ++#ifdef CONFIG_PCI ++ &iteuart_device, ++#endif ++}; ++ ++#ifdef CONFIG_PCI ++/* ++ * Install handler for IT8152 IRQ. Yes, yes... we are way down the IRQ ++ * cascade which is not good for IRQ latency, but the hardware has been ++ * designed that way... ++ */ ++static inline void cmx270_irq(int irq, struct pt_regs *regs) ++{ ++ struct irqdesc *desc; ++ desc = irq_desc + irq; ++ desc->handle(irq, desc, regs); ++} ++ ++static void cmx270_irq_demux(unsigned int irq, struct irqdesc *desc, ++ struct pt_regs *regs) ++{ ++ unsigned long pdcnimr, ldcnimr; ++ int pdcnirr, ldcnir; ++ ++ /* clear our parent irq */ ++ GEDR(GPIO_IT8152_IRQ) = GPIO_bit(GPIO_IT8152_IRQ); ++ ++ /* read pending IRQs in the chip registers and clear them */ ++ pdcnirr = IT8152_INTC_PDCNIRR; ++ ldcnir = IT8152_INTC_LDCNIRR; ++ IT8152_INTC_PDCNIRR = ~pdcnirr; ++ IT8152_INTC_LDCNIRR = ~ldcnir; ++ ++ /* mask ITE irqs */ ++ pdcnimr = IT8152_INTC_PDCNIMR; ++ ldcnimr = IT8152_INTC_LDCNIMR; ++ IT8152_INTC_PDCNIMR = 0xffff; ++ IT8152_INTC_LDCNIMR = 0xffff; ++ ++ pdcnirr &= (PCISERR_BIT | H2PTADR_BIT | H2PMAR_BIT | ++ PCI_INTD_BIT | PCI_INTC_BIT | PCI_INTB_BIT | PCI_INTA_BIT | ++ USB_INT_BIT | CDMA_INT_BIT); ++ ++ ldcnir &= ITESER_BIT; ++ ++ IT8152_INTC_PDCNIRR = ~pdcnirr; ++ IT8152_INTC_LDCNIRR = ~ldcnir; ++ ++ /* are there interrupts pending ? */ ++ if( (pdcnirr | ldcnir) ) { ++ if (pdcnirr) { ++ if( pdcnirr & PCISERR_BIT ) ++ cmx270_irq(PCISERR, regs); ++ if( pdcnirr & H2PTADR_BIT ) ++ cmx270_irq(H2PTADR, regs); ++ if( pdcnirr & H2PMAR_BIT ) ++ cmx270_irq(H2PMAR, regs); ++ if( pdcnirr & PCI_INTA_BIT ) ++ cmx270_irq(PCI_INTA, regs); ++ if( pdcnirr & PCI_INTB_BIT ) ++ cmx270_irq(PCI_INTB, regs); ++ if( pdcnirr & PCI_INTC_BIT ) ++ cmx270_irq(PCI_INTC, regs); ++ if( pdcnirr & PCI_INTD_BIT ) ++ cmx270_irq(PCI_INTD, regs); ++ if( pdcnirr & USB_INT_BIT ) ++ cmx270_irq(USB_INT, regs); ++ if( pdcnirr & CDMA_INT_BIT ) ++ cmx270_irq(CDMA_INT, regs); ++ } ++ if(ldcnir) { ++ if( ldcnir & ITESER_BIT ) ++ cmx270_irq(IRQ_ITESER, regs); ++ } ++ } ++ ++ /* re-enable ITE interrupts */ ++ IT8152_INTC_PDCNIMR = pdcnimr; ++ IT8152_INTC_LDCNIMR = ldcnimr; ++} ++#else ++unsigned long it8152_base_address = CMX270_IT8152_VIRT; ++#endif ++ ++/* Map PCI companion and IDE/General Purpose CS statically */ ++static struct map_desc cmx270_io_desc[] __initdata = { ++ { ++ .virtual = CMX270_IDE104_VIRT, ++ .pfn = __phys_to_pfn(CMX270_IDE104_PHYS), ++ .length = PXA_CS_SIZE, ++ .type = MT_DEVICE ++ }, ++ { ++ .virtual = CMX270_IT8152_VIRT, ++ .pfn = __phys_to_pfn(CMX270_IT8152_PHYS), ++ .length = PXA_CS_SIZE, ++ .type = MT_DEVICE ++ }, ++}; ++ ++/*********************** Display definitions ****************************/ ++static int mtype=MTYPE_CRT640x480; ++static int mbpp=-1; ++ ++struct cmx270_display_info { ++ struct pxafb_mach_info fb_info; ++ char *display_name; ++}; ++ ++static struct __initdata cmx270_display_info cmx270_displays[] = { ++ [ MTYPE_STN320x240 ] = { ++ .fb_info = { ++ .pixclock = 76923, ++ .bpp = 8, ++ .xres = 320, ++ .yres = 240, ++ .hsync_len = 3, ++ .vsync_len = 2, ++ .left_margin = 3, ++ .upper_margin = 0, ++ .right_margin = 3, ++ .lower_margin = 0, ++ .sync = (FB_SYNC_HOR_HIGH_ACT | ++ FB_SYNC_VERT_HIGH_ACT), ++ .lccr0 = 0, ++ .lccr3 = (LCCR3_PixClkDiv(0x03) | ++ LCCR3_Acb(0xff) | ++ LCCR3_PCP), ++ .cmap_greyscale = 0, ++ .cmap_inverse = 0, ++ .cmap_static = 0, ++ }, ++ .display_name = "STN 320x240", ++ }, ++ [ MTYPE_TFT640x480 ] = { ++ .fb_info = { ++ .pixclock = 38461, ++ .bpp = 8, ++ .xres = 640, ++ .yres = 480, ++ .hsync_len = 60, ++ .vsync_len = 2, ++ .left_margin = 70, ++ .upper_margin = 10, ++ .right_margin = 70, ++ .lower_margin = 5, ++ .sync = 0, ++ .lccr0 = (LCCR0_PAS), ++ .lccr3 = (LCCR3_PixClkDiv(0x01) | ++ LCCR3_Acb(0xff) | ++ LCCR3_PCP), ++ .cmap_greyscale = 0, ++ .cmap_inverse = 0, ++ .cmap_static = 0, ++ }, ++ .display_name = "TFT 640x480", ++ }, ++ [ MTYPE_CRT640x480 ] = { ++ .fb_info = { ++ .pixclock = 38461, ++ .bpp = 8, ++ .xres = 640, ++ .yres = 480, ++ .hsync_len = 63, ++ .vsync_len = 2, ++ .left_margin = 81, ++ .upper_margin = 33, ++ .right_margin = 16, ++ .lower_margin = 10, ++ .sync = (FB_SYNC_HOR_HIGH_ACT | ++ FB_SYNC_VERT_HIGH_ACT), ++ .lccr0 = (LCCR0_PAS), ++ .lccr3 = (LCCR3_PixClkDiv(0x01) | ++ LCCR3_Acb(0xff)), ++ .cmap_greyscale = 0, ++ .cmap_inverse = 0, ++ .cmap_static = 0, ++ }, ++ .display_name = "CRT 640x480", ++ }, ++ [ MTYPE_CRT800x600 ] = { ++ .fb_info = { ++ .pixclock = 28846, ++ .bpp = 8, ++ .xres = 800, ++ .yres = 600, ++ .hsync_len = 63, ++ .vsync_len = 2, ++ .left_margin = 26, ++ .upper_margin = 21, ++ .right_margin = 26, ++ .lower_margin = 11, ++ .sync = (FB_SYNC_HOR_HIGH_ACT | ++ FB_SYNC_VERT_HIGH_ACT), ++ .lccr0 = (LCCR0_PAS), ++ .lccr3 = (LCCR3_PixClkDiv(0x02) | ++ LCCR3_Acb(0xff)), ++ .cmap_greyscale = 0, ++ .cmap_inverse = 0, ++ .cmap_static = 0, ++ }, ++ .display_name = "CRT 800x600", ++ }, ++ [ MTYPE_CRT1024x768 ] = { ++ .fb_info = { ++ .pixclock = 0, ++ .xres = 0, ++ .yres = 0, ++ }, ++ .display_name = "CRT 1024x768", ++ }, ++ [ MTYPE_USER_DEFINED ] = { ++ .fb_info = { ++ .pixclock = LCD_PIXCLOCK, ++ .bpp = LCD_BPP, ++ .xres = LCD_XRES, ++ .yres = LCD_YRES, ++ .hsync_len = LCD_HORIZONTAL_SYNC_PULSE_WIDTH, ++ .vsync_len = LCD_VERTICAL_SYNC_PULSE_WIDTH, ++ .left_margin = LCD_BEGIN_OF_LINE_WAIT_COUNT, ++ .upper_margin = LCD_BEGIN_FRAME_WAIT_COUNT, ++ .right_margin = LCD_END_OF_LINE_WAIT_COUNT, ++ .lower_margin = LCD_END_OF_FRAME_WAIT_COUNT, ++ .sync = LCD_SYNC, ++ .lccr0 = LCD_LCCR0, ++ .lccr3 = LCD_LCCR3, ++ .cmap_greyscale = CMAP_GREYSCALE, ++ .cmap_inverse = CMAP_INVERSE, ++ .cmap_static = CMAP_STATIC, ++ }, ++ .display_name = LCD_NAME, ++ }, ++ [ MTYPE_TFT320x240 ] = { ++ .fb_info = { ++ .pixclock = 134615, ++ .bpp = 16, ++ .xres = 320, ++ .yres = 240, ++ .hsync_len = 63, ++ .vsync_len = 7, ++ .left_margin = 75, ++ .upper_margin = 0, ++ .right_margin = 15, ++ .lower_margin = 15, ++ .sync = 0, ++ .lccr0 = (LCCR0_PAS), ++ .lccr3 = (LCCR3_PixClkDiv(0x06) | ++ LCCR3_Acb(0xff) | ++ LCCR3_PCP), ++ .cmap_greyscale = 0, ++ .cmap_inverse = 0, ++ .cmap_static = 0, ++ }, ++ .display_name = "TFT 320x240", ++ }, ++ [ MTYPE_STN640x480 ] = { ++ .fb_info = { ++ .pixclock = 57692, ++ .bpp = 8, ++ .xres = 640, ++ .yres = 480, ++ .hsync_len = 4, ++ .vsync_len = 2, ++ .left_margin = 10, ++ .upper_margin = 5, ++ .right_margin = 10, ++ .lower_margin = 5, ++ .sync = (FB_SYNC_HOR_HIGH_ACT | ++ FB_SYNC_VERT_HIGH_ACT), ++ .lccr0 = 0, ++ .lccr3 = (LCCR3_PixClkDiv(0x02) | ++ LCCR3_Acb(0xff)), ++ .cmap_greyscale = 0, ++ .cmap_inverse = 0, ++ .cmap_static = 0, ++ }, ++ .display_name = "STN 640x480", ++ }, ++}; ++ ++static int __init monitor_params(char *str) ++{ ++ mtype = simple_strtol(str, NULL, 0); ++ return 1; ++} ++ ++__setup("monitor=", monitor_params); ++ ++static int __init fb_bpp(char *str) ++{ ++ mbpp = simple_strtol(str, NULL, 0); ++ return 1; ++} ++ ++__setup("bpp=", fb_bpp); ++ ++/* PXA27x OHCI controller setup */ ++static int cmx270_ohci_init(struct device *dev) ++{ ++ /* Set the Power Control Polarity Low */ ++ UHCHR = (UHCHR | UHCHR_PCPL) & ++ ~(UHCHR_SSEP1 | UHCHR_SSEP2 | UHCHR_SSE); ++ ++ return 0; ++} ++ ++static struct pxaohci_platform_data cmx270_ohci_platform_data = { ++ .port_mode = PMM_PERPORT_MODE, ++ .init = cmx270_ohci_init, ++}; ++ ++#ifdef CONFIG_PM ++/* timeout for RTC wakeup */ ++unsigned int cmx270_suspend_timeout; ++ ++static ssize_t timeout_show(struct subsystem * subsys, char * buf) ++{ ++ char * s = buf; ++ ++ s += sprintf(s,"%d seconds\n", cmx270_suspend_timeout); ++ return (s - buf); ++} ++ ++static ssize_t timeout_store(struct subsystem * subsys, const char * buf, size_t n) ++{ ++ char *endp = 0; ++ int timeout; ++ ++ timeout = simple_strtoul(buf, &endp, 10); ++ if ( *endp && *endp != '\n') ++ return -EINVAL; ++ ++ cmx270_suspend_timeout = timeout; ++ return n; ++} ++ ++static struct subsys_attribute timeout_attr = { ++ .attr = { ++ .name = __stringify(timeout), ++ .mode = 0644, ++ }, ++ .show = timeout_show, ++ .store = timeout_store, ++}; ++ ++static struct attribute * g[] = { ++ &timeout_attr.attr, ++ NULL, ++}; ++ ++static struct attribute_group attr_group = { ++ .attrs = g, ++}; ++ ++extern struct subsystem power_subsys; ++static unsigned long sleep_save_ite[10]; ++static unsigned long sleep_save_msc[10]; ++ ++static int cmx270_suspend(struct sys_device *dev, pm_message_t state) ++{ ++#ifdef CONFIG_PCI ++ /* save ITE state */ ++ sleep_save_ite[0] = IT8152_INTC_PDCNIMR; ++ sleep_save_ite[1] = IT8152_INTC_LPCNIMR; ++ sleep_save_ite[2] = IT8152_INTC_LPNIAR; ++ ++ /* Clear ITE IRQ's */ ++ IT8152_INTC_PDCNIRR = 0; ++ IT8152_INTC_LPCNIRR = 0; ++#endif ++ ++ /* save MSC registers */ ++ sleep_save_msc[0] = MSC0; ++ sleep_save_msc[1] = MSC1; ++ sleep_save_msc[2] = MSC2; ++ ++ /* setup power saving mode registers */ ++ PCFR = 0x0; ++ PSLR = 0xff400000; ++ PMCR = 0x00000005; ++ PWER = 0x80000000; ++ PFER = 0x00000000; ++ PRER = 0x00000000; ++ PGSR0 = 0xC0018800; ++ PGSR1 = 0x004F0002; ++ PGSR2 = 0x6021C000; ++ PGSR3 = 0x00020000; ++ ++ if ( cmx270_suspend_timeout ) { ++ RTAR = RCNR + cmx270_suspend_timeout; ++ cmx270_suspend_timeout = 0; ++ } ++ ++ return 0; ++} ++ ++static int cmx270_resume(struct sys_device *dev) ++{ ++#ifdef CONFIG_PCI ++ /* restore IT8152 state */ ++ IT8152_INTC_PDCNIMR = sleep_save_ite[0]; ++ IT8152_INTC_LPCNIMR = sleep_save_ite[1]; ++ IT8152_INTC_LPNIAR = sleep_save_ite[2]; ++#endif ++ ++ /* restore MSC registers */ ++ MSC0 = sleep_save_msc[0]; ++ MSC1 = sleep_save_msc[1]; ++ MSC2 = sleep_save_msc[2]; ++ ++ return 0; ++} ++ ++static struct sysdev_class cmx270_pm_sysclass = { ++ set_kset_name("pm"), ++ .resume = cmx270_resume, ++ .suspend = cmx270_suspend, ++}; ++ ++static struct sys_device cmx270_pm_device = { ++ .cls = &cmx270_pm_sysclass, ++}; ++ ++static int __init cmx270_pm_init(void) ++{ ++ int error; ++ error = sysdev_class_register(&cmx270_pm_sysclass); ++ if (error == 0) ++ error = sysdev_register(&cmx270_pm_device); ++ ++ error = sysfs_create_group(&power_subsys.kset.kobj,&attr_group); ++ return error; ++} ++#else ++static int __init cmx270_pm_init(void) { return 0; } ++#endif ++ ++/* SA1111 compatibiliy 8 bit read register needed for proper function ++ of ITE8152 UART */ ++#define MEMC_SA1111 __REG(0x48000064) ++ ++static void __init cmx270_init(void) ++{ ++ /* set display timings for VGA 640x480 by default */ ++ struct cmx270_display_info *tfbi = &cmx270_displays[2]; ++ ++ MEMC_SA1111 = 0x3c; ++ ++ cmx270_pm_init(); ++ ++ if ( mtype >= 0 && mtype < ARRAY_SIZE(cmx270_displays) ) ++ tfbi = &cmx270_displays[mtype]; ++ ++ /* use default instead of unsupported displays */ ++ if ( tfbi->fb_info.pixclock == 0 && ++ tfbi->fb_info.xres == 0 && ++ tfbi->fb_info.yres == 0 ) { ++ printk(KERN_WARNING "CM-X270 does not support %s display\n", cmx270_displays[mtype].display_name); ++ tfbi = &cmx270_displays[2]; ++ } ++ ++ /* setup color depth */ ++ if( mtype == MTYPE_USER_DEFINED ) { ++ mbpp = tfbi->fb_info.bpp; ++ } ++ if( mbpp > 0 ) { ++ if( (mbpp!=1) && (mbpp!=2) && (mbpp!=4) && ++ (mbpp!=8) && (mbpp!=16)) { ++ printk(KERN_WARNING "Illegal BPP value " ++ "supplied, leaving default\n"); ++ mbpp = 8; ++ } ++ } ++ else mbpp = 8; ++ tfbi->fb_info.bpp = mbpp; ++ ++ printk(KERN_INFO "Running a %s display with %d bits per pixel\n", ++ tfbi->display_name, tfbi->fb_info.bpp); ++ set_pxa_fb_info(&tfbi->fb_info); ++ ++#ifdef CONFIG_PCI ++ /* setup ITE8152 UART base addresses */ ++ ite_uart_port[0].membase = (void *)&IT8152_UART_BASE; ++ ite_uart_port[0].mapbase = IT8152_UART_BASE; ++#endif ++ ++ /* register CM-X270 platform devices */ ++ platform_add_devices(platform_devices, ARRAY_SIZE(platform_devices)); ++ ++ pxa_set_ohci_info(&cmx270_ohci_platform_data); ++ ++ /* This enables the STUART */ ++ pxa_gpio_mode(GPIO46_STRXD_MD); ++ pxa_gpio_mode(GPIO47_STTXD_MD); ++ ++ /* This enables the BTUART */ ++ pxa_gpio_mode(GPIO42_BTRXD_MD); ++ pxa_gpio_mode(GPIO43_BTTXD_MD); ++ pxa_gpio_mode(GPIO44_BTCTS_MD); ++ pxa_gpio_mode(GPIO45_BTRTS_MD); ++} ++ ++#ifdef CONFIG_PCI ++static void cmx270_mask_irq(unsigned int irq) ++{ ++ switch(irq) { ++ case IT8152_IRQ(0): ++ IT8152_INTC_PDCNIMR |= PCISERR_BIT; ++ break; ++ case IT8152_IRQ(1): ++ IT8152_INTC_PDCNIMR |= H2PTADR_BIT; ++ break; ++ case IT8152_IRQ(2): ++ IT8152_INTC_PDCNIMR |= H2PMAR_BIT; ++ break; ++ case IT8152_IRQ(3): ++ IT8152_INTC_PDCNIMR |= PCI_INTA_BIT; ++ break; ++ case IT8152_IRQ(4): ++ IT8152_INTC_PDCNIMR |= PCI_INTB_BIT; ++ break; ++ case IT8152_IRQ(5): ++ IT8152_INTC_PDCNIMR |= PCI_INTC_BIT; ++ break; ++ case IT8152_IRQ(6): ++ IT8152_INTC_PDCNIMR |= PCI_INTD_BIT; ++ break; ++ case IT8152_IRQ(7): ++ IT8152_INTC_PDCNIMR |= USB_INT_BIT; ++ break; ++ case IT8152_IRQ(9): ++ IT8152_INTC_PDCNIMR |= CDMA_INT_BIT; ++ break; ++ case IT8152_IRQ(10): ++ IT8152_INTC_LDCNIMR |= ITESER_BIT; ++ break; ++ } ++} ++ ++static void cmx270_unmask_irq(unsigned int irq) ++{ ++ switch(irq) { ++ case IT8152_IRQ(0): ++ IT8152_INTC_PDCNIMR &= (~PCISERR_BIT); ++ break; ++ case IT8152_IRQ(1): ++ IT8152_INTC_PDCNIMR &= (~H2PTADR_BIT); ++ break; ++ case IT8152_IRQ(2): ++ IT8152_INTC_PDCNIMR &= (~H2PMAR_BIT); ++ break; ++ case IT8152_IRQ(3): ++ IT8152_INTC_PDCNIMR &= (~PCI_INTA_BIT); ++ break; ++ case IT8152_IRQ(4): ++ IT8152_INTC_PDCNIMR &= (~PCI_INTB_BIT); ++ break; ++ case IT8152_IRQ(5): ++ IT8152_INTC_PDCNIMR &= (~PCI_INTC_BIT); ++ break; ++ case IT8152_IRQ(6): ++ IT8152_INTC_PDCNIMR &= (~PCI_INTD_BIT); ++ break; ++ case IT8152_IRQ(7): ++ IT8152_INTC_PDCNIMR &= (~USB_INT_BIT); ++ break; ++ case IT8152_IRQ(9): ++ IT8152_INTC_PDCNIMR &= (~CDMA_INT_BIT); ++ break; ++ case IT8152_IRQ(10): ++ IT8152_INTC_LDCNIMR &= (~ITESER_BIT); ++ break; ++ } ++} ++ ++static struct irqchip cmx270_irq_chip = { ++ .ack = cmx270_mask_irq, ++ .mask = cmx270_mask_irq, ++ .unmask = cmx270_unmask_irq, ++}; ++#endif ++ ++static void __init cmx270_init_irq(void) ++{ ++ int irq; ++ ++ pxa_init_irq(); ++ ++ /* LED and NAND GPIOs should not be probed for IRQ */ ++ irq_desc[IRQ_GPIO(11)].probe_ok = 0; ++ irq_desc[IRQ_GPIO(89)].probe_ok = 0; ++ irq_desc[IRQ_GPIO(93)].probe_ok = 0; ++ irq_desc[IRQ_GPIO(94)].probe_ok = 0; ++ ++ IT8152_INTC_PDCNIMR = 0xffff; ++ ++#ifdef CONFIG_PCI ++ /* Disable and clear IRQ's for ITE8152 */ ++ IT8152_INTC_PDCNIMR = 0xffff; ++ IT8152_INTC_PDCNIRR = 0; ++ IT8152_INTC_LPCNIMR = 0xffff; ++ IT8152_INTC_LPCNIRR = 0; ++ IT8152_INTC_LDCNIMR = 0xffff; ++ IT8152_INTC_LDCNIRR = 0; ++ ++ /* Set IT8152 serial port IRQ as active high*/ ++ IT8152_INTC_LDNIAR |= ITESER_BIT; ++ ++ for(irq = IT8152_IRQ(0); irq <= IT8152_IRQ_MAX; irq++) { ++ set_irq_chip(irq, &cmx270_irq_chip); ++ set_irq_handler(irq, do_level_IRQ); ++ set_irq_flags(irq, IRQF_VALID | IRQF_PROBE); ++ } ++ ++ /* INTC signal from IT8152 is connected to GPIO0 */ ++ pxa_gpio_mode(IRQ_GPIO_IT8152_IRQ); ++ set_irq_chained_handler(IRQ_GPIO_IT8152_IRQ, cmx270_irq_demux); ++ set_irq_type(IRQ_GPIO_IT8152_IRQ, IRQT_RISING); ++#endif ++ ++ /* Setup interrupt for dm9000 */ ++ pxa_gpio_mode(IRQ_TO_GPIO(CMX270_ETHIRQ)); ++ set_irq_type(CMX270_ETHIRQ, IRQT_RISING); ++ ++ /* Setup interrupt for 2700G */ ++ pxa_gpio_mode(IRQ_TO_GPIO(CMX270_GFXIRQ)); ++ set_irq_type(CMX270_GFXIRQ, IRQT_FALLING); ++} ++ ++static void __init cmx270_map_io(void) ++{ ++ pxa_map_io(); ++ iotable_init(cmx270_io_desc, ARRAY_SIZE(cmx270_io_desc)); ++} ++ ++ ++MACHINE_START(ARMCORE, "Compulab CM-x270") ++ .boot_params = 0xa0000100, ++ .phys_io = 0x40000000, ++ .io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc, ++ .map_io = cmx270_map_io, ++ .init_irq = cmx270_init_irq, ++ .timer = &pxa_timer, ++ .init_machine = cmx270_init, ++MACHINE_END +diff --git a/arch/arm/mach-pxa/it8152.c b/arch/arm/mach-pxa/it8152.c +new file mode 100644 +index 0000000..91bb49c +--- /dev/null ++++ b/arch/arm/mach-pxa/it8152.c +@@ -0,0 +1,248 @@ ++/* ++ * arch/arm/common/it8152.c: PCI functions for IT8152 ++ * ++ * Compulab Ltd, 2002-2006 ++ * ++ * The DMA bouncing is taken from arch/arm/mach-ixp4xx/common-pci.c ++ * (see this file for respective copyrights) ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 as ++ * published by the Free Software Foundation. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++ ++#include ++#include ++#include ++#include ++#include ++ ++#define MAX_SLOTS 21 ++ ++static unsigned long ++it8152_pci_dev_base_address(struct pci_bus *bus, unsigned int devfn) ++{ ++ unsigned long addr = 0; ++ ++ if (bus->number == 0) { ++ if (devfn < PCI_DEVFN(MAX_SLOTS, 0)) ++ addr = (devfn << 8); ++ } else ++ addr = (bus->number << 16) | (devfn << 8); ++ ++ return addr; ++} ++ ++static int ++it8152_pci_read_config(struct pci_bus *bus, unsigned int devfn, int where, ++ int size, u32 *value) ++{ ++ unsigned long addr = it8152_pci_dev_base_address(bus, devfn); ++ u32 v; ++ int shift; ++ ++#ifdef CONFIG_MACH_ARMCORE ++ if(devfn!=0) IT8152_GPIO_GPLR=0x00; ++#endif ++ shift = (where & 3); ++ ++ IT8152_PCI_CFG_ADDR = (addr + where); ++ v = (IT8152_PCI_CFG_DATA >> (8 * (shift))); ++ ++ *value = v; ++ ++#ifdef CONFIG_MACH_ARMCORE ++ if(devfn!=0) IT8152_GPIO_GPLR=0x20; ++#endif ++ ++ return PCIBIOS_SUCCESSFUL; ++} ++ ++ ++static int ++it8152_pci_write_config(struct pci_bus *bus, unsigned int devfn, int where, ++ int size, u32 value) ++{ ++ unsigned long addr = it8152_pci_dev_base_address(bus, devfn); ++ u32 v, vtemp, mask=0; ++ int shift; ++ ++#ifdef CONFIG_MACH_ARMCORE ++ if(devfn!=0) IT8152_GPIO_GPLR=0x00; ++#endif ++ ++ if(size==1) mask=0xff; ++ if(size==2) mask=0xffff; ++ ++ shift = (where & 3); ++ ++ IT8152_PCI_CFG_ADDR = addr + where; ++ vtemp = IT8152_PCI_CFG_DATA; ++ ++ if(mask) vtemp &= ~(mask << (8 * shift)); ++ else vtemp = 0; ++ ++ v = (value << (8 * shift)); ++ IT8152_PCI_CFG_ADDR = addr + where; ++ IT8152_PCI_CFG_DATA = (v | vtemp); ++ ++#ifdef CONFIG_MACH_ARMCORE ++ if(devfn!=0) IT8152_GPIO_GPLR=0x20; ++#endif ++ ++ return PCIBIOS_SUCCESSFUL; ++} ++ ++static struct pci_ops it8152_ops = { ++ .read = it8152_pci_read_config, ++ .write = it8152_pci_write_config, ++}; ++ ++static struct resource it8152_io = { ++ .name = "IT8152 PCI I/O region", ++ .flags = IORESOURCE_IO, ++}; ++ ++static struct resource it8152_mem1 = { ++ .name = "First IT8152 PCI memory region", ++ .start = 0x10000000, ++ .end = 0x13e00000, ++ .flags = IORESOURCE_MEM, ++}; ++ ++/* ++ * The following functions are needed for DMA bouncing. ++ * ITE8152 chip can addrees up to 64MByte, so all the devices ++ * connected to ITE8152 (PCI and USB) should have limited DMA window ++ */ ++ ++/* ++ * Setup DMA mask to 64MB on devices connected to ITE8152. Ignore all ++ * other devices. ++ */ ++static int it8152_pci_platform_notify(struct device *dev) ++{ ++ if ( dev->bus == &pci_bus_type ) { ++ if ( dev->dma_mask ) ++ *dev->dma_mask = SZ_64M - 1; ++ dev->coherent_dma_mask = SZ_64M - 1; ++ dmabounce_register_dev(dev, 2048, 4096); ++ } ++ return 0; ++} ++ ++static int it8152_pci_platform_notify_remove(struct device *dev) ++{ ++ if ( dev->bus == &pci_bus_type ) { ++ dmabounce_unregister_dev(dev); ++ } ++ return 0; ++} ++ ++int dma_needs_bounce(struct device *dev, dma_addr_t dma_addr, size_t size) ++{ ++ dev_dbg(dev, "%s: dma_addr %08x, size %08x\n", ++ __FUNCTION__, dma_addr, size); ++ return (dev->bus == &pci_bus_type ) && ++ ((dma_addr + size - PHYS_OFFSET) >= SZ_64M); ++} ++ ++/* ++ * Only first 64MB of memory can be accessed via PCI. ++ * We use GFP_DMA to allocate safe buffers to do map/unmap. ++ * This is really ugly and we need a better way of specifying ++ * DMA-capable regions of memory. ++ */ ++void __init it8152_adjust_zones(int node, unsigned long *zone_size, ++ unsigned long *zhole_size) ++{ ++ unsigned int sz = SZ_64M >> PAGE_SHIFT; ++ ++ /* ++ * Only adjust if > 64M on current system ++ */ ++ if (node || (zone_size[0] <= sz)) ++ return; ++ ++ zone_size[1] = zone_size[0] - sz; ++ zone_size[0] = sz; ++ zhole_size[1] = zhole_size[0]; ++ zhole_size[0] = 0; ++} ++ ++/* ++ * We override these so we properly do dmabounce otherwise drivers ++ * are able to set the dma_mask to 0xffffffff and we can no longer ++ * trap bounces. :( ++ * ++ * We just return true on everyhing except for < 64MB in which case ++ * we will fail miseralby and die since we can't handle that case. ++ */ ++int ++pci_set_dma_mask(struct pci_dev *dev, u64 mask) ++{ ++ if (mask >= SZ_64M - 1 ) ++ return 0; ++ ++ return -EIO; ++} ++ ++int ++pci_set_consistent_dma_mask(struct pci_dev *dev, u64 mask) ++{ ++ if (mask >= SZ_64M - 1 ) ++ return 0; ++ ++ return -EIO; ++} ++ ++EXPORT_SYMBOL(pci_set_dma_mask); ++EXPORT_SYMBOL(pci_set_consistent_dma_mask); ++ ++ ++int __init it8152_pci_setup(int nr, struct pci_sys_data *sys) ++{ ++ it8152_io.start = IT8152_IO_BASE + 0x12000; ++ it8152_io.end = IT8152_IO_BASE + 0x100000; ++ ++ if (request_resource(&ioport_resource, &it8152_io)) { ++ printk(KERN_ERR "PCI: unable to allocate IO region\n"); ++ return -EBUSY; ++ } ++ if (request_resource(&iomem_resource, &it8152_mem1)) { ++ printk(KERN_ERR "PCI: unable to allocate memory region\n"); ++ return -EBUSY; ++ } ++ ++ sys->resource[0] = &it8152_io; ++ sys->resource[1] = &it8152_mem1; ++ ++ if (platform_notify || platform_notify_remove) { ++ printk(KERN_ERR "PCI: Can't use platform_notify\n"); ++ return -EBUSY; ++ } ++ ++ platform_notify = it8152_pci_platform_notify; ++ platform_notify_remove = it8152_pci_platform_notify_remove; ++ ++ return 1; ++} ++ ++ ++struct pci_bus * __init it8152_pci_scan_bus(int nr, struct pci_sys_data *sys) ++{ ++ return pci_scan_bus(nr, &it8152_ops, sys); ++} ++ +diff --git a/arch/arm/mach-pxa/leds-cm-x270.c b/arch/arm/mach-pxa/leds-cm-x270.c +new file mode 100644 +index 0000000..5402b69 +--- /dev/null ++++ b/arch/arm/mach-pxa/leds-cm-x270.c +@@ -0,0 +1,134 @@ ++/* ++ * linux/arch/arm/mach-pxa/leds-cm-x270.c ++ * ++ * Compulab Ltd., 2003 ++ * ++ * Original (leds-footbridge.c) by Russell King ++ * ++ * Macros for actual LED manipulation should be in machine specific ++ * files in this 'mach' directory. ++ */ ++ ++ ++#include ++#include ++#include ++ ++#include ++#include ++#include ++ ++#include ++#include ++ ++#include "leds.h" ++ ++#define LED_STATE_ENABLED 1 ++#define LED_STATE_CLAIMED 2 ++ ++#define RED_LED_ON 1 ++#define GREEN_LED_ON 2 ++ ++static unsigned int led_state; ++static unsigned int hw_led_state; ++ ++void armcore_leds_event(led_event_t evt) ++{ ++ unsigned long flags; ++ ++ local_irq_save(flags); ++ ++ switch (evt) { ++ case led_start: ++ hw_led_state = GREEN_LED_ON | RED_LED_ON; ++ led_state = LED_STATE_ENABLED; ++ break; ++ ++ case led_stop: ++ led_state &= ~LED_STATE_ENABLED; ++ break; ++ ++ case led_claim: ++ led_state |= LED_STATE_CLAIMED; ++ hw_led_state = GREEN_LED_ON | RED_LED_ON; ++ break; ++ ++ case led_release: ++ led_state &= ~LED_STATE_CLAIMED; ++ hw_led_state = GREEN_LED_ON | RED_LED_ON; ++ break; ++ ++#ifdef CONFIG_LEDS_TIMER ++ case led_timer: ++ if (!(led_state & LED_STATE_CLAIMED)) ++ hw_led_state ^= GREEN_LED_ON; ++ break; ++#endif ++ ++#ifdef CONFIG_LEDS_CPU ++ case led_idle_start: ++ if (!(led_state & LED_STATE_CLAIMED)) ++ hw_led_state &= ~RED_LED_ON; ++ break; ++ ++ case led_idle_end: ++ if (!(led_state & LED_STATE_CLAIMED)) ++ hw_led_state |= RED_LED_ON; ++ break; ++#endif ++ ++ case led_halted: ++ break; ++ ++ case led_green_on: ++ if (led_state & LED_STATE_CLAIMED) ++ hw_led_state &= ~GREEN_LED_ON; ++ break; ++ ++ case led_green_off: ++ if (led_state & LED_STATE_CLAIMED) ++ hw_led_state |= GREEN_LED_ON; ++ break; ++ ++ case led_amber_on: ++ break; ++ ++ case led_amber_off: ++ break; ++ ++ case led_red_on: ++ if (led_state & LED_STATE_CLAIMED) ++ hw_led_state &= ~RED_LED_ON; ++ break; ++ ++ case led_red_off: ++ if (led_state & LED_STATE_CLAIMED) ++ hw_led_state |= RED_LED_ON; ++ break; ++ ++ default: ++ break; ++ } ++ ++ if (led_state & LED_STATE_ENABLED) ++ { ++ if(hw_led_state & RED_LED_ON) { ++ CMX270_RED_ON(); ++// printk("Red on\n"); ++ } ++ else { ++// printk("Red off\n"); ++ CMX270_RED_OFF(); ++ } ++ if(hw_led_state & GREEN_LED_ON) { ++// printk("Green on\n"); ++ CMX270_GREEN_ON(); ++ } ++ else { ++// printk("Green off\n"); ++ CMX270_GREEN_OFF(); ++ } ++ } ++ ++ local_irq_restore(flags); ++} +diff --git a/arch/arm/mach-pxa/leds.c b/arch/arm/mach-pxa/leds.c +index bbe4d5f..a27d027 100644 +--- a/arch/arm/mach-pxa/leds.c ++++ b/arch/arm/mach-pxa/leds.c +@@ -24,6 +24,8 @@ pxa_leds_init(void) + leds_event = mainstone_leds_event; + if (machine_is_pxa_idp()) + leds_event = idp_leds_event; ++ if (machine_is_armcore()) ++ leds_event = armcore_leds_event; + + leds_event(led_start); + return 0; +diff --git a/arch/arm/mach-pxa/leds.h b/arch/arm/mach-pxa/leds.h +index d98f6e9..0dcc346 100644 +--- a/arch/arm/mach-pxa/leds.h ++++ b/arch/arm/mach-pxa/leds.h +@@ -10,3 +10,4 @@ + extern void idp_leds_event(led_event_t evt); + extern void lubbock_leds_event(led_event_t evt); + extern void mainstone_leds_event(led_event_t evt); ++extern void armcore_leds_event(led_event_t evt); +diff --git a/arch/arm/mach-pxa/pxa27x.c b/arch/arm/mach-pxa/pxa27x.c +index 3baa708..823c32d 100644 +--- a/arch/arm/mach-pxa/pxa27x.c ++++ b/arch/arm/mach-pxa/pxa27x.c +@@ -140,10 +140,12 @@ void pxa_cpu_pm_enter(suspend_state_t st + extern void pxa_cpu_suspend(unsigned int); + extern void pxa_cpu_resume(void); + ++#ifndef CONFIG_MACH_ARMCORE + if (state == PM_SUSPEND_STANDBY) + CKEN = CKEN22_MEMC | CKEN9_OSTIMER | CKEN16_LCD |CKEN0_PWM0; + else + CKEN = CKEN22_MEMC | CKEN9_OSTIMER; ++#endif + + /* ensure voltage-change sequencer not initiated, which hangs */ + PCFR &= ~PCFR_FVC; +@@ -158,7 +160,11 @@ void pxa_cpu_pm_enter(suspend_state_t st + case PM_SUSPEND_MEM: + /* set resume return address */ + PSPR = virt_to_phys(pxa_cpu_resume); ++#ifdef CONFIG_MACH_ARMCORE ++ pxa_cpu_suspend(PWRMODE_DEEPSLEEP); ++#else + pxa_cpu_suspend(PWRMODE_SLEEP); ++#endif + break; + } + } +diff --git a/drivers/block/Kconfig b/drivers/block/Kconfig +index 8b13316..8ffaad0 100644 +--- a/drivers/block/Kconfig ++++ b/drivers/block/Kconfig +@@ -453,4 +453,9 @@ config ATA_OVER_ETH + This driver provides Support for ATA over Ethernet block + devices like the Coraid EtherDrive (R) Storage Blade. + ++config ARMCORE_FLASH ++ tristate "ARMCORE flash drivers" ++ depends on MACH_ARMCORE ++ source "drivers/block/cl_flash/Kconfig" ++ + endmenu +diff --git a/drivers/block/Makefile b/drivers/block/Makefile +index 3ec1f8d..ebeb4c6 100644 +--- a/drivers/block/Makefile ++++ b/drivers/block/Makefile +@@ -31,3 +31,4 @@ obj-$(CONFIG_VIODASD) += viodasd.o + obj-$(CONFIG_BLK_DEV_SX8) += sx8.o + obj-$(CONFIG_BLK_DEV_UB) += ub.o + ++obj-$(CONFIG_ARMCORE_FLASH) += cl_flash/ +diff --git a/drivers/block/cl_flash/CL_Logic.h b/drivers/block/cl_flash/CL_Logic.h +new file mode 100644 +index 0000000..fe3e8d7 +--- /dev/null ++++ b/drivers/block/cl_flash/CL_Logic.h +@@ -0,0 +1,245 @@ ++/* Module: CL_Logic.h ++ Author: Vova Lifliand ++ Description: Controls Nand flash management logic ++ Notes: ++*/ ++ ++#ifndef __CL_LOGIC__ ++#define __CL_LOGIC__ ++/*#define CL_NAND_BIG_DELAYS*/ ++#if defined(FLASH_PLATFORM_LINUX) || defined(FLASH_PLATFORM_ARMonitor) ++/* Structure packaging */ ++ #define PACKAGE __attribute__ ((packed,aligned(1))) ++ #define CL_ST static ++#else ++ #define PACKAGE ++ #define CL_ST ++#endif ++ #define FAR ++ #define far ++/* NOR Flash management constants */ ++#define CL_NOR_FLASH_PAGE_SIZE 512 /* bytes */ ++ ++#ifdef FLASH_PLATFORM_DOS ++ #define cl_error_log(x,...){} ++#endif /* MS-DOS */ ++/* Nand Flash management constants */ ++ ++/* Page size must not be changed because this value is also used for ++ page size of Nand flash */ ++/*#define CL_FLASH_PAGE_SIZE 512 // bytes */ ++#define CL_FLASH_MAXIMUM_PAGE_SIZE 2048/* bytes */ ++#define CL_FLASH_MINIMAL_SECTOR_SIZE 512 /* Sectors can't be less than 512 bytes */ ++/*#define CL_FLASH_SPARE_AREA_SIZE 16 // bytes */ ++/*#define CL_FLASH_MAXIMUM_SPARE_AREA_SIZE 128 bytes - twice the needed for biggest ++ flash today 2004/05 */ ++#define CL_FLASH_MAXIMUM_SPARE_AREA_SIZE 128 /*Stingy with space...*/ ++ ++/* Maximum blocks number in flash - adjust according to maximum flash size */ ++#define CL_MAX_BLKS_NUMBER 8192 /* good for 128MB flash */ ++ /* Good up to 512 MB flash, if 64kb is the smallest block */ ++/* Number of pages in Nand flash block */ ++/* #define CL_FLASH_PAGES_PER_NAND_BLK 32 */ ++/* Maximum Number of pages in Nand flash block */ ++#define CL_FLASH_MAXIMUM_PAGES_PER_NAND_BLK 128 /* 32 */ /* Can't be more than 255 ++ to fit in unsigned char arrays*/ ++/* Number of pages to make free */ ++#define CL_FLASH_FREE_PAGE_PER_BLK 1 ++/* Usable pages per 16 KB Nand flash block */ ++/*#define CL_FLASH_USE_PAGE_PER_BLK (CL_FLASH_PAGES_PER_NAND_BLK - CL_FLASH_FREE_PAGE_PER_BLK)*/ ++#define CL_FLASH_USE_PAGE_PER_BLK (flogic->nand->pages_per_block - CL_FLASH_FREE_PAGE_PER_BLK) ++/* Number of logical to physical page translation tables stored in memory ++ Each table size is ~40 bytes */ ++#define CL_LTF_PAGE_TBLS 30 ++/* Always leave a number of blocks unused - just for sure */ ++#define CL_EXTRA_SPARE_BLKS 10 ++/* Define maximum number of different blocks with cached pages */ ++#define CL_MAX_CACHED_BLKS 4 ++/* Number of erases per one launching of anti wearing procedure */ ++#define CL_ERASE_PER_ANTI_WEARING 1000 ++ ++ ++#define CLBYTEPTR unsigned char far* ++ ++ ++/* Flash mapping and accessing interface */ ++typedef struct PACKAGE cl_nand_map_if_t ++{ ++ /* Destroy function must free all allocated resources (such as virtual memory) */ ++ void (*init) (void); ++ void (*destroy) (void); ++ /* Chip select operation. When on = 1: chip select, on = 0: disable chip select */ ++ /* need_auto_operation - Whe the ON is false, the pin is expected to pulse in accordance ++ with bus transactions. This function exists on x86, but not on ARM */ ++ void (*chip_select) (int on, int need_auto_operation); ++ /* Reading from flash (HW read access, not actual data reading) */ ++ unsigned char (*readb) (unsigned char offset); ++ /* Writing to flash (HW write access, not actual data writing) */ ++ void (*writeb) (unsigned char offset, unsigned char data); ++ /* Reads block from flash: reads data from address 0 while incrementing data pointer */ ++ void (*blockread) (CLBYTEPTR data, int count); ++ /* Writes block to flash: writes data to address 0 while incrementing data pointer */ ++ void (*blockwrite) ( CLBYTEPTR data, int count); ++ /* Turns on/off activity indication leds */ ++ void (*activity_leds) (short operation, short reclaim); ++ /* Performs specified delay (parameter in microsecond units) */ ++ int (*sleep) (unsigned long microseconds); ++ /* Wait for completion using R/B line */ ++ /* Use microseconds, if R/B line not implemented */ ++ int (*rbwait) (unsigned long microseconds); ++} cl_nand_map_if; ++ ++ ++/* Internal flash logic structure */ ++typedef struct cl_logic_t far*cl_logic; ++ ++ ++/* Parameter retrive enum */ ++typedef enum ++{ ++ CL_FLASH_TOTAL_SIZE, /* Total size of the flash in bytes */ ++ CL_FLASH_HEADS_NUM, /* Number of heads */ ++ CL_FLASH_SECTOR_SIZE = 512, /* Sector size (in bytes) =512 - is legacy for ARMonitor only*/ ++ CL_FLASH_SECTORS_NUM, /* Number of sectors per tracks */ ++ CL_FLASH_CYLINDERS_NUM, /* Number of cylinders */ ++ CL_FLASH_PAGE_SIZE, /* Size of the page without spare area */ ++ CL_FLASH_READ_PAGE_CNT, /* Read page operations count */ ++ CL_FLASH_WRITE_PAGE_CNT, /* Write page operations count */ ++ CL_FLASH_RECLAIM_CNT, /* Reclaim block count */ ++ CL_FLASH_BURSTS_NUM, /* Bursts of length 'var' numbers */ ++ CL_FLASH_ERASE_CNT, /* Erase cnt of block specified by 'var' */ ++ CL_FLASH_BAD_BLOCK_CNT, ++} PACKAGE cl_logic_param; ++ ++/* Direct access type enum */ ++typedef enum ++{ ++ CL_FLASH_READ_PAGE, ++ CL_FLASH_READ_SPARE_AREA, ++ CL_FLASH_READ_BLK_SPARES, /* All spare areas of specified block */ ++ CL_FLASH_WRITE_PAGE, ++ CL_FLASH_WRITE_SPARE_AREA, ++ CL_FLASH_ERASE_BLOCK /* Data ignored */ ++} PACKAGE cl_nand_direct_access_type; ++ ++/* memory access type enum */ ++typedef enum //Memory areas usage is dscribed in separate document. ++{ ++ CL_FLOGIC = 0, ++ CL_NAND, ++ CL_CACHE, ++ CL_CACHE_ORDERED_ARRAY, ++ CL_SP_AREA, ++ CL_SP_AREA_2, ++ CL_SP_AREA_3, ++ CL_PAGE, ++ CL_CACHE_REF ++} PACKAGE cl_memory_region_name; ++ ++#define NUMBER_OF_MEMORY_REGIONS 9 ++ ++ ++typedef enum ++{ ++ CL_FIRST_ALLOCATION_STAGE, ++ CL_SECOND_ALLOCATION_STAGE ++}PACKAGE cl_memory_allocation_stages; ++ ++typedef struct cl_memory_pointer_type ++{ ++ void far* pMemory; ++ char IN_USE; ++} PACKAGE cl_memory_pointer; ++ ++void far* cl_memory_request (cl_memory_region_name mem_name); ++ ++void cl_memory_return (cl_memory_region_name mem_name); ++ ++/* Creates flash logic object and attaches it to specified HW nand flash. ++ cache_size is max. number of pages, the cache can hold. ++ The flash is formatted prior initialization if format != 0. ++ When formatting reseved blocks and bad are not erased. */ ++cl_logic cl_logic_create (cl_nand_map_if* nand_if, long cache_size, int format, unsigned short sector_size); ++ ++/* Removes flash logic object and frees all allocated resources. */ ++void cl_logic_free (cl_logic flogic); ++ ++/* Parameters retrival function. */ ++long cl_logic_get_param (cl_logic flogic, cl_logic_param prm, long var); ++ ++/* Read page command. */ ++int cl_logic_read_page (cl_logic flogic, long fs_sectn, ++ CLBYTEPTR sector_data); ++ ++/* Write page command. */ ++int cl_logic_write_page (cl_logic flogic, long fs_pagen, ++ CLBYTEPTR page_data); ++ ++/* Flushes too old cache. If force_one_flush is TRUE, at least one ++ cached block is flushed. */ ++void cl_logic_on_idle (cl_logic flogic, int force_one_flush); ++ ++/* Flushes all cached data to disk. */ ++void cl_logic_sync (cl_logic flogic); ++ ++/* Direct accessing commands */ ++int cl_logic_direct_access (cl_logic flogic, cl_nand_direct_access_type type, ++ unsigned short block, unsigned char page, CLBYTEPTR data); ++ ++ ++/* NOR Flash Disk Driver */ ++ ++/* The header describes block information */ ++typedef struct ++{ ++ unsigned short Signature; /* 0x1998 for initialized blocks */ ++ unsigned short State; ++ unsigned short EraseCounter; ++ unsigned short PageIndex[128]; ++ unsigned short Unused[10]; ++ unsigned short BlockReserved; /* 0xFFFF - usable block, 0 - reserved block */ ++} PACKAGE cl_nor_block_header; ++ ++/* Abstract class for flash access */ ++typedef struct ++{ ++ /* Constructor */ ++ void (*Constructor)(void); ++ /* Destructor */ ++ void (*Destructor)(void); ++ /* Define flash access functions */ ++ /* Returns usable size */ ++ unsigned long (*GetSize)(void); ++ /* Remaps or unmaps MMS windows, allocated by flash */ ++ void (*EnableFlashMap)(int EnableFlag); ++ /* Returns number of usable pages, 512 bytes each. */ ++ /* Doesn't include first page that is used for header - signature, state . . . */ ++ int (*GetPagesPerBlock)(void); ++ /* Header */ ++ int (*ReadHeader)(unsigned short BlockN, cl_nor_block_header* Header); ++ /* The PageNum == 0 is first data page and not the header. Max. value of PageNum */ ++ /* is GetBlockSize() / BytesPerPage - 1 (min. is 0) */ ++ int (*ReadPage)(unsigned short BlockN, unsigned char PageNum, CLBYTEPTR DestBuff); ++ int (*SetBlockState) (unsigned short BlockN, unsigned short Signature, ++ unsigned short State, unsigned short Reserved); ++ /* Sets logical page index to zero - invalidates page. PageN is like in WritePage */ ++ int (*InvalidatePage)(unsigned short BlockN, unsigned char PageN); ++ /* BlockN and PageN - destination location, where PageN doesn't include header */ ++ /* information (PageN = 0 means first logical page and it's seconds physical page). */ ++ /* PageIndex is physical page number for further identification (by ReadHeader) */ ++ int (*WritePage)(unsigned short BlockN, unsigned char PageN, ++ const CLBYTEPTR PageData, unsigned short PageIndex); ++ int (*EraseBlock)(unsigned short BlockN); ++} PACKAGE cl_nor_flash_access; ++ ++/* Define flash access functions */ ++int cl_nor_init_flash (void); ++int cl_nor_free_mem (void); ++int cl_nor_format_flash (int (*ProgressCallback)(int Percentage)); ++int cl_nor_write_page (int PageIndex, CLBYTEPTR Data); ++int cl_nor_read_page (int PageIndex, CLBYTEPTR Data); ++int cl_nor_get_disk_param (unsigned long* TotalPage, unsigned long* BytesPerPage, ++ unsigned long* Cylinders, unsigned long* PagesPerTrk, ++ unsigned long* Heads); ++#endif /* __CL_LOGIC__ */ ++ +diff --git a/drivers/block/cl_flash/Kconfig b/drivers/block/cl_flash/Kconfig +new file mode 100644 +index 0000000..60aa80d +--- /dev/null ++++ b/drivers/block/cl_flash/Kconfig +@@ -0,0 +1,11 @@ ++# ++# Block device driver configuration ++# ++ ++config ARMCORE_NOR ++ bool "CompuLab NOR flash driver" ++ depends on ARMCORE_FLASH ++config ARMCORE_NAND ++ bool "CompuLab NAND flash driver" ++ depends on ARMCORE_FLASH ++ +diff --git a/drivers/block/cl_flash/Makefile b/drivers/block/cl_flash/Makefile +new file mode 100644 +index 0000000..538cb2c +--- /dev/null ++++ b/drivers/block/cl_flash/Makefile +@@ -0,0 +1,12 @@ ++# ++# Makefile for Compulab flash disk driver ++# ++ ++EXTRA_CFLAGS += -DTARGET_ARM_CORE -DFLASH_PLATFORM_LINUX ++ ++obj-$(CONFIG_ARMCORE_FLASH) += fdrv.o ++ ++fdrv-y += cl_nordev.o cl_blkdev.o CL_FlashDrv ++ ++ ++fdrv-$(CONFIG_MACH_ARMCORE) += cl_nanddev_x270.o +diff --git a/drivers/block/cl_flash/cl_blkdev.c b/drivers/block/cl_flash/cl_blkdev.c +new file mode 100644 +index 0000000..adb030d +--- /dev/null ++++ b/drivers/block/cl_flash/cl_blkdev.c +@@ -0,0 +1,731 @@ ++/* ++ * Flash Disk Driver for Linux. ++ * Generic block device and genric disk implementation ++ * ++ * Copyright Compulab 2003-2006 (c). ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "CL_Logic.h" ++#include "cl_blkdev.h" ++ ++/* I/O Controls */ ++#define CL_FLASH_IOC_MAGIC 'f' ++#define CL_FLASH_IO_GET_PARAM _IOWR (CL_FLASH_IOC_MAGIC, 1, char[12]) ++#define CL_FLASH_IO_DIRECT_ACCESS _IOWR (CL_FLASH_IOC_MAGIC, 2, char[524]) ++ ++#define FLUSH_INTERVAL 100 ++ ++struct cl_blkdev; ++ ++struct flash_blkdev_ops { ++ /* timer for periodic flushes of NAND flash */ ++ void (*flush_proc)(void* dev); ++ ++ /* HW specific ioctl */ ++ int (*flash_hw_ioctl)(struct cl_blkdev *dev, struct inode *inode, ++ struct file *file, unsigned int cmd, ++ unsigned long arg); ++ ++ /* HW specific request handling */ ++ int (*do_flash_hw_request)(struct cl_blkdev *dev, struct request *q); ++ /* HW specific cleanups */ ++ int (*flash_hw_release)(struct cl_blkdev *dev, struct inode *inode, ++ struct file *file); ++}; ++ ++struct cl_blkdev_priv { ++ /* thread is dead indication */ ++ struct completion thread_dead; ++ /* flag to notify the thread that we are done */ ++ int exiting; ++ /* thread wait queue head for requests */ ++ wait_queue_head_t thread_wq; ++ /* block device request queue */ ++ struct request_queue *rq; ++ /* request queue lock */ ++ spinlock_t queue_lock; ++}; ++ ++struct cl_blkdev { ++ struct cl_blkdev_priv *blkdev_priv; ++ struct gendisk *flash_disk; ++ struct flash_blkdev_ops *ops; ++ struct semaphore sem; ++ char name[32]; ++ ++ int major; ++ void *hw_private; /* Low level hook */ ++ ++#ifdef CONFIG_PROC_FS ++ /* proc entry */ ++ struct proc_dir_entry *pde; ++#endif ++}; ++ ++#define FLASH_SECTOR 512 ++ ++/* declarations of cl_mem_set etc */ ++#include "cl_common.c" ++ ++ ++/***************************************************************/ ++/* Flash software write protect setup */ ++/***************************************************************/ ++unsigned long wpstart=0, wpend=0; ++ ++static int __init wpstart_det(char *str) /*30-May-04, interrupts */ ++{ ++ wpstart = simple_strtol(str, NULL, 0); ++ return 1; ++} ++ ++static int __init wpend_det(char *str) /*30-May-04, interrupts */ ++{ ++ wpend = simple_strtol(str, NULL, 0); ++ return 1; ++} ++ ++__setup("wpstart=", wpstart_det); ++__setup("wpend=", wpend_det); ++ ++ ++/***************************************************************/ ++/* generic block device interface */ ++/***************************************************************/ ++/* cl_blkdev_open: open a device */ ++static int cl_blkdev_open(struct inode *inode, struct file *file) ++{ ++ return 0; ++} ++ ++static int cl_blkdev_check_media_change(struct gendisk* dev) ++{ ++ return 0; /* Disk not changed */ ++} ++ ++static int cl_blkdev_revalidate(struct gendisk* dev) ++{ ++ return 0; ++} ++ ++/* cl_blkdev_release: release the device */ ++static int cl_blkdev_release(struct inode *inode, struct file *file) ++{ ++ struct cl_blkdev *dev; ++ dev = inode->i_bdev->bd_disk->private_data; ++ ++ down (&dev->sem); ++ dev->ops->flash_hw_release(dev, inode, file); ++ up (&dev->sem); ++ ++ return 0; ++} ++ ++/* ++ cl_blkdev_ioctl: handle device ioctl's ++ common ioctls (if any) for NAND and NOR flash are handled here ++ then HW specific ioctl handler is invoked ++ */ ++static int cl_blkdev_ioctl(struct inode *inode, ++ struct file *file, u_int cmd, u_long arg) ++{ ++ struct cl_blkdev *dev; ++ ++ if ((!inode) || !(inode->i_rdev)) ++ return -EINVAL; ++ ++ dev = inode->i_bdev->bd_disk->private_data; ++ return dev->ops->flash_hw_ioctl(dev, inode, file, cmd, arg); ++} ++ ++static struct block_device_operations flash_fops = ++{ ++ .owner = THIS_MODULE, ++ .open = cl_blkdev_open, ++ .release = cl_blkdev_release, ++ .ioctl = cl_blkdev_ioctl, ++ .media_changed = cl_blkdev_check_media_change, ++ .revalidate_disk = cl_blkdev_revalidate ++}; ++ ++static int cl_nand_request (struct cl_blkdev *_dev, struct request * req); ++ ++/* wake up the flashdiskd thread to handle the request */ ++static void do_cl_blkdev_request(struct request_queue *rq) ++{ ++ struct cl_blkdev *dev = rq->queuedata; ++ wake_up(&dev->blkdev_priv->thread_wq); ++} ++ ++void cl_blkdev_suspend(struct cl_blkdev* dev) ++{ ++ dev->ops->flush_proc(dev); ++} ++ ++/***************************************************************/ ++/* flashdiskd thread is handling all transfer requests */ ++/***************************************************************/ ++static int cl_flashdisk_thread(void *arg) ++{ ++ struct cl_blkdev *dev = (struct cl_blkdev*)arg; ++ struct request_queue *rq = dev->blkdev_priv->rq; ++ unsigned long flush_period = msecs_to_jiffies(FLUSH_INTERVAL); ++ unsigned long last_flush_jiffies = jiffies; ++ ++ current->flags |= PF_MEMALLOC/* | PF_NOFREEZE */; ++ daemonize("%sd", "flashdisk"); ++ ++ while (!dev->blkdev_priv->exiting) { ++ struct request *req; ++ int res = 0; ++ DECLARE_WAITQUEUE(wait, current); ++ ++ try_to_freeze(); ++ ++ spin_lock_irq(rq->queue_lock); ++ req = elv_next_request(rq); ++ ++ if (!req) { ++ add_wait_queue(&dev->blkdev_priv->thread_wq, &wait); ++ set_current_state(TASK_INTERRUPTIBLE); ++ ++ spin_unlock_irq(rq->queue_lock); ++ ++ schedule(); ++ remove_wait_queue(&dev->blkdev_priv->thread_wq, &wait); ++ ++ continue; ++ } ++ ++ dev = req->rq_disk->private_data; ++ spin_unlock_irq(rq->queue_lock); ++ ++ down(&dev->sem); ++ res = dev->ops->do_flash_hw_request(dev, req); ++ ++ if ( jiffies - last_flush_jiffies > flush_period ) { ++ if ( dev->ops->flush_proc ) ++ dev->ops->flush_proc(dev); ++ last_flush_jiffies = jiffies; ++ } ++ up(&dev->sem); ++ ++ spin_lock_irq(rq->queue_lock); ++ end_request(req, res); ++ spin_unlock_irq(rq->queue_lock); ++ } ++ complete_and_exit(&dev->blkdev_priv->thread_dead, 0); ++} ++ ++/***************************************************************/ ++/* block device initialization routines */ ++/***************************************************************/ ++ ++/* ++ cl_blkdev_init: ++ - initialize and register generic block device, ++ - initialize timers for peroidic flushes ++ - initialize thread syncronization data ++ - start request processing thread ++ ++ dev - preallocated device that should be initialized ++ ops - HW specific implementation of block device ioctl, do_request etc ++ name - device name ++*/ ++int cl_blkdev_init(struct cl_blkdev *dev, ++ struct flash_blkdev_ops *ops, const char *name) ++{ ++ int ret; ++ ++ /* allocate the thread synchronization structure */ ++ dev->blkdev_priv = kmalloc(sizeof(*dev->blkdev_priv), GFP_KERNEL); ++ if (!dev->blkdev_priv) ++ return -ENOMEM; ++ memset(dev->blkdev_priv, 0, sizeof(*dev->blkdev_priv)); ++ ++ dev->ops = ops; ++ dev->major = 0; ++ strcpy(dev->name, name); ++ ++ /* register block device */ ++ if ((dev->major = register_blkdev(dev->major, dev->name)) <= 0) { ++ printk("flash: Unable to get major number.\n"); ++ return -ENODEV; ++ } ++ else ++ printk("Major number received: %d\n", dev->major); ++ ++ /* initialize data for 'flashdiskd' thread */ ++ spin_lock_init(&dev->blkdev_priv->queue_lock); ++ init_completion(&dev->blkdev_priv->thread_dead); ++ init_waitqueue_head(&dev->blkdev_priv->thread_wq); ++ init_MUTEX(&dev->sem); ++ ++ /* initialize block device request queue */ ++ dev->blkdev_priv->rq = blk_init_queue(do_cl_blkdev_request, ++ &dev->blkdev_priv->queue_lock); ++ if(!dev->blkdev_priv->rq) { ++ printk ("Could not initialize queue.\n"); ++ unregister_blkdev(dev->major, dev->name); ++ kfree(dev->blkdev_priv); ++ return -ENOMEM; ++ } ++ dev->blkdev_priv->rq->queuedata = dev; ++ blk_queue_hardsect_size(dev->blkdev_priv->rq, FLASH_SECTOR); ++ ++ /* start thread */ ++ ret = kernel_thread(cl_flashdisk_thread, dev, CLONE_KERNEL); ++ if (ret < 0) { ++ blk_cleanup_queue(dev->blkdev_priv->rq); ++ unregister_blkdev(dev->major, dev->name); ++ kfree(dev->blkdev_priv); ++ printk(KERN_ERR "%s: kernel_thread returned %d\n", __FUNCTION__, ret); ++ return ret; ++ } ++ ++ return 0; ++} ++ ++/* ++ cl_blkdev_register_disk: ++ - allocate generic dik object ++ - setup the disk (major, minors, name, ops) ++ - register the disk ++ ++ dev - block device enclosing the disk ++ name - disk name ++ size - size of the disk in sectors ++*/ ++int cl_blkdev_register_disk(struct cl_blkdev *dev, ++ const char* name, sector_t size) ++{ ++ /* allocate disk data structure */ ++ dev->flash_disk = alloc_disk(16); ++ if (! dev->flash_disk) ++ return -ENOMEM; ++ ++ /* initialize disk parameters */ ++ dev->flash_disk->major = dev->major; ++ dev->flash_disk->first_minor = 0; ++ dev->flash_disk->fops = &flash_fops; ++ dev->flash_disk->private_data = dev; ++ dev->flash_disk->queue = dev->blkdev_priv->rq; ++ ++ /* set /dev node names */ ++ strcpy(dev->flash_disk->disk_name, name); ++ strcpy(dev->flash_disk->devfs_name, name); ++ set_capacity(dev->flash_disk, size); ++ ++ /* Insert this disk into linked list of disks */ ++ add_disk(dev->flash_disk); ++ ++ return 0; ++} ++ ++/* ++ cl_blkdev_unregister: unregister flash disk and associated block device ++*/ ++void cl_blkdev_unregister(struct cl_blkdev *dev) ++{ ++ dev->blkdev_priv->exiting = 1; ++ wake_up(&dev->blkdev_priv->thread_wq); ++ wait_for_completion(&dev->blkdev_priv->thread_dead); ++ ++ del_gendisk(dev->flash_disk); ++ put_disk(dev->flash_disk); ++ blk_cleanup_queue(dev->blkdev_priv->rq); ++ ++ unregister_blkdev(dev->major, dev->name); ++} ++ ++/***************************************************************/ ++/* NAND flash specific */ ++/***************************************************************/ ++int format = 0; ++MODULE_PARM(format, "i"); ++ ++#define CACHE_SIZE 128 ++ ++/* This buffer is used for cach allocation, when cash size is bigger ++ than 128kb. 300 KB is the approximate amount needed for cache of 128 ++ pages, 2kb each. */ ++#define BUFFER_SIZE (300 * 1024) ++#define MAXIMUM_ALLOCATABLE_MEMORY (128 * 1024) ++char tmp_buff[BUFFER_SIZE]; ++ ++/* ++ cl_nand_mem_alloc: allocates memory for driver cache ++*/ ++void* cl_nand_mem_alloc (unsigned long size) ++{ ++ static int buf_not_used = 1; ++ if ((size > MAXIMUM_ALLOCATABLE_MEMORY) && ++ (size < BUFFER_SIZE) && buf_not_used) { ++ buf_not_used = 0; ++ return (void*)tmp_buff; ++ } ++ return kmalloc (size, GFP_KERNEL); ++} ++ ++/* ++ cl_nand_mem_free: frees memory allocated for driver cache ++*/ ++void cl_nand_mem_free (void* ptr) ++{ ++ kfree (ptr); ++} ++ ++/* ++ cl_nand_flush_proc: flushes driver caches to the device ++*/ ++static void cl_nand_flush_proc (void* _dev) ++{ ++ struct cl_blkdev *blkdev = (struct cl_blkdev*)_dev; ++ struct cl_nand_dev *dev = (struct cl_nand_dev*)blkdev->hw_private; ++ ++ dev->logic_sync(dev->logic); ++ cl_trace_log ("Data synced\n"); ++ dev->last_end_write_cmd = 0; ++} ++ ++/* ++ cl_nand_request: handles an incoming IO request ++*/ ++static int cl_nand_request (struct cl_blkdev *_dev, struct request * req) ++{ ++ struct cl_blkdev *blkdev = (struct cl_blkdev*)_dev; ++ struct cl_nand_dev *dev = (struct cl_nand_dev*)blkdev->hw_private; ++ ++ u_int block, count; ++ int code=1, i; ++ ++ block = req->sector; ++ count = req->current_nr_sectors; ++ ++ switch (rq_data_dir(req)) { ++ case 0: /* READ */ ++ for (i = 0, code = 1; i < count; i++) ++ if (!dev->logic_read_page( ++ dev->logic, block + i, ++ (char*)req->buffer + i * 512)) { ++ cl_trace_log ("Reading failed.\n"); ++ code = 0; /* failure */ ++ break; ++ } ++ break; ++ case 1: /* WRITE */ ++ for (i = 0, code = 1; i < count; i++) { ++ if(wpend) { ++ if (((block + i) >= wpstart) || ++ ((block + i) <= wpend)) { ++ code=0; ++ break; ++ } ++ } ++ if (!dev->logic_write_page( ++ dev->logic, block + i, ++ (char*)req->buffer + i * 512)) { ++ cl_trace_log ("Writing failed.\n"); ++ code = 0; /* failure */ ++ break; ++ } ++ } ++ dev->last_end_write_cmd = jiffies; ++ break; ++ default: ++ printk("do_flash_request: unknown request\n"); ++ break; ++ } ++ ++ return code; ++} ++ ++/* ++ cl_nand_ioctl: handles device ioctl's ++*/ ++static int cl_nand_ioctl(struct cl_blkdev *_dev, struct inode *inode, ++ struct file *file,unsigned int cmd,unsigned long arg) ++{ ++ struct cl_nand_dev *dev = (struct cl_nand_dev*)_dev->hw_private; ++ ++ cl_trace_log ("flash_ioctl called.\n"); ++ printk("fdrv.o ioctl\n"); ++ if ((!inode) || !(inode->i_rdev)) ++ return -EINVAL; ++ ++ switch (cmd) { ++ case HDIO_GETGEO: ++ { ++ struct hd_geometry *geometry = (struct hd_geometry*)arg; ++ if (!geometry) ++ return -EINVAL; /* Bad arguments to ioctl */ ++ put_user(dev->logic_get_param(dev->logic, ++ CL_FLASH_CYLINDERS_NUM, ++ 0), ++ &geometry->cylinders); ++ put_user(dev->logic_get_param(dev->logic, ++ CL_FLASH_HEADS_NUM, 0), ++ &geometry->heads); ++ put_user(dev->logic_get_param(dev->logic, ++ CL_FLASH_SECTORS_NUM, 0), ++ &geometry->sectors); ++ put_user(0, &geometry->start); ++ return 0; ++ } ++ case BLKGETSIZE: ++ if (!arg) ++ return -EINVAL; ++ return put_user(dev->logic_get_param( ++ dev->logic, ++ CL_FLASH_TOTAL_SIZE, 0) / 512, ++ (long *) arg); ++ case HDIO_SET_DMA: ++ /* We don't use DMA for flash. ++ This has no meaning */ ++ if (!capable (CAP_SYS_ADMIN)) ++ return -EACCES; ++ return 0; ++ case HDIO_GET_DMA: ++ return put_user( 0, (long *) arg); /* No DMA */ ++ case HDIO_GET_MULTCOUNT: ++ /* We don't have a limitation of number of ++ sectors in op. */ ++ return put_user (128, (long *) arg); ++ case BLKRRPART: ++ case BLKFLSBUF: ++ case BLKROSET: ++ case BLKROGET: ++ case BLKRASET: ++ case BLKRAGET: ++ case BLKPG: ++ case CL_FLASH_IO_GET_PARAM: ++ { ++ int err; ++ long* prm = (long*)arg; ++ err = access_ok(VERIFY_READ, prm, ++ sizeof(long) * 2) ? 0 : -EFAULT; ++ if (err) ++ return err; ++ err = access_ok(VERIFY_WRITE, prm, ++ sizeof (long)) ? 0 : -EFAULT; ++ if (err) ++ return err; ++ prm[0] = dev->logic_get_param(dev->logic, ++ prm[0], prm[1]); ++ return 0; ++ } ++ ++ case CL_FLASH_IO_DIRECT_ACCESS: ++ { ++ int err; ++ printk("====> CL_FLASH_IO_DIRECT_ACCESS\n"); ++ long* prm = (long*)arg; ++ err = access_ok(VERIFY_READ, prm, ++ sizeof(long) * 3) ? 0 : -EFAULT; ++ if(err) return err; ++ err = access_ok(VERIFY_WRITE, prm, ++ CL_FLASH_SECTOR_SIZE) ? 0 : -EFAULT; ++ if(err) return err; ++ return dev->logic_direct_access( ++ dev->logic, ++ (cl_nand_direct_access_type)prm[0], ++ (unsigned short)prm[1], ++ (unsigned short)prm[2], ++ (unsigned char*)(prm + 3)); ++ } ++ ++ default: ++ return -EINVAL; ++ } ++} ++ ++/* ++ cl_nand_release: releases the device ++*/ ++static int cl_nand_release (struct cl_blkdev *_dev, ++ struct inode *inode, struct file *file) ++{ ++ struct cl_nand_dev *dev = (struct cl_nand_dev*)_dev->hw_private; ++ ++ dev->logic_sync(dev->logic); ++ cl_trace_log ("Data synced after RELEASE command\n"); ++ dev->last_end_write_cmd = 0; ++ ++ return 0; ++} ++ ++static struct flash_blkdev_ops nand_blkdev_ops = { ++ .flush_proc = cl_nand_flush_proc, ++ .flash_hw_ioctl = cl_nand_ioctl, ++ .do_flash_hw_request = cl_nand_request, ++ .flash_hw_release = cl_nand_release ++}; ++ ++#ifdef CONFIG_PROC_FS ++/***************************************************************/ ++/* proc entry /proc/flashdisk implementation */ ++/***************************************************************/ ++#include ++#include ++ ++static void cl_nand_proc_show(struct seq_file *s, struct cl_blkdev *_dev) ++{ ++ struct cl_nand_dev *dev = _dev->hw_private; ++ ++ unsigned long heads, sects, tot_size, cylinders; ++ unsigned short sector_size, page_size; ++ long read_page_cnt, write_page_cnt, reclaim_cnt; ++ ++ tot_size = dev->logic_get_param(dev->logic, CL_FLASH_TOTAL_SIZE, 0); ++ heads = dev->logic_get_param(dev->logic, CL_FLASH_HEADS_NUM, 0); ++ sects = dev->logic_get_param(dev->logic, CL_FLASH_SECTOR_SIZE, 0); ++ cylinders = dev->logic_get_param(dev->logic, CL_FLASH_CYLINDERS_NUM, 0); ++ sector_size = dev->logic_get_param(dev->logic, CL_FLASH_SECTOR_SIZE, 0); ++ page_size = dev->logic_get_param(dev->logic, CL_FLASH_PAGE_SIZE, 0); ++ read_page_cnt = dev->logic_get_param(dev->logic, ++ CL_FLASH_READ_PAGE_CNT, 0); ++ write_page_cnt = dev->logic_get_param(dev->logic, ++ CL_FLASH_WRITE_PAGE_CNT, 0); ++ reclaim_cnt = dev->logic_get_param(dev->logic, CL_FLASH_RECLAIM_CNT, 0); ++ ++ ++ seq_printf(s, "NAND flash disk:\n"); ++ seq_printf(s, "\ttotal size: %lu Mbytes (%lu bytes)\n", ++ (tot_size >> 20), tot_size); ++ seq_printf(s, "\theads: %lu \tcylinders: %lu\tsectors: %lu\n", heads, ++ cylinders, sects); ++ seq_printf(s, "\tsector: %d\tpage: %d\n", sector_size, page_size); ++ seq_printf(s, "Stats:\n"); ++ seq_printf(s, "\tread: %ld\twritten: %ld\treclaimed: %ld\n", ++ read_page_cnt, write_page_cnt, reclaim_cnt); ++} ++ ++static int cl_blkdev_proc_show(struct seq_file *s, void *unused) ++{ ++ struct cl_blkdev *dev = s->private; ++ ++ seq_printf(s, "CompuLab flash disks:\n"); ++ cl_nand_proc_show(s, dev); ++ ++ return 0; ++} ++ ++static int cl_blkdev_proc_open(struct inode *inode, struct file *file) ++{ ++ return single_open(file, cl_blkdev_proc_show, PDE(inode)->data); ++} ++ ++static struct file_operations proc_ops = { ++ .open = cl_blkdev_proc_open, ++ .read = seq_read, ++ .llseek = seq_lseek, ++ .release = single_release, ++}; ++ ++static const char proc_filename[] = "flashdisk"; ++ ++static void cl_blkdev_proc_create_file(struct cl_blkdev *dev) ++{ ++ struct proc_dir_entry *pde; ++ pde = create_proc_entry(proc_filename, 0666, NULL); ++ if (pde == NULL) ++ return; ++ ++ pde->proc_fops = &proc_ops; ++ pde->data = dev; ++ dev->pde = pde; ++} ++ ++static void cl_blkdev_remove_proc_file(struct cl_blkdev *dev) ++{ ++ if (dev->pde) ++ remove_proc_entry(proc_filename, NULL); ++} ++ ++#else ++ ++#define cl_blkdev_create_proc_file(x) do {} while(0) ++#define cl_blkdev_remove_proc_file(x) do {} while(0) ++ ++#endif ++ ++/*******************************************************************/ ++/* NAND device initialization and cleanup */ ++/*******************************************************************/ ++/* ++ cl_nand_flash_init: ++ - initialize the CL_Logic ++ - register the block device and gendisk ++ ++ dev - preallocated cl_nand_dev object ++ cl_nand_linux - HW interface ++*/ ++int cl_nand_flash_init(struct cl_nand_dev *dev, cl_nand_map_if *cl_nand_linux) ++{ ++ const char *name = "nand"; ++ int ret = 0; ++ printk ("Nand Flash disk driver, CompuLab"); ++ ++ if( wpend ) ++ printk("NAND Write Protection activated from %ld to %ld.\n", ++ wpstart, wpend); ++ ++ if (format) ++ printk ("Formatting Nand flash . . .\n"); ++ dev->logic = dev->logic_create(cl_nand_linux, CACHE_SIZE, format, FLASH_SECTOR); ++ if (!dev->logic) { ++ printk ("Flash logic couldn't be created.\n"); ++ return -1; ++ } ++ ++ dev->blkdev = kmalloc(sizeof(*dev->blkdev), GFP_KERNEL); ++ if ( !dev->blkdev ) { ++ return -ENOMEM; ++ } ++ ++ dev->blkdev->hw_private = dev; ++ if ( (ret = cl_blkdev_init(dev->blkdev, &nand_blkdev_ops, name)) ) { ++ printk(KERN_ERR "%s: cl_blkdev initialization failed: %d\n", ++ __FUNCTION__, ret); ++ dev->logic_free(dev->logic); ++ return ret; ++ } ++ ++ ret = cl_blkdev_register_disk(dev->blkdev, name, ++ dev->logic_get_param(dev->logic, ++ CL_FLASH_TOTAL_SIZE, ++ 0) / 512); ++ if ( ret ) { ++ printk(KERN_ERR "%s: NAND disk registration failed: %d\n", ++ __FUNCTION__, ret); ++ cl_blkdev_unregister(dev->blkdev); ++ dev->logic_free(dev->logic); ++ return ret; ++ } ++ ++ cl_blkdev_proc_create_file(dev->blkdev); ++ ++ return 0; ++} ++ ++/* ++ cl_nand_flash_cleanup: performs cleanup when driver is no longer used ++*/ ++void cl_nand_flash_cleanup(struct cl_nand_dev * dev) ++{ ++ cl_blkdev_unregister(dev->blkdev); ++ if ( dev->logic ) ++ dev->logic_free(dev->logic); ++ ++ cl_blkdev_remove_proc_file(dev->blkdev); ++ ++ if ( dev->blkdev ) ++ kfree(dev->blkdev); ++} +diff --git a/drivers/block/cl_flash/cl_blkdev.h b/drivers/block/cl_flash/cl_blkdev.h +new file mode 100644 +index 0000000..bca1944 +--- /dev/null ++++ b/drivers/block/cl_flash/cl_blkdev.h +@@ -0,0 +1,43 @@ ++#ifndef __CL_BLKDEV_H__ ++#define __CL_BLKDEV_H__ ++ ++struct cl_blkdev; ++ ++struct cl_nand_dev { ++ struct cl_blkdev *blkdev; ++ cl_logic logic; ++ unsigned long last_end_write_cmd; ++ ++ /* CL logic access layer */ ++ cl_logic (*logic_create)(cl_nand_map_if*, long, ++ int, unsigned short); ++ void (*logic_free)(cl_logic); ++ long (*logic_get_param)(cl_logic, cl_logic_param, long); ++ int (*logic_read_page)(cl_logic, long, CLBYTEPTR); ++ int (*logic_write_page)(cl_logic, long, CLBYTEPTR); ++ void (*logic_on_idle)(cl_logic, int); ++ void (*logic_sync)(cl_logic); ++ int (*logic_direct_access)(cl_logic,cl_nand_direct_access_type, ++ unsigned short, unsigned char, CLBYTEPTR); ++}; ++ ++extern int cl_nand_flash_init(struct cl_nand_dev *dev, cl_nand_map_if *cl_nand_linux); ++extern void cl_nand_flash_cleanup(struct cl_nand_dev * dev); ++ ++#define INIT_NAND_DEV(dev) \ ++ do { \ ++ dev->logic = 0; \ ++ dev->blkdev = 0; \ ++ dev->last_end_write_cmd = 0; \ ++ dev->logic_create = cl_logic_create; \ ++ dev->logic_free = cl_logic_free; \ ++ dev->logic_get_param = cl_logic_get_param; \ ++ dev->logic_read_page = cl_logic_read_page; \ ++ dev->logic_write_page = cl_logic_write_page; \ ++ dev->logic_on_idle = cl_logic_on_idle; \ ++ dev->logic_sync = cl_logic_sync; \ ++ dev->logic_direct_access = cl_logic_direct_access; \ ++ } while(0) ++ ++ ++#endif /* __CL_BLKDEV_H__ */ +diff --git a/drivers/block/cl_flash/cl_common.c b/drivers/block/cl_flash/cl_common.c +new file mode 100644 +index 0000000..a0d2a9c +--- /dev/null ++++ b/drivers/block/cl_flash/cl_common.c +@@ -0,0 +1,52 @@ ++void cl_zero_mem (void* ptr, long size) ++{ ++ memset (ptr, 0, size); ++} ++ ++void cl_ff_mem (void* ptr, long size) ++{ ++ memset (ptr, 0xff, size); ++} ++void cl_mem_copy (void* dest, void* src, long size) ++{ ++ memcpy (dest, src, size); ++} ++ ++int cl_mem_compare (void* mem1, void* mem2, long size) ++{ ++ return memcmp (mem1, mem2, size); ++} ++ ++unsigned long cl_get_jiffies (void) ++{ ++ return jiffies; ++} ++ ++unsigned long cl_nand_get_max_cache_time (void) ++{ ++ return HZ * 30; /* 30 seconds in cache maximum */ ++} ++ ++void cl_trace_log ( char* format, ...) ++{ ++#ifdef DO_CL_TRACE_LOG ++ char full_msg[300]; ++ va_list marker; ++ ++ va_start(marker, format); ++ vsprintf(full_msg, format, marker); ++ printk(full_msg); ++ va_end(marker); ++#endif ++} ++ ++void cl_error_log ( char* format, ...) ++{ ++ char full_msg[300]; ++ va_list marker; ++ ++ va_start(marker, format); ++ vsprintf(full_msg, format, marker); ++ printk(full_msg); ++ va_end(marker); ++} +diff --git a/drivers/block/cl_flash/cl_nanddev_x270.c b/drivers/block/cl_flash/cl_nanddev_x270.c +new file mode 100644 +index 0000000..71f05f8 +--- /dev/null ++++ b/drivers/block/cl_flash/cl_nanddev_x270.c +@@ -0,0 +1,233 @@ ++/* ++ * drivers/block/cl_flash/cl_nandded_x270.c ++ * ++ * Flash Disk Driver for CM-X270 platform. ++ * Low level device interface implementation ++ * ++ * Copyright Compulab 2003-2006 (c). ++ */ ++ ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++ ++#include "CL_Logic.h" ++#include "cl_blkdev.h" ++ ++/* The following macro enables flash activity indication by LEDs */ ++#undef USE_LEDS ++ ++#define NAND_RB (GPLR2 & (1<<25)) ++ ++#define NandCLE (1<<0) ++#define NandALE (1<<1) ++ ++/* ++ * Values specific to the ARMCore ++ */ ++volatile unsigned long * FLASH_DATA; ++volatile unsigned long * FLASH_DATA_ALE; ++volatile unsigned long * FLASH_DATA_CLE; ++ ++/* asm-arm/arch-pxa/hardware.h defines UNCACHED_ADDR */ ++volatile unsigned char * UNC = (volatile unsigned char *)UNCACHED_ADDR; ++ ++/*******************************************************************/ ++/* CM-X270 NAND HW access layer */ ++/*******************************************************************/ ++static inline void nand_cs_on(void) ++{ ++ GPCR0 = 1<<11; ++ while( (GPLR0 & (1<<11)) ); ++} ++ ++static inline void nand_cs_off(void) ++{ ++ unsigned char dummy; ++ asm volatile ("mcr p15, 0, r0, c7, c10, 4":::"r0"); ++ dummy=*UNC; ++ ++ GPSR0 = 1<<11; ++ while( !(GPLR0 & (1<<11)) ); ++} ++ ++static void FlashInitial(void) ++{ ++} ++ ++static void FlashChipSelect (int on, int need_auto_operation) ++{ ++ static int cs_state = -1; ++ ++ if (need_auto_operation) ++ on = 1; ++ ++ if (cs_state == on) ++ return; ++ ++ cs_state = on; ++ ++ if (on) { ++ nand_cs_on(); ++ } ++ else { ++ nand_cs_off(); ++ } ++} ++ ++static unsigned char FlashReadByte (unsigned char offset) ++{ ++ return (unsigned char)(*FLASH_DATA >> 16); ++} ++ ++static void FlashWriteByte (unsigned char offset, unsigned char data) ++{ ++ if(offset & NandALE) *FLASH_DATA_ALE = (data << 16); ++ else if(offset & NandCLE) *FLASH_DATA_CLE = (data << 16); ++ else *FLASH_DATA = (data << 16); ++} ++ ++static void FlashBlockRead (unsigned char* data, int count) ++{ ++ while (count--) ++ *data++ = (unsigned char)(*FLASH_DATA >> 16); ++} ++ ++static void FlashBlockWrite ( unsigned char* data, int count) ++{ ++ while (count--) ++ *FLASH_DATA = (*data++ << 16); ++} ++ ++/* Orange LED used by Linux kernel activity */ ++static void FlashCoreLeds (short operation, short reclaim) ++{ ++#ifdef USE_LEDS ++ ++#endif ++} ++ ++static void do_nothing (void) ++{ ++} ++ ++int nand_delay(unsigned long microseconds) ++{ ++ if ( microseconds < 1000 ) { ++ udelay(microseconds); ++ return 0; ++ } ++ udelay(1000); ++ udelay(1000); ++ udelay(1000); ++ return 0; ++} ++ ++/* Wait on Ready/Busy signal */ ++static int RBWait(unsigned long microseconds) ++{ ++ unsigned char dummy; ++ int i=0; ++ ++ /* ensure there's no outstanding bus transaction */ ++ asm volatile ("mcr p15, 0, r0, c7, c10, 4":::"r0"); ++ dummy=*UNC; ++ ++ /* protect from big delays in R/B GPIO falling edge (or no R/B ++ falling edge activity) */ ++ while((NAND_RB == 1) && (i < 3000)){ ++ udelay(1); ++ i++; ++ }; ++ ++ if ( i > 0 ) ++ printk(KERN_DEBUG "%s: No immediate R/B activity\n", __FILE__); ++ ++ if (i == 3000){ ++ printk(KERN_DEBUG "%s: No R/B activity for 3 ms\n", __FILE__); ++ return (0); ++ } ++ ++ i=0; ++ ++ /* protect from big delays in R/B GPIO rising edge */ ++ while((NAND_RB == 0) && (i < 3000)){ ++ udelay(1); ++ i++; ++ }; ++ ++ if (i == 3000){ ++ printk(KERN_DEBUG "%s: R/B timed out\n", __FILE__); ++ return (0); ++ } ++ ++ /* ensure there's no outstanding bus transaction */ ++ asm volatile ("mcr p15, 0, r0, c7, c10, 4":::"r0"); ++ dummy=*UNC; ++ ++ return(1); ++} ++ ++static cl_nand_map_if cl_nand_linux = { ++ .init = FlashInitial, ++ .destroy = do_nothing, ++ .chip_select = FlashChipSelect, ++ .readb = FlashReadByte, ++ .writeb = FlashWriteByte, ++ .blockread = FlashBlockRead, ++ .blockwrite = FlashBlockWrite, ++ .activity_leds = FlashCoreLeds, ++ .sleep = nand_delay, ++ .rbwait = RBWait ++}; ++ ++static struct cl_nand_dev nand_dev; ++ ++/* ++ nand_flash_init: ++ - perform board specific initialization ++ - initialize NAND device data structure ++ - initialize block device layer ++*/ ++static int nand_flash_init (void) ++{ ++ struct cl_nand_dev *dev = &nand_dev; ++ ++ FLASH_DATA = (volatile unsigned long*)ioremap(PXA_CS1_PHYS, 12); ++ if (FLASH_DATA == NULL) { ++ printk("Bad NAND flash window at %X (already in use)\n", 0x04000000); ++ return -1; ++ } ++ FLASH_DATA_CLE = FLASH_DATA + 1; ++ FLASH_DATA_ALE = FLASH_DATA + 2; ++ ++ INIT_NAND_DEV(dev); ++ return cl_nand_flash_init(dev, &cl_nand_linux); ++} ++ ++#ifdef CONFIG_ARMCORE_NAND ++int cl_nand_init_module(void) ++{ ++ return nand_flash_init(); ++} ++ ++void cl_nand_cleanup_module(void) ++{ ++ struct cl_nand_dev *dev = &nand_dev; ++ cl_nand_flash_cleanup(dev); ++} ++#else ++int cl_nand_init_module(void) ++{ ++ return 0; ++} ++ ++void cl_nand_cleanup_module(void) ++{ ++} ++#endif +diff --git a/drivers/block/cl_flash/cl_nordev.c b/drivers/block/cl_flash/cl_nordev.c +new file mode 100644 +index 0000000..c141735 +--- /dev/null ++++ b/drivers/block/cl_flash/cl_nordev.c +@@ -0,0 +1,594 @@ ++/* ++ Flash Disk Driver Interface for Linux 2.4.x ++ Written by Vova Lifliand ++*/ ++ ++/* Includes */ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++ ++/* Macros for correct linux/blk.h inclusion */ ++ ++#define DEVICE_NAME "nor" ++ ++static int major = 0; ++ ++#define FLASH_SECTOR 512 ++ ++#include ++#include ++ ++extern void cl_error_log ( char* format, ...); ++extern void cl_trace_log ( char* format, ...); ++extern void cl_mem_copy (void* dest, void* src, long size); ++ ++ ++/* Undefine for custom LEDs usage */ ++#undef USE_LEDS ++ ++/* CrFlash driver interface */ ++#ifndef FLASH_PLATFORM_LINUX ++#define FLASH_PLATFORM_LINUX ++#endif ++#include "CL_Logic.h" ++ ++typedef unsigned long ULONG; ++ ++/* Forward functions declaration */ ++static int flash_open (struct inode *inode,struct file *file); ++static void do_flash_request (request_queue_t * q); ++static int flash_ioctl (struct inode *inode,struct file *file,unsigned int cmd,unsigned long arg); ++static int flash_release (struct inode *inode, struct file *file); ++ ++static DECLARE_MUTEX (nor_flash_sem); ++static int nor_flash_sem_catched = 0; ++ ++ ++volatile unsigned short * NorFlashMem; ++ ++static int flash_check_media_change (struct gendisk* dev) ++{ ++/* printk ("flash_check_media_change called.\r\n");*/ ++ return 0; /* Disk not changed */ ++} ++ ++static int flash_revalidate (struct gendisk* dev) ++{ ++/* printk ("flash_revalidate called.\r\n");*/ ++ return 0; ++} ++ ++static struct block_device_operations flash_fops = ++{ ++ .owner = THIS_MODULE, ++ .open = flash_open, ++ .release = flash_release, ++ .ioctl = flash_ioctl, ++ .media_changed = flash_check_media_change, ++ .revalidate_disk = flash_revalidate ++}; ++ ++static struct gendisk *flash_gendisk; ++static spinlock_t flash_lock; ++static struct request_queue *flash_queue; ++ ++ ++#ifdef CONFIG_ARMCORE_NOR ++/* nor_flash_init: register the block device number and set up pointer tables */ ++int __init nor_flash_init (void) ++{ ++ ULONG trash1, trash2, trash3, trash4, TotalSect; ++ ++ /* Request memory for NOR Flash */ ++ NorFlashMem = (volatile unsigned short*)ioremap (0x00000000, 0x800000); ++ if (NorFlashMem == NULL) { ++ printk("Bad NOR flash window at %X (already in use)\n", 0x00000000); ++ return -1; ++ } ++ ++ /* Do flash initialization */ ++ if (!cl_nor_init_flash()) { ++ printk("NOR: Flash initialization failed\n"); ++ iounmap((void __iomem *)NorFlashMem); ++ return -1; ++ } ++ ++ spin_lock_init(&flash_lock); ++ flash_queue = blk_init_queue(do_flash_request, &flash_lock); ++ if(flash_queue == NULL) ++ { ++ printk ("Could not initialize queue.\r\n"); ++ iounmap((void __iomem *)NorFlashMem); ++ return -1; ++ } ++ blk_queue_hardsect_size(flash_queue, FLASH_SECTOR); ++ ++ if ((major=register_blkdev (0, DEVICE_NAME)) <= 0) ++ { ++ printk("flash: Unable to get major number \n"); ++ iounmap((void __iomem *)NorFlashMem); ++ return -1; ++ } else printk("Major number received: %d\n", major); ++ ++ /* Insert this disk into linked list of disks */ ++ ++ flash_gendisk = alloc_disk(16); ++ if (! flash_gendisk) return -ENOMEM; ++ flash_gendisk->major = major; ++ flash_gendisk->first_minor = 0; ++ flash_gendisk->fops = &flash_fops; ++ flash_gendisk->private_data=NULL; ++ flash_gendisk->queue = flash_queue; ++ strcpy(flash_gendisk->disk_name, "nor"); ++ cl_nor_get_disk_param( &TotalSect, &trash1, &trash2, &trash3, &trash4); ++ set_capacity(flash_gendisk, TotalSect); ++ add_disk(flash_gendisk); ++ ++ /* Starting flush timer: the cl_timer_proc will be executed on each timer interrupt */ ++ ++ return 0; ++} ++#else ++int __init nor_flash_init (void) ++{ ++ return 0; ++} ++#endif ++ ++/* flash_open: open a device */ ++static int flash_open (struct inode *inode, struct file *file) ++{ ++ ++ return 0; ++ ++} ++ ++/* do_flash_request: handle an incoming request */ ++static void do_flash_request (request_queue_t * q) ++{ ++ u_int block, count; ++ int code=1, i; ++ struct request* req=NULL; ++ ++ while ((code == 1) && ((req = elv_next_request(q)) != NULL)) ++ { ++ block = req->sector; ++ // printk ("req->nr_sectors = %d.\r\n", req->nr_sectors); ++ // printk ("req->current_nr_sectors = %d.\r\n", req->current_nr_sectors); ++ count = req->current_nr_sectors; ++ ++ nor_flash_sem_catched++; ++ down (&nor_flash_sem); ++ ++ switch (rq_data_dir(req)) { ++ case 0: // READ ++ for (i = 0, code = 1; i < count; i++) ++ // printk ("Reading sector %d (of %d).\r\n", block + i, count); ++ if (!cl_nor_read_page ( block + i, ++ (void *)((char*)req->buffer + i * 512))) { ++ // printk ("Reading failed.\r\n"); ++ code = 0; /* failure */ ++ break; ++ } ++ // printk ("Reading completed successfully.\r\n"); ++ break; ++ case 1: // WRITE ++ for (i = 0, code = 1; i < count; i++) { ++ // printk ("Writing sector %d.\r\n", block + i); ++ if (!cl_nor_write_page ( block + i, ++ (void *)((char*)req->buffer + i * 512))) { ++ // printk ("Writing failed.\r\n"); ++ code = 0; /* failure */ ++ break; ++ } ++ // printk ("Writing completed successfully.\r\n"); ++ } ++ break; ++ default: ++ printk("do_flash_request: unknown request\n"); ++ break; ++ } ++ up (&nor_flash_sem); ++ nor_flash_sem_catched--; ++ end_request (req, code); /* wrap up, 0 = fail, 1 = success */ ++ } ++} ++ ++/* flash_ioctl: handle device ioctl's */ ++static int flash_ioctl (struct inode *inode, struct file *file, u_int cmd, u_long arg) ++{ ++ ULONG trash1, trash2, trash3, trash4, TotalSect; ++ ++ // printk ("flash_ioctl called.\r\n"); ++ ++ if ((!inode) || !(inode->i_rdev)) ++ return -EINVAL; ++ ++ cl_nor_get_disk_param( &TotalSect, &trash1, &trash2, &trash3, &trash4); ++ // printk ("flash_ioctl in switch.\r\n"); ++ switch (cmd) ++ { ++ case HDIO_GETGEO: ++ { ++ struct hd_geometry *geometry = (struct hd_geometry*)arg; ++ if (!geometry) ++ return -EINVAL; /* Bad arguments to ioctl */ ++ put_user(TotalSect / 32 , &geometry->cylinders); ++ put_user(1, &geometry->heads); ++ put_user(32, &geometry->sectors); ++ put_user(2, &geometry->start); ++ } ++ case BLKGETSIZE: ++ if (!arg) ++ return -EINVAL; ++ return put_user (TotalSect, (long *) arg); ++ case HDIO_SET_DMA: /* We don't use DMA for flash. This has no meaning */ ++ if (!capable (CAP_SYS_ADMIN)) ++ return -EACCES; ++ return 0; ++ case HDIO_GET_DMA: ++ return put_user( 0, (long *) arg); /* No DMA */ ++ case HDIO_GET_MULTCOUNT: /* We don't have a limitation of number of sectors in op. */ ++ return put_user (128, (long *) arg); ++ case BLKFLSBUF: ++ case BLKROSET: ++ case BLKROGET: ++ case BLKRASET: ++ case BLKRAGET: ++ case BLKPG: ++ ++ default: ++ return -EINVAL; ++ } ++} ++ ++/* flash_release: release the device */ ++static int flash_release (struct inode *inode, struct file *file) ++{ ++ ++ return 0; ++} ++ ++#ifdef CONFIG_ARMCORE_NOR ++static void flash_done (void) ++{ ++ del_gendisk(flash_gendisk); ++ put_disk(flash_gendisk); ++ blk_cleanup_queue(flash_queue); ++ ++ /* Free memory allocated by flash module */ ++ cl_nor_free_mem (); ++ ++ unregister_blkdev (major, DEVICE_NAME); ++} ++#else ++static void flash_done (void) ++{ ++} ++#endif ++ ++extern int cl_nand_init_module(void); ++extern void cl_nand_cleanup_module(void); ++ ++int flash_init_module(void) ++{ ++ int error; ++ ++ error = cl_nand_init_module(); ++ if (error) return error; ++ ++ error = nor_flash_init(); ++ if (error) return error; ++ ++ return 0; ++} ++ ++void flash_cleanup_module(void) ++{ ++ flash_done(); ++ cl_nand_cleanup_module(); ++} ++ ++module_init (flash_init_module); ++module_exit (flash_cleanup_module); ++ ++//-------------------- CMNLIN.C --------- ++ ++#define TRUE 1 ++#define FALSE 0 ++ ++#define FL_CLKS_PER_SEC 182 ++ ++#define NAND_HEAP_SIZE 64000 /* bytes */ ++#define NOR_HEAP_SIZE 50000 /* bytes */ ++ ++/* NOR Flash constants */ ++#define NorFlashBlockSize 0x10000L /* 64 KB */ ++#define NorFlashDiskPagesPerBlock 127 ++ ++#define NOR_DRIVE_STARTING_BLOCK 27 ++ ++/* NOR Flash Functions Support */ ++ ++/* Constructor / destructor */ ++static void Nor_Create(void); ++/* Basic operations */ ++static void Nor_EnableFlashMap(int EnableFlag); ++static unsigned long Nor_GetSize(void); ++static int Nor_GetPagesPerBlock(void); ++static int Nor_ReadHeader (unsigned short BlockN, cl_nor_block_header* Header); ++static int Nor_ReadPage (unsigned short BlockN, unsigned char PageNum, CLBYTEPTR DestBuff); ++static int Nor_SetBlockState(unsigned short BlockN, unsigned short Signature, ++ unsigned short State, unsigned short Reserved); ++static int Nor_InvalidatePage(unsigned short BlockN, unsigned char PageN); ++static int Nor_WritePage(unsigned short BlockN, unsigned char PageN, ++ CLBYTEPTR PageData, unsigned short PageIndex); ++static int Nor_EraseBlock(unsigned short BlockN); ++ ++extern volatile unsigned short * NorFlashMem; ++unsigned char Nor_IntelFlash; ++ ++void Nor_EmptyFunc(void){}; ++ ++cl_nor_flash_access NorFlashAccess = ++ { ++ Nor_Create, ++ Nor_EmptyFunc, /*NULL,*/ /* Destructor not needed */ ++ Nor_GetSize, ++ Nor_EnableFlashMap, ++ Nor_GetPagesPerBlock, ++ Nor_ReadHeader, ++ Nor_ReadPage, ++ Nor_SetBlockState, ++ Nor_InvalidatePage, ++ Nor_WritePage, ++ Nor_EraseBlock, ++ }; ++ ++/* Driver see NOR Flash Blocks as linear, while there are BIOS holes */ ++static int Nor_GetPhysBlockIndex (int BlockN) ++{ ++ return (BlockN + NOR_DRIVE_STARTING_BLOCK); ++} ++ ++static void NorWrWord(unsigned long index, unsigned short data) ++{ ++ *(NorFlashMem+index)=data; ++} ++extern void NorWrWord(unsigned long index, unsigned short data); ++ ++static unsigned short NorRdWord(unsigned long index) ++{ ++ return *(NorFlashMem+index); ++} ++ ++static unsigned char Nor_OutAMDCommand(unsigned short command) ++{ ++ NorWrWord(0x555, 0xAAAA); ++ NorWrWord(0x2AA, 0x5555); ++ NorWrWord(0x555, command); ++ return TRUE; ++} ++ ++ ++static void Nor_Create(void) ++{ ++ /* Nothing should be done here - all services are provided by BIOS */ ++} ++ ++static unsigned long Nor_GetSize(void) ++{ ++ unsigned long NorFlashSize = 0x100000; ++ unsigned short n; ++/* unsigned long i; */ ++ ++ /* Determine flash type */ ++ NorWrWord(0, 0xFFFF); ++ NorWrWord(0, 0x9090); ++ if(NorRdWord(0) == 0x89) ++ Nor_IntelFlash = TRUE; ++ else Nor_IntelFlash = FALSE; ++ NorWrWord(0, 0xFFFF); ++ ++ /* Query flash size */ ++ /* 1. Do reset command */ ++ NorWrWord(0, 0xF0F0); /* was 0f0f */ ++ NorWrWord(0, 0xFFFF); /* Will also reset intel flash */ ++ /* 2. Enter CFI mode */ ++ NorWrWord(0x55, 0x9898); ++ /* 3. Read flash size */ ++/* READ WHOLE CFI for (i=10; i<0x3D; i++){ ++ n = NorRdWord(i); ++ printk("CFI n=%x\n", n);} */ ++ n = NorRdWord(0x27); ++ /* 4. Do reset again - exit CFI mode */ ++ NorWrWord(0, 0xF0F0); /* was 0f0f */ ++ NorWrWord(0, 0xFFFF); /* Will also reset intel flash */ ++ /* Exclude BIOS area */ ++ if((n>0x17) | (n<0x14)) n=0x14; // if detection is unsuccessfull (no CFI) default to 1MB ++ NorFlashSize = (1 << n); /* 2 ^ n */ ++ ++ cl_error_log("NOR Flash (%s) size: %d MB total\n",(Nor_IntelFlash ? "Intel" : "AMD"),NorFlashSize / (1024 * 1024)); ++ ++ if(NorFlashSize == (1024 * 1024)) { ++ cl_error_log("1Mb flash not supported!\n"); ++ return 0; ++ } ++ ++ return NorFlashSize -= NOR_DRIVE_STARTING_BLOCK * 64L * 1024L; /*exclude BIOS and jump areas, spareblocks etc.*/ ++} ++ ++/* Remaps or unmaps MMS windows, allocated by flash */ ++static void Nor_EnableFlashMap (int EnableFlag) ++{ ++ /* Just to prevent warning */ ++ int x = EnableFlag; ++ EnableFlag = x; ++ /* Nothing should be done here - all services are provided by BIOS */ ++} ++ ++static int Nor_GetPagesPerBlock(void) ++{ ++ return NorFlashDiskPagesPerBlock; ++} ++ ++static int Nor_ReadHeader (unsigned short BlockN, cl_nor_block_header* Header) ++{ ++ ++ cl_mem_copy (Header, ++ (char*)(NorFlashMem + (0x8000 * Nor_GetPhysBlockIndex(BlockN))), ++ (sizeof (cl_nor_block_header) + 1) & 0xFFFE); ++ return 1; ++} ++ ++static int Nor_ReadPage (unsigned short BlockN, unsigned char PageNum, CLBYTEPTR DestBuff) ++{ ++ cl_mem_copy (DestBuff, ++ (char*)(NorFlashMem + (0x8000 * Nor_GetPhysBlockIndex(BlockN)) + ++ ((PageNum + 1) * (CL_NOR_FLASH_PAGE_SIZE / 2))), ++ CL_NOR_FLASH_PAGE_SIZE); ++ return 1; ++} ++ ++static int Nor_EraseBlock(unsigned short BlockN) ++{ ++ unsigned long addr; ++ unsigned short dummy; ++ ++ addr=(Nor_GetPhysBlockIndex(BlockN)*NorFlashBlockSize)/2; ++ if(Nor_IntelFlash) ++ { /* Erase block sequence from Intel flash */ ++ NorWrWord(addr, 0xFFFF); ++ NorWrWord(addr, 0x7070); ++ NorWrWord(addr, 0x2020); ++ NorWrWord(addr, 0xD0D0); ++ NorWrWord(addr, 0xD0D0); ++ while(!(NorRdWord(addr) & 128)) ++ ; ++ NorWrWord(0, 0xFFFF); ++ return TRUE; ++ } ++ else ++ { ++ /* Do "erase block" commands sequence */ ++ if(!Nor_OutAMDCommand(0xF0F0)) return FALSE; ++ dummy = NorRdWord(addr); /* read and discard */ ++ if(!Nor_OutAMDCommand(0x8080)) return FALSE; ++ NorWrWord(0x555, 0xAAAA); ++ NorWrWord(0x2AA, 0x5555); ++ NorWrWord(addr, 0x3030); ++ ++ /* Waiting block is erased - no timeout here */ ++ while(TRUE) ++ { ++ /* Stall processor execution for about 20 microseconds <--- it is much less */ ++ for(dummy = 0; dummy < 20; dummy++) ++ ; ++ /* Check if ready */ ++ if(NorRdWord(addr) == 0xFFFF) ++ return TRUE; ++ } ++ } ++} ++ ++static int Nor_SetWord (unsigned long ofs, unsigned short word) ++{ ++ unsigned short timeout = 0xFFF; ++ unsigned long addr; ++ addr = ((Nor_GetPhysBlockIndex (ofs >> 15))<<15)+(ofs&0x7FFF);// 15 because address is given for word argument ++ /* The address should be word aligned since accessing by word and not by byte */ ++ ++ if(Nor_IntelFlash) ++ { /* Write sequence from Intel flash */ ++ NorWrWord(addr, 0x4040); ++ NorWrWord(addr, word); ++ while(timeout--) ++ udelay(1); ++ if(NorRdWord(addr) & 128) ++ { ++ unsigned char res = !(NorRdWord(addr) & 16); ++ NorWrWord(addr, 0x5050); ++ NorWrWord(addr, 0xFFFF); ++ return res; ++ } ++ NorWrWord(0, 0x5050); ++ } ++ else ++ { /* Write sequence from AMD flash */ ++ /* Output command is a necessary sequence to write word */ ++ if(!Nor_OutAMDCommand(0xA0A0)) ++ return FALSE; ++ ++ /* Write data */ ++ NorWrWord(addr, word); ++ /* Wait data written */ ++ while(timeout--) { ++ udelay(1); ++ if(NorRdWord(addr) == word) ++ return TRUE; ++ } ++ } ++ /* Failure */ ++ cl_error_log("ERROR: SetWord timeout."); ++ ++ return FALSE; ++} ++ ++static int Nor_SetBlockState(unsigned short BlockN, unsigned short Signature, ++ unsigned short State, unsigned short Reserved) ++{ ++ return Nor_SetWord ((BlockN * NorFlashBlockSize + 0)/2, Signature) && ++ Nor_SetWord ((BlockN * NorFlashBlockSize + 2)/2, State) && ++ Nor_SetWord ((BlockN * NorFlashBlockSize + 26 + 127 * 2)/2, Reserved); ++} ++ ++static int Nor_InvalidatePage (unsigned short BlockN, unsigned char PageN) ++{ ++ return Nor_SetWord ((BlockN * NorFlashBlockSize + 6 + 2 * PageN)/2, 0); ++} ++ ++static int Nor_WritePage (unsigned short BlockN, unsigned char PageN, ++ CLBYTEPTR PageData, unsigned short PageIndex) ++{ ++ int words_left, dest_addr; ++ unsigned short* ptr; ++ ++ /* Write index to first page - header information */ ++ if(!Nor_SetWord((BlockN * NorFlashBlockSize + 6 + 2 * PageN)/2, PageIndex)) ++ { ++ cl_error_log("A"); ++ return FALSE; /* Couldn't write page index */ ++ } ++ ++ /* Write page data */ ++ words_left = (512 >> 1); /* Write by word */ ++ dest_addr = BlockN * NorFlashBlockSize + (PageN + 1) * 512; ++ ptr = (unsigned short*)PageData; ++ while(words_left--) ++ { ++ if(!Nor_SetWord(dest_addr/2, *ptr++)) ++ { ++ cl_error_log("B"); ++ return FALSE; /* Page data writing failure */ ++ } ++ dest_addr += 2; /* Write by word (2 bytes each write command) */ ++ } ++ ++ return TRUE; ++} ++ +diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig +index 05ba410..a820db0 100644 +--- a/drivers/char/Kconfig ++++ b/drivers/char/Kconfig +@@ -1020,5 +1020,11 @@ config TELCLOCK + sysfs directory, /sys/devices/platform/telco_clock, with a number of + files for controlling the behavior of this hardware. + ++ ++config EMV3020_RTC ++ tristate "EM-V3020 RTC" ++ ---help--- ++ Support for EM Microelectronics V3020 RTC ++ + endmenu + +diff --git a/drivers/char/Makefile b/drivers/char/Makefile +index 503dd90..625bfd9 100644 +--- a/drivers/char/Makefile ++++ b/drivers/char/Makefile +@@ -49,6 +49,7 @@ obj-$(CONFIG_VIOCONS) += viocons.o + obj-$(CONFIG_VIOTAPE) += viotape.o + obj-$(CONFIG_HVCS) += hvcs.o + obj-$(CONFIG_SGI_MBCS) += mbcs.o ++obj-$(CONFIG_EMV3020_RTC) += emv3020.o + + obj-$(CONFIG_PRINTER) += lp.o + obj-$(CONFIG_TIPAR) += tipar.o +diff --git a/drivers/char/emv3020.c b/drivers/char/emv3020.c +new file mode 100644 +index 0000000..df7f1a4 +--- /dev/null ++++ b/drivers/char/emv3020.c +@@ -0,0 +1,365 @@ ++/* ++ * emv3020.c ++ * ++ * Driver for EMV3020 RTC ++ * ++ * Copyright (C) 2006 Compulab Ltd. ++ * ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 as ++ * published by the Free Software Foundation. ++ * ++ * ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++ ++#define EMV3020_VA_RTC emv3020_rtc_base ++ ++static struct resource *emv3020_rtc_mem; ++static void __iomem *emv3020_rtc_base; ++ ++#define DEBUG 0 ++#if DEBUG ++static unsigned int rtc_debug = DEBUG; ++#else ++#define rtc_debug 0 /* gcc will remove all the debug code for us */ ++#endif ++ ++static void emv3020_set_reg(unsigned char address, unsigned char data) ++{ ++ int i; ++ ++ for ( i = 0; i < 4; i++ ) ++ writel((address << (16-i)), EMV3020_VA_RTC); ++ ++ if ( address < 0xe) ++ for ( i = 0; i < 8; i++) ++ writel((data << (16-i)), EMV3020_VA_RTC); ++} ++ ++static unsigned char emv3020_get_reg(unsigned char address) ++{ ++ unsigned int data=0; ++ int i, tmp; ++ ++ for ( i = 0; i < 4; i++ ) ++ writel((address << (16-i)), EMV3020_VA_RTC); ++ ++ for ( i = 0; i < 8; i++ ) { ++ tmp = readl(EMV3020_VA_RTC); ++ data |= ((tmp & 0x10000) >> (16 - i)); ++ } ++ ++ return data; ++} ++ ++static int emv3020_detect(struct device *dev) ++{ ++ int i; ++ int temp; ++ ++ for ( i=0; i<8; i++) ++ temp = readl(EMV3020_VA_RTC); ++ ++ emv3020_set_reg(0x2, 0x33); ++ ++ if ( emv3020_get_reg(0x2) == 0x33 ) { ++ emv3020_set_reg(0x0, 0x0); ++ return 0; ++ } ++ ++ return -ENODEV; ++} ++ ++static int emv3020_rtc_gettime(struct rtc_time *dt) ++{ ++ int ret=0; ++ ++ emv3020_set_reg(0x0F, 0); ++ ++ dt->tm_sec = emv3020_get_reg(0x02); ++ dt->tm_min = emv3020_get_reg(0x03); ++ dt->tm_hour = emv3020_get_reg(0x04); ++ dt->tm_mday = emv3020_get_reg(0x05); ++ dt->tm_mon = emv3020_get_reg(0x06); ++ dt->tm_wday = emv3020_get_reg(0x08); ++ dt->tm_year = emv3020_get_reg(0x07); ++ ++ BCD_TO_BIN(dt->tm_sec); ++ BCD_TO_BIN(dt->tm_min); ++ BCD_TO_BIN(dt->tm_hour); ++ BCD_TO_BIN(dt->tm_mday); ++ BCD_TO_BIN(dt->tm_mon); ++ BCD_TO_BIN(dt->tm_wday); ++ BCD_TO_BIN(dt->tm_year); ++ dt->tm_year += 100; ++ ++ if(rtc_debug)printk("\n%s : Read RTC values\n",__FUNCTION__); ++ if(rtc_debug)printk("tm_hour: %i\n",dt->tm_hour); ++ if(rtc_debug)printk("tm_min : %i\n",dt->tm_min); ++ if(rtc_debug)printk("tm_sec : %i\n",dt->tm_sec); ++ if(rtc_debug)printk("tm_year: %i\n",dt->tm_year); ++ if(rtc_debug)printk("tm_mon : %i\n",dt->tm_mon); ++ if(rtc_debug)printk("tm_mday: %i\n",dt->tm_mday); ++ if(rtc_debug)printk("tm_wday: %i\n",dt->tm_wday); ++ ++ return ret; ++} ++ ++static int emv3020_rtc_settime(struct rtc_time *dt) ++{ ++ if(rtc_debug)printk("\n%s : Setting RTC values\n",__FUNCTION__); ++ if(rtc_debug)printk("tm_sec : %i\n",dt->tm_sec); ++ if(rtc_debug)printk("tm_min : %i\n",dt->tm_min); ++ if(rtc_debug)printk("tm_hour: %i\n",dt->tm_hour); ++ if(rtc_debug)printk("tm_mday: %i\n",dt->tm_mday); ++ if(rtc_debug)printk("tm_wday: %i\n",dt->tm_wday); ++ if(rtc_debug)printk("tm_year: %i\n",dt->tm_year); ++ ++ dt->tm_year %= 100; ++ BIN_TO_BCD(dt->tm_sec); ++ BIN_TO_BCD(dt->tm_min); ++ BIN_TO_BCD(dt->tm_hour); ++ BIN_TO_BCD(dt->tm_mday); ++ BIN_TO_BCD(dt->tm_mon); ++ BIN_TO_BCD(dt->tm_wday); ++ BIN_TO_BCD(dt->tm_year); ++ ++ emv3020_set_reg(0x02, dt->tm_sec); ++ emv3020_set_reg(0x03, dt->tm_min); ++ emv3020_set_reg(0x04, dt->tm_hour); ++ emv3020_set_reg(0x05, dt->tm_mday); ++ emv3020_set_reg(0x06, dt->tm_mon); ++ emv3020_set_reg(0x08, dt->tm_wday); ++ emv3020_set_reg(0x07, dt->tm_year); ++ ++ emv3020_set_reg(0x0E, 0); ++ ++ return 0; ++} ++ ++static int emv3020_rtc_open(void) ++{ ++ return 0; ++} ++ ++static void emv3020_rtc_release(void) ++{ ++} ++ ++static int emv3020_rtc_ioctl(unsigned int cmd, unsigned long arg) ++{ ++ struct rtc_time wtime; ++ int status = 0; ++ ++ switch (cmd) { ++ default: ++ case RTC_UIE_ON: ++ case RTC_UIE_OFF: ++ case RTC_PIE_ON: ++ case RTC_PIE_OFF: ++ case RTC_AIE_ON: ++ case RTC_AIE_OFF: ++ case RTC_ALM_SET: ++ case RTC_ALM_READ: ++ case RTC_IRQP_READ: ++ case RTC_IRQP_SET: ++ case RTC_EPOCH_READ: ++ case RTC_EPOCH_SET: ++ case RTC_WKALM_SET: ++ case RTC_WKALM_RD: ++ status = -EINVAL; ++ break; ++ ++ case RTC_RD_TIME: ++ emv3020_rtc_gettime(&wtime); ++ if( copy_to_user((void *)arg, &wtime, ++ sizeof (struct rtc_time))) ++ status = -EFAULT; ++ break; ++ ++ case RTC_SET_TIME: ++ if (!capable(CAP_SYS_TIME)) { ++ status = -EACCES; ++ break; ++ } ++ ++ if (copy_from_user(&wtime, (struct rtc_time *)arg, ++ sizeof(struct rtc_time)) ) { ++ status = -EFAULT; ++ break; ++ } ++ ++ emv3020_rtc_settime(&wtime); ++ break; ++ } ++ ++ return status; ++} ++ ++static char *emv3020_mon2str(unsigned int mon) ++{ ++ char *mon2str[12] = { ++ "Jan", "Feb", "Mar", "Apr", "May", "Jun", ++ "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" ++ }; ++ if( mon > 11) return "error"; ++ else return mon2str[ mon]; ++} ++ ++static int emv3020_rtc_proc( char *buf) ++{ ++ char *p = buf; ++ struct rtc_time dt; ++ ++ emv3020_rtc_gettime(&dt); ++ ++ p += sprintf(p, "\nEMV3020 (Real Time Clock)\n"); ++ p += sprintf(p, "Date/Time : %02d-%s-%04d %02d:%02d:%02d\n", ++ dt.tm_mday, ++ emv3020_mon2str(dt.tm_mon), ++ dt.tm_year+1900, ++ dt.tm_hour, ++ dt.tm_min, ++ dt.tm_sec); ++ return p - buf; ++} ++ ++static struct rtc_ops emv3020_rtcops = { ++ .owner = THIS_MODULE, ++ .open = emv3020_rtc_open, ++ .release = emv3020_rtc_release, ++ .ioctl = emv3020_rtc_ioctl, ++ .read_time = emv3020_rtc_gettime, ++ .set_time = emv3020_rtc_settime, ++ .read_alarm = 0, ++ .set_alarm = 0, ++ .proc = emv3020_rtc_proc, ++}; ++ ++static int emv3020_rtc_remove(struct device *dev) ++{ ++ unregister_rtc(&emv3020_rtcops); ++ ++ if (emv3020_rtc_mem != NULL) { ++ pr_debug("emv3020_rtc: releasing emv3020_rtc_mem\n"); ++ iounmap(emv3020_rtc_base); ++ release_resource(emv3020_rtc_mem); ++ } ++ ++ return 0; ++} ++ ++static int emv3020_rtc_probe(struct device *dev) ++{ ++ struct platform_device *pdev = to_platform_device(dev); ++ struct resource *res; ++ int ret; ++ ++ pr_debug("%s: probe=%p, device=%p\n", __FUNCTION__, pdev, dev); ++ ++ /* get the memory region */ ++ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ if (res == NULL) { ++ dev_err(dev, "failed to get memory region resource\n"); ++ return -ENOENT; ++ } ++ ++ emv3020_rtc_mem = request_mem_region(res->start, ++ res->end - res->start + 1, ++ pdev->name); ++ ++ if (emv3020_rtc_mem == NULL) { ++ dev_err(dev, "failed to reserve memory region\n"); ++ ret = -ENOENT; ++ goto exit_err; ++ } ++ ++ emv3020_rtc_base = ioremap(res->start, res->end - res->start + 1); ++ if (emv3020_rtc_base == NULL) { ++ dev_err(dev, "failed ioremap()\n"); ++ ret = -EINVAL; ++ goto exit_err; ++ } ++ ++ emv3020_rtc_mem = res; ++ pr_debug("emv3020_rtc_base=%p\n", emv3020_rtc_base); ++ ++ /* check to see if everything is setup correctly */ ++ if ( (ret = emv3020_detect(dev)) != 0 ) { ++ iounmap(emv3020_rtc_base); ++ release_resource(emv3020_rtc_mem); ++ goto exit_err; ++ } ++ ++ /* register RTC and exit */ ++ register_rtc(&emv3020_rtcops); ++ ++ return 0; ++ ++ exit_err: ++ dev_err(dev, "error %d during initialisation\n", ret); ++ ++ return ret; ++} ++ ++#ifdef CONFIG_PM ++/* EMV3020 RTC Power management control */ ++static int emv3020_rtc_suspend(struct device *dev, pm_message_t state) ++{ ++ return 0; ++} ++ ++static int emv3020_rtc_resume(struct device *dev) ++{ ++ return 0; ++} ++#else ++#define emv3020_rtc_suspend NULL ++#define emv3020_rtc_resume NULL ++#endif ++ ++static struct device_driver emv3020_rtcdrv = { ++ .name = "emv3020-rtc", ++ .bus = &platform_bus_type, ++ .probe = emv3020_rtc_probe, ++ .remove = emv3020_rtc_remove, ++ .suspend = emv3020_rtc_suspend, ++ .resume = emv3020_rtc_resume, ++}; ++ ++static __init int emv3020_init(void) ++{ ++ return driver_register(&emv3020_rtcdrv); ++} ++ ++static __exit void emv3020_exit(void) ++{ ++ driver_unregister(&emv3020_rtcdrv); ++} ++ ++module_init(emv3020_init); ++module_exit(emv3020_exit); ++ ++ ++MODULE_AUTHOR ("Compulab Ltd."); ++MODULE_LICENSE ("GPL"); +diff --git a/drivers/ide/Kconfig b/drivers/ide/Kconfig +index d633081..5e7f6ee 100644 +--- a/drivers/ide/Kconfig ++++ b/drivers/ide/Kconfig +@@ -850,6 +850,13 @@ config BLK_DEV_IDE_BAST + Say Y here if you want to support the onboard IDE channels on the + Simtec BAST or the Thorcom VR1000 + ++config BLK_DEV_IDE_CM_X270 ++ tristate "CompuLab CM-X270 IDE support" ++ depends on ARM && (MACH_ARMCORE) ++ help ++ Say Y here if you want to support the onboard IDE channels on the ++ CompuLab CM-X270 module ++ + config BLK_DEV_GAYLE + bool "Amiga Gayle IDE interface support" + depends on AMIGA +diff --git a/drivers/ide/arm/Makefile b/drivers/ide/arm/Makefile +index 6a78f07..e5cadb7 100644 +--- a/drivers/ide/arm/Makefile ++++ b/drivers/ide/arm/Makefile +@@ -2,5 +2,6 @@ + obj-$(CONFIG_BLK_DEV_IDE_ICSIDE) += icside.o + obj-$(CONFIG_BLK_DEV_IDE_RAPIDE) += rapide.o + obj-$(CONFIG_BLK_DEV_IDE_BAST) += bast-ide.o ++obj-$(CONFIG_BLK_DEV_IDE_CM_X270) += cm-x270-ide.o + + EXTRA_CFLAGS := -Idrivers/ide +diff --git a/drivers/ide/arm/cm-x270-ide.c b/drivers/ide/arm/cm-x270-ide.c +new file mode 100644 +index 0000000..ba0904c +--- /dev/null ++++ b/drivers/ide/arm/cm-x270-ide.c +@@ -0,0 +1,113 @@ ++/* linux/drivers/ide/arm/bast-ide.c ++ * ++ * Copyright (c) 2003-2004 Simtec Electronics ++ * Ben Dooks ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 as ++ * published by the Free Software Foundation. ++ * ++*/ ++ ++#include ++#include ++#include ++#include ++ ++#include ++ ++#include ++#include ++#include ++#include ++ ++/* list of registered interfaces */ ++static ide_hwif_t *ifs[1]; ++ ++static int __init ++cmx270_register(unsigned int base, unsigned int aux, int irq, ++ ide_hwif_t **hwif) ++{ ++ hw_regs_t hw; ++ ++ memset(&hw, 0, sizeof(hw)); ++ ++ if(!base || !aux) return -EINVAL; ++ ++ printk(KERN_DEBUG "%s: base = %08x, aux = %08x\n", __FUNCTION__, ++ base, aux); ++ ++ // Different mappings for local bus IDE and PCMCIA IDE ++ if(base == CMX270_IDECS0_VIRT) { ++#ifdef CONFIG_ARMCORE_SB270 ++ hw.io_ports[IDE_DATA_OFFSET] = base + 0; ++ hw.io_ports[IDE_ERROR_OFFSET] = base + (0x1<<3); ++ hw.io_ports[IDE_NSECTOR_OFFSET]= base + (0x2<<3); ++ hw.io_ports[IDE_SECTOR_OFFSET]= base + (0x3<<3); ++ hw.io_ports[IDE_LCYL_OFFSET]= base + (0x4<<3); ++ hw.io_ports[IDE_HCYL_OFFSET]= base + (0x5<<3); ++ hw.io_ports[IDE_SELECT_OFFSET]= base + (0x6<<3); ++ hw.io_ports[IDE_STATUS_OFFSET]= base + (0x7<<3); ++ ++ hw.io_ports[IDE_CONTROL_OFFSET] = aux+(0x6<<3); ++#else ++ hw.io_ports[IDE_DATA_OFFSET] = base + 0; ++ hw.io_ports[IDE_ERROR_OFFSET] = base + 8; ++ hw.io_ports[IDE_NSECTOR_OFFSET]= base + 2; ++ hw.io_ports[IDE_SECTOR_OFFSET]= base + 10; ++ hw.io_ports[IDE_LCYL_OFFSET]= base + 4; ++ hw.io_ports[IDE_HCYL_OFFSET]= base + 12; ++ hw.io_ports[IDE_SELECT_OFFSET]= base + 6; //6; ++ hw.io_ports[IDE_STATUS_OFFSET]= base + 14; ++ ++ hw.io_ports[IDE_CONTROL_OFFSET] = (aux+0x6); ++#endif ++ } else { ++ printk(KERN_DEBUG "%s: registering wrong IDE i/f\n", __FUNCTION__); ++ hw.io_ports[IDE_DATA_OFFSET] = base + 8; ++ hw.io_ports[IDE_ERROR_OFFSET] = base + 13; ++ hw.io_ports[IDE_NSECTOR_OFFSET] = base + 2; ++ hw.io_ports[IDE_SECTOR_OFFSET] = base + 3; ++ hw.io_ports[IDE_LCYL_OFFSET] = base + 4; ++ hw.io_ports[IDE_HCYL_OFFSET] = base + 5; ++ hw.io_ports[IDE_SELECT_OFFSET] = base + 6; ++ hw.io_ports[IDE_STATUS_OFFSET] = base + 7; ++ ++ hw.io_ports[IDE_CONTROL_OFFSET] = aux; ++ } ++ ++ hw.irq = irq; ++ ++ ide_register_hw(&hw, hwif); ++ ++ return 0; ++} ++ ++static int __init cmx270_init(void) ++{ ++ if (!(machine_is_armcore())) ++ return 0; ++ ++ printk("CM-X270: IDE driver, (c) 2003-2006 CompuLab Ltd\n"); ++ ++ MSC1 = 0x7ffc7ff4; ++ ++ /* Interrupts on rising edge: lines are inverted before they get to ++ the PXA */ ++ pxa_gpio_mode(IRQ_TO_GPIO(CMX270_IDE_IRQ)); ++ ++#ifdef CONFIG_ARMCORE_SB270 ++ set_irq_type(CMX270_IDE_IRQ, IRQT_RISING); ++#else ++ set_irq_type(CMX270_IDE_IRQ, IRQT_FALLING); ++#endif ++ ++ return cmx270_register(CMX270_IDECS0_VIRT, CMX270_IDECS1_VIRT, CMX270_IDE_IRQ, &ifs[0]); ++ return 0; ++} ++ ++module_init(cmx270_init); ++ ++MODULE_AUTHOR("CompuLab"); ++MODULE_LICENSE("GPL"); ++MODULE_DESCRIPTION("CompuLab CM-X270 IDE driver"); +diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig +index 550f297..ed5bb70 100644 +--- a/drivers/mfd/Kconfig ++++ b/drivers/mfd/Kconfig +@@ -23,3 +23,13 @@ config MCP_UCB1200_TS + depends on MCP_UCB1200 && INPUT + + endmenu ++ ++config UCB1400 ++ tristate ++ ++config UCB1400_TS ++ tristate "UCB1400 Touchscreen support" ++ depends on ARCH_LUBBOCK || MACH_MAINSTONE || MACH_ARMCORE ++ select UCB1400 ++ select SND_AC97_BUS ++ +diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile +index adb29b5..24429d1 100644 +--- a/drivers/mfd/Makefile ++++ b/drivers/mfd/Makefile +@@ -10,3 +10,10 @@ obj-$(CONFIG_MCP_UCB1200_TS) += ucb1x00- + ifeq ($(CONFIG_SA1100_ASSABET),y) + obj-$(CONFIG_MCP_UCB1200) += ucb1x00-assabet.o + endif ++ ++ucb1400-core-y := ucb1x00-core.o mcp-ac97.o ++obj-$(CONFIG_UCB1400_TS) += ucb1400-core.o ucb1x00-ts.o ++ ++ucb1400-core-$(CONFIG_UCB1400) := ucb1x00-core.o mcp-ac97.o ++obj-$(CONFIG_UCB1400_TS) += ucb1400-core.o ucb1x00-ts.o ++ +diff --git a/drivers/mfd/mcp-ac97.c b/drivers/mfd/mcp-ac97.c +new file mode 100644 +index 0000000..223f8c2 +--- /dev/null ++++ b/drivers/mfd/mcp-ac97.c +@@ -0,0 +1,151 @@ ++/* ++ * linux/drivers/misc/mcp-ac97.c ++ * ++ * Author: Nicolas Pitre ++ * Created: Jan 14, 2005 ++ * Copyright: (C) MontaVista Software Inc. ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public License ++ * version 2 as published by the Free Software Foundation. ++ * ++ * This module provides the minimum replacement for mcp-core.c allowing for ++ * the UCB1400 chip to be driven by the ucb1x00 driver over an AC97 link. ++ */ ++ ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++ ++#include "mcp.h" ++ ++/* ucb1x00 SIB register to ucb1400 AC-link register mapping */ ++ ++static const unsigned char regmap[] = { ++ 0x5a, /* UCB_IO_DATA */ ++ 0X5C, /* UCB_IO_DIR */ ++ 0X5E, /* UCB_IE_RIS */ ++ 0x60, /* UCB_IE_FAL */ ++ 0x62, /* UCB_IE_STATUS */ ++ 0, /* UCB_TC_A */ ++ 0, /* UCB_TC_B */ ++ 0, /* UCB_AC_A */ ++ 0, /* UCB_AC_B */ ++ 0x64, /* UCB_TS_CR */ ++ 0x66, /* UCB_ADC_CR */ ++ 0x68, /* UCB_ADC_DATA */ ++ 0x7e, /* UCB_ID */ ++ 0, /* UCB_MODE */ ++}; ++ ++unsigned int mcp_reg_read(struct mcp *mcp, unsigned int reg) ++{ ++ ac97_t *ac97 = to_ac97_t(mcp->dev); ++ if (reg < ARRAY_SIZE(regmap)) { ++ reg = regmap[reg]; ++ if (reg) ++ return ac97->bus->ops->read(ac97, reg); ++ } ++ return -1; ++} ++EXPORT_SYMBOL(mcp_reg_read); ++ ++void mcp_reg_write(struct mcp *mcp, unsigned int reg, unsigned int val) ++{ ++ ac97_t *ac97 = to_ac97_t(mcp->dev); ++ if (reg < ARRAY_SIZE(regmap)) { ++ reg = regmap[reg]; ++ if (reg) ++ ac97->bus->ops->write(ac97, reg, val); ++ } ++} ++EXPORT_SYMBOL(mcp_reg_write); ++ ++void mcp_enable(struct mcp *mcp) ++{ ++} ++EXPORT_SYMBOL(mcp_enable); ++ ++void mcp_disable(struct mcp *mcp) ++{ ++} ++EXPORT_SYMBOL(mcp_disable); ++ ++#define to_mcp_driver(d) container_of(d, struct mcp_driver, drv) ++ ++static int mcp_probe(struct device *dev) ++{ ++ struct mcp_driver *drv = to_mcp_driver(dev->driver); ++ struct mcp *mcp; ++ int ret; ++ ++ ret = -ENOMEM; ++ mcp = kmalloc(sizeof(*mcp), GFP_KERNEL); ++ if (mcp) { ++ memset(mcp, 0, sizeof(*mcp)); ++ mcp->owner = THIS_MODULE; ++ mcp->dev = dev; ++ ret = drv->probe(mcp); ++ if (ret) ++ kfree(mcp); ++ } ++ if (!ret) ++ dev_set_drvdata(dev, mcp); ++ return ret; ++} ++ ++static int mcp_remove(struct device *dev) ++{ ++ struct mcp_driver *drv = to_mcp_driver(dev->driver); ++ struct mcp *mcp = dev_get_drvdata(dev); ++ ++ drv->remove(mcp); ++ dev_set_drvdata(dev, NULL); ++ kfree(mcp); ++ return 0; ++} ++ ++static int mcp_suspend(struct device *dev, pm_message_t state) ++{ ++ struct mcp_driver *drv = to_mcp_driver(dev->driver); ++ struct mcp *mcp = dev_get_drvdata(dev); ++ int ret = 0; ++ ++ if (drv->suspend) ++ ret = drv->suspend(mcp, state); ++ return ret; ++} ++ ++static int mcp_resume(struct device *dev) ++{ ++ struct mcp_driver *drv = to_mcp_driver(dev->driver); ++ struct mcp *mcp = dev_get_drvdata(dev); ++ int ret = 0; ++ ++ if (drv->resume) ++ ret = drv->resume(mcp); ++ return ret; ++} ++ ++int mcp_driver_register(struct mcp_driver *mcpdrv) ++{ ++ mcpdrv->drv.owner = THIS_MODULE; ++ mcpdrv->drv.bus = &ac97_bus_type; ++ mcpdrv->drv.probe = mcp_probe; ++ mcpdrv->drv.remove = mcp_remove; ++ mcpdrv->drv.suspend = mcp_suspend; ++ mcpdrv->drv.resume = mcp_resume; ++ return driver_register(&mcpdrv->drv); ++} ++ ++void mcp_driver_unregister(struct mcp_driver *mcpdrv) ++{ ++ driver_unregister(&mcpdrv->drv); ++} ++ ++MODULE_LICENSE("GPL"); +diff --git a/drivers/mfd/mcp-core.c b/drivers/mfd/mcp-core.c +index 75f401d..2a7c176 100644 +--- a/drivers/mfd/mcp-core.c ++++ b/drivers/mfd/mcp-core.c +@@ -208,6 +208,7 @@ struct mcp *mcp_host_alloc(struct device + mcp->attached_device.bus = &mcp_bus_type; + mcp->attached_device.dma_mask = parent->dma_mask; + mcp->attached_device.release = mcp_release; ++ mcp->dev = &mcp->attached_device; + } + return mcp; + } +diff --git a/drivers/mfd/mcp.h b/drivers/mfd/mcp.h +index c093a93..2897d8c 100644 +--- a/drivers/mfd/mcp.h ++++ b/drivers/mfd/mcp.h +@@ -19,11 +19,12 @@ struct mcp { + int use_count; + unsigned int sclk_rate; + unsigned int rw_timeout; +- dma_device_t dma_audio_rd; +- dma_device_t dma_audio_wr; +- dma_device_t dma_telco_rd; +- dma_device_t dma_telco_wr; ++/* dma_device_t dma_audio_rd; */ ++/* dma_device_t dma_audio_wr; */ ++/* dma_device_t dma_telco_rd; */ ++/* dma_device_t dma_telco_wr; */ + struct device attached_device; ++ struct device *dev; + }; + + struct mcp_ops { +diff --git a/drivers/mfd/ucb1x00-core.c b/drivers/mfd/ucb1x00-core.c +index aff83f9..f9a532b 100644 +--- a/drivers/mfd/ucb1x00-core.c ++++ b/drivers/mfd/ucb1x00-core.c +@@ -23,6 +23,7 @@ #include + #include + #include + #include ++#include + #include + #include + +@@ -31,6 +32,12 @@ #include + + #include "ucb1x00.h" + ++#if defined(CONFIG_UCB1400) || defined(CONFIG_UCB1400_MODULE) ++#define UCB_IS_1400(id) ((id) == UCB_ID_1400) ++#else ++#define UCB_IS_1400(id) (0) ++#endif ++ + static DEFINE_MUTEX(ucb1x00_mutex); + static LIST_HEAD(ucb1x00_drivers); + static LIST_HEAD(ucb1x00_devices); +@@ -58,9 +65,9 @@ void ucb1x00_io_set_dir(struct ucb1x00 * + spin_lock_irqsave(&ucb->io_lock, flags); + ucb->io_dir |= out; + ucb->io_dir &= ~in; ++ spin_unlock_irqrestore(&ucb->io_lock, flags); + + ucb1x00_reg_write(ucb, UCB_IO_DIR, ucb->io_dir); +- spin_unlock_irqrestore(&ucb->io_lock, flags); + } + + /** +@@ -86,9 +93,9 @@ void ucb1x00_io_write(struct ucb1x00 *uc + spin_lock_irqsave(&ucb->io_lock, flags); + ucb->io_out |= set; + ucb->io_out &= ~clear; ++ spin_unlock_irqrestore(&ucb->io_lock, flags); + + ucb1x00_reg_write(ucb, UCB_IO_DATA, ucb->io_out); +- spin_unlock_irqrestore(&ucb->io_lock, flags); + } + + /** +@@ -178,7 +185,7 @@ unsigned int ucb1x00_adc_read(struct ucb + schedule_timeout(1); + } + +- return UCB_ADC_DAT(val); ++ return UCB_IS_1400(ucb->id) ? (val & 0x3ff) : ((val & 0x7fe0) >> 5); + } + + /** +@@ -223,6 +230,47 @@ static irqreturn_t ucb1x00_irq(int irqnr + return IRQ_HANDLED; + } + ++/* ++ * A restriction with interrupts exists when using the ucb1400, as ++ * the codec read/write routines may sleep while waiting for codec ++ * access completion and uses semaphores for access control to the ++ * AC97 bus. A complete codec read cycle could take anywhere from ++ * 60 to 100uSec so we *definitely* don't want to spin inside the ++ * interrupt handler waiting for codec access. So, we handle the ++ * interrupt by scheduling a RT kernel thread to run in process ++ * context instead of interrupt context. ++ */ ++static int ucb1x00_thread(void *_ucb) ++{ ++ struct task_struct *tsk = current; ++ struct ucb1x00 *ucb = _ucb; ++ ++ tsk->policy = SCHED_FIFO; ++ tsk->rt_priority = 1; ++ ++ while (!kthread_should_stop()) { ++ wait_for_completion_interruptible(&ucb->irq_wait); ++ if (try_to_freeze()) ++ continue; ++ ucb1x00_irq(ucb->irq, ucb, NULL); ++ enable_irq(ucb->irq); ++ } ++ ++ ucb->irq_task = NULL; ++ return 0; ++} ++ ++static irqreturn_t ucb1x00_threaded_irq(int irqnr, void *devid, struct pt_regs *regs) ++{ ++ struct ucb1x00 *ucb = devid; ++ if (irqnr == ucb->irq) { ++ disable_irq(ucb->irq); ++ complete(&ucb->irq_wait); ++ return IRQ_HANDLED; ++ } ++ return IRQ_NONE; ++} ++ + /** + * ucb1x00_hook_irq - hook a UCB1x00 interrupt + * @ucb: UCB1x00 structure describing chip +@@ -276,18 +324,22 @@ void ucb1x00_enable_irq(struct ucb1x00 * + + if (idx < 16) { + spin_lock_irqsave(&ucb->lock, flags); +- +- ucb1x00_enable(ucb); +- if (edges & UCB_RISING) { ++ if (edges & UCB_RISING) + ucb->irq_ris_enbl |= 1 << idx; +- ucb1x00_reg_write(ucb, UCB_IE_RIS, ucb->irq_ris_enbl); +- } +- if (edges & UCB_FALLING) { ++ if (edges & UCB_FALLING) + ucb->irq_fal_enbl |= 1 << idx; +- ucb1x00_reg_write(ucb, UCB_IE_FAL, ucb->irq_fal_enbl); +- } +- ucb1x00_disable(ucb); + spin_unlock_irqrestore(&ucb->lock, flags); ++ ++ ucb1x00_enable(ucb); ++ ++ /* This prevents spurious interrupts on the UCB1400 */ ++ ucb1x00_reg_write(ucb, UCB_IE_CLEAR, 1 << idx); ++ ucb1x00_reg_write(ucb, UCB_IE_CLEAR, 0); ++ ++ ucb1x00_reg_write(ucb, UCB_IE_RIS, ucb->irq_ris_enbl); ++ ucb1x00_reg_write(ucb, UCB_IE_FAL, ucb->irq_fal_enbl); ++ ++ ucb1x00_disable(ucb); + } + } + +@@ -305,18 +357,16 @@ void ucb1x00_disable_irq(struct ucb1x00 + + if (idx < 16) { + spin_lock_irqsave(&ucb->lock, flags); +- +- ucb1x00_enable(ucb); +- if (edges & UCB_RISING) { ++ if (edges & UCB_RISING) + ucb->irq_ris_enbl &= ~(1 << idx); +- ucb1x00_reg_write(ucb, UCB_IE_RIS, ucb->irq_ris_enbl); +- } +- if (edges & UCB_FALLING) { ++ if (edges & UCB_FALLING) + ucb->irq_fal_enbl &= ~(1 << idx); +- ucb1x00_reg_write(ucb, UCB_IE_FAL, ucb->irq_fal_enbl); +- } +- ucb1x00_disable(ucb); + spin_unlock_irqrestore(&ucb->lock, flags); ++ ++ ucb1x00_enable(ucb); ++ ucb1x00_reg_write(ucb, UCB_IE_RIS, ucb->irq_ris_enbl); ++ ucb1x00_reg_write(ucb, UCB_IE_FAL, ucb->irq_fal_enbl); ++ ucb1x00_disable(ucb); + } + } + +@@ -349,16 +399,17 @@ int ucb1x00_free_irq(struct ucb1x00 *ucb + ucb->irq_ris_enbl &= ~(1 << idx); + ucb->irq_fal_enbl &= ~(1 << idx); + +- ucb1x00_enable(ucb); +- ucb1x00_reg_write(ucb, UCB_IE_RIS, ucb->irq_ris_enbl); +- ucb1x00_reg_write(ucb, UCB_IE_FAL, ucb->irq_fal_enbl); +- ucb1x00_disable(ucb); +- + irq->fn = NULL; + irq->devid = NULL; + ret = 0; + } + spin_unlock_irq(&ucb->lock); ++ ++ ucb1x00_enable(ucb); ++ ucb1x00_reg_write(ucb, UCB_IE_RIS, ucb->irq_ris_enbl); ++ ucb1x00_reg_write(ucb, UCB_IE_FAL, ucb->irq_fal_enbl); ++ ucb1x00_disable(ucb); ++ + return ret; + + bad: +@@ -478,7 +529,7 @@ static int ucb1x00_probe(struct mcp *mcp + mcp_enable(mcp); + id = mcp_reg_read(mcp, UCB_ID); + +- if (id != UCB_ID_1200 && id != UCB_ID_1300) { ++ if (id != UCB_ID_1200 && id != UCB_ID_1300 && !UCB_IS_1400(id)) { + printk(KERN_WARNING "UCB1x00 ID not found: %04x\n", id); + goto err_disable; + } +@@ -491,12 +542,13 @@ static int ucb1x00_probe(struct mcp *mcp + memset(ucb, 0, sizeof(struct ucb1x00)); + + ucb->cdev.class = &ucb1x00_class; +- ucb->cdev.dev = &mcp->attached_device; ++ ucb->cdev.dev = mcp->dev; + strlcpy(ucb->cdev.class_id, "ucb1x00", sizeof(ucb->cdev.class_id)); + + spin_lock_init(&ucb->lock); + spin_lock_init(&ucb->io_lock); + sema_init(&ucb->adc_sem, 1); ++ init_completion(&ucb->irq_wait); + + ucb->id = id; + ucb->mcp = mcp; +@@ -507,13 +559,22 @@ static int ucb1x00_probe(struct mcp *mcp + goto err_free; + } + +- ret = request_irq(ucb->irq, ucb1x00_irq, SA_TRIGGER_RISING, +- "UCB1x00", ucb); ++ ret = request_irq(ucb->irq, ++ UCB_IS_1400(id) ? ucb1x00_threaded_irq : ucb1x00_irq, ++ SA_TRIGGER_RISING, "UCB1x00", ucb); + if (ret) { + printk(KERN_ERR "ucb1x00: unable to grab irq%d: %d\n", + ucb->irq, ret); + goto err_free; + } ++ if (UCB_IS_1400(id)) { ++ ucb->irq_task = kthread_run(ucb1x00_thread, ucb, "kUCB1x00d"); ++ if (IS_ERR(ucb->irq_task)) { ++ ret = PTR_ERR(ucb->irq_task); ++ ucb->irq_task = NULL; ++ goto err_irq; ++ } ++ } + + mcp_set_drvdata(mcp, ucb); + +@@ -531,6 +592,8 @@ static int ucb1x00_probe(struct mcp *mcp + goto out; + + err_irq: ++ if (UCB_IS_1400(id) && ucb->irq_task) ++ kthread_stop(ucb->irq_task); + free_irq(ucb->irq, ucb); + err_free: + kfree(ucb); +@@ -553,6 +616,10 @@ static void ucb1x00_remove(struct mcp *m + } + mutex_unlock(&ucb1x00_mutex); + ++ if (UCB_IS_1400(ucb->id) && ucb->irq_task) { ++ complete(&ucb->irq_wait); ++ kthread_stop(ucb->irq_task); ++ } + free_irq(ucb->irq, ucb); + class_device_unregister(&ucb->cdev); + } +diff --git a/drivers/mfd/ucb1x00-ts.c b/drivers/mfd/ucb1x00-ts.c +index 79fd062..e68132d 100644 +--- a/drivers/mfd/ucb1x00-ts.c ++++ b/drivers/mfd/ucb1x00-ts.c +@@ -35,7 +35,15 @@ #include + + #include + #include ++ ++/* FIXME: proper machine detection should be implemented */ ++#ifdef CONFIG_SA1100_COLLIE + #include ++#else ++#define machine_is_collie() (0) ++#define COLLIE_TC35143_GPIO_TBL_CHK (0) ++#endif ++ + #include + + #include "ucb1x00.h" +@@ -45,7 +53,7 @@ struct ucb1x00_ts { + struct input_dev *idev; + struct ucb1x00 *ucb; + +- wait_queue_head_t irq_wait; ++ struct completion irq_wait; + struct task_struct *rtask; + u16 x_res; + u16 y_res; +@@ -98,7 +106,8 @@ static inline unsigned int ucb1x00_ts_re + udelay(55); + + return ucb1x00_adc_read(ts->ucb, UCB_ADC_INP_AD2, ts->adcsync); +- } else { ++ } ++ else { + ucb1x00_reg_write(ts->ucb, UCB_TS_CR, + UCB_TS_CR_TSMX_POW | UCB_TS_CR_TSPX_POW | + UCB_TS_CR_TSMY_GND | UCB_TS_CR_TSPY_GND | +@@ -205,7 +214,6 @@ static int ucb1x00_thread(void *_ts) + { + struct ucb1x00_ts *ts = _ts; + struct task_struct *tsk = current; +- DECLARE_WAITQUEUE(wait, tsk); + int valid; + + /* +@@ -217,10 +225,8 @@ static int ucb1x00_thread(void *_ts) + + valid = 0; + +- add_wait_queue(&ts->irq_wait, &wait); + while (!kthread_should_stop()) { + unsigned int x, y, p; +- signed long timeout; + + ts->restart = 0; + +@@ -242,8 +248,6 @@ static int ucb1x00_thread(void *_ts) + + + if (ucb1x00_ts_pen_down(ts)) { +- set_task_state(tsk, TASK_INTERRUPTIBLE); +- + ucb1x00_enable_irq(ts->ucb, UCB_IRQ_TSPX, machine_is_collie() ? UCB_RISING : UCB_FALLING); + ucb1x00_disable(ts->ucb); + +@@ -256,7 +260,15 @@ static int ucb1x00_thread(void *_ts) + valid = 0; + } + +- timeout = MAX_SCHEDULE_TIMEOUT; ++ /* ++ * Since ucb1x00_enable_irq() might sleep due ++ * to the way the UCB1400 regs are accessed, we ++ * can't use set_task_state() before that call, ++ * and not changing state before enabling the ++ * interrupt is racy. A completion handler avoids ++ * the issue. ++ */ ++ wait_for_completion_interruptible(&ts->irq_wait); + } else { + ucb1x00_disable(ts->ucb); + +@@ -271,16 +283,12 @@ static int ucb1x00_thread(void *_ts) + } + + set_task_state(tsk, TASK_INTERRUPTIBLE); +- timeout = HZ / 100; ++ schedule_timeout(HZ/100); + } + + try_to_freeze(); +- +- schedule_timeout(timeout); + } + +- remove_wait_queue(&ts->irq_wait, &wait); +- + ts->rtask = NULL; + return 0; + } +@@ -293,7 +301,7 @@ static void ucb1x00_ts_irq(int idx, void + { + struct ucb1x00_ts *ts = id; + ucb1x00_disable_irq(ts->ucb, UCB_IRQ_TSPX, UCB_FALLING); +- wake_up(&ts->irq_wait); ++ complete(&ts->irq_wait); + } + + static int ucb1x00_ts_open(struct input_dev *idev) +@@ -303,7 +311,7 @@ static int ucb1x00_ts_open(struct input_ + + BUG_ON(ts->rtask); + +- init_waitqueue_head(&ts->irq_wait); ++ init_completion(&ts->irq_wait); + ret = ucb1x00_hook_irq(ts->ucb, UCB_IRQ_TSPX, ucb1x00_ts_irq, ts); + if (ret < 0) + goto out; +@@ -337,8 +345,10 @@ static void ucb1x00_ts_close(struct inpu + { + struct ucb1x00_ts *ts = idev->private; + +- if (ts->rtask) ++ if (ts->rtask) { ++ complete(&ts->irq_wait); + kthread_stop(ts->rtask); ++ } + + ucb1x00_enable(ts->ucb); + ucb1x00_free_irq(ts->ucb, UCB_IRQ_TSPX, ts); +@@ -358,7 +368,7 @@ static int ucb1x00_ts_resume(struct ucb1 + * after sleep. + */ + ts->restart = 1; +- wake_up(&ts->irq_wait); ++ complete(&ts->irq_wait); + } + return 0; + } +diff --git a/drivers/mfd/ucb1x00.h b/drivers/mfd/ucb1x00.h +index 9c9a647..ff04dc9 100644 +--- a/drivers/mfd/ucb1x00.h ++++ b/drivers/mfd/ucb1x00.h +@@ -94,6 +94,7 @@ #define UCB_ADC_DAT(x) (((x) & 0x7fe0) + #define UCB_ID 0x0c + #define UCB_ID_1200 0x1004 + #define UCB_ID_1300 0x1005 ++#define UCB_ID_1400 0x4304 + + #define UCB_MODE 0x0d + #define UCB_MODE_DYN_VFLAG_ENA (1 << 12) +@@ -110,6 +111,8 @@ struct ucb1x00 { + spinlock_t lock; + struct mcp *mcp; + unsigned int irq; ++ struct task_struct *irq_task; ++ struct completion irq_wait; + struct semaphore adc_sem; + spinlock_t io_lock; + u16 id; +@@ -122,6 +125,7 @@ struct ucb1x00 { + struct class_device cdev; + struct list_head node; + struct list_head devs; ++ + }; + + struct ucb1x00_driver; +diff --git a/drivers/mtd/nand/cmx270-nand.c b/drivers/mtd/nand/cmx270-nand.c +new file mode 100644 +index 0000000..fb37d6d +--- /dev/null ++++ b/drivers/mtd/nand/cmx270-nand.c +@@ -0,0 +1,291 @@ ++/* ++ * drivers/mtd/nand/cmx270-nand.c ++ * ++ * Copyright (C) 2005 Compulab, Ltd. (mike@compulab.co.il) ++ * ++ * Derived from drivers/mtd/nand/h1910.c ++ * Copyright (C) 2002 Marius Gröger (mag@sysgo.de) ++ * Copyright (c) 2001 Thomas Gleixner (gleixner@autronix.de) ++ * ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 as ++ * published by the Free Software Foundation. ++ * ++ * Overview: ++ * This is a device driver for the NAND flash device found on the ++ * CM-X270 board. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++ ++#define NAND_CS_ON (GPCR0 = (1<<11)) ++#define NAND_CS_OFF (GPSR0 = (1<<11)) ++#define NAND_RB (GPLR2 & (1<<25)) ++ ++/* ++ * MTD structure for CM-X270 board ++ */ ++static struct mtd_info *cmx270_nand_mtd = NULL; ++ ++/* ++ * Module stuff ++ */ ++ ++#ifdef CONFIG_MTD_PARTITIONS ++/* ++ * Define static partitions for flash device ++ */ ++static struct mtd_partition partition_info[] = { ++/* { */ ++/* name: "cmx270-0", */ ++/* offset: 0, */ ++/* size: 2*1024*1024 */ ++/* }, */ ++ { ++ name: "cmx270-0", ++ offset: 0, ++ size: MTDPART_SIZ_FULL ++ } ++}; ++#define NUM_PARTITIONS 1 ++ ++#endif ++ ++ ++static u_char cmx270_read_byte(struct mtd_info *mtd) ++{ ++ struct nand_chip *this = mtd->priv; ++ volatile u_long* addr = (volatile u_long*)this->IO_ADDR_R; ++ u_long word = *addr; ++ ++/* printk(KERN_DEBUG "%s: addr = %p, byte = %x, byte_shift = %x\n", */ ++/* __FUNCTION__, addr, word, (word >> 16)); */ ++ ++ return (unsigned char)(word >> 16); ++/* return (unsigned char)(*addr >> 16); */ ++} ++ ++static void cmx270_write_byte(struct mtd_info *mtd, u_char byte) ++{ ++ struct nand_chip *this = mtd->priv; ++ volatile u_long* addr = (volatile u_long*)this->IO_ADDR_R; ++ ++/* printk(KERN_DEBUG "%s: addr = %p, byte = %x, byte_shift = %x\n", */ ++/* __FUNCTION__, addr, byte, (byte << 16)); */ ++ ++ *addr = (byte << 16); ++} ++ ++static void cmx270_write_buf(struct mtd_info *mtd, const u_char *buf, int len) ++{ ++ int i; ++ struct nand_chip *this = mtd->priv; ++ volatile u_long* addr = (volatile u_long*)this->IO_ADDR_R; ++ u_long value; ++ ++ for (i=0; ipriv; ++ volatile u_long* addr = (volatile u_long*)this->IO_ADDR_R; ++/* u_long value; */ ++ ++ for (i=0; i> 16); ++/* value = *addr; */ ++/* buf[i] = (u_char)((value & 0x000000ff)); */ ++ } ++} ++ ++static int cmx270_verify_buf(struct mtd_info *mtd, const u_char *buf, int len) ++{ ++ int i; ++ struct nand_chip *this = mtd->priv; ++ volatile u_long* addr = (volatile u_long*)this->IO_ADDR_R; ++ u_long value; ++ ++/* for (i=0; ipriv); ++ unsigned int nandaddr = (unsigned int)this->IO_ADDR_R; ++ ++ switch(cmd) { ++ ++ case NAND_CTL_SETCLE: ++ nandaddr |= (1 << 2); ++ this->IO_ADDR_R = (void __iomem*)nandaddr; ++ this->IO_ADDR_W = (void __iomem*)nandaddr; ++ break; ++ case NAND_CTL_CLRCLE: ++ nandaddr &= ~(1 << 2); ++ this->IO_ADDR_R = (void __iomem*)nandaddr; ++ this->IO_ADDR_W = (void __iomem*)nandaddr; ++ break; ++ ++ case NAND_CTL_SETALE: ++ nandaddr |= (1 << 3); ++ this->IO_ADDR_R = (void __iomem*)nandaddr; ++ this->IO_ADDR_W = (void __iomem*)nandaddr; ++ break; ++ case NAND_CTL_CLRALE: ++ nandaddr &= ~(1 << 3); ++ this->IO_ADDR_R = (void __iomem*)nandaddr; ++ this->IO_ADDR_W = (void __iomem*)nandaddr; ++ break; ++ ++ case NAND_CTL_SETNCE: ++ NAND_CS_ON; ++ break; ++ case NAND_CTL_CLRNCE: ++ NAND_CS_OFF; ++ break; ++ } ++} ++ ++/* ++ * read device ready pin ++ */ ++static int cmx270_device_ready(struct mtd_info *mtd) ++{ ++/* volatile cpm2_map_t *immap = (volatile cpm2_map_t *)CPM_MAP_ADDR; */ ++/* return ((immap->im_ioport.iop_pdatd & NAND_RDY) != 0); */ ++ ++ return ( NAND_RB != 0 ); ++} ++ ++/* ++ * Main initialization routine ++ */ ++static int __init cmx270_init (void) ++{ ++ struct nand_chip *this; ++ const char *part_type = 0; ++ int mtd_parts_nb = 0; ++ struct mtd_partition *mtd_parts = 0; ++ static unsigned int nandaddr = 0; ++ ++ ++ /* Allocate memory for MTD device structure and private data */ ++ cmx270_nand_mtd = kmalloc(sizeof(struct mtd_info) + ++ sizeof(struct nand_chip), ++ GFP_KERNEL); ++ if (!cmx270_nand_mtd) { ++ printk("Unable to allocate CM-X270 NAND MTD device structure.\n"); ++ return -ENOMEM; ++ } ++ ++ nandaddr = (volatile unsigned long*)ARMCORE_CS1_VIRT; ++ ++ /* Get pointer to private data */ ++ this = (struct nand_chip *) (&cmx270_nand_mtd[1]); ++ ++ /* Initialize structures */ ++ memset((char *) cmx270_nand_mtd, 0, sizeof(struct mtd_info)); ++ memset((char *) this, 0, sizeof(struct nand_chip)); ++ ++/* pxa_gpio_mode(89 | GPIO_IN ); */ ++ printk(KERN_WARNING "%s: PSSR = %x\n", __FUNCTION__, PSSR); ++ printk(KERN_WARNING "%s: GPDR2 = %x\n", __FUNCTION__, GPDR2); ++ printk(KERN_WARNING "%s: GRER2 = %x\n", __FUNCTION__, GRER2); ++ printk(KERN_WARNING "%s: GAFR2_U = %x\n", __FUNCTION__, GAFR2_U); ++ printk(KERN_WARNING "%s: GPLR2 = %x\n", __FUNCTION__, GPLR2); ++ printk(KERN_WARNING "%s: GEDR2 = %x\n", __FUNCTION__, GEDR2); ++ ++ /* Link the private data with the MTD structure */ ++ cmx270_nand_mtd->priv = this; ++ ++ /* insert callbacks */ ++ this->IO_ADDR_R = (void __iomem *)nandaddr; ++ this->IO_ADDR_W = (void __iomem *)nandaddr; ++ this->hwcontrol = cmx270_hwcontrol; ++/* this->dev_ready = cmx270_device_ready; /\* unknown whether that was correct or not so we will just do it like this *\/ */ ++ ++ /* 15 us command delay time */ ++ this->chip_delay = 50; ++ this->eccmode = NAND_ECC_SOFT; ++ ++ /* read/write functions */ ++ this->read_byte = cmx270_read_byte; ++ this->write_byte = cmx270_write_byte; ++ this->read_buf = cmx270_read_buf; ++ this->write_buf = cmx270_write_buf; ++ this->verify_buf = cmx270_verify_buf; ++ ++ /* Scan to find existence of the device */ ++ if (nand_scan (cmx270_nand_mtd, 1)) { ++ printk(KERN_NOTICE "No NAND device - returning -ENXIO\n"); ++ kfree (cmx270_nand_mtd); ++ return -ENXIO; ++ } ++ ++#ifdef CONFIG_MTD_CMDLINE_PARTS ++ mtd_parts_nb = parse_cmdline_partitions(cmx270_nand_mtd, &mtd_parts, ++ "cmx270"); ++ if (mtd_parts_nb > 0) ++ part_type = "command line"; ++ else ++ mtd_parts_nb = 0; ++#endif ++ if (mtd_parts_nb == 0) ++ { ++ mtd_parts = partition_info; ++ mtd_parts_nb = NUM_PARTITIONS; ++ part_type = "static"; ++ } ++ ++ /* Register the partitions */ ++ printk(KERN_NOTICE "Using %s partition definition\n", part_type); ++ add_mtd_partitions(cmx270_nand_mtd, mtd_parts, mtd_parts_nb); ++ ++ /* Return happy */ ++ return 0; ++} ++module_init(cmx270_init); ++ ++/* ++ * Clean up routine ++ */ ++static void __exit cmx270_cleanup (void) ++{ ++ /* Release resources, unregister device */ ++ nand_release (cmx270_nand_mtd); ++ ++ /* Free the MTD device structure */ ++ kfree (cmx270_nand_mtd); ++} ++module_exit(cmx270_cleanup); ++ ++MODULE_LICENSE("GPL"); ++MODULE_AUTHOR("Mike Rapoport "); ++MODULE_DESCRIPTION("NAND flash driver for Compulab CM-X270 Core"); +diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig +index aa633fa..505f92b 100644 +--- a/drivers/net/Kconfig ++++ b/drivers/net/Kconfig +@@ -865,6 +865,14 @@ config DM9000 + . The module will be + called dm9000. + ++config DM9000_NOEPROM ++ bool "DM9000 without EEPROM attached" ++ depends on DM9000 ++ ---help--- ++ Select this option if you have DM9000 chipset without EEPROM ++ containing the MAC address. In this case MAC address should ++ be set either by the bootloader or using ifconfig ++ + config NET_VENDOR_RACAL + bool "Racal-Interlan (Micom) NI cards" + depends on NET_ETHERNET && ISA +diff --git a/drivers/net/dm9000.c b/drivers/net/dm9000.c +index 24996da..7e45756 100644 +--- a/drivers/net/dm9000.c ++++ b/drivers/net/dm9000.c +@@ -561,8 +561,14 @@ #endif + ((u16 *) db->srom)[i] = read_srom_word(db, i); + + /* Set Node Address */ ++#ifndef CONFIG_DM9000_NOEPROM + for (i = 0; i < 6; i++) + ndev->dev_addr[i] = db->srom[i]; ++#else ++ /* The Node Address was set by bootloader */ ++ for (i=0; i<6; i++) ++ ndev->dev_addr[i] = ior(db, 0x10+i); ++#endif + + if (!is_valid_ether_addr(ndev->dev_addr)) + printk("%s: Invalid ethernet MAC address. Please " +@@ -1098,6 +1104,10 @@ dm9000_phy_read(struct net_device *dev, + /* The read data keeps on REG_0D & REG_0E */ + ret = (ior(db, DM9000_EPDRH) << 8) | ior(db, DM9000_EPDRL); + ++/* if ( reg == MII_BMSR ) { */ ++/* printk(KERN_WARNING "===> %s: ret = %x\n", __FUNCTION__, ret); */ ++/* } */ ++ + /* restore the previous address */ + writeb(reg_save, db->io_addr); + +@@ -1163,7 +1173,6 @@ dm9000_drv_resume(struct platform_device + if (netif_running(ndev)) { + dm9000_reset(db); + dm9000_init_dm9000(ndev); +- + netif_device_attach(ndev); + } + } +diff --git a/drivers/pcmcia/Makefile b/drivers/pcmcia/Makefile +index bcecf51..b6a4173 100644 +--- a/drivers/pcmcia/Makefile ++++ b/drivers/pcmcia/Makefile +@@ -68,4 +68,4 @@ sa1100_cs-$(CONFIG_SA1100_SIMPAD) += sa + pxa2xx_cs-$(CONFIG_ARCH_LUBBOCK) += pxa2xx_lubbock.o sa1111_generic.o + pxa2xx_cs-$(CONFIG_MACH_MAINSTONE) += pxa2xx_mainstone.o + pxa2xx_cs-$(CONFIG_PXA_SHARPSL) += pxa2xx_sharpsl.o +- ++pxa2xx_cs-$(CONFIG_MACH_ARMCORE) += pxa2xx_cm_x270.o +diff --git a/drivers/pcmcia/pxa2xx_cm_x270.c b/drivers/pcmcia/pxa2xx_cm_x270.c +new file mode 100644 +index 0000000..eb4df11 +--- /dev/null ++++ b/drivers/pcmcia/pxa2xx_cm_x270.c +@@ -0,0 +1,198 @@ ++/* ++ * linux/drivers/pcmcia/pxa/pxa_armcore.c ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 as ++ * published by the Free Software Foundation. ++ * ++ * Compulab Ltd., 2003 ++ * ++ */ ++ ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++ ++#include ++#include ++ ++#include "soc_common.h" ++ ++ ++static struct pcmcia_irqs irqs[] = { ++ { 0, PCMCIA_S0_CD_VALID, "PCMCIA0 CD" }, ++ { 1, PCMCIA_S1_CD_VALID, "PCMCIA1 CD" }, ++}; ++ ++ ++static int ++cmx270_pcmcia_hw_init(struct soc_pcmcia_socket *skt) ++{ ++ int return_val=0; ++ ++ GPSR(GPIO48_nPOE) = GPIO_bit(GPIO48_nPOE) | ++ GPIO_bit(GPIO49_nPWE) | ++ GPIO_bit(GPIO50_nPIOR) | ++ GPIO_bit(GPIO51_nPIOW) | ++ GPIO_bit(GPIO85_nPCE_1) | ++ GPIO_bit(GPIO54_nPCE_2); ++ ++ pxa_gpio_mode(GPIO48_nPOE_MD); ++ pxa_gpio_mode(GPIO49_nPWE_MD); ++ pxa_gpio_mode(GPIO50_nPIOR_MD); ++ pxa_gpio_mode(GPIO51_nPIOW_MD); ++ pxa_gpio_mode(GPIO85_nPCE_1_MD); ++ pxa_gpio_mode(GPIO54_nPCE_2_MD); ++ //pxa_gpio_mode(GPIO79_pSKTSEL_MD); /* REVISIT: s/b dependent on num sockets (on ATX base not routed)*/ ++ pxa_gpio_mode(GPIO55_nPREG_MD); ++ pxa_gpio_mode(GPIO56_nPWAIT_MD); ++ pxa_gpio_mode(GPIO57_nIOIS16_MD); ++ ++ // Reset signal ++ GPDR(GPIO53_nPCE_2) |= GPIO_bit(GPIO53_nPCE_2); ++ GPCR(GPIO53_nPCE_2) = GPIO_bit(GPIO53_nPCE_2); ++ ++ GPDR(IRQ_TO_GPIO(PCMCIA_S0_CD_VALID)) &= ~GPIO_bit(IRQ_TO_GPIO(PCMCIA_S0_CD_VALID)); ++ GPDR(IRQ_TO_GPIO(PCMCIA_S1_CD_VALID)) &= ~GPIO_bit(IRQ_TO_GPIO(PCMCIA_S1_CD_VALID)); ++ ++ set_irq_type(PCMCIA_S0_CD_VALID, IRQT_BOTHEDGE); ++ set_irq_type(PCMCIA_S1_CD_VALID, IRQT_BOTHEDGE); ++ ++ //irq's for slots: ++ GPDR(IRQ_TO_GPIO(PCMCIA_S0_RDYINT)) &= ~GPIO_bit(IRQ_TO_GPIO(PCMCIA_S0_RDYINT)); ++ GPDR(IRQ_TO_GPIO(PCMCIA_S1_RDYINT)) &= ~GPIO_bit(IRQ_TO_GPIO(PCMCIA_S1_RDYINT)); ++ ++ set_irq_type(PCMCIA_S0_RDYINT, IRQT_FALLING); ++ set_irq_type(PCMCIA_S1_RDYINT, IRQT_FALLING); ++ ++ skt->irq = (skt->nr == 0) ? PCMCIA_S0_RDYINT : PCMCIA_S1_RDYINT; ++ return_val = soc_pcmcia_request_irqs(skt, irqs, ARRAY_SIZE(irqs)); ++ ++ return return_val; ++} ++ ++ ++static void cmx270_pcmcia_shutdown(struct soc_pcmcia_socket *skt) ++{ ++ soc_pcmcia_free_irqs(skt, irqs, ARRAY_SIZE(irqs)); ++ ++ set_irq_type(IRQ_TO_GPIO(PCMCIA_S0_CD_VALID), IRQT_NOEDGE); ++ set_irq_type(IRQ_TO_GPIO(PCMCIA_S1_CD_VALID), IRQT_NOEDGE); ++ ++ set_irq_type(IRQ_TO_GPIO(PCMCIA_S0_RDYINT), IRQT_NOEDGE); ++ set_irq_type(IRQ_TO_GPIO(PCMCIA_S1_RDYINT), IRQT_NOEDGE); ++} ++ ++ ++static void cmx270_pcmcia_socket_state(struct soc_pcmcia_socket *skt, ++ struct pcmcia_state *state) ++{ ++ ++ state->detect = (PCC_DETECT(skt->nr) == 0) ? 1 : 0; ++ state->ready = (PCC_READY(skt->nr) == 0) ? 0 : 1; ++ state->bvd1 = 1; ++ state->bvd2 = 1; ++ state->vs_3v = 0; ++ state->vs_Xv = 0; ++ state->wrprot = 0; /* not available */ ++ ++} ++ ++ ++static int ++cmx270_pcmcia_configure_socket(struct soc_pcmcia_socket *skt, ++ const socket_state_t *state) ++{ ++ ++ GPSR(GPIO49_nPWE) = GPIO_bit(GPIO49_nPWE); ++ pxa_gpio_mode(GPIO49_nPWE | GPIO_OUT); ++ //pxa_gpio_mode(GPIO79_pSKTSEL_MD | GPIO_OUT); /* For 2-socket mode */ ++ ++ switch(skt->nr){ ++ case 0: ++ if(state->flags & SS_RESET) { ++ //GPCR(GPIO79_pSKTSEL) = GPIO_bit(GPIO79_pSKTSEL); /* For 2-socket mode */ ++ //udelay(1); ++ GPCR(GPIO49_nPWE) = GPIO_bit(GPIO49_nPWE); ++ GPSR(GPIO53_nPCE_2) = GPIO_bit(GPIO53_nPCE_2); ++ udelay(10); ++ GPCR(GPIO53_nPCE_2) = GPIO_bit(GPIO53_nPCE_2); ++ GPSR(GPIO49_nPWE) = GPIO_bit(GPIO49_nPWE); ++ } ++ break; ++ case 1: ++ if(state->flags & SS_RESET) { ++ //GPCR(GPIO79_pSKTSEL) = GPIO_bit(GPIO79_pSKTSEL); /* For 2-socket mode */ ++ //udelay(1); ++ GPCR(GPIO49_nPWE) = GPIO_bit(GPIO49_nPWE); ++ GPSR(GPIO53_nPCE_2) = GPIO_bit(GPIO53_nPCE_2); ++ udelay(10); ++ GPCR(GPIO53_nPCE_2) = GPIO_bit(GPIO53_nPCE_2); ++ GPSR(GPIO49_nPWE) = GPIO_bit(GPIO49_nPWE); ++ } ++ break; ++ } ++ ++ pxa_gpio_mode(GPIO49_nPWE_MD); ++ //pxa_gpio_mode(GPIO79_pSKTSEL_MD); /* For 2-socket mode */ ++ ++ ++ return 0; ++} ++ ++static void cmx270_pcmcia_socket_init(struct soc_pcmcia_socket *skt) ++{ ++} ++ ++static void cmx270_pcmcia_socket_suspend(struct soc_pcmcia_socket *skt) ++{ ++} ++ ++ ++static struct pcmcia_low_level cmx270_pcmcia_ops = { ++ .owner = THIS_MODULE, ++ .hw_init = cmx270_pcmcia_hw_init, ++ .hw_shutdown = cmx270_pcmcia_shutdown, ++ .socket_state = cmx270_pcmcia_socket_state, ++ .configure_socket = cmx270_pcmcia_configure_socket, ++ .socket_init = cmx270_pcmcia_socket_init, ++ .socket_suspend = cmx270_pcmcia_socket_suspend, ++ .nr = 2, ++}; ++ ++static struct platform_device *cmx270_pcmcia_device; ++ ++static int __init cmx270_pcmcia_init(void) ++{ ++ int ret; ++ ++ cmx270_pcmcia_device = platform_device_alloc("pxa2xx-pcmcia", -1); ++ ++ if (!cmx270_pcmcia_device) ++ return -ENOMEM; ++ ++ cmx270_pcmcia_device->dev.platform_data = &cmx270_pcmcia_ops; ++ ++ printk ("Registering cm-x270 PCMCIA interface.\n"); ++ ret = platform_device_add(cmx270_pcmcia_device); ++ ++ if (ret) ++ platform_device_put(cmx270_pcmcia_device); ++ ++ return ret; ++} ++ ++static void __exit cmx270_pcmcia_exit(void) ++{ ++ platform_device_unregister(cmx270_pcmcia_device); ++} ++ ++module_init(cmx270_pcmcia_init); ++module_exit(cmx270_pcmcia_exit); ++ ++MODULE_LICENSE("GPL"); +diff --git a/drivers/serial/pxa.c b/drivers/serial/pxa.c +index 10535f0..e04624f 100644 +--- a/drivers/serial/pxa.c ++++ b/drivers/serial/pxa.c +@@ -49,6 +49,8 @@ #include + #include + #include + ++#define SERIAL_SA1100_MAJOR 204 ++#define MINOR_START 5 + + struct uart_pxa_port { + struct uart_port port; +@@ -683,7 +685,7 @@ serial_pxa_console_setup(struct console + } + + static struct console serial_pxa_console = { +- .name = "ttyS", ++ .name = "ttySA", + .write = serial_pxa_console_write, + .device = uart_console_device, + .setup = serial_pxa_console_setup, +@@ -788,11 +790,16 @@ static struct uart_pxa_port serial_pxa_p + + static struct uart_driver serial_pxa_reg = { + .owner = THIS_MODULE, +- .driver_name = "PXA serial", +- .devfs_name = "tts/", +- .dev_name = "ttyS", +- .major = TTY_MAJOR, +- .minor = 64, ++/* .driver_name = "PXA serial", */ ++/* .devfs_name = "tts/", */ ++/* .dev_name = "ttyS", */ ++/* .major = TTY_MAJOR, */ ++/* .minor = 64, */ ++ .driver_name = "ttySA", ++ .dev_name = "ttySA", ++ .devfs_name = "ttySA", ++ .major = SERIAL_SA1100_MAJOR, ++ .minor = MINOR_START, + .nr = ARRAY_SIZE(serial_pxa_ports), + .cons = PXA_CONSOLE, + }; +diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig +index f5079c7..e49580a 100644 +--- a/drivers/video/Kconfig ++++ b/drivers/video/Kconfig +@@ -1387,6 +1387,16 @@ config FB_PXA_PARAMETERS + + describes the available parameters. + ++config FB_MBX ++ tristate "2700G LCD framebuffer support" ++ depends on FB && ARCH_PXA ++ select FB_CFB_FILLRECT ++ select FB_CFB_COPYAREA ++ select FB_CFB_IMAGEBLIT ++ ---help--- ++ ++ If unsure, say N. ++ + config FB_W100 + tristate "W100 frame buffer support" + depends on FB && PXA_SHARPSL +diff --git a/drivers/video/Makefile b/drivers/video/Makefile +index aa434e7..c6fe5e4 100644 +--- a/drivers/video/Makefile ++++ b/drivers/video/Makefile +@@ -94,6 +94,7 @@ obj-$(CONFIG_FB_TX3912) += tx3912fb.o + obj-$(CONFIG_FB_S1D13XXX) += s1d13xxxfb.o + obj-$(CONFIG_FB_IMX) += imxfb.o + obj-$(CONFIG_FB_S3C2410) += s3c2410fb.o ++obj-$(CONFIG_FB_MBX) += mbx/ + + # Platform or fallback drivers go here + obj-$(CONFIG_FB_VESA) += vesafb.o +diff --git a/drivers/video/mbx/Makefile b/drivers/video/mbx/Makefile +new file mode 100644 +index 0000000..ef6b729 +--- /dev/null ++++ b/drivers/video/mbx/Makefile +@@ -0,0 +1,7 @@ ++# Makefile for the Linux video drivers. ++# 5 Aug 1999, James Simmons, ++# Rewritten to use lists instead of if-statements. ++ ++# Each configuration option enables a list of files. ++ ++obj-$(CONFIG_FB_MBX) += mbxfb.o +diff --git a/drivers/video/mbx/mbxfb.c b/drivers/video/mbx/mbxfb.c +new file mode 100644 +index 0000000..93dcfa5 +--- /dev/null ++++ b/drivers/video/mbx/mbxfb.c +@@ -0,0 +1,659 @@ ++/* ++ * linux/drivers/video/mbx/mbxfb.c ++ * ++ * Copyright (C) 2006 Compulab, Ltd. ++ * ++ * Based on pxafb.c ++ * ++ * This file is subject to the terms and conditions of the GNU General Public ++ * License. See the file COPYING in the main directory of this archive for ++ * more details. ++ * ++ * Intel 2700G (Marathon) Graphics Accelerator Frame Buffer Driver ++ * ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++static unsigned long virt_base_2700; ++#include "regs.h" ++#include "reg_bits.h" ++ ++#define MIN_XRES 16 ++#define MIN_YRES 16 ++#define MAX_XRES 2048 ++#define MAX_YRES 2048 ++ ++/* FIXME: take care of different chip reivsions with different sizes ++ of ODFB */ ++#define MEMORY_OFFSET 0x60000 ++ ++struct mbxfb_info { ++ struct device *dev; ++ ++ struct resource *fb_res; ++ struct resource *fb_req; ++ ++ struct resource *reg_res; ++ struct resource *reg_req; ++ ++ void __iomem *fb_virt_addr; ++ unsigned long fb_phys_addr; ++ ++ void __iomem *reg_virt_addr; ++ unsigned long reg_phys_addr; ++ ++ int (*platform_probe)(struct fb_info *fb); ++ int (*platform_remove)(struct fb_info *fb); ++}; ++ ++static struct fb_var_screeninfo mbxfb_default __initdata = { ++ .xres = 640, ++ .yres = 480, ++ .xres_virtual = 640, ++ .yres_virtual = 480, ++ .bits_per_pixel = 16, ++ .red = { 11, 5, 0 }, ++ .green = { 5, 6, 0 }, ++ .blue = { 0, 5, 0 }, ++ .activate = FB_ACTIVATE_TEST, ++ .height = -1, ++ .width = -1, ++ .pixclock = 40000, ++ .left_margin = 48, ++ .right_margin = 16, ++ .upper_margin = 33, ++ .lower_margin = 10, ++ .hsync_len = 96, ++ .vsync_len = 2, ++ .vmode = FB_VMODE_NONINTERLACED, ++ .sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, ++}; ++ ++static struct fb_fix_screeninfo mbxfb_fix __initdata = { ++ .id = "MBX", ++ .type = FB_TYPE_PACKED_PIXELS, ++ .visual = FB_VISUAL_TRUECOLOR, ++ .xpanstep = 0, ++ .ypanstep = 0, ++ .ywrapstep = 0, ++ .accel = FB_ACCEL_NONE, ++}; ++ ++struct pixclock_div { ++ u8 m; ++ u8 n; ++ u8 p; ++}; ++ ++static unsigned int mbxfb_get_pixclock(unsigned int pixclock_ps, struct pixclock_div *div) ++{ ++ u8 m, n, p; ++ unsigned int err = 0; ++ unsigned int min_err = ~0x0; ++ unsigned int clk; ++ unsigned int best_clk = 0; ++ unsigned int ref_clk = 13000; /* FIXME: take from platform data */ ++ unsigned int pixclock; ++ ++ /* convert pixclock to KHz */ ++ pixclock = PICOS2KHZ(pixclock_ps); ++ ++ for ( m = 1; m < 64; m++ ) { ++ for ( n = 1; n < 8; n++ ) { ++ for ( p = 0; p < 8; p++ ) { ++ clk = (ref_clk * m) / (n * (1 << p)); ++ err = (clk > pixclock) ? (clk - pixclock) : ++ (pixclock - clk); ++ if ( err < min_err ) { ++ min_err = err; ++ best_clk = clk; ++ div->m = m; ++ div->n = n; ++ div->p = p; ++ } ++ } ++ } ++ } ++ return KHZ2PICOS(best_clk); ++} ++ ++static int ++mbxfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue, ++ u_int trans, struct fb_info *info) ++{ ++ uint val, ret = 1; ++ ++ if ( regno < 255 ) { ++ val = (red & 0xff) << 16; ++ val |= (green & 0xff) << 8; ++ val |= (blue & 0xff) << 0; ++ GPLUT = Gplut_Lutadr(regno) | Gplut_Lutdata(val); ++ udelay(1000); ++ ret = 0; ++ } ++ return ret; ++} ++ ++static int mbxfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info) ++{ ++ struct pixclock_div div; ++ ++ var->pixclock = mbxfb_get_pixclock(var->pixclock, &div); ++ ++ if (var->xres < MIN_XRES) ++ var->xres = MIN_XRES; ++ if (var->yres < MIN_YRES) ++ var->yres = MIN_YRES; ++ if (var->xres > MAX_XRES) ++ var->xres = MAX_XRES; ++ if (var->yres > MAX_YRES) ++ var->yres = MAX_YRES; ++ var->xres_virtual = ++ max(var->xres_virtual, var->xres); ++ var->yres_virtual = ++ max(var->yres_virtual, var->yres); ++ ++ switch (var->bits_per_pixel) { ++ /* FIXME: implement 8 bits-per-pixel */ ++ case 8: ++ var->bits_per_pixel = 16; ++ case 16: ++ var->green.length = (var->green.length == 5) ? 5 : 6; ++ var->red.length = 5; ++ var->blue.length = 5; ++ var->transp.length = 6 - var->green.length; ++ var->blue.offset = 0; ++ var->green.offset = 5; ++ var->red.offset = 5 + var->green.length; ++ var->transp.offset = (5 + var->red.offset) & 15; ++ break; ++ case 24: /* RGB 888 */ ++ case 32: /* RGBA 8888 */ ++ var->red.offset = 16; ++ var->red.length = 8; ++ var->green.offset = 8; ++ var->green.length = 8; ++ var->blue.offset = 0; ++ var->blue.length = 8; ++ var->transp.length = var->bits_per_pixel - 24; ++ var->transp.offset = (var->transp.length) ? 24 : 0; ++ break; ++ } ++ var->red.msb_right = 0; ++ var->green.msb_right = 0; ++ var->blue.msb_right = 0; ++ var->transp.msb_right = 0; ++ ++ return 0; ++} ++ ++static int mbxfb_set_par(struct fb_info *info) ++{ ++ struct fb_var_screeninfo *var = &info->var; ++ struct pixclock_div div; ++ ushort hbps, ht, hfps, has; ++ ushort vbps, vt, vfps, vas; ++ ++ info->fix.line_length = var->xres_virtual * var->bits_per_pixel / 8; ++ ++ /* setup color mode */ ++ GSCTRL &= ~(FMsk(GSCTRL_GPIXFMT)); ++ /* FIXME: add *WORKING* support for 8-bits per color */ ++ if ( info->var.bits_per_pixel == 8 ) { ++ GSCTRL |= GSCTRL_GPIXFMT_INDEXED; ++ GSCTRL |= GSCTRL_LUT_EN; ++ GSCTRL &= ~GSCTRL_GAMMA_EN; ++ info->fix.visual = FB_VISUAL_PSEUDOCOLOR; ++ fb_alloc_cmap(&info->cmap, 1<var.bits_per_pixel, 0); ++ } ++ else { ++ fb_dealloc_cmap(&info->cmap); ++ GSCTRL &= ~GSCTRL_LUT_EN; ++ info->fix.visual = FB_VISUAL_TRUECOLOR; ++ switch ( info->var.bits_per_pixel ) { ++ case 16: ++ if ( info->var.green.length == 5 ) ++ GSCTRL |= GSCTRL_GPIXFMT_ARGB1555; ++ else ++ GSCTRL |= GSCTRL_GPIXFMT_RGB565; ++ break; ++ case 24: ++ GSCTRL |= GSCTRL_GPIXFMT_RGB888; ++ break; ++ case 32: ++ GSCTRL |= GSCTRL_GPIXFMT_ARGB8888; ++ break; ++ } ++ } ++ ++ /* setup resolution */ ++ GSCTRL &= ~(FMsk(GSCTRL_GSWIDTH) | FMsk(GSCTRL_GSHEIGHT)); ++ GSCTRL |= Gsctrl_Width(info->var.xres - 1) | ++ Gsctrl_Height(info->var.yres - 1); ++ ++ GSADR &= ~(FMsk(GSADR_SRCSTRIDE)); udelay(1000); ++ GSADR |= Gsadr_Srcstride(info->var.xres * info->var.bits_per_pixel / (8 * 16) - 1); udelay(1000); ++ ++ /* setup timings */ ++ var->pixclock = mbxfb_get_pixclock(info->var.pixclock, &div); ++ ++ DISPPLL = Disp_Pll_M(div.m) | Disp_Pll_N(div.n) | Disp_Pll_P(div.p) | DISP_PLL_EN; ++ ++ hbps = var->hsync_len; ++ has = hbps + var->left_margin; ++ hfps = has + var->xres; ++ ht = hfps + var->right_margin; ++ ++ vbps = var->vsync_len; ++ vas = vbps + var->upper_margin; ++ vfps = vas + var->yres; ++ vt = vfps + var->lower_margin; ++ ++ DHT01 = Dht01_Hbps(hbps) | Dht01_Ht(ht); ++ DHT02 = Dht02_Hlbs(has) | Dht02_Has(has); ++ DHT03 = Dht03_Hfps(hfps) | Dht03_Hrbs(hfps); ++ DHDET = Dhdet_Hdes(has) | Dhdet_Hdef(hfps); ++ ++ DVT01 = Dvt01_Vbps(vbps) | Dvt01_Vt(vt); ++ DVT02 = Dvt02_Vtbs(vas) | Dvt02_Vas(vas); ++ DVT03 = Dvt03_Vfps(vfps) | Dvt03_Vbbs(vfps); ++ DVDET = Dvdet_Vdes(vas) | Dvdet_Vdef(vfps); ++ DVECTRL = Dvectrl_Vevent(vfps) | Dvectrl_Vfetch(vbps); ++ DSCTRL |= DSCTRL_SYNCGEN_EN; ++ ++ return 0; ++} ++ ++static char *blank_mode[] = { ++ "FB_BLANK_UNBLANK", ++ "FB_BLANK_NORMAL", ++ "FB_BLANK_VSYNC_SUSPEND", ++ "FB_BLANK_HSYNC_SUSPEND", ++ "FB_BLANK_POWERDOWN", ++}; ++ ++static int mbxfb_blank(int blank, struct fb_info *info) ++{ ++ switch (blank) { ++ case FB_BLANK_POWERDOWN: ++ case FB_BLANK_VSYNC_SUSPEND: ++ case FB_BLANK_HSYNC_SUSPEND: ++ case FB_BLANK_NORMAL: ++ DSCTRL &= ~DSCTRL_SYNCGEN_EN; udelay(1000); ++ PIXCLK &= ~PIXCLK_EN; udelay(1000); ++ VOVRCLK &= ~VOVRCLK_EN; udelay(1000); ++ break; ++ case FB_BLANK_UNBLANK: ++ DSCTRL |= DSCTRL_SYNCGEN_EN; udelay(1000); ++ PIXCLK |= PIXCLK_EN; udelay(1000); ++ break; ++ } ++ return 0; ++} ++ ++static struct fb_ops mbxfb_ops = { ++ .owner = THIS_MODULE, ++ .fb_check_var = mbxfb_check_var, ++ .fb_set_par = mbxfb_set_par, ++ .fb_setcolreg = mbxfb_setcolreg, ++ .fb_fillrect = cfb_fillrect, ++ .fb_copyarea = cfb_copyarea, ++ .fb_imageblit = cfb_imageblit, ++ .fb_blank = mbxfb_blank, ++}; ++ ++/* ++ Enable external SDRAM controller. Assume that all clocks are active ++ by now. ++*/ ++static void setup_memc(struct fb_info *fbi) ++{ ++ unsigned long tmp; ++ ++ /* FIXME: use platfrom specific parameters */ ++ /* setup SDRAM controller */ ++ LMCFG = LMCFG_LMC_DS | LMCFG_LMC_TS | LMCFG_LMD_TS | LMCFG_LMA_TS; ++ udelay(1000); ++ LMPWR = LMPWR_MC_PWR_ACT; ++ udelay(1000); ++ /* setup SDRAM timings */ ++ LMTIM = Lmtim_Tras(7) | Lmtim_Trp(3) | Lmtim_Trcd(3) | Lmtim_Trc(9) | ++ Lmtim_Tdpl(2); ++ udelay(1000); ++ /* setup SDRAM refresh rate */ ++ LMREFRESH = 0xc2b; ++ udelay(1000); ++ /* setup SDRAM type parameters */ ++ LMTYPE = LMTYPE_CASLAT_3 | LMTYPE_BKSZ_2 | LMTYPE_ROWSZ_11 | ++ LMTYPE_COLSZ_8; ++ udelay(1000); ++ /* enable memory controller */ ++ LMPWR = LMPWR_MC_PWR_ACT; ++ udelay(1000); ++ ++ tmp = *(unsigned long*)(virt_base_2700 + MEMORY_OFFSET); ++ tmp = *(unsigned long*)(virt_base_2700 + MEMORY_OFFSET); ++ tmp = *(unsigned long*)(virt_base_2700 + MEMORY_OFFSET); ++ tmp = *(unsigned long*)(virt_base_2700 + MEMORY_OFFSET); ++ tmp = *(unsigned long*)(virt_base_2700 + MEMORY_OFFSET); ++ tmp = *(unsigned long*)(virt_base_2700 + MEMORY_OFFSET); ++ tmp = *(unsigned long*)(virt_base_2700 + MEMORY_OFFSET); ++ tmp = *(unsigned long*)(virt_base_2700 + MEMORY_OFFSET); ++ tmp = *(unsigned long*)(virt_base_2700 + MEMORY_OFFSET); ++ tmp = *(unsigned long*)(virt_base_2700 + MEMORY_OFFSET); ++ tmp = *(unsigned long*)(virt_base_2700 + MEMORY_OFFSET); ++} ++ ++static void enable_clocks(struct fb_info* fbi) ++{ ++ /* enable clocks */ ++ SYSCLKSRC = SYSCLKSRC_PLL_2; udelay(1000); ++ PIXCLKSRC = PIXCLKSRC_PLL_1; udelay(1000); ++ CLKSLEEP = 0x00000000; udelay(1000); ++ COREPLL = Core_Pll_M(0x17) | Core_Pll_N(0x3) | Core_Pll_P(0x0) | CORE_PLL_EN; udelay(1000); ++ DISPPLL = Disp_Pll_M(0x1b) | Disp_Pll_N(0x7) | Disp_Pll_P(0x1) | DISP_PLL_EN; ++ ++ VOVRCLK = 0x00000000; udelay(1000); ++ PIXCLK = PIXCLK_EN; udelay(1000); ++ MEMCLK = MEMCLK_EN; udelay(1000); ++ M24CLK = 0x00000006; udelay(1000); ++ MBXCLK = 0x00000006; udelay(1000); ++ SDCLK = SDCLK_EN; udelay(1000); ++ PIXCLKDIV = 0x00000001; udelay(1000); ++} ++ ++static void setup_graphics(struct fb_info* fbi) ++{ ++ unsigned long gsctrl; ++ ++ gsctrl = GSCTRL_GAMMA_EN | Gsctrl_Width(fbi->var.xres-1) | ++ Gsctrl_Height(fbi->var.yres-1); ++ switch ( fbi->var.bits_per_pixel ) { ++ case 16: ++ if ( fbi->var.green.length == 5 ) ++ gsctrl |= GSCTRL_GPIXFMT_ARGB1555; ++ else ++ gsctrl |= GSCTRL_GPIXFMT_RGB565; ++ break; ++ case 24: gsctrl |= GSCTRL_GPIXFMT_RGB888; break; ++ case 32: gsctrl |= GSCTRL_GPIXFMT_ARGB8888; break; ++ } ++ ++ GSCTRL = gsctrl; udelay(1000); ++ GBBASE = 0x00000000; udelay(1000); ++ GDRCTRL = 0x00ffffff; udelay(1000); ++ GSCADR = GSCADR_STR_EN | Gscadr_Gbase_Adr(0x6000); udelay(1000); ++ GPLUT = 0x00000000; udelay(1000); ++} ++ ++static void setup_display(struct fb_info* fbi) ++{ ++ unsigned long dsctrl = 0; ++ ++ dsctrl = DSCTRL_BLNK_POL; ++ if ( fbi->var.sync & FB_SYNC_HOR_HIGH_ACT ) ++ dsctrl |= DSCTRL_HS_POL; ++ if ( fbi->var.sync & FB_SYNC_VERT_HIGH_ACT ) ++ dsctrl |= DSCTRL_VS_POL; ++ DSCTRL = dsctrl; udelay(1000); ++ DMCTRL = 0xd0303010; udelay(1000); ++ DSCTRL |= DSCTRL_SYNCGEN_EN; ++} ++ ++static void enable_controller(struct fb_info* fbi) ++{ ++ SYSRST = SYSRST_RST; ++ udelay(1000); ++ ++ enable_clocks(fbi); ++ setup_memc(fbi); ++ setup_graphics(fbi); ++ setup_display(fbi); ++} ++ ++ ++#ifdef CONFIG_PM ++/* ++ * Power management hooks. Note that we won't be called from IRQ context, ++ * unlike the blank functions above, so we may sleep. ++ */ ++static int mbxfb_suspend(struct platform_device *dev, pm_message_t state) ++{ ++ /* make frame buffer memory enter self-refresh mode */ ++ LMPWR = LMPWR_MC_PWR_SRM; ++ while ( LMPWRSTAT != LMPWRSTAT_MC_PWR_SRM ); ++ ++ /* reset the device, since it's initial state is 'mostly sleeping' */ ++ SYSRST = SYSRST_RST; ++ return 0; ++} ++ ++static int mbxfb_resume(struct platform_device *dev) ++{ ++ struct fb_info *fbi = (struct fb_info*)platform_get_drvdata(dev); ++ ++ enable_clocks(fbi); ++/* setup_graphics(fbi); */ ++/* setup_display(fbi); */ ++ ++ DSCTRL |= DSCTRL_SYNCGEN_EN; ++ return 0; ++} ++#else ++#define mbxfb_suspend NULL ++#define mbxfb_resume NULL ++#endif ++ ++#include "mbxsysfs.c" ++ ++#define res_size(_r) (((_r)->end - (_r)->start) + 1) ++ ++static int mbxfb_probe(struct platform_device *dev) ++{ ++ int ret; ++ struct fb_info *fbi; ++ struct mbxfb_info *mfbi; ++ struct mbxfb_platform_data *pdata; ++ ++ dev_dbg(dev, "mbxfb_probe\n"); ++ ++ fbi = framebuffer_alloc(sizeof(struct mbxfb_info), &dev->dev); ++ if ( fbi == NULL ) { ++ dev_err(&dev->dev, "framebuffer_alloc failed\n"); ++ return -ENOMEM; ++ } ++ ++ mfbi = fbi->par; ++ pdata = dev->dev.platform_data; ++ if ( pdata->probe ) ++ mfbi->platform_probe = pdata->probe; ++ if ( pdata->remove ) ++ mfbi->platform_remove = pdata->remove; ++ ++ mfbi->fb_res = platform_get_resource(dev, IORESOURCE_MEM, 0); ++ mfbi->reg_res = platform_get_resource(dev, IORESOURCE_MEM, 1); ++ ++ if ( !mfbi->fb_res || !mfbi->reg_res ) { ++ dev_err(&dev->dev, "no resources found\n"); ++ ret = -ENODEV; ++ goto err1; ++ } ++ ++ mfbi->fb_req = request_mem_region(mfbi->fb_res->start, ++ res_size(mfbi->fb_res), ++ dev->name); ++ if ( mfbi->fb_req == NULL ) { ++ dev_err(&dev->dev, "failed to claim framebuffer memory\n"); ++ ret = -EINVAL; ++ goto err1; ++ } ++ mfbi->fb_phys_addr = mfbi->fb_res->start; ++ ++ mfbi->reg_req = request_mem_region(mfbi->reg_res->start, ++ res_size(mfbi->reg_res), ++ dev->name); ++ if ( mfbi->reg_req == NULL ) { ++ dev_err(&dev->dev, "failed to claim Marathon registers\n"); ++ ret = -EINVAL; ++ goto err2; ++ } ++ mfbi->reg_phys_addr = mfbi->reg_res->start; ++ ++ mfbi->reg_virt_addr = ioremap_nocache(mfbi->reg_phys_addr, ++ res_size(mfbi->reg_req)); ++ if ( !mfbi->reg_virt_addr ) { ++ dev_err(&dev->dev, "failed to ioremap Marathon registers\n"); ++ ret = -EINVAL; ++ goto err3; ++ } ++ virt_base_2700 = mfbi->reg_virt_addr; ++ ++ mfbi->fb_virt_addr = ioremap_nocache(mfbi->fb_phys_addr, ++ res_size(mfbi->fb_req)); ++ if ( !mfbi->reg_virt_addr ) { ++ dev_err(&dev->dev, "failed to ioremap frame buffer\n"); ++ ret = -EINVAL; ++ goto err4; ++ } ++ ++ fbi->screen_base = (char __iomem *)(mfbi->fb_virt_addr + 0x60000); /* FIXME: */ ++ fbi->screen_size = 8*1024*1024; /* 8 Megs */ /* FIXME: get from platform */ ++ fbi->fbops = &mbxfb_ops; ++ ++ fbi->var = mbxfb_default; ++ fbi->fix = mbxfb_fix; ++ fbi->fix.smem_start = mfbi->fb_phys_addr + 0x60000; ++ fbi->fix.smem_len = 8*1024*1024; ++ fbi->fix.line_length = 640*2; ++ ++ ret = fb_alloc_cmap(&fbi->cmap, 256, 0); ++ if (ret < 0) { ++ dev_err(&dev->dev, "fb_alloc_cmap failed\n"); ++ ret = -EINVAL; ++ goto err5; ++ } ++ ++ ret = register_framebuffer(fbi); ++ if (ret < 0) { ++ dev_err(&dev->dev, "register_framebuffer failed\n"); ++ ret = -EINVAL; ++ goto err6; ++ } ++ ++ platform_set_drvdata(dev, fbi); ++ ++ printk(KERN_INFO "fb%d: mbx frame buffer device\n", fbi->node); ++ ++ if ( mfbi->platform_probe ) ++ mfbi->platform_probe(fbi); ++ ++ enable_controller(fbi); ++ ++ mbxfb_sysfs_register(fbi); ++ ++ return 0; ++ ++ err6: ++ fb_dealloc_cmap(&fbi->cmap); ++ err5: ++ iounmap(mfbi->fb_virt_addr); ++ err4: ++ iounmap(mfbi->reg_virt_addr); ++ err3: ++ release_mem_region(mfbi->reg_res->start, ++ res_size(mfbi->reg_res)); ++ err2: ++ release_mem_region(mfbi->fb_res->start, ++ res_size(mfbi->fb_res)); ++ err1: ++ framebuffer_release(fbi); ++ ++ return ret; ++} ++ ++static int mbxfb_remove(struct platform_device *dev) ++{ ++ struct fb_info *fbi = (struct fb_info*)platform_get_drvdata(dev); ++ ++ SYSRST = SYSRST_RST; ++ udelay(1000); ++ ++ if (fbi) { ++ struct mbxfb_info *mfbi = fbi->par; ++ ++ unregister_framebuffer(fbi); ++ if ( mfbi ) { ++ if ( mfbi->platform_remove ) ++ mfbi->platform_remove(fbi); ++ ++ if ( mfbi->fb_virt_addr ) ++ iounmap(mfbi->fb_virt_addr); ++ if ( mfbi->reg_virt_addr ) ++ iounmap(mfbi->reg_virt_addr); ++ if ( mfbi->reg_req ) ++ release_mem_region(mfbi->reg_req->start, ++ res_size(mfbi->reg_req)); ++ if ( mfbi->fb_req ) ++ release_mem_region(mfbi->fb_req->start, ++ res_size(mfbi->fb_req)); ++ } ++ framebuffer_release(fbi); ++ } ++ ++ return 0; ++} ++ ++static struct platform_driver mbxfb_driver = { ++ .probe = mbxfb_probe, ++ .remove = mbxfb_remove, ++ ++#ifdef CONFIG_PM ++ .suspend = mbxfb_suspend, ++ .resume = mbxfb_resume, ++#endif ++ .driver = { ++ .name = "mbx-fb", ++ }, ++}; ++ ++int __devinit mbxfb_init(void) ++{ ++ return platform_driver_register(&mbxfb_driver); ++} ++ ++static void __exit mbxfb_exit(void) ++{ ++ platform_driver_unregister(&mbxfb_driver); ++} ++ ++module_init(mbxfb_init); ++module_exit(mbxfb_exit); ++ ++MODULE_DESCRIPTION("loadable framebuffer driver for Marathon device"); ++MODULE_AUTHOR("Mike Rapoport, Compulab"); ++MODULE_LICENSE("GPL"); +diff --git a/drivers/video/mbx/mbxsysfs.c b/drivers/video/mbx/mbxsysfs.c +new file mode 100644 +index 0000000..4b9571a +--- /dev/null ++++ b/drivers/video/mbx/mbxsysfs.c +@@ -0,0 +1,129 @@ ++static ssize_t sysconf_show(struct class_device * subsys, char * buf) ++{ ++ char * s = buf; ++ ++ s += sprintf(s, "SYSCFG = %08lx\n", SYSCFG); ++ s += sprintf(s, "PFBASE = %08lx\n", PFBASE); ++ s += sprintf(s, "PFCEIL = %08lx\n", PFCEIL); ++ s += sprintf(s, "POLLFLAG = %08lx\n", POLLFLAG); ++ s += sprintf(s, "SYSRST = %08lx\n", SYSRST); ++ return (s - buf); ++} ++ ++static ssize_t sysconf_store(struct class_device * subsys, const char * buf, size_t n) ++{ ++ return n; ++} ++ ++static ssize_t gsctl_show(struct class_device * subsys, char * buf) ++{ ++ char * s = buf; ++ ++ s += sprintf(s, "GSCTRL = %08lx\n", GSCTRL); ++ s += sprintf(s, "VSCTRL = %08lx\n", VSCTRL); ++ s += sprintf(s, "GBBASE = %08lx\n", GBBASE); ++ s += sprintf(s, "VBBASE = %08lx\n", VBBASE); ++ s += sprintf(s, "GDRCTRL = %08lx\n", GDRCTRL); ++ s += sprintf(s, "VCMSK = %08lx\n", VCMSK); ++ s += sprintf(s, "GSCADR = %08lx\n", GSCADR); ++ s += sprintf(s, "VSCADR = %08lx\n", VSCADR); ++ s += sprintf(s, "VUBASE = %08lx\n", VUBASE); ++ s += sprintf(s, "VVBASE = %08lx\n", VVBASE); ++ s += sprintf(s, "GSADR = %08lx\n", GSADR); ++ s += sprintf(s, "VSADR = %08lx\n", VSADR); ++ s += sprintf(s, "HCCTRL = %08lx\n", HCCTRL); ++ s += sprintf(s, "HCSIZE = %08lx\n", HCSIZE); ++ s += sprintf(s, "HCPOS = %08lx\n", HCPOS); ++ s += sprintf(s, "HCBADR = %08lx\n", HCBADR); ++ s += sprintf(s, "HCCKMSK = %08lx\n", HCCKMSK); ++ s += sprintf(s, "GPLUT = %08lx\n", GPLUT); ++ return (s - buf); ++} ++ ++static ssize_t gsctl_store(struct class_device * subsys, const char * buf, size_t n) ++{ ++ return n; ++} ++ ++static ssize_t display_show(struct class_device * subsys, char * buf) ++{ ++ char * s = buf; ++ ++ s += sprintf(s, "DSCTRL = %08lx\n", DSCTRL); ++ s += sprintf(s, "DHT01 = %08lx\n", DHT01); ++ s += sprintf(s, "DHT02 = %08lx\n", DHT02); ++ s += sprintf(s, "DHT03 = %08lx\n", DHT03); ++ s += sprintf(s, "DVT01 = %08lx\n", DVT01); ++ s += sprintf(s, "DVT02 = %08lx\n", DVT02); ++ s += sprintf(s, "DVT03 = %08lx\n", DVT03); ++ s += sprintf(s, "DBCOL = %08lx\n", DBCOL); ++ s += sprintf(s, "BGCOLOR = %08lx\n", BGCOLOR); ++ s += sprintf(s, "DINTRS = %08lx\n", DINTRS); ++ s += sprintf(s, "DINTRE = %08lx\n", DINTRE); ++ s += sprintf(s, "DINTRCNT = %08lx\n", DINTRCNT); ++ s += sprintf(s, "DSIG = %08lx\n", DSIG); ++ s += sprintf(s, "DMCTRL = %08lx\n", DMCTRL); ++ s += sprintf(s, "CLIPCTRL = %08lx\n", CLIPCTRL); ++ s += sprintf(s, "SPOCTRL = %08lx\n", SPOCTRL); ++ s += sprintf(s, "SVCTRL = %08lx\n", SVCTRL); ++ s += sprintf(s, "DLSTS = %08lx\n", DLSTS); ++ s += sprintf(s, "DLLCTRL = %08lx\n", DLLCTRL); ++ s += sprintf(s, "DVLNUM = %08lx\n", DVLNUM); ++ s += sprintf(s, "DUCTRL = %08lx\n", DUCTRL); ++ s += sprintf(s, "DVECTRL = %08lx\n", DVECTRL); ++ s += sprintf(s, "DHDET = %08lx\n", DHDET); ++ s += sprintf(s, "DVDET = %08lx\n", DVDET); ++ s += sprintf(s, "DODMSK = %08lx\n", DODMSK); ++ s += sprintf(s, "CSC01 = %08lx\n", CSC01); ++ s += sprintf(s, "CSC02 = %08lx\n", CSC02); ++ s += sprintf(s, "CSC03 = %08lx\n", CSC03); ++ s += sprintf(s, "CSC04 = %08lx\n", CSC04); ++ s += sprintf(s, "CSC05 = %08lx\n", CSC05); ++ return (s - buf); ++} ++ ++static ssize_t display_store(struct class_device * subsys, const char * buf, size_t n) ++{ ++ return n; ++} ++ ++static ssize_t clock_show(struct class_device * subsys, char * buf) ++{ ++ char * s = buf; ++ ++ s += sprintf(s, "SYSCLKSRC = %08lx\n", SYSCLKSRC); ++ s += sprintf(s, "PIXCLKSRC = %08lx\n", PIXCLKSRC); ++ s += sprintf(s, "CLKSLEEP = %08lx\n", CLKSLEEP); ++ s += sprintf(s, "COREPLL = %08lx\n", COREPLL); ++ s += sprintf(s, "DISPPLL = %08lx\n", DISPPLL); ++ s += sprintf(s, "PLLSTAT = %08lx\n", PLLSTAT); ++ s += sprintf(s, "VOVRCLK = %08lx\n", VOVRCLK); ++ s += sprintf(s, "PIXCLK = %08lx\n", PIXCLK); ++ s += sprintf(s, "MEMCLK = %08lx\n", MEMCLK); ++ s += sprintf(s, "M24CLK = %08lx\n", M24CLK); ++ s += sprintf(s, "MBXCLK = %08lx\n", MBXCLK); ++ s += sprintf(s, "SDCLK = %08lx\n", SDCLK); ++ s += sprintf(s, "PIXCLKDIV = %08lx\n", PIXCLKDIV); ++ return (s - buf); ++} ++ ++static ssize_t clock_store(struct class_device * subsys, const char * buf, size_t n) ++{ ++ return n; ++} ++ ++static struct class_device_attribute mbx_class_attrs[] = { ++ __ATTR(sysconf,0644,sysconf_show,sysconf_store), ++ __ATTR(gsctl,0644,gsctl_show,gsctl_store), ++ __ATTR(display,0644,display_show,display_store), ++ __ATTR(clock,0644,clock_show,clock_store), ++}; ++ ++ ++static void mbxfb_sysfs_register(struct fb_info *fbi) ++{ ++ int i; ++ for (i = 0; i < ARRAY_SIZE(mbx_class_attrs); i++) ++ class_device_create_file(fbi->class_device, ++ &mbx_class_attrs[i]); ++} +diff --git a/drivers/video/mbx/reg_bits.h b/drivers/video/mbx/reg_bits.h +new file mode 100644 +index 0000000..be152f6 +--- /dev/null ++++ b/drivers/video/mbx/reg_bits.h +@@ -0,0 +1,489 @@ ++#ifndef __REG_BITS_2700G_ ++#define __REG_BITS_2700G_ ++ ++/* /\* System Configuration Registers (0x03FE_0000 0x03FE_0010) *\/ */ ++/* #define SYSCFG __REG_2700G(0x03FE0000) */ ++/* #define PFBASE __REG_2700G(0x03FE0004) */ ++/* #define PFCEIL __REG_2700G(0x03FE0008) */ ++/* #define POLLFLAG __REG_2700G(0x03FE000C) */ ++ ++#define SYSRST_RST (1 << 0) ++ ++/* /\* Interrupt Control Registers (0x03FE_0014 0x03FE_002F) *\/ */ ++/* #define NINTPW __REG_2700G(0x03FE0014) */ ++/* #define MINTENABLE __REG_2700G(0x03FE0018) */ ++/* #define MINTSTAT __REG_2700G(0x03FE001C) */ ++/* #define SINTENABLE __REG_2700G(0x03FE0020) */ ++/* #define SINTSTAT __REG_2700G(0x03FE0024) */ ++/* #define SINTCLR __REG_2700G(0x03FE0028) */ ++ ++/* SYSCLKSRC - SYSCLK Source Control Register */ ++#define SYSCLKSRC_SEL Fld(2,0) ++#define SYSCLKSRC_REF ((0x0) << FShft(SYSCLKSRC_SEL)) ++#define SYSCLKSRC_PLL_1 ((0x1) << FShft(SYSCLKSRC_SEL)) ++#define SYSCLKSRC_PLL_2 ((0x2) << FShft(SYSCLKSRC_SEL)) ++ ++/* PIXCLKSRC - PIXCLK Source Control Register */ ++#define PIXCLKSRC_SEL Fld(2,0) ++#define PIXCLKSRC_REF ((0x0) << FShft(PIXCLKSRC_SEL)) ++#define PIXCLKSRC_PLL_1 ((0x1) << FShft(PIXCLKSRC_SEL)) ++#define PIXCLKSRC_PLL_2 ((0x2) << FShft(PIXCLKSRC_SEL)) ++ ++/* Clock Disable Register */ ++#define CLKSLEEP_SLP (1 << 0) ++ ++/* Core PLL Control Register */ ++#define CORE_PLL_M Fld(6,7) ++#define Core_Pll_M(x) ((x) << FShft(CORE_PLL_M)) ++#define CORE_PLL_N Fld(3,4) ++#define Core_Pll_N(x) ((x) << FShft(CORE_PLL_N)) ++#define CORE_PLL_P Fld(3,1) ++#define Core_Pll_P(x) ((x) << FShft(CORE_PLL_P)) ++#define CORE_PLL_EN (1 << 0) ++ ++/* Display PLL Control Register */ ++#define DISP_PLL_M Fld(6,7) ++#define Disp_Pll_M(x) ((x) << FShft(DISP_PLL_M)) ++#define DISP_PLL_N Fld(3,4) ++#define Disp_Pll_N(x) ((x) << FShft(DISP_PLL_N)) ++#define DISP_PLL_P Fld(3,1) ++#define Disp_Pll_P(x) ((x) << FShft(DISP_PLL_P)) ++#define DISP_PLL_EN (1 << 0) ++ ++/* PLL status register */ ++#define PLLSTAT_CORE_PLL_LOST_L (1 << 3) ++#define PLLSTAT_CORE_PLL_LSTS (1 << 2) ++#define PLLSTAT_DISP_PLL_LOST_L (1 << 1) ++#define PLLSTAT_DISP_PLL_LSTS (1 << 0) ++ ++/* Video and scale clock control register */ ++#define VOVRCLK_EN (1 << 0) ++ ++/* Pixel clock control register */ ++#define PIXCLK_EN (1 << 0) ++ ++/* Memory clock control register */ ++#define MEMCLK_EN (1 << 0) ++ ++/* MBX clock control register */ ++#define MBXCLK_DIV Fld(2,2) ++#define MBXCLK_DIV_1 ((0x0) << FShft(MBXCLK_DIV)) ++#define MBXCLK_DIV_2 ((0x1) << FShft(MBXCLK_DIV)) ++#define MBXCLK_DIV_3 ((0x2) << FShft(MBXCLK_DIV)) ++#define MBXCLK_DIV_4 ((0x3) << FShft(MBXCLK_DIV)) ++#define MBXCLK_EN Fld(2,0) ++#define MBXCLK_EN_NONE ((0x0) << FShft(MBXCLK_EN)) ++#define MBXCLK_EN_2D ((0x1) << FShft(MBXCLK_EN)) ++#define MBXCLK_EN_BOTH ((0x2) << FShft(MBXCLK_EN)) ++ ++/* M24 clock control register */ ++#define M24CLK_DIV Fld(2,1) ++#define M24CLK_DIV_1 ((0x0) << FShft(M24CLK_DIV)) ++#define M24CLK_DIV_2 ((0x1) << FShft(M24CLK_DIV)) ++#define M24CLK_DIV_3 ((0x2) << FShft(M24CLK_DIV)) ++#define M24CLK_DIV_4 ((0x3) << FShft(M24CLK_DIV)) ++#define M24CLK_EN (1 << 0) ++ ++/* SDRAM clock control register */ ++#define SDCLK_EN (1 << 0) ++ ++/* PixClk Divisor Register */ ++#define PIXCLKDIV_PD Fld(9,0) ++#define Pixclkdiv_Pd(x) ((x) << FShft(PIXCLKDIV_PD)) ++ ++/* LCD Config control register */ ++#define LCDCFG_IN_FMT Fld(3,28) ++#define Lcdcfg_In_Fmt(x) ((x) << FShft(LCDCFG_IN_FMT)) ++#define LCDCFG_LCD1DEN_POL (1 << 27) ++#define LCDCFG_LCD1FCLK_POL (1 << 26) ++#define LCDCFG_LCD1LCLK_POL (1 << 25) ++#define LCDCFG_LCD1D_POL (1 << 24) ++#define LCDCFG_LCD2DEN_POL (1 << 23) ++#define LCDCFG_LCD2FCLK_POL (1 << 22) ++#define LCDCFG_LCD2LCLK_POL (1 << 21) ++#define LCDCFG_LCD2D_POL (1 << 20) ++#define LCDCFG_LCD1_TS (1 << 19) ++#define LCDCFG_LCD1D_DS (1 << 18) ++#define LCDCFG_LCD1C_DS (1 << 17) ++#define LCDCFG_LCD1_IS_IN (1 << 16) ++#define LCDCFG_LCD2_TS (1 << 3) ++#define LCDCFG_LCD2D_DS (1 << 2) ++#define LCDCFG_LCD2C_DS (1 << 1) ++#define LCDCFG_LCD2_IS_IN (1 << 0) ++ ++/* On-Die Frame Buffer Power Control Register */ ++#define ODFBPWR_SLOW (1 << 2) ++#define ODFBPWR_MODE Fld(2,0) ++#define ODFBPWR_MODE_ACT ((0x0) << FShft(ODFBPWR_MODE)) ++#define ODFBPWR_MODE_ACT_LP ((0x1) << FShft(ODFBPWR_MODE)) ++#define ODFBPWR_MODE_SLEEP ((0x2) << FShft(ODFBPWR_MODE)) ++#define ODFBPWR_MODE_SHUTD ((0x3) << FShft(ODFBPWR_MODE)) ++ ++/* On-Die Frame Buffer Power State Status Register */ ++#define ODFBSTAT_ACT (1 << 2) ++#define ODFBSTAT_SLP (1 << 1) ++#define ODFBSTAT_SDN (1 << 0) ++ ++/* /\* GPIO Registers (0x03FE_006C 0x03FE_007F) *\/ */ ++/* #define GPIOCGF __REG_2700G(0x03FE006C) */ ++/* #define GPIOHI __REG_2700G(0x03FE0070) */ ++/* #define GPIOLO __REG_2700G(0x03FE0074) */ ++/* #define GPIOSTAT __REG_2700G(0x03FE0078) */ ++ ++/* /\* Pulse Width Modulator (PWM) Registers (0x03FE_0200 0x03FE_02FF) *\/ */ ++/* #define PWMRST __REG_2700G(0x03FE0200) */ ++/* #define PWMCFG __REG_2700G(0x03FE0204) */ ++/* #define PWM0DIV __REG_2700G(0x03FE0210) */ ++/* #define PWM0DUTY __REG_2700G(0x03FE0214) */ ++/* #define PWM0PER __REG_2700G(0x03FE0218) */ ++/* #define PWM1DIV __REG_2700G(0x03FE0220) */ ++/* #define PWM1DUTY __REG_2700G(0x03FE0224) */ ++/* #define PWM1PER __REG_2700G(0x03FE0228) */ ++ ++ ++/* LMRST - Local Memory (SDRAM) Reset */ ++#define LMRST_MC_RST (1 << 0) ++ ++/* LMCFG - Local Memory (SDRAM) Configuration Register */ ++#define LMCFG_LMC_DS (1 << 5) ++#define LMCFG_LMD_DS (1 << 4) ++#define LMCFG_LMA_DS (1 << 3) ++#define LMCFG_LMC_TS (1 << 2) ++#define LMCFG_LMD_TS (1 << 1) ++#define LMCFG_LMA_TS (1 << 0) ++ ++/* LMPWR - Local Memory (SDRAM) Power Control Register */ ++#define LMPWR_MC_PWR_CNT Fld(2,0) ++#define LMPWR_MC_PWR_ACT ((0x0) << FShft(LMPWR_MC_PWR_CNT)) /* Active */ ++#define LMPWR_MC_PWR_SRM ((0x1) << FShft(LMPWR_MC_PWR_CNT)) /* Self-refresh */ ++#define LMPWR_MC_PWR_DPD ((0x3) << FShft(LMPWR_MC_PWR_CNT)) /* deep power down */ ++ ++/* LMPWRSTAT - Local Memory (SDRAM) Power Status Register */ ++#define LMPWRSTAT_MC_PWR_CNT Fld(2,0) ++#define LMPWRSTAT_MC_PWR_ACT ((0x0) << FShft(LMPWRSTAT_MC_PWR_CNT)) /* Active */ ++#define LMPWRSTAT_MC_PWR_SRM ((0x1) << FShft(LMPWRSTAT_MC_PWR_CNT)) /* Self-refresh */ ++#define LMPWRSTAT_MC_PWR_DPD ((0x3) << FShft(LMPWRSTAT_MC_PWR_CNT)) /* deep power down */ ++ ++/* LMTYPE - Local Memory (SDRAM) Type Register */ ++#define LMTYPE_CASLAT Fld(3,10) ++#define LMTYPE_CASLAT_1 ((0x1) << FShft(LMTYPE_CASLAT)) ++#define LMTYPE_CASLAT_2 ((0x2) << FShft(LMTYPE_CASLAT)) ++#define LMTYPE_CASLAT_3 ((0x3) << FShft(LMTYPE_CASLAT)) ++#define LMTYPE_BKSZ Fld(2,8) ++#define LMTYPE_BKSZ_1 ((0x1) << FShft(LMTYPE_BKSZ)) ++#define LMTYPE_BKSZ_2 ((0x2) << FShft(LMTYPE_BKSZ)) ++#define LMTYPE_ROWSZ Fld(4,4) ++#define LMTYPE_ROWSZ_11 ((0xb) << FShft(LMTYPE_ROWSZ)) ++#define LMTYPE_ROWSZ_12 ((0xc) << FShft(LMTYPE_ROWSZ)) ++#define LMTYPE_ROWSZ_13 ((0xd) << FShft(LMTYPE_ROWSZ)) ++#define LMTYPE_COLSZ Fld(4,0) ++#define LMTYPE_COLSZ_7 ((0x7) << FShft(LMTYPE_COLSZ)) ++#define LMTYPE_COLSZ_8 ((0x8) << FShft(LMTYPE_COLSZ)) ++#define LMTYPE_COLSZ_9 ((0x9) << FShft(LMTYPE_COLSZ)) ++#define LMTYPE_COLSZ_10 ((0xa) << FShft(LMTYPE_COLSZ)) ++#define LMTYPE_COLSZ_11 ((0xb) << FShft(LMTYPE_COLSZ)) ++#define LMTYPE_COLSZ_12 ((0xc) << FShft(LMTYPE_COLSZ)) ++ ++/* LMTIM - Local Memory (SDRAM) Timing Register */ ++#define LMTIM_TRAS Fld(4,16) ++#define Lmtim_Tras(x) ((x) << FShft(LMTIM_TRAS)) ++#define LMTIM_TRP Fld(4,12) ++#define Lmtim_Trp(x) ((x) << FShft(LMTIM_TRP)) ++#define LMTIM_TRCD Fld(4,8) ++#define Lmtim_Trcd(x) ((x) << FShft(LMTIM_TRCD)) ++#define LMTIM_TRC Fld(4,4) ++#define Lmtim_Trc(x) ((x) << FShft(LMTIM_TRC)) ++#define LMTIM_TDPL Fld(4,0) ++#define Lmtim_Tdpl(x) ((x) << FShft(LMTIM_TDPL)) ++ ++/* LMREFRESH - Local Memory (SDRAM) tREF Control Register */ ++#define LMREFRESH_TREF Fld(2,0) ++#define Lmrefresh_Tref(x) ((x) << FShft(LMREFRESH_TREF)) ++ ++/* #define LMCEMR __REG_2700G(0x03FE1010) */ ++/* #define LMPROTMIN __REG_2700G(0x03FE1020) */ ++/* #define LMPROTMAX __REG_2700G(0x03FE1024) */ ++/* #define LMPROTCFG __REG_2700G(0x03FE1028) */ ++/* #define LMPROTERR __REG_2700G(0x03FE102C) */ ++ ++/* GSCTRL - Graphics surface control register */ ++#define GSCTRL_LUT_EN (1 << 31) ++#define GSCTRL_GPIXFMT Fld(4,27) ++#define GSCTRL_GPIXFMT_INDEXED ((0x0) << FShft(GSCTRL_GPIXFMT)) ++#define GSCTRL_GPIXFMT_ARGB4444 ((0x4) << FShft(GSCTRL_GPIXFMT)) ++#define GSCTRL_GPIXFMT_ARGB1555 ((0x5) << FShft(GSCTRL_GPIXFMT)) ++#define GSCTRL_GPIXFMT_RGB888 ((0x6) << FShft(GSCTRL_GPIXFMT)) ++#define GSCTRL_GPIXFMT_RGB565 ((0x7) << FShft(GSCTRL_GPIXFMT)) ++#define GSCTRL_GPIXFMT_ARGB8888 ((0x8) << FShft(GSCTRL_GPIXFMT)) ++#define GSCTRL_GAMMA_EN (1 << 26) ++ ++#define GSCTRL_GSWIDTH Fld(11,11) ++#define Gsctrl_Width(Pixel) /* Display Width [1..2048 pix.] */ \ ++ (((Pixel) - 1) << FShft(GSCTRL_GSWIDTH)) ++ ++#define GSCTRL_GSHEIGHT Fld(11,0) ++#define Gsctrl_Height(Pixel) /* Display Height [1..2048 pix.] */ \ ++ (((Pixel) - 1) << FShft(GSCTRL_GSHEIGHT)) ++ ++/* GBBASE fileds */ ++#define GBBASE_GLALPHA Fld(8,24) ++#define Gbbase_Glalpha(x) ((x) << FShft(GBBASE_GLALPHA)) ++ ++#define GBBASE_COLKEY Fld(24,0) ++#define Gbbase_Colkey(x) ((x) << FShft(GBBASE_COLKEY)) ++ ++/* GDRCTRL fields */ ++#define GDRCTRL_PIXDBL (1 << 31) ++#define GDRCTRL_PIXHLV (1 << 30) ++#define GDRCTRL_LNDBL (1 << 29) ++#define GDRCTRL_LNHLV (1 << 28) ++#define GDRCTRL_COLKEYM Fld(24,0) ++#define Gdrctrl_Colkeym(x) ((x) << FShft(GDRCTRL_COLKEYM)) ++ ++/* GSCADR graphics stream control address register fields */ ++#define GSCADR_STR_EN (1 << 31) ++#define GSCADR_COLKEY_EN (1 << 30) ++#define GSCADR_COLKEYSCR (1 << 29) ++#define GSCADR_BLEND_M Fld(2,27) ++#define GSCADR_BLEND_NONE ((0x0) << FShft(GSCADR_BLEND_M)) ++#define GSCADR_BLEND_INV ((0x1) << FShft(GSCADR_BLEND_M)) ++#define GSCADR_BLEND_GLOB ((0x2) << FShft(GSCADR_BLEND_M)) ++#define GSCADR_BLEND_PIX ((0x3) << FShft(GSCADR_BLEND_M)) ++#define GSCADR_BLEND_POS Fld(2,24) ++#define GSCADR_BLEND_GFX ((0x0) << FShft(GSCADR_BLEND_POS)) ++#define GSCADR_BLEND_VID ((0x1) << FShft(GSCADR_BLEND_POS)) ++#define GSCADR_BLEND_CUR ((0x2) << FShft(GSCADR_BLEND_POS)) ++#define GSCADR_GBASE_ADR Fld(23,0) ++#define Gscadr_Gbase_Adr(x) ((x) << FShft(GSCADR_GBASE_ADR)) ++ ++/* GSADR graphics stride address register fields */ ++#define GSADR_SRCSTRIDE Fld(10,22) ++#define Gsadr_Srcstride(x) ((x) << FShft(GSADR_SRCSTRIDE)) ++#define GSADR_XSTART Fld(11,11) ++#define Gsadr_Xstart(x) ((x) << FShft(GSADR_XSTART)) ++#define GSADR_YSTART Fld(11,0) ++#define Gsadr_Ystart(y) ((y) << FShft(GSADR_YSTART)) ++ ++/* GPLUT graphics palette register fields */ ++#define GPLUT_LUTADR Fld(8,24) ++#define Gplut_Lutadr(x) ((x) << FShft(GPLUT_LUTADR)) ++#define GPLUT_LUTDATA Fld(24,0) ++#define Gplut_Lutdata(x) ((x) << FShft(GPLUT_LUTDATA)) ++ ++/* #define VSCTRL __REG_2700G(0x03FE2004) */ ++/* #define VBBASE __REG_2700G(0x03FE2024) */ ++/* #define VCMSK __REG_2700G(0x03FE2044) */ ++/* #define VSCADR __REG_2700G(0x03FE2064) */ ++/* #define VUBASE __REG_2700G(0x03FE2084) */ ++/* #define VVBASE __REG_2700G(0x03FE20A4) */ ++/* #define VSADR __REG_2700G(0x03FE20C4) */ ++ ++ ++/* HCCTRL - Hardware Cursor Register fields */ ++#define HCCTRL_CUR_EN (1 << 31) ++#define HCCTRL_COLKEY_EN (1 << 29) ++#define HCCTRL_COLKEYSRC (1 << 28) ++#define HCCTRL_BLEND_M Fld(2,26) ++#define HCCTRL_BLEND_NONE ((0x0) << FShft(HCCTRL_BLEND_M)) ++#define HCCTRL_BLEND_INV ((0x1) << FShft(HCCTRL_BLEND_M)) ++#define HCCTRL_BLEND_GLOB ((0x2) << FShft(HCCTRL_BLEND_M)) ++#define HCCTRL_BLEND_PIX ((0x3) << FShft(HCCTRL_BLEND_M)) ++#define HCCTRL_CPIXFMT Fld(3,23) ++#define HCCTRL_CPIXFMT_RGB332 ((0x3) << FShft(HCCTRL_CPIXFMT)) ++#define HCCTRL_CPIXFMT_ARGB4444 ((0x4) << FShft(HCCTRL_CPIXFMT)) ++#define HCCTRL_CPIXFMT_ARGB1555 ((0x5) << FShft(HCCTRL_CPIXFMT)) ++#define HCCTRL_CBASE_ADR Fld(23,0) ++#define Hcctrl_Cbase_Adr(x) ((x) << FShft(HCCTRL_CBASE_ADR)) ++ ++/* HCSIZE Hardware Cursor Size Register fields */ ++#define HCSIZE_BLEND_POS Fld(2,29) ++#define HCSIZE_BLEND_GFX ((0x0) << FShft(HCSIZE_BLEND_POS)) ++#define HCSIZE_BLEND_VID ((0x1) << FShft(HCSIZE_BLEND_POS)) ++#define HCSIZE_BLEND_CUR ((0x2) << FShft(HCSIZE_BLEND_POS)) ++#define HCSIZE_CWIDTH Fld(3,16) ++#define Hcsize_Cwidth(x) ((x) << FShft(HCSIZE_CWIDTH)) ++#define HCSIZE_CHEIGHT Fld(3,0) ++#define Hcsize_Cheight(x) ((x) << FShft(HCSIZE_CHEIGHT)) ++ ++/* HCPOS Hardware Cursor Position Register fields */ ++#define HCPOS_SWITCHSRC (1 << 30) ++#define HCPOS_CURBLINK Fld(6,24) ++#define Hcpos_Curblink(x) ((x) << FShft(HCPOS_CURBLINK)) ++#define HCPOS_XSTART Fld(12,12) ++#define Hcpos_Xstart(x) ((x) << FShft(HCPOS_XSTART)) ++#define HCPOS_YSTART Fld(12,0) ++#define Hcpos_Ystart(y) ((y) << FShft(HCPOS_YSTART)) ++ ++/* HCBADR Hardware Cursor Blend Address Register */ ++#define HCBADR_GLALPHA Fld(8,24) ++#define Hcbadr_Glalpha(x) ((x) << FShft(HCBADR_GLALPHA)) ++#define HCBADR_COLKEY Fld(24,0) ++#define Hcbadr_Colkey(x) ((x) << FShft(HCBADR_COLKEY)) ++ ++/* HCCKMSK - Hardware Cursor Color Key Mask Register */ ++#define HCCKMSK_COLKEY_M Fld(24,0) ++#define Hcckmsk_Colkey_M(x) ((x) << FShft(HCCKMSK_COLKEY_M)) ++ ++/* DSCTRL - Display sync control register */ ++#define DSCTRL_SYNCGEN_EN (1 << 31) ++#define DSCTRL_DPL_RST (1 << 29) ++#define DSCTRL_PWRDN_M (1 << 28) ++#define DSCTRL_UPDSYNCCNT (1 << 26) ++#define DSCTRL_UPDINTCNT (1 << 25) ++#define DSCTRL_UPDCNT (1 << 24) ++#define DSCTRL_UPDWAIT Fld(4,16) ++#define Dsctrl_Updwait(x) ((x) << FShft(DSCTRL_UPDWAIT)) ++#define DSCTRL_CLKPOL (1 << 11) ++#define DSCTRL_CSYNC_EN (1 << 10) ++#define DSCTRL_VS_SLAVE (1 << 7) ++#define DSCTRL_HS_SLAVE (1 << 6) ++#define DSCTRL_BLNK_POL (1 << 5) ++#define DSCTRL_BLNK_DIS (1 << 4) ++#define DSCTRL_VS_POL (1 << 3) ++#define DSCTRL_VS_DIS (1 << 2) ++#define DSCTRL_HS_POL (1 << 1) ++#define DSCTRL_HS_DIS (1 << 0) ++ ++/* DHT01 - Display horizontal timing register 01 */ ++#define DHT01_HBPS Fld(12,16) ++#define Dht01_Hbps(x) ((x) << FShft(DHT01_HBPS)) ++#define DHT01_HT Fld(12,0) ++#define Dht01_Ht(x) ((x) << FShft(DHT01_HT)) ++ ++/* DHT02 - Display horizontal timing register 02 */ ++#define DHT02_HAS Fld(12,16) ++#define Dht02_Has(x) ((x) << FShft(DHT02_HAS)) ++#define DHT02_HLBS Fld(12,0) ++#define Dht02_Hlbs(x) ((x) << FShft(DHT02_HLBS)) ++ ++/* DHT03 - Display horizontal timing register 03 */ ++#define DHT03_HFPS Fld(12,16) ++#define Dht03_Hfps(x) ((x) << FShft(DHT03_HFPS)) ++#define DHT03_HRBS Fld(12,0) ++#define Dht03_Hrbs(x) ((x) << FShft(DHT03_HRBS)) ++ ++/* DVT01 - Display vertical timing register 01 */ ++#define DVT01_VBPS Fld(12,16) ++#define Dvt01_Vbps(x) ((x) << FShft(DVT01_VBPS)) ++#define DVT01_VT Fld(12,0) ++#define Dvt01_Vt(x) ((x) << FShft(DVT01_VT)) ++ ++/* DVT02 - Display vertical timing register 02 */ ++#define DVT02_VAS Fld(12,16) ++#define Dvt02_Vas(x) ((x) << FShft(DVT02_VAS)) ++#define DVT02_VTBS Fld(12,0) ++#define Dvt02_Vtbs(x) ((x) << FShft(DVT02_VTBS)) ++ ++/* DVT03 - Display vertical timing register 03 */ ++#define DVT03_VFPS Fld(12,16) ++#define Dvt03_Vfps(x) ((x) << FShft(DVT03_VFPS)) ++#define DVT03_VBBS Fld(12,0) ++#define Dvt03_Vbbs(x) ((x) << FShft(DVT03_VBBS)) ++ ++/* DVECTRL - display vertical event control register */ ++#define DVECTRL_VEVENT Fld(12,16) ++#define Dvectrl_Vevent(x) ((x) << FShft(DVECTRL_VEVENT)) ++#define DVECTRL_VFETCH Fld(12,0) ++#define Dvectrl_Vfetch(x) ((x) << FShft(DVECTRL_VFETCH)) ++ ++/* DHDET - display horizontal DE timing register */ ++#define DHDET_HDES Fld(12,16) ++#define Dhdet_Hdes(x) ((x) << FShft(DHDET_HDES)) ++#define DHDET_HDEF Fld(12,0) ++#define Dhdet_Hdef(x) ((x) << FShft(DHDET_HDEF)) ++ ++/* DVDET - display vertical DE timing register */ ++#define DVDET_VDES Fld(12,16) ++#define Dvdet_Vdes(x) ((x) << FShft(DVDET_VDES)) ++#define DVDET_VDEF Fld(12,0) ++#define Dvdet_Vdef(x) ((x) << FShft(DVDET_VDEF)) ++ ++/* DODMSK - display output data mask register */ ++#define DODMSK_MASK_LVL (1 << 31) ++#define DODMSK_BLNK_LVL (1 << 30) ++#define DODMSK_MASK_B Fld(8,16) ++#define Dodmsk_Mask_B(x) ((x) << FShft(DODMSK_MASK_B)) ++#define DODMSK_MASK_G Fld(8,8) ++#define Dodmsk_Mask_G(x) ((x) << FShft(DODMSK_MASK_G)) ++#define DODMSK_MASK_R Fld(8,0) ++#define Dodmsk_Mask_R(x) ((x) << FShft(DODMSK_MASK_R)) ++ ++/* DBCOL - display border color control register */ ++#define DBCOL_BORDCOL Fld(24,0) ++#define Dbcol_Bordcol(x) ((x) << FShft(DBCOL_BORDCOL)) ++ ++/* DVLNUM - display vertical line number register */ ++#define DVLNUM_VLINE Fld(12,0) ++#define Dvlnum_Vline(x) ((x) << FShft(DVLNUM_VLINE)) ++ ++/* DMCTRL - Display Memory Control Register */ ++#define DMCTRL_MEM_REF Fld(2,30) ++#define DMCTRL_MEM_REF_ACT ((0x0) << FShft(DMCTRL_MEM_REF)) ++#define DMCTRL_MEM_REF_HB ((0x1) << FShft(DMCTRL_MEM_REF)) ++#define DMCTRL_MEM_REF_VB ((0x2) << FShft(DMCTRL_MEM_REF)) ++#define DMCTRL_MEM_REF_BOTH ((0x3) << FShft(DMCTRL_MEM_REF)) ++#define DMCTRL_UV_THRHLD Fld(6,24) ++#define Dmctrl_Uv_Thrhld(x) ((x) << FShft(DMCTRL_UV_THRHLD)) ++#define DMCTRL_V_THRHLD Fld(7,16) ++#define Dmctrl_V_Thrhld(x) ((x) << FShft(DMCTRL_V_THRHLD)) ++#define DMCTRL_D_THRHLD Fld(7,8) ++#define Dmctrl_D_Thrhld(x) ((x) << FShft(DMCTRL_D_THRHLD)) ++#define DMCTRL_BURSTLEN Fld(6,0) ++#define Dmctrl_Burstlen(x) ((x) << FShft(DMCTRL_BURSTLEN)) ++ ++ ++/* DLSTS - display load status register */ ++#define DLSTS_RLD_ADONE (1 << 23) ++/* #define DLSTS_RLD_ADOUT Fld(23,0) */ ++ ++/* DLLCTRL - display list load control register */ ++#define DLLCTRL_RLD_ADRLN Fld(8,24) ++#define Dllctrl_Rld_Adrln(x) ((x) << FShft(DLLCTRL_RLD_ADRLN)) ++ ++/* #define DSIG __REG_2700G(0x03FE2184) */ ++/* #define DINTRS __REG_2700G(0x03FE2178) */ ++/* #define DINTRE __REG_2700G(0x03FE217C) */ ++/* #define DINTRCNT __REG_2700G(0x03FE2180) */ ++/* #define DUCTRL __REG_2700G(0x03FE230C) */ ++ ++/* BGCOLOR - background color control register */ ++/* #define BGCOLOR __REG_2700G(0x03FE2174) */ ++ ++/* #define CLIPCTRL __REG_2700G(0x03FE218C) */ ++/* SPOCTRL - Scale Pitch/Order Control Register */ ++#define SPOCTRL_H_SC_BP (1 << 31) ++#define SPOCTRL_V_SC_BP (1 << 30) ++#define SPOCTRL_HV_SC_OR (1 << 29) ++#define SPOCTRL_VS_UR_C (1 << 27) ++#define SPOCTRL_VORDER Fld(2,16) ++#define SPOCTRL_VORDER_1TAP ((0x0) << FShft(SPOCTRL_VORDER)) ++#define SPOCTRL_VORDER_2TAP ((0x1) << FShft(SPOCTRL_VORDER)) ++#define SPOCTRL_VORDER_4TAP ((0x3) << FShft(SPOCTRL_VORDER)) ++#define SPOCTRL_VPITCH Fld(16,0) ++#define Spoctrl_Vpitch(x) ((x) << FShft(SPOCTRL_VPITCH)) ++ ++/* #define SVCTRL __REG_2700G(0x03FE2194) */ ++ ++/* /\* 0x03FE_2198 *\/ */ ++/* /\* 0x03FE_21A8 VSCOEFF[0:4] Video Scalar Vertical Coefficient [0:4] 4.14.5 *\/ */ ++ ++/* #define SHCTRL __REG_2700G(0x03FE21B0) */ ++ ++/* /\* 0x03FE_21B4 *\/ */ ++/* /\* 0x03FE_21D4 HSCOEFF[0:8] Video Scalar Horizontal Coefficient [0:8] 4.14.7 *\/ */ ++ ++/* #define SSSIZE __REG_2700G(0x03FE21D8) */ ++ ++/* /\* 0x03FE_2200 *\/ */ ++/* /\* 0x03FE_2240 VIDGAM[0:16] Video Gamma LUT Index [0:16] 4.15.2 *\/ */ ++ ++/* /\* 0x03FE_2250 *\/ */ ++/* /\* 0x03FE_2290 GFXGAM[0:16] Graphics Gamma LUT Index [0:16] 4.15.3 *\/ */ ++ ++/* #define CSC01 __REG_2700G(0x03FE2330) */ ++/* #define CSC02 __REG_2700G(0x03FE2334) */ ++/* #define CSC03 __REG_2700G(0x03FE2338) */ ++/* #define CSC04 __REG_2700G(0x03FE233C) */ ++/* #define CSC05 __REG_2700G(0x03FE2340) */ ++ ++#endif /* __REG_BITS_2700G_ */ +diff --git a/drivers/video/mbx/regs.h b/drivers/video/mbx/regs.h +new file mode 100644 +index 0000000..edf0f14 +--- /dev/null ++++ b/drivers/video/mbx/regs.h +@@ -0,0 +1,192 @@ ++#ifndef __REGS_2700G_ ++#define __REGS_2700G_ ++ ++/* extern unsigned long virt_base_2700; */ ++#define __REG_2700G(x) (*(volatile unsigned long*)((x)+virt_base_2700)) ++ ++/* System Configuration Registers (0x0000_0000 0x0000_0010) */ ++#define SYSCFG __REG_2700G(0x00000000) ++#define PFBASE __REG_2700G(0x00000004) ++#define PFCEIL __REG_2700G(0x00000008) ++#define POLLFLAG __REG_2700G(0x0000000c) ++#define SYSRST __REG_2700G(0x00000010) ++ ++/* Interrupt Control Registers (0x0000_0014 0x0000_002F) */ ++#define NINTPW __REG_2700G(0x00000014) ++#define MINTENABLE __REG_2700G(0x00000018) ++#define MINTSTAT __REG_2700G(0x0000001c) ++#define SINTENABLE __REG_2700G(0x00000020) ++#define SINTSTAT __REG_2700G(0x00000024) ++#define SINTCLR __REG_2700G(0x00000028) ++ ++/* Clock Control Registers (0x0000_002C 0x0000_005F) */ ++#define SYSCLKSRC __REG_2700G(0x0000002c) ++#define PIXCLKSRC __REG_2700G(0x00000030) ++#define CLKSLEEP __REG_2700G(0x00000034) ++#define COREPLL __REG_2700G(0x00000038) ++#define DISPPLL __REG_2700G(0x0000003c) ++#define PLLSTAT __REG_2700G(0x00000040) ++#define VOVRCLK __REG_2700G(0x00000044) ++#define PIXCLK __REG_2700G(0x00000048) ++#define MEMCLK __REG_2700G(0x0000004c) ++#define M24CLK __REG_2700G(0x00000054) ++#define MBXCLK __REG_2700G(0x00000054) ++#define SDCLK __REG_2700G(0x00000058) ++#define PIXCLKDIV __REG_2700G(0x0000005c) ++ ++/* LCD Port Control Register (0x0000_0060 0x0000_006F) */ ++#define LCD_CONFIG __REG_2700G(0x00000060) ++ ++/* On-Die Frame Buffer Registers (0x0000_0064 0x0000_006B) */ ++#define ODFBPWR __REG_2700G(0x00000064) ++#define ODFBSTAT __REG_2700G(0x00000068) ++ ++/* GPIO Registers (0x0000_006C 0x0000_007F) */ ++#define GPIOCGF __REG_2700G(0x0000006c) ++#define GPIOHI __REG_2700G(0x00000070) ++#define GPIOLO __REG_2700G(0x00000074) ++#define GPIOSTAT __REG_2700G(0x00000078) ++ ++/* Pulse Width Modulator (PWM) Registers (0x0000_0200 0x0000_02FF) */ ++#define PWMRST __REG_2700G(0x00000200) ++#define PWMCFG __REG_2700G(0x00000204) ++#define PWM0DIV __REG_2700G(0x00000210) ++#define PWM0DUTY __REG_2700G(0x00000214) ++#define PWM0PER __REG_2700G(0x00000218) ++#define PWM1DIV __REG_2700G(0x00000220) ++#define PWM1DUTY __REG_2700G(0x00000224) ++#define PWM1PER __REG_2700G(0x00000228) ++ ++/* Identification (ID) Registers (0x0000_0300 0x0000_0FFF) */ ++#define ID __REG_2700G(0x00000FF0) ++ ++/* Local Memory (SDRAM) Interface Registers (0x0000_1000 0x0000_1FFF) */ ++#define LMRST __REG_2700G(0x00001000) ++#define LMCFG __REG_2700G(0x00001004) ++#define LMPWR __REG_2700G(0x00001008) ++#define LMPWRSTAT __REG_2700G(0x0000100c) ++#define LMCEMR __REG_2700G(0x00001010) ++#define LMTYPE __REG_2700G(0x00001014) ++#define LMTIM __REG_2700G(0x00001018) ++#define LMREFRESH __REG_2700G(0x0000101c) ++#define LMPROTMIN __REG_2700G(0x00001020) ++#define LMPROTMAX __REG_2700G(0x00001024) ++#define LMPROTCFG __REG_2700G(0x00001028) ++#define LMPROTERR __REG_2700G(0x0000102c) ++ ++/* Plane Controller Registers (0x0000_2000 0x0000_2FFF) */ ++#define GSCTRL __REG_2700G(0x00002000) ++#define VSCTRL __REG_2700G(0x00002004) ++#define GBBASE __REG_2700G(0x00002020) ++#define VBBASE __REG_2700G(0x00002024) ++#define GDRCTRL __REG_2700G(0x00002040) ++#define VCMSK __REG_2700G(0x00002044) ++#define GSCADR __REG_2700G(0x00002060) ++#define VSCADR __REG_2700G(0x00002064) ++#define VUBASE __REG_2700G(0x00002084) ++#define VVBASE __REG_2700G(0x000020a4) ++#define GSADR __REG_2700G(0x000020c0) ++#define VSADR __REG_2700G(0x000020c4) ++#define HCCTRL __REG_2700G(0x00002100) ++#define HCSIZE __REG_2700G(0x00002110) ++#define HCPOS __REG_2700G(0x00002120) ++#define HCBADR __REG_2700G(0x00002130) ++#define HCCKMSK __REG_2700G(0x00002140) ++#define GPLUT __REG_2700G(0x00002150) ++#define DSCTRL __REG_2700G(0x00002154) ++#define DHT01 __REG_2700G(0x00002158) ++#define DHT02 __REG_2700G(0x0000215c) ++#define DHT03 __REG_2700G(0x00002160) ++#define DVT01 __REG_2700G(0x00002164) ++#define DVT02 __REG_2700G(0x00002168) ++#define DVT03 __REG_2700G(0x0000216c) ++#define DBCOL __REG_2700G(0x00002170) ++#define BGCOLOR __REG_2700G(0x00002174) ++#define DINTRS __REG_2700G(0x00002178) ++#define DINTRE __REG_2700G(0x0000217c) ++#define DINTRCNT __REG_2700G(0x00002180) ++#define DSIG __REG_2700G(0x00002184) ++#define DMCTRL __REG_2700G(0x00002188) ++#define CLIPCTRL __REG_2700G(0x0000218c) ++#define SPOCTRL __REG_2700G(0x00002190) ++#define SVCTRL __REG_2700G(0x00002194) ++ ++/* 0x0000_2198 */ ++/* 0x0000_21A8 VSCOEFF[0:4] Video Scalar Vertical Coefficient [0:4] 4.14.5 */ ++#define VSCOEFF0 __REG_2700G(0x00002198) ++#define VSCOEFF1 __REG_2700G(0x0000219c) ++#define VSCOEFF2 __REG_2700G(0x000021a0) ++#define VSCOEFF3 __REG_2700G(0x000021a4) ++#define VSCOEFF4 __REG_2700G(0x000021a8) ++ ++#define SHCTRL __REG_2700G(0x000021b0) ++ ++/* 0x0000_21B4 */ ++/* 0x0000_21D4 HSCOEFF[0:8] Video Scalar Horizontal Coefficient [0:8] 4.14.7 */ ++#define HSCOEFF0 __REG_2700G(0x000021b4) ++#define HSCOEFF1 __REG_2700G(0x000021b8) ++#define HSCOEFF2 __REG_2700G(0x000021bc) ++#define HSCOEFF3 __REG_2700G(0x000021b0) ++#define HSCOEFF4 __REG_2700G(0x000021c4) ++#define HSCOEFF5 __REG_2700G(0x000021c8) ++#define HSCOEFF6 __REG_2700G(0x000021cc) ++#define HSCOEFF7 __REG_2700G(0x000021d0) ++#define HSCOEFF8 __REG_2700G(0x000021d4) ++ ++#define SSSIZE __REG_2700G(0x000021D8) ++ ++/* 0x0000_2200 */ ++/* 0x0000_2240 VIDGAM[0:16] Video Gamma LUT Index [0:16] 4.15.2 */ ++#define VIDGAM0 __REG_2700G(0x00002200) ++#define VIDGAM1 __REG_2700G(0x00002204) ++#define VIDGAM2 __REG_2700G(0x00002208) ++#define VIDGAM3 __REG_2700G(0x0000220c) ++#define VIDGAM4 __REG_2700G(0x00002210) ++#define VIDGAM5 __REG_2700G(0x00002214) ++#define VIDGAM6 __REG_2700G(0x00002218) ++#define VIDGAM7 __REG_2700G(0x0000221c) ++#define VIDGAM8 __REG_2700G(0x00002220) ++#define VIDGAM9 __REG_2700G(0x00002224) ++#define VIDGAM10 __REG_2700G(0x00002228) ++#define VIDGAM11 __REG_2700G(0x0000222c) ++#define VIDGAM12 __REG_2700G(0x00002230) ++#define VIDGAM13 __REG_2700G(0x00002234) ++#define VIDGAM14 __REG_2700G(0x00002238) ++#define VIDGAM15 __REG_2700G(0x0000223c) ++#define VIDGAM16 __REG_2700G(0x00002240) ++ ++/* 0x0000_2250 */ ++/* 0x0000_2290 GFXGAM[0:16] Graphics Gamma LUT Index [0:16] 4.15.3 */ ++#define GFXGAM0 __REG_2700G(0x00002250) ++#define GFXGAM1 __REG_2700G(0x00002254) ++#define GFXGAM2 __REG_2700G(0x00002258) ++#define GFXGAM3 __REG_2700G(0x0000225c) ++#define GFXGAM4 __REG_2700G(0x00002260) ++#define GFXGAM5 __REG_2700G(0x00002264) ++#define GFXGAM6 __REG_2700G(0x00002268) ++#define GFXGAM7 __REG_2700G(0x0000226c) ++#define GFXGAM8 __REG_2700G(0x00002270) ++#define GFXGAM9 __REG_2700G(0x00002274) ++#define GFXGAM10 __REG_2700G(0x00002278) ++#define GFXGAM11 __REG_2700G(0x0000227c) ++#define GFXGAM12 __REG_2700G(0x00002280) ++#define GFXGAM13 __REG_2700G(0x00002284) ++#define GFXGAM14 __REG_2700G(0x00002288) ++#define GFXGAM15 __REG_2700G(0x0000228c) ++#define GFXGAM16 __REG_2700G(0x00002290) ++ ++#define DLSTS __REG_2700G(0x00002300) ++#define DLLCTRL __REG_2700G(0x00002304) ++#define DVLNUM __REG_2700G(0x00002308) ++#define DUCTRL __REG_2700G(0x0000230c) ++#define DVECTRL __REG_2700G(0x00002310) ++#define DHDET __REG_2700G(0x00002314) ++#define DVDET __REG_2700G(0x00002318) ++#define DODMSK __REG_2700G(0x0000231c) ++#define CSC01 __REG_2700G(0x00002330) ++#define CSC02 __REG_2700G(0x00002334) ++#define CSC03 __REG_2700G(0x00002338) ++#define CSC04 __REG_2700G(0x0000233c) ++#define CSC05 __REG_2700G(0x00002340) ++ ++#endif /* __REGS_2700G_ */ +diff --git a/drivers/video/pxafb.c b/drivers/video/pxafb.c +index 53ad61f..76675f6 100644 +--- a/drivers/video/pxafb.c ++++ b/drivers/video/pxafb.c +@@ -48,6 +48,11 @@ #include + #include + #include + ++#ifdef CONFIG_PXA27x ++#define LCCR4 __REG(0x44000010) /* LCD Controller Control Register 3 */ ++#endif ++ ++ + /* + * Complain if VAR is out of range. + */ +@@ -113,9 +118,15 @@ pxafb_setpalettereg(u_int regno, u_int r + if (fbi->fb.var.grayscale) { + val = ((blue >> 8) & 0x00ff); + } else { ++#ifdef CONFIG_ARMCORE_REV11 ++ val = (((red & 0xff) << 16) & 0xfc0000); ++ val |= (((green & 0xff) << 8) & 0xfc00); ++ val |= (((blue & 0xff) << 0) & 0x00fc); ++#else + val = ((red >> 0) & 0xf800); + val |= ((green >> 5) & 0x07e0); + val |= ((blue >> 11) & 0x001f); ++#endif + } + fbi->palette_cpu[regno] = val; + ret = 0; +@@ -426,6 +437,8 @@ static struct fb_ops pxafb_ops = { + * We take account of the PPCR clock setting. + * From PXA Developer's Manual: + * ++ * If PCDDIV = 0 then: ++ * + * PixelClock = LCLK + * ------------- + * 2 ( PCD + 1 ) +@@ -434,6 +447,17 @@ static struct fb_ops pxafb_ops = { + * ------------- - 1 + * 2(PixelClock) + * ++ * ++ * If PCDDIV = 1 then: ++ * ++ * PixelClock = LCLK ++ * ------------- ++ * ( PCD + 1 ) ++ * ++ * PCD = LCLK ++ * ------------- - 1 ++ * PixelClock ++ * + * Where: + * LCLK = LCD/Memory Clock + * PCD = LCCR3[7:0] +@@ -448,22 +472,64 @@ static struct fb_ops pxafb_ops = { + * PCD = (lclk * 10^4 ) * ( pixclock * 10^-12 ) + * -------------------------------------- - 1 + * 2 ++ * or ++ * PCD = (lclk * 10^4 ) * ( pixclock * 10^-12 ) - 1 + * + * Factoring the 10^4 and 10^-12 out gives 10^-8 == 1 / 100000000 as used below. + */ +-static inline unsigned int get_pcd(unsigned int pixclock) ++static inline unsigned int get_pcd(unsigned int pixclock, unsigned int *lccr4) + { +- unsigned long long pcd; ++ /* pcd1 is for PCDDIV=0 and pcd2 for PCDDIV=1 */ ++ unsigned long long pcd1, pcd2; ++ unsigned long long clk1, clk2; ++ unsigned long long dif1, dif2; ++ ++ *lccr4 = LCCR4; + + /* FIXME: Need to take into account Double Pixel Clock mode + * (DPC) bit? or perhaps set it based on the various clock + * speeds */ + +- pcd = (unsigned long long)get_lcdclk_frequency_10khz() * pixclock; +- do_div(pcd, 100000000 * 2); ++ pcd1 = pcd2 = (unsigned long long)get_lcdclk_frequency_10khz() * pixclock; ++ do_div(pcd1, 100000000 * 2); /* pcd1 /= 100000000 * 2; */ ++ do_div(pcd2, 100000000); /* pcd2 /= 100000000; */ ++ ++/* clk1 = 100000000*(2 * (pcd1 + 1))/get_lcdclk_frequency_10khz(); */ ++/* clk2 = 100000000*(pcd2 + 1)/get_lcdclk_frequency_10khz(); */ ++ ++ clk1 = 100000000*(2 * (pcd1 + 1)); ++ clk2 = 100000000*(pcd2 + 1); ++ do_div(clk1, get_lcdclk_frequency_10khz()); ++ do_div(clk2, get_lcdclk_frequency_10khz()); ++ ++ pr_debug("get_pcd: pcd1 = %lld, dotclock = %lld\n", pcd1, clk1); ++ pr_debug("get_pcd: pcd2 = %lld, dotclock = %lld\n", pcd2, clk2); ++ ++ dif1 = pixclock - clk1; ++ if ( clk1 > pixclock ) ++ dif1 *= -1; ++ ++ dif2 = pixclock - clk2; ++ if ( clk2 > pixclock ) ++ dif2 *= -1; ++ ++ if ( dif1 > dif2 ) { ++ *lccr4 |= (1 << 31); ++ pr_debug(KERN_INFO "get_pcd: setting pixclock to high rate\n"); ++ return (unsigned int)pcd2; ++ } ++ else { ++ *lccr4 &= ~(1 << 31); ++ pr_debug(KERN_INFO "get_pcd: setting pixclock to low rate\n"); ++ return (unsigned int)pcd1; ++ } ++ + /* no need for this, since we should subtract 1 anyway. they cancel */ + /* pcd += 1; */ /* make up for integer math truncations */ +- return (unsigned int)pcd; ++/* return (unsigned int)pcd2; */ ++ ++ /* never get here */ ++ return (unsigned int)0; + } + + /* +@@ -505,7 +571,9 @@ static int pxafb_activate_var(struct fb_ + { + struct pxafb_lcd_reg new_regs; + u_long flags; +- u_int lines_per_panel, pcd = get_pcd(var->pixclock); ++ u_int lines_per_panel; ++ u_int lccr4; ++ u_int pcd = get_pcd(var->pixclock, &lccr4); + + pr_debug("pxafb: Configuring PXA LCD\n"); + +@@ -735,10 +803,18 @@ static void pxafb_setup_gpio(struct pxaf + pxa_gpio_mode(GPIO75_LCD_LCLK_MD); + pxa_gpio_mode(GPIO76_LCD_PCLK_MD); + pxa_gpio_mode(GPIO77_LCD_ACBIAS_MD); ++ ++#ifdef CONFIG_ARMCORE_REV11 ++ pxa_gpio_mode(86 | GPIO_ALT_FN_2_OUT); ++ pxa_gpio_mode(87 | GPIO_ALT_FN_2_OUT); ++#endif + } + + static void pxafb_enable_controller(struct pxafb_info *fbi) + { ++ unsigned int lccr4; ++ unsigned int pcd = get_pcd(fbi->fb.var.pixclock, &lccr4); ++ + pr_debug("pxafb: Enabling LCD controller\n"); + pr_debug("fdadr0 0x%08x\n", (unsigned int) fbi->fdadr0); + pr_debug("fdadr1 0x%08x\n", (unsigned int) fbi->fdadr1); +@@ -751,7 +827,20 @@ static void pxafb_enable_controller(stru + pxa_set_cken(CKEN16_LCD, 1); + + /* Sequence from 11.7.10 */ +- LCCR3 = fbi->reg_lccr3; ++#ifdef CONFIG_ARMCORE_REV12 ++ LCCR4 = lccr4; ++#else ++ LCCR4 = 0 | (2 << 15) | lccr4; ++#endif ++ ++ fbi->reg_lccr3 = (fbi->reg_lccr3 & ~0xff) | LCCR3_PixClkDiv(pcd); ++ ++#ifdef CONFIG_ARMCORE_REV12 ++ LCCR3 = (fbi->reg_lccr3);//& (~(7 << 24))) | (3 << 24); ++#else ++ LCCR3 = (fbi->reg_lccr3 | (3 << 30)) ;//& (~(7 << 24))) | (3 << 24); ++#endif ++ + LCCR2 = fbi->reg_lccr2; + LCCR1 = fbi->reg_lccr1; + LCCR0 = fbi->reg_lccr0 & ~LCCR0_ENB; +@@ -1083,6 +1172,7 @@ static struct pxafb_info * __init pxafb_ + addr = addr + sizeof(struct pxafb_info); + fbi->fb.pseudo_palette = addr; + ++ fbi->fb.var.pixclock = inf->pixclock; + fbi->max_xres = inf->xres; + fbi->fb.var.xres = inf->xres; + fbi->fb.var.xres_virtual = inf->xres; +diff --git a/include/asm-arm/arch-pxa/cm-x270.h b/include/asm-arm/arch-pxa/cm-x270.h +new file mode 100644 +index 0000000..f2d3675 +--- /dev/null ++++ b/include/asm-arm/arch-pxa/cm-x270.h +@@ -0,0 +1,169 @@ ++/* ++ * linux/include/asm/arch-pxa/armcore.h ++ * ++ * Compulab Ltd., 2003 ++ * ++ * ARMCore registers ++ */ ++ ++#include ++ ++#define CMX270_CS1_PHYS (PXA_CS1_PHYS) ++#define MARATHON_PHYS (PXA_CS2_PHYS) ++#define CMX270_IDE104_PHYS (PXA_CS3_PHYS) ++#define CMX270_IT8152_PHYS (PXA_CS4_PHYS) ++ ++#define PXA_CS_SIZE (64*1024*1024) ++ ++/* Virtual map */ ++ ++#define CMX270_VIRT_BASE (0xe8000000) ++/* #define MARATHON_VIRT (CMX270_VIRT_BASE) */ ++ ++#define CMX270_IT8152_VIRT (CMX270_VIRT_BASE) ++ ++#define CMX270_IDE104_VIRT (CMX270_IT8152_VIRT + PXA_CS_SIZE) ++#ifdef CONFIG_CMX270_SB270 ++#define CMX270_IDECS0_VIRT (CMX270_IDE104_VIRT + (1<<24) + (1<<25)) ++#define CMX270_IDECS1_VIRT (CMX270_IDE104_VIRT + (1<<25)) ++#else ++#define CMX270_IDECS0_VIRT (CMX270_IDE104_VIRT + (1<<25)) ++#define CMX270_IDECS1_VIRT (CMX270_IDE104_VIRT + (1<<25) + (1<<22)) ++#endif ++ ++/* #define CMX270_RTC_VIRT (CMX270_CS1_VIRT + (5<<22)) */ ++ ++ ++/* GPIO related definitions */ ++#define GPIO_IT8152_IRQ (22) ++#define GPIO_RED_LED (93) ++#define GPIO_GREEN_LED (94) ++ ++ ++#define IRQ_GPIO_IT8152_IRQ IRQ_GPIO(GPIO_IT8152_IRQ) ++#define PME_IRQ IRQ_GPIO(0) ++#define CMX270_IDE_IRQ IRQ_GPIO(100) ++#define CMX270_GPIRQ1 IRQ_GPIO(101) ++#define CMX270_TOUCHIRQ IRQ_GPIO(96) ++#define CMX270_ETHIRQ IRQ_GPIO(10) ++#define CMX270_GFXIRQ IRQ_GPIO(95) ++#define CMX270_NANDIRQ IRQ_GPIO(89) ++#define ARMCORE_MMC_IRQ IRQ_GPIO(83) ++ ++/* LED macros */ ++#define CMX270_RED_ON() GPCR(GPIO_RED_LED) = GPIO_bit(GPIO_RED_LED) ++#define CMX270_RED_OFF() GPSR(GPIO_RED_LED) = GPIO_bit(GPIO_RED_LED) ++#define CMX270_GREEN_ON() GPCR(GPIO_GREEN_LED) = GPIO_bit(GPIO_GREEN_LED) ++#define CMX270_GREEN_OFF() GPSR(GPIO_GREEN_LED) = GPIO_bit(GPIO_GREEN_LED) ++ ++/* PCMCIA related definitions */ ++#define PCC_DETECT(x) (GPLR(84 - (x)) & GPIO_bit(84 - (x))) ++#define PCC_READY(x) (GPLR(82 - (x)) & GPIO_bit(81 - (x))) ++ ++#define PCMCIA_S0_CD_VALID IRQ_GPIO(84) ++#define PCMCIA_S0_CD_VALID_EDGE GPIO_BOTH_EDGES ++ ++#define PCMCIA_S1_CD_VALID IRQ_GPIO(83) ++#define PCMCIA_S1_CD_VALID_EDGE GPIO_BOTH_EDGES ++ ++#define PCMCIA_S0_RDYINT IRQ_GPIO(82) ++#define PCMCIA_S1_RDYINT IRQ_GPIO(81) ++ ++#define PCMCIA_RESET_GPIO 53 ++ ++ ++/* #define IT8152_IO_BASE (CMX270_IT8152_VIRT + 0x03e00000) */ ++/* #define IT8152_CFGREG_BASE (CMX270_IT8152_VIRT + 0x03f00000) */ ++/* #define CMX270_CS1_VIRT (CMX270_IT8152_VIRT + PXA_CS_SIZE) */ ++/* #define IT8152_SHORT_IO(x) (*((volatile unsigned short *)(IT8152_CFGREG_BASE+(x)))) */ ++/* #define IT8152_LONG_IO(x) (*((volatile unsigned long *)(IT8152_CFGREG_BASE+(x)))) */ ++ ++ ++/* /\* PCI related definitions *\/ */ ++ ++/* /\* #define PCIBIOS_MIN_IO (IT8152_IO_BASE + 0x12000) *\/ */ ++/* /\* #define PCIBIOS_MIN_MEM (0x10000000) *\/ */ ++ ++ ++/* #define IT8152_PCI_IACK (*((volatile unsigned long *)(CMX270_IT8152_VIRT + 0x3f00808))) */ ++/* #define IT8152_PCI_CFG_ADDR (*((volatile unsigned long *)(CMX270_IT8152_VIRT + 0x3f00800))) */ ++/* #define IT8152_PCI_CFG_DATA (*((volatile unsigned long *)(CMX270_IT8152_VIRT + 0x3f00804))) */ ++/* #define IT8152_PCI_MEMBASE (*((volatile unsigned long *)(CMX270_IT8152_VIRT))) */ ++/* #define IT8152_PCI_IOBASE (*((volatile unsigned long *)(CMX270_IT8152_VIRT + 0x3e00000))) */ ++ ++/* #define IT_BUSNUM_SHF 16 */ ++/* #define IT_DEVNUM_SHF 11 */ ++/* #define IT_FUNCNUM_SHF 8 */ ++/* #define IT_REGNUM_SHF 2 */ ++ ++ ++/* /\* Power management & PLL registers *\/ */ ++/* #define IT8152_PMPLL_DSR IT8152_LONG_IO(0x00) */ ++/* #define IT8152_PMPLL_DSSR IT8152_LONG_IO(0x04) */ ++/* #define IT8152_PMPLL_PLLCR IT8152_LONG_IO(0x20) */ ++/* #define IT8152_PMPLL_MFSR IT8152_LONG_IO(0x24) */ ++ ++ ++/* /\* Memory controller *\/ */ ++/* #define IT8152_MC_REG_OFFSET 0x100 */ ++ ++/* #define IT8152_MC_SDCR IT8152_LONG_IO(IT8152_MC_REG_OFFSET + 0x00) */ ++/* #define IT8152_MC_PCICR IT8152_LONG_IO(IT8152_MC_REG_OFFSET + 0x04) */ ++ ++/* /\* Interrupt related definitions *\/ */ ++/* #define IT8152_INTC_REG_OFFSET 0x300 */ ++ ++/* #define IT8152_INTC_LDCNIRR IT8152_LONG_IO(IT8152_INTC_REG_OFFSET + 0x00) */ ++/* #define IT8152_INTC_LDPNIRR IT8152_LONG_IO(IT8152_INTC_REG_OFFSET + 0x04) */ ++/* #define IT8152_INTC_LDCNIMR IT8152_LONG_IO(IT8152_INTC_REG_OFFSET + 0x08) */ ++/* #define IT8152_INTC_LDPNIMR IT8152_LONG_IO(IT8152_INTC_REG_OFFSET + 0x0C) */ ++/* #define IT8152_INTC_LDNITR IT8152_LONG_IO(IT8152_INTC_REG_OFFSET + 0x10) */ ++/* #define IT8152_INTC_LDNIAR IT8152_LONG_IO(IT8152_INTC_REG_OFFSET + 0x14) */ ++/* #define IT8152_INTC_LPCNIRR IT8152_LONG_IO(IT8152_INTC_REG_OFFSET + 0x20) */ ++/* #define IT8152_INTC_LPPNIRR IT8152_LONG_IO(IT8152_INTC_REG_OFFSET + 0x24) */ ++/* #define IT8152_INTC_LPCNIMR IT8152_LONG_IO(IT8152_INTC_REG_OFFSET + 0x28) */ ++/* #define IT8152_INTC_LPPNIMR IT8152_LONG_IO(IT8152_INTC_REG_OFFSET + 0x2C) */ ++/* #define IT8152_INTC_LPNITR IT8152_LONG_IO(IT8152_INTC_REG_OFFSET + 0x30) */ ++/* #define IT8152_INTC_LPNIAR IT8152_LONG_IO(IT8152_INTC_REG_OFFSET + 0x34) */ ++/* #define IT8152_INTC_PDCNIRR IT8152_LONG_IO(IT8152_INTC_REG_OFFSET + 0x40) */ ++/* #define IT8152_INTC_PDPNIRR IT8152_LONG_IO(IT8152_INTC_REG_OFFSET + 0x44) */ ++/* #define IT8152_INTC_PDCNIMR IT8152_LONG_IO(IT8152_INTC_REG_OFFSET + 0x48) */ ++/* #define IT8152_INTC_PDPNIMR IT8152_LONG_IO(IT8152_INTC_REG_OFFSET + 0x4C) */ ++/* #define IT8152_INTC_PDNITR IT8152_LONG_IO(IT8152_INTC_REG_OFFSET + 0x50) */ ++/* #define IT8152_INTC_PDNIAR IT8152_LONG_IO(IT8152_INTC_REG_OFFSET + 0x54) */ ++/* #define IT8152_INTC_INTC_TYPER IT8152_LONG_IO(IT8152_INTC_REG_OFFSET + 0xFC) */ ++ ++/* #define IT8152_UART_BASE IT8152_LONG_IO(0x200) */ ++ ++/* #define IT8152_GPIO_REG_OFFSET 0x500 */ ++ ++/* #define IT8152_GPIO_GPLR IT8152_LONG_IO(IT8152_GPIO_REG_OFFSET) */ ++/* #define IT8152_GPIO_GPCR12 IT8152_LONG_IO(IT8152_GPIO_REG_OFFSET + 0x04) */ ++/* #define IT8152_GPIO_GPCR34 IT8152_LONG_IO(IT8152_GPIO_REG_OFFSET + 0x08) */ ++ ++ ++/* /\* Interrupt bit definitions *\/ */ ++/* #define PCISERR_BIT (1<<14) */ ++/* #define H2PTADR_BIT (1<<13) */ ++/* #define H2PMAR_BIT (1<<12) */ ++/* #define PCI_INTD_BIT (1<<11) */ ++/* #define PCI_INTC_BIT (1<<10) */ ++/* #define PCI_INTB_BIT (1<<9) */ ++/* #define PCI_INTA_BIT (1<<8) */ ++/* #define CDMA_INT_BIT (1<<2) */ ++/* #define USB_INT_BIT (1<<1) */ ++/* #define AUDIO_INT_BIT (1<<0) */ ++ ++/* // IT8152 UART */ ++/* #define ITESER_BIT (1<<5) */ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ +diff --git a/include/asm-arm/arch-pxa/hardware.h b/include/asm-arm/arch-pxa/hardware.h +index 3e70bd9..cb4fb2f 100644 +--- a/include/asm-arm/arch-pxa/hardware.h ++++ b/include/asm-arm/arch-pxa/hardware.h +@@ -80,4 +80,15 @@ extern unsigned int get_lcdclk_frequency + + #endif + ++#if defined(CONFIG_MACH_ARMCORE) && defined(CONFIG_PCI) ++#define HAVE_ARCH_PCI_SET_DMA_MASK ++#ifndef __ASSEMBLY__ ++extern unsigned long armcore_pcibios_min_io; ++extern unsigned long armcore_pcibios_min_mem; ++#endif ++#define PCIBIOS_MIN_IO (armcore_pcibios_min_io) ++#define PCIBIOS_MIN_MEM (armcore_pcibios_min_mem) ++#define pcibios_assign_all_busses() 1 ++#endif ++ + #endif /* _ASM_ARCH_HARDWARE_H */ +diff --git a/include/asm-arm/arch-pxa/irqs.h b/include/asm-arm/arch-pxa/irqs.h +index 05c4b70..f0259cd 100644 +--- a/include/asm-arm/arch-pxa/irqs.h ++++ b/include/asm-arm/arch-pxa/irqs.h +@@ -176,7 +176,8 @@ #define NR_IRQS (IRQ_S1_BVD1_STSCHG + + #elif defined(CONFIG_SHARP_LOCOMO) + #define NR_IRQS (IRQ_LOCOMO_SPI_TEND + 1) + #elif defined(CONFIG_ARCH_LUBBOCK) || \ +- defined(CONFIG_MACH_MAINSTONE) ++ defined(CONFIG_MACH_MAINSTONE) || \ ++ defined(CONFIG_MACH_ARMCORE) + #define NR_IRQS (IRQ_BOARD_END) + #else + #define NR_IRQS (IRQ_BOARD_START) +@@ -217,3 +218,24 @@ #define IRQ_LOCOMO_KEY_BASE (IRQ_BOARD_S + #define IRQ_LOCOMO_GPIO_BASE (IRQ_BOARD_START + 1) + #define IRQ_LOCOMO_LT_BASE (IRQ_BOARD_START + 2) + #define IRQ_LOCOMO_SPI_BASE (IRQ_BOARD_START + 3) ++ ++/* ITE8152 irqs on CM-x2xx */ ++#ifdef CONFIG_MACH_ARMCORE ++#define IT8152_IRQ(x) (IRQ_BOARD_START + (x)) ++#define PCISERR IT8152_IRQ(0) ++#define H2PTADR IT8152_IRQ(1) ++#define H2PMAR IT8152_IRQ(2) ++#define PCI_INTA IT8152_IRQ(3) ++#define PCI_INTB IT8152_IRQ(4) ++#define PCI_INTC IT8152_IRQ(5) ++#define PCI_INTD IT8152_IRQ(6) ++#define USB_INT IT8152_IRQ(7) ++#define AUDIO_INT IT8152_IRQ(8) ++#define CDMA_INT IT8152_IRQ(9) ++#define IRQ_ITESER IT8152_IRQ(10) ++#define IT8152_IRQ_MAX IT8152_IRQ(10) ++ ++ ++#undef NR_IRQS ++#define NR_IRQS IT8152_IRQ_MAX+1 ++#endif +diff --git a/include/asm-arm/arch-pxa/marathonfb.h b/include/asm-arm/arch-pxa/marathonfb.h +new file mode 100644 +index 0000000..97b69ef +--- /dev/null ++++ b/include/asm-arm/arch-pxa/marathonfb.h +@@ -0,0 +1,28 @@ ++#ifndef __MARATHON_FB_H ++#define __MARATHON_FB_H ++ ++struct mbxfb_val { ++ unsigned int defval; ++ unsigned int min; ++ unsigned int max; ++}; ++ ++struct fb_info; ++ ++struct mbxfb_platform_data { ++ /* Screen info */ ++ struct mbxfb_val xres; ++ struct mbxfb_val yres; ++ struct mbxfb_val bpp; ++ ++ /* Memory info */ ++ unsigned long memsize; /* if 0 use ODFB? */ ++ unsigned long timings1; ++ unsigned long timings2; ++ unsigned long timings3; ++ ++ int (*probe)(struct fb_info *fb); ++ int (*remove)(struct fb_info *fb); ++}; ++ ++#endif /* __MARATHON_FB_H */ +diff --git a/include/asm-arm/arch-pxa/memory.h b/include/asm-arm/arch-pxa/memory.h +index eaf6d43..98807e7 100644 +--- a/include/asm-arm/arch-pxa/memory.h ++++ b/include/asm-arm/arch-pxa/memory.h +@@ -17,6 +17,19 @@ #define __ASM_ARCH_MEMORY_H + */ + #define PHYS_OFFSET UL(0xa0000000) + ++ ++#ifdef CONFIG_PCI_HOST_ITE8152 ++#ifndef __ASSEMBLY__ ++void it8152_adjust_zones(int node, unsigned long *size, unsigned long *holes); ++ ++#define arch_adjust_zones(node, size, holes) \ ++ it8152_adjust_zones(node, size, holes) ++ ++#define ISA_DMA_THRESHOLD (SZ_64M - 1) ++#endif ++#endif ++ ++ + /* + * Virtual view <-> DMA view memory address translations + * virt_to_bus: Used to translate the virtual address to an +diff --git a/include/asm-arm/arch-pxa/pxafbsetup.h b/include/asm-arm/arch-pxa/pxafbsetup.h +new file mode 100644 +index 0000000..8a7c8de +--- /dev/null ++++ b/include/asm-arm/arch-pxa/pxafbsetup.h +@@ -0,0 +1,39 @@ ++/* ++ Panel specific LCD controller setup ++ */ ++ ++#ifndef _PXAFBSETUP_H ++#define _PXAFBSETUP_H ++ ++#define MTYPE_STN320x240 0 ++#define MTYPE_TFT640x480 1 ++#define MTYPE_CRT640x480 2 ++#define MTYPE_CRT800x600 3 ++#define MTYPE_CRT1024x768 4 ++#define MTYPE_USER_DEFINED 5 ++#define MTYPE_TFT320x240 6 ++#define MTYPE_STN640x480 7 ++ ++#define CMAP_GREYSCALE 0 ++#define CMAP_INVERSE 0 ++#define CMAP_STATIC 0 ++ ++ ++// Example for user defined display ++// Hitach SX19V-009 ++#define LCD_PIXCLOCK 38461 ++#define LCD_BPP 8 ++#define LCD_XRES 640 ++#define LCD_YRES 480 ++#define LCD_HORIZONTAL_SYNC_PULSE_WIDTH 4 ++#define LCD_VERTICAL_SYNC_PULSE_WIDTH 2 ++#define LCD_BEGIN_OF_LINE_WAIT_COUNT 10 ++#define LCD_BEGIN_FRAME_WAIT_COUNT 5 ++#define LCD_END_OF_LINE_WAIT_COUNT 10 ++#define LCD_END_OF_FRAME_WAIT_COUNT 5 ++#define LCD_SYNC (FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT) ++#define LCD_LCCR0 (LCCR0_LDM | LCCR0_IUM | LCCR0_QDM | LCCR0_BM | LCCR0_OUM ) ++#define LCD_LCCR3 (LCCR3_PixClkDiv(0x02) | LCCR3_Acb(0xff)) ++#define LCD_NAME "Hitachi SX19V-009-ZZA-1" ++ ++#endif +diff --git a/include/asm-arm/hardware/it8152.h b/include/asm-arm/hardware/it8152.h +new file mode 100644 +index 0000000..d28210d +--- /dev/null ++++ b/include/asm-arm/hardware/it8152.h +@@ -0,0 +1,104 @@ ++/* ++ * arch/arm/mach-pxa/it8152.h ++ * ++ * Compulab Ltd., 2006 ++ * ++ * ITE 8152 companion chip definitions ++ */ ++ ++ ++/* #define CMX270_IT8152_VIRT (CMX270_VIRT_BASE) */ ++ ++ ++extern unsigned long it8152_base_address; ++ ++#define IT8152_IO_BASE (it8152_base_address + 0x03e00000) ++#define IT8152_CFGREG_BASE (it8152_base_address + 0x03f00000) ++ ++/* #define IRQ_GPIO_IT8152_IRQ IRQ_GPIO(GPIO_IT8152_IRQ) */ ++ ++#define IT8152_SHORT_IO(x) (*((volatile unsigned short *)(IT8152_CFGREG_BASE+(x)))) ++#define IT8152_LONG_IO(x) (*((volatile unsigned long *)(IT8152_CFGREG_BASE+(x)))) ++ ++ ++#define IT8152_PCI_MEMBASE (*((volatile unsigned long *)(it8152_base_address))) ++/* #define IT8152_PCI_IOBASE (*((volatile unsigned long *)(it8152_base_address + 0x3e00000))) */ ++ ++#define IT8152_PCI_IACK (*((volatile unsigned long *)(it8152_base_address + 0x3f00808))) ++#define IT8152_PCI_CFG_ADDR (*((volatile unsigned long *)(it8152_base_address + 0x3f00800))) ++#define IT8152_PCI_CFG_DATA (*((volatile unsigned long *)(it8152_base_address + 0x3f00804))) ++ ++#define IT_BUSNUM_SHF 16 ++#define IT_DEVNUM_SHF 11 ++#define IT_FUNCNUM_SHF 8 ++#define IT_REGNUM_SHF 2 ++ ++/* Power management & PLL registers */ ++#define IT8152_PMPLL_DSR IT8152_LONG_IO(0x00) ++#define IT8152_PMPLL_DSSR IT8152_LONG_IO(0x04) ++#define IT8152_PMPLL_PLLCR IT8152_LONG_IO(0x20) ++#define IT8152_PMPLL_MFSR IT8152_LONG_IO(0x24) ++ ++/* Memory controller */ ++#define IT8152_MC_REG_OFFSET 0x100 ++ ++#define IT8152_MC_SDCR IT8152_LONG_IO(IT8152_MC_REG_OFFSET + 0x00) ++#define IT8152_MC_PCICR IT8152_LONG_IO(IT8152_MC_REG_OFFSET + 0x04) ++ ++/* Interrupt related definitions */ ++#define IT8152_INTC_REG_OFFSET 0x300 ++ ++#define IT8152_INTC_LDCNIRR IT8152_LONG_IO(IT8152_INTC_REG_OFFSET + 0x00) ++#define IT8152_INTC_LDPNIRR IT8152_LONG_IO(IT8152_INTC_REG_OFFSET + 0x04) ++#define IT8152_INTC_LDCNIMR IT8152_LONG_IO(IT8152_INTC_REG_OFFSET + 0x08) ++#define IT8152_INTC_LDPNIMR IT8152_LONG_IO(IT8152_INTC_REG_OFFSET + 0x0C) ++#define IT8152_INTC_LDNITR IT8152_LONG_IO(IT8152_INTC_REG_OFFSET + 0x10) ++#define IT8152_INTC_LDNIAR IT8152_LONG_IO(IT8152_INTC_REG_OFFSET + 0x14) ++#define IT8152_INTC_LPCNIRR IT8152_LONG_IO(IT8152_INTC_REG_OFFSET + 0x20) ++#define IT8152_INTC_LPPNIRR IT8152_LONG_IO(IT8152_INTC_REG_OFFSET + 0x24) ++#define IT8152_INTC_LPCNIMR IT8152_LONG_IO(IT8152_INTC_REG_OFFSET + 0x28) ++#define IT8152_INTC_LPPNIMR IT8152_LONG_IO(IT8152_INTC_REG_OFFSET + 0x2C) ++#define IT8152_INTC_LPNITR IT8152_LONG_IO(IT8152_INTC_REG_OFFSET + 0x30) ++#define IT8152_INTC_LPNIAR IT8152_LONG_IO(IT8152_INTC_REG_OFFSET + 0x34) ++#define IT8152_INTC_PDCNIRR IT8152_LONG_IO(IT8152_INTC_REG_OFFSET + 0x40) ++#define IT8152_INTC_PDPNIRR IT8152_LONG_IO(IT8152_INTC_REG_OFFSET + 0x44) ++#define IT8152_INTC_PDCNIMR IT8152_LONG_IO(IT8152_INTC_REG_OFFSET + 0x48) ++#define IT8152_INTC_PDPNIMR IT8152_LONG_IO(IT8152_INTC_REG_OFFSET + 0x4C) ++#define IT8152_INTC_PDNITR IT8152_LONG_IO(IT8152_INTC_REG_OFFSET + 0x50) ++#define IT8152_INTC_PDNIAR IT8152_LONG_IO(IT8152_INTC_REG_OFFSET + 0x54) ++#define IT8152_INTC_INTC_TYPER IT8152_LONG_IO(IT8152_INTC_REG_OFFSET + 0xFC) ++ ++#define IT8152_UART_BASE IT8152_LONG_IO(0x200) ++ ++#define IT8152_GPIO_REG_OFFSET 0x500 ++ ++#define IT8152_GPIO_GPLR IT8152_LONG_IO(IT8152_GPIO_REG_OFFSET) ++#define IT8152_GPIO_GPCR12 IT8152_LONG_IO(IT8152_GPIO_REG_OFFSET + 0x04) ++#define IT8152_GPIO_GPCR34 IT8152_LONG_IO(IT8152_GPIO_REG_OFFSET + 0x08) ++ ++ ++/* Interrupt bit definitions */ ++#define PCISERR_BIT (1<<14) ++#define H2PTADR_BIT (1<<13) ++#define H2PMAR_BIT (1<<12) ++#define PCI_INTD_BIT (1<<11) ++#define PCI_INTC_BIT (1<<10) ++#define PCI_INTB_BIT (1<<9) ++#define PCI_INTA_BIT (1<<8) ++#define CDMA_INT_BIT (1<<2) ++#define USB_INT_BIT (1<<1) ++#define AUDIO_INT_BIT (1<<0) ++ ++/* IT8152 UART */ ++#define ITESER_BIT (1<<5) ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ +diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h +index 751eea5..bc45d11 100644 +--- a/include/linux/pci_ids.h ++++ b/include/linux/pci_ids.h +@@ -1568,6 +1568,7 @@ #define PCI_DEVICE_ID_EFFICEON 0x0060 + #define PCI_VENDOR_ID_ROCKWELL 0x127A + + #define PCI_VENDOR_ID_ITE 0x1283 ++#define PCI_DEVICE_ID_ITE_IT8152 0x8152 + #define PCI_DEVICE_ID_ITE_IT8172G 0x8172 + #define PCI_DEVICE_ID_ITE_IT8172G_AUDIO 0x0801 + #define PCI_DEVICE_ID_ITE_8211 0x8211 +diff --git a/sound/pci/ac97/ac97_codec.c b/sound/pci/ac97/ac97_codec.c +index 3020ca2..ba1dc8a 100644 +--- a/sound/pci/ac97/ac97_codec.c ++++ b/sound/pci/ac97/ac97_codec.c +@@ -150,7 +150,7 @@ static const struct ac97_codec_id snd_ac + { 0x4e534300, 0xffffffff, "LM4540,43,45,46,48", NULL, NULL }, // only guess --jk + { 0x4e534331, 0xffffffff, "LM4549", NULL, NULL }, + { 0x4e534350, 0xffffffff, "LM4550", NULL, NULL }, +-{ 0x50534304, 0xffffffff, "UCB1400", NULL, NULL }, ++{ 0x50534304, 0xffffffff, "UCB1400", patch_ucb1400, NULL }, + { 0x53494c20, 0xffffffe0, "Si3036,8", mpatch_si3036, mpatch_si3036, AC97_MODEM_PATCH }, + { 0x54524102, 0xffffffff, "TR28022", NULL, NULL }, + { 0x54524106, 0xffffffff, "TR28026", NULL, NULL }, +diff --git a/sound/pci/ac97/ac97_patch.c b/sound/pci/ac97/ac97_patch.c +index a444a78..0bb1d71 100644 +--- a/sound/pci/ac97/ac97_patch.c ++++ b/sound/pci/ac97/ac97_patch.c +@@ -2823,3 +2823,33 @@ int mpatch_si3036(struct snd_ac97 * ac97 + snd_ac97_write_cache(ac97, 0x68, 0); + return 0; + } ++ ++/* ++ * UCB1400 codec ++ */ ++static const struct snd_kcontrol_new snd_ac97_controls_ucb1400[] = { ++AC97_SINGLE("Headphone driver", 0x6a, 6, 1, 0), ++AC97_SINGLE("DC filter", 0x6a, 4, 1, 0), ++AC97_SINGLE("Smart power mode", 0x6c, 4, 3, 0), ++}; ++ ++static int patch_ucb1400_specific(struct snd_ac97 * ac97) ++{ ++ int idx, err; ++ for (idx = 0; idx < ARRAY_SIZE(snd_ac97_controls_ucb1400); idx++) ++ if ((err = snd_ctl_add(ac97->bus->card, snd_ctl_new1(&snd_ac97_controls_ucb1400[idx], ac97))) < 0) ++ return err; ++ return 0; ++} ++ ++static struct snd_ac97_build_ops patch_ucb1400_ops = { ++ .build_specific = patch_ucb1400_specific, ++}; ++ ++int patch_ucb1400(struct snd_ac97 * ac97) ++{ ++ ac97->build_ops = &patch_ucb1400_ops; ++ snd_ac97_write(ac97, 0x6a, 0x0050); ++ snd_ac97_write(ac97, 0x6c, 0x0030); ++ return 0; ++} +diff --git a/sound/pci/ac97/ac97_patch.h b/sound/pci/ac97/ac97_patch.h +index 5060cb6..068b674 100644 +--- a/sound/pci/ac97/ac97_patch.h ++++ b/sound/pci/ac97/ac97_patch.h +@@ -58,4 +58,5 @@ int patch_cm9780(struct snd_ac97 * ac97) + int patch_vt1616(struct snd_ac97 * ac97); + int patch_vt1617a(struct snd_ac97 * ac97); + int patch_it2646(struct snd_ac97 * ac97); ++int patch_ucb1400(struct snd_ac97 * ac97); + int mpatch_si3036(struct snd_ac97 * ac97); diff --git a/meta/packages/linux/linux-cmx270-rp_2.6.17.bb b/meta/packages/linux/linux-cmx270-rp_2.6.17.bb index 846095e401..a67dd4efcb 100644 --- a/meta/packages/linux/linux-cmx270-rp_2.6.17.bb +++ b/meta/packages/linux/linux-cmx270-rp_2.6.17.bb @@ -3,6 +3,8 @@ DESCRIPTION = "Linux kernel for Compulab cmx270" LICENSE = "GPL" PR = "r1" +DEFAULT_PREFERENCE = "-1" + SRC_URI = "http://www.kernel.org/pub/linux/kernel/v2.6/linux-2.6.17.tar.bz2 \ http://www.rpsys.net/openzaurus/patches/archive/cmx270/cm_x2xx_ide-r1.patch;patch=1 \ http://www.rpsys.net/openzaurus/patches/archive/cmx270/cm_x2xx_mtd-r2.patch;patch=1 \ diff --git a/meta/packages/linux/linux-cmx270_2.6.16.bb b/meta/packages/linux/linux-cmx270_2.6.16.bb new file mode 100644 index 0000000000..1101c06e87 --- /dev/null +++ b/meta/packages/linux/linux-cmx270_2.6.16.bb @@ -0,0 +1,34 @@ +SECTION = "kernel" +DESCRIPTION = "Linux kernel CM-X270" +LICENSE = "GPL" +PR = "r1" + +SRC_URI = "http://www.kernel.org/pub/linux/kernel/v2.6/linux-2.6.16.tar.bz2 \ + file://diff-2.6.16-cm-x270;patch=1 \ + file://CL_FlashDrv" + +S = "${WORKDIR}//linux-2.6.16" + +KERNEL_OUTPUT = "arch/${ARCH}/boot/compressed/${KERNEL_IMAGETYPE}" + +inherit kernel + +COMPATIBLE_HOST = "arm.*-linux" +COMPATIBLE_MACHINE = "cmx270" + +do_configure_prepend() { + install -m 0644 ${S}/arch/arm/configs/cm_x270_defconfig ${S}/.config + install -m 0644 ${WORKDIR}/CL_FlashDrv ${S}/drivers/block/cl_flash + oe_runmake oldconfig +} + +do_deploy() { + install -d ${DEPLOY_DIR}/images + install -m 0644 arch/${ARCH}/boot/${KERNEL_IMAGETYPE} ${DEPLOY_DIR}/images/${KERNEL_IMAGETYPE}-${PV}-${MACHINE}-${DATETIME}.bin +} + +do_deploy[dirs] = "${S}" + +addtask deploy before do_build after do_compile + +KERNEL_RELEASE = "2.6.16" \ No newline at end of file diff --git a/meta/packages/linux/linux-cmx270_2.6.17.bb b/meta/packages/linux/linux-cmx270_2.6.17.bb index d9cdd7e9e2..61ea78f0bd 100644 --- a/meta/packages/linux/linux-cmx270_2.6.17.bb +++ b/meta/packages/linux/linux-cmx270_2.6.17.bb @@ -3,6 +3,8 @@ DESCRIPTION = "Linux kernel CM-X270" LICENSE = "GPL" PR = "r7" +DEFAULT_PREFERENCE = "-1" + SRC_URI = "http://www.kernel.org/pub/linux/kernel/v2.6/linux-2.6.17.tar.bz2 \ http://raph.people.8d.com/kernels/8d-cmx2xx-2.6.17.1-june21.diff;patch=1 \ http://raph.people.8d.com/kernels/hardcode-archID.diff;patch=1 \ -- 2.40.1