}
 EXPORT_SYMBOL_GPL(serdev_device_set_baudrate);
 
+void serdev_device_set_error_mask(struct serdev_device *serdev, unsigned long mask)
+{
+       struct serdev_controller *ctrl = serdev->ctrl;
+
+       if (!ctrl || !ctrl->ops->set_error_mask)
+               return;
+
+       ctrl->ops->set_error_mask(ctrl, mask);
+}
+EXPORT_SYMBOL_GPL(serdev_device_set_error_mask);
+
 void serdev_device_set_flow_control(struct serdev_device *serdev, bool enable)
 {
        struct serdev_controller *ctrl = serdev->ctrl;
 
 /*
  * Copyright (C) 2016-2017 Linaro Ltd., Rob Herring <robh@kernel.org>
  */
+#include <linux/bits.h>
 #include <linux/kernel.h>
 #include <linux/serdev.h>
 #include <linux/tty.h>
 #include <linux/poll.h>
 
 #define SERPORT_ACTIVE         1
+#define SERPORT_NOTIFY_BREAK   2
+#define SERPORT_NOTIFY_FRAME   3
+#define SERPORT_NOTIFY_PARITY  4
+#define SERPORT_NOTIFY_OVERRUN 5
 
 struct serport {
        struct tty_port *port;
 {
        struct serdev_controller *ctrl = port->client_data;
        struct serport *serport = serdev_controller_get_drvdata(ctrl);
+       unsigned long errors = 0;
+       unsigned int i;
        int ret;
 
        if (!test_bit(SERPORT_ACTIVE, &serport->flags))
                return 0;
 
+       for (i = 0; fp && i < count; i++) {
+               switch (fp[i]) {
+               case TTY_BREAK:
+                       if (test_bit(SERPORT_NOTIFY_BREAK, &serport->flags))
+                               __set_bit(SERDEV_ERROR_BREAK, &errors);
+                       break;
+
+               case TTY_FRAME:
+                       if (test_bit(SERPORT_NOTIFY_FRAME, &serport->flags))
+                               __set_bit(SERDEV_ERROR_FRAME, &errors);
+                       break;
+
+               case TTY_PARITY:
+                       if (test_bit(SERPORT_NOTIFY_PARITY, &serport->flags))
+                               __set_bit(SERDEV_ERROR_PARITY, &errors);
+                       break;
+
+               case TTY_OVERRUN:
+                       if (test_bit(SERPORT_NOTIFY_OVERRUN, &serport->flags))
+                               __set_bit(SERDEV_ERROR_OVERRUN, &errors);
+                       break;
+               }
+       }
+       if (errors)
+               serdev_controller_error(ctrl, errors);
+
        ret = serdev_controller_receive_buf(ctrl, cp, count);
 
        dev_WARN_ONCE(&ctrl->dev, ret < 0 || ret > count,
        return ktermios.c_ospeed;
 }
 
+static void ttyport_set_error_mask(struct serdev_controller *ctrl,
+                                  unsigned long m)
+{
+       struct serport *sp = serdev_controller_get_drvdata(ctrl);
+
+       assign_bit(SERPORT_NOTIFY_BREAK, &sp->flags,
+                  m & BIT(SERDEV_ERROR_BREAK));
+       assign_bit(SERPORT_NOTIFY_FRAME, &sp->flags,
+                  m & BIT(SERDEV_ERROR_FRAME));
+       assign_bit(SERPORT_NOTIFY_PARITY, &sp->flags,
+                  m & BIT(SERDEV_ERROR_PARITY));
+       assign_bit(SERPORT_NOTIFY_OVERRUN, &sp->flags,
+                  m & BIT(SERDEV_ERROR_OVERRUN));
+}
+
 static void ttyport_set_flow_control(struct serdev_controller *ctrl, bool enable)
 {
        struct serport *serport = serdev_controller_get_drvdata(ctrl);
        .write_room = ttyport_write_room,
        .open = ttyport_open,
        .close = ttyport_close,
+       .set_error_mask = ttyport_set_error_mask,
        .set_flow_control = ttyport_set_flow_control,
        .set_parity = ttyport_set_parity,
        .set_baudrate = ttyport_set_baudrate,
 
 
 /**
  * struct serdev_device_ops - Callback operations for a serdev device
+ * @error:             Function called with errors received from device;
+ *                     may sleep.
  * @receive_buf:       Function called with data received from device;
  *                     returns number of bytes accepted; may sleep.
  * @write_wakeup:      Function called when ready to transmit more data; must
  *                     not sleep.
  */
 struct serdev_device_ops {
+       void (*error)(struct serdev_device *, unsigned long);
        int (*receive_buf)(struct serdev_device *, const unsigned char *, size_t);
        void (*write_wakeup)(struct serdev_device *);
 };
        SERDEV_PARITY_ODD,
 };
 
+#define SERDEV_ERROR_BREAK 0
+#define SERDEV_ERROR_FRAME 1
+#define SERDEV_ERROR_PARITY 2
+#define SERDEV_ERROR_OVERRUN 3
+
 /*
  * serdev controller structures
  */
        int (*write_room)(struct serdev_controller *);
        int (*open)(struct serdev_controller *);
        void (*close)(struct serdev_controller *);
+       void (*set_error_mask)(struct serdev_controller *, unsigned long);
        void (*set_flow_control)(struct serdev_controller *, bool);
        int (*set_parity)(struct serdev_controller *, enum serdev_parity);
        unsigned int (*set_baudrate)(struct serdev_controller *, unsigned int);
        return serdev->ops->receive_buf(serdev, data, count);
 }
 
+static inline void serdev_controller_error(struct serdev_controller *ctrl,
+                                          unsigned long errors)
+{
+       struct serdev_device *serdev = ctrl->serdev;
+
+       if (!serdev || !serdev->ops->error)
+               return;
+
+       serdev->ops->error(serdev, errors);
+}
+
 #if IS_ENABLED(CONFIG_SERIAL_DEV_BUS)
 
 int serdev_device_open(struct serdev_device *);
 void serdev_device_close(struct serdev_device *);
 int devm_serdev_device_open(struct device *, struct serdev_device *);
 unsigned int serdev_device_set_baudrate(struct serdev_device *, unsigned int);
+void serdev_device_set_error_mask(struct serdev_device *, unsigned long);
 void serdev_device_set_flow_control(struct serdev_device *, bool);
 int serdev_device_write_buf(struct serdev_device *, const unsigned char *, size_t);
 void serdev_device_wait_until_sent(struct serdev_device *, long);
 {
        return 0;
 }
+static inline void serdev_device_set_error_mask(struct serdev_device *sdev, unsigned long mask) {}
 static inline void serdev_device_set_flow_control(struct serdev_device *sdev, bool enable) {}
 static inline int serdev_device_write_buf(struct serdev_device *serdev,
                                          const unsigned char *buf,