1 // SPDX-License-Identifier: GPL-2.0 2 // 3 // Register map access API - Memory region with raw access 4 // 5 // This is intended for testing only 6 // 7 // Copyright (c) 2023, Arm Ltd 8 9 #include <linux/clk.h> 10 #include <linux/err.h> 11 #include <linux/io.h> 12 #include <linux/module.h> 13 #include <linux/regmap.h> 14 #include <linux/slab.h> 15 #include <linux/swab.h> 16 17 #include "internal.h" 18 19 static unsigned int decode_reg(enum regmap_endian endian, const void *reg) 20 { 21 const u16 *r = reg; 22 23 if (endian == REGMAP_ENDIAN_BIG) 24 return be16_to_cpu(*r); 25 else 26 return le16_to_cpu(*r); 27 } 28 29 static int regmap_raw_ram_gather_write(void *context, 30 const void *reg, size_t reg_len, 31 const void *val, size_t val_len) 32 { 33 struct regmap_ram_data *data = context; 34 unsigned int r; 35 u16 *our_buf = (u16 *)data->vals; 36 int i; 37 38 if (reg_len != 2) 39 return -EINVAL; 40 if (val_len % 2) 41 return -EINVAL; 42 43 r = decode_reg(data->reg_endian, reg); 44 memcpy(&our_buf[r], val, val_len); 45 46 for (i = 0; i < val_len / 2; i++) 47 data->written[r + i] = true; 48 49 return 0; 50 } 51 52 static int regmap_raw_ram_write(void *context, const void *data, size_t count) 53 { 54 return regmap_raw_ram_gather_write(context, data, 2, 55 data + 2, count - 2); 56 } 57 58 static int regmap_raw_ram_read(void *context, 59 const void *reg, size_t reg_len, 60 void *val, size_t val_len) 61 { 62 struct regmap_ram_data *data = context; 63 unsigned int r; 64 u16 *our_buf = (u16 *)data->vals; 65 int i; 66 67 if (reg_len != 2) 68 return -EINVAL; 69 if (val_len % 2) 70 return -EINVAL; 71 72 r = decode_reg(data->reg_endian, reg); 73 memcpy(val, &our_buf[r], val_len); 74 75 for (i = 0; i < val_len / 2; i++) 76 data->read[r + i] = true; 77 78 return 0; 79 } 80 81 static void regmap_raw_ram_free_context(void *context) 82 { 83 struct regmap_ram_data *data = context; 84 85 kfree(data->vals); 86 kfree(data->read); 87 kfree(data->written); 88 kfree(data); 89 } 90 91 static const struct regmap_bus regmap_raw_ram = { 92 .fast_io = true, 93 .write = regmap_raw_ram_write, 94 .gather_write = regmap_raw_ram_gather_write, 95 .read = regmap_raw_ram_read, 96 .free_context = regmap_raw_ram_free_context, 97 }; 98 99 struct regmap *__regmap_init_raw_ram(const struct regmap_config *config, 100 struct regmap_ram_data *data, 101 struct lock_class_key *lock_key, 102 const char *lock_name) 103 { 104 struct regmap *map; 105 106 if (config->reg_bits != 16) 107 return ERR_PTR(-EINVAL); 108 109 if (!config->max_register) { 110 pr_crit("No max_register specified for RAM regmap\n"); 111 return ERR_PTR(-EINVAL); 112 } 113 114 data->read = kcalloc(sizeof(bool), config->max_register + 1, 115 GFP_KERNEL); 116 if (!data->read) 117 return ERR_PTR(-ENOMEM); 118 119 data->written = kcalloc(sizeof(bool), config->max_register + 1, 120 GFP_KERNEL); 121 if (!data->written) 122 return ERR_PTR(-ENOMEM); 123 124 data->reg_endian = config->reg_format_endian; 125 126 map = __regmap_init(NULL, ®map_raw_ram, data, config, 127 lock_key, lock_name); 128 129 return map; 130 } 131 EXPORT_SYMBOL_GPL(__regmap_init_raw_ram); 132 133 MODULE_LICENSE("GPL v2"); 134