008-serial.patch 74 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809
  1. --- /dev/null
  2. +++ b/drivers/serial/it8712.c
  3. @@ -0,0 +1,858 @@
  4. +/*
  5. + * linux/drivers/char/serial_uart00.c
  6. + *
  7. + * Driver for UART00 serial ports
  8. + *
  9. + * Based on drivers/char/serial_amba.c, by ARM Limited &
  10. + * Deep Blue Solutions Ltd.
  11. + * Copyright 2001 Altera Corporation
  12. + *
  13. + * This program is free software; you can redistribute it and/or modify
  14. + * it under the terms of the GNU General Public License as published by
  15. + * the Free Software Foundation; either version 2 of the License, or
  16. + * (at your option) any later version.
  17. + *
  18. + * This program is distributed in the hope that it will be useful,
  19. + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  20. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  21. + * GNU General Public License for more details.
  22. + *
  23. + * You should have received a copy of the GNU General Public License
  24. + * along with this program; if not, write to the Free Software
  25. + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  26. + *
  27. + * $Id: it8712.c,v 1.2 2006/06/06 06:36:04 middle Exp $
  28. + *
  29. + */
  30. +#include <linux/module.h>
  31. +#include <linux/tty.h>
  32. +#include <linux/ioport.h>
  33. +#include <linux/init.h>
  34. +#include <linux/serial.h>
  35. +#include <linux/console.h>
  36. +#include <linux/sysrq.h>
  37. +#include <asm/hardware.h>
  38. +#include <asm/system.h>
  39. +#include <asm/io.h>
  40. +#include <asm/irq.h>
  41. +#include <asm/uaccess.h>
  42. +#include <asm/bitops.h>
  43. +#include <asm/sizes.h>
  44. +
  45. +#if defined(CONFIG_SERIAL_IT8712_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
  46. +#define SUPPORT_SYSRQ
  47. +#endif
  48. +
  49. +#include <linux/serial_core.h>
  50. +#include <asm/arch/sl2312.h>
  51. +#include <asm/arch/int_ctrl.h>
  52. +#include <asm/arch/it8712.h>
  53. +#include "it8712.h"
  54. +
  55. +//#define DEBUG 1
  56. +#define UART_NR 1
  57. +
  58. +#define SERIAL_IT8712_NAME "ttySI"
  59. +#define SERIAL_IT8712_MAJOR 204
  60. +#define SERIAL_IT8712_MINOR 41 /* Temporary - will change in future */
  61. +#define SERIAL_IT8712_NR UART_NR
  62. +#define UART_PORT_SIZE 0x50
  63. +#define LPC_HOST_CONTINUE_MODE 0x00000040
  64. +
  65. +#define IT8712_NO_PORTS UART_NR
  66. +#define IT8712_ISR_PASS_LIMIT 256
  67. +
  68. +#define LPC_BUS_CTRL *(unsigned int*)(IO_ADDRESS(SL2312_LPC_HOST_BASE + 4))
  69. +#define LPC_BUS_STATUS *(unsigned int*)(IO_ADDRESS(SL2312_LPC_HOST_BASE + 4))
  70. +#define LPC_SERIAL_IRQ_CTRL *(unsigned int*)(IO_ADDRESS(SL2312_LPC_HOST_BASE + 8))
  71. +#define LPC_SERIAL_IRQ_STATUS *(unsigned int*)(IO_ADDRESS(SL2312_LPC_HOST_BASE + 0x0c))
  72. +#define LPC_SERIAL_IRQ_TRITYPE *(unsigned int*)(IO_ADDRESS(SL2312_LPC_HOST_BASE + 0x10))
  73. +#define LPC_SERIAL_IRQ_POLARITY *(unsigned int*)(IO_ADDRESS(SL2312_LPC_HOST_BASE + 0x14))
  74. +#define LPC_SERIAL_IRQ_ENABLE *(unsigned int*)(IO_ADDRESS(SL2312_LPC_HOST_BASE + 0x18))
  75. +
  76. +
  77. +
  78. +
  79. +/*
  80. + * Access macros for the SL2312 UARTs
  81. + */
  82. +#define UART_GET_INT_STATUS(p) (inb(((p)->membase+UART_IIR)) & 0x0F) // interrupt identification
  83. +#define UART_PUT_IER(p, c) outb(c,((p)->membase+UART_IER)) // interrupt enable
  84. +#define UART_GET_IER(p) inb(((p)->membase+UART_IER))
  85. +#define UART_PUT_CHAR(p, c) outb(c,((p)->membase+UART_TX)) // transmitter holding
  86. +#define UART_GET_CHAR(p) inb(((p)->membase+UART_RX)) // receive buffer
  87. +#define UART_GET_LSR(p) inb(((p)->membase+UART_LSR)) // line status
  88. +#define UART_GET_MSR(p) inb(((p)->membase+UART_MSR)) // modem status
  89. +#define UART_GET_MCR(p) inb(((p)->membase+UART_MCR)) // modem control
  90. +#define UART_PUT_MCR(p, c) outb(c,((p)->membase+UART_MCR))
  91. +#define UART_GET_LCR(p) inb(((p)->membase+UART_LCR)) // mode control
  92. +#define UART_PUT_LCR(p, c) outb(c,((p)->membase+UART_LCR))
  93. +#define UART_PUT_FCR(p, c) outb(c,((p)->membase+UART_FCR)) // fifo control
  94. +#define UART_GET_DIV_HI(p) inb(((p)->membase+UART_DLM))
  95. +#define UART_PUT_DIV_HI(p, c) outb(c,((p)->membase+UART_DLM))
  96. +#define UART_GET_DIV_LO(p) inb(((p)->membase+UART_DLL))
  97. +#define UART_PUT_DIV_LO(p, c) outb(c,((p)->membase+UART_DLL))
  98. +#define UART_PUT_MDR(p, c) outb(c,UART_MDR((p)->membase))
  99. +#define UART_RX_DATA(s) ((s) & UART_LSR_DR)
  100. +#define UART_TX_READY(s) ((s) & UART_LSR_THRE)
  101. +
  102. +static void it8712_stop_tx(struct uart_port *port, u_int from_tty)
  103. +{
  104. + unsigned int reg;
  105. +
  106. + //printk("it8712 stop tx : \n");
  107. + reg = UART_GET_IER(port);
  108. + reg &= ~(UART_IER_THRI);
  109. + UART_PUT_IER(port, reg);
  110. +}
  111. +
  112. +static void it8712_stop_rx(struct uart_port *port)
  113. +{
  114. + unsigned int reg;
  115. +
  116. + //printk("it8712 stop rx : \n");
  117. + reg = UART_GET_IER(port);
  118. + reg &= ~(UART_IER_RDI);
  119. + UART_PUT_IER(port, reg);
  120. +
  121. +}
  122. +
  123. +static void it8712_enable_ms(struct uart_port *port)
  124. +{
  125. + unsigned int reg;
  126. +
  127. + //printk("it8712 enable ms : \n");
  128. +
  129. + reg = UART_GET_IER(port);
  130. + reg |= (UART_IER_MSI);
  131. + UART_PUT_IER(port, reg);
  132. +
  133. +}
  134. +
  135. +static void it8712_rx_chars(struct uart_port *port, struct pt_regs *regs)
  136. +{
  137. + struct tty_struct *tty = port->info->tty;
  138. + unsigned int status, mask, ch, flg, ignored = 0;
  139. +
  140. + // printk("it8712_rx_chars : \n");
  141. + status = UART_GET_LSR(port);
  142. + while (UART_RX_DATA(status)) {
  143. +
  144. + /*
  145. + * We need to read rds before reading the
  146. + * character from the fifo
  147. + */
  148. + ch = UART_GET_CHAR(port);
  149. + port->icount.rx++;
  150. +
  151. + if (tty->flip.count >= TTY_FLIPBUF_SIZE)
  152. + goto ignore_char;
  153. +
  154. + flg = TTY_NORMAL;
  155. +
  156. + /*
  157. + * Note that the error handling code is
  158. + * out of the main execution path
  159. + */
  160. +
  161. + if (status & (UART_LSR_OE|UART_LSR_PE|UART_LSR_FE|UART_LSR_BI|UART_LSR_DE))
  162. + goto handle_error;
  163. + if (uart_handle_sysrq_char(port, ch, regs))
  164. + goto ignore_char;
  165. +
  166. + error_return:
  167. + *tty->flip.flag_buf_ptr++ = flg;
  168. + *tty->flip.char_buf_ptr++ = ch;
  169. + tty->flip.count++;
  170. + ignore_char:
  171. + status = UART_GET_LSR(port);
  172. + } // end of while
  173. +out:
  174. + tty_flip_buffer_push(tty);
  175. + return;
  176. +
  177. +handle_error:
  178. + if (status & UART_LSR_BI) {
  179. + status &= ~(UART_LSR_FE);
  180. + port->icount.brk++;
  181. +
  182. +#ifdef SUPPORT_SYSRQ
  183. + if (uart_handle_break(port))
  184. + goto ignore_char;
  185. +#endif
  186. + } else if (status & UART_LSR_PE)
  187. + port->icount.parity++;
  188. + else if (status & UART_LSR_FE)
  189. + port->icount.frame++;
  190. +
  191. + if (status & UART_LSR_OE)
  192. + port->icount.overrun++;
  193. +
  194. + if (status & port->ignore_status_mask) {
  195. + if (++ignored > 100)
  196. + goto out;
  197. + goto ignore_char;
  198. + }
  199. +
  200. + mask = status & port->read_status_mask;
  201. +
  202. + if (mask & UART_LSR_BI)
  203. + flg = TTY_BREAK;
  204. + else if (mask & UART_LSR_PE)
  205. + flg = TTY_PARITY;
  206. + else if (mask & UART_LSR_FE)
  207. + flg = TTY_FRAME;
  208. +
  209. + if (status & UART_LSR_OE) {
  210. + /*
  211. + * CHECK: does overrun affect the current character?
  212. + * ASSUMPTION: it does not.
  213. + */
  214. + *tty->flip.flag_buf_ptr++ = flg;
  215. + *tty->flip.char_buf_ptr++ = ch;
  216. + tty->flip.count++;
  217. + if (tty->flip.count >= TTY_FLIPBUF_SIZE)
  218. + goto ignore_char;
  219. + ch = 0;
  220. + flg = TTY_OVERRUN;
  221. + }
  222. +#ifdef SUPPORT_SYSRQ
  223. + port->sysrq = 0;
  224. +#endif
  225. + goto error_return;
  226. +}
  227. +
  228. +static void it8712_tx_chars(struct uart_port *port)
  229. +{
  230. + struct circ_buf *xmit = &port->info->xmit;
  231. + int count;
  232. +
  233. + if (port->x_char) {
  234. + while(!(UART_GET_LSR(port)&UART_LSR_THRE));
  235. + UART_PUT_CHAR(port, port->x_char);
  236. + port->icount.tx++;
  237. + port->x_char = 0;
  238. +
  239. + return;
  240. + }
  241. + if (uart_circ_empty(xmit) || uart_tx_stopped(port)) {
  242. + it8712_stop_tx(port, 0);
  243. + return;
  244. + }
  245. +
  246. + count = port->fifosize >> 1;
  247. + do {
  248. + while(!(UART_GET_LSR(port)&UART_LSR_THRE));
  249. + UART_PUT_CHAR(port, xmit->buf[xmit->tail]);
  250. + xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
  251. + port->icount.tx++;
  252. + if (uart_circ_empty(xmit))
  253. + break;
  254. + } while (--count > 0);
  255. +
  256. + if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
  257. + uart_write_wakeup(port);
  258. +
  259. + if (uart_circ_empty(xmit))
  260. + it8712_stop_tx(port, 0);
  261. +}
  262. +
  263. +static void it8712_start_tx(struct uart_port *port, unsigned int tty_start)
  264. +{
  265. + unsigned int reg;
  266. +
  267. + //printk("it8712 start tx : \n");
  268. + reg = UART_GET_IER(port);
  269. + reg |= (UART_IER_THRI);
  270. + UART_PUT_IER(port, reg);
  271. + it8712_tx_chars(port);
  272. +}
  273. +
  274. +static void it8712_modem_status(struct uart_port *port)
  275. +{
  276. + unsigned int status;
  277. +
  278. +// printk("it8712 modem status : \n");
  279. +
  280. + status = UART_GET_MSR(port);
  281. +
  282. + if (!(status & (UART_MSR_DCTS | UART_MSR_DDSR |
  283. + UART_MSR_TERI | UART_MSR_DDCD)))
  284. + return;
  285. +
  286. + if (status & UART_MSR_DDCD)
  287. + uart_handle_dcd_change(port, status & UART_MSR_DCD);
  288. +
  289. + if (status & UART_MSR_DDSR)
  290. + port->icount.dsr++;
  291. +
  292. + if (status & UART_MSR_DCTS)
  293. + uart_handle_cts_change(port, status & UART_MSR_CTS);
  294. +
  295. + wake_up_interruptible(&port->info->delta_msr_wait);
  296. +
  297. +}
  298. +
  299. +static irqreturn_t it8712_int(int irq, void *dev_id, struct pt_regs *regs)
  300. +{
  301. + struct uart_port *port = dev_id;
  302. + unsigned int status, pass_counter = 0, data;
  303. +
  304. +
  305. + data = LPC_SERIAL_IRQ_STATUS;
  306. + if((data&0x10)==0x10)
  307. + {
  308. + status = UART_GET_INT_STATUS(port);
  309. + do {
  310. +// printk("it8712_int: status %x \n", status);
  311. + switch(status)
  312. + {
  313. + case UART_IIR_RDI:
  314. + case UART_IIR_RLSI:
  315. + case UART_IIR_RCTO:
  316. + it8712_rx_chars(port, regs);
  317. + break;
  318. + case UART_IIR_THRI:
  319. + it8712_tx_chars(port);
  320. + break;
  321. + case UART_IIR_MSI:
  322. + it8712_modem_status(port);
  323. + break;
  324. + default:
  325. + break;
  326. + }
  327. + if (pass_counter++ > IT8712_ISR_PASS_LIMIT)
  328. + break;
  329. +
  330. + status = UART_GET_INT_STATUS(port);
  331. + } while (status);
  332. + }
  333. +
  334. + status = 0;
  335. + status |= (IRQ_LPC_MASK);
  336. + *((volatile unsigned int *)IRQ_CLEAR(IO_ADDRESS(SL2312_INTERRUPT_BASE))) = status;
  337. +
  338. + //cnt=0;
  339. + //do{
  340. + // data = LPC_SERIAL_IRQ_STATUS;
  341. + LPC_SERIAL_IRQ_STATUS = data;
  342. + // cnt++;
  343. + //}while(data);
  344. + //if(cnt>2)
  345. + // printf("it8712_uart_Isr clear LPC_SERIAL_IRQ_STATUS %x \n", cnt);
  346. + return IRQ_HANDLED;
  347. +}
  348. +
  349. +static u_int it8712_tx_empty(struct uart_port *port)
  350. +{
  351. +// printk("it8712 tx empty : \n");
  352. +
  353. + return ((UART_GET_LSR(port) & UART_LSR_THRE)? TIOCSER_TEMT : 0);
  354. +}
  355. +
  356. +static u_int it8712_get_mctrl(struct uart_port *port)
  357. +{
  358. + unsigned int result = 0;
  359. + unsigned int status;
  360. +
  361. +// printk("it8712 get mctrl : \n");
  362. +
  363. + status = UART_GET_MSR(port);
  364. + if (status & UART_MSR_DCD)
  365. + result |= TIOCM_CAR;
  366. + if (status & UART_MSR_DSR)
  367. + result |= TIOCM_DSR;
  368. + if (status & UART_MSR_CTS)
  369. + result |= TIOCM_CTS;
  370. + if (status & UART_MSR_RI)
  371. + result |= TIOCM_RI;
  372. +
  373. + return result;
  374. +}
  375. +
  376. +static void it8712_set_mctrl_null(struct uart_port *port, u_int mctrl)
  377. +{
  378. +}
  379. +
  380. +static void it8712_break_ctl(struct uart_port *port, int break_state)
  381. +{
  382. + unsigned int lcr;
  383. +
  384. +// printk("it8712 break ctl : \n");
  385. +
  386. + lcr = UART_GET_LCR(port);
  387. + if (break_state == -1)
  388. + lcr |= UART_LCR_SBC;
  389. + else
  390. + lcr &= ~UART_LCR_SBC;
  391. + UART_PUT_LCR(port, lcr);
  392. +}
  393. +
  394. +static inline u_int uart_calculate_quot(struct uart_port *port, u_int baud)
  395. +{
  396. + u_int quot;
  397. +
  398. + /* Special case: B0 rate */
  399. + if (!baud)
  400. + baud = 9600;
  401. +
  402. + quot = (port->uartclk/(16 * baud)) ;
  403. +
  404. + return quot;
  405. +}
  406. +static void it8712_set_termios(struct uart_port *port, struct termios *termios,
  407. + struct termios *old)
  408. +{
  409. + unsigned int uart_mc, old_ier, baud, quot;
  410. + unsigned long flags;
  411. +
  412. + termios->c_cflag |= CREAD;
  413. + termios->c_cflag |= CLOCAL;
  414. +#ifdef DEBUG
  415. + printk("it8712_set_cflag(0x%x) called\n", cflag);
  416. +#endif
  417. + baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk/16);
  418. + quot = uart_get_divisor(port, baud);
  419. +
  420. + /* byte size and parity */
  421. + switch (termios->c_cflag & CSIZE) {
  422. + case CS5:
  423. + uart_mc = UART_LCR_WLEN5;
  424. + break;
  425. + case CS6:
  426. + uart_mc = UART_LCR_WLEN6;
  427. + break;
  428. + case CS7:
  429. + uart_mc = UART_LCR_WLEN7;
  430. + break;
  431. + default: // CS8
  432. + uart_mc = UART_LCR_WLEN8;
  433. + break;
  434. + }
  435. +
  436. + if (termios->c_cflag & CSTOPB)
  437. + uart_mc|= UART_LCR_STOP;
  438. + if (termios->c_cflag & PARENB) {
  439. + uart_mc |= UART_LCR_EVEN;
  440. + if (!(termios->c_cflag & PARODD))
  441. + uart_mc |= UART_LCR_ODD;
  442. + }
  443. +
  444. + spin_lock_irqsave(&port->lock, flags);
  445. + /*
  446. + * Update the per-port timeout
  447. + */
  448. + uart_update_timeout(port, termios->c_cflag, baud);
  449. + port->read_status_mask = UART_LSR_OE;
  450. + if (termios->c_iflag & INPCK)
  451. + port->read_status_mask |= UART_LSR_FE | UART_LSR_PE;
  452. + if (termios->c_iflag & (BRKINT | PARMRK))
  453. + port->read_status_mask |= UART_LSR_BI;
  454. +
  455. + /*
  456. + * Characters to ignore
  457. + */
  458. + port->ignore_status_mask = 0;
  459. + if (termios->c_iflag & IGNPAR)
  460. + port->ignore_status_mask |= UART_LSR_FE | UART_LSR_PE;
  461. + if (termios->c_iflag & IGNBRK) {
  462. + port->ignore_status_mask |= UART_LSR_BI;
  463. + /*
  464. + * If we're ignoring parity and break indicators,
  465. + * ignore overruns to (for real raw support).
  466. + */
  467. + if (termios->c_iflag & IGNPAR)
  468. + port->ignore_status_mask |= UART_LSR_OE;
  469. + }
  470. +
  471. + old_ier = UART_GET_IER(port);
  472. +
  473. + if(UART_ENABLE_MS(port, termios->c_cflag))
  474. + old_ier |= UART_IER_MSI;
  475. +
  476. + /* Set baud rate */
  477. + quot = quot / 13;
  478. + UART_PUT_LCR(port, UART_LCR_DLAB);
  479. + UART_PUT_DIV_LO(port, (quot & 0xff));
  480. + UART_PUT_DIV_HI(port, ((quot & 0xf00) >> 8));
  481. +
  482. + UART_PUT_LCR(port, uart_mc);
  483. +// UART_PUT_LCR(port, 0x07); // ???? it is wired
  484. + UART_PUT_MCR(port, 0x08);
  485. + UART_PUT_FCR(port, 0x01);
  486. + UART_PUT_IER(port, 0x07);
  487. +
  488. + spin_unlock_irqrestore(&port->lock, flags);
  489. +}
  490. +
  491. +static int it8712_startup(struct uart_port *port)
  492. +{
  493. + int retval, i;
  494. + unsigned int regs;
  495. +
  496. + //printk("it8712 startup : \n");
  497. +
  498. + /*
  499. + * Use iobase to store a pointer to info. We need this to start a
  500. + * transmission as the tranmittr interrupt is only generated on
  501. + * the transition to the idle state
  502. + */
  503. +
  504. + // regs = 0;
  505. + // regs |= (IRQ_LPC_MASK);
  506. + // *((volatile unsigned int *)IRQ_CLEAR(IO_ADDRESS(SL2312_INTERRUPT_BASE))) = regs;
  507. +
  508. + /*
  509. + * Allocate the IRQ
  510. + */
  511. + retval = request_irq(port->irq, it8712_int, SA_INTERRUPT, "it8712", port);
  512. + if (retval)
  513. + return retval;
  514. +
  515. + //printk("Init LPC int...........\n");
  516. + /* setup interrupt controller */
  517. + regs = *((volatile unsigned int *)IRQ_TMODE(IO_ADDRESS(SL2312_INTERRUPT_BASE)));
  518. + regs &= ~(IRQ_LPC_MASK);
  519. + *((volatile unsigned int *)IRQ_TMODE(IO_ADDRESS(SL2312_INTERRUPT_BASE))) = regs;
  520. + regs = *((volatile unsigned int *)IRQ_TLEVEL(IO_ADDRESS(SL2312_INTERRUPT_BASE)));
  521. + regs &= ~(IRQ_LPC_MASK);
  522. + *((volatile unsigned int *)IRQ_TLEVEL(IO_ADDRESS(SL2312_INTERRUPT_BASE))) = regs;
  523. + *((volatile unsigned int *)IRQ_MASK(IO_ADDRESS(SL2312_INTERRUPT_BASE))) |= (unsigned int)(IRQ_LPC_MASK);
  524. +
  525. + LPC_SERIAL_IRQ_POLARITY = 0x10; //0x10; //0x02;
  526. + LPC_SERIAL_IRQ_TRITYPE = 0x10; //0x10;//
  527. + LPC_SERIAL_IRQ_ENABLE = 0x10;
  528. +
  529. + LPC_BUS_CTRL = 0xc0;
  530. + LPC_SERIAL_IRQ_CTRL = 0xc0;
  531. + for(i=0;i<1000;i++) ;
  532. + LPC_SERIAL_IRQ_CTRL = 0x80;
  533. + /*
  534. + * Finally, enable interrupts. Use the TII interrupt to minimise
  535. + * the number of interrupts generated. If higher performance is
  536. + * needed, consider using the TI interrupt with a suitable FIFO
  537. + * threshold
  538. + */
  539. + //UART_PUT_IER(port, (UART_IER_RDI|UART_IER_THRI));
  540. + UART_PUT_IER(port, (UART_IER_RDI|UART_IER_THRI|UART_IER_RLSI));//middle
  541. +
  542. + return 0;
  543. +}
  544. +
  545. +static void it8712_shutdown(struct uart_port *port)
  546. +{
  547. + //printk("it8712 shutdown : \n");
  548. +
  549. + /*
  550. + * disable all interrupts, disable the port
  551. + */
  552. + UART_PUT_IER(port, 0x0);
  553. +
  554. + /* disable break condition and fifos */
  555. +// UART_PUT_MCR(port, (UART_GET_MCR(port)&UART_MCR_MASK));
  556. +
  557. + /*
  558. + * Free the interrupt
  559. + */
  560. + free_irq(port->irq, port);
  561. +}
  562. +
  563. +static const char *it8712_type(struct uart_port *port)
  564. +{
  565. + return port->type == PORT_IT8712 ? "IT8712" : NULL;
  566. +}
  567. +
  568. +/*
  569. + * Release the memory region(s) being used by 'port'
  570. + */
  571. +static void it8712_release_port(struct uart_port *port)
  572. +{
  573. +// printk("it8712 release port : \n");
  574. +
  575. + release_mem_region(port->mapbase, UART_PORT_SIZE);
  576. +}
  577. +
  578. +/*
  579. + * Request the memory region(s) being used by 'port'
  580. + */
  581. +static int it8712_request_port(struct uart_port *port)
  582. +{
  583. + return request_mem_region(port->mapbase, UART_PORT_SIZE,
  584. + "serial_it8712") != NULL ? 0 : -EBUSY;
  585. +}
  586. +
  587. +/*
  588. + * Configure/autoconfigure the port.
  589. + */
  590. +static void it8712_config_port(struct uart_port *port, int flags)
  591. +{
  592. +
  593. + if (flags & UART_CONFIG_TYPE) {
  594. + if (it8712_request_port(port) == 0)
  595. + port->type = PORT_IT8712;
  596. + }
  597. +}
  598. +
  599. +/*
  600. + * verify the new serial_struct (for TIOCSSERIAL).
  601. + */
  602. +static int it8712_verify_port(struct uart_port *port, struct serial_struct *ser)
  603. +{
  604. + int ret = 0;
  605. +
  606. + if (ser->type != PORT_UNKNOWN && ser->type != PORT_UART00)
  607. + ret = -EINVAL;
  608. + if (ser->irq < 0 || ser->irq >= NR_IRQS)
  609. + ret = -EINVAL;
  610. + if (ser->baud_base < 9600)
  611. + ret = -EINVAL;
  612. + return ret;
  613. +}
  614. +
  615. +static struct uart_ops it8712_pops = {
  616. + .tx_empty = it8712_tx_empty,
  617. + .set_mctrl = it8712_set_mctrl_null,
  618. + .get_mctrl = it8712_get_mctrl,
  619. + .stop_tx = it8712_stop_tx,
  620. + .start_tx = it8712_start_tx,
  621. + .stop_rx = it8712_stop_rx,
  622. + .enable_ms = it8712_enable_ms,
  623. + .break_ctl = it8712_break_ctl,
  624. + .startup = it8712_startup,
  625. + .shutdown = it8712_shutdown,
  626. + .set_termios = it8712_set_termios,
  627. + .type = it8712_type,
  628. + .release_port = it8712_release_port,
  629. + .request_port = it8712_request_port,
  630. + .config_port = it8712_config_port,
  631. + .verify_port = it8712_verify_port,
  632. +};
  633. +
  634. +#ifdef CONFIG_ARCH_SL2312
  635. +
  636. +static struct uart_port it8712_ports[UART_NR] = {
  637. + {
  638. + membase: (void *)0,
  639. + mapbase: 0,
  640. + iotype: SERIAL_IO_MEM,
  641. + irq: 0,
  642. + uartclk: UART_CLK/2,
  643. + fifosize: 16,
  644. + ops: &it8712_pops,
  645. + flags: ASYNC_BOOT_AUTOCONF,
  646. + }
  647. +};
  648. +
  649. +#endif
  650. +
  651. +#ifdef CONFIG_SERIAL_IT8712_CONSOLE
  652. +#ifdef used_and_not_const_char_pointer
  653. +static int it8712_console_read(struct uart_port *port, char *s, u_int count)
  654. +{
  655. + unsigned int status;
  656. + int c;
  657. +#ifdef DEBUG
  658. + printk("it8712_console_read() called\n");
  659. +#endif
  660. +
  661. + c = 0;
  662. + while (c < count) {
  663. + status = UART_GET_LSR(port);
  664. + if (UART_RX_DATA(status)) {
  665. + *s++ = UART_GET_CHAR(port);
  666. + c++;
  667. + } else {
  668. + // nothing more to get, return
  669. + return c;
  670. + }
  671. + }
  672. + // return the count
  673. + return c;
  674. +}
  675. +#endif
  676. +static void it8712_console_write(struct console *co, const char *s, unsigned count)
  677. +{
  678. +#ifdef CONFIG_ARCH_SL2312
  679. + struct uart_port *port = it8712_ports + co->index;
  680. + unsigned int status, old_ies;
  681. + int i;
  682. +
  683. + /*
  684. + * First save the CR then disable the interrupts
  685. + */
  686. + old_ies = UART_GET_IER(port);
  687. + //if(old_ies!=7)
  688. + //{
  689. + //
  690. + // printk("old_ies = %x\n",old_ies);
  691. + // old_ies = 7;
  692. + //}
  693. + UART_PUT_IER(port,0x0);
  694. +
  695. + /*
  696. + * Now, do each character
  697. + */
  698. + for (i = 0; i < count; i++) {
  699. + do {
  700. + status = UART_GET_LSR(port);
  701. + } while (!UART_TX_READY(status));
  702. + UART_PUT_CHAR(port, s[i]);
  703. + if (s[i] == '\n') {
  704. + do {
  705. + status = UART_GET_LSR(port);
  706. + } while (!UART_TX_READY(status));
  707. + UART_PUT_CHAR(port, '\r');
  708. + }
  709. + }
  710. +
  711. + /*
  712. + * Finally, wait for transmitter to become empty
  713. + * and restore the IES
  714. + */
  715. + do {
  716. + status = UART_GET_LSR(port);
  717. + } while (!(status&UART_LSR_THRE));
  718. + UART_PUT_IER(port, old_ies);
  719. +#endif
  720. +}
  721. +
  722. +static void /*__init*/ it8712_console_get_options(struct uart_port *port, int *baud, int *parity, int *bits)
  723. +{
  724. + //printk("it8712 console get options : \n");
  725. +
  726. + u_int uart_mc, quot;
  727. + uart_mc= UART_GET_MCR(port);
  728. +
  729. + *parity = 'n';
  730. + if (uart_mc & UART_LCR_PARITY) {
  731. + if (uart_mc & UART_LCR_EVEN)
  732. + *parity = 'e';
  733. + else
  734. + *parity = 'o';
  735. + }
  736. +
  737. + switch (uart_mc & UART_LCR_MSK){
  738. +
  739. + case UART_LCR_WLEN5:
  740. + *bits = 5;
  741. + break;
  742. + case UART_LCR_WLEN6:
  743. + *bits = 6;
  744. + break;
  745. + case UART_LCR_WLEN7:
  746. + *bits = 7;
  747. + break;
  748. + case UART_LCR_WLEN8:
  749. + *bits = 8;
  750. + break;
  751. + }
  752. + UART_PUT_MCR(port,UART_LCR_DLAB);
  753. + quot = UART_GET_DIV_LO(port) | (UART_GET_DIV_HI(port) << 8);
  754. + UART_PUT_MCR(port,uart_mc);
  755. + *baud = (port->uartclk / (16 *quot));
  756. +}
  757. +
  758. +static int __init it8712_console_setup(struct console *co, char *options)
  759. +{
  760. + struct uart_port *port;
  761. + int baud = 38400;
  762. + int bits = 8;
  763. + int parity = 'n';
  764. + int flow= 'n';
  765. + int base;//, irq;
  766. + int i ;
  767. +
  768. + printk("it8712 console setup : \n");
  769. +
  770. + LPCSetConfig(0, 0x02, 0x01);
  771. + LPCSetConfig(LDN_SERIAL1, 0x30, 0x1);
  772. + LPCSetConfig(LDN_SERIAL1, 0x23, 0x0);
  773. + base = IT8712_IO_BASE;
  774. + base += ((LPCGetConfig(LDN_SERIAL1, 0x60) << 8) + LPCGetConfig(LDN_SERIAL1, 0x61));
  775. + it8712_ports[0].mapbase = base;
  776. + it8712_ports[0].membase = (void *)IO_ADDRESS(base);
  777. + it8712_ports[0].irq = IRQ_LPC_OFFSET;
  778. + // irq = LPCGetConfig(LDN_SERIAL1, 0x70);
  779. + //it8712_ports[0].irq += irq;
  780. +
  781. + //printk("it8712 irq is %x \n", it8712_ports[0].irq);
  782. +
  783. + // setup LPC Host 'quiet mode'
  784. + //*((volatile unsigned int *)IO_ADDRESS((SL2312_LPC_HOST_BASE+0x04))) |= LPC_HOST_CONTINUE_MODE ;
  785. + //for(i=0;i<1000;i++) ; // delay
  786. + //*((volatile unsigned int *)IO_ADDRESS((SL2312_LPC_HOST_BASE+0x04))) &= ~(LPC_HOST_CONTINUE_MODE) ;
  787. + LPC_BUS_CTRL = 0xc0;
  788. + LPC_SERIAL_IRQ_CTRL = 0xc0;
  789. + for(i=0;i<1000;i++) ;
  790. + LPC_SERIAL_IRQ_CTRL = 0x80;
  791. +
  792. +#ifdef CONFIG_ARCH_SL2312
  793. + /*
  794. + * Check whether an invalid uart number has been specified, and
  795. + * if so, search for the first available port that does have
  796. + * console support.
  797. + */
  798. + port = uart_get_console(it8712_ports,IT8712_NO_PORTS,co);
  799. +#else
  800. + return -ENODEV;
  801. +#endif
  802. +
  803. + if (options)
  804. + uart_parse_options(options, &baud, &parity, &bits, &flow);
  805. + else
  806. + it8712_console_get_options(port, &baud, &parity, &bits);
  807. +
  808. + return uart_set_options(port, co, baud, parity, bits, flow);
  809. +}
  810. +
  811. +extern struct uart_driver it8712_reg;
  812. +static struct console it8712_console = {
  813. + .name = SERIAL_IT8712_NAME,
  814. + .write = it8712_console_write,
  815. + .device = uart_console_device,
  816. + .setup = it8712_console_setup,
  817. + .flags = CON_PRINTBUFFER,
  818. + .index = 0,
  819. + .data = &it8712_reg,
  820. +};
  821. +
  822. +static int __init it8712_console_init(void)
  823. +{
  824. + register_console(&it8712_console);
  825. + return 0;
  826. +}
  827. +
  828. +console_initcall(it8712_console_init);
  829. +
  830. +#define IT8712_CONSOLE &it8712_console
  831. +#else
  832. +#define IT8712_CONSOLE NULL
  833. +#endif
  834. +
  835. +static struct uart_driver it8712_reg = {
  836. + .owner = NULL,
  837. + .driver_name = SERIAL_IT8712_NAME,
  838. + .dev_name = SERIAL_IT8712_NAME,
  839. + .major = SERIAL_IT8712_MAJOR,
  840. + .minor = SERIAL_IT8712_MINOR,
  841. + .nr = UART_NR,
  842. + .cons = IT8712_CONSOLE,
  843. +};
  844. +
  845. +static int __init it8712_init(void)
  846. +{
  847. + int result;
  848. + //printk("serial_it8712: it871212_init \n");
  849. +
  850. +
  851. + result = uart_register_driver(&it8712_reg);
  852. + if(result)
  853. + return result;
  854. + result = uart_add_one_port(&it8712_reg, &it8712_ports[0]);
  855. +
  856. + return result;
  857. +
  858. +}
  859. +
  860. +
  861. +__initcall(it8712_init);
  862. --- /dev/null
  863. +++ b/drivers/serial/it8712.h
  864. @@ -0,0 +1,135 @@
  865. +#define UART_RX 0 /* In: Receive buffer (DLAB=0) */
  866. +#define UART_TX 0 /* Out: Transmit buffer (DLAB=0) */
  867. +#define UART_DLL 0 /* Out: Divisor Latch Low (DLAB=1) */
  868. +#define UART_TRG 0 /* (LCR=BF) FCTR bit 7 selects Rx or Tx
  869. + * In: Fifo count
  870. + * Out: Fifo custom trigger levels
  871. + * XR16C85x only */
  872. +
  873. +#define UART_DLM 1 /* Out: Divisor Latch High (DLAB=1) */
  874. +#define UART_IER 1 /* Out: Interrupt Enable Register */
  875. +#define UART_FCTR 1 /* (LCR=BF) Feature Control Register
  876. + * XR16C85x only */
  877. +
  878. +#define UART_IIR 2 /* In: Interrupt ID Register */
  879. +#define UART_FCR 2 /* Out: FIFO Control Register */
  880. +#define UART_EFR 2 /* I/O: Extended Features Register */
  881. + /* (DLAB=1, 16C660 only) */
  882. +
  883. +#define UART_LCR 3 /* Out: Line Control Register */
  884. +#define UART_MCR 4 /* Out: Modem Control Register */
  885. +#define UART_LSR 5 /* In: Line Status Register */
  886. +#define UART_MSR 6 /* In: Modem Status Register */
  887. +#define UART_SCR 7 /* I/O: Scratch Register */
  888. +#define UART_EMSR 7 /* (LCR=BF) Extended Mode Select Register
  889. + * FCTR bit 6 selects SCR or EMSR
  890. + * XR16c85x only */
  891. +
  892. +/*
  893. + * These are the definitions for the FIFO Control Register
  894. + * (16650 only)
  895. + */
  896. +#define UART_FCR_ENABLE_FIFO 0x01 /* Enable the FIFO */
  897. +#define UART_FCR_CLEAR_RCVR 0x02 /* Clear the RCVR FIFO */
  898. +#define UART_FCR_CLEAR_XMIT 0x04 /* Clear the XMIT FIFO */
  899. +#define UART_FCR_DMA_SELECT 0x08 /* For DMA applications */
  900. +#define UART_FCR_TRIGGER_MASK 0xC0 /* Mask for the FIFO trigger range */
  901. +#define UART_FCR_TRIGGER_1 0x00 /* Mask for trigger set at 1 */
  902. +#define UART_FCR_TRIGGER_4 0x40 /* Mask for trigger set at 4 */
  903. +#define UART_FCR_TRIGGER_8 0x80 /* Mask for trigger set at 8 */
  904. +#define UART_FCR_TRIGGER_14 0xC0 /* Mask for trigger set at 14 */
  905. +/* 16650 redefinitions */
  906. +#define UART_FCR6_R_TRIGGER_8 0x00 /* Mask for receive trigger set at 1 */
  907. +#define UART_FCR6_R_TRIGGER_16 0x40 /* Mask for receive trigger set at 4 */
  908. +#define UART_FCR6_R_TRIGGER_24 0x80 /* Mask for receive trigger set at 8 */
  909. +#define UART_FCR6_R_TRIGGER_28 0xC0 /* Mask for receive trigger set at 14 */
  910. +#define UART_FCR6_T_TRIGGER_16 0x00 /* Mask for transmit trigger set at 16 */
  911. +#define UART_FCR6_T_TRIGGER_8 0x10 /* Mask for transmit trigger set at 8 */
  912. +#define UART_FCR6_T_TRIGGER_24 0x20 /* Mask for transmit trigger set at 24 */
  913. +#define UART_FCR6_T_TRIGGER_30 0x30 /* Mask for transmit trigger set at 30 */
  914. +/* TI 16750 definitions */
  915. +#define UART_FCR7_64BYTE 0x20 /* Go into 64 byte mode */
  916. +
  917. +/*
  918. + * These are the definitions for the Line Control Register
  919. + *
  920. + * Note: if the word length is 5 bits (UART_LCR_WLEN5), then setting
  921. + * UART_LCR_STOP will select 1.5 stop bits, not 2 stop bits.
  922. + */
  923. +#define UART_LCR_DLAB 0x80 /* Divisor latch access bit */
  924. +#define UART_LCR_SBC 0x40 /* Set break control */
  925. +#define UART_LCR_SPAR 0x20 /* Stick parity (?) */
  926. +#define UART_LCR_EPAR 0x10 /* Even parity select */
  927. +#define UART_LCR_PARITY 0x08 /* Parity Enable */
  928. +#define UART_LCR_STOP 0x04 /* Stop bits: 0=1 stop bit, 1= 2 stop bits */
  929. +#define UART_LCR_WLEN5 0x00 /* Wordlength: 5 bits */
  930. +#define UART_LCR_WLEN6 0x01 /* Wordlength: 6 bits */
  931. +#define UART_LCR_WLEN7 0x02 /* Wordlength: 7 bits */
  932. +#define UART_LCR_WLEN8 0x03 /* Wordlength: 8 bits */
  933. +#define UART_LCR_EVEN 0x18 /* Even parity */
  934. +#define UART_LCR_ODD 0x08 /* Odd parity */
  935. +#define UART_LCR_MSK 0x03
  936. +/*
  937. + * These are the definitions for the Line Status Register
  938. + */
  939. +#define UART_LSR_DE 0x80 /* FIFO Data Error */
  940. +#define UART_LSR_TEMT 0x40 /* Transmitter empty */
  941. +#define UART_LSR_THRE 0x20 /* Transmit-hold-register empty */
  942. +#define UART_LSR_BI 0x10 /* Break interrupt indicator */
  943. +#define UART_LSR_FE 0x08 /* Frame error indicator */
  944. +#define UART_LSR_PE 0x04 /* Parity error indicator */
  945. +#define UART_LSR_OE 0x02 /* Overrun error indicator */
  946. +#define UART_LSR_DR 0x01 /* Receiver data ready */
  947. +
  948. +/*
  949. + * These are the definitions for the Interrupt Identification Register
  950. + */
  951. +#define UART_IIR_NO_INT 0x01 /* No interrupts pending */
  952. +#define UART_IIR_ID 0x06 /* Mask for the interrupt ID */
  953. +
  954. +#define UART_IIR_MSI 0x00 /* Modem status interrupt */
  955. +#define UART_IIR_THRI 0x02 /* Transmitter holding register empty */
  956. +#define UART_IIR_RDI 0x04 /* Receiver data interrupt */
  957. +#define UART_IIR_RLSI 0x06 /* Receiver line status interrupt */
  958. +#define UART_IIR_RCTO 0x0c /* Receiver character timeout interrupt */
  959. +/*
  960. + * These are the definitions for the Interrupt Enable Register
  961. + */
  962. +#define UART_IER_MSI 0x08 /* Enable Modem status interrupt */
  963. +#define UART_IER_RLSI 0x04 /* Enable receiver line status interrupt */
  964. +#define UART_IER_THRI 0x02 /* Enable Transmitter holding register int. */
  965. +#define UART_IER_RDI 0x01 /* Enable receiver data interrupt */
  966. +/*
  967. + * Sleep mode for ST16650 and TI16750.
  968. + * Note that for 16650, EFR-bit 4 must be selected as well.
  969. + */
  970. +#define UART_IERX_SLEEP 0x10 /* Enable sleep mode */
  971. +
  972. +/*
  973. + * These are the definitions for the Modem Control Register
  974. + */
  975. +#define UART_MCR_LOOP 0x10 /* Enable loopback test mode */
  976. +#define UART_MCR_OUT2 0x08 /* Out2 complement */
  977. +#define UART_MCR_OUT1 0x04 /* Out1 complement */
  978. +#define UART_MCR_RTS 0x02 /* RTS complement */
  979. +#define UART_MCR_DTR 0x01 /* DTR complement */
  980. +
  981. +/*
  982. + * These are the definitions for the Modem Status Register
  983. + */
  984. +#define UART_MSR_DCD 0x80 /* Data Carrier Detect */
  985. +#define UART_MSR_RI 0x40 /* Ring Indicator */
  986. +#define UART_MSR_DSR 0x20 /* Data Set Ready */
  987. +#define UART_MSR_CTS 0x10 /* Clear to Send */
  988. +#define UART_MSR_DDCD 0x08 /* Delta DCD */
  989. +#define UART_MSR_TERI 0x04 /* Trailing edge ring indicator */
  990. +#define UART_MSR_DDSR 0x02 /* Delta DSR */
  991. +#define UART_MSR_DCTS 0x01 /* Delta CTS */
  992. +#define UART_MSR_ANY_DELTA 0x0F /* Any of the delta bits! */
  993. +
  994. +#define UART_PARITY_NONE 0x00
  995. +#define UART_PARITY_ODD 0x01
  996. +#define UART_PARITY_EVEN 0x02
  997. +
  998. +
  999. +
  1000. --- /dev/null
  1001. +++ b/drivers/serial/serial_it8712.c
  1002. @@ -0,0 +1,876 @@
  1003. +/*
  1004. + * linux/drivers/char/serial_uart00.c
  1005. + *
  1006. + * Driver for UART00 serial ports
  1007. + *
  1008. + * Based on drivers/char/serial_amba.c, by ARM Limited &
  1009. + * Deep Blue Solutions Ltd.
  1010. + * Copyright 2001 Altera Corporation
  1011. + *
  1012. + * This program is free software; you can redistribute it and/or modify
  1013. + * it under the terms of the GNU General Public License as published by
  1014. + * the Free Software Foundation; either version 2 of the License, or
  1015. + * (at your option) any later version.
  1016. + *
  1017. + * This program is distributed in the hope that it will be useful,
  1018. + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  1019. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  1020. + * GNU General Public License for more details.
  1021. + *
  1022. + * You should have received a copy of the GNU General Public License
  1023. + * along with this program; if not, write to the Free Software
  1024. + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  1025. + *
  1026. + * $Id: serial_it8712.c,v 1.1.1.1 2006/04/03 08:41:00 amos_lee Exp $
  1027. + *
  1028. + */
  1029. +#include <linux/module.h>
  1030. +
  1031. +#include <linux/errno.h>
  1032. +#include <linux/signal.h>
  1033. +#include <linux/sched.h>
  1034. +#include <linux/interrupt.h>
  1035. +#include <linux/tty.h>
  1036. +#include <linux/tty_flip.h>
  1037. +#include <linux/major.h>
  1038. +#include <linux/string.h>
  1039. +#include <linux/fcntl.h>
  1040. +#include <linux/ptrace.h>
  1041. +#include <linux/ioport.h>
  1042. +#include <linux/mm.h>
  1043. +#include <linux/slab.h>
  1044. +#include <linux/init.h>
  1045. +#include <linux/circ_buf.h>
  1046. +#include <linux/serial.h>
  1047. +#include <linux/console.h>
  1048. +#include <linux/sysrq.h>
  1049. +
  1050. +#include <asm/system.h>
  1051. +#include <asm/io.h>
  1052. +#include <asm/irq.h>
  1053. +#include <asm/uaccess.h>
  1054. +#include <asm/bitops.h>
  1055. +#include <asm/sizes.h>
  1056. +
  1057. +#if defined(CONFIG_SERIAL_IT8712_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
  1058. +#define SUPPORT_SYSRQ
  1059. +#endif
  1060. +
  1061. +#include <linux/serial_core.h>
  1062. +#include <asm/arch/sl2312.h>
  1063. +#include <asm/arch/int_ctrl.h>
  1064. +#include <asm/arch/it8712.h>
  1065. +#include "serial_it8712.h"
  1066. +
  1067. +//#define DEBUG 1
  1068. +#define UART_NR 1
  1069. +
  1070. +#define SERIAL_IT8712_NAME "ttySI"
  1071. +#define SERIAL_IT8712_MAJOR 204
  1072. +#define SERIAL_IT8712_MINOR 41 /* Temporary - will change in future */
  1073. +#define SERIAL_IT8712_NR UART_NR
  1074. +#define UART_PORT_SIZE 0x50
  1075. +
  1076. +#define CALLOUT_IT8712_NAME "cuaslI"
  1077. +#define CALLOUT_IT8712_MAJOR 205
  1078. +#define CALLOUT_IT8712_MINOR 41 /* Temporary - will change in future */
  1079. +#define CALLOUT_IT8712_NR UART_NR
  1080. +#define LPC_HOST_CONTINUE_MODE 0x00000040
  1081. +
  1082. +#define IT8712_NO_PORTS UART_NR
  1083. +
  1084. +static struct tty_driver normal, callout;
  1085. +static struct tty_struct *it8712_table[UART_NR];
  1086. +static struct termios *it8712_termios[UART_NR], *it8712_termios_locked[UART_NR];
  1087. +static struct console it8712_console;
  1088. +
  1089. +#define IT8712_ISR_PASS_LIMIT 256
  1090. +
  1091. +/*
  1092. + * Access macros for the SL2312 UARTs
  1093. + */
  1094. +#define UART_GET_INT_STATUS(p) (inb(((p)->membase+UART_IIR)) & 0x0F) // interrupt identification
  1095. +#define UART_PUT_IER(p, c) outb(c,((p)->membase+UART_IER)) // interrupt enable
  1096. +#define UART_GET_IER(p) inb(((p)->membase+UART_IER))
  1097. +#define UART_PUT_CHAR(p, c) outb(c,((p)->membase+UART_TX)) // transmitter holding
  1098. +#define UART_GET_CHAR(p) inb(((p)->membase+UART_RX)) // receive buffer
  1099. +#define UART_GET_LSR(p) inb(((p)->membase+UART_LSR)) // line status
  1100. +#define UART_GET_MSR(p) inb(((p)->membase+UART_MSR)) // modem status
  1101. +#define UART_GET_MCR(p) inb(((p)->membase+UART_MCR)) // modem control
  1102. +#define UART_PUT_MCR(p, c) outb(c,((p)->membase+UART_MCR))
  1103. +#define UART_GET_LCR(p) inb(((p)->membase+UART_LCR)) // mode control
  1104. +#define UART_PUT_LCR(p, c) outb(c,((p)->membase+UART_LCR))
  1105. +#define UART_PUT_FCR(p, c) outb(c,((p)->membase+UART_FCR)) // fifo control
  1106. +#define UART_GET_DIV_HI(p) inb(((p)->membase+UART_DLM))
  1107. +#define UART_PUT_DIV_HI(p, c) outb(c,((p)->membase+UART_DLM))
  1108. +#define UART_GET_DIV_LO(p) inb(((p)->membase+UART_DLL))
  1109. +#define UART_PUT_DIV_LO(p, c) outb(c,((p)->membase+UART_DLL))
  1110. +#define UART_PUT_MDR(p, c) outb(c,UART_MDR((p)->membase))
  1111. +#define UART_RX_DATA(s) ((s) & UART_LSR_DR)
  1112. +#define UART_TX_READY(s) ((s) & UART_LSR_THRE)
  1113. +
  1114. +static void it8712_stop_tx(struct uart_port *port, u_int from_tty)
  1115. +{
  1116. + unsigned int reg;
  1117. +
  1118. +// printk("it8712 stop tx : \n");
  1119. + reg = UART_GET_IER(port);
  1120. + reg &= ~(UART_IER_THRI);
  1121. + UART_PUT_IER(port, reg);
  1122. +}
  1123. +
  1124. +static void it8712_stop_rx(struct uart_port *port)
  1125. +{
  1126. + unsigned int reg;
  1127. +
  1128. +// printk("it8712 stop rx : \n");
  1129. + reg = UART_GET_IER(port);
  1130. + reg &= ~(UART_IER_RDI);
  1131. + UART_PUT_IER(port, reg);
  1132. +
  1133. +}
  1134. +
  1135. +static void it8712_enable_ms(struct uart_port *port)
  1136. +{
  1137. + unsigned int reg;
  1138. +
  1139. +// printk("it8712 enable ms : \n");
  1140. +
  1141. + reg = UART_GET_IER(port);
  1142. + reg |= (UART_IER_MSI);
  1143. + UART_PUT_IER(port, reg);
  1144. +
  1145. +}
  1146. +
  1147. +static void
  1148. +it8712_rx_chars(struct uart_info *info, struct pt_regs *regs)
  1149. +{
  1150. + struct tty_struct *tty = info->tty;
  1151. + unsigned int status, mask, ch, flg, ignored = 0;
  1152. + struct uart_port *port = info->port;
  1153. +
  1154. + // printk("it8712_rx_chars : \n");
  1155. + status = UART_GET_LSR(port);
  1156. + while (UART_RX_DATA(status)) {
  1157. +
  1158. + /*
  1159. + * We need to read rds before reading the
  1160. + * character from the fifo
  1161. + */
  1162. + ch = UART_GET_CHAR(port);
  1163. + port->icount.rx++;
  1164. +
  1165. + if (tty->flip.count >= TTY_FLIPBUF_SIZE)
  1166. + goto ignore_char;
  1167. +
  1168. + flg = TTY_NORMAL;
  1169. +
  1170. + /*
  1171. + * Note that the error handling code is
  1172. + * out of the main execution path
  1173. + */
  1174. +
  1175. + if (status & (UART_LSR_OE|UART_LSR_PE|UART_LSR_FE|UART_LSR_BI|UART_LSR_DE))
  1176. + goto handle_error;
  1177. + if (uart_handle_sysrq_char(info, ch, regs))
  1178. + goto ignore_char;
  1179. +
  1180. + error_return:
  1181. + *tty->flip.flag_buf_ptr++ = flg;
  1182. + *tty->flip.char_buf_ptr++ = ch;
  1183. + tty->flip.count++;
  1184. + ignore_char:
  1185. + status = UART_GET_LSR(port);
  1186. + } // end of while
  1187. +out:
  1188. + tty_flip_buffer_push(tty);
  1189. + return;
  1190. +
  1191. +handle_error:
  1192. + if (status & UART_LSR_BI) {
  1193. + status &= ~(UART_LSR_FE);
  1194. + port->icount.brk++;
  1195. +
  1196. +#ifdef SUPPORT_SYSRQ
  1197. + if (uart_handle_break(info, &it8712_console))
  1198. + goto ignore_char;
  1199. +#endif
  1200. + } else if (status & UART_LSR_PE)
  1201. + port->icount.parity++;
  1202. + else if (status & UART_LSR_FE)
  1203. + port->icount.frame++;
  1204. +
  1205. + if (status & UART_LSR_OE)
  1206. + port->icount.overrun++;
  1207. +
  1208. + if (status & port->ignore_status_mask) {
  1209. + if (++ignored > 100)
  1210. + goto out;
  1211. + goto ignore_char;
  1212. + }
  1213. +
  1214. + mask = status & port->read_status_mask;
  1215. +
  1216. + if (mask & UART_LSR_BI)
  1217. + flg = TTY_BREAK;
  1218. + else if (mask & UART_LSR_PE)
  1219. + flg = TTY_PARITY;
  1220. + else if (mask & UART_LSR_FE)
  1221. + flg = TTY_FRAME;
  1222. +
  1223. + if (status & UART_LSR_OE) {
  1224. + /*
  1225. + * CHECK: does overrun affect the current character?
  1226. + * ASSUMPTION: it does not.
  1227. + */
  1228. + *tty->flip.flag_buf_ptr++ = flg;
  1229. + *tty->flip.char_buf_ptr++ = ch;
  1230. + tty->flip.count++;
  1231. + if (tty->flip.count >= TTY_FLIPBUF_SIZE)
  1232. + goto ignore_char;
  1233. + ch = 0;
  1234. + flg = TTY_OVERRUN;
  1235. + }
  1236. +#ifdef SUPPORT_SYSRQ
  1237. + info->sysrq = 0;
  1238. +#endif
  1239. + goto error_return;
  1240. +}
  1241. +
  1242. +static void it8712_tx_chars(struct uart_info *info)
  1243. +{
  1244. + int count;
  1245. + struct uart_port *port=info->port;
  1246. +
  1247. + if (port->x_char) {
  1248. + while(!(UART_GET_LSR(port)&UART_LSR_THRE));
  1249. + UART_PUT_CHAR(port, port->x_char);
  1250. + port->icount.tx++;
  1251. + port->x_char = 0;
  1252. +
  1253. + return;
  1254. + }
  1255. + if (info->xmit.head == info->xmit.tail
  1256. + || info->tty->stopped
  1257. + || info->tty->hw_stopped) {
  1258. + it8712_stop_tx(info->port, 0);
  1259. + return;
  1260. + }
  1261. +
  1262. + count = port->fifosize >> 1;
  1263. + do {
  1264. + while(!(UART_GET_LSR(port)&UART_LSR_THRE));
  1265. + UART_PUT_CHAR(port, info->xmit.buf[info->xmit.tail]);
  1266. + info->xmit.tail = (info->xmit.tail + 1) & (UART_XMIT_SIZE - 1);
  1267. + port->icount.tx++;
  1268. + if (info->xmit.head == info->xmit.tail)
  1269. + break;
  1270. + } while (--count > 0);
  1271. +
  1272. + if (CIRC_CNT(info->xmit.head,
  1273. + info->xmit.tail,
  1274. + UART_XMIT_SIZE) < WAKEUP_CHARS)
  1275. + uart_event(info, EVT_WRITE_WAKEUP);
  1276. +
  1277. + if (info->xmit.head == info->xmit.tail)
  1278. + it8712_stop_tx(info->port, 0);
  1279. +}
  1280. +
  1281. +static void it8712_start_tx(struct uart_port *port, u_int nonempty, u_int from_tty)
  1282. +{
  1283. + unsigned int reg;
  1284. + struct uart_info *info=(struct uart_info*)(port->iobase);
  1285. +
  1286. +// printk("it8712 start tx : \n");
  1287. + reg = UART_GET_IER(port);
  1288. + reg |= (UART_IER_THRI);
  1289. + UART_PUT_IER(port, reg);
  1290. + it8712_tx_chars(info);
  1291. +}
  1292. +
  1293. +static void it8712_modem_status(struct uart_info *info)
  1294. +{
  1295. + unsigned int status;
  1296. + struct uart_icount *icount = &info->port->icount;
  1297. +
  1298. +// printk("it8712 modem status : \n");
  1299. +
  1300. + status = UART_GET_MSR(info->port);
  1301. +
  1302. + if (!(status & (UART_MSR_DCTS | UART_MSR_DDSR |
  1303. + UART_MSR_TERI | UART_MSR_DDCD)))
  1304. + return;
  1305. +
  1306. + if (status & UART_MSR_DCD) {
  1307. + icount->dcd++;
  1308. +#ifdef CONFIG_HARD_PPS
  1309. + if ((info->flags & ASYNC_HARDPPS_CD) &&
  1310. + (status & UART_MSR_DCD_MSK))
  1311. + hardpps();
  1312. +#endif
  1313. + if (info->flags & ASYNC_CHECK_CD) {
  1314. + if (status & UART_MSR_DCD)
  1315. + wake_up_interruptible(&info->open_wait);
  1316. + else if (!((info->flags & ASYNC_CALLOUT_ACTIVE) &&
  1317. + (info->flags & ASYNC_CALLOUT_NOHUP))) {
  1318. + if (info->tty)
  1319. + tty_hangup(info->tty);
  1320. + }
  1321. + }
  1322. + }
  1323. +
  1324. + if (status & UART_MSR_DDSR)
  1325. + icount->dsr++;
  1326. +
  1327. + if (status & UART_MSR_DCTS) {
  1328. + icount->cts++;
  1329. +
  1330. + if (info->flags & ASYNC_CTS_FLOW) {
  1331. + status &= UART_MSR_CTS;
  1332. +
  1333. + if (info->tty->hw_stopped) {
  1334. + if (status) {
  1335. + info->tty->hw_stopped = 0;
  1336. + info->ops->start_tx(info->port, 1, 0);
  1337. + uart_event(info, EVT_WRITE_WAKEUP);
  1338. + }
  1339. + } else {
  1340. + if (!status) {
  1341. + info->tty->hw_stopped = 1;
  1342. + info->ops->stop_tx(info->port, 0);
  1343. + }
  1344. + }
  1345. + }
  1346. + }
  1347. + wake_up_interruptible(&info->delta_msr_wait);
  1348. +
  1349. +}
  1350. +
  1351. +static void it8712_int(int irq, void *dev_id, struct pt_regs *regs)
  1352. +{
  1353. + struct uart_info *info = dev_id;
  1354. + unsigned int status, pass_counter = 0;
  1355. +
  1356. + status = UART_GET_INT_STATUS(info->port);
  1357. + do {
  1358. +// printk("it8712_int: status %x \n", status);
  1359. + switch(status)
  1360. + {
  1361. + case UART_IIR_RDI:
  1362. + case UART_IIR_RLSI:
  1363. + case UART_IIR_RCTO:
  1364. + it8712_rx_chars(info, regs);
  1365. + break;
  1366. + case UART_IIR_THRI:
  1367. + it8712_tx_chars(info);
  1368. + break;
  1369. + case UART_IIR_MSI:
  1370. + it8712_modem_status(info);
  1371. + break;
  1372. + default:
  1373. + break;
  1374. + }
  1375. + if (pass_counter++ > IT8712_ISR_PASS_LIMIT)
  1376. + break;
  1377. +
  1378. + status = UART_GET_INT_STATUS(info->port);
  1379. + } while (status);
  1380. +}
  1381. +
  1382. +static u_int it8712_tx_empty(struct uart_port *port)
  1383. +{
  1384. +// printk("it8712 tx empty : \n");
  1385. +
  1386. + return ((UART_GET_LSR(port) & UART_LSR_THRE)? TIOCSER_TEMT : 0);
  1387. +}
  1388. +
  1389. +static u_int it8712_get_mctrl(struct uart_port *port)
  1390. +{
  1391. + unsigned int result = 0;
  1392. + unsigned int status;
  1393. +
  1394. +// printk("it8712 get mctrl : \n");
  1395. +
  1396. + status = UART_GET_MSR(port);
  1397. + if (status & UART_MSR_DCD)
  1398. + result |= TIOCM_CAR;
  1399. + if (status & UART_MSR_DSR)
  1400. + result |= TIOCM_DSR;
  1401. + if (status & UART_MSR_CTS)
  1402. + result |= TIOCM_CTS;
  1403. + if (status & UART_MSR_RI)
  1404. + result |= TIOCM_RI;
  1405. +
  1406. + return result;
  1407. +}
  1408. +
  1409. +static void it8712_set_mctrl_null(struct uart_port *port, u_int mctrl)
  1410. +{
  1411. +}
  1412. +
  1413. +static void it8712_break_ctl(struct uart_port *port, int break_state)
  1414. +{
  1415. + unsigned int lcr;
  1416. +
  1417. +// printk("it8712 break ctl : \n");
  1418. +
  1419. + lcr = UART_GET_LCR(port);
  1420. + if (break_state == -1)
  1421. + lcr |= UART_LCR_SBC;
  1422. + else
  1423. + lcr &= ~UART_LCR_SBC;
  1424. + UART_PUT_LCR(port, lcr);
  1425. +}
  1426. +
  1427. +static inline u_int uart_calculate_quot(struct uart_info *info, u_int baud)
  1428. +{
  1429. + u_int quot;
  1430. +
  1431. + /* Special case: B0 rate */
  1432. + if (!baud)
  1433. + baud = 9600;
  1434. +
  1435. + quot = (info->port->uartclk/(16 * baud)) ;
  1436. +
  1437. + return quot;
  1438. +}
  1439. +static void it8712_change_speed(struct uart_port *port, u_int cflag, u_int iflag, u_int quot)
  1440. +{
  1441. + u_int uart_mc=0, old_ier;
  1442. + unsigned long flags;
  1443. +
  1444. +#ifdef DEBUG
  1445. + printk("it8712_set_cflag(0x%x) called\n", cflag);
  1446. +#endif
  1447. +
  1448. +
  1449. + /* byte size and parity */
  1450. + switch (cflag & CSIZE) {
  1451. + case CS5: uart_mc = UART_LCR_WLEN5; break;
  1452. + case CS6: uart_mc = UART_LCR_WLEN6; break;
  1453. + case CS7: uart_mc = UART_LCR_WLEN7; break;
  1454. + default: uart_mc = UART_LCR_WLEN8; break; // CS8
  1455. + }
  1456. + if (cflag & CSTOPB)
  1457. + uart_mc|= UART_LCR_STOP;
  1458. + if (cflag & PARENB) {
  1459. + uart_mc |= UART_LCR_EVEN;
  1460. + if (!(cflag & PARODD))
  1461. + uart_mc |= UART_LCR_ODD;
  1462. + }
  1463. +
  1464. + port->read_status_mask = UART_LSR_OE;
  1465. + if (iflag & INPCK)
  1466. + port->read_status_mask |= UART_LSR_FE | UART_LSR_PE;
  1467. + if (iflag & (BRKINT | PARMRK))
  1468. + port->read_status_mask |= UART_LSR_BI;
  1469. +
  1470. + /*
  1471. + * Characters to ignore
  1472. + */
  1473. + port->ignore_status_mask = 0;
  1474. + if (iflag & IGNPAR)
  1475. + port->ignore_status_mask |= UART_LSR_FE | UART_LSR_PE;
  1476. + if (iflag & IGNBRK) {
  1477. + port->ignore_status_mask |= UART_LSR_BI;
  1478. + /*
  1479. + * If we're ignoring parity and break indicators,
  1480. + * ignore overruns to (for real raw support).
  1481. + */
  1482. + if (iflag & IGNPAR)
  1483. + port->ignore_status_mask |= UART_LSR_OE;
  1484. + }
  1485. +
  1486. + /* first, disable everything */
  1487. + save_flags(flags); cli();
  1488. + old_ier = UART_GET_IER(port);
  1489. +
  1490. + if ((port->flags & ASYNC_HARDPPS_CD) ||
  1491. + (cflag & CRTSCTS) || !(cflag & CLOCAL))
  1492. + old_ier |= UART_IER_MSI;
  1493. +
  1494. + /* Set baud rate */
  1495. + quot = quot / 13;
  1496. + UART_PUT_LCR(port, UART_LCR_DLAB);
  1497. + UART_PUT_DIV_LO(port, (quot & 0xff));
  1498. + UART_PUT_DIV_HI(port, ((quot & 0xf00) >> 8));
  1499. +
  1500. + UART_PUT_LCR(port, uart_mc);
  1501. +// UART_PUT_LCR(port, 0x07); // ???? it is wired
  1502. + UART_PUT_MCR(port, 0x08);
  1503. + UART_PUT_FCR(port, 0x01);
  1504. + UART_PUT_IER(port, 0x05);
  1505. +
  1506. + restore_flags(flags);
  1507. +}
  1508. +
  1509. +static int it8712_startup(struct uart_port *port, struct uart_info *info)
  1510. +{
  1511. + int retval;
  1512. + unsigned int regs;
  1513. +
  1514. +// printk("it8712 startup : \n");
  1515. +
  1516. + /*
  1517. + * Use iobase to store a pointer to info. We need this to start a
  1518. + * transmission as the tranmittr interrupt is only generated on
  1519. + * the transition to the idle state
  1520. + */
  1521. +
  1522. + port->iobase=(u_int)info;
  1523. +
  1524. + /*
  1525. + * Allocate the IRQ
  1526. + */
  1527. + retval = request_irq(port->irq, it8712_int, SA_INTERRUPT, "it8712", info);
  1528. + if (retval)
  1529. + return retval;
  1530. +
  1531. + /* setup interrupt controller */
  1532. + regs = *((volatile unsigned int *)IRQ_TMODE(IO_ADDRESS(SL2312_INTERRUPT_BASE)));
  1533. + regs |= (IRQ_SERIRQ0_MASK);
  1534. + *((volatile unsigned int *)IRQ_TMODE(IO_ADDRESS(SL2312_INTERRUPT_BASE))) = regs;
  1535. + regs = *((volatile unsigned int *)IRQ_LEVEL(IO_ADDRESS(SL2312_INTERRUPT_BASE)));
  1536. + regs &= ~(IRQ_SERIRQ0_MASK);
  1537. + *((volatile unsigned int *)IRQ_LEVEL(IO_ADDRESS(SL2312_INTERRUPT_BASE))) = regs;
  1538. + *((volatile unsigned int *)IRQ_MASK(IO_ADDRESS(SL2312_INTERRUPT_BASE))) |= (unsigned int)(IRQ_SERIRQ0_MASK);
  1539. +
  1540. + /*
  1541. + * Finally, enable interrupts. Use the TII interrupt to minimise
  1542. + * the number of interrupts generated. If higher performance is
  1543. + * needed, consider using the TI interrupt with a suitable FIFO
  1544. + * threshold
  1545. + */
  1546. + UART_PUT_IER(port, (UART_IER_RDI|UART_IER_THRI));
  1547. +
  1548. + return 0;
  1549. +}
  1550. +
  1551. +static void it8712_shutdown(struct uart_port *port, struct uart_info *info)
  1552. +{
  1553. +// printk("it8712 shutdown : \n");
  1554. +
  1555. + /*
  1556. + * disable all interrupts, disable the port
  1557. + */
  1558. + UART_PUT_IER(port, 0x0);
  1559. +
  1560. + /* disable break condition and fifos */
  1561. +// UART_PUT_MCR(port, (UART_GET_MCR(port)&UART_MCR_MASK));
  1562. +
  1563. + /*
  1564. + * Free the interrupt
  1565. + */
  1566. + free_irq(port->irq, info);
  1567. +}
  1568. +
  1569. +static const char *it8712_type(struct uart_port *port)
  1570. +{
  1571. + return port->type == PORT_IT8712 ? "IT8712" : NULL;
  1572. +}
  1573. +
  1574. +/*
  1575. + * Release the memory region(s) being used by 'port'
  1576. + */
  1577. +static void it8712_release_port(struct uart_port *port)
  1578. +{
  1579. +// printk("it8712 release port : \n");
  1580. +
  1581. + release_mem_region(port->mapbase, UART_PORT_SIZE);
  1582. +}
  1583. +
  1584. +/*
  1585. + * Request the memory region(s) being used by 'port'
  1586. + */
  1587. +static int it8712_request_port(struct uart_port *port)
  1588. +{
  1589. + return request_mem_region(port->mapbase, UART_PORT_SIZE,
  1590. + "serial_it8712") != NULL ? 0 : -EBUSY;
  1591. +}
  1592. +
  1593. +/*
  1594. + * Configure/autoconfigure the port.
  1595. + */
  1596. +static void it8712_config_port(struct uart_port *port, int flags)
  1597. +{
  1598. +
  1599. + if (flags & UART_CONFIG_TYPE) {
  1600. + if (it8712_request_port(port) == 0)
  1601. + port->type = PORT_IT8712;
  1602. + }
  1603. +}
  1604. +
  1605. +/*
  1606. + * verify the new serial_struct (for TIOCSSERIAL).
  1607. + */
  1608. +static int it8712_verify_port(struct uart_port *port, struct serial_struct *ser)
  1609. +{
  1610. + int ret = 0;
  1611. +
  1612. + if (ser->type != PORT_UNKNOWN && ser->type != PORT_UART00)
  1613. + ret = -EINVAL;
  1614. + if (ser->irq < 0 || ser->irq >= NR_IRQS)
  1615. + ret = -EINVAL;
  1616. + if (ser->baud_base < 9600)
  1617. + ret = -EINVAL;
  1618. + return ret;
  1619. +}
  1620. +
  1621. +static struct uart_ops it8712_pops = {
  1622. + tx_empty: it8712_tx_empty,
  1623. + set_mctrl: it8712_set_mctrl_null,
  1624. + get_mctrl: it8712_get_mctrl,
  1625. + stop_tx: it8712_stop_tx,
  1626. + start_tx: it8712_start_tx,
  1627. + stop_rx: it8712_stop_rx,
  1628. + enable_ms: it8712_enable_ms,
  1629. + break_ctl: it8712_break_ctl,
  1630. + startup: it8712_startup,
  1631. + shutdown: it8712_shutdown,
  1632. + change_speed: it8712_change_speed,
  1633. + type: it8712_type,
  1634. + release_port: it8712_release_port,
  1635. + request_port: it8712_request_port,
  1636. + config_port: it8712_config_port,
  1637. + verify_port: it8712_verify_port,
  1638. +};
  1639. +
  1640. +#ifdef CONFIG_ARCH_SL2312
  1641. +
  1642. +static struct uart_port it8712_ports[UART_NR] = {
  1643. + {
  1644. + membase: (void *)0,
  1645. + mapbase: 0,
  1646. + iotype: SERIAL_IO_MEM,
  1647. + irq: 0,
  1648. + uartclk: UART_CLK/2,
  1649. + fifosize: 16,
  1650. + ops: &it8712_pops,
  1651. + flags: ASYNC_BOOT_AUTOCONF,
  1652. + }
  1653. +};
  1654. +
  1655. +#endif
  1656. +
  1657. +#ifdef CONFIG_SERIAL_IT8712_CONSOLE
  1658. +#ifdef used_and_not_const_char_pointer
  1659. +static int it8712_console_read(struct uart_port *port, char *s, u_int count)
  1660. +{
  1661. + unsigned int status;
  1662. + int c;
  1663. +#ifdef DEBUG
  1664. + printk("it8712_console_read() called\n");
  1665. +#endif
  1666. +
  1667. + c = 0;
  1668. + while (c < count) {
  1669. + status = UART_GET_LSR(port);
  1670. + if (UART_RX_DATA(status)) {
  1671. + *s++ = UART_GET_CHAR(port);
  1672. + c++;
  1673. + } else {
  1674. + // nothing more to get, return
  1675. + return c;
  1676. + }
  1677. + }
  1678. + // return the count
  1679. + return c;
  1680. +}
  1681. +#endif
  1682. +static void it8712_console_write(struct console *co, const char *s, unsigned count)
  1683. +{
  1684. +#ifdef CONFIG_ARCH_SL2312
  1685. + struct uart_port *port = it8712_ports + co->index;
  1686. + unsigned int status, old_ies;
  1687. + int i;
  1688. +
  1689. + /*
  1690. + * First save the CR then disable the interrupts
  1691. + */
  1692. + old_ies = UART_GET_IER(port);
  1693. + UART_PUT_IER(port,0x0);
  1694. +
  1695. + /*
  1696. + * Now, do each character
  1697. + */
  1698. + for (i = 0; i < count; i++) {
  1699. + do {
  1700. + status = UART_GET_LSR(port);
  1701. + } while (!UART_TX_READY(status));
  1702. + UART_PUT_CHAR(port, s[i]);
  1703. + if (s[i] == '\n') {
  1704. + do {
  1705. + status = UART_GET_LSR(port);
  1706. + } while (!UART_TX_READY(status));
  1707. + UART_PUT_CHAR(port, '\r');
  1708. + }
  1709. + }
  1710. +
  1711. + /*
  1712. + * Finally, wait for transmitter to become empty
  1713. + * and restore the IES
  1714. + */
  1715. + do {
  1716. + status = UART_GET_LSR(port);
  1717. + } while (!(status&UART_LSR_THRE));
  1718. + UART_PUT_IER(port, old_ies);
  1719. +#endif
  1720. +}
  1721. +
  1722. +static kdev_t it8712_console_device(struct console *co)
  1723. +{
  1724. + return MKDEV(SERIAL_IT8712_MAJOR, SERIAL_IT8712_MINOR + co->index);
  1725. +}
  1726. +
  1727. +static int it8712_console_wait_key(struct console *co)
  1728. +{
  1729. +#ifdef CONFIG_ARCH_SL2312
  1730. + struct uart_port *port = (it8712_ports + co->index);
  1731. + unsigned int status;
  1732. +
  1733. + do {
  1734. + status = UART_GET_LSR(port);
  1735. + } while (!UART_RX_DATA(status));
  1736. + return UART_GET_CHAR(port);
  1737. +#else
  1738. + return 0;
  1739. +#endif
  1740. +}
  1741. +
  1742. +static void /*__init*/ it8712_console_get_options(struct uart_port *port, int *baud, int *parity, int *bits)
  1743. +{
  1744. + printk("it8712 console get options : \n");
  1745. +
  1746. + u_int uart_mc, quot;
  1747. + uart_mc= UART_GET_MCR(port);
  1748. +
  1749. + *parity = 'n';
  1750. + if (uart_mc & UART_LCR_PARITY) {
  1751. + if (uart_mc & UART_LCR_EVEN)
  1752. + *parity = 'e';
  1753. + else
  1754. + *parity = 'o';
  1755. + }
  1756. +
  1757. + switch (uart_mc & UART_LCR_MSK){
  1758. +
  1759. + case UART_LCR_WLEN5:
  1760. + *bits = 5;
  1761. + break;
  1762. + case UART_LCR_WLEN6:
  1763. + *bits = 6;
  1764. + break;
  1765. + case UART_LCR_WLEN7:
  1766. + *bits = 7;
  1767. + break;
  1768. + case UART_LCR_WLEN8:
  1769. + *bits = 8;
  1770. + break;
  1771. + }
  1772. + UART_PUT_MCR(port,UART_LCR_DLAB);
  1773. + quot = UART_GET_DIV_LO(port) | (UART_GET_DIV_HI(port) << 8);
  1774. + UART_PUT_MCR(port,uart_mc);
  1775. + *baud = (port->uartclk / (16 *quot));
  1776. +}
  1777. +
  1778. +static int __init it8712_console_setup(struct console *co, char *options)
  1779. +{
  1780. + struct uart_port *port;
  1781. + int baud = 38400;
  1782. + int bits = 8;
  1783. + int parity = 'n';
  1784. + int flow= 'n';
  1785. + int base, irq;
  1786. + int i ;
  1787. +
  1788. +// printk("it8712 console setup : \n");
  1789. +
  1790. + LPCSetConfig(0, 0x02, 0x01);
  1791. + LPCSetConfig(LDN_SERIAL1, 0x30, 0x1);
  1792. + LPCSetConfig(LDN_SERIAL1, 0x23, 0x0);
  1793. + base = IT8712_IO_BASE;
  1794. + base += ((LPCGetConfig(LDN_SERIAL1, 0x60) << 8) + LPCGetConfig(LDN_SERIAL1, 0x61));
  1795. + it8712_ports[0].mapbase = base;
  1796. + it8712_ports[0].membase = IO_ADDRESS(base);
  1797. + it8712_ports[0].irq = IRQ_SERIRQ0_OFFSET;
  1798. + irq = LPCGetConfig(LDN_SERIAL1, 0x70);
  1799. + it8712_ports[0].irq += irq;
  1800. +
  1801. + printk("it8712 irq is %x %x \n", it8712_ports[0].irq, irq);
  1802. +
  1803. + // setup LPC Host 'quiet mode'
  1804. + *((volatile unsigned int *)IO_ADDRESS((SL2312_LPC_HOST_BASE+0x04))) |= LPC_HOST_CONTINUE_MODE ;
  1805. + for(i=0;i<1000;i++) ; // delay
  1806. + *((volatile unsigned int *)IO_ADDRESS((SL2312_LPC_HOST_BASE+0x04))) &= ~(LPC_HOST_CONTINUE_MODE) ;
  1807. +
  1808. +#ifdef CONFIG_ARCH_SL2312
  1809. + /*
  1810. + * Check whether an invalid uart number has been specified, and
  1811. + * if so, search for the first available port that does have
  1812. + * console support.
  1813. + */
  1814. + port = uart_get_console(it8712_ports,IT8712_NO_PORTS,co);
  1815. +#else
  1816. + return -ENODEV;
  1817. +#endif
  1818. +
  1819. + if (options)
  1820. + uart_parse_options(options, &baud, &parity, &bits, &flow);
  1821. + else
  1822. + it8712_console_get_options(port, &baud, &parity, &bits);
  1823. +
  1824. + return uart_set_options(port, co, baud, parity, bits, flow);
  1825. +}
  1826. +
  1827. +static struct console it8712_console = {
  1828. + name: SERIAL_IT8712_NAME,
  1829. + write: it8712_console_write,
  1830. +#ifdef used_and_not_const_char_pointer
  1831. + read: it8712_console_read,
  1832. +#endif
  1833. + device: it8712_console_device,
  1834. +// wait_key: it8712_console_wait_key,
  1835. + setup: it8712_console_setup,
  1836. + flags: (CON_PRINTBUFFER|CON_ENABLED),
  1837. + index: -1,
  1838. +};
  1839. +
  1840. +void __init it8712_console_init(void)
  1841. +{
  1842. + register_console(&it8712_console);
  1843. +}
  1844. +
  1845. +#define IT8712_CONSOLE &it8712_console
  1846. +#else
  1847. +#define IT8712_CONSOLE NULL
  1848. +#endif
  1849. +
  1850. +static struct uart_driver it8712_reg = {
  1851. + owner: NULL,
  1852. + normal_major: SERIAL_IT8712_MAJOR,
  1853. + normal_name: SERIAL_IT8712_NAME,
  1854. + normal_driver: &normal,
  1855. + callout_major: CALLOUT_IT8712_MAJOR,
  1856. + callout_name: CALLOUT_IT8712_NAME,
  1857. + callout_driver: &callout,
  1858. + table: it8712_table,
  1859. + termios: it8712_termios,
  1860. + termios_locked: it8712_termios_locked,
  1861. + minor: SERIAL_IT8712_MINOR,
  1862. + nr: UART_NR,
  1863. +#ifdef CONFIG_ARCH_SL2312
  1864. + port: it8712_ports,
  1865. +#endif
  1866. + state: NULL,
  1867. + cons: IT8712_CONSOLE,
  1868. +};
  1869. +
  1870. +static int __init it8712_init(void)
  1871. +{
  1872. +// printk("serial_it8712: it871212_init \n");
  1873. +
  1874. + return uart_register_driver(&it8712_reg);
  1875. +}
  1876. +
  1877. +
  1878. +__initcall(it8712_init);
  1879. --- /dev/null
  1880. +++ b/drivers/serial/serial_sl2312.c
  1881. @@ -0,0 +1,827 @@
  1882. +/*
  1883. + * linux/drivers/char/serial_uart00.c
  1884. + *
  1885. + * Driver for UART00 serial ports
  1886. + *
  1887. + * Based on drivers/char/serial_amba.c, by ARM Limited &
  1888. + * Deep Blue Solutions Ltd.
  1889. + * Copyright 2001 Altera Corporation
  1890. + *
  1891. + * This program is free software; you can redistribute it and/or modify
  1892. + * it under the terms of the GNU General Public License as published by
  1893. + * the Free Software Foundation; either version 2 of the License, or
  1894. + * (at your option) any later version.
  1895. + *
  1896. + * This program is distributed in the hope that it will be useful,
  1897. + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  1898. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  1899. + * GNU General Public License for more details.
  1900. + *
  1901. + * You should have received a copy of the GNU General Public License
  1902. + * along with this program; if not, write to the Free Software
  1903. + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  1904. + *
  1905. + * $Id: serial_sl2312.c,v 1.1.1.1 2006/04/03 08:41:00 amos_lee Exp $
  1906. + *
  1907. + */
  1908. +#include <linux/module.h>
  1909. +
  1910. +#include <linux/errno.h>
  1911. +#include <linux/signal.h>
  1912. +#include <linux/sched.h>
  1913. +#include <linux/interrupt.h>
  1914. +#include <linux/tty.h>
  1915. +#include <linux/tty_flip.h>
  1916. +#include <linux/major.h>
  1917. +#include <linux/string.h>
  1918. +#include <linux/fcntl.h>
  1919. +#include <linux/ptrace.h>
  1920. +#include <linux/ioport.h>
  1921. +#include <linux/mm.h>
  1922. +#include <linux/slab.h>
  1923. +#include <linux/init.h>
  1924. +#include <linux/circ_buf.h>
  1925. +#include <linux/serial.h>
  1926. +#include <linux/console.h>
  1927. +#include <linux/sysrq.h>
  1928. +#include <linux/serial_core.h>
  1929. +
  1930. +#include <asm/system.h>
  1931. +#include <asm/hardware.h>
  1932. +#include <asm/io.h>
  1933. +#include <asm/irq.h>
  1934. +#include <asm/uaccess.h>
  1935. +#include <asm/bitops.h>
  1936. +#include <asm/sizes.h>
  1937. +#include <linux/spinlock.h>
  1938. +#include <linux/irq.h>
  1939. +
  1940. +
  1941. +#if defined(CONFIG_SERIAL_SL2312_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
  1942. +#define SUPPORT_SYSRQ
  1943. +#endif
  1944. +
  1945. +#include <asm/arch/sl2312.h>
  1946. +#define UART_TYPE (volatile unsigned int*)
  1947. +#include <asm/arch/uart.h>
  1948. +#include <asm/arch/int_ctrl.h>
  1949. +
  1950. +// #define DEBUG 1
  1951. +#define UART_NR 1
  1952. +
  1953. +
  1954. +#define SERIAL_SL2312_NAME "ttyS"
  1955. +#define SERIAL_SL2312_MAJOR 204
  1956. +#define SERIAL_SL2312_MINOR 40 /* Temporary - will change in future */
  1957. +#define SERIAL_SL2312_NR UART_NR
  1958. +#define UART_PORT_SIZE 0x50
  1959. +
  1960. +#define SL2312_NO_PORTS UART_NR
  1961. +#define SL2312_ISR_PASS_LIMIT 256
  1962. +
  1963. +/*
  1964. + * Access macros for the SL2312 UARTs
  1965. + */
  1966. +#define UART_GET_INT_STATUS(p) (inl(UART_IIR((p)->membase)) & 0x0F) // interrupt identification
  1967. +#define UART_PUT_IER(p, c) outl(c,UART_IER((p)->membase)) // interrupt enable
  1968. +#define UART_GET_IER(p) inl(UART_IER((p)->membase))
  1969. +#define UART_PUT_CHAR(p, c) outl(c,UART_THR((p)->membase)) // transmitter holding
  1970. +#define UART_GET_CHAR(p) inl(UART_RBR((p)->membase)) // receive buffer
  1971. +#define UART_GET_LSR(p) inl(UART_LSR((p)->membase)) // line status
  1972. +#define UART_GET_MSR(p) inl(UART_MSR((p)->membase)) // modem status
  1973. +#define UART_GET_MCR(p) inl(UART_MCR((p)->membase)) // modem control
  1974. +#define UART_PUT_MCR(p, c) outl(c,UART_MCR((p)->membase))
  1975. +#define UART_GET_LCR(p) inl(UART_LCR((p)->membase)) // mode control
  1976. +#define UART_PUT_LCR(p, c) outl(c,UART_LCR((p)->membase))
  1977. +#define UART_GET_DIV_HI(p) inl(UART_DIV_HI((p)->membase))
  1978. +#define UART_PUT_DIV_HI(p, c) outl(c,UART_DIV_HI((p)->membase))
  1979. +#define UART_GET_DIV_LO(p) inl(UART_DIV_LO((p)->membase))
  1980. +#define UART_PUT_DIV_LO(p, c) outl(c,UART_DIV_LO((p)->membase))
  1981. +#define UART_PUT_MDR(p, c) outl(c,UART_MDR((p)->membase))
  1982. +#define UART_RX_DATA(s) ((s) & UART_LSR_DR)
  1983. +#define UART_TX_READY(s) ((s) & UART_LSR_THRE)
  1984. +
  1985. +
  1986. +static void sl2312_stop_tx(struct uart_port *port)
  1987. +{
  1988. + unsigned int reg;
  1989. +
  1990. +// printk("sl2312 stop tx : \n");
  1991. + reg = UART_GET_IER(port);
  1992. + reg &= ~(UART_IER_TE);
  1993. + UART_PUT_IER(port, reg);
  1994. +}
  1995. +
  1996. +static void sl2312_stop_rx(struct uart_port *port)
  1997. +{
  1998. + unsigned int reg;
  1999. +
  2000. +// printk("sl2312 stop rx : \n");
  2001. + reg = UART_GET_IER(port);
  2002. + reg &= ~(UART_IER_DR);
  2003. + UART_PUT_IER(port, reg);
  2004. +
  2005. +}
  2006. +
  2007. +static void sl2312_enable_ms(struct uart_port *port)
  2008. +{
  2009. + unsigned int reg;
  2010. +
  2011. +// printk("sl2312 enable ms : \n");
  2012. +
  2013. + reg = UART_GET_IER(port);
  2014. + reg |= (UART_IER_MS);
  2015. + UART_PUT_IER(port, reg);
  2016. +
  2017. +}
  2018. +
  2019. +static void
  2020. +sl2312_rx_chars(struct uart_port *port)
  2021. +{
  2022. + struct tty_struct *tty = port->info->tty;
  2023. + unsigned int status, mask, ch, flg, ignored = 0;
  2024. +
  2025. +
  2026. + // printk("sl2312_rx_chars : \n");
  2027. + status = UART_GET_LSR(port);
  2028. + while (UART_RX_DATA(status)) {
  2029. +
  2030. + /*
  2031. + * We need to read rds before reading the
  2032. + * character from the fifo
  2033. + */
  2034. + ch = UART_GET_CHAR(port);
  2035. + port->icount.rx++;
  2036. +
  2037. + //if (tty->flip.count >= TTY_FLIPBUF_SIZE)
  2038. + if (tty && !tty_buffer_request_room(tty, 1))
  2039. + goto ignore_char;
  2040. +
  2041. + flg = TTY_NORMAL;
  2042. +
  2043. + /*
  2044. + * Note that the error handling code is
  2045. + * out of the main execution path
  2046. + */
  2047. +
  2048. + if (status & (UART_LSR_OE|UART_LSR_PE|UART_LSR_FE|UART_LSR_BI|UART_LSR_DE))
  2049. + goto handle_error;
  2050. + if (uart_handle_sysrq_char(port, ch))
  2051. + goto ignore_char;
  2052. +
  2053. + error_return:
  2054. + //*tty->flip.flag_buf_ptr++ = flg;
  2055. + //*tty->flip.char_buf_ptr++ = ch;
  2056. + //tty->flip.count++;
  2057. + tty_insert_flip_char(tty, ch, flg);
  2058. + ignore_char:
  2059. + status = UART_GET_LSR(port);
  2060. + } // end of while
  2061. +out:
  2062. + tty_flip_buffer_push(tty);
  2063. + return;
  2064. +
  2065. +handle_error:
  2066. + if (status & UART_LSR_BI) {
  2067. + status &= ~(UART_LSR_FE);
  2068. + port->icount.brk++;
  2069. +
  2070. +#ifdef SUPPORT_SYSRQ
  2071. + if (uart_handle_break(port))
  2072. + goto ignore_char;
  2073. +#endif
  2074. + } else if (status & UART_LSR_PE)
  2075. + port->icount.parity++;
  2076. + else if (status & UART_LSR_FE)
  2077. + port->icount.frame++;
  2078. +
  2079. + if (status & UART_LSR_OE)
  2080. + port->icount.overrun++;
  2081. +
  2082. + if (status & port->ignore_status_mask) {
  2083. + if (++ignored > 100)
  2084. + goto out;
  2085. + goto ignore_char;
  2086. + }
  2087. +
  2088. + mask = status & port->read_status_mask;
  2089. +
  2090. + if (mask & UART_LSR_BI)
  2091. + flg = TTY_BREAK;
  2092. + else if (mask & UART_LSR_PE)
  2093. + flg = TTY_PARITY;
  2094. + else if (mask & UART_LSR_FE)
  2095. + flg = TTY_FRAME;
  2096. +
  2097. + if (status & UART_LSR_OE) {
  2098. + /*
  2099. + * CHECK: does overrun affect the current character?
  2100. + * ASSUMPTION: it does not.
  2101. + */
  2102. + //*tty->flip.flag_buf_ptr++ = flg;
  2103. + //*tty->flip.char_buf_ptr++ = ch;
  2104. + //tty->flip.count++;
  2105. +
  2106. + tty_insert_flip_char(tty, 0, TTY_BREAK);
  2107. +
  2108. + // if (tty->flip.count >= TTY_FLIPBUF_SIZE)
  2109. + if (tty_buffer_request_room(tty, 1))
  2110. + goto ignore_char;
  2111. + ch = 0;
  2112. + flg = TTY_OVERRUN;
  2113. + }
  2114. +#ifdef SUPPORT_SYSRQ
  2115. + port->sysrq = 0;
  2116. +#endif
  2117. + goto error_return;
  2118. +}
  2119. +
  2120. +static void sl2312_tx_chars(struct uart_port *port)
  2121. +{
  2122. + struct circ_buf *xmit = &port->info->xmit;
  2123. + int count;
  2124. +
  2125. +
  2126. + if (port->x_char) {
  2127. + while(!(UART_GET_LSR(port)&UART_LSR_THRE));
  2128. + UART_PUT_CHAR(port, port->x_char);
  2129. + port->icount.tx++;
  2130. + port->x_char = 0;
  2131. +
  2132. + return;
  2133. + }
  2134. + if (uart_circ_empty(xmit) || uart_tx_stopped(port)) {
  2135. + sl2312_stop_tx(port);
  2136. +
  2137. + return;
  2138. + }
  2139. +
  2140. + count = port->fifosize >> 1;
  2141. + do {
  2142. + while(!(UART_GET_LSR(port)&UART_LSR_THRE));
  2143. + UART_PUT_CHAR(port, xmit->buf[xmit->tail]);
  2144. + xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
  2145. + port->icount.tx++;
  2146. + if (uart_circ_empty(xmit))
  2147. + break;
  2148. + } while (--count > 0);
  2149. +
  2150. + if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
  2151. + uart_write_wakeup(port);
  2152. +
  2153. + if (uart_circ_empty(xmit))
  2154. + sl2312_stop_tx(port);
  2155. +
  2156. +}
  2157. +
  2158. +static void sl2312_start_tx(struct uart_port *port)
  2159. +{
  2160. + unsigned int reg;
  2161. +
  2162. +// printk("sl2312 start tx : \n");
  2163. + reg = UART_GET_IER(port);
  2164. + reg |= (UART_IER_TE);
  2165. + UART_PUT_IER(port, reg);
  2166. +
  2167. + sl2312_tx_chars(port);
  2168. +}
  2169. +
  2170. +static void sl2312_modem_status(struct uart_port *port)
  2171. +{
  2172. + unsigned int status;
  2173. +
  2174. +// printk("it8712 modem status : \n");
  2175. +
  2176. + status = UART_GET_MSR(port);
  2177. +
  2178. + if (!(status & (UART_MSR_DCTS | UART_MSR_DDSR |
  2179. + UART_MSR_TERI | UART_MSR_DDCD)))
  2180. + return;
  2181. +
  2182. + if (status & UART_MSR_DDCD)
  2183. + uart_handle_dcd_change(port, status & UART_MSR_DCD);
  2184. +
  2185. + if (status & UART_MSR_DDSR)
  2186. + port->icount.dsr++;
  2187. +
  2188. + if (status & UART_MSR_DCTS)
  2189. + uart_handle_cts_change(port, status & UART_MSR_CTS);
  2190. +
  2191. + wake_up_interruptible(&port->info->delta_msr_wait);
  2192. +
  2193. +}
  2194. +
  2195. +static irqreturn_t sl2312_int(int irq, void *dev_id)
  2196. +{
  2197. + struct uart_port *port = dev_id;
  2198. + unsigned int status, pass_counter = 0;
  2199. +
  2200. + status = UART_GET_INT_STATUS(port);
  2201. + do {
  2202. + switch(status)
  2203. + {
  2204. + case UART_IIR_DR:
  2205. + case UART_IIR_RLS:
  2206. + sl2312_rx_chars(port);
  2207. + break;
  2208. + case UART_IIR_TE:
  2209. + sl2312_tx_chars(port);
  2210. + break;
  2211. + case UART_IIR_MODEM:
  2212. + sl2312_modem_status(port);
  2213. + break;
  2214. + default:
  2215. + break;
  2216. + }
  2217. + if (pass_counter++ > SL2312_ISR_PASS_LIMIT)
  2218. + break;
  2219. +
  2220. + status = UART_GET_INT_STATUS(port);
  2221. + } while (status);
  2222. +
  2223. + return IRQ_HANDLED;
  2224. +}
  2225. +
  2226. +static u_int sl2312_tx_empty(struct uart_port *port)
  2227. +{
  2228. +// printk("sl2312 tx empty : \n");
  2229. +
  2230. + return ((UART_GET_LSR(port) & UART_LSR_TE)? TIOCSER_TEMT : 0);
  2231. +}
  2232. +
  2233. +static u_int sl2312_get_mctrl(struct uart_port *port)
  2234. +{
  2235. + unsigned int result = 0;
  2236. + unsigned int status;
  2237. +
  2238. +// printk("sl2312 get mctrl : \n");
  2239. +
  2240. + status = UART_GET_MSR(port);
  2241. + if (status & UART_MSR_DCD)
  2242. + result |= TIOCM_CAR;
  2243. + if (status & UART_MSR_DSR)
  2244. + result |= TIOCM_DSR;
  2245. + if (status & UART_MSR_CTS)
  2246. + result |= TIOCM_CTS;
  2247. + if (status & UART_MSR_RI)
  2248. + result |= TIOCM_RI;
  2249. +
  2250. + return result;
  2251. +}
  2252. +
  2253. +static void sl2312_set_mctrl_null(struct uart_port *port, u_int mctrl)
  2254. +{
  2255. +}
  2256. +
  2257. +static void sl2312_break_ctl(struct uart_port *port, int break_state)
  2258. +{
  2259. + unsigned int lcr;
  2260. +
  2261. +// printk("sl2312 break ctl : \n");
  2262. +
  2263. + lcr = UART_GET_LCR(port);
  2264. + if (break_state == -1)
  2265. + lcr |= UART_LCR_SETBREAK;
  2266. + else
  2267. + lcr &= ~UART_LCR_SETBREAK;
  2268. + UART_PUT_LCR(port, lcr);
  2269. +}
  2270. +
  2271. +static inline u_int uart_calculate_quot(struct uart_port *port, u_int baud)
  2272. +{
  2273. + u_int quot;
  2274. +
  2275. + /* Special case: B0 rate */
  2276. + if (!baud)
  2277. + baud = 9600;
  2278. +
  2279. + quot = (port->uartclk / (16 * baud)-1) ;
  2280. +
  2281. + return quot;
  2282. +}
  2283. +
  2284. +static void sl2312_set_termios(struct uart_port *port, struct ktermios *termios,
  2285. + struct ktermios *old)
  2286. +{
  2287. + unsigned int uart_mc, old_ier, baud, quot;
  2288. + unsigned long flags;
  2289. +
  2290. + termios->c_cflag |= CREAD;
  2291. +#ifdef DEBUG
  2292. + printk("it8712_set_cflag(0x%x) called\n", cflag);
  2293. +#endif
  2294. + baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk/16);
  2295. + quot = (port->uartclk / (16 * baud)) ;
  2296. + //uart_get_divisor(port, baud);
  2297. +
  2298. + /* byte size and parity */
  2299. + switch (termios->c_cflag & CSIZE) {
  2300. + case CS5:
  2301. + uart_mc = UART_LCR_LEN5;
  2302. + break;
  2303. + case CS6:
  2304. + uart_mc = UART_LCR_LEN6;
  2305. + break;
  2306. + case CS7:
  2307. + uart_mc = UART_LCR_LEN7;
  2308. + break;
  2309. + default: // CS8
  2310. + uart_mc = UART_LCR_LEN8;
  2311. + break;
  2312. + }
  2313. +
  2314. + if (termios->c_cflag & CSTOPB)
  2315. + uart_mc|= UART_LCR_STOP;
  2316. + if (termios->c_cflag & PARENB) {
  2317. + uart_mc |= UART_LCR_EVEN;
  2318. + if (!(termios->c_cflag & PARODD))
  2319. + uart_mc |= UART_LCR_ODD;
  2320. + }
  2321. +
  2322. + spin_lock_irqsave(&port->lock, flags);
  2323. + /*
  2324. + * Update the per-port timeout
  2325. + */
  2326. + uart_update_timeout(port, termios->c_cflag, baud);
  2327. + port->read_status_mask = UART_LSR_OE;
  2328. + if (termios->c_iflag & INPCK)
  2329. + port->read_status_mask |= UART_LSR_FE | UART_LSR_PE;
  2330. + if (termios->c_iflag & (BRKINT | PARMRK))
  2331. + port->read_status_mask |= UART_LSR_BI;
  2332. +
  2333. + /*
  2334. + * Characters to ignore
  2335. + */
  2336. + port->ignore_status_mask = 0;
  2337. + if (termios->c_iflag & IGNPAR)
  2338. + port->ignore_status_mask |= UART_LSR_FE | UART_LSR_PE;
  2339. + if (termios->c_iflag & IGNBRK) {
  2340. + port->ignore_status_mask |= UART_LSR_BI;
  2341. + /*
  2342. + * If we're ignoring parity and break indicators,
  2343. + * ignore overruns to (for real raw support).
  2344. + */
  2345. + if (termios->c_iflag & IGNPAR)
  2346. + port->ignore_status_mask |= UART_LSR_OE;
  2347. + }
  2348. +
  2349. + //save_flags(flags); cli();
  2350. + old_ier = UART_GET_IER(port);
  2351. +
  2352. + if(UART_ENABLE_MS(port, termios->c_cflag))
  2353. + old_ier |= UART_IER_MS;
  2354. +
  2355. + /* Set baud rate */
  2356. + UART_PUT_LCR(port, UART_LCR_DLAB);
  2357. + UART_PUT_DIV_LO(port, (quot & 0xff));
  2358. + UART_PUT_DIV_HI(port, ((quot & 0xf00) >> 8));
  2359. +
  2360. + UART_PUT_LCR(port, uart_mc);
  2361. + UART_PUT_IER(port, old_ier);
  2362. +
  2363. + //restore_flags(flags);
  2364. + spin_unlock_irqrestore(&port->lock, flags);
  2365. +}
  2366. +
  2367. +
  2368. +
  2369. +static int sl2312_startup(struct uart_port *port)
  2370. +{
  2371. + int retval;
  2372. + unsigned int regs;
  2373. +
  2374. +// printk("sl2312 startup : \n");
  2375. +
  2376. + /*
  2377. + * Use iobase to store a pointer to info. We need this to start a
  2378. + * transmission as the tranmittr interrupt is only generated on
  2379. + * the transition to the idle state
  2380. + */
  2381. +
  2382. + /*
  2383. + * Allocate the IRQ
  2384. + */
  2385. + retval = request_irq(port->irq, sl2312_int, IRQF_DISABLED, "sl2312", port);
  2386. + if (retval)
  2387. + return retval;
  2388. +
  2389. + /* setup interrupt controller */
  2390. + regs = *((volatile unsigned int *)IRQ_TMODE(IO_ADDRESS(SL2312_INTERRUPT_BASE)));
  2391. + regs &= ~(IRQ_UART_MASK);
  2392. + *((volatile unsigned int *)IRQ_TMODE(IO_ADDRESS(SL2312_INTERRUPT_BASE))) = regs;
  2393. + regs = *((volatile unsigned int *)IRQ_TLEVEL(IO_ADDRESS(SL2312_INTERRUPT_BASE)));
  2394. + regs &= ~(IRQ_UART_MASK);
  2395. + *((volatile unsigned int *)IRQ_TLEVEL(IO_ADDRESS(SL2312_INTERRUPT_BASE))) = regs;
  2396. + *((volatile unsigned int *)IRQ_MASK(IO_ADDRESS(SL2312_INTERRUPT_BASE))) |= (unsigned int)(IRQ_UART_MASK);
  2397. +
  2398. + /*
  2399. + * Finally, enable interrupts. Use the TII interrupt to minimise
  2400. + * the number of interrupts generated. If higher performance is
  2401. + * needed, consider using the TI interrupt with a suitable FIFO
  2402. + * threshold
  2403. + */
  2404. + UART_PUT_IER(port, (UART_IER_DR|UART_IER_TE));
  2405. +
  2406. + return 0;
  2407. +}
  2408. +
  2409. +static void sl2312_shutdown(struct uart_port *port)
  2410. +{
  2411. +// printk("sl2312 shutdown : \n");
  2412. +
  2413. + /*
  2414. + * disable all interrupts, disable the port
  2415. + */
  2416. + UART_PUT_IER(port, 0x0);
  2417. +
  2418. + /* disable break condition and fifos */
  2419. +// UART_PUT_MCR(port, (UART_GET_MCR(port)&UART_MCR_MASK));
  2420. +
  2421. + /*
  2422. + * Free the interrupt
  2423. + */
  2424. + free_irq(port->irq, port);
  2425. +}
  2426. +
  2427. +static const char *sl2312_type(struct uart_port *port)
  2428. +{
  2429. + return port->type == PORT_SL2312 ? "SL2312" : NULL;
  2430. +}
  2431. +
  2432. +/*
  2433. + * Release the memory region(s) being used by 'port'
  2434. + */
  2435. +static void sl2312_release_port(struct uart_port *port)
  2436. +{
  2437. +// printk("sl2312 release port : \n");
  2438. +
  2439. + release_mem_region(port->mapbase, UART_PORT_SIZE);
  2440. +}
  2441. +
  2442. +/*
  2443. + * Request the memory region(s) being used by 'port'
  2444. + */
  2445. +static int sl2312_request_port(struct uart_port *port)
  2446. +{
  2447. + return request_mem_region(port->mapbase, UART_PORT_SIZE,
  2448. + "serial_sl2312") != NULL ? 0 : -EBUSY;
  2449. +}
  2450. +
  2451. +/*
  2452. + * Configure/autoconfigure the port.
  2453. + */
  2454. +static void sl2312_config_port(struct uart_port *port, int flags)
  2455. +{
  2456. +
  2457. + if (flags & UART_CONFIG_TYPE) {
  2458. + if (sl2312_request_port(port) == 0)
  2459. + port->type = PORT_SL2312;
  2460. + }
  2461. +}
  2462. +
  2463. +/*
  2464. + * verify the new serial_struct (for TIOCSSERIAL).
  2465. + */
  2466. +static int sl2312_verify_port(struct uart_port *port, struct serial_struct *ser)
  2467. +{
  2468. + int ret = 0;
  2469. +
  2470. + if (ser->type != PORT_UNKNOWN && ser->type != PORT_UART00)
  2471. + ret = -EINVAL;
  2472. + if (ser->irq < 0 || ser->irq >= NR_IRQS)
  2473. + ret = -EINVAL;
  2474. + if (ser->baud_base < 9600)
  2475. + ret = -EINVAL;
  2476. + return ret;
  2477. +}
  2478. +
  2479. +static struct uart_ops sl2312_pops = {
  2480. + .tx_empty =sl2312_tx_empty,
  2481. + .set_mctrl =sl2312_set_mctrl_null,
  2482. + .get_mctrl =sl2312_get_mctrl,
  2483. + .stop_tx =sl2312_stop_tx,
  2484. + .start_tx =sl2312_start_tx,
  2485. + .stop_rx =sl2312_stop_rx,
  2486. + .enable_ms =sl2312_enable_ms,
  2487. + .break_ctl =sl2312_break_ctl,
  2488. + .startup =sl2312_startup,
  2489. + .shutdown =sl2312_shutdown,
  2490. + .set_termios =sl2312_set_termios,
  2491. + .type =sl2312_type,
  2492. + .release_port =sl2312_release_port,
  2493. + .request_port =sl2312_request_port,
  2494. + .config_port =sl2312_config_port,
  2495. + .verify_port =sl2312_verify_port,
  2496. +};
  2497. +
  2498. +#ifdef CONFIG_ARCH_SL2312
  2499. +
  2500. +static struct uart_port sl2312_ports[UART_NR] = {
  2501. + {
  2502. + membase: (void *)IO_ADDRESS(SL2312_UART_BASE),
  2503. + mapbase: SL2312_UART_BASE,
  2504. + iotype: SERIAL_IO_MEM,
  2505. + irq: IRQ_UART,
  2506. + uartclk: UART_CLK,
  2507. + fifosize: 16,
  2508. + ops: &sl2312_pops,
  2509. + flags: ASYNC_BOOT_AUTOCONF,
  2510. + }
  2511. +};
  2512. +
  2513. +#endif
  2514. +
  2515. +#ifdef CONFIG_SERIAL_SL2312_CONSOLE
  2516. +#ifdef used_and_not_const_char_pointer
  2517. +static int sl2312_console_read(struct uart_port *port, char *s, u_int count)
  2518. +{
  2519. + unsigned int status;
  2520. + int c;
  2521. +#ifdef DEBUG
  2522. + printk("sl2312_console_read() called\n");
  2523. +#endif
  2524. +
  2525. + c = 0;
  2526. + while (c < count) {
  2527. + status = UART_GET_LSR(port);
  2528. + if (UART_RX_DATA(status)) {
  2529. + *s++ = UART_GET_CHAR(port);
  2530. + c++;
  2531. + } else {
  2532. + // nothing more to get, return
  2533. + return c;
  2534. + }
  2535. + }
  2536. + // return the count
  2537. + return c;
  2538. +}
  2539. +#endif
  2540. +static void sl2312_console_write(struct console *co, const char *s, unsigned count)
  2541. +{
  2542. +#ifdef CONFIG_ARCH_SL2312
  2543. + struct uart_port *port = sl2312_ports + co->index;
  2544. + unsigned int status, old_ies;
  2545. + int i;
  2546. +
  2547. + /*
  2548. + * First save the CR then disable the interrupts
  2549. + */
  2550. + old_ies = UART_GET_IER(port);
  2551. + UART_PUT_IER(port,0x0);
  2552. +
  2553. + /*
  2554. + * Now, do each character
  2555. + */
  2556. + for (i = 0; i < count; i++) {
  2557. + do {
  2558. + status = UART_GET_LSR(port);
  2559. + } while (!UART_TX_READY(status));
  2560. + UART_PUT_CHAR(port, s[i]);
  2561. + if (s[i] == '\n') {
  2562. + do {
  2563. + status = UART_GET_LSR(port);
  2564. + } while (!UART_TX_READY(status));
  2565. + UART_PUT_CHAR(port, '\r');
  2566. + }
  2567. + }
  2568. +
  2569. + /*
  2570. + * Finally, wait for transmitter to become empty
  2571. + * and restore the IES
  2572. + */
  2573. + do {
  2574. + status = UART_GET_LSR(port);
  2575. + } while (!(status&UART_LSR_TE));
  2576. + UART_PUT_IER(port, old_ies);
  2577. +#endif
  2578. +}
  2579. +
  2580. +#if 0
  2581. +static void sl2312_console_device(struct console *co,int *index)
  2582. +{
  2583. +
  2584. + struct uart_driver *p = co->data;
  2585. + *index = co->index;
  2586. + return p->tty_driver;
  2587. +
  2588. +}
  2589. +#endif
  2590. +
  2591. +static void /*__init*/ sl2312_console_get_options(struct uart_port *port, int *baud, int *parity, int *bits)
  2592. +{
  2593. +// printk("sl2312 console get options : \n");
  2594. +
  2595. + u_int uart_mc, quot;
  2596. + uart_mc= UART_GET_MCR(port);
  2597. +
  2598. + *parity = 'n';
  2599. + if (uart_mc & UART_LCR_PE) {
  2600. + if (uart_mc & UART_LCR_EVEN)
  2601. + *parity = 'e';
  2602. + else
  2603. + *parity = 'o';
  2604. + }
  2605. +
  2606. + switch (uart_mc & UART_LCR_MSK){
  2607. +
  2608. + case UART_LCR_LEN5:
  2609. + *bits = 5;
  2610. + break;
  2611. + case UART_LCR_LEN6:
  2612. + *bits = 6;
  2613. + break;
  2614. + case UART_LCR_LEN7:
  2615. + *bits = 7;
  2616. + break;
  2617. + case UART_LCR_LEN8:
  2618. + *bits = 8;
  2619. + break;
  2620. + }
  2621. + UART_PUT_MCR(port,UART_LCR_DLAB);
  2622. + quot = UART_GET_DIV_LO(port) | (UART_GET_DIV_HI(port) << 8);
  2623. + UART_PUT_MCR(port,uart_mc);
  2624. + *baud = port->uartclk / (16 *quot );
  2625. +}
  2626. +
  2627. +static int __init sl2312_console_setup(struct console *co, char *options)
  2628. +{
  2629. + struct uart_port *port;
  2630. + int baud = 19200;
  2631. + int bits = 8;
  2632. + int parity = 'n';
  2633. + int flow= 'n';
  2634. +
  2635. + printk("sl2312 console setup : \n");
  2636. +
  2637. +#ifdef CONFIG_ARCH_SL2312
  2638. + /*
  2639. + * Check whether an invalid uart number has been specified, and
  2640. + * if so, search for the first available port that does have
  2641. + * console support.
  2642. + */
  2643. + port = uart_get_console(sl2312_ports,SL2312_NO_PORTS,co);
  2644. +#else
  2645. + return -ENODEV;
  2646. +#endif
  2647. +
  2648. + if (options)
  2649. + uart_parse_options(options, &baud, &parity, &bits, &flow);
  2650. + else
  2651. + sl2312_console_get_options(port, &baud, &parity, &bits);
  2652. +
  2653. + return uart_set_options(port, co, baud, parity, bits, flow);
  2654. +}
  2655. +
  2656. +extern struct uart_driver sl2312_reg;
  2657. +static struct console sl2312_console = {
  2658. + .name = SERIAL_SL2312_NAME,
  2659. + .write = sl2312_console_write,
  2660. + .device = uart_console_device,
  2661. +// .device = sl2312_console_device,
  2662. + .setup = sl2312_console_setup,
  2663. +// .flags = (CON_PRINTBUFFER|CON_ENABLED),
  2664. + .flags = CON_PRINTBUFFER,
  2665. + .index = -1,
  2666. + .data = &sl2312_reg,
  2667. +};
  2668. +
  2669. +static int __init sl2312_console_init(void)
  2670. +{
  2671. + register_console(&sl2312_console);
  2672. + return 0;
  2673. +
  2674. +}
  2675. +
  2676. +console_initcall(sl2312_console_init);
  2677. +
  2678. +#define SL2312_CONSOLE &sl2312_console
  2679. +#else
  2680. +#define SL2312_CONSOLE NULL
  2681. +#endif
  2682. +
  2683. +// static
  2684. +struct uart_driver sl2312_reg = {
  2685. + .owner = NULL,
  2686. + .driver_name = SERIAL_SL2312_NAME,
  2687. + .dev_name = SERIAL_SL2312_NAME,
  2688. + .major = SERIAL_SL2312_MAJOR,
  2689. + .minor = SERIAL_SL2312_MINOR,
  2690. + .nr = UART_NR,
  2691. + .cons = SL2312_CONSOLE,
  2692. +};
  2693. +
  2694. +static int __init sl2312_init(void)
  2695. +{
  2696. + int result;
  2697. + //printk("serial_it8712: it871212_init \n");
  2698. +
  2699. + result = uart_register_driver(&sl2312_reg);
  2700. + if(result)
  2701. + return result;
  2702. + result = uart_add_one_port(&sl2312_reg, &sl2312_ports[0]);
  2703. +
  2704. + return result;
  2705. +}
  2706. +
  2707. +
  2708. +__initcall(sl2312_init);
  2709. --- a/include/linux/serial_core.h
  2710. +++ b/include/linux/serial_core.h
  2711. @@ -147,6 +147,10 @@
  2712. #define PORT_SB1250_DUART 77
  2713. +/* Storlink Soc */
  2714. +#define PORT_SL2312 72
  2715. +#define PORT_IT8712 73
  2716. +
  2717. #ifdef __KERNEL__
  2718. #include <linux/compiler.h>
  2719. --- a/drivers/char/Makefile
  2720. +++ b/drivers/char/Makefile
  2721. @@ -70,6 +70,16 @@
  2722. obj-$(CONFIG_APPLICOM) += applicom.o
  2723. obj-$(CONFIG_SONYPI) += sonypi.o
  2724. obj-$(CONFIG_RTC) += rtc.o
  2725. +
  2726. +### for Storlink SoC ###
  2727. +obj-$(CONFIG_SL2312_RTC) += sl2312_rtc.o
  2728. +obj-$(CONFIG_IT8712_GPIO) += it8712_gpio.o
  2729. +obj-$(CONFIG_GEMINI_GPIO) += gemini_gpio.o
  2730. +obj-$(CONFIG_GEMINI_PWC) += gemini_pwr.o
  2731. +obj-$(CONFIG_GEMINI_CIR) += gemini_cir.o
  2732. +obj-$(CONFIG_GEMINI_I2S) += gemini_i2s.o
  2733. +obj-$(CONFIG_SL2312_WATCHDOG) += sl2312_wd.o
  2734. +
  2735. obj-$(CONFIG_HPET) += hpet.o
  2736. obj-$(CONFIG_GEN_RTC) += genrtc.o
  2737. obj-$(CONFIG_EFI_RTC) += efirtc.o
  2738. --- a/drivers/serial/Kconfig
  2739. +++ b/drivers/serial/Kconfig
  2740. @@ -280,6 +280,56 @@
  2741. comment "Non-8250 serial port support"
  2742. +config SERIAL_SL2312
  2743. + bool "SL2312 serial port (sl2312) support"
  2744. + depends on ARCH_SL2312
  2745. + select SERIAL_CORE
  2746. + select SERIAL_SL2312_CONSOLE
  2747. + help
  2748. + Say Y here if you want to use the hard logic uart on SWORD. This
  2749. + driver also supports soft logic implentations of this uart core.
  2750. +
  2751. +config SERIAL_SL2312_CONSOLE
  2752. + bool "Support for console on SL2312 serial port"
  2753. + depends on SERIAL_SL2312
  2754. + select SERIAL_CORE_CONSOLE
  2755. + help
  2756. + Say Y here if you want to support a serial console on an SWORD
  2757. + hard logic uart or uart00 IP core.
  2758. +
  2759. + Even if you say Y here, the currently visible virtual console
  2760. + (/dev/tty0) will still be used as the system console by default, but
  2761. + you can alter that using a kernel command line option such as
  2762. + "console=ttyS0". (Try "man bootparam" or see the documentation of
  2763. + your boot loader (lilo or loadlin) about how to pass options to the
  2764. + kernel at boot time.)
  2765. +
  2766. +
  2767. +config SERIAL_IT8712
  2768. + bool "Sl2312 serial port(IT8712) support"
  2769. + depends on ARM && ARCH_SL2312 && SL2312_LPC
  2770. + select SERIAL_CORE
  2771. + select SERIAL_IT8712_CONSOLE
  2772. + help
  2773. + Say Y here if you want to use the hard logic uart on Excalibur. This
  2774. + driver also supports soft logic implentations of this uart core.
  2775. +
  2776. +config SERIAL_IT8712_CONSOLE
  2777. + bool "Support for console on Sword serial port(IT8712)"
  2778. + depends on SERIAL_IT8712
  2779. + select SERIAL_CORE_CONSOLE
  2780. + help
  2781. + Say Y here if you want to support a serial console on an Excalibur
  2782. + hard logic uart or uart00 IP core.
  2783. +
  2784. + Even if you say Y here, the currently visible virtual console
  2785. + (/dev/tty0) will still be used as the system console by default, but
  2786. + you can alter that using a kernel command line option such as
  2787. + "console=ttySI0". (Try "man bootparam" or see the documentation of
  2788. + your boot loader (lilo or loadlin) about how to pass options to the
  2789. + kernel at boot time.)
  2790. +
  2791. +
  2792. config SERIAL_AMBA_PL010
  2793. tristate "ARM AMBA PL010 serial port support"
  2794. depends on ARM_AMBA && (BROKEN || !ARCH_VERSATILE)
  2795. --- a/drivers/serial/Makefile
  2796. +++ b/drivers/serial/Makefile
  2797. @@ -62,5 +62,7 @@
  2798. obj-$(CONFIG_SERIAL_ATMEL) += atmel_serial.o
  2799. obj-$(CONFIG_SERIAL_UARTLITE) += uartlite.o
  2800. obj-$(CONFIG_SERIAL_NETX) += netx-serial.o
  2801. +obj-$(CONFIG_SERIAL_IT8712) += it8712.o
  2802. +obj-$(CONFIG_SERIAL_SL2312) += serial_sl2312.o
  2803. obj-$(CONFIG_SERIAL_OF_PLATFORM) += of_serial.o
  2804. obj-$(CONFIG_SERIAL_KS8695) += serial_ks8695.o