1 /* 2 * AMD 10Gb Ethernet driver 3 * 4 * This file is available to you under your choice of the following two 5 * licenses: 6 * 7 * License 1: GPLv2 8 * 9 * Copyright (c) 2014 Advanced Micro Devices, Inc. 10 * 11 * This file is free software; you may copy, redistribute and/or modify 12 * it under the terms of the GNU General Public License as published by 13 * the Free Software Foundation, either version 2 of the License, or (at 14 * your option) any later version. 15 * 16 * This file is distributed in the hope that it will be useful, but 17 * WITHOUT ANY WARRANTY; without even the implied warranty of 18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 19 * General Public License for more details. 20 * 21 * You should have received a copy of the GNU General Public License 22 * along with this program. If not, see <http://www.gnu.org/licenses/>. 23 * 24 * This file incorporates work covered by the following copyright and 25 * permission notice: 26 * The Synopsys DWC ETHER XGMAC Software Driver and documentation 27 * (hereinafter "Software") is an unsupported proprietary work of Synopsys, 28 * Inc. unless otherwise expressly agreed to in writing between Synopsys 29 * and you. 30 * 31 * The Software IS NOT an item of Licensed Software or Licensed Product 32 * under any End User Software License Agreement or Agreement for Licensed 33 * Product with Synopsys or any supplement thereto. Permission is hereby 34 * granted, free of charge, to any person obtaining a copy of this software 35 * annotated with this license and the Software, to deal in the Software 36 * without restriction, including without limitation the rights to use, 37 * copy, modify, merge, publish, distribute, sublicense, and/or sell copies 38 * of the Software, and to permit persons to whom the Software is furnished 39 * to do so, subject to the following conditions: 40 * 41 * The above copyright notice and this permission notice shall be included 42 * in all copies or substantial portions of the Software. 43 * 44 * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" 45 * BASIS AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 46 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 47 * PARTICULAR PURPOSE ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS 48 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 49 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 50 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 51 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 52 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 53 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 54 * THE POSSIBILITY OF SUCH DAMAGE. 55 * 56 * 57 * License 2: Modified BSD 58 * 59 * Copyright (c) 2014 Advanced Micro Devices, Inc. 60 * All rights reserved. 61 * 62 * Redistribution and use in source and binary forms, with or without 63 * modification, are permitted provided that the following conditions are met: 64 * * Redistributions of source code must retain the above copyright 65 * notice, this list of conditions and the following disclaimer. 66 * * Redistributions in binary form must reproduce the above copyright 67 * notice, this list of conditions and the following disclaimer in the 68 * documentation and/or other materials provided with the distribution. 69 * * Neither the name of Advanced Micro Devices, Inc. nor the 70 * names of its contributors may be used to endorse or promote products 71 * derived from this software without specific prior written permission. 72 * 73 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 74 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 75 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 76 * ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY 77 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 78 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 79 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 80 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 81 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 82 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 83 * 84 * This file incorporates work covered by the following copyright and 85 * permission notice: 86 * The Synopsys DWC ETHER XGMAC Software Driver and documentation 87 * (hereinafter "Software") is an unsupported proprietary work of Synopsys, 88 * Inc. unless otherwise expressly agreed to in writing between Synopsys 89 * and you. 90 * 91 * The Software IS NOT an item of Licensed Software or Licensed Product 92 * under any End User Software License Agreement or Agreement for Licensed 93 * Product with Synopsys or any supplement thereto. Permission is hereby 94 * granted, free of charge, to any person obtaining a copy of this software 95 * annotated with this license and the Software, to deal in the Software 96 * without restriction, including without limitation the rights to use, 97 * copy, modify, merge, publish, distribute, sublicense, and/or sell copies 98 * of the Software, and to permit persons to whom the Software is furnished 99 * to do so, subject to the following conditions: 100 * 101 * The above copyright notice and this permission notice shall be included 102 * in all copies or substantial portions of the Software. 103 * 104 * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" 105 * BASIS AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 106 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 107 * PARTICULAR PURPOSE ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS 108 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 109 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 110 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 111 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 112 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 113 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 114 * THE POSSIBILITY OF SUCH DAMAGE. 115 */ 116 117 #include <linux/debugfs.h> 118 #include <linux/module.h> 119 #include <linux/slab.h> 120 121 #include "xgbe.h" 122 #include "xgbe-common.h" 123 124 static ssize_t xgbe_common_read(char __user *buffer, size_t count, 125 loff_t *ppos, unsigned int value) 126 { 127 char *buf; 128 ssize_t len; 129 130 if (*ppos != 0) 131 return 0; 132 133 buf = kasprintf(GFP_KERNEL, "0x%08x\n", value); 134 if (!buf) 135 return -ENOMEM; 136 137 if (count < strlen(buf)) { 138 kfree(buf); 139 return -ENOSPC; 140 } 141 142 len = simple_read_from_buffer(buffer, count, ppos, buf, strlen(buf)); 143 kfree(buf); 144 145 return len; 146 } 147 148 static ssize_t xgbe_common_write(const char __user *buffer, size_t count, 149 loff_t *ppos, unsigned int *value) 150 { 151 char workarea[32]; 152 ssize_t len; 153 int ret; 154 155 if (*ppos != 0) 156 return -EINVAL; 157 158 if (count >= sizeof(workarea)) 159 return -ENOSPC; 160 161 len = simple_write_to_buffer(workarea, sizeof(workarea) - 1, ppos, 162 buffer, count); 163 if (len < 0) 164 return len; 165 166 workarea[len] = '\0'; 167 ret = kstrtouint(workarea, 16, value); 168 if (ret) 169 return -EIO; 170 171 return len; 172 } 173 174 static ssize_t xgmac_reg_addr_read(struct file *filp, char __user *buffer, 175 size_t count, loff_t *ppos) 176 { 177 struct xgbe_prv_data *pdata = filp->private_data; 178 179 return xgbe_common_read(buffer, count, ppos, pdata->debugfs_xgmac_reg); 180 } 181 182 static ssize_t xgmac_reg_addr_write(struct file *filp, 183 const char __user *buffer, 184 size_t count, loff_t *ppos) 185 { 186 struct xgbe_prv_data *pdata = filp->private_data; 187 188 return xgbe_common_write(buffer, count, ppos, 189 &pdata->debugfs_xgmac_reg); 190 } 191 192 static ssize_t xgmac_reg_value_read(struct file *filp, char __user *buffer, 193 size_t count, loff_t *ppos) 194 { 195 struct xgbe_prv_data *pdata = filp->private_data; 196 unsigned int value; 197 198 value = XGMAC_IOREAD(pdata, pdata->debugfs_xgmac_reg); 199 200 return xgbe_common_read(buffer, count, ppos, value); 201 } 202 203 static ssize_t xgmac_reg_value_write(struct file *filp, 204 const char __user *buffer, 205 size_t count, loff_t *ppos) 206 { 207 struct xgbe_prv_data *pdata = filp->private_data; 208 unsigned int value; 209 ssize_t len; 210 211 len = xgbe_common_write(buffer, count, ppos, &value); 212 if (len < 0) 213 return len; 214 215 XGMAC_IOWRITE(pdata, pdata->debugfs_xgmac_reg, value); 216 217 return len; 218 } 219 220 static const struct file_operations xgmac_reg_addr_fops = { 221 .owner = THIS_MODULE, 222 .open = simple_open, 223 .read = xgmac_reg_addr_read, 224 .write = xgmac_reg_addr_write, 225 }; 226 227 static const struct file_operations xgmac_reg_value_fops = { 228 .owner = THIS_MODULE, 229 .open = simple_open, 230 .read = xgmac_reg_value_read, 231 .write = xgmac_reg_value_write, 232 }; 233 234 static ssize_t xpcs_mmd_read(struct file *filp, char __user *buffer, 235 size_t count, loff_t *ppos) 236 { 237 struct xgbe_prv_data *pdata = filp->private_data; 238 239 return xgbe_common_read(buffer, count, ppos, pdata->debugfs_xpcs_mmd); 240 } 241 242 static ssize_t xpcs_mmd_write(struct file *filp, const char __user *buffer, 243 size_t count, loff_t *ppos) 244 { 245 struct xgbe_prv_data *pdata = filp->private_data; 246 247 return xgbe_common_write(buffer, count, ppos, 248 &pdata->debugfs_xpcs_mmd); 249 } 250 251 static ssize_t xpcs_reg_addr_read(struct file *filp, char __user *buffer, 252 size_t count, loff_t *ppos) 253 { 254 struct xgbe_prv_data *pdata = filp->private_data; 255 256 return xgbe_common_read(buffer, count, ppos, pdata->debugfs_xpcs_reg); 257 } 258 259 static ssize_t xpcs_reg_addr_write(struct file *filp, const char __user *buffer, 260 size_t count, loff_t *ppos) 261 { 262 struct xgbe_prv_data *pdata = filp->private_data; 263 264 return xgbe_common_write(buffer, count, ppos, 265 &pdata->debugfs_xpcs_reg); 266 } 267 268 static ssize_t xpcs_reg_value_read(struct file *filp, char __user *buffer, 269 size_t count, loff_t *ppos) 270 { 271 struct xgbe_prv_data *pdata = filp->private_data; 272 unsigned int value; 273 274 value = XMDIO_READ(pdata, pdata->debugfs_xpcs_mmd, 275 pdata->debugfs_xpcs_reg); 276 277 return xgbe_common_read(buffer, count, ppos, value); 278 } 279 280 static ssize_t xpcs_reg_value_write(struct file *filp, 281 const char __user *buffer, 282 size_t count, loff_t *ppos) 283 { 284 struct xgbe_prv_data *pdata = filp->private_data; 285 unsigned int value; 286 ssize_t len; 287 288 len = xgbe_common_write(buffer, count, ppos, &value); 289 if (len < 0) 290 return len; 291 292 XMDIO_WRITE(pdata, pdata->debugfs_xpcs_mmd, pdata->debugfs_xpcs_reg, 293 value); 294 295 return len; 296 } 297 298 static const struct file_operations xpcs_mmd_fops = { 299 .owner = THIS_MODULE, 300 .open = simple_open, 301 .read = xpcs_mmd_read, 302 .write = xpcs_mmd_write, 303 }; 304 305 static const struct file_operations xpcs_reg_addr_fops = { 306 .owner = THIS_MODULE, 307 .open = simple_open, 308 .read = xpcs_reg_addr_read, 309 .write = xpcs_reg_addr_write, 310 }; 311 312 static const struct file_operations xpcs_reg_value_fops = { 313 .owner = THIS_MODULE, 314 .open = simple_open, 315 .read = xpcs_reg_value_read, 316 .write = xpcs_reg_value_write, 317 }; 318 319 static ssize_t xprop_reg_addr_read(struct file *filp, char __user *buffer, 320 size_t count, loff_t *ppos) 321 { 322 struct xgbe_prv_data *pdata = filp->private_data; 323 324 return xgbe_common_read(buffer, count, ppos, pdata->debugfs_xprop_reg); 325 } 326 327 static ssize_t xprop_reg_addr_write(struct file *filp, 328 const char __user *buffer, 329 size_t count, loff_t *ppos) 330 { 331 struct xgbe_prv_data *pdata = filp->private_data; 332 333 return xgbe_common_write(buffer, count, ppos, 334 &pdata->debugfs_xprop_reg); 335 } 336 337 static ssize_t xprop_reg_value_read(struct file *filp, char __user *buffer, 338 size_t count, loff_t *ppos) 339 { 340 struct xgbe_prv_data *pdata = filp->private_data; 341 unsigned int value; 342 343 value = XP_IOREAD(pdata, pdata->debugfs_xprop_reg); 344 345 return xgbe_common_read(buffer, count, ppos, value); 346 } 347 348 static ssize_t xprop_reg_value_write(struct file *filp, 349 const char __user *buffer, 350 size_t count, loff_t *ppos) 351 { 352 struct xgbe_prv_data *pdata = filp->private_data; 353 unsigned int value; 354 ssize_t len; 355 356 len = xgbe_common_write(buffer, count, ppos, &value); 357 if (len < 0) 358 return len; 359 360 XP_IOWRITE(pdata, pdata->debugfs_xprop_reg, value); 361 362 return len; 363 } 364 365 static const struct file_operations xprop_reg_addr_fops = { 366 .owner = THIS_MODULE, 367 .open = simple_open, 368 .read = xprop_reg_addr_read, 369 .write = xprop_reg_addr_write, 370 }; 371 372 static const struct file_operations xprop_reg_value_fops = { 373 .owner = THIS_MODULE, 374 .open = simple_open, 375 .read = xprop_reg_value_read, 376 .write = xprop_reg_value_write, 377 }; 378 379 static ssize_t xi2c_reg_addr_read(struct file *filp, char __user *buffer, 380 size_t count, loff_t *ppos) 381 { 382 struct xgbe_prv_data *pdata = filp->private_data; 383 384 return xgbe_common_read(buffer, count, ppos, pdata->debugfs_xi2c_reg); 385 } 386 387 static ssize_t xi2c_reg_addr_write(struct file *filp, 388 const char __user *buffer, 389 size_t count, loff_t *ppos) 390 { 391 struct xgbe_prv_data *pdata = filp->private_data; 392 393 return xgbe_common_write(buffer, count, ppos, 394 &pdata->debugfs_xi2c_reg); 395 } 396 397 static ssize_t xi2c_reg_value_read(struct file *filp, char __user *buffer, 398 size_t count, loff_t *ppos) 399 { 400 struct xgbe_prv_data *pdata = filp->private_data; 401 unsigned int value; 402 403 value = XI2C_IOREAD(pdata, pdata->debugfs_xi2c_reg); 404 405 return xgbe_common_read(buffer, count, ppos, value); 406 } 407 408 static ssize_t xi2c_reg_value_write(struct file *filp, 409 const char __user *buffer, 410 size_t count, loff_t *ppos) 411 { 412 struct xgbe_prv_data *pdata = filp->private_data; 413 unsigned int value; 414 ssize_t len; 415 416 len = xgbe_common_write(buffer, count, ppos, &value); 417 if (len < 0) 418 return len; 419 420 XI2C_IOWRITE(pdata, pdata->debugfs_xi2c_reg, value); 421 422 return len; 423 } 424 425 static const struct file_operations xi2c_reg_addr_fops = { 426 .owner = THIS_MODULE, 427 .open = simple_open, 428 .read = xi2c_reg_addr_read, 429 .write = xi2c_reg_addr_write, 430 }; 431 432 static const struct file_operations xi2c_reg_value_fops = { 433 .owner = THIS_MODULE, 434 .open = simple_open, 435 .read = xi2c_reg_value_read, 436 .write = xi2c_reg_value_write, 437 }; 438 439 void xgbe_debugfs_init(struct xgbe_prv_data *pdata) 440 { 441 struct dentry *pfile; 442 char *buf; 443 444 /* Set defaults */ 445 pdata->debugfs_xgmac_reg = 0; 446 pdata->debugfs_xpcs_mmd = 1; 447 pdata->debugfs_xpcs_reg = 0; 448 449 buf = kasprintf(GFP_KERNEL, "amd-xgbe-%s", pdata->netdev->name); 450 if (!buf) 451 return; 452 453 pdata->xgbe_debugfs = debugfs_create_dir(buf, NULL); 454 if (!pdata->xgbe_debugfs) { 455 netdev_err(pdata->netdev, "debugfs_create_dir failed\n"); 456 kfree(buf); 457 return; 458 } 459 460 pfile = debugfs_create_file("xgmac_register", 0600, 461 pdata->xgbe_debugfs, pdata, 462 &xgmac_reg_addr_fops); 463 if (!pfile) 464 netdev_err(pdata->netdev, "debugfs_create_file failed\n"); 465 466 pfile = debugfs_create_file("xgmac_register_value", 0600, 467 pdata->xgbe_debugfs, pdata, 468 &xgmac_reg_value_fops); 469 if (!pfile) 470 netdev_err(pdata->netdev, "debugfs_create_file failed\n"); 471 472 pfile = debugfs_create_file("xpcs_mmd", 0600, 473 pdata->xgbe_debugfs, pdata, 474 &xpcs_mmd_fops); 475 if (!pfile) 476 netdev_err(pdata->netdev, "debugfs_create_file failed\n"); 477 478 pfile = debugfs_create_file("xpcs_register", 0600, 479 pdata->xgbe_debugfs, pdata, 480 &xpcs_reg_addr_fops); 481 if (!pfile) 482 netdev_err(pdata->netdev, "debugfs_create_file failed\n"); 483 484 pfile = debugfs_create_file("xpcs_register_value", 0600, 485 pdata->xgbe_debugfs, pdata, 486 &xpcs_reg_value_fops); 487 if (!pfile) 488 netdev_err(pdata->netdev, "debugfs_create_file failed\n"); 489 490 if (pdata->xprop_regs) { 491 pfile = debugfs_create_file("xprop_register", 0600, 492 pdata->xgbe_debugfs, pdata, 493 &xprop_reg_addr_fops); 494 if (!pfile) 495 netdev_err(pdata->netdev, 496 "debugfs_create_file failed\n"); 497 498 pfile = debugfs_create_file("xprop_register_value", 0600, 499 pdata->xgbe_debugfs, pdata, 500 &xprop_reg_value_fops); 501 if (!pfile) 502 netdev_err(pdata->netdev, 503 "debugfs_create_file failed\n"); 504 } 505 506 if (pdata->xi2c_regs) { 507 pfile = debugfs_create_file("xi2c_register", 0600, 508 pdata->xgbe_debugfs, pdata, 509 &xi2c_reg_addr_fops); 510 if (!pfile) 511 netdev_err(pdata->netdev, 512 "debugfs_create_file failed\n"); 513 514 pfile = debugfs_create_file("xi2c_register_value", 0600, 515 pdata->xgbe_debugfs, pdata, 516 &xi2c_reg_value_fops); 517 if (!pfile) 518 netdev_err(pdata->netdev, 519 "debugfs_create_file failed\n"); 520 } 521 522 kfree(buf); 523 } 524 525 void xgbe_debugfs_exit(struct xgbe_prv_data *pdata) 526 { 527 debugfs_remove_recursive(pdata->xgbe_debugfs); 528 pdata->xgbe_debugfs = NULL; 529 } 530