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 125 static ssize_t xgbe_common_read(char __user *buffer, size_t count, 126 loff_t *ppos, unsigned int value) 127 { 128 char *buf; 129 ssize_t len; 130 131 if (*ppos != 0) 132 return 0; 133 134 buf = kasprintf(GFP_KERNEL, "0x%08x\n", value); 135 if (!buf) 136 return -ENOMEM; 137 138 if (count < strlen(buf)) { 139 kfree(buf); 140 return -ENOSPC; 141 } 142 143 len = simple_read_from_buffer(buffer, count, ppos, buf, strlen(buf)); 144 kfree(buf); 145 146 return len; 147 } 148 149 static ssize_t xgbe_common_write(const char __user *buffer, size_t count, 150 loff_t *ppos, unsigned int *value) 151 { 152 char workarea[32]; 153 ssize_t len; 154 int ret; 155 156 if (*ppos != 0) 157 return 0; 158 159 if (count >= sizeof(workarea)) 160 return -ENOSPC; 161 162 len = simple_write_to_buffer(workarea, sizeof(workarea) - 1, ppos, 163 buffer, count); 164 if (len < 0) 165 return len; 166 167 workarea[len] = '\0'; 168 ret = kstrtouint(workarea, 16, value); 169 if (ret) 170 return -EIO; 171 172 return len; 173 } 174 175 static ssize_t xgmac_reg_addr_read(struct file *filp, char __user *buffer, 176 size_t count, loff_t *ppos) 177 { 178 struct xgbe_prv_data *pdata = filp->private_data; 179 180 return xgbe_common_read(buffer, count, ppos, pdata->debugfs_xgmac_reg); 181 } 182 183 static ssize_t xgmac_reg_addr_write(struct file *filp, 184 const char __user *buffer, 185 size_t count, loff_t *ppos) 186 { 187 struct xgbe_prv_data *pdata = filp->private_data; 188 189 return xgbe_common_write(buffer, count, ppos, 190 &pdata->debugfs_xgmac_reg); 191 } 192 193 static ssize_t xgmac_reg_value_read(struct file *filp, char __user *buffer, 194 size_t count, loff_t *ppos) 195 { 196 struct xgbe_prv_data *pdata = filp->private_data; 197 unsigned int value; 198 199 value = XGMAC_IOREAD(pdata, pdata->debugfs_xgmac_reg); 200 201 return xgbe_common_read(buffer, count, ppos, value); 202 } 203 204 static ssize_t xgmac_reg_value_write(struct file *filp, 205 const char __user *buffer, 206 size_t count, loff_t *ppos) 207 { 208 struct xgbe_prv_data *pdata = filp->private_data; 209 unsigned int value; 210 ssize_t len; 211 212 len = xgbe_common_write(buffer, count, ppos, &value); 213 if (len < 0) 214 return len; 215 216 XGMAC_IOWRITE(pdata, pdata->debugfs_xgmac_reg, value); 217 218 return len; 219 } 220 221 static const struct file_operations xgmac_reg_addr_fops = { 222 .owner = THIS_MODULE, 223 .open = simple_open, 224 .read = xgmac_reg_addr_read, 225 .write = xgmac_reg_addr_write, 226 }; 227 228 static const struct file_operations xgmac_reg_value_fops = { 229 .owner = THIS_MODULE, 230 .open = simple_open, 231 .read = xgmac_reg_value_read, 232 .write = xgmac_reg_value_write, 233 }; 234 235 static ssize_t xpcs_mmd_read(struct file *filp, char __user *buffer, 236 size_t count, loff_t *ppos) 237 { 238 struct xgbe_prv_data *pdata = filp->private_data; 239 240 return xgbe_common_read(buffer, count, ppos, pdata->debugfs_xpcs_mmd); 241 } 242 243 static ssize_t xpcs_mmd_write(struct file *filp, const char __user *buffer, 244 size_t count, loff_t *ppos) 245 { 246 struct xgbe_prv_data *pdata = filp->private_data; 247 248 return xgbe_common_write(buffer, count, ppos, 249 &pdata->debugfs_xpcs_mmd); 250 } 251 252 static ssize_t xpcs_reg_addr_read(struct file *filp, char __user *buffer, 253 size_t count, loff_t *ppos) 254 { 255 struct xgbe_prv_data *pdata = filp->private_data; 256 257 return xgbe_common_read(buffer, count, ppos, pdata->debugfs_xpcs_reg); 258 } 259 260 static ssize_t xpcs_reg_addr_write(struct file *filp, const char __user *buffer, 261 size_t count, loff_t *ppos) 262 { 263 struct xgbe_prv_data *pdata = filp->private_data; 264 265 return xgbe_common_write(buffer, count, ppos, 266 &pdata->debugfs_xpcs_reg); 267 } 268 269 static ssize_t xpcs_reg_value_read(struct file *filp, char __user *buffer, 270 size_t count, loff_t *ppos) 271 { 272 struct xgbe_prv_data *pdata = filp->private_data; 273 unsigned int value; 274 275 value = pdata->hw_if.read_mmd_regs(pdata, pdata->debugfs_xpcs_mmd, 276 pdata->debugfs_xpcs_reg); 277 278 return xgbe_common_read(buffer, count, ppos, value); 279 } 280 281 static ssize_t xpcs_reg_value_write(struct file *filp, 282 const char __user *buffer, 283 size_t count, loff_t *ppos) 284 { 285 struct xgbe_prv_data *pdata = filp->private_data; 286 unsigned int value; 287 ssize_t len; 288 289 len = xgbe_common_write(buffer, count, ppos, &value); 290 if (len < 0) 291 return len; 292 293 pdata->hw_if.write_mmd_regs(pdata, pdata->debugfs_xpcs_mmd, 294 pdata->debugfs_xpcs_reg, value); 295 296 return len; 297 } 298 299 static const struct file_operations xpcs_mmd_fops = { 300 .owner = THIS_MODULE, 301 .open = simple_open, 302 .read = xpcs_mmd_read, 303 .write = xpcs_mmd_write, 304 }; 305 306 static const struct file_operations xpcs_reg_addr_fops = { 307 .owner = THIS_MODULE, 308 .open = simple_open, 309 .read = xpcs_reg_addr_read, 310 .write = xpcs_reg_addr_write, 311 }; 312 313 static const struct file_operations xpcs_reg_value_fops = { 314 .owner = THIS_MODULE, 315 .open = simple_open, 316 .read = xpcs_reg_value_read, 317 .write = xpcs_reg_value_write, 318 }; 319 320 void xgbe_debugfs_init(struct xgbe_prv_data *pdata) 321 { 322 struct dentry *pfile; 323 char *buf; 324 325 /* Set defaults */ 326 pdata->debugfs_xgmac_reg = 0; 327 pdata->debugfs_xpcs_mmd = 1; 328 pdata->debugfs_xpcs_reg = 0; 329 330 buf = kasprintf(GFP_KERNEL, "amd-xgbe-%s", pdata->netdev->name); 331 pdata->xgbe_debugfs = debugfs_create_dir(buf, NULL); 332 if (pdata->xgbe_debugfs == NULL) { 333 netdev_err(pdata->netdev, "debugfs_create_dir failed\n"); 334 return; 335 } 336 337 pfile = debugfs_create_file("xgmac_register", 0600, 338 pdata->xgbe_debugfs, pdata, 339 &xgmac_reg_addr_fops); 340 if (!pfile) 341 netdev_err(pdata->netdev, "debugfs_create_file failed\n"); 342 343 pfile = debugfs_create_file("xgmac_register_value", 0600, 344 pdata->xgbe_debugfs, pdata, 345 &xgmac_reg_value_fops); 346 if (!pfile) 347 netdev_err(pdata->netdev, "debugfs_create_file failed\n"); 348 349 pfile = debugfs_create_file("xpcs_mmd", 0600, 350 pdata->xgbe_debugfs, pdata, 351 &xpcs_mmd_fops); 352 if (!pfile) 353 netdev_err(pdata->netdev, "debugfs_create_file failed\n"); 354 355 pfile = debugfs_create_file("xpcs_register", 0600, 356 pdata->xgbe_debugfs, pdata, 357 &xpcs_reg_addr_fops); 358 if (!pfile) 359 netdev_err(pdata->netdev, "debugfs_create_file failed\n"); 360 361 pfile = debugfs_create_file("xpcs_register_value", 0600, 362 pdata->xgbe_debugfs, pdata, 363 &xpcs_reg_value_fops); 364 if (!pfile) 365 netdev_err(pdata->netdev, "debugfs_create_file failed\n"); 366 367 kfree(buf); 368 } 369 370 void xgbe_debugfs_exit(struct xgbe_prv_data *pdata) 371 { 372 debugfs_remove_recursive(pdata->xgbe_debugfs); 373 pdata->xgbe_debugfs = NULL; 374 } 375