// SPDX-License-Identifier: GPL-2.0
/*
* Driver for the ps - mode pin configuration .
*
* Copyright ( c ) 2021 Xilinx , Inc .
*/
#include <linux/delay.h>
#include <linux/err.h>
#include <linux/gpio/driver.h>
#include <linux/io.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/slab.h>
#include <linux/firmware/xlnx-zynqmp.h>
/* 4-bit boot mode pins */
#define MODE_PINS 4
/**
* modepin_gpio_get_value - Get the state of the specified pin of GPIO device
* @ chip : gpio_chip instance to be worked on
* @ pin : gpio pin number within the device
*
* This function reads the state of the specified pin of the GPIO device .
*
* Return : 0 if the pin is low , 1 if pin is high , - EINVAL wrong pin configured
* or error value .
*/
static int modepin_gpio_get_value(struct gpio_chip *chip, unsigned int pin)
{
u32 regval = 0 ;
int ret;
ret = zynqmp_pm_bootmode_read(®val);
if (ret)
return ret;
/* When [0:3] corresponding bit is set, then read output bit [8:11],
* if the bit is clear then read input bit [ 4 : 7 ] for status or value .
*/
if (regval & BIT(pin))
return !!(regval & BIT(pin + 8 ));
else
return !!(regval & BIT(pin + 4 ));
}
/**
* modepin_gpio_set_value - Modify the state of the pin with specified value
* @ chip : gpio_chip instance to be worked on
* @ pin : gpio pin number within the device
* @ state : value used to modify the state of the specified pin
*
* This function reads the state of the specified pin of the GPIO device , mask
* with the capture state of GPIO pin , and update pin of GPIO device .
*
* Return : None .
*/
static int modepin_gpio_set_value(struct gpio_chip *chip, unsigned int pin,
int state)
{
u32 bootpin_val = 0 ;
int ret;
zynqmp_pm_bootmode_read(&bootpin_val);
/* Configure pin as an output by set bit [0:3] */
bootpin_val |= BIT(pin);
if (state)
bootpin_val |= BIT(pin + 8 );
else
bootpin_val &= ~BIT(pin + 8 );
/* Configure bootpin value */
ret = zynqmp_pm_bootmode_write(bootpin_val);
if (ret)
pr_err("modepin: set value error %d for pin %d\n" , ret, pin);
return ret;
}
/**
* modepin_gpio_dir_in - Set the direction of the specified GPIO pin as input
* @ chip : gpio_chip instance to be worked on
* @ pin : gpio pin number within the device
*
* Return : 0 always
*/
static int modepin_gpio_dir_in(struct gpio_chip *chip, unsigned int pin)
{
return 0 ;
}
/**
* modepin_gpio_dir_out - Set the direction of the specified GPIO pin as output
* @ chip : gpio_chip instance to be worked on
* @ pin : gpio pin number within the device
* @ state : value to be written to specified pin
*
* Return : 0 always
*/
static int modepin_gpio_dir_out(struct gpio_chip *chip, unsigned int pin,
int state)
{
return modepin_gpio_set_value(chip, pin, state);
}
/**
* modepin_gpio_probe - Initialization method for modepin_gpio
* @ pdev : platform device instance
*
* Return : 0 on success , negative error otherwise .
*/
static int modepin_gpio_probe(struct platform_device *pdev)
{
struct gpio_chip *chip;
int status;
chip = devm_kzalloc(&pdev->dev, sizeof (*chip), GFP_KERNEL);
if (!chip)
return -ENOMEM;
platform_set_drvdata(pdev, chip);
/* configure the gpio chip */
chip->base = -1 ;
chip->ngpio = MODE_PINS;
chip->owner = THIS_MODULE;
chip->parent = &pdev->dev;
chip->get = modepin_gpio_get_value;
chip->set = modepin_gpio_set_value;
chip->direction_input = modepin_gpio_dir_in;
chip->direction_output = modepin_gpio_dir_out;
chip->label = dev_name(&pdev->dev);
/* modepin gpio registration */
status = devm_gpiochip_add_data(&pdev->dev, chip, chip);
if (status)
return dev_err_probe(&pdev->dev, status,
"Failed to add GPIO chip\n" );
return status;
}
static const struct of_device_id modepin_platform_id[] = {
{ .compatible = "xlnx,zynqmp-gpio-modepin" , },
{ }
};
MODULE_DEVICE_TABLE(of, modepin_platform_id);
static struct platform_driver modepin_platform_driver = {
.driver = {
.name = "modepin-gpio" ,
.of_match_table = modepin_platform_id,
},
.probe = modepin_gpio_probe,
};
module_platform_driver(modepin_platform_driver);
MODULE_AUTHOR("Piyush Mehta <piyush.mehta@xilinx.com>" );
MODULE_DESCRIPTION("ZynqMP Boot PS_MODE Configuration" );
MODULE_LICENSE("GPL v2" );
Messung V0.5 in Prozent C=93 H=100 G=96
¤ Dauer der Verarbeitung: 0.10 Sekunden
(vorverarbeitet am 2026-09-29)
¤
*© Formatika GbR, Deutschland