LCOV - code coverage report
Current view: top level - drivers/pinctrl/bcm - pinctrl-bcm2835.c (source / functions) Hit Total Coverage
Test: gcov_data_raspi2_real_modules_combined.info Lines: 151 366 41.3 %
Date: 2020-09-30 20:25:40 Functions: 21 37 56.8 %
Branches: 50 162 30.9 %

           Branch data     Line data    Source code
       1                 :            : // SPDX-License-Identifier: GPL-2.0+
       2                 :            : /*
       3                 :            :  * Driver for Broadcom BCM2835 GPIO unit (pinctrl + GPIO)
       4                 :            :  *
       5                 :            :  * Copyright (C) 2012 Chris Boot, Simon Arlott, Stephen Warren
       6                 :            :  *
       7                 :            :  * This driver is inspired by:
       8                 :            :  * pinctrl-nomadik.c, please see original file for copyright information
       9                 :            :  * pinctrl-tegra.c, please see original file for copyright information
      10                 :            :  */
      11                 :            : 
      12                 :            : #include <linux/bitmap.h>
      13                 :            : #include <linux/bug.h>
      14                 :            : #include <linux/delay.h>
      15                 :            : #include <linux/device.h>
      16                 :            : #include <linux/err.h>
      17                 :            : #include <linux/gpio/driver.h>
      18                 :            : #include <linux/io.h>
      19                 :            : #include <linux/irq.h>
      20                 :            : #include <linux/irqdesc.h>
      21                 :            : #include <linux/init.h>
      22                 :            : #include <linux/of_address.h>
      23                 :            : #include <linux/of.h>
      24                 :            : #include <linux/of_irq.h>
      25                 :            : #include <linux/pinctrl/consumer.h>
      26                 :            : #include <linux/pinctrl/machine.h>
      27                 :            : #include <linux/pinctrl/pinconf.h>
      28                 :            : #include <linux/pinctrl/pinctrl.h>
      29                 :            : #include <linux/pinctrl/pinmux.h>
      30                 :            : #include <linux/pinctrl/pinconf-generic.h>
      31                 :            : #include <linux/platform_device.h>
      32                 :            : #include <linux/seq_file.h>
      33                 :            : #include <linux/slab.h>
      34                 :            : #include <linux/spinlock.h>
      35                 :            : #include <linux/types.h>
      36                 :            : #include <dt-bindings/pinctrl/bcm2835.h>
      37                 :            : 
      38                 :            : #define MODULE_NAME "pinctrl-bcm2835"
      39                 :            : #define BCM2835_NUM_GPIOS 54
      40                 :            : #define BCM2835_NUM_BANKS 2
      41                 :            : #define BCM2835_NUM_IRQS  3
      42                 :            : 
      43                 :            : #define BCM2835_PIN_BITMAP_SZ \
      44                 :            :         DIV_ROUND_UP(BCM2835_NUM_GPIOS, sizeof(unsigned long) * 8)
      45                 :            : 
      46                 :            : /* GPIO register offsets */
      47                 :            : #define GPFSEL0         0x0     /* Function Select */
      48                 :            : #define GPSET0          0x1c    /* Pin Output Set */
      49                 :            : #define GPCLR0          0x28    /* Pin Output Clear */
      50                 :            : #define GPLEV0          0x34    /* Pin Level */
      51                 :            : #define GPEDS0          0x40    /* Pin Event Detect Status */
      52                 :            : #define GPREN0          0x4c    /* Pin Rising Edge Detect Enable */
      53                 :            : #define GPFEN0          0x58    /* Pin Falling Edge Detect Enable */
      54                 :            : #define GPHEN0          0x64    /* Pin High Detect Enable */
      55                 :            : #define GPLEN0          0x70    /* Pin Low Detect Enable */
      56                 :            : #define GPAREN0         0x7c    /* Pin Async Rising Edge Detect */
      57                 :            : #define GPAFEN0         0x88    /* Pin Async Falling Edge Detect */
      58                 :            : #define GPPUD           0x94    /* Pin Pull-up/down Enable */
      59                 :            : #define GPPUDCLK0       0x98    /* Pin Pull-up/down Enable Clock */
      60                 :            : #define GP_GPIO_PUP_PDN_CNTRL_REG0 0xe4 /* 2711 Pin Pull-up/down select */
      61                 :            : 
      62                 :            : #define FSEL_REG(p)             (GPFSEL0 + (((p) / 10) * 4))
      63                 :            : #define FSEL_SHIFT(p)           (((p) % 10) * 3)
      64                 :            : #define GPIO_REG_OFFSET(p)      ((p) / 32)
      65                 :            : #define GPIO_REG_SHIFT(p)       ((p) % 32)
      66                 :            : 
      67                 :            : #define PUD_2711_MASK           0x3
      68                 :            : #define PUD_2711_REG_OFFSET(p)  ((p) / 16)
      69                 :            : #define PUD_2711_REG_SHIFT(p)   (((p) % 16) * 2)
      70                 :            : 
      71                 :            : /* argument: bcm2835_pinconf_pull */
      72                 :            : #define BCM2835_PINCONF_PARAM_PULL      (PIN_CONFIG_END + 1)
      73                 :            : 
      74                 :            : #define BCM2711_PULL_NONE       0x0
      75                 :            : #define BCM2711_PULL_UP         0x1
      76                 :            : #define BCM2711_PULL_DOWN       0x2
      77                 :            : 
      78                 :            : struct bcm2835_pinctrl {
      79                 :            :         struct device *dev;
      80                 :            :         void __iomem *base;
      81                 :            :         int irq[BCM2835_NUM_IRQS];
      82                 :            : 
      83                 :            :         /* note: locking assumes each bank will have its own unsigned long */
      84                 :            :         unsigned long enabled_irq_map[BCM2835_NUM_BANKS];
      85                 :            :         unsigned int irq_type[BCM2835_NUM_GPIOS];
      86                 :            : 
      87                 :            :         struct pinctrl_dev *pctl_dev;
      88                 :            :         struct gpio_chip gpio_chip;
      89                 :            :         struct pinctrl_gpio_range gpio_range;
      90                 :            : 
      91                 :            :         raw_spinlock_t irq_lock[BCM2835_NUM_BANKS];
      92                 :            : };
      93                 :            : 
      94                 :            : /* pins are just named GPIO0..GPIO53 */
      95                 :            : #define BCM2835_GPIO_PIN(a) PINCTRL_PIN(a, "gpio" #a)
      96                 :            : static struct pinctrl_pin_desc bcm2835_gpio_pins[] = {
      97                 :            :         BCM2835_GPIO_PIN(0),
      98                 :            :         BCM2835_GPIO_PIN(1),
      99                 :            :         BCM2835_GPIO_PIN(2),
     100                 :            :         BCM2835_GPIO_PIN(3),
     101                 :            :         BCM2835_GPIO_PIN(4),
     102                 :            :         BCM2835_GPIO_PIN(5),
     103                 :            :         BCM2835_GPIO_PIN(6),
     104                 :            :         BCM2835_GPIO_PIN(7),
     105                 :            :         BCM2835_GPIO_PIN(8),
     106                 :            :         BCM2835_GPIO_PIN(9),
     107                 :            :         BCM2835_GPIO_PIN(10),
     108                 :            :         BCM2835_GPIO_PIN(11),
     109                 :            :         BCM2835_GPIO_PIN(12),
     110                 :            :         BCM2835_GPIO_PIN(13),
     111                 :            :         BCM2835_GPIO_PIN(14),
     112                 :            :         BCM2835_GPIO_PIN(15),
     113                 :            :         BCM2835_GPIO_PIN(16),
     114                 :            :         BCM2835_GPIO_PIN(17),
     115                 :            :         BCM2835_GPIO_PIN(18),
     116                 :            :         BCM2835_GPIO_PIN(19),
     117                 :            :         BCM2835_GPIO_PIN(20),
     118                 :            :         BCM2835_GPIO_PIN(21),
     119                 :            :         BCM2835_GPIO_PIN(22),
     120                 :            :         BCM2835_GPIO_PIN(23),
     121                 :            :         BCM2835_GPIO_PIN(24),
     122                 :            :         BCM2835_GPIO_PIN(25),
     123                 :            :         BCM2835_GPIO_PIN(26),
     124                 :            :         BCM2835_GPIO_PIN(27),
     125                 :            :         BCM2835_GPIO_PIN(28),
     126                 :            :         BCM2835_GPIO_PIN(29),
     127                 :            :         BCM2835_GPIO_PIN(30),
     128                 :            :         BCM2835_GPIO_PIN(31),
     129                 :            :         BCM2835_GPIO_PIN(32),
     130                 :            :         BCM2835_GPIO_PIN(33),
     131                 :            :         BCM2835_GPIO_PIN(34),
     132                 :            :         BCM2835_GPIO_PIN(35),
     133                 :            :         BCM2835_GPIO_PIN(36),
     134                 :            :         BCM2835_GPIO_PIN(37),
     135                 :            :         BCM2835_GPIO_PIN(38),
     136                 :            :         BCM2835_GPIO_PIN(39),
     137                 :            :         BCM2835_GPIO_PIN(40),
     138                 :            :         BCM2835_GPIO_PIN(41),
     139                 :            :         BCM2835_GPIO_PIN(42),
     140                 :            :         BCM2835_GPIO_PIN(43),
     141                 :            :         BCM2835_GPIO_PIN(44),
     142                 :            :         BCM2835_GPIO_PIN(45),
     143                 :            :         BCM2835_GPIO_PIN(46),
     144                 :            :         BCM2835_GPIO_PIN(47),
     145                 :            :         BCM2835_GPIO_PIN(48),
     146                 :            :         BCM2835_GPIO_PIN(49),
     147                 :            :         BCM2835_GPIO_PIN(50),
     148                 :            :         BCM2835_GPIO_PIN(51),
     149                 :            :         BCM2835_GPIO_PIN(52),
     150                 :            :         BCM2835_GPIO_PIN(53),
     151                 :            : };
     152                 :            : 
     153                 :            : /* one pin per group */
     154                 :            : static const char * const bcm2835_gpio_groups[] = {
     155                 :            :         "gpio0",
     156                 :            :         "gpio1",
     157                 :            :         "gpio2",
     158                 :            :         "gpio3",
     159                 :            :         "gpio4",
     160                 :            :         "gpio5",
     161                 :            :         "gpio6",
     162                 :            :         "gpio7",
     163                 :            :         "gpio8",
     164                 :            :         "gpio9",
     165                 :            :         "gpio10",
     166                 :            :         "gpio11",
     167                 :            :         "gpio12",
     168                 :            :         "gpio13",
     169                 :            :         "gpio14",
     170                 :            :         "gpio15",
     171                 :            :         "gpio16",
     172                 :            :         "gpio17",
     173                 :            :         "gpio18",
     174                 :            :         "gpio19",
     175                 :            :         "gpio20",
     176                 :            :         "gpio21",
     177                 :            :         "gpio22",
     178                 :            :         "gpio23",
     179                 :            :         "gpio24",
     180                 :            :         "gpio25",
     181                 :            :         "gpio26",
     182                 :            :         "gpio27",
     183                 :            :         "gpio28",
     184                 :            :         "gpio29",
     185                 :            :         "gpio30",
     186                 :            :         "gpio31",
     187                 :            :         "gpio32",
     188                 :            :         "gpio33",
     189                 :            :         "gpio34",
     190                 :            :         "gpio35",
     191                 :            :         "gpio36",
     192                 :            :         "gpio37",
     193                 :            :         "gpio38",
     194                 :            :         "gpio39",
     195                 :            :         "gpio40",
     196                 :            :         "gpio41",
     197                 :            :         "gpio42",
     198                 :            :         "gpio43",
     199                 :            :         "gpio44",
     200                 :            :         "gpio45",
     201                 :            :         "gpio46",
     202                 :            :         "gpio47",
     203                 :            :         "gpio48",
     204                 :            :         "gpio49",
     205                 :            :         "gpio50",
     206                 :            :         "gpio51",
     207                 :            :         "gpio52",
     208                 :            :         "gpio53",
     209                 :            : };
     210                 :            : 
     211                 :            : enum bcm2835_fsel {
     212                 :            :         BCM2835_FSEL_COUNT = 8,
     213                 :            :         BCM2835_FSEL_MASK = 0x7,
     214                 :            : };
     215                 :            : 
     216                 :            : static const char * const bcm2835_functions[BCM2835_FSEL_COUNT] = {
     217                 :            :         [BCM2835_FSEL_GPIO_IN] = "gpio_in",
     218                 :            :         [BCM2835_FSEL_GPIO_OUT] = "gpio_out",
     219                 :            :         [BCM2835_FSEL_ALT0] = "alt0",
     220                 :            :         [BCM2835_FSEL_ALT1] = "alt1",
     221                 :            :         [BCM2835_FSEL_ALT2] = "alt2",
     222                 :            :         [BCM2835_FSEL_ALT3] = "alt3",
     223                 :            :         [BCM2835_FSEL_ALT4] = "alt4",
     224                 :            :         [BCM2835_FSEL_ALT5] = "alt5",
     225                 :            : };
     226                 :            : 
     227                 :            : static const char * const irq_type_names[] = {
     228                 :            :         [IRQ_TYPE_NONE] = "none",
     229                 :            :         [IRQ_TYPE_EDGE_RISING] = "edge-rising",
     230                 :            :         [IRQ_TYPE_EDGE_FALLING] = "edge-falling",
     231                 :            :         [IRQ_TYPE_EDGE_BOTH] = "edge-both",
     232                 :            :         [IRQ_TYPE_LEVEL_HIGH] = "level-high",
     233                 :            :         [IRQ_TYPE_LEVEL_LOW] = "level-low",
     234                 :            : };
     235                 :            : 
     236                 :            : static inline u32 bcm2835_gpio_rd(struct bcm2835_pinctrl *pc, unsigned reg)
     237                 :            : {
     238                 :      34776 :         return readl(pc->base + reg);
     239                 :            : }
     240                 :            : 
     241                 :            : static inline void bcm2835_gpio_wr(struct bcm2835_pinctrl *pc, unsigned reg,
     242                 :            :                 u32 val)
     243                 :            : {
     244                 :    2432034 :         writel(val, pc->base + reg);
     245                 :            : }
     246                 :            : 
     247                 :            : static inline int bcm2835_gpio_get_bit(struct bcm2835_pinctrl *pc, unsigned reg,
     248                 :            :                 unsigned bit)
     249                 :            : {
     250                 :        621 :         reg += GPIO_REG_OFFSET(bit) * 4;
     251                 :        621 :         return (bcm2835_gpio_rd(pc, reg) >> GPIO_REG_SHIFT(bit)) & 1;
     252                 :            : }
     253                 :            : 
     254                 :            : /* note NOT a read/modify/write cycle */
     255                 :            : static inline void bcm2835_gpio_set_bit(struct bcm2835_pinctrl *pc,
     256                 :            :                 unsigned reg, unsigned bit)
     257                 :            : {
     258                 :    2424168 :         reg += GPIO_REG_OFFSET(bit) * 4;
     259                 :    2424168 :         bcm2835_gpio_wr(pc, reg, BIT(GPIO_REG_SHIFT(bit)));
     260                 :            : }
     261                 :            : 
     262                 :            : static inline enum bcm2835_fsel bcm2835_pinctrl_fsel_get(
     263                 :            :                 struct bcm2835_pinctrl *pc, unsigned pin)
     264                 :            : {
     265                 :      11592 :         u32 val = bcm2835_gpio_rd(pc, FSEL_REG(pin));
     266                 :      11592 :         enum bcm2835_fsel status = (val >> FSEL_SHIFT(pin)) & BCM2835_FSEL_MASK;
     267                 :            : 
     268                 :            :         dev_dbg(pc->dev, "get %08x (%u => %s)\n", val, pin,
     269                 :            :                         bcm2835_functions[status]);
     270                 :            : 
     271                 :            :         return status;
     272                 :            : }
     273                 :            : 
     274                 :       4761 : static inline void bcm2835_pinctrl_fsel_set(
     275                 :            :                 struct bcm2835_pinctrl *pc, unsigned pin,
     276                 :            :                 enum bcm2835_fsel fsel)
     277                 :            : {
     278                 :       4761 :         u32 val = bcm2835_gpio_rd(pc, FSEL_REG(pin));
     279                 :       4761 :         enum bcm2835_fsel cur = (val >> FSEL_SHIFT(pin)) & BCM2835_FSEL_MASK;
     280                 :            : 
     281                 :            :         dev_dbg(pc->dev, "read %08x (%u => %s)\n", val, pin,
     282                 :            :                         bcm2835_functions[cur]);
     283                 :            : 
     284         [ +  + ]:       4761 :         if (cur == fsel)
     285                 :       4761 :                 return;
     286                 :            : 
     287         [ +  + ]:       4140 :         if (cur != BCM2835_FSEL_GPIO_IN && fsel != BCM2835_FSEL_GPIO_IN) {
     288                 :            :                 /* always transition through GPIO_IN */
     289                 :       1242 :                 val &= ~(BCM2835_FSEL_MASK << FSEL_SHIFT(pin));
     290                 :            :                 val |= BCM2835_FSEL_GPIO_IN << FSEL_SHIFT(pin);
     291                 :            : 
     292                 :            :                 dev_dbg(pc->dev, "trans %08x (%u <= %s)\n", val, pin,
     293                 :            :                                 bcm2835_functions[BCM2835_FSEL_GPIO_IN]);
     294                 :            :                 bcm2835_gpio_wr(pc, FSEL_REG(pin), val);
     295                 :            :         }
     296                 :            : 
     297                 :       4140 :         val &= ~(BCM2835_FSEL_MASK << FSEL_SHIFT(pin));
     298                 :       4140 :         val |= fsel << FSEL_SHIFT(pin);
     299                 :            : 
     300                 :            :         dev_dbg(pc->dev, "write %08x (%u <= %s)\n", val, pin,
     301                 :            :                         bcm2835_functions[fsel]);
     302                 :            :         bcm2835_gpio_wr(pc, FSEL_REG(pin), val);
     303                 :            : }
     304                 :            : 
     305                 :        207 : static int bcm2835_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
     306                 :            : {
     307                 :        207 :         return pinctrl_gpio_direction_input(chip->base + offset);
     308                 :            : }
     309                 :            : 
     310                 :        621 : static int bcm2835_gpio_get(struct gpio_chip *chip, unsigned offset)
     311                 :            : {
     312                 :        621 :         struct bcm2835_pinctrl *pc = gpiochip_get_data(chip);
     313                 :            : 
     314                 :        621 :         return bcm2835_gpio_get_bit(pc, GPLEV0, offset);
     315                 :            : }
     316                 :            : 
     317                 :      11592 : static int bcm2835_gpio_get_direction(struct gpio_chip *chip, unsigned int offset)
     318                 :            : {
     319                 :      11592 :         struct bcm2835_pinctrl *pc = gpiochip_get_data(chip);
     320                 :            :         enum bcm2835_fsel fsel = bcm2835_pinctrl_fsel_get(pc, offset);
     321                 :            : 
     322                 :            :         /* Alternative function doesn't clearly provide a direction */
     323         [ +  + ]:      11592 :         if (fsel > BCM2835_FSEL_GPIO_OUT)
     324                 :            :                 return -EINVAL;
     325                 :            : 
     326                 :       9315 :         return (fsel == BCM2835_FSEL_GPIO_IN);
     327                 :            : }
     328                 :            : 
     329                 :    2424168 : static void bcm2835_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
     330                 :            : {
     331                 :    2424168 :         struct bcm2835_pinctrl *pc = gpiochip_get_data(chip);
     332                 :            : 
     333         [ +  + ]:    2424168 :         bcm2835_gpio_set_bit(pc, value ? GPSET0 : GPCLR0, offset);
     334                 :    2424168 : }
     335                 :            : 
     336                 :        414 : static int bcm2835_gpio_direction_output(struct gpio_chip *chip,
     337                 :            :                 unsigned offset, int value)
     338                 :            : {
     339                 :        414 :         bcm2835_gpio_set(chip, offset, value);
     340                 :        414 :         return pinctrl_gpio_direction_output(chip->base + offset);
     341                 :            : }
     342                 :            : 
     343                 :            : static const struct gpio_chip bcm2835_gpio_chip = {
     344                 :            :         .label = MODULE_NAME,
     345                 :            :         .owner = THIS_MODULE,
     346                 :            :         .request = gpiochip_generic_request,
     347                 :            :         .free = gpiochip_generic_free,
     348                 :            :         .direction_input = bcm2835_gpio_direction_input,
     349                 :            :         .direction_output = bcm2835_gpio_direction_output,
     350                 :            :         .get_direction = bcm2835_gpio_get_direction,
     351                 :            :         .get = bcm2835_gpio_get,
     352                 :            :         .set = bcm2835_gpio_set,
     353                 :            :         .set_config = gpiochip_generic_config,
     354                 :            :         .base = 0,
     355                 :            :         .ngpio = BCM2835_NUM_GPIOS,
     356                 :            :         .can_sleep = false,
     357                 :            : };
     358                 :            : 
     359                 :          0 : static void bcm2835_gpio_irq_handle_bank(struct bcm2835_pinctrl *pc,
     360                 :            :                                          unsigned int bank, u32 mask)
     361                 :            : {
     362                 :            :         unsigned long events;
     363                 :            :         unsigned offset;
     364                 :            :         unsigned gpio;
     365                 :            : 
     366                 :          0 :         events = bcm2835_gpio_rd(pc, GPEDS0 + bank * 4);
     367                 :          0 :         events &= mask;
     368                 :          0 :         events &= pc->enabled_irq_map[bank];
     369         [ #  # ]:          0 :         for_each_set_bit(offset, &events, 32) {
     370                 :          0 :                 gpio = (32 * bank) + offset;
     371                 :          0 :                 generic_handle_irq(irq_linear_revmap(pc->gpio_chip.irq.domain,
     372                 :            :                                                      gpio));
     373                 :            :         }
     374                 :          0 : }
     375                 :            : 
     376                 :          0 : static void bcm2835_gpio_irq_handler(struct irq_desc *desc)
     377                 :            : {
     378                 :            :         struct gpio_chip *chip = irq_desc_get_handler_data(desc);
     379                 :          0 :         struct bcm2835_pinctrl *pc = gpiochip_get_data(chip);
     380                 :            :         struct irq_chip *host_chip = irq_desc_get_chip(desc);
     381                 :          0 :         int irq = irq_desc_get_irq(desc);
     382                 :            :         int group;
     383                 :            :         int i;
     384                 :            : 
     385         [ #  # ]:          0 :         for (i = 0; i < ARRAY_SIZE(pc->irq); i++) {
     386         [ #  # ]:          0 :                 if (pc->irq[i] == irq) {
     387                 :          0 :                         group = i;
     388                 :          0 :                         break;
     389                 :            :                 }
     390                 :            :         }
     391                 :            :         /* This should not happen, every IRQ has a bank */
     392         [ #  # ]:          0 :         if (i == ARRAY_SIZE(pc->irq))
     393                 :          0 :                 BUG();
     394                 :            : 
     395                 :          0 :         chained_irq_enter(host_chip, desc);
     396                 :            : 
     397   [ #  #  #  # ]:          0 :         switch (group) {
     398                 :            :         case 0: /* IRQ0 covers GPIOs 0-27 */
     399                 :          0 :                 bcm2835_gpio_irq_handle_bank(pc, 0, 0x0fffffff);
     400                 :          0 :                 break;
     401                 :            :         case 1: /* IRQ1 covers GPIOs 28-45 */
     402                 :          0 :                 bcm2835_gpio_irq_handle_bank(pc, 0, 0xf0000000);
     403                 :          0 :                 bcm2835_gpio_irq_handle_bank(pc, 1, 0x00003fff);
     404                 :          0 :                 break;
     405                 :            :         case 2: /* IRQ2 covers GPIOs 46-53 */
     406                 :          0 :                 bcm2835_gpio_irq_handle_bank(pc, 1, 0x003fc000);
     407                 :          0 :                 break;
     408                 :            :         }
     409                 :            : 
     410                 :            :         chained_irq_exit(host_chip, desc);
     411                 :          0 : }
     412                 :            : 
     413                 :          0 : static inline void __bcm2835_gpio_irq_config(struct bcm2835_pinctrl *pc,
     414                 :            :         unsigned reg, unsigned offset, bool enable)
     415                 :            : {
     416                 :            :         u32 value;
     417                 :          0 :         reg += GPIO_REG_OFFSET(offset) * 4;
     418                 :            :         value = bcm2835_gpio_rd(pc, reg);
     419         [ #  # ]:          0 :         if (enable)
     420                 :          0 :                 value |= BIT(GPIO_REG_SHIFT(offset));
     421                 :            :         else
     422                 :          0 :                 value &= ~(BIT(GPIO_REG_SHIFT(offset)));
     423                 :            :         bcm2835_gpio_wr(pc, reg, value);
     424                 :          0 : }
     425                 :            : 
     426                 :            : /* fast path for IRQ handler */
     427                 :          0 : static void bcm2835_gpio_irq_config(struct bcm2835_pinctrl *pc,
     428                 :            :         unsigned offset, bool enable)
     429                 :            : {
     430   [ #  #  #  #  :          0 :         switch (pc->irq_type[offset]) {
                   #  # ]
     431                 :            :         case IRQ_TYPE_EDGE_RISING:
     432                 :          0 :                 __bcm2835_gpio_irq_config(pc, GPREN0, offset, enable);
     433                 :          0 :                 break;
     434                 :            : 
     435                 :            :         case IRQ_TYPE_EDGE_FALLING:
     436                 :          0 :                 __bcm2835_gpio_irq_config(pc, GPFEN0, offset, enable);
     437                 :          0 :                 break;
     438                 :            : 
     439                 :            :         case IRQ_TYPE_EDGE_BOTH:
     440                 :          0 :                 __bcm2835_gpio_irq_config(pc, GPREN0, offset, enable);
     441                 :          0 :                 __bcm2835_gpio_irq_config(pc, GPFEN0, offset, enable);
     442                 :          0 :                 break;
     443                 :            : 
     444                 :            :         case IRQ_TYPE_LEVEL_HIGH:
     445                 :          0 :                 __bcm2835_gpio_irq_config(pc, GPHEN0, offset, enable);
     446                 :          0 :                 break;
     447                 :            : 
     448                 :            :         case IRQ_TYPE_LEVEL_LOW:
     449                 :          0 :                 __bcm2835_gpio_irq_config(pc, GPLEN0, offset, enable);
     450                 :          0 :                 break;
     451                 :            :         }
     452                 :          0 : }
     453                 :            : 
     454                 :          0 : static void bcm2835_gpio_irq_enable(struct irq_data *data)
     455                 :            : {
     456                 :            :         struct gpio_chip *chip = irq_data_get_irq_chip_data(data);
     457                 :          0 :         struct bcm2835_pinctrl *pc = gpiochip_get_data(chip);
     458                 :            :         unsigned gpio = irqd_to_hwirq(data);
     459                 :          0 :         unsigned offset = GPIO_REG_SHIFT(gpio);
     460                 :          0 :         unsigned bank = GPIO_REG_OFFSET(gpio);
     461                 :            :         unsigned long flags;
     462                 :            : 
     463                 :          0 :         raw_spin_lock_irqsave(&pc->irq_lock[bank], flags);
     464                 :          0 :         set_bit(offset, &pc->enabled_irq_map[bank]);
     465                 :          0 :         bcm2835_gpio_irq_config(pc, gpio, true);
     466                 :          0 :         raw_spin_unlock_irqrestore(&pc->irq_lock[bank], flags);
     467                 :          0 : }
     468                 :            : 
     469                 :          0 : static void bcm2835_gpio_irq_disable(struct irq_data *data)
     470                 :            : {
     471                 :            :         struct gpio_chip *chip = irq_data_get_irq_chip_data(data);
     472                 :          0 :         struct bcm2835_pinctrl *pc = gpiochip_get_data(chip);
     473                 :            :         unsigned gpio = irqd_to_hwirq(data);
     474                 :          0 :         unsigned offset = GPIO_REG_SHIFT(gpio);
     475                 :          0 :         unsigned bank = GPIO_REG_OFFSET(gpio);
     476                 :            :         unsigned long flags;
     477                 :            : 
     478                 :          0 :         raw_spin_lock_irqsave(&pc->irq_lock[bank], flags);
     479                 :          0 :         bcm2835_gpio_irq_config(pc, gpio, false);
     480                 :            :         /* Clear events that were latched prior to clearing event sources */
     481                 :            :         bcm2835_gpio_set_bit(pc, GPEDS0, gpio);
     482                 :          0 :         clear_bit(offset, &pc->enabled_irq_map[bank]);
     483                 :          0 :         raw_spin_unlock_irqrestore(&pc->irq_lock[bank], flags);
     484                 :          0 : }
     485                 :            : 
     486                 :            : static int __bcm2835_gpio_irq_set_type_disabled(struct bcm2835_pinctrl *pc,
     487                 :            :         unsigned offset, unsigned int type)
     488                 :            : {
     489         [ #  # ]:          0 :         switch (type) {
     490                 :            :         case IRQ_TYPE_NONE:
     491                 :            :         case IRQ_TYPE_EDGE_RISING:
     492                 :            :         case IRQ_TYPE_EDGE_FALLING:
     493                 :            :         case IRQ_TYPE_EDGE_BOTH:
     494                 :            :         case IRQ_TYPE_LEVEL_HIGH:
     495                 :            :         case IRQ_TYPE_LEVEL_LOW:
     496                 :          0 :                 pc->irq_type[offset] = type;
     497                 :            :                 break;
     498                 :            : 
     499                 :            :         default:
     500                 :            :                 return -EINVAL;
     501                 :            :         }
     502                 :            :         return 0;
     503                 :            : }
     504                 :            : 
     505                 :            : /* slower path for reconfiguring IRQ type */
     506                 :          0 : static int __bcm2835_gpio_irq_set_type_enabled(struct bcm2835_pinctrl *pc,
     507                 :            :         unsigned offset, unsigned int type)
     508                 :            : {
     509   [ #  #  #  #  :          0 :         switch (type) {
                   #  # ]
     510                 :            :         case IRQ_TYPE_NONE:
     511         [ #  # ]:          0 :                 if (pc->irq_type[offset] != type) {
     512                 :          0 :                         bcm2835_gpio_irq_config(pc, offset, false);
     513                 :          0 :                         pc->irq_type[offset] = type;
     514                 :            :                 }
     515                 :            :                 break;
     516                 :            : 
     517                 :            :         case IRQ_TYPE_EDGE_RISING:
     518         [ #  # ]:          0 :                 if (pc->irq_type[offset] == IRQ_TYPE_EDGE_BOTH) {
     519                 :            :                         /* RISING already enabled, disable FALLING */
     520                 :          0 :                         pc->irq_type[offset] = IRQ_TYPE_EDGE_FALLING;
     521                 :          0 :                         bcm2835_gpio_irq_config(pc, offset, false);
     522                 :          0 :                         pc->irq_type[offset] = type;
     523         [ #  # ]:          0 :                 } else if (pc->irq_type[offset] != type) {
     524                 :          0 :                         bcm2835_gpio_irq_config(pc, offset, false);
     525                 :          0 :                         pc->irq_type[offset] = type;
     526                 :          0 :                         bcm2835_gpio_irq_config(pc, offset, true);
     527                 :            :                 }
     528                 :            :                 break;
     529                 :            : 
     530                 :            :         case IRQ_TYPE_EDGE_FALLING:
     531         [ #  # ]:          0 :                 if (pc->irq_type[offset] == IRQ_TYPE_EDGE_BOTH) {
     532                 :            :                         /* FALLING already enabled, disable RISING */
     533                 :          0 :                         pc->irq_type[offset] = IRQ_TYPE_EDGE_RISING;
     534                 :          0 :                         bcm2835_gpio_irq_config(pc, offset, false);
     535                 :          0 :                         pc->irq_type[offset] = type;
     536         [ #  # ]:          0 :                 } else if (pc->irq_type[offset] != type) {
     537                 :          0 :                         bcm2835_gpio_irq_config(pc, offset, false);
     538                 :          0 :                         pc->irq_type[offset] = type;
     539                 :          0 :                         bcm2835_gpio_irq_config(pc, offset, true);
     540                 :            :                 }
     541                 :            :                 break;
     542                 :            : 
     543                 :            :         case IRQ_TYPE_EDGE_BOTH:
     544         [ #  # ]:          0 :                 if (pc->irq_type[offset] == IRQ_TYPE_EDGE_RISING) {
     545                 :            :                         /* RISING already enabled, enable FALLING too */
     546                 :          0 :                         pc->irq_type[offset] = IRQ_TYPE_EDGE_FALLING;
     547                 :          0 :                         bcm2835_gpio_irq_config(pc, offset, true);
     548                 :          0 :                         pc->irq_type[offset] = type;
     549         [ #  # ]:          0 :                 } else if (pc->irq_type[offset] == IRQ_TYPE_EDGE_FALLING) {
     550                 :            :                         /* FALLING already enabled, enable RISING too */
     551                 :          0 :                         pc->irq_type[offset] = IRQ_TYPE_EDGE_RISING;
     552                 :          0 :                         bcm2835_gpio_irq_config(pc, offset, true);
     553                 :          0 :                         pc->irq_type[offset] = type;
     554         [ #  # ]:          0 :                 } else if (pc->irq_type[offset] != type) {
     555                 :          0 :                         bcm2835_gpio_irq_config(pc, offset, false);
     556                 :          0 :                         pc->irq_type[offset] = type;
     557                 :          0 :                         bcm2835_gpio_irq_config(pc, offset, true);
     558                 :            :                 }
     559                 :            :                 break;
     560                 :            : 
     561                 :            :         case IRQ_TYPE_LEVEL_HIGH:
     562                 :            :         case IRQ_TYPE_LEVEL_LOW:
     563         [ #  # ]:          0 :                 if (pc->irq_type[offset] != type) {
     564                 :          0 :                         bcm2835_gpio_irq_config(pc, offset, false);
     565                 :          0 :                         pc->irq_type[offset] = type;
     566                 :          0 :                         bcm2835_gpio_irq_config(pc, offset, true);
     567                 :            :                 }
     568                 :            :                 break;
     569                 :            : 
     570                 :            :         default:
     571                 :            :                 return -EINVAL;
     572                 :            :         }
     573                 :            :         return 0;
     574                 :            : }
     575                 :            : 
     576                 :          0 : static int bcm2835_gpio_irq_set_type(struct irq_data *data, unsigned int type)
     577                 :            : {
     578                 :            :         struct gpio_chip *chip = irq_data_get_irq_chip_data(data);
     579                 :          0 :         struct bcm2835_pinctrl *pc = gpiochip_get_data(chip);
     580                 :            :         unsigned gpio = irqd_to_hwirq(data);
     581                 :          0 :         unsigned offset = GPIO_REG_SHIFT(gpio);
     582                 :          0 :         unsigned bank = GPIO_REG_OFFSET(gpio);
     583                 :            :         unsigned long flags;
     584                 :            :         int ret;
     585                 :            : 
     586                 :          0 :         raw_spin_lock_irqsave(&pc->irq_lock[bank], flags);
     587                 :            : 
     588         [ #  # ]:          0 :         if (test_bit(offset, &pc->enabled_irq_map[bank]))
     589                 :          0 :                 ret = __bcm2835_gpio_irq_set_type_enabled(pc, gpio, type);
     590                 :            :         else
     591                 :            :                 ret = __bcm2835_gpio_irq_set_type_disabled(pc, gpio, type);
     592                 :            : 
     593         [ #  # ]:          0 :         if (type & IRQ_TYPE_EDGE_BOTH)
     594                 :            :                 irq_set_handler_locked(data, handle_edge_irq);
     595                 :            :         else
     596                 :            :                 irq_set_handler_locked(data, handle_level_irq);
     597                 :            : 
     598                 :          0 :         raw_spin_unlock_irqrestore(&pc->irq_lock[bank], flags);
     599                 :            : 
     600                 :          0 :         return ret;
     601                 :            : }
     602                 :            : 
     603                 :          0 : static void bcm2835_gpio_irq_ack(struct irq_data *data)
     604                 :            : {
     605                 :            :         struct gpio_chip *chip = irq_data_get_irq_chip_data(data);
     606                 :          0 :         struct bcm2835_pinctrl *pc = gpiochip_get_data(chip);
     607                 :            :         unsigned gpio = irqd_to_hwirq(data);
     608                 :            : 
     609                 :            :         bcm2835_gpio_set_bit(pc, GPEDS0, gpio);
     610                 :          0 : }
     611                 :            : 
     612                 :            : static struct irq_chip bcm2835_gpio_irq_chip = {
     613                 :            :         .name = MODULE_NAME,
     614                 :            :         .irq_enable = bcm2835_gpio_irq_enable,
     615                 :            :         .irq_disable = bcm2835_gpio_irq_disable,
     616                 :            :         .irq_set_type = bcm2835_gpio_irq_set_type,
     617                 :            :         .irq_ack = bcm2835_gpio_irq_ack,
     618                 :            :         .irq_mask = bcm2835_gpio_irq_disable,
     619                 :            :         .irq_unmask = bcm2835_gpio_irq_enable,
     620                 :            : };
     621                 :            : 
     622                 :       2898 : static int bcm2835_pctl_get_groups_count(struct pinctrl_dev *pctldev)
     623                 :            : {
     624                 :       2898 :         return ARRAY_SIZE(bcm2835_gpio_groups);
     625                 :            : }
     626                 :            : 
     627                 :     145935 : static const char *bcm2835_pctl_get_group_name(struct pinctrl_dev *pctldev,
     628                 :            :                 unsigned selector)
     629                 :            : {
     630                 :     145935 :         return bcm2835_gpio_groups[selector];
     631                 :            : }
     632                 :            : 
     633                 :       4140 : static int bcm2835_pctl_get_group_pins(struct pinctrl_dev *pctldev,
     634                 :            :                 unsigned selector,
     635                 :            :                 const unsigned **pins,
     636                 :            :                 unsigned *num_pins)
     637                 :            : {
     638                 :       4140 :         *pins = &bcm2835_gpio_pins[selector].number;
     639                 :       4140 :         *num_pins = 1;
     640                 :            : 
     641                 :       4140 :         return 0;
     642                 :            : }
     643                 :            : 
     644                 :          0 : static void bcm2835_pctl_pin_dbg_show(struct pinctrl_dev *pctldev,
     645                 :            :                 struct seq_file *s,
     646                 :            :                 unsigned offset)
     647                 :            : {
     648                 :          0 :         struct bcm2835_pinctrl *pc = pinctrl_dev_get_drvdata(pctldev);
     649                 :            :         struct gpio_chip *chip = &pc->gpio_chip;
     650                 :            :         enum bcm2835_fsel fsel = bcm2835_pinctrl_fsel_get(pc, offset);
     651                 :          0 :         const char *fname = bcm2835_functions[fsel];
     652                 :            :         int value = bcm2835_gpio_get_bit(pc, GPLEV0, offset);
     653                 :          0 :         int irq = irq_find_mapping(chip->irq.domain, offset);
     654                 :            : 
     655         [ #  # ]:          0 :         seq_printf(s, "function %s in %s; irq %d (%s)",
     656                 :            :                 fname, value ? "hi" : "lo",
     657                 :          0 :                 irq, irq_type_names[pc->irq_type[offset]]);
     658                 :          0 : }
     659                 :            : 
     660                 :        207 : static void bcm2835_pctl_dt_free_map(struct pinctrl_dev *pctldev,
     661                 :            :                 struct pinctrl_map *maps, unsigned num_maps)
     662                 :            : {
     663                 :            :         int i;
     664                 :            : 
     665         [ +  + ]:       1449 :         for (i = 0; i < num_maps; i++)
     666         [ -  + ]:       1242 :                 if (maps[i].type == PIN_MAP_TYPE_CONFIGS_PIN)
     667                 :          0 :                         kfree(maps[i].data.configs.configs);
     668                 :            : 
     669                 :        207 :         kfree(maps);
     670                 :        207 : }
     671                 :            : 
     672                 :       2898 : static int bcm2835_pctl_dt_node_to_map_func(struct bcm2835_pinctrl *pc,
     673                 :            :                 struct device_node *np, u32 pin, u32 fnum,
     674                 :            :                 struct pinctrl_map **maps)
     675                 :            : {
     676                 :       2898 :         struct pinctrl_map *map = *maps;
     677                 :            : 
     678         [ -  + ]:       2898 :         if (fnum >= ARRAY_SIZE(bcm2835_functions)) {
     679                 :          0 :                 dev_err(pc->dev, "%pOF: invalid brcm,function %d\n", np, fnum);
     680                 :          0 :                 return -EINVAL;
     681                 :            :         }
     682                 :            : 
     683                 :       2898 :         map->type = PIN_MAP_TYPE_MUX_GROUP;
     684                 :       2898 :         map->data.mux.group = bcm2835_gpio_groups[pin];
     685                 :       2898 :         map->data.mux.function = bcm2835_functions[fnum];
     686                 :       2898 :         (*maps)++;
     687                 :            : 
     688                 :       2898 :         return 0;
     689                 :            : }
     690                 :            : 
     691                 :          0 : static int bcm2835_pctl_dt_node_to_map_pull(struct bcm2835_pinctrl *pc,
     692                 :            :                 struct device_node *np, u32 pin, u32 pull,
     693                 :            :                 struct pinctrl_map **maps)
     694                 :            : {
     695                 :          0 :         struct pinctrl_map *map = *maps;
     696                 :            :         unsigned long *configs;
     697                 :            : 
     698         [ #  # ]:          0 :         if (pull > 2) {
     699                 :          0 :                 dev_err(pc->dev, "%pOF: invalid brcm,pull %d\n", np, pull);
     700                 :          0 :                 return -EINVAL;
     701                 :            :         }
     702                 :            : 
     703                 :          0 :         configs = kzalloc(sizeof(*configs), GFP_KERNEL);
     704         [ #  # ]:          0 :         if (!configs)
     705                 :            :                 return -ENOMEM;
     706                 :          0 :         configs[0] = pinconf_to_config_packed(BCM2835_PINCONF_PARAM_PULL, pull);
     707                 :            : 
     708                 :          0 :         map->type = PIN_MAP_TYPE_CONFIGS_PIN;
     709                 :          0 :         map->data.configs.group_or_pin = bcm2835_gpio_pins[pin].name;
     710                 :          0 :         map->data.configs.configs = configs;
     711                 :          0 :         map->data.configs.num_configs = 1;
     712                 :          0 :         (*maps)++;
     713                 :            : 
     714                 :          0 :         return 0;
     715                 :            : }
     716                 :            : 
     717                 :        621 : static int bcm2835_pctl_dt_node_to_map(struct pinctrl_dev *pctldev,
     718                 :            :                 struct device_node *np,
     719                 :            :                 struct pinctrl_map **map, unsigned int *num_maps)
     720                 :            : {
     721                 :        621 :         struct bcm2835_pinctrl *pc = pinctrl_dev_get_drvdata(pctldev);
     722                 :            :         struct property *pins, *funcs, *pulls;
     723                 :            :         int num_pins, num_funcs, num_pulls, maps_per_pin;
     724                 :            :         struct pinctrl_map *maps, *cur_map;
     725                 :            :         int i, err;
     726                 :            :         u32 pin, func, pull;
     727                 :            : 
     728                 :            :         /* Check for generic binding in this node */
     729                 :            :         err = pinconf_generic_dt_node_to_map_all(pctldev, np, map, num_maps);
     730   [ +  -  +  - ]:        621 :         if (err || *num_maps)
     731                 :            :                 return err;
     732                 :            : 
     733                 :            :         /* Generic binding did not find anything continue with legacy parse */
     734                 :        621 :         pins = of_find_property(np, "brcm,pins", NULL);
     735         [ -  + ]:        621 :         if (!pins) {
     736                 :          0 :                 dev_err(pc->dev, "%pOF: missing brcm,pins property\n", np);
     737                 :          0 :                 return -EINVAL;
     738                 :            :         }
     739                 :            : 
     740                 :        621 :         funcs = of_find_property(np, "brcm,function", NULL);
     741                 :        621 :         pulls = of_find_property(np, "brcm,pull", NULL);
     742                 :            : 
     743         [ -  + ]:        621 :         if (!funcs && !pulls) {
     744                 :          0 :                 dev_err(pc->dev,
     745                 :            :                         "%pOF: neither brcm,function nor brcm,pull specified\n",
     746                 :            :                         np);
     747                 :          0 :                 return -EINVAL;
     748                 :            :         }
     749                 :            : 
     750                 :        621 :         num_pins = pins->length / 4;
     751         [ +  - ]:        621 :         num_funcs = funcs ? (funcs->length / 4) : 0;
     752         [ -  + ]:        621 :         num_pulls = pulls ? (pulls->length / 4) : 0;
     753                 :            : 
     754         [ -  + ]:        621 :         if (num_funcs > 1 && num_funcs != num_pins) {
     755                 :          0 :                 dev_err(pc->dev,
     756                 :            :                         "%pOF: brcm,function must have 1 or %d entries\n",
     757                 :            :                         np, num_pins);
     758                 :          0 :                 return -EINVAL;
     759                 :            :         }
     760                 :            : 
     761         [ -  + ]:        621 :         if (num_pulls > 1 && num_pulls != num_pins) {
     762                 :          0 :                 dev_err(pc->dev,
     763                 :            :                         "%pOF: brcm,pull must have 1 or %d entries\n",
     764                 :            :                         np, num_pins);
     765                 :          0 :                 return -EINVAL;
     766                 :            :         }
     767                 :            : 
     768                 :            :         maps_per_pin = 0;
     769         [ +  - ]:        621 :         if (num_funcs)
     770                 :            :                 maps_per_pin++;
     771         [ -  + ]:        621 :         if (num_pulls)
     772                 :          0 :                 maps_per_pin++;
     773                 :       1242 :         cur_map = maps = kcalloc(num_pins * maps_per_pin, sizeof(*maps),
     774                 :            :                                  GFP_KERNEL);
     775         [ +  - ]:        621 :         if (!maps)
     776                 :            :                 return -ENOMEM;
     777                 :            : 
     778         [ +  + ]:       2898 :         for (i = 0; i < num_pins; i++) {
     779                 :       2898 :                 err = of_property_read_u32_index(np, "brcm,pins", i, &pin);
     780         [ +  - ]:       2898 :                 if (err)
     781                 :            :                         goto out;
     782         [ -  + ]:       2898 :                 if (pin >= ARRAY_SIZE(bcm2835_gpio_pins)) {
     783                 :          0 :                         dev_err(pc->dev, "%pOF: invalid brcm,pins value %d\n",
     784                 :            :                                 np, pin);
     785                 :            :                         err = -EINVAL;
     786                 :          0 :                         goto out;
     787                 :            :                 }
     788                 :            : 
     789         [ +  - ]:       2898 :                 if (num_funcs) {
     790         [ -  + ]:       2898 :                         err = of_property_read_u32_index(np, "brcm,function",
     791                 :            :                                         (num_funcs > 1) ? i : 0, &func);
     792         [ +  - ]:       2898 :                         if (err)
     793                 :            :                                 goto out;
     794                 :       2898 :                         err = bcm2835_pctl_dt_node_to_map_func(pc, np, pin,
     795                 :            :                                                         func, &cur_map);
     796         [ +  - ]:       2898 :                         if (err)
     797                 :            :                                 goto out;
     798                 :            :                 }
     799         [ -  + ]:       2898 :                 if (num_pulls) {
     800         [ #  # ]:          0 :                         err = of_property_read_u32_index(np, "brcm,pull",
     801                 :            :                                         (num_pulls > 1) ? i : 0, &pull);
     802         [ #  # ]:          0 :                         if (err)
     803                 :            :                                 goto out;
     804                 :          0 :                         err = bcm2835_pctl_dt_node_to_map_pull(pc, np, pin,
     805                 :            :                                                         pull, &cur_map);
     806         [ #  # ]:          0 :                         if (err)
     807                 :            :                                 goto out;
     808                 :            :                 }
     809                 :            :         }
     810                 :            : 
     811                 :        621 :         *map = maps;
     812                 :        621 :         *num_maps = num_pins * maps_per_pin;
     813                 :            : 
     814                 :        621 :         return 0;
     815                 :            : 
     816                 :            : out:
     817                 :          0 :         bcm2835_pctl_dt_free_map(pctldev, maps, num_pins * maps_per_pin);
     818                 :          0 :         return err;
     819                 :            : }
     820                 :            : 
     821                 :            : static const struct pinctrl_ops bcm2835_pctl_ops = {
     822                 :            :         .get_groups_count = bcm2835_pctl_get_groups_count,
     823                 :            :         .get_group_name = bcm2835_pctl_get_group_name,
     824                 :            :         .get_group_pins = bcm2835_pctl_get_group_pins,
     825                 :            :         .pin_dbg_show = bcm2835_pctl_pin_dbg_show,
     826                 :            :         .dt_node_to_map = bcm2835_pctl_dt_node_to_map,
     827                 :            :         .dt_free_map = bcm2835_pctl_dt_free_map,
     828                 :            : };
     829                 :            : 
     830                 :       1242 : static int bcm2835_pmx_free(struct pinctrl_dev *pctldev,
     831                 :            :                 unsigned offset)
     832                 :            : {
     833                 :       1242 :         struct bcm2835_pinctrl *pc = pinctrl_dev_get_drvdata(pctldev);
     834                 :            : 
     835                 :            :         /* disable by setting to GPIO_IN */
     836                 :       1242 :         bcm2835_pinctrl_fsel_set(pc, offset, BCM2835_FSEL_GPIO_IN);
     837                 :       1242 :         return 0;
     838                 :            : }
     839                 :            : 
     840                 :       3105 : static int bcm2835_pmx_get_functions_count(struct pinctrl_dev *pctldev)
     841                 :            : {
     842                 :       3105 :         return BCM2835_FSEL_COUNT;
     843                 :            : }
     844                 :            : 
     845                 :      16146 : static const char *bcm2835_pmx_get_function_name(struct pinctrl_dev *pctldev,
     846                 :            :                 unsigned selector)
     847                 :            : {
     848                 :      16146 :         return bcm2835_functions[selector];
     849                 :            : }
     850                 :            : 
     851                 :       2898 : static int bcm2835_pmx_get_function_groups(struct pinctrl_dev *pctldev,
     852                 :            :                 unsigned selector,
     853                 :            :                 const char * const **groups,
     854                 :            :                 unsigned * const num_groups)
     855                 :            : {
     856                 :            :         /* every pin can do every function */
     857                 :       2898 :         *groups = bcm2835_gpio_groups;
     858                 :       2898 :         *num_groups = ARRAY_SIZE(bcm2835_gpio_groups);
     859                 :            : 
     860                 :       2898 :         return 0;
     861                 :            : }
     862                 :            : 
     863                 :       2898 : static int bcm2835_pmx_set(struct pinctrl_dev *pctldev,
     864                 :            :                 unsigned func_selector,
     865                 :            :                 unsigned group_selector)
     866                 :            : {
     867                 :       2898 :         struct bcm2835_pinctrl *pc = pinctrl_dev_get_drvdata(pctldev);
     868                 :            : 
     869                 :       2898 :         bcm2835_pinctrl_fsel_set(pc, group_selector, func_selector);
     870                 :            : 
     871                 :       2898 :         return 0;
     872                 :            : }
     873                 :            : 
     874                 :          0 : static void bcm2835_pmx_gpio_disable_free(struct pinctrl_dev *pctldev,
     875                 :            :                 struct pinctrl_gpio_range *range,
     876                 :            :                 unsigned offset)
     877                 :            : {
     878                 :          0 :         struct bcm2835_pinctrl *pc = pinctrl_dev_get_drvdata(pctldev);
     879                 :            : 
     880                 :            :         /* disable by setting to GPIO_IN */
     881                 :          0 :         bcm2835_pinctrl_fsel_set(pc, offset, BCM2835_FSEL_GPIO_IN);
     882                 :          0 : }
     883                 :            : 
     884                 :        621 : static int bcm2835_pmx_gpio_set_direction(struct pinctrl_dev *pctldev,
     885                 :            :                 struct pinctrl_gpio_range *range,
     886                 :            :                 unsigned offset,
     887                 :            :                 bool input)
     888                 :            : {
     889                 :        621 :         struct bcm2835_pinctrl *pc = pinctrl_dev_get_drvdata(pctldev);
     890         [ +  + ]:        621 :         enum bcm2835_fsel fsel = input ?
     891                 :            :                 BCM2835_FSEL_GPIO_IN : BCM2835_FSEL_GPIO_OUT;
     892                 :            : 
     893                 :        621 :         bcm2835_pinctrl_fsel_set(pc, offset, fsel);
     894                 :            : 
     895                 :        621 :         return 0;
     896                 :            : }
     897                 :            : 
     898                 :            : static const struct pinmux_ops bcm2835_pmx_ops = {
     899                 :            :         .free = bcm2835_pmx_free,
     900                 :            :         .get_functions_count = bcm2835_pmx_get_functions_count,
     901                 :            :         .get_function_name = bcm2835_pmx_get_function_name,
     902                 :            :         .get_function_groups = bcm2835_pmx_get_function_groups,
     903                 :            :         .set_mux = bcm2835_pmx_set,
     904                 :            :         .gpio_disable_free = bcm2835_pmx_gpio_disable_free,
     905                 :            :         .gpio_set_direction = bcm2835_pmx_gpio_set_direction,
     906                 :            : };
     907                 :            : 
     908                 :          0 : static int bcm2835_pinconf_get(struct pinctrl_dev *pctldev,
     909                 :            :                         unsigned pin, unsigned long *config)
     910                 :            : {
     911                 :            :         /* No way to read back config in HW */
     912                 :          0 :         return -ENOTSUPP;
     913                 :            : }
     914                 :            : 
     915                 :          0 : static void bcm2835_pull_config_set(struct bcm2835_pinctrl *pc,
     916                 :            :                 unsigned int pin, unsigned int arg)
     917                 :            : {
     918                 :            :         u32 off, bit;
     919                 :            : 
     920                 :          0 :         off = GPIO_REG_OFFSET(pin);
     921                 :          0 :         bit = GPIO_REG_SHIFT(pin);
     922                 :            : 
     923                 :          0 :         bcm2835_gpio_wr(pc, GPPUD, arg & 3);
     924                 :            :         /*
     925                 :            :          * BCM2835 datasheet say to wait 150 cycles, but not of what.
     926                 :            :          * But the VideoCore firmware delay for this operation
     927                 :            :          * based nearly on the same amount of VPU cycles and this clock
     928                 :            :          * runs at 250 MHz.
     929                 :            :          */
     930                 :          0 :         udelay(1);
     931                 :          0 :         bcm2835_gpio_wr(pc, GPPUDCLK0 + (off * 4), BIT(bit));
     932                 :          0 :         udelay(1);
     933                 :            :         bcm2835_gpio_wr(pc, GPPUDCLK0 + (off * 4), 0);
     934                 :          0 : }
     935                 :            : 
     936                 :        828 : static int bcm2835_pinconf_set(struct pinctrl_dev *pctldev,
     937                 :            :                         unsigned int pin, unsigned long *configs,
     938                 :            :                         unsigned int num_configs)
     939                 :            : {
     940                 :        828 :         struct bcm2835_pinctrl *pc = pinctrl_dev_get_drvdata(pctldev);
     941                 :            :         u32 param, arg;
     942                 :            :         int i;
     943                 :            : 
     944         [ +  - ]:        828 :         for (i = 0; i < num_configs; i++) {
     945                 :        828 :                 param = pinconf_to_config_param(configs[i]);
     946                 :            :                 arg = pinconf_to_config_argument(configs[i]);
     947                 :            : 
     948   [ -  -  -  -  :        828 :                 switch (param) {
                   -  + ]
     949                 :            :                 /* Set legacy brcm,pull */
     950                 :            :                 case BCM2835_PINCONF_PARAM_PULL:
     951                 :          0 :                         bcm2835_pull_config_set(pc, pin, arg);
     952                 :          0 :                         break;
     953                 :            : 
     954                 :            :                 /* Set pull generic bindings */
     955                 :            :                 case PIN_CONFIG_BIAS_DISABLE:
     956                 :          0 :                         bcm2835_pull_config_set(pc, pin, BCM2835_PUD_OFF);
     957                 :          0 :                         break;
     958                 :            : 
     959                 :            :                 case PIN_CONFIG_BIAS_PULL_DOWN:
     960                 :          0 :                         bcm2835_pull_config_set(pc, pin, BCM2835_PUD_DOWN);
     961                 :          0 :                         break;
     962                 :            : 
     963                 :            :                 case PIN_CONFIG_BIAS_PULL_UP:
     964                 :          0 :                         bcm2835_pull_config_set(pc, pin, BCM2835_PUD_UP);
     965                 :          0 :                         break;
     966                 :            : 
     967                 :            :                 /* Set output-high or output-low */
     968                 :            :                 case PIN_CONFIG_OUTPUT:
     969         [ #  # ]:          0 :                         bcm2835_gpio_set_bit(pc, arg ? GPSET0 : GPCLR0, pin);
     970                 :            :                         break;
     971                 :            : 
     972                 :            :                 default:
     973                 :            :                         return -ENOTSUPP;
     974                 :            : 
     975                 :            :                 } /* switch param type */
     976                 :            :         } /* for each config */
     977                 :            : 
     978                 :            :         return 0;
     979                 :            : }
     980                 :            : 
     981                 :            : static const struct pinconf_ops bcm2835_pinconf_ops = {
     982                 :            :         .is_generic = true,
     983                 :            :         .pin_config_get = bcm2835_pinconf_get,
     984                 :            :         .pin_config_set = bcm2835_pinconf_set,
     985                 :            : };
     986                 :            : 
     987                 :          0 : static void bcm2711_pull_config_set(struct bcm2835_pinctrl *pc,
     988                 :            :                                     unsigned int pin, unsigned int arg)
     989                 :            : {
     990                 :            :         u32 shifter;
     991                 :            :         u32 value;
     992                 :            :         u32 off;
     993                 :            : 
     994                 :          0 :         off = PUD_2711_REG_OFFSET(pin);
     995                 :          0 :         shifter = PUD_2711_REG_SHIFT(pin);
     996                 :            : 
     997                 :          0 :         value = bcm2835_gpio_rd(pc, GP_GPIO_PUP_PDN_CNTRL_REG0 + (off * 4));
     998                 :          0 :         value &= ~(PUD_2711_MASK << shifter);
     999                 :          0 :         value |= (arg << shifter);
    1000                 :            :         bcm2835_gpio_wr(pc, GP_GPIO_PUP_PDN_CNTRL_REG0 + (off * 4), value);
    1001                 :          0 : }
    1002                 :            : 
    1003                 :          0 : static int bcm2711_pinconf_set(struct pinctrl_dev *pctldev,
    1004                 :            :                                unsigned int pin, unsigned long *configs,
    1005                 :            :                                unsigned int num_configs)
    1006                 :            : {
    1007                 :          0 :         struct bcm2835_pinctrl *pc = pinctrl_dev_get_drvdata(pctldev);
    1008                 :            :         u32 param, arg;
    1009                 :            :         int i;
    1010                 :            : 
    1011         [ #  # ]:          0 :         for (i = 0; i < num_configs; i++) {
    1012                 :          0 :                 param = pinconf_to_config_param(configs[i]);
    1013                 :            :                 arg = pinconf_to_config_argument(configs[i]);
    1014                 :            : 
    1015   [ #  #  #  #  :          0 :                 switch (param) {
                   #  # ]
    1016                 :            :                 /* convert legacy brcm,pull */
    1017                 :            :                 case BCM2835_PINCONF_PARAM_PULL:
    1018         [ #  # ]:          0 :                         if (arg == BCM2835_PUD_UP)
    1019                 :            :                                 arg = BCM2711_PULL_UP;
    1020         [ #  # ]:          0 :                         else if (arg == BCM2835_PUD_DOWN)
    1021                 :            :                                 arg = BCM2711_PULL_DOWN;
    1022                 :            :                         else
    1023                 :            :                                 arg = BCM2711_PULL_NONE;
    1024                 :            : 
    1025                 :          0 :                         bcm2711_pull_config_set(pc, pin, arg);
    1026                 :          0 :                         break;
    1027                 :            : 
    1028                 :            :                 /* Set pull generic bindings */
    1029                 :            :                 case PIN_CONFIG_BIAS_DISABLE:
    1030                 :          0 :                         bcm2711_pull_config_set(pc, pin, BCM2711_PULL_NONE);
    1031                 :          0 :                         break;
    1032                 :            :                 case PIN_CONFIG_BIAS_PULL_DOWN:
    1033                 :          0 :                         bcm2711_pull_config_set(pc, pin, BCM2711_PULL_DOWN);
    1034                 :          0 :                         break;
    1035                 :            :                 case PIN_CONFIG_BIAS_PULL_UP:
    1036                 :          0 :                         bcm2711_pull_config_set(pc, pin, BCM2711_PULL_UP);
    1037                 :          0 :                         break;
    1038                 :            : 
    1039                 :            :                 /* Set output-high or output-low */
    1040                 :            :                 case PIN_CONFIG_OUTPUT:
    1041         [ #  # ]:          0 :                         bcm2835_gpio_set_bit(pc, arg ? GPSET0 : GPCLR0, pin);
    1042                 :            :                         break;
    1043                 :            : 
    1044                 :            :                 default:
    1045                 :            :                         return -ENOTSUPP;
    1046                 :            :                 }
    1047                 :            :         } /* for each config */
    1048                 :            : 
    1049                 :            :         return 0;
    1050                 :            : }
    1051                 :            : 
    1052                 :            : static const struct pinconf_ops bcm2711_pinconf_ops = {
    1053                 :            :         .is_generic = true,
    1054                 :            :         .pin_config_get = bcm2835_pinconf_get,
    1055                 :            :         .pin_config_set = bcm2711_pinconf_set,
    1056                 :            : };
    1057                 :            : 
    1058                 :            : static struct pinctrl_desc bcm2835_pinctrl_desc = {
    1059                 :            :         .name = MODULE_NAME,
    1060                 :            :         .pins = bcm2835_gpio_pins,
    1061                 :            :         .npins = ARRAY_SIZE(bcm2835_gpio_pins),
    1062                 :            :         .pctlops = &bcm2835_pctl_ops,
    1063                 :            :         .pmxops = &bcm2835_pmx_ops,
    1064                 :            :         .confops = &bcm2835_pinconf_ops,
    1065                 :            :         .owner = THIS_MODULE,
    1066                 :            : };
    1067                 :            : 
    1068                 :            : static struct pinctrl_gpio_range bcm2835_pinctrl_gpio_range = {
    1069                 :            :         .name = MODULE_NAME,
    1070                 :            :         .npins = BCM2835_NUM_GPIOS,
    1071                 :            : };
    1072                 :            : 
    1073                 :            : static const struct of_device_id bcm2835_pinctrl_match[] = {
    1074                 :            :         {
    1075                 :            :                 .compatible = "brcm,bcm2835-gpio",
    1076                 :            :                 .data = &bcm2835_pinconf_ops,
    1077                 :            :         },
    1078                 :            :         {
    1079                 :            :                 .compatible = "brcm,bcm2711-gpio",
    1080                 :            :                 .data = &bcm2711_pinconf_ops,
    1081                 :            :         },
    1082                 :            :         {}
    1083                 :            : };
    1084                 :            : 
    1085                 :        207 : static int bcm2835_pinctrl_probe(struct platform_device *pdev)
    1086                 :            : {
    1087                 :        207 :         struct device *dev = &pdev->dev;
    1088                 :        207 :         struct device_node *np = dev->of_node;
    1089                 :            :         struct bcm2835_pinctrl *pc;
    1090                 :            :         struct resource iomem;
    1091                 :            :         int err, i;
    1092                 :            :         const struct of_device_id *match;
    1093                 :            : 
    1094                 :            :         BUILD_BUG_ON(ARRAY_SIZE(bcm2835_gpio_pins) != BCM2835_NUM_GPIOS);
    1095                 :            :         BUILD_BUG_ON(ARRAY_SIZE(bcm2835_gpio_groups) != BCM2835_NUM_GPIOS);
    1096                 :            : 
    1097                 :            :         pc = devm_kzalloc(dev, sizeof(*pc), GFP_KERNEL);
    1098         [ +  - ]:        207 :         if (!pc)
    1099                 :            :                 return -ENOMEM;
    1100                 :            : 
    1101                 :            :         platform_set_drvdata(pdev, pc);
    1102                 :        207 :         pc->dev = dev;
    1103                 :            : 
    1104                 :        207 :         err = of_address_to_resource(np, 0, &iomem);
    1105         [ -  + ]:        207 :         if (err) {
    1106                 :          0 :                 dev_err(dev, "could not get IO memory\n");
    1107                 :          0 :                 return err;
    1108                 :            :         }
    1109                 :            : 
    1110                 :        207 :         pc->base = devm_ioremap_resource(dev, &iomem);
    1111         [ -  + ]:        207 :         if (IS_ERR(pc->base))
    1112                 :          0 :                 return PTR_ERR(pc->base);
    1113                 :            : 
    1114                 :        207 :         pc->gpio_chip = bcm2835_gpio_chip;
    1115                 :        207 :         pc->gpio_chip.parent = dev;
    1116                 :        207 :         pc->gpio_chip.of_node = np;
    1117                 :            : 
    1118         [ +  + ]:        621 :         for (i = 0; i < BCM2835_NUM_BANKS; i++) {
    1119                 :            :                 unsigned long events;
    1120                 :            :                 unsigned offset;
    1121                 :            : 
    1122                 :            :                 /* clear event detection flags */
    1123                 :        414 :                 bcm2835_gpio_wr(pc, GPREN0 + i * 4, 0);
    1124                 :        414 :                 bcm2835_gpio_wr(pc, GPFEN0 + i * 4, 0);
    1125                 :        414 :                 bcm2835_gpio_wr(pc, GPHEN0 + i * 4, 0);
    1126                 :        414 :                 bcm2835_gpio_wr(pc, GPLEN0 + i * 4, 0);
    1127                 :        414 :                 bcm2835_gpio_wr(pc, GPAREN0 + i * 4, 0);
    1128                 :        414 :                 bcm2835_gpio_wr(pc, GPAFEN0 + i * 4, 0);
    1129                 :            : 
    1130                 :            :                 /* clear all the events */
    1131                 :        828 :                 events = bcm2835_gpio_rd(pc, GPEDS0 + i * 4);
    1132         [ -  + ]:        414 :                 for_each_set_bit(offset, &events, 32)
    1133                 :          0 :                         bcm2835_gpio_wr(pc, GPEDS0 + i * 4, BIT(offset));
    1134                 :            : 
    1135                 :        414 :                 raw_spin_lock_init(&pc->irq_lock[i]);
    1136                 :            :         }
    1137                 :            : 
    1138                 :        207 :         match = of_match_node(bcm2835_pinctrl_match, pdev->dev.of_node);
    1139         [ +  - ]:        207 :         if (match) {
    1140                 :        207 :                 bcm2835_pinctrl_desc.confops =
    1141                 :        207 :                         (const struct pinconf_ops *)match->data;
    1142                 :            :         }
    1143                 :            : 
    1144                 :        207 :         pc->pctl_dev = devm_pinctrl_register(dev, &bcm2835_pinctrl_desc, pc);
    1145         [ -  + ]:        207 :         if (IS_ERR(pc->pctl_dev))
    1146                 :          0 :                 return PTR_ERR(pc->pctl_dev);
    1147                 :            : 
    1148                 :        207 :         pc->gpio_range = bcm2835_pinctrl_gpio_range;
    1149                 :        207 :         pc->gpio_range.base = pc->gpio_chip.base;
    1150                 :        207 :         pc->gpio_range.gc = &pc->gpio_chip;
    1151                 :        207 :         pinctrl_add_gpio_range(pc->pctl_dev, &pc->gpio_range);
    1152                 :            : 
    1153                 :        207 :         err = devm_gpiochip_add_data(dev, &pc->gpio_chip, pc);
    1154         [ -  + ]:        207 :         if (err) {
    1155                 :          0 :                 dev_err(dev, "could not add GPIO chip\n");
    1156                 :          0 :                 pinctrl_remove_gpio_range(pc->pctl_dev, &pc->gpio_range);
    1157                 :          0 :                 return err;
    1158                 :            :         }
    1159                 :            : 
    1160                 :            :         err = gpiochip_irqchip_add(&pc->gpio_chip, &bcm2835_gpio_irq_chip,
    1161                 :            :                                    0, handle_level_irq, IRQ_TYPE_NONE);
    1162         [ +  - ]:        207 :         if (err) {
    1163                 :          0 :                 dev_info(dev, "could not add irqchip\n");
    1164                 :          0 :                 pinctrl_remove_gpio_range(pc->pctl_dev, &pc->gpio_range);
    1165                 :          0 :                 return err;
    1166                 :            :         }
    1167                 :            : 
    1168         [ +  + ]:        621 :         for (i = 0; i < BCM2835_NUM_IRQS; i++) {
    1169                 :        621 :                 pc->irq[i] = irq_of_parse_and_map(np, i);
    1170                 :            : 
    1171         [ +  + ]:        621 :                 if (pc->irq[i] == 0)
    1172                 :        207 :                         continue;
    1173                 :            : 
    1174                 :            :                 /*
    1175                 :            :                  * Use the same handler for all groups: this is necessary
    1176                 :            :                  * since we use one gpiochip to cover all lines - the
    1177                 :            :                  * irq handler then needs to figure out which group and
    1178                 :            :                  * bank that was firing the IRQ and look up the per-group
    1179                 :            :                  * and bank data.
    1180                 :            :                  */
    1181                 :        414 :                 gpiochip_set_chained_irqchip(&pc->gpio_chip,
    1182                 :            :                                              &bcm2835_gpio_irq_chip,
    1183                 :            :                                              pc->irq[i],
    1184                 :            :                                              bcm2835_gpio_irq_handler);
    1185                 :            :         }
    1186                 :            : 
    1187                 :            :         return 0;
    1188                 :            : }
    1189                 :            : 
    1190                 :            : static struct platform_driver bcm2835_pinctrl_driver = {
    1191                 :            :         .probe = bcm2835_pinctrl_probe,
    1192                 :            :         .driver = {
    1193                 :            :                 .name = MODULE_NAME,
    1194                 :            :                 .of_match_table = bcm2835_pinctrl_match,
    1195                 :            :                 .suppress_bind_attrs = true,
    1196                 :            :         },
    1197                 :            : };
    1198                 :        207 : builtin_platform_driver(bcm2835_pinctrl_driver);

Generated by: LCOV version 1.14