/* * This function will allocate both the DMA descriptor structure, and the * buffers it contains. These are used to contain the descriptors used * by the system. */ int ath_descdma_setup(struct ath_softc *sc, struct ath_descdma *dd, struct list_head *head, const char *name, int nbuf, int ndesc, bool is_tx) { struct ath_common *common = ath9k_hw_common(sc->sc_ah); u8 *ds; int i, bsize, desc_len; ath_dbg(common, CONFIG, "%s DMA: %u buffers %u desc/buf\n", name, nbuf, ndesc); INIT_LIST_HEAD(head); if (is_tx) desc_len = sc->sc_ah->caps.tx_desc_len; else desc_len = sizeof(struct ath_desc); /* ath_desc must be a multiple of DWORDs */ if ((desc_len % 4) != 0) { ath_err(common, "ath_desc not DWORD aligned\n"); BUG_ON((desc_len % 4) != 0); return -ENOMEM; } dd->dd_desc_len = desc_len * nbuf * ndesc; /* * Need additional DMA memory because we can't use * descriptors that cross the 4K page boundary. Assume * one skipped descriptor per 4K page. */ if (!(sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_4KB_SPLITTRANS)) { u32 ndesc_skipped = ATH_DESC_4KB_BOUND_NUM_SKIPPED(dd->dd_desc_len); u32 dma_len; while (ndesc_skipped) { dma_len = ndesc_skipped * desc_len; dd->dd_desc_len += dma_len; ndesc_skipped = ATH_DESC_4KB_BOUND_NUM_SKIPPED(dma_len); } } /* allocate descriptors */ dd->dd_desc = dmam_alloc_coherent(sc->dev, dd->dd_desc_len, &dd->dd_desc_paddr, GFP_KERNEL); if (!dd->dd_desc) return -ENOMEM; ds = (u8 *) dd->dd_desc; ath_dbg(common, CONFIG, "%s DMA map: %p (%u) -> %llx (%u)\n", name, ds, (u32) dd->dd_desc_len, ito64(dd->dd_desc_paddr), /*XXX*/(u32) dd->dd_desc_len); /* allocate buffers */ if (is_tx) { struct ath_buf *bf; bsize = sizeof(struct ath_buf) * nbuf; bf = devm_kzalloc(sc->dev, bsize, GFP_KERNEL); if (!bf) return -ENOMEM; for (i = 0; i < nbuf; i++, bf++, ds += (desc_len * ndesc)) { bf->bf_desc = ds; bf->bf_daddr = DS2PHYS(dd, ds); if (!(sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_4KB_SPLITTRANS)) { /* * Skip descriptor addresses which can cause 4KB * boundary crossing (addr + length) with a 32 dword * descriptor fetch. */ while (ATH_DESC_4KB_BOUND_CHECK(bf->bf_daddr)) { BUG_ON((caddr_t) bf->bf_desc >= ((caddr_t) dd->dd_desc + dd->dd_desc_len)); ds += (desc_len * ndesc); bf->bf_desc = ds; bf->bf_daddr = DS2PHYS(dd, ds); } } list_add_tail(&bf->list, head); } } else { struct ath_rxbuf *bf; bsize = sizeof(struct ath_rxbuf) * nbuf; bf = devm_kzalloc(sc->dev, bsize, GFP_KERNEL); if (!bf) return -ENOMEM; for (i = 0; i < nbuf; i++, bf++, ds += (desc_len * ndesc)) { bf->bf_desc = ds; bf->bf_daddr = DS2PHYS(dd, ds); if (!(sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_4KB_SPLITTRANS)) { /* * Skip descriptor addresses which can cause 4KB * boundary crossing (addr + length) with a 32 dword * descriptor fetch. */ while (ATH_DESC_4KB_BOUND_CHECK(bf->bf_daddr)) { BUG_ON((caddr_t) bf->bf_desc >= ((caddr_t) dd->dd_desc + dd->dd_desc_len)); ds += (desc_len * ndesc); bf->bf_desc = ds; bf->bf_daddr = DS2PHYS(dd, ds); } } list_add_tail(&bf->list, head); } } return 0; }
static int wm8505fb_probe(struct platform_device *pdev) { struct wm8505fb_info *fbi; struct resource *res; struct display_timings *disp_timing; void *addr; int ret; struct fb_videomode mode; u32 bpp; dma_addr_t fb_mem_phys; unsigned long fb_mem_len; void *fb_mem_virt; fbi = devm_kzalloc(&pdev->dev, sizeof(struct wm8505fb_info) + sizeof(u32) * 16, GFP_KERNEL); if (!fbi) { dev_err(&pdev->dev, "Failed to initialize framebuffer device\n"); return -ENOMEM; } strcpy(fbi->fb.fix.id, DRIVER_NAME); fbi->fb.fix.type = FB_TYPE_PACKED_PIXELS; fbi->fb.fix.xpanstep = 1; fbi->fb.fix.ypanstep = 1; fbi->fb.fix.ywrapstep = 0; fbi->fb.fix.accel = FB_ACCEL_NONE; fbi->fb.fbops = &wm8505fb_ops; fbi->fb.flags = FBINFO_DEFAULT | FBINFO_HWACCEL_COPYAREA | FBINFO_HWACCEL_FILLRECT | FBINFO_HWACCEL_XPAN | FBINFO_HWACCEL_YPAN | FBINFO_VIRTFB | FBINFO_PARTIAL_PAN_OK; fbi->fb.node = -1; addr = fbi; addr = addr + sizeof(struct wm8505fb_info); fbi->fb.pseudo_palette = addr; res = platform_get_resource(pdev, IORESOURCE_MEM, 0); fbi->regbase = devm_ioremap_resource(&pdev->dev, res); if (IS_ERR(fbi->regbase)) return PTR_ERR(fbi->regbase); disp_timing = of_get_display_timings(pdev->dev.of_node); if (!disp_timing) return -EINVAL; ret = of_get_fb_videomode(pdev->dev.of_node, &mode, OF_USE_NATIVE_MODE); if (ret) return ret; ret = of_property_read_u32(pdev->dev.of_node, "bits-per-pixel", &bpp); if (ret) return ret; fb_videomode_to_var(&fbi->fb.var, &mode); fbi->fb.var.nonstd = 0; fbi->fb.var.activate = FB_ACTIVATE_NOW; fbi->fb.var.height = -1; fbi->fb.var.width = -1; /* try allocating the framebuffer */ fb_mem_len = mode.xres * mode.yres * 2 * (bpp / 8); fb_mem_virt = dmam_alloc_coherent(&pdev->dev, fb_mem_len, &fb_mem_phys, GFP_KERNEL); if (!fb_mem_virt) { pr_err("%s: Failed to allocate framebuffer\n", __func__); return -ENOMEM; } fbi->fb.var.xres_virtual = mode.xres; fbi->fb.var.yres_virtual = mode.yres * 2; fbi->fb.var.bits_per_pixel = bpp; fbi->fb.fix.smem_start = fb_mem_phys; fbi->fb.fix.smem_len = fb_mem_len; fbi->fb.screen_base = fb_mem_virt; fbi->fb.screen_size = fb_mem_len; fbi->contrast = 0x10; ret = wm8505fb_set_par(&fbi->fb); if (ret) { dev_err(&pdev->dev, "Failed to set parameters\n"); return ret; } if (fb_alloc_cmap(&fbi->fb.cmap, 256, 0) < 0) { dev_err(&pdev->dev, "Failed to allocate color map\n"); return -ENOMEM; } wm8505fb_init_hw(&fbi->fb); platform_set_drvdata(pdev, fbi); ret = register_framebuffer(&fbi->fb); if (ret < 0) { dev_err(&pdev->dev, "Failed to register framebuffer device: %d\n", ret); if (fbi->fb.cmap.len) fb_dealloc_cmap(&fbi->fb.cmap); return ret; } ret = device_create_file(&pdev->dev, &dev_attr_contrast); if (ret < 0) fb_warn(&fbi->fb, "failed to register attributes (%d)\n", ret); fb_info(&fbi->fb, "%s frame buffer at 0x%lx-0x%lx\n", fbi->fb.fix.id, fbi->fb.fix.smem_start, fbi->fb.fix.smem_start + fbi->fb.fix.smem_len - 1); return 0; }
static int __devinit pxa_ata_probe(struct platform_device *pdev) { struct ata_host *host; struct ata_port *ap; struct pata_pxa_data *data; struct resource *cmd_res; struct resource *ctl_res; struct resource *dma_res; struct resource *irq_res; struct pata_pxa_pdata *pdata = pdev->dev.platform_data; int ret = 0; /* * Resource validation, three resources are needed: * - CMD port base address * - CTL port base address * - DMA port base address * - IRQ pin */ if (pdev->num_resources != 4) { dev_err(&pdev->dev, "invalid number of resources\n"); return -EINVAL; } /* * CMD port base address */ cmd_res = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (unlikely(cmd_res == NULL)) return -EINVAL; /* * CTL port base address */ ctl_res = platform_get_resource(pdev, IORESOURCE_MEM, 1); if (unlikely(ctl_res == NULL)) return -EINVAL; /* * DMA port base address */ dma_res = platform_get_resource(pdev, IORESOURCE_DMA, 0); if (unlikely(dma_res == NULL)) return -EINVAL; /* * IRQ pin */ irq_res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); if (unlikely(irq_res == NULL)) return -EINVAL; /* * Allocate the host */ host = ata_host_alloc(&pdev->dev, 1); if (!host) return -ENOMEM; ap = host->ports[0]; ap->ops = &pxa_ata_port_ops; ap->pio_mask = ATA_PIO4; ap->mwdma_mask = ATA_MWDMA2; ap->ioaddr.cmd_addr = devm_ioremap(&pdev->dev, cmd_res->start, resource_size(cmd_res)); ap->ioaddr.ctl_addr = devm_ioremap(&pdev->dev, ctl_res->start, resource_size(ctl_res)); ap->ioaddr.bmdma_addr = devm_ioremap(&pdev->dev, dma_res->start, resource_size(dma_res)); /* * Adjust register offsets */ ap->ioaddr.altstatus_addr = ap->ioaddr.ctl_addr; ap->ioaddr.data_addr = ap->ioaddr.cmd_addr + (ATA_REG_DATA << pdata->reg_shift); ap->ioaddr.error_addr = ap->ioaddr.cmd_addr + (ATA_REG_ERR << pdata->reg_shift); ap->ioaddr.feature_addr = ap->ioaddr.cmd_addr + (ATA_REG_FEATURE << pdata->reg_shift); ap->ioaddr.nsect_addr = ap->ioaddr.cmd_addr + (ATA_REG_NSECT << pdata->reg_shift); ap->ioaddr.lbal_addr = ap->ioaddr.cmd_addr + (ATA_REG_LBAL << pdata->reg_shift); ap->ioaddr.lbam_addr = ap->ioaddr.cmd_addr + (ATA_REG_LBAM << pdata->reg_shift); ap->ioaddr.lbah_addr = ap->ioaddr.cmd_addr + (ATA_REG_LBAH << pdata->reg_shift); ap->ioaddr.device_addr = ap->ioaddr.cmd_addr + (ATA_REG_DEVICE << pdata->reg_shift); ap->ioaddr.status_addr = ap->ioaddr.cmd_addr + (ATA_REG_STATUS << pdata->reg_shift); ap->ioaddr.command_addr = ap->ioaddr.cmd_addr + (ATA_REG_CMD << pdata->reg_shift); /* * Allocate and load driver's internal data structure */ data = devm_kzalloc(&pdev->dev, sizeof(struct pata_pxa_data), GFP_KERNEL); if (!data) return -ENOMEM; ap->private_data = data; data->dma_dreq = pdata->dma_dreq; data->dma_io_addr = dma_res->start; /* * Allocate space for the DMA descriptors */ data->dma_desc = dmam_alloc_coherent(&pdev->dev, PAGE_SIZE, &data->dma_desc_addr, GFP_KERNEL); if (!data->dma_desc) return -EINVAL; /* * Request the DMA channel */ data->dma_channel = pxa_request_dma(DRV_NAME, DMA_PRIO_LOW, pxa_ata_dma_irq, ap); if (data->dma_channel < 0) return -EBUSY; /* * Stop and clear the DMA channel */ DCSR(data->dma_channel) = 0; /* * Activate the ATA host */ ret = ata_host_activate(host, irq_res->start, ata_sff_interrupt, pdata->irq_flags, &pxa_ata_sht); if (ret) pxa_free_dma(data->dma_channel); return ret; }
int qpic_init_sps(struct platform_device *pdev, struct qpic_sps_endpt *end_point) { int rc = 0; struct sps_pipe *pipe_handle; struct sps_connect *sps_config = &end_point->config; struct sps_register_event *sps_event = &end_point->bam_event; struct sps_bam_props bam = {0}; u32 bam_handle = 0; if (qpic_res->sps_init) return 0; bam.phys_addr = qpic_res->qpic_phys + 0x4000; bam.virt_addr = qpic_res->qpic_base + 0x4000; bam.irq = qpic_res->irq - 4; bam.manage = SPS_BAM_MGR_DEVICE_REMOTE | SPS_BAM_MGR_MULTI_EE; rc = sps_phy2h(bam.phys_addr, &bam_handle); if (rc) rc = sps_register_bam_device(&bam, &bam_handle); if (rc) { pr_err("%s bam_handle is NULL", __func__); rc = -ENOMEM; goto out; } pipe_handle = sps_alloc_endpoint(); if (!pipe_handle) { pr_err("sps_alloc_endpoint() failed\n"); rc = -ENOMEM; goto out; } rc = sps_get_config(pipe_handle, sps_config); if (rc) { pr_err("sps_get_config() failed %d\n", rc); goto free_endpoint; } /* WRITE CASE: source - system memory; destination - BAM */ sps_config->source = SPS_DEV_HANDLE_MEM; sps_config->destination = bam_handle; sps_config->mode = SPS_MODE_DEST; sps_config->dest_pipe_index = 6; sps_config->options = SPS_O_AUTO_ENABLE | SPS_O_EOT; sps_config->lock_group = 0; /* * Descriptor FIFO is a cyclic FIFO. If 64 descriptors * are allowed to be submitted before we get any ack for any of them, * the descriptor FIFO size should be: (SPS_MAX_DESC_NUM + 1) * * sizeof(struct sps_iovec). */ sps_config->desc.size = (64) * sizeof(struct sps_iovec); sps_config->desc.base = dmam_alloc_coherent(&pdev->dev, sps_config->desc.size, &sps_config->desc.phys_base, GFP_KERNEL); if (!sps_config->desc.base) { pr_err("dmam_alloc_coherent() failed for size %x\n", sps_config->desc.size); rc = -ENOMEM; goto free_endpoint; } memset(sps_config->desc.base, 0x00, sps_config->desc.size); rc = sps_connect(pipe_handle, sps_config); if (rc) { pr_err("sps_connect() failed %d\n", rc); goto free_endpoint; } init_completion(&end_point->completion); sps_event->mode = SPS_TRIGGER_WAIT; sps_event->options = SPS_O_EOT; sps_event->xfer_done = &end_point->completion; sps_event->user = (void *)qpic_res; rc = sps_register_event(pipe_handle, sps_event); if (rc) { pr_err("sps_register_event() failed %d\n", rc); goto sps_disconnect; } end_point->handle = pipe_handle; qpic_res->sps_init = true; goto out; sps_disconnect: sps_disconnect(pipe_handle); free_endpoint: sps_free_endpoint(pipe_handle); out: return rc; }
/* probe for CAN-FD channel #pciefd_board->can_count */ static int pciefd_can_probe(struct pciefd_board *pciefd) { struct net_device *ndev; struct pciefd_can *priv; u32 clk; int err; /* allocate the candev object with default isize of echo skbs ring */ ndev = alloc_peak_canfd_dev(sizeof(*priv), pciefd->can_count, PCIEFD_ECHO_SKB_MAX); if (!ndev) { dev_err(&pciefd->pci_dev->dev, "failed to alloc candev object\n"); goto failure; } priv = netdev_priv(ndev); /* fill-in candev private object: */ /* setup PCIe-FD own callbacks */ priv->ucan.pre_cmd = pciefd_pre_cmd; priv->ucan.write_cmd = pciefd_write_cmd; priv->ucan.post_cmd = pciefd_post_cmd; priv->ucan.enable_tx_path = pciefd_enable_tx_path; priv->ucan.alloc_tx_msg = pciefd_alloc_tx_msg; priv->ucan.write_tx_msg = pciefd_write_tx_msg; /* setup PCIe-FD own command buffer */ priv->ucan.cmd_buffer = &priv->pucan_cmd; priv->ucan.cmd_maxlen = sizeof(priv->pucan_cmd); priv->board = pciefd; /* CAN config regs block address */ priv->reg_base = pciefd->reg_base + PCIEFD_CANX_OFF(priv->ucan.index); /* allocate non-cacheable DMA'able 4KB memory area for Rx */ priv->rx_dma_vaddr = dmam_alloc_coherent(&pciefd->pci_dev->dev, PCIEFD_RX_DMA_SIZE, &priv->rx_dma_laddr, GFP_KERNEL); if (!priv->rx_dma_vaddr) { dev_err(&pciefd->pci_dev->dev, "Rx dmam_alloc_coherent(%u) failure\n", PCIEFD_RX_DMA_SIZE); goto err_free_candev; } /* allocate non-cacheable DMA'able 4KB memory area for Tx */ priv->tx_dma_vaddr = dmam_alloc_coherent(&pciefd->pci_dev->dev, PCIEFD_TX_DMA_SIZE, &priv->tx_dma_laddr, GFP_KERNEL); if (!priv->tx_dma_vaddr) { dev_err(&pciefd->pci_dev->dev, "Tx dmaim_alloc_coherent(%u) failure\n", PCIEFD_TX_DMA_SIZE); goto err_free_candev; } /* CAN clock in RST mode */ pciefd_can_writereg(priv, CANFD_MISC_TS_RST, PCIEFD_REG_CAN_MISC); /* read current clock value */ clk = pciefd_can_readreg(priv, PCIEFD_REG_CAN_CLK_SEL); switch (clk) { case CANFD_CLK_SEL_20MHZ: priv->ucan.can.clock.freq = 20 * 1000 * 1000; break; case CANFD_CLK_SEL_24MHZ: priv->ucan.can.clock.freq = 24 * 1000 * 1000; break; case CANFD_CLK_SEL_30MHZ: priv->ucan.can.clock.freq = 30 * 1000 * 1000; break; case CANFD_CLK_SEL_40MHZ: priv->ucan.can.clock.freq = 40 * 1000 * 1000; break; case CANFD_CLK_SEL_60MHZ: priv->ucan.can.clock.freq = 60 * 1000 * 1000; break; default: pciefd_can_writereg(priv, CANFD_CLK_SEL_80MHZ, PCIEFD_REG_CAN_CLK_SEL); /* fallthough */ case CANFD_CLK_SEL_80MHZ: priv->ucan.can.clock.freq = 80 * 1000 * 1000; break; } ndev->irq = pciefd->pci_dev->irq; SET_NETDEV_DEV(ndev, &pciefd->pci_dev->dev); err = register_candev(ndev); if (err) { dev_err(&pciefd->pci_dev->dev, "couldn't register CAN device: %d\n", err); goto err_free_candev; } spin_lock_init(&priv->tx_lock); /* save the object address in the board structure */ pciefd->can[pciefd->can_count] = priv; dev_info(&pciefd->pci_dev->dev, "%s at reg_base=0x%p irq=%d\n", ndev->name, priv->reg_base, pciefd->pci_dev->irq); return 0; err_free_candev: free_candev(ndev); failure: return -ENOMEM; }
int vchiq_platform_init(struct platform_device *pdev, VCHIQ_STATE_T *state) { struct device *dev = &pdev->dev; struct rpi_firmware *fw = platform_get_drvdata(pdev); VCHIQ_SLOT_ZERO_T *vchiq_slot_zero; struct resource *res; void *slot_mem; dma_addr_t slot_phys; u32 channelbase; int slot_mem_size, frag_mem_size; int err, irq, i; g_virt_to_bus_offset = virt_to_dma(dev, (void *)0); (void)of_property_read_u32(dev->of_node, "cache-line-size", &g_cache_line_size); g_fragments_size = 2 * g_cache_line_size; /* Allocate space for the channels in coherent memory */ slot_mem_size = PAGE_ALIGN(TOTAL_SLOTS * VCHIQ_SLOT_SIZE); frag_mem_size = PAGE_ALIGN(g_fragments_size * MAX_FRAGMENTS); slot_mem = dmam_alloc_coherent(dev, slot_mem_size + frag_mem_size, &slot_phys, GFP_KERNEL); if (!slot_mem) { dev_err(dev, "could not allocate DMA memory\n"); return -ENOMEM; } WARN_ON(((int)slot_mem & (PAGE_SIZE - 1)) != 0); vchiq_slot_zero = vchiq_init_slots(slot_mem, slot_mem_size); if (!vchiq_slot_zero) return -EINVAL; vchiq_slot_zero->platform_data[VCHIQ_PLATFORM_FRAGMENTS_OFFSET_IDX] = (int)slot_phys + slot_mem_size; vchiq_slot_zero->platform_data[VCHIQ_PLATFORM_FRAGMENTS_COUNT_IDX] = MAX_FRAGMENTS; g_fragments_base = (char *)slot_mem + slot_mem_size; slot_mem_size += frag_mem_size; g_free_fragments = g_fragments_base; for (i = 0; i < (MAX_FRAGMENTS - 1); i++) { *(char **)&g_fragments_base[i*g_fragments_size] = &g_fragments_base[(i + 1)*g_fragments_size]; } *(char **)&g_fragments_base[i * g_fragments_size] = NULL; sema_init(&g_free_fragments_sema, MAX_FRAGMENTS); if (vchiq_init_state(state, vchiq_slot_zero, 0) != VCHIQ_SUCCESS) return -EINVAL; res = platform_get_resource(pdev, IORESOURCE_MEM, 0); g_regs = devm_ioremap_resource(&pdev->dev, res); if (IS_ERR(g_regs)) return PTR_ERR(g_regs); irq = platform_get_irq(pdev, 0); if (irq <= 0) { dev_err(dev, "failed to get IRQ\n"); return irq; } err = devm_request_irq(dev, irq, vchiq_doorbell_irq, IRQF_IRQPOLL, "VCHIQ doorbell", state); if (err) { dev_err(dev, "failed to register irq=%d\n", irq); return err; } /* Send the base address of the slots to VideoCore */ channelbase = slot_phys; err = rpi_firmware_property(fw, RPI_FIRMWARE_VCHIQ_INIT, &channelbase, sizeof(channelbase)); if (err || channelbase) { dev_err(dev, "failed to set channelbase\n"); return err ? : -ENXIO; }
static int arc_emac_probe(struct platform_device *pdev) { struct resource res_regs; struct device_node *phy_node; struct arc_emac_priv *priv; struct net_device *ndev; const char *mac_addr; unsigned int id, clock_frequency, irq; int err; if (!pdev->dev.of_node) return -ENODEV; /* Get PHY from device tree */ phy_node = of_parse_phandle(pdev->dev.of_node, "phy", 0); if (!phy_node) { dev_err(&pdev->dev, "failed to retrieve phy description from device tree\n"); return -ENODEV; } /* Get EMAC registers base address from device tree */ err = of_address_to_resource(pdev->dev.of_node, 0, &res_regs); if (err) { dev_err(&pdev->dev, "failed to retrieve registers base from device tree\n"); return -ENODEV; } /* Get CPU clock frequency from device tree */ if (of_property_read_u32(pdev->dev.of_node, "clock-frequency", &clock_frequency)) { dev_err(&pdev->dev, "failed to retrieve <clock-frequency> from device tree\n"); return -EINVAL; } /* Get IRQ from device tree */ irq = irq_of_parse_and_map(pdev->dev.of_node, 0); if (!irq) { dev_err(&pdev->dev, "failed to retrieve <irq> value from device tree\n"); return -ENODEV; } ndev = alloc_etherdev(sizeof(struct arc_emac_priv)); if (!ndev) return -ENOMEM; platform_set_drvdata(pdev, ndev); SET_NETDEV_DEV(ndev, &pdev->dev); ndev->netdev_ops = &arc_emac_netdev_ops; ndev->ethtool_ops = &arc_emac_ethtool_ops; ndev->watchdog_timeo = TX_TIMEOUT; /* FIXME :: no multicast support yet */ ndev->flags &= ~IFF_MULTICAST; priv = netdev_priv(ndev); priv->dev = &pdev->dev; priv->ndev = ndev; priv->regs = devm_ioremap_resource(&pdev->dev, &res_regs); if (IS_ERR(priv->regs)) { err = PTR_ERR(priv->regs); goto out; } dev_dbg(&pdev->dev, "Registers base address is 0x%p\n", priv->regs); id = arc_reg_get(priv, R_ID); /* Check for EMAC revision 5 or 7, magic number */ if (!(id == 0x0005fd02 || id == 0x0007fd02)) { dev_err(&pdev->dev, "ARC EMAC not detected, id=0x%x\n", id); err = -ENODEV; goto out; } dev_info(&pdev->dev, "ARC EMAC detected with id: 0x%x\n", id); /* Set poll rate so that it polls every 1 ms */ arc_reg_set(priv, R_POLLRATE, clock_frequency / 1000000); /* Get max speed of operation from device tree */ if (of_property_read_u32(pdev->dev.of_node, "max-speed", &priv->max_speed)) { dev_err(&pdev->dev, "failed to retrieve <max-speed> from device tree\n"); err = -EINVAL; goto out; } ndev->irq = irq; dev_info(&pdev->dev, "IRQ is %d\n", ndev->irq); /* Register interrupt handler for device */ err = devm_request_irq(&pdev->dev, ndev->irq, arc_emac_intr, 0, ndev->name, ndev); if (err) { dev_err(&pdev->dev, "could not allocate IRQ\n"); goto out; } /* Get MAC address from device tree */ mac_addr = of_get_mac_address(pdev->dev.of_node); if (mac_addr) memcpy(ndev->dev_addr, mac_addr, ETH_ALEN); else eth_hw_addr_random(ndev); dev_info(&pdev->dev, "MAC address is now %pM\n", ndev->dev_addr); /* Do 1 allocation instead of 2 separate ones for Rx and Tx BD rings */ priv->rxbd = dmam_alloc_coherent(&pdev->dev, RX_RING_SZ + TX_RING_SZ, &priv->rxbd_dma, GFP_KERNEL); if (!priv->rxbd) { dev_err(&pdev->dev, "failed to allocate data buffers\n"); err = -ENOMEM; goto out; } priv->txbd = priv->rxbd + RX_BD_NUM; priv->txbd_dma = priv->rxbd_dma + RX_RING_SZ; dev_dbg(&pdev->dev, "EMAC Device addr: Rx Ring [0x%x], Tx Ring[%x]\n", (unsigned int)priv->rxbd_dma, (unsigned int)priv->txbd_dma); err = arc_mdio_probe(pdev, priv); if (err) { dev_err(&pdev->dev, "failed to probe MII bus\n"); goto out; } priv->phy_dev = of_phy_connect(ndev, phy_node, arc_emac_adjust_link, 0, PHY_INTERFACE_MODE_MII); if (!priv->phy_dev) { dev_err(&pdev->dev, "of_phy_connect() failed\n"); err = -ENODEV; goto out; } dev_info(&pdev->dev, "connected to %s phy with id 0x%x\n", priv->phy_dev->drv->name, priv->phy_dev->phy_id); netif_napi_add(ndev, &priv->napi, arc_emac_poll, ARC_EMAC_NAPI_WEIGHT); err = register_netdev(ndev); if (err) { netif_napi_del(&priv->napi); dev_err(&pdev->dev, "failed to register network device\n"); goto out; } return 0; out: free_netdev(ndev); return err; }
static int goldfish_audio_probe(struct platform_device *pdev) { int ret; struct resource *r; struct goldfish_audio *data; dma_addr_t buf_addr; data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL); if (!data) return -ENOMEM; spin_lock_init(&data->lock); init_waitqueue_head(&data->wait); platform_set_drvdata(pdev, data); r = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (r == NULL) { dev_err(&pdev->dev, "platform_get_resource failed\n"); return -ENODEV; } data->reg_base = devm_ioremap(&pdev->dev, r->start, PAGE_SIZE); if (data->reg_base == NULL) return -ENOMEM; data->irq = platform_get_irq(pdev, 0); if (data->irq < 0) { dev_err(&pdev->dev, "platform_get_irq failed\n"); return -ENODEV; } data->buffer_virt = dmam_alloc_coherent(&pdev->dev, COMBINED_BUFFER_SIZE, &buf_addr, GFP_KERNEL); if (data->buffer_virt == NULL) { dev_err(&pdev->dev, "allocate buffer failed\n"); return -ENOMEM; } data->buffer_phys = buf_addr; data->write_buffer1 = data->buffer_virt; data->write_buffer2 = data->buffer_virt + WRITE_BUFFER_SIZE; data->read_buffer = data->buffer_virt + 2 * WRITE_BUFFER_SIZE; ret = devm_request_irq(&pdev->dev, data->irq, goldfish_audio_interrupt, IRQF_SHARED, pdev->name, data); if (ret) { dev_err(&pdev->dev, "request_irq failed\n"); return ret; } ret = misc_register(&goldfish_audio_device); if (ret) { dev_err(&pdev->dev, "misc_register returned %d in goldfish_audio_init\n", ret); return ret; } AUDIO_WRITE64(data, AUDIO_SET_WRITE_BUFFER_1, AUDIO_SET_WRITE_BUFFER_1_HIGH, buf_addr); buf_addr += WRITE_BUFFER_SIZE; AUDIO_WRITE64(data, AUDIO_SET_WRITE_BUFFER_2, AUDIO_SET_WRITE_BUFFER_2_HIGH, buf_addr); buf_addr += WRITE_BUFFER_SIZE; data->read_supported = AUDIO_READ(data, AUDIO_READ_SUPPORTED); if (data->read_supported) AUDIO_WRITE64(data, AUDIO_SET_READ_BUFFER, AUDIO_SET_READ_BUFFER_HIGH, buf_addr); audio_data = data; return 0; }
int vchiq_platform_init(struct platform_device *pdev, VCHIQ_STATE_T *state) { struct device *dev = &pdev->dev; VCHIQ_SLOT_ZERO_T *vchiq_slot_zero; struct resource *res; void *slot_mem; dma_addr_t slot_phys; int slot_mem_size, frag_mem_size; int err, irq, i; g_virt_to_bus_offset = virt_to_dma(dev, (void *)0); /* Allocate space for the channels in coherent memory */ slot_mem_size = PAGE_ALIGN(TOTAL_SLOTS * VCHIQ_SLOT_SIZE); frag_mem_size = PAGE_ALIGN(sizeof(FRAGMENTS_T) * MAX_FRAGMENTS); slot_mem = dmam_alloc_coherent(dev, slot_mem_size + frag_mem_size, &slot_phys, GFP_KERNEL); if (!slot_mem) { dev_err(dev, "could not allocate DMA memory\n"); return -ENOMEM; } WARN_ON(((int)slot_mem & (PAGE_SIZE - 1)) != 0); vchiq_slot_zero = vchiq_init_slots(slot_mem, slot_mem_size); if (!vchiq_slot_zero) return -EINVAL; vchiq_slot_zero->platform_data[VCHIQ_PLATFORM_FRAGMENTS_OFFSET_IDX] = (int)slot_phys + slot_mem_size; vchiq_slot_zero->platform_data[VCHIQ_PLATFORM_FRAGMENTS_COUNT_IDX] = MAX_FRAGMENTS; g_fragments_base = (FRAGMENTS_T *)(slot_mem + slot_mem_size); slot_mem_size += frag_mem_size; g_free_fragments = g_fragments_base; for (i = 0; i < (MAX_FRAGMENTS - 1); i++) { *(FRAGMENTS_T **)&g_fragments_base[i] = &g_fragments_base[i + 1]; } *(FRAGMENTS_T **)&g_fragments_base[i] = NULL; sema_init(&g_free_fragments_sema, MAX_FRAGMENTS); if (vchiq_init_state(state, vchiq_slot_zero, 0) != VCHIQ_SUCCESS) return -EINVAL; res = platform_get_resource(pdev, IORESOURCE_MEM, 0); g_regs = devm_ioremap_resource(&pdev->dev, res); if (IS_ERR(g_regs)) return PTR_ERR(g_regs); irq = platform_get_irq(pdev, 0); if (irq <= 0) { dev_err(dev, "failed to get IRQ\n"); return irq; } err = devm_request_irq(dev, irq, vchiq_doorbell_irq, IRQF_IRQPOLL, "VCHIQ doorbell", state); if (err) { dev_err(dev, "failed to register irq=%d\n", irq); return err; } /* Send the base address of the slots to VideoCore */ dsb(); /* Ensure all writes have completed */ err = bcm_mailbox_write(MBOX_CHAN_VCHIQ, (unsigned int)slot_phys); if (err) { dev_err(dev, "mailbox write failed\n"); return err; } vchiq_log_info(vchiq_arm_log_level, "vchiq_init - done (slots %x, phys %pad)", (unsigned int)vchiq_slot_zero, &slot_phys); vchiq_call_connected_callbacks(); return 0; }