示例#1
0
int asoc_simple_card_parse_dai(struct device_node *node,
				    struct device_node **dai_of_node,
				    const char **dai_name,
				    const char *list_name,
				    const char *cells_name,
				    int *is_single_link)
{
	struct of_phandle_args args;
	int ret;

	if (!node)
		return 0;

	/*
	 * Get node via "sound-dai = <&phandle port>"
	 * it will be used as xxx_of_node on soc_bind_dai_link()
	 */
	ret = of_parse_phandle_with_args(node, list_name, cells_name, 0, &args);
	if (ret)
		return ret;

	/* Get dai->name */
	if (dai_name) {
		ret = snd_soc_of_get_dai_name(node, dai_name);
		if (ret < 0)
			return ret;
	}

	*dai_of_node = args.np;

	if (is_single_link)
		*is_single_link = !args.args_count;

	return 0;
}
示例#2
0
/**
 * thermal_zone_of_sensor_register - registers a sensor to a DT thermal zone
 * @dev: a valid struct device pointer of a sensor device. Must contain
 *       a valid .of_node, for the sensor node.
 * @sensor_id: a sensor identifier, in case the sensor IP has more
 *             than one sensors
 * @data: a private pointer (owned by the caller) that will be passed
 *        back, when a temperature reading is needed.
 * @ops: struct thermal_zone_of_device_ops *. Must contain at least .get_temp.
 *
 * This function will search the list of thermal zones described in device
 * tree and look for the zone that refer to the sensor device pointed by
 * @dev->of_node as temperature providers. For the zone pointing to the
 * sensor node, the sensor will be added to the DT thermal zone device.
 *
 * The thermal zone temperature is provided by the @get_temp function
 * pointer. When called, it will have the private pointer @data back.
 *
 * The thermal zone temperature trend is provided by the @get_trend function
 * pointer. When called, it will have the private pointer @data back.
 *
 * TODO:
 * 01 - This function must enqueue the new sensor instead of using
 * it as the only source of temperature values.
 *
 * 02 - There must be a way to match the sensor with all thermal zones
 * that refer to it.
 *
 * Return: On success returns a valid struct thermal_zone_device,
 * otherwise, it returns a corresponding ERR_PTR(). Caller must
 * check the return value with help of IS_ERR() helper.
 */
struct thermal_zone_device *
thermal_zone_of_sensor_register(struct device *dev, int sensor_id, void *data,
				const struct thermal_zone_of_device_ops *ops)
{
	struct device_node *np, *child, *sensor_np;
	struct thermal_zone_device *tzd = ERR_PTR(-ENODEV);

	np = of_find_node_by_name(NULL, "thermal-zones");
	if (!np)
		return ERR_PTR(-ENODEV);

	if (!dev || !dev->of_node) {
		of_node_put(np);
		return ERR_PTR(-EINVAL);
	}

	sensor_np = of_node_get(dev->of_node);

	for_each_child_of_node(np, child) {
		struct of_phandle_args sensor_specs;
		int ret, id;

		/* Check whether child is enabled or not */
		if (!of_device_is_available(child))
			continue;

		/* For now, thermal framework supports only 1 sensor per zone */
		ret = of_parse_phandle_with_args(child, "thermal-sensors",
						 "#thermal-sensor-cells",
						 0, &sensor_specs);
		if (ret)
			continue;

		if (sensor_specs.args_count >= 1) {
			id = sensor_specs.args[0];
			WARN(sensor_specs.args_count > 1,
			     "%s: too many cells in sensor specifier %d\n",
			     sensor_specs.np->name, sensor_specs.args_count);
		} else {
			id = 0;
		}

		if (sensor_specs.np == sensor_np && id == sensor_id) {
			tzd = thermal_zone_of_add_sensor(child, sensor_np,
							 data, ops);
			if (!IS_ERR(tzd))
				tzd->ops->set_mode(tzd, THERMAL_DEVICE_ENABLED);

			of_node_put(sensor_specs.np);
			of_node_put(child);
			goto exit;
		}
		of_node_put(sensor_specs.np);
	}
exit:
	of_node_put(sensor_np);
	of_node_put(np);

	return tzd;
}
示例#3
0
文件: gdsc.c 项目: guanhe0/kernel
static int gdsc_attach(struct generic_pm_domain *domain, struct device *dev)
{
	int ret, i = 0, j = 0;
	struct gdsc *sc = domain_to_gdsc(domain);
	struct of_phandle_args clkspec;
	struct device_node *np = dev->of_node;

	if (!sc->clock_count)
		return 0;

	ret = pm_clk_create(dev);
	if (ret) {
		dev_dbg(dev, "pm_clk_create failed %d\n", ret);
		return ret;
	}

	sc->clks = devm_kcalloc(dev, sc->clock_count, sizeof(sc->clks),
				       GFP_KERNEL);
	if (!sc->clks)
		return -ENOMEM;

	while (!of_parse_phandle_with_args(np, "clocks", "#clock-cells", i,
					   &clkspec)) {
		if (match(clkspec.args[0], sc->clocks, sc->clock_count)) {
			sc->clks[j] = of_clk_get_from_provider(&clkspec);
			pm_clk_add_clk(dev, sc->clks[j]);
			j++;
		} else if (clkspec.args[0] == sc->root_clock)
			sc->root_clk = of_clk_get_from_provider(&clkspec);
		i++;
	}
	return 0;
};
示例#4
0
文件: of_gpio.c 项目: bmourit/barebox
/**
 * of_get_named_gpio_flags() - Get a GPIO number and flags to use with GPIO API
 * @np:		device node to get GPIO from
 * @propname:	property name containing gpio specifier(s)
 * @index:	index of the GPIO
 * @flags:	a flags pointer to fill in
 *
 * Returns GPIO number to use with GPIO API, or one of the errno value on the
 * error condition. If @flags is not NULL the function also fills in flags for
 * the GPIO.
 */
int of_get_named_gpio_flags(struct device_node *np, const char *propname,
			   int index, enum of_gpio_flags *flags)
{
	struct of_phandle_args out_args;
	struct device_d *dev;
	int ret;

	ret = of_parse_phandle_with_args(np, propname, "#gpio-cells",
					index, &out_args);
	if (ret) {
		pr_debug("%s: cannot parse %s property: %d\n",
			__func__, propname, ret);
		return ret;
	}

	dev = of_find_device_by_node(out_args.np);
	if (!dev) {
		pr_err("%s: unable to find device of node %s: %d\n",
			__func__, out_args.np->full_name, ret);
		return ret;
	}

	ret = gpio_get_num(dev, out_args.args[0]);
	if (ret < 0) {
		pr_err("%s: unable to get gpio num of device %s: %d\n",
			__func__, dev_name(dev), ret);
		return ret;
	}

	if (flags)
		*flags = out_args.args[1];

	return ret;
}
示例#5
0
int usbmisc_get_init_data(struct device *dev, struct usbmisc_usb_device *usbdev)
{
	struct device_node *np = dev->of_node;
	struct of_phandle_args args;
	int ret;

	usbdev->dev = dev;

	ret = of_parse_phandle_with_args(np, "fsl,usbmisc", "#index-cells",
					0, &args);
	if (ret) {
		dev_err(dev, "Failed to parse property fsl,usbmisc, errno %d\n",
			ret);
		memset(usbdev, 0, sizeof(*usbdev));
		return ret;
	}
	usbdev->index = args.args[0];
	of_node_put(args.np);

	if (of_find_property(np, "disable-over-current", NULL))
		usbdev->disable_oc = 1;

	if (of_find_property(np, "external-vbus-divider", NULL))
		usbdev->evdo = 1;

	return 0;
}
示例#6
0
static void of_gpiochip_add_pin_range(struct gpio_chip *chip)
{
	struct device_node *np = chip->of_node;
	struct of_phandle_args pinspec;
	struct pinctrl_dev *pctldev;
	int index = 0, ret;

	if (!np)
		return;

	for (;; index++) {
		ret = of_parse_phandle_with_args(np, "gpio-ranges",
				"#gpio-range-cells", index, &pinspec);
		if (ret)
			break;

		pctldev = of_pinctrl_get(pinspec.np);
		if (!pctldev)
			break;

		ret = gpiochip_add_pin_range(chip,
					     pinctrl_dev_get_devname(pctldev),
					     pinspec.args[0],
					     pinspec.args[1],
					     pinspec.args[2]);

		if (ret)
			break;
	}
}
/**
 * of_irq_parse_one - Resolve an interrupt for a device
 * @device: the device whose interrupt is to be resolved
 * @index: index of the interrupt to resolve
 * @out_irq: structure of_irq filled by this function
 *
 * This function resolves an interrupt for a node by walking the interrupt tree,
 * finding which interrupt controller node it is attached to, and returning the
 * interrupt specifier that can be used to retrieve a Linux IRQ number.
 */
int of_irq_parse_one(struct device_node *device, int index, struct of_phandle_args *out_irq)
{
	struct device_node *p;
	const __be32 *intspec, *tmp, *addr;
	u32 intsize, intlen;
	int i, res = -EINVAL;

	pr_debug("of_irq_parse_one: dev=%s, index=%d\n", of_node_full_name(device), index);

	/* OldWorld mac stuff is "special", handle out of line */
	if (of_irq_workarounds & OF_IMAP_OLDWORLD_MAC)
		return of_irq_parse_oldworld(device, index, out_irq);

	/* Get the reg property (if any) */
	addr = of_get_property(device, "reg", NULL);

	/* Get the interrupts property */
	intspec = of_get_property(device, "interrupts", &intlen);
	if (intspec == NULL) {
		/* Try the new-style interrupts-extended */
		res = of_parse_phandle_with_args(device, "interrupts-extended",
						"#interrupt-cells", index, out_irq);
		if (res)
			return -EINVAL;
		return of_irq_parse_raw(addr, out_irq);
	}
	intlen /= sizeof(*intspec);

	pr_debug(" intspec=%d intlen=%d\n", be32_to_cpup(intspec), intlen);

	/* Look for the interrupt parent. */
	p = of_irq_find_parent(device);
	if (p == NULL)
		return -EINVAL;

	/* Get size of interrupt specifier */
	tmp = of_get_property(p, "#interrupt-cells", NULL);
	if (tmp == NULL)
		goto out;
	intsize = be32_to_cpu(*tmp);

	pr_debug(" intsize=%d intlen=%d\n", intsize, intlen);

	/* Check index */
	if ((index + 1) * intsize > intlen)
		goto out;

	/* Copy intspec into irq structure */
	intspec += index * intsize;
	out_irq->np = p;
	out_irq->args_count = intsize;
	for (i = 0; i < intsize; i++)
		out_irq->args[i] = be32_to_cpup(intspec++);

	/* Check if there are any interrupt-map translations to process */
	res = of_irq_parse_raw(addr, out_irq);
 out:
	of_node_put(p);
	return res;
}
示例#8
0
文件: irq.c 项目: ilikenwf/zen-kernel
static int __init ar79_cpu_intc_of_init(
	struct device_node *node, struct device_node *parent)
{
	int err, i, count;

	/* Fill the irq_wb_chan table */
	count = of_count_phandle_with_args(
		node, "qca,ddr-wb-channels", "#qca,ddr-wb-channel-cells");

	for (i = 0; i < count; i++) {
		struct of_phandle_args args;
		u32 irq = i;

		of_property_read_u32_index(
			node, "qca,ddr-wb-channel-interrupts", i, &irq);
		if (irq >= ARRAY_SIZE(irq_wb_chan))
			continue;

		err = of_parse_phandle_with_args(
			node, "qca,ddr-wb-channels",
			"#qca,ddr-wb-channel-cells",
			i, &args);
		if (err)
			return err;

		irq_wb_chan[irq] = args.args[0];
		pr_info("IRQ: Set flush channel of IRQ%d to %d\n",
			irq, args.args[0]);
	}

	return mips_cpu_irq_of_init(node, parent);
}
示例#9
0
static int
asoc_simple_card_sub_parse_of(struct device_node *np,
                              struct asoc_simple_dai *dai,
                              struct device_node **p_node,
                              const char **name,
                              int *args_count)
{
    struct of_phandle_args args;
    struct clk *clk;
    u32 val;
    int ret;

    /*
     * Get node via "sound-dai = <&phandle port>"
     * it will be used as xxx_of_node on soc_bind_dai_link()
     */
    ret = of_parse_phandle_with_args(np, "sound-dai",
                                     "#sound-dai-cells", 0, &args);
    if (ret)
        return ret;

    *p_node = args.np;

    if (args_count)
        *args_count = args.args_count;

    /* Get dai->name */
    ret = snd_soc_of_get_dai_name(np, name);
    if (ret < 0)
        return ret;

    /* Parse TDM slot */
    ret = snd_soc_of_parse_tdm_slot(np, &dai->slots, &dai->slot_width);
    if (ret)
        return ret;

    /*
     * Parse dai->sysclk come from "clocks = <&xxx>"
     * (if system has common clock)
     *  or "system-clock-frequency = <xxx>"
     *  or device's module clock.
     */
    if (of_property_read_bool(np, "clocks")) {
        clk = of_clk_get(np, 0);
        if (IS_ERR(clk)) {
            ret = PTR_ERR(clk);
            return ret;
        }

        dai->sysclk = clk_get_rate(clk);
    } else if (!of_property_read_u32(np, "system-clock-frequency", &val)) {
        dai->sysclk = val;
    } else {
        clk = of_clk_get(args.np, 0);
        if (!IS_ERR(clk))
            dai->sysclk = clk_get_rate(clk);
    }

    return 0;
}
示例#10
0
int axidma_of_parse_dma_nodes(struct platform_device *pdev,
                              struct axidma_device *dev)
{
    int i, rc;
    int channel;
    struct of_phandle_args phandle_args;
    struct device_node *driver_node, *dma_node;

    // Get the device tree node for the driver
    driver_node = pdev->dev.of_node;

    // Initialize the channel type counts
    dev->num_dma_tx_chans = 0;
    dev->num_dma_rx_chans = 0;
    dev->num_vdma_tx_chans = 0;
    dev->num_vdma_rx_chans = 0;

    /* For each DMA channel specified in the deivce tree, parse out the
     * information about the channel, namely its direction and type. */
    for (i = 0; i < dev->num_chans; i++)
    {
        // Get the phanlde to the DMA channel
        rc = of_parse_phandle_with_args(driver_node, "dmas", "#dma-cells", i,
                                        &phandle_args);
        if (rc < 0) {
            axidma_node_err(driver_node, "Unable to get phandle %d from the "
                            "'dmas' property.\n", i);
            return rc;
        }

        // Check that the phandle has the expected arguments
        dma_node = phandle_args.np;
        channel = phandle_args.args[0];
        if (phandle_args.args_count < 1) {
            axidma_node_err(driver_node, "Phandle %d in the 'dmas' property is "
                            "is missing the channel direciton argument.\n", i);
            return -EINVAL;
        } else if (channel != 0 && channel != 1) {
            axidma_node_err(driver_node, "Phandle %d in the 'dmas' property "
                            "has an invalid channel (argument 0).\n", i);
            return -EINVAL;
        }

        // Parse out the information about the channel
        rc = axidma_of_parse_channel(dma_node, channel, &dev->channels[i], dev);
        if (rc < 0) {
            return rc;
        }

        // Parse the name of the channel
        rc = axidma_of_parse_dma_name(driver_node, i, &dev->channels[i]);
        if (rc < 0) {
            return rc;
        }
    }

    // Check that all channels have unique channel ID's
    return axidma_check_unique_ids(dev);
}
示例#11
0
文件: irq.c 项目: Lyude/linux
/**
 * of_irq_parse_one - Resolve an interrupt for a device
 * @device: the device whose interrupt is to be resolved
 * @index: index of the interrupt to resolve
 * @out_irq: structure of_irq filled by this function
 *
 * This function resolves an interrupt for a node by walking the interrupt tree,
 * finding which interrupt controller node it is attached to, and returning the
 * interrupt specifier that can be used to retrieve a Linux IRQ number.
 */
int of_irq_parse_one(struct device_node *device, int index, struct of_phandle_args *out_irq)
{
	struct device_node *p;
	const __be32 *addr;
	u32 intsize;
	int i, res;

	pr_debug("of_irq_parse_one: dev=%pOF, index=%d\n", device, index);

	/* OldWorld mac stuff is "special", handle out of line */
	if (of_irq_workarounds & OF_IMAP_OLDWORLD_MAC)
		return of_irq_parse_oldworld(device, index, out_irq);

	/* Get the reg property (if any) */
	addr = of_get_property(device, "reg", NULL);

	/* Try the new-style interrupts-extended first */
	res = of_parse_phandle_with_args(device, "interrupts-extended",
					"#interrupt-cells", index, out_irq);
	if (!res)
		return of_irq_parse_raw(addr, out_irq);

	/* Look for the interrupt parent. */
	p = of_irq_find_parent(device);
	if (p == NULL)
		return -EINVAL;

	/* Get size of interrupt specifier */
	if (of_property_read_u32(p, "#interrupt-cells", &intsize)) {
		res = -EINVAL;
		goto out;
	}

	pr_debug(" parent=%pOF, intsize=%d\n", p, intsize);

	/* Copy intspec into irq structure */
	out_irq->np = p;
	out_irq->args_count = intsize;
	for (i = 0; i < intsize; i++) {
		res = of_property_read_u32_index(device, "interrupts",
						 (index * intsize) + i,
						 out_irq->args + i);
		if (res)
			goto out;
	}

	pr_debug(" intspec=%d\n", *out_irq->args);


	/* Check if there are any interrupt-map translations to process */
	res = of_irq_parse_raw(addr, out_irq);
 out:
	of_node_put(p);
	return res;
}
示例#12
0
/**
 * thermal_of_populate_bind_params - parse and fill cooling map data
 * @np: DT node containing a cooling-map node
 * @__tbp: data structure to be filled with cooling map info
 * @trips: array of thermal zone trip points
 * @ntrips: number of trip points inside trips.
 *
 * This function parses a cooling-map type of node represented by
 * @np parameter and fills the read data into @__tbp data structure.
 * It needs the already parsed array of trip points of the thermal zone
 * in consideration.
 *
 * Return: 0 on success, proper error code otherwise
 */
static int thermal_of_populate_bind_params(struct device_node *np,
					   struct __thermal_bind_params *__tbp,
					   struct thermal_trip *trips,
					   int ntrips)
{
	struct of_phandle_args cooling_spec;
	struct device_node *trip;
	int ret, i;
	u32 prop;

	/* Default weight. Usage is optional */
	__tbp->usage = THERMAL_WEIGHT_DEFAULT;
	ret = of_property_read_u32(np, "contribution", &prop);
	if (ret == 0)
		__tbp->usage = prop;

	trip = of_parse_phandle(np, "trip", 0);
	if (!trip) {
		pr_err("missing trip property\n");
		return -ENODEV;
	}

	/* match using device_node */
	for (i = 0; i < ntrips; i++)
		if (trip == trips[i].np) {
			__tbp->trip_id = i;
			break;
		}

	if (i == ntrips) {
		ret = -ENODEV;
		goto end;
	}

	ret = of_parse_phandle_with_args(np, "cooling-device", "#cooling-cells",
					 0, &cooling_spec);
	if (ret < 0) {
		pr_err("missing cooling_device property\n");
		goto end;
	}
	__tbp->cooling_device = cooling_spec.np;
	if (cooling_spec.args_count >= 2) { /* at least min and max */
		__tbp->min = cooling_spec.args[0];
		__tbp->max = cooling_spec.args[1];
	} else {
		pr_err("wrong reference to cooling device, missing limits\n");
	}

end:
	of_node_put(trip);

	return ret;
}
示例#13
0
文件: of-thermal.c 项目: 3null/linux
/**
 * thermal_zone_of_sensor_register - registers a sensor to a DT thermal zone
 * @dev: a valid struct device pointer of a sensor device. Must contain
 *       a valid .of_node, for the sensor node.
 * @sensor_id: a sensor identifier, in case the sensor IP has more
 *             than one sensors
 * @data: a private pointer (owned by the caller) that will be passed
 *        back, when a temperature reading is needed.
 * @get_temp: a pointer to a function that reads the sensor temperature.
 * @get_trend: a pointer to a function that reads the sensor temperature trend.
 *
 * This function will search the list of thermal zones described in device
 * tree and look for the zone that refer to the sensor device pointed by
 * @dev->of_node as temperature providers. For the zone pointing to the
 * sensor node, the sensor will be added to the DT thermal zone device.
 *
 * The thermal zone temperature is provided by the @get_temp function
 * pointer. When called, it will have the private pointer @data back.
 *
 * The thermal zone temperature trend is provided by the @get_trend function
 * pointer. When called, it will have the private pointer @data back.
 *
 * TODO:
 * 01 - This function must enqueue the new sensor instead of using
 * it as the only source of temperature values.
 *
 * 02 - There must be a way to match the sensor with all thermal zones
 * that refer to it.
 *
 * Return: On success returns a valid struct thermal_zone_device,
 * otherwise, it returns a corresponding ERR_PTR(). Caller must
 * check the return value with help of IS_ERR() helper.
 */
struct thermal_zone_device *
thermal_zone_of_sensor_register(struct device *dev, int sensor_id,
				void *data, int (*get_temp)(void *, long *),
				int (*get_trend)(void *, long *))
{
	struct device_node *np, *child, *sensor_np;

	np = of_find_node_by_name(NULL, "thermal-zones");
	if (!np)
		return ERR_PTR(-ENODEV);

	if (!dev || !dev->of_node)
		return ERR_PTR(-EINVAL);

	sensor_np = dev->of_node;

	for_each_child_of_node(np, child) {
		struct of_phandle_args sensor_specs;
		int ret, id;

		/* Check whether child is enabled or not */
		if (!of_device_is_available(child))
			continue;

		/* For now, thermal framework supports only 1 sensor per zone */
		ret = of_parse_phandle_with_args(child, "thermal-sensors",
						 "#thermal-sensor-cells",
						 0, &sensor_specs);
		if (ret)
			continue;

		if (sensor_specs.args_count >= 1) {
			id = sensor_specs.args[0];
			WARN(sensor_specs.args_count > 1,
			     "%s: too many cells in sensor specifier %d\n",
			     sensor_specs.np->name, sensor_specs.args_count);
		} else {
			id = 0;
		}

		if (sensor_specs.np == sensor_np && id == sensor_id) {
			of_node_put(np);
			return thermal_zone_of_add_sensor(child, sensor_np,
							  data,
							  get_temp,
							  get_trend);
		}
	}
	of_node_put(np);

	return ERR_PTR(-ENODEV);
}
示例#14
0
int cpg_mssr_attach_dev(struct generic_pm_domain *unused, struct device *dev)
{
    struct cpg_mssr_clk_domain *pd = cpg_mssr_clk_domain;
    struct device_node *np = dev->of_node;
    struct of_phandle_args clkspec;
    struct clk *clk;
    int i = 0;
    int error;

    if (!pd) {
        dev_dbg(dev, "CPG/MSSR clock domain not yet available\n");
        return -EPROBE_DEFER;
    }

    while (!of_parse_phandle_with_args(np, "clocks", "#clock-cells", i,
                                       &clkspec)) {
        if (cpg_mssr_is_pm_clk(&clkspec, pd))
            goto found;

        of_node_put(clkspec.np);
        i++;
    }

    return 0;

found:
    clk = of_clk_get_from_provider(&clkspec);
    of_node_put(clkspec.np);

    if (IS_ERR(clk))
        return PTR_ERR(clk);

    error = pm_clk_create(dev);
    if (error) {
        dev_err(dev, "pm_clk_create failed %d\n", error);
        goto fail_put;
    }

    error = pm_clk_add_clk(dev, clk);
    if (error) {
        dev_err(dev, "pm_clk_add_clk %pC failed %d\n", clk, error);
        goto fail_destroy;
    }

    return 0;

fail_destroy:
    pm_clk_destroy(dev);
fail_put:
    clk_put(clk);
    return error;
}
示例#15
0
文件: gdsc.c 项目: guanhe0/kernel
static int clk_notify(struct notifier_block *nb, unsigned long action,
		      void *data)
{
	int sz, i = 0;
	struct device *dev = data;
	struct gdsc_notifier_block *gdsc_nb;
	struct of_phandle_args clkspec;
	struct device_node *np = dev->of_node;

	if (!of_find_property(dev->of_node, "power-domains", &sz))
		return 0;

	gdsc_nb = container_of(nb, struct gdsc_notifier_block, nb);

	if (!gdsc_nb->clock_count)
		return 0;

	switch (action) {
	case BUS_NOTIFY_BIND_DRIVER:
		while (!of_parse_phandle_with_args(np, "clocks", "#clock-cells",
						   i, &clkspec)) {
			if (match(clkspec.args[0], gdsc_nb->clocks,
				  gdsc_nb->clock_count))
				enable_clock(&clkspec);
			i++;
		}
		break;
	case BUS_NOTIFY_UNBOUND_DRIVER:
		while (!of_parse_phandle_with_args(np, "clocks", "#clock-cells",
						   i, &clkspec)) {
			if (match(clkspec.args[0], gdsc_nb->clocks,
				  gdsc_nb->clock_count))
				disable_clock(&clkspec);
			i++;
		}
		break;
	}
	return 0;
}
示例#16
0
int cpg_mstp_attach_dev(struct generic_pm_domain *unused, struct device *dev)
{
	struct device_node *np = dev->of_node;
	struct of_phandle_args clkspec;
	struct clk *clk;
	int i = 0;
	int error;

	while (!of_parse_phandle_with_args(np, "clocks", "#clock-cells", i,
					   &clkspec)) {
		if (of_device_is_compatible(clkspec.np,
					    "renesas,cpg-mstp-clocks"))
			goto found;

		/* BSC on r8a73a4/sh73a0 uses zb_clk instead of an mstp clock */
		if (of_node_name_eq(clkspec.np, "zb_clk"))
			goto found;

		of_node_put(clkspec.np);
		i++;
	}

	return 0;

found:
	clk = of_clk_get_from_provider(&clkspec);
	of_node_put(clkspec.np);

	if (IS_ERR(clk))
		return PTR_ERR(clk);

	error = pm_clk_create(dev);
	if (error) {
		dev_err(dev, "pm_clk_create failed %d\n", error);
		goto fail_put;
	}

	error = pm_clk_add_clk(dev, clk);
	if (error) {
		dev_err(dev, "pm_clk_add_clk %pC failed %d\n", clk, error);
		goto fail_destroy;
	}

	return 0;

fail_destroy:
	pm_clk_destroy(dev);
fail_put:
	clk_put(clk);
	return error;
}
示例#17
0
static int imx_chipidea_probe_dt(struct imx_chipidea *ci)
{
	struct of_phandle_args out_args;
	enum usb_dr_mode mode;

	if (of_parse_phandle_with_args(ci->dev->device_node, "fsl,usbmisc",
					"#index-cells", 0, &out_args))
		return -ENODEV;

	ci->portno = out_args.args[0];
	ci->flags = MXC_EHCI_MODE_UTMI_8BIT;

	mode = of_usb_get_dr_mode(ci->dev->device_node, NULL);

	switch (mode) {
	case USB_DR_MODE_HOST:
	default:
		ci->mode = IMX_USB_MODE_HOST;
		break;
	case USB_DR_MODE_PERIPHERAL:
		ci->mode = IMX_USB_MODE_DEVICE;
		break;
	}

	ci->phymode = of_usb_get_phy_mode(ci->dev->device_node, NULL);
	switch (ci->phymode) {
	case USBPHY_INTERFACE_MODE_UTMI:
		ci->flags = MXC_EHCI_MODE_UTMI_8BIT;
		break;
	case USBPHY_INTERFACE_MODE_UTMIW:
		ci->flags = MXC_EHCI_MODE_UTMI_16_BIT;
		break;
	case USBPHY_INTERFACE_MODE_ULPI:
		ci->flags = MXC_EHCI_MODE_ULPI;
		break;
	case USBPHY_INTERFACE_MODE_SERIAL:
		ci->flags = MXC_EHCI_MODE_SERIAL;
		break;
	case USBPHY_INTERFACE_MODE_HSIC:
		ci->flags = MXC_EHCI_MODE_HSIC;
		break;
	default:
		dev_dbg(ci->dev, "no phy_type setting. Relying on reset default\n");
	}

	if (of_find_property(ci->dev->device_node,
				"disable-over-current", NULL))
		ci->flags |= MXC_EHCI_DISABLE_OVERCURRENT;

	return 0;
}
示例#18
0
static int analog_drm_load(struct drm_device *dev, unsigned long flags)
{
	struct analog_drm_private *private;
	struct of_phandle_args dma_spec;
	struct device_node *of_node;
	int ret;

	ret = of_parse_phandle_with_args(analog_drm_pdev->dev.of_node, "dma-request", "#dma-cells",
					 0, &dma_spec);
	if (ret) {
		return ret;
	}

	private = kzalloc(sizeof(struct analog_drm_private), GFP_KERNEL);
示例#19
0
/**
 * of_gpio_count - Count GPIOs for a device
 * @np:		device node to count GPIOs for
 *
 * The function returns the count of GPIOs specified for a node.
 *
 * Note that the empty GPIO specifiers counts too. For example,
 *
 * gpios = <0
 *          &pio1 1 2
 *          0
 *          &pio2 3 4>;
 *
 * defines four GPIOs (so this function will return 4), two of which
 * are not specified.
 */
unsigned int of_gpio_count(struct device_node *np)
{
	unsigned int cnt = 0;

	do {
		int ret;

		ret = of_parse_phandle_with_args(np, "gpios", "#gpio-cells",
						 cnt, NULL);
		/* A hole in the gpios = <> counts anyway. */
		if (ret < 0 && ret != -EEXIST)
			break;
	} while (++cnt);

	return cnt;
}
示例#20
0
文件: mipi.c 项目: grate-driver/linux
struct tegra_mipi_device *tegra_mipi_request(struct device *device)
{
	struct device_node *np = device->of_node;
	struct tegra_mipi_device *dev;
	struct of_phandle_args args;
	int err;

	err = of_parse_phandle_with_args(np, "nvidia,mipi-calibrate",
					 "#nvidia,mipi-calibrate-cells", 0,
					 &args);
	if (err < 0)
		return ERR_PTR(err);

	dev = kzalloc(sizeof(*dev), GFP_KERNEL);
	if (!dev) {
		err = -ENOMEM;
		goto out;
	}

	dev->pdev = of_find_device_by_node(args.np);
	if (!dev->pdev) {
		err = -ENODEV;
		goto free;
	}

	dev->mipi = platform_get_drvdata(dev->pdev);
	if (!dev->mipi) {
		err = -EPROBE_DEFER;
		goto put;
	}

	of_node_put(args.np);

	dev->pads = args.args[0];
	dev->device = device;

	return dev;

put:
	platform_device_put(dev->pdev);
free:
	kfree(dev);
out:
	of_node_put(args.np);
	return ERR_PTR(err);
}
示例#21
0
文件: of-dma.c 项目: 24hours/linux
/**
 * of_dma_match_channel - Check if a DMA specifier matches name
 * @np:		device node to look for DMA channels
 * @name:	channel name to be matched
 * @index:	index of DMA specifier in list of DMA specifiers
 * @dma_spec:	pointer to DMA specifier as found in the device tree
 *
 * Check if the DMA specifier pointed to by the index in a list of DMA
 * specifiers, matches the name provided. Returns 0 if the name matches and
 * a valid pointer to the DMA specifier is found. Otherwise returns -ENODEV.
 */
static int of_dma_match_channel(struct device_node *np, const char *name,
				int index, struct of_phandle_args *dma_spec)
{
	const char *s;

	if (of_property_read_string_index(np, "dma-names", index, &s))
		return -ENODEV;

	if (strcmp(name, s))
		return -ENODEV;

	if (of_parse_phandle_with_args(np, "dmas", "#dma-cells", index,
				       dma_spec))
		return -ENODEV;

	return 0;
}
示例#22
0
char *of_clk_get_parent_name(struct device_node *np, unsigned int index)
{
	struct of_phandle_args clkspec;
	const char *clk_name;
	int rc;

	rc = of_parse_phandle_with_args(np, "clocks", "#clock-cells", index,
			&clkspec);
	if (rc)
		return NULL;

	if (of_property_read_string_index(clkspec.np, "clock-output-names",
				clkspec.args_count ? clkspec.args[0] : 0,
				&clk_name) < 0)
		clk_name = clkspec.np->name;

	return xstrdup(clk_name);
}
示例#23
0
/**
 * of_get_named_gpio_flags() - Get a GPIO number and flags to use with GPIO API
 * @np:		device node to get GPIO from
 * @propname:	property name containing gpio specifier(s)
 * @index:	index of the GPIO
 * @flags:	a flags pointer to fill in
 *
 * Returns GPIO number to use with Linux generic GPIO API, or one of the errno
 * value on the error condition. If @flags is not NULL the function also fills
 * in flags for the GPIO.
 */
int of_get_named_gpio_flags(struct device_node *np, const char *propname,
                           int index, enum of_gpio_flags *flags)
{
	int ret;
	struct gpio_chip *gc;
	struct of_phandle_args gpiospec;

	ret = of_parse_phandle_with_args(np, propname, "#gpio-cells", index,
					 &gpiospec);
	if (ret) {
		pr_debug("%s: can't parse gpios property\n", __func__);
		goto err0;
	}

	gc = of_node_to_gpiochip(gpiospec.np);
	if (!gc) {
		pr_debug("%s: gpio controller %s isn't registered\n",
			 np->full_name, gpiospec.np->full_name);
		ret = -ENODEV;
		goto err1;
	}

	if (gpiospec.args_count != gc->of_gpio_n_cells) {
		pr_debug("%s: wrong #gpio-cells for %s\n",
			 np->full_name, gpiospec.np->full_name);
		ret = -EINVAL;
		goto err1;
	}

	/* .xlate might decide to not fill in the flags, so clear it. */
	if (flags)
		*flags = 0;

	ret = gc->of_xlate(gc, &gpiospec, flags);
	if (ret < 0)
		goto err1;

	ret += gc->base;
err1:
	of_node_put(gpiospec.np);
err0:
	pr_debug("%s exited with status %d\n", __func__, ret);
	return ret;
}
示例#24
0
static int of_get_dml_pipe_index(struct device_node *np, const char *name)
{
	int index;
	struct of_phandle_args	dma_spec;

	index = of_property_match_string(np, "dma-names", name);

	if (index < 0)
		return -ENODEV;

	if (of_parse_phandle_with_args(np, "dmas", "#dma-cells", index,
				       &dma_spec))
		return -ENODEV;

	if (dma_spec.args_count)
		return dma_spec.args[0];

	return -ENODEV;
}
示例#25
0
static void of_gpiochip_add_pin_range(struct gpio_chip *chip)
{
	struct device_node *np = chip->of_node;
	struct of_phandle_args pinspec;
	struct pinctrl_dev *pctldev;
	int index = 0, ret;

	if (!np)
		return;

	do {
		ret = of_parse_phandle_with_args(np, "gpio-ranges",
				"#gpio-range-cells", index, &pinspec);
		if (ret)
			break;

		pctldev = of_pinctrl_get(pinspec.np);
		if (!pctldev)
			break;

		/*
		 * This assumes that the n GPIO pins are consecutive in the
		 * GPIO number space, and that the pins are also consecutive
		 * in their local number space. Currently it is not possible
		 * to add different ranges for one and the same GPIO chip,
		 * as the code assumes that we have one consecutive range
		 * on both, mapping 1-to-1.
		 *
		 * TODO: make the OF bindings handle multiple sparse ranges
		 * on the same GPIO chip.
		 */
		ret = gpiochip_add_pin_range(chip,
					     pinctrl_dev_get_name(pctldev),
					     0, /* offset in gpiochip */
					     pinspec.args[0],
					     pinspec.args[1]);

		if (ret)
			break;

	} while (index++);
}
static int highbank_initialize_phys(struct device *dev, void __iomem *addr)
{
	struct device_node *sata_node = dev->of_node;
	int phy_count = 0, phy, port = 0, i;
	void __iomem *cphy_base[CPHY_PHY_COUNT] = {};
	struct device_node *phy_nodes[CPHY_PHY_COUNT] = {};
	u32 tx_atten[CPHY_PORT_COUNT] = {};

	memset(port_data, 0, sizeof(struct phy_lane_info) * CPHY_PORT_COUNT);

	do {
		u32 tmp;
		struct of_phandle_args phy_data;
		if (of_parse_phandle_with_args(sata_node,
				"calxeda,port-phys", "#phy-cells",
				port, &phy_data))
			break;
		for (phy = 0; phy < phy_count; phy++) {
			if (phy_nodes[phy] == phy_data.np)
				break;
		}
		if (phy_nodes[phy] == NULL) {
			phy_nodes[phy] = phy_data.np;
			cphy_base[phy] = of_iomap(phy_nodes[phy], 0);
			if (cphy_base[phy] == NULL) {
				return 0;
			}
			phy_count += 1;
		}
		port_data[port].lane_mapping = phy_data.args[0];
		of_property_read_u32(phy_nodes[phy], "phydev", &tmp);
		port_data[port].phy_devs = tmp;
		port_data[port].phy_base = cphy_base[phy];
		of_node_put(phy_data.np);
		port += 1;
	} while (port < CPHY_PORT_COUNT);
	of_property_read_u32_array(sata_node, "calxeda,tx-atten",
				tx_atten, port);
	for (i = 0; i < port; i++)
		port_data[i].tx_atten = (u8) tx_atten[i];
	return 0;
}
示例#27
0
文件: common.c 项目: AK101111/linux
/**
 * of_usb_get_dr_mode_by_phy - Get dual role mode for the controller device
 * which is associated with the given phy device_node
 * @np:	Pointer to the given phy device_node
 * @arg0: phandle args[0] for phy's with #phy-cells >= 1, or -1 for
 *        phys which do not have phy-cells
 *
 * In dts a usb controller associates with phy devices.  The function gets
 * the string from property 'dr_mode' of the controller associated with the
 * given phy device node, and returns the correspondig enum usb_dr_mode.
 */
enum usb_dr_mode of_usb_get_dr_mode_by_phy(struct device_node *np, int arg0)
{
	struct device_node *controller = NULL;
	struct of_phandle_args args;
	const char *dr_mode;
	int index;
	int err;

	do {
		controller = of_find_node_with_property(controller, "phys");
		index = 0;
		do {
			if (arg0 == -1) {
				args.np = of_parse_phandle(controller, "phys",
							index);
				args.args_count = 0;
			} else {
				err = of_parse_phandle_with_args(controller,
							"phys", "#phy-cells",
							index, &args);
				if (err)
					break;
			}

			of_node_put(args.np);
			if (args.np == np && (args.args_count == 0 ||
					      args.args[0] == arg0))
				goto finish;
			index++;
		} while (args.np);
	} while (controller);

finish:
	err = of_property_read_string(controller, "dr_mode", &dr_mode);
	of_node_put(controller);

	if (err < 0)
		return USB_DR_MODE_UNKNOWN;

	return usb_get_dr_mode_from_string(dr_mode);
}
示例#28
0
static int bcm63xx_pmb_get_resources(struct device_node *dn,
				     void __iomem **base,
				     unsigned int *cpu,
				     unsigned int *addr)
{
	struct device_node *pmb_dn;
	struct of_phandle_args args;
	int ret;

	ret = of_property_read_u32(dn, "reg", cpu);
	if (ret) {
		pr_err("CPU is missing a reg node\n");
		return ret;
	}

	ret = of_parse_phandle_with_args(dn, "resets", "#reset-cells",
					 0, &args);
	if (ret) {
		pr_err("CPU is missing a resets phandle\n");
		return ret;
	}

	pmb_dn = args.np;
	if (args.args_count != 2) {
		pr_err("reset-controller does not conform to reset-cells\n");
		return -EINVAL;
	}

	*base = of_iomap(args.np, 0);
	if (!*base) {
		pr_err("failed remapping PMB register\n");
		return -ENOMEM;
	}

	/* We do not need the number of zones */
	*addr = args.args[0];

	return 0;
}
static struct imx_usbmisc_data *usbmisc_get_init_data(struct device *dev)
{
	struct device_node *np = dev->of_node;
	struct of_phandle_args args;
	struct imx_usbmisc_data *data;
	int ret;

	/*
	 * In case the fsl,usbmisc property is not present this device doesn't
	 * need usbmisc. Return NULL (which is no error here)
	 */
	if (!of_get_property(np, "fsl,usbmisc", NULL))
		return NULL;

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

	ret = of_parse_phandle_with_args(np, "fsl,usbmisc", "#index-cells",
					0, &args);
	if (ret) {
		dev_err(dev, "Failed to parse property fsl,usbmisc, errno %d\n",
			ret);
		return ERR_PTR(ret);
	}

	data->index = args.args[0];
	of_node_put(args.np);

	if (of_find_property(np, "disable-over-current", NULL))
		data->disable_oc = 1;

	if (of_find_property(np, "external-vbus-divider", NULL))
		data->evdo = 1;

	return data;
}
static void __init of_selftest_parse_phandle_with_args(void)
{
	struct device_node *np;
	struct of_phandle_args args;
	int rc, i;
	bool passed_all = true;

	pr_info("start\n");
	np = of_find_node_by_path("/testcase-data/phandle-tests/consumer-a");
	if (!np) {
		pr_err("missing testcase data\n");
		return;
	}

	for (i = 0; i < 7; i++) {
		bool passed = true;
		rc = of_parse_phandle_with_args(np, "phandle-list",
						"#phandle-cells", i, &args);

		/* Test the values from tests-phandle.dtsi */
		switch (i) {
		case 0:
			passed &= !rc;
			passed &= (args.args_count == 1);
			passed &= (args.args[0] == (i + 1));
			break;
		case 1:
			passed &= !rc;
			passed &= (args.args_count == 2);
			passed &= (args.args[0] == (i + 1));
			passed &= (args.args[1] == 0);
			break;
		case 2:
			passed &= (rc == -ENOENT);
			break;
		case 3:
			passed &= !rc;
			passed &= (args.args_count == 3);
			passed &= (args.args[0] == (i + 1));
			passed &= (args.args[1] == 4);
			passed &= (args.args[2] == 3);
			break;
		case 4:
			passed &= !rc;
			passed &= (args.args_count == 2);
			passed &= (args.args[0] == (i + 1));
			passed &= (args.args[1] == 100);
			break;
		case 5:
			passed &= !rc;
			passed &= (args.args_count == 0);
			break;
		case 6:
			passed &= !rc;
			passed &= (args.args_count == 1);
			passed &= (args.args[0] == (i + 1));
			break;
		case 7:
			passed &= (rc == -EINVAL);
			break;
		default:
			passed = false;
		}

		if (!passed) {
			int j;
			pr_err("index %i - data error on node %s rc=%i regs=[",
				i, args.np->full_name, rc);
			for (j = 0; j < args.args_count; j++)
				printk(" %i", args.args[j]);
			printk(" ]\n");

			passed_all = false;
		}
	}

	/* Check for missing list property */
	rc = of_parse_phandle_with_args(np, "phandle-list-missing",
					"#phandle-cells", 0, &args);
	passed_all &= (rc == -EINVAL);

	/* Check for missing cells property */
	rc = of_parse_phandle_with_args(np, "phandle-list",
					"#phandle-cells-missing", 0, &args);
	passed_all &= (rc == -EINVAL);

	/* Check for bad phandle in list */
	rc = of_parse_phandle_with_args(np, "phandle-list-bad-phandle",
					"#phandle-cells", 0, &args);
	passed_all &= (rc == -EINVAL);

	/* Check for incorrectly formed argument list */
	rc = of_parse_phandle_with_args(np, "phandle-list-bad-args",
					"#phandle-cells", 1, &args);
	passed_all &= (rc == -EINVAL);

	pr_info("end - %s\n", passed_all ? "PASS" : "FAIL");
}