[Nokia-7215-A1]Update Nokia-7215-A1 Platform (#18147)

1) Update Nokia-7215-A1 platform to address UT and OC test failures
2) Enable watchdog service
3) EZB files for SAI upgrade
This commit is contained in:
Pavan-Nokia 2024-03-04 13:53:00 -05:00 committed by GitHub
parent 0c6b143e00
commit d4ca86bf9d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
31 changed files with 1034 additions and 785 deletions

View File

@ -1 +1 @@
ee44e299ca857b9f0abf2e804ec4850f 4983b60d1d68623c202b91093f3730db

View File

@ -1 +1 @@
8d006b7a29c75f81b641df68102a6aa3 48c76e16726ad2b1cb797c55c477fc30

View File

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<data xmlns="urn:ietf:params:xml:ns:netconf:base:1.0" version="2023-05-05-1.04" profile="Askl1" dsig="md5"> <data xmlns="urn:ietf:params:xml:ns:netconf:base:1.0" version="2023-11-20-1.05" profile="Askl1" sid="a9deb744-f6cb-4675-bab3-11132e7db1cd">
<ASKL1plt:ASK-L1 xmlns:ASKL1plt="urn:marvell:ASKL1:yang"> <ASKL1plt:ASK-L1 xmlns:ASKL1plt="urn:marvell:ASKL1:yang">
<ASKL1plt:typedefs> <ASKL1plt:typedefs>
<ASKL1plt:typedef> <ASKL1plt:typedef>

View File

@ -1 +1 @@
b42f2a2be9da6c7752c0807f9dee48bf d36319f76733ae8593e31f3231599936

View File

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<data xmlns="urn:ietf:params:xml:ns:netconf:base:1.0" version="2023-05-05-1.04" profile="Askpp" dsig="md5"> <data xmlns="urn:ietf:params:xml:ns:netconf:base:1.0" version="2023-11-20-1.05" profile="Askpp" sid="fdf5b1c2-b80a-47a6-ac37-47e174286524">
<askppplt:ASK-PP xmlns:askppplt="urn:marvell:askpp:yang"> <askppplt:ASK-PP xmlns:askppplt="urn:marvell:askpp:yang">
<askppplt:typedefs> <askppplt:typedefs>
<askppplt:typedef> <askppplt:typedef>
@ -357,28 +357,28 @@
<askppplt:enum> <askppplt:enum>
<askppplt:name>NATIVE</askppplt:name> <askppplt:name>NATIVE</askppplt:name>
<askppplt:description>NATIVE <askppplt:description>NATIVE
* the trunk members are filled * the trunk members are filled
* according to the order given by application. * according to the order given by application.
* Regular trunk may hold max of 8 members. * Regular trunk may hold max of 8 members.
* Cascade trunk may hold : * Cascade trunk may hold :
* max of 64 members</askppplt:description> * max of 64 members</askppplt:description>
<askppplt:value>0</askppplt:value> <askppplt:value>0</askppplt:value>
</askppplt:enum> </askppplt:enum>
<askppplt:enum> <askppplt:enum>
<askppplt:name>FLEX</askppplt:name> <askppplt:name>FLEX</askppplt:name>
<askppplt:description>FLEX <askppplt:description>FLEX
* A mode to allows flexibility for * A mode to allows flexibility for
* each Regular trunk to state it's max number of members (before starting to add members). * each Regular trunk to state it's max number of members (before starting to add members).
* (this mode not effect 'cascade trunk' members) * (this mode not effect 'cascade trunk' members)
* Regular trunk may hold : max of 4K members. (each trunk set it's own limit) * Regular trunk may hold : max of 4K members. (each trunk set it's own limit)
* Cascade trunk may hold : max of 64 members.</askppplt:description> * Cascade trunk may hold : max of 64 members.</askppplt:description>
<askppplt:value>2</askppplt:value> <askppplt:value>2</askppplt:value>
</askppplt:enum> </askppplt:enum>
</askppplt:typedef> </askppplt:typedef>
<askppplt:typedef> <askppplt:typedef>
<askppplt:name>number-physical-port-type</askppplt:name> <askppplt:name>number-physical-port-type</askppplt:name>
<askppplt:type>enumeration</askppplt:type> <askppplt:type>enumeration</askppplt:type>
<askppplt:description>ac5x 128, falcon 64,128,256, 512, 1024</askppplt:description> <askppplt:description>AC3X/AC5X 128, falcon 64, 128, 256, 512, 1024</askppplt:description>
<askppplt:enum> <askppplt:enum>
<askppplt:name>no-ports</askppplt:name> <askppplt:name>no-ports</askppplt:name>
<askppplt:description>no-ports</askppplt:description> <askppplt:description>no-ports</askppplt:description>

View File

@ -1 +1 @@
b43a871130f9e59ac21a74940574558f 1ff8c65eb4b5dfff5d2c9be67401c723

View File

@ -1,13 +1,13 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<data xmlns="urn:ietf:params:xml:ns:netconf:base:1.0" version="2023-05-05-1.04" profile="SAI" dsig="md5"> <data xmlns="urn:ietf:params:xml:ns:netconf:base:1.0" version="2024-01-08-1.05" profile="SAI" sid="fd56a8b4-6b41-4ead-9a27-c491bc2f95b9">
<SAIplt:SAI xmlns:SAIplt="urn:marvell:SAI:yang"> <SAIplt:SAI xmlns:SAIplt="urn:marvell:SAI:yang">
<SAIplt:typedefs> <SAIplt:typedefs>
<SAIplt:typedef> <SAIplt:typedef>
<SAIplt:name>device-id-type</SAIplt:name> <SAIplt:name>device-id-type</SAIplt:name>
<SAIplt:type>uint32</SAIplt:type> <SAIplt:type>uint32</SAIplt:type>
<SAIplt:description>Device ID 0..1023</SAIplt:description> <SAIplt:description>Device ID 0..1</SAIplt:description>
<SAIplt:min>0</SAIplt:min> <SAIplt:min>0</SAIplt:min>
<SAIplt:max>1023</SAIplt:max> <SAIplt:max>1</SAIplt:max>
</SAIplt:typedef> </SAIplt:typedef>
<SAIplt:typedef> <SAIplt:typedef>
<SAIplt:name>port-id-type</SAIplt:name> <SAIplt:name>port-id-type</SAIplt:name>
@ -22,7 +22,7 @@
<SAIplt:description>Logging Feature Options</SAIplt:description> <SAIplt:description>Logging Feature Options</SAIplt:description>
<SAIplt:enum> <SAIplt:enum>
<SAIplt:name>SAI_LOG_SYSLOG</SAIplt:name> <SAIplt:name>SAI_LOG_SYSLOG</SAIplt:name>
<SAIplt:description>SYSLOG {Syslog service should be running to use this option}</SAIplt:description> <SAIplt:description>SYSLOG {Syslog service should be running to use this option}</SAIplt:description>
<SAIplt:value>0</SAIplt:value> <SAIplt:value>0</SAIplt:value>
</SAIplt:enum> </SAIplt:enum>
<SAIplt:enum> <SAIplt:enum>
@ -32,7 +32,7 @@
</SAIplt:enum> </SAIplt:enum>
<SAIplt:enum> <SAIplt:enum>
<SAIplt:name>SAI_LOG_FILE</SAIplt:name> <SAIplt:name>SAI_LOG_FILE</SAIplt:name>
<SAIplt:description>FILE {Warning !!! Use with caution. Can cause disk full issues}</SAIplt:description> <SAIplt:description>FILE {Warning !!! Use with caution. Can cause disk full issues}</SAIplt:description>
<SAIplt:value>2</SAIplt:value> <SAIplt:value>2</SAIplt:value>
</SAIplt:enum> </SAIplt:enum>
</SAIplt:typedef> </SAIplt:typedef>
@ -43,11 +43,93 @@
<SAIplt:min>2</SAIplt:min> <SAIplt:min>2</SAIplt:min>
<SAIplt:max>30</SAIplt:max> <SAIplt:max>30</SAIplt:max>
</SAIplt:typedef> </SAIplt:typedef>
<SAIplt:typedef>
<SAIplt:name>acl-feature-name-type</SAIplt:name>
<SAIplt:type>enumeration</SAIplt:type>
<SAIplt:description/>
<SAIplt:enum>
<SAIplt:name>port-sFlow</SAIplt:name>
<SAIplt:description>SFlow over Port</SAIplt:description>
<SAIplt:value>0</SAIplt:value>
</SAIplt:enum>
<SAIplt:enum>
<SAIplt:name>port-counters-ipv4-ipv6</SAIplt:name>
<SAIplt:description>Port ipv4/ipv6 counters</SAIplt:description>
<SAIplt:value>1</SAIplt:value>
</SAIplt:enum>
<SAIplt:enum>
<SAIplt:name>control-acl</SAIplt:name>
<SAIplt:description>ACLs for control packet handling</SAIplt:description>
<SAIplt:value>2</SAIplt:value>
</SAIplt:enum>
</SAIplt:typedef>
<SAIplt:typedef>
<SAIplt:name>ingress-acl-stage-type</SAIplt:name>
<SAIplt:type>enumeration</SAIplt:type>
<SAIplt:description/>
<SAIplt:enum>
<SAIplt:name>disabled</SAIplt:name>
<SAIplt:description>Feature not enabled</SAIplt:description>
<SAIplt:value>0</SAIplt:value>
</SAIplt:enum>
<SAIplt:enum>
<SAIplt:name>IPCL0</SAIplt:name>
<SAIplt:description>Stage IPCL0</SAIplt:description>
<SAIplt:value>1</SAIplt:value>
</SAIplt:enum>
<SAIplt:enum>
<SAIplt:name>IPCL1</SAIplt:name>
<SAIplt:description>Stage IPCL1</SAIplt:description>
<SAIplt:value>2</SAIplt:value>
</SAIplt:enum>
</SAIplt:typedef>
<SAIplt:typedef>
<SAIplt:name>egress-acl-stage-type</SAIplt:name>
<SAIplt:type>enumeration</SAIplt:type>
<SAIplt:description/>
<SAIplt:enum>
<SAIplt:name>disabled</SAIplt:name>
<SAIplt:description>Feature not enabled</SAIplt:description>
<SAIplt:value>0</SAIplt:value>
</SAIplt:enum>
<SAIplt:enum>
<SAIplt:name>EPCL0</SAIplt:name>
<SAIplt:description>Stage EPCL0</SAIplt:description>
<SAIplt:value>2</SAIplt:value>
</SAIplt:enum>
</SAIplt:typedef>
<SAIplt:typedef>
<SAIplt:name>feature-priority-type</SAIplt:name>
<SAIplt:type>uint32</SAIplt:type>
<SAIplt:description>Feature priority</SAIplt:description>
<SAIplt:min>2</SAIplt:min>
<SAIplt:max>15</SAIplt:max>
</SAIplt:typedef>
<SAIplt:typedef>
<SAIplt:name>hit-number-type</SAIplt:name>
<SAIplt:type>uint32</SAIplt:type>
<SAIplt:description>Hit/lookup number</SAIplt:description>
<SAIplt:min>0</SAIplt:min>
<SAIplt:max>3</SAIplt:max>
</SAIplt:typedef>
<SAIplt:typedef>
<SAIplt:name>asic-type</SAIplt:name>
<SAIplt:type>enumeration</SAIplt:type>
<SAIplt:description>ASIC Type</SAIplt:description>
<SAIplt:enum>
<SAIplt:name>ASIC_AC3X</SAIplt:name>
<SAIplt:description>AC3X</SAIplt:description>
<SAIplt:value>0</SAIplt:value>
</SAIplt:enum>
<SAIplt:enum>
<SAIplt:name>ASIC_AC5X</SAIplt:name>
<SAIplt:description>AC5X</SAIplt:description>
<SAIplt:value>1</SAIplt:value>
</SAIplt:enum>
</SAIplt:typedef>
</SAIplt:typedefs> </SAIplt:typedefs>
<SAIplt:ASIC_Type SAIplt:type="asic-type">ASIC_AC5X</SAIplt:ASIC_Type>
<SAIplt:ASK-BOARD-Profile-Name SAIplt:type="string">ASK-Board-AC5X-xb.xml</SAIplt:ASK-BOARD-Profile-Name> <SAIplt:ASK-BOARD-Profile-Name SAIplt:type="string">ASK-Board-AC5X-xb.xml</SAIplt:ASK-BOARD-Profile-Name>
<SAIplt:Features>
<SAIplt:RoCE SAIplt:type="boolean">false</SAIplt:RoCE>
</SAIplt:Features>
<SAIplt:Ports> <SAIplt:Ports>
<SAIplt:port-list> <SAIplt:port-list>
<SAIplt:sai_port_id SAIplt:type="port-id-type">0</SAIplt:sai_port_id> <SAIplt:sai_port_id SAIplt:type="port-id-type">0</SAIplt:sai_port_id>
@ -310,7 +392,7 @@
<SAIplt:sdk_port_id SAIplt:type="port-id-type">51</SAIplt:sdk_port_id> <SAIplt:sdk_port_id SAIplt:type="port-id-type">51</SAIplt:sdk_port_id>
</SAIplt:port-list> </SAIplt:port-list>
</SAIplt:Ports> </SAIplt:Ports>
<SAIplt:Scaling> <SAIplt:scalingAC5>
<SAIplt:max_lag_members SAIplt:type="uint32">8</SAIplt:max_lag_members> <SAIplt:max_lag_members SAIplt:type="uint32">8</SAIplt:max_lag_members>
<SAIplt:max_route_ipv4 SAIplt:type="uint32">0</SAIplt:max_route_ipv4> <SAIplt:max_route_ipv4 SAIplt:type="uint32">0</SAIplt:max_route_ipv4>
<SAIplt:max_route_ipv6 SAIplt:type="uint32">0</SAIplt:max_route_ipv6> <SAIplt:max_route_ipv6 SAIplt:type="uint32">0</SAIplt:max_route_ipv6>
@ -320,9 +402,45 @@
<SAIplt:max_tti SAIplt:type="uint32">1024</SAIplt:max_tti> <SAIplt:max_tti SAIplt:type="uint32">1024</SAIplt:max_tti>
<SAIplt:wred_size SAIplt:type="uint32">0</SAIplt:wred_size> <SAIplt:wred_size SAIplt:type="uint32">0</SAIplt:wred_size>
<SAIplt:max_nat SAIplt:type="uint32">0</SAIplt:max_nat> <SAIplt:max_nat SAIplt:type="uint32">0</SAIplt:max_nat>
</SAIplt:Scaling> </SAIplt:scalingAC5>
<SAIplt:Logging> <SAIplt:Logging>
<SAIplt:log_dest SAIplt:type="logDest-type">SAI_LOG_SYSLOG</SAIplt:log_dest> <SAIplt:log_dest SAIplt:type="logDest-type">SAI_LOG_SYSLOG</SAIplt:log_dest>
</SAIplt:Logging> </SAIplt:Logging>
<SAIplt:Features-using-acl>
<SAIplt:feature SAIplt:type="acl-feature-name-type">control-acl</SAIplt:feature>
<SAIplt:feature-priority SAIplt:type="feature-priority-type">2</SAIplt:feature-priority>
<SAIplt:Ingress>
<SAIplt:ingress-stage SAIplt:type="ingress-acl-stage-type">IPCL0</SAIplt:ingress-stage>
<SAIplt:hit-number SAIplt:type="hit-number-type">1</SAIplt:hit-number>
</SAIplt:Ingress>
<SAIplt:Egress>
<SAIplt:egress-stage SAIplt:type="egress-acl-stage-type">EPCL0</SAIplt:egress-stage>
<SAIplt:hit-number SAIplt:type="hit-number-type">0</SAIplt:hit-number>
</SAIplt:Egress>
</SAIplt:Features-using-acl>
<SAIplt:Features-using-acl>
<SAIplt:feature SAIplt:type="acl-feature-name-type">port-sFlow</SAIplt:feature>
<SAIplt:feature-priority SAIplt:type="feature-priority-type">3</SAIplt:feature-priority>
<SAIplt:Ingress>
<SAIplt:ingress-stage SAIplt:type="ingress-acl-stage-type">IPCL0</SAIplt:ingress-stage>
<SAIplt:hit-number SAIplt:type="hit-number-type">0</SAIplt:hit-number>
</SAIplt:Ingress>
<SAIplt:Egress>
<SAIplt:egress-stage SAIplt:type="egress-acl-stage-type">EPCL0</SAIplt:egress-stage>
<SAIplt:hit-number SAIplt:type="hit-number-type">0</SAIplt:hit-number>
</SAIplt:Egress>
</SAIplt:Features-using-acl>
<SAIplt:Features-using-acl>
<SAIplt:feature SAIplt:type="acl-feature-name-type">port-counters-ipv4-ipv6</SAIplt:feature>
<SAIplt:feature-priority SAIplt:type="feature-priority-type">4</SAIplt:feature-priority>
<SAIplt:Ingress>
<SAIplt:ingress-stage SAIplt:type="ingress-acl-stage-type">IPCL0</SAIplt:ingress-stage>
<SAIplt:hit-number SAIplt:type="hit-number-type">3</SAIplt:hit-number>
</SAIplt:Ingress>
<SAIplt:Egress>
<SAIplt:egress-stage SAIplt:type="egress-acl-stage-type">EPCL0</SAIplt:egress-stage>
<SAIplt:hit-number SAIplt:type="hit-number-type">0</SAIplt:hit-number>
</SAIplt:Egress>
</SAIplt:Features-using-acl>
</SAIplt:SAI> </SAIplt:SAI>
</data> </data>

View File

@ -1,2 +1 @@
VAR_LOG_SIZE=4096
ONIE_PLATFORM_EXTRA_CMDLINE_LINUX="default_hugepagesz=32M hugepages=4 loglevel=4" ONIE_PLATFORM_EXTRA_CMDLINE_LINUX="default_hugepagesz=32M hugepages=4 loglevel=4"

View File

@ -0,0 +1,10 @@
- bus: '00'
dev: '00'
fn: '0'
id: '0110'
name: 'PCI bridge: Marvell Technology Group Ltd. 88F60x0/88F70x0/88F80x0/CN913x ARM SoC'
- bus: '01'
dev: '00'
fn: '0'
id: '9821'
name: 'Ethernet controller: Marvell Technology Group Ltd. Device 9821'

View File

@ -97,17 +97,22 @@
"high-crit-threshold": false "high-crit-threshold": false
}, },
{ {
"name": "AC5X CORE", "name": "PCB MID",
"controllable": false, "controllable": false,
"low-threshold": false, "low-threshold": false,
"low-crit-threshold": false, "low-crit-threshold": false,
"high-crit-threshold": false "high-crit-threshold": false
}, },
{ {
"name": "OOB PHY", "name": "ASIC",
"controllable": false,
"low-threshold": false,
"low-crit-threshold": false
},
{
"name": "CPU CORE",
"controllable": false, "controllable": false,
"low-threshold": false, "low-threshold": false,
"high-threshold": false,
"low-crit-threshold": false "low-crit-threshold": false
} }
], ],

View File

@ -1,11 +1,13 @@
#!/bin/bash #!/bin/bash
function SafePwrCycle() { function SafeReboot() {
sync ; sync sync ; sync
sudo umount -fa > /dev/null 2&>1 sudo umount -fa > /dev/null 2&>1
# Write CPLD register to initiate cold reboot # Turn off watchdog monitor gpio for correct reboot-cause
sudo echo 0 > /sys/bus/i2c/devices/i2c-0/0-0041/cold_reset sudo echo 1 > /sys/class/gpio/gpio41/value
cat /sys/bus/i2c/devices/0-0041/last_reset_cause > /dev/null 2&>1
exec /sbin/reboot
} }
SafePwrCycle SafeReboot

View File

@ -1,3 +0,0 @@
{
"skip_pcied": true
}

View File

@ -2,9 +2,7 @@
"services_to_ignore": [], "services_to_ignore": [],
"devices_to_ignore": [ "devices_to_ignore": [
"asic", "asic",
"psu.temperature", "psu.temperature"
"fan",
"psu"
], ],
"user_defined_checkers": [], "user_defined_checkers": [],
"polling_interval": 60, "polling_interval": 60,

View File

@ -1 +1 @@
obj-m:= nokia_7215_ixs_a1_cpld.o ac5_thermal_sensor.o obj-m:= nokia_7215_ixs_a1_cpld.o cn9130_cpu_thermal_sensor.o

View File

@ -1,218 +0,0 @@
/*
* HWMON Driver for AC5x thermal sensor
*
* Author: Natarajan Subbiramani <nataraja.subbiramani.ext@nokia.com>
*
* 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 <linux/module.h>
#include <linux/init.h>
#include <linux/miscdevice.h>
#include <linux/hwmon.h>
#include <linux/hwmon-sysfs.h>
#include <linux/err.h>
#include <linux/io.h>
#include <linux/delay.h>
#define AC5_DEFAULT_TEMP_CRIT 100000
#define AC5_DEFAULT_TEMP_MAX 110000
#define AC5_TEMP_BASE_ADDR 0x944F80D0
static unsigned long thermal_base_addr=AC5_TEMP_BASE_ADDR;
module_param(thermal_base_addr, ulong, 0444);
MODULE_PARM_DESC(thermal_base_addr,
"Initialize the base address of the thermal sensor");
struct ac5_thermal_data {
struct device *dev;
struct device *hwmon_dev;
uint8_t * __iomem temp_base;
int temp_input;
int temp_crit;
int temp_max;
};
static long ac5_thermal_read_reg_in_mcelcius(struct device *dev, struct ac5_thermal_data *data)
{
volatile uint8_t * __iomem temp_base = data->temp_base;
uint32_t regval;
long output=data->temp_max;
//STOP MEASUREMENT
writel(0xF0F01034, temp_base);
//delay for 1ms
mdelay(1);
//Read thermal value
regval = readl(temp_base+0xC);
//RE-START MEASUREMENT
writel(0xF0F01035, temp_base);
//Validate data
if(regval & 0x10000) {
//Calibrate it to milli-celcius
output = (regval>> 6) & 0x3FF;
output = ((output*42)-27250)*10;
}
return output;
}
static int ac5_thermal_read(struct device *dev, enum hwmon_sensor_types type,
u32 attr, int channel, long *val)
{
struct ac5_thermal_data *data = dev_get_drvdata(dev);
switch (type) {
case hwmon_temp:
switch (attr) {
case hwmon_temp_input:
*val = ac5_thermal_read_reg_in_mcelcius(dev, data);
break;
case hwmon_temp_crit:
*val = data->temp_crit;
break;
case hwmon_temp_max:
*val = data->temp_max;
break;
default:
return -EINVAL;
}
break;
default:
return -EINVAL;
}
return 0;
}
static int ac5_thermal_write(struct device *dev, enum hwmon_sensor_types type,
u32 attr, int channel, long val)
{
struct ac5_thermal_data *data = dev_get_drvdata(dev);
switch (type) {
case hwmon_temp:
switch (attr) {
case hwmon_temp_crit:
data->temp_crit = val;
break;
case hwmon_temp_max:
data->temp_max = val;
break;
default:
return -EINVAL;
}
break;
default:
return -EINVAL;
}
return 0;
}
static umode_t ac5_thermal_is_visible(const void *data, enum hwmon_sensor_types type,
u32 attr, int channel)
{
switch (type) {
case hwmon_temp:
switch (attr) {
case hwmon_temp_input:
return 0444;
case hwmon_temp_crit:
case hwmon_temp_max:
return 0644;
}
break;
default:
break;
}
return 0;
}
static const struct hwmon_channel_info *ac5_thermal_info[] = {
HWMON_CHANNEL_INFO(temp,
HWMON_T_INPUT | HWMON_T_MAX | HWMON_T_CRIT),
NULL
};
static const struct hwmon_ops ac5_thermal_hwmon_ops = {
.is_visible = ac5_thermal_is_visible,
.read = ac5_thermal_read,
.write = ac5_thermal_write,
};
static const struct hwmon_chip_info ac5_thermal_chip_info = {
.ops = &ac5_thermal_hwmon_ops,
.info = ac5_thermal_info,
};
static const struct file_operations fops = {
.owner = THIS_MODULE,
};
struct miscdevice ac5_thermal_misc_device = {
.minor = TEMP_MINOR,
.name = "ac5_thermal",
.fops = &fops,
};
static int __init ac5_thermal_init_misc_driver(void)
{
struct device *dev;
struct ac5_thermal_data *thermal_data;
int err;
void * __iomem reg;
err = misc_register(&ac5_thermal_misc_device);
if (err) {
pr_err("ac5_thermal misc_register failed!!!\n");
return err;
}
dev = ac5_thermal_misc_device.this_device;
thermal_data = devm_kzalloc(dev, sizeof(struct ac5_thermal_data), GFP_KERNEL);
if (!thermal_data)
return -ENOMEM;
thermal_data->dev = dev;
thermal_data->temp_crit = AC5_DEFAULT_TEMP_CRIT;
thermal_data->temp_max = AC5_DEFAULT_TEMP_MAX;
thermal_data->hwmon_dev = devm_hwmon_device_register_with_info(dev, ac5_thermal_misc_device.name,
thermal_data, &ac5_thermal_chip_info,
NULL);
if (IS_ERR(thermal_data->hwmon_dev)) {
dev_err(dev, "%s: hwmon registration failed.\n", ac5_thermal_misc_device.name);
return PTR_ERR(thermal_data->hwmon_dev);
}
reg = devm_ioremap(dev, thermal_base_addr, 16);
if (IS_ERR(reg)) {
dev_err(dev, "%s: base addr remap failed\n", ac5_thermal_misc_device.name);
return PTR_ERR(reg);
}
thermal_data->temp_base = reg;
/*Enable measurement*/
writel(0xF0F01035, thermal_data->temp_base);
writel(0x0584e680, thermal_data->temp_base+8);
dev_info(dev, "%s: initialized. base_addr: 0x%lx\n", dev_name(thermal_data->hwmon_dev), thermal_base_addr);
return 0;
}
static void __exit ac5_thermal_exit_misc_driver(void)
{
misc_deregister(&ac5_thermal_misc_device);
}
module_init(ac5_thermal_init_misc_driver);
module_exit(ac5_thermal_exit_misc_driver);
MODULE_AUTHOR("Natarajan Subbiramani <natarajan.subbiramani.ext@nokia.com>");
MODULE_DESCRIPTION("AC5 Thermal sensor Driver");
MODULE_LICENSE("GPL");

View File

@ -0,0 +1,242 @@
/*
* HWMON Driver for CN9130 thermal sensor
*
* Author: Natarajan Subbiramani <nataraja.subbiramani.ext@nokia.com>
*
* 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 <linux/module.h>
#include <linux/init.h>
#include <linux/miscdevice.h>
#include <linux/hwmon.h>
#include <linux/hwmon-sysfs.h>
#include <linux/err.h>
#include <linux/io.h>
#include <linux/delay.h>
#define CN9130_DEFAULT_TEMP_CRIT 100000
#define CN9130_DEFAULT_TEMP_MAX 106000
#define CN9130_TEMP_BASE_ADDR 0xF06F8080
#define CN9130_TSEN_REG_CTRL_0_OFFSET 0x4
#define CN9130_TSEN_REG_CTRL_1_OFFSET 0x8
#define CN9130_TSEN_REG_STATUS_OFFSET 0xC
#define CN9130_TSEN_SENSOR_MAX_ID 6
static unsigned long thermal_base_addr=CN9130_TEMP_BASE_ADDR;
module_param(thermal_base_addr, ulong, 0444);
MODULE_PARM_DESC(thermal_base_addr,
"Initialize the base address of the thermal sensor");
struct cn9130_thermal_data {
struct device *dev;
struct device *hwmon_dev;
uint8_t * __iomem temp_base;
int temp_input;
int temp_crit;
int temp_max;
};
static long cn9130_thermal_read_reg_in_mcelcius(struct device *dev, struct cn9130_thermal_data *data)
{
volatile uint8_t * __iomem temp_base = data->temp_base;
uint32_t regval;
uint32_t status_regval=0;
uint32_t output=data->temp_max;
//STOP MEASUREMENT
regval = readl(temp_base+CN9130_TSEN_REG_CTRL_0_OFFSET);
regval &= ~( 1 << 0); //TSEN_STOP
writel(regval, temp_base+CN9130_TSEN_REG_CTRL_0_OFFSET);
//delay for 1ms
mdelay(1);
//Read thermal value
status_regval = readl(temp_base+CN9130_TSEN_REG_STATUS_OFFSET);
dev_dbg(dev, "%s: cn9130_thermal_read_reg_in_mcelcius: addr: 0x%lx value:0x%x\n", dev_name(data->hwmon_dev), temp_base+CN9130_TSEN_REG_STATUS_OFFSET, status_regval);
//START MEASUREMENT
regval = readl(temp_base+CN9130_TSEN_REG_CTRL_0_OFFSET);
regval |= 1 << 0; //TSEN_START
writel(regval, temp_base+CN9130_TSEN_REG_CTRL_0_OFFSET);
//Validate data
if(status_regval &= 0x3ff) {
//Convert it to milli-celcius
output = 150000 - (~(status_regval-1) & 0x3ff) * 423;
}
return output;
}
static int cn9130_thermal_read(struct device *dev, enum hwmon_sensor_types type,
u32 attr, int channel, long *val)
{
struct cn9130_thermal_data *data = dev_get_drvdata(dev);
switch (type) {
case hwmon_temp:
switch (attr) {
case hwmon_temp_input:
*val = cn9130_thermal_read_reg_in_mcelcius(dev, data);
break;
case hwmon_temp_crit:
*val = data->temp_crit;
break;
case hwmon_temp_max:
*val = data->temp_max;
break;
default:
return -EINVAL;
}
break;
default:
return -EINVAL;
}
return 0;
}
static int cn9130_thermal_write(struct device *dev, enum hwmon_sensor_types type,
u32 attr, int channel, long val)
{
struct cn9130_thermal_data *data = dev_get_drvdata(dev);
switch (type) {
case hwmon_temp:
switch (attr) {
case hwmon_temp_crit:
data->temp_crit = val;
break;
case hwmon_temp_max:
data->temp_max = val;
break;
default:
return -EINVAL;
}
break;
default:
return -EINVAL;
}
return 0;
}
static umode_t cn9130_thermal_is_visible(const void *data, enum hwmon_sensor_types type,
u32 attr, int channel)
{
switch (type) {
case hwmon_temp:
switch (attr) {
case hwmon_temp_input:
return 0444;
case hwmon_temp_crit:
case hwmon_temp_max:
return 0644;
}
break;
default:
break;
}
return 0;
}
static const struct hwmon_channel_info *cn9130_thermal_info[] = {
HWMON_CHANNEL_INFO(temp,
HWMON_T_INPUT | HWMON_T_MAX | HWMON_T_CRIT),
NULL
};
static const struct hwmon_ops cn9130_thermal_hwmon_ops = {
.is_visible = cn9130_thermal_is_visible,
.read = cn9130_thermal_read,
.write = cn9130_thermal_write,
};
static const struct hwmon_chip_info cn9130_thermal_chip_info = {
.ops = &cn9130_thermal_hwmon_ops,
.info = cn9130_thermal_info,
};
static const struct file_operations fops = {
.owner = THIS_MODULE,
};
struct miscdevice cn9130_thermal_device = {
.minor = TEMP_MINOR,
.name = "cn9130_thermal",
.fops = &fops,
};
static int __init cn9130_thermal_init_driver(void)
{
struct device *dev;
struct cn9130_thermal_data *thermal_data;
int err;
void * __iomem reg;
uint32_t regval=0;
err = misc_register(&cn9130_thermal_device);
if (err) {
pr_err("cn9130_thermal misc_register failed!!!\n");
return err;
}
dev = cn9130_thermal_device.this_device;
thermal_data = devm_kzalloc(dev, sizeof(struct cn9130_thermal_data), GFP_KERNEL);
if (!thermal_data)
return -ENOMEM;
thermal_data->dev = dev;
thermal_data->temp_crit = CN9130_DEFAULT_TEMP_CRIT;
thermal_data->temp_max = CN9130_DEFAULT_TEMP_MAX;
thermal_data->hwmon_dev = devm_hwmon_device_register_with_info(dev, cn9130_thermal_device.name,
thermal_data, &cn9130_thermal_chip_info,
NULL);
if (IS_ERR(thermal_data->hwmon_dev)) {
dev_err(dev, "%s: hwmon registration failed.\n", cn9130_thermal_device.name);
return PTR_ERR(thermal_data->hwmon_dev);
}
reg = devm_ioremap(dev, thermal_base_addr, 16);
if (IS_ERR(reg)) {
dev_err(dev, "%s: base addr remap failed\n", cn9130_thermal_device.name);
return PTR_ERR(reg);
}
thermal_data->temp_base = reg;
/*Enable measurement*/
regval = readl(thermal_data->temp_base+CN9130_TSEN_REG_CTRL_0_OFFSET);
regval |= 1 << 2; //TSEN_EN
writel(regval, thermal_data->temp_base+CN9130_TSEN_REG_CTRL_0_OFFSET);
mdelay(10);
// Set temperature reading zone as max reading
regval = readl(thermal_data->temp_base+CN9130_TSEN_REG_CTRL_1_OFFSET);
regval &= ~(0x7 << 21);
regval |= (CN9130_TSEN_SENSOR_MAX_ID & 0x7) << 21;
writel(regval, thermal_data->temp_base+CN9130_TSEN_REG_CTRL_1_OFFSET);
//START MEASUREMENT
regval = readl(thermal_data->temp_base+CN9130_TSEN_REG_CTRL_0_OFFSET);
regval |= 1 << 0; //TSEN_START
writel(regval, thermal_data->temp_base+CN9130_TSEN_REG_CTRL_0_OFFSET);
dev_info(dev, "%s: initialized. base_addr: 0x%lx virt_addr:0x%lx\n", dev_name(thermal_data->hwmon_dev), thermal_base_addr, thermal_data->temp_base);
return 0;
}
static void __exit cn9101_thermal_exit_driver(void)
{
misc_deregister(&cn9130_thermal_device);
}
module_init(cn9130_thermal_init_driver);
module_exit(cn9101_thermal_exit_driver);
MODULE_AUTHOR("Natarajan Subbiramani <natarajan.subbiramani.ext@nokia.com>");
MODULE_DESCRIPTION("CN9130 CPU Thermal sensor Driver");
MODULE_LICENSE("GPL");

View File

@ -0,0 +1,46 @@
#!/usr/bin/python
from sonic_platform.chassis import Chassis
from sonic_py_common import logger
import time
import os
import signal
import sys
TIMEOUT=180
KEEPALIVE=60
sonic_logger = logger.Logger('Watchdog')
sonic_logger.set_min_log_priority_info()
time.sleep(60)
chassis = Chassis()
watchdog = chassis.get_watchdog()
def stopWdtService(signal, frame):
watchdog._disablewatchdog()
sonic_logger.log_notice("CPUWDT Disabled: watchdog armed=%s" % watchdog.is_armed() )
sys.exit()
def main():
signal.signal(signal.SIGHUP, signal.SIG_IGN)
signal.signal(signal.SIGINT, stopWdtService)
signal.signal(signal.SIGTERM, stopWdtService)
watchdog.arm(TIMEOUT)
sonic_logger.log_notice("CPUWDT Enabled: watchdog armed=%s" % watchdog.is_armed() )
while True:
time.sleep(KEEPALIVE)
watchdog._keepalive()
sonic_logger.log_info("CPUWDT keepalive")
done
stopWdtService
return
if __name__ == '__main__':
main()

View File

@ -0,0 +1,8 @@
[Unit]
Description=CPU WDT
After=nokia-7215init.service
[Service]
ExecStart=/usr/local/bin/cpu_wdt.py
[Install]
WantedBy=multi-user.target

View File

@ -35,7 +35,7 @@ MAX_7215_COMPONENT=2
MAX_7215_FAN_DRAWERS = 2 MAX_7215_FAN_DRAWERS = 2
MAX_7215_FANS_PER_DRAWER = 1 MAX_7215_FANS_PER_DRAWER = 1
MAX_7215_PSU = 2 MAX_7215_PSU = 2
MAX_7215_THERMAL = 4 MAX_7215_THERMAL = 5
CPLD_DIR = "/sys/bus/i2c/devices/0-0041/" CPLD_DIR = "/sys/bus/i2c/devices/0-0041/"
SYSLOG_IDENTIFIER = "chassis" SYSLOG_IDENTIFIER = "chassis"
@ -92,7 +92,7 @@ class Chassis(ChassisBase):
drawer = drawer_ctor(drawer_index) drawer = drawer_ctor(drawer_index)
self._fan_drawer_list.append(drawer) self._fan_drawer_list.append(drawer)
for index in range(fan_num_per_drawer): for index in range(fan_num_per_drawer):
fan = Fan(fan_index, drawer) fan = Fan(fan_index, drawer, self.get_model())
fan_index += 1 fan_index += 1
drawer._fan_list.append(fan) drawer._fan_list.append(fan)
self._fan_list.append(fan) self._fan_list.append(fan)
@ -259,10 +259,21 @@ class Chassis(ChassisBase):
is "REBOOT_CAUSE_HARDWARE_OTHER", the second string can be used is "REBOOT_CAUSE_HARDWARE_OTHER", the second string can be used
to pass a description of the reboot cause. to pass a description of the reboot cause.
""" """
# The ixs7215 CPLD does not have a hardware reboot cause register so value = self._read_sysfs_file(CPLD_DIR+"last_reset_cause")
# the hardware portion of reboot cause can't be implemented thermal = self._read_sysfs_file(CPLD_DIR+"temp_event_status")
if (value == 'cold_reset'):
return (ChassisBase.REBOOT_CAUSE_NON_HARDWARE, None) reboot_cause=(ChassisBase.REBOOT_CAUSE_POWER_LOSS, "Cold Reset")
elif (value == 'warm_reset'):
reboot_cause=(ChassisBase.REBOOT_CAUSE_HARDWARE_OTHER, "Warm Reset")
elif (value == 'wdog_reset'):
reboot_cause=(ChassisBase.REBOOT_CAUSE_WATCHDOG, None)
elif (value == 'thermal_reset'):
reboot_cause=(ChassisBase.REBOOT_CAUSE_THERMAL_OVERLOAD_OTHER, thermal)
else:
reboot_cause=(ChassisBase.REBOOT_CAUSE_NON_HARDWARE, None)
#unmask temperature event
self._write_sysfs_file(CPLD_DIR+"temp_event_mask", 0)
return reboot_cause
def get_watchdog(self): def get_watchdog(self):
""" """

View File

@ -175,7 +175,7 @@ class Component(ComponentBase):
return self._get_cpld_version(self.index) return self._get_cpld_version(self.index)
if self.index == 1: if self.index == 1:
cmdstatus, uboot_version = cmd.getstatusoutput('grep --null-data ^U-Boot /dev/mtd0ro | cut -d" " -f2') cmdstatus, uboot_version = cmd.getstatusoutput('grep --null-data ^U-Boot /dev/mtd0ro | cut -d" " -f4')
return uboot_version return uboot_version
def install_firmware(self, image_path): def install_firmware(self, image_path):

View File

@ -41,8 +41,7 @@ class Eeprom(TlvInfoDecoder):
self.index = psu_index self.index = psu_index
self.part_number = '1' self.part_number = '1'
self.model_str = 'PJT-12V100WBBA' self.model_str = 'PJT-12V100WBBA'
self.serial_number = 'NA' self.serial_number = 'NA'
self.serial_number = 'NA'
if self.is_fan_eeprom: if self.is_fan_eeprom:
self.index = fan_index self.index = fan_index

View File

@ -16,8 +16,8 @@ try:
except ImportError as e: except ImportError as e:
raise ImportError(str(e) + "- required module not found") raise ImportError(str(e) + "- required module not found")
MAX_IXS7215_FAN_SPEED = 24000 MAX_IXS7215_FAN_SPEED = 23000
WORKING_IXS7215_FAN_SPEED = 2400 WORKING_IXS7215_FAN_SPEED = 2300
sonic_logger = logger.Logger('fan') sonic_logger = logger.Logger('fan')
@ -26,10 +26,10 @@ sonic_logger = logger.Logger('fan')
class Fan(FanBase): class Fan(FanBase):
"""Nokia platform-specific Fan class""" """Nokia platform-specific Fan class"""
def __init__(self, fan_index, fan_drawer, psu_fan=False, dependency=None): def __init__(self, fan_index, fan_drawer, chassis_model, psu_fan=False, dependency=None):
self.is_psu_fan = psu_fan self.is_psu_fan = psu_fan
EMC2302_DIR = " " EMC2302_DIR = " "
i2c_path = "/sys/bus/i2c/devices/0-002e/hwmon/" i2c_path = "/sys/bus/i2c/devices/0-002f/hwmon/"
if(os.path.exists(i2c_path)): if(os.path.exists(i2c_path)):
hwmon_node = os.listdir(i2c_path)[0] hwmon_node = os.listdir(i2c_path)[0]
EMC2302_DIR = i2c_path + hwmon_node + '/' EMC2302_DIR = i2c_path + hwmon_node + '/'
@ -38,6 +38,7 @@ class Fan(FanBase):
# Fan is 1-based in Nokia platforms # Fan is 1-based in Nokia platforms
self.index = fan_index + 1 self.index = fan_index + 1
self.fan_drawer = fan_drawer self.fan_drawer = fan_drawer
self.chassis_model = chassis_model
self.set_fan_speed_reg = EMC2302_DIR+"pwm{}".format(self.index) self.set_fan_speed_reg = EMC2302_DIR+"pwm{}".format(self.index)
self.get_fan_speed_reg = EMC2302_DIR+"fan{}_input".format(self.index) self.get_fan_speed_reg = EMC2302_DIR+"fan{}_input".format(self.index)
self.max_fan_speed = MAX_IXS7215_FAN_SPEED self.max_fan_speed = MAX_IXS7215_FAN_SPEED
@ -116,7 +117,16 @@ class Fan(FanBase):
Returns: Returns:
string: Model number of Fan. Use part number for this. string: Model number of Fan. Use part number for this.
""" """
return self.eeprom.part_number_str() return self.eeprom.modelstr()
def get_chassis_model(self):
"""
Retrieves the model number of the Fan
Returns:
string: Model number of Fan. Use part number for this.
"""
return self.chassis_model
def get_serial(self): def get_serial(self):
""" """
@ -169,8 +179,14 @@ class Fan(FanBase):
A string, either FAN_DIRECTION_INTAKE or A string, either FAN_DIRECTION_INTAKE or
FAN_DIRECTION_EXHAUST depending on fan direction FAN_DIRECTION_EXHAUST depending on fan direction
""" """
ch_model=self.get_chassis_model()
#compare first 8 characters of chassis molel string
if(ch_model[:8]=='3HE18723'):
direction = 'intake'
else:
direction = 'exhaust'
return 'intake' return direction
def get_position_in_parent(self): def get_position_in_parent(self):
""" """
@ -219,8 +235,10 @@ class Fan(FanBase):
which is considered tolerable which is considered tolerable
""" """
if self.get_presence(): if self.get_presence():
# The tolerance value is fixed as 25% for this platform if self.get_target_speed()<50:
tolerance = 50 tolerance=60
else:
tolerance = 25
else: else:
tolerance = 0 tolerance = 0

View File

@ -19,6 +19,8 @@ except ImportError as e:
sonic_logger = logger.Logger('psu') sonic_logger = logger.Logger('psu')
INA230_DIR = "/sys/bus/i2c/devices/0-0040/iio:device0/" INA230_DIR = "/sys/bus/i2c/devices/0-0040/iio:device0/"
CPLD_DIR = "/sys/bus/i2c/devices/0-0041/" CPLD_DIR = "/sys/bus/i2c/devices/0-0041/"
PSU_GPIO_DIR = ["/sys/class/gpio/gpio61/value", "/sys/class/gpio/gpio62/value"]
class Psu(PsuBase): class Psu(PsuBase):
"""Nokia platform-specific PSU class for 7215 """ """Nokia platform-specific PSU class for 7215 """
@ -32,6 +34,8 @@ class Psu(PsuBase):
# PSU eeprom # PSU eeprom
self.eeprom = Eeprom(is_psu=True, psu_index=self.index) self.eeprom = Eeprom(is_psu=True, psu_index=self.index)
self.MAX_VOLTAGE = 14
self.MIN_VOLTAGE = 10
def _read_sysfs_file(self, sysfs_file): def _read_sysfs_file(self, sysfs_file):
# On successful read, returns the value read from given # On successful read, returns the value read from given
@ -80,8 +84,8 @@ class Psu(PsuBase):
Integer: Number of active PSU's Integer: Number of active PSU's
""" """
active_psus = 0 active_psus = 0
psu1_good = self._read_sysfs_file(CPLD_DIR+"psu1_power_good") psu1_good = self._read_sysfs_file(PSU_GPIO_DIR[0])
psu2_good = self._read_sysfs_file(CPLD_DIR+"psu2_power_good") psu2_good = self._read_sysfs_file(PSU_GPIO_DIR[1])
active_psus = int(psu1_good) + int(psu2_good) active_psus = int(psu1_good) + int(psu2_good)
@ -150,7 +154,7 @@ class Psu(PsuBase):
Returns: Returns:
bool: True if PSU is operating properly, False if not bool: True if PSU is operating properly, False if not
""" """
psu_sysfs_str=CPLD_DIR+"psu{}_power_good".format(self.index) psu_sysfs_str=PSU_GPIO_DIR[self.index-1]
psu_status = self._read_sysfs_file(psu_sysfs_str) psu_status = self._read_sysfs_file(psu_sysfs_str)
if psu_status == '1': if psu_status == '1':
@ -212,6 +216,26 @@ class Psu(PsuBase):
""" """
return self.index return self.index
def get_voltage_high_threshold(self):
"""
Retrieves the high threshold PSU voltage output
Returns:
A float number, the high threshold output voltage in volts,
e.g. 12.1
"""
return self.MAX_VOLTAGE
def get_voltage_low_threshold(self):
"""
Retrieves the low threshold PSU voltage output
Returns:
A float number, the low threshold output voltage in volts,
e.g. 12.1
"""
return self.MIN_VOLTAGE
def is_replaceable(self): def is_replaceable(self):
""" """
Indicate whether this device is replaceable. Indicate whether this device is replaceable.
@ -227,7 +251,7 @@ class Psu(PsuBase):
A boolean, True if PSU has stablized its output voltages and A boolean, True if PSU has stablized its output voltages and
passed all its internal self-tests, False if not. passed all its internal self-tests, False if not.
""" """
psu_sysfs_str=CPLD_DIR+"psu{}_power_good".format(self.index) psu_sysfs_str=PSU_GPIO_DIR[self.index-1]
psu_pg_status = self._read_sysfs_file(psu_sysfs_str) psu_pg_status = self._read_sysfs_file(psu_sysfs_str)
if psu_pg_status == '1': if psu_pg_status == '1':
@ -294,4 +318,4 @@ class Psu(PsuBase):
if status == "ERR": if status == "ERR":
return False return False
return True return True

View File

@ -30,7 +30,7 @@ logger = Logger()
class Sfp(SfpOptoeBase): class Sfp(SfpOptoeBase):
""" """
Nokia IXR-7215 Platform-specific Sfp refactor class Nokia IXS-7215 Platform-specific Sfp refactor class
""" """
instances = [] instances = []

View File

@ -10,6 +10,7 @@
try: try:
import os import os
from sonic_platform_base.thermal_base import ThermalBase from sonic_platform_base.thermal_base import ThermalBase
from swsscommon.swsscommon import SonicV2Connector
from sonic_py_common import logger from sonic_py_common import logger
except ImportError as e: except ImportError as e:
raise ImportError(str(e) + "- required module not found") raise ImportError(str(e) + "- required module not found")
@ -21,12 +22,13 @@ class Thermal(ThermalBase):
I2C_CLASS_DIR = "/sys/class/i2c-adapter/" I2C_CLASS_DIR = "/sys/class/i2c-adapter/"
I2C_DEV_MAPPING = (['i2c-0/0-0048/hwmon/', 1], I2C_DEV_MAPPING = (['i2c-0/0-0048/hwmon/', 1],
['i2c-0/0-0049/hwmon/', 1]) ['i2c-0/0-0049/hwmon/', 1],
['i2c-0/0-004a/hwmon/', 1])
HWMON_CLASS_DIR = "/sys/class/hwmon/hwmon0/" CN9130_THERMAL_DIR = "/sys/class/hwmon/hwmon1/"
AC5X_THERMAL_DIR = "/sys/class/hwmon/hwmon1/" ASIC_TEMP_INFO = "ASIC_TEMPERATURE_INFO"
THERMAL_NAME = ("PCB BACK", "PCB FRONT", "AC5X CORE", "OOB PHY") THERMAL_NAME = ("PCB BACK", "PCB FRONT", "PCB MID", "ASIC", "CPU CORE")
def __init__(self, thermal_index): def __init__(self, thermal_index):
ThermalBase.__init__(self) ThermalBase.__init__(self)
@ -37,7 +39,7 @@ class Thermal(ThermalBase):
self._maximum = None self._maximum = None
self.thermal_high_threshold_file = None self.thermal_high_threshold_file = None
# PCB temperature sensors # PCB temperature sensors
if self.index < 3: if self.index < 4:
i2c_path = self.I2C_CLASS_DIR + self.I2C_DEV_MAPPING[self.index - 1][0] i2c_path = self.I2C_CLASS_DIR + self.I2C_DEV_MAPPING[self.index - 1][0]
sensor_index = self.I2C_DEV_MAPPING[self.index - 1][1] sensor_index = self.I2C_DEV_MAPPING[self.index - 1][1]
sensor_high_suffix = "max" sensor_high_suffix = "max"
@ -45,24 +47,26 @@ class Thermal(ThermalBase):
hwmon_node = os.listdir(i2c_path)[0] hwmon_node = os.listdir(i2c_path)[0]
self.SENSOR_DIR = i2c_path + hwmon_node + '/' self.SENSOR_DIR = i2c_path + hwmon_node + '/'
# SOC temperature sensor #ASIC temperature sensor
elif self.index == 3: elif self.index == 4:
dev_path = self.AC5X_THERMAL_DIR
sensor_index = 1
sensor_high_suffix = "max"
sensor_high_crit_suffix = None
self.SENSOR_DIR = dev_path
#
else:
dev_path = self.HWMON_CLASS_DIR
sensor_index = 1
sensor_high_suffix = None sensor_high_suffix = None
sensor_high_crit_suffix = "crit" sensor_high_crit_suffix = None
self.sensor_high_threshold = 100.0
self.sensor_crit_threshold = 110.0
self.SENSOR_DIR = None
# CPU CN9130 temperature sensor
elif self.index == 5:
dev_path = self.CN9130_THERMAL_DIR
sensor_index = 1
sensor_high_suffix = "crit"
sensor_high_crit_suffix = "max"
self.SENSOR_DIR = dev_path self.SENSOR_DIR = dev_path
# sysfs file for current temperature value # sysfs file for current temperature value
self.thermal_temperature_file = self.SENSOR_DIR \ if self.SENSOR_DIR:
+ "temp{}_input".format(sensor_index) self.thermal_temperature_file = self.SENSOR_DIR \
+ "temp{}_input".format(sensor_index)
# sysfs file for high threshold value if supported for this sensor # sysfs file for high threshold value if supported for this sensor
if sensor_high_suffix: if sensor_high_suffix:
@ -156,16 +160,23 @@ class Thermal(ThermalBase):
A float number of current temperature in Celsius up to A float number of current temperature in Celsius up to
nearest thousandth of one degree Celsius, e.g. 30.125 nearest thousandth of one degree Celsius, e.g. 30.125
""" """
thermal_temperature = self._read_sysfs_file( #read from state_db for asic temperature
self.thermal_temperature_file) if self.index == 4:
if (thermal_temperature != 'ERR'): db = SonicV2Connector()
thermal_temperature = float(thermal_temperature) / 1000 db.connect(db.STATE_DB)
if self._minimum is None or self._minimum > thermal_temperature: data_dict = db.get_all(db.STATE_DB, self.ASIC_TEMP_INFO)
self._minimum = thermal_temperature thermal_temperature = float(data_dict['maximum_temperature'])
if self._maximum is None or self._maximum < thermal_temperature:
self._maximum = thermal_temperature
else: else:
thermal_temperature = 0 thermal_temperature = self._read_sysfs_file(self.thermal_temperature_file)
if (thermal_temperature != 'ERR'):
thermal_temperature = float(thermal_temperature) / 1000
else:
thermal_temperature = 0
if self._minimum is None or self._minimum > thermal_temperature:
self._minimum = thermal_temperature
if self._maximum is None or self._maximum < thermal_temperature:
self._maximum = thermal_temperature
return float("{:.3f}".format(thermal_temperature)) return float("{:.3f}".format(thermal_temperature))
@ -178,12 +189,13 @@ class Thermal(ThermalBase):
Celsius up to nearest thousandth of one degree Celsius, Celsius up to nearest thousandth of one degree Celsius,
e.g. 30.125 e.g. 30.125
""" """
if self.index == 4:
return float("{:.3f}".format(self.sensor_high_threshold))
# Not implemented for this sensor # Not implemented for this sensor
if not self.thermal_high_threshold_file: if not self.thermal_high_threshold_file:
raise NotImplementedError raise NotImplementedError
thermal_high_threshold = self._read_sysfs_file( thermal_high_threshold = self._read_sysfs_file(self.thermal_high_threshold_file)
self.thermal_high_threshold_file)
if (thermal_high_threshold != 'ERR'): if (thermal_high_threshold != 'ERR'):
thermal_high_threshold = float(thermal_high_threshold) / 1000 thermal_high_threshold = float(thermal_high_threshold) / 1000
else: else:
@ -213,7 +225,8 @@ class Thermal(ThermalBase):
A float number, the high critical threshold temperature of thermal in Celsius A float number, the high critical threshold temperature of thermal in Celsius
up to nearest thousandth of one degree Celsius, e.g. 30.125 up to nearest thousandth of one degree Celsius, e.g. 30.125
""" """
if self.index == 4:
return float("{:.3f}".format(self.sensor_crit_threshold))
# Not implemented for this sensor # Not implemented for this sensor
if not self.thermal_high_crit_threshold_file: if not self.thermal_high_crit_threshold_file:
raise NotImplementedError raise NotImplementedError

View File

@ -73,14 +73,22 @@ class ThermalInfo(ThermalPolicyInfoBase):
self._current_threshold_level = 0 self._current_threshold_level = 0
self._num_fan_levels = 3 self._num_fan_levels = 3
self._high_crital_threshold = 75 self._high_crital_threshold = 75
self._level_up_threshold = [[31,39,58,46], #THERMAL_NAME ("PCB BACK", "PCB FRONT", "PCB MID", "ASIC", "CPU CORE")
[39,46,65,54], self._f2b_level_up_threshold = [[38,30,37,60,77],
[51,57,77,68]] [51,44,50,72,90],
[61,57,61,77,94]]
self._level_down_threshold = [[24,31,47,40], self._f2b_level_down_threshold = [[29,24,29,50,64],
[31,38,53,46], [40,37,40,59,75],
[48,54,72,63]] [58,54,58,72,90]]
self._b2f_level_up_threshold = [[30,38,41,65,71],
[43,50,54,76,86],
[53,59,61,79,92]]
self._b2f_level_down_threshold = [[22,30,33,54,60],
[37,44,46,62,73],
[51,57,58,75,90]]
def collect(self, chassis): def collect(self, chassis):
""" """
Collect thermal sensor temperature change status Collect thermal sensor temperature change status
@ -99,6 +107,13 @@ class ThermalInfo(ThermalPolicyInfoBase):
for index in range(num_of_thermals): for index in range(num_of_thermals):
self._temps.insert(index, chassis.get_thermal(index).get_temperature()) self._temps.insert(index, chassis.get_thermal(index).get_temperature())
fan_direction=chassis.get_fan(1).get_direction()
if(fan_direction == "intake"):
level_up_threshold=self._f2b_level_up_threshold
level_down_threshold=self._f2b_level_down_threshold
else:
level_up_threshold=self._b2f_level_up_threshold
level_down_threshold=self._b2f_level_down_threshold
# Find current required threshold level # Find current required threshold level
max_level =0 max_level =0
@ -106,10 +121,10 @@ class ThermalInfo(ThermalPolicyInfoBase):
for index in range(num_of_thermals): for index in range(num_of_thermals):
for level in range(self._num_fan_levels): for level in range(self._num_fan_levels):
if self._temps[index]>self._level_up_threshold[level][index]: if self._temps[index]>level_up_threshold[level][index]:
if max_level<level+1: if max_level<level+1:
max_level=level+1 max_level=level+1
if self._temps[index]<self._level_down_threshold[level][index]: if self._temps[index]<level_down_threshold[level][index]:
if min_level[index]>level: if min_level[index]>level:
min_level[index]=level min_level[index]=level

View File

@ -6,9 +6,8 @@ provides access to hardware watchdog
import os import os
import fcntl import fcntl
import array import array
import time
from sonic_platform_base.watchdog_base import WatchdogBase from sonic_platform_base.watchdog_base import WatchdogBase
from sonic_py_common import logger
""" ioctl constants """ """ ioctl constants """
IO_WRITE = 0x40000000 IO_WRITE = 0x40000000
@ -34,13 +33,12 @@ WDIOS_DISABLECARD = 0x0001
WDIOS_ENABLECARD = 0x0002 WDIOS_ENABLECARD = 0x0002
""" watchdog sysfs """ """ watchdog sysfs """
WD_SYSFS_PATH = "/sys/class/watchdog/" WD_SYSFS_PATH = "/sys/class/watchdog/watchdog0/"
WD_GPIO_PATH = "/sys/class/gpio/gpio41/value"
CPLD_DIR = "/sys/bus/i2c/devices/0-0041/"
WD_COMMON_ERROR = -1 WD_COMMON_ERROR = -1
sonic_logger = logger.Logger()
class WatchdogImplBase(WatchdogBase): class WatchdogImplBase(WatchdogBase):
""" """
Base class that implements common logic for interacting Base class that implements common logic for interacting
@ -53,34 +51,53 @@ class WatchdogImplBase(WatchdogBase):
@param wd_device_path Path to watchdog device @param wd_device_path Path to watchdog device
""" """
super(WatchdogImplBase, self).__init__() super(WatchdogImplBase, self).__init__()
self.watchdog=""
self.watchdog_path = wd_device_path self.watchdog_path = wd_device_path
self.watchdog = os.open(self.watchdog_path, os.O_WRONLY) self.watchdog_gpio_reg = WD_GPIO_PATH
self.wd_state_reg = WD_SYSFS_PATH+"state"
# Opening a watchdog descriptor starts self.wd_timeout_reg = WD_SYSFS_PATH+"timeout"
# watchdog timer; by default it should be stopped self.wd_timeleft_reg = WD_SYSFS_PATH+"timeleft"
self._disablewatchdog()
self.armed = False
self.timeout = self._gettimeout() self.timeout = self._gettimeout()
def disarm(self): def _read_sysfs_file(self, sysfs_file):
""" # On successful read, returns the value read from given
Disarm the hardware watchdog # reg_name and on failure returns 'ERR'
rv = 'ERR'
Returns:
A boolean, True if watchdog is disarmed successfully, False
if not
"""
sonic_logger.log_info(" Debug disarm watchdog ")
if (not os.path.isfile(sysfs_file)):
return rv
try: try:
self._disablewatchdog() with open(sysfs_file, 'r') as fd:
self.armed = False rv = fd.read()
self.timeout = 0 except Exception as e:
except IOError: rv = 'ERR'
return False
return True rv = rv.rstrip('\r\n')
rv = rv.lstrip(" ")
return rv
def _write_sysfs_file(self, sysfs_file, value):
# On successful write, the value read will be written on
# reg_name and on failure returns 'ERR'
rv = 'ERR'
if (not os.path.isfile(sysfs_file)):
return rv
try:
with open(sysfs_file, 'w') as fd:
rv = fd.write(str(value))
except Exception as e:
rv = 'ERR'
# Ensure that the write operation has succeeded
if (int(self._read_sysfs_file(sysfs_file)) != value ):
time.sleep(3)
if (int(self._read_sysfs_file(sysfs_file)) != value ):
rv = 'ERR'
return rv
def _disablewatchdog(self): def _disablewatchdog(self):
""" """
@ -89,6 +106,23 @@ class WatchdogImplBase(WatchdogBase):
req = array.array('h', [WDIOS_DISABLECARD]) req = array.array('h', [WDIOS_DISABLECARD])
fcntl.ioctl(self.watchdog, WDIOC_SETOPTIONS, req, False) fcntl.ioctl(self.watchdog, WDIOC_SETOPTIONS, req, False)
self._write_sysfs_file(self.watchdog_gpio_reg, 1)
self._read_sysfs_file(CPLD_DIR+"last_reset_cause")
def _enablewatchdog(self):
"""
Turn on the watchdog timer
"""
req = array.array('h', [WDIOS_ENABLECARD])
fcntl.ioctl(self.watchdog, WDIOC_SETOPTIONS, req, False)
def _keepalive(self):
"""
Keep alive watchdog timer
"""
fcntl.ioctl(self.watchdog, WDIOC_KEEPALIVE)
def _settimeout(self, seconds): def _settimeout(self, seconds):
""" """
@ -107,11 +141,10 @@ class WatchdogImplBase(WatchdogBase):
Get watchdog timeout Get watchdog timeout
@return watchdog timeout @return watchdog timeout
""" """
timeout=0
timeout=self._read_sysfs_file(self.wd_timeout_reg)
req = array.array('I', [0]) return timeout
fcntl.ioctl(self.watchdog, WDIOC_GETTIMEOUT, req, True)
return int(req[0])
def _gettimeleft(self): def _gettimeleft(self):
""" """
@ -128,47 +161,62 @@ class WatchdogImplBase(WatchdogBase):
""" """
Implements arm WatchdogBase API Implements arm WatchdogBase API
""" """
sonic_logger.log_info(" Debug arm watchdog4 ")
ret = WD_COMMON_ERROR
if seconds < 0:
return ret
ret = WD_COMMON_ERROR
if (seconds < 0 or seconds > 340 ):
return ret
# Stop the watchdog service to gain access of watchdog file pointer
if self.is_armed():
os.popen("systemctl stop cpu_wdt.service")
time.sleep(2)
if not self.watchdog:
self.watchdog = os.open(self.watchdog_path, os.O_WRONLY)
try: try:
if self.timeout != seconds: if self.timeout != seconds:
self.timeout = self._settimeout(seconds) self.timeout = self._settimeout(seconds)
if self.armed: if self.is_armed():
self._keepalive() self._keepalive()
else: else:
sonic_logger.log_info(" Debug arm watchdog5 ")
self._enablewatchdog() self._enablewatchdog()
self.armed = True
ret = self.timeout ret = self.timeout
except IOError: except IOError:
pass pass
if(ret == seconds):
self._write_sysfs_file(self.watchdog_gpio_reg, 0)
return ret return ret
def _enablewatchdog(self): def disarm(self):
"""
Turn on the watchdog timer
""" """
Implements disarm WatchdogBase API
req = array.array('h', [WDIOS_ENABLECARD]) Returns:
fcntl.ioctl(self.watchdog, WDIOC_SETOPTIONS, req, False) A boolean, True if watchdog is disarmed successfully, False
if not
def _keepalive(self):
""" """
Keep alive watchdog timer
""" if self.is_armed():
os.popen("systemctl stop cpu_wdt.service")
fcntl.ioctl(self.watchdog, WDIOC_KEEPALIVE) time.sleep(2)
if not self.watchdog:
self.watchdog = os.open(self.watchdog_path, os.O_WRONLY)
try:
self._disablewatchdog()
self.timeout = 0
except IOError:
return False
return True
def is_armed(self): def is_armed(self):
""" """
Implements is_armed WatchdogBase API Implements is_armed WatchdogBase API
""" """
status = False
return self.armed state = self._read_sysfs_file(self.wd_state_reg)
if (state != 'inactive'):
status = True
return status
def get_remaining_time(self): def get_remaining_time(self):
""" """
@ -177,10 +225,7 @@ class WatchdogImplBase(WatchdogBase):
timeleft = WD_COMMON_ERROR timeleft = WD_COMMON_ERROR
if self.armed: if self.is_armed():
try: timeleft=self._read_sysfs_file(self.wd_timeleft_reg)
timeleft = self._gettimeleft()
except IOError:
pass
return timeleft return int(timeleft)

View File

@ -33,7 +33,7 @@ build:
(for mod in $(MODULE_DIRS); do \ (for mod in $(MODULE_DIRS); do \
cd $(MOD_SRC_DIR)/../$(PRESTERA_MODULE_SRC)/; \ cd $(MOD_SRC_DIR)/../$(PRESTERA_MODULE_SRC)/; \
make clean; \ make clean; \
make modules -C $(KERNEL_SRC)/build M=`pwd` CONFIG_KM_MVMBUS=y CONFIG_KM_MVINT=y || exit 1; \ make modules -C $(KERNEL_SRC)/build M=`pwd` CONFIG_KM_MVPCI=y CONFIG_KM_MVINT=y || exit 1; \
mkdir $(MOD_SRC_DIR)/$${mod}/$(MRVL_MODULE_DIR); \ mkdir $(MOD_SRC_DIR)/$${mod}/$(MRVL_MODULE_DIR); \
cp *.ko $(MOD_SRC_DIR)/$${mod}/$(MRVL_MODULE_DIR)/; \ cp *.ko $(MOD_SRC_DIR)/$${mod}/$(MRVL_MODULE_DIR)/; \
cd $(MOD_SRC_DIR); \ cd $(MOD_SRC_DIR); \

View File

@ -1,4 +1,6 @@
7215/scripts/nokia-7215-init.sh usr/local/bin 7215/scripts/nokia-7215-init.sh usr/local/bin
7215/scripts/cpu_wdt.py usr/local/bin
7215/service/nokia-7215init.service etc/systemd/system 7215/service/nokia-7215init.service etc/systemd/system
7215/service/cpu_wdt.service etc/systemd/system
7215/sonic_platform-1.0-py3-none-any.whl usr/share/sonic/device/arm64-nokia_ixs7215_52xb-r0 7215/sonic_platform-1.0-py3-none-any.whl usr/share/sonic/device/arm64-nokia_ixs7215_52xb-r0
../mrvl-prestera/platform/arm64/ac5x/* / ../mrvl-prestera/platform/arm64/ac5x/* /

View File

@ -26,6 +26,9 @@ case "$1" in
systemctl enable nokia-7215init.service systemctl enable nokia-7215init.service
systemctl start nokia-7215init.service systemctl start nokia-7215init.service
systemctl enable cpu_wdt.service
systemctl start cpu_wdt.service
;; ;;
abort-upgrade|abort-remove|abort-deconfigure) abort-upgrade|abort-remove|abort-deconfigure)