static int max1619_probe(struct i2c_client *new_client, const struct i2c_device_id *id) { struct max1619_data *data; int err; data = kzalloc(sizeof(struct max1619_data), GFP_KERNEL); if (!data) { err = -ENOMEM; goto exit; } i2c_set_clientdata(new_client, data); data->valid = 0; mutex_init(&data->update_lock); /* Initialize the MAX1619 chip */ max1619_init_client(new_client); /* Register sysfs hooks */ if ((err = sysfs_create_group(&new_client->dev.kobj, &max1619_group))) goto exit_free; data->hwmon_dev = hwmon_device_register(&new_client->dev); if (IS_ERR(data->hwmon_dev)) { err = PTR_ERR(data->hwmon_dev); goto exit_remove_files; } return 0; exit_remove_files: sysfs_remove_group(&new_client->dev.kobj, &max1619_group); exit_free: kfree(data); exit: return err; }
/* * The following function does more than just detection. If detection * succeeds, it also registers the new chip. */ static int max1619_detect(struct i2c_adapter *adapter, int address, unsigned short flags, int kind) { struct i2c_client *new_client; struct max1619_data *data; int err = 0; const char *type_name = ""; const char *client_name = ""; #ifdef DEBUG if (i2c_is_isa_adapter(adapter)) { printk(KERN_DEBUG "max1619.o: Called for an ISA bus " "adapter, aborting.\n"); return 0; } #endif if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) { #ifdef DEBUG printk(KERN_DEBUG "max1619.o: I2C bus doesn't support " "byte read mode, skipping.\n"); #endif return 0; } if (!(data = kmalloc(sizeof(struct max1619_data), GFP_KERNEL))) { printk(KERN_ERR "max1619.o: Out of memory in " "max1619_detect (new_client).\n"); return -ENOMEM; } /* * The common I2C client data is placed right before the * MAX1619-specific data. The MAX1619-specific data is pointed to * by the data field from the I2C client da1ta. */ new_client = &data->client; new_client->addr = address; new_client->data = data; new_client->adapter = adapter; new_client->driver = &max1619_driver; new_client->flags = 0; /* * Now we do the remaining detection. A negative kind means that * the driver was loaded with no force parameter (default), so we * must both detect and identify the chip. A zero kind means that * the driver was loaded with the force parameter, the detection * step shall be skipped. A positive kind means that the driver * was loaded with the force parameter and a given kind of chip is * requested, so both the detection and the identification steps * are skipped. */ if (kind < 0) { u8 reg_config, reg_convrate, reg_status; reg_config = i2c_smbus_read_byte_data(new_client, MAX1619_REG_R_CONFIG); reg_convrate = i2c_smbus_read_byte_data(new_client, MAX1619_REG_R_CONVRATE); reg_status = i2c_smbus_read_byte_data(new_client, MAX1619_REG_R_STATUS); if ((reg_config & 0x03) != 0x00 || reg_convrate > 0x07 || (reg_status & 0x61) != 0x00) { #ifdef DEBUG printk(KERN_DEBUG "max1619.o: Detection failed at " "0x%02x.\n", address); #endif goto ERROR1; } } if (kind <= 0) { u8 man_id, chip_id; man_id = i2c_smbus_read_byte_data(new_client, MAX1619_REG_R_MAN_ID); chip_id = i2c_smbus_read_byte_data(new_client, MAX1619_REG_R_CHIP_ID); if ((man_id == 0x4D) && (chip_id == 0x04)) { kind = max1619; } } if (kind <= 0) { printk(KERN_INFO "max1619.o: Unsupported chip.\n"); goto ERROR1; } if (kind == max1619) { type_name = "max1619"; client_name = "MAX1619 chip"; } else { printk(KERN_ERR "max1619.o: Unknown kind %d.\n", kind); goto ERROR1; } /* * OK, we got a valid chip so we can fill in the remaining client * fields. */ strcpy(new_client->name, client_name); data->valid = 0; init_MUTEX(&data->update_lock); /* * Tell the I2C layer a new client has arrived. */ if ((err = i2c_attach_client(new_client))) { printk(KERN_ERR "max1619.o: Failed attaching client.\n"); goto ERROR1; } /* * Register a new directory entry. */ if ((err = i2c_register_entry(new_client, type_name, max1619_dir_table_template, THIS_MODULE)) < 0) { printk(KERN_ERR "max1619.o: Failed registering directory " "entry.\n"); goto ERROR2; } data->sysctl_id = err; /* * Initialize the MAX1619 chip. */ max1619_init_client(new_client); return 0; ERROR2: i2c_detach_client(new_client); ERROR1: kfree(data); return err; }