#include <common.h>
#include <dm.h>
-#include <dm/device_compat.h>
+#include <log.h>
#include <dm/device-internal.h>
#include <dm/lists.h>
#include <dm/uclass-internal.h>
#include <fdtdec.h>
#include <malloc.h>
#include <asm/gpio.h>
+#include <dm/device_compat.h>
#include <linux/bug.h>
#include <linux/ctype.h>
if (desc->flags & GPIOD_ACTIVE_LOW)
value = !value;
+
+ /*
+ * Emulate open drain by not actively driving the line high or
+ * Emulate open source by not actively driving the line low
+ */
+ if ((desc->flags & GPIOD_OPEN_DRAIN && value) ||
+ (desc->flags & GPIOD_OPEN_SOURCE && !value))
+ return gpio_get_ops(desc->dev)->direction_input(desc->dev,
+ desc->offset);
+ else if (desc->flags & GPIOD_OPEN_DRAIN ||
+ desc->flags & GPIOD_OPEN_SOURCE)
+ return gpio_get_ops(desc->dev)->direction_output(desc->dev,
+ desc->offset,
+ value);
+
gpio_get_ops(desc->dev)->set_value(desc->dev, desc->offset, value);
return 0;
}
return ret;
}
- if (flags & GPIOD_IS_OUT) {
- ret = ops->direction_output(dev, desc->offset,
- GPIOD_FLAGS_OUTPUT(flags));
- } else if (flags & GPIOD_IS_IN) {
- ret = ops->direction_input(dev, desc->offset);
+ /* GPIOD_ are directly managed by driver in set_dir_flags*/
+ if (ops->set_dir_flags) {
+ ret = ops->set_dir_flags(dev, desc->offset, flags);
+ } else {
+ if (flags & GPIOD_IS_OUT) {
+ ret = ops->direction_output(dev, desc->offset,
+ GPIOD_FLAGS_OUTPUT(flags));
+ } else if (flags & GPIOD_IS_IN) {
+ ret = ops->direction_input(dev, desc->offset);
+ }
}
return ret;
ops->get_function += gd->reloc_off;
if (ops->xlate)
ops->xlate += gd->reloc_off;
+ if (ops->set_dir_flags)
+ ops->set_dir_flags += gd->reloc_off;
if (ops->get_dir_flags)
ops->get_dir_flags += gd->reloc_off;