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

gpio-zynqmp-modepin.c (4159B)


      1// SPDX-License-Identifier: GPL-2.0
      2/*
      3 * Driver for the ps-mode pin configuration.
      4 *
      5 * Copyright (c) 2021 Xilinx, Inc.
      6 */
      7
      8#include <linux/delay.h>
      9#include <linux/err.h>
     10#include <linux/gpio/driver.h>
     11#include <linux/io.h>
     12#include <linux/kernel.h>
     13#include <linux/module.h>
     14#include <linux/platform_device.h>
     15#include <linux/slab.h>
     16#include <linux/firmware/xlnx-zynqmp.h>
     17
     18/* 4-bit boot mode pins */
     19#define MODE_PINS			4
     20
     21/**
     22 * modepin_gpio_get_value - Get the state of the specified pin of GPIO device
     23 * @chip:	gpio_chip instance to be worked on
     24 * @pin:	gpio pin number within the device
     25 *
     26 * This function reads the state of the specified pin of the GPIO device.
     27 *
     28 * Return: 0 if the pin is low, 1 if pin is high, -EINVAL wrong pin configured
     29 *         or error value.
     30 */
     31static int modepin_gpio_get_value(struct gpio_chip *chip, unsigned int pin)
     32{
     33	u32 regval = 0;
     34	int ret;
     35
     36	ret = zynqmp_pm_bootmode_read(&regval);
     37	if (ret)
     38		return ret;
     39
     40	/* When [0:3] corresponding bit is set, then read output bit [8:11],
     41	 * if the bit is clear then read input bit [4:7] for status or value.
     42	 */
     43	if (regval & BIT(pin))
     44		return !!(regval & BIT(pin + 8));
     45	else
     46		return !!(regval & BIT(pin + 4));
     47}
     48
     49/**
     50 * modepin_gpio_set_value - Modify the state of the pin with specified value
     51 * @chip:	gpio_chip instance to be worked on
     52 * @pin:	gpio pin number within the device
     53 * @state:	value used to modify the state of the specified pin
     54 *
     55 * This function reads the state of the specified pin of the GPIO device, mask
     56 * with the capture state of GPIO pin, and update pin of GPIO device.
     57 *
     58 * Return:	None.
     59 */
     60static void modepin_gpio_set_value(struct gpio_chip *chip, unsigned int pin,
     61				   int state)
     62{
     63	u32 bootpin_val = 0;
     64	int ret;
     65
     66	zynqmp_pm_bootmode_read(&bootpin_val);
     67
     68	/* Configure pin as an output by set bit [0:3] */
     69	bootpin_val |= BIT(pin);
     70
     71	if (state)
     72		bootpin_val |= BIT(pin + 8);
     73	else
     74		bootpin_val &= ~BIT(pin + 8);
     75
     76	/* Configure bootpin value */
     77	ret = zynqmp_pm_bootmode_write(bootpin_val);
     78	if (ret)
     79		pr_err("modepin: set value error %d for pin %d\n", ret, pin);
     80}
     81
     82/**
     83 * modepin_gpio_dir_in - Set the direction of the specified GPIO pin as input
     84 * @chip:	gpio_chip instance to be worked on
     85 * @pin:	gpio pin number within the device
     86 *
     87 * Return: 0 always
     88 */
     89static int modepin_gpio_dir_in(struct gpio_chip *chip, unsigned int pin)
     90{
     91	return 0;
     92}
     93
     94/**
     95 * modepin_gpio_dir_out - Set the direction of the specified GPIO pin as output
     96 * @chip:	gpio_chip instance to be worked on
     97 * @pin:	gpio pin number within the device
     98 * @state:	value to be written to specified pin
     99 *
    100 * Return: 0 always
    101 */
    102static int modepin_gpio_dir_out(struct gpio_chip *chip, unsigned int pin,
    103				int state)
    104{
    105	return 0;
    106}
    107
    108/**
    109 * modepin_gpio_probe - Initialization method for modepin_gpio
    110 * @pdev:		platform device instance
    111 *
    112 * Return: 0 on success, negative error otherwise.
    113 */
    114static int modepin_gpio_probe(struct platform_device *pdev)
    115{
    116	struct gpio_chip *chip;
    117	int status;
    118
    119	chip = devm_kzalloc(&pdev->dev, sizeof(*chip), GFP_KERNEL);
    120	if (!chip)
    121		return -ENOMEM;
    122
    123	platform_set_drvdata(pdev, chip);
    124
    125	/* configure the gpio chip */
    126	chip->base = -1;
    127	chip->ngpio = MODE_PINS;
    128	chip->owner = THIS_MODULE;
    129	chip->parent = &pdev->dev;
    130	chip->get = modepin_gpio_get_value;
    131	chip->set = modepin_gpio_set_value;
    132	chip->direction_input = modepin_gpio_dir_in;
    133	chip->direction_output = modepin_gpio_dir_out;
    134	chip->label = dev_name(&pdev->dev);
    135
    136	/* modepin gpio registration */
    137	status = devm_gpiochip_add_data(&pdev->dev, chip, chip);
    138	if (status)
    139		return dev_err_probe(&pdev->dev, status,
    140			      "Failed to add GPIO chip\n");
    141
    142	return status;
    143}
    144
    145static const struct of_device_id modepin_platform_id[] = {
    146	{ .compatible = "xlnx,zynqmp-gpio-modepin", },
    147	{ }
    148};
    149
    150static struct platform_driver modepin_platform_driver = {
    151	.driver = {
    152		.name = "modepin-gpio",
    153		.of_match_table = modepin_platform_id,
    154	},
    155	.probe = modepin_gpio_probe,
    156};
    157
    158module_platform_driver(modepin_platform_driver);
    159
    160MODULE_AUTHOR("Piyush Mehta <piyush.mehta@xilinx.com>");
    161MODULE_DESCRIPTION("ZynqMP Boot PS_MODE Configuration");
    162MODULE_LICENSE("GPL v2");