diff options
| -rw-r--r-- | arch/arm/mach-omap2/devices.c | 2 | ||||
| -rw-r--r-- | arch/arm/mach-omap2/omap-iommu.c | 168 | ||||
| -rw-r--r-- | drivers/iommu/omap-iommu.c | 23 | ||||
| -rw-r--r-- | drivers/iommu/omap-iommu2.c | 19 | ||||
| -rw-r--r-- | include/linux/platform_data/iommu-omap.h | 8 |
5 files changed, 64 insertions, 156 deletions
diff --git a/arch/arm/mach-omap2/devices.c b/arch/arm/mach-omap2/devices.c index c15f5a97b51c..787a996ec4eb 100644 --- a/arch/arm/mach-omap2/devices.c +++ b/arch/arm/mach-omap2/devices.c | |||
| @@ -214,7 +214,7 @@ static struct platform_device omap3isp_device = { | |||
| 214 | }; | 214 | }; |
| 215 | 215 | ||
| 216 | static struct omap_iommu_arch_data omap3_isp_iommu = { | 216 | static struct omap_iommu_arch_data omap3_isp_iommu = { |
| 217 | .name = "isp", | 217 | .name = "mmu_isp", |
| 218 | }; | 218 | }; |
| 219 | 219 | ||
| 220 | int omap3_init_camera(struct isp_platform_data *pdata) | 220 | int omap3_init_camera(struct isp_platform_data *pdata) |
diff --git a/arch/arm/mach-omap2/omap-iommu.c b/arch/arm/mach-omap2/omap-iommu.c index a6a4ff8744b7..02726a647b1d 100644 --- a/arch/arm/mach-omap2/omap-iommu.c +++ b/arch/arm/mach-omap2/omap-iommu.c | |||
| @@ -12,153 +12,61 @@ | |||
| 12 | 12 | ||
| 13 | #include <linux/module.h> | 13 | #include <linux/module.h> |
| 14 | #include <linux/platform_device.h> | 14 | #include <linux/platform_device.h> |
| 15 | #include <linux/err.h> | ||
| 16 | #include <linux/slab.h> | ||
| 15 | 17 | ||
| 16 | #include <linux/platform_data/iommu-omap.h> | 18 | #include <linux/platform_data/iommu-omap.h> |
| 19 | #include <plat/omap_hwmod.h> | ||
| 20 | #include <plat/omap_device.h> | ||
| 17 | 21 | ||
| 18 | #include "soc.h" | 22 | static int __init omap_iommu_dev_init(struct omap_hwmod *oh, void *unused) |
| 19 | #include "common.h" | ||
| 20 | |||
| 21 | struct iommu_device { | ||
| 22 | resource_size_t base; | ||
| 23 | int irq; | ||
| 24 | struct iommu_platform_data pdata; | ||
| 25 | struct resource res[2]; | ||
| 26 | }; | ||
| 27 | static struct iommu_device *devices; | ||
| 28 | static int num_iommu_devices; | ||
| 29 | |||
| 30 | #ifdef CONFIG_ARCH_OMAP3 | ||
| 31 | static struct iommu_device omap3_devices[] = { | ||
| 32 | { | ||
| 33 | .base = 0x480bd400, | ||
| 34 | .irq = 24 + OMAP_INTC_START, | ||
| 35 | .pdata = { | ||
| 36 | .name = "isp", | ||
| 37 | .nr_tlb_entries = 8, | ||
| 38 | .clk_name = "cam_ick", | ||
| 39 | .da_start = 0x0, | ||
| 40 | .da_end = 0xFFFFF000, | ||
| 41 | }, | ||
| 42 | }, | ||
| 43 | #if defined(CONFIG_OMAP_IOMMU_IVA2) | ||
| 44 | { | ||
| 45 | .base = 0x5d000000, | ||
| 46 | .irq = 28 + OMAP_INTC_START, | ||
| 47 | .pdata = { | ||
| 48 | .name = "iva2", | ||
| 49 | .nr_tlb_entries = 32, | ||
| 50 | .clk_name = "iva2_ck", | ||
| 51 | .da_start = 0x11000000, | ||
| 52 | .da_end = 0xFFFFF000, | ||
| 53 | }, | ||
| 54 | }, | ||
| 55 | #endif | ||
| 56 | }; | ||
| 57 | #define NR_OMAP3_IOMMU_DEVICES ARRAY_SIZE(omap3_devices) | ||
| 58 | static struct platform_device *omap3_iommu_pdev[NR_OMAP3_IOMMU_DEVICES]; | ||
| 59 | #else | ||
| 60 | #define omap3_devices NULL | ||
| 61 | #define NR_OMAP3_IOMMU_DEVICES 0 | ||
| 62 | #define omap3_iommu_pdev NULL | ||
| 63 | #endif | ||
| 64 | |||
| 65 | #ifdef CONFIG_ARCH_OMAP4 | ||
| 66 | static struct iommu_device omap4_devices[] = { | ||
| 67 | { | ||
| 68 | .base = OMAP4_MMU1_BASE, | ||
| 69 | .irq = 100 + OMAP44XX_IRQ_GIC_START, | ||
| 70 | .pdata = { | ||
| 71 | .name = "ducati", | ||
| 72 | .nr_tlb_entries = 32, | ||
| 73 | .clk_name = "ipu_fck", | ||
| 74 | .da_start = 0x0, | ||
| 75 | .da_end = 0xFFFFF000, | ||
| 76 | }, | ||
| 77 | }, | ||
| 78 | { | ||
| 79 | .base = OMAP4_MMU2_BASE, | ||
| 80 | .irq = 28 + OMAP44XX_IRQ_GIC_START, | ||
| 81 | .pdata = { | ||
| 82 | .name = "tesla", | ||
| 83 | .nr_tlb_entries = 32, | ||
| 84 | .clk_name = "dsp_fck", | ||
| 85 | .da_start = 0x0, | ||
| 86 | .da_end = 0xFFFFF000, | ||
| 87 | }, | ||
| 88 | }, | ||
| 89 | }; | ||
| 90 | #define NR_OMAP4_IOMMU_DEVICES ARRAY_SIZE(omap4_devices) | ||
| 91 | static struct platform_device *omap4_iommu_pdev[NR_OMAP4_IOMMU_DEVICES]; | ||
| 92 | #else | ||
| 93 | #define omap4_devices NULL | ||
| 94 | #define NR_OMAP4_IOMMU_DEVICES 0 | ||
| 95 | #define omap4_iommu_pdev NULL | ||
| 96 | #endif | ||
| 97 | |||
| 98 | static struct platform_device **omap_iommu_pdev; | ||
| 99 | |||
| 100 | static int __init omap_iommu_init(void) | ||
| 101 | { | 23 | { |
| 102 | int i, err; | 24 | struct platform_device *pdev; |
| 103 | struct resource res[] = { | 25 | struct iommu_platform_data *pdata; |
| 104 | { .flags = IORESOURCE_MEM }, | 26 | struct omap_mmu_dev_attr *a = (struct omap_mmu_dev_attr *)oh->dev_attr; |
| 105 | { .flags = IORESOURCE_IRQ }, | 27 | static int i; |
| 106 | }; | 28 | |
| 29 | pdata = kzalloc(sizeof(*pdata), GFP_KERNEL); | ||
| 30 | if (!pdata) | ||
| 31 | return -ENOMEM; | ||
| 32 | |||
| 33 | pdata->name = oh->name; | ||
| 34 | pdata->clk_name = oh->main_clk; | ||
| 35 | pdata->nr_tlb_entries = a->nr_tlb_entries; | ||
| 36 | pdata->da_start = a->da_start; | ||
| 37 | pdata->da_end = a->da_end; | ||
| 38 | |||
| 39 | if (oh->rst_lines_cnt == 1) { | ||
| 40 | pdata->reset_name = oh->rst_lines->name; | ||
| 41 | pdata->assert_reset = omap_device_assert_hardreset; | ||
| 42 | pdata->deassert_reset = omap_device_deassert_hardreset; | ||
| 43 | } | ||
| 107 | 44 | ||
| 108 | if (cpu_is_omap34xx()) { | 45 | pdev = omap_device_build("omap-iommu", i, oh, pdata, sizeof(*pdata), |
| 109 | devices = omap3_devices; | 46 | NULL, 0, 0); |
| 110 | omap_iommu_pdev = omap3_iommu_pdev; | ||
| 111 | num_iommu_devices = NR_OMAP3_IOMMU_DEVICES; | ||
| 112 | } else if (cpu_is_omap44xx()) { | ||
| 113 | devices = omap4_devices; | ||
| 114 | omap_iommu_pdev = omap4_iommu_pdev; | ||
| 115 | num_iommu_devices = NR_OMAP4_IOMMU_DEVICES; | ||
| 116 | } else | ||
| 117 | return -ENODEV; | ||
| 118 | 47 | ||
| 119 | for (i = 0; i < num_iommu_devices; i++) { | 48 | kfree(pdata); |
| 120 | struct platform_device *pdev; | ||
| 121 | const struct iommu_device *d = &devices[i]; | ||
| 122 | 49 | ||
| 123 | pdev = platform_device_alloc("omap-iommu", i); | 50 | if (IS_ERR(pdev)) { |
| 124 | if (!pdev) { | 51 | pr_err("%s: device build err: %ld\n", __func__, PTR_ERR(pdev)); |
| 125 | err = -ENOMEM; | 52 | return PTR_ERR(pdev); |
| 126 | goto err_out; | 53 | } |
| 127 | } | ||
| 128 | 54 | ||
| 129 | res[0].start = d->base; | 55 | i++; |
| 130 | res[0].end = d->base + MMU_REG_SIZE - 1; | ||
| 131 | res[1].start = res[1].end = d->irq; | ||
| 132 | 56 | ||
| 133 | err = platform_device_add_resources(pdev, res, | ||
| 134 | ARRAY_SIZE(res)); | ||
| 135 | if (err) | ||
| 136 | goto err_out; | ||
| 137 | err = platform_device_add_data(pdev, &d->pdata, | ||
| 138 | sizeof(d->pdata)); | ||
| 139 | if (err) | ||
| 140 | goto err_out; | ||
| 141 | err = platform_device_add(pdev); | ||
| 142 | if (err) | ||
| 143 | goto err_out; | ||
| 144 | omap_iommu_pdev[i] = pdev; | ||
| 145 | } | ||
| 146 | return 0; | 57 | return 0; |
| 58 | } | ||
| 147 | 59 | ||
| 148 | err_out: | 60 | static int __init omap_iommu_init(void) |
| 149 | while (i--) | 61 | { |
| 150 | platform_device_put(omap_iommu_pdev[i]); | 62 | return omap_hwmod_for_each_by_class("mmu", omap_iommu_dev_init, NULL); |
| 151 | return err; | ||
| 152 | } | 63 | } |
| 153 | /* must be ready before omap3isp is probed */ | 64 | /* must be ready before omap3isp is probed */ |
| 154 | subsys_initcall(omap_iommu_init); | 65 | subsys_initcall(omap_iommu_init); |
| 155 | 66 | ||
| 156 | static void __exit omap_iommu_exit(void) | 67 | static void __exit omap_iommu_exit(void) |
| 157 | { | 68 | { |
| 158 | int i; | 69 | /* Do nothing */ |
| 159 | |||
| 160 | for (i = 0; i < num_iommu_devices; i++) | ||
| 161 | platform_device_unregister(omap_iommu_pdev[i]); | ||
| 162 | } | 70 | } |
| 163 | module_exit(omap_iommu_exit); | 71 | module_exit(omap_iommu_exit); |
| 164 | 72 | ||
diff --git a/drivers/iommu/omap-iommu.c b/drivers/iommu/omap-iommu.c index f8082da6179b..af9b4f31f594 100644 --- a/drivers/iommu/omap-iommu.c +++ b/drivers/iommu/omap-iommu.c | |||
| @@ -143,13 +143,23 @@ EXPORT_SYMBOL_GPL(omap_iommu_arch_version); | |||
| 143 | static int iommu_enable(struct omap_iommu *obj) | 143 | static int iommu_enable(struct omap_iommu *obj) |
| 144 | { | 144 | { |
| 145 | int err; | 145 | int err; |
| 146 | struct platform_device *pdev = to_platform_device(obj->dev); | ||
| 147 | struct iommu_platform_data *pdata = pdev->dev.platform_data; | ||
| 146 | 148 | ||
| 147 | if (!obj) | 149 | if (!obj || !pdata) |
| 148 | return -EINVAL; | 150 | return -EINVAL; |
| 149 | 151 | ||
| 150 | if (!arch_iommu) | 152 | if (!arch_iommu) |
| 151 | return -ENODEV; | 153 | return -ENODEV; |
| 152 | 154 | ||
| 155 | if (pdata->deassert_reset) { | ||
| 156 | err = pdata->deassert_reset(pdev, pdata->reset_name); | ||
| 157 | if (err) { | ||
| 158 | dev_err(obj->dev, "deassert_reset failed: %d\n", err); | ||
| 159 | return err; | ||
| 160 | } | ||
| 161 | } | ||
| 162 | |||
| 153 | clk_enable(obj->clk); | 163 | clk_enable(obj->clk); |
| 154 | 164 | ||
| 155 | err = arch_iommu->enable(obj); | 165 | err = arch_iommu->enable(obj); |
| @@ -159,12 +169,18 @@ static int iommu_enable(struct omap_iommu *obj) | |||
| 159 | 169 | ||
| 160 | static void iommu_disable(struct omap_iommu *obj) | 170 | static void iommu_disable(struct omap_iommu *obj) |
| 161 | { | 171 | { |
| 162 | if (!obj) | 172 | struct platform_device *pdev = to_platform_device(obj->dev); |
| 173 | struct iommu_platform_data *pdata = pdev->dev.platform_data; | ||
| 174 | |||
| 175 | if (!obj || !pdata) | ||
| 163 | return; | 176 | return; |
| 164 | 177 | ||
| 165 | arch_iommu->disable(obj); | 178 | arch_iommu->disable(obj); |
| 166 | 179 | ||
| 167 | clk_disable(obj->clk); | 180 | clk_disable(obj->clk); |
| 181 | |||
| 182 | if (pdata->assert_reset) | ||
| 183 | pdata->assert_reset(pdev, pdata->reset_name); | ||
| 168 | } | 184 | } |
| 169 | 185 | ||
| 170 | /* | 186 | /* |
| @@ -926,9 +942,6 @@ static int __devinit omap_iommu_probe(struct platform_device *pdev) | |||
| 926 | struct resource *res; | 942 | struct resource *res; |
| 927 | struct iommu_platform_data *pdata = pdev->dev.platform_data; | 943 | struct iommu_platform_data *pdata = pdev->dev.platform_data; |
| 928 | 944 | ||
| 929 | if (pdev->num_resources != 2) | ||
| 930 | return -EINVAL; | ||
| 931 | |||
| 932 | obj = kzalloc(sizeof(*obj) + MMU_REG_SIZE, GFP_KERNEL); | 945 | obj = kzalloc(sizeof(*obj) + MMU_REG_SIZE, GFP_KERNEL); |
| 933 | if (!obj) | 946 | if (!obj) |
| 934 | return -ENOMEM; | 947 | return -ENOMEM; |
diff --git a/drivers/iommu/omap-iommu2.c b/drivers/iommu/omap-iommu2.c index c02020292377..4a3a1c7a38c1 100644 --- a/drivers/iommu/omap-iommu2.c +++ b/drivers/iommu/omap-iommu2.c | |||
| @@ -35,12 +35,8 @@ | |||
| 35 | #define MMU_SYS_IDLE_SMART (2 << MMU_SYS_IDLE_SHIFT) | 35 | #define MMU_SYS_IDLE_SMART (2 << MMU_SYS_IDLE_SHIFT) |
| 36 | #define MMU_SYS_IDLE_MASK (3 << MMU_SYS_IDLE_SHIFT) | 36 | #define MMU_SYS_IDLE_MASK (3 << MMU_SYS_IDLE_SHIFT) |
| 37 | 37 | ||
| 38 | #define MMU_SYS_SOFTRESET (1 << 1) | ||
| 39 | #define MMU_SYS_AUTOIDLE 1 | 38 | #define MMU_SYS_AUTOIDLE 1 |
| 40 | 39 | ||
| 41 | /* SYSSTATUS */ | ||
| 42 | #define MMU_SYS_RESETDONE 1 | ||
| 43 | |||
| 44 | /* IRQSTATUS & IRQENABLE */ | 40 | /* IRQSTATUS & IRQENABLE */ |
| 45 | #define MMU_IRQ_MULTIHITFAULT (1 << 4) | 41 | #define MMU_IRQ_MULTIHITFAULT (1 << 4) |
| 46 | #define MMU_IRQ_TABLEWALKFAULT (1 << 3) | 42 | #define MMU_IRQ_TABLEWALKFAULT (1 << 3) |
| @@ -97,7 +93,6 @@ static void __iommu_set_twl(struct omap_iommu *obj, bool on) | |||
| 97 | static int omap2_iommu_enable(struct omap_iommu *obj) | 93 | static int omap2_iommu_enable(struct omap_iommu *obj) |
| 98 | { | 94 | { |
| 99 | u32 l, pa; | 95 | u32 l, pa; |
| 100 | unsigned long timeout; | ||
| 101 | 96 | ||
| 102 | if (!obj->iopgd || !IS_ALIGNED((u32)obj->iopgd, SZ_16K)) | 97 | if (!obj->iopgd || !IS_ALIGNED((u32)obj->iopgd, SZ_16K)) |
| 103 | return -EINVAL; | 98 | return -EINVAL; |
| @@ -106,20 +101,6 @@ static int omap2_iommu_enable(struct omap_iommu *obj) | |||
| 106 | if (!IS_ALIGNED(pa, SZ_16K)) | 101 | if (!IS_ALIGNED(pa, SZ_16K)) |
| 107 | return -EINVAL; | 102 | return -EINVAL; |
| 108 | 103 | ||
| 109 | iommu_write_reg(obj, MMU_SYS_SOFTRESET, MMU_SYSCONFIG); | ||
| 110 | |||
| 111 | timeout = jiffies + msecs_to_jiffies(20); | ||
| 112 | do { | ||
| 113 | l = iommu_read_reg(obj, MMU_SYSSTATUS); | ||
| 114 | if (l & MMU_SYS_RESETDONE) | ||
| 115 | break; | ||
| 116 | } while (!time_after(jiffies, timeout)); | ||
| 117 | |||
| 118 | if (!(l & MMU_SYS_RESETDONE)) { | ||
| 119 | dev_err(obj->dev, "can't take mmu out of reset\n"); | ||
| 120 | return -ENODEV; | ||
| 121 | } | ||
| 122 | |||
| 123 | l = iommu_read_reg(obj, MMU_REVISION); | 104 | l = iommu_read_reg(obj, MMU_REVISION); |
| 124 | dev_info(obj->dev, "%s: version %d.%d\n", obj->name, | 105 | dev_info(obj->dev, "%s: version %d.%d\n", obj->name, |
| 125 | (l >> 4) & 0xf, l & 0xf); | 106 | (l >> 4) & 0xf, l & 0xf); |
diff --git a/include/linux/platform_data/iommu-omap.h b/include/linux/platform_data/iommu-omap.h index c677b9f2fefa..ef2060d7eeb8 100644 --- a/include/linux/platform_data/iommu-omap.h +++ b/include/linux/platform_data/iommu-omap.h | |||
| @@ -10,6 +10,8 @@ | |||
| 10 | * published by the Free Software Foundation. | 10 | * published by the Free Software Foundation. |
| 11 | */ | 11 | */ |
| 12 | 12 | ||
| 13 | #include <linux/platform_device.h> | ||
| 14 | |||
| 13 | #define MMU_REG_SIZE 256 | 15 | #define MMU_REG_SIZE 256 |
| 14 | 16 | ||
| 15 | /** | 17 | /** |
| @@ -43,7 +45,11 @@ struct omap_mmu_dev_attr { | |||
| 43 | struct iommu_platform_data { | 45 | struct iommu_platform_data { |
| 44 | const char *name; | 46 | const char *name; |
| 45 | const char *clk_name; | 47 | const char *clk_name; |
| 46 | const int nr_tlb_entries; | 48 | const char *reset_name; |
| 49 | int nr_tlb_entries; | ||
| 47 | u32 da_start; | 50 | u32 da_start; |
| 48 | u32 da_end; | 51 | u32 da_end; |
| 52 | |||
| 53 | int (*assert_reset)(struct platform_device *pdev, const char *name); | ||
| 54 | int (*deassert_reset)(struct platform_device *pdev, const char *name); | ||
| 49 | }; | 55 | }; |
