1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * GPIO interface for Intel Poulsbo SCH 4 * 5 * Copyright (c) 2010 CompuLab Ltd 6 * Author: Denis Turischev <denis@compulab.co.il> 7 */ 8 9 #include <linux/acpi.h> 10 #include <linux/errno.h> 11 #include <linux/gpio/driver.h> 12 #include <linux/io.h> 13 #include <linux/irq.h> 14 #include <linux/kernel.h> 15 #include <linux/module.h> 16 #include <linux/pci_ids.h> 17 #include <linux/platform_device.h> 18 #include <linux/types.h> 19 20 #define GEN 0x00 21 #define GIO 0x04 22 #define GLV 0x08 23 #define GTPE 0x0c 24 #define GTNE 0x10 25 #define GGPE 0x14 26 #define GSMI 0x18 27 #define GTS 0x1c 28 29 #define CORE_BANK_OFFSET 0x00 30 #define RESUME_BANK_OFFSET 0x20 31 32 struct sch_gpio { 33 struct gpio_chip chip; 34 struct irq_chip irqchip; 35 spinlock_t lock; 36 unsigned short iobase; 37 unsigned short resume_base; 38 }; 39 40 static unsigned int sch_gpio_offset(struct sch_gpio *sch, unsigned int gpio, 41 unsigned int reg) 42 { 43 unsigned int base = CORE_BANK_OFFSET; 44 45 if (gpio >= sch->resume_base) { 46 gpio -= sch->resume_base; 47 base = RESUME_BANK_OFFSET; 48 } 49 50 return base + reg + gpio / 8; 51 } 52 53 static unsigned int sch_gpio_bit(struct sch_gpio *sch, unsigned int gpio) 54 { 55 if (gpio >= sch->resume_base) 56 gpio -= sch->resume_base; 57 return gpio % 8; 58 } 59 60 static int sch_gpio_reg_get(struct sch_gpio *sch, unsigned int gpio, unsigned int reg) 61 { 62 unsigned short offset, bit; 63 u8 reg_val; 64 65 offset = sch_gpio_offset(sch, gpio, reg); 66 bit = sch_gpio_bit(sch, gpio); 67 68 reg_val = !!(inb(sch->iobase + offset) & BIT(bit)); 69 70 return reg_val; 71 } 72 73 static void sch_gpio_reg_set(struct sch_gpio *sch, unsigned int gpio, unsigned int reg, 74 int val) 75 { 76 unsigned short offset, bit; 77 u8 reg_val; 78 79 offset = sch_gpio_offset(sch, gpio, reg); 80 bit = sch_gpio_bit(sch, gpio); 81 82 reg_val = inb(sch->iobase + offset); 83 84 if (val) 85 outb(reg_val | BIT(bit), sch->iobase + offset); 86 else 87 outb((reg_val & ~BIT(bit)), sch->iobase + offset); 88 } 89 90 static int sch_gpio_direction_in(struct gpio_chip *gc, unsigned int gpio_num) 91 { 92 struct sch_gpio *sch = gpiochip_get_data(gc); 93 unsigned long flags; 94 95 spin_lock_irqsave(&sch->lock, flags); 96 sch_gpio_reg_set(sch, gpio_num, GIO, 1); 97 spin_unlock_irqrestore(&sch->lock, flags); 98 return 0; 99 } 100 101 static int sch_gpio_get(struct gpio_chip *gc, unsigned int gpio_num) 102 { 103 struct sch_gpio *sch = gpiochip_get_data(gc); 104 105 return sch_gpio_reg_get(sch, gpio_num, GLV); 106 } 107 108 static void sch_gpio_set(struct gpio_chip *gc, unsigned int gpio_num, int val) 109 { 110 struct sch_gpio *sch = gpiochip_get_data(gc); 111 unsigned long flags; 112 113 spin_lock_irqsave(&sch->lock, flags); 114 sch_gpio_reg_set(sch, gpio_num, GLV, val); 115 spin_unlock_irqrestore(&sch->lock, flags); 116 } 117 118 static int sch_gpio_direction_out(struct gpio_chip *gc, unsigned int gpio_num, 119 int val) 120 { 121 struct sch_gpio *sch = gpiochip_get_data(gc); 122 unsigned long flags; 123 124 spin_lock_irqsave(&sch->lock, flags); 125 sch_gpio_reg_set(sch, gpio_num, GIO, 0); 126 spin_unlock_irqrestore(&sch->lock, flags); 127 128 /* 129 * according to the datasheet, writing to the level register has no 130 * effect when GPIO is programmed as input. 131 * Actually the the level register is read-only when configured as input. 132 * Thus presetting the output level before switching to output is _NOT_ possible. 133 * Hence we set the level after configuring the GPIO as output. 134 * But we cannot prevent a short low pulse if direction is set to high 135 * and an external pull-up is connected. 136 */ 137 sch_gpio_set(gc, gpio_num, val); 138 return 0; 139 } 140 141 static int sch_gpio_get_direction(struct gpio_chip *gc, unsigned int gpio_num) 142 { 143 struct sch_gpio *sch = gpiochip_get_data(gc); 144 145 if (sch_gpio_reg_get(sch, gpio_num, GIO)) 146 return GPIO_LINE_DIRECTION_IN; 147 148 return GPIO_LINE_DIRECTION_OUT; 149 } 150 151 static const struct gpio_chip sch_gpio_chip = { 152 .label = "sch_gpio", 153 .owner = THIS_MODULE, 154 .direction_input = sch_gpio_direction_in, 155 .get = sch_gpio_get, 156 .direction_output = sch_gpio_direction_out, 157 .set = sch_gpio_set, 158 .get_direction = sch_gpio_get_direction, 159 }; 160 161 static int sch_irq_type(struct irq_data *d, unsigned int type) 162 { 163 struct gpio_chip *gc = irq_data_get_irq_chip_data(d); 164 struct sch_gpio *sch = gpiochip_get_data(gc); 165 irq_hw_number_t gpio_num = irqd_to_hwirq(d); 166 unsigned long flags; 167 int rising, falling; 168 169 switch (type & IRQ_TYPE_SENSE_MASK) { 170 case IRQ_TYPE_EDGE_RISING: 171 rising = 1; 172 falling = 0; 173 break; 174 case IRQ_TYPE_EDGE_FALLING: 175 rising = 0; 176 falling = 1; 177 break; 178 case IRQ_TYPE_EDGE_BOTH: 179 rising = 1; 180 falling = 1; 181 break; 182 default: 183 return -EINVAL; 184 } 185 186 spin_lock_irqsave(&sch->lock, flags); 187 188 sch_gpio_reg_set(sch, gpio_num, GTPE, rising); 189 sch_gpio_reg_set(sch, gpio_num, GTNE, falling); 190 191 irq_set_handler_locked(d, handle_edge_irq); 192 193 spin_unlock_irqrestore(&sch->lock, flags); 194 195 return 0; 196 } 197 198 static void sch_irq_ack(struct irq_data *d) 199 { 200 struct gpio_chip *gc = irq_data_get_irq_chip_data(d); 201 struct sch_gpio *sch = gpiochip_get_data(gc); 202 irq_hw_number_t gpio_num = irqd_to_hwirq(d); 203 unsigned long flags; 204 205 spin_lock_irqsave(&sch->lock, flags); 206 sch_gpio_reg_set(sch, gpio_num, GTS, 1); 207 spin_unlock_irqrestore(&sch->lock, flags); 208 } 209 210 static void sch_irq_mask_unmask(struct irq_data *d, int val) 211 { 212 struct gpio_chip *gc = irq_data_get_irq_chip_data(d); 213 struct sch_gpio *sch = gpiochip_get_data(gc); 214 irq_hw_number_t gpio_num = irqd_to_hwirq(d); 215 unsigned long flags; 216 217 spin_lock_irqsave(&sch->lock, flags); 218 sch_gpio_reg_set(sch, gpio_num, GGPE, val); 219 spin_unlock_irqrestore(&sch->lock, flags); 220 } 221 222 static void sch_irq_mask(struct irq_data *d) 223 { 224 sch_irq_mask_unmask(d, 0); 225 } 226 227 static void sch_irq_unmask(struct irq_data *d) 228 { 229 sch_irq_mask_unmask(d, 1); 230 } 231 232 static int sch_gpio_probe(struct platform_device *pdev) 233 { 234 struct gpio_irq_chip *girq; 235 struct sch_gpio *sch; 236 struct resource *res; 237 238 sch = devm_kzalloc(&pdev->dev, sizeof(*sch), GFP_KERNEL); 239 if (!sch) 240 return -ENOMEM; 241 242 res = platform_get_resource(pdev, IORESOURCE_IO, 0); 243 if (!res) 244 return -EBUSY; 245 246 if (!devm_request_region(&pdev->dev, res->start, resource_size(res), 247 pdev->name)) 248 return -EBUSY; 249 250 spin_lock_init(&sch->lock); 251 sch->iobase = res->start; 252 sch->chip = sch_gpio_chip; 253 sch->chip.label = dev_name(&pdev->dev); 254 sch->chip.parent = &pdev->dev; 255 256 switch (pdev->id) { 257 case PCI_DEVICE_ID_INTEL_SCH_LPC: 258 sch->resume_base = 10; 259 sch->chip.ngpio = 14; 260 261 /* 262 * GPIO[6:0] enabled by default 263 * GPIO7 is configured by the CMC as SLPIOVR 264 * Enable GPIO[9:8] core powered gpios explicitly 265 */ 266 sch_gpio_reg_set(sch, 8, GEN, 1); 267 sch_gpio_reg_set(sch, 9, GEN, 1); 268 /* 269 * SUS_GPIO[2:0] enabled by default 270 * Enable SUS_GPIO3 resume powered gpio explicitly 271 */ 272 sch_gpio_reg_set(sch, 13, GEN, 1); 273 break; 274 275 case PCI_DEVICE_ID_INTEL_ITC_LPC: 276 sch->resume_base = 5; 277 sch->chip.ngpio = 14; 278 break; 279 280 case PCI_DEVICE_ID_INTEL_CENTERTON_ILB: 281 sch->resume_base = 21; 282 sch->chip.ngpio = 30; 283 break; 284 285 case PCI_DEVICE_ID_INTEL_QUARK_X1000_ILB: 286 sch->resume_base = 2; 287 sch->chip.ngpio = 8; 288 break; 289 290 default: 291 return -ENODEV; 292 } 293 294 platform_set_drvdata(pdev, sch); 295 296 sch->irqchip.name = "sch_gpio"; 297 sch->irqchip.irq_ack = sch_irq_ack; 298 sch->irqchip.irq_mask = sch_irq_mask; 299 sch->irqchip.irq_unmask = sch_irq_unmask; 300 sch->irqchip.irq_set_type = sch_irq_type; 301 302 girq = &sch->chip.irq; 303 girq->chip = &sch->irqchip; 304 girq->num_parents = 0; 305 girq->parents = NULL; 306 girq->parent_handler = NULL; 307 girq->default_type = IRQ_TYPE_NONE; 308 girq->handler = handle_bad_irq; 309 310 return devm_gpiochip_add_data(&pdev->dev, &sch->chip, sch); 311 } 312 313 static struct platform_driver sch_gpio_driver = { 314 .driver = { 315 .name = "sch_gpio", 316 }, 317 .probe = sch_gpio_probe, 318 }; 319 320 module_platform_driver(sch_gpio_driver); 321 322 MODULE_AUTHOR("Denis Turischev <denis@compulab.co.il>"); 323 MODULE_DESCRIPTION("GPIO interface for Intel Poulsbo SCH"); 324 MODULE_LICENSE("GPL v2"); 325 MODULE_ALIAS("platform:sch_gpio"); 326