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