static int tmon_tmp411_probe(struct i2c_client *client, const struct i2c_device_id *id) { struct tmon_plat_data *tmon_pdata = client->dev.platform_data; struct tmon_info *data; int err; int i; u8 man_id; u8 config; u64 mask; char extern_tsensor_loc_name[] = "extern_tsensor_loc"; if (tmon_pdata == NULL) { dev_err(&client->dev, "no platform data\n"); return -EINVAL; } if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) { dev_err(&client->dev, "insufficient functionality!\n"); return -ENODEV; } data = devm_kzalloc(&client->dev, sizeof(struct tmon_info), GFP_KERNEL); if (!data) return -ENOMEM; TMON_RD(client, REG_MAN_ID, &man_id); if (man_id == 0x41) { tmon_device = NVT210; dev_info(&client->dev, "detected NVT210\n"); } else if (man_id == 0x55) { tmon_device = TMP411; dev_info(&client->dev, "detected TMP411\n"); } else { dev_warn(&client->dev, "unsuported t-sensor with manufacturer-id:0x%x\n", man_id); return -EINVAL; } TMON_RD(client, REG_CFG_READ, &config); /* Enable Alert, Extended mode and disable stand by */ config |= CFG_EXTEND; config &= ~CFG_ALERT_MASK; config &= ~CFG_STANDBY; config &= ~CFG_ALERT_DISABLE; err = i2c_smbus_write_byte_data(client, REG_CFG_WRITE, config); /*FIXME: Is it required to wait for one temperature conversion? */ if (err < 0) { dev_warn(&client->dev, "\n Failed to write config for temperature sensor\n"); return err; } data->client = client; i2c_set_clientdata(client, data); data->pdata = tmon_pdata; mutex_init(&data->update_lock); mutex_init(&data->sysfs_alert_lock); spin_lock_init(&data->alert_spinlock); data->sysfs_therm_alert_timeout = 0; data->therm_alert = 0; /* * Suppose, if we get alert interrupts immediately after irq * registeration and before disable_irq_nosync, then once entered * in to Isr, if the below variable is set then irq will be disabled, * otherwise it's likely that continious interrupts comes. */ data->disable_intr_reqr = 1; init_waitqueue_head(&data->alert_wait_queue); if (data->pdata->alert_gpio != -1) { /* IRQ for therm alert */ data->irq_num = gpio_to_irq(data->pdata->alert_gpio); err = request_irq(data->irq_num, tmon_alert_isr, IRQF_TRIGGER_LOW, "tmon alert", data); dev_info(&client->dev, "\n Tmon IRQ registered for gpio:%d\n", data->pdata->alert_gpio); if (!err) { /*Disable now and enable only when sysfs alert is opened */ disable_irq_nosync(data->irq_num); data->alert_info = devm_kzalloc(&client->dev, sizeof(struct i2c_smbus_alert_setup), GFP_KERNEL); if (!data->alert_info) { err = -ENOMEM; goto err_irq; } data->alert_info->alert_edge_triggered = 1; data->ara = i2c_setup_smbus_alert(client->adapter, data->alert_info); } else { dev_warn(&client->dev, "failed to get irq for alert gpio:%d\n", data->pdata->alert_gpio); return err; } } for (i = 0; i < ARRAY_SIZE(tmp411_attr); i++) { err = device_create_file(&client->dev, &tmp411_attr[i].dev_attr); if (err) goto err_exit; } mask = 0; /* if mask of ith trip is 1 then make the debugfs entry for * this trip point writable */ for (i = 0; i < tmon_pdata->num_trips; i++) if (tmon_pdata->trips[i].mask) mask |= 1ULL << i; data->thz = thermal_zone_device_register(extern_tsensor_loc_name, tmon_pdata->num_trips, mask, data, &tmon_loc_ops, tmon_pdata->tzp, tmon_pdata->passive_delay, tmon_pdata->polling_delay); if (IS_ERR_OR_NULL(data->thz)) dev_err(&client->dev, "extern_tsensor_loc thermal zone device not registered\n"); dev_info(&client->dev, "Temperature Monitor enabled\n"); return 0; err_exit: for (i = 0; i < ARRAY_SIZE(tmp411_attr); i++) device_remove_file(&client->dev, &tmp411_attr[i].dev_attr); i2c_unregister_device(data->ara); err_irq: free_irq(data->irq_num, data); return err; }
static int __init my_init(void) { int status = 0; struct i2c_smbus_alert_setup setup = { .alert_edge_triggered = 1, }; struct i2c_adapter *adapter = i2c_get_adapter(6); if (!adapter) { pr_err("Failed to find i2c adapter #%d\n", 6); status = -1; goto fail; } if (!gpio_is_valid(gpioNum)) { pr_err("GPIO number %d is not valid\n", gpioNum); goto fail; } status = gpio_request_one(gpioNum, GPIOF_DIR_IN, "smbus_alert"); if (status < 0) { pr_err("GPIO allocation failed, result %d\n", status); goto fail; } setup.irq = gpio_to_irq(gpioNum); if (setup.irq < 0) { pr_err("Failed to get gpio interrupt, err is %d\n", setup.irq); goto release_gpio; } #if 1 alert_client = i2c_setup_smbus_alert(adapter, &setup); if (!alert_client) { pr_err("Failed to register smbus alert device.\n"); goto release_gpio; } i2c_put_adapter(adapter); #else status = request_threaded_irq(setup.irq, NULL, my_handler, IRQF_TRIGGER_FALLING | IRQF_ONESHOT, "smartio_smbus", &gpioNum); if (status < 0) { pr_err("Failed to install interrupt handlert, err is %d\n", status); goto release_gpio; } #endif pr_warn("Done setting up smbus alert\n"); return status; release_gpio: gpio_free(gpioNum); release_adapter: i2c_put_adapter(adapter); fail: pr_err("Failed setting up smbus alert\n"); return status; } module_init(my_init); static void __exit my_cleanup(void) { #if 0 i2c_unregister_device(alert_client); gpiod_put(gpio); #endif gpio_free(gpioNum); pr_warn("Removed smbus alert\n"); }