1e6cbbe42SPatrick Rudolph // SPDX-License-Identifier: GPL-2.0-only 2e6cbbe42SPatrick Rudolph /* 3e6cbbe42SPatrick Rudolph * CY8C95X0 20/40/60 pin I2C GPIO port expander with interrupt support 4e6cbbe42SPatrick Rudolph * 5e6cbbe42SPatrick Rudolph * Copyright (C) 2022 9elements GmbH 663e23304SAndy Shevchenko * Authors: Patrick Rudolph <patrick.rudolph@9elements.com> 763e23304SAndy Shevchenko * Naresh Solanki <Naresh.Solanki@9elements.com> 8e6cbbe42SPatrick Rudolph */ 9e6cbbe42SPatrick Rudolph 10785b1bd8SAndy Shevchenko #include <linux/acpi.h> 11e6cbbe42SPatrick Rudolph #include <linux/bitmap.h> 12785b1bd8SAndy Shevchenko #include <linux/dmi.h> 13e6cbbe42SPatrick Rudolph #include <linux/gpio/driver.h> 14e6cbbe42SPatrick Rudolph #include <linux/gpio/consumer.h> 15e6cbbe42SPatrick Rudolph #include <linux/i2c.h> 16e6cbbe42SPatrick Rudolph #include <linux/init.h> 17e6cbbe42SPatrick Rudolph #include <linux/interrupt.h> 188586466eSAndy Shevchenko #include <linux/mod_devicetable.h> 19e6cbbe42SPatrick Rudolph #include <linux/module.h> 208586466eSAndy Shevchenko #include <linux/property.h> 218586466eSAndy Shevchenko #include <linux/regmap.h> 228586466eSAndy Shevchenko #include <linux/regulator/consumer.h> 23*9c0c7525SAndy Shevchenko #include <linux/seq_file.h> 248586466eSAndy Shevchenko 25e6cbbe42SPatrick Rudolph #include <linux/pinctrl/pinctrl.h> 26e6cbbe42SPatrick Rudolph #include <linux/pinctrl/pinconf.h> 27e6cbbe42SPatrick Rudolph #include <linux/pinctrl/pinconf-generic.h> 28e6cbbe42SPatrick Rudolph #include <linux/pinctrl/pinmux.h> 29e6cbbe42SPatrick Rudolph 30e6cbbe42SPatrick Rudolph /* Fast access registers */ 31e6cbbe42SPatrick Rudolph #define CY8C95X0_INPUT 0x00 32e6cbbe42SPatrick Rudolph #define CY8C95X0_OUTPUT 0x08 33e6cbbe42SPatrick Rudolph #define CY8C95X0_INTSTATUS 0x10 34e6cbbe42SPatrick Rudolph 35e6cbbe42SPatrick Rudolph #define CY8C95X0_INPUT_(x) (CY8C95X0_INPUT + (x)) 36e6cbbe42SPatrick Rudolph #define CY8C95X0_OUTPUT_(x) (CY8C95X0_OUTPUT + (x)) 37e6cbbe42SPatrick Rudolph #define CY8C95X0_INTSTATUS_(x) (CY8C95X0_INTSTATUS + (x)) 38e6cbbe42SPatrick Rudolph 39e6cbbe42SPatrick Rudolph /* Port Select configures the port */ 40e6cbbe42SPatrick Rudolph #define CY8C95X0_PORTSEL 0x18 4163e23304SAndy Shevchenko /* Port settings, write PORTSEL first */ 42e6cbbe42SPatrick Rudolph #define CY8C95X0_INTMASK 0x19 43e6cbbe42SPatrick Rudolph #define CY8C95X0_PWMSEL 0x1A 44e6cbbe42SPatrick Rudolph #define CY8C95X0_INVERT 0x1B 45e6cbbe42SPatrick Rudolph #define CY8C95X0_DIRECTION 0x1C 46e6cbbe42SPatrick Rudolph /* Drive mode register change state on writing '1' */ 47e6cbbe42SPatrick Rudolph #define CY8C95X0_DRV_PU 0x1D 48e6cbbe42SPatrick Rudolph #define CY8C95X0_DRV_PD 0x1E 49e6cbbe42SPatrick Rudolph #define CY8C95X0_DRV_ODH 0x1F 50e6cbbe42SPatrick Rudolph #define CY8C95X0_DRV_ODL 0x20 51e6cbbe42SPatrick Rudolph #define CY8C95X0_DRV_PP_FAST 0x21 52e6cbbe42SPatrick Rudolph #define CY8C95X0_DRV_PP_SLOW 0x22 53e6cbbe42SPatrick Rudolph #define CY8C95X0_DRV_HIZ 0x23 54e6cbbe42SPatrick Rudolph #define CY8C95X0_DEVID 0x2E 55e6cbbe42SPatrick Rudolph #define CY8C95X0_WATCHDOG 0x2F 56e6cbbe42SPatrick Rudolph #define CY8C95X0_COMMAND 0x30 57e6cbbe42SPatrick Rudolph 58e6cbbe42SPatrick Rudolph #define CY8C95X0_PIN_TO_OFFSET(x) (((x) >= 20) ? ((x) + 4) : (x)) 59e6cbbe42SPatrick Rudolph 60e6cbbe42SPatrick Rudolph static const struct i2c_device_id cy8c95x0_id[] = { 61e6cbbe42SPatrick Rudolph { "cy8c9520", 20, }, 62e6cbbe42SPatrick Rudolph { "cy8c9540", 40, }, 63e6cbbe42SPatrick Rudolph { "cy8c9560", 60, }, 64e6cbbe42SPatrick Rudolph { } 65e6cbbe42SPatrick Rudolph }; 66e6cbbe42SPatrick Rudolph MODULE_DEVICE_TABLE(i2c, cy8c95x0_id); 67e6cbbe42SPatrick Rudolph 68e6cbbe42SPatrick Rudolph #define OF_CY8C95X(__nrgpio) ((void *)(__nrgpio)) 69e6cbbe42SPatrick Rudolph 70e6cbbe42SPatrick Rudolph static const struct of_device_id cy8c95x0_dt_ids[] = { 71e6cbbe42SPatrick Rudolph { .compatible = "cypress,cy8c9520", .data = OF_CY8C95X(20), }, 72e6cbbe42SPatrick Rudolph { .compatible = "cypress,cy8c9540", .data = OF_CY8C95X(40), }, 73e6cbbe42SPatrick Rudolph { .compatible = "cypress,cy8c9560", .data = OF_CY8C95X(60), }, 74e6cbbe42SPatrick Rudolph { } 75e6cbbe42SPatrick Rudolph }; 76e6cbbe42SPatrick Rudolph MODULE_DEVICE_TABLE(of, cy8c95x0_dt_ids); 77e6cbbe42SPatrick Rudolph 78785b1bd8SAndy Shevchenko static const struct acpi_gpio_params cy8c95x0_irq_gpios = { 0, 0, true }; 79785b1bd8SAndy Shevchenko 80785b1bd8SAndy Shevchenko static const struct acpi_gpio_mapping cy8c95x0_acpi_irq_gpios[] = { 81785b1bd8SAndy Shevchenko { "irq-gpios", &cy8c95x0_irq_gpios, 1, ACPI_GPIO_QUIRK_ABSOLUTE_NUMBER }, 82785b1bd8SAndy Shevchenko { } 83785b1bd8SAndy Shevchenko }; 84785b1bd8SAndy Shevchenko 85785b1bd8SAndy Shevchenko static int cy8c95x0_acpi_get_irq(struct device *dev) 86785b1bd8SAndy Shevchenko { 87785b1bd8SAndy Shevchenko int ret; 88785b1bd8SAndy Shevchenko 89785b1bd8SAndy Shevchenko ret = devm_acpi_dev_add_driver_gpios(dev, cy8c95x0_acpi_irq_gpios); 90785b1bd8SAndy Shevchenko if (ret) 91785b1bd8SAndy Shevchenko dev_warn(dev, "can't add GPIO ACPI mapping\n"); 92785b1bd8SAndy Shevchenko 93785b1bd8SAndy Shevchenko ret = acpi_dev_gpio_irq_get_by(ACPI_COMPANION(dev), "irq-gpios", 0); 94785b1bd8SAndy Shevchenko if (ret < 0) 95785b1bd8SAndy Shevchenko return ret; 96785b1bd8SAndy Shevchenko 97785b1bd8SAndy Shevchenko dev_info(dev, "ACPI interrupt quirk (IRQ %d)\n", ret); 98785b1bd8SAndy Shevchenko return ret; 99785b1bd8SAndy Shevchenko } 100785b1bd8SAndy Shevchenko 101785b1bd8SAndy Shevchenko static const struct dmi_system_id cy8c95x0_dmi_acpi_irq_info[] = { 102785b1bd8SAndy Shevchenko { 103785b1bd8SAndy Shevchenko /* 104785b1bd8SAndy Shevchenko * On Intel Galileo Gen 1 board the IRQ pin is provided 105785b1bd8SAndy Shevchenko * as an absolute number instead of being relative. 106785b1bd8SAndy Shevchenko * Since first controller (gpio-sch.c) and second 107785b1bd8SAndy Shevchenko * (gpio-dwapb.c) are at the fixed bases, we may safely 108785b1bd8SAndy Shevchenko * refer to the number in the global space to get an IRQ 109785b1bd8SAndy Shevchenko * out of it. 110785b1bd8SAndy Shevchenko */ 111785b1bd8SAndy Shevchenko .matches = { 112785b1bd8SAndy Shevchenko DMI_EXACT_MATCH(DMI_BOARD_NAME, "Galileo"), 113785b1bd8SAndy Shevchenko }, 114785b1bd8SAndy Shevchenko }, 115785b1bd8SAndy Shevchenko {} 116785b1bd8SAndy Shevchenko }; 117785b1bd8SAndy Shevchenko 118e6cbbe42SPatrick Rudolph #define MAX_BANK 8 119e6cbbe42SPatrick Rudolph #define BANK_SZ 8 120e6cbbe42SPatrick Rudolph #define MAX_LINE (MAX_BANK * BANK_SZ) 121e6cbbe42SPatrick Rudolph 122e6cbbe42SPatrick Rudolph #define CY8C95X0_GPIO_MASK GENMASK(7, 0) 123e6cbbe42SPatrick Rudolph 124e6cbbe42SPatrick Rudolph /** 125e6cbbe42SPatrick Rudolph * struct cy8c95x0_pinctrl - driver data 126e6cbbe42SPatrick Rudolph * @regmap: Device's regmap 127e6cbbe42SPatrick Rudolph * @irq_lock: IRQ bus lock 128e6cbbe42SPatrick Rudolph * @i2c_lock: Mutex for the device internal mux register 129e6cbbe42SPatrick Rudolph * @irq_mask: I/O bits affected by interrupts 130e6cbbe42SPatrick Rudolph * @irq_trig_raise: I/O bits affected by raising voltage level 131e6cbbe42SPatrick Rudolph * @irq_trig_fall: I/O bits affected by falling voltage level 132e6cbbe42SPatrick Rudolph * @irq_trig_low: I/O bits affected by a low voltage level 133e6cbbe42SPatrick Rudolph * @irq_trig_high: I/O bits affected by a high voltage level 134e6cbbe42SPatrick Rudolph * @push_pull: I/O bits configured as push pull driver 135e6cbbe42SPatrick Rudolph * @shiftmask: Mask used to compensate for Gport2 width 136e6cbbe42SPatrick Rudolph * @nport: Number of Gports in this chip 137e6cbbe42SPatrick Rudolph * @gpio_chip: gpiolib chip 138e6cbbe42SPatrick Rudolph * @driver_data: private driver data 139e6cbbe42SPatrick Rudolph * @regulator: Pointer to the regulator for the IC 140e6cbbe42SPatrick Rudolph * @dev: struct device 141e6cbbe42SPatrick Rudolph * @pctldev: pin controller device 142e6cbbe42SPatrick Rudolph * @pinctrl_desc: pin controller description 143e6cbbe42SPatrick Rudolph * @name: Chip controller name 144e6cbbe42SPatrick Rudolph * @tpin: Total number of pins 145e6cbbe42SPatrick Rudolph */ 146e6cbbe42SPatrick Rudolph struct cy8c95x0_pinctrl { 147e6cbbe42SPatrick Rudolph struct regmap *regmap; 148e6cbbe42SPatrick Rudolph struct mutex irq_lock; 149e6cbbe42SPatrick Rudolph struct mutex i2c_lock; 150e6cbbe42SPatrick Rudolph DECLARE_BITMAP(irq_mask, MAX_LINE); 151e6cbbe42SPatrick Rudolph DECLARE_BITMAP(irq_trig_raise, MAX_LINE); 152e6cbbe42SPatrick Rudolph DECLARE_BITMAP(irq_trig_fall, MAX_LINE); 153e6cbbe42SPatrick Rudolph DECLARE_BITMAP(irq_trig_low, MAX_LINE); 154e6cbbe42SPatrick Rudolph DECLARE_BITMAP(irq_trig_high, MAX_LINE); 155e6cbbe42SPatrick Rudolph DECLARE_BITMAP(push_pull, MAX_LINE); 156e6cbbe42SPatrick Rudolph DECLARE_BITMAP(shiftmask, MAX_LINE); 157e6cbbe42SPatrick Rudolph int nport; 158e6cbbe42SPatrick Rudolph struct gpio_chip gpio_chip; 159e6cbbe42SPatrick Rudolph unsigned long driver_data; 160e6cbbe42SPatrick Rudolph struct regulator *regulator; 161e6cbbe42SPatrick Rudolph struct device *dev; 162e6cbbe42SPatrick Rudolph struct pinctrl_dev *pctldev; 163e6cbbe42SPatrick Rudolph struct pinctrl_desc pinctrl_desc; 164e6cbbe42SPatrick Rudolph char name[32]; 165e6cbbe42SPatrick Rudolph unsigned int tpin; 166e6cbbe42SPatrick Rudolph }; 167e6cbbe42SPatrick Rudolph 168e6cbbe42SPatrick Rudolph static const struct pinctrl_pin_desc cy8c9560_pins[] = { 169e6cbbe42SPatrick Rudolph PINCTRL_PIN(0, "gp00"), 170e6cbbe42SPatrick Rudolph PINCTRL_PIN(1, "gp01"), 171e6cbbe42SPatrick Rudolph PINCTRL_PIN(2, "gp02"), 172e6cbbe42SPatrick Rudolph PINCTRL_PIN(3, "gp03"), 173e6cbbe42SPatrick Rudolph PINCTRL_PIN(4, "gp04"), 174e6cbbe42SPatrick Rudolph PINCTRL_PIN(5, "gp05"), 175e6cbbe42SPatrick Rudolph PINCTRL_PIN(6, "gp06"), 176e6cbbe42SPatrick Rudolph PINCTRL_PIN(7, "gp07"), 177e6cbbe42SPatrick Rudolph 178e6cbbe42SPatrick Rudolph PINCTRL_PIN(8, "gp10"), 179e6cbbe42SPatrick Rudolph PINCTRL_PIN(9, "gp11"), 180e6cbbe42SPatrick Rudolph PINCTRL_PIN(10, "gp12"), 181e6cbbe42SPatrick Rudolph PINCTRL_PIN(11, "gp13"), 182e6cbbe42SPatrick Rudolph PINCTRL_PIN(12, "gp14"), 183e6cbbe42SPatrick Rudolph PINCTRL_PIN(13, "gp15"), 184e6cbbe42SPatrick Rudolph PINCTRL_PIN(14, "gp16"), 185e6cbbe42SPatrick Rudolph PINCTRL_PIN(15, "gp17"), 186e6cbbe42SPatrick Rudolph 187e6cbbe42SPatrick Rudolph PINCTRL_PIN(16, "gp20"), 188e6cbbe42SPatrick Rudolph PINCTRL_PIN(17, "gp21"), 189e6cbbe42SPatrick Rudolph PINCTRL_PIN(18, "gp22"), 190e6cbbe42SPatrick Rudolph PINCTRL_PIN(19, "gp23"), 191e6cbbe42SPatrick Rudolph 192e6cbbe42SPatrick Rudolph PINCTRL_PIN(20, "gp30"), 193e6cbbe42SPatrick Rudolph PINCTRL_PIN(21, "gp31"), 194e6cbbe42SPatrick Rudolph PINCTRL_PIN(22, "gp32"), 195e6cbbe42SPatrick Rudolph PINCTRL_PIN(23, "gp33"), 196e6cbbe42SPatrick Rudolph PINCTRL_PIN(24, "gp34"), 197e6cbbe42SPatrick Rudolph PINCTRL_PIN(25, "gp35"), 198e6cbbe42SPatrick Rudolph PINCTRL_PIN(26, "gp36"), 199e6cbbe42SPatrick Rudolph PINCTRL_PIN(27, "gp37"), 200e6cbbe42SPatrick Rudolph 201e6cbbe42SPatrick Rudolph PINCTRL_PIN(28, "gp40"), 202e6cbbe42SPatrick Rudolph PINCTRL_PIN(29, "gp41"), 203e6cbbe42SPatrick Rudolph PINCTRL_PIN(30, "gp42"), 204e6cbbe42SPatrick Rudolph PINCTRL_PIN(31, "gp43"), 205e6cbbe42SPatrick Rudolph PINCTRL_PIN(32, "gp44"), 206e6cbbe42SPatrick Rudolph PINCTRL_PIN(33, "gp45"), 207e6cbbe42SPatrick Rudolph PINCTRL_PIN(34, "gp46"), 208e6cbbe42SPatrick Rudolph PINCTRL_PIN(35, "gp47"), 209e6cbbe42SPatrick Rudolph 210e6cbbe42SPatrick Rudolph PINCTRL_PIN(36, "gp50"), 211e6cbbe42SPatrick Rudolph PINCTRL_PIN(37, "gp51"), 212e6cbbe42SPatrick Rudolph PINCTRL_PIN(38, "gp52"), 213e6cbbe42SPatrick Rudolph PINCTRL_PIN(39, "gp53"), 214e6cbbe42SPatrick Rudolph PINCTRL_PIN(40, "gp54"), 215e6cbbe42SPatrick Rudolph PINCTRL_PIN(41, "gp55"), 216e6cbbe42SPatrick Rudolph PINCTRL_PIN(42, "gp56"), 217e6cbbe42SPatrick Rudolph PINCTRL_PIN(43, "gp57"), 218e6cbbe42SPatrick Rudolph 219e6cbbe42SPatrick Rudolph PINCTRL_PIN(44, "gp60"), 220e6cbbe42SPatrick Rudolph PINCTRL_PIN(45, "gp61"), 221e6cbbe42SPatrick Rudolph PINCTRL_PIN(46, "gp62"), 222e6cbbe42SPatrick Rudolph PINCTRL_PIN(47, "gp63"), 223e6cbbe42SPatrick Rudolph PINCTRL_PIN(48, "gp64"), 224e6cbbe42SPatrick Rudolph PINCTRL_PIN(49, "gp65"), 225e6cbbe42SPatrick Rudolph PINCTRL_PIN(50, "gp66"), 226e6cbbe42SPatrick Rudolph PINCTRL_PIN(51, "gp67"), 227e6cbbe42SPatrick Rudolph 228e6cbbe42SPatrick Rudolph PINCTRL_PIN(52, "gp70"), 229e6cbbe42SPatrick Rudolph PINCTRL_PIN(53, "gp71"), 230e6cbbe42SPatrick Rudolph PINCTRL_PIN(54, "gp72"), 231e6cbbe42SPatrick Rudolph PINCTRL_PIN(55, "gp73"), 232e6cbbe42SPatrick Rudolph PINCTRL_PIN(56, "gp74"), 233e6cbbe42SPatrick Rudolph PINCTRL_PIN(57, "gp75"), 234e6cbbe42SPatrick Rudolph PINCTRL_PIN(58, "gp76"), 235e6cbbe42SPatrick Rudolph PINCTRL_PIN(59, "gp77"), 236e6cbbe42SPatrick Rudolph }; 237e6cbbe42SPatrick Rudolph 238e6cbbe42SPatrick Rudolph static const char * const cy8c95x0_groups[] = { 239e6cbbe42SPatrick Rudolph "gp00", 240e6cbbe42SPatrick Rudolph "gp01", 241e6cbbe42SPatrick Rudolph "gp02", 242e6cbbe42SPatrick Rudolph "gp03", 243e6cbbe42SPatrick Rudolph "gp04", 244e6cbbe42SPatrick Rudolph "gp05", 245e6cbbe42SPatrick Rudolph "gp06", 246e6cbbe42SPatrick Rudolph "gp07", 247e6cbbe42SPatrick Rudolph 248e6cbbe42SPatrick Rudolph "gp10", 249e6cbbe42SPatrick Rudolph "gp11", 250e6cbbe42SPatrick Rudolph "gp12", 251e6cbbe42SPatrick Rudolph "gp13", 252e6cbbe42SPatrick Rudolph "gp14", 253e6cbbe42SPatrick Rudolph "gp15", 254e6cbbe42SPatrick Rudolph "gp16", 255e6cbbe42SPatrick Rudolph "gp17", 256e6cbbe42SPatrick Rudolph 257e6cbbe42SPatrick Rudolph "gp20", 258e6cbbe42SPatrick Rudolph "gp21", 259e6cbbe42SPatrick Rudolph "gp22", 260e6cbbe42SPatrick Rudolph "gp23", 261e6cbbe42SPatrick Rudolph 262e6cbbe42SPatrick Rudolph "gp30", 263e6cbbe42SPatrick Rudolph "gp31", 264e6cbbe42SPatrick Rudolph "gp32", 265e6cbbe42SPatrick Rudolph "gp33", 266e6cbbe42SPatrick Rudolph "gp34", 267e6cbbe42SPatrick Rudolph "gp35", 268e6cbbe42SPatrick Rudolph "gp36", 269e6cbbe42SPatrick Rudolph "gp37", 270e6cbbe42SPatrick Rudolph 271e6cbbe42SPatrick Rudolph "gp40", 272e6cbbe42SPatrick Rudolph "gp41", 273e6cbbe42SPatrick Rudolph "gp42", 274e6cbbe42SPatrick Rudolph "gp43", 275e6cbbe42SPatrick Rudolph "gp44", 276e6cbbe42SPatrick Rudolph "gp45", 277e6cbbe42SPatrick Rudolph "gp46", 278e6cbbe42SPatrick Rudolph "gp47", 279e6cbbe42SPatrick Rudolph 280e6cbbe42SPatrick Rudolph "gp50", 281e6cbbe42SPatrick Rudolph "gp51", 282e6cbbe42SPatrick Rudolph "gp52", 283e6cbbe42SPatrick Rudolph "gp53", 284e6cbbe42SPatrick Rudolph "gp54", 285e6cbbe42SPatrick Rudolph "gp55", 286e6cbbe42SPatrick Rudolph "gp56", 287e6cbbe42SPatrick Rudolph "gp57", 288e6cbbe42SPatrick Rudolph 289e6cbbe42SPatrick Rudolph "gp60", 290e6cbbe42SPatrick Rudolph "gp61", 291e6cbbe42SPatrick Rudolph "gp62", 292e6cbbe42SPatrick Rudolph "gp63", 293e6cbbe42SPatrick Rudolph "gp64", 294e6cbbe42SPatrick Rudolph "gp65", 295e6cbbe42SPatrick Rudolph "gp66", 296e6cbbe42SPatrick Rudolph "gp67", 297e6cbbe42SPatrick Rudolph 298e6cbbe42SPatrick Rudolph "gp70", 299e6cbbe42SPatrick Rudolph "gp71", 300e6cbbe42SPatrick Rudolph "gp72", 301e6cbbe42SPatrick Rudolph "gp73", 302e6cbbe42SPatrick Rudolph "gp74", 303e6cbbe42SPatrick Rudolph "gp75", 304e6cbbe42SPatrick Rudolph "gp76", 305e6cbbe42SPatrick Rudolph "gp77", 306e6cbbe42SPatrick Rudolph }; 307e6cbbe42SPatrick Rudolph 308e6cbbe42SPatrick Rudolph static inline u8 cypress_get_port(struct cy8c95x0_pinctrl *chip, unsigned int pin) 309e6cbbe42SPatrick Rudolph { 310e6cbbe42SPatrick Rudolph /* Account for GPORT2 which only has 4 bits */ 311e6cbbe42SPatrick Rudolph return CY8C95X0_PIN_TO_OFFSET(pin) / BANK_SZ; 312e6cbbe42SPatrick Rudolph } 313e6cbbe42SPatrick Rudolph 314e6cbbe42SPatrick Rudolph static int cypress_get_pin_mask(struct cy8c95x0_pinctrl *chip, unsigned int pin) 315e6cbbe42SPatrick Rudolph { 316e6cbbe42SPatrick Rudolph /* Account for GPORT2 which only has 4 bits */ 317e6cbbe42SPatrick Rudolph return BIT(CY8C95X0_PIN_TO_OFFSET(pin) % BANK_SZ); 318e6cbbe42SPatrick Rudolph } 319e6cbbe42SPatrick Rudolph 320e6cbbe42SPatrick Rudolph static bool cy8c95x0_readable_register(struct device *dev, unsigned int reg) 321e6cbbe42SPatrick Rudolph { 322e6cbbe42SPatrick Rudolph switch (reg) { 323e6cbbe42SPatrick Rudolph case 0x24 ... 0x27: 324e6cbbe42SPatrick Rudolph return false; 325c3e40952SAndy Shevchenko default: 326e6cbbe42SPatrick Rudolph return true; 327e6cbbe42SPatrick Rudolph } 328c3e40952SAndy Shevchenko } 329e6cbbe42SPatrick Rudolph 330e6cbbe42SPatrick Rudolph static bool cy8c95x0_writeable_register(struct device *dev, unsigned int reg) 331e6cbbe42SPatrick Rudolph { 332e6cbbe42SPatrick Rudolph switch (reg) { 333e6cbbe42SPatrick Rudolph case CY8C95X0_INPUT_(0) ... CY8C95X0_INPUT_(7): 334e6cbbe42SPatrick Rudolph return false; 335e6cbbe42SPatrick Rudolph case CY8C95X0_DEVID: 336e6cbbe42SPatrick Rudolph return false; 337e6cbbe42SPatrick Rudolph case 0x24 ... 0x27: 338e6cbbe42SPatrick Rudolph return false; 339c3e40952SAndy Shevchenko default: 340e6cbbe42SPatrick Rudolph return true; 341e6cbbe42SPatrick Rudolph } 342c3e40952SAndy Shevchenko } 343e6cbbe42SPatrick Rudolph 344e6cbbe42SPatrick Rudolph static bool cy8c95x0_volatile_register(struct device *dev, unsigned int reg) 345e6cbbe42SPatrick Rudolph { 346e6cbbe42SPatrick Rudolph switch (reg) { 347e6cbbe42SPatrick Rudolph case CY8C95X0_INPUT_(0) ... CY8C95X0_INPUT_(7): 348e6cbbe42SPatrick Rudolph case CY8C95X0_INTSTATUS_(0) ... CY8C95X0_INTSTATUS_(7): 349e6cbbe42SPatrick Rudolph case CY8C95X0_INTMASK: 350e6cbbe42SPatrick Rudolph case CY8C95X0_INVERT: 351e6cbbe42SPatrick Rudolph case CY8C95X0_PWMSEL: 352e6cbbe42SPatrick Rudolph case CY8C95X0_DIRECTION: 353e6cbbe42SPatrick Rudolph case CY8C95X0_DRV_PU: 354e6cbbe42SPatrick Rudolph case CY8C95X0_DRV_PD: 355e6cbbe42SPatrick Rudolph case CY8C95X0_DRV_ODH: 356e6cbbe42SPatrick Rudolph case CY8C95X0_DRV_ODL: 357e6cbbe42SPatrick Rudolph case CY8C95X0_DRV_PP_FAST: 358e6cbbe42SPatrick Rudolph case CY8C95X0_DRV_PP_SLOW: 359e6cbbe42SPatrick Rudolph case CY8C95X0_DRV_HIZ: 360e6cbbe42SPatrick Rudolph return true; 361e662d349SAndy Shevchenko default: 362e6cbbe42SPatrick Rudolph return false; 363e6cbbe42SPatrick Rudolph } 364e662d349SAndy Shevchenko } 365e6cbbe42SPatrick Rudolph 366e6cbbe42SPatrick Rudolph static bool cy8c95x0_precious_register(struct device *dev, unsigned int reg) 367e6cbbe42SPatrick Rudolph { 368e6cbbe42SPatrick Rudolph switch (reg) { 369e6cbbe42SPatrick Rudolph case CY8C95X0_INTSTATUS_(0) ... CY8C95X0_INTSTATUS_(7): 370e6cbbe42SPatrick Rudolph return true; 371c3e40952SAndy Shevchenko default: 372e6cbbe42SPatrick Rudolph return false; 373e6cbbe42SPatrick Rudolph } 374c3e40952SAndy Shevchenko } 375e6cbbe42SPatrick Rudolph 376e6cbbe42SPatrick Rudolph static const struct reg_default cy8c95x0_reg_defaults[] = { 3779540a836SAndy Shevchenko { CY8C95X0_OUTPUT_(0), GENMASK(7, 0) }, 3789540a836SAndy Shevchenko { CY8C95X0_OUTPUT_(1), GENMASK(7, 0) }, 3799540a836SAndy Shevchenko { CY8C95X0_OUTPUT_(2), GENMASK(7, 0) }, 3809540a836SAndy Shevchenko { CY8C95X0_OUTPUT_(3), GENMASK(7, 0) }, 3819540a836SAndy Shevchenko { CY8C95X0_OUTPUT_(4), GENMASK(7, 0) }, 3829540a836SAndy Shevchenko { CY8C95X0_OUTPUT_(5), GENMASK(7, 0) }, 3839540a836SAndy Shevchenko { CY8C95X0_OUTPUT_(6), GENMASK(7, 0) }, 3849540a836SAndy Shevchenko { CY8C95X0_OUTPUT_(7), GENMASK(7, 0) }, 385e6cbbe42SPatrick Rudolph { CY8C95X0_PORTSEL, 0 }, 386e6cbbe42SPatrick Rudolph { CY8C95X0_PWMSEL, 0 }, 387e6cbbe42SPatrick Rudolph }; 388e6cbbe42SPatrick Rudolph 389e6cbbe42SPatrick Rudolph static const struct regmap_config cy8c95x0_i2c_regmap = { 390e6cbbe42SPatrick Rudolph .reg_bits = 8, 391e6cbbe42SPatrick Rudolph .val_bits = 8, 392e6cbbe42SPatrick Rudolph 393e6cbbe42SPatrick Rudolph .reg_defaults = cy8c95x0_reg_defaults, 394e6cbbe42SPatrick Rudolph .num_reg_defaults = ARRAY_SIZE(cy8c95x0_reg_defaults), 395e6cbbe42SPatrick Rudolph 396e6cbbe42SPatrick Rudolph .readable_reg = cy8c95x0_readable_register, 397e6cbbe42SPatrick Rudolph .writeable_reg = cy8c95x0_writeable_register, 398e6cbbe42SPatrick Rudolph .volatile_reg = cy8c95x0_volatile_register, 399e6cbbe42SPatrick Rudolph .precious_reg = cy8c95x0_precious_register, 400e6cbbe42SPatrick Rudolph 401e6cbbe42SPatrick Rudolph .cache_type = REGCACHE_FLAT, 402e6cbbe42SPatrick Rudolph .max_register = CY8C95X0_COMMAND, 403e6cbbe42SPatrick Rudolph }; 404e6cbbe42SPatrick Rudolph 405e6cbbe42SPatrick Rudolph static int cy8c95x0_write_regs_mask(struct cy8c95x0_pinctrl *chip, int reg, 406e6cbbe42SPatrick Rudolph unsigned long *val, unsigned long *mask) 407e6cbbe42SPatrick Rudolph { 408e6cbbe42SPatrick Rudolph DECLARE_BITMAP(tmask, MAX_LINE); 409e6cbbe42SPatrick Rudolph DECLARE_BITMAP(tval, MAX_LINE); 410e6cbbe42SPatrick Rudolph int write_val; 411e6cbbe42SPatrick Rudolph int ret = 0; 412e6cbbe42SPatrick Rudolph int i, off = 0; 413e6cbbe42SPatrick Rudolph u8 bits; 414e6cbbe42SPatrick Rudolph 415e6cbbe42SPatrick Rudolph /* Add the 4 bit gap of Gport2 */ 416e6cbbe42SPatrick Rudolph bitmap_andnot(tmask, mask, chip->shiftmask, MAX_LINE); 417e6cbbe42SPatrick Rudolph bitmap_shift_left(tmask, tmask, 4, MAX_LINE); 418e6cbbe42SPatrick Rudolph bitmap_replace(tmask, tmask, mask, chip->shiftmask, BANK_SZ * 3); 419e6cbbe42SPatrick Rudolph 420e6cbbe42SPatrick Rudolph bitmap_andnot(tval, val, chip->shiftmask, MAX_LINE); 421e6cbbe42SPatrick Rudolph bitmap_shift_left(tval, tval, 4, MAX_LINE); 422e6cbbe42SPatrick Rudolph bitmap_replace(tval, tval, val, chip->shiftmask, BANK_SZ * 3); 423e6cbbe42SPatrick Rudolph 424e6cbbe42SPatrick Rudolph mutex_lock(&chip->i2c_lock); 425e6cbbe42SPatrick Rudolph for (i = 0; i < chip->nport; i++) { 426e6cbbe42SPatrick Rudolph /* Skip over unused banks */ 427e6cbbe42SPatrick Rudolph bits = bitmap_get_value8(tmask, i * BANK_SZ); 428e6cbbe42SPatrick Rudolph if (!bits) 429e6cbbe42SPatrick Rudolph continue; 430e6cbbe42SPatrick Rudolph 431e6cbbe42SPatrick Rudolph switch (reg) { 43263e23304SAndy Shevchenko /* Muxed registers */ 433e6cbbe42SPatrick Rudolph case CY8C95X0_INTMASK: 434e6cbbe42SPatrick Rudolph case CY8C95X0_PWMSEL: 435e6cbbe42SPatrick Rudolph case CY8C95X0_INVERT: 436e6cbbe42SPatrick Rudolph case CY8C95X0_DIRECTION: 437e6cbbe42SPatrick Rudolph case CY8C95X0_DRV_PU: 438e6cbbe42SPatrick Rudolph case CY8C95X0_DRV_PD: 439e6cbbe42SPatrick Rudolph case CY8C95X0_DRV_ODH: 440e6cbbe42SPatrick Rudolph case CY8C95X0_DRV_ODL: 441e6cbbe42SPatrick Rudolph case CY8C95X0_DRV_PP_FAST: 442e6cbbe42SPatrick Rudolph case CY8C95X0_DRV_PP_SLOW: 443e6cbbe42SPatrick Rudolph case CY8C95X0_DRV_HIZ: 444e6cbbe42SPatrick Rudolph ret = regmap_write(chip->regmap, CY8C95X0_PORTSEL, i); 445e6cbbe42SPatrick Rudolph if (ret < 0) 446e6cbbe42SPatrick Rudolph goto out; 447e6cbbe42SPatrick Rudolph off = reg; 448e6cbbe42SPatrick Rudolph break; 44963e23304SAndy Shevchenko /* Direct access registers */ 450e6cbbe42SPatrick Rudolph case CY8C95X0_INPUT: 451e6cbbe42SPatrick Rudolph case CY8C95X0_OUTPUT: 452e6cbbe42SPatrick Rudolph case CY8C95X0_INTSTATUS: 453e6cbbe42SPatrick Rudolph off = reg + i; 454e6cbbe42SPatrick Rudolph break; 455e6cbbe42SPatrick Rudolph default: 456e6cbbe42SPatrick Rudolph ret = -EINVAL; 457e6cbbe42SPatrick Rudolph goto out; 458e6cbbe42SPatrick Rudolph } 459e6cbbe42SPatrick Rudolph 460e6cbbe42SPatrick Rudolph write_val = bitmap_get_value8(tval, i * BANK_SZ); 461e6cbbe42SPatrick Rudolph 462e6cbbe42SPatrick Rudolph ret = regmap_update_bits(chip->regmap, off, bits, write_val); 463e6cbbe42SPatrick Rudolph if (ret < 0) 464e6cbbe42SPatrick Rudolph goto out; 465e6cbbe42SPatrick Rudolph } 466e6cbbe42SPatrick Rudolph out: 467e6cbbe42SPatrick Rudolph mutex_unlock(&chip->i2c_lock); 468e6cbbe42SPatrick Rudolph 469e6cbbe42SPatrick Rudolph if (ret < 0) 470e6cbbe42SPatrick Rudolph dev_err(chip->dev, "failed writing register %d: err %d\n", off, ret); 471e6cbbe42SPatrick Rudolph 472e6cbbe42SPatrick Rudolph return ret; 473e6cbbe42SPatrick Rudolph } 474e6cbbe42SPatrick Rudolph 475e6cbbe42SPatrick Rudolph static int cy8c95x0_read_regs_mask(struct cy8c95x0_pinctrl *chip, int reg, 476e6cbbe42SPatrick Rudolph unsigned long *val, unsigned long *mask) 477e6cbbe42SPatrick Rudolph { 478e6cbbe42SPatrick Rudolph DECLARE_BITMAP(tmask, MAX_LINE); 479e6cbbe42SPatrick Rudolph DECLARE_BITMAP(tval, MAX_LINE); 480e6cbbe42SPatrick Rudolph DECLARE_BITMAP(tmp, MAX_LINE); 481e6cbbe42SPatrick Rudolph int read_val; 482e6cbbe42SPatrick Rudolph int ret = 0; 483e6cbbe42SPatrick Rudolph int i, off = 0; 484e6cbbe42SPatrick Rudolph u8 bits; 485e6cbbe42SPatrick Rudolph 486e6cbbe42SPatrick Rudolph /* Add the 4 bit gap of Gport2 */ 487e6cbbe42SPatrick Rudolph bitmap_andnot(tmask, mask, chip->shiftmask, MAX_LINE); 488e6cbbe42SPatrick Rudolph bitmap_shift_left(tmask, tmask, 4, MAX_LINE); 489e6cbbe42SPatrick Rudolph bitmap_replace(tmask, tmask, mask, chip->shiftmask, BANK_SZ * 3); 490e6cbbe42SPatrick Rudolph 491e6cbbe42SPatrick Rudolph bitmap_andnot(tval, val, chip->shiftmask, MAX_LINE); 492e6cbbe42SPatrick Rudolph bitmap_shift_left(tval, tval, 4, MAX_LINE); 493e6cbbe42SPatrick Rudolph bitmap_replace(tval, tval, val, chip->shiftmask, BANK_SZ * 3); 494e6cbbe42SPatrick Rudolph 495e6cbbe42SPatrick Rudolph mutex_lock(&chip->i2c_lock); 496e6cbbe42SPatrick Rudolph for (i = 0; i < chip->nport; i++) { 497e6cbbe42SPatrick Rudolph /* Skip over unused banks */ 498e6cbbe42SPatrick Rudolph bits = bitmap_get_value8(tmask, i * BANK_SZ); 499e6cbbe42SPatrick Rudolph if (!bits) 500e6cbbe42SPatrick Rudolph continue; 501e6cbbe42SPatrick Rudolph 502e6cbbe42SPatrick Rudolph switch (reg) { 50363e23304SAndy Shevchenko /* Muxed registers */ 504e6cbbe42SPatrick Rudolph case CY8C95X0_INTMASK: 505e6cbbe42SPatrick Rudolph case CY8C95X0_PWMSEL: 506e6cbbe42SPatrick Rudolph case CY8C95X0_INVERT: 507e6cbbe42SPatrick Rudolph case CY8C95X0_DIRECTION: 508e6cbbe42SPatrick Rudolph case CY8C95X0_DRV_PU: 509e6cbbe42SPatrick Rudolph case CY8C95X0_DRV_PD: 510e6cbbe42SPatrick Rudolph case CY8C95X0_DRV_ODH: 511e6cbbe42SPatrick Rudolph case CY8C95X0_DRV_ODL: 512e6cbbe42SPatrick Rudolph case CY8C95X0_DRV_PP_FAST: 513e6cbbe42SPatrick Rudolph case CY8C95X0_DRV_PP_SLOW: 514e6cbbe42SPatrick Rudolph case CY8C95X0_DRV_HIZ: 515e6cbbe42SPatrick Rudolph ret = regmap_write(chip->regmap, CY8C95X0_PORTSEL, i); 516e6cbbe42SPatrick Rudolph if (ret < 0) 517e6cbbe42SPatrick Rudolph goto out; 518e6cbbe42SPatrick Rudolph off = reg; 519e6cbbe42SPatrick Rudolph break; 52063e23304SAndy Shevchenko /* Direct access registers */ 521e6cbbe42SPatrick Rudolph case CY8C95X0_INPUT: 522e6cbbe42SPatrick Rudolph case CY8C95X0_OUTPUT: 523e6cbbe42SPatrick Rudolph case CY8C95X0_INTSTATUS: 524e6cbbe42SPatrick Rudolph off = reg + i; 525e6cbbe42SPatrick Rudolph break; 526e6cbbe42SPatrick Rudolph default: 527e6cbbe42SPatrick Rudolph ret = -EINVAL; 528e6cbbe42SPatrick Rudolph goto out; 529e6cbbe42SPatrick Rudolph } 530e6cbbe42SPatrick Rudolph 531e6cbbe42SPatrick Rudolph ret = regmap_read(chip->regmap, off, &read_val); 532e6cbbe42SPatrick Rudolph if (ret < 0) 533e6cbbe42SPatrick Rudolph goto out; 534e6cbbe42SPatrick Rudolph 535e6cbbe42SPatrick Rudolph read_val &= bits; 536e6cbbe42SPatrick Rudolph read_val |= bitmap_get_value8(tval, i * BANK_SZ) & ~bits; 537e6cbbe42SPatrick Rudolph bitmap_set_value8(tval, read_val, i * BANK_SZ); 538e6cbbe42SPatrick Rudolph } 539e6cbbe42SPatrick Rudolph 540e6cbbe42SPatrick Rudolph /* Fill the 4 bit gap of Gport2 */ 541e6cbbe42SPatrick Rudolph bitmap_shift_right(tmp, tval, 4, MAX_LINE); 542e6cbbe42SPatrick Rudolph bitmap_replace(val, tmp, tval, chip->shiftmask, MAX_LINE); 543e6cbbe42SPatrick Rudolph 544e6cbbe42SPatrick Rudolph out: 545e6cbbe42SPatrick Rudolph mutex_unlock(&chip->i2c_lock); 546e6cbbe42SPatrick Rudolph 547e6cbbe42SPatrick Rudolph if (ret < 0) 548e6cbbe42SPatrick Rudolph dev_err(chip->dev, "failed reading register %d: err %d\n", off, ret); 549e6cbbe42SPatrick Rudolph 550e6cbbe42SPatrick Rudolph return ret; 551e6cbbe42SPatrick Rudolph } 552e6cbbe42SPatrick Rudolph 553e6cbbe42SPatrick Rudolph static int cy8c95x0_gpio_direction_input(struct gpio_chip *gc, unsigned int off) 554e6cbbe42SPatrick Rudolph { 555e6cbbe42SPatrick Rudolph struct cy8c95x0_pinctrl *chip = gpiochip_get_data(gc); 556e6cbbe42SPatrick Rudolph u8 port = cypress_get_port(chip, off); 557e6cbbe42SPatrick Rudolph u8 bit = cypress_get_pin_mask(chip, off); 558e6cbbe42SPatrick Rudolph int ret; 559e6cbbe42SPatrick Rudolph 560e6cbbe42SPatrick Rudolph mutex_lock(&chip->i2c_lock); 561e6cbbe42SPatrick Rudolph ret = regmap_write(chip->regmap, CY8C95X0_PORTSEL, port); 562e6cbbe42SPatrick Rudolph if (ret) 563e6cbbe42SPatrick Rudolph goto out; 564e6cbbe42SPatrick Rudolph 565e6cbbe42SPatrick Rudolph ret = regmap_write_bits(chip->regmap, CY8C95X0_DIRECTION, bit, bit); 566e6cbbe42SPatrick Rudolph if (ret) 567e6cbbe42SPatrick Rudolph goto out; 568e6cbbe42SPatrick Rudolph 569e6cbbe42SPatrick Rudolph if (test_bit(off, chip->push_pull)) { 570e6cbbe42SPatrick Rudolph /* 571e6cbbe42SPatrick Rudolph * Disable driving the pin by forcing it to HighZ. Only setting the 572e6cbbe42SPatrick Rudolph * direction register isn't sufficient in Push-Pull mode. 573e6cbbe42SPatrick Rudolph */ 574e6cbbe42SPatrick Rudolph ret = regmap_write_bits(chip->regmap, CY8C95X0_DRV_HIZ, bit, bit); 575e6cbbe42SPatrick Rudolph if (ret) 576e6cbbe42SPatrick Rudolph goto out; 577d6afdf88SAndy Shevchenko 578d6afdf88SAndy Shevchenko __clear_bit(off, chip->push_pull); 579e6cbbe42SPatrick Rudolph } 580e6cbbe42SPatrick Rudolph 581e6cbbe42SPatrick Rudolph out: 582e6cbbe42SPatrick Rudolph mutex_unlock(&chip->i2c_lock); 583e6cbbe42SPatrick Rudolph 584e6cbbe42SPatrick Rudolph return ret; 585e6cbbe42SPatrick Rudolph } 586e6cbbe42SPatrick Rudolph 587e6cbbe42SPatrick Rudolph static int cy8c95x0_gpio_direction_output(struct gpio_chip *gc, 588e6cbbe42SPatrick Rudolph unsigned int off, int val) 589e6cbbe42SPatrick Rudolph { 590e6cbbe42SPatrick Rudolph struct cy8c95x0_pinctrl *chip = gpiochip_get_data(gc); 591e6cbbe42SPatrick Rudolph u8 port = cypress_get_port(chip, off); 592e6cbbe42SPatrick Rudolph u8 outreg = CY8C95X0_OUTPUT_(port); 593e6cbbe42SPatrick Rudolph u8 bit = cypress_get_pin_mask(chip, off); 594e6cbbe42SPatrick Rudolph int ret; 595e6cbbe42SPatrick Rudolph 59663e23304SAndy Shevchenko /* Set output level */ 597e6cbbe42SPatrick Rudolph ret = regmap_write_bits(chip->regmap, outreg, bit, val ? bit : 0); 598e6cbbe42SPatrick Rudolph if (ret) 599e6cbbe42SPatrick Rudolph return ret; 600e6cbbe42SPatrick Rudolph 601e6cbbe42SPatrick Rudolph mutex_lock(&chip->i2c_lock); 60263e23304SAndy Shevchenko /* Select port... */ 603e6cbbe42SPatrick Rudolph ret = regmap_write(chip->regmap, CY8C95X0_PORTSEL, port); 604e6cbbe42SPatrick Rudolph if (ret) 605e6cbbe42SPatrick Rudolph goto out; 606e6cbbe42SPatrick Rudolph 60763e23304SAndy Shevchenko /* ...then direction */ 608e6cbbe42SPatrick Rudolph ret = regmap_write_bits(chip->regmap, CY8C95X0_DIRECTION, bit, 0); 609e6cbbe42SPatrick Rudolph 610e6cbbe42SPatrick Rudolph out: 611e6cbbe42SPatrick Rudolph mutex_unlock(&chip->i2c_lock); 612e6cbbe42SPatrick Rudolph 613e6cbbe42SPatrick Rudolph return ret; 614e6cbbe42SPatrick Rudolph } 615e6cbbe42SPatrick Rudolph 616e6cbbe42SPatrick Rudolph static int cy8c95x0_gpio_get_value(struct gpio_chip *gc, unsigned int off) 617e6cbbe42SPatrick Rudolph { 618e6cbbe42SPatrick Rudolph struct cy8c95x0_pinctrl *chip = gpiochip_get_data(gc); 619e6cbbe42SPatrick Rudolph u8 inreg = CY8C95X0_INPUT_(cypress_get_port(chip, off)); 620e6cbbe42SPatrick Rudolph u8 bit = cypress_get_pin_mask(chip, off); 621e6cbbe42SPatrick Rudolph u32 reg_val; 622e6cbbe42SPatrick Rudolph int ret; 623e6cbbe42SPatrick Rudolph 624e6cbbe42SPatrick Rudolph ret = regmap_read(chip->regmap, inreg, ®_val); 625e6cbbe42SPatrick Rudolph if (ret < 0) { 626e6cbbe42SPatrick Rudolph /* 627e6cbbe42SPatrick Rudolph * NOTE: 62863e23304SAndy Shevchenko * Diagnostic already emitted; that's all we should 629e6cbbe42SPatrick Rudolph * do unless gpio_*_value_cansleep() calls become different 630e6cbbe42SPatrick Rudolph * from their nonsleeping siblings (and report faults). 631e6cbbe42SPatrick Rudolph */ 632e6cbbe42SPatrick Rudolph return 0; 633e6cbbe42SPatrick Rudolph } 634e6cbbe42SPatrick Rudolph 635e6cbbe42SPatrick Rudolph return !!(reg_val & bit); 636e6cbbe42SPatrick Rudolph } 637e6cbbe42SPatrick Rudolph 638e6cbbe42SPatrick Rudolph static void cy8c95x0_gpio_set_value(struct gpio_chip *gc, unsigned int off, 639e6cbbe42SPatrick Rudolph int val) 640e6cbbe42SPatrick Rudolph { 641e6cbbe42SPatrick Rudolph struct cy8c95x0_pinctrl *chip = gpiochip_get_data(gc); 642e6cbbe42SPatrick Rudolph u8 outreg = CY8C95X0_OUTPUT_(cypress_get_port(chip, off)); 643e6cbbe42SPatrick Rudolph u8 bit = cypress_get_pin_mask(chip, off); 644e6cbbe42SPatrick Rudolph 645e6cbbe42SPatrick Rudolph regmap_write_bits(chip->regmap, outreg, bit, val ? bit : 0); 646e6cbbe42SPatrick Rudolph } 647e6cbbe42SPatrick Rudolph 648e6cbbe42SPatrick Rudolph static int cy8c95x0_gpio_get_direction(struct gpio_chip *gc, unsigned int off) 649e6cbbe42SPatrick Rudolph { 650e6cbbe42SPatrick Rudolph struct cy8c95x0_pinctrl *chip = gpiochip_get_data(gc); 651e6cbbe42SPatrick Rudolph u8 port = cypress_get_port(chip, off); 652e6cbbe42SPatrick Rudolph u8 bit = cypress_get_pin_mask(chip, off); 653e6cbbe42SPatrick Rudolph u32 reg_val; 654e6cbbe42SPatrick Rudolph int ret; 655e6cbbe42SPatrick Rudolph 656e6cbbe42SPatrick Rudolph mutex_lock(&chip->i2c_lock); 657e6cbbe42SPatrick Rudolph 658e6cbbe42SPatrick Rudolph ret = regmap_write(chip->regmap, CY8C95X0_PORTSEL, port); 659e6cbbe42SPatrick Rudolph if (ret < 0) 660e6cbbe42SPatrick Rudolph goto out; 661e6cbbe42SPatrick Rudolph 662e6cbbe42SPatrick Rudolph ret = regmap_read(chip->regmap, CY8C95X0_DIRECTION, ®_val); 663e6cbbe42SPatrick Rudolph if (ret < 0) 664e6cbbe42SPatrick Rudolph goto out; 665e6cbbe42SPatrick Rudolph 666e6cbbe42SPatrick Rudolph mutex_unlock(&chip->i2c_lock); 667e6cbbe42SPatrick Rudolph 668e6cbbe42SPatrick Rudolph if (reg_val & bit) 669e6cbbe42SPatrick Rudolph return GPIO_LINE_DIRECTION_IN; 670e6cbbe42SPatrick Rudolph 671e6cbbe42SPatrick Rudolph return GPIO_LINE_DIRECTION_OUT; 672e6cbbe42SPatrick Rudolph out: 673e6cbbe42SPatrick Rudolph mutex_unlock(&chip->i2c_lock); 674e6cbbe42SPatrick Rudolph return ret; 675e6cbbe42SPatrick Rudolph } 676e6cbbe42SPatrick Rudolph 677e6cbbe42SPatrick Rudolph static int cy8c95x0_gpio_get_pincfg(struct cy8c95x0_pinctrl *chip, 678e6cbbe42SPatrick Rudolph unsigned int off, 679e6cbbe42SPatrick Rudolph unsigned long *config) 680e6cbbe42SPatrick Rudolph { 681e6cbbe42SPatrick Rudolph enum pin_config_param param = pinconf_to_config_param(*config); 682e6cbbe42SPatrick Rudolph u8 port = cypress_get_port(chip, off); 683e6cbbe42SPatrick Rudolph u8 bit = cypress_get_pin_mask(chip, off); 684e6cbbe42SPatrick Rudolph unsigned int reg; 685e6cbbe42SPatrick Rudolph u32 reg_val; 686e6cbbe42SPatrick Rudolph u16 arg = 0; 687e6cbbe42SPatrick Rudolph int ret; 688e6cbbe42SPatrick Rudolph 689e6cbbe42SPatrick Rudolph mutex_lock(&chip->i2c_lock); 690e6cbbe42SPatrick Rudolph 69163e23304SAndy Shevchenko /* Select port */ 692e6cbbe42SPatrick Rudolph ret = regmap_write(chip->regmap, CY8C95X0_PORTSEL, port); 693e6cbbe42SPatrick Rudolph if (ret < 0) 694e6cbbe42SPatrick Rudolph goto out; 695e6cbbe42SPatrick Rudolph 696e6cbbe42SPatrick Rudolph switch (param) { 697e6cbbe42SPatrick Rudolph case PIN_CONFIG_BIAS_PULL_UP: 698e6cbbe42SPatrick Rudolph reg = CY8C95X0_DRV_PU; 699e6cbbe42SPatrick Rudolph break; 700e6cbbe42SPatrick Rudolph case PIN_CONFIG_BIAS_PULL_DOWN: 701e6cbbe42SPatrick Rudolph reg = CY8C95X0_DRV_PD; 702e6cbbe42SPatrick Rudolph break; 703e6cbbe42SPatrick Rudolph case PIN_CONFIG_BIAS_DISABLE: 704e6cbbe42SPatrick Rudolph reg = CY8C95X0_DRV_HIZ; 705e6cbbe42SPatrick Rudolph break; 706e6cbbe42SPatrick Rudolph case PIN_CONFIG_DRIVE_OPEN_DRAIN: 707e6cbbe42SPatrick Rudolph reg = CY8C95X0_DRV_ODL; 708e6cbbe42SPatrick Rudolph break; 709e6cbbe42SPatrick Rudolph case PIN_CONFIG_DRIVE_OPEN_SOURCE: 710e6cbbe42SPatrick Rudolph reg = CY8C95X0_DRV_ODH; 711e6cbbe42SPatrick Rudolph break; 712e6cbbe42SPatrick Rudolph case PIN_CONFIG_DRIVE_PUSH_PULL: 713e6cbbe42SPatrick Rudolph reg = CY8C95X0_DRV_PP_FAST; 714e6cbbe42SPatrick Rudolph break; 715e6cbbe42SPatrick Rudolph case PIN_CONFIG_INPUT_ENABLE: 716e6cbbe42SPatrick Rudolph reg = CY8C95X0_DIRECTION; 717e6cbbe42SPatrick Rudolph break; 718e6cbbe42SPatrick Rudolph case PIN_CONFIG_MODE_PWM: 719e6cbbe42SPatrick Rudolph reg = CY8C95X0_PWMSEL; 720e6cbbe42SPatrick Rudolph break; 721e6cbbe42SPatrick Rudolph case PIN_CONFIG_OUTPUT: 722e6cbbe42SPatrick Rudolph reg = CY8C95X0_OUTPUT_(port); 723e6cbbe42SPatrick Rudolph break; 724e6cbbe42SPatrick Rudolph case PIN_CONFIG_OUTPUT_ENABLE: 725e6cbbe42SPatrick Rudolph reg = CY8C95X0_DIRECTION; 726e6cbbe42SPatrick Rudolph break; 727e6cbbe42SPatrick Rudolph 728e6cbbe42SPatrick Rudolph case PIN_CONFIG_BIAS_HIGH_IMPEDANCE: 729e6cbbe42SPatrick Rudolph case PIN_CONFIG_BIAS_BUS_HOLD: 730e6cbbe42SPatrick Rudolph case PIN_CONFIG_BIAS_PULL_PIN_DEFAULT: 731e6cbbe42SPatrick Rudolph case PIN_CONFIG_DRIVE_STRENGTH: 732e6cbbe42SPatrick Rudolph case PIN_CONFIG_DRIVE_STRENGTH_UA: 733e6cbbe42SPatrick Rudolph case PIN_CONFIG_INPUT_DEBOUNCE: 734e6cbbe42SPatrick Rudolph case PIN_CONFIG_INPUT_SCHMITT: 735e6cbbe42SPatrick Rudolph case PIN_CONFIG_INPUT_SCHMITT_ENABLE: 736e6cbbe42SPatrick Rudolph case PIN_CONFIG_MODE_LOW_POWER: 737e6cbbe42SPatrick Rudolph case PIN_CONFIG_PERSIST_STATE: 738e6cbbe42SPatrick Rudolph case PIN_CONFIG_POWER_SOURCE: 739e6cbbe42SPatrick Rudolph case PIN_CONFIG_SKEW_DELAY: 740e6cbbe42SPatrick Rudolph case PIN_CONFIG_SLEEP_HARDWARE_STATE: 741e6cbbe42SPatrick Rudolph case PIN_CONFIG_SLEW_RATE: 742e6cbbe42SPatrick Rudolph default: 743e6cbbe42SPatrick Rudolph ret = -ENOTSUPP; 744e6cbbe42SPatrick Rudolph goto out; 745e6cbbe42SPatrick Rudolph } 74663e23304SAndy Shevchenko /* 74763e23304SAndy Shevchenko * Writing 1 to one of the drive mode registers will automatically 748e6cbbe42SPatrick Rudolph * clear conflicting set bits in the other drive mode registers. 749e6cbbe42SPatrick Rudolph */ 750e6cbbe42SPatrick Rudolph ret = regmap_read(chip->regmap, reg, ®_val); 751e6cbbe42SPatrick Rudolph if (reg_val & bit) 752e6cbbe42SPatrick Rudolph arg = 1; 753e6cbbe42SPatrick Rudolph 754e6cbbe42SPatrick Rudolph *config = pinconf_to_config_packed(param, (u16)arg); 755e6cbbe42SPatrick Rudolph out: 756e6cbbe42SPatrick Rudolph mutex_unlock(&chip->i2c_lock); 757e6cbbe42SPatrick Rudolph 758e6cbbe42SPatrick Rudolph return ret; 759e6cbbe42SPatrick Rudolph } 760e6cbbe42SPatrick Rudolph 761e6cbbe42SPatrick Rudolph static int cy8c95x0_gpio_set_pincfg(struct cy8c95x0_pinctrl *chip, 762e6cbbe42SPatrick Rudolph unsigned int off, 763e6cbbe42SPatrick Rudolph unsigned long config) 764e6cbbe42SPatrick Rudolph { 765e6cbbe42SPatrick Rudolph u8 port = cypress_get_port(chip, off); 766e6cbbe42SPatrick Rudolph u8 bit = cypress_get_pin_mask(chip, off); 767e6cbbe42SPatrick Rudolph unsigned long param = pinconf_to_config_param(config); 768e6cbbe42SPatrick Rudolph unsigned int reg; 769e6cbbe42SPatrick Rudolph int ret; 770e6cbbe42SPatrick Rudolph 771e6cbbe42SPatrick Rudolph mutex_lock(&chip->i2c_lock); 772e6cbbe42SPatrick Rudolph 77363e23304SAndy Shevchenko /* Select port */ 774e6cbbe42SPatrick Rudolph ret = regmap_write(chip->regmap, CY8C95X0_PORTSEL, port); 775e6cbbe42SPatrick Rudolph if (ret < 0) 776e6cbbe42SPatrick Rudolph goto out; 777e6cbbe42SPatrick Rudolph 778e6cbbe42SPatrick Rudolph switch (param) { 779e6cbbe42SPatrick Rudolph case PIN_CONFIG_BIAS_PULL_UP: 780d6afdf88SAndy Shevchenko __clear_bit(off, chip->push_pull); 781e6cbbe42SPatrick Rudolph reg = CY8C95X0_DRV_PU; 782e6cbbe42SPatrick Rudolph break; 783e6cbbe42SPatrick Rudolph case PIN_CONFIG_BIAS_PULL_DOWN: 784d6afdf88SAndy Shevchenko __clear_bit(off, chip->push_pull); 785e6cbbe42SPatrick Rudolph reg = CY8C95X0_DRV_PD; 786e6cbbe42SPatrick Rudolph break; 787e6cbbe42SPatrick Rudolph case PIN_CONFIG_BIAS_DISABLE: 788d6afdf88SAndy Shevchenko __clear_bit(off, chip->push_pull); 789e6cbbe42SPatrick Rudolph reg = CY8C95X0_DRV_HIZ; 790e6cbbe42SPatrick Rudolph break; 791e6cbbe42SPatrick Rudolph case PIN_CONFIG_DRIVE_OPEN_DRAIN: 792d6afdf88SAndy Shevchenko __clear_bit(off, chip->push_pull); 793e6cbbe42SPatrick Rudolph reg = CY8C95X0_DRV_ODL; 794e6cbbe42SPatrick Rudolph break; 795e6cbbe42SPatrick Rudolph case PIN_CONFIG_DRIVE_OPEN_SOURCE: 796d6afdf88SAndy Shevchenko __clear_bit(off, chip->push_pull); 797e6cbbe42SPatrick Rudolph reg = CY8C95X0_DRV_ODH; 798e6cbbe42SPatrick Rudolph break; 799e6cbbe42SPatrick Rudolph case PIN_CONFIG_DRIVE_PUSH_PULL: 800d6afdf88SAndy Shevchenko __set_bit(off, chip->push_pull); 801e6cbbe42SPatrick Rudolph reg = CY8C95X0_DRV_PP_FAST; 802e6cbbe42SPatrick Rudolph break; 803e6cbbe42SPatrick Rudolph case PIN_CONFIG_MODE_PWM: 804e6cbbe42SPatrick Rudolph reg = CY8C95X0_PWMSEL; 805e6cbbe42SPatrick Rudolph break; 806e6cbbe42SPatrick Rudolph default: 807e6cbbe42SPatrick Rudolph ret = -ENOTSUPP; 808e6cbbe42SPatrick Rudolph goto out; 809e6cbbe42SPatrick Rudolph } 81063e23304SAndy Shevchenko /* 81163e23304SAndy Shevchenko * Writing 1 to one of the drive mode registers will automatically 812e6cbbe42SPatrick Rudolph * clear conflicting set bits in the other drive mode registers. 813e6cbbe42SPatrick Rudolph */ 814e6cbbe42SPatrick Rudolph ret = regmap_write_bits(chip->regmap, reg, bit, bit); 815e6cbbe42SPatrick Rudolph 816e6cbbe42SPatrick Rudolph out: 817e6cbbe42SPatrick Rudolph mutex_unlock(&chip->i2c_lock); 818e6cbbe42SPatrick Rudolph return ret; 819e6cbbe42SPatrick Rudolph } 820e6cbbe42SPatrick Rudolph 821e6cbbe42SPatrick Rudolph static int cy8c95x0_gpio_get_multiple(struct gpio_chip *gc, 822e6cbbe42SPatrick Rudolph unsigned long *mask, unsigned long *bits) 823e6cbbe42SPatrick Rudolph { 824e6cbbe42SPatrick Rudolph struct cy8c95x0_pinctrl *chip = gpiochip_get_data(gc); 825e6cbbe42SPatrick Rudolph 826e6cbbe42SPatrick Rudolph return cy8c95x0_read_regs_mask(chip, CY8C95X0_INPUT, bits, mask); 827e6cbbe42SPatrick Rudolph } 828e6cbbe42SPatrick Rudolph 829e6cbbe42SPatrick Rudolph static void cy8c95x0_gpio_set_multiple(struct gpio_chip *gc, 830e6cbbe42SPatrick Rudolph unsigned long *mask, unsigned long *bits) 831e6cbbe42SPatrick Rudolph { 832e6cbbe42SPatrick Rudolph struct cy8c95x0_pinctrl *chip = gpiochip_get_data(gc); 833e6cbbe42SPatrick Rudolph 834e6cbbe42SPatrick Rudolph cy8c95x0_write_regs_mask(chip, CY8C95X0_OUTPUT, bits, mask); 835e6cbbe42SPatrick Rudolph } 836e6cbbe42SPatrick Rudolph 837d86e0344SAndy Shevchenko static int cy8c95x0_add_pin_ranges(struct gpio_chip *gc) 838d86e0344SAndy Shevchenko { 839d86e0344SAndy Shevchenko struct cy8c95x0_pinctrl *chip = gpiochip_get_data(gc); 840d86e0344SAndy Shevchenko struct device *dev = chip->dev; 841d86e0344SAndy Shevchenko int ret; 842d86e0344SAndy Shevchenko 843d86e0344SAndy Shevchenko ret = gpiochip_add_pin_range(gc, dev_name(dev), 0, 0, chip->tpin); 844d86e0344SAndy Shevchenko if (ret) 845d86e0344SAndy Shevchenko dev_err(dev, "failed to add GPIO pin range\n"); 846d86e0344SAndy Shevchenko 847d86e0344SAndy Shevchenko return ret; 848d86e0344SAndy Shevchenko } 849d86e0344SAndy Shevchenko 850d86e0344SAndy Shevchenko static int cy8c95x0_setup_gpiochip(struct cy8c95x0_pinctrl *chip) 851e6cbbe42SPatrick Rudolph { 852e6cbbe42SPatrick Rudolph struct gpio_chip *gc = &chip->gpio_chip; 853e6cbbe42SPatrick Rudolph 854e6cbbe42SPatrick Rudolph gc->direction_input = cy8c95x0_gpio_direction_input; 855e6cbbe42SPatrick Rudolph gc->direction_output = cy8c95x0_gpio_direction_output; 856e6cbbe42SPatrick Rudolph gc->get = cy8c95x0_gpio_get_value; 857e6cbbe42SPatrick Rudolph gc->set = cy8c95x0_gpio_set_value; 858e6cbbe42SPatrick Rudolph gc->get_direction = cy8c95x0_gpio_get_direction; 859e6cbbe42SPatrick Rudolph gc->get_multiple = cy8c95x0_gpio_get_multiple; 860e6cbbe42SPatrick Rudolph gc->set_multiple = cy8c95x0_gpio_set_multiple; 8611fa3df90SAndy Shevchenko gc->set_config = gpiochip_generic_config, 862e6cbbe42SPatrick Rudolph gc->can_sleep = true; 863d86e0344SAndy Shevchenko gc->add_pin_ranges = cy8c95x0_add_pin_ranges; 864e6cbbe42SPatrick Rudolph 865e6cbbe42SPatrick Rudolph gc->base = -1; 866d86e0344SAndy Shevchenko gc->ngpio = chip->tpin; 867e6cbbe42SPatrick Rudolph 868e6cbbe42SPatrick Rudolph gc->parent = chip->dev; 869e6cbbe42SPatrick Rudolph gc->owner = THIS_MODULE; 870e6cbbe42SPatrick Rudolph gc->names = NULL; 871e6cbbe42SPatrick Rudolph 872e6cbbe42SPatrick Rudolph gc->label = dev_name(chip->dev); 873e6cbbe42SPatrick Rudolph 874e6cbbe42SPatrick Rudolph return devm_gpiochip_add_data(chip->dev, gc, chip); 875e6cbbe42SPatrick Rudolph } 876e6cbbe42SPatrick Rudolph 877e6cbbe42SPatrick Rudolph static void cy8c95x0_irq_mask(struct irq_data *d) 878e6cbbe42SPatrick Rudolph { 879e6cbbe42SPatrick Rudolph struct gpio_chip *gc = irq_data_get_irq_chip_data(d); 880e6cbbe42SPatrick Rudolph struct cy8c95x0_pinctrl *chip = gpiochip_get_data(gc); 881f5d62025SAndy Shevchenko irq_hw_number_t hwirq = irqd_to_hwirq(d); 882e6cbbe42SPatrick Rudolph 883f5d62025SAndy Shevchenko set_bit(hwirq, chip->irq_mask); 884f5d62025SAndy Shevchenko gpiochip_disable_irq(gc, hwirq); 885e6cbbe42SPatrick Rudolph } 886e6cbbe42SPatrick Rudolph 887e6cbbe42SPatrick Rudolph static void cy8c95x0_irq_unmask(struct irq_data *d) 888e6cbbe42SPatrick Rudolph { 889e6cbbe42SPatrick Rudolph struct gpio_chip *gc = irq_data_get_irq_chip_data(d); 890e6cbbe42SPatrick Rudolph struct cy8c95x0_pinctrl *chip = gpiochip_get_data(gc); 891f5d62025SAndy Shevchenko irq_hw_number_t hwirq = irqd_to_hwirq(d); 892e6cbbe42SPatrick Rudolph 893f5d62025SAndy Shevchenko gpiochip_enable_irq(gc, hwirq); 894f5d62025SAndy Shevchenko clear_bit(hwirq, chip->irq_mask); 895e6cbbe42SPatrick Rudolph } 896e6cbbe42SPatrick Rudolph 897e6cbbe42SPatrick Rudolph static void cy8c95x0_irq_bus_lock(struct irq_data *d) 898e6cbbe42SPatrick Rudolph { 899e6cbbe42SPatrick Rudolph struct gpio_chip *gc = irq_data_get_irq_chip_data(d); 900e6cbbe42SPatrick Rudolph struct cy8c95x0_pinctrl *chip = gpiochip_get_data(gc); 901e6cbbe42SPatrick Rudolph 902e6cbbe42SPatrick Rudolph mutex_lock(&chip->irq_lock); 903e6cbbe42SPatrick Rudolph } 904e6cbbe42SPatrick Rudolph 905e6cbbe42SPatrick Rudolph static void cy8c95x0_irq_bus_sync_unlock(struct irq_data *d) 906e6cbbe42SPatrick Rudolph { 907e6cbbe42SPatrick Rudolph struct gpio_chip *gc = irq_data_get_irq_chip_data(d); 908e6cbbe42SPatrick Rudolph struct cy8c95x0_pinctrl *chip = gpiochip_get_data(gc); 909e6cbbe42SPatrick Rudolph DECLARE_BITMAP(ones, MAX_LINE); 910e6cbbe42SPatrick Rudolph DECLARE_BITMAP(irq_mask, MAX_LINE); 911e6cbbe42SPatrick Rudolph DECLARE_BITMAP(reg_direction, MAX_LINE); 912e6cbbe42SPatrick Rudolph 913e6cbbe42SPatrick Rudolph bitmap_fill(ones, MAX_LINE); 914e6cbbe42SPatrick Rudolph 915e6cbbe42SPatrick Rudolph cy8c95x0_write_regs_mask(chip, CY8C95X0_INTMASK, chip->irq_mask, ones); 916e6cbbe42SPatrick Rudolph 917e6cbbe42SPatrick Rudolph /* Switch direction to input if needed */ 918e6cbbe42SPatrick Rudolph cy8c95x0_read_regs_mask(chip, CY8C95X0_DIRECTION, reg_direction, chip->irq_mask); 919e6cbbe42SPatrick Rudolph bitmap_or(irq_mask, chip->irq_mask, reg_direction, MAX_LINE); 920e6cbbe42SPatrick Rudolph bitmap_complement(irq_mask, irq_mask, MAX_LINE); 921e6cbbe42SPatrick Rudolph 922e6cbbe42SPatrick Rudolph /* Look for any newly setup interrupt */ 923e6cbbe42SPatrick Rudolph cy8c95x0_write_regs_mask(chip, CY8C95X0_DIRECTION, ones, irq_mask); 924e6cbbe42SPatrick Rudolph 925e6cbbe42SPatrick Rudolph mutex_unlock(&chip->irq_lock); 926e6cbbe42SPatrick Rudolph } 927e6cbbe42SPatrick Rudolph 928e6cbbe42SPatrick Rudolph static int cy8c95x0_irq_set_type(struct irq_data *d, unsigned int type) 929e6cbbe42SPatrick Rudolph { 930e6cbbe42SPatrick Rudolph struct gpio_chip *gc = irq_data_get_irq_chip_data(d); 931e6cbbe42SPatrick Rudolph struct cy8c95x0_pinctrl *chip = gpiochip_get_data(gc); 932e6cbbe42SPatrick Rudolph irq_hw_number_t hwirq = irqd_to_hwirq(d); 933e6cbbe42SPatrick Rudolph unsigned int trig_type; 934e6cbbe42SPatrick Rudolph 935e6cbbe42SPatrick Rudolph switch (type) { 936e6cbbe42SPatrick Rudolph case IRQ_TYPE_EDGE_RISING: 937e6cbbe42SPatrick Rudolph case IRQ_TYPE_EDGE_FALLING: 938e6cbbe42SPatrick Rudolph case IRQ_TYPE_EDGE_BOTH: 939e6cbbe42SPatrick Rudolph trig_type = type; 940e6cbbe42SPatrick Rudolph break; 941e6cbbe42SPatrick Rudolph case IRQ_TYPE_LEVEL_HIGH: 942e6cbbe42SPatrick Rudolph trig_type = IRQ_TYPE_EDGE_RISING; 943e6cbbe42SPatrick Rudolph break; 944e6cbbe42SPatrick Rudolph case IRQ_TYPE_LEVEL_LOW: 945e6cbbe42SPatrick Rudolph trig_type = IRQ_TYPE_EDGE_FALLING; 946e6cbbe42SPatrick Rudolph break; 947e6cbbe42SPatrick Rudolph default: 948e6cbbe42SPatrick Rudolph dev_err(chip->dev, "irq %d: unsupported type %d\n", d->irq, type); 949e6cbbe42SPatrick Rudolph return -EINVAL; 950e6cbbe42SPatrick Rudolph } 951e6cbbe42SPatrick Rudolph 952e6cbbe42SPatrick Rudolph assign_bit(hwirq, chip->irq_trig_fall, trig_type & IRQ_TYPE_EDGE_FALLING); 953e6cbbe42SPatrick Rudolph assign_bit(hwirq, chip->irq_trig_raise, trig_type & IRQ_TYPE_EDGE_RISING); 954e6cbbe42SPatrick Rudolph assign_bit(hwirq, chip->irq_trig_low, type == IRQ_TYPE_LEVEL_LOW); 955e6cbbe42SPatrick Rudolph assign_bit(hwirq, chip->irq_trig_high, type == IRQ_TYPE_LEVEL_HIGH); 956e6cbbe42SPatrick Rudolph 957e6cbbe42SPatrick Rudolph return 0; 958e6cbbe42SPatrick Rudolph } 959e6cbbe42SPatrick Rudolph 960e6cbbe42SPatrick Rudolph static void cy8c95x0_irq_shutdown(struct irq_data *d) 961e6cbbe42SPatrick Rudolph { 962e6cbbe42SPatrick Rudolph struct gpio_chip *gc = irq_data_get_irq_chip_data(d); 963e6cbbe42SPatrick Rudolph struct cy8c95x0_pinctrl *chip = gpiochip_get_data(gc); 964e6cbbe42SPatrick Rudolph irq_hw_number_t hwirq = irqd_to_hwirq(d); 965e6cbbe42SPatrick Rudolph 966e6cbbe42SPatrick Rudolph clear_bit(hwirq, chip->irq_trig_raise); 967e6cbbe42SPatrick Rudolph clear_bit(hwirq, chip->irq_trig_fall); 968e6cbbe42SPatrick Rudolph clear_bit(hwirq, chip->irq_trig_low); 969e6cbbe42SPatrick Rudolph clear_bit(hwirq, chip->irq_trig_high); 970e6cbbe42SPatrick Rudolph } 971e6cbbe42SPatrick Rudolph 972f5d62025SAndy Shevchenko static const struct irq_chip cy8c95x0_irqchip = { 973f5d62025SAndy Shevchenko .name = "cy8c95x0-irq", 974f5d62025SAndy Shevchenko .irq_mask = cy8c95x0_irq_mask, 975f5d62025SAndy Shevchenko .irq_unmask = cy8c95x0_irq_unmask, 976f5d62025SAndy Shevchenko .irq_bus_lock = cy8c95x0_irq_bus_lock, 977f5d62025SAndy Shevchenko .irq_bus_sync_unlock = cy8c95x0_irq_bus_sync_unlock, 978f5d62025SAndy Shevchenko .irq_set_type = cy8c95x0_irq_set_type, 979f5d62025SAndy Shevchenko .irq_shutdown = cy8c95x0_irq_shutdown, 980f5d62025SAndy Shevchenko .flags = IRQCHIP_IMMUTABLE, 981f5d62025SAndy Shevchenko GPIOCHIP_IRQ_RESOURCE_HELPERS, 982f5d62025SAndy Shevchenko }; 983f5d62025SAndy Shevchenko 984e6cbbe42SPatrick Rudolph static bool cy8c95x0_irq_pending(struct cy8c95x0_pinctrl *chip, unsigned long *pending) 985e6cbbe42SPatrick Rudolph { 986e6cbbe42SPatrick Rudolph DECLARE_BITMAP(ones, MAX_LINE); 987e6cbbe42SPatrick Rudolph DECLARE_BITMAP(cur_stat, MAX_LINE); 988e6cbbe42SPatrick Rudolph DECLARE_BITMAP(new_stat, MAX_LINE); 989e6cbbe42SPatrick Rudolph DECLARE_BITMAP(trigger, MAX_LINE); 990e6cbbe42SPatrick Rudolph 991e6cbbe42SPatrick Rudolph bitmap_fill(ones, MAX_LINE); 992e6cbbe42SPatrick Rudolph 993e6cbbe42SPatrick Rudolph /* Read the current interrupt status from the device */ 994e6cbbe42SPatrick Rudolph if (cy8c95x0_read_regs_mask(chip, CY8C95X0_INTSTATUS, trigger, ones)) 995e6cbbe42SPatrick Rudolph return false; 996e6cbbe42SPatrick Rudolph 997e6cbbe42SPatrick Rudolph /* Check latched inputs */ 998e6cbbe42SPatrick Rudolph if (cy8c95x0_read_regs_mask(chip, CY8C95X0_INPUT, cur_stat, trigger)) 999e6cbbe42SPatrick Rudolph return false; 1000e6cbbe42SPatrick Rudolph 1001e6cbbe42SPatrick Rudolph /* Apply filter for rising/falling edge selection */ 1002e6cbbe42SPatrick Rudolph bitmap_replace(new_stat, chip->irq_trig_fall, chip->irq_trig_raise, 1003e6cbbe42SPatrick Rudolph cur_stat, MAX_LINE); 1004e6cbbe42SPatrick Rudolph 1005e6cbbe42SPatrick Rudolph bitmap_and(pending, new_stat, trigger, MAX_LINE); 1006e6cbbe42SPatrick Rudolph 1007e6cbbe42SPatrick Rudolph return !bitmap_empty(pending, MAX_LINE); 1008e6cbbe42SPatrick Rudolph } 1009e6cbbe42SPatrick Rudolph 1010e6cbbe42SPatrick Rudolph static irqreturn_t cy8c95x0_irq_handler(int irq, void *devid) 1011e6cbbe42SPatrick Rudolph { 1012e6cbbe42SPatrick Rudolph struct cy8c95x0_pinctrl *chip = devid; 1013e6cbbe42SPatrick Rudolph struct gpio_chip *gc = &chip->gpio_chip; 1014e6cbbe42SPatrick Rudolph DECLARE_BITMAP(pending, MAX_LINE); 1015e6cbbe42SPatrick Rudolph int nested_irq, level; 1016e6cbbe42SPatrick Rudolph bool ret; 1017e6cbbe42SPatrick Rudolph 1018e6cbbe42SPatrick Rudolph ret = cy8c95x0_irq_pending(chip, pending); 1019e6cbbe42SPatrick Rudolph if (!ret) 1020e6cbbe42SPatrick Rudolph return IRQ_RETVAL(0); 1021e6cbbe42SPatrick Rudolph 1022e6cbbe42SPatrick Rudolph ret = 0; 1023e6cbbe42SPatrick Rudolph for_each_set_bit(level, pending, MAX_LINE) { 1024e6cbbe42SPatrick Rudolph /* Already accounted for 4bit gap in GPort2 */ 1025e6cbbe42SPatrick Rudolph nested_irq = irq_find_mapping(gc->irq.domain, level); 1026e6cbbe42SPatrick Rudolph 1027e6cbbe42SPatrick Rudolph if (unlikely(nested_irq <= 0)) { 1028e6cbbe42SPatrick Rudolph dev_warn_ratelimited(gc->parent, "unmapped interrupt %d\n", level); 1029e6cbbe42SPatrick Rudolph continue; 1030e6cbbe42SPatrick Rudolph } 1031e6cbbe42SPatrick Rudolph 1032e6cbbe42SPatrick Rudolph if (test_bit(level, chip->irq_trig_low)) 1033e6cbbe42SPatrick Rudolph while (!cy8c95x0_gpio_get_value(gc, level)) 1034e6cbbe42SPatrick Rudolph handle_nested_irq(nested_irq); 1035e6cbbe42SPatrick Rudolph else if (test_bit(level, chip->irq_trig_high)) 1036e6cbbe42SPatrick Rudolph while (cy8c95x0_gpio_get_value(gc, level)) 1037e6cbbe42SPatrick Rudolph handle_nested_irq(nested_irq); 1038e6cbbe42SPatrick Rudolph else 1039e6cbbe42SPatrick Rudolph handle_nested_irq(nested_irq); 1040e6cbbe42SPatrick Rudolph 1041e6cbbe42SPatrick Rudolph ret = 1; 1042e6cbbe42SPatrick Rudolph } 1043e6cbbe42SPatrick Rudolph 1044e6cbbe42SPatrick Rudolph return IRQ_RETVAL(ret); 1045e6cbbe42SPatrick Rudolph } 1046e6cbbe42SPatrick Rudolph 1047e6cbbe42SPatrick Rudolph static int cy8c95x0_pinctrl_get_groups_count(struct pinctrl_dev *pctldev) 1048e6cbbe42SPatrick Rudolph { 1049e6cbbe42SPatrick Rudolph struct cy8c95x0_pinctrl *chip = pinctrl_dev_get_drvdata(pctldev); 1050e6cbbe42SPatrick Rudolph 1051e6cbbe42SPatrick Rudolph return chip->tpin; 1052e6cbbe42SPatrick Rudolph } 1053e6cbbe42SPatrick Rudolph 1054e6cbbe42SPatrick Rudolph static const char *cy8c95x0_pinctrl_get_group_name(struct pinctrl_dev *pctldev, 1055e6cbbe42SPatrick Rudolph unsigned int group) 1056e6cbbe42SPatrick Rudolph { 1057e6cbbe42SPatrick Rudolph return cy8c95x0_groups[group]; 1058e6cbbe42SPatrick Rudolph } 1059e6cbbe42SPatrick Rudolph 1060e6cbbe42SPatrick Rudolph static int cy8c95x0_pinctrl_get_group_pins(struct pinctrl_dev *pctldev, 1061e6cbbe42SPatrick Rudolph unsigned int group, 1062e6cbbe42SPatrick Rudolph const unsigned int **pins, 1063e6cbbe42SPatrick Rudolph unsigned int *num_pins) 1064e6cbbe42SPatrick Rudolph { 1065e6cbbe42SPatrick Rudolph *pins = &cy8c9560_pins[group].number; 1066e6cbbe42SPatrick Rudolph *num_pins = 1; 1067e6cbbe42SPatrick Rudolph return 0; 1068e6cbbe42SPatrick Rudolph } 1069e6cbbe42SPatrick Rudolph 1070f12352f3SAndy Shevchenko static const char *cy8c95x0_get_fname(unsigned int selector) 1071f12352f3SAndy Shevchenko { 1072f12352f3SAndy Shevchenko if (selector == 0) 1073f12352f3SAndy Shevchenko return "gpio"; 1074f12352f3SAndy Shevchenko else 1075f12352f3SAndy Shevchenko return "pwm"; 1076f12352f3SAndy Shevchenko } 1077f12352f3SAndy Shevchenko 1078f12352f3SAndy Shevchenko static void cy8c95x0_pin_dbg_show(struct pinctrl_dev *pctldev, struct seq_file *s, 1079f12352f3SAndy Shevchenko unsigned int pin) 1080f12352f3SAndy Shevchenko { 1081f12352f3SAndy Shevchenko struct cy8c95x0_pinctrl *chip = pinctrl_dev_get_drvdata(pctldev); 1082f12352f3SAndy Shevchenko DECLARE_BITMAP(mask, MAX_LINE); 1083f12352f3SAndy Shevchenko DECLARE_BITMAP(pwm, MAX_LINE); 1084f12352f3SAndy Shevchenko 1085f12352f3SAndy Shevchenko bitmap_zero(mask, MAX_LINE); 1086f12352f3SAndy Shevchenko __set_bit(pin, mask); 1087f12352f3SAndy Shevchenko 1088f12352f3SAndy Shevchenko if (cy8c95x0_read_regs_mask(chip, CY8C95X0_PWMSEL, pwm, mask)) { 1089f12352f3SAndy Shevchenko seq_puts(s, "not available"); 1090f12352f3SAndy Shevchenko return; 1091f12352f3SAndy Shevchenko } 1092f12352f3SAndy Shevchenko 1093f12352f3SAndy Shevchenko seq_printf(s, "MODE:%s", cy8c95x0_get_fname(test_bit(pin, pwm))); 1094f12352f3SAndy Shevchenko } 1095f12352f3SAndy Shevchenko 1096e6cbbe42SPatrick Rudolph static const struct pinctrl_ops cy8c95x0_pinctrl_ops = { 1097e6cbbe42SPatrick Rudolph .get_groups_count = cy8c95x0_pinctrl_get_groups_count, 1098e6cbbe42SPatrick Rudolph .get_group_name = cy8c95x0_pinctrl_get_group_name, 1099e6cbbe42SPatrick Rudolph .get_group_pins = cy8c95x0_pinctrl_get_group_pins, 11008586466eSAndy Shevchenko #ifdef CONFIG_OF 1101e6cbbe42SPatrick Rudolph .dt_node_to_map = pinconf_generic_dt_node_to_map_pin, 1102e6cbbe42SPatrick Rudolph .dt_free_map = pinconf_generic_dt_free_map, 11038586466eSAndy Shevchenko #endif 1104f12352f3SAndy Shevchenko .pin_dbg_show = cy8c95x0_pin_dbg_show, 1105e6cbbe42SPatrick Rudolph }; 1106e6cbbe42SPatrick Rudolph 1107ee6cac37SAndy Shevchenko static const char *cy8c95x0_get_function_name(struct pinctrl_dev *pctldev, unsigned int selector) 1108f12352f3SAndy Shevchenko { 1109f12352f3SAndy Shevchenko return cy8c95x0_get_fname(selector); 1110f12352f3SAndy Shevchenko } 1111f12352f3SAndy Shevchenko 1112e6cbbe42SPatrick Rudolph static int cy8c95x0_get_functions_count(struct pinctrl_dev *pctldev) 1113e6cbbe42SPatrick Rudolph { 1114e6cbbe42SPatrick Rudolph return 2; 1115e6cbbe42SPatrick Rudolph } 1116e6cbbe42SPatrick Rudolph 1117ee6cac37SAndy Shevchenko static int cy8c95x0_get_function_groups(struct pinctrl_dev *pctldev, unsigned int selector, 1118e6cbbe42SPatrick Rudolph const char * const **groups, 1119e6cbbe42SPatrick Rudolph unsigned int * const num_groups) 1120e6cbbe42SPatrick Rudolph { 1121e6cbbe42SPatrick Rudolph struct cy8c95x0_pinctrl *chip = pinctrl_dev_get_drvdata(pctldev); 1122e6cbbe42SPatrick Rudolph 1123e6cbbe42SPatrick Rudolph *groups = cy8c95x0_groups; 1124e6cbbe42SPatrick Rudolph *num_groups = chip->tpin; 1125e6cbbe42SPatrick Rudolph return 0; 1126e6cbbe42SPatrick Rudolph } 1127e6cbbe42SPatrick Rudolph 1128e6cbbe42SPatrick Rudolph static int cy8c95x0_pinmux_cfg(struct cy8c95x0_pinctrl *chip, 1129e6cbbe42SPatrick Rudolph unsigned int val, 1130e6cbbe42SPatrick Rudolph unsigned long off) 1131e6cbbe42SPatrick Rudolph { 1132e6cbbe42SPatrick Rudolph u8 port = cypress_get_port(chip, off); 1133e6cbbe42SPatrick Rudolph u8 bit = cypress_get_pin_mask(chip, off); 1134e6cbbe42SPatrick Rudolph int ret; 1135e6cbbe42SPatrick Rudolph 113663e23304SAndy Shevchenko /* Select port */ 1137e6cbbe42SPatrick Rudolph ret = regmap_write(chip->regmap, CY8C95X0_PORTSEL, port); 1138e6cbbe42SPatrick Rudolph if (ret < 0) 1139e6cbbe42SPatrick Rudolph return ret; 1140e6cbbe42SPatrick Rudolph 1141e6cbbe42SPatrick Rudolph ret = regmap_write_bits(chip->regmap, CY8C95X0_PWMSEL, bit, val ? bit : 0); 1142e6cbbe42SPatrick Rudolph if (ret < 0) 1143e6cbbe42SPatrick Rudolph return ret; 1144e6cbbe42SPatrick Rudolph 1145e6cbbe42SPatrick Rudolph /* Set direction to output & set output to 1 so that PWM can work */ 1146e6cbbe42SPatrick Rudolph ret = regmap_write_bits(chip->regmap, CY8C95X0_DIRECTION, bit, bit); 1147e6cbbe42SPatrick Rudolph if (ret < 0) 1148e6cbbe42SPatrick Rudolph return ret; 1149e6cbbe42SPatrick Rudolph 1150e6cbbe42SPatrick Rudolph return regmap_write_bits(chip->regmap, CY8C95X0_OUTPUT_(port), bit, bit); 1151e6cbbe42SPatrick Rudolph } 1152e6cbbe42SPatrick Rudolph 1153e6cbbe42SPatrick Rudolph static int cy8c95x0_set_mux(struct pinctrl_dev *pctldev, unsigned int selector, 1154e6cbbe42SPatrick Rudolph unsigned int group) 1155e6cbbe42SPatrick Rudolph { 1156e6cbbe42SPatrick Rudolph struct cy8c95x0_pinctrl *chip = pinctrl_dev_get_drvdata(pctldev); 115756e380cfSAndy Shevchenko int ret; 1158e6cbbe42SPatrick Rudolph 115956e380cfSAndy Shevchenko mutex_lock(&chip->i2c_lock); 116056e380cfSAndy Shevchenko ret = cy8c95x0_pinmux_cfg(chip, selector, group); 116156e380cfSAndy Shevchenko mutex_unlock(&chip->i2c_lock); 116256e380cfSAndy Shevchenko 116356e380cfSAndy Shevchenko return ret; 1164e6cbbe42SPatrick Rudolph } 1165e6cbbe42SPatrick Rudolph 1166e6cbbe42SPatrick Rudolph static const struct pinmux_ops cy8c95x0_pmxops = { 1167e6cbbe42SPatrick Rudolph .get_functions_count = cy8c95x0_get_functions_count, 1168ee6cac37SAndy Shevchenko .get_function_name = cy8c95x0_get_function_name, 1169ee6cac37SAndy Shevchenko .get_function_groups = cy8c95x0_get_function_groups, 1170e6cbbe42SPatrick Rudolph .set_mux = cy8c95x0_set_mux, 1171e6cbbe42SPatrick Rudolph .strict = true, 1172e6cbbe42SPatrick Rudolph }; 1173e6cbbe42SPatrick Rudolph 1174e6cbbe42SPatrick Rudolph static int cy8c95x0_pinconf_get(struct pinctrl_dev *pctldev, unsigned int pin, 1175e6cbbe42SPatrick Rudolph unsigned long *config) 1176e6cbbe42SPatrick Rudolph { 1177e6cbbe42SPatrick Rudolph struct cy8c95x0_pinctrl *chip = pinctrl_dev_get_drvdata(pctldev); 1178e6cbbe42SPatrick Rudolph 1179e6cbbe42SPatrick Rudolph return cy8c95x0_gpio_get_pincfg(chip, pin, config); 1180e6cbbe42SPatrick Rudolph } 1181e6cbbe42SPatrick Rudolph 1182e6cbbe42SPatrick Rudolph static int cy8c95x0_pinconf_set(struct pinctrl_dev *pctldev, unsigned int pin, 1183e6cbbe42SPatrick Rudolph unsigned long *configs, unsigned int num_configs) 1184e6cbbe42SPatrick Rudolph { 1185e6cbbe42SPatrick Rudolph struct cy8c95x0_pinctrl *chip = pinctrl_dev_get_drvdata(pctldev); 1186e6cbbe42SPatrick Rudolph int ret = 0; 1187e6cbbe42SPatrick Rudolph int i; 1188e6cbbe42SPatrick Rudolph 1189e6cbbe42SPatrick Rudolph for (i = 0; i < num_configs; i++) { 1190e6cbbe42SPatrick Rudolph ret = cy8c95x0_gpio_set_pincfg(chip, pin, configs[i]); 1191e6cbbe42SPatrick Rudolph if (ret) 1192e6cbbe42SPatrick Rudolph return ret; 1193e6cbbe42SPatrick Rudolph } 1194e6cbbe42SPatrick Rudolph 1195e6cbbe42SPatrick Rudolph return ret; 1196e6cbbe42SPatrick Rudolph } 1197e6cbbe42SPatrick Rudolph 1198e6cbbe42SPatrick Rudolph static const struct pinconf_ops cy8c95x0_pinconf_ops = { 1199e6cbbe42SPatrick Rudolph .pin_config_get = cy8c95x0_pinconf_get, 1200e6cbbe42SPatrick Rudolph .pin_config_set = cy8c95x0_pinconf_set, 1201e6cbbe42SPatrick Rudolph .is_generic = true, 1202e6cbbe42SPatrick Rudolph }; 1203e6cbbe42SPatrick Rudolph 1204e6cbbe42SPatrick Rudolph static int cy8c95x0_irq_setup(struct cy8c95x0_pinctrl *chip, int irq) 1205e6cbbe42SPatrick Rudolph { 1206e6cbbe42SPatrick Rudolph struct gpio_irq_chip *girq = &chip->gpio_chip.irq; 1207e6cbbe42SPatrick Rudolph DECLARE_BITMAP(pending_irqs, MAX_LINE); 1208e6cbbe42SPatrick Rudolph int ret; 1209e6cbbe42SPatrick Rudolph 1210e6cbbe42SPatrick Rudolph mutex_init(&chip->irq_lock); 1211e6cbbe42SPatrick Rudolph 1212e6cbbe42SPatrick Rudolph bitmap_zero(pending_irqs, MAX_LINE); 1213e6cbbe42SPatrick Rudolph 1214e6cbbe42SPatrick Rudolph /* Read IRQ status register to clear all pending interrupts */ 1215e6cbbe42SPatrick Rudolph ret = cy8c95x0_irq_pending(chip, pending_irqs); 1216e6cbbe42SPatrick Rudolph if (ret) { 1217e6cbbe42SPatrick Rudolph dev_err(chip->dev, "failed to clear irq status register\n"); 1218e6cbbe42SPatrick Rudolph return ret; 1219e6cbbe42SPatrick Rudolph } 1220e6cbbe42SPatrick Rudolph 1221e6cbbe42SPatrick Rudolph /* Mask all interrupts */ 1222e6cbbe42SPatrick Rudolph bitmap_fill(chip->irq_mask, MAX_LINE); 1223e6cbbe42SPatrick Rudolph 1224f5d62025SAndy Shevchenko gpio_irq_chip_set_chip(girq, &cy8c95x0_irqchip); 1225e6cbbe42SPatrick Rudolph 1226e6cbbe42SPatrick Rudolph /* This will let us handle the parent IRQ in the driver */ 1227e6cbbe42SPatrick Rudolph girq->parent_handler = NULL; 1228e6cbbe42SPatrick Rudolph girq->num_parents = 0; 1229e6cbbe42SPatrick Rudolph girq->parents = NULL; 1230e6cbbe42SPatrick Rudolph girq->default_type = IRQ_TYPE_NONE; 1231e6cbbe42SPatrick Rudolph girq->handler = handle_simple_irq; 1232e6cbbe42SPatrick Rudolph girq->threaded = true; 1233e6cbbe42SPatrick Rudolph 1234e6cbbe42SPatrick Rudolph ret = devm_request_threaded_irq(chip->dev, irq, 1235e6cbbe42SPatrick Rudolph NULL, cy8c95x0_irq_handler, 1236e6cbbe42SPatrick Rudolph IRQF_ONESHOT | IRQF_SHARED | IRQF_TRIGGER_HIGH, 1237e6cbbe42SPatrick Rudolph dev_name(chip->dev), chip); 1238e6cbbe42SPatrick Rudolph if (ret) { 1239e6cbbe42SPatrick Rudolph dev_err(chip->dev, "failed to request irq %d\n", irq); 1240e6cbbe42SPatrick Rudolph return ret; 1241e6cbbe42SPatrick Rudolph } 1242e6cbbe42SPatrick Rudolph dev_info(chip->dev, "Registered threaded IRQ\n"); 1243e6cbbe42SPatrick Rudolph 1244e6cbbe42SPatrick Rudolph return 0; 1245e6cbbe42SPatrick Rudolph } 1246e6cbbe42SPatrick Rudolph 1247e6cbbe42SPatrick Rudolph static int cy8c95x0_setup_pinctrl(struct cy8c95x0_pinctrl *chip) 1248e6cbbe42SPatrick Rudolph { 1249e6cbbe42SPatrick Rudolph struct pinctrl_desc *pd = &chip->pinctrl_desc; 1250e6cbbe42SPatrick Rudolph 1251e6cbbe42SPatrick Rudolph pd->pctlops = &cy8c95x0_pinctrl_ops; 1252e6cbbe42SPatrick Rudolph pd->confops = &cy8c95x0_pinconf_ops; 1253e6cbbe42SPatrick Rudolph pd->pmxops = &cy8c95x0_pmxops; 1254641d6cc6SAndy Shevchenko pd->name = dev_name(chip->dev); 1255e6cbbe42SPatrick Rudolph pd->pins = cy8c9560_pins; 1256e6cbbe42SPatrick Rudolph pd->npins = chip->tpin; 1257e6cbbe42SPatrick Rudolph pd->owner = THIS_MODULE; 1258e6cbbe42SPatrick Rudolph 125963e23304SAndy Shevchenko chip->pctldev = devm_pinctrl_register(chip->dev, pd, chip); 1260e6cbbe42SPatrick Rudolph if (IS_ERR(chip->pctldev)) 1261e6cbbe42SPatrick Rudolph return dev_err_probe(chip->dev, PTR_ERR(chip->pctldev), 1262e6cbbe42SPatrick Rudolph "can't register controller\n"); 126363e23304SAndy Shevchenko 1264e6cbbe42SPatrick Rudolph return 0; 1265e6cbbe42SPatrick Rudolph } 1266e6cbbe42SPatrick Rudolph 1267e6cbbe42SPatrick Rudolph static int cy8c95x0_detect(struct i2c_client *client, 1268e6cbbe42SPatrick Rudolph struct i2c_board_info *info) 1269e6cbbe42SPatrick Rudolph { 1270e6cbbe42SPatrick Rudolph struct i2c_adapter *adapter = client->adapter; 1271e6cbbe42SPatrick Rudolph int ret; 1272e6cbbe42SPatrick Rudolph const char *name; 1273e6cbbe42SPatrick Rudolph 1274e6cbbe42SPatrick Rudolph if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) 1275e6cbbe42SPatrick Rudolph return -ENODEV; 1276e6cbbe42SPatrick Rudolph 1277e6cbbe42SPatrick Rudolph ret = i2c_smbus_read_byte_data(client, CY8C95X0_DEVID); 1278e6cbbe42SPatrick Rudolph if (ret < 0) 1279e6cbbe42SPatrick Rudolph return ret; 12809540a836SAndy Shevchenko switch (ret & GENMASK(7, 4)) { 1281e6cbbe42SPatrick Rudolph case 0x20: 1282e6cbbe42SPatrick Rudolph name = cy8c95x0_id[0].name; 1283e6cbbe42SPatrick Rudolph break; 1284e6cbbe42SPatrick Rudolph case 0x40: 1285e6cbbe42SPatrick Rudolph name = cy8c95x0_id[1].name; 1286e6cbbe42SPatrick Rudolph break; 1287e6cbbe42SPatrick Rudolph case 0x60: 1288e6cbbe42SPatrick Rudolph name = cy8c95x0_id[2].name; 1289e6cbbe42SPatrick Rudolph break; 1290e6cbbe42SPatrick Rudolph default: 1291e6cbbe42SPatrick Rudolph return -ENODEV; 1292e6cbbe42SPatrick Rudolph } 1293e6cbbe42SPatrick Rudolph 1294e6cbbe42SPatrick Rudolph dev_info(&client->dev, "Found a %s chip at 0x%02x.\n", name, client->addr); 1295e6cbbe42SPatrick Rudolph strscpy(info->type, name, I2C_NAME_SIZE); 1296e6cbbe42SPatrick Rudolph 129743dcf873SAndy Shevchenko return 0; 1298e6cbbe42SPatrick Rudolph } 1299e6cbbe42SPatrick Rudolph 1300e6cbbe42SPatrick Rudolph static int cy8c95x0_probe(struct i2c_client *client) 1301e6cbbe42SPatrick Rudolph { 1302e6cbbe42SPatrick Rudolph struct cy8c95x0_pinctrl *chip; 1303e6cbbe42SPatrick Rudolph struct regulator *reg; 1304e6cbbe42SPatrick Rudolph int ret; 1305e6cbbe42SPatrick Rudolph 1306e6cbbe42SPatrick Rudolph chip = devm_kzalloc(&client->dev, sizeof(*chip), GFP_KERNEL); 1307e6cbbe42SPatrick Rudolph if (!chip) 1308e6cbbe42SPatrick Rudolph return -ENOMEM; 1309e6cbbe42SPatrick Rudolph 1310e6cbbe42SPatrick Rudolph chip->dev = &client->dev; 1311e6cbbe42SPatrick Rudolph 1312e6cbbe42SPatrick Rudolph /* Set the device type */ 13138586466eSAndy Shevchenko chip->driver_data = (unsigned long)device_get_match_data(&client->dev); 13148586466eSAndy Shevchenko if (!chip->driver_data) 1315e6cbbe42SPatrick Rudolph chip->driver_data = i2c_match_id(cy8c95x0_id, client)->driver_data; 1316e6cbbe42SPatrick Rudolph if (!chip->driver_data) 1317e6cbbe42SPatrick Rudolph return -ENODEV; 1318e6cbbe42SPatrick Rudolph 1319e6cbbe42SPatrick Rudolph i2c_set_clientdata(client, chip); 1320e6cbbe42SPatrick Rudolph 1321e6cbbe42SPatrick Rudolph chip->tpin = chip->driver_data & CY8C95X0_GPIO_MASK; 1322e6cbbe42SPatrick Rudolph chip->nport = DIV_ROUND_UP(CY8C95X0_PIN_TO_OFFSET(chip->tpin), BANK_SZ); 1323e6cbbe42SPatrick Rudolph 1324e6cbbe42SPatrick Rudolph switch (chip->tpin) { 1325e6cbbe42SPatrick Rudolph case 20: 1326e6cbbe42SPatrick Rudolph strscpy(chip->name, cy8c95x0_id[0].name, I2C_NAME_SIZE); 1327e6cbbe42SPatrick Rudolph break; 1328e6cbbe42SPatrick Rudolph case 40: 1329e6cbbe42SPatrick Rudolph strscpy(chip->name, cy8c95x0_id[1].name, I2C_NAME_SIZE); 1330e6cbbe42SPatrick Rudolph break; 1331e6cbbe42SPatrick Rudolph case 60: 1332e6cbbe42SPatrick Rudolph strscpy(chip->name, cy8c95x0_id[2].name, I2C_NAME_SIZE); 1333e6cbbe42SPatrick Rudolph break; 1334c3e40952SAndy Shevchenko default: 1335c3e40952SAndy Shevchenko return -ENODEV; 1336e6cbbe42SPatrick Rudolph } 1337e6cbbe42SPatrick Rudolph 1338e6cbbe42SPatrick Rudolph reg = devm_regulator_get(&client->dev, "vdd"); 1339e6cbbe42SPatrick Rudolph if (IS_ERR(reg)) { 1340e6cbbe42SPatrick Rudolph if (PTR_ERR(reg) == -EPROBE_DEFER) 1341e6cbbe42SPatrick Rudolph return -EPROBE_DEFER; 1342e6cbbe42SPatrick Rudolph } else { 1343e6cbbe42SPatrick Rudolph ret = regulator_enable(reg); 1344e6cbbe42SPatrick Rudolph if (ret) { 1345e6cbbe42SPatrick Rudolph dev_err(&client->dev, "failed to enable regulator vdd: %d\n", ret); 1346e6cbbe42SPatrick Rudolph return ret; 1347e6cbbe42SPatrick Rudolph } 1348e6cbbe42SPatrick Rudolph chip->regulator = reg; 1349e6cbbe42SPatrick Rudolph } 1350e6cbbe42SPatrick Rudolph 1351e6cbbe42SPatrick Rudolph chip->regmap = devm_regmap_init_i2c(client, &cy8c95x0_i2c_regmap); 1352e6cbbe42SPatrick Rudolph if (IS_ERR(chip->regmap)) { 1353e6cbbe42SPatrick Rudolph ret = PTR_ERR(chip->regmap); 1354e6cbbe42SPatrick Rudolph goto err_exit; 1355e6cbbe42SPatrick Rudolph } 1356e6cbbe42SPatrick Rudolph 1357e6cbbe42SPatrick Rudolph bitmap_zero(chip->push_pull, MAX_LINE); 1358e6cbbe42SPatrick Rudolph bitmap_zero(chip->shiftmask, MAX_LINE); 1359e6cbbe42SPatrick Rudolph bitmap_set(chip->shiftmask, 0, 20); 1360e6cbbe42SPatrick Rudolph mutex_init(&chip->i2c_lock); 1361e6cbbe42SPatrick Rudolph 1362785b1bd8SAndy Shevchenko if (dmi_first_match(cy8c95x0_dmi_acpi_irq_info)) { 1363785b1bd8SAndy Shevchenko ret = cy8c95x0_acpi_get_irq(&client->dev); 1364785b1bd8SAndy Shevchenko if (ret > 0) 1365785b1bd8SAndy Shevchenko client->irq = ret; 1366785b1bd8SAndy Shevchenko } 1367785b1bd8SAndy Shevchenko 1368e6cbbe42SPatrick Rudolph if (client->irq) { 1369e6cbbe42SPatrick Rudolph ret = cy8c95x0_irq_setup(chip, client->irq); 1370e6cbbe42SPatrick Rudolph if (ret) 1371e6cbbe42SPatrick Rudolph goto err_exit; 1372e6cbbe42SPatrick Rudolph } 1373e6cbbe42SPatrick Rudolph 1374d86e0344SAndy Shevchenko ret = cy8c95x0_setup_pinctrl(chip); 1375e6cbbe42SPatrick Rudolph if (ret) 1376e6cbbe42SPatrick Rudolph goto err_exit; 1377e6cbbe42SPatrick Rudolph 1378d86e0344SAndy Shevchenko ret = cy8c95x0_setup_gpiochip(chip); 1379e6cbbe42SPatrick Rudolph if (ret) 1380e6cbbe42SPatrick Rudolph goto err_exit; 1381e6cbbe42SPatrick Rudolph 1382e6cbbe42SPatrick Rudolph return 0; 1383e6cbbe42SPatrick Rudolph 1384e6cbbe42SPatrick Rudolph err_exit: 1385e6cbbe42SPatrick Rudolph if (!IS_ERR_OR_NULL(chip->regulator)) 1386e6cbbe42SPatrick Rudolph regulator_disable(chip->regulator); 1387e6cbbe42SPatrick Rudolph return ret; 1388e6cbbe42SPatrick Rudolph } 1389e6cbbe42SPatrick Rudolph 1390bbe2a5d8SStephen Rothwell static void cy8c95x0_remove(struct i2c_client *client) 1391e6cbbe42SPatrick Rudolph { 1392e6cbbe42SPatrick Rudolph struct cy8c95x0_pinctrl *chip = i2c_get_clientdata(client); 1393e6cbbe42SPatrick Rudolph 1394e6cbbe42SPatrick Rudolph if (!IS_ERR_OR_NULL(chip->regulator)) 1395e6cbbe42SPatrick Rudolph regulator_disable(chip->regulator); 1396e6cbbe42SPatrick Rudolph } 1397e6cbbe42SPatrick Rudolph 1398618a43ffSAndy Shevchenko static const struct acpi_device_id cy8c95x0_acpi_ids[] = { 1399618a43ffSAndy Shevchenko { "INT3490", 40, }, 1400618a43ffSAndy Shevchenko { } 1401618a43ffSAndy Shevchenko }; 1402618a43ffSAndy Shevchenko MODULE_DEVICE_TABLE(acpi, cy8c95x0_acpi_ids); 1403618a43ffSAndy Shevchenko 1404e6cbbe42SPatrick Rudolph static struct i2c_driver cy8c95x0_driver = { 1405e6cbbe42SPatrick Rudolph .driver = { 1406e6cbbe42SPatrick Rudolph .name = "cy8c95x0-pinctrl", 1407e6cbbe42SPatrick Rudolph .of_match_table = cy8c95x0_dt_ids, 1408618a43ffSAndy Shevchenko .acpi_match_table = cy8c95x0_acpi_ids, 1409e6cbbe42SPatrick Rudolph }, 1410e6cbbe42SPatrick Rudolph .probe_new = cy8c95x0_probe, 1411e6cbbe42SPatrick Rudolph .remove = cy8c95x0_remove, 1412e6cbbe42SPatrick Rudolph .id_table = cy8c95x0_id, 1413e6cbbe42SPatrick Rudolph .detect = cy8c95x0_detect, 1414e6cbbe42SPatrick Rudolph }; 1415e6cbbe42SPatrick Rudolph module_i2c_driver(cy8c95x0_driver); 1416e6cbbe42SPatrick Rudolph 1417e6cbbe42SPatrick Rudolph MODULE_AUTHOR("Patrick Rudolph <patrick.rudolph@9elements.com>"); 1418e6cbbe42SPatrick Rudolph MODULE_AUTHOR("Naresh Solanki <naresh.solanki@9elements.com>"); 1419e6cbbe42SPatrick Rudolph MODULE_DESCRIPTION("Pinctrl driver for CY8C95X0"); 1420e6cbbe42SPatrick Rudolph MODULE_LICENSE("GPL"); 1421