^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) * GPIO driver for AMD 8111 south bridges
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) * Copyright (c) 2012 Dmitry Eremin-Solenikov
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * Based on the AMD RNG driver:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * Copyright 2005 (c) MontaVista Software, Inc.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * with the majority of the code coming from:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) * Hardware driver for the Intel/AMD/VIA Random Number Generators (RNG)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) * (c) Copyright 2003 Red Hat Inc <jgarzik@redhat.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) * derived from
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) * Hardware driver for the AMD 768 Random Number Generator (RNG)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) * (c) Copyright 2001 Red Hat Inc
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) * derived from
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) * Hardware driver for Intel i810 Random Number Generator (RNG)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) * Copyright 2000,2001 Jeff Garzik <jgarzik@pobox.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) * Copyright 2000,2001 Philipp Rumpf <prumpf@mandrakesoft.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) * This file is licensed under the terms of the GNU General Public
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) * License version 2. This program is licensed "as is" without any
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) * warranty of any kind, whether express or implied.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) #include <linux/ioport.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) #include <linux/gpio/driver.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) #include <linux/pci.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) #include <linux/spinlock.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) #define PMBASE_OFFSET 0xb0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) #define PMBASE_SIZE 0x30
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) #define AMD_REG_GPIO(i) (0x10 + (i))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) #define AMD_GPIO_LTCH_STS 0x40 /* Latch status, w1 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) #define AMD_GPIO_RTIN 0x20 /* Real Time in, ro */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) #define AMD_GPIO_DEBOUNCE 0x10 /* Debounce, rw */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) #define AMD_GPIO_MODE_MASK 0x0c /* Pin Mode Select, rw */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) #define AMD_GPIO_MODE_IN 0x00
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) #define AMD_GPIO_MODE_OUT 0x04
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) /* Enable alternative (e.g. clkout, IRQ, etc) function of the pin */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) #define AMD_GPIO_MODE_ALTFN 0x08 /* Or 0x09 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) #define AMD_GPIO_X_MASK 0x03 /* In/Out specific, rw */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) #define AMD_GPIO_X_IN_ACTIVEHI 0x01 /* Active High */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) #define AMD_GPIO_X_IN_LATCH 0x02 /* Latched version is selected */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) #define AMD_GPIO_X_OUT_LOW 0x00
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) #define AMD_GPIO_X_OUT_HI 0x01
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) #define AMD_GPIO_X_OUT_CLK0 0x02
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) #define AMD_GPIO_X_OUT_CLK1 0x03
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) * Data for PCI driver interface
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) * This data only exists for exporting the supported
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) * PCI ids via MODULE_DEVICE_TABLE. We do not actually
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) * register a pci_driver, because someone else might one day
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) * want to register another driver on the same PCI id.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) static const struct pci_device_id pci_tbl[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_8111_SMBUS), 0 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) { 0, }, /* terminate list */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) MODULE_DEVICE_TABLE(pci, pci_tbl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) struct amd_gpio {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) struct gpio_chip chip;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) u32 pmbase;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) void __iomem *pm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) struct pci_dev *pdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) spinlock_t lock; /* guards hw registers and orig table */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) u8 orig[32];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) static int amd_gpio_request(struct gpio_chip *chip, unsigned offset)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) struct amd_gpio *agp = gpiochip_get_data(chip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) agp->orig[offset] = ioread8(agp->pm + AMD_REG_GPIO(offset)) &
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) (AMD_GPIO_DEBOUNCE | AMD_GPIO_MODE_MASK | AMD_GPIO_X_MASK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) dev_dbg(&agp->pdev->dev, "Requested gpio %d, data %x\n", offset, agp->orig[offset]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) static void amd_gpio_free(struct gpio_chip *chip, unsigned offset)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) struct amd_gpio *agp = gpiochip_get_data(chip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) dev_dbg(&agp->pdev->dev, "Freed gpio %d, data %x\n", offset, agp->orig[offset]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) iowrite8(agp->orig[offset], agp->pm + AMD_REG_GPIO(offset));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) static void amd_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) struct amd_gpio *agp = gpiochip_get_data(chip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) u8 temp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) spin_lock_irqsave(&agp->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) temp = ioread8(agp->pm + AMD_REG_GPIO(offset));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) temp = (temp & AMD_GPIO_DEBOUNCE) | AMD_GPIO_MODE_OUT | (value ? AMD_GPIO_X_OUT_HI : AMD_GPIO_X_OUT_LOW);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) iowrite8(temp, agp->pm + AMD_REG_GPIO(offset));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) spin_unlock_irqrestore(&agp->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) dev_dbg(&agp->pdev->dev, "Setting gpio %d, value %d, reg=%02x\n", offset, !!value, temp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) static int amd_gpio_get(struct gpio_chip *chip, unsigned offset)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) struct amd_gpio *agp = gpiochip_get_data(chip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) u8 temp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) temp = ioread8(agp->pm + AMD_REG_GPIO(offset));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) dev_dbg(&agp->pdev->dev, "Getting gpio %d, reg=%02x\n", offset, temp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) return (temp & AMD_GPIO_RTIN) ? 1 : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) static int amd_gpio_dirout(struct gpio_chip *chip, unsigned offset, int value)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) struct amd_gpio *agp = gpiochip_get_data(chip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) u8 temp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) spin_lock_irqsave(&agp->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) temp = ioread8(agp->pm + AMD_REG_GPIO(offset));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) temp = (temp & AMD_GPIO_DEBOUNCE) | AMD_GPIO_MODE_OUT | (value ? AMD_GPIO_X_OUT_HI : AMD_GPIO_X_OUT_LOW);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) iowrite8(temp, agp->pm + AMD_REG_GPIO(offset));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) spin_unlock_irqrestore(&agp->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) dev_dbg(&agp->pdev->dev, "Dirout gpio %d, value %d, reg=%02x\n", offset, !!value, temp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) static int amd_gpio_dirin(struct gpio_chip *chip, unsigned offset)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) struct amd_gpio *agp = gpiochip_get_data(chip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) u8 temp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) spin_lock_irqsave(&agp->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) temp = ioread8(agp->pm + AMD_REG_GPIO(offset));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) temp = (temp & AMD_GPIO_DEBOUNCE) | AMD_GPIO_MODE_IN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) iowrite8(temp, agp->pm + AMD_REG_GPIO(offset));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) spin_unlock_irqrestore(&agp->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) dev_dbg(&agp->pdev->dev, "Dirin gpio %d, reg=%02x\n", offset, temp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) static struct amd_gpio gp = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) .chip = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) .label = "AMD GPIO",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) .owner = THIS_MODULE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) .base = -1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) .ngpio = 32,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) .request = amd_gpio_request,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) .free = amd_gpio_free,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) .set = amd_gpio_set,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) .get = amd_gpio_get,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) .direction_output = amd_gpio_dirout,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) .direction_input = amd_gpio_dirin,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) static int __init amd_gpio_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) int err = -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) struct pci_dev *pdev = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) const struct pci_device_id *ent;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) /* We look for our device - AMD South Bridge
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) * I don't know about a system with two such bridges,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) * so we can assume that there is max. one device.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) * We can't use plain pci_driver mechanism,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) * as the device is really a multiple function device,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) * main driver that binds to the pci_device is an smbus
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) * driver and have to find & bind to the device this way.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) for_each_pci_dev(pdev) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) ent = pci_match_id(pci_tbl, pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) if (ent)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) goto found;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) /* Device not found. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) found:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) err = pci_read_config_dword(pdev, 0x58, &gp.pmbase);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) err = -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) gp.pmbase &= 0x0000FF00;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) if (gp.pmbase == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) if (!devm_request_region(&pdev->dev, gp.pmbase + PMBASE_OFFSET,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) PMBASE_SIZE, "AMD GPIO")) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) dev_err(&pdev->dev, "AMD GPIO region 0x%x already in use!\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) gp.pmbase + PMBASE_OFFSET);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) err = -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) gp.pm = ioport_map(gp.pmbase + PMBASE_OFFSET, PMBASE_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) if (!gp.pm) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) dev_err(&pdev->dev, "Couldn't map io port into io memory\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) err = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) gp.pdev = pdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) gp.chip.parent = &pdev->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) spin_lock_init(&gp.lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) printk(KERN_INFO "AMD-8111 GPIO detected\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) err = gpiochip_add_data(&gp.chip, &gp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) if (err) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) printk(KERN_ERR "GPIO registering failed (%d)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) err);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) ioport_unmap(gp.pm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) static void __exit amd_gpio_exit(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) gpiochip_remove(&gp.chip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) ioport_unmap(gp.pm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) module_init(amd_gpio_init);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) module_exit(amd_gpio_exit);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) MODULE_AUTHOR("The Linux Kernel team");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) MODULE_DESCRIPTION("GPIO driver for AMD chipsets");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) MODULE_LICENSE("GPL");