-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
console: Add simplified 'serdev' framework from Linux kernel
Port 'serdev' UART-slave deivce framework found in recent Linux kernels (post 4.13) in order to be able to port 'serdev' slave drivers from Linux. Signed-off-by: Andrey Smirnov <[email protected]> Signed-off-by: Sascha Hauer <[email protected]>
- Loading branch information
1 parent
84fc611
commit c2ee90f
Showing
6 changed files
with
180 additions
and
3 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,89 @@ | ||
|
||
#include <common.h> | ||
#include <serdev.h> | ||
|
||
static void serdev_device_poller(void *context) | ||
{ | ||
struct serdev_device *serdev = context; | ||
struct console_device *cdev = to_console_device(serdev); | ||
unsigned char *buf = serdev->buf; | ||
int ret, len; | ||
|
||
/* | ||
* Since this callback is a part of poller infrastructure we | ||
* want to use _non_interruptible version of the function | ||
* below to prevent recursion from happening (regular | ||
* console_drain will call is_timeout, which might end up | ||
* calling this function again). | ||
*/ | ||
len = console_drain_non_interruptible(cdev, serdev->fifo, buf, | ||
PAGE_SIZE, | ||
serdev->polling_window); | ||
while (len > 0) { | ||
ret = serdev->receive_buf(serdev, buf, len); | ||
len -= ret; | ||
buf += ret; | ||
} | ||
|
||
if (serdev->polling_interval) { | ||
/* | ||
* Re-schedule ourselves in 'serdev->polling_interval' | ||
* nanoseconds | ||
*/ | ||
poller_call_async(&serdev->poller, | ||
serdev->polling_interval, | ||
serdev_device_poller, | ||
serdev); | ||
} | ||
} | ||
|
||
int serdev_device_open(struct serdev_device *serdev) | ||
{ | ||
struct console_device *cdev = to_console_device(serdev); | ||
int ret; | ||
|
||
if (!cdev->putc || !cdev->getc) | ||
return -EINVAL; | ||
|
||
if (!serdev->polling_window) | ||
return -EINVAL; | ||
|
||
serdev->buf = xzalloc(PAGE_SIZE); | ||
serdev->fifo = kfifo_alloc(PAGE_SIZE); | ||
if (!serdev->fifo) | ||
return -ENOMEM; | ||
|
||
ret = poller_async_register(&serdev->poller); | ||
if (ret) | ||
return ret; | ||
|
||
return console_open(cdev); | ||
} | ||
|
||
unsigned int serdev_device_set_baudrate(struct serdev_device *serdev, | ||
unsigned int speed) | ||
{ | ||
struct console_device *cdev = to_console_device(serdev); | ||
|
||
if (console_set_baudrate(cdev, speed) < 0) | ||
return 0; | ||
|
||
return console_get_baudrate(cdev); | ||
} | ||
|
||
int serdev_device_write(struct serdev_device *serdev, const unsigned char *buf, | ||
size_t count, unsigned long timeout) | ||
{ | ||
struct console_device *cdev = to_console_device(serdev); | ||
|
||
while (count--) | ||
cdev->putc(cdev, *buf++); | ||
/* | ||
* Poll Rx once right after we just send some data in case our | ||
* serdev device implements command/response type of a | ||
* protocol and we need to start draining input as soon as | ||
* possible. | ||
*/ | ||
serdev_device_poller(serdev); | ||
return 0; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
#ifndef _SERDEV_H_ | ||
#define _SERDEV_H_ | ||
|
||
#include <driver.h> | ||
#include <poller.h> | ||
#include <kfifo.h> | ||
|
||
/** | ||
* struct serdev_device - Basic representation of an serdev device | ||
* | ||
* @dev: Corresponding device | ||
* @fifo: Circular buffer used for console draining | ||
* @buf: Buffer used to pass Rx data to consumers | ||
* @poller Async poller used to poll this serdev | ||
* @polling_interval: Async poller periodicity | ||
* @polling_window: Duration of a single busy loop poll | ||
* @receive_buf: Function called with data received from device; | ||
* returns number of bytes accepted; | ||
*/ | ||
struct serdev_device { | ||
struct device_d *dev; | ||
struct kfifo *fifo; | ||
unsigned char *buf; | ||
struct poller_async poller; | ||
uint64_t polling_interval; | ||
uint64_t polling_window; | ||
|
||
int (*receive_buf)(struct serdev_device *, const unsigned char *, | ||
size_t); | ||
}; | ||
|
||
int serdev_device_open(struct serdev_device *); | ||
unsigned int serdev_device_set_baudrate(struct serdev_device *, unsigned int); | ||
int serdev_device_write(struct serdev_device *, const unsigned char *, | ||
size_t, unsigned long); | ||
#endif |