1 // SPDX-License-Identifier: GPL-2.0
3 * Driver for the ps-mode pin configuration.
5 * Copyright (c) 2021 Xilinx, Inc.
8 #include <linux/delay.h>
10 #include <linux/gpio/driver.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>
18 /* 4-bit boot mode pins */
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
26 * This function reads the state of the specified pin of the GPIO device.
28 * Return: 0 if the pin is low, 1 if pin is high, -EINVAL wrong pin configured
31 static int modepin_gpio_get_value(struct gpio_chip
*chip
, unsigned int pin
)
36 ret
= zynqmp_pm_bootmode_read(®val
);
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.
43 if (regval
& BIT(pin
))
44 return !!(regval
& BIT(pin
+ 8));
46 return !!(regval
& BIT(pin
+ 4));
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
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.
60 static void modepin_gpio_set_value(struct gpio_chip
*chip
, unsigned int pin
,
66 zynqmp_pm_bootmode_read(&bootpin_val
);
68 /* Configure pin as an output by set bit [0:3] */
69 bootpin_val
|= BIT(pin
);
72 bootpin_val
|= BIT(pin
+ 8);
74 bootpin_val
&= ~BIT(pin
+ 8);
76 /* Configure bootpin value */
77 ret
= zynqmp_pm_bootmode_write(bootpin_val
);
79 pr_err("modepin: set value error %d for pin %d\n", ret
, pin
);
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
89 static int modepin_gpio_dir_in(struct gpio_chip
*chip
, unsigned int pin
)
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
102 static int modepin_gpio_dir_out(struct gpio_chip
*chip
, unsigned int pin
,
109 * modepin_gpio_probe - Initialization method for modepin_gpio
110 * @pdev: platform device instance
112 * Return: 0 on success, negative error otherwise.
114 static int modepin_gpio_probe(struct platform_device
*pdev
)
116 struct gpio_chip
*chip
;
119 chip
= devm_kzalloc(&pdev
->dev
, sizeof(*chip
), GFP_KERNEL
);
123 platform_set_drvdata(pdev
, chip
);
125 /* configure the gpio chip */
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
);
136 /* modepin gpio registration */
137 status
= devm_gpiochip_add_data(&pdev
->dev
, chip
, chip
);
139 return dev_err_probe(&pdev
->dev
, status
,
140 "Failed to add GPIO chip\n");
145 static const struct of_device_id modepin_platform_id
[] = {
146 { .compatible
= "xlnx,zynqmp-gpio-modepin", },
149 MODULE_DEVICE_TABLE(of
, modepin_platform_id
);
151 static struct platform_driver modepin_platform_driver
= {
153 .name
= "modepin-gpio",
154 .of_match_table
= modepin_platform_id
,
156 .probe
= modepin_gpio_probe
,
159 module_platform_driver(modepin_platform_driver
);
161 MODULE_AUTHOR("Piyush Mehta <piyush.mehta@xilinx.com>");
162 MODULE_DESCRIPTION("ZynqMP Boot PS_MODE Configuration");
163 MODULE_LICENSE("GPL v2");