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