Linux Audio

Check our new training course

Loading...
Note: File does not exist in v4.6.
  1/*
  2 * S3C series device definition for nand device
  3 *
  4 * This program is free software; you can redistribute it and/or modify
  5 * it under the terms of the GNU General Public License version 2 as
  6 * published by the Free Software Foundation.
  7*/
  8
  9#include <linux/gfp.h>
 10#include <linux/kernel.h>
 11#include <linux/platform_device.h>
 12
 13#include <linux/mtd/mtd.h>
 14#include <linux/mtd/partitions.h>
 15
 16#include <mach/map.h>
 17#include <plat/devs.h>
 18#include <plat/nand.h>
 19
 20static struct resource s3c_nand_resource[] = {
 21	[0] = {
 22		.start = S3C_PA_NAND,
 23		.end   = S3C_PA_NAND + SZ_1M,
 24		.flags = IORESOURCE_MEM,
 25	}
 26};
 27
 28struct platform_device s3c_device_nand = {
 29	.name		  = "s3c2410-nand",
 30	.id		  = -1,
 31	.num_resources	  = ARRAY_SIZE(s3c_nand_resource),
 32	.resource	  = s3c_nand_resource,
 33};
 34
 35EXPORT_SYMBOL(s3c_device_nand);
 36
 37/**
 38 * s3c_nand_copy_set() - copy nand set data
 39 * @set: The new structure, directly copied from the old.
 40 *
 41 * Copy all the fields from the NAND set field from what is probably __initdata
 42 * to new kernel memory. The code returns 0 if the copy happened correctly or
 43 * an error code for the calling function to display.
 44 *
 45 * Note, we currently do not try and look to see if we've already copied the
 46 * data in a previous set.
 47 */
 48static int __init s3c_nand_copy_set(struct s3c2410_nand_set *set)
 49{
 50	void *ptr;
 51	int size;
 52
 53	size = sizeof(struct mtd_partition) * set->nr_partitions;
 54	if (size) {
 55		ptr = kmemdup(set->partitions, size, GFP_KERNEL);
 56		set->partitions = ptr;
 57
 58		if (!ptr)
 59			return -ENOMEM;
 60	}
 61	
 62	if (set->nr_map && set->nr_chips) {
 63		size = sizeof(int) * set->nr_chips;
 64		ptr = kmemdup(set->nr_map, size, GFP_KERNEL);
 65		set->nr_map = ptr;
 66
 67		if (!ptr)
 68			return -ENOMEM;
 69	}
 70
 71	if (set->ecc_layout) {
 72		ptr = kmemdup(set->ecc_layout,
 73			      sizeof(struct nand_ecclayout), GFP_KERNEL);
 74		set->ecc_layout = ptr;
 75
 76		if (!ptr)
 77			return -ENOMEM;
 78	}
 79	
 80	return 0;
 81}
 82
 83void __init s3c_nand_set_platdata(struct s3c2410_platform_nand *nand)
 84{
 85	struct s3c2410_platform_nand *npd;
 86	int size;
 87	int ret;
 88
 89	/* note, if we get a failure in allocation, we simply drop out of the
 90	 * function. If there is so little memory available at initialisation
 91	 * time then there is little chance the system is going to run.
 92	 */ 
 93
 94	npd = s3c_set_platdata(nand, sizeof(struct s3c2410_platform_nand),
 95				&s3c_device_nand);
 96	if (!npd)
 97		return;
 98
 99	/* now see if we need to copy any of the nand set data */
100
101	size = sizeof(struct s3c2410_nand_set) * npd->nr_sets;
102	if (size) {
103		struct s3c2410_nand_set *from = npd->sets;
104		struct s3c2410_nand_set *to;
105		int i;
106
107		to = kmemdup(from, size, GFP_KERNEL);
108		npd->sets = to;	/* set, even if we failed */
109
110		if (!to) {
111			printk(KERN_ERR "%s: no memory for sets\n", __func__);
112			return;
113		}
114		
115		for (i = 0; i < npd->nr_sets; i++) {
116			ret = s3c_nand_copy_set(to);
117			if (ret) {
118				printk(KERN_ERR "%s: failed to copy set %d\n",
119				__func__, i);
120				return;
121			}
122			to++;
123		}
124	}
125}