0001
0002
0003
0004
0005
0006
0007
0008 #include <linux/delay.h>
0009 #include <linux/err.h>
0010 #include <linux/gpio/driver.h>
0011 #include <linux/io.h>
0012 #include <linux/kernel.h>
0013 #include <linux/module.h>
0014 #include <linux/platform_device.h>
0015 #include <linux/slab.h>
0016 #include <linux/firmware/xlnx-zynqmp.h>
0017
0018
0019 #define MODE_PINS 4
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031 static int modepin_gpio_get_value(struct gpio_chip *chip, unsigned int pin)
0032 {
0033 u32 regval = 0;
0034 int ret;
0035
0036 ret = zynqmp_pm_bootmode_read(®val);
0037 if (ret)
0038 return ret;
0039
0040
0041
0042
0043 if (regval & BIT(pin))
0044 return !!(regval & BIT(pin + 8));
0045 else
0046 return !!(regval & BIT(pin + 4));
0047 }
0048
0049
0050
0051
0052
0053
0054
0055
0056
0057
0058
0059
0060 static void modepin_gpio_set_value(struct gpio_chip *chip, unsigned int pin,
0061 int state)
0062 {
0063 u32 bootpin_val = 0;
0064 int ret;
0065
0066 zynqmp_pm_bootmode_read(&bootpin_val);
0067
0068
0069 bootpin_val |= BIT(pin);
0070
0071 if (state)
0072 bootpin_val |= BIT(pin + 8);
0073 else
0074 bootpin_val &= ~BIT(pin + 8);
0075
0076
0077 ret = zynqmp_pm_bootmode_write(bootpin_val);
0078 if (ret)
0079 pr_err("modepin: set value error %d for pin %d\n", ret, pin);
0080 }
0081
0082
0083
0084
0085
0086
0087
0088
0089 static int modepin_gpio_dir_in(struct gpio_chip *chip, unsigned int pin)
0090 {
0091 return 0;
0092 }
0093
0094
0095
0096
0097
0098
0099
0100
0101
0102 static int modepin_gpio_dir_out(struct gpio_chip *chip, unsigned int pin,
0103 int state)
0104 {
0105 return 0;
0106 }
0107
0108
0109
0110
0111
0112
0113
0114 static int modepin_gpio_probe(struct platform_device *pdev)
0115 {
0116 struct gpio_chip *chip;
0117 int status;
0118
0119 chip = devm_kzalloc(&pdev->dev, sizeof(*chip), GFP_KERNEL);
0120 if (!chip)
0121 return -ENOMEM;
0122
0123 platform_set_drvdata(pdev, chip);
0124
0125
0126 chip->base = -1;
0127 chip->ngpio = MODE_PINS;
0128 chip->owner = THIS_MODULE;
0129 chip->parent = &pdev->dev;
0130 chip->get = modepin_gpio_get_value;
0131 chip->set = modepin_gpio_set_value;
0132 chip->direction_input = modepin_gpio_dir_in;
0133 chip->direction_output = modepin_gpio_dir_out;
0134 chip->label = dev_name(&pdev->dev);
0135
0136
0137 status = devm_gpiochip_add_data(&pdev->dev, chip, chip);
0138 if (status)
0139 return dev_err_probe(&pdev->dev, status,
0140 "Failed to add GPIO chip\n");
0141
0142 return status;
0143 }
0144
0145 static const struct of_device_id modepin_platform_id[] = {
0146 { .compatible = "xlnx,zynqmp-gpio-modepin", },
0147 { }
0148 };
0149
0150 static struct platform_driver modepin_platform_driver = {
0151 .driver = {
0152 .name = "modepin-gpio",
0153 .of_match_table = modepin_platform_id,
0154 },
0155 .probe = modepin_gpio_probe,
0156 };
0157
0158 module_platform_driver(modepin_platform_driver);
0159
0160 MODULE_AUTHOR("Piyush Mehta <piyush.mehta@xilinx.com>");
0161 MODULE_DESCRIPTION("ZynqMP Boot PS_MODE Configuration");
0162 MODULE_LICENSE("GPL v2");