brintos

brintos / linux-shallow public Read only

0
0
Text · 14.8 KiB · 5f16a7b Raw
516 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/* Unit tests for IIO light sensor gain-time-scale helpers3 *4 * Copyright (c) 2023 Matti Vaittinen <mazziesaccount@gmail.com>5 */6 7#include <kunit/device.h>8#include <kunit/test.h>9#include <linux/device.h>10#include <linux/iio/iio-gts-helper.h>11#include <linux/iio/types.h>12 13/*14 * Please, read the "rant" from the top of the lib/test_linear_ranges.c if15 * you see a line of helper code which is not being tested.16 *17 * Then, please look at the line which is not being tested. Is this line18 * somehow unusually complex? If answer is "no", then chances are that the19 * "development inertia" caused by adding a test exceeds the benefits.20 *21 * If yes, then adding a test is probably a good idea but please stop for a22 * moment and consider the effort of changing all the tests when code gets23 * refactored. Eventually it neeeds to be.24 */25 26#define TEST_TSEL_50		127#define TEST_TSEL_X_MIN		TEST_TSEL_5028#define TEST_TSEL_100		029#define TEST_TSEL_200		230#define TEST_TSEL_400		431#define TEST_TSEL_X_MAX		TEST_TSEL_40032 33#define TEST_GSEL_1		0x0034#define TEST_GSEL_X_MIN		TEST_GSEL_135#define TEST_GSEL_4		0x0836#define TEST_GSEL_16		0x0a37#define TEST_GSEL_32		0x0b38#define TEST_GSEL_64		0x0c39#define TEST_GSEL_256		0x1840#define TEST_GSEL_512		0x1941#define TEST_GSEL_1024		0x1a42#define TEST_GSEL_2048		0x1b43#define TEST_GSEL_4096		0x1c44#define TEST_GSEL_X_MAX		TEST_GSEL_409645 46#define TEST_SCALE_1X		6447#define TEST_SCALE_MIN_X	TEST_SCALE_1X48#define TEST_SCALE_2X		3249#define TEST_SCALE_4X		1650#define TEST_SCALE_8X		851#define TEST_SCALE_16X		452#define TEST_SCALE_32X		253#define TEST_SCALE_64X		154 55#define TEST_SCALE_NANO_128X	50000000056#define TEST_SCALE_NANO_256X	25000000057#define TEST_SCALE_NANO_512X	12500000058#define TEST_SCALE_NANO_1024X	6250000059#define TEST_SCALE_NANO_2048X	3125000060#define TEST_SCALE_NANO_4096X	1562500061#define TEST_SCALE_NANO_4096X2	781250062#define TEST_SCALE_NANO_4096X4	390625063#define TEST_SCALE_NANO_4096X8	195312564 65#define TEST_SCALE_NANO_MAX_X TEST_SCALE_NANO_4096X866 67/*68 * Can't have this allocated from stack because the kunit clean-up will69 * happen only after the test function has already gone70 */71static struct iio_gts gts;72 73/* Keep the gain and time tables unsorted to test the sorting */74static const struct iio_gain_sel_pair gts_test_gains[] = {75	GAIN_SCALE_GAIN(1, TEST_GSEL_1),76	GAIN_SCALE_GAIN(4, TEST_GSEL_4),77	GAIN_SCALE_GAIN(16, TEST_GSEL_16),78	GAIN_SCALE_GAIN(32, TEST_GSEL_32),79	GAIN_SCALE_GAIN(64, TEST_GSEL_64),80	GAIN_SCALE_GAIN(256, TEST_GSEL_256),81	GAIN_SCALE_GAIN(512, TEST_GSEL_512),82	GAIN_SCALE_GAIN(1024, TEST_GSEL_1024),83	GAIN_SCALE_GAIN(4096, TEST_GSEL_4096),84	GAIN_SCALE_GAIN(2048, TEST_GSEL_2048),85#define HWGAIN_MAX 409686};87 88static const struct iio_itime_sel_mul gts_test_itimes[] = {89	GAIN_SCALE_ITIME_US(100 * 1000, TEST_TSEL_100, 2),90	GAIN_SCALE_ITIME_US(400 * 1000, TEST_TSEL_400, 8),91	GAIN_SCALE_ITIME_US(400 * 1000, TEST_TSEL_400, 8),92	GAIN_SCALE_ITIME_US(50 * 1000, TEST_TSEL_50, 1),93	GAIN_SCALE_ITIME_US(200 * 1000, TEST_TSEL_200, 4),94#define TIMEGAIN_MAX 895};96#define TOTAL_GAIN_MAX	(HWGAIN_MAX * TIMEGAIN_MAX)97#define IIO_GTS_TEST_DEV "iio-gts-test-dev"98 99static struct device *__test_init_iio_gain_scale(struct kunit *test,100		struct iio_gts *gts, const struct iio_gain_sel_pair *g_table,101		int num_g, const struct iio_itime_sel_mul *i_table, int num_i)102{103	struct device *dev;104	int ret;105 106	dev = kunit_device_register(test, IIO_GTS_TEST_DEV);107 108	KUNIT_EXPECT_NOT_ERR_OR_NULL(test, dev);109	if (IS_ERR_OR_NULL(dev))110		return NULL;111 112	ret = devm_iio_init_iio_gts(dev, TEST_SCALE_1X, 0, g_table, num_g,113				    i_table, num_i, gts);114	KUNIT_EXPECT_EQ(test, 0, ret);115	if (ret)116		return NULL;117 118	return dev;119}120 121#define test_init_iio_gain_scale(test, gts)	\122	__test_init_iio_gain_scale(test, gts, gts_test_gains, \123				   ARRAY_SIZE(gts_test_gains), gts_test_itimes, \124				   ARRAY_SIZE(gts_test_itimes))125 126static void test_init_iio_gts_invalid(struct kunit *test)127{128	struct device *dev;129	int ret;130	const struct iio_itime_sel_mul itimes_neg[] = {131		GAIN_SCALE_ITIME_US(-10, TEST_TSEL_400, 8),132		GAIN_SCALE_ITIME_US(200 * 1000, TEST_TSEL_200, 4),133	};134	const struct iio_gain_sel_pair gains_neg[] = {135		GAIN_SCALE_GAIN(1, TEST_GSEL_1),136		GAIN_SCALE_GAIN(2, TEST_GSEL_4),137		GAIN_SCALE_GAIN(-2, TEST_GSEL_16),138	};139	/* 55555 * 38656 = 2147534080 => overflows 32bit int */140	const struct iio_itime_sel_mul itimes_overflow[] = {141		GAIN_SCALE_ITIME_US(400 * 1000, TEST_TSEL_400, 55555),142		GAIN_SCALE_ITIME_US(200 * 1000, TEST_TSEL_200, 4),143	};144	const struct iio_gain_sel_pair gains_overflow[] = {145		GAIN_SCALE_GAIN(1, TEST_GSEL_1),146		GAIN_SCALE_GAIN(2, TEST_GSEL_4),147		GAIN_SCALE_GAIN(38656, TEST_GSEL_16),148	};149 150	dev = kunit_device_register(test, IIO_GTS_TEST_DEV);151	KUNIT_EXPECT_NOT_ERR_OR_NULL(test, dev);152	if (!dev)153		return;154 155	/* Ok gains, negative time */156	ret = devm_iio_init_iio_gts(dev, TEST_SCALE_1X, 0, gts_test_gains,157				    ARRAY_SIZE(gts_test_gains), itimes_neg,158				    ARRAY_SIZE(itimes_neg), &gts);159	KUNIT_EXPECT_EQ(test, -EINVAL, ret);160 161	/* Ok times, negative gain */162	ret = devm_iio_init_iio_gts(dev, TEST_SCALE_1X, 0, gains_neg,163				    ARRAY_SIZE(gains_neg), gts_test_itimes,164				    ARRAY_SIZE(gts_test_itimes), &gts);165	KUNIT_EXPECT_EQ(test, -EINVAL, ret);166 167	/* gain * time overflow int */168	ret = devm_iio_init_iio_gts(dev, TEST_SCALE_1X, 0, gains_overflow,169				    ARRAY_SIZE(gains_overflow), itimes_overflow,170				    ARRAY_SIZE(itimes_overflow), &gts);171	KUNIT_EXPECT_EQ(test, -EOVERFLOW, ret);172}173 174static void test_iio_gts_find_gain_for_scale_using_time(struct kunit *test)175{176	struct device *dev;177	int ret, gain_sel;178 179	dev = test_init_iio_gain_scale(test, &gts);180	if (!dev)181		return;182 183	ret = iio_gts_find_gain_sel_for_scale_using_time(&gts, TEST_TSEL_100,184						TEST_SCALE_8X, 0, &gain_sel);185	/*186	 * Meas time 100 => gain by time 2x187	 * TEST_SCALE_8X matches total gain 8x188	 * => required HWGAIN 4x189	 */190	KUNIT_EXPECT_EQ(test, 0, ret);191	KUNIT_EXPECT_EQ(test, TEST_GSEL_4, gain_sel);192 193	ret = iio_gts_find_gain_sel_for_scale_using_time(&gts, TEST_TSEL_200, 0,194						TEST_SCALE_NANO_256X, &gain_sel);195	/*196	 * Meas time 200 => gain by time 4x197	 * TEST_SCALE_256X matches total gain 256x198	 * => required HWGAIN 256/4 => 64x199	 */200	KUNIT_EXPECT_EQ(test, 0, ret);201	KUNIT_EXPECT_EQ(test, TEST_GSEL_64, gain_sel);202 203	/* Min time, Min gain */204	ret = iio_gts_find_gain_sel_for_scale_using_time(&gts, TEST_TSEL_X_MIN,205						TEST_SCALE_MIN_X, 0, &gain_sel);206	KUNIT_EXPECT_EQ(test, 0, ret);207	KUNIT_EXPECT_EQ(test, TEST_GSEL_1, gain_sel);208 209	/* Max time, Max gain */210	ret = iio_gts_find_gain_sel_for_scale_using_time(&gts, TEST_TSEL_X_MAX,211					0, TEST_SCALE_NANO_MAX_X, &gain_sel);212	KUNIT_EXPECT_EQ(test, 0, ret);213	KUNIT_EXPECT_EQ(test, TEST_GSEL_4096, gain_sel);214 215	ret = iio_gts_find_gain_sel_for_scale_using_time(&gts, TEST_TSEL_100, 0,216						TEST_SCALE_NANO_256X, &gain_sel);217	/*218	 * Meas time 100 => gain by time 2x219	 * TEST_SCALE_256X matches total gain 256x220	 * => required HWGAIN 256/2 => 128x (not in gain-table - unsupported)221	 */222	KUNIT_EXPECT_NE(test, 0, ret);223 224	ret = iio_gts_find_gain_sel_for_scale_using_time(&gts, TEST_TSEL_200, 0,225						TEST_SCALE_NANO_MAX_X, &gain_sel);226	/* We can't reach the max gain with integration time smaller than MAX */227	KUNIT_EXPECT_NE(test, 0, ret);228 229	ret = iio_gts_find_gain_sel_for_scale_using_time(&gts, TEST_TSEL_50, 0,230						TEST_SCALE_NANO_MAX_X, &gain_sel);231	/* We can't reach the max gain with integration time smaller than MAX */232	KUNIT_EXPECT_NE(test, 0, ret);233}234 235static void test_iio_gts_find_new_gain_sel_by_old_gain_time(struct kunit *test)236{237	struct device *dev;238	int ret, old_gain, new_gain, old_time_sel, new_time_sel;239 240	dev = test_init_iio_gain_scale(test, &gts);241	if (!dev)242		return;243 244	old_gain = 32;245	old_time_sel = TEST_TSEL_200;246	new_time_sel = TEST_TSEL_400;247 248	ret = iio_gts_find_new_gain_sel_by_old_gain_time(&gts, old_gain,249					old_time_sel, new_time_sel, &new_gain);250	KUNIT_EXPECT_EQ(test, 0, ret);251	/*252	 * Doubling the integration time doubles the total gain - so old253	 * (hw)gain must be divided by two to compensate. => 32 / 2 => 16254	 */255	KUNIT_EXPECT_EQ(test, 16, new_gain);256 257	old_gain = 4;258	old_time_sel = TEST_TSEL_50;259	new_time_sel = TEST_TSEL_200;260	ret = iio_gts_find_new_gain_sel_by_old_gain_time(&gts, old_gain,261					old_time_sel, new_time_sel, &new_gain);262	KUNIT_EXPECT_EQ(test, 0, ret);263	/*264	 * gain by time 1x => 4x - (hw)gain 4x => 1x265	 */266	KUNIT_EXPECT_EQ(test, 1, new_gain);267 268	old_gain = 512;269	old_time_sel = TEST_TSEL_400;270	new_time_sel = TEST_TSEL_50;271	ret = iio_gts_find_new_gain_sel_by_old_gain_time(&gts, old_gain,272					old_time_sel, new_time_sel, &new_gain);273	KUNIT_EXPECT_EQ(test, 0, ret);274	/*275	 * gain by time 8x => 1x - (hw)gain 512x => 4096x)276	 */277	KUNIT_EXPECT_EQ(test, 4096, new_gain);278 279	/* Unsupported gain 2x */280	old_gain = 4;281	old_time_sel = TEST_TSEL_200;282	new_time_sel = TEST_TSEL_400;283	ret = iio_gts_find_new_gain_sel_by_old_gain_time(&gts, old_gain,284					old_time_sel, new_time_sel, &new_gain);285	KUNIT_EXPECT_NE(test, 0, ret);286 287	/* Too small gain */288	old_gain = 4;289	old_time_sel = TEST_TSEL_50;290	new_time_sel = TEST_TSEL_400;291	ret = iio_gts_find_new_gain_sel_by_old_gain_time(&gts, old_gain,292					old_time_sel, new_time_sel, &new_gain);293	KUNIT_EXPECT_NE(test, 0, ret);294 295	/* Too big gain */296	old_gain = 1024;297	old_time_sel = TEST_TSEL_400;298	new_time_sel = TEST_TSEL_50;299	ret = iio_gts_find_new_gain_sel_by_old_gain_time(&gts, old_gain,300					old_time_sel, new_time_sel, &new_gain);301	KUNIT_EXPECT_NE(test, 0, ret);302 303}304 305static void test_iio_find_closest_gain_low(struct kunit *test)306{307	struct device *dev;308	bool in_range;309	int ret;310 311	const struct iio_gain_sel_pair gts_test_gains_gain_low[] = {312		GAIN_SCALE_GAIN(4, TEST_GSEL_4),313		GAIN_SCALE_GAIN(16, TEST_GSEL_16),314		GAIN_SCALE_GAIN(32, TEST_GSEL_32),315	};316 317	dev = test_init_iio_gain_scale(test, &gts);318	if (!dev)319		return;320 321	ret = iio_find_closest_gain_low(&gts, 2, &in_range);322	KUNIT_EXPECT_EQ(test, 1, ret);323	KUNIT_EXPECT_EQ(test, true, in_range);324 325	ret = iio_find_closest_gain_low(&gts, 1, &in_range);326	KUNIT_EXPECT_EQ(test, 1, ret);327	KUNIT_EXPECT_EQ(test, true, in_range);328 329	ret = iio_find_closest_gain_low(&gts, 4095, &in_range);330	KUNIT_EXPECT_EQ(test, 2048, ret);331	KUNIT_EXPECT_EQ(test, true, in_range);332 333	ret = iio_find_closest_gain_low(&gts, 4097, &in_range);334	KUNIT_EXPECT_EQ(test, 4096, ret);335	KUNIT_EXPECT_EQ(test, false, in_range);336 337	kunit_device_unregister(test, dev);338 339	dev = __test_init_iio_gain_scale(test, &gts, gts_test_gains_gain_low,340				ARRAY_SIZE(gts_test_gains_gain_low),341				gts_test_itimes, ARRAY_SIZE(gts_test_itimes));342	if (!dev)343		return;344 345	ret = iio_find_closest_gain_low(&gts, 3, &in_range);346	KUNIT_EXPECT_EQ(test, -EINVAL, ret);347	KUNIT_EXPECT_EQ(test, false, in_range);348}349 350static void test_iio_gts_total_gain_to_scale(struct kunit *test)351{352	struct device *dev;353	int ret, scale_int, scale_nano;354 355	dev = test_init_iio_gain_scale(test, &gts);356	if (!dev)357		return;358 359	ret = iio_gts_total_gain_to_scale(&gts, 1, &scale_int, &scale_nano);360	KUNIT_EXPECT_EQ(test, 0, ret);361	KUNIT_EXPECT_EQ(test, TEST_SCALE_1X, scale_int);362	KUNIT_EXPECT_EQ(test, 0, scale_nano);363 364	ret = iio_gts_total_gain_to_scale(&gts, 1, &scale_int, &scale_nano);365	KUNIT_EXPECT_EQ(test, 0, ret);366	KUNIT_EXPECT_EQ(test, TEST_SCALE_1X, scale_int);367	KUNIT_EXPECT_EQ(test, 0, scale_nano);368 369	ret = iio_gts_total_gain_to_scale(&gts, 4096 * 8, &scale_int,370					  &scale_nano);371	KUNIT_EXPECT_EQ(test, 0, ret);372	KUNIT_EXPECT_EQ(test, 0, scale_int);373	KUNIT_EXPECT_EQ(test, TEST_SCALE_NANO_4096X8, scale_nano);374}375 376static void test_iio_gts_chk_times(struct kunit *test, const int *vals)377{378	static const int expected[] = {0, 50000, 0, 100000, 0, 200000, 0, 400000};379	int i;380 381	for (i = 0; i < ARRAY_SIZE(expected); i++)382		KUNIT_EXPECT_EQ(test, expected[i], vals[i]);383}384 385static void test_iio_gts_chk_scales_all(struct kunit *test, struct iio_gts *gts,386					const int *vals, int len)387{388	static const int gains[] = {1, 2, 4, 8, 16, 32, 64, 128, 256, 512,389				    1024, 2048, 4096, 4096 * 2, 4096 * 4,390				    4096 * 8};391	int expected[ARRAY_SIZE(gains) * 2];392	int i, ret;393	int exp_len = ARRAY_SIZE(gains) * 2;394 395	KUNIT_EXPECT_EQ(test, exp_len, len);396	if (len != exp_len)397		return;398 399	for (i = 0; i < ARRAY_SIZE(gains); i++) {400		ret = iio_gts_total_gain_to_scale(gts, gains[i],401						  &expected[2 * i],402						  &expected[2 * i + 1]);403		KUNIT_EXPECT_EQ(test, 0, ret);404		if (ret)405			return;406	}407 408	for (i = 0; i < ARRAY_SIZE(expected); i++)409		KUNIT_EXPECT_EQ(test, expected[i], vals[i]);410}411 412static void test_iio_gts_chk_scales_t200(struct kunit *test, struct iio_gts *gts,413					 const int *vals, int len)414{415	/* The gain caused by time 200 is 4x */416	static const int gains[] = {417		1 * 4,418		4 * 4,419		16 * 4,420		32 * 4,421		64 * 4,422		256 * 4,423		512 * 4,424		1024 * 4,425		2048 * 4,426		4096 * 4427	};428	int expected[ARRAY_SIZE(gains) * 2];429	int i, ret;430 431	KUNIT_EXPECT_EQ(test, 2 * ARRAY_SIZE(gains), len);432	if (len < 2 * ARRAY_SIZE(gains))433		return;434 435	for (i = 0; i < ARRAY_SIZE(gains); i++) {436		ret = iio_gts_total_gain_to_scale(gts, gains[i],437						  &expected[2 * i],438						  &expected[2 * i + 1]);439		KUNIT_EXPECT_EQ(test, 0, ret);440		if (ret)441			return;442	}443 444	for (i = 0; i < ARRAY_SIZE(expected); i++)445		KUNIT_EXPECT_EQ(test, expected[i], vals[i]);446}447 448static void test_iio_gts_avail_test(struct kunit *test)449{450	struct device *dev;451	int ret;452	int type, len;453	const int *vals;454 455	dev = test_init_iio_gain_scale(test, &gts);456	if (!dev)457		return;458 459	/* test table building for times and iio_gts_avail_times() */460	ret = iio_gts_avail_times(&gts, &vals, &type, &len);461	KUNIT_EXPECT_EQ(test, IIO_AVAIL_LIST, ret);462	if (ret)463		return;464 465	KUNIT_EXPECT_EQ(test, IIO_VAL_INT_PLUS_MICRO, type);466	KUNIT_EXPECT_EQ(test, 8, len);467	if (len < 8)468		return;469 470	test_iio_gts_chk_times(test, vals);471 472	/* Test table building for all scales and iio_gts_all_avail_scales() */473	ret = iio_gts_all_avail_scales(&gts, &vals, &type, &len);474	KUNIT_EXPECT_EQ(test, IIO_AVAIL_LIST, ret);475	if (ret)476		return;477 478	KUNIT_EXPECT_EQ(test, IIO_VAL_INT_PLUS_NANO, type);479 480	test_iio_gts_chk_scales_all(test, &gts, vals, len);481 482	/*483	 * Test table building for scales/time and484	 * iio_gts_avail_scales_for_time()485	 */486	ret = iio_gts_avail_scales_for_time(&gts, 200000, &vals, &type, &len);487	KUNIT_EXPECT_EQ(test, IIO_AVAIL_LIST, ret);488	if (ret)489		return;490 491	KUNIT_EXPECT_EQ(test, IIO_VAL_INT_PLUS_NANO, type);492	test_iio_gts_chk_scales_t200(test, &gts, vals, len);493}494 495static struct kunit_case iio_gts_test_cases[] = {496	KUNIT_CASE(test_init_iio_gts_invalid),497	KUNIT_CASE(test_iio_gts_find_gain_for_scale_using_time),498	KUNIT_CASE(test_iio_gts_find_new_gain_sel_by_old_gain_time),499	KUNIT_CASE(test_iio_find_closest_gain_low),500	KUNIT_CASE(test_iio_gts_total_gain_to_scale),501	KUNIT_CASE(test_iio_gts_avail_test),502	{}503};504 505static struct kunit_suite iio_gts_test_suite = {506	.name = "iio-gain-time-scale",507	.test_cases = iio_gts_test_cases,508};509 510kunit_test_suite(iio_gts_test_suite);511 512MODULE_LICENSE("GPL");513MODULE_AUTHOR("Matti Vaittinen <mazziesaccount@gmail.com>");514MODULE_DESCRIPTION("Test IIO light sensor gain-time-scale helpers");515MODULE_IMPORT_NS(IIO_GTS_HELPER);516