Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 5f8106b4 authored by qctecmdr's avatar qctecmdr Committed by Gerrit - the friendly Code Review server
Browse files

Merge "defconfig: gen3auto: Enable ION & Secure buffer driver"

parents b76e4e45 ffbc2eb8
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -14,6 +14,9 @@ CONFIG_UNUSED_KSYMS_WHITELIST="android/abi_gki_aarch64_qcom android/abi_gki_aarc
CONFIG_UNUSED_KSYMS_WHITELIST_ONLY=y
CONFIG_PINCTRL_SM8150=m
CONFIG_PINCTRL_SDMSHRIKE=m
CONFIG_PINCTRL_SLPI=m
CONFIG_ION_MSM_HEAPS=m
CONFIG_QCOM_SECURE_BUFFER=m
CONFIG_HEADER_TEST=y
CONFIG_HEADERS_INSTALL=y
CONFIG_KERNEL_HEADER_TEST=y
+1 −0
Original line number Diff line number Diff line
@@ -3,6 +3,7 @@ CONFIG_LOCALVERSION="-qgki"
CONFIG_DEBUG_FS=y
# CONFIG_TRIM_UNUSED_KSYMS is not set
CONFIG_REGULATOR_QTI_DEBUG=y
CONFIG_ION_POOL_AUTO_REFILL=y
# CONFIG_DETECT_HUNG_TASK is not set
# CONFIG_ZONE_DMA32 is not set
# CONFIG_SOFTLOCKUP_DETECTOR is not set
+10 −0
Original line number Diff line number Diff line
@@ -300,4 +300,14 @@ config PINCTRL_MONACO
	  Say Y here to compile statically, or M here to compile it as a module.
	  If unsure, say N.

config PINCTRL_SLPI
        tristate "Qualcomm Technologies, Inc SLPI pin controller driver"
	depends on GPIOLIB && OF
	help
	  Sensor Low Power Island(SLPI) has a Pin controller which can support
	  14 pin configurations. This is the pinctrl, pinmux and  pinconf
	  driver for the SLPI pin controller block.
	  Say Y here to compile statically, or M here to compile it as a module.
          If unsure, say N.

endif
+1 −0
Original line number Diff line number Diff line
@@ -33,3 +33,4 @@ obj-$(CONFIG_PINCTRL_SCUBA) += pinctrl-scuba.o
obj-$(CONFIG_PINCTRL_SDXLEMUR) += pinctrl-sdxlemur.o
obj-$(CONFIG_PINCTRL_SDXNIGHTJAR) += pinctrl-sdxnightjar.o
obj-$(CONFIG_PINCTRL_MONACO) += pinctrl-monaco.o
obj-$(CONFIG_PINCTRL_SLPI) += pinctrl-slpi.o
+457 −0
Original line number Diff line number Diff line
// SPDX-License-Identifier: GPL-2.0-only
/*
 * Copyright (c) 2018-2020, The Linux Foundation. All rights reserved.
 */

#include <linux/gpio.h>
#include <linux/io.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/pinctrl/pinconf-generic.h>
#include <linux/pinctrl/pinconf.h>
#include <linux/pinctrl/pinmux.h>
#include <linux/platform_device.h>
#include <linux/slab.h>
#include <linux/types.h>

#include "../core.h"
#include "../pinctrl-utils.h"

/**
 * struct slpi_pin - SLPI pin definition
 * @name:	Name of the pin.
 * @ctl_reg:	Offset of the register holding control bits for this group.
 * @io_reg:	Offset of the register holding input/output bits for this group.
 * @pull_bit:	Offset in @ctl_reg for the bias configuration.
 * @mux_bit:	Offset in @ctl_reg for the pinmux function selection.
 * @drv_bit:	Offset in @ctl_reg for the drive strength configuration.
 * @oe_bit:	Offset in @ctl_reg for controlling output enable.
 * @in_bit:	Offset in @io_reg for the input bit value.
 * @out_bit:	Offset in @io_reg for the output bit value.
 */
struct slpi_pin {
	void __iomem *base;
	unsigned int offset;

	unsigned int ctl_reg;
	unsigned int io_reg;

	unsigned int pull_bit:5;
	unsigned int mux_bit:5;
	unsigned int drv_bit:5;
	unsigned int oe_bit:5;
	unsigned int in_bit:5;
	unsigned int out_bit:5;
};


/* The index of each function in slpi_pin_functions[] array */
enum slpi_pin_func_index {
	SLPI_PIN_FUNC_INDEX_GPIO	= 0x00,
	SLPI_PIN_FUNC_INDEX_FUNC1	= 0x01,
	SLPI_PIN_FUNC_INDEX_FUNC2	= 0x02,
	SLPI_PIN_FUNC_INDEX_FUNC3	= 0x03,
	SLPI_PIN_FUNC_INDEX_FUNC4	= 0x04,
	SLPI_PIN_FUNC_INDEX_FUNC5	= 0x05,
};

#define SLPI_PIN_FUNC_GPIO	"gpio"
#define SLPI_PIN_FUNC_FUNC1	"func1"
#define SLPI_PIN_FUNC_FUNC2	"func2"
#define SLPI_PIN_FUNC_FUNC3	"func3"
#define SLPI_PIN_FUNC_FUNC4	"func4"
#define SLPI_PIN_FUNC_FUNC5	"func5"

static const char *const slpi_gpio_groups[] = {
	"gpio0", "gpio1", "gpio2", "gpio3", "gpio4", "gpio5", "gpio6", "gpio7",
	"gpio8", "gpio9", "gpio10", "gpio11", "gpio12", "gpio13", "gpio14",
	"gpio15", "gpio16", "gpio17", "gpio18", "gpio19", "gpio20", "gpio21",
	"gpio22", "gpio23", "gpio24", "gpio25", "gpio26", "gpio27", "gpio28",
	"gpio29", "gpio30", "gpio31",
};

static const char *const slpi_pin_functions[] = {
	[SLPI_PIN_FUNC_INDEX_GPIO]	= SLPI_PIN_FUNC_GPIO,
	[SLPI_PIN_FUNC_INDEX_FUNC1]	= SLPI_PIN_FUNC_FUNC1,
	[SLPI_PIN_FUNC_INDEX_FUNC2]	= SLPI_PIN_FUNC_FUNC2,
	[SLPI_PIN_FUNC_INDEX_FUNC3]	= SLPI_PIN_FUNC_FUNC3,
	[SLPI_PIN_FUNC_INDEX_FUNC4]	= SLPI_PIN_FUNC_FUNC4,
	[SLPI_PIN_FUNC_INDEX_FUNC5]	= SLPI_PIN_FUNC_FUNC5,
};

static unsigned int slpi_read(struct slpi_pin *pin, u32 reg)
{
	return readl_relaxed(pin->base + pin->offset + reg);
}

static void  slpi_write(u32 val, struct slpi_pin *pin,  u32 reg)
{
	return writel_relaxed(val, pin->base + pin->offset + reg);
}

static int slpi_get_groups_count(struct pinctrl_dev *pctldev)
{
	/* Every PIN is a group */
	return pctldev->desc->npins;
}

static const char *slpi_get_group_name(struct pinctrl_dev *pctldev,
					unsigned int pin)
{
	return pctldev->desc->pins[pin].name;
}

static int slpi_get_group_pins(struct pinctrl_dev *pctldev,
			      unsigned int pin,
			      const unsigned int **pins,
			      unsigned int *num_pins)
{
	*pins = &pctldev->desc->pins[pin].number;
	*num_pins = 1;
	return 0;
}

static const struct pinctrl_ops slpi_pinctrl_ops = {
	.get_groups_count	= slpi_get_groups_count,
	.get_group_name		= slpi_get_group_name,
	.get_group_pins		= slpi_get_group_pins,
	.dt_node_to_map		= pinconf_generic_dt_node_to_map_group,
	.dt_free_map		= pinctrl_utils_free_map,
};

static int slpi_get_functions_count(struct pinctrl_dev *pctldev)
{
	return ARRAY_SIZE(slpi_pin_functions);
}

static const char *slpi_get_function_name(struct pinctrl_dev *pctldev,
					 unsigned int function)
{
	return slpi_pin_functions[function];
}

static int slpi_get_function_groups(struct pinctrl_dev *pctldev,
				   unsigned int function,
				   const char * const **groups,
				   unsigned int * const num_groups)
{
	*groups = slpi_gpio_groups;
	*num_groups = pctldev->desc->npins;
	return 0;
}

static int slpi_pinmux_set_mux(struct pinctrl_dev *pctldev,
			      unsigned int function,
			      unsigned int pin_index)
{
	struct slpi_pin *pin;
	u32 val;

	pin = pctldev->desc->pins[pin_index].drv_data;

	if (WARN_ON(function >= ARRAY_SIZE(slpi_pin_functions)))
		return -EINVAL;

	val = slpi_read(pin, pin->ctl_reg);
	val &= ~(0x7 << pin->mux_bit);
	val |= function << pin->mux_bit;
	slpi_write(val, pin, pin->ctl_reg);

	return 0;
}

static const struct pinmux_ops slpi_pinmux_ops = {
	.get_functions_count	= slpi_get_functions_count,
	.get_function_name	= slpi_get_function_name,
	.get_function_groups	= slpi_get_function_groups,
	.set_mux		= slpi_pinmux_set_mux,
};

static int slpi_config_reg(const struct slpi_pin *pin,
			  unsigned int param,
			  unsigned int *mask,
			  unsigned int *bit)
{
	switch (param) {
	case PIN_CONFIG_BIAS_DISABLE:
	case PIN_CONFIG_BIAS_PULL_DOWN:
	case PIN_CONFIG_BIAS_BUS_HOLD:
	case PIN_CONFIG_BIAS_PULL_UP:
		*bit = pin->pull_bit;
		*mask = 3;
		break;
	case PIN_CONFIG_DRIVE_STRENGTH:
		*bit = pin->drv_bit;
		*mask = 7;
		break;
	case PIN_CONFIG_OUTPUT:
	case PIN_CONFIG_INPUT_ENABLE:
		*bit = pin->oe_bit;
		*mask = 1;
		break;
	default:
		return -EOPNOTSUPP;
	}

	return 0;
}

#define MSM_NO_PULL	0
#define MSM_PULL_DOWN	1
#define MSM_KEEPER	2
#define MSM_PULL_UP	3

static unsigned int slpi_regval_to_drive(u32 val)
{
	return (val + 1) * 2;
}

static int slpi_config_group_get(struct pinctrl_dev *pctldev,
				unsigned int pin_index,
				unsigned long *config)
{
	unsigned int param = pinconf_to_config_param(*config);
	struct slpi_pin *pin;
	unsigned int mask;
	unsigned int arg;
	unsigned int bit;
	int ret;
	u32 val;

	pin = pctldev->desc->pins[pin_index].drv_data;
	ret = slpi_config_reg(pin, param, &mask, &bit);
	if (ret < 0)
		return ret;

	val = slpi_read(pin, pin->ctl_reg);
	arg = (val >> bit) & mask;

	/* Convert register value to pinconf value */
	switch (param) {
	case PIN_CONFIG_BIAS_DISABLE:
		arg = arg == MSM_NO_PULL;
		break;
	case PIN_CONFIG_BIAS_PULL_DOWN:
		arg = arg == MSM_PULL_DOWN;
		break;
	case PIN_CONFIG_BIAS_BUS_HOLD:
		arg = arg == MSM_KEEPER;
		break;
	case PIN_CONFIG_BIAS_PULL_UP:
		arg = arg == MSM_PULL_UP;
		break;
	case PIN_CONFIG_DRIVE_STRENGTH:
		arg = slpi_regval_to_drive(arg);
		break;
	case PIN_CONFIG_OUTPUT:
		/* Pin is not output */
		if (!arg)
			return -EINVAL;

		val = slpi_read(pin, pin->io_reg);
		arg = !!(val & BIT(pin->in_bit));
		break;
	case PIN_CONFIG_INPUT_ENABLE:
		/* Pin is output */
		if (arg)
			return -EINVAL;
		arg = 1;
		break;
	default:
		return -EOPNOTSUPP;
	}

	*config = pinconf_to_config_packed(param, arg);

	return 0;
}

static int slpi_config_group_set(struct pinctrl_dev *pctldev,
				unsigned int pin_index,
				unsigned long *configs,
				unsigned int num_configs)
{
	struct slpi_pin *pin;
	unsigned int param;
	unsigned int mask;
	unsigned int arg;
	unsigned int bit;
	int ret;
	u32 val;
	int i;

	pin = pctldev->desc->pins[pin_index].drv_data;

	for (i = 0; i < num_configs; i++) {
		param = pinconf_to_config_param(configs[i]);
		arg = pinconf_to_config_argument(configs[i]);

		ret = slpi_config_reg(pin, param, &mask, &bit);
		if (ret < 0)
			return ret;

		/* Convert pinconf values to register values */
		switch (param) {
		case PIN_CONFIG_BIAS_DISABLE:
			arg = MSM_NO_PULL;
			break;
		case PIN_CONFIG_BIAS_PULL_DOWN:
			arg = MSM_PULL_DOWN;
			break;
		case PIN_CONFIG_BIAS_BUS_HOLD:
			arg = MSM_KEEPER;
			break;
		case PIN_CONFIG_BIAS_PULL_UP:
			arg = MSM_PULL_UP;
			break;
		case PIN_CONFIG_DRIVE_STRENGTH:
			/* Check for invalid values */
			if (arg > 16 || arg < 2 || (arg % 2) != 0)
				arg = -1;
			else
				arg = (arg / 2) - 1;
			break;
		case PIN_CONFIG_OUTPUT:
			/* set output value */
			val = slpi_read(pin, pin->io_reg);
			if (arg)
				val |= BIT(pin->out_bit);
			else
				val &= ~BIT(pin->out_bit);
			slpi_write(val, pin, pin->io_reg);

			/* enable output */
			arg = 1;
			break;
		case PIN_CONFIG_INPUT_ENABLE:
			/* disable output */
			arg = 0;
			break;
		default:
			dev_err(pctldev->dev, "Unsupported config parameter: %x\n",
				param);
			return -EINVAL;
		}

		/* Range-check user-supplied value */
		if (arg & ~mask) {
			dev_err(pctldev->dev, "config %x: %x is invalid\n",
								param, arg);
			return -EINVAL;
		}

		val = slpi_read(pin, pin->ctl_reg);
		val &= ~(mask << bit);
		val |= arg << bit;
		slpi_write(val, pin, pin->ctl_reg);
	}

	return 0;
}

static const struct pinconf_ops slpi_pinconf_ops = {
	.is_generic		= true,
	.pin_config_group_get	= slpi_config_group_get,
	.pin_config_group_set	= slpi_config_group_set,
};

static int slpi_pinctrl_probe(struct platform_device *pdev)
{
	struct device *dev = &pdev->dev;
	struct pinctrl_dev *pctldev;
	struct pinctrl_pin_desc *pindesc;
	struct pinctrl_desc *pctrldesc;
	struct slpi_pin *pin, *pins;
	struct resource *res;
	int ret, npins, i;
	void __iomem *base;

	dev_err(dev, "SLPI probe called !!!!!!\n");
	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
	base = devm_ioremap_resource(&pdev->dev, res);
	if (IS_ERR(base))
		return PTR_ERR(base);

	ret = of_property_read_u32(dev->of_node, "qcom,num-pins", &npins);
	if (ret < 0)
		return ret;

	pindesc = devm_kcalloc(dev, npins, sizeof(*pindesc), GFP_KERNEL);
	if (!pindesc)
		return -ENOMEM;

	WARN_ON(npins > ARRAY_SIZE(slpi_gpio_groups));

	pins = devm_kcalloc(dev, npins, sizeof(*pins), GFP_KERNEL);
	if (!pins)
		return -ENOMEM;

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

	pctrldesc->pctlops = &slpi_pinctrl_ops;
	pctrldesc->pmxops = &slpi_pinmux_ops;
	pctrldesc->confops = &slpi_pinconf_ops;
	pctrldesc->owner = THIS_MODULE;
	pctrldesc->name = dev_name(&pdev->dev);
	pctrldesc->pins = pindesc;
	pctrldesc->npins = npins;

	for (i = 0; i < npins; i++, pindesc++) {
		pin = &pins[i];
		pindesc->drv_data = pin;
		pindesc->number = i;
		pindesc->name = slpi_gpio_groups[i];

		pin->base = base;
		pin->offset = i * 0x1000;
		pin->ctl_reg = 0x0;
		pin->io_reg = 0x4;

		pin->pull_bit = 0;
		pin->out_bit = 1;
		pin->mux_bit = 2;
		pin->oe_bit = 9;
		pin->drv_bit = 6;
		pin->in_bit = 0;
	}

	pctldev = devm_pinctrl_register(&pdev->dev, pctrldesc, NULL);
	if (IS_ERR(pctldev)) {
		dev_err(dev, "Failed to register pinctrl device\n");
		return PTR_ERR(pctldev);
	}
	dev_err(dev, "Registered pinctrl SLPI !!!!!!\n");
	return 0;
}

static const struct of_device_id slpi_pinctrl_of_match[] = {
	{ .compatible = "qcom,slpi-pinctrl" }, /* Generic */
	{ },
};

MODULE_DEVICE_TABLE(of, slpi_pinctrl_of_match);

static struct platform_driver slpi_pinctrl_driver = {
	.driver = {
		   .name = "qcom-slpi-pinctrl",
		   .of_match_table = slpi_pinctrl_of_match,
	},
	.probe = slpi_pinctrl_probe,
};

static int __init slpi_pinctrl_init(void)
{
	return platform_driver_register(&slpi_pinctrl_driver);
}
arch_initcall(slpi_pinctrl_init);

static void __exit slpi_pinctrl_exit(void)
{
	platform_driver_unregister(&slpi_pinctrl_driver);
}
module_exit(slpi_pinctrl_exit);

MODULE_DESCRIPTION("QTI SLPI GPIO pin control driver");
MODULE_LICENSE("GPL v2");