コード例 #1
0
/*
 * Tasklet handler
 */
static void retu_tasklet_handler(unsigned long data)
{
	struct retu_irq_handler_desc *hnd;
	u16 id;
	u16 im;
	int i;

	for (;;) {
		id = retu_read_reg(RETU_REG_IDR);
		im = ~retu_read_reg(RETU_REG_IMR);
		id &= im;

		if (!id)
			break;

		for (i = 0; id != 0; i++, id >>= 1) {
			if (!(id & 1))
				continue;
			hnd = &retu_irq_handlers[i];
			if (hnd->func == NULL) {
                               /* Spurious retu interrupt - disable and ack it */
				printk(KERN_INFO "Spurious Retu interrupt "
						 "(id %d)\n", i);
				retu_disable_irq(i);
				retu_ack_irq(i);
				continue;
			}
			hnd->func(hnd->arg);
			/*
			 * Don't acknowledge the interrupt here
			 * It must be done explicitly
			 */
		}
	}
}
コード例 #2
0
/**
 * retu_power_off - Shut down power to system
 *
 * This function puts the system in power off state
 */
static void retu_power_off(void)
{
	/* Ignore power button state */
	retu_write_reg(RETU_REG_CC1, retu_read_reg(RETU_REG_CC1) | 2);
	/* Expire watchdog immediately */
	retu_write_reg(RETU_REG_WATCHDOG, 0);
	/* Wait for poweroff*/
	for (;;);
}
コード例 #3
0
/*
 * Disable given RETU interrupt
 */
void retu_disable_irq(int id)
{
	unsigned long flags;
	u16 mask;

	spin_lock_irqsave(&retu_lock, flags);
	mask = retu_read_reg(RETU_REG_IMR);
	mask |= 1 << id;
	mask = retu_disable_bogus_irqs(mask);
	retu_write_reg(RETU_REG_IMR, mask);
	spin_unlock_irqrestore(&retu_lock, flags);
}
コード例 #4
0
ファイル: retu.c プロジェクト: Aircell/asp-kernel
void retu_set_clear_reg_bits(int reg, u16 set, u16 clear)
{
	unsigned long flags;
	u16 w;

	spin_lock_irqsave(&retu_lock, flags);
	w = retu_read_reg(reg);
	w &= ~clear;
	w |= set;
	retu_write_reg(reg, w);
	spin_unlock_irqrestore(&retu_lock, flags);
}
コード例 #5
0
ファイル: retu-pwrbutton.c プロジェクト: Aircell/asp-kernel
static void retubutton_timer_func(unsigned long arg)
{
	int state;

	if (retu_read_reg(RETU_REG_STATUS) & RETU_STATUS_PWRONX)
		state = PWRBTN_UP;
	else
		state = PWRBTN_PRESSED;

	if (pwrbtn_state != state) {
		input_report_key(pwrbtn_dev, KEY_POWER, state);
		pwrbtn_state = state;
	}
}
コード例 #6
0
/*
 * Enable given RETU interrupt
 */
void retu_enable_irq(int id)
{
	unsigned long flags;
	u16 mask;

	if (id == 3) {
		printk("Enabling Retu IRQ %d\n", id);
		dump_stack();
	}
	spin_lock_irqsave(&retu_lock, flags);
	mask = retu_read_reg(RETU_REG_IMR);
	mask &= ~(1 << id);
	mask = retu_disable_bogus_irqs(mask);
	retu_write_reg(RETU_REG_IMR, mask);
	spin_unlock_irqrestore(&retu_lock, flags);
}
コード例 #7
0
ファイル: retu.c プロジェクト: Aircell/asp-kernel
int retu_read_adc(int channel)
{
	unsigned long flags;
	int res;

	if (channel < 0 || channel > ADC_MAX_CHAN_NUMBER)
		return -EINVAL;

	spin_lock_irqsave(&retu_lock, flags);

	if ((channel == 8) && retu_is_vilma) {
		int scr = retu_read_reg(RETU_REG_ADCSCR);
		int ch = (retu_read_reg(RETU_REG_ADCR) >> 10) & 0xf;
		if (((scr & 0xff) != 0) && (ch != 8))
			retu_write_reg (RETU_REG_ADCSCR, (scr & ~0xff));
	}
コード例 #8
0
int retu_read_adc(int channel)
{
	unsigned long flags;
	int res;

	if (channel < 0 || channel > ADC_MAX_CHAN_NUMBER)
		return -EINVAL;

	spin_lock_irqsave(&retu_lock, flags);
	/* Select the channel and read result */
	retu_write_reg(RETU_REG_ADCR, channel << 10);
	res = retu_read_reg(RETU_REG_ADCR) & 0x3ff;
	/* Unlock retu */
	spin_unlock_irqrestore(&retu_lock, flags);

	return res;
}
コード例 #9
0
/**
 * retu_probe - Probe for Retu ASIC
 * @dev: the Retu device
 *
 * Probe for the Retu ASIC and allocate memory
 * for its device-struct if found
 */
static int __devinit retu_probe(struct device *dev)
{
	const struct omap_em_asic_bb5_config * em_asic_config;
	int rev, ret;

	/* Prepare tasklet */
	tasklet_init(&retu_tasklet, retu_tasklet_handler, 0);

	em_asic_config = omap_get_config(OMAP_TAG_EM_ASIC_BB5,
					 struct omap_em_asic_bb5_config);
	if (em_asic_config == NULL) {
		printk(KERN_ERR PFX "Unable to retrieve config data\n");
		return -ENODATA;
	}

	retu_irq_pin = em_asic_config->retu_irq_gpio;

	if ((ret = omap_request_gpio(retu_irq_pin)) < 0) {
		printk(KERN_ERR PFX "Unable to reserve IRQ GPIO\n");
		return ret;
	}

	/* Set the pin as input */
	omap_set_gpio_direction(retu_irq_pin, 1);

	/* Rising edge triggers the IRQ */
	set_irq_type(OMAP_GPIO_IRQ(retu_irq_pin), IRQT_RISING);

	retu_initialized = 1;

	rev = retu_read_reg(RETU_REG_ASICR) & 0xff;
	if (rev & (1 << 7))
		retu_is_vilma = 1;

	printk(KERN_INFO "%s v%d.%d found\n", retu_is_vilma ? "Vilma" : "Retu",
	       (rev >> 4) & 0x07, rev & 0x0f);

	/* Mask all RETU interrupts */
	retu_write_reg(RETU_REG_IMR, 0xffff);

	ret = request_irq(OMAP_GPIO_IRQ(retu_irq_pin), retu_irq_handler, 0,
			  "retu", 0);

	if (ret < 0) {
		printk(KERN_ERR PFX "Unable to register IRQ handler\n");
		omap_free_gpio(retu_irq_pin);
		return ret;
	}

	/* Register power off function */
	pm_power_off = retu_power_off;

#ifdef CONFIG_CBUS_RETU_USER
	/* Initialize user-space interface */
	if (retu_user_init() < 0) {
		printk(KERN_ERR "Unable to initialize driver\n");
		free_irq(OMAP_GPIO_IRQ(retu_irq_pin), 0);
		omap_free_gpio(retu_irq_pin);
		return ret;
	}
#endif

	return 0;
}
コード例 #10
0
ファイル: retu.c プロジェクト: Aircell/asp-kernel
	if (channel < 0 || channel > ADC_MAX_CHAN_NUMBER)
		return -EINVAL;

	spin_lock_irqsave(&retu_lock, flags);

	if ((channel == 8) && retu_is_vilma) {
		int scr = retu_read_reg(RETU_REG_ADCSCR);
		int ch = (retu_read_reg(RETU_REG_ADCR) >> 10) & 0xf;
		if (((scr & 0xff) != 0) && (ch != 8))
			retu_write_reg (RETU_REG_ADCSCR, (scr & ~0xff));
	}

	/* Select the channel and read result */
	retu_write_reg(RETU_REG_ADCR, channel << 10);
	res = retu_read_reg(RETU_REG_ADCR) & 0x3ff;

	if (retu_is_vilma)
		retu_write_reg(RETU_REG_ADCR, (1 << 13));

	/* Unlock retu */
	spin_unlock_irqrestore(&retu_lock, flags);

	return res;
}


static u16 retu_disable_bogus_irqs(u16 mask)
{
       int i;