Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0+
0002 /*
0003  * Copyright 2019 Google Inc
0004  *
0005  * This program is free software; you can redistribute it and/or
0006  * modify it under the terms of the GNU General Public License
0007  * as published by the Free Software Foundation; either version
0008  * 2 of the License, or (at your option) any later version.
0009  *
0010  * Provides a simple driver to control the ASPEED P2A interface which allows
0011  * the host to read and write to various regions of the BMC's memory.
0012  */
0013 
0014 #include <linux/fs.h>
0015 #include <linux/io.h>
0016 #include <linux/mfd/syscon.h>
0017 #include <linux/miscdevice.h>
0018 #include <linux/mm.h>
0019 #include <linux/module.h>
0020 #include <linux/mutex.h>
0021 #include <linux/of_address.h>
0022 #include <linux/of_device.h>
0023 #include <linux/platform_device.h>
0024 #include <linux/regmap.h>
0025 #include <linux/slab.h>
0026 #include <linux/uaccess.h>
0027 
0028 #include <linux/aspeed-p2a-ctrl.h>
0029 
0030 #define DEVICE_NAME "aspeed-p2a-ctrl"
0031 
0032 /* SCU2C is a Misc. Control Register. */
0033 #define SCU2C 0x2c
0034 /* SCU180 is the PCIe Configuration Setting Control Register. */
0035 #define SCU180 0x180
0036 /* Bit 1 controls the P2A bridge, while bit 0 controls the entire VGA device
0037  * on the PCI bus.
0038  */
0039 #define SCU180_ENP2A BIT(1)
0040 
0041 /* The ast2400/2500 both have six ranges. */
0042 #define P2A_REGION_COUNT 6
0043 
0044 struct region {
0045     u64 min;
0046     u64 max;
0047     u32 bit;
0048 };
0049 
0050 struct aspeed_p2a_model_data {
0051     /* min, max, bit */
0052     struct region regions[P2A_REGION_COUNT];
0053 };
0054 
0055 struct aspeed_p2a_ctrl {
0056     struct miscdevice miscdev;
0057     struct regmap *regmap;
0058 
0059     const struct aspeed_p2a_model_data *config;
0060 
0061     /* Access to these needs to be locked, held via probe, mapping ioctl,
0062      * and release, remove.
0063      */
0064     struct mutex tracking;
0065     u32 readers;
0066     u32 readerwriters[P2A_REGION_COUNT];
0067 
0068     phys_addr_t mem_base;
0069     resource_size_t mem_size;
0070 };
0071 
0072 struct aspeed_p2a_user {
0073     struct file *file;
0074     struct aspeed_p2a_ctrl *parent;
0075 
0076     /* The entire memory space is opened for reading once the bridge is
0077      * enabled, therefore this needs only to be tracked once per user.
0078      * If any user has it open for read, the bridge must stay enabled.
0079      */
0080     u32 read;
0081 
0082     /* Each entry of the array corresponds to a P2A Region.  If the user
0083      * opens for read or readwrite, the reference goes up here.  On
0084      * release, this array is walked and references adjusted accordingly.
0085      */
0086     u32 readwrite[P2A_REGION_COUNT];
0087 };
0088 
0089 static void aspeed_p2a_enable_bridge(struct aspeed_p2a_ctrl *p2a_ctrl)
0090 {
0091     regmap_update_bits(p2a_ctrl->regmap,
0092         SCU180, SCU180_ENP2A, SCU180_ENP2A);
0093 }
0094 
0095 static void aspeed_p2a_disable_bridge(struct aspeed_p2a_ctrl *p2a_ctrl)
0096 {
0097     regmap_update_bits(p2a_ctrl->regmap, SCU180, SCU180_ENP2A, 0);
0098 }
0099 
0100 static int aspeed_p2a_mmap(struct file *file, struct vm_area_struct *vma)
0101 {
0102     unsigned long vsize;
0103     pgprot_t prot;
0104     struct aspeed_p2a_user *priv = file->private_data;
0105     struct aspeed_p2a_ctrl *ctrl = priv->parent;
0106 
0107     if (ctrl->mem_base == 0 && ctrl->mem_size == 0)
0108         return -EINVAL;
0109 
0110     vsize = vma->vm_end - vma->vm_start;
0111     prot = vma->vm_page_prot;
0112 
0113     if (vma->vm_pgoff + vma_pages(vma) > ctrl->mem_size >> PAGE_SHIFT)
0114         return -EINVAL;
0115 
0116     /* ast2400/2500 AHB accesses are not cache coherent */
0117     prot = pgprot_noncached(prot);
0118 
0119     if (remap_pfn_range(vma, vma->vm_start,
0120         (ctrl->mem_base >> PAGE_SHIFT) + vma->vm_pgoff,
0121         vsize, prot))
0122         return -EAGAIN;
0123 
0124     return 0;
0125 }
0126 
0127 static bool aspeed_p2a_region_acquire(struct aspeed_p2a_user *priv,
0128         struct aspeed_p2a_ctrl *ctrl,
0129         struct aspeed_p2a_ctrl_mapping *map)
0130 {
0131     int i;
0132     u64 base, end;
0133     bool matched = false;
0134 
0135     base = map->addr;
0136     end = map->addr + (map->length - 1);
0137 
0138     /* If the value is a legal u32, it will find a match. */
0139     for (i = 0; i < P2A_REGION_COUNT; i++) {
0140         const struct region *curr = &ctrl->config->regions[i];
0141 
0142         /* If the top of this region is lower than your base, skip it.
0143          */
0144         if (curr->max < base)
0145             continue;
0146 
0147         /* If the bottom of this region is higher than your end, bail.
0148          */
0149         if (curr->min > end)
0150             break;
0151 
0152         /* Lock this and update it, therefore it someone else is
0153          * closing their file out, this'll preserve the increment.
0154          */
0155         mutex_lock(&ctrl->tracking);
0156         ctrl->readerwriters[i] += 1;
0157         mutex_unlock(&ctrl->tracking);
0158 
0159         /* Track with the user, so when they close their file, we can
0160          * decrement properly.
0161          */
0162         priv->readwrite[i] += 1;
0163 
0164         /* Enable the region as read-write. */
0165         regmap_update_bits(ctrl->regmap, SCU2C, curr->bit, 0);
0166         matched = true;
0167     }
0168 
0169     return matched;
0170 }
0171 
0172 static long aspeed_p2a_ioctl(struct file *file, unsigned int cmd,
0173         unsigned long data)
0174 {
0175     struct aspeed_p2a_user *priv = file->private_data;
0176     struct aspeed_p2a_ctrl *ctrl = priv->parent;
0177     void __user *arg = (void __user *)data;
0178     struct aspeed_p2a_ctrl_mapping map;
0179 
0180     if (copy_from_user(&map, arg, sizeof(map)))
0181         return -EFAULT;
0182 
0183     switch (cmd) {
0184     case ASPEED_P2A_CTRL_IOCTL_SET_WINDOW:
0185         /* If they want a region to be read-only, since the entire
0186          * region is read-only once enabled, we just need to track this
0187          * user wants to read from the bridge, and if it's not enabled.
0188          * Enable it.
0189          */
0190         if (map.flags == ASPEED_P2A_CTRL_READ_ONLY) {
0191             mutex_lock(&ctrl->tracking);
0192             ctrl->readers += 1;
0193             mutex_unlock(&ctrl->tracking);
0194 
0195             /* Track with the user, so when they close their file,
0196              * we can decrement properly.
0197              */
0198             priv->read += 1;
0199         } else if (map.flags == ASPEED_P2A_CTRL_READWRITE) {
0200             /* If we don't acquire any region return error. */
0201             if (!aspeed_p2a_region_acquire(priv, ctrl, &map)) {
0202                 return -EINVAL;
0203             }
0204         } else {
0205             /* Invalid map flags. */
0206             return -EINVAL;
0207         }
0208 
0209         aspeed_p2a_enable_bridge(ctrl);
0210         return 0;
0211     case ASPEED_P2A_CTRL_IOCTL_GET_MEMORY_CONFIG:
0212         /* This is a request for the memory-region and corresponding
0213          * length that is used by the driver for mmap.
0214          */
0215 
0216         map.flags = 0;
0217         map.addr = ctrl->mem_base;
0218         map.length = ctrl->mem_size;
0219 
0220         return copy_to_user(arg, &map, sizeof(map)) ? -EFAULT : 0;
0221     }
0222 
0223     return -EINVAL;
0224 }
0225 
0226 
0227 /*
0228  * When a user opens this file, we create a structure to track their mappings.
0229  *
0230  * A user can map a region as read-only (bridge enabled), or read-write (bit
0231  * flipped, and bridge enabled).  Either way, this tracking is used, s.t. when
0232  * they release the device references are handled.
0233  *
0234  * The bridge is not enabled until a user calls an ioctl to map a region,
0235  * simply opening the device does not enable it.
0236  */
0237 static int aspeed_p2a_open(struct inode *inode, struct file *file)
0238 {
0239     struct aspeed_p2a_user *priv;
0240 
0241     priv = kmalloc(sizeof(*priv), GFP_KERNEL);
0242     if (!priv)
0243         return -ENOMEM;
0244 
0245     priv->file = file;
0246     priv->read = 0;
0247     memset(priv->readwrite, 0, sizeof(priv->readwrite));
0248 
0249     /* The file's private_data is initialized to the p2a_ctrl. */
0250     priv->parent = file->private_data;
0251 
0252     /* Set the file's private_data to the user's data. */
0253     file->private_data = priv;
0254 
0255     return 0;
0256 }
0257 
0258 /*
0259  * This will close the users mappings.  It will go through what they had opened
0260  * for readwrite, and decrement those counts.  If at the end, this is the last
0261  * user, it'll close the bridge.
0262  */
0263 static int aspeed_p2a_release(struct inode *inode, struct file *file)
0264 {
0265     int i;
0266     u32 bits = 0;
0267     bool open_regions = false;
0268     struct aspeed_p2a_user *priv = file->private_data;
0269 
0270     /* Lock others from changing these values until everything is updated
0271      * in one pass.
0272      */
0273     mutex_lock(&priv->parent->tracking);
0274 
0275     priv->parent->readers -= priv->read;
0276 
0277     for (i = 0; i < P2A_REGION_COUNT; i++) {
0278         priv->parent->readerwriters[i] -= priv->readwrite[i];
0279 
0280         if (priv->parent->readerwriters[i] > 0)
0281             open_regions = true;
0282         else
0283             bits |= priv->parent->config->regions[i].bit;
0284     }
0285 
0286     /* Setting a bit to 1 disables the region, so let's just OR with the
0287      * above to disable any.
0288      */
0289 
0290     /* Note, if another user is trying to ioctl, they can't grab tracking,
0291      * and therefore can't grab either register mutex.
0292      * If another user is trying to close, they can't grab tracking either.
0293      */
0294     regmap_update_bits(priv->parent->regmap, SCU2C, bits, bits);
0295 
0296     /* If parent->readers is zero and open windows is 0, disable the
0297      * bridge.
0298      */
0299     if (!open_regions && priv->parent->readers == 0)
0300         aspeed_p2a_disable_bridge(priv->parent);
0301 
0302     mutex_unlock(&priv->parent->tracking);
0303 
0304     kfree(priv);
0305 
0306     return 0;
0307 }
0308 
0309 static const struct file_operations aspeed_p2a_ctrl_fops = {
0310     .owner = THIS_MODULE,
0311     .mmap = aspeed_p2a_mmap,
0312     .unlocked_ioctl = aspeed_p2a_ioctl,
0313     .open = aspeed_p2a_open,
0314     .release = aspeed_p2a_release,
0315 };
0316 
0317 /* The regions are controlled by SCU2C */
0318 static void aspeed_p2a_disable_all(struct aspeed_p2a_ctrl *p2a_ctrl)
0319 {
0320     int i;
0321     u32 value = 0;
0322 
0323     for (i = 0; i < P2A_REGION_COUNT; i++)
0324         value |= p2a_ctrl->config->regions[i].bit;
0325 
0326     regmap_update_bits(p2a_ctrl->regmap, SCU2C, value, value);
0327 
0328     /* Disable the bridge. */
0329     aspeed_p2a_disable_bridge(p2a_ctrl);
0330 }
0331 
0332 static int aspeed_p2a_ctrl_probe(struct platform_device *pdev)
0333 {
0334     struct aspeed_p2a_ctrl *misc_ctrl;
0335     struct device *dev;
0336     struct resource resm;
0337     struct device_node *node;
0338     int rc = 0;
0339 
0340     dev = &pdev->dev;
0341 
0342     misc_ctrl = devm_kzalloc(dev, sizeof(*misc_ctrl), GFP_KERNEL);
0343     if (!misc_ctrl)
0344         return -ENOMEM;
0345 
0346     mutex_init(&misc_ctrl->tracking);
0347 
0348     /* optional. */
0349     node = of_parse_phandle(dev->of_node, "memory-region", 0);
0350     if (node) {
0351         rc = of_address_to_resource(node, 0, &resm);
0352         of_node_put(node);
0353         if (rc) {
0354             dev_err(dev, "Couldn't address to resource for reserved memory\n");
0355             return -ENODEV;
0356         }
0357 
0358         misc_ctrl->mem_size = resource_size(&resm);
0359         misc_ctrl->mem_base = resm.start;
0360     }
0361 
0362     misc_ctrl->regmap = syscon_node_to_regmap(pdev->dev.parent->of_node);
0363     if (IS_ERR(misc_ctrl->regmap)) {
0364         dev_err(dev, "Couldn't get regmap\n");
0365         return -ENODEV;
0366     }
0367 
0368     misc_ctrl->config = of_device_get_match_data(dev);
0369 
0370     dev_set_drvdata(&pdev->dev, misc_ctrl);
0371 
0372     aspeed_p2a_disable_all(misc_ctrl);
0373 
0374     misc_ctrl->miscdev.minor = MISC_DYNAMIC_MINOR;
0375     misc_ctrl->miscdev.name = DEVICE_NAME;
0376     misc_ctrl->miscdev.fops = &aspeed_p2a_ctrl_fops;
0377     misc_ctrl->miscdev.parent = dev;
0378 
0379     rc = misc_register(&misc_ctrl->miscdev);
0380     if (rc)
0381         dev_err(dev, "Unable to register device\n");
0382 
0383     return rc;
0384 }
0385 
0386 static int aspeed_p2a_ctrl_remove(struct platform_device *pdev)
0387 {
0388     struct aspeed_p2a_ctrl *p2a_ctrl = dev_get_drvdata(&pdev->dev);
0389 
0390     misc_deregister(&p2a_ctrl->miscdev);
0391 
0392     return 0;
0393 }
0394 
0395 #define SCU2C_DRAM  BIT(25)
0396 #define SCU2C_SPI   BIT(24)
0397 #define SCU2C_SOC   BIT(23)
0398 #define SCU2C_FLASH BIT(22)
0399 
0400 static const struct aspeed_p2a_model_data ast2400_model_data = {
0401     .regions = {
0402         {0x00000000, 0x17FFFFFF, SCU2C_FLASH},
0403         {0x18000000, 0x1FFFFFFF, SCU2C_SOC},
0404         {0x20000000, 0x2FFFFFFF, SCU2C_FLASH},
0405         {0x30000000, 0x3FFFFFFF, SCU2C_SPI},
0406         {0x40000000, 0x5FFFFFFF, SCU2C_DRAM},
0407         {0x60000000, 0xFFFFFFFF, SCU2C_SOC},
0408     }
0409 };
0410 
0411 static const struct aspeed_p2a_model_data ast2500_model_data = {
0412     .regions = {
0413         {0x00000000, 0x0FFFFFFF, SCU2C_FLASH},
0414         {0x10000000, 0x1FFFFFFF, SCU2C_SOC},
0415         {0x20000000, 0x3FFFFFFF, SCU2C_FLASH},
0416         {0x40000000, 0x5FFFFFFF, SCU2C_SOC},
0417         {0x60000000, 0x7FFFFFFF, SCU2C_SPI},
0418         {0x80000000, 0xFFFFFFFF, SCU2C_DRAM},
0419     }
0420 };
0421 
0422 static const struct of_device_id aspeed_p2a_ctrl_match[] = {
0423     { .compatible = "aspeed,ast2400-p2a-ctrl",
0424       .data = &ast2400_model_data },
0425     { .compatible = "aspeed,ast2500-p2a-ctrl",
0426       .data = &ast2500_model_data },
0427     { },
0428 };
0429 
0430 static struct platform_driver aspeed_p2a_ctrl_driver = {
0431     .driver = {
0432         .name       = DEVICE_NAME,
0433         .of_match_table = aspeed_p2a_ctrl_match,
0434     },
0435     .probe = aspeed_p2a_ctrl_probe,
0436     .remove = aspeed_p2a_ctrl_remove,
0437 };
0438 
0439 module_platform_driver(aspeed_p2a_ctrl_driver);
0440 
0441 MODULE_DEVICE_TABLE(of, aspeed_p2a_ctrl_match);
0442 MODULE_LICENSE("GPL");
0443 MODULE_AUTHOR("Patrick Venture <venture@google.com>");
0444 MODULE_DESCRIPTION("Control for aspeed 2400/2500 P2A VGA HOST to BMC mappings");