File Index
Files and directories
Sign in
FILE

gpio-zynqmp-modepin.c

File preview with syntax highlighting.

linux-6.19.14/drivers/gpio/gpio-zynqmp-modepin.c C
  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 int 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	return ret;
 82}
 83
 84/**
 85 * modepin_gpio_dir_in - Set the direction of the specified GPIO pin as input
 86 * @chip:	gpio_chip instance to be worked on
 87 * @pin:	gpio pin number within the device
 88 *
 89 * Return: 0 always
 90 */
 91static int modepin_gpio_dir_in(struct gpio_chip *chip, unsigned int pin)
 92{
 93	return 0;
 94}
 95
 96/**
 97 * modepin_gpio_dir_out - Set the direction of the specified GPIO pin as output
 98 * @chip:	gpio_chip instance to be worked on
 99 * @pin:	gpio pin number within the device
100 * @state:	value to be written to specified pin
101 *
102 * Return: 0 always
103 */
104static int modepin_gpio_dir_out(struct gpio_chip *chip, unsigned int pin,
105				int state)
106{
107	return modepin_gpio_set_value(chip, pin, state);
108}
109
110/**
111 * modepin_gpio_probe - Initialization method for modepin_gpio
112 * @pdev:		platform device instance
113 *
114 * Return: 0 on success, negative error otherwise.
115 */
116static int modepin_gpio_probe(struct platform_device *pdev)
117{
118	struct gpio_chip *chip;
119	int status;
120
121	chip = devm_kzalloc(&pdev->dev, sizeof(*chip), GFP_KERNEL);
122	if (!chip)
123		return -ENOMEM;
124
125	platform_set_drvdata(pdev, chip);
126
127	/* configure the gpio chip */
128	chip->base = -1;
129	chip->ngpio = MODE_PINS;
130	chip->owner = THIS_MODULE;
131	chip->parent = &pdev->dev;
132	chip->get = modepin_gpio_get_value;
133	chip->set = modepin_gpio_set_value;
134	chip->direction_input = modepin_gpio_dir_in;
135	chip->direction_output = modepin_gpio_dir_out;
136	chip->label = dev_name(&pdev->dev);
137
138	/* modepin gpio registration */
139	status = devm_gpiochip_add_data(&pdev->dev, chip, chip);
140	if (status)
141		return dev_err_probe(&pdev->dev, status,
142			      "Failed to add GPIO chip\n");
143
144	return status;
145}
146
147static const struct of_device_id modepin_platform_id[] = {
148	{ .compatible = "xlnx,zynqmp-gpio-modepin", },
149	{ }
150};
151MODULE_DEVICE_TABLE(of, modepin_platform_id);
152
153static struct platform_driver modepin_platform_driver = {
154	.driver = {
155		.name = "modepin-gpio",
156		.of_match_table = modepin_platform_id,
157	},
158	.probe = modepin_gpio_probe,
159};
160
161module_platform_driver(modepin_platform_driver);
162
163MODULE_AUTHOR("Piyush Mehta <piyush.mehta@xilinx.com>");
164MODULE_DESCRIPTION("ZynqMP Boot PS_MODE Configuration");
165MODULE_LICENSE("GPL v2");
~/ Read-only file preview.