^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0+
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) //
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) // S3C64xx specific support for pinctrl-samsung driver.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) //
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) // Copyright (c) 2013 Tomasz Figa <tomasz.figa@gmail.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) //
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) // Based on pinctrl-exynos.c, please see the file for original copyrights.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) //
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) // This file contains the Samsung S3C64xx specific information required by the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) // the Samsung pinctrl/gpiolib driver. It also includes the implementation of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) // external gpio and wakeup interrupt support.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/init.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <linux/interrupt.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <linux/irqdomain.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <linux/irq.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <linux/of_irq.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include <linux/io.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include <linux/irqchip/chained_irq.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #include <linux/err.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #include "pinctrl-samsung.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #define NUM_EINT0 28
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) #define NUM_EINT0_IRQ 4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) #define EINT_MAX_PER_REG 16
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) #define EINT_MAX_PER_GROUP 16
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) /* External GPIO and wakeup interrupt related definitions */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) #define SVC_GROUP_SHIFT 4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) #define SVC_GROUP_MASK 0xf
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) #define SVC_NUM_MASK 0xf
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) #define SVC_GROUP(x) ((x >> SVC_GROUP_SHIFT) & \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) SVC_GROUP_MASK)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) #define EINT12CON_REG 0x200
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) #define EINT12MASK_REG 0x240
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) #define EINT12PEND_REG 0x260
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) #define EINT_OFFS(i) ((i) % (2 * EINT_MAX_PER_GROUP))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) #define EINT_GROUP(i) ((i) / EINT_MAX_PER_GROUP)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) #define EINT_REG(g) (4 * ((g) / 2))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) #define EINTCON_REG(i) (EINT12CON_REG + EINT_REG(EINT_GROUP(i)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) #define EINTMASK_REG(i) (EINT12MASK_REG + EINT_REG(EINT_GROUP(i)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) #define EINTPEND_REG(i) (EINT12PEND_REG + EINT_REG(EINT_GROUP(i)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) #define SERVICE_REG 0x284
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) #define SERVICEPEND_REG 0x288
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) #define EINT0CON0_REG 0x900
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) #define EINT0MASK_REG 0x920
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) #define EINT0PEND_REG 0x924
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) /* S3C64xx specific external interrupt trigger types */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) #define EINT_LEVEL_LOW 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) #define EINT_LEVEL_HIGH 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) #define EINT_EDGE_FALLING 2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) #define EINT_EDGE_RISING 4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) #define EINT_EDGE_BOTH 6
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) #define EINT_CON_MASK 0xF
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) #define EINT_CON_LEN 4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) static const struct samsung_pin_bank_type bank_type_4bit_off = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) .fld_width = { 4, 1, 2, 0, 2, 2, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) .reg_offset = { 0x00, 0x04, 0x08, 0, 0x0c, 0x10, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) static const struct samsung_pin_bank_type bank_type_4bit_alive = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) .fld_width = { 4, 1, 2, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) .reg_offset = { 0x00, 0x04, 0x08, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) static const struct samsung_pin_bank_type bank_type_4bit2_off = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) .fld_width = { 4, 1, 2, 0, 2, 2, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) .reg_offset = { 0x00, 0x08, 0x0c, 0, 0x10, 0x14, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) static const struct samsung_pin_bank_type bank_type_4bit2_alive = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) .fld_width = { 4, 1, 2, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) .reg_offset = { 0x00, 0x08, 0x0c, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) static const struct samsung_pin_bank_type bank_type_2bit_off = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) .fld_width = { 2, 1, 2, 0, 2, 2, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) .reg_offset = { 0x00, 0x04, 0x08, 0, 0x0c, 0x10, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) static const struct samsung_pin_bank_type bank_type_2bit_alive = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) .fld_width = { 2, 1, 2, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) .reg_offset = { 0x00, 0x04, 0x08, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) #define PIN_BANK_4BIT(pins, reg, id) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) { \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) .type = &bank_type_4bit_off, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) .pctl_offset = reg, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) .nr_pins = pins, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) .eint_type = EINT_TYPE_NONE, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) .name = id \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) #define PIN_BANK_4BIT_EINTG(pins, reg, id, eoffs) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) { \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) .type = &bank_type_4bit_off, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) .pctl_offset = reg, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) .nr_pins = pins, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) .eint_type = EINT_TYPE_GPIO, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) .eint_func = 7, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) .eint_mask = (1 << (pins)) - 1, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) .eint_offset = eoffs, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) .name = id \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) #define PIN_BANK_4BIT_EINTW(pins, reg, id, eoffs, emask) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) { \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) .type = &bank_type_4bit_alive,\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) .pctl_offset = reg, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) .nr_pins = pins, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) .eint_type = EINT_TYPE_WKUP, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) .eint_func = 3, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) .eint_mask = emask, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) .eint_offset = eoffs, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) .name = id \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) #define PIN_BANK_4BIT2_EINTG(pins, reg, id, eoffs) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) { \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) .type = &bank_type_4bit2_off, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) .pctl_offset = reg, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) .nr_pins = pins, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) .eint_type = EINT_TYPE_GPIO, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) .eint_func = 7, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) .eint_mask = (1 << (pins)) - 1, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) .eint_offset = eoffs, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) .name = id \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) #define PIN_BANK_4BIT2_EINTW(pins, reg, id, eoffs, emask) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) { \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) .type = &bank_type_4bit2_alive,\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) .pctl_offset = reg, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) .nr_pins = pins, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) .eint_type = EINT_TYPE_WKUP, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) .eint_func = 3, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) .eint_mask = emask, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) .eint_offset = eoffs, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) .name = id \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) #define PIN_BANK_4BIT2_ALIVE(pins, reg, id) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) { \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) .type = &bank_type_4bit2_alive,\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) .pctl_offset = reg, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) .nr_pins = pins, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) .eint_type = EINT_TYPE_NONE, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) .name = id \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) #define PIN_BANK_2BIT(pins, reg, id) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) { \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) .type = &bank_type_2bit_off, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) .pctl_offset = reg, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) .nr_pins = pins, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) .eint_type = EINT_TYPE_NONE, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) .name = id \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) #define PIN_BANK_2BIT_EINTG(pins, reg, id, eoffs, emask) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) { \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) .type = &bank_type_2bit_off, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) .pctl_offset = reg, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) .nr_pins = pins, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) .eint_type = EINT_TYPE_GPIO, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) .eint_func = 3, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) .eint_mask = emask, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) .eint_offset = eoffs, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) .name = id \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) #define PIN_BANK_2BIT_EINTW(pins, reg, id, eoffs) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) { \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) .type = &bank_type_2bit_alive,\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) .pctl_offset = reg, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) .nr_pins = pins, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) .eint_type = EINT_TYPE_WKUP, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) .eint_func = 2, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) .eint_mask = (1 << (pins)) - 1, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) .eint_offset = eoffs, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) .name = id \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) * struct s3c64xx_eint0_data - EINT0 common data
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) * @drvdata: pin controller driver data
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) * @domains: IRQ domains of particular EINT0 interrupts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) * @pins: pin offsets inside of banks of particular EINT0 interrupts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) struct s3c64xx_eint0_data {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) struct samsung_pinctrl_drv_data *drvdata;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) struct irq_domain *domains[NUM_EINT0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) u8 pins[NUM_EINT0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) * struct s3c64xx_eint0_domain_data - EINT0 per-domain data
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) * @bank: pin bank related to the domain
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) * @eints: EINT0 interrupts related to the domain
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) struct s3c64xx_eint0_domain_data {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) struct samsung_pin_bank *bank;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) u8 eints[];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) * struct s3c64xx_eint_gpio_data - GPIO EINT data
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) * @drvdata: pin controller driver data
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) * @domains: array of domains related to EINT interrupt groups
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) struct s3c64xx_eint_gpio_data {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) struct samsung_pinctrl_drv_data *drvdata;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) struct irq_domain *domains[];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) * Common functions for S3C64xx EINT configuration
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) static int s3c64xx_irq_get_trigger(unsigned int type)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) int trigger;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) switch (type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) case IRQ_TYPE_EDGE_RISING:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) trigger = EINT_EDGE_RISING;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) case IRQ_TYPE_EDGE_FALLING:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) trigger = EINT_EDGE_FALLING;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) case IRQ_TYPE_EDGE_BOTH:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) trigger = EINT_EDGE_BOTH;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) case IRQ_TYPE_LEVEL_HIGH:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) trigger = EINT_LEVEL_HIGH;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) case IRQ_TYPE_LEVEL_LOW:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) trigger = EINT_LEVEL_LOW;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) return trigger;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) static void s3c64xx_irq_set_handler(struct irq_data *d, unsigned int type)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) /* Edge- and level-triggered interrupts need different handlers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) if (type & IRQ_TYPE_EDGE_BOTH)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) irq_set_handler_locked(d, handle_edge_irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) irq_set_handler_locked(d, handle_level_irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) static void s3c64xx_irq_set_function(struct samsung_pinctrl_drv_data *d,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) struct samsung_pin_bank *bank, int pin)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) const struct samsung_pin_bank_type *bank_type = bank->type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) void __iomem *reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) u8 shift;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) u32 mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) u32 val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) /* Make sure that pin is configured as interrupt */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) reg = d->virt_base + bank->pctl_offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) shift = pin;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) if (bank_type->fld_width[PINCFG_TYPE_FUNC] * shift >= 32) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) /* 4-bit bank type with 2 con regs */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) reg += 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) shift -= 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) shift = shift * bank_type->fld_width[PINCFG_TYPE_FUNC];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) mask = (1 << bank_type->fld_width[PINCFG_TYPE_FUNC]) - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) spin_lock_irqsave(&bank->slock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) val = readl(reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) val &= ~(mask << shift);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) val |= bank->eint_func << shift;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) writel(val, reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) spin_unlock_irqrestore(&bank->slock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) * Functions for EINT GPIO configuration (EINT groups 1-9)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) static inline void s3c64xx_gpio_irq_set_mask(struct irq_data *irqd, bool mask)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) struct samsung_pin_bank *bank = irq_data_get_irq_chip_data(irqd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) struct samsung_pinctrl_drv_data *d = bank->drvdata;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) unsigned char index = EINT_OFFS(bank->eint_offset) + irqd->hwirq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) void __iomem *reg = d->virt_base + EINTMASK_REG(bank->eint_offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) u32 val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) val = readl(reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) if (mask)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) val |= 1 << index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) val &= ~(1 << index);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) writel(val, reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) static void s3c64xx_gpio_irq_unmask(struct irq_data *irqd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) s3c64xx_gpio_irq_set_mask(irqd, false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) static void s3c64xx_gpio_irq_mask(struct irq_data *irqd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) s3c64xx_gpio_irq_set_mask(irqd, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) static void s3c64xx_gpio_irq_ack(struct irq_data *irqd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) struct samsung_pin_bank *bank = irq_data_get_irq_chip_data(irqd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) struct samsung_pinctrl_drv_data *d = bank->drvdata;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) unsigned char index = EINT_OFFS(bank->eint_offset) + irqd->hwirq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) void __iomem *reg = d->virt_base + EINTPEND_REG(bank->eint_offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) writel(1 << index, reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) static int s3c64xx_gpio_irq_set_type(struct irq_data *irqd, unsigned int type)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) struct samsung_pin_bank *bank = irq_data_get_irq_chip_data(irqd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) struct samsung_pinctrl_drv_data *d = bank->drvdata;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) void __iomem *reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) int trigger;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) u8 shift;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) u32 val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) trigger = s3c64xx_irq_get_trigger(type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) if (trigger < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) pr_err("unsupported external interrupt type\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) s3c64xx_irq_set_handler(irqd, type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) /* Set up interrupt trigger */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) reg = d->virt_base + EINTCON_REG(bank->eint_offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) shift = EINT_OFFS(bank->eint_offset) + irqd->hwirq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) shift = 4 * (shift / 4); /* 4 EINTs per trigger selector */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) val = readl(reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) val &= ~(EINT_CON_MASK << shift);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) val |= trigger << shift;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) writel(val, reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) s3c64xx_irq_set_function(d, bank, irqd->hwirq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) * irq_chip for gpio interrupts.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) static struct irq_chip s3c64xx_gpio_irq_chip = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) .name = "GPIO",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) .irq_unmask = s3c64xx_gpio_irq_unmask,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) .irq_mask = s3c64xx_gpio_irq_mask,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) .irq_ack = s3c64xx_gpio_irq_ack,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) .irq_set_type = s3c64xx_gpio_irq_set_type,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) static int s3c64xx_gpio_irq_map(struct irq_domain *h, unsigned int virq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) irq_hw_number_t hw)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) struct samsung_pin_bank *bank = h->host_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) if (!(bank->eint_mask & (1 << hw)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) irq_set_chip_and_handler(virq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) &s3c64xx_gpio_irq_chip, handle_level_irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) irq_set_chip_data(virq, bank);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) * irq domain callbacks for external gpio interrupt controller.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) static const struct irq_domain_ops s3c64xx_gpio_irqd_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) .map = s3c64xx_gpio_irq_map,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) .xlate = irq_domain_xlate_twocell,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) static void s3c64xx_eint_gpio_irq(struct irq_desc *desc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) struct irq_chip *chip = irq_desc_get_chip(desc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) struct s3c64xx_eint_gpio_data *data = irq_desc_get_handler_data(desc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) struct samsung_pinctrl_drv_data *drvdata = data->drvdata;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) chained_irq_enter(chip, desc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) unsigned int svc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) unsigned int group;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) unsigned int pin;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) unsigned int virq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) svc = readl(drvdata->virt_base + SERVICE_REG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) group = SVC_GROUP(svc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) pin = svc & SVC_NUM_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) if (!group)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) /* Group 1 is used for two pin banks */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) if (group == 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) if (pin < 8)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) group = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) pin -= 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) virq = irq_linear_revmap(data->domains[group], pin);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) * Something must be really wrong if an unmapped EINT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) * was unmasked...
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) BUG_ON(!virq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) generic_handle_irq(virq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) } while (1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) chained_irq_exit(chip, desc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) * s3c64xx_eint_gpio_init() - setup handling of external gpio interrupts.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) * @d: driver data of samsung pinctrl driver.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) static int s3c64xx_eint_gpio_init(struct samsung_pinctrl_drv_data *d)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) struct s3c64xx_eint_gpio_data *data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) struct samsung_pin_bank *bank;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) struct device *dev = d->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) unsigned int nr_domains;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) unsigned int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) if (!d->irq) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) dev_err(dev, "irq number not available\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) nr_domains = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) bank = d->pin_banks;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) for (i = 0; i < d->nr_banks; ++i, ++bank) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) unsigned int nr_eints;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) unsigned int mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) if (bank->eint_type != EINT_TYPE_GPIO)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) mask = bank->eint_mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) nr_eints = fls(mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) bank->irq_domain = irq_domain_add_linear(bank->of_node,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) nr_eints, &s3c64xx_gpio_irqd_ops, bank);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) if (!bank->irq_domain) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) dev_err(dev, "gpio irq domain add failed\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) return -ENXIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) ++nr_domains;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) data = devm_kzalloc(dev, struct_size(data, domains, nr_domains),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) if (!data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) data->drvdata = d;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) bank = d->pin_banks;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) nr_domains = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) for (i = 0; i < d->nr_banks; ++i, ++bank) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) if (bank->eint_type != EINT_TYPE_GPIO)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) data->domains[nr_domains++] = bank->irq_domain;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) irq_set_chained_handler_and_data(d->irq, s3c64xx_eint_gpio_irq, data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) * Functions for configuration of EINT0 wake-up interrupts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) static inline void s3c64xx_eint0_irq_set_mask(struct irq_data *irqd, bool mask)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) struct s3c64xx_eint0_domain_data *ddata =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) irq_data_get_irq_chip_data(irqd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) struct samsung_pinctrl_drv_data *d = ddata->bank->drvdata;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) u32 val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) val = readl(d->virt_base + EINT0MASK_REG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) if (mask)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) val |= 1 << ddata->eints[irqd->hwirq];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) val &= ~(1 << ddata->eints[irqd->hwirq]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) writel(val, d->virt_base + EINT0MASK_REG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) static void s3c64xx_eint0_irq_unmask(struct irq_data *irqd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) s3c64xx_eint0_irq_set_mask(irqd, false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) static void s3c64xx_eint0_irq_mask(struct irq_data *irqd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) s3c64xx_eint0_irq_set_mask(irqd, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) static void s3c64xx_eint0_irq_ack(struct irq_data *irqd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) struct s3c64xx_eint0_domain_data *ddata =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) irq_data_get_irq_chip_data(irqd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) struct samsung_pinctrl_drv_data *d = ddata->bank->drvdata;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) writel(1 << ddata->eints[irqd->hwirq],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) d->virt_base + EINT0PEND_REG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) static int s3c64xx_eint0_irq_set_type(struct irq_data *irqd, unsigned int type)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) struct s3c64xx_eint0_domain_data *ddata =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) irq_data_get_irq_chip_data(irqd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) struct samsung_pin_bank *bank = ddata->bank;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) struct samsung_pinctrl_drv_data *d = bank->drvdata;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) void __iomem *reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) int trigger;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) u8 shift;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) u32 val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) trigger = s3c64xx_irq_get_trigger(type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) if (trigger < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) pr_err("unsupported external interrupt type\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) s3c64xx_irq_set_handler(irqd, type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) /* Set up interrupt trigger */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) reg = d->virt_base + EINT0CON0_REG;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) shift = ddata->eints[irqd->hwirq];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) if (shift >= EINT_MAX_PER_REG) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) reg += 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) shift -= EINT_MAX_PER_REG;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) shift = EINT_CON_LEN * (shift / 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) val = readl(reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) val &= ~(EINT_CON_MASK << shift);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) val |= trigger << shift;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) writel(val, reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) s3c64xx_irq_set_function(d, bank, irqd->hwirq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) * irq_chip for wakeup interrupts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) static struct irq_chip s3c64xx_eint0_irq_chip = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) .name = "EINT0",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) .irq_unmask = s3c64xx_eint0_irq_unmask,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) .irq_mask = s3c64xx_eint0_irq_mask,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) .irq_ack = s3c64xx_eint0_irq_ack,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) .irq_set_type = s3c64xx_eint0_irq_set_type,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) static inline void s3c64xx_irq_demux_eint(struct irq_desc *desc, u32 range)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) struct irq_chip *chip = irq_desc_get_chip(desc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) struct s3c64xx_eint0_data *data = irq_desc_get_handler_data(desc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) struct samsung_pinctrl_drv_data *drvdata = data->drvdata;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) unsigned int pend, mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) chained_irq_enter(chip, desc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) pend = readl(drvdata->virt_base + EINT0PEND_REG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) mask = readl(drvdata->virt_base + EINT0MASK_REG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) pend = pend & range & ~mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) pend &= range;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) while (pend) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) unsigned int virq, irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) irq = fls(pend) - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) pend &= ~(1 << irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) virq = irq_linear_revmap(data->domains[irq], data->pins[irq]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) * Something must be really wrong if an unmapped EINT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) * was unmasked...
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) BUG_ON(!virq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) generic_handle_irq(virq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) chained_irq_exit(chip, desc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) static void s3c64xx_demux_eint0_3(struct irq_desc *desc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) s3c64xx_irq_demux_eint(desc, 0xf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) static void s3c64xx_demux_eint4_11(struct irq_desc *desc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) s3c64xx_irq_demux_eint(desc, 0xff0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) static void s3c64xx_demux_eint12_19(struct irq_desc *desc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) s3c64xx_irq_demux_eint(desc, 0xff000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) static void s3c64xx_demux_eint20_27(struct irq_desc *desc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) s3c64xx_irq_demux_eint(desc, 0xff00000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) static irq_flow_handler_t s3c64xx_eint0_handlers[NUM_EINT0_IRQ] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) s3c64xx_demux_eint0_3,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) s3c64xx_demux_eint4_11,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) s3c64xx_demux_eint12_19,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) s3c64xx_demux_eint20_27,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) static int s3c64xx_eint0_irq_map(struct irq_domain *h, unsigned int virq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) irq_hw_number_t hw)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) struct s3c64xx_eint0_domain_data *ddata = h->host_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) struct samsung_pin_bank *bank = ddata->bank;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) if (!(bank->eint_mask & (1 << hw)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) irq_set_chip_and_handler(virq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) &s3c64xx_eint0_irq_chip, handle_level_irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) irq_set_chip_data(virq, ddata);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) * irq domain callbacks for external wakeup interrupt controller.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) static const struct irq_domain_ops s3c64xx_eint0_irqd_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) .map = s3c64xx_eint0_irq_map,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) .xlate = irq_domain_xlate_twocell,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) /* list of external wakeup controllers supported */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) static const struct of_device_id s3c64xx_eint0_irq_ids[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) { .compatible = "samsung,s3c64xx-wakeup-eint", },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) { }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) * s3c64xx_eint_eint0_init() - setup handling of external wakeup interrupts.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) * @d: driver data of samsung pinctrl driver.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) static int s3c64xx_eint_eint0_init(struct samsung_pinctrl_drv_data *d)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) struct device *dev = d->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) struct device_node *eint0_np = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) struct device_node *np;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) struct samsung_pin_bank *bank;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) struct s3c64xx_eint0_data *data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) unsigned int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) for_each_child_of_node(dev->of_node, np) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) if (of_match_node(s3c64xx_eint0_irq_ids, np)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) eint0_np = np;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) if (!eint0_np)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) if (!data) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) of_node_put(eint0_np);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) data->drvdata = d;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) for (i = 0; i < NUM_EINT0_IRQ; ++i) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) unsigned int irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) irq = irq_of_parse_and_map(eint0_np, i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) if (!irq) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) dev_err(dev, "failed to get wakeup EINT IRQ %d\n", i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) of_node_put(eint0_np);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) return -ENXIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) irq_set_chained_handler_and_data(irq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) s3c64xx_eint0_handlers[i],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) of_node_put(eint0_np);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) bank = d->pin_banks;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) for (i = 0; i < d->nr_banks; ++i, ++bank) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) struct s3c64xx_eint0_domain_data *ddata;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) unsigned int nr_eints;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733) unsigned int mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) unsigned int irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) unsigned int pin;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) if (bank->eint_type != EINT_TYPE_WKUP)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) mask = bank->eint_mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) nr_eints = fls(mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) ddata = devm_kzalloc(dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) sizeof(*ddata) + nr_eints, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) if (!ddata)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747) ddata->bank = bank;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) bank->irq_domain = irq_domain_add_linear(bank->of_node,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) nr_eints, &s3c64xx_eint0_irqd_ops, ddata);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) if (!bank->irq_domain) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) dev_err(dev, "wkup irq domain add failed\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753) return -ENXIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) irq = bank->eint_offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) mask = bank->eint_mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758) for (pin = 0; mask; ++pin, mask >>= 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759) if (!(mask & 1))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761) data->domains[irq] = bank->irq_domain;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) data->pins[irq] = pin;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763) ddata->eints[pin] = irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764) ++irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) /* pin banks of s3c64xx pin-controller 0 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) static const struct samsung_pin_bank_data s3c64xx_pin_banks0[] __initconst = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773) PIN_BANK_4BIT_EINTG(8, 0x000, "gpa", 0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774) PIN_BANK_4BIT_EINTG(7, 0x020, "gpb", 8),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775) PIN_BANK_4BIT_EINTG(8, 0x040, "gpc", 16),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776) PIN_BANK_4BIT_EINTG(5, 0x060, "gpd", 32),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777) PIN_BANK_4BIT(5, 0x080, "gpe"),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778) PIN_BANK_2BIT_EINTG(16, 0x0a0, "gpf", 48, 0x3fff),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779) PIN_BANK_4BIT_EINTG(7, 0x0c0, "gpg", 64),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780) PIN_BANK_4BIT2_EINTG(10, 0x0e0, "gph", 80),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781) PIN_BANK_2BIT(16, 0x100, "gpi"),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782) PIN_BANK_2BIT(12, 0x120, "gpj"),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) PIN_BANK_4BIT2_ALIVE(16, 0x800, "gpk"),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784) PIN_BANK_4BIT2_EINTW(15, 0x810, "gpl", 16, 0x7f00),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785) PIN_BANK_4BIT_EINTW(6, 0x820, "gpm", 23, 0x1f),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786) PIN_BANK_2BIT_EINTW(16, 0x830, "gpn", 0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787) PIN_BANK_2BIT_EINTG(16, 0x140, "gpo", 96, 0xffff),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788) PIN_BANK_2BIT_EINTG(15, 0x160, "gpp", 112, 0x7fff),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789) PIN_BANK_2BIT_EINTG(9, 0x180, "gpq", 128, 0x1ff),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793) * Samsung pinctrl driver data for S3C64xx SoC. S3C64xx SoC includes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794) * one gpio/pin-mux/pinconfig controller.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796) static const struct samsung_pin_ctrl s3c64xx_pin_ctrl[] __initconst = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798) /* pin-controller instance 1 data */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799) .pin_banks = s3c64xx_pin_banks0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800) .nr_banks = ARRAY_SIZE(s3c64xx_pin_banks0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801) .eint_gpio_init = s3c64xx_eint_gpio_init,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802) .eint_wkup_init = s3c64xx_eint_eint0_init,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806) const struct samsung_pinctrl_of_match_data s3c64xx_of_data __initconst = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807) .ctrl = s3c64xx_pin_ctrl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808) .num_ctrl = ARRAY_SIZE(s3c64xx_pin_ctrl),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809) };