⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 omap24xx-uart.c

📁 omap3 linux 2.6 用nocc去除了冗余代码
💻 C
📖 第 1 页 / 共 3 页
字号:
/* * arch/arm/mach-omap2/omap24xx-uart.c * * Support functions for the OMAP24xx uart controller. * * Copyright (C) 2004-2006 Texas Instruments, Inc. * * This package is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */#include <linux/module.h>#include <linux/init.h>#include <linux/sched.h>#include <linux/errno.h>#include <linux/interrupt.h>#include <linux/slab.h>#include <linux/serial.h>#include <linux/dma-mapping.h>#include <asm/system.h>#include <asm/mach/irq.h>#include <asm/irq.h>#include <asm/hardware.h>#include <asm/dma.h>#include <asm/io.h>#include <asm/setup.h>#include <asm/arch/clock.h>#include <asm/arch/serial.h>#include <asm/arch/omap24xx-uart.h>#include <asm/arch/dmtimer.h>#define HSUART_LAT_CONST 1static struct constraint_handle *constr_handle;static struct constraint_id cnstr_id = {	.type = RES_LATENCY_CO,	.data = (void *)"latency",};/* Enable DEBUG_MODE for Non DMA operation *//* #define DEBUG_MODE	*//* ----- debug defines ----------------------------------------------- *//* Debug - four macros: * FN_IN, FN_OUT(value),D1,D2,D3 enabled based on log level *//* Log level standard used here: * Log level 3 all messages * Log level 2 all entry-exit points * Log level 1 major messages * Log level 0 no messages */#define OMAP24XX_UART_LOG_LEVEL 0/* detail - 0 - no detail *          1 - function name *          2 - function name, line number * prefix is added to every log message */#define OMAP24XX_UART_DETAIL    4/* kernel log level*///#define OMAP24XX_UART_K_LOG_LEVEL KERN_DEBUG#define OMAP24XX_UART_K_LOG_LEVEL#define DL1 "%s "#define DR1 ,__FUNCTION__#define DEBUG#define DL2 "[%d] "#define DR2 ,__LINE__#define D(format,...)\	printk(OMAP24XX_UART_K_LOG_LEVEL DL1 DL2 format "\n" DR1 DR2, ## __VA_ARGS__)#define D1(ARGS...)#define D2(ARGS...)#define D3(ARGS...)#define FN_IN#define FN_OUT(ARG)#define CONSOLE_NAME    "console="#define FREE		0#define USED		1#define MAX_BUF_SIZE	12000/* forward declartation */static void uart_rx_dma_callback(int lch, u16 ch_status, void *data);static void omap24xx_timeout_isr(unsigned long uart_no); /* structure for storing UART DMA info */struct omap24xx_uart {	u8 uart_no;	int rx_dma_channel;	int tx_dma_channel;	dma_addr_t rx_buf_dma_phys;	/* Physical adress of RX DMA buffer */	dma_addr_t tx_buf_dma_phys;	/* Physical adress of TX DMA buffer */	void *rx_buf_dma_virt;	/* Virtual adress of RX DMA buffer */	void *tx_buf_dma_virt;	/* Virtual adress of TX DMA buffer */	u8 tx_buf_state;	u8 rx_buf_state;	spinlock_t uart_lock;	int in_use;	/* timer to poll variable size release */	struct timer_list timer;	unsigned int timer_rate;	u32 timeout;	u32 timer_active;};static int get_uart_clocks(struct clk **uarti, struct clk **uartf, u8 uart_no);static int uart_irq[MAX_UARTS + 1] =    { INT_24XX_UART1_IRQ, INT_24XX_UART2_IRQ, INT_24XX_UART3_IRQ };static u8 uart_dma_rx[MAX_UARTS + 1] =    { OMAP24XX_DMA_UART1_RX, OMAP24XX_DMA_UART2_RX, OMAP24XX_DMA_UART3_RX };static u8 uart_dma_tx[MAX_UARTS + 1] =    { OMAP24XX_DMA_UART1_TX, OMAP24XX_DMA_UART2_TX, OMAP24XX_DMA_UART3_TX };static struct omap24xx_uart ui[MAX_UARTS + 1];static struct uart_callback uart_cb[MAX_UARTS + 1];static u8 uart_mode[MAX_UARTS + 1];/** * brief get_uart_clocks * used to enable/disable UART clocks. * param *uarti * param *uartf * param uart_no * * return */static int get_uart_clocks(struct clk **uarti, struct clk **uartf, u8 uart_no){	char *iname = NULL, *fname = NULL;	switch (uart_no) {	case UART1:		iname = "uart1_ick";		fname = "uart1_fck";		break;	case UART2:		iname = "uart2_ick";		fname = "uart2_fck";		break;	case UART3:		iname = "uart3_ick";		fname = "uart3_fck";		break;	default:		return -EPERM;	}	*uarti = clk_get(NULL, iname);	if (*uarti < 0) {		printk(KERN_ERR "Error : %s : No entry in the clock table \n",		       iname);		return -ENOENT;	}	*uartf = clk_get(NULL, fname);	if (*uartf < 0) {		printk(KERN_ERR "Error : %s : No entry in the clock table \n",		       fname);		return -ENOENT;	}	return 0;}/* * omap24xxx_timeout_isr * Looks at DMA destination register and calls receive * callback if the destination register is the same on * two timer isr. */static voidomap24xx_timeout_isr(unsigned long uart_no){	u32	w = 0;	int	lch;	int	curr_pos;	static int	prev_pos = 0;	struct	omap24xx_uart *hsuart = &ui[uart_no]; 	FN_IN;	lch = hsuart->rx_dma_channel;	curr_pos = omap_get_dma_dst_pos(lch);	if ((curr_pos == prev_pos) && (curr_pos != hsuart->rx_buf_dma_phys)) {		omap_stop_dma(lch);		w = OMAP_DMA_CSR_REG(lch);		uart_rx_dma_callback(lch, w, uart_cb[hsuart->uart_no].dev);		prev_pos = 0;	}	else {		prev_pos = curr_pos;		mod_timer(&hsuart->timer, jiffies +				msecs_to_jiffies(hsuart->timeout));	}	FN_OUT(0);}/** * brief omap24xx_uart_isr * Identifes the source of interrupt(UART1, UART2, UART3) * and reads respective IIR register data. * Sends IIR data to the user driver. * param irq * param dev_id * param regs */static irqreturn_tomap24xx_uart_isr(int irq, void *dev_id, struct pt_regs *regs){	u8 iir_data;	u32 uart_base;	int uart_no;	FN_IN;	switch (irq) {	case INT_24XX_UART1_IRQ:		uart_base = UART_MODULE_BASE(UART1);		uart_no = UART1;		break;	case INT_24XX_UART2_IRQ:		uart_base = UART_MODULE_BASE(UART2);		uart_no = UART2;		break;	case INT_24XX_UART3_IRQ:		uart_base = UART_MODULE_BASE(UART3);		uart_no = UART3;		break;	default:		printk("UART interrupt from unknown source\n");		return IRQ_NONE;	}	iir_data = readb(uart_base + REG_IIR);	uart_cb[uart_no].int_callback(iir_data, dev_id);	FN_OUT(0);	return IRQ_HANDLED;}/** * brief uart_rx_dma_callback * * param lch * param ch_status * param data */static void uart_rx_dma_callback(int lch, u16 ch_status, void *data){	int uart_no = 0;	FN_IN;	if (lch == ui[UART1].rx_dma_channel)		uart_no = UART1;	else if (lch == ui[UART2].rx_dma_channel)		uart_no = UART2;	else if (lch == ui[UART3].rx_dma_channel)		uart_no = UART3;	del_timer(&ui[uart_no].timer);	ui[uart_no].timer_active = 0;	uart_cb[uart_no].uart_rx_dma_callback(lch, ch_status, data);	ui[uart_no].rx_buf_state = FREE;	FN_OUT(0);}/** * brief uart_tx_dma_callback * * param lch * param ch_status * param data */static void uart_tx_dma_callback(int lch, u16 ch_status, void *data){	FN_IN;	if (lch == ui[UART1].tx_dma_channel) {		uart_cb[UART1].uart_tx_dma_callback(lch, ch_status, data);		ui[UART1].tx_buf_state = FREE;	} else if (lch == ui[UART2].tx_dma_channel) {		uart_cb[UART2].uart_tx_dma_callback(lch, ch_status, data);		ui[UART2].tx_buf_state = FREE;	} else if (lch == ui[UART3].tx_dma_channel) {		uart_cb[UART3].uart_tx_dma_callback(lch, ch_status, data);		ui[UART3].tx_buf_state = FREE;	}	FN_OUT(0);}/** * brief omap24xx_uart_get_parms * reads requested register data * param uart_no * param data * param reg * param lcr_mode * * return */int omap24xx_uart_get_parms(int uart_no, u8 * data, u8 reg, u8 lcr_mode){	u32 uart_base = UART_MODULE_BASE(uart_no);	u8 lcr_data;	FN_IN;	if (unlikely(uart_no < 0 || uart_no > MAX_UARTS)) {		D3(KERN_INFO "C Bad uart id %d \n", uart_no);		FN_OUT(EPERM);		return -EPERM;	}	lcr_data = readb(uart_base + REG_LCR);	outb(lcr_mode, uart_base + REG_LCR);	*data = readb(uart_base + reg);	/* Restore LCR data */	outb(lcr_data, uart_base + REG_LCR);	return 0;	FN_OUT(0);}EXPORT_SYMBOL(omap24xx_uart_get_parms);/** * brief omap24xx_uart_set_parms * writes values into requested UART register * param uart_no * param uart_set * * return */int omap24xx_uart_set_parms(int uart_no, struct uart_setparm *uart_set){	u32 uart_base = UART_MODULE_BASE(uart_no);	u8 lcr_data;	FN_IN;	if (unlikely(uart_no < 0 || uart_no > MAX_UARTS)) {		D3(KERN_INFO "C Bad uart id %d \n", uart_no);		FN_OUT(EPERM);		return -EPERM;	}	spin_lock(&(ui[uart_no].uart_lock));	lcr_data = readb(uart_base + REG_LCR);	outb(uart_set->lcr, uart_base + REG_LCR);	outb(uart_set->reg_data, uart_base + uart_set->reg);	/* Restore LCR data */	outb(lcr_data, uart_base + REG_LCR);	spin_unlock(&(ui[uart_no].uart_lock));	return 0;	FN_OUT(0);}EXPORT_SYMBOL(omap24xx_uart_set_parms);/** * brief omap24xx_uart_get_speed * reads DLL and DLH register values and * calculates UART speed. * param uart_no * param speed * * return */int omap24xx_uart_get_speed(int uart_no, int *speed){	u32 uart_base = UART_MODULE_BASE(uart_no);	u8 reg = 0;	u8 dll, dlh;	u16 divisor = 0;	FN_IN;	if (unlikely(uart_no < 0 || uart_no > MAX_UARTS)) {		D3(KERN_INFO "C Bad uart id %d \n", uart_no);		return -EPERM;	}	spin_lock(&(ui[uart_no].uart_lock));	reg = LCR_MODE2;	outb(reg, uart_base + REG_LCR);	dll = readb(uart_base + REG_DLL);	dlh = readb(uart_base + REG_DLH);	divisor = (dlh << 8) + dll;	if (!divisor) {		printk(KERN_WARNING "DLL and DLH read error !!!!!!!!!!!");		return -EPERM;	}	*speed = (BASE_CLK) / 16 * divisor;	spin_unlock(&(ui[uart_no].uart_lock));	return 0;	FN_OUT(0);}EXPORT_SYMBOL(omap24xx_uart_get_speed);/** * brief omap24xx_uart_set_speed * used to set the UART speed. * param uart_no * param speed * * return */int omap24xx_uart_set_speed(int uart_no, int speed){	u32 uart_base = UART_MODULE_BASE(uart_no);	u8 lcr_data, mdr1_data;	int divisor;	FN_IN;	if (unlikely(uart_no < 0 || uart_no > MAX_UARTS)) {		D3(KERN_INFO "C Bad uart id %d \n", uart_no);		return -EPERM;	}	spin_lock(&(ui[uart_no].uart_lock));	/* Disable UART before changing the clock speed - TRM - 18-52 */	mdr1_data = readb(uart_base + REG_MDR1);	outb(UART_DISABLE, uart_base + REG_MDR1);	/* Enable access to DLL and DLH registers */	lcr_data = readb(uart_base + REG_LCR);	outb(LCR_MODE2, uart_base + REG_LCR);	/* Only UART3 supports IrDA mode */	if ((uart_no == UART3) && (uart_mode[uart_no] == IRDA_MODE)) {		if (speed <= IR_SIR_SPEED) {			printk(KERN_INFO			       "SIR Mode : Changing UART speed to %d....",			       speed);			divisor = BASE_CLK / (16 * speed);			outb(divisor & 0xFF, uart_base + REG_DLL);			outb(divisor >> 8, uart_base + REG_DLH);			mdr1_data &= MODE_SELECT_MASK;			mdr1_data |= UART_SIR_MODE;			outb(mdr1_data, uart_base + REG_MDR1);			printk("Done\n");		} else if (speed <= IR_MIR_SPEED) {			printk(KERN_INFO			       "MIR Mode : Changing UART speed to %d....",			       speed);			divisor = BASE_CLK / (41 * speed);			outb(divisor & 0xFF, uart_base + REG_DLL);			outb(divisor >> 8, uart_base + REG_DLH);			mdr1_data &= MODE_SELECT_MASK;			mdr1_data |= UART_MIR_MODE;			outb(mdr1_data, uart_base + REG_MDR1);			printk("Done\n");		} else if (speed <= IR_FIR_SPEED) {

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -