LCOV - code coverage report
Current view: top level - include/linux - serdev.h (source / functions) Hit Total Coverage
Test: gcov_data_raspi2_real_modules_combined.info Lines: 3 11 27.3 %
Date: 2020-09-30 20:25:40 Functions: 0 0 -
Branches: 2 44 4.5 %

           Branch data     Line data    Source code
       1                 :            : /* SPDX-License-Identifier: GPL-2.0-only */
       2                 :            : /*
       3                 :            :  * Copyright (C) 2016-2017 Linaro Ltd., Rob Herring <robh@kernel.org>
       4                 :            :  */
       5                 :            : #ifndef _LINUX_SERDEV_H
       6                 :            : #define _LINUX_SERDEV_H
       7                 :            : 
       8                 :            : #include <linux/types.h>
       9                 :            : #include <linux/device.h>
      10                 :            : #include <linux/termios.h>
      11                 :            : #include <linux/delay.h>
      12                 :            : 
      13                 :            : struct serdev_controller;
      14                 :            : struct serdev_device;
      15                 :            : 
      16                 :            : /*
      17                 :            :  * serdev device structures
      18                 :            :  */
      19                 :            : 
      20                 :            : /**
      21                 :            :  * struct serdev_device_ops - Callback operations for a serdev device
      22                 :            :  * @receive_buf:        Function called with data received from device;
      23                 :            :  *                      returns number of bytes accepted; may sleep.
      24                 :            :  * @write_wakeup:       Function called when ready to transmit more data; must
      25                 :            :  *                      not sleep.
      26                 :            :  */
      27                 :            : struct serdev_device_ops {
      28                 :            :         int (*receive_buf)(struct serdev_device *, const unsigned char *, size_t);
      29                 :            :         void (*write_wakeup)(struct serdev_device *);
      30                 :            : };
      31                 :            : 
      32                 :            : /**
      33                 :            :  * struct serdev_device - Basic representation of an serdev device
      34                 :            :  * @dev:        Driver model representation of the device.
      35                 :            :  * @nr:         Device number on serdev bus.
      36                 :            :  * @ctrl:       serdev controller managing this device.
      37                 :            :  * @ops:        Device operations.
      38                 :            :  * @write_comp  Completion used by serdev_device_write() internally
      39                 :            :  * @write_lock  Lock to serialize access when writing data
      40                 :            :  */
      41                 :            : struct serdev_device {
      42                 :            :         struct device dev;
      43                 :            :         int nr;
      44                 :            :         struct serdev_controller *ctrl;
      45                 :            :         const struct serdev_device_ops *ops;
      46                 :            :         struct completion write_comp;
      47                 :            :         struct mutex write_lock;
      48                 :            : };
      49                 :            : 
      50                 :            : static inline struct serdev_device *to_serdev_device(struct device *d)
      51                 :            : {
      52                 :            :         return container_of(d, struct serdev_device, dev);
      53                 :            : }
      54                 :            : 
      55                 :            : /**
      56                 :            :  * struct serdev_device_driver - serdev slave device driver
      57                 :            :  * @driver:     serdev device drivers should initialize name field of this
      58                 :            :  *              structure.
      59                 :            :  * @probe:      binds this driver to a serdev device.
      60                 :            :  * @remove:     unbinds this driver from the serdev device.
      61                 :            :  */
      62                 :            : struct serdev_device_driver {
      63                 :            :         struct device_driver driver;
      64                 :            :         int     (*probe)(struct serdev_device *);
      65                 :            :         void    (*remove)(struct serdev_device *);
      66                 :            : };
      67                 :            : 
      68                 :            : static inline struct serdev_device_driver *to_serdev_device_driver(struct device_driver *d)
      69                 :            : {
      70                 :            :         return container_of(d, struct serdev_device_driver, driver);
      71                 :            : }
      72                 :            : 
      73                 :            : enum serdev_parity {
      74                 :            :         SERDEV_PARITY_NONE,
      75                 :            :         SERDEV_PARITY_EVEN,
      76                 :            :         SERDEV_PARITY_ODD,
      77                 :            : };
      78                 :            : 
      79                 :            : /*
      80                 :            :  * serdev controller structures
      81                 :            :  */
      82                 :            : struct serdev_controller_ops {
      83                 :            :         int (*write_buf)(struct serdev_controller *, const unsigned char *, size_t);
      84                 :            :         void (*write_flush)(struct serdev_controller *);
      85                 :            :         int (*write_room)(struct serdev_controller *);
      86                 :            :         int (*open)(struct serdev_controller *);
      87                 :            :         void (*close)(struct serdev_controller *);
      88                 :            :         void (*set_flow_control)(struct serdev_controller *, bool);
      89                 :            :         int (*set_parity)(struct serdev_controller *, enum serdev_parity);
      90                 :            :         unsigned int (*set_baudrate)(struct serdev_controller *, unsigned int);
      91                 :            :         void (*wait_until_sent)(struct serdev_controller *, long);
      92                 :            :         int (*get_tiocm)(struct serdev_controller *);
      93                 :            :         int (*set_tiocm)(struct serdev_controller *, unsigned int, unsigned int);
      94                 :            : };
      95                 :            : 
      96                 :            : /**
      97                 :            :  * struct serdev_controller - interface to the serdev controller
      98                 :            :  * @dev:        Driver model representation of the device.
      99                 :            :  * @nr:         number identifier for this controller/bus.
     100                 :            :  * @serdev:     Pointer to slave device for this controller.
     101                 :            :  * @ops:        Controller operations.
     102                 :            :  */
     103                 :            : struct serdev_controller {
     104                 :            :         struct device           dev;
     105                 :            :         unsigned int            nr;
     106                 :            :         struct serdev_device    *serdev;
     107                 :            :         const struct serdev_controller_ops *ops;
     108                 :            : };
     109                 :            : 
     110                 :            : static inline struct serdev_controller *to_serdev_controller(struct device *d)
     111                 :            : {
     112                 :            :         return container_of(d, struct serdev_controller, dev);
     113                 :            : }
     114                 :            : 
     115                 :            : static inline void *serdev_device_get_drvdata(const struct serdev_device *serdev)
     116                 :            : {
     117                 :            :         return dev_get_drvdata(&serdev->dev);
     118                 :            : }
     119                 :            : 
     120                 :            : static inline void serdev_device_set_drvdata(struct serdev_device *serdev, void *data)
     121                 :            : {
     122                 :            :         dev_set_drvdata(&serdev->dev, data);
     123                 :            : }
     124                 :            : 
     125                 :            : /**
     126                 :            :  * serdev_device_put() - decrement serdev device refcount
     127                 :            :  * @serdev      serdev device.
     128                 :            :  */
     129                 :            : static inline void serdev_device_put(struct serdev_device *serdev)
     130                 :            : {
     131         [ #  # ]:          0 :         if (serdev)
     132                 :          0 :                 put_device(&serdev->dev);
     133                 :            : }
     134                 :            : 
     135                 :            : static inline void serdev_device_set_client_ops(struct serdev_device *serdev,
     136                 :            :                                               const struct serdev_device_ops *ops)
     137                 :            : {
     138                 :            :         serdev->ops = ops;
     139                 :            : }
     140                 :            : 
     141                 :            : static inline
     142                 :            : void *serdev_controller_get_drvdata(const struct serdev_controller *ctrl)
     143                 :            : {
     144   [ #  #  +  -  :        207 :         return ctrl ? dev_get_drvdata(&ctrl->dev) : NULL;
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
                      # ]
     145                 :            : }
     146                 :            : 
     147                 :            : static inline void serdev_controller_set_drvdata(struct serdev_controller *ctrl,
     148                 :            :                                                void *data)
     149                 :            : {
     150                 :            :         dev_set_drvdata(&ctrl->dev, data);
     151                 :            : }
     152                 :            : 
     153                 :            : /**
     154                 :            :  * serdev_controller_put() - decrement controller refcount
     155                 :            :  * @ctrl        serdev controller.
     156                 :            :  */
     157                 :            : static inline void serdev_controller_put(struct serdev_controller *ctrl)
     158                 :            : {
     159   [ #  #  +  - ]:        207 :         if (ctrl)
     160                 :        207 :                 put_device(&ctrl->dev);
     161                 :            : }
     162                 :            : 
     163                 :            : struct serdev_device *serdev_device_alloc(struct serdev_controller *);
     164                 :            : int serdev_device_add(struct serdev_device *);
     165                 :            : void serdev_device_remove(struct serdev_device *);
     166                 :            : 
     167                 :            : struct serdev_controller *serdev_controller_alloc(struct device *, size_t);
     168                 :            : int serdev_controller_add(struct serdev_controller *);
     169                 :            : void serdev_controller_remove(struct serdev_controller *);
     170                 :            : 
     171                 :            : static inline void serdev_controller_write_wakeup(struct serdev_controller *ctrl)
     172                 :            : {
     173                 :          0 :         struct serdev_device *serdev = ctrl->serdev;
     174                 :            : 
     175   [ #  #  #  # ]:          0 :         if (!serdev || !serdev->ops->write_wakeup)
     176                 :            :                 return;
     177                 :            : 
     178                 :          0 :         serdev->ops->write_wakeup(serdev);
     179                 :            : }
     180                 :            : 
     181                 :            : static inline int serdev_controller_receive_buf(struct serdev_controller *ctrl,
     182                 :            :                                               const unsigned char *data,
     183                 :            :                                               size_t count)
     184                 :            : {
     185                 :          0 :         struct serdev_device *serdev = ctrl->serdev;
     186                 :            : 
     187   [ #  #  #  # ]:          0 :         if (!serdev || !serdev->ops->receive_buf)
     188                 :            :                 return 0;
     189                 :            : 
     190                 :          0 :         return serdev->ops->receive_buf(serdev, data, count);
     191                 :            : }
     192                 :            : 
     193                 :            : #if IS_ENABLED(CONFIG_SERIAL_DEV_BUS)
     194                 :            : 
     195                 :            : int serdev_device_open(struct serdev_device *);
     196                 :            : void serdev_device_close(struct serdev_device *);
     197                 :            : int devm_serdev_device_open(struct device *, struct serdev_device *);
     198                 :            : unsigned int serdev_device_set_baudrate(struct serdev_device *, unsigned int);
     199                 :            : void serdev_device_set_flow_control(struct serdev_device *, bool);
     200                 :            : int serdev_device_write_buf(struct serdev_device *, const unsigned char *, size_t);
     201                 :            : void serdev_device_wait_until_sent(struct serdev_device *, long);
     202                 :            : int serdev_device_get_tiocm(struct serdev_device *);
     203                 :            : int serdev_device_set_tiocm(struct serdev_device *, int, int);
     204                 :            : void serdev_device_write_wakeup(struct serdev_device *);
     205                 :            : int serdev_device_write(struct serdev_device *, const unsigned char *, size_t, long);
     206                 :            : void serdev_device_write_flush(struct serdev_device *);
     207                 :            : int serdev_device_write_room(struct serdev_device *);
     208                 :            : 
     209                 :            : /*
     210                 :            :  * serdev device driver functions
     211                 :            :  */
     212                 :            : int __serdev_device_driver_register(struct serdev_device_driver *, struct module *);
     213                 :            : #define serdev_device_driver_register(sdrv) \
     214                 :            :         __serdev_device_driver_register(sdrv, THIS_MODULE)
     215                 :            : 
     216                 :            : /**
     217                 :            :  * serdev_device_driver_unregister() - unregister an serdev client driver
     218                 :            :  * @sdrv:       the driver to unregister
     219                 :            :  */
     220                 :            : static inline void serdev_device_driver_unregister(struct serdev_device_driver *sdrv)
     221                 :            : {
     222                 :            :         if (sdrv)
     223                 :            :                 driver_unregister(&sdrv->driver);
     224                 :            : }
     225                 :            : 
     226                 :            : #define module_serdev_device_driver(__serdev_device_driver) \
     227                 :            :         module_driver(__serdev_device_driver, serdev_device_driver_register, \
     228                 :            :                         serdev_device_driver_unregister)
     229                 :            : 
     230                 :            : #else
     231                 :            : 
     232                 :            : static inline int serdev_device_open(struct serdev_device *sdev)
     233                 :            : {
     234                 :            :         return -ENODEV;
     235                 :            : }
     236                 :            : static inline void serdev_device_close(struct serdev_device *sdev) {}
     237                 :            : static inline unsigned int serdev_device_set_baudrate(struct serdev_device *sdev, unsigned int baudrate)
     238                 :            : {
     239                 :            :         return 0;
     240                 :            : }
     241                 :            : static inline void serdev_device_set_flow_control(struct serdev_device *sdev, bool enable) {}
     242                 :            : static inline int serdev_device_write_buf(struct serdev_device *serdev,
     243                 :            :                                           const unsigned char *buf,
     244                 :            :                                           size_t count)
     245                 :            : {
     246                 :            :         return -ENODEV;
     247                 :            : }
     248                 :            : static inline void serdev_device_wait_until_sent(struct serdev_device *sdev, long timeout) {}
     249                 :            : static inline int serdev_device_get_tiocm(struct serdev_device *serdev)
     250                 :            : {
     251                 :            :         return -ENOTSUPP;
     252                 :            : }
     253                 :            : static inline int serdev_device_set_tiocm(struct serdev_device *serdev, int set, int clear)
     254                 :            : {
     255                 :            :         return -ENOTSUPP;
     256                 :            : }
     257                 :            : static inline int serdev_device_write(struct serdev_device *sdev, const unsigned char *buf,
     258                 :            :                                       size_t count, unsigned long timeout)
     259                 :            : {
     260                 :            :         return -ENODEV;
     261                 :            : }
     262                 :            : static inline void serdev_device_write_flush(struct serdev_device *sdev) {}
     263                 :            : static inline int serdev_device_write_room(struct serdev_device *sdev)
     264                 :            : {
     265                 :            :         return 0;
     266                 :            : }
     267                 :            : 
     268                 :            : #define serdev_device_driver_register(x)
     269                 :            : #define serdev_device_driver_unregister(x)
     270                 :            : 
     271                 :            : #endif /* CONFIG_SERIAL_DEV_BUS */
     272                 :            : 
     273                 :            : static inline bool serdev_device_get_cts(struct serdev_device *serdev)
     274                 :            : {
     275                 :            :         int status = serdev_device_get_tiocm(serdev);
     276                 :            :         return !!(status & TIOCM_CTS);
     277                 :            : }
     278                 :            : 
     279                 :            : static inline int serdev_device_wait_for_cts(struct serdev_device *serdev, bool state, int timeout_ms)
     280                 :            : {
     281                 :            :         unsigned long timeout;
     282                 :            :         bool signal;
     283                 :            : 
     284                 :            :         timeout = jiffies + msecs_to_jiffies(timeout_ms);
     285                 :            :         while (time_is_after_jiffies(timeout)) {
     286                 :            :                 signal = serdev_device_get_cts(serdev);
     287                 :            :                 if (signal == state)
     288                 :            :                         return 0;
     289                 :            :                 usleep_range(1000, 2000);
     290                 :            :         }
     291                 :            : 
     292                 :            :         return -ETIMEDOUT;
     293                 :            : }
     294                 :            : 
     295                 :            : static inline int serdev_device_set_rts(struct serdev_device *serdev, bool enable)
     296                 :            : {
     297                 :            :         if (enable)
     298                 :            :                 return serdev_device_set_tiocm(serdev, TIOCM_RTS, 0);
     299                 :            :         else
     300                 :            :                 return serdev_device_set_tiocm(serdev, 0, TIOCM_RTS);
     301                 :            : }
     302                 :            : 
     303                 :            : int serdev_device_set_parity(struct serdev_device *serdev,
     304                 :            :                              enum serdev_parity parity);
     305                 :            : 
     306                 :            : /*
     307                 :            :  * serdev hooks into TTY core
     308                 :            :  */
     309                 :            : struct tty_port;
     310                 :            : struct tty_driver;
     311                 :            : 
     312                 :            : #ifdef CONFIG_SERIAL_DEV_CTRL_TTYPORT
     313                 :            : struct device *serdev_tty_port_register(struct tty_port *port,
     314                 :            :                                         struct device *parent,
     315                 :            :                                         struct tty_driver *drv, int idx);
     316                 :            : int serdev_tty_port_unregister(struct tty_port *port);
     317                 :            : #else
     318                 :            : static inline struct device *serdev_tty_port_register(struct tty_port *port,
     319                 :            :                                            struct device *parent,
     320                 :            :                                            struct tty_driver *drv, int idx)
     321                 :            : {
     322                 :            :         return ERR_PTR(-ENODEV);
     323                 :            : }
     324                 :            : static inline int serdev_tty_port_unregister(struct tty_port *port)
     325                 :            : {
     326                 :            :         return -ENODEV;
     327                 :            : }
     328                 :            : #endif /* CONFIG_SERIAL_DEV_CTRL_TTYPORT */
     329                 :            : 
     330                 :            : #endif /*_LINUX_SERDEV_H */

Generated by: LCOV version 1.14