diff options
author | Sandeep Singh <Sandeep@freescale.com> | 2013-12-02 12:34:11 (GMT) |
---|---|---|
committer | Jose Rivera <German.Rivera@freescale.com> | 2013-12-06 14:36:48 (GMT) |
commit | 3dea020415467452d6ca2e907e21af07954741cf (patch) | |
tree | a51b2cf364463df5d072f444146541667f523057 /drivers/tdm | |
parent | d448c2e045e4d1e0adf01c1ecc6e02be81292ed2 (diff) | |
download | linux-fsl-qoriq-3dea020415467452d6ca2e907e21af07954741cf.tar.xz |
tdm/test: Added loopback test module for tdm
This module requires tdm device to be configure in loopback mode.
This test will write sample data on a tdm channel and compare
the read value with the sample data sent.
Signed-off-by: Sandeep Singh <Sandeep@freescale.com>
Change-Id: I2db7d40c0177c0b5e3a54467dab90c4de9d9b975
Reviewed-on: http://git.am.freescale.net:8181/7001
Tested-by: Review Code-CDREVIEW <CDREVIEW@freescale.com>
Reviewed-by: Poonam Aggrwal <Poonam.Aggrwal@freescale.com>
Reviewed-by: Jose Rivera <German.Rivera@freescale.com>
Diffstat (limited to 'drivers/tdm')
-rw-r--r-- | drivers/tdm/test/Kconfig | 7 | ||||
-rw-r--r-- | drivers/tdm/test/Makefile | 1 | ||||
-rw-r--r-- | drivers/tdm/test/tdm_loopback_test.c | 251 |
3 files changed, 259 insertions, 0 deletions
diff --git a/drivers/tdm/test/Kconfig b/drivers/tdm/test/Kconfig index 81fc3f4..39f9581 100644 --- a/drivers/tdm/test/Kconfig +++ b/drivers/tdm/test/Kconfig @@ -19,4 +19,11 @@ config UCC_TDM_TEST This UCC TDM test module is a small test module to test ucc tdm transfer and receive data via ucc1. +config TDM_LOOPBACK_TEST + tristate "TDM Loopback test Module" + depends on FSL_SOC + ---help--- + This TDM Loopback test module is a small test module which + performs a simple internal loopback testing. + endmenu diff --git a/drivers/tdm/test/Makefile b/drivers/tdm/test/Makefile index c229934..47bb4ef 100644 --- a/drivers/tdm/test/Makefile +++ b/drivers/tdm/test/Makefile @@ -4,3 +4,4 @@ obj-$(CONFIG_TDM_TEST) += tdm_test.o obj-$(CONFIG_UCC_TDM_TEST) += ucc_tdm_test.o +obj-$(CONFIG_TDM_LOOPBACK_TEST) += tdm_loopback_test.o diff --git a/drivers/tdm/test/tdm_loopback_test.c b/drivers/tdm/test/tdm_loopback_test.c new file mode 100644 index 0000000..49554aa --- /dev/null +++ b/drivers/tdm/test/tdm_loopback_test.c @@ -0,0 +1,251 @@ +/* + * + * Copyright 2011-2012 Freescale Semiconductor, Inc. + * + * TDM Loopback Test Module. + * This TDM test module is a small test module which registers with the + * TDM framework and transfer and receive data in loopback mode and also + * compares if the data sent is received correctly. + * + * Author: Sandeep Kumar Singh <sandeep@freescale.com> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 675 Mass Ave, Cambridge, MA 02139, USA. + */ +#include <linux/module.h> +#include <linux/device.h> +#include <linux/kernel.h> +#include <linux/sched.h> +#include <linux/kthread.h> +#include <linux/wait.h> +#include <linux/param.h> +#include <linux/tdm.h> +#include <linux/fs.h> +#include <linux/slab.h> +#include <linux/init.h> +#include <linux/tdm.h> + + +#define DRV_DESC "Test Module for Freescale Platforms with TDM support" +#define DRV_NAME "tdm_test" + + +#define POLL_COUNT 38 +#define TDM_FRAME_LENGTH NUM_SAMPLES_PER_FRAME +#define TDM_E_OK 0 +#define BUF_COUNT 7 + +#define DEBUG 0 + +int poll_count = POLL_COUNT; +module_param(poll_count, int, 0); + +static struct task_struct *tdm_thread_task; +static struct tdm_driver test_tdmdev_driver; +struct tdm_port *tdmport; +int tdm_thread_state; + +static int tdm_check_data(unsigned short *tx_data, unsigned short *rx_data) +{ + int i, error = 0; + static int call_count; + + for (i = 1; i < TDM_FRAME_LENGTH; i++) { + if (tx_data[i] != rx_data[i]) + error++; + else + continue; + } + + pr_info("Iteration: %d\n", ++call_count); +#if DEBUG + pr_info("TX DATA:\n"); + for (i = 0; i < TDM_FRAME_LENGTH; i++) { + pr_info("%5x ", tx_data[i]); + if (i%20 == 19) + pr_info("\n"); + } + pr_info("RX DATA:\n"); + for (i = 0; i < TDM_FRAME_LENGTH; i++) { + pr_info("%5x ", rx_data[i]); + if (i%20 == 19) + pr_info("\n"); + } +#endif + if (error) + pr_info("TX and RX buffer do NOT match. Err_count:" + "%d\n", error); + else + pr_info("TX and RX buffer MATCH\n"); + + return error; +} + + +static int tdm_thread(void *ptr) +{ + void *h_port; + void *h_channel1; + int ret = TDM_E_OK; + int poll = 0; + int i = 0, j = 0; + int index = 0; + int error_count = 0; + int buffer_size; + uint16_t size = TDM_FRAME_LENGTH; + u16 ch1_id = 0; + unsigned short *tx_data[BUF_COUNT]; + unsigned short *rx_data[BUF_COUNT]; + + tdm_thread_state = 1; + + /* Open port */ + ret = tdm_port_open(&test_tdmdev_driver, &h_port); + pr_debug("%s tdm_port_open ret = %d\n", __func__, ret); + if ((ret != TDM_E_OK) || (h_port == NULL)) { + pr_err("Error in tdm_port_open- ret %x\n", ret); + goto port1_failed; + } + /* Open Channel 1*/ + ret = tdm_channel_open(ch1_id, 1, h_port, &h_channel1); + if ((ret != TDM_E_OK) || (h_channel1 == NULL)) { + pr_err("Error in tdm_channel_open(%d)- ret %x\n", ch1_id, ret); + goto ch1_failed; + } + + buffer_size = sizeof(unsigned short)*BUF_COUNT*TDM_FRAME_LENGTH; + tx_data[0] = kmalloc(buffer_size, GFP_KERNEL); + rx_data[0] = kmalloc(buffer_size, GFP_KERNEL); + + if ((tx_data[0] == NULL) || (rx_data[0] == NULL)) { + pr_err("Failed to get memory for buffer"); + return 0; + } + for (i = 0; i < BUF_COUNT-1; i++) { + tx_data[i+1] = tx_data[i] + TDM_FRAME_LENGTH; + rx_data[i+1] = rx_data[i] + TDM_FRAME_LENGTH; + } + while ((poll < poll_count) && !kthread_should_stop()) { + + poll++; + while (tdm_ch_poll(h_channel1, 10) != TDM_E_OK) + continue; + for (i = 0; i < TDM_FRAME_LENGTH; i++) + tx_data[index][i] = j*TDM_FRAME_LENGTH+i; + + ret = tdm_channel_write(h_port, h_channel1, tx_data[index], + size); + if (ret != TDM_E_OK) + pr_info("Error in tdm_channel_write\n"); + ret = tdm_channel_read(h_port, h_channel1, rx_data[index], + &size); + if (ret != TDM_E_OK) + pr_info("Error in tdm_channel_read\n"); + /* + * There is a delay of 6 frame between transmitted data and + * received data. Hence we compare tx_data[0] with rx data[6] + * and so on + */ + if (j++ > BUF_COUNT) + error_count += tdm_check_data(tx_data[(index + 1) + %BUF_COUNT], rx_data[index]); + index++; + index = index%BUF_COUNT; + + } + pr_info("\nTDM Loppback test completed.\n"); + if (error_count == 0) + pr_info("TDM loopback test PASSED!\n"); + else + pr_info("TDM loopback test FAILED!\n"); + + ret = tdm_channel_close(ch1_id, 1, h_port, h_channel1); + if (ret != TDM_E_OK) { + pr_err("Error in tdm_channel_close(%d)- ret %x\n", ch1_id, ret); + ret = -ENXIO; + } + + ret = tdm_port_close(h_port); + pr_debug("%s tdm_port_close ret = %d\n", __func__, ret); + if (ret != TDM_E_OK) { + pr_err("Error in tdm_port_close- ret %x\n", ret); + ret = -ENXIO; + } + + tdm_thread_state = 0; + + return ret; + +ch1_failed: + tdm_channel_close(ch1_id, 1, h_port, h_channel1); +port1_failed: + tdm_port_close(h_port); + return -ENXIO; +} + +static int test_attach_adapter(struct tdm_adapter *adap) +{ + tdm_thread_state = 0; + tdm_thread_task = kthread_run(tdm_thread, NULL, "tdm_thread"); + + return 0; +} + +static int test_detach_adapter(struct tdm_adapter *adap) +{ + if (tdm_thread_state) + kthread_stop(tdm_thread_task); + + return 0; +} + +static const struct tdm_device_id tdm_loopback_test_id[] = { + { "fsl_tdm", 0 }, + { } +}; + +static struct tdm_driver test_tdmdev_driver = { + .attach_adapter = test_attach_adapter, + .detach_adapter = test_detach_adapter, + .id_table = tdm_loopback_test_id, +}; + +static int __init tdm_loopback_test_init(void) +{ + int ret; + pr_info("TDM LOOPBACK TEST: \n"); + test_tdmdev_driver.id = 1; + + /* create a binding with TDM driver */ + ret = tdm_add_driver(&test_tdmdev_driver); + if (ret == 0) + pr_info("TDM LOOPBACK TEST module installed\n"); + else + pr_err("%s tdm_port_init failed\n", __func__); + return ret; +} + +static void __exit tdm_loopback_test_exit(void) +{ + tdm_unregister_driver(&test_tdmdev_driver); + pr_info("TDM LOOPBACK TEST module un-installed\n"); +} + +module_init(tdm_loopback_test_init); +module_exit(tdm_loopback_test_exit); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Sandeep Kumar Singh <sandeep@freescale.com>"); +MODULE_DESCRIPTION("Test Loopback Test Module for Freescale Platforms" +" with TDM support"); |