Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 9fd04992 authored by Grant Likely's avatar Grant Likely
Browse files

of/i2c: Generalize OF support



This patch cleans up the i2c OF support code to make it selectable by
all architectures and allow for automatic registration of i2c devices.

Signed-off-by: default avatarGrant Likely <grant.likely@secretlab.ca>
parent 4f0ddcb0
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -652,6 +652,7 @@ static int __devinit cpm_i2c_probe(struct of_device *ofdev,
	cpm->adap = cpm_ops;
	i2c_set_adapdata(&cpm->adap, cpm);
	cpm->adap.dev.parent = &ofdev->dev;
	cpm->adap.dev.of_node = of_node_get(ofdev->dev.of_node);

	result = cpm_i2c_setup(cpm);
	if (result) {
@@ -679,7 +680,7 @@ static int __devinit cpm_i2c_probe(struct of_device *ofdev,
	/*
	 * register OF I2C devices
	 */
	of_register_i2c_devices(&cpm->adap, ofdev->dev.of_node);
	of_i2c_register_devices(&cpm->adap);

	return 0;
out_shut:
+2 −1
Original line number Diff line number Diff line
@@ -745,6 +745,7 @@ static int __devinit iic_probe(struct of_device *ofdev,
	/* Register it with i2c layer */
	adap = &dev->adap;
	adap->dev.parent = &ofdev->dev;
	adap->dev.of_node = of_node_get(np);
	strlcpy(adap->name, "IBM IIC", sizeof(adap->name));
	i2c_set_adapdata(adap, dev);
	adap->class = I2C_CLASS_HWMON | I2C_CLASS_SPD;
@@ -761,7 +762,7 @@ static int __devinit iic_probe(struct of_device *ofdev,
		 dev->fast_mode ? "fast (400 kHz)" : "standard (100 kHz)");

	/* Now register all the child nodes */
	of_register_i2c_devices(adap, np);
	of_i2c_register_devices(adap);

	return 0;

+2 −1
Original line number Diff line number Diff line
@@ -600,13 +600,14 @@ static int __devinit fsl_i2c_probe(struct of_device *op,
	i2c->adap = mpc_ops;
	i2c_set_adapdata(&i2c->adap, i2c);
	i2c->adap.dev.parent = &op->dev;
	i2c->adap.dev.of_node = of_node_get(op->dev.of_node);

	result = i2c_add_adapter(&i2c->adap);
	if (result < 0) {
		dev_err(i2c->dev, "failed to add adapter\n");
		goto fail_add;
	}
	of_register_i2c_devices(&i2c->adap, op->dev.of_node);
	of_i2c_register_devices(&i2c->adap);

	return result;

+1 −1
Original line number Diff line number Diff line
@@ -26,7 +26,7 @@ config OF_GPIO

config OF_I2C
	def_tristate I2C
	depends on (PPC_OF || MICROBLAZE) && I2C
	depends on OF && !SPARC && I2C
	help
	  OpenFirmware I2C accessors

+29 −21
Original line number Diff line number Diff line
@@ -14,57 +14,65 @@
#include <linux/i2c.h>
#include <linux/of.h>
#include <linux/of_i2c.h>
#include <linux/of_irq.h>
#include <linux/module.h>

void of_register_i2c_devices(struct i2c_adapter *adap,
			     struct device_node *adap_node)
void of_i2c_register_devices(struct i2c_adapter *adap)
{
	void *result;
	struct device_node *node;

	for_each_child_of_node(adap_node, node) {
	/* Only register child devices if the adapter has a node pointer set */
	if (!adap->dev.of_node)
		return;

	dev_dbg(&adap->dev, "of_i2c: walking child nodes\n");

	for_each_child_of_node(adap->dev.of_node, node) {
		struct i2c_board_info info = {};
		struct dev_archdata dev_ad = {};
		const __be32 *addr;
		int len;

		if (of_modalias_node(node, info.type, sizeof(info.type)) < 0)
		dev_dbg(&adap->dev, "of_i2c: register %s\n", node->full_name);

		if (of_modalias_node(node, info.type, sizeof(info.type)) < 0) {
			dev_err(&adap->dev, "of_i2c: modalias failure on %s\n",
				node->full_name);
			continue;
		}

		addr = of_get_property(node, "reg", &len);
		if (!addr || len < sizeof(int) || *addr > (1 << 10) - 1) {
			printk(KERN_ERR
			       "of-i2c: invalid i2c device entry\n");
		if (!addr || (len < sizeof(int))) {
			dev_err(&adap->dev, "of_i2c: invalid reg on %s\n",
				node->full_name);
			continue;
		}

		info.irq = irq_of_parse_and_map(node, 0);

		info.addr = be32_to_cpup(addr);
		if (info.addr > (1 << 10) - 1) {
			dev_err(&adap->dev, "of_i2c: invalid addr=%x on %s\n",
				info.addr, node->full_name);
			continue;
		}

		info.of_node = node;
		info.irq = irq_of_parse_and_map(node, 0);
		info.of_node = of_node_get(node);
		info.archdata = &dev_ad;

		request_module("%s", info.type);

		result = i2c_new_device(adap, &info);
		if (result == NULL) {
			printk(KERN_ERR
			       "of-i2c: Failed to load driver for %s\n",
			       info.type);
			dev_err(&adap->dev, "of_i2c: Failure registering %s\n",
			        node->full_name);
			of_node_put(node);
			irq_dispose_mapping(info.irq);
			continue;
		}

		/*
		 * Get the node to not lose the dev_archdata->of_node.
		 * Currently there is no way to put it back, as well as no
		 * of_unregister_i2c_devices() call.
		 */
		of_node_get(node);
	}
}
EXPORT_SYMBOL(of_register_i2c_devices);
EXPORT_SYMBOL(of_i2c_register_devices);

static int of_dev_node_match(struct device *dev, void *data)
{
Loading