linux/drivers/gpio/gpio-hisi.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-only
   2/* Copyright (c) 2020 HiSilicon Limited. */
   3#include <linux/gpio/driver.h>
   4#include <linux/module.h>
   5#include <linux/mod_devicetable.h>
   6#include <linux/platform_device.h>
   7#include <linux/property.h>
   8
   9#define HISI_GPIO_SWPORT_DR_SET_WX      0x000
  10#define HISI_GPIO_SWPORT_DR_CLR_WX      0x004
  11#define HISI_GPIO_SWPORT_DDR_SET_WX     0x010
  12#define HISI_GPIO_SWPORT_DDR_CLR_WX     0x014
  13#define HISI_GPIO_SWPORT_DDR_ST_WX      0x018
  14#define HISI_GPIO_INTEN_SET_WX          0x020
  15#define HISI_GPIO_INTEN_CLR_WX          0x024
  16#define HISI_GPIO_INTMASK_SET_WX        0x030
  17#define HISI_GPIO_INTMASK_CLR_WX        0x034
  18#define HISI_GPIO_INTTYPE_EDGE_SET_WX   0x040
  19#define HISI_GPIO_INTTYPE_EDGE_CLR_WX   0x044
  20#define HISI_GPIO_INT_POLARITY_SET_WX   0x050
  21#define HISI_GPIO_INT_POLARITY_CLR_WX   0x054
  22#define HISI_GPIO_DEBOUNCE_SET_WX       0x060
  23#define HISI_GPIO_DEBOUNCE_CLR_WX       0x064
  24#define HISI_GPIO_INTSTATUS_WX          0x070
  25#define HISI_GPIO_PORTA_EOI_WX          0x078
  26#define HISI_GPIO_EXT_PORT_WX           0x080
  27#define HISI_GPIO_INTCOMB_MASK_WX       0x0a0
  28#define HISI_GPIO_INT_DEDGE_SET         0x0b0
  29#define HISI_GPIO_INT_DEDGE_CLR         0x0b4
  30#define HISI_GPIO_INT_DEDGE_ST          0x0b8
  31
  32#define HISI_GPIO_LINE_NUM_MAX  32
  33#define HISI_GPIO_DRIVER_NAME   "gpio-hisi"
  34
  35struct hisi_gpio {
  36        struct gpio_chip        chip;
  37        struct device           *dev;
  38        void __iomem            *reg_base;
  39        unsigned int            line_num;
  40        struct irq_chip         irq_chip;
  41        int                     irq;
  42};
  43
  44static inline u32 hisi_gpio_read_reg(struct gpio_chip *chip,
  45                                     unsigned int off)
  46{
  47        struct hisi_gpio *hisi_gpio =
  48                        container_of(chip, struct hisi_gpio, chip);
  49        void __iomem *reg = hisi_gpio->reg_base + off;
  50
  51        return readl(reg);
  52}
  53
  54static inline void hisi_gpio_write_reg(struct gpio_chip *chip,
  55                                       unsigned int off, u32 val)
  56{
  57        struct hisi_gpio *hisi_gpio =
  58                        container_of(chip, struct hisi_gpio, chip);
  59        void __iomem *reg = hisi_gpio->reg_base + off;
  60
  61        writel(val, reg);
  62}
  63
  64static void hisi_gpio_set_debounce(struct gpio_chip *chip, unsigned int off,
  65                                   u32 debounce)
  66{
  67        if (debounce)
  68                hisi_gpio_write_reg(chip, HISI_GPIO_DEBOUNCE_SET_WX, BIT(off));
  69        else
  70                hisi_gpio_write_reg(chip, HISI_GPIO_DEBOUNCE_CLR_WX, BIT(off));
  71}
  72
  73static int hisi_gpio_set_config(struct gpio_chip *chip, unsigned int offset,
  74                                unsigned long config)
  75{
  76        u32 config_para = pinconf_to_config_param(config);
  77        u32 config_arg;
  78
  79        switch (config_para) {
  80        case PIN_CONFIG_INPUT_DEBOUNCE:
  81                config_arg = pinconf_to_config_argument(config);
  82                hisi_gpio_set_debounce(chip, offset, config_arg);
  83                break;
  84        default:
  85                return -ENOTSUPP;
  86        }
  87
  88        return 0;
  89}
  90
  91static void hisi_gpio_set_ack(struct irq_data *d)
  92{
  93        struct gpio_chip *chip = irq_data_get_irq_chip_data(d);
  94
  95        hisi_gpio_write_reg(chip, HISI_GPIO_PORTA_EOI_WX, BIT(irqd_to_hwirq(d)));
  96}
  97
  98static void hisi_gpio_irq_set_mask(struct irq_data *d)
  99{
 100        struct gpio_chip *chip = irq_data_get_irq_chip_data(d);
 101
 102        hisi_gpio_write_reg(chip, HISI_GPIO_INTMASK_SET_WX, BIT(irqd_to_hwirq(d)));
 103}
 104
 105static void hisi_gpio_irq_clr_mask(struct irq_data *d)
 106{
 107        struct gpio_chip *chip = irq_data_get_irq_chip_data(d);
 108
 109        hisi_gpio_write_reg(chip, HISI_GPIO_INTMASK_CLR_WX, BIT(irqd_to_hwirq(d)));
 110}
 111
 112static int hisi_gpio_irq_set_type(struct irq_data *d, u32 type)
 113{
 114        struct gpio_chip *chip = irq_data_get_irq_chip_data(d);
 115        unsigned int mask = BIT(irqd_to_hwirq(d));
 116
 117        switch (type) {
 118        case IRQ_TYPE_EDGE_BOTH:
 119                hisi_gpio_write_reg(chip, HISI_GPIO_INT_DEDGE_SET, mask);
 120                break;
 121        case IRQ_TYPE_EDGE_RISING:
 122                hisi_gpio_write_reg(chip, HISI_GPIO_INTTYPE_EDGE_SET_WX, mask);
 123                hisi_gpio_write_reg(chip, HISI_GPIO_INT_POLARITY_SET_WX, mask);
 124                break;
 125        case IRQ_TYPE_EDGE_FALLING:
 126                hisi_gpio_write_reg(chip, HISI_GPIO_INTTYPE_EDGE_SET_WX, mask);
 127                hisi_gpio_write_reg(chip, HISI_GPIO_INT_POLARITY_CLR_WX, mask);
 128                break;
 129        case IRQ_TYPE_LEVEL_HIGH:
 130                hisi_gpio_write_reg(chip, HISI_GPIO_INTTYPE_EDGE_CLR_WX, mask);
 131                hisi_gpio_write_reg(chip, HISI_GPIO_INT_POLARITY_SET_WX, mask);
 132                break;
 133        case IRQ_TYPE_LEVEL_LOW:
 134                hisi_gpio_write_reg(chip, HISI_GPIO_INTTYPE_EDGE_CLR_WX, mask);
 135                hisi_gpio_write_reg(chip, HISI_GPIO_INT_POLARITY_CLR_WX, mask);
 136                break;
 137        default:
 138                return -EINVAL;
 139        }
 140
 141        /*
 142         * The dual-edge interrupt and other interrupt's registers do not
 143         * take effect at the same time. The registers of the two-edge
 144         * interrupts have higher priorities, the configuration of
 145         * the dual-edge interrupts must be disabled before the configuration
 146         * of other kind of interrupts.
 147         */
 148        if (type != IRQ_TYPE_EDGE_BOTH) {
 149                unsigned int both = hisi_gpio_read_reg(chip, HISI_GPIO_INT_DEDGE_ST);
 150
 151                if (both & mask)
 152                        hisi_gpio_write_reg(chip, HISI_GPIO_INT_DEDGE_CLR, mask);
 153        }
 154
 155        if (type & IRQ_TYPE_LEVEL_MASK)
 156                irq_set_handler_locked(d, handle_level_irq);
 157        else if (type & IRQ_TYPE_EDGE_BOTH)
 158                irq_set_handler_locked(d, handle_edge_irq);
 159
 160        return 0;
 161}
 162
 163static void hisi_gpio_irq_enable(struct irq_data *d)
 164{
 165        struct gpio_chip *chip = irq_data_get_irq_chip_data(d);
 166
 167        hisi_gpio_irq_clr_mask(d);
 168        hisi_gpio_write_reg(chip, HISI_GPIO_INTEN_SET_WX, BIT(irqd_to_hwirq(d)));
 169}
 170
 171static void hisi_gpio_irq_disable(struct irq_data *d)
 172{
 173        struct gpio_chip *chip = irq_data_get_irq_chip_data(d);
 174
 175        hisi_gpio_irq_set_mask(d);
 176        hisi_gpio_write_reg(chip, HISI_GPIO_INTEN_CLR_WX, BIT(irqd_to_hwirq(d)));
 177}
 178
 179static void hisi_gpio_irq_handler(struct irq_desc *desc)
 180{
 181        struct hisi_gpio *hisi_gpio = irq_desc_get_handler_data(desc);
 182        unsigned long irq_msk = hisi_gpio_read_reg(&hisi_gpio->chip,
 183                                                   HISI_GPIO_INTSTATUS_WX);
 184        struct irq_chip *irq_c = irq_desc_get_chip(desc);
 185        int hwirq;
 186
 187        chained_irq_enter(irq_c, desc);
 188        for_each_set_bit(hwirq, &irq_msk, HISI_GPIO_LINE_NUM_MAX)
 189                generic_handle_irq(irq_find_mapping(hisi_gpio->chip.irq.domain,
 190                                                    hwirq));
 191        chained_irq_exit(irq_c, desc);
 192}
 193
 194static void hisi_gpio_init_irq(struct hisi_gpio *hisi_gpio)
 195{
 196        struct gpio_chip *chip = &hisi_gpio->chip;
 197        struct gpio_irq_chip *girq_chip = &chip->irq;
 198
 199        /* Set hooks for irq_chip */
 200        hisi_gpio->irq_chip.irq_ack = hisi_gpio_set_ack;
 201        hisi_gpio->irq_chip.irq_mask = hisi_gpio_irq_set_mask;
 202        hisi_gpio->irq_chip.irq_unmask = hisi_gpio_irq_clr_mask;
 203        hisi_gpio->irq_chip.irq_set_type = hisi_gpio_irq_set_type;
 204        hisi_gpio->irq_chip.irq_enable = hisi_gpio_irq_enable;
 205        hisi_gpio->irq_chip.irq_disable = hisi_gpio_irq_disable;
 206
 207        girq_chip->chip = &hisi_gpio->irq_chip;
 208        girq_chip->default_type = IRQ_TYPE_NONE;
 209        girq_chip->num_parents = 1;
 210        girq_chip->parents = &hisi_gpio->irq;
 211        girq_chip->parent_handler = hisi_gpio_irq_handler;
 212        girq_chip->parent_handler_data = hisi_gpio;
 213
 214        /* Clear Mask of GPIO controller combine IRQ */
 215        hisi_gpio_write_reg(chip, HISI_GPIO_INTCOMB_MASK_WX, 1);
 216}
 217
 218static const struct acpi_device_id hisi_gpio_acpi_match[] = {
 219        {"HISI0184", 0},
 220        {}
 221};
 222MODULE_DEVICE_TABLE(acpi, hisi_gpio_acpi_match);
 223
 224static void hisi_gpio_get_pdata(struct device *dev,
 225                                struct hisi_gpio *hisi_gpio)
 226{
 227        struct platform_device *pdev = to_platform_device(dev);
 228        struct fwnode_handle *fwnode;
 229        int idx = 0;
 230
 231        device_for_each_child_node(dev, fwnode)  {
 232                /* Cycle for once, no need for an array to save line_num */
 233                if (fwnode_property_read_u32(fwnode, "ngpios",
 234                                             &hisi_gpio->line_num)) {
 235                        dev_err(dev,
 236                                "failed to get number of lines for port%d and use default value instead\n",
 237                                idx);
 238                        hisi_gpio->line_num = HISI_GPIO_LINE_NUM_MAX;
 239                }
 240
 241                if (WARN_ON(hisi_gpio->line_num > HISI_GPIO_LINE_NUM_MAX))
 242                        hisi_gpio->line_num = HISI_GPIO_LINE_NUM_MAX;
 243
 244                hisi_gpio->irq = platform_get_irq(pdev, idx);
 245
 246                dev_info(dev,
 247                         "get hisi_gpio[%d] with %d lines\n", idx,
 248                         hisi_gpio->line_num);
 249
 250                idx++;
 251        }
 252}
 253
 254static int hisi_gpio_probe(struct platform_device *pdev)
 255{
 256        struct device *dev = &pdev->dev;
 257        struct hisi_gpio *hisi_gpio;
 258        int port_num;
 259        int ret;
 260
 261        /*
 262         * One GPIO controller own one port currently,
 263         * if we get more from ACPI table, return error.
 264         */
 265        port_num = device_get_child_node_count(dev);
 266        if (WARN_ON(port_num != 1))
 267                return -ENODEV;
 268
 269        hisi_gpio = devm_kzalloc(dev, sizeof(*hisi_gpio), GFP_KERNEL);
 270        if (!hisi_gpio)
 271                return -ENOMEM;
 272
 273        hisi_gpio->reg_base = devm_platform_ioremap_resource(pdev, 0);
 274        if (IS_ERR(hisi_gpio->reg_base))
 275                return PTR_ERR(hisi_gpio->reg_base);
 276
 277        hisi_gpio_get_pdata(dev, hisi_gpio);
 278
 279        hisi_gpio->dev = dev;
 280
 281        ret = bgpio_init(&hisi_gpio->chip, hisi_gpio->dev, 0x4,
 282                         hisi_gpio->reg_base + HISI_GPIO_EXT_PORT_WX,
 283                         hisi_gpio->reg_base + HISI_GPIO_SWPORT_DR_SET_WX,
 284                         hisi_gpio->reg_base + HISI_GPIO_SWPORT_DR_CLR_WX,
 285                         hisi_gpio->reg_base + HISI_GPIO_SWPORT_DDR_SET_WX,
 286                         hisi_gpio->reg_base + HISI_GPIO_SWPORT_DDR_CLR_WX,
 287                         BGPIOF_NO_SET_ON_INPUT);
 288        if (ret) {
 289                dev_err(dev, "failed to init, ret = %d\n", ret);
 290                return ret;
 291        }
 292
 293        hisi_gpio->chip.set_config = hisi_gpio_set_config;
 294        hisi_gpio->chip.ngpio = hisi_gpio->line_num;
 295        hisi_gpio->chip.bgpio_dir_unreadable = 1;
 296        hisi_gpio->chip.base = -1;
 297
 298        if (hisi_gpio->irq > 0)
 299                hisi_gpio_init_irq(hisi_gpio);
 300
 301        ret = devm_gpiochip_add_data(dev, &hisi_gpio->chip, hisi_gpio);
 302        if (ret) {
 303                dev_err(dev, "failed to register gpiochip, ret = %d\n", ret);
 304                return ret;
 305        }
 306
 307        return 0;
 308}
 309
 310static struct platform_driver hisi_gpio_driver = {
 311        .driver         = {
 312                .name   = HISI_GPIO_DRIVER_NAME,
 313                .acpi_match_table = hisi_gpio_acpi_match,
 314        },
 315        .probe          = hisi_gpio_probe,
 316};
 317
 318module_platform_driver(hisi_gpio_driver);
 319
 320MODULE_LICENSE("GPL");
 321MODULE_AUTHOR("Luo Jiaxing <luojiaxing@huawei.com>");
 322MODULE_DESCRIPTION("HiSilicon GPIO controller driver");
 323MODULE_ALIAS("platform:" HISI_GPIO_DRIVER_NAME);
 324