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