[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"?>
<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:typedefs>
<ASKL1plt:typedef>

View File

@ -1 +1 @@
b42f2a2be9da6c7752c0807f9dee48bf
d36319f76733ae8593e31f3231599936

View File

@ -1,5 +1,5 @@
<?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:typedefs>
<askppplt:typedef>
@ -357,28 +357,28 @@
<askppplt:enum>
<askppplt:name>NATIVE</askppplt:name>
<askppplt:description>NATIVE
* the trunk members are filled
* according to the order given by application.
* Regular trunk may hold max of 8 members.
* Cascade trunk may hold :
* max of 64 members</askppplt:description>
* the trunk members are filled
* according to the order given by application.
* Regular trunk may hold max of 8 members.
* Cascade trunk may hold :
* max of 64 members</askppplt:description>
<askppplt:value>0</askppplt:value>
</askppplt:enum>
<askppplt:enum>
<askppplt:name>FLEX</askppplt:name>
<askppplt:description>FLEX
* A mode to allows flexibility for
* each Regular trunk to state it's max number of members (before starting to add members).
* (this mode not effect 'cascade trunk' members)
* 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>
* A mode to allows flexibility for
* each Regular trunk to state it's max number of members (before starting to add members).
* (this mode not effect 'cascade trunk' members)
* 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>
<askppplt:value>2</askppplt:value>
</askppplt:enum>
</askppplt:typedef>
<askppplt:typedef>
<askppplt:name>number-physical-port-type</askppplt:name>
<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:name>no-ports</askppplt:name>
<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"?>
<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:typedefs>
<SAIplt:typedef>
<SAIplt:name>device-id-type</SAIplt:name>
<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:max>1023</SAIplt:max>
<SAIplt:max>1</SAIplt:max>
</SAIplt:typedef>
<SAIplt:typedef>
<SAIplt:name>port-id-type</SAIplt:name>
@ -22,7 +22,7 @@
<SAIplt:description>Logging Feature Options</SAIplt:description>
<SAIplt:enum>
<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:enum>
<SAIplt:enum>
@ -32,7 +32,7 @@
</SAIplt:enum>
<SAIplt:enum>
<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:enum>
</SAIplt:typedef>
@ -43,11 +43,93 @@
<SAIplt:min>2</SAIplt:min>
<SAIplt:max>30</SAIplt:max>
</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: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:Features>
<SAIplt:RoCE SAIplt:type="boolean">false</SAIplt:RoCE>
</SAIplt:Features>
<SAIplt:Ports>
<SAIplt:port-list>
<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:port-list>
</SAIplt:Ports>
<SAIplt:Scaling>
<SAIplt:scalingAC5>
<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_ipv6 SAIplt:type="uint32">0</SAIplt:max_route_ipv6>
@ -320,9 +402,45 @@
<SAIplt:max_tti SAIplt:type="uint32">1024</SAIplt:max_tti>
<SAIplt:wred_size SAIplt:type="uint32">0</SAIplt:wred_size>
<SAIplt:max_nat SAIplt:type="uint32">0</SAIplt:max_nat>
</SAIplt:Scaling>
</SAIplt:scalingAC5>
<SAIplt:Logging>
<SAIplt:log_dest SAIplt:type="logDest-type">SAI_LOG_SYSLOG</SAIplt:log_dest>
</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>
</data>

View File

@ -1,2 +1 @@
VAR_LOG_SIZE=4096
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
},
{
"name": "AC5X CORE",
"name": "PCB MID",
"controllable": false,
"low-threshold": false,
"low-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,
"low-threshold": false,
"high-threshold": false,
"low-crit-threshold": false
}
],

View File

@ -1,11 +1,13 @@
#!/bin/bash
function SafePwrCycle() {
function SafeReboot() {
sync ; sync
sudo umount -fa > /dev/null 2&>1
# Write CPLD register to initiate cold reboot
sudo echo 0 > /sys/bus/i2c/devices/i2c-0/0-0041/cold_reset
# Turn off watchdog monitor gpio for correct reboot-cause
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": [],
"devices_to_ignore": [
"asic",
"psu.temperature",
"fan",
"psu"
"psu.temperature"
],
"user_defined_checkers": [],
"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_FANS_PER_DRAWER = 1
MAX_7215_PSU = 2
MAX_7215_THERMAL = 4
MAX_7215_THERMAL = 5
CPLD_DIR = "/sys/bus/i2c/devices/0-0041/"
SYSLOG_IDENTIFIER = "chassis"
@ -92,7 +92,7 @@ class Chassis(ChassisBase):
drawer = drawer_ctor(drawer_index)
self._fan_drawer_list.append(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
drawer._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
to pass a description of the reboot cause.
"""
# The ixs7215 CPLD does not have a hardware reboot cause register so
# the hardware portion of reboot cause can't be implemented
return (ChassisBase.REBOOT_CAUSE_NON_HARDWARE, None)
value = self._read_sysfs_file(CPLD_DIR+"last_reset_cause")
thermal = self._read_sysfs_file(CPLD_DIR+"temp_event_status")
if (value == 'cold_reset'):
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):
"""

View File

@ -175,7 +175,7 @@ class Component(ComponentBase):
return self._get_cpld_version(self.index)
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
def install_firmware(self, image_path):

View File

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

View File

@ -16,8 +16,8 @@ try:
except ImportError as e:
raise ImportError(str(e) + "- required module not found")
MAX_IXS7215_FAN_SPEED = 24000
WORKING_IXS7215_FAN_SPEED = 2400
MAX_IXS7215_FAN_SPEED = 23000
WORKING_IXS7215_FAN_SPEED = 2300
sonic_logger = logger.Logger('fan')
@ -26,10 +26,10 @@ sonic_logger = logger.Logger('fan')
class Fan(FanBase):
"""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
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)):
hwmon_node = os.listdir(i2c_path)[0]
EMC2302_DIR = i2c_path + hwmon_node + '/'
@ -38,6 +38,7 @@ class Fan(FanBase):
# Fan is 1-based in Nokia platforms
self.index = fan_index + 1
self.fan_drawer = fan_drawer
self.chassis_model = chassis_model
self.set_fan_speed_reg = EMC2302_DIR+"pwm{}".format(self.index)
self.get_fan_speed_reg = EMC2302_DIR+"fan{}_input".format(self.index)
self.max_fan_speed = MAX_IXS7215_FAN_SPEED
@ -116,7 +117,16 @@ class Fan(FanBase):
Returns:
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):
"""
@ -169,8 +179,14 @@ class Fan(FanBase):
A string, either FAN_DIRECTION_INTAKE or
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):
"""
@ -219,8 +235,10 @@ class Fan(FanBase):
which is considered tolerable
"""
if self.get_presence():
# The tolerance value is fixed as 25% for this platform
tolerance = 50
if self.get_target_speed()<50:
tolerance=60
else:
tolerance = 25
else:
tolerance = 0

View File

@ -19,6 +19,8 @@ except ImportError as e:
sonic_logger = logger.Logger('psu')
INA230_DIR = "/sys/bus/i2c/devices/0-0040/iio:device0/"
CPLD_DIR = "/sys/bus/i2c/devices/0-0041/"
PSU_GPIO_DIR = ["/sys/class/gpio/gpio61/value", "/sys/class/gpio/gpio62/value"]
class Psu(PsuBase):
"""Nokia platform-specific PSU class for 7215 """
@ -32,6 +34,8 @@ class Psu(PsuBase):
# PSU eeprom
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):
# On successful read, returns the value read from given
@ -80,8 +84,8 @@ class Psu(PsuBase):
Integer: Number of active PSU's
"""
active_psus = 0
psu1_good = self._read_sysfs_file(CPLD_DIR+"psu1_power_good")
psu2_good = self._read_sysfs_file(CPLD_DIR+"psu2_power_good")
psu1_good = self._read_sysfs_file(PSU_GPIO_DIR[0])
psu2_good = self._read_sysfs_file(PSU_GPIO_DIR[1])
active_psus = int(psu1_good) + int(psu2_good)
@ -150,7 +154,7 @@ class Psu(PsuBase):
Returns:
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)
if psu_status == '1':
@ -212,6 +216,26 @@ class Psu(PsuBase):
"""
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):
"""
Indicate whether this device is replaceable.
@ -227,7 +251,7 @@ class Psu(PsuBase):
A boolean, True if PSU has stablized its output voltages and
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)
if psu_pg_status == '1':
@ -294,4 +318,4 @@ class Psu(PsuBase):
if status == "ERR":
return False
return True
return True

View File

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

View File

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

View File

@ -73,14 +73,22 @@ class ThermalInfo(ThermalPolicyInfoBase):
self._current_threshold_level = 0
self._num_fan_levels = 3
self._high_crital_threshold = 75
self._level_up_threshold = [[31,39,58,46],
[39,46,65,54],
[51,57,77,68]]
#THERMAL_NAME ("PCB BACK", "PCB FRONT", "PCB MID", "ASIC", "CPU CORE")
self._f2b_level_up_threshold = [[38,30,37,60,77],
[51,44,50,72,90],
[61,57,61,77,94]]
self._level_down_threshold = [[24,31,47,40],
[31,38,53,46],
[48,54,72,63]]
self._f2b_level_down_threshold = [[29,24,29,50,64],
[40,37,40,59,75],
[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):
"""
Collect thermal sensor temperature change status
@ -99,6 +107,13 @@ class ThermalInfo(ThermalPolicyInfoBase):
for index in range(num_of_thermals):
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
max_level =0
@ -106,10 +121,10 @@ class ThermalInfo(ThermalPolicyInfoBase):
for index in range(num_of_thermals):
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:
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:
min_level[index]=level

View File

@ -6,9 +6,8 @@ provides access to hardware watchdog
import os
import fcntl
import array
import time
from sonic_platform_base.watchdog_base import WatchdogBase
from sonic_py_common import logger
""" ioctl constants """
IO_WRITE = 0x40000000
@ -34,13 +33,12 @@ WDIOS_DISABLECARD = 0x0001
WDIOS_ENABLECARD = 0x0002
""" 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
sonic_logger = logger.Logger()
class WatchdogImplBase(WatchdogBase):
"""
Base class that implements common logic for interacting
@ -53,34 +51,53 @@ class WatchdogImplBase(WatchdogBase):
@param wd_device_path Path to watchdog device
"""
super(WatchdogImplBase, self).__init__()
self.watchdog=""
self.watchdog_path = wd_device_path
self.watchdog = os.open(self.watchdog_path, os.O_WRONLY)
# Opening a watchdog descriptor starts
# watchdog timer; by default it should be stopped
self._disablewatchdog()
self.armed = False
self.watchdog_gpio_reg = WD_GPIO_PATH
self.wd_state_reg = WD_SYSFS_PATH+"state"
self.wd_timeout_reg = WD_SYSFS_PATH+"timeout"
self.wd_timeleft_reg = WD_SYSFS_PATH+"timeleft"
self.timeout = self._gettimeout()
def disarm(self):
"""
Disarm the hardware watchdog
Returns:
A boolean, True if watchdog is disarmed successfully, False
if not
"""
sonic_logger.log_info(" Debug disarm watchdog ")
def _read_sysfs_file(self, sysfs_file):
# On successful read, returns the value read from given
# reg_name and on failure returns 'ERR'
rv = 'ERR'
if (not os.path.isfile(sysfs_file)):
return rv
try:
self._disablewatchdog()
self.armed = False
self.timeout = 0
except IOError:
return False
with open(sysfs_file, 'r') as fd:
rv = fd.read()
except Exception as e:
rv = 'ERR'
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):
"""
@ -89,6 +106,23 @@ class WatchdogImplBase(WatchdogBase):
req = array.array('h', [WDIOS_DISABLECARD])
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):
"""
@ -107,11 +141,10 @@ class WatchdogImplBase(WatchdogBase):
Get watchdog timeout
@return watchdog timeout
"""
timeout=0
timeout=self._read_sysfs_file(self.wd_timeout_reg)
req = array.array('I', [0])
fcntl.ioctl(self.watchdog, WDIOC_GETTIMEOUT, req, True)
return int(req[0])
return timeout
def _gettimeleft(self):
"""
@ -128,47 +161,62 @@ class WatchdogImplBase(WatchdogBase):
"""
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:
if self.timeout != seconds:
self.timeout = self._settimeout(seconds)
if self.armed:
if self.is_armed():
self._keepalive()
else:
sonic_logger.log_info(" Debug arm watchdog5 ")
self._enablewatchdog()
self.armed = True
ret = self.timeout
except IOError:
pass
if(ret == seconds):
self._write_sysfs_file(self.watchdog_gpio_reg, 0)
return ret
def _enablewatchdog(self):
"""
Turn on the watchdog timer
def disarm(self):
"""
Implements disarm WatchdogBase API
req = array.array('h', [WDIOS_ENABLECARD])
fcntl.ioctl(self.watchdog, WDIOC_SETOPTIONS, req, False)
def _keepalive(self):
Returns:
A boolean, True if watchdog is disarmed successfully, False
if not
"""
Keep alive watchdog timer
"""
fcntl.ioctl(self.watchdog, WDIOC_KEEPALIVE)
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:
self._disablewatchdog()
self.timeout = 0
except IOError:
return False
return True
def is_armed(self):
"""
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):
"""
@ -177,10 +225,7 @@ class WatchdogImplBase(WatchdogBase):
timeleft = WD_COMMON_ERROR
if self.armed:
try:
timeleft = self._gettimeleft()
except IOError:
pass
if self.is_armed():
timeleft=self._read_sysfs_file(self.wd_timeleft_reg)
return timeleft
return int(timeleft)

View File

@ -33,7 +33,7 @@ build:
(for mod in $(MODULE_DIRS); do \
cd $(MOD_SRC_DIR)/../$(PRESTERA_MODULE_SRC)/; \
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); \
cp *.ko $(MOD_SRC_DIR)/$${mod}/$(MRVL_MODULE_DIR)/; \
cd $(MOD_SRC_DIR); \

View File

@ -1,4 +1,6 @@
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/cpu_wdt.service etc/systemd/system
7215/sonic_platform-1.0-py3-none-any.whl usr/share/sonic/device/arm64-nokia_ixs7215_52xb-r0
../mrvl-prestera/platform/arm64/ac5x/* /

View File

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