Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <linux/bitops.h>
- #include <linux/clk.h>
- #include <linux/delay.h>
- #include <linux/device.h>
- #include <linux/gpio/driver.h>
- #include <linux/module.h>
- #include <linux/of.h>
- #include <linux/of_device.h>
- #include <linux/regmap.h>
- #include <linux/serial_core.h>
- #include <linux/serial.h>
- #include <linux/tty.h>
- #include <linux/tty_flip.h>
- #include <linux/spi/spi.h>
- #include <linux/uaccess.h>
- #define test_NAME "test_spi_uart"
- #define test_UART_NRMAX 3
- struct test_devtype {
- char name[9];
- int nr;
- };
- struct test_one {
- struct uart_port port;
- struct work_struct tx_work;
- struct work_struct md_work;
- struct work_struct rs_work;
- u8 wr_header;
- u8 rd_header;
- };
- #define to_test_port(_port) \
- container_of(_port, struct test_one, port)
- struct test_port {
- struct test_devtype *devtype;
- struct clk *clk;
- struct test_one p[0];
- struct regmap *regmap;
- };
- static struct uart_driver test_uart = {
- .owner = THIS_MODULE,
- .dev_name = "ttyTH",
- .nr = test_UART_NRMAX,
- };
- static DECLARE_BITMAP(test_lines, test_UART_NRMAX);
- static void test_start_tx(struct uart_port *port)
- {
- struct test_one *one = to_test_port(port);
- dev_info(port->dev, "calling: %s\n", __func__);
- }
- static void test_tx_proc(struct work_struct *ws)
- {
- struct test_one *one = container_of(ws, struct test_one, tx_work);
- }
- static unsigned int test_tx_empty(struct uart_port *port)
- {
- return 0;
- }
- static unsigned int test_get_mctrl(struct uart_port *port)
- {
- /* DCD and DSR are not wired and CTS/RTS is handled automatically
- * so just indicate DSR and CAR asserted
- */
- dev_info(port->dev, "calling: %s\n", __func__);
- return TIOCM_DSR | TIOCM_CAR;
- }
- static void test_md_proc(struct work_struct *ws)
- {
- struct test_one *one = container_of(ws, struct test_one, md_work);
- }
- static void test_set_mctrl(struct uart_port *port, unsigned int mctrl)
- {
- struct test_one *one = to_test_port(port);
- dev_info(port->dev, "calling: %s\n", __func__);
- }
- static void test_break_ctl(struct uart_port *port, int break_state)
- {
- dev_info(port->dev, "calling: %s\n", __func__);
- }
- static void test_set_termios(struct uart_port *port,
- struct ktermios *termios,
- struct ktermios *old)
- {
- unsigned int lcr = 0, flow = 0;
- int baud;
- dev_info(port->dev, "calling: %s\n", __func__);
- /* Mask termios capabilities we don't support */
- termios->c_cflag &= ~CMSPAR;
- }
- static void test_rs_proc(struct work_struct *ws)
- {
- struct test_one *one = container_of(ws, struct test_one, rs_work);
- unsigned int delay, mode1 = 0, mode2 = 0;
- }
- static int test_rs485_config(struct uart_port *port,
- struct serial_rs485 *rs485)
- {
- return 0;
- }
- static int test_startup(struct uart_port *port)
- {
- struct test_port *s = dev_get_drvdata(port->dev);
- unsigned int val;
- dev_info(port->dev, "calling: %s\n", __func__);
- return 0;
- }
- static void test_shutdown(struct uart_port *port)
- {
- struct test_port *s = dev_get_drvdata(port->dev);
- dev_info(port->dev, "calling: %s\n", __func__);
- }
- static const char *test_type(struct uart_port *port)
- {
- struct test_port *s = dev_get_drvdata(port->dev);
- return (port->type == PORT_test) ? s->devtype->name : NULL;
- }
- static int test_request_port(struct uart_port *port)
- {
- /* Do nothing */
- return 0;
- }
- static void test_config_port(struct uart_port *port, int flags)
- {
- if (flags & UART_CONFIG_TYPE)
- port->type = PORT_test;
- dev_info(port->dev, "calling: %s\n", __func__);
- }
- static int test_verify_port(struct uart_port *port, struct serial_struct *s)
- {
- dev_info(port->dev, "calling: %s\n", __func__);
- if ((s->type != PORT_UNKNOWN) && (s->type != PORT_test))
- return -EINVAL;
- if (s->irq != port->irq)
- return -EINVAL;
- return 0;
- }
- static void test_null_void(struct uart_port *port)
- {
- /* Do nothing */
- }
- static const struct test_devtype th_devtype = {
- .name = "test",
- .nr = 16,
- };
- static const struct uart_ops test_ops = {
- .tx_empty = test_tx_empty,
- .set_mctrl = test_set_mctrl,
- .get_mctrl = test_get_mctrl,
- .stop_tx = test_null_void,
- .start_tx = test_start_tx,
- .stop_rx = test_null_void,
- .break_ctl = test_break_ctl,
- .startup = test_startup,
- .shutdown = test_shutdown,
- .set_termios = test_set_termios,
- .type = test_type,
- .request_port = test_request_port,
- .release_port = test_null_void,
- .config_port = test_config_port,
- .verify_port = test_verify_port,
- };
- static int test_probe(struct device *dev, struct test_devtype *devtype,
- struct regmap *regmap, int irq)
- {
- int i, ret, fmin, fmax, freq, uartclk = 150000;
- struct clk *clk_osc, *clk_xtal;
- struct test_port *s;
- bool xtal = false;
- if (IS_ERR(regmap))
- return PTR_ERR(regmap);
- /* Alloc port structure */
- s = devm_kzalloc(dev, struct_size(s, p, 3), GFP_KERNEL);
- if (!s) {
- dev_err(dev, "Error allocating port structure\n");
- return -ENOMEM;
- }
- s->devtype = devtype;
- dev_set_drvdata(dev, s);
- for (i = 0; i < 3; i++) {
- unsigned int line;
- line = find_first_zero_bit(test_lines, test_UART_NRMAX);
- if (line == test_UART_NRMAX) {
- ret = -ERANGE;
- goto out_uart;
- }
- /* Initialize port data */
- s->p[i].port.line = line;
- s->p[i].port.dev = dev;
- s->p[i].port.type = PORT_test;
- s->p[i].port.fifosize = 300;
- s->p[i].port.flags = UPF_SKIP_TEST | UPF_AUTO_IRQ;
- s->p[i].port.iotype = UPIO_PORT;
- s->p[i].port.iobase = i + 1;
- s->p[i].port.uartclk = uartclk;
- s->p[i].port.ops = &test_ops;
- /* Initialize queue for start TX */
- //INIT_WORK(&s->p[i].tx_work, test_tx_proc);
- /* Initialize queue for changing LOOPBACK mode */
- //INIT_WORK(&s->p[i].md_work, test_md_proc);
- /* Initialize queue for changing RS485 mode */
- //INIT_WORK(&s->p[i].rs_work, test_rs_proc);
- /* Initialize SPI-transfer buffers */
- //s->p[i].wr_header = (s->p[i].port.iobase + test_THR_REG) |
- // test_WRITE_BIT;
- //s->p[i].rd_header = (s->p[i].port.iobase + test_RHR_REG);
- /* Register port */
- ret = uart_add_one_port(&test_uart, &s->p[i].port);
- if (ret < 0) {
- s->p[i].port.dev = NULL;
- dev_err(dev, "failed to add uart port:%d\n", ret);
- goto out_uart;
- } else {
- }
- set_bit(line, test_lines);
- }
- out_uart:
- for (i = 0; i < 3; i++) {
- if (s->p[i].port.dev) {
- uart_remove_one_port(&test_uart, &s->p[i].port);
- clear_bit(s->p[i].port.line, test_lines);
- }
- }
- out_clk:
- return ret;
- }
- static int test_remove(struct device *dev)
- {
- struct test_port *s = dev_get_drvdata(dev);
- int i;
- for (i = 0; i < 3; i++) {
- // cancel_work_sync(&s->p[i].tx_work);
- // cancel_work_sync(&s->p[i].md_work);
- // cancel_work_sync(&s->p[i].rs_work);
- uart_remove_one_port(&test_uart, &s->p[i].port);
- clear_bit(s->p[i].port.line, test_lines);
- // s->devtype->power(&s->p[i].port, 0);
- }
- //clk_disable_unprepare(s->clk);
- return 0;
- }
- static const struct of_device_id __maybe_unused test_dt_ids[] = {
- { .compatible = "th,spi_uart", .data = &th_devtype },
- { }
- };
- MODULE_DEVICE_TABLE(of, test_dt_ids);
- static int test_spi_probe(struct spi_device *spi)
- {
- struct test_devtype *devtype;
- int ret;
- /* Setup SPI bus */
- spi->bits_per_word = 8;
- spi->mode = spi->mode ? : SPI_MODE_0;
- spi->max_speed_hz = spi->max_speed_hz ? : 26000000;
- ret = spi_setup(spi);
- if (ret)
- return ret;
- if (spi->dev.of_node) {
- const struct of_device_id *of_id =
- of_match_device(test_dt_ids, &spi->dev);
- if (!of_id)
- return -ENODEV;
- devtype = (struct test_devtype *)of_id->data;
- }
- return test_probe(&spi->dev, devtype, NULL, spi->irq);
- }
- static int test_spi_remove(struct spi_device *spi)
- {
- return test_remove(&spi->dev);
- }
- static const struct spi_device_id test_id_table[] = {
- { "th_spi_uart" },
- { }
- };
- MODULE_DEVICE_TABLE(spi, test_id_table);
- static struct spi_driver test_spi_driver = {
- .driver = {
- .name = test_NAME,
- .of_match_table = of_match_ptr(test_dt_ids),
- },
- .probe = test_spi_probe,
- .remove = test_spi_remove,
- .id_table = test_id_table,
- };
- static int __init test_uart_init(void)
- {
- int ret;
- bitmap_zero(test_lines, test_UART_NRMAX);
- ret = uart_register_driver(&test_uart);
- if (ret) {
- pr_err("Failed to init driver:%d\n", ret);
- return ret;
- }
- ret = spi_register_driver(&test_spi_driver);
- return ret;
- }
- module_init(test_uart_init);
- static void __exit test_uart_exit(void)
- {
- spi_unregister_driver(&test_spi_driver);
- uart_unregister_driver(&test_uart);
- }
- module_exit(test_uart_exit);
- MODULE_LICENSE("GPL");
- MODULE_AUTHOR("Marek Belisko <marek.belisko@gmail.com>");
- MODULE_DESCRIPTION("Test serial driver");
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement