/* * 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 ssize_t hv_stats_store(struct device *dev, struct device_attribute *attr, const char *page, size_t count) { int cpu = dev->id; long lotar = HV_XY_TO_LOTAR(cpu_x(cpu), cpu_y(cpu)); ssize_t n = hv_confstr(HV_CONFSTR_HV_STATS, 0, 0, lotar, 1); return n < 0 ? n : count; }
static ssize_t hv_stats_show(struct device *dev, struct device_attribute *attr, char *page) { int cpu = dev->id; long lotar = HV_XY_TO_LOTAR(cpu_x(cpu), cpu_y(cpu)); ssize_t n = hv_confstr(HV_CONFSTR_HV_STATS, (unsigned long)page, PAGE_SIZE - 1, lotar, 0); n = n < 0 ? 0 : min(n, (ssize_t)PAGE_SIZE - 1); page[n] = '\0'; return n; }
static int __init create_sysfs_entries(void) { int err = 0; #define create_cpu_attr(name) \ if (!err) \ err = device_create_file(cpu_subsys.dev_root, &dev_attr_##name); create_cpu_attr(chip_width); create_cpu_attr(chip_height); create_cpu_attr(chip_serial); create_cpu_attr(chip_revision); #define create_hv_attr(name) \ if (!err) \ err = sysfs_create_file(hypervisor_kobj, &dev_attr_##name.attr); create_hv_attr(type); create_hv_attr(version); create_hv_attr(config_version); if (!err) err = sysfs_create_group(hypervisor_kobj, &board_attr_group); if (!err) { sysfs_bin_attr_init(&hvconfig_bin); hvconfig_bin.attr.name = "hvconfig"; hvconfig_bin.attr.mode = S_IRUGO; hvconfig_bin.read = hvconfig_bin_read; hvconfig_bin.size = PAGE_SIZE; err = sysfs_create_bin_file(hypervisor_kobj, &hvconfig_bin); } if (!err) { /* * Don't bother adding the hv_stats files on each CPU if * our hypervisor doesn't supply statistics. */ int cpu = raw_smp_processor_id(); long lotar = HV_XY_TO_LOTAR(cpu_x(cpu), cpu_y(cpu)); char dummy; ssize_t n = hv_confstr(HV_CONFSTR_HV_STATS, (unsigned long) &dummy, 1, lotar, 0); if (n >= 0) err = subsys_interface_register(&hv_stats_interface); } return err; }
/* * Stop receiving - port is in process of being closed. */ static void tilegx_stop_rx(struct uart_port *port) { int err; 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_trylock(&tile_uart->mutex)) return; context = &tile_uart->context; cpu = tile_uart->irq_cpu; err = gxio_uart_cfg_interrupt(context, cpu_x(cpu), cpu_y(cpu), KERNEL_PL, -1); mutex_unlock(&tile_uart->mutex); }
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 = create_irq(); if (pdata->irq < 0) { 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); return ret; } err_have_irq: destroy_irq(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; }
static int ehci_hcd_tilegx_drv_probe(struct platform_device *pdev) { struct usb_hcd *hcd; struct ehci_hcd *ehci; 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, 1) != 0) return -ENXIO; hcd = usb_create_hcd(&ehci_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_ehc(); ehci = hcd_to_ehci(hcd); ehci->caps = hcd->regs; ehci->regs = hcd->regs + HC_LENGTH(ehci, readl(&ehci->caps->hc_capbase)); /* cache this readonly data; minimize chip reads */ ehci->hcs_params = readl(&ehci->caps->hcs_params); /* 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; } 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_ehc(); usb_put_hcd(hcd); err_hcd: gxio_usb_host_destroy(&pdata->usb_ctx); return ret; }