hi6421v600-irq.c (7689B)
1// SPDX-License-Identifier: GPL-2.0 2/* 3 * Device driver for irqs in HISI PMIC IC 4 * 5 * Copyright (c) 2013 Linaro Ltd. 6 * Copyright (c) 2011 Hisilicon. 7 * Copyright (c) 2020-2021 Huawei Technologies Co., Ltd. 8 */ 9 10#include <linux/bitops.h> 11#include <linux/interrupt.h> 12#include <linux/irq.h> 13#include <linux/module.h> 14#include <linux/of_gpio.h> 15#include <linux/platform_device.h> 16#include <linux/slab.h> 17#include <linux/irqdomain.h> 18#include <linux/regmap.h> 19 20struct hi6421v600_irq { 21 struct device *dev; 22 struct irq_domain *domain; 23 int irq; 24 unsigned int *irqs; 25 struct regmap *regmap; 26 27 /* Protect IRQ mask changes */ 28 spinlock_t lock; 29}; 30 31enum hi6421v600_irq_list { 32 OTMP = 0, 33 VBUS_CONNECT, 34 VBUS_DISCONNECT, 35 ALARMON_R, 36 HOLD_6S, 37 HOLD_1S, 38 POWERKEY_UP, 39 POWERKEY_DOWN, 40 OCP_SCP_R, 41 COUL_R, 42 SIM0_HPD_R, 43 SIM0_HPD_F, 44 SIM1_HPD_R, 45 SIM1_HPD_F, 46 47 PMIC_IRQ_LIST_MAX 48}; 49 50#define HISI_IRQ_BANK_SIZE 2 51 52/* 53 * IRQ number for the power key button and mask for both UP and DOWN IRQs 54 */ 55#define HISI_POWERKEY_IRQ_NUM 0 56#define HISI_IRQ_POWERKEY_UP_DOWN (BIT(POWERKEY_DOWN) | BIT(POWERKEY_UP)) 57 58/* 59 * Registers for IRQ address and IRQ mask bits 60 * 61 * Please notice that we need to regmap a larger region, as other 62 * registers are used by the irqs. 63 * See drivers/irq/hi6421-irq.c. 64 */ 65#define SOC_PMIC_IRQ_MASK_0_ADDR 0x0202 66#define SOC_PMIC_IRQ0_ADDR 0x0212 67 68/* 69 * The IRQs are mapped as: 70 * 71 * ====================== ============= ============ ===== 72 * IRQ MASK REGISTER IRQ REGISTER BIT 73 * ====================== ============= ============ ===== 74 * OTMP 0x0202 0x212 bit 0 75 * VBUS_CONNECT 0x0202 0x212 bit 1 76 * VBUS_DISCONNECT 0x0202 0x212 bit 2 77 * ALARMON_R 0x0202 0x212 bit 3 78 * HOLD_6S 0x0202 0x212 bit 4 79 * HOLD_1S 0x0202 0x212 bit 5 80 * POWERKEY_UP 0x0202 0x212 bit 6 81 * POWERKEY_DOWN 0x0202 0x212 bit 7 82 * 83 * OCP_SCP_R 0x0203 0x213 bit 0 84 * COUL_R 0x0203 0x213 bit 1 85 * SIM0_HPD_R 0x0203 0x213 bit 2 86 * SIM0_HPD_F 0x0203 0x213 bit 3 87 * SIM1_HPD_R 0x0203 0x213 bit 4 88 * SIM1_HPD_F 0x0203 0x213 bit 5 89 * ====================== ============= ============ ===== 90 * 91 * Each mask register contains 8 bits. The ancillary macros below 92 * convert a number from 0 to 14 into a register address and a bit mask 93 */ 94#define HISI_IRQ_MASK_REG(irq_data) (SOC_PMIC_IRQ_MASK_0_ADDR + \ 95 (irqd_to_hwirq(irq_data) / BITS_PER_BYTE)) 96#define HISI_IRQ_MASK_BIT(irq_data) BIT(irqd_to_hwirq(irq_data) & (BITS_PER_BYTE - 1)) 97#define HISI_8BITS_MASK 0xff 98 99static irqreturn_t hi6421v600_irq_handler(int irq, void *__priv) 100{ 101 struct hi6421v600_irq *priv = __priv; 102 unsigned long pending; 103 unsigned int in; 104 int i, offset; 105 106 for (i = 0; i < HISI_IRQ_BANK_SIZE; i++) { 107 regmap_read(priv->regmap, SOC_PMIC_IRQ0_ADDR + i, &in); 108 109 /* Mark pending IRQs as handled */ 110 regmap_write(priv->regmap, SOC_PMIC_IRQ0_ADDR + i, in); 111 112 pending = in & HISI_8BITS_MASK; 113 114 if (i == HISI_POWERKEY_IRQ_NUM && 115 (pending & HISI_IRQ_POWERKEY_UP_DOWN) == HISI_IRQ_POWERKEY_UP_DOWN) { 116 /* 117 * If both powerkey down and up IRQs are received, 118 * handle them at the right order 119 */ 120 generic_handle_irq_safe(priv->irqs[POWERKEY_DOWN]); 121 generic_handle_irq_safe(priv->irqs[POWERKEY_UP]); 122 pending &= ~HISI_IRQ_POWERKEY_UP_DOWN; 123 } 124 125 if (!pending) 126 continue; 127 128 for_each_set_bit(offset, &pending, BITS_PER_BYTE) { 129 generic_handle_irq_safe(priv->irqs[offset + i * BITS_PER_BYTE]); 130 } 131 } 132 133 return IRQ_HANDLED; 134} 135 136static void hi6421v600_irq_mask(struct irq_data *d) 137{ 138 struct hi6421v600_irq *priv = irq_data_get_irq_chip_data(d); 139 unsigned long flags; 140 unsigned int data; 141 u32 offset; 142 143 offset = HISI_IRQ_MASK_REG(d); 144 145 spin_lock_irqsave(&priv->lock, flags); 146 147 regmap_read(priv->regmap, offset, &data); 148 data |= HISI_IRQ_MASK_BIT(d); 149 regmap_write(priv->regmap, offset, data); 150 151 spin_unlock_irqrestore(&priv->lock, flags); 152} 153 154static void hi6421v600_irq_unmask(struct irq_data *d) 155{ 156 struct hi6421v600_irq *priv = irq_data_get_irq_chip_data(d); 157 u32 data, offset; 158 unsigned long flags; 159 160 offset = HISI_IRQ_MASK_REG(d); 161 162 spin_lock_irqsave(&priv->lock, flags); 163 164 regmap_read(priv->regmap, offset, &data); 165 data &= ~HISI_IRQ_MASK_BIT(d); 166 regmap_write(priv->regmap, offset, data); 167 168 spin_unlock_irqrestore(&priv->lock, flags); 169} 170 171static struct irq_chip hi6421v600_pmu_irqchip = { 172 .name = "hi6421v600-irq", 173 .irq_mask = hi6421v600_irq_mask, 174 .irq_unmask = hi6421v600_irq_unmask, 175 .irq_disable = hi6421v600_irq_mask, 176 .irq_enable = hi6421v600_irq_unmask, 177}; 178 179static int hi6421v600_irq_map(struct irq_domain *d, unsigned int virq, 180 irq_hw_number_t hw) 181{ 182 struct hi6421v600_irq *priv = d->host_data; 183 184 irq_set_chip_and_handler_name(virq, &hi6421v600_pmu_irqchip, 185 handle_simple_irq, "hi6421v600"); 186 irq_set_chip_data(virq, priv); 187 irq_set_irq_type(virq, IRQ_TYPE_NONE); 188 189 return 0; 190} 191 192static const struct irq_domain_ops hi6421v600_domain_ops = { 193 .map = hi6421v600_irq_map, 194 .xlate = irq_domain_xlate_twocell, 195}; 196 197static void hi6421v600_irq_init(struct hi6421v600_irq *priv) 198{ 199 int i; 200 unsigned int pending; 201 202 /* Mask all IRQs */ 203 for (i = 0; i < HISI_IRQ_BANK_SIZE; i++) 204 regmap_write(priv->regmap, SOC_PMIC_IRQ_MASK_0_ADDR + i, 205 HISI_8BITS_MASK); 206 207 /* Mark all IRQs as handled */ 208 for (i = 0; i < HISI_IRQ_BANK_SIZE; i++) { 209 regmap_read(priv->regmap, SOC_PMIC_IRQ0_ADDR + i, &pending); 210 regmap_write(priv->regmap, SOC_PMIC_IRQ0_ADDR + i, 211 HISI_8BITS_MASK); 212 } 213} 214 215static int hi6421v600_irq_probe(struct platform_device *pdev) 216{ 217 struct device *pmic_dev = pdev->dev.parent; 218 struct device_node *np = pmic_dev->of_node; 219 struct platform_device *pmic_pdev; 220 struct device *dev = &pdev->dev; 221 struct hi6421v600_irq *priv; 222 struct regmap *regmap; 223 unsigned int virq; 224 int i, ret; 225 226 /* 227 * This driver is meant to be called by hi6421-spmi-core, 228 * which should first set drvdata. If this doesn't happen, hit 229 * a warn on and return. 230 */ 231 regmap = dev_get_drvdata(pmic_dev); 232 if (WARN_ON(!regmap)) 233 return -ENODEV; 234 235 priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); 236 if (!priv) 237 return -ENOMEM; 238 239 priv->dev = dev; 240 priv->regmap = regmap; 241 242 spin_lock_init(&priv->lock); 243 244 pmic_pdev = container_of(pmic_dev, struct platform_device, dev); 245 246 priv->irq = platform_get_irq(pmic_pdev, 0); 247 if (priv->irq < 0) { 248 dev_err(dev, "Error %d when getting IRQs\n", priv->irq); 249 return priv->irq; 250 } 251 252 platform_set_drvdata(pdev, priv); 253 254 hi6421v600_irq_init(priv); 255 256 priv->irqs = devm_kzalloc(dev, PMIC_IRQ_LIST_MAX * sizeof(int), GFP_KERNEL); 257 if (!priv->irqs) 258 return -ENOMEM; 259 260 priv->domain = irq_domain_add_simple(np, PMIC_IRQ_LIST_MAX, 0, 261 &hi6421v600_domain_ops, priv); 262 if (!priv->domain) { 263 dev_err(dev, "Failed to create IRQ domain\n"); 264 return -ENODEV; 265 } 266 267 for (i = 0; i < PMIC_IRQ_LIST_MAX; i++) { 268 virq = irq_create_mapping(priv->domain, i); 269 if (!virq) { 270 dev_err(dev, "Failed to map H/W IRQ\n"); 271 return -ENODEV; 272 } 273 priv->irqs[i] = virq; 274 } 275 276 ret = devm_request_threaded_irq(dev, 277 priv->irq, hi6421v600_irq_handler, 278 NULL, 279 IRQF_TRIGGER_LOW | IRQF_SHARED | IRQF_NO_SUSPEND, 280 "pmic", priv); 281 if (ret < 0) { 282 dev_err(dev, "Failed to start IRQ handling thread: error %d\n", 283 ret); 284 return ret; 285 } 286 287 return 0; 288} 289 290static const struct platform_device_id hi6421v600_irq_table[] = { 291 { .name = "hi6421v600-irq" }, 292 {}, 293}; 294MODULE_DEVICE_TABLE(platform, hi6421v600_irq_table); 295 296static struct platform_driver hi6421v600_irq_driver = { 297 .id_table = hi6421v600_irq_table, 298 .driver = { 299 .name = "hi6421v600-irq", 300 }, 301 .probe = hi6421v600_irq_probe, 302}; 303module_platform_driver(hi6421v600_irq_driver); 304 305MODULE_DESCRIPTION("HiSilicon Hi6421v600 IRQ driver"); 306MODULE_LICENSE("GPL v2");