1a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman/* 2a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman * Pinctrl GPIO driver for Intel Baytrail 3a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman * Copyright (c) 2012-2013, Intel Corporation. 4a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman * 5a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman * Author: Mathias Nyman <mathias.nyman@linux.intel.com> 6a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman * 7a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman * This program is free software; you can redistribute it and/or modify it 8a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman * under the terms and conditions of the GNU General Public License, 9a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman * version 2, as published by the Free Software Foundation. 10a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman * 11a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman * This program is distributed in the hope it will be useful, but WITHOUT 12a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 14a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman * more details. 15a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman * 16a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman * You should have received a copy of the GNU General Public License along with 17a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman * this program; if not, write to the Free Software Foundation, Inc., 18a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. 19a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman * 20a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman */ 21a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman 22a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman#include <linux/kernel.h> 23a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman#include <linux/module.h> 24a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman#include <linux/init.h> 25a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman#include <linux/types.h> 26a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman#include <linux/bitops.h> 27a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman#include <linux/interrupt.h> 28a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman#include <linux/gpio.h> 29a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman#include <linux/acpi.h> 30a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman#include <linux/platform_device.h> 31a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman#include <linux/seq_file.h> 32a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman#include <linux/io.h> 33a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman#include <linux/pm_runtime.h> 34a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman#include <linux/pinctrl/pinctrl.h> 35a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman 36a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman/* memory mapped register offsets */ 37a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman#define BYT_CONF0_REG 0x000 38a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman#define BYT_CONF1_REG 0x004 39a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman#define BYT_VAL_REG 0x008 40a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman#define BYT_DFT_REG 0x00c 41a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman#define BYT_INT_STAT_REG 0x800 42a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman 43a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman/* BYT_CONF0_REG register bits */ 443ff95885ed7c974ecf308c1d4d27baaa218e32dcMika Westerberg#define BYT_IODEN BIT(31) 45ff998356b644ebe723127bd9eec6040b59a4a4f6Eric Ernst#define BYT_DIRECT_IRQ_EN BIT(27) 46a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman#define BYT_TRIG_NEG BIT(26) 47a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman#define BYT_TRIG_POS BIT(25) 48a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman#define BYT_TRIG_LVL BIT(24) 493ff95885ed7c974ecf308c1d4d27baaa218e32dcMika Westerberg#define BYT_PULL_STR_SHIFT 9 503ff95885ed7c974ecf308c1d4d27baaa218e32dcMika Westerberg#define BYT_PULL_STR_MASK (3 << BYT_PULL_STR_SHIFT) 513ff95885ed7c974ecf308c1d4d27baaa218e32dcMika Westerberg#define BYT_PULL_STR_2K (0 << BYT_PULL_STR_SHIFT) 523ff95885ed7c974ecf308c1d4d27baaa218e32dcMika Westerberg#define BYT_PULL_STR_10K (1 << BYT_PULL_STR_SHIFT) 533ff95885ed7c974ecf308c1d4d27baaa218e32dcMika Westerberg#define BYT_PULL_STR_20K (2 << BYT_PULL_STR_SHIFT) 543ff95885ed7c974ecf308c1d4d27baaa218e32dcMika Westerberg#define BYT_PULL_STR_40K (3 << BYT_PULL_STR_SHIFT) 553ff95885ed7c974ecf308c1d4d27baaa218e32dcMika Westerberg#define BYT_PULL_ASSIGN_SHIFT 7 563ff95885ed7c974ecf308c1d4d27baaa218e32dcMika Westerberg#define BYT_PULL_ASSIGN_MASK (3 << BYT_PULL_ASSIGN_SHIFT) 573ff95885ed7c974ecf308c1d4d27baaa218e32dcMika Westerberg#define BYT_PULL_ASSIGN_UP (1 << BYT_PULL_ASSIGN_SHIFT) 583ff95885ed7c974ecf308c1d4d27baaa218e32dcMika Westerberg#define BYT_PULL_ASSIGN_DOWN (2 << BYT_PULL_ASSIGN_SHIFT) 59a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman#define BYT_PIN_MUX 0x07 60a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman 61a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman/* BYT_VAL_REG register bits */ 62a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman#define BYT_INPUT_EN BIT(2) /* 0: input enabled (active low)*/ 63a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman#define BYT_OUTPUT_EN BIT(1) /* 0: output enabled (active low)*/ 64a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman#define BYT_LEVEL BIT(0) 65a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman 66a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman#define BYT_DIR_MASK (BIT(1) | BIT(2)) 67a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman#define BYT_TRIG_MASK (BIT(26) | BIT(25) | BIT(24)) 68a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman 69a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman#define BYT_NGPIO_SCORE 102 70a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman#define BYT_NGPIO_NCORE 28 71a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman#define BYT_NGPIO_SUS 44 72a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman 7342bd00706ce95d74ad6ebcb8528ee1fbbb992f6aChew, Kean Ho#define BYT_SCORE_ACPI_UID "1" 7442bd00706ce95d74ad6ebcb8528ee1fbbb992f6aChew, Kean Ho#define BYT_NCORE_ACPI_UID "2" 7542bd00706ce95d74ad6ebcb8528ee1fbbb992f6aChew, Kean Ho#define BYT_SUS_ACPI_UID "3" 7642bd00706ce95d74ad6ebcb8528ee1fbbb992f6aChew, Kean Ho 77a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman/* 78a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman * Baytrail gpio controller consist of three separate sub-controllers called 79a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman * SCORE, NCORE and SUS. The sub-controllers are identified by their acpi UID. 80a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman * 81a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman * GPIO numbering is _not_ ordered meaning that gpio # 0 in ACPI namespace does 82a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman * _not_ correspond to the first gpio register at controller's gpio base. 83a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman * There is no logic or pattern in mapping gpio numbers to registers (pads) so 84a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman * each sub-controller needs to have its own mapping table 85a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman */ 86a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman 87a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman/* score_pins[gpio_nr] = pad_nr */ 88a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman 89a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nymanstatic unsigned const score_pins[BYT_NGPIO_SCORE] = { 90a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman 85, 89, 93, 96, 99, 102, 98, 101, 34, 37, 91a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman 36, 38, 39, 35, 40, 84, 62, 61, 64, 59, 92a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman 54, 56, 60, 55, 63, 57, 51, 50, 53, 47, 93a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman 52, 49, 48, 43, 46, 41, 45, 42, 58, 44, 94a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman 95, 105, 70, 68, 67, 66, 69, 71, 65, 72, 95a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman 86, 90, 88, 92, 103, 77, 79, 83, 78, 81, 96a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman 80, 82, 13, 12, 15, 14, 17, 18, 19, 16, 97a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman 2, 1, 0, 4, 6, 7, 9, 8, 33, 32, 98a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman 31, 30, 29, 27, 25, 28, 26, 23, 21, 20, 99a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman 24, 22, 5, 3, 10, 11, 106, 87, 91, 104, 100a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman 97, 100, 101a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman}; 102a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman 103a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nymanstatic unsigned const ncore_pins[BYT_NGPIO_NCORE] = { 104a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman 19, 18, 17, 20, 21, 22, 24, 25, 23, 16, 105a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman 14, 15, 12, 26, 27, 1, 4, 8, 11, 0, 106a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman 3, 6, 10, 13, 2, 5, 9, 7, 107a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman}; 108a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman 109a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nymanstatic unsigned const sus_pins[BYT_NGPIO_SUS] = { 110a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman 29, 33, 30, 31, 32, 34, 36, 35, 38, 37, 111a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman 18, 7, 11, 20, 17, 1, 8, 10, 19, 12, 112a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman 0, 2, 23, 39, 28, 27, 22, 21, 24, 25, 113a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman 26, 51, 56, 54, 49, 55, 48, 57, 50, 58, 114a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman 52, 53, 59, 40, 115a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman}; 116a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman 117a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nymanstatic struct pinctrl_gpio_range byt_ranges[] = { 118a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman { 11942bd00706ce95d74ad6ebcb8528ee1fbbb992f6aChew, Kean Ho .name = BYT_SCORE_ACPI_UID, /* match with acpi _UID in probe */ 120a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman .npins = BYT_NGPIO_SCORE, 121a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman .pins = score_pins, 122a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman }, 123a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman { 12442bd00706ce95d74ad6ebcb8528ee1fbbb992f6aChew, Kean Ho .name = BYT_NCORE_ACPI_UID, 125a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman .npins = BYT_NGPIO_NCORE, 126a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman .pins = ncore_pins, 127a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman }, 128a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman { 12942bd00706ce95d74ad6ebcb8528ee1fbbb992f6aChew, Kean Ho .name = BYT_SUS_ACPI_UID, 130a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman .npins = BYT_NGPIO_SUS, 131a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman .pins = sus_pins, 132a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman }, 133a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman { 134a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman }, 135a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman}; 136a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman 137a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nymanstruct byt_gpio { 138a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman struct gpio_chip chip; 139a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman struct platform_device *pdev; 140a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman spinlock_t lock; 141a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman void __iomem *reg_base; 142a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman struct pinctrl_gpio_range *range; 143a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman}; 144a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman 14517e52464292320d0de260b146605d93326a9014cAndy Shevchenko#define to_byt_gpio(c) container_of(c, struct byt_gpio, chip) 14617e52464292320d0de260b146605d93326a9014cAndy Shevchenko 147a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nymanstatic void __iomem *byt_gpio_reg(struct gpio_chip *chip, unsigned offset, 148a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman int reg) 149a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman{ 15017e52464292320d0de260b146605d93326a9014cAndy Shevchenko struct byt_gpio *vg = to_byt_gpio(chip); 151a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman u32 reg_offset; 152a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman 153a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman if (reg == BYT_INT_STAT_REG) 154a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman reg_offset = (offset / 32) * 4; 155a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman else 156a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman reg_offset = vg->range->pins[offset] * 16; 157a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman 1589c5b65579597609844ae248a6e76f614f02e3c42Andy Shevchenko return vg->reg_base + reg_offset + reg; 159a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman} 160a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman 16142bd00706ce95d74ad6ebcb8528ee1fbbb992f6aChew, Kean Hostatic bool is_special_pin(struct byt_gpio *vg, unsigned offset) 16242bd00706ce95d74ad6ebcb8528ee1fbbb992f6aChew, Kean Ho{ 16342bd00706ce95d74ad6ebcb8528ee1fbbb992f6aChew, Kean Ho /* SCORE pin 92-93 */ 16442bd00706ce95d74ad6ebcb8528ee1fbbb992f6aChew, Kean Ho if (!strcmp(vg->range->name, BYT_SCORE_ACPI_UID) && 16542bd00706ce95d74ad6ebcb8528ee1fbbb992f6aChew, Kean Ho offset >= 92 && offset <= 93) 16642bd00706ce95d74ad6ebcb8528ee1fbbb992f6aChew, Kean Ho return true; 16742bd00706ce95d74ad6ebcb8528ee1fbbb992f6aChew, Kean Ho 16842bd00706ce95d74ad6ebcb8528ee1fbbb992f6aChew, Kean Ho /* SUS pin 11-21 */ 16942bd00706ce95d74ad6ebcb8528ee1fbbb992f6aChew, Kean Ho if (!strcmp(vg->range->name, BYT_SUS_ACPI_UID) && 17042bd00706ce95d74ad6ebcb8528ee1fbbb992f6aChew, Kean Ho offset >= 11 && offset <= 21) 17142bd00706ce95d74ad6ebcb8528ee1fbbb992f6aChew, Kean Ho return true; 17242bd00706ce95d74ad6ebcb8528ee1fbbb992f6aChew, Kean Ho 17342bd00706ce95d74ad6ebcb8528ee1fbbb992f6aChew, Kean Ho return false; 17442bd00706ce95d74ad6ebcb8528ee1fbbb992f6aChew, Kean Ho} 17542bd00706ce95d74ad6ebcb8528ee1fbbb992f6aChew, Kean Ho 176a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nymanstatic int byt_gpio_request(struct gpio_chip *chip, unsigned offset) 177a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman{ 17817e52464292320d0de260b146605d93326a9014cAndy Shevchenko struct byt_gpio *vg = to_byt_gpio(chip); 17942bd00706ce95d74ad6ebcb8528ee1fbbb992f6aChew, Kean Ho void __iomem *reg = byt_gpio_reg(chip, offset, BYT_CONF0_REG); 18042bd00706ce95d74ad6ebcb8528ee1fbbb992f6aChew, Kean Ho u32 value; 18142bd00706ce95d74ad6ebcb8528ee1fbbb992f6aChew, Kean Ho bool special; 18242bd00706ce95d74ad6ebcb8528ee1fbbb992f6aChew, Kean Ho 18342bd00706ce95d74ad6ebcb8528ee1fbbb992f6aChew, Kean Ho /* 18442bd00706ce95d74ad6ebcb8528ee1fbbb992f6aChew, Kean Ho * In most cases, func pin mux 000 means GPIO function. 18542bd00706ce95d74ad6ebcb8528ee1fbbb992f6aChew, Kean Ho * But, some pins may have func pin mux 001 represents 18642bd00706ce95d74ad6ebcb8528ee1fbbb992f6aChew, Kean Ho * GPIO function. Only allow user to export pin with 18742bd00706ce95d74ad6ebcb8528ee1fbbb992f6aChew, Kean Ho * func pin mux preset as GPIO function by BIOS/FW. 18842bd00706ce95d74ad6ebcb8528ee1fbbb992f6aChew, Kean Ho */ 18942bd00706ce95d74ad6ebcb8528ee1fbbb992f6aChew, Kean Ho value = readl(reg) & BYT_PIN_MUX; 19042bd00706ce95d74ad6ebcb8528ee1fbbb992f6aChew, Kean Ho special = is_special_pin(vg, offset); 19142bd00706ce95d74ad6ebcb8528ee1fbbb992f6aChew, Kean Ho if ((special && value != 1) || (!special && value)) { 19242bd00706ce95d74ad6ebcb8528ee1fbbb992f6aChew, Kean Ho dev_err(&vg->pdev->dev, 19342bd00706ce95d74ad6ebcb8528ee1fbbb992f6aChew, Kean Ho "pin %u cannot be used as GPIO.\n", offset); 19442bd00706ce95d74ad6ebcb8528ee1fbbb992f6aChew, Kean Ho return -EINVAL; 19542bd00706ce95d74ad6ebcb8528ee1fbbb992f6aChew, Kean Ho } 196a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman 197a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman pm_runtime_get(&vg->pdev->dev); 198a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman 199a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman return 0; 200a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman} 201a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman 202a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nymanstatic void byt_gpio_free(struct gpio_chip *chip, unsigned offset) 203a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman{ 20417e52464292320d0de260b146605d93326a9014cAndy Shevchenko struct byt_gpio *vg = to_byt_gpio(chip); 205a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman void __iomem *reg = byt_gpio_reg(&vg->chip, offset, BYT_CONF0_REG); 206a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman u32 value; 207a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman 208a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman /* clear interrupt triggering */ 209a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman value = readl(reg); 210a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman value &= ~(BYT_TRIG_POS | BYT_TRIG_NEG | BYT_TRIG_LVL); 211a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman writel(value, reg); 212a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman 213a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman pm_runtime_put(&vg->pdev->dev); 214a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman} 215a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman 216a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nymanstatic int byt_irq_type(struct irq_data *d, unsigned type) 217a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman{ 218e1ee5c578fb1fa24b7ccaf1a11237a2bd70b6f9aMika Westerberg struct byt_gpio *vg = to_byt_gpio(irq_data_get_irq_chip_data(d)); 219a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman u32 offset = irqd_to_hwirq(d); 220a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman u32 value; 221a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman unsigned long flags; 222a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman void __iomem *reg = byt_gpio_reg(&vg->chip, offset, BYT_CONF0_REG); 223a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman 224a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman if (offset >= vg->chip.ngpio) 225a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman return -EINVAL; 226a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman 227a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman spin_lock_irqsave(&vg->lock, flags); 228a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman value = readl(reg); 229a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman 2303a71c05e66e597a1349fdbd5f0bb119d8d9cb850Loic Poulain WARN(value & BYT_DIRECT_IRQ_EN, 2313a71c05e66e597a1349fdbd5f0bb119d8d9cb850Loic Poulain "Bad pad config for io mode, force direct_irq_en bit clearing"); 2323a71c05e66e597a1349fdbd5f0bb119d8d9cb850Loic Poulain 233a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman /* For level trigges the BYT_TRIG_POS and BYT_TRIG_NEG bits 234a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman * are used to indicate high and low level triggering 235a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman */ 2363a71c05e66e597a1349fdbd5f0bb119d8d9cb850Loic Poulain value &= ~(BYT_DIRECT_IRQ_EN | BYT_TRIG_POS | BYT_TRIG_NEG | 2373a71c05e66e597a1349fdbd5f0bb119d8d9cb850Loic Poulain BYT_TRIG_LVL); 238a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman 239a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman switch (type) { 240a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman case IRQ_TYPE_LEVEL_HIGH: 241a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman value |= BYT_TRIG_LVL; 242a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman case IRQ_TYPE_EDGE_RISING: 243a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman value |= BYT_TRIG_POS; 244a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman break; 245a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman case IRQ_TYPE_LEVEL_LOW: 246a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman value |= BYT_TRIG_LVL; 247a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman case IRQ_TYPE_EDGE_FALLING: 248a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman value |= BYT_TRIG_NEG; 249a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman break; 250a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman case IRQ_TYPE_EDGE_BOTH: 251a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman value |= (BYT_TRIG_NEG | BYT_TRIG_POS); 252a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman break; 253a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman } 254a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman writel(value, reg); 255a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman 256a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman spin_unlock_irqrestore(&vg->lock, flags); 257a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman 258a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman return 0; 259a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman} 260a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman 261a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nymanstatic int byt_gpio_get(struct gpio_chip *chip, unsigned offset) 262a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman{ 263a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman void __iomem *reg = byt_gpio_reg(chip, offset, BYT_VAL_REG); 264a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman return readl(reg) & BYT_LEVEL; 265a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman} 266a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman 267a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nymanstatic void byt_gpio_set(struct gpio_chip *chip, unsigned offset, int value) 268a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman{ 26917e52464292320d0de260b146605d93326a9014cAndy Shevchenko struct byt_gpio *vg = to_byt_gpio(chip); 270a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman void __iomem *reg = byt_gpio_reg(chip, offset, BYT_VAL_REG); 271a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman unsigned long flags; 272a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman u32 old_val; 273a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman 274a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman spin_lock_irqsave(&vg->lock, flags); 275a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman 276a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman old_val = readl(reg); 277a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman 278a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman if (value) 279a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman writel(old_val | BYT_LEVEL, reg); 280a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman else 281a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman writel(old_val & ~BYT_LEVEL, reg); 282a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman 283a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman spin_unlock_irqrestore(&vg->lock, flags); 284a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman} 285a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman 286a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nymanstatic int byt_gpio_direction_input(struct gpio_chip *chip, unsigned offset) 287a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman{ 28817e52464292320d0de260b146605d93326a9014cAndy Shevchenko struct byt_gpio *vg = to_byt_gpio(chip); 289a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman void __iomem *reg = byt_gpio_reg(chip, offset, BYT_VAL_REG); 290a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman unsigned long flags; 291a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman u32 value; 292a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman 293a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman spin_lock_irqsave(&vg->lock, flags); 294a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman 295a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman value = readl(reg) | BYT_DIR_MASK; 296496940c10278599528cfbde0e05208bf4ef0c7c0Andy Shevchenko value &= ~BYT_INPUT_EN; /* active low */ 297a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman writel(value, reg); 298a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman 299a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman spin_unlock_irqrestore(&vg->lock, flags); 300a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman 301a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman return 0; 302a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman} 303a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman 304a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nymanstatic int byt_gpio_direction_output(struct gpio_chip *chip, 305a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman unsigned gpio, int value) 306a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman{ 30717e52464292320d0de260b146605d93326a9014cAndy Shevchenko struct byt_gpio *vg = to_byt_gpio(chip); 308ff998356b644ebe723127bd9eec6040b59a4a4f6Eric Ernst void __iomem *conf_reg = byt_gpio_reg(chip, gpio, BYT_CONF0_REG); 309a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman void __iomem *reg = byt_gpio_reg(chip, gpio, BYT_VAL_REG); 310a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman unsigned long flags; 311a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman u32 reg_val; 312a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman 313a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman spin_lock_irqsave(&vg->lock, flags); 314a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman 315ff998356b644ebe723127bd9eec6040b59a4a4f6Eric Ernst /* 316ff998356b644ebe723127bd9eec6040b59a4a4f6Eric Ernst * Before making any direction modifications, do a check if gpio 317ff998356b644ebe723127bd9eec6040b59a4a4f6Eric Ernst * is set for direct IRQ. On baytrail, setting GPIO to output does 318ff998356b644ebe723127bd9eec6040b59a4a4f6Eric Ernst * not make sense, so let's at least warn the caller before they shoot 319ff998356b644ebe723127bd9eec6040b59a4a4f6Eric Ernst * themselves in the foot. 320ff998356b644ebe723127bd9eec6040b59a4a4f6Eric Ernst */ 321ff998356b644ebe723127bd9eec6040b59a4a4f6Eric Ernst WARN(readl(conf_reg) & BYT_DIRECT_IRQ_EN, 322ff998356b644ebe723127bd9eec6040b59a4a4f6Eric Ernst "Potential Error: Setting GPIO with direct_irq_en to output"); 323ff998356b644ebe723127bd9eec6040b59a4a4f6Eric Ernst 324496940c10278599528cfbde0e05208bf4ef0c7c0Andy Shevchenko reg_val = readl(reg) | BYT_DIR_MASK; 325d90c33818967c5e5371961604ad98b4dea4fa3f4David Cohen reg_val &= ~(BYT_OUTPUT_EN | BYT_INPUT_EN); 326496940c10278599528cfbde0e05208bf4ef0c7c0Andy Shevchenko 327496940c10278599528cfbde0e05208bf4ef0c7c0Andy Shevchenko if (value) 328496940c10278599528cfbde0e05208bf4ef0c7c0Andy Shevchenko writel(reg_val | BYT_LEVEL, reg); 329496940c10278599528cfbde0e05208bf4ef0c7c0Andy Shevchenko else 330496940c10278599528cfbde0e05208bf4ef0c7c0Andy Shevchenko writel(reg_val & ~BYT_LEVEL, reg); 331a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman 332a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman spin_unlock_irqrestore(&vg->lock, flags); 333a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman 334a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman return 0; 335a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman} 336a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman 337a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nymanstatic void byt_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip) 338a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman{ 33917e52464292320d0de260b146605d93326a9014cAndy Shevchenko struct byt_gpio *vg = to_byt_gpio(chip); 340a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman int i; 341a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman unsigned long flags; 342a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman u32 conf0, val, offs; 343a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman 344a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman spin_lock_irqsave(&vg->lock, flags); 345a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman 346a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman for (i = 0; i < vg->chip.ngpio; i++) { 3473ff95885ed7c974ecf308c1d4d27baaa218e32dcMika Westerberg const char *pull_str = NULL; 3483ff95885ed7c974ecf308c1d4d27baaa218e32dcMika Westerberg const char *pull = NULL; 349a4d8d6da4820230a2e0e977fda44ced9345c41d4Mathias Nyman const char *label; 350a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman offs = vg->range->pins[i] * 16; 351a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman conf0 = readl(vg->reg_base + offs + BYT_CONF0_REG); 352a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman val = readl(vg->reg_base + offs + BYT_VAL_REG); 353a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman 354a4d8d6da4820230a2e0e977fda44ced9345c41d4Mathias Nyman label = gpiochip_is_requested(chip, i); 355a4d8d6da4820230a2e0e977fda44ced9345c41d4Mathias Nyman if (!label) 356a4d8d6da4820230a2e0e977fda44ced9345c41d4Mathias Nyman label = "Unrequested"; 357a4d8d6da4820230a2e0e977fda44ced9345c41d4Mathias Nyman 3583ff95885ed7c974ecf308c1d4d27baaa218e32dcMika Westerberg switch (conf0 & BYT_PULL_ASSIGN_MASK) { 3593ff95885ed7c974ecf308c1d4d27baaa218e32dcMika Westerberg case BYT_PULL_ASSIGN_UP: 3603ff95885ed7c974ecf308c1d4d27baaa218e32dcMika Westerberg pull = "up"; 3613ff95885ed7c974ecf308c1d4d27baaa218e32dcMika Westerberg break; 3623ff95885ed7c974ecf308c1d4d27baaa218e32dcMika Westerberg case BYT_PULL_ASSIGN_DOWN: 3633ff95885ed7c974ecf308c1d4d27baaa218e32dcMika Westerberg pull = "down"; 3643ff95885ed7c974ecf308c1d4d27baaa218e32dcMika Westerberg break; 3653ff95885ed7c974ecf308c1d4d27baaa218e32dcMika Westerberg } 3663ff95885ed7c974ecf308c1d4d27baaa218e32dcMika Westerberg 3673ff95885ed7c974ecf308c1d4d27baaa218e32dcMika Westerberg switch (conf0 & BYT_PULL_STR_MASK) { 3683ff95885ed7c974ecf308c1d4d27baaa218e32dcMika Westerberg case BYT_PULL_STR_2K: 3693ff95885ed7c974ecf308c1d4d27baaa218e32dcMika Westerberg pull_str = "2k"; 3703ff95885ed7c974ecf308c1d4d27baaa218e32dcMika Westerberg break; 3713ff95885ed7c974ecf308c1d4d27baaa218e32dcMika Westerberg case BYT_PULL_STR_10K: 3723ff95885ed7c974ecf308c1d4d27baaa218e32dcMika Westerberg pull_str = "10k"; 3733ff95885ed7c974ecf308c1d4d27baaa218e32dcMika Westerberg break; 3743ff95885ed7c974ecf308c1d4d27baaa218e32dcMika Westerberg case BYT_PULL_STR_20K: 3753ff95885ed7c974ecf308c1d4d27baaa218e32dcMika Westerberg pull_str = "20k"; 3763ff95885ed7c974ecf308c1d4d27baaa218e32dcMika Westerberg break; 3773ff95885ed7c974ecf308c1d4d27baaa218e32dcMika Westerberg case BYT_PULL_STR_40K: 3783ff95885ed7c974ecf308c1d4d27baaa218e32dcMika Westerberg pull_str = "40k"; 3793ff95885ed7c974ecf308c1d4d27baaa218e32dcMika Westerberg break; 3803ff95885ed7c974ecf308c1d4d27baaa218e32dcMika Westerberg } 3813ff95885ed7c974ecf308c1d4d27baaa218e32dcMika Westerberg 382a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman seq_printf(s, 3833ff95885ed7c974ecf308c1d4d27baaa218e32dcMika Westerberg " gpio-%-3d (%-20.20s) %s %s %s pad-%-3d offset:0x%03x mux:%d %s%s%s", 384a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman i, 385a4d8d6da4820230a2e0e977fda44ced9345c41d4Mathias Nyman label, 386a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman val & BYT_INPUT_EN ? " " : "in", 387a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman val & BYT_OUTPUT_EN ? " " : "out", 388a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman val & BYT_LEVEL ? "hi" : "lo", 389a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman vg->range->pins[i], offs, 390a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman conf0 & 0x7, 3913ff95885ed7c974ecf308c1d4d27baaa218e32dcMika Westerberg conf0 & BYT_TRIG_NEG ? " fall" : " ", 3923ff95885ed7c974ecf308c1d4d27baaa218e32dcMika Westerberg conf0 & BYT_TRIG_POS ? " rise" : " ", 3933ff95885ed7c974ecf308c1d4d27baaa218e32dcMika Westerberg conf0 & BYT_TRIG_LVL ? " level" : " "); 3943ff95885ed7c974ecf308c1d4d27baaa218e32dcMika Westerberg 3953ff95885ed7c974ecf308c1d4d27baaa218e32dcMika Westerberg if (pull && pull_str) 3963ff95885ed7c974ecf308c1d4d27baaa218e32dcMika Westerberg seq_printf(s, " %-4s %-3s", pull, pull_str); 3973ff95885ed7c974ecf308c1d4d27baaa218e32dcMika Westerberg else 3983ff95885ed7c974ecf308c1d4d27baaa218e32dcMika Westerberg seq_puts(s, " "); 3993ff95885ed7c974ecf308c1d4d27baaa218e32dcMika Westerberg 4003ff95885ed7c974ecf308c1d4d27baaa218e32dcMika Westerberg if (conf0 & BYT_IODEN) 4013ff95885ed7c974ecf308c1d4d27baaa218e32dcMika Westerberg seq_puts(s, " open-drain"); 4023ff95885ed7c974ecf308c1d4d27baaa218e32dcMika Westerberg 4033ff95885ed7c974ecf308c1d4d27baaa218e32dcMika Westerberg seq_puts(s, "\n"); 404a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman } 405a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman spin_unlock_irqrestore(&vg->lock, flags); 406a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman} 407a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman 408a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nymanstatic void byt_gpio_irq_handler(unsigned irq, struct irq_desc *desc) 409a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman{ 410a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman struct irq_data *data = irq_desc_get_irq_data(desc); 411e1ee5c578fb1fa24b7ccaf1a11237a2bd70b6f9aMika Westerberg struct byt_gpio *vg = to_byt_gpio(irq_desc_get_handler_data(desc)); 412a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman struct irq_chip *chip = irq_data_get_irq_chip(data); 413a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman u32 base, pin, mask; 414a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman void __iomem *reg; 415a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman u32 pending; 416a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman unsigned virq; 417a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman int looplimit = 0; 418a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman 419a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman /* check from GPIO controller which pin triggered the interrupt */ 420a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman for (base = 0; base < vg->chip.ngpio; base += 32) { 421a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman 422a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman reg = byt_gpio_reg(&vg->chip, base, BYT_INT_STAT_REG); 423a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman 424a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman while ((pending = readl(reg))) { 425a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman pin = __ffs(pending); 426a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman mask = BIT(pin); 427a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman /* Clear before handling so we can't lose an edge */ 428a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman writel(mask, reg); 429a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman 430e1ee5c578fb1fa24b7ccaf1a11237a2bd70b6f9aMika Westerberg virq = irq_find_mapping(vg->chip.irqdomain, base + pin); 431a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman generic_handle_irq(virq); 432a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman 433a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman /* In case bios or user sets triggering incorretly a pin 434a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman * might remain in "interrupt triggered" state. 435a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman */ 436a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman if (looplimit++ > 32) { 437a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman dev_err(&vg->pdev->dev, 438a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman "Gpio %d interrupt flood, disabling\n", 439a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman base + pin); 440a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman 441a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman reg = byt_gpio_reg(&vg->chip, base + pin, 442a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman BYT_CONF0_REG); 443a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman mask = readl(reg); 444a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman mask &= ~(BYT_TRIG_NEG | BYT_TRIG_POS | 445a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman BYT_TRIG_LVL); 446a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman writel(mask, reg); 447a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman mask = readl(reg); /* flush */ 448a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman break; 449a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman } 450a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman } 451a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman } 452a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman chip->irq_eoi(data); 453a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman} 454a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman 455a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nymanstatic void byt_irq_unmask(struct irq_data *d) 456a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman{ 457a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman} 458a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman 459a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nymanstatic void byt_irq_mask(struct irq_data *d) 460a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman{ 461a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman} 462a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman 463a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nymanstatic struct irq_chip byt_irqchip = { 464a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman .name = "BYT-GPIO", 465a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman .irq_mask = byt_irq_mask, 466a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman .irq_unmask = byt_irq_unmask, 467a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman .irq_set_type = byt_irq_type, 46841939e699c507a3441625862d125eb348f5319e0Mathias Nyman .flags = IRQCHIP_SKIP_SET_WAKE, 469a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman}; 470a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman 471a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nymanstatic void byt_gpio_irq_init_hw(struct byt_gpio *vg) 472a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman{ 473a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman void __iomem *reg; 474a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman u32 base, value; 475a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman 476a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman /* clear interrupt status trigger registers */ 477a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman for (base = 0; base < vg->chip.ngpio; base += 32) { 478a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman reg = byt_gpio_reg(&vg->chip, base, BYT_INT_STAT_REG); 479a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman writel(0xffffffff, reg); 480a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman /* make sure trigger bits are cleared, if not then a pin 481a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman might be misconfigured in bios */ 482a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman value = readl(reg); 483a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman if (value) 484a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman dev_err(&vg->pdev->dev, 485a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman "GPIO interrupt error, pins misconfigured\n"); 486a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman } 487a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman} 488a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman 489a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nymanstatic int byt_gpio_probe(struct platform_device *pdev) 490a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman{ 491a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman struct byt_gpio *vg; 492a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman struct gpio_chip *gc; 493a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman struct resource *mem_rc, *irq_rc; 494a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman struct device *dev = &pdev->dev; 495a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman struct acpi_device *acpi_dev; 496a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman struct pinctrl_gpio_range *range; 497a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman acpi_handle handle = ACPI_HANDLE(dev); 498a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman int ret; 499a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman 500a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman if (acpi_bus_get_device(handle, &acpi_dev)) 501a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman return -ENODEV; 502a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman 503a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman vg = devm_kzalloc(dev, sizeof(struct byt_gpio), GFP_KERNEL); 504a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman if (!vg) { 505a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman dev_err(&pdev->dev, "can't allocate byt_gpio chip data\n"); 506a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman return -ENOMEM; 507a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman } 508a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman 509a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman for (range = byt_ranges; range->name; range++) { 510a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman if (!strcmp(acpi_dev->pnp.unique_id, range->name)) { 511a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman vg->chip.ngpio = range->npins; 512a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman vg->range = range; 513a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman break; 514a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman } 515a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman } 516a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman 517a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman if (!vg->chip.ngpio || !vg->range) 518a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman return -ENODEV; 519a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman 520a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman vg->pdev = pdev; 521a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman platform_set_drvdata(pdev, vg); 522a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman 523a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman mem_rc = platform_get_resource(pdev, IORESOURCE_MEM, 0); 524a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman vg->reg_base = devm_ioremap_resource(dev, mem_rc); 525a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman if (IS_ERR(vg->reg_base)) 526a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman return PTR_ERR(vg->reg_base); 527a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman 528a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman spin_lock_init(&vg->lock); 529a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman 530a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman gc = &vg->chip; 531a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman gc->label = dev_name(&pdev->dev); 532a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman gc->owner = THIS_MODULE; 533a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman gc->request = byt_gpio_request; 534a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman gc->free = byt_gpio_free; 535a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman gc->direction_input = byt_gpio_direction_input; 536a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman gc->direction_output = byt_gpio_direction_output; 537a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman gc->get = byt_gpio_get; 538a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman gc->set = byt_gpio_set; 539a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman gc->dbg_show = byt_gpio_dbg_show; 540a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman gc->base = -1; 5419fb1f39eb2d6707d265087ee186376e24995f55aLinus Walleij gc->can_sleep = false; 542a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman gc->dev = dev; 543a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman 544e1ee5c578fb1fa24b7ccaf1a11237a2bd70b6f9aMika Westerberg ret = gpiochip_add(gc); 545e1ee5c578fb1fa24b7ccaf1a11237a2bd70b6f9aMika Westerberg if (ret) { 546e1ee5c578fb1fa24b7ccaf1a11237a2bd70b6f9aMika Westerberg dev_err(&pdev->dev, "failed adding byt-gpio chip\n"); 547e1ee5c578fb1fa24b7ccaf1a11237a2bd70b6f9aMika Westerberg return ret; 548e1ee5c578fb1fa24b7ccaf1a11237a2bd70b6f9aMika Westerberg } 549e1ee5c578fb1fa24b7ccaf1a11237a2bd70b6f9aMika Westerberg 550a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman /* set up interrupts */ 551a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman irq_rc = platform_get_resource(pdev, IORESOURCE_IRQ, 0); 552a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman if (irq_rc && irq_rc->start) { 553a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman byt_gpio_irq_init_hw(vg); 554e1ee5c578fb1fa24b7ccaf1a11237a2bd70b6f9aMika Westerberg ret = gpiochip_irqchip_add(gc, &byt_irqchip, 0, 555e1ee5c578fb1fa24b7ccaf1a11237a2bd70b6f9aMika Westerberg handle_simple_irq, IRQ_TYPE_NONE); 556e1ee5c578fb1fa24b7ccaf1a11237a2bd70b6f9aMika Westerberg if (ret) { 557e1ee5c578fb1fa24b7ccaf1a11237a2bd70b6f9aMika Westerberg dev_err(dev, "failed to add irqchip\n"); 558e1ee5c578fb1fa24b7ccaf1a11237a2bd70b6f9aMika Westerberg gpiochip_remove(gc); 559e1ee5c578fb1fa24b7ccaf1a11237a2bd70b6f9aMika Westerberg return ret; 560e1ee5c578fb1fa24b7ccaf1a11237a2bd70b6f9aMika Westerberg } 561a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman 562e1ee5c578fb1fa24b7ccaf1a11237a2bd70b6f9aMika Westerberg gpiochip_set_chained_irqchip(gc, &byt_irqchip, 563e1ee5c578fb1fa24b7ccaf1a11237a2bd70b6f9aMika Westerberg (unsigned)irq_rc->start, 564e1ee5c578fb1fa24b7ccaf1a11237a2bd70b6f9aMika Westerberg byt_gpio_irq_handler); 565605a7bca7cf39cbfa835022e9c29b6a4bb980281Jin Yao } 566605a7bca7cf39cbfa835022e9c29b6a4bb980281Jin Yao 567a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman pm_runtime_enable(dev); 568a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman 569a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman return 0; 570a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman} 571a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman 572a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nymanstatic int byt_gpio_runtime_suspend(struct device *dev) 573a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman{ 574a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman return 0; 575a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman} 576a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman 577a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nymanstatic int byt_gpio_runtime_resume(struct device *dev) 578a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman{ 579a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman return 0; 580a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman} 581a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman 582a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nymanstatic const struct dev_pm_ops byt_gpio_pm_ops = { 583a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman .runtime_suspend = byt_gpio_runtime_suspend, 584a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman .runtime_resume = byt_gpio_runtime_resume, 585a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman}; 586a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman 587a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nymanstatic const struct acpi_device_id byt_gpio_acpi_match[] = { 588a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman { "INT33B2", 0 }, 58920482d3279226d2d2802647ffa3ce82e511b74d7Jin Yao { "INT33FC", 0 }, 590a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman { } 591a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman}; 592a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias NymanMODULE_DEVICE_TABLE(acpi, byt_gpio_acpi_match); 593a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman 594a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nymanstatic int byt_gpio_remove(struct platform_device *pdev) 595a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman{ 596a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman struct byt_gpio *vg = platform_get_drvdata(pdev); 597ec243320e02ca9e3cb64c0ba774e25db73b32fdbAndy Shevchenko 598a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman pm_runtime_disable(&pdev->dev); 599b4e7c55dabf611cf5cccd1554fec06f72e1c9fafabdoulaye berthe gpiochip_remove(&vg->chip); 600a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman 601a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman return 0; 602a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman} 603a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman 604a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nymanstatic struct platform_driver byt_gpio_driver = { 605a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman .probe = byt_gpio_probe, 606a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman .remove = byt_gpio_remove, 607a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman .driver = { 608a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman .name = "byt_gpio", 609a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman .owner = THIS_MODULE, 610a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman .pm = &byt_gpio_pm_ops, 611a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman .acpi_match_table = ACPI_PTR(byt_gpio_acpi_match), 612a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman }, 613a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman}; 614a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman 615a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nymanstatic int __init byt_gpio_init(void) 616a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman{ 617a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman return platform_driver_register(&byt_gpio_driver); 618a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman} 619a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nyman 620a5d811bbf1c6df86cfe23948059ea614554b9f19Mathias Nymansubsys_initcall(byt_gpio_init); 621