Exemple #1
0
static int __init envctrl_init(void)
{
#ifdef CONFIG_PCI
	struct linux_ebus *ebus = NULL;
	struct linux_ebus_device *edev = NULL;
	struct linux_ebus_child *edev_child = NULL;
	int i = 0;

	/* Traverse through ebus and ebus device list for i2c device and
	 * adc and gpio nodes.
	 */
	for_each_ebus(ebus) {
		for_each_ebusdev(edev, ebus) {
			if (!strcmp(edev->prom_name, "i2c")) {
				i2c = ioremap(	edev->resource[0].start, 
								sizeof(struct pcf8584_reg));
				for_each_edevchild(edev, edev_child) {
					if (!strcmp("gpio", edev_child->prom_name)) {
						i2c_childlist[i].i2ctype = I2C_GPIO;
						envctrl_init_i2c_child(edev_child, &(i2c_childlist[i++]));
					}
					if (!strcmp("adc", edev_child->prom_name)) {
						i2c_childlist[i].i2ctype = I2C_ADC;
						envctrl_init_i2c_child(edev_child, &(i2c_childlist[i++]));
					}
				}
				goto done;
			}
		}
	}
static int __init envctrl_init(void)
{
#ifdef CONFIG_PCI
	struct linux_ebus *ebus = NULL;
	struct linux_ebus_device *edev = NULL;
	struct linux_ebus_child *edev_child = NULL;
	int err, i = 0;

	for_each_ebus(ebus) {
		for_each_ebusdev(edev, ebus) {
			if (!strcmp(edev->prom_name, "bbc")) {
				/* If we find a boot-bus controller node,
				 * then this envctrl driver is not for us.
				 */
				return -ENODEV;
			}
		}
	}

	/* Traverse through ebus and ebus device list for i2c device and
	 * adc and gpio nodes.
	 */
	for_each_ebus(ebus) {
		for_each_ebusdev(edev, ebus) {
			if (!strcmp(edev->prom_name, "i2c")) {
				i2c = ioremap(	edev->resource[0].start, 
								sizeof(struct pcf8584_reg));
				for_each_edevchild(edev, edev_child) {
					if (!strcmp("gpio", edev_child->prom_name)) {
						i2c_childlist[i].i2ctype = I2C_GPIO;
						envctrl_init_i2c_child(edev_child, &(i2c_childlist[i++]));
					}
					if (!strcmp("adc", edev_child->prom_name)) {
						i2c_childlist[i].i2ctype = I2C_ADC;
						envctrl_init_i2c_child(edev_child, &(i2c_childlist[i++]));
					}
				}
				goto done;
			}
		}
	}
static int __devinit envctrl_probe(struct of_device *op,
				   const struct of_device_id *match)
{
	struct device_node *dp;
	int index, err;

	if (i2c)
		return -EINVAL;

	i2c = of_ioremap(&op->resource[0], 0, 0x2, DRIVER_NAME);
	if (!i2c)
		return -ENOMEM;

	index = 0;
	dp = op->node->child;
	while (dp) {
		if (!strcmp(dp->name, "gpio")) {
			i2c_childlist[index].i2ctype = I2C_GPIO;
			envctrl_init_i2c_child(dp, &(i2c_childlist[index++]));
		} else if (!strcmp(dp->name, "adc")) {
			i2c_childlist[index].i2ctype = I2C_ADC;
			envctrl_init_i2c_child(dp, &(i2c_childlist[index++]));
		}

		dp = dp->sibling;
	}

	/* Set device address. */
	writeb(CONTROL_PIN, i2c + PCF8584_CSR);
	writeb(PCF8584_ADDRESS, i2c + PCF8584_DATA);

	/* Set system clock and SCL frequencies. */ 
	writeb(CONTROL_PIN | CONTROL_ES1, i2c + PCF8584_CSR);
	writeb(CLK_4_43 | BUS_CLK_90, i2c + PCF8584_DATA);

	/* Enable serial interface. */
	writeb(CONTROL_PIN | CONTROL_ES0 | CONTROL_ACK, i2c + PCF8584_CSR);
	udelay(200);

	/* Register the device as a minor miscellaneous device. */
	err = misc_register(&envctrl_dev);
	if (err) {
		printk(KERN_ERR PFX "Unable to get misc minor %d\n",
		       envctrl_dev.minor);
		goto out_iounmap;
	}

	/* Note above traversal routine post-incremented 'i' to accommodate 
	 * a next child device, so we decrement before reverse-traversal of
	 * child devices.
	 */
	printk(KERN_INFO PFX "Initialized ");
	for (--index; index >= 0; --index) {
		printk("[%s 0x%lx]%s", 
			(I2C_ADC == i2c_childlist[index].i2ctype) ? "adc" : 
			((I2C_GPIO == i2c_childlist[index].i2ctype) ? "gpio" : "unknown"), 
			i2c_childlist[index].addr, (0 == index) ? "\n" : " ");
	}

	kenvctrld_task = kthread_run(kenvctrld, NULL, "kenvctrld");
	if (IS_ERR(kenvctrld_task)) {
		err = PTR_ERR(kenvctrld_task);
		goto out_deregister;
	}

	return 0;

out_deregister:
	misc_deregister(&envctrl_dev);
out_iounmap:
	of_iounmap(&op->resource[0], i2c, 0x2);
	for (index = 0; index < ENVCTRL_MAX_CPU * 2; index++)
		kfree(i2c_childlist[index].tables);

	return err;
}