0001
0002
0003
0004
0005
0006
0007
0008 #include <linux/bitops.h>
0009 #include <linux/gpio/driver.h>
0010 #include <linux/moxtet.h>
0011 #include <linux/module.h>
0012
0013 #define MOXTET_GPIO_NGPIOS 12
0014 #define MOXTET_GPIO_INPUTS 4
0015
0016 struct moxtet_gpio_desc {
0017 u16 in_mask;
0018 u16 out_mask;
0019 };
0020
0021 static const struct moxtet_gpio_desc descs[] = {
0022 [TURRIS_MOX_MODULE_SFP] = {
0023 .in_mask = GENMASK(2, 0),
0024 .out_mask = GENMASK(5, 4),
0025 },
0026 };
0027
0028 struct moxtet_gpio_chip {
0029 struct device *dev;
0030 struct gpio_chip gpio_chip;
0031 const struct moxtet_gpio_desc *desc;
0032 };
0033
0034 static int moxtet_gpio_get_value(struct gpio_chip *gc, unsigned int offset)
0035 {
0036 struct moxtet_gpio_chip *chip = gpiochip_get_data(gc);
0037 int ret;
0038
0039 if (chip->desc->in_mask & BIT(offset)) {
0040 ret = moxtet_device_read(chip->dev);
0041 } else if (chip->desc->out_mask & BIT(offset)) {
0042 ret = moxtet_device_written(chip->dev);
0043 if (ret >= 0)
0044 ret <<= MOXTET_GPIO_INPUTS;
0045 } else {
0046 return -EINVAL;
0047 }
0048
0049 if (ret < 0)
0050 return ret;
0051
0052 return !!(ret & BIT(offset));
0053 }
0054
0055 static void moxtet_gpio_set_value(struct gpio_chip *gc, unsigned int offset,
0056 int val)
0057 {
0058 struct moxtet_gpio_chip *chip = gpiochip_get_data(gc);
0059 int state;
0060
0061 state = moxtet_device_written(chip->dev);
0062 if (state < 0)
0063 return;
0064
0065 offset -= MOXTET_GPIO_INPUTS;
0066
0067 if (val)
0068 state |= BIT(offset);
0069 else
0070 state &= ~BIT(offset);
0071
0072 moxtet_device_write(chip->dev, state);
0073 }
0074
0075 static int moxtet_gpio_get_direction(struct gpio_chip *gc, unsigned int offset)
0076 {
0077 struct moxtet_gpio_chip *chip = gpiochip_get_data(gc);
0078
0079
0080 if (chip->desc->in_mask & BIT(offset))
0081 return GPIO_LINE_DIRECTION_IN;
0082 else if (chip->desc->out_mask & BIT(offset))
0083 return GPIO_LINE_DIRECTION_OUT;
0084 else
0085 return -EINVAL;
0086 }
0087
0088 static int moxtet_gpio_direction_input(struct gpio_chip *gc,
0089 unsigned int offset)
0090 {
0091 struct moxtet_gpio_chip *chip = gpiochip_get_data(gc);
0092
0093 if (chip->desc->in_mask & BIT(offset))
0094 return 0;
0095 else if (chip->desc->out_mask & BIT(offset))
0096 return -ENOTSUPP;
0097 else
0098 return -EINVAL;
0099 }
0100
0101 static int moxtet_gpio_direction_output(struct gpio_chip *gc,
0102 unsigned int offset, int val)
0103 {
0104 struct moxtet_gpio_chip *chip = gpiochip_get_data(gc);
0105
0106 if (chip->desc->out_mask & BIT(offset))
0107 moxtet_gpio_set_value(gc, offset, val);
0108 else if (chip->desc->in_mask & BIT(offset))
0109 return -ENOTSUPP;
0110 else
0111 return -EINVAL;
0112
0113 return 0;
0114 }
0115
0116 static int moxtet_gpio_probe(struct device *dev)
0117 {
0118 struct moxtet_gpio_chip *chip;
0119 struct device_node *nc = dev->of_node;
0120 int id;
0121
0122 id = to_moxtet_device(dev)->id;
0123
0124 if (id >= ARRAY_SIZE(descs)) {
0125 dev_err(dev, "%pOF Moxtet device id 0x%x is not supported by gpio-moxtet driver\n",
0126 nc, id);
0127 return -ENOTSUPP;
0128 }
0129
0130 chip = devm_kzalloc(dev, sizeof(*chip), GFP_KERNEL);
0131 if (!chip)
0132 return -ENOMEM;
0133
0134 chip->dev = dev;
0135 chip->gpio_chip.parent = dev;
0136 chip->desc = &descs[id];
0137
0138 dev_set_drvdata(dev, chip);
0139
0140 chip->gpio_chip.label = dev_name(dev);
0141 chip->gpio_chip.get_direction = moxtet_gpio_get_direction;
0142 chip->gpio_chip.direction_input = moxtet_gpio_direction_input;
0143 chip->gpio_chip.direction_output = moxtet_gpio_direction_output;
0144 chip->gpio_chip.get = moxtet_gpio_get_value;
0145 chip->gpio_chip.set = moxtet_gpio_set_value;
0146 chip->gpio_chip.base = -1;
0147
0148 chip->gpio_chip.ngpio = MOXTET_GPIO_NGPIOS;
0149
0150 chip->gpio_chip.can_sleep = true;
0151 chip->gpio_chip.owner = THIS_MODULE;
0152
0153 return devm_gpiochip_add_data(dev, &chip->gpio_chip, chip);
0154 }
0155
0156 static const struct of_device_id moxtet_gpio_dt_ids[] = {
0157 { .compatible = "cznic,moxtet-gpio", },
0158 {},
0159 };
0160 MODULE_DEVICE_TABLE(of, moxtet_gpio_dt_ids);
0161
0162 static const enum turris_mox_module_id moxtet_gpio_module_table[] = {
0163 TURRIS_MOX_MODULE_SFP,
0164 0,
0165 };
0166
0167 static struct moxtet_driver moxtet_gpio_driver = {
0168 .driver = {
0169 .name = "moxtet-gpio",
0170 .of_match_table = moxtet_gpio_dt_ids,
0171 .probe = moxtet_gpio_probe,
0172 },
0173 .id_table = moxtet_gpio_module_table,
0174 };
0175 module_moxtet_driver(moxtet_gpio_driver);
0176
0177 MODULE_AUTHOR("Marek Behun <kabel@kernel.org>");
0178 MODULE_DESCRIPTION("Turris Mox Moxtet GPIO expander");
0179 MODULE_LICENSE("GPL v2");