From 7a11d8e2142ef17e6728850fc3362974e639cdab Mon Sep 17 00:00:00 2001
From: Lakesh Sharma <lakesh_sharma@dell.com>
Date: Mon, 2 Mar 2015 13:00:24 -0800
Subject: [PATCH] Dell Networking Z9100 top-of-rack switch.

This patch supports adding Z9100 platform related changes to ONIE ver 2015.02.
Z9100 would use Broadcom Tomahawk as switch ASIC. It has 32x100G ports.
CPU module is C2538 Atom (Rangeley) based.
---
 machine/dell/dell_z9100_c2538/INSTALL              | 120 ++++++++
 machine/dell/dell_z9100_c2538/demo/platform.conf   |   1 +
 .../i2ctools/i2ctools-sys-eeprom-platform.patch    | 303 +++++++++++++++++++++
 machine/dell/dell_z9100_c2538/i2ctools/series      |   1 +
 machine/dell/dell_z9100_c2538/installer.conf       |  44 +++
 machine/dell/dell_z9100_c2538/kernel/config        |   2 +
 .../kernel/platform-dell-z9100-c2538.patch         |  24 ++
 machine/dell/dell_z9100_c2538/kernel/series        |   1 +
 machine/dell/dell_z9100_c2538/machine.conf         |   1 +
 machine/dell/dell_z9100_c2538/machine.make         |  37 +++
 .../rootconf/sysroot-bin/onie-diag                 |  34 +++
 11 files changed, 568 insertions(+)
 create mode 100644 machine/dell/dell_z9100_c2538/INSTALL
 create mode 100644 machine/dell/dell_z9100_c2538/demo/platform.conf
 create mode 100644 machine/dell/dell_z9100_c2538/i2ctools/i2ctools-sys-eeprom-platform.patch
 create mode 100644 machine/dell/dell_z9100_c2538/i2ctools/series
 create mode 100644 machine/dell/dell_z9100_c2538/installer.conf
 create mode 100644 machine/dell/dell_z9100_c2538/kernel/config
 create mode 100644 machine/dell/dell_z9100_c2538/kernel/platform-dell-z9100-c2538.patch
 create mode 100644 machine/dell/dell_z9100_c2538/kernel/series
 create mode 100644 machine/dell/dell_z9100_c2538/machine.conf
 create mode 100644 machine/dell/dell_z9100_c2538/machine.make
 create mode 100755 machine/dell/dell_z9100_c2538/rootconf/sysroot-bin/onie-diag

diff --git a/machine/dell/dell_z9100_c2538/INSTALL b/machine/dell/dell_z9100_c2538/INSTALL
new file mode 100644
index 0000000..103c744
--- /dev/null
+++ b/machine/dell/dell_z9100_c2538/INSTALL
@@ -0,0 +1,120 @@
+================================================================================
+Installing ONIE on DELL Z9100 Series w/ Intel Atom Rangeley (C2538) CPU Module
+================================================================================
+
+Cross-Compiling ONIE
+====================
+
+To compile ONIE first change directories to ``build-config`` and then
+type ``"make MACHINE=dell_z9100_c2538 all"``.  For example::
+
+  $ cd build-config
+  $ make -j4 MACHINE=dell_z9100_c2538 all
+
+When complete, the ONIE binaries are located in
+``build/images``::
+
+-rw-r--r-- 1 lsharma ncore  3347584 Oct  1 11:05 dell_z9100_c2538-r0.vmlinuz
+-rw-r--r-- 1 lsharma ncore  5816696 Oct  1 11:09 dell_z9100_c2538-r0.initrd
+-rw-r--r-- 1 lsharma ncore  9186933 Oct  1 11:09 onie-updater-x86_64-dell_z9100_c2538-r0
+-rw-r--r-- 1 lsharma ncore 18874368 Oct  1 11:09 onie-recovery-x86_64-dell_z9100_c2538-r0.iso
+-rw-r--r-- 1 lsharma ncore 21449728 Oct  1 11:10 onie-recovery-x86_64-dell_z9100_c2538-r0.efi64.pxe
+
+Cross-Compiling the DEMO OS
+===========================
+
+To compile the demo OS first change directories to ``build-config``
+and then type ``"make MACHINE=dell_z9100_c2538 demo"``.  For example::
+
+  $ cd build-config
+  $ make -j4 MACHINE=dell_z9100_c2538 demo
+
+When complete, the demo OS installer is located in ``build/images``::
+
+  -rw-r--r-- 10486945 Mar 27 13:30 demo-installer-x86_64-dell_z9100_c2538-r0.bin
+
+Installing ONIE on a Blank Machine
+==================================
+
+To install ONIE on a new machine use one of the onie-recovery images.
+
+Overview
+--------
+
+An "ONIE recovery image" is used for:
+
+1. installing ONIE on a blank machine, i.e. what manufacturing would
+   use.
+
+2. recovering a destroyed ONIE system.
+
+The two types of recovery images are:
+
+. <machine>.iso       -- a hybrid ISO image.
+
+. <machine>.efi64.pxe -- a PXE image for UEFI64 machines.
+
+PXE-UEFI64 Recovery Image
+-------------------------
+
+The .efi64.pxe was made for the Z9100 whose PXE client is UEFI64
+based.  Booting regular PXE does not work on this platform.
+
+The .efi64.pxe is simply a combination of grub-efi-64 and the .iso
+recovery image, that looks like a UEFI application.  The UEFI/PXE
+client on this particular platform can then boot it.
+
+See this discussion about `UEFI/PXE Netboot
+https://wiki.ubuntu.com/UEFI/PXE-netboot-install`_.
+
+Next configure your DHCP server to serve the .efi64.pxe image as the
+bootfile.
+
+To enable IPv4 PXE boot on the Z9100 enter the BIOS configuration and:
+
+1. Enable the PXE network stack:
+
+  Advanced-->Network Stack-->Ipv4 PXE Support-->Enabled
+
+2. Change the boot order to boot PXE IPv4 first:
+
+  Boot-->Boot Option #1-->UEFI: IP4 
+
+3. Save and Exit the BIOS configuration
+
+
+ISO Recovery Image
+------------------
+
+The .iso image is used to create the .efi64.pxe image.
+
+You can also use the .iso image to create a bootable USB memory stick.
+Use ``dd`` to copy the .iso image to a USB stick and boot from that::
+
+  dd if=<machine>.iso of=/dev/sdX bs=10M
+
+For can find the correct ``/dev/sdX`` by inspecing the ``dmesg``
+output after inserting the USB stick into your work station.
+
+To enable booting from USB in the BIOS:
+
+1. Insert the USB stick (needs to be in before configuring BIOS)
+
+2. Power on the Z9100 and enter the BIOS configuration
+
+3. Set the USB device to "Hard Disk"::
+
+  Advanced-->USB Configuration-->Mass Storage Devices:
+      <Name of your device>    [Hard Disk]
+
+  <Name of your device> might be something like "SanDisk 1.26".
+
+4. Set the hard drive boot order::
+
+  Boot-->Hard Drive BBS Priorities-->Boot Option #1
+
+  In "Boot Option #1" select the device that corresponds to your
+  device.
+
+5. Save and Exit the BIOS configuration
+
diff --git a/machine/dell/dell_z9100_c2538/demo/platform.conf b/machine/dell/dell_z9100_c2538/demo/platform.conf
new file mode 100644
index 0000000..815fc54
--- /dev/null
+++ b/machine/dell/dell_z9100_c2538/demo/platform.conf
@@ -0,0 +1 @@
+# dell_z9100_c2538 specific info
diff --git a/machine/dell/dell_z9100_c2538/i2ctools/i2ctools-sys-eeprom-platform.patch b/machine/dell/dell_z9100_c2538/i2ctools/i2ctools-sys-eeprom-platform.patch
new file mode 100644
index 0000000..e4e602c
--- /dev/null
+++ b/machine/dell/dell_z9100_c2538/i2ctools/i2ctools-sys-eeprom-platform.patch
@@ -0,0 +1,303 @@
+Add platform specific stuff for the sys-eeprom
+
+diff --git a/sys_eeprom/onie_tlvinfo.c b/sys_eeprom/onie_tlvinfo.c
+index 1ef477c..e24d9ae 100644
+--- a/sys_eeprom/onie_tlvinfo.c
++++ b/sys_eeprom/onie_tlvinfo.c
+@@ -1,6 +1,9 @@
+ #include <stdio.h>
+ #include <stdlib.h>
+ #include <string.h>
++#include <unistd.h>
++#include <sys/io.h>
++#include <errno.h>
+ #include "24cXX.h"
+ #include "onie_tlvinfo.h"
+ 
+@@ -259,6 +262,7 @@ static void decode_tlv_value(tlvinfo_tlv_t * tlv, char* value)
+     case TLV_CODE_VENDOR_NAME:
+     case TLV_CODE_DIAG_VERSION:
+     case TLV_CODE_SERVICE_TAG:
++    case TLV_CODE_VENDOR_EXT:
+ 	memcpy(value, tlv->value, tlv->length);
+ 	value[tlv->length] = 0;
+ 	break;
+@@ -273,13 +277,6 @@ static void decode_tlv_value(tlvinfo_tlv_t * tlv, char* value)
+     case TLV_CODE_MAC_SIZE:
+ 	sprintf(value, "%u", (tlv->value[0] << 8) | tlv->value[1]);
+ 	break;
+-    case TLV_CODE_VENDOR_EXT:
+-	value[0] = 0;
+-	for (i = 0; (i < (TLV_DECODE_VALUE_MAX_LEN/5)) && (i < tlv->length);
+-	     i++) {
+-	    sprintf(value, "%s 0x%02X", value, tlv->value[i]);
+-	}
+-	break;
+     case TLV_CODE_CRC_32:
+ 	sprintf(value, "0x%02X%02X%02X%02X",
+ 		tlv->value[0], tlv->value[1], tlv->value[2],
+@@ -507,12 +504,32 @@ int read_eeprom(u_int8_t *eeprom)
+  */
+ int prog_eeprom(u_int8_t * eeprom)
+ {
+-    int ret = 0;
++    int ret = 0, rc;
+     tlvinfo_header_t * eeprom_hdr = (tlvinfo_header_t *) eeprom;
+     int eeprom_len;
++    unsigned char read_byte;
+ 
+     eeprom_len = sizeof(tlvinfo_header_t) + be16_to_cpu(eeprom_hdr->totallen);
++    /* Remove write-protection of system eeprom */
++    rc = ioperm(SYS_EEPROM_WP_REG_ADDR, 1, 1);
++    if(rc) {
++	printf("Error disabling EEPROM WP, errno %d \n",errno);
++	return -1;
++    }
++    read_byte = inb(SYS_EEPROM_WP_REG_ADDR);
++    read_byte = read_byte & ~SYS_EEPROM_WP_REG_MASK;
++    outb(read_byte, SYS_EEPROM_WP_REG_ADDR);
++
+     ret = write_sys_eeprom(eeprom, eeprom_len);
++
++    /* Restore write-protection of system eeprom */
++    read_byte = inb(SYS_EEPROM_WP_REG_ADDR);
++    read_byte = read_byte | SYS_EEPROM_WP_REG_MASK;
++    outb(read_byte, SYS_EEPROM_WP_REG_ADDR);
++    rc = ioperm(SYS_EEPROM_WP_REG_ADDR, 1, 0);
++    if(rc) {
++	printf("Error enabling EEPROM WP, errno %d \n",errno);
++    }
+     if (ret) {
+ 	printf("Programming failed.\n");
+ 	return -1;
+@@ -647,6 +664,7 @@ bool tlvinfo_add_tlv(u_int8_t * eeprom, int tcode, char * strval)
+     case TLV_CODE_VENDOR_NAME:
+     case TLV_CODE_DIAG_VERSION:
+     case TLV_CODE_SERVICE_TAG:
++    case TLV_CODE_VENDOR_EXT:
+ 	strncpy(data, strval, MAX_TLV_VALUE_LEN);
+ 	new_tlv_len = min(MAX_TLV_VALUE_LEN, strlen(strval));
+ 	break;
+@@ -687,7 +705,6 @@ bool tlvinfo_add_tlv(u_int8_t * eeprom, int tcode, char * strval)
+ 	printf("WARNING: The CRC TLV is set automatically and cannot be set " \
+ 	       "manually.\n");
+ 	return(FALSE);
+-    case TLV_CODE_VENDOR_EXT:
+     default:
+ 	if (set_bytes(data, strval, &new_tlv_len) != 0 ) {
+ 	    return(FALSE);
+@@ -723,6 +740,7 @@ bool tlvinfo_add_tlv(u_int8_t * eeprom, int tcode, char * strval)
+     return(TRUE);
+ }
+ 
++#define MAX_EEPROM_I2C_BUS_PATH 15
+ /*
+  * read_sys_eeprom - read the hwinfo from i2c EEPROM
+  */
+@@ -733,9 +751,16 @@ int read_sys_eeprom(void *eeprom_data, int offset, int len)
+     int i = 0;
+     u_int8_t *c;
+     int addr = SYS_EEPROM_OFFSET + offset;
++    int i2c_addr, i2c_bus;
++    char i2c_bus_path[MAX_EEPROM_I2C_BUS_PATH];
+ 
+     c = eeprom_data;
+-    if (eeprom_open(SYS_EEPROM_I2C_DEVICE, SYS_EEPROM_I2C_ADDR,
++    i2c_addr = get_i2c_addr();
++    i2c_bus = get_i2c_bus();
++    memset(i2c_bus_path, 0, MAX_EEPROM_I2C_BUS_PATH);
++    snprintf(i2c_bus_path, MAX_EEPROM_I2C_BUS_PATH, "/dev/i2c-%d", i2c_bus);
++
++    if (eeprom_open(i2c_bus_path, i2c_addr,
+ 		    EEPROM_TYPE_8BIT_ADDR, &e)) {
+ 	printf("ERROR: Cannot open I2C device\n");
+ 	return -1;
+@@ -758,15 +783,23 @@ int write_sys_eeprom(void *eeprom_data, int len)
+     int i = 0;
+     u_int8_t *c;
+     u_int16_t  addr = SYS_EEPROM_OFFSET;
++    int i2c_addr, i2c_bus;
++    char i2c_bus_path[MAX_EEPROM_I2C_BUS_PATH];
+ 
+     c = eeprom_data;
++    i2c_addr = get_i2c_addr();
++    i2c_bus = get_i2c_bus();
++    memset(i2c_bus_path, 0, MAX_EEPROM_I2C_BUS_PATH);
++    snprintf(i2c_bus_path, MAX_EEPROM_I2C_BUS_PATH, "/dev/i2c-%d", i2c_bus);
++
+     for (i = 0; i < len; i++) {
+-	if (eeprom_open(SYS_EEPROM_I2C_DEVICE, SYS_EEPROM_I2C_ADDR,
++	if (eeprom_open(i2c_bus_path, i2c_addr,
+ 			EEPROM_TYPE_8BIT_ADDR, &e)) {
+ 	    printf("ERROR: Cannot open I2C device\n");
+ 	    return -1;
+ 	}
+ 	eeprom_write_byte(&e, addr, *c);
++	usleep(5000);
+ 	eeprom_close(&e);
+ 	c++; addr++;
+     }
+diff --git a/sys_eeprom/onie_tlvinfo.h b/sys_eeprom/onie_tlvinfo.h
+index 5714f37..da8ab3a 100644
+--- a/sys_eeprom/onie_tlvinfo.h
++++ b/sys_eeprom/onie_tlvinfo.h
+@@ -170,3 +170,5 @@ bool tlvinfo_delete_tlv(u_int8_t * eeprom, u_int8_t code);
+ bool tlvinfo_add_tlv(u_int8_t * eeprom, int tcode, char * strval);
+ bool tlvinfo_decode_tlv(u_int8_t *eeprom, u_int8_t tcode, char* value);
+ void show_tlv_code_list(void);
++int get_i2c_addr(void);
++int get_i2c_bus (void);
+diff --git a/sys_eeprom/sys_eeprom.c b/sys_eeprom/sys_eeprom.c
+index a77837f..2a7ade4 100644
+--- a/sys_eeprom/sys_eeprom.c
++++ b/sys_eeprom/sys_eeprom.c
+@@ -5,6 +5,9 @@
+ #include "onie_tlvinfo.h"
+ 
+ static u_int8_t eeprom[SYS_EEPROM_SIZE];
++static int i2c_addr = SYS_EEPROM_I2C_ADDR;
++static int i2c_bus = 0;
++
+ /*
+  *  This macro defines the sys_eeprom command line command.
+  */
+@@ -12,10 +15,14 @@ cmd_usage()
+ {
+     static const char *usage =
+ 	"Display and program the system EEPROM data block.\n"
+-	"Usage: sys-eeprom [-h][-l] [-e] [-s <code>=<value>,...]\n"
++	"Usage: sys-eeprom [-h][-l] [-e] [-b bus] [-a address] [-s <code>=<value>,...]\n"
+ 	"   With no arguments display the EEPROM contents.\n"
+ 	"   -h --help\n"
+ 	"      Display usage\n"
++	"   -a --addr <address>\n"
++	"      Set the I2C bus address. \n"
++	"   -b --bus <bus>\n"
++	"      Set the I2C device bus. \n"
+ 	"   -l --list\n"
+ 	"      List the understood TLV codes and names.\n"
+ 	"   -e --erase\n"
+@@ -38,24 +45,57 @@ int main(int argc, char * const argv[])
+     int count = 0;
+     int err = 0;
+     int update = 0;
++    int skip_usage = 0;
+     char *value, *subopts, *tname;
+     int index, c, i, option_index, tcode;
+     char tlv_value[TLV_DECODE_VALUE_MAX_LEN];
++    char i2c_sw_sel_cmd[SYS_EEPROM_I2C_SW_CMD_SZ];
++    int idx;
++    bool address_present = 0;
+ 
+     const size_t tlv_code_count = sizeof(tlv_code_list) /
+ 	sizeof(tlv_code_list[0]);
+ 
+     char *tokens[tlv_code_count + 1];
+-    const char *short_options = "hels:g:";
++    const char *short_options = "hels:g:a:b:";
+     const struct option long_options[] = {
+ 	{"help",    no_argument,          0,    'h'},
+ 	{"list",    no_argument,          0,    'l'},
+ 	{"erase",   no_argument,          0,    'e'},
+ 	{"set",     required_argument,    0,    's'},
+ 	{"get",     required_argument,    0,    'g'},
++	{"addr",    required_argument,    0,    'a'},
++	{"bus",     required_argument,    0,    'b'},
+ 	{0,         0,                    0,      0},
+     };
+ 
++    /*
++     * Parse the arguments to check if user has provided i2c address,
++     * if so, user wants to access other eeprom on board, i.e. not
++     * the ID eeprom. So we would skip the mux setting needed for
++     * ID eeprom access.
++     */
++    for(idx = 0; idx < argc; ++idx) {
++	if((strcmp(argv[idx],"-a") == 0) || (strcmp(argv[idx],"--a") == 0)
++	    || (strcmp(argv[idx],"-addr") == 0) || (strcmp(argv[idx],"--addr") == 0)) {
++	    address_present = 1;
++	}
++    }
++
++    /*
++     * If user has not provided the i2c address,
++     * Set the I2C switch config so that ID-eeprom channel is selected.
++     */
++    if(address_present == 0) {
++	memset(i2c_sw_sel_cmd, 0, SYS_EEPROM_I2C_SW_CMD_SZ);
++	snprintf(i2c_sw_sel_cmd, SYS_EEPROM_I2C_SW_CMD_SZ, "i2cset -y %d 0x%x %d %d ",
++	    SYS_EEPROM_I2C_SW_I2C_BUS, SYS_EEPROM_I2C_SW_I2C_ADDR,
++	    SYS_EEPROM_I2C_SW_CH_SEL_REG, SYS_EEPROM_I2C_SW_CH_SEL_VAL);
++
++	    system(i2c_sw_sel_cmd);
++    }
++
++
+     for (i = 0; i < tlv_code_count; i++) {
+ 	    tokens[i] = (char *) malloc(6);
+ 	    sprintf(tokens[i], "0x%x", tlv_code_list[i].m_code);
+@@ -136,6 +176,17 @@ int main(int argc, char * const argv[])
+             goto syseeprom_err;
+ 	break;
+ 
++	case 'a':
++            i2c_addr = strtoul(optarg, NULL, 0);
++            count = 0;
++            skip_usage = 1;
++	break;
++
++	case 'b':
++            i2c_bus = strtoul(optarg, NULL, 0);
++            count = 0;
++            skip_usage = 1;
++	break;
+ 	default:
+ 	    cmd_usage();
+             err = 1;
+@@ -143,7 +194,7 @@ int main(int argc, char * const argv[])
+ 	}
+     }
+     if (!count) {
+-	if (argc > 1) {
++	if ((argc > 1) && (skip_usage == 0)) {
+ 	    cmd_usage();
+             err = 1;
+ 	} else {
+@@ -167,3 +218,13 @@ syseeprom_err:
+     }
+     return  (err == 0) ? 0 : 1;
+ }
++
++int get_i2c_addr (void)
++{
++    return i2c_addr;
++}
++
++int get_i2c_bus (void)
++{
++    return i2c_bus;
++}
+diff --git a/sys_eeprom/sys_eeprom_platform.h b/sys_eeprom/sys_eeprom_platform.h
+index 529f774..aaa56be 100644
+--- a/sys_eeprom/sys_eeprom_platform.h
++++ b/sys_eeprom/sys_eeprom_platform.h
+@@ -1,4 +1,19 @@
+ #ifndef __SYS_EEPROM_PLATFORM_H_
+ #define __SYS_EEPROM_PLATFORM_H_
+ 
++#define SYS_EEPROM_MAX_SIZE     0x100
++#define SYS_EEPROM_OFFSET       0
++#define SYS_EEPROM_SIZE         SYS_EEPROM_MAX_SIZE
++#define SYS_EEPROM_I2C_DEVICE  "/dev/i2c-0"
++#define SYS_EEPROM_I2C_ADDR     0x53
++
++#define SYS_EEPROM_I2C_SW_I2C_BUS     0
++#define SYS_EEPROM_I2C_SW_I2C_ADDR    0x70
++#define SYS_EEPROM_I2C_SW_CH_SEL_REG  0
++#define SYS_EEPROM_I2C_SW_CH_SEL_VAL  8
++#define SYS_EEPROM_I2C_SW_CMD_SZ      50
++
++#define SYS_EEPROM_WP_REG_ADDR        0x220
++#define SYS_EEPROM_WP_REG_MASK        0x1
++
+ #endif /* __SYS_EEPROM_PLATFORM_H_ */
diff --git a/machine/dell/dell_z9100_c2538/i2ctools/series b/machine/dell/dell_z9100_c2538/i2ctools/series
new file mode 100644
index 0000000..bbc4fde
--- /dev/null
+++ b/machine/dell/dell_z9100_c2538/i2ctools/series
@@ -0,0 +1 @@
+i2ctools-sys-eeprom-platform.patch
diff --git a/machine/dell/dell_z9100_c2538/installer.conf b/machine/dell/dell_z9100_c2538/installer.conf
new file mode 100644
index 0000000..a6d2353
--- /dev/null
+++ b/machine/dell/dell_z9100_c2538/installer.conf
@@ -0,0 +1,44 @@
+# DELL Z9100 Series
+# CPU Module: Intel Rangeley (C2538)
+
+description="DELL Z9100 Series w/ Intel Atom Rangeley (C2538) CPU Module"
+
+# Default ONIE block device
+install_device_platform()
+{
+    # The problem we are trying to solve is:
+    #
+    #    How to determine the block device upon which to install ONIE?
+    #
+    # The question is complicated when multiple block devices are
+    # present, i.e. perhaps the system has two hard drives installed
+    # or maybe a USB memory stick is currently installed.  For example
+    # the mSATA device usually shows up as /dev/sda under Linux, but
+    # maybe with a USB drive connected the internal disk now shows as
+    # /dev/sdb.
+    #
+    # The approach here is to look for the block device that has a
+    # very specific, bus centric path in the system.  The internal
+    # CFast device can only show up with this address.
+
+    # Find the internal CFast device -- this path is specific to this platform
+    dell_z9100_c2538_disk="/sys/devices/pci0000:00/0000:00:18.0/host4/target4:0:0/4:0:0:0"
+    for d in /sys/block/* ; do
+        if [ -e "$d/device" ] ; then
+            path="$(realpath $d/device)"
+            if [ "$path" = "$dell_z9100_c2538_disk" ] ; then
+                device="/dev/$(basename $d)"
+                echo $device
+                return 0
+            fi
+        fi
+    done
+    echo "WARNING: ${onie_platform}: Unable to find internal ONIE install device"
+    echo "WARNING: expecting $dell_z9100_c2538_disk"
+    return 1
+}
+
+# Local Variables:
+# mode: shell-script
+# eval: (sh-set-shell "/bin/sh" t nil)
+# End:
diff --git a/machine/dell/dell_z9100_c2538/kernel/config b/machine/dell/dell_z9100_c2538/kernel/config
new file mode 100644
index 0000000..c9590fc
--- /dev/null
+++ b/machine/dell/dell_z9100_c2538/kernel/config
@@ -0,0 +1,2 @@
+CONFIG_DELL_Z9100_C2538=y
+CONFIG_STRICT_DEVMEM=y
diff --git a/machine/dell/dell_z9100_c2538/kernel/platform-dell-z9100-c2538.patch b/machine/dell/dell_z9100_c2538/kernel/platform-dell-z9100-c2538.patch
new file mode 100644
index 0000000..581b4f6
--- /dev/null
+++ b/machine/dell/dell_z9100_c2538/kernel/platform-dell-z9100-c2538.patch
@@ -0,0 +1,24 @@
+Platform support for the DELL Z9100 with the Rangeley C2538 CPU module
+
+diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig
+index 7f43cf8..b1acf68 100644
+--- a/drivers/platform/x86/Kconfig
++++ b/drivers/platform/x86/Kconfig
+@@ -779,4 +779,17 @@ config SAMSUNG_Q10
+ 	  This driver provides support for backlight control on Samsung Q10
+ 	  and related laptops, including Dell Latitude X200.
+ 
++config DELL_Z9100_C2538
++	tristate "DELL Z9100_C2538 Platform Support"
++	depends on X86 && PCI
++	select I2C_ISCH
++	select I2C_ISMT
++	select GPIO_SCH
++	select MFD_CORE
++	select LPC_SCH
++	---help---
++	 Enable support for DELL Z9100 switching platform.  This
++	 platform has a C2538 Atom (Rangeley) CPU module, a Broadcom
++	 Tomahawk switch ASIC. It has 32x100G ports.
++
+ endif # X86_PLATFORM_DEVICES
diff --git a/machine/dell/dell_z9100_c2538/kernel/series b/machine/dell/dell_z9100_c2538/kernel/series
new file mode 100644
index 0000000..cb3f5bb
--- /dev/null
+++ b/machine/dell/dell_z9100_c2538/kernel/series
@@ -0,0 +1 @@
+platform-dell-z9100-c2538.patch
diff --git a/machine/dell/dell_z9100_c2538/machine.conf b/machine/dell/dell_z9100_c2538/machine.conf
new file mode 100644
index 0000000..ab7b5ea
--- /dev/null
+++ b/machine/dell/dell_z9100_c2538/machine.conf
@@ -0,0 +1 @@
+GRUB_CMDLINE_LINUX="i2c-ismt.bus_speed=100 console=tty0 console=ttyS1,115200n8"=
diff --git a/machine/dell/dell_z9100_c2538/machine.make b/machine/dell/dell_z9100_c2538/machine.make
new file mode 100644
index 0000000..bfaabfd
--- /dev/null
+++ b/machine/dell/dell_z9100_c2538/machine.make
@@ -0,0 +1,37 @@
+# DELL Z9100 Series
+# CPU Module: Intel Atom Rangeley (C2538)
+
+ONIE_ARCH ?= x86_64
+
+VENDOR_REV ?= 0
+
+# Translate hardware revision to ONIE hardware revision
+ifeq ($(VENDOR_REV),0)
+  MACHINE_REV = 0
+else
+  $(warning Unknown VENDOR_REV '$(VENDOR_REV)' for MACHINE '$(MACHINE)')
+  $(error Unknown VENDOR_REV)
+endif
+
+# Vendor ID -- IANA Private Enterprise Number:
+# http://www.iana.org/assignments/enterprise-numbers
+# DELL IANA number
+VENDOR_ID = 674
+
+# This platform requires the PXE_EFI64 installer
+PXE_EFI64_ENABLE = yes
+
+CONSOLE_SPEED = 115200
+CONSOLE_DEV = 1
+CONSOLE_FLAG = 0
+
+EXTRA_CMDLINE_LINUX = i2c-ismt.bus_speed=100
+
+GRUB_CMDLINE_LINUX = "console=tty0 console=ttyS1,115200n8"
+GRUB_SERIAL_COMMAND = "serial --port=0x2f8 --speed=115200 --word=8 --parity=no --stop=1"
+
+#-------------------------------------------------------------------------------
+#
+# Local Variables:
+# mode: makefile-gmake
+# End:
diff --git a/machine/dell/dell_z9100_c2538/rootconf/sysroot-bin/onie-diag b/machine/dell/dell_z9100_c2538/rootconf/sysroot-bin/onie-diag
new file mode 100755
index 0000000..07567ab
--- /dev/null
+++ b/machine/dell/dell_z9100_c2538/rootconf/sysroot-bin/onie-diag
@@ -0,0 +1,34 @@
+#!/bin/sh
+
+##
+## 
+## Script to launch platform specific diag.
+## 
+##
+
+
+this_script=$(basename $(realpath $0))
+lib_dir="$(dirname $(realpath $0))/../lib/onie"
+
+. $lib_dir/onie-blkdev-common
+
+echo "mount point is $onie_boot_mnt"
+diag_file="$onie_boot_mnt/diag.sh"
+echo " file path is $diag_file "
+
+#to recover diag.sh / avoid loosing it after onie-update 
+diag_mount=$(blkid | grep -- '-DIAG"' | awk '{print $1}' | sed -e 's/:.*$//')
+if [[ ! -z "$diag_mount" ]]; then
+mount $diag_mount /tmp
+cp /tmp/diag/diag.sh $onie_boot_mnt
+umount /tmp 
+fi
+
+
+if [ -x $diag_file ] ; then
+echo "Platform specific diag found launching....."
+. $diag_file
+else
+echo "Platform specific diag not found..."
+fi
+exit 0
-- 
1.9.1

