Root/UART/src/8250_fpga.c

1/* Driver Para UART tipo 8250 Implementada en FPGA.
2 * Autor: amasprillav - Basado en 'Tiny TTY driver * * Copyright (C) 2002 Greg Kroah-Hartman' y algunas funciones de xuart7350 de la página
3 * http://www.embeddedarm.com, también de http://lkml.org/lkml/2008/8/5/295 y de http://en.wikibooks.org/wiki/Serial_Programming/termios
4 * Fecha: 6/11/2010
5 * Sistemas Embebidos - UNAL 2010-II
6 */
7
8#define DEBUG 1
9#include <linux/kernel.h>
10#include <linux/module.h>
11#include <linux/init.h>
12#include <asm/mach-jz4740/gpio.h>
13#include <linux/serial.h>
14#include <linux/serial_core.h>
15#include <linux/delay.h>
16
17#define FPGA_BASE 0xB5000000
18/*Registros de la UART*/
19#define RHR 0x00
20#define THR 0x00
21#define IER 0x01
22#define FCR 0x02
23#define ISR 0x02
24#define LCR 0x03
25#define MCR 0x04
26#define LSR 0x05
27#define MSR 0x06
28#define SCR 0x07
29/*Registros para la velocidad de transmisión*/
30#define DIVLSB 0x00 //latch de las cifras más significativas
31#define DIVMSB 0x01 //latch de las cifras menos significativas
32
33#define FPGA_IRQ_PIN JZ_GPIO_PORTC(15)
34#define CS2_PIN JZ_GPIO_PORTB(26)
35
36struct uart_port port;
37
38static const char driver_name[] = "ttyFPGA";
39static const char tty_dev_name[] = "ttyFPGA";
40
41static void fpga_putc(struct uart_port *port, unsigned char c){outb(c,FPGA_BASE);}
42
43static irqreturn_t vuart_rxint(int irq,void *dev_id){
44        tty_insert_flip_char(port.state->port.tty, inb(FPGA_BASE), TTY_NORMAL);
45        tty_flip_buffer_push(port.state->port.tty);
46        return IRQ_HANDLED;
47    return IRQ_HANDLED;
48}
49
50
51static unsigned int fpga_tx_empty(struct uart_port *port){return 1;}
52
53static void fpga_set_mctrl(struct uart_port *port, unsigned int mctrl){}
54
55static unsigned int fpga_get_mctrl(struct uart_port *port){return TIOCM_CAR | TIOCM_DSR | TIOCM_CTS;}
56
57static void fpga_stop_tx(struct uart_port *port){}
58
59static void fpga_start_tx(struct uart_port *port){
60    
61    while(1){
62        fpga_putc(port,port->state->xmit.buf[port->state->xmit.tail]);
63        printk("enviado: %c\n",port->state->xmit.buf[port->state->xmit.tail]);
64        //Ajustar la cola de la UART Al buffer
65        port->state->xmit.tail=(port->state->xmit.tail+1)&(UART_XMIT_SIZE-1);
66        port->icount.tx++;
67        if(uart_circ_empty(&port->state->xmit))break;
68    }
69    
70}
71static void fpga_stop_rx(struct uart_port *port){}
72
73static void fpga_enable_ms(struct uart_port *port){}
74
75static void fpga_break_ctl(struct uart_port *port, int break_state){}
76
77static int fpga_startup(struct uart_port *port){
78    int res;
79    printk("fpga_startup\n");
80      res = request_irq(port->irq, vuart_rxint,IRQF_TRIGGER_FALLING, "ttyFPGA",(void*)port);//IRQF_DISABLED |
81    if(res){
82        printk("No se pudo registrar el IRQ!\n");
83        return res;
84    }
85    //Envío los registros de inicialización para la velocidad de transmisión y recepción, también el formato de datos...
86    outb(0x80,FPGA_BASE+LCR);
87    //acá lo coloco a 9600 baudios porque es la velocidad de transmisión (esto es temporal).
88    outb(0x00,FPGA_BASE+DIVMSB);
89    outb(0x0c,FPGA_BASE+DIVLSB);
90    //registro para habilitar las interrupciones...
91    outb(0x03,FPGA_BASE+LCR);
92    outb(0xCF,FPGA_BASE+FCR);
93    outb(0x0B,FPGA_BASE+MCR);
94    outb(0x01,FPGA_BASE+IER);
95    return 0;
96}
97static void fpga_shutdown(struct uart_port *port){free_irq(port->irq, (void*)port);}
98
99static void fpga_set_termios(struct uart_port *port,struct ktermios *termios,struct ktermios *old){}
100
101static const char *fpga_type(struct uart_port *port){return "ttyfpga";}
102
103static int fpga_request_port(struct uart_port *port){return 0;}
104
105static void fpga_config_port(struct uart_port *port, int flags){
106    if (flags & UART_CONFIG_TYPE)
107               port->type = PORT_16550A;
108}
109static void fpga_release_port(struct uart_port *port){}
110
111static int fpga_verify_port(struct uart_port *port, struct serial_struct *ser){return 0;}
112
113static struct uart_ops fpga_uart_ops = {
114    .tx_empty = fpga_tx_empty,
115    .set_mctrl = fpga_set_mctrl,
116    .get_mctrl = fpga_get_mctrl,
117    .stop_tx = fpga_stop_tx,
118    .start_tx = fpga_start_tx,
119    .stop_rx = fpga_stop_rx,
120    .enable_ms = fpga_enable_ms,
121    .break_ctl = fpga_break_ctl,
122    .startup = fpga_startup,
123    .shutdown = fpga_shutdown,
124    .set_termios = fpga_set_termios,
125    .type = fpga_type,
126    .release_port = fpga_release_port,
127    .request_port = fpga_request_port,
128    .config_port = fpga_config_port,
129    .verify_port = fpga_verify_port,
130};
131
132static struct uart_driver fpga_driver = {
133    .owner = THIS_MODULE,
134    .driver_name = driver_name,
135    .dev_name = tty_dev_name,
136    .major = 240,
137    .minor = 0,
138    .nr = 2,
139};
140static int __init fpga_init (void){
141    int ret;
142    unsigned int irq;
143
144        // Set GPIOB26 as part of External Memory Controller
145        jz_gpio_set_function(CS2_PIN, JZ_GPIO_FUNC1);
146
147    //registrar el driver
148    ret = uart_register_driver(&fpga_driver);
149    if (ret) {
150        pr_err("%s: No se pudo registrar la UART!\n", driver_name);
151        return ret;
152    }
153    //asignar el pin de IRQ al que está conectado a la FPGA (IRQ_F en el esquemático)
154     irq = gpio_to_irq(FPGA_IRQ_PIN);
155    //insertar los valores del puerto
156    port.membase=(u8*)FPGA_BASE;
157    port.line = 0;
158    port.ops = &fpga_uart_ops;
159    port.flags = ASYNC_BOOT_AUTOCONF;
160    port.type = PORT_16550A;
161    port.irq = irq;
162    ret = uart_add_one_port(&fpga_driver, &port);
163    if (ret) {
164        pr_err("%s: No se pudo agregar el puerto ttyFPGA0!\n", driver_name);
165        uart_remove_one_port(&fpga_driver, &port);
166        uart_unregister_driver(&fpga_driver);
167        return ret;
168    }
169
170    printk ("%s: Modulo cargado...\n", driver_name);
171    return 0;
172}
173
174static void __exit fpga_exit (void){
175    uart_remove_one_port(&fpga_driver, &port);
176    uart_unregister_driver(&fpga_driver);
177    printk ("%s: Modulo descargado...\n", driver_name);
178}
179
180MODULE_AUTHOR("amasprillav <amasprillav@unal.edu.co>");
181MODULE_DESCRIPTION("Driver para UART tipo 8250 implementada en Verilog");
182MODULE_LICENSE("GPL");
183
184module_init(fpga_init);
185module_exit(fpga_exit);
186

Archive Download this file

Branches:
master



interactive