static int samsung_driver_probe(struct vmm_device *dev, const struct vmm_devtree_nodeid *devid) { u32 ucon; int rc = VMM_EFAIL; struct samsung_port *port = NULL; port = vmm_zalloc(sizeof(struct samsung_port)); if (!port) { rc = VMM_ENOMEM; goto free_nothing; } rc = vmm_devtree_request_regmap(dev->of_node, &port->base, 0, "Samsung UART"); if (rc) { goto free_port; } /* Make sure all interrupts except Rx are masked. */ port->mask = S3C64XX_UINTM_RXD_MSK; port->mask = ~port->mask; vmm_out_le16((void *)(port->base + S3C64XX_UINTM), port->mask); 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 interrupt handler */ port->irq = vmm_devtree_irq_parse_map(dev->of_node, 0); if (!port->irq) { rc = VMM_ENODEV; goto free_reg; } if ((rc = vmm_host_irq_register(port->irq, dev->name, samsung_irq_handler, port))) { goto free_reg; } /* Call low-level init function */ samsung_lowlevel_init(port->base, port->baudrate, port->input_clock); /* Create Serial Port */ port->p = serial_create(dev, 256, samsung_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 */ ucon = vmm_in_le32((void *)(port->base + S3C2410_UCON)); ucon |= S3C2410_UCON_RXIRQMODE; vmm_out_le32((void *)(port->base + S3C2410_UCON), ucon); return VMM_OK; free_irq: vmm_host_irq_unregister(port->irq, port); free_reg: vmm_devtree_regunmap_release(dev->of_node, port->base, 0); free_port: vmm_free(port); free_nothing: return rc; }
static int __cpuinit twd_clockchip_init(struct vmm_devtree_node *node) { int rc; u32 ref_cnt_freq; virtual_addr_t ref_cnt_addr; u32 cpu = vmm_smp_processor_id(); struct twd_clockchip *cc = &this_cpu(twd_cc); if (!twd_base) { rc = vmm_devtree_request_regmap(node, &twd_base, 0, "ARM Local Timer"); if (rc) { goto fail; } } if (!twd_ppi_irq) { twd_ppi_irq = vmm_devtree_irq_parse_map(node, 0); if (!twd_ppi_irq) { rc = VMM_ENODEV; goto fail_regunmap; } } if (!twd_freq_hz) { /* First try to find TWD clock */ if (!twd_clk) { twd_clk = of_clk_get(node, 0); } if (VMM_IS_ERR_OR_NULL(twd_clk)) { twd_clk = clk_get_sys("smp_twd", NULL); } if (!VMM_IS_ERR_OR_NULL(twd_clk)) { /* Use TWD clock to find frequency */ rc = clk_prepare_enable(twd_clk); if (rc) { clk_put(twd_clk); goto fail_regunmap; } twd_freq_hz = clk_get_rate(twd_clk); } else { /* No TWD clock found hence caliberate */ rc = vmm_devtree_regmap(node, &ref_cnt_addr, 1); if (rc) { vmm_devtree_regunmap(node, ref_cnt_addr, 1); goto fail_regunmap; } if (vmm_devtree_read_u32(node, "ref-counter-freq", &ref_cnt_freq)) { vmm_devtree_regunmap(node, ref_cnt_addr, 1); goto fail_regunmap; } twd_caliberate_freq(twd_base, ref_cnt_addr, ref_cnt_freq); vmm_devtree_regunmap(node, ref_cnt_addr, 1); } } memset(cc, 0, sizeof(struct twd_clockchip)); vmm_sprintf(cc->name, "twd/%d", cpu); cc->clkchip.name = cc->name; cc->clkchip.hirq = twd_ppi_irq; cc->clkchip.rating = 350; cc->clkchip.cpumask = vmm_cpumask_of(cpu); cc->clkchip.features = VMM_CLOCKCHIP_FEAT_PERIODIC | VMM_CLOCKCHIP_FEAT_ONESHOT; vmm_clocks_calc_mult_shift(&cc->clkchip.mult, &cc->clkchip.shift, VMM_NSEC_PER_SEC, twd_freq_hz, 10); cc->clkchip.min_delta_ns = vmm_clockchip_delta2ns(0xF, &cc->clkchip); cc->clkchip.max_delta_ns = vmm_clockchip_delta2ns(0xFFFFFFFF, &cc->clkchip); cc->clkchip.set_mode = &twd_clockchip_set_mode; cc->clkchip.set_next_event = &twd_clockchip_set_next_event; cc->clkchip.priv = cc; /* Register interrupt handler */ if ((rc = vmm_host_irq_register(twd_ppi_irq, "twd", &twd_clockchip_irq_handler, cc))) { goto fail_regunmap; } rc = vmm_clockchip_register(&cc->clkchip); if (rc) { goto fail_unreg_irq; } return VMM_OK; fail_unreg_irq: vmm_host_irq_unregister(twd_ppi_irq, cc); fail_regunmap: vmm_devtree_regunmap_release(node, twd_base, 0); fail: return rc; }
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; }
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; }
static int omap_uart_driver_probe(struct vmm_device *dev, const struct vmm_devtree_nodeid *devid) { int rc; struct omap_uart_port *port; port = vmm_zalloc(sizeof(struct omap_uart_port)); if (!port) { rc = VMM_ENOMEM; goto free_nothing; } rc = vmm_devtree_request_regmap(dev->of_node, &port->base, 0, "omap-uart"); if (rc) { goto free_port; } if (vmm_devtree_read_u32(dev->of_node, "reg-shift", &port->reg_shift)) { port->reg_shift = 0; } 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; } omap_uart_startup_configure(port); port->irq = vmm_devtree_irq_parse_map(dev->of_node, 0); if (!port->irq) { rc = VMM_ENODEV; goto free_reg; } if ((rc = vmm_host_irq_register(port->irq, dev->name, omap_uart_irq_handler, port))) { goto free_reg; } /* Create Serial Port */ port->p = serial_create(dev, 256, omap_uart_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_RDI | UART_IER_RLSI); omap_serial_out(port, UART_IER, port->ier); return VMM_OK; free_irq: vmm_host_irq_unregister(port->irq, port); free_reg: vmm_devtree_regunmap_release(dev->of_node, port->base, 0); free_port: vmm_free(port); free_nothing: return rc; }