コード例 #1
0
ファイル: clk.c プロジェクト: xboot/xboot
void clk_set_parent(const char * name, const char * pname)
{
	struct clk_t * clk = search_clk(name);
	struct clk_t * pclk = search_clk(pname);

	if(pclk && clk && clk->set_parent)
		clk->set_parent(clk, pname);
}
コード例 #2
0
ファイル: cs-samsung-timer.c プロジェクト: xboot/xboot
static struct device_t * cs_samsung_timer_probe(struct driver_t * drv, struct dtnode_t * n)
{
	struct cs_samsung_timer_pdata_t * pdat;
	struct clocksource_t * cs;
	struct device_t * dev;
	virtual_addr_t virt = phys_to_virt(dt_read_address(n));
	char * clk = dt_read_string(n, "clock-name", NULL);
	int channel = dt_read_int(n, "timer-channel", -1);
	u64_t rate;

	if(!search_clk(clk))
		return NULL;

	if(channel < 0 || channel > 3)
		return NULL;

	pdat = malloc(sizeof(struct cs_samsung_timer_pdata_t));
	if(!pdat)
		return NULL;

	cs = malloc(sizeof(struct clocksource_t));
	if(!cs)
	{
		free(pdat);
		return NULL;
	}

	pdat->virt = virt;
	pdat->clk = strdup(clk);
	pdat->channel = channel;

	clk_enable(pdat->clk);
	rate = samsung_timer_calc_tin(pdat->virt, pdat->clk, pdat->channel, 13);
	clocksource_calc_mult_shift(&cs->mult, &cs->shift, rate, 1000000000ULL, 10);
	cs->name = alloc_device_name(dt_read_name(n), -1);
	cs->mask = CLOCKSOURCE_MASK(32);
	cs->read = cs_samsung_timer_read;
	cs->priv = pdat;

	samsung_timer_enable(pdat->virt, pdat->channel, 0);
	samsung_timer_count(pdat->virt, pdat->channel, 0xffffffff);
	samsung_timer_start(pdat->virt, pdat->channel, 0);

	if(!register_clocksource(&dev, cs))
	{
		samsung_timer_stop(pdat->virt, pdat->channel);
		samsung_timer_disable(pdat->virt, pdat->channel);
		clk_disable(pdat->clk);
		free(pdat->clk);

		free_device_name(cs->name);
		free(cs->priv);
		free(cs);
		return NULL;
	}
	dev->driver = drv;

	return dev;
}
コード例 #3
0
ファイル: clk.c プロジェクト: xboot/xboot
const char * clk_get_parent(const char * name)
{
	struct clk_t * clk = search_clk(name);

	if(clk && clk->get_parent)
		return clk->get_parent(clk);
	return NULL;
}
コード例 #4
0
ファイル: pwm-v3s.c プロジェクト: xboot/xboot
static struct device_t * pwm_v3s_probe(struct driver_t * drv, struct dtnode_t * n)
{
	struct pwm_v3s_pdata_t * pdat;
	struct pwm_t * pwm;
	struct device_t * dev;
	virtual_addr_t virt = phys_to_virt(dt_read_address(n));
	char * clk = dt_read_string(n, "clock-name", NULL);
	int channel = dt_read_int(n, "channel", -1);

	if(channel < 0 || channel > 1)
		return NULL;

	if(!search_clk(clk))
		return NULL;

	pdat = malloc(sizeof(struct pwm_v3s_pdata_t));
	if(!pdat)
		return NULL;

	pwm = malloc(sizeof(struct pwm_t));
	if(!pwm)
	{
		free(pdat);
		return NULL;
	}

	pdat->virt = virt;
	pdat->clk = strdup(clk);
	pdat->channel = channel;
	pdat->pwm = dt_read_int(n, "pwm-gpio", -1);
	pdat->pwmcfg = dt_read_int(n, "pwm-gpio-config", -1);

	pwm->name = alloc_device_name(dt_read_name(n), -1);
	pwm->config = pwm_v3s_config;
	pwm->enable = pwm_v3s_enable;
	pwm->disable = pwm_v3s_disable;
	pwm->priv = pdat;

	write32(pdat->virt + PWM_CTRL, read32(pdat->virt + PWM_CTRL) &~(0x3fff << (pdat->channel * 15)));
	write32(pdat->virt + PWM_PERIOD(pdat->channel), 0);

	if(!register_pwm(&dev, pwm))
	{
		free(pdat->clk);

		free_device_name(pwm->name);
		free(pwm->priv);
		free(pwm);
		return NULL;
	}
	dev->driver = drv;

	return dev;
}
コード例 #5
0
ファイル: wdg-s5pv210.c プロジェクト: xboot/xboot
static struct device_t * wdg_s5pv210_probe(struct driver_t * drv, struct dtnode_t * n)
{
	struct wdg_s5pv210_pdata_t * pdat;
	struct watchdog_t * wdg;
	struct device_t * dev;
	virtual_addr_t virt = phys_to_virt(dt_read_address(n));
	char * clk = dt_read_string(n, "clock-name", NULL);

	if(!search_clk(clk))
		return NULL;

	pdat = malloc(sizeof(struct wdg_s5pv210_pdata_t));
	if(!pdat)
		return NULL;

	wdg = malloc(sizeof(struct watchdog_t));
	if(!wdg)
	{
		free(pdat);
		return NULL;
	}

	pdat->virt = virt;
	pdat->clk = strdup(clk);

	wdg->name = alloc_device_name(dt_read_name(n), -1);
	wdg->set = wdg_s5pv210_set;
	wdg->get = wdg_s5pv210_get;
	wdg->priv = pdat;

	clk_enable(pdat->clk);
	write32(pdat->virt + WTCON, 0x0);
	write32(pdat->virt + WTDAT, 0x0);
	write32(pdat->virt + WTCNT, 0x0);

	if(!register_watchdog(&dev, wdg))
	{
		clk_disable(pdat->clk);
		free(pdat->clk);

		free_device_name(wdg->name);
		free(wdg->priv);
		free(wdg);
		return NULL;
	}
	dev->driver = drv;

	return dev;
}
コード例 #6
0
ファイル: clk.c プロジェクト: xboot/xboot
void clk_enable(const char * name)
{
	struct clk_t * clk = search_clk(name);

	if(!clk)
		return;

	if(clk->get_parent)
		clk_enable(clk->get_parent(clk));

	if(clk->set_enable)
		clk->set_enable(clk, TRUE);

	clk->count++;
}
コード例 #7
0
ファイル: clk.c プロジェクト: xboot/xboot
bool_t clk_status(const char * name)
{
	struct clk_t * clk = search_clk(name);

	if(!clk)
		return FALSE;

	if(!clk->get_parent(clk))
		return clk->get_enable(clk);

	if(clk->get_enable(clk))
		return clk_status(clk->get_parent(clk));

	return FALSE;
}
コード例 #8
0
ファイル: clk.c プロジェクト: xboot/xboot
void clk_set_rate(const char * name, u64_t rate)
{
	struct clk_t * clk = search_clk(name);
	u64_t prate;

	if(!clk)
		return;

	if(clk->get_parent)
		prate = clk_get_rate(clk->get_parent(clk));
	else
		prate = 0;

	if(clk->set_rate)
		clk->set_rate(clk, prate, rate);
}
コード例 #9
0
ファイル: clk.c プロジェクト: xboot/xboot
u64_t clk_get_rate(const char * name)
{
	struct clk_t * clk = search_clk(name);
	u64_t prate;

	if(!clk)
		return 0;

	if(clk->get_parent)
		prate = clk_get_rate(clk->get_parent(clk));
	else
		prate = 0;

	if(clk->get_rate)
		return clk->get_rate(clk, prate);

	return 0;
}
コード例 #10
0
ファイル: clk.c プロジェクト: xboot/xboot
void clk_disable(const char * name)
{
	struct clk_t * clk = search_clk(name);

	if(!clk)
		return;

	if(clk->count > 0)
		clk->count--;

	if(clk->count == 0)
	{
		if(clk->get_parent)
			clk_disable(clk->get_parent(clk));

		if(clk->set_enable)
			clk->set_enable(clk, FALSE);
	}
}
コード例 #11
0
ファイル: clk.c プロジェクト: xboot/xboot
bool_t register_clk(struct device_t ** device, struct clk_t * clk)
{
	struct device_t * dev;

	if(!clk || !clk->name)
		return FALSE;

	if(search_clk(clk->name))
		return FALSE;

	dev = malloc(sizeof(struct device_t));
	if(!dev)
		return FALSE;

	dev->name = strdup(clk->name);
	dev->type = DEVICE_TYPE_CLK;
	dev->driver = NULL;
	dev->priv = clk;
	dev->kobj = kobj_alloc_directory(dev->name);
	kobj_add_regular(dev->kobj, "summary", clk_read_summary, NULL, clk);
	kobj_add_regular(dev->kobj, "parent", clk_read_parent, clk_write_parent, clk);
	kobj_add_regular(dev->kobj, "enable", clk_read_enable, clk_write_enable, clk);
	kobj_add_regular(dev->kobj, "rate", clk_read_rate, clk_write_rate, clk);

	if(!register_device(dev))
	{
		kobj_remove_self(dev->kobj);
		free(dev->name);
		free(dev);
		return FALSE;
	}

	if(device)
		*device = dev;
	return TRUE;
}
コード例 #12
0
static struct device_t * ce_samsung_timer_probe(struct driver_t * drv, struct dtnode_t * n)
{
	struct ce_samsung_timer_pdata_t * pdat;
	struct clockevent_t * ce;
	struct device_t * dev;
	virtual_addr_t virt = phys_to_virt(dt_read_address(n));
	char * clk = dt_read_string(n, "clock-name", NULL);
	int irq = dt_read_int(n, "interrupt", -1);
	int channel = dt_read_int(n, "timer-channel", -1);
	u64_t rate;

	if(!search_clk(clk))
		return NULL;

	if(!irq_is_valid(irq))
		return NULL;

	if(channel < 0 || channel > 3)
		return NULL;

	pdat = malloc(sizeof(struct ce_samsung_timer_pdata_t));
	if(!pdat)
		return NULL;

	ce = malloc(sizeof(struct clockevent_t));
	if(!ce)
	{
		free(pdat);
		return NULL;
	}

	pdat->virt = virt;
	pdat->clk = strdup(clk);
	pdat->irq = irq;
	pdat->channel = channel;

	clk_enable(pdat->clk);
	rate = samsung_timer_calc_tin(pdat->virt, pdat->clk, pdat->channel, 107);
	clockevent_calc_mult_shift(ce, rate, 10);
	ce->name = alloc_device_name(dt_read_name(n), -1);
	ce->min_delta_ns = clockevent_delta2ns(ce, 0x1);
	ce->max_delta_ns = clockevent_delta2ns(ce, 0xffffffff);
	ce->next = ce_samsung_timer_next,
	ce->priv = pdat;

	if(!request_irq(pdat->irq, ce_samsung_timer_interrupt, IRQ_TYPE_NONE, ce))
	{
		clk_disable(pdat->clk);
		free(pdat->clk);

		free(ce->priv);
		free(ce);
		return NULL;
	}
	samsung_timer_enable(pdat->virt, pdat->channel, 1);
	samsung_timer_count(pdat->virt, pdat->channel, 0);
	samsung_timer_stop(pdat->virt, pdat->channel);

	if(!register_clockevent(&dev, ce))
	{
		samsung_timer_irq_clear(pdat->virt, pdat->channel);
		samsung_timer_stop(pdat->virt, pdat->channel);
		samsung_timer_disable(pdat->virt, pdat->channel);
		clk_disable(pdat->clk);
		free_irq(pdat->irq);
		free(pdat->clk);

		free_device_name(ce->name);
		free(ce->priv);
		free(ce);
		return NULL;
	}
	dev->driver = drv;

	return dev;
}
コード例 #13
0
ファイル: sdhci-v3s.c プロジェクト: xboot/xboot
static struct device_t * sdhci_v3s_probe(struct driver_t * drv, struct dtnode_t * n)
{
	struct sdhci_v3s_pdata_t * pdat;
	struct sdhci_t * sdhci;
	struct device_t * dev;
	virtual_addr_t virt = phys_to_virt(dt_read_address(n));
	char * pclk = dt_read_string(n, "clock-name", NULL);

	if(!search_clk(pclk))
		return NULL;

	pdat = malloc(sizeof(struct sdhci_v3s_pdata_t));
	if(!pdat)
		return FALSE;

	sdhci = malloc(sizeof(struct sdhci_t));
	if(!sdhci)
	{
		free(pdat);
		return FALSE;
	}

	pdat->virt = virt;
	pdat->pclk = strdup(pclk);
	pdat->reset = dt_read_int(n, "reset", -1);
	pdat->clk = dt_read_int(n, "clk-gpio", -1);
	pdat->clkcfg = dt_read_int(n, "clk-gpio-config", -1);
	pdat->cmd = dt_read_int(n, "cmd-gpio", -1);
	pdat->cmdcfg = dt_read_int(n, "cmd-gpio-config", -1);
	pdat->dat0 = dt_read_int(n, "dat0-gpio", -1);
	pdat->dat0cfg = dt_read_int(n, "dat0-gpio-config", -1);
	pdat->dat1 = dt_read_int(n, "dat1-gpio", -1);
	pdat->dat1cfg = dt_read_int(n, "dat1-gpio-config", -1);
	pdat->dat2 = dt_read_int(n, "dat2-gpio", -1);
	pdat->dat2cfg = dt_read_int(n, "dat2-gpio-config", -1);
	pdat->dat3 = dt_read_int(n, "dat3-gpio", -1);
	pdat->dat3cfg = dt_read_int(n, "dat3-gpio-config", -1);
	pdat->dat4 = dt_read_int(n, "dat4-gpio", -1);
	pdat->dat4cfg = dt_read_int(n, "dat4-gpio-config", -1);
	pdat->dat5 = dt_read_int(n, "dat5-gpio", -1);
	pdat->dat5cfg = dt_read_int(n, "dat5-gpio-config", -1);
	pdat->dat6 = dt_read_int(n, "dat6-gpio", -1);
	pdat->dat6cfg = dt_read_int(n, "dat6-gpio-config", -1);
	pdat->dat7 = dt_read_int(n, "dat7-gpio", -1);
	pdat->dat7cfg = dt_read_int(n, "dat7-gpio-config", -1);
	pdat->cd = dt_read_int(n, "cd-gpio", -1);
	pdat->cdcfg = dt_read_int(n, "cd-gpio-config", -1);

	sdhci->name = alloc_device_name(dt_read_name(n), -1);
	sdhci->voltage = MMC_VDD_27_36;
	sdhci->width = MMC_BUS_WIDTH_4;
	sdhci->clock = 52 * 1000 * 1000;
	sdhci->removable = TRUE;
	sdhci->detect = sdhci_v3s_detect;
	sdhci->setvoltage = sdhci_v3s_setvoltage;
	sdhci->setwidth = sdhci_v3s_setwidth;
	sdhci->setclock = sdhci_v3s_setclock;
	sdhci->transfer = sdhci_v3s_transfer;
	sdhci->priv = pdat;

	clk_enable(pdat->pclk);
	if(pdat->reset >= 0)
		reset_deassert(pdat->reset);

	if(pdat->clk >= 0)
	{
		if(pdat->clkcfg >= 0)
			gpio_set_cfg(pdat->clk, pdat->clkcfg);
		gpio_set_pull(pdat->clk, GPIO_PULL_UP);
	}
	if(pdat->cmd >= 0)
	{
		if(pdat->cmdcfg >= 0)
			gpio_set_cfg(pdat->cmd, pdat->cmdcfg);
		gpio_set_pull(pdat->cmd, GPIO_PULL_UP);
	}
	if(pdat->dat0 >= 0)
	{
		if(pdat->dat0cfg >= 0)
			gpio_set_cfg(pdat->dat0, pdat->dat0cfg);
		gpio_set_pull(pdat->dat0, GPIO_PULL_UP);
	}
	if(pdat->dat1 >= 0)
	{
		if(pdat->dat1cfg >= 0)
			gpio_set_cfg(pdat->dat1, pdat->dat1cfg);
		gpio_set_pull(pdat->dat1, GPIO_PULL_UP);
	}
	if(pdat->dat2 >= 0)
	{
		if(pdat->dat2cfg >= 0)
			gpio_set_cfg(pdat->dat2, pdat->dat2cfg);
		gpio_set_pull(pdat->dat2, GPIO_PULL_UP);
	}
	if(pdat->dat3 >= 0)
	{
		if(pdat->dat3cfg >= 0)
			gpio_set_cfg(pdat->dat3, pdat->dat3cfg);
		gpio_set_pull(pdat->dat3, GPIO_PULL_UP);
	}
	if(pdat->dat4 >= 0)
	{
		if(pdat->dat4cfg >= 0)
			gpio_set_cfg(pdat->dat4, pdat->dat4cfg);
		gpio_set_pull(pdat->dat4, GPIO_PULL_UP);
	}
	if(pdat->dat5 >= 0)
	{
		if(pdat->dat5cfg >= 0)
			gpio_set_cfg(pdat->dat5, pdat->dat5cfg);
		gpio_set_pull(pdat->dat5, GPIO_PULL_UP);
	}
	if(pdat->dat6 >= 0)
	{
		if(pdat->dat6cfg >= 0)
			gpio_set_cfg(pdat->dat6, pdat->dat6cfg);
		gpio_set_pull(pdat->dat6, GPIO_PULL_UP);
	}
	if(pdat->dat7 >= 0)
	{
		if(pdat->dat7cfg >= 0)
			gpio_set_cfg(pdat->dat7, pdat->dat7cfg);
		gpio_set_pull(pdat->dat7, GPIO_PULL_UP);
	}
	if(pdat->cd >= 0)
	{
		if(pdat->cdcfg >= 0)
			gpio_set_cfg(pdat->cd, pdat->cdcfg);
		gpio_set_pull(pdat->cd, GPIO_PULL_UP);
	}

	if(!register_sdhci(&dev, sdhci))
	{
		clk_disable(pdat->pclk);
		free(pdat->pclk);

		free_device_name(sdhci->name);
		free(sdhci->priv);
		free(sdhci);
		return NULL;
	}
	dev->driver = drv;

	return dev;
}
コード例 #14
0
static struct device_t * clk_mux_probe(struct driver_t * drv, struct dtnode_t * n)
{
	struct clk_mux_pdata_t * pdat;
	struct clk_mux_parent_t * parent;
	struct clk_t * clk;
	struct device_t * dev;
	struct dtnode_t o;
	virtual_addr_t virt = phys_to_virt(dt_read_address(n));
	char * name = dt_read_string(n, "name", NULL);
	int nparent = dt_read_array_length(n, "parent");
	int shift = dt_read_int(n, "shift", -1);
	int width = dt_read_int(n, "width", -1);
	int i;

	if(!name || (nparent <= 0) || (shift < 0) || (width <= 0))
		return NULL;

	if(search_clk(name))
		return NULL;

	pdat = malloc(sizeof(struct clk_mux_pdata_t));
	if(!pdat)
		return NULL;

	parent = malloc(sizeof(struct clk_mux_parent_t) * nparent);
	if(!parent)
	{
		free(pdat);
		return NULL;
	}

	clk = malloc(sizeof(struct clk_t));
	if(!clk)
	{
		free(pdat);
		free(parent);
		return NULL;
	}

	for(i = 0; i < nparent; i++)
	{
		dt_read_array_object(n, "parent", i, &o);
		parent[i].name = strdup(dt_read_string(&o, "name", NULL));
		parent[i].value = dt_read_int(&o, "value", 0);
	}

	pdat->virt = virt;
	pdat->parent = parent;
	pdat->nparent = nparent;
	pdat->shift = shift;
	pdat->width = width;

	clk->name = strdup(name);
	clk->count = 0;
	clk->set_parent = clk_mux_set_parent;
	clk->get_parent = clk_mux_get_parent;
	clk->set_enable = clk_mux_set_enable;
	clk->get_enable = clk_mux_get_enable;
	clk->set_rate = clk_mux_set_rate;
	clk->get_rate = clk_mux_get_rate;
	clk->priv = pdat;

	if(!register_clk(&dev, clk))
	{
		for(i = 0; i < pdat->nparent; i++)
			free(pdat->parent[i].name);
		free(pdat->parent);

		free(clk->name);
		free(clk->priv);
		free(clk);
		return NULL;
	}
	dev->driver = drv;

	if(dt_read_object(n, "default", &o))
	{
		char * c = clk->name;
		char * p;
		u64_t r;
		int e;

		if((p = dt_read_string(&o, "parent", NULL)) && search_clk(p))
			clk_set_parent(c, p);
		if((r = (u64_t)dt_read_long(&o, "rate", 0)) > 0)
			clk_set_rate(c, r);
		if((e = dt_read_bool(&o, "enable", -1)) != -1)
		{
			if(e > 0)
				clk_enable(c);
			else
				clk_disable(c);
		}
	}
	return dev;
}
コード例 #15
0
ファイル: clk-rk3128-gate.c プロジェクト: xboot/xboot
static struct device_t * clk_rk3128_gate_probe(struct driver_t * drv, struct dtnode_t * n)
{
	struct clk_rk3128_gate_pdata_t * pdat;
	struct clk_t * clk;
	struct device_t * dev;
	struct dtnode_t o;
	virtual_addr_t virt = phys_to_virt(dt_read_address(n));
	char * parent = dt_read_string(n, "parent", NULL);
	char * name = dt_read_string(n, "name", NULL);
	int shift = dt_read_int(n, "shift", -1);

	if(!parent || !name || (shift < 0))
		return NULL;

	if(!search_clk(parent) || search_clk(name))
		return NULL;

	pdat = malloc(sizeof(struct clk_rk3128_gate_pdata_t));
	if(!pdat)
		return NULL;

	clk = malloc(sizeof(struct clk_t));
	if(!clk)
	{
		free(pdat);
		return NULL;
	}

	pdat->virt = virt;
	pdat->parent = strdup(parent);
	pdat->shift = shift;
	pdat->invert = dt_read_bool(n, "invert", 0);

	clk->name = strdup(name);
	clk->count = 0;
	clk->set_parent = clk_rk3128_gate_set_parent;
	clk->get_parent = clk_rk3128_gate_get_parent;
	clk->set_enable = clk_rk3128_gate_set_enable;
	clk->get_enable = clk_rk3128_gate_get_enable;
	clk->set_rate = clk_rk3128_gate_set_rate;
	clk->get_rate = clk_rk3128_gate_get_rate;
	clk->priv = pdat;

	if(!register_clk(&dev, clk))
	{
		free(pdat->parent);

		free(clk->name);
		free(clk->priv);
		free(clk);
		return NULL;
	}
	dev->driver = drv;

	if(dt_read_object(n, "default", &o))
	{
		char * c = clk->name;
		char * p;
		u64_t r;
		int e;

		if((p = dt_read_string(&o, "parent", NULL)) && search_clk(p))
			clk_set_parent(c, p);
		if((r = (u64_t)dt_read_long(&o, "rate", 0)) > 0)
			clk_set_rate(c, r);
		if((e = dt_read_bool(&o, "enable", -1)) != -1)
		{
			if(e > 0)
				clk_enable(c);
			else
				clk_disable(c);
		}
	}
	return dev;
}
コード例 #16
0
ファイル: fb-f1c500s.c プロジェクト: xboot/xboot
static struct device_t * fb_f1c500s_probe(struct driver_t * drv, struct dtnode_t * n)
{
	struct fb_f1c500s_pdata_t * pdat;
	struct framebuffer_t * fb;
	struct device_t * dev;
	char * clkdefe = dt_read_string(n, "clock-name-defe", NULL);
	char * clkdebe = dt_read_string(n, "clock-name-debe", NULL);
	char * clktcon = dt_read_string(n, "clock-name-tcon", NULL);
	int i;

	if(!search_clk(clkdefe) || !search_clk(clkdebe) || !search_clk(clktcon))
		return NULL;

	pdat = malloc(sizeof(struct fb_f1c500s_pdata_t));
	if(!pdat)
		return NULL;

	fb = malloc(sizeof(struct framebuffer_t));
	if(!fb)
	{
		free(pdat);
		return NULL;
	}

	pdat->virtdefe = phys_to_virt(F1C500S_DEFE_BASE);
	pdat->virtdebe = phys_to_virt(F1C500S_DEBE_BASE);
	pdat->virttcon = phys_to_virt(F1C500S_TCON_BASE);
	pdat->virtgpio = phys_to_virt(F1C500S_GPIO_BASE);
	pdat->clkdefe = strdup(clkdefe);
	pdat->clkdebe = strdup(clkdebe);
	pdat->clktcon = strdup(clktcon);
	pdat->rstdefe = dt_read_int(n, "reset-defe", -1);
	pdat->rstdebe = dt_read_int(n, "reset-debe", -1);
	pdat->rsttcon = dt_read_int(n, "reset-tcon", -1);
	pdat->width = dt_read_int(n, "width", 320);
	pdat->height = dt_read_int(n, "height", 240);
	pdat->pwidth = dt_read_int(n, "physical-width", 216);
	pdat->pheight = dt_read_int(n, "physical-height", 135);
	pdat->bits_per_pixel = dt_read_int(n, "bits-per-pixel", 18);
	pdat->bytes_per_pixel = dt_read_int(n, "bytes-per-pixel", 4);
	pdat->index = 0;
	pdat->vram[0] = dma_alloc_noncoherent(pdat->width * pdat->height * pdat->bytes_per_pixel);
	pdat->vram[1] = dma_alloc_noncoherent(pdat->width * pdat->height * pdat->bytes_per_pixel);
	pdat->nrl = region_list_alloc(0);
	pdat->orl = region_list_alloc(0);

	pdat->timing.pixel_clock_hz = dt_read_long(n, "clock-frequency", 8000000);
	pdat->timing.h_front_porch = dt_read_int(n, "hfront-porch", 40);
	pdat->timing.h_back_porch = dt_read_int(n, "hback-porch", 87);
	pdat->timing.h_sync_len = dt_read_int(n, "hsync-len", 1);
	pdat->timing.v_front_porch = dt_read_int(n, "vfront-porch", 13);
	pdat->timing.v_back_porch = dt_read_int(n, "vback-porch", 31);
	pdat->timing.v_sync_len = dt_read_int(n, "vsync-len", 1);
	pdat->timing.h_sync_active = dt_read_bool(n, "hsync-active", 0);
	pdat->timing.v_sync_active = dt_read_bool(n, "vsync-active", 0);
	pdat->timing.den_active = dt_read_bool(n, "den-active", 0);
	pdat->timing.clk_active = dt_read_bool(n, "clk-active", 0);
	pdat->backlight = search_led(dt_read_string(n, "backlight", NULL));

	fb->name = alloc_device_name(dt_read_name(n), dt_read_id(n));
	fb->width = pdat->width;
	fb->height = pdat->height;
	fb->pwidth = pdat->pwidth;
	fb->pheight = pdat->pheight;
	fb->bytes = pdat->bytes_per_pixel;
	fb->setbl = fb_setbl;
	fb->getbl = fb_getbl;
	fb->create = fb_create;
	fb->destroy = fb_destroy;
	fb->present = fb_present;
	fb->priv = pdat;

	clk_enable(pdat->clkdefe);
	clk_enable(pdat->clkdebe);
	clk_enable(pdat->clktcon);
	if(pdat->rstdefe >= 0)
		reset_deassert(pdat->rstdefe);
	if(pdat->rstdebe >= 0)
		reset_deassert(pdat->rstdebe);
	if(pdat->rsttcon >= 0)
		reset_deassert(pdat->rsttcon);
	for(i = 0x0800; i < 0x1000; i += 4)
		write32(pdat->virtdebe + i, 0);
	fb_f1c500s_init(pdat);

	if(!register_framebuffer(&dev, fb))
	{
		clk_disable(pdat->clkdefe);
		clk_disable(pdat->clkdebe);
		clk_disable(pdat->clktcon);
		free(pdat->clkdefe);
		free(pdat->clkdebe);
		free(pdat->clktcon);
		dma_free_noncoherent(pdat->vram[0]);
		dma_free_noncoherent(pdat->vram[1]);
		region_list_free(pdat->nrl);
		region_list_free(pdat->orl);

		free_device_name(fb->name);
		free(fb->priv);
		free(fb);
		return NULL;
	}
	dev->driver = drv;

	return dev;
}
コード例 #17
0
static struct device_t * fb_rk3288_probe(struct driver_t * drv, struct dtnode_t * n)
{
	struct fb_rk3288_pdata_t * pdat;
	struct fb_t * fb;
	struct device_t * dev;
	virtual_addr_t virt = phys_to_virt(dt_read_address(n));
	char * clk = dt_read_string(n, "clock-name", NULL);

	if(!search_clk(clk))
		return NULL;

	pdat = malloc(sizeof(struct fb_rk3288_pdata_t));
	if(!pdat)
		return NULL;

	fb = malloc(sizeof(struct fb_t));
	if(!fb)
	{
		free(pdat);
		return NULL;
	}

	pdat->virtvop = virt;
	pdat->virtgrf = phys_to_virt(RK3288_GRF_BASE);
	pdat->virtlvds = phys_to_virt(RK3288_LVDS_BASE);
	pdat->lcd_avdd_3v3 = strdup(dt_read_string(n, "regulator-lcd-avdd-3v3", NULL));
	pdat->lcd_avdd_1v8 = strdup(dt_read_string(n, "regulator-lcd-avdd-1v8", NULL));
	pdat->lcd_avdd_1v0 = strdup(dt_read_string(n, "regulator-lcd-avdd-1v0", NULL));
	pdat->clk = strdup(clk);
	pdat->width = dt_read_int(n, "width", 1024);
	pdat->height = dt_read_int(n, "height", 600);
	pdat->xdpi = dt_read_int(n, "dots-per-inch-x", 160);
	pdat->ydpi = dt_read_int(n, "dots-per-inch-y", 160);
	pdat->bits_per_pixel = dt_read_int(n, "bits-per-pixel", 32);
	pdat->bytes_per_pixel = dt_read_int(n, "bytes-per-pixel", 4);
	pdat->index = 0;
	pdat->vram[0] = dma_alloc_noncoherent(pdat->width * pdat->height * pdat->bytes_per_pixel);
	pdat->vram[1] = dma_alloc_noncoherent(pdat->width * pdat->height * pdat->bytes_per_pixel);

	pdat->interface = RK3288_VOP_INTERFACE_RGB_LVDS;
	pdat->output = RK3288_LVDS_OUTPUT_RGB;
	pdat->format = RK3288_LVDS_FORMAT_JEIDA;

	pdat->mode.mirrorx = 0;
	pdat->mode.mirrory = 0;
	pdat->mode.swaprg = 0;
	pdat->mode.swaprb = 0;
	pdat->mode.swapbg = 0;

	pdat->timing.pixel_clock_hz = dt_read_long(n, "clock-frequency", 52000000);
	pdat->timing.h_front_porch = dt_read_int(n, "hfront-porch", 1);
	pdat->timing.h_back_porch = dt_read_int(n, "hback-porch", 1);
	pdat->timing.h_sync_len = dt_read_int(n, "hsync-len", 1);
	pdat->timing.v_front_porch = dt_read_int(n, "vfront-porch", 1);
	pdat->timing.v_back_porch = dt_read_int(n, "vback-porch", 1);
	pdat->timing.v_sync_len = dt_read_int(n, "vsync-len", 1);
	pdat->timing.h_sync_active = dt_read_bool(n, "hsync-active", 0);
	pdat->timing.v_sync_active = dt_read_bool(n, "vsync-active", 0);
	pdat->timing.den_active = dt_read_bool(n, "den-active", 0);
	pdat->timing.clk_active = dt_read_bool(n, "clk-active", 0);
	pdat->backlight = search_led(dt_read_string(n, "backlight", NULL));

	fb->name = alloc_device_name(dt_read_name(n), -1);
	fb->width = pdat->width;
	fb->height = pdat->height;
	fb->xdpi = pdat->xdpi;
	fb->ydpi = pdat->ydpi;
	fb->bpp = pdat->bits_per_pixel;
	fb->setbl = fb_setbl,
	fb->getbl = fb_getbl,
	fb->create = fb_create,
	fb->destroy = fb_destroy,
	fb->present = fb_present,
	fb->priv = pdat;

	regulator_set_voltage(pdat->lcd_avdd_3v3, 3300000);
	regulator_enable(pdat->lcd_avdd_3v3);
	regulator_set_voltage(pdat->lcd_avdd_1v8, 1800000);
	regulator_enable(pdat->lcd_avdd_1v8);
	regulator_set_voltage(pdat->lcd_avdd_1v0, 1000000);
	regulator_enable(pdat->lcd_avdd_1v0);
	clk_enable(pdat->clk);
	rk3288_fb_init(pdat);

	if(!register_fb(&dev, fb))
	{
		regulator_disable(pdat->lcd_avdd_3v3);
		free(pdat->lcd_avdd_3v3);
		regulator_disable(pdat->lcd_avdd_1v8);
		free(pdat->lcd_avdd_1v8);
		regulator_disable(pdat->lcd_avdd_1v0);
		free(pdat->lcd_avdd_1v0);
		clk_disable(pdat->clk);
		free(pdat->clk);
		dma_free_noncoherent(pdat->vram[0]);
		dma_free_noncoherent(pdat->vram[1]);

		free_device_name(fb->name);
		free(fb->priv);
		free(fb);
		return NULL;
	}
	dev->driver = drv;

	return dev;
}