0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011 #include <linux/err.h>
0012 #include <linux/gpio/driver.h>
0013 #include <linux/module.h>
0014 #include <linux/platform_device.h>
0015 #include <soc/bcm2835/raspberrypi-firmware.h>
0016
0017 #define MODULE_NAME "raspberrypi-exp-gpio"
0018 #define NUM_GPIO 8
0019
0020 #define RPI_EXP_GPIO_BASE 128
0021
0022 #define RPI_EXP_GPIO_DIR_IN 0
0023 #define RPI_EXP_GPIO_DIR_OUT 1
0024
0025 struct rpi_exp_gpio {
0026 struct gpio_chip gc;
0027 struct rpi_firmware *fw;
0028 };
0029
0030
0031
0032 struct gpio_set_config {
0033 u32 gpio;
0034 u32 direction;
0035 u32 polarity;
0036 u32 term_en;
0037 u32 term_pull_up;
0038 u32 state;
0039 };
0040
0041 struct gpio_get_config {
0042 u32 gpio;
0043 u32 direction;
0044 u32 polarity;
0045 u32 term_en;
0046 u32 term_pull_up;
0047 };
0048
0049 struct gpio_get_set_state {
0050 u32 gpio;
0051 u32 state;
0052 };
0053
0054 static int rpi_exp_gpio_get_polarity(struct gpio_chip *gc, unsigned int off)
0055 {
0056 struct rpi_exp_gpio *gpio;
0057 struct gpio_get_config get;
0058 int ret;
0059
0060 gpio = gpiochip_get_data(gc);
0061
0062 get.gpio = off + RPI_EXP_GPIO_BASE;
0063
0064 ret = rpi_firmware_property(gpio->fw, RPI_FIRMWARE_GET_GPIO_CONFIG,
0065 &get, sizeof(get));
0066 if (ret || get.gpio != 0) {
0067 dev_err(gc->parent, "Failed to get GPIO %u config (%d %x)\n",
0068 off, ret, get.gpio);
0069 return ret ? ret : -EIO;
0070 }
0071 return get.polarity;
0072 }
0073
0074 static int rpi_exp_gpio_dir_in(struct gpio_chip *gc, unsigned int off)
0075 {
0076 struct rpi_exp_gpio *gpio;
0077 struct gpio_set_config set_in;
0078 int ret;
0079
0080 gpio = gpiochip_get_data(gc);
0081
0082 set_in.gpio = off + RPI_EXP_GPIO_BASE;
0083 set_in.direction = RPI_EXP_GPIO_DIR_IN;
0084 set_in.term_en = 0;
0085 set_in.term_pull_up = 0;
0086 set_in.state = 0;
0087
0088 ret = rpi_exp_gpio_get_polarity(gc, off);
0089 if (ret < 0)
0090 return ret;
0091 set_in.polarity = ret;
0092
0093 ret = rpi_firmware_property(gpio->fw, RPI_FIRMWARE_SET_GPIO_CONFIG,
0094 &set_in, sizeof(set_in));
0095 if (ret || set_in.gpio != 0) {
0096 dev_err(gc->parent, "Failed to set GPIO %u to input (%d %x)\n",
0097 off, ret, set_in.gpio);
0098 return ret ? ret : -EIO;
0099 }
0100 return 0;
0101 }
0102
0103 static int rpi_exp_gpio_dir_out(struct gpio_chip *gc, unsigned int off, int val)
0104 {
0105 struct rpi_exp_gpio *gpio;
0106 struct gpio_set_config set_out;
0107 int ret;
0108
0109 gpio = gpiochip_get_data(gc);
0110
0111 set_out.gpio = off + RPI_EXP_GPIO_BASE;
0112 set_out.direction = RPI_EXP_GPIO_DIR_OUT;
0113 set_out.term_en = 0;
0114 set_out.term_pull_up = 0;
0115 set_out.state = val;
0116
0117 ret = rpi_exp_gpio_get_polarity(gc, off);
0118 if (ret < 0)
0119 return ret;
0120 set_out.polarity = ret;
0121
0122 ret = rpi_firmware_property(gpio->fw, RPI_FIRMWARE_SET_GPIO_CONFIG,
0123 &set_out, sizeof(set_out));
0124 if (ret || set_out.gpio != 0) {
0125 dev_err(gc->parent, "Failed to set GPIO %u to output (%d %x)\n",
0126 off, ret, set_out.gpio);
0127 return ret ? ret : -EIO;
0128 }
0129 return 0;
0130 }
0131
0132 static int rpi_exp_gpio_get_direction(struct gpio_chip *gc, unsigned int off)
0133 {
0134 struct rpi_exp_gpio *gpio;
0135 struct gpio_get_config get;
0136 int ret;
0137
0138 gpio = gpiochip_get_data(gc);
0139
0140 get.gpio = off + RPI_EXP_GPIO_BASE;
0141
0142 ret = rpi_firmware_property(gpio->fw, RPI_FIRMWARE_GET_GPIO_CONFIG,
0143 &get, sizeof(get));
0144 if (ret || get.gpio != 0) {
0145 dev_err(gc->parent,
0146 "Failed to get GPIO %u config (%d %x)\n", off, ret,
0147 get.gpio);
0148 return ret ? ret : -EIO;
0149 }
0150 if (get.direction)
0151 return GPIO_LINE_DIRECTION_OUT;
0152
0153 return GPIO_LINE_DIRECTION_IN;
0154 }
0155
0156 static int rpi_exp_gpio_get(struct gpio_chip *gc, unsigned int off)
0157 {
0158 struct rpi_exp_gpio *gpio;
0159 struct gpio_get_set_state get;
0160 int ret;
0161
0162 gpio = gpiochip_get_data(gc);
0163
0164 get.gpio = off + RPI_EXP_GPIO_BASE;
0165 get.state = 0;
0166
0167 ret = rpi_firmware_property(gpio->fw, RPI_FIRMWARE_GET_GPIO_STATE,
0168 &get, sizeof(get));
0169 if (ret || get.gpio != 0) {
0170 dev_err(gc->parent,
0171 "Failed to get GPIO %u state (%d %x)\n", off, ret,
0172 get.gpio);
0173 return ret ? ret : -EIO;
0174 }
0175 return !!get.state;
0176 }
0177
0178 static void rpi_exp_gpio_set(struct gpio_chip *gc, unsigned int off, int val)
0179 {
0180 struct rpi_exp_gpio *gpio;
0181 struct gpio_get_set_state set;
0182 int ret;
0183
0184 gpio = gpiochip_get_data(gc);
0185
0186 set.gpio = off + RPI_EXP_GPIO_BASE;
0187 set.state = val;
0188
0189 ret = rpi_firmware_property(gpio->fw, RPI_FIRMWARE_SET_GPIO_STATE,
0190 &set, sizeof(set));
0191 if (ret || set.gpio != 0)
0192 dev_err(gc->parent,
0193 "Failed to set GPIO %u state (%d %x)\n", off, ret,
0194 set.gpio);
0195 }
0196
0197 static int rpi_exp_gpio_probe(struct platform_device *pdev)
0198 {
0199 struct device *dev = &pdev->dev;
0200 struct device_node *np = dev->of_node;
0201 struct device_node *fw_node;
0202 struct rpi_firmware *fw;
0203 struct rpi_exp_gpio *rpi_gpio;
0204
0205 fw_node = of_get_parent(np);
0206 if (!fw_node) {
0207 dev_err(dev, "Missing firmware node\n");
0208 return -ENOENT;
0209 }
0210
0211 fw = devm_rpi_firmware_get(&pdev->dev, fw_node);
0212 of_node_put(fw_node);
0213 if (!fw)
0214 return -EPROBE_DEFER;
0215
0216 rpi_gpio = devm_kzalloc(dev, sizeof(*rpi_gpio), GFP_KERNEL);
0217 if (!rpi_gpio)
0218 return -ENOMEM;
0219
0220 rpi_gpio->fw = fw;
0221 rpi_gpio->gc.parent = dev;
0222 rpi_gpio->gc.label = MODULE_NAME;
0223 rpi_gpio->gc.owner = THIS_MODULE;
0224 rpi_gpio->gc.base = -1;
0225 rpi_gpio->gc.ngpio = NUM_GPIO;
0226
0227 rpi_gpio->gc.direction_input = rpi_exp_gpio_dir_in;
0228 rpi_gpio->gc.direction_output = rpi_exp_gpio_dir_out;
0229 rpi_gpio->gc.get_direction = rpi_exp_gpio_get_direction;
0230 rpi_gpio->gc.get = rpi_exp_gpio_get;
0231 rpi_gpio->gc.set = rpi_exp_gpio_set;
0232 rpi_gpio->gc.can_sleep = true;
0233
0234 return devm_gpiochip_add_data(dev, &rpi_gpio->gc, rpi_gpio);
0235 }
0236
0237 static const struct of_device_id rpi_exp_gpio_ids[] = {
0238 { .compatible = "raspberrypi,firmware-gpio" },
0239 { }
0240 };
0241 MODULE_DEVICE_TABLE(of, rpi_exp_gpio_ids);
0242
0243 static struct platform_driver rpi_exp_gpio_driver = {
0244 .driver = {
0245 .name = MODULE_NAME,
0246 .of_match_table = of_match_ptr(rpi_exp_gpio_ids),
0247 },
0248 .probe = rpi_exp_gpio_probe,
0249 };
0250 module_platform_driver(rpi_exp_gpio_driver);
0251
0252 MODULE_LICENSE("GPL");
0253 MODULE_AUTHOR("Dave Stevenson <dave.stevenson@raspberrypi.org>");
0254 MODULE_DESCRIPTION("Raspberry Pi 3 expander GPIO driver");
0255 MODULE_ALIAS("platform:rpi-exp-gpio");