static int pwm_fan_probe()

in pwm-fan.c [297:462]


static int pwm_fan_probe(struct platform_device *pdev)
{
	struct thermal_cooling_device *cdev;
	struct device *dev = &pdev->dev;
	struct pwm_fan_ctx *ctx;
	struct device *hwmon;
	int ret;
	const struct hwmon_channel_info **channels;
	u32 *fan_channel_config;
	int channel_count = 1;	/* We always have a PWM channel. */
	int i;

	ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL);
	if (!ctx)
		return -ENOMEM;

	mutex_init(&ctx->lock);

	ctx->pwm = devm_of_pwm_get(dev, dev->of_node, NULL);
	if (IS_ERR(ctx->pwm))
		return dev_err_probe(dev, PTR_ERR(ctx->pwm), "Could not get PWM\n");

	platform_set_drvdata(pdev, ctx);

	ctx->reg_en = devm_regulator_get_optional(dev, "fan");
	if (IS_ERR(ctx->reg_en)) {
		if (PTR_ERR(ctx->reg_en) != -ENODEV)
			return PTR_ERR(ctx->reg_en);

		ctx->reg_en = NULL;
	} else {
		ret = regulator_enable(ctx->reg_en);
		if (ret) {
			dev_err(dev, "Failed to enable fan supply: %d\n", ret);
			return ret;
		}
		ret = devm_add_action_or_reset(dev, pwm_fan_regulator_disable,
					       ctx->reg_en);
		if (ret)
			return ret;
	}

	pwm_init_state(ctx->pwm, &ctx->pwm_state);

	/*
	 * __set_pwm assumes that MAX_PWM * (period - 1) fits into an unsigned
	 * long. Check this here to prevent the fan running at a too low
	 * frequency.
	 */
	if (ctx->pwm_state.period > ULONG_MAX / MAX_PWM + 1) {
		dev_err(dev, "Configured period too big\n");
		return -EINVAL;
	}

	/* Set duty cycle to maximum allowed and enable PWM output */
	ret = __set_pwm(ctx, MAX_PWM);
	if (ret) {
		dev_err(dev, "Failed to configure PWM: %d\n", ret);
		return ret;
	}
	timer_setup(&ctx->rpm_timer, sample_timer, 0);
	ret = devm_add_action_or_reset(dev, pwm_fan_pwm_disable, ctx);
	if (ret)
		return ret;

	ctx->tach_count = platform_irq_count(pdev);
	if (ctx->tach_count < 0)
		return dev_err_probe(dev, ctx->tach_count,
				     "Could not get number of fan tachometer inputs\n");
	dev_dbg(dev, "%d fan tachometer inputs\n", ctx->tach_count);

	if (ctx->tach_count) {
		channel_count++;	/* We also have a FAN channel. */

		ctx->tachs = devm_kcalloc(dev, ctx->tach_count,
					  sizeof(struct pwm_fan_tach),
					  GFP_KERNEL);
		if (!ctx->tachs)
			return -ENOMEM;

		ctx->fan_channel.type = hwmon_fan;
		fan_channel_config = devm_kcalloc(dev, ctx->tach_count + 1,
						  sizeof(u32), GFP_KERNEL);
		if (!fan_channel_config)
			return -ENOMEM;
		ctx->fan_channel.config = fan_channel_config;
	}

	channels = devm_kcalloc(dev, channel_count + 1,
				sizeof(struct hwmon_channel_info *), GFP_KERNEL);
	if (!channels)
		return -ENOMEM;

	channels[0] = &pwm_fan_channel_pwm;

	for (i = 0; i < ctx->tach_count; i++) {
		struct pwm_fan_tach *tach = &ctx->tachs[i];
		u32 ppr = 2;

		tach->irq = platform_get_irq(pdev, i);
		if (tach->irq == -EPROBE_DEFER)
			return tach->irq;
		if (tach->irq > 0) {
			ret = devm_request_irq(dev, tach->irq, pulse_handler, 0,
					       pdev->name, tach);
			if (ret) {
				dev_err(dev,
					"Failed to request interrupt: %d\n",
					ret);
				return ret;
			}
		}

		of_property_read_u32_index(dev->of_node,
					   "pulses-per-revolution",
					   i,
					   &ppr);
		tach->pulses_per_revolution = ppr;
		if (!tach->pulses_per_revolution) {
			dev_err(dev, "pulses-per-revolution can't be zero.\n");
			return -EINVAL;
		}

		fan_channel_config[i] = HWMON_F_INPUT;

		dev_dbg(dev, "tach%d: irq=%d, pulses_per_revolution=%d\n",
			i, tach->irq, tach->pulses_per_revolution);
	}

	if (ctx->tach_count > 0) {
		ctx->sample_start = ktime_get();
		mod_timer(&ctx->rpm_timer, jiffies + HZ);

		channels[1] = &ctx->fan_channel;
	}

	ctx->info.ops = &pwm_fan_hwmon_ops;
	ctx->info.info = channels;

	hwmon = devm_hwmon_device_register_with_info(dev, "pwmfan",
						     ctx, &ctx->info, NULL);
	if (IS_ERR(hwmon)) {
		dev_err(dev, "Failed to register hwmon device\n");
		return PTR_ERR(hwmon);
	}

	ret = pwm_fan_of_get_cooling_data(dev, ctx);
	if (ret)
		return ret;

	ctx->pwm_fan_state = ctx->pwm_fan_max_state;
	if (IS_ENABLED(CONFIG_THERMAL)) {
		cdev = devm_thermal_of_cooling_device_register(dev,
			dev->of_node, "pwm-fan", ctx, &pwm_fan_cooling_ops);
		if (IS_ERR(cdev)) {
			ret = PTR_ERR(cdev);
			dev_err(dev,
				"Failed to register pwm-fan as cooling device: %d\n",
				ret);
			return ret;
		}
		ctx->cdev = cdev;
	}

	return 0;
}