Esempio n. 1
0
int of_read_drc_info_cell(struct property **prop, const __be32 **curval,
			struct of_drc_info *data)
{
	const char *p;
	const __be32 *p2;

	if (!data)
		return -EINVAL;

	/* Get drc-type:encode-string */
	p = data->drc_type = (char*) (*curval);
	p = of_prop_next_string(*prop, p);
	if (!p)
		return -EINVAL;

	/* Get drc-name-prefix:encode-string */
	data->drc_name_prefix = (char *)p;
	p = of_prop_next_string(*prop, p);
	if (!p)
		return -EINVAL;

	/* Get drc-index-start:encode-int */
	p2 = (const __be32 *)p;
	p2 = of_prop_next_u32(*prop, p2, &data->drc_index_start);
	if (!p2)
		return -EINVAL;

	/* Get drc-name-suffix-start:encode-int */
	p2 = of_prop_next_u32(*prop, p2, &data->drc_name_suffix_start);
	if (!p2)
		return -EINVAL;

	/* Get number-sequential-elements:encode-int */
	p2 = of_prop_next_u32(*prop, p2, &data->num_sequential_elems);
	if (!p2)
		return -EINVAL;

	/* Get sequential-increment:encode-int */
	p2 = of_prop_next_u32(*prop, p2, &data->sequential_inc);
	if (!p2)
		return -EINVAL;

	/* Get drc-power-domain:encode-int */
	p2 = of_prop_next_u32(*prop, p2, &data->drc_power_domain);
	if (!p2)
		return -EINVAL;

	/* Should now know end of current entry */
	(*curval) = (void *)p2;
	data->last_drc_index = data->drc_index_start +
		((data->num_sequential_elems - 1) * data->sequential_inc);

	return 0;
}
static void v4l2_of_parse_csi_bus(const struct device_node *node,
				  struct v4l2_of_endpoint *endpoint)
{
	struct v4l2_of_bus_mipi_csi2 *bus = &endpoint->bus.mipi_csi2;
	u32 data_lanes[ARRAY_SIZE(bus->data_lanes)];
	struct property *prop;
	bool have_clk_lane = false;
	unsigned int flags = 0;
	u32 v;

	prop = of_find_property(node, "data-lanes", NULL);
	if (prop) {
		const __be32 *lane = NULL;
		int i;

		for (i = 0; i < ARRAY_SIZE(data_lanes); i++) {
			lane = of_prop_next_u32(prop, lane, &data_lanes[i]);
			if (!lane)
				break;
		}
		bus->num_data_lanes = i;
		while (i--)
			bus->data_lanes[i] = data_lanes[i];
	}

	if (!of_property_read_u32(node, "clock-lanes", &v)) {
		bus->clock_lane = v;
		have_clk_lane = true;
	}

	if (of_get_property(node, "clock-noncontinuous", &v))
		flags |= V4L2_MBUS_CSI2_NONCONTINUOUS_CLOCK;
	else if (have_clk_lane || bus->num_data_lanes > 0)
		flags |= V4L2_MBUS_CSI2_CONTINUOUS_CLOCK;

	bus->flags = flags;
	endpoint->bus_type = V4L2_MBUS_CSI2;
}
static u32 cpu_to_drc_index(int cpu)
{
	struct device_node *dn = NULL;
	int thread_index;
	int rc = 1;
	u32 ret = 0;

	dn = of_find_node_by_path("/cpus");
	if (dn == NULL)
		goto err;

	/* Convert logical cpu number to core number */
	thread_index = cpu_core_index_of_thread(cpu);

	if (firmware_has_feature(FW_FEATURE_DRC_INFO)) {
		struct property *info = NULL;
		struct of_drc_info drc;
		int j;
		u32 num_set_entries;
		const __be32 *value;

		info = of_find_property(dn, "ibm,drc-info", NULL);
		if (info == NULL)
			goto err_of_node_put;

		value = of_prop_next_u32(info, NULL, &num_set_entries);
		if (!value)
			goto err_of_node_put;

		for (j = 0; j < num_set_entries; j++) {

			of_read_drc_info_cell(&info, &value, &drc);
			if (strncmp(drc.drc_type, "CPU", 3))
				goto err;

			if (thread_index < drc.last_drc_index)
				break;
		}

		ret = drc.drc_index_start + (thread_index * drc.sequential_inc);
	} else {
		const __be32 *indexes;

		indexes = of_get_property(dn, "ibm,drc-indexes", NULL);
		if (indexes == NULL)
			goto err_of_node_put;

		/*
		 * The first element indexes[0] is the number of drc_indexes
		 * returned in the list.  Hence thread_index+1 will get the
		 * drc_index corresponding to core number thread_index.
		 */
		ret = indexes[thread_index + 1];
	}

	rc = 0;

err_of_node_put:
	of_node_put(dn);
err:
	if (rc)
		printk(KERN_WARNING "cpu_to_drc_index(%d) failed", cpu);
	return ret;
}
static int drc_index_to_cpu(u32 drc_index)
{
	struct device_node *dn = NULL;
	const int *indexes;
	int thread_index = 0, cpu = 0;
	int rc = 1;

	dn = of_find_node_by_path("/cpus");
	if (dn == NULL)
		goto err;

	if (firmware_has_feature(FW_FEATURE_DRC_INFO)) {
		struct property *info = NULL;
		struct of_drc_info drc;
		int j;
		u32 num_set_entries;
		const __be32 *value;

		info = of_find_property(dn, "ibm,drc-info", NULL);
		if (info == NULL)
			goto err_of_node_put;

		value = of_prop_next_u32(info, NULL, &num_set_entries);
		if (!value)
			goto err_of_node_put;

		for (j = 0; j < num_set_entries; j++) {

			of_read_drc_info_cell(&info, &value, &drc);
			if (strncmp(drc.drc_type, "CPU", 3))
				goto err;

			if (drc_index > drc.last_drc_index) {
				cpu += drc.num_sequential_elems;
				continue;
			}
			cpu += ((drc_index - drc.drc_index_start) /
				drc.sequential_inc);

			thread_index = cpu_first_thread_of_core(cpu);
			rc = 0;
			break;
		}
	} else {
		unsigned long int i;

		indexes = of_get_property(dn, "ibm,drc-indexes", NULL);
		if (indexes == NULL)
			goto err_of_node_put;
		/*
		 * First element in the array is the number of drc_indexes
		 * returned.  Search through the list to find the matching
		 * drc_index and get the core number
		 */
		for (i = 0; i < indexes[0]; i++) {
			if (indexes[i + 1] == drc_index)
				break;
		}
		/* Convert core number to logical cpu number */
		thread_index = cpu_first_thread_of_core(i);
		rc = 0;
	}

err_of_node_put:
	of_node_put(dn);
err:
	if (rc)
		printk(KERN_WARNING "drc_index_to_cpu(%d) failed", drc_index);
	return thread_index;
}
Esempio n. 5
0
static int max77693_led_parse_dt(struct max77693_led_device *led,
				struct max77693_led_config_data *cfg,
				struct device_node **sub_nodes)
{
	struct device *dev = &led->pdev->dev;
	struct max77693_sub_led *sub_leds = led->sub_leds;
	struct device_node *node = dev->of_node, *child_node;
	struct property *prop;
	u32 led_sources[2];
	int i, ret, fled_id;

	of_property_read_u32(node, "maxim,boost-mode", &cfg->boost_mode);
	of_property_read_u32(node, "maxim,boost-mvout", &cfg->boost_vout);
	of_property_read_u32(node, "maxim,mvsys-min", &cfg->low_vsys);

	for_each_available_child_of_node(node, child_node) {
		prop = of_find_property(child_node, "led-sources", NULL);
		if (prop) {
			const __be32 *srcs = NULL;

			for (i = 0; i < ARRAY_SIZE(led_sources); ++i) {
				srcs = of_prop_next_u32(prop, srcs,
							&led_sources[i]);
				if (!srcs)
					break;
			}
		} else {
			dev_err(dev,
				"led-sources DT property missing\n");
			of_node_put(child_node);
			return -EINVAL;
		}

		if (i == 2) {
			fled_id = FLED1;
			led->fled_mask = FLED1_IOUT | FLED2_IOUT;
		} else if (led_sources[0] == FLED1) {
			fled_id = FLED1;
			led->fled_mask |= FLED1_IOUT;
		} else if (led_sources[0] == FLED2) {
			fled_id = FLED2;
			led->fled_mask |= FLED2_IOUT;
		} else {
			dev_err(dev,
				"Wrong led-sources DT property value.\n");
			of_node_put(child_node);
			return -EINVAL;
		}

		if (sub_nodes[fled_id]) {
			dev_err(dev,
				"Conflicting \"led-sources\" DT properties\n");
			of_node_put(child_node);
			return -EINVAL;
		}

		sub_nodes[fled_id] = child_node;
		sub_leds[fled_id].fled_id = fled_id;

		cfg->label[fled_id] =
			of_get_property(child_node, "label", NULL) ? :
						child_node->name;

		ret = of_property_read_u32(child_node, "led-max-microamp",
					&cfg->iout_torch_max[fled_id]);
		if (ret < 0) {
			cfg->iout_torch_max[fled_id] = TORCH_IOUT_MIN;
			dev_warn(dev, "led-max-microamp DT property missing\n");
		}

		ret = of_property_read_u32(child_node, "flash-max-microamp",
					&cfg->iout_flash_max[fled_id]);
		if (ret < 0) {
			cfg->iout_flash_max[fled_id] = FLASH_IOUT_MIN;
			dev_warn(dev,
				 "flash-max-microamp DT property missing\n");
		}

		ret = of_property_read_u32(child_node, "flash-max-timeout-us",
					&cfg->flash_timeout_max[fled_id]);
		if (ret < 0) {
			cfg->flash_timeout_max[fled_id] = FLASH_TIMEOUT_MIN;
			dev_warn(dev,
				 "flash-max-timeout-us DT property missing\n");
		}

		if (++cfg->num_leds == 2 ||
		    (max77693_fled_used(led, FLED1) &&
		     max77693_fled_used(led, FLED2))) {
			of_node_put(child_node);
			break;
		}
	}