static void msic_bus_sync_unlock(struct irq_data *data) { struct msic_gpio *mg = irq_data_get_irq_chip_data(data); int offset; int reg; u8 trig = 0; /* We can only get one change at a time as the buslock covers the entire transaction. The irq_desc->lock is dropped before we are called but that is fine */ if (mg->trig_change_mask) { offset = __ffs(mg->trig_change_mask); reg = msic_gpio_to_ireg(offset); if (reg < 0) goto out; if (mg->trig_type & IRQ_TYPE_EDGE_RISING) trig |= MSIC_GPIO_TRIG_RISE; if (mg->trig_type & IRQ_TYPE_EDGE_FALLING) trig |= MSIC_GPIO_TRIG_FALL; intel_msic_reg_update(reg, trig, MSIC_GPIO_INTCNT_MASK); mg->trig_change_mask = 0; } out: mutex_unlock(&mg->buslock); }
static void msic_gpio_set(struct gpio_chip *chip, unsigned offset, int value) { int reg; reg = msic_gpio_to_oreg(offset); if (reg < 0) return; intel_msic_reg_update(reg, !!value , MSIC_GPIO_DOUT_MASK); }
static int msic_gpio_direction_input(struct gpio_chip *chip, unsigned offset) { int reg; reg = msic_gpio_to_oreg(offset); if (reg < 0) return reg; return intel_msic_reg_update(reg, MSIC_GPIO_DIR_IN, MSIC_GPIO_DIR_MASK); }
static int __devinit mfld_pb_probe(struct platform_device *pdev) { struct input_dev *input; int irq = platform_get_irq(pdev, 0); int error; if (irq < 0) return -EINVAL; input = input_allocate_device(); if (!input) { dev_err(&pdev->dev, "Input device allocation error\n"); return -ENOMEM; } input->name = pdev->name; input->phys = "power-button/input0"; input->id.bustype = BUS_HOST; input->dev.parent = &pdev->dev; input_set_capability(input, EV_KEY, KEY_POWER); error = request_threaded_irq(irq, NULL, mfld_pb_isr, IRQF_NO_SUSPEND, DRIVER_NAME, input); if (error) { dev_err(&pdev->dev, "Unable to request irq %d for mfld power" "button\n", irq); goto err_free_input; } error = input_register_device(input); if (error) { dev_err(&pdev->dev, "Unable to register input dev, error " "%d\n", error); goto err_free_irq; } platform_set_drvdata(pdev, input); error = intel_msic_reg_update(INTEL_MSIC_IRQLVL1MSK, 0, MSIC_PWRBTNM); if (error) { dev_err(&pdev->dev, "Unable to clear power button interrupt, " "error: %d\n", error); goto err_free_irq; } return 0; err_free_irq: free_irq(irq, input); err_free_input: input_free_device(input); return error; }
static int msic_gpio_direction_output(struct gpio_chip *chip, unsigned offset, int value) { int reg; unsigned mask; value = (!!value) | MSIC_GPIO_DIR_OUT; mask = MSIC_GPIO_DIR_MASK | MSIC_GPIO_DOUT_MASK; reg = msic_gpio_to_oreg(offset); if (reg < 0) return reg; return intel_msic_reg_update(reg, value, mask); }
static int mfld_pb_probe(struct platform_device *pdev) { struct input_dev *input; int irq = platform_get_irq(pdev, 0); int error; if (irq < 0) return -EINVAL; input = input_allocate_device(); if (!input) { dev_err(&pdev->dev, "Input device allocation error\n"); return -ENOMEM; } input->name = pdev->name; input->phys = "power-button/input0"; input->id.bustype = BUS_HOST; input->dev.parent = &pdev->dev; input_set_capability(input, EV_KEY, KEY_POWER); error = request_threaded_irq(irq, NULL, mfld_pb_isr, IRQF_NO_SUSPEND, DRIVER_NAME, input); if (error) { dev_err(&pdev->dev, "Unable to request irq %d for mfld power" "button\n", irq); goto err_free_input; } error = input_register_device(input); if (error) { dev_err(&pdev->dev, "Unable to register input dev, error " "%d\n", error); goto err_free_irq; } platform_set_drvdata(pdev, input); /* * SCU firmware might send power button interrupts to IA core before * kernel boots and doesn't get EOI from IA core. The first bit of * MSIC reg 0x21 is kept masked, and SCU firmware doesn't send new * power interrupt to Android kernel. Unmask the bit when probing * power button in kernel. * There is a very narrow race between irq handler and power button * initialization. The race happens rarely. So we needn't worry * about it. */ error = intel_msic_reg_update(INTEL_MSIC_IRQLVL1MSK, 0, MSIC_PWRBTNM); if (error) { dev_err(&pdev->dev, "Unable to clear power button interrupt, " "error: %d\n", error); goto err_free_irq; } return 0; err_free_irq: free_irq(irq, input); err_free_input: input_free_device(input); return error; }