static int __init uart8250_defterm_init(struct vmm_devtree_node *node) { int rc; rc = vmm_devtree_regmap(node, &uart8250_port.base, 0); if (rc) { return rc; } rc = vmm_devtree_clock_frequency(node, &uart8250_port.input_clock); if (rc) { return rc; } if (vmm_devtree_read_u32(node, "baudrate", &uart8250_port.baudrate)) { uart8250_port.baudrate = 115200; } if (vmm_devtree_read_u32(node, "reg-shift", &uart8250_port.reg_shift)) { uart8250_port.reg_shift = 2; } if (vmm_devtree_read_u32(node, "reg-io-width", &uart8250_port.reg_width)) { uart8250_port.reg_width = 1; } uart_8250_lowlevel_init(&uart8250_port); return VMM_OK; }
int __init arch_defterm_init(void) { int rc; u32 *val; struct vmm_devtree_node *node; node = vmm_devtree_getnode(VMM_DEVTREE_PATH_SEPARATOR_STRING VMM_DEVTREE_HOSTINFO_NODE_NAME VMM_DEVTREE_PATH_SEPARATOR_STRING "soc" VMM_DEVTREE_PATH_SEPARATOR_STRING "uart0"); if (!node) { return VMM_ENODEV; } rc = vmm_devtree_regmap(node, &sun4i_uart_port.base, 0); if (rc) { return rc; } val = vmm_devtree_attrval(node, VMM_DEVTREE_CLOCK_RATE_ATTR_NAME); sun4i_uart_port.input_clock = (val) ? *val : 24000000; val = vmm_devtree_attrval(node, "baudrate"); sun4i_uart_port.baudrate = (val) ? *val : 115200; val = vmm_devtree_attrval(node, "reg_align"); sun4i_uart_port.reg_align = (val) ? *val : 4; uart_8250_lowlevel_init(&sun4i_uart_port); return VMM_OK; }
static int uart_8250_driver_probe(struct vmm_device *dev, const struct vmm_devtree_nodeid *devid) { int rc; struct uart_8250_port *port; physical_addr_t ioport; const char *aval; port = vmm_zalloc(sizeof(struct uart_8250_port)); if(!port) { rc = VMM_ENOMEM; goto free_nothing; } if (vmm_devtree_read_string(dev->node, VMM_DEVTREE_ADDRESS_TYPE_ATTR_NAME, &aval)) { aval = NULL; } if (aval && !strcmp(aval, VMM_DEVTREE_ADDRESS_TYPE_VAL_IO)) { port->use_ioport = TRUE; } else { port->use_ioport = FALSE; } if (port->use_ioport) { rc = vmm_devtree_regaddr(dev->node, &ioport, 0); if (rc) { goto free_port; } port->base = ioport; } else { rc = vmm_devtree_request_regmap(dev->node, &port->base, 0, "UART 8250"); if (rc) { goto free_port; } } if (vmm_devtree_read_u32(dev->node, "reg-shift", &port->reg_shift)) { port->reg_shift = 0; } if (vmm_devtree_read_u32(dev->node, "reg-io-width", &port->reg_width)) { port->reg_width = 1; } if (vmm_devtree_read_u32(dev->node, "baudrate", &port->baudrate)) { port->baudrate = 115200; } rc = vmm_devtree_clock_frequency(dev->node, &port->input_clock); if (rc) { goto free_reg; } /* Call low-level init function * Note: low-level init will make sure that * interrupts are disabled in IER register. */ uart_8250_lowlevel_init(port); /* Setup interrupt handler */ port->irq = vmm_devtree_irq_parse_map(dev->node, 0); if (!port->irq) { rc = VMM_ENODEV; goto free_reg; } if ((rc = vmm_host_irq_register(port->irq, dev->name, uart_8250_irq_handler, port))) { goto free_reg; } /* Create Serial Port */ port->p = serial_create(dev, 256, uart_8250_tx, port); if (VMM_IS_ERR_OR_NULL(port->p)) { rc = VMM_PTR_ERR(port->p); goto free_irq; } /* Save port pointer */ dev->priv = port; /* Unmask Rx interrupt */ port->ier |= (UART_IER_RLSI | UART_IER_RDI); uart_8250_out(port, UART_IER_OFFSET, port->ier); return VMM_OK; free_irq: vmm_host_irq_unregister(port->irq, port); free_reg: if (!port->use_ioport) { vmm_devtree_regunmap_release(dev->node, port->base, 0); } free_port: vmm_free(port); free_nothing: return rc; }