Blame view
drivers/gpio/gpio-amdpt.c
4.23 KB
6057d40f4 gpio: driver for ... |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
/* * AMD Promontory GPIO driver * * Copyright (C) 2015 ASMedia Technology Inc. * Author: YD Tseng <yd_tseng@asmedia.com.tw> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. */ #include <linux/kernel.h> #include <linux/module.h> #include <linux/gpio/driver.h> #include <linux/spinlock.h> #include <linux/acpi.h> #include <linux/platform_device.h> #define PT_TOTAL_GPIO 8 /* PCI-E MMIO register offsets */ #define PT_DIRECTION_REG 0x00 #define PT_INPUTDATA_REG 0x04 #define PT_OUTPUTDATA_REG 0x08 #define PT_CLOCKRATE_REG 0x0C #define PT_SYNC_REG 0x28 struct pt_gpio_chip { struct gpio_chip gc; void __iomem *reg_base; |
6057d40f4 gpio: driver for ... |
31 |
}; |
6057d40f4 gpio: driver for ... |
32 33 |
static int pt_gpio_request(struct gpio_chip *gc, unsigned offset) { |
fb7228879 gpio: amdpt: use ... |
34 |
struct pt_gpio_chip *pt_gpio = gpiochip_get_data(gc); |
6057d40f4 gpio: driver for ... |
35 36 |
unsigned long flags; u32 using_pins; |
58383c784 gpio: change memb... |
37 38 |
dev_dbg(gc->parent, "pt_gpio_request offset=%x ", offset); |
6057d40f4 gpio: driver for ... |
39 |
|
574b782e7 gpio: amdpt: Conv... |
40 |
spin_lock_irqsave(&gc->bgpio_lock, flags); |
6057d40f4 gpio: driver for ... |
41 42 43 |
using_pins = readl(pt_gpio->reg_base + PT_SYNC_REG); if (using_pins & BIT(offset)) { |
58383c784 gpio: change memb... |
44 45 46 |
dev_warn(gc->parent, "PT GPIO pin %x reconfigured ", offset); |
574b782e7 gpio: amdpt: Conv... |
47 |
spin_unlock_irqrestore(&gc->bgpio_lock, flags); |
6057d40f4 gpio: driver for ... |
48 49 50 51 |
return -EINVAL; } writel(using_pins | BIT(offset), pt_gpio->reg_base + PT_SYNC_REG); |
574b782e7 gpio: amdpt: Conv... |
52 |
spin_unlock_irqrestore(&gc->bgpio_lock, flags); |
6057d40f4 gpio: driver for ... |
53 54 55 56 57 58 |
return 0; } static void pt_gpio_free(struct gpio_chip *gc, unsigned offset) { |
fb7228879 gpio: amdpt: use ... |
59 |
struct pt_gpio_chip *pt_gpio = gpiochip_get_data(gc); |
6057d40f4 gpio: driver for ... |
60 61 |
unsigned long flags; u32 using_pins; |
574b782e7 gpio: amdpt: Conv... |
62 |
spin_lock_irqsave(&gc->bgpio_lock, flags); |
6057d40f4 gpio: driver for ... |
63 64 65 66 |
using_pins = readl(pt_gpio->reg_base + PT_SYNC_REG); using_pins &= ~BIT(offset); writel(using_pins, pt_gpio->reg_base + PT_SYNC_REG); |
574b782e7 gpio: amdpt: Conv... |
67 |
spin_unlock_irqrestore(&gc->bgpio_lock, flags); |
6057d40f4 gpio: driver for ... |
68 |
|
58383c784 gpio: change memb... |
69 70 |
dev_dbg(gc->parent, "pt_gpio_free offset=%x ", offset); |
6057d40f4 gpio: driver for ... |
71 |
} |
6057d40f4 gpio: driver for ... |
72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 |
static int pt_gpio_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; struct acpi_device *acpi_dev; acpi_handle handle = ACPI_HANDLE(dev); struct pt_gpio_chip *pt_gpio; struct resource *res_mem; int ret = 0; if (acpi_bus_get_device(handle, &acpi_dev)) { dev_err(dev, "PT GPIO device node not found "); return -ENODEV; } pt_gpio = devm_kzalloc(dev, sizeof(struct pt_gpio_chip), GFP_KERNEL); if (!pt_gpio) return -ENOMEM; res_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!res_mem) { dev_err(&pdev->dev, "Failed to get MMIO resource for PT GPIO. "); return -EINVAL; } pt_gpio->reg_base = devm_ioremap_resource(dev, res_mem); if (IS_ERR(pt_gpio->reg_base)) { dev_err(&pdev->dev, "Failed to map MMIO resource for PT GPIO. "); return PTR_ERR(pt_gpio->reg_base); } |
574b782e7 gpio: amdpt: Conv... |
103 104 105 106 107 108 109 110 111 112 |
ret = bgpio_init(&pt_gpio->gc, dev, 4, pt_gpio->reg_base + PT_INPUTDATA_REG, pt_gpio->reg_base + PT_OUTPUTDATA_REG, NULL, pt_gpio->reg_base + PT_DIRECTION_REG, NULL, BGPIOF_READ_OUTPUT_REG_SET); if (ret) { dev_err(&pdev->dev, "bgpio_init failed "); return ret; } |
6057d40f4 gpio: driver for ... |
113 |
|
6057d40f4 gpio: driver for ... |
114 |
pt_gpio->gc.owner = THIS_MODULE; |
6057d40f4 gpio: driver for ... |
115 116 |
pt_gpio->gc.request = pt_gpio_request; pt_gpio->gc.free = pt_gpio_free; |
6057d40f4 gpio: driver for ... |
117 118 119 120 |
pt_gpio->gc.ngpio = PT_TOTAL_GPIO; #if defined(CONFIG_OF_GPIO) pt_gpio->gc.of_node = pdev->dev.of_node; #endif |
fb7228879 gpio: amdpt: use ... |
121 |
ret = gpiochip_add_data(&pt_gpio->gc, pt_gpio); |
6057d40f4 gpio: driver for ... |
122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 |
if (ret) { dev_err(&pdev->dev, "Failed to register GPIO lib "); return ret; } platform_set_drvdata(pdev, pt_gpio); /* initialize register setting */ writel(0, pt_gpio->reg_base + PT_SYNC_REG); writel(0, pt_gpio->reg_base + PT_CLOCKRATE_REG); dev_dbg(&pdev->dev, "PT GPIO driver loaded "); return ret; } static int pt_gpio_remove(struct platform_device *pdev) { struct pt_gpio_chip *pt_gpio = platform_get_drvdata(pdev); gpiochip_remove(&pt_gpio->gc); return 0; } static const struct acpi_device_id pt_gpio_acpi_match[] = { { "AMDF030", 0 }, |
ca27379f5 gpio: amdpt: Add ... |
150 |
{ "AMDIF030", 0 }, |
6057d40f4 gpio: driver for ... |
151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 |
{ }, }; MODULE_DEVICE_TABLE(acpi, pt_gpio_acpi_match); static struct platform_driver pt_gpio_driver = { .driver = { .name = "pt-gpio", .acpi_match_table = ACPI_PTR(pt_gpio_acpi_match), }, .probe = pt_gpio_probe, .remove = pt_gpio_remove, }; module_platform_driver(pt_gpio_driver); MODULE_LICENSE("GPL"); MODULE_AUTHOR("YD Tseng <yd_tseng@asmedia.com.tw>"); MODULE_DESCRIPTION("AMD Promontory GPIO Driver"); |