0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
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
0033 #define SCU2C 0x2c
0034
0035 #define SCU180 0x180
0036
0037
0038
0039 #define SCU180_ENP2A BIT(1)
0040
0041
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
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
0062
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
0077
0078
0079
0080 u32 read;
0081
0082
0083
0084
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
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
0139 for (i = 0; i < P2A_REGION_COUNT; i++) {
0140 const struct region *curr = &ctrl->config->regions[i];
0141
0142
0143
0144 if (curr->max < base)
0145 continue;
0146
0147
0148
0149 if (curr->min > end)
0150 break;
0151
0152
0153
0154
0155 mutex_lock(&ctrl->tracking);
0156 ctrl->readerwriters[i] += 1;
0157 mutex_unlock(&ctrl->tracking);
0158
0159
0160
0161
0162 priv->readwrite[i] += 1;
0163
0164
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
0186
0187
0188
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
0196
0197
0198 priv->read += 1;
0199 } else if (map.flags == ASPEED_P2A_CTRL_READWRITE) {
0200
0201 if (!aspeed_p2a_region_acquire(priv, ctrl, &map)) {
0202 return -EINVAL;
0203 }
0204 } else {
0205
0206 return -EINVAL;
0207 }
0208
0209 aspeed_p2a_enable_bridge(ctrl);
0210 return 0;
0211 case ASPEED_P2A_CTRL_IOCTL_GET_MEMORY_CONFIG:
0212
0213
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
0229
0230
0231
0232
0233
0234
0235
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
0250 priv->parent = file->private_data;
0251
0252
0253 file->private_data = priv;
0254
0255 return 0;
0256 }
0257
0258
0259
0260
0261
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
0271
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
0287
0288
0289
0290
0291
0292
0293
0294 regmap_update_bits(priv->parent->regmap, SCU2C, bits, bits);
0295
0296
0297
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
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
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
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");