1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * Copyright (c) 2021, The Linux Foundation. All rights reserved. 4 */ 5 6 #include <linux/bitops.h> 7 #include <linux/gpio/consumer.h> 8 #include <linux/i2c.h> 9 #include <linux/interrupt.h> 10 #include <linux/ioport.h> 11 #include <linux/irq.h> 12 #include <linux/irqdomain.h> 13 #include <linux/mfd/core.h> 14 #include <linux/module.h> 15 #include <linux/of.h> 16 #include <linux/of_platform.h> 17 #include <linux/pinctrl/consumer.h> 18 #include <linux/regmap.h> 19 #include <linux/slab.h> 20 21 #define I2C_INTR_STATUS_BASE 0x0550 22 #define INT_RT_STS_OFFSET 0x10 23 #define INT_SET_TYPE_OFFSET 0x11 24 #define INT_POL_HIGH_OFFSET 0x12 25 #define INT_POL_LOW_OFFSET 0x13 26 #define INT_LATCHED_CLR_OFFSET 0x14 27 #define INT_EN_SET_OFFSET 0x15 28 #define INT_EN_CLR_OFFSET 0x16 29 #define INT_LATCHED_STS_OFFSET 0x18 30 31 enum { 32 PM8008_MISC, 33 PM8008_TEMP_ALARM, 34 PM8008_GPIO1, 35 PM8008_GPIO2, 36 PM8008_NUM_PERIPHS, 37 }; 38 39 #define PM8008_PERIPH_0_BASE 0x900 40 #define PM8008_PERIPH_1_BASE 0x2400 41 #define PM8008_PERIPH_2_BASE 0xc000 42 #define PM8008_PERIPH_3_BASE 0xc100 43 44 #define PM8008_TEMP_ALARM_ADDR PM8008_PERIPH_1_BASE 45 #define PM8008_GPIO1_ADDR PM8008_PERIPH_2_BASE 46 #define PM8008_GPIO2_ADDR PM8008_PERIPH_3_BASE 47 48 /* PM8008 IRQ numbers */ 49 #define PM8008_IRQ_MISC_UVLO 0 50 #define PM8008_IRQ_MISC_OVLO 1 51 #define PM8008_IRQ_MISC_OTST2 2 52 #define PM8008_IRQ_MISC_OTST3 3 53 #define PM8008_IRQ_MISC_LDO_OCP 4 54 #define PM8008_IRQ_TEMP_ALARM 5 55 #define PM8008_IRQ_GPIO1 6 56 #define PM8008_IRQ_GPIO2 7 57 58 enum { 59 SET_TYPE_INDEX, 60 POLARITY_HI_INDEX, 61 POLARITY_LO_INDEX, 62 }; 63 64 static const unsigned int pm8008_config_regs[] = { 65 INT_SET_TYPE_OFFSET, 66 INT_POL_HIGH_OFFSET, 67 INT_POL_LOW_OFFSET, 68 }; 69 70 #define _IRQ(_irq, _off, _mask, _types) \ 71 [_irq] = { \ 72 .reg_offset = (_off), \ 73 .mask = (_mask), \ 74 .type = { \ 75 .type_reg_offset = (_off), \ 76 .types_supported = (_types), \ 77 }, \ 78 } 79 80 static const struct regmap_irq pm8008_irqs[] = { 81 _IRQ(PM8008_IRQ_MISC_UVLO, PM8008_MISC, BIT(0), IRQ_TYPE_EDGE_RISING), 82 _IRQ(PM8008_IRQ_MISC_OVLO, PM8008_MISC, BIT(1), IRQ_TYPE_EDGE_RISING), 83 _IRQ(PM8008_IRQ_MISC_OTST2, PM8008_MISC, BIT(2), IRQ_TYPE_EDGE_RISING), 84 _IRQ(PM8008_IRQ_MISC_OTST3, PM8008_MISC, BIT(3), IRQ_TYPE_EDGE_RISING), 85 _IRQ(PM8008_IRQ_MISC_LDO_OCP, PM8008_MISC, BIT(4), IRQ_TYPE_EDGE_RISING), 86 _IRQ(PM8008_IRQ_TEMP_ALARM, PM8008_TEMP_ALARM,BIT(0), IRQ_TYPE_SENSE_MASK), 87 _IRQ(PM8008_IRQ_GPIO1, PM8008_GPIO1, BIT(0), IRQ_TYPE_SENSE_MASK), 88 _IRQ(PM8008_IRQ_GPIO2, PM8008_GPIO2, BIT(0), IRQ_TYPE_SENSE_MASK), 89 }; 90 91 static const unsigned int pm8008_periph_base[] = { 92 PM8008_PERIPH_0_BASE, 93 PM8008_PERIPH_1_BASE, 94 PM8008_PERIPH_2_BASE, 95 PM8008_PERIPH_3_BASE, 96 }; 97 98 static unsigned int pm8008_get_irq_reg(struct regmap_irq_chip_data *data, 99 unsigned int base, int index) 100 { 101 /* Simple linear addressing for the main status register */ 102 if (base == I2C_INTR_STATUS_BASE) 103 return base + index; 104 105 return pm8008_periph_base[index] + base; 106 } 107 108 static int pm8008_set_type_config(unsigned int **buf, unsigned int type, 109 const struct regmap_irq *irq_data, int idx, 110 void *irq_drv_data) 111 { 112 switch (type) { 113 case IRQ_TYPE_EDGE_FALLING: 114 case IRQ_TYPE_LEVEL_LOW: 115 buf[POLARITY_HI_INDEX][idx] &= ~irq_data->mask; 116 buf[POLARITY_LO_INDEX][idx] |= irq_data->mask; 117 break; 118 119 case IRQ_TYPE_EDGE_RISING: 120 case IRQ_TYPE_LEVEL_HIGH: 121 buf[POLARITY_HI_INDEX][idx] |= irq_data->mask; 122 buf[POLARITY_LO_INDEX][idx] &= ~irq_data->mask; 123 break; 124 125 case IRQ_TYPE_EDGE_BOTH: 126 buf[POLARITY_HI_INDEX][idx] |= irq_data->mask; 127 buf[POLARITY_LO_INDEX][idx] |= irq_data->mask; 128 break; 129 130 default: 131 return -EINVAL; 132 } 133 134 if (type & IRQ_TYPE_EDGE_BOTH) 135 buf[SET_TYPE_INDEX][idx] |= irq_data->mask; 136 else 137 buf[SET_TYPE_INDEX][idx] &= ~irq_data->mask; 138 139 return 0; 140 } 141 142 static const struct regmap_irq_chip pm8008_irq_chip = { 143 .name = "pm8008", 144 .main_status = I2C_INTR_STATUS_BASE, 145 .num_main_regs = 1, 146 .irqs = pm8008_irqs, 147 .num_irqs = ARRAY_SIZE(pm8008_irqs), 148 .num_regs = PM8008_NUM_PERIPHS, 149 .status_base = INT_LATCHED_STS_OFFSET, 150 .mask_base = INT_EN_CLR_OFFSET, 151 .unmask_base = INT_EN_SET_OFFSET, 152 .mask_unmask_non_inverted = true, 153 .ack_base = INT_LATCHED_CLR_OFFSET, 154 .config_base = pm8008_config_regs, 155 .num_config_bases = ARRAY_SIZE(pm8008_config_regs), 156 .num_config_regs = PM8008_NUM_PERIPHS, 157 .set_type_config = pm8008_set_type_config, 158 .get_irq_reg = pm8008_get_irq_reg, 159 }; 160 161 static const struct regmap_config qcom_mfd_regmap_cfg = { 162 .name = "primary", 163 .reg_bits = 16, 164 .val_bits = 8, 165 .max_register = 0xffff, 166 }; 167 168 static const struct regmap_config pm8008_regmap_cfg_2 = { 169 .name = "secondary", 170 .reg_bits = 16, 171 .val_bits = 8, 172 .max_register = 0xffff, 173 }; 174 175 static const struct resource pm8008_temp_res[] = { 176 DEFINE_RES_MEM(PM8008_TEMP_ALARM_ADDR, 0x100), 177 DEFINE_RES_IRQ(PM8008_IRQ_TEMP_ALARM), 178 }; 179 180 static const struct mfd_cell pm8008_cells[] = { 181 MFD_CELL_NAME("pm8008-regulator"), 182 MFD_CELL_RES("qpnp-temp-alarm", pm8008_temp_res), 183 MFD_CELL_NAME("pm8008-gpio"), 184 }; 185 186 static void devm_irq_domain_fwnode_release(void *data) 187 { 188 struct fwnode_handle *fwnode = data; 189 190 irq_domain_free_fwnode(fwnode); 191 } 192 193 static int pm8008_probe(struct i2c_client *client) 194 { 195 struct regmap_irq_chip_data *irq_data; 196 struct device *dev = &client->dev; 197 struct regmap *regmap, *regmap2; 198 struct fwnode_handle *fwnode; 199 struct i2c_client *dummy; 200 struct gpio_desc *reset; 201 char *name; 202 int ret; 203 204 dummy = devm_i2c_new_dummy_device(dev, client->adapter, client->addr + 1); 205 if (IS_ERR(dummy)) { 206 ret = PTR_ERR(dummy); 207 dev_err(dev, "failed to claim second address: %d\n", ret); 208 return ret; 209 } 210 211 regmap2 = devm_regmap_init_i2c(dummy, &qcom_mfd_regmap_cfg); 212 if (IS_ERR(regmap2)) 213 return PTR_ERR(regmap2); 214 215 ret = regmap_attach_dev(dev, regmap2, &pm8008_regmap_cfg_2); 216 if (ret) 217 return ret; 218 219 /* Default regmap must be attached last. */ 220 regmap = devm_regmap_init_i2c(client, &qcom_mfd_regmap_cfg); 221 if (IS_ERR(regmap)) 222 return PTR_ERR(regmap); 223 224 reset = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_LOW); 225 if (IS_ERR(reset)) 226 return PTR_ERR(reset); 227 228 /* 229 * The PMIC does not appear to require a post-reset delay, but wait 230 * for a millisecond for now anyway. 231 */ 232 usleep_range(1000, 2000); 233 234 name = devm_kasprintf(dev, GFP_KERNEL, "%pOF-internal", dev->of_node); 235 if (!name) 236 return -ENOMEM; 237 238 name = strreplace(name, '/', ':'); 239 240 fwnode = irq_domain_alloc_named_fwnode(name); 241 if (!fwnode) 242 return -ENOMEM; 243 244 ret = devm_add_action_or_reset(dev, devm_irq_domain_fwnode_release, fwnode); 245 if (ret) 246 return ret; 247 248 ret = devm_regmap_add_irq_chip_fwnode(dev, fwnode, regmap, client->irq, 249 IRQF_SHARED, 0, &pm8008_irq_chip, &irq_data); 250 if (ret) { 251 dev_err(dev, "failed to add IRQ chip: %d\n", ret); 252 return ret; 253 } 254 255 /* Needed by GPIO driver. */ 256 dev_set_drvdata(dev, regmap_irq_get_domain(irq_data)); 257 258 return devm_mfd_add_devices(dev, PLATFORM_DEVID_AUTO, pm8008_cells, 259 ARRAY_SIZE(pm8008_cells), NULL, 0, 260 regmap_irq_get_domain(irq_data)); 261 } 262 263 static const struct of_device_id pm8008_match[] = { 264 { .compatible = "qcom,pm8008", }, 265 { }, 266 }; 267 MODULE_DEVICE_TABLE(of, pm8008_match); 268 269 static struct i2c_driver pm8008_mfd_driver = { 270 .driver = { 271 .name = "pm8008", 272 .of_match_table = pm8008_match, 273 }, 274 .probe = pm8008_probe, 275 }; 276 module_i2c_driver(pm8008_mfd_driver); 277 278 MODULE_DESCRIPTION("QCOM PM8008 Power Management IC driver"); 279 MODULE_LICENSE("GPL v2"); 280