spin_lock_irqsave(&qtty->lock, irq_flags);
gf_write_ptr((void *)address, base + GOLDFISH_TTY_REG_DATA_PTR,
base + GOLDFISH_TTY_REG_DATA_PTR_HIGH);
gf_iowrite32(count, base + GOLDFISH_TTY_REG_DATA_LEN);
if (is_write)
gf_iowrite32(GOLDFISH_TTY_CMD_WRITE_BUFFER,
base + GOLDFISH_TTY_REG_CMD); else
gf_iowrite32(GOLDFISH_TTY_CMD_READ_BUFFER,
base + GOLDFISH_TTY_REG_CMD);
dma_dir = (is_write ? DMA_TO_DEVICE : DMA_FROM_DEVICE); if (qtty->version > 0) { /* * Goldfish TTY for Ranchu platform uses * physical addresses and DMA for read/write operations
*/ unsignedlong addr_end = addr + count;
while (addr < addr_end) { unsignedlong pg_end = (addr & PAGE_MASK) + PAGE_SIZE; unsignedlong next =
pg_end < addr_end ? pg_end : addr_end; unsignedlong avail = next - addr;
/* * Map the buffer's virtual address to the DMA address * so the buffer can be accessed by the device.
*/
dma_handle = dma_map_single(qtty->dev, (void *)addr,
avail, dma_dir);
/* * Unmap the previously mapped region after * the completion of the read/write operation.
*/
dma_unmap_single(qtty->dev, dma_handle, avail, dma_dir);
addr += avail;
}
} else { /* * Old style Goldfish TTY used on the Goldfish platform * uses virtual addresses.
*/
do_rw_io(qtty, addr, count, is_write);
}
}
staticint goldfish_tty_probe(struct platform_device *pdev)
{ struct goldfish_tty *qtty; int ret = -ENODEV; struct resource *r; struct device *ttydev; void __iomem *base; int irq; unsignedint line;
r = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!r) {
pr_err("goldfish_tty: No MEM resource available!\n"); return -ENOMEM;
}
base = ioremap(r->start, 0x1000); if (!base) {
pr_err("goldfish_tty: Unable to ioremap base!\n"); return -ENOMEM;
}
irq = platform_get_irq(pdev, 0); if (irq < 0) {
ret = irq; goto err_unmap;
}
mutex_lock(&goldfish_tty_lock);
if (pdev->id == PLATFORM_DEVID_NONE)
line = goldfish_tty_current_line_count; else
line = pdev->id;
if (line >= goldfish_tty_line_count) {
pr_err("goldfish_tty: Reached maximum tty number of %d.\n",
goldfish_tty_current_line_count);
ret = -ENOMEM; goto err_unlock;
}
if (goldfish_tty_current_line_count == 0) {
ret = goldfish_tty_create_driver(); if (ret) goto err_unlock;
}
goldfish_tty_current_line_count++;
/* * Goldfish TTY device used by the Goldfish emulator * should identify itself with 0, forcing the driver * to use virtual addresses. Goldfish TTY device * on Ranchu emulator (qemu2) returns 1 here and * driver will use physical addresses.
*/
qtty->version = gf_ioread32(base + GOLDFISH_TTY_REG_VERSION);
/* * Goldfish TTY device on Ranchu emulator (qemu2) * will use DMA for read/write IO operations.
*/ if (qtty->version > 0) { /* * Initialize dma_mask to 32-bits.
*/ if (!pdev->dev.dma_mask)
pdev->dev.dma_mask = &pdev->dev.coherent_dma_mask;
ret = dma_set_mask(&pdev->dev, DMA_BIT_MASK(32)); if (ret) {
dev_err(&pdev->dev, "No suitable DMA available.\n"); goto err_dec_line_count;
}
}
gf_iowrite32(GOLDFISH_TTY_CMD_INT_DISABLE, base + GOLDFISH_TTY_REG_CMD);
ret = request_irq(irq, goldfish_tty_interrupt, IRQF_SHARED, "goldfish_tty", qtty); if (ret) {
pr_err("goldfish_tty: No IRQ available!\n"); goto err_dec_line_count;
}
ttydev = tty_port_register_device(&qtty->port, goldfish_tty_driver,
line, &pdev->dev); if (IS_ERR(ttydev)) {
ret = PTR_ERR(ttydev); goto err_tty_register_device_failed;
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.