199d14b01SJoseph Chen /*
299d14b01SJoseph Chen * (C) Copyright 2019 Rockchip Electronics Co., Ltd
399d14b01SJoseph Chen *
499d14b01SJoseph Chen * SPDX-License-Identifier: GPL-2.0+
599d14b01SJoseph Chen */
699d14b01SJoseph Chen
799d14b01SJoseph Chen #include <common.h>
899d14b01SJoseph Chen #include <adc.h>
999d14b01SJoseph Chen #include <console.h>
1099d14b01SJoseph Chen #include <dm.h>
1199d14b01SJoseph Chen #include <key.h>
1299d14b01SJoseph Chen #include <misc.h>
1399d14b01SJoseph Chen #include <rc.h>
1499d14b01SJoseph Chen #ifdef CONFIG_IRQ
1599d14b01SJoseph Chen #include <irq-generic.h>
1699d14b01SJoseph Chen #include <rk_timer_irq.h>
1799d14b01SJoseph Chen #endif
1899d14b01SJoseph Chen #include <asm/io.h>
1999d14b01SJoseph Chen #include <linux/input.h>
2099d14b01SJoseph Chen #include "test-rockchip.h"
2199d14b01SJoseph Chen
2299d14b01SJoseph Chen #ifdef CONFIG_IRQ
2399d14b01SJoseph Chen /* Must use volatile to avoid being optimized by complier */
2499d14b01SJoseph Chen static int volatile irq_exit;
2599d14b01SJoseph Chen static ulong seconds;
2699d14b01SJoseph Chen
timer_irq_handler(int irq,void * data)2799d14b01SJoseph Chen static void timer_irq_handler(int irq, void *data)
2899d14b01SJoseph Chen {
2999d14b01SJoseph Chen int period;
3099d14b01SJoseph Chen
3199d14b01SJoseph Chen writel(TIMER_CLR_INT, TIMER_BASE + TIMER_INTSTATUS);
3299d14b01SJoseph Chen period = get_timer(seconds);
3399d14b01SJoseph Chen printf(" Hello, this is timer isr: irq=%d, period=%dms\n", irq, period);
3499d14b01SJoseph Chen
3599d14b01SJoseph Chen irq_exit = 1;
3699d14b01SJoseph Chen }
3799d14b01SJoseph Chen
timer_interrupt_test(void)3899d14b01SJoseph Chen static int timer_interrupt_test(void)
3999d14b01SJoseph Chen {
4099d14b01SJoseph Chen printf("Timer interrupt:\n");
4199d14b01SJoseph Chen
4299d14b01SJoseph Chen /* Disable before config */
4399d14b01SJoseph Chen writel(0, TIMER_BASE + TIMER_CTRL);
4499d14b01SJoseph Chen
4599d14b01SJoseph Chen /* Configure 1s */
46*13ceb2afSXuhui Lin writel(gd->arch.timer_rate_hz, TIMER_BASE + TIMER_LOAD_COUNT0);
4799d14b01SJoseph Chen writel(0, TIMER_BASE + TIMER_LOAD_COUNT1);
4899d14b01SJoseph Chen writel(TIMER_CLR_INT, TIMER_BASE + TIMER_INTSTATUS);
4999d14b01SJoseph Chen writel(TIMER_EN | TIMER_INT_EN, TIMER_BASE + TIMER_CTRL);
5099d14b01SJoseph Chen
5199d14b01SJoseph Chen /* Request irq */
5299d14b01SJoseph Chen irq_install_handler(TIMER_IRQ, timer_irq_handler, NULL);
5399d14b01SJoseph Chen irq_handler_enable(TIMER_IRQ);
5499d14b01SJoseph Chen
5539e1dbd6SJoseph Chen irq_exit = 0;
5699d14b01SJoseph Chen seconds = get_timer(0);
5799d14b01SJoseph Chen while (!irq_exit)
5899d14b01SJoseph Chen ;
5999d14b01SJoseph Chen
6099d14b01SJoseph Chen irq_free_handler(TIMER_IRQ);
6199d14b01SJoseph Chen
6299d14b01SJoseph Chen return 0;
6399d14b01SJoseph Chen }
6499d14b01SJoseph Chen #endif
6599d14b01SJoseph Chen
timer_delay_test(void)6699d14b01SJoseph Chen static void timer_delay_test(void)
6799d14b01SJoseph Chen {
6899d14b01SJoseph Chen ulong delay = 100, delta;
6999d14b01SJoseph Chen u64 start;
7099d14b01SJoseph Chen
7199d14b01SJoseph Chen printf("Timer delay:\n");
7299d14b01SJoseph Chen
7399d14b01SJoseph Chen start = get_ticks();
7499d14b01SJoseph Chen udelay(delay);
75*13ceb2afSXuhui Lin delta = (get_ticks() - start) / (gd->arch.timer_rate_hz / 1000000);
7699d14b01SJoseph Chen printf(" Set %4luus, real %4luus\n", delay, delta);
7799d14b01SJoseph Chen
7899d14b01SJoseph Chen start = get_ticks();
7999d14b01SJoseph Chen mdelay(delay);
80*13ceb2afSXuhui Lin delta = (get_ticks() - start) / (gd->arch.timer_rate_hz / 1000);
8199d14b01SJoseph Chen printf(" Set %4lums, real %4lums\n", delay, delta);
8299d14b01SJoseph Chen
8399d14b01SJoseph Chen start = get_ticks();
8499d14b01SJoseph Chen mdelay(delay * 10UL);
85*13ceb2afSXuhui Lin delta = (get_ticks() - start) / (gd->arch.timer_rate_hz / 1000);
8699d14b01SJoseph Chen printf(" Set %4lums, real %4lums\n\n", delay * 10UL, delta);
8799d14b01SJoseph Chen }
8899d14b01SJoseph Chen
do_test_timer(cmd_tbl_t * cmdtp,int flag,int argc,char * const argv[])8999d14b01SJoseph Chen int do_test_timer(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
9099d14b01SJoseph Chen {
9199d14b01SJoseph Chen timer_delay_test();
9299d14b01SJoseph Chen
9399d14b01SJoseph Chen #ifdef CONFIG_IRQ
9499d14b01SJoseph Chen timer_interrupt_test();
9599d14b01SJoseph Chen #endif
9699d14b01SJoseph Chen return 0;
9799d14b01SJoseph Chen }
9899d14b01SJoseph Chen
9999d14b01SJoseph Chen #ifdef CONFIG_RK_IR
ir_test(void)10099d14b01SJoseph Chen static int ir_test(void)
10199d14b01SJoseph Chen {
10299d14b01SJoseph Chen struct udevice *dev;
10399d14b01SJoseph Chen int keycode, repeat;
10499d14b01SJoseph Chen int last_keycode;
10599d14b01SJoseph Chen int last_repeat;
10699d14b01SJoseph Chen ulong start;
10799d14b01SJoseph Chen int ret;
10899d14b01SJoseph Chen
10999d14b01SJoseph Chen printf("\nYou have 30s to test ir, press them, start!\n");
11099d14b01SJoseph Chen
11199d14b01SJoseph Chen ret = uclass_get_device(UCLASS_RC, 0, &dev);
11299d14b01SJoseph Chen if (ret) {
113443feaabSJoseph Chen ut_err("ir: failed to get device, ret=%d\n", ret);
11499d14b01SJoseph Chen goto out;
11599d14b01SJoseph Chen }
11699d14b01SJoseph Chen
11799d14b01SJoseph Chen keycode = rc_get_keycode(dev);
11899d14b01SJoseph Chen if (keycode == -ENOSYS) {
119443feaabSJoseph Chen ut_err("ir: failed to bind driver\n");
12099d14b01SJoseph Chen goto out;
12199d14b01SJoseph Chen }
12299d14b01SJoseph Chen
12399d14b01SJoseph Chen last_keycode = KEY_RESERVED;
12499d14b01SJoseph Chen last_repeat = KEY_RESERVED;
12599d14b01SJoseph Chen start = get_timer(0);
12699d14b01SJoseph Chen while (get_timer(start) <= 30000) {
12799d14b01SJoseph Chen mdelay(100);
12899d14b01SJoseph Chen
12999d14b01SJoseph Chen keycode = rc_get_keycode(dev);
13099d14b01SJoseph Chen repeat = rc_get_repeat(dev);
13199d14b01SJoseph Chen if (keycode == KEY_RESERVED)
13299d14b01SJoseph Chen continue;
13399d14b01SJoseph Chen
13499d14b01SJoseph Chen if (keycode != last_keycode || repeat != last_repeat) {
135443feaabSJoseph Chen printf("ir: press key:0x%x repeat:%d\n",
13699d14b01SJoseph Chen keycode, repeat);
13799d14b01SJoseph Chen last_keycode = keycode;
13899d14b01SJoseph Chen last_repeat = repeat;
13999d14b01SJoseph Chen }
14099d14b01SJoseph Chen }
14199d14b01SJoseph Chen
14299d14b01SJoseph Chen return 0;
14399d14b01SJoseph Chen
14499d14b01SJoseph Chen out:
14599d14b01SJoseph Chen return -EINVAL;
14699d14b01SJoseph Chen }
14799d14b01SJoseph Chen
do_test_ir(cmd_tbl_t * cmdtp,int flag,int argc,char * const argv[])14899d14b01SJoseph Chen int do_test_ir(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
14999d14b01SJoseph Chen {
15099d14b01SJoseph Chen return ir_test();
15199d14b01SJoseph Chen }
15299d14b01SJoseph Chen #endif
15399d14b01SJoseph Chen
15499d14b01SJoseph Chen #ifdef CONFIG_DM_KEY
do_test_key(cmd_tbl_t * cmdtp,int flag,int argc,char * const argv[])15599d14b01SJoseph Chen int do_test_key(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
15699d14b01SJoseph Chen {
15799d14b01SJoseph Chen struct dm_key_uclass_platdata *key;
15899d14b01SJoseph Chen struct udevice *dev;
15999d14b01SJoseph Chen struct uclass *uc;
16099d14b01SJoseph Chen int ret, evt;
16199d14b01SJoseph Chen
16299d14b01SJoseph Chen ret = uclass_get(UCLASS_KEY, &uc);
16399d14b01SJoseph Chen if (ret)
16499d14b01SJoseph Chen return ret;
16599d14b01SJoseph Chen
16699d14b01SJoseph Chen printf("Please press any key button...\n");
16799d14b01SJoseph Chen while (!ctrlc()) {
16899d14b01SJoseph Chen for (uclass_first_device(UCLASS_KEY, &dev);
16999d14b01SJoseph Chen dev;
17099d14b01SJoseph Chen uclass_next_device(&dev)) {
17199d14b01SJoseph Chen key = dev_get_uclass_platdata(dev);
17299d14b01SJoseph Chen evt = key_read(key->code);
17399d14b01SJoseph Chen if (evt == KEY_PRESS_DOWN)
17499d14b01SJoseph Chen printf("'%s' key pressed...\n", key->name);
17599d14b01SJoseph Chen else if (evt == KEY_PRESS_LONG_DOWN)
17699d14b01SJoseph Chen printf("'%s' key long pressed...\n", key->name);
17799d14b01SJoseph Chen
17899d14b01SJoseph Chen mdelay(25);
17999d14b01SJoseph Chen }
18099d14b01SJoseph Chen }
18199d14b01SJoseph Chen
18299d14b01SJoseph Chen return 0;
18399d14b01SJoseph Chen }
18499d14b01SJoseph Chen #endif
18599d14b01SJoseph Chen
18699d14b01SJoseph Chen #ifdef CONFIG_DM_CRYPTO
do_test_crypto(cmd_tbl_t * cmdtp,int flag,int argc,char * const argv[])18799d14b01SJoseph Chen static int do_test_crypto(cmd_tbl_t *cmdtp, int flag,
18899d14b01SJoseph Chen int argc, char *const argv[])
18999d14b01SJoseph Chen {
19099d14b01SJoseph Chen return run_command("crypto", 0);
19199d14b01SJoseph Chen }
19299d14b01SJoseph Chen #endif
19399d14b01SJoseph Chen
19499d14b01SJoseph Chen #ifdef CONFIG_ADC
do_test_adc(cmd_tbl_t * cmdtp,int flag,int argc,char * const argv[])19599d14b01SJoseph Chen static int do_test_adc(cmd_tbl_t *cmdtp, int flag,
19699d14b01SJoseph Chen int argc, char *const argv[])
19799d14b01SJoseph Chen {
19899d14b01SJoseph Chen uint val, chn;
19999d14b01SJoseph Chen int ret;
20099d14b01SJoseph Chen
20199d14b01SJoseph Chen chn = argc < 2 ? 0 : strtoul(argv[1], NULL, 10);
20299d14b01SJoseph Chen ret = adc_channel_single_shot("saradc", chn, &val);
203443feaabSJoseph Chen if (ret)
204a6c9ff86SJoseph Chen ret = adc_channel_single_shot("adc", chn, &val);
205a6c9ff86SJoseph Chen if (ret)
206443feaabSJoseph Chen ut_err("adc: failed to get channel%d value, ret=%d\n", chn, ret);
207443feaabSJoseph Chen
20899d14b01SJoseph Chen printf("adc channel%d: adc value is %d\n", chn, val);
20999d14b01SJoseph Chen
21099d14b01SJoseph Chen return ret;
21199d14b01SJoseph Chen }
21299d14b01SJoseph Chen #endif
21399d14b01SJoseph Chen
21499d14b01SJoseph Chen static cmd_tbl_t sub_cmd[] = {
21599d14b01SJoseph Chen #ifdef CONFIG_DM_CRYPTO
21699d14b01SJoseph Chen UNIT_CMD_DEFINE(crypto, 0),
21799d14b01SJoseph Chen #endif
21899d14b01SJoseph Chen #ifdef CONFIG_RK_IR
21999d14b01SJoseph Chen UNIT_CMD_ATTR_DEFINE(ir, 0, CMD_FLG_INTERACTIVE),
22099d14b01SJoseph Chen #endif
22199d14b01SJoseph Chen #ifdef CONFIG_DM_KEY
22299d14b01SJoseph Chen UNIT_CMD_ATTR_DEFINE(key, 0, CMD_FLG_INTERACTIVE),
22399d14b01SJoseph Chen #endif
22499d14b01SJoseph Chen #ifdef CONFIG_ADC
22599d14b01SJoseph Chen UNIT_CMD_DEFINE(adc, 0),
22699d14b01SJoseph Chen #endif
22799d14b01SJoseph Chen #ifdef CONFIG_IRQ
22899d14b01SJoseph Chen UNIT_CMD_DEFINE(timer, 0),
22999d14b01SJoseph Chen #endif
23099d14b01SJoseph Chen };
23199d14b01SJoseph Chen
23299d14b01SJoseph Chen static const char sub_cmd_help[] =
23399d14b01SJoseph Chen #ifdef CONFIG_DM_CRYPTO
23499d14b01SJoseph Chen " [.] rktest crypto - test crypto\n"
23599d14b01SJoseph Chen #endif
23699d14b01SJoseph Chen #ifdef CONFIG_RK_IR
23799d14b01SJoseph Chen " [i] rktest ir - test pwm ir remoter\n"
23899d14b01SJoseph Chen #endif
23999d14b01SJoseph Chen #ifdef CONFIG_DM_KEY
24099d14b01SJoseph Chen " [i] rktest key - test key buttons\n"
24199d14b01SJoseph Chen #endif
24299d14b01SJoseph Chen #ifdef CONFIG_ADC
24399d14b01SJoseph Chen " [.] rktest adc [chn] - test adc channel\n"
24499d14b01SJoseph Chen #endif
24599d14b01SJoseph Chen #ifdef CONFIG_IRQ
24699d14b01SJoseph Chen " [.] rktest timer - test timer and interrupt\n"
24799d14b01SJoseph Chen #endif
24899d14b01SJoseph Chen ;
24999d14b01SJoseph Chen
25099d14b01SJoseph Chen const struct cmd_group cmd_grp_misc = {
25199d14b01SJoseph Chen .id = TEST_ID_MISC,
25299d14b01SJoseph Chen .help = sub_cmd_help,
25399d14b01SJoseph Chen .cmd = sub_cmd,
25499d14b01SJoseph Chen .cmd_n = ARRAY_SIZE(sub_cmd),
25599d14b01SJoseph Chen };
256