static int it87_probe()

in it87.c [3034:3180]


static int it87_probe(struct platform_device *pdev)
{
	struct it87_data *data;
	struct resource *res;
	struct device *dev = &pdev->dev;
	struct it87_sio_data *sio_data = dev_get_platdata(dev);
	int enable_pwm_interface;
	struct device *hwmon_dev;

	res = platform_get_resource(pdev, IORESOURCE_IO, 0);
	if (!devm_request_region(&pdev->dev, res->start, IT87_EC_EXTENT,
				 DRVNAME)) {
		dev_err(dev, "Failed to request region 0x%lx-0x%lx\n",
			(unsigned long)res->start,
			(unsigned long)(res->start + IT87_EC_EXTENT - 1));
		return -EBUSY;
	}

	data = devm_kzalloc(&pdev->dev, sizeof(struct it87_data), GFP_KERNEL);
	if (!data)
		return -ENOMEM;

	data->addr = res->start;
	data->sioaddr = sio_data->sioaddr;
	data->type = sio_data->type;
	data->features = it87_devices[sio_data->type].features;
	data->peci_mask = it87_devices[sio_data->type].peci_mask;
	data->old_peci_mask = it87_devices[sio_data->type].old_peci_mask;
	/*
	 * IT8705F Datasheet 0.4.1, 3h == Version G.
	 * IT8712F Datasheet 0.9.1, section 8.3.5 indicates 8h == Version J.
	 * These are the first revisions with 16-bit tachometer support.
	 */
	switch (data->type) {
	case it87:
		if (sio_data->revision >= 0x03) {
			data->features &= ~FEAT_OLD_AUTOPWM;
			data->features |= FEAT_FAN16_CONFIG | FEAT_16BIT_FANS;
		}
		break;
	case it8712:
		if (sio_data->revision >= 0x08) {
			data->features &= ~FEAT_OLD_AUTOPWM;
			data->features |= FEAT_FAN16_CONFIG | FEAT_16BIT_FANS |
					  FEAT_FIVE_FANS;
		}
		break;
	default:
		break;
	}

	/* Now, we do the remaining detection. */
	if ((it87_read_value(data, IT87_REG_CONFIG) & 0x80) ||
	    it87_read_value(data, IT87_REG_CHIPID) != 0x90)
		return -ENODEV;

	platform_set_drvdata(pdev, data);

	mutex_init(&data->update_lock);

	/* Check PWM configuration */
	enable_pwm_interface = it87_check_pwm(dev);
	if (!enable_pwm_interface)
		dev_info(dev,
			 "Detected broken BIOS defaults, disabling PWM interface\n");

	/* Starting with IT8721F, we handle scaling of internal voltages */
	if (has_12mv_adc(data)) {
		if (sio_data->internal & BIT(0))
			data->in_scaled |= BIT(3);	/* in3 is AVCC */
		if (sio_data->internal & BIT(1))
			data->in_scaled |= BIT(7);	/* in7 is VSB */
		if (sio_data->internal & BIT(2))
			data->in_scaled |= BIT(8);	/* in8 is Vbat */
		if (sio_data->internal & BIT(3))
			data->in_scaled |= BIT(9);	/* in9 is AVCC */
	} else if (sio_data->type == it8781 || sio_data->type == it8782 ||
		   sio_data->type == it8783) {
		if (sio_data->internal & BIT(0))
			data->in_scaled |= BIT(3);	/* in3 is VCC5V */
		if (sio_data->internal & BIT(1))
			data->in_scaled |= BIT(7);	/* in7 is VCCH5V */
	}

	data->has_temp = 0x07;
	if (sio_data->skip_temp & BIT(2)) {
		if (sio_data->type == it8782 &&
		    !(it87_read_value(data, IT87_REG_TEMP_EXTRA) & 0x80))
			data->has_temp &= ~BIT(2);
	}

	data->in_internal = sio_data->internal;
	data->need_in7_reroute = sio_data->need_in7_reroute;
	data->has_in = 0x3ff & ~sio_data->skip_in;

	if (has_six_temp(data)) {
		u8 reg = it87_read_value(data, IT87_REG_TEMP456_ENABLE);

		/* Check for additional temperature sensors */
		if ((reg & 0x03) >= 0x02)
			data->has_temp |= BIT(3);
		if (((reg >> 2) & 0x03) >= 0x02)
			data->has_temp |= BIT(4);
		if (((reg >> 4) & 0x03) >= 0x02)
			data->has_temp |= BIT(5);

		/* Check for additional voltage sensors */
		if ((reg & 0x03) == 0x01)
			data->has_in |= BIT(10);
		if (((reg >> 2) & 0x03) == 0x01)
			data->has_in |= BIT(11);
		if (((reg >> 4) & 0x03) == 0x01)
			data->has_in |= BIT(12);
	}

	data->has_beep = !!sio_data->beep_pin;

	/* Initialize the IT87 chip */
	it87_init_device(pdev);

	if (!sio_data->skip_vid) {
		data->has_vid = true;
		data->vrm = vid_which_vrm();
		/* VID reading from Super-I/O config space if available */
		data->vid = sio_data->vid_value;
	}

	/* Prepare for sysfs hooks */
	data->groups[0] = &it87_group;
	data->groups[1] = &it87_group_in;
	data->groups[2] = &it87_group_temp;
	data->groups[3] = &it87_group_fan;

	if (enable_pwm_interface) {
		data->has_pwm = BIT(ARRAY_SIZE(IT87_REG_PWM)) - 1;
		data->has_pwm &= ~sio_data->skip_pwm;

		data->groups[4] = &it87_group_pwm;
		if (has_old_autopwm(data) || has_newer_autopwm(data))
			data->groups[5] = &it87_group_auto_pwm;
	}

	hwmon_dev = devm_hwmon_device_register_with_groups(dev,
					it87_devices[sio_data->type].name,
					data, data->groups);
	return PTR_ERR_OR_ZERO(hwmon_dev);
}