/* * Release kernel resources if it is the last close, disable the port, * free IRQ and close the port. */ static void tilegx_shutdown(struct uart_port *port) { int err; UART_INTERRUPT_MASK_t intr_mask; struct tile_uart_port *tile_uart; gxio_uart_context_t *context; int cpu; tile_uart = container_of(port, struct tile_uart_port, uart); if (mutex_lock_interruptible(&tile_uart->mutex)) return; context = &tile_uart->context; /* Disable UART Tx/Rx Interrupt. */ intr_mask.word = gxio_uart_read(context, UART_INTERRUPT_MASK); intr_mask.wfifo_re = 1; intr_mask.rfifo_we = 1; gxio_uart_write(context, UART_INTERRUPT_MASK, intr_mask.word); /* Request that the hardware stop sending us interrupts. */ cpu = tile_uart->irq_cpu; err = gxio_uart_cfg_interrupt(context, cpu_x(cpu), cpu_y(cpu), KERNEL_PL, -1); if (port->irq > 0) { free_irq(port->irq, port); irq_free_hwirq(port->irq); port->irq = 0; } gxio_uart_destroy(context); mutex_unlock(&tile_uart->mutex); }
static int hvc_tile_remove(struct platform_device *pdev) { int rc; struct hvc_struct *hp = dev_get_drvdata(&pdev->dev); rc = hvc_remove(hp); if (rc == 0) irq_free_hwirq(hp->data); return rc; }
static int ohci_hcd_tilegx_drv_remove(struct platform_device *pdev) { struct usb_hcd *hcd = platform_get_drvdata(pdev); struct tilegx_usb_platform_data *pdata = dev_get_platdata(&pdev->dev); usb_remove_hcd(hcd); usb_put_hcd(hcd); tilegx_stop_ohc(); gxio_usb_host_destroy(&pdata->usb_ctx); irq_free_hwirq(pdata->irq); return 0; }
static int hvc_tile_probe(struct platform_device *pdev) { struct hvc_struct *hp; int tile_hvc_irq; /* Create our IRQ and register it. */ tile_hvc_irq = irq_alloc_hwirq(-1); if (!tile_hvc_irq) return -ENXIO; tile_irq_activate(tile_hvc_irq, TILE_IRQ_PERCPU); hp = hvc_alloc(0, tile_hvc_irq, &hvc_tile_get_put_ops, 128); if (IS_ERR(hp)) { irq_free_hwirq(tile_hvc_irq); return PTR_ERR(hp); } dev_set_drvdata(&pdev->dev, hp); return 0; }
static int ohci_hcd_tilegx_drv_probe(struct platform_device *pdev) { struct usb_hcd *hcd; struct tilegx_usb_platform_data *pdata = dev_get_platdata(&pdev->dev); pte_t pte = { 0 }; int my_cpu = smp_processor_id(); int ret; if (usb_disabled()) return -ENODEV; /* * Try to initialize our GXIO context; if we can't, the device * doesn't exist. */ if (gxio_usb_host_init(&pdata->usb_ctx, pdata->dev_index, 0) != 0) return -ENXIO; hcd = usb_create_hcd(&ohci_tilegx_hc_driver, &pdev->dev, dev_name(&pdev->dev)); if (!hcd) { ret = -ENOMEM; goto err_hcd; } /* * We don't use rsrc_start to map in our registers, but seems like * we ought to set it to something, so we use the register VA. */ hcd->rsrc_start = (ulong) gxio_usb_host_get_reg_start(&pdata->usb_ctx); hcd->rsrc_len = gxio_usb_host_get_reg_len(&pdata->usb_ctx); hcd->regs = gxio_usb_host_get_reg_start(&pdata->usb_ctx); tilegx_start_ohc(); /* Create our IRQs and register them. */ pdata->irq = irq_alloc_hwirq(-1); if (!pdata->irq) { ret = -ENXIO; goto err_no_irq; } tile_irq_activate(pdata->irq, TILE_IRQ_PERCPU); /* Configure interrupts. */ ret = gxio_usb_host_cfg_interrupt(&pdata->usb_ctx, cpu_x(my_cpu), cpu_y(my_cpu), KERNEL_PL, pdata->irq); if (ret) { ret = -ENXIO; goto err_have_irq; } /* Register all of our memory. */ pte = pte_set_home(pte, PAGE_HOME_HASH); ret = gxio_usb_host_register_client_memory(&pdata->usb_ctx, pte, 0); if (ret) { ret = -ENXIO; goto err_have_irq; } ohci_hcd_init(hcd_to_ohci(hcd)); ret = usb_add_hcd(hcd, pdata->irq, IRQF_SHARED); if (ret == 0) { platform_set_drvdata(pdev, hcd); device_wakeup_enable(hcd->self.controller); return ret; } err_have_irq: irq_free_hwirq(pdata->irq); err_no_irq: tilegx_stop_ohc(); usb_put_hcd(hcd); err_hcd: gxio_usb_host_destroy(&pdata->usb_ctx); return ret; }
/* * Perform initialization and enable port for reception. */ static int tilegx_startup(struct uart_port *port) { struct tile_uart_port *tile_uart; gxio_uart_context_t *context; int ret = 0; int cpu = raw_smp_processor_id(); /* pick an arbitrary cpu */ tile_uart = container_of(port, struct tile_uart_port, uart); if (mutex_lock_interruptible(&tile_uart->mutex)) return -EBUSY; context = &tile_uart->context; /* Now open the hypervisor device if we haven't already. */ if (context->fd < 0) { UART_INTERRUPT_MASK_t intr_mask; /* Initialize UART device. */ ret = gxio_uart_init(context, port->line); if (ret) { ret = -ENXIO; goto err; } /* Create our IRQs. */ port->irq = irq_alloc_hwirq(-1); if (!port->irq) goto err_uart_dest; tile_irq_activate(port->irq, TILE_IRQ_PERCPU); /* Register our IRQs. */ ret = request_irq(port->irq, tilegx_interrupt, 0, tilegx_uart_driver.driver_name, port); if (ret) goto err_dest_irq; /* Request that the hardware start sending us interrupts. */ tile_uart->irq_cpu = cpu; ret = gxio_uart_cfg_interrupt(context, cpu_x(cpu), cpu_y(cpu), KERNEL_PL, port->irq); if (ret) goto err_free_irq; /* Enable UART Tx/Rx Interrupt. */ intr_mask.word = gxio_uart_read(context, UART_INTERRUPT_MASK); intr_mask.wfifo_re = 0; intr_mask.rfifo_we = 0; gxio_uart_write(context, UART_INTERRUPT_MASK, intr_mask.word); /* Reset the Tx/Rx interrupt in case it's set. */ gxio_uart_write(context, UART_INTERRUPT_STATUS, UART_INTERRUPT_MASK__WFIFO_RE_MASK | UART_INTERRUPT_MASK__RFIFO_WE_MASK); } mutex_unlock(&tile_uart->mutex); return ret; err_free_irq: free_irq(port->irq, port); err_dest_irq: irq_free_hwirq(port->irq); err_uart_dest: gxio_uart_destroy(context); ret = -ENXIO; err: mutex_unlock(&tile_uart->mutex); return ret; }