at v6.19 421 lines 9.9 kB view raw
1// SPDX-License-Identifier: GPL-2.0 2/* 3 * Copyright (c) 2020 Synopsys, Inc. and/or its affiliates. 4 * Synopsys DesignWare xData driver 5 * 6 * Author: Gustavo Pimentel <gustavo.pimentel@synopsys.com> 7 */ 8 9#include <linux/miscdevice.h> 10#include <linux/bitfield.h> 11#include <linux/pci-epf.h> 12#include <linux/kernel.h> 13#include <linux/module.h> 14#include <linux/device.h> 15#include <linux/bitops.h> 16#include <linux/mutex.h> 17#include <linux/delay.h> 18#include <linux/pci.h> 19#include <linux/string_choices.h> 20 21#define DW_XDATA_DRIVER_NAME "dw-xdata-pcie" 22 23#define DW_XDATA_EP_MEM_OFFSET 0x8000000 24 25static DEFINE_IDA(xdata_ida); 26 27#define STATUS_DONE BIT(0) 28 29#define CONTROL_DOORBELL BIT(0) 30#define CONTROL_IS_WRITE BIT(1) 31#define CONTROL_LENGTH(a) FIELD_PREP(GENMASK(13, 2), a) 32#define CONTROL_PATTERN_INC BIT(16) 33#define CONTROL_NO_ADDR_INC BIT(18) 34 35#define XPERF_CONTROL_ENABLE BIT(5) 36 37#define BURST_REPEAT BIT(31) 38#define BURST_VALUE 0x1001 39 40#define PATTERN_VALUE 0x0 41 42struct dw_xdata_regs { 43 u32 addr_lsb; /* 0x000 */ 44 u32 addr_msb; /* 0x004 */ 45 u32 burst_cnt; /* 0x008 */ 46 u32 control; /* 0x00c */ 47 u32 pattern; /* 0x010 */ 48 u32 status; /* 0x014 */ 49 u32 RAM_addr; /* 0x018 */ 50 u32 RAM_port; /* 0x01c */ 51 u32 _reserved0[14]; /* 0x020..0x054 */ 52 u32 perf_control; /* 0x058 */ 53 u32 _reserved1[41]; /* 0x05c..0x0fc */ 54 u32 wr_cnt_lsb; /* 0x100 */ 55 u32 wr_cnt_msb; /* 0x104 */ 56 u32 rd_cnt_lsb; /* 0x108 */ 57 u32 rd_cnt_msb; /* 0x10c */ 58} __packed; 59 60struct dw_xdata_region { 61 phys_addr_t paddr; /* physical address */ 62 void __iomem *vaddr; /* virtual address */ 63}; 64 65struct dw_xdata { 66 struct dw_xdata_region rg_region; /* registers */ 67 size_t max_wr_len; /* max wr xfer len */ 68 size_t max_rd_len; /* max rd xfer len */ 69 struct mutex mutex; 70 struct pci_dev *pdev; 71 struct miscdevice misc_dev; 72}; 73 74static inline struct dw_xdata_regs __iomem *__dw_regs(struct dw_xdata *dw) 75{ 76 return dw->rg_region.vaddr; 77} 78 79static void dw_xdata_stop(struct dw_xdata *dw) 80{ 81 u32 burst; 82 83 mutex_lock(&dw->mutex); 84 85 burst = readl(&(__dw_regs(dw)->burst_cnt)); 86 87 if (burst & BURST_REPEAT) { 88 burst &= ~(u32)BURST_REPEAT; 89 writel(burst, &(__dw_regs(dw)->burst_cnt)); 90 } 91 92 mutex_unlock(&dw->mutex); 93} 94 95static void dw_xdata_start(struct dw_xdata *dw, bool write) 96{ 97 struct device *dev = &dw->pdev->dev; 98 u32 control, status; 99 100 /* Stop first if xfer in progress */ 101 dw_xdata_stop(dw); 102 103 mutex_lock(&dw->mutex); 104 105 /* Clear status register */ 106 writel(0x0, &(__dw_regs(dw)->status)); 107 108 /* Burst count register set for continuous until stopped */ 109 writel(BURST_REPEAT | BURST_VALUE, &(__dw_regs(dw)->burst_cnt)); 110 111 /* Pattern register */ 112 writel(PATTERN_VALUE, &(__dw_regs(dw)->pattern)); 113 114 /* Control register */ 115 control = CONTROL_DOORBELL | CONTROL_PATTERN_INC | CONTROL_NO_ADDR_INC; 116 if (write) { 117 control |= CONTROL_IS_WRITE; 118 control |= CONTROL_LENGTH(dw->max_wr_len); 119 } else { 120 control |= CONTROL_LENGTH(dw->max_rd_len); 121 } 122 writel(control, &(__dw_regs(dw)->control)); 123 124 /* 125 * The xData HW block needs about 100 ms to initiate the traffic 126 * generation according this HW block datasheet. 127 */ 128 usleep_range(100, 150); 129 130 status = readl(&(__dw_regs(dw)->status)); 131 132 mutex_unlock(&dw->mutex); 133 134 if (!(status & STATUS_DONE)) 135 dev_dbg(dev, "xData: started %s direction\n", 136 str_write_read(write)); 137} 138 139static void dw_xdata_perf_meas(struct dw_xdata *dw, u64 *data, bool write) 140{ 141 if (write) { 142 *data = readl(&(__dw_regs(dw)->wr_cnt_msb)); 143 *data <<= 32; 144 *data |= readl(&(__dw_regs(dw)->wr_cnt_lsb)); 145 } else { 146 *data = readl(&(__dw_regs(dw)->rd_cnt_msb)); 147 *data <<= 32; 148 *data |= readl(&(__dw_regs(dw)->rd_cnt_lsb)); 149 } 150} 151 152static u64 dw_xdata_perf_diff(u64 *m1, u64 *m2, u64 time) 153{ 154 u64 rate = (*m1 - *m2); 155 156 rate *= (1000 * 1000 * 1000); 157 rate >>= 20; 158 rate = DIV_ROUND_CLOSEST_ULL(rate, time); 159 160 return rate; 161} 162 163static void dw_xdata_perf(struct dw_xdata *dw, u64 *rate, bool write) 164{ 165 struct device *dev = &dw->pdev->dev; 166 u64 data[2], time[2], diff; 167 168 mutex_lock(&dw->mutex); 169 170 /* First acquisition of current count frames */ 171 writel(0x0, &(__dw_regs(dw)->perf_control)); 172 dw_xdata_perf_meas(dw, &data[0], write); 173 time[0] = jiffies; 174 writel((u32)XPERF_CONTROL_ENABLE, &(__dw_regs(dw)->perf_control)); 175 176 /* 177 * Wait 100ms between the 1st count frame acquisition and the 2nd 178 * count frame acquisition, in order to calculate the speed later 179 */ 180 mdelay(100); 181 182 /* Second acquisition of current count frames */ 183 writel(0x0, &(__dw_regs(dw)->perf_control)); 184 dw_xdata_perf_meas(dw, &data[1], write); 185 time[1] = jiffies; 186 writel((u32)XPERF_CONTROL_ENABLE, &(__dw_regs(dw)->perf_control)); 187 188 /* 189 * Speed calculation 190 * 191 * rate = (2nd count frames - 1st count frames) / (time elapsed) 192 */ 193 diff = jiffies_to_nsecs(time[1] - time[0]); 194 *rate = dw_xdata_perf_diff(&data[1], &data[0], diff); 195 196 mutex_unlock(&dw->mutex); 197 198 dev_dbg(dev, "xData: time=%llu us, %s=%llu MB/s\n", 199 diff, str_write_read(write), *rate); 200} 201 202static struct dw_xdata *misc_dev_to_dw(struct miscdevice *misc_dev) 203{ 204 return container_of(misc_dev, struct dw_xdata, misc_dev); 205} 206 207static ssize_t write_show(struct device *dev, struct device_attribute *attr, 208 char *buf) 209{ 210 struct miscdevice *misc_dev = dev_get_drvdata(dev); 211 struct dw_xdata *dw = misc_dev_to_dw(misc_dev); 212 u64 rate; 213 214 dw_xdata_perf(dw, &rate, true); 215 216 return sysfs_emit(buf, "%llu\n", rate); 217} 218 219static ssize_t write_store(struct device *dev, struct device_attribute *attr, 220 const char *buf, size_t size) 221{ 222 struct miscdevice *misc_dev = dev_get_drvdata(dev); 223 struct dw_xdata *dw = misc_dev_to_dw(misc_dev); 224 bool enabled; 225 int ret; 226 227 ret = kstrtobool(buf, &enabled); 228 if (ret < 0) 229 return ret; 230 231 if (enabled) { 232 dev_dbg(dev, "xData: requested write transfer\n"); 233 dw_xdata_start(dw, true); 234 } else { 235 dev_dbg(dev, "xData: requested stop transfer\n"); 236 dw_xdata_stop(dw); 237 } 238 239 return size; 240} 241 242static DEVICE_ATTR_RW(write); 243 244static ssize_t read_show(struct device *dev, struct device_attribute *attr, 245 char *buf) 246{ 247 struct miscdevice *misc_dev = dev_get_drvdata(dev); 248 struct dw_xdata *dw = misc_dev_to_dw(misc_dev); 249 u64 rate; 250 251 dw_xdata_perf(dw, &rate, false); 252 253 return sysfs_emit(buf, "%llu\n", rate); 254} 255 256static ssize_t read_store(struct device *dev, struct device_attribute *attr, 257 const char *buf, size_t size) 258{ 259 struct miscdevice *misc_dev = dev_get_drvdata(dev); 260 struct dw_xdata *dw = misc_dev_to_dw(misc_dev); 261 bool enabled; 262 int ret; 263 264 ret = kstrtobool(buf, &enabled); 265 if (ret < 0) 266 return ret; 267 268 if (enabled) { 269 dev_dbg(dev, "xData: requested read transfer\n"); 270 dw_xdata_start(dw, false); 271 } else { 272 dev_dbg(dev, "xData: requested stop transfer\n"); 273 dw_xdata_stop(dw); 274 } 275 276 return size; 277} 278 279static DEVICE_ATTR_RW(read); 280 281static struct attribute *xdata_attrs[] = { 282 &dev_attr_write.attr, 283 &dev_attr_read.attr, 284 NULL, 285}; 286 287ATTRIBUTE_GROUPS(xdata); 288 289static int dw_xdata_pcie_probe(struct pci_dev *pdev, 290 const struct pci_device_id *pid) 291{ 292 struct device *dev = &pdev->dev; 293 struct dw_xdata *dw; 294 char name[24]; 295 u64 addr; 296 int err; 297 int id; 298 299 /* Enable PCI device */ 300 err = pcim_enable_device(pdev); 301 if (err) { 302 dev_err(dev, "enabling device failed\n"); 303 return err; 304 } 305 306 /* Mapping PCI BAR regions */ 307 err = pcim_iomap_regions(pdev, BIT(BAR_0), pci_name(pdev)); 308 if (err) { 309 dev_err(dev, "xData BAR I/O remapping failed\n"); 310 return err; 311 } 312 313 pci_set_master(pdev); 314 315 /* Allocate memory */ 316 dw = devm_kzalloc(dev, sizeof(*dw), GFP_KERNEL); 317 if (!dw) 318 return -ENOMEM; 319 320 /* Data structure initialization */ 321 mutex_init(&dw->mutex); 322 323 dw->rg_region.vaddr = pcim_iomap_table(pdev)[BAR_0]; 324 if (!dw->rg_region.vaddr) 325 return -ENOMEM; 326 327 dw->rg_region.paddr = pdev->resource[BAR_0].start; 328 329 dw->max_wr_len = pcie_get_mps(pdev); 330 dw->max_wr_len >>= 2; 331 332 dw->max_rd_len = pcie_get_readrq(pdev); 333 dw->max_rd_len >>= 2; 334 335 dw->pdev = pdev; 336 337 id = ida_alloc(&xdata_ida, GFP_KERNEL); 338 if (id < 0) { 339 dev_err(dev, "xData: unable to get id\n"); 340 return id; 341 } 342 343 snprintf(name, sizeof(name), DW_XDATA_DRIVER_NAME ".%d", id); 344 dw->misc_dev.name = kstrdup(name, GFP_KERNEL); 345 if (!dw->misc_dev.name) { 346 err = -ENOMEM; 347 goto err_ida_remove; 348 } 349 350 dw->misc_dev.minor = MISC_DYNAMIC_MINOR; 351 dw->misc_dev.parent = dev; 352 dw->misc_dev.groups = xdata_groups; 353 354 writel(0x0, &(__dw_regs(dw)->RAM_addr)); 355 writel(0x0, &(__dw_regs(dw)->RAM_port)); 356 357 addr = dw->rg_region.paddr + DW_XDATA_EP_MEM_OFFSET; 358 writel(lower_32_bits(addr), &(__dw_regs(dw)->addr_lsb)); 359 writel(upper_32_bits(addr), &(__dw_regs(dw)->addr_msb)); 360 dev_dbg(dev, "xData: target address = 0x%.16llx\n", addr); 361 362 dev_dbg(dev, "xData: wr_len = %zu, rd_len = %zu\n", 363 dw->max_wr_len * 4, dw->max_rd_len * 4); 364 365 /* Saving data structure reference */ 366 pci_set_drvdata(pdev, dw); 367 368 /* Register misc device */ 369 err = misc_register(&dw->misc_dev); 370 if (err) { 371 dev_err(dev, "xData: failed to register device\n"); 372 goto err_kfree_name; 373 } 374 375 return 0; 376 377err_kfree_name: 378 kfree(dw->misc_dev.name); 379 380err_ida_remove: 381 ida_free(&xdata_ida, id); 382 383 return err; 384} 385 386static void dw_xdata_pcie_remove(struct pci_dev *pdev) 387{ 388 struct dw_xdata *dw = pci_get_drvdata(pdev); 389 int id; 390 391 if (sscanf(dw->misc_dev.name, DW_XDATA_DRIVER_NAME ".%d", &id) != 1) 392 return; 393 394 if (id < 0) 395 return; 396 397 dw_xdata_stop(dw); 398 misc_deregister(&dw->misc_dev); 399 kfree(dw->misc_dev.name); 400 ida_free(&xdata_ida, id); 401} 402 403static const struct pci_device_id dw_xdata_pcie_id_table[] = { 404 { PCI_DEVICE_DATA(SYNOPSYS, EDDA, NULL) }, 405 { } 406}; 407MODULE_DEVICE_TABLE(pci, dw_xdata_pcie_id_table); 408 409static struct pci_driver dw_xdata_pcie_driver = { 410 .name = DW_XDATA_DRIVER_NAME, 411 .id_table = dw_xdata_pcie_id_table, 412 .probe = dw_xdata_pcie_probe, 413 .remove = dw_xdata_pcie_remove, 414}; 415 416module_pci_driver(dw_xdata_pcie_driver); 417 418MODULE_LICENSE("GPL v2"); 419MODULE_DESCRIPTION("Synopsys DesignWare xData PCIe driver"); 420MODULE_AUTHOR("Gustavo Pimentel <gustavo.pimentel@synopsys.com>"); 421