static int tc3589x_chip_init(struct tc3589x *tc3589x) { int manf, ver, ret; manf = tc3589x_reg_read(tc3589x, TC3589x_MANFCODE); if (manf < 0) return manf; ver = tc3589x_reg_read(tc3589x, TC3589x_VERSION); if (ver < 0) return ver; if (manf != TC3589x_MANFCODE_MAGIC) { dev_err(tc3589x->dev, "unknown manufacturer: %#x\n", manf); return -EINVAL; } dev_info(tc3589x->dev, "manufacturer: %#x, version: %#x\n", manf, ver); /* * Put everything except the IRQ module into reset; * also spare the GPIO module for any pin initialization * done during pre-kernel boot */ ret = tc3589x_reg_write(tc3589x, TC3589x_RSTCTRL, TC3589x_RSTCTRL_TIMRST | TC3589x_RSTCTRL_ROTRST | TC3589x_RSTCTRL_KBDRST); if (ret < 0) return ret; /* Clear the reset interrupt. */ return tc3589x_reg_write(tc3589x, TC3589x_RSTINTCLR, 0x1); }
static irqreturn_t tc3589x_irq(int irq, void *data) { struct tc3589x *tc3589x = data; int status; again: status = tc3589x_reg_read(tc3589x, TC3589x_IRQST); if (status < 0) return IRQ_NONE; while (status) { int bit = __ffs(status); handle_nested_irq(tc3589x->irq_base + bit); status &= ~(1 << bit); } /* * A dummy read or write (to any register) appears to be necessary to * have the last interrupt clear (for example, GPIO IC write) take * effect. In such a case, recheck for any interrupt which is still * pending. */ status = tc3589x_reg_read(tc3589x, TC3589x_IRQST); if (status) goto again; return IRQ_HANDLED; }
static int tc3589x_gpio_get(struct gpio_chip *chip, unsigned offset) { struct tc3589x_gpio *tc3589x_gpio = gpiochip_get_data(chip); struct tc3589x *tc3589x = tc3589x_gpio->tc3589x; u8 reg = TC3589x_GPIODATA0 + (offset / 8) * 2; u8 mask = 1 << (offset % 8); int ret; ret = tc3589x_reg_read(tc3589x, reg); if (ret < 0) return ret; return !!(ret & mask); }
/** * tc3589x_set_bits() - set the value of a bitfield in a TC3589x register * @tc3589x: Device to write to * @reg: Register to write * @mask: Mask of bits to set * @values: Value to set */ int tc3589x_set_bits(struct tc3589x *tc3589x, u8 reg, u8 mask, u8 val) { int ret; mutex_lock(&tc3589x->lock); ret = tc3589x_reg_read(tc3589x, reg); if (ret < 0) goto out; ret &= ~mask; ret |= val; ret = tc3589x_reg_write(tc3589x, reg, ret); out: mutex_unlock(&tc3589x->lock); return ret; }
static irqreturn_t tc3589x_keypad_irq(int irq, void *dev) { struct tc_keypad *keypad = dev; struct tc3589x *tc3589x = keypad->tc3589x; u8 i, row_index, col_index, kbd_code, up; u8 code; for (i = 0; i < TC35893_DATA_REGS * 2; i++) { kbd_code = tc3589x_reg_read(tc3589x, TC3589x_EVTCODE_FIFO); /* loop till fifo is empty and no more keys are pressed */ if (kbd_code == TC35893_KEYCODE_FIFO_EMPTY || kbd_code == TC35893_KEYCODE_FIFO_CLEAR) continue; /* valid key is found */ col_index = kbd_code & KP_EVCODE_COL_MASK; row_index = (kbd_code & KP_EVCODE_ROW_MASK) >> KP_ROW_SHIFT; code = MATRIX_SCAN_CODE(row_index, col_index, TC35893_KEYPAD_ROW_SHIFT); up = kbd_code & KP_RELEASE_EVT_MASK; input_event(keypad->input, EV_MSC, MSC_SCAN, code); input_report_key(keypad->input, keypad->keymap[code], !up); input_sync(keypad->input); } /* clear IRQ */ tc3589x_set_bits(tc3589x, TC3589x_KBDIC, 0x0, TC3589x_EVT_INT_CLR | TC3589x_KBD_INT_CLR); /* enable IRQ */ tc3589x_set_bits(tc3589x, TC3589x_KBDMSK, 0x0, TC3589x_EVT_LOSS_INT | TC3589x_EVT_INT); return IRQ_HANDLED; }