static int __init imx_defterm_init(struct vmm_devtree_node *node) { int rc; rc = vmm_devtree_regmap(node, &imx_defterm_base, 0); if (rc) { return rc; } rc = vmm_devtree_clock_frequency(node, &imx_defterm_inclk); if (rc) { return rc; } if (vmm_devtree_read_u32(node, "baudrate", &imx_defterm_baud)) { imx_defterm_baud = 115200; } imx_lowlevel_init(imx_defterm_base, imx_defterm_baud, imx_defterm_inclk); return VMM_OK; }
int __init arch_defterm_init(void) { int rc; u32 *val; const char *attr; struct vmm_devtree_node *node; u32 imx_defterm_inclk; u32 imx_defterm_baud; node = vmm_devtree_getnode(VMM_DEVTREE_PATH_SEPARATOR_STRING VMM_DEVTREE_CHOSEN_NODE_NAME); if (!node) { return VMM_ENODEV; } attr = vmm_devtree_attrval(node, VMM_DEVTREE_CONSOLE_ATTR_NAME); if (!attr) { return VMM_ENODEV; } node = vmm_devtree_getnode(attr); if (!node) { return VMM_ENODEV; } rc = vmm_devtree_regmap(node, &imx_defterm_base, 0); if (rc) { return rc; } rc = vmm_devtree_clock_frequency(node, &imx_defterm_inclk); if (rc) { return rc; } val = vmm_devtree_attrval(node, "baudrate"); imx_defterm_baud = (val) ? *val : 115200; imx_lowlevel_init(imx_defterm_base, imx_defterm_baud, imx_defterm_inclk); return VMM_OK; }
static int imx_driver_probe(struct vmm_device *dev, const struct vmm_devtree_nodeid *devid) { int rc = VMM_EFAIL; struct imx_port *port = NULL; port = vmm_zalloc(sizeof(struct imx_port)); if (!port) { rc = VMM_ENOMEM; goto free_nothing; } if (strlcpy(port->cd.name, dev->name, sizeof(port->cd.name)) >= sizeof(port->cd.name)) { rc = VMM_EOVERFLOW; goto free_port; } port->cd.dev.parent = dev; port->cd.ioctl = NULL; port->cd.read = imx_read; port->cd.write = imx_write; port->cd.priv = port; INIT_COMPLETION(&port->read_possible); #if defined(UART_IMX_USE_TXINTR) INIT_COMPLETION(&port->write_possible); #endif rc = vmm_devtree_regmap(dev->node, &port->base, 0); if (rc) { goto free_port; } port->mask = UCR1_RRDYEN | UCR1_UARTEN; #if defined(UART_IMX_USE_TXINTR) port->mask |= UCR1_TRDYEN; #endif vmm_writel(port->mask, (void *)port->base + UCR1); 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; } rc = vmm_devtree_irq_get(dev->node, &port->irq, 0); if (rc) { goto free_reg; } if ((rc = vmm_host_irq_register(port->irq, dev->name, imx_irq_handler, port))) { goto free_reg; } /* Call low-level init function */ imx_lowlevel_init(port->base, port->baudrate, port->input_clock); port->mask = vmm_readl((void *)port->base + UCR1); rc = vmm_chardev_register(&port->cd); if (rc) { goto free_irq; } dev->priv = port; return rc; free_irq: vmm_host_irq_unregister(port->irq, port); free_reg: vmm_devtree_regunmap(dev->node, port->base, 0); free_port: vmm_free(port); free_nothing: return rc; }
static int imx_driver_probe(struct vmm_device *dev, const struct vmm_devtree_nodeid *devid) { int rc = VMM_EFAIL; struct clk *clk_ipg = NULL; struct clk *clk_uart = NULL; struct imx_port *port = NULL; unsigned long old_rate = 0; port = vmm_zalloc(sizeof(struct imx_port)); if (!port) { rc = VMM_ENOMEM; goto free_nothing; } rc = vmm_devtree_request_regmap(dev->of_node, &port->base, 0, "iMX UART"); if (rc) { goto free_port; } if (vmm_devtree_read_u32(dev->of_node, "baudrate", &port->baudrate)) { port->baudrate = 115200; } rc = vmm_devtree_clock_frequency(dev->of_node, &port->input_clock); if (rc) { goto free_reg; } /* Setup clocks */ clk_ipg = of_clk_get(dev->of_node, 0); clk_uart = of_clk_get(dev->of_node, 1); if (!VMM_IS_ERR_OR_NULL(clk_ipg)) { rc = clk_prepare_enable(clk_ipg); if (rc) { goto free_reg; } } if (!VMM_IS_ERR_OR_NULL(clk_uart)) { rc = clk_prepare_enable(clk_uart); if (rc) { goto clk_disable_unprepare_ipg; } old_rate = clk_get_rate(clk_uart); if (clk_set_rate(clk_uart, port->input_clock)) { vmm_printf("Could not set %s clock rate to %u Hz, " "actual rate: %u Hz\n", __clk_get_name(clk_uart), port->input_clock, clk_get_rate(clk_uart)); rc = VMM_ERANGE; goto clk_disable_unprepare_uart; } } /* Register interrupt handler */ port->irq = vmm_devtree_irq_parse_map(dev->of_node, 0); if (!port->irq) { rc = VMM_ENODEV; goto clk_old_rate; } if ((rc = vmm_host_irq_register(port->irq, dev->name, imx_irq_handler, port))) { goto clk_old_rate; } /* Call low-level init function */ imx_lowlevel_init(port->base, port->baudrate, port->input_clock); /* Create Serial Port */ port->p = serial_create(dev, 256, imx_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, Mask Tx, and Enable UART */ port->mask = vmm_readl((void *)port->base + UCR1); port->mask |= (UCR1_RRDYEN | UCR1_UARTEN); port->mask &= ~(UCR1_TRDYEN); vmm_writel(port->mask, (void *)port->base + UCR1); return rc; free_irq: vmm_host_irq_unregister(port->irq, port); clk_old_rate: if (!VMM_IS_ERR_OR_NULL(clk_uart)) { if (old_rate) { clk_set_rate(clk_uart, old_rate); } } clk_disable_unprepare_uart: if (!VMM_IS_ERR_OR_NULL(clk_uart)) { clk_disable_unprepare(clk_uart); } clk_disable_unprepare_ipg: if (!VMM_IS_ERR_OR_NULL(clk_ipg)) { clk_disable_unprepare(clk_ipg); } free_reg: vmm_devtree_regunmap_release(dev->of_node, port->base, 0); free_port: vmm_free(port); free_nothing: return rc; }