static int __init pl011_defterm_init(struct vmm_devtree_node *node) { int rc; rc = vmm_devtree_regmap(node, &pl011_defterm_base, 0); if (rc) { return rc; } rc = vmm_devtree_clock_frequency(node, &pl011_defterm_inclk); if (rc) { return rc; } if (vmm_devtree_read_u32(node, "baudrate", &pl011_defterm_baud)) { pl011_defterm_baud = 115200; } pl011_lowlevel_init(pl011_defterm_base, pl011_defterm_baud, pl011_defterm_inclk); return VMM_OK; }
int __init arch_clocksource_init(void) { int rc; struct vmm_devtree_node *node; /* Map timer0 registers */ node = vmm_devtree_getnode(VMM_DEVTREE_PATH_SEPARATOR_STRING "mct"); if (!node) { rc = VMM_EFAIL; goto skip_mct_timer_init; } rc = vmm_devtree_clock_frequency(node, &mct_clk_rate); if (rc) { goto skip_mct_timer_init; } if (!mct_timer_base) { rc = vmm_devtree_regmap(node, &mct_timer_base, 0); if (rc) { return rc; } } /* Initialize mct as clocksource */ rc = exynos4_clocksource_init(mct_timer_base, node->name, 300, mct_clk_rate); if (rc) { return rc; } skip_mct_timer_init: return rc; }
static int __init samsung_defterm_init(struct vmm_devtree_node *node) { int rc; /* map this console device */ rc = vmm_devtree_regmap(node, &samsung_defterm_base, 0); if (rc) { return rc; } /* retrieve clock frequency */ rc = vmm_devtree_clock_frequency(node, &samsung_defterm_inclk); if (rc) { return rc; } /* retrieve baud rate */ if (vmm_devtree_read_u32(node, "baudrate", &samsung_defterm_baud)) { samsung_defterm_baud = 115200; } /* initialize the console port */ samsung_lowlevel_init(samsung_defterm_base, samsung_defterm_baud, samsung_defterm_inclk); return VMM_OK; }
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 epit_clocksource_init(void) { int rc = VMM_ENODEV; u32 clock; struct vmm_devtree_node *node; struct epit_clocksource *ecs; /* find a epit compatible node */ node = vmm_devtree_find_compatible(NULL, NULL, "freescale,epit-timer"); if (!node) { goto fail; } /* Read clock frequency from node */ rc = vmm_devtree_clock_frequency(node, &clock); if (rc) { goto fail; } /* allocate our struct */ ecs = vmm_zalloc(sizeof(struct epit_clocksource)); if (!ecs) { rc = VMM_ENOMEM; goto fail; } /* Map timer registers */ rc = vmm_devtree_regmap(node, &ecs->base, 0); if (rc) { goto regmap_fail; } /* Setup clocksource */ ecs->clksrc.name = node->name; ecs->clksrc.rating = 300; ecs->clksrc.read = epit_clksrc_read; ecs->clksrc.mask = VMM_CLOCKSOURCE_MASK(32); vmm_clocks_calc_mult_shift(&ecs->clksrc.mult, &ecs->clksrc.shift, clock, VMM_NSEC_PER_SEC, 10); ecs->clksrc.priv = ecs; /* Register clocksource */ rc = vmm_clocksource_register(&ecs->clksrc); if (rc) { goto register_fail; } return VMM_OK; register_fail: vmm_devtree_regunmap(node, ecs->base, 0); regmap_fail: vmm_free(ecs); fail: return rc; }
int __cpuinit arch_clockchip_init(void) { int rc; struct vmm_devtree_node *node; u32 val, cpu = vmm_smp_processor_id(); if (!cpu) { /* Map timer0 registers */ node = vmm_devtree_getnode(VMM_DEVTREE_PATH_SEPARATOR_STRING "mct"); if (!node) { goto skip_mct_timer_init; } if (!mct_timer_base) { rc = vmm_devtree_regmap(node, &mct_timer_base, 0); if (rc) { return rc; } } rc = vmm_devtree_clock_frequency(node, &mct_clk_rate); if (rc) { return rc; } /* Get MCT irq */ rc = vmm_devtree_irq_get(node, &val, 0); if (rc) { return rc; } /* Initialize MCT as clockchip */ rc = exynos4_clockchip_init(mct_timer_base, val, node->name, 300, mct_clk_rate, 0); if (rc) { return rc; } } skip_mct_timer_init: #if CONFIG_SAMSUNG_MCT_LOCAL_TIMERS if (mct_timer_base) { exynos4_local_timer_init(mct_timer_base, 0, "mct_tick", 450, mct_clk_rate); } #endif return VMM_OK; }
int __init generic_timer_clocksource_init(void) { int rc; struct vmm_clocksource *cs; struct vmm_devtree_node *node; node = vmm_devtree_find_matching(NULL, generic_timer_match); if (!node) { return VMM_ENODEV; } if (generic_timer_hz == 0) { rc = vmm_devtree_clock_frequency(node, &generic_timer_hz); if (rc) { /* Use preconfigured counter frequency * in absence of dts node */ generic_timer_hz = generic_timer_reg_read(GENERIC_TIMER_REG_FREQ); } else { if (generic_timer_freq_writeable()) { /* Program the counter frequency * as per the dts node */ generic_timer_reg_write(GENERIC_TIMER_REG_FREQ, generic_timer_hz); } } } if (generic_timer_hz == 0) { return VMM_EFAIL; } cs = vmm_zalloc(sizeof(struct vmm_clocksource)); if (!cs) { return VMM_EFAIL; } cs->name = "gen-timer"; cs->rating = 400; cs->read = &generic_counter_read; cs->mask = VMM_CLOCKSOURCE_MASK(56); vmm_clocks_calc_mult_shift(&cs->mult, &cs->shift, generic_timer_hz, VMM_NSEC_PER_SEC, 10); cs->priv = NULL; return vmm_clocksource_register(cs); }
static int __init bcm2835_clocksource_init(struct vmm_devtree_node *node) { int rc; u32 clock; struct bcm2835_clocksource *bcs; /* Read clock frequency */ rc = vmm_devtree_clock_frequency(node, &clock); if (rc) { return rc; } bcs = vmm_zalloc(sizeof(struct bcm2835_clocksource)); if (!bcs) { return VMM_ENOMEM; } /* Map timer registers */ rc = vmm_devtree_regmap(node, &bcs->base, 0); if (rc) { vmm_free(bcs); return rc; } bcs->system_clock = (void *)(bcs->base + REG_COUNTER_LO); /* Setup clocksource */ bcs->clksrc.name = "bcm2835_timer"; bcs->clksrc.rating = 300; bcs->clksrc.read = bcm2835_clksrc_read; bcs->clksrc.mask = VMM_CLOCKSOURCE_MASK(32); vmm_clocks_calc_mult_shift(&bcs->clksrc.mult, &bcs->clksrc.shift, clock, VMM_NSEC_PER_SEC, 10); bcs->clksrc.priv = bcs; /* Register clocksource */ rc = vmm_clocksource_register(&bcs->clksrc); if (rc) { vmm_devtree_regunmap(node, bcs->base, 0); vmm_free(bcs); return rc; } 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 void generic_timer_get_freq(struct vmm_devtree_node *node) { int rc; if (generic_timer_hz == 0) { rc = vmm_devtree_clock_frequency(node, &generic_timer_hz); if (rc) { /* Use preconfigured counter frequency * in absence of dts node */ generic_timer_hz = generic_timer_reg_read(GENERIC_TIMER_REG_FREQ); } else { if (generic_timer_freq_writeable()) { /* Program the counter frequency * as per the dts node */ generic_timer_reg_write(GENERIC_TIMER_REG_FREQ, generic_timer_hz); } } } }
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 __cpuinit bcm2835_clockchip_init(struct vmm_devtree_node *node) { int rc; u32 clock, hirq; struct bcm2835_clockchip *bcc; /* Read clock frequency */ rc = vmm_devtree_clock_frequency(node, &clock); if (rc) { return rc; } /* Read irq attribute */ rc = vmm_devtree_irq_get(node, &hirq, DEFAULT_TIMER); if (rc) { return rc; } bcc = vmm_zalloc(sizeof(struct bcm2835_clockchip)); if (!bcc) { return VMM_ENOMEM; } /* Map timer registers */ rc = vmm_devtree_regmap(node, &bcc->base, 0); if (rc) { vmm_free(bcc); return rc; } bcc->system_clock = (void *)(bcc->base + REG_COUNTER_LO); bcc->control = (void *)(bcc->base + REG_CONTROL); bcc->compare = (void *)(bcc->base + REG_COMPARE(DEFAULT_TIMER)); bcc->match_mask = 1 << DEFAULT_TIMER; /* Setup clockchip */ bcc->clkchip.name = "bcm2835-clkchip"; bcc->clkchip.hirq = hirq; bcc->clkchip.rating = 300; bcc->clkchip.cpumask = vmm_cpumask_of(0); bcc->clkchip.features = VMM_CLOCKCHIP_FEAT_ONESHOT; vmm_clocks_calc_mult_shift(&bcc->clkchip.mult, &bcc->clkchip.shift, VMM_NSEC_PER_SEC, clock, 10); bcc->clkchip.min_delta_ns = vmm_clockchip_delta2ns(MIN_REG_COMPARE, &bcc->clkchip); bcc->clkchip.max_delta_ns = vmm_clockchip_delta2ns(MAX_REG_COMPARE, &bcc->clkchip); bcc->clkchip.set_mode = &bcm2835_clockchip_set_mode; bcc->clkchip.set_next_event = &bcm2835_clockchip_set_next_event; bcc->clkchip.priv = bcc; /* Make sure compare register is set to zero */ vmm_writel(0x0, bcc->compare); /* Make sure pending timer interrupts acknowledged */ if (vmm_readl(bcc->control) & bcc->match_mask) { vmm_writel(bcc->match_mask, bcc->control); } /* Register interrupt handler */ rc = vmm_host_irq_register(hirq, "bcm2835_timer", &bcm2835_clockchip_irq_handler, bcc); if (rc) { vmm_devtree_regunmap(node, bcc->base, 0); vmm_free(bcc); return rc; } /* Register clockchip */ rc = vmm_clockchip_register(&bcc->clkchip); if (rc) { vmm_host_irq_unregister(hirq, bcc); vmm_devtree_regunmap(node, bcc->base, 0); vmm_free(bcc); return rc; } 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; }
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; u32 reg_offset; struct omap_uart_port *port; port = vmm_zalloc(sizeof(struct omap_uart_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 = omap_uart_read; port->cd.write = omap_uart_write; port->cd.priv = port; INIT_COMPLETION(&port->read_possible); INIT_COMPLETION(&port->write_possible); rc = vmm_devtree_regmap(dev->node, &port->base, 0); if(rc) { goto free_port; } if (vmm_devtree_read_u32(dev->node, "reg_align", &port->reg_align)) { port->reg_align = 1; } if (vmm_devtree_read_u32(dev->node, "reg_offset", ®_offset) == VMM_OK) { port->base += reg_offset; } rc = vmm_devtree_read_u32(dev->node, "baudrate", &port->baudrate); if (rc) { goto free_reg; } rc = vmm_devtree_clock_frequency(dev->node, &port->input_clock); if (rc) { goto free_reg; } omap_uart_startup_configure(port); 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, omap_uart_irq_handler, port))) { goto free_reg; } rc = vmm_chardev_register(&port->cd); if (rc) { goto free_irq; } dev->priv = port; return VMM_OK; 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 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; }
int __cpuinit epit_clockchip_init(void) { int rc = VMM_ENODEV; u32 clock, hirq, timer_num, *val; struct vmm_devtree_node *node; struct epit_clockchip *ecc; /* find the first epit compatible node */ node = vmm_devtree_find_compatible(NULL, NULL, "freescale,epit-timer"); if (!node) { goto fail; } /* Read clock frequency */ rc = vmm_devtree_clock_frequency(node, &clock); if (rc) { goto fail; } /* Read timer_num attribute */ val = vmm_devtree_attrval(node, "timer_num"); if (!val) { rc = VMM_ENOTAVAIL; goto fail; } timer_num = *val; /* Read irq attribute */ rc = vmm_devtree_irq_get(node, &hirq, 0); if (rc) { goto fail; } /* allocate our struct */ ecc = vmm_zalloc(sizeof(struct epit_clockchip)); if (!ecc) { rc = VMM_ENOMEM; goto fail; } /* Map timer registers */ rc = vmm_devtree_regmap(node, &ecc->base, 0); if (rc) { goto regmap_fail; } ecc->match_mask = 1 << timer_num; ecc->timer_num = timer_num; /* Setup clockchip */ ecc->clkchip.name = node->name; ecc->clkchip.hirq = hirq; ecc->clkchip.rating = 300; ecc->clkchip.cpumask = vmm_cpumask_of(0); ecc->clkchip.features = VMM_CLOCKCHIP_FEAT_ONESHOT; vmm_clocks_calc_mult_shift(&ecc->clkchip.mult, &ecc->clkchip.shift, VMM_NSEC_PER_SEC, clock, 10); ecc->clkchip.min_delta_ns = vmm_clockchip_delta2ns(MIN_REG_COMPARE, &ecc->clkchip); ecc->clkchip.max_delta_ns = vmm_clockchip_delta2ns(MAX_REG_COMPARE, &ecc->clkchip); ecc->clkchip.set_mode = epit_set_mode; ecc->clkchip.set_next_event = epit_set_next_event; ecc->clkchip.priv = ecc; /* * Initialise to a known state (all timers off, and timing reset) */ vmm_writel(0x0, (void *)(ecc->base + EPITCR)); /* * Initialize the load register to the max value to decrement. */ vmm_writel(0xffffffff, (void *)(ecc->base + EPITLR)); /* * enable the timer, set it to the high reference clock, * allow the timer to work in WAIT mode. */ vmm_writel(EPITCR_EN | EPITCR_CLKSRC_REF_HIGH | EPITCR_WAITEN, (void *)(ecc->base + EPITCR)); /* Register interrupt handler */ rc = vmm_host_irq_register(hirq, ecc->clkchip.name, &epit_timer_interrupt, ecc); if (rc) { goto irq_fail; } /* Register clockchip */ rc = vmm_clockchip_register(&ecc->clkchip); if (rc) { goto register_fail; } return VMM_OK; register_fail: vmm_host_irq_unregister(hirq, ecc); irq_fail: vmm_devtree_regunmap(node, ecc->base, 0); regmap_fail: vmm_free(ecc); fail: return rc; }
int __cpuinit generic_timer_clockchip_init(void) { int rc; u32 irq[3], num_irqs, val; struct vmm_clockchip *cc; struct vmm_devtree_node *node; /* Find generic timer device tree node */ node = vmm_devtree_find_matching(NULL, generic_timer_match); if (!node) { return VMM_ENODEV; } /* Determine generic timer frequency */ if (generic_timer_hz == 0) { rc = vmm_devtree_clock_frequency(node, &generic_timer_hz); if (rc) { /* Use preconfigured counter frequency * in absence of dts node */ generic_timer_hz = generic_timer_reg_read(GENERIC_TIMER_REG_FREQ); } else if (generic_timer_freq_writeable()) { /* Program the counter frequency as per the dts node */ generic_timer_reg_write(GENERIC_TIMER_REG_FREQ, generic_timer_hz); } } if (generic_timer_hz == 0) { return VMM_EFAIL; } /* Get hypervisor timer irq number */ rc = vmm_devtree_irq_get(node, &irq[GENERIC_HYPERVISOR_TIMER], GENERIC_HYPERVISOR_TIMER); if (rc) { return rc; } /* Get physical timer irq number */ rc = vmm_devtree_irq_get(node, &irq[GENERIC_PHYSICAL_TIMER], GENERIC_PHYSICAL_TIMER); if (rc) { return rc; } /* Get virtual timer irq number */ rc = vmm_devtree_irq_get(node, &irq[GENERIC_VIRTUAL_TIMER], GENERIC_VIRTUAL_TIMER); if (rc) { return rc; } /* Number of generic timer irqs */ num_irqs = vmm_devtree_irq_count(node); if (!num_irqs) { return VMM_EFAIL; } /* Ensure hypervisor timer is stopped */ generic_timer_stop(); /* Create generic hypervisor timer clockchip */ cc = vmm_zalloc(sizeof(struct vmm_clockchip)); if (!cc) { return VMM_EFAIL; } cc->name = "gen-hyp-timer"; cc->hirq = irq[GENERIC_HYPERVISOR_TIMER]; cc->rating = 400; cc->cpumask = vmm_cpumask_of(vmm_smp_processor_id()); cc->features = VMM_CLOCKCHIP_FEAT_ONESHOT; vmm_clocks_calc_mult_shift(&cc->mult, &cc->shift, VMM_NSEC_PER_SEC, generic_timer_hz, 10); cc->min_delta_ns = vmm_clockchip_delta2ns(0xF, cc); cc->max_delta_ns = vmm_clockchip_delta2ns(0x7FFFFFFF, cc); cc->set_mode = &generic_timer_set_mode; cc->set_next_event = &generic_timer_set_next_event; cc->priv = NULL; /* Register hypervisor timer clockchip */ rc = vmm_clockchip_register(cc); if (rc) { goto fail_free_cc; } if (!vmm_smp_processor_id()) { /* Register irq handler for hypervisor timer */ rc = vmm_host_irq_register(irq[GENERIC_HYPERVISOR_TIMER], "gen-hyp-timer", &generic_hyp_timer_handler, cc); if (rc) { goto fail_unreg_cc; } /* Mark hypervisor timer irq as per-CPU */ if ((rc = vmm_host_irq_mark_per_cpu(cc->hirq))) { goto fail_unreg_htimer; } if (num_irqs > 1) { /* Register irq handler for physical timer */ rc = vmm_host_irq_register(irq[GENERIC_PHYSICAL_TIMER], "gen-phys-timer", &generic_phys_timer_handler, NULL); if (rc) { goto fail_unreg_htimer; } /* Mark physical timer irq as per-CPU */ rc = vmm_host_irq_mark_per_cpu( irq[GENERIC_PHYSICAL_TIMER]); if (rc) { goto fail_unreg_ptimer; } } if (num_irqs > 2) { /* Register irq handler for virtual timer */ rc = vmm_host_irq_register(irq[GENERIC_VIRTUAL_TIMER], "gen-virt-timer", &generic_virt_timer_handler, NULL); if (rc) { goto fail_unreg_ptimer; } /* Mark virtual timer irq as per-CPU */ rc = vmm_host_irq_mark_per_cpu( irq[GENERIC_VIRTUAL_TIMER]); if (rc) { goto fail_unreg_vtimer; } } } if (num_irqs > 1) { val = generic_timer_reg_read(GENERIC_TIMER_REG_HCTL); val |= GENERIC_TIMER_HCTL_KERN_PCNT_EN; val |= GENERIC_TIMER_HCTL_KERN_PTMR_EN; generic_timer_reg_write(GENERIC_TIMER_REG_HCTL, val); } for (val = 0; val < num_irqs; val++) { gic_enable_ppi(irq[val]); } return VMM_OK; fail_unreg_vtimer: if (!vmm_smp_processor_id() && num_irqs > 2) { vmm_host_irq_unregister(irq[GENERIC_HYPERVISOR_TIMER], &generic_virt_timer_handler); } fail_unreg_ptimer: if (!vmm_smp_processor_id() && num_irqs > 1) { vmm_host_irq_unregister(irq[GENERIC_PHYSICAL_TIMER], &generic_phys_timer_handler); } fail_unreg_htimer: if (!vmm_smp_processor_id()) { vmm_host_irq_unregister(irq[GENERIC_HYPERVISOR_TIMER], &generic_hyp_timer_handler); } fail_unreg_cc: vmm_clockchip_register(cc); fail_free_cc: vmm_free(cc); 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; }