^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-or-later
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * SYSCON GPIO driver
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Copyright (C) 2014 Alexander Shiyan <shc_work@mail.ru>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) #include <linux/err.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #include <linux/gpio/driver.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/of.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/of_device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/platform_device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/regmap.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <linux/mfd/syscon.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #define GPIO_SYSCON_FEAT_IN BIT(0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #define GPIO_SYSCON_FEAT_OUT BIT(1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #define GPIO_SYSCON_FEAT_DIR BIT(2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) /* SYSCON driver is designed to use 32-bit wide registers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #define SYSCON_REG_SIZE (4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #define SYSCON_REG_BITS (SYSCON_REG_SIZE * 8)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) * struct syscon_gpio_data - Configuration for the device.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) * @compatible: SYSCON driver compatible string.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) * @flags: Set of GPIO_SYSCON_FEAT_ flags:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) * GPIO_SYSCON_FEAT_IN: GPIOs supports input,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) * GPIO_SYSCON_FEAT_OUT: GPIOs supports output,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) * GPIO_SYSCON_FEAT_DIR: GPIOs supports switch direction.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) * @bit_count: Number of bits used as GPIOs.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) * @dat_bit_offset: Offset (in bits) to the first GPIO bit.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) * @dir_bit_offset: Optional offset (in bits) to the first bit to switch
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) * GPIO direction (Used with GPIO_SYSCON_FEAT_DIR flag).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) * @set: HW specific callback to assigns output value
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) * for signal "offset"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) struct syscon_gpio_data {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) const char *compatible;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) unsigned int flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) unsigned int bit_count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) unsigned int dat_bit_offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) unsigned int dir_bit_offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) void (*set)(struct gpio_chip *chip,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) unsigned offset, int value);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) struct syscon_gpio_priv {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) struct gpio_chip chip;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) struct regmap *syscon;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) const struct syscon_gpio_data *data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) u32 dreg_offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) u32 dir_reg_offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) static int syscon_gpio_get(struct gpio_chip *chip, unsigned offset)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) struct syscon_gpio_priv *priv = gpiochip_get_data(chip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) unsigned int val, offs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) offs = priv->dreg_offset + priv->data->dat_bit_offset + offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) ret = regmap_read(priv->syscon,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) (offs / SYSCON_REG_BITS) * SYSCON_REG_SIZE, &val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) return !!(val & BIT(offs % SYSCON_REG_BITS));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) static void syscon_gpio_set(struct gpio_chip *chip, unsigned offset, int val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) struct syscon_gpio_priv *priv = gpiochip_get_data(chip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) unsigned int offs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) offs = priv->dreg_offset + priv->data->dat_bit_offset + offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) regmap_update_bits(priv->syscon,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) (offs / SYSCON_REG_BITS) * SYSCON_REG_SIZE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) BIT(offs % SYSCON_REG_BITS),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) val ? BIT(offs % SYSCON_REG_BITS) : 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) static int syscon_gpio_dir_in(struct gpio_chip *chip, unsigned offset)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) struct syscon_gpio_priv *priv = gpiochip_get_data(chip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) if (priv->data->flags & GPIO_SYSCON_FEAT_DIR) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) unsigned int offs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) offs = priv->dir_reg_offset +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) priv->data->dir_bit_offset + offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) regmap_update_bits(priv->syscon,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) (offs / SYSCON_REG_BITS) * SYSCON_REG_SIZE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) BIT(offs % SYSCON_REG_BITS), 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) static int syscon_gpio_dir_out(struct gpio_chip *chip, unsigned offset, int val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) struct syscon_gpio_priv *priv = gpiochip_get_data(chip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) if (priv->data->flags & GPIO_SYSCON_FEAT_DIR) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) unsigned int offs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) offs = priv->dir_reg_offset +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) priv->data->dir_bit_offset + offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) regmap_update_bits(priv->syscon,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) (offs / SYSCON_REG_BITS) * SYSCON_REG_SIZE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) BIT(offs % SYSCON_REG_BITS),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) BIT(offs % SYSCON_REG_BITS));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) chip->set(chip, offset, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) static const struct syscon_gpio_data clps711x_mctrl_gpio = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) /* ARM CLPS711X SYSFLG1 Bits 8-10 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) .compatible = "cirrus,ep7209-syscon1",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) .flags = GPIO_SYSCON_FEAT_IN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) .bit_count = 3,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) .dat_bit_offset = 0x40 * 8 + 8,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) static void rockchip_gpio_set(struct gpio_chip *chip, unsigned int offset,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) int val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) struct syscon_gpio_priv *priv = gpiochip_get_data(chip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) unsigned int offs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) u8 bit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) u32 data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) offs = priv->dreg_offset + priv->data->dat_bit_offset + offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) bit = offs % SYSCON_REG_BITS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) data = (val ? BIT(bit) : 0) | BIT(bit + 16);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) ret = regmap_write(priv->syscon,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) (offs / SYSCON_REG_BITS) * SYSCON_REG_SIZE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) dev_err(chip->parent, "gpio write failed ret(%d)\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) static const struct syscon_gpio_data rockchip_rk3328_gpio_mute = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) /* RK3328 GPIO_MUTE is an output only pin at GRF_SOC_CON10[1] */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) .flags = GPIO_SYSCON_FEAT_OUT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) .bit_count = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) .dat_bit_offset = 0x0428 * 8 + 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) .set = rockchip_gpio_set,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) #define KEYSTONE_LOCK_BIT BIT(0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) static void keystone_gpio_set(struct gpio_chip *chip, unsigned offset, int val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) struct syscon_gpio_priv *priv = gpiochip_get_data(chip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) unsigned int offs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) offs = priv->dreg_offset + priv->data->dat_bit_offset + offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) if (!val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) ret = regmap_update_bits(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) priv->syscon,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) (offs / SYSCON_REG_BITS) * SYSCON_REG_SIZE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) BIT(offs % SYSCON_REG_BITS) | KEYSTONE_LOCK_BIT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) BIT(offs % SYSCON_REG_BITS) | KEYSTONE_LOCK_BIT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) dev_err(chip->parent, "gpio write failed ret(%d)\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) static const struct syscon_gpio_data keystone_dsp_gpio = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) /* ARM Keystone 2 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) .compatible = NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) .flags = GPIO_SYSCON_FEAT_OUT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) .bit_count = 28,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) .dat_bit_offset = 4,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) .set = keystone_gpio_set,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) static const struct of_device_id syscon_gpio_ids[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) .compatible = "cirrus,ep7209-mctrl-gpio",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) .data = &clps711x_mctrl_gpio,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) .compatible = "ti,keystone-dsp-gpio",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) .data = &keystone_dsp_gpio,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) .compatible = "rockchip,rk3328-grf-gpio",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) .data = &rockchip_rk3328_gpio_mute,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) { }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) MODULE_DEVICE_TABLE(of, syscon_gpio_ids);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) static int syscon_gpio_probe(struct platform_device *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) struct device *dev = &pdev->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) struct syscon_gpio_priv *priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) struct device_node *np = dev->of_node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) if (!priv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) priv->data = of_device_get_match_data(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) if (priv->data->compatible) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) priv->syscon = syscon_regmap_lookup_by_compatible(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) priv->data->compatible);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) if (IS_ERR(priv->syscon))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) return PTR_ERR(priv->syscon);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) priv->syscon =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) syscon_regmap_lookup_by_phandle(np, "gpio,syscon-dev");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) if (IS_ERR(priv->syscon) && np->parent)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) priv->syscon = syscon_node_to_regmap(np->parent);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) if (IS_ERR(priv->syscon))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) return PTR_ERR(priv->syscon);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) ret = of_property_read_u32_index(np, "gpio,syscon-dev", 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) &priv->dreg_offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) dev_err(dev, "can't read the data register offset!\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) priv->dreg_offset <<= 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) ret = of_property_read_u32_index(np, "gpio,syscon-dev", 2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) &priv->dir_reg_offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) dev_dbg(dev, "can't read the dir register offset!\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) priv->dir_reg_offset <<= 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) priv->chip.parent = dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) priv->chip.owner = THIS_MODULE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) priv->chip.label = dev_name(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) priv->chip.base = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) priv->chip.ngpio = priv->data->bit_count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) priv->chip.get = syscon_gpio_get;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) if (priv->data->flags & GPIO_SYSCON_FEAT_IN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) priv->chip.direction_input = syscon_gpio_dir_in;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) if (priv->data->flags & GPIO_SYSCON_FEAT_OUT) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) priv->chip.set = priv->data->set ? : syscon_gpio_set;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) priv->chip.direction_output = syscon_gpio_dir_out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) platform_set_drvdata(pdev, priv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) return devm_gpiochip_add_data(&pdev->dev, &priv->chip, priv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) static struct platform_driver syscon_gpio_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) .driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) .name = "gpio-syscon",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) .of_match_table = syscon_gpio_ids,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) .probe = syscon_gpio_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) module_platform_driver(syscon_gpio_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) MODULE_AUTHOR("Alexander Shiyan <shc_work@mail.ru>");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) MODULE_DESCRIPTION("SYSCON GPIO driver");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) MODULE_LICENSE("GPL");