161dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa/* 261dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa * S3C64xx specific support for pinctrl-samsung driver. 361dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa * 461dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa * Copyright (c) 2013 Tomasz Figa <tomasz.figa@gmail.com> 561dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa * 661dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa * Based on pinctrl-exynos.c, please see the file for original copyrights. 761dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa * 861dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa * This program is free software; you can redistribute it and/or modify 961dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa * it under the terms of the GNU General Public License as published by 1061dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa * the Free Software Foundation; either version 2 of the License, or 1161dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa * (at your option) any later version. 1261dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa * 1361dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa * This file contains the Samsung S3C64xx specific information required by the 1461dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa * the Samsung pinctrl/gpiolib driver. It also includes the implementation of 1561dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa * external gpio and wakeup interrupt support. 1661dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa */ 1761dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa 1861dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa#include <linux/module.h> 1961dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa#include <linux/device.h> 2061dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa#include <linux/interrupt.h> 2161dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa#include <linux/irqdomain.h> 2261dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa#include <linux/irq.h> 2361dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa#include <linux/of_irq.h> 2461dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa#include <linux/io.h> 25a0d4262a25966aa34674397ba6b438dc025827efTomasz Figa#include <linux/irqchip/chained_irq.h> 2661dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa#include <linux/slab.h> 2761dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa#include <linux/err.h> 2861dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa 2961dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa#include "pinctrl-samsung.h" 3061dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa 3161dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa#define NUM_EINT0 28 3261dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa#define NUM_EINT0_IRQ 4 3361dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa#define EINT_MAX_PER_REG 16 3461dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa#define EINT_MAX_PER_GROUP 16 3561dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa 3661dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa/* External GPIO and wakeup interrupt related definitions */ 3761dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa#define SVC_GROUP_SHIFT 4 3861dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa#define SVC_GROUP_MASK 0xf 3961dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa#define SVC_NUM_MASK 0xf 4061dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa#define SVC_GROUP(x) ((x >> SVC_GROUP_SHIFT) & \ 4161dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa SVC_GROUP_MASK) 4261dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa 4361dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa#define EINT12CON_REG 0x200 4461dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa#define EINT12MASK_REG 0x240 4561dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa#define EINT12PEND_REG 0x260 4661dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa 4761dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa#define EINT_OFFS(i) ((i) % (2 * EINT_MAX_PER_GROUP)) 4861dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa#define EINT_GROUP(i) ((i) / EINT_MAX_PER_GROUP) 4961dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa#define EINT_REG(g) (4 * ((g) / 2)) 5061dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa 5161dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa#define EINTCON_REG(i) (EINT12CON_REG + EINT_REG(EINT_GROUP(i))) 5261dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa#define EINTMASK_REG(i) (EINT12MASK_REG + EINT_REG(EINT_GROUP(i))) 5361dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa#define EINTPEND_REG(i) (EINT12PEND_REG + EINT_REG(EINT_GROUP(i))) 5461dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa 5561dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa#define SERVICE_REG 0x284 5661dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa#define SERVICEPEND_REG 0x288 5761dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa 5861dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa#define EINT0CON0_REG 0x900 5961dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa#define EINT0MASK_REG 0x920 6061dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa#define EINT0PEND_REG 0x924 6161dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa 6261dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa/* S3C64xx specific external interrupt trigger types */ 6361dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa#define EINT_LEVEL_LOW 0 6461dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa#define EINT_LEVEL_HIGH 1 6561dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa#define EINT_EDGE_FALLING 2 6661dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa#define EINT_EDGE_RISING 4 6761dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa#define EINT_EDGE_BOTH 6 6861dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa#define EINT_CON_MASK 0xF 6961dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa#define EINT_CON_LEN 4 7061dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa 7161dd726131777017348b70bd8576b42994a8ffa2Tomasz Figastatic struct samsung_pin_bank_type bank_type_4bit_off = { 7261dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa .fld_width = { 4, 1, 2, 0, 2, 2, }, 7361dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa .reg_offset = { 0x00, 0x04, 0x08, 0, 0x0c, 0x10, }, 7461dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa}; 7561dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa 7661dd726131777017348b70bd8576b42994a8ffa2Tomasz Figastatic struct samsung_pin_bank_type bank_type_4bit_alive = { 7761dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa .fld_width = { 4, 1, 2, }, 7861dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa .reg_offset = { 0x00, 0x04, 0x08, }, 7961dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa}; 8061dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa 8161dd726131777017348b70bd8576b42994a8ffa2Tomasz Figastatic struct samsung_pin_bank_type bank_type_4bit2_off = { 8261dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa .fld_width = { 4, 1, 2, 0, 2, 2, }, 8361dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa .reg_offset = { 0x00, 0x08, 0x0c, 0, 0x10, 0x14, }, 8461dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa}; 8561dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa 8661dd726131777017348b70bd8576b42994a8ffa2Tomasz Figastatic struct samsung_pin_bank_type bank_type_4bit2_alive = { 8761dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa .fld_width = { 4, 1, 2, }, 8861dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa .reg_offset = { 0x00, 0x08, 0x0c, }, 8961dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa}; 9061dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa 9161dd726131777017348b70bd8576b42994a8ffa2Tomasz Figastatic struct samsung_pin_bank_type bank_type_2bit_off = { 9261dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa .fld_width = { 2, 1, 2, 0, 2, 2, }, 9361dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa .reg_offset = { 0x00, 0x04, 0x08, 0, 0x0c, 0x10, }, 9461dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa}; 9561dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa 9661dd726131777017348b70bd8576b42994a8ffa2Tomasz Figastatic struct samsung_pin_bank_type bank_type_2bit_alive = { 9761dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa .fld_width = { 2, 1, 2, }, 9861dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa .reg_offset = { 0x00, 0x04, 0x08, }, 9961dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa}; 10061dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa 10161dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa#define PIN_BANK_4BIT(pins, reg, id) \ 10261dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa { \ 10361dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa .type = &bank_type_4bit_off, \ 10461dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa .pctl_offset = reg, \ 10561dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa .nr_pins = pins, \ 10661dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa .eint_type = EINT_TYPE_NONE, \ 10761dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa .name = id \ 10861dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa } 10961dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa 11061dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa#define PIN_BANK_4BIT_EINTG(pins, reg, id, eoffs) \ 11161dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa { \ 11261dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa .type = &bank_type_4bit_off, \ 11361dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa .pctl_offset = reg, \ 11461dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa .nr_pins = pins, \ 11561dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa .eint_type = EINT_TYPE_GPIO, \ 11661dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa .eint_func = 7, \ 11761dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa .eint_mask = (1 << (pins)) - 1, \ 11861dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa .eint_offset = eoffs, \ 11961dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa .name = id \ 12061dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa } 12161dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa 12261dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa#define PIN_BANK_4BIT_EINTW(pins, reg, id, eoffs, emask) \ 12361dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa { \ 12461dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa .type = &bank_type_4bit_alive,\ 12561dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa .pctl_offset = reg, \ 12661dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa .nr_pins = pins, \ 12761dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa .eint_type = EINT_TYPE_WKUP, \ 12861dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa .eint_func = 3, \ 12961dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa .eint_mask = emask, \ 13061dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa .eint_offset = eoffs, \ 13161dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa .name = id \ 13261dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa } 13361dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa 13461dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa#define PIN_BANK_4BIT2_EINTG(pins, reg, id, eoffs) \ 13561dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa { \ 13661dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa .type = &bank_type_4bit2_off, \ 13761dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa .pctl_offset = reg, \ 13861dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa .nr_pins = pins, \ 13961dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa .eint_type = EINT_TYPE_GPIO, \ 14061dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa .eint_func = 7, \ 14161dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa .eint_mask = (1 << (pins)) - 1, \ 14261dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa .eint_offset = eoffs, \ 14361dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa .name = id \ 14461dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa } 14561dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa 14661dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa#define PIN_BANK_4BIT2_EINTW(pins, reg, id, eoffs, emask) \ 14761dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa { \ 14861dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa .type = &bank_type_4bit2_alive,\ 14961dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa .pctl_offset = reg, \ 15061dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa .nr_pins = pins, \ 15161dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa .eint_type = EINT_TYPE_WKUP, \ 15261dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa .eint_func = 3, \ 15361dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa .eint_mask = emask, \ 15461dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa .eint_offset = eoffs, \ 15561dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa .name = id \ 15661dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa } 15761dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa 15861dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa#define PIN_BANK_4BIT2_ALIVE(pins, reg, id) \ 15961dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa { \ 16061dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa .type = &bank_type_4bit2_alive,\ 16161dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa .pctl_offset = reg, \ 16261dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa .nr_pins = pins, \ 16361dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa .eint_type = EINT_TYPE_NONE, \ 16461dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa .name = id \ 16561dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa } 16661dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa 16761dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa#define PIN_BANK_2BIT(pins, reg, id) \ 16861dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa { \ 16961dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa .type = &bank_type_2bit_off, \ 17061dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa .pctl_offset = reg, \ 17161dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa .nr_pins = pins, \ 17261dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa .eint_type = EINT_TYPE_NONE, \ 17361dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa .name = id \ 17461dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa } 17561dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa 17661dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa#define PIN_BANK_2BIT_EINTG(pins, reg, id, eoffs, emask) \ 17761dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa { \ 17861dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa .type = &bank_type_2bit_off, \ 17961dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa .pctl_offset = reg, \ 18061dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa .nr_pins = pins, \ 18161dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa .eint_type = EINT_TYPE_GPIO, \ 18261dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa .eint_func = 3, \ 18361dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa .eint_mask = emask, \ 18461dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa .eint_offset = eoffs, \ 18561dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa .name = id \ 18661dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa } 18761dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa 18861dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa#define PIN_BANK_2BIT_EINTW(pins, reg, id, eoffs) \ 18961dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa { \ 19061dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa .type = &bank_type_2bit_alive,\ 19161dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa .pctl_offset = reg, \ 19261dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa .nr_pins = pins, \ 19361dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa .eint_type = EINT_TYPE_WKUP, \ 19461dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa .eint_func = 2, \ 19561dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa .eint_mask = (1 << (pins)) - 1, \ 19661dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa .eint_offset = eoffs, \ 19761dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa .name = id \ 19861dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa } 19961dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa 20061dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa/** 20161dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa * struct s3c64xx_eint0_data: EINT0 common data 20261dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa * @drvdata: pin controller driver data 20361dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa * @domains: IRQ domains of particular EINT0 interrupts 20461dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa * @pins: pin offsets inside of banks of particular EINT0 interrupts 20561dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa */ 20661dd726131777017348b70bd8576b42994a8ffa2Tomasz Figastruct s3c64xx_eint0_data { 20761dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa struct samsung_pinctrl_drv_data *drvdata; 20861dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa struct irq_domain *domains[NUM_EINT0]; 20961dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa u8 pins[NUM_EINT0]; 21061dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa}; 21161dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa 21261dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa/** 21361dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa * struct s3c64xx_eint0_domain_data: EINT0 per-domain data 21461dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa * @bank: pin bank related to the domain 21561dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa * @eints: EINT0 interrupts related to the domain 21661dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa */ 21761dd726131777017348b70bd8576b42994a8ffa2Tomasz Figastruct s3c64xx_eint0_domain_data { 21861dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa struct samsung_pin_bank *bank; 21961dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa u8 eints[]; 22061dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa}; 22161dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa 22261dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa/** 22361dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa * struct s3c64xx_eint_gpio_data: GPIO EINT data 22461dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa * @drvdata: pin controller driver data 22561dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa * @domains: array of domains related to EINT interrupt groups 22661dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa */ 22761dd726131777017348b70bd8576b42994a8ffa2Tomasz Figastruct s3c64xx_eint_gpio_data { 22861dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa struct samsung_pinctrl_drv_data *drvdata; 22961dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa struct irq_domain *domains[]; 23061dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa}; 23161dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa 23261dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa/* 23361dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa * Common functions for S3C64xx EINT configuration 23461dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa */ 23561dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa 23661dd726131777017348b70bd8576b42994a8ffa2Tomasz Figastatic int s3c64xx_irq_get_trigger(unsigned int type) 23761dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa{ 23861dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa int trigger; 23961dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa 24061dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa switch (type) { 24161dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa case IRQ_TYPE_EDGE_RISING: 24261dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa trigger = EINT_EDGE_RISING; 24361dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa break; 24461dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa case IRQ_TYPE_EDGE_FALLING: 24561dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa trigger = EINT_EDGE_FALLING; 24661dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa break; 24761dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa case IRQ_TYPE_EDGE_BOTH: 24861dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa trigger = EINT_EDGE_BOTH; 24961dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa break; 25061dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa case IRQ_TYPE_LEVEL_HIGH: 25161dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa trigger = EINT_LEVEL_HIGH; 25261dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa break; 25361dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa case IRQ_TYPE_LEVEL_LOW: 25461dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa trigger = EINT_LEVEL_LOW; 25561dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa break; 25661dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa default: 25761dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa return -EINVAL; 25861dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa } 25961dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa 26061dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa return trigger; 26161dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa} 26261dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa 26361dd726131777017348b70bd8576b42994a8ffa2Tomasz Figastatic void s3c64xx_irq_set_handler(unsigned int irq, unsigned int type) 26461dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa{ 26561dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa /* Edge- and level-triggered interrupts need different handlers */ 26661dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa if (type & IRQ_TYPE_EDGE_BOTH) 26761dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa __irq_set_handler_locked(irq, handle_edge_irq); 26861dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa else 26961dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa __irq_set_handler_locked(irq, handle_level_irq); 27061dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa} 27161dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa 27261dd726131777017348b70bd8576b42994a8ffa2Tomasz Figastatic void s3c64xx_irq_set_function(struct samsung_pinctrl_drv_data *d, 27361dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa struct samsung_pin_bank *bank, int pin) 27461dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa{ 27561dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa struct samsung_pin_bank_type *bank_type = bank->type; 27661dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa unsigned long flags; 27761dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa void __iomem *reg; 27861dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa u8 shift; 27961dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa u32 mask; 28061dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa u32 val; 28161dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa 28261dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa /* Make sure that pin is configured as interrupt */ 28361dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa reg = d->virt_base + bank->pctl_offset; 28461dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa shift = pin; 28561dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa if (bank_type->fld_width[PINCFG_TYPE_FUNC] * shift >= 32) { 28661dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa /* 4-bit bank type with 2 con regs */ 28761dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa reg += 4; 28861dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa shift -= 8; 28961dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa } 29061dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa 29161dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa shift = shift * bank_type->fld_width[PINCFG_TYPE_FUNC]; 29261dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa mask = (1 << bank_type->fld_width[PINCFG_TYPE_FUNC]) - 1; 29361dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa 29461dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa spin_lock_irqsave(&bank->slock, flags); 29561dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa 29661dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa val = readl(reg); 29761dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa val &= ~(mask << shift); 29861dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa val |= bank->eint_func << shift; 29961dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa writel(val, reg); 30061dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa 30161dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa spin_unlock_irqrestore(&bank->slock, flags); 30261dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa} 30361dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa 30461dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa/* 30561dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa * Functions for EINT GPIO configuration (EINT groups 1-9) 30661dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa */ 30761dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa 30861dd726131777017348b70bd8576b42994a8ffa2Tomasz Figastatic inline void s3c64xx_gpio_irq_set_mask(struct irq_data *irqd, bool mask) 30961dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa{ 31061dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa struct samsung_pin_bank *bank = irq_data_get_irq_chip_data(irqd); 31161dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa struct samsung_pinctrl_drv_data *d = bank->drvdata; 31261dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa unsigned char index = EINT_OFFS(bank->eint_offset) + irqd->hwirq; 31361dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa void __iomem *reg = d->virt_base + EINTMASK_REG(bank->eint_offset); 31461dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa u32 val; 31561dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa 31661dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa val = readl(reg); 31761dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa if (mask) 31861dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa val |= 1 << index; 31961dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa else 32061dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa val &= ~(1 << index); 32161dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa writel(val, reg); 32261dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa} 32361dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa 32461dd726131777017348b70bd8576b42994a8ffa2Tomasz Figastatic void s3c64xx_gpio_irq_unmask(struct irq_data *irqd) 32561dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa{ 32661dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa s3c64xx_gpio_irq_set_mask(irqd, false); 32761dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa} 32861dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa 32961dd726131777017348b70bd8576b42994a8ffa2Tomasz Figastatic void s3c64xx_gpio_irq_mask(struct irq_data *irqd) 33061dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa{ 33161dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa s3c64xx_gpio_irq_set_mask(irqd, true); 33261dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa} 33361dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa 33461dd726131777017348b70bd8576b42994a8ffa2Tomasz Figastatic void s3c64xx_gpio_irq_ack(struct irq_data *irqd) 33561dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa{ 33661dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa struct samsung_pin_bank *bank = irq_data_get_irq_chip_data(irqd); 33761dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa struct samsung_pinctrl_drv_data *d = bank->drvdata; 33861dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa unsigned char index = EINT_OFFS(bank->eint_offset) + irqd->hwirq; 33961dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa void __iomem *reg = d->virt_base + EINTPEND_REG(bank->eint_offset); 34061dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa 34161dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa writel(1 << index, reg); 34261dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa} 34361dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa 34461dd726131777017348b70bd8576b42994a8ffa2Tomasz Figastatic int s3c64xx_gpio_irq_set_type(struct irq_data *irqd, unsigned int type) 34561dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa{ 34661dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa struct samsung_pin_bank *bank = irq_data_get_irq_chip_data(irqd); 34761dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa struct samsung_pinctrl_drv_data *d = bank->drvdata; 34861dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa void __iomem *reg; 34961dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa int trigger; 35061dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa u8 shift; 35161dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa u32 val; 35261dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa 35361dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa trigger = s3c64xx_irq_get_trigger(type); 35461dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa if (trigger < 0) { 35561dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa pr_err("unsupported external interrupt type\n"); 35661dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa return -EINVAL; 35761dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa } 35861dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa 35961dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa s3c64xx_irq_set_handler(irqd->irq, type); 36061dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa 36161dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa /* Set up interrupt trigger */ 36261dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa reg = d->virt_base + EINTCON_REG(bank->eint_offset); 36361dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa shift = EINT_OFFS(bank->eint_offset) + irqd->hwirq; 36461dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa shift = 4 * (shift / 4); /* 4 EINTs per trigger selector */ 36561dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa 36661dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa val = readl(reg); 36761dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa val &= ~(EINT_CON_MASK << shift); 36861dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa val |= trigger << shift; 36961dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa writel(val, reg); 37061dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa 37161dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa s3c64xx_irq_set_function(d, bank, irqd->hwirq); 37261dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa 37361dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa return 0; 37461dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa} 37561dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa 37661dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa/* 37761dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa * irq_chip for gpio interrupts. 37861dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa */ 37961dd726131777017348b70bd8576b42994a8ffa2Tomasz Figastatic struct irq_chip s3c64xx_gpio_irq_chip = { 38061dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa .name = "GPIO", 38161dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa .irq_unmask = s3c64xx_gpio_irq_unmask, 38261dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa .irq_mask = s3c64xx_gpio_irq_mask, 38361dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa .irq_ack = s3c64xx_gpio_irq_ack, 38461dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa .irq_set_type = s3c64xx_gpio_irq_set_type, 38561dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa}; 38661dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa 38761dd726131777017348b70bd8576b42994a8ffa2Tomasz Figastatic int s3c64xx_gpio_irq_map(struct irq_domain *h, unsigned int virq, 38861dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa irq_hw_number_t hw) 38961dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa{ 39061dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa struct samsung_pin_bank *bank = h->host_data; 39161dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa 39261dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa if (!(bank->eint_mask & (1 << hw))) 39361dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa return -EINVAL; 39461dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa 39561dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa irq_set_chip_and_handler(virq, 39661dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa &s3c64xx_gpio_irq_chip, handle_level_irq); 39761dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa irq_set_chip_data(virq, bank); 39861dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa set_irq_flags(virq, IRQF_VALID); 39961dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa 40061dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa return 0; 40161dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa} 40261dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa 40361dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa/* 40461dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa * irq domain callbacks for external gpio interrupt controller. 40561dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa */ 40661dd726131777017348b70bd8576b42994a8ffa2Tomasz Figastatic const struct irq_domain_ops s3c64xx_gpio_irqd_ops = { 40761dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa .map = s3c64xx_gpio_irq_map, 40861dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa .xlate = irq_domain_xlate_twocell, 40961dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa}; 41061dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa 41161dd726131777017348b70bd8576b42994a8ffa2Tomasz Figastatic void s3c64xx_eint_gpio_irq(unsigned int irq, struct irq_desc *desc) 41261dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa{ 41361dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa struct irq_chip *chip = irq_get_chip(irq); 41461dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa struct s3c64xx_eint_gpio_data *data = irq_get_handler_data(irq); 41561dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa struct samsung_pinctrl_drv_data *drvdata = data->drvdata; 41661dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa 41761dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa chained_irq_enter(chip, desc); 41861dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa 41961dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa do { 42061dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa unsigned int svc; 42161dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa unsigned int group; 42261dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa unsigned int pin; 42361dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa unsigned int virq; 42461dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa 42561dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa svc = readl(drvdata->virt_base + SERVICE_REG); 42661dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa group = SVC_GROUP(svc); 42761dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa pin = svc & SVC_NUM_MASK; 42861dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa 42961dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa if (!group) 43061dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa break; 43161dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa 43261dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa /* Group 1 is used for two pin banks */ 43361dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa if (group == 1) { 43461dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa if (pin < 8) 43561dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa group = 0; 43661dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa else 43761dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa pin -= 8; 43861dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa } 43961dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa 44061dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa virq = irq_linear_revmap(data->domains[group], pin); 44161dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa /* 44261dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa * Something must be really wrong if an unmapped EINT 44361dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa * was unmasked... 44461dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa */ 44561dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa BUG_ON(!virq); 44661dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa 44761dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa generic_handle_irq(virq); 44861dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa } while (1); 44961dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa 45061dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa chained_irq_exit(chip, desc); 45161dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa} 45261dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa 45361dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa/** 45461dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa * s3c64xx_eint_gpio_init() - setup handling of external gpio interrupts. 45561dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa * @d: driver data of samsung pinctrl driver. 45661dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa */ 45761dd726131777017348b70bd8576b42994a8ffa2Tomasz Figastatic int s3c64xx_eint_gpio_init(struct samsung_pinctrl_drv_data *d) 45861dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa{ 45961dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa struct s3c64xx_eint_gpio_data *data; 46061dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa struct samsung_pin_bank *bank; 46161dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa struct device *dev = d->dev; 46261dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa unsigned int nr_domains; 46361dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa unsigned int i; 46461dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa 46561dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa if (!d->irq) { 46661dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa dev_err(dev, "irq number not available\n"); 46761dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa return -EINVAL; 46861dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa } 46961dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa 47061dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa nr_domains = 0; 47161dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa bank = d->ctrl->pin_banks; 47261dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa for (i = 0; i < d->ctrl->nr_banks; ++i, ++bank) { 47361dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa unsigned int nr_eints; 47461dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa unsigned int mask; 47561dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa 47661dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa if (bank->eint_type != EINT_TYPE_GPIO) 47761dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa continue; 47861dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa 47961dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa mask = bank->eint_mask; 48061dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa nr_eints = fls(mask); 48161dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa 48261dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa bank->irq_domain = irq_domain_add_linear(bank->of_node, 48361dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa nr_eints, &s3c64xx_gpio_irqd_ops, bank); 48461dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa if (!bank->irq_domain) { 48561dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa dev_err(dev, "gpio irq domain add failed\n"); 48661dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa return -ENXIO; 48761dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa } 48861dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa 48961dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa ++nr_domains; 49061dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa } 49161dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa 49261dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa data = devm_kzalloc(dev, sizeof(*data) 49361dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa + nr_domains * sizeof(*data->domains), GFP_KERNEL); 49461dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa if (!data) { 49561dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa dev_err(dev, "failed to allocate handler data\n"); 49661dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa return -ENOMEM; 49761dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa } 49861dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa data->drvdata = d; 49961dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa 50061dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa bank = d->ctrl->pin_banks; 50161dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa nr_domains = 0; 50261dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa for (i = 0; i < d->ctrl->nr_banks; ++i, ++bank) { 50361dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa if (bank->eint_type != EINT_TYPE_GPIO) 50461dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa continue; 50561dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa 50661dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa data->domains[nr_domains++] = bank->irq_domain; 50761dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa } 50861dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa 50961dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa irq_set_chained_handler(d->irq, s3c64xx_eint_gpio_irq); 51061dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa irq_set_handler_data(d->irq, data); 51161dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa 51261dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa return 0; 51361dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa} 51461dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa 51561dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa/* 51661dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa * Functions for configuration of EINT0 wake-up interrupts 51761dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa */ 51861dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa 51961dd726131777017348b70bd8576b42994a8ffa2Tomasz Figastatic inline void s3c64xx_eint0_irq_set_mask(struct irq_data *irqd, bool mask) 52061dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa{ 52161dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa struct s3c64xx_eint0_domain_data *ddata = 52261dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa irq_data_get_irq_chip_data(irqd); 52361dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa struct samsung_pinctrl_drv_data *d = ddata->bank->drvdata; 52461dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa u32 val; 52561dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa 52661dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa val = readl(d->virt_base + EINT0MASK_REG); 52761dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa if (mask) 52861dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa val |= 1 << ddata->eints[irqd->hwirq]; 52961dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa else 53061dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa val &= ~(1 << ddata->eints[irqd->hwirq]); 53161dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa writel(val, d->virt_base + EINT0MASK_REG); 53261dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa} 53361dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa 53461dd726131777017348b70bd8576b42994a8ffa2Tomasz Figastatic void s3c64xx_eint0_irq_unmask(struct irq_data *irqd) 53561dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa{ 53661dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa s3c64xx_eint0_irq_set_mask(irqd, false); 53761dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa} 53861dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa 53961dd726131777017348b70bd8576b42994a8ffa2Tomasz Figastatic void s3c64xx_eint0_irq_mask(struct irq_data *irqd) 54061dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa{ 54161dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa s3c64xx_eint0_irq_set_mask(irqd, true); 54261dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa} 54361dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa 54461dd726131777017348b70bd8576b42994a8ffa2Tomasz Figastatic void s3c64xx_eint0_irq_ack(struct irq_data *irqd) 54561dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa{ 54661dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa struct s3c64xx_eint0_domain_data *ddata = 54761dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa irq_data_get_irq_chip_data(irqd); 54861dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa struct samsung_pinctrl_drv_data *d = ddata->bank->drvdata; 54961dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa 55061dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa writel(1 << ddata->eints[irqd->hwirq], 55161dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa d->virt_base + EINT0PEND_REG); 55261dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa} 55361dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa 55461dd726131777017348b70bd8576b42994a8ffa2Tomasz Figastatic int s3c64xx_eint0_irq_set_type(struct irq_data *irqd, unsigned int type) 55561dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa{ 55661dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa struct s3c64xx_eint0_domain_data *ddata = 55761dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa irq_data_get_irq_chip_data(irqd); 55861dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa struct samsung_pin_bank *bank = ddata->bank; 55961dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa struct samsung_pinctrl_drv_data *d = bank->drvdata; 56061dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa void __iomem *reg; 56161dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa int trigger; 56261dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa u8 shift; 56361dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa u32 val; 56461dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa 56561dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa trigger = s3c64xx_irq_get_trigger(type); 56661dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa if (trigger < 0) { 56761dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa pr_err("unsupported external interrupt type\n"); 56861dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa return -EINVAL; 56961dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa } 57061dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa 57161dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa s3c64xx_irq_set_handler(irqd->irq, type); 57261dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa 57361dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa /* Set up interrupt trigger */ 57461dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa reg = d->virt_base + EINT0CON0_REG; 57561dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa shift = ddata->eints[irqd->hwirq]; 57661dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa if (shift >= EINT_MAX_PER_REG) { 57761dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa reg += 4; 57861dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa shift -= EINT_MAX_PER_REG; 57961dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa } 58061dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa shift = EINT_CON_LEN * (shift / 2); 58161dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa 58261dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa val = readl(reg); 58361dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa val &= ~(EINT_CON_MASK << shift); 58461dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa val |= trigger << shift; 58561dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa writel(val, reg); 58661dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa 58761dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa s3c64xx_irq_set_function(d, bank, irqd->hwirq); 58861dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa 58961dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa return 0; 59061dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa} 59161dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa 59261dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa/* 59361dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa * irq_chip for wakeup interrupts 59461dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa */ 59561dd726131777017348b70bd8576b42994a8ffa2Tomasz Figastatic struct irq_chip s3c64xx_eint0_irq_chip = { 59661dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa .name = "EINT0", 59761dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa .irq_unmask = s3c64xx_eint0_irq_unmask, 59861dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa .irq_mask = s3c64xx_eint0_irq_mask, 59961dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa .irq_ack = s3c64xx_eint0_irq_ack, 60061dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa .irq_set_type = s3c64xx_eint0_irq_set_type, 60161dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa}; 60261dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa 60361dd726131777017348b70bd8576b42994a8ffa2Tomasz Figastatic inline void s3c64xx_irq_demux_eint(unsigned int irq, 60461dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa struct irq_desc *desc, u32 range) 60561dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa{ 60661dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa struct irq_chip *chip = irq_get_chip(irq); 60761dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa struct s3c64xx_eint0_data *data = irq_get_handler_data(irq); 60861dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa struct samsung_pinctrl_drv_data *drvdata = data->drvdata; 60961dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa unsigned int pend, mask; 61061dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa 61161dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa chained_irq_enter(chip, desc); 61261dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa 61361dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa pend = readl(drvdata->virt_base + EINT0PEND_REG); 61461dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa mask = readl(drvdata->virt_base + EINT0MASK_REG); 61561dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa 61661dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa pend = pend & range & ~mask; 61761dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa pend &= range; 61861dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa 61961dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa while (pend) { 62061dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa unsigned int virq; 62161dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa 62261dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa irq = fls(pend) - 1; 62361dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa pend &= ~(1 << irq); 62461dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa 62561dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa virq = irq_linear_revmap(data->domains[irq], data->pins[irq]); 62661dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa /* 62761dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa * Something must be really wrong if an unmapped EINT 62861dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa * was unmasked... 62961dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa */ 63061dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa BUG_ON(!virq); 63161dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa 63261dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa generic_handle_irq(virq); 63361dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa } 63461dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa 63561dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa chained_irq_exit(chip, desc); 63661dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa} 63761dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa 63861dd726131777017348b70bd8576b42994a8ffa2Tomasz Figastatic void s3c64xx_demux_eint0_3(unsigned int irq, struct irq_desc *desc) 63961dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa{ 64061dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa s3c64xx_irq_demux_eint(irq, desc, 0xf); 64161dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa} 64261dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa 64361dd726131777017348b70bd8576b42994a8ffa2Tomasz Figastatic void s3c64xx_demux_eint4_11(unsigned int irq, struct irq_desc *desc) 64461dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa{ 64561dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa s3c64xx_irq_demux_eint(irq, desc, 0xff0); 64661dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa} 64761dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa 64861dd726131777017348b70bd8576b42994a8ffa2Tomasz Figastatic void s3c64xx_demux_eint12_19(unsigned int irq, struct irq_desc *desc) 64961dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa{ 65061dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa s3c64xx_irq_demux_eint(irq, desc, 0xff000); 65161dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa} 65261dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa 65361dd726131777017348b70bd8576b42994a8ffa2Tomasz Figastatic void s3c64xx_demux_eint20_27(unsigned int irq, struct irq_desc *desc) 65461dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa{ 65561dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa s3c64xx_irq_demux_eint(irq, desc, 0xff00000); 65661dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa} 65761dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa 65861dd726131777017348b70bd8576b42994a8ffa2Tomasz Figastatic irq_flow_handler_t s3c64xx_eint0_handlers[NUM_EINT0_IRQ] = { 65961dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa s3c64xx_demux_eint0_3, 66061dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa s3c64xx_demux_eint4_11, 66161dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa s3c64xx_demux_eint12_19, 66261dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa s3c64xx_demux_eint20_27, 66361dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa}; 66461dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa 66561dd726131777017348b70bd8576b42994a8ffa2Tomasz Figastatic int s3c64xx_eint0_irq_map(struct irq_domain *h, unsigned int virq, 66661dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa irq_hw_number_t hw) 66761dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa{ 66861dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa struct s3c64xx_eint0_domain_data *ddata = h->host_data; 66961dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa struct samsung_pin_bank *bank = ddata->bank; 67061dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa 67161dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa if (!(bank->eint_mask & (1 << hw))) 67261dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa return -EINVAL; 67361dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa 67461dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa irq_set_chip_and_handler(virq, 67561dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa &s3c64xx_eint0_irq_chip, handle_level_irq); 67661dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa irq_set_chip_data(virq, ddata); 67761dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa set_irq_flags(virq, IRQF_VALID); 67861dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa 67961dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa return 0; 68061dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa} 68161dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa 68261dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa/* 68361dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa * irq domain callbacks for external wakeup interrupt controller. 68461dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa */ 68561dd726131777017348b70bd8576b42994a8ffa2Tomasz Figastatic const struct irq_domain_ops s3c64xx_eint0_irqd_ops = { 68661dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa .map = s3c64xx_eint0_irq_map, 68761dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa .xlate = irq_domain_xlate_twocell, 68861dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa}; 68961dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa 69061dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa/* list of external wakeup controllers supported */ 69161dd726131777017348b70bd8576b42994a8ffa2Tomasz Figastatic const struct of_device_id s3c64xx_eint0_irq_ids[] = { 69261dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa { .compatible = "samsung,s3c64xx-wakeup-eint", }, 69361dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa { } 69461dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa}; 69561dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa 69661dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa/** 69761dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa * s3c64xx_eint_eint0_init() - setup handling of external wakeup interrupts. 69861dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa * @d: driver data of samsung pinctrl driver. 69961dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa */ 70061dd726131777017348b70bd8576b42994a8ffa2Tomasz Figastatic int s3c64xx_eint_eint0_init(struct samsung_pinctrl_drv_data *d) 70161dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa{ 70261dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa struct device *dev = d->dev; 70361dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa struct device_node *eint0_np = NULL; 70461dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa struct device_node *np; 70561dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa struct samsung_pin_bank *bank; 70661dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa struct s3c64xx_eint0_data *data; 70761dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa unsigned int i; 70861dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa 70961dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa for_each_child_of_node(dev->of_node, np) { 71061dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa if (of_match_node(s3c64xx_eint0_irq_ids, np)) { 71161dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa eint0_np = np; 71261dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa break; 71361dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa } 71461dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa } 71561dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa if (!eint0_np) 71661dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa return -ENODEV; 71761dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa 71861dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL); 71961dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa if (!data) { 72061dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa dev_err(dev, "could not allocate memory for wkup eint data\n"); 72161dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa return -ENOMEM; 72261dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa } 72361dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa data->drvdata = d; 72461dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa 72561dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa for (i = 0; i < NUM_EINT0_IRQ; ++i) { 72661dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa unsigned int irq; 72761dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa 72861dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa irq = irq_of_parse_and_map(eint0_np, i); 72961dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa if (!irq) { 73061dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa dev_err(dev, "failed to get wakeup EINT IRQ %d\n", i); 73161dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa return -ENXIO; 73261dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa } 73361dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa 73461dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa irq_set_chained_handler(irq, s3c64xx_eint0_handlers[i]); 73561dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa irq_set_handler_data(irq, data); 73661dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa } 73761dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa 73861dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa bank = d->ctrl->pin_banks; 73961dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa for (i = 0; i < d->ctrl->nr_banks; ++i, ++bank) { 74061dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa struct s3c64xx_eint0_domain_data *ddata; 74161dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa unsigned int nr_eints; 74261dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa unsigned int mask; 74361dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa unsigned int irq; 74461dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa unsigned int pin; 74561dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa 74661dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa if (bank->eint_type != EINT_TYPE_WKUP) 74761dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa continue; 74861dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa 74961dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa mask = bank->eint_mask; 75061dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa nr_eints = fls(mask); 75161dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa 75261dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa ddata = devm_kzalloc(dev, 75361dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa sizeof(*ddata) + nr_eints, GFP_KERNEL); 75461dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa if (!ddata) { 75561dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa dev_err(dev, "failed to allocate domain data\n"); 75661dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa return -ENOMEM; 75761dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa } 75861dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa ddata->bank = bank; 75961dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa 76061dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa bank->irq_domain = irq_domain_add_linear(bank->of_node, 76161dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa nr_eints, &s3c64xx_eint0_irqd_ops, ddata); 76261dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa if (!bank->irq_domain) { 76361dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa dev_err(dev, "wkup irq domain add failed\n"); 76461dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa return -ENXIO; 76561dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa } 76661dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa 76761dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa irq = bank->eint_offset; 76861dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa mask = bank->eint_mask; 76961dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa for (pin = 0; mask; ++pin, mask >>= 1) { 77061dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa if (!(mask & 1)) 77161dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa continue; 77261dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa data->domains[irq] = bank->irq_domain; 77361dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa data->pins[irq] = pin; 77461dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa ddata->eints[pin] = irq; 77561dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa ++irq; 77661dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa } 77761dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa } 77861dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa 77961dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa return 0; 78061dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa} 78161dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa 78261dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa/* pin banks of s3c64xx pin-controller 0 */ 78361dd726131777017348b70bd8576b42994a8ffa2Tomasz Figastatic struct samsung_pin_bank s3c64xx_pin_banks0[] = { 78461dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa PIN_BANK_4BIT_EINTG(8, 0x000, "gpa", 0), 78561dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa PIN_BANK_4BIT_EINTG(7, 0x020, "gpb", 8), 78661dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa PIN_BANK_4BIT_EINTG(8, 0x040, "gpc", 16), 78761dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa PIN_BANK_4BIT_EINTG(5, 0x060, "gpd", 32), 78861dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa PIN_BANK_4BIT(5, 0x080, "gpe"), 78961dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa PIN_BANK_2BIT_EINTG(16, 0x0a0, "gpf", 48, 0x3fff), 79061dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa PIN_BANK_4BIT_EINTG(7, 0x0c0, "gpg", 64), 79161dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa PIN_BANK_4BIT2_EINTG(10, 0x0e0, "gph", 80), 79261dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa PIN_BANK_2BIT(16, 0x100, "gpi"), 79361dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa PIN_BANK_2BIT(12, 0x120, "gpj"), 79461dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa PIN_BANK_4BIT2_ALIVE(16, 0x800, "gpk"), 79561dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa PIN_BANK_4BIT2_EINTW(15, 0x810, "gpl", 16, 0x7f00), 79661dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa PIN_BANK_4BIT_EINTW(6, 0x820, "gpm", 23, 0x1f), 79761dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa PIN_BANK_2BIT_EINTW(16, 0x830, "gpn", 0), 79861dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa PIN_BANK_2BIT_EINTG(16, 0x140, "gpo", 96, 0xffff), 79961dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa PIN_BANK_2BIT_EINTG(15, 0x160, "gpp", 112, 0x7fff), 80061dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa PIN_BANK_2BIT_EINTG(9, 0x180, "gpq", 128, 0x1ff), 80161dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa}; 80261dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa 80361dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa/* 80461dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa * Samsung pinctrl driver data for S3C64xx SoC. S3C64xx SoC includes 80561dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa * one gpio/pin-mux/pinconfig controller. 80661dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa */ 80761dd726131777017348b70bd8576b42994a8ffa2Tomasz Figastruct samsung_pin_ctrl s3c64xx_pin_ctrl[] = { 80861dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa { 80961dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa /* pin-controller instance 1 data */ 81061dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa .pin_banks = s3c64xx_pin_banks0, 81161dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa .nr_banks = ARRAY_SIZE(s3c64xx_pin_banks0), 81261dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa .eint_gpio_init = s3c64xx_eint_gpio_init, 81361dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa .eint_wkup_init = s3c64xx_eint_eint0_init, 81461dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa .label = "S3C64xx-GPIO", 81561dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa }, 81661dd726131777017348b70bd8576b42994a8ffa2Tomasz Figa}; 817