18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * Copyright (C) ST-Ericsson SA 2013 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * Author: Patrice Chotard <patrice.chotard@st.com> 68c2ecf20Sopenharmony_ci * 78c2ecf20Sopenharmony_ci * Driver allows to use AxB5xx unused pins to be used as GPIO 88c2ecf20Sopenharmony_ci */ 98c2ecf20Sopenharmony_ci#include <linux/kernel.h> 108c2ecf20Sopenharmony_ci#include <linux/types.h> 118c2ecf20Sopenharmony_ci#include <linux/slab.h> 128c2ecf20Sopenharmony_ci#include <linux/init.h> 138c2ecf20Sopenharmony_ci#include <linux/err.h> 148c2ecf20Sopenharmony_ci#include <linux/of.h> 158c2ecf20Sopenharmony_ci#include <linux/of_device.h> 168c2ecf20Sopenharmony_ci#include <linux/platform_device.h> 178c2ecf20Sopenharmony_ci#include <linux/gpio/driver.h> 188c2ecf20Sopenharmony_ci#include <linux/irq.h> 198c2ecf20Sopenharmony_ci#include <linux/irqdomain.h> 208c2ecf20Sopenharmony_ci#include <linux/interrupt.h> 218c2ecf20Sopenharmony_ci#include <linux/bitops.h> 228c2ecf20Sopenharmony_ci#include <linux/mfd/abx500.h> 238c2ecf20Sopenharmony_ci#include <linux/mfd/abx500/ab8500.h> 248c2ecf20Sopenharmony_ci#include <linux/pinctrl/pinctrl.h> 258c2ecf20Sopenharmony_ci#include <linux/pinctrl/consumer.h> 268c2ecf20Sopenharmony_ci#include <linux/pinctrl/pinmux.h> 278c2ecf20Sopenharmony_ci#include <linux/pinctrl/pinconf.h> 288c2ecf20Sopenharmony_ci#include <linux/pinctrl/pinconf-generic.h> 298c2ecf20Sopenharmony_ci#include <linux/pinctrl/machine.h> 308c2ecf20Sopenharmony_ci 318c2ecf20Sopenharmony_ci#include "pinctrl-abx500.h" 328c2ecf20Sopenharmony_ci#include "../core.h" 338c2ecf20Sopenharmony_ci#include "../pinconf.h" 348c2ecf20Sopenharmony_ci#include "../pinctrl-utils.h" 358c2ecf20Sopenharmony_ci 368c2ecf20Sopenharmony_ci/* 378c2ecf20Sopenharmony_ci * GPIO registers offset 388c2ecf20Sopenharmony_ci * Bank: 0x10 398c2ecf20Sopenharmony_ci */ 408c2ecf20Sopenharmony_ci#define AB8500_GPIO_SEL1_REG 0x00 418c2ecf20Sopenharmony_ci#define AB8500_GPIO_SEL2_REG 0x01 428c2ecf20Sopenharmony_ci#define AB8500_GPIO_SEL3_REG 0x02 438c2ecf20Sopenharmony_ci#define AB8500_GPIO_SEL4_REG 0x03 448c2ecf20Sopenharmony_ci#define AB8500_GPIO_SEL5_REG 0x04 458c2ecf20Sopenharmony_ci#define AB8500_GPIO_SEL6_REG 0x05 468c2ecf20Sopenharmony_ci 478c2ecf20Sopenharmony_ci#define AB8500_GPIO_DIR1_REG 0x10 488c2ecf20Sopenharmony_ci#define AB8500_GPIO_DIR2_REG 0x11 498c2ecf20Sopenharmony_ci#define AB8500_GPIO_DIR3_REG 0x12 508c2ecf20Sopenharmony_ci#define AB8500_GPIO_DIR4_REG 0x13 518c2ecf20Sopenharmony_ci#define AB8500_GPIO_DIR5_REG 0x14 528c2ecf20Sopenharmony_ci#define AB8500_GPIO_DIR6_REG 0x15 538c2ecf20Sopenharmony_ci 548c2ecf20Sopenharmony_ci#define AB8500_GPIO_OUT1_REG 0x20 558c2ecf20Sopenharmony_ci#define AB8500_GPIO_OUT2_REG 0x21 568c2ecf20Sopenharmony_ci#define AB8500_GPIO_OUT3_REG 0x22 578c2ecf20Sopenharmony_ci#define AB8500_GPIO_OUT4_REG 0x23 588c2ecf20Sopenharmony_ci#define AB8500_GPIO_OUT5_REG 0x24 598c2ecf20Sopenharmony_ci#define AB8500_GPIO_OUT6_REG 0x25 608c2ecf20Sopenharmony_ci 618c2ecf20Sopenharmony_ci#define AB8500_GPIO_PUD1_REG 0x30 628c2ecf20Sopenharmony_ci#define AB8500_GPIO_PUD2_REG 0x31 638c2ecf20Sopenharmony_ci#define AB8500_GPIO_PUD3_REG 0x32 648c2ecf20Sopenharmony_ci#define AB8500_GPIO_PUD4_REG 0x33 658c2ecf20Sopenharmony_ci#define AB8500_GPIO_PUD5_REG 0x34 668c2ecf20Sopenharmony_ci#define AB8500_GPIO_PUD6_REG 0x35 678c2ecf20Sopenharmony_ci 688c2ecf20Sopenharmony_ci#define AB8500_GPIO_IN1_REG 0x40 698c2ecf20Sopenharmony_ci#define AB8500_GPIO_IN2_REG 0x41 708c2ecf20Sopenharmony_ci#define AB8500_GPIO_IN3_REG 0x42 718c2ecf20Sopenharmony_ci#define AB8500_GPIO_IN4_REG 0x43 728c2ecf20Sopenharmony_ci#define AB8500_GPIO_IN5_REG 0x44 738c2ecf20Sopenharmony_ci#define AB8500_GPIO_IN6_REG 0x45 748c2ecf20Sopenharmony_ci#define AB8500_GPIO_ALTFUN_REG 0x50 758c2ecf20Sopenharmony_ci 768c2ecf20Sopenharmony_ci#define ABX500_GPIO_INPUT 0 778c2ecf20Sopenharmony_ci#define ABX500_GPIO_OUTPUT 1 788c2ecf20Sopenharmony_ci 798c2ecf20Sopenharmony_cistruct abx500_pinctrl { 808c2ecf20Sopenharmony_ci struct device *dev; 818c2ecf20Sopenharmony_ci struct pinctrl_dev *pctldev; 828c2ecf20Sopenharmony_ci struct abx500_pinctrl_soc_data *soc; 838c2ecf20Sopenharmony_ci struct gpio_chip chip; 848c2ecf20Sopenharmony_ci struct ab8500 *parent; 858c2ecf20Sopenharmony_ci struct abx500_gpio_irq_cluster *irq_cluster; 868c2ecf20Sopenharmony_ci int irq_cluster_size; 878c2ecf20Sopenharmony_ci}; 888c2ecf20Sopenharmony_ci 898c2ecf20Sopenharmony_cistatic int abx500_gpio_get_bit(struct gpio_chip *chip, u8 reg, 908c2ecf20Sopenharmony_ci unsigned offset, bool *bit) 918c2ecf20Sopenharmony_ci{ 928c2ecf20Sopenharmony_ci struct abx500_pinctrl *pct = gpiochip_get_data(chip); 938c2ecf20Sopenharmony_ci u8 pos = offset % 8; 948c2ecf20Sopenharmony_ci u8 val; 958c2ecf20Sopenharmony_ci int ret; 968c2ecf20Sopenharmony_ci 978c2ecf20Sopenharmony_ci reg += offset / 8; 988c2ecf20Sopenharmony_ci ret = abx500_get_register_interruptible(pct->dev, 998c2ecf20Sopenharmony_ci AB8500_MISC, reg, &val); 1008c2ecf20Sopenharmony_ci if (ret < 0) { 1018c2ecf20Sopenharmony_ci dev_err(pct->dev, 1028c2ecf20Sopenharmony_ci "%s read reg =%x, offset=%x failed (%d)\n", 1038c2ecf20Sopenharmony_ci __func__, reg, offset, ret); 1048c2ecf20Sopenharmony_ci return ret; 1058c2ecf20Sopenharmony_ci } 1068c2ecf20Sopenharmony_ci 1078c2ecf20Sopenharmony_ci *bit = !!(val & BIT(pos)); 1088c2ecf20Sopenharmony_ci 1098c2ecf20Sopenharmony_ci return 0; 1108c2ecf20Sopenharmony_ci} 1118c2ecf20Sopenharmony_ci 1128c2ecf20Sopenharmony_cistatic int abx500_gpio_set_bits(struct gpio_chip *chip, u8 reg, 1138c2ecf20Sopenharmony_ci unsigned offset, int val) 1148c2ecf20Sopenharmony_ci{ 1158c2ecf20Sopenharmony_ci struct abx500_pinctrl *pct = gpiochip_get_data(chip); 1168c2ecf20Sopenharmony_ci u8 pos = offset % 8; 1178c2ecf20Sopenharmony_ci int ret; 1188c2ecf20Sopenharmony_ci 1198c2ecf20Sopenharmony_ci reg += offset / 8; 1208c2ecf20Sopenharmony_ci ret = abx500_mask_and_set_register_interruptible(pct->dev, 1218c2ecf20Sopenharmony_ci AB8500_MISC, reg, BIT(pos), val << pos); 1228c2ecf20Sopenharmony_ci if (ret < 0) 1238c2ecf20Sopenharmony_ci dev_err(pct->dev, "%s write reg, %x offset %x failed (%d)\n", 1248c2ecf20Sopenharmony_ci __func__, reg, offset, ret); 1258c2ecf20Sopenharmony_ci 1268c2ecf20Sopenharmony_ci return ret; 1278c2ecf20Sopenharmony_ci} 1288c2ecf20Sopenharmony_ci 1298c2ecf20Sopenharmony_ci/** 1308c2ecf20Sopenharmony_ci * abx500_gpio_get() - Get the particular GPIO value 1318c2ecf20Sopenharmony_ci * @chip: Gpio device 1328c2ecf20Sopenharmony_ci * @offset: GPIO number to read 1338c2ecf20Sopenharmony_ci */ 1348c2ecf20Sopenharmony_cistatic int abx500_gpio_get(struct gpio_chip *chip, unsigned offset) 1358c2ecf20Sopenharmony_ci{ 1368c2ecf20Sopenharmony_ci struct abx500_pinctrl *pct = gpiochip_get_data(chip); 1378c2ecf20Sopenharmony_ci bool bit; 1388c2ecf20Sopenharmony_ci bool is_out; 1398c2ecf20Sopenharmony_ci u8 gpio_offset = offset - 1; 1408c2ecf20Sopenharmony_ci int ret; 1418c2ecf20Sopenharmony_ci 1428c2ecf20Sopenharmony_ci ret = abx500_gpio_get_bit(chip, AB8500_GPIO_DIR1_REG, 1438c2ecf20Sopenharmony_ci gpio_offset, &is_out); 1448c2ecf20Sopenharmony_ci if (ret < 0) 1458c2ecf20Sopenharmony_ci goto out; 1468c2ecf20Sopenharmony_ci 1478c2ecf20Sopenharmony_ci if (is_out) 1488c2ecf20Sopenharmony_ci ret = abx500_gpio_get_bit(chip, AB8500_GPIO_OUT1_REG, 1498c2ecf20Sopenharmony_ci gpio_offset, &bit); 1508c2ecf20Sopenharmony_ci else 1518c2ecf20Sopenharmony_ci ret = abx500_gpio_get_bit(chip, AB8500_GPIO_IN1_REG, 1528c2ecf20Sopenharmony_ci gpio_offset, &bit); 1538c2ecf20Sopenharmony_ciout: 1548c2ecf20Sopenharmony_ci if (ret < 0) { 1558c2ecf20Sopenharmony_ci dev_err(pct->dev, "%s failed (%d)\n", __func__, ret); 1568c2ecf20Sopenharmony_ci return ret; 1578c2ecf20Sopenharmony_ci } 1588c2ecf20Sopenharmony_ci 1598c2ecf20Sopenharmony_ci return bit; 1608c2ecf20Sopenharmony_ci} 1618c2ecf20Sopenharmony_ci 1628c2ecf20Sopenharmony_cistatic void abx500_gpio_set(struct gpio_chip *chip, unsigned offset, int val) 1638c2ecf20Sopenharmony_ci{ 1648c2ecf20Sopenharmony_ci struct abx500_pinctrl *pct = gpiochip_get_data(chip); 1658c2ecf20Sopenharmony_ci int ret; 1668c2ecf20Sopenharmony_ci 1678c2ecf20Sopenharmony_ci ret = abx500_gpio_set_bits(chip, AB8500_GPIO_OUT1_REG, offset, val); 1688c2ecf20Sopenharmony_ci if (ret < 0) 1698c2ecf20Sopenharmony_ci dev_err(pct->dev, "%s write failed (%d)\n", __func__, ret); 1708c2ecf20Sopenharmony_ci} 1718c2ecf20Sopenharmony_ci 1728c2ecf20Sopenharmony_cistatic int abx500_gpio_direction_output(struct gpio_chip *chip, 1738c2ecf20Sopenharmony_ci unsigned offset, 1748c2ecf20Sopenharmony_ci int val) 1758c2ecf20Sopenharmony_ci{ 1768c2ecf20Sopenharmony_ci struct abx500_pinctrl *pct = gpiochip_get_data(chip); 1778c2ecf20Sopenharmony_ci int ret; 1788c2ecf20Sopenharmony_ci 1798c2ecf20Sopenharmony_ci /* set direction as output */ 1808c2ecf20Sopenharmony_ci ret = abx500_gpio_set_bits(chip, 1818c2ecf20Sopenharmony_ci AB8500_GPIO_DIR1_REG, 1828c2ecf20Sopenharmony_ci offset, 1838c2ecf20Sopenharmony_ci ABX500_GPIO_OUTPUT); 1848c2ecf20Sopenharmony_ci if (ret < 0) 1858c2ecf20Sopenharmony_ci goto out; 1868c2ecf20Sopenharmony_ci 1878c2ecf20Sopenharmony_ci /* disable pull down */ 1888c2ecf20Sopenharmony_ci ret = abx500_gpio_set_bits(chip, 1898c2ecf20Sopenharmony_ci AB8500_GPIO_PUD1_REG, 1908c2ecf20Sopenharmony_ci offset, 1918c2ecf20Sopenharmony_ci ABX500_GPIO_PULL_NONE); 1928c2ecf20Sopenharmony_ci 1938c2ecf20Sopenharmony_ciout: 1948c2ecf20Sopenharmony_ci if (ret < 0) { 1958c2ecf20Sopenharmony_ci dev_err(pct->dev, "%s failed (%d)\n", __func__, ret); 1968c2ecf20Sopenharmony_ci return ret; 1978c2ecf20Sopenharmony_ci } 1988c2ecf20Sopenharmony_ci 1998c2ecf20Sopenharmony_ci /* set the output as 1 or 0 */ 2008c2ecf20Sopenharmony_ci return abx500_gpio_set_bits(chip, AB8500_GPIO_OUT1_REG, offset, val); 2018c2ecf20Sopenharmony_ci} 2028c2ecf20Sopenharmony_ci 2038c2ecf20Sopenharmony_cistatic int abx500_gpio_direction_input(struct gpio_chip *chip, unsigned offset) 2048c2ecf20Sopenharmony_ci{ 2058c2ecf20Sopenharmony_ci /* set the register as input */ 2068c2ecf20Sopenharmony_ci return abx500_gpio_set_bits(chip, 2078c2ecf20Sopenharmony_ci AB8500_GPIO_DIR1_REG, 2088c2ecf20Sopenharmony_ci offset, 2098c2ecf20Sopenharmony_ci ABX500_GPIO_INPUT); 2108c2ecf20Sopenharmony_ci} 2118c2ecf20Sopenharmony_ci 2128c2ecf20Sopenharmony_cistatic int abx500_gpio_to_irq(struct gpio_chip *chip, unsigned offset) 2138c2ecf20Sopenharmony_ci{ 2148c2ecf20Sopenharmony_ci struct abx500_pinctrl *pct = gpiochip_get_data(chip); 2158c2ecf20Sopenharmony_ci /* The AB8500 GPIO numbers are off by one */ 2168c2ecf20Sopenharmony_ci int gpio = offset + 1; 2178c2ecf20Sopenharmony_ci int hwirq; 2188c2ecf20Sopenharmony_ci int i; 2198c2ecf20Sopenharmony_ci 2208c2ecf20Sopenharmony_ci for (i = 0; i < pct->irq_cluster_size; i++) { 2218c2ecf20Sopenharmony_ci struct abx500_gpio_irq_cluster *cluster = 2228c2ecf20Sopenharmony_ci &pct->irq_cluster[i]; 2238c2ecf20Sopenharmony_ci 2248c2ecf20Sopenharmony_ci if (gpio >= cluster->start && gpio <= cluster->end) { 2258c2ecf20Sopenharmony_ci /* 2268c2ecf20Sopenharmony_ci * The ABx500 GPIO's associated IRQs are clustered together 2278c2ecf20Sopenharmony_ci * throughout the interrupt numbers at irregular intervals. 2288c2ecf20Sopenharmony_ci * To solve this quandry, we have placed the read-in values 2298c2ecf20Sopenharmony_ci * into the cluster information table. 2308c2ecf20Sopenharmony_ci */ 2318c2ecf20Sopenharmony_ci hwirq = gpio - cluster->start + cluster->to_irq; 2328c2ecf20Sopenharmony_ci return irq_create_mapping(pct->parent->domain, hwirq); 2338c2ecf20Sopenharmony_ci } 2348c2ecf20Sopenharmony_ci } 2358c2ecf20Sopenharmony_ci 2368c2ecf20Sopenharmony_ci return -EINVAL; 2378c2ecf20Sopenharmony_ci} 2388c2ecf20Sopenharmony_ci 2398c2ecf20Sopenharmony_cistatic int abx500_set_mode(struct pinctrl_dev *pctldev, struct gpio_chip *chip, 2408c2ecf20Sopenharmony_ci unsigned gpio, int alt_setting) 2418c2ecf20Sopenharmony_ci{ 2428c2ecf20Sopenharmony_ci struct abx500_pinctrl *pct = pinctrl_dev_get_drvdata(pctldev); 2438c2ecf20Sopenharmony_ci struct alternate_functions af = pct->soc->alternate_functions[gpio]; 2448c2ecf20Sopenharmony_ci int ret; 2458c2ecf20Sopenharmony_ci int val; 2468c2ecf20Sopenharmony_ci unsigned offset; 2478c2ecf20Sopenharmony_ci 2488c2ecf20Sopenharmony_ci const char *modes[] = { 2498c2ecf20Sopenharmony_ci [ABX500_DEFAULT] = "default", 2508c2ecf20Sopenharmony_ci [ABX500_ALT_A] = "altA", 2518c2ecf20Sopenharmony_ci [ABX500_ALT_B] = "altB", 2528c2ecf20Sopenharmony_ci [ABX500_ALT_C] = "altC", 2538c2ecf20Sopenharmony_ci }; 2548c2ecf20Sopenharmony_ci 2558c2ecf20Sopenharmony_ci /* sanity check */ 2568c2ecf20Sopenharmony_ci if (((alt_setting == ABX500_ALT_A) && (af.gpiosel_bit == UNUSED)) || 2578c2ecf20Sopenharmony_ci ((alt_setting == ABX500_ALT_B) && (af.alt_bit1 == UNUSED)) || 2588c2ecf20Sopenharmony_ci ((alt_setting == ABX500_ALT_C) && (af.alt_bit2 == UNUSED))) { 2598c2ecf20Sopenharmony_ci dev_dbg(pct->dev, "pin %d doesn't support %s mode\n", gpio, 2608c2ecf20Sopenharmony_ci modes[alt_setting]); 2618c2ecf20Sopenharmony_ci return -EINVAL; 2628c2ecf20Sopenharmony_ci } 2638c2ecf20Sopenharmony_ci 2648c2ecf20Sopenharmony_ci /* on ABx5xx, there is no GPIO0, so adjust the offset */ 2658c2ecf20Sopenharmony_ci offset = gpio - 1; 2668c2ecf20Sopenharmony_ci 2678c2ecf20Sopenharmony_ci switch (alt_setting) { 2688c2ecf20Sopenharmony_ci case ABX500_DEFAULT: 2698c2ecf20Sopenharmony_ci /* 2708c2ecf20Sopenharmony_ci * for ABx5xx family, default mode is always selected by 2718c2ecf20Sopenharmony_ci * writing 0 to GPIOSELx register, except for pins which 2728c2ecf20Sopenharmony_ci * support at least ALT_B mode, default mode is selected 2738c2ecf20Sopenharmony_ci * by writing 1 to GPIOSELx register 2748c2ecf20Sopenharmony_ci */ 2758c2ecf20Sopenharmony_ci val = 0; 2768c2ecf20Sopenharmony_ci if (af.alt_bit1 != UNUSED) 2778c2ecf20Sopenharmony_ci val++; 2788c2ecf20Sopenharmony_ci 2798c2ecf20Sopenharmony_ci ret = abx500_gpio_set_bits(chip, AB8500_GPIO_SEL1_REG, 2808c2ecf20Sopenharmony_ci offset, val); 2818c2ecf20Sopenharmony_ci break; 2828c2ecf20Sopenharmony_ci 2838c2ecf20Sopenharmony_ci case ABX500_ALT_A: 2848c2ecf20Sopenharmony_ci /* 2858c2ecf20Sopenharmony_ci * for ABx5xx family, alt_a mode is always selected by 2868c2ecf20Sopenharmony_ci * writing 1 to GPIOSELx register, except for pins which 2878c2ecf20Sopenharmony_ci * support at least ALT_B mode, alt_a mode is selected 2888c2ecf20Sopenharmony_ci * by writing 0 to GPIOSELx register and 0 in ALTFUNC 2898c2ecf20Sopenharmony_ci * register 2908c2ecf20Sopenharmony_ci */ 2918c2ecf20Sopenharmony_ci if (af.alt_bit1 != UNUSED) { 2928c2ecf20Sopenharmony_ci ret = abx500_gpio_set_bits(chip, AB8500_GPIO_SEL1_REG, 2938c2ecf20Sopenharmony_ci offset, 0); 2948c2ecf20Sopenharmony_ci if (ret < 0) 2958c2ecf20Sopenharmony_ci goto out; 2968c2ecf20Sopenharmony_ci 2978c2ecf20Sopenharmony_ci ret = abx500_gpio_set_bits(chip, 2988c2ecf20Sopenharmony_ci AB8500_GPIO_ALTFUN_REG, 2998c2ecf20Sopenharmony_ci af.alt_bit1, 3008c2ecf20Sopenharmony_ci !!(af.alta_val & BIT(0))); 3018c2ecf20Sopenharmony_ci if (ret < 0) 3028c2ecf20Sopenharmony_ci goto out; 3038c2ecf20Sopenharmony_ci 3048c2ecf20Sopenharmony_ci if (af.alt_bit2 != UNUSED) 3058c2ecf20Sopenharmony_ci ret = abx500_gpio_set_bits(chip, 3068c2ecf20Sopenharmony_ci AB8500_GPIO_ALTFUN_REG, 3078c2ecf20Sopenharmony_ci af.alt_bit2, 3088c2ecf20Sopenharmony_ci !!(af.alta_val & BIT(1))); 3098c2ecf20Sopenharmony_ci } else 3108c2ecf20Sopenharmony_ci ret = abx500_gpio_set_bits(chip, AB8500_GPIO_SEL1_REG, 3118c2ecf20Sopenharmony_ci offset, 1); 3128c2ecf20Sopenharmony_ci break; 3138c2ecf20Sopenharmony_ci 3148c2ecf20Sopenharmony_ci case ABX500_ALT_B: 3158c2ecf20Sopenharmony_ci ret = abx500_gpio_set_bits(chip, AB8500_GPIO_SEL1_REG, 3168c2ecf20Sopenharmony_ci offset, 0); 3178c2ecf20Sopenharmony_ci if (ret < 0) 3188c2ecf20Sopenharmony_ci goto out; 3198c2ecf20Sopenharmony_ci 3208c2ecf20Sopenharmony_ci ret = abx500_gpio_set_bits(chip, AB8500_GPIO_ALTFUN_REG, 3218c2ecf20Sopenharmony_ci af.alt_bit1, !!(af.altb_val & BIT(0))); 3228c2ecf20Sopenharmony_ci if (ret < 0) 3238c2ecf20Sopenharmony_ci goto out; 3248c2ecf20Sopenharmony_ci 3258c2ecf20Sopenharmony_ci if (af.alt_bit2 != UNUSED) 3268c2ecf20Sopenharmony_ci ret = abx500_gpio_set_bits(chip, 3278c2ecf20Sopenharmony_ci AB8500_GPIO_ALTFUN_REG, 3288c2ecf20Sopenharmony_ci af.alt_bit2, 3298c2ecf20Sopenharmony_ci !!(af.altb_val & BIT(1))); 3308c2ecf20Sopenharmony_ci break; 3318c2ecf20Sopenharmony_ci 3328c2ecf20Sopenharmony_ci case ABX500_ALT_C: 3338c2ecf20Sopenharmony_ci ret = abx500_gpio_set_bits(chip, AB8500_GPIO_SEL1_REG, 3348c2ecf20Sopenharmony_ci offset, 0); 3358c2ecf20Sopenharmony_ci if (ret < 0) 3368c2ecf20Sopenharmony_ci goto out; 3378c2ecf20Sopenharmony_ci 3388c2ecf20Sopenharmony_ci ret = abx500_gpio_set_bits(chip, AB8500_GPIO_ALTFUN_REG, 3398c2ecf20Sopenharmony_ci af.alt_bit2, !!(af.altc_val & BIT(0))); 3408c2ecf20Sopenharmony_ci if (ret < 0) 3418c2ecf20Sopenharmony_ci goto out; 3428c2ecf20Sopenharmony_ci 3438c2ecf20Sopenharmony_ci ret = abx500_gpio_set_bits(chip, AB8500_GPIO_ALTFUN_REG, 3448c2ecf20Sopenharmony_ci af.alt_bit2, !!(af.altc_val & BIT(1))); 3458c2ecf20Sopenharmony_ci break; 3468c2ecf20Sopenharmony_ci 3478c2ecf20Sopenharmony_ci default: 3488c2ecf20Sopenharmony_ci dev_dbg(pct->dev, "unknown alt_setting %d\n", alt_setting); 3498c2ecf20Sopenharmony_ci 3508c2ecf20Sopenharmony_ci return -EINVAL; 3518c2ecf20Sopenharmony_ci } 3528c2ecf20Sopenharmony_ciout: 3538c2ecf20Sopenharmony_ci if (ret < 0) 3548c2ecf20Sopenharmony_ci dev_err(pct->dev, "%s failed (%d)\n", __func__, ret); 3558c2ecf20Sopenharmony_ci 3568c2ecf20Sopenharmony_ci return ret; 3578c2ecf20Sopenharmony_ci} 3588c2ecf20Sopenharmony_ci 3598c2ecf20Sopenharmony_ci#ifdef CONFIG_DEBUG_FS 3608c2ecf20Sopenharmony_cistatic int abx500_get_mode(struct pinctrl_dev *pctldev, struct gpio_chip *chip, 3618c2ecf20Sopenharmony_ci unsigned gpio) 3628c2ecf20Sopenharmony_ci{ 3638c2ecf20Sopenharmony_ci u8 mode; 3648c2ecf20Sopenharmony_ci bool bit_mode; 3658c2ecf20Sopenharmony_ci bool alt_bit1; 3668c2ecf20Sopenharmony_ci bool alt_bit2; 3678c2ecf20Sopenharmony_ci struct abx500_pinctrl *pct = pinctrl_dev_get_drvdata(pctldev); 3688c2ecf20Sopenharmony_ci struct alternate_functions af = pct->soc->alternate_functions[gpio]; 3698c2ecf20Sopenharmony_ci /* on ABx5xx, there is no GPIO0, so adjust the offset */ 3708c2ecf20Sopenharmony_ci unsigned offset = gpio - 1; 3718c2ecf20Sopenharmony_ci int ret; 3728c2ecf20Sopenharmony_ci 3738c2ecf20Sopenharmony_ci /* 3748c2ecf20Sopenharmony_ci * if gpiosel_bit is set to unused, 3758c2ecf20Sopenharmony_ci * it means no GPIO or special case 3768c2ecf20Sopenharmony_ci */ 3778c2ecf20Sopenharmony_ci if (af.gpiosel_bit == UNUSED) 3788c2ecf20Sopenharmony_ci return ABX500_DEFAULT; 3798c2ecf20Sopenharmony_ci 3808c2ecf20Sopenharmony_ci /* read GpioSelx register */ 3818c2ecf20Sopenharmony_ci ret = abx500_gpio_get_bit(chip, AB8500_GPIO_SEL1_REG + (offset / 8), 3828c2ecf20Sopenharmony_ci af.gpiosel_bit, &bit_mode); 3838c2ecf20Sopenharmony_ci if (ret < 0) 3848c2ecf20Sopenharmony_ci goto out; 3858c2ecf20Sopenharmony_ci 3868c2ecf20Sopenharmony_ci mode = bit_mode; 3878c2ecf20Sopenharmony_ci 3888c2ecf20Sopenharmony_ci /* sanity check */ 3898c2ecf20Sopenharmony_ci if ((af.alt_bit1 < UNUSED) || (af.alt_bit1 > 7) || 3908c2ecf20Sopenharmony_ci (af.alt_bit2 < UNUSED) || (af.alt_bit2 > 7)) { 3918c2ecf20Sopenharmony_ci dev_err(pct->dev, 3928c2ecf20Sopenharmony_ci "alt_bitX value not in correct range (-1 to 7)\n"); 3938c2ecf20Sopenharmony_ci return -EINVAL; 3948c2ecf20Sopenharmony_ci } 3958c2ecf20Sopenharmony_ci 3968c2ecf20Sopenharmony_ci /* if alt_bit2 is used, alt_bit1 must be used too */ 3978c2ecf20Sopenharmony_ci if ((af.alt_bit2 != UNUSED) && (af.alt_bit1 == UNUSED)) { 3988c2ecf20Sopenharmony_ci dev_err(pct->dev, 3998c2ecf20Sopenharmony_ci "if alt_bit2 is used, alt_bit1 can't be unused\n"); 4008c2ecf20Sopenharmony_ci return -EINVAL; 4018c2ecf20Sopenharmony_ci } 4028c2ecf20Sopenharmony_ci 4038c2ecf20Sopenharmony_ci /* check if pin use AlternateFunction register */ 4048c2ecf20Sopenharmony_ci if ((af.alt_bit1 == UNUSED) && (af.alt_bit2 == UNUSED)) 4058c2ecf20Sopenharmony_ci return mode; 4068c2ecf20Sopenharmony_ci /* 4078c2ecf20Sopenharmony_ci * if pin GPIOSEL bit is set and pin supports alternate function, 4088c2ecf20Sopenharmony_ci * it means DEFAULT mode 4098c2ecf20Sopenharmony_ci */ 4108c2ecf20Sopenharmony_ci if (mode) 4118c2ecf20Sopenharmony_ci return ABX500_DEFAULT; 4128c2ecf20Sopenharmony_ci 4138c2ecf20Sopenharmony_ci /* 4148c2ecf20Sopenharmony_ci * pin use the AlternatFunction register 4158c2ecf20Sopenharmony_ci * read alt_bit1 value 4168c2ecf20Sopenharmony_ci */ 4178c2ecf20Sopenharmony_ci ret = abx500_gpio_get_bit(chip, AB8500_GPIO_ALTFUN_REG, 4188c2ecf20Sopenharmony_ci af.alt_bit1, &alt_bit1); 4198c2ecf20Sopenharmony_ci if (ret < 0) 4208c2ecf20Sopenharmony_ci goto out; 4218c2ecf20Sopenharmony_ci 4228c2ecf20Sopenharmony_ci if (af.alt_bit2 != UNUSED) { 4238c2ecf20Sopenharmony_ci /* read alt_bit2 value */ 4248c2ecf20Sopenharmony_ci ret = abx500_gpio_get_bit(chip, AB8500_GPIO_ALTFUN_REG, 4258c2ecf20Sopenharmony_ci af.alt_bit2, 4268c2ecf20Sopenharmony_ci &alt_bit2); 4278c2ecf20Sopenharmony_ci if (ret < 0) 4288c2ecf20Sopenharmony_ci goto out; 4298c2ecf20Sopenharmony_ci } else 4308c2ecf20Sopenharmony_ci alt_bit2 = 0; 4318c2ecf20Sopenharmony_ci 4328c2ecf20Sopenharmony_ci mode = (alt_bit2 << 1) + alt_bit1; 4338c2ecf20Sopenharmony_ci if (mode == af.alta_val) 4348c2ecf20Sopenharmony_ci return ABX500_ALT_A; 4358c2ecf20Sopenharmony_ci else if (mode == af.altb_val) 4368c2ecf20Sopenharmony_ci return ABX500_ALT_B; 4378c2ecf20Sopenharmony_ci else 4388c2ecf20Sopenharmony_ci return ABX500_ALT_C; 4398c2ecf20Sopenharmony_ci 4408c2ecf20Sopenharmony_ciout: 4418c2ecf20Sopenharmony_ci dev_err(pct->dev, "%s failed (%d)\n", __func__, ret); 4428c2ecf20Sopenharmony_ci return ret; 4438c2ecf20Sopenharmony_ci} 4448c2ecf20Sopenharmony_ci 4458c2ecf20Sopenharmony_ci#include <linux/seq_file.h> 4468c2ecf20Sopenharmony_ci 4478c2ecf20Sopenharmony_cistatic void abx500_gpio_dbg_show_one(struct seq_file *s, 4488c2ecf20Sopenharmony_ci struct pinctrl_dev *pctldev, 4498c2ecf20Sopenharmony_ci struct gpio_chip *chip, 4508c2ecf20Sopenharmony_ci unsigned offset, unsigned gpio) 4518c2ecf20Sopenharmony_ci{ 4528c2ecf20Sopenharmony_ci struct abx500_pinctrl *pct = pinctrl_dev_get_drvdata(pctldev); 4538c2ecf20Sopenharmony_ci const char *label = gpiochip_is_requested(chip, offset - 1); 4548c2ecf20Sopenharmony_ci u8 gpio_offset = offset - 1; 4558c2ecf20Sopenharmony_ci int mode = -1; 4568c2ecf20Sopenharmony_ci bool is_out; 4578c2ecf20Sopenharmony_ci bool pd; 4588c2ecf20Sopenharmony_ci int ret; 4598c2ecf20Sopenharmony_ci 4608c2ecf20Sopenharmony_ci const char *modes[] = { 4618c2ecf20Sopenharmony_ci [ABX500_DEFAULT] = "default", 4628c2ecf20Sopenharmony_ci [ABX500_ALT_A] = "altA", 4638c2ecf20Sopenharmony_ci [ABX500_ALT_B] = "altB", 4648c2ecf20Sopenharmony_ci [ABX500_ALT_C] = "altC", 4658c2ecf20Sopenharmony_ci }; 4668c2ecf20Sopenharmony_ci 4678c2ecf20Sopenharmony_ci const char *pull_up_down[] = { 4688c2ecf20Sopenharmony_ci [ABX500_GPIO_PULL_DOWN] = "pull down", 4698c2ecf20Sopenharmony_ci [ABX500_GPIO_PULL_NONE] = "pull none", 4708c2ecf20Sopenharmony_ci [ABX500_GPIO_PULL_NONE + 1] = "pull none", 4718c2ecf20Sopenharmony_ci [ABX500_GPIO_PULL_UP] = "pull up", 4728c2ecf20Sopenharmony_ci }; 4738c2ecf20Sopenharmony_ci 4748c2ecf20Sopenharmony_ci ret = abx500_gpio_get_bit(chip, AB8500_GPIO_DIR1_REG, 4758c2ecf20Sopenharmony_ci gpio_offset, &is_out); 4768c2ecf20Sopenharmony_ci if (ret < 0) 4778c2ecf20Sopenharmony_ci goto out; 4788c2ecf20Sopenharmony_ci 4798c2ecf20Sopenharmony_ci seq_printf(s, " gpio-%-3d (%-20.20s) %-3s", 4808c2ecf20Sopenharmony_ci gpio, label ?: "(none)", 4818c2ecf20Sopenharmony_ci is_out ? "out" : "in "); 4828c2ecf20Sopenharmony_ci 4838c2ecf20Sopenharmony_ci if (!is_out) { 4848c2ecf20Sopenharmony_ci ret = abx500_gpio_get_bit(chip, AB8500_GPIO_PUD1_REG, 4858c2ecf20Sopenharmony_ci gpio_offset, &pd); 4868c2ecf20Sopenharmony_ci if (ret < 0) 4878c2ecf20Sopenharmony_ci goto out; 4888c2ecf20Sopenharmony_ci 4898c2ecf20Sopenharmony_ci seq_printf(s, " %-9s", pull_up_down[pd]); 4908c2ecf20Sopenharmony_ci } else 4918c2ecf20Sopenharmony_ci seq_printf(s, " %-9s", chip->get(chip, offset) ? "hi" : "lo"); 4928c2ecf20Sopenharmony_ci 4938c2ecf20Sopenharmony_ci mode = abx500_get_mode(pctldev, chip, offset); 4948c2ecf20Sopenharmony_ci 4958c2ecf20Sopenharmony_ci seq_printf(s, " %s", (mode < 0) ? "unknown" : modes[mode]); 4968c2ecf20Sopenharmony_ci 4978c2ecf20Sopenharmony_ciout: 4988c2ecf20Sopenharmony_ci if (ret < 0) 4998c2ecf20Sopenharmony_ci dev_err(pct->dev, "%s failed (%d)\n", __func__, ret); 5008c2ecf20Sopenharmony_ci} 5018c2ecf20Sopenharmony_ci 5028c2ecf20Sopenharmony_cistatic void abx500_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip) 5038c2ecf20Sopenharmony_ci{ 5048c2ecf20Sopenharmony_ci unsigned i; 5058c2ecf20Sopenharmony_ci unsigned gpio = chip->base; 5068c2ecf20Sopenharmony_ci struct abx500_pinctrl *pct = gpiochip_get_data(chip); 5078c2ecf20Sopenharmony_ci struct pinctrl_dev *pctldev = pct->pctldev; 5088c2ecf20Sopenharmony_ci 5098c2ecf20Sopenharmony_ci for (i = 0; i < chip->ngpio; i++, gpio++) { 5108c2ecf20Sopenharmony_ci /* On AB8500, there is no GPIO0, the first is the GPIO 1 */ 5118c2ecf20Sopenharmony_ci abx500_gpio_dbg_show_one(s, pctldev, chip, i + 1, gpio); 5128c2ecf20Sopenharmony_ci seq_putc(s, '\n'); 5138c2ecf20Sopenharmony_ci } 5148c2ecf20Sopenharmony_ci} 5158c2ecf20Sopenharmony_ci 5168c2ecf20Sopenharmony_ci#else 5178c2ecf20Sopenharmony_cistatic inline void abx500_gpio_dbg_show_one(struct seq_file *s, 5188c2ecf20Sopenharmony_ci struct pinctrl_dev *pctldev, 5198c2ecf20Sopenharmony_ci struct gpio_chip *chip, 5208c2ecf20Sopenharmony_ci unsigned offset, unsigned gpio) 5218c2ecf20Sopenharmony_ci{ 5228c2ecf20Sopenharmony_ci} 5238c2ecf20Sopenharmony_ci#define abx500_gpio_dbg_show NULL 5248c2ecf20Sopenharmony_ci#endif 5258c2ecf20Sopenharmony_ci 5268c2ecf20Sopenharmony_cistatic const struct gpio_chip abx500gpio_chip = { 5278c2ecf20Sopenharmony_ci .label = "abx500-gpio", 5288c2ecf20Sopenharmony_ci .owner = THIS_MODULE, 5298c2ecf20Sopenharmony_ci .request = gpiochip_generic_request, 5308c2ecf20Sopenharmony_ci .free = gpiochip_generic_free, 5318c2ecf20Sopenharmony_ci .direction_input = abx500_gpio_direction_input, 5328c2ecf20Sopenharmony_ci .get = abx500_gpio_get, 5338c2ecf20Sopenharmony_ci .direction_output = abx500_gpio_direction_output, 5348c2ecf20Sopenharmony_ci .set = abx500_gpio_set, 5358c2ecf20Sopenharmony_ci .to_irq = abx500_gpio_to_irq, 5368c2ecf20Sopenharmony_ci .dbg_show = abx500_gpio_dbg_show, 5378c2ecf20Sopenharmony_ci}; 5388c2ecf20Sopenharmony_ci 5398c2ecf20Sopenharmony_cistatic int abx500_pmx_get_funcs_cnt(struct pinctrl_dev *pctldev) 5408c2ecf20Sopenharmony_ci{ 5418c2ecf20Sopenharmony_ci struct abx500_pinctrl *pct = pinctrl_dev_get_drvdata(pctldev); 5428c2ecf20Sopenharmony_ci 5438c2ecf20Sopenharmony_ci return pct->soc->nfunctions; 5448c2ecf20Sopenharmony_ci} 5458c2ecf20Sopenharmony_ci 5468c2ecf20Sopenharmony_cistatic const char *abx500_pmx_get_func_name(struct pinctrl_dev *pctldev, 5478c2ecf20Sopenharmony_ci unsigned function) 5488c2ecf20Sopenharmony_ci{ 5498c2ecf20Sopenharmony_ci struct abx500_pinctrl *pct = pinctrl_dev_get_drvdata(pctldev); 5508c2ecf20Sopenharmony_ci 5518c2ecf20Sopenharmony_ci return pct->soc->functions[function].name; 5528c2ecf20Sopenharmony_ci} 5538c2ecf20Sopenharmony_ci 5548c2ecf20Sopenharmony_cistatic int abx500_pmx_get_func_groups(struct pinctrl_dev *pctldev, 5558c2ecf20Sopenharmony_ci unsigned function, 5568c2ecf20Sopenharmony_ci const char * const **groups, 5578c2ecf20Sopenharmony_ci unsigned * const num_groups) 5588c2ecf20Sopenharmony_ci{ 5598c2ecf20Sopenharmony_ci struct abx500_pinctrl *pct = pinctrl_dev_get_drvdata(pctldev); 5608c2ecf20Sopenharmony_ci 5618c2ecf20Sopenharmony_ci *groups = pct->soc->functions[function].groups; 5628c2ecf20Sopenharmony_ci *num_groups = pct->soc->functions[function].ngroups; 5638c2ecf20Sopenharmony_ci 5648c2ecf20Sopenharmony_ci return 0; 5658c2ecf20Sopenharmony_ci} 5668c2ecf20Sopenharmony_ci 5678c2ecf20Sopenharmony_cistatic int abx500_pmx_set(struct pinctrl_dev *pctldev, unsigned function, 5688c2ecf20Sopenharmony_ci unsigned group) 5698c2ecf20Sopenharmony_ci{ 5708c2ecf20Sopenharmony_ci struct abx500_pinctrl *pct = pinctrl_dev_get_drvdata(pctldev); 5718c2ecf20Sopenharmony_ci struct gpio_chip *chip = &pct->chip; 5728c2ecf20Sopenharmony_ci const struct abx500_pingroup *g; 5738c2ecf20Sopenharmony_ci int i; 5748c2ecf20Sopenharmony_ci int ret = 0; 5758c2ecf20Sopenharmony_ci 5768c2ecf20Sopenharmony_ci g = &pct->soc->groups[group]; 5778c2ecf20Sopenharmony_ci if (g->altsetting < 0) 5788c2ecf20Sopenharmony_ci return -EINVAL; 5798c2ecf20Sopenharmony_ci 5808c2ecf20Sopenharmony_ci dev_dbg(pct->dev, "enable group %s, %u pins\n", g->name, g->npins); 5818c2ecf20Sopenharmony_ci 5828c2ecf20Sopenharmony_ci for (i = 0; i < g->npins; i++) { 5838c2ecf20Sopenharmony_ci dev_dbg(pct->dev, "setting pin %d to altsetting %d\n", 5848c2ecf20Sopenharmony_ci g->pins[i], g->altsetting); 5858c2ecf20Sopenharmony_ci 5868c2ecf20Sopenharmony_ci ret = abx500_set_mode(pctldev, chip, g->pins[i], g->altsetting); 5878c2ecf20Sopenharmony_ci } 5888c2ecf20Sopenharmony_ci 5898c2ecf20Sopenharmony_ci if (ret < 0) 5908c2ecf20Sopenharmony_ci dev_err(pct->dev, "%s failed (%d)\n", __func__, ret); 5918c2ecf20Sopenharmony_ci 5928c2ecf20Sopenharmony_ci return ret; 5938c2ecf20Sopenharmony_ci} 5948c2ecf20Sopenharmony_ci 5958c2ecf20Sopenharmony_cistatic int abx500_gpio_request_enable(struct pinctrl_dev *pctldev, 5968c2ecf20Sopenharmony_ci struct pinctrl_gpio_range *range, 5978c2ecf20Sopenharmony_ci unsigned offset) 5988c2ecf20Sopenharmony_ci{ 5998c2ecf20Sopenharmony_ci struct abx500_pinctrl *pct = pinctrl_dev_get_drvdata(pctldev); 6008c2ecf20Sopenharmony_ci const struct abx500_pinrange *p; 6018c2ecf20Sopenharmony_ci int ret; 6028c2ecf20Sopenharmony_ci int i; 6038c2ecf20Sopenharmony_ci 6048c2ecf20Sopenharmony_ci /* 6058c2ecf20Sopenharmony_ci * Different ranges have different ways to enable GPIO function on a 6068c2ecf20Sopenharmony_ci * pin, so refer back to our local range type, where we handily define 6078c2ecf20Sopenharmony_ci * what altfunc enables GPIO for a certain pin. 6088c2ecf20Sopenharmony_ci */ 6098c2ecf20Sopenharmony_ci for (i = 0; i < pct->soc->gpio_num_ranges; i++) { 6108c2ecf20Sopenharmony_ci p = &pct->soc->gpio_ranges[i]; 6118c2ecf20Sopenharmony_ci if ((offset >= p->offset) && 6128c2ecf20Sopenharmony_ci (offset < (p->offset + p->npins))) 6138c2ecf20Sopenharmony_ci break; 6148c2ecf20Sopenharmony_ci } 6158c2ecf20Sopenharmony_ci 6168c2ecf20Sopenharmony_ci if (i == pct->soc->gpio_num_ranges) { 6178c2ecf20Sopenharmony_ci dev_err(pct->dev, "%s failed to locate range\n", __func__); 6188c2ecf20Sopenharmony_ci return -ENODEV; 6198c2ecf20Sopenharmony_ci } 6208c2ecf20Sopenharmony_ci 6218c2ecf20Sopenharmony_ci dev_dbg(pct->dev, "enable GPIO by altfunc %d at gpio %d\n", 6228c2ecf20Sopenharmony_ci p->altfunc, offset); 6238c2ecf20Sopenharmony_ci 6248c2ecf20Sopenharmony_ci ret = abx500_set_mode(pct->pctldev, &pct->chip, 6258c2ecf20Sopenharmony_ci offset, p->altfunc); 6268c2ecf20Sopenharmony_ci if (ret < 0) 6278c2ecf20Sopenharmony_ci dev_err(pct->dev, "%s setting altfunc failed\n", __func__); 6288c2ecf20Sopenharmony_ci 6298c2ecf20Sopenharmony_ci return ret; 6308c2ecf20Sopenharmony_ci} 6318c2ecf20Sopenharmony_ci 6328c2ecf20Sopenharmony_cistatic void abx500_gpio_disable_free(struct pinctrl_dev *pctldev, 6338c2ecf20Sopenharmony_ci struct pinctrl_gpio_range *range, 6348c2ecf20Sopenharmony_ci unsigned offset) 6358c2ecf20Sopenharmony_ci{ 6368c2ecf20Sopenharmony_ci} 6378c2ecf20Sopenharmony_ci 6388c2ecf20Sopenharmony_cistatic const struct pinmux_ops abx500_pinmux_ops = { 6398c2ecf20Sopenharmony_ci .get_functions_count = abx500_pmx_get_funcs_cnt, 6408c2ecf20Sopenharmony_ci .get_function_name = abx500_pmx_get_func_name, 6418c2ecf20Sopenharmony_ci .get_function_groups = abx500_pmx_get_func_groups, 6428c2ecf20Sopenharmony_ci .set_mux = abx500_pmx_set, 6438c2ecf20Sopenharmony_ci .gpio_request_enable = abx500_gpio_request_enable, 6448c2ecf20Sopenharmony_ci .gpio_disable_free = abx500_gpio_disable_free, 6458c2ecf20Sopenharmony_ci}; 6468c2ecf20Sopenharmony_ci 6478c2ecf20Sopenharmony_cistatic int abx500_get_groups_cnt(struct pinctrl_dev *pctldev) 6488c2ecf20Sopenharmony_ci{ 6498c2ecf20Sopenharmony_ci struct abx500_pinctrl *pct = pinctrl_dev_get_drvdata(pctldev); 6508c2ecf20Sopenharmony_ci 6518c2ecf20Sopenharmony_ci return pct->soc->ngroups; 6528c2ecf20Sopenharmony_ci} 6538c2ecf20Sopenharmony_ci 6548c2ecf20Sopenharmony_cistatic const char *abx500_get_group_name(struct pinctrl_dev *pctldev, 6558c2ecf20Sopenharmony_ci unsigned selector) 6568c2ecf20Sopenharmony_ci{ 6578c2ecf20Sopenharmony_ci struct abx500_pinctrl *pct = pinctrl_dev_get_drvdata(pctldev); 6588c2ecf20Sopenharmony_ci 6598c2ecf20Sopenharmony_ci return pct->soc->groups[selector].name; 6608c2ecf20Sopenharmony_ci} 6618c2ecf20Sopenharmony_ci 6628c2ecf20Sopenharmony_cistatic int abx500_get_group_pins(struct pinctrl_dev *pctldev, 6638c2ecf20Sopenharmony_ci unsigned selector, 6648c2ecf20Sopenharmony_ci const unsigned **pins, 6658c2ecf20Sopenharmony_ci unsigned *num_pins) 6668c2ecf20Sopenharmony_ci{ 6678c2ecf20Sopenharmony_ci struct abx500_pinctrl *pct = pinctrl_dev_get_drvdata(pctldev); 6688c2ecf20Sopenharmony_ci 6698c2ecf20Sopenharmony_ci *pins = pct->soc->groups[selector].pins; 6708c2ecf20Sopenharmony_ci *num_pins = pct->soc->groups[selector].npins; 6718c2ecf20Sopenharmony_ci 6728c2ecf20Sopenharmony_ci return 0; 6738c2ecf20Sopenharmony_ci} 6748c2ecf20Sopenharmony_ci 6758c2ecf20Sopenharmony_cistatic void abx500_pin_dbg_show(struct pinctrl_dev *pctldev, 6768c2ecf20Sopenharmony_ci struct seq_file *s, unsigned offset) 6778c2ecf20Sopenharmony_ci{ 6788c2ecf20Sopenharmony_ci struct abx500_pinctrl *pct = pinctrl_dev_get_drvdata(pctldev); 6798c2ecf20Sopenharmony_ci struct gpio_chip *chip = &pct->chip; 6808c2ecf20Sopenharmony_ci 6818c2ecf20Sopenharmony_ci abx500_gpio_dbg_show_one(s, pctldev, chip, offset, 6828c2ecf20Sopenharmony_ci chip->base + offset - 1); 6838c2ecf20Sopenharmony_ci} 6848c2ecf20Sopenharmony_ci 6858c2ecf20Sopenharmony_cistatic int abx500_dt_add_map_mux(struct pinctrl_map **map, 6868c2ecf20Sopenharmony_ci unsigned *reserved_maps, 6878c2ecf20Sopenharmony_ci unsigned *num_maps, const char *group, 6888c2ecf20Sopenharmony_ci const char *function) 6898c2ecf20Sopenharmony_ci{ 6908c2ecf20Sopenharmony_ci if (*num_maps == *reserved_maps) 6918c2ecf20Sopenharmony_ci return -ENOSPC; 6928c2ecf20Sopenharmony_ci 6938c2ecf20Sopenharmony_ci (*map)[*num_maps].type = PIN_MAP_TYPE_MUX_GROUP; 6948c2ecf20Sopenharmony_ci (*map)[*num_maps].data.mux.group = group; 6958c2ecf20Sopenharmony_ci (*map)[*num_maps].data.mux.function = function; 6968c2ecf20Sopenharmony_ci (*num_maps)++; 6978c2ecf20Sopenharmony_ci 6988c2ecf20Sopenharmony_ci return 0; 6998c2ecf20Sopenharmony_ci} 7008c2ecf20Sopenharmony_ci 7018c2ecf20Sopenharmony_cistatic int abx500_dt_add_map_configs(struct pinctrl_map **map, 7028c2ecf20Sopenharmony_ci unsigned *reserved_maps, 7038c2ecf20Sopenharmony_ci unsigned *num_maps, const char *group, 7048c2ecf20Sopenharmony_ci unsigned long *configs, unsigned num_configs) 7058c2ecf20Sopenharmony_ci{ 7068c2ecf20Sopenharmony_ci unsigned long *dup_configs; 7078c2ecf20Sopenharmony_ci 7088c2ecf20Sopenharmony_ci if (*num_maps == *reserved_maps) 7098c2ecf20Sopenharmony_ci return -ENOSPC; 7108c2ecf20Sopenharmony_ci 7118c2ecf20Sopenharmony_ci dup_configs = kmemdup(configs, num_configs * sizeof(*dup_configs), 7128c2ecf20Sopenharmony_ci GFP_KERNEL); 7138c2ecf20Sopenharmony_ci if (!dup_configs) 7148c2ecf20Sopenharmony_ci return -ENOMEM; 7158c2ecf20Sopenharmony_ci 7168c2ecf20Sopenharmony_ci (*map)[*num_maps].type = PIN_MAP_TYPE_CONFIGS_PIN; 7178c2ecf20Sopenharmony_ci 7188c2ecf20Sopenharmony_ci (*map)[*num_maps].data.configs.group_or_pin = group; 7198c2ecf20Sopenharmony_ci (*map)[*num_maps].data.configs.configs = dup_configs; 7208c2ecf20Sopenharmony_ci (*map)[*num_maps].data.configs.num_configs = num_configs; 7218c2ecf20Sopenharmony_ci (*num_maps)++; 7228c2ecf20Sopenharmony_ci 7238c2ecf20Sopenharmony_ci return 0; 7248c2ecf20Sopenharmony_ci} 7258c2ecf20Sopenharmony_ci 7268c2ecf20Sopenharmony_cistatic const char *abx500_find_pin_name(struct pinctrl_dev *pctldev, 7278c2ecf20Sopenharmony_ci const char *pin_name) 7288c2ecf20Sopenharmony_ci{ 7298c2ecf20Sopenharmony_ci int i, pin_number; 7308c2ecf20Sopenharmony_ci struct abx500_pinctrl *npct = pinctrl_dev_get_drvdata(pctldev); 7318c2ecf20Sopenharmony_ci 7328c2ecf20Sopenharmony_ci if (sscanf((char *)pin_name, "GPIO%d", &pin_number) == 1) 7338c2ecf20Sopenharmony_ci for (i = 0; i < npct->soc->npins; i++) 7348c2ecf20Sopenharmony_ci if (npct->soc->pins[i].number == pin_number) 7358c2ecf20Sopenharmony_ci return npct->soc->pins[i].name; 7368c2ecf20Sopenharmony_ci return NULL; 7378c2ecf20Sopenharmony_ci} 7388c2ecf20Sopenharmony_ci 7398c2ecf20Sopenharmony_cistatic int abx500_dt_subnode_to_map(struct pinctrl_dev *pctldev, 7408c2ecf20Sopenharmony_ci struct device_node *np, 7418c2ecf20Sopenharmony_ci struct pinctrl_map **map, 7428c2ecf20Sopenharmony_ci unsigned *reserved_maps, 7438c2ecf20Sopenharmony_ci unsigned *num_maps) 7448c2ecf20Sopenharmony_ci{ 7458c2ecf20Sopenharmony_ci int ret; 7468c2ecf20Sopenharmony_ci const char *function = NULL; 7478c2ecf20Sopenharmony_ci unsigned long *configs; 7488c2ecf20Sopenharmony_ci unsigned int nconfigs = 0; 7498c2ecf20Sopenharmony_ci struct property *prop; 7508c2ecf20Sopenharmony_ci 7518c2ecf20Sopenharmony_ci ret = of_property_read_string(np, "function", &function); 7528c2ecf20Sopenharmony_ci if (ret >= 0) { 7538c2ecf20Sopenharmony_ci const char *group; 7548c2ecf20Sopenharmony_ci 7558c2ecf20Sopenharmony_ci ret = of_property_count_strings(np, "groups"); 7568c2ecf20Sopenharmony_ci if (ret < 0) 7578c2ecf20Sopenharmony_ci goto exit; 7588c2ecf20Sopenharmony_ci 7598c2ecf20Sopenharmony_ci ret = pinctrl_utils_reserve_map(pctldev, map, reserved_maps, 7608c2ecf20Sopenharmony_ci num_maps, ret); 7618c2ecf20Sopenharmony_ci if (ret < 0) 7628c2ecf20Sopenharmony_ci goto exit; 7638c2ecf20Sopenharmony_ci 7648c2ecf20Sopenharmony_ci of_property_for_each_string(np, "groups", prop, group) { 7658c2ecf20Sopenharmony_ci ret = abx500_dt_add_map_mux(map, reserved_maps, 7668c2ecf20Sopenharmony_ci num_maps, group, function); 7678c2ecf20Sopenharmony_ci if (ret < 0) 7688c2ecf20Sopenharmony_ci goto exit; 7698c2ecf20Sopenharmony_ci } 7708c2ecf20Sopenharmony_ci } 7718c2ecf20Sopenharmony_ci 7728c2ecf20Sopenharmony_ci ret = pinconf_generic_parse_dt_config(np, pctldev, &configs, &nconfigs); 7738c2ecf20Sopenharmony_ci if (nconfigs) { 7748c2ecf20Sopenharmony_ci const char *gpio_name; 7758c2ecf20Sopenharmony_ci const char *pin; 7768c2ecf20Sopenharmony_ci 7778c2ecf20Sopenharmony_ci ret = of_property_count_strings(np, "pins"); 7788c2ecf20Sopenharmony_ci if (ret < 0) 7798c2ecf20Sopenharmony_ci goto exit; 7808c2ecf20Sopenharmony_ci 7818c2ecf20Sopenharmony_ci ret = pinctrl_utils_reserve_map(pctldev, map, 7828c2ecf20Sopenharmony_ci reserved_maps, 7838c2ecf20Sopenharmony_ci num_maps, ret); 7848c2ecf20Sopenharmony_ci if (ret < 0) 7858c2ecf20Sopenharmony_ci goto exit; 7868c2ecf20Sopenharmony_ci 7878c2ecf20Sopenharmony_ci of_property_for_each_string(np, "pins", prop, pin) { 7888c2ecf20Sopenharmony_ci gpio_name = abx500_find_pin_name(pctldev, pin); 7898c2ecf20Sopenharmony_ci 7908c2ecf20Sopenharmony_ci ret = abx500_dt_add_map_configs(map, reserved_maps, 7918c2ecf20Sopenharmony_ci num_maps, gpio_name, configs, 1); 7928c2ecf20Sopenharmony_ci if (ret < 0) 7938c2ecf20Sopenharmony_ci goto exit; 7948c2ecf20Sopenharmony_ci } 7958c2ecf20Sopenharmony_ci } 7968c2ecf20Sopenharmony_ci 7978c2ecf20Sopenharmony_ciexit: 7988c2ecf20Sopenharmony_ci return ret; 7998c2ecf20Sopenharmony_ci} 8008c2ecf20Sopenharmony_ci 8018c2ecf20Sopenharmony_cistatic int abx500_dt_node_to_map(struct pinctrl_dev *pctldev, 8028c2ecf20Sopenharmony_ci struct device_node *np_config, 8038c2ecf20Sopenharmony_ci struct pinctrl_map **map, unsigned *num_maps) 8048c2ecf20Sopenharmony_ci{ 8058c2ecf20Sopenharmony_ci unsigned reserved_maps; 8068c2ecf20Sopenharmony_ci struct device_node *np; 8078c2ecf20Sopenharmony_ci int ret; 8088c2ecf20Sopenharmony_ci 8098c2ecf20Sopenharmony_ci reserved_maps = 0; 8108c2ecf20Sopenharmony_ci *map = NULL; 8118c2ecf20Sopenharmony_ci *num_maps = 0; 8128c2ecf20Sopenharmony_ci 8138c2ecf20Sopenharmony_ci for_each_child_of_node(np_config, np) { 8148c2ecf20Sopenharmony_ci ret = abx500_dt_subnode_to_map(pctldev, np, map, 8158c2ecf20Sopenharmony_ci &reserved_maps, num_maps); 8168c2ecf20Sopenharmony_ci if (ret < 0) { 8178c2ecf20Sopenharmony_ci pinctrl_utils_free_map(pctldev, *map, *num_maps); 8188c2ecf20Sopenharmony_ci of_node_put(np); 8198c2ecf20Sopenharmony_ci return ret; 8208c2ecf20Sopenharmony_ci } 8218c2ecf20Sopenharmony_ci } 8228c2ecf20Sopenharmony_ci 8238c2ecf20Sopenharmony_ci return 0; 8248c2ecf20Sopenharmony_ci} 8258c2ecf20Sopenharmony_ci 8268c2ecf20Sopenharmony_cistatic const struct pinctrl_ops abx500_pinctrl_ops = { 8278c2ecf20Sopenharmony_ci .get_groups_count = abx500_get_groups_cnt, 8288c2ecf20Sopenharmony_ci .get_group_name = abx500_get_group_name, 8298c2ecf20Sopenharmony_ci .get_group_pins = abx500_get_group_pins, 8308c2ecf20Sopenharmony_ci .pin_dbg_show = abx500_pin_dbg_show, 8318c2ecf20Sopenharmony_ci .dt_node_to_map = abx500_dt_node_to_map, 8328c2ecf20Sopenharmony_ci .dt_free_map = pinctrl_utils_free_map, 8338c2ecf20Sopenharmony_ci}; 8348c2ecf20Sopenharmony_ci 8358c2ecf20Sopenharmony_cistatic int abx500_pin_config_get(struct pinctrl_dev *pctldev, 8368c2ecf20Sopenharmony_ci unsigned pin, 8378c2ecf20Sopenharmony_ci unsigned long *config) 8388c2ecf20Sopenharmony_ci{ 8398c2ecf20Sopenharmony_ci return -ENOSYS; 8408c2ecf20Sopenharmony_ci} 8418c2ecf20Sopenharmony_ci 8428c2ecf20Sopenharmony_cistatic int abx500_pin_config_set(struct pinctrl_dev *pctldev, 8438c2ecf20Sopenharmony_ci unsigned pin, 8448c2ecf20Sopenharmony_ci unsigned long *configs, 8458c2ecf20Sopenharmony_ci unsigned num_configs) 8468c2ecf20Sopenharmony_ci{ 8478c2ecf20Sopenharmony_ci struct abx500_pinctrl *pct = pinctrl_dev_get_drvdata(pctldev); 8488c2ecf20Sopenharmony_ci struct gpio_chip *chip = &pct->chip; 8498c2ecf20Sopenharmony_ci unsigned offset; 8508c2ecf20Sopenharmony_ci int ret = -EINVAL; 8518c2ecf20Sopenharmony_ci int i; 8528c2ecf20Sopenharmony_ci enum pin_config_param param; 8538c2ecf20Sopenharmony_ci enum pin_config_param argument; 8548c2ecf20Sopenharmony_ci 8558c2ecf20Sopenharmony_ci for (i = 0; i < num_configs; i++) { 8568c2ecf20Sopenharmony_ci param = pinconf_to_config_param(configs[i]); 8578c2ecf20Sopenharmony_ci argument = pinconf_to_config_argument(configs[i]); 8588c2ecf20Sopenharmony_ci 8598c2ecf20Sopenharmony_ci dev_dbg(chip->parent, "pin %d [%#lx]: %s %s\n", 8608c2ecf20Sopenharmony_ci pin, configs[i], 8618c2ecf20Sopenharmony_ci (param == PIN_CONFIG_OUTPUT) ? "output " : "input", 8628c2ecf20Sopenharmony_ci (param == PIN_CONFIG_OUTPUT) ? 8638c2ecf20Sopenharmony_ci (argument ? "high" : "low") : 8648c2ecf20Sopenharmony_ci (argument ? "pull up" : "pull down")); 8658c2ecf20Sopenharmony_ci 8668c2ecf20Sopenharmony_ci /* on ABx500, there is no GPIO0, so adjust the offset */ 8678c2ecf20Sopenharmony_ci offset = pin - 1; 8688c2ecf20Sopenharmony_ci 8698c2ecf20Sopenharmony_ci switch (param) { 8708c2ecf20Sopenharmony_ci case PIN_CONFIG_BIAS_DISABLE: 8718c2ecf20Sopenharmony_ci ret = abx500_gpio_direction_input(chip, offset); 8728c2ecf20Sopenharmony_ci if (ret < 0) 8738c2ecf20Sopenharmony_ci goto out; 8748c2ecf20Sopenharmony_ci 8758c2ecf20Sopenharmony_ci /* Chip only supports pull down */ 8768c2ecf20Sopenharmony_ci ret = abx500_gpio_set_bits(chip, 8778c2ecf20Sopenharmony_ci AB8500_GPIO_PUD1_REG, offset, 8788c2ecf20Sopenharmony_ci ABX500_GPIO_PULL_NONE); 8798c2ecf20Sopenharmony_ci break; 8808c2ecf20Sopenharmony_ci 8818c2ecf20Sopenharmony_ci case PIN_CONFIG_BIAS_PULL_DOWN: 8828c2ecf20Sopenharmony_ci ret = abx500_gpio_direction_input(chip, offset); 8838c2ecf20Sopenharmony_ci if (ret < 0) 8848c2ecf20Sopenharmony_ci goto out; 8858c2ecf20Sopenharmony_ci /* 8868c2ecf20Sopenharmony_ci * if argument = 1 set the pull down 8878c2ecf20Sopenharmony_ci * else clear the pull down 8888c2ecf20Sopenharmony_ci * Chip only supports pull down 8898c2ecf20Sopenharmony_ci */ 8908c2ecf20Sopenharmony_ci ret = abx500_gpio_set_bits(chip, 8918c2ecf20Sopenharmony_ci AB8500_GPIO_PUD1_REG, 8928c2ecf20Sopenharmony_ci offset, 8938c2ecf20Sopenharmony_ci argument ? ABX500_GPIO_PULL_DOWN : 8948c2ecf20Sopenharmony_ci ABX500_GPIO_PULL_NONE); 8958c2ecf20Sopenharmony_ci break; 8968c2ecf20Sopenharmony_ci 8978c2ecf20Sopenharmony_ci case PIN_CONFIG_BIAS_PULL_UP: 8988c2ecf20Sopenharmony_ci ret = abx500_gpio_direction_input(chip, offset); 8998c2ecf20Sopenharmony_ci if (ret < 0) 9008c2ecf20Sopenharmony_ci goto out; 9018c2ecf20Sopenharmony_ci /* 9028c2ecf20Sopenharmony_ci * if argument = 1 set the pull up 9038c2ecf20Sopenharmony_ci * else clear the pull up 9048c2ecf20Sopenharmony_ci */ 9058c2ecf20Sopenharmony_ci ret = abx500_gpio_direction_input(chip, offset); 9068c2ecf20Sopenharmony_ci break; 9078c2ecf20Sopenharmony_ci 9088c2ecf20Sopenharmony_ci case PIN_CONFIG_OUTPUT: 9098c2ecf20Sopenharmony_ci ret = abx500_gpio_direction_output(chip, offset, 9108c2ecf20Sopenharmony_ci argument); 9118c2ecf20Sopenharmony_ci break; 9128c2ecf20Sopenharmony_ci 9138c2ecf20Sopenharmony_ci default: 9148c2ecf20Sopenharmony_ci dev_err(chip->parent, 9158c2ecf20Sopenharmony_ci "illegal configuration requested\n"); 9168c2ecf20Sopenharmony_ci } 9178c2ecf20Sopenharmony_ci } /* for each config */ 9188c2ecf20Sopenharmony_ciout: 9198c2ecf20Sopenharmony_ci if (ret < 0) 9208c2ecf20Sopenharmony_ci dev_err(pct->dev, "%s failed (%d)\n", __func__, ret); 9218c2ecf20Sopenharmony_ci 9228c2ecf20Sopenharmony_ci return ret; 9238c2ecf20Sopenharmony_ci} 9248c2ecf20Sopenharmony_ci 9258c2ecf20Sopenharmony_cistatic const struct pinconf_ops abx500_pinconf_ops = { 9268c2ecf20Sopenharmony_ci .pin_config_get = abx500_pin_config_get, 9278c2ecf20Sopenharmony_ci .pin_config_set = abx500_pin_config_set, 9288c2ecf20Sopenharmony_ci .is_generic = true, 9298c2ecf20Sopenharmony_ci}; 9308c2ecf20Sopenharmony_ci 9318c2ecf20Sopenharmony_cistatic struct pinctrl_desc abx500_pinctrl_desc = { 9328c2ecf20Sopenharmony_ci .name = "pinctrl-abx500", 9338c2ecf20Sopenharmony_ci .pctlops = &abx500_pinctrl_ops, 9348c2ecf20Sopenharmony_ci .pmxops = &abx500_pinmux_ops, 9358c2ecf20Sopenharmony_ci .confops = &abx500_pinconf_ops, 9368c2ecf20Sopenharmony_ci .owner = THIS_MODULE, 9378c2ecf20Sopenharmony_ci}; 9388c2ecf20Sopenharmony_ci 9398c2ecf20Sopenharmony_cistatic int abx500_get_gpio_num(struct abx500_pinctrl_soc_data *soc) 9408c2ecf20Sopenharmony_ci{ 9418c2ecf20Sopenharmony_ci unsigned int lowest = 0; 9428c2ecf20Sopenharmony_ci unsigned int highest = 0; 9438c2ecf20Sopenharmony_ci unsigned int npins = 0; 9448c2ecf20Sopenharmony_ci int i; 9458c2ecf20Sopenharmony_ci 9468c2ecf20Sopenharmony_ci /* 9478c2ecf20Sopenharmony_ci * Compute number of GPIOs from the last SoC gpio range descriptors 9488c2ecf20Sopenharmony_ci * These ranges may include "holes" but the GPIO number space shall 9498c2ecf20Sopenharmony_ci * still be homogeneous, so we need to detect and account for any 9508c2ecf20Sopenharmony_ci * such holes so that these are included in the number of GPIO pins. 9518c2ecf20Sopenharmony_ci */ 9528c2ecf20Sopenharmony_ci for (i = 0; i < soc->gpio_num_ranges; i++) { 9538c2ecf20Sopenharmony_ci unsigned gstart; 9548c2ecf20Sopenharmony_ci unsigned gend; 9558c2ecf20Sopenharmony_ci const struct abx500_pinrange *p; 9568c2ecf20Sopenharmony_ci 9578c2ecf20Sopenharmony_ci p = &soc->gpio_ranges[i]; 9588c2ecf20Sopenharmony_ci gstart = p->offset; 9598c2ecf20Sopenharmony_ci gend = p->offset + p->npins - 1; 9608c2ecf20Sopenharmony_ci 9618c2ecf20Sopenharmony_ci if (i == 0) { 9628c2ecf20Sopenharmony_ci /* First iteration, set start values */ 9638c2ecf20Sopenharmony_ci lowest = gstart; 9648c2ecf20Sopenharmony_ci highest = gend; 9658c2ecf20Sopenharmony_ci } else { 9668c2ecf20Sopenharmony_ci if (gstart < lowest) 9678c2ecf20Sopenharmony_ci lowest = gstart; 9688c2ecf20Sopenharmony_ci if (gend > highest) 9698c2ecf20Sopenharmony_ci highest = gend; 9708c2ecf20Sopenharmony_ci } 9718c2ecf20Sopenharmony_ci } 9728c2ecf20Sopenharmony_ci /* this gives the absolute number of pins */ 9738c2ecf20Sopenharmony_ci npins = highest - lowest + 1; 9748c2ecf20Sopenharmony_ci return npins; 9758c2ecf20Sopenharmony_ci} 9768c2ecf20Sopenharmony_ci 9778c2ecf20Sopenharmony_cistatic const struct of_device_id abx500_gpio_match[] = { 9788c2ecf20Sopenharmony_ci { .compatible = "stericsson,ab8500-gpio", .data = (void *)PINCTRL_AB8500, }, 9798c2ecf20Sopenharmony_ci { .compatible = "stericsson,ab8505-gpio", .data = (void *)PINCTRL_AB8505, }, 9808c2ecf20Sopenharmony_ci { } 9818c2ecf20Sopenharmony_ci}; 9828c2ecf20Sopenharmony_ci 9838c2ecf20Sopenharmony_cistatic int abx500_gpio_probe(struct platform_device *pdev) 9848c2ecf20Sopenharmony_ci{ 9858c2ecf20Sopenharmony_ci struct device_node *np = pdev->dev.of_node; 9868c2ecf20Sopenharmony_ci const struct of_device_id *match; 9878c2ecf20Sopenharmony_ci struct abx500_pinctrl *pct; 9888c2ecf20Sopenharmony_ci unsigned int id = -1; 9898c2ecf20Sopenharmony_ci int ret; 9908c2ecf20Sopenharmony_ci int i; 9918c2ecf20Sopenharmony_ci 9928c2ecf20Sopenharmony_ci if (!np) { 9938c2ecf20Sopenharmony_ci dev_err(&pdev->dev, "gpio dt node missing\n"); 9948c2ecf20Sopenharmony_ci return -ENODEV; 9958c2ecf20Sopenharmony_ci } 9968c2ecf20Sopenharmony_ci 9978c2ecf20Sopenharmony_ci pct = devm_kzalloc(&pdev->dev, sizeof(*pct), GFP_KERNEL); 9988c2ecf20Sopenharmony_ci if (!pct) 9998c2ecf20Sopenharmony_ci return -ENOMEM; 10008c2ecf20Sopenharmony_ci 10018c2ecf20Sopenharmony_ci pct->dev = &pdev->dev; 10028c2ecf20Sopenharmony_ci pct->parent = dev_get_drvdata(pdev->dev.parent); 10038c2ecf20Sopenharmony_ci pct->chip = abx500gpio_chip; 10048c2ecf20Sopenharmony_ci pct->chip.parent = &pdev->dev; 10058c2ecf20Sopenharmony_ci pct->chip.base = -1; /* Dynamic allocation */ 10068c2ecf20Sopenharmony_ci 10078c2ecf20Sopenharmony_ci match = of_match_device(abx500_gpio_match, &pdev->dev); 10088c2ecf20Sopenharmony_ci if (!match) { 10098c2ecf20Sopenharmony_ci dev_err(&pdev->dev, "gpio dt not matching\n"); 10108c2ecf20Sopenharmony_ci return -ENODEV; 10118c2ecf20Sopenharmony_ci } 10128c2ecf20Sopenharmony_ci id = (unsigned long)match->data; 10138c2ecf20Sopenharmony_ci 10148c2ecf20Sopenharmony_ci /* Poke in other ASIC variants here */ 10158c2ecf20Sopenharmony_ci switch (id) { 10168c2ecf20Sopenharmony_ci case PINCTRL_AB8500: 10178c2ecf20Sopenharmony_ci abx500_pinctrl_ab8500_init(&pct->soc); 10188c2ecf20Sopenharmony_ci break; 10198c2ecf20Sopenharmony_ci case PINCTRL_AB8505: 10208c2ecf20Sopenharmony_ci abx500_pinctrl_ab8505_init(&pct->soc); 10218c2ecf20Sopenharmony_ci break; 10228c2ecf20Sopenharmony_ci default: 10238c2ecf20Sopenharmony_ci dev_err(&pdev->dev, "Unsupported pinctrl sub driver (%d)\n", id); 10248c2ecf20Sopenharmony_ci return -EINVAL; 10258c2ecf20Sopenharmony_ci } 10268c2ecf20Sopenharmony_ci 10278c2ecf20Sopenharmony_ci if (!pct->soc) { 10288c2ecf20Sopenharmony_ci dev_err(&pdev->dev, "Invalid SOC data\n"); 10298c2ecf20Sopenharmony_ci return -EINVAL; 10308c2ecf20Sopenharmony_ci } 10318c2ecf20Sopenharmony_ci 10328c2ecf20Sopenharmony_ci pct->chip.ngpio = abx500_get_gpio_num(pct->soc); 10338c2ecf20Sopenharmony_ci pct->irq_cluster = pct->soc->gpio_irq_cluster; 10348c2ecf20Sopenharmony_ci pct->irq_cluster_size = pct->soc->ngpio_irq_cluster; 10358c2ecf20Sopenharmony_ci 10368c2ecf20Sopenharmony_ci ret = gpiochip_add_data(&pct->chip, pct); 10378c2ecf20Sopenharmony_ci if (ret) { 10388c2ecf20Sopenharmony_ci dev_err(&pdev->dev, "unable to add gpiochip: %d\n", ret); 10398c2ecf20Sopenharmony_ci return ret; 10408c2ecf20Sopenharmony_ci } 10418c2ecf20Sopenharmony_ci dev_info(&pdev->dev, "added gpiochip\n"); 10428c2ecf20Sopenharmony_ci 10438c2ecf20Sopenharmony_ci abx500_pinctrl_desc.pins = pct->soc->pins; 10448c2ecf20Sopenharmony_ci abx500_pinctrl_desc.npins = pct->soc->npins; 10458c2ecf20Sopenharmony_ci pct->pctldev = devm_pinctrl_register(&pdev->dev, &abx500_pinctrl_desc, 10468c2ecf20Sopenharmony_ci pct); 10478c2ecf20Sopenharmony_ci if (IS_ERR(pct->pctldev)) { 10488c2ecf20Sopenharmony_ci dev_err(&pdev->dev, 10498c2ecf20Sopenharmony_ci "could not register abx500 pinctrl driver\n"); 10508c2ecf20Sopenharmony_ci ret = PTR_ERR(pct->pctldev); 10518c2ecf20Sopenharmony_ci goto out_rem_chip; 10528c2ecf20Sopenharmony_ci } 10538c2ecf20Sopenharmony_ci dev_info(&pdev->dev, "registered pin controller\n"); 10548c2ecf20Sopenharmony_ci 10558c2ecf20Sopenharmony_ci /* We will handle a range of GPIO pins */ 10568c2ecf20Sopenharmony_ci for (i = 0; i < pct->soc->gpio_num_ranges; i++) { 10578c2ecf20Sopenharmony_ci const struct abx500_pinrange *p = &pct->soc->gpio_ranges[i]; 10588c2ecf20Sopenharmony_ci 10598c2ecf20Sopenharmony_ci ret = gpiochip_add_pin_range(&pct->chip, 10608c2ecf20Sopenharmony_ci dev_name(&pdev->dev), 10618c2ecf20Sopenharmony_ci p->offset - 1, p->offset, p->npins); 10628c2ecf20Sopenharmony_ci if (ret < 0) 10638c2ecf20Sopenharmony_ci goto out_rem_chip; 10648c2ecf20Sopenharmony_ci } 10658c2ecf20Sopenharmony_ci 10668c2ecf20Sopenharmony_ci platform_set_drvdata(pdev, pct); 10678c2ecf20Sopenharmony_ci dev_info(&pdev->dev, "initialized abx500 pinctrl driver\n"); 10688c2ecf20Sopenharmony_ci 10698c2ecf20Sopenharmony_ci return 0; 10708c2ecf20Sopenharmony_ci 10718c2ecf20Sopenharmony_ciout_rem_chip: 10728c2ecf20Sopenharmony_ci gpiochip_remove(&pct->chip); 10738c2ecf20Sopenharmony_ci return ret; 10748c2ecf20Sopenharmony_ci} 10758c2ecf20Sopenharmony_ci 10768c2ecf20Sopenharmony_ci/** 10778c2ecf20Sopenharmony_ci * abx500_gpio_remove() - remove Ab8500-gpio driver 10788c2ecf20Sopenharmony_ci * @pdev: Platform device registered 10798c2ecf20Sopenharmony_ci */ 10808c2ecf20Sopenharmony_cistatic int abx500_gpio_remove(struct platform_device *pdev) 10818c2ecf20Sopenharmony_ci{ 10828c2ecf20Sopenharmony_ci struct abx500_pinctrl *pct = platform_get_drvdata(pdev); 10838c2ecf20Sopenharmony_ci 10848c2ecf20Sopenharmony_ci gpiochip_remove(&pct->chip); 10858c2ecf20Sopenharmony_ci return 0; 10868c2ecf20Sopenharmony_ci} 10878c2ecf20Sopenharmony_ci 10888c2ecf20Sopenharmony_cistatic struct platform_driver abx500_gpio_driver = { 10898c2ecf20Sopenharmony_ci .driver = { 10908c2ecf20Sopenharmony_ci .name = "abx500-gpio", 10918c2ecf20Sopenharmony_ci .of_match_table = abx500_gpio_match, 10928c2ecf20Sopenharmony_ci }, 10938c2ecf20Sopenharmony_ci .probe = abx500_gpio_probe, 10948c2ecf20Sopenharmony_ci .remove = abx500_gpio_remove, 10958c2ecf20Sopenharmony_ci}; 10968c2ecf20Sopenharmony_ci 10978c2ecf20Sopenharmony_cistatic int __init abx500_gpio_init(void) 10988c2ecf20Sopenharmony_ci{ 10998c2ecf20Sopenharmony_ci return platform_driver_register(&abx500_gpio_driver); 11008c2ecf20Sopenharmony_ci} 11018c2ecf20Sopenharmony_cicore_initcall(abx500_gpio_init); 1102