예제 #1
0
static int sync_serial_open(struct inode *inode, struct file *file)
{
	int dev = iminor(inode);
	int ret = -EBUSY;
	sync_port *port;
	reg_dma_rw_cfg cfg = {.en = regk_dma_yes};
	reg_dma_rw_intr_mask intr_mask = {.data = regk_dma_yes};

	lock_kernel();
	DEBUG(printk(KERN_DEBUG "Open sync serial port %d\n", dev));

	if (dev < 0 || dev >= NBR_PORTS || !ports[dev].enabled)
	{
		DEBUG(printk(KERN_DEBUG "Invalid minor %d\n", dev));
		ret = -ENODEV;
		goto out;
	}
	port = &ports[dev];
	/* Allow open this device twice (assuming one reader and one writer) */
	if (port->busy == 2)
	{
		DEBUG(printk(KERN_DEBUG "Device is busy.. \n"));
		goto out;
	}


	if (port->init_irqs) {
		if (port->use_dma) {
			if (port == &ports[0]) {
#ifdef SYNC_SER_DMA
				if (request_irq(DMA_OUT_INTR_VECT,
						tr_interrupt,
						0,
						"synchronous serial 0 dma tr",
						&ports[0])) {
					printk(KERN_CRIT "Can't allocate sync serial port 0 IRQ");
					goto out;
				} else if (request_irq(DMA_IN_INTR_VECT,
						rx_interrupt,
						0,
						"synchronous serial 1 dma rx",
						&ports[0])) {
					free_irq(DMA_OUT_INTR_VECT, &port[0]);
					printk(KERN_CRIT "Can't allocate sync serial port 0 IRQ");
					goto out;
				} else if (crisv32_request_dma(OUT_DMA_NBR,
						"synchronous serial 0 dma tr",
						DMA_VERBOSE_ON_ERROR,
						0,
						REQ_DMA_SYNCSER)) {
					free_irq(DMA_OUT_INTR_VECT, &port[0]);
					free_irq(DMA_IN_INTR_VECT, &port[0]);
					printk(KERN_CRIT "Can't allocate sync serial port 0 TX DMA channel");
					goto out;
				} else if (crisv32_request_dma(IN_DMA_NBR,
						"synchronous serial 0 dma rec",
						DMA_VERBOSE_ON_ERROR,
						0,
						REQ_DMA_SYNCSER)) {
					crisv32_free_dma(OUT_DMA_NBR);
					free_irq(DMA_OUT_INTR_VECT, &port[0]);
					free_irq(DMA_IN_INTR_VECT, &port[0]);
					printk(KERN_CRIT "Can't allocate sync serial port 1 RX DMA channel");
					goto out;
				}
#endif
			}
#ifdef CONFIG_ETRAXFS
			else if (port == &ports[1]) {
#ifdef SYNC_SER_DMA
				if (request_irq(DMA6_INTR_VECT,
						tr_interrupt,
						0,
						"synchronous serial 1 dma tr",
						&ports[1])) {
					printk(KERN_CRIT "Can't allocate sync serial port 1 IRQ");
					goto out;
				} else if (request_irq(DMA7_INTR_VECT,
						       rx_interrupt,
						       0,
						       "synchronous serial 1 dma rx",
						       &ports[1])) {
					free_irq(DMA6_INTR_VECT, &ports[1]);
					printk(KERN_CRIT "Can't allocate sync serial port 3 IRQ");
					goto out;
				} else if (crisv32_request_dma(
						SYNC_SER1_TX_DMA_NBR,
						"synchronous serial 1 dma tr",
						DMA_VERBOSE_ON_ERROR,
						0,
						dma_sser1)) {
					free_irq(DMA6_INTR_VECT, &ports[1]);
					free_irq(DMA7_INTR_VECT, &ports[1]);
					printk(KERN_CRIT "Can't allocate sync serial port 3 TX DMA channel");
					goto out;
				} 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");
					goto out;
				}
#endif
			}
#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 = 1 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(SYNCSER_INTR_VECT,
						manual_interrupt,
						0,
						"synchronous serial manual irq",
						&ports[0])) {
					printk("Can't allocate sync serial manual irq");
					goto out;
				}
			}
#ifdef CONFIG_ETRAXFS
			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");
					goto out;
				}
			}
#endif
			port->init_irqs = 0;
#else
			panic("sync_serial: Manual mode not supported.\n");
#endif /* SYNC_SER_MANUAL */
		}

	} /* port->init_irqs */

	port->busy++;
	ret = 0;
out:
	unlock_kernel();
	return ret;
}
예제 #2
0
static int sync_serial_open(struct inode *inode, struct file *file)
{
	int ret = 0;
	int dev = iminor(inode);
	struct sync_port *port;
#ifdef SYNC_SER_DMA
	reg_dma_rw_cfg cfg = { .en = regk_dma_yes };
	reg_dma_rw_intr_mask intr_mask = { .data = regk_dma_yes };
#endif

	DEBUG(pr_debug("Open sync serial port %d\n", dev));

	if (dev < 0 || dev >= NBR_PORTS || !ports[dev].enabled) {
		DEBUG(pr_info("Invalid minor %d\n", dev));
		return -ENODEV;
	}
	port = &ports[dev];
	/* Allow open this device twice (assuming one reader and one writer) */
	if (port->busy == 2) {
		DEBUG(pr_info("syncser%d is busy\n", dev));
		return -EBUSY;
	}

	mutex_lock(&sync_serial_mutex);

	/* Clear any stale date left in the flip buffer */
	port->readp = port->writep = port->flip;
	port->in_buffer_len = 0;
	port->read_ts_idx = 0;
	port->write_ts_idx = 0;

	if (port->init_irqs != no_irq_setup) {
		/* Init only on first call. */
		port->busy++;
		mutex_unlock(&sync_serial_mutex);
		return 0;
	}
	if (port->use_dma) {
#ifdef SYNC_SER_DMA
		const char *tmp;
		DEBUG(pr_info("Using DMA for syncser%d\n", dev));

		tmp = dev == 0 ? "syncser0 tx" : "syncser1 tx";
		if (request_irq(port->dma_out_intr_vect, tr_interrupt, 0,
				tmp, port)) {
			pr_err("Can't alloc syncser%d TX IRQ", dev);
			ret = -EBUSY;
			goto unlock_and_exit;
		}
		if (artpec_request_dma(port->dma_out_nbr, tmp,
				DMA_VERBOSE_ON_ERROR, 0, port->req_dma)) {
			free_irq(port->dma_out_intr_vect, port);
			pr_err("Can't alloc syncser%d TX DMA", dev);
			ret = -EBUSY;
			goto unlock_and_exit;
		}
		tmp = dev == 0 ? "syncser0 rx" : "syncser1 rx";
		if (request_irq(port->dma_in_intr_vect, rx_interrupt, 0,
				tmp, port)) {
			artpec_free_dma(port->dma_out_nbr);
			free_irq(port->dma_out_intr_vect, port);
			pr_err("Can't alloc syncser%d RX IRQ", dev);
			ret = -EBUSY;
			goto unlock_and_exit;
		}
		if (artpec_request_dma(port->dma_in_nbr, tmp,
				DMA_VERBOSE_ON_ERROR, 0, port->req_dma)) {
			artpec_free_dma(port->dma_out_nbr);
			free_irq(port->dma_out_intr_vect, port);
			free_irq(port->dma_in_intr_vect, port);
			pr_err("Can't alloc syncser%d RX DMA", dev);
			ret = -EBUSY;
			goto unlock_and_exit;
		}
		/* 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 = 1 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 = dma_irq_setup;
#endif
	} else { /* !port->use_dma */
#ifdef SYNC_SER_MANUAL
		const char *tmp = dev == 0 ? "syncser0 manual irq" :
					     "syncser1 manual irq";
		if (request_irq(port->syncser_intr_vect, manual_interrupt,
				0, tmp, port)) {
			pr_err("Can't alloc syncser%d manual irq",
				dev);
			ret = -EBUSY;
			goto unlock_and_exit;
		}
		port->init_irqs = manual_irq_setup;
#else
		panic("sync_serial: Manual mode not supported\n");
#endif /* SYNC_SER_MANUAL */
	}
	port->busy++;
	ret = 0;

unlock_and_exit:
	mutex_unlock(&sync_serial_mutex);
	return ret;
}