cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

pinctrl-da850-pupd.c (4966B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/*
      3 * Pinconf driver for TI DA850/OMAP-L138/AM18XX pullup/pulldown groups
      4 *
      5 * Copyright (C) 2016  David Lechner
      6 */
      7
      8#include <linux/bitops.h>
      9#include <linux/device.h>
     10#include <linux/io.h>
     11#include <linux/ioport.h>
     12#include <linux/mod_devicetable.h>
     13#include <linux/module.h>
     14#include <linux/pinctrl/pinconf.h>
     15#include <linux/pinctrl/pinconf-generic.h>
     16#include <linux/pinctrl/pinctrl.h>
     17#include <linux/platform_device.h>
     18
     19#define DA850_PUPD_ENA		0x00
     20#define DA850_PUPD_SEL		0x04
     21
     22struct da850_pupd_data {
     23	void __iomem *base;
     24	struct pinctrl_desc desc;
     25	struct pinctrl_dev *pinctrl;
     26};
     27
     28static const char * const da850_pupd_group_names[] = {
     29	"cp0", "cp1", "cp2", "cp3", "cp4", "cp5", "cp6", "cp7",
     30	"cp8", "cp9", "cp10", "cp11", "cp12", "cp13", "cp14", "cp15",
     31	"cp16", "cp17", "cp18", "cp19", "cp20", "cp21", "cp22", "cp23",
     32	"cp24", "cp25", "cp26", "cp27", "cp28", "cp29", "cp30", "cp31",
     33};
     34
     35static int da850_pupd_get_groups_count(struct pinctrl_dev *pctldev)
     36{
     37	return ARRAY_SIZE(da850_pupd_group_names);
     38}
     39
     40static const char *da850_pupd_get_group_name(struct pinctrl_dev *pctldev,
     41					     unsigned int selector)
     42{
     43	return da850_pupd_group_names[selector];
     44}
     45
     46static int da850_pupd_get_group_pins(struct pinctrl_dev *pctldev,
     47				     unsigned int selector,
     48				     const unsigned int **pins,
     49				     unsigned int *num_pins)
     50{
     51	*num_pins = 0;
     52
     53	return 0;
     54}
     55
     56static const struct pinctrl_ops da850_pupd_pctlops = {
     57	.get_groups_count	= da850_pupd_get_groups_count,
     58	.get_group_name		= da850_pupd_get_group_name,
     59	.get_group_pins		= da850_pupd_get_group_pins,
     60	.dt_node_to_map		= pinconf_generic_dt_node_to_map_group,
     61	.dt_free_map		= pinconf_generic_dt_free_map,
     62};
     63
     64static int da850_pupd_pin_config_group_get(struct pinctrl_dev *pctldev,
     65					   unsigned int selector,
     66					   unsigned long *config)
     67{
     68	struct da850_pupd_data *data = pinctrl_dev_get_drvdata(pctldev);
     69	enum pin_config_param param = pinconf_to_config_param(*config);
     70	u32 val;
     71	u16 arg;
     72
     73	val = readl(data->base + DA850_PUPD_ENA);
     74	arg = !!(~val & BIT(selector));
     75
     76	switch (param) {
     77	case PIN_CONFIG_BIAS_DISABLE:
     78		break;
     79	case PIN_CONFIG_BIAS_PULL_UP:
     80	case PIN_CONFIG_BIAS_PULL_DOWN:
     81		if (arg) {
     82			/* bias is disabled */
     83			arg = 0;
     84			break;
     85		}
     86		val = readl(data->base + DA850_PUPD_SEL);
     87		if (param == PIN_CONFIG_BIAS_PULL_DOWN)
     88			val = ~val;
     89		arg = !!(val & BIT(selector));
     90		break;
     91	default:
     92		return -EINVAL;
     93	}
     94
     95	*config = pinconf_to_config_packed(param, arg);
     96
     97	return 0;
     98}
     99
    100static int da850_pupd_pin_config_group_set(struct pinctrl_dev *pctldev,
    101					   unsigned int selector,
    102					   unsigned long *configs,
    103					   unsigned int num_configs)
    104{
    105	struct da850_pupd_data *data = pinctrl_dev_get_drvdata(pctldev);
    106	u32 ena, sel;
    107	enum pin_config_param param;
    108	int i;
    109
    110	ena = readl(data->base + DA850_PUPD_ENA);
    111	sel = readl(data->base + DA850_PUPD_SEL);
    112
    113	for (i = 0; i < num_configs; i++) {
    114		param = pinconf_to_config_param(configs[i]);
    115
    116		switch (param) {
    117		case PIN_CONFIG_BIAS_DISABLE:
    118			ena &= ~BIT(selector);
    119			break;
    120		case PIN_CONFIG_BIAS_PULL_UP:
    121			ena |= BIT(selector);
    122			sel |= BIT(selector);
    123			break;
    124		case PIN_CONFIG_BIAS_PULL_DOWN:
    125			ena |= BIT(selector);
    126			sel &= ~BIT(selector);
    127			break;
    128		default:
    129			return -EINVAL;
    130		}
    131	}
    132
    133	writel(sel, data->base + DA850_PUPD_SEL);
    134	writel(ena, data->base + DA850_PUPD_ENA);
    135
    136	return 0;
    137}
    138
    139static const struct pinconf_ops da850_pupd_confops = {
    140	.is_generic		= true,
    141	.pin_config_group_get	= da850_pupd_pin_config_group_get,
    142	.pin_config_group_set	= da850_pupd_pin_config_group_set,
    143};
    144
    145static int da850_pupd_probe(struct platform_device *pdev)
    146{
    147	struct device *dev = &pdev->dev;
    148	struct da850_pupd_data *data;
    149
    150	data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
    151	if (!data)
    152		return -ENOMEM;
    153
    154	data->base = devm_platform_ioremap_resource(pdev, 0);
    155	if (IS_ERR(data->base)) {
    156		dev_err(dev, "Could not map resource\n");
    157		return PTR_ERR(data->base);
    158	}
    159
    160	data->desc.name = dev_name(dev);
    161	data->desc.pctlops = &da850_pupd_pctlops;
    162	data->desc.confops = &da850_pupd_confops;
    163	data->desc.owner = THIS_MODULE;
    164
    165	data->pinctrl = devm_pinctrl_register(dev, &data->desc, data);
    166	if (IS_ERR(data->pinctrl)) {
    167		dev_err(dev, "Failed to register pinctrl\n");
    168		return PTR_ERR(data->pinctrl);
    169	}
    170
    171	platform_set_drvdata(pdev, data);
    172
    173	return 0;
    174}
    175
    176static int da850_pupd_remove(struct platform_device *pdev)
    177{
    178	return 0;
    179}
    180
    181static const struct of_device_id da850_pupd_of_match[] = {
    182	{ .compatible = "ti,da850-pupd" },
    183	{ }
    184};
    185MODULE_DEVICE_TABLE(of, da850_pupd_of_match);
    186
    187static struct platform_driver da850_pupd_driver = {
    188	.driver	= {
    189		.name		= "ti-da850-pupd",
    190		.of_match_table	= da850_pupd_of_match,
    191	},
    192	.probe	= da850_pupd_probe,
    193	.remove	= da850_pupd_remove,
    194};
    195module_platform_driver(da850_pupd_driver);
    196
    197MODULE_AUTHOR("David Lechner <david@lechnology.com>");
    198MODULE_DESCRIPTION("TI DA850/OMAP-L138/AM18XX pullup/pulldown configuration");
    199MODULE_LICENSE("GPL");