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

📄 sync_serial.c

📁 linux内核源码
💻 C
📖 第 1 页 / 共 3 页
字号:
				} else if (crisv32_request_dma(SYNC_SER1_RX_DMA_NBR,							    "synchronous serial 3 dma rec",							    DMA_VERBOSE_ON_ERROR,							    0,							    dma_sser1)) {					crisv32_free_dma(SYNC_SER1_TX_DMA_NBR);					free_irq(DMA6_INTR_VECT, &ports[1]);					free_irq(DMA7_INTR_VECT, &ports[1]);					printk(KERN_CRIT "Can't allocate sync serial port 3 RX DMA channel");					return -EBUSY;				}#endif			}                        /* Enable DMAs */			REG_WR(dma, port->regi_dmain, rw_cfg, cfg);			REG_WR(dma, port->regi_dmaout, rw_cfg, cfg);			/* Enable DMA IRQs */			REG_WR(dma, port->regi_dmain, rw_intr_mask, intr_mask);			REG_WR(dma, port->regi_dmaout, rw_intr_mask, intr_mask);			/* Set up wordsize = 2 for DMAs. */			DMA_WR_CMD (port->regi_dmain, regk_dma_set_w_size1);			DMA_WR_CMD (port->regi_dmaout, regk_dma_set_w_size1);			start_dma_in(port);			port->init_irqs = 0;		} else { /* !port->use_dma */#ifdef SYNC_SER_MANUAL			if (port == &ports[0]) {				if (request_irq(SSER0_INTR_VECT,						manual_interrupt,						0,						"synchronous serial manual irq",						&ports[0])) {					printk("Can't allocate sync serial manual irq");					return -EBUSY;				}			} else if (port == &ports[1]) {				if (request_irq(SSER1_INTR_VECT,						manual_interrupt,						0,						"synchronous serial manual irq",						&ports[1])) {					printk(KERN_CRIT "Can't allocate sync serial manual irq");					return -EBUSY;				}			}			port->init_irqs = 0;#else			panic("sync_serial: Manual mode not supported.\n");#endif /* SYNC_SER_MANUAL */		}	} /* port->init_irqs */	port->busy++;	return 0;}static int sync_serial_release(struct inode *inode, struct file *file){	int dev = iminor(inode);	sync_port* port;	if (dev < 0 || dev >= NUMBER_OF_PORTS || !ports[dev].enabled)	{		DEBUG(printk("Invalid minor %d\n", dev));		return -ENODEV;	}	port = &ports[dev];	if (port->busy)		port->busy--;	if (!port->busy)          /* XXX */ ;	return 0;}static unsigned int sync_serial_poll(struct file *file, poll_table *wait){	int dev = iminor(file->f_path.dentry->d_inode);	unsigned int mask = 0;	sync_port* port;	DEBUGPOLL( static unsigned int prev_mask = 0; );	port = &ports[dev];	poll_wait(file, &port->out_wait_q, wait);	poll_wait(file, &port->in_wait_q, wait);	/* Some room to write */	if (port->out_count < OUT_BUFFER_SIZE)		mask |=  POLLOUT | POLLWRNORM;	/* At least an inbufchunk of data */	if (sync_data_avail(port) >= port->inbufchunk)		mask |= POLLIN | POLLRDNORM;	DEBUGPOLL(if (mask != prev_mask)	      printk("sync_serial_poll: mask 0x%08X %s %s\n", mask,		     mask&POLLOUT?"POLLOUT":"", mask&POLLIN?"POLLIN":"");	      prev_mask = mask;	      );	return mask;}static int sync_serial_ioctl(struct inode *inode, struct file *file,		  unsigned int cmd, unsigned long arg){	int return_val = 0;	int dev = iminor(file->f_path.dentry->d_inode);	sync_port* port;	reg_sser_rw_tr_cfg tr_cfg;	reg_sser_rw_rec_cfg rec_cfg;	reg_sser_rw_frm_cfg frm_cfg;	reg_sser_rw_cfg gen_cfg;	reg_sser_rw_intr_mask intr_mask;	if (dev < 0 || dev >= NUMBER_OF_PORTS || !ports[dev].enabled)	{		DEBUG(printk("Invalid minor %d\n", dev));		return -1;	}        port = &ports[dev];	spin_lock_irq(&port->lock);	tr_cfg = REG_RD(sser, port->regi_sser, rw_tr_cfg);	rec_cfg = REG_RD(sser, port->regi_sser, rw_rec_cfg);	frm_cfg = REG_RD(sser, port->regi_sser, rw_frm_cfg);	gen_cfg = REG_RD(sser, port->regi_sser, rw_cfg);	intr_mask = REG_RD(sser, port->regi_sser, rw_intr_mask);	switch(cmd)	{	case SSP_SPEED:		if (GET_SPEED(arg) == CODEC)		{			gen_cfg.base_freq = regk_sser_f32;			/* FREQ = 0 => 4 MHz => clk_div = 7*/			gen_cfg.clk_div = 6 + (1 << GET_FREQ(arg));		}		else		{			gen_cfg.base_freq = regk_sser_f29_493;			switch (GET_SPEED(arg))			{				case SSP150:					gen_cfg.clk_div = 29493000 / (150 * 8) - 1;					break;				case SSP300:					gen_cfg.clk_div = 29493000 / (300 * 8) - 1;					break;				case SSP600:					gen_cfg.clk_div = 29493000 / (600 * 8) - 1;					break;				case SSP1200:					gen_cfg.clk_div = 29493000 / (1200 * 8) - 1;					break;				case SSP2400:					gen_cfg.clk_div = 29493000 / (2400 * 8) - 1;					break;				case SSP4800:					gen_cfg.clk_div = 29493000 / (4800 * 8) - 1;					break;				case SSP9600:					gen_cfg.clk_div = 29493000 / (9600 * 8) - 1;					break;				case SSP19200:					gen_cfg.clk_div = 29493000 / (19200 * 8) - 1;					break;				case SSP28800:					gen_cfg.clk_div = 29493000 / (28800 * 8) - 1;					break;				case SSP57600:					gen_cfg.clk_div = 29493000 / (57600 * 8) - 1;					break;				case SSP115200:					gen_cfg.clk_div = 29493000 / (115200 * 8) - 1;					break;				case SSP230400:					gen_cfg.clk_div = 29493000 / (230400 * 8) - 1;					break;				case SSP460800:					gen_cfg.clk_div = 29493000 / (460800 * 8) - 1;					break;				case SSP921600:					gen_cfg.clk_div = 29493000 / (921600 * 8) - 1;					break;				case SSP3125000:					gen_cfg.base_freq = regk_sser_f100;					gen_cfg.clk_div = 100000000 / (3125000 * 8) - 1;					break;			}		}		frm_cfg.wordrate = GET_WORD_RATE(arg);		break;	case SSP_MODE:		switch(arg)		{			case MASTER_OUTPUT:				port->output = 1;				port->input = 0;				gen_cfg.clk_dir = regk_sser_out;				break;			case SLAVE_OUTPUT:				port->output = 1;				port->input = 0;				gen_cfg.clk_dir = regk_sser_in;				break;			case MASTER_INPUT:				port->output = 0;				port->input = 1;				gen_cfg.clk_dir = regk_sser_out;				break;			case SLAVE_INPUT:				port->output = 0;				port->input = 1;				gen_cfg.clk_dir = regk_sser_in;				break;			case MASTER_BIDIR:				port->output = 1;				port->input = 1;				gen_cfg.clk_dir = regk_sser_out;				break;			case SLAVE_BIDIR:				port->output = 1;				port->input = 1;				gen_cfg.clk_dir = regk_sser_in;				break;			default:				spin_unlock_irq(&port->lock);				return -EINVAL;		}		if (!port->use_dma || (arg == MASTER_OUTPUT || arg == SLAVE_OUTPUT))			intr_mask.rdav = regk_sser_yes;		break;	case SSP_FRAME_SYNC:		if (arg & NORMAL_SYNC)			frm_cfg.tr_delay = 1;		else if (arg & EARLY_SYNC)			frm_cfg.tr_delay = 0;		tr_cfg.bulk_wspace = frm_cfg.tr_delay;		frm_cfg.early_wend = regk_sser_yes;		if (arg & BIT_SYNC)			frm_cfg.type = regk_sser_edge;		else if (arg & WORD_SYNC)			frm_cfg.type = regk_sser_level;		else if (arg & EXTENDED_SYNC)			frm_cfg.early_wend = regk_sser_no;		if (arg & SYNC_ON)			frm_cfg.frame_pin_use = regk_sser_frm;		else if (arg & SYNC_OFF)			frm_cfg.frame_pin_use = regk_sser_gio0;		if (arg & WORD_SIZE_8)			rec_cfg.sample_size = tr_cfg.sample_size = 7;		else if (arg & WORD_SIZE_12)			rec_cfg.sample_size = tr_cfg.sample_size = 11;		else if (arg & WORD_SIZE_16)			rec_cfg.sample_size = tr_cfg.sample_size = 15;		else if (arg & WORD_SIZE_24)			rec_cfg.sample_size = tr_cfg.sample_size = 23;		else if (arg & WORD_SIZE_32)			rec_cfg.sample_size = tr_cfg.sample_size = 31;		if (arg & BIT_ORDER_MSB)			rec_cfg.sh_dir = tr_cfg.sh_dir = regk_sser_msbfirst;		else if (arg & BIT_ORDER_LSB)			rec_cfg.sh_dir = tr_cfg.sh_dir = regk_sser_lsbfirst;		if (arg & FLOW_CONTROL_ENABLE)			rec_cfg.fifo_thr = regk_sser_thr16;		else if (arg & FLOW_CONTROL_DISABLE)			rec_cfg.fifo_thr = regk_sser_inf;		if (arg & CLOCK_NOT_GATED)			gen_cfg.gate_clk = regk_sser_no;		else if (arg & CLOCK_GATED)			gen_cfg.gate_clk = regk_sser_yes;		break;	case SSP_IPOLARITY:		/* NOTE!! negedge is considered NORMAL */		if (arg & CLOCK_NORMAL)			rec_cfg.clk_pol = regk_sser_neg;		else if (arg & CLOCK_INVERT)			rec_cfg.clk_pol = regk_sser_pos;		if (arg & FRAME_NORMAL)			frm_cfg.level = regk_sser_pos_hi;		else if (arg & FRAME_INVERT)			frm_cfg.level = regk_sser_neg_lo;		if (arg & STATUS_NORMAL)			gen_cfg.hold_pol = regk_sser_pos;		else if (arg & STATUS_INVERT)			gen_cfg.hold_pol = regk_sser_neg;		break;	case SSP_OPOLARITY:		if (arg & CLOCK_NORMAL)			gen_cfg.out_clk_pol = regk_sser_neg;		else if (arg & CLOCK_INVERT)			gen_cfg.out_clk_pol = regk_sser_pos;		if (arg & FRAME_NORMAL)			frm_cfg.level = regk_sser_pos_hi;		else if (arg & FRAME_INVERT)			frm_cfg.level = regk_sser_neg_lo;		if (arg & STATUS_NORMAL)			gen_cfg.hold_pol = regk_sser_pos;		else if (arg & STATUS_INVERT)			gen_cfg.hold_pol = regk_sser_neg;		break;	case SSP_SPI:		rec_cfg.fifo_thr = regk_sser_inf;		rec_cfg.sh_dir = tr_cfg.sh_dir = regk_sser_msbfirst;		rec_cfg.sample_size = tr_cfg.sample_size = 7;		frm_cfg.frame_pin_use = regk_sser_frm;		frm_cfg.type = regk_sser_level;		frm_cfg.tr_delay = 1;		frm_cfg.level = regk_sser_neg_lo;		if (arg & SPI_SLAVE)		{			rec_cfg.clk_pol = regk_sser_neg;			gen_cfg.clk_dir = regk_sser_in;			port->input = 1;			port->output = 0;		}		else		{			gen_cfg.out_clk_pol = regk_sser_pos;			port->input = 0;			port->output = 1;			gen_cfg.clk_dir = regk_sser_out;		}		break;	case SSP_INBUFCHUNK:		break;	default:		return_val = -1;	}	if (port->started)	{		tr_cfg.tr_en = port->output;		rec_cfg.rec_en = port->input;	}	REG_WR(sser, port->regi_sser, rw_tr_cfg, tr_cfg);	REG_WR(sser, port->regi_sser, rw_rec_cfg, rec_cfg);	REG_WR(sser, port->regi_sser, rw_frm_cfg, frm_cfg);	REG_WR(sser, port->regi_sser, rw_intr_mask, intr_mask);	REG_WR(sser, port->regi_sser, rw_cfg, gen_cfg);	spin_unlock_irq(&port->lock);	return return_val;}static ssize_t sync_serial_write(struct file * file, const char * buf,                                 size_t count, loff_t *ppos){	int dev = iminor(file->f_path.dentry->d_inode);	DECLARE_WAITQUEUE(wait, current);	sync_port *port;	unsigned long c, c1;	unsigned long free_outp;	unsigned long outp;	unsigned long out_buffer;	unsigned long flags;	if (dev < 0 || dev >= NUMBER_OF_PORTS || !ports[dev].enabled)	{		DEBUG(printk("Invalid minor %d\n", dev));		return -ENODEV;	}	port = &ports[dev];	DEBUGWRITE(printk("W d%d c %lu (%d/%d)\n", port->port_nbr, count, port->out_count, OUT_BUFFER_SIZE));	/* Space to end of buffer */	/*	 * out_buffer <c1>012345<-   c    ->OUT_BUFFER_SIZE	 *            outp^    +out_count	                        ^free_outp	 * out_buffer 45<-     c      ->0123OUT_BUFFER_SIZE	 *             +out_count   outp^	 *              free_outp	 *	 */	/* Read variables that may be updated by interrupts */	spin_lock_irqsave(&port->lock, flags);	count = count > OUT_BUFFER_SIZE - port->out_count ? OUT_BUFFER_SIZE  - port->out_count : count;	outp = (unsigned long)port->outp;	free_outp = outp + port->out_count;	spin_unlock_irqrestore(&port->lock, flags);	out_buffer = (unsigned long)port->out_buffer;	/* Find out where and how much to write */	if (free_outp >= out_buffer + OUT_BUFFER_SIZE)		free_outp -= OUT_BUFFER_SIZE;	if (free_outp >= outp)		c = out_buffer + OUT_BUFFER_SIZE - free_outp;	else		c = outp - free_outp;	if (c > count)		c = count;//	DEBUGWRITE(printk("w op %08lX fop %08lX c %lu\n", outp, free_outp, c));	if (copy_from_user((void*)free_outp, buf, c))		return -EFAULT;	if (c != count) {		buf += c;		c1 = count - c;		DEBUGWRITE(printk("w2 fi %lu c %lu c1 %lu\n", free_outp-out_buffer, c, c1));		if (copy_from_user((void*)out_buffer, buf, c1))			return -EFAULT;	}	spin_lock_irqsave(&port->lock, flags);	port->out_count += count;	spin_unlock_irqrestore(&port->lock, flags);	/* Make sure transmitter/receiver is running */	if (!port->started)	{		reg_sser_rw_cfg cfg = REG_RD(sser, port->regi_sser, rw_cfg);

⌨️ 快捷键说明

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