Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v5.3-rc8 284 lines 6.5 kB view raw
1// SPDX-License-Identifier: GPL-2.0-only 2/* 3 * arch/arm/mach-ks8695/gpio.c 4 * 5 * Copyright (C) 2006 Andrew Victor 6 * Updated to GPIOLIB, Copyright 2008 Simtec Electronics 7 * Daniel Silverstone <dsilvers@simtec.co.uk> 8 */ 9#include <linux/gpio/driver.h> 10#include <linux/kernel.h> 11#include <linux/mm.h> 12#include <linux/init.h> 13#include <linux/debugfs.h> 14#include <linux/seq_file.h> 15#include <linux/module.h> 16#include <linux/io.h> 17 18#include <mach/hardware.h> 19#include <asm/mach/irq.h> 20 21#include <mach/regs-gpio.h> 22#include <mach/gpio-ks8695.h> 23 24/* 25 * Configure a GPIO line for either GPIO function, or its internal 26 * function (Interrupt, Timer, etc). 27 */ 28static void ks8695_gpio_mode(unsigned int pin, short gpio) 29{ 30 unsigned int enable[] = { IOPC_IOEINT0EN, IOPC_IOEINT1EN, IOPC_IOEINT2EN, IOPC_IOEINT3EN, IOPC_IOTIM0EN, IOPC_IOTIM1EN }; 31 unsigned long x, flags; 32 33 if (pin > KS8695_GPIO_5) /* only GPIO 0..5 have internal functions */ 34 return; 35 36 local_irq_save(flags); 37 38 x = __raw_readl(KS8695_GPIO_VA + KS8695_IOPC); 39 if (gpio) /* GPIO: set bit to 0 */ 40 x &= ~enable[pin]; 41 else /* Internal function: set bit to 1 */ 42 x |= enable[pin]; 43 __raw_writel(x, KS8695_GPIO_VA + KS8695_IOPC); 44 45 local_irq_restore(flags); 46} 47 48 49static unsigned short gpio_irq[] = { KS8695_IRQ_EXTERN0, KS8695_IRQ_EXTERN1, KS8695_IRQ_EXTERN2, KS8695_IRQ_EXTERN3 }; 50 51/* 52 * Configure GPIO pin as external interrupt source. 53 */ 54int ks8695_gpio_interrupt(unsigned int pin, unsigned int type) 55{ 56 unsigned long x, flags; 57 58 if (pin > KS8695_GPIO_3) /* only GPIO 0..3 can generate IRQ */ 59 return -EINVAL; 60 61 local_irq_save(flags); 62 63 /* set pin as input */ 64 x = __raw_readl(KS8695_GPIO_VA + KS8695_IOPM); 65 x &= ~IOPM(pin); 66 __raw_writel(x, KS8695_GPIO_VA + KS8695_IOPM); 67 68 local_irq_restore(flags); 69 70 /* Set IRQ triggering type */ 71 irq_set_irq_type(gpio_irq[pin], type); 72 73 /* enable interrupt mode */ 74 ks8695_gpio_mode(pin, 0); 75 76 return 0; 77} 78EXPORT_SYMBOL(ks8695_gpio_interrupt); 79 80 81 82/* .... Generic GPIO interface .............................................. */ 83 84/* 85 * Configure the GPIO line as an input. 86 */ 87static int ks8695_gpio_direction_input(struct gpio_chip *gc, unsigned int pin) 88{ 89 unsigned long x, flags; 90 91 if (pin > KS8695_GPIO_15) 92 return -EINVAL; 93 94 /* set pin to GPIO mode */ 95 ks8695_gpio_mode(pin, 1); 96 97 local_irq_save(flags); 98 99 /* set pin as input */ 100 x = __raw_readl(KS8695_GPIO_VA + KS8695_IOPM); 101 x &= ~IOPM(pin); 102 __raw_writel(x, KS8695_GPIO_VA + KS8695_IOPM); 103 104 local_irq_restore(flags); 105 106 return 0; 107} 108 109 110/* 111 * Configure the GPIO line as an output, with default state. 112 */ 113static int ks8695_gpio_direction_output(struct gpio_chip *gc, 114 unsigned int pin, int state) 115{ 116 unsigned long x, flags; 117 118 if (pin > KS8695_GPIO_15) 119 return -EINVAL; 120 121 /* set pin to GPIO mode */ 122 ks8695_gpio_mode(pin, 1); 123 124 local_irq_save(flags); 125 126 /* set line state */ 127 x = __raw_readl(KS8695_GPIO_VA + KS8695_IOPD); 128 if (state) 129 x |= IOPD(pin); 130 else 131 x &= ~IOPD(pin); 132 __raw_writel(x, KS8695_GPIO_VA + KS8695_IOPD); 133 134 /* set pin as output */ 135 x = __raw_readl(KS8695_GPIO_VA + KS8695_IOPM); 136 x |= IOPM(pin); 137 __raw_writel(x, KS8695_GPIO_VA + KS8695_IOPM); 138 139 local_irq_restore(flags); 140 141 return 0; 142} 143 144 145/* 146 * Set the state of an output GPIO line. 147 */ 148static void ks8695_gpio_set_value(struct gpio_chip *gc, 149 unsigned int pin, int state) 150{ 151 unsigned long x, flags; 152 153 if (pin > KS8695_GPIO_15) 154 return; 155 156 local_irq_save(flags); 157 158 /* set output line state */ 159 x = __raw_readl(KS8695_GPIO_VA + KS8695_IOPD); 160 if (state) 161 x |= IOPD(pin); 162 else 163 x &= ~IOPD(pin); 164 __raw_writel(x, KS8695_GPIO_VA + KS8695_IOPD); 165 166 local_irq_restore(flags); 167} 168 169 170/* 171 * Read the state of a GPIO line. 172 */ 173static int ks8695_gpio_get_value(struct gpio_chip *gc, unsigned int pin) 174{ 175 unsigned long x; 176 177 if (pin > KS8695_GPIO_15) 178 return -EINVAL; 179 180 x = __raw_readl(KS8695_GPIO_VA + KS8695_IOPD); 181 return (x & IOPD(pin)) != 0; 182} 183 184 185/* 186 * Map GPIO line to IRQ number. 187 */ 188static int ks8695_gpio_to_irq(struct gpio_chip *gc, unsigned int pin) 189{ 190 if (pin > KS8695_GPIO_3) /* only GPIO 0..3 can generate IRQ */ 191 return -EINVAL; 192 193 return gpio_irq[pin]; 194} 195 196/* GPIOLIB interface */ 197 198static struct gpio_chip ks8695_gpio_chip = { 199 .label = "KS8695", 200 .direction_input = ks8695_gpio_direction_input, 201 .direction_output = ks8695_gpio_direction_output, 202 .get = ks8695_gpio_get_value, 203 .set = ks8695_gpio_set_value, 204 .to_irq = ks8695_gpio_to_irq, 205 .base = 0, 206 .ngpio = 16, 207 .can_sleep = false, 208}; 209 210/* Register the GPIOs */ 211void ks8695_register_gpios(void) 212{ 213 if (gpiochip_add_data(&ks8695_gpio_chip, NULL)) 214 printk(KERN_ERR "Unable to register core GPIOs\n"); 215} 216 217/* .... Debug interface ..................................................... */ 218 219#ifdef CONFIG_DEBUG_FS 220 221static int ks8695_gpio_show(struct seq_file *s, void *unused) 222{ 223 unsigned int enable[] = { IOPC_IOEINT0EN, IOPC_IOEINT1EN, IOPC_IOEINT2EN, IOPC_IOEINT3EN, IOPC_IOTIM0EN, IOPC_IOTIM1EN }; 224 unsigned int intmask[] = { IOPC_IOEINT0TM, IOPC_IOEINT1TM, IOPC_IOEINT2TM, IOPC_IOEINT3TM }; 225 unsigned long mode, ctrl, data; 226 int i; 227 228 mode = __raw_readl(KS8695_GPIO_VA + KS8695_IOPM); 229 ctrl = __raw_readl(KS8695_GPIO_VA + KS8695_IOPC); 230 data = __raw_readl(KS8695_GPIO_VA + KS8695_IOPD); 231 232 seq_printf(s, "Pin\tI/O\tFunction\tState\n\n"); 233 234 for (i = KS8695_GPIO_0; i <= KS8695_GPIO_15 ; i++) { 235 seq_printf(s, "%i:\t", i); 236 237 seq_printf(s, "%s\t", (mode & IOPM(i)) ? "Output" : "Input"); 238 239 if (i <= KS8695_GPIO_3) { 240 if (ctrl & enable[i]) { 241 seq_printf(s, "EXT%i ", i); 242 243 switch ((ctrl & intmask[i]) >> (4 * i)) { 244 case IOPC_TM_LOW: 245 seq_printf(s, "(Low)"); break; 246 case IOPC_TM_HIGH: 247 seq_printf(s, "(High)"); break; 248 case IOPC_TM_RISING: 249 seq_printf(s, "(Rising)"); break; 250 case IOPC_TM_FALLING: 251 seq_printf(s, "(Falling)"); break; 252 case IOPC_TM_EDGE: 253 seq_printf(s, "(Edges)"); break; 254 } 255 } else 256 seq_printf(s, "GPIO\t"); 257 } else if (i <= KS8695_GPIO_5) { 258 if (ctrl & enable[i]) 259 seq_printf(s, "TOUT%i\t", i - KS8695_GPIO_4); 260 else 261 seq_printf(s, "GPIO\t"); 262 } else { 263 seq_printf(s, "GPIO\t"); 264 } 265 266 seq_printf(s, "\t"); 267 268 seq_printf(s, "%i\n", (data & IOPD(i)) ? 1 : 0); 269 } 270 return 0; 271} 272 273DEFINE_SHOW_ATTRIBUTE(ks8695_gpio); 274 275static int __init ks8695_gpio_debugfs_init(void) 276{ 277 /* /sys/kernel/debug/ks8695_gpio */ 278 debugfs_create_file("ks8695_gpio", S_IFREG | S_IRUGO, NULL, NULL, 279 &ks8695_gpio_fops); 280 return 0; 281} 282postcore_initcall(ks8695_gpio_debugfs_init); 283 284#endif