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