Skip to content

Commit 5b5e01b

Browse files
danieldegrassedleach02
authored andcommitted
tests: sdhc: Add SD host controller driver test
SD host controller driver runs basic SD host controller tests, including checking SD presence, and sending commands to SD card. No data transfer is performed. Signed-off-by: Daniel DeGrasse <[email protected]>
1 parent 32cd207 commit 5b5e01b

File tree

6 files changed

+222
-0
lines changed

6 files changed

+222
-0
lines changed

tests/drivers/sdhc/CMakeLists.txt

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
# SPDX-License-Identifier: Apache-2.0
2+
3+
cmake_minimum_required(VERSION 3.20.0)
4+
find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE})
5+
project(sdhc_test)
6+
7+
FILE(GLOB app_sources src/*.c)
8+
target_sources(app PRIVATE ${app_sources})

tests/drivers/sdhc/Kconfig

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
# Copyright 2022 NXP
2+
# SPDX-License-Identifier: Apache-2.0
3+
4+
mainmenu "SD Host controller test"
5+
6+
source "Kconfig.zephyr"
7+
8+
config SDHC_LABEL
9+
string "SD host controller label"
10+
default "SDHC_0"
11+
help
12+
Devicetree label for SD host controller. Used to get reference to
13+
device

tests/drivers/sdhc/README.txt

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
SDHC API Test
2+
##################
3+
4+
This test is designed to verify the functionality of a device implementing the
5+
SD host controller API. It requires that an SD card be present on the SD bus
6+
to pass. The test has the following phases:
7+
8+
* Reset test: Verify the SDHC can successfully reset the host controller state.
9+
This primarily tests that the driver returns zero for this call, although if
10+
the reset left the SDHC in a bad state subsequent tests may fail.
11+
12+
* Host props: Get host properties structure from SDHC. This verifies that
13+
the API returns a valid host property structure (at a minimum, the driver
14+
must initialize all fields of the structure to zero.)
15+
16+
* Set_IO test: Verify that the SDHC will reject clock frequencies outside of
17+
the frequency range it claims to support via sdhc_get_host_props.
18+
19+
* Card presence test. Verify that the SDHC detects card presence.
20+
21+
* Request test: Make a request to read the card interface condition,
22+
and verify that valid data is returned.
23+
24+
Note that this test does not verify the tuning or card busy api, as the SD
25+
specification is state based, and testing these portions of the SDHC would
26+
require implementing a large portion of the SD subsystem in this test.

tests/drivers/sdhc/prj.conf

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
CONFIG_TEST=y
2+
CONFIG_ZTEST=y
3+
CONFIG_SDHC=y

tests/drivers/sdhc/src/main.c

Lines changed: 160 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,160 @@
1+
/*
2+
* Copyright 2022 NXP
3+
*
4+
* SPDX-License-Identifier: Apache-2.0
5+
*/
6+
7+
#include <zephyr/zephyr.h>
8+
#include <zephyr/drivers/sdhc.h>
9+
#include <zephyr/device.h>
10+
#include <ztest.h>
11+
12+
static const struct device *sdhc_dev;
13+
static struct sdhc_host_props props;
14+
static struct sdhc_io io;
15+
16+
#define SDHC_FREQUENCY_SLIP 10000000
17+
18+
/* Resets SD host controller, verifies API */
19+
static void test_reset(void)
20+
{
21+
sdhc_dev = device_get_binding(CONFIG_SDHC_LABEL);
22+
int ret;
23+
24+
zassert_not_null(sdhc_dev, "Could not get SDHC device");
25+
26+
ret = sdhc_hw_reset(sdhc_dev);
27+
zassert_equal(ret, 0, "SDHC HW reset failed");
28+
}
29+
30+
/* Gets host properties, verifies all properties are set */
31+
static void test_host_props(void)
32+
{
33+
int ret;
34+
35+
/* Set all host properties to 0xFF */
36+
props.f_max = 0xFF;
37+
props.f_min = 0xFF;
38+
props.power_delay = 0xFF;
39+
props.max_current_330 = 0xFF;
40+
props.max_current_300 = 0xFF;
41+
props.max_current_180 = 0xFF;
42+
ret = sdhc_get_host_props(sdhc_dev, &props);
43+
zassert_equal(ret, 0, "SDHC host props api call failed");
44+
45+
zassert_not_equal(props.f_max, 0xFF, "props structure not initialized");
46+
zassert_not_equal(props.f_min, 0xFF, "props structure not initialized");
47+
zassert_not_equal(props.power_delay, 0xFF, "props structure not initialized");
48+
zassert_not_equal(props.max_current_330, 0xFF, "props structure not initialized");
49+
zassert_not_equal(props.max_current_300, 0xFF, "props structure not initialized");
50+
zassert_not_equal(props.max_current_180, 0xFF, "props structure not initialized");
51+
}
52+
53+
/* Verify that driver rejects frequencies outside of claimed range */
54+
static void test_set_io(void)
55+
{
56+
int ret;
57+
58+
io.clock = props.f_min;
59+
io.bus_mode = SDHC_BUSMODE_PUSHPULL;
60+
io.power_mode = SDHC_POWER_ON;
61+
io.bus_width = SDHC_BUS_WIDTH1BIT;
62+
io.timing = SDHC_TIMING_LEGACY;
63+
io.signal_voltage = SD_VOL_3_3_V;
64+
65+
ret = sdhc_set_io(sdhc_dev, &io);
66+
zassert_equal(ret, 0, "IO configuration failed");
67+
68+
/* Verify that IO configuration fails with high frequency */
69+
/* Since SDHC may select nearby frequency, increase frequency
70+
* by a large margin over the max.
71+
*/
72+
io.clock = props.f_max + SDHC_FREQUENCY_SLIP;
73+
ret = sdhc_set_io(sdhc_dev, &io);
74+
zassert_not_equal(ret, 0, "Invalid io configuration should not succeed");
75+
}
76+
77+
78+
/* Verify that the driver can detect a present SD card */
79+
static void test_card_presence(void)
80+
{
81+
int ret;
82+
83+
io.clock = props.f_min;
84+
ret = sdhc_set_io(sdhc_dev, &io);
85+
zassert_equal(ret, 0, "Setting io configuration failed");
86+
k_msleep(props.power_delay);
87+
88+
ret = sdhc_card_present(sdhc_dev);
89+
zassert_equal(ret, 1, "Card is not reported as present, is one connected?");
90+
}
91+
92+
/* Verify that the driver can send commands to SD card, by reading interface
93+
* condition. This follows the first part of the SD initialization defined in
94+
* the SD specification.
95+
*/
96+
static void test_card_if_cond(void)
97+
{
98+
struct sdhc_command cmd;
99+
int ret, resp;
100+
int check_pattern = SD_IF_COND_CHECK;
101+
102+
/* Toggle power to card, to clear state */
103+
io.power_mode = SDHC_POWER_OFF;
104+
ret = sdhc_set_io(sdhc_dev, &io);
105+
zassert_equal(ret, 0, "Setting io configuration failed");
106+
k_msleep(props.power_delay);
107+
io.power_mode = SDHC_POWER_ON;
108+
ret = sdhc_set_io(sdhc_dev, &io);
109+
zassert_equal(ret, 0, "Setting io configuration failed");
110+
k_msleep(props.power_delay);
111+
112+
113+
memset(&cmd, 0, sizeof(struct sdhc_command));
114+
cmd.opcode = SD_GO_IDLE_STATE;
115+
cmd.response_type = (SD_RSP_TYPE_NONE | SD_SPI_RSP_TYPE_R1);
116+
cmd.timeout_ms = 200;
117+
118+
ret = sdhc_request(sdhc_dev, &cmd, NULL);
119+
zassert_equal(ret, 0, "Card reset command failed");
120+
121+
cmd.opcode = SD_SEND_IF_COND;
122+
/* Indicate 3.3V support, plus check pattern */
123+
cmd.arg = SD_IF_COND_VHS_3V3 | check_pattern;
124+
cmd.response_type = (SD_RSP_TYPE_R7 | SD_SPI_RSP_TYPE_R7);
125+
cmd.timeout_ms = 500;
126+
cmd.retries = 3;
127+
128+
ret = sdhc_request(sdhc_dev, &cmd, NULL);
129+
zassert_equal(ret, 0, "Read Interface condition failed");
130+
if (props.is_spi) {
131+
resp = cmd.response[1];
132+
} else {
133+
resp = cmd.response[0];
134+
}
135+
if ((resp & 0xFF) == check_pattern) {
136+
/* Although both responses are valid in SD spec, most
137+
* modern cards are SDHC or better, and should respond as such.
138+
*/
139+
TC_PRINT("Found SDHC/SDXC card\n");
140+
} else if (resp & 0x4) {
141+
/* An illegal command response indicates an SDSC card */
142+
TC_PRINT("Found SDSC card\n");
143+
} else {
144+
zassert_unreachable("Invalid response to SD interface condition");
145+
}
146+
}
147+
148+
149+
void test_main(void)
150+
{
151+
ztest_test_suite(sdhc_api_test,
152+
ztest_unit_test(test_reset),
153+
ztest_unit_test(test_host_props),
154+
ztest_unit_test(test_set_io),
155+
ztest_unit_test(test_card_presence),
156+
ztest_unit_test(test_card_if_cond)
157+
);
158+
159+
ztest_run_test_suite(sdhc_api_test);
160+
}

tests/drivers/sdhc/testcase.yaml

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
common:
2+
depends_on: sdhc
3+
tags: drivers sdhc
4+
tests:
5+
drivers.sdhc.sdhc_api:
6+
harness: ztest
7+
harness_config:
8+
fixture: fixture_sdhc
9+
filter: CONFIG_SDHC
10+
tags: sdhc
11+
integration_platforms:
12+
- mimxrt1064_evk

0 commit comments

Comments
 (0)