linux/drivers/iommu/shmobile-ipmmu.c
<<
>>
Prefs
   1/*
   2 * IPMMU/IPMMUI
   3 * Copyright (C) 2012  Hideki EIRAKU
   4 *
   5 * This program is free software; you can redistribute it and/or modify
   6 * it under the terms of the GNU General Public License as published by
   7 * the Free Software Foundation; version 2 of the License.
   8 */
   9
  10#include <linux/err.h>
  11#include <linux/export.h>
  12#include <linux/io.h>
  13#include <linux/platform_device.h>
  14#include <linux/slab.h>
  15#include <linux/platform_data/sh_ipmmu.h>
  16#include "shmobile-ipmmu.h"
  17
  18#define IMCTR1 0x000
  19#define IMCTR2 0x004
  20#define IMASID 0x010
  21#define IMTTBR 0x014
  22#define IMTTBCR 0x018
  23
  24#define IMCTR1_TLBEN (1 << 0)
  25#define IMCTR1_FLUSH (1 << 1)
  26
  27static void ipmmu_reg_write(struct shmobile_ipmmu *ipmmu, unsigned long reg_off,
  28                            unsigned long data)
  29{
  30        iowrite32(data, ipmmu->ipmmu_base + reg_off);
  31}
  32
  33void ipmmu_tlb_flush(struct shmobile_ipmmu *ipmmu)
  34{
  35        if (!ipmmu)
  36                return;
  37
  38        mutex_lock(&ipmmu->flush_lock);
  39        if (ipmmu->tlb_enabled)
  40                ipmmu_reg_write(ipmmu, IMCTR1, IMCTR1_FLUSH | IMCTR1_TLBEN);
  41        else
  42                ipmmu_reg_write(ipmmu, IMCTR1, IMCTR1_FLUSH);
  43        mutex_unlock(&ipmmu->flush_lock);
  44}
  45
  46void ipmmu_tlb_set(struct shmobile_ipmmu *ipmmu, unsigned long phys, int size,
  47                   int asid)
  48{
  49        if (!ipmmu)
  50                return;
  51
  52        mutex_lock(&ipmmu->flush_lock);
  53        switch (size) {
  54        default:
  55                ipmmu->tlb_enabled = 0;
  56                break;
  57        case 0x2000:
  58                ipmmu_reg_write(ipmmu, IMTTBCR, 1);
  59                ipmmu->tlb_enabled = 1;
  60                break;
  61        case 0x1000:
  62                ipmmu_reg_write(ipmmu, IMTTBCR, 2);
  63                ipmmu->tlb_enabled = 1;
  64                break;
  65        case 0x800:
  66                ipmmu_reg_write(ipmmu, IMTTBCR, 3);
  67                ipmmu->tlb_enabled = 1;
  68                break;
  69        case 0x400:
  70                ipmmu_reg_write(ipmmu, IMTTBCR, 4);
  71                ipmmu->tlb_enabled = 1;
  72                break;
  73        case 0x200:
  74                ipmmu_reg_write(ipmmu, IMTTBCR, 5);
  75                ipmmu->tlb_enabled = 1;
  76                break;
  77        case 0x100:
  78                ipmmu_reg_write(ipmmu, IMTTBCR, 6);
  79                ipmmu->tlb_enabled = 1;
  80                break;
  81        case 0x80:
  82                ipmmu_reg_write(ipmmu, IMTTBCR, 7);
  83                ipmmu->tlb_enabled = 1;
  84                break;
  85        }
  86        ipmmu_reg_write(ipmmu, IMTTBR, phys);
  87        ipmmu_reg_write(ipmmu, IMASID, asid);
  88        mutex_unlock(&ipmmu->flush_lock);
  89}
  90
  91static int ipmmu_probe(struct platform_device *pdev)
  92{
  93        struct shmobile_ipmmu *ipmmu;
  94        struct resource *res;
  95        struct shmobile_ipmmu_platform_data *pdata = pdev->dev.platform_data;
  96
  97        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
  98        if (!res) {
  99                dev_err(&pdev->dev, "cannot get platform resources\n");
 100                return -ENOENT;
 101        }
 102        ipmmu = devm_kzalloc(&pdev->dev, sizeof(*ipmmu), GFP_KERNEL);
 103        if (!ipmmu) {
 104                dev_err(&pdev->dev, "cannot allocate device data\n");
 105                return -ENOMEM;
 106        }
 107        mutex_init(&ipmmu->flush_lock);
 108        ipmmu->dev = &pdev->dev;
 109        ipmmu->ipmmu_base = devm_ioremap_nocache(&pdev->dev, res->start,
 110                                                resource_size(res));
 111        if (!ipmmu->ipmmu_base) {
 112                dev_err(&pdev->dev, "ioremap_nocache failed\n");
 113                return -ENOMEM;
 114        }
 115        ipmmu->dev_names = pdata->dev_names;
 116        ipmmu->num_dev_names = pdata->num_dev_names;
 117        platform_set_drvdata(pdev, ipmmu);
 118        ipmmu_reg_write(ipmmu, IMCTR1, 0x0); /* disable TLB */
 119        ipmmu_reg_write(ipmmu, IMCTR2, 0x0); /* disable PMB */
 120        ipmmu_iommu_init(ipmmu);
 121        return 0;
 122}
 123
 124static struct platform_driver ipmmu_driver = {
 125        .probe = ipmmu_probe,
 126        .driver = {
 127                .owner = THIS_MODULE,
 128                .name = "ipmmu",
 129        },
 130};
 131
 132static int __init ipmmu_init(void)
 133{
 134        return platform_driver_register(&ipmmu_driver);
 135}
 136subsys_initcall(ipmmu_init);
 137
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.