Example #1
0
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;
}
Example #2
0
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;
}
Example #3
0
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;
}
Example #4
0
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;
}
Example #5
0
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 "motherboard"
				   VMM_DEVTREE_PATH_SEPARATOR_STRING "iofpga"
				   VMM_DEVTREE_PATH_SEPARATOR_STRING "uart0");
	if (!node) {
		return VMM_ENODEV;
	}
	rc = vmm_devtree_regmap(node, &v2m_defterm_base, 0);
	if (rc) {
		return rc;
	}

	val = vmm_devtree_attrval(node, VMM_DEVTREE_CLOCK_RATE_ATTR_NAME);
	v2m_defterm_inclk = (val) ? *val : 24000000;

	val = vmm_devtree_attrval(node, "baudrate");
	v2m_defterm_baud = (val) ? *val : 115200;

	pl011_lowlevel_init(v2m_defterm_base,
			    v2m_defterm_baud, 
			    v2m_defterm_inclk);
	return VMM_OK;
}
Example #6
0
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;
}
Example #7
0
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;
}
Example #8
0
int __init arch_smp_init_cpus(void)
{
	u32 ncores;
	int i, rc = VMM_OK;
	struct vmm_devtree_node *node;

	/* Get the PMU node in the dev tree */
	node = vmm_devtree_getnode(VMM_DEVTREE_PATH_SEPARATOR_STRING "pmu");
	if (!node) {
		return VMM_EFAIL;
	}

	/* Map the PMU physical address to virtual address */
	rc = vmm_devtree_regmap(node, &pmu_base, 0);
	if (rc) {
		return rc;
	}

	/* Get the SCU node in the dev tree */
	node = vmm_devtree_getnode(VMM_DEVTREE_PATH_SEPARATOR_STRING "scu");
	if (!node) {
		return VMM_EFAIL;
	}

	/* Map the SCU physical address to virtual address */
	rc = vmm_devtree_regmap(node, &scu_base, 0);
	if (rc) {
		return rc;
	}

	/* How many ARM core do we have */
	ncores = scu_get_core_count((void *)scu_base);

	/* Update the cpu_possible bitmap based on SCU */
	for (i = 0; i < CONFIG_CPU_COUNT; i++) {
		if ((i < ncores) &&
		    scu_cpu_core_is_smp((void *)scu_base, i)) {
			vmm_set_cpu_possible(i, TRUE);
		}
	}

	return VMM_OK;
}
Example #9
0
static int __init scu_cpu_init(struct vmm_devtree_node *node,
				unsigned int cpu)
{
	int rc;
	u32 ncores;
	physical_addr_t pa;
	struct vmm_devtree_node *scu_node;

	/* Map SCU base */
	if (!scu_base) {
		scu_node = vmm_devtree_find_matching(NULL, scu_matches);
		if (!scu_node) {
			return VMM_ENODEV;
		}
		rc = vmm_devtree_regmap(scu_node, &scu_base, 0);
		vmm_devtree_dref_node(scu_node);
		if (rc) {
			return rc;
		}
	}

	/* Map clear address */
	rc = vmm_devtree_read_physaddr(node,
			VMM_DEVTREE_CPU_CLEAR_ADDR_ATTR_NAME, &pa);
	if (rc) {
		clear_addr[cpu] = 0x0;
	} else {
		clear_addr[cpu] = pa;
	}

	/* Map release address */
	rc = vmm_devtree_read_physaddr(node,
			VMM_DEVTREE_CPU_RELEASE_ADDR_ATTR_NAME, &pa);
	if (rc) {
		release_addr[cpu] = 0x0;
	} else {
		release_addr[cpu] = pa;
	}

	/* Check core count from SCU */
	ncores = scu_get_core_count((void *)scu_base);
	if (ncores <= cpu) {
		return VMM_ENOSYS;
	}

	/* Check SCU status */
	if (!scu_cpu_core_is_smp((void *)scu_base, cpu)) {
		return VMM_ENOSYS;
	}

	return VMM_OK;
}
Example #10
0
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;
}
Example #11
0
static int __init sun4i_reboot_driver_probe(struct vmm_device *dev,
					const struct vmm_devtree_nodeid *devid)
{
	int rc;

	/* Map timer registers */
	rc = vmm_devtree_regmap(dev->node, &aw_base, 0);
	if (rc) {
		return rc;
	}

	/* Register reset callbacks */
	vmm_register_system_reset(aw_timer_force_reset);

	return VMM_OK;
}
Example #12
0
static int __init bcm2836_early_init(struct vmm_devtree_node *node)
{
	int rc = VMM_OK;
	void *base;
	u32 prescaler, cntfreq;
	virtual_addr_t base_va;
	struct vmm_devtree_node *np;

	np = vmm_devtree_find_compatible(NULL, NULL, "brcm,bcm2836-l1-intc");
	if (!np) {
		return VMM_ENODEV;
	}

	rc = vmm_devtree_regmap(np, &base_va, 0);
	if (rc) {
		goto done;
	}
	base = (void *)base_va;

	cntfreq = generic_timer_reg_read(GENERIC_TIMER_REG_FREQ);
	switch (cntfreq) {
	case 19200000:
		prescaler = 0x80000000;
	case 1000000:
		prescaler = 0x06AAAAAB;
	default:
		prescaler = (u32)udiv64((u64)0x80000000 * (u64)cntfreq,
					(u64)19200000);
		break;
	};

	if (!prescaler) {
		rc = VMM_EINVALID;
		goto done_unmap;
	}

	vmm_writel(prescaler, base + LOCAL_TIMER_PRESCALER);

done_unmap:
	vmm_devtree_regunmap(node, base_va, 0);

done:
	vmm_devtree_dref_node(np);

	return rc;
}
Example #13
0
int __init arch_smp_prepare_cpus(void)
{
	int rc = VMM_OK;
	struct vmm_devtree_node *node;
	virtual_addr_t ca9_scu_base;
	u32 ncores;
	int i;

	/* Get the SCU node in the dev tree */
	node = vmm_devtree_getnode(VMM_DEVTREE_PATH_SEPARATOR_STRING
				   VMM_DEVTREE_HOSTINFO_NODE_NAME
				   VMM_DEVTREE_PATH_SEPARATOR_STRING "scu");
	if (!node) {
		return VMM_EFAIL;
	}

	/* map the SCU physical address to virtual address */
	rc = vmm_devtree_regmap(node, &ca9_scu_base, 0);
	if (rc) {
		return rc;
	}

	/* How many ARM core do we have */
	ncores = scu_get_core_count((void *)ca9_scu_base);

	/* Find out the number of SMP-enabled cpu cores */
	for (i = 0; i < CONFIG_CPU_COUNT; i++) {
		/* build the possible CPU map */
		if ((i >= ncores)
		    || !scu_cpu_core_is_smp((void *)ca9_scu_base, i)) {
			/* Update the cpu_possible bitmap */
			vmm_set_cpu_possible(i, 0);
		} else {
			vmm_set_cpu_possible(i, 1);
		}
	}

	/* Enable snooping through SCU */
	scu_enable((void *)ca9_scu_base);

	/* unmap the SCU node */
	rc = vmm_devtree_regunmap(node, ca9_scu_base, 0);

	return rc;
}
Example #14
0
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;
}
Example #15
0
int __init bcm2835_pm_init(void)
{
	int rc;
	struct vmm_devtree_node *node;

	node = vmm_devtree_find_compatible(NULL, NULL, 
					   "brcm,bcm2835-pm-wdt");
	if (!node) {
		return VMM_ENODEV;
	}

	rc = vmm_devtree_regmap(node, &pm_base_va, 0);
	if (rc) {
		return rc;
	}

	return VMM_OK;
}
Example #16
0
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;
}
Example #17
0
void __init realview_sysreg_of_early_init(void)
{
	int err;
	virtual_addr_t base_va;
	struct vmm_devtree_node *node;

	if (realview_sysreg_base)
		return;

	node = vmm_devtree_find_compatible(NULL, NULL, "arm,realview-sysreg");
	if (node) {
		err = vmm_devtree_regmap(node, &base_va, 0);
		if (err) {
			vmm_printf("%s: Faild to map registers (err %d)\n",
				   __func__, err);
			return;
		}		
		realview_sysreg_base = (void *)base_va;
	}
}
Example #18
0
static int realview_sysreg_probe(struct vmm_device *dev, 
				 const struct vmm_devtree_nodeid *devid)
{
	int err;
	virtual_addr_t base_va;

	if (!realview_sysreg_base) {
		err = vmm_devtree_regmap(dev->node, &base_va, 0);
		if (err) {
			return err;
		}
		realview_sysreg_base = (void *)base_va;
	}

	if (!realview_sysreg_base) {
		vmm_printf("%s: Failed to obtain base address!\n", __func__);
		return VMM_EFAULT;
	}

	return VMM_OK;
}
Example #19
0
int __init arch_smp_start_cpu(u32 cpu)
{
	const struct vmm_cpumask *mask;
	int rc;
	struct vmm_devtree_node *node;
	virtual_addr_t ca9_pmu_base;

	if (cpu == 0) {
		/* Nothing to do for first CPU */
		return VMM_OK;
	}

	/* Get the PMU node in the dev tree */
	node = vmm_devtree_getnode(VMM_DEVTREE_PATH_SEPARATOR_STRING
				   VMM_DEVTREE_HOSTINFO_NODE_NAME
				   VMM_DEVTREE_PATH_SEPARATOR_STRING "pmu");
	if (!node) {
		return VMM_EFAIL;
	}

	/* map the PMU physical address to virtual address */
	rc = vmm_devtree_regmap(node, &ca9_pmu_base, 0);
	if (rc) {
		return rc;
	}

	mask = get_cpu_mask(cpu);

	/* Write the entry address for the secondary cpus */
	vmm_writel((u32)_load_start, (void *)ca9_pmu_base + 0x814);

	/* unmap the PMU node */
	rc = vmm_devtree_regunmap(node, ca9_pmu_base, 0);

	/* Wakeup target cpu from wfe/wfi by sending an IPI */
	gic_raise_softirq(mask, 0);

	return rc;
}
Example #20
0
static int __init versatile_early_init(struct vmm_devtree_node *node)
{
	int rc;

	/* Host aspace, Heap, Device tree, and Host IRQ available.
	 *
	 * Do necessary early stuff like:
	 * iomapping devices, 
	 * SOC clocking init, 
	 * Setting-up system data in device tree nodes,
	 * ....
	 */

	/* Map sysreg */
	node = vmm_devtree_find_compatible(NULL, NULL, "arm,versatile-sysreg");
	if (!node) {
		return VMM_ENODEV;
	}
	rc = vmm_devtree_regmap(node, &versatile_sys_base, 0);
	if (rc) {
		return rc;
	}

	/* Register reset & shutdown callbacks */
	vmm_register_system_reset(versatile_reset);
	vmm_register_system_shutdown(versatile_shutdown);

	/* Initialize versatile clocking */
	versatile_clk_init((void *)versatile_sys_base);

	/* Setup CLCD (before probing) */
	node = vmm_devtree_find_compatible(NULL, NULL, "arm,pl110,versatile");
	if (node) {
		node->system_data = &clcd_system_data;
	}

	return 0;
}
Example #21
0
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_regmap(node, &twd_base, 0);
		if (rc) {
			goto fail;
		}
	}

	if (!twd_ppi_irq) {
		rc = vmm_devtree_irq_get(node, &twd_ppi_irq, 0);
		if (rc) {
			goto fail_regunmap;
		}
	}

	if (!twd_freq_hz) {
		/* First try to find TWD clock */
		if (!twd_clk) {
			twd_clk = of_clk_get(node, 0);
		}
		if (!twd_clk) {
			twd_clk = clk_get_sys("smp_twd", NULL);
		}

		if (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;

	if (vmm_smp_is_bootcpu()) {
		/* Register interrupt handler */
		if ((rc = vmm_host_irq_register(twd_ppi_irq, "twd",
						&twd_clockchip_irq_handler, 
						cc))) {
			
			goto fail_regunmap;
		}

		/* Mark interrupt as per-cpu */
		if ((rc = vmm_host_irq_mark_per_cpu(twd_ppi_irq))) {
			goto fail_unreg_irq;
		}
	}

	/* Explicitly enable local timer PPI in GIC 
	 * Note: Local timer requires PPI support hence requires GIC
	 */
	gic_enable_ppi(twd_ppi_irq);

	rc = vmm_clockchip_register(&cc->clkchip);
	if (rc) {
		goto fail_unreg_irq;
	}

	return VMM_OK;

fail_unreg_irq:
	if (vmm_smp_is_bootcpu()) {
		vmm_host_irq_unregister(twd_ppi_irq, cc);
	}
fail_regunmap:
	vmm_devtree_regunmap(node, twd_base, 0);
fail:
	return rc;
}
Example #22
0
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",
				 &reg_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;
}
Example #23
0
static int mmci_driver_probe(struct vmm_device *dev,
				   const struct vmm_devtree_nodeid *devid)
{
	int rc;
	u32 sdi;
	virtual_addr_t base;
	physical_addr_t basepa;
	struct mmc_host *mmc;
	struct mmci_host *host;

	mmc = mmc_alloc_host(sizeof(struct mmci_host), dev);
	if (!mmc) {
		rc = VMM_ENOMEM;
		goto free_nothing;
	}
	host = mmc_priv(mmc);

	rc = vmm_devtree_regmap(dev->node, &base, 0);
	if (rc) {
		goto free_host;
	}
	host->base = (struct sdi_registers *)base;

	rc = vmm_devtree_irq_get(dev->node, &host->irq0, 0);
	if (rc) {
		goto free_reg;
	}
	if ((rc = vmm_host_irq_register(host->irq0, dev->name, 
					mmci_cmd_irq_handler, mmc))) {
		goto free_reg;
	}

	rc = vmm_devtree_irq_get(dev->node, &host->irq1, 1);
	if (!rc) {
		if ((rc = vmm_host_irq_register(host->irq1, dev->name, 
						mmci_pio_irq_handler, mmc))) {
			goto free_irq0;
		}
		host->singleirq = 0;
	} else {
		host->singleirq = 1;
	}

	/* Retrive matching data */
	host->pwr_init = ((const u32 *)devid->data)[0];
	host->clkdiv_init = ((const u32 *)devid->data)[1];
	host->voltages = ((const u32 *)devid->data)[2];
	host->caps = ((const u32 *)devid->data)[3];
	host->clock_in = ((const u32 *)devid->data)[4];
	host->clock_min = ((const u32 *)devid->data)[5];
	host->clock_max = ((const u32 *)devid->data)[6];
	host->b_max = ((const u32 *)devid->data)[7];
	host->version2 = ((const u32 *)devid->data)[8];

	/* Initialize power and clock divider */
	vmm_writel(host->pwr_init, &host->base->power);
	vmm_writel(host->clkdiv_init, &host->base->clock);
	vmm_udelay(CLK_CHANGE_DELAY);

	/* Disable interrupts */
	sdi = vmm_readl(&host->base->mask0) & ~SDI_MASK0_MASK;
	vmm_writel(sdi, &host->base->mask0);

	/* Setup mmc host configuration */
	mmc->caps = host->caps;
	mmc->voltages = host->voltages;
	mmc->f_min = host->clock_min;
	mmc->f_max = host->clock_max;
	mmc->b_max = host->b_max;

	/* Setup mmc host operations */
	mmc->ops.send_cmd = mmci_request;
	mmc->ops.set_ios = mmci_set_ios;
	mmc->ops.init_card = mmci_init_card;
	mmc->ops.get_cd = NULL;
	mmc->ops.get_wp = NULL;

	rc = mmc_add_host(mmc);
	if (rc) {
		goto free_irq1;
	}

	dev->priv = mmc;

	vmm_devtree_regaddr(dev->node, &basepa, 0);
	vmm_printf("%s: PL%03x manf %x rev%u at 0x%08llx irq %d,%d (pio)\n",
		   dev->name, amba_part(dev), amba_manf(dev),
		   amba_rev(dev), (unsigned long long)basepa,
		   host->irq0, host->irq1);

	return VMM_OK;

free_irq1:
	if (!host->singleirq) {
		vmm_host_irq_unregister(host->irq1, mmc);
	}
free_irq0:
	vmm_host_irq_unregister(host->irq0, mmc);
free_reg:
	vmm_devtree_regunmap(dev->node, (virtual_addr_t)host->base, 0);
free_host:
	mmc_free_host(mmc);
free_nothing:
	return rc;
}
Example #24
0
static int uart_driver_probe(struct vmm_device *dev,const struct vmm_devid *devid)
{
	int rc;
	const char *attr;
	struct vmm_chardev *cd;
	struct uart_port *port;
	
	cd = vmm_malloc(sizeof(struct vmm_chardev));
	if(!cd) {
		rc = VMM_EFAIL;
		goto free_nothing;
	}
	memset(cd, 0, sizeof(struct vmm_chardev));

	port = vmm_malloc(sizeof(struct uart_port));
	if(!port) {
		rc = VMM_EFAIL;
		goto free_chardev;
	}
	memset(port, 0, sizeof(struct uart_port));

	strcpy(cd->name, dev->node->name);
	cd->dev = dev;
	cd->ioctl = NULL;
	cd->read = uart_read;
	cd->write = uart_write;
	cd->priv = port;

	rc = vmm_devtree_regmap(dev->node, &port->base, 0);
	if(rc) {
		goto free_port;
	}

	attr = vmm_devtree_attrval(dev->node, "reg_align");
	if (attr) {
		port->reg_align = *((u32 *)attr);
	} else {
		port->reg_align = 1;
	}

	attr = vmm_devtree_attrval(dev->node, "reg_offset");
	if (attr) {
		port->base += *((u32 *)attr);
	}

	attr = vmm_devtree_attrval(dev->node, "baudrate");
	if(!attr) {
		rc = VMM_EFAIL;
		goto free_port;
	}
	port->baudrate = *((u32 *)attr);
	port->input_clock = vmm_devdrv_clock_get_rate(dev);

	/* Call low-level init function */
	uart_lowlevel_init(port->base, port->reg_align, 
			port->baudrate, port->input_clock);

	rc = vmm_chardev_register(cd);
	if(rc) {
		goto free_port;
	}

	return VMM_OK;

free_port:
	vmm_free(port);
free_chardev:
	vmm_free(cd);
free_nothing:
	return rc;
}
Example #25
0
int __cpuinit twd_clockchip_init(virtual_addr_t ref_counter_addr,
                                 u32 ref_counter_freq)
{
    int rc;
    u32 cpu = vmm_smp_processor_id();
    struct vmm_devtree_node *node;
    struct twd_clockchip *cc = &this_cpu(twd_cc);

    node = vmm_devtree_find_matching(NULL, twd_match);
    if (!node) {
        return VMM_ENODEV;
    }

    if (!twd_base) {
        rc = vmm_devtree_regmap(node, &twd_base, 0);
        if (rc) {
            return rc;
        }
    }

    if (!twd_ppi_irq) {
        rc = vmm_devtree_irq_get(node, &twd_ppi_irq, 0);
        if (rc) {
            return rc;
        }
    }

    twd_caliberate_freq(twd_base, ref_counter_addr, ref_counter_freq);

    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;

    if (!cpu) {
        /* Register interrupt handler */
        if ((rc = vmm_host_irq_register(twd_ppi_irq, "twd",
                                        &twd_clockchip_irq_handler,
                                        cc))) {
            return rc;
        }

        /* Mark interrupt as per-cpu */
        if ((rc = vmm_host_irq_mark_per_cpu(twd_ppi_irq))) {
            return rc;
        }
    }

    /* Explicitly enable local timer PPI in GIC
     * Note: Local timer requires PPI support hence requires GIC
     */
    gic_enable_ppi(twd_ppi_irq);

    return vmm_clockchip_register(&cc->clkchip);
}
Example #26
0
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;
}
Example #27
0
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;
}
Example #28
0
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;
}
Example #29
0
static int s3c_rtc_driver_probe(struct vmm_device *pdev,
				const struct vmm_devtree_nodeid *devid)
{
	u32 alarmno, tickno;
	struct rtc_time rtc_tm;
	int ret, tmp, rc;

	/* find the IRQs */

	rc = vmm_devtree_irq_get(pdev->node, &alarmno, 0);
	if (rc) {
		rc = VMM_EFAIL;
		return rc;
	}
	s3c_rtc_alarmno = alarmno;
	rc = vmm_devtree_irq_get(pdev->node, &tickno, 1);
	if (rc) {
		rc = VMM_EFAIL;
		return rc;
	}
	s3c_rtc_tickno = tickno;

	/* get the memory region */

	rc = vmm_devtree_regmap(pdev->node, (virtual_addr_t *)&s3c_rtc_base,
				0);
	if (rc) {
		dev_err(pdev, "failed ioremap()\n");
		ret = rc;
		goto err_nomap;
	}

	rtc_clk = clk_get(pdev, "rtc");
	if (rtc_clk == NULL) {
		dev_err(pdev, "failed to find rtc clock source\n");
		ret = -ENODEV;
		goto err_clk;
	}

	clk_enable(rtc_clk);

	/* check to see if everything is setup correctly */

	s3c_rtc_enable(pdev, 1);

	//device_init_wakeup(pdev, 1);

	/* register RTC and exit */

	s3c_rtcops.dev = pdev;

	rc = vmm_rtcdev_register(&s3c_rtcops);

	if (rc) {
		dev_err(pdev, "cannot attach rtc\n");
		ret = rc;
		goto err_nortc;
	}

	s3c_rtc_cpu_type = (enum s3c_cpu_type)devid->data;

	/* Check RTC Time */

	s3c_rtc_gettime(NULL, &rtc_tm);

	if (!rtc_valid_tm(&rtc_tm)) {
		dev_warn(pdev,
			 "warning: invalid RTC value so initializing it\n");

		rtc_tm.tm_year = 100;
		rtc_tm.tm_mon = 0;
		rtc_tm.tm_mday = 1;
		rtc_tm.tm_hour = 0;
		rtc_tm.tm_min = 0;
		rtc_tm.tm_sec = 0;

		s3c_rtc_settime(NULL, &rtc_tm);
	}

	if (s3c_rtc_cpu_type != TYPE_S3C2410)
		max_user_freq = 32768;
	else
		max_user_freq = 128;

	if (s3c_rtc_cpu_type == TYPE_S3C2416
	    || s3c_rtc_cpu_type == TYPE_S3C2443) {
		tmp = readw(s3c_rtc_base + S3C2410_RTCCON);
		tmp |= S3C2443_RTCCON_TICSEL;
		writew(tmp, s3c_rtc_base + S3C2410_RTCCON);
	}

	pdev->priv = &s3c_rtcops;

	s3c_rtc_setfreq(&s3c_rtcops, 1);

	if ((rc =
	     vmm_host_irq_register(s3c_rtc_alarmno, "s3c_rtc_alarm",
				   s3c_rtc_alarmirq, &s3c_rtcops))) {
		dev_err(pdev, "IRQ%d error %d\n", s3c_rtc_alarmno, rc);
		goto err_alarm_irq;
	}

	if ((rc =
	     vmm_host_irq_register(s3c_rtc_tickno, "s3c_rtc_tick",
				   s3c_rtc_tickirq, &s3c_rtcops))) {
		dev_err(pdev, "IRQ%d error %d\n", s3c_rtc_tickno, rc);
		goto err_tick_irq;
	}

	clk_disable(rtc_clk);

	return 0;

 err_tick_irq:
	vmm_host_irq_unregister(s3c_rtc_alarmno, &s3c_rtcops);

 err_alarm_irq:
	pdev->priv = NULL;
	vmm_rtcdev_unregister(&s3c_rtcops);

 err_nortc:
	s3c_rtc_enable(pdev, 0);
	clk_disable(rtc_clk);
	clk_put(rtc_clk);

 err_clk:
	vmm_devtree_regunmap(pdev->node, (virtual_addr_t) s3c_rtc_base, 0);

 err_nomap:
	return ret;
}