diff options
-rw-r--r-- | arch/sparc64/kernel/chmc.c | 237 |
1 files changed, 120 insertions, 117 deletions
diff --git a/arch/sparc64/kernel/chmc.c b/arch/sparc64/kernel/chmc.c index b9cd736a11f7..2f73ddc8676d 100644 --- a/arch/sparc64/kernel/chmc.c +++ b/arch/sparc64/kernel/chmc.c | |||
@@ -35,35 +35,35 @@ MODULE_VERSION(DRV_MODULE_VERSION); | |||
35 | #define CHMCTRL_NDGRPS 2 | 35 | #define CHMCTRL_NDGRPS 2 |
36 | #define CHMCTRL_NDIMMS 4 | 36 | #define CHMCTRL_NDIMMS 4 |
37 | 37 | ||
38 | #define DIMMS_PER_MC (CHMCTRL_NDGRPS * CHMCTRL_NDIMMS) | 38 | #define CHMC_DIMMS_PER_MC (CHMCTRL_NDGRPS * CHMCTRL_NDIMMS) |
39 | 39 | ||
40 | /* OBP memory-layout property format. */ | 40 | /* OBP memory-layout property format. */ |
41 | struct obp_map { | 41 | struct chmc_obp_map { |
42 | unsigned char dimm_map[144]; | 42 | unsigned char dimm_map[144]; |
43 | unsigned char pin_map[576]; | 43 | unsigned char pin_map[576]; |
44 | }; | 44 | }; |
45 | 45 | ||
46 | #define DIMM_LABEL_SZ 8 | 46 | #define DIMM_LABEL_SZ 8 |
47 | 47 | ||
48 | struct obp_mem_layout { | 48 | struct chmc_obp_mem_layout { |
49 | /* One max 8-byte string label per DIMM. Usually | 49 | /* One max 8-byte string label per DIMM. Usually |
50 | * this matches the label on the motherboard where | 50 | * this matches the label on the motherboard where |
51 | * that DIMM resides. | 51 | * that DIMM resides. |
52 | */ | 52 | */ |
53 | char dimm_labels[DIMMS_PER_MC][DIMM_LABEL_SZ]; | 53 | char dimm_labels[CHMC_DIMMS_PER_MC][DIMM_LABEL_SZ]; |
54 | 54 | ||
55 | /* If symmetric use map[0], else it is | 55 | /* If symmetric use map[0], else it is |
56 | * asymmetric and map[1] should be used. | 56 | * asymmetric and map[1] should be used. |
57 | */ | 57 | */ |
58 | char symmetric; | 58 | char symmetric; |
59 | 59 | ||
60 | struct obp_map map[2]; | 60 | struct chmc_obp_map map[2]; |
61 | }; | 61 | }; |
62 | 62 | ||
63 | #define CHMCTRL_NBANKS 4 | 63 | #define CHMCTRL_NBANKS 4 |
64 | 64 | ||
65 | struct bank_info { | 65 | struct chmc_bank_info { |
66 | struct mctrl_info *mp; | 66 | struct chmc *p; |
67 | int bank_id; | 67 | int bank_id; |
68 | 68 | ||
69 | u64 raw_reg; | 69 | u64 raw_reg; |
@@ -77,28 +77,28 @@ struct bank_info { | |||
77 | unsigned long size; | 77 | unsigned long size; |
78 | }; | 78 | }; |
79 | 79 | ||
80 | struct mctrl_info { | 80 | struct chmc { |
81 | struct list_head list; | 81 | struct list_head list; |
82 | int portid; | 82 | int portid; |
83 | 83 | ||
84 | struct obp_mem_layout layout_prop; | 84 | struct chmc_obp_mem_layout layout_prop; |
85 | int layout_size; | 85 | int layout_size; |
86 | 86 | ||
87 | void __iomem *regs; | 87 | void __iomem *regs; |
88 | 88 | ||
89 | u64 timing_control1; | 89 | u64 timing_control1; |
90 | u64 timing_control2; | 90 | u64 timing_control2; |
91 | u64 timing_control3; | 91 | u64 timing_control3; |
92 | u64 timing_control4; | 92 | u64 timing_control4; |
93 | u64 memaddr_control; | 93 | u64 memaddr_control; |
94 | 94 | ||
95 | struct bank_info logical_banks[CHMCTRL_NBANKS]; | 95 | struct chmc_bank_info logical_banks[CHMCTRL_NBANKS]; |
96 | }; | 96 | }; |
97 | 97 | ||
98 | static LIST_HEAD(mctrl_list); | 98 | static LIST_HEAD(mctrl_list); |
99 | 99 | ||
100 | /* Does BANK decode PHYS_ADDR? */ | 100 | /* Does BANK decode PHYS_ADDR? */ |
101 | static int bank_match(struct bank_info *bp, unsigned long phys_addr) | 101 | static int chmc_bank_match(struct chmc_bank_info *bp, unsigned long phys_addr) |
102 | { | 102 | { |
103 | unsigned long upper_bits = (phys_addr & PA_UPPER_BITS) >> PA_UPPER_BITS_SHIFT; | 103 | unsigned long upper_bits = (phys_addr & PA_UPPER_BITS) >> PA_UPPER_BITS_SHIFT; |
104 | unsigned long lower_bits = (phys_addr & PA_LOWER_BITS) >> PA_LOWER_BITS_SHIFT; | 104 | unsigned long lower_bits = (phys_addr & PA_LOWER_BITS) >> PA_LOWER_BITS_SHIFT; |
@@ -130,14 +130,13 @@ static int bank_match(struct bank_info *bp, unsigned long phys_addr) | |||
130 | } | 130 | } |
131 | 131 | ||
132 | /* Given PHYS_ADDR, search memory controller banks for a match. */ | 132 | /* Given PHYS_ADDR, search memory controller banks for a match. */ |
133 | static struct bank_info *find_bank(unsigned long phys_addr) | 133 | static struct chmc_bank_info *chmc_find_bank(unsigned long phys_addr) |
134 | { | 134 | { |
135 | struct list_head *mctrl_head = &mctrl_list; | 135 | struct list_head *mctrl_head = &mctrl_list; |
136 | struct list_head *mctrl_entry = mctrl_head->next; | 136 | struct list_head *mctrl_entry = mctrl_head->next; |
137 | 137 | ||
138 | for (;;) { | 138 | for (;;) { |
139 | struct mctrl_info *mp = | 139 | struct chmc *p = list_entry(mctrl_entry, struct chmc, list); |
140 | list_entry(mctrl_entry, struct mctrl_info, list); | ||
141 | int bank_no; | 140 | int bank_no; |
142 | 141 | ||
143 | if (mctrl_entry == mctrl_head) | 142 | if (mctrl_entry == mctrl_head) |
@@ -145,10 +144,10 @@ static struct bank_info *find_bank(unsigned long phys_addr) | |||
145 | mctrl_entry = mctrl_entry->next; | 144 | mctrl_entry = mctrl_entry->next; |
146 | 145 | ||
147 | for (bank_no = 0; bank_no < CHMCTRL_NBANKS; bank_no++) { | 146 | for (bank_no = 0; bank_no < CHMCTRL_NBANKS; bank_no++) { |
148 | struct bank_info *bp; | 147 | struct chmc_bank_info *bp; |
149 | 148 | ||
150 | bp = &mp->logical_banks[bank_no]; | 149 | bp = &p->logical_banks[bank_no]; |
151 | if (bank_match(bp, phys_addr)) | 150 | if (chmc_bank_match(bp, phys_addr)) |
152 | return bp; | 151 | return bp; |
153 | } | 152 | } |
154 | } | 153 | } |
@@ -163,11 +162,11 @@ int chmc_getunumber(int syndrome_code, | |||
163 | unsigned long phys_addr, | 162 | unsigned long phys_addr, |
164 | char *buf, int buflen) | 163 | char *buf, int buflen) |
165 | { | 164 | { |
166 | struct bank_info *bp; | 165 | struct chmc_bank_info *bp; |
167 | struct obp_mem_layout *prop; | 166 | struct chmc_obp_mem_layout *prop; |
168 | int bank_in_controller, first_dimm; | 167 | int bank_in_controller, first_dimm; |
169 | 168 | ||
170 | bp = find_bank(phys_addr); | 169 | bp = chmc_find_bank(phys_addr); |
171 | if (bp == NULL || | 170 | if (bp == NULL || |
172 | syndrome_code < SYNDROME_MIN || | 171 | syndrome_code < SYNDROME_MIN || |
173 | syndrome_code > SYNDROME_MAX) { | 172 | syndrome_code > SYNDROME_MAX) { |
@@ -178,13 +177,13 @@ int chmc_getunumber(int syndrome_code, | |||
178 | return 0; | 177 | return 0; |
179 | } | 178 | } |
180 | 179 | ||
181 | prop = &bp->mp->layout_prop; | 180 | prop = &bp->p->layout_prop; |
182 | bank_in_controller = bp->bank_id & (CHMCTRL_NBANKS - 1); | 181 | bank_in_controller = bp->bank_id & (CHMCTRL_NBANKS - 1); |
183 | first_dimm = (bank_in_controller & (CHMCTRL_NDGRPS - 1)); | 182 | first_dimm = (bank_in_controller & (CHMCTRL_NDGRPS - 1)); |
184 | first_dimm *= CHMCTRL_NDIMMS; | 183 | first_dimm *= CHMCTRL_NDIMMS; |
185 | 184 | ||
186 | if (syndrome_code != SYNDROME_MIN) { | 185 | if (syndrome_code != SYNDROME_MIN) { |
187 | struct obp_map *map; | 186 | struct chmc_obp_map *map; |
188 | int qword, where_in_line, where, map_index, map_offset; | 187 | int qword, where_in_line, where, map_index, map_offset; |
189 | unsigned int map_val; | 188 | unsigned int map_val; |
190 | 189 | ||
@@ -252,7 +251,7 @@ int chmc_getunumber(int syndrome_code, | |||
252 | * the code is executing, you must use special ASI load/store else | 251 | * the code is executing, you must use special ASI load/store else |
253 | * you go through the global mapping. | 252 | * you go through the global mapping. |
254 | */ | 253 | */ |
255 | static u64 read_mcreg(struct mctrl_info *mp, unsigned long offset) | 254 | static u64 chmc_read_mcreg(struct chmc *p, unsigned long offset) |
256 | { | 255 | { |
257 | unsigned long ret, this_cpu; | 256 | unsigned long ret, this_cpu; |
258 | 257 | ||
@@ -260,14 +259,14 @@ static u64 read_mcreg(struct mctrl_info *mp, unsigned long offset) | |||
260 | 259 | ||
261 | this_cpu = real_hard_smp_processor_id(); | 260 | this_cpu = real_hard_smp_processor_id(); |
262 | 261 | ||
263 | if (mp->portid == this_cpu) { | 262 | if (p->portid == this_cpu) { |
264 | __asm__ __volatile__("ldxa [%1] %2, %0" | 263 | __asm__ __volatile__("ldxa [%1] %2, %0" |
265 | : "=r" (ret) | 264 | : "=r" (ret) |
266 | : "r" (offset), "i" (ASI_MCU_CTRL_REG)); | 265 | : "r" (offset), "i" (ASI_MCU_CTRL_REG)); |
267 | } else { | 266 | } else { |
268 | __asm__ __volatile__("ldxa [%1] %2, %0" | 267 | __asm__ __volatile__("ldxa [%1] %2, %0" |
269 | : "=r" (ret) | 268 | : "=r" (ret) |
270 | : "r" (mp->regs + offset), | 269 | : "r" (p->regs + offset), |
271 | "i" (ASI_PHYS_BYPASS_EC_E)); | 270 | "i" (ASI_PHYS_BYPASS_EC_E)); |
272 | } | 271 | } |
273 | 272 | ||
@@ -277,164 +276,168 @@ static u64 read_mcreg(struct mctrl_info *mp, unsigned long offset) | |||
277 | } | 276 | } |
278 | 277 | ||
279 | #if 0 /* currently unused */ | 278 | #if 0 /* currently unused */ |
280 | static void write_mcreg(struct mctrl_info *mp, unsigned long offset, u64 val) | 279 | static void chmc_write_mcreg(struct chmc *p, unsigned long offset, u64 val) |
281 | { | 280 | { |
282 | if (mp->portid == smp_processor_id()) { | 281 | if (p->portid == smp_processor_id()) { |
283 | __asm__ __volatile__("stxa %0, [%1] %2" | 282 | __asm__ __volatile__("stxa %0, [%1] %2" |
284 | : : "r" (val), | 283 | : : "r" (val), |
285 | "r" (offset), "i" (ASI_MCU_CTRL_REG)); | 284 | "r" (offset), "i" (ASI_MCU_CTRL_REG)); |
286 | } else { | 285 | } else { |
287 | __asm__ __volatile__("ldxa %0, [%1] %2" | 286 | __asm__ __volatile__("ldxa %0, [%1] %2" |
288 | : : "r" (val), | 287 | : : "r" (val), |
289 | "r" (mp->regs + offset), | 288 | "r" (p->regs + offset), |
290 | "i" (ASI_PHYS_BYPASS_EC_E)); | 289 | "i" (ASI_PHYS_BYPASS_EC_E)); |
291 | } | 290 | } |
292 | } | 291 | } |
293 | #endif | 292 | #endif |
294 | 293 | ||
295 | static void interpret_one_decode_reg(struct mctrl_info *mp, int which_bank, u64 val) | 294 | static void chmc_interpret_one_decode_reg(struct chmc *p, int which_bank, u64 val) |
296 | { | 295 | { |
297 | struct bank_info *p = &mp->logical_banks[which_bank]; | 296 | struct chmc_bank_info *bp = &p->logical_banks[which_bank]; |
298 | 297 | ||
299 | p->mp = mp; | 298 | bp->p = p; |
300 | p->bank_id = (CHMCTRL_NBANKS * mp->portid) + which_bank; | 299 | bp->bank_id = (CHMCTRL_NBANKS * p->portid) + which_bank; |
301 | p->raw_reg = val; | 300 | bp->raw_reg = val; |
302 | p->valid = (val & MEM_DECODE_VALID) >> MEM_DECODE_VALID_SHIFT; | 301 | bp->valid = (val & MEM_DECODE_VALID) >> MEM_DECODE_VALID_SHIFT; |
303 | p->uk = (val & MEM_DECODE_UK) >> MEM_DECODE_UK_SHIFT; | 302 | bp->uk = (val & MEM_DECODE_UK) >> MEM_DECODE_UK_SHIFT; |
304 | p->um = (val & MEM_DECODE_UM) >> MEM_DECODE_UM_SHIFT; | 303 | bp->um = (val & MEM_DECODE_UM) >> MEM_DECODE_UM_SHIFT; |
305 | p->lk = (val & MEM_DECODE_LK) >> MEM_DECODE_LK_SHIFT; | 304 | bp->lk = (val & MEM_DECODE_LK) >> MEM_DECODE_LK_SHIFT; |
306 | p->lm = (val & MEM_DECODE_LM) >> MEM_DECODE_LM_SHIFT; | 305 | bp->lm = (val & MEM_DECODE_LM) >> MEM_DECODE_LM_SHIFT; |
307 | 306 | ||
308 | p->base = (p->um); | 307 | bp->base = (bp->um); |
309 | p->base &= ~(p->uk); | 308 | bp->base &= ~(bp->uk); |
310 | p->base <<= PA_UPPER_BITS_SHIFT; | 309 | bp->base <<= PA_UPPER_BITS_SHIFT; |
311 | 310 | ||
312 | switch(p->lk) { | 311 | switch(bp->lk) { |
313 | case 0xf: | 312 | case 0xf: |
314 | default: | 313 | default: |
315 | p->interleave = 1; | 314 | bp->interleave = 1; |
316 | break; | 315 | break; |
317 | 316 | ||
318 | case 0xe: | 317 | case 0xe: |
319 | p->interleave = 2; | 318 | bp->interleave = 2; |
320 | break; | 319 | break; |
321 | 320 | ||
322 | case 0xc: | 321 | case 0xc: |
323 | p->interleave = 4; | 322 | bp->interleave = 4; |
324 | break; | 323 | break; |
325 | 324 | ||
326 | case 0x8: | 325 | case 0x8: |
327 | p->interleave = 8; | 326 | bp->interleave = 8; |
328 | break; | 327 | break; |
329 | 328 | ||
330 | case 0x0: | 329 | case 0x0: |
331 | p->interleave = 16; | 330 | bp->interleave = 16; |
332 | break; | 331 | break; |
333 | }; | 332 | }; |
334 | 333 | ||
335 | /* UK[10] is reserved, and UK[11] is not set for the SDRAM | 334 | /* UK[10] is reserved, and UK[11] is not set for the SDRAM |
336 | * bank size definition. | 335 | * bank size definition. |
337 | */ | 336 | */ |
338 | p->size = (((unsigned long)p->uk & | 337 | bp->size = (((unsigned long)bp->uk & |
339 | ((1UL << 10UL) - 1UL)) + 1UL) << PA_UPPER_BITS_SHIFT; | 338 | ((1UL << 10UL) - 1UL)) + 1UL) << PA_UPPER_BITS_SHIFT; |
340 | p->size /= p->interleave; | 339 | bp->size /= bp->interleave; |
341 | } | 340 | } |
342 | 341 | ||
343 | static void fetch_decode_regs(struct mctrl_info *mp) | 342 | static void chmc_fetch_decode_regs(struct chmc *p) |
344 | { | 343 | { |
345 | if (mp->layout_size == 0) | 344 | if (p->layout_size == 0) |
346 | return; | 345 | return; |
347 | 346 | ||
348 | interpret_one_decode_reg(mp, 0, | 347 | chmc_interpret_one_decode_reg(p, 0, |
349 | read_mcreg(mp, CHMCTRL_DECODE1)); | 348 | chmc_read_mcreg(p, CHMCTRL_DECODE1)); |
350 | interpret_one_decode_reg(mp, 1, | 349 | chmc_interpret_one_decode_reg(p, 1, |
351 | read_mcreg(mp, CHMCTRL_DECODE2)); | 350 | chmc_read_mcreg(p, CHMCTRL_DECODE2)); |
352 | interpret_one_decode_reg(mp, 2, | 351 | chmc_interpret_one_decode_reg(p, 2, |
353 | read_mcreg(mp, CHMCTRL_DECODE3)); | 352 | chmc_read_mcreg(p, CHMCTRL_DECODE3)); |
354 | interpret_one_decode_reg(mp, 3, | 353 | chmc_interpret_one_decode_reg(p, 3, |
355 | read_mcreg(mp, CHMCTRL_DECODE4)); | 354 | chmc_read_mcreg(p, CHMCTRL_DECODE4)); |
356 | } | 355 | } |
357 | 356 | ||
358 | static int __devinit chmc_probe(struct of_device *op, | 357 | static int __devinit chmc_probe(struct of_device *op, |
359 | const struct of_device_id *match) | 358 | const struct of_device_id *match) |
360 | { | 359 | { |
361 | struct device_node *dp = op->node; | 360 | struct device_node *dp = op->node; |
362 | struct mctrl_info *mp; | ||
363 | unsigned long ver; | 361 | unsigned long ver; |
364 | const void *pval; | 362 | const void *pval; |
365 | int len, portid; | 363 | int len, portid; |
364 | struct chmc *p; | ||
365 | int err; | ||
366 | 366 | ||
367 | err = -ENODEV; | ||
367 | __asm__ ("rdpr %%ver, %0" : "=r" (ver)); | 368 | __asm__ ("rdpr %%ver, %0" : "=r" (ver)); |
368 | if ((ver >> 32UL) == __JALAPENO_ID || | 369 | if ((ver >> 32UL) == __JALAPENO_ID || |
369 | (ver >> 32UL) == __SERRANO_ID) | 370 | (ver >> 32UL) == __SERRANO_ID) |
370 | return -ENODEV; | 371 | goto out; |
371 | |||
372 | mp = kzalloc(sizeof(*mp), GFP_KERNEL); | ||
373 | if (!mp) | ||
374 | return -ENOMEM; | ||
375 | 372 | ||
376 | portid = of_getintprop_default(dp, "portid", -1); | 373 | portid = of_getintprop_default(dp, "portid", -1); |
377 | if (portid == -1) | 374 | if (portid == -1) |
378 | goto fail; | 375 | goto out; |
379 | 376 | ||
380 | mp->portid = portid; | ||
381 | pval = of_get_property(dp, "memory-layout", &len); | 377 | pval = of_get_property(dp, "memory-layout", &len); |
382 | mp->layout_size = len; | 378 | if (pval && len > sizeof(p->layout_prop)) { |
383 | if (!pval) | 379 | printk(KERN_ERR PFX "Unexpected memory-layout property " |
384 | mp->layout_size = 0; | 380 | "size %d.\n", len); |
385 | else { | 381 | goto out; |
386 | if (mp->layout_size > sizeof(mp->layout_prop)) { | 382 | } |
387 | printk(KERN_ERR PFX "Unexpected memory-layout property " | 383 | |
388 | "size %d.\n", mp->layout_size); | 384 | err = -ENOMEM; |
389 | goto fail; | 385 | p = kzalloc(sizeof(*p), GFP_KERNEL); |
390 | } | 386 | if (!p) { |
391 | memcpy(&mp->layout_prop, pval, len); | 387 | printk(KERN_ERR PFX "Could not allocate struct chmc.\n"); |
388 | goto out; | ||
392 | } | 389 | } |
393 | 390 | ||
394 | mp->regs = of_ioremap(&op->resource[0], 0, 0x48, "chmc"); | 391 | p->portid = portid; |
395 | if (!mp->regs) { | 392 | p->layout_size = len; |
393 | if (!pval) | ||
394 | p->layout_size = 0; | ||
395 | else | ||
396 | memcpy(&p->layout_prop, pval, len); | ||
397 | |||
398 | p->regs = of_ioremap(&op->resource[0], 0, 0x48, "chmc"); | ||
399 | if (!p->regs) { | ||
396 | printk(KERN_ERR PFX "Could not map registers.\n"); | 400 | printk(KERN_ERR PFX "Could not map registers.\n"); |
397 | goto fail; | 401 | goto out_free; |
398 | } | 402 | } |
399 | 403 | ||
400 | if (mp->layout_size != 0UL) { | 404 | if (p->layout_size != 0UL) { |
401 | mp->timing_control1 = read_mcreg(mp, CHMCTRL_TCTRL1); | 405 | p->timing_control1 = chmc_read_mcreg(p, CHMCTRL_TCTRL1); |
402 | mp->timing_control2 = read_mcreg(mp, CHMCTRL_TCTRL2); | 406 | p->timing_control2 = chmc_read_mcreg(p, CHMCTRL_TCTRL2); |
403 | mp->timing_control3 = read_mcreg(mp, CHMCTRL_TCTRL3); | 407 | p->timing_control3 = chmc_read_mcreg(p, CHMCTRL_TCTRL3); |
404 | mp->timing_control4 = read_mcreg(mp, CHMCTRL_TCTRL4); | 408 | p->timing_control4 = chmc_read_mcreg(p, CHMCTRL_TCTRL4); |
405 | mp->memaddr_control = read_mcreg(mp, CHMCTRL_MACTRL); | 409 | p->memaddr_control = chmc_read_mcreg(p, CHMCTRL_MACTRL); |
406 | } | 410 | } |
407 | 411 | ||
408 | fetch_decode_regs(mp); | 412 | chmc_fetch_decode_regs(p); |
409 | 413 | ||
410 | list_add(&mp->list, &mctrl_list); | 414 | list_add(&p->list, &mctrl_list); |
411 | 415 | ||
412 | /* Report the device. */ | 416 | /* Report the device. */ |
413 | printk(KERN_INFO PFX "UltraSPARC-III memory controller at %s [%s]\n", | 417 | printk(KERN_INFO PFX "UltraSPARC-III memory controller at %s [%s]\n", |
414 | dp->full_name, | 418 | dp->full_name, |
415 | (mp->layout_size ? "ACTIVE" : "INACTIVE")); | 419 | (p->layout_size ? "ACTIVE" : "INACTIVE")); |
416 | 420 | ||
417 | dev_set_drvdata(&op->dev, mp); | 421 | dev_set_drvdata(&op->dev, p); |
418 | 422 | ||
419 | return 0; | 423 | err = 0; |
420 | 424 | ||
421 | fail: | 425 | out: |
422 | if (mp) { | 426 | return err; |
423 | if (mp->regs != NULL) | 427 | |
424 | of_iounmap(&op->resource[0], mp->regs, 0x48); | 428 | out_free: |
425 | kfree(mp); | 429 | kfree(p); |
426 | } | 430 | goto out; |
427 | return -1; | ||
428 | } | 431 | } |
429 | 432 | ||
430 | static int __devexit chmc_remove(struct of_device *op) | 433 | static int __devexit chmc_remove(struct of_device *op) |
431 | { | 434 | { |
432 | struct mctrl_info *mp = dev_get_drvdata(&op->dev); | 435 | struct chmc *p = dev_get_drvdata(&op->dev); |
433 | 436 | ||
434 | if (mp) { | 437 | if (p) { |
435 | list_del(&mp->list); | 438 | list_del(&p->list); |
436 | of_iounmap(&op->resource[0], mp->regs, 0x48); | 439 | of_iounmap(&op->resource[0], p->regs, 0x48); |
437 | kfree(mp); | 440 | kfree(p); |
438 | } | 441 | } |
439 | return 0; | 442 | return 0; |
440 | } | 443 | } |