Beispiel #1
0
static int spi_mailbox_platform_remove(struct platform_device *pdev) {
  struct spi_mailbox *mailbox;

  /* Get a handle to the mailbox and begin shutting it down */
  mailbox = platform_get_drvdata(pdev);
  if(!mailbox) return(-1);
  cdev_del(&mailbox->cdev);
  reset_mailbox(mailbox);
  iounmap(mailbox->virtualAddress);
  release_mem_region(mailbox->physicalAddress, mailbox->addressRangeSize);
  kfree(mailbox);
  return(0);
}
Beispiel #2
0
static int mailbox_platform_remove(struct platform_device *pdev) {
  struct labx_mailbox *mailbox;

  /* Get a handle to the mailbox and begin shutting it down */
  mailbox = platform_get_drvdata(pdev);
  if(!mailbox) return(-1);
  
  /* Release the IRQ */
  if (mailbox->irq != NO_IRQ_SUPPLIED) {
    free_irq(mailbox->irq, mailbox);
  }
  
  kthread_stop(mailbox->netlinkTask);
  reset_mailbox(mailbox);
  iounmap(mailbox->virtualAddress);
  release_mem_region(mailbox->physicalAddress, mailbox->addressRangeSize);
  kfree(mailbox);
  return(0);
}
Beispiel #3
0
/* Function containing the "meat" of the probe mechanism - this is used by
 * the OpenFirmware probe as well as the standard platform device mechanism.
 * @param name - Name of the instance
 * @param pdev - Platform device structure
 * @param addressRange - Resource describing the hardware's I/O range
 * @param irq          - Resource describing the hardware's IRQ
 */
static int mailbox_probe(const char *name, 
                             struct platform_device *pdev,
                             struct resource *addressRange,
                             struct resource *irq) {
  struct labx_mailbox *mailbox;
  int returnValue;
  int i;

  /* Create and populate a device structure */
  mailbox = (struct labx_mailbox*) kmalloc(sizeof(struct labx_mailbox), GFP_KERNEL);
  if(!mailbox) return(-ENOMEM);

  /* Request and map the device's I/O memory region into uncacheable space */
  mailbox->physicalAddress = addressRange->start;
  mailbox->addressRangeSize = ((addressRange->end - addressRange->start) + 1);
  snprintf(mailbox->name, NAME_MAX_SIZE, "%s", name);
  mailbox->name[NAME_MAX_SIZE - 1] = '\0';
  if(request_mem_region(mailbox->physicalAddress, mailbox->addressRangeSize,
                        mailbox->name) == NULL) {
    returnValue = -ENOMEM;
    goto free;
  }

  mailbox->virtualAddress = 
    (void*) ioremap_nocache(mailbox->physicalAddress, mailbox->addressRangeSize);
  if(!mailbox->virtualAddress) {
    returnValue = -ENOMEM;
    goto release;
  }

  /* Ensure that the mailbox and its interrupts are disabled */
  disable_mailbox(mailbox);
  XIo_Out32(REGISTER_ADDRESS(mailbox, SUPRV_IRQ_MASK_REG), NO_IRQS);

  /* Clear the message ready flag for the first time */
  mailbox->messageReadyFlag = MESSAGE_NOT_READY;
  
  /* Retain the IRQ and register our handler, if an IRQ resource was supplied. */
  if(irq != NULL) {
    mailbox->irq = irq->start;
    returnValue = request_irq(mailbox->irq, &mailbox_interrupt, IRQF_DISABLED,
                              mailbox->name, mailbox);
    if (returnValue) {
      printk(KERN_ERR "%s : Could not allocate Mailbox interrupt (%d).\n",
             mailbox->name, mailbox->irq);
      goto unmap;
    }
  } else mailbox->irq = NO_IRQ_SUPPLIED;
  
  /* Announce the device */
  printk(KERN_INFO "%s: Found mailbox at 0x%08X, ",
         mailbox->name, (uint32_t)mailbox->physicalAddress);
  if(mailbox->irq == NO_IRQ_SUPPLIED) {
    printk("polled interlocks\n");
  } else {
    printk("IRQ %d\n", mailbox->irq);
  }

  /* Initialize other resources */
  spin_lock_init(&mailbox->mutex);
  mailbox->opened = true;

  /* Provide navigation between the device structures */
  platform_set_drvdata(pdev, mailbox);
  mailbox->pdev = pdev;

  /* Reset the state of the mailbox */
  reset_mailbox(mailbox);

  /* Initialize the waitqueue used for synchronized writes */
  init_waitqueue_head(&(mailbox->messageReadQueue));

  /* Initialize the netlink state and start the thread */
  mailbox->netlinkSequence = 0;
  mailbox->netlinkTask = kthread_run(netlink_thread, (void*)mailbox, "%s:netlink", mailbox->name);
  if (IS_ERR(mailbox->netlinkTask)) {
    printk(KERN_ERR "Mailbox netlink task creation failed.\n");
    returnValue = -EIO;
    goto free;
  }
  
  /* Now that the device is configured, enable interrupts if they are to be used */
  if(mailbox->irq != NO_IRQ_SUPPLIED) {
    XIo_Out32(REGISTER_ADDRESS(mailbox, SUPRV_IRQ_MASK_REG), ALL_IRQS);
    XIo_Out32(REGISTER_ADDRESS(mailbox, SUPRV_IRQ_FLAGS_REG), ALL_IRQS);
  }

  // Add the mailbox instance to the list of current devices
  for(i=0;i<MAX_MAILBOX_DEVICES;i++) {
    if(NULL == labx_mailboxes[i]) {
      labx_mailboxes[i] = mailbox;
      printk("Adding mailbox: %s\n", labx_mailboxes[i]->name);
      break;
    }
  }

  DBG("Mailbox initialized\n");

  /* Return success */
  return(0);

 unmap:
  iounmap(mailbox->virtualAddress);
 release:
  release_mem_region(mailbox->physicalAddress, mailbox->addressRangeSize);
 free:
  kfree(mailbox);
  return(returnValue);
}
Beispiel #4
0
/* Function containing the "meat" of the probe mechanism - this is used by
 * the OpenFirmware probe as well as the standard platform device mechanism.
 * @param name - Name of the instance
 * @param pdev - Platform device structure
 * @param addressRange - Resource describing the hardware's I/O range
 * @param irq          - Resource describing the hardware's IRQ
 */
static int spi_mailbox_probe(const char *name, 
                             struct platform_device *pdev,
                             struct resource *addressRange,
                             struct resource *irq) {
  struct spi_mailbox *mailbox;
  int returnValue;

  /* Create and populate a device structure */
  mailbox = (struct spi_mailbox*) kmalloc(sizeof(struct spi_mailbox), GFP_KERNEL);
  if(!mailbox) return(-ENOMEM);

  /* Request and map the device's I/O memory region into uncacheable space */
  mailbox->physicalAddress = addressRange->start;
  mailbox->addressRangeSize = ((addressRange->end - addressRange->start) + 1);
  snprintf(mailbox->name, NAME_MAX_SIZE, "%s", name);
  mailbox->name[NAME_MAX_SIZE - 1] = '\0';
  if(request_mem_region(mailbox->physicalAddress, mailbox->addressRangeSize,
                        mailbox->name) == NULL) {
    returnValue = -ENOMEM;
    goto free;
  }

  mailbox->virtualAddress = 
    (void*) ioremap_nocache(mailbox->physicalAddress, mailbox->addressRangeSize);
  if(!mailbox->virtualAddress) {
    returnValue = -ENOMEM;
    goto release;
  }

  /* Ensure that the mailbox and its interrupts are disabled */
  disable_mailbox(mailbox);
  XIo_Out32(REGISTER_ADDRESS(mailbox, IRQ_MASK_REG), NO_IRQS);

  /* Retain the IRQ and register our handler, if an IRQ resource was supplied. */
  if(irq != NULL) {
    mailbox->irq = irq->start;
    returnValue = request_irq(mailbox->irq, &biamp_spi_mailbox_interrupt, IRQF_DISABLED,
                              mailbox->name, mailbox);
    if (returnValue) {
      printk(KERN_ERR "%s : Could not allocate Biamp SPI Mailbox interrupt (%d).\n",
             mailbox->name, mailbox->irq);
      goto unmap;
    }
  } else mailbox->irq = NO_IRQ_SUPPLIED;
  
  /* Announce the device */
  printk(KERN_INFO "%s: Found Biamp mailbox at 0x%08X, ",
         mailbox->name, (uint32_t)mailbox->physicalAddress);
  if(mailbox->irq == NO_IRQ_SUPPLIED) {
    printk("polled interlocks\n");
  } else {
    printk("IRQ %d\n", mailbox->irq);
  }

  /* Initialize other resources */
  spin_lock_init(&mailbox->mutex);
  mailbox->opened = false;

  /* Provide navigation between the device structures */
  platform_set_drvdata(pdev, mailbox);
  mailbox->pdev = pdev;

  /* Reset the state of the mailbox */
  reset_mailbox(mailbox);

  /* Add as a character device to make the instance available for use */
  cdev_init(&mailbox->cdev, &spi_mailbox_fops);
  mailbox->cdev.owner = THIS_MODULE;
  kobject_set_name(&mailbox->cdev.kobj, "%s%d", mailbox->name, mailbox->instanceNumber);
  mailbox->instanceNumber = instanceCount++;
  cdev_add(&mailbox->cdev, MKDEV(DRIVER_MAJOR, mailbox->instanceNumber), 1);

  /* Initialize the waitqueue used for synchronized writes */
  init_waitqueue_head(&(mailbox->messageReadQueue));

  /* Now that the device is configured, enable interrupts if they are to be used */
  if(mailbox->irq != NO_IRQ_SUPPLIED) {
    XIo_Out32(REGISTER_ADDRESS(mailbox, IRQ_FLAGS_REG), ALL_IRQS);
    XIo_Out32(REGISTER_ADDRESS(mailbox, IRQ_MASK_REG), IRQ_S2H_MSG_RX);
  }

  DBG("Mailbox initialized\n");

  /* Return success */
  return(0);

 unmap:
  iounmap(mailbox->virtualAddress);
 release:
  release_mem_region(mailbox->physicalAddress, mailbox->addressRangeSize);
 free:
  kfree(mailbox);
  return(returnValue);
}