Esempio n. 1
0
static int mdss_dsi_get_dt_vreg_data(struct device *dev,
	struct dss_module_power *mp, enum dsi_pm_type module)
{
	int i = 0, rc = 0;
	u32 tmp = 0;
	struct device_node *of_node = NULL, *supply_node = NULL;
	const char *pm_supply_name = NULL;
	struct device_node *supply_root_node = NULL;

	if (!dev || !mp) {
		pr_err("%s: invalid input\n", __func__);
		rc = -EINVAL;
		return rc;
	}

	of_node = dev->of_node;

	mp->num_vreg = 0;
	pm_supply_name = __mdss_dsi_pm_supply_node_name(module);
	supply_root_node = of_get_child_by_name(of_node, pm_supply_name);
	if (!supply_root_node) {
		pr_err("no supply entry present\n");
		goto novreg;
	}

	for_each_child_of_node(supply_root_node, supply_node) {
		mp->num_vreg++;
	}

	if (mp->num_vreg == 0) {
		pr_debug("%s: no vreg\n", __func__);
		goto novreg;
	} else {
		pr_debug("%s: vreg found. count=%d\n", __func__, mp->num_vreg);
	}

	mp->vreg_config = devm_kzalloc(dev, sizeof(struct dss_vreg) *
		mp->num_vreg, GFP_KERNEL);
	if (!mp->vreg_config) {
		pr_err("%s: can't alloc vreg mem\n", __func__);
		rc = -ENOMEM;
		goto error;
	}

	for_each_child_of_node(supply_root_node, supply_node) {
		const char *st = NULL;
		
		rc = of_property_read_string(supply_node,
			"qcom,supply-name", &st);
		if (rc) {
			pr_err("%s: error reading name. rc=%d\n",
				__func__, rc);
			goto error;
		}
		snprintf(mp->vreg_config[i].vreg_name,
			ARRAY_SIZE((mp->vreg_config[i].vreg_name)), "%s", st);
		
		rc = of_property_read_u32(supply_node,
			"qcom,supply-min-voltage", &tmp);
		if (rc) {
			pr_err("%s: error reading min volt. rc=%d\n",
				__func__, rc);
			goto error;
		}
		mp->vreg_config[i].min_voltage = tmp;

		
		rc = of_property_read_u32(supply_node,
			"qcom,supply-max-voltage", &tmp);
		if (rc) {
			pr_err("%s: error reading max volt. rc=%d\n",
				__func__, rc);
			goto error;
		}
		mp->vreg_config[i].max_voltage = tmp;

		
		rc = of_property_read_u32(supply_node,
			"qcom,supply-enable-load", &tmp);
		if (rc) {
			pr_err("%s: error reading enable load. rc=%d\n",
				__func__, rc);
			goto error;
		}
		mp->vreg_config[i].enable_load = tmp;

		
		rc = of_property_read_u32(supply_node,
			"qcom,supply-disable-load", &tmp);
		if (rc) {
			pr_err("%s: error reading disable load. rc=%d\n",
				__func__, rc);
			goto error;
		}
		mp->vreg_config[i].disable_load = tmp;

		
		rc = of_property_read_u32(supply_node,
			"qcom,supply-pre-on-sleep", &tmp);
		if (rc) {
			pr_debug("%s: error reading supply pre sleep value. rc=%d\n",
				__func__, rc);
			rc = 0;
		} else {
			mp->vreg_config[i].pre_on_sleep = tmp;
		}

		rc = of_property_read_u32(supply_node,
			"qcom,supply-pre-off-sleep", &tmp);
		if (rc) {
			pr_debug("%s: error reading supply pre sleep value. rc=%d\n",
				__func__, rc);
			rc = 0;
		} else {
			mp->vreg_config[i].pre_off_sleep = tmp;
		}

		
		rc = of_property_read_u32(supply_node,
			"qcom,supply-post-on-sleep", &tmp);
		if (rc) {
			pr_debug("%s: error reading supply post sleep value. rc=%d\n",
				__func__, rc);
			rc = 0;
		} else {
			mp->vreg_config[i].post_on_sleep = tmp;
		}

		rc = of_property_read_u32(supply_node,
			"qcom,supply-post-off-sleep", &tmp);
		if (rc) {
			pr_debug("%s: error reading supply post sleep value. rc=%d\n",
				__func__, rc);
			rc = 0;
		} else {
			mp->vreg_config[i].post_off_sleep = tmp;
		}

		pr_debug("%s: %s min=%d, max=%d, enable=%d, disable=%d, preonsleep=%d, postonsleep=%d, preoffsleep=%d, postoffsleep=%d\n",
			__func__,
			mp->vreg_config[i].vreg_name,
			mp->vreg_config[i].min_voltage,
			mp->vreg_config[i].max_voltage,
			mp->vreg_config[i].enable_load,
			mp->vreg_config[i].disable_load,
			mp->vreg_config[i].pre_on_sleep,
			mp->vreg_config[i].post_on_sleep,
			mp->vreg_config[i].pre_off_sleep,
			mp->vreg_config[i].post_off_sleep
			);
		++i;
	}

	return rc;

error:
	if (mp->vreg_config) {
		devm_kfree(dev, mp->vreg_config);
		mp->vreg_config = NULL;
	}
novreg:
	mp->num_vreg = 0;

	return rc;
}
Esempio n. 2
0
static int exynos5433_decon_probe(struct platform_device *pdev)
{
	const struct of_device_id *of_id;
	struct device *dev = &pdev->dev;
	struct decon_context *ctx;
	struct resource *res;
	int ret;
	int i;

	ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL);
	if (!ctx)
		return -ENOMEM;

	__set_bit(BIT_SUSPENDED, &ctx->flags);
	ctx->dev = dev;

	of_id = of_match_device(exynos5433_decon_driver_dt_match, &pdev->dev);
	ctx->out_type = (enum decon_iftype)of_id->data;

	if (ctx->out_type == IFTYPE_HDMI)
		ctx->first_win = 1;
	else if (of_get_child_by_name(dev->of_node, "i80-if-timings"))
		ctx->out_type = IFTYPE_I80;

	for (i = 0; i < ARRAY_SIZE(decon_clks_name); i++) {
		struct clk *clk;

		clk = devm_clk_get(ctx->dev, decon_clks_name[i]);
		if (IS_ERR(clk))
			return PTR_ERR(clk);

		ctx->clks[i] = clk;
	}

	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
	if (!res) {
		dev_err(dev, "cannot find IO resource\n");
		return -ENXIO;
	}

	ctx->addr = devm_ioremap_resource(dev, res);
	if (IS_ERR(ctx->addr)) {
		dev_err(dev, "ioremap failed\n");
		return PTR_ERR(ctx->addr);
	}

	res = platform_get_resource_byname(pdev, IORESOURCE_IRQ,
			(ctx->out_type == IFTYPE_I80) ? "lcd_sys" : "vsync");
	if (!res) {
		dev_err(dev, "cannot find IRQ resource\n");
		return -ENXIO;
	}

	ret = devm_request_irq(dev, res->start, decon_irq_handler, 0,
			       "drm_decon", ctx);
	if (ret < 0) {
		dev_err(dev, "lcd_sys irq request failed\n");
		return ret;
	}

	platform_set_drvdata(pdev, ctx);

	pm_runtime_enable(dev);

	ret = component_add(dev, &decon_component_ops);
	if (ret)
		goto err_disable_pm_runtime;

	return 0;

err_disable_pm_runtime:
	pm_runtime_disable(dev);

	return ret;
}
static int exynos_mipi_lli_mphy_get_setting(struct exynos_mphy *phy)
{
	struct device_node *modem_node;
	struct device_node *mphy_node = phy->dev->of_node;
	const char *modem_name;
	const __be32 *prop;

	modem_name = (char *)of_get_property(mphy_node, "modem-name", NULL);
	if (!modem_name) {
		dev_err(phy->dev, "parsing err : modem-name\n");
		goto parsing_err;
	}
	modem_node = of_get_child_by_name(mphy_node, "modems");
	if (!modem_node) {
		dev_err(phy->dev, "parsing err : modems node\n");
		goto parsing_err;
	}
	modem_node = of_get_child_by_name(modem_node, modem_name);
	if (!modem_node) {
		dev_err(phy->dev, "parsing err : modem node\n");
		goto parsing_err;
	}

	prop = of_get_property(modem_node, "init-gear", NULL);
	if (prop) {
		int value = 0;

		value = be32_to_cpu(prop[0]);
		if (value == 0x2)
			phy->default_mode = OPMODE_HS;
		else
			phy->default_mode = OPMODE_PWM;

		value = be32_to_cpu(prop[1]);
		if (value > 0x0 && value < 0x8)
			phy->default_mode |= value;
		else
			phy->default_mode |= GEAR_1;

		value = be32_to_cpu(prop[2]);
		if (value == 0x2)
			phy->default_mode |= HS_RATE_B;
		else
			phy->default_mode |= HS_RATE_A;
	}
	else {
		phy->default_mode = OPMODE_PWM | GEAR_1 | HS_RATE_A;
	}

	prop = of_get_property(modem_node, "shd-refclk", NULL);
	if (prop)
		phy->is_shared_clk = be32_to_cpup(prop) ? true : false;
	else
		phy->is_shared_clk = true;

parsing_err:
	dev_err(phy->dev, "modem_name:%s, gear:%s-G%d%s, shdclk:%d\n",
			modem_name,
			phy->default_mode & OPMODE_HS ? "HS" : "PWM",
			phy->default_mode & 0x7,
			phy->default_mode & HS_RATE_B ? "B" : "A",
			phy->is_shared_clk);
	return 0;
}
Esempio n. 4
0
static	int ti_tscadc_probe(struct platform_device *pdev)
{
	struct ti_tscadc_dev	*tscadc;
	struct resource		*res;
	struct clk		*clk;
	struct mfd_tscadc_board	*pdata = pdev->dev.platform_data;
	struct device_node	*node = pdev->dev.of_node;
	struct mfd_cell		*cell;
	int			err, ctrl;
	int			clk_value, clock_rate;
	int			tsc_wires = 0, adc_channels = 0, total_channels;

	if (!pdata && !pdev->dev.of_node) {
		dev_err(&pdev->dev, "Could not find platform data\n");
		return -EINVAL;
	}

	if (pdev->dev.platform_data) {
		if (pdata->tsc_init)
			tsc_wires = pdata->tsc_init->wires;

		if (pdata->adc_init)
			adc_channels = pdata->adc_init->adc_channels;
	} else {
		node = of_get_child_by_name(pdev->dev.of_node, "tsc");
		of_property_read_u32(node, "ti,wires", &tsc_wires);

		node = of_get_child_by_name(pdev->dev.of_node, "adc");
		of_property_read_u32(node, "ti,adc-channels", &adc_channels);
	}

	total_channels = tsc_wires + adc_channels;

	if (total_channels > 8) {
		dev_err(&pdev->dev, "Number of i/p channels more than 8\n");
		return -EINVAL;
	}

	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
	if (!res) {
		dev_err(&pdev->dev, "no memory resource defined.\n");
		return -EINVAL;
	}

	/* Allocate memory for device */
	tscadc = devm_kzalloc(&pdev->dev,
			sizeof(struct ti_tscadc_dev), GFP_KERNEL);
	if (!tscadc) {
		dev_err(&pdev->dev, "failed to allocate memory.\n");
		return -ENOMEM;
	}
	tscadc->dev = &pdev->dev;

	err = platform_get_irq(pdev, 0);
	if (err < 0) {
		dev_err(&pdev->dev, "no irq ID is specified.\n");
		goto ret;
	} else
		tscadc->irq = err;

	res = devm_request_mem_region(&pdev->dev,
			res->start, resource_size(res), pdev->name);
	if (!res) {
		dev_err(&pdev->dev, "failed to reserve registers.\n");
		return -EBUSY;
	}

	tscadc->tscadc_base = devm_ioremap(&pdev->dev,
			res->start, resource_size(res));
	if (!tscadc->tscadc_base) {
		dev_err(&pdev->dev, "failed to map registers.\n");
		return -ENOMEM;
	}

	tscadc->regmap_tscadc = devm_regmap_init_mmio(&pdev->dev,
			tscadc->tscadc_base, &tscadc_regmap_config);
	if (IS_ERR(tscadc->regmap_tscadc)) {
		dev_err(&pdev->dev, "regmap init failed\n");
		err = PTR_ERR(tscadc->regmap_tscadc);
		goto ret;
	}

	pm_runtime_enable(&pdev->dev);
	pm_runtime_get_sync(&pdev->dev);

	/*
	 * The TSC_ADC_Subsystem has 2 clock domains
	 * OCP_CLK and ADC_CLK.
	 * The ADC clock is expected to run at target of 3MHz,
	 * and expected to capture 12-bit data at a rate of 200 KSPS.
	 * The TSC_ADC_SS controller design assumes the OCP clock is
	 * at least 6x faster than the ADC clock.
	 */
	clk = clk_get(&pdev->dev, "adc_tsc_fck");
	if (IS_ERR(clk)) {
		dev_err(&pdev->dev, "failed to get TSC fck\n");
		err = PTR_ERR(clk);
		goto err_disable_clk;
	}
	clock_rate = clk_get_rate(clk);
	clk_put(clk);
	clk_value = clock_rate / ADC_CLK;
	if (clk_value < MAX_CLK_DIV) {
		dev_err(&pdev->dev, "clock input less than min clock requirement\n");
		err = -EINVAL;
		goto err_disable_clk;
	}
	/* TSCADC_CLKDIV needs to be configured to the value minus 1 */
	clk_value = clk_value - 1;
	tscadc_writel(tscadc, REG_CLKDIV, clk_value);

	/* Set the control register bits */
	ctrl = CNTRLREG_STEPCONFIGWRT |
			CNTRLREG_TSCENB |
			CNTRLREG_STEPID |
			CNTRLREG_4WIRE;
	tscadc_writel(tscadc, REG_CTRL, ctrl);

	/* Set register bits for Idle Config Mode */
	tscadc_idle_config(tscadc);

	/* Enable the TSC module enable bit */
	ctrl = tscadc_readl(tscadc, REG_CTRL);
	ctrl |= CNTRLREG_TSCSSENB;
	tscadc_writel(tscadc, REG_CTRL, ctrl);

	tscadc->used_cells = 0;
	tscadc->tsc_cell = -1;
	tscadc->adc_cell = -1;

	/* TSC Cell */
	if (tsc_wires > 0) {
		tscadc->tsc_cell = tscadc->used_cells;
		cell = &tscadc->cells[tscadc->used_cells++];
		cell->name = "tsc";
		cell->platform_data = tscadc;
		cell->pdata_size = sizeof(*tscadc);
	}

	/* ADC Cell */
	if (adc_channels > 0) {
		tscadc->adc_cell = tscadc->used_cells;
		cell = &tscadc->cells[tscadc->used_cells++];
		cell->name = "tiadc";
		cell->platform_data = tscadc;
		cell->pdata_size = sizeof(*tscadc);
	}

	err = mfd_add_devices(&pdev->dev, pdev->id, tscadc->cells,
			tscadc->used_cells, NULL, 0, NULL);
	if (err < 0)
		goto err_disable_clk;

	device_init_wakeup(&pdev->dev, true);
	platform_set_drvdata(pdev, tscadc);

	dev_info(&pdev->dev, "Initialized OK.\n");

	return 0;

err_disable_clk:
	pm_runtime_put_sync(&pdev->dev);
	pm_runtime_disable(&pdev->dev);
ret:
	return err;
}
Esempio n. 5
0
static struct apq8016_sbc_data *apq8016_sbc_parse_of(struct snd_soc_card *card)
{
	struct device *dev = card->dev;
	struct snd_soc_dai_link *link;
	struct device_node *np, *codec, *cpu, *node  = dev->of_node;
	struct apq8016_sbc_data *data;
	int ret, num_links;

	ret = snd_soc_of_parse_card_name(card, "qcom,model");
	if (ret) {
		dev_err(dev, "Error parsing card name: %d\n", ret);
		return ERR_PTR(ret);
	}

	/* DAPM routes */
	if (of_property_read_bool(node, "qcom,audio-routing")) {
		ret = snd_soc_of_parse_audio_routing(card,
					"qcom,audio-routing");
		if (ret)
			return ERR_PTR(ret);
	}


	/* Populate links */
	num_links = of_get_child_count(node);

	/* Allocate the private data and the DAI link array */
	data = devm_kzalloc(dev,
			    struct_size(data, dai_link, num_links),
			    GFP_KERNEL);
	if (!data)
		return ERR_PTR(-ENOMEM);

	card->dai_link	= &data->dai_link[0];
	card->num_links	= num_links;

	link = data->dai_link;

	for_each_child_of_node(node, np) {
		cpu = of_get_child_by_name(np, "cpu");
		codec = of_get_child_by_name(np, "codec");

		if (!cpu || !codec) {
			dev_err(dev, "Can't find cpu/codec DT node\n");
			return ERR_PTR(-EINVAL);
		}

		link->cpu_of_node = of_parse_phandle(cpu, "sound-dai", 0);
		if (!link->cpu_of_node) {
			dev_err(card->dev, "error getting cpu phandle\n");
			return ERR_PTR(-EINVAL);
		}

		ret = snd_soc_of_get_dai_name(cpu, &link->cpu_dai_name);
		if (ret) {
			dev_err(card->dev, "error getting cpu dai name\n");
			return ERR_PTR(ret);
		}

		ret = snd_soc_of_get_dai_link_codecs(dev, codec, link);

		if (ret < 0) {
			dev_err(card->dev, "error getting codec dai name\n");
			return ERR_PTR(ret);
		}

		link->platform_of_node = link->cpu_of_node;
		ret = of_property_read_string(np, "link-name", &link->name);
		if (ret) {
			dev_err(card->dev, "error getting codec dai_link name\n");
			return ERR_PTR(ret);
		}

		link->stream_name = link->name;
		link->init = apq8016_sbc_dai_init;
		link++;
	}
Esempio n. 6
0
static inline struct device_node *
of_coresight_get_output_ports_node(const struct device_node *node)
{
	return of_get_child_by_name(node, "out-ports");
}
Esempio n. 7
0
static int st_dwc3_probe(struct platform_device *pdev)
{
	struct st_dwc3 *dwc3_data;
	struct resource *res;
	struct device *dev = &pdev->dev;
	struct device_node *node = dev->of_node, *child;
	struct platform_device *child_pdev;
	struct regmap *regmap;
	int ret;

	dwc3_data = devm_kzalloc(dev, sizeof(*dwc3_data), GFP_KERNEL);
	if (!dwc3_data)
		return -ENOMEM;

	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "reg-glue");
	dwc3_data->glue_base = devm_ioremap_resource(dev, res);
	if (IS_ERR(dwc3_data->glue_base))
		return PTR_ERR(dwc3_data->glue_base);

	regmap = syscon_regmap_lookup_by_phandle(node, "st,syscfg");
	if (IS_ERR(regmap))
		return PTR_ERR(regmap);

	dwc3_data->dev = dev;
	dwc3_data->regmap = regmap;

	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "syscfg-reg");
	if (!res) {
		ret = -ENXIO;
		goto undo_platform_dev_alloc;
	}

	dwc3_data->syscfg_reg_off = res->start;

	dev_vdbg(&pdev->dev, "glue-logic addr 0x%pK, syscfg-reg offset 0x%x\n",
		 dwc3_data->glue_base, dwc3_data->syscfg_reg_off);

	dwc3_data->rstc_pwrdn =
		devm_reset_control_get_exclusive(dev, "powerdown");
	if (IS_ERR(dwc3_data->rstc_pwrdn)) {
		dev_err(&pdev->dev, "could not get power controller\n");
		ret = PTR_ERR(dwc3_data->rstc_pwrdn);
		goto undo_platform_dev_alloc;
	}

	/* Manage PowerDown */
	reset_control_deassert(dwc3_data->rstc_pwrdn);

	dwc3_data->rstc_rst =
		devm_reset_control_get_shared(dev, "softreset");
	if (IS_ERR(dwc3_data->rstc_rst)) {
		dev_err(&pdev->dev, "could not get reset controller\n");
		ret = PTR_ERR(dwc3_data->rstc_rst);
		goto undo_powerdown;
	}

	/* Manage SoftReset */
	reset_control_deassert(dwc3_data->rstc_rst);

	child = of_get_child_by_name(node, "dwc3");
	if (!child) {
		dev_err(&pdev->dev, "failed to find dwc3 core node\n");
		ret = -ENODEV;
		goto undo_softreset;
	}

	/* Allocate and initialize the core */
	ret = of_platform_populate(node, NULL, NULL, dev);
	if (ret) {
		dev_err(dev, "failed to add dwc3 core\n");
		goto undo_softreset;
	}

	child_pdev = of_find_device_by_node(child);
	if (!child_pdev) {
		dev_err(dev, "failed to find dwc3 core device\n");
		ret = -ENODEV;
		goto undo_softreset;
	}

	dwc3_data->dr_mode = usb_get_dr_mode(&child_pdev->dev);

	/*
	 * Configure the USB port as device or host according to the static
	 * configuration passed from DT.
	 * DRD is the only mode currently supported so this will be enhanced
	 * as soon as OTG is available.
	 */
	ret = st_dwc3_drd_init(dwc3_data);
	if (ret) {
		dev_err(dev, "drd initialisation failed\n");
		goto undo_softreset;
	}

	/* ST glue logic init */
	st_dwc3_init(dwc3_data);

	platform_set_drvdata(pdev, dwc3_data);
	return 0;

undo_softreset:
	reset_control_assert(dwc3_data->rstc_rst);
undo_powerdown:
	reset_control_assert(dwc3_data->rstc_pwrdn);
undo_platform_dev_alloc:
	platform_device_put(pdev);
	return ret;
}
Esempio n. 8
0
static int xylonfb_parse_layer_info(struct device_node *parent_dn,
				    struct xylonfb_data *data, int id)
{
	struct device *dev = &data->pdev->dev;
	struct device_node *dn;
	struct xylonfb_layer_fix_data *fd;
	int ret;
	char layer_name[10];
	const char *string;

	XYLONFB_DBG(INFO, "%s", __func__);

	snprintf(layer_name, sizeof(layer_name), "layer_%d", id);
	dn = of_get_child_by_name(parent_dn, layer_name);
	if (!dn)
		return 0;

	data->layers++;

	fd = devm_kzalloc(&data->pdev->dev,
			  sizeof(struct xylonfb_layer_fix_data), GFP_KERNEL);
	if (!fd) {
		dev_err(dev, "failed allocate layer fix data (%d)\n", id);
		return -ENOMEM;
	}

	data->fd[id] = fd;

	fd->id = id;

	ret = of_property_read_u32(dn, "address", &fd->address);
	if (ret && (ret != -EINVAL)) {
		dev_err(dev, "failed get address\n");
		return ret;
	}
	ret = of_property_read_u32_index(dn, "address", 1, &fd->address_range);

	ret = of_property_read_u32(dn, "buffer-offset", &fd->buffer_offset);
	if (ret && (ret != -EINVAL)) {
		dev_err(dev, "failed get buffer-offset\n");
		return ret;
	}

	ret = of_property_read_u32(dn, "bits-per-pixel", &fd->bpp);
	if (ret) {
		dev_err(dev, "failed get bits-per-pixel\n");
		return ret;
	}
	switch (fd->bpp) {
	case 8:
	case 16:
	case 32:
		break;
	default:
		dev_err(dev, "invalid bits-per-pixel value\n");
		return -EINVAL;
	}

	ret = of_property_read_string(dn, "type", &string);
	if (ret) {
		dev_err(dev, "failed get type\n");
		return ret;
	}
	if (!strcmp(string, "alpha")) {
		fd->type = LOGICVC_LAYER_ALPHA;
	} else if (!strcmp(string, "rgb")) {
		fd->type = LOGICVC_LAYER_RGB;
	} else if (!strcmp(string, "yuv")) {
		fd->type = LOGICVC_LAYER_YUV;
	} else {
		dev_err(dev, "unsupported layer type\n");
		return -EINVAL;
	}

	if (fd->type != LOGICVC_LAYER_ALPHA) {
		ret = of_property_read_string(dn, "transparency", &string);
		if (ret) {
			dev_err(dev, "failed get transparency\n");
			return ret;
		}
		if (!strcmp(string, "clut16")) {
			fd->transparency = LOGICVC_ALPHA_CLUT_16BPP;
		} else if (!strcmp(string, "clut32")) {
			fd->transparency = LOGICVC_ALPHA_CLUT_32BPP;
		} else if (!strcmp(string, "layer")) {
			fd->transparency = LOGICVC_ALPHA_LAYER;
		} else if (!strcmp(string, "pixel")) {
			fd->transparency = LOGICVC_ALPHA_PIXEL;
		} else {
			dev_err(dev, "unsupported layer transparency\n");
			return -EINVAL;
		}
	}

	if (of_property_read_bool(dn, "component-swap"))
		fd->component_swap = true;

	fd->width = data->pixel_stride;

	ret = xylonfb_layer_set_format(fd, dev);
	if (ret) {
		dev_err(dev, "failed set layer format\n");
		return ret;
	}

	of_node_put(dn);

	return id + 1;
}
Esempio n. 9
0
File: core.c Progetto: 3null/linux
static void rsnd_of_parse_dai(struct platform_device *pdev,
			      const struct rsnd_of_data *of_data,
			      struct rsnd_priv *priv)
{
	struct device_node *dai_node,	*dai_np;
	struct device_node *ssi_node,	*ssi_np;
	struct device_node *src_node,	*src_np;
	struct device_node *dvc_node,	*dvc_np;
	struct device_node *playback, *capture;
	struct rsnd_dai_platform_info *dai_info;
	struct rcar_snd_info *info = rsnd_priv_to_info(priv);
	struct device *dev = &pdev->dev;
	int nr, i;
	int dai_i, ssi_i, src_i, dvc_i;

	if (!of_data)
		return;

	dai_node = of_get_child_by_name(dev->of_node, "rcar_sound,dai");
	if (!dai_node)
		return;

	nr = of_get_child_count(dai_node);
	if (!nr)
		return;

	dai_info = devm_kzalloc(dev,
				sizeof(struct rsnd_dai_platform_info) * nr,
				GFP_KERNEL);
	if (!dai_info) {
		dev_err(dev, "dai info allocation error\n");
		return;
	}

	info->dai_info_nr	= nr;
	info->dai_info		= dai_info;

	ssi_node = of_get_child_by_name(dev->of_node, "rcar_sound,ssi");
	src_node = of_get_child_by_name(dev->of_node, "rcar_sound,src");
	dvc_node = of_get_child_by_name(dev->of_node, "rcar_sound,dvc");

#define mod_parse(name)							\
if (name##_node) {							\
	struct rsnd_##name##_platform_info *name##_info;		\
									\
	name##_i = 0;							\
	for_each_child_of_node(name##_node, name##_np) {		\
		name##_info = info->name##_info + name##_i;		\
									\
		if (name##_np == playback)				\
			dai_info->playback.name = name##_info;		\
		if (name##_np == capture)				\
			dai_info->capture.name = name##_info;		\
									\
		name##_i++;						\
	}								\
}

	/*
	 * parse all dai
	 */
	dai_i = 0;
	for_each_child_of_node(dai_node, dai_np) {
		dai_info = info->dai_info + dai_i;

		for (i = 0;; i++) {

			playback = of_parse_phandle(dai_np, "playback", i);
			capture  = of_parse_phandle(dai_np, "capture", i);

			if (!playback && !capture)
				break;

			mod_parse(ssi);
			mod_parse(src);
			mod_parse(dvc);

			of_node_put(playback);
			of_node_put(capture);
		}

		dai_i++;
	}
Esempio n. 10
0
			if (!of_property_read_u32(cp, "rockchip,saturation", &saturation)) {
				MAP(base);
				CPU_AXI_SET_QOS_SATURATION(saturation, base);
				pr_debug("qos: %s saturation %x\n", cp->name, saturation);
			}
			if (!of_property_read_u32(cp, "rockchip,extcontrol", &extcontrol)) {
				MAP(base);
				CPU_AXI_SET_QOS_EXTCONTROL(extcontrol, base);
				pr_debug("qos: %s extcontrol %x\n", cp->name, extcontrol);
			}
			if (base)
				iounmap(base);
		}
	};

	gp = of_get_child_by_name(np, "msch");
	if (gp) {
		for_each_child_of_node(gp, cp) {
			u32 val;
			base = NULL;
#ifdef DEBUG
			{
				struct resource r;
				of_address_to_resource(cp, 0, &r);
				pr_debug("msch: %s [%x ~ %x]\n", cp->name, r.start, r.end);
			}
#endif
			if (!of_property_read_u32(cp, "rockchip,read-latency", &val)) {
				MAP(base);
				writel_relaxed(val, base + 0x0014);	// memory scheduler read latency
				pr_debug("msch: %s read latency %x\n", cp->name, val);
static void palmas_dt_to_pdata(struct device *dev,
			       struct device_node *node,
			       struct palmas_pmic_platform_data *pdata,
			       struct palmas_pmic_driver_data *ddata)
{
	struct device_node *regulators;
	u32 prop;
	int idx, ret;

	regulators = of_get_child_by_name(node, "regulators");
	if (!regulators) {
		dev_info(dev, "regulator node not found\n");
		return;
	}

	ret = of_regulator_match(dev, regulators, ddata->palmas_matches,
				 ddata->max_reg);
	of_node_put(regulators);
	if (ret < 0) {
		dev_err(dev, "Error parsing regulator init data: %d\n", ret);
		return;
	}

	for (idx = 0; idx < ddata->max_reg; idx++) {
		if (!ddata->palmas_matches[idx].init_data ||
		    !ddata->palmas_matches[idx].of_node)
			continue;

		pdata->reg_data[idx] = ddata->palmas_matches[idx].init_data;

		pdata->reg_init[idx] = devm_kzalloc(dev,
				sizeof(struct palmas_reg_init), GFP_KERNEL);

		pdata->reg_init[idx]->warm_reset =
			of_property_read_bool(ddata->palmas_matches[idx].of_node,
					      "ti,warm-reset");

		ret = of_property_read_u32(ddata->palmas_matches[idx].of_node,
					   "ti,roof-floor", &prop);
		/* EINVAL: Property not found */
		if (ret != -EINVAL) {
			int econtrol;

			/* use default value, when no value is specified */
			econtrol = PALMAS_EXT_CONTROL_NSLEEP;
			if (!ret) {
				switch (prop) {
				case 1:
					econtrol = PALMAS_EXT_CONTROL_ENABLE1;
					break;
				case 2:
					econtrol = PALMAS_EXT_CONTROL_ENABLE2;
					break;
				case 3:
					econtrol = PALMAS_EXT_CONTROL_NSLEEP;
					break;
				default:
					WARN_ON(1);
					dev_warn(dev,
						 "%s: Invalid roof-floor option: %u\n",
					     palmas_matches[idx].name, prop);
					break;
				}
			}
			pdata->reg_init[idx]->roof_floor = econtrol;
		}

		ret = of_property_read_u32(ddata->palmas_matches[idx].of_node,
					   "ti,mode-sleep", &prop);
		if (!ret)
			pdata->reg_init[idx]->mode_sleep = prop;

		ret = of_property_read_bool(ddata->palmas_matches[idx].of_node,
					    "ti,smps-range");
		if (ret)
			pdata->reg_init[idx]->vsel =
				PALMAS_SMPS12_VOLTAGE_RANGE;

		if (idx == PALMAS_REG_LDO8)
			pdata->enable_ldo8_tracking = of_property_read_bool(
						ddata->palmas_matches[idx].of_node,
						"ti,enable-ldo8-tracking");
	}

	pdata->ldo6_vibrator = of_property_read_bool(node, "ti,ldo6-vibrator");
}
static int __init parse_cluster(struct device_node *cluster, int depth)
{
	char name[10];
	bool leaf = true;
	bool has_cores = false;
	struct device_node *c;
	int core_id = 0;
	int i, ret;
	static int cluster_id __initdata;

	/*
	* First check for child clusters; we currently ignore any
	* information about the nesting of clusters and present the
	* scheduler with a flat list of them.
	*/
	i = 0;
	do {
		snprintf(name, sizeof(name), "cluster%d", i);
		c = of_get_child_by_name(cluster, name);
		if (c) {
			leaf = false;
			ret = parse_cluster(c, depth + 1);
			of_node_put(c);
			if (ret != 0)
				return ret;
		}
		i++;
	} while (c);

	/* Now check for cores */
	i = 0;
	do {
		snprintf(name, sizeof(name), "core%d", i);
		c = of_get_child_by_name(cluster, name);
		if (c) {
			has_cores = true;

			if (depth == 0) {
				pr_err("%s: cpu-map children should be clusters\n",
					c->full_name);
				of_node_put(c);
				return -EINVAL;
		}

		if (leaf) {
			ret = parse_core(c, cluster_id, core_id++);
		} else {
			pr_err("%s: Non-leaf cluster with core %s\n",
				cluster->full_name, name);
			ret = -EINVAL;
		}

		of_node_put(c);
		if (ret != 0)
			return ret;
		}
		i++;
	} while (c);

	if (leaf && !has_cores)
		pr_warn("%s: empty cluster\n", cluster->full_name);

	if (leaf)
		cluster_id++;

	return 0;
}
Esempio n. 13
0
/* create a plane */
static struct xilinx_drm_plane *
xilinx_drm_plane_create(struct xilinx_drm_plane_manager *manager,
			unsigned int possible_crtcs, bool priv)
{
	struct xilinx_drm_plane *plane;
	struct device *dev = manager->drm->dev;
	char plane_name[16];
	struct device_node *plane_node;
	struct device_node *sub_node;
	uint32_t fmt_in = -1;
	uint32_t fmt_out = -1;
	const char *fmt;
	int i;
	int ret;

	for (i = 0; i < manager->num_planes; i++)
		if (!manager->planes[i])
			break;

	if (i >= manager->num_planes) {
		DRM_ERROR("failed to allocate plane\n");
		return ERR_PTR(-ENODEV);
	}

	snprintf(plane_name, sizeof(plane_name), "plane%d", i);
	plane_node = of_get_child_by_name(manager->node, plane_name);
	if (!plane_node) {
		DRM_ERROR("failed to find a plane node\n");
		return ERR_PTR(-ENODEV);
	}

	plane = devm_kzalloc(dev, sizeof(*plane), GFP_KERNEL);
	if (!plane) {
		ret = -ENOMEM;
		goto err_out;
	}

	plane->priv = priv;
	plane->id = i;
	plane->prio = i;
	plane->zpos = i;
	plane->alpha = manager->default_alpha;
	plane->dpms = DRM_MODE_DPMS_OFF;
	plane->format = -1;
	DRM_DEBUG_KMS("plane->id: %d\n", plane->id);

	plane->vdma.chan = of_dma_request_slave_channel(plane_node, "vdma");
	if (!plane->vdma.chan) {
		DRM_ERROR("failed to request dma channel\n");
		ret = -ENODEV;
		goto err_out;
	}

	/* probe color space converter */
	sub_node = of_parse_phandle(plane_node, "rgb2yuv", i);
	if (sub_node) {
		plane->rgb2yuv = xilinx_rgb2yuv_probe(dev, sub_node);
		of_node_put(sub_node);
		if (IS_ERR(plane->rgb2yuv)) {
			DRM_ERROR("failed to probe a rgb2yuv\n");
			ret = PTR_ERR(plane->rgb2yuv);
			goto err_dma;
		}

		/* rgb2yuv input format */
		plane->format = DRM_FORMAT_XRGB8888;

		/* rgb2yuv output format */
		fmt_out = DRM_FORMAT_YUV444;
	}

	/* probe chroma resampler */
	sub_node = of_parse_phandle(plane_node, "cresample", i);
	if (sub_node) {
		plane->cresample = xilinx_cresample_probe(dev, sub_node);
		of_node_put(sub_node);
		if (IS_ERR(plane->cresample)) {
			DRM_ERROR("failed to probe a cresample\n");
			ret = PTR_ERR(plane->cresample);
			goto err_dma;
		}

		/* cresample input format */
		fmt = xilinx_cresample_get_input_format_name(plane->cresample);
		ret = xilinx_drm_format_by_name(fmt, &fmt_in);
		if (ret)
			goto err_dma;

		/* format sanity check */
		if ((fmt_out != -1) && (fmt_out != fmt_in)) {
			DRM_ERROR("input/output format mismatch\n");
			ret = -EINVAL;
			goto err_dma;
		}

		if (plane->format == -1)
			plane->format = fmt_in;

		/* cresample output format */
		fmt = xilinx_cresample_get_output_format_name(plane->cresample);
		ret = xilinx_drm_format_by_name(fmt, &fmt_out);
		if (ret)
			goto err_dma;
	}

	/* create an OSD layer when OSD is available */
	if (manager->osd) {
		/* format sanity check */
		if ((fmt_out != -1) && (fmt_out != manager->format)) {
			DRM_ERROR("input/output format mismatch\n");
			ret = -EINVAL;
			goto err_dma;
		}

		/* create an osd layer */
		plane->osd_layer = xilinx_osd_layer_get(manager->osd);
		if (IS_ERR(plane->osd_layer)) {
			DRM_ERROR("failed to create a osd layer\n");
			ret = PTR_ERR(plane->osd_layer);
			plane->osd_layer = NULL;
			goto err_dma;
		}

		if (plane->format == -1)
			plane->format = manager->format;
	}

	/* If there's no IP other than VDMA, pick the manager's format */
	if (plane->format == -1)
		plane->format = manager->format;

	/* initialize drm plane */
	ret = drm_plane_init(manager->drm, &plane->base, possible_crtcs,
			     &xilinx_drm_plane_funcs, &plane->format, 1, priv);
	if (ret) {
		DRM_ERROR("failed to initialize plane\n");
		goto err_init;
	}
	plane->manager = manager;
	manager->planes[i] = plane;

	of_node_put(plane_node);

	return plane;

err_init:
	if (manager->osd) {
		xilinx_osd_layer_disable(plane->osd_layer);
		xilinx_osd_layer_put(plane->osd_layer);
	}
err_dma:
	dma_release_channel(plane->vdma.chan);
err_out:
	of_node_put(plane_node);
	return ERR_PTR(ret);
}
Esempio n. 14
0
/**
 * thermal_of_build_thermal_zone - parse and fill one thermal zone data
 * @np: DT node containing a thermal zone node
 *
 * This function parses a thermal zone type of node represented by
 * @np parameter and fills the read data into a __thermal_zone data structure
 * and return this pointer.
 *
 * TODO: Missing properties to parse: thermal-sensor-names
 *
 * Return: On success returns a valid struct __thermal_zone,
 * otherwise, it returns a corresponding ERR_PTR(). Caller must
 * check the return value with help of IS_ERR() helper.
 */
static struct __thermal_zone
__init *thermal_of_build_thermal_zone(struct device_node *np)
{
	struct device_node *child = NULL, *gchild;
	struct __thermal_zone *tz;
	int ret, i;
	u32 prop, coef[2];

	if (!np) {
		pr_err("no thermal zone np\n");
		return ERR_PTR(-EINVAL);
	}

	tz = kzalloc(sizeof(*tz), GFP_KERNEL);
	if (!tz)
		return ERR_PTR(-ENOMEM);

	ret = of_property_read_u32(np, "polling-delay-passive", &prop);
	if (ret < 0) {
		pr_err("missing polling-delay-passive property\n");
		goto free_tz;
	}
	tz->passive_delay = prop;

	ret = of_property_read_u32(np, "polling-delay", &prop);
	if (ret < 0) {
		pr_err("missing polling-delay property\n");
		goto free_tz;
	}
	tz->polling_delay = prop;

	/*
	 * REVIST: for now, the thermal framework supports only
	 * one sensor per thermal zone. Thus, we are considering
	 * only the first two values as slope and offset.
	 */
	ret = of_property_read_u32_array(np, "coefficients", coef, 2);
	if (ret == 0) {
		tz->slope = coef[0];
		tz->offset = coef[1];
	} else {
		tz->slope = 1;
		tz->offset = 0;
	}

	/* trips */
	child = of_get_child_by_name(np, "trips");

	/* No trips provided */
	if (!child)
		goto finish;

	tz->ntrips = of_get_child_count(child);
	if (tz->ntrips == 0) /* must have at least one child */
		goto finish;

	tz->trips = kcalloc(tz->ntrips, sizeof(*tz->trips), GFP_KERNEL);
	if (!tz->trips) {
		ret = -ENOMEM;
		goto free_tz;
	}

	i = 0;
	for_each_child_of_node(child, gchild) {
		ret = thermal_of_populate_trip(gchild, &tz->trips[i++]);
		if (ret)
			goto free_trips;
	}
Esempio n. 15
0
/**
 * of_get_display_timings - parse all display_timing entries from a device_node
 * @np: device_node with the subnodes
 **/
struct display_timings *of_get_display_timings(struct device_node *np)
{
	struct device_node *timings_np;
	struct device_node *entry;
	struct device_node *native_mode;
	struct display_timings *disp;

	if (!np)
		return NULL;

	timings_np = of_get_child_by_name(np, "display-timings");
	if (!timings_np) {
		pr_err("%s: could not find display-timings node\n",
			of_node_full_name(np));
		return NULL;
	}

	disp = kzalloc(sizeof(*disp), GFP_KERNEL);
	if (!disp) {
		pr_err("%s: could not allocate struct disp'\n",
			of_node_full_name(np));
		goto dispfail;
	}

	entry = of_parse_phandle(timings_np, "native-mode", 0);
	/* assume first child as native mode if none provided */
	if (!entry)
		entry = of_get_next_child(timings_np, NULL);
	/* if there is no child, it is useless to go on */
	if (!entry) {
		pr_err("%s: no timing specifications given\n",
			of_node_full_name(np));
		goto entryfail;
	}

	pr_debug("%s: using %s as default timing\n",
		of_node_full_name(np), entry->name);

	native_mode = entry;

	disp->num_timings = of_get_child_count(timings_np);
	if (disp->num_timings == 0) {
		/* should never happen, as entry was already found above */
		pr_err("%s: no timings specified\n", of_node_full_name(np));
		goto entryfail;
	}

	disp->timings = kzalloc(sizeof(struct display_timing *) *
				disp->num_timings, GFP_KERNEL);
	if (!disp->timings) {
		pr_err("%s: could not allocate timings array\n",
			of_node_full_name(np));
		goto entryfail;
	}

	disp->num_timings = 0;
	disp->native_mode = 0;

	for_each_child_of_node(timings_np, entry) {
		struct display_timing *dt;
		int r;

		dt = kzalloc(sizeof(*dt), GFP_KERNEL);
		if (!dt) {
			pr_err("%s: could not allocate display_timing struct\n",
					of_node_full_name(np));
			goto timingfail;
		}

		r = of_parse_display_timing(entry, dt);
		if (r) {
			/*
			 * to not encourage wrong devicetrees, fail in case of
			 * an error
			 */
			pr_err("%s: error in timing %d\n",
				of_node_full_name(np), disp->num_timings + 1);
			kfree(dt);
			goto timingfail;
		}

		if (native_mode == entry)
			disp->native_mode = disp->num_timings;

		disp->timings[disp->num_timings] = dt;
		disp->num_timings++;
	}
	of_node_put(timings_np);
	/*
	 * native_mode points to the device_node returned by of_parse_phandle
	 * therefore call of_node_put on it
	 */
	of_node_put(native_mode);

	pr_debug("%s: got %d timings. Using timing #%d as default\n",
		of_node_full_name(np), disp->num_timings,
		disp->native_mode + 1);

	return disp;

timingfail:
	of_node_put(native_mode);
	display_timings_release(disp);
	disp = NULL;
entryfail:
	kfree(disp);
dispfail:
	of_node_put(timings_np);
	return NULL;
}
Esempio n. 16
0
	if (!tz->trips) {
		ret = -ENOMEM;
		goto free_tz;
	}

	i = 0;
	for_each_child_of_node(child, gchild) {
		ret = thermal_of_populate_trip(gchild, &tz->trips[i++]);
		if (ret)
			goto free_trips;
	}

	of_node_put(child);

	/* cooling-maps */
	child = of_get_child_by_name(np, "cooling-maps");

	/* cooling-maps not provided */
	if (!child)
		goto finish;

	tz->num_tbps = of_get_child_count(child);
	if (tz->num_tbps == 0)
		goto finish;

	tz->tbps = kzalloc(tz->num_tbps * sizeof(*tz->tbps), GFP_KERNEL);
	if (!tz->tbps) {
		ret = -ENOMEM;
		goto free_trips;
	}
Esempio n. 17
0
static int asoc_simple_card_dai_link_of(struct device_node *node,
					struct simple_card_data *priv,
					int idx,
					bool is_top_level_node)
{
	struct device *dev = simple_priv_to_dev(priv);
	struct snd_soc_dai_link *dai_link = simple_priv_to_link(priv, idx);
	struct simple_dai_props *dai_props = simple_priv_to_props(priv, idx);
	struct asoc_simple_dai *cpu_dai = &dai_props->cpu_dai;
	struct asoc_simple_dai *codec_dai = &dai_props->codec_dai;
	struct device_node *cpu = NULL;
	struct device_node *plat = NULL;
	struct device_node *codec = NULL;
	char prop[128];
	char *prefix = "";
	int ret, single_cpu;

	/* For single DAI link & old style of DT node */
	if (is_top_level_node)
		prefix = PREFIX;

	snprintf(prop, sizeof(prop), "%scpu", prefix);
	cpu = of_get_child_by_name(node, prop);

	if (!cpu) {
		ret = -EINVAL;
		dev_err(dev, "%s: Can't find %s DT node\n", __func__, prop);
		goto dai_link_of_err;
	}

	snprintf(prop, sizeof(prop), "%splat", prefix);
	plat = of_get_child_by_name(node, prop);

	snprintf(prop, sizeof(prop), "%scodec", prefix);
	codec = of_get_child_by_name(node, prop);

	if (!codec) {
		ret = -EINVAL;
		dev_err(dev, "%s: Can't find %s DT node\n", __func__, prop);
		goto dai_link_of_err;
	}

	ret = asoc_simple_card_parse_daifmt(dev, node, codec,
					    prefix, &dai_link->dai_fmt);
	if (ret < 0)
		goto dai_link_of_err;

	of_property_read_u32(node, "mclk-fs", &dai_props->mclk_fs);

	ret = asoc_simple_card_parse_cpu(cpu, dai_link,
					 DAI, CELL, &single_cpu);
	if (ret < 0)
		goto dai_link_of_err;

	ret = asoc_simple_card_parse_codec(codec, dai_link, DAI, CELL);
	if (ret < 0)
		goto dai_link_of_err;

	ret = asoc_simple_card_parse_platform(plat, dai_link, DAI, CELL);
	if (ret < 0)
		goto dai_link_of_err;

	ret = asoc_simple_card_of_parse_tdm(cpu, cpu_dai);
	if (ret < 0)
		goto dai_link_of_err;

	ret = asoc_simple_card_of_parse_tdm(codec, codec_dai);
	if (ret < 0)
		goto dai_link_of_err;

	ret = asoc_simple_card_parse_clk_cpu(dev, cpu, dai_link, cpu_dai);
	if (ret < 0)
		goto dai_link_of_err;

	ret = asoc_simple_card_parse_clk_codec(dev, codec, dai_link, codec_dai);
	if (ret < 0)
		goto dai_link_of_err;

	ret = asoc_simple_card_canonicalize_dailink(dai_link);
	if (ret < 0)
		goto dai_link_of_err;

	ret = asoc_simple_card_set_dailink_name(dev, dai_link,
						"%s-%s",
						dai_link->cpu_dai_name,
						dai_link->codec_dai_name);
	if (ret < 0)
		goto dai_link_of_err;

	dai_link->ops = &asoc_simple_card_ops;
	dai_link->init = asoc_simple_card_dai_init;

	asoc_simple_card_canonicalize_cpu(dai_link, single_cpu);

dai_link_of_err:
	of_node_put(cpu);
	of_node_put(codec);

	return ret;
}
Esempio n. 18
0
static void of_get_regulation_constraints(struct device_node *np,
					struct regulator_init_data **init_data,
					const struct regulator_desc *desc)
{
	struct regulation_constraints *constraints = &(*init_data)->constraints;
	struct regulator_state *suspend_state;
	struct device_node *suspend_np;
	unsigned int mode;
	int ret, i, len;
	u32 pval;

	constraints->name = of_get_property(np, "regulator-name", NULL);

	if (!of_property_read_u32(np, "regulator-min-microvolt", &pval))
		constraints->min_uV = pval;

	if (!of_property_read_u32(np, "regulator-max-microvolt", &pval))
		constraints->max_uV = pval;

	/* Voltage change possible? */
	if (constraints->min_uV != constraints->max_uV)
		constraints->valid_ops_mask |= REGULATOR_CHANGE_VOLTAGE;

	/* Do we have a voltage range, if so try to apply it? */
	if (constraints->min_uV && constraints->max_uV)
		constraints->apply_uV = true;

	if (!of_property_read_u32(np, "regulator-microvolt-offset", &pval))
		constraints->uV_offset = pval;
	if (!of_property_read_u32(np, "regulator-min-microamp", &pval))
		constraints->min_uA = pval;
	if (!of_property_read_u32(np, "regulator-max-microamp", &pval))
		constraints->max_uA = pval;

	if (!of_property_read_u32(np, "regulator-input-current-limit-microamp",
				  &pval))
		constraints->ilim_uA = pval;

	/* Current change possible? */
	if (constraints->min_uA != constraints->max_uA)
		constraints->valid_ops_mask |= REGULATOR_CHANGE_CURRENT;

	constraints->boot_on = of_property_read_bool(np, "regulator-boot-on");
	constraints->always_on = of_property_read_bool(np, "regulator-always-on");
	if (!constraints->always_on) /* status change should be possible. */
		constraints->valid_ops_mask |= REGULATOR_CHANGE_STATUS;

	constraints->pull_down = of_property_read_bool(np, "regulator-pull-down");

	if (of_property_read_bool(np, "regulator-allow-bypass"))
		constraints->valid_ops_mask |= REGULATOR_CHANGE_BYPASS;

	if (of_property_read_bool(np, "regulator-allow-set-load"))
		constraints->valid_ops_mask |= REGULATOR_CHANGE_DRMS;

	ret = of_property_read_u32(np, "regulator-ramp-delay", &pval);
	if (!ret) {
		if (pval)
			constraints->ramp_delay = pval;
		else
			constraints->ramp_disable = true;
	}

	ret = of_property_read_u32(np, "regulator-settling-time-us", &pval);
	if (!ret)
		constraints->settling_time = pval;

	ret = of_property_read_u32(np, "regulator-settling-time-up-us", &pval);
	if (!ret)
		constraints->settling_time_up = pval;
	if (constraints->settling_time_up && constraints->settling_time) {
		pr_warn("%s: ambiguous configuration for settling time, ignoring 'regulator-settling-time-up-us'\n",
			np->name);
		constraints->settling_time_up = 0;
	}

	ret = of_property_read_u32(np, "regulator-settling-time-down-us",
				   &pval);
	if (!ret)
		constraints->settling_time_down = pval;
	if (constraints->settling_time_down && constraints->settling_time) {
		pr_warn("%s: ambiguous configuration for settling time, ignoring 'regulator-settling-time-down-us'\n",
			np->name);
		constraints->settling_time_down = 0;
	}

	ret = of_property_read_u32(np, "regulator-enable-ramp-delay", &pval);
	if (!ret)
		constraints->enable_time = pval;

	constraints->soft_start = of_property_read_bool(np,
					"regulator-soft-start");
	ret = of_property_read_u32(np, "regulator-active-discharge", &pval);
	if (!ret) {
		constraints->active_discharge =
				(pval) ? REGULATOR_ACTIVE_DISCHARGE_ENABLE :
					REGULATOR_ACTIVE_DISCHARGE_DISABLE;
	}

	if (!of_property_read_u32(np, "regulator-initial-mode", &pval)) {
		if (desc && desc->of_map_mode) {
			mode = desc->of_map_mode(pval);
			if (mode == REGULATOR_MODE_INVALID)
				pr_err("%s: invalid mode %u\n", np->name, pval);
			else
				constraints->initial_mode = mode;
		} else {
			pr_warn("%s: mapping for mode %d not defined\n",
				np->name, pval);
		}
	}

	len = of_property_count_elems_of_size(np, "regulator-allowed-modes",
						sizeof(u32));
	if (len > 0) {
		if (desc && desc->of_map_mode) {
			for (i = 0; i < len; i++) {
				ret = of_property_read_u32_index(np,
					"regulator-allowed-modes", i, &pval);
				if (ret) {
					pr_err("%s: couldn't read allowed modes index %d, ret=%d\n",
						np->name, i, ret);
					break;
				}
				mode = desc->of_map_mode(pval);
				if (mode == REGULATOR_MODE_INVALID)
					pr_err("%s: invalid regulator-allowed-modes element %u\n",
						np->name, pval);
				else
					constraints->valid_modes_mask |= mode;
			}
			if (constraints->valid_modes_mask)
				constraints->valid_ops_mask
					|= REGULATOR_CHANGE_MODE;
		} else {
			pr_warn("%s: mode mapping not defined\n", np->name);
		}
	}

	if (!of_property_read_u32(np, "regulator-system-load", &pval))
		constraints->system_load = pval;

	if (!of_property_read_u32(np, "regulator-coupled-max-spread",
				  &pval))
		constraints->max_spread = pval;

	constraints->over_current_protection = of_property_read_bool(np,
					"regulator-over-current-protection");

	for (i = 0; i < ARRAY_SIZE(regulator_states); i++) {
		switch (i) {
		case PM_SUSPEND_MEM:
			suspend_state = &constraints->state_mem;
			break;
		case PM_SUSPEND_MAX:
			suspend_state = &constraints->state_disk;
			break;
		case PM_SUSPEND_ON:
		case PM_SUSPEND_TO_IDLE:
		case PM_SUSPEND_STANDBY:
		default:
			continue;
		}

		suspend_np = of_get_child_by_name(np, regulator_states[i]);
		if (!suspend_np || !suspend_state)
			continue;

		if (!of_property_read_u32(suspend_np, "regulator-mode",
					  &pval)) {
			if (desc && desc->of_map_mode) {
				mode = desc->of_map_mode(pval);
				if (mode == REGULATOR_MODE_INVALID)
					pr_err("%s: invalid mode %u\n",
					       np->name, pval);
				else
					suspend_state->mode = mode;
			} else {
				pr_warn("%s: mapping for mode %d not defined\n",
					np->name, pval);
			}
		}

		if (of_property_read_bool(suspend_np,
					"regulator-on-in-suspend"))
			suspend_state->enabled = ENABLE_IN_SUSPEND;
		else if (of_property_read_bool(suspend_np,
					"regulator-off-in-suspend"))
			suspend_state->enabled = DISABLE_IN_SUSPEND;
		else
			suspend_state->enabled = DO_NOTHING_IN_SUSPEND;

		if (!of_property_read_u32(np, "regulator-suspend-min-microvolt",
					  &pval))
			suspend_state->min_uV = pval;

		if (!of_property_read_u32(np, "regulator-suspend-max-microvolt",
					  &pval))
			suspend_state->max_uV = pval;

		if (!of_property_read_u32(suspend_np,
					"regulator-suspend-microvolt", &pval))
			suspend_state->uV = pval;
		else /* otherwise use min_uV as default suspend voltage */
			suspend_state->uV = suspend_state->min_uV;

		if (of_property_read_bool(suspend_np,
					"regulator-changeable-in-suspend"))
			suspend_state->changeable = true;

		if (i == PM_SUSPEND_MEM)
			constraints->initial_state = PM_SUSPEND_MEM;

		of_node_put(suspend_np);
		suspend_state = NULL;
		suspend_np = NULL;
	}
}