diff options
author | Omar Ramirez Luna <omar.luna@linaro.org> | 2012-11-19 20:05:50 -0500 |
---|---|---|
committer | Joerg Roedel <joro@8bytes.org> | 2012-12-03 12:48:13 -0500 |
commit | 72b15b6ae97796c5fac687addde5dbfab872cf94 (patch) | |
tree | be849a67c3b00a4bb0f4651901e0c37323e74c94 | |
parent | 87f8e57327bd8d85fb5b46cad29ac281430cc50d (diff) |
iommu/omap: Migrate to hwmod framework
Use hwmod data and device attributes to build and register an
omap device for iommu driver.
- Update the naming convention in isp module.
- Remove unneeded check for number of resources, as this is now
handled by omap_device and prevents driver from loading.
- Now unused, remove platform device and resource data, handling
of sysconfig register for softreset purposes, use default
latency structure.
- Use hwmod API for reset handling.
Signed-off-by: Omar Ramirez Luna <omar.luna@linaro.org>
Tested-by: Ohad Ben-Cohen <ohad@wizery.com>
Signed-off-by: Joerg Roedel <joro@8bytes.org>
-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 | }; |