1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * Copyright (C) 2020 BAIKAL ELECTRONICS, JSC 4 * 5 * Authors: 6 * Serge Semin <Sergey.Semin@baikalelectronics.ru> 7 * 8 * Baikal-T1 CM2 L2-cache Control Block driver. 9 */ 10 11 #include <linux/kernel.h> 12 #include <linux/module.h> 13 #include <linux/bitfield.h> 14 #include <linux/types.h> 15 #include <linux/device.h> 16 #include <linux/platform_device.h> 17 #include <linux/regmap.h> 18 #include <linux/mfd/syscon.h> 19 #include <linux/sysfs.h> 20 #include <linux/of.h> 21 22 #define L2_CTL_REG 0x028 23 #define L2_CTL_DATA_STALL_FLD 0 24 #define L2_CTL_DATA_STALL_MASK GENMASK(1, L2_CTL_DATA_STALL_FLD) 25 #define L2_CTL_TAG_STALL_FLD 2 26 #define L2_CTL_TAG_STALL_MASK GENMASK(3, L2_CTL_TAG_STALL_FLD) 27 #define L2_CTL_WS_STALL_FLD 4 28 #define L2_CTL_WS_STALL_MASK GENMASK(5, L2_CTL_WS_STALL_FLD) 29 #define L2_CTL_SET_CLKRATIO BIT(13) 30 #define L2_CTL_CLKRATIO_LOCK BIT(31) 31 32 #define L2_CTL_STALL_MIN 0 33 #define L2_CTL_STALL_MAX 3 34 #define L2_CTL_STALL_SET_DELAY_US 1 35 #define L2_CTL_STALL_SET_TOUT_US 1000 36 37 /* 38 * struct l2_ctl - Baikal-T1 L2 Control block private data. 39 * @dev: Pointer to the device structure. 40 * @sys_regs: Baikal-T1 System Controller registers map. 41 */ 42 struct l2_ctl { 43 struct device *dev; 44 45 struct regmap *sys_regs; 46 }; 47 48 /* 49 * enum l2_ctl_stall - Baikal-T1 L2-cache-RAM stall identifier. 50 * @L2_WSSTALL: Way-select latency. 51 * @L2_TAGSTALL: Tag latency. 52 * @L2_DATASTALL: Data latency. 53 */ 54 enum l2_ctl_stall { 55 L2_WS_STALL, 56 L2_TAG_STALL, 57 L2_DATA_STALL 58 }; 59 60 /* 61 * struct l2_ctl_device_attribute - Baikal-T1 L2-cache device attribute. 62 * @dev_attr: Actual sysfs device attribute. 63 * @id: L2-cache stall field identifier. 64 */ 65 struct l2_ctl_device_attribute { 66 struct device_attribute dev_attr; 67 enum l2_ctl_stall id; 68 }; 69 #define to_l2_ctl_dev_attr(_dev_attr) \ 70 container_of(_dev_attr, struct l2_ctl_device_attribute, dev_attr) 71 72 #define L2_CTL_ATTR_RW(_name, _prefix, _id) \ 73 struct l2_ctl_device_attribute l2_ctl_attr_##_name = \ 74 { __ATTR(_name, 0644, _prefix##_show, _prefix##_store), _id } 75 76 static int l2_ctl_get_latency(struct l2_ctl *l2, enum l2_ctl_stall id, u32 *val) 77 { 78 u32 data = 0; 79 int ret; 80 81 ret = regmap_read(l2->sys_regs, L2_CTL_REG, &data); 82 if (ret) 83 return ret; 84 85 switch (id) { 86 case L2_WS_STALL: 87 *val = FIELD_GET(L2_CTL_WS_STALL_MASK, data); 88 break; 89 case L2_TAG_STALL: 90 *val = FIELD_GET(L2_CTL_TAG_STALL_MASK, data); 91 break; 92 case L2_DATA_STALL: 93 *val = FIELD_GET(L2_CTL_DATA_STALL_MASK, data); 94 break; 95 default: 96 return -EINVAL; 97 } 98 99 return 0; 100 } 101 102 static int l2_ctl_set_latency(struct l2_ctl *l2, enum l2_ctl_stall id, u32 val) 103 { 104 u32 mask = 0, data = 0; 105 int ret; 106 107 val = clamp_val(val, L2_CTL_STALL_MIN, L2_CTL_STALL_MAX); 108 109 switch (id) { 110 case L2_WS_STALL: 111 data = FIELD_PREP(L2_CTL_WS_STALL_MASK, val); 112 mask = L2_CTL_WS_STALL_MASK; 113 break; 114 case L2_TAG_STALL: 115 data = FIELD_PREP(L2_CTL_TAG_STALL_MASK, val); 116 mask = L2_CTL_TAG_STALL_MASK; 117 break; 118 case L2_DATA_STALL: 119 data = FIELD_PREP(L2_CTL_DATA_STALL_MASK, val); 120 mask = L2_CTL_DATA_STALL_MASK; 121 break; 122 default: 123 return -EINVAL; 124 } 125 126 data |= L2_CTL_SET_CLKRATIO; 127 mask |= L2_CTL_SET_CLKRATIO; 128 129 ret = regmap_update_bits(l2->sys_regs, L2_CTL_REG, mask, data); 130 if (ret) 131 return ret; 132 133 return regmap_read_poll_timeout(l2->sys_regs, L2_CTL_REG, data, 134 data & L2_CTL_CLKRATIO_LOCK, 135 L2_CTL_STALL_SET_DELAY_US, 136 L2_CTL_STALL_SET_TOUT_US); 137 } 138 139 static void l2_ctl_clear_data(void *data) 140 { 141 struct l2_ctl *l2 = data; 142 struct platform_device *pdev = to_platform_device(l2->dev); 143 144 platform_set_drvdata(pdev, NULL); 145 } 146 147 static struct l2_ctl *l2_ctl_create_data(struct platform_device *pdev) 148 { 149 struct device *dev = &pdev->dev; 150 struct l2_ctl *l2; 151 int ret; 152 153 l2 = devm_kzalloc(dev, sizeof(*l2), GFP_KERNEL); 154 if (!l2) 155 return ERR_PTR(-ENOMEM); 156 157 ret = devm_add_action(dev, l2_ctl_clear_data, l2); 158 if (ret) { 159 dev_err(dev, "Can't add L2 CTL data clear action\n"); 160 return ERR_PTR(ret); 161 } 162 163 l2->dev = dev; 164 platform_set_drvdata(pdev, l2); 165 166 return l2; 167 } 168 169 static int l2_ctl_find_sys_regs(struct l2_ctl *l2) 170 { 171 l2->sys_regs = syscon_node_to_regmap(l2->dev->of_node->parent); 172 if (IS_ERR(l2->sys_regs)) { 173 dev_err(l2->dev, "Couldn't get L2 CTL register map\n"); 174 return PTR_ERR(l2->sys_regs); 175 } 176 177 return 0; 178 } 179 180 static int l2_ctl_of_parse_property(struct l2_ctl *l2, enum l2_ctl_stall id, 181 const char *propname) 182 { 183 int ret = 0; 184 u32 data; 185 186 if (!of_property_read_u32(l2->dev->of_node, propname, &data)) { 187 ret = l2_ctl_set_latency(l2, id, data); 188 if (ret) 189 dev_err(l2->dev, "Invalid value of '%s'\n", propname); 190 } 191 192 return ret; 193 } 194 195 static int l2_ctl_of_parse(struct l2_ctl *l2) 196 { 197 int ret; 198 199 ret = l2_ctl_of_parse_property(l2, L2_WS_STALL, "baikal,l2-ws-latency"); 200 if (ret) 201 return ret; 202 203 ret = l2_ctl_of_parse_property(l2, L2_TAG_STALL, "baikal,l2-tag-latency"); 204 if (ret) 205 return ret; 206 207 return l2_ctl_of_parse_property(l2, L2_DATA_STALL, 208 "baikal,l2-data-latency"); 209 } 210 211 static ssize_t l2_ctl_latency_show(struct device *dev, 212 struct device_attribute *attr, 213 char *buf) 214 { 215 struct l2_ctl_device_attribute *devattr = to_l2_ctl_dev_attr(attr); 216 struct l2_ctl *l2 = dev_get_drvdata(dev); 217 u32 data; 218 int ret; 219 220 ret = l2_ctl_get_latency(l2, devattr->id, &data); 221 if (ret) 222 return ret; 223 224 return scnprintf(buf, PAGE_SIZE, "%u\n", data); 225 } 226 227 static ssize_t l2_ctl_latency_store(struct device *dev, 228 struct device_attribute *attr, 229 const char *buf, size_t count) 230 { 231 struct l2_ctl_device_attribute *devattr = to_l2_ctl_dev_attr(attr); 232 struct l2_ctl *l2 = dev_get_drvdata(dev); 233 u32 data; 234 int ret; 235 236 if (kstrtouint(buf, 0, &data) < 0) 237 return -EINVAL; 238 239 ret = l2_ctl_set_latency(l2, devattr->id, data); 240 if (ret) 241 return ret; 242 243 return count; 244 } 245 static L2_CTL_ATTR_RW(l2_ws_latency, l2_ctl_latency, L2_WS_STALL); 246 static L2_CTL_ATTR_RW(l2_tag_latency, l2_ctl_latency, L2_TAG_STALL); 247 static L2_CTL_ATTR_RW(l2_data_latency, l2_ctl_latency, L2_DATA_STALL); 248 249 static struct attribute *l2_ctl_sysfs_attrs[] = { 250 &l2_ctl_attr_l2_ws_latency.dev_attr.attr, 251 &l2_ctl_attr_l2_tag_latency.dev_attr.attr, 252 &l2_ctl_attr_l2_data_latency.dev_attr.attr, 253 NULL 254 }; 255 ATTRIBUTE_GROUPS(l2_ctl_sysfs); 256 257 static void l2_ctl_remove_sysfs(void *data) 258 { 259 struct l2_ctl *l2 = data; 260 261 device_remove_groups(l2->dev, l2_ctl_sysfs_groups); 262 } 263 264 static int l2_ctl_init_sysfs(struct l2_ctl *l2) 265 { 266 int ret; 267 268 ret = device_add_groups(l2->dev, l2_ctl_sysfs_groups); 269 if (ret) { 270 dev_err(l2->dev, "Failed to create L2 CTL sysfs nodes\n"); 271 return ret; 272 } 273 274 ret = devm_add_action_or_reset(l2->dev, l2_ctl_remove_sysfs, l2); 275 if (ret) 276 dev_err(l2->dev, "Can't add L2 CTL sysfs remove action\n"); 277 278 return ret; 279 } 280 281 static int l2_ctl_probe(struct platform_device *pdev) 282 { 283 struct l2_ctl *l2; 284 int ret; 285 286 l2 = l2_ctl_create_data(pdev); 287 if (IS_ERR(l2)) 288 return PTR_ERR(l2); 289 290 ret = l2_ctl_find_sys_regs(l2); 291 if (ret) 292 return ret; 293 294 ret = l2_ctl_of_parse(l2); 295 if (ret) 296 return ret; 297 298 ret = l2_ctl_init_sysfs(l2); 299 if (ret) 300 return ret; 301 302 return 0; 303 } 304 305 static const struct of_device_id l2_ctl_of_match[] = { 306 { .compatible = "baikal,bt1-l2-ctl" }, 307 { } 308 }; 309 MODULE_DEVICE_TABLE(of, l2_ctl_of_match); 310 311 static struct platform_driver l2_ctl_driver = { 312 .probe = l2_ctl_probe, 313 .driver = { 314 .name = "bt1-l2-ctl", 315 .of_match_table = l2_ctl_of_match 316 } 317 }; 318 module_platform_driver(l2_ctl_driver); 319 320 MODULE_AUTHOR("Serge Semin <Sergey.Semin@baikalelectronics.ru>"); 321 MODULE_DESCRIPTION("Baikal-T1 L2-cache driver"); 322 MODULE_LICENSE("GPL v2"); 323