1 // SPDX-License-Identifier: GPL-2.0+ 2 /* 3 * Freescale i.MX28 GPIO control code 4 * 5 * Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com> 6 * on behalf of DENX Software Engineering GmbH 7 */ 8 9 #include <common.h> 10 #include <linux/errno.h> 11 #include <asm/io.h> 12 #include <asm/arch/iomux.h> 13 #include <asm/arch/imx-regs.h> 14 15 #if defined(CONFIG_MX23) 16 #define PINCTRL_BANKS 3 17 #define PINCTRL_DOUT(n) (0x0500 + ((n) * 0x10)) 18 #define PINCTRL_DIN(n) (0x0600 + ((n) * 0x10)) 19 #define PINCTRL_DOE(n) (0x0700 + ((n) * 0x10)) 20 #define PINCTRL_PIN2IRQ(n) (0x0800 + ((n) * 0x10)) 21 #define PINCTRL_IRQEN(n) (0x0900 + ((n) * 0x10)) 22 #define PINCTRL_IRQSTAT(n) (0x0c00 + ((n) * 0x10)) 23 #elif defined(CONFIG_MX28) 24 #define PINCTRL_BANKS 5 25 #define PINCTRL_DOUT(n) (0x0700 + ((n) * 0x10)) 26 #define PINCTRL_DIN(n) (0x0900 + ((n) * 0x10)) 27 #define PINCTRL_DOE(n) (0x0b00 + ((n) * 0x10)) 28 #define PINCTRL_PIN2IRQ(n) (0x1000 + ((n) * 0x10)) 29 #define PINCTRL_IRQEN(n) (0x1100 + ((n) * 0x10)) 30 #define PINCTRL_IRQSTAT(n) (0x1400 + ((n) * 0x10)) 31 #else 32 #error "Please select CONFIG_MX23 or CONFIG_MX28" 33 #endif 34 35 #define GPIO_INT_FALL_EDGE 0x0 36 #define GPIO_INT_LOW_LEV 0x1 37 #define GPIO_INT_RISE_EDGE 0x2 38 #define GPIO_INT_HIGH_LEV 0x3 39 #define GPIO_INT_LEV_MASK (1 << 0) 40 #define GPIO_INT_POL_MASK (1 << 1) 41 42 void mxs_gpio_init(void) 43 { 44 int i; 45 46 for (i = 0; i < PINCTRL_BANKS; i++) { 47 writel(0, MXS_PINCTRL_BASE + PINCTRL_PIN2IRQ(i)); 48 writel(0, MXS_PINCTRL_BASE + PINCTRL_IRQEN(i)); 49 /* Use SCT address here to clear the IRQSTAT bits */ 50 writel(0xffffffff, MXS_PINCTRL_BASE + PINCTRL_IRQSTAT(i) + 8); 51 } 52 } 53 54 int gpio_get_value(unsigned gpio) 55 { 56 uint32_t bank = PAD_BANK(gpio); 57 uint32_t offset = PINCTRL_DIN(bank); 58 struct mxs_register_32 *reg = 59 (struct mxs_register_32 *)(MXS_PINCTRL_BASE + offset); 60 61 return (readl(®->reg) >> PAD_PIN(gpio)) & 1; 62 } 63 64 void gpio_set_value(unsigned gpio, int value) 65 { 66 uint32_t bank = PAD_BANK(gpio); 67 uint32_t offset = PINCTRL_DOUT(bank); 68 struct mxs_register_32 *reg = 69 (struct mxs_register_32 *)(MXS_PINCTRL_BASE + offset); 70 71 if (value) 72 writel(1 << PAD_PIN(gpio), ®->reg_set); 73 else 74 writel(1 << PAD_PIN(gpio), ®->reg_clr); 75 } 76 77 int gpio_direction_input(unsigned gpio) 78 { 79 uint32_t bank = PAD_BANK(gpio); 80 uint32_t offset = PINCTRL_DOE(bank); 81 struct mxs_register_32 *reg = 82 (struct mxs_register_32 *)(MXS_PINCTRL_BASE + offset); 83 84 writel(1 << PAD_PIN(gpio), ®->reg_clr); 85 86 return 0; 87 } 88 89 int gpio_direction_output(unsigned gpio, int value) 90 { 91 uint32_t bank = PAD_BANK(gpio); 92 uint32_t offset = PINCTRL_DOE(bank); 93 struct mxs_register_32 *reg = 94 (struct mxs_register_32 *)(MXS_PINCTRL_BASE + offset); 95 96 gpio_set_value(gpio, value); 97 98 writel(1 << PAD_PIN(gpio), ®->reg_set); 99 100 return 0; 101 } 102 103 int gpio_request(unsigned gpio, const char *label) 104 { 105 if (PAD_BANK(gpio) >= PINCTRL_BANKS) 106 return -1; 107 108 return 0; 109 } 110 111 int gpio_free(unsigned gpio) 112 { 113 return 0; 114 } 115 116 int name_to_gpio(const char *name) 117 { 118 unsigned bank, pin; 119 char *end; 120 121 bank = simple_strtoul(name, &end, 10); 122 123 if (!*end || *end != ':') 124 return bank; 125 126 pin = simple_strtoul(end + 1, NULL, 10); 127 128 return (bank << MXS_PAD_BANK_SHIFT) | (pin << MXS_PAD_PIN_SHIFT); 129 } 130