コード例 #1
0
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;
}
コード例 #2
0
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;
}
コード例 #3
0
ファイル: switch_module.c プロジェクト: badowsky/rpi-scripts
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);
}
コード例 #4
0
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;
}
コード例 #5
0
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;
}
コード例 #6
0
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));
}
コード例 #7
0
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;
}
コード例 #8
0
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;
}
コード例 #9
0
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;
}
コード例 #10
0
ファイル: switch_module.c プロジェクト: badowsky/rpi-scripts
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;
}
コード例 #11
0
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;
}