// SPDX-License-Identifier: GPL-2.0-only
/*
 * Qualcomm Wireless Connectivity Subsystem Iris driver
 *
 * Copyright (C) 2016 Linaro Ltd
 * Copyright (C) 2014 Sony Mobile Communications AB
 * Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
 */

#include <linux/clk.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/of_device.h>
#include <linux/platform_device.h>
#include <linux/regulator/consumer.h>

#include "qcom_wcnss.h"

struct qcom_iris {
	struct device dev;

	struct clk *xo_clk;

	struct regulator_bulk_data *vregs;
	size_t num_vregs;
};

struct iris_data {
	const struct wcnss_vreg_info *vregs;
	size_t num_vregs;

	bool use_48mhz_xo;
};

static const struct iris_data wcn3620_data = {
	.vregs = (struct wcnss_vreg_info[]) {
		{ "vddxo",  1800000, 1800000, 10000 },
		{ "vddrfa", 1300000, 1300000, 100000 },
		{ "vddpa",  3300000, 3300000, 515000 },
		{ "vdddig", 1800000, 1800000, 10000 },
	},
	.num_vregs = 4,
	.use_48mhz_xo = false,
};

static const struct iris_data wcn3660_data = {
	.vregs = (struct wcnss_vreg_info[]) {
		{ "vddxo",  1800000, 1800000, 10000 },
		{ "vddrfa", 1300000, 1300000, 100000 },
		{ "vddpa",  2900000, 3000000, 515000 },
		{ "vdddig", 1200000, 1225000, 10000 },
	},
	.num_vregs = 4,
	.use_48mhz_xo = true,
};

static const struct iris_data wcn3680_data = {
	.vregs = (struct wcnss_vreg_info[]) {
		{ "vddxo",  1800000, 1800000, 10000 },
		{ "vddrfa", 1300000, 1300000, 100000 },
		{ "vddpa",  3300000, 3300000, 515000 },
		{ "vdddig", 1800000, 1800000, 10000 },
	},
	.num_vregs = 4,
	.use_48mhz_xo = true,
};

int qcom_iris_enable(struct qcom_iris *iris)
{
	int ret;

	ret = regulator_bulk_enable(iris->num_vregs, iris->vregs);
	if (ret)
		return ret;

	ret = clk_prepare_enable(iris->xo_clk);
	if (ret) {
		dev_err(&iris->dev, "failed to enable xo clk\n");
		goto disable_regulators;
	}

	return 0;

disable_regulators:
	regulator_bulk_disable(iris->num_vregs, iris->vregs);

	return ret;
}

void qcom_iris_disable(struct qcom_iris *iris)
{
	clk_disable_unprepare(iris->xo_clk);
	regulator_bulk_disable(iris->num_vregs, iris->vregs);
}

static const struct of_device_id iris_of_match[] = {
	{ .compatible = "qcom,wcn3620", .data = &wcn3620_data },
	{ .compatible = "qcom,wcn3660", .data = &wcn3660_data },
	{ .compatible = "qcom,wcn3660b", .data = &wcn3680_data },
	{ .compatible = "qcom,wcn3680", .data = &wcn3680_data },
	{}
};

static void qcom_iris_release(struct device *dev)
{
	struct qcom_iris *iris = container_of(dev, struct qcom_iris, dev);

	of_node_put(iris->dev.of_node);
	kfree(iris);
}

struct qcom_iris *qcom_iris_probe(struct device *parent, bool *use_48mhz_xo)
{
	const struct of_device_id *match;
	const struct iris_data *data;
	struct device_node *of_node;
	struct qcom_iris *iris;
	int ret;
	int i;

	of_node = of_get_child_by_name(parent->of_node, "iris");
	if (!of_node) {
		dev_err(parent, "No child node \"iris\" found\n");
		return ERR_PTR(-EINVAL);
	}

	iris = kzalloc(sizeof(*iris), GFP_KERNEL);
	if (!iris) {
		of_node_put(of_node);
		return ERR_PTR(-ENOMEM);
	}

	device_initialize(&iris->dev);
	iris->dev.parent = parent;
	iris->dev.release = qcom_iris_release;
	iris->dev.of_node = of_node;

	dev_set_name(&iris->dev, "%s.iris", dev_name(parent));

	ret = device_add(&iris->dev);
	if (ret) {
		put_device(&iris->dev);
		return ERR_PTR(ret);
	}

	match = of_match_device(iris_of_match, &iris->dev);
	if (!match) {
		dev_err(&iris->dev, "no matching compatible for iris\n");
		ret = -EINVAL;
		goto err_device_del;
	}

	data = match->data;

	iris->xo_clk = devm_clk_get(&iris->dev, "xo");
	if (IS_ERR(iris->xo_clk)) {
		ret = PTR_ERR(iris->xo_clk);
		if (ret != -EPROBE_DEFER)
			dev_err(&iris->dev, "failed to acquire xo clk\n");
		goto err_device_del;
	}

	iris->num_vregs = data->num_vregs;
	iris->vregs = devm_kcalloc(&iris->dev,
				   iris->num_vregs,
				   sizeof(struct regulator_bulk_data),
				   GFP_KERNEL);
	if (!iris->vregs) {
		ret = -ENOMEM;
		goto err_device_del;
	}

	for (i = 0; i < iris->num_vregs; i++)
		iris->vregs[i].supply = data->vregs[i].name;

	ret = devm_regulator_bulk_get(&iris->dev, iris->num_vregs, iris->vregs);
	if (ret) {
		dev_err(&iris->dev, "failed to get regulators\n");
		goto err_device_del;
	}

	for (i = 0; i < iris->num_vregs; i++) {
		if (data->vregs[i].max_voltage)
			regulator_set_voltage(iris->vregs[i].consumer,
					      data->vregs[i].min_voltage,
					      data->vregs[i].max_voltage);

		if (data->vregs[i].load_uA)
			regulator_set_load(iris->vregs[i].consumer,
					   data->vregs[i].load_uA);
	}

	*use_48mhz_xo = data->use_48mhz_xo;

	return iris;

err_device_del:
	device_del(&iris->dev);

	return ERR_PTR(ret);
}

void qcom_iris_remove(struct qcom_iris *iris)
{
	device_del(&iris->dev);
}
