diff --git a/machine/netberg/netberg_aurora_610/INSTALL b/machine/netberg/netberg_aurora_610/INSTALL new file mode 100644 index 000000000..c69a2c887 --- /dev/null +++ b/machine/netberg/netberg_aurora_610/INSTALL @@ -0,0 +1,106 @@ +====================================== +Installing ONIE on Netberg Aurora 610 +====================================== + +Cross-Compiling ONIE +==================== + +Change directories to ``build-config`` to compile ONIE. + +To compile ONIE first change directories to ``build-config`` and then +type ``"make MACHINEROOT=../machine/netberg MACHINE=netberg_aurora_610 all"``. For example:: + + $ cd build-config + $ make MACHINEROOT=../machine/netberg MACHINE=netberg_aurora_610 all + +When complete, the ONIE binaries are located in +``build/images``:: + +-rw-rw-r-- 1 asapronov asapronov 9275148 jan 27 19:08 netberg_aurora_610-r0.initrd +-rw-rw-r-- 1 asapronov asapronov 3928144 jan 27 19:05 netberg_aurora_610-r0.vmlinuz +-rw-rw-r-- 1 asapronov asapronov 30146560 jan 27 19:09 onie-recovery-x86_64-netberg_aurora_610-r0.iso +-rw-rw-r-- 1 asapronov asapronov 13150071 jan 27 19:08 onie-updater-x86_64-netberg_aurora_610-r0 + + +netberg_aurora_610-r0.vmlinuz -- This is the ONIE kernel image + +netberg_aurora_610-r0.initrd -- This is the ONIE initramfs (filesystem) + +onie-updater-x86_64-netberg_aurora_610-r0 -- This is the ONIE self-update +image. This image is a self-extracting archive used for installing +ONIE. + +onie-recovery-x86_64-netberg_aurora_610-r0.iso -- This is a recovery ISO image +that can be install as a CDROM image. + +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 recovery image is: + +. .iso -- a hybrid ISO image. + +ISO Recovery Image +------------------ + +The .iso image is used to create the usb recovery disk. + +You can 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=.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 BIOS: + +1. Insert the USB stick + +2. Power on the Netberg Aurora 610 Switch + +3. Press ECS to get into the BIOS and set USB as boot device + +4. Wait for scanning USB disk grub.cfg + + GNU GRUB version 2.02 + + +----------------------------------------------------------------------------+ + |*ONIE: Rescue | + | ONIE: Embed ONIE | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + +----------------------------------------------------------------------------+ + + Use the ^ and v keys to select which entry is highlighted. + Press enter to boot the selected OS, `e' to edit the commands + before booting or `c' for a command-line. + +5. Choose ``ONIE: Embed ONIE``, then ONIE will be ready after reboot. + +6. ``ONIE: Rescue`` for ONIE rescue mode on USB disk shall also provide + an debugging environment. + + + + diff --git a/machine/netberg/netberg_aurora_610/busybox/conf/config b/machine/netberg/netberg_aurora_610/busybox/conf/config new file mode 100644 index 000000000..1bfcae709 Binary files /dev/null and b/machine/netberg/netberg_aurora_610/busybox/conf/config differ diff --git a/machine/netberg/netberg_aurora_610/demo/platform.conf b/machine/netberg/netberg_aurora_610/demo/platform.conf new file mode 100644 index 000000000..e69de29bb diff --git a/machine/netberg/netberg_aurora_610/installer.conf b/machine/netberg/netberg_aurora_610/installer.conf new file mode 100644 index 000000000..8fffd23eb --- /dev/null +++ b/machine/netberg/netberg_aurora_610/installer.conf @@ -0,0 +1,73 @@ +# Netberg Aurora 610 +# CPU Module: Intel Broadwell-DE + +description="Netberg Aurora 610" + +# Default ONIE block device +install_device_platform() +{ + # find ata device on the systme, return the 1st one. + + ## + # find the usb dom first + ## + for _device in /sys/block/*/device; do + _device=$(echo $_device | sed -e 's/\/device//') + + # work for kernel 3.2.35 (usb dom, which is connected to usb port 0, i.e, 1-1.1) + if echo $(readlink -f $_device)|egrep -q "pci0000:00\/0000:00:16.0\/usb1\/1-1\/1-1.1\/"; then + _disk=`echo $_device | cut -f4 -d/` + echo /dev/$_disk + return 0 + fi + done + + ## + # no usb dom found, try to find sata dom + ## + for _device in /sys/block/*/device; do + _device=$(echo $_device | sed -e 's/\/device//') + + # work for kernel 3.2.35 + if echo $(readlink -f $_device)|egrep -q "pci0000:00\/0000:00:18.0"; then + _disk=`echo $_device | cut -f4 -d/` + echo /dev/$_disk + return 0 + fi + # work for kernel 3.14.16 + if echo $(readlink -f $_device)|egrep -q "ata"; then + _disk=`echo $_device | cut -f4 -d/` + echo /dev/$_disk + return 0 + fi + done + + # nothing found, just return /dev/sda + echo /dev/sda + return 1 +} + +post_install() +{ + echo "Post installation hook" + + # + # Add platform specific hooks here. + # + # For example, set BIOS to directly + # boot from hard drive as onie is + # already installed. + # + + $onie_root_dir/tools/bin/onie-boot-mode -q -o rescue + + return 0 +} + +# Set install callback hooks +post_install_hook=post_install + +# Local Variables: +# mode: shell-script +# eval: (sh-set-shell "/bin/sh" t nil) +# End: diff --git a/machine/netberg/netberg_aurora_610/kernel/0001-Netberg-Aurora-610-associate-platform-drive.patch b/machine/netberg/netberg_aurora_610/kernel/0001-Netberg-Aurora-610-associate-platform-drive.patch new file mode 100644 index 000000000..5e05b46f6 --- /dev/null +++ b/machine/netberg/netberg_aurora_610/kernel/0001-Netberg-Aurora-610-associate-platform-drive.patch @@ -0,0 +1,2009 @@ +From 78620d6992bdc2a8db3733460c04e74e8a3d9057 Mon Sep 17 00:00:00 2001 +From: Andrew Sapronov +Date: Fri, 31 Jan 2020 15:52:55 +0300 +Subject: [PATCH] Netberg Aurora 610 associate platform drive + +--- + drivers/platform/x86/Kconfig | 6 + + drivers/platform/x86/Makefile | 1 + + drivers/platform/x86/nb_cpld.c | 550 +++++++++++++++++ + drivers/platform/x86/nb_platform.c | 244 ++++++++ + drivers/platform/x86/nb_psoc.c | 1154 ++++++++++++++++++++++++++++++++++++ + 5 files changed, 1955 insertions(+) + create mode 100644 drivers/platform/x86/nb_cpld.c + create mode 100644 drivers/platform/x86/nb_platform.c + create mode 100644 drivers/platform/x86/nb_psoc.c + +diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig +index b8a21d7..95786a0 100644 +--- a/drivers/platform/x86/Kconfig ++++ b/drivers/platform/x86/Kconfig +@@ -1027,4 +1027,10 @@ config INTEL_TELEMETRY + used to get various SoC events and parameters + directly via debugfs files. Various tools may use + this interface for SoC state monitoring. ++ ++config NETBERG_AURORA_610 ++ tristate "Netberg Aurora 610" ++ depends on X86 ++ ---help--- ++ This driver provides support for i2c topology on Aurora 610. + endif # X86_PLATFORM_DEVICES +diff --git a/drivers/platform/x86/Makefile b/drivers/platform/x86/Makefile +index 2efa86d..a229d15 100644 +--- a/drivers/platform/x86/Makefile ++++ b/drivers/platform/x86/Makefile +@@ -71,3 +71,4 @@ obj-$(CONFIG_INTEL_TELEMETRY) += intel_telemetry_core.o \ + intel_telemetry_pltdrv.o \ + intel_telemetry_debugfs.o + obj-$(CONFIG_INTEL_PMC_CORE) += intel_pmc_core.o ++obj-$(CONFIG_NETBERG_AURORA_610) += nb_platform.o nb_psoc.o nb_cpld.o +diff --git a/drivers/platform/x86/nb_cpld.c b/drivers/platform/x86/nb_cpld.c +new file mode 100644 +index 0000000..050d6f5 +--- /dev/null ++++ b/drivers/platform/x86/nb_cpld.c +@@ -0,0 +1,550 @@ ++/* ++ * 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 "I2CHostCommunication.h" ++ ++#define USE_SMBUS 1 ++ ++/* definition */ ++#define CPLD_INFO_OFFSET 0x00 ++#define CPLD_PSU_OFFSET 0x08 ++#define CPLD_LED_OFFSET 0x0E ++#define CPLD_NEWLED_OFFSET 0x14 ++#define CPLD_LED_STATU_OFFSET 0x0D ++#define CPLD_CTL_OFFSET 0x0C ++#define CPLD_BIOSCS_OFFSET 0x04 ++ ++ ++/* Each client has this additional data */ ++struct cpld_data { ++ struct device *hwmon_dev; ++ struct mutex update_lock; ++}; ++ ++/*-----------------------------------------------------------------------*/ ++ ++static ssize_t cpld_i2c_read (struct i2c_client *client, u8 * buf, u8 offset, ++ size_t count) ++{ ++#if USE_SMBUS ++ int i; ++ ++ for (i = 0; i < count; i++) ++ { ++ buf[i] = i2c_smbus_read_byte_data (client, offset + i); ++ } ++ return count; ++#else ++ struct i2c_msg msg[2]; ++ char msgbuf[2]; ++ int status; ++ ++ memset (msg, 0, sizeof (msg)); ++ ++ msgbuf[0] = offset; ++ ++ msg[0].addr = client->addr; ++ msg[0].buf = msgbuf; ++ msg[0].len = 1; ++ ++ msg[1].addr = client->addr; ++ msg[1].flags = I2C_M_RD; ++ msg[1].buf = buf; ++ msg[1].len = count; ++ ++ status = i2c_transfer (client->adapter, msg, 2); ++ ++ if (status == 2) ++ status = count; ++ ++ return status; ++#endif ++} ++ ++static ssize_t cpld_i2c_write (struct i2c_client *client, char *buf, ++ unsigned offset, size_t count) ++{ ++#if USE_SMBUS ++ int i; ++ ++ for (i = 0; i < count; i++) ++ { ++ i2c_smbus_write_byte_data (client, offset + i, buf[i]); ++ } ++ return count; ++#else ++ struct i2c_msg msg; ++ int status; ++ u8 writebuf[64]; ++ ++ int i = 0; ++ ++ msg.addr = client->addr; ++ msg.flags = 0; ++ ++ /* msg.buf is u8 and casts will mask the values */ ++ msg.buf = writebuf; ++ ++ msg.buf[i++] = offset; ++ memcpy (&msg.buf[i], buf, count); ++ msg.len = i + count; ++ ++ status = i2c_transfer (client->adapter, &msg, 1); ++ if (status == 1) ++ status = count; ++ ++ return status; ++#endif ++} ++ ++/*-----------------------------------------------------------------------*/ ++ ++/* sysfs attributes for hwmon */ ++ ++static ssize_t show_info (struct device *dev, struct device_attribute *da, ++ char *buf) ++{ ++ u32 status; ++ //struct sensor_device_attribute *attr = to_sensor_dev_attr(da); ++ struct i2c_client *client = to_i2c_client (dev); ++ struct cpld_data *data = i2c_get_clientdata (client); ++ u8 b[4]; ++ ++ memset (b, 0, 4); ++ ++ mutex_lock (&data->update_lock); ++ status = cpld_i2c_read (client, b, CPLD_INFO_OFFSET, 4); ++ mutex_unlock (&data->update_lock); ++ ++ if (status != 4) ++ return sprintf (buf, "read cpld info fail\n"); ++ ++ status = sprintf (buf, "The CPLD release date is %02d/%02d/%d.\n", b[2] & 0xf, (b[3] & 0x1f), 2014 + (b[2] >> 4)); /* mm/dd/yyyy */ ++ status = ++ sprintf (buf, "%sThe PCB version is %X%X\n", buf, b[0] >> 4, ++ b[0] & 0xf); ++ status = ++ sprintf (buf, "%sThe CPLD version is %d.%d\n", buf, b[1] >> 4, ++ b[1] & 0xf); ++ ++ return strlen (buf); ++} ++ ++ ++static ssize_t show_ctl (struct device *dev, struct device_attribute *da, ++ char *buf) ++{ ++ u32 status; ++ //struct sensor_device_attribute *attr = to_sensor_dev_attr(da); ++ struct i2c_client *client = to_i2c_client (dev); ++ struct cpld_data *data = i2c_get_clientdata (client); ++ u8 b[1]; ++ ++ mutex_lock (&data->update_lock); ++ ++ status = cpld_i2c_read (client, b, CPLD_CTL_OFFSET, 1); ++ ++ mutex_unlock (&data->update_lock); ++ ++ if (status != 1) ++ return sprintf (buf, "read cpld ctl fail\n"); ++ ++ ++ status = sprintf (buf, "0x%X\n", b[0]); ++ ++ return strlen (buf); ++} ++ ++static ssize_t set_ctl (struct device *dev, ++ struct device_attribute *devattr, ++ const char *buf, size_t count) ++{ ++ //struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); ++ struct i2c_client *client = to_i2c_client (dev); ++ struct cpld_data *data = i2c_get_clientdata (client); ++ u8 byte; ++ ++ u8 temp = simple_strtol (buf, NULL, 10); ++ ++ mutex_lock (&data->update_lock); ++ cpld_i2c_read (client, &byte, CPLD_CTL_OFFSET, 1); ++ if (temp) ++ byte |= (1 << 0); ++ else ++ byte &= ~(1 << 0); ++ cpld_i2c_write (client, &byte, CPLD_CTL_OFFSET, 1); ++ mutex_unlock (&data->update_lock); ++ ++ return count; ++} ++ ++static ssize_t show_bios_cs (struct device *dev, struct device_attribute *da, ++ char *buf) ++{ ++ u32 status; ++ //struct sensor_device_attribute *attr = to_sensor_dev_attr(da); ++ struct i2c_client *client = to_i2c_client (dev); ++ struct cpld_data *data = i2c_get_clientdata (client); ++ u8 b[1]; ++ ++ mutex_lock (&data->update_lock); ++ ++ status = cpld_i2c_read (client, b, CPLD_BIOSCS_OFFSET, 1); ++ ++ mutex_unlock (&data->update_lock); ++ ++ if (status != 1) ++ return sprintf (buf, "read cpld BIOS_CS fail\n"); ++ ++ ++ status = sprintf (buf, "0x%X\n", b[0] & 0x01); ++ ++ return strlen (buf); ++} ++ ++static ssize_t set_bios_cs (struct device *dev, ++ struct device_attribute *devattr, ++ const char *buf, size_t count) ++{ ++ //struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); ++ struct i2c_client *client = to_i2c_client (dev); ++ struct cpld_data *data = i2c_get_clientdata (client); ++ u8 byte; ++ ++ u8 temp = simple_strtol (buf, NULL, 10); ++ ++ mutex_lock (&data->update_lock); ++ cpld_i2c_read (client, &byte, CPLD_BIOSCS_OFFSET, 1); ++ if (temp) ++ byte |= 0x01; ++ else ++ byte &= ~(0x01); ++ cpld_i2c_write (client, &byte, CPLD_BIOSCS_OFFSET, 1); ++ mutex_unlock (&data->update_lock); ++ ++ return count; ++} ++ ++ ++static char *led_str[] = { ++ "OFF", //000 ++ "0.5 Hz", //001 ++ "1 Hz", //010 ++ "2 Hz", //011 ++ "4 Hz", //100 ++ "NA", //101 ++ "NA", //110 ++ "ON", //111 ++}; ++ ++static ssize_t show_led (struct device *dev, struct device_attribute *da, ++ char *buf) ++{ ++ u32 status; ++ struct sensor_device_attribute *attr = to_sensor_dev_attr (da); ++ struct i2c_client *client = to_i2c_client (dev); ++ struct cpld_data *data = i2c_get_clientdata (client); ++ u8 byte; ++ int shift = (attr->index == 0) ? 3 : 0; ++ ++ mutex_lock (&data->update_lock); ++ status = cpld_i2c_read (client, &byte, CPLD_LED_OFFSET, 1); ++ mutex_unlock (&data->update_lock); ++ ++ if (status != 1) ++ return sprintf (buf, "read cpld offset 0x%x\n", CPLD_LED_OFFSET); ++ ++ byte = (byte >> shift) & 0x7; ++ ++ status = sprintf (buf, "%d: %s\n", byte, led_str[byte]); ++ ++ return strlen (buf); ++} ++ ++static ssize_t set_led (struct device *dev, ++ struct device_attribute *devattr, ++ const char *buf, size_t count) ++{ ++ struct sensor_device_attribute *attr = to_sensor_dev_attr (devattr); ++ struct i2c_client *client = to_i2c_client (dev); ++ struct cpld_data *data = i2c_get_clientdata (client); ++ ++ u8 temp = simple_strtol (buf, NULL, 16); ++ u8 byte; ++ int shift = (attr->index == 0) ? 3 : 0; ++ ++ temp &= 0x7; ++ //validate temp value: 0,1,2,3,7, TBD ++ ++ mutex_lock (&data->update_lock); ++ cpld_i2c_read (client, &byte, CPLD_LED_OFFSET, 1); ++ byte &= ~(0x7 << shift); ++ byte |= (temp << shift); ++ cpld_i2c_write (client, &byte, CPLD_LED_OFFSET, 1); ++ mutex_unlock (&data->update_lock); ++ ++ return count; ++} ++ ++static char *servicefanpsuled_str[] = { ++ "OFF", //00 ++ "ON", //01 ++ "1Hz", //10 ++ "4hz", //11 ++}; ++ ++static ssize_t show_servicefanpsuled (struct device *dev, ++ struct device_attribute *da, char *buf) ++{ ++ struct sensor_device_attribute *attr = to_sensor_dev_attr (da); ++ struct i2c_client *client = to_i2c_client (dev); ++ struct cpld_data *data = i2c_get_clientdata (client); ++ u8 byte; ++ int shift = attr->index; ++ ++ mutex_lock (&data->update_lock); ++ cpld_i2c_read (client, &byte, CPLD_NEWLED_OFFSET + shift, 1); ++ mutex_unlock (&data->update_lock); ++ ++ if (shift == 0) ++ return sprintf (buf, "0x%02X:Blue %s\n", byte, ++ servicefanpsuled_str[byte & 0x3]); ++ else ++ return sprintf (buf, "0x%02X:Green %s Red %s\n", byte, ++ servicefanpsuled_str[byte & 0x03], ++ servicefanpsuled_str[(byte >> 4) & 0x03]); ++ ++ return strlen (buf); ++} ++ ++static ssize_t set_servicefanpsuled (struct device *dev, ++ struct device_attribute *devattr, ++ const char *buf, size_t count) ++{ ++ struct sensor_device_attribute *attr = to_sensor_dev_attr (devattr); ++ struct i2c_client *client = to_i2c_client (dev); ++ struct cpld_data *data = i2c_get_clientdata (client); ++ ++ u8 temp = simple_strtol (buf, NULL, 16) & 0x33; ++ int shift = attr->index; ++ ++ mutex_lock (&data->update_lock); ++ cpld_i2c_write (client, &temp, CPLD_NEWLED_OFFSET + shift, 1); ++ mutex_unlock (&data->update_lock); ++ return count; ++} ++ ++/* ++CPLD report the PSU0 status ++000 = PSU normal operation ++100 = PSU fault ++010 = PSU unpowered ++111 = PSU not installed ++ ++7 6 | 5 4 3 | 2 1 0 ++---------------------- ++ | psu0 | psu1 ++*/ ++static char *psu_str[] = { ++ "normal", //000 ++ "NA", //001 ++ "unpowered", //010 ++ "NA", //011 ++ "fault", //100 ++ "NA", //101 ++ "NA", //110 ++ "not installed", //111 ++}; ++ ++static ssize_t show_psu (struct device *dev, struct device_attribute *da, ++ char *buf) ++{ ++ u32 status; ++ struct sensor_device_attribute *attr = to_sensor_dev_attr (da); ++ struct i2c_client *client = to_i2c_client (dev); ++ struct cpld_data *data = i2c_get_clientdata (client); ++ u8 byte; ++ int shift = (attr->index == 1) ? 0 : 3; ++ ++ mutex_lock (&data->update_lock); ++ status = cpld_i2c_read (client, &byte, CPLD_PSU_OFFSET, 1); ++ mutex_unlock (&data->update_lock); ++ ++ byte = (byte >> shift) & 0x7; ++ ++ status = sprintf (buf, "%d : %s\n", byte, psu_str[byte]); ++ ++ return strlen (buf); ++} ++ ++ ++static SENSOR_DEVICE_ATTR (info, S_IRUGO, show_info, 0, 0); ++static SENSOR_DEVICE_ATTR (ctl, S_IWUSR | S_IRUGO, show_ctl, set_ctl, 0); ++ ++static SENSOR_DEVICE_ATTR (grn_led, S_IWUSR | S_IRUGO, show_led, set_led, 0); ++static SENSOR_DEVICE_ATTR (red_led, S_IWUSR | S_IRUGO, show_led, set_led, 1); ++static SENSOR_DEVICE_ATTR (service_led, S_IWUSR | S_IRUGO, ++ show_servicefanpsuled, set_servicefanpsuled, 0); ++static SENSOR_DEVICE_ATTR (fan_led, S_IWUSR | S_IRUGO, show_servicefanpsuled, ++ set_servicefanpsuled, 1); ++static SENSOR_DEVICE_ATTR (power_led, S_IWUSR | S_IRUGO, show_servicefanpsuled, ++ set_servicefanpsuled, 2); ++ ++static SENSOR_DEVICE_ATTR (psu0, S_IRUGO, show_psu, 0, 0); ++static SENSOR_DEVICE_ATTR (psu1, S_IRUGO, show_psu, 0, 1); ++ ++static SENSOR_DEVICE_ATTR (bios_cs, S_IWUSR | S_IRUGO, show_bios_cs, ++ set_bios_cs, 0); ++ ++static struct attribute *cpld_attributes[] = { ++ //info ++ &sensor_dev_attr_info.dev_attr.attr, ++ &sensor_dev_attr_ctl.dev_attr.attr, ++ ++ &sensor_dev_attr_grn_led.dev_attr.attr, ++ &sensor_dev_attr_red_led.dev_attr.attr, ++ &sensor_dev_attr_service_led.dev_attr.attr, ++ &sensor_dev_attr_fan_led.dev_attr.attr, ++ &sensor_dev_attr_power_led.dev_attr.attr, ++ ++ ++ &sensor_dev_attr_psu0.dev_attr.attr, ++ &sensor_dev_attr_psu1.dev_attr.attr, ++ ++ &sensor_dev_attr_bios_cs.dev_attr.attr, ++ ++ NULL ++}; ++ ++static const struct attribute_group cpld_group = { ++ .attrs = cpld_attributes, ++}; ++ ++static struct attribute *cpld2_attributes[] = { ++ //info ++ &sensor_dev_attr_info.dev_attr.attr, ++ ++ NULL ++}; ++ ++static const struct attribute_group cpld2_group = { ++ .attrs = cpld2_attributes, ++}; ++ ++ ++/*-----------------------------------------------------------------------*/ ++ ++/* device probe and removal */ ++ ++static int ++cpld_probe (struct i2c_client *client, const struct i2c_device_id *id) ++{ ++ struct cpld_data *data; ++ int status; ++ ++// printk("+%s \n", __func__); ++ ++ if (!i2c_check_functionality (client->adapter, ++ I2C_FUNC_SMBUS_BYTE_DATA | ++ I2C_FUNC_SMBUS_WORD_DATA)) ++ return -EIO; ++ ++ data = kzalloc (sizeof (struct cpld_data), GFP_KERNEL); ++ if (!data) ++ return -ENOMEM; ++ ++ i2c_set_clientdata (client, data); ++ mutex_init (&data->update_lock); ++ ++ /* Register sysfs hooks */ ++ if (id->driver_data == 1) // CPLD2 ++ status = sysfs_create_group (&client->dev.kobj, &cpld2_group); ++ else // default CPLD1 ++ status = sysfs_create_group (&client->dev.kobj, &cpld_group); ++ ++ if (status) ++ goto exit_free; ++ ++ data->hwmon_dev = hwmon_device_register (&client->dev); ++ if (IS_ERR (data->hwmon_dev)) ++ { ++ status = PTR_ERR (data->hwmon_dev); ++ goto exit_remove; ++ } ++ ++ dev_info (&client->dev, "%s: sensor '%s'\n", ++ dev_name (data->hwmon_dev), client->name); ++ ++ return 0; ++ ++ exit_remove: ++ sysfs_remove_group (&client->dev.kobj, &cpld_group); ++ exit_free: ++ i2c_set_clientdata (client, NULL); ++ kfree (data); ++ return status; ++} ++ ++static int cpld_remove (struct i2c_client *client) ++{ ++ struct cpld_data *data = i2c_get_clientdata (client); ++ ++ hwmon_device_unregister (data->hwmon_dev); ++ sysfs_remove_group (&client->dev.kobj, &cpld_group); ++ i2c_set_clientdata (client, NULL); ++ kfree (data); ++ return 0; ++} ++ ++static const struct i2c_device_id cpld_ids[] = { ++ {"nb_cpld", 0,}, ++ {"nb_cpld2", 1,}, ++ { /* LIST END */ } ++}; ++ ++MODULE_DEVICE_TABLE (i2c, cpld_ids); ++ ++static struct i2c_driver cpld_driver = { ++ .class = I2C_CLASS_HWMON, ++ .driver = { ++ .name = "nb_cpld", ++ }, ++ .probe = cpld_probe, ++ .remove = cpld_remove, ++ .id_table = cpld_ids, ++}; ++ ++/*-----------------------------------------------------------------------*/ ++ ++/* module glue */ ++ ++static int __init nb_cpld_init (void) ++{ ++ return i2c_add_driver (&cpld_driver); ++} ++ ++static void __exit nb_cpld_exit (void) ++{ ++ i2c_del_driver (&cpld_driver); ++} ++ ++MODULE_AUTHOR ("support "); ++MODULE_DESCRIPTION ("netberg cpld driver"); ++MODULE_LICENSE ("GPL"); ++ ++module_init (nb_cpld_init); ++module_exit (nb_cpld_exit); +diff --git a/drivers/platform/x86/nb_platform.c b/drivers/platform/x86/nb_platform.c +new file mode 100644 +index 0000000..a323894 +--- /dev/null ++++ b/drivers/platform/x86/nb_platform.c +@@ -0,0 +1,244 @@ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++struct nb_i2c_board_info { ++ int ch; ++ int size; ++ struct i2c_board_info *board_info; ++}; ++ ++#define bus_id(id) (id) ++static struct pca954x_platform_mode mux_modes_0[] = { ++ {.adap_id = bus_id (2),}, {.adap_id = bus_id (3),}, ++ {.adap_id = bus_id (4),}, {.adap_id = bus_id (5),}, ++ {.adap_id = bus_id (6),}, {.adap_id = bus_id (7),}, ++ {.adap_id = bus_id (8),}, {.adap_id = bus_id (9),}, ++}; ++ ++static struct pca954x_platform_mode mux_modes_0_0[] = { ++ {.adap_id = bus_id (10),}, {.adap_id = bus_id (11),}, ++ {.adap_id = bus_id (12),}, {.adap_id = bus_id (13),}, ++ {.adap_id = bus_id (14),}, {.adap_id = bus_id (15),}, ++ {.adap_id = bus_id (16),}, {.adap_id = bus_id (17),}, ++}; ++ ++static struct pca954x_platform_mode mux_modes_0_1[] = { ++ {.adap_id = bus_id (18),}, {.adap_id = bus_id (19),}, ++ {.adap_id = bus_id (20),}, {.adap_id = bus_id (21),}, ++ {.adap_id = bus_id (22),}, {.adap_id = bus_id (23),}, ++ {.adap_id = bus_id (24),}, {.adap_id = bus_id (25),}, ++}; ++ ++static struct pca954x_platform_mode mux_modes_0_2[] = { ++ {.adap_id = bus_id (26),}, {.adap_id = bus_id (27),}, ++ {.adap_id = bus_id (28),}, {.adap_id = bus_id (29),}, ++ {.adap_id = bus_id (30),}, {.adap_id = bus_id (31),}, ++ {.adap_id = bus_id (32),}, {.adap_id = bus_id (33),}, ++}; ++ ++static struct pca954x_platform_mode mux_modes_0_3[] = { ++ {.adap_id = bus_id (34),}, {.adap_id = bus_id (35),}, ++ {.adap_id = bus_id (36),}, {.adap_id = bus_id (37),}, ++ {.adap_id = bus_id (38),}, {.adap_id = bus_id (39),}, ++ {.adap_id = bus_id (40),}, {.adap_id = bus_id (41),}, ++}; ++ ++static struct pca954x_platform_mode mux_modes_0_4[] = { ++ {.adap_id = bus_id (42),}, {.adap_id = bus_id (43),}, ++ {.adap_id = bus_id (44),}, {.adap_id = bus_id (45),}, ++ {.adap_id = bus_id (46),}, {.adap_id = bus_id (47),}, ++ {.adap_id = bus_id (48),}, {.adap_id = bus_id (49),}, ++}; ++ ++static struct pca954x_platform_mode mux_modes_0_5[] = { ++ {.adap_id = bus_id (50),}, {.adap_id = bus_id (51),}, ++ {.adap_id = bus_id (52),}, {.adap_id = bus_id (53),}, ++ {.adap_id = bus_id (54),}, {.adap_id = bus_id (55),}, ++ {.adap_id = bus_id (56),}, {.adap_id = bus_id (57),}, ++}; ++ ++static struct pca954x_platform_mode mux_modes_0_6[] = { ++ {.adap_id = bus_id (58),}, {.adap_id = bus_id (59),}, ++ {.adap_id = bus_id (60),}, {.adap_id = bus_id (61),}, ++ {.adap_id = bus_id (62),}, {.adap_id = bus_id (63),}, ++ {.adap_id = bus_id (64),}, {.adap_id = bus_id (65),}, ++}; ++ ++//no i2c device driver attach to mux 7 ++ ++ ++static struct pca954x_platform_data mux_data_0 = { ++ .modes = mux_modes_0, ++ .num_modes = 8, ++}; ++ ++static struct pca954x_platform_data mux_data_0_0 = { ++ .modes = mux_modes_0_0, ++ .num_modes = 8, ++}; ++ ++static struct pca954x_platform_data mux_data_0_1 = { ++ .modes = mux_modes_0_1, ++ .num_modes = 8, ++}; ++ ++static struct pca954x_platform_data mux_data_0_2 = { ++ .modes = mux_modes_0_2, ++ .num_modes = 8, ++}; ++ ++static struct pca954x_platform_data mux_data_0_3 = { ++ .modes = mux_modes_0_3, ++ .num_modes = 8, ++}; ++ ++static struct pca954x_platform_data mux_data_0_4 = { ++ .modes = mux_modes_0_4, ++ .num_modes = 8, ++}; ++ ++static struct pca954x_platform_data mux_data_0_5 = { ++ .modes = mux_modes_0_5, ++ .num_modes = 8, ++}; ++ ++static struct pca954x_platform_data mux_data_0_6 = { ++ .modes = mux_modes_0_6, ++ .num_modes = 8, ++}; ++ ++static struct i2c_board_info i2c_device_info0[] __initdata = { ++ {"nb_cpld", 0, 0x77, 0, 0, 0}, //cpld ++}; ++static struct i2c_board_info i2c_device_info1[] __initdata = { ++ {"pca9548", 0, 0x70, &mux_data_0, 0, 0}, ++}; ++ ++static struct i2c_board_info i2c_device_info2[] __initdata = { ++ {"pca9548", 0, 0x72, &mux_data_0_0, 0, 0}, ++}; ++ ++static struct i2c_board_info i2c_device_info3[] __initdata = { ++ {"pca9548", 0, 0x72, &mux_data_0_1, 0, 0}, ++}; ++ ++static struct i2c_board_info i2c_device_info4[] __initdata = { ++ {"pca9548", 0, 0x72, &mux_data_0_2, 0, 0}, ++}; ++ ++static struct i2c_board_info i2c_device_info5[] __initdata = { ++ {"pca9548", 0, 0x72, &mux_data_0_3, 0, 0}, ++}; ++ ++static struct i2c_board_info i2c_device_info6[] __initdata = { ++ {"pca9548", 0, 0x72, &mux_data_0_4, 0, 0}, ++}; ++ ++static struct i2c_board_info i2c_device_info7[] __initdata = { ++ {"pca9548", 0, 0x72, &mux_data_0_5, 0, 0}, ++}; ++ ++static struct i2c_board_info i2c_device_info8[] __initdata = { ++ {"pca9548", 0, 0x72, &mux_data_0_6, 0, 0}, ++}; ++ ++ ++static struct nb_i2c_board_info i2cdev_list[] = { ++ {bus_id (0), ARRAY_SIZE (i2c_device_info0), i2c_device_info0}, //mux root ++ {bus_id (1), ARRAY_SIZE (i2c_device_info0), i2c_device_info1}, //mux root ++ ++ {bus_id (2), ARRAY_SIZE (i2c_device_info2), i2c_device_info2}, //mux 0 ++ {bus_id (3), ARRAY_SIZE (i2c_device_info3), i2c_device_info3}, //mux 1 ++ {bus_id (4), ARRAY_SIZE (i2c_device_info4), i2c_device_info4}, //mux 2 ++ {bus_id (5), ARRAY_SIZE (i2c_device_info5), i2c_device_info5}, //mux 3 ++ {bus_id (6), ARRAY_SIZE (i2c_device_info6), i2c_device_info6}, //mux 4 ++ {bus_id (7), ARRAY_SIZE (i2c_device_info7), i2c_device_info7}, //mux 5 ++ {bus_id (8), ARRAY_SIZE (i2c_device_info8), i2c_device_info8}, //mux 6 ++}; ++ ++///////////////////////////////////////////////////////////////////////////////////////// ++static struct platform_device *device_i2c_gpio0; ++static struct i2c_gpio_platform_data i2c_gpio_platdata0 = { ++ .scl_pin = 58, //494, ++ .sda_pin = 75, //511, ++ ++ .udelay = 5, //5:100kHz ++ .sda_is_open_drain = 0, ++ .scl_is_open_drain = 0, ++ .scl_is_output_only = 0 ++}; ++ ++static int __init nb_platform_init (void) ++{ ++ struct i2c_adapter *adap = NULL; ++ struct i2c_client *e = NULL; ++ int ret = 0; ++ int i, j, k; ++ ++ //printk("%s \n", __func__); ++ ++ //use i2c-gpio ++ //register i2c gpio ++ //config gpio58,75 to gpio function 58=32+3*8+2 75=32*2+8*1+3 gpio69=32*2+8*0+5 ++ outl (inl (0x533) | (1 << 2), 0x533); //i2c-gpio sdl (GPIO58) ++ outl (inl (0x541) | (1 << 3), 0x541); //i2c-gpio sda (GPIO75) ++ outl (inl (0x540) | (1 << 5), 0x540); //RST_I2C_MUX_N (GPIO69) ++ outl (inl (0x500) | (1 << 7), 0x500); //SYS_RDY_N (GPIO7) ++ outl (inl (0x501) | (1 << 7), 0x501); //BMC_HEART_BEAT (GPIO15) ++ outl (inl (0x503) | (1 << 2) | (1 << 3), 0x503); //PSOC_HEART_BEAT(26),CPLD_HEART_BEAT(27) ++ ++ device_i2c_gpio0 = platform_device_alloc ("i2c-gpio", 1); ++ if (!device_i2c_gpio0) ++ { ++ printk (KERN_ERR "i2c-gpio: platform_device_alloc fail\n"); ++ return -ENOMEM; ++ } ++ device_i2c_gpio0->name = "i2c-gpio"; ++ device_i2c_gpio0->id = 1; ++ device_i2c_gpio0->dev.platform_data = &i2c_gpio_platdata0; ++ ++ ret = platform_device_add (device_i2c_gpio0); ++ if (ret) ++ { ++ printk (KERN_ERR "i2c-gpio: platform_device_add fail %d\n", ret); ++ } ++ ++ for (i = 0; i < ARRAY_SIZE (i2cdev_list); i++) ++ { ++ adap = i2c_get_adapter (i2cdev_list[i].ch); ++ if (adap == NULL) ++ { ++ printk ("platform get channel %d adapter fail\n", i); ++ continue; ++ } ++ i2c_put_adapter (adap); ++ for (j = 0; j < i2cdev_list[i].size; j++) ++ { ++ for (k = 0; k < 300; k++) ++ { ++ e = i2c_new_device (adap, &i2cdev_list[i].board_info[j]); ++ if (e == NULL) ++ msleep (10); ++ else ++ break; ++ } ++ } ++ } ++ return ret; ++} ++ ++static void __exit nb_platform_exit (void) ++{ ++ device_i2c_gpio0->dev.platform_data = NULL; ++ platform_device_unregister (device_i2c_gpio0); ++} ++ ++module_init (nb_platform_init); ++module_exit (nb_platform_exit); ++ +diff --git a/drivers/platform/x86/nb_psoc.c b/drivers/platform/x86/nb_psoc.c +new file mode 100644 +index 0000000..c9cebb5 +--- /dev/null ++++ b/drivers/platform/x86/nb_psoc.c +@@ -0,0 +1,1154 @@ ++/* ++ * 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 ++#define SWITCH_TEMPERATURE_SOCK "/proc/switch/temp" ++#define PSOC_POLLING_PERIOD 1000 ++ ++#include ++#include ++#include ++#include ++ ++#define IPMI_MAX_INTF (4) ++#define NETFN_OEM 0x30 ++#define CMD_GETDATA 0x31 ++#define CMD_SETDATA 0x32 ++#define FAN_NUM 4 ++#define PSU_NUM 2 ++ ++#define FAN_CLEI_SUPPORT 0 ++#define PSU_CLEI_SUPPORT 0 ++ ++#define PSU1 0x5800 ++#define PSU2 0x5900 ++#define BMC_PMBusNumber 3 ++#define PMBus_Vendor 0x99 ++#define PMBus_Serial 0x9E ++#define PMBus_Temp2 0x8E ++#define PMBus_Version 0x9B ++#define MaxLeng_Result 0x40 ++ ++#define BMC_FanCLEIBusNumber 9 ++#define DEVICE_CLEI_ADDR 0x52,0x53,0x54,0x55,0x56,0x50,0x51 ++ ++#define MAX_IPMI_RECV_LENGTH 0xff ++static char CLEI_ADDR[] = { DEVICE_CLEI_ADDR }; ++ ++struct task_struct *kthread_auto_update; ++static long pmbus_reg2data_linear (int data, int linear16); ++struct ipmi_result { ++ char result[MAX_IPMI_RECV_LENGTH]; ++ int result_length; ++}; ++ ++DEFINE_MUTEX (ipmi_mutex); ++DEFINE_MUTEX (ipmi2_mutex); ++static struct ipmi_result ipmiresult; ++static struct device *hwmon_dev; ++static struct kobject *device_kobj; ++static ipmi_user_t ipmi_mh_user = NULL; ++static void msg_handler (struct ipmi_recv_msg *msg, void *handler_data); ++static struct ipmi_user_hndl ipmi_hndlrs = {.ipmi_recv_hndl = msg_handler, }; ++ ++static atomic_t dummy_count = ATOMIC_INIT (0); ++static void dummy_smi_free (struct ipmi_smi_msg *msg) ++{ ++ atomic_dec (&dummy_count); ++} ++ ++static void dummy_recv_free (struct ipmi_recv_msg *msg) ++{ ++ atomic_dec (&dummy_count); ++} ++ ++static struct ipmi_smi_msg halt_smi_msg = { ++ .done = dummy_smi_free ++}; ++ ++static struct ipmi_recv_msg halt_recv_msg = { ++ .done = dummy_recv_free ++}; ++ ++struct __attribute__ ((__packed__)) psoc_psu_layout ++{ ++ u16 psu1_iin; ++ u16 psu2_iin; ++ u16 psu1_iout; ++ u16 psu2_iout; ++ ++ u16 psu1_pin; ++ u16 psu2_pin; ++ u16 psu1_pout; ++ u16 psu2_pout; ++ ++ u16 psu1_vin; ++ u16 psu2_vin; ++ u16 psu1_vout; ++ u16 psu2_vout; ++}; ++ ++struct __attribute__ ((__packed__)) clei ++{ ++ u8 issue_number[3]; ++ u8 abbreviation_number[9]; ++ u8 fc_number[10]; ++ u8 clei_code[10]; ++ u8 product_year_and_month[5]; ++ u8 label_location_code[2]; ++ u8 serial_number[5]; ++ u8 pcb_revision[5]; ++ u8 vendor_name[10]; ++ u8 reserved[5]; ++}; ++ ++struct __attribute__ ((__packed__)) psoc_layout ++{ ++ u8 ctl; //offset: 0 ++ u16 switch_temp; //offset: 1 ++ ++ // BYTE[03:20] - voltage ++ u16 voltage[15]; //offset: 0x03-0x20 ++ ++ // BYTE[21:27] - ExtFan ++ u8 led_ctl2; //offset: 21 ++ u8 ext_pwm; //offset: 22 ++ u16 ext_rpm[2]; //offset: 23 ++ u8 gpi_fan2; //offset: 27 ++ ++ //gpo ++ u8 led_ctl; //offset: 28 ++ ++ u8 gpio; //offset: 29 ++ ++ //pwm duty ++ u8 pwm[4]; //offset: 2a ++ u8 pwm_psu[2]; //offset: 2e ++ ++ //fan rpm ++ u16 fan[4 * 2]; //offset: 30 ++ ++ u8 reserve1[4]; //offset: 40 ++ ++ //gpi ++ u8 gpi_fan; //offset: 44 ++ ++ //psu state ++ u8 psu_state; //offset: 45 ++ ++ //temperature ++ u16 temp[5]; //offset: 46 ++ u16 temp_psu[2]; //offset: 50 ++ ++ //version ++ u8 version[2]; //offset: 54 ++ ++ u8 reserve2[4]; //offset: 56 ++ struct psoc_psu_layout psu_info; //offset: 5a ++}; ++ ++/* definition */ ++#define PSOC_OFF(m) offsetof(struct psoc_layout, m) ++#define PSOC_PSU_OFF(m) offsetof(struct psoc_psu_layout, m) ++ ++#define SWITCH_TMP_OFFSET PSOC_OFF(switch_temp) ++#define PWM_OFFSET PSOC_OFF(pwm) ++#define THERMAL_OFFSET PSOC_OFF(temp) ++#define RPM_OFFSET PSOC_OFF(fan) ++#define DIAG_FLAG_OFFSET PSOC_OFF(ctl) ++#define FAN_LED_OFFSET PSOC_OFF(led_ctl) ++#define FAN_GPI_OFFSET PSOC_OFF(gpi_fan) ++#define PSOC_PSU_OFFSET PSOC_OFF(psu_state) ++#define VERSION_OFFSET PSOC_OFF(version) ++#define PSU_INFO_OFFSET PSOC_OFF(psu_info) ++ ++#define PWM2_OFFSET PSOC_OFF(ext_pwm) ++#define RPM2_OFFSET PSOC_OFF(ext_rpm) ++#define FAN_LED2_OFFSET PSOC_OFF(led_ctl2) ++#define FAN_GPI2_OFFSET PSOC_OFF(gpi_fan2) ++ ++#define CLEI_OFF(m) offsetof(struct clei, m) ++#define FAN1_CLEI_INDEX 0 ++#define FAN2_CLEI_INDEX 1 ++#define FAN3_CLEI_INDEX 2 ++#define FAN4_CLEI_INDEX 3 ++#define FAN5_CLEI_INDEX 4 ++#define PSU1_CLEI_INDEX 5 ++#define PSU2_CLEI_INDEX 6 ++ ++static void msg_handler (struct ipmi_recv_msg *recv_msg, void *handler_data) ++{ ++ struct ipmi_result *msg_result = recv_msg->user_msg_data; ++ ++ msg_result->result_length = recv_msg->msg.data_len - 1; ++ memcpy (msg_result->result, &recv_msg->msg.data[1], ++ recv_msg->msg.data_len - 1); ++ ++ ipmi_free_recv_msg (recv_msg); ++ mutex_unlock (&ipmi_mutex); ++ ++ return; ++} ++ ++int start_ipmi_command (char NetFn, char cmd, char *data, int data_length, ++ char *result, int *result_length) ++{ ++ int rv = 0, i; ++ int timeout; ++ ++ //wait previous command finish at least 50msec ++ timeout = 50; ++ while ((mutex_is_locked (&ipmi_mutex) == 1 ++ || (mutex_is_locked (&ipmi2_mutex) == 1)) && (--timeout) > 0) ++ { ++ usleep_range (1000, 1010); ++ } ++ if (timeout == 0) ++ { ++ return -1; ++ } ++ mutex_lock (&ipmi_mutex); ++ mutex_lock (&ipmi2_mutex); ++ ++ if (ipmi_mh_user == NULL) ++ { ++ for (i = 0, rv = 1; i < IPMI_MAX_INTF && rv; i++) ++ { ++ rv = ipmi_create_user (i, &ipmi_hndlrs, NULL, &ipmi_mh_user); ++ } ++ } ++ ++ if (rv < 0) ++ { ++ mutex_unlock (&ipmi_mutex); ++ mutex_unlock (&ipmi2_mutex); ++ return rv; ++ } ++ else ++ { ++ struct ipmi_system_interface_addr addr; ++ struct kernel_ipmi_msg msg; ++ uint8_t msg_data[data_length]; ++ ++ memcpy (msg_data, data, data_length); ++ addr.addr_type = IPMI_SYSTEM_INTERFACE_ADDR_TYPE; ++ addr.channel = IPMI_BMC_CHANNEL; ++ addr.lun = 0; ++ ++ msg.netfn = NetFn; ++ msg.cmd = cmd; ++ msg.data = msg_data; ++ msg.data_len = data_length; ++ ++ rv = ipmi_request_supply_msgs (ipmi_mh_user, (struct ipmi_addr *)&addr, ++ 0, &msg, &ipmiresult, &halt_smi_msg, ++ &halt_recv_msg, 0); ++ if (rv) ++ { ++ mutex_unlock (&ipmi_mutex); ++ mutex_unlock (&ipmi2_mutex); ++ return -6; ++ } ++ ++ //skip command if 1sec no response from remote ++ timeout = 1000; ++ while (mutex_is_locked (&ipmi_mutex) == 1 && (--timeout) > 0) ++ { ++ usleep_range (1000, 1100); ++ } ++ if (timeout == 0) ++ { ++ mutex_unlock (&ipmi2_mutex); ++ return -1; ++ } ++ else ++ { ++ *result_length = ipmiresult.result_length; ++ memcpy (result, ipmiresult.result, *result_length); ++ mutex_unlock (&ipmi2_mutex); ++ return 0; ++ } ++ } ++ return 0; ++} ++ ++EXPORT_SYMBOL (start_ipmi_command); ++ ++static ssize_t psoc_ipmi_read (u8 * buf, u8 offset, size_t count) ++{ ++ uint8_t data[2]; ++ int result_len = 0; ++ int rv; ++ ++ data[0] = offset; ++ data[1] = count; ++ ++ rv = start_ipmi_command (NETFN_OEM, CMD_GETDATA, data, 2, buf, &result_len); ++ ++ return result_len; ++} ++ ++static ssize_t psoc_ipmi_write (char *buf, unsigned offset, size_t count) ++{ ++ uint8_t data[count + 1], result[1]; ++ int result_len; ++ ++ data[0] = offset; ++ memcpy (&data[1], buf, count); ++ ++ start_ipmi_command (NETFN_OEM, CMD_SETDATA, data, count + 1, result, ++ &result_len); ++ return count; ++} ++ ++ ++static u16 psoc_read16 (u8 offset) ++{ ++ u16 value = 0; ++ u8 buf[] = { 0, 0 }; ++ ++ if (psoc_ipmi_read (buf, offset, 2) == 2) ++ value = (buf[0] << 8 | buf[1] << 0); ++ ++ return value; ++} ++ ++static u8 psoc_read8 (u8 offset) ++{ ++ u8 value = 0; ++ u8 buf = 0; ++ ++ if (psoc_ipmi_read (&buf, offset, 1) == 1) ++ value = buf; ++ ++ return value; ++} ++ ++/* ++CPLD report the PSU0 status ++000 = PSU normal operation ++100 = PSU fault ++010 = PSU unpowered ++111 = PSU not installed ++ ++7 6 | 5 4 3 | 2 1 0 ++---------------------- ++ | psu1 | psu0 ++*/ ++static char *psu_str[] = { ++ "normal", //000 ++ "NA", //001 ++ "unpowered", //010 ++ "NA", //011 ++ "fault", //100 ++ "NA", //101 ++ "NA", //110 ++ "not installed", //111 ++}; ++ ++static ssize_t show_psu_st (struct device *dev, struct device_attribute *da, ++ char *buf) ++{ ++ u32 status = 0; ++ struct sensor_device_attribute *attr = to_sensor_dev_attr (da); ++ u8 byte = 0; ++ int shift = (attr->index == 0) ? 3 : 0; ++ ++ status = psoc_ipmi_read (&byte, PSOC_PSU_OFFSET, 1); ++ ++ byte = (byte >> shift) & 0x7; ++ ++ status = sprintf (buf, "%d : %s\n", byte, psu_str[byte]); ++ ++ return strlen (buf); ++} ++ ++static ssize_t show_ipmi_pmbus (struct device *dev, struct device_attribute *da, ++ char *buf) ++{ ++ struct sensor_device_attribute *attr = to_sensor_dev_attr (da); ++ uint8_t data[4], result[MaxLeng_Result]; ++ int result_len = 0; ++ ++ data[0] = BMC_PMBusNumber; ++ data[1] = (attr->index & 0xFF00) >> 7; ++ data[3] = attr->index & 0xff; ++ if (data[3] == PMBus_Temp2) ++ { ++ data[2] = 2; ++ } ++ else ++ { ++ data[2] = MaxLeng_Result; ++ } ++ ++ if (start_ipmi_command (0x06, 0x52, data, 4, result, &result_len) == 0) ++ { ++ if (data[3] == PMBus_Temp2) ++ { ++ return sprintf (buf, "%ld \n", ++ ((result_len == ++ 2) ? (pmbus_reg2data_linear (result[0] | ++ (result[1] << 8), ++ 0)) : 0)); ++ } ++ else ++ { ++ if (result_len == 0) ++ result[0] = 0; ++ result[result[0] + 1] = '\0'; ++ return sprintf (buf, "%s\n", &result[1]); ++ } ++ } ++ else ++ { ++ return 0; ++ } ++} ++ ++static ssize_t show_clei (struct device *dev, struct device_attribute *da, ++ char *buf) ++{ ++ struct sensor_device_attribute *attr = to_sensor_dev_attr (da); ++ u8 device_index = attr->index & 0xFF; ++ ++ uint8_t data[5], result[MaxLeng_Result]; ++ int result_len = 0; ++ ++ data[0] = ++ (device_index <= ++ FAN5_CLEI_INDEX) ? BMC_FanCLEIBusNumber : BMC_PMBusNumber; ++ data[1] = CLEI_ADDR[device_index] << 1; ++ data[2] = sizeof (struct clei); ++ data[3] = (device_index <= FAN5_CLEI_INDEX) ? 0x00 : 0x01; //PSU CLEI will start from 0x0100 ++ data[4] = 0; ++ ++ if (start_ipmi_command (0x06, 0x52, data, 5, result, &result_len) == 0) ++ { ++ if (result_len < sizeof (struct clei)) ++ memset (result, 0, sizeof (struct clei)); ++ sprintf (buf, "Issue Number: %.3s\n", &result[CLEI_OFF (issue_number)]); ++ sprintf (buf, "%sAbbreviation Number: %.9s\n", buf, ++ &result[CLEI_OFF (abbreviation_number)]); ++ sprintf (buf, "%sFC Number: %.10s\n", buf, ++ &result[CLEI_OFF (fc_number)]); ++ sprintf (buf, "%sCLEI Code: %.10s\n", buf, ++ &result[CLEI_OFF (clei_code)]); ++ sprintf (buf, "%sProduct Year and Month: %.5s\n", buf, ++ &result[CLEI_OFF (product_year_and_month)]); ++ sprintf (buf, "%s2D Label Location Code: %.2s\n", buf, ++ &result[CLEI_OFF (label_location_code)]); ++ sprintf (buf, "%sSerial Number: %.5s\n", buf, ++ &result[CLEI_OFF (serial_number)]); ++ sprintf (buf, "%sPCB Revision: %.5s\n", buf, ++ &result[CLEI_OFF (pcb_revision)]); ++ sprintf (buf, "%sVendor Name: %.10s\n", buf, ++ &result[CLEI_OFF (vendor_name)]); ++ return strlen (buf); ++ } ++ else ++ { ++ return sprintf (buf, "NONE\n"); ++ } ++} ++ ++static ssize_t show_thermal (struct device *dev, struct device_attribute *da, ++ char *buf) ++{ ++ int status = 0; ++ struct sensor_device_attribute *attr = to_sensor_dev_attr (da); ++ u8 offset = attr->index * 2 + THERMAL_OFFSET; ++ ++ status = psoc_read16 (offset); ++ ++ return sprintf (buf, "%d\n", (s8) (status >> 8) * 1000); ++} ++ ++static ssize_t show_pwm (struct device *dev, struct device_attribute *da, ++ char *buf) ++{ ++ int status = 0; ++ struct sensor_device_attribute *attr = to_sensor_dev_attr (da); ++ u8 offset = attr->index; ++ ++ status = psoc_read8 (offset); ++ ++ return sprintf (buf, "%d\n", status); ++} ++ ++static ssize_t set_pwm (struct device *dev, ++ struct device_attribute *da, ++ const char *buf, size_t count) ++{ ++ struct sensor_device_attribute *attr = to_sensor_dev_attr (da); ++ u8 offset = attr->index; ++ u8 pwm = simple_strtol (buf, NULL, 10); ++ if (pwm > 255) ++ pwm = 255; ++ psoc_ipmi_write (&pwm, offset, 1); ++ ++ return count; ++} ++ ++ ++static ssize_t show_rpm (struct device *dev, struct device_attribute *da, ++ char *buf) ++{ ++ int status = 0; ++ struct sensor_device_attribute *attr = to_sensor_dev_attr (da); ++ u8 offset = attr->index; ++ status = psoc_read16 (offset); ++ ++ return sprintf (buf, "%d\n", status); ++} ++ ++static ssize_t show_switch_tmp (struct device *dev, struct device_attribute *da, ++ char *buf) ++{ ++ u16 status = 0; ++ u16 temp = 0; ++ ++ status = psoc_ipmi_read ((u8 *) & temp, SWITCH_TMP_OFFSET, 2); ++ ++ status = sprintf (buf, "%d\n", (s8) (temp >> 8) * 1000); ++ ++ return strlen (buf); ++} ++ ++static ssize_t set_switch_tmp (struct device *dev, ++ struct device_attribute *devattr, ++ const char *buf, size_t count) ++{ ++ long temp = simple_strtol (buf, NULL, 10); ++ u16 temp2 = ((temp / 1000) << 8) & 0xFF00; ++ ++ psoc_ipmi_write ((u8 *) & temp2, SWITCH_TMP_OFFSET, 2); ++ ++ ++ return count; ++} ++ ++static ssize_t show_diag (struct device *dev, struct device_attribute *da, ++ char *buf) ++{ ++ u16 status = 0; ++ u8 diag_flag = 0; ++ ++ status = psoc_ipmi_read ((u8 *) & diag_flag, DIAG_FLAG_OFFSET, 1); ++ ++ status = sprintf (buf, "%d\n", ((diag_flag & 0x80) ? 1 : 0)); ++ ++ return strlen (buf); ++} ++ ++static ssize_t set_diag (struct device *dev, ++ struct device_attribute *devattr, ++ const char *buf, size_t count) ++{ ++ u8 value = 0; ++ u8 diag = simple_strtol (buf, NULL, 10); ++ ++ diag = diag ? 1 : 0; ++ ++ psoc_ipmi_read ((u8 *) & value, DIAG_FLAG_OFFSET, 1); ++ if (diag) ++ value |= (1 << 7); ++ else ++ value &= ~(1 << 7); ++ psoc_ipmi_write ((u8 *) & value, DIAG_FLAG_OFFSET, 1); ++ ++ return count; ++} ++ ++static ssize_t show_version (struct device *dev, struct device_attribute *da, ++ char *buf) ++{ ++ u16 status = 0; ++ ++ status = psoc_read16 (VERSION_OFFSET); ++ ++ return sprintf (buf, "ver: %x.%x\n", (status & 0xFF00) >> 8, ++ (status & 0xFF)); ++} ++ ++ ++static ssize_t show_fan_led (struct device *dev, struct device_attribute *da, ++ char *buf) ++{ ++ int status = 0; ++ struct sensor_device_attribute *attr = to_sensor_dev_attr (da); ++ u8 bit = attr->index; ++ ++ if (bit < 8) ++ { ++ status = psoc_read8 (FAN_LED_OFFSET); ++ } ++#if FAN_NUM>4 ++ if (bit >= 8) ++ { ++ status = psoc_read8 (FAN_LED2_OFFSET); ++ bit -= 8; ++ } ++#endif ++ ++ return sprintf (buf, "%d\n", (status & (1 << bit)) ? 1 : 0); ++} ++ ++static ssize_t set_fan_led (struct device *dev, ++ struct device_attribute *devattr, ++ const char *buf, size_t count) ++{ ++ struct sensor_device_attribute *attr = to_sensor_dev_attr (devattr); ++ u8 bit = attr->index; ++ u8 led_state = 0; ++ ++ u8 v = simple_strtol (buf, NULL, 10); ++ ++ if (attr->index < 8) ++ { ++ led_state = psoc_read8 (FAN_LED_OFFSET); ++ } ++#if FAN_NUM>4 ++ if (attr->index >= 8) ++ { ++ led_state = psoc_read8 (FAN_LED2_OFFSET); ++ bit -= 8; ++ } ++#endif ++ if (v) ++ led_state |= (1 << bit); ++ else ++ led_state &= ~(1 << bit); ++ ++ if (attr->index < 8) ++ { ++ psoc_ipmi_write (&led_state, FAN_LED_OFFSET, 1); ++ } ++#if FAN_NUM>4 ++ if (attr->index >= 8) ++ { ++ psoc_ipmi_write (&led_state, FAN_LED2_OFFSET, 1); ++ } ++#endif ++ return count; ++} ++ ++static ssize_t show_value8 (struct device *dev, struct device_attribute *da, ++ char *buf) ++{ ++ int status = 0; ++ struct sensor_device_attribute *attr = to_sensor_dev_attr (da); ++ u8 offset = attr->index; ++ ++ status = psoc_read8 (offset); ++ ++ return sprintf (buf, "0x%02X\n", status); ++} ++ ++static long pmbus_reg2data_linear (int data, int linear16) ++{ ++ s16 exponent; ++ s32 mantissa; ++ long val; ++ ++ if (linear16) ++ { /* LINEAR16 */ ++ exponent = -9; ++ mantissa = (u16) data; ++ } ++ else ++ { /* LINEAR11 */ ++ exponent = ((s16) data) >> 11; ++ exponent = ((s16) (data & 0xF800)) >> 11; ++ mantissa = ((s32) ((data & 0x7ff) << 5)) >> 5; ++ } ++ ++ //printk("data=%d, m=%d, e=%d\n", data, exponent, mantissa); ++ val = mantissa; ++ ++ /* scale result to micro-units for power sensors */ ++ val = val * 1000L; ++ ++ if (exponent >= 0) ++ val <<= exponent; ++ else ++ val >>= -exponent; ++ ++ return val; ++} ++ ++static ssize_t show_psu_psoc (struct device *dev, struct device_attribute *da, ++ char *buf) ++{ ++ u16 status = 0; ++ struct sensor_device_attribute *attr = to_sensor_dev_attr (da); ++ u8 offset = attr->index + PSU_INFO_OFFSET; ++ ++ status = psoc_read16 (offset); ++ ++ if ((strstr (attr->dev_attr.attr.name, "vout") != ++ NULL) | (strstr (attr->dev_attr.attr.name, ++ "in3") != NULL) | (strstr (attr->dev_attr.attr.name, ++ "in4") != NULL)) ++ { ++ offset = 1; ++ } ++ else ++ { ++ offset = 0; ++ } ++ ++ return sprintf (buf, "%ld \n", pmbus_reg2data_linear (status, offset)); ++} ++ ++static ssize_t show_name (struct device *dev, ++ struct device_attribute *devattr, char *buf) ++{ ++ return sprintf (buf, "nb_psoc\n"); ++} ++ ++static DEVICE_ATTR (name, S_IRUGO, show_name, NULL); ++static SENSOR_DEVICE_ATTR (temp1_input, S_IRUGO, show_thermal, 0, 0); ++static SENSOR_DEVICE_ATTR (temp2_input, S_IRUGO, show_thermal, 0, 1); ++static SENSOR_DEVICE_ATTR (temp3_input, S_IRUGO, show_thermal, 0, 2); ++static SENSOR_DEVICE_ATTR (temp4_input, S_IRUGO, show_thermal, 0, 3); ++static SENSOR_DEVICE_ATTR (temp5_input, S_IRUGO, show_thermal, 0, 4); ++static SENSOR_DEVICE_ATTR (thermal_psu1, S_IRUGO, show_thermal, 0, 5); ++static SENSOR_DEVICE_ATTR (thermal_psu2, S_IRUGO, show_thermal, 0, 6); ++static SENSOR_DEVICE_ATTR (temp7_input, S_IRUGO, show_thermal, 0, 5); ++static SENSOR_DEVICE_ATTR (temp8_input, S_IRUGO, show_thermal, 0, 6); ++ ++static SENSOR_DEVICE_ATTR (pwm1, S_IWUSR | S_IRUGO, show_pwm, set_pwm, ++ 0 + PWM_OFFSET); ++static SENSOR_DEVICE_ATTR (pwm2, S_IWUSR | S_IRUGO, show_pwm, set_pwm, ++ 1 + PWM_OFFSET); ++static SENSOR_DEVICE_ATTR (pwm3, S_IWUSR | S_IRUGO, show_pwm, set_pwm, ++ 2 + PWM_OFFSET); ++static SENSOR_DEVICE_ATTR (pwm4, S_IWUSR | S_IRUGO, show_pwm, set_pwm, ++ 3 + PWM_OFFSET); ++#if FAN_NUM > 4 ++static SENSOR_DEVICE_ATTR (pwm5, S_IWUSR | S_IRUGO, show_pwm, set_pwm, ++ 0 + PWM2_OFFSET); ++#endif ++static SENSOR_DEVICE_ATTR (pwm_psu1, S_IWUSR | S_IRUGO, show_pwm, set_pwm, ++ 4 + PWM_OFFSET); ++static SENSOR_DEVICE_ATTR (pwm_psu2, S_IWUSR | S_IRUGO, show_pwm, set_pwm, ++ 5 + PWM_OFFSET); ++static SENSOR_DEVICE_ATTR (pwm6, S_IWUSR | S_IRUGO, show_pwm, set_pwm, ++ 4 + PWM_OFFSET); ++static SENSOR_DEVICE_ATTR (pwm7, S_IWUSR | S_IRUGO, show_pwm, set_pwm, ++ 5 + PWM_OFFSET); ++ ++static SENSOR_DEVICE_ATTR (psu1, S_IRUGO, show_psu_st, 0, 0); ++static SENSOR_DEVICE_ATTR (psu2, S_IRUGO, show_psu_st, 0, 1); ++ ++static SENSOR_DEVICE_ATTR (fan1_input, S_IRUGO, show_rpm, 0, ++ 0 * 2 + RPM_OFFSET); ++static SENSOR_DEVICE_ATTR (fan2_input, S_IRUGO, show_rpm, 0, ++ 1 * 2 + RPM_OFFSET); ++static SENSOR_DEVICE_ATTR (fan3_input, S_IRUGO, show_rpm, 0, ++ 2 * 2 + RPM_OFFSET); ++static SENSOR_DEVICE_ATTR (fan4_input, S_IRUGO, show_rpm, 0, ++ 3 * 2 + RPM_OFFSET); ++static SENSOR_DEVICE_ATTR (fan5_input, S_IRUGO, show_rpm, 0, ++ 4 * 2 + RPM_OFFSET); ++static SENSOR_DEVICE_ATTR (fan6_input, S_IRUGO, show_rpm, 0, ++ 5 * 2 + RPM_OFFSET); ++static SENSOR_DEVICE_ATTR (fan7_input, S_IRUGO, show_rpm, 0, ++ 6 * 2 + RPM_OFFSET); ++static SENSOR_DEVICE_ATTR (fan8_input, S_IRUGO, show_rpm, 0, ++ 7 * 2 + RPM_OFFSET); ++static SENSOR_DEVICE_ATTR (rpm_psu1, S_IRUGO, show_rpm, 0, 8 * 2 + RPM_OFFSET); ++static SENSOR_DEVICE_ATTR (rpm_psu2, S_IRUGO, show_rpm, 0, 9 * 2 + RPM_OFFSET); ++static SENSOR_DEVICE_ATTR (fan11_input, S_IRUGO, show_rpm, 0, ++ 8 * 2 + RPM_OFFSET); ++static SENSOR_DEVICE_ATTR (fan12_input, S_IRUGO, show_rpm, 0, ++ 9 * 2 + RPM_OFFSET); ++ ++#if FAN_NUM > 4 ++static SENSOR_DEVICE_ATTR (fan9_input, S_IRUGO, show_rpm, 0, ++ 0 * 2 + RPM2_OFFSET); ++static SENSOR_DEVICE_ATTR (fan10_input, S_IRUGO, show_rpm, 0, ++ 1 * 2 + RPM2_OFFSET); ++#endif ++ ++static SENSOR_DEVICE_ATTR (switch_tmp, S_IWUSR | S_IRUGO, show_switch_tmp, ++ set_switch_tmp, 0); ++static SENSOR_DEVICE_ATTR (temp6_input, S_IWUSR | S_IRUGO, show_switch_tmp, ++ set_switch_tmp, 0); ++ ++static SENSOR_DEVICE_ATTR (diag, S_IWUSR | S_IRUGO, show_diag, set_diag, 0); ++static SENSOR_DEVICE_ATTR (version, S_IRUGO, show_version, 0, 0); ++ ++static SENSOR_DEVICE_ATTR (fan_led_grn1, S_IWUSR | S_IRUGO, show_fan_led, ++ set_fan_led, 0); ++static SENSOR_DEVICE_ATTR (fan_led_grn2, S_IWUSR | S_IRUGO, show_fan_led, ++ set_fan_led, 1); ++static SENSOR_DEVICE_ATTR (fan_led_grn3, S_IWUSR | S_IRUGO, show_fan_led, ++ set_fan_led, 2); ++static SENSOR_DEVICE_ATTR (fan_led_grn4, S_IWUSR | S_IRUGO, show_fan_led, ++ set_fan_led, 3); ++static SENSOR_DEVICE_ATTR (fan_led_red1, S_IWUSR | S_IRUGO, show_fan_led, ++ set_fan_led, 4); ++static SENSOR_DEVICE_ATTR (fan_led_red2, S_IWUSR | S_IRUGO, show_fan_led, ++ set_fan_led, 5); ++static SENSOR_DEVICE_ATTR (fan_led_red3, S_IWUSR | S_IRUGO, show_fan_led, ++ set_fan_led, 6); ++static SENSOR_DEVICE_ATTR (fan_led_red4, S_IWUSR | S_IRUGO, show_fan_led, ++ set_fan_led, 7); ++ ++#if FAN_NUM>4 ++static SENSOR_DEVICE_ATTR (fan_led_grn5, S_IWUSR | S_IRUGO, show_fan_led, ++ set_fan_led, 8); ++static SENSOR_DEVICE_ATTR (fan_led_red5, S_IWUSR | S_IRUGO, show_fan_led, ++ set_fan_led, 12); ++static SENSOR_DEVICE_ATTR (fan_gpi2, S_IRUGO, show_value8, 0, FAN_GPI2_OFFSET); ++#endif ++ ++static SENSOR_DEVICE_ATTR (fan_gpi, S_IRUGO, show_value8, 0, FAN_GPI_OFFSET); ++static SENSOR_DEVICE_ATTR (psoc_psu1_vin, S_IRUGO, show_psu_psoc, 0, ++ PSOC_PSU_OFF (psu1_vin)); ++static SENSOR_DEVICE_ATTR (psoc_psu1_vout, S_IRUGO, show_psu_psoc, 0, ++ PSOC_PSU_OFF (psu1_vout)); ++static SENSOR_DEVICE_ATTR (psoc_psu1_iin, S_IRUGO, show_psu_psoc, 0, ++ PSOC_PSU_OFF (psu1_iin)); ++static SENSOR_DEVICE_ATTR (psoc_psu1_iout, S_IRUGO, show_psu_psoc, 0, ++ PSOC_PSU_OFF (psu1_iout)); ++static SENSOR_DEVICE_ATTR (psoc_psu1_pin, S_IRUGO, show_psu_psoc, 0, ++ PSOC_PSU_OFF (psu1_pin)); ++static SENSOR_DEVICE_ATTR (psoc_psu1_pout, S_IRUGO, show_psu_psoc, 0, ++ PSOC_PSU_OFF (psu1_pout)); ++ ++static SENSOR_DEVICE_ATTR (in1_input, S_IRUGO, show_psu_psoc, 0, ++ PSOC_PSU_OFF (psu1_vin)); ++static SENSOR_DEVICE_ATTR (curr1_input, S_IRUGO, show_psu_psoc, 0, ++ PSOC_PSU_OFF (psu1_iin)); ++static SENSOR_DEVICE_ATTR (power1_input, S_IRUGO, show_psu_psoc, 0, ++ PSOC_PSU_OFF (psu1_pin)); ++static SENSOR_DEVICE_ATTR (in3_input, S_IRUGO, show_psu_psoc, 0, ++ PSOC_PSU_OFF (psu1_vout)); ++static SENSOR_DEVICE_ATTR (curr3_input, S_IRUGO, show_psu_psoc, 0, ++ PSOC_PSU_OFF (psu1_iout)); ++static SENSOR_DEVICE_ATTR (power3_input, S_IRUGO, show_psu_psoc, 0, ++ PSOC_PSU_OFF (psu1_pout)); ++ ++static SENSOR_DEVICE_ATTR (psoc_psu2_vin, S_IRUGO, show_psu_psoc, 0, ++ PSOC_PSU_OFF (psu2_vin)); ++static SENSOR_DEVICE_ATTR (psoc_psu2_vout, S_IRUGO, show_psu_psoc, 0, ++ PSOC_PSU_OFF (psu2_vout)); ++static SENSOR_DEVICE_ATTR (psoc_psu2_iin, S_IRUGO, show_psu_psoc, 0, ++ PSOC_PSU_OFF (psu2_iin)); ++static SENSOR_DEVICE_ATTR (psoc_psu2_iout, S_IRUGO, show_psu_psoc, 0, ++ PSOC_PSU_OFF (psu2_iout)); ++static SENSOR_DEVICE_ATTR (psoc_psu2_pin, S_IRUGO, show_psu_psoc, 0, ++ PSOC_PSU_OFF (psu2_pin)); ++static SENSOR_DEVICE_ATTR (psoc_psu2_pout, S_IRUGO, show_psu_psoc, 0, ++ PSOC_PSU_OFF (psu2_pout)); ++ ++static SENSOR_DEVICE_ATTR (in2_input, S_IRUGO, show_psu_psoc, 0, ++ PSOC_PSU_OFF (psu2_vin)); ++static SENSOR_DEVICE_ATTR (curr2_input, S_IRUGO, show_psu_psoc, 0, ++ PSOC_PSU_OFF (psu2_iin)); ++static SENSOR_DEVICE_ATTR (power2_input, S_IRUGO, show_psu_psoc, 0, ++ PSOC_PSU_OFF (psu2_pin)); ++static SENSOR_DEVICE_ATTR (in4_input, S_IRUGO, show_psu_psoc, 0, ++ PSOC_PSU_OFF (psu2_vout)); ++static SENSOR_DEVICE_ATTR (curr4_input, S_IRUGO, show_psu_psoc, 0, ++ PSOC_PSU_OFF (psu2_iout)); ++static SENSOR_DEVICE_ATTR (power4_input, S_IRUGO, show_psu_psoc, 0, ++ PSOC_PSU_OFF (psu2_pout)); ++ ++//IPMI ++static SENSOR_DEVICE_ATTR (thermal2_psu1, S_IRUGO, show_ipmi_pmbus, 0, ++ PSU1 | PMBus_Temp2); ++static SENSOR_DEVICE_ATTR (temp9_input, S_IRUGO, show_ipmi_pmbus, 0, ++ PSU1 | PMBus_Temp2); ++ ++static SENSOR_DEVICE_ATTR (psoc_psu1_vendor, S_IRUGO, show_ipmi_pmbus, 0, ++ PSU1 | PMBus_Vendor); ++static SENSOR_DEVICE_ATTR (psoc_psu1_serial, S_IRUGO, show_ipmi_pmbus, 0, ++ PSU1 | PMBus_Serial); ++static SENSOR_DEVICE_ATTR (psoc_psu1_version, S_IRUGO, show_ipmi_pmbus, 0, ++ PSU1 | PMBus_Version); ++ ++static SENSOR_DEVICE_ATTR (thermal2_psu2, S_IRUGO, show_ipmi_pmbus, 0, ++ PSU2 | PMBus_Temp2); ++static SENSOR_DEVICE_ATTR (temp10_input, S_IRUGO, show_ipmi_pmbus, 0, ++ PSU2 | PMBus_Temp2); ++static SENSOR_DEVICE_ATTR (psoc_psu2_vendor, S_IRUGO, show_ipmi_pmbus, 0, ++ PSU2 | PMBus_Vendor); ++static SENSOR_DEVICE_ATTR (psoc_psu2_serial, S_IRUGO, show_ipmi_pmbus, 0, ++ PSU2 | PMBus_Serial); ++static SENSOR_DEVICE_ATTR (psoc_psu2_version, S_IRUGO, show_ipmi_pmbus, 0, ++ PSU2 | PMBus_Version); ++ ++//CLEI ++#if FAN_CLEI_SUPPORT ++static SENSOR_DEVICE_ATTR (fan1_clei, S_IRUGO, show_clei, 0, FAN1_CLEI_INDEX); ++static SENSOR_DEVICE_ATTR (fan2_clei, S_IRUGO, show_clei, 0, FAN2_CLEI_INDEX); ++static SENSOR_DEVICE_ATTR (fan3_clei, S_IRUGO, show_clei, 0, FAN3_CLEI_INDEX); ++static SENSOR_DEVICE_ATTR (fan4_clei, S_IRUGO, show_clei, 0, FAN4_CLEI_INDEX); ++#if FAN_NUM > 4 ++static SENSOR_DEVICE_ATTR (fan5_clei, S_IRUGO, show_clei, 0, FAN5_CLEI_INDEX); ++#endif ++#endif ++ ++#if PSU_CLEI_SUPPORT ++static SENSOR_DEVICE_ATTR (psu1_clei, S_IRUGO, show_clei, 0, PSU1_CLEI_INDEX); ++static SENSOR_DEVICE_ATTR (psu2_clei, S_IRUGO, show_clei, 0, PSU2_CLEI_INDEX); ++#endif ++ ++static struct attribute *psoc_attributes[] = { ++ //name ++ &dev_attr_name.attr, ++ //thermal ++ &sensor_dev_attr_temp1_input.dev_attr.attr, ++ &sensor_dev_attr_temp2_input.dev_attr.attr, ++ &sensor_dev_attr_temp3_input.dev_attr.attr, ++ &sensor_dev_attr_temp4_input.dev_attr.attr, ++ &sensor_dev_attr_temp5_input.dev_attr.attr, ++ &sensor_dev_attr_thermal_psu1.dev_attr.attr, ++ &sensor_dev_attr_thermal_psu2.dev_attr.attr, ++ ++ &sensor_dev_attr_temp7_input.dev_attr.attr, ++ &sensor_dev_attr_temp8_input.dev_attr.attr, ++ ++ //pwm ++ &sensor_dev_attr_pwm1.dev_attr.attr, ++ &sensor_dev_attr_pwm2.dev_attr.attr, ++ &sensor_dev_attr_pwm3.dev_attr.attr, ++ &sensor_dev_attr_pwm4.dev_attr.attr, ++#if FAN_NUM > 4 ++ &sensor_dev_attr_pwm5.dev_attr.attr, ++#endif ++ &sensor_dev_attr_pwm_psu1.dev_attr.attr, ++ &sensor_dev_attr_pwm_psu2.dev_attr.attr, ++ &sensor_dev_attr_pwm6.dev_attr.attr, ++ &sensor_dev_attr_pwm7.dev_attr.attr, ++ ++ //rpm ++ &sensor_dev_attr_fan1_input.dev_attr.attr, ++ &sensor_dev_attr_fan2_input.dev_attr.attr, ++ &sensor_dev_attr_fan3_input.dev_attr.attr, ++ &sensor_dev_attr_fan4_input.dev_attr.attr, ++ &sensor_dev_attr_fan5_input.dev_attr.attr, ++ &sensor_dev_attr_fan6_input.dev_attr.attr, ++ &sensor_dev_attr_fan7_input.dev_attr.attr, ++ &sensor_dev_attr_fan8_input.dev_attr.attr, ++#if FAN_NUM > 4 ++ &sensor_dev_attr_fan9_input.dev_attr.attr, ++ &sensor_dev_attr_fan10_input.dev_attr.attr, ++#endif ++ &sensor_dev_attr_rpm_psu1.dev_attr.attr, ++ &sensor_dev_attr_rpm_psu2.dev_attr.attr, ++ &sensor_dev_attr_fan11_input.dev_attr.attr, ++ &sensor_dev_attr_fan12_input.dev_attr.attr, ++ //switch temperature ++ &sensor_dev_attr_switch_tmp.dev_attr.attr, ++ &sensor_dev_attr_temp6_input.dev_attr.attr, ++ ++ //diag flag ++ &sensor_dev_attr_diag.dev_attr.attr, ++ ++ //version ++ &sensor_dev_attr_version.dev_attr.attr, ++ ++ //fan led ++ &sensor_dev_attr_fan_led_grn1.dev_attr.attr, ++ &sensor_dev_attr_fan_led_grn2.dev_attr.attr, ++ &sensor_dev_attr_fan_led_grn3.dev_attr.attr, ++ &sensor_dev_attr_fan_led_grn4.dev_attr.attr, ++ &sensor_dev_attr_fan_led_red1.dev_attr.attr, ++ &sensor_dev_attr_fan_led_red2.dev_attr.attr, ++ &sensor_dev_attr_fan_led_red3.dev_attr.attr, ++ &sensor_dev_attr_fan_led_red4.dev_attr.attr, ++#if FAN_NUM >4 ++ &sensor_dev_attr_fan_led_grn5.dev_attr.attr, ++ &sensor_dev_attr_fan_led_red5.dev_attr.attr, ++ &sensor_dev_attr_fan_gpi2.dev_attr.attr, ++#endif ++ //fan GPI ++ &sensor_dev_attr_fan_gpi.dev_attr.attr, ++ &sensor_dev_attr_psu1.dev_attr.attr, ++ &sensor_dev_attr_psu2.dev_attr.attr, ++ ++ ++ //psu_psoc ++ &sensor_dev_attr_psoc_psu1_vin.dev_attr.attr, ++ &sensor_dev_attr_psoc_psu1_vout.dev_attr.attr, ++ &sensor_dev_attr_psoc_psu1_iin.dev_attr.attr, ++ &sensor_dev_attr_psoc_psu1_iout.dev_attr.attr, ++ &sensor_dev_attr_psoc_psu1_pin.dev_attr.attr, ++ &sensor_dev_attr_psoc_psu1_pout.dev_attr.attr, ++ &sensor_dev_attr_psoc_psu2_vin.dev_attr.attr, ++ &sensor_dev_attr_psoc_psu2_vout.dev_attr.attr, ++ &sensor_dev_attr_psoc_psu2_iin.dev_attr.attr, ++ &sensor_dev_attr_psoc_psu2_iout.dev_attr.attr, ++ &sensor_dev_attr_psoc_psu2_pin.dev_attr.attr, ++ &sensor_dev_attr_psoc_psu2_pout.dev_attr.attr, ++ ++ &sensor_dev_attr_in1_input.dev_attr.attr, ++ &sensor_dev_attr_curr1_input.dev_attr.attr, ++ &sensor_dev_attr_power1_input.dev_attr.attr, ++ &sensor_dev_attr_in2_input.dev_attr.attr, ++ &sensor_dev_attr_curr2_input.dev_attr.attr, ++ &sensor_dev_attr_power2_input.dev_attr.attr, ++ &sensor_dev_attr_in3_input.dev_attr.attr, ++ &sensor_dev_attr_curr3_input.dev_attr.attr, ++ &sensor_dev_attr_power3_input.dev_attr.attr, ++ &sensor_dev_attr_in4_input.dev_attr.attr, ++ &sensor_dev_attr_curr4_input.dev_attr.attr, ++ &sensor_dev_attr_power4_input.dev_attr.attr, ++ ++ //ipmi_i2c_command ++ &sensor_dev_attr_thermal2_psu1.dev_attr.attr, ++ &sensor_dev_attr_temp9_input.dev_attr.attr, ++ &sensor_dev_attr_psoc_psu1_vendor.dev_attr.attr, ++ &sensor_dev_attr_psoc_psu1_serial.dev_attr.attr, ++ &sensor_dev_attr_psoc_psu1_version.dev_attr.attr, ++ ++ &sensor_dev_attr_thermal2_psu2.dev_attr.attr, ++ &sensor_dev_attr_temp10_input.dev_attr.attr, ++ &sensor_dev_attr_psoc_psu2_vendor.dev_attr.attr, ++ &sensor_dev_attr_psoc_psu2_serial.dev_attr.attr, ++ &sensor_dev_attr_psoc_psu2_version.dev_attr.attr, ++ ++ //clei ++#if FAN_CLEI_SUPPORT ++ &sensor_dev_attr_fan1_clei.dev_attr.attr, ++ &sensor_dev_attr_fan2_clei.dev_attr.attr, ++ &sensor_dev_attr_fan3_clei.dev_attr.attr, ++ &sensor_dev_attr_fan4_clei.dev_attr.attr, ++#if FAN_NUM > 4 ++ &sensor_dev_attr_fan5_clei.dev_attr.attr, ++#endif ++#endif ++ ++#if PSU_CLEI_SUPPORT ++ &sensor_dev_attr_psu1_clei.dev_attr.attr, ++ &sensor_dev_attr_psu2_clei.dev_attr.attr, ++#endif ++ NULL ++}; ++ ++static const struct attribute_group psoc_group = { ++ .attrs = psoc_attributes, ++}; ++ ++//================================= ++static void check_switch_temp (void) ++{ ++ static struct file *f; ++ mm_segment_t old_fs; ++ ++ set_fs (get_ds ()); ++ f = filp_open (SWITCH_TEMPERATURE_SOCK, O_RDONLY, 0644); ++ if (IS_ERR (f)) ++ { ++ return; ++ } ++ else ++ { ++ char temp_str[] = { 0, 0, 0, 0, 0, 0, 0 }; ++ loff_t pos = 0; ++ u16 temp2 = 0; ++ old_fs = get_fs (); ++ set_fs (KERNEL_DS); ++ vfs_read (f, temp_str, 6, &pos); ++ temp2 = ((simple_strtoul (temp_str, NULL, 10) / 1000) << 8) & 0xFF00; ++ psoc_ipmi_write ((u8 *) & temp2, SWITCH_TMP_OFFSET, 2); ++ } ++ filp_close (f, NULL); ++ set_fs (old_fs); ++} ++ ++static int psoc_polling_thread (void *p) ++{ ++ while (!kthread_should_stop ()) ++ { ++ check_switch_temp (); ++ set_current_state (TASK_INTERRUPTIBLE); ++ if (kthread_should_stop ()) ++ break; ++ ++ schedule_timeout (msecs_to_jiffies (PSOC_POLLING_PERIOD)); ++ } ++ return 0; ++} ++ ++static int __init nb_psoc_init (void) ++{ ++ int ret; ++ ++ hwmon_dev = hwmon_device_register (NULL); ++ if (IS_ERR (hwmon_dev)) ++ { ++ goto fail_hwmon_device_register; ++ } ++ ++ device_kobj = kobject_create_and_add ("device", &hwmon_dev->kobj); ++ if (!device_kobj) ++ { ++ goto fail_hwmon_device_register; ++ } ++ ++ ret = sysfs_create_group (device_kobj, &psoc_group); ++ if (ret) ++ { ++ goto fail_create_group_hwmon; ++ } ++ ++ ret = sysfs_create_group (&hwmon_dev->kobj, &psoc_group); ++ if (ret) ++ { ++ goto fail_create_group_hwmon; ++ } ++ ++ kthread_auto_update = kthread_run (psoc_polling_thread, NULL, "BMC_DRIVER"); ++ if (IS_ERR (kthread_auto_update)) ++ { ++ goto fail_create_group_hwmon; ++ } ++ return ret; ++ ++ fail_create_group_hwmon: ++ hwmon_device_unregister (hwmon_dev); ++ fail_hwmon_device_register: ++ return -ENOMEM; ++} ++ ++static void __exit nb_psoc_exit (void) ++{ ++ kthread_stop (kthread_auto_update); ++ if (ipmi_mh_user != NULL) ++ { ++ ipmi_destroy_user (ipmi_mh_user); ++ } ++ sysfs_remove_group (device_kobj, &psoc_group); ++ if (hwmon_dev != NULL) ++ hwmon_device_unregister (hwmon_dev); ++} ++ ++MODULE_AUTHOR ("support "); ++MODULE_DESCRIPTION ("nb psoc driver"); ++MODULE_LICENSE ("GPL"); ++ ++module_init (nb_psoc_init); ++module_exit (nb_psoc_exit); +-- +2.7.4 + diff --git a/machine/netberg/netberg_aurora_610/kernel/config b/machine/netberg/netberg_aurora_610/kernel/config new file mode 100644 index 000000000..8590d2e90 --- /dev/null +++ b/machine/netberg/netberg_aurora_610/kernel/config @@ -0,0 +1,51 @@ +CONFIG_LOG_BUF_SHIFT=14 +CONFIG_MODULES=y +CONFIG_MODULE_FORCE_LOAD=y +CONFIG_MODULE_UNLOAD=y +CONFIG_MODULE_FORCE_UNLOAD=y +CONFIG_MODVERSIONS=y +CONFIG_ACPI_IPMI=y +CONFIG_PCI_MMCONFIG=y +CONFIG_CHR_DEV_SG=y +CONFIG_SCSI_WAIT_SCAN=m +CONFIG_MDIO=y +CONFIG_IXGB=y +CONFIG_IXGBE=y +CONFIG_SERIAL_8250_NR_UARTS=2 +CONFIG_IPMI_HANDLER=y +CONFIG_IPMI_PANIC_EVENT=y +CONFIG_IPMI_DEVICE_INTERFACE=y +CONFIG_IPMI_SI=y +CONFIG_IPMI_WATCHDOG=m +CONFIG_IPMI_POWEROFF=m +CONFIG_I2C_ALGOBIT=y +CONFIG_I2C_I801=y +CONFIG_I2C_GPIO=y +CONFIG_MFD_CORE=y +CONFIG_USB_DEVICEFS=y +CONFIG_USB_MON=y +CONFIG_NETBERG_AURORA_610=y +CONFIG_ISO9660_FS=y +CONFIG_GPIO_ICH=y +CONFIG_LPC_ICH=y +# CONFIG_SYSFS_DEPRECATED is not set +# CONFIG_KPROBES is not set +# CONFIG_MODULE_SRCVERSION_ALL is not set +# CONFIG_X86_PAT is not set +# CONFIG_BPF_JIT is not set +# CONFIG_MTD_TESTS is not set +# CONFIG_E1000 is not set +# CONFIG_E1000E is not set +# CONFIG_IXGBE_HWMON is not set +# CONFIG_IXGBE_DCB is not set +# CONFIG_IPMI_PANIC_STRING is not set +# CONFIG_IPMI_SSIF is not set +# CONFIG_I2C_SMBUS is not set +# CONFIG_I2C_STUB is not set +# CONFIG_SENSORS_IBMAEM is not set +# CONFIG_SENSORS_IBMPEX is not set +# CONFIG_JOLIET is not set +# CONFIG_ZISOFS is not set +# CONFIG_DEBUG_SET_MODULE_RONX is not set +# CONFIG_DEBUG_NX_TEST is not set +# CONFIG_CRYPTO_TEST is not set diff --git a/machine/netberg/netberg_aurora_610/kernel/kernel-ich-gpio.patch b/machine/netberg/netberg_aurora_610/kernel/kernel-ich-gpio.patch new file mode 100644 index 000000000..7173120eb --- /dev/null +++ b/machine/netberg/netberg_aurora_610/kernel/kernel-ich-gpio.patch @@ -0,0 +1,25 @@ +diff --git a/drivers/gpio/gpio-ich.c b/drivers/gpio/gpio-ich.c +index 4f6d6435..4415d5d8 100644 +--- a/drivers/gpio/gpio-ich.c ++++ b/drivers/gpio/gpio-ich.c +@@ -109,7 +109,7 @@ static struct { + int outlvl_cache[3]; /* cached output values */ + } ichx_priv; + +-static int modparam_gpiobase = -1; /* dynamic */ ++static int modparam_gpiobase = 0; /* Default: -1 dynamic */ + module_param_named(gpiobase, modparam_gpiobase, int, 0444); + MODULE_PARM_DESC(gpiobase, "The GPIO number base. -1 means dynamic, " + "which is the default."); +diff --git a/drivers/mfd/lpc_ich.c b/drivers/mfd/lpc_ich.c +index c8dee47b..64738c49 100644 +--- a/drivers/mfd/lpc_ich.c ++++ b/drivers/mfd/lpc_ich.c +@@ -493,6 +493,7 @@ static struct lpc_ich_info lpc_chipset_info[] = { + [LPC_LPT] = { + .name = "Lynx Point", + .iTCO_version = 2, ++ .gpio_version = ICH_V5_GPIO, + }, + [LPC_LPT_LP] = { + .name = "Lynx Point_LP", diff --git a/machine/netberg/netberg_aurora_610/kernel/series b/machine/netberg/netberg_aurora_610/kernel/series new file mode 100644 index 000000000..ea37a75c8 --- /dev/null +++ b/machine/netberg/netberg_aurora_610/kernel/series @@ -0,0 +1,2 @@ +0001-Netberg-Aurora-610-associate-platform-drive.patch +kernel-ich-gpio.patch diff --git a/machine/netberg/netberg_aurora_610/machine.make b/machine/netberg/netberg_aurora_610/machine.make new file mode 100644 index 000000000..783bee6bb --- /dev/null +++ b/machine/netberg/netberg_aurora_610/machine.make @@ -0,0 +1,54 @@ +# Netberg Aurora 610 +# CPU Module: Intel Broadwell_DE (C2000) + +ONIE_ARCH ?= x86_64 +SWITCH_ASIC_VENDOR = bcm +UEFI_ENABLE = yes + +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 +VENDOR_ID = 50424 + +# Skip the i2ctools and the onie-syseeprom command for this platform +I2CTOOLS_ENABLE = yes + +# Set the desired kernel version. +LINUX_VERSION = 4.9 +LINUX_MINOR_VERSION = 95 + +# Use gcc-6.3.0 +GCC_VERSION = 6.3.0 + +# +# Console parameters can be defined here +# - default values are in build-config/arch/x86_64.make +# - template files are build-config/recovery/syslinux.cfg and build-config/recovery/grub-pxe.cfg +# +CONSOLE_FLAG = 1 +CONSOLE_DEV = 0 + +# +# rootdelay parameter (only for nos) +# +ROOTDELAY = 5 + +# +# Use IPMITOOL +# +IPMITOOL_ENABLE = yes + +#------------------------------------------------------------------------------- +# +# Local Variables: +# mode: makefile-gmake +# End: