static int ohci_hcd_tmio_drv_suspend(struct platform_device *dev, pm_message_t state) { const struct mfd_cell *cell = mfd_get_cell(dev); struct usb_hcd *hcd = platform_get_drvdata(dev); struct ohci_hcd *ohci = hcd_to_ohci(hcd); struct tmio_hcd *tmio = hcd_to_tmio(hcd); unsigned long flags; u8 misc; int ret; if (time_before(jiffies, ohci->next_statechange)) msleep(5); ohci->next_statechange = jiffies; spin_lock_irqsave(&tmio->lock, flags); misc = tmio_ioread8(tmio->ccr + CCR_MISC); misc |= 1 << 3; /* USSUSP */ tmio_iowrite8(misc, tmio->ccr + CCR_MISC); spin_unlock_irqrestore(&tmio->lock, flags); if (cell->suspend) { ret = cell->suspend(dev); if (ret) return ret; } return 0; }
int mfd_clone_cell(const char *cell, const char **clones, size_t n_clones) { struct mfd_cell cell_entry; struct device *dev; struct platform_device *pdev; int i; /* fetch the parent cell's device (should already be registered!) */ dev = bus_find_device_by_name(&platform_bus_type, NULL, cell); if (!dev) { printk(KERN_ERR "failed to find device for cell %s\n", cell); return -ENODEV; } pdev = to_platform_device(dev); memcpy(&cell_entry, mfd_get_cell(pdev), sizeof(cell_entry)); WARN_ON(!cell_entry.enable); for (i = 0; i < n_clones; i++) { cell_entry.name = clones[i]; /* don't give up if a single call fails; just report error */ if (mfd_add_device(pdev->dev.parent, -1, &cell_entry, NULL, 0)) dev_err(dev, "failed to create platform device '%s'\n", clones[i]); } return 0; }
int mfd_clone_cell(const char *cell, const char **clones, size_t n_clones) { struct mfd_cell cell_entry; struct device *dev; struct platform_device *pdev; int i; dev = bus_find_device_by_name(&platform_bus_type, NULL, cell); if (!dev) { printk(KERN_ERR "failed to find device for cell %s\n", cell); return -ENODEV; } pdev = to_platform_device(dev); memcpy(&cell_entry, mfd_get_cell(pdev), sizeof(cell_entry)); WARN_ON(!cell_entry.enable); for (i = 0; i < n_clones; i++) { cell_entry.name = clones[i]; if (mfd_add_device(pdev->dev.parent, -1, &cell_entry, NULL, 0)) dev_err(dev, "failed to create platform device '%s'\n", clones[i]); } return 0; }
static int ohci_hcd_tmio_drv_resume(struct platform_device *dev) { const struct mfd_cell *cell = mfd_get_cell(dev); struct usb_hcd *hcd = platform_get_drvdata(dev); struct ohci_hcd *ohci = hcd_to_ohci(hcd); struct tmio_hcd *tmio = hcd_to_tmio(hcd); unsigned long flags; u8 misc; int ret; if (time_before(jiffies, ohci->next_statechange)) msleep(5); ohci->next_statechange = jiffies; if (cell->resume) { ret = cell->resume(dev); if (ret) return ret; } tmio_start_hc(dev); spin_lock_irqsave(&tmio->lock, flags); misc = tmio_ioread8(tmio->ccr + CCR_MISC); misc &= ~(1 << 3); /* USSUSP */ tmio_iowrite8(misc, tmio->ccr + CCR_MISC); spin_unlock_irqrestore(&tmio->lock, flags); ohci_finish_controller_resume(hcd); return 0; }
static void tmio_hw_stop(struct platform_device *dev, struct tmio_nand *tmio) { const struct mfd_cell *cell = mfd_get_cell(dev); tmio_iowrite8(FCR_MODE_POWER_OFF, tmio->fcr + FCR_MODE); if (cell->disable) cell->disable(dev); }
static int tmio_suspend(struct platform_device *dev, pm_message_t state) { const struct mfd_cell *cell = mfd_get_cell(dev); if (cell->suspend) cell->suspend(dev); tmio_hw_stop(dev, platform_get_drvdata(dev)); return 0; }
static int asic3_led_resume(struct device *dev) { struct platform_device *pdev = to_platform_device(dev); const struct mfd_cell *cell = mfd_get_cell(pdev); int ret; ret = 0; if (cell->resume) ret = (*cell->resume)(pdev); return ret; }
static int mfd_remove_devices_fn(struct device *dev, void *c) { struct platform_device *pdev = to_platform_device(dev); const struct mfd_cell *cell = mfd_get_cell(pdev); atomic_t **usage_count = c; /* find the base address of usage_count pointers (for freeing) */ if (!*usage_count || (cell->usage_count < *usage_count)) *usage_count = cell->usage_count; platform_device_unregister(pdev); return 0; }
static int tmio_mmc_suspend(struct platform_device *dev, pm_message_t state) { const struct mfd_cell *cell = mfd_get_cell(dev); int ret; ret = tmio_mmc_host_suspend(&dev->dev); /* */ if (!ret && cell->disable) cell->disable(dev); return ret; }
static int tmio_resume(struct platform_device *dev) { const struct mfd_cell *cell = mfd_get_cell(dev); /* FIXME - is this required or merely another attack of the broken * SHARP platform? Looks suspicious. */ tmio_hw_init(dev, platform_get_drvdata(dev)); if (cell->resume) cell->resume(dev); return 0; }
static int tmio_mmc_resume(struct platform_device *dev) { const struct mfd_cell *cell = mfd_get_cell(dev); int ret = 0; /* Tell the MFD core we are ready to be enabled */ if (cell->resume) ret = cell->resume(dev); if (!ret) ret = tmio_mmc_host_resume(&dev->dev); return ret; }
static int tmio_mmc_resume(struct platform_device *dev) { const struct mfd_cell *cell = mfd_get_cell(dev); int ret = 0; /* */ if (cell->resume) ret = cell->resume(dev); if (!ret) ret = tmio_mmc_host_resume(&dev->dev); return ret; }
static int tmio_mmc_suspend(struct platform_device *dev, pm_message_t state) { const struct mfd_cell *cell = mfd_get_cell(dev); struct mmc_host *mmc = platform_get_drvdata(dev); int ret; ret = mmc_suspend_host(mmc); /* Tell MFD core it can disable us now.*/ if (!ret && cell->disable) cell->disable(dev); return ret; }
static int __devinit tmio_mmc_probe(struct platform_device *pdev) { const struct mfd_cell *cell = mfd_get_cell(pdev); struct tmio_mmc_data *pdata; struct tmio_mmc_host *host; int ret = -EINVAL, irq; if (pdev->num_resources != 2) goto out; pdata = pdev->dev.platform_data; if (!pdata || !pdata->hclk) goto out; irq = platform_get_irq(pdev, 0); if (irq < 0) { ret = irq; goto out; } /* */ if (cell->enable) { ret = cell->enable(pdev); if (ret) goto out; } ret = tmio_mmc_host_probe(&host, pdev, pdata); if (ret) goto cell_disable; ret = request_irq(irq, tmio_mmc_irq, IRQF_TRIGGER_FALLING, dev_name(&pdev->dev), host); if (ret) goto host_remove; pr_info("%s at 0x%08lx irq %d\n", mmc_hostname(host->mmc), (unsigned long)host->ctl, irq); return 0; host_remove: tmio_mmc_host_remove(host); cell_disable: if (cell->disable) cell->disable(pdev); out: return ret; }
int mfd_cell_enable(struct platform_device *pdev) { const struct mfd_cell *cell = mfd_get_cell(pdev); int err = 0; /* only call enable hook if the cell wasn't previously enabled */ if (atomic_inc_return(cell->usage_count) == 1) err = cell->enable(pdev); /* if the enable hook failed, decrement counter to allow retries */ if (err) atomic_dec(cell->usage_count); return err; }
static int tmio_mmc_remove(struct platform_device *pdev) { const struct mfd_cell *cell = mfd_get_cell(pdev); struct mmc_host *mmc = platform_get_drvdata(pdev); if (mmc) { struct tmio_mmc_host *host = mmc_priv(mmc); free_irq(platform_get_irq(pdev, 0), host); tmio_mmc_host_remove(host); if (cell->disable) cell->disable(pdev); } return 0; }
int mfd_cell_enable(struct platform_device *pdev) { const struct mfd_cell *cell = mfd_get_cell(pdev); int err = 0; if (atomic_inc_return(cell->usage_count) == 1) err = cell->enable(pdev); if (err) atomic_dec(cell->usage_count); return err; }
static int __devexit tmio_mmc_remove(struct platform_device *pdev) { const struct mfd_cell *cell = mfd_get_cell(pdev); struct mmc_host *mmc = platform_get_drvdata(pdev); platform_set_drvdata(pdev, NULL); if (mmc) { tmio_mmc_host_remove(mmc_priv(mmc)); if (cell->disable) cell->disable(pdev); } return 0; }
static int ohci_hcd_tmio_drv_remove(struct platform_device *dev) { struct usb_hcd *hcd = platform_get_drvdata(dev); struct tmio_hcd *tmio = hcd_to_tmio(hcd); const struct mfd_cell *cell = mfd_get_cell(dev); usb_remove_hcd(hcd); tmio_stop_hc(dev); if (cell->disable) cell->disable(dev); dma_release_declared_memory(&dev->dev); iounmap(hcd->regs); iounmap(tmio->ccr); usb_put_hcd(hcd); return 0; }
static void brightness_set(struct led_classdev *cdev, enum led_brightness value) { struct platform_device *pdev = to_platform_device(cdev->dev->parent); const struct mfd_cell *cell = mfd_get_cell(pdev); struct asic3 *asic = dev_get_drvdata(pdev->dev.parent); u32 timebase; unsigned int base; timebase = (value == LED_OFF) ? 0 : (LED_EN|0x4); base = led_n_base[cell->id]; asic3_write_register(asic, (base + ASIC3_LED_PeriodTime), 32); asic3_write_register(asic, (base + ASIC3_LED_DutyTime), 32); asic3_write_register(asic, (base + ASIC3_LED_AutoStopCount), 0); asic3_write_register(asic, (base + ASIC3_LED_TimeBase), timebase); }
static int mfd_remove_devices_fn(struct device *dev, void *c) { struct platform_device *pdev; const struct mfd_cell *cell; atomic_t **usage_count = c; if (dev->type != &mfd_dev_type) return 0; pdev = to_platform_device(dev); cell = mfd_get_cell(pdev); if (!*usage_count || (cell->usage_count < *usage_count)) *usage_count = cell->usage_count; platform_device_unregister(pdev); return 0; }
static int tmio_mmc_resume(struct platform_device *dev) { const struct mfd_cell *cell = mfd_get_cell(dev); struct mmc_host *mmc = platform_get_drvdata(dev); int ret = 0; /* Tell the MFD core we are ready to be enabled */ if (cell->resume) { ret = cell->resume(dev); if (ret) goto out; } mmc_resume_host(mmc); out: return ret; }
int mfd_cell_disable(struct platform_device *pdev) { const struct mfd_cell *cell = mfd_get_cell(pdev); int err = 0; if (atomic_dec_return(cell->usage_count) == 0) err = cell->disable(pdev); if (err) atomic_inc(cell->usage_count); WARN_ON(atomic_read(cell->usage_count) < 0); return err; }
int mfd_cell_disable(struct platform_device *pdev) { const struct mfd_cell *cell = mfd_get_cell(pdev); int err = 0; /* only disable if no other clients are using it */ if (atomic_dec_return(cell->usage_count) == 0) err = cell->disable(pdev); /* if the disable hook failed, increment to allow retries */ if (err) atomic_inc(cell->usage_count); /* sanity check; did someone call disable too many times? */ WARN_ON(atomic_read(cell->usage_count) < 0); return err; }
static int tmio_hw_init(struct platform_device *dev, struct tmio_nand *tmio) { const struct mfd_cell *cell = mfd_get_cell(dev); int ret; if (cell->enable) { ret = cell->enable(dev); if (ret) return ret; } /* (4Ch) CLKRUN Enable 1st spcrunc */ tmio_iowrite8(0x81, tmio->ccr + CCR_ICC); /* (10h)BaseAddress 0x1000 spba.spba2 */ tmio_iowrite16(tmio->fcr_base, tmio->ccr + CCR_BASE); tmio_iowrite16(tmio->fcr_base >> 16, tmio->ccr + CCR_BASE + 2); /* (04h)Command Register I/O spcmd */ tmio_iowrite8(0x02, tmio->ccr + CCR_COMMAND); /* (62h) Power Supply Control ssmpwc */ /* HardPowerOFF - SuspendOFF - PowerSupplyWait_4MS */ tmio_iowrite8(0x02, tmio->ccr + CCR_NFPSC); /* (63h) Detect Control ssmdtc */ tmio_iowrite8(0x02, tmio->ccr + CCR_NFDC); /* Interrupt status register clear sintst */ tmio_iowrite8(0x0f, tmio->fcr + FCR_ISR); /* After power supply, Media are reset smode */ tmio_iowrite8(FCR_MODE_POWER_ON, tmio->fcr + FCR_MODE); tmio_iowrite8(FCR_MODE_COMMAND, tmio->fcr + FCR_MODE); tmio_iowrite8(NAND_CMD_RESET, tmio->fcr + FCR_DATA); /* Standby Mode smode */ tmio_iowrite8(FCR_MODE_STANDBY, tmio->fcr + FCR_MODE); mdelay(5); return 0; }
static int blink_set(struct led_classdev *cdev, unsigned long *delay_on, unsigned long *delay_off) { struct platform_device *pdev = to_platform_device(cdev->dev->parent); const struct mfd_cell *cell = mfd_get_cell(pdev); struct asic3 *asic = dev_get_drvdata(pdev->dev.parent); u32 on; u32 off; unsigned int base; if (*delay_on > MAX_MS || *delay_off > MAX_MS) return -EINVAL; if (*delay_on == 0 && *delay_off == 0) { /* If both are zero then a sensible default should be chosen */ on = MS_TO_CLK(500); off = MS_TO_CLK(500); } else { on = MS_TO_CLK(*delay_on); off = MS_TO_CLK(*delay_off); if ((on + off) > MAX_CLK) return -EINVAL; } base = led_n_base[cell->id]; asic3_write_register(asic, (base + ASIC3_LED_PeriodTime), (on + off)); asic3_write_register(asic, (base + ASIC3_LED_DutyTime), on); asic3_write_register(asic, (base + ASIC3_LED_AutoStopCount), 0); asic3_write_register(asic, (base + ASIC3_LED_TimeBase), (LED_EN|0x4)); *delay_on = CLK_TO_MS(on); *delay_off = CLK_TO_MS(off); return 0; }
static int __devinit tmio_mmc_probe(struct platform_device *pdev) { const struct mfd_cell *cell = mfd_get_cell(pdev); struct tmio_mmc_data *pdata; struct tmio_mmc_host *host; int ret = -EINVAL; if (pdev->num_resources != 2) goto out; pdata = mfd_get_data(pdev); if (!pdata || !pdata->hclk) goto out; /* Tell the MFD core we are ready to be enabled */ if (cell->enable) { ret = cell->enable(pdev); if (ret) goto out; } ret = tmio_mmc_host_probe(&host, pdev, pdata); if (ret) goto cell_disable; pr_info("%s at 0x%08lx irq %d\n", mmc_hostname(host->mmc), (unsigned long)host->ctl, host->irq); return 0; cell_disable: if (cell->disable) cell->disable(pdev); out: return ret; }
static int __devinit ohci_hcd_tmio_drv_probe(struct platform_device *dev) { const struct mfd_cell *cell = mfd_get_cell(dev); struct resource *regs = platform_get_resource(dev, IORESOURCE_MEM, 0); struct resource *config = platform_get_resource(dev, IORESOURCE_MEM, 1); struct resource *sram = platform_get_resource(dev, IORESOURCE_MEM, 2); int irq = platform_get_irq(dev, 0); struct tmio_hcd *tmio; struct ohci_hcd *ohci; struct usb_hcd *hcd; int ret; if (usb_disabled()) return -ENODEV; if (!cell) return -EINVAL; hcd = usb_create_hcd(&ohci_tmio_hc_driver, &dev->dev, dev_name(&dev->dev)); if (!hcd) { ret = -ENOMEM; goto err_usb_create_hcd; } hcd->rsrc_start = regs->start; hcd->rsrc_len = resource_size(regs); tmio = hcd_to_tmio(hcd); spin_lock_init(&tmio->lock); tmio->ccr = ioremap(config->start, resource_size(config)); if (!tmio->ccr) { ret = -ENOMEM; goto err_ioremap_ccr; } hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len); if (!hcd->regs) { ret = -ENOMEM; goto err_ioremap_regs; } if (!dma_declare_coherent_memory(&dev->dev, sram->start, sram->start, resource_size(sram), DMA_MEMORY_MAP | DMA_MEMORY_EXCLUSIVE)) { ret = -EBUSY; goto err_dma_declare; } if (cell->enable) { ret = cell->enable(dev); if (ret) goto err_enable; } tmio_start_hc(dev); ohci = hcd_to_ohci(hcd); ohci_hcd_init(ohci); ret = usb_add_hcd(hcd, irq, 0); if (ret) goto err_add_hcd; if (ret == 0) return ret; usb_remove_hcd(hcd); err_add_hcd: tmio_stop_hc(dev); if (cell->disable) cell->disable(dev); err_enable: dma_release_declared_memory(&dev->dev); err_dma_declare: iounmap(hcd->regs); err_ioremap_regs: iounmap(tmio->ccr); err_ioremap_ccr: usb_put_hcd(hcd); err_usb_create_hcd: return ret; }