Ejemplo n.º 1
0
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;
}
Ejemplo n.º 2
0
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");
}