1// SPDX-License-Identifier: GPL-2.0+ 2/* 3 * Copyright (C) 2015 Google, Inc 4 */ 5 6#include <common.h> 7#include <dm.h> 8#include <log.h> 9#include <mapmem.h> 10#include <regmap.h> 11#include <syscon.h> 12#include <rand.h> 13#include <asm/test.h> 14#include <dm/test.h> 15#include <dm/devres.h> 16#include <linux/err.h> 17#include <test/test.h> 18#include <test/ut.h> 19 20/* Base test of register maps */ 21static int dm_test_regmap_base(struct unit_test_state *uts) 22{ 23 struct udevice *dev; 24 struct regmap *map; 25 ofnode node; 26 int i; 27 28 ut_assertok(uclass_get_device(UCLASS_SYSCON, 0, &dev)); 29 map = syscon_get_regmap(dev); 30 ut_assertok_ptr(map); 31 ut_asserteq(1, map->range_count); 32 ut_asserteq(0x10, map->ranges[0].start); 33 ut_asserteq(16, map->ranges[0].size); 34 ut_asserteq(0x10, map_to_sysmem(regmap_get_range(map, 0))); 35 36 ut_assertok(uclass_get_device(UCLASS_SYSCON, 1, &dev)); 37 map = syscon_get_regmap(dev); 38 ut_assertok_ptr(map); 39 ut_asserteq(4, map->range_count); 40 ut_asserteq(0x20, map->ranges[0].start); 41 for (i = 0; i < 4; i++) { 42 const unsigned long addr = 0x20 + 8 * i; 43 44 ut_asserteq(addr, map->ranges[i].start); 45 ut_asserteq(5 + i, map->ranges[i].size); 46 ut_asserteq(addr, map_to_sysmem(regmap_get_range(map, i))); 47 } 48 49 /* Check that we can't pretend a different device is a syscon */ 50 ut_assertok(uclass_get_device(UCLASS_I2C, 0, &dev)); 51 map = syscon_get_regmap(dev); 52 ut_asserteq_ptr(ERR_PTR(-ENOEXEC), map); 53 54 /* A different device can be a syscon by using Linux-compat API */ 55 node = ofnode_path("/syscon@2"); 56 ut_assert(ofnode_valid(node)); 57 58 map = syscon_node_to_regmap(node); 59 ut_assertok_ptr(map); 60 ut_asserteq(4, map->range_count); 61 ut_asserteq(0x40, map->ranges[0].start); 62 for (i = 0; i < 4; i++) { 63 const unsigned long addr = 0x40 + 8 * i; 64 65 ut_asserteq(addr, map->ranges[i].start); 66 ut_asserteq(5 + i, map->ranges[i].size); 67 ut_asserteq(addr, map_to_sysmem(regmap_get_range(map, i))); 68 } 69 70 return 0; 71} 72DM_TEST(dm_test_regmap_base, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); 73 74/* Test we can access a regmap through syscon */ 75static int dm_test_regmap_syscon(struct unit_test_state *uts) 76{ 77 struct regmap *map; 78 79 map = syscon_get_regmap_by_driver_data(SYSCON0); 80 ut_assertok_ptr(map); 81 ut_asserteq(1, map->range_count); 82 83 map = syscon_get_regmap_by_driver_data(SYSCON1); 84 ut_assertok_ptr(map); 85 ut_asserteq(4, map->range_count); 86 87 map = syscon_get_regmap_by_driver_data(SYSCON_COUNT); 88 ut_asserteq_ptr(ERR_PTR(-ENODEV), map); 89 90 ut_asserteq(0x10, map_to_sysmem(syscon_get_first_range(SYSCON0))); 91 ut_asserteq(0x20, map_to_sysmem(syscon_get_first_range(SYSCON1))); 92 ut_asserteq_ptr(ERR_PTR(-ENODEV), 93 syscon_get_first_range(SYSCON_COUNT)); 94 95 return 0; 96} 97 98DM_TEST(dm_test_regmap_syscon, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); 99 100/* Read/Write/Modify test */ 101static int dm_test_regmap_rw(struct unit_test_state *uts) 102{ 103 struct udevice *dev; 104 struct regmap *map; 105 uint reg; 106 107 sandbox_set_enable_memio(true); 108 ut_assertok(uclass_get_device(UCLASS_SYSCON, 0, &dev)); 109 map = syscon_get_regmap(dev); 110 ut_assertok_ptr(map); 111 112 ut_assertok(regmap_write(map, 0, 0xcacafafa)); 113 ut_assertok(regmap_write(map, 5, 0x55aa2211)); 114 115 ut_assertok(regmap_read(map, 0, ®)); 116 ut_asserteq(0xcacafafa, reg); 117 ut_assertok(regmap_read(map, 5, ®)); 118 ut_asserteq(0x55aa2211, reg); 119 120 ut_assertok(regmap_read(map, 0, ®)); 121 ut_asserteq(0xcacafafa, reg); 122 ut_assertok(regmap_update_bits(map, 0, 0xff00ff00, 0x55aa2211)); 123 ut_assertok(regmap_read(map, 0, ®)); 124 ut_asserteq(0x55ca22fa, reg); 125 ut_assertok(regmap_update_bits(map, 5, 0x00ff00ff, 0xcacafada)); 126 ut_assertok(regmap_read(map, 5, ®)); 127 ut_asserteq(0x55ca22da, reg); 128 129 return 0; 130} 131 132DM_TEST(dm_test_regmap_rw, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); 133 134/* Get/Set test */ 135static int dm_test_regmap_getset(struct unit_test_state *uts) 136{ 137 struct udevice *dev; 138 struct regmap *map; 139 uint reg; 140 struct layout { 141 u32 val0; 142 u32 val1; 143 u32 val2; 144 u32 val3; 145 }; 146 147 sandbox_set_enable_memio(true); 148 ut_assertok(uclass_get_device(UCLASS_SYSCON, 0, &dev)); 149 map = syscon_get_regmap(dev); 150 ut_assertok_ptr(map); 151 152 regmap_set(map, struct layout, val0, 0xcacafafa); 153 regmap_set(map, struct layout, val3, 0x55aa2211); 154 155 ut_assertok(regmap_get(map, struct layout, val0, ®)); 156 ut_asserteq(0xcacafafa, reg); 157 ut_assertok(regmap_get(map, struct layout, val3, ®)); 158 ut_asserteq(0x55aa2211, reg); 159 160 return 0; 161} 162 163DM_TEST(dm_test_regmap_getset, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); 164 165/* Read polling test */ 166static int dm_test_regmap_poll(struct unit_test_state *uts) 167{ 168 struct udevice *dev; 169 struct regmap *map; 170 uint reg; 171 unsigned long start; 172 173 ut_assertok(uclass_get_device(UCLASS_SYSCON, 0, &dev)); 174 map = syscon_get_regmap(dev); 175 ut_assertok_ptr(map); 176 177 start = get_timer(0); 178 179 ut_assertok(regmap_write(map, 0, 0x0)); 180 ut_asserteq(-ETIMEDOUT, 181 regmap_read_poll_timeout_test(map, 0, reg, 182 (reg == 0xcacafafa), 183 1, 5 * CONFIG_SYS_HZ, 184 5 * CONFIG_SYS_HZ)); 185 186 ut_assert(get_timer(start) > (5 * CONFIG_SYS_HZ)); 187 188 return 0; 189} 190 191DM_TEST(dm_test_regmap_poll, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); 192 193struct regmaptest_priv { 194 struct regmap *cfg_regmap; /* For testing regmap_config options. */ 195 struct regmap *fld_regmap; /* For testing regmap fields. */ 196 struct regmap_field **fields; 197}; 198 199static const struct reg_field field_cfgs[] = { 200 { 201 .reg = 0, 202 .lsb = 0, 203 .msb = 6, 204 }, 205 { 206 .reg = 2, 207 .lsb = 4, 208 .msb = 12, 209 }, 210 { 211 .reg = 2, 212 .lsb = 12, 213 .msb = 15, 214 } 215}; 216 217#define REGMAP_TEST_BUF_START 0 218#define REGMAP_TEST_BUF_SZ 5 219 220static int remaptest_probe(struct udevice *dev) 221{ 222 struct regmaptest_priv *priv = dev_get_priv(dev); 223 struct regmap *regmap; 224 struct regmap_field *field; 225 struct regmap_config cfg; 226 int i; 227 static const int n = ARRAY_SIZE(field_cfgs); 228 229 /* 230 * To exercise all the regmap config options, create a regmap that 231 * points to a custom memory area instead of the one defined in device 232 * tree. Use 2-byte elements. To allow directly indexing into the 233 * elements, use an offset shift of 1. So, accessing offset 1 gets the 234 * element at index 1 at memory location 2. 235 * 236 * REGMAP_TEST_BUF_SZ is the number of elements, so we need to multiply 237 * it by 2 because r_size expects number of bytes. 238 */ 239 cfg.reg_offset_shift = 1; 240 cfg.r_start = REGMAP_TEST_BUF_START; 241 cfg.r_size = REGMAP_TEST_BUF_SZ * 2; 242 cfg.width = REGMAP_SIZE_16; 243 244 regmap = devm_regmap_init(dev, NULL, NULL, &cfg); 245 if (IS_ERR(regmap)) 246 return PTR_ERR(regmap); 247 priv->cfg_regmap = regmap; 248 249 memset(&cfg, 0, sizeof(struct regmap_config)); 250 cfg.width = REGMAP_SIZE_16; 251 252 regmap = devm_regmap_init(dev, NULL, NULL, &cfg); 253 if (IS_ERR(regmap)) 254 return PTR_ERR(regmap); 255 priv->fld_regmap = regmap; 256 257 priv->fields = devm_kzalloc(dev, sizeof(struct regmap_field *) * n, 258 GFP_KERNEL); 259 if (!priv->fields) 260 return -ENOMEM; 261 262 for (i = 0 ; i < n; i++) { 263 field = devm_regmap_field_alloc(dev, priv->fld_regmap, 264 field_cfgs[i]); 265 if (IS_ERR(field)) 266 return PTR_ERR(field); 267 priv->fields[i] = field; 268 } 269 270 return 0; 271} 272 273static const struct udevice_id regmaptest_ids[] = { 274 { .compatible = "sandbox,regmap_test" }, 275 { } 276}; 277 278U_BOOT_DRIVER(regmap_test) = { 279 .name = "regmaptest_drv", 280 .of_match = regmaptest_ids, 281 .id = UCLASS_NOP, 282 .probe = remaptest_probe, 283 .priv_auto = sizeof(struct regmaptest_priv), 284}; 285 286static int dm_test_devm_regmap(struct unit_test_state *uts) 287{ 288 int i = 0; 289 uint val; 290 u16 pattern[REGMAP_TEST_BUF_SZ]; 291 u16 *buffer; 292 struct udevice *dev; 293 struct regmaptest_priv *priv; 294 295 sandbox_set_enable_memio(true); 296 297 /* 298 * Map the memory area the regmap should point to so we can make sure 299 * the writes actually go to that location. 300 */ 301 buffer = map_physmem(REGMAP_TEST_BUF_START, 302 REGMAP_TEST_BUF_SZ * 2, MAP_NOCACHE); 303 304 ut_assertok(uclass_get_device_by_name(UCLASS_NOP, "regmap-test_0", 305 &dev)); 306 priv = dev_get_priv(dev); 307 308 for (i = 0; i < REGMAP_TEST_BUF_SZ; i++) { 309 pattern[i] = i * 0x87654321; 310 ut_assertok(regmap_write(priv->cfg_regmap, i, pattern[i])); 311 } 312 for (i = 0; i < REGMAP_TEST_BUF_SZ; i++) { 313 ut_assertok(regmap_read(priv->cfg_regmap, i, &val)); 314 ut_asserteq(val, buffer[i]); 315 ut_asserteq(val, pattern[i]); 316 } 317 318 ut_asserteq(-ERANGE, regmap_write(priv->cfg_regmap, REGMAP_TEST_BUF_SZ, 319 val)); 320 ut_asserteq(-ERANGE, regmap_read(priv->cfg_regmap, REGMAP_TEST_BUF_SZ, 321 &val)); 322 ut_asserteq(-ERANGE, regmap_write(priv->cfg_regmap, -1, val)); 323 ut_asserteq(-ERANGE, regmap_read(priv->cfg_regmap, -1, &val)); 324 325 return 0; 326} 327DM_TEST(dm_test_devm_regmap, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); 328 329static int test_one_field(struct unit_test_state *uts, 330 struct regmap *regmap, 331 struct regmap_field *field, 332 struct reg_field field_cfg) 333{ 334 int j; 335 unsigned int val; 336 int mask = (1 << (field_cfg.msb - field_cfg.lsb + 1)) - 1; 337 int shift = field_cfg.lsb; 338 339 ut_assertok(regmap_write(regmap, field_cfg.reg, 0)); 340 ut_assertok(regmap_read(regmap, field_cfg.reg, &val)); 341 ut_asserteq(0, val); 342 343 for (j = 0; j <= mask; j++) { 344 ut_assertok(regmap_field_write(field, j)); 345 ut_assertok(regmap_field_read(field, &val)); 346 ut_asserteq(j, val); 347 ut_assertok(regmap_read(regmap, field_cfg.reg, &val)); 348 ut_asserteq(j << shift, val); 349 } 350 351 ut_assertok(regmap_field_write(field, mask + 1)); 352 ut_assertok(regmap_read(regmap, field_cfg.reg, &val)); 353 ut_asserteq(0, val); 354 355 ut_assertok(regmap_field_write(field, 0xFFFF)); 356 ut_assertok(regmap_read(regmap, field_cfg.reg, &val)); 357 ut_asserteq(mask << shift, val); 358 359 ut_assertok(regmap_write(regmap, field_cfg.reg, 0xFFFF)); 360 ut_assertok(regmap_field_write(field, 0)); 361 ut_assertok(regmap_read(regmap, field_cfg.reg, &val)); 362 ut_asserteq(0xFFFF & ~(mask << shift), val); 363 return 0; 364} 365 366static int dm_test_devm_regmap_field(struct unit_test_state *uts) 367{ 368 int i, rc; 369 struct udevice *dev; 370 struct regmaptest_priv *priv; 371 372 ut_assertok(uclass_get_device_by_name(UCLASS_NOP, "regmap-test_0", 373 &dev)); 374 priv = dev_get_priv(dev); 375 376 sandbox_set_enable_memio(true); 377 for (i = 0 ; i < ARRAY_SIZE(field_cfgs); i++) { 378 rc = test_one_field(uts, priv->fld_regmap, priv->fields[i], 379 field_cfgs[i]); 380 if (rc) 381 break; 382 } 383 384 return 0; 385} 386DM_TEST(dm_test_devm_regmap_field, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); 387