Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /*
0003  * GPIO driver for AMD 8111 south bridges
0004  *
0005  * Copyright (c) 2012 Dmitry Eremin-Solenikov
0006  *
0007  * Based on the AMD RNG driver:
0008  * Copyright 2005 (c) MontaVista Software, Inc.
0009  * with the majority of the code coming from:
0010  *
0011  * Hardware driver for the Intel/AMD/VIA Random Number Generators (RNG)
0012  * (c) Copyright 2003 Red Hat Inc <jgarzik@redhat.com>
0013  *
0014  * derived from
0015  *
0016  * Hardware driver for the AMD 768 Random Number Generator (RNG)
0017  * (c) Copyright 2001 Red Hat Inc
0018  *
0019  * derived from
0020  *
0021  * Hardware driver for Intel i810 Random Number Generator (RNG)
0022  * Copyright 2000,2001 Jeff Garzik <jgarzik@pobox.com>
0023  * Copyright 2000,2001 Philipp Rumpf <prumpf@mandrakesoft.com>
0024  */
0025 #include <linux/ioport.h>
0026 #include <linux/module.h>
0027 #include <linux/kernel.h>
0028 #include <linux/gpio/driver.h>
0029 #include <linux/pci.h>
0030 #include <linux/spinlock.h>
0031 
0032 #define PMBASE_OFFSET 0xb0
0033 #define PMBASE_SIZE   0x30
0034 
0035 #define AMD_REG_GPIO(i) (0x10 + (i))
0036 
0037 #define AMD_GPIO_LTCH_STS   0x40 /* Latch status, w1 */
0038 #define AMD_GPIO_RTIN       0x20 /* Real Time in, ro */
0039 #define AMD_GPIO_DEBOUNCE   0x10 /* Debounce, rw */
0040 #define AMD_GPIO_MODE_MASK  0x0c /* Pin Mode Select, rw */
0041 #define AMD_GPIO_MODE_IN    0x00
0042 #define AMD_GPIO_MODE_OUT   0x04
0043 /* Enable alternative (e.g. clkout, IRQ, etc) function of the pin */
0044 #define AMD_GPIO_MODE_ALTFN 0x08 /* Or 0x09 */
0045 #define AMD_GPIO_X_MASK     0x03 /* In/Out specific, rw */
0046 #define AMD_GPIO_X_IN_ACTIVEHI  0x01 /* Active High */
0047 #define AMD_GPIO_X_IN_LATCH 0x02 /* Latched version is selected */
0048 #define AMD_GPIO_X_OUT_LOW  0x00
0049 #define AMD_GPIO_X_OUT_HI   0x01
0050 #define AMD_GPIO_X_OUT_CLK0 0x02
0051 #define AMD_GPIO_X_OUT_CLK1 0x03
0052 
0053 /*
0054  * Data for PCI driver interface
0055  *
0056  * This data only exists for exporting the supported
0057  * PCI ids via MODULE_DEVICE_TABLE.  We do not actually
0058  * register a pci_driver, because someone else might one day
0059  * want to register another driver on the same PCI id.
0060  */
0061 static const struct pci_device_id pci_tbl[] = {
0062     { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_8111_SMBUS), 0 },
0063     { 0, }, /* terminate list */
0064 };
0065 MODULE_DEVICE_TABLE(pci, pci_tbl);
0066 
0067 struct amd_gpio {
0068     struct gpio_chip    chip;
0069     u32         pmbase;
0070     void __iomem        *pm;
0071     struct pci_dev      *pdev;
0072     spinlock_t      lock; /* guards hw registers and orig table */
0073     u8          orig[32];
0074 };
0075 
0076 static int amd_gpio_request(struct gpio_chip *chip, unsigned offset)
0077 {
0078     struct amd_gpio *agp = gpiochip_get_data(chip);
0079 
0080     agp->orig[offset] = ioread8(agp->pm + AMD_REG_GPIO(offset)) &
0081         (AMD_GPIO_DEBOUNCE | AMD_GPIO_MODE_MASK | AMD_GPIO_X_MASK);
0082 
0083     dev_dbg(&agp->pdev->dev, "Requested gpio %d, data %x\n", offset, agp->orig[offset]);
0084 
0085     return 0;
0086 }
0087 
0088 static void amd_gpio_free(struct gpio_chip *chip, unsigned offset)
0089 {
0090     struct amd_gpio *agp = gpiochip_get_data(chip);
0091 
0092     dev_dbg(&agp->pdev->dev, "Freed gpio %d, data %x\n", offset, agp->orig[offset]);
0093 
0094     iowrite8(agp->orig[offset], agp->pm + AMD_REG_GPIO(offset));
0095 }
0096 
0097 static void amd_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
0098 {
0099     struct amd_gpio *agp = gpiochip_get_data(chip);
0100     u8 temp;
0101     unsigned long flags;
0102 
0103     spin_lock_irqsave(&agp->lock, flags);
0104     temp = ioread8(agp->pm + AMD_REG_GPIO(offset));
0105     temp = (temp & AMD_GPIO_DEBOUNCE) | AMD_GPIO_MODE_OUT | (value ? AMD_GPIO_X_OUT_HI : AMD_GPIO_X_OUT_LOW);
0106     iowrite8(temp, agp->pm + AMD_REG_GPIO(offset));
0107     spin_unlock_irqrestore(&agp->lock, flags);
0108 
0109     dev_dbg(&agp->pdev->dev, "Setting gpio %d, value %d, reg=%02x\n", offset, !!value, temp);
0110 }
0111 
0112 static int amd_gpio_get(struct gpio_chip *chip, unsigned offset)
0113 {
0114     struct amd_gpio *agp = gpiochip_get_data(chip);
0115     u8 temp;
0116 
0117     temp = ioread8(agp->pm + AMD_REG_GPIO(offset));
0118 
0119     dev_dbg(&agp->pdev->dev, "Getting gpio %d, reg=%02x\n", offset, temp);
0120 
0121     return (temp & AMD_GPIO_RTIN) ? 1 : 0;
0122 }
0123 
0124 static int amd_gpio_dirout(struct gpio_chip *chip, unsigned offset, int value)
0125 {
0126     struct amd_gpio *agp = gpiochip_get_data(chip);
0127     u8 temp;
0128     unsigned long flags;
0129 
0130     spin_lock_irqsave(&agp->lock, flags);
0131     temp = ioread8(agp->pm + AMD_REG_GPIO(offset));
0132     temp = (temp & AMD_GPIO_DEBOUNCE) | AMD_GPIO_MODE_OUT | (value ? AMD_GPIO_X_OUT_HI : AMD_GPIO_X_OUT_LOW);
0133     iowrite8(temp, agp->pm + AMD_REG_GPIO(offset));
0134     spin_unlock_irqrestore(&agp->lock, flags);
0135 
0136     dev_dbg(&agp->pdev->dev, "Dirout gpio %d, value %d, reg=%02x\n", offset, !!value, temp);
0137 
0138     return 0;
0139 }
0140 
0141 static int amd_gpio_dirin(struct gpio_chip *chip, unsigned offset)
0142 {
0143     struct amd_gpio *agp = gpiochip_get_data(chip);
0144     u8 temp;
0145     unsigned long flags;
0146 
0147     spin_lock_irqsave(&agp->lock, flags);
0148     temp = ioread8(agp->pm + AMD_REG_GPIO(offset));
0149     temp = (temp & AMD_GPIO_DEBOUNCE) | AMD_GPIO_MODE_IN;
0150     iowrite8(temp, agp->pm + AMD_REG_GPIO(offset));
0151     spin_unlock_irqrestore(&agp->lock, flags);
0152 
0153     dev_dbg(&agp->pdev->dev, "Dirin gpio %d, reg=%02x\n", offset, temp);
0154 
0155     return 0;
0156 }
0157 
0158 static struct amd_gpio gp = {
0159     .chip = {
0160         .label      = "AMD GPIO",
0161         .owner      = THIS_MODULE,
0162         .base       = -1,
0163         .ngpio      = 32,
0164         .request    = amd_gpio_request,
0165         .free       = amd_gpio_free,
0166         .set        = amd_gpio_set,
0167         .get        = amd_gpio_get,
0168         .direction_output = amd_gpio_dirout,
0169         .direction_input = amd_gpio_dirin,
0170     },
0171 };
0172 
0173 static int __init amd_gpio_init(void)
0174 {
0175     int err = -ENODEV;
0176     struct pci_dev *pdev = NULL;
0177     const struct pci_device_id *ent;
0178 
0179     /* We look for our device - AMD South Bridge
0180      * I don't know about a system with two such bridges,
0181      * so we can assume that there is max. one device.
0182      *
0183      * We can't use plain pci_driver mechanism,
0184      * as the device is really a multiple function device,
0185      * main driver that binds to the pci_device is an smbus
0186      * driver and have to find & bind to the device this way.
0187      */
0188     for_each_pci_dev(pdev) {
0189         ent = pci_match_id(pci_tbl, pdev);
0190         if (ent)
0191             goto found;
0192     }
0193     /* Device not found. */
0194     goto out;
0195 
0196 found:
0197     err = pci_read_config_dword(pdev, 0x58, &gp.pmbase);
0198     if (err)
0199         goto out;
0200     err = -EIO;
0201     gp.pmbase &= 0x0000FF00;
0202     if (gp.pmbase == 0)
0203         goto out;
0204     if (!devm_request_region(&pdev->dev, gp.pmbase + PMBASE_OFFSET,
0205         PMBASE_SIZE, "AMD GPIO")) {
0206         dev_err(&pdev->dev, "AMD GPIO region 0x%x already in use!\n",
0207             gp.pmbase + PMBASE_OFFSET);
0208         err = -EBUSY;
0209         goto out;
0210     }
0211     gp.pm = ioport_map(gp.pmbase + PMBASE_OFFSET, PMBASE_SIZE);
0212     if (!gp.pm) {
0213         dev_err(&pdev->dev, "Couldn't map io port into io memory\n");
0214         err = -ENOMEM;
0215         goto out;
0216     }
0217     gp.pdev = pdev;
0218     gp.chip.parent = &pdev->dev;
0219 
0220     spin_lock_init(&gp.lock);
0221 
0222     dev_info(&pdev->dev, "AMD-8111 GPIO detected\n");
0223     err = gpiochip_add_data(&gp.chip, &gp);
0224     if (err) {
0225         dev_err(&pdev->dev, "GPIO registering failed (%d)\n", err);
0226         ioport_unmap(gp.pm);
0227         goto out;
0228     }
0229 out:
0230     return err;
0231 }
0232 
0233 static void __exit amd_gpio_exit(void)
0234 {
0235     gpiochip_remove(&gp.chip);
0236     ioport_unmap(gp.pm);
0237 }
0238 
0239 module_init(amd_gpio_init);
0240 module_exit(amd_gpio_exit);
0241 
0242 MODULE_AUTHOR("The Linux Kernel team");
0243 MODULE_DESCRIPTION("GPIO driver for AMD chipsets");
0244 MODULE_LICENSE("GPL");