Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

vlynq: remove bus driver

There are no users with a vlynq_driver in the Kernel tree. Also, only
the AR7 platform ever initialized a VLYNQ bus, but AR7 is going to be
removed from the Kernel. OpenWRT had some out-of-tree drivers which they
probably intended to upport, but AR7 devices are even there not
supported anymore because they are "stuck with Kernel
3.18" [1]. This code can go.

[1] https://openwrt.org/docs/techref/targets/ar7

Signed-off-by: Wolfram Sang <wsa+renesas@sang-engineering.com>
Acked-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Acked-by: Florian Fainelli <f.fainelli@gmail.com>
Signed-off-by: Thomas Bogendoerfer <tsbogend@alpha.franken.de>

authored by

Wolfram Sang and committed by
Thomas Bogendoerfer
9a6c7821 f1067280

-985
-7
MAINTAINERS
··· 22963 22963 T: git git://linuxtv.org/media_tree.git 22964 22964 F: drivers/media/test-drivers/vivid/* 22965 22965 22966 - VLYNQ BUS 22967 - M: Florian Fainelli <f.fainelli@gmail.com> 22968 - L: openwrt-devel@lists.openwrt.org (subscribers-only) 22969 - S: Maintained 22970 - F: drivers/vlynq/vlynq.c 22971 - F: include/linux/vlynq.h 22972 - 22973 22966 VM SOCKETS (AF_VSOCK) 22974 22967 M: Stefano Garzarella <sgarzare@redhat.com> 22975 22968 L: virtualization@lists.linux-foundation.org
-2
drivers/Kconfig
··· 135 135 136 136 source "drivers/vfio/Kconfig" 137 137 138 - source "drivers/vlynq/Kconfig" 139 - 140 138 source "drivers/virt/Kconfig" 141 139 142 140 source "drivers/virtio/Kconfig"
-1
drivers/Makefile
··· 151 151 obj-$(CONFIG_VHOST_RING) += vhost/ 152 152 obj-$(CONFIG_VHOST_IOTLB) += vhost/ 153 153 obj-$(CONFIG_VHOST) += vhost/ 154 - obj-$(CONFIG_VLYNQ) += vlynq/ 155 154 obj-$(CONFIG_GREYBUS) += greybus/ 156 155 obj-$(CONFIG_COMEDI) += comedi/ 157 156 obj-$(CONFIG_STAGING) += staging/
-21
drivers/vlynq/Kconfig
··· 1 - # SPDX-License-Identifier: GPL-2.0-only 2 - menu "TI VLYNQ" 3 - depends on AR7 4 - 5 - config VLYNQ 6 - bool "TI VLYNQ bus support" 7 - help 8 - Support for Texas Instruments(R) VLYNQ bus. 9 - The VLYNQ bus is a high-speed, serial and packetized 10 - data bus which allows external peripherals of a SoC 11 - to appear into the system's main memory. 12 - 13 - If unsure, say N 14 - 15 - config VLYNQ_DEBUG 16 - bool "VLYNQ bus debug" 17 - depends on VLYNQ && DEBUG_KERNEL 18 - help 19 - Turn on VLYNQ bus debugging. 20 - 21 - endmenu
-6
drivers/vlynq/Makefile
··· 1 - # SPDX-License-Identifier: GPL-2.0-only 2 - # 3 - # Makefile for kernel vlynq drivers 4 - # 5 - 6 - obj-$(CONFIG_VLYNQ) += vlynq.o
-799
drivers/vlynq/vlynq.c
··· 1 - // SPDX-License-Identifier: GPL-2.0-or-later 2 - /* 3 - * Copyright (C) 2006, 2007 Eugene Konev <ejka@openwrt.org> 4 - * 5 - * Parts of the VLYNQ specification can be found here: 6 - * http://www.ti.com/litv/pdf/sprue36a 7 - */ 8 - 9 - #include <linux/init.h> 10 - #include <linux/types.h> 11 - #include <linux/kernel.h> 12 - #include <linux/string.h> 13 - #include <linux/device.h> 14 - #include <linux/module.h> 15 - #include <linux/errno.h> 16 - #include <linux/platform_device.h> 17 - #include <linux/interrupt.h> 18 - #include <linux/delay.h> 19 - #include <linux/io.h> 20 - #include <linux/slab.h> 21 - #include <linux/irq.h> 22 - 23 - #include <linux/vlynq.h> 24 - 25 - #define VLYNQ_CTRL_PM_ENABLE 0x80000000 26 - #define VLYNQ_CTRL_CLOCK_INT 0x00008000 27 - #define VLYNQ_CTRL_CLOCK_DIV(x) (((x) & 7) << 16) 28 - #define VLYNQ_CTRL_INT_LOCAL 0x00004000 29 - #define VLYNQ_CTRL_INT_ENABLE 0x00002000 30 - #define VLYNQ_CTRL_INT_VECTOR(x) (((x) & 0x1f) << 8) 31 - #define VLYNQ_CTRL_INT2CFG 0x00000080 32 - #define VLYNQ_CTRL_RESET 0x00000001 33 - 34 - #define VLYNQ_CTRL_CLOCK_MASK (0x7 << 16) 35 - 36 - #define VLYNQ_INT_OFFSET 0x00000014 37 - #define VLYNQ_REMOTE_OFFSET 0x00000080 38 - 39 - #define VLYNQ_STATUS_LINK 0x00000001 40 - #define VLYNQ_STATUS_LERROR 0x00000080 41 - #define VLYNQ_STATUS_RERROR 0x00000100 42 - 43 - #define VINT_ENABLE 0x00000100 44 - #define VINT_TYPE_EDGE 0x00000080 45 - #define VINT_LEVEL_LOW 0x00000040 46 - #define VINT_VECTOR(x) ((x) & 0x1f) 47 - #define VINT_OFFSET(irq) (8 * ((irq) % 4)) 48 - 49 - #define VLYNQ_AUTONEGO_V2 0x00010000 50 - 51 - struct vlynq_regs { 52 - u32 revision; 53 - u32 control; 54 - u32 status; 55 - u32 int_prio; 56 - u32 int_status; 57 - u32 int_pending; 58 - u32 int_ptr; 59 - u32 tx_offset; 60 - struct vlynq_mapping rx_mapping[4]; 61 - u32 chip; 62 - u32 autonego; 63 - u32 unused[6]; 64 - u32 int_device[8]; 65 - }; 66 - 67 - #ifdef CONFIG_VLYNQ_DEBUG 68 - static void vlynq_dump_regs(struct vlynq_device *dev) 69 - { 70 - int i; 71 - 72 - printk(KERN_DEBUG "VLYNQ local=%p remote=%p\n", 73 - dev->local, dev->remote); 74 - for (i = 0; i < 32; i++) { 75 - printk(KERN_DEBUG "VLYNQ: local %d: %08x\n", 76 - i + 1, ((u32 *)dev->local)[i]); 77 - printk(KERN_DEBUG "VLYNQ: remote %d: %08x\n", 78 - i + 1, ((u32 *)dev->remote)[i]); 79 - } 80 - } 81 - 82 - static void vlynq_dump_mem(u32 *base, int count) 83 - { 84 - int i; 85 - 86 - for (i = 0; i < (count + 3) / 4; i++) { 87 - if (i % 4 == 0) 88 - printk(KERN_DEBUG "\nMEM[0x%04x]:", i * 4); 89 - printk(KERN_DEBUG " 0x%08x", *(base + i)); 90 - } 91 - printk(KERN_DEBUG "\n"); 92 - } 93 - #endif 94 - 95 - /* Check the VLYNQ link status with a given device */ 96 - static int vlynq_linked(struct vlynq_device *dev) 97 - { 98 - int i; 99 - 100 - for (i = 0; i < 100; i++) 101 - if (readl(&dev->local->status) & VLYNQ_STATUS_LINK) 102 - return 1; 103 - else 104 - cpu_relax(); 105 - 106 - return 0; 107 - } 108 - 109 - static void vlynq_reset(struct vlynq_device *dev) 110 - { 111 - writel(readl(&dev->local->control) | VLYNQ_CTRL_RESET, 112 - &dev->local->control); 113 - 114 - /* Wait for the devices to finish resetting */ 115 - msleep(5); 116 - 117 - /* Remove reset bit */ 118 - writel(readl(&dev->local->control) & ~VLYNQ_CTRL_RESET, 119 - &dev->local->control); 120 - 121 - /* Give some time for the devices to settle */ 122 - msleep(5); 123 - } 124 - 125 - static void vlynq_irq_unmask(struct irq_data *d) 126 - { 127 - struct vlynq_device *dev = irq_data_get_irq_chip_data(d); 128 - int virq; 129 - u32 val; 130 - 131 - BUG_ON(!dev); 132 - virq = d->irq - dev->irq_start; 133 - val = readl(&dev->remote->int_device[virq >> 2]); 134 - val |= (VINT_ENABLE | virq) << VINT_OFFSET(virq); 135 - writel(val, &dev->remote->int_device[virq >> 2]); 136 - } 137 - 138 - static void vlynq_irq_mask(struct irq_data *d) 139 - { 140 - struct vlynq_device *dev = irq_data_get_irq_chip_data(d); 141 - int virq; 142 - u32 val; 143 - 144 - BUG_ON(!dev); 145 - virq = d->irq - dev->irq_start; 146 - val = readl(&dev->remote->int_device[virq >> 2]); 147 - val &= ~(VINT_ENABLE << VINT_OFFSET(virq)); 148 - writel(val, &dev->remote->int_device[virq >> 2]); 149 - } 150 - 151 - static int vlynq_irq_type(struct irq_data *d, unsigned int flow_type) 152 - { 153 - struct vlynq_device *dev = irq_data_get_irq_chip_data(d); 154 - int virq; 155 - u32 val; 156 - 157 - BUG_ON(!dev); 158 - virq = d->irq - dev->irq_start; 159 - val = readl(&dev->remote->int_device[virq >> 2]); 160 - switch (flow_type & IRQ_TYPE_SENSE_MASK) { 161 - case IRQ_TYPE_EDGE_RISING: 162 - case IRQ_TYPE_EDGE_FALLING: 163 - case IRQ_TYPE_EDGE_BOTH: 164 - val |= VINT_TYPE_EDGE << VINT_OFFSET(virq); 165 - val &= ~(VINT_LEVEL_LOW << VINT_OFFSET(virq)); 166 - break; 167 - case IRQ_TYPE_LEVEL_HIGH: 168 - val &= ~(VINT_TYPE_EDGE << VINT_OFFSET(virq)); 169 - val &= ~(VINT_LEVEL_LOW << VINT_OFFSET(virq)); 170 - break; 171 - case IRQ_TYPE_LEVEL_LOW: 172 - val &= ~(VINT_TYPE_EDGE << VINT_OFFSET(virq)); 173 - val |= VINT_LEVEL_LOW << VINT_OFFSET(virq); 174 - break; 175 - default: 176 - return -EINVAL; 177 - } 178 - writel(val, &dev->remote->int_device[virq >> 2]); 179 - return 0; 180 - } 181 - 182 - static void vlynq_local_ack(struct irq_data *d) 183 - { 184 - struct vlynq_device *dev = irq_data_get_irq_chip_data(d); 185 - u32 status = readl(&dev->local->status); 186 - 187 - pr_debug("%s: local status: 0x%08x\n", 188 - dev_name(&dev->dev), status); 189 - writel(status, &dev->local->status); 190 - } 191 - 192 - static void vlynq_remote_ack(struct irq_data *d) 193 - { 194 - struct vlynq_device *dev = irq_data_get_irq_chip_data(d); 195 - u32 status = readl(&dev->remote->status); 196 - 197 - pr_debug("%s: remote status: 0x%08x\n", 198 - dev_name(&dev->dev), status); 199 - writel(status, &dev->remote->status); 200 - } 201 - 202 - static irqreturn_t vlynq_irq(int irq, void *dev_id) 203 - { 204 - struct vlynq_device *dev = dev_id; 205 - u32 status; 206 - int virq = 0; 207 - 208 - status = readl(&dev->local->int_status); 209 - writel(status, &dev->local->int_status); 210 - 211 - if (unlikely(!status)) 212 - spurious_interrupt(); 213 - 214 - while (status) { 215 - if (status & 1) 216 - do_IRQ(dev->irq_start + virq); 217 - status >>= 1; 218 - virq++; 219 - } 220 - 221 - return IRQ_HANDLED; 222 - } 223 - 224 - static struct irq_chip vlynq_irq_chip = { 225 - .name = "vlynq", 226 - .irq_unmask = vlynq_irq_unmask, 227 - .irq_mask = vlynq_irq_mask, 228 - .irq_set_type = vlynq_irq_type, 229 - }; 230 - 231 - static struct irq_chip vlynq_local_chip = { 232 - .name = "vlynq local error", 233 - .irq_unmask = vlynq_irq_unmask, 234 - .irq_mask = vlynq_irq_mask, 235 - .irq_ack = vlynq_local_ack, 236 - }; 237 - 238 - static struct irq_chip vlynq_remote_chip = { 239 - .name = "vlynq local error", 240 - .irq_unmask = vlynq_irq_unmask, 241 - .irq_mask = vlynq_irq_mask, 242 - .irq_ack = vlynq_remote_ack, 243 - }; 244 - 245 - static int vlynq_setup_irq(struct vlynq_device *dev) 246 - { 247 - u32 val; 248 - int i, virq; 249 - 250 - if (dev->local_irq == dev->remote_irq) { 251 - printk(KERN_ERR 252 - "%s: local vlynq irq should be different from remote\n", 253 - dev_name(&dev->dev)); 254 - return -EINVAL; 255 - } 256 - 257 - /* Clear local and remote error bits */ 258 - writel(readl(&dev->local->status), &dev->local->status); 259 - writel(readl(&dev->remote->status), &dev->remote->status); 260 - 261 - /* Now setup interrupts */ 262 - val = VLYNQ_CTRL_INT_VECTOR(dev->local_irq); 263 - val |= VLYNQ_CTRL_INT_ENABLE | VLYNQ_CTRL_INT_LOCAL | 264 - VLYNQ_CTRL_INT2CFG; 265 - val |= readl(&dev->local->control); 266 - writel(VLYNQ_INT_OFFSET, &dev->local->int_ptr); 267 - writel(val, &dev->local->control); 268 - 269 - val = VLYNQ_CTRL_INT_VECTOR(dev->remote_irq); 270 - val |= VLYNQ_CTRL_INT_ENABLE; 271 - val |= readl(&dev->remote->control); 272 - writel(VLYNQ_INT_OFFSET, &dev->remote->int_ptr); 273 - writel(val, &dev->remote->int_ptr); 274 - writel(val, &dev->remote->control); 275 - 276 - for (i = dev->irq_start; i <= dev->irq_end; i++) { 277 - virq = i - dev->irq_start; 278 - if (virq == dev->local_irq) { 279 - irq_set_chip_and_handler(i, &vlynq_local_chip, 280 - handle_level_irq); 281 - irq_set_chip_data(i, dev); 282 - } else if (virq == dev->remote_irq) { 283 - irq_set_chip_and_handler(i, &vlynq_remote_chip, 284 - handle_level_irq); 285 - irq_set_chip_data(i, dev); 286 - } else { 287 - irq_set_chip_and_handler(i, &vlynq_irq_chip, 288 - handle_simple_irq); 289 - irq_set_chip_data(i, dev); 290 - writel(0, &dev->remote->int_device[virq >> 2]); 291 - } 292 - } 293 - 294 - if (request_irq(dev->irq, vlynq_irq, IRQF_SHARED, "vlynq", dev)) { 295 - printk(KERN_ERR "%s: request_irq failed\n", 296 - dev_name(&dev->dev)); 297 - return -EAGAIN; 298 - } 299 - 300 - return 0; 301 - } 302 - 303 - static void vlynq_device_release(struct device *dev) 304 - { 305 - struct vlynq_device *vdev = to_vlynq_device(dev); 306 - kfree(vdev); 307 - } 308 - 309 - static int vlynq_device_match(struct device *dev, 310 - struct device_driver *drv) 311 - { 312 - struct vlynq_device *vdev = to_vlynq_device(dev); 313 - struct vlynq_driver *vdrv = to_vlynq_driver(drv); 314 - struct vlynq_device_id *ids = vdrv->id_table; 315 - 316 - while (ids->id) { 317 - if (ids->id == vdev->dev_id) { 318 - vdev->divisor = ids->divisor; 319 - vlynq_set_drvdata(vdev, ids); 320 - printk(KERN_INFO "Driver found for VLYNQ " 321 - "device: %08x\n", vdev->dev_id); 322 - return 1; 323 - } 324 - printk(KERN_DEBUG "Not using the %08x VLYNQ device's driver" 325 - " for VLYNQ device: %08x\n", ids->id, vdev->dev_id); 326 - ids++; 327 - } 328 - return 0; 329 - } 330 - 331 - static int vlynq_device_probe(struct device *dev) 332 - { 333 - struct vlynq_device *vdev = to_vlynq_device(dev); 334 - struct vlynq_driver *drv = to_vlynq_driver(dev->driver); 335 - struct vlynq_device_id *id = vlynq_get_drvdata(vdev); 336 - int result = -ENODEV; 337 - 338 - if (drv->probe) 339 - result = drv->probe(vdev, id); 340 - if (result) 341 - put_device(dev); 342 - return result; 343 - } 344 - 345 - static void vlynq_device_remove(struct device *dev) 346 - { 347 - struct vlynq_driver *drv = to_vlynq_driver(dev->driver); 348 - 349 - if (drv->remove) 350 - drv->remove(to_vlynq_device(dev)); 351 - } 352 - 353 - int __vlynq_register_driver(struct vlynq_driver *driver, struct module *owner) 354 - { 355 - driver->driver.name = driver->name; 356 - driver->driver.bus = &vlynq_bus_type; 357 - return driver_register(&driver->driver); 358 - } 359 - EXPORT_SYMBOL(__vlynq_register_driver); 360 - 361 - void vlynq_unregister_driver(struct vlynq_driver *driver) 362 - { 363 - driver_unregister(&driver->driver); 364 - } 365 - EXPORT_SYMBOL(vlynq_unregister_driver); 366 - 367 - /* 368 - * A VLYNQ remote device can clock the VLYNQ bus master 369 - * using a dedicated clock line. In that case, both the 370 - * remove device and the bus master should have the same 371 - * serial clock dividers configured. Iterate through the 372 - * 8 possible dividers until we actually link with the 373 - * device. 374 - */ 375 - static int __vlynq_try_remote(struct vlynq_device *dev) 376 - { 377 - int i; 378 - 379 - vlynq_reset(dev); 380 - for (i = dev->dev_id ? vlynq_rdiv2 : vlynq_rdiv8; dev->dev_id ? 381 - i <= vlynq_rdiv8 : i >= vlynq_rdiv2; 382 - dev->dev_id ? i++ : i--) { 383 - 384 - if (!vlynq_linked(dev)) 385 - break; 386 - 387 - writel((readl(&dev->remote->control) & 388 - ~VLYNQ_CTRL_CLOCK_MASK) | 389 - VLYNQ_CTRL_CLOCK_INT | 390 - VLYNQ_CTRL_CLOCK_DIV(i - vlynq_rdiv1), 391 - &dev->remote->control); 392 - writel((readl(&dev->local->control) 393 - & ~(VLYNQ_CTRL_CLOCK_INT | 394 - VLYNQ_CTRL_CLOCK_MASK)) | 395 - VLYNQ_CTRL_CLOCK_DIV(i - vlynq_rdiv1), 396 - &dev->local->control); 397 - 398 - if (vlynq_linked(dev)) { 399 - printk(KERN_DEBUG 400 - "%s: using remote clock divisor %d\n", 401 - dev_name(&dev->dev), i - vlynq_rdiv1 + 1); 402 - dev->divisor = i; 403 - return 0; 404 - } else { 405 - vlynq_reset(dev); 406 - } 407 - } 408 - 409 - return -ENODEV; 410 - } 411 - 412 - /* 413 - * A VLYNQ remote device can be clocked by the VLYNQ bus 414 - * master using a dedicated clock line. In that case, only 415 - * the bus master configures the serial clock divider. 416 - * Iterate through the 8 possible dividers until we 417 - * actually get a link with the device. 418 - */ 419 - static int __vlynq_try_local(struct vlynq_device *dev) 420 - { 421 - int i; 422 - 423 - vlynq_reset(dev); 424 - 425 - for (i = dev->dev_id ? vlynq_ldiv2 : vlynq_ldiv8; dev->dev_id ? 426 - i <= vlynq_ldiv8 : i >= vlynq_ldiv2; 427 - dev->dev_id ? i++ : i--) { 428 - 429 - writel((readl(&dev->local->control) & 430 - ~VLYNQ_CTRL_CLOCK_MASK) | 431 - VLYNQ_CTRL_CLOCK_INT | 432 - VLYNQ_CTRL_CLOCK_DIV(i - vlynq_ldiv1), 433 - &dev->local->control); 434 - 435 - if (vlynq_linked(dev)) { 436 - printk(KERN_DEBUG 437 - "%s: using local clock divisor %d\n", 438 - dev_name(&dev->dev), i - vlynq_ldiv1 + 1); 439 - dev->divisor = i; 440 - return 0; 441 - } else { 442 - vlynq_reset(dev); 443 - } 444 - } 445 - 446 - return -ENODEV; 447 - } 448 - 449 - /* 450 - * When using external clocking method, serial clock 451 - * is supplied by an external oscillator, therefore we 452 - * should mask the local clock bit in the clock control 453 - * register for both the bus master and the remote device. 454 - */ 455 - static int __vlynq_try_external(struct vlynq_device *dev) 456 - { 457 - vlynq_reset(dev); 458 - if (!vlynq_linked(dev)) 459 - return -ENODEV; 460 - 461 - writel((readl(&dev->remote->control) & 462 - ~VLYNQ_CTRL_CLOCK_INT), 463 - &dev->remote->control); 464 - 465 - writel((readl(&dev->local->control) & 466 - ~VLYNQ_CTRL_CLOCK_INT), 467 - &dev->local->control); 468 - 469 - if (vlynq_linked(dev)) { 470 - printk(KERN_DEBUG "%s: using external clock\n", 471 - dev_name(&dev->dev)); 472 - dev->divisor = vlynq_div_external; 473 - return 0; 474 - } 475 - 476 - return -ENODEV; 477 - } 478 - 479 - static int __vlynq_enable_device(struct vlynq_device *dev) 480 - { 481 - int result; 482 - struct plat_vlynq_ops *ops = dev->dev.platform_data; 483 - 484 - result = ops->on(dev); 485 - if (result) 486 - return result; 487 - 488 - switch (dev->divisor) { 489 - case vlynq_div_external: 490 - case vlynq_div_auto: 491 - /* When the device is brought from reset it should have clock 492 - * generation negotiated by hardware. 493 - * Check which device is generating clocks and perform setup 494 - * accordingly */ 495 - if (vlynq_linked(dev) && readl(&dev->remote->control) & 496 - VLYNQ_CTRL_CLOCK_INT) { 497 - if (!__vlynq_try_remote(dev) || 498 - !__vlynq_try_local(dev) || 499 - !__vlynq_try_external(dev)) 500 - return 0; 501 - } else { 502 - if (!__vlynq_try_external(dev) || 503 - !__vlynq_try_local(dev) || 504 - !__vlynq_try_remote(dev)) 505 - return 0; 506 - } 507 - break; 508 - case vlynq_ldiv1: 509 - case vlynq_ldiv2: 510 - case vlynq_ldiv3: 511 - case vlynq_ldiv4: 512 - case vlynq_ldiv5: 513 - case vlynq_ldiv6: 514 - case vlynq_ldiv7: 515 - case vlynq_ldiv8: 516 - writel(VLYNQ_CTRL_CLOCK_INT | 517 - VLYNQ_CTRL_CLOCK_DIV(dev->divisor - 518 - vlynq_ldiv1), &dev->local->control); 519 - writel(0, &dev->remote->control); 520 - if (vlynq_linked(dev)) { 521 - printk(KERN_DEBUG 522 - "%s: using local clock divisor %d\n", 523 - dev_name(&dev->dev), 524 - dev->divisor - vlynq_ldiv1 + 1); 525 - return 0; 526 - } 527 - break; 528 - case vlynq_rdiv1: 529 - case vlynq_rdiv2: 530 - case vlynq_rdiv3: 531 - case vlynq_rdiv4: 532 - case vlynq_rdiv5: 533 - case vlynq_rdiv6: 534 - case vlynq_rdiv7: 535 - case vlynq_rdiv8: 536 - writel(0, &dev->local->control); 537 - writel(VLYNQ_CTRL_CLOCK_INT | 538 - VLYNQ_CTRL_CLOCK_DIV(dev->divisor - 539 - vlynq_rdiv1), &dev->remote->control); 540 - if (vlynq_linked(dev)) { 541 - printk(KERN_DEBUG 542 - "%s: using remote clock divisor %d\n", 543 - dev_name(&dev->dev), 544 - dev->divisor - vlynq_rdiv1 + 1); 545 - return 0; 546 - } 547 - break; 548 - } 549 - 550 - ops->off(dev); 551 - return -ENODEV; 552 - } 553 - 554 - int vlynq_enable_device(struct vlynq_device *dev) 555 - { 556 - struct plat_vlynq_ops *ops = dev->dev.platform_data; 557 - int result = -ENODEV; 558 - 559 - result = __vlynq_enable_device(dev); 560 - if (result) 561 - return result; 562 - 563 - result = vlynq_setup_irq(dev); 564 - if (result) 565 - ops->off(dev); 566 - 567 - dev->enabled = !result; 568 - return result; 569 - } 570 - EXPORT_SYMBOL(vlynq_enable_device); 571 - 572 - 573 - void vlynq_disable_device(struct vlynq_device *dev) 574 - { 575 - struct plat_vlynq_ops *ops = dev->dev.platform_data; 576 - 577 - dev->enabled = 0; 578 - free_irq(dev->irq, dev); 579 - ops->off(dev); 580 - } 581 - EXPORT_SYMBOL(vlynq_disable_device); 582 - 583 - int vlynq_set_local_mapping(struct vlynq_device *dev, u32 tx_offset, 584 - struct vlynq_mapping *mapping) 585 - { 586 - int i; 587 - 588 - if (!dev->enabled) 589 - return -ENXIO; 590 - 591 - writel(tx_offset, &dev->local->tx_offset); 592 - for (i = 0; i < 4; i++) { 593 - writel(mapping[i].offset, &dev->local->rx_mapping[i].offset); 594 - writel(mapping[i].size, &dev->local->rx_mapping[i].size); 595 - } 596 - return 0; 597 - } 598 - EXPORT_SYMBOL(vlynq_set_local_mapping); 599 - 600 - int vlynq_set_remote_mapping(struct vlynq_device *dev, u32 tx_offset, 601 - struct vlynq_mapping *mapping) 602 - { 603 - int i; 604 - 605 - if (!dev->enabled) 606 - return -ENXIO; 607 - 608 - writel(tx_offset, &dev->remote->tx_offset); 609 - for (i = 0; i < 4; i++) { 610 - writel(mapping[i].offset, &dev->remote->rx_mapping[i].offset); 611 - writel(mapping[i].size, &dev->remote->rx_mapping[i].size); 612 - } 613 - return 0; 614 - } 615 - EXPORT_SYMBOL(vlynq_set_remote_mapping); 616 - 617 - int vlynq_set_local_irq(struct vlynq_device *dev, int virq) 618 - { 619 - int irq = dev->irq_start + virq; 620 - if (dev->enabled) 621 - return -EBUSY; 622 - 623 - if ((irq < dev->irq_start) || (irq > dev->irq_end)) 624 - return -EINVAL; 625 - 626 - if (virq == dev->remote_irq) 627 - return -EINVAL; 628 - 629 - dev->local_irq = virq; 630 - 631 - return 0; 632 - } 633 - EXPORT_SYMBOL(vlynq_set_local_irq); 634 - 635 - int vlynq_set_remote_irq(struct vlynq_device *dev, int virq) 636 - { 637 - int irq = dev->irq_start + virq; 638 - if (dev->enabled) 639 - return -EBUSY; 640 - 641 - if ((irq < dev->irq_start) || (irq > dev->irq_end)) 642 - return -EINVAL; 643 - 644 - if (virq == dev->local_irq) 645 - return -EINVAL; 646 - 647 - dev->remote_irq = virq; 648 - 649 - return 0; 650 - } 651 - EXPORT_SYMBOL(vlynq_set_remote_irq); 652 - 653 - static int vlynq_probe(struct platform_device *pdev) 654 - { 655 - struct vlynq_device *dev; 656 - struct resource *regs_res, *mem_res, *irq_res; 657 - int len, result; 658 - 659 - regs_res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "regs"); 660 - if (!regs_res) 661 - return -ENODEV; 662 - 663 - mem_res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "mem"); 664 - if (!mem_res) 665 - return -ENODEV; 666 - 667 - irq_res = platform_get_resource_byname(pdev, IORESOURCE_IRQ, "devirq"); 668 - if (!irq_res) 669 - return -ENODEV; 670 - 671 - dev = kzalloc(sizeof(*dev), GFP_KERNEL); 672 - if (!dev) { 673 - printk(KERN_ERR 674 - "vlynq: failed to allocate device structure\n"); 675 - return -ENOMEM; 676 - } 677 - 678 - dev->id = pdev->id; 679 - dev->dev.bus = &vlynq_bus_type; 680 - dev->dev.parent = &pdev->dev; 681 - dev_set_name(&dev->dev, "vlynq%d", dev->id); 682 - dev->dev.platform_data = pdev->dev.platform_data; 683 - dev->dev.release = vlynq_device_release; 684 - 685 - dev->regs_start = regs_res->start; 686 - dev->regs_end = regs_res->end; 687 - dev->mem_start = mem_res->start; 688 - dev->mem_end = mem_res->end; 689 - 690 - len = resource_size(regs_res); 691 - if (!request_mem_region(regs_res->start, len, dev_name(&dev->dev))) { 692 - printk(KERN_ERR "%s: Can't request vlynq registers\n", 693 - dev_name(&dev->dev)); 694 - result = -ENXIO; 695 - goto fail_request; 696 - } 697 - 698 - dev->local = ioremap(regs_res->start, len); 699 - if (!dev->local) { 700 - printk(KERN_ERR "%s: Can't remap vlynq registers\n", 701 - dev_name(&dev->dev)); 702 - result = -ENXIO; 703 - goto fail_remap; 704 - } 705 - 706 - dev->remote = (struct vlynq_regs *)((void *)dev->local + 707 - VLYNQ_REMOTE_OFFSET); 708 - 709 - dev->irq = platform_get_irq_byname(pdev, "irq"); 710 - dev->irq_start = irq_res->start; 711 - dev->irq_end = irq_res->end; 712 - dev->local_irq = dev->irq_end - dev->irq_start; 713 - dev->remote_irq = dev->local_irq - 1; 714 - 715 - if (device_register(&dev->dev)) 716 - goto fail_register; 717 - platform_set_drvdata(pdev, dev); 718 - 719 - printk(KERN_INFO "%s: regs 0x%p, irq %d, mem 0x%p\n", 720 - dev_name(&dev->dev), (void *)dev->regs_start, dev->irq, 721 - (void *)dev->mem_start); 722 - 723 - dev->dev_id = 0; 724 - dev->divisor = vlynq_div_auto; 725 - result = __vlynq_enable_device(dev); 726 - if (result == 0) { 727 - dev->dev_id = readl(&dev->remote->chip); 728 - ((struct plat_vlynq_ops *)(dev->dev.platform_data))->off(dev); 729 - } 730 - if (dev->dev_id) 731 - printk(KERN_INFO "Found a VLYNQ device: %08x\n", dev->dev_id); 732 - 733 - return 0; 734 - 735 - fail_register: 736 - iounmap(dev->local); 737 - fail_remap: 738 - fail_request: 739 - release_mem_region(regs_res->start, len); 740 - kfree(dev); 741 - return result; 742 - } 743 - 744 - static int vlynq_remove(struct platform_device *pdev) 745 - { 746 - struct vlynq_device *dev = platform_get_drvdata(pdev); 747 - 748 - device_unregister(&dev->dev); 749 - iounmap(dev->local); 750 - release_mem_region(dev->regs_start, 751 - dev->regs_end - dev->regs_start + 1); 752 - 753 - kfree(dev); 754 - 755 - return 0; 756 - } 757 - 758 - static struct platform_driver vlynq_platform_driver = { 759 - .driver.name = "vlynq", 760 - .probe = vlynq_probe, 761 - .remove = vlynq_remove, 762 - }; 763 - 764 - struct bus_type vlynq_bus_type = { 765 - .name = "vlynq", 766 - .match = vlynq_device_match, 767 - .probe = vlynq_device_probe, 768 - .remove = vlynq_device_remove, 769 - }; 770 - EXPORT_SYMBOL(vlynq_bus_type); 771 - 772 - static int vlynq_init(void) 773 - { 774 - int res = 0; 775 - 776 - res = bus_register(&vlynq_bus_type); 777 - if (res) 778 - goto fail_bus; 779 - 780 - res = platform_driver_register(&vlynq_platform_driver); 781 - if (res) 782 - goto fail_platform; 783 - 784 - return 0; 785 - 786 - fail_platform: 787 - bus_unregister(&vlynq_bus_type); 788 - fail_bus: 789 - return res; 790 - } 791 - 792 - static void vlynq_exit(void) 793 - { 794 - platform_driver_unregister(&vlynq_platform_driver); 795 - bus_unregister(&vlynq_bus_type); 796 - } 797 - 798 - module_init(vlynq_init); 799 - module_exit(vlynq_exit);
-149
include/linux/vlynq.h
··· 1 - /* SPDX-License-Identifier: GPL-2.0-or-later */ 2 - /* 3 - * Copyright (C) 2006, 2007 Eugene Konev <ejka@openwrt.org> 4 - */ 5 - 6 - #ifndef __VLYNQ_H__ 7 - #define __VLYNQ_H__ 8 - 9 - #include <linux/device.h> 10 - #include <linux/types.h> 11 - 12 - struct module; 13 - 14 - #define VLYNQ_NUM_IRQS 32 15 - 16 - struct vlynq_mapping { 17 - u32 size; 18 - u32 offset; 19 - }; 20 - 21 - enum vlynq_divisor { 22 - vlynq_div_auto = 0, 23 - vlynq_ldiv1, 24 - vlynq_ldiv2, 25 - vlynq_ldiv3, 26 - vlynq_ldiv4, 27 - vlynq_ldiv5, 28 - vlynq_ldiv6, 29 - vlynq_ldiv7, 30 - vlynq_ldiv8, 31 - vlynq_rdiv1, 32 - vlynq_rdiv2, 33 - vlynq_rdiv3, 34 - vlynq_rdiv4, 35 - vlynq_rdiv5, 36 - vlynq_rdiv6, 37 - vlynq_rdiv7, 38 - vlynq_rdiv8, 39 - vlynq_div_external 40 - }; 41 - 42 - struct vlynq_device_id { 43 - u32 id; 44 - enum vlynq_divisor divisor; 45 - unsigned long driver_data; 46 - }; 47 - 48 - struct vlynq_regs; 49 - struct vlynq_device { 50 - u32 id, dev_id; 51 - int local_irq; 52 - int remote_irq; 53 - enum vlynq_divisor divisor; 54 - u32 regs_start, regs_end; 55 - u32 mem_start, mem_end; 56 - u32 irq_start, irq_end; 57 - int irq; 58 - int enabled; 59 - struct vlynq_regs *local; 60 - struct vlynq_regs *remote; 61 - struct device dev; 62 - }; 63 - 64 - struct vlynq_driver { 65 - char *name; 66 - struct vlynq_device_id *id_table; 67 - int (*probe)(struct vlynq_device *dev, struct vlynq_device_id *id); 68 - void (*remove)(struct vlynq_device *dev); 69 - struct device_driver driver; 70 - }; 71 - 72 - struct plat_vlynq_ops { 73 - int (*on)(struct vlynq_device *dev); 74 - void (*off)(struct vlynq_device *dev); 75 - }; 76 - 77 - static inline struct vlynq_driver *to_vlynq_driver(struct device_driver *drv) 78 - { 79 - return container_of(drv, struct vlynq_driver, driver); 80 - } 81 - 82 - static inline struct vlynq_device *to_vlynq_device(struct device *device) 83 - { 84 - return container_of(device, struct vlynq_device, dev); 85 - } 86 - 87 - extern struct bus_type vlynq_bus_type; 88 - 89 - extern int __vlynq_register_driver(struct vlynq_driver *driver, 90 - struct module *owner); 91 - 92 - static inline int vlynq_register_driver(struct vlynq_driver *driver) 93 - { 94 - return __vlynq_register_driver(driver, THIS_MODULE); 95 - } 96 - 97 - static inline void *vlynq_get_drvdata(struct vlynq_device *dev) 98 - { 99 - return dev_get_drvdata(&dev->dev); 100 - } 101 - 102 - static inline void vlynq_set_drvdata(struct vlynq_device *dev, void *data) 103 - { 104 - dev_set_drvdata(&dev->dev, data); 105 - } 106 - 107 - static inline u32 vlynq_mem_start(struct vlynq_device *dev) 108 - { 109 - return dev->mem_start; 110 - } 111 - 112 - static inline u32 vlynq_mem_end(struct vlynq_device *dev) 113 - { 114 - return dev->mem_end; 115 - } 116 - 117 - static inline u32 vlynq_mem_len(struct vlynq_device *dev) 118 - { 119 - return dev->mem_end - dev->mem_start + 1; 120 - } 121 - 122 - static inline int vlynq_virq_to_irq(struct vlynq_device *dev, int virq) 123 - { 124 - int irq = dev->irq_start + virq; 125 - if ((irq < dev->irq_start) || (irq > dev->irq_end)) 126 - return -EINVAL; 127 - 128 - return irq; 129 - } 130 - 131 - static inline int vlynq_irq_to_virq(struct vlynq_device *dev, int irq) 132 - { 133 - if ((irq < dev->irq_start) || (irq > dev->irq_end)) 134 - return -EINVAL; 135 - 136 - return irq - dev->irq_start; 137 - } 138 - 139 - extern void vlynq_unregister_driver(struct vlynq_driver *driver); 140 - extern int vlynq_enable_device(struct vlynq_device *dev); 141 - extern void vlynq_disable_device(struct vlynq_device *dev); 142 - extern int vlynq_set_local_mapping(struct vlynq_device *dev, u32 tx_offset, 143 - struct vlynq_mapping *mapping); 144 - extern int vlynq_set_remote_mapping(struct vlynq_device *dev, u32 tx_offset, 145 - struct vlynq_mapping *mapping); 146 - extern int vlynq_set_local_irq(struct vlynq_device *dev, int virq); 147 - extern int vlynq_set_remote_irq(struct vlynq_device *dev, int virq); 148 - 149 - #endif /* __VLYNQ_H__ */