diff --git a/device/celestica/x86_64-cel_silverstone-r0/Silverstone-128x100/minigraph.xml b/device/celestica/x86_64-cel_silverstone-r0/Silverstone-128x100/minigraph.xml
new file mode 100644
index 000000000000..5e204776cb63
--- /dev/null
+++ b/device/celestica/x86_64-cel_silverstone-r0/Silverstone-128x100/minigraph.xml
@@ -0,0 +1,1333 @@
+
+
+
+
+
+ ARISTA01T0
+ 10.0.0.33
+ sonic
+ 10.0.0.32
+ 1
+ 180
+ 60
+
+
+ sonic
+ 10.0.0.0
+ ARISTA01T2
+ 10.0.0.1
+ 1
+ 180
+ 60
+
+
+ ARISTA02T0
+ 10.0.0.35
+ sonic
+ 10.0.0.34
+ 1
+ 180
+ 60
+
+
+ sonic
+ 10.0.0.2
+ ARISTA02T2
+ 10.0.0.3
+ 1
+ 180
+ 60
+
+
+ ARISTA03T0
+ 10.0.0.37
+ sonic
+ 10.0.0.36
+ 1
+ 180
+ 60
+
+
+ sonic
+ 10.0.0.4
+ ARISTA03T2
+ 10.0.0.5
+ 1
+ 180
+ 60
+
+
+ ARISTA04T0
+ 10.0.0.39
+ sonic
+ 10.0.0.38
+ 1
+ 180
+ 60
+
+
+ sonic
+ 10.0.0.6
+ ARISTA04T2
+ 10.0.0.7
+ 1
+ 180
+ 60
+
+
+ ARISTA05T0
+ 10.0.0.41
+ sonic
+ 10.0.0.40
+ 1
+ 180
+ 60
+
+
+ sonic
+ 10.0.0.8
+ ARISTA05T2
+ 10.0.0.9
+ 1
+ 180
+ 60
+
+
+ ARISTA06T0
+ 10.0.0.43
+ sonic
+ 10.0.0.42
+ 1
+ 180
+ 60
+
+
+ sonic
+ 10.0.0.10
+ ARISTA06T2
+ 10.0.0.11
+ 1
+ 180
+ 60
+
+
+ ARISTA07T0
+ 10.0.0.45
+ sonic
+ 10.0.0.44
+ 1
+ 180
+ 60
+
+
+ sonic
+ 10.0.0.12
+ ARISTA07T2
+ 10.0.0.13
+ 1
+ 180
+ 60
+
+
+ ARISTA08T0
+ 10.0.0.47
+ sonic
+ 10.0.0.46
+ 1
+ 180
+ 60
+
+
+ sonic
+ 10.0.0.14
+ ARISTA08T2
+ 10.0.0.15
+ 1
+ 180
+ 60
+
+
+ ARISTA09T0
+ 10.0.0.49
+ sonic
+ 10.0.0.48
+ 1
+ 180
+ 60
+
+
+ sonic
+ 10.0.0.16
+ ARISTA09T2
+ 10.0.0.17
+ 1
+ 180
+ 60
+
+
+ ARISTA10T0
+ 10.0.0.51
+ sonic
+ 10.0.0.50
+ 1
+ 180
+ 60
+
+
+ sonic
+ 10.0.0.18
+ ARISTA10T2
+ 10.0.0.19
+ 1
+ 180
+ 60
+
+
+ ARISTA11T0
+ 10.0.0.53
+ sonic
+ 10.0.0.52
+ 1
+ 180
+ 60
+
+
+ sonic
+ 10.0.0.20
+ ARISTA11T2
+ 10.0.0.21
+ 1
+ 180
+ 60
+
+
+ ARISTA12T0
+ 10.0.0.55
+ sonic
+ 10.0.0.54
+ 1
+ 180
+ 60
+
+
+ sonic
+ 10.0.0.22
+ ARISTA12T2
+ 10.0.0.23
+ 1
+ 180
+ 60
+
+
+ ARISTA13T0
+ 10.0.0.57
+ sonic
+ 10.0.0.56
+ 1
+ 180
+ 60
+
+
+ sonic
+ 10.0.0.24
+ ARISTA13T2
+ 10.0.0.25
+ 1
+ 180
+ 60
+
+
+ ARISTA14T0
+ 10.0.0.59
+ sonic
+ 10.0.0.58
+ 1
+ 180
+ 60
+
+
+ sonic
+ 10.0.0.26
+ ARISTA14T2
+ 10.0.0.27
+ 1
+ 180
+ 60
+
+
+ ARISTA15T0
+ 10.0.0.61
+ sonic
+ 10.0.0.60
+ 1
+ 180
+ 60
+
+
+ sonic
+ 10.0.0.28
+ ARISTA15T2
+ 10.0.0.29
+ 1
+ 180
+ 60
+
+
+ ARISTA16T0
+ 10.0.0.63
+ sonic
+ 10.0.0.62
+ 1
+ 180
+ 60
+
+
+ sonic
+ 10.0.0.30
+ ARISTA16T2
+ 10.0.0.31
+ 1
+ 180
+ 60
+
+
+
+
+ 65100
+ sonic
+
+
+ 10.0.0.33
+
+
+
+
+ 10.0.0.1
+
+
+
+
+ 10.0.0.35
+
+
+
+
+ 10.0.0.3
+
+
+
+
+ 10.0.0.37
+
+
+
+
+ 10.0.0.5
+
+
+
+
+ 10.0.0.39
+
+
+
+
+ 10.0.0.7
+
+
+
+
+ 10.0.0.41
+
+
+
+
+ 10.0.0.9
+
+
+
+
+ 10.0.0.43
+
+
+
+
+ 10.0.0.11
+
+
+
+
+ 10.0.0.45
+
+
+
+
+ 10.0.0.13
+
+
+
+
+ 10.0.0.47
+
+
+
+
+ 10.0.0.15
+
+
+
+
+ 10.0.0.49
+
+
+
+
+ 10.0.0.17
+
+
+
+
+ 10.0.0.51
+
+
+
+
+ 10.0.0.19
+
+
+
+
+ 10.0.0.53
+
+
+
+
+ 10.0.0.21
+
+
+
+
+ 10.0.0.55
+
+
+
+
+ 10.0.0.23
+
+
+
+
+ 10.0.0.57
+
+
+
+
+ 10.0.0.25
+
+
+
+
+ 10.0.0.59
+
+
+
+
+ 10.0.0.27
+
+
+
+
+ 10.0.0.61
+
+
+
+
+ 10.0.0.29
+
+
+
+
+ 10.0.0.63
+
+
+
+
+ 10.0.0.31
+
+
+
+
+
+
+
+ 64001
+ ARISTA01T0
+
+
+
+ 65200
+ ARISTA01T2
+
+
+
+ 64002
+ ARISTA02T0
+
+
+
+ 65200
+ ARISTA02T2
+
+
+
+ 64003
+ ARISTA03T0
+
+
+
+ 65200
+ ARISTA03T2
+
+
+
+ 64004
+ ARISTA04T0
+
+
+
+ 65200
+ ARISTA04T2
+
+
+
+ 64005
+ ARISTA05T0
+
+
+
+ 65200
+ ARISTA05T2
+
+
+
+ 64006
+ ARISTA06T0
+
+
+
+ 65200
+ ARISTA06T2
+
+
+
+ 64007
+ ARISTA07T0
+
+
+
+ 65200
+ ARISTA07T2
+
+
+
+ 64008
+ ARISTA08T0
+
+
+
+ 65200
+ ARISTA08T2
+
+
+
+ 64009
+ ARISTA09T0
+
+
+
+ 65200
+ ARISTA09T2
+
+
+
+ 64010
+ ARISTA10T0
+
+
+
+ 65200
+ ARISTA10T2
+
+
+
+ 64011
+ ARISTA11T0
+
+
+
+ 65200
+ ARISTA11T2
+
+
+
+ 64012
+ ARISTA12T0
+
+
+
+ 65200
+ ARISTA12T2
+
+
+
+ 64013
+ ARISTA13T0
+
+
+
+ 65200
+ ARISTA13T2
+
+
+
+ 64014
+ ARISTA14T0
+
+
+
+ 65200
+ ARISTA14T2
+
+
+
+ 64015
+ ARISTA15T0
+
+
+
+ 65200
+ ARISTA15T2
+
+
+
+ 64016
+ ARISTA16T0
+
+
+
+ 65200
+ ARISTA16T2
+
+
+
+
+
+
+
+
+
+ HostIP
+ Loopback0
+
+ 10.1.0.32/32
+
+ 10.1.0.32/32
+
+
+
+
+
+
+
+ sonic
+
+
+
+
+
+ QSFP1
+ 10.0.0.0/31
+
+
+
+ QSFP2
+ 10.0.0.2/31
+
+
+
+ QSFP3
+ 10.0.0.4/31
+
+
+
+ QSFP4
+ 10.0.0.6/31
+
+
+
+ QSFP5
+ 10.0.0.8/31
+
+
+
+ QSFP6
+ 10.0.0.10/31
+
+
+
+ QSFP7
+ 10.0.0.12/31
+
+
+
+ QSFP8
+ 10.0.0.14/31
+
+
+
+ QSFP9
+ 10.0.0.16/31
+
+
+
+ QSFP10
+ 10.0.0.18/31
+
+
+
+ QSFP11
+ 10.0.0.20/31
+
+
+
+ QSFP12
+ 10.0.0.22/31
+
+
+
+ QSFP13
+ 10.0.0.24/31
+
+
+
+ QSFP14
+ 10.0.0.26/31
+
+
+
+ QSFP15
+ 10.0.0.28/31
+
+
+
+ QSFP16
+ 10.0.0.30/31
+
+
+
+ QSFP17
+ 10.0.0.32/31
+
+
+
+ QSFP18
+ 10.0.0.34/31
+
+
+
+ QSFP19
+ 10.0.0.36/31
+
+
+
+ QSFP20
+ 10.0.0.38/31
+
+
+
+ QSFP21
+ 10.0.0.40/31
+
+
+
+ QSFP22
+ 10.0.0.42/31
+
+
+
+ QSFP23
+ 10.0.0.44/31
+
+
+
+ QSFP24
+ 10.0.0.46/31
+
+
+
+ QSFP25
+ 10.0.0.48/31
+
+
+
+ QSFP26
+ 10.0.0.50/31
+
+
+
+ QSFP27
+ 10.0.0.52/31
+
+
+
+ QSFP28
+ 10.0.0.54/31
+
+
+
+ QSFP29
+ 10.0.0.56/31
+
+
+
+ QSFP30
+ 10.0.0.58/31
+
+
+
+ QSFP31
+ 10.0.0.60/31
+
+
+
+ QSFP32
+ 10.0.0.62/31
+
+
+
+ QSFP33
+ 10.0.0.64/31
+
+
+
+ QSFP34
+ 10.0.0.66/31
+
+
+
+ QSFP35
+ 10.0.0.68/31
+
+
+
+ QSFP36
+ 10.0.0.70/31
+
+
+
+ QSFP37
+ 10.0.0.72/31
+
+
+
+ QSFP38
+ 10.0.0.74/31
+
+
+
+ QSFP39
+ 10.0.0.76/31
+
+
+
+ QSFP40
+ 10.0.0.78/31
+
+
+
+ QSFP41
+ 10.0.0.80/31
+
+
+
+ QSFP42
+ 10.0.0.82/31
+
+
+
+ QSFP43
+ 10.0.0.84/31
+
+
+
+ QSFP44
+ 10.0.0.86/31
+
+
+
+ QSFP45
+ 10.0.0.88/31
+
+
+
+ QSFP46
+ 10.0.0.90/31
+
+
+
+ QSFP47
+ 10.0.0.92/31
+
+
+
+ QSFP48
+ 10.0.0.94/31
+
+
+
+ QSFP49
+ 10.0.0.96/31
+
+
+
+ QSFP50
+ 10.0.0.98/31
+
+
+
+ QSFP51
+ 10.0.0.100/31
+
+
+
+ QSFP52
+ 10.0.0.102/31
+
+
+
+ QSFP53
+ 10.0.0.104/31
+
+
+
+ QSFP54
+ 10.0.0.106/31
+
+
+
+ QSFP55
+ 10.0.0.108/31
+
+
+
+ QSFP56
+ 10.0.0.110/31
+
+
+
+ QSFP57
+ 10.0.0.112/31
+
+
+
+ QSFP58
+ 10.0.0.114/31
+
+
+
+ QSFP59
+ 10.0.0.116/31
+
+
+
+ QSFP60
+ 10.0.0.118/31
+
+
+
+ QSFP61
+ 10.0.0.120/31
+
+
+
+ QSFP62
+ 10.0.0.122/31
+
+
+
+ QSFP63
+ 10.0.0.124/31
+
+
+
+ QSFP64
+ 10.0.0.126/31
+
+
+
+ QSFP65
+ 10.0.1.0/31
+
+
+
+ QSFP66
+ 10.0.1.2/31
+
+
+
+ QSFP67
+ 10.0.1.4/31
+
+
+
+ QSFP68
+ 10.0.1.6/31
+
+
+
+ QSFP69
+ 10.0.1.8/31
+
+
+
+ QSFP70
+ 10.0.1.10/31
+
+
+
+ QSFP71
+ 10.0.1.12/31
+
+
+
+ QSFP72
+ 10.0.1.14/31
+
+
+
+ QSFP73
+ 10.0.1.16/31
+
+
+
+ QSFP74
+ 10.0.1.18/31
+
+
+
+ QSFP75
+ 10.0.1.20/31
+
+
+
+ QSFP76
+ 10.0.1.22/31
+
+
+
+ QSFP77
+ 10.0.1.24/31
+
+
+
+ QSFP78
+ 10.0.1.26/31
+
+
+
+ QSFP79
+ 10.0.1.28/31
+
+
+
+ QSFP80
+ 10.0.1.30/31
+
+
+
+ QSFP81
+ 10.0.1.32/31
+
+
+
+ QSFP82
+ 10.0.1.34/31
+
+
+
+ QSFP83
+ 10.0.1.36/31
+
+
+
+ QSFP84
+ 10.0.1.38/31
+
+
+
+ QSFP85
+ 10.0.1.40/31
+
+
+
+ QSFP86
+ 10.0.1.42/31
+
+
+
+ QSFP87
+ 10.0.1.44/31
+
+
+
+ QSFP88
+ 10.0.1.46/31
+
+
+
+ QSFP89
+ 10.0.1.48/31
+
+
+
+ QSFP90
+ 10.0.1.50/31
+
+
+
+ QSFP91
+ 10.0.1.52/31
+
+
+
+ QSFP92
+ 10.0.1.54/31
+
+
+
+ QSFP93
+ 10.0.1.56/31
+
+
+
+ QSFP94
+ 10.0.1.58/31
+
+
+
+ QSFP95
+ 10.0.1.60/31
+
+
+
+ QSFP96
+ 10.0.1.62/31
+
+
+
+ QSFP97
+ 10.0.1.64/31
+
+
+
+ QSFP98
+ 10.0.1.66/31
+
+
+
+ QSFP99
+ 10.0.1.68/31
+
+
+
+ QSFP100
+ 10.0.1.70/31
+
+
+
+ QSFP101
+ 10.0.1.72/31
+
+
+
+ QSFP102
+ 10.0.1.74/31
+
+
+
+ QSFP103
+ 10.0.1.76/31
+
+
+
+ QSFP104
+ 10.0.1.78/31
+
+
+
+ QSFP105
+ 10.0.1.80/31
+
+
+
+ QSFP106
+ 10.0.1.82/31
+
+
+
+ QSFP107
+ 10.0.1.84/31
+
+
+
+ QSFP108
+ 10.0.1.86/31
+
+
+
+ QSFP109
+ 10.0.1.88/31
+
+
+
+ QSFP110
+ 10.0.1.90/31
+
+
+
+ QSFP111
+ 10.0.1.92/31
+
+
+
+ QSFP112
+ 10.0.1.94/31
+
+
+
+ QSFP113
+ 10.0.1.96/31
+
+
+
+ QSFP114
+ 10.0.1.98/31
+
+
+
+ QSFP115
+ 10.0.1.100/31
+
+
+
+ QSFP116
+ 10.0.1.102/31
+
+
+
+ QSFP117
+ 10.0.1.104/31
+
+
+
+ QSFP118
+ 10.0.1.106/31
+
+
+
+ QSFP119
+ 10.0.1.108/31
+
+
+
+ QSFP120
+ 10.0.1.110/31
+
+
+
+ QSFP121
+ 10.0.1.112/31
+
+
+
+ QSFP122
+ 10.0.1.114/31
+
+
+
+ QSFP123
+ 10.0.1.116/31
+
+
+
+ QSFP124
+ 10.0.1.118/31
+
+
+
+ QSFP125
+ 10.0.1.120/31
+
+
+
+ QSFP126
+ 10.0.1.122/31
+
+
+
+ QSFP127
+ 10.0.1.124/31
+
+
+
+ QSFP128
+ 10.0.1.126/31
+
+
+
+
+
+
+
+
+
+
+
+ sonic
+ Silverstone-128x100
+
+
+
+
+
+
+ sonic
+
+
+ DhcpResources
+
+
+
+
+ NtpResources
+
+ 0.debian.pool.ntp.org;1.debian.pool.ntp.org;2.debian.pool.ntp.org;3.debian.pool.ntp.org
+
+
+ SyslogResources
+
+
+
+
+ ErspanDestinationIpv4
+
+ 2.2.2.2
+
+
+
+
+
+
+ sonic
+ Silverstone-128x100
+
diff --git a/device/celestica/x86_64-cel_silverstone-r0/Silverstone-128x100/port_config.ini b/device/celestica/x86_64-cel_silverstone-r0/Silverstone-128x100/port_config.ini
new file mode 100644
index 000000000000..a448edd9287d
--- /dev/null
+++ b/device/celestica/x86_64-cel_silverstone-r0/Silverstone-128x100/port_config.ini
@@ -0,0 +1,129 @@
+# name lanes alias index
+Ethernet0 33,34 QSFP1 1
+Ethernet1 35,36 QSFP2 2
+Ethernet2 37,38 QSFP3 3
+Ethernet3 39,40 QSFP4 4
+Ethernet4 41,42 QSFP5 5
+Ethernet5 43,44 QSFP6 6
+Ethernet6 45,46 QSFP7 7
+Ethernet7 47,48 QSFP8 8
+Ethernet8 49,50 QSFP9 9
+Ethernet9 51,52 QSFP10 10
+Ethernet10 53,54 QSFP11 11
+Ethernet11 55,56 QSFP12 12
+Ethernet12 57,58 QSFP13 13
+Ethernet13 59,60 QSFP14 14
+Ethernet14 61,62 QSFP15 15
+Ethernet15 63,64 QSFP16 16
+Ethernet16 65,66 QSFP17 17
+Ethernet17 67,68 QSFP18 18
+Ethernet18 69,70 QSFP19 19
+Ethernet19 71,72 QSFP20 20
+Ethernet20 73,74 QSFP21 21
+Ethernet21 75,76 QSFP22 22
+Ethernet22 77,78 QSFP23 23
+Ethernet23 79,80 QSFP24 24
+Ethernet24 81,82 QSFP25 25
+Ethernet25 83,84 QSFP26 26
+Ethernet26 85,86 QSFP27 27
+Ethernet27 87,88 QSFP28 28
+Ethernet28 89,90 QSFP29 29
+Ethernet29 91,92 QSFP30 30
+Ethernet30 93,94 QSFP31 31
+Ethernet31 95,96 QSFP32 32
+Ethernet32 1,2 QSFP33 33
+Ethernet33 3,4 QSFP34 34
+Ethernet34 5,6 QSFP35 35
+Ethernet35 7,8 QSFP36 36
+Ethernet36 9,10 QSFP37 37
+Ethernet37 11,12 QSFP38 38
+Ethernet38 13,14 QSFP39 39
+Ethernet39 15,16 QSFP40 40
+Ethernet40 17,18 QSFP41 41
+Ethernet41 19,20 QSFP42 42
+Ethernet42 21,22 QSFP43 43
+Ethernet43 23,24 QSFP44 44
+Ethernet44 25,26 QSFP45 45
+Ethernet45 27,28 QSFP46 46
+Ethernet46 29,30 QSFP47 47
+Ethernet47 31,32 QSFP48 48
+Ethernet48 97,98 QSFP49 49
+Ethernet49 99,100 QSFP50 50
+Ethernet50 101,102 QSFP51 51
+Ethernet51 103,104 QSFP52 52
+Ethernet52 105,106 QSFP53 53
+Ethernet53 107,108 QSFP54 54
+Ethernet54 109,110 QSFP55 55
+Ethernet55 111,112 QSFP56 56
+Ethernet56 113,114 QSFP57 57
+Ethernet57 115,116 QSFP58 58
+Ethernet58 117,118 QSFP59 59
+Ethernet59 119,120 QSFP60 60
+Ethernet60 121,122 QSFP61 61
+Ethernet61 123,124 QSFP62 62
+Ethernet62 125,126 QSFP63 63
+Ethernet63 127,128 QSFP64 64
+Ethernet64 129,130 QSFP65 65
+Ethernet65 131,132 QSFP66 66
+Ethernet66 133,134 QSFP67 67
+Ethernet67 135,136 QSFP68 68
+Ethernet68 137,138 QSFP69 69
+Ethernet69 139,140 QSFP70 70
+Ethernet70 141,142 QSFP71 71
+Ethernet71 143,144 QSFP72 72
+Ethernet72 145,146 QSFP73 73
+Ethernet73 147,148 QSFP74 74
+Ethernet74 149,150 QSFP75 75
+Ethernet75 151,152 QSFP76 76
+Ethernet76 153,154 QSFP77 77
+Ethernet77 155,156 QSFP78 78
+Ethernet78 157,158 QSFP79 79
+Ethernet79 159,160 QSFP80 80
+Ethernet80 225,226 QSFP81 81
+Ethernet81 227,228 QSFP82 82
+Ethernet82 229,230 QSFP83 83
+Ethernet83 231,232 QSFP84 84
+Ethernet84 233,234 QSFP85 85
+Ethernet85 235,236 QSFP86 86
+Ethernet86 237,238 QSFP87 87
+Ethernet87 239,240 QSFP88 88
+Ethernet88 241,242 QSFP89 89
+Ethernet89 243,244 QSFP90 90
+Ethernet90 245,246 QSFP91 91
+Ethernet91 247,248 QSFP92 92
+Ethernet92 249,250 QSFP93 93
+Ethernet93 251,252 QSFP94 94
+Ethernet94 253,254 QSFP95 95
+Ethernet95 255,256 QSFP96 96
+Ethernet96 161,162 QSFP97 97
+Ethernet97 163,164 QSFP98 98
+Ethernet98 165,166 QSFP99 99
+Ethernet99 167,168 QSFP100 100
+Ethernet100 169,170 QSFP101 101
+Ethernet101 171,172 QSFP102 102
+Ethernet102 173,174 QSFP103 103
+Ethernet103 175,176 QSFP104 104
+Ethernet104 177,178 QSFP105 105
+Ethernet105 179,180 QSFP106 106
+Ethernet106 181,182 QSFP107 107
+Ethernet107 183,184 QSFP108 108
+Ethernet108 185,186 QSFP109 109
+Ethernet109 187,188 QSFP110 110
+Ethernet110 189,190 QSFP111 111
+Ethernet111 191,192 QSFP112 112
+Ethernet112 193,194 QSFP113 113
+Ethernet113 195,196 QSFP114 114
+Ethernet114 197,198 QSFP115 115
+Ethernet115 199,200 QSFP116 116
+Ethernet116 201,202 QSFP117 117
+Ethernet117 203,204 QSFP118 118
+Ethernet118 205,206 QSFP119 119
+Ethernet119 207,208 QSFP120 120
+Ethernet120 209,210 QSFP121 121
+Ethernet121 211,212 QSFP122 122
+Ethernet122 213,214 QSFP123 123
+Ethernet123 215,216 QSFP124 124
+Ethernet124 217,218 QSFP125 125
+Ethernet125 219,220 QSFP126 126
+Ethernet126 221,222 QSFP127 127
+Ethernet127 223,224 QSFP128 128
diff --git a/device/celestica/x86_64-cel_silverstone-r0/Silverstone-128x100/sai.profile b/device/celestica/x86_64-cel_silverstone-r0/Silverstone-128x100/sai.profile
new file mode 100644
index 000000000000..df15d1112261
--- /dev/null
+++ b/device/celestica/x86_64-cel_silverstone-r0/Silverstone-128x100/sai.profile
@@ -0,0 +1 @@
+SAI_INIT_CONFIG_FILE=/usr/share/sonic/platform/th3-128x100G.config.bcm
diff --git a/device/celestica/x86_64-cel_silverstone-r0/Silverstone-128x100/th3-128x100G.config.bcm b/device/celestica/x86_64-cel_silverstone-r0/Silverstone-128x100/th3-128x100G.config.bcm
new file mode 100644
index 000000000000..0b66c8b53814
--- /dev/null
+++ b/device/celestica/x86_64-cel_silverstone-r0/Silverstone-128x100/th3-128x100G.config.bcm
@@ -0,0 +1,441 @@
+pbmp_xport_xe.0=0x8ffff8ffffcffff8ffff8ffff8ffffcffff9fffe
+ccm_dma_enable=0
+ccmdma_intr_enable=0
+ctr_evict_enable=0
+mem_cache_enable=0
+parity_correction=0
+parity_enable=0
+phy_enable=0
+phy_null=1
+pll_bypass=1
+
+init_all_modules=0
+
+portmap_20=33:100:2
+portmap_21=35:100:2
+portmap_22=37:100:2
+portmap_23=39:100:2
+
+portmap_24=41:100:2
+portmap_25=43:100:2
+portmap_26=45:100:2
+portmap_27=47:100:2
+
+portmap_28=49:100:2
+portmap_29=51:100:2
+portmap_30=53:100:2
+portmap_31=55:100:2
+
+portmap_32=57:100:2
+portmap_33=59:100:2
+portmap_34=61:100:2
+portmap_35=63:100:2
+
+portmap_40=65:100:2
+portmap_41=67:100:2
+portmap_42=69:100:2
+portmap_43=71:100:2
+
+portmap_44=73:100:2
+portmap_45=75:100:2
+portmap_46=77:100:2
+portmap_47=79:100:2
+
+portmap_48=81:100:2
+portmap_49=83:100:2
+portmap_50=85:100:2
+portmap_51=87:100:2
+
+portmap_52=89:100:2
+portmap_53=91:100:2
+portmap_54=93:100:2
+portmap_55=95:100:2
+
+portmap_1=1:100:2
+portmap_2=3:100:2
+portmap_3=5:100:2
+portmap_4=7:100:2
+
+portmap_5=9:100:2
+portmap_6=11:100:2
+portmap_7=13:100:2
+portmap_8=15:100:2
+
+portmap_9=17:100:2
+portmap_10=19:100:2
+portmap_11=21:100:2
+portmap_12=23:100:2
+
+portmap_13=25:100:2
+portmap_14=27:100:2
+portmap_15=29:100:2
+portmap_16=31:100:2
+
+portmap_60=97:100:2
+portmap_61=99:100:2
+portmap_62=101:100:2
+portmap_63=103:100:2
+
+portmap_64=105:100:2
+portmap_65=107:100:2
+portmap_66=109:100:2
+portmap_67=111:100:2
+
+portmap_68=113:100:2
+portmap_69=115:100:2
+portmap_70=117:100:2
+portmap_71=119:100:2
+
+portmap_72=121:100:2
+portmap_73=123:100:2
+portmap_74=125:100:2
+portmap_75=127:100:2
+
+portmap_80=129:100:2
+portmap_81=131:100:2
+portmap_82=133:100:2
+portmap_83=135:100:2
+
+portmap_84=137:100:2
+portmap_85=139:100:2
+portmap_86=141:100:2
+portmap_87=143:100:2
+
+portmap_88=145:100:2
+portmap_89=147:100:2
+portmap_90=149:100:2
+portmap_91=151:100:2
+
+portmap_92=153:100:2
+portmap_93=155:100:2
+portmap_94=157:100:2
+portmap_95=159:100:2
+
+portmap_140=225:100:2
+portmap_141=227:100:2
+portmap_142=229:100:2
+portmap_143=231:100:2
+
+portmap_144=233:100:2
+portmap_145=235:100:2
+portmap_146=237:100:2
+portmap_147=239:100:2
+
+portmap_148=241:100:2
+portmap_149=243:100:2
+portmap_150=245:100:2
+portmap_151=247:100:2
+
+portmap_152=249:100:2
+portmap_153=251:100:2
+portmap_154=253:100:2
+portmap_155=255:100:2
+
+portmap_100=161:100:2
+portmap_101=163:100:2
+portmap_102=165:100:2
+portmap_103=167:100:2
+
+portmap_104=169:100:2
+portmap_105=171:100:2
+portmap_106=173:100:2
+portmap_107=175:100:2
+
+portmap_108=177:100:2
+portmap_109=179:100:2
+portmap_110=181:100:2
+portmap_111=183:100:2
+
+portmap_112=185:100:2
+portmap_113=187:100:2
+portmap_114=189:100:2
+portmap_115=191:100:2
+
+portmap_120=193:100:2
+portmap_121=195:100:2
+portmap_122=197:100:2
+portmap_123=199:100:2
+
+portmap_124=201:100:2
+portmap_125=203:100:2
+portmap_126=205:100:2
+portmap_127=207:100:2
+
+portmap_128=209:100:2
+portmap_129=211:100:2
+portmap_130=213:100:2
+portmap_131=215:100:2
+
+portmap_132=217:100:2
+portmap_133=219:100:2
+portmap_134=221:100:2
+portmap_135=223:100:2
+
+phy_chain_rx_lane_map_physical{33.0}=0x65732041
+phy_chain_tx_lane_map_physical{33.0}=0x47206531
+phy_chain_rx_lane_map_physical{41.0}=0x07561243
+phy_chain_tx_lane_map_physical{41.0}=0x36207514
+phy_chain_rx_lane_map_physical{49.0}=0x54632071
+phy_chain_tx_lane_map_physical{49.0}=0x06241735
+phy_chain_rx_lane_map_physical{57.0}=0x07561243
+phy_chain_tx_lane_map_physical{57.0}=0x35207614
+phy_chain_rx_lane_map_physical{65.0}=0x45623170
+phy_chain_tx_lane_map_physical{65.0}=0x51260734
+phy_chain_rx_lane_map_physical{73.0}=0x07561243
+phy_chain_tx_lane_map_physical{73.0}=0x37245610
+phy_chain_rx_lane_map_physical{81.0}=0x45632071
+phy_chain_tx_lane_map_physical{81.0}=0x51260734
+phy_chain_rx_lane_map_physical{89.0}=0x07561243
+phy_chain_tx_lane_map_physical{89.0}=0x26437510
+phy_chain_rx_lane_map_physical{1.0}=0x30176524
+phy_chain_tx_lane_map_physical{1.0}=0x20615374
+phy_chain_rx_lane_map_physical{9.0}=0x37562041
+phy_chain_tx_lane_map_physical{9.0}=0x05176432
+phy_chain_rx_lane_map_physical{17.0}=0x43607251
+phy_chain_tx_lane_map_physical{17.0}=0x70261435
+phy_chain_rx_lane_map_physical{25.0}=0x60347125
+phy_chain_tx_lane_map_physical{25.0}=0x46357120
+phy_chain_rx_lane_map_physical{97.0}=0x47601352
+phy_chain_tx_lane_map_physical{97.0}=0x04265137
+phy_chain_rx_lane_map_physical{105.0}=0x73206415
+phy_chain_tx_lane_map_physical{105.0}=0x26374150
+phy_chain_rx_lane_map_physical{113.0}=0x47632051
+phy_chain_tx_lane_map_physical{113.0}=0x03254617
+phy_chain_rx_lane_map_physical{121.0}=0x63027415
+phy_chain_tx_lane_map_physical{121.0}=0x63721045
+phy_chain_rx_lane_map_physical{129.0}=0x30154627
+phy_chain_tx_lane_map_physical{129.0}=0x04735261
+phy_chain_rx_lane_map_physical{137.0}=0x24753061
+phy_chain_tx_lane_map_physical{137.0}=0x37614520
+phy_chain_rx_lane_map_physical{145.0}=0x47601352
+phy_chain_tx_lane_map_physical{145.0}=0x63274510
+phy_chain_rx_lane_map_physical{153.0}=0x07361524
+phy_chain_tx_lane_map_physical{153.0}=0x36527104
+phy_chain_rx_lane_map_physical{225.0}=0x56410273
+phy_chain_tx_lane_map_physical{225.0}=0x10274635
+phy_chain_rx_lane_map_physical{233.0}=0x15740263
+phy_chain_tx_lane_map_physical{233.0}=0x24351607
+phy_chain_rx_lane_map_physical{241.0}=0x74015263
+phy_chain_tx_lane_map_physical{241.0}=0x04152637
+phy_chain_rx_lane_map_physical{249.0}=0x62037514
+phy_chain_tx_lane_map_physical{249.0}=0x72453160
+phy_chain_rx_lane_map_physical{161.0}=0x46510273
+phy_chain_tx_lane_map_physical{161.0}=0x01653724
+phy_chain_rx_lane_map_physical{169.0}=0x25743160
+phy_chain_tx_lane_map_physical{169.0}=0x07216435
+phy_chain_rx_lane_map_physical{177.0}=0x46510273
+phy_chain_tx_lane_map_physical{177.0}=0x01652734
+phy_chain_rx_lane_map_physical{185.0}=0x25743160
+phy_chain_tx_lane_map_physical{185.0}=0x37016425
+phy_chain_rx_lane_map_physical{193.0}=0x46510372
+phy_chain_tx_lane_map_physical{193.0}=0x06153724
+phy_chain_rx_lane_map_physical{201.0}=0x25743160
+phy_chain_tx_lane_map_physical{201.0}=0x36017524
+phy_chain_rx_lane_map_physical{209.0}=0x47601352
+phy_chain_tx_lane_map_physical{209.0}=0x04152736
+phy_chain_rx_lane_map_physical{217.0}=0x26453170
+phy_chain_tx_lane_map_physical{217.0}=0x36027415
+
+serdes_core_rx_polarity_flip_physical{33}=0x29
+serdes_core_tx_polarity_flip_physical{33}=0xfe
+serdes_core_rx_polarity_flip_physical{41}=0xb1
+serdes_core_tx_polarity_flip_physical{41}=0xe8
+serdes_core_rx_polarity_flip_physical{49}=0xca
+serdes_core_tx_polarity_flip_physical{49}=0xb6
+serdes_core_rx_polarity_flip_physical{57}=0x9b
+serdes_core_tx_polarity_flip_physical{57}=0xdc
+serdes_core_rx_polarity_flip_physical{65}=0x17
+serdes_core_tx_polarity_flip_physical{65}=0x86
+serdes_core_rx_polarity_flip_physical{73}=0x9b
+serdes_core_tx_polarity_flip_physical{73}=0x55
+serdes_core_rx_polarity_flip_physical{81}=0xa
+serdes_core_tx_polarity_flip_physical{81}=0x6
+serdes_core_rx_polarity_flip_physical{89}=0x9b
+serdes_core_tx_polarity_flip_physical{89}=0x48
+serdes_core_rx_polarity_flip_physical{1}=0xec
+serdes_core_tx_polarity_flip_physical{1}=0x56
+serdes_core_rx_polarity_flip_physical{9}=0x13
+serdes_core_tx_polarity_flip_physical{9}=0xa6
+serdes_core_rx_polarity_flip_physical{17}=0x5a
+serdes_core_tx_polarity_flip_physical{17}=0xc6
+serdes_core_rx_polarity_flip_physical{25}=0xf
+serdes_core_tx_polarity_flip_physical{25}=0x4e
+serdes_core_rx_polarity_flip_physical{97}=0x17
+serdes_core_tx_polarity_flip_physical{97}=0x2e
+serdes_core_rx_polarity_flip_physical{105}=0xce
+serdes_core_tx_polarity_flip_physical{105}=0x7c
+serdes_core_rx_polarity_flip_physical{113}=0xa
+serdes_core_tx_polarity_flip_physical{113}=0x35
+
+serdes_core_rx_polarity_flip_physical{121}=0xb9
+serdes_core_tx_polarity_flip_physical{121}=0xef
+serdes_core_rx_polarity_flip_physical{129}=0xe8
+serdes_core_tx_polarity_flip_physical{129}=0xac
+serdes_core_rx_polarity_flip_physical{137}=0xcb
+serdes_core_tx_polarity_flip_physical{137}=0x9c
+serdes_core_rx_polarity_flip_physical{145}=0x17
+serdes_core_tx_polarity_flip_physical{145}=0x32
+serdes_core_rx_polarity_flip_physical{153}=0xb9
+serdes_core_tx_polarity_flip_physical{153}=0xaf
+serdes_core_rx_polarity_flip_physical{225}=0xaa
+serdes_core_tx_polarity_flip_physical{225}=0x7
+serdes_core_rx_polarity_flip_physical{233}=0x31
+serdes_core_tx_polarity_flip_physical{233}=0x47
+serdes_core_rx_polarity_flip_physical{241}=0xe8
+serdes_core_tx_polarity_flip_physical{241}=0x9e
+serdes_core_rx_polarity_flip_physical{249}=0xec
+serdes_core_tx_polarity_flip_physical{249}=0x1f
+serdes_core_rx_polarity_flip_physical{161}=0x6a
+serdes_core_tx_polarity_flip_physical{161}=0xd4
+serdes_core_rx_polarity_flip_physical{169}=0x9e
+serdes_core_tx_polarity_flip_physical{169}=0x7b
+serdes_core_rx_polarity_flip_physical{177}=0x6a
+serdes_core_tx_polarity_flip_physical{177}=0xcc
+serdes_core_rx_polarity_flip_physical{185}=0x9e
+serdes_core_tx_polarity_flip_physical{185}=0x58
+serdes_core_rx_polarity_flip_physical{193}=0x6f
+serdes_core_tx_polarity_flip_physical{193}=0x24
+serdes_core_rx_polarity_flip_physical{201}=0x9e
+serdes_core_tx_polarity_flip_physical{201}=0xdf
+serdes_core_rx_polarity_flip_physical{209}=0x17
+serdes_core_tx_polarity_flip_physical{209}=0xe9
+serdes_core_rx_polarity_flip_physical{217}=0xec
+serdes_core_tx_polarity_flip_physical{217}=0x68
+
+
+dport_map_port_20=1
+dport_map_port_21=2
+dport_map_port_22=3
+dport_map_port_23=4
+dport_map_port_24=5
+dport_map_port_25=6
+dport_map_port_26=7
+dport_map_port_27=8
+dport_map_port_28=9
+dport_map_port_29=10
+dport_map_port_30=11
+dport_map_port_31=12
+dport_map_port_32=13
+dport_map_port_33=14
+dport_map_port_34=15
+dport_map_port_35=16
+dport_map_port_40=17
+dport_map_port_41=18
+dport_map_port_42=19
+dport_map_port_43=20
+dport_map_port_44=21
+dport_map_port_45=22
+dport_map_port_46=23
+dport_map_port_47=24
+dport_map_port_48=25
+dport_map_port_49=26
+dport_map_port_50=27
+dport_map_port_51=28
+dport_map_port_52=29
+dport_map_port_53=30
+dport_map_port_54=31
+dport_map_port_55=32
+dport_map_port_1=33
+dport_map_port_2=34
+dport_map_port_3=35
+dport_map_port_4=36
+dport_map_port_5=37
+dport_map_port_6=38
+dport_map_port_7=39
+dport_map_port_8=40
+dport_map_port_9=41
+dport_map_port_10=42
+dport_map_port_11=43
+dport_map_port_12=44
+dport_map_port_13=45
+dport_map_port_14=46
+dport_map_port_15=47
+dport_map_port_16=48
+dport_map_port_60=49
+dport_map_port_61=50
+dport_map_port_62=51
+dport_map_port_63=52
+dport_map_port_64=53
+dport_map_port_65=54
+dport_map_port_66=55
+dport_map_port_67=56
+dport_map_port_68=57
+dport_map_port_69=58
+dport_map_port_70=59
+dport_map_port_71=60
+dport_map_port_72=61
+dport_map_port_73=62
+dport_map_port_74=63
+dport_map_port_75=64
+dport_map_port_80=65
+dport_map_port_81=66
+dport_map_port_82=67
+dport_map_port_83=68
+dport_map_port_84=69
+dport_map_port_85=70
+dport_map_port_86=71
+dport_map_port_87=72
+dport_map_port_88=73
+dport_map_port_89=74
+dport_map_port_90=75
+dport_map_port_91=76
+dport_map_port_92=77
+dport_map_port_93=78
+dport_map_port_94=79
+dport_map_port_95=80
+dport_map_port_140=81
+dport_map_port_141=82
+dport_map_port_142=83
+dport_map_port_143=84
+dport_map_port_144=85
+dport_map_port_145=86
+dport_map_port_146=87
+dport_map_port_147=88
+dport_map_port_148=89
+dport_map_port_149=90
+dport_map_port_150=91
+dport_map_port_151=92
+dport_map_port_152=93
+dport_map_port_153=94
+dport_map_port_154=95
+dport_map_port_155=96
+dport_map_port_100=97
+dport_map_port_101=98
+dport_map_port_102=99
+dport_map_port_103=100
+dport_map_port_104=101
+dport_map_port_105=102
+dport_map_port_106=103
+dport_map_port_107=104
+dport_map_port_108=105
+dport_map_port_109=106
+dport_map_port_110=107
+dport_map_port_111=108
+dport_map_port_112=109
+dport_map_port_113=110
+dport_map_port_114=111
+dport_map_port_115=112
+dport_map_port_120=113
+dport_map_port_121=114
+dport_map_port_122=115
+dport_map_port_123=116
+dport_map_port_124=117
+dport_map_port_125=118
+dport_map_port_126=119
+dport_map_port_127=120
+dport_map_port_128=121
+dport_map_port_129=122
+dport_map_port_130=123
+dport_map_port_131=124
+dport_map_port_132=125
+dport_map_port_133=126
+dport_map_port_134=127
+dport_map_port_135=128
+
+core_clock_frequency=1325
+dpr_clock_frequency=1000
+device_clock_frequency=1325
+port_flex_enable=1
+
+#firmware load method, use fast load
+load_firmware=0x2
diff --git a/device/celestica/x86_64-cel_silverstone-r0/Silverstone/minigraph.xml b/device/celestica/x86_64-cel_silverstone-r0/Silverstone/minigraph.xml
new file mode 100644
index 000000000000..1904b64219eb
--- /dev/null
+++ b/device/celestica/x86_64-cel_silverstone-r0/Silverstone/minigraph.xml
@@ -0,0 +1,854 @@
+
+
+
+
+
+ ARISTA01T0
+ 10.0.0.33
+ sonic
+ 10.0.0.32
+ 1
+ 180
+ 60
+
+
+ sonic
+ 10.0.0.0
+ ARISTA01T2
+ 10.0.0.1
+ 1
+ 180
+ 60
+
+
+ ARISTA02T0
+ 10.0.0.35
+ sonic
+ 10.0.0.34
+ 1
+ 180
+ 60
+
+
+ sonic
+ 10.0.0.2
+ ARISTA02T2
+ 10.0.0.3
+ 1
+ 180
+ 60
+
+
+ ARISTA03T0
+ 10.0.0.37
+ sonic
+ 10.0.0.36
+ 1
+ 180
+ 60
+
+
+ sonic
+ 10.0.0.4
+ ARISTA03T2
+ 10.0.0.5
+ 1
+ 180
+ 60
+
+
+ ARISTA04T0
+ 10.0.0.39
+ sonic
+ 10.0.0.38
+ 1
+ 180
+ 60
+
+
+ sonic
+ 10.0.0.6
+ ARISTA04T2
+ 10.0.0.7
+ 1
+ 180
+ 60
+
+
+ ARISTA05T0
+ 10.0.0.41
+ sonic
+ 10.0.0.40
+ 1
+ 180
+ 60
+
+
+ sonic
+ 10.0.0.8
+ ARISTA05T2
+ 10.0.0.9
+ 1
+ 180
+ 60
+
+
+ ARISTA06T0
+ 10.0.0.43
+ sonic
+ 10.0.0.42
+ 1
+ 180
+ 60
+
+
+ sonic
+ 10.0.0.10
+ ARISTA06T2
+ 10.0.0.11
+ 1
+ 180
+ 60
+
+
+ ARISTA07T0
+ 10.0.0.45
+ sonic
+ 10.0.0.44
+ 1
+ 180
+ 60
+
+
+ sonic
+ 10.0.0.12
+ ARISTA07T2
+ 10.0.0.13
+ 1
+ 180
+ 60
+
+
+ ARISTA08T0
+ 10.0.0.47
+ sonic
+ 10.0.0.46
+ 1
+ 180
+ 60
+
+
+ sonic
+ 10.0.0.14
+ ARISTA08T2
+ 10.0.0.15
+ 1
+ 180
+ 60
+
+
+ ARISTA09T0
+ 10.0.0.49
+ sonic
+ 10.0.0.48
+ 1
+ 180
+ 60
+
+
+ sonic
+ 10.0.0.16
+ ARISTA09T2
+ 10.0.0.17
+ 1
+ 180
+ 60
+
+
+ ARISTA10T0
+ 10.0.0.51
+ sonic
+ 10.0.0.50
+ 1
+ 180
+ 60
+
+
+ sonic
+ 10.0.0.18
+ ARISTA10T2
+ 10.0.0.19
+ 1
+ 180
+ 60
+
+
+ ARISTA11T0
+ 10.0.0.53
+ sonic
+ 10.0.0.52
+ 1
+ 180
+ 60
+
+
+ sonic
+ 10.0.0.20
+ ARISTA11T2
+ 10.0.0.21
+ 1
+ 180
+ 60
+
+
+ ARISTA12T0
+ 10.0.0.55
+ sonic
+ 10.0.0.54
+ 1
+ 180
+ 60
+
+
+ sonic
+ 10.0.0.22
+ ARISTA12T2
+ 10.0.0.23
+ 1
+ 180
+ 60
+
+
+ ARISTA13T0
+ 10.0.0.57
+ sonic
+ 10.0.0.56
+ 1
+ 180
+ 60
+
+
+ sonic
+ 10.0.0.24
+ ARISTA13T2
+ 10.0.0.25
+ 1
+ 180
+ 60
+
+
+ ARISTA14T0
+ 10.0.0.59
+ sonic
+ 10.0.0.58
+ 1
+ 180
+ 60
+
+
+ sonic
+ 10.0.0.26
+ ARISTA14T2
+ 10.0.0.27
+ 1
+ 180
+ 60
+
+
+ ARISTA15T0
+ 10.0.0.61
+ sonic
+ 10.0.0.60
+ 1
+ 180
+ 60
+
+
+ sonic
+ 10.0.0.28
+ ARISTA15T2
+ 10.0.0.29
+ 1
+ 180
+ 60
+
+
+ ARISTA16T0
+ 10.0.0.63
+ sonic
+ 10.0.0.62
+ 1
+ 180
+ 60
+
+
+ sonic
+ 10.0.0.30
+ ARISTA16T2
+ 10.0.0.31
+ 1
+ 180
+ 60
+
+
+
+
+ 65100
+ sonic
+
+
+ 10.0.0.33
+
+
+
+
+ 10.0.0.1
+
+
+
+
+ 10.0.0.35
+
+
+
+
+ 10.0.0.3
+
+
+
+
+ 10.0.0.37
+
+
+
+
+ 10.0.0.5
+
+
+
+
+ 10.0.0.39
+
+
+
+
+ 10.0.0.7
+
+
+
+
+ 10.0.0.41
+
+
+
+
+ 10.0.0.9
+
+
+
+
+ 10.0.0.43
+
+
+
+
+ 10.0.0.11
+
+
+
+
+ 10.0.0.45
+
+
+
+
+ 10.0.0.13
+
+
+
+
+ 10.0.0.47
+
+
+
+
+ 10.0.0.15
+
+
+
+
+ 10.0.0.49
+
+
+
+
+ 10.0.0.17
+
+
+
+
+ 10.0.0.51
+
+
+
+
+ 10.0.0.19
+
+
+
+
+ 10.0.0.53
+
+
+
+
+ 10.0.0.21
+
+
+
+
+ 10.0.0.55
+
+
+
+
+ 10.0.0.23
+
+
+
+
+ 10.0.0.57
+
+
+
+
+ 10.0.0.25
+
+
+
+
+ 10.0.0.59
+
+
+
+
+ 10.0.0.27
+
+
+
+
+ 10.0.0.61
+
+
+
+
+ 10.0.0.29
+
+
+
+
+ 10.0.0.63
+
+
+
+
+ 10.0.0.31
+
+
+
+
+
+
+
+ 64001
+ ARISTA01T0
+
+
+
+ 65200
+ ARISTA01T2
+
+
+
+ 64002
+ ARISTA02T0
+
+
+
+ 65200
+ ARISTA02T2
+
+
+
+ 64003
+ ARISTA03T0
+
+
+
+ 65200
+ ARISTA03T2
+
+
+
+ 64004
+ ARISTA04T0
+
+
+
+ 65200
+ ARISTA04T2
+
+
+
+ 64005
+ ARISTA05T0
+
+
+
+ 65200
+ ARISTA05T2
+
+
+
+ 64006
+ ARISTA06T0
+
+
+
+ 65200
+ ARISTA06T2
+
+
+
+ 64007
+ ARISTA07T0
+
+
+
+ 65200
+ ARISTA07T2
+
+
+
+ 64008
+ ARISTA08T0
+
+
+
+ 65200
+ ARISTA08T2
+
+
+
+ 64009
+ ARISTA09T0
+
+
+
+ 65200
+ ARISTA09T2
+
+
+
+ 64010
+ ARISTA10T0
+
+
+
+ 65200
+ ARISTA10T2
+
+
+
+ 64011
+ ARISTA11T0
+
+
+
+ 65200
+ ARISTA11T2
+
+
+
+ 64012
+ ARISTA12T0
+
+
+
+ 65200
+ ARISTA12T2
+
+
+
+ 64013
+ ARISTA13T0
+
+
+
+ 65200
+ ARISTA13T2
+
+
+
+ 64014
+ ARISTA14T0
+
+
+
+ 65200
+ ARISTA14T2
+
+
+
+ 64015
+ ARISTA15T0
+
+
+
+ 65200
+ ARISTA15T2
+
+
+
+ 64016
+ ARISTA16T0
+
+
+
+ 65200
+ ARISTA16T2
+
+
+
+
+
+
+
+
+
+ HostIP
+ Loopback0
+
+ 10.1.0.32/32
+
+ 10.1.0.32/32
+
+
+
+
+
+
+
+ sonic
+
+
+
+
+
+ QSFPDD1
+ 10.0.0.0/31
+
+
+
+ QSFPDD2
+ 10.0.0.2/31
+
+
+
+ QSFPDD3
+ 10.0.0.4/31
+
+
+
+ QSFPDD4
+ 10.0.0.6/31
+
+
+
+ QSFPDD5
+ 10.0.0.8/31
+
+
+
+ QSFPDD6
+ 10.0.0.10/31
+
+
+
+ QSFPDD7
+ 10.0.0.12/31
+
+
+
+ QSFPDD8
+ 10.0.0.14/31
+
+
+
+ QSFPDD9
+ 10.0.0.16/31
+
+
+
+ QSFPDD10
+ 10.0.0.18/31
+
+
+
+ QSFPDD11
+ 10.0.0.20/31
+
+
+
+ QSFPDD12
+ 10.0.0.22/31
+
+
+
+ QSFPDD13
+ 10.0.0.24/31
+
+
+
+ QSFPDD14
+ 10.0.0.26/31
+
+
+
+ QSFPDD15
+ 10.0.0.28/31
+
+
+
+ QSFPDD16
+ 10.0.0.30/31
+
+
+
+ QSFPDD17
+ 10.0.0.32/31
+
+
+
+ QSFPDD18
+ 10.0.0.34/31
+
+
+
+ QSFPDD19
+ 10.0.0.36/31
+
+
+
+ QSFPDD20
+ 10.0.0.38/31
+
+
+
+ QSFPDD21
+ 10.0.0.40/31
+
+
+
+ QSFPDD22
+ 10.0.0.42/31
+
+
+
+ QSFPDD23
+ 10.0.0.44/31
+
+
+
+ QSFPDD24
+ 10.0.0.46/31
+
+
+
+ QSFPDD25
+ 10.0.0.48/31
+
+
+
+ QSFPDD26
+ 10.0.0.50/31
+
+
+
+ QSFPDD27
+ 10.0.0.52/31
+
+
+
+ QSFPDD28
+ 10.0.0.54/31
+
+
+
+ QSFPDD29
+ 10.0.0.56/31
+
+
+
+ QSFPDD30
+ 10.0.0.58/31
+
+
+
+ QSFPDD31
+ 10.0.0.60/31
+
+
+
+ QSFPDD32
+ 10.0.0.62/31
+
+
+
+
+
+
+
+
+
+
+
+
+ sonic
+ Silverstone
+
+
+
+
+
+
+ sonic
+
+
+ DhcpResources
+
+
+
+
+ NtpResources
+
+ 0.debian.pool.ntp.org;1.debian.pool.ntp.org;2.debian.pool.ntp.org;3.debian.pool.ntp.org
+
+
+ SyslogResources
+
+
+
+
+ ErspanDestinationIpv4
+
+ 2.2.2.2
+
+
+
+
+
+
+ sonic
+ Silverstone
+
diff --git a/device/celestica/x86_64-cel_silverstone-r0/Silverstone/port_config.ini b/device/celestica/x86_64-cel_silverstone-r0/Silverstone/port_config.ini
new file mode 100644
index 000000000000..32756e949299
--- /dev/null
+++ b/device/celestica/x86_64-cel_silverstone-r0/Silverstone/port_config.ini
@@ -0,0 +1,35 @@
+# name lanes alias index
+Ethernet0 33,34,35,36,37,38,39,40 QSFPDD1 1
+Ethernet4 41,42,43,44,45,46,47,48 QSFPDD2 2
+Ethernet8 49,50,51,52,53,54,55,56 QSFPDD3 3
+Ethernet12 57,58,59,60,61,62,63,64 QSFPDD4 4
+Ethernet16 65,66,67,68,69,70,71,72 QSFPDD5 5
+Ethernet20 73,74,75,76,77,78,79,80 QSFPDD6 6
+Ethernet24 81,82,83,84,85,86,87,88 QSFPDD7 7
+Ethernet28 89,90,91,92,93,94,95,96 QSFPDD8 8
+Ethernet32 1,2,3,4,5,6,7,8 QSFPDD9 9
+Ethernet36 9,10,11,12,13,14,15,16 QSFPDD10 10
+Ethernet40 17,18,19,20,21,22,23,24 QSFPDD11 11
+Ethernet44 25,26,27,28,29,30,31,32 QSFPDD12 12
+Ethernet48 97,98,99,100,101,102,103,104 QSFPDD13 13
+Ethernet52 105,106,107,108,109,110,111,112 QSFPDD14 14
+Ethernet56 113,114,115,116,117,118,119,120 QSFPDD15 15
+Ethernet60 121,122,123,124,125,126,127,128 QSFPDD16 16
+Ethernet64 129,130,131,132,133,134,135,136 QSFPDD17 17
+Ethernet68 137,138,139,140,141,142,143,144 QSFPDD18 18
+Ethernet72 145,146,147,148,149,150,151,152 QSFPDD19 19
+Ethernet76 153,154,155,156,157,158,159,160 QSFPDD20 20
+Ethernet80 225,226,227,228,229,230,231,232 QSFPDD21 21
+Ethernet84 233,234,235,236,237,238,239,240 QSFPDD22 22
+Ethernet88 241,242,243,244,245,246,247,248 QSFPDD23 23
+Ethernet92 249,250,251,252,253,254,255,256 QSFPDD24 24
+Ethernet96 161,162,163,164,165,166,167,168 QSFPDD25 25
+Ethernet100 169,170,171,172,173,174,175,176 QSFPDD26 26
+Ethernet104 177,178,179,180,181,182,183,184 QSFPDD27 27
+Ethernet108 185,186,187,188,189,190,191,192 QSFPDD28 28
+Ethernet112 193,194,195,196,197,198,199,200 QSFPDD29 29
+Ethernet116 201,202,203,204,205,206,207,208 QSFPDD30 30
+Ethernet120 209,210,211,212,213,214,215,216 QSFPDD31 31
+Ethernet124 217,218,219,220,221,222,223,224 QSFPDD32 32
+Ethernet125 257 SFP1 33
+Ethernet126 258 SFP2 34
diff --git a/device/celestica/x86_64-cel_silverstone-r0/Silverstone/sai.profile b/device/celestica/x86_64-cel_silverstone-r0/Silverstone/sai.profile
new file mode 100644
index 000000000000..f028faf377ea
--- /dev/null
+++ b/device/celestica/x86_64-cel_silverstone-r0/Silverstone/sai.profile
@@ -0,0 +1 @@
+SAI_INIT_CONFIG_FILE=/usr/share/sonic/platform/th3-32x400G.config.bcm
diff --git a/device/celestica/x86_64-cel_silverstone-r0/Silverstone/th3-32x400G.config.bcm b/device/celestica/x86_64-cel_silverstone-r0/Silverstone/th3-32x400G.config.bcm
new file mode 100644
index 000000000000..f53d098a5575
--- /dev/null
+++ b/device/celestica/x86_64-cel_silverstone-r0/Silverstone/th3-32x400G.config.bcm
@@ -0,0 +1,231 @@
+
+pbmp_xport_xe.0=0x8111181111c1111811118111181111c111182222
+ccm_dma_enable=0
+ccmdma_intr_enable=0
+ctr_evict_enable=0
+mem_cache_enable=0
+parity_correction=0
+parity_enable=0
+phy_enable=0
+phy_null=1
+pll_bypass=1
+
+init_all_modules=0
+
+
+
+portmap_38=257:10
+portmap_118=258:10
+
+
+portmap_20=33:400
+portmap_24=41:400
+portmap_28=49:400
+portmap_32=57:400
+portmap_40=65:400
+portmap_44=73:400
+portmap_48=81:400
+portmap_52=89:400
+portmap_1=1:400
+portmap_5=9:400
+portmap_9=17:400
+portmap_13=25:400
+portmap_60=97:400
+portmap_64=105:400
+portmap_68=113:400
+portmap_72=121:400
+portmap_80=129:400
+portmap_84=137:400
+portmap_88=145:400
+portmap_92=153:400
+portmap_140=225:400
+portmap_144=233:400
+portmap_148=241:400
+portmap_152=249:400
+portmap_100=161:400
+portmap_104=169:400
+portmap_108=177:400
+portmap_112=185:400
+portmap_120=193:400
+portmap_124=201:400
+portmap_128=209:400
+portmap_132=217:400
+
+phy_chain_rx_lane_map_physical{33.0}=0x65732041
+phy_chain_tx_lane_map_physical{33.0}=0x47206531
+phy_chain_rx_lane_map_physical{41.0}=0x07561243
+phy_chain_tx_lane_map_physical{41.0}=0x36207514
+phy_chain_rx_lane_map_physical{49.0}=0x54632071
+phy_chain_tx_lane_map_physical{49.0}=0x06241735
+phy_chain_rx_lane_map_physical{57.0}=0x07561243
+phy_chain_tx_lane_map_physical{57.0}=0x35207614
+phy_chain_rx_lane_map_physical{65.0}=0x45623170
+phy_chain_tx_lane_map_physical{65.0}=0x51260734
+phy_chain_rx_lane_map_physical{73.0}=0x07561243
+phy_chain_tx_lane_map_physical{73.0}=0x37245610
+phy_chain_rx_lane_map_physical{81.0}=0x45632071
+phy_chain_tx_lane_map_physical{81.0}=0x51260734
+phy_chain_rx_lane_map_physical{89.0}=0x07561243
+phy_chain_tx_lane_map_physical{89.0}=0x26437510
+phy_chain_rx_lane_map_physical{1.0}=0x30176524
+phy_chain_tx_lane_map_physical{1.0}=0x20615374
+phy_chain_rx_lane_map_physical{9.0}=0x37562041
+phy_chain_tx_lane_map_physical{9.0}=0x05176432
+phy_chain_rx_lane_map_physical{17.0}=0x43607251
+phy_chain_tx_lane_map_physical{17.0}=0x70261435
+phy_chain_rx_lane_map_physical{25.0}=0x60347125
+phy_chain_tx_lane_map_physical{25.0}=0x46357120
+phy_chain_rx_lane_map_physical{97.0}=0x47601352
+phy_chain_tx_lane_map_physical{97.0}=0x04265137
+phy_chain_rx_lane_map_physical{105.0}=0x73206415
+phy_chain_tx_lane_map_physical{105.0}=0x26374150
+phy_chain_rx_lane_map_physical{113.0}=0x47632051
+phy_chain_tx_lane_map_physical{113.0}=0x03254617
+phy_chain_rx_lane_map_physical{121.0}=0x63027415
+phy_chain_tx_lane_map_physical{121.0}=0x63721045
+phy_chain_rx_lane_map_physical{129.0}=0x30154627
+phy_chain_tx_lane_map_physical{129.0}=0x04735261
+phy_chain_rx_lane_map_physical{137.0}=0x24753061
+phy_chain_tx_lane_map_physical{137.0}=0x37614520
+phy_chain_rx_lane_map_physical{145.0}=0x47601352
+phy_chain_tx_lane_map_physical{145.0}=0x63274510
+phy_chain_rx_lane_map_physical{153.0}=0x07361524
+phy_chain_tx_lane_map_physical{153.0}=0x36527104
+phy_chain_rx_lane_map_physical{225.0}=0x56410273
+phy_chain_tx_lane_map_physical{225.0}=0x10274635
+phy_chain_rx_lane_map_physical{233.0}=0x15740263
+phy_chain_tx_lane_map_physical{233.0}=0x24351607
+phy_chain_rx_lane_map_physical{241.0}=0x74015263
+phy_chain_tx_lane_map_physical{241.0}=0x04152637
+phy_chain_rx_lane_map_physical{249.0}=0x62037514
+phy_chain_tx_lane_map_physical{249.0}=0x72453160
+phy_chain_rx_lane_map_physical{161.0}=0x46510273
+phy_chain_tx_lane_map_physical{161.0}=0x01653724
+phy_chain_rx_lane_map_physical{169.0}=0x25743160
+phy_chain_tx_lane_map_physical{169.0}=0x07216435
+phy_chain_rx_lane_map_physical{177.0}=0x46510273
+phy_chain_tx_lane_map_physical{177.0}=0x01652734
+phy_chain_rx_lane_map_physical{185.0}=0x25743160
+phy_chain_tx_lane_map_physical{185.0}=0x37016425
+phy_chain_rx_lane_map_physical{193.0}=0x46510372
+phy_chain_tx_lane_map_physical{193.0}=0x06153724
+phy_chain_rx_lane_map_physical{201.0}=0x25743160
+phy_chain_tx_lane_map_physical{201.0}=0x36017524
+phy_chain_rx_lane_map_physical{209.0}=0x47601352
+phy_chain_tx_lane_map_physical{209.0}=0x04152736
+phy_chain_rx_lane_map_physical{217.0}=0x26453170
+phy_chain_tx_lane_map_physical{217.0}=0x36027415
+
+serdes_core_rx_polarity_flip_physical{33}=0x29
+serdes_core_tx_polarity_flip_physical{33}=0xfe
+serdes_core_rx_polarity_flip_physical{41}=0xb1
+serdes_core_tx_polarity_flip_physical{41}=0xe8
+serdes_core_rx_polarity_flip_physical{49}=0xca
+serdes_core_tx_polarity_flip_physical{49}=0xb6
+serdes_core_rx_polarity_flip_physical{57}=0x9b
+serdes_core_tx_polarity_flip_physical{57}=0xdc
+serdes_core_rx_polarity_flip_physical{65}=0x17
+serdes_core_tx_polarity_flip_physical{65}=0x86
+serdes_core_rx_polarity_flip_physical{73}=0x9b
+serdes_core_tx_polarity_flip_physical{73}=0x55
+serdes_core_rx_polarity_flip_physical{81}=0xa
+serdes_core_tx_polarity_flip_physical{81}=0x6
+serdes_core_rx_polarity_flip_physical{89}=0x9b
+serdes_core_tx_polarity_flip_physical{89}=0x48
+serdes_core_rx_polarity_flip_physical{1}=0xec
+serdes_core_tx_polarity_flip_physical{1}=0x56
+serdes_core_rx_polarity_flip_physical{9}=0x13
+serdes_core_tx_polarity_flip_physical{9}=0xa6
+serdes_core_rx_polarity_flip_physical{17}=0x5a
+serdes_core_tx_polarity_flip_physical{17}=0xc6
+serdes_core_rx_polarity_flip_physical{25}=0xf
+serdes_core_tx_polarity_flip_physical{25}=0x4e
+serdes_core_rx_polarity_flip_physical{97}=0x17
+serdes_core_tx_polarity_flip_physical{97}=0x2e
+serdes_core_rx_polarity_flip_physical{105}=0xce
+serdes_core_tx_polarity_flip_physical{105}=0x7c
+serdes_core_rx_polarity_flip_physical{113}=0xa
+serdes_core_tx_polarity_flip_physical{113}=0x35
+
+serdes_core_rx_polarity_flip_physical{121}=0xb9
+serdes_core_tx_polarity_flip_physical{121}=0xef
+serdes_core_rx_polarity_flip_physical{129}=0xe8
+serdes_core_tx_polarity_flip_physical{129}=0xac
+serdes_core_rx_polarity_flip_physical{137}=0xcb
+serdes_core_tx_polarity_flip_physical{137}=0x9c
+serdes_core_rx_polarity_flip_physical{145}=0x17
+serdes_core_tx_polarity_flip_physical{145}=0x32
+serdes_core_rx_polarity_flip_physical{153}=0xb9
+serdes_core_tx_polarity_flip_physical{153}=0xaf
+serdes_core_rx_polarity_flip_physical{225}=0xaa
+serdes_core_tx_polarity_flip_physical{225}=0x7
+serdes_core_rx_polarity_flip_physical{233}=0x31
+serdes_core_tx_polarity_flip_physical{233}=0x47
+serdes_core_rx_polarity_flip_physical{241}=0xe8
+serdes_core_tx_polarity_flip_physical{241}=0x9e
+serdes_core_rx_polarity_flip_physical{249}=0xec
+serdes_core_tx_polarity_flip_physical{249}=0x1f
+serdes_core_rx_polarity_flip_physical{161}=0x6a
+serdes_core_tx_polarity_flip_physical{161}=0xd4
+serdes_core_rx_polarity_flip_physical{169}=0x9e
+serdes_core_tx_polarity_flip_physical{169}=0x7b
+serdes_core_rx_polarity_flip_physical{177}=0x6a
+serdes_core_tx_polarity_flip_physical{177}=0xcc
+serdes_core_rx_polarity_flip_physical{185}=0x9e
+serdes_core_tx_polarity_flip_physical{185}=0x58
+serdes_core_rx_polarity_flip_physical{193}=0x6f
+serdes_core_tx_polarity_flip_physical{193}=0x24
+serdes_core_rx_polarity_flip_physical{201}=0x9e
+serdes_core_tx_polarity_flip_physical{201}=0xdf
+serdes_core_rx_polarity_flip_physical{209}=0x17
+serdes_core_tx_polarity_flip_physical{209}=0xe9
+serdes_core_rx_polarity_flip_physical{217}=0xec
+serdes_core_tx_polarity_flip_physical{217}=0x68
+
+dport_map_port_20=1
+dport_map_port_24=2
+dport_map_port_28=3
+dport_map_port_32=4
+dport_map_port_40=5
+dport_map_port_44=6
+dport_map_port_48=7
+dport_map_port_52=8
+dport_map_port_1=9
+dport_map_port_5=10
+dport_map_port_9=11
+dport_map_port_13=12
+dport_map_port_60=13
+dport_map_port_64=14
+dport_map_port_68=15
+dport_map_port_72=16
+dport_map_port_80=17
+dport_map_port_84=18
+dport_map_port_88=19
+dport_map_port_92=20
+dport_map_port_140=21
+dport_map_port_144=22
+dport_map_port_148=23
+dport_map_port_152=24
+dport_map_port_100=25
+dport_map_port_104=26
+dport_map_port_108=27
+dport_map_port_112=28
+dport_map_port_120=29
+dport_map_port_124=30
+dport_map_port_128=31
+dport_map_port_132=32
+
+dport_map_port_38=33
+dport_map_port_118=34
+
+
+
+core_clock_frequency=1325
+dpr_clock_frequency=1000
+device_clock_frequency=1325
+port_flex_enable=1
+
+#firmware load method, use fast load
+load_firmware=0x2
+
+
diff --git a/device/celestica/x86_64-cel_silverstone-r0/custom.bin b/device/celestica/x86_64-cel_silverstone-r0/custom.bin
new file mode 100644
index 000000000000..a08ba6c06661
Binary files /dev/null and b/device/celestica/x86_64-cel_silverstone-r0/custom.bin differ
diff --git a/device/celestica/x86_64-cel_silverstone-r0/default_sku b/device/celestica/x86_64-cel_silverstone-r0/default_sku
new file mode 100644
index 000000000000..07d986a8431d
--- /dev/null
+++ b/device/celestica/x86_64-cel_silverstone-r0/default_sku
@@ -0,0 +1 @@
+Silverstone t1
diff --git a/device/celestica/x86_64-cel_silverstone-r0/installer.conf b/device/celestica/x86_64-cel_silverstone-r0/installer.conf
new file mode 100644
index 000000000000..5e62742c11bf
--- /dev/null
+++ b/device/celestica/x86_64-cel_silverstone-r0/installer.conf
@@ -0,0 +1 @@
+CONSOLE_SPEED=115200
diff --git a/device/celestica/x86_64-cel_silverstone-r0/led_proc_init.soc b/device/celestica/x86_64-cel_silverstone-r0/led_proc_init.soc
new file mode 100644
index 000000000000..b01d62353ff2
--- /dev/null
+++ b/device/celestica/x86_64-cel_silverstone-r0/led_proc_init.soc
@@ -0,0 +1,12 @@
+#Enable all ports
+sleep 6
+port all en=1
+#sleep 6
+#linkscan 250000; port xe,ce linkscan=on
+
+#Load LED
+#m0 load 0 0x0 /usr/share/sonic/platform/linkscan_led_fw.bin
+#m0 load 0 0x3800 /usr/share/sonic/platform/custom_led.bin
+#led auto on; led start
+
+
diff --git a/device/celestica/x86_64-cel_silverstone-r0/linkscan_fw.bin b/device/celestica/x86_64-cel_silverstone-r0/linkscan_fw.bin
new file mode 100644
index 000000000000..e86cdc1ef647
Binary files /dev/null and b/device/celestica/x86_64-cel_silverstone-r0/linkscan_fw.bin differ
diff --git a/device/celestica/x86_64-cel_silverstone-r0/minigraph.xml b/device/celestica/x86_64-cel_silverstone-r0/minigraph.xml
new file mode 100644
index 000000000000..5e204776cb63
--- /dev/null
+++ b/device/celestica/x86_64-cel_silverstone-r0/minigraph.xml
@@ -0,0 +1,1333 @@
+
+
+
+
+
+ ARISTA01T0
+ 10.0.0.33
+ sonic
+ 10.0.0.32
+ 1
+ 180
+ 60
+
+
+ sonic
+ 10.0.0.0
+ ARISTA01T2
+ 10.0.0.1
+ 1
+ 180
+ 60
+
+
+ ARISTA02T0
+ 10.0.0.35
+ sonic
+ 10.0.0.34
+ 1
+ 180
+ 60
+
+
+ sonic
+ 10.0.0.2
+ ARISTA02T2
+ 10.0.0.3
+ 1
+ 180
+ 60
+
+
+ ARISTA03T0
+ 10.0.0.37
+ sonic
+ 10.0.0.36
+ 1
+ 180
+ 60
+
+
+ sonic
+ 10.0.0.4
+ ARISTA03T2
+ 10.0.0.5
+ 1
+ 180
+ 60
+
+
+ ARISTA04T0
+ 10.0.0.39
+ sonic
+ 10.0.0.38
+ 1
+ 180
+ 60
+
+
+ sonic
+ 10.0.0.6
+ ARISTA04T2
+ 10.0.0.7
+ 1
+ 180
+ 60
+
+
+ ARISTA05T0
+ 10.0.0.41
+ sonic
+ 10.0.0.40
+ 1
+ 180
+ 60
+
+
+ sonic
+ 10.0.0.8
+ ARISTA05T2
+ 10.0.0.9
+ 1
+ 180
+ 60
+
+
+ ARISTA06T0
+ 10.0.0.43
+ sonic
+ 10.0.0.42
+ 1
+ 180
+ 60
+
+
+ sonic
+ 10.0.0.10
+ ARISTA06T2
+ 10.0.0.11
+ 1
+ 180
+ 60
+
+
+ ARISTA07T0
+ 10.0.0.45
+ sonic
+ 10.0.0.44
+ 1
+ 180
+ 60
+
+
+ sonic
+ 10.0.0.12
+ ARISTA07T2
+ 10.0.0.13
+ 1
+ 180
+ 60
+
+
+ ARISTA08T0
+ 10.0.0.47
+ sonic
+ 10.0.0.46
+ 1
+ 180
+ 60
+
+
+ sonic
+ 10.0.0.14
+ ARISTA08T2
+ 10.0.0.15
+ 1
+ 180
+ 60
+
+
+ ARISTA09T0
+ 10.0.0.49
+ sonic
+ 10.0.0.48
+ 1
+ 180
+ 60
+
+
+ sonic
+ 10.0.0.16
+ ARISTA09T2
+ 10.0.0.17
+ 1
+ 180
+ 60
+
+
+ ARISTA10T0
+ 10.0.0.51
+ sonic
+ 10.0.0.50
+ 1
+ 180
+ 60
+
+
+ sonic
+ 10.0.0.18
+ ARISTA10T2
+ 10.0.0.19
+ 1
+ 180
+ 60
+
+
+ ARISTA11T0
+ 10.0.0.53
+ sonic
+ 10.0.0.52
+ 1
+ 180
+ 60
+
+
+ sonic
+ 10.0.0.20
+ ARISTA11T2
+ 10.0.0.21
+ 1
+ 180
+ 60
+
+
+ ARISTA12T0
+ 10.0.0.55
+ sonic
+ 10.0.0.54
+ 1
+ 180
+ 60
+
+
+ sonic
+ 10.0.0.22
+ ARISTA12T2
+ 10.0.0.23
+ 1
+ 180
+ 60
+
+
+ ARISTA13T0
+ 10.0.0.57
+ sonic
+ 10.0.0.56
+ 1
+ 180
+ 60
+
+
+ sonic
+ 10.0.0.24
+ ARISTA13T2
+ 10.0.0.25
+ 1
+ 180
+ 60
+
+
+ ARISTA14T0
+ 10.0.0.59
+ sonic
+ 10.0.0.58
+ 1
+ 180
+ 60
+
+
+ sonic
+ 10.0.0.26
+ ARISTA14T2
+ 10.0.0.27
+ 1
+ 180
+ 60
+
+
+ ARISTA15T0
+ 10.0.0.61
+ sonic
+ 10.0.0.60
+ 1
+ 180
+ 60
+
+
+ sonic
+ 10.0.0.28
+ ARISTA15T2
+ 10.0.0.29
+ 1
+ 180
+ 60
+
+
+ ARISTA16T0
+ 10.0.0.63
+ sonic
+ 10.0.0.62
+ 1
+ 180
+ 60
+
+
+ sonic
+ 10.0.0.30
+ ARISTA16T2
+ 10.0.0.31
+ 1
+ 180
+ 60
+
+
+
+
+ 65100
+ sonic
+
+
+ 10.0.0.33
+
+
+
+
+ 10.0.0.1
+
+
+
+
+ 10.0.0.35
+
+
+
+
+ 10.0.0.3
+
+
+
+
+ 10.0.0.37
+
+
+
+
+ 10.0.0.5
+
+
+
+
+ 10.0.0.39
+
+
+
+
+ 10.0.0.7
+
+
+
+
+ 10.0.0.41
+
+
+
+
+ 10.0.0.9
+
+
+
+
+ 10.0.0.43
+
+
+
+
+ 10.0.0.11
+
+
+
+
+ 10.0.0.45
+
+
+
+
+ 10.0.0.13
+
+
+
+
+ 10.0.0.47
+
+
+
+
+ 10.0.0.15
+
+
+
+
+ 10.0.0.49
+
+
+
+
+ 10.0.0.17
+
+
+
+
+ 10.0.0.51
+
+
+
+
+ 10.0.0.19
+
+
+
+
+ 10.0.0.53
+
+
+
+
+ 10.0.0.21
+
+
+
+
+ 10.0.0.55
+
+
+
+
+ 10.0.0.23
+
+
+
+
+ 10.0.0.57
+
+
+
+
+ 10.0.0.25
+
+
+
+
+ 10.0.0.59
+
+
+
+
+ 10.0.0.27
+
+
+
+
+ 10.0.0.61
+
+
+
+
+ 10.0.0.29
+
+
+
+
+ 10.0.0.63
+
+
+
+
+ 10.0.0.31
+
+
+
+
+
+
+
+ 64001
+ ARISTA01T0
+
+
+
+ 65200
+ ARISTA01T2
+
+
+
+ 64002
+ ARISTA02T0
+
+
+
+ 65200
+ ARISTA02T2
+
+
+
+ 64003
+ ARISTA03T0
+
+
+
+ 65200
+ ARISTA03T2
+
+
+
+ 64004
+ ARISTA04T0
+
+
+
+ 65200
+ ARISTA04T2
+
+
+
+ 64005
+ ARISTA05T0
+
+
+
+ 65200
+ ARISTA05T2
+
+
+
+ 64006
+ ARISTA06T0
+
+
+
+ 65200
+ ARISTA06T2
+
+
+
+ 64007
+ ARISTA07T0
+
+
+
+ 65200
+ ARISTA07T2
+
+
+
+ 64008
+ ARISTA08T0
+
+
+
+ 65200
+ ARISTA08T2
+
+
+
+ 64009
+ ARISTA09T0
+
+
+
+ 65200
+ ARISTA09T2
+
+
+
+ 64010
+ ARISTA10T0
+
+
+
+ 65200
+ ARISTA10T2
+
+
+
+ 64011
+ ARISTA11T0
+
+
+
+ 65200
+ ARISTA11T2
+
+
+
+ 64012
+ ARISTA12T0
+
+
+
+ 65200
+ ARISTA12T2
+
+
+
+ 64013
+ ARISTA13T0
+
+
+
+ 65200
+ ARISTA13T2
+
+
+
+ 64014
+ ARISTA14T0
+
+
+
+ 65200
+ ARISTA14T2
+
+
+
+ 64015
+ ARISTA15T0
+
+
+
+ 65200
+ ARISTA15T2
+
+
+
+ 64016
+ ARISTA16T0
+
+
+
+ 65200
+ ARISTA16T2
+
+
+
+
+
+
+
+
+
+ HostIP
+ Loopback0
+
+ 10.1.0.32/32
+
+ 10.1.0.32/32
+
+
+
+
+
+
+
+ sonic
+
+
+
+
+
+ QSFP1
+ 10.0.0.0/31
+
+
+
+ QSFP2
+ 10.0.0.2/31
+
+
+
+ QSFP3
+ 10.0.0.4/31
+
+
+
+ QSFP4
+ 10.0.0.6/31
+
+
+
+ QSFP5
+ 10.0.0.8/31
+
+
+
+ QSFP6
+ 10.0.0.10/31
+
+
+
+ QSFP7
+ 10.0.0.12/31
+
+
+
+ QSFP8
+ 10.0.0.14/31
+
+
+
+ QSFP9
+ 10.0.0.16/31
+
+
+
+ QSFP10
+ 10.0.0.18/31
+
+
+
+ QSFP11
+ 10.0.0.20/31
+
+
+
+ QSFP12
+ 10.0.0.22/31
+
+
+
+ QSFP13
+ 10.0.0.24/31
+
+
+
+ QSFP14
+ 10.0.0.26/31
+
+
+
+ QSFP15
+ 10.0.0.28/31
+
+
+
+ QSFP16
+ 10.0.0.30/31
+
+
+
+ QSFP17
+ 10.0.0.32/31
+
+
+
+ QSFP18
+ 10.0.0.34/31
+
+
+
+ QSFP19
+ 10.0.0.36/31
+
+
+
+ QSFP20
+ 10.0.0.38/31
+
+
+
+ QSFP21
+ 10.0.0.40/31
+
+
+
+ QSFP22
+ 10.0.0.42/31
+
+
+
+ QSFP23
+ 10.0.0.44/31
+
+
+
+ QSFP24
+ 10.0.0.46/31
+
+
+
+ QSFP25
+ 10.0.0.48/31
+
+
+
+ QSFP26
+ 10.0.0.50/31
+
+
+
+ QSFP27
+ 10.0.0.52/31
+
+
+
+ QSFP28
+ 10.0.0.54/31
+
+
+
+ QSFP29
+ 10.0.0.56/31
+
+
+
+ QSFP30
+ 10.0.0.58/31
+
+
+
+ QSFP31
+ 10.0.0.60/31
+
+
+
+ QSFP32
+ 10.0.0.62/31
+
+
+
+ QSFP33
+ 10.0.0.64/31
+
+
+
+ QSFP34
+ 10.0.0.66/31
+
+
+
+ QSFP35
+ 10.0.0.68/31
+
+
+
+ QSFP36
+ 10.0.0.70/31
+
+
+
+ QSFP37
+ 10.0.0.72/31
+
+
+
+ QSFP38
+ 10.0.0.74/31
+
+
+
+ QSFP39
+ 10.0.0.76/31
+
+
+
+ QSFP40
+ 10.0.0.78/31
+
+
+
+ QSFP41
+ 10.0.0.80/31
+
+
+
+ QSFP42
+ 10.0.0.82/31
+
+
+
+ QSFP43
+ 10.0.0.84/31
+
+
+
+ QSFP44
+ 10.0.0.86/31
+
+
+
+ QSFP45
+ 10.0.0.88/31
+
+
+
+ QSFP46
+ 10.0.0.90/31
+
+
+
+ QSFP47
+ 10.0.0.92/31
+
+
+
+ QSFP48
+ 10.0.0.94/31
+
+
+
+ QSFP49
+ 10.0.0.96/31
+
+
+
+ QSFP50
+ 10.0.0.98/31
+
+
+
+ QSFP51
+ 10.0.0.100/31
+
+
+
+ QSFP52
+ 10.0.0.102/31
+
+
+
+ QSFP53
+ 10.0.0.104/31
+
+
+
+ QSFP54
+ 10.0.0.106/31
+
+
+
+ QSFP55
+ 10.0.0.108/31
+
+
+
+ QSFP56
+ 10.0.0.110/31
+
+
+
+ QSFP57
+ 10.0.0.112/31
+
+
+
+ QSFP58
+ 10.0.0.114/31
+
+
+
+ QSFP59
+ 10.0.0.116/31
+
+
+
+ QSFP60
+ 10.0.0.118/31
+
+
+
+ QSFP61
+ 10.0.0.120/31
+
+
+
+ QSFP62
+ 10.0.0.122/31
+
+
+
+ QSFP63
+ 10.0.0.124/31
+
+
+
+ QSFP64
+ 10.0.0.126/31
+
+
+
+ QSFP65
+ 10.0.1.0/31
+
+
+
+ QSFP66
+ 10.0.1.2/31
+
+
+
+ QSFP67
+ 10.0.1.4/31
+
+
+
+ QSFP68
+ 10.0.1.6/31
+
+
+
+ QSFP69
+ 10.0.1.8/31
+
+
+
+ QSFP70
+ 10.0.1.10/31
+
+
+
+ QSFP71
+ 10.0.1.12/31
+
+
+
+ QSFP72
+ 10.0.1.14/31
+
+
+
+ QSFP73
+ 10.0.1.16/31
+
+
+
+ QSFP74
+ 10.0.1.18/31
+
+
+
+ QSFP75
+ 10.0.1.20/31
+
+
+
+ QSFP76
+ 10.0.1.22/31
+
+
+
+ QSFP77
+ 10.0.1.24/31
+
+
+
+ QSFP78
+ 10.0.1.26/31
+
+
+
+ QSFP79
+ 10.0.1.28/31
+
+
+
+ QSFP80
+ 10.0.1.30/31
+
+
+
+ QSFP81
+ 10.0.1.32/31
+
+
+
+ QSFP82
+ 10.0.1.34/31
+
+
+
+ QSFP83
+ 10.0.1.36/31
+
+
+
+ QSFP84
+ 10.0.1.38/31
+
+
+
+ QSFP85
+ 10.0.1.40/31
+
+
+
+ QSFP86
+ 10.0.1.42/31
+
+
+
+ QSFP87
+ 10.0.1.44/31
+
+
+
+ QSFP88
+ 10.0.1.46/31
+
+
+
+ QSFP89
+ 10.0.1.48/31
+
+
+
+ QSFP90
+ 10.0.1.50/31
+
+
+
+ QSFP91
+ 10.0.1.52/31
+
+
+
+ QSFP92
+ 10.0.1.54/31
+
+
+
+ QSFP93
+ 10.0.1.56/31
+
+
+
+ QSFP94
+ 10.0.1.58/31
+
+
+
+ QSFP95
+ 10.0.1.60/31
+
+
+
+ QSFP96
+ 10.0.1.62/31
+
+
+
+ QSFP97
+ 10.0.1.64/31
+
+
+
+ QSFP98
+ 10.0.1.66/31
+
+
+
+ QSFP99
+ 10.0.1.68/31
+
+
+
+ QSFP100
+ 10.0.1.70/31
+
+
+
+ QSFP101
+ 10.0.1.72/31
+
+
+
+ QSFP102
+ 10.0.1.74/31
+
+
+
+ QSFP103
+ 10.0.1.76/31
+
+
+
+ QSFP104
+ 10.0.1.78/31
+
+
+
+ QSFP105
+ 10.0.1.80/31
+
+
+
+ QSFP106
+ 10.0.1.82/31
+
+
+
+ QSFP107
+ 10.0.1.84/31
+
+
+
+ QSFP108
+ 10.0.1.86/31
+
+
+
+ QSFP109
+ 10.0.1.88/31
+
+
+
+ QSFP110
+ 10.0.1.90/31
+
+
+
+ QSFP111
+ 10.0.1.92/31
+
+
+
+ QSFP112
+ 10.0.1.94/31
+
+
+
+ QSFP113
+ 10.0.1.96/31
+
+
+
+ QSFP114
+ 10.0.1.98/31
+
+
+
+ QSFP115
+ 10.0.1.100/31
+
+
+
+ QSFP116
+ 10.0.1.102/31
+
+
+
+ QSFP117
+ 10.0.1.104/31
+
+
+
+ QSFP118
+ 10.0.1.106/31
+
+
+
+ QSFP119
+ 10.0.1.108/31
+
+
+
+ QSFP120
+ 10.0.1.110/31
+
+
+
+ QSFP121
+ 10.0.1.112/31
+
+
+
+ QSFP122
+ 10.0.1.114/31
+
+
+
+ QSFP123
+ 10.0.1.116/31
+
+
+
+ QSFP124
+ 10.0.1.118/31
+
+
+
+ QSFP125
+ 10.0.1.120/31
+
+
+
+ QSFP126
+ 10.0.1.122/31
+
+
+
+ QSFP127
+ 10.0.1.124/31
+
+
+
+ QSFP128
+ 10.0.1.126/31
+
+
+
+
+
+
+
+
+
+
+
+ sonic
+ Silverstone-128x100
+
+
+
+
+
+
+ sonic
+
+
+ DhcpResources
+
+
+
+
+ NtpResources
+
+ 0.debian.pool.ntp.org;1.debian.pool.ntp.org;2.debian.pool.ntp.org;3.debian.pool.ntp.org
+
+
+ SyslogResources
+
+
+
+
+ ErspanDestinationIpv4
+
+ 2.2.2.2
+
+
+
+
+
+
+ sonic
+ Silverstone-128x100
+
diff --git a/device/celestica/x86_64-cel_silverstone-r0/plugins/eeprom.py b/device/celestica/x86_64-cel_silverstone-r0/plugins/eeprom.py
new file mode 100644
index 000000000000..34c50a6ce31f
--- /dev/null
+++ b/device/celestica/x86_64-cel_silverstone-r0/plugins/eeprom.py
@@ -0,0 +1,23 @@
+#!/usr/bin/env python
+
+#############################################################################
+# Celestica Silverstone
+#
+# Platform and model specific eeprom subclass, inherits from the base class,
+# and provides the followings:
+# - the eeprom format definition
+# - specific encoder/decoder if there is special need
+#############################################################################
+
+try:
+ from sonic_eeprom import eeprom_tlvinfo
+except ImportError, e:
+ raise ImportError (str(e) + "- required module not found")
+
+
+class board(eeprom_tlvinfo.TlvInfoDecoder):
+
+ def __init__(self, name, path, cpld_root, ro):
+ self.eeprom_path = "/sys/class/i2c-adapter/i2c-0/0-0056/eeprom"
+ super(board, self).__init__(self.eeprom_path, 0, '', True)
+
diff --git a/device/celestica/x86_64-cel_silverstone-r0/plugins/psuutil.py b/device/celestica/x86_64-cel_silverstone-r0/plugins/psuutil.py
new file mode 100644
index 000000000000..d5e197e82d2b
--- /dev/null
+++ b/device/celestica/x86_64-cel_silverstone-r0/plugins/psuutil.py
@@ -0,0 +1,91 @@
+#!/usr/bin/env python
+
+import os.path
+import subprocess
+import sys
+import re
+
+try:
+ from sonic_psu.psu_base import PsuBase
+except ImportError as e:
+ raise ImportError (str(e) + "- required module not found")
+
+
+class PsuUtil(PsuBase):
+ """Platform-specific PSUutil class"""
+
+ def __init__(self):
+ self.ipmi_raw = "docker exec -ti pmon ipmitool raw 0x4 0x2d"
+ self.psu1_id = "0x2f"
+ self.psu2_id = "0x39"
+ PsuBase.__init__(self)
+
+ def run_command(self, command):
+ proc = subprocess.Popen(command, shell=True, stdout=subprocess.PIPE)
+ (out, err) = proc.communicate()
+
+ if proc.returncode != 0:
+ sys.exit(proc.returncode)
+
+ return out
+
+ def find_value(self, in_string):
+ result = re.search("^.+ ([0-9a-f]{2}) .+$", in_string)
+ if result:
+ return result.group(1)
+ else:
+ return result
+
+ def get_num_psus(self):
+ """
+ Retrieves the number of PSUs available on the device
+ :return: An integer, the number of PSUs available on the device
+ """
+ return 2
+
+ def get_psu_status(self, index):
+ """
+ Retrieves the oprational status of power supply unit (PSU) defined
+ by 1-based index
+ :param index: An integer, 1-based index of the PSU of which to query status
+ :return: Boolean, True if PSU is operating properly, False if PSU is faulty
+ """
+ if index is None:
+ return False
+
+ psu_id = self.psu1_id if index == 1 else self.psu2_id
+ res_string = self.run_command(self.ipmi_raw + ' ' + psu_id)
+ status_byte = self.find_value(res_string)
+
+ if status_byte is None:
+ return False
+
+ failure_detected = (int(status_byte, 16) >> 1) & 1
+ input_lost = (int(status_byte, 16) >> 3) & 1
+ if failure_detected or input_lost:
+ return False
+ else:
+ return True
+
+ def get_psu_presence(self, index):
+ """
+ Retrieves the presence status of power supply unit (PSU) defined
+ by 1-based index
+ :param index: An integer, 1-based index of the PSU of which to query status
+ :return: Boolean, True if PSU is plugged, False if not
+ """
+ if index is None:
+ return False
+
+ psu_id = self.psu1_id if index == 1 else self.psu2_id
+ res_string = self.run_command(self.ipmi_raw + ' ' + psu_id)
+ status_byte = self.find_value(res_string)
+
+ if status_byte is None:
+ return False
+
+ presence = ( int(status_byte, 16) >> 0 ) & 1
+ if presence:
+ return True
+ else:
+ return False
\ No newline at end of file
diff --git a/device/celestica/x86_64-cel_silverstone-r0/plugins/sfputil.py b/device/celestica/x86_64-cel_silverstone-r0/plugins/sfputil.py
new file mode 100755
index 000000000000..02e3b9db8f01
--- /dev/null
+++ b/device/celestica/x86_64-cel_silverstone-r0/plugins/sfputil.py
@@ -0,0 +1,184 @@
+#!/usr/bin/env python
+#
+# Platform-specific SFP transceiver interface for SONiC
+# This plugins only support QSFP and SFP.
+
+try:
+ import time
+ from sonic_sfp.sfputilbase import SfpUtilBase
+except ImportError as e:
+ raise ImportError("%s - required module not found" % str(e))
+
+
+class SfpUtil(SfpUtilBase):
+ """Platform-specific SfpUtil class"""
+
+ PORT_START = 1
+ PORT_END = 34
+ QSFP_PORT_START = 1
+ QSFP_PORT_END = 32
+ SFP_PORT_START = 33
+ SFP_PORT_END = 34
+
+ EEPROM_OFFSET = 9
+ PORT_INFO_PATH = '/sys/class/silverstone_fpga'
+
+ _port_name = ""
+ _port_to_eeprom_mapping = {}
+ _port_to_i2cbus_mapping = {}
+
+ @property
+ def port_start(self):
+ return self.PORT_START
+
+ @property
+ def port_end(self):
+ return self.PORT_END
+
+ @property
+ def qsfp_ports(self):
+ return range(self.QSFP_PORT_START, self.QSFP_PORT_END + 1)
+
+ @property
+ def port_to_eeprom_mapping(self):
+ return self._port_to_eeprom_mapping
+
+ @property
+ def port_to_i2cbus_mapping(self):
+ return self._port_to_i2cbus_mapping
+
+ def get_port_name(self, port_num):
+ if port_num in self.qsfp_ports:
+ self._port_name = "QSFP" + str(port_num - self.QSFP_PORT_START + 1)
+ else:
+ self._port_name = "SFP" + str(port_num - self.SFP_PORT_START + 1)
+ return self._port_name
+
+ def get_eeprom_dom_raw(self, port_num):
+ if port_num in self.qsfp_ports:
+ # QSFP DOM EEPROM is also at addr 0x50 and thus also stored in eeprom_ifraw
+ return None
+ else:
+ # Read dom eeprom at addr 0x51
+ return self._read_eeprom_devid(port_num, self.DOM_EEPROM_ADDR, 256)
+
+ def __init__(self):
+ # Override port_to_eeprom_mapping for class initialization
+ eeprom_path = '/sys/bus/i2c/devices/i2c-{0}/{0}-0050/eeprom'
+
+ for x in range(self.PORT_START, self.PORT_END+1):
+ self.port_to_i2cbus_mapping[x] = (x + self.EEPROM_OFFSET)
+ self.port_to_eeprom_mapping[x] = eeprom_path.format(
+ x + self.EEPROM_OFFSET)
+ SfpUtilBase.__init__(self)
+
+ def get_presence(self, port_num):
+
+ # Check for invalid port_num
+ if port_num not in range(self.port_start, self.port_end + 1):
+ return False
+
+ # Get path for access port presence status
+ port_name = self.get_port_name(port_num)
+ sysfs_filename = "qsfp_modprs" if port_num in self.qsfp_ports else "sfp_modabs"
+ reg_path = "/".join([self.PORT_INFO_PATH, port_name, sysfs_filename])
+
+ # Read status
+ try:
+ reg_file = open(reg_path)
+ content = reg_file.readline().rstrip()
+ reg_value = int(content)
+ except IOError as e:
+ print "Error: unable to open file: %s" % str(e)
+ return False
+
+ # Module present is active low
+ if reg_value == 0:
+ return True
+
+ return False
+
+ def get_low_power_mode(self, port_num):
+ # Check for invalid QSFP port_num
+ if port_num not in self.qsfp_ports:
+ return False
+
+ try:
+ port_name = self.get_port_name(port_num)
+ reg_file = open("/".join([self.PORT_INFO_PATH,
+ port_name, "qsfp_lpmode"]))
+ except IOError as e:
+ print "Error: unable to open file: %s" % str(e)
+ return False
+
+ # Read status
+ content = reg_file.readline().rstrip()
+ reg_value = int(content)
+ # low power mode is active high
+ if reg_value == 0:
+ return False
+
+ return True
+
+ def set_low_power_mode(self, port_num, lpmode):
+ # Check for invalid QSFP port_num
+ if port_num not in self.qsfp_ports:
+ return False
+
+ try:
+ port_name = self.get_port_name(port_num)
+ reg_file = open("/".join([self.PORT_INFO_PATH,
+ port_name, "qsfp_lpmode"]), "r+")
+ except IOError as e:
+ print "Error: unable to open file: %s" % str(e)
+ return False
+
+ content = hex(lpmode)
+
+ reg_file.seek(0)
+ reg_file.write(content)
+ reg_file.close()
+
+ return True
+
+ def reset(self, port_num):
+ # Check for invalid QSFP port_num
+ if port_num not in self.qsfp_ports:
+ return False
+
+ try:
+ port_name = self.get_port_name(port_num)
+ reg_file = open("/".join([self.PORT_INFO_PATH,
+ port_name, "qsfp_reset"]), "w")
+ except IOError as e:
+ print "Error: unable to open file: %s" % str(e)
+ return False
+
+ # Convert our register value back to a hex string and write back
+ reg_file.seek(0)
+ reg_file.write(hex(0))
+ reg_file.close()
+
+ # Sleep 1 second to allow it to settle
+ time.sleep(1)
+
+ # Flip the bit back high and write back to the register to take port out of reset
+ try:
+ reg_file = open(
+ "/".join([self.PORT_INFO_PATH, port_name, "qsfp_reset"]), "w")
+ except IOError as e:
+ print "Error: unable to open file: %s" % str(e)
+ return False
+
+ reg_file.seek(0)
+ reg_file.write(hex(1))
+ reg_file.close()
+
+ return True
+
+ def get_transceiver_change_event(self, timeout=0):
+ """
+ TBD
+ """
+ return NotImplementedError
+
diff --git a/device/celestica/x86_64-cel_silverstone-r0/th3-128x100G.config.bcm b/device/celestica/x86_64-cel_silverstone-r0/th3-128x100G.config.bcm
new file mode 100644
index 000000000000..0b66c8b53814
--- /dev/null
+++ b/device/celestica/x86_64-cel_silverstone-r0/th3-128x100G.config.bcm
@@ -0,0 +1,441 @@
+pbmp_xport_xe.0=0x8ffff8ffffcffff8ffff8ffff8ffffcffff9fffe
+ccm_dma_enable=0
+ccmdma_intr_enable=0
+ctr_evict_enable=0
+mem_cache_enable=0
+parity_correction=0
+parity_enable=0
+phy_enable=0
+phy_null=1
+pll_bypass=1
+
+init_all_modules=0
+
+portmap_20=33:100:2
+portmap_21=35:100:2
+portmap_22=37:100:2
+portmap_23=39:100:2
+
+portmap_24=41:100:2
+portmap_25=43:100:2
+portmap_26=45:100:2
+portmap_27=47:100:2
+
+portmap_28=49:100:2
+portmap_29=51:100:2
+portmap_30=53:100:2
+portmap_31=55:100:2
+
+portmap_32=57:100:2
+portmap_33=59:100:2
+portmap_34=61:100:2
+portmap_35=63:100:2
+
+portmap_40=65:100:2
+portmap_41=67:100:2
+portmap_42=69:100:2
+portmap_43=71:100:2
+
+portmap_44=73:100:2
+portmap_45=75:100:2
+portmap_46=77:100:2
+portmap_47=79:100:2
+
+portmap_48=81:100:2
+portmap_49=83:100:2
+portmap_50=85:100:2
+portmap_51=87:100:2
+
+portmap_52=89:100:2
+portmap_53=91:100:2
+portmap_54=93:100:2
+portmap_55=95:100:2
+
+portmap_1=1:100:2
+portmap_2=3:100:2
+portmap_3=5:100:2
+portmap_4=7:100:2
+
+portmap_5=9:100:2
+portmap_6=11:100:2
+portmap_7=13:100:2
+portmap_8=15:100:2
+
+portmap_9=17:100:2
+portmap_10=19:100:2
+portmap_11=21:100:2
+portmap_12=23:100:2
+
+portmap_13=25:100:2
+portmap_14=27:100:2
+portmap_15=29:100:2
+portmap_16=31:100:2
+
+portmap_60=97:100:2
+portmap_61=99:100:2
+portmap_62=101:100:2
+portmap_63=103:100:2
+
+portmap_64=105:100:2
+portmap_65=107:100:2
+portmap_66=109:100:2
+portmap_67=111:100:2
+
+portmap_68=113:100:2
+portmap_69=115:100:2
+portmap_70=117:100:2
+portmap_71=119:100:2
+
+portmap_72=121:100:2
+portmap_73=123:100:2
+portmap_74=125:100:2
+portmap_75=127:100:2
+
+portmap_80=129:100:2
+portmap_81=131:100:2
+portmap_82=133:100:2
+portmap_83=135:100:2
+
+portmap_84=137:100:2
+portmap_85=139:100:2
+portmap_86=141:100:2
+portmap_87=143:100:2
+
+portmap_88=145:100:2
+portmap_89=147:100:2
+portmap_90=149:100:2
+portmap_91=151:100:2
+
+portmap_92=153:100:2
+portmap_93=155:100:2
+portmap_94=157:100:2
+portmap_95=159:100:2
+
+portmap_140=225:100:2
+portmap_141=227:100:2
+portmap_142=229:100:2
+portmap_143=231:100:2
+
+portmap_144=233:100:2
+portmap_145=235:100:2
+portmap_146=237:100:2
+portmap_147=239:100:2
+
+portmap_148=241:100:2
+portmap_149=243:100:2
+portmap_150=245:100:2
+portmap_151=247:100:2
+
+portmap_152=249:100:2
+portmap_153=251:100:2
+portmap_154=253:100:2
+portmap_155=255:100:2
+
+portmap_100=161:100:2
+portmap_101=163:100:2
+portmap_102=165:100:2
+portmap_103=167:100:2
+
+portmap_104=169:100:2
+portmap_105=171:100:2
+portmap_106=173:100:2
+portmap_107=175:100:2
+
+portmap_108=177:100:2
+portmap_109=179:100:2
+portmap_110=181:100:2
+portmap_111=183:100:2
+
+portmap_112=185:100:2
+portmap_113=187:100:2
+portmap_114=189:100:2
+portmap_115=191:100:2
+
+portmap_120=193:100:2
+portmap_121=195:100:2
+portmap_122=197:100:2
+portmap_123=199:100:2
+
+portmap_124=201:100:2
+portmap_125=203:100:2
+portmap_126=205:100:2
+portmap_127=207:100:2
+
+portmap_128=209:100:2
+portmap_129=211:100:2
+portmap_130=213:100:2
+portmap_131=215:100:2
+
+portmap_132=217:100:2
+portmap_133=219:100:2
+portmap_134=221:100:2
+portmap_135=223:100:2
+
+phy_chain_rx_lane_map_physical{33.0}=0x65732041
+phy_chain_tx_lane_map_physical{33.0}=0x47206531
+phy_chain_rx_lane_map_physical{41.0}=0x07561243
+phy_chain_tx_lane_map_physical{41.0}=0x36207514
+phy_chain_rx_lane_map_physical{49.0}=0x54632071
+phy_chain_tx_lane_map_physical{49.0}=0x06241735
+phy_chain_rx_lane_map_physical{57.0}=0x07561243
+phy_chain_tx_lane_map_physical{57.0}=0x35207614
+phy_chain_rx_lane_map_physical{65.0}=0x45623170
+phy_chain_tx_lane_map_physical{65.0}=0x51260734
+phy_chain_rx_lane_map_physical{73.0}=0x07561243
+phy_chain_tx_lane_map_physical{73.0}=0x37245610
+phy_chain_rx_lane_map_physical{81.0}=0x45632071
+phy_chain_tx_lane_map_physical{81.0}=0x51260734
+phy_chain_rx_lane_map_physical{89.0}=0x07561243
+phy_chain_tx_lane_map_physical{89.0}=0x26437510
+phy_chain_rx_lane_map_physical{1.0}=0x30176524
+phy_chain_tx_lane_map_physical{1.0}=0x20615374
+phy_chain_rx_lane_map_physical{9.0}=0x37562041
+phy_chain_tx_lane_map_physical{9.0}=0x05176432
+phy_chain_rx_lane_map_physical{17.0}=0x43607251
+phy_chain_tx_lane_map_physical{17.0}=0x70261435
+phy_chain_rx_lane_map_physical{25.0}=0x60347125
+phy_chain_tx_lane_map_physical{25.0}=0x46357120
+phy_chain_rx_lane_map_physical{97.0}=0x47601352
+phy_chain_tx_lane_map_physical{97.0}=0x04265137
+phy_chain_rx_lane_map_physical{105.0}=0x73206415
+phy_chain_tx_lane_map_physical{105.0}=0x26374150
+phy_chain_rx_lane_map_physical{113.0}=0x47632051
+phy_chain_tx_lane_map_physical{113.0}=0x03254617
+phy_chain_rx_lane_map_physical{121.0}=0x63027415
+phy_chain_tx_lane_map_physical{121.0}=0x63721045
+phy_chain_rx_lane_map_physical{129.0}=0x30154627
+phy_chain_tx_lane_map_physical{129.0}=0x04735261
+phy_chain_rx_lane_map_physical{137.0}=0x24753061
+phy_chain_tx_lane_map_physical{137.0}=0x37614520
+phy_chain_rx_lane_map_physical{145.0}=0x47601352
+phy_chain_tx_lane_map_physical{145.0}=0x63274510
+phy_chain_rx_lane_map_physical{153.0}=0x07361524
+phy_chain_tx_lane_map_physical{153.0}=0x36527104
+phy_chain_rx_lane_map_physical{225.0}=0x56410273
+phy_chain_tx_lane_map_physical{225.0}=0x10274635
+phy_chain_rx_lane_map_physical{233.0}=0x15740263
+phy_chain_tx_lane_map_physical{233.0}=0x24351607
+phy_chain_rx_lane_map_physical{241.0}=0x74015263
+phy_chain_tx_lane_map_physical{241.0}=0x04152637
+phy_chain_rx_lane_map_physical{249.0}=0x62037514
+phy_chain_tx_lane_map_physical{249.0}=0x72453160
+phy_chain_rx_lane_map_physical{161.0}=0x46510273
+phy_chain_tx_lane_map_physical{161.0}=0x01653724
+phy_chain_rx_lane_map_physical{169.0}=0x25743160
+phy_chain_tx_lane_map_physical{169.0}=0x07216435
+phy_chain_rx_lane_map_physical{177.0}=0x46510273
+phy_chain_tx_lane_map_physical{177.0}=0x01652734
+phy_chain_rx_lane_map_physical{185.0}=0x25743160
+phy_chain_tx_lane_map_physical{185.0}=0x37016425
+phy_chain_rx_lane_map_physical{193.0}=0x46510372
+phy_chain_tx_lane_map_physical{193.0}=0x06153724
+phy_chain_rx_lane_map_physical{201.0}=0x25743160
+phy_chain_tx_lane_map_physical{201.0}=0x36017524
+phy_chain_rx_lane_map_physical{209.0}=0x47601352
+phy_chain_tx_lane_map_physical{209.0}=0x04152736
+phy_chain_rx_lane_map_physical{217.0}=0x26453170
+phy_chain_tx_lane_map_physical{217.0}=0x36027415
+
+serdes_core_rx_polarity_flip_physical{33}=0x29
+serdes_core_tx_polarity_flip_physical{33}=0xfe
+serdes_core_rx_polarity_flip_physical{41}=0xb1
+serdes_core_tx_polarity_flip_physical{41}=0xe8
+serdes_core_rx_polarity_flip_physical{49}=0xca
+serdes_core_tx_polarity_flip_physical{49}=0xb6
+serdes_core_rx_polarity_flip_physical{57}=0x9b
+serdes_core_tx_polarity_flip_physical{57}=0xdc
+serdes_core_rx_polarity_flip_physical{65}=0x17
+serdes_core_tx_polarity_flip_physical{65}=0x86
+serdes_core_rx_polarity_flip_physical{73}=0x9b
+serdes_core_tx_polarity_flip_physical{73}=0x55
+serdes_core_rx_polarity_flip_physical{81}=0xa
+serdes_core_tx_polarity_flip_physical{81}=0x6
+serdes_core_rx_polarity_flip_physical{89}=0x9b
+serdes_core_tx_polarity_flip_physical{89}=0x48
+serdes_core_rx_polarity_flip_physical{1}=0xec
+serdes_core_tx_polarity_flip_physical{1}=0x56
+serdes_core_rx_polarity_flip_physical{9}=0x13
+serdes_core_tx_polarity_flip_physical{9}=0xa6
+serdes_core_rx_polarity_flip_physical{17}=0x5a
+serdes_core_tx_polarity_flip_physical{17}=0xc6
+serdes_core_rx_polarity_flip_physical{25}=0xf
+serdes_core_tx_polarity_flip_physical{25}=0x4e
+serdes_core_rx_polarity_flip_physical{97}=0x17
+serdes_core_tx_polarity_flip_physical{97}=0x2e
+serdes_core_rx_polarity_flip_physical{105}=0xce
+serdes_core_tx_polarity_flip_physical{105}=0x7c
+serdes_core_rx_polarity_flip_physical{113}=0xa
+serdes_core_tx_polarity_flip_physical{113}=0x35
+
+serdes_core_rx_polarity_flip_physical{121}=0xb9
+serdes_core_tx_polarity_flip_physical{121}=0xef
+serdes_core_rx_polarity_flip_physical{129}=0xe8
+serdes_core_tx_polarity_flip_physical{129}=0xac
+serdes_core_rx_polarity_flip_physical{137}=0xcb
+serdes_core_tx_polarity_flip_physical{137}=0x9c
+serdes_core_rx_polarity_flip_physical{145}=0x17
+serdes_core_tx_polarity_flip_physical{145}=0x32
+serdes_core_rx_polarity_flip_physical{153}=0xb9
+serdes_core_tx_polarity_flip_physical{153}=0xaf
+serdes_core_rx_polarity_flip_physical{225}=0xaa
+serdes_core_tx_polarity_flip_physical{225}=0x7
+serdes_core_rx_polarity_flip_physical{233}=0x31
+serdes_core_tx_polarity_flip_physical{233}=0x47
+serdes_core_rx_polarity_flip_physical{241}=0xe8
+serdes_core_tx_polarity_flip_physical{241}=0x9e
+serdes_core_rx_polarity_flip_physical{249}=0xec
+serdes_core_tx_polarity_flip_physical{249}=0x1f
+serdes_core_rx_polarity_flip_physical{161}=0x6a
+serdes_core_tx_polarity_flip_physical{161}=0xd4
+serdes_core_rx_polarity_flip_physical{169}=0x9e
+serdes_core_tx_polarity_flip_physical{169}=0x7b
+serdes_core_rx_polarity_flip_physical{177}=0x6a
+serdes_core_tx_polarity_flip_physical{177}=0xcc
+serdes_core_rx_polarity_flip_physical{185}=0x9e
+serdes_core_tx_polarity_flip_physical{185}=0x58
+serdes_core_rx_polarity_flip_physical{193}=0x6f
+serdes_core_tx_polarity_flip_physical{193}=0x24
+serdes_core_rx_polarity_flip_physical{201}=0x9e
+serdes_core_tx_polarity_flip_physical{201}=0xdf
+serdes_core_rx_polarity_flip_physical{209}=0x17
+serdes_core_tx_polarity_flip_physical{209}=0xe9
+serdes_core_rx_polarity_flip_physical{217}=0xec
+serdes_core_tx_polarity_flip_physical{217}=0x68
+
+
+dport_map_port_20=1
+dport_map_port_21=2
+dport_map_port_22=3
+dport_map_port_23=4
+dport_map_port_24=5
+dport_map_port_25=6
+dport_map_port_26=7
+dport_map_port_27=8
+dport_map_port_28=9
+dport_map_port_29=10
+dport_map_port_30=11
+dport_map_port_31=12
+dport_map_port_32=13
+dport_map_port_33=14
+dport_map_port_34=15
+dport_map_port_35=16
+dport_map_port_40=17
+dport_map_port_41=18
+dport_map_port_42=19
+dport_map_port_43=20
+dport_map_port_44=21
+dport_map_port_45=22
+dport_map_port_46=23
+dport_map_port_47=24
+dport_map_port_48=25
+dport_map_port_49=26
+dport_map_port_50=27
+dport_map_port_51=28
+dport_map_port_52=29
+dport_map_port_53=30
+dport_map_port_54=31
+dport_map_port_55=32
+dport_map_port_1=33
+dport_map_port_2=34
+dport_map_port_3=35
+dport_map_port_4=36
+dport_map_port_5=37
+dport_map_port_6=38
+dport_map_port_7=39
+dport_map_port_8=40
+dport_map_port_9=41
+dport_map_port_10=42
+dport_map_port_11=43
+dport_map_port_12=44
+dport_map_port_13=45
+dport_map_port_14=46
+dport_map_port_15=47
+dport_map_port_16=48
+dport_map_port_60=49
+dport_map_port_61=50
+dport_map_port_62=51
+dport_map_port_63=52
+dport_map_port_64=53
+dport_map_port_65=54
+dport_map_port_66=55
+dport_map_port_67=56
+dport_map_port_68=57
+dport_map_port_69=58
+dport_map_port_70=59
+dport_map_port_71=60
+dport_map_port_72=61
+dport_map_port_73=62
+dport_map_port_74=63
+dport_map_port_75=64
+dport_map_port_80=65
+dport_map_port_81=66
+dport_map_port_82=67
+dport_map_port_83=68
+dport_map_port_84=69
+dport_map_port_85=70
+dport_map_port_86=71
+dport_map_port_87=72
+dport_map_port_88=73
+dport_map_port_89=74
+dport_map_port_90=75
+dport_map_port_91=76
+dport_map_port_92=77
+dport_map_port_93=78
+dport_map_port_94=79
+dport_map_port_95=80
+dport_map_port_140=81
+dport_map_port_141=82
+dport_map_port_142=83
+dport_map_port_143=84
+dport_map_port_144=85
+dport_map_port_145=86
+dport_map_port_146=87
+dport_map_port_147=88
+dport_map_port_148=89
+dport_map_port_149=90
+dport_map_port_150=91
+dport_map_port_151=92
+dport_map_port_152=93
+dport_map_port_153=94
+dport_map_port_154=95
+dport_map_port_155=96
+dport_map_port_100=97
+dport_map_port_101=98
+dport_map_port_102=99
+dport_map_port_103=100
+dport_map_port_104=101
+dport_map_port_105=102
+dport_map_port_106=103
+dport_map_port_107=104
+dport_map_port_108=105
+dport_map_port_109=106
+dport_map_port_110=107
+dport_map_port_111=108
+dport_map_port_112=109
+dport_map_port_113=110
+dport_map_port_114=111
+dport_map_port_115=112
+dport_map_port_120=113
+dport_map_port_121=114
+dport_map_port_122=115
+dport_map_port_123=116
+dport_map_port_124=117
+dport_map_port_125=118
+dport_map_port_126=119
+dport_map_port_127=120
+dport_map_port_128=121
+dport_map_port_129=122
+dport_map_port_130=123
+dport_map_port_131=124
+dport_map_port_132=125
+dport_map_port_133=126
+dport_map_port_134=127
+dport_map_port_135=128
+
+core_clock_frequency=1325
+dpr_clock_frequency=1000
+device_clock_frequency=1325
+port_flex_enable=1
+
+#firmware load method, use fast load
+load_firmware=0x2
diff --git a/platform/broadcom/one-image.mk b/platform/broadcom/one-image.mk
index 451e22ba3722..68db9eeb22c3 100644
--- a/platform/broadcom/one-image.mk
+++ b/platform/broadcom/one-image.mk
@@ -52,7 +52,9 @@ $(SONIC_ONE_IMAGE)_LAZY_INSTALLS += $(DELL_S6000_PLATFORM_MODULE) \
$(ALPHANETWORKS_SNH60B0_640F_PLATFORM_MODULE) \
$(BRCM_XLR_GTS_PLATFORM_MODULE) \
$(DELTA_AG9032V2A_PLATFORM_MODULE) \
- $(JUNIPER_QFX5210_PLATFORM_MODULE)
+ $(JUNIPER_QFX5210_PLATFORM_MODULE) \
+ $(DELTA_AG9032V2A_PLATFORM_MODULE) \
+ $(CEL_SILVERSTONE_PLATFORM_MODULE)
ifeq ($(INSTALL_DEBUG_TOOLS),y)
$(SONIC_ONE_IMAGE)_DOCKERS += $(SONIC_INSTALL_DOCKER_DBG_IMAGES)
$(SONIC_ONE_IMAGE)_DOCKERS += $(filter-out $(patsubst %-$(DBG_IMAGE_MARK).gz,%.gz, $(SONIC_INSTALL_DOCKER_DBG_IMAGES)), $(SONIC_INSTALL_DOCKER_IMAGES))
diff --git a/platform/broadcom/platform-modules-cel.mk b/platform/broadcom/platform-modules-cel.mk
index 1224faaa6750..b7371e3282de 100644
--- a/platform/broadcom/platform-modules-cel.mk
+++ b/platform/broadcom/platform-modules-cel.mk
@@ -2,9 +2,11 @@
CEL_DX010_PLATFORM_MODULE_VERSION = 0.9
CEL_HALIBURTON_PLATFORM_MODULE_VERSION = 0.9
+CEL_SILVERSTONE_PLATFORM_MODULE_VERSION = 0.9
export CEL_DX010_PLATFORM_MODULE_VERSION
export CEL_HALIBURTON_PLATFORM_MODULE_VERSION
+export CEL_SILVERSTONE_PLATFORM_MODULE_VERSION
CEL_DX010_PLATFORM_MODULE = platform-modules-dx010_$(CEL_DX010_PLATFORM_MODULE_VERSION)_amd64.deb
$(CEL_DX010_PLATFORM_MODULE)_SRC_PATH = $(PLATFORM_PATH)/sonic-platform-modules-cel
@@ -16,4 +18,8 @@ CEL_HALIBURTON_PLATFORM_MODULE = platform-modules-haliburton_$(CEL_HALIBURTON_PL
$(CEL_HALIBURTON_PLATFORM_MODULE)_PLATFORM = x86_64-cel_e1031-r0
$(eval $(call add_extra_package,$(CEL_DX010_PLATFORM_MODULE),$(CEL_HALIBURTON_PLATFORM_MODULE)))
+CEL_SILVERSTONE_PLATFORM_MODULE = platform-modules-silverstone_$(CEL_SILVERSTONE_PLATFORM_MODULE_VERSION)_amd64.deb
+$(CEL_SILVERSTONE_PLATFORM_MODULE)_PLATFORM = x86_64-cel_silverstone-r0
+$(eval $(call add_extra_package,$(CEL_DX010_PLATFORM_MODULE),$(CEL_SILVERSTONE_PLATFORM_MODULE)))
+
SONIC_STRETCH_DEBS += $(CEL_DX010_PLATFORM_MODULE)
diff --git a/platform/broadcom/sonic-platform-modules-cel/debian/control b/platform/broadcom/sonic-platform-modules-cel/debian/control
index 445189822039..2e9b578872fa 100644
--- a/platform/broadcom/sonic-platform-modules-cel/debian/control
+++ b/platform/broadcom/sonic-platform-modules-cel/debian/control
@@ -15,3 +15,8 @@ Package: platform-modules-haliburton
Architecture: amd64
Depends: linux-image-4.9.0-9-2-amd64
Description: kernel modules for platform devices such as fan, led, sfp
+
+Package: platform-modules-silverstone
+Architecture: amd64
+Depends: linux-image-4.9.0-9-2-amd64
+Description: kernel modules for platform devices such as led, sfp.
diff --git a/platform/broadcom/sonic-platform-modules-cel/debian/platform-modules-silverstone.init b/platform/broadcom/sonic-platform-modules-cel/debian/platform-modules-silverstone.init
new file mode 100644
index 000000000000..c1d4c10b48fc
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-cel/debian/platform-modules-silverstone.init
@@ -0,0 +1,49 @@
+#!/bin/bash
+
+### BEGIN INIT INFO
+# Provides: setup-board
+# Required-Start: $portmap
+# Required-Stop:
+# Should-Start:
+# Should-Stop:
+# Default-Start: S
+# Default-Stop: 0 6
+# Short-Description: Setup SilverStone board.
+### END INIT INFO
+
+
+case "$1" in
+start)
+ echo -n "Setting up board... "
+
+ modprobe i2c-dev
+ modprobe baseboard-lpc
+ modprobe switchboard
+ modprobe mc24lc64t
+ modprobe ipmi_devintf
+
+ # Instantiate TLV EEPROM device on I801 bus
+ devname=`cat /sys/bus/i2c/devices/i2c-0/name`
+ if [[ $devname == 'SMBus I801 adapter at '* ]]; then
+ echo 24lc64t 0x56 > /sys/bus/i2c/devices/i2c-0/new_device
+ fi
+ decode-syseeprom --init 2> /dev/null &
+
+ echo "done."
+ ;;
+
+stop)
+ echo "done."
+ ;;
+
+force-reload|restart)
+ echo "Not supported"
+ ;;
+
+*)
+ echo "Usage: /etc/init.d/platform-modules-silverstone.init {start|stop}"
+ exit 1
+ ;;
+esac
+
+exit 0
\ No newline at end of file
diff --git a/platform/broadcom/sonic-platform-modules-cel/debian/platform-modules-silverstone.install b/platform/broadcom/sonic-platform-modules-cel/debian/platform-modules-silverstone.install
new file mode 100644
index 000000000000..a3a8b3d424a1
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-cel/debian/platform-modules-silverstone.install
@@ -0,0 +1,2 @@
+silverstone/cfg/silverstone-modules.conf etc/modules-load.d
+silverstone/systemd/platform-modules-silverstone.service lib/systemd/system
\ No newline at end of file
diff --git a/platform/broadcom/sonic-platform-modules-cel/debian/platform-modules-silverstone.postinst b/platform/broadcom/sonic-platform-modules-cel/debian/platform-modules-silverstone.postinst
new file mode 100644
index 000000000000..771057bed0dc
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-cel/debian/platform-modules-silverstone.postinst
@@ -0,0 +1,3 @@
+depmod -a
+systemctl enable platform-modules-silverstone.service
+systemctl start platform-modules-silverstone.service
\ No newline at end of file
diff --git a/platform/broadcom/sonic-platform-modules-cel/debian/rules b/platform/broadcom/sonic-platform-modules-cel/debian/rules
index 6f35290bce26..dd5452ccaa11 100755
--- a/platform/broadcom/sonic-platform-modules-cel/debian/rules
+++ b/platform/broadcom/sonic-platform-modules-cel/debian/rules
@@ -5,7 +5,7 @@ export INSTALL_MOD_DIR:=extra
KVERSION ?= $(shell uname -r)
KERNEL_SRC := /lib/modules/$(KVERSION)
MOD_SRC_DIR:= $(shell pwd)
-MODULE_DIRS:= dx010 haliburton
+MODULE_DIRS:= dx010 haliburton silverstone
%:
dh $@
diff --git a/platform/broadcom/sonic-platform-modules-cel/silverstone/cfg/silverstone-modules.conf b/platform/broadcom/sonic-platform-modules-cel/silverstone/cfg/silverstone-modules.conf
new file mode 100644
index 000000000000..cb8dcf640ba3
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-cel/silverstone/cfg/silverstone-modules.conf
@@ -0,0 +1,15 @@
+# /etc/modules: kernel modules to load at boot time.
+#
+# This file contains the names of kernel modules that should be loaded
+# at boot time, one per line. Lines beginning with "#" are ignored.
+
+i2c-i801
+i2c-isch
+i2c-ismt
+i2c-dev
+i2c-mux
+i2c-smbus
+
+i2c-mux-pca954x
+ipmi_devintf
+ipmi_si
\ No newline at end of file
diff --git a/platform/broadcom/sonic-platform-modules-cel/silverstone/modules/Makefile b/platform/broadcom/sonic-platform-modules-cel/silverstone/modules/Makefile
new file mode 100644
index 000000000000..f6ad4d9ba4d1
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-cel/silverstone/modules/Makefile
@@ -0,0 +1 @@
+obj-m := baseboard-lpc.o mc24lc64t.o switchboard.o
\ No newline at end of file
diff --git a/platform/broadcom/sonic-platform-modules-cel/silverstone/modules/baseboard-lpc.c b/platform/broadcom/sonic-platform-modules-cel/silverstone/modules/baseboard-lpc.c
new file mode 100644
index 000000000000..b6291f7d3ce4
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-cel/silverstone/modules/baseboard-lpc.c
@@ -0,0 +1,433 @@
+/*
+ * baseboard-lpc.c - The CPLD driver for the Base Board of Silverstone
+ * The driver implement sysfs to access CPLD register on the baseboard of Silverstone via LPC bus.
+ * Copyright (C) 2018 Celestica Corp.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#define DRIVER_NAME "baseboard-lpc"
+/**
+ * CPLD register address for read and write.
+ */
+#define VERSION_ADDR 0xA100
+#define SCRATCH_ADDR 0xA101
+#define BLT_MONTH_ADDR 0xA102
+#define BLT_DATE_ADDR 0xA103
+#define REBOOT_CAUSE 0xA106
+#define SYS_LED_ADDR 0xA162
+#define CPLD_REGISTER_SIZE 0x93
+
+/* System reboot cause recorded in CPLD */
+static const struct {
+ const char *reason;
+ u8 reset_code;
+} reboot_causes[] = {
+ {"POR", 0x11},
+ {"soft-warm-rst", 0x22},
+ {"soft-cold-rst", 0x33},
+ {"warm-rst", 0x44},
+ {"cold-rst", 0x55},
+ {"wdt-rst", 0x66},
+ {"power-cycle", 0x77}
+};
+
+struct cpld_b_data {
+ struct mutex cpld_lock;
+ uint16_t read_addr;
+};
+
+struct cpld_b_data *cpld_data;
+
+static ssize_t scratch_show(struct device *dev, struct device_attribute *devattr,
+ char *buf)
+{
+ unsigned char data = 0;
+ mutex_lock(&cpld_data->cpld_lock);
+ data = inb(SCRATCH_ADDR);
+ mutex_unlock(&cpld_data->cpld_lock);
+ return sprintf(buf,"0x%2.2x\n", data);
+}
+
+static ssize_t scratch_store(struct device *dev, struct device_attribute *devattr,
+ const char *buf, size_t count)
+{
+ unsigned long data;
+ char *last;
+
+ mutex_lock(&cpld_data->cpld_lock);
+ data = (uint16_t)strtoul(buf,&last,16);
+ if(data == 0 && buf == last){
+ mutex_unlock(&cpld_data->cpld_lock);
+ return -EINVAL;
+ }
+ outb(data, SCRATCH_ADDR);
+ mutex_unlock(&cpld_data->cpld_lock);
+ return count;
+}
+static DEVICE_ATTR_RW(scratch);
+
+
+/* CPLD version attributes */
+static ssize_t version_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ u8 version;
+ mutex_lock(&cpld_data->cpld_lock);
+ version = inb(VERSION_ADDR);
+ mutex_unlock(&cpld_data->cpld_lock);
+ return sprintf(buf, "%d.%d\n", version >> 4, version & 0x0F);
+}
+static DEVICE_ATTR_RO(version);
+
+/* CPLD version attributes */
+static ssize_t build_date_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ u8 month, day_of_month;
+ mutex_lock(&cpld_data->cpld_lock);
+ day_of_month = inb(BLT_DATE_ADDR);
+ month = inb(BLT_MONTH_ADDR);
+ mutex_unlock(&cpld_data->cpld_lock);
+ return sprintf(buf, "%x/%x\n", day_of_month, month);
+}
+static DEVICE_ATTR_RO(build_date);
+
+
+static ssize_t getreg_store(struct device *dev, struct device_attribute *devattr,
+ const char *buf, size_t count)
+{
+ uint16_t addr;
+ char *last;
+
+ addr = (uint16_t)strtoul(buf,&last,16);
+ if(addr == 0 && buf == last){
+ return -EINVAL;
+ }
+ cpld_data->read_addr = addr;
+ return count;
+}
+
+static ssize_t getreg_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ int len = 0;
+
+ mutex_lock(&cpld_data->cpld_lock);
+ len = sprintf(buf, "0x%2.2x\n",inb(cpld_data->read_addr));
+ mutex_unlock(&cpld_data->cpld_lock);
+ return len;
+}
+static DEVICE_ATTR_RW(getreg);
+
+static ssize_t setreg_store(struct device *dev, struct device_attribute *devattr,
+ const char *buf, size_t count)
+{
+ uint16_t addr;
+ uint8_t value;
+ char *tok;
+ char clone[count];
+ char *pclone = clone;
+ char *last;
+
+ strcpy(clone, buf);
+
+ mutex_lock(&cpld_data->cpld_lock);
+ tok = strsep((char**)&pclone, " ");
+ if(tok == NULL){
+ mutex_unlock(&cpld_data->cpld_lock);
+ return -EINVAL;
+ }
+ addr = (uint16_t)strtoul(tok,&last,16);
+ if(addr == 0 && tok == last){
+ mutex_unlock(&cpld_data->cpld_lock);
+ return -EINVAL;
+ }
+
+ tok = strsep((char**)&pclone, " ");
+ if(tok == NULL){
+ mutex_unlock(&cpld_data->cpld_lock);
+ return -EINVAL;
+ }
+ value = (uint8_t)strtoul(tok,&last,16);
+ if(value == 0 && tok == last){
+ mutex_unlock(&cpld_data->cpld_lock);
+ return -EINVAL;
+ }
+
+ outb(value,addr);
+ mutex_unlock(&cpld_data->cpld_lock);
+ return count;
+}
+static DEVICE_ATTR_WO(setreg);
+
+/**
+ * Read all CPLD register in binary mode.
+ */
+static ssize_t dump_read(struct file *filp, struct kobject *kobj,
+ struct bin_attribute *attr, char *buf,
+ loff_t off, size_t count)
+{
+ unsigned long i=0;
+ ssize_t status;
+
+ mutex_lock(&cpld_data->cpld_lock);
+begin:
+ if(i < count){
+ buf[i++] = inb(VERSION_ADDR + off);
+ off++;
+ msleep(1);
+ goto begin;
+ }
+ status = count;
+
+ mutex_unlock(&cpld_data->cpld_lock);
+ return status;
+}
+static BIN_ATTR_RO(dump, CPLD_REGISTER_SIZE);
+
+/**
+ * Show system led status - on/off/1hz/4hz
+ * @return Hex string read from scratch register.
+ */
+static ssize_t sys_led_show(struct device *dev, struct device_attribute *devattr,
+ char *buf)
+{
+ unsigned char data = 0;
+ mutex_lock(&cpld_data->cpld_lock);
+ data = inb(SYS_LED_ADDR);
+ mutex_unlock(&cpld_data->cpld_lock);
+ data = data & 0x3;
+ return sprintf(buf, "%s\n",
+ data == 0x03 ? "off" : data == 0x02 ? "4hz" : data ==0x01 ? "1hz": "on");
+}
+
+/**
+ * Set the status of system led - on/off/1hz/4hz
+ */
+static ssize_t sys_led_store(struct device *dev, struct device_attribute *devattr,
+ const char *buf, size_t count)
+{
+ unsigned char led_status,data;
+ if(sysfs_streq(buf, "off")){
+ led_status = 0x03;
+ }else if(sysfs_streq(buf, "4hz")){
+ led_status = 0x02;
+ }else if(sysfs_streq(buf, "1hz")){
+ led_status = 0x01;
+ }else if(sysfs_streq(buf, "on")){
+ led_status = 0x00;
+ }else{
+ count = -EINVAL;
+ return count;
+ }
+ mutex_lock(&cpld_data->cpld_lock);
+ data = inb(SYS_LED_ADDR);
+ data = data & ~(0x3);
+ data = data | led_status;
+ outb(data, SYS_LED_ADDR);
+ mutex_unlock(&cpld_data->cpld_lock);
+ return count;
+}
+static DEVICE_ATTR_RW(sys_led);
+
+/**
+ * Show system led color - both/green/yellow/none
+ * @return Current led color.
+ */
+static ssize_t sys_led_color_show(struct device *dev, struct device_attribute *devattr,
+ char *buf)
+{
+ unsigned char data = 0;
+ mutex_lock(&cpld_data->cpld_lock);
+ data = inb(SYS_LED_ADDR);
+ mutex_unlock(&cpld_data->cpld_lock);
+ data = (data >> 4) & 0x3;
+ return sprintf(buf, "%s\n",
+ data == 0x03 ? "off" : data == 0x02 ? "yellow" : data ==0x01 ? "green": "both");
+}
+
+/**
+ * Set the color of system led - both/green/yellow/none
+ */
+static ssize_t sys_led_color_store(struct device *dev, struct device_attribute *devattr,
+ const char *buf, size_t count)
+{
+ unsigned char led_status,data;
+ if(sysfs_streq(buf, "off")){
+ led_status = 0x03;
+ }else if(sysfs_streq(buf, "yellow")){
+ led_status = 0x02;
+ }else if(sysfs_streq(buf, "green")){
+ led_status = 0x01;
+ }else if(sysfs_streq(buf, "both")){
+ led_status = 0x00;
+ }else{
+ count = -EINVAL;
+ return count;
+ }
+ mutex_lock(&cpld_data->cpld_lock);
+ data = inb(SYS_LED_ADDR);
+ data = data & ~( 0x3 << 4);
+ data = data | (led_status << 4);
+ outb(data, SYS_LED_ADDR);
+ mutex_unlock(&cpld_data->cpld_lock);
+ return count;
+}
+static DEVICE_ATTR_RW(sys_led_color);
+
+static ssize_t reboot_cause_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ ssize_t status;
+ u8 reg;
+ int i;
+
+ mutex_lock(&cpld_data->cpld_lock);
+ reg = inb(REBOOT_CAUSE);
+ mutex_unlock(&cpld_data->cpld_lock);
+
+ status = 0;
+ dev_dbg(dev,"reboot: 0x%x\n", (u8)reg);
+ for(i = 0; i < ARRAY_SIZE(reboot_causes); i++){
+ if((u8)reg == reboot_causes[i].reset_code){
+ status = sprintf(buf, "%s\n",
+ reboot_causes[i].reason);
+ break;
+ }
+ }
+ return status;
+}
+DEVICE_ATTR_RO(reboot_cause);
+
+static struct attribute *cpld_b_attrs[] = {
+ &dev_attr_version.attr,
+ &dev_attr_build_date.attr,
+ &dev_attr_scratch.attr,
+ &dev_attr_getreg.attr,
+ &dev_attr_setreg.attr,
+ &dev_attr_sys_led.attr,
+ &dev_attr_sys_led_color.attr,
+ &dev_attr_reboot_cause.attr,
+ NULL,
+};
+
+static struct bin_attribute *cpld_b_bin_attrs[] = {
+ &bin_attr_dump,
+ NULL,
+};
+
+static struct attribute_group cpld_b_attrs_grp = {
+ .attrs = cpld_b_attrs,
+ .bin_attrs = cpld_b_bin_attrs,
+};
+
+static struct resource cpld_b_resources[] = {
+ {
+ .start = 0xA100,
+ .end = 0xA192,
+ .flags = IORESOURCE_IO,
+ },
+};
+
+static void cpld_b_dev_release( struct device * dev)
+{
+ return;
+}
+
+static struct platform_device cpld_b_dev = {
+ .name = DRIVER_NAME,
+ .id = -1,
+ .num_resources = ARRAY_SIZE(cpld_b_resources),
+ .resource = cpld_b_resources,
+ .dev = {
+ .release = cpld_b_dev_release,
+ }
+};
+
+static int cpld_b_drv_probe(struct platform_device *pdev)
+{
+ struct resource *res;
+ int err = 0;
+
+ cpld_data = devm_kzalloc(&pdev->dev, sizeof(struct cpld_b_data),
+ GFP_KERNEL);
+ if (!cpld_data)
+ return -ENOMEM;
+
+ mutex_init(&cpld_data->cpld_lock);
+
+ cpld_data->read_addr = VERSION_ADDR;
+
+ res = platform_get_resource(pdev, IORESOURCE_IO, 0);
+ if (unlikely(!res)) {
+ printk(KERN_ERR "Specified Resource Not Available...\n");
+ return -ENODEV;
+ }
+
+ err = sysfs_create_group(&pdev->dev.kobj, &cpld_b_attrs_grp);
+ if (err) {
+ printk(KERN_ERR "Cannot create sysfs for baseboard CPLD\n");
+ return err;
+ }
+ return 0;
+}
+
+static int cpld_b_drv_remove(struct platform_device *pdev)
+{
+ sysfs_remove_group(&pdev->dev.kobj, &cpld_b_attrs_grp);
+ return 0;
+}
+
+static struct platform_driver cpld_b_drv = {
+ .probe = cpld_b_drv_probe,
+ .remove = __exit_p(cpld_b_drv_remove),
+ .driver = {
+ .name = DRIVER_NAME,
+ },
+};
+
+int cpld_b_init(void)
+{
+ // Register platform device and platform driver
+ platform_device_register(&cpld_b_dev);
+ platform_driver_register(&cpld_b_drv);
+ return 0;
+}
+
+void cpld_b_exit(void)
+{
+ // Unregister platform device and platform driver
+ platform_driver_unregister(&cpld_b_drv);
+ platform_device_unregister(&cpld_b_dev);
+}
+
+module_init(cpld_b_init);
+module_exit(cpld_b_exit);
+
+
+MODULE_AUTHOR("Celestica Inc.");
+MODULE_DESCRIPTION("Celestica Silverstone CPLD baseboard driver");
+MODULE_VERSION("0.2.0");
+MODULE_LICENSE("GPL");
\ No newline at end of file
diff --git a/platform/broadcom/sonic-platform-modules-cel/silverstone/modules/mc24lc64t.c b/platform/broadcom/sonic-platform-modules-cel/silverstone/modules/mc24lc64t.c
new file mode 100644
index 000000000000..fc15bb74b68d
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-cel/silverstone/modules/mc24lc64t.c
@@ -0,0 +1,174 @@
+/*
+ * mc24lc64t.c - driver for Microchip 24LC64T
+ *
+ * Copyright (C) 2017 Celestica Corp.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#define EEPROM_SIZE 8192 //mc24lt64t eeprom size in bytes.
+
+struct mc24lc64t_data {
+ struct mutex update_lock;
+};
+
+static ssize_t mc24lc64t_read(struct file *filp, struct kobject *kobj,
+ struct bin_attribute *bin_attr,
+ char *buf, loff_t off, size_t count)
+{
+ struct i2c_client *client = kobj_to_i2c_client(kobj);
+ struct mc24lc64t_data *drvdata = i2c_get_clientdata(client);
+ unsigned long timeout, read_time, i = 0;
+ int status;
+
+ mutex_lock(&drvdata->update_lock);
+
+ if (i2c_smbus_write_byte_data(client, off>>8, off))
+ {
+ status = -EIO;
+ goto exit;
+ }
+
+ msleep(1);
+
+begin:
+
+ if (i < count)
+ {
+ timeout = jiffies + msecs_to_jiffies(25); /* 25 mS timeout*/
+ do {
+ read_time = jiffies;
+
+ status = i2c_smbus_read_byte(client);
+ if (status >= 0)
+ {
+ buf[i++] = status;
+ goto begin;
+ }
+ } while (time_before(read_time, timeout));
+
+ status = -ETIMEDOUT;
+ goto exit;
+ }
+
+ status = count;
+
+exit:
+ mutex_unlock(&drvdata->update_lock);
+
+ return status;
+}
+
+
+static ssize_t mc24lc64t_write (struct file *filp, struct kobject *kobj,
+ struct bin_attribute *bin_attr,
+ char *buf, loff_t off, size_t count){
+
+ struct i2c_client *client = kobj_to_i2c_client(kobj);
+ struct mc24lc64t_data *drvdata = i2c_get_clientdata(client);
+ unsigned long timeout, write_time, i = 0;
+ int status;
+ u16 value;
+
+ mutex_lock(&drvdata->update_lock);
+
+begin:
+ if (i < count){
+ timeout = jiffies + msecs_to_jiffies(25); /* 25 mS timeout*/
+ value = (buf[i] << 8 | ( off &0xff));
+ do {
+ write_time = jiffies;
+ status = i2c_smbus_write_word_data(client, off>>8, value);
+ if (status >= 0)
+ {
+ // increase offset
+ off++;
+ // increase buffer index
+ i++;
+ goto begin;
+ }
+ } while (time_before(write_time, timeout));
+ status = -ETIMEDOUT;
+ goto exit;
+ }
+ status = count;
+
+exit:
+ mutex_unlock(&drvdata->update_lock);
+ return status;
+}
+
+
+static struct bin_attribute mc24lc64t_bit_attr = {
+ .attr = {
+ .name = "eeprom",
+ .mode = S_IRUGO | S_IWUGO,
+ },
+ .size = EEPROM_SIZE,
+ .read = mc24lc64t_read,
+ .write = mc24lc64t_write,
+};
+
+static int mc24lc64t_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ struct i2c_adapter *adapter = client->adapter;
+ struct mc24lc64t_data *drvdata;
+ int err;
+
+ if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_WRITE_BYTE_DATA
+ | I2C_FUNC_SMBUS_READ_BYTE))
+ return -EPFNOSUPPORT;
+
+ if (!(drvdata = devm_kzalloc(&client->dev,
+ sizeof(struct mc24lc64t_data), GFP_KERNEL)))
+ return -ENOMEM;
+
+ i2c_set_clientdata(client, drvdata);
+ mutex_init(&drvdata->update_lock);
+
+ err = sysfs_create_bin_file(&client->dev.kobj, &mc24lc64t_bit_attr);
+ return err;
+}
+
+static int mc24lc64t_remove(struct i2c_client *client)
+{
+ struct mc24lc64t_data *drvdata = i2c_get_clientdata(client);
+ sysfs_remove_bin_file(&client->dev.kobj, &mc24lc64t_bit_attr);
+
+ return 0;
+}
+
+static const struct i2c_device_id mc24lc64t_id[] = {
+ { "24lc64t", 0 },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, mc24lc64t_id);
+
+static struct i2c_driver mc24lc64t_driver = {
+ .driver = {
+ .name = "mc24lc64t",
+ .owner = THIS_MODULE,
+ },
+ .probe = mc24lc64t_probe,
+ .remove = mc24lc64t_remove,
+ .id_table = mc24lc64t_id,
+};
+
+module_i2c_driver(mc24lc64t_driver);
+
+MODULE_AUTHOR("Abhisit Sangjan ");
+MODULE_DESCRIPTION("Microchip 24LC64T Driver");
+MODULE_LICENSE("GPL");
\ No newline at end of file
diff --git a/platform/broadcom/sonic-platform-modules-cel/silverstone/modules/switchboard.c b/platform/broadcom/sonic-platform-modules-cel/silverstone/modules/switchboard.c
new file mode 100644
index 000000000000..2ee6c858a8b6
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-cel/silverstone/modules/switchboard.c
@@ -0,0 +1,2106 @@
+/*
+ * switchboard.c - driver for Silverstone Switch board FPGA/CPLD.
+ *
+ * Author: Pradchaya Phucharoen
+ *
+ * Copyright (C) 2018 Celestica Corp.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * /
+ * \--sys
+ * \--devices
+ * \--platform
+ * \--silverstone
+ * |--FPGA
+ * |--CPLD1
+ * |--CPLD2
+ * \--SFF
+ * |--QSFP[1..32]
+ * \--SFP[1..2]
+ *
+ */
+
+#ifndef TEST_MODE
+#define MOD_VERSION "1.2.0"
+#else
+#define MOD_VERSION "TEST"
+#endif
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+static int majorNumber;
+
+#define CLASS_NAME "silverstone_fpga"
+#define DRIVER_NAME "switchboard"
+#define FPGA_PCI_NAME "Silverstone_fpga_pci"
+#define DEVICE_NAME "fwupgrade"
+
+
+static int smbus_access(struct i2c_adapter *adapter, u16 addr,
+ unsigned short flags, char rw, u8 cmd,
+ int size, union i2c_smbus_data *data);
+
+static int fpga_i2c_access(struct i2c_adapter *adapter, u16 addr,
+ unsigned short flags, char rw, u8 cmd,
+ int size, union i2c_smbus_data *data);
+
+static int fpgafw_init(void);
+static void fpgafw_exit(void);
+
+
+/*
+========================================
+FPGA PCIe BAR 0 Registers
+========================================
+Misc Control 0x00000000 – 0x000000FF.
+I2C_CH1 0x00000100 - 0x00000110
+I2C_CH2 0x00000200 - 0x00000210.
+I2C_CH3 0x00000300 - 0x00000310.
+I2C_CH4 0x00000400 - 0x00000410.
+I2C_CH5 0x00000500 - 0x00000510.
+I2C_CH6 0x00000600 - 0x00000610.
+I2C_CH7 0x00000700 - 0x00000710.
+I2C_CH8 0x00000800 - 0x00000810.
+I2C_CH9 0x00000900 - 0x00000910.
+I2C_CH10 0x00000A00 - 0x00000A10.
+I2C_CH11 0x00000B00 - 0x00000B10.
+I2C_CH12 0x00000C00 - 0x00000C10.
+I2C_CH13 0x00000D00 - 0x00000D10.
+SPI Master 0x00001200 - 0x00001300.
+DPLL SPI Master 0x00001320 - 0x0000132F.
+PORT XCVR 0x00004000 - 0x00004FFF.
+*/
+
+/* MISC */
+#define FPGA_VERSION 0x0000
+#define FPGA_VERSION_MJ_MSK 0xff00
+#define FPGA_VERSION_MN_MSK 0x00ff
+#define FPGA_SCRATCH 0x0004
+#define FPGA_BROAD_TYPE 0x0008
+#define FPGA_BROAD_REV_MSK 0x0038
+#define FPGA_BROAD_ID_MSK 0x0007
+#define FPGA_PLL_STATUS 0x0014
+#define BMC_I2C_SCRATCH 0x0020
+#define FPGA_SLAVE_CPLD_REST 0x0030
+#define FPGA_PERIPH_RESET_CTRL 0x0034
+#define FPGA_INT_STATUS 0x0040
+#define FPGA_INT_SRC_STATUS 0x0044
+#define FPGA_INT_FLAG 0x0048
+#define FPGA_INT_MASK 0x004c
+#define FPGA_MISC_CTRL 0x0050
+#define FPGA_MISC_STATUS 0x0054
+#define FPGA_AVS_VID_STATUS 0x0068
+#define FPGA_PORT_XCVR_READY 0x000c
+
+/* I2C_MASTER BASE ADDR */
+#define I2C_MASTER_FREQ_1 0x0100
+#define I2C_MASTER_CTRL_1 0x0104
+#define I2C_MASTER_STATUS_1 0x0108
+#define I2C_MASTER_DATA_1 0x010c
+#define I2C_MASTER_PORT_ID_1 0x0110
+#define I2C_MASTER_CH_1 1
+#define I2C_MASTER_CH_2 2
+#define I2C_MASTER_CH_3 3
+#define I2C_MASTER_CH_4 4
+#define I2C_MASTER_CH_5 5
+#define I2C_MASTER_CH_6 6
+#define I2C_MASTER_CH_7 7
+#define I2C_MASTER_CH_8 8
+#define I2C_MASTER_CH_9 9
+#define I2C_MASTER_CH_10 10
+#define I2C_MASTER_CH_11 11
+#define I2C_MASTER_CH_12 12
+#define I2C_MASTER_CH_13 13
+
+#define I2C_MASTER_CH_TOTAL I2C_MASTER_CH_5
+
+/* SPI_MASTER */
+#define SPI_MASTER_WR_EN 0x1200 /* one bit */
+#define SPI_MASTER_WR_DATA 0x1204 /* 32 bits */
+#define SPI_MASTER_CHK_ID 0x1208 /* one bit */
+#define SPI_MASTER_VERIFY 0x120c /* one bit */
+#define SPI_MASTER_STATUS 0x1210 /* 15 bits */
+#define SPI_MASTER_MODULE_RST 0x1214 /* one bit */
+
+/* FPGA FRONT PANEL PORT MGMT */
+#define SFF_PORT_CTRL_BASE 0x4000
+#define SFF_PORT_STATUS_BASE 0x4004
+#define SFF_PORT_INT_STATUS_BASE 0x4008
+#define SFF_PORT_INT_MASK_BASE 0x400c
+
+#define PORT_XCVR_REGISTER_SIZE 0x1000
+
+/* PORT CTRL REGISTER
+[31:7] RSVD
+[6] LPMOD 6
+[5] RSVD
+[4] RST 4
+[3:1] RSVD
+[0] TXDIS 0
+*/
+#define CTRL_LPMOD 6
+#define CTRL_RST 4
+#define CTRL_TXDIS 0
+
+/* PORT STATUS REGISTER
+[31:6] RSVD
+[5] IRQ 5
+[4] PRESENT 4
+[3] RSVD
+[2] TXFAULT 2
+[1] RXLOS 1
+[0] MODABS 0
+*/
+#define STAT_IRQ 5
+#define STAT_PRESENT 4
+#define STAT_TXFAULT 2
+#define STAT_RXLOS 1
+#define STAT_MODABS 0
+
+/* PORT INTRPT REGISTER
+[31:6] RSVD
+[5] INT_N 5
+[4] PRESENT 4
+[3] RSVD
+[2] RSVD
+[1] RXLOS 1
+[0] MODABS 0
+*/
+#define INTR_INT_N 5
+#define INTR_PRESENT 4
+#define INTR_TXFAULT 2
+#define INTR_RXLOS 1
+#define INTR_MODABS 0
+
+/* PORT INT MASK REGISTER
+[31:6] RSVD
+[5] INT_N 5
+[4] PRESENT 4
+[3] RSVD
+[2] RSVD
+[1] RXLOS_INT 1
+[0] MODABS 0
+*/
+#define MASK_INT_N 5
+#define MASK_PRESENT 4
+#define MASK_TXFAULT 2
+#define MASK_RXLOS 1
+#define MASK_MODABS 0
+
+enum {
+ I2C_SR_BIT_RXAK = 0,
+ I2C_SR_BIT_MIF,
+ I2C_SR_BIT_SRW,
+ I2C_SR_BIT_BCSTM,
+ I2C_SR_BIT_MAL,
+ I2C_SR_BIT_MBB,
+ I2C_SR_BIT_MAAS,
+ I2C_SR_BIT_MCF
+};
+
+enum {
+ I2C_CR_BIT_BCST = 0,
+ I2C_CR_BIT_RSTA = 2,
+ I2C_CR_BIT_TXAK,
+ I2C_CR_BIT_MTX,
+ I2C_CR_BIT_MSTA,
+ I2C_CR_BIT_MIEN,
+ I2C_CR_BIT_MEN,
+};
+
+/**
+ *
+ * The function is i2c algorithm implement to allow master access to
+ * correct endpoint devices trough the PCA9548 switch devices.
+ *
+ * FPGA I2C Master [mutex resource]
+ * |
+ * |
+ * ---------------------------
+ * | PCA9548(s) |
+ * ---1--2--3--4--5--6--7--8--
+ * | | | | | | | |
+ * EEPROM ... EEPROM
+ *
+ */
+
+#define VIRTUAL_I2C_QSFP_PORT 32
+#define VIRTUAL_I2C_SFP_PORT 2
+
+#define SFF_PORT_TOTAL VIRTUAL_I2C_QSFP_PORT + VIRTUAL_I2C_SFP_PORT
+
+#define VIRTUAL_I2C_BUS_OFFSET 10
+#define CPLD1_SLAVE_ADDR 0x30
+#define CPLD2_SLAVE_ADDR 0x31
+
+static struct class* fpgafwclass = NULL; // < The device-driver class struct pointer
+static struct device* fpgafwdev = NULL; // < The device-driver device struct pointer
+
+#define PCI_VENDOR_ID_TEST 0x1af4
+
+#ifndef PCI_VENDOR_ID_XILINX
+#define PCI_VENDOR_ID_XILINX 0x10EE
+#endif
+
+#define FPGA_PCIE_DEVICE_ID 0x7021
+#define TEST_PCIE_DEVICE_ID 0x1110
+
+
+#ifdef DEBUG_KERN
+#define info(fmt,args...) printk(KERN_INFO "line %3d : "fmt,__LINE__,##args)
+#define check(REG) printk(KERN_INFO "line %3d : %-8s = %2.2X",__LINE__,#REG,ioread8(REG));
+#else
+#define info(fmt,args...)
+#define check(REG)
+#endif
+
+#define GET_REG_BIT(REG,BIT) ((ioread8(REG) >> BIT) & 0x01)
+#define SET_REG_BIT_H(REG,BIT) iowrite8(ioread8(REG) | (0x01 << BIT),REG)
+#define SET_REG_BIT_L(REG,BIT) iowrite8(ioread8(REG) & ~(0x01 << BIT),REG)
+
+static struct mutex fpga_i2c_master_locks[I2C_MASTER_CH_TOTAL];
+/* Store lasted switch address and channel */
+static uint16_t fpga_i2c_lasted_access_port[I2C_MASTER_CH_TOTAL];
+
+enum PORT_TYPE {
+ NONE,
+ QSFP,
+ SFP
+};
+
+struct i2c_switch {
+ unsigned char master_bus; // I2C bus number
+ unsigned char switch_addr; // PCA9548 device address, 0xFF if directly connect to a bus.
+ unsigned char channel; // PCA9548 channel number. If the switch_addr is 0xFF, this value is ignored.
+ enum PORT_TYPE port_type; // QSFP/SFP tranceiver port type.
+ char calling_name[20]; // Calling name.
+};
+
+struct i2c_dev_data {
+ int portid;
+ struct i2c_switch pca9548;
+};
+
+/* PREDEFINED I2C SWITCH DEVICE TOPOLOGY */
+static struct i2c_switch fpga_i2c_bus_dev[] = {
+ /* BUS3 QSFP Exported as virtual bus */
+ {I2C_MASTER_CH_3, 0x71, 2, QSFP, "QSFP1"}, {I2C_MASTER_CH_3, 0x71, 3, QSFP, "QSFP2"},
+ {I2C_MASTER_CH_3, 0x71, 0, QSFP, "QSFP3"}, {I2C_MASTER_CH_3, 0x71, 1, QSFP, "QSFP4"},
+ {I2C_MASTER_CH_3, 0x71, 6, QSFP, "QSFP5"}, {I2C_MASTER_CH_3, 0x71, 5, QSFP, "QSFP6"},
+ {I2C_MASTER_CH_3, 0x73, 7, QSFP, "QSFP7"}, {I2C_MASTER_CH_3, 0x71, 4, QSFP, "QSFP8"},
+
+ {I2C_MASTER_CH_3, 0x73, 4, QSFP, "QSFP9"}, {I2C_MASTER_CH_3, 0x73, 3, QSFP, "QSFP10"},
+ {I2C_MASTER_CH_3, 0x73, 6, QSFP, "QSFP11"}, {I2C_MASTER_CH_3, 0x73, 2, QSFP, "QSFP12"},
+ {I2C_MASTER_CH_3, 0x73, 1, QSFP, "QSFP13"}, {I2C_MASTER_CH_3, 0x73, 5, QSFP, "QSFP14"},
+ {I2C_MASTER_CH_3, 0x71, 7, QSFP, "QSFP15"}, {I2C_MASTER_CH_3, 0x73, 0, QSFP, "QSFP16"},
+
+ {I2C_MASTER_CH_3, 0x72, 1, QSFP, "QSFP17"}, {I2C_MASTER_CH_3, 0x72, 7, QSFP, "QSFP18"},
+ {I2C_MASTER_CH_3, 0x72, 4, QSFP, "QSFP19"}, {I2C_MASTER_CH_3, 0x72, 0, QSFP, "QSFP20"},
+ {I2C_MASTER_CH_3, 0x72, 5, QSFP, "QSFP21"}, {I2C_MASTER_CH_3, 0x72, 2, QSFP, "QSFP22"},
+ {I2C_MASTER_CH_3, 0x70, 5, QSFP, "QSFP23"}, {I2C_MASTER_CH_3, 0x72, 6, QSFP, "QSFP24"},
+
+ {I2C_MASTER_CH_3, 0x72, 3, QSFP, "QSFP25"}, {I2C_MASTER_CH_3, 0x70, 6, QSFP, "QSFP26"},
+ {I2C_MASTER_CH_3, 0x70, 0, QSFP, "QSFP27"}, {I2C_MASTER_CH_3, 0x70, 7, QSFP, "QSFP28"},
+ {I2C_MASTER_CH_3, 0x70, 2, QSFP, "QSFP29"}, {I2C_MASTER_CH_3, 0x70, 4, QSFP, "QSFP30"},
+ {I2C_MASTER_CH_3, 0x70, 3, QSFP, "QSFP31"}, {I2C_MASTER_CH_3, 0x70, 1, QSFP, "QSFP32"},
+ /* BUS1 SFP+ Exported as virtual bus */
+ {I2C_MASTER_CH_1, 0xFF, 0, SFP, "SFP1"},
+ /* BUS2 SFP+ Exported as virtual bus */
+ {I2C_MASTER_CH_2, 0xFF, 0, SFP, "SFP2"},
+ /* BUS4 CPLD Access via I2C */
+ {I2C_MASTER_CH_4, 0xFF, 0, NONE, "CPLD_S"},
+ /* BUS5 CPLD_B */
+ {I2C_MASTER_CH_5, 0xFF, 0, NONE, "CPLD_B"},
+};
+
+#define VIRTUAL_I2C_PORT_LENGTH ARRAY_SIZE(fpga_i2c_bus_dev)
+#define SW_I2C_CPLD_INDEX SFF_PORT_TOTAL
+
+struct fpga_device {
+ /* data mmio region */
+ void __iomem *data_base_addr;
+ resource_size_t data_mmio_start;
+ resource_size_t data_mmio_len;
+};
+
+static struct fpga_device fpga_dev = {
+ .data_base_addr = 0,
+ .data_mmio_start = 0,
+ .data_mmio_len = 0,
+};
+
+struct silverstone_fpga_data {
+ struct device *sff_devices[SFF_PORT_TOTAL];
+ struct i2c_client *sff_i2c_clients[SFF_PORT_TOTAL];
+ struct i2c_adapter *i2c_adapter[VIRTUAL_I2C_PORT_LENGTH];
+ struct mutex fpga_lock; // For FPGA internal lock
+ void __iomem * fpga_read_addr;
+ uint8_t cpld1_read_addr;
+ uint8_t cpld2_read_addr;
+};
+
+struct sff_device_data {
+ int portid;
+ enum PORT_TYPE port_type;
+};
+
+struct silverstone_fpga_data *fpga_data;
+
+/*
+ * Kernel object for other module drivers.
+ * Other module can use these kobject as a parent.
+ */
+
+static struct kobject *fpga = NULL;
+static struct kobject *cpld1 = NULL;
+static struct kobject *cpld2 = NULL;
+
+/**
+ * Device node in sysfs tree.
+ */
+static struct device *sff_dev = NULL;
+
+
+static ssize_t version_show(struct device *dev, struct device_attribute *devattr,
+ char *buf)
+{
+ u32 version;
+
+ mutex_lock(&fpga_data->fpga_lock);
+ version = ioread32(fpga_dev.data_base_addr + FPGA_VERSION);
+ mutex_unlock(&fpga_data->fpga_lock);
+ return sprintf(buf, "%d.%d\n", version >> 16, version & 0xFFFF);
+}
+
+/**
+ * Show the value of the register set by 'set_fpga_reg_address'
+ * If the address is not set by 'set_fpga_reg_address' first,
+ * The version register is selected by default.
+ * @param buf register value in hextring
+ * @return number of bytes read, or an error code
+ */
+static ssize_t get_fpga_reg_value(struct device *dev, struct device_attribute *devattr,
+ char *buf)
+{
+ // read data from the address
+ uint32_t data;
+ data = ioread32(fpga_data->fpga_read_addr);
+ return sprintf(buf, "0x%8.8x\n", data);
+}
+/**
+ * Store the register address
+ * @param buf address wanted to be read value of
+ * @return number of bytes stored, or an error code
+ */
+static ssize_t set_fpga_reg_address(struct device *dev, struct device_attribute *devattr,
+ const char *buf, size_t count)
+{
+ uint32_t addr;
+ char *last;
+
+ addr = (uint32_t)strtoul(buf, &last, 16);
+ if (addr == 0 && buf == last) {
+ return -EINVAL;
+ }
+ fpga_data->fpga_read_addr = fpga_dev.data_base_addr + addr;
+ return count;
+}
+/**
+ * Show value of fpga scratch register
+ * @param buf register value in hexstring
+ * @return number of bytes read, or an error code
+ */
+static ssize_t get_fpga_scratch(struct device *dev, struct device_attribute *devattr,
+ char *buf)
+{
+ return sprintf(buf, "0x%8.8x\n", ioread32(fpga_dev.data_base_addr + FPGA_SCRATCH) & 0xffffffff);
+}
+/**
+ * Store value of fpga scratch register
+ * @param buf scratch register value passing from user space
+ * @return number of bytes stored, or an error code
+ */
+static ssize_t set_fpga_scratch(struct device *dev, struct device_attribute *devattr,
+ const char *buf, size_t count)
+{
+ uint32_t data;
+ char *last;
+ data = (uint32_t)strtoul(buf, &last, 16);
+ if (data == 0 && buf == last) {
+ return -EINVAL;
+ }
+ iowrite32(data, fpga_dev.data_base_addr + FPGA_SCRATCH);
+ return count;
+}
+/**
+ * Store a value in a specific register address
+ * @param buf the value and address in format '0xhhhh 0xhhhhhhhh'
+ * @return number of bytes sent by user space, or an error code
+ */
+static ssize_t set_fpga_reg_value(struct device *dev, struct device_attribute *devattr,
+ const char *buf, size_t count)
+{
+ // register are 4 bytes
+ uint32_t addr;
+ uint32_t value;
+ uint32_t mode = 8;
+ char *tok;
+ char clone[count];
+ char *pclone = clone;
+ char *last;
+
+ strcpy(clone, buf);
+
+ mutex_lock(&fpga_data->fpga_lock);
+ tok = strsep((char**)&pclone, " ");
+ if (tok == NULL) {
+ mutex_unlock(&fpga_data->fpga_lock);
+ return -EINVAL;
+ }
+ addr = (uint32_t)strtoul(tok, &last, 16);
+ if (addr == 0 && tok == last) {
+ mutex_unlock(&fpga_data->fpga_lock);
+ return -EINVAL;
+ }
+ tok = strsep((char**)&pclone, " ");
+ if (tok == NULL) {
+ mutex_unlock(&fpga_data->fpga_lock);
+ return -EINVAL;
+ }
+ value = (uint32_t)strtoul(tok, &last, 16);
+ if (value == 0 && tok == last) {
+ mutex_unlock(&fpga_data->fpga_lock);
+ return -EINVAL;
+ }
+ tok = strsep((char**)&pclone, " ");
+ if (tok == NULL) {
+ mode = 32;
+ } else {
+ mode = (uint32_t)strtoul(tok, &last, 10);
+ if (mode == 0 && tok == last) {
+ mutex_unlock(&fpga_data->fpga_lock);
+ return -EINVAL;
+ }
+ }
+ if (mode == 32) {
+ iowrite32(value, fpga_dev.data_base_addr + addr);
+ } else if (mode == 8) {
+ iowrite8(value, fpga_dev.data_base_addr + addr);
+ } else {
+ mutex_unlock(&fpga_data->fpga_lock);
+ return -EINVAL;
+ }
+ mutex_unlock(&fpga_data->fpga_lock);
+ return count;
+}
+
+/**
+ * Show FPGA port XCVR ready status
+ * @param buf 1 if the functin is ready, 0 if not.
+ * @return number of bytes read, or an error code
+ */
+static ssize_t ready_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ u32 data;
+ unsigned int REGISTER = FPGA_PORT_XCVR_READY;
+
+ mutex_lock(&fpga_data->fpga_lock);
+ data = ioread32(fpga_dev.data_base_addr + REGISTER);
+ mutex_unlock(&fpga_data->fpga_lock);
+ return sprintf(buf, "%d\n", (data >> 0) & 1U);
+}
+
+/* FPGA attributes */
+static DEVICE_ATTR( getreg, 0600, get_fpga_reg_value, set_fpga_reg_address);
+static DEVICE_ATTR( scratch, 0600, get_fpga_scratch, set_fpga_scratch);
+static DEVICE_ATTR( setreg, 0200, NULL , set_fpga_reg_value);
+static DEVICE_ATTR_RO(ready);
+static DEVICE_ATTR_RO(version);
+
+static struct attribute *fpga_attrs[] = {
+ &dev_attr_getreg.attr,
+ &dev_attr_scratch.attr,
+ &dev_attr_setreg.attr,
+ &dev_attr_ready.attr,
+ &dev_attr_version.attr,
+ NULL,
+};
+
+static struct attribute_group fpga_attr_grp = {
+ .attrs = fpga_attrs,
+};
+
+static ssize_t cpld1_version_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ u8 version;
+ int err;
+ err = fpga_i2c_access(fpga_data->i2c_adapter[SW_I2C_CPLD_INDEX],
+ CPLD1_SLAVE_ADDR, 0x00, I2C_SMBUS_READ, 0x00,
+ I2C_SMBUS_BYTE_DATA,
+ (union i2c_smbus_data *)&version);
+ if (err < 0)
+ return err;
+ return sprintf(buf, "%d.%d\n", version >> 4, version & 0x0F);
+}
+struct device_attribute dev_attr_cpld1_version = __ATTR(version, 0444, cpld1_version_show , NULL);
+
+/* SW CPLDs attributes */
+static ssize_t cpld1_getreg_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ // CPLD register is one byte
+ uint8_t data;
+ fpga_i2c_access(fpga_data->i2c_adapter[SW_I2C_CPLD_INDEX], CPLD1_SLAVE_ADDR, 0x00, I2C_SMBUS_READ, fpga_data->cpld1_read_addr, I2C_SMBUS_BYTE_DATA, (union i2c_smbus_data*)&data);
+ return sprintf(buf, "0x%2.2x\n", data);
+}
+static ssize_t cpld1_getreg_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t size)
+{
+ uint8_t addr;
+ char *last;
+ addr = (uint8_t)strtoul(buf, &last, 16);
+ if (addr == 0 && buf == last) {
+ return -EINVAL;
+ }
+ fpga_data->cpld1_read_addr = addr;
+ return size;
+}
+struct device_attribute dev_attr_cpld1_getreg = __ATTR(getreg, 0600, cpld1_getreg_show, cpld1_getreg_store);
+
+static ssize_t cpld1_scratch_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ // CPLD register is one byte
+ __u8 data;
+ int err;
+ err = fpga_i2c_access(fpga_data->i2c_adapter[SW_I2C_CPLD_INDEX], CPLD1_SLAVE_ADDR, 0x00, I2C_SMBUS_READ, 0x01, I2C_SMBUS_BYTE_DATA, (union i2c_smbus_data*)&data);
+ if (err < 0)
+ return err;
+ return sprintf(buf, "0x%2.2x\n", data);
+}
+static ssize_t cpld1_scratch_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t size)
+{
+ // CPLD register is one byte
+ __u8 data;
+ char *last;
+ int err;
+ data = (uint8_t)strtoul(buf, &last, 16);
+ if (data == 0 && buf == last) {
+ return -EINVAL;
+ }
+ err = fpga_i2c_access(fpga_data->i2c_adapter[SW_I2C_CPLD_INDEX], CPLD1_SLAVE_ADDR, 0x00, I2C_SMBUS_WRITE, 0x01, I2C_SMBUS_BYTE_DATA, (union i2c_smbus_data*)&data);
+ if (err < 0)
+ return err;
+ return size;
+}
+struct device_attribute dev_attr_cpld1_scratch = __ATTR(scratch, 0600, cpld1_scratch_show, cpld1_scratch_store);
+
+static ssize_t cpld1_setreg_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t size)
+{
+
+ uint8_t addr, value;
+ char *tok;
+ char clone[size];
+ char *pclone = clone;
+ int err;
+ char *last;
+
+ strcpy(clone, buf);
+
+ tok = strsep((char**)&pclone, " ");
+ if (tok == NULL) {
+ return -EINVAL;
+ }
+ addr = (uint8_t)strtoul(tok, &last, 16);
+ if (addr == 0 && tok == last) {
+ return -EINVAL;
+ }
+ tok = strsep((char**)&pclone, " ");
+ if (tok == NULL) {
+ return -EINVAL;
+ }
+ value = (uint8_t)strtoul(tok, &last, 16);
+ if (value == 0 && tok == last) {
+ return -EINVAL;
+ }
+
+ err = fpga_i2c_access(fpga_data->i2c_adapter[SW_I2C_CPLD_INDEX], CPLD1_SLAVE_ADDR, 0x00, I2C_SMBUS_WRITE, addr, I2C_SMBUS_BYTE_DATA, (union i2c_smbus_data*)&value);
+ if (err < 0)
+ return err;
+
+ return size;
+}
+struct device_attribute dev_attr_cpld1_setreg = __ATTR(setreg, 0200, NULL, cpld1_setreg_store);
+
+static struct attribute *cpld1_attrs[] = {
+ &dev_attr_cpld1_version.attr,
+ &dev_attr_cpld1_getreg.attr,
+ &dev_attr_cpld1_scratch.attr,
+ &dev_attr_cpld1_setreg.attr,
+ NULL,
+};
+
+static struct attribute_group cpld1_attr_grp = {
+ .attrs = cpld1_attrs,
+};
+
+static ssize_t cpld2_version_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ u8 version;
+ int err;
+ err = fpga_i2c_access(fpga_data->i2c_adapter[SW_I2C_CPLD_INDEX],
+ CPLD2_SLAVE_ADDR, 0x00, I2C_SMBUS_READ, 0x00,
+ I2C_SMBUS_BYTE_DATA,
+ (union i2c_smbus_data *)&version);
+ if (err < 0)
+ return err;
+ return sprintf(buf, "%d.%d\n", version >> 4, version & 0x0F);
+}
+struct device_attribute dev_attr_cpld2_version = __ATTR(version, 0444, cpld2_version_show , NULL);
+
+static ssize_t cpld2_getreg_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ // CPLD register is one byte
+ uint8_t data;
+ fpga_i2c_access(fpga_data->i2c_adapter[SW_I2C_CPLD_INDEX], CPLD2_SLAVE_ADDR, 0x00, I2C_SMBUS_READ, fpga_data->cpld2_read_addr, I2C_SMBUS_BYTE_DATA, (union i2c_smbus_data*)&data);
+ return sprintf(buf, "0x%2.2x\n", data);
+}
+
+static ssize_t cpld2_getreg_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t size)
+{
+ // CPLD register is one byte
+ uint32_t addr;
+ char *last;
+ addr = (uint8_t)strtoul(buf, &last, 16);
+ if (addr == 0 && buf == last) {
+ return -EINVAL;
+ }
+ fpga_data->cpld2_read_addr = addr;
+ return size;
+}
+struct device_attribute dev_attr_cpld2_getreg = __ATTR(getreg, 0600, cpld2_getreg_show, cpld2_getreg_store);
+
+static ssize_t cpld2_scratch_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ // CPLD register is one byte
+ __u8 data;
+ int err;
+ err = fpga_i2c_access(fpga_data->i2c_adapter[SW_I2C_CPLD_INDEX], CPLD2_SLAVE_ADDR, 0x00, I2C_SMBUS_READ, 0x01, I2C_SMBUS_BYTE_DATA, (union i2c_smbus_data*)&data);
+ if (err < 0)
+ return err;
+ return sprintf(buf, "0x%2.2x\n", data);
+}
+
+static ssize_t cpld2_scratch_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t size)
+{
+ // CPLD register is one byte
+ __u8 data;
+ char *last;
+ int err;
+
+ data = (uint8_t)strtoul(buf, &last, 16);
+ if (data == 0 && buf == last) {
+ return -EINVAL;
+ }
+ err = fpga_i2c_access(fpga_data->i2c_adapter[SW_I2C_CPLD_INDEX], CPLD2_SLAVE_ADDR, 0x00, I2C_SMBUS_WRITE, 0x01, I2C_SMBUS_BYTE_DATA, (union i2c_smbus_data*)&data);
+ if (err < 0)
+ return err;
+ return size;
+}
+struct device_attribute dev_attr_cpld2_scratch = __ATTR(scratch, 0600, cpld2_scratch_show, cpld2_scratch_store);
+
+static ssize_t cpld2_setreg_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t size)
+{
+ uint8_t addr, value;
+ char *tok;
+ char clone[size];
+ char *pclone = clone;
+ int err;
+ char *last;
+
+ strcpy(clone, buf);
+
+ tok = strsep((char**)&pclone, " ");
+ if (tok == NULL) {
+ return -EINVAL;
+ }
+ addr = (uint8_t)strtoul(tok, &last, 16);
+ if (addr == 0 && tok == last) {
+ return -EINVAL;
+ }
+ tok = strsep((char**)&pclone, " ");
+ if (tok == NULL) {
+ return -EINVAL;
+ }
+ value = (uint8_t)strtoul(tok, &last, 16);
+ if (value == 0 && tok == last) {
+ return -EINVAL;
+ }
+
+ err = fpga_i2c_access(fpga_data->i2c_adapter[SW_I2C_CPLD_INDEX], CPLD2_SLAVE_ADDR, 0x00, I2C_SMBUS_WRITE, addr, I2C_SMBUS_BYTE_DATA, (union i2c_smbus_data*)&value);
+ if (err < 0)
+ return err;
+
+ return size;
+}
+struct device_attribute dev_attr_cpld2_setreg = __ATTR(setreg, 0200, NULL, cpld2_setreg_store);
+
+static struct attribute *cpld2_attrs[] = {
+ &dev_attr_cpld2_version.attr,
+ &dev_attr_cpld2_getreg.attr,
+ &dev_attr_cpld2_scratch.attr,
+ &dev_attr_cpld2_setreg.attr,
+ NULL,
+};
+
+static struct attribute_group cpld2_attr_grp = {
+ .attrs = cpld2_attrs,
+};
+
+/* QSFP/SFP+ attributes */
+static ssize_t qsfp_modirq_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ u32 data;
+ struct sff_device_data *dev_data = dev_get_drvdata(dev);
+ unsigned int portid = dev_data->portid;
+ unsigned int REGISTER = SFF_PORT_STATUS_BASE + (portid - 1) * 0x10;
+
+ mutex_lock(&fpga_data->fpga_lock);
+ data = ioread32(fpga_dev.data_base_addr + REGISTER);
+ mutex_unlock(&fpga_data->fpga_lock);
+ return sprintf(buf, "%d\n", (data >> STAT_IRQ) & 1U);
+}
+DEVICE_ATTR_RO(qsfp_modirq);
+
+static ssize_t qsfp_modprs_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ u32 data;
+ struct sff_device_data *dev_data = dev_get_drvdata(dev);
+ unsigned int portid = dev_data->portid;
+ unsigned int REGISTER = SFF_PORT_STATUS_BASE + (portid - 1) * 0x10;
+
+ mutex_lock(&fpga_data->fpga_lock);
+ data = ioread32(fpga_dev.data_base_addr + REGISTER);
+ mutex_unlock(&fpga_data->fpga_lock);
+ return sprintf(buf, "%d\n", (data >> STAT_PRESENT) & 1U);
+}
+DEVICE_ATTR_RO(qsfp_modprs);
+
+static ssize_t sfp_txfault_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ u32 data;
+ struct sff_device_data *dev_data = dev_get_drvdata(dev);
+ unsigned int portid = dev_data->portid;
+ unsigned int REGISTER = SFF_PORT_STATUS_BASE + (portid - 1) * 0x10;
+
+ mutex_lock(&fpga_data->fpga_lock);
+ data = ioread32(fpga_dev.data_base_addr + REGISTER);
+ mutex_unlock(&fpga_data->fpga_lock);
+ return sprintf(buf, "%d\n", (data >> STAT_TXFAULT) & 1U);
+}
+DEVICE_ATTR_RO(sfp_txfault);
+
+static ssize_t sfp_rxlos_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ u32 data;
+ struct sff_device_data *dev_data = dev_get_drvdata(dev);
+ unsigned int portid = dev_data->portid;
+ unsigned int REGISTER = SFF_PORT_STATUS_BASE + (portid - 1) * 0x10;
+
+ mutex_lock(&fpga_data->fpga_lock);
+ data = ioread32(fpga_dev.data_base_addr + REGISTER);
+ mutex_unlock(&fpga_data->fpga_lock);
+ return sprintf(buf, "%d\n", (data >> STAT_RXLOS) & 1U);
+}
+DEVICE_ATTR_RO(sfp_rxlos);
+
+static ssize_t sfp_modabs_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ u32 data;
+ struct sff_device_data *dev_data = dev_get_drvdata(dev);
+ unsigned int portid = dev_data->portid;
+ unsigned int REGISTER = SFF_PORT_STATUS_BASE + (portid - 1) * 0x10;
+
+ mutex_lock(&fpga_data->fpga_lock);
+ data = ioread32(fpga_dev.data_base_addr + REGISTER);
+ mutex_unlock(&fpga_data->fpga_lock);
+ return sprintf(buf, "%d\n", (data >> STAT_MODABS) & 1U);
+}
+DEVICE_ATTR_RO(sfp_modabs);
+
+static ssize_t qsfp_lpmode_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ u32 data;
+ struct sff_device_data *dev_data = dev_get_drvdata(dev);
+ unsigned int portid = dev_data->portid;
+ unsigned int REGISTER = SFF_PORT_CTRL_BASE + (portid - 1) * 0x10;
+
+ mutex_lock(&fpga_data->fpga_lock);
+ data = ioread32(fpga_dev.data_base_addr + REGISTER);
+ mutex_unlock(&fpga_data->fpga_lock);
+ return sprintf(buf, "%d\n", (data >> CTRL_LPMOD) & 1U);
+}
+static ssize_t qsfp_lpmode_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t size)
+{
+ ssize_t status;
+ long value;
+ u32 data;
+ struct sff_device_data *dev_data = dev_get_drvdata(dev);
+ unsigned int portid = dev_data->portid;
+ unsigned int REGISTER = SFF_PORT_CTRL_BASE + (portid - 1) * 0x10;
+
+ mutex_lock(&fpga_data->fpga_lock);
+ status = kstrtol(buf, 0, &value);
+ if (status == 0) {
+ // if value is 0, disable the lpmode
+ data = ioread32(fpga_dev.data_base_addr + REGISTER);
+ if (!value)
+ data = data & ~( (u32)0x1 << CTRL_LPMOD);
+ else
+ data = data | ((u32)0x1 << CTRL_LPMOD);
+ iowrite32(data, fpga_dev.data_base_addr + REGISTER);
+ status = size;
+ }
+ mutex_unlock(&fpga_data->fpga_lock);
+ return status;
+}
+DEVICE_ATTR_RW(qsfp_lpmode);
+
+static ssize_t qsfp_reset_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ u32 data;
+ struct sff_device_data *dev_data = dev_get_drvdata(dev);
+ unsigned int portid = dev_data->portid;
+ unsigned int REGISTER = SFF_PORT_CTRL_BASE + (portid - 1) * 0x10;
+
+ mutex_lock(&fpga_data->fpga_lock);
+ data = ioread32(fpga_dev.data_base_addr + REGISTER);
+ mutex_unlock(&fpga_data->fpga_lock);
+ return sprintf(buf, "%d\n", (data >> CTRL_RST) & 1U);
+}
+
+static ssize_t qsfp_reset_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t size)
+{
+ ssize_t status;
+ long value;
+ u32 data;
+ struct sff_device_data *dev_data = dev_get_drvdata(dev);
+ unsigned int portid = dev_data->portid;
+ unsigned int REGISTER = SFF_PORT_CTRL_BASE + (portid - 1) * 0x10;
+
+ mutex_lock(&fpga_data->fpga_lock);
+ status = kstrtol(buf, 0, &value);
+ if (status == 0) {
+ // if value is 0, reset signal is low
+ data = ioread32(fpga_dev.data_base_addr + REGISTER);
+ if (!value)
+ data = data & ~( (u32)0x1 << CTRL_RST);
+ else
+ data = data | ((u32)0x1 << CTRL_RST);
+ iowrite32(data, fpga_dev.data_base_addr + REGISTER);
+ status = size;
+ }
+ mutex_unlock(&fpga_data->fpga_lock);
+ return status;
+}
+DEVICE_ATTR_RW(qsfp_reset);
+
+static ssize_t sfp_txdisable_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ u32 data;
+ struct sff_device_data *dev_data = dev_get_drvdata(dev);
+ unsigned int portid = dev_data->portid;
+ unsigned int REGISTER = SFF_PORT_CTRL_BASE + (portid - 1) * 0x10;
+
+ mutex_lock(&fpga_data->fpga_lock);
+ data = ioread32(fpga_dev.data_base_addr + REGISTER);
+ mutex_unlock(&fpga_data->fpga_lock);
+ return sprintf(buf, "%d\n", (data >> CTRL_TXDIS) & 1U);
+}
+static ssize_t sfp_txdisable_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t size)
+{
+ ssize_t status;
+ long value;
+ u32 data;
+ struct sff_device_data *dev_data = dev_get_drvdata(dev);
+ unsigned int portid = dev_data->portid;
+ unsigned int REGISTER = SFF_PORT_CTRL_BASE + (portid - 1) * 0x10;
+
+ mutex_lock(&fpga_data->fpga_lock);
+ status = kstrtol(buf, 0, &value);
+ if (status == 0) {
+ // check if value is 0 clear
+ data = ioread32(fpga_dev.data_base_addr + REGISTER);
+ if (!value)
+ data = data & ~( (u32)0x1 << CTRL_TXDIS);
+ else
+ data = data | ((u32)0x1 << CTRL_TXDIS);
+ iowrite32(data, fpga_dev.data_base_addr + REGISTER);
+ status = size;
+ }
+ mutex_unlock(&fpga_data->fpga_lock);
+ return status;
+}
+DEVICE_ATTR_RW(sfp_txdisable);
+
+static struct attribute *sff_attrs[] = {
+ &dev_attr_qsfp_modirq.attr,
+ &dev_attr_qsfp_modprs.attr,
+ &dev_attr_qsfp_lpmode.attr,
+ &dev_attr_qsfp_reset.attr,
+ &dev_attr_sfp_txfault.attr,
+ &dev_attr_sfp_rxlos.attr,
+ &dev_attr_sfp_modabs.attr,
+ &dev_attr_sfp_txdisable.attr,
+ NULL,
+};
+
+static struct attribute_group sff_attr_grp = {
+ .attrs = sff_attrs,
+};
+
+static const struct attribute_group *sff_attr_grps[] = {
+ &sff_attr_grp,
+ NULL
+};
+
+
+static ssize_t port_led_mode_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ // value can be "nomal", "test"
+ __u8 led_mode_1, led_mode_2;
+ int err;
+ err = fpga_i2c_access(fpga_data->i2c_adapter[SW_I2C_CPLD_INDEX], CPLD1_SLAVE_ADDR, 0x00, I2C_SMBUS_READ, 0x09, I2C_SMBUS_BYTE_DATA, (union i2c_smbus_data*)&led_mode_1);
+ if (err < 0)
+ return err;
+ err = fpga_i2c_access(fpga_data->i2c_adapter[SW_I2C_CPLD_INDEX], CPLD2_SLAVE_ADDR, 0x00, I2C_SMBUS_READ, 0x09, I2C_SMBUS_BYTE_DATA, (union i2c_smbus_data*)&led_mode_2);
+ if (err < 0)
+ return err;
+ return sprintf(buf, "%s %s\n",
+ led_mode_1 ? "test" : "normal",
+ led_mode_2 ? "test" : "normal");
+}
+static ssize_t port_led_mode_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t size)
+{
+ int status;
+ __u8 led_mode_1;
+ if (sysfs_streq(buf, "test")) {
+ led_mode_1 = 0x01;
+ } else if (sysfs_streq(buf, "normal")) {
+ led_mode_1 = 0x00;
+ } else {
+ return -EINVAL;
+ }
+ status = fpga_i2c_access(fpga_data->i2c_adapter[SW_I2C_CPLD_INDEX], CPLD1_SLAVE_ADDR, 0x00,
+ I2C_SMBUS_WRITE, 0x09, I2C_SMBUS_BYTE_DATA, (union i2c_smbus_data*)&led_mode_1);
+ status = fpga_i2c_access(fpga_data->i2c_adapter[SW_I2C_CPLD_INDEX], CPLD2_SLAVE_ADDR, 0x00,
+ I2C_SMBUS_WRITE, 0x09, I2C_SMBUS_BYTE_DATA, (union i2c_smbus_data*)&led_mode_1);
+ return size;
+}
+DEVICE_ATTR_RW(port_led_mode);
+
+// Only work when port_led_mode set to 1
+static ssize_t port_led_color_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ // value can be R/G/B/C/M/Y/W/OFF
+ __u8 led_color1, led_color2;
+ int err;
+ err = fpga_i2c_access(fpga_data->i2c_adapter[SW_I2C_CPLD_INDEX], CPLD1_SLAVE_ADDR, 0x00, I2C_SMBUS_READ, 0x09, I2C_SMBUS_BYTE_DATA, (union i2c_smbus_data*)&led_color1);
+ if (err < 0)
+ return err;
+ err = fpga_i2c_access(fpga_data->i2c_adapter[SW_I2C_CPLD_INDEX], CPLD2_SLAVE_ADDR, 0x00, I2C_SMBUS_READ, 0x09, I2C_SMBUS_BYTE_DATA, (union i2c_smbus_data*)&led_color2);
+ if (err < 0)
+ return err;
+ return sprintf(buf, "%s %s\n",
+ led_color1 == 0x07 ? "off" : led_color1 == 0x06 ? "green" : led_color1 == 0x05 ? "red" : led_color1 == 0x04 ?
+ "yellow" : led_color1 == 0x03 ? "blue" : led_color1 == 0x02 ? "cyan" : led_color1 == 0x01 ? "magenta" : "white",
+ led_color1 == 0x07 ? "off" : led_color1 == 0x06 ? "green" : led_color1 == 0x05 ? "red" : led_color1 == 0x04 ?
+ "yellow" : led_color1 == 0x03 ? "blue" : led_color1 == 0x02 ? "cyan" : led_color1 == 0x01 ? "magenta" : "white");
+}
+
+static ssize_t port_led_color_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t size)
+{
+ int status;
+ __u8 led_color;
+ if (sysfs_streq(buf, "off")) {
+ led_color = 0x07;
+ } else if (sysfs_streq(buf, "green")) {
+ led_color = 0x06;
+ } else if (sysfs_streq(buf, "red")) {
+ led_color = 0x05;
+ } else if (sysfs_streq(buf, "yellow")) {
+ led_color = 0x04;
+ } else if (sysfs_streq(buf, "blue")) {
+ led_color = 0x03;
+ } else if (sysfs_streq(buf, "cyan")) {
+ led_color = 0x02;
+ } else if (sysfs_streq(buf, "magenta")) {
+ led_color = 0x01;
+ } else if (sysfs_streq(buf, "white")) {
+ led_color = 0x00;
+ } else {
+ status = -EINVAL;
+ return status;
+ }
+ status = fpga_i2c_access(fpga_data->i2c_adapter[SW_I2C_CPLD_INDEX], CPLD1_SLAVE_ADDR, 0x00,
+ I2C_SMBUS_WRITE, 0x0A, I2C_SMBUS_BYTE_DATA, (union i2c_smbus_data*)&led_color);
+ status = fpga_i2c_access(fpga_data->i2c_adapter[SW_I2C_CPLD_INDEX], CPLD2_SLAVE_ADDR, 0x00,
+ I2C_SMBUS_WRITE, 0x0A, I2C_SMBUS_BYTE_DATA, (union i2c_smbus_data*)&led_color);
+ return size;
+}
+DEVICE_ATTR_RW(port_led_color);
+
+static struct attribute *sff_led_test[] = {
+ &dev_attr_port_led_mode.attr,
+ &dev_attr_port_led_color.attr,
+ NULL,
+};
+
+static struct attribute_group sff_led_test_grp = {
+ .attrs = sff_led_test,
+};
+
+static struct device * silverstone_sff_init(int portid) {
+ struct sff_device_data *new_data;
+ struct device *new_device;
+
+ new_data = kzalloc(sizeof(*new_data), GFP_KERNEL);
+ if (!new_data) {
+ printk(KERN_ALERT "Cannot alloc sff device data @port%d", portid);
+ return NULL;
+ }
+ /* The QSFP port ID start from 1 */
+ new_data->portid = portid + 1;
+ new_data->port_type = fpga_i2c_bus_dev[portid].port_type;
+ new_device = device_create_with_groups(fpgafwclass, sff_dev, MKDEV(0, 0), new_data, sff_attr_grps, "%s", fpga_i2c_bus_dev[portid].calling_name);
+ if (IS_ERR(new_device)) {
+ printk(KERN_ALERT "Cannot create sff device @port%d", portid);
+ kfree(new_data);
+ return NULL;
+ }
+ return new_device;
+}
+
+static int i2c_wait_ack(struct i2c_adapter *a, unsigned long timeout, int writing) {
+ int error = 0;
+ int Status;
+
+ struct i2c_dev_data *new_data = i2c_get_adapdata(a);
+ void __iomem *pci_bar = fpga_dev.data_base_addr;
+
+ unsigned int REG_FDR0;
+ unsigned int REG_CR0;
+ unsigned int REG_SR0;
+ unsigned int REG_DR0;
+ unsigned int REG_ID0;
+
+ unsigned int master_bus = new_data->pca9548.master_bus;
+
+ if (master_bus < I2C_MASTER_CH_1 || master_bus > I2C_MASTER_CH_TOTAL) {
+ error = -EINVAL;
+ return error;
+ }
+
+ REG_FDR0 = I2C_MASTER_FREQ_1 + (master_bus - 1) * 0x0100;
+ REG_CR0 = I2C_MASTER_CTRL_1 + (master_bus - 1) * 0x0100;
+ REG_SR0 = I2C_MASTER_STATUS_1 + (master_bus - 1) * 0x0100;
+ REG_DR0 = I2C_MASTER_DATA_1 + (master_bus - 1) * 0x0100;
+ REG_ID0 = I2C_MASTER_PORT_ID_1 + (master_bus - 1) * 0x0100;
+
+ check(pci_bar + REG_SR0);
+ check(pci_bar + REG_CR0);
+
+ timeout = jiffies + msecs_to_jiffies(timeout);
+ while (1) {
+ Status = ioread8(pci_bar + REG_SR0);
+ if (jiffies > timeout) {
+ info("Status %2.2X", Status);
+ info("Error Timeout");
+ error = -ETIMEDOUT;
+ break;
+ }
+
+
+ if (Status & (1 << I2C_SR_BIT_MIF)) {
+ break;
+ }
+
+ if (writing == 0 && (Status & (1 << I2C_SR_BIT_MCF))) {
+ break;
+ }
+ }
+ Status = ioread8(pci_bar + REG_SR0);
+ iowrite8(0, pci_bar + REG_SR0);
+
+ if (error < 0) {
+ info("Status %2.2X", Status);
+ return error;
+ }
+
+ if (!(Status & (1 << I2C_SR_BIT_MCF))) {
+ info("Error Unfinish");
+ return -EIO;
+ }
+
+ if (Status & (1 << I2C_SR_BIT_MAL)) {
+ info("Error MAL");
+ return -EAGAIN;
+ }
+
+ if (Status & (1 << I2C_SR_BIT_RXAK)) {
+ info( "SL No Acknowlege");
+ if (writing) {
+ info("Error No Acknowlege");
+ iowrite8(1 << I2C_CR_BIT_MEN, pci_bar + REG_CR0);
+ return -ENXIO;
+ }
+ } else {
+ info( "SL Acknowlege");
+ }
+
+ return 0;
+}
+
+static int smbus_access(struct i2c_adapter *adapter, u16 addr,
+ unsigned short flags, char rw, u8 cmd,
+ int size, union i2c_smbus_data *data)
+{
+ int error = 0;
+ int cnt = 0;
+ int bid = 0;
+ struct i2c_dev_data *dev_data;
+ void __iomem *pci_bar;
+ unsigned int portid, master_bus;
+ unsigned int REG_FDR0;
+ unsigned int REG_CR0;
+ unsigned int REG_SR0;
+ unsigned int REG_DR0;
+ unsigned int REG_ID0;
+
+ /* Write the command register */
+ dev_data = i2c_get_adapdata(adapter);
+ portid = dev_data->portid;
+ pci_bar = fpga_dev.data_base_addr;
+ master_bus = dev_data->pca9548.master_bus;
+ REG_FDR0 = I2C_MASTER_FREQ_1 + (master_bus - 1) * 0x0100;
+ REG_CR0 = I2C_MASTER_CTRL_1 + (master_bus - 1) * 0x0100;
+ REG_SR0 = I2C_MASTER_STATUS_1 + (master_bus - 1) * 0x0100;
+ REG_DR0 = I2C_MASTER_DATA_1 + (master_bus - 1) * 0x0100;
+ REG_ID0 = I2C_MASTER_PORT_ID_1 + (master_bus - 1) * 0x0100;
+
+ if (master_bus < I2C_MASTER_CH_1 || master_bus > I2C_MASTER_CH_TOTAL) {
+ error = -EINVAL;
+ goto Done;
+ }
+
+#ifdef DEBUG_KERN
+ printk(KERN_INFO "portid %2d|@ 0x%2.2X|f 0x%4.4X|(%d)%-5s| (%d)%-10s|CMD %2.2X "
+ , portid, addr, flags, rw, rw == 1 ? "READ " : "WRITE"
+ , size, size == 0 ? "QUICK" :
+ size == 1 ? "BYTE" :
+ size == 2 ? "BYTE_DATA" :
+ size == 3 ? "WORD_DATA" :
+ size == 4 ? "PROC_CALL" :
+ size == 5 ? "BLOCK_DATA" : "ERROR"
+ , cmd);
+#endif
+ /* Map the size to what the chip understands */
+ switch (size) {
+ case I2C_SMBUS_QUICK:
+ case I2C_SMBUS_BYTE:
+ case I2C_SMBUS_BYTE_DATA:
+ case I2C_SMBUS_WORD_DATA:
+ case I2C_SMBUS_BLOCK_DATA:
+ break;
+ default:
+ printk(KERN_INFO "Unsupported transaction %d\n", size);
+ error = -EOPNOTSUPP;
+ goto Done;
+ }
+
+ iowrite8(portid, pci_bar + REG_ID0);
+
+ ////[S][ADDR/R]
+ //Clear status register
+ iowrite8(0, pci_bar + REG_SR0);
+ iowrite8(1 << I2C_CR_BIT_MIEN | 1 << I2C_CR_BIT_MTX | 1 << I2C_CR_BIT_MSTA , pci_bar + REG_CR0);
+ SET_REG_BIT_H(pci_bar + REG_CR0, I2C_CR_BIT_MEN);
+
+ if (rw == I2C_SMBUS_READ &&
+ (size == I2C_SMBUS_QUICK || size == I2C_SMBUS_BYTE)) {
+ // sent device address with Read mode
+ iowrite8(addr << 1 | 0x01, pci_bar + REG_DR0);
+ } else {
+ // sent device address with Write mode
+ iowrite8(addr << 1 | 0x00, pci_bar + REG_DR0);
+ }
+
+
+
+ info( "MS Start");
+
+ //// Wait {A}
+ error = i2c_wait_ack(adapter, 12, 1);
+ if (error < 0) {
+ info( "get error %d", error);
+ goto Done;
+ }
+
+ //// [CMD]{A}
+ if (size == I2C_SMBUS_BYTE_DATA ||
+ size == I2C_SMBUS_WORD_DATA ||
+ size == I2C_SMBUS_BLOCK_DATA ||
+ (size == I2C_SMBUS_BYTE && rw == I2C_SMBUS_WRITE)) {
+
+ //sent command code to data register
+ iowrite8(cmd, pci_bar + REG_DR0);
+ info( "MS Send CMD 0x%2.2X", cmd);
+
+ // Wait {A}
+ error = i2c_wait_ack(adapter, 12, 1);
+ if (error < 0) {
+ info( "get error %d", error);
+ goto Done;
+ }
+ }
+
+ switch (size) {
+ case I2C_SMBUS_BYTE_DATA:
+ cnt = 1; break;
+ case I2C_SMBUS_WORD_DATA:
+ cnt = 2; break;
+ case I2C_SMBUS_BLOCK_DATA:
+ // in block data mode keep number of byte in block[0]
+ cnt = data->block[0];
+ break;
+ default:
+ cnt = 0; break;
+ }
+
+ // [CNT] used only bloack data write
+ if (size == I2C_SMBUS_BLOCK_DATA && rw == I2C_SMBUS_WRITE) {
+
+ iowrite8(cnt, pci_bar + REG_DR0);
+ info( "MS Send CNT 0x%2.2X", cnt);
+
+ // Wait {A}
+ error = i2c_wait_ack(adapter, 12, 1);
+ if (error < 0) {
+ info( "get error %d", error);
+ goto Done;
+ }
+ }
+
+ // [DATA]{A}
+ if ( rw == I2C_SMBUS_WRITE && (
+ size == I2C_SMBUS_BYTE ||
+ size == I2C_SMBUS_BYTE_DATA ||
+ size == I2C_SMBUS_WORD_DATA ||
+ size == I2C_SMBUS_BLOCK_DATA
+ )) {
+ int bid = 0;
+ info( "MS prepare to sent [%d bytes]", cnt);
+ if (size == I2C_SMBUS_BLOCK_DATA ) {
+ bid = 1; // block[0] is cnt;
+ cnt += 1; // offset from block[0]
+ }
+ for (; bid < cnt; bid++) {
+
+ iowrite8(data->block[bid], pci_bar + REG_DR0);
+ info( " Data > %2.2X", data->block[bid]);
+ // Wait {A}
+ error = i2c_wait_ack(adapter, 12, 1);
+ if (error < 0) {
+ goto Done;
+ }
+ }
+ }
+
+ //REPEATE START
+ if ( rw == I2C_SMBUS_READ && (
+ size == I2C_SMBUS_BYTE_DATA ||
+ size == I2C_SMBUS_WORD_DATA ||
+ size == I2C_SMBUS_BLOCK_DATA
+ )) {
+ info( "MS Repeated Start");
+
+ SET_REG_BIT_L(pci_bar + REG_CR0, I2C_CR_BIT_MEN);
+ iowrite8(1 << I2C_CR_BIT_MIEN |
+ 1 << I2C_CR_BIT_MTX |
+ 1 << I2C_CR_BIT_MSTA |
+ 1 << I2C_CR_BIT_RSTA , pci_bar + REG_CR0);
+ SET_REG_BIT_H(pci_bar + REG_CR0, I2C_CR_BIT_MEN);
+
+ // sent Address with Read mode
+ iowrite8( addr << 1 | 0x1 , pci_bar + REG_DR0);
+
+ // Wait {A}
+ error = i2c_wait_ack(adapter, 12, 1);
+ if (error < 0) {
+ goto Done;
+ }
+
+ }
+
+ if ( rw == I2C_SMBUS_READ && (
+ size == I2C_SMBUS_BYTE ||
+ size == I2C_SMBUS_BYTE_DATA ||
+ size == I2C_SMBUS_WORD_DATA ||
+ size == I2C_SMBUS_BLOCK_DATA
+ )) {
+
+ switch (size) {
+ case I2C_SMBUS_BYTE:
+ case I2C_SMBUS_BYTE_DATA:
+ cnt = 1; break;
+ case I2C_SMBUS_WORD_DATA:
+ cnt = 2; break;
+ case I2C_SMBUS_BLOCK_DATA:
+ //will be changed after recived first data
+ cnt = 3; break;
+ default:
+ cnt = 0; break;
+ }
+
+ info( "MS Receive");
+
+ //set to Receive mode
+ iowrite8(1 << I2C_CR_BIT_MEN |
+ 1 << I2C_CR_BIT_MIEN |
+ 1 << I2C_CR_BIT_MSTA , pci_bar + REG_CR0);
+
+ for (bid = -1; bid < cnt; bid++) {
+
+ // Wait {A}
+ error = i2c_wait_ack(adapter, 12, 0);
+ if (error < 0) {
+ goto Done;
+ }
+
+ if (bid == cnt - 2) {
+ info( "SET NAK");
+ SET_REG_BIT_H(pci_bar + REG_CR0, I2C_CR_BIT_TXAK);
+ }
+
+ if (bid < 0) {
+ ioread8(pci_bar + REG_DR0);
+ info( "READ Dummy Byte" );
+ } else {
+
+ if (bid == cnt - 1) {
+ info ( "SET STOP in read loop");
+ SET_REG_BIT_L(pci_bar + REG_CR0, I2C_CR_BIT_MSTA);
+ }
+ data->block[bid] = ioread8(pci_bar + REG_DR0);
+
+ info( "DATA IN [%d] %2.2X", bid, data->block[bid]);
+
+ if (size == I2C_SMBUS_BLOCK_DATA && bid == 0) {
+ cnt = data->block[0] + 1;
+ }
+ }
+ }
+ }
+
+ //[P]
+ SET_REG_BIT_L(pci_bar + REG_CR0, I2C_CR_BIT_MSTA);
+ i2c_wait_ack(adapter, 12, 0);
+ info( "MS STOP");
+
+Done:
+ iowrite8(1 << I2C_CR_BIT_MEN, pci_bar + REG_CR0);
+ check(pci_bar + REG_CR0);
+ check(pci_bar + REG_SR0);
+#ifdef DEBUG_KERN
+ printk(KERN_INFO "END --- Error code %d", error);
+#endif
+
+ return error;
+}
+
+/**
+ * Wrapper of smbus_access access with PCA9548 I2C switch management.
+ * This function set PCA9548 switches to the proper slave channel.
+ * Only one channel among switches chip is selected during communication time.
+ *
+ * Note: If the bus does not have any PCA9548 on it, the switch_addr must be
+ * set to 0xFF, it will use normal smbus_access function.
+ */
+static int fpga_i2c_access(struct i2c_adapter *adapter, u16 addr,
+ unsigned short flags, char rw, u8 cmd,
+ int size, union i2c_smbus_data *data)
+{
+ int error = 0;
+ struct i2c_dev_data *dev_data;
+ unsigned char master_bus;
+ unsigned char switch_addr;
+ unsigned char channel;
+ uint16_t prev_port = 0;
+ unsigned char prev_switch;
+ unsigned char prev_ch;
+ int retry;
+
+ dev_data = i2c_get_adapdata(adapter);
+ master_bus = dev_data->pca9548.master_bus;
+ switch_addr = dev_data->pca9548.switch_addr;
+ channel = dev_data->pca9548.channel;
+
+ // Acquire the master resource.
+ mutex_lock(&fpga_i2c_master_locks[master_bus - 1]);
+ prev_port = fpga_i2c_lasted_access_port[master_bus - 1];
+ prev_switch = (unsigned char)(prev_port >> 8) & 0xFF;
+ prev_ch = (unsigned char)(prev_port & 0xFF);
+
+ if (switch_addr != 0xFF) {
+
+ // Check lasted access switch address on a master
+ if ( prev_switch != switch_addr && prev_switch != 0 ) {
+ // reset prev_port PCA9548 chip
+ retry = 3;
+ while(retry--){
+ error = smbus_access(adapter, (u16)(prev_switch), flags, I2C_SMBUS_WRITE, 0x00, I2C_SMBUS_BYTE, NULL);
+ if(error >= 0){
+ break;
+ }else{
+ dev_dbg(&adapter->dev,"Failed to deselect ch %d of 0x%x, CODE %d\n", prev_ch, prev_switch, error);
+ }
+ }
+ if(retry == 0)
+ goto release_unlock;
+ // set PCA9548 to current channel
+ retry = 3;
+ while(retry--){
+ error = smbus_access(adapter, switch_addr, flags, I2C_SMBUS_WRITE, 1 << channel, I2C_SMBUS_BYTE, NULL);
+ if(error >= 0){
+ break;
+ }else{
+ dev_dbg(&adapter->dev,"Failed to select ch %d of 0x%x, CODE %d\n", channel, switch_addr, error);
+ }
+ }
+ if(retry == 0)
+ goto release_unlock;
+ // update lasted port
+ fpga_i2c_lasted_access_port[master_bus - 1] = switch_addr << 8 | channel;
+
+ } else {
+ // check if channel is also changes
+ if ( prev_ch != channel || prev_switch == 0 ) {
+ // set new PCA9548 at switch_addr to current
+ retry = 3;
+ while(retry--){
+ error = smbus_access(adapter, switch_addr, flags, I2C_SMBUS_WRITE, 1 << channel, I2C_SMBUS_BYTE, NULL);
+ if(error >= 0){
+ break;
+ }else{
+ dev_dbg(&adapter->dev,"Failed to select ch %d of 0x%x, CODE %d\n", channel, switch_addr, error);
+ }
+ }
+ if(retry == 0)
+ goto release_unlock;
+ // update lasted port
+ fpga_i2c_lasted_access_port[master_bus - 1] = switch_addr << 8 | channel;
+ }
+ }
+ }
+
+ // Do SMBus communication
+ error = smbus_access(adapter, addr, flags, rw, cmd, size, data);
+ if(error < 0){
+ dev_dbg( &adapter->dev,"smbus_xfer failed (%d) @ 0x%2.2X|f 0x%4.4X|(%d)%-5s| (%d)%-10s|CMD %2.2X "
+ , error, addr, flags, rw, rw == 1 ? "READ " : "WRITE"
+ , size, size == 0 ? "QUICK" :
+ size == 1 ? "BYTE" :
+ size == 2 ? "BYTE_DATA" :
+ size == 3 ? "WORD_DATA" :
+ size == 4 ? "PROC_CALL" :
+ size == 5 ? "BLOCK_DATA" :
+ size == 8 ? "I2C_BLOCK_DATA" : "ERROR"
+ , cmd);
+ }
+
+release_unlock:
+ mutex_unlock(&fpga_i2c_master_locks[master_bus - 1]);
+ dev_dbg(&adapter->dev,"switch ch %d of 0x%x -> ch %d of 0x%x\n", prev_ch, prev_switch, channel, switch_addr);
+ return error;
+}
+
+
+
+/**
+ * A callback function show available smbus functions.
+ */
+static u32 fpga_i2c_func(struct i2c_adapter *a)
+{
+ return I2C_FUNC_SMBUS_QUICK |
+ I2C_FUNC_SMBUS_BYTE |
+ I2C_FUNC_SMBUS_BYTE_DATA |
+ I2C_FUNC_SMBUS_WORD_DATA |
+ I2C_FUNC_SMBUS_BLOCK_DATA;
+}
+
+static const struct i2c_algorithm silverstone_i2c_algorithm = {
+ .smbus_xfer = fpga_i2c_access,
+ .functionality = fpga_i2c_func,
+};
+
+/**
+ * Create virtual I2C bus adapter for switch devices
+ * @param pdev platform device pointer
+ * @param portid virtual i2c port id for switch device mapping
+ * @param bus_number_offset bus offset for virtual i2c adapter in system
+ * @return i2c adapter.
+ *
+ * When bus_number_offset is -1, created adapter with dynamic bus number.
+ * Otherwise create adapter at i2c bus = bus_number_offset + portid.
+ */
+static struct i2c_adapter * silverstone_i2c_init(struct platform_device *pdev, int portid, int bus_number_offset)
+{
+ int error;
+
+ struct i2c_adapter *new_adapter;
+ struct i2c_dev_data *new_data;
+ void __iomem *i2c_freq_base_reg;
+
+ new_adapter = kzalloc(sizeof(*new_adapter), GFP_KERNEL);
+ if (!new_adapter) {
+ printk(KERN_ALERT "Cannot alloc i2c adapter for %s", fpga_i2c_bus_dev[portid].calling_name);
+ return NULL;
+ }
+
+ new_adapter->owner = THIS_MODULE;
+ new_adapter->class = I2C_CLASS_HWMON | I2C_CLASS_SPD;
+ new_adapter->algo = &silverstone_i2c_algorithm;
+ /* If the bus offset is -1, use dynamic bus number */
+ if (bus_number_offset == -1) {
+ new_adapter->nr = -1;
+ } else {
+ new_adapter->nr = bus_number_offset + portid;
+ }
+
+ new_data = kzalloc(sizeof(*new_data), GFP_KERNEL);
+ if (!new_data) {
+ printk(KERN_ALERT "Cannot alloc i2c data for %s", fpga_i2c_bus_dev[portid].calling_name);
+ kzfree(new_adapter);
+ return NULL;
+ }
+
+ new_data->portid = portid;
+ new_data->pca9548.master_bus = fpga_i2c_bus_dev[portid].master_bus;
+ new_data->pca9548.switch_addr = fpga_i2c_bus_dev[portid].switch_addr;
+ new_data->pca9548.channel = fpga_i2c_bus_dev[portid].channel;
+ strcpy(new_data->pca9548.calling_name, fpga_i2c_bus_dev[portid].calling_name);
+
+ snprintf(new_adapter->name, sizeof(new_adapter->name),
+ "SMBus I2C Adapter PortID: %s", new_data->pca9548.calling_name);
+
+ i2c_freq_base_reg = fpga_dev.data_base_addr + I2C_MASTER_FREQ_1;
+ iowrite8(0x07, i2c_freq_base_reg + (new_data->pca9548.master_bus - 1) * 0x100); // 0x07 400kHz
+ i2c_set_adapdata(new_adapter, new_data);
+ error = i2c_add_numbered_adapter(new_adapter);
+ if (error < 0) {
+ printk(KERN_ALERT "Cannot add i2c adapter %s", new_data->pca9548.calling_name);
+ kzfree(new_adapter);
+ kzfree(new_data);
+ return NULL;
+ }
+
+ return new_adapter;
+};
+
+static void silverstone_dev_release( struct device * dev)
+{
+ return;
+}
+
+static struct platform_device silverstone_dev = {
+ .name = DRIVER_NAME,
+ .id = -1,
+ .num_resources = 0,
+ .resource = NULL,
+ .dev = {
+ .release = silverstone_dev_release,
+ }
+};
+
+/**
+ * Board info for QSFP/SFP+ eeprom.
+ * Note: Using OOM optoe as I2C eeprom driver.
+ * https://www.opencompute.org/wiki/Networking/SpecsAndDesigns#Open_Optical_Monitoring
+ */
+static struct i2c_board_info sff8436_eeprom_info[] = {
+ { I2C_BOARD_INFO("optoe1", 0x50) }, //For QSFP w/ sff8436
+ { I2C_BOARD_INFO("optoe2", 0x50) }, //For SFP+ w/ sff8472
+};
+
+static int silverstone_drv_probe(struct platform_device *pdev)
+{
+ int ret = 0;
+ int portid_count;
+ uint8_t cpld1_version, cpld2_version;
+ uint16_t prev_i2c_switch = 0;
+ struct sff_device_data *sff_data;
+
+ /* The device class need to be instantiated before this function called */
+ BUG_ON(fpgafwclass == NULL);
+
+ fpga_data = devm_kzalloc(&pdev->dev, sizeof(struct silverstone_fpga_data),
+ GFP_KERNEL);
+
+ if (!fpga_data)
+ return -ENOMEM;
+
+ // Set default read address to VERSION
+ fpga_data->fpga_read_addr = fpga_dev.data_base_addr + FPGA_VERSION;
+ fpga_data->cpld1_read_addr = 0x00;
+ fpga_data->cpld2_read_addr = 0x00;
+
+ mutex_init(&fpga_data->fpga_lock);
+ for (ret = I2C_MASTER_CH_1 ; ret <= I2C_MASTER_CH_TOTAL; ret++) {
+ mutex_init(&fpga_i2c_master_locks[ret - 1]);
+ }
+
+ fpga = kobject_create_and_add("FPGA", &pdev->dev.kobj);
+ if (!fpga) {
+ kzfree(fpga_data);
+ return -ENOMEM;
+ }
+
+ ret = sysfs_create_group(fpga, &fpga_attr_grp);
+ if (ret != 0) {
+ printk(KERN_ERR "Cannot create FPGA sysfs attributes\n");
+ kobject_put(fpga);
+ kzfree(fpga_data);
+ return ret;
+ }
+
+ cpld1 = kobject_create_and_add("CPLD1", &pdev->dev.kobj);
+ if (!cpld1) {
+ sysfs_remove_group(fpga, &fpga_attr_grp);
+ kobject_put(fpga);
+ kzfree(fpga_data);
+ return -ENOMEM;
+ }
+ ret = sysfs_create_group(cpld1, &cpld1_attr_grp);
+ if (ret != 0) {
+ printk(KERN_ERR "Cannot create CPLD1 sysfs attributes\n");
+ kobject_put(cpld1);
+ sysfs_remove_group(fpga, &fpga_attr_grp);
+ kobject_put(fpga);
+ kzfree(fpga_data);
+ return ret;
+ }
+
+ cpld2 = kobject_create_and_add("CPLD2", &pdev->dev.kobj);
+ if (!cpld2) {
+ sysfs_remove_group(cpld1, &cpld1_attr_grp);
+ kobject_put(cpld1);
+ sysfs_remove_group(fpga, &fpga_attr_grp);
+ kobject_put(fpga);
+ kzfree(fpga_data);
+ return -ENOMEM;
+ }
+ ret = sysfs_create_group(cpld2, &cpld2_attr_grp);
+ if (ret != 0) {
+ printk(KERN_ERR "Cannot create CPLD2 sysfs attributes\n");
+ kobject_put(cpld2);
+ sysfs_remove_group(cpld1, &cpld1_attr_grp);
+ kobject_put(cpld1);
+ sysfs_remove_group(fpga, &fpga_attr_grp);
+ kobject_put(fpga);
+ kzfree(fpga_data);
+ return ret;
+ }
+
+ sff_dev = device_create(fpgafwclass, NULL, MKDEV(0, 0), NULL, "sff_device");
+ if (IS_ERR(sff_dev)) {
+ printk(KERN_ERR "Failed to create sff device\n");
+ sysfs_remove_group(cpld2, &cpld2_attr_grp);
+ kobject_put(cpld2);
+ sysfs_remove_group(cpld1, &cpld1_attr_grp);
+ kobject_put(cpld1);
+ sysfs_remove_group(fpga, &fpga_attr_grp);
+ kobject_put(fpga);
+ kzfree(fpga_data);
+ return PTR_ERR(sff_dev);
+ }
+
+ ret = sysfs_create_group(&sff_dev->kobj, &sff_led_test_grp);
+ if (ret != 0) {
+ printk(KERN_ERR "Cannot create SFF attributes\n");
+ device_destroy(fpgafwclass, MKDEV(0, 0));
+ sysfs_remove_group(cpld2, &cpld2_attr_grp);
+ kobject_put(cpld2);
+ sysfs_remove_group(cpld1, &cpld1_attr_grp);
+ kobject_put(cpld1);
+ sysfs_remove_group(fpga, &fpga_attr_grp);
+ kobject_put(fpga);
+ kzfree(fpga_data);
+ return ret;
+ }
+
+ ret = sysfs_create_link(&pdev->dev.kobj, &sff_dev->kobj, "SFF");
+ if (ret != 0) {
+ sysfs_remove_group(&sff_dev->kobj, &sff_led_test_grp);
+ device_destroy(fpgafwclass, MKDEV(0, 0));
+ sysfs_remove_group(cpld2, &cpld2_attr_grp);
+ kobject_put(cpld2);
+ sysfs_remove_group(cpld1, &cpld1_attr_grp);
+ kobject_put(cpld1);
+ sysfs_remove_group(fpga, &fpga_attr_grp);
+ kobject_put(fpga);
+ kzfree(fpga_data);
+ return ret;
+ }
+
+ for (portid_count = 0 ; portid_count < VIRTUAL_I2C_PORT_LENGTH ; portid_count++) {
+ fpga_data->i2c_adapter[portid_count] = silverstone_i2c_init(pdev, portid_count, VIRTUAL_I2C_BUS_OFFSET);
+ }
+
+ /* Init SFF devices */
+ for (portid_count = 0; portid_count < SFF_PORT_TOTAL; portid_count++) {
+ struct i2c_adapter *i2c_adap = fpga_data->i2c_adapter[portid_count];
+ if (i2c_adap) {
+ fpga_data->sff_devices[portid_count] = silverstone_sff_init(portid_count);
+ sff_data = dev_get_drvdata(fpga_data->sff_devices[portid_count]);
+ BUG_ON(sff_data == NULL);
+ if ( sff_data->port_type == QSFP ) {
+ fpga_data->sff_i2c_clients[portid_count] = i2c_new_device(i2c_adap, &sff8436_eeprom_info[0]);
+ } else {
+ fpga_data->sff_i2c_clients[portid_count] = i2c_new_device(i2c_adap, &sff8436_eeprom_info[1]);
+ }
+ sff_data = NULL;
+ sysfs_create_link(&fpga_data->sff_devices[portid_count]->kobj,
+ &fpga_data->sff_i2c_clients[portid_count]->dev.kobj,
+ "i2c");
+ }
+ }
+
+#ifdef TEST_MODE
+ return 0;
+#endif
+ fpga_i2c_access(fpga_data->i2c_adapter[SW_I2C_CPLD_INDEX], CPLD1_SLAVE_ADDR, 0x00,
+ I2C_SMBUS_READ, 0x00, I2C_SMBUS_BYTE_DATA, (union i2c_smbus_data*)&cpld1_version);
+ fpga_i2c_access(fpga_data->i2c_adapter[SW_I2C_CPLD_INDEX], CPLD2_SLAVE_ADDR, 0x00,
+ I2C_SMBUS_READ, 0x00, I2C_SMBUS_BYTE_DATA, (union i2c_smbus_data*)&cpld2_version);
+
+ printk(KERN_INFO "Switch CPLD1 VERSION: %2.2x\n", cpld1_version);
+ printk(KERN_INFO "Switch CPLD2 VERSION: %2.2x\n", cpld2_version);
+
+
+ /* Init I2C buses that has PCA9548 switch device. */
+ for (portid_count = 0; portid_count < VIRTUAL_I2C_PORT_LENGTH; portid_count++) {
+
+ struct i2c_dev_data *dev_data;
+ unsigned char master_bus;
+ unsigned char switch_addr;
+
+ dev_data = i2c_get_adapdata(fpga_data->i2c_adapter[portid_count]);
+ master_bus = dev_data->pca9548.master_bus;
+ switch_addr = dev_data->pca9548.switch_addr;
+
+ if (switch_addr != 0xFF) {
+
+ if (prev_i2c_switch != ( (master_bus << 8) | switch_addr) ) {
+ // Found the bus with PCA9548, trying to clear all switch in it.
+ smbus_access(fpga_data->i2c_adapter[portid_count], switch_addr, 0x00, I2C_SMBUS_WRITE, 0x00, I2C_SMBUS_BYTE, NULL);
+ prev_i2c_switch = ( master_bus << 8 ) | switch_addr;
+ }
+ }
+ }
+ return 0;
+}
+
+static int silverstone_drv_remove(struct platform_device *pdev)
+{
+ int portid_count;
+ struct sff_device_data *rem_data;
+
+ for (portid_count = 0; portid_count < SFF_PORT_TOTAL; portid_count++) {
+ sysfs_remove_link(&fpga_data->sff_devices[portid_count]->kobj, "i2c");
+ i2c_unregister_device(fpga_data->sff_i2c_clients[portid_count]);
+ }
+
+ for (portid_count = 0 ; portid_count < VIRTUAL_I2C_PORT_LENGTH ; portid_count++) {
+ if (fpga_data->i2c_adapter[portid_count] != NULL) {
+ info(KERN_INFO "<%x>", fpga_data->i2c_adapter[portid_count]);
+ i2c_del_adapter(fpga_data->i2c_adapter[portid_count]);
+ }
+ }
+
+ for (portid_count = 0; portid_count < SFF_PORT_TOTAL; portid_count++) {
+ if (fpga_data->sff_devices[portid_count] != NULL) {
+ rem_data = dev_get_drvdata(fpga_data->sff_devices[portid_count]);
+ device_unregister(fpga_data->sff_devices[portid_count]);
+ put_device(fpga_data->sff_devices[portid_count]);
+ kfree(rem_data);
+ }
+ }
+
+ sysfs_remove_group(fpga, &fpga_attr_grp);
+ sysfs_remove_group(cpld1, &cpld1_attr_grp);
+ sysfs_remove_group(cpld2, &cpld2_attr_grp);
+ sysfs_remove_group(&sff_dev->kobj, &sff_led_test_grp);
+ kobject_put(fpga);
+ kobject_put(cpld1);
+ kobject_put(cpld2);
+ device_destroy(fpgafwclass, MKDEV(0, 0));
+ devm_kfree(&pdev->dev, fpga_data);
+ return 0;
+}
+
+#ifdef TEST_MODE
+#define FPGA_PCI_BAR_NUM 2
+#else
+#define FPGA_PCI_BAR_NUM 0
+#endif
+
+static struct platform_driver silverstone_drv = {
+ .probe = silverstone_drv_probe,
+ .remove = __exit_p(silverstone_drv_remove),
+ .driver = {
+ .name = DRIVER_NAME,
+ },
+};
+
+static const struct pci_device_id fpga_id_table[] = {
+ { PCI_VDEVICE(XILINX, FPGA_PCIE_DEVICE_ID) },
+ { PCI_VDEVICE(TEST, TEST_PCIE_DEVICE_ID) },
+ {0, }
+};
+
+MODULE_DEVICE_TABLE(pci, fpga_id_table);
+
+static int fpga_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
+{
+ int err;
+ struct device *dev = &pdev->dev;
+ uint32_t fpga_version;
+
+ if ((err = pci_enable_device(pdev))) {
+ dev_err(dev, "pci_enable_device probe error %d for device %s\n",
+ err, pci_name(pdev));
+ return err;
+ }
+
+ if ((err = pci_request_regions(pdev, FPGA_PCI_NAME)) < 0) {
+ dev_err(dev, "pci_request_regions error %d\n", err);
+ goto pci_disable;
+ }
+
+ /* bar0: data mmio region */
+ fpga_dev.data_mmio_start = pci_resource_start(pdev, FPGA_PCI_BAR_NUM);
+ fpga_dev.data_mmio_len = pci_resource_len(pdev, FPGA_PCI_BAR_NUM);
+ fpga_dev.data_base_addr = pci_iomap(pdev, FPGA_PCI_BAR_NUM, 0);
+ if (!fpga_dev.data_base_addr) {
+ dev_err(dev, "cannot iomap region of size %lu\n",
+ (unsigned long)fpga_dev.data_mmio_len);
+ goto pci_release;
+ }
+ dev_info(dev, "data_mmio iomap base = 0x%lx \n",
+ (unsigned long)fpga_dev.data_base_addr);
+ dev_info(dev, "data_mmio_start = 0x%lx data_mmio_len = %lu\n",
+ (unsigned long)fpga_dev.data_mmio_start,
+ (unsigned long)fpga_dev.data_mmio_len);
+
+ printk(KERN_INFO "FPGA PCIe driver probe OK.\n");
+ printk(KERN_INFO "FPGA ioremap registers of size %lu\n", (unsigned long)fpga_dev.data_mmio_len);
+ printk(KERN_INFO "FPGA Virtual BAR %d at %8.8lx - %8.8lx\n", FPGA_PCI_BAR_NUM,
+ (unsigned long)fpga_dev.data_base_addr,
+ (unsigned long)(fpga_dev.data_base_addr + fpga_dev.data_mmio_len));
+ printk(KERN_INFO "");
+ fpga_version = ioread32(fpga_dev.data_base_addr);
+ printk(KERN_INFO "FPGA VERSION : %8.8x\n", fpga_version);
+ fpgafw_init();
+ platform_device_register(&silverstone_dev);
+ platform_driver_register(&silverstone_drv);
+ return 0;
+
+pci_release:
+ pci_release_regions(pdev);
+pci_disable:
+ pci_disable_device(pdev);
+ return -EBUSY;
+}
+
+static void fpga_pci_remove(struct pci_dev *pdev)
+{
+ platform_driver_unregister(&silverstone_drv);
+ platform_device_unregister(&silverstone_dev);
+ fpgafw_exit();
+ pci_iounmap(pdev, fpga_dev.data_base_addr);
+ pci_release_regions(pdev);
+ pci_disable_device(pdev);
+ printk(KERN_INFO "FPGA PCIe driver remove OK.\n");
+};
+
+static struct pci_driver pci_dev_ops = {
+ .name = FPGA_PCI_NAME,
+ .probe = fpga_pci_probe,
+ .remove = fpga_pci_remove,
+ .id_table = fpga_id_table,
+};
+
+enum {
+ READREG,
+ WRITEREG
+};
+
+struct fpga_reg_data {
+ uint32_t addr;
+ uint32_t value;
+};
+
+static long fpgafw_unlocked_ioctl(struct file *file, unsigned int cmd, unsigned long arg) {
+ int ret = 0;
+ struct fpga_reg_data data;
+ mutex_lock(&fpga_data->fpga_lock);
+
+#ifdef TEST_MODE
+ static uint32_t status_reg;
+#endif
+ // Switch function to read and write.
+ switch (cmd) {
+ case READREG:
+ if (copy_from_user(&data, (void __user*)arg, sizeof(data)) != 0) {
+ mutex_unlock(&fpga_data->fpga_lock);
+ return -EFAULT;
+ }
+ data.value = ioread32(fpga_dev.data_base_addr + data.addr);
+ if (copy_to_user((void __user*)arg , &data, sizeof(data)) != 0) {
+ mutex_unlock(&fpga_data->fpga_lock);
+ return -EFAULT;
+ }
+#ifdef TEST_MODE
+ if (data.addr == 0x1210) {
+ switch (status_reg) {
+ case 0x0000 : status_reg = 0x8000;
+ break;
+
+ case 0x8080 : status_reg = 0x80C0;
+ break;
+ case 0x80C0 : status_reg = 0x80F0;
+ break;
+ case 0x80F0 : status_reg = 0x80F8;
+ break;
+
+ }
+ iowrite32(status_reg, fpga_dev.data_base_addr + 0x1210);
+ }
+#endif
+
+
+ break;
+ case WRITEREG:
+ if (copy_from_user(&data, (void __user*)arg, sizeof(data)) != 0) {
+ mutex_unlock(&fpga_data->fpga_lock);
+ return -EFAULT;
+ }
+ iowrite32(data.value, fpga_dev.data_base_addr + data.addr);
+
+#ifdef TEST_MODE
+ if (data.addr == 0x1204) {
+ status_reg = 0x8080;
+ iowrite32(status_reg, fpga_dev.data_base_addr + 0x1210);
+ }
+#endif
+
+ break;
+ default:
+ mutex_unlock(&fpga_data->fpga_lock);
+ return -EINVAL;
+ }
+ mutex_unlock(&fpga_data->fpga_lock);
+ return ret;
+}
+
+
+const struct file_operations fpgafw_fops = {
+ .owner = THIS_MODULE,
+ .unlocked_ioctl = fpgafw_unlocked_ioctl,
+};
+
+
+static int fpgafw_init(void) {
+ printk(KERN_INFO "Initializing the switchboard driver\n");
+ // Try to dynamically allocate a major number for the device -- more difficult but worth it
+ majorNumber = register_chrdev(0, DEVICE_NAME, &fpgafw_fops);
+ if (majorNumber < 0) {
+ printk(KERN_ALERT "Failed to register a major number\n");
+ return majorNumber;
+ }
+ printk(KERN_INFO "Device registered correctly with major number %d\n", majorNumber);
+
+ // Register the device class
+ fpgafwclass = class_create(THIS_MODULE, CLASS_NAME);
+ if (IS_ERR(fpgafwclass)) { // Check for error and clean up if there is
+ unregister_chrdev(majorNumber, DEVICE_NAME);
+ printk(KERN_ALERT "Failed to register device class\n");
+ return PTR_ERR(fpgafwclass);
+ }
+ printk(KERN_INFO "Device class registered correctly\n");
+
+ // Register the device driver
+ fpgafwdev = device_create(fpgafwclass, NULL, MKDEV(majorNumber, 0), NULL, DEVICE_NAME);
+ if (IS_ERR(fpgafwdev)) { // Clean up if there is an error
+ class_destroy(fpgafwclass); // Repeated code but the alternative is goto statements
+ unregister_chrdev(majorNumber, DEVICE_NAME);
+ printk(KERN_ALERT "Failed to create the FW upgrade device node\n");
+ return PTR_ERR(fpgafwdev);
+ }
+ printk(KERN_INFO "FPGA fw upgrade device node created correctly\n");
+ return 0;
+}
+
+static void fpgafw_exit(void) {
+ device_destroy(fpgafwclass, MKDEV(majorNumber, 0)); // remove the device
+ class_unregister(fpgafwclass); // unregister the device class
+ class_destroy(fpgafwclass); // remove the device class
+ unregister_chrdev(majorNumber, DEVICE_NAME); // unregister the major number
+ printk(KERN_INFO "Goodbye!\n");
+}
+
+int silverstone_init(void)
+{
+ int rc;
+ rc = pci_register_driver(&pci_dev_ops);
+ if (rc)
+ return rc;
+ return 0;
+}
+
+void silverstone_exit(void)
+{
+ pci_unregister_driver(&pci_dev_ops);
+}
+
+module_init(silverstone_init);
+module_exit(silverstone_exit);
+
+MODULE_AUTHOR("Celestica Inc.");
+MODULE_DESCRIPTION("Celestica Silverstone platform driver");
+MODULE_VERSION(MOD_VERSION);
+MODULE_LICENSE("GPL");
\ No newline at end of file
diff --git a/platform/broadcom/sonic-platform-modules-cel/silverstone/systemd/platform-modules-silverstone.service b/platform/broadcom/sonic-platform-modules-cel/silverstone/systemd/platform-modules-silverstone.service
new file mode 100644
index 000000000000..907764153a27
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-cel/silverstone/systemd/platform-modules-silverstone.service
@@ -0,0 +1,13 @@
+[Unit]
+Description=Celestica Silverstone platform modules
+After=local-fs.target
+Before=pmon.service
+
+[Service]
+Type=oneshot
+ExecStart=-/etc/init.d/platform-modules-silverstone start
+ExecStop=-/etc/init.d/platform-modules-silverstone stop
+RemainAfterExit=yes
+
+[Install]
+WantedBy=multi-user.target
\ No newline at end of file