1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * Maxim MAX7360 Core Driver 4 * 5 * Copyright 2025 Bootlin 6 * 7 * Authors: 8 * Kamel Bouhara <kamel.bouhara@bootlin.com> 9 * Mathieu Dubois-Briand <mathieu.dubois-briand@bootlin.com> 10 */ 11 12 #include <linux/array_size.h> 13 #include <linux/bits.h> 14 #include <linux/delay.h> 15 #include <linux/device/devres.h> 16 #include <linux/dev_printk.h> 17 #include <linux/err.h> 18 #include <linux/i2c.h> 19 #include <linux/interrupt.h> 20 #include <linux/mfd/core.h> 21 #include <linux/mfd/max7360.h> 22 #include <linux/module.h> 23 #include <linux/regmap.h> 24 #include <linux/types.h> 25 26 static const struct mfd_cell max7360_cells[] = { 27 { .name = "max7360-pinctrl" }, 28 { .name = "max7360-pwm" }, 29 { .name = "max7360-keypad" }, 30 { .name = "max7360-rotary" }, 31 { 32 .name = "max7360-gpo", 33 .of_compatible = "maxim,max7360-gpo", 34 }, 35 { 36 .name = "max7360-gpio", 37 .of_compatible = "maxim,max7360-gpio", 38 }, 39 }; 40 41 static const struct regmap_range max7360_volatile_ranges[] = { 42 regmap_reg_range(MAX7360_REG_KEYFIFO, MAX7360_REG_KEYFIFO), 43 regmap_reg_range(MAX7360_REG_I2C_TIMEOUT, MAX7360_REG_RTR_CNT), 44 }; 45 46 static const struct regmap_access_table max7360_volatile_table = { 47 .yes_ranges = max7360_volatile_ranges, 48 .n_yes_ranges = ARRAY_SIZE(max7360_volatile_ranges), 49 }; 50 51 static const struct regmap_config max7360_regmap_config = { 52 .reg_bits = 8, 53 .val_bits = 8, 54 .max_register = MAX7360_REG_PWMCFG(MAX7360_PORT_PWM_COUNT - 1), 55 .volatile_table = &max7360_volatile_table, 56 .cache_type = REGCACHE_MAPLE, 57 }; 58 59 static int max7360_mask_irqs(struct regmap *regmap) 60 { 61 struct device *dev = regmap_get_device(regmap); 62 unsigned int val; 63 int ret; 64 65 /* 66 * GPIO/PWM interrupts are not masked on reset: as the MAX7360 "INTI" 67 * interrupt line is shared between GPIOs and rotary encoder, this could 68 * result in repeated spurious interrupts on the rotary encoder driver 69 * if the GPIO driver is not loaded. Mask them now to avoid this 70 * situation. 71 */ 72 for (unsigned int i = 0; i < MAX7360_PORT_PWM_COUNT; i++) { 73 ret = regmap_write_bits(regmap, MAX7360_REG_PWMCFG(i), 74 MAX7360_PORT_CFG_INTERRUPT_MASK, 75 MAX7360_PORT_CFG_INTERRUPT_MASK); 76 if (ret) 77 return dev_err_probe(dev, ret, 78 "Failed to write MAX7360 port configuration\n"); 79 } 80 81 /* Read GPIO in register, to ACK any pending IRQ. */ 82 ret = regmap_read(regmap, MAX7360_REG_GPIOIN, &val); 83 if (ret) 84 return dev_err_probe(dev, ret, "Failed to read GPIO values\n"); 85 86 return 0; 87 } 88 89 static int max7360_reset(struct regmap *regmap) 90 { 91 struct device *dev = regmap_get_device(regmap); 92 int ret; 93 94 ret = regmap_write(regmap, MAX7360_REG_GPIOCFG, MAX7360_GPIO_CFG_GPIO_RST); 95 if (ret) { 96 dev_err(dev, "Failed to reset GPIO configuration: %x\n", ret); 97 return ret; 98 } 99 100 ret = regcache_drop_region(regmap, MAX7360_REG_GPIOCFG, MAX7360_REG_GPIO_LAST); 101 if (ret) { 102 dev_err(dev, "Failed to drop regmap cache: %x\n", ret); 103 return ret; 104 } 105 106 ret = regmap_write(regmap, MAX7360_REG_SLEEP, 0); 107 if (ret) { 108 dev_err(dev, "Failed to reset autosleep configuration: %x\n", ret); 109 return ret; 110 } 111 112 ret = regmap_write(regmap, MAX7360_REG_DEBOUNCE, 0); 113 if (ret) 114 dev_err(dev, "Failed to reset GPO port count: %x\n", ret); 115 116 return ret; 117 } 118 119 static int max7360_probe(struct i2c_client *client) 120 { 121 struct device *dev = &client->dev; 122 struct regmap *regmap; 123 int ret; 124 125 regmap = devm_regmap_init_i2c(client, &max7360_regmap_config); 126 if (IS_ERR(regmap)) 127 return dev_err_probe(dev, PTR_ERR(regmap), "Failed to initialise regmap\n"); 128 129 ret = max7360_reset(regmap); 130 if (ret) 131 return dev_err_probe(dev, ret, "Failed to reset device\n"); 132 133 /* Get the device out of shutdown mode. */ 134 ret = regmap_write_bits(regmap, MAX7360_REG_GPIOCFG, 135 MAX7360_GPIO_CFG_GPIO_EN, 136 MAX7360_GPIO_CFG_GPIO_EN); 137 if (ret) 138 return dev_err_probe(dev, ret, "Failed to enable GPIO and PWM module\n"); 139 140 ret = max7360_mask_irqs(regmap); 141 if (ret) 142 return dev_err_probe(dev, ret, "Could not mask interrupts\n"); 143 144 ret = devm_mfd_add_devices(dev, PLATFORM_DEVID_NONE, 145 max7360_cells, ARRAY_SIZE(max7360_cells), 146 NULL, 0, NULL); 147 if (ret) 148 return dev_err_probe(dev, ret, "Failed to register child devices\n"); 149 150 return 0; 151 } 152 153 static const struct of_device_id max7360_dt_match[] = { 154 { .compatible = "maxim,max7360" }, 155 {} 156 }; 157 MODULE_DEVICE_TABLE(of, max7360_dt_match); 158 159 static struct i2c_driver max7360_driver = { 160 .driver = { 161 .name = "max7360", 162 .of_match_table = max7360_dt_match, 163 }, 164 .probe = max7360_probe, 165 }; 166 module_i2c_driver(max7360_driver); 167 168 MODULE_DESCRIPTION("Maxim MAX7360 I2C IO Expander core driver"); 169 MODULE_AUTHOR("Kamel Bouhara <kamel.bouhara@bootlin.com>"); 170 MODULE_LICENSE("GPL"); 171