diff options
author | Sricharan R <r.sricharan@ti.com> | 2013-11-26 08:38:23 -0500 |
---|---|---|
committer | Nishanth Menon <nm@ti.com> | 2014-05-05 15:33:33 -0400 |
commit | 0659452dd2b2602058b80cfdcc673e98f2a67184 (patch) | |
tree | 388e6d8d848f72e2f61466169bec7057461d1e89 | |
parent | 3340d739f8e1273abd408c59ad1843ea2ac35566 (diff) |
bus: omap_l3_noc: use of_match_data to pick up SoC information
DRA7xx SoC has the same l3-noc interconnect ip (as OMAP4 and OMAP5), but
AM437x SoC has just 2 modules instead of 3 which other SoCs have.
So, stop using direct access of array indices and use of->match data and
simplify implementation to benefit future usage.
While at it, rename a few very generic variables to make them omap
specific. This helps us differentiate from DRA7 and AM43xx data in the
future.
NOTE: None of the platforms that use omap_l3_noc are non-device tree
anymore. So, it is safe to assume OF match here.
Signed-off-by: Sricharan R <r.sricharan@ti.com>
Signed-off-by: Rajendra Nayak <rnayak@ti.com>
[nm@ti.com: split, refactor and optimize logic]
Signed-off-by: Nishanth Menon <nm@ti.com>
Acked-by: Santosh Shilimkar <santosh.shilimkar@ti.com>
Acked-by: Peter Ujfalusi <peter.ujfalusi@ti.com>
Tested-by: Darren Etheridge <detheridge@ti.com>
Tested-by: Sekhar Nori <nsekhar@ti.com>
-rw-r--r-- | drivers/bus/omap_l3_noc.c | 55 | ||||
-rw-r--r-- | drivers/bus/omap_l3_noc.h | 72 |
2 files changed, 84 insertions, 43 deletions
diff --git a/drivers/bus/omap_l3_noc.c b/drivers/bus/omap_l3_noc.c index 7743e86e88b1..7e0a988ad579 100644 --- a/drivers/bus/omap_l3_noc.c +++ b/drivers/bus/omap_l3_noc.c | |||
@@ -14,12 +14,14 @@ | |||
14 | * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | 14 | * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
15 | * GNU General Public License for more details. | 15 | * GNU General Public License for more details. |
16 | */ | 16 | */ |
17 | #include <linux/module.h> | ||
18 | #include <linux/init.h> | 17 | #include <linux/init.h> |
19 | #include <linux/io.h> | ||
20 | #include <linux/platform_device.h> | ||
21 | #include <linux/interrupt.h> | 18 | #include <linux/interrupt.h> |
19 | #include <linux/io.h> | ||
22 | #include <linux/kernel.h> | 20 | #include <linux/kernel.h> |
21 | #include <linux/module.h> | ||
22 | #include <linux/of_device.h> | ||
23 | #include <linux/of.h> | ||
24 | #include <linux/platform_device.h> | ||
23 | #include <linux/slab.h> | 25 | #include <linux/slab.h> |
24 | 26 | ||
25 | #include "omap_l3_noc.h" | 27 | #include "omap_l3_noc.h" |
@@ -58,17 +60,18 @@ static irqreturn_t l3_interrupt_handler(int irq, void *_l3) | |||
58 | void __iomem *l3_targ_stderr, *l3_targ_slvofslsb, *l3_targ_mstaddr; | 60 | void __iomem *l3_targ_stderr, *l3_targ_slvofslsb, *l3_targ_mstaddr; |
59 | char *target_name, *master_name = "UN IDENTIFIED"; | 61 | char *target_name, *master_name = "UN IDENTIFIED"; |
60 | struct l3_target_data *l3_targ_inst; | 62 | struct l3_target_data *l3_targ_inst; |
63 | struct l3_masters_data *master; | ||
61 | 64 | ||
62 | /* Get the Type of interrupt */ | 65 | /* Get the Type of interrupt */ |
63 | inttype = irq == l3->app_irq ? L3_APPLICATION_ERROR : L3_DEBUG_ERROR; | 66 | inttype = irq == l3->app_irq ? L3_APPLICATION_ERROR : L3_DEBUG_ERROR; |
64 | 67 | ||
65 | for (i = 0; i < L3_MODULES; i++) { | 68 | for (i = 0; i < l3->num_modules; i++) { |
66 | /* | 69 | /* |
67 | * Read the regerr register of the clock domain | 70 | * Read the regerr register of the clock domain |
68 | * to determine the source | 71 | * to determine the source |
69 | */ | 72 | */ |
70 | base = l3->l3_base[i]; | 73 | base = l3->l3_base[i]; |
71 | err_reg = readl_relaxed(base + l3_flagmux[i] + | 74 | err_reg = readl_relaxed(base + l3->l3_flagmux[i] + |
72 | L3_FLAGMUX_REGERR0 + (inttype << 3)); | 75 | L3_FLAGMUX_REGERR0 + (inttype << 3)); |
73 | 76 | ||
74 | /* Get the corresponding error and analyse */ | 77 | /* Get the corresponding error and analyse */ |
@@ -79,7 +82,7 @@ static irqreturn_t l3_interrupt_handler(int irq, void *_l3) | |||
79 | /* We DONOT expect err_src to go out of bounds */ | 82 | /* We DONOT expect err_src to go out of bounds */ |
80 | BUG_ON(err_src > MAX_CLKDM_TARGETS); | 83 | BUG_ON(err_src > MAX_CLKDM_TARGETS); |
81 | 84 | ||
82 | l3_targ_inst = &l3_targ[i][err_src]; | 85 | l3_targ_inst = &l3->l3_targ[i][err_src]; |
83 | target_name = l3_targ_inst->name; | 86 | target_name = l3_targ_inst->name; |
84 | l3_targ_base = base + l3_targ_inst->offset; | 87 | l3_targ_base = base + l3_targ_inst->offset; |
85 | 88 | ||
@@ -101,7 +104,7 @@ static irqreturn_t l3_interrupt_handler(int irq, void *_l3) | |||
101 | inttype ? "debug" : "application", | 104 | inttype ? "debug" : "application", |
102 | err_src, i, "(unclearable)"); | 105 | err_src, i, "(unclearable)"); |
103 | 106 | ||
104 | mask_reg = base + l3_flagmux[i] + | 107 | mask_reg = base + l3->l3_flagmux[i] + |
105 | L3_FLAGMUX_MASK0 + (inttype << 3); | 108 | L3_FLAGMUX_MASK0 + (inttype << 3); |
106 | mask_val = readl_relaxed(mask_reg); | 109 | mask_val = readl_relaxed(mask_reg); |
107 | mask_val &= ~(1 << err_src); | 110 | mask_val &= ~(1 << err_src); |
@@ -131,10 +134,12 @@ static irqreturn_t l3_interrupt_handler(int irq, void *_l3) | |||
131 | break; | 134 | break; |
132 | 135 | ||
133 | case CUSTOM_ERROR: | 136 | case CUSTOM_ERROR: |
134 | for (k = 0; k < NUM_OF_L3_MASTERS; k++) { | 137 | for (k = 0, master = l3->l3_masters; |
135 | if (masterid == l3_masters[k].id) | 138 | k < l3->num_masters; k++, master++) { |
136 | master_name = | 139 | if (masterid == master->id) { |
137 | l3_masters[k].name; | 140 | master_name = master->name; |
141 | break; | ||
142 | } | ||
138 | } | 143 | } |
139 | WARN(true, "L3 custom error: MASTER:%s TARGET:%s\n", | 144 | WARN(true, "L3 custom error: MASTER:%s TARGET:%s\n", |
140 | master_name, target_name); | 145 | master_name, target_name); |
@@ -154,20 +159,34 @@ static irqreturn_t l3_interrupt_handler(int irq, void *_l3) | |||
154 | return IRQ_HANDLED; | 159 | return IRQ_HANDLED; |
155 | } | 160 | } |
156 | 161 | ||
162 | static const struct of_device_id l3_noc_match[] = { | ||
163 | {.compatible = "ti,omap4-l3-noc", .data = &omap_l3_data}, | ||
164 | {}, | ||
165 | }; | ||
166 | MODULE_DEVICE_TABLE(of, l3_noc_match); | ||
167 | |||
157 | static int omap_l3_probe(struct platform_device *pdev) | 168 | static int omap_l3_probe(struct platform_device *pdev) |
158 | { | 169 | { |
170 | const struct of_device_id *of_id; | ||
159 | static struct omap_l3 *l3; | 171 | static struct omap_l3 *l3; |
160 | int ret, i; | 172 | int ret, i; |
161 | 173 | ||
174 | of_id = of_match_device(l3_noc_match, &pdev->dev); | ||
175 | if (!of_id) { | ||
176 | dev_err(&pdev->dev, "OF data missing\n"); | ||
177 | return -EINVAL; | ||
178 | } | ||
179 | |||
162 | l3 = devm_kzalloc(&pdev->dev, sizeof(*l3), GFP_KERNEL); | 180 | l3 = devm_kzalloc(&pdev->dev, sizeof(*l3), GFP_KERNEL); |
163 | if (!l3) | 181 | if (!l3) |
164 | return -ENOMEM; | 182 | return -ENOMEM; |
165 | 183 | ||
184 | memcpy(l3, of_id->data, sizeof(*l3)); | ||
166 | l3->dev = &pdev->dev; | 185 | l3->dev = &pdev->dev; |
167 | platform_set_drvdata(pdev, l3); | 186 | platform_set_drvdata(pdev, l3); |
168 | 187 | ||
169 | /* Get mem resources */ | 188 | /* Get mem resources */ |
170 | for (i = 0; i < L3_MODULES; i++) { | 189 | for (i = 0; i < l3->num_modules; i++) { |
171 | struct resource *res = platform_get_resource(pdev, | 190 | struct resource *res = platform_get_resource(pdev, |
172 | IORESOURCE_MEM, i); | 191 | IORESOURCE_MEM, i); |
173 | 192 | ||
@@ -199,22 +218,12 @@ static int omap_l3_probe(struct platform_device *pdev) | |||
199 | return ret; | 218 | return ret; |
200 | } | 219 | } |
201 | 220 | ||
202 | #if defined(CONFIG_OF) | ||
203 | static const struct of_device_id l3_noc_match[] = { | ||
204 | {.compatible = "ti,omap4-l3-noc", }, | ||
205 | {}, | ||
206 | }; | ||
207 | MODULE_DEVICE_TABLE(of, l3_noc_match); | ||
208 | #else | ||
209 | #define l3_noc_match NULL | ||
210 | #endif | ||
211 | |||
212 | static struct platform_driver omap_l3_driver = { | 221 | static struct platform_driver omap_l3_driver = { |
213 | .probe = omap_l3_probe, | 222 | .probe = omap_l3_probe, |
214 | .driver = { | 223 | .driver = { |
215 | .name = "omap_l3_noc", | 224 | .name = "omap_l3_noc", |
216 | .owner = THIS_MODULE, | 225 | .owner = THIS_MODULE, |
217 | .of_match_table = l3_noc_match, | 226 | .of_match_table = of_match_ptr(l3_noc_match), |
218 | }, | 227 | }, |
219 | }; | 228 | }; |
220 | 229 | ||
diff --git a/drivers/bus/omap_l3_noc.h b/drivers/bus/omap_l3_noc.h index 66caeceaf123..e60865fe5965 100644 --- a/drivers/bus/omap_l3_noc.h +++ b/drivers/bus/omap_l3_noc.h | |||
@@ -17,7 +17,9 @@ | |||
17 | #ifndef __OMAP_L3_NOC_H | 17 | #ifndef __OMAP_L3_NOC_H |
18 | #define __OMAP_L3_NOC_H | 18 | #define __OMAP_L3_NOC_H |
19 | 19 | ||
20 | #define L3_MODULES 3 | 20 | #define OMAP_L3_MODULES 3 |
21 | #define MAX_L3_MODULES 3 | ||
22 | |||
21 | #define CLEAR_STDERR_LOG (1 << 31) | 23 | #define CLEAR_STDERR_LOG (1 << 31) |
22 | #define CUSTOM_ERROR 0x2 | 24 | #define CUSTOM_ERROR 0x2 |
23 | #define STANDARD_ERROR 0x0 | 25 | #define STANDARD_ERROR 0x0 |
@@ -36,8 +38,6 @@ | |||
36 | 38 | ||
37 | #define MAX_CLKDM_TARGETS 31 | 39 | #define MAX_CLKDM_TARGETS 31 |
38 | 40 | ||
39 | #define NUM_OF_L3_MASTERS (sizeof(l3_masters)/sizeof(l3_masters[0])) | ||
40 | |||
41 | /** | 41 | /** |
42 | * struct l3_masters_data - L3 Master information | 42 | * struct l3_masters_data - L3 Master information |
43 | * @id: ID of the L3 Master | 43 | * @id: ID of the L3 Master |
@@ -60,13 +60,47 @@ struct l3_target_data { | |||
60 | char *name; | 60 | char *name; |
61 | }; | 61 | }; |
62 | 62 | ||
63 | static u32 l3_flagmux[L3_MODULES] = { | 63 | |
64 | /** | ||
65 | * struct omap_l3 - Description of data relevant for L3 bus. | ||
66 | * @dev: device representing the bus (populated runtime) | ||
67 | * @l3_base: base addresses of modules (populated runtime) | ||
68 | * @l3_flag_mux: array containing offsets to flag mux per module | ||
69 | * offset from corresponding module base indexed per | ||
70 | * module. | ||
71 | * @num_modules: number of clock domains / modules. | ||
72 | * @l3_masters: array pointing to master data containing name and register | ||
73 | * offset for the master. | ||
74 | * @num_master: number of masters | ||
75 | * @l3_targ: array indexed by flagmux index (bit offset) pointing to the | ||
76 | * target data. unsupported ones are marked with | ||
77 | * L3_TARGET_NOT_SUPPORTED | ||
78 | * @debug_irq: irq number of the debug interrupt (populated runtime) | ||
79 | * @app_irq: irq number of the application interrupt (populated runtime) | ||
80 | */ | ||
81 | struct omap_l3 { | ||
82 | struct device *dev; | ||
83 | |||
84 | void __iomem *l3_base[MAX_L3_MODULES]; | ||
85 | u32 *l3_flagmux; | ||
86 | int num_modules; | ||
87 | |||
88 | struct l3_masters_data *l3_masters; | ||
89 | int num_masters; | ||
90 | |||
91 | struct l3_target_data **l3_targ; | ||
92 | |||
93 | int debug_irq; | ||
94 | int app_irq; | ||
95 | }; | ||
96 | |||
97 | static u32 omap_l3_flagmux[OMAP_L3_MODULES] = { | ||
64 | 0x500, | 98 | 0x500, |
65 | 0x1000, | 99 | 0x1000, |
66 | 0X0200 | 100 | 0X0200 |
67 | }; | 101 | }; |
68 | 102 | ||
69 | static struct l3_target_data l3_target_inst_data_clk1[MAX_CLKDM_TARGETS] = { | 103 | static struct l3_target_data omap_l3_target_data_clk1[MAX_CLKDM_TARGETS] = { |
70 | {0x100, "DMM1",}, | 104 | {0x100, "DMM1",}, |
71 | {0x200, "DMM2",}, | 105 | {0x200, "DMM2",}, |
72 | {0x300, "ABE",}, | 106 | {0x300, "ABE",}, |
@@ -76,7 +110,7 @@ static struct l3_target_data l3_target_inst_data_clk1[MAX_CLKDM_TARGETS] = { | |||
76 | {0x900, "L4WAKEUP",}, | 110 | {0x900, "L4WAKEUP",}, |
77 | }; | 111 | }; |
78 | 112 | ||
79 | static struct l3_target_data l3_target_inst_data_clk2[MAX_CLKDM_TARGETS] = { | 113 | static struct l3_target_data omap_l3_target_data_clk2[MAX_CLKDM_TARGETS] = { |
80 | {0x500, "CORTEXM3",}, | 114 | {0x500, "CORTEXM3",}, |
81 | {0x300, "DSS",}, | 115 | {0x300, "DSS",}, |
82 | {0x100, "GPMC",}, | 116 | {0x100, "GPMC",}, |
@@ -100,13 +134,13 @@ static struct l3_target_data l3_target_inst_data_clk2[MAX_CLKDM_TARGETS] = { | |||
100 | {0x1700, "LLI",}, | 134 | {0x1700, "LLI",}, |
101 | }; | 135 | }; |
102 | 136 | ||
103 | static struct l3_target_data l3_target_inst_data_clk3[MAX_CLKDM_TARGETS] = { | 137 | static struct l3_target_data omap_l3_target_data_clk3[MAX_CLKDM_TARGETS] = { |
104 | {0x0100, "EMUSS",}, | 138 | {0x0100, "EMUSS",}, |
105 | {0x0300, "DEBUG SOURCE",}, | 139 | {0x0300, "DEBUG SOURCE",}, |
106 | {0x0, "HOST CLK3",}, | 140 | {0x0, "HOST CLK3",}, |
107 | }; | 141 | }; |
108 | 142 | ||
109 | static struct l3_masters_data l3_masters[] = { | 143 | static struct l3_masters_data omap_l3_masters[] = { |
110 | { 0x0 , "MPU"}, | 144 | { 0x0 , "MPU"}, |
111 | { 0x10, "CS_ADP"}, | 145 | { 0x10, "CS_ADP"}, |
112 | { 0x14, "xxx"}, | 146 | { 0x14, "xxx"}, |
@@ -134,20 +168,18 @@ static struct l3_masters_data l3_masters[] = { | |||
134 | { 0xC8, "USBHOSTFS"} | 168 | { 0xC8, "USBHOSTFS"} |
135 | }; | 169 | }; |
136 | 170 | ||
137 | static struct l3_target_data *l3_targ[L3_MODULES] = { | 171 | static struct l3_target_data *omap_l3_targ[OMAP_L3_MODULES] = { |
138 | l3_target_inst_data_clk1, | 172 | omap_l3_target_data_clk1, |
139 | l3_target_inst_data_clk2, | 173 | omap_l3_target_data_clk2, |
140 | l3_target_inst_data_clk3, | 174 | omap_l3_target_data_clk3, |
141 | }; | 175 | }; |
142 | 176 | ||
143 | struct omap_l3 { | 177 | static const struct omap_l3 omap_l3_data = { |
144 | struct device *dev; | 178 | .l3_flagmux = omap_l3_flagmux, |
145 | 179 | .num_modules = OMAP_L3_MODULES, | |
146 | /* memory base */ | 180 | .l3_masters = omap_l3_masters, |
147 | void __iomem *l3_base[L3_MODULES]; | 181 | .num_masters = ARRAY_SIZE(omap_l3_masters), |
148 | 182 | .l3_targ = omap_l3_targ, | |
149 | int debug_irq; | ||
150 | int app_irq; | ||
151 | }; | 183 | }; |
152 | 184 | ||
153 | #endif /* __OMAP_L3_NOC_H */ | 185 | #endif /* __OMAP_L3_NOC_H */ |