]> Git Repo - J-u-boot.git/blob - drivers/block/rkmtd.c
net: mediatek: fix gmac2 usability for mt7629
[J-u-boot.git] / drivers / block / rkmtd.c
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * Some functions are derived from:
4  * https://github.com/rockchip-linux/u-boot/blob/next-dev/drivers/rknand/rk_ftl_arm_v7.S
5  * Copyright (c) 2016-2018, Fuzhou Rockchip Electronics Co., Ltd
6  *
7  * Driver interface derived from:
8  * /drivers/block/host_dev.c
9  * /drivers/block/host-uclass.c
10  * Copyright 2022 Google LLC
11  * Written by Simon Glass <[email protected]>
12  *
13  * Copyright (C) 2023 Johan Jonker <[email protected]>
14  */
15
16 #include <blk.h>
17 #include <dm.h>
18 #include <nand.h>
19 #include <part.h>
20 #include <rkmtd.h>
21 #include <stddef.h>
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <dm/device-internal.h>
25 #include <dm/devres.h>
26 #include <dm/lists.h>
27 #include <dm/root.h>
28 #include <dm/uclass-internal.h>
29 #include <linux/mtd/mtd.h>
30 #if !IS_ENABLED(CONFIG_SANDBOX)
31 #include <linux/mtd/rawnand.h>
32 #endif
33 #include <u-boot/crc.h>
34
35 struct nand_para_info nand_para_tbl[] = {
36         {6, {0x2c, 0x64, 0x44, 0x4b, 0xa9, 0x00}, 4, 1, 16,  256, 2, 2, 2048, 0x01df,  3, 17, 40, 32, 1, 0, 1, 0, 0, {0, 0, 0, 0, 0}},
37         {6, {0x2c, 0x44, 0x44, 0x4b, 0xa9, 0x00}, 4, 1, 16,  256, 2, 2, 1064, 0x01df,  3, 17, 40, 32, 1, 0, 1, 0, 0, {0, 0, 0, 0, 0}},
38         {6, {0x2c, 0x68, 0x04, 0x4a, 0xa9, 0x00}, 4, 1,  8,  256, 2, 2, 2048, 0x011f,  1,  0, 24, 32, 1, 0, 1, 0, 0, {0, 0, 0, 0, 0}},
39         {5, {0x2c, 0x88, 0x04, 0x4b, 0xa9, 0x00}, 4, 1, 16,  256, 2, 2, 2048, 0x011f,  1,  0, 24, 32, 1, 0, 1, 0, 0, {0, 0, 0, 0, 0}},
40         {6, {0x2c, 0xa8, 0x05, 0xcb, 0xa9, 0x00}, 4, 2, 16,  256, 2, 2, 2048, 0x011f,  1,  0, 24, 32, 1, 0, 1, 0, 0, {0, 0, 0, 0, 0}},
41         {6, {0x2c, 0x68, 0x04, 0x46, 0x89, 0x00}, 4, 1,  8,  256, 2, 2, 2048, 0x011f,  1,  0, 24, 32, 1, 0, 1, 0, 0, {0, 0, 0, 0, 0}},
42         {6, {0x2c, 0x48, 0x04, 0x4a, 0xa5, 0x00}, 4, 1,  8,  256, 2, 2, 1024, 0x011f,  1,  0, 24, 32, 1, 0, 1, 0, 0, {0, 0, 0, 0, 0}},
43         {6, {0x2c, 0x84, 0x64, 0x3c, 0xa5, 0x00}, 4, 1, 32,  512, 2, 2, 1024, 0x01df,  3, 17, 40, 32, 1, 0, 1, 0, 0, {0, 0, 0, 0, 0}},
44         {5, {0x2c, 0x84, 0x64, 0x54, 0xa9, 0x00}, 4, 1, 32,  512, 2, 2, 1024, 0x01df,  4, 18, 60, 32, 1, 0, 1, 0, 0, {0, 0, 0, 0, 0}},
45         {6, {0x2c, 0xd7, 0x94, 0x3e, 0x84, 0x00}, 4, 1,  8,  128, 2, 2, 4096, 0x0117,  1,  0, 24, 32, 1, 0, 1, 0, 0, {0, 0, 0, 0, 0}},
46         {6, {0x2c, 0x48, 0x04, 0x46, 0x85, 0x00}, 4, 1,  8,  256, 2, 2, 1024, 0x011f,  1,  0, 24, 32, 1, 0, 1, 0, 0, {0, 0, 0, 0, 0}},
47         {6, {0x2c, 0x88, 0x05, 0xc6, 0x89, 0x00}, 4, 2,  8,  256, 2, 2, 2048, 0x011f,  1,  0, 24, 32, 1, 0, 1, 0, 0, {0, 0, 0, 0, 0}},
48         {5, {0x2c, 0x88, 0x24, 0x4b, 0xa9, 0x00}, 4, 1, 16,  256, 2, 2, 2048, 0x011f,  1,  0, 24, 32, 1, 0, 1, 0, 0, {0, 0, 0, 0, 0}},
49         {6, {0x2c, 0x68, 0x00, 0x27, 0xa9, 0x00}, 4, 1, 16,  128, 1, 2, 2048, 0x011f,  0,  0, 24, 32, 1, 0, 1, 0, 0, {0, 0, 0, 0, 0}},
50         {5, {0x2c, 0x64, 0x64, 0x56, 0xa5, 0x00}, 4, 1, 24,  512, 2, 2,  700, 0x01df,  4, 18, 60, 32, 1, 0, 1, 0, 0, {0, 0, 0, 0, 0}},
51         {6, {0x2c, 0x84, 0xc5, 0x4b, 0xa9, 0x00}, 4, 2, 16,  256, 2, 2, 2048, 0x01df,  3, 17, 40, 32, 1, 0, 1, 0, 0, {0, 0, 0, 0, 0}},
52         {6, {0x2c, 0xd5, 0xd1, 0xa6, 0x68, 0x00}, 4, 2,  8,   64, 1, 2, 2048, 0x0117,  0,  0, 24, 32, 1, 0, 1, 0, 0, {0, 0, 0, 0, 0}},
53         {6, {0x2c, 0xdc, 0x90, 0xa6, 0x54, 0x00}, 4, 1,  8,   64, 1, 2, 1024, 0x0117,  0,  0, 24, 32, 1, 0, 1, 0, 0, {0, 0, 0, 0, 0}},
54         {5, {0x2c, 0x64, 0x64, 0x54, 0xa4, 0x00}, 4, 1, 32,  512, 2, 1, 1024, 0x01df,  4, 18, 60, 32, 1, 0, 1, 0, 0, {0, 0, 0, 0, 0}},
55         {5, {0x2c, 0x84, 0x44, 0x32, 0xaa, 0x00}, 4, 1, 32,  512, 2, 1, 2184, 0x05c7,  5, 19, 60, 32, 1, 0, 1, 0, 1, {0, 0, 0, 0, 0}},
56         {5, {0x2c, 0x64, 0x44, 0x32, 0xa5, 0x00}, 4, 1, 32,  512, 2, 1, 1048, 0x05c7,  5, 19, 60, 32, 1, 0, 1, 0, 1, {0, 0, 0, 0, 0}},
57         {5, {0x2c, 0x64, 0x64, 0x3c, 0xa5, 0x00}, 4, 1, 32,  512, 2, 1, 1044, 0x01df,  3, 17, 40, 32, 1, 0, 1, 0, 0, {0, 0, 0, 0, 0}},
58         {5, {0x2c, 0x84, 0x44, 0x32, 0xaa, 0x00}, 4, 1, 32,  512, 2, 1, 2184, 0x05c7,  5, 19, 60, 32, 1, 0, 4, 0, 1, {0, 0, 0, 0, 0}},
59         {5, {0x2c, 0x84, 0x44, 0x34, 0xaa, 0x00}, 4, 1, 32,  512, 2, 1, 2184, 0x05c7,  5, 19, 60, 32, 1, 0, 4, 0, 1, {0, 0, 0, 0, 0}},
60         {5, {0x2c, 0x84, 0xc4, 0x34, 0xaa, 0x00}, 4, 1, 32,  512, 2, 1, 2184, 0x05c7,  5, 19, 60, 32, 1, 0, 1, 0, 1, {0, 0, 0, 0, 0}},
61         {5, {0x2c, 0x84, 0x44, 0x34, 0xa4, 0x00}, 4, 1, 32,  512, 2, 1, 2184, 0x05c7,  5, 19, 60, 32, 1, 0, 1, 0, 1, {0, 0, 0, 0, 0}},
62         {5, {0x2c, 0x84, 0x64, 0x3c, 0xa9, 0x00}, 4, 1, 32,  512, 2, 2, 1024, 0x01df,  3, 17, 40, 32, 1, 0, 1, 0, 0, {0, 0, 0, 0, 0}},
63         {6, {0x2c, 0xa4, 0x64, 0x32, 0xaa, 0x04}, 4, 1, 32, 1024, 2, 1, 2192, 0x05c7, 10, 19, 60, 32, 1, 0, 4, 0, 1, {0, 0, 0, 0, 0}},
64         {6, {0xad, 0xde, 0x94, 0xd2, 0x04, 0x43}, 2, 1, 16,  256, 2, 2, 2048, 0x01d9,  1,  1, 24, 32, 4, 0, 3, 0, 0, {0, 0, 0, 0, 0}},
65         {6, {0xad, 0xd7, 0x94, 0xda, 0x74, 0xc3}, 2, 1, 16,  256, 2, 2, 1024, 0x01d9,  1,  2, 40, 32, 4, 0, 3, 0, 0, {0, 0, 0, 0, 0}},
66         {6, {0xad, 0xd7, 0x94, 0x91, 0x60, 0x44}, 2, 1, 16,  256, 2, 2, 1046, 0x01d9,  1,  3, 40, 32, 4, 1, 3, 0, 0, {0, 0, 0, 0, 0}},
67         {6, {0xad, 0xde, 0x94, 0xda, 0x74, 0xc4}, 2, 1, 16,  256, 2, 2, 2090, 0x01d9,  1,  4, 40, 32, 4, 1, 3, 0, 0, {0, 0, 0, 0, 0}},
68         {6, {0xad, 0xde, 0x94, 0xeb, 0x74, 0x44}, 2, 1, 32,  256, 2, 2, 1066, 0x01d9,  1,  7, 40, 32, 4, 1, 3, 0, 0, {0, 0, 0, 0, 0}},
69         {6, {0xad, 0xd5, 0x94, 0xda, 0x74, 0xc4}, 2, 1, 16,  256, 2, 2,  530, 0x01d9,  1,  3, 40, 32, 4, 1, 3, 0, 0, {0, 0, 0, 0, 0}},
70         {6, {0xad, 0xd7, 0x94, 0x9a, 0x74, 0x42}, 2, 1, 16,  256, 2, 2, 1024, 0x0119,  1,  0, 24, 32, 4, 0, 3, 0, 0, {0, 0, 0, 0, 0}},
71         {6, {0xad, 0xde, 0x14, 0xa7, 0x42, 0x4a}, 2, 1, 32,  256, 2, 2, 1060, 0x01d9,  2,  5, 40, 32, 4, 1, 3, 0, 0, {0, 0, 0, 0, 0}},
72         {6, {0xad, 0xd7, 0x14, 0x9e, 0x34, 0x4a}, 2, 1, 16,  256, 2, 2, 1056, 0x01d9,  2,  5, 40, 32, 4, 1, 3, 0, 0, {0, 0, 0, 0, 0}},
73         {6, {0xad, 0xde, 0x94, 0xa7, 0x42, 0x48}, 2, 1, 32,  256, 2, 2, 1060, 0x01d9,  2,  5, 40, 32, 4, 1, 3, 0, 0, {0, 0, 0, 0, 0}},
74         {6, {0xad, 0xde, 0x14, 0xab, 0x42, 0x4a}, 2, 1, 32,  256, 2, 2, 1056, 0x01d9,  2,  6, 40, 32, 3, 1, 3, 0, 0, {0, 0, 0, 0, 0}},
75         {6, {0xad, 0x3a, 0x14, 0xab, 0x42, 0x4a}, 2, 1, 32,  256, 2, 2, 2092, 0x01d9,  2,  5, 40, 32, 3, 1, 3, 0, 0, {0, 0, 0, 0, 0}},
76         {6, {0xad, 0xd5, 0x94, 0x9a, 0x74, 0x42}, 2, 1, 16,  256, 2, 1, 1024, 0x0111,  1,  0, 24, 32, 4, 1, 3, 0, 0, {0, 0, 0, 0, 0}},
77         {6, {0xad, 0x3a, 0x14, 0x03, 0x08, 0x50}, 2, 1, 32,  388, 2, 2, 1362, 0x01d9,  9,  8, 40, 32, 3, 1, 3, 0, 0, {0, 0, 0, 0, 0}},
78         {6, {0x89, 0x64, 0x44, 0x4b, 0xa9, 0x00}, 7, 1, 16,  256, 2, 2, 2048, 0x01df,  3, 17, 40, 32, 1, 0, 1, 0, 0, {0, 0, 0, 0, 0}},
79         {6, {0x89, 0x88, 0x24, 0x4b, 0xa9, 0x84}, 7, 1, 16,  256, 2, 2, 2048, 0x01df,  3, 17, 40, 32, 1, 0, 1, 0, 0, {0, 0, 0, 0, 0}},
80         {6, {0x89, 0x88, 0x24, 0x4b, 0xa9, 0x00}, 7, 1, 16,  256, 2, 2, 2048, 0x0117,  1,  0, 24, 32, 1, 0, 1, 0, 0, {0, 0, 0, 0, 0}},
81         {6, {0x89, 0x68, 0x24, 0x4a, 0xa9, 0x00}, 7, 1,  8,  256, 2, 2, 2048, 0x0117,  1,  0, 24, 32, 1, 0, 1, 0, 0, {0, 0, 0, 0, 0}},
82         {6, {0x89, 0x68, 0x04, 0x4a, 0xa9, 0x00}, 7, 1,  8,  256, 2, 2, 2048, 0x0117,  1,  0, 24, 32, 1, 0, 1, 0, 0, {0, 0, 0, 0, 0}},
83         {6, {0x89, 0xd7, 0x94, 0x3e, 0x84, 0x00}, 7, 1,  8,  256, 2, 2, 2048, 0x0117,  1,  0, 24, 32, 1, 0, 1, 0, 0, {0, 0, 0, 0, 0}},
84         {6, {0x89, 0x68, 0x04, 0x46, 0xa9, 0x00}, 7, 1,  8,  256, 2, 2, 2048, 0x0117,  1,  0, 24, 32, 1, 0, 1, 0, 0, {0, 0, 0, 0, 0}},
85         {5, {0x89, 0x64, 0x64, 0x3c, 0xa1, 0x00}, 7, 1, 32,  512, 2, 1, 1024, 0x01c7,  4, 17, 40, 32, 1, 0, 1, 0, 0, {0, 0, 0, 0, 0}},
86         {5, {0x89, 0x84, 0x64, 0x3c, 0xa5, 0x00}, 7, 1, 32,  512, 2, 2, 1024, 0x01c7,  4, 17, 40, 32, 1, 0, 1, 0, 0, {0, 0, 0, 0, 0}},
87         {6, {0x89, 0x88, 0x24, 0x3b, 0xa9, 0x00}, 7, 1, 16,  192, 2, 2, 2048, 0x0117, 12,  0, 24, 32, 1, 0, 1, 0, 0, {0, 0, 0, 0, 0}},
88         {6, {0x98, 0xd7, 0x84, 0x93, 0x72, 0x57}, 1, 1, 32,  256, 2, 1, 1060, 0x05c1,  2, 33, 40, 32, 2, 1, 1, 0, 0, {0, 0, 0, 0, 0}},
89         {6, {0x98, 0xde, 0x84, 0x93, 0x72, 0x57}, 1, 1, 32,  256, 2, 1, 2092, 0x05c1,  2, 33, 40, 32, 2, 1, 1, 0, 0, {0, 0, 0, 0, 0}},
90         {6, {0x98, 0x3a, 0x85, 0x93, 0x76, 0x57}, 1, 2, 32,  256, 2, 1, 2092, 0x05e1,  2, 33, 40, 32, 2, 1, 1, 0, 0, {0, 0, 0, 0, 0}},
91         {6, {0x98, 0xd5, 0x84, 0x32, 0x72, 0x56}, 1, 1, 16,  128, 2, 1, 2056, 0x05c1,  2, 33, 40, 32, 2, 1, 1, 0, 0, {0, 0, 0, 0, 0}},
92         {6, {0x98, 0xd7, 0x94, 0x32, 0x76, 0x56}, 1, 1, 16,  128, 2, 2, 2058, 0x05d1,  2, 33, 40, 32, 2, 1, 1, 0, 0, {0, 0, 0, 0, 0}},
93         {6, {0x98, 0xde, 0x94, 0x82, 0x76, 0x56}, 1, 1, 16,  256, 2, 2, 2062, 0x05d1,  1, 33, 40, 32, 2, 1, 1, 0, 0, {0, 0, 0, 0, 0}},
94         {6, {0x98, 0xde, 0x94, 0x93, 0x76, 0x50}, 1, 1, 32,  256, 2, 2, 1066, 0x05d9,  2, 34, 40, 32, 3, 1, 1, 0, 0, {0, 0, 0, 0, 0}},
95         {6, {0x98, 0x3a, 0x95, 0x93, 0x7a, 0x50}, 1, 2, 32,  256, 2, 2, 1066, 0x05d9,  2, 34, 40, 32, 3, 1, 1, 0, 0, {0, 0, 0, 0, 0}},
96         {6, {0x98, 0xd7, 0x94, 0x32, 0x76, 0x55}, 1, 1, 16,  128, 2, 2, 2050, 0x0191,  2,  0, 24, 32, 1, 1, 1, 0, 0, {0, 0, 0, 0, 0}},
97         {6, {0x98, 0xde, 0x94, 0x93, 0x76, 0x57}, 1, 1, 32,  256, 2, 2, 1058, 0x05d9,  2, 33, 40, 32, 3, 1, 1, 0, 0, {0, 0, 0, 0, 0}},
98         {6, {0x98, 0xd7, 0x84, 0x93, 0x72, 0x50}, 1, 1, 32,  256, 2, 1, 1060, 0x05c1,  2, 34, 40, 32, 3, 1, 1, 0, 0, {0, 0, 0, 0, 0}},
99         {6, {0x98, 0xde, 0x94, 0x93, 0x76, 0x51}, 1, 1, 32,  256, 2, 2, 1074, 0x05d9,  2, 35, 40, 32, 3, 1, 4, 0, 0, {0, 0, 0, 0, 0}},
100         {6, {0x98, 0x3a, 0x94, 0x93, 0x76, 0x51}, 1, 1, 32,  256, 2, 2, 2106, 0x05d9,  2, 35, 40, 32, 3, 1, 4, 0, 0, {0, 0, 0, 0, 0}},
101         {6, {0x98, 0xd7, 0x84, 0x93, 0x72, 0x51}, 1, 1, 32,  256, 2, 1, 1056, 0x05d9,  2, 35, 40, 32, 3, 1, 4, 0, 0, {0, 0, 0, 0, 0}},
102         {6, {0x98, 0xde, 0x94, 0x93, 0x76, 0xd1}, 1, 1, 32,  256, 2, 2, 1074, 0x05d9,  2, 35, 40, 32, 3, 1, 4, 0, 0, {0, 0, 0, 0, 0}},
103         {6, {0x45, 0xde, 0x94, 0x93, 0x76, 0x57}, 8, 1, 32,  256, 2, 2, 1058, 0x05d9,  2, 66, 40, 32, 3, 1, 1, 0, 0, {0, 0, 0, 0, 0}},
104         {6, {0x45, 0xd7, 0x84, 0x93, 0x72, 0x57}, 8, 1, 32,  256, 2, 1, 1060, 0x05c1,  2, 66, 40, 32, 2, 1, 1, 0, 0, {0, 0, 0, 0, 0}},
105         {6, {0x45, 0xde, 0xa4, 0x82, 0x76, 0x56}, 8, 1, 16,  256, 2, 2, 2082, 0x01d9,  1, 65, 40, 32, 3, 1, 1, 0, 0, {0, 0, 0, 0, 0}},
106         {6, {0x45, 0xde, 0x94, 0x93, 0x76, 0x50}, 8, 1, 32,  256, 2, 2, 1066, 0x05d9,  2, 67, 40, 32, 3, 1, 1, 0, 0, {0, 0, 0, 0, 0}},
107         {6, {0x45, 0xd7, 0x84, 0x93, 0x72, 0x50}, 8, 1, 32,  256, 2, 1, 1060, 0x05c1,  2, 67, 40, 32, 3, 1, 1, 0, 0, {0, 0, 0, 0, 0}},
108         {6, {0x45, 0xde, 0xa4, 0x82, 0x76, 0xd7}, 8, 1, 16,  256, 2, 2, 2090, 0x04d9,  1, 66, 40, 32, 3, 1, 1, 0, 0, {0, 0, 0, 0, 0}},
109         {6, {0x45, 0xde, 0x84, 0x93, 0x72, 0x57}, 8, 1, 32,  256, 2, 1, 2092, 0x05c1,  2, 66, 40, 32, 3, 1, 1, 0, 0, {0, 0, 0, 0, 0}},
110         {6, {0x45, 0x3a, 0x94, 0x93, 0x76, 0x51}, 8, 1, 32,  256, 2, 2, 2106, 0x01d9,  2, 68, 40, 32, 3, 1, 4, 0, 0, {0, 0, 0, 0, 0}},
111         {6, {0x45, 0xde, 0x94, 0x93, 0x76, 0x51}, 8, 1, 32,  256, 2, 2, 1074, 0x01d9,  2, 68, 40, 32, 3, 1, 4, 0, 0, {0, 0, 0, 0, 0}},
112         {6, {0x45, 0x3a, 0xa4, 0x93, 0x7a, 0x50}, 8, 1, 32,  256, 2, 2, 2138, 0x05d9,  2,  0, 40, 32, 3, 1, 1, 0, 0, {0, 0, 0, 0, 0}},
113         {6, {0x45, 0xde, 0x94, 0x82, 0x76, 0x56}, 8, 1, 16,  256, 2, 2, 2062, 0x01d9,  1,  0, 40, 32, 3, 1, 1, 0, 0, {0, 0, 0, 0, 0}},
114         {6, {0x45, 0xde, 0x94, 0x93, 0x76, 0xd7}, 8, 1, 32,  256, 2, 2, 1058, 0x05d9,  2, 66, 40, 32, 3, 1, 1, 0, 0, {0, 0, 0, 0, 0}},
115         {6, {0xec, 0xd7, 0x94, 0x7e, 0x64, 0x44}, 0, 1, 16,  128, 2, 2, 2048, 0x01d9,  2, 49, 60, 36, 3, 0, 3, 0, 0, {0, 0, 0, 0, 0}},
116         {6, {0xec, 0xde, 0xd5, 0x7e, 0x68, 0x44}, 0, 2, 16,  128, 2, 2, 2048, 0x01f9,  2, 49, 60, 36, 3, 0, 3, 0, 0, {0, 0, 0, 0, 0}},
117         {6, {0xec, 0xd7, 0x94, 0x7a, 0x54, 0x43}, 0, 1, 16,  128, 2, 2, 2076, 0x0199,  2,  0, 40, 36, 3, 1, 3, 0, 0, {0, 0, 0, 0, 0}},
118         {6, {0xec, 0xde, 0xd5, 0x7a, 0x58, 0x43}, 0, 2, 16,  128, 2, 2, 2076, 0x01b9,  2,  0, 40, 36, 3, 1, 3, 0, 0, {0, 0, 0, 0, 0}},
119         {6, {0xec, 0xd5, 0x94, 0x76, 0x54, 0x43}, 0, 1, 16,  128, 2, 2, 1038, 0x0119,  2,  0, 24, 36, 3, 1, 3, 0, 0, {0, 0, 0, 0, 0}},
120         {6, {0xec, 0xd7, 0x14, 0x76, 0x54, 0xc2}, 0, 1, 16,  128, 2, 2, 2076, 0x0491,  2,  0, 24, 40, 3, 1, 3, 0, 0, {0, 0, 0, 0, 0}},
121         {6, {0xec, 0xde, 0x94, 0xc3, 0xa4, 0xca}, 0, 1, 32,  792, 2, 1,  688, 0x04c1, 11, 50, 40, 32, 3, 1, 1, 0, 1, {0, 0, 0, 0, 0}},
122 };
123
124 #if !IS_ENABLED(CONFIG_SANDBOX)
125 static int rkmtd_write_oob(struct rkmtd_dev *plat, ulong off, u_char *datbuf, u_char *oobbuf)
126 {
127         struct mtd_info *mtd = plat->mtd;
128         struct mtd_oob_ops ops;
129         loff_t addr;
130         int ret;
131
132         off &= ~(mtd->writesize - 1);
133         addr = (loff_t)off;
134
135         memset(&ops, 0, sizeof(ops));
136         ops.datbuf = datbuf;
137         ops.oobbuf = oobbuf;
138         ops.len = mtd->writesize;
139         ops.ooblen = mtd->oobsize;
140         ops.mode = MTD_OPS_PLACE_OOB;
141         ret = mtd_write_oob(mtd, addr, &ops);
142         if (ret < 0) {
143                 debug("Error (%d) writing page %08lx\n", ret, off);
144                 return 1;
145         }
146
147         return 0;
148 }
149
150 static int rkmtd_read_oob(struct rkmtd_dev *plat, ulong off, u_char *datbuf, u_char *oobbuf)
151 {
152         struct mtd_info *mtd = plat->mtd;
153         struct mtd_oob_ops ops;
154         loff_t addr;
155         int ret;
156
157         off &= ~(mtd->writesize - 1);
158         addr = (loff_t)off;
159
160         memset(&ops, 0, sizeof(ops));
161         ops.datbuf = datbuf;
162         ops.oobbuf = oobbuf;
163         ops.len = mtd->writesize;
164         ops.ooblen = mtd->oobsize;
165         ops.mode = MTD_OPS_PLACE_OOB;
166         ret = mtd_read_oob(mtd, addr, &ops);
167         if (ret < 0) {
168                 debug("Error (%d) reading page %08lx\n", ret, off);
169                 return 1;
170         }
171
172         return 0;
173 }
174
175 static int rkmtd_erase(struct rkmtd_dev *plat, ulong off)
176 {
177         struct mtd_info *mtd = plat->mtd;
178         struct erase_info info;
179         loff_t addr;
180         int ret;
181
182         off &= ~(mtd->writesize - 1);
183         addr = (loff_t)off;
184
185         memset(&info, 0, sizeof(info));
186         info.mtd = mtd;
187         info.addr = addr;
188         info.len = mtd->erasesize;
189         info.scrub = 1;
190         ret = mtd_erase(mtd, &info);
191         if (ret) {
192                 debug("Error (%d) erasing page %08lx\n", ret, off);
193                 return 1;
194         }
195
196         return 0;
197 }
198 #endif
199 void rkmtd_scan_block(struct rkmtd_dev *plat)
200 {
201         plat->blk_counter = 0;
202
203 #if !IS_ENABLED(CONFIG_SANDBOX)
204         u32 blk;
205
206         for (blk = 0; blk < plat->boot_blks; blk++) {
207                 rkmtd_read_oob(plat, blk * plat->mtd->erasesize, plat->datbuf, plat->oobbuf);
208                 if (*(u32 *)plat->datbuf == RK_TAG) {
209                         struct sector0 *sec0 = (struct sector0 *)plat->datbuf;
210
211                         rkmtd_rc4(plat->datbuf, 512);
212
213                         plat->idblock[plat->blk_counter].blk = blk;
214                         plat->idblock[plat->blk_counter].offset = sec0->boot_code1_offset;
215                         plat->idblock[plat->blk_counter].boot_size = sec0->flash_boot_size;
216
217                         debug("\nblk       : %d\n", plat->idblock[plat->blk_counter].blk);
218                         debug("offset    : %d\n", plat->idblock[plat->blk_counter].offset);
219                         debug("boot_size : %d\n", plat->idblock[plat->blk_counter].boot_size);
220
221                         plat->blk_counter += 1;
222
223                         if (plat->blk_counter >= ARRAY_SIZE(plat->idblock))
224                                 return;
225                 }
226         }
227 #endif
228 }
229
230 void rkmtd_read_block(struct rkmtd_dev *plat, u32 idx, u8 *buf)
231 {
232 #if !IS_ENABLED(CONFIG_SANDBOX)
233         ulong off = plat->idblock[idx].blk * plat->mtd->erasesize;
234         struct nand_chip *chip = mtd_to_nand(plat->mtd);
235         struct nand_ecc_ctrl *ecc = &chip->ecc;
236         int counter = 0;
237         u32 spare0 = 0;
238         u32 *p_spare;
239         int sector;
240         int page;
241
242         rkmtd_read_oob(plat, off,
243                        plat->datbuf, plat->oobbuf);
244
245         memcpy(buf, plat->datbuf, BLK_SIZE);
246
247         while (counter < plat->idblock[idx].boot_size) {
248                 if (spare0)
249                         page = (plat->idblock[idx].offset + spare0) / 4;
250                 else
251                         page = (plat->idblock[idx].offset + counter) / 4;
252
253                 rkmtd_read_oob(plat,
254                                off + page * plat->mtd->writesize,
255                                plat->datbuf, plat->oobbuf);
256
257                 sector = plat->idblock[idx].offset + counter;
258
259                 memcpy(&buf[(sector / 4) * BLK_SIZE], plat->datbuf, BLK_SIZE);
260
261                 p_spare = (u32 *)&plat->oobbuf[(ecc->steps - 1) * NFC_SYS_DATA_SIZE];
262
263                 spare0 = *p_spare;
264                 if (spare0 == -1)
265                         break;
266
267                 counter += 4;
268         }
269 #endif
270 }
271
272 void rkmtd_write_block(struct rkmtd_dev *plat, u32 idx, u8 *buf)
273 {
274 #if !IS_ENABLED(CONFIG_SANDBOX)
275         ulong off = plat->idblock[idx].blk * plat->mtd->erasesize;
276         struct nand_chip *chip = mtd_to_nand(plat->mtd);
277         struct nand_ecc_ctrl *ecc = &chip->ecc;
278         int counter = 0;
279         u32 *p_spare;
280         int sector;
281         int page;
282         int j, w, r;
283
284         rkmtd_erase(plat, off);
285
286         memset(plat->datbuf, 0xff, plat->mtd->writesize);
287         memcpy(plat->datbuf, buf, BLK_SIZE);
288         memset(plat->oobbuf, 0xff, plat->mtd->oobsize);
289
290         rkmtd_write_oob(plat, off,
291                         plat->datbuf, plat->oobbuf);
292
293         while (counter < plat->idblock[idx].boot_size) {
294                 sector = plat->idblock[idx].offset + counter;
295
296                 memset(plat->datbuf, 0xff, plat->mtd->writesize);
297                 memcpy(plat->datbuf, &buf[(sector / 4) * BLK_SIZE], BLK_SIZE);
298                 memset(plat->oobbuf, 0xff, plat->mtd->oobsize);
299
300                 p_spare = (u32 *)&plat->oobbuf[(ecc->steps - 1) * NFC_SYS_DATA_SIZE];
301
302                 *p_spare = (plat->page_table[sector / 4 + 1] - 1) * 4;
303
304                 page = plat->page_table[sector / 4];
305
306                 rkmtd_write_oob(plat,
307                                 off + page * plat->mtd->writesize,
308                                 plat->datbuf, plat->oobbuf);
309
310                 counter += 4;
311         }
312
313         memset(plat->check, 0, BUF_SIZE);
314         rkmtd_read_block(plat, idx, plat->check);
315
316         for (j = 0; j < BLK_SIZE; j++) {
317                 w = *(buf + j);
318                 r = *(plat->check + j);
319
320                 if (r != w)
321                         goto dumpblock;
322         }
323
324         for (j = 0; j < (plat->idblock[idx].boot_size * 512); j++) {
325                 w = *(buf + plat->idblock[idx].offset * 512 + j);
326                 r = *(plat->check + plat->idblock[idx].offset * 512  + j);
327
328                 if (r != w)
329                         goto dumpblock;
330         }
331
332         debug("write OK\n");
333         return;
334
335 dumpblock:
336         debug("write and check error:%x r=%x w=%x\n", j, r, w);
337
338         plat->idblock[idx].offset = 0;
339         plat->idblock[idx].boot_size = 0;
340
341         memset(plat->datbuf, 0xff, plat->mtd->writesize);
342         memset(plat->datbuf, 0, BLK_SIZE);
343         memset(plat->oobbuf, 0xff, plat->mtd->oobsize);
344
345         rkmtd_write_oob(plat, off, plat->datbuf, plat->oobbuf);
346 #endif
347 }
348
349 ulong rkmtd_bread(struct udevice *udev, lbaint_t start,
350                   lbaint_t blkcnt, void *dst)
351 {
352         struct blk_desc *block_dev = dev_get_uclass_plat(udev);
353         struct udevice *parent_dev = dev_get_parent(udev);
354         struct rkmtd_dev *plat = dev_get_plat(parent_dev);
355         char *buf = dst;
356         int i;
357
358         if (blkcnt == 0)
359                 return 0;
360
361         if (start > (block_dev->lba - 1) ||
362             (start + blkcnt) > block_dev->lba)
363                 return 0;
364
365         memset(dst, 0, blkcnt * block_dev->blksz);
366
367         for (i = start; i < (start + blkcnt); i++) {
368                 if (i == 0)  {
369                         debug("mbr     : %d\n", i);
370
371                         memcpy(&buf[(i - start) * block_dev->blksz],
372                                plat->mbr, sizeof(legacy_mbr));
373                 } else if (i == 1) {
374                         debug("gpt_h   : %d\n", i);
375
376                         memcpy(&buf[(i - start) * block_dev->blksz],
377                                plat->gpt_h, sizeof(gpt_header));
378                 } else if (i == (block_dev->lba - 1)) {
379                         debug("gpt_h2  : %d\n", i);
380
381                         memcpy(&buf[(i - start) * block_dev->blksz],
382                                plat->gpt_h2, sizeof(gpt_header));
383                 } else if (i == 2 || i == (block_dev->lba - 33)) {
384                         debug("gpt_e   : %d\n", i);
385
386                         memcpy(&buf[(i - start) * block_dev->blksz],
387                                plat->gpt_e, sizeof(gpt_entry));
388                 } else if (i >= 64 && i < (block_dev->lba - 33)) {
389                         debug("rd      : %d\n", i);
390
391                         memcpy(&buf[(i - start) * block_dev->blksz],
392                                &plat->idb[(i - 64) * block_dev->blksz], block_dev->blksz);
393                 }
394         }
395
396         return blkcnt;
397 }
398
399 ulong rkmtd_bwrite(struct udevice *udev, lbaint_t start,
400                    lbaint_t blkcnt, const void *src)
401 {
402         struct blk_desc *block_dev = dev_get_uclass_plat(udev);
403         struct udevice *parent_dev = dev_get_parent(udev);
404         struct rkmtd_dev *plat = dev_get_plat(parent_dev);
405         struct sector0 *sec0;
406         int i, j;
407
408         if (blkcnt == 0)
409                 return 0;
410
411         if (start > (block_dev->lba - 1) ||
412             (start + blkcnt) > block_dev->lba)
413                 return 0;
414
415         for (i = start; i < (start + blkcnt); i++) {
416                 debug("wr      : %d\n", i);
417
418                 if (i >= 64 && i < (block_dev->lba - 33)) {
419                         if (i == 64) {
420                                 debug("first block\n");
421
422                                 plat->idb_need_write_back = 1;
423                                 memset(plat->idb, 0, BUF_SIZE);
424                         }
425
426                         if (plat->idb_need_write_back) {
427                                 char *buf = (char *)src;
428
429                                 memcpy(&plat->idb[(i - 64) * block_dev->blksz],
430                                        &buf[(i - start) * block_dev->blksz],
431                                        block_dev->blksz);
432
433                                 if (i == 64) {
434                                         memcpy(plat->check, plat->idb, 512);
435
436                                         if (*(u32 *)plat->check == RK_TAG) {
437                                                 rkmtd_rc4(plat->check, 512);
438
439                                                 sec0 = (struct sector0 *)plat->check;
440                                                 plat->offset = sec0->boot_code1_offset;
441                                                 plat->boot_size = sec0->flash_boot_size;
442
443                                                 if (plat->offset + plat->boot_size > 512) {
444                                                         debug("max size limit\n");
445                                                         plat->idb_need_write_back = 0;
446                                                 }
447                                         } else {
448                                                 debug("no IDB block found\n");
449                                                 plat->idb_need_write_back = 0;
450                                         }
451                                 }
452
453                                 if (i == (64 + plat->offset + plat->boot_size - 1)) {
454                                         debug("last block\n");
455
456                                         plat->idb_need_write_back = 0;
457
458                                         if (!plat->blk_counter) {
459                                                 plat->idblock[0].blk = 2;
460                                                 plat->idblock[1].blk = 3;
461                                                 plat->idblock[2].blk = 4;
462                                                 plat->idblock[3].blk = 5;
463                                                 plat->idblock[4].blk = 6;
464                                                 plat->blk_counter = 5;
465                                         }
466
467                                         for (j = 0; j < plat->blk_counter; j++) {
468                                                 if (plat->idblock[j].blk < plat->boot_blks) {
469                                                         plat->idblock[j].offset = plat->offset;
470                                                         plat->idblock[j].boot_size = plat->boot_size;
471                                                         rkmtd_write_block(plat, j, plat->idb);
472                                                 }
473                                         }
474
475                                         rkmtd_scan_block(plat);
476
477                                         if (!IS_ENABLED(CONFIG_SANDBOX))
478                                                 memset(plat->idb, 0, BUF_SIZE);
479
480                                         if (plat->blk_counter)
481                                                 rkmtd_read_block(plat, 0, plat->idb);
482                                 }
483                         }
484                 } else if (plat->idb_need_write_back) {
485                         plat->idb_need_write_back = 0;
486
487                         memset(plat->idb, 0, BUF_SIZE);
488
489                         if (plat->blk_counter)
490                                 rkmtd_read_block(plat, 0, plat->idb);
491                 }
492         }
493
494         return blkcnt;
495 }
496
497 static const struct blk_ops rkmtd_blk_ops = {
498         .read   = rkmtd_bread,
499         .write  = rkmtd_bwrite,
500 };
501
502 U_BOOT_DRIVER(rkmtd_blk) = {
503         .name           = "rkmtd_blk",
504         .id             = UCLASS_BLK,
505         .ops            = &rkmtd_blk_ops,
506 };
507
508 void rkmtd_build_page_table(struct rkmtd_dev *plat)
509 {
510         u32 counter;
511         u32 counter2;
512
513         switch (plat->lsb_mode) {
514         case 0:
515                 counter = 0;
516                 do {
517                         u16 val = counter;
518
519                         plat->page_table[counter++] = val;
520                 } while (counter != 512);
521                 break;
522         case 1:
523                 counter = 0;
524                 do {
525                         u16 val = counter;
526
527                         if (counter > 3) {
528                                 u16 offset;
529
530                                 if (counter & 1)
531                                         offset = 3;
532                                 else
533                                         offset = 2;
534                                 val = 2 * counter - offset;
535                         }
536                         plat->page_table[counter++] = val;
537                 } while (counter != 512);
538                 break;
539         case 2:
540                 counter = 0;
541                 do {
542                         u16 val = counter;
543
544                         if (counter > 1)
545                                 val = 2 * counter - 1;
546                         plat->page_table[counter++] = val;
547                 } while (counter != 512);
548                 break;
549         case 3:
550                 counter = 0;
551                 do {
552                         u16 val = counter;
553
554                         if (counter > 5) {
555                                 u16 offset;
556
557                                 if (counter & 1)
558                                         offset = 5;
559                                 else
560                                         offset = 4;
561                                 val = 2 * counter - offset;
562                         }
563                         plat->page_table[counter++] = val;
564                 } while (counter != 512);
565                 break;
566         case 4:
567                 counter = 8;
568                 plat->page_table[0] = 0;
569                 plat->page_table[1] = 1;
570                 plat->page_table[2] = 2;
571                 plat->page_table[3] = 3;
572                 plat->page_table[4] = 4;
573                 plat->page_table[5] = 5;
574                 plat->page_table[6] = 7;
575                 plat->page_table[7] = 8;
576                 do {
577                         u32 offset;
578                         u32 val;
579
580                         if (counter & 1)
581                                 offset = 7;
582                         else
583                                 offset = 6;
584                         val = 2 * counter - offset;
585                         plat->page_table[counter++] = val;
586                 } while (counter != 512);
587                 break;
588         case 5:
589                 counter = 0;
590                 counter2 = 16;
591                 do {
592                         u16 val = counter;
593
594                         plat->page_table[counter++] = val;
595                 } while (counter != 16);
596                 do {
597                         plat->page_table[counter++] = counter2;
598                         counter2 = counter2 + 2;
599                 } while (counter != 512);
600                 break;
601         case 6:
602                 counter = 0;
603                 counter2 = 0;
604                 do {
605                         u16 val = counter;
606
607                         if (counter > 5) {
608                                 u16 offset;
609
610                                 if (counter & 1)
611                                         offset = 12;
612                                 else
613                                         offset = 10;
614                                 val = counter2 - offset;
615                         }
616                         plat->page_table[counter++] = val;
617                         counter2 = counter2 + 3;
618                 } while (counter != 512);
619                 break;
620         case 9:
621                 counter = 3;
622                 counter2 = 3;
623                 plat->page_table[0] = 0;
624                 plat->page_table[1] = 1;
625                 plat->page_table[2] = 2;
626                 do {
627                         plat->page_table[counter++] = counter2;
628                         counter2 = counter2 + 2;
629                 } while (counter != 512);
630                 break;
631         case 10:
632                 counter = 0;
633                 counter2 = 63;
634                 do {
635                         u16 val = counter;
636
637                         plat->page_table[counter++] = val;
638                 } while (counter != 63);
639                 do {
640                         plat->page_table[counter++] = counter2;
641                         counter2 = counter2 + 2;
642                 } while (counter != 512);
643                 break;
644         case 11:
645                 counter = 0;
646                 do {
647                         u16 val = counter;
648
649                         plat->page_table[counter++] = val;
650                 } while (counter != 8);
651                 do {
652                         u32 offset;
653                         u32 val;
654
655                         if (counter & 1)
656                                 offset = 7;
657                         else
658                                 offset = 6;
659                         val = 2 * counter - offset;
660                         plat->page_table[counter++] = val;
661                 } while (counter != 512);
662                 break;
663         case 12:
664                 counter = 4;
665                 plat->page_table[0] = 0;
666                 plat->page_table[1] = 1;
667                 plat->page_table[2] = 2;
668                 plat->page_table[3] = 3;
669                 do {
670                         u32 val = counter - 1 + (counter >> 1);
671
672                         plat->page_table[counter++] = val;
673                 } while (counter != 512);
674                 break;
675         }
676 }
677
678 static inline u32 efi_crc32(const void *buf, u32 len)
679 {
680         return crc32(0, buf, len);
681 }
682
683 int rkmtd_init_plat(struct udevice *dev)
684 {
685         static const efi_guid_t partition_basic_data_guid = PARTITION_BASIC_DATA_GUID;
686         struct rkmtd_dev *plat = dev_get_plat(dev);
687         size_t efiname_len, dosname_len;
688         uchar name[] = "loader1";
689         u32 calc_crc32;
690         int k;
691
692         gen_rand_uuid_str(plat->uuid_disk_str, UUID_STR_FORMAT_GUID);
693         gen_rand_uuid_str(plat->uuid_part_str, UUID_STR_FORMAT_GUID);
694
695         debug("uuid_part_str          : %s\n", plat->uuid_part_str);
696         debug("uuid_disk_str          : %s\n", plat->uuid_disk_str);
697
698         plat->idb = devm_kzalloc(plat->dev, BUF_SIZE, GFP_KERNEL);
699         if (!plat->idb)
700                 return -ENOMEM;
701
702         plat->check = devm_kzalloc(plat->dev, BUF_SIZE, GFP_KERNEL);
703         if (!plat->check)
704                 return -ENOMEM;
705
706         plat->mbr = devm_kzalloc(plat->dev, sizeof(legacy_mbr), GFP_KERNEL);
707         if (!plat->mbr)
708                 return -ENOMEM;
709
710         plat->gpt_e = devm_kzalloc(plat->dev, sizeof(gpt_entry), GFP_KERNEL);
711         if (!plat->gpt_e)
712                 return -ENOMEM;
713
714         plat->gpt_h = devm_kzalloc(plat->dev, sizeof(gpt_header), GFP_KERNEL);
715         if (!plat->gpt_h)
716                 return -ENOMEM;
717
718         plat->gpt_h2 = devm_kzalloc(plat->dev, sizeof(gpt_header), GFP_KERNEL);
719         if (!plat->gpt_h2)
720                 return -ENOMEM;
721
722         /* Init mbr */
723         plat->mbr->signature = MSDOS_MBR_SIGNATURE;
724         plat->mbr->partition_record[0].sys_ind = EFI_PMBR_OSTYPE_EFI_GPT;
725         plat->mbr->partition_record[0].start_sect = 1;
726         plat->mbr->partition_record[0].nr_sects = LBA - 1;
727
728         /* Init gpt_e */
729         plat->gpt_e->starting_lba = cpu_to_le64(64);
730         plat->gpt_e->ending_lba = cpu_to_le64(LBA - 34);
731
732         debug("starting_lba           : %llu\n", le64_to_cpu(plat->gpt_e->starting_lba));
733         debug("ending_lba             : %llu\n", le64_to_cpu(plat->gpt_e->ending_lba));
734
735         memcpy(plat->gpt_e->partition_type_guid.b, &partition_basic_data_guid, 16);
736
737         uuid_str_to_bin(plat->uuid_part_str, plat->gpt_e->unique_partition_guid.b,
738                         UUID_STR_FORMAT_GUID);
739
740         efiname_len = sizeof(plat->gpt_e->partition_name) / sizeof(efi_char16_t);
741         dosname_len = sizeof(name);
742
743         for (k = 0; k < min(dosname_len, efiname_len); k++)
744                 plat->gpt_e->partition_name[k] = (efi_char16_t)(name[k]);
745
746         /* Init gpt_h */
747         plat->gpt_h->signature = cpu_to_le64(GPT_HEADER_SIGNATURE_UBOOT);
748         plat->gpt_h->revision = cpu_to_le32(GPT_HEADER_REVISION_V1);
749         plat->gpt_h->header_size = cpu_to_le32(sizeof(gpt_header));
750         plat->gpt_h->first_usable_lba = cpu_to_le64(64);
751         plat->gpt_h->last_usable_lba = cpu_to_le64(LBA - 34);
752         plat->gpt_h->num_partition_entries = cpu_to_le32(1);
753         plat->gpt_h->sizeof_partition_entry = cpu_to_le32(sizeof(gpt_entry));
754
755         uuid_str_to_bin(plat->uuid_disk_str, plat->gpt_h->disk_guid.b,
756                         UUID_STR_FORMAT_GUID);
757
758         plat->gpt_h->partition_entry_array_crc32 = 0;
759         calc_crc32 = efi_crc32((const unsigned char *)plat->gpt_e,
760                                le32_to_cpu(plat->gpt_h->num_partition_entries) *
761                                le32_to_cpu(plat->gpt_h->sizeof_partition_entry));
762         plat->gpt_h->partition_entry_array_crc32 = cpu_to_le32(calc_crc32);
763
764         debug("partition crc32        : 0x%08x\n", calc_crc32);
765
766         plat->gpt_h->my_lba = cpu_to_le64(1);
767         plat->gpt_h->partition_entry_lba = cpu_to_le64(2);
768         plat->gpt_h->alternate_lba = cpu_to_le64(LBA - 1);
769
770         plat->gpt_h->header_crc32 = 0;
771         calc_crc32 = efi_crc32((const unsigned char *)plat->gpt_h,
772                                le32_to_cpu(plat->gpt_h->header_size));
773         plat->gpt_h->header_crc32 = cpu_to_le32(calc_crc32);
774
775         debug("header h1 crc32        : 0x%08x\n", calc_crc32);
776
777         /* Init gpt_h2 */
778         memcpy(plat->gpt_h2, plat->gpt_h, sizeof(gpt_header));
779
780         plat->gpt_h2->my_lba = cpu_to_le64(LBA - 1);
781         plat->gpt_h2->partition_entry_lba =
782                 cpu_to_le64(le64_to_cpu(plat->gpt_h2->last_usable_lba) + 1);
783         plat->gpt_h2->alternate_lba = cpu_to_le64(1);
784
785         plat->gpt_h2->header_crc32 = 0;
786         calc_crc32 = efi_crc32((const unsigned char *)plat->gpt_h2,
787                                le32_to_cpu(plat->gpt_h2->header_size));
788         plat->gpt_h2->header_crc32 = cpu_to_le32(calc_crc32);
789
790         debug("header h2 crc32        : 0x%08x\n", calc_crc32);
791
792         part_init(plat->desc);
793
794         return 0;
795 }
796
797 static int rkmtd_bind(struct udevice *dev)
798 {
799         struct rkmtd_dev *plat = dev_get_plat(dev);
800         struct blk_desc *desc;
801         struct udevice *bdev;
802         int ret;
803
804         ret = blk_create_devicef(dev, "rkmtd_blk", "blk", UCLASS_RKMTD,
805                                  -1, 512, LBA, &bdev);
806         if (ret) {
807                 return log_msg_ret("blk", ret);
808         }
809
810         desc = dev_get_uclass_plat(bdev);
811         sprintf(desc->vendor, "0x%.4x", 0x2207);
812         memcpy(desc->product, "RKMTD", sizeof("RKMTD"));
813         memcpy(desc->revision, "V1.00", sizeof("V1.00"));
814         plat->desc = desc;
815
816         return 0;
817 }
818
819 static int rkmtd_attach_mtd(struct udevice *dev)
820 {
821         struct rkmtd_dev *plat = dev_get_plat(dev);
822         struct mtd_info *mtd;
823         struct udevice *blk;
824         int ret;
825
826         plat->dev = dev;
827
828         /* Sanity check that rkmtd_bind() has been used */
829         ret = blk_find_from_parent(dev, &blk);
830         if (ret)
831                 return ret;
832
833 #if IS_ENABLED(CONFIG_SANDBOX)
834         plat->mtd = devm_kzalloc(dev, sizeof(struct mtd_info), GFP_KERNEL);
835         if (!plat->mtd)
836                 return -ENOMEM;
837
838         mtd = plat->mtd;
839         mtd->erasesize = 2 ^ 3 * BLK_SIZE;
840         mtd->writesize = BLK_SIZE;
841         mtd->oobsize = BLK_SIZE / STEP_SIZE * NFC_SYS_DATA_SIZE;
842         plat->boot_blks = 0;
843         plat->lsb_mode = 0;
844 #else
845         struct nand_chip *chip;
846         u8 id[6];
847         int i, j;
848         u32 tmp;
849
850         mtd = get_nand_dev_by_index(0);
851         if (!mtd)
852                 return -ENOSYS;
853
854         chip = mtd_to_nand(mtd);
855
856         ret = ofnode_read_u32(chip->flash_node, "rockchip,boot-blks", &tmp);
857         plat->boot_blks = ret ? 0 : tmp;
858         plat->mtd = mtd;
859
860         if (chip->select_chip)
861                 chip->select_chip(mtd, 0);
862
863         nand_readid_op(chip, 0, id, 6);
864
865         if (chip->select_chip)
866                 chip->select_chip(mtd, -1);
867
868         for (i = 0; i < ARRAY_SIZE(nand_para_tbl); i++) {
869                 plat->info = (struct nand_para_info *)&nand_para_tbl[i];
870                 for (j = 0; j < plat->info->id_bytes; j++) {
871                         if (plat->info->nand_id[j] != id[j])
872                                 break;
873                         if (j == plat->info->id_bytes - 1)
874                                 goto valid;
875                 }
876         }
877
878         debug("no nand_para_info found\n");
879         return -ENODEV;
880 valid:
881         plat->lsb_mode = plat->info->lsb_mode;
882
883         debug("FLASH ID :");
884
885         for (j = 0; j < plat->info->id_bytes; j++)
886                 debug(" %x", id[j]);
887
888         debug("\n");
889 #endif
890
891         rkmtd_build_page_table(plat);
892
893         plat->datbuf = devm_kzalloc(dev, mtd->writesize, GFP_KERNEL);
894         if (!plat->datbuf)
895                 return -ENOMEM;
896
897         plat->oobbuf = devm_kzalloc(dev, mtd->oobsize, GFP_KERNEL);
898         if (!plat->oobbuf)
899                 return -ENOMEM;
900
901         debug("erasesize     %8d\n", mtd->erasesize);
902         debug("writesize     %8d\n", mtd->writesize);
903         debug("oobsize       %8d\n", mtd->oobsize);
904         debug("boot_blks     %8d\n", plat->boot_blks);
905         debug("lsb_mode      %8d\n", plat->lsb_mode);
906
907         ret = rkmtd_init_plat(dev);
908         if (ret) {
909                 debug("rkmtd_init_plat failed\n");
910                 return -ENOENT;
911         }
912
913         rkmtd_scan_block(plat);
914
915         memset(plat->idb, 0, BUF_SIZE);
916
917         if (plat->blk_counter)
918                 rkmtd_read_block(plat, 0, plat->idb);
919
920         return 0;
921 }
922
923 int rkmtd_detach_mtd(struct udevice *dev)
924 {
925         int ret;
926
927         ret = device_remove(dev, DM_REMOVE_NORMAL);
928         if (ret)
929                 return log_msg_ret("rem", ret);
930
931         ret = device_chld_unbind(dev, NULL);
932         if (ret)
933                 return log_msg_ret("unb", ret);
934
935         return 0;
936 }
937
938 struct rkmtd_ops rkmtd_ops = {
939         .attach_mtd     = rkmtd_attach_mtd,
940         .detach_mtd     = rkmtd_detach_mtd,
941 };
942
943 U_BOOT_DRIVER(rkmtd_drv) = {
944         .name           = "rkmtd_drv",
945         .id             = UCLASS_RKMTD,
946         .ops            = &rkmtd_ops,
947         .bind           = rkmtd_bind,
948         .plat_auto      = sizeof(struct rkmtd_dev),
949 };
950
951 struct rkmtd_priv {
952         struct udevice *cur_dev;
953 };
954
955 void rkmtd_rc4(u8 *buf, u32 len)
956 {
957         u8 S[256], K[256], temp;
958         u32 i, j, t, x;
959         u8 key[16] = { 124, 78, 3, 4, 85, 5, 9, 7, 45, 44, 123, 56, 23, 13, 23, 17};
960
961         j = 0;
962         for (i = 0; i < 256; i++) {
963                 S[i] = (u8)i;
964                 j &= 0x0f;
965                 K[i] = key[j];
966                 j++;
967         }
968
969         j = 0;
970         for (i = 0; i < 256; i++) {
971                 j = (j + S[i] + K[i]) % 256;
972                 temp = S[i];
973                 S[i] = S[j];
974                 S[j] = temp;
975         }
976
977         i = 0;
978         j = 0;
979         for (x = 0; x < len; x++) {
980                 i = (i + 1) % 256;
981                 j = (j + S[i]) % 256;
982                 temp = S[i];
983                 S[i] = S[j];
984                 S[j] = temp;
985                 t = (S[i] + (S[j] % 256)) % 256;
986                 buf[x] = buf[x] ^ S[t];
987         }
988 }
989
990 struct udevice *rkmtd_get_cur_dev(void)
991 {
992         struct uclass *uc = uclass_find(UCLASS_RKMTD);
993
994         if (uc) {
995                 struct rkmtd_priv *priv = uclass_get_priv(uc);
996
997                 return priv->cur_dev;
998         }
999
1000         return NULL;
1001 }
1002
1003 void rkmtd_set_cur_dev(struct udevice *dev)
1004 {
1005         struct uclass *uc = uclass_find(UCLASS_RKMTD);
1006
1007         if (uc) {
1008                 struct rkmtd_priv *priv = uclass_get_priv(uc);
1009
1010                 priv->cur_dev = dev;
1011         }
1012 }
1013
1014 struct udevice *rkmtd_find_by_label(const char *label)
1015 {
1016         struct udevice *dev;
1017         struct uclass *uc;
1018
1019         uclass_id_foreach_dev(UCLASS_RKMTD, dev, uc) {
1020                 struct rkmtd_dev *plat = dev_get_plat(dev);
1021
1022                 if (plat->label && !strcmp(label, plat->label))
1023                         return dev;
1024         }
1025
1026         return NULL;
1027 }
1028
1029 int rkmtd_attach(struct udevice *dev)
1030 {
1031         struct rkmtd_ops *ops = rkmtd_get_ops(dev);
1032
1033         if (!ops->attach_mtd)
1034                 return -ENOSYS;
1035
1036         return ops->attach_mtd(dev);
1037 }
1038
1039 int rkmtd_detach(struct udevice *dev)
1040 {
1041         struct rkmtd_ops *ops = rkmtd_get_ops(dev);
1042
1043         if (!ops->detach_mtd)
1044                 return -ENOSYS;
1045
1046         if (dev == rkmtd_get_cur_dev())
1047                 rkmtd_set_cur_dev(NULL);
1048
1049         return ops->detach_mtd(dev);
1050 }
1051
1052 static void rkmtd_drv_kmalloc_release(struct udevice *dev, void *res)
1053 {
1054         /* noop */
1055 }
1056
1057 int rkmtd_create_device(const char *label, struct udevice **devp)
1058 {
1059         char dev_name[30], *str, *label_new;
1060         struct udevice *dev, *blk;
1061         struct rkmtd_dev *plat;
1062         int ret;
1063
1064         /* unbind any existing device with this label */
1065         dev = rkmtd_find_by_label(label);
1066         if (dev) {
1067                 ret = rkmtd_detach(dev);
1068                 if (ret)
1069                         return log_msg_ret("det", ret);
1070
1071                 ret = device_unbind(dev);
1072                 if (ret)
1073                         return log_msg_ret("unb", ret);
1074         }
1075
1076         snprintf(dev_name, sizeof(dev_name), "rkmtd-%s", label);
1077
1078         str = devres_alloc(rkmtd_drv_kmalloc_release, strlen(dev_name) + 1, GFP_KERNEL);
1079         if (unlikely(!str))
1080                 return -ENOMEM;
1081
1082         strcpy(str, dev_name);
1083
1084         ret = device_bind_driver(dm_root(), "rkmtd_drv", str, &dev);
1085         if (ret) {
1086                 free(str);
1087                 return log_msg_ret("drv", ret);
1088         }
1089
1090         devres_add(dev, str);
1091
1092         if (!blk_find_from_parent(dev, &blk)) {
1093                 struct blk_desc *desc = dev_get_uclass_plat(blk);
1094
1095                 desc->removable = true;
1096         }
1097
1098         label_new = devm_kzalloc(dev, strlen(label) + 1, GFP_KERNEL);
1099         if (!label_new)
1100                 return -ENOMEM;
1101
1102         strcpy(label_new, label);
1103
1104         plat = dev_get_plat(dev);
1105         plat->label = label_new;
1106         *devp = dev;
1107
1108         return 0;
1109 }
1110
1111 int rkmtd_create_attach_mtd(const char *label, struct udevice **devp)
1112 {
1113         struct udevice *dev;
1114         int ret;
1115
1116         ret = rkmtd_create_device(label, &dev);
1117         if (ret)
1118                 return log_msg_ret("cre", ret);
1119
1120         ret = rkmtd_attach(dev);
1121         if (ret) {
1122                 device_unbind(dev);
1123                 return log_msg_ret("att", ret);
1124         }
1125         *devp = dev;
1126
1127         return 0;
1128 }
1129
1130 UCLASS_DRIVER(rkmtd) = {
1131         .name           = "rkmtd",
1132         .id             = UCLASS_RKMTD,
1133         .post_bind      = dm_scan_fdt_dev,
1134         .priv_auto      = sizeof(struct rkmtd_priv),
1135 };
This page took 0.091309 seconds and 4 git commands to generate.