static void c55_ctrl_int_setup(struct c55_ctrl_data *cdata, int gpio) { int ret; int irq = __gpio_to_irq(gpio); unsigned int flags = 0; if (cdata->c55_ap_int_gpio >= 0) { /* Interrupt already registered */ return; } /* Interrupt is shared with user space */ flags |= IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING; flags |= IRQF_SHARED; cdata->c55_ap_int_enabled = 1; ret = request_threaded_irq(irq, c55_ctrl_isr, NULL, flags, "c55_ctrl", cdata); if (ret) { pr_err("%s: IRQ request failed: %d\n", __func__, ret); return; } cdata->c55_ap_int_gpio = gpio; }
static int c55_ctrl_suspend(struct platform_device *dev, pm_message_t state) { struct c55_ctrl_data *cdata = dev_get_drvdata(&dev->dev); struct m4sensorhub_data *m4sensorhub = m4sensorhub_client_get_drvdata(); if (cdata->c55_mode != C55_OFF) { dev_warn(&dev->dev, "C55 still ON when going into suspend\n"); /* Disable C55->AP IRQ when turning off C55 */ if (cdata->c55_ap_int_enabled) { disable_irq_nosync( __gpio_to_irq(cdata->c55_ap_int_gpio)); cdata->c55_ap_int_enabled = 0; } if (m4sensorhub_reg_write_1byte (m4sensorhub, M4SH_REG_USERSETTINGS_AUDIOSTATUS, AUDIO_STATUS_OFF, 0xFF) != 1) { dev_err(&dev->dev, "Unable to set screen status to 0x00\n"); } /* AP->C55 interrupt needs to be set low when C55 is off * for current drain reasons */ gpio_set_value(cdata->ap_c55_int_gpio, 0); cdata->c55_mode = C55_OFF; } pinctrl_select_state(cdata->pctrl, cdata->states[C55_OFF]); return 0; }
void __exit rpi_power_switch_cleanup(void) { sysfs_remove_group(&switch_dev->kobj,&rpi_power_switch_attribute_group); device_unregister(switch_dev); free_irq(__gpio_to_irq(gpio_pin), NULL); gpio_free(gpio_pin); pm_power_off = old_pm_power_off; class_unregister(&power_switch_class); iounmap(gpio_reg); }
int amlogic_request_gpio_to_irq(unsigned int pin,const char *label,unsigned int flag) { int ret=-1; unsigned long flags; if(gpio_range_check(pin)) return -1; ret=amlogic_gpio_request(pin, label); if(!ret) { spin_lock_irqsave(&gpio_irqlock, flags); gpio_flag=flag; __gpio_to_irq(pin); spin_unlock_irqrestore(&gpio_irqlock, flags); } return ret; }
int amlogic_gpio_to_irq(unsigned int pin,const char *owner,unsigned int flag) { int ret=-1; unsigned long flags; if(gpio_range_check(pin)) return -1; if( amlogic_pins[pin].gpio_owner && owner) if(!strcmp(amlogic_pins[pin].gpio_owner,owner)) { spin_lock_irqsave(&gpio_irqlock, flags); gpio_flag=flag; __gpio_to_irq(pin); spin_unlock_irqrestore(&gpio_irqlock, flags); return 0; } return ret; }
void sd_extr_work(struct work_struct *work) { //printk("#######get into extr sd work function######\n"); unsigned long flags; spin_lock_irqsave(&s3c_sd_changed_lock, flags); if (early_suspend_stat&sd_early_suspend) { //printk("$$$$$$$$$$early_suspend_stat:%d\n",early_suspend_stat); //wake_lock(&sd_lock); SendPowerbuttonEvent(); //wake_unlock(&sd_lock); sd_early_suspend=0; } spin_unlock_irqrestore(&s3c_sd_changed_lock, flags); enable_irq(__gpio_to_irq(SD_DET_WAKE)); }
int bcm_wlan_get_oob_irq(void) { int host_oob_irq = 0; int ret = 0; int wl_host_wake = 0; script_item_u val ; script_item_value_type_e type; printk("bcm_wlan_get_oob_irq enter.\n"); type = script_get_item("wifi_para", "ap6xxx_wl_host_wake", &val); if (SCIRPT_ITEM_VALUE_TYPE_PIO!=type) printk("get bcmdhd ap6xxx_wl_host_wake gpio failed\n"); else wl_host_wake = val.gpio.gpio; host_oob_irq = __gpio_to_irq(wl_host_wake); if (host_oob_irq == -ENXIO) { printk("bcm_wlan_get_oob_irq fail to get WL_HOST_WAKE irq.\n"); return 0; } printk("bcm_wlan_get_oob_irq GPIO(WL_HOST_WAKE) = %d\n", host_oob_irq); ret = gpio_request(wl_host_wake, NULL); if (ret != 0) { printk("bcm_wlan_get_oob_irq gpio request fail.\n"); return 0; } ret = gpio_direction_input(wl_host_wake); if (ret != 0) { printk("bcm_wlan_get_oob_irq gpio_direction_input failed.\n"); } gpio_free(wl_host_wake); return host_oob_irq; }
static int __devinit sdhci_s3c_probe(struct platform_device *pdev) { struct s3c_sdhci_platdata *pdata = pdev->dev.platform_data; struct device *dev = &pdev->dev; struct sdhci_host *host; struct sdhci_s3c *sc; struct resource *res; int ret, irq, ptr, clks; if (!pdata) { dev_err(dev, "no device data specified\n"); return -ENOENT; } irq = platform_get_irq(pdev, 0); if (irq < 0) { dev_err(dev, "no irq specified\n"); return irq; } res = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!res) { dev_err(dev, "no memory specified\n"); return -ENOENT; } host = sdhci_alloc_host(dev, sizeof(struct sdhci_s3c)); if (IS_ERR(host)) { dev_err(dev, "sdhci_alloc_host() failed\n"); return PTR_ERR(host); } sc = sdhci_priv(host); sc->host = host; sc->pdev = pdev; sc->pdata = pdata; platform_set_drvdata(pdev, host); sc->clk_io = clk_get(dev, "hsmmc"); if (IS_ERR(sc->clk_io)) { dev_err(dev, "failed to get io clock\n"); ret = PTR_ERR(sc->clk_io); goto err_io_clk; } /* enable the local io clock and keep it running for the moment. */ clk_enable(sc->clk_io); for (clks = 0, ptr = 0; ptr < MAX_BUS_CLK; ptr++) { struct clk *clk; char *name = pdata->clocks[ptr]; if (name == NULL) continue; clk = clk_get(dev, name); if (IS_ERR(clk)) { dev_err(dev, "failed to get clock %s\n", name); continue; } clks++; sc->clk_bus[ptr] = clk; clk_enable(clk); dev_info(dev, "clock source %d: %s (%ld Hz)\n", ptr, name, clk_get_rate(clk)); } if (clks == 0) { dev_err(dev, "failed to find any bus clocks\n"); ret = -ENOENT; goto err_no_busclks; } sc->ioarea = request_mem_region(res->start, resource_size(res), mmc_hostname(host->mmc)); if (!sc->ioarea) { dev_err(dev, "failed to reserve register area\n"); ret = -ENXIO; goto err_req_regs; } host->ioaddr = ioremap_nocache(res->start, resource_size(res)); if (!host->ioaddr) { dev_err(dev, "failed to map registers\n"); ret = -ENXIO; goto err_req_regs; } /* Ensure we have minimal gpio selected CMD/CLK/Detect */ if (pdata->cfg_gpio) pdata->cfg_gpio(pdev, pdata->max_width); if (pdata->get_ro) sdhci_s3c_ops.get_ro = sdhci_s3c_get_ro; host->hw_name = "samsung-hsmmc"; host->ops = &sdhci_s3c_ops; host->quirks = 0; host->irq = irq; /* Setup quirks for the controller */ host->quirks |= SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC; host->quirks |= SDHCI_QUIRK_BROKEN_CARD_PRESENT_BIT; host->quirks |= SDHCI_QUIRK_BROKEN_TIMEOUT_VAL; #ifndef CONFIG_MMC_SDHCI_S3C_DMA /* we currently see overruns on errors, so disable the SDMA * support as well. */ host->quirks |= SDHCI_QUIRK_BROKEN_DMA; /* PIO currently has problems with multi-block IO */ host->quirks |= SDHCI_QUIRK_NO_MULTIBLOCK; #endif /* CONFIG_MMC_SDHCI_S3C_DMA */ /* It seems we do not get an DATA transfer complete on non-busy * transfers, not sure if this is a problem with this specific * SDHCI block, or a missing configuration that needs to be set. */ host->quirks |= SDHCI_QUIRK_NO_BUSY_IRQ; host->quirks |= (SDHCI_QUIRK_32BIT_DMA_ADDR | SDHCI_QUIRK_32BIT_DMA_SIZE); host->quirks |= SDHCI_QUIRK_NO_HISPD_BIT; if (pdata->host_caps) host->mmc->caps = pdata->host_caps; else host->mmc->caps = 0; /* Set pm_flags for built_in device */ host->mmc->pm_caps = MMC_PM_KEEP_POWER | MMC_PM_IGNORE_PM_NOTIFY; if (pdata->built_in) host->mmc->pm_flags = MMC_PM_KEEP_POWER | MMC_PM_IGNORE_PM_NOTIFY; /* to add external irq as a card detect signal */ if (pdata->cfg_ext_cd) { pdata->cfg_ext_cd(); if (pdata->detect_ext_cd()) host->flags |= SDHCI_DEVICE_ALIVE; } /* to configure gpio pin as a card write protection signal */ if (pdata->cfg_wp) pdata->cfg_wp(); ret = sdhci_add_host(host); if (ret) { dev_err(dev, "sdhci_add_host() failed\n"); goto err_add_host; } /* register external irq here (after all init is done) */ if (pdata->cfg_ext_cd) { ret = request_irq(pdata->ext_cd, sdhci_irq_cd, IRQF_SHARED, mmc_hostname(host->mmc), sc); if(ret) goto err_add_host; } #if SD_DYNAMIC if (strcmp(mmc_hostname(host->mmc),"mmc1")==0) { int retval=0; spin_lock_init(&s3c_sd_changed_lock); INIT_WORK(&sd_monitor_work, sd_extr_work); s3c_gpio_cfgpin(SD_DET_WAKE, S3C_GPIO_SFN(0xf)); s3c_gpio_setpull(SD_DET_WAKE, 0); retval = request_irq(__gpio_to_irq(SD_DET_WAKE), s3c_sdhci_power_irq, IRQ_TYPE_EDGE_BOTH, sd_driver_name, NULL); if (retval != 0) { printk(KERN_ERR "%s: can't get irq %i, err %d\n", sd_driver_name, __gpio_to_irq(SD_DET_WAKE), retval); } printk(KERN_ERR "%s: get irq %i, err %d\n", sd_driver_name, __gpio_to_irq(SD_DET_WAKE), retval); } #endif return 0; err_add_host: release_resource(sc->ioarea); kfree(sc->ioarea); err_req_regs: for (ptr = 0; ptr < MAX_BUS_CLK; ptr++) { if (sc->clk_bus[ptr]) { clk_disable(sc->clk_bus[ptr]); clk_put(sc->clk_bus[ptr]); } } err_no_busclks: clk_disable(sc->clk_io); clk_put(sc->clk_io); err_io_clk: sdhci_free_host(host); return ret; }
static irqreturn_t s3c_sdhci_power_irq(int irq, void *handle) { disable_irq_nosync(__gpio_to_irq(SD_DET_WAKE)); schedule_work(&sd_monitor_work); return IRQ_HANDLED; }
int __init rpi_power_switch_init(void) { int ret = 0; if (gpio_pin < 0) { pr_err(POWER_SWITCH_CLASS_NAME ": missing argument: gpio_pin\n"); return -EINVAL; } old_pm_power_off = pm_power_off; pm_power_off = rpi_power_switch_power_off; pr_info("Switch driver v%s\n", RPI_POWER_SWITCH_VERSION); INIT_DELAYED_WORK(&initiate_shutdown_work, initiate_shutdown); /* Register our own class for the power switch */ ret = class_register(&power_switch_class); if (ret < 0) { pr_err("%s: Unable to register class\n", power_switch_class.name); goto out0; } /* Create devices for each PWM present */ switch_dev = device_create(&power_switch_class, &platform_bus, MKDEV(0, 0), NULL, "pswitch%u", 0); if (IS_ERR(switch_dev)) { pr_err("%s: device_create failed\n", power_switch_class.name); ret = PTR_ERR(switch_dev); goto out1; } ret = sysfs_create_group(&switch_dev->kobj, &rpi_power_switch_attribute_group); if (ret < 0) { pr_err("%s: create_group failed\n", power_switch_class.name); goto out2; } /* GPIO register memory must be mapped before doing any direct * accesses such as changing GPIO alt functions or changing GPIO * pull ups or pull downs. */ gpio_reg = ioremap(GPIO_BASE, 1024); /* Set the specified pin as a GPIO input */ SET_GPIO_INPUT(gpio_pin); /* Set the pin as a pulldown. Most pins should default to having * pulldowns, and this seems most intuitive. */ set_gpio_pull(gpio_pin, GPIO_PULL_UP); gpio_request(gpio_pin, "Power switch"); gpio_direction_input(gpio_pin); /* The targeted polarity should be the opposite of the current value. * I.e. we want the pin to transition to this state in order to * initiate a shutdown. */ gpio_pol = !gpio_get_value(gpio_pin); /* Request an interrupt to fire when the pin transitions to our * desired state. */ ret = request_irq(__gpio_to_irq(gpio_pin), power_isr, gpio_pol?IRQF_TRIGGER_RISING:IRQF_TRIGGER_FALLING, "Power button", NULL); if (ret) { pr_err("Unable to request IRQ\n"); goto out3; } return 0; /* Error handling */ out3: sysfs_remove_group(&switch_dev->kobj,&rpi_power_switch_attribute_group); out2: device_unregister(switch_dev); out1: class_unregister(&power_switch_class); out0: iounmap(gpio_reg); pm_power_off = old_pm_power_off; return ret; }
static ssize_t c55_ctrl_enable(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { struct c55_ctrl_data *cdata = dev_get_drvdata(dev); struct m4sensorhub_data *m4sensorhub = m4sensorhub_client_get_drvdata(); int mode; if (kstrtoint(buf, 10, &mode) < 0) return -EINVAL; if (mode >= C55_MODE_MAX) { dev_err(dev, "%s: Invalid mode %d\n", __func__, mode); return -EINVAL; } if (m4sensorhub->mode != NORMALMODE) { dev_err(dev, "M4 not ready, Unable to set screen status\n"); return -EINVAL; } if (mode == cdata->c55_mode) return count; mutex_lock(&cdata->ctrl_mutex); if (mode == C55_ON) { pinctrl_select_state(cdata->pctrl, cdata->states[C55_ON]); gpio_set_value(cdata->ap_c55_int_gpio, 1); if (m4sensorhub_reg_write_1byte (m4sensorhub, M4SH_REG_USERSETTINGS_AUDIOSTATUS, AUDIO_STATUS_ON, 0xFF) != 1) { dev_err(dev, "Unable to set screen status to 0x01\n"); mutex_unlock(&cdata->ctrl_mutex); return -EINVAL; } if (!cdata->c55_ap_int_enabled) { cdata->c55_ap_int_enabled = 1; enable_irq(__gpio_to_irq(cdata->c55_ap_int_gpio)); } } else { /* Disable C55->AP IRQ when turning off C55 */ if (cdata->c55_ap_int_enabled) { disable_irq_nosync( __gpio_to_irq(cdata->c55_ap_int_gpio)); cdata->c55_ap_int_enabled = 0; } if (m4sensorhub_reg_write_1byte (m4sensorhub, M4SH_REG_USERSETTINGS_AUDIOSTATUS, AUDIO_STATUS_OFF, 0xFF) != 1) { dev_err(dev, "Unable to set screen status to 0x00\n"); mutex_unlock(&cdata->ctrl_mutex); return -EINVAL; } /* AP->C55 interrupt needs to be set low when C55 is off * for current drain reasons */ gpio_set_value(cdata->ap_c55_int_gpio, 0); pinctrl_select_state(cdata->pctrl, cdata->states[C55_OFF]); /* Unlock wake lock in case it is active */ wake_unlock(&cdata->wake_lock); } cdata->c55_mode = mode; mutex_unlock(&cdata->ctrl_mutex); dev_info(dev, "%s: enable = %d\n", __func__, mode); return count; }