[Device]: Add new CIG device CS6436-54P and CS5435-54P, also update code for CS6436-56P (#4157)

* Add new CIG device CS6436-54P and CS5435-54P, also update code for CS6436-56P

* security kernel update to 4.9.189 for CIG devices

* security kernel update to 4.9.189 for CIG devices

* Update rules

Update rule file
This commit is contained in:
michealylj1 2020-02-18 06:09:15 +08:00 committed by Abhishek Dosi
parent 91e64f063e
commit bb73687514
90 changed files with 20272 additions and 1459 deletions

View File

@ -0,0 +1,111 @@
{# Default values which will be used if no actual configura available #}
{% set default_cable = '40m' %}
{% set default_speed = '10G' %}
{% set default_ports_num = 54 -%}
{# Port configuration to cable length look-up table #}
{# Each record describes mapping of DUT (DUT port) role and neighbor role to cable length #}
{# Roles described in the minigraph #}
{% set ports2cable = {
'torrouter_server' : '5m',
'leafrouter_torrouter' : '40m',
'spinerouter_leafrouter' : '300m'
}
%}
{%- macro cable_length(port_name) -%}
{%- set cable_len = [] -%}
{%- for local_port in DEVICE_NEIGHBOR -%}
{%- if local_port == port_name -%}
{%- if DEVICE_NEIGHBOR_METADATA[DEVICE_NEIGHBOR[local_port].name] -%}
{%- set neighbor = DEVICE_NEIGHBOR_METADATA[DEVICE_NEIGHBOR[local_port].name] -%}
{%- set neighbor_role = neighbor.type -%}
{%- set roles1 = switch_role + '_' + neighbor_role %}
{%- set roles2 = neighbor_role + '_' + switch_role -%}
{%- set roles1 = roles1 | lower -%}
{%- set roles2 = roles2 | lower -%}
{%- if roles1 in ports2cable -%}
{%- if cable_len.append(ports2cable[roles1]) -%}{%- endif -%}
{%- elif roles2 in ports2cable -%}
{%- if cable_len.append(ports2cable[roles2]) -%}{%- endif -%}
{%- endif -%}
{%- endif -%}
{%- endif -%}
{%- endfor -%}
{%- if cable_len -%}
{{ cable_len.0 }}
{%- else -%}
{{ default_cable }}
{%- endif -%}
{% endmacro %}
{%- if DEVICE_METADATA is defined %}
{%- set switch_role = DEVICE_METADATA['localhost']['type'] %}
{%- endif -%}
{# Generate list of ports if not defined #}
{% if PORT is not defined %}
{% set PORT = [] %}
{% for port_idx in range(0,default_ports_num) %}
{% if PORT.append("Ethernet%d" % (port_idx)) %}{% endif %}
{% endfor %}
{% endif -%}
{% set port_names_list = [] %}
{% for port in PORT %}
{%- if port_names_list.append(port) %}{% endif %}
{% endfor %}
{% set port_names = port_names_list | join(',') -%}
{
"CABLE_LENGTH": {
"AZURE": {
{% for port in PORT %}
{% set cable = cable_length(port) -%}
"{{ port }}": "{{ cable }}"{%- if not loop.last -%},{% endif %}
{% endfor %}
}
},
"BUFFER_POOL": {
"ingress_lossless_pool": {
"size": "20971328",
"type": "ingress",
"mode": "static"
},
"ingress_lossy_pool": {
"size": "20971328",
"type": "ingress",
"mode": "static"
},
"egress_lossy_pool": {
"size": "20971328",
"type": "egress",
"mode": "static"
}
},
"BUFFER_PROFILE": {
"ingress_lossless_profile": {
"pool":"[BUFFER_POOL|ingress_lossless_pool]",
"xon":"78400",
"xoff":"132160",
"size":"3584",
"static_th":"82880"
},
"ingress_lossy_profile": {
"pool":"[BUFFER_POOL|ingress_lossy_pool]",
"size":"3584",
"dynamic_th":"-1"
},
"egress_lossy_profile": {
"pool":"[BUFFER_POOL|egress_lossy_pool]",
"size":"3584",
"dynamic_th":"-4"
}
},
"BUFFER_PG": {
},
"BUFFER_QUEUE": {
}
}

View File

@ -0,0 +1,17 @@
# PG lossless profiles.
# speed cable size xon xoff threshold
10000 5m 3584 32256 59136 36736
25000 5m 3584 41216 68096 45696
40000 5m 3584 47488 74368 51968
50000 5m 3584 52864 79744 57344
100000 5m 3584 78400 132160 82880
10000 40m 3584 32256 59136 36736
25000 40m 3584 41216 68096 45696
40000 40m 3584 47488 74368 51968
50000 40m 3584 52864 79744 57344
100000 40m 3584 78400 132160 82880
10000 300m 3584 32256 65856 36736
25000 300m 3584 41216 84672 45696
40000 300m 3584 47488 101024 51968
50000 300m 3584 52864 113120 57344
100000 300m 3584 78400 198688 82880

View File

@ -0,0 +1,55 @@
# name lanes alias index speed
Ethernet0 8 Ethernet1/1 1 10000
Ethernet1 9 Ethernet2/1 2 10000
Ethernet2 10 Ethernet3/1 3 10000
Ethernet3 11 Ethernet4/1 4 10000
Ethernet4 12 Ethernet5/1 5 10000
Ethernet5 13 Ethernet6/1 6 10000
Ethernet6 14 Ethernet7/1 7 10000
Ethernet7 15 Ethernet8/1 8 10000
Ethernet8 16 Ethernet9/1 9 10000
Ethernet9 17 Ethernet10/1 10 10000
Ethernet10 18 Ethernet11/1 11 10000
Ethernet11 19 Ethernet12/1 12 10000
Ethernet12 20 Ethernet13/1 13 10000
Ethernet13 21 Ethernet14/1 14 10000
Ethernet14 22 Ethernet15/1 15 10000
Ethernet15 23 Ethernet16/1 16 10000
Ethernet16 32 Ethernet17/1 17 10000
Ethernet17 33 Ethernet18/1 18 10000
Ethernet18 34 Ethernet19/1 19 10000
Ethernet19 35 Ethernet20/1 20 10000
Ethernet20 40 Ethernet21/1 21 10000
Ethernet21 41 Ethernet22/1 22 10000
Ethernet22 42 Ethernet23/1 23 10000
Ethernet23 43 Ethernet24/1 24 10000
Ethernet24 48 Ethernet25/1 25 10000
Ethernet25 49 Ethernet26/1 26 10000
Ethernet26 50 Ethernet27/1 27 10000
Ethernet27 51 Ethernet28/1 28 10000
Ethernet28 56 Ethernet29/1 29 10000
Ethernet29 57 Ethernet30/1 30 10000
Ethernet30 58 Ethernet31/1 31 10000
Ethernet31 59 Ethernet32/1 32 10000
Ethernet32 64 Ethernet33/1 33 10000
Ethernet33 65 Ethernet34/1 34 10000
Ethernet34 66 Ethernet35/1 35 10000
Ethernet35 67 Ethernet36/1 36 10000
Ethernet36 68 Ethernet37/1 37 10000
Ethernet37 69 Ethernet38/1 38 10000
Ethernet38 70 Ethernet39/1 39 10000
Ethernet39 71 Ethernet40/1 40 10000
Ethernet40 72 Ethernet41/1 41 10000
Ethernet41 73 Ethernet42/1 42 10000
Ethernet42 74 Ethernet43/1 43 10000
Ethernet43 75 Ethernet44/1 44 10000
Ethernet44 76 Ethernet45/1 45 10000
Ethernet45 77 Ethernet46/1 46 10000
Ethernet46 78 Ethernet47/1 47 10000
Ethernet47 79 Ethernet48/1 48 10000
Ethernet48 84,85,86,87 Ethernet49/1 49 100000
Ethernet49 80,81,82,83 Ethernet50/1 50 100000
Ethernet50 108,109,110,111 Ethernet51/1 51 100000
Ethernet51 104,105,106,107 Ethernet52/1 52 100000
Ethernet52 116,117,118,119 Ethernet53/1 53 100000
Ethernet53 112,113,114,115 Ethernet54/1 54 100000

View File

@ -1,60 +1,58 @@
init start stage unit=0 low-level
init set port-map unit=0 port=0 eth-macro=2 lane=0 max-speed=25g active=true
init set port-map unit=0 port=1 eth-macro=2 lane=1 max-speed=25g active=true
init set port-map unit=0 port=2 eth-macro=2 lane=2 max-speed=25g active=true
init set port-map unit=0 port=3 eth-macro=2 lane=3 max-speed=25g active=true
init set port-map unit=0 port=4 eth-macro=3 lane=0 max-speed=25g active=true
init set port-map unit=0 port=5 eth-macro=3 lane=1 max-speed=25g active=true
init set port-map unit=0 port=6 eth-macro=3 lane=2 max-speed=25g active=true
init set port-map unit=0 port=7 eth-macro=3 lane=3 max-speed=25g active=true
init set port-map unit=0 port=8 eth-macro=4 lane=0 max-speed=25g active=true
init set port-map unit=0 port=9 eth-macro=4 lane=1 max-speed=25g active=true
init set port-map unit=0 port=10 eth-macro=4 lane=2 max-speed=25g active=true
init set port-map unit=0 port=11 eth-macro=4 lane=3 max-speed=25g active=true
init set port-map unit=0 port=12 eth-macro=5 lane=0 max-speed=25g active=true
init set port-map unit=0 port=13 eth-macro=5 lane=1 max-speed=25g active=true
init set port-map unit=0 port=14 eth-macro=5 lane=2 max-speed=25g active=true
init set port-map unit=0 port=15 eth-macro=5 lane=3 max-speed=25g active=true
init set port-map unit=0 port=16 eth-macro=8 lane=0 max-speed=25g active=true
init set port-map unit=0 port=17 eth-macro=8 lane=1 max-speed=25g active=true
init set port-map unit=0 port=18 eth-macro=8 lane=2 max-speed=25g active=true
init set port-map unit=0 port=19 eth-macro=8 lane=3 max-speed=25g active=true
init set port-map unit=0 port=20 eth-macro=10 lane=0 max-speed=25g active=true
init set port-map unit=0 port=21 eth-macro=10 lane=1 max-speed=25g active=true
init set port-map unit=0 port=22 eth-macro=10 lane=2 max-speed=25g active=true
init set port-map unit=0 port=23 eth-macro=10 lane=3 max-speed=25g active=true
init set port-map unit=0 port=24 eth-macro=12 lane=0 max-speed=25g active=true
init set port-map unit=0 port=25 eth-macro=12 lane=1 max-speed=25g active=true
init set port-map unit=0 port=26 eth-macro=12 lane=2 max-speed=25g active=true
init set port-map unit=0 port=27 eth-macro=12 lane=3 max-speed=25g active=true
init set port-map unit=0 port=28 eth-macro=14 lane=0 max-speed=25g active=true
init set port-map unit=0 port=29 eth-macro=14 lane=1 max-speed=25g active=true
init set port-map unit=0 port=30 eth-macro=14 lane=2 max-speed=25g active=true
init set port-map unit=0 port=31 eth-macro=14 lane=3 max-speed=25g active=true
init set port-map unit=0 port=32 eth-macro=16 lane=0 max-speed=25g active=true
init set port-map unit=0 port=33 eth-macro=16 lane=1 max-speed=25g active=true
init set port-map unit=0 port=34 eth-macro=16 lane=2 max-speed=25g active=true
init set port-map unit=0 port=35 eth-macro=16 lane=3 max-speed=25g active=true
init set port-map unit=0 port=36 eth-macro=17 lane=0 max-speed=25g active=true
init set port-map unit=0 port=37 eth-macro=17 lane=1 max-speed=25g active=true
init set port-map unit=0 port=38 eth-macro=17 lane=2 max-speed=25g active=true
init set port-map unit=0 port=39 eth-macro=17 lane=3 max-speed=25g active=true
init set port-map unit=0 port=40 eth-macro=18 lane=0 max-speed=25g active=true
init set port-map unit=0 port=41 eth-macro=18 lane=1 max-speed=25g active=true
init set port-map unit=0 port=42 eth-macro=18 lane=2 max-speed=25g active=true
init set port-map unit=0 port=43 eth-macro=18 lane=3 max-speed=25g active=true
init set port-map unit=0 port=44 eth-macro=19 lane=0 max-speed=25g active=true
init set port-map unit=0 port=45 eth-macro=19 lane=1 max-speed=25g active=true
init set port-map unit=0 port=46 eth-macro=19 lane=2 max-speed=25g active=true
init set port-map unit=0 port=47 eth-macro=19 lane=3 max-speed=25g active=true
init set port-map unit=0 port=0 eth-macro=2 lane=0 max-speed=10g active=true
init set port-map unit=0 port=1 eth-macro=2 lane=1 max-speed=10g active=true
init set port-map unit=0 port=2 eth-macro=2 lane=2 max-speed=10g active=true
init set port-map unit=0 port=3 eth-macro=2 lane=3 max-speed=10g active=true
init set port-map unit=0 port=4 eth-macro=3 lane=0 max-speed=10g active=true
init set port-map unit=0 port=5 eth-macro=3 lane=1 max-speed=10g active=true
init set port-map unit=0 port=6 eth-macro=3 lane=2 max-speed=10g active=true
init set port-map unit=0 port=7 eth-macro=3 lane=3 max-speed=10g active=true
init set port-map unit=0 port=8 eth-macro=4 lane=0 max-speed=10g active=true
init set port-map unit=0 port=9 eth-macro=4 lane=1 max-speed=10g active=true
init set port-map unit=0 port=10 eth-macro=4 lane=2 max-speed=10g active=true
init set port-map unit=0 port=11 eth-macro=4 lane=3 max-speed=10g active=true
init set port-map unit=0 port=12 eth-macro=5 lane=0 max-speed=10g active=true
init set port-map unit=0 port=13 eth-macro=5 lane=1 max-speed=10g active=true
init set port-map unit=0 port=14 eth-macro=5 lane=2 max-speed=10g active=true
init set port-map unit=0 port=15 eth-macro=5 lane=3 max-speed=10g active=true
init set port-map unit=0 port=16 eth-macro=8 lane=0 max-speed=10g active=true
init set port-map unit=0 port=17 eth-macro=8 lane=1 max-speed=10g active=true
init set port-map unit=0 port=18 eth-macro=8 lane=2 max-speed=10g active=true
init set port-map unit=0 port=19 eth-macro=8 lane=3 max-speed=10g active=true
init set port-map unit=0 port=20 eth-macro=10 lane=0 max-speed=10g active=true
init set port-map unit=0 port=21 eth-macro=10 lane=1 max-speed=10g active=true
init set port-map unit=0 port=22 eth-macro=10 lane=2 max-speed=10g active=true
init set port-map unit=0 port=23 eth-macro=10 lane=3 max-speed=10g active=true
init set port-map unit=0 port=24 eth-macro=12 lane=0 max-speed=10g active=true
init set port-map unit=0 port=25 eth-macro=12 lane=1 max-speed=10g active=true
init set port-map unit=0 port=26 eth-macro=12 lane=2 max-speed=10g active=true
init set port-map unit=0 port=27 eth-macro=12 lane=3 max-speed=10g active=true
init set port-map unit=0 port=28 eth-macro=14 lane=0 max-speed=10g active=true
init set port-map unit=0 port=29 eth-macro=14 lane=1 max-speed=10g active=true
init set port-map unit=0 port=30 eth-macro=14 lane=2 max-speed=10g active=true
init set port-map unit=0 port=31 eth-macro=14 lane=3 max-speed=10g active=true
init set port-map unit=0 port=32 eth-macro=16 lane=0 max-speed=10g active=true
init set port-map unit=0 port=33 eth-macro=16 lane=1 max-speed=10g active=true
init set port-map unit=0 port=34 eth-macro=16 lane=2 max-speed=10g active=true
init set port-map unit=0 port=35 eth-macro=16 lane=3 max-speed=10g active=true
init set port-map unit=0 port=36 eth-macro=17 lane=0 max-speed=10g active=true
init set port-map unit=0 port=37 eth-macro=17 lane=1 max-speed=10g active=true
init set port-map unit=0 port=38 eth-macro=17 lane=2 max-speed=10g active=true
init set port-map unit=0 port=39 eth-macro=17 lane=3 max-speed=10g active=true
init set port-map unit=0 port=40 eth-macro=18 lane=0 max-speed=10g active=true
init set port-map unit=0 port=41 eth-macro=18 lane=1 max-speed=10g active=true
init set port-map unit=0 port=42 eth-macro=18 lane=2 max-speed=10g active=true
init set port-map unit=0 port=43 eth-macro=18 lane=3 max-speed=10g active=true
init set port-map unit=0 port=44 eth-macro=19 lane=0 max-speed=10g active=true
init set port-map unit=0 port=45 eth-macro=19 lane=1 max-speed=10g active=true
init set port-map unit=0 port=46 eth-macro=19 lane=2 max-speed=10g active=true
init set port-map unit=0 port=47 eth-macro=19 lane=3 max-speed=10g active=true
init set port-map unit=0 port=48 eth-macro=21 lane=0 max-speed=100g active=true
init set port-map unit=0 port=49 eth-macro=20 lane=0 max-speed=100g active=true
init set port-map unit=0 port=50 eth-macro=23 lane=0 max-speed=100g active=true
init set port-map unit=0 port=51 eth-macro=22 lane=0 max-speed=100g active=true
init set port-map unit=0 port=52 eth-macro=27 lane=0 max-speed=100g active=true
init set port-map unit=0 port=53 eth-macro=26 lane=0 max-speed=100g active=true
init set port-map unit=0 port=54 eth-macro=29 lane=0 max-speed=100g active=true
init set port-map unit=0 port=55 eth-macro=28 lane=0 max-speed=100g active=true
init set port-map unit=0 port=50 eth-macro=27 lane=0 max-speed=100g active=true
init set port-map unit=0 port=51 eth-macro=26 lane=0 max-speed=100g active=true
init set port-map unit=0 port=52 eth-macro=29 lane=0 max-speed=100g active=true
init set port-map unit=0 port=53 eth-macro=28 lane=0 max-speed=100g active=true
init set port-map unit=0 port=129 eth-macro=0 lane=1 max-speed=10g active=true guarantee=true cpi=true
init set port-map unit=0 port=130 eth-macro=0 lane=0 max-speed=10g active=true guarantee=true cpi=true init-done=true
init start stage unit=0 task-rsrc
@ -110,12 +108,10 @@ phy set lane-swap unit=0 portlist=46 lane-cnt=1 property=tx data=0x2
phy set lane-swap unit=0 portlist=47 lane-cnt=1 property=tx data=0x3
phy set lane-swap unit=0 portlist=48 lane-cnt=4 property=tx data=0x3.0.1.2
phy set lane-swap unit=0 portlist=49 lane-cnt=4 property=tx data=0x3.2.1.0
phy set lane-swap unit=0 portlist=50 lane-cnt=4 property=tx data=0x0.1.2.3
phy set lane-swap unit=0 portlist=51 lane-cnt=4 property=tx data=0x3.2.0.1
phy set lane-swap unit=0 portlist=50 lane-cnt=4 property=tx data=0x3.2.1.0
phy set lane-swap unit=0 portlist=51 lane-cnt=4 property=tx data=0x3.2.1.0
phy set lane-swap unit=0 portlist=52 lane-cnt=4 property=tx data=0x3.2.1.0
phy set lane-swap unit=0 portlist=53 lane-cnt=4 property=tx data=0x3.2.1.0
phy set lane-swap unit=0 portlist=54 lane-cnt=4 property=tx data=0x3.2.1.0
phy set lane-swap unit=0 portlist=55 lane-cnt=4 property=tx data=0x3.2.1.0
phy set lane-swap unit=0 portlist=129 lane-cnt=1 property=tx data=0x1
phy set lane-swap unit=0 portlist=130 lane-cnt=1 property=tx data=0x0
phy set lane-swap unit=0 portlist=0 lane-cnt=1 property=rx data=0x0
@ -168,12 +164,10 @@ phy set lane-swap unit=0 portlist=46 lane-cnt=1 property=rx data=0x0
phy set lane-swap unit=0 portlist=47 lane-cnt=1 property=rx data=0x3
phy set lane-swap unit=0 portlist=48 lane-cnt=4 property=rx data=0x3.1.0.2
phy set lane-swap unit=0 portlist=49 lane-cnt=4 property=rx data=0x3.2.1.0
phy set lane-swap unit=0 portlist=50 lane-cnt=4 property=rx data=0x3.0.1.2
phy set lane-swap unit=0 portlist=51 lane-cnt=4 property=rx data=0x3.2.1.0
phy set lane-swap unit=0 portlist=50 lane-cnt=4 property=rx data=0x1.0.3.2
phy set lane-swap unit=0 portlist=51 lane-cnt=4 property=rx data=0x2.0.1.3
phy set lane-swap unit=0 portlist=52 lane-cnt=4 property=rx data=0x1.0.3.2
phy set lane-swap unit=0 portlist=53 lane-cnt=4 property=rx data=0x2.0.1.3
phy set lane-swap unit=0 portlist=54 lane-cnt=4 property=rx data=0x1.0.3.2
phy set lane-swap unit=0 portlist=55 lane-cnt=4 property=rx data=0x1.0.3.2
phy set lane-swap unit=0 portlist=53 lane-cnt=4 property=rx data=0x1.0.3.2
phy set lane-swap unit=0 portlist=129 lane-cnt=1 property=rx data=0x1
phy set lane-swap unit=0 portlist=130 lane-cnt=1 property=rx data=0x0
phy set polarity-rev unit=0 portlist=0 lane-cnt=1 property=tx data=0x0
@ -230,8 +224,6 @@ phy set polarity-rev unit=0 portlist=50 lane-cnt=4 property=tx data=0x0.0.0.0
phy set polarity-rev unit=0 portlist=51 lane-cnt=4 property=tx data=0x0.0.0.0
phy set polarity-rev unit=0 portlist=52 lane-cnt=4 property=tx data=0x0.0.0.0
phy set polarity-rev unit=0 portlist=53 lane-cnt=4 property=tx data=0x0.0.0.0
phy set polarity-rev unit=0 portlist=54 lane-cnt=4 property=tx data=0x0.0.0.0
phy set polarity-rev unit=0 portlist=55 lane-cnt=4 property=tx data=0x0.0.0.0
phy set polarity-rev unit=0 portlist=129 lane-cnt=1 property=tx data=0x0
phy set polarity-rev unit=0 portlist=130 lane-cnt=1 property=tx data=0x0
phy set polarity-rev unit=0 portlist=0 lane-cnt=1 property=rx data=0x0
@ -284,12 +276,10 @@ phy set polarity-rev unit=0 portlist=46 lane-cnt=1 property=rx data=0x0
phy set polarity-rev unit=0 portlist=47 lane-cnt=1 property=rx data=0x0
phy set polarity-rev unit=0 portlist=48 lane-cnt=4 property=rx data=0x0.1.1.0
phy set polarity-rev unit=0 portlist=49 lane-cnt=4 property=rx data=0x0.0.0.0
phy set polarity-rev unit=0 portlist=50 lane-cnt=4 property=rx data=0x1.1.1.1
phy set polarity-rev unit=0 portlist=50 lane-cnt=4 property=rx data=0x1.1.1.0
phy set polarity-rev unit=0 portlist=51 lane-cnt=4 property=rx data=0x0.0.0.0
phy set polarity-rev unit=0 portlist=52 lane-cnt=4 property=rx data=0x1.1.1.0
phy set polarity-rev unit=0 portlist=53 lane-cnt=4 property=rx data=0x0.0.0.0
phy set polarity-rev unit=0 portlist=54 lane-cnt=4 property=rx data=0x1.1.1.0
phy set polarity-rev unit=0 portlist=55 lane-cnt=4 property=rx data=0x0.0.0.0
phy set polarity-rev unit=0 portlist=129 lane-cnt=1 property=rx data=0x0
phy set polarity-rev unit=0 portlist=130 lane-cnt=1 property=rx data=0x0
phy set pre-emphasis unit=0 portlist=0 lane-cnt=1 property=c2 data=0x2
@ -508,14 +498,6 @@ phy set pre-emphasis unit=0 portlist=53 lane-cnt=4 property=c2 data=0x2.2.2.2
phy set pre-emphasis unit=0 portlist=53 lane-cnt=4 property=cn1 data=0x0.0.0.0
phy set pre-emphasis unit=0 portlist=53 lane-cnt=4 property=c0 data=0x1b.1b.1b.1b
phy set pre-emphasis unit=0 portlist=53 lane-cnt=4 property=c1 data=0x6.6.6.6
phy set pre-emphasis unit=0 portlist=54 lane-cnt=4 property=c2 data=0x2.2.2.2
phy set pre-emphasis unit=0 portlist=54 lane-cnt=4 property=cn1 data=0x0.0.0.0
phy set pre-emphasis unit=0 portlist=54 lane-cnt=4 property=c0 data=0x1b.1b.1b.1b
phy set pre-emphasis unit=0 portlist=54 lane-cnt=4 property=c1 data=0x6.6.6.6
phy set pre-emphasis unit=0 portlist=55 lane-cnt=4 property=c2 data=0x2.2.2.2
phy set pre-emphasis unit=0 portlist=55 lane-cnt=4 property=cn1 data=0x0.0.0.0
phy set pre-emphasis unit=0 portlist=55 lane-cnt=4 property=c0 data=0x1b.1b.1b.1b
phy set pre-emphasis unit=0 portlist=55 lane-cnt=4 property=c1 data=0x6.6.6.6
phy set pre-emphasis unit=0 portlist=129 lane-cnt=1 property=c2 data=0x1
phy set pre-emphasis unit=0 portlist=129 lane-cnt=1 property=cn1 data=0x1
phy set pre-emphasis unit=0 portlist=129 lane-cnt=1 property=c0 data=0x2
@ -524,62 +506,60 @@ phy set pre-emphasis unit=0 portlist=130 lane-cnt=1 property=c2 data=0x1
phy set pre-emphasis unit=0 portlist=130 lane-cnt=1 property=cn1 data=0x0
phy set pre-emphasis unit=0 portlist=130 lane-cnt=1 property=c0 data=0x2
phy set pre-emphasis unit=0 portlist=130 lane-cnt=1 property=c1 data=0x3
port set property unit=0 portlist=0 speed=25g
port set property unit=0 portlist=1 speed=25g
port set property unit=0 portlist=2 speed=25g
port set property unit=0 portlist=3 speed=25g
port set property unit=0 portlist=4 speed=25g
port set property unit=0 portlist=5 speed=25g
port set property unit=0 portlist=6 speed=25g
port set property unit=0 portlist=7 speed=25g
port set property unit=0 portlist=8 speed=25g
port set property unit=0 portlist=9 speed=25g
port set property unit=0 portlist=10 speed=25g
port set property unit=0 portlist=11 speed=25g
port set property unit=0 portlist=12 speed=25g
port set property unit=0 portlist=13 speed=25g
port set property unit=0 portlist=14 speed=25g
port set property unit=0 portlist=15 speed=25g
port set property unit=0 portlist=16 speed=25g
port set property unit=0 portlist=17 speed=25g
port set property unit=0 portlist=18 speed=25g
port set property unit=0 portlist=19 speed=25g
port set property unit=0 portlist=20 speed=25g
port set property unit=0 portlist=21 speed=25g
port set property unit=0 portlist=22 speed=25g
port set property unit=0 portlist=23 speed=25g
port set property unit=0 portlist=24 speed=25g
port set property unit=0 portlist=25 speed=25g
port set property unit=0 portlist=26 speed=25g
port set property unit=0 portlist=27 speed=25g
port set property unit=0 portlist=28 speed=25g
port set property unit=0 portlist=29 speed=25g
port set property unit=0 portlist=30 speed=25g
port set property unit=0 portlist=31 speed=25g
port set property unit=0 portlist=32 speed=25g
port set property unit=0 portlist=33 speed=25g
port set property unit=0 portlist=34 speed=25g
port set property unit=0 portlist=35 speed=25g
port set property unit=0 portlist=36 speed=25g
port set property unit=0 portlist=37 speed=25g
port set property unit=0 portlist=38 speed=25g
port set property unit=0 portlist=39 speed=25g
port set property unit=0 portlist=40 speed=25g
port set property unit=0 portlist=41 speed=25g
port set property unit=0 portlist=42 speed=25g
port set property unit=0 portlist=43 speed=25g
port set property unit=0 portlist=44 speed=25g
port set property unit=0 portlist=45 speed=25g
port set property unit=0 portlist=46 speed=25g
port set property unit=0 portlist=47 speed=25g
port set property unit=0 portlist=0 speed=10g
port set property unit=0 portlist=1 speed=10g
port set property unit=0 portlist=2 speed=10g
port set property unit=0 portlist=3 speed=10g
port set property unit=0 portlist=4 speed=10g
port set property unit=0 portlist=5 speed=10g
port set property unit=0 portlist=6 speed=10g
port set property unit=0 portlist=7 speed=10g
port set property unit=0 portlist=8 speed=10g
port set property unit=0 portlist=9 speed=10g
port set property unit=0 portlist=10 speed=10g
port set property unit=0 portlist=11 speed=10g
port set property unit=0 portlist=12 speed=10g
port set property unit=0 portlist=13 speed=10g
port set property unit=0 portlist=14 speed=10g
port set property unit=0 portlist=15 speed=10g
port set property unit=0 portlist=16 speed=10g
port set property unit=0 portlist=17 speed=10g
port set property unit=0 portlist=18 speed=10g
port set property unit=0 portlist=19 speed=10g
port set property unit=0 portlist=20 speed=10g
port set property unit=0 portlist=21 speed=10g
port set property unit=0 portlist=22 speed=10g
port set property unit=0 portlist=23 speed=10g
port set property unit=0 portlist=24 speed=10g
port set property unit=0 portlist=25 speed=10g
port set property unit=0 portlist=26 speed=10g
port set property unit=0 portlist=27 speed=10g
port set property unit=0 portlist=28 speed=10g
port set property unit=0 portlist=29 speed=10g
port set property unit=0 portlist=30 speed=10g
port set property unit=0 portlist=31 speed=10g
port set property unit=0 portlist=32 speed=10g
port set property unit=0 portlist=33 speed=10g
port set property unit=0 portlist=34 speed=10g
port set property unit=0 portlist=35 speed=10g
port set property unit=0 portlist=36 speed=10g
port set property unit=0 portlist=37 speed=10g
port set property unit=0 portlist=38 speed=10g
port set property unit=0 portlist=39 speed=10g
port set property unit=0 portlist=40 speed=10g
port set property unit=0 portlist=41 speed=10g
port set property unit=0 portlist=42 speed=10g
port set property unit=0 portlist=43 speed=10g
port set property unit=0 portlist=44 speed=10g
port set property unit=0 portlist=45 speed=10g
port set property unit=0 portlist=46 speed=10g
port set property unit=0 portlist=47 speed=10g
port set property unit=0 portlist=48 speed=100g
port set property unit=0 portlist=49 speed=100g
port set property unit=0 portlist=50 speed=100g
port set property unit=0 portlist=51 speed=100g
port set property unit=0 portlist=52 speed=100g
port set property unit=0 portlist=53 speed=100g
port set property unit=0 portlist=54 speed=100g
port set property unit=0 portlist=55 speed=100g
port set property unit=0 portlist=129 speed=10g
port set property unit=0 portlist=130 speed=1g
port set property unit=0 portlist=0 medium-type=sr
@ -636,8 +616,6 @@ port set property unit=0 portlist=50 medium-type=sr4
port set property unit=0 portlist=51 medium-type=sr4
port set property unit=0 portlist=52 medium-type=sr4
port set property unit=0 portlist=53 medium-type=sr4
port set property unit=0 portlist=54 medium-type=sr4
port set property unit=0 portlist=55 medium-type=sr4
port set property unit=0 portlist=129 medium-type=kr
port set property unit=0 portlist=130 medium-type=x
port advertise unit=0 portlist=129 speed-10g-kr
@ -696,7 +674,5 @@ port set property unit=0 portlist=50 admin=enable
port set property unit=0 portlist=51 admin=enable
port set property unit=0 portlist=52 admin=enable
port set property unit=0 portlist=53 admin=enable
port set property unit=0 portlist=54 admin=enable
port set property unit=0 portlist=55 admin=enable
port set property unit=0 portlist=129 admin=enable
port set property unit=0 portlist=130 admin=enable
port set property unit=0 portlist=129 admin=disable
port set property unit=0 portlist=130 admin=disable

View File

@ -0,0 +1 @@
{%- include 'qos_config.j2' %}

View File

@ -0,0 +1,3 @@
SAI_INIT_LED_CONFIG_FILE=/usr/share/sonic/hwsku/led.bin
SAI_INIT_CONFIG_FILE=/usr/share/sonic/hwsku/proc_init.nps
SAI_DSH_CONFIG_FILE=/usr/share/sonic/hwsku/port_config.nps

View File

@ -0,0 +1 @@
Cig-CS5435-54P t1

View File

@ -0,0 +1,4 @@
CONSOLE_PORT=0x3f8
CONSOLE_DEV=0
CONSOLE_SPEED=115200
ONIE_PLATFORM_EXTRA_CMDLINE_LINUX="pci=noaer"

View File

@ -0,0 +1,21 @@
#!/usr/bin/env python
try:
import exceptions
import binascii
import time
import optparse
import warnings
import os
import sys
from sonic_eeprom import eeprom_base
from sonic_eeprom import eeprom_tlvinfo
import subprocess
except ImportError, e:
raise ImportError (str(e) + "- required module not found")
class board(eeprom_tlvinfo.TlvInfoDecoder):
_TLV_INFO_MAX_LEN = 256
def __init__(self, name, path, cpld_root, ro):
self.eeprom_path = "/sys/bus/i2c/devices/7-0057/eeprom"
super(board, self).__init__(self.eeprom_path, 0, '', True)

View File

@ -0,0 +1,93 @@
#
# psuutil.py
# Platform-specific PSU status interface for SONiC
#
import os.path
import logging
try:
from sonic_psu.psu_base import PsuBase
except ImportError as e:
raise ImportError(str(e) + "- required module not found")
class PsuUtil(PsuBase):
"""Platform-specific PSUutil class"""
SYSFS_PSU_DIR = ["/sys/bus/i2c/devices/5-005a",
"/sys/bus/i2c/devices/5-005b"]
def __init__(self):
PsuBase.__init__(self)
# Get sysfs attribute
def get_attr_value(self, attr_path):
retval = 'ERR'
if (not os.path.isfile(attr_path)):
return retval
try:
with open(attr_path, 'r') as fd:
retval = fd.read()
except Exception as error:
logging.error("Unable to open %s file !", attr_path)
retval = retval.rstrip('\r\n')
return retval
def get_num_psus(self):
"""
Retrieves the number of PSUs available on the device
:return: An integer, the number of PSUs available on the device
"""
MAX_PSUS = 2
return MAX_PSUS
def get_psu_status(self, index):
"""
Retrieves the oprational status of power supply unit (PSU) defined
by index <index>
:param index: An integer, index of the PSU of which to query status
:return: Boolean, True if PSU is operating properly, False if PSU is\
faulty
"""
status = 0
attr_file = 'psu_power_good'
attr_path = self.SYSFS_PSU_DIR[index-1] +'/' + attr_file
attr_value = self.get_attr_value(attr_path)
if (attr_value != 'ERR'):
attr_value = int(attr_value, 16)
# Check for PSU status
if (attr_value == 1):
status = 1
return status
def get_psu_presence(self, index):
"""
Retrieves the presence status of power supply unit (PSU) defined
by index <index>
:param index: An integer, index of the PSU of which to query status
:return: Boolean, True if PSU is plugged, False if not
"""
status = 0
psu_absent = 0
attr_file ='psu_present'
attr_path = self.SYSFS_PSU_DIR[index-1] +'/' + attr_file
attr_value = self.get_attr_value(attr_path)
if (attr_value != 'ERR'):
attr_value = int(attr_value, 16)
# Check for PSU presence
if (attr_value == 1):
status = 1
return status

View File

@ -0,0 +1,250 @@
#!/usr/bin/env python
try:
import time
from sonic_sfp.sfputilbase import SfpUtilBase
except ImportError, e:
raise ImportError (str(e) + "- required module not found")
class SfpUtil(SfpUtilBase):
"""Platform specific SfpUtill class"""
_port_start = 1
_port_end = 54
_qsfp_port_start = 49
_ports_in_block = 54
_port_to_eeprom_mapping = {}
_global_port_pres_dict = {}
_port_to_i2c_mapping = {
1 : 8,
2 : 9,
3 : 10,
4 : 11,
5 : 12,
6 : 13,
7 : 14,
8 : 15,
9 : 16,
10: 17,
11 : 18,
12 : 19,
13 : 20,
14 : 21,
15 : 22,
16 : 23,
17 : 24,
18 : 25,
19 : 26,
20 : 27,
21 : 28,
22 : 29,
23 : 30,
24 : 31,
25 : 32,
26 : 33,
27 : 34,
28 : 35,
29 : 36,
30 : 37,
31 : 38,
32 : 39,
33 : 40,
34 : 41,
35 : 42,
36 : 43,
37 : 44,
38 : 45,
39 : 46,
40 : 47,
41 : 48,
42 : 49,
43 : 50,
44 : 51,
45 : 52,
46 : 53,
47 : 54,
48 : 55,
49 : 56,
50 : 57,
51 : 60,
52 : 61,
53 : 62,
54 : 63,
}
_qsfp_ports = range(_qsfp_port_start, _ports_in_block + 1)
def get_presence(self, port_num):
# Check for invalid port_num
if port_num < self._port_start or port_num > self._port_end:
return False
path = "/sys/bus/i2c/devices/{0}-0050/sfp_is_present"
port_ps = path.format(self._port_to_i2c_mapping[port_num])
try:
reg_file = open(port_ps)
except IOError as e:
print "Error: unable to open file: %s" % str(e)
return False
try:
reg_value = reg_file.readline().rstrip()
except IOError as e:
time.sleep(1)
try:
reg_value = reg_file.readline().rstrip()
except IOError as e:
print "Error:try again to read file failed: %s %s" % (str(e), port_ps)
reg_file.close()
return False
reg_file.close()
if reg_value == '1':
return True
reg_file.close()
if reg_value == '1':
return True
return False
def init_global_port_presence(self):
for port_num in range(self.port_start, (self.port_end + 1)):
self._global_port_pres_dict[port_num] = '0'
def __init__(self):
eeprom_path = '/sys/bus/i2c/devices/{0}-0050/sfp_eeprom'
for x in range(self._port_start, self._port_end + 1):
port_eeprom_path = eeprom_path.format(self._port_to_i2c_mapping[x])
self._port_to_eeprom_mapping[x] = port_eeprom_path
self.init_global_port_presence()
SfpUtilBase.__init__(self)
def reset(self, port_num):
# Check for invalid port_num
if port_num < self._port_start or port_num > self._port_end:
return False
path = "/sys/bus/i2c/devices/{0}-0050/sfp_port_reset"
port_ps = path.format(self._port_to_i2c_mapping[port_num])
try:
reg_file = open(port_ps, 'w')
except IOError as e:
print "Error: unable to open file: %s" % str(e)
return False
#toggle reset
reg_file.seek(0)
reg_file.write('1')
time.sleep(1)
reg_file.seek(0)
reg_file.write('0')
reg_file.close()
return True
def set_low_power_mode(self, port_num, lpmode):
# Check for invalid port_num
if port_num < self._qsfp_port_start or port_num > self._port_end:
return False
pre_value = self.get_presence(port_num)
if pre_value == False:
return False
path = "/sys/bus/i2c/devices/{0}-0050/sfp_lpmode"
port_ps = path.format(self._port_to_i2c_mapping[port_num])
try:
reg_file = open(port_ps,'w')
except IOError as e:
print "Error: unable to open file: %s" % str(e)
return False
reg_file.seek(0)
if lpmode == 1:
reg_file.write('1')
elif lpmode == 0:
reg_file.write('0')
reg_file.close()
return True
def get_low_power_mode(self, port_num):
# Check for invalid port_num
if port_num < self._qsfp_port_start or port_num > self._port_end:
return False
pre_value = self.get_presence(port_num)
if pre_value == False:
return False
path = "/sys/bus/i2c/devices/{0}-0050/sfp_lpmode"
port_ps = path.format(self._port_to_i2c_mapping[port_num])
try:
reg_file = open(port_ps)
except IOError as e:
print "Error: unable to open file:%s %s" % (str(e), port_ps)
return False
try:
reg_value = reg_file.readline().rstrip()
except IOError as e:
print "Error: unable to open file:%s %s" % (str(e), port_ps)
reg_file.close()
return False
reg_file.close()
if reg_value == '1':
return True
return False
def get_transceiver_change_event(self):
port_dict = {}
while True:
for port_num in range(self.port_start, (self.port_end + 1)):
presence = self.get_presence(port_num)
if(presence and self._global_port_pres_dict[port_num] == '0'):
self._global_port_pres_dict[port_num] = '1'
port_dict[port_num] = '1'
elif(not presence and
self._global_port_pres_dict[port_num] == '1'):
self._global_port_pres_dict[port_num] = '0'
port_dict[port_num] = '0'
if(len(port_dict) > 0):
return True, port_dict
time.sleep(0.5)
@property
def port_start(self):
return self._port_start
@property
def port_end(self):
return self._port_end
@property
def qsfp_ports(self):
return self._qsfp_ports
@property
def port_to_eeprom_mapping(self):
return self._port_to_eeprom_mapping

View File

@ -0,0 +1,13 @@
# libsensors configuration file
chip "cs5435_54p_fan-*"
label fan1 "front fan 1"
label fan2 "front fan 2"
label fan3 "front fan 3"
label fan4 "front fan 4"
label fan5 "front fan 5"
label fan6 "rear fan 1"
label fan7 "rear fan 2"
label fan8 "rear fan 3"
label fan9 "rear fan 4"
label fan10 "rear fan 5"

View File

@ -0,0 +1,111 @@
{# Default values which will be used if no actual configura available #}
{% set default_cable = '40m' %}
{% set default_speed = '10G' %}
{% set default_ports_num = 54 -%}
{# Port configuration to cable length look-up table #}
{# Each record describes mapping of DUT (DUT port) role and neighbor role to cable length #}
{# Roles described in the minigraph #}
{% set ports2cable = {
'torrouter_server' : '5m',
'leafrouter_torrouter' : '40m',
'spinerouter_leafrouter' : '300m'
}
%}
{%- macro cable_length(port_name) -%}
{%- set cable_len = [] -%}
{%- for local_port in DEVICE_NEIGHBOR -%}
{%- if local_port == port_name -%}
{%- if DEVICE_NEIGHBOR_METADATA[DEVICE_NEIGHBOR[local_port].name] -%}
{%- set neighbor = DEVICE_NEIGHBOR_METADATA[DEVICE_NEIGHBOR[local_port].name] -%}
{%- set neighbor_role = neighbor.type -%}
{%- set roles1 = switch_role + '_' + neighbor_role %}
{%- set roles2 = neighbor_role + '_' + switch_role -%}
{%- set roles1 = roles1 | lower -%}
{%- set roles2 = roles2 | lower -%}
{%- if roles1 in ports2cable -%}
{%- if cable_len.append(ports2cable[roles1]) -%}{%- endif -%}
{%- elif roles2 in ports2cable -%}
{%- if cable_len.append(ports2cable[roles2]) -%}{%- endif -%}
{%- endif -%}
{%- endif -%}
{%- endif -%}
{%- endfor -%}
{%- if cable_len -%}
{{ cable_len.0 }}
{%- else -%}
{{ default_cable }}
{%- endif -%}
{% endmacro %}
{%- if DEVICE_METADATA is defined %}
{%- set switch_role = DEVICE_METADATA['localhost']['type'] %}
{%- endif -%}
{# Generate list of ports if not defined #}
{% if PORT is not defined %}
{% set PORT = [] %}
{% for port_idx in range(0,default_ports_num) %}
{% if PORT.append("Ethernet%d" % (port_idx)) %}{% endif %}
{% endfor %}
{% endif -%}
{% set port_names_list = [] %}
{% for port in PORT %}
{%- if port_names_list.append(port) %}{% endif %}
{% endfor %}
{% set port_names = port_names_list | join(',') -%}
{
"CABLE_LENGTH": {
"AZURE": {
{% for port in PORT %}
{% set cable = cable_length(port) -%}
"{{ port }}": "{{ cable }}"{%- if not loop.last -%},{% endif %}
{% endfor %}
}
},
"BUFFER_POOL": {
"ingress_lossless_pool": {
"size": "20971328",
"type": "ingress",
"mode": "static"
},
"ingress_lossy_pool": {
"size": "20971328",
"type": "ingress",
"mode": "static"
},
"egress_lossy_pool": {
"size": "20971328",
"type": "egress",
"mode": "static"
}
},
"BUFFER_PROFILE": {
"ingress_lossless_profile": {
"pool":"[BUFFER_POOL|ingress_lossless_pool]",
"xon":"78400",
"xoff":"132160",
"size":"3584",
"static_th":"82880"
},
"ingress_lossy_profile": {
"pool":"[BUFFER_POOL|ingress_lossy_pool]",
"size":"3584",
"dynamic_th":"-1"
},
"egress_lossy_profile": {
"pool":"[BUFFER_POOL|egress_lossy_pool]",
"size":"3584",
"dynamic_th":"-4"
}
},
"BUFFER_PG": {
},
"BUFFER_QUEUE": {
}
}

View File

@ -0,0 +1,17 @@
# PG lossless profiles.
# speed cable size xon xoff threshold
10000 5m 3584 32256 59136 36736
25000 5m 3584 41216 68096 45696
40000 5m 3584 47488 74368 51968
50000 5m 3584 52864 79744 57344
100000 5m 3584 78400 132160 82880
10000 40m 3584 32256 59136 36736
25000 40m 3584 41216 68096 45696
40000 40m 3584 47488 74368 51968
50000 40m 3584 52864 79744 57344
100000 40m 3584 78400 132160 82880
10000 300m 3584 32256 65856 36736
25000 300m 3584 41216 84672 45696
40000 300m 3584 47488 101024 51968
50000 300m 3584 52864 113120 57344
100000 300m 3584 78400 198688 82880

View File

@ -0,0 +1,55 @@
# name lanes alias index speed
Ethernet0 8 Ethernet1/1 1 25000
Ethernet1 9 Ethernet2/1 2 25000
Ethernet2 10 Ethernet3/1 3 25000
Ethernet3 11 Ethernet4/1 4 25000
Ethernet4 12 Ethernet5/1 5 25000
Ethernet5 13 Ethernet6/1 6 25000
Ethernet6 14 Ethernet7/1 7 25000
Ethernet7 15 Ethernet8/1 8 25000
Ethernet8 16 Ethernet9/1 9 25000
Ethernet9 17 Ethernet10/1 10 25000
Ethernet10 18 Ethernet11/1 11 25000
Ethernet11 19 Ethernet12/1 12 25000
Ethernet12 20 Ethernet13/1 13 25000
Ethernet13 21 Ethernet14/1 14 25000
Ethernet14 22 Ethernet15/1 15 25000
Ethernet15 23 Ethernet16/1 16 25000
Ethernet16 32 Ethernet17/1 17 25000
Ethernet17 33 Ethernet18/1 18 25000
Ethernet18 34 Ethernet19/1 19 25000
Ethernet19 35 Ethernet20/1 20 25000
Ethernet20 40 Ethernet21/1 21 25000
Ethernet21 41 Ethernet22/1 22 25000
Ethernet22 42 Ethernet23/1 23 25000
Ethernet23 43 Ethernet24/1 24 25000
Ethernet24 48 Ethernet25/1 25 25000
Ethernet25 49 Ethernet26/1 26 25000
Ethernet26 50 Ethernet27/1 27 25000
Ethernet27 51 Ethernet28/1 28 25000
Ethernet28 56 Ethernet29/1 29 25000
Ethernet29 57 Ethernet30/1 30 25000
Ethernet30 58 Ethernet31/1 31 25000
Ethernet31 59 Ethernet32/1 32 25000
Ethernet32 64 Ethernet33/1 33 25000
Ethernet33 65 Ethernet34/1 34 25000
Ethernet34 66 Ethernet35/1 35 25000
Ethernet35 67 Ethernet36/1 36 25000
Ethernet36 68 Ethernet37/1 37 25000
Ethernet37 69 Ethernet38/1 38 25000
Ethernet38 70 Ethernet39/1 39 25000
Ethernet39 71 Ethernet40/1 40 25000
Ethernet40 72 Ethernet41/1 41 25000
Ethernet41 73 Ethernet42/1 42 25000
Ethernet42 74 Ethernet43/1 43 25000
Ethernet43 75 Ethernet44/1 44 25000
Ethernet44 76 Ethernet45/1 45 25000
Ethernet45 77 Ethernet46/1 46 25000
Ethernet46 78 Ethernet47/1 47 25000
Ethernet47 79 Ethernet48/1 48 25000
Ethernet48 84,85,86,87 Ethernet49/1 49 100000
Ethernet49 80,81,82,83 Ethernet50/1 50 100000
Ethernet50 108,109,110,111 Ethernet51/1 51 100000
Ethernet51 104,105,106,107 Ethernet52/1 52 100000
Ethernet52 116,117,118,119 Ethernet53/1 53 100000
Ethernet53 112,113,114,115 Ethernet54/1 54 100000

View File

@ -49,12 +49,10 @@ init set port-map unit=0 port=46 eth-macro=19 lane=2 max-speed=25g active=true
init set port-map unit=0 port=47 eth-macro=19 lane=3 max-speed=25g active=true
init set port-map unit=0 port=48 eth-macro=21 lane=0 max-speed=100g active=true
init set port-map unit=0 port=49 eth-macro=20 lane=0 max-speed=100g active=true
init set port-map unit=0 port=50 eth-macro=23 lane=0 max-speed=100g active=true
init set port-map unit=0 port=51 eth-macro=22 lane=0 max-speed=100g active=true
init set port-map unit=0 port=52 eth-macro=27 lane=0 max-speed=100g active=true
init set port-map unit=0 port=53 eth-macro=26 lane=0 max-speed=100g active=true
init set port-map unit=0 port=54 eth-macro=29 lane=0 max-speed=100g active=true
init set port-map unit=0 port=55 eth-macro=28 lane=0 max-speed=100g active=true
init set port-map unit=0 port=50 eth-macro=27 lane=0 max-speed=100g active=true
init set port-map unit=0 port=51 eth-macro=26 lane=0 max-speed=100g active=true
init set port-map unit=0 port=52 eth-macro=29 lane=0 max-speed=100g active=true
init set port-map unit=0 port=53 eth-macro=28 lane=0 max-speed=100g active=true
init set port-map unit=0 port=129 eth-macro=0 lane=1 max-speed=10g active=true guarantee=true cpi=true
init set port-map unit=0 port=130 eth-macro=0 lane=0 max-speed=10g active=true guarantee=true cpi=true init-done=true
init start stage unit=0 task-rsrc
@ -110,12 +108,10 @@ phy set lane-swap unit=0 portlist=46 lane-cnt=1 property=tx data=0x2
phy set lane-swap unit=0 portlist=47 lane-cnt=1 property=tx data=0x3
phy set lane-swap unit=0 portlist=48 lane-cnt=4 property=tx data=0x3.0.1.2
phy set lane-swap unit=0 portlist=49 lane-cnt=4 property=tx data=0x3.2.1.0
phy set lane-swap unit=0 portlist=50 lane-cnt=4 property=tx data=0x0.1.2.3
phy set lane-swap unit=0 portlist=51 lane-cnt=4 property=tx data=0x3.2.0.1
phy set lane-swap unit=0 portlist=50 lane-cnt=4 property=tx data=0x3.2.1.0
phy set lane-swap unit=0 portlist=51 lane-cnt=4 property=tx data=0x3.2.1.0
phy set lane-swap unit=0 portlist=52 lane-cnt=4 property=tx data=0x3.2.1.0
phy set lane-swap unit=0 portlist=53 lane-cnt=4 property=tx data=0x3.2.1.0
phy set lane-swap unit=0 portlist=54 lane-cnt=4 property=tx data=0x3.2.1.0
phy set lane-swap unit=0 portlist=55 lane-cnt=4 property=tx data=0x3.2.1.0
phy set lane-swap unit=0 portlist=129 lane-cnt=1 property=tx data=0x1
phy set lane-swap unit=0 portlist=130 lane-cnt=1 property=tx data=0x0
phy set lane-swap unit=0 portlist=0 lane-cnt=1 property=rx data=0x0
@ -168,12 +164,10 @@ phy set lane-swap unit=0 portlist=46 lane-cnt=1 property=rx data=0x0
phy set lane-swap unit=0 portlist=47 lane-cnt=1 property=rx data=0x3
phy set lane-swap unit=0 portlist=48 lane-cnt=4 property=rx data=0x3.1.0.2
phy set lane-swap unit=0 portlist=49 lane-cnt=4 property=rx data=0x3.2.1.0
phy set lane-swap unit=0 portlist=50 lane-cnt=4 property=rx data=0x3.0.1.2
phy set lane-swap unit=0 portlist=51 lane-cnt=4 property=rx data=0x3.2.1.0
phy set lane-swap unit=0 portlist=50 lane-cnt=4 property=rx data=0x1.0.3.2
phy set lane-swap unit=0 portlist=51 lane-cnt=4 property=rx data=0x2.0.1.3
phy set lane-swap unit=0 portlist=52 lane-cnt=4 property=rx data=0x1.0.3.2
phy set lane-swap unit=0 portlist=53 lane-cnt=4 property=rx data=0x2.0.1.3
phy set lane-swap unit=0 portlist=54 lane-cnt=4 property=rx data=0x1.0.3.2
phy set lane-swap unit=0 portlist=55 lane-cnt=4 property=rx data=0x1.0.3.2
phy set lane-swap unit=0 portlist=53 lane-cnt=4 property=rx data=0x1.0.3.2
phy set lane-swap unit=0 portlist=129 lane-cnt=1 property=rx data=0x1
phy set lane-swap unit=0 portlist=130 lane-cnt=1 property=rx data=0x0
phy set polarity-rev unit=0 portlist=0 lane-cnt=1 property=tx data=0x0
@ -230,8 +224,6 @@ phy set polarity-rev unit=0 portlist=50 lane-cnt=4 property=tx data=0x0.0.0.0
phy set polarity-rev unit=0 portlist=51 lane-cnt=4 property=tx data=0x0.0.0.0
phy set polarity-rev unit=0 portlist=52 lane-cnt=4 property=tx data=0x0.0.0.0
phy set polarity-rev unit=0 portlist=53 lane-cnt=4 property=tx data=0x0.0.0.0
phy set polarity-rev unit=0 portlist=54 lane-cnt=4 property=tx data=0x0.0.0.0
phy set polarity-rev unit=0 portlist=55 lane-cnt=4 property=tx data=0x0.0.0.0
phy set polarity-rev unit=0 portlist=129 lane-cnt=1 property=tx data=0x0
phy set polarity-rev unit=0 portlist=130 lane-cnt=1 property=tx data=0x0
phy set polarity-rev unit=0 portlist=0 lane-cnt=1 property=rx data=0x0
@ -284,12 +276,10 @@ phy set polarity-rev unit=0 portlist=46 lane-cnt=1 property=rx data=0x0
phy set polarity-rev unit=0 portlist=47 lane-cnt=1 property=rx data=0x0
phy set polarity-rev unit=0 portlist=48 lane-cnt=4 property=rx data=0x0.1.1.0
phy set polarity-rev unit=0 portlist=49 lane-cnt=4 property=rx data=0x0.0.0.0
phy set polarity-rev unit=0 portlist=50 lane-cnt=4 property=rx data=0x1.1.1.1
phy set polarity-rev unit=0 portlist=50 lane-cnt=4 property=rx data=0x1.1.1.0
phy set polarity-rev unit=0 portlist=51 lane-cnt=4 property=rx data=0x0.0.0.0
phy set polarity-rev unit=0 portlist=52 lane-cnt=4 property=rx data=0x1.1.1.0
phy set polarity-rev unit=0 portlist=53 lane-cnt=4 property=rx data=0x0.0.0.0
phy set polarity-rev unit=0 portlist=54 lane-cnt=4 property=rx data=0x1.1.1.0
phy set polarity-rev unit=0 portlist=55 lane-cnt=4 property=rx data=0x0.0.0.0
phy set polarity-rev unit=0 portlist=129 lane-cnt=1 property=rx data=0x0
phy set polarity-rev unit=0 portlist=130 lane-cnt=1 property=rx data=0x0
phy set pre-emphasis unit=0 portlist=0 lane-cnt=1 property=c2 data=0x2
@ -508,14 +498,6 @@ phy set pre-emphasis unit=0 portlist=53 lane-cnt=4 property=c2 data=0x2.2.2.2
phy set pre-emphasis unit=0 portlist=53 lane-cnt=4 property=cn1 data=0x0.0.0.0
phy set pre-emphasis unit=0 portlist=53 lane-cnt=4 property=c0 data=0x1b.1b.1b.1b
phy set pre-emphasis unit=0 portlist=53 lane-cnt=4 property=c1 data=0x6.6.6.6
phy set pre-emphasis unit=0 portlist=54 lane-cnt=4 property=c2 data=0x2.2.2.2
phy set pre-emphasis unit=0 portlist=54 lane-cnt=4 property=cn1 data=0x0.0.0.0
phy set pre-emphasis unit=0 portlist=54 lane-cnt=4 property=c0 data=0x1b.1b.1b.1b
phy set pre-emphasis unit=0 portlist=54 lane-cnt=4 property=c1 data=0x6.6.6.6
phy set pre-emphasis unit=0 portlist=55 lane-cnt=4 property=c2 data=0x2.2.2.2
phy set pre-emphasis unit=0 portlist=55 lane-cnt=4 property=cn1 data=0x0.0.0.0
phy set pre-emphasis unit=0 portlist=55 lane-cnt=4 property=c0 data=0x1b.1b.1b.1b
phy set pre-emphasis unit=0 portlist=55 lane-cnt=4 property=c1 data=0x6.6.6.6
phy set pre-emphasis unit=0 portlist=129 lane-cnt=1 property=c2 data=0x1
phy set pre-emphasis unit=0 portlist=129 lane-cnt=1 property=cn1 data=0x1
phy set pre-emphasis unit=0 portlist=129 lane-cnt=1 property=c0 data=0x2
@ -578,8 +560,6 @@ port set property unit=0 portlist=50 speed=100g
port set property unit=0 portlist=51 speed=100g
port set property unit=0 portlist=52 speed=100g
port set property unit=0 portlist=53 speed=100g
port set property unit=0 portlist=54 speed=100g
port set property unit=0 portlist=55 speed=100g
port set property unit=0 portlist=129 speed=10g
port set property unit=0 portlist=130 speed=1g
port set property unit=0 portlist=0 medium-type=sr
@ -636,8 +616,6 @@ port set property unit=0 portlist=50 medium-type=sr4
port set property unit=0 portlist=51 medium-type=sr4
port set property unit=0 portlist=52 medium-type=sr4
port set property unit=0 portlist=53 medium-type=sr4
port set property unit=0 portlist=54 medium-type=sr4
port set property unit=0 portlist=55 medium-type=sr4
port set property unit=0 portlist=129 medium-type=kr
port set property unit=0 portlist=130 medium-type=x
port advertise unit=0 portlist=129 speed-10g-kr
@ -696,7 +674,5 @@ port set property unit=0 portlist=50 admin=enable
port set property unit=0 portlist=51 admin=enable
port set property unit=0 portlist=52 admin=enable
port set property unit=0 portlist=53 admin=enable
port set property unit=0 portlist=54 admin=enable
port set property unit=0 portlist=55 admin=enable
port set property unit=0 portlist=129 admin=enable
port set property unit=0 portlist=130 admin=enable
port set property unit=0 portlist=129 admin=disable
port set property unit=0 portlist=130 admin=disable

View File

@ -0,0 +1 @@
{%- include 'qos_config.j2' %}

View File

@ -0,0 +1,3 @@
SAI_INIT_LED_CONFIG_FILE=/usr/share/sonic/hwsku/led.bin
SAI_INIT_CONFIG_FILE=/usr/share/sonic/hwsku/proc_init.nps
SAI_DSH_CONFIG_FILE=/usr/share/sonic/hwsku/port_config.nps

View File

@ -0,0 +1 @@
Cig-CS6436-54P t1

View File

@ -0,0 +1,4 @@
CONSOLE_PORT=0x3f8
CONSOLE_DEV=0
CONSOLE_SPEED=115200
ONIE_PLATFORM_EXTRA_CMDLINE_LINUX="pci=noaer"

View File

@ -0,0 +1,21 @@
#!/usr/bin/env python
try:
import exceptions
import binascii
import time
import optparse
import warnings
import os
import sys
from sonic_eeprom import eeprom_base
from sonic_eeprom import eeprom_tlvinfo
import subprocess
except ImportError, e:
raise ImportError (str(e) + "- required module not found")
class board(eeprom_tlvinfo.TlvInfoDecoder):
_TLV_INFO_MAX_LEN = 256
def __init__(self, name, path, cpld_root, ro):
self.eeprom_path = "/sys/bus/i2c/devices/7-0057/eeprom"
super(board, self).__init__(self.eeprom_path, 0, '', True)

View File

@ -0,0 +1,93 @@
#
# psuutil.py
# Platform-specific PSU status interface for SONiC
#
import os.path
import logging
try:
from sonic_psu.psu_base import PsuBase
except ImportError as e:
raise ImportError(str(e) + "- required module not found")
class PsuUtil(PsuBase):
"""Platform-specific PSUutil class"""
SYSFS_PSU_DIR = ["/sys/bus/i2c/devices/5-005a",
"/sys/bus/i2c/devices/5-005b"]
def __init__(self):
PsuBase.__init__(self)
# Get sysfs attribute
def get_attr_value(self, attr_path):
retval = 'ERR'
if (not os.path.isfile(attr_path)):
return retval
try:
with open(attr_path, 'r') as fd:
retval = fd.read()
except Exception as error:
logging.error("Unable to open %s file !", attr_path)
retval = retval.rstrip('\r\n')
return retval
def get_num_psus(self):
"""
Retrieves the number of PSUs available on the device
:return: An integer, the number of PSUs available on the device
"""
MAX_PSUS = 2
return MAX_PSUS
def get_psu_status(self, index):
"""
Retrieves the oprational status of power supply unit (PSU) defined
by index <index>
:param index: An integer, index of the PSU of which to query status
:return: Boolean, True if PSU is operating properly, False if PSU is\
faulty
"""
status = 0
attr_file = 'psu_power_good'
attr_path = self.SYSFS_PSU_DIR[index-1] +'/' + attr_file
attr_value = self.get_attr_value(attr_path)
if (attr_value != 'ERR'):
attr_value = int(attr_value, 16)
# Check for PSU status
if (attr_value == 1):
status = 1
return status
def get_psu_presence(self, index):
"""
Retrieves the presence status of power supply unit (PSU) defined
by index <index>
:param index: An integer, index of the PSU of which to query status
:return: Boolean, True if PSU is plugged, False if not
"""
status = 0
psu_absent = 0
attr_file ='psu_present'
attr_path = self.SYSFS_PSU_DIR[index-1] +'/' + attr_file
attr_value = self.get_attr_value(attr_path)
if (attr_value != 'ERR'):
attr_value = int(attr_value, 16)
# Check for PSU presence
if (attr_value == 1):
status = 1
return status

View File

@ -0,0 +1,250 @@
#!/usr/bin/env python
try:
import time
from sonic_sfp.sfputilbase import SfpUtilBase
except ImportError, e:
raise ImportError (str(e) + "- required module not found")
class SfpUtil(SfpUtilBase):
"""Platform specific SfpUtill class"""
_port_start = 1
_port_end = 54
_qsfp_port_start = 49
_ports_in_block = 54
_port_to_eeprom_mapping = {}
_global_port_pres_dict = {}
_port_to_i2c_mapping = {
1 : 8,
2 : 9,
3 : 10,
4 : 11,
5 : 12,
6 : 13,
7 : 14,
8 : 15,
9 : 16,
10: 17,
11 : 18,
12 : 19,
13 : 20,
14 : 21,
15 : 22,
16 : 23,
17 : 24,
18 : 25,
19 : 26,
20 : 27,
21 : 28,
22 : 29,
23 : 30,
24 : 31,
25 : 32,
26 : 33,
27 : 34,
28 : 35,
29 : 36,
30 : 37,
31 : 38,
32 : 39,
33 : 40,
34 : 41,
35 : 42,
36 : 43,
37 : 44,
38 : 45,
39 : 46,
40 : 47,
41 : 48,
42 : 49,
43 : 50,
44 : 51,
45 : 52,
46 : 53,
47 : 54,
48 : 55,
49 : 56,
50 : 57,
51 : 60,
52 : 61,
53 : 62,
54 : 63,
}
_qsfp_ports = range(_qsfp_port_start, _ports_in_block + 1)
def get_presence(self, port_num):
# Check for invalid port_num
if port_num < self._port_start or port_num > self._port_end:
return False
path = "/sys/bus/i2c/devices/{0}-0050/sfp_is_present"
port_ps = path.format(self._port_to_i2c_mapping[port_num])
try:
reg_file = open(port_ps)
except IOError as e:
print "Error: unable to open file: %s" % str(e)
return False
try:
reg_value = reg_file.readline().rstrip()
except IOError as e:
time.sleep(1)
try:
reg_value = reg_file.readline().rstrip()
except IOError as e:
print "Error:try again to read file failed: %s %s" % (str(e), port_ps)
reg_file.close()
return False
reg_file.close()
if reg_value == '1':
return True
reg_file.close()
if reg_value == '1':
return True
return False
def init_global_port_presence(self):
for port_num in range(self.port_start, (self.port_end + 1)):
self._global_port_pres_dict[port_num] = '0'
def __init__(self):
eeprom_path = '/sys/bus/i2c/devices/{0}-0050/sfp_eeprom'
for x in range(self._port_start, self._port_end + 1):
port_eeprom_path = eeprom_path.format(self._port_to_i2c_mapping[x])
self._port_to_eeprom_mapping[x] = port_eeprom_path
self.init_global_port_presence()
SfpUtilBase.__init__(self)
def reset(self, port_num):
# Check for invalid port_num
if port_num < self._port_start or port_num > self._port_end:
return False
path = "/sys/bus/i2c/devices/{0}-0050/sfp_port_reset"
port_ps = path.format(self._port_to_i2c_mapping[port_num])
try:
reg_file = open(port_ps, 'w')
except IOError as e:
print "Error: unable to open file: %s" % str(e)
return False
#toggle reset
reg_file.seek(0)
reg_file.write('1')
time.sleep(1)
reg_file.seek(0)
reg_file.write('0')
reg_file.close()
return True
def set_low_power_mode(self, port_num, lpmode):
# Check for invalid port_num
if port_num < self._qsfp_port_start or port_num > self._port_end:
return False
pre_value = self.get_presence(port_num)
if pre_value == False:
return False
path = "/sys/bus/i2c/devices/{0}-0050/sfp_lpmode"
port_ps = path.format(self._port_to_i2c_mapping[port_num])
try:
reg_file = open(port_ps,'w')
except IOError as e:
print "Error: unable to open file: %s" % str(e)
return False
reg_file.seek(0)
if lpmode == 1:
reg_file.write('1')
elif lpmode == 0:
reg_file.write('0')
reg_file.close()
return True
def get_low_power_mode(self, port_num):
# Check for invalid port_num
if port_num < self._qsfp_port_start or port_num > self._port_end:
return False
pre_value = self.get_presence(port_num)
if pre_value == False:
return False
path = "/sys/bus/i2c/devices/{0}-0050/sfp_lpmode"
port_ps = path.format(self._port_to_i2c_mapping[port_num])
try:
reg_file = open(port_ps)
except IOError as e:
print "Error: unable to open file:%s %s" % (str(e), port_ps)
return False
try:
reg_value = reg_file.readline().rstrip()
except IOError as e:
print "Error: unable to open file:%s %s" % (str(e), port_ps)
reg_file.close()
return False
reg_file.close()
if reg_value == '1':
return True
return False
def get_transceiver_change_event(self):
port_dict = {}
while True:
for port_num in range(self.port_start, (self.port_end + 1)):
presence = self.get_presence(port_num)
if(presence and self._global_port_pres_dict[port_num] == '0'):
self._global_port_pres_dict[port_num] = '1'
port_dict[port_num] = '1'
elif(not presence and
self._global_port_pres_dict[port_num] == '1'):
self._global_port_pres_dict[port_num] = '0'
port_dict[port_num] = '0'
if(len(port_dict) > 0):
return True, port_dict
time.sleep(0.5)
@property
def port_start(self):
return self._port_start
@property
def port_end(self):
return self._port_end
@property
def qsfp_ports(self):
return self._qsfp_ports
@property
def port_to_eeprom_mapping(self):
return self._port_to_eeprom_mapping

View File

@ -0,0 +1,13 @@
# libsensors configuration file
chip "cs6436_54p_fan-*"
label fan1 "front fan 1"
label fan2 "front fan 2"
label fan3 "front fan 3"
label fan4 "front fan 4"
label fan5 "front fan 5"
label fan6 "rear fan 1"
label fan7 "rear fan 2"
label fan8 "rear fan 3"
label fan9 "rear fan 4"
label fan10 "rear fan 5"

View File

View File

@ -1,57 +1,57 @@
# name lanes alias index speed
Ethernet0 8 Ethernet1/1 0 25000
Ethernet1 9 Ethernet2/1 1 25000
Ethernet2 10 Ethernet3/1 2 25000
Ethernet3 11 Ethernet4/1 3 25000
Ethernet4 12 Ethernet5/1 4 25000
Ethernet5 13 Ethernet6/1 5 25000
Ethernet6 14 Ethernet7/1 6 25000
Ethernet7 15 Ethernet8/1 7 25000
Ethernet8 16 Ethernet9/1 8 25000
Ethernet9 17 Ethernet10/1 9 25000
Ethernet10 18 Ethernet11/1 10 25000
Ethernet11 19 Ethernet12/1 11 25000
Ethernet12 20 Ethernet13/1 12 25000
Ethernet13 21 Ethernet14/1 13 25000
Ethernet14 22 Ethernet15/1 14 25000
Ethernet15 23 Ethernet16/1 15 25000
Ethernet16 32 Ethernet17/1 16 25000
Ethernet17 33 Ethernet18/1 17 25000
Ethernet18 34 Ethernet19/1 18 25000
Ethernet19 35 Ethernet20/1 19 25000
Ethernet20 40 Ethernet21/1 20 25000
Ethernet21 41 Ethernet22/1 21 25000
Ethernet22 42 Ethernet23/1 22 25000
Ethernet23 43 Ethernet24/1 23 25000
Ethernet24 48 Ethernet25/1 24 25000
Ethernet25 49 Ethernet26/1 25 25000
Ethernet26 50 Ethernet27/1 26 25000
Ethernet27 51 Ethernet28/1 27 25000
Ethernet28 56 Ethernet29/1 28 25000
Ethernet29 57 Ethernet30/1 29 25000
Ethernet30 58 Ethernet31/1 30 25000
Ethernet31 59 Ethernet32/1 31 25000
Ethernet32 64 Ethernet33/1 32 25000
Ethernet33 65 Ethernet34/1 33 25000
Ethernet34 66 Ethernet35/1 34 25000
Ethernet35 67 Ethernet36/1 35 25000
Ethernet36 68 Ethernet37/1 36 25000
Ethernet37 69 Ethernet38/1 37 25000
Ethernet38 70 Ethernet39/1 38 25000
Ethernet39 71 Ethernet40/1 39 25000
Ethernet40 72 Ethernet41/1 40 25000
Ethernet41 73 Ethernet42/1 41 25000
Ethernet42 74 Ethernet43/1 42 25000
Ethernet43 75 Ethernet44/1 43 25000
Ethernet44 76 Ethernet45/1 44 25000
Ethernet45 77 Ethernet46/1 45 25000
Ethernet46 78 Ethernet47/1 46 25000
Ethernet47 79 Ethernet48/1 47 25000
Ethernet48 84,85,86,87 Ethernet49/1 48 100000
Ethernet49 80,81,82,83 Ethernet50/1 49 100000
Ethernet50 92,93,94,95 Ethernet51/1 50 100000
Ethernet51 88,89,90,91 Ethernet52/1 51 100000
Ethernet52 108,109,110,111 Ethernet53/1 52 100000
Ethernet53 104,105,106,107 Ethernet54/1 53 100000
Ethernet54 116,117,118,119 Ethernet55/1 54 100000
Ethernet55 112,113,114,115 Ethernet56/1 55 100000
Ethernet0 8 Ethernet1/1 1 25000
Ethernet1 9 Ethernet2/1 2 25000
Ethernet2 10 Ethernet3/1 3 25000
Ethernet3 11 Ethernet4/1 4 25000
Ethernet4 12 Ethernet5/1 5 25000
Ethernet5 13 Ethernet6/1 6 25000
Ethernet6 14 Ethernet7/1 7 25000
Ethernet7 15 Ethernet8/1 8 25000
Ethernet8 16 Ethernet9/1 9 25000
Ethernet9 17 Ethernet10/1 10 25000
Ethernet10 18 Ethernet11/1 11 25000
Ethernet11 19 Ethernet12/1 12 25000
Ethernet12 20 Ethernet13/1 13 25000
Ethernet13 21 Ethernet14/1 14 25000
Ethernet14 22 Ethernet15/1 15 25000
Ethernet15 23 Ethernet16/1 16 25000
Ethernet16 32 Ethernet17/1 17 25000
Ethernet17 33 Ethernet18/1 18 25000
Ethernet18 34 Ethernet19/1 19 25000
Ethernet19 35 Ethernet20/1 20 25000
Ethernet20 40 Ethernet21/1 21 25000
Ethernet21 41 Ethernet22/1 22 25000
Ethernet22 42 Ethernet23/1 23 25000
Ethernet23 43 Ethernet24/1 24 25000
Ethernet24 48 Ethernet25/1 25 25000
Ethernet25 49 Ethernet26/1 26 25000
Ethernet26 50 Ethernet27/1 27 25000
Ethernet27 51 Ethernet28/1 28 25000
Ethernet28 56 Ethernet29/1 29 25000
Ethernet29 57 Ethernet30/1 30 25000
Ethernet30 58 Ethernet31/1 31 25000
Ethernet31 59 Ethernet32/1 32 25000
Ethernet32 64 Ethernet33/1 33 25000
Ethernet33 65 Ethernet34/1 34 25000
Ethernet34 66 Ethernet35/1 35 25000
Ethernet35 67 Ethernet36/1 36 25000
Ethernet36 68 Ethernet37/1 37 25000
Ethernet37 69 Ethernet38/1 38 25000
Ethernet38 70 Ethernet39/1 39 25000
Ethernet39 71 Ethernet40/1 40 25000
Ethernet40 72 Ethernet41/1 41 25000
Ethernet41 73 Ethernet42/1 42 25000
Ethernet42 74 Ethernet43/1 43 25000
Ethernet43 75 Ethernet44/1 44 25000
Ethernet44 76 Ethernet45/1 45 25000
Ethernet45 77 Ethernet46/1 46 25000
Ethernet46 78 Ethernet47/1 47 25000
Ethernet47 79 Ethernet48/1 48 25000
Ethernet48 84,85,86,87 Ethernet49/1 49 100000
Ethernet49 80,81,82,83 Ethernet50/1 50 100000
Ethernet50 92,93,94,95 Ethernet51/1 51 100000
Ethernet51 88,89,90,91 Ethernet52/1 52 100000
Ethernet52 108,109,110,111 Ethernet53/1 53 100000
Ethernet53 104,105,106,107 Ethernet54/1 54 100000
Ethernet54 116,117,118,119 Ethernet55/1 55 100000
Ethernet55 112,113,114,115 Ethernet56/1 56 100000

View File

@ -698,5 +698,5 @@ port set property unit=0 portlist=52 admin=enable
port set property unit=0 portlist=53 admin=enable
port set property unit=0 portlist=54 admin=enable
port set property unit=0 portlist=55 admin=enable
port set property unit=0 portlist=129 admin=enable
port set property unit=0 portlist=130 admin=enable
port set property unit=0 portlist=129 admin=disable
port set property unit=0 portlist=130 admin=disable

View File

@ -1,7 +1,7 @@
#unit NPS_CFG_TYPE_XXX param0 param1 value
#---- ---------------- ------ ------ -----
0 NPS_CFG_TYPE_USE_UNIT_PORT 0 0 1
0 NPS_CFG_TYPE_LED_CFG 0 0 7
0 NPS_CFG_TYPE_LED_CFG 0 0 9
0 NPS_CFG_TYPE_CPI_PORT_MODE 129 0 1
0 NPS_CFG_TYPE_CPI_PORT_MODE 130 0 1
0 NPS_CFG_TYPE_USER_BUF_CTRL 0 0 1

View File

View File

@ -1,2 +1,3 @@
SAI_INIT_CONFIG_FILE=/usr/share/sonic/platform/led_proc_init.nps
SAI_INIT_LED_CONFIG_FILE=/usr/share/sonic/hwsku/led.bin
SAI_INIT_CONFIG_FILE=/usr/share/sonic/hwsku/proc_init.nps
SAI_DSH_CONFIG_FILE=/usr/share/sonic/hwsku/port_config.nps

0
device/cig/x86_64-cig_cs6436_56p-r0/default_sku Executable file → Normal file
View File

4
device/cig/x86_64-cig_cs6436_56p-r0/installer.conf Executable file → Normal file
View File

@ -1,4 +1,4 @@
CONSOLE_PORT=0x3e8
CONSOLE_DEV=2
CONSOLE_PORT=0x3f8
CONSOLE_DEV=0
CONSOLE_SPEED=115200
ONIE_PLATFORM_EXTRA_CMDLINE_LINUX="pci=noaer"

View File

@ -5,6 +5,7 @@
import os.path
import logging
try:
from sonic_psu.psu_base import PsuBase
@ -33,7 +34,7 @@ class PsuUtil(PsuBase):
with open(attr_path, 'r') as fd:
retval = fd.read()
except Exception as error:
logging.error("Unable to open ", attr_path, " file !")
logging.error("Unable to open %s file !", attr_path)
retval = retval.rstrip('\r\n')
return retval

View File

@ -10,79 +10,124 @@ except ImportError, e:
class SfpUtil(SfpUtilBase):
"""Platform specific SfpUtill class"""
_port_start = 0
_port_end = 55
_qsfp_port_start = 48
_ports_in_block = 55
_port_start = 1
_port_end = 56
_qsfp_port_start = 49
_ports_in_block = 56
_port_to_eeprom_mapping = {}
_global_port_pres_dict = {}
_port_to_i2c_mapping = {
0 : 8,
1 : 9,
2 : 10,
3 : 11,
4 : 12,
5 : 13,
6 : 14,
7 : 15,
8 : 16,
9 : 17,
10 : 18,
11 : 19,
12 : 20,
13 : 21,
14 : 22,
15 : 23,
16 : 24,
17 : 25,
18 : 26,
19 : 27,
20 : 28,
21 : 29,
22 : 30,
23 : 31,
24 : 32,
25 : 33,
26 : 34,
27 : 35,
28 : 36,
29 : 37,
30 : 38,
31 : 39,
32 : 40,
33 : 41,
34 : 42,
35 : 43,
36 : 44,
37 : 45,
38 : 46,
39 : 47,
40 : 48,
41 : 49,
42 : 50,
43 : 51,
44 : 52,
45 : 53,
46 : 54,
47 : 55,
48 : 56,
49 : 57,
50 : 58,
51 : 59,
52 : 60,
53 : 61,
54 : 62,
55 : 63,
1 : 8,
2 : 9,
3 : 10,
4 : 11,
5 : 12,
6 : 13,
7 : 14,
8 : 15,
9 : 16,
10: 17,
11 : 18,
12 : 19,
13 : 20,
14 : 21,
15 : 22,
16 : 23,
17 : 24,
18 : 25,
19 : 26,
20 : 27,
21 : 28,
22 : 29,
23 : 30,
24 : 31,
25 : 32,
26 : 33,
27 : 34,
28 : 35,
29 : 36,
30 : 37,
31 : 38,
32 : 39,
33 : 40,
34 : 41,
35 : 42,
36 : 43,
37 : 44,
38 : 45,
39 : 46,
40 : 47,
41 : 48,
42 : 49,
43 : 50,
44 : 51,
45 : 52,
46 : 53,
47 : 54,
48 : 55,
49 : 56,
50 : 57,
51 : 58,
52 : 59,
53 : 60,
54 : 61,
55 : 62,
56 : 63,
}
_qsfp_ports = range(_qsfp_port_start, _ports_in_block + 1)
def get_presence(self, port_num):
# Check for invalid port_num
if port_num < self._port_start or port_num > self._port_end:
return False
path = "/sys/bus/i2c/devices/{0}-0050/sfp_is_present"
port_ps = path.format(self._port_to_i2c_mapping[port_num])
try:
reg_file = open(port_ps)
except IOError as e:
print "Error: unable to open file: %s" % str(e)
return False
try:
reg_value = reg_file.readline().rstrip()
except IOError as e:
time.sleep(1)
try:
reg_value = reg_file.readline().rstrip()
except IOError as e:
print "Error:try again to read file failed: %s %s" % (str(e), port_ps)
reg_file.close()
return False
reg_file.close()
if reg_value == '1':
return True
reg_file.close()
if reg_value == '1':
return True
return False
def init_global_port_presence(self):
for port_num in range(self.port_start, (self.port_end + 1)):
self._global_port_pres_dict[port_num] = '0'
def __init__(self):
eeprom_path = '/sys/bus/i2c/devices/{0}-0050/sfp_eeprom'
for x in range(self._port_start, self._port_end + 1):
port_eeprom_path = eeprom_path.format(self._port_to_i2c_mapping[x])
self._port_to_eeprom_mapping[x] = port_eeprom_path
self.init_global_port_presence()
SfpUtilBase.__init__(self)
def reset(self, port_num):
@ -108,40 +153,87 @@ class SfpUtil(SfpUtilBase):
reg_file.close()
return True
def set_low_power_mode(self, port_nuM, lpmode):
raise NotImplementedError
def get_low_power_mode(self, port_num):
raise NotImplementedError
def get_presence(self, port_num):
def set_low_power_mode(self, port_num, lpmode):
# Check for invalid port_num
if port_num < self._port_start or port_num > self._port_end:
if port_num < self._qsfp_port_start or port_num > self._port_end:
return False
path = "/sys/bus/i2c/devices/{0}-0050/sfp_is_present"
pre_value = self.get_presence(port_num)
if pre_value == False:
return False
path = "/sys/bus/i2c/devices/{0}-0050/sfp_lpmode"
port_ps = path.format(self._port_to_i2c_mapping[port_num])
try:
reg_file = open(port_ps)
reg_file = open(port_ps,'w')
except IOError as e:
print "Error: unable to open file: %s" % str(e)
return False
reg_file.seek(0)
if lpmode == 1:
reg_file.write('1')
elif lpmode == 0:
reg_file.write('0')
reg_file.close()
return True
def get_low_power_mode(self, port_num):
# Check for invalid port_num
if port_num < self._qsfp_port_start or port_num > self._port_end:
return False
pre_value = self.get_presence(port_num)
if pre_value == False:
return False
path = "/sys/bus/i2c/devices/{0}-0050/sfp_lpmode"
port_ps = path.format(self._port_to_i2c_mapping[port_num])
try:
reg_file = open(port_ps)
except IOError as e:
print "Error: unable to open file:%s %s" % (str(e), port_ps)
return False
try:
reg_value = reg_file.readline().rstrip()
except IOError as e:
print "Error: unable to open file:%s %s" % (str(e), port_ps)
reg_file.close()
return False
reg_file.close()
if reg_value == '1':
return True
return False
def get_transceiver_change_event(self):
"""
TODO: This function need to be implemented
when decide to support monitoring SFP(Xcvrd)
on this platform.
"""
raise NotImplementedError
port_dict = {}
while True:
for port_num in range(self.port_start, (self.port_end + 1)):
presence = self.get_presence(port_num)
if(presence and self._global_port_pres_dict[port_num] == '0'):
self._global_port_pres_dict[port_num] = '1'
port_dict[port_num] = '1'
elif(not presence and
self._global_port_pres_dict[port_num] == '1'):
self._global_port_pres_dict[port_num] = '0'
port_dict[port_num] = '0'
if(len(port_dict) > 0):
return True, port_dict
time.sleep(0.5)
@property
def port_start(self):

0
device/cig/x86_64-cig_cs6436_56p-r0/sensors.conf Executable file → Normal file
View File

View File

@ -8,7 +8,10 @@ $(SONIC_ONE_IMAGE)_INSTALLS += $(SYSTEMD_SONIC_GENERATOR)
$(SONIC_ONE_IMAGE)_LAZY_INSTALLS += $(INGRASYS_S9130_32X_PLATFORM_MODULE) \
$(INGRASYS_S9230_64X_PLATFORM_MODULE) \
$(ACCTON_AS7116_54X_PLATFORM_MODULE) \
$(CIG_CS6436_56P_PLATFORM_MODULE)
$(CIG_CS6436_56P_PLATFORM_MODULE) \
$(CIG_CS6436_54P_PLATFORM_MODULE) \
$(CIG_CS5435_54P_PLATFORM_MODULE)
ifeq ($(INSTALL_DEBUG_TOOLS),y)
$(SONIC_ONE_IMAGE)_DOCKERS += $(SONIC_INSTALL_DOCKER_DBG_IMAGES)
$(SONIC_ONE_IMAGE)_DOCKERS += $(filter-out $(patsubst %-$(DBG_IMAGE_MARK).gz,%.gz, $(SONIC_INSTALL_DOCKER_DBG_IMAGES)), $(SONIC_INSTALL_DOCKER_IMAGES))

View File

@ -1,12 +1,26 @@
# Cig CS6436 56P Platform modules
# Cig Nephos Switch Platform modules
CIG_CS6436_56P_PLATFORM_MODULE_VERSION = 1.0.0
CIG_MTK_PLATFORM_MODULE_VERSION = 1.0.0
export CIG_CS6436_56P_PLATFORM_MODULE_VERSION
export CIG_MTK_PLATFORM_MODULE_VERSION
CIG_CS6436_56P_PLATFORM_MODULE = sonic-platform-cig-cs6436-56p_$(CIG_CS6436_56P_PLATFORM_MODULE_VERSION)_amd64.deb
CIG_CS6436_56P_PLATFORM_MODULE = sonic-platform-cig-cs6436-56p_$(CIG_MTK_PLATFORM_MODULE_VERSION)_amd64.deb
$(CIG_CS6436_56P_PLATFORM_MODULE)_SRC_PATH = $(PLATFORM_PATH)/sonic-platform-modules-cig
$(CIG_CS6436_56P_PLATFORM_MODULE)_DEPENDS += $(LINUX_HEADERS) $(LINUX_HEADERS_COMMON)
$(CIG_CS6436_56P_PLATFORM_MODULE)_PLATFORM = x86_64-cig_cs6436_56p-r0
SONIC_DPKG_DEBS += $(CIG_CS6436_56P_PLATFORM_MODULE)
SONIC_STRETCH_DEBS += $(CIG_CS6436_56P_PLATFORM_MODULE)
CIG_CS6436_54P_PLATFORM_MODULE = sonic-platform-cig-cs6436-54p_$(CIG_MTK_PLATFORM_MODULE_VERSION)_amd64.deb
$(CIG_CS6436_54P_PLATFORM_MODULE)_SRC_PATH = $(PLATFORM_PATH)/sonic-platform-modules-cig
$(CIG_CS6436_54P_PLATFORM_MODULE)_DEPENDS += $(LINUX_HEADERS) $(LINUX_HEADERS_COMMON)
$(CIG_CS6436_54P_PLATFORM_MODULE)_PLATFORM = x86_64-cig_cs6436_54p-r0
SONIC_DPKG_DEBS += $(CIG_CS6436_54P_PLATFORM_MODULE)
SONIC_STRETCH_DEBS += $(CIG_CS6436_54P_PLATFORM_MODULE)
CIG_CS5435_54P_PLATFORM_MODULE = sonic-platform-cig-cs5435-54p_$(CIG_MTK_PLATFORM_MODULE_VERSION)_amd64.deb
$(CIG_CS5435_54P_PLATFORM_MODULE)_SRC_PATH = $(PLATFORM_PATH)/sonic-platform-modules-cig
$(CIG_CS5435_54P_PLATFORM_MODULE)_DEPENDS += $(LINUX_HEADERS) $(LINUX_HEADERS_COMMON)
$(CIG_CS5435_54P_PLATFORM_MODULE)_PLATFORM = x86_64-cig_cs5435_54p-r0
SONIC_DPKG_DEBS += $(CIG_CS5435_54P_PLATFORM_MODULE)
SONIC_STRETCH_DEBS += $(CIG_CS5435_54P_PLATFORM_MODULE)

View File

@ -0,0 +1,6 @@
obj-m :=x86-64-cig-cs5435-54p-sysfs.o \
x86-64-cig-cs5435-54p-cpld.o \
x86-64-cig-cs5435-54p-fan.o \
x86-64-cig-cs5435-54p-led.o \
x86-64-cig-cs5435-54p-psu.o \
x86-64-cig-cs5435-54p-sfp.o

View File

@ -0,0 +1,222 @@
/* --------------------------------------------------------------------
* A hwmon driver for the CIG cs5435-54P
*
* Copyright (C) 2018 Cambridge, Inc.
*
* 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.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/* -------------------------------------------------------------------- */
#ifndef I2C_LPC_H
#define I2C_LPC_H 1
/* ----- Control register bits ---------------------------------------- */
#define I2C_LPC_PIN 0x80
#define I2C_LPC_ESO 0x40
#define I2C_LPC_ES1 0x20
#define I2C_LPC_ES2 0x10
#define I2C_LPC_ENI 0x08
#define I2C_LPC_STO 0x40
#define I2C_LPC_ACK 0x01
/*command register*/
#define I2C_LPC_STA 0x80
#define I2C_LPC_ABT 0x40
/*status register*/
#define I2C_LPC_TBE 0x02
#define I2C_LPC_IBB 0x80
#define I2C_LPC_RBF 0x01
#define I2C_LPC_TD 0x08
#define I2C_LPC_START I2C_LPC_STA
#define I2C_LPC_STOP I2C_LPC_STO
#define I2C_LPC_REPSTART I2C_LPC_STA
#define I2C_LPC_IDLE
/* ----- Status register bits ----------------------------------------- */
/*#define I2C_LPC_PIN 0x80 as above*/
#define I2C_LPC_INI 0x40 /* 1 if not initialized */
#define I2C_LPC_STS 0x20
#define I2C_LPC_BER 0x10
#define I2C_LPC_AD0 0x08
#define I2C_LPC_LRB 0x08
#define I2C_LPC_AAS 0x04
#define I2C_LPC_LAB 0x02
#define I2C_LPC_BB 0x80
/* ----- Chip clock frequencies --------------------------------------- */
#define I2C_LPC_CLK3 0x00
#define I2C_LPC_CLK443 0x10
#define I2C_LPC_CLK6 0x14
#define I2C_LPC_CLK 0x18
#define I2C_LPC_CLK12 0x1c
/* ----- transmission frequencies ------------------------------------- */
#define I2C_LPC_TRNS90 0x00 /* 90 kHz */
#define I2C_LPC_TRNS45 0x01 /* 45 kHz */
#define I2C_LPC_TRNS11 0x02 /* 11 kHz */
#define I2C_LPC_TRNS15 0x03 /* 1.5 kHz */
#define I2C_LPC_OWNADR 0
#define I2C_LPC_INTREG I2C_LPC_ES2
#define I2C_LPC_CLKREG I2C_LPC_ES1
#define I2C_LPC_REG_TEST 0x01
#define I2C_LPC_REG_BUS_SEL 0x80
#define I2C_LPC_REG_DEVICE_ADDR 0x81
#define I2C_LPC_REG_BYTE_COUNT 0x83
#define I2C_LPC_REG_COMMAND 0x84
#define I2C_LPC_REG_STATUS 0x85
#define I2C_LPC_REG_DATA_RX1 0x86
#define I2C_LPC_REG_DATA_RX2 0x87
#define I2C_LPC_REG_DATA_RX3 0x88
#define I2C_LPC_REG_DATA_RX4 0x89
#define I2C_LPC_REG_DATA_TX1 0x8a
#define I2C_LPC_REG_DATA_TX2 0x8b
#define I2C_LPC_REG_DATA_TX3 0x8c
#define I2C_LPC_REG_DATA_TX4 0x8d
#define ADDR_REG_SFP_STATUS_ADDR 0X62 //reg addr +R/W# //1031
#define ADDR_REG_SFP_STATUS_TX 0X63 // write data
#define ADDR_REG_SFP_STATUS_RX 0X64 //read data
#define ADDR_REG_SFP_STATUS_COMMAND 0X65 //cmd bit7=1,go
#define ADDR_REG_SFP_STATUS_STATUS 0X66 //status
#define CPLD_MASTER_INTERRUPT_STATUS_REG 0x20
#define CPLD_MASTER_INTERRUPT_MASK_REG 0x21
#define CPLD_MASTER_INTERRUPT_ALL 0x3f
#define CPLD_MASTER_INTERRUPT_CPLD2 0x20
#define CPLD_MASTER_INTERRUPT_CPLD1 0x10
#define CPLD_MASTER_INTERRUPT_PSU2 0x08
#define CPLD_MASTER_INTERRUPT_PSU1 0x04
#define CPLD_MASTER_INTERRUPT_6320 0x02
#define CPLD_MASTER_INTERRUPT_LSW 0x01
#define CPLD_SLAVE1_INTERRUPT_STATUS_L_REG 0x20
#define CPLD_SLAVE1_INTERRUPT_STATUS_H_REG 0x21
#define CPLD_SLAVE2_INTERRUPT_STATUS_L_REG 0x22
#define CPLD_SLAVE2_INTERRUPT_STATUS_H_REG 0x23
#define CPLD_SLAVE1_INTERRUPT_MASK_REG 0x24
#define CPLD_SLAVE2_INTERRUPT_MASK_REG 0x25
#define CPLD_SLAVE1_PRESENT08_REG 0x01
#define CPLD_SLAVE1_PRESENT16_REG 0x02
#define CPLD_SLAVE1_PRESENT24_REG 0x03
#define CPLD_SLAVE2_PRESENT32_REG 0x04
#define CPLD_SLAVE2_PRESENT40_REG 0x05
#define CPLD_SLAVE2_PRESENT48_REG 0x06
#define CPLD_SLAVE1_RX_LOST08_REG 0x07
#define CPLD_SLAVE1_RX_LOST16_REG 0x08
#define CPLD_SLAVE1_RX_LOST24_REG 0x09
#define CPLD_SLAVE2_RX_LOST32_REG 0x0a
#define CPLD_SLAVE2_RX_LOST40_REG 0x0b
#define CPLD_SLAVE2_RX_LOST48_REG 0x0c
#define CPLD_SLAVE1_TX_FAULT08_REG 0x0d
#define CPLD_SLAVE1_TX_FAULT16_REG 0x0e
#define CPLD_SLAVE1_TX_FAULT24_REG 0x0f
#define CPLD_SLAVE2_TX_FAULT32_REG 0x10
#define CPLD_SLAVE2_TX_FAULT40_REG 0x11
#define CPLD_SLAVE2_TX_FAULT48_REG 0x12
#define CPLD_SLAVE2_PRESENT56_REG 0x19
#define CPLD_SLAVE2_QSFP_CR56_REG 0x1a
#define CPLD_SLAVE1_INTERRUPT_PRESENT08 0x0001
#define CPLD_SLAVE1_INTERRUPT_PRESENT16 0x0002
#define CPLD_SLAVE1_INTERRUPT_PRESENT24 0x0004
#define CPLD_SLAVE2_INTERRUPT_PRESENT32 0x0001
#define CPLD_SLAVE2_INTERRUPT_PRESENT40 0x0002
#define CPLD_SLAVE2_INTERRUPT_PRESENT48 0x0004
#define CPLD_SLAVE2_INTERRUPT_QSFP_CR56 0x0200
#define CPLD_SLAVE2_INTERRUPT_PRESENT56 0x0400
#define CPLD_SLAVE1_INTERRUPT_RX_LOST08 0x0008
#define CPLD_SLAVE1_INTERRUPT_RX_LOST16 0x0010
#define CPLD_SLAVE1_INTERRUPT_RX_LOST24 0x0020
#define CPLD_SLAVE2_INTERRUPT_RX_LOST32 0x0008
#define CPLD_SLAVE2_INTERRUPT_RX_LOST40 0x0010
#define CPLD_SLAVE2_INTERRUPT_RX_LOST48 0x0020
#define CPLD_SLAVE1_INTERRUPT_TX_FAULT08 0x0040
#define CPLD_SLAVE1_INTERRUPT_TX_FAULT16 0x0080
#define CPLD_SLAVE1_INTERRUPT_TX_FAULT24 0x0100
#define CPLD_SLAVE2_INTERRUPT_TX_FAULT32 0x0040
#define CPLD_SLAVE2_INTERRUPT_TX_FAULT40 0x0080
#define CPLD_SLAVE2_INTERRUPT_TX_FAULT48 0x0100
#define WAIT_TIME_OUT_COUNT 100
struct i2c_algo_lpc_data {
void *data; /* private data for lolevel routines */
void (*setlpc) (void *data, int ctl, int val);
int (*getlpc) (void *data, int ctl);
int (*getown) (void *data);
int (*getclock) (void *data);
void (*waitforpin) (void *data);
int (*xfer_begin) (void *data);
int (*xfer_end) (void *data);
/* Multi-master lost arbitration back-off delay (msecs)
* This should be set by the bus adapter or knowledgable client
* if bus is multi-mastered, else zero
*/
unsigned long lab_mdelay;
};
struct subsys_private {
struct kset subsys;
struct kset *devices_kset;
struct list_head interfaces;
struct mutex mutex;
struct kset *drivers_kset;
struct klist klist_devices;
struct klist klist_drivers;
struct blocking_notifier_head bus_notifier;
unsigned int drivers_autoprobe:1;
struct bus_type *bus;
struct kset glue_dirs;
struct class *class;
};
void cs5435_54p_sysfs_add_client(struct i2c_client *client);
void cs5435_54p_sysfs_remove_client(struct i2c_client *client);
#endif /* I2C_LPC8584_H */

View File

@ -0,0 +1,521 @@
/*
* A hwmon driver for the CIG cs5435-54p fan
*
* Copyright (C) 2018 Cambridge, Inc.
*
* 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.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/jiffies.h>
#include <linux/i2c.h>
#include <linux/hwmon.h>
#include <linux/hwmon-sysfs.h>
#include <linux/err.h>
#include <linux/mutex.h>
#include <linux/sysfs.h>
#include <linux/slab.h>
#include <linux/dmi.h>
#include <linux/fs.h>
#include <linux/uaccess.h>
#include <linux/syscalls.h>
#include <linux/kthread.h>
#include <linux/device.h>
#include <linux/platform_device.h>
#define FAN_SPEED_DUTY_TO_CPLD_STEP 10
static struct cs5435_54p_fan_data *cs5435_54p_fan_update_device(struct device *dev);
static ssize_t fan_show_value(struct device *dev, struct device_attribute *da, char *buf);
static ssize_t set_duty_cycle(struct device *dev, struct device_attribute *da,
const char *buf, size_t count);
static ssize_t set_fan_direction(struct device *dev, struct device_attribute *da,
const char *buf, size_t count);
extern int cig_cpld_write_register(u8 reg_off, u8 val);
extern int cig_cpld_read_register(u8 reg_off, u8 *val);
/* fan related data, the index should match sysfs_fan_attributes
*/
static const u8 fan_reg[] = {
0x41, /* fan enable/disable */
0x40, /* fan PWM(for all fan) */
0x42, /* front fan 1 speed(rpm) */
0x44, /* front fan 2 speed(rpm) */
0x46, /* front fan 3 speed(rpm) */
0x48, /* front fan 4 speed(rpm) */
0x4a, /* front fan 5 speed(rpm) */
0x43, /* rear fan 1 speed(rpm) */
0x45, /* rear fan 2 speed(rpm) */
0x47, /* rear fan 3 speed(rpm) */
0x49, /* rear fan 4 speed(rpm) */
0x4b, /* rear fan 5 speed(rpm) */
0x4c, /* fan direction rear to front or front to rear */
};
/* Each client has this additional data */
struct cs5435_54p_fan_data {
struct platform_device *pdev;
struct device *hwmon_dev;
struct mutex update_lock;
char valid; /* != 0 if registers are valid */
unsigned long last_updated; /* In jiffies */
u8 reg_val[ARRAY_SIZE(fan_reg)]; /* Register value */
};
static struct cs5435_54p_fan_data *fan_data = NULL;
enum fan_id {
FAN1_ID,
FAN2_ID,
FAN3_ID,
FAN4_ID,
FAN5_ID,
};
enum sysfs_fan_attributes {
FAN_STATE_REG,
FAN_DUTY_CYCLE_PERCENTAGE, /* Only one CPLD register to control duty cycle for all fans */
FAN1_FRONT_SPEED_RPM,
FAN2_FRONT_SPEED_RPM,
FAN3_FRONT_SPEED_RPM,
FAN4_FRONT_SPEED_RPM,
FAN5_FRONT_SPEED_RPM,
FAN1_REAR_SPEED_RPM,
FAN2_REAR_SPEED_RPM,
FAN3_REAR_SPEED_RPM,
FAN4_REAR_SPEED_RPM,
FAN5_REAR_SPEED_RPM,
FAN_DIRECTION,
FAN1_STATE,
FAN2_STATE,
FAN3_STATE,
FAN4_STATE,
FAN5_STATE,
FAN1_FAULT,
FAN2_FAULT,
FAN3_FAULT,
FAN4_FAULT,
FAN5_FAULT,
FAN1_DIRECTION,
FAN2_DIRECTION,
FAN3_DIRECTION,
FAN4_DIRECTION,
FAN5_DIRECTION,
};
/* Define attributes
*/
#define DECLARE_FAN_STATE_SENSOR_DEV_ATTR(index) \
static SENSOR_DEVICE_ATTR(fan##index##_state, S_IRUGO, fan_show_value, NULL, FAN##index##_STATE)
#define DECLARE_FAN_STATE_ATTR(index) &sensor_dev_attr_fan##index##_state.dev_attr.attr
#define DECLARE_FAN_FAULT_SENSOR_DEV_ATTR(index) \
static SENSOR_DEVICE_ATTR(fan##index##_fault, S_IRUGO, fan_show_value, NULL, FAN##index##_FAULT)
#define DECLARE_FAN_FAULT_ATTR(index) &sensor_dev_attr_fan##index##_fault.dev_attr.attr
#define DECLARE_FAN_DUTY_CYCLE_SENSOR_DEV_ATTR(index) \
static SENSOR_DEVICE_ATTR(fan##index##_duty_cycle_percentage, S_IWUSR | S_IRUGO, fan_show_value, set_duty_cycle, FAN##index##_DUTY_CYCLE_PERCENTAGE)
#define DECLARE_FAN_DUTY_CYCLE_ATTR(index) &sensor_dev_attr_fan##index##_duty_cycle_percentage.dev_attr.attr
#define DECLARE_FAN_SPEED_RPM_SENSOR_DEV_ATTR(index) \
static SENSOR_DEVICE_ATTR(fan##index##_front_speed_rpm, S_IRUGO, fan_show_value, NULL, FAN##index##_FRONT_SPEED_RPM);\
static SENSOR_DEVICE_ATTR(fan##index##_rear_speed_rpm, S_IRUGO, fan_show_value, NULL, FAN##index##_REAR_SPEED_RPM)
#define DECLARE_FAN_SPEED_RPM_ATTR(index) &sensor_dev_attr_fan##index##_front_speed_rpm.dev_attr.attr, \
&sensor_dev_attr_fan##index##_rear_speed_rpm.dev_attr.attr
#define DECLARE_FAN_DIRECTION_SENSOR_DEV_ATTR(index) \
static SENSOR_DEVICE_ATTR(fan##index##_direction, S_IWUSR | S_IRUGO, fan_show_value, set_fan_direction, FAN##index##_DIRECTION)
#define DECLARE_FAN_DIRECTION_ATTR(index) &sensor_dev_attr_fan##index##_direction.dev_attr.attr
/* 5 fan state attributes in this platform */
DECLARE_FAN_STATE_SENSOR_DEV_ATTR(1);
DECLARE_FAN_STATE_SENSOR_DEV_ATTR(2);
DECLARE_FAN_STATE_SENSOR_DEV_ATTR(3);
DECLARE_FAN_STATE_SENSOR_DEV_ATTR(4);
DECLARE_FAN_STATE_SENSOR_DEV_ATTR(5);
/* 5 fan fault attributes in this platform */
DECLARE_FAN_FAULT_SENSOR_DEV_ATTR(1);
DECLARE_FAN_FAULT_SENSOR_DEV_ATTR(2);
DECLARE_FAN_FAULT_SENSOR_DEV_ATTR(3);
DECLARE_FAN_FAULT_SENSOR_DEV_ATTR(4);
DECLARE_FAN_FAULT_SENSOR_DEV_ATTR(5);
/* 5 fan speed(rpm) attributes in this platform */
DECLARE_FAN_SPEED_RPM_SENSOR_DEV_ATTR(1);
DECLARE_FAN_SPEED_RPM_SENSOR_DEV_ATTR(2);
DECLARE_FAN_SPEED_RPM_SENSOR_DEV_ATTR(3);
DECLARE_FAN_SPEED_RPM_SENSOR_DEV_ATTR(4);
DECLARE_FAN_SPEED_RPM_SENSOR_DEV_ATTR(5);
/* 1 fan duty cycle attribute in this platform */
DECLARE_FAN_DUTY_CYCLE_SENSOR_DEV_ATTR();
DECLARE_FAN_DIRECTION_SENSOR_DEV_ATTR(1);
DECLARE_FAN_DIRECTION_SENSOR_DEV_ATTR(2);
DECLARE_FAN_DIRECTION_SENSOR_DEV_ATTR(3);
DECLARE_FAN_DIRECTION_SENSOR_DEV_ATTR(4);
DECLARE_FAN_DIRECTION_SENSOR_DEV_ATTR(5);
static struct attribute *cs5435_54p_fan_attributes[] = {
/* fan related attributes */
DECLARE_FAN_STATE_ATTR(1),
DECLARE_FAN_STATE_ATTR(2),
DECLARE_FAN_STATE_ATTR(3),
DECLARE_FAN_STATE_ATTR(4),
DECLARE_FAN_STATE_ATTR(5),
DECLARE_FAN_FAULT_ATTR(1),
DECLARE_FAN_FAULT_ATTR(2),
DECLARE_FAN_FAULT_ATTR(3),
DECLARE_FAN_FAULT_ATTR(4),
DECLARE_FAN_FAULT_ATTR(5),
DECLARE_FAN_SPEED_RPM_ATTR(1),
DECLARE_FAN_SPEED_RPM_ATTR(2),
DECLARE_FAN_SPEED_RPM_ATTR(3),
DECLARE_FAN_SPEED_RPM_ATTR(4),
DECLARE_FAN_SPEED_RPM_ATTR(5),
DECLARE_FAN_DUTY_CYCLE_ATTR(),
DECLARE_FAN_DIRECTION_ATTR(1),
DECLARE_FAN_DIRECTION_ATTR(2),
DECLARE_FAN_DIRECTION_ATTR(3),
DECLARE_FAN_DIRECTION_ATTR(4),
DECLARE_FAN_DIRECTION_ATTR(5),
NULL
};
#define FAN_MAX_DUTY_CYCLE 100
#define FAN_REG_VAL_TO_SPEED_RPM_STEP 100
/* fan utility functions
*/
static u32 reg_val_to_duty_cycle(u8 reg_val)
{
if (reg_val
== 0xFF) {
return 100;
}
return ((u32)(reg_val) * 100)/ 255;
}
static u8 duty_cycle_to_reg_val(u8 duty_cycle)
{
if (duty_cycle >= FAN_MAX_DUTY_CYCLE) {
return 0xFF;
}
return 255 / 10 * (duty_cycle / 10);
}
static u32 reg_val_to_speed_rpm(u8 reg_val)
{
return (u32)reg_val * FAN_REG_VAL_TO_SPEED_RPM_STEP;
}
static u8 reg_val_to_is_state(u8 reg_val, enum fan_id id)
{
u8 mask = (1 << id);
reg_val &= mask;
return reg_val ? 0 : 1;
}
static u8 is_fan_fault(struct cs5435_54p_fan_data *data, enum fan_id id)
{
u8 ret = 1;
int front_fan_index = FAN1_FRONT_SPEED_RPM + id;
int rear_fan_index = FAN1_REAR_SPEED_RPM + id;
/* Check if the speed of front or rear fan is ZERO,
*/
if (reg_val_to_speed_rpm(data->reg_val[front_fan_index]) &&
reg_val_to_speed_rpm(data->reg_val[rear_fan_index])) {
ret = 0;
}
return ret;
}
static ssize_t set_duty_cycle(struct device *dev, struct device_attribute *da,
const char *buf, size_t count)
{
int error, value;
error = kstrtoint(buf, 10, &value);
if (error)
return error;
if (value <= 0 || value > FAN_MAX_DUTY_CYCLE)
return -EINVAL;
cig_cpld_write_register(fan_reg[FAN_DUTY_CYCLE_PERCENTAGE], duty_cycle_to_reg_val(value));
return count;
}
static ssize_t set_fan_direction(struct device *dev, struct device_attribute *da,
const char *buf, size_t count)
{
int error, value,fan_index;
u8 mask,reg_val;
struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
fan_index = attr->index - FAN1_DIRECTION;
error = kstrtoint(buf, 10, &value);
if (error)
return error;
if (!(value == 0 || value == 1))
return -EINVAL;
cig_cpld_read_register(fan_reg[FAN_DIRECTION],&reg_val);
if(value == 1)
{
reg_val |= (1 << fan_index);
}
else
{
reg_val &= ~(1 << fan_index);
}
cig_cpld_write_register(fan_reg[FAN_DIRECTION], reg_val);
return count;
}
static ssize_t fan_show_value(struct device *dev, struct device_attribute *da,
char *buf)
{
struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
cs5435_54p_fan_update_device(dev);
struct cs5435_54p_fan_data *data = fan_data;
ssize_t ret = 0;
if (data->valid) {
switch (attr->index) {
case FAN1_STATE:
case FAN2_STATE:
case FAN3_STATE:
case FAN4_STATE:
case FAN5_STATE:
//printk("FAN_STATE_REG: 0x%x\n", data->reg_val[FAN_STATE_REG]);
//printk("index: %d\n", attr->index);
ret = sprintf(buf, "%d\n",
reg_val_to_is_state(data->reg_val[FAN_STATE_REG],
attr->index - FAN1_STATE));
break;
case FAN_DUTY_CYCLE_PERCENTAGE:
{
u32 duty_cycle = reg_val_to_duty_cycle(data->reg_val[FAN_DUTY_CYCLE_PERCENTAGE]);
ret = sprintf(buf, "%u\n", duty_cycle);
break;
}
case FAN1_FRONT_SPEED_RPM:
case FAN2_FRONT_SPEED_RPM:
case FAN3_FRONT_SPEED_RPM:
case FAN4_FRONT_SPEED_RPM:
case FAN5_FRONT_SPEED_RPM:
case FAN1_REAR_SPEED_RPM:
case FAN2_REAR_SPEED_RPM:
case FAN3_REAR_SPEED_RPM:
case FAN4_REAR_SPEED_RPM:
case FAN5_REAR_SPEED_RPM:
// printk("FAN_seed_REG: 0x%x\n", data->reg_val[attr->index]);
// printk("index: %d\n", attr->index);
ret = sprintf(buf, "%u\n", reg_val_to_speed_rpm(data->reg_val[attr->index]));
break;
case FAN1_FAULT:
case FAN2_FAULT:
case FAN3_FAULT:
case FAN4_FAULT:
case FAN5_FAULT:
ret = sprintf(buf, "%d\n", is_fan_fault(data, attr->index - FAN1_FAULT));
break;
case FAN1_DIRECTION:
case FAN2_DIRECTION:
case FAN3_DIRECTION:
case FAN4_DIRECTION:
case FAN5_DIRECTION:
ret = sprintf(buf, "%d\n",reg_val_to_is_state(data->reg_val[FAN_DIRECTION],attr->index - FAN1_DIRECTION));
break;
default:
break;
}
}
return ret;
}
static const struct attribute_group cs5435_54p_fan_group = {
.attrs = cs5435_54p_fan_attributes,
};
static struct cs5435_54p_fan_data *cs5435_54p_fan_update_device(struct device *dev)
{
struct cs5435_54p_fan_data *data = fan_data;
mutex_lock(&data->update_lock);
if (time_after(jiffies, data->last_updated + HZ + HZ / 2) ||
!data->valid) {
int i;
data->valid = 0;
/* Update fan data
*/
for (i = 0; i < ARRAY_SIZE(data->reg_val); i++) {
u8 status;
(void)cig_cpld_read_register(fan_reg[i], &status);
if (status < 0) {
data->valid = 0;
mutex_unlock(&data->update_lock);
return data;
}
else {
data->reg_val[i] = status;
}
}
data->last_updated = jiffies;
data->valid = 1;
}
mutex_unlock(&data->update_lock);
return data;
}
static int cs5435_54p_fan_probe(struct platform_device *pdev)
{
int status = -1;
/* Register sysfs hooks */
status = sysfs_create_group(&pdev->dev.kobj, &cs5435_54p_fan_group);
if (status) {
goto exit;
}
fan_data->hwmon_dev = hwmon_device_register(&pdev->dev);
if (IS_ERR(fan_data->hwmon_dev)) {
status = PTR_ERR(fan_data->hwmon_dev);
goto exit_remove;
}
dev_info(&pdev->dev, "cs5435_54p_fan\n");
return 0;
exit_remove:
sysfs_remove_group(&pdev->dev.kobj, &cs5435_54p_fan_group);
exit:
return status;
}
static int cs5435_54p_fan_remove(struct platform_device *pdev)
{
hwmon_device_unregister(fan_data->hwmon_dev);
sysfs_remove_group(&fan_data->pdev->dev.kobj, &cs5435_54p_fan_group);
return 0;
}
#define DRVNAME "cs5435_54p_fan"
static struct platform_driver cs5435_54p_fan_driver = {
.probe = cs5435_54p_fan_probe,
.remove = cs5435_54p_fan_remove,
.driver = {
.name = DRVNAME,
.owner = THIS_MODULE,
},
};
static int __init cs5435_54p_fan_init(void)
{
int ret;
cig_cpld_write_register(0x40, duty_cycle_to_reg_val(50));
ret = platform_driver_register(&cs5435_54p_fan_driver);
if (ret < 0) {
goto exit;
}
fan_data = kzalloc(sizeof(struct cs5435_54p_fan_data), GFP_KERNEL);
if (!fan_data) {
ret = -ENOMEM;
platform_driver_unregister(&cs5435_54p_fan_driver);
goto exit;
}
mutex_init(&fan_data->update_lock);
fan_data->valid = 0;
fan_data->pdev = platform_device_register_simple(DRVNAME, -1, NULL, 0);
if (IS_ERR(fan_data->pdev)) {
ret = PTR_ERR(fan_data->pdev);
platform_driver_unregister(&cs5435_54p_fan_driver);
kfree(fan_data);
goto exit;
}
exit:
return ret;
}
static void __exit cs5435_54p_fan_exit(void)
{
platform_device_unregister(fan_data->pdev);
platform_driver_unregister(&cs5435_54p_fan_driver);
kfree(fan_data);
}
MODULE_AUTHOR("CIG");
MODULE_DESCRIPTION("cs5435_54p_fan driver");
MODULE_LICENSE("GPL");
module_init(cs5435_54p_fan_init);
module_exit(cs5435_54p_fan_exit);
MODULE_AUTHOR("Zhang Peng <zhangpeng@cigtech.com>");
MODULE_DESCRIPTION("cs5435_54p_fan driver");
MODULE_LICENSE("GPL");

View File

@ -0,0 +1,594 @@
/*
* A hwmon driver for the CIG cs5435-54P LED
*
* Copyright (C) 2018 Cambridge, Inc.
*
* 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.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/*#define DEBUG*/
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/platform_device.h>
#include <linux/err.h>
#include <linux/leds.h>
#include <linux/slab.h>
#include <linux/dmi.h>
extern int cig_cpld_write_register(u8 reg_off, u8 val);
extern int cig_cpld_read_register(u8 reg_off, u8 *val);
extern void led_classdev_unregister(struct led_classdev *led_cdev);
extern int led_classdev_register(struct device *parent, struct led_classdev *led_cdev);
extern void led_classdev_resume(struct led_classdev *led_cdev);
extern void led_classdev_suspend(struct led_classdev *led_cdev);
#define DRVNAME "cs5435_54p_led"
struct cs5435_54p_led_data {
struct platform_device *pdev;
struct mutex update_lock;
char valid; /* != 0 if registers are valid */
unsigned long last_updated; /* In jiffies */
u8 reg_val[6]; /* 0: system & location
1: PSU1 &PSU12
2: fan & management
3: console & ToD
4-5 : fan1-fan5*/
};
static struct cs5435_54p_led_data *ledctl = NULL;
/* LED related data
*/
#define LED_TYPE_PSU1_REG_MASK 0x0C
#define LED_MODE_PSU1_GREEN_MASK 0x08
#define LED_MODE_PSU1_RED_MASK 0x04
#define LED_MODE_PSU1_AMBER_MASK 0x0C
#define LED_MODE_PSU1_OFF_MASK 0x00
#define LED_TYPE_PSU2_REG_MASK 0x30
#define LED_MODE_PSU2_GREEN_MASK 0x20
#define LED_MODE_PSU2_RED_MASK 0x10
#define LED_MODE_PSU2_AMBER_MASK 0x30
#define LED_MODE_PSU2_OFF_MASK 0x00
#define LED_TYPE_SYS_REG_MASK 0xF0
#define LED_MODE_SYS_GREEN_MASK 0x40
#define LED_MODE_SYS_RED_MASK 0x20
#define LED_MODE_SYS_AMBER_MASK 0x60
#define LED_MODE_SYS_AMBER_FLASHING_MASK 0x70
#define LED_MODE_SYS_OFF_MASK 0x00
#define LED_TYPE_RES_REG_MASK 0x0F
#define LED_MODE_RES_GREEN_MASK 0x04
#define LED_MODE_RES_RED_MASK 0x02
#define LED_MODE_RES_AMBER_MASK 0x06
#define LED_MODE_RES_AMBER_FLASHING_MASK 0x07
#define LED_MODE_RES_OFF_MASK 0x00
#define LED_TYPE_FAN_REG_MASK 0x03
#define LED_MODE_FAN_GREEN_MASK 0x02
#define LED_MODE_FAN_RED_MASK 0x01
#define LED_MODE_FAN_AMBER_MASK 0x03
#define LED_MODE_FAN_OFF_MASK 0x00
#define LED_TYPE_FAN1_REG_MASK 0x03
#define LED_TYPE_FAN2_REG_MASK 0x0C
#define LED_TYPE_FAN3_REG_MASK 0x30
#define LED_TYPE_FAN4_REG_MASK 0xC0
#define LED_TYPE_FAN5_REG_MASK 0x03
#define LED_MODE_FANX_GREEN_MASK 0x02
#define LED_MODE_FANX_RED_MASK 0x01
#define LED_MODE_FANX_AMBER_MASK 0x03
#define LED_MODE_FANX_OFF_MASK 0x00
enum led_type {
LED_TYPE_SYS,
LED_TYPE_PSU2,
LED_TYPE_PSU1,
LED_TYPE_FAN,
LED_TYPE_FAN1,
LED_TYPE_FAN2,
LED_TYPE_FAN3,
LED_TYPE_FAN4,
LED_TYPE_FAN5,
};
static const u8 led_reg[] = {
0x30, /* system & reserved*/
0x31, /* fan & PSU1 & PSU2 */
0x32, /* FAN5 LED */
0x33, /* FAN1-4 LED */
};
enum led_light_mode {
LED_MODE_OFF = 0,
LED_MODE_GREEN,
LED_MODE_AMBER,
LED_MODE_RED,
LED_MODE_GREEN_BLINK,
LED_MODE_AMBER_BLINK,
LED_MODE_RED_BLINK,
LED_MODE_GREEN_FLASHING,
LED_MODE_AMBER_FLASHING,
LED_MODE_RED_FLASHING,
LED_MODE_AUTO,
LED_MODE_UNKNOWN
};
struct led_type_mode {
enum led_type type;
int type_mask;
enum led_light_mode mode;
int mode_mask;
};
static struct led_type_mode led_type_mode_data[] = {
{LED_TYPE_PSU1, LED_TYPE_PSU1_REG_MASK, LED_MODE_GREEN, LED_MODE_PSU1_GREEN_MASK},
{LED_TYPE_PSU1, LED_TYPE_PSU1_REG_MASK, LED_MODE_AMBER, LED_MODE_PSU1_AMBER_MASK},
{LED_TYPE_PSU1, LED_TYPE_PSU1_REG_MASK, LED_MODE_RED, LED_MODE_PSU1_RED_MASK},
{LED_TYPE_PSU1, LED_TYPE_PSU1_REG_MASK, LED_MODE_OFF, LED_MODE_PSU1_OFF_MASK},
{LED_TYPE_PSU2, LED_TYPE_PSU2_REG_MASK, LED_MODE_GREEN, LED_MODE_PSU2_GREEN_MASK},
{LED_TYPE_PSU2, LED_TYPE_PSU2_REG_MASK, LED_MODE_AMBER, LED_MODE_PSU2_AMBER_MASK},
{LED_TYPE_PSU2, LED_TYPE_PSU2_REG_MASK, LED_MODE_RED, LED_MODE_PSU2_RED_MASK},
{LED_TYPE_PSU2, LED_TYPE_PSU2_REG_MASK, LED_MODE_OFF, LED_MODE_PSU2_OFF_MASK},
{LED_TYPE_SYS, LED_TYPE_SYS_REG_MASK, LED_MODE_GREEN, LED_MODE_SYS_GREEN_MASK},
{LED_TYPE_SYS, LED_TYPE_SYS_REG_MASK, LED_MODE_AMBER, LED_MODE_SYS_AMBER_MASK},
{LED_TYPE_SYS, LED_TYPE_SYS_REG_MASK, LED_MODE_RED, LED_MODE_SYS_RED_MASK},
{LED_TYPE_SYS, LED_TYPE_SYS_REG_MASK, LED_MODE_AMBER_FLASHING, LED_MODE_SYS_AMBER_FLASHING_MASK},
{LED_TYPE_SYS, LED_TYPE_SYS_REG_MASK, LED_MODE_OFF, LED_MODE_SYS_OFF_MASK},
{LED_TYPE_FAN, LED_TYPE_FAN_REG_MASK, LED_MODE_GREEN, LED_MODE_FAN_GREEN_MASK},
{LED_TYPE_FAN, LED_TYPE_FAN_REG_MASK, LED_MODE_AMBER, LED_MODE_FAN_AMBER_MASK},
{LED_TYPE_FAN, LED_TYPE_FAN_REG_MASK, LED_MODE_RED, LED_MODE_FAN_RED_MASK},
{LED_TYPE_FAN, LED_TYPE_FAN_REG_MASK, LED_MODE_OFF, LED_MODE_FAN_OFF_MASK},
{LED_TYPE_FAN1, LED_TYPE_FAN1_REG_MASK, LED_MODE_GREEN, LED_MODE_FANX_GREEN_MASK << 0},
{LED_TYPE_FAN1, LED_TYPE_FAN1_REG_MASK, LED_MODE_RED, LED_MODE_FANX_RED_MASK << 0},
{LED_TYPE_FAN1, LED_TYPE_FAN1_REG_MASK, LED_MODE_AMBER, LED_MODE_FANX_AMBER_MASK << 0},
{LED_TYPE_FAN1, LED_TYPE_FAN1_REG_MASK, LED_MODE_OFF, LED_MODE_FANX_OFF_MASK << 0},
{LED_TYPE_FAN2, LED_TYPE_FAN2_REG_MASK, LED_MODE_GREEN, LED_MODE_FANX_GREEN_MASK << 2},
{LED_TYPE_FAN2, LED_TYPE_FAN2_REG_MASK, LED_MODE_RED, LED_MODE_FANX_RED_MASK << 2},
{LED_TYPE_FAN2, LED_TYPE_FAN2_REG_MASK, LED_MODE_AMBER, LED_MODE_FANX_AMBER_MASK << 2},
{LED_TYPE_FAN2, LED_TYPE_FAN2_REG_MASK, LED_MODE_OFF, LED_MODE_FANX_OFF_MASK << 2},
{LED_TYPE_FAN3, LED_TYPE_FAN3_REG_MASK, LED_MODE_GREEN, LED_MODE_FANX_GREEN_MASK << 4},
{LED_TYPE_FAN3, LED_TYPE_FAN3_REG_MASK, LED_MODE_RED, LED_MODE_FANX_RED_MASK << 4},
{LED_TYPE_FAN3, LED_TYPE_FAN3_REG_MASK, LED_MODE_AMBER, LED_MODE_FANX_AMBER_MASK << 4},
{LED_TYPE_FAN3, LED_TYPE_FAN3_REG_MASK, LED_MODE_OFF, LED_MODE_FANX_OFF_MASK << 4},
{LED_TYPE_FAN4, LED_TYPE_FAN4_REG_MASK, LED_MODE_GREEN, LED_MODE_FANX_GREEN_MASK << 6},
{LED_TYPE_FAN4, LED_TYPE_FAN4_REG_MASK, LED_MODE_RED, LED_MODE_FANX_RED_MASK << 6},
{LED_TYPE_FAN4, LED_TYPE_FAN4_REG_MASK, LED_MODE_AMBER, LED_MODE_FANX_AMBER_MASK << 6},
{LED_TYPE_FAN4, LED_TYPE_FAN4_REG_MASK, LED_MODE_OFF, LED_MODE_FANX_OFF_MASK << 6},
{LED_TYPE_FAN5, LED_TYPE_FAN5_REG_MASK, LED_MODE_GREEN, LED_MODE_FANX_GREEN_MASK << 0},
{LED_TYPE_FAN5, LED_TYPE_FAN5_REG_MASK, LED_MODE_RED, LED_MODE_FANX_RED_MASK << 0},
{LED_TYPE_FAN5, LED_TYPE_FAN5_REG_MASK, LED_MODE_AMBER, LED_MODE_FANX_AMBER_MASK << 0},
{LED_TYPE_FAN5, LED_TYPE_FAN5_REG_MASK, LED_MODE_OFF, LED_MODE_FANX_OFF_MASK << 0},
};
struct fanx_info_s {
u8 cname; /* device name */
enum led_type type;
u8 reg_id; /* map to led_reg & reg_val */
};
static struct fanx_info_s fanx_info[] = {
{'1', LED_TYPE_FAN1, 3},
{'2', LED_TYPE_FAN2, 3},
{'3', LED_TYPE_FAN3, 3},
{'4', LED_TYPE_FAN4, 3},
{'5', LED_TYPE_FAN5, 2},
};
static int led_reg_val_to_light_mode(enum led_type type, u8 reg_val) {
int i;
for (i = 0; i < ARRAY_SIZE(led_type_mode_data); i++) {
if (type != led_type_mode_data[i].type)
continue;
if ((led_type_mode_data[i].type_mask & reg_val) ==
led_type_mode_data[i].mode_mask)
{
return led_type_mode_data[i].mode;
}
}
return 0;
}
static u8 led_light_mode_to_reg_val(enum led_type type,
enum led_light_mode mode, u8 reg_val) {
int i;
for (i = 0; i < ARRAY_SIZE(led_type_mode_data); i++) {
if (type != led_type_mode_data[i].type)
continue;
if (mode != led_type_mode_data[i].mode)
continue;
reg_val = led_type_mode_data[i].mode_mask |
(reg_val & (~led_type_mode_data[i].type_mask));
break;
}
return reg_val;
}
static void cs5435_54p_led_update(void)
{
mutex_lock(&ledctl->update_lock);
if (time_after(jiffies, ledctl->last_updated + HZ + HZ / 2)
|| !ledctl->valid) {
int i;
dev_dbg(&ledctl->pdev->dev, "Starting cs5435_54p_led update\n");
/* Update LED data
*/
for (i = 0; i < ARRAY_SIZE(ledctl->reg_val); i++) {
u8 status;
cig_cpld_read_register(led_reg[i], &status);
if (status < 0) {
ledctl->valid = 0;
dev_dbg(&ledctl->pdev->dev, "reg %d, err %d\n", led_reg[i], status);
goto exit;
}
else
{
ledctl->reg_val[i] = status;
}
}
ledctl->last_updated = jiffies;
ledctl->valid = 1;
}
exit:
mutex_unlock(&ledctl->update_lock);
}
static void cs5435_54p_led_set(struct led_classdev *led_cdev,
enum led_brightness led_light_mode,
u8 reg, enum led_type type)
{
u8 reg_val;
mutex_lock(&ledctl->update_lock);
cig_cpld_read_register(reg, &reg_val);
if (reg_val < 0) {
dev_dbg(&ledctl->pdev->dev, "reg %d, err %d\n", reg, reg_val);
goto exit;
}
reg_val = led_light_mode_to_reg_val(type, led_light_mode, reg_val);
cig_cpld_write_register(reg, reg_val);
/* to prevent the slow-update issue */
ledctl->valid = 0;
exit:
mutex_unlock(&ledctl->update_lock);
}
static void cs5435_54p_led_fanx_set(struct led_classdev *led_cdev,
enum led_brightness led_light_mode)
{
enum led_type led_type1;
int reg_id;
int i, nsize;
int ncount = sizeof(fanx_info)/sizeof(struct fanx_info_s);
for(i=0;i<ncount;i++)
{
nsize=strlen(led_cdev->name);
if (led_cdev->name[nsize-1] == fanx_info[i].cname)
{
led_type1 = fanx_info[i].type;
reg_id = fanx_info[i].reg_id;
cs5435_54p_led_set(led_cdev, led_light_mode, led_reg[reg_id], led_type1);
return;
}
}
}
static enum led_brightness cs5435_54p_led_fanx_get(struct led_classdev *cdev)
{
enum led_type led_type1;
int reg_id;
int i, nsize;
int ncount = sizeof(fanx_info)/sizeof(struct fanx_info_s);
for(i=0;i<ncount;i++)
{
nsize=strlen(cdev->name);
if (cdev->name[nsize-1] == fanx_info[i].cname)
{
led_type1 = fanx_info[i].type;
reg_id = fanx_info[i].reg_id;
cs5435_54p_led_update();
return led_reg_val_to_light_mode(led_type1, ledctl->reg_val[reg_id]);
}
}
return led_reg_val_to_light_mode(LED_TYPE_FAN1, ledctl->reg_val[5]);
}
static void cs5435_54p_led_psu1_set(struct led_classdev *led_cdev,
enum led_brightness led_light_mode)
{
cs5435_54p_led_set(led_cdev, led_light_mode, led_reg[1], LED_TYPE_PSU1);
}
static enum led_brightness cs5435_54p_led_psu1_get(struct led_classdev *cdev)
{
cs5435_54p_led_update();
return led_reg_val_to_light_mode(LED_TYPE_PSU1, ledctl->reg_val[1]);
}
static void cs5435_54p_led_psu2_set(struct led_classdev *led_cdev,
enum led_brightness led_light_mode)
{
cs5435_54p_led_set(led_cdev, led_light_mode, led_reg[1], LED_TYPE_PSU2);
}
static enum led_brightness cs5435_54p_led_psu2_get(struct led_classdev *cdev)
{
cs5435_54p_led_update();
return led_reg_val_to_light_mode(LED_TYPE_PSU2, ledctl->reg_val[1]);
}
static void cs5435_54p_led_sys_set(struct led_classdev *led_cdev,
enum led_brightness led_light_mode)
{
cs5435_54p_led_set(led_cdev, led_light_mode,led_reg[0], LED_TYPE_SYS);
}
static enum led_brightness cs5435_54p_led_sys_get(struct led_classdev *cdev)
{
cs5435_54p_led_update();
return led_reg_val_to_light_mode(LED_TYPE_SYS, ledctl->reg_val[0]);
}
static enum led_brightness cs5435_54p_led_fan_get(struct led_classdev *cdev)
{
cs5435_54p_led_update();
return led_reg_val_to_light_mode(LED_TYPE_FAN, ledctl->reg_val[1]);
}
static void cs5435_54p_led_fan_set(struct led_classdev *led_cdev,
enum led_brightness led_light_mode)
{
cs5435_54p_led_set(led_cdev, led_light_mode, led_reg[1], LED_TYPE_FAN);
}
static struct led_classdev cs5435_54p_leds[] = {
[LED_TYPE_SYS] = {
.name = "cs5435_54p_led::sys",
.default_trigger = "unused",
.brightness_set = cs5435_54p_led_sys_set,
.brightness_get = cs5435_54p_led_sys_get,
.flags = LED_CORE_SUSPENDRESUME,
.max_brightness = LED_MODE_AUTO,
},
[LED_TYPE_FAN] = {
.name = "cs5435_54p_led::fan",
.default_trigger = "unused",
.brightness_set = cs5435_54p_led_fan_set,
.brightness_get = cs5435_54p_led_fan_get,
.flags = LED_CORE_SUSPENDRESUME,
.max_brightness = LED_MODE_AUTO,
},
[LED_TYPE_PSU1] = {
.name = "cs5435_54p_led::psu1",
.default_trigger = "unused",
.brightness_set = cs5435_54p_led_psu1_set,
.brightness_get = cs5435_54p_led_psu1_get,
.flags = LED_CORE_SUSPENDRESUME,
.max_brightness = LED_MODE_AUTO,
},
[LED_TYPE_PSU2] = {
.name = "cs5435_54p_led::psu2",
.default_trigger = "unused",
.brightness_set = cs5435_54p_led_psu2_set,
.brightness_get = cs5435_54p_led_psu2_get,
.flags = LED_CORE_SUSPENDRESUME,
.max_brightness = LED_MODE_AUTO,
},
[LED_TYPE_FAN1] = {
.name = "cs5435_54p_led::fan1",
.default_trigger = "unused",
.brightness_set = cs5435_54p_led_fanx_set,
.brightness_get = cs5435_54p_led_fanx_get,
.flags = LED_CORE_SUSPENDRESUME,
.max_brightness = LED_MODE_AUTO,
},
[LED_TYPE_FAN2] = {
.name = "cs5435_54p_led::fan2",
.default_trigger = "unused",
.brightness_set = cs5435_54p_led_fanx_set,
.brightness_get = cs5435_54p_led_fanx_get,
.flags = LED_CORE_SUSPENDRESUME,
.max_brightness = LED_MODE_AUTO,
},
[LED_TYPE_FAN3] = {
.name = "cs5435_54p_led::fan3",
.default_trigger = "unused",
.brightness_set = cs5435_54p_led_fanx_set,
.brightness_get = cs5435_54p_led_fanx_get,
.flags = LED_CORE_SUSPENDRESUME,
.max_brightness = LED_MODE_AUTO,
},
[LED_TYPE_FAN4] = {
.name = "cs5435_54p_led::fan4",
.default_trigger = "unused",
.brightness_set = cs5435_54p_led_fanx_set,
.brightness_get = cs5435_54p_led_fanx_get,
.flags = LED_CORE_SUSPENDRESUME,
.max_brightness = LED_MODE_AUTO,
},
[LED_TYPE_FAN5] = {
.name = "cs5435_54p_led::fan5",
.default_trigger = "unused",
.brightness_set = cs5435_54p_led_fanx_set,
.brightness_get = cs5435_54p_led_fanx_get,
.flags = LED_CORE_SUSPENDRESUME,
.max_brightness = LED_MODE_AUTO,
}
};
static int cs5435_54p_led_suspend(struct platform_device *dev,
pm_message_t state)
{
int i = 0;
for (i = 0; i < ARRAY_SIZE(cs5435_54p_leds); i++) {
led_classdev_suspend(&cs5435_54p_leds[i]);
}
return 0;
}
static int cs5435_54p_led_resume(struct platform_device *dev)
{
int i = 0;
for (i = 0; i < ARRAY_SIZE(cs5435_54p_leds); i++) {
led_classdev_resume(&cs5435_54p_leds[i]);
}
return 0;
}
static int cs5435_54p_led_probe(struct platform_device *pdev)
{
int ret, i;
for (i = 0; i < ARRAY_SIZE(cs5435_54p_leds); i++) {
ret = led_classdev_register(&pdev->dev, &cs5435_54p_leds[i]);
if (ret < 0)
break;
}
/* Check if all LEDs were successfully registered */
if (i != ARRAY_SIZE(cs5435_54p_leds)) {
int j;
/* only unregister the LEDs that were successfully registered */
for (j = 0; j < i; j++) {
led_classdev_unregister(&cs5435_54p_leds[i]);
}
}
return ret;
}
static int cs5435_54p_led_remove(struct platform_device *pdev)
{
int i;
for (i = 0; i < ARRAY_SIZE(cs5435_54p_leds); i++) {
led_classdev_unregister(&cs5435_54p_leds[i]);
}
return 0;
}
static struct platform_driver cs5435_54p_led_driver = {
.probe = cs5435_54p_led_probe,
.remove = cs5435_54p_led_remove,
.suspend = cs5435_54p_led_suspend,
.resume = cs5435_54p_led_resume,
.driver = {
.name = DRVNAME,
.owner = THIS_MODULE,
},
};
static int cs5435_54p_led_default(void)
{
cig_cpld_write_register(0x30, 0x40);// system green led solid on
}
static int __init cs5435_54p_led_init(void)
{
int ret;
ret = platform_driver_register(&cs5435_54p_led_driver);
if (ret < 0) {
goto exit;
}
ledctl = kzalloc(sizeof(struct cs5435_54p_led_data), GFP_KERNEL);
if (!ledctl) {
ret = -ENOMEM;
platform_driver_unregister(&cs5435_54p_led_driver);
goto exit;
}
mutex_init(&ledctl->update_lock);
ledctl->pdev = platform_device_register_simple(DRVNAME, -1, NULL, 0);
if (IS_ERR(ledctl->pdev)) {
ret = PTR_ERR(ledctl->pdev);
platform_driver_unregister(&cs5435_54p_led_driver);
kfree(ledctl);
goto exit;
}
cs5435_54p_led_default();
exit:
return ret;
}
static void __exit cs5435_54p_led_exit(void)
{
platform_device_unregister(ledctl->pdev);
platform_driver_unregister(&cs5435_54p_led_driver);
kfree(ledctl);
}
module_init(cs5435_54p_led_init);
module_exit(cs5435_54p_led_exit);
MODULE_AUTHOR("Zhang Peng <zhangpeng@cigtech.com>");
MODULE_DESCRIPTION("cs5435_54p_led driver");
MODULE_LICENSE("GPL");

View File

@ -0,0 +1,946 @@
/*
* A hwmon driver for the CIG cs5435-54P Power Module
*
* Copyright (C) 2018 Cambridge, Inc.
*
* 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.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <linux/module.h>
#include <linux/jiffies.h>
#include <linux/i2c.h>
#include <linux/hwmon.h>
#include <linux/hwmon-sysfs.h>
#include <linux/err.h>
#include <linux/mutex.h>
#include <linux/sysfs.h>
#include <linux/slab.h>
#include <linux/delay.h>
#include <linux/dmi.h>
#include <linux/fs.h>
#include <linux/uaccess.h>
#include <linux/syscalls.h>
#include <linux/kthread.h>
#include <linux/device.h>
#include <linux/platform_device.h>
#include "i2c-algo-lpc.h"
#define MAX_FAN_DUTY_CYCLE 100
/* Address scanned */
static const unsigned short normal_i2c[] = {I2C_CLIENT_END };
/* This is additional data */
struct cs5435_54p_psu_data {
struct device *hwmon_dev;
struct mutex update_lock;
char valid;
unsigned long last_updated; /* In jiffies */
/* Registers value */
u8 vout_mode;
u16 v_in;
u16 v_out;
u16 i_in;
u16 i_out;
u16 p_in;
u16 p_out;
u16 temp_input[3];
u8 temp_fault;
u8 fan_fault;
u16 fan_duty_cycle[2];
u16 fan_speed[2];
u8 mfr_id[8];
u8 mfr_model[20];
u8 mfr_serial[20];
u8 psu_is_present;
u8 psu_is_good;
struct i2c_client *client;
struct bin_attribute *bin; /* eeprom data */
};
static int two_complement_to_int(u16 data, u8 valid_bit, int mask);
static ssize_t set_fan_duty_cycle(struct device *dev, struct device_attribute *dev_attr, const char *buf, size_t count);
static ssize_t for_linear_data(struct device *dev, struct device_attribute *dev_attr, char *buf);
static ssize_t for_fan_fault(struct device *dev, struct device_attribute *dev_attr, char *buf);
static ssize_t for_fan_warning(struct device *dev, struct device_attribute *dev_attr, char *buf);
static ssize_t for_temp_fault(struct device *dev, struct device_attribute *dev_attr, char *buf);
static ssize_t for_temp_warning(struct device *dev, struct device_attribute *dev_attr, char *buf);
static ssize_t for_vout_data(struct device *dev, struct device_attribute *dev_attr, char *buf);
static int cs5435_54p_psu_read_byte(struct i2c_client *client, u8 reg);
static int cs5435_54p_psu_read_word(struct i2c_client *client, u8 reg);
static int cs5435_54p_psu_write_word(struct i2c_client *client, u8 reg, u16 value);
static int cs5435_54p_psu_read_block(struct i2c_client *client, u8 command, u8 *data, int data_len);
static struct cs5435_54p_psu_data *cs5435_54p_psu_update_device(struct device *dev);
static ssize_t for_ascii(struct device *dev, struct device_attribute *dev_attr, char *buf);
static ssize_t for_status(struct device *dev, struct device_attribute *dev_attr, char *buf);
enum cs5435_54p_psu_sysfs_attributes {
PSU_V_IN,
PSU_V_OUT,
PSU_I_IN,
PSU_I_OUT,
PSU_P_IN,
PSU_P_OUT,
PSU_TEMP1_INPUT,
PSU_TEMP2_INPUT,
PSU_TEMP3_INPUT,
PSU_TEMP_FAULT,
PSU_TEMP_WARN,
PSU_FAN1_FAULT,
PSU_FAN1_WARN,
PSU_FAN1_DUTY_CYCLE,
PSU_FAN1_SPEED,
PSU_MFR_ID,
PSU_MFR_MODEL,
PSU_MFR_SERIAL,
PSU_PRESENT,
PSU_P_GOOD,
};
static int two_complement_to_int(u16 data, u8 valid_bit, int mask)
{
u16 valid_data = data & mask;
bool is_negative = valid_data >> (valid_bit - 1);
return is_negative ? (-(((~valid_data) & mask) + 1)) : valid_data;
}
static ssize_t set_fan_duty_cycle(struct device *dev, struct device_attribute \
*dev_attr, const char *buf, size_t count)
{
struct sensor_device_attribute *attr = to_sensor_dev_attr(dev_attr);
struct i2c_client *client = to_i2c_client(dev);
struct cs5435_54p_psu_data *data = i2c_get_clientdata(client);
int nr = (attr->index == PSU_FAN1_DUTY_CYCLE) ? 0 : 1;
long speed;
int error;
if (data->valid != 1)
{
return -ENODEV;
}
error = kstrtol(buf, 10, &speed);
if (error)
return error;
if (speed < 0 || speed > MAX_FAN_DUTY_CYCLE)
return -EINVAL;
mutex_lock(&data->update_lock);
data->fan_duty_cycle[nr] = speed;
cs5435_54p_psu_write_word(client, 0x3B + nr, data->fan_duty_cycle[nr]);
mutex_unlock(&data->update_lock);
return count;
}
static ssize_t for_linear_data(struct device *dev, struct device_attribute *dev_attr, char *buf)
{
struct sensor_device_attribute *attr = to_sensor_dev_attr(dev_attr);
struct cs5435_54p_psu_data *data = cs5435_54p_psu_update_device(dev);
u16 value = 0;
int exponent, mantissa;
int multiplier = 1000;
if (data->valid != 1)
{
return -ENODEV;
}
switch (attr->index) {
case PSU_V_IN:
value = data->v_in;
break;
case PSU_I_IN:
value = data->i_in;
break;
case PSU_I_OUT:
value = data->i_out;
break;
case PSU_P_IN:
value = data->p_in;
break;
case PSU_P_OUT:
value = data->p_out;
break;
case PSU_TEMP1_INPUT:
value = data->temp_input[0];
break;
case PSU_TEMP2_INPUT:
value = data->temp_input[1];
break;
case PSU_TEMP3_INPUT:
value = data->temp_input[2];
break;
case PSU_FAN1_DUTY_CYCLE:
multiplier = 1;
value = data->fan_duty_cycle[0];
break;
case PSU_FAN1_SPEED:
multiplier = 1;
value = data->fan_speed[0];
break;
default:
break;
}
exponent = two_complement_to_int(value >> 11, 5, 0x1f);
mantissa = two_complement_to_int(value & 0x7ff, 11, 0x7ff);
return (exponent >= 0) ? sprintf(buf, "%d\n", \
(mantissa << exponent) * multiplier) : \
sprintf(buf, "%d\n", (mantissa * multiplier) / (1 << -exponent));
}
static ssize_t for_fan_fault(struct device *dev, struct device_attribute \
*dev_attr, char *buf)
{
struct sensor_device_attribute *attr = to_sensor_dev_attr(dev_attr);
struct cs5435_54p_psu_data *data = cs5435_54p_psu_update_device(dev);
if (data->valid != 1)
{
return -ENODEV;
}
u8 shift = (attr->index == PSU_FAN1_FAULT) ? 7 : 6;
return sprintf(buf, "%d\n", data->fan_fault >> shift);
}
static ssize_t for_fan_warning(struct device *dev, struct device_attribute \
*dev_attr, char *buf)
{
struct sensor_device_attribute *attr = to_sensor_dev_attr(dev_attr);
struct cs5435_54p_psu_data *data = cs5435_54p_psu_update_device(dev);
if (data->valid != 1)
{
return -ENODEV;
}
u8 shift = (attr->index == PSU_FAN1_WARN) ? 5 : 4;
return sprintf(buf, "%d\n", data->fan_fault >> shift);
}
static ssize_t for_temp_fault(struct device *dev, struct device_attribute \
*dev_attr, char *buf)
{
struct sensor_device_attribute *attr = to_sensor_dev_attr(dev_attr);
struct cs5435_54p_psu_data *data = cs5435_54p_psu_update_device(dev);
if (data->valid != 1)
{
return -ENODEV;
}
return sprintf(buf, "%d\n", data->temp_fault >> 7);
}
static ssize_t for_temp_warning(struct device *dev, struct device_attribute \
*dev_attr, char *buf)
{
struct sensor_device_attribute *attr = to_sensor_dev_attr(dev_attr);
struct cs5435_54p_psu_data *data = cs5435_54p_psu_update_device(dev);
if (data->valid != 1)
{
return -ENODEV;
}
return sprintf(buf, "%d\n", data->temp_fault >> 6);
}
static ssize_t for_vout_data(struct device *dev, struct device_attribute \
*dev_attr, char *buf)
{
struct cs5435_54p_psu_data *data = cs5435_54p_psu_update_device(dev);
int exponent, mantissa;
int multiplier = 1000;
if (data->valid != 1)
{
return -ENODEV;
}
exponent = two_complement_to_int(data->vout_mode, 5, 0x1f);
mantissa = data->v_out;
return (exponent > 0) ? sprintf(buf, "%d\n", \
(mantissa << exponent) * multiplier) : \
sprintf(buf, "%d\n", ((mantissa * multiplier) >> (-exponent)));
}
static ssize_t for_ascii(struct device *dev, struct device_attribute \
*dev_attr, char *buf)
{
struct sensor_device_attribute *attr = to_sensor_dev_attr(dev_attr);
struct cs5435_54p_psu_data *data = cs5435_54p_psu_update_device(dev);
u8 *ptr = NULL;
if (data->valid != 1)
{
return -ENODEV;
}
switch (attr->index) {
case PSU_MFR_ID:
ptr = data->mfr_id + 1;
break;
case PSU_MFR_MODEL:
ptr = data->mfr_model + 1;
break;
case PSU_MFR_SERIAL:
ptr = data->mfr_serial + 1;
break;
default:
return 0;
}
return sprintf(buf, "%s\n", ptr);
}
static ssize_t for_status(struct device *dev, struct device_attribute *dev_attr, char *buf)
{
struct sensor_device_attribute *attr = to_sensor_dev_attr(dev_attr);
struct cs5435_54p_psu_data *data = cs5435_54p_psu_update_device(dev);
u8 *ptr = NULL;
u8 status = 0;
if (attr->index == PSU_PRESENT) {
status = data->psu_is_present;
}
else { /* PSU_POWER_GOOD */
if (!data->valid) {
return -ENODEV;
}
status = data->psu_is_good;
}
return sprintf(buf, "%d\n", status);
}
static int cs5435_54p_psu_read_byte(struct i2c_client *client, u8 reg)
{
return i2c_smbus_read_byte_data(client, reg);
}
static int cs5435_54p_psu_read_word(struct i2c_client *client, u8 reg)
{
return i2c_smbus_read_word_data(client, reg);
}
static int cs5435_54p_psu_write_word(struct i2c_client *client, u8 reg, \
u16 value)
{
union i2c_smbus_data data;
data.word = value;
return i2c_smbus_xfer(client->adapter, client->addr,
client->flags |= I2C_CLIENT_PEC,
I2C_SMBUS_WRITE, reg,
I2C_SMBUS_WORD_DATA, &data);
}
static int cs5435_54p_psu_read_block(struct i2c_client *client, u8 command, \
u8 *data, int data_len)
{
int result = i2c_smbus_read_i2c_block_data(client, command, data_len,
data);
if (unlikely(result < 0))
goto abort;
if (unlikely(result != data_len)) {
result = -EIO;
goto abort;
}
result = 0;
abort:
return result;
}
struct reg_data_byte {
u8 reg;
u8 *value;
};
struct reg_data_word {
u8 reg;
u16 *value;
};
#define EEPROM_NAME "psu_eeprom"
#define EEPROM_SIZE 256 /* 256 byte eeprom */
/* Platform dependent --- */
static ssize_t psu_eeprom_write(struct i2c_client *client, u8 command, const char *data,
int data_len)
{
int status, retry = 3;
if (data_len > I2C_SMBUS_BLOCK_MAX) {
data_len = I2C_SMBUS_BLOCK_MAX;
}
while (retry) {
status = i2c_smbus_write_i2c_block_data(client, command, data_len, data);
if (unlikely(status < 0)) {
msleep(100);
retry--;
continue;
}
break;
}
if (unlikely(status < 0)) {
return status;
}
return data_len;
}
static ssize_t psu_page_write(struct i2c_client *client,const char *buf, loff_t off, size_t count)
{
ssize_t retval = 0;
if (unlikely(!count)) {
return count;
}
/*
* Write data to chip, protecting against concurrent updates
* from this host, but not from other I2C masters.
*/
while (count) {
ssize_t status;
status = psu_eeprom_write(client, off, buf, count);
if (status <= 0) {
if (retval == 0) {
retval = status;
}
break;
}
buf += status;
off += status;
count -= status;
retval += status;
}
return retval;
}
static ssize_t psu_bin_write(struct file *filp, struct kobject *kobj,
struct bin_attribute *attr,
char *buf, loff_t off, size_t count)
{
int present;
struct cs5435_54p_psu_data *data;
ssize_t retval = 0;
struct i2c_client *client;
data = dev_get_drvdata(container_of(kobj, struct device, kobj));
client = to_i2c_client(container_of(kobj, struct device, kobj));
mutex_lock(&data->update_lock);
retval = psu_page_write(client, buf, off, count);
mutex_unlock(&data->update_lock);
return retval;
}
static ssize_t psu_eeprom_read(struct i2c_client *client, u8 command, u8 *data,
int data_len)
{
int status, retry = 3;
if (data_len > I2C_SMBUS_BLOCK_MAX) {
data_len = I2C_SMBUS_BLOCK_MAX;
}
while (retry) {
status = i2c_smbus_read_i2c_block_data(client, command, data_len, data);
if (unlikely(status < 0)) {
msleep(100);
retry--;
continue;
}
break;
}
if (unlikely(status < 0)) {
goto abort;
}
if (unlikely(status != data_len)) {
status = -EIO;
goto abort;
}
abort:
return status;
}
static ssize_t psu_page_read(struct i2c_client *client,char *buf, loff_t off, size_t count)
{
ssize_t retval = 0;
if (unlikely(!count)) {
printk("Count = 0, return");
return count;
}
/*
* Read data from chip, protecting against concurrent updates
* from this host, but not from other I2C masters.
*/
while (count) {
ssize_t status;
status = psu_eeprom_read(client, off, buf, count);
if (status <= 0) {
if (retval == 0) {
retval = status;
}
break;
}
buf += status;
off += status;
count -= status;
retval += status;
}
return retval;
}
static ssize_t psu_bin_read(struct file *filp, struct kobject *kobj,
struct bin_attribute *attr,
char *buf, loff_t off, size_t count)
{
int present;
struct cs5435_54p_psu_data *data;
struct i2c_client *client;
ssize_t retval = 0;
data = dev_get_drvdata(container_of(kobj, struct device, kobj));
client = to_i2c_client(container_of(kobj, struct device, kobj));
mutex_lock(&data->update_lock);
retval = psu_page_read(client, buf, off, count);
mutex_unlock(&data->update_lock);
return retval;
}
static int psu_sysfs_eeprom_init(struct kobject *kobj, struct bin_attribute *eeprom)
{
int err;
sysfs_bin_attr_init(eeprom);
eeprom->attr.name = EEPROM_NAME;
eeprom->attr.mode = S_IWUSR | S_IRUGO;
eeprom->read = psu_bin_read;
eeprom->write = psu_bin_write;
eeprom->size = EEPROM_SIZE;
/* Create eeprom file */
err = sysfs_create_bin_file(kobj, eeprom);
if (err) {
return err;
}
return 0;
}
static int psu_sysfs_eeprom_cleanup(struct kobject *kobj, struct bin_attribute *eeprom)
{
sysfs_remove_bin_file(kobj, eeprom);
return 0;
}
static int psu_i2c_check_functionality(struct i2c_client *client)
{
return i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA | I2C_FUNC_SMBUS_I2C_BLOCK);
}
static int psu_eeprom_probe(struct i2c_client *client, const struct i2c_device_id *dev_id)
{
int status;
struct cs5435_54p_psu_data *data;
if (!psu_i2c_check_functionality(client)) {
status = -EIO;
goto exit;
}
data = kzalloc(sizeof(*data), GFP_KERNEL);
if (!data) {
status = -ENOMEM;
goto exit;
}
i2c_set_clientdata(client, data);
data->valid = 0;
mutex_init(&data->update_lock);
data->bin = kzalloc(sizeof(struct bin_attribute), GFP_KERNEL);
if (!data->bin) {
status = -ENOMEM;
goto eeprom_bin_error;
}
/* init eeprom */
status = psu_sysfs_eeprom_init(&client->dev.kobj, data->bin);
if (status) {
status = -ENOMEM;
goto sys_init_error;
}
dev_info(&client->dev, "psu eeprom '%s'\n", client->name);
return 0;
sys_init_error:
kfree(data->bin);
eeprom_bin_error:
kfree(data);
exit:
return status;
}
static struct cs5435_54p_psu_data *cs5435_54p_psu_update_device(struct device *dev)
{
struct i2c_client *client = to_i2c_client(dev);
struct cs5435_54p_psu_data *data = i2c_get_clientdata(client);
mutex_lock(&data->update_lock);
if (time_after(jiffies, data->last_updated)) {
int i, status;
u8 command;
struct reg_data_byte regs_byte[] = {
{0x20, &data->vout_mode},
{0x81, &data->fan_fault},
{0x7d, &data->temp_fault},
};
struct reg_data_word regs_word[] = {
{0x88, &data->v_in},
{0x8b, &data->v_out},
{0x89, &data->i_in},
{0x8c, &data->i_out},
{0x96, &data->p_out},
{0x97, &data->p_in},
{0x8d, &(data->temp_input[0])},
{0x8e, &(data->temp_input[1])},
{0x3b, &(data->fan_duty_cycle[0])},
{0x90, &(data->fan_speed[0])},
};
data->valid = 1;
dev_dbg(&client->dev, "start data update\n");
/* one milliseconds from now */
data->last_updated = jiffies + HZ / 1000;
for (i = 0; i < ARRAY_SIZE(regs_byte); i++) {
status = cs5435_54p_psu_read_byte(client,
regs_byte[i].reg);
if (status < 0) {
dev_dbg(&client->dev, "reg %d, err %d\n",
regs_byte[i].reg, status);
*(regs_byte[i].value) = 0;
data->valid = 0;
} else {
*(regs_byte[i].value) = status;
}
}
for (i = 0; i < ARRAY_SIZE(regs_word); i++)
{
status = cs5435_54p_psu_read_word(client,regs_word[i].reg);
if (status < 0)
{
dev_dbg(&client->dev, "reg %d, err %d\n",
regs_word[i].reg, status);
*(regs_word[i].value) = 0;
data->valid = 0;
}
else
{
*(regs_word[i].value) = status;
}
}
command = 0x99; /* PSU mfr_id */
status = cs5435_54p_psu_read_block(client, command,
data->mfr_id, ARRAY_SIZE(data->mfr_id) - 1);
data->mfr_id[ARRAY_SIZE(data->mfr_id) - 1] = '\0';
if (status < 0) {
dev_dbg(&client->dev, "reg %d, err %d\n", command, status);
memset(data->mfr_id, 0, sizeof(data->mfr_id));
data->valid = 0;
}
command = 0x9a; /* PSU mfr_model */
status = cs5435_54p_psu_read_block(client, command,
data->mfr_model, ARRAY_SIZE(data->mfr_model) - 1);
data->mfr_model[ARRAY_SIZE(data->mfr_model) - 1] = '\0';
if (status < 0) {
dev_dbg(&client->dev, "reg %d, err %d\n", command, status);
memset(data->mfr_model, 0, sizeof(data->mfr_id));
data->valid = 0;
}
command = 0x9e; /* PSU mfr_serial */
status = cs5435_54p_psu_read_block(client, command,
data->mfr_serial, ARRAY_SIZE(data->mfr_serial) - 1);
data->mfr_serial[ARRAY_SIZE(data->mfr_serial) - 1] = '\0';
if (status < 0) {
dev_dbg(&client->dev, "reg %d, err %d\n", command, status);
memset(data->mfr_serial, 0, sizeof(data->mfr_id));
data->valid = 0;
}
data->psu_is_present = strlen(data->mfr_id) > 1 ? 1:0;
if(data->psu_is_present)
{
data->psu_is_good = ((data->fan_fault) || (data->temp_fault))? 0:1;
}
else
{
data->valid = 0;
data->psu_is_good = 0;
}
}
mutex_unlock(&data->update_lock);
return data;
}
/* sysfs attributes for hwmon */
static SENSOR_DEVICE_ATTR(psu_v_in, S_IRUGO, for_linear_data, NULL, PSU_V_IN);
static SENSOR_DEVICE_ATTR(psu_v_out, S_IRUGO, for_vout_data, NULL, PSU_V_OUT);
static SENSOR_DEVICE_ATTR(psu_i_in, S_IRUGO, for_linear_data, NULL, PSU_I_IN);
static SENSOR_DEVICE_ATTR(psu_i_out, S_IRUGO, for_linear_data, NULL, PSU_I_OUT);
static SENSOR_DEVICE_ATTR(psu_p_in, S_IRUGO, for_linear_data, NULL, PSU_P_IN);
static SENSOR_DEVICE_ATTR(psu_p_out, S_IRUGO, for_linear_data, NULL, PSU_P_OUT);
static SENSOR_DEVICE_ATTR(psu_temp1_input, S_IRUGO, for_linear_data, NULL, PSU_TEMP1_INPUT);
static SENSOR_DEVICE_ATTR(psu_temp2_input, S_IRUGO, for_linear_data, NULL, PSU_TEMP2_INPUT);
static SENSOR_DEVICE_ATTR(psu_temp3_input, S_IRUGO, for_linear_data, NULL, PSU_TEMP3_INPUT);
static SENSOR_DEVICE_ATTR(psu_temp_fault, S_IRUGO, for_temp_fault, NULL, PSU_TEMP_FAULT);
static SENSOR_DEVICE_ATTR(psu_temp_warning, S_IRUGO, for_temp_warning, NULL, PSU_TEMP_WARN);
static SENSOR_DEVICE_ATTR(psu_fan1_fault, S_IRUGO, for_fan_fault, NULL, PSU_FAN1_FAULT);
static SENSOR_DEVICE_ATTR(psu_fan1_warning, S_IRUGO, for_fan_warning, NULL, PSU_FAN1_WARN);
static SENSOR_DEVICE_ATTR(psu_fan1_duty_cycle_percentage, S_IWUSR | S_IRUGO, for_linear_data, set_fan_duty_cycle, PSU_FAN1_DUTY_CYCLE);
static SENSOR_DEVICE_ATTR(psu_fan1_speed_rpm, S_IRUGO, for_linear_data, NULL, PSU_FAN1_SPEED);
static SENSOR_DEVICE_ATTR(psu_mfr_id, S_IRUGO, for_ascii, NULL, PSU_MFR_ID);
static SENSOR_DEVICE_ATTR(psu_mfr_model, S_IRUGO, for_ascii, NULL, PSU_MFR_MODEL);
static SENSOR_DEVICE_ATTR(psu_mfr_serial, S_IRUGO, for_ascii, NULL, PSU_MFR_SERIAL);
static SENSOR_DEVICE_ATTR(psu_present, S_IRUGO, for_status, NULL, PSU_PRESENT);
static SENSOR_DEVICE_ATTR(psu_power_good, S_IRUGO, for_status, NULL, PSU_P_GOOD);
static struct attribute *cs5435_54p_psu_attributes[] = {
&sensor_dev_attr_psu_v_in.dev_attr.attr,
&sensor_dev_attr_psu_v_out.dev_attr.attr,
&sensor_dev_attr_psu_i_in.dev_attr.attr,
&sensor_dev_attr_psu_i_out.dev_attr.attr,
&sensor_dev_attr_psu_p_in.dev_attr.attr,
&sensor_dev_attr_psu_p_out.dev_attr.attr,
&sensor_dev_attr_psu_temp1_input.dev_attr.attr,
&sensor_dev_attr_psu_temp2_input.dev_attr.attr,
&sensor_dev_attr_psu_temp3_input.dev_attr.attr,
&sensor_dev_attr_psu_temp_fault.dev_attr.attr,
&sensor_dev_attr_psu_temp_warning.dev_attr.attr,
&sensor_dev_attr_psu_fan1_fault.dev_attr.attr,
&sensor_dev_attr_psu_fan1_warning.dev_attr.attr,
&sensor_dev_attr_psu_fan1_duty_cycle_percentage.dev_attr.attr,
&sensor_dev_attr_psu_fan1_speed_rpm.dev_attr.attr,
&sensor_dev_attr_psu_mfr_id.dev_attr.attr,
&sensor_dev_attr_psu_mfr_model.dev_attr.attr,
&sensor_dev_attr_psu_mfr_serial.dev_attr.attr,
&sensor_dev_attr_psu_present.dev_attr.attr,
&sensor_dev_attr_psu_power_good.dev_attr.attr,
NULL
};
static const struct attribute_group cs5435_54p_psu_group = {
.attrs = cs5435_54p_psu_attributes,
};
static int psu_register_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
int status;
struct cs5435_54p_psu_data *data;
if (!psu_i2c_check_functionality(client)) {
status = -EIO;
goto exit;
}
data = kzalloc(sizeof(*data), GFP_KERNEL);
if (!data) {
status = -ENOMEM;
goto exit;
}
i2c_set_clientdata(client, data);
data->valid = 0;
mutex_init(&data->update_lock);
/* Register sysfs hooks */
status = sysfs_create_group(&client->dev.kobj, &cs5435_54p_psu_group);
if (status)
goto exit_sysfs_create_group;
cs5435_54p_sysfs_add_client(client);
data->hwmon_dev = hwmon_device_register(&client->dev);
if (IS_ERR(data->hwmon_dev)) {
status = PTR_ERR(data->hwmon_dev);
goto exit_hwmon_device_register;
}
/* init eeprom */
return 0;
exit_hwmon_device_register:
sysfs_remove_group(&client->dev.kobj, &cs5435_54p_psu_group);
exit_sysfs_create_group:
kfree(data);
exit:
return status;
}
static int cs5435_54p_psu_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
int status;
if((client->addr == 0x52) ||(client->addr == 0x53))
{
status = psu_eeprom_probe(client, id);
}
else if((client->addr == 0x5a) ||(client->addr == 0x5b))
{
status = psu_register_probe(client, id);
}
return status;
}
static int cs5435_54p_psu_remove(struct i2c_client *client)
{
cs5435_54p_sysfs_remove_client(client);
if((client->addr == 0x52) ||(client->addr == 0x53))
{
struct cs5435_54p_psu_data *data;
data = i2c_get_clientdata(client);
psu_sysfs_eeprom_cleanup(&client->dev.kobj,data->bin);
kfree(data);
}
else if((client->addr == 0x5a) ||(client->addr == 0x5b))
{
struct cs5435_54p_psu_data *data;
data = i2c_get_clientdata(client);
hwmon_device_unregister(data->hwmon_dev);
sysfs_remove_group(&client->dev.kobj, &cs5435_54p_psu_group);
kfree(data);
}
return 0;
}
enum psu_index
{
cs5435_54p_psu1,
cs5435_54p_psu2
};
static const struct i2c_device_id cs5435_54p_psu_id[] = {
{ "cs5435_54p_psu1", cs5435_54p_psu1 },
{ "cs5435_54p_psu2", cs5435_54p_psu2 },
{}
};
MODULE_DEVICE_TABLE(i2c, cs5435_54p_psu_id);
static struct i2c_driver cs5435_54p_psu_driver = {
.class = I2C_CLASS_HWMON,
.driver = {
.name = "cs5435_54p_psu",
},
.probe = cs5435_54p_psu_probe,
.remove = cs5435_54p_psu_remove,
.id_table = cs5435_54p_psu_id,
.address_list = normal_i2c,
};
module_i2c_driver(cs5435_54p_psu_driver);
MODULE_AUTHOR("Zhang Peng <zhangpeng@cigtech.com>");
MODULE_DESCRIPTION("cs5435_54p_psu driver");
MODULE_LICENSE("GPL");

View File

@ -0,0 +1,335 @@
/*
* A hwmon driver for the CIG cs5435-54P sysfs Module
*
* Copyright (C) 2018 Cambridge, Inc.
*
* 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.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <linux/module.h>
#include <linux/jiffies.h>
#include <linux/i2c.h>
#include <linux/hwmon.h>
#include <linux/hwmon-sysfs.h>
#include <linux/err.h>
#include <linux/mutex.h>
#include <linux/sysfs.h>
#include <linux/slab.h>
#include <linux/delay.h>
#include <linux/dmi.h>
#include <linux/uaccess.h>
#include <linux/syscalls.h>
#include <linux/kthread.h>
#include <linux/device.h>
#include <linux/platform_device.h>
#include <linux/init.h>
#include <linux/fs.h>
#include <asm/uaccess.h>
#include <asm/device.h>
#include <linux/cdev.h>
#include "i2c-algo-lpc.h"
static LIST_HEAD(sysfs_client_list);
static struct mutex list_lock;
struct sysfs_client_node {
struct i2c_client *client;
struct list_head list;
};
#define DEVICE_NAME "cigfs"
static int dev_major;
static struct class *dev_class;
static struct cdev *dev_cdev;
static struct device *dev_device;
static struct class *psu_class;
static struct class *sfp_class;
void cs5435_54p_sysfs_add_client(struct i2c_client *client)
{
struct sysfs_client_node *node = kzalloc(sizeof(struct sysfs_client_node), GFP_KERNEL);
if (!node) {
dev_dbg(&client->dev, "Can't allocate sysfs_client_node (0x%x)\n", client->addr);
return;
}
node->client = client;
mutex_lock(&list_lock);
list_add(&node->list, &sysfs_client_list);
mutex_unlock(&list_lock);
}
EXPORT_SYMBOL(cs5435_54p_sysfs_add_client);
void cs5435_54p_sysfs_remove_client(struct i2c_client *client)
{
struct list_head *list_node = NULL;
struct sysfs_client_node *sysfs_node = NULL;
int found = 0;
mutex_lock(&list_lock);
list_for_each(list_node, &sysfs_client_list)
{
sysfs_node = list_entry(list_node, struct sysfs_client_node, list);
if (IS_ERR(sysfs_node))
{
break;
}
if (sysfs_node->client == client) {
found = 1;
break;
}
}
if (found) {
list_del(list_node);
kfree(sysfs_node);
}
mutex_unlock(&list_lock);
}
EXPORT_SYMBOL(cs5435_54p_sysfs_remove_client);
struct class * cs5435_54p_sysfs_create_symclass(char *cls_name)
{
int rc = 0;
struct class *my_class;
/**************************************************************************************/
my_class = class_create(THIS_MODULE,cls_name);
if (IS_ERR(my_class)) {
pr_err("failed to create my class\n");
}
return my_class;
/**************************************************************************************/
}
void cs5435_54p_sysfs_delete_symclass(struct class *my_class)
{
/**************************************************************************************/
if (IS_ERR(my_class)) {
pr_err("Pointer is invaild\n");
}
class_destroy(my_class);
/**************************************************************************************/
}
int cs5435_54p_sysfs_create_symlink(struct class *my_class,char * driver_name,char *device_name)
{
struct list_head *list_node = NULL;
struct sysfs_client_node *sysfs_node = NULL;
int ret = -EPERM;
int rc = 0;
mutex_lock(&list_lock);
list_for_each(list_node, &sysfs_client_list)
{
sysfs_node = list_entry(list_node, struct sysfs_client_node, list);
if (!strcmp(sysfs_node->client->name,driver_name)) {
rc = sysfs_create_link(&my_class->p->subsys.kobj, &sysfs_node->client->dev.kobj,device_name);
if(rc)
{
pr_err("failed to create symlink %d\n",rc);
}
break;
}
}
mutex_unlock(&list_lock);
return ret;
}
int cs5435_54p_sysfs_delete_symlink(struct class *my_class,char * driver_name,char *device_name)
{
struct list_head *list_node = NULL;
struct sysfs_client_node *sysfs_node = NULL;
int ret = -EPERM;
int rc = 0;
mutex_lock(&list_lock);
list_for_each(list_node, &sysfs_client_list)
{
sysfs_node = list_entry(list_node, struct sysfs_client_node, list);
if (!strcmp(sysfs_node->client->name,driver_name)) {
sysfs_remove_link(&my_class->p->subsys.kobj,device_name);
break;
}
}
mutex_unlock(&list_lock);
return ret;
}
static int cs5435_54p_sysfs_open(struct inode *inode, struct file *file)
{
return 0;
}
static ssize_t cs5435_54p_sysfs_write(struct file *file, const char __user *buf, size_t count, loff_t * ppos)
{
char str[10],name[18],port[8];
int ret;
int i;
memset(str, 0, sizeof(str));
ret = copy_from_user(str, buf, count);
if (ret)
{
printk(KERN_ERR "copy_from_user fail\n");
return -EINVAL;
}
if(!strncmp(str,"start",5))
{
psu_class = cs5435_54p_sysfs_create_symclass("psu");
cs5435_54p_sysfs_create_symlink(psu_class,"cs5435_54p_psu1","psu1");
cs5435_54p_sysfs_create_symlink(psu_class,"cs5435_54p_psu2","psu2");
sfp_class = cs5435_54p_sysfs_create_symclass("swps");
for(i = 1; i <= 48;i++)
{
memset(name,0xff,sizeof(name));
memset(port,0xff,sizeof(port));
snprintf(name,sizeof(name),"cs5435_54p_sfp%d",i);
snprintf(port,sizeof(port),"port%d",i);
cs5435_54p_sysfs_create_symlink(sfp_class,name,port);
}
}
else if(!strncmp(str,"stop",4))
{
cs5435_54p_sysfs_delete_symlink(psu_class,"cs5435_54p_psu1","psu1");
cs5435_54p_sysfs_delete_symlink(psu_class,"cs5435_54p_psu2","psu2");
cs5435_54p_sysfs_delete_symclass(psu_class);
for(i = 1; i <= 48;i++)
{
memset(name,0xff,sizeof(name));
memset(port,0xff,sizeof(port));
snprintf(name,sizeof(name),"cs5435_54p_sfp%d",i);
snprintf(port,sizeof(port),"port%d",i);
cs5435_54p_sysfs_delete_symlink(sfp_class,name,port);
}
cs5435_54p_sysfs_delete_symclass(sfp_class);
}
return count;
}
static struct file_operations cs5435_54p_sysfs_fops = {
.owner = THIS_MODULE,
.open = cs5435_54p_sysfs_open,
.write = cs5435_54p_sysfs_write,
};
static int __init cs5435_54p_sysfs_init(void)
{
int result = 0;
int err = 0;
dev_t dev = MKDEV(dev_major, 0);
if (dev_major)
result = register_chrdev_region(dev, 1, DEVICE_NAME);
else {
result = alloc_chrdev_region(&dev, 0, 1, DEVICE_NAME);
dev_major = MAJOR(dev);
}
if (result < 0)
{
printk("unable to get major %d\n", dev_major);
err= -EINVAL;
}
printk("get major is %d\n", dev_major);
if (dev_major == 0)
dev_major = result;
dev_cdev= kmalloc(sizeof(struct cdev), GFP_KERNEL);
if(IS_ERR(dev_cdev)) {
err= -ENOMEM;
}
cdev_init(dev_cdev, &cs5435_54p_sysfs_fops);
dev_cdev->owner = THIS_MODULE;
dev_cdev->ops = &cs5435_54p_sysfs_fops;
err = cdev_add(dev_cdev, dev, 1);
if (err)
{
printk("error %d add fpga ", err);
goto err_malloc;
}
dev_class = class_create(THIS_MODULE, DEVICE_NAME);
if (IS_ERR(dev_class))
{
printk("Err:failed in creating class.\n");
goto err_cdev_add;
}
dev_device = device_create(dev_class, NULL, MKDEV(dev_major, 0), NULL, DEVICE_NAME);
if (IS_ERR(dev_device))
{
printk("Err:failed in creating device.\n");
goto err_class_crt;
}
mutex_init(&list_lock);
return err;
err_class_crt:
cdev_del(dev_cdev);
err_cdev_add:
kfree(dev_cdev);
err_malloc:
unregister_chrdev_region(MKDEV(dev_major,0), 1);
return err;
}
static void __exit cs5435_54p_sysfs_exit(void)
{
cdev_del(dev_cdev);
printk("cdev_del ok\n");
device_destroy(dev_class, MKDEV(dev_major, 0));
class_destroy(dev_class);
if(dev_cdev != NULL)
kfree(dev_cdev);
unregister_chrdev_region(MKDEV(dev_major, 0), 1);
printk("cs5435_54p_sysfs_exit...\r\n");
}
MODULE_AUTHOR("Zhang Peng <zhangpeng@cigtech.com>");
MODULE_DESCRIPTION("cs5435-54p-sysfs driver");
MODULE_LICENSE("GPL");
module_init(cs5435_54p_sysfs_init);
module_exit(cs5435_54p_sysfs_exit);

View File

@ -0,0 +1,13 @@
[Unit]
Description=Cig CS5435-54P Platform initialization service
Before=pmon.service
DefaultDependencies=no
[Service]
Type=oneshot
ExecStart=/usr/local/bin/cig_cs5435_util.py install
ExecStop=/usr/local/bin/cig_cs5435_util.py clean
RemainAfterExit=yes
[Install]
WantedBy=multi-user.target

View File

@ -0,0 +1,15 @@
[Unit]
Description=Cig CS5435-54P Platform miscellaneous service
After=cs5435-platform-init.service
DefaultDependencies=no
[Service]
ExecStart=/usr/local/bin/cig_cs5435_misc.py
KillSignal=SIGKILL
SuccessExitStatus=SIGKILL
# Resource Limitations
LimitCORE=infinity
[Install]
WantedBy=multi-user.target

View File

@ -0,0 +1,15 @@
#!/usr/bin/env python
import os
import sys
from setuptools import setup
os.listdir
setup(
name='cs5435-54p',
version='1.0.0',
description='Module to initialize Cig CS5435-54P platforms',
packages=['cs5435-54p'],
package_dir={'cs5435-54p': 'cs5435-54p/classes'},
)

View File

@ -0,0 +1,574 @@
#!/usr/bin/env python
#
# Copyright (C) 2018 Cambridge, Inc.
#
# 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 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
import os
import commands
import sys, getopt
import logging
import re
import time
import datetime
from collections import namedtuple
from threading import Thread
DEBUG = False
i2c_prefix = '/sys/bus/i2c/devices/'
leds_prefix = '/sys/devices/platform/cs5435_54p_led/leds/'
fans_prefix = '/sys/devices/platform/cs5435_54p_fan/'
fansdir_prefix = fans_prefix + 'fan{}_direction'
ageing_controlfile = '/etc/sonic/agcontrol'
AGFlag = 0
platform_misc_log = '/var/log/platform_misc.log'
misclogger = logging.getLogger('platform_misc')
misclogger.setLevel(logging.INFO)
miscformatter = logging.Formatter('%(asctime)s-%(levelname)s-%(message)s')
if not os.path.isfile(platform_misc_log):
try:
os.mknod(platform_misc_log)
except:
print 'Failed to creat platform_misc.log'
fileHandler = logging.FileHandler(platform_misc_log)
fileHandler.setLevel(logging.INFO)
fileHandler.setFormatter(miscformatter)
misclogger.addHandler(fileHandler)
starttime = datetime.datetime.now()
IsGetlswt = 0
coretemp_prefix = '/sys/class/hwmon/hwmon1/'
coretemp_ps = []
psu1_p = '/sys/bus/i2c/devices/5-005a/psu_present'
psu2_p = '/sys/bus/i2c/devices/5-005b/psu_present'
psu1_d = '/sys/bus/i2c/devices/5-0052/psu_eeprom'
psu2_d = '/sys/bus/i2c/devices/5-0053/psu_eeprom'
psu1led_d = leds_prefix + 'cs5435_54p_led::psu1/brightness'
psu2led_d = leds_prefix + 'cs5435_54p_led::psu2/brightness'
cs5435_ledpath = {'fan':leds_prefix + 'cs5435_54p_led::fan/brightness',
'fan1':leds_prefix + 'cs5435_54p_led::fan1/brightness',
'fan2':leds_prefix + 'cs5435_54p_led::fan2/brightness',
'fan3':leds_prefix + 'cs5435_54p_led::fan3/brightness',
'fan4':leds_prefix + 'cs5435_54p_led::fan4/brightness',
'fan5':leds_prefix + 'cs5435_54p_led::fan5/brightness',
'psu1':leds_prefix + 'cs5435_54p_led::psu1/brightness',
'psu2':leds_prefix + 'cs5435_54p_led::psu2/brightness',
'sys':leds_prefix + 'cs5435_54p_led::sys/brightness'}
def system_read_filestr(node):
with open(node, 'r') as f:
try:
str = f.read()
except IOError as e:
misclogger.error('Failed to get node, str={}'.format(node))
return "0"
return str
def system_bright_leds(dev, colour):
global AGFlag
if AGFlag == 1:
return
cmd = 'echo {} > {}'.format(colour, dev)
log_os_system(cmd, 1)
return
'''
1: front in tail out
0: front out tail in
'''
def system_getpsu_direction(dev):
try:
with open(dev) as f:
f.seek(0x30)
str = f.read(2)
except IOError as e:
misclogger.error('Failed to get psu eep')
return 1
if str == 'AA': ## front in tail out
return 1
elif str == 'RA':## tail in front out
return 0
else:
misclogger.error('Failed to get psu eep, str={}'.format(str))
return -1
def system_get_cputype():
cmdretfd = os.popen("lscpu | grep 'Model name'")
retstring = cmdretfd.read()
endindex = retstring.find('@') - 1
startindex = retstring[:endindex].rfind(' ') + 1
cputype = retstring[startindex:endindex]
return cputype
def system_init_coretemppath():
global coretemp_ps
cmdstr = "ls {} | grep 'input'".format(coretemp_prefix)
cmdretfd = os.popen(cmdstr)
coretemppss = cmdretfd.read().splitlines()
if len(coretemppss) < 3:
cputype = system_get_cputype()
misclogger.error('Failed to init core temperature path.'
' cpu type = {}, num thermal = {}'.format(cputype, len(coretemp_ps)))
return 1
for i in range(0,3):
coretemp_ps.append(coretemp_prefix + coretemppss[i])
print coretemp_ps
return 0
class cs5435_fanattr:
def __init__(self, name):
self.name = name
self.direction = 0
self.direction_p = ''
self.rear = 0
self.rear_p = ''
self.front = 0
self.front_p = ''
self.fault = 0
self.fault_p = ''
self.status = 0
self.setpath()
self.updatedevice()
return
def setpath(self):
self.direction_p = fans_prefix + '{}_direction'.format(self.name)
self.rear_p = fans_prefix + '{}_rear_speed_rpm'.format(self.name)
self.front_p = fans_prefix + '{}_front_speed_rpm'.format(self.name)
self.fault_p = fans_prefix + '{}_fault'.format(self.name)
return
def updatedevice(self):
self.direction = int(system_read_filestr(self.direction_p))
self.rear = int(system_read_filestr(self.rear_p))
self.front = int(system_read_filestr(self.front_p))
self.fault = int(system_read_filestr(self.fault_p))
return
def checkspeedrpm(self, speedrpm):
frontrpmexp = speedrpm * 21000 / 100
rearrpmexp = speedrpm * 19000 / 100
deviationfront = abs(frontrpmexp - self.front) / float(frontrpmexp)
deviationrear = abs(rearrpmexp - self.rear) / float(rearrpmexp)
if deviationfront < 0.3 and deviationrear < 0.3:
return 0
else:
misclogger.error(':{} speed wrong. frontexp is {}, but rpm is {}.rearexp is {}, but rpm is {}'.format(self.name, frontrpmexp, self.front, rearrpmexp, self.rear))
return 1
def checkstatus(self, speedrpm, totaldirct):
speedstatus = self.checkspeedrpm(speedrpm)
if self.direction != totaldirct:
self.status = 1
misclogger.error(':{} direction = {}.fan direction is not ok.'.format(self.name, self.direction))
elif speedstatus != 0:
self.status = 1
elif self.fault != 0:
misclogger.error(':{} fault.'.format(self.name))
self.status = 1
else:
self.status = 0
if self.status == 1:
system_bright_leds(cs5435_ledpath[self.name], 3)
else:
system_bright_leds(cs5435_ledpath[self.name], 1)
return self.status
cs5435_fanattrnodes = []
class cs5435_psuattr:
def __init__(self, name):
self.name = name
self.direction = 0
self.direction_p = ''
self.present = 0
self.present_p = ''
self.status = 0
self.setpath()
self.updatepresent()
self.updatedirection()
return
def setpath(self):
if self.name == 'psu1':
self.present_p = psu1_p
self.direction_p = psu1_d
if self.name == 'psu2':
self.present_p = psu2_p
self.direction_p = psu2_d
return
def updatepresent(self):
self.present = int(system_read_filestr(self.present_p))
return
def updatedirection(self):
if self.present == 1:
self.direction = system_getpsu_direction(self.direction_p)
else:
self.direction = 2
return
def checkstatus(self, totaldirct):
if self.present != 1:
self.status = 1
misclogger.error(':{} not present.'.format(self.name))
elif self.direction == 2:
self.status = 0
misclogger.info(':{} direction need to be update.'.format(self.name))
elif self.direction != totaldirct:
self.status = 1
misclogger.info(':{} direction is wrong.'.format(self.name))
else:
self.status = 0
if self.status == 1:
system_bright_leds(cs5435_ledpath[self.name], 3)
else:
system_bright_leds(cs5435_ledpath[self.name], 1)
return self.status
cs5435_psuattrnodes = []
def my_log(txt):
if DEBUG == True:
print "[ROY]"+txt
return
def device_exist():
ret1, log = log_os_system("ls "+i2c_prefix+"5-005a", 0)
ret2, log = log_os_system("ls "+i2c_prefix+"5-005b", 0)
ret3, log = log_os_system("ls "+leds_prefix+"cs5435_54p_led*", 0)
return not(ret1 or ret2 or ret3)
def log_os_system(cmd, show):
logging.info('Run :'+cmd)
status, output = commands.getstatusoutput(cmd)
my_log (cmd +"with result:" + str(status))
my_log (" output:"+output)
if status:
logging.info('Failed :'+cmd)
if show:
print('Failed :'+cmd)
return status, output
def system_get_coretemp():
temp1 = system_read_filestr(coretemp_ps[0]).strip()
temp2 = system_read_filestr(coretemp_ps[1]).strip()
temp3 = system_read_filestr(coretemp_ps[2]).strip()
return int(temp1), int(temp2), int(temp3)
def system_get_boardtemp():
for i in range(0,16):
temp1path = "/sys/bus/i2c/devices/5-004a/hwmon/hwmon%d/temp1_input" % i
if os.access(temp1path, os.F_OK):
break
for i in range(0,16):
temp2path = "/sys/bus/i2c/devices/5-004b/hwmon/hwmon%d/temp1_input" % i
if os.access(temp2path, os.F_OK):
break
temp1 = system_read_filestr(temp1path).strip()
temp2 = system_read_filestr(temp2path).strip()
return int(temp1), int(temp2)
def system_get_lswtemp():
global IsGetlswt
global starttime
if IsGetlswt == 0:
now = datetime.datetime.now()
misclogger.info("time wait.")
misclogger.info("start = {}, now = {}.".format(starttime, now))
if (now - starttime).seconds > 150:
misclogger.info("time = ".format((now - starttime).seconds))
IsGetlswt = 1
return 25
# chp = subprocess.Popen("docker ps --filter name=syncd", shell=True, stdout=subprocess.PIPE)
# if chp.poll() == None:
# misclogger.info("No subp.")
# chp.kill()
#
# return 25
# retstring = chp.stdout.read()
# chp.kill()
# if 'Up' not in retstring:
# misclogger.info("lsw not up.")
#
# return 25
status, output = log_os_system('npx_diag swc show temperature', 1)
if status:
misclogger.error('failed to show lsw temperature')
return 25
output = output.strip()
if output.find("it 0, temperature ") > 0:
startindex = output.find('temperature') + len('temperature') + 1
endindex = output[startindex:].find(" ")
endindex = startindex + endindex
temp = output[startindex:endindex]
b = temp.find('.')
if b > 0:
temp=temp[:b]
temp = int(temp)
else:
misclogger.error("Failed to get temperature.")
temp = 0
return int(temp)
def system_monitor_temperature():
ctemp1, ctemp2, ctemp3 = system_get_coretemp()
btemp1, btemp2 = system_get_boardtemp()
ltemp = system_get_lswtemp()
fan_speed_str = system_cs5435_getfanexspeed()
fan_speed = int(fan_speed_str)
policy = 'stay'
pos = 0
#speed c1 c2 c3 b1 b2 lsw
fan_policy_up = ([30, 40000, 40000, 40000, 42000, 35000, 95],
[40, 44000, 44000, 44000, 44000, 39000, 96],
[50, 49000, 49000, 49000, 47000, 44000, 91],
[60, 52000, 52000, 52000, 51500, 47500, 92],
[70, 53000, 53000, 53000, 52000, 49000, 93],
[100,999999,999999,999999,999999,999999,999])
fan_policy_down=([30, 0, 0, 0, 0, 0, 0],
[40, 34000, 34000, 34000, 34000, 30000, 80],
[50, 38000, 38000, 38000, 37000, 33000, 81],
[60, 44000, 44000, 44000, 43000, 39000, 84],
[70, 44000, 44000, 44000, 43000, 40000, 84],
[100, 48000, 48000, 48000, 46000, 42000, 85],)
for policytable in fan_policy_up:
if fan_speed <= policytable[0]:
break
pos = pos + 1
fan_speed = policytable[0]
if (ctemp1 < policytable[1]) and (ctemp2 < policytable[2]) and (ctemp3 < policytable[3]) and (btemp1 < policytable[4]) and (btemp2 < policytable[5]) and (ltemp < policytable[6]):
policy = 'stay'
policytable = fan_policy_down[pos]
if (ctemp1 < policytable[1]) and (ctemp2 < policytable[2]) and (ctemp3 < policytable[3]) and (btemp1 < policytable[4]) and (btemp2 < policytable[5]) and (ltemp < policytable[6]):
policy = 'down'
else:
policy = 'up'
if policy == 'up':
misclogger.info("speed = %d." % fan_speed)
misclogger.info("core1 = %d, core2 = %d, core3 = %d." % (ctemp1, ctemp2, ctemp3))
misclogger.info("board1 = %d, board2 = %d." % (btemp1, btemp2))
misclogger.info("lsw = %d" % ltemp)
fan_speed = fan_policy_down[pos + 1][0]
misclogger.info("fan policy: up. speedexp = {}".format(fan_speed))
if policy == 'stay':
fan_speed = fan_policy_down[pos]
return
if policy == 'down':
misclogger.info("speed = %d." % fan_speed)
misclogger.info("core1 = %d, core2 = %d, core3 = %d." % (ctemp1, ctemp2, ctemp3))
misclogger.info("board1 = %d, board2 = %d." % (btemp1, btemp2))
misclogger.info("lsw = %d" % ltemp)
fan_speed = fan_policy_down[pos - 1][0]
misclogger.info("fan policy: down.speedexp = {}".format(fan_speed))
cmd = "echo %d > /sys/devices/platform/cs5435_54p_fan/fan_duty_cycle_percentage" % fan_speed
status, output = log_os_system(cmd, 1)
if status:
misclogger.error("set fan speed fault")
return
def system_cs5435_setfanexspeed(num):
fanspeednode = fans_prefix + 'fan_duty_cycle_percentage'
numstr = str(num)
with open(fanspeednode, 'w') as f:
f.write(numstr)
def system_cs5435_getfanexspeed():
fanspeednode = fans_prefix + 'fan_duty_cycle_percentage'
fanspeedstr = system_read_filestr(fanspeednode)
fanspeedexp = int(fanspeedstr)
return fanspeedexp
def system_cs5435_getdirection():
global cs5435_fanattrnodes
direction = 0
for fan in cs5435_fanattrnodes:
direction = direction + fan.direction
if direction > 2:
direction = 1
else:
direction = 0
return direction
def system_check_psusdirection():
global cs5435_psuattrnodes
cs5435totaldirct = system_cs5435_getdirection()
psutatus = 0
for psu in cs5435_psuattrnodes:
psu.updatedirection()
psu.checkstatus(cs5435totaldirct)
psutatus = psu.status + psutatus
return (psutatus != 0)
def system_check_psuspresent():
global cs5435_psuattrnodes
cs5435totaldirct = system_cs5435_getdirection()
psutatus = 0
for psu in cs5435_psuattrnodes:
psu.updatepresent()
psu.checkstatus(cs5435totaldirct)
psutatus = psu.status + psutatus
return (psutatus != 0)
def system_check_fansstate():
global cs5435_fanattrnodes
global cs5435_ledpath
cs5435totaldirct = system_cs5435_getdirection()
fanstatus = 0
fanexspeed = 0
fanexspeed = system_cs5435_getfanexspeed()
for fan in cs5435_fanattrnodes:
fan.updatedevice()
fan.checkstatus(fanexspeed, cs5435totaldirct)
fanstatus = fanstatus + fan.status
if fanstatus > 0:
misclogger.error(':fan error.set fans speed 100.')
system_cs5435_setfanexspeed(100)
system_bright_leds(cs5435_ledpath['fan'], 3)
else:
system_bright_leds(cs5435_ledpath['fan'], 1)
return (fanstatus != 0)
def system_misc_polling(threadName,delay):
for count in range(1,5):
if device_exist() == False:
time.sleep(delay+3)
print "%s: %s, count=%d" % ( threadName, time.ctime(time.time()), count)
else:
break
if count == 4:
return
status, output = log_os_system("echo 1 > /sys/devices/platform/cs5435_54p_led/leds/cs5435_54p_led::sys/brightness", 1)
status, output = log_os_system("hwconfig -cfp 1", 1)
global AGFlag
if os.access(ageing_controlfile, os.F_OK):
AGFlag = 1
else:
AGFlag = 0
os.system('csw_daemon &')
global cs5435_fanattrnodes
global cs5435_psuattrnodes
for num in range(1,6):
name = 'fan{}'.format(num)
fannode = cs5435_fanattr(name)
cs5435_fanattrnodes.append(fannode)
for num in range(1,3):
name = 'psu{}'.format(num)
psunode = cs5435_psuattr(name)
cs5435_psuattrnodes.append(psunode)
tempcontrol = system_init_coretemppath()
misclogger.info("%s: %s misc start." % ( threadName, time.ctime(time.time())))
count = 0
while 1:
count = count + 1
ret = system_check_psuspresent()
ret = system_check_fansstate()
if count % 10 == 0:
misclogger.info(": adjust fans and check psu direction.")
system_check_psusdirection()
if tempcontrol == 0:
system_monitor_temperature()
count = 0
time.sleep(delay)
return
if __name__ == '__main__':
target=system_misc_polling("Thread-misc",10)

View File

@ -0,0 +1,563 @@
#!/usr/bin/env python
#
# Copyright (C) 2018 Cambridge, Inc.
#
# 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 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
"""
Usage: %(scriptName)s [options] command object
options:
-h | --help : this help message
-d | --debug : run with debug mode
-f | --force : ignore error during installation or clean
command:
install : install drivers and generate related sysfs nodes
clean : uninstall drivers and remove related sysfs nodes
show : show all systen status
sff : dump SFP eeprom
set : change board setting with fan|led|sfp
"""
import os
import commands
import sys, getopt
import logging
import re
import time
from collections import namedtuple
PROJECT_NAME = 'cs5435_54p'
version = '0.1.1'
verbose = False
DEBUG = False
args = []
ALL_DEVICE = {}
DEVICE_NO = {'led':9, 'fan':5, 'thermal':4, 'psu':2, 'sfp':54}
FORCE = 0
CPU_TYPE = 'C3308'
if DEBUG == True:
print sys.argv[0]
print 'ARGV :', sys.argv[1:]
def main():
global DEBUG
global args
global FORCE
if len(sys.argv)<2:
show_help()
options, args = getopt.getopt(sys.argv[1:], 'hdf', ['help',
'debug',
'force',
])
if DEBUG == True:
print options
print args
print len(sys.argv)
for opt, arg in options:
if opt in ('-h', '--help'):
show_help()
elif opt in ('-d', '--debug'):
DEBUG = True
logging.basicConfig(level=logging.INFO)
elif opt in ('-f', '--force'):
FORCE = 1
else:
logging.info('no option')
for arg in args:
if arg == 'install':
do_install()
elif arg == 'clean':
do_uninstall()
elif arg == 'show':
device_traversal()
elif arg == 'sff':
if len(args)!=2:
show_eeprom_help()
elif int(args[1]) ==0 or int(args[1]) > DEVICE_NO['sfp']:
show_eeprom_help()
else:
show_eeprom(args[1])
return
elif arg == 'set':
if len(args)<3:
show_set_help()
else:
set_device(args[1:])
return
else:
show_help()
return 0
def show_help():
print __doc__ % {'scriptName' : sys.argv[0].split("/")[-1]}
sys.exit(0)
def show_set_help():
cmd = sys.argv[0].split("/")[-1]+ " " + args[0]
print cmd +" [led|sfp|fan]"
print " use \""+ cmd + " led 0-4 \" to set led color"
print " use \""+ cmd + " fan 0-100\" to set fan duty percetage"
print " use \""+ cmd + " sfp 1-54 {0|1}\" to set sfp# tx_disable"
sys.exit(0)
def show_eeprom_help():
cmd = sys.argv[0].split("/")[-1]+ " " + args[0]
print " use \""+ cmd + " 1-54 \" to dump sfp# eeprom"
sys.exit(0)
def my_log(txt):
if DEBUG == True:
print "[ROY]"+txt
return
def log_os_system(cmd, show):
logging.info('Run :'+cmd)
status, output = commands.getstatusoutput(cmd)
my_log (cmd +"with result:" + str(status))
my_log (" output:"+output)
if status:
logging.info('Failed :'+cmd)
if show:
print('Failed :'+cmd)
return status, output
def driver_check():
for count in range(1,5):
time.sleep(1)
ret, lsmod = log_os_system("lsmod| grep i2c_i801", 0)
if len(lsmod) > 2:
log_os_system("rmmod i2c_i801", 0)
break
ret, lsmod = log_os_system("lsmod| grep i2c_designware_platform", 0)
if len(lsmod) > 2:
log_os_system("rmmod i2c_designware_platform", 0)
log_os_system("modprobe i2c-designware-platform", 0)
ret, lsmod = log_os_system("lsmod| grep cig", 0)
logging.info('mods:'+lsmod)
if len(lsmod) ==0:
return False
return True
kos = [
'depmod',
'modprobe i2c_dev',
'modprobe i2c_mux_pca954x force_deselect_on_exit=1',
'modprobe x86-64-cig-cs5435-54p-sysfs ' ,
'modprobe x86-64-cig-cs5435-54p-cpld ' ,
'modprobe x86-64-cig-cs5435-54p-fan' ,
'modprobe x86-64-cig-cs5435-54p-psu' ,
'modprobe x86-64-cig-cs5435-54p-sfp' ,
'modprobe x86-64-cig-cs5435-54p-led' ]
def driver_install():
global FORCE
for i in range(0,len(kos)):
if i == 4:
ret, CPU_TYPE = log_os_system("cat /proc/cpuinfo | grep \"model name\" | cut -b 32-39 | head -n 1", 0)
if CPU_TYPE=='i3-6100U':
kos[i] =kos[i] + 'board_id=1'
ret, CPU_TYPE = log_os_system("cat /proc/cpuinfo | grep \"model name\" | cut -b 36-40 | head -n 1", 0)
if CPU_TYPE=='C3758' or CPU_TYPE=='C3308':
kos[i] =kos[i] + 'board_id=2'
status, output = log_os_system(kos[i], 1)
if status:
if FORCE == 0:
return status
return 0
def driver_uninstall():
global FORCE
for i in range(0,len(kos)):
rm = kos[-(i+1)].replace("modprobe", "modprobe -rq")
rm = rm.replace("insmod", "rmmod")
status, output = log_os_system(rm, 1)
if status:
if FORCE == 0:
return status
return 0
led_prefix ='/sys/class/leds/'+PROJECT_NAME+'_led::'
hwmon_types = {'led': ['sys','fan','fan1','fan2','fan3','fan4','fan5','psu1','psu2']}
hwmon_nodes = {'led': ['brightness'] }
hwmon_prefix ={'led': led_prefix}
i2c_prefix = '/sys/bus/i2c/devices/'
i2c_bus = {'thermal': ['4-0048','4-0049', '5-004a', '5-004b'] ,
'psu': ['5-005a','5-005b'],
'sfp': ['-0050']}
i2c_nodes = {'thermal': ['hwmon/hwmon*/temp1_input'] ,
'psu': ['psu_present ', 'psu_power_good'] ,
'sfp': ['sfp_is_present ', 'sfp_tx_disable']}
fan_prefix ='/sys/bus/platform/devices/'+PROJECT_NAME+'_fan'
fan_types = {'fan': ['fan1','fan2', 'fan3', 'fan4', 'fan5']}
fan_nodes = {'fan': ['state', 'front_speed_rpm', 'rear_speed_rpm', 'fault']}
sfp_map = [8,9,10,11,12,13,14,15,16,
17,18,19,20,21,22,23,24,25,26,
27,28,29,30,31,32,33,34,35,36,
37,38,39,40,41,42,43,44,45,46,
47,48,49,50,51,52,53,54,55,56,
57,60,61,62,63]
mknod =[
'echo pca9548 0x71 > /sys/bus/i2c/devices/i2c-2/new_device',
'echo pca9548 0x72 > /sys/bus/i2c/devices/i2c-2/new_device',
'echo pca9548 0x73 > /sys/bus/i2c/devices/i2c-2/new_device',
'echo pca9548 0x74 > /sys/bus/i2c/devices/i2c-2/new_device',
'echo pca9548 0x75 > /sys/bus/i2c/devices/i2c-3/new_device',
'echo pca9548 0x76 > /sys/bus/i2c/devices/i2c-3/new_device',
'echo pca9548 0x77 > /sys/bus/i2c/devices/i2c-3/new_device',
'echo lm75 0x48 > /sys/bus/i2c/devices/i2c-4/new_device',
'echo lm75 0x49 > /sys/bus/i2c/devices/i2c-4/new_device',
'echo lm75 0x4a > /sys/bus/i2c/devices/i2c-5/new_device',
'echo lm75 0x4b > /sys/bus/i2c/devices/i2c-5/new_device',
'echo cs5435_54p_psu1 0x5a > /sys/bus/i2c/devices/i2c-5/new_device',
'echo cs5435_54p_psu2 0x5b > /sys/bus/i2c/devices/i2c-5/new_device',
'echo cs5435_54p_psu1 0x52 > /sys/bus/i2c/devices/i2c-5/new_device',
'echo cs5435_54p_psu2 0x53 > /sys/bus/i2c/devices/i2c-5/new_device',
'echo 24c128 0x57 > /sys/bus/i2c/devices/i2c-7/new_device']
port = 0
def device_install():
global FORCE
global port
for i in range(0,len(mknod)):
#all nodes need times to built new i2c buses
time.sleep(1)
status, output = log_os_system(mknod[i], 1)
if status:
print output
if FORCE == 0:
return status
for i in range(0,len(sfp_map)):
if (i == 50):
port = port + 3
else:
port = port + 1
status, output =log_os_system("echo cs5435_54p_sfp"+str(port)+" 0x50 > /sys/bus/i2c/devices/i2c-"+str(sfp_map[i])+"/new_device", 1)
if status:
print output
if FORCE == 0:
return status
if port <= 48:
status, output =log_os_system("echo cs5435_54p_sfp"+str(port)+" 0x51 > /sys/bus/i2c/devices/i2c-"+str(sfp_map[i])+"/new_device", 1)
if status:
print output
if FORCE == 0:
return status
return
def device_uninstall():
global FORCE
for i in range(0,len(sfp_map)):
target = "/sys/bus/i2c/devices/i2c-"+str(sfp_map[i])+"/delete_device"
status, output =log_os_system("echo 0x50 > "+ target, 1)
if status:
print output
if FORCE == 0:
return status
nodelist = mknod
for i in range(len(nodelist)):
target = nodelist[-(i+1)]
temp = target.split()
del temp[1]
temp[-1] = temp[-1].replace('new_device', 'delete_device')
status, output = log_os_system(" ".join(temp), 1)
if status:
print output
if FORCE == 0:
return status
return
def system_ready():
if driver_check() == False:
return False
if not device_exist():
return False
return True
def do_install():
print "Checking system...."
if driver_check() == False:
print "No driver, installing...."
status = driver_install()
if status:
if FORCE == 0:
return status
else:
print PROJECT_NAME.upper()+" drivers detected...."
if not device_exist():
print "No device, installing...."
status = device_install()
if status:
if FORCE == 0:
return status
else:
print PROJECT_NAME.upper()+" devices detected...."
return
def do_uninstall():
print "Checking system...."
if not device_exist():
print PROJECT_NAME.upper() +" has no device installed...."
else:
print "Removing device...."
status = device_uninstall()
if status:
if FORCE == 0:
return status
if driver_check()== False :
print PROJECT_NAME.upper() +" has no driver installed...."
else:
print "Removing installed driver...."
status = driver_uninstall()
if status:
if FORCE == 0:
return status
return
def devices_info():
global DEVICE_NO
global ALL_DEVICE
global i2c_bus, hwmon_types, fan_types
for key in DEVICE_NO:
ALL_DEVICE[key]= {}
for i in range(0,DEVICE_NO[key]):
ALL_DEVICE[key][key+str(i+1)] = []
for key in i2c_bus:
buses = i2c_bus[key]
nodes = i2c_nodes[key]
for i in range(0,len(buses)):
for j in range(0,len(nodes)):
if 'sfp' == key:
for k in range(0,DEVICE_NO[key]):
node = key+str(k+1)
path = i2c_prefix+ str(sfp_map[k])+ buses[i]+"/"+ nodes[j]
my_log(node+": "+ path)
ALL_DEVICE[key][node].append(path)
else:
node = key+str(i+1)
path = i2c_prefix+ buses[i]+"/"+ nodes[j]
my_log(node+": "+ path)
ALL_DEVICE[key][node].append(path)
for key in hwmon_types:
itypes = hwmon_types[key]
nodes = hwmon_nodes[key]
for i in range(0,len(itypes)):
for j in range(0,len(nodes)):
node = key+"_"+itypes[i]
path = hwmon_prefix[key]+ itypes[i]+"/"+ nodes[j]
my_log(node+": "+ path)
ALL_DEVICE[key][ key+str(i+1)].append(path)
for key in fan_types:
itypes = fan_types[key]
nodes = fan_nodes[key]
for i in range(0,len(itypes)):
for j in range(0,len(nodes)):
node = key+"_"+itypes[i]
path = fan_prefix+"/"+ itypes[i]+"_"+ nodes[j]
my_log(node+": "+ path)
ALL_DEVICE[key][ key+str(i+1)].append(path)
#show dict all in the order
if DEBUG == True:
for i in sorted(ALL_DEVICE.keys()):
print(i+": ")
for j in sorted(ALL_DEVICE[i].keys()):
print(" "+j)
for k in (ALL_DEVICE[i][j]):
print(" "+" "+k)
return
def show_eeprom(index):
if system_ready()==False:
print("System's not ready.")
print("Please install first!")
return
if len(ALL_DEVICE)==0:
devices_info()
node = ALL_DEVICE['sfp'] ['sfp'+str(index)][0]
node = node.replace(node.split("/")[-1], 'sfp_eeprom')
# check if got hexdump command in current environment
ret, log = log_os_system("which hexdump", 0)
ret, log2 = log_os_system("which busybox hexdump", 0)
if len(log):
hex_cmd = 'hexdump'
elif len(log2):
hex_cmd = ' busybox hexdump'
else:
log = 'Failed : no hexdump cmd!!'
logging.info(log)
print log
return 1
print node + ":"
ret, log = log_os_system("cat "+node+"| "+hex_cmd+" -C", 1)
if ret==0:
print log
else:
print "**********device no found**********"
return
def set_device(args):
global DEVICE_NO
global ALL_DEVICE
if system_ready()==False:
print("System's not ready.")
print("Please install first!")
return
if len(ALL_DEVICE)==0:
devices_info()
if args[0]=='led':
if int(args[1])>4:
show_set_help()
return
#print ALL_DEVICE['led']
for i in range(0,len(ALL_DEVICE['led'])):
for k in (ALL_DEVICE['led']['led'+str(i+1)]):
ret, log = log_os_system("echo "+args[1]+" >"+k, 1)
if ret:
return ret
elif args[0]=='fan':
if int(args[1])>100:
show_set_help()
return
#print ALL_DEVICE['fan']
#fan1~6 is all fine, all fan share same setting
node = ALL_DEVICE['fan'] ['fan1'][0]
node = node.replace(node.split("/")[-1], 'fan_duty_cycle_percentage')
ret, log = log_os_system("cat "+ node, 1)
if ret==0:
print ("Previous fan duty: " + log.strip() +"%")
ret, log = log_os_system("echo "+args[1]+" >"+node, 1)
if ret==0:
print ("Current fan duty: " + args[1] +"%")
return ret
elif args[0]=='sfp':
if int(args[1])> DEVICE_NO[args[0]] or int(args[1])==0:
show_set_help()
return
if len(args)<2:
show_set_help()
return
if int(args[2])>1:
show_set_help()
return
#print ALL_DEVICE[args[0]]
for i in range(0,len(ALL_DEVICE[args[0]])):
for j in ALL_DEVICE[args[0]][args[0]+str(args[1])]:
if j.find('tx_disable')!= -1:
ret, log = log_os_system("echo "+args[2]+" >"+ j, 1)
if ret:
return ret
return
def get_value(input):
digit = re.findall('\d+', input)
return int(digit[0])
def get_ledname(ledx):
name_table={'led1':'SYS','led2':'FSTUS','led3':'FAN1','led4':'FAN2','led5':'FAN3','led6':'FAN4','led7':'FAN5','led8':'PSU1','led9':'PSU2'}
if name_table.has_key(ledx):
name = name_table[ledx]
else:
name = ledx
return name
def device_traversal():
if system_ready()==False:
print("System's not ready.")
print("Please install first!")
return
if len(ALL_DEVICE)==0:
devices_info()
for i in sorted(ALL_DEVICE.keys()):
print("============================================")
print(i.upper()+": ")
print("============================================")
for j in sorted(ALL_DEVICE[i].keys(), key=get_value):
nwnamex = get_ledname(j)
if nwnamex == j:
print " "+j+":",
else:
print " "+nwnamex+":",
for k in (ALL_DEVICE[i][j]):
ret, log = log_os_system("cat "+k, 0)
func = k.split("/")[-1].strip()
func = re.sub(j+'_','',func,1)
func = re.sub(i.lower()+'_','',func,1)
if ret==0:
print func+"="+log+" ",
else:
print func+"="+"X"+" ",
print
print("----------------------------------------------------------------")
print
return
def device_exist():
ret1, log = log_os_system("ls "+i2c_prefix+"*0077", 0)
ret2, log = log_os_system("ls "+i2c_prefix+"i2c-3", 0)
return not(ret1 or ret2)
if __name__ == "__main__":
main()

View File

@ -0,0 +1,6 @@
obj-m :=x86-64-cig-cs6436-54p-sysfs.o \
x86-64-cig-cs6436-54p-cpld.o \
x86-64-cig-cs6436-54p-fan.o \
x86-64-cig-cs6436-54p-led.o \
x86-64-cig-cs6436-54p-psu.o \
x86-64-cig-cs6436-54p-sfp.o

View File

@ -0,0 +1,222 @@
/* --------------------------------------------------------------------
* A hwmon driver for the CIG cs6436-54P
*
* Copyright (C) 2018 Cambridge, Inc.
*
* 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.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/* -------------------------------------------------------------------- */
#ifndef I2C_LPC_H
#define I2C_LPC_H 1
/* ----- Control register bits ---------------------------------------- */
#define I2C_LPC_PIN 0x80
#define I2C_LPC_ESO 0x40
#define I2C_LPC_ES1 0x20
#define I2C_LPC_ES2 0x10
#define I2C_LPC_ENI 0x08
#define I2C_LPC_STO 0x40
#define I2C_LPC_ACK 0x01
/*command register*/
#define I2C_LPC_STA 0x80
#define I2C_LPC_ABT 0x40
/*status register*/
#define I2C_LPC_TBE 0x02
#define I2C_LPC_IBB 0x80
#define I2C_LPC_RBF 0x01
#define I2C_LPC_TD 0x08
#define I2C_LPC_START I2C_LPC_STA
#define I2C_LPC_STOP I2C_LPC_STO
#define I2C_LPC_REPSTART I2C_LPC_STA
#define I2C_LPC_IDLE
/* ----- Status register bits ----------------------------------------- */
/*#define I2C_LPC_PIN 0x80 as above*/
#define I2C_LPC_INI 0x40 /* 1 if not initialized */
#define I2C_LPC_STS 0x20
#define I2C_LPC_BER 0x10
#define I2C_LPC_AD0 0x08
#define I2C_LPC_LRB 0x08
#define I2C_LPC_AAS 0x04
#define I2C_LPC_LAB 0x02
#define I2C_LPC_BB 0x80
/* ----- Chip clock frequencies --------------------------------------- */
#define I2C_LPC_CLK3 0x00
#define I2C_LPC_CLK443 0x10
#define I2C_LPC_CLK6 0x14
#define I2C_LPC_CLK 0x18
#define I2C_LPC_CLK12 0x1c
/* ----- transmission frequencies ------------------------------------- */
#define I2C_LPC_TRNS90 0x00 /* 90 kHz */
#define I2C_LPC_TRNS45 0x01 /* 45 kHz */
#define I2C_LPC_TRNS11 0x02 /* 11 kHz */
#define I2C_LPC_TRNS15 0x03 /* 1.5 kHz */
#define I2C_LPC_OWNADR 0
#define I2C_LPC_INTREG I2C_LPC_ES2
#define I2C_LPC_CLKREG I2C_LPC_ES1
#define I2C_LPC_REG_TEST 0x01
#define I2C_LPC_REG_BUS_SEL 0x80
#define I2C_LPC_REG_DEVICE_ADDR 0x81
#define I2C_LPC_REG_BYTE_COUNT 0x83
#define I2C_LPC_REG_COMMAND 0x84
#define I2C_LPC_REG_STATUS 0x85
#define I2C_LPC_REG_DATA_RX1 0x86
#define I2C_LPC_REG_DATA_RX2 0x87
#define I2C_LPC_REG_DATA_RX3 0x88
#define I2C_LPC_REG_DATA_RX4 0x89
#define I2C_LPC_REG_DATA_TX1 0x8a
#define I2C_LPC_REG_DATA_TX2 0x8b
#define I2C_LPC_REG_DATA_TX3 0x8c
#define I2C_LPC_REG_DATA_TX4 0x8d
#define ADDR_REG_SFP_STATUS_ADDR 0X62 //reg addr +R/W# //1031
#define ADDR_REG_SFP_STATUS_TX 0X63 // write data
#define ADDR_REG_SFP_STATUS_RX 0X64 //read data
#define ADDR_REG_SFP_STATUS_COMMAND 0X65 //cmd bit7=1,go
#define ADDR_REG_SFP_STATUS_STATUS 0X66 //status
#define CPLD_MASTER_INTERRUPT_STATUS_REG 0x20
#define CPLD_MASTER_INTERRUPT_MASK_REG 0x21
#define CPLD_MASTER_INTERRUPT_ALL 0x3f
#define CPLD_MASTER_INTERRUPT_CPLD2 0x20
#define CPLD_MASTER_INTERRUPT_CPLD1 0x10
#define CPLD_MASTER_INTERRUPT_PSU2 0x08
#define CPLD_MASTER_INTERRUPT_PSU1 0x04
#define CPLD_MASTER_INTERRUPT_6320 0x02
#define CPLD_MASTER_INTERRUPT_LSW 0x01
#define CPLD_SLAVE1_INTERRUPT_STATUS_L_REG 0x20
#define CPLD_SLAVE1_INTERRUPT_STATUS_H_REG 0x21
#define CPLD_SLAVE2_INTERRUPT_STATUS_L_REG 0x22
#define CPLD_SLAVE2_INTERRUPT_STATUS_H_REG 0x23
#define CPLD_SLAVE1_INTERRUPT_MASK_REG 0x24
#define CPLD_SLAVE2_INTERRUPT_MASK_REG 0x25
#define CPLD_SLAVE1_PRESENT08_REG 0x01
#define CPLD_SLAVE1_PRESENT16_REG 0x02
#define CPLD_SLAVE1_PRESENT24_REG 0x03
#define CPLD_SLAVE2_PRESENT32_REG 0x04
#define CPLD_SLAVE2_PRESENT40_REG 0x05
#define CPLD_SLAVE2_PRESENT48_REG 0x06
#define CPLD_SLAVE1_RX_LOST08_REG 0x07
#define CPLD_SLAVE1_RX_LOST16_REG 0x08
#define CPLD_SLAVE1_RX_LOST24_REG 0x09
#define CPLD_SLAVE2_RX_LOST32_REG 0x0a
#define CPLD_SLAVE2_RX_LOST40_REG 0x0b
#define CPLD_SLAVE2_RX_LOST48_REG 0x0c
#define CPLD_SLAVE1_TX_FAULT08_REG 0x0d
#define CPLD_SLAVE1_TX_FAULT16_REG 0x0e
#define CPLD_SLAVE1_TX_FAULT24_REG 0x0f
#define CPLD_SLAVE2_TX_FAULT32_REG 0x10
#define CPLD_SLAVE2_TX_FAULT40_REG 0x11
#define CPLD_SLAVE2_TX_FAULT48_REG 0x12
#define CPLD_SLAVE2_PRESENT56_REG 0x19
#define CPLD_SLAVE2_QSFP_CR56_REG 0x1a
#define CPLD_SLAVE1_INTERRUPT_PRESENT08 0x0001
#define CPLD_SLAVE1_INTERRUPT_PRESENT16 0x0002
#define CPLD_SLAVE1_INTERRUPT_PRESENT24 0x0004
#define CPLD_SLAVE2_INTERRUPT_PRESENT32 0x0001
#define CPLD_SLAVE2_INTERRUPT_PRESENT40 0x0002
#define CPLD_SLAVE2_INTERRUPT_PRESENT48 0x0004
#define CPLD_SLAVE2_INTERRUPT_QSFP_CR56 0x0200
#define CPLD_SLAVE2_INTERRUPT_PRESENT56 0x0400
#define CPLD_SLAVE1_INTERRUPT_RX_LOST08 0x0008
#define CPLD_SLAVE1_INTERRUPT_RX_LOST16 0x0010
#define CPLD_SLAVE1_INTERRUPT_RX_LOST24 0x0020
#define CPLD_SLAVE2_INTERRUPT_RX_LOST32 0x0008
#define CPLD_SLAVE2_INTERRUPT_RX_LOST40 0x0010
#define CPLD_SLAVE2_INTERRUPT_RX_LOST48 0x0020
#define CPLD_SLAVE1_INTERRUPT_TX_FAULT08 0x0040
#define CPLD_SLAVE1_INTERRUPT_TX_FAULT16 0x0080
#define CPLD_SLAVE1_INTERRUPT_TX_FAULT24 0x0100
#define CPLD_SLAVE2_INTERRUPT_TX_FAULT32 0x0040
#define CPLD_SLAVE2_INTERRUPT_TX_FAULT40 0x0080
#define CPLD_SLAVE2_INTERRUPT_TX_FAULT48 0x0100
#define WAIT_TIME_OUT_COUNT 100
struct i2c_algo_lpc_data {
void *data; /* private data for lolevel routines */
void (*setlpc) (void *data, int ctl, int val);
int (*getlpc) (void *data, int ctl);
int (*getown) (void *data);
int (*getclock) (void *data);
void (*waitforpin) (void *data);
int (*xfer_begin) (void *data);
int (*xfer_end) (void *data);
/* Multi-master lost arbitration back-off delay (msecs)
* This should be set by the bus adapter or knowledgable client
* if bus is multi-mastered, else zero
*/
unsigned long lab_mdelay;
};
struct subsys_private {
struct kset subsys;
struct kset *devices_kset;
struct list_head interfaces;
struct mutex mutex;
struct kset *drivers_kset;
struct klist klist_devices;
struct klist klist_drivers;
struct blocking_notifier_head bus_notifier;
unsigned int drivers_autoprobe:1;
struct bus_type *bus;
struct kset glue_dirs;
struct class *class;
};
void cs6436_54p_sysfs_add_client(struct i2c_client *client);
void cs6436_54p_sysfs_remove_client(struct i2c_client *client);
#endif /* I2C_LPC8584_H */

View File

@ -0,0 +1,521 @@
/*
* A hwmon driver for the CIG cs6436-54p fan
*
* Copyright (C) 2018 Cambridge, Inc.
*
* 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.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/jiffies.h>
#include <linux/i2c.h>
#include <linux/hwmon.h>
#include <linux/hwmon-sysfs.h>
#include <linux/err.h>
#include <linux/mutex.h>
#include <linux/sysfs.h>
#include <linux/slab.h>
#include <linux/dmi.h>
#include <linux/fs.h>
#include <linux/uaccess.h>
#include <linux/syscalls.h>
#include <linux/kthread.h>
#include <linux/device.h>
#include <linux/platform_device.h>
#define FAN_SPEED_DUTY_TO_CPLD_STEP 10
static struct cs6436_54p_fan_data *cs6436_54p_fan_update_device(struct device *dev);
static ssize_t fan_show_value(struct device *dev, struct device_attribute *da, char *buf);
static ssize_t set_duty_cycle(struct device *dev, struct device_attribute *da,
const char *buf, size_t count);
static ssize_t set_fan_direction(struct device *dev, struct device_attribute *da,
const char *buf, size_t count);
extern int cig_cpld_write_register(u8 reg_off, u8 val);
extern int cig_cpld_read_register(u8 reg_off, u8 *val);
/* fan related data, the index should match sysfs_fan_attributes
*/
static const u8 fan_reg[] = {
0x41, /* fan enable/disable */
0x40, /* fan PWM(for all fan) */
0x42, /* front fan 1 speed(rpm) */
0x44, /* front fan 2 speed(rpm) */
0x46, /* front fan 3 speed(rpm) */
0x48, /* front fan 4 speed(rpm) */
0x4a, /* front fan 5 speed(rpm) */
0x43, /* rear fan 1 speed(rpm) */
0x45, /* rear fan 2 speed(rpm) */
0x47, /* rear fan 3 speed(rpm) */
0x49, /* rear fan 4 speed(rpm) */
0x4b, /* rear fan 5 speed(rpm) */
0x4c, /* fan direction rear to front or front to rear */
};
/* Each client has this additional data */
struct cs6436_54p_fan_data {
struct platform_device *pdev;
struct device *hwmon_dev;
struct mutex update_lock;
char valid; /* != 0 if registers are valid */
unsigned long last_updated; /* In jiffies */
u8 reg_val[ARRAY_SIZE(fan_reg)]; /* Register value */
};
static struct cs6436_54p_fan_data *fan_data = NULL;
enum fan_id {
FAN1_ID,
FAN2_ID,
FAN3_ID,
FAN4_ID,
FAN5_ID,
};
enum sysfs_fan_attributes {
FAN_STATE_REG,
FAN_DUTY_CYCLE_PERCENTAGE, /* Only one CPLD register to control duty cycle for all fans */
FAN1_FRONT_SPEED_RPM,
FAN2_FRONT_SPEED_RPM,
FAN3_FRONT_SPEED_RPM,
FAN4_FRONT_SPEED_RPM,
FAN5_FRONT_SPEED_RPM,
FAN1_REAR_SPEED_RPM,
FAN2_REAR_SPEED_RPM,
FAN3_REAR_SPEED_RPM,
FAN4_REAR_SPEED_RPM,
FAN5_REAR_SPEED_RPM,
FAN_DIRECTION,
FAN1_STATE,
FAN2_STATE,
FAN3_STATE,
FAN4_STATE,
FAN5_STATE,
FAN1_FAULT,
FAN2_FAULT,
FAN3_FAULT,
FAN4_FAULT,
FAN5_FAULT,
FAN1_DIRECTION,
FAN2_DIRECTION,
FAN3_DIRECTION,
FAN4_DIRECTION,
FAN5_DIRECTION,
};
/* Define attributes
*/
#define DECLARE_FAN_STATE_SENSOR_DEV_ATTR(index) \
static SENSOR_DEVICE_ATTR(fan##index##_state, S_IRUGO, fan_show_value, NULL, FAN##index##_STATE)
#define DECLARE_FAN_STATE_ATTR(index) &sensor_dev_attr_fan##index##_state.dev_attr.attr
#define DECLARE_FAN_FAULT_SENSOR_DEV_ATTR(index) \
static SENSOR_DEVICE_ATTR(fan##index##_fault, S_IRUGO, fan_show_value, NULL, FAN##index##_FAULT)
#define DECLARE_FAN_FAULT_ATTR(index) &sensor_dev_attr_fan##index##_fault.dev_attr.attr
#define DECLARE_FAN_DUTY_CYCLE_SENSOR_DEV_ATTR(index) \
static SENSOR_DEVICE_ATTR(fan##index##_duty_cycle_percentage, S_IWUSR | S_IRUGO, fan_show_value, set_duty_cycle, FAN##index##_DUTY_CYCLE_PERCENTAGE)
#define DECLARE_FAN_DUTY_CYCLE_ATTR(index) &sensor_dev_attr_fan##index##_duty_cycle_percentage.dev_attr.attr
#define DECLARE_FAN_SPEED_RPM_SENSOR_DEV_ATTR(index) \
static SENSOR_DEVICE_ATTR(fan##index##_front_speed_rpm, S_IRUGO, fan_show_value, NULL, FAN##index##_FRONT_SPEED_RPM);\
static SENSOR_DEVICE_ATTR(fan##index##_rear_speed_rpm, S_IRUGO, fan_show_value, NULL, FAN##index##_REAR_SPEED_RPM)
#define DECLARE_FAN_SPEED_RPM_ATTR(index) &sensor_dev_attr_fan##index##_front_speed_rpm.dev_attr.attr, \
&sensor_dev_attr_fan##index##_rear_speed_rpm.dev_attr.attr
#define DECLARE_FAN_DIRECTION_SENSOR_DEV_ATTR(index) \
static SENSOR_DEVICE_ATTR(fan##index##_direction, S_IWUSR | S_IRUGO, fan_show_value, set_fan_direction, FAN##index##_DIRECTION)
#define DECLARE_FAN_DIRECTION_ATTR(index) &sensor_dev_attr_fan##index##_direction.dev_attr.attr
/* 5 fan state attributes in this platform */
DECLARE_FAN_STATE_SENSOR_DEV_ATTR(1);
DECLARE_FAN_STATE_SENSOR_DEV_ATTR(2);
DECLARE_FAN_STATE_SENSOR_DEV_ATTR(3);
DECLARE_FAN_STATE_SENSOR_DEV_ATTR(4);
DECLARE_FAN_STATE_SENSOR_DEV_ATTR(5);
/* 5 fan fault attributes in this platform */
DECLARE_FAN_FAULT_SENSOR_DEV_ATTR(1);
DECLARE_FAN_FAULT_SENSOR_DEV_ATTR(2);
DECLARE_FAN_FAULT_SENSOR_DEV_ATTR(3);
DECLARE_FAN_FAULT_SENSOR_DEV_ATTR(4);
DECLARE_FAN_FAULT_SENSOR_DEV_ATTR(5);
/* 5 fan speed(rpm) attributes in this platform */
DECLARE_FAN_SPEED_RPM_SENSOR_DEV_ATTR(1);
DECLARE_FAN_SPEED_RPM_SENSOR_DEV_ATTR(2);
DECLARE_FAN_SPEED_RPM_SENSOR_DEV_ATTR(3);
DECLARE_FAN_SPEED_RPM_SENSOR_DEV_ATTR(4);
DECLARE_FAN_SPEED_RPM_SENSOR_DEV_ATTR(5);
/* 1 fan duty cycle attribute in this platform */
DECLARE_FAN_DUTY_CYCLE_SENSOR_DEV_ATTR();
DECLARE_FAN_DIRECTION_SENSOR_DEV_ATTR(1);
DECLARE_FAN_DIRECTION_SENSOR_DEV_ATTR(2);
DECLARE_FAN_DIRECTION_SENSOR_DEV_ATTR(3);
DECLARE_FAN_DIRECTION_SENSOR_DEV_ATTR(4);
DECLARE_FAN_DIRECTION_SENSOR_DEV_ATTR(5);
static struct attribute *cs6436_54p_fan_attributes[] = {
/* fan related attributes */
DECLARE_FAN_STATE_ATTR(1),
DECLARE_FAN_STATE_ATTR(2),
DECLARE_FAN_STATE_ATTR(3),
DECLARE_FAN_STATE_ATTR(4),
DECLARE_FAN_STATE_ATTR(5),
DECLARE_FAN_FAULT_ATTR(1),
DECLARE_FAN_FAULT_ATTR(2),
DECLARE_FAN_FAULT_ATTR(3),
DECLARE_FAN_FAULT_ATTR(4),
DECLARE_FAN_FAULT_ATTR(5),
DECLARE_FAN_SPEED_RPM_ATTR(1),
DECLARE_FAN_SPEED_RPM_ATTR(2),
DECLARE_FAN_SPEED_RPM_ATTR(3),
DECLARE_FAN_SPEED_RPM_ATTR(4),
DECLARE_FAN_SPEED_RPM_ATTR(5),
DECLARE_FAN_DUTY_CYCLE_ATTR(),
DECLARE_FAN_DIRECTION_ATTR(1),
DECLARE_FAN_DIRECTION_ATTR(2),
DECLARE_FAN_DIRECTION_ATTR(3),
DECLARE_FAN_DIRECTION_ATTR(4),
DECLARE_FAN_DIRECTION_ATTR(5),
NULL
};
#define FAN_MAX_DUTY_CYCLE 100
#define FAN_REG_VAL_TO_SPEED_RPM_STEP 100
/* fan utility functions
*/
static u32 reg_val_to_duty_cycle(u8 reg_val)
{
if (reg_val
== 0xFF) {
return 100;
}
return ((u32)(reg_val) * 100)/ 255;
}
static u8 duty_cycle_to_reg_val(u8 duty_cycle)
{
if (duty_cycle >= FAN_MAX_DUTY_CYCLE) {
return 0xFF;
}
return 255 / 10 * (duty_cycle / 10);
}
static u32 reg_val_to_speed_rpm(u8 reg_val)
{
return (u32)reg_val * FAN_REG_VAL_TO_SPEED_RPM_STEP;
}
static u8 reg_val_to_is_state(u8 reg_val, enum fan_id id)
{
u8 mask = (1 << id);
reg_val &= mask;
return reg_val ? 0 : 1;
}
static u8 is_fan_fault(struct cs6436_54p_fan_data *data, enum fan_id id)
{
u8 ret = 1;
int front_fan_index = FAN1_FRONT_SPEED_RPM + id;
int rear_fan_index = FAN1_REAR_SPEED_RPM + id;
/* Check if the speed of front or rear fan is ZERO,
*/
if (reg_val_to_speed_rpm(data->reg_val[front_fan_index]) &&
reg_val_to_speed_rpm(data->reg_val[rear_fan_index])) {
ret = 0;
}
return ret;
}
static ssize_t set_duty_cycle(struct device *dev, struct device_attribute *da,
const char *buf, size_t count)
{
int error, value;
error = kstrtoint(buf, 10, &value);
if (error)
return error;
if (value <= 0 || value > FAN_MAX_DUTY_CYCLE)
return -EINVAL;
cig_cpld_write_register(fan_reg[FAN_DUTY_CYCLE_PERCENTAGE], duty_cycle_to_reg_val(value));
return count;
}
static ssize_t set_fan_direction(struct device *dev, struct device_attribute *da,
const char *buf, size_t count)
{
int error, value,fan_index;
u8 mask,reg_val;
struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
fan_index = attr->index - FAN1_DIRECTION;
error = kstrtoint(buf, 10, &value);
if (error)
return error;
if (!(value == 0 || value == 1))
return -EINVAL;
cig_cpld_read_register(fan_reg[FAN_DIRECTION],&reg_val);
if(value == 1)
{
reg_val |= (1 << fan_index);
}
else
{
reg_val &= ~(1 << fan_index);
}
cig_cpld_write_register(fan_reg[FAN_DIRECTION], reg_val);
return count;
}
static ssize_t fan_show_value(struct device *dev, struct device_attribute *da,
char *buf)
{
struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
cs6436_54p_fan_update_device(dev);
struct cs6436_54p_fan_data *data = fan_data;
ssize_t ret = 0;
if (data->valid) {
switch (attr->index) {
case FAN1_STATE:
case FAN2_STATE:
case FAN3_STATE:
case FAN4_STATE:
case FAN5_STATE:
//printk("FAN_STATE_REG: 0x%x\n", data->reg_val[FAN_STATE_REG]);
//printk("index: %d\n", attr->index);
ret = sprintf(buf, "%d\n",
reg_val_to_is_state(data->reg_val[FAN_STATE_REG],
attr->index - FAN1_STATE));
break;
case FAN_DUTY_CYCLE_PERCENTAGE:
{
u32 duty_cycle = reg_val_to_duty_cycle(data->reg_val[FAN_DUTY_CYCLE_PERCENTAGE]);
ret = sprintf(buf, "%u\n", duty_cycle);
break;
}
case FAN1_FRONT_SPEED_RPM:
case FAN2_FRONT_SPEED_RPM:
case FAN3_FRONT_SPEED_RPM:
case FAN4_FRONT_SPEED_RPM:
case FAN5_FRONT_SPEED_RPM:
case FAN1_REAR_SPEED_RPM:
case FAN2_REAR_SPEED_RPM:
case FAN3_REAR_SPEED_RPM:
case FAN4_REAR_SPEED_RPM:
case FAN5_REAR_SPEED_RPM:
// printk("FAN_seed_REG: 0x%x\n", data->reg_val[attr->index]);
// printk("index: %d\n", attr->index);
ret = sprintf(buf, "%u\n", reg_val_to_speed_rpm(data->reg_val[attr->index]));
break;
case FAN1_FAULT:
case FAN2_FAULT:
case FAN3_FAULT:
case FAN4_FAULT:
case FAN5_FAULT:
ret = sprintf(buf, "%d\n", is_fan_fault(data, attr->index - FAN1_FAULT));
break;
case FAN1_DIRECTION:
case FAN2_DIRECTION:
case FAN3_DIRECTION:
case FAN4_DIRECTION:
case FAN5_DIRECTION:
ret = sprintf(buf, "%d\n",reg_val_to_is_state(data->reg_val[FAN_DIRECTION],attr->index - FAN1_DIRECTION));
break;
default:
break;
}
}
return ret;
}
static const struct attribute_group cs6436_54p_fan_group = {
.attrs = cs6436_54p_fan_attributes,
};
static struct cs6436_54p_fan_data *cs6436_54p_fan_update_device(struct device *dev)
{
struct cs6436_54p_fan_data *data = fan_data;
mutex_lock(&data->update_lock);
if (time_after(jiffies, data->last_updated + HZ + HZ / 2) ||
!data->valid) {
int i;
data->valid = 0;
/* Update fan data
*/
for (i = 0; i < ARRAY_SIZE(data->reg_val); i++) {
u8 status;
(void)cig_cpld_read_register(fan_reg[i], &status);
if (status < 0) {
data->valid = 0;
mutex_unlock(&data->update_lock);
return data;
}
else {
data->reg_val[i] = status;
}
}
data->last_updated = jiffies;
data->valid = 1;
}
mutex_unlock(&data->update_lock);
return data;
}
static int cs6436_54p_fan_probe(struct platform_device *pdev)
{
int status = -1;
/* Register sysfs hooks */
status = sysfs_create_group(&pdev->dev.kobj, &cs6436_54p_fan_group);
if (status) {
goto exit;
}
fan_data->hwmon_dev = hwmon_device_register(&pdev->dev);
if (IS_ERR(fan_data->hwmon_dev)) {
status = PTR_ERR(fan_data->hwmon_dev);
goto exit_remove;
}
dev_info(&pdev->dev, "cs6436_54p_fan\n");
return 0;
exit_remove:
sysfs_remove_group(&pdev->dev.kobj, &cs6436_54p_fan_group);
exit:
return status;
}
static int cs6436_54p_fan_remove(struct platform_device *pdev)
{
hwmon_device_unregister(fan_data->hwmon_dev);
sysfs_remove_group(&fan_data->pdev->dev.kobj, &cs6436_54p_fan_group);
return 0;
}
#define DRVNAME "cs6436_54p_fan"
static struct platform_driver cs6436_54p_fan_driver = {
.probe = cs6436_54p_fan_probe,
.remove = cs6436_54p_fan_remove,
.driver = {
.name = DRVNAME,
.owner = THIS_MODULE,
},
};
static int __init cs6436_54p_fan_init(void)
{
int ret;
cig_cpld_write_register(0x40, duty_cycle_to_reg_val(50));
ret = platform_driver_register(&cs6436_54p_fan_driver);
if (ret < 0) {
goto exit;
}
fan_data = kzalloc(sizeof(struct cs6436_54p_fan_data), GFP_KERNEL);
if (!fan_data) {
ret = -ENOMEM;
platform_driver_unregister(&cs6436_54p_fan_driver);
goto exit;
}
mutex_init(&fan_data->update_lock);
fan_data->valid = 0;
fan_data->pdev = platform_device_register_simple(DRVNAME, -1, NULL, 0);
if (IS_ERR(fan_data->pdev)) {
ret = PTR_ERR(fan_data->pdev);
platform_driver_unregister(&cs6436_54p_fan_driver);
kfree(fan_data);
goto exit;
}
exit:
return ret;
}
static void __exit cs6436_54p_fan_exit(void)
{
platform_device_unregister(fan_data->pdev);
platform_driver_unregister(&cs6436_54p_fan_driver);
kfree(fan_data);
}
MODULE_AUTHOR("CIG");
MODULE_DESCRIPTION("cs6436_54p_fan driver");
MODULE_LICENSE("GPL");
module_init(cs6436_54p_fan_init);
module_exit(cs6436_54p_fan_exit);
MODULE_AUTHOR("Zhang Peng <zhangpeng@cigtech.com>");
MODULE_DESCRIPTION("cs6436_54p_fan driver");
MODULE_LICENSE("GPL");

View File

@ -0,0 +1,594 @@
/*
* A hwmon driver for the CIG cs6436-54P LED
*
* Copyright (C) 2018 Cambridge, Inc.
*
* 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.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/*#define DEBUG*/
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/platform_device.h>
#include <linux/err.h>
#include <linux/leds.h>
#include <linux/slab.h>
#include <linux/dmi.h>
extern int cig_cpld_write_register(u8 reg_off, u8 val);
extern int cig_cpld_read_register(u8 reg_off, u8 *val);
extern void led_classdev_unregister(struct led_classdev *led_cdev);
extern int led_classdev_register(struct device *parent, struct led_classdev *led_cdev);
extern void led_classdev_resume(struct led_classdev *led_cdev);
extern void led_classdev_suspend(struct led_classdev *led_cdev);
#define DRVNAME "cs6436_54p_led"
struct cs6436_54p_led_data {
struct platform_device *pdev;
struct mutex update_lock;
char valid; /* != 0 if registers are valid */
unsigned long last_updated; /* In jiffies */
u8 reg_val[6]; /* 0: system & location
1: PSU1 &PSU12
2: fan & management
3: console & ToD
4-5 : fan1-fan5*/
};
static struct cs6436_54p_led_data *ledctl = NULL;
/* LED related data
*/
#define LED_TYPE_PSU1_REG_MASK 0x0C
#define LED_MODE_PSU1_GREEN_MASK 0x08
#define LED_MODE_PSU1_RED_MASK 0x04
#define LED_MODE_PSU1_AMBER_MASK 0x0C
#define LED_MODE_PSU1_OFF_MASK 0x00
#define LED_TYPE_PSU2_REG_MASK 0x30
#define LED_MODE_PSU2_GREEN_MASK 0x20
#define LED_MODE_PSU2_RED_MASK 0x10
#define LED_MODE_PSU2_AMBER_MASK 0x30
#define LED_MODE_PSU2_OFF_MASK 0x00
#define LED_TYPE_SYS_REG_MASK 0xF0
#define LED_MODE_SYS_GREEN_MASK 0x40
#define LED_MODE_SYS_RED_MASK 0x20
#define LED_MODE_SYS_AMBER_MASK 0x60
#define LED_MODE_SYS_AMBER_FLASHING_MASK 0x70
#define LED_MODE_SYS_OFF_MASK 0x00
#define LED_TYPE_RES_REG_MASK 0x0F
#define LED_MODE_RES_GREEN_MASK 0x04
#define LED_MODE_RES_RED_MASK 0x02
#define LED_MODE_RES_AMBER_MASK 0x06
#define LED_MODE_RES_AMBER_FLASHING_MASK 0x07
#define LED_MODE_RES_OFF_MASK 0x00
#define LED_TYPE_FAN_REG_MASK 0x03
#define LED_MODE_FAN_GREEN_MASK 0x02
#define LED_MODE_FAN_RED_MASK 0x01
#define LED_MODE_FAN_AMBER_MASK 0x03
#define LED_MODE_FAN_OFF_MASK 0x00
#define LED_TYPE_FAN1_REG_MASK 0x03
#define LED_TYPE_FAN2_REG_MASK 0x0C
#define LED_TYPE_FAN3_REG_MASK 0x30
#define LED_TYPE_FAN4_REG_MASK 0xC0
#define LED_TYPE_FAN5_REG_MASK 0x03
#define LED_MODE_FANX_GREEN_MASK 0x02
#define LED_MODE_FANX_RED_MASK 0x01
#define LED_MODE_FANX_AMBER_MASK 0x03
#define LED_MODE_FANX_OFF_MASK 0x00
enum led_type {
LED_TYPE_SYS,
LED_TYPE_PSU2,
LED_TYPE_PSU1,
LED_TYPE_FAN,
LED_TYPE_FAN1,
LED_TYPE_FAN2,
LED_TYPE_FAN3,
LED_TYPE_FAN4,
LED_TYPE_FAN5,
};
static const u8 led_reg[] = {
0x30, /* system & reserved*/
0x31, /* fan & PSU1 & PSU2 */
0x32, /* FAN5 LED */
0x33, /* FAN1-4 LED */
};
enum led_light_mode {
LED_MODE_OFF = 0,
LED_MODE_GREEN,
LED_MODE_AMBER,
LED_MODE_RED,
LED_MODE_GREEN_BLINK,
LED_MODE_AMBER_BLINK,
LED_MODE_RED_BLINK,
LED_MODE_GREEN_FLASHING,
LED_MODE_AMBER_FLASHING,
LED_MODE_RED_FLASHING,
LED_MODE_AUTO,
LED_MODE_UNKNOWN
};
struct led_type_mode {
enum led_type type;
int type_mask;
enum led_light_mode mode;
int mode_mask;
};
static struct led_type_mode led_type_mode_data[] = {
{LED_TYPE_PSU1, LED_TYPE_PSU1_REG_MASK, LED_MODE_GREEN, LED_MODE_PSU1_GREEN_MASK},
{LED_TYPE_PSU1, LED_TYPE_PSU1_REG_MASK, LED_MODE_AMBER, LED_MODE_PSU1_AMBER_MASK},
{LED_TYPE_PSU1, LED_TYPE_PSU1_REG_MASK, LED_MODE_RED, LED_MODE_PSU1_RED_MASK},
{LED_TYPE_PSU1, LED_TYPE_PSU1_REG_MASK, LED_MODE_OFF, LED_MODE_PSU1_OFF_MASK},
{LED_TYPE_PSU2, LED_TYPE_PSU2_REG_MASK, LED_MODE_GREEN, LED_MODE_PSU2_GREEN_MASK},
{LED_TYPE_PSU2, LED_TYPE_PSU2_REG_MASK, LED_MODE_AMBER, LED_MODE_PSU2_AMBER_MASK},
{LED_TYPE_PSU2, LED_TYPE_PSU2_REG_MASK, LED_MODE_RED, LED_MODE_PSU2_RED_MASK},
{LED_TYPE_PSU2, LED_TYPE_PSU2_REG_MASK, LED_MODE_OFF, LED_MODE_PSU2_OFF_MASK},
{LED_TYPE_SYS, LED_TYPE_SYS_REG_MASK, LED_MODE_GREEN, LED_MODE_SYS_GREEN_MASK},
{LED_TYPE_SYS, LED_TYPE_SYS_REG_MASK, LED_MODE_AMBER, LED_MODE_SYS_AMBER_MASK},
{LED_TYPE_SYS, LED_TYPE_SYS_REG_MASK, LED_MODE_RED, LED_MODE_SYS_RED_MASK},
{LED_TYPE_SYS, LED_TYPE_SYS_REG_MASK, LED_MODE_AMBER_FLASHING, LED_MODE_SYS_AMBER_FLASHING_MASK},
{LED_TYPE_SYS, LED_TYPE_SYS_REG_MASK, LED_MODE_OFF, LED_MODE_SYS_OFF_MASK},
{LED_TYPE_FAN, LED_TYPE_FAN_REG_MASK, LED_MODE_GREEN, LED_MODE_FAN_GREEN_MASK},
{LED_TYPE_FAN, LED_TYPE_FAN_REG_MASK, LED_MODE_AMBER, LED_MODE_FAN_AMBER_MASK},
{LED_TYPE_FAN, LED_TYPE_FAN_REG_MASK, LED_MODE_RED, LED_MODE_FAN_RED_MASK},
{LED_TYPE_FAN, LED_TYPE_FAN_REG_MASK, LED_MODE_OFF, LED_MODE_FAN_OFF_MASK},
{LED_TYPE_FAN1, LED_TYPE_FAN1_REG_MASK, LED_MODE_GREEN, LED_MODE_FANX_GREEN_MASK << 0},
{LED_TYPE_FAN1, LED_TYPE_FAN1_REG_MASK, LED_MODE_RED, LED_MODE_FANX_RED_MASK << 0},
{LED_TYPE_FAN1, LED_TYPE_FAN1_REG_MASK, LED_MODE_AMBER, LED_MODE_FANX_AMBER_MASK << 0},
{LED_TYPE_FAN1, LED_TYPE_FAN1_REG_MASK, LED_MODE_OFF, LED_MODE_FANX_OFF_MASK << 0},
{LED_TYPE_FAN2, LED_TYPE_FAN2_REG_MASK, LED_MODE_GREEN, LED_MODE_FANX_GREEN_MASK << 2},
{LED_TYPE_FAN2, LED_TYPE_FAN2_REG_MASK, LED_MODE_RED, LED_MODE_FANX_RED_MASK << 2},
{LED_TYPE_FAN2, LED_TYPE_FAN2_REG_MASK, LED_MODE_AMBER, LED_MODE_FANX_AMBER_MASK << 2},
{LED_TYPE_FAN2, LED_TYPE_FAN2_REG_MASK, LED_MODE_OFF, LED_MODE_FANX_OFF_MASK << 2},
{LED_TYPE_FAN3, LED_TYPE_FAN3_REG_MASK, LED_MODE_GREEN, LED_MODE_FANX_GREEN_MASK << 4},
{LED_TYPE_FAN3, LED_TYPE_FAN3_REG_MASK, LED_MODE_RED, LED_MODE_FANX_RED_MASK << 4},
{LED_TYPE_FAN3, LED_TYPE_FAN3_REG_MASK, LED_MODE_AMBER, LED_MODE_FANX_AMBER_MASK << 4},
{LED_TYPE_FAN3, LED_TYPE_FAN3_REG_MASK, LED_MODE_OFF, LED_MODE_FANX_OFF_MASK << 4},
{LED_TYPE_FAN4, LED_TYPE_FAN4_REG_MASK, LED_MODE_GREEN, LED_MODE_FANX_GREEN_MASK << 6},
{LED_TYPE_FAN4, LED_TYPE_FAN4_REG_MASK, LED_MODE_RED, LED_MODE_FANX_RED_MASK << 6},
{LED_TYPE_FAN4, LED_TYPE_FAN4_REG_MASK, LED_MODE_AMBER, LED_MODE_FANX_AMBER_MASK << 6},
{LED_TYPE_FAN4, LED_TYPE_FAN4_REG_MASK, LED_MODE_OFF, LED_MODE_FANX_OFF_MASK << 6},
{LED_TYPE_FAN5, LED_TYPE_FAN5_REG_MASK, LED_MODE_GREEN, LED_MODE_FANX_GREEN_MASK << 0},
{LED_TYPE_FAN5, LED_TYPE_FAN5_REG_MASK, LED_MODE_RED, LED_MODE_FANX_RED_MASK << 0},
{LED_TYPE_FAN5, LED_TYPE_FAN5_REG_MASK, LED_MODE_AMBER, LED_MODE_FANX_AMBER_MASK << 0},
{LED_TYPE_FAN5, LED_TYPE_FAN5_REG_MASK, LED_MODE_OFF, LED_MODE_FANX_OFF_MASK << 0},
};
struct fanx_info_s {
u8 cname; /* device name */
enum led_type type;
u8 reg_id; /* map to led_reg & reg_val */
};
static struct fanx_info_s fanx_info[] = {
{'1', LED_TYPE_FAN1, 3},
{'2', LED_TYPE_FAN2, 3},
{'3', LED_TYPE_FAN3, 3},
{'4', LED_TYPE_FAN4, 3},
{'5', LED_TYPE_FAN5, 2},
};
static int led_reg_val_to_light_mode(enum led_type type, u8 reg_val) {
int i;
for (i = 0; i < ARRAY_SIZE(led_type_mode_data); i++) {
if (type != led_type_mode_data[i].type)
continue;
if ((led_type_mode_data[i].type_mask & reg_val) ==
led_type_mode_data[i].mode_mask)
{
return led_type_mode_data[i].mode;
}
}
return 0;
}
static u8 led_light_mode_to_reg_val(enum led_type type,
enum led_light_mode mode, u8 reg_val) {
int i;
for (i = 0; i < ARRAY_SIZE(led_type_mode_data); i++) {
if (type != led_type_mode_data[i].type)
continue;
if (mode != led_type_mode_data[i].mode)
continue;
reg_val = led_type_mode_data[i].mode_mask |
(reg_val & (~led_type_mode_data[i].type_mask));
break;
}
return reg_val;
}
static void cs6436_54p_led_update(void)
{
mutex_lock(&ledctl->update_lock);
if (time_after(jiffies, ledctl->last_updated + HZ + HZ / 2)
|| !ledctl->valid) {
int i;
dev_dbg(&ledctl->pdev->dev, "Starting cs6436_54p_led update\n");
/* Update LED data
*/
for (i = 0; i < ARRAY_SIZE(ledctl->reg_val); i++) {
u8 status;
cig_cpld_read_register(led_reg[i], &status);
if (status < 0) {
ledctl->valid = 0;
dev_dbg(&ledctl->pdev->dev, "reg %d, err %d\n", led_reg[i], status);
goto exit;
}
else
{
ledctl->reg_val[i] = status;
}
}
ledctl->last_updated = jiffies;
ledctl->valid = 1;
}
exit:
mutex_unlock(&ledctl->update_lock);
}
static void cs6436_54p_led_set(struct led_classdev *led_cdev,
enum led_brightness led_light_mode,
u8 reg, enum led_type type)
{
u8 reg_val;
mutex_lock(&ledctl->update_lock);
cig_cpld_read_register(reg, &reg_val);
if (reg_val < 0) {
dev_dbg(&ledctl->pdev->dev, "reg %d, err %d\n", reg, reg_val);
goto exit;
}
reg_val = led_light_mode_to_reg_val(type, led_light_mode, reg_val);
cig_cpld_write_register(reg, reg_val);
/* to prevent the slow-update issue */
ledctl->valid = 0;
exit:
mutex_unlock(&ledctl->update_lock);
}
static void cs6436_54p_led_fanx_set(struct led_classdev *led_cdev,
enum led_brightness led_light_mode)
{
enum led_type led_type1;
int reg_id;
int i, nsize;
int ncount = sizeof(fanx_info)/sizeof(struct fanx_info_s);
for(i=0;i<ncount;i++)
{
nsize=strlen(led_cdev->name);
if (led_cdev->name[nsize-1] == fanx_info[i].cname)
{
led_type1 = fanx_info[i].type;
reg_id = fanx_info[i].reg_id;
cs6436_54p_led_set(led_cdev, led_light_mode, led_reg[reg_id], led_type1);
return;
}
}
}
static enum led_brightness cs6436_54p_led_fanx_get(struct led_classdev *cdev)
{
enum led_type led_type1;
int reg_id;
int i, nsize;
int ncount = sizeof(fanx_info)/sizeof(struct fanx_info_s);
for(i=0;i<ncount;i++)
{
nsize=strlen(cdev->name);
if (cdev->name[nsize-1] == fanx_info[i].cname)
{
led_type1 = fanx_info[i].type;
reg_id = fanx_info[i].reg_id;
cs6436_54p_led_update();
return led_reg_val_to_light_mode(led_type1, ledctl->reg_val[reg_id]);
}
}
return led_reg_val_to_light_mode(LED_TYPE_FAN1, ledctl->reg_val[5]);
}
static void cs6436_54p_led_psu1_set(struct led_classdev *led_cdev,
enum led_brightness led_light_mode)
{
cs6436_54p_led_set(led_cdev, led_light_mode, led_reg[1], LED_TYPE_PSU1);
}
static enum led_brightness cs6436_54p_led_psu1_get(struct led_classdev *cdev)
{
cs6436_54p_led_update();
return led_reg_val_to_light_mode(LED_TYPE_PSU1, ledctl->reg_val[1]);
}
static void cs6436_54p_led_psu2_set(struct led_classdev *led_cdev,
enum led_brightness led_light_mode)
{
cs6436_54p_led_set(led_cdev, led_light_mode, led_reg[1], LED_TYPE_PSU2);
}
static enum led_brightness cs6436_54p_led_psu2_get(struct led_classdev *cdev)
{
cs6436_54p_led_update();
return led_reg_val_to_light_mode(LED_TYPE_PSU2, ledctl->reg_val[1]);
}
static void cs6436_54p_led_sys_set(struct led_classdev *led_cdev,
enum led_brightness led_light_mode)
{
cs6436_54p_led_set(led_cdev, led_light_mode,led_reg[0], LED_TYPE_SYS);
}
static enum led_brightness cs6436_54p_led_sys_get(struct led_classdev *cdev)
{
cs6436_54p_led_update();
return led_reg_val_to_light_mode(LED_TYPE_SYS, ledctl->reg_val[0]);
}
static enum led_brightness cs6436_54p_led_fan_get(struct led_classdev *cdev)
{
cs6436_54p_led_update();
return led_reg_val_to_light_mode(LED_TYPE_FAN, ledctl->reg_val[1]);
}
static void cs6436_54p_led_fan_set(struct led_classdev *led_cdev,
enum led_brightness led_light_mode)
{
cs6436_54p_led_set(led_cdev, led_light_mode, led_reg[1], LED_TYPE_FAN);
}
static struct led_classdev cs6436_54p_leds[] = {
[LED_TYPE_SYS] = {
.name = "cs6436_54p_led::sys",
.default_trigger = "unused",
.brightness_set = cs6436_54p_led_sys_set,
.brightness_get = cs6436_54p_led_sys_get,
.flags = LED_CORE_SUSPENDRESUME,
.max_brightness = LED_MODE_AUTO,
},
[LED_TYPE_FAN] = {
.name = "cs6436_54p_led::fan",
.default_trigger = "unused",
.brightness_set = cs6436_54p_led_fan_set,
.brightness_get = cs6436_54p_led_fan_get,
.flags = LED_CORE_SUSPENDRESUME,
.max_brightness = LED_MODE_AUTO,
},
[LED_TYPE_PSU1] = {
.name = "cs6436_54p_led::psu1",
.default_trigger = "unused",
.brightness_set = cs6436_54p_led_psu1_set,
.brightness_get = cs6436_54p_led_psu1_get,
.flags = LED_CORE_SUSPENDRESUME,
.max_brightness = LED_MODE_AUTO,
},
[LED_TYPE_PSU2] = {
.name = "cs6436_54p_led::psu2",
.default_trigger = "unused",
.brightness_set = cs6436_54p_led_psu2_set,
.brightness_get = cs6436_54p_led_psu2_get,
.flags = LED_CORE_SUSPENDRESUME,
.max_brightness = LED_MODE_AUTO,
},
[LED_TYPE_FAN1] = {
.name = "cs6436_54p_led::fan1",
.default_trigger = "unused",
.brightness_set = cs6436_54p_led_fanx_set,
.brightness_get = cs6436_54p_led_fanx_get,
.flags = LED_CORE_SUSPENDRESUME,
.max_brightness = LED_MODE_AUTO,
},
[LED_TYPE_FAN2] = {
.name = "cs6436_54p_led::fan2",
.default_trigger = "unused",
.brightness_set = cs6436_54p_led_fanx_set,
.brightness_get = cs6436_54p_led_fanx_get,
.flags = LED_CORE_SUSPENDRESUME,
.max_brightness = LED_MODE_AUTO,
},
[LED_TYPE_FAN3] = {
.name = "cs6436_54p_led::fan3",
.default_trigger = "unused",
.brightness_set = cs6436_54p_led_fanx_set,
.brightness_get = cs6436_54p_led_fanx_get,
.flags = LED_CORE_SUSPENDRESUME,
.max_brightness = LED_MODE_AUTO,
},
[LED_TYPE_FAN4] = {
.name = "cs6436_54p_led::fan4",
.default_trigger = "unused",
.brightness_set = cs6436_54p_led_fanx_set,
.brightness_get = cs6436_54p_led_fanx_get,
.flags = LED_CORE_SUSPENDRESUME,
.max_brightness = LED_MODE_AUTO,
},
[LED_TYPE_FAN5] = {
.name = "cs6436_54p_led::fan5",
.default_trigger = "unused",
.brightness_set = cs6436_54p_led_fanx_set,
.brightness_get = cs6436_54p_led_fanx_get,
.flags = LED_CORE_SUSPENDRESUME,
.max_brightness = LED_MODE_AUTO,
}
};
static int cs6436_54p_led_suspend(struct platform_device *dev,
pm_message_t state)
{
int i = 0;
for (i = 0; i < ARRAY_SIZE(cs6436_54p_leds); i++) {
led_classdev_suspend(&cs6436_54p_leds[i]);
}
return 0;
}
static int cs6436_54p_led_resume(struct platform_device *dev)
{
int i = 0;
for (i = 0; i < ARRAY_SIZE(cs6436_54p_leds); i++) {
led_classdev_resume(&cs6436_54p_leds[i]);
}
return 0;
}
static int cs6436_54p_led_probe(struct platform_device *pdev)
{
int ret, i;
for (i = 0; i < ARRAY_SIZE(cs6436_54p_leds); i++) {
ret = led_classdev_register(&pdev->dev, &cs6436_54p_leds[i]);
if (ret < 0)
break;
}
/* Check if all LEDs were successfully registered */
if (i != ARRAY_SIZE(cs6436_54p_leds)) {
int j;
/* only unregister the LEDs that were successfully registered */
for (j = 0; j < i; j++) {
led_classdev_unregister(&cs6436_54p_leds[i]);
}
}
return ret;
}
static int cs6436_54p_led_remove(struct platform_device *pdev)
{
int i;
for (i = 0; i < ARRAY_SIZE(cs6436_54p_leds); i++) {
led_classdev_unregister(&cs6436_54p_leds[i]);
}
return 0;
}
static struct platform_driver cs6436_54p_led_driver = {
.probe = cs6436_54p_led_probe,
.remove = cs6436_54p_led_remove,
.suspend = cs6436_54p_led_suspend,
.resume = cs6436_54p_led_resume,
.driver = {
.name = DRVNAME,
.owner = THIS_MODULE,
},
};
static int cs6436_54p_led_default(void)
{
cig_cpld_write_register(0x30, 0x40);// system green led solid on
}
static int __init cs6436_54p_led_init(void)
{
int ret;
ret = platform_driver_register(&cs6436_54p_led_driver);
if (ret < 0) {
goto exit;
}
ledctl = kzalloc(sizeof(struct cs6436_54p_led_data), GFP_KERNEL);
if (!ledctl) {
ret = -ENOMEM;
platform_driver_unregister(&cs6436_54p_led_driver);
goto exit;
}
mutex_init(&ledctl->update_lock);
ledctl->pdev = platform_device_register_simple(DRVNAME, -1, NULL, 0);
if (IS_ERR(ledctl->pdev)) {
ret = PTR_ERR(ledctl->pdev);
platform_driver_unregister(&cs6436_54p_led_driver);
kfree(ledctl);
goto exit;
}
cs6436_54p_led_default();
exit:
return ret;
}
static void __exit cs6436_54p_led_exit(void)
{
platform_device_unregister(ledctl->pdev);
platform_driver_unregister(&cs6436_54p_led_driver);
kfree(ledctl);
}
module_init(cs6436_54p_led_init);
module_exit(cs6436_54p_led_exit);
MODULE_AUTHOR("Zhang Peng <zhangpeng@cigtech.com>");
MODULE_DESCRIPTION("cs6436_54p_led driver");
MODULE_LICENSE("GPL");

View File

@ -0,0 +1,943 @@
/*
* A hwmon driver for the CIG cs6436-54P Power Module
*
* Copyright (C) 2018 Cambridge, Inc.
*
* 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.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <linux/module.h>
#include <linux/jiffies.h>
#include <linux/i2c.h>
#include <linux/hwmon.h>
#include <linux/hwmon-sysfs.h>
#include <linux/err.h>
#include <linux/mutex.h>
#include <linux/sysfs.h>
#include <linux/slab.h>
#include <linux/delay.h>
#include <linux/dmi.h>
#include <linux/fs.h>
#include <linux/uaccess.h>
#include <linux/syscalls.h>
#include <linux/kthread.h>
#include <linux/device.h>
#include <linux/platform_device.h>
#include "i2c-algo-lpc.h"
#define MAX_FAN_DUTY_CYCLE 100
/* Address scanned */
static const unsigned short normal_i2c[] = {I2C_CLIENT_END };
/* This is additional data */
struct cs6436_54p_psu_data {
struct device *hwmon_dev;
struct mutex update_lock;
char valid;
unsigned long last_updated; /* In jiffies */
/* Registers value */
u8 vout_mode;
u16 v_in;
u16 v_out;
u16 i_in;
u16 i_out;
u16 p_in;
u16 p_out;
u16 temp_input[3];
u8 temp_fault;
u8 fan_fault;
u16 fan_duty_cycle[2];
u16 fan_speed[2];
u8 mfr_id[8];
u8 mfr_model[20];
u8 mfr_serial[20];
u8 psu_is_present;
u8 psu_is_good;
struct i2c_client *client;
struct bin_attribute *bin; /* eeprom data */
};
static int two_complement_to_int(u16 data, u8 valid_bit, int mask);
static ssize_t set_fan_duty_cycle(struct device *dev, struct device_attribute *dev_attr, const char *buf, size_t count);
static ssize_t for_linear_data(struct device *dev, struct device_attribute *dev_attr, char *buf);
static ssize_t for_fan_fault(struct device *dev, struct device_attribute *dev_attr, char *buf);
static ssize_t for_fan_warning(struct device *dev, struct device_attribute *dev_attr, char *buf);
static ssize_t for_temp_fault(struct device *dev, struct device_attribute *dev_attr, char *buf);
static ssize_t for_temp_warning(struct device *dev, struct device_attribute *dev_attr, char *buf);
static ssize_t for_vout_data(struct device *dev, struct device_attribute *dev_attr, char *buf);
static int cs6436_54p_psu_read_byte(struct i2c_client *client, u8 reg);
static int cs6436_54p_psu_read_word(struct i2c_client *client, u8 reg);
static int cs6436_54p_psu_write_word(struct i2c_client *client, u8 reg, u16 value);
static int cs6436_54p_psu_read_block(struct i2c_client *client, u8 command, u8 *data, int data_len);
static struct cs6436_54p_psu_data *cs6436_54p_psu_update_device(struct device *dev);
static ssize_t for_ascii(struct device *dev, struct device_attribute *dev_attr, char *buf);
static ssize_t for_status(struct device *dev, struct device_attribute *dev_attr, char *buf);
enum cs6436_54p_psu_sysfs_attributes {
PSU_V_IN,
PSU_V_OUT,
PSU_I_IN,
PSU_I_OUT,
PSU_P_IN,
PSU_P_OUT,
PSU_TEMP1_INPUT,
PSU_TEMP2_INPUT,
PSU_TEMP3_INPUT,
PSU_TEMP_FAULT,
PSU_TEMP_WARN,
PSU_FAN1_FAULT,
PSU_FAN1_WARN,
PSU_FAN1_DUTY_CYCLE,
PSU_FAN1_SPEED,
PSU_MFR_ID,
PSU_MFR_MODEL,
PSU_MFR_SERIAL,
PSU_PRESENT,
PSU_P_GOOD,
};
static int two_complement_to_int(u16 data, u8 valid_bit, int mask)
{
u16 valid_data = data & mask;
bool is_negative = valid_data >> (valid_bit - 1);
return is_negative ? (-(((~valid_data) & mask) + 1)) : valid_data;
}
static ssize_t set_fan_duty_cycle(struct device *dev, struct device_attribute \
*dev_attr, const char *buf, size_t count)
{
struct sensor_device_attribute *attr = to_sensor_dev_attr(dev_attr);
struct i2c_client *client = to_i2c_client(dev);
struct cs6436_54p_psu_data *data = i2c_get_clientdata(client);
int nr = (attr->index == PSU_FAN1_DUTY_CYCLE) ? 0 : 1;
long speed;
int error;
if (data->valid != 1)
{
return -ENODEV;
}
error = kstrtol(buf, 10, &speed);
if (error)
return error;
if (speed < 0 || speed > MAX_FAN_DUTY_CYCLE)
return -EINVAL;
mutex_lock(&data->update_lock);
data->fan_duty_cycle[nr] = speed;
cs6436_54p_psu_write_word(client, 0x3B + nr, data->fan_duty_cycle[nr]);
mutex_unlock(&data->update_lock);
return count;
}
static ssize_t for_linear_data(struct device *dev, struct device_attribute *dev_attr, char *buf)
{
struct sensor_device_attribute *attr = to_sensor_dev_attr(dev_attr);
struct cs6436_54p_psu_data *data = cs6436_54p_psu_update_device(dev);
u16 value = 0;
int exponent, mantissa;
int multiplier = 1000;
if (data->valid != 1)
{
return -ENODEV;
}
switch (attr->index) {
case PSU_V_IN:
value = data->v_in;
break;
case PSU_I_IN:
value = data->i_in;
break;
case PSU_I_OUT:
value = data->i_out;
break;
case PSU_P_IN:
value = data->p_in;
break;
case PSU_P_OUT:
value = data->p_out;
break;
case PSU_TEMP1_INPUT:
value = data->temp_input[0];
break;
case PSU_TEMP2_INPUT:
value = data->temp_input[1];
break;
case PSU_TEMP3_INPUT:
value = data->temp_input[2];
break;
case PSU_FAN1_DUTY_CYCLE:
multiplier = 1;
value = data->fan_duty_cycle[0];
break;
case PSU_FAN1_SPEED:
multiplier = 1;
value = data->fan_speed[0];
break;
default:
break;
}
exponent = two_complement_to_int(value >> 11, 5, 0x1f);
mantissa = two_complement_to_int(value & 0x7ff, 11, 0x7ff);
return (exponent >= 0) ? sprintf(buf, "%d\n", \
(mantissa << exponent) * multiplier) : \
sprintf(buf, "%d\n", (mantissa * multiplier) / (1 << -exponent));
}
static ssize_t for_fan_fault(struct device *dev, struct device_attribute \
*dev_attr, char *buf)
{
struct sensor_device_attribute *attr = to_sensor_dev_attr(dev_attr);
struct cs6436_54p_psu_data *data = cs6436_54p_psu_update_device(dev);
if (data->valid != 1)
{
return -ENODEV;
}
u8 shift = (attr->index == PSU_FAN1_FAULT) ? 7 : 6;
return sprintf(buf, "%d\n", data->fan_fault >> shift);
}
static ssize_t for_fan_warning(struct device *dev, struct device_attribute \
*dev_attr, char *buf)
{
struct sensor_device_attribute *attr = to_sensor_dev_attr(dev_attr);
struct cs6436_54p_psu_data *data = cs6436_54p_psu_update_device(dev);
if (data->valid != 1)
{
return -ENODEV;
}
u8 shift = (attr->index == PSU_FAN1_WARN) ? 5 : 4;
return sprintf(buf, "%d\n", data->fan_fault >> shift);
}
static ssize_t for_temp_fault(struct device *dev, struct device_attribute \
*dev_attr, char *buf)
{
struct sensor_device_attribute *attr = to_sensor_dev_attr(dev_attr);
struct cs6436_54p_psu_data *data = cs6436_54p_psu_update_device(dev);
if (data->valid != 1)
{
return -ENODEV;
}
return sprintf(buf, "%d\n", data->temp_fault >> 7);
}
static ssize_t for_temp_warning(struct device *dev, struct device_attribute \
*dev_attr, char *buf)
{
struct sensor_device_attribute *attr = to_sensor_dev_attr(dev_attr);
struct cs6436_54p_psu_data *data = cs6436_54p_psu_update_device(dev);
if (data->valid != 1)
{
return -ENODEV;
}
return sprintf(buf, "%d\n", data->temp_fault >> 6);
}
static ssize_t for_vout_data(struct device *dev, struct device_attribute \
*dev_attr, char *buf)
{
struct cs6436_54p_psu_data *data = cs6436_54p_psu_update_device(dev);
int exponent, mantissa;
int multiplier = 1000;
if (data->valid != 1)
{
return -ENODEV;
}
exponent = two_complement_to_int(data->vout_mode, 5, 0x1f);
mantissa = data->v_out;
return (exponent > 0) ? sprintf(buf, "%d\n", \
(mantissa << exponent) * multiplier) : \
sprintf(buf, "%d\n", ((mantissa * multiplier) >> (-exponent)));
}
static ssize_t for_ascii(struct device *dev, struct device_attribute \
*dev_attr, char *buf)
{
struct sensor_device_attribute *attr = to_sensor_dev_attr(dev_attr);
struct cs6436_54p_psu_data *data = cs6436_54p_psu_update_device(dev);
u8 *ptr = NULL;
if (data->valid != 1)
{
return -ENODEV;
}
switch (attr->index) {
case PSU_MFR_ID:
ptr = data->mfr_id + 1;
break;
case PSU_MFR_MODEL:
ptr = data->mfr_model + 1;
break;
case PSU_MFR_SERIAL:
ptr = data->mfr_serial + 1;
break;
default:
return 0;
}
return sprintf(buf, "%s\n", ptr);
}
static ssize_t for_status(struct device *dev, struct device_attribute *dev_attr, char *buf)
{
struct sensor_device_attribute *attr = to_sensor_dev_attr(dev_attr);
struct cs6436_54p_psu_data *data = cs6436_54p_psu_update_device(dev);
u8 *ptr = NULL;
u8 status = 0;
if (attr->index == PSU_PRESENT) {
status = data->psu_is_present;
}
else { /* PSU_POWER_GOOD */
if (!data->valid) {
return -ENODEV;
}
status = data->psu_is_good;
}
return sprintf(buf, "%d\n", status);
}
static int cs6436_54p_psu_read_byte(struct i2c_client *client, u8 reg)
{
return i2c_smbus_read_byte_data(client, reg);
}
static int cs6436_54p_psu_read_word(struct i2c_client *client, u8 reg)
{
return i2c_smbus_read_word_data(client, reg);
}
static int cs6436_54p_psu_write_word(struct i2c_client *client, u8 reg, \
u16 value)
{
union i2c_smbus_data data;
data.word = value;
return i2c_smbus_xfer(client->adapter, client->addr,
client->flags |= I2C_CLIENT_PEC,
I2C_SMBUS_WRITE, reg,
I2C_SMBUS_WORD_DATA, &data);
}
static int cs6436_54p_psu_read_block(struct i2c_client *client, u8 command, \
u8 *data, int data_len)
{
int result = i2c_smbus_read_i2c_block_data(client, command, data_len,
data);
if (unlikely(result < 0))
goto abort;
if (unlikely(result != data_len)) {
result = -EIO;
goto abort;
}
result = 0;
abort:
return result;
}
struct reg_data_byte {
u8 reg;
u8 *value;
};
struct reg_data_word {
u8 reg;
u16 *value;
};
#define EEPROM_NAME "psu_eeprom"
#define EEPROM_SIZE 256 /* 256 byte eeprom */
/* Platform dependent --- */
static ssize_t psu_eeprom_write(struct i2c_client *client, u8 command, const char *data,
int data_len)
{
int status, retry = 3;
if (data_len > I2C_SMBUS_BLOCK_MAX) {
data_len = I2C_SMBUS_BLOCK_MAX;
}
while (retry) {
status = i2c_smbus_write_i2c_block_data(client, command, data_len, data);
if (unlikely(status < 0)) {
msleep(100);
retry--;
continue;
}
break;
}
if (unlikely(status < 0)) {
return status;
}
return data_len;
}
static ssize_t psu_page_write(struct i2c_client *client,const char *buf, loff_t off, size_t count)
{
ssize_t retval = 0;
if (unlikely(!count)) {
return count;
}
/*
* Write data to chip, protecting against concurrent updates
* from this host, but not from other I2C masters.
*/
while (count) {
ssize_t status;
status = psu_eeprom_write(client, off, buf, count);
if (status <= 0) {
if (retval == 0) {
retval = status;
}
break;
}
buf += status;
off += status;
count -= status;
retval += status;
}
return retval;
}
static ssize_t psu_bin_write(struct file *filp, struct kobject *kobj,
struct bin_attribute *attr,
char *buf, loff_t off, size_t count)
{
int present;
struct cs6436_54p_psu_data *data;
ssize_t retval = 0;
struct i2c_client *client;
data = dev_get_drvdata(container_of(kobj, struct device, kobj));
client = to_i2c_client(container_of(kobj, struct device, kobj));
mutex_lock(&data->update_lock);
retval = psu_page_write(client, buf, off, count);
mutex_unlock(&data->update_lock);
return retval;
}
static ssize_t psu_eeprom_read(struct i2c_client *client, u8 command, u8 *data,
int data_len)
{
int status, retry = 3;
if (data_len > I2C_SMBUS_BLOCK_MAX) {
data_len = I2C_SMBUS_BLOCK_MAX;
}
while (retry) {
status = i2c_smbus_read_i2c_block_data(client, command, data_len, data);
if (unlikely(status < 0)) {
msleep(100);
retry--;
continue;
}
break;
}
if (unlikely(status < 0)) {
goto abort;
}
if (unlikely(status != data_len)) {
status = -EIO;
goto abort;
}
abort:
return status;
}
static ssize_t psu_page_read(struct i2c_client *client,char *buf, loff_t off, size_t count)
{
ssize_t retval = 0;
if (unlikely(!count)) {
printk("Count = 0, return");
return count;
}
/*
* Read data from chip, protecting against concurrent updates
* from this host, but not from other I2C masters.
*/
while (count) {
ssize_t status;
status = psu_eeprom_read(client, off, buf, count);
if (status <= 0) {
if (retval == 0) {
retval = status;
}
break;
}
buf += status;
off += status;
count -= status;
retval += status;
}
return retval;
}
static ssize_t psu_bin_read(struct file *filp, struct kobject *kobj,
struct bin_attribute *attr,
char *buf, loff_t off, size_t count)
{
int present;
struct cs6436_54p_psu_data *data;
struct i2c_client *client;
ssize_t retval = 0;
data = dev_get_drvdata(container_of(kobj, struct device, kobj));
client = to_i2c_client(container_of(kobj, struct device, kobj));
mutex_lock(&data->update_lock);
retval = psu_page_read(client, buf, off, count);
mutex_unlock(&data->update_lock);
return retval;
}
static int psu_sysfs_eeprom_init(struct kobject *kobj, struct bin_attribute *eeprom)
{
int err;
sysfs_bin_attr_init(eeprom);
eeprom->attr.name = EEPROM_NAME;
eeprom->attr.mode = S_IWUSR | S_IRUGO;
eeprom->read = psu_bin_read;
eeprom->write = psu_bin_write;
eeprom->size = EEPROM_SIZE;
/* Create eeprom file */
err = sysfs_create_bin_file(kobj, eeprom);
if (err) {
return err;
}
return 0;
}
static int psu_sysfs_eeprom_cleanup(struct kobject *kobj, struct bin_attribute *eeprom)
{
sysfs_remove_bin_file(kobj, eeprom);
return 0;
}
static int psu_i2c_check_functionality(struct i2c_client *client)
{
return i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA | I2C_FUNC_SMBUS_I2C_BLOCK);
}
static int psu_eeprom_probe(struct i2c_client *client, const struct i2c_device_id *dev_id)
{
int status;
struct cs6436_54p_psu_data *data;
if (!psu_i2c_check_functionality(client)) {
status = -EIO;
goto exit;
}
data = kzalloc(sizeof(*data), GFP_KERNEL);
if (!data) {
status = -ENOMEM;
goto exit;
}
i2c_set_clientdata(client, data);
data->valid = 0;
mutex_init(&data->update_lock);
data->bin = kzalloc(sizeof(struct bin_attribute), GFP_KERNEL);
if (!data->bin) {
status = -ENOMEM;
goto eeprom_bin_error;
}
/* init eeprom */
status = psu_sysfs_eeprom_init(&client->dev.kobj, data->bin);
if (status) {
status = -ENOMEM;
goto sys_init_error;
}
dev_info(&client->dev, "psu eeprom '%s'\n", client->name);
return 0;
sys_init_error:
kfree(data->bin);
eeprom_bin_error:
kfree(data);
exit:
return status;
}
static struct cs6436_54p_psu_data *cs6436_54p_psu_update_device(struct device *dev)
{
struct i2c_client *client = to_i2c_client(dev);
struct cs6436_54p_psu_data *data = i2c_get_clientdata(client);
mutex_lock(&data->update_lock);
if (time_after(jiffies, data->last_updated)) {
int i, status;
u8 command;
struct reg_data_byte regs_byte[] = {
{0x20, &data->vout_mode},
{0x81, &data->fan_fault},
{0x7d, &data->temp_fault},
};
struct reg_data_word regs_word[] = {
{0x88, &data->v_in},
{0x8b, &data->v_out},
{0x89, &data->i_in},
{0x8c, &data->i_out},
{0x96, &data->p_out},
{0x97, &data->p_in},
{0x8d, &(data->temp_input[0])},
{0x8e, &(data->temp_input[1])},
{0x3b, &(data->fan_duty_cycle[0])},
{0x90, &(data->fan_speed[0])},
};
data->valid = 1;
dev_dbg(&client->dev, "start data update\n");
/* one milliseconds from now */
data->last_updated = jiffies + HZ / 1000;
for (i = 0; i < ARRAY_SIZE(regs_byte); i++) {
status = cs6436_54p_psu_read_byte(client,
regs_byte[i].reg);
if (status < 0) {
dev_dbg(&client->dev, "reg %d, err %d\n",
regs_byte[i].reg, status);
*(regs_byte[i].value) = 0;
data->valid = 0;
} else {
*(regs_byte[i].value) = status;
}
}
for (i = 0; i < ARRAY_SIZE(regs_word); i++) {
status = cs6436_54p_psu_read_word(client,
regs_word[i].reg);
if (status < 0) {
dev_dbg(&client->dev, "reg %d, err %d\n",
regs_word[i].reg, status);
*(regs_word[i].value) = 0;
data->valid = 0;
} else {
*(regs_word[i].value) = status;
}
}
command = 0x99; /* PSU mfr_id */
status = cs6436_54p_psu_read_block(client, command,
data->mfr_id, ARRAY_SIZE(data->mfr_id) - 1);
data->mfr_id[ARRAY_SIZE(data->mfr_id) - 1] = '\0';
if (status < 0) {
dev_dbg(&client->dev, "reg %d, err %d\n", command, status);
memset(data->mfr_id, 0, sizeof(data->mfr_id));
data->valid = 0;
}
command = 0x9a; /* PSU mfr_model */
status = cs6436_54p_psu_read_block(client, command,
data->mfr_model, ARRAY_SIZE(data->mfr_model) - 1);
data->mfr_model[ARRAY_SIZE(data->mfr_model) - 1] = '\0';
if (status < 0) {
dev_dbg(&client->dev, "reg %d, err %d\n", command, status);
memset(data->mfr_model, 0, sizeof(data->mfr_id));
data->valid = 0;
}
command = 0x9e; /* PSU mfr_serial */
status = cs6436_54p_psu_read_block(client, command,
data->mfr_serial, ARRAY_SIZE(data->mfr_serial) - 1);
data->mfr_serial[ARRAY_SIZE(data->mfr_serial) - 1] = '\0';
if (status < 0) {
dev_dbg(&client->dev, "reg %d, err %d\n", command, status);
memset(data->mfr_serial, 0, sizeof(data->mfr_id));
data->valid = 0;
}
data->psu_is_present = strlen(data->mfr_id) > 1 ? 1:0;
if(data->psu_is_present)
{
data->psu_is_good = ((data->fan_fault) || (data->temp_fault))? 0:1;
}
else
{
data->valid = 0;
data->psu_is_good = 0;
}
}
mutex_unlock(&data->update_lock);
return data;
}
/* sysfs attributes for hwmon */
static SENSOR_DEVICE_ATTR(psu_v_in, S_IRUGO, for_linear_data, NULL, PSU_V_IN);
static SENSOR_DEVICE_ATTR(psu_v_out, S_IRUGO, for_vout_data, NULL, PSU_V_OUT);
static SENSOR_DEVICE_ATTR(psu_i_in, S_IRUGO, for_linear_data, NULL, PSU_I_IN);
static SENSOR_DEVICE_ATTR(psu_i_out, S_IRUGO, for_linear_data, NULL, PSU_I_OUT);
static SENSOR_DEVICE_ATTR(psu_p_in, S_IRUGO, for_linear_data, NULL, PSU_P_IN);
static SENSOR_DEVICE_ATTR(psu_p_out, S_IRUGO, for_linear_data, NULL, PSU_P_OUT);
static SENSOR_DEVICE_ATTR(psu_temp1_input, S_IRUGO, for_linear_data, NULL, PSU_TEMP1_INPUT);
static SENSOR_DEVICE_ATTR(psu_temp2_input, S_IRUGO, for_linear_data, NULL, PSU_TEMP2_INPUT);
static SENSOR_DEVICE_ATTR(psu_temp3_input, S_IRUGO, for_linear_data, NULL, PSU_TEMP3_INPUT);
static SENSOR_DEVICE_ATTR(psu_temp_fault, S_IRUGO, for_temp_fault, NULL, PSU_TEMP_FAULT);
static SENSOR_DEVICE_ATTR(psu_temp_warning, S_IRUGO, for_temp_warning, NULL, PSU_TEMP_WARN);
static SENSOR_DEVICE_ATTR(psu_fan1_fault, S_IRUGO, for_fan_fault, NULL, PSU_FAN1_FAULT);
static SENSOR_DEVICE_ATTR(psu_fan1_warning, S_IRUGO, for_fan_warning, NULL, PSU_FAN1_WARN);
static SENSOR_DEVICE_ATTR(psu_fan1_duty_cycle_percentage, S_IWUSR | S_IRUGO, for_linear_data, set_fan_duty_cycle, PSU_FAN1_DUTY_CYCLE);
static SENSOR_DEVICE_ATTR(psu_fan1_speed_rpm, S_IRUGO, for_linear_data, NULL, PSU_FAN1_SPEED);
static SENSOR_DEVICE_ATTR(psu_mfr_id, S_IRUGO, for_ascii, NULL, PSU_MFR_ID);
static SENSOR_DEVICE_ATTR(psu_mfr_model, S_IRUGO, for_ascii, NULL, PSU_MFR_MODEL);
static SENSOR_DEVICE_ATTR(psu_mfr_serial, S_IRUGO, for_ascii, NULL, PSU_MFR_SERIAL);
static SENSOR_DEVICE_ATTR(psu_present, S_IRUGO, for_status, NULL, PSU_PRESENT);
static SENSOR_DEVICE_ATTR(psu_power_good, S_IRUGO, for_status, NULL, PSU_P_GOOD);
static struct attribute *cs6436_54p_psu_attributes[] = {
&sensor_dev_attr_psu_v_in.dev_attr.attr,
&sensor_dev_attr_psu_v_out.dev_attr.attr,
&sensor_dev_attr_psu_i_in.dev_attr.attr,
&sensor_dev_attr_psu_i_out.dev_attr.attr,
&sensor_dev_attr_psu_p_in.dev_attr.attr,
&sensor_dev_attr_psu_p_out.dev_attr.attr,
&sensor_dev_attr_psu_temp1_input.dev_attr.attr,
&sensor_dev_attr_psu_temp2_input.dev_attr.attr,
&sensor_dev_attr_psu_temp3_input.dev_attr.attr,
&sensor_dev_attr_psu_temp_fault.dev_attr.attr,
&sensor_dev_attr_psu_temp_warning.dev_attr.attr,
&sensor_dev_attr_psu_fan1_fault.dev_attr.attr,
&sensor_dev_attr_psu_fan1_warning.dev_attr.attr,
&sensor_dev_attr_psu_fan1_duty_cycle_percentage.dev_attr.attr,
&sensor_dev_attr_psu_fan1_speed_rpm.dev_attr.attr,
&sensor_dev_attr_psu_mfr_id.dev_attr.attr,
&sensor_dev_attr_psu_mfr_model.dev_attr.attr,
&sensor_dev_attr_psu_mfr_serial.dev_attr.attr,
&sensor_dev_attr_psu_present.dev_attr.attr,
&sensor_dev_attr_psu_power_good.dev_attr.attr,
NULL
};
static const struct attribute_group cs6436_54p_psu_group = {
.attrs = cs6436_54p_psu_attributes,
};
static int psu_register_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
int status;
struct cs6436_54p_psu_data *data;
if (!psu_i2c_check_functionality(client)) {
status = -EIO;
goto exit;
}
data = kzalloc(sizeof(*data), GFP_KERNEL);
if (!data) {
status = -ENOMEM;
goto exit;
}
i2c_set_clientdata(client, data);
data->valid = 0;
mutex_init(&data->update_lock);
/* Register sysfs hooks */
status = sysfs_create_group(&client->dev.kobj, &cs6436_54p_psu_group);
if (status)
goto exit_sysfs_create_group;
cs6436_54p_sysfs_add_client(client);
data->hwmon_dev = hwmon_device_register(&client->dev);
if (IS_ERR(data->hwmon_dev)) {
status = PTR_ERR(data->hwmon_dev);
goto exit_hwmon_device_register;
}
/* init eeprom */
return 0;
exit_hwmon_device_register:
sysfs_remove_group(&client->dev.kobj, &cs6436_54p_psu_group);
exit_sysfs_create_group:
kfree(data);
exit:
return status;
}
static int cs6436_54p_psu_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
int status;
if((client->addr == 0x52) ||(client->addr == 0x53))
{
status = psu_eeprom_probe(client, id);
}
else if((client->addr == 0x5a) ||(client->addr == 0x5b))
{
status = psu_register_probe(client, id);
}
return status;
}
static int cs6436_54p_psu_remove(struct i2c_client *client)
{
cs6436_54p_sysfs_remove_client(client);
if((client->addr == 0x52) ||(client->addr == 0x53))
{
struct cs6436_54p_psu_data *data;
data = i2c_get_clientdata(client);
psu_sysfs_eeprom_cleanup(&client->dev.kobj,data->bin);
kfree(data);
}
else if((client->addr == 0x5a) ||(client->addr == 0x5b))
{
struct cs6436_54p_psu_data *data;
data = i2c_get_clientdata(client);
hwmon_device_unregister(data->hwmon_dev);
sysfs_remove_group(&client->dev.kobj, &cs6436_54p_psu_group);
kfree(data);
}
return 0;
}
enum psu_index
{
cs6436_54p_psu1,
cs6436_54p_psu2
};
static const struct i2c_device_id cs6436_54p_psu_id[] = {
{ "cs6436_54p_psu1", cs6436_54p_psu1 },
{ "cs6436_54p_psu2", cs6436_54p_psu2 },
{}
};
MODULE_DEVICE_TABLE(i2c, cs6436_54p_psu_id);
static struct i2c_driver cs6436_54p_psu_driver = {
.class = I2C_CLASS_HWMON,
.driver = {
.name = "cs6436_54p_psu",
},
.probe = cs6436_54p_psu_probe,
.remove = cs6436_54p_psu_remove,
.id_table = cs6436_54p_psu_id,
.address_list = normal_i2c,
};
module_i2c_driver(cs6436_54p_psu_driver);
MODULE_AUTHOR("Zhang Peng <zhangpeng@cigtech.com>");
MODULE_DESCRIPTION("cs6436_54p_psu driver");
MODULE_LICENSE("GPL");

View File

@ -0,0 +1,335 @@
/*
* A hwmon driver for the CIG cs6436-54P sysfs Module
*
* Copyright (C) 2018 Cambridge, Inc.
*
* 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.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <linux/module.h>
#include <linux/jiffies.h>
#include <linux/i2c.h>
#include <linux/hwmon.h>
#include <linux/hwmon-sysfs.h>
#include <linux/err.h>
#include <linux/mutex.h>
#include <linux/sysfs.h>
#include <linux/slab.h>
#include <linux/delay.h>
#include <linux/dmi.h>
#include <linux/uaccess.h>
#include <linux/syscalls.h>
#include <linux/kthread.h>
#include <linux/device.h>
#include <linux/platform_device.h>
#include <linux/init.h>
#include <linux/fs.h>
#include <asm/uaccess.h>
#include <asm/device.h>
#include <linux/cdev.h>
#include "i2c-algo-lpc.h"
static LIST_HEAD(sysfs_client_list);
static struct mutex list_lock;
struct sysfs_client_node {
struct i2c_client *client;
struct list_head list;
};
#define DEVICE_NAME "cigfs"
static int dev_major;
static struct class *dev_class;
static struct cdev *dev_cdev;
static struct device *dev_device;
static struct class *psu_class;
static struct class *sfp_class;
void cs6436_54p_sysfs_add_client(struct i2c_client *client)
{
struct sysfs_client_node *node = kzalloc(sizeof(struct sysfs_client_node), GFP_KERNEL);
if (!node) {
dev_dbg(&client->dev, "Can't allocate sysfs_client_node (0x%x)\n", client->addr);
return;
}
node->client = client;
mutex_lock(&list_lock);
list_add(&node->list, &sysfs_client_list);
mutex_unlock(&list_lock);
}
EXPORT_SYMBOL(cs6436_54p_sysfs_add_client);
void cs6436_54p_sysfs_remove_client(struct i2c_client *client)
{
struct list_head *list_node = NULL;
struct sysfs_client_node *sysfs_node = NULL;
int found = 0;
mutex_lock(&list_lock);
list_for_each(list_node, &sysfs_client_list)
{
sysfs_node = list_entry(list_node, struct sysfs_client_node, list);
if (IS_ERR(sysfs_node))
{
break;
}
if (sysfs_node->client == client) {
found = 1;
break;
}
}
if (found) {
list_del(list_node);
kfree(sysfs_node);
}
mutex_unlock(&list_lock);
}
EXPORT_SYMBOL(cs6436_54p_sysfs_remove_client);
struct class * cs6436_54p_sysfs_create_symclass(char *cls_name)
{
int rc = 0;
struct class *my_class;
/**************************************************************************************/
my_class = class_create(THIS_MODULE,cls_name);
if (IS_ERR(my_class)) {
pr_err("failed to create my class\n");
}
return my_class;
/**************************************************************************************/
}
void cs6436_54p_sysfs_delete_symclass(struct class *my_class)
{
/**************************************************************************************/
if (IS_ERR(my_class)) {
pr_err("Pointer is invaild\n");
}
class_destroy(my_class);
/**************************************************************************************/
}
int cs6436_54p_sysfs_create_symlink(struct class *my_class,char * driver_name,char *device_name)
{
struct list_head *list_node = NULL;
struct sysfs_client_node *sysfs_node = NULL;
int ret = -EPERM;
int rc = 0;
mutex_lock(&list_lock);
list_for_each(list_node, &sysfs_client_list)
{
sysfs_node = list_entry(list_node, struct sysfs_client_node, list);
if (!strcmp(sysfs_node->client->name,driver_name)) {
rc = sysfs_create_link(&my_class->p->subsys.kobj, &sysfs_node->client->dev.kobj,device_name);
if(rc)
{
pr_err("failed to create symlink %d\n",rc);
}
break;
}
}
mutex_unlock(&list_lock);
return ret;
}
int cs6436_54p_sysfs_delete_symlink(struct class *my_class,char * driver_name,char *device_name)
{
struct list_head *list_node = NULL;
struct sysfs_client_node *sysfs_node = NULL;
int ret = -EPERM;
int rc = 0;
mutex_lock(&list_lock);
list_for_each(list_node, &sysfs_client_list)
{
sysfs_node = list_entry(list_node, struct sysfs_client_node, list);
if (!strcmp(sysfs_node->client->name,driver_name)) {
sysfs_remove_link(&my_class->p->subsys.kobj,device_name);
break;
}
}
mutex_unlock(&list_lock);
return ret;
}
static int cs6436_54p_sysfs_open(struct inode *inode, struct file *file)
{
return 0;
}
static ssize_t cs6436_54p_sysfs_write(struct file *file, const char __user *buf, size_t count, loff_t * ppos)
{
char str[10],name[18],port[8];
int ret;
int i;
memset(str, 0, sizeof(str));
ret = copy_from_user(str, buf, count);
if (ret)
{
printk(KERN_ERR "copy_from_user fail\n");
return -EINVAL;
}
if(!strncmp(str,"start",5))
{
psu_class = cs6436_54p_sysfs_create_symclass("psu");
cs6436_54p_sysfs_create_symlink(psu_class,"cs6436_54p_psu1","psu1");
cs6436_54p_sysfs_create_symlink(psu_class,"cs6436_54p_psu2","psu2");
sfp_class = cs6436_54p_sysfs_create_symclass("swps");
for(i = 1; i <= 48;i++)
{
memset(name,0xff,sizeof(name));
memset(port,0xff,sizeof(port));
snprintf(name,sizeof(name),"cs6436_54p_sfp%d",i);
snprintf(port,sizeof(port),"port%d",i);
cs6436_54p_sysfs_create_symlink(sfp_class,name,port);
}
}
else if(!strncmp(str,"stop",4))
{
cs6436_54p_sysfs_delete_symlink(psu_class,"cs6436_54p_psu1","psu1");
cs6436_54p_sysfs_delete_symlink(psu_class,"cs6436_54p_psu2","psu2");
cs6436_54p_sysfs_delete_symclass(psu_class);
for(i = 1; i <= 48;i++)
{
memset(name,0xff,sizeof(name));
memset(port,0xff,sizeof(port));
snprintf(name,sizeof(name),"cs6436_54p_sfp%d",i);
snprintf(port,sizeof(port),"port%d",i);
cs6436_54p_sysfs_delete_symlink(sfp_class,name,port);
}
cs6436_54p_sysfs_delete_symclass(sfp_class);
}
return count;
}
static struct file_operations cs6436_54p_sysfs_fops = {
.owner = THIS_MODULE,
.open = cs6436_54p_sysfs_open,
.write = cs6436_54p_sysfs_write,
};
static int __init cs6436_54p_sysfs_init(void)
{
int result = 0;
int err = 0;
dev_t dev = MKDEV(dev_major, 0);
if (dev_major)
result = register_chrdev_region(dev, 1, DEVICE_NAME);
else {
result = alloc_chrdev_region(&dev, 0, 1, DEVICE_NAME);
dev_major = MAJOR(dev);
}
if (result < 0)
{
printk("unable to get major %d\n", dev_major);
err= -EINVAL;
}
printk("get major is %d\n", dev_major);
if (dev_major == 0)
dev_major = result;
dev_cdev= kmalloc(sizeof(struct cdev), GFP_KERNEL);
if(IS_ERR(dev_cdev)) {
err= -ENOMEM;
}
cdev_init(dev_cdev, &cs6436_54p_sysfs_fops);
dev_cdev->owner = THIS_MODULE;
dev_cdev->ops = &cs6436_54p_sysfs_fops;
err = cdev_add(dev_cdev, dev, 1);
if (err)
{
printk("error %d add fpga ", err);
goto err_malloc;
}
dev_class = class_create(THIS_MODULE, DEVICE_NAME);
if (IS_ERR(dev_class))
{
printk("Err:failed in creating class.\n");
goto err_cdev_add;
}
dev_device = device_create(dev_class, NULL, MKDEV(dev_major, 0), NULL, DEVICE_NAME);
if (IS_ERR(dev_device))
{
printk("Err:failed in creating device.\n");
goto err_class_crt;
}
mutex_init(&list_lock);
return err;
err_class_crt:
cdev_del(dev_cdev);
err_cdev_add:
kfree(dev_cdev);
err_malloc:
unregister_chrdev_region(MKDEV(dev_major,0), 1);
return err;
}
static void __exit cs6436_54p_sysfs_exit(void)
{
cdev_del(dev_cdev);
printk("cdev_del ok\n");
device_destroy(dev_class, MKDEV(dev_major, 0));
class_destroy(dev_class);
if(dev_cdev != NULL)
kfree(dev_cdev);
unregister_chrdev_region(MKDEV(dev_major, 0), 1);
printk("cs6436_54p_sysfs_exit...\r\n");
}
MODULE_AUTHOR("Zhang Peng <zhangpeng@cigtech.com>");
MODULE_DESCRIPTION("cs6436-54p-sysfs driver");
MODULE_LICENSE("GPL");
module_init(cs6436_54p_sysfs_init);
module_exit(cs6436_54p_sysfs_exit);

View File

@ -0,0 +1,13 @@
[Unit]
Description=Cig CS6436-54P Platform initialization service
Before=pmon.service
DefaultDependencies=no
[Service]
Type=oneshot
ExecStart=/usr/local/bin/cig_cs6436_util.py install
ExecStop=/usr/local/bin/cig_cs6436_util.py clean
RemainAfterExit=yes
[Install]
WantedBy=multi-user.target

View File

@ -0,0 +1,15 @@
[Unit]
Description=Cig CS6436-54P Platform miscellaneous service
After=cs6436-platform-init.service
DefaultDependencies=no
[Service]
ExecStart=/usr/local/bin/cig_cs6436_misc.py
KillSignal=SIGKILL
SuccessExitStatus=SIGKILL
# Resource Limitations
LimitCORE=infinity
[Install]
WantedBy=multi-user.target

View File

@ -0,0 +1,15 @@
#!/usr/bin/env python
import os
import sys
from setuptools import setup
os.listdir
setup(
name='cs6436-54p',
version='1.0.0',
description='Module to initialize Cig CS6436-54P platforms',
packages=['cs6436-54p'],
package_dir={'cs6436-54p': 'cs6436-54p/classes'},
)

View File

@ -0,0 +1,574 @@
#!/usr/bin/env python
#
# Copyright (C) 2018 Cambridge, Inc.
#
# 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 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
import os
import commands
import sys, getopt
import logging
import re
import time
import datetime
from collections import namedtuple
from threading import Thread
DEBUG = False
i2c_prefix = '/sys/bus/i2c/devices/'
leds_prefix = '/sys/devices/platform/cs6436_54p_led/leds/'
fans_prefix = '/sys/devices/platform/cs6436_54p_fan/'
fansdir_prefix = fans_prefix + 'fan{}_direction'
ageing_controlfile = '/etc/sonic/agcontrol'
AGFlag = 0
platform_misc_log = '/var/log/platform_misc.log'
misclogger = logging.getLogger('platform_misc')
misclogger.setLevel(logging.INFO)
miscformatter = logging.Formatter('%(asctime)s-%(levelname)s-%(message)s')
if not os.path.isfile(platform_misc_log):
try:
os.mknod(platform_misc_log)
except:
print 'Failed to creat platform_misc.log'
fileHandler = logging.FileHandler(platform_misc_log)
fileHandler.setLevel(logging.INFO)
fileHandler.setFormatter(miscformatter)
misclogger.addHandler(fileHandler)
starttime = datetime.datetime.now()
IsGetlswt = 0
coretemp_prefix = '/sys/class/hwmon/hwmon1/'
coretemp_ps = []
psu1_p = '/sys/bus/i2c/devices/5-005a/psu_present'
psu2_p = '/sys/bus/i2c/devices/5-005b/psu_present'
psu1_d = '/sys/bus/i2c/devices/5-0052/psu_eeprom'
psu2_d = '/sys/bus/i2c/devices/5-0053/psu_eeprom'
psu1led_d = leds_prefix + 'cs6436_54p_led::psu1/brightness'
psu2led_d = leds_prefix + 'cs6436_54p_led::psu2/brightness'
cs6436_ledpath = {'fan':leds_prefix + 'cs6436_54p_led::fan/brightness',
'fan1':leds_prefix + 'cs6436_54p_led::fan1/brightness',
'fan2':leds_prefix + 'cs6436_54p_led::fan2/brightness',
'fan3':leds_prefix + 'cs6436_54p_led::fan3/brightness',
'fan4':leds_prefix + 'cs6436_54p_led::fan4/brightness',
'fan5':leds_prefix + 'cs6436_54p_led::fan5/brightness',
'psu1':leds_prefix + 'cs6436_54p_led::psu1/brightness',
'psu2':leds_prefix + 'cs6436_54p_led::psu2/brightness',
'sys':leds_prefix + 'cs6436_54p_led::sys/brightness'}
def system_read_filestr(node):
with open(node, 'r') as f:
try:
str = f.read()
except IOError as e:
misclogger.error('Failed to get node, str={}'.format(node))
return "0"
return str
def system_bright_leds(dev, colour):
global AGFlag
if AGFlag == 1:
return
cmd = 'echo {} > {}'.format(colour, dev)
log_os_system(cmd, 1)
return
'''
1: front in tail out
0: front out tail in
'''
def system_getpsu_direction(dev):
try:
with open(dev) as f:
f.seek(0x30)
str = f.read(2)
except IOError as e:
misclogger.error('Failed to get psu eep')
return 1
if str == 'AA': ## front in tail out
return 1
elif str == 'RA':## tail in front out
return 0
else:
misclogger.error('Failed to get psu eep, str={}'.format(str))
return -1
def system_get_cputype():
cmdretfd = os.popen("lscpu | grep 'Model name'")
retstring = cmdretfd.read()
endindex = retstring.find('@') - 1
startindex = retstring[:endindex].rfind(' ') + 1
cputype = retstring[startindex:endindex]
return cputype
def system_init_coretemppath():
global coretemp_ps
cmdstr = "ls {} | grep 'input'".format(coretemp_prefix)
cmdretfd = os.popen(cmdstr)
coretemppss = cmdretfd.read().splitlines()
if len(coretemppss) < 3:
cputype = system_get_cputype()
misclogger.error('Failed to init core temperature path.'
' cpu type = {}, num thermal = {}'.format(cputype, len(coretemp_ps)))
return 1
for i in range(0,3):
coretemp_ps.append(coretemp_prefix + coretemppss[i])
print coretemp_ps
return 0
class cs6436_fanattr:
def __init__(self, name):
self.name = name
self.direction = 0
self.direction_p = ''
self.rear = 0
self.rear_p = ''
self.front = 0
self.front_p = ''
self.fault = 0
self.fault_p = ''
self.status = 0
self.setpath()
self.updatedevice()
return
def setpath(self):
self.direction_p = fans_prefix + '{}_direction'.format(self.name)
self.rear_p = fans_prefix + '{}_rear_speed_rpm'.format(self.name)
self.front_p = fans_prefix + '{}_front_speed_rpm'.format(self.name)
self.fault_p = fans_prefix + '{}_fault'.format(self.name)
return
def updatedevice(self):
self.direction = int(system_read_filestr(self.direction_p))
self.rear = int(system_read_filestr(self.rear_p))
self.front = int(system_read_filestr(self.front_p))
self.fault = int(system_read_filestr(self.fault_p))
return
def checkspeedrpm(self, speedrpm):
frontrpmexp = speedrpm * 21000 / 100
rearrpmexp = speedrpm * 19000 / 100
deviationfront = abs(frontrpmexp - self.front) / float(frontrpmexp)
deviationrear = abs(rearrpmexp - self.rear) / float(rearrpmexp)
if deviationfront < 0.3 and deviationrear < 0.3:
return 0
else:
misclogger.error(':{} speed wrong. frontexp is {}, but rpm is {}.rearexp is {}, but rpm is {}'.format(self.name, frontrpmexp, self.front, rearrpmexp, self.rear))
return 1
def checkstatus(self, speedrpm, totaldirct):
speedstatus = self.checkspeedrpm(speedrpm)
if self.direction != totaldirct:
self.status = 1
misclogger.error(':{} direction = {}.fan direction is not ok.'.format(self.name, self.direction))
elif speedstatus != 0:
self.status = 1
elif self.fault != 0:
misclogger.error(':{} fault.'.format(self.name))
self.status = 1
else:
self.status = 0
if self.status == 1:
system_bright_leds(cs6436_ledpath[self.name], 3)
else:
system_bright_leds(cs6436_ledpath[self.name], 1)
return self.status
cs6436_fanattrnodes = []
class cs6436_psuattr:
def __init__(self, name):
self.name = name
self.direction = 0
self.direction_p = ''
self.present = 0
self.present_p = ''
self.status = 0
self.setpath()
self.updatepresent()
self.updatedirection()
return
def setpath(self):
if self.name == 'psu1':
self.present_p = psu1_p
self.direction_p = psu1_d
if self.name == 'psu2':
self.present_p = psu2_p
self.direction_p = psu2_d
return
def updatepresent(self):
self.present = int(system_read_filestr(self.present_p))
return
def updatedirection(self):
if self.present == 1:
self.direction = system_getpsu_direction(self.direction_p)
else:
self.direction = 2
return
def checkstatus(self, totaldirct):
if self.present != 1:
self.status = 1
misclogger.error(':{} not present.'.format(self.name))
elif self.direction == 2:
self.status = 0
misclogger.info(':{} direction need to be update.'.format(self.name))
elif self.direction != totaldirct:
self.status = 1
misclogger.info(':{} direction is wrong.'.format(self.name))
else:
self.status = 0
if self.status == 1:
system_bright_leds(cs6436_ledpath[self.name], 3)
else:
system_bright_leds(cs6436_ledpath[self.name], 1)
return self.status
cs6436_psuattrnodes = []
def my_log(txt):
if DEBUG == True:
print "[ROY]"+txt
return
def device_exist():
ret1, log = log_os_system("ls "+i2c_prefix+"5-005a", 0)
ret2, log = log_os_system("ls "+i2c_prefix+"5-005b", 0)
ret3, log = log_os_system("ls "+leds_prefix+"cs6436_54p_led*", 0)
return not(ret1 or ret2 or ret3)
def log_os_system(cmd, show):
logging.info('Run :'+cmd)
status, output = commands.getstatusoutput(cmd)
my_log (cmd +"with result:" + str(status))
my_log (" output:"+output)
if status:
logging.info('Failed :'+cmd)
if show:
print('Failed :'+cmd)
return status, output
def system_get_coretemp():
temp1 = system_read_filestr(coretemp_ps[0]).strip()
temp2 = system_read_filestr(coretemp_ps[1]).strip()
temp3 = system_read_filestr(coretemp_ps[2]).strip()
return int(temp1), int(temp2), int(temp3)
def system_get_boardtemp():
for i in range(0,16):
temp1path = "/sys/bus/i2c/devices/5-004a/hwmon/hwmon%d/temp1_input" % i
if os.access(temp1path, os.F_OK):
break
for i in range(0,16):
temp2path = "/sys/bus/i2c/devices/5-004b/hwmon/hwmon%d/temp1_input" % i
if os.access(temp2path, os.F_OK):
break
temp1 = system_read_filestr(temp1path).strip()
temp2 = system_read_filestr(temp2path).strip()
return int(temp1), int(temp2)
def system_get_lswtemp():
global IsGetlswt
global starttime
if IsGetlswt == 0:
now = datetime.datetime.now()
misclogger.info("time wait.")
misclogger.info("start = {}, now = {}.".format(starttime, now))
if (now - starttime).seconds > 150:
misclogger.info("time = ".format((now - starttime).seconds))
IsGetlswt = 1
return 25
# chp = subprocess.Popen("docker ps --filter name=syncd", shell=True, stdout=subprocess.PIPE)
# if chp.poll() == None:
# misclogger.info("No subp.")
# chp.kill()
#
# return 25
# retstring = chp.stdout.read()
# chp.kill()
# if 'Up' not in retstring:
# misclogger.info("lsw not up.")
#
# return 25
status, output = log_os_system('npx_diag swc show temperature', 1)
if status:
misclogger.error('failed to show lsw temperature')
return 25
output = output.strip()
if output.find("it 0, temperature ") > 0:
startindex = output.find('temperature') + len('temperature') + 1
endindex = output[startindex:].find(" ")
endindex = startindex + endindex
temp = output[startindex:endindex]
b = temp.find('.')
if b > 0:
temp=temp[:b]
temp = int(temp)
else:
misclogger.error("Failed to get temperature.")
temp = 0
return int(temp)
def system_monitor_temperature():
ctemp1, ctemp2, ctemp3 = system_get_coretemp()
btemp1, btemp2 = system_get_boardtemp()
ltemp = system_get_lswtemp()
fan_speed_str = system_cs6436_getfanexspeed()
fan_speed = int(fan_speed_str)
policy = 'stay'
pos = 0
#speed c1 c2 c3 b1 b2 lsw
fan_policy_up = ([30, 40000, 40000, 40000, 42000, 35000, 95],
[40, 44000, 44000, 44000, 44000, 39000, 96],
[50, 49000, 49000, 49000, 47000, 44000, 91],
[60, 52000, 52000, 52000, 51500, 47500, 92],
[70, 53000, 53000, 53000, 52000, 49000, 93],
[100,999999,999999,999999,999999,999999,999])
fan_policy_down=([30, 0, 0, 0, 0, 0, 0],
[40, 34000, 34000, 34000, 34000, 30000, 80],
[50, 38000, 38000, 38000, 37000, 33000, 81],
[60, 44000, 44000, 44000, 43000, 39000, 84],
[70, 44000, 44000, 44000, 43000, 40000, 84],
[100, 48000, 48000, 48000, 46000, 42000, 85],)
for policytable in fan_policy_up:
if fan_speed <= policytable[0]:
break
pos = pos + 1
fan_speed = policytable[0]
if (ctemp1 < policytable[1]) and (ctemp2 < policytable[2]) and (ctemp3 < policytable[3]) and (btemp1 < policytable[4]) and (btemp2 < policytable[5]) and (ltemp < policytable[6]):
policy = 'stay'
policytable = fan_policy_down[pos]
if (ctemp1 < policytable[1]) and (ctemp2 < policytable[2]) and (ctemp3 < policytable[3]) and (btemp1 < policytable[4]) and (btemp2 < policytable[5]) and (ltemp < policytable[6]):
policy = 'down'
else:
policy = 'up'
if policy == 'up':
misclogger.info("speed = %d." % fan_speed)
misclogger.info("core1 = %d, core2 = %d, core3 = %d." % (ctemp1, ctemp2, ctemp3))
misclogger.info("board1 = %d, board2 = %d." % (btemp1, btemp2))
misclogger.info("lsw = %d" % ltemp)
fan_speed = fan_policy_down[pos + 1][0]
misclogger.info("fan policy: up. speedexp = {}".format(fan_speed))
if policy == 'stay':
fan_speed = fan_policy_down[pos]
return
if policy == 'down':
misclogger.info("speed = %d." % fan_speed)
misclogger.info("core1 = %d, core2 = %d, core3 = %d." % (ctemp1, ctemp2, ctemp3))
misclogger.info("board1 = %d, board2 = %d." % (btemp1, btemp2))
misclogger.info("lsw = %d" % ltemp)
fan_speed = fan_policy_down[pos - 1][0]
misclogger.info("fan policy: down.speedexp = {}".format(fan_speed))
cmd = "echo {} > /sys/devices/platform/cs6436_54p_fan/fan_duty_cycle_percentage".format(fan_speed)
status, output = log_os_system(cmd, 1)
if status:
misclogger.error("set fan speed fault")
return
def system_cs6436_setfanexspeed(num):
fanspeednode = fans_prefix + 'fan_duty_cycle_percentage'
numstr = str(num)
with open(fanspeednode, 'w') as f:
f.write(numstr)
def system_cs6436_getfanexspeed():
fanspeednode = fans_prefix + 'fan_duty_cycle_percentage'
fanspeedstr = system_read_filestr(fanspeednode)
fanspeedexp = int(fanspeedstr)
return fanspeedexp
def system_cs6436_getdirection():
global cs6436_fanattrnodes
direction = 0
for fan in cs6436_fanattrnodes:
direction = direction + fan.direction
if direction > 2:
direction = 1
else:
direction = 0
return direction
def system_check_psusdirection():
global cs6436_psuattrnodes
cs6436totaldirct = system_cs6436_getdirection()
psutatus = 0
for psu in cs6436_psuattrnodes:
psu.updatedirection()
psu.checkstatus(cs6436totaldirct)
psutatus = psu.status + psutatus
return (psutatus != 0)
def system_check_psuspresent():
global cs6436_psuattrnodes
cs6436totaldirct = system_cs6436_getdirection()
psutatus = 0
for psu in cs6436_psuattrnodes:
psu.updatepresent()
psu.checkstatus(cs6436totaldirct)
psutatus = psu.status + psutatus
return (psutatus != 0)
def system_check_fansstate():
global cs6436_fanattrnodes
global cs6436_ledpath
cs6436totaldirct = system_cs6436_getdirection()
fanstatus = 0
fanexspeed = 0
fanexspeed = system_cs6436_getfanexspeed()
for fan in cs6436_fanattrnodes:
fan.updatedevice()
fan.checkstatus(fanexspeed, cs6436totaldirct)
fanstatus = fanstatus + fan.status
if fanstatus > 0:
misclogger.error(':fan error.set fans speed 100.')
system_cs6436_setfanexspeed(100)
system_bright_leds(cs6436_ledpath['fan'], 3)
else:
system_bright_leds(cs6436_ledpath['fan'], 1)
return (fanstatus != 0)
def system_misc_polling(threadName,delay):
for count in range(1,5):
if device_exist() == False:
time.sleep(delay+3)
print "%s: %s, count=%d" % ( threadName, time.ctime(time.time()), count)
else:
break
if count == 4:
return
status, output = log_os_system("echo 1 > /sys/devices/platform/cs6436_54p_led/leds/cs6436_54p_led::sys/brightness", 1)
status, output = log_os_system("hwconfig -cfp 1", 1)
global AGFlag
if os.access(ageing_controlfile, os.F_OK):
AGFlag = 1
else:
AGFlag = 0
os.system('csw_daemon &')
global cs6436_fanattrnodes
global cs6436_psuattrnodes
for num in range(1,6):
name = 'fan{}'.format(num)
fannode = cs6436_fanattr(name)
cs6436_fanattrnodes.append(fannode)
for num in range(1,3):
name = 'psu{}'.format(num)
psunode = cs6436_psuattr(name)
cs6436_psuattrnodes.append(psunode)
tempcontrol = system_init_coretemppath()
misclogger.info("%s: %s misc start." % ( threadName, time.ctime(time.time())))
count = 0
while 1:
count = count + 1
ret = system_check_psuspresent()
ret = system_check_fansstate()
if count % 10 == 0:
misclogger.info(": adjust fans and check psu direction.")
system_check_psusdirection()
if tempcontrol == 0:
system_monitor_temperature()
count = 0
time.sleep(delay)
return
if __name__ == '__main__':
target=system_misc_polling("Thread-misc",10)

View File

@ -0,0 +1,565 @@
#!/usr/bin/env python
#
# Copyright (C) 2018 Cambridge, Inc.
#
# 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 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
"""
Usage: %(scriptName)s [options] command object
options:
-h | --help : this help message
-d | --debug : run with debug mode
-f | --force : ignore error during installation or clean
command:
install : install drivers and generate related sysfs nodes
clean : uninstall drivers and remove related sysfs nodes
show : show all systen status
sff : dump SFP eeprom
set : change board setting with fan|led|sfp
"""
import os
import commands
import sys, getopt
import logging
import re
import time
from collections import namedtuple
PROJECT_NAME = 'cs6436_54p'
version = '0.1.1'
verbose = False
DEBUG = False
args = []
ALL_DEVICE = {}
DEVICE_NO = {'led':9, 'fan':5, 'thermal':4, 'psu':2, 'sfp':54}
FORCE = 0
CPU_TYPE = 'C3308'
if DEBUG == True:
print sys.argv[0]
print 'ARGV :', sys.argv[1:]
def main():
global DEBUG
global args
global FORCE
if len(sys.argv)<2:
show_help()
options, args = getopt.getopt(sys.argv[1:], 'hdf', ['help',
'debug',
'force',
])
if DEBUG == True:
print options
print args
print len(sys.argv)
for opt, arg in options:
if opt in ('-h', '--help'):
show_help()
elif opt in ('-d', '--debug'):
DEBUG = True
logging.basicConfig(level=logging.INFO)
elif opt in ('-f', '--force'):
FORCE = 1
else:
logging.info('no option')
for arg in args:
if arg == 'install':
do_install()
elif arg == 'clean':
do_uninstall()
elif arg == 'show':
device_traversal()
elif arg == 'sff':
if len(args)!=2:
show_eeprom_help()
elif int(args[1]) ==0 or int(args[1]) > DEVICE_NO['sfp']:
show_eeprom_help()
else:
show_eeprom(args[1])
return
elif arg == 'set':
if len(args)<3:
show_set_help()
else:
set_device(args[1:])
return
else:
show_help()
return 0
def show_help():
print __doc__ % {'scriptName' : sys.argv[0].split("/")[-1]}
sys.exit(0)
def show_set_help():
cmd = sys.argv[0].split("/")[-1]+ " " + args[0]
print cmd +" [led|sfp|fan]"
print " use \""+ cmd + " led 0-4 \" to set led color"
print " use \""+ cmd + " fan 0-100\" to set fan duty percetage"
print " use \""+ cmd + " sfp 1-54 {0|1}\" to set sfp# tx_disable"
sys.exit(0)
def show_eeprom_help():
cmd = sys.argv[0].split("/")[-1]+ " " + args[0]
print " use \""+ cmd + " 1-54 \" to dump sfp# eeprom"
sys.exit(0)
def my_log(txt):
if DEBUG == True:
print "[ROY]"+txt
return
def log_os_system(cmd, show):
logging.info('Run :'+cmd)
status, output = commands.getstatusoutput(cmd)
my_log (cmd +"with result:" + str(status))
my_log (" output:"+output)
if status:
logging.info('Failed :'+cmd)
if show:
print('Failed :'+cmd)
return status, output
def driver_check():
for count in range(1,5):
time.sleep(1)
ret, lsmod = log_os_system("lsmod| grep i2c_i801", 0)
if len(lsmod) > 2:
log_os_system("rmmod i2c_i801", 0)
break
ret, lsmod = log_os_system("lsmod| grep i2c_designware_platform", 0)
if len(lsmod) > 2:
log_os_system("rmmod i2c_designware_platform", 0)
log_os_system("modprobe i2c-designware-platform", 0)
ret, lsmod = log_os_system("lsmod| grep cig", 0)
logging.info('mods:'+lsmod)
if len(lsmod) ==0:
return False
return True
kos = [
'depmod',
'modprobe i2c_dev',
'modprobe i2c_mux_pca954x force_deselect_on_exit=1',
'modprobe x86-64-cig-cs6436-54p-sysfs ' ,
'modprobe x86-64-cig-cs6436-54p-cpld ' ,
'modprobe x86-64-cig-cs6436-54p-fan' ,
'modprobe x86-64-cig-cs6436-54p-psu' ,
'modprobe x86-64-cig-cs6436-54p-sfp' ,
'modprobe x86-64-cig-cs6436-54p-led' ]
def driver_install():
global FORCE
for i in range(0,len(kos)):
if i == 4:
ret, CPU_TYPE = log_os_system("cat /proc/cpuinfo | grep \"model name\" | cut -b 32-39 | head -n 1", 0)
if CPU_TYPE=='i3-6100U':
kos[i] =kos[i] + 'board_id=1'
ret, CPU_TYPE = log_os_system("cat /proc/cpuinfo | grep \"model name\" | cut -b 36-40 | head -n 1", 0)
if CPU_TYPE=='C3758' or CPU_TYPE=='C3308':
kos[i] =kos[i] + 'board_id=2'
status, output = log_os_system(kos[i], 1)
if status:
if FORCE == 0:
return status
return 0
def driver_uninstall():
global FORCE
for i in range(0,len(kos)):
rm = kos[-(i+1)].replace("modprobe", "modprobe -rq")
rm = rm.replace("insmod", "rmmod")
status, output = log_os_system(rm, 1)
if status:
if FORCE == 0:
return status
return 0
led_prefix ='/sys/class/leds/'+PROJECT_NAME+'_led::'
hwmon_types = {'led': ['sys','fan','fan1','fan2','fan3','fan4','fan5','psu1','psu2']}
hwmon_nodes = {'led': ['brightness'] }
hwmon_prefix ={'led': led_prefix}
i2c_prefix = '/sys/bus/i2c/devices/'
i2c_bus = {'thermal': ['4-0048','4-0049', '5-004a', '5-004b'] ,
'psu': ['5-005a','5-005b'],
'sfp': ['-0050']}
i2c_nodes = {'thermal': ['hwmon/hwmon*/temp1_input'] ,
'psu': ['psu_present ', 'psu_power_good'] ,
'sfp': ['sfp_is_present ', 'sfp_tx_disable']}
fan_prefix ='/sys/bus/platform/devices/'+PROJECT_NAME+'_fan'
fan_types = {'fan': ['fan1','fan2', 'fan3', 'fan4', 'fan5']}
fan_nodes = {'fan': ['state', 'front_speed_rpm', 'rear_speed_rpm', 'fault']}
sfp_map = [8,9,10,11,12,13,14,15,16,
17,18,19,20,21,22,23,24,25,26,
27,28,29,30,31,32,33,34,35,36,
37,38,39,40,41,42,43,44,45,46,
47,48,49,50,51,52,53,54,55,56,
57,60,61,62,63]
mknod =[
'echo pca9548 0x71 > /sys/bus/i2c/devices/i2c-2/new_device',
'echo pca9548 0x72 > /sys/bus/i2c/devices/i2c-2/new_device',
'echo pca9548 0x73 > /sys/bus/i2c/devices/i2c-2/new_device',
'echo pca9548 0x74 > /sys/bus/i2c/devices/i2c-2/new_device',
'echo pca9548 0x75 > /sys/bus/i2c/devices/i2c-3/new_device',
'echo pca9548 0x76 > /sys/bus/i2c/devices/i2c-3/new_device',
'echo pca9548 0x77 > /sys/bus/i2c/devices/i2c-3/new_device',
'echo lm75 0x48 > /sys/bus/i2c/devices/i2c-4/new_device',
'echo lm75 0x49 > /sys/bus/i2c/devices/i2c-4/new_device',
'echo lm75 0x4a > /sys/bus/i2c/devices/i2c-5/new_device',
'echo lm75 0x4b > /sys/bus/i2c/devices/i2c-5/new_device',
'echo cs6436_54p_psu1 0x5a > /sys/bus/i2c/devices/i2c-5/new_device',
'echo cs6436_54p_psu2 0x5b > /sys/bus/i2c/devices/i2c-5/new_device',
'echo cs6436_54p_psu1 0x52 > /sys/bus/i2c/devices/i2c-5/new_device',
'echo cs6436_54p_psu2 0x53 > /sys/bus/i2c/devices/i2c-5/new_device',
'echo 24c128 0x57 > /sys/bus/i2c/devices/i2c-7/new_device']
port = 0
def device_install():
global FORCE
global port
for i in range(0,len(mknod)):
#all nodes need times to built new i2c buses
time.sleep(1)
status, output = log_os_system(mknod[i], 1)
if status:
print output
if FORCE == 0:
return status
for i in range(0,len(sfp_map)):
if (i == 50):
port = port + 3
else:
port = port + 1
status, output =log_os_system("echo cs6436_54p_sfp"+str(port)+" 0x50 > /sys/bus/i2c/devices/i2c-"+str(sfp_map[i])+"/new_device", 1)
if status:
print output
if FORCE == 0:
return status
if port <= 48:
status, output =log_os_system("echo cs6436_54p_sfp"+str(port)+" 0x51 > /sys/bus/i2c/devices/i2c-"+str(sfp_map[i])+"/new_device", 1)
if status:
print output
if FORCE == 0:
return status
return
def device_uninstall():
global FORCE
for i in range(0,len(sfp_map)):
target = "/sys/bus/i2c/devices/i2c-"+str(sfp_map[i])+"/delete_device"
status, output =log_os_system("echo 0x50 > "+ target, 1)
if status:
print output
if FORCE == 0:
return status
nodelist = mknod
for i in range(len(nodelist)):
target = nodelist[-(i+1)]
temp = target.split()
del temp[1]
temp[-1] = temp[-1].replace('new_device', 'delete_device')
status, output = log_os_system(" ".join(temp), 1)
if status:
print output
if FORCE == 0:
return status
return
def system_ready():
if driver_check() == False:
return False
if not device_exist():
return False
return True
def do_install():
print "Checking system...."
if driver_check() == False:
print "No driver, installing...."
status = driver_install()
if status:
if FORCE == 0:
return status
else:
print PROJECT_NAME.upper()+" drivers detected...."
if not device_exist():
print "No device, installing...."
status = device_install()
if status:
if FORCE == 0:
return status
else:
print PROJECT_NAME.upper()+" devices detected...."
return
def do_uninstall():
print "Checking system...."
if not device_exist():
print PROJECT_NAME.upper() +" has no device installed...."
else:
print "Removing device...."
status = device_uninstall()
if status:
if FORCE == 0:
return status
if driver_check()== False :
print PROJECT_NAME.upper() +" has no driver installed...."
else:
print "Removing installed driver...."
status = driver_uninstall()
if status:
if FORCE == 0:
return status
return
def devices_info():
global DEVICE_NO
global ALL_DEVICE
global i2c_bus, hwmon_types, fan_types
for key in DEVICE_NO:
ALL_DEVICE[key]= {}
for i in range(0,DEVICE_NO[key]):
ALL_DEVICE[key][key+str(i+1)] = []
for key in i2c_bus:
buses = i2c_bus[key]
nodes = i2c_nodes[key]
for i in range(0,len(buses)):
for j in range(0,len(nodes)):
if 'sfp' == key:
for k in range(0,DEVICE_NO[key]):
node = key+str(k+1)
path = i2c_prefix+ str(sfp_map[k])+ buses[i]+"/"+ nodes[j]
my_log(node+": "+ path)
ALL_DEVICE[key][node].append(path)
else:
node = key+str(i+1)
path = i2c_prefix+ buses[i]+"/"+ nodes[j]
my_log(node+": "+ path)
ALL_DEVICE[key][node].append(path)
for key in hwmon_types:
itypes = hwmon_types[key]
nodes = hwmon_nodes[key]
for i in range(0,len(itypes)):
for j in range(0,len(nodes)):
node = key+"_"+itypes[i]
path = hwmon_prefix[key]+ itypes[i]+"/"+ nodes[j]
my_log(node+": "+ path)
ALL_DEVICE[key][ key+str(i+1)].append(path)
for key in fan_types:
itypes = fan_types[key]
nodes = fan_nodes[key]
for i in range(0,len(itypes)):
for j in range(0,len(nodes)):
node = key+"_"+itypes[i]
path = fan_prefix+"/"+ itypes[i]+"_"+ nodes[j]
my_log(node+": "+ path)
ALL_DEVICE[key][ key+str(i+1)].append(path)
#show dict all in the order
if DEBUG == True:
for i in sorted(ALL_DEVICE.keys()):
print(i+": ")
for j in sorted(ALL_DEVICE[i].keys()):
print(" "+j)
for k in (ALL_DEVICE[i][j]):
print(" "+" "+k)
return
def show_eeprom(index):
if system_ready()==False:
print("System's not ready.")
print("Please install first!")
return
if len(ALL_DEVICE)==0:
devices_info()
node = ALL_DEVICE['sfp'] ['sfp'+str(index)][0]
node = node.replace(node.split("/")[-1], 'sfp_eeprom')
# check if got hexdump command in current environment
ret, log = log_os_system("which hexdump", 0)
ret, log2 = log_os_system("which busybox hexdump", 0)
if len(log):
hex_cmd = 'hexdump'
elif len(log2):
hex_cmd = ' busybox hexdump'
else:
log = 'Failed : no hexdump cmd!!'
logging.info(log)
print log
return 1
print node + ":"
ret, log = log_os_system("cat "+node+"| "+hex_cmd+" -C", 1)
if ret==0:
print log
else:
print "**********device no found**********"
return
def set_device(args):
global DEVICE_NO
global ALL_DEVICE
if system_ready()==False:
print("System's not ready.")
print("Please install first!")
return
if len(ALL_DEVICE)==0:
devices_info()
if args[0]=='led':
if int(args[1])>4:
show_set_help()
return
#print ALL_DEVICE['led']
for i in range(0,len(ALL_DEVICE['led'])):
for k in (ALL_DEVICE['led']['led'+str(i+1)]):
ret, log = log_os_system("echo "+args[1]+" >"+k, 1)
if ret:
return ret
elif args[0]=='fan':
if int(args[1])>100:
show_set_help()
return
#print ALL_DEVICE['fan']
#fan1~6 is all fine, all fan share same setting
node = ALL_DEVICE['fan'] ['fan1'][0]
node = node.replace(node.split("/")[-1], 'fan_duty_cycle_percentage')
ret, log = log_os_system("cat "+ node, 1)
if ret==0:
print ("Previous fan duty: " + log.strip() +"%")
ret, log = log_os_system("echo "+args[1]+" >"+node, 1)
if ret==0:
print ("Current fan duty: " + args[1] +"%")
return ret
elif args[0]=='sfp':
if int(args[1])> DEVICE_NO[args[0]] or int(args[1])==0:
show_set_help()
return
if len(args)<2:
show_set_help()
return
if int(args[2])>1:
show_set_help()
return
#print ALL_DEVICE[args[0]]
for i in range(0,len(ALL_DEVICE[args[0]])):
for j in ALL_DEVICE[args[0]][args[0]+str(args[1])]:
if j.find('tx_disable')!= -1:
ret, log = log_os_system("echo "+args[2]+" >"+ j, 1)
if ret:
return ret
return
def get_value(input):
digit = re.findall('\d+', input)
return int(digit[0])
def get_ledname(ledx):
name_table={'led1':'SYS','led2':'FSTUS','led3':'FAN1','led4':'FAN2','led5':'FAN3','led6':'FAN4','led7':'FAN5','led8':'PSU1','led9':'PSU2'}
if name_table.has_key(ledx):
name = name_table[ledx]
else:
name = ledx
return name
def device_traversal():
if system_ready()==False:
print("System's not ready.")
print("Please install first!")
return
if len(ALL_DEVICE)==0:
devices_info()
for i in sorted(ALL_DEVICE.keys()):
print("============================================")
print(i.upper()+": ")
print("============================================")
for j in sorted(ALL_DEVICE[i].keys(), key=get_value):
nwnamex = get_ledname(j)
if nwnamex == j:
print " "+j+":",
else:
print " "+nwnamex+":",
for k in (ALL_DEVICE[i][j]):
ret, log = log_os_system("cat "+k, 0)
func = k.split("/")[-1].strip()
func = re.sub(j+'_','',func,1)
func = re.sub(i.lower()+'_','',func,1)
if ret==0:
print func+"="+log+" ",
else:
print func+"="+"X"+" ",
print
print("----------------------------------------------------------------")
print
return
def device_exist():
ret1, log = log_os_system("ls "+i2c_prefix+"*0077", 0)
ret2, log = log_os_system("ls "+i2c_prefix+"i2c-3", 0)
return not(ret1 or ret2)
if __name__ == "__main__":
main()

View File

@ -1,4 +1,5 @@
obj-m := x86-64-cig-cs6436-56p-cpld.o \
obj-m :=x86-64-cig-cs6436-56p-sysfs.o \
x86-64-cig-cs6436-56p-cpld.o \
x86-64-cig-cs6436-56p-fan.o \
x86-64-cig-cs6436-56p-led.o \
x86-64-cig-cs6436-56p-psu.o \

View File

@ -94,4 +94,129 @@
#define I2C_LPC_REG_DATA_TX3 0x8c
#define I2C_LPC_REG_DATA_TX4 0x8d
#endif /* I2C_LPC_H */
#define ADDR_REG_SFP_STATUS_ADDR 0X62 //reg addr +R/W# //1031
#define ADDR_REG_SFP_STATUS_TX 0X63 // write data
#define ADDR_REG_SFP_STATUS_RX 0X64 //read data
#define ADDR_REG_SFP_STATUS_COMMAND 0X65 //cmd bit7=1,go
#define ADDR_REG_SFP_STATUS_STATUS 0X66 //status
#define CPLD_MASTER_INTERRUPT_STATUS_REG 0x20
#define CPLD_MASTER_INTERRUPT_MASK_REG 0x21
#define CPLD_MASTER_INTERRUPT_ALL 0x3f
#define CPLD_MASTER_INTERRUPT_CPLD2 0x20
#define CPLD_MASTER_INTERRUPT_CPLD1 0x10
#define CPLD_MASTER_INTERRUPT_PSU2 0x08
#define CPLD_MASTER_INTERRUPT_PSU1 0x04
#define CPLD_MASTER_INTERRUPT_6320 0x02
#define CPLD_MASTER_INTERRUPT_LSW 0x01
#define CPLD_SLAVE1_INTERRUPT_STATUS_L_REG 0x20
#define CPLD_SLAVE1_INTERRUPT_STATUS_H_REG 0x21
#define CPLD_SLAVE2_INTERRUPT_STATUS_L_REG 0x22
#define CPLD_SLAVE2_INTERRUPT_STATUS_H_REG 0x23
#define CPLD_SLAVE1_INTERRUPT_MASK_REG 0x24
#define CPLD_SLAVE2_INTERRUPT_MASK_REG 0x25
#define CPLD_SLAVE1_PRESENT08_REG 0x01
#define CPLD_SLAVE1_PRESENT16_REG 0x02
#define CPLD_SLAVE1_PRESENT24_REG 0x03
#define CPLD_SLAVE2_PRESENT32_REG 0x04
#define CPLD_SLAVE2_PRESENT40_REG 0x05
#define CPLD_SLAVE2_PRESENT48_REG 0x06
#define CPLD_SLAVE1_RX_LOST08_REG 0x07
#define CPLD_SLAVE1_RX_LOST16_REG 0x08
#define CPLD_SLAVE1_RX_LOST24_REG 0x09
#define CPLD_SLAVE2_RX_LOST32_REG 0x0a
#define CPLD_SLAVE2_RX_LOST40_REG 0x0b
#define CPLD_SLAVE2_RX_LOST48_REG 0x0c
#define CPLD_SLAVE1_TX_FAULT08_REG 0x0d
#define CPLD_SLAVE1_TX_FAULT16_REG 0x0e
#define CPLD_SLAVE1_TX_FAULT24_REG 0x0f
#define CPLD_SLAVE2_TX_FAULT32_REG 0x10
#define CPLD_SLAVE2_TX_FAULT40_REG 0x11
#define CPLD_SLAVE2_TX_FAULT48_REG 0x12
#define CPLD_SLAVE2_PRESENT56_REG 0x19
#define CPLD_SLAVE2_QSFP_CR56_REG 0x1a
#define CPLD_SLAVE1_INTERRUPT_PRESENT08 0x0001
#define CPLD_SLAVE1_INTERRUPT_PRESENT16 0x0002
#define CPLD_SLAVE1_INTERRUPT_PRESENT24 0x0004
#define CPLD_SLAVE2_INTERRUPT_PRESENT32 0x0001
#define CPLD_SLAVE2_INTERRUPT_PRESENT40 0x0002
#define CPLD_SLAVE2_INTERRUPT_PRESENT48 0x0004
#define CPLD_SLAVE2_INTERRUPT_QSFP_CR56 0x0200
#define CPLD_SLAVE2_INTERRUPT_PRESENT56 0x0400
#define CPLD_SLAVE1_INTERRUPT_RX_LOST08 0x0008
#define CPLD_SLAVE1_INTERRUPT_RX_LOST16 0x0010
#define CPLD_SLAVE1_INTERRUPT_RX_LOST24 0x0020
#define CPLD_SLAVE2_INTERRUPT_RX_LOST32 0x0008
#define CPLD_SLAVE2_INTERRUPT_RX_LOST40 0x0010
#define CPLD_SLAVE2_INTERRUPT_RX_LOST48 0x0020
#define CPLD_SLAVE1_INTERRUPT_TX_FAULT08 0x0040
#define CPLD_SLAVE1_INTERRUPT_TX_FAULT16 0x0080
#define CPLD_SLAVE1_INTERRUPT_TX_FAULT24 0x0100
#define CPLD_SLAVE2_INTERRUPT_TX_FAULT32 0x0040
#define CPLD_SLAVE2_INTERRUPT_TX_FAULT40 0x0080
#define CPLD_SLAVE2_INTERRUPT_TX_FAULT48 0x0100
#define WAIT_TIME_OUT_COUNT 100
struct i2c_algo_lpc_data {
void *data; /* private data for lolevel routines */
void (*setlpc) (void *data, int ctl, int val);
int (*getlpc) (void *data, int ctl);
int (*getown) (void *data);
int (*getclock) (void *data);
void (*waitforpin) (void *data);
int (*xfer_begin) (void *data);
int (*xfer_end) (void *data);
/* Multi-master lost arbitration back-off delay (msecs)
* This should be set by the bus adapter or knowledgable client
* if bus is multi-mastered, else zero
*/
unsigned long lab_mdelay;
};
struct subsys_private {
struct kset subsys;
struct kset *devices_kset;
struct list_head interfaces;
struct mutex mutex;
struct kset *drivers_kset;
struct klist klist_devices;
struct klist klist_drivers;
struct blocking_notifier_head bus_notifier;
unsigned int drivers_autoprobe:1;
struct bus_type *bus;
struct kset glue_dirs;
struct class *class;
};
void cs6436_56p_sysfs_add_client(struct i2c_client *client);
void cs6436_56p_sysfs_remove_client(struct i2c_client *client);
#endif /* I2C_LPC8584_H */

File diff suppressed because it is too large Load Diff

View File

@ -44,6 +44,9 @@ static struct cs6436_56p_fan_data *cs6436_56p_fan_update_device(struct device *d
static ssize_t fan_show_value(struct device *dev, struct device_attribute *da, char *buf);
static ssize_t set_duty_cycle(struct device *dev, struct device_attribute *da,
const char *buf, size_t count);
static ssize_t set_fan_direction(struct device *dev, struct device_attribute *da,
const char *buf, size_t count);
extern int cig_cpld_write_register(u8 reg_off, u8 val);
extern int cig_cpld_read_register(u8 reg_off, u8 *val);
@ -63,6 +66,7 @@ static const u8 fan_reg[] = {
0x47, /* rear fan 3 speed(rpm) */
0x49, /* rear fan 4 speed(rpm) */
0x4b, /* rear fan 5 speed(rpm) */
0x4c, /* fan direction rear to front or front to rear */
};
@ -99,6 +103,7 @@ enum sysfs_fan_attributes {
FAN3_REAR_SPEED_RPM,
FAN4_REAR_SPEED_RPM,
FAN5_REAR_SPEED_RPM,
FAN_DIRECTION,
FAN1_STATE,
FAN2_STATE,
FAN3_STATE,
@ -109,6 +114,11 @@ enum sysfs_fan_attributes {
FAN3_FAULT,
FAN4_FAULT,
FAN5_FAULT,
FAN1_DIRECTION,
FAN2_DIRECTION,
FAN3_DIRECTION,
FAN4_DIRECTION,
FAN5_DIRECTION,
};
/* Define attributes
@ -131,6 +141,11 @@ enum sysfs_fan_attributes {
#define DECLARE_FAN_SPEED_RPM_ATTR(index) &sensor_dev_attr_fan##index##_front_speed_rpm.dev_attr.attr, \
&sensor_dev_attr_fan##index##_rear_speed_rpm.dev_attr.attr
#define DECLARE_FAN_DIRECTION_SENSOR_DEV_ATTR(index) \
static SENSOR_DEVICE_ATTR(fan##index##_direction, S_IWUSR | S_IRUGO, fan_show_value, set_fan_direction, FAN##index##_DIRECTION)
#define DECLARE_FAN_DIRECTION_ATTR(index) &sensor_dev_attr_fan##index##_direction.dev_attr.attr
/* 5 fan state attributes in this platform */
DECLARE_FAN_STATE_SENSOR_DEV_ATTR(1);
DECLARE_FAN_STATE_SENSOR_DEV_ATTR(2);
@ -156,6 +171,13 @@ DECLARE_FAN_SPEED_RPM_SENSOR_DEV_ATTR(5);
/* 1 fan duty cycle attribute in this platform */
DECLARE_FAN_DUTY_CYCLE_SENSOR_DEV_ATTR();
DECLARE_FAN_DIRECTION_SENSOR_DEV_ATTR(1);
DECLARE_FAN_DIRECTION_SENSOR_DEV_ATTR(2);
DECLARE_FAN_DIRECTION_SENSOR_DEV_ATTR(3);
DECLARE_FAN_DIRECTION_SENSOR_DEV_ATTR(4);
DECLARE_FAN_DIRECTION_SENSOR_DEV_ATTR(5);
static struct attribute *cs6436_56p_fan_attributes[] = {
/* fan related attributes */
DECLARE_FAN_STATE_ATTR(1),
@ -174,6 +196,11 @@ static struct attribute *cs6436_56p_fan_attributes[] = {
DECLARE_FAN_SPEED_RPM_ATTR(4),
DECLARE_FAN_SPEED_RPM_ATTR(5),
DECLARE_FAN_DUTY_CYCLE_ATTR(),
DECLARE_FAN_DIRECTION_ATTR(1),
DECLARE_FAN_DIRECTION_ATTR(2),
DECLARE_FAN_DIRECTION_ATTR(3),
DECLARE_FAN_DIRECTION_ATTR(4),
DECLARE_FAN_DIRECTION_ATTR(5),
NULL
};
@ -230,6 +257,7 @@ static u8 is_fan_fault(struct cs6436_56p_fan_data *data, enum fan_id id)
return ret;
}
static ssize_t set_duty_cycle(struct device *dev, struct device_attribute *da,
const char *buf, size_t count)
{
@ -247,6 +275,41 @@ static ssize_t set_duty_cycle(struct device *dev, struct device_attribute *da,
return count;
}
static ssize_t set_fan_direction(struct device *dev, struct device_attribute *da,
const char *buf, size_t count)
{
int error, value,fan_index;
u8 mask,reg_val;
struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
fan_index = attr->index - FAN1_DIRECTION;
error = kstrtoint(buf, 10, &value);
if (error)
return error;
if (!(value == 0 || value == 1))
return -EINVAL;
cig_cpld_read_register(fan_reg[FAN_DIRECTION],&reg_val);
if(value == 1)
{
reg_val |= (1 << fan_index);
}
else
{
reg_val &= ~(1 << fan_index);
}
cig_cpld_write_register(fan_reg[FAN_DIRECTION], reg_val);
return count;
}
static ssize_t fan_show_value(struct device *dev, struct device_attribute *da,
char *buf)
{
@ -300,6 +363,13 @@ static ssize_t fan_show_value(struct device *dev, struct device_attribute *da,
case FAN5_FAULT:
ret = sprintf(buf, "%d\n", is_fan_fault(data, attr->index - FAN1_FAULT));
break;
case FAN1_DIRECTION:
case FAN2_DIRECTION:
case FAN3_DIRECTION:
case FAN4_DIRECTION:
case FAN5_DIRECTION:
ret = sprintf(buf, "%d\n",reg_val_to_is_state(data->reg_val[FAN_DIRECTION],attr->index - FAN1_DIRECTION));
break;
default:
break;
}

View File

@ -34,6 +34,7 @@
#include <linux/kthread.h>
#include <linux/device.h>
#include <linux/platform_device.h>
#include "i2c-algo-lpc.h"
@ -67,6 +68,8 @@ struct cs6436_56p_psu_data {
u8 mfr_serial[20];
u8 psu_is_present;
u8 psu_is_good;
struct i2c_client *client;
struct bin_attribute *bin; /* eeprom data */
};
static int two_complement_to_int(u16 data, u8 valid_bit, int mask);
@ -126,6 +129,11 @@ static ssize_t set_fan_duty_cycle(struct device *dev, struct device_attribute \
long speed;
int error;
if (data->valid != 1)
{
return -ENODEV;
}
error = kstrtol(buf, 10, &speed);
if (error)
return error;
@ -151,6 +159,11 @@ static ssize_t for_linear_data(struct device *dev, struct device_attribute *dev_
int exponent, mantissa;
int multiplier = 1000;
if (data->valid != 1)
{
return -ENODEV;
}
switch (attr->index) {
case PSU_V_IN:
value = data->v_in;
@ -191,8 +204,8 @@ static ssize_t for_linear_data(struct device *dev, struct device_attribute *dev_
exponent = two_complement_to_int(value >> 11, 5, 0x1f);
mantissa = two_complement_to_int(value & 0x7ff, 11, 0x7ff);
return (exponent >= 0) ? sprintf(buf, "%d\n", \
(mantissa << exponent) * multiplier) : \
return (exponent >= 0) ? \
sprintf(buf, "%d\n", (mantissa << exponent) * multiplier) :\
sprintf(buf, "%d\n", (mantissa * multiplier) / (1 << -exponent));
}
@ -202,6 +215,11 @@ static ssize_t for_fan_fault(struct device *dev, struct device_attribute \
struct sensor_device_attribute *attr = to_sensor_dev_attr(dev_attr);
struct cs6436_56p_psu_data *data = cs6436_56p_psu_update_device(dev);
if (data->valid != 1)
{
return -ENODEV;
}
u8 shift = (attr->index == PSU_FAN1_FAULT) ? 7 : 6;
return sprintf(buf, "%d\n", data->fan_fault >> shift);
@ -213,6 +231,11 @@ static ssize_t for_fan_warning(struct device *dev, struct device_attribute \
struct sensor_device_attribute *attr = to_sensor_dev_attr(dev_attr);
struct cs6436_56p_psu_data *data = cs6436_56p_psu_update_device(dev);
if (data->valid != 1)
{
return -ENODEV;
}
u8 shift = (attr->index == PSU_FAN1_WARN) ? 5 : 4;
return sprintf(buf, "%d\n", data->fan_fault >> shift);
@ -224,6 +247,12 @@ static ssize_t for_temp_fault(struct device *dev, struct device_attribute \
struct sensor_device_attribute *attr = to_sensor_dev_attr(dev_attr);
struct cs6436_56p_psu_data *data = cs6436_56p_psu_update_device(dev);
if (data->valid != 1)
{
return -ENODEV;
}
return sprintf(buf, "%d\n", data->temp_fault >> 7);
}
@ -233,6 +262,11 @@ static ssize_t for_temp_warning(struct device *dev, struct device_attribute \
{
struct sensor_device_attribute *attr = to_sensor_dev_attr(dev_attr);
struct cs6436_56p_psu_data *data = cs6436_56p_psu_update_device(dev);
if (data->valid != 1)
{
return -ENODEV;
}
return sprintf(buf, "%d\n", data->temp_fault >> 6);
}
@ -242,6 +276,11 @@ static ssize_t for_vout_data(struct device *dev, struct device_attribute \
struct cs6436_56p_psu_data *data = cs6436_56p_psu_update_device(dev);
int exponent, mantissa;
int multiplier = 1000;
if (data->valid != 1)
{
return -ENODEV;
}
exponent = two_complement_to_int(data->vout_mode, 5, 0x1f);
mantissa = data->v_out;
@ -258,8 +297,10 @@ static ssize_t for_ascii(struct device *dev, struct device_attribute \
struct cs6436_56p_psu_data *data = cs6436_56p_psu_update_device(dev);
u8 *ptr = NULL;
if (!data->valid)
return 0;
if (data->valid != 1)
{
return -ENODEV;
}
switch (attr->index) {
case PSU_MFR_ID:
@ -286,14 +327,14 @@ static ssize_t for_status(struct device *dev, struct device_attribute *dev_attr,
u8 status = 0;
if (!data->valid) {
return -EIO;
}
if (attr->index == PSU_PRESENT) {
status = data->psu_is_present;
}
else { /* PSU_POWER_GOOD */
if (!data->valid) {
return -ENODEV;
}
status = data->psu_is_good;
}
@ -301,7 +342,6 @@ static ssize_t for_status(struct device *dev, struct device_attribute *dev_attr,
}
static int cs6436_56p_psu_read_byte(struct i2c_client *client, u8 reg)
{
return i2c_smbus_read_byte_data(client, reg);
@ -352,12 +392,279 @@ struct reg_data_word {
u16 *value;
};
static struct cs6436_56p_psu_data *cs6436_56p_psu_update_device( \
struct device *dev)
#define EEPROM_NAME "psu_eeprom"
#define EEPROM_SIZE 256 /* 256 byte eeprom */
/* Platform dependent --- */
static ssize_t psu_eeprom_write(struct i2c_client *client, u8 command, const char *data,
int data_len)
{
int status, retry = 3;
if (data_len > I2C_SMBUS_BLOCK_MAX) {
data_len = I2C_SMBUS_BLOCK_MAX;
}
while (retry) {
status = i2c_smbus_write_i2c_block_data(client, command, data_len, data);
if (unlikely(status < 0)) {
msleep(100);
retry--;
continue;
}
break;
}
if (unlikely(status < 0)) {
return status;
}
return data_len;
}
static ssize_t psu_page_write(struct i2c_client *client,const char *buf, loff_t off, size_t count)
{
ssize_t retval = 0;
if (unlikely(!count)) {
return count;
}
/*
* Write data to chip, protecting against concurrent updates
* from this host, but not from other I2C masters.
*/
while (count) {
ssize_t status;
status = psu_eeprom_write(client, off, buf, count);
if (status <= 0) {
if (retval == 0) {
retval = status;
}
break;
}
buf += status;
off += status;
count -= status;
retval += status;
}
return retval;
}
static ssize_t psu_bin_write(struct file *filp, struct kobject *kobj,
struct bin_attribute *attr,
char *buf, loff_t off, size_t count)
{
int present;
struct cs6436_56p_psu_data *data;
ssize_t retval = 0;
struct i2c_client *client;
data = dev_get_drvdata(container_of(kobj, struct device, kobj));
client = to_i2c_client(container_of(kobj, struct device, kobj));
mutex_lock(&data->update_lock);
retval = psu_page_write(client, buf, off, count);
mutex_unlock(&data->update_lock);
return retval;
}
static ssize_t psu_eeprom_read(struct i2c_client *client, u8 command, u8 *data,
int data_len)
{
int status, retry = 3;
if (data_len > I2C_SMBUS_BLOCK_MAX) {
data_len = I2C_SMBUS_BLOCK_MAX;
}
while (retry) {
status = i2c_smbus_read_i2c_block_data(client, command, data_len, data);
if (unlikely(status < 0)) {
msleep(100);
retry--;
continue;
}
break;
}
if (unlikely(status < 0)) {
goto abort;
}
if (unlikely(status != data_len)) {
status = -EIO;
goto abort;
}
abort:
return status;
}
static ssize_t psu_page_read(struct i2c_client *client,char *buf, loff_t off, size_t count)
{
ssize_t retval = 0;
if (unlikely(!count)) {
printk("Count = 0, return");
return count;
}
/*
* Read data from chip, protecting against concurrent updates
* from this host, but not from other I2C masters.
*/
while (count) {
ssize_t status;
status = psu_eeprom_read(client, off, buf, count);
if (status <= 0) {
if (retval == 0) {
retval = status;
}
break;
}
buf += status;
off += status;
count -= status;
retval += status;
}
return retval;
}
static ssize_t psu_bin_read(struct file *filp, struct kobject *kobj,
struct bin_attribute *attr,
char *buf, loff_t off, size_t count)
{
int present;
struct cs6436_56p_psu_data *data;
struct i2c_client *client;
ssize_t retval = 0;
data = dev_get_drvdata(container_of(kobj, struct device, kobj));
client = to_i2c_client(container_of(kobj, struct device, kobj));
mutex_lock(&data->update_lock);
retval = psu_page_read(client, buf, off, count);
mutex_unlock(&data->update_lock);
return retval;
}
static int psu_sysfs_eeprom_init(struct kobject *kobj, struct bin_attribute *eeprom)
{
int err;
sysfs_bin_attr_init(eeprom);
eeprom->attr.name = EEPROM_NAME;
eeprom->attr.mode = S_IWUSR | S_IRUGO;
eeprom->read = psu_bin_read;
eeprom->write = psu_bin_write;
eeprom->size = EEPROM_SIZE;
/* Create eeprom file */
err = sysfs_create_bin_file(kobj, eeprom);
if (err) {
return err;
}
return 0;
}
static int psu_sysfs_eeprom_cleanup(struct kobject *kobj, struct bin_attribute *eeprom)
{
sysfs_remove_bin_file(kobj, eeprom);
return 0;
}
static int psu_i2c_check_functionality(struct i2c_client *client)
{
return i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA | I2C_FUNC_SMBUS_I2C_BLOCK);
}
static int psu_eeprom_probe(struct i2c_client *client, const struct i2c_device_id *dev_id)
{
int status;
struct cs6436_56p_psu_data *data;
if (!psu_i2c_check_functionality(client)) {
status = -EIO;
goto exit;
}
data = kzalloc(sizeof(*data), GFP_KERNEL);
if (!data) {
status = -ENOMEM;
goto exit;
}
i2c_set_clientdata(client, data);
data->valid = 0;
mutex_init(&data->update_lock);
data->bin = kzalloc(sizeof(struct bin_attribute), GFP_KERNEL);
if (!data->bin) {
status = -ENOMEM;
goto eeprom_bin_error;
}
/* init eeprom */
status = psu_sysfs_eeprom_init(&client->dev.kobj, data->bin);
if (status) {
status = -ENOMEM;
goto sys_init_error;
}
dev_info(&client->dev, "psu eeprom '%s'\n", client->name);
return 0;
sys_init_error:
kfree(data->bin);
eeprom_bin_error:
kfree(data);
exit:
return status;
}
static struct cs6436_56p_psu_data *cs6436_56p_psu_update_device(struct device *dev)
{
struct i2c_client *client = to_i2c_client(dev);
struct cs6436_56p_psu_data *data = i2c_get_clientdata(client);
mutex_lock(&data->update_lock);
@ -378,10 +685,10 @@ static struct cs6436_56p_psu_data *cs6436_56p_psu_update_device( \
{0x97, &data->p_in},
{0x8d, &(data->temp_input[0])},
{0x8e, &(data->temp_input[1])},
{0x8f, &(data->temp_input[2])},
{0x3b, &(data->fan_duty_cycle[0])},
{0x90, &(data->fan_speed[0])},
};
data->valid = 1;
dev_dbg(&client->dev, "start data update\n");
@ -394,6 +701,8 @@ static struct cs6436_56p_psu_data *cs6436_56p_psu_update_device( \
if (status < 0) {
dev_dbg(&client->dev, "reg %d, err %d\n",
regs_byte[i].reg, status);
*(regs_byte[i].value) = 0;
data->valid = 0;
} else {
*(regs_byte[i].value) = status;
}
@ -405,6 +714,8 @@ static struct cs6436_56p_psu_data *cs6436_56p_psu_update_device( \
if (status < 0) {
dev_dbg(&client->dev, "reg %d, err %d\n",
regs_word[i].reg, status);
*(regs_word[i].value) = 0;
data->valid = 0;
} else {
*(regs_word[i].value) = status;
}
@ -416,6 +727,8 @@ static struct cs6436_56p_psu_data *cs6436_56p_psu_update_device( \
data->mfr_id[ARRAY_SIZE(data->mfr_id) - 1] = '\0';
if (status < 0) {
dev_dbg(&client->dev, "reg %d, err %d\n", command, status);
memset(data->mfr_id, 0, sizeof(data->mfr_id));
data->valid = 0;
}
command = 0x9a; /* PSU mfr_model */
@ -424,6 +737,8 @@ static struct cs6436_56p_psu_data *cs6436_56p_psu_update_device( \
data->mfr_model[ARRAY_SIZE(data->mfr_model) - 1] = '\0';
if (status < 0) {
dev_dbg(&client->dev, "reg %d, err %d\n", command, status);
memset(data->mfr_model, 0, sizeof(data->mfr_id));
data->valid = 0;
}
command = 0x9e; /* PSU mfr_serial */
@ -432,14 +747,21 @@ static struct cs6436_56p_psu_data *cs6436_56p_psu_update_device( \
data->mfr_serial[ARRAY_SIZE(data->mfr_serial) - 1] = '\0';
if (status < 0) {
dev_dbg(&client->dev, "reg %d, err %d\n", command, status);
memset(data->mfr_serial, 0, sizeof(data->mfr_id));
data->valid = 0;
}
data->valid = 1;
data->psu_is_present = strlen(data->mfr_id) > 1 ? 1:0;
if(data->psu_is_present)
{
data->psu_is_good = ((data->fan_fault) || (data->temp_fault))? 0:1;
}
else
{
data->valid = 0;
data->psu_is_good = 0;
}
}
mutex_unlock(&data->update_lock);
@ -499,14 +821,16 @@ static const struct attribute_group cs6436_56p_psu_group = {
.attrs = cs6436_56p_psu_attributes,
};
static int cs6436_56p_psu_probe(struct i2c_client *client,
static int psu_register_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
struct cs6436_56p_psu_data *data;
int status;
if (!i2c_check_functionality(client->adapter,
I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA)) {
struct cs6436_56p_psu_data *data;
if (!psu_i2c_check_functionality(client)) {
status = -EIO;
goto exit;
}
@ -521,35 +845,68 @@ static int cs6436_56p_psu_probe(struct i2c_client *client,
data->valid = 0;
mutex_init(&data->update_lock);
dev_info(&client->dev, "new chip found\n");
/* Register sysfs hooks */
status = sysfs_create_group(&client->dev.kobj, &cs6436_56p_psu_group);
if (status)
goto exit_sysfs_create_group;
cs6436_56p_sysfs_add_client(client);
data->hwmon_dev = hwmon_device_register(&client->dev);
if (IS_ERR(data->hwmon_dev)) {
status = PTR_ERR(data->hwmon_dev);
goto exit_hwmon_device_register;
}
/* init eeprom */
return 0;
exit_hwmon_device_register:
exit_hwmon_device_register:
sysfs_remove_group(&client->dev.kobj, &cs6436_56p_psu_group);
exit_sysfs_create_group:
exit_sysfs_create_group:
kfree(data);
exit:
exit:
return status;
}
static int cs6436_56p_psu_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
int status;
if((client->addr == 0x52) ||(client->addr == 0x53))
{
status = psu_eeprom_probe(client, id);
}
else if((client->addr == 0x5a) ||(client->addr == 0x5b))
{
status = psu_register_probe(client, id);
}
return status;
}
static int cs6436_56p_psu_remove(struct i2c_client *client)
{
struct cs6436_56p_psu_data *data = i2c_get_clientdata(client);
cs6436_56p_sysfs_remove_client(client);
if((client->addr == 0x52) ||(client->addr == 0x53))
{
struct cs6436_56p_psu_data *data;
data = i2c_get_clientdata(client);
psu_sysfs_eeprom_cleanup(&client->dev.kobj,data->bin);
kfree(data);
}
else if((client->addr == 0x5a) ||(client->addr == 0x5b))
{
struct cs6436_56p_psu_data *data;
data = i2c_get_clientdata(client);
hwmon_device_unregister(data->hwmon_dev);
sysfs_remove_group(&client->dev.kobj, &cs6436_56p_psu_group);
kfree(data);
}
return 0;
}

View File

@ -28,6 +28,7 @@
#include <linux/sysfs.h>
#include <linux/slab.h>
#include <linux/delay.h>
#include "i2c-algo-lpc.h"
#define DRIVER_NAME "cs6436_56p_sfp" /* Platform dependent */
@ -64,15 +65,9 @@
#define SFF8436_RX_LOS_ADDR 3
#define SFF8436_TX_FAULT_ADDR 4
#define SFF8436_TX_DISABLE_ADDR 86
#define ADDR_REG_SFP_STATUS_ADDR 0X62 //reg addr +R/W# //1031
#define ADDR_REG_SFP_STATUS_TX 0X63 // write data
#define ADDR_REG_SFP_STATUS_RX 0X64 //read data
#define ADDR_REG_SFP_STATUS_COMMAND 0X65 //cmd bit7=1,go
#define ADDR_REG_SFP_STATUS_STATUS 0X66 //status
#define QSFP_RESET_ADDR 0x1b
#define QSFP_INTER_ADDR 0x1a
#define QSFP_LPMODE_ADDR 0x1c
static ssize_t show_port_number(struct device *dev, struct device_attribute *da, char *buf);
static ssize_t show_port_type(struct device *dev, struct device_attribute *da, char *buf);
@ -87,6 +82,11 @@ static ssize_t sfp_eeprom_write(struct i2c_client *, u8 , const char *,int);
extern int cig_cpld_read_register(u8 reg_off, u8 *val);
extern int cig_cpld_write_register(u8 reg_off, u8 val);
static ssize_t qsfp_reset_read(struct device *dev, struct device_attribute *da, char *buf);
static ssize_t qsfp_reset_write(struct device *dev, struct device_attribute *da, const char *buf, size_t count);
static ssize_t qsfp_inter_read(struct device *dev, struct device_attribute *da, char *buf);
static ssize_t qsfp_lpmode_read(struct device *dev, struct device_attribute *da, char *buf);
static ssize_t qsfp_lpmode_write(struct device *dev, struct device_attribute *da, const char *buf, size_t count);
enum sfp_sysfs_attributes {
PRESENT,
@ -109,7 +109,10 @@ enum sfp_sysfs_attributes {
RX_LOS2,
RX_LOS3,
RX_LOS4,
RX_LOS_ALL
RX_LOS_ALL,
QSFPRESET,
QSFPINT,
QSFPLPMODE
};
/* SFP/QSFP common attributes for sysfs */
@ -134,6 +137,9 @@ static SENSOR_DEVICE_ATTR(sfp_tx_fault1, S_IRUGO, qsfp_show_tx_rx_status, NULL,
static SENSOR_DEVICE_ATTR(sfp_tx_fault2, S_IRUGO, qsfp_show_tx_rx_status, NULL, TX_FAULT2);
static SENSOR_DEVICE_ATTR(sfp_tx_fault3, S_IRUGO, qsfp_show_tx_rx_status, NULL, TX_FAULT3);
static SENSOR_DEVICE_ATTR(sfp_tx_fault4, S_IRUGO, qsfp_show_tx_rx_status, NULL, TX_FAULT4);
static SENSOR_DEVICE_ATTR(sfp_reset, S_IWUSR | S_IRUGO, qsfp_reset_read, qsfp_reset_write, QSFPRESET);
static SENSOR_DEVICE_ATTR(sfp_inter, S_IRUGO, qsfp_inter_read, NULL, QSFPINT);
static SENSOR_DEVICE_ATTR(sfp_lpmode, S_IWUSR | S_IRUGO, qsfp_lpmode_read, qsfp_lpmode_write, QSFPLPMODE);
static struct attribute *qsfp_attributes[] = {
&sensor_dev_attr_sfp_port_number.dev_attr.attr,
&sensor_dev_attr_sfp_port_type.dev_attr.attr,
@ -154,6 +160,9 @@ static struct attribute *qsfp_attributes[] = {
&sensor_dev_attr_sfp_tx_fault2.dev_attr.attr,
&sensor_dev_attr_sfp_tx_fault3.dev_attr.attr,
&sensor_dev_attr_sfp_tx_fault4.dev_attr.attr,
&sensor_dev_attr_sfp_reset.dev_attr.attr,
&sensor_dev_attr_sfp_inter.dev_attr.attr,
&sensor_dev_attr_sfp_lpmode.dev_attr.attr,
NULL
};
@ -342,7 +351,7 @@ static ssize_t show_port_number(struct device *dev, struct device_attribute *da,
return sprintf(buf, "%d\n", CPLD_PORT_TO_FRONT_PORT(data->port));
}
#define WAIT_TIME_OUT_COUNT 100
static int cig_cpld_write_sfp_register(u8 sfp_reg_addr, u8 sfp_write_reg_data)
{
@ -536,7 +545,7 @@ static ssize_t sfp_set_tx_disable(struct device *dev, struct device_attribute *d
if(data->port <= 48) {
cpld_reg_addr = 19 + data->port / 8;
cpld_reg_bit = 1 << (data->port);
cpld_reg_bit = 1 << ((data->port) % 8);
}
/* Read current status */
@ -548,7 +557,7 @@ static ssize_t sfp_set_tx_disable(struct device *dev, struct device_attribute *d
cpld_reg_data |= cpld_reg_bit;
}
else {
data->msa->status[1] &= ~BIT_INDEX(data->port);
data->msa->status[1] &= ~ BIT_INDEX(data->port);
cpld_reg_data &= ~cpld_reg_bit;
}
@ -750,6 +759,253 @@ exit:
return (status < 0) ? ERR_PTR(status) : data;
}
static ssize_t qsfp_inter_read(struct device *dev, struct device_attribute *da, char *buf)
{
int present;
int status;
u8 val = 0;
int ret = 0;
u8 cpld_reg_data = 0;
u8 index = 0;
struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
struct i2c_client *client = to_i2c_client(dev);
struct sfp_port_data *data = i2c_get_clientdata(client);
present = sfp_is_port_present(client, data->port);
if (IS_ERR_VALUE(present)) {
return present;
}
if (present == 0) {
/* port is not present */
return -ENODEV;
}
mutex_lock(&data->update_lock);
udelay(6000);
/* Read current status */
ret = cig_cpld_read_sfp_register(QSFP_INTER_ADDR, &cpld_reg_data);
index = data->port - 48;
index = 1 << index;
val = (cpld_reg_data & index) > 0 ? 1 : 0;
printk("inter read:data->port = %d, index = %hhu, cpld_reg_data = %hhu\n", data->port, index, cpld_reg_data);
mutex_unlock(&data->update_lock);
return sprintf(buf, "%d\n", val);
}
static ssize_t qsfp_reset_read(struct device *dev, struct device_attribute *da, char *buf)
{
int present;
int status;
u8 val = 0;
int ret = 0;
u8 cpld_reg_data = 0;
u8 index = 0;
struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
struct i2c_client *client = to_i2c_client(dev);
struct sfp_port_data *data = i2c_get_clientdata(client);
present = sfp_is_port_present(client, data->port);
if (IS_ERR_VALUE(present)) {
return present;
}
if (present == 0) {
/* port is not present */
return -ENODEV;
}
mutex_lock(&data->update_lock);
udelay(6000);
/* Read current status */
ret = cig_cpld_read_sfp_register(QSFP_RESET_ADDR, &cpld_reg_data);
index = data->port - 48;
index = 1 << index;
val = (cpld_reg_data & index) > 0 ? 1 : 0;
printk("reset read:data->port = %d, index = %hhu, cpld_reg_data = %hhu\n", data->port, index, cpld_reg_data);
mutex_unlock(&data->update_lock);
return sprintf(buf, "%d\n", val);
}
static ssize_t qsfp_reset_write(struct device *dev, struct device_attribute *da, const char *buf, size_t count)
{
int present;
int status;
u8 val = 0;
int ret = 0;
u8 cpld_reg_data = 0;
u8 index = 0;
long usrdata;
struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
struct i2c_client *client = to_i2c_client(dev);
struct sfp_port_data *data = i2c_get_clientdata(client);
present = sfp_is_port_present(client, data->port);
if (IS_ERR_VALUE(present)) {
return present;
}
if (present == 0) {
/* port is not present */
return -ENODEV;
}
ret = kstrtol(buf, 10, &usrdata);
if (ret) {
return ret;
}
usrdata = usrdata > 0 ? 1 : 0;
index = data->port - 48;
DEBUG_PRINT("usrdata = %u, index = %hhu\n", usrdata, index);
mutex_lock(&data->update_lock);
udelay(6000);
/* Read current status */
ret = cig_cpld_read_sfp_register(QSFP_RESET_ADDR, &cpld_reg_data);
if (ret == 1)
{
DEBUG_PRINT("cpld_reg_data = %x\n", cpld_reg_data);
cpld_reg_data &= ~(1 << index);
cpld_reg_data |= usrdata << index;
DEBUG_PRINT("cpld_reg_data = %x\n", cpld_reg_data);
ret = cig_cpld_write_sfp_register(QSFP_RESET_ADDR, cpld_reg_data);
if (1 != ret)
{
DEBUG_PRINT("write failed\n");
}
}
else
{
DEBUG_PRINT("read failed\n");
}
mutex_unlock(&data->update_lock);
if (ret != 1)
return -1;
return count;
}
static ssize_t qsfp_lpmode_read(struct device *dev, struct device_attribute *da, char *buf)
{
int present;
int status;
u8 val = 0;
int ret = 0;
u8 cpld_reg_data = 0;
u8 index = 0;
struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
struct i2c_client *client = to_i2c_client(dev);
struct sfp_port_data *data = i2c_get_clientdata(client);
present = sfp_is_port_present(client, data->port);
if (IS_ERR_VALUE(present)) {
return present;
}
if (present == 0) {
/* port is not present */
return -ENODEV;
}
mutex_lock(&data->update_lock);
udelay(6000);
/* Read current status */
ret = cig_cpld_read_sfp_register(QSFP_LPMODE_ADDR, &cpld_reg_data);
index = data->port - 48;
index = 1 << index;
val = (cpld_reg_data & index) > 0 ? 1 : 0;
printk("lpmode read:data->port = %d, index = %hhu, cpld_reg_data = %hhu\n", data->port, index, cpld_reg_data);
mutex_unlock(&data->update_lock);
return sprintf(buf, "%d\n", val);
}
static ssize_t qsfp_lpmode_write(struct device *dev, struct device_attribute *da, const char *buf, size_t count)
{
int present;
int status;
u8 val = 0;
int ret = 0;
u8 cpld_reg_data = 0;
u8 index = 0;
long usrdata;
struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
struct i2c_client *client = to_i2c_client(dev);
struct sfp_port_data *data = i2c_get_clientdata(client);
present = sfp_is_port_present(client, data->port);
if (IS_ERR_VALUE(present)) {
return present;
}
if (present == 0) {
/* port is not present */
return -ENODEV;
}
ret = kstrtol(buf, 10, &usrdata);
if (ret) {
return ret;
}
usrdata = usrdata > 0 ? 1 : 0;
index = data->port - 48;
DEBUG_PRINT("usrdata = %u, index = %hhu\n", usrdata, index);
mutex_lock(&data->update_lock);
udelay(6000);
/* Read current status */
ret = cig_cpld_read_sfp_register(QSFP_LPMODE_ADDR, &cpld_reg_data);
if (ret == 1)
{
DEBUG_PRINT("cpld_reg_data = %x\n", cpld_reg_data);
cpld_reg_data &= ~(1 << index);
cpld_reg_data |= usrdata << index;
DEBUG_PRINT("cpld_reg_data = %x\n", cpld_reg_data);
ret = cig_cpld_write_sfp_register(QSFP_LPMODE_ADDR, cpld_reg_data);
if (1 != ret)
{
DEBUG_PRINT("write failed\n");
}
}
else
{
DEBUG_PRINT("read failed\n");
}
mutex_unlock(&data->update_lock);
if (ret != 1)
return -1;
return count;
}
static ssize_t qsfp_show_tx_rx_status(struct device *dev, struct device_attribute *da,
char *buf)
{
@ -1246,6 +1502,8 @@ static int sfp_msa_probe(struct i2c_client *client, const struct i2c_device_id *
*data = msa;
dev_info(&client->dev, "sfp msa '%s'\n", client->name);
cs6436_56p_sysfs_add_client(client);
return 0;
exit_remove:
@ -1419,6 +1677,7 @@ static int sfp_device_remove(struct i2c_client *client)
{
struct sfp_port_data *data = i2c_get_clientdata(client);
cs6436_56p_sysfs_remove_client(client);
switch (data->driver_type) {
case DRIVER_TYPE_SFP_MSA:
return sfp_msa_remove(client, data->msa);

View File

@ -0,0 +1,335 @@
/*
* A hwmon driver for the CIG cs6436-56P sysfs Module
*
* Copyright (C) 2018 Cambridge, Inc.
*
* 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.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <linux/module.h>
#include <linux/jiffies.h>
#include <linux/i2c.h>
#include <linux/hwmon.h>
#include <linux/hwmon-sysfs.h>
#include <linux/err.h>
#include <linux/mutex.h>
#include <linux/sysfs.h>
#include <linux/slab.h>
#include <linux/delay.h>
#include <linux/dmi.h>
#include <linux/uaccess.h>
#include <linux/syscalls.h>
#include <linux/kthread.h>
#include <linux/device.h>
#include <linux/platform_device.h>
#include <linux/init.h>
#include <linux/fs.h>
#include <asm/uaccess.h>
#include <asm/device.h>
#include <linux/cdev.h>
#include "i2c-algo-lpc.h"
static LIST_HEAD(sysfs_client_list);
static struct mutex list_lock;
struct sysfs_client_node {
struct i2c_client *client;
struct list_head list;
};
#define DEVICE_NAME "cigfs"
static int dev_major;
static struct class *dev_class;
static struct cdev *dev_cdev;
static struct device *dev_device;
static struct class *psu_class;
static struct class *sfp_class;
void cs6436_56p_sysfs_add_client(struct i2c_client *client)
{
struct sysfs_client_node *node = kzalloc(sizeof(struct sysfs_client_node), GFP_KERNEL);
if (!node) {
dev_dbg(&client->dev, "Can't allocate sysfs_client_node (0x%x)\n", client->addr);
return;
}
node->client = client;
mutex_lock(&list_lock);
list_add(&node->list, &sysfs_client_list);
mutex_unlock(&list_lock);
}
EXPORT_SYMBOL(cs6436_56p_sysfs_add_client);
void cs6436_56p_sysfs_remove_client(struct i2c_client *client)
{
struct list_head *list_node = NULL;
struct sysfs_client_node *sysfs_node = NULL;
int found = 0;
mutex_lock(&list_lock);
list_for_each(list_node, &sysfs_client_list)
{
sysfs_node = list_entry(list_node, struct sysfs_client_node, list);
if (IS_ERR(sysfs_node))
{
break;
}
if (sysfs_node->client == client) {
found = 1;
break;
}
}
if (found) {
list_del(list_node);
kfree(sysfs_node);
}
mutex_unlock(&list_lock);
}
EXPORT_SYMBOL(cs6436_56p_sysfs_remove_client);
struct class * cs6436_56p_sysfs_create_symclass(char *cls_name)
{
int rc = 0;
struct class *my_class;
/**************************************************************************************/
my_class = class_create(THIS_MODULE,cls_name);
if (IS_ERR(my_class)) {
pr_err("failed to create my class\n");
}
return my_class;
/**************************************************************************************/
}
void cs6436_56p_sysfs_delete_symclass(struct class *my_class)
{
/**************************************************************************************/
if (IS_ERR(my_class)) {
pr_err("Pointer is invaild\n");
}
class_destroy(my_class);
/**************************************************************************************/
}
int cs6436_56p_sysfs_create_symlink(struct class *my_class,char * driver_name,char *device_name)
{
struct list_head *list_node = NULL;
struct sysfs_client_node *sysfs_node = NULL;
int ret = -EPERM;
int rc = 0;
mutex_lock(&list_lock);
list_for_each(list_node, &sysfs_client_list)
{
sysfs_node = list_entry(list_node, struct sysfs_client_node, list);
if (!strcmp(sysfs_node->client->name,driver_name)) {
rc = sysfs_create_link(&my_class->p->subsys.kobj, &sysfs_node->client->dev.kobj,device_name);
if(rc)
{
pr_err("failed to create symlink %d\n",rc);
}
break;
}
}
mutex_unlock(&list_lock);
return ret;
}
int cs6436_56p_sysfs_delete_symlink(struct class *my_class,char * driver_name,char *device_name)
{
struct list_head *list_node = NULL;
struct sysfs_client_node *sysfs_node = NULL;
int ret = -EPERM;
int rc = 0;
mutex_lock(&list_lock);
list_for_each(list_node, &sysfs_client_list)
{
sysfs_node = list_entry(list_node, struct sysfs_client_node, list);
if (!strcmp(sysfs_node->client->name,driver_name)) {
sysfs_remove_link(&my_class->p->subsys.kobj,device_name);
break;
}
}
mutex_unlock(&list_lock);
return ret;
}
static int cs6436_56p_sysfs_open(struct inode *inode, struct file *file)
{
return 0;
}
static ssize_t cs6436_56p_sysfs_write(struct file *file, const char __user *buf, size_t count, loff_t * ppos)
{
char str[10],name[18],port[8];
int ret;
int i;
memset(str, 0, sizeof(str));
ret = copy_from_user(str, buf, count);
if (ret)
{
printk(KERN_ERR "copy_from_user fail\n");
return -EINVAL;
}
if(!strncmp(str,"start",5))
{
psu_class = cs6436_56p_sysfs_create_symclass("psu");
cs6436_56p_sysfs_create_symlink(psu_class,"cs6436_56p_psu1","psu1");
cs6436_56p_sysfs_create_symlink(psu_class,"cs6436_56p_psu2","psu2");
sfp_class = cs6436_56p_sysfs_create_symclass("swps");
for(i = 1; i <= 48;i++)
{
memset(name,0xff,sizeof(name));
memset(port,0xff,sizeof(port));
snprintf(name,sizeof(name),"cs6436_56p_sfp%d",i);
snprintf(port,sizeof(port),"port%d",i);
cs6436_56p_sysfs_create_symlink(sfp_class,name,port);
}
}
else if(!strncmp(str,"stop",4))
{
cs6436_56p_sysfs_delete_symlink(psu_class,"cs6436_56p_psu1","psu1");
cs6436_56p_sysfs_delete_symlink(psu_class,"cs6436_56p_psu2","psu2");
cs6436_56p_sysfs_delete_symclass(psu_class);
for(i = 1; i <= 48;i++)
{
memset(name,0xff,sizeof(name));
memset(port,0xff,sizeof(port));
snprintf(name,sizeof(name),"cs6436_56p_sfp%d",i);
snprintf(port,sizeof(port),"port%d",i);
cs6436_56p_sysfs_delete_symlink(sfp_class,name,port);
}
cs6436_56p_sysfs_delete_symclass(sfp_class);
}
return count;
}
static struct file_operations cs6436_56p_sysfs_fops = {
.owner = THIS_MODULE,
.open = cs6436_56p_sysfs_open,
.write = cs6436_56p_sysfs_write,
};
static int __init cs6436_56p_sysfs_init(void)
{
int result = 0;
int err = 0;
dev_t dev = MKDEV(dev_major, 0);
if (dev_major)
result = register_chrdev_region(dev, 1, DEVICE_NAME);
else {
result = alloc_chrdev_region(&dev, 0, 1, DEVICE_NAME);
dev_major = MAJOR(dev);
}
if (result < 0)
{
printk("unable to get major %d\n", dev_major);
err= -EINVAL;
}
printk("get major is %d\n", dev_major);
if (dev_major == 0)
dev_major = result;
dev_cdev= kmalloc(sizeof(struct cdev), GFP_KERNEL);
if(IS_ERR(dev_cdev)) {
err= -ENOMEM;
}
cdev_init(dev_cdev, &cs6436_56p_sysfs_fops);
dev_cdev->owner = THIS_MODULE;
dev_cdev->ops = &cs6436_56p_sysfs_fops;
err = cdev_add(dev_cdev, dev, 1);
if (err)
{
printk("error %d add fpga ", err);
goto err_malloc;
}
dev_class = class_create(THIS_MODULE, DEVICE_NAME);
if (IS_ERR(dev_class))
{
printk("Err:failed in creating class.\n");
goto err_cdev_add;
}
dev_device = device_create(dev_class, NULL, MKDEV(dev_major, 0), NULL, DEVICE_NAME);
if (IS_ERR(dev_device))
{
printk("Err:failed in creating device.\n");
goto err_class_crt;
}
mutex_init(&list_lock);
return err;
err_class_crt:
cdev_del(dev_cdev);
err_cdev_add:
kfree(dev_cdev);
err_malloc:
unregister_chrdev_region(MKDEV(dev_major,0), 1);
return err;
}
static void __exit cs6436_56p_sysfs_exit(void)
{
cdev_del(dev_cdev);
printk("cdev_del ok\n");
device_destroy(dev_class, MKDEV(dev_major, 0));
class_destroy(dev_class);
if(dev_cdev != NULL)
kfree(dev_cdev);
unregister_chrdev_region(MKDEV(dev_major, 0), 1);
printk("cs6436_56p_sysfs_exit...\r\n");
}
MODULE_AUTHOR("Zhang Peng <zhangpeng@cigtech.com>");
MODULE_DESCRIPTION("cs6436-56p-sysfs driver");
MODULE_LICENSE("GPL");
module_init(cs6436_56p_sysfs_init);
module_exit(cs6436_56p_sysfs_exit);

View File

@ -21,12 +21,259 @@ import sys, getopt
import logging
import re
import time
import datetime
from collections import namedtuple
from threading import Thread
DEBUG = False
i2c_prefix = '/sys/bus/i2c/devices/'
cs6436__prefix = '/sys/devices/platform/cs6436_56p_led/leds/'
leds_prefix = '/sys/devices/platform/cs6436_56p_led/leds/'
fans_prefix = '/sys/devices/platform/cs6436_56p_fan/'
fansdir_prefix = fans_prefix + 'fan{}_direction'
ageing_controlfile = '/etc/sonic/agcontrol'
AGFlag = 0
platform_misc_log = '/var/log/platform_misc.log'
misclogger = logging.getLogger('platform_misc')
misclogger.setLevel(logging.INFO)
miscformatter = logging.Formatter('%(asctime)s-%(levelname)s-%(message)s')
if not os.path.isfile(platform_misc_log):
try:
os.mknod(platform_misc_log)
except:
print 'Failed to creat platform_misc.log'
fileHandler = logging.FileHandler(platform_misc_log)
fileHandler.setLevel(logging.INFO)
fileHandler.setFormatter(miscformatter)
misclogger.addHandler(fileHandler)
starttime = datetime.datetime.now()
IsGetlswt = 0
coretemp_prefix = '/sys/class/hwmon/hwmon1/'
coretemp_ps = []
psu1_p = '/sys/bus/i2c/devices/5-005a/psu_present'
psu2_p = '/sys/bus/i2c/devices/5-005b/psu_present'
psu1_d = '/sys/bus/i2c/devices/5-0052/psu_eeprom'
psu2_d = '/sys/bus/i2c/devices/5-0053/psu_eeprom'
psu1led_d = leds_prefix + 'cs6436_56p_led::psu1/brightness'
psu2led_d = leds_prefix + 'cs6436_56p_led::psu2/brightness'
cs6436_ledpath = {'fan':leds_prefix + 'cs6436_56p_led::fan/brightness',
'fan1':leds_prefix + 'cs6436_56p_led::fan1/brightness',
'fan2':leds_prefix + 'cs6436_56p_led::fan2/brightness',
'fan3':leds_prefix + 'cs6436_56p_led::fan3/brightness',
'fan4':leds_prefix + 'cs6436_56p_led::fan4/brightness',
'fan5':leds_prefix + 'cs6436_56p_led::fan5/brightness',
'psu1':leds_prefix + 'cs6436_56p_led::psu1/brightness',
'psu2':leds_prefix + 'cs6436_56p_led::psu2/brightness',
'sys':leds_prefix + 'cs6436_56p_led::sys/brightness'}
def system_read_filestr(node):
with open(node, 'r') as f:
try:
str = f.read()
except IOError as e:
misclogger.error('Failed to get node, str={}'.format(node))
return "0"
return str
def system_bright_leds(dev, colour):
global AGFlag
if AGFlag == 1:
return
cmd = 'echo {} > {}'.format(colour, dev)
log_os_system(cmd, 1)
return
'''
1: front in tail out
0: front out tail in
'''
def system_getpsu_direction(dev):
try:
with open(dev) as f:
f.seek(0x30)
str = f.read(2)
except IOError as e:
misclogger.error('Failed to get psu eep')
return 1
if str == 'AA': ## front in tail out
return 1
elif str == 'RA':## tail in front out
return 0
else:
misclogger.error('Failed to get psu eep, str={}'.format(str))
return -1
def system_get_cputype():
cmdretfd = os.popen("lscpu | grep 'Model name'")
retstring = cmdretfd.read()
endindex = retstring.find('@') - 1
startindex = retstring[:endindex].rfind(' ') + 1
cputype = retstring[startindex:endindex]
return cputype
def system_init_coretemppath():
global coretemp_ps
cmdstr = "ls {} | grep 'input'".format(coretemp_prefix)
cmdretfd = os.popen(cmdstr)
coretemppss = cmdretfd.read().splitlines()
if len(coretemppss) < 3:
cputype = system_get_cputype()
misclogger.error('Failed to init core temperature path.'
' cpu type = {}, num thermal = {}'.format(cputype, len(coretemp_ps)))
return 1
for i in range(0,3):
coretemp_ps.append(coretemp_prefix + coretemppss[i])
print coretemp_ps
return 0
class cs6436_fanattr:
def __init__(self, name):
self.name = name
self.direction = 0
self.direction_p = ''
self.rear = 0
self.rear_p = ''
self.front = 0
self.front_p = ''
self.fault = 0
self.fault_p = ''
self.status = 0
self.setpath()
self.updatedevice()
return
def setpath(self):
self.direction_p = fans_prefix + '{}_direction'.format(self.name)
self.rear_p = fans_prefix + '{}_rear_speed_rpm'.format(self.name)
self.front_p = fans_prefix + '{}_front_speed_rpm'.format(self.name)
self.fault_p = fans_prefix + '{}_fault'.format(self.name)
return
def updatedevice(self):
self.direction = int(system_read_filestr(self.direction_p))
self.rear = int(system_read_filestr(self.rear_p))
self.front = int(system_read_filestr(self.front_p))
self.fault = int(system_read_filestr(self.fault_p))
return
def checkspeedrpm(self, speedrpm):
frontrpmexp = speedrpm * 21000 / 100
rearrpmexp = speedrpm * 19000 / 100
deviationfront = abs(frontrpmexp - self.front) / float(frontrpmexp)
deviationrear = abs(rearrpmexp - self.rear) / float(rearrpmexp)
if deviationfront < 0.3 and deviationrear < 0.3:
return 0
else:
misclogger.error(':{} speed wrong. frontexp is {}, but rpm is {}.rearexp is {}, but rpm is {}'.format(self.name, frontrpmexp, self.front, rearrpmexp, self.rear))
return 1
def checkstatus(self, speedrpm, totaldirct):
speedstatus = self.checkspeedrpm(speedrpm)
if self.direction != totaldirct:
self.status = 1
misclogger.error(':{} direction = {}.fan direction is not ok.'.format(self.name, self.direction))
elif speedstatus != 0:
self.status = 1
elif self.fault != 0:
misclogger.error(':{} fault.'.format(self.name))
self.status = 1
else:
self.status = 0
if self.status == 1:
system_bright_leds(cs6436_ledpath[self.name], 3)
else:
system_bright_leds(cs6436_ledpath[self.name], 1)
return self.status
cs6436_fanattrnodes = []
class cs6436_psuattr:
def __init__(self, name):
self.name = name
self.direction = 0
self.direction_p = ''
self.present = 0
self.present_p = ''
self.status = 0
self.setpath()
self.updatepresent()
self.updatedirection()
return
def setpath(self):
if self.name == 'psu1':
self.present_p = psu1_p
self.direction_p = psu1_d
if self.name == 'psu2':
self.present_p = psu2_p
self.direction_p = psu2_d
return
def updatepresent(self):
self.present = int(system_read_filestr(self.present_p))
return
def updatedirection(self):
if self.present == 1:
self.direction = system_getpsu_direction(self.direction_p)
else:
self.direction = 2
return
def checkstatus(self, totaldirct):
if self.present != 1:
self.status = 1
misclogger.error(':{} not present.'.format(self.name))
elif self.direction == 2:
self.status = 0
misclogger.info(':{} direction need to be update.'.format(self.name))
elif self.direction != totaldirct:
self.status = 1
misclogger.info(':{} direction is wrong.'.format(self.name))
else:
self.status = 0
if self.status == 1:
system_bright_leds(cs6436_ledpath[self.name], 3)
else:
system_bright_leds(cs6436_ledpath[self.name], 1)
return self.status
cs6436_psuattrnodes = []
def my_log(txt):
if DEBUG == True:
@ -36,7 +283,7 @@ def my_log(txt):
def device_exist():
ret1, log = log_os_system("ls "+i2c_prefix+"5-005a", 0)
ret2, log = log_os_system("ls "+i2c_prefix+"5-005b", 0)
ret3, log = log_os_system("ls "+cs6436__prefix+"cs6436_56p_led*", 0)
ret3, log = log_os_system("ls "+leds_prefix+"cs6436_56p_led*", 0)
return not(ret1 or ret2 or ret3)
@ -52,6 +299,222 @@ def log_os_system(cmd, show):
return status, output
def system_get_coretemp():
temp1 = system_read_filestr(coretemp_ps[0]).strip()
temp2 = system_read_filestr(coretemp_ps[1]).strip()
temp3 = system_read_filestr(coretemp_ps[2]).strip()
return int(temp1), int(temp2), int(temp3)
def system_get_boardtemp():
for i in range(0,16):
temp1path = "/sys/bus/i2c/devices/5-004a/hwmon/hwmon%d/temp1_input" % i
if os.access(temp1path, os.F_OK):
break
for i in range(0,16):
temp2path = "/sys/bus/i2c/devices/5-004b/hwmon/hwmon%d/temp1_input" % i
if os.access(temp2path, os.F_OK):
break
temp1 = system_read_filestr(temp1path).strip()
temp2 = system_read_filestr(temp2path).strip()
return int(temp1), int(temp2)
def system_get_lswtemp():
global IsGetlswt
global starttime
if IsGetlswt == 0:
now = datetime.datetime.now()
misclogger.info("time wait.")
misclogger.info("start = {}, now = {}.".format(starttime, now))
if (now - starttime).seconds > 150:
misclogger.info("time = ".format((now - starttime).seconds))
IsGetlswt = 1
return 25
# chp = subprocess.Popen("docker ps --filter name=syncd", shell=True, stdout=subprocess.PIPE)
# if chp.poll() == None:
# misclogger.info("No subp.")
# chp.kill()
#
# return 25
# retstring = chp.stdout.read()
# chp.kill()
# if 'Up' not in retstring:
# misclogger.info("lsw not up.")
#
# return 25
status, output = log_os_system('npx_diag swc show temperature', 1)
if status:
misclogger.error('failed to show lsw temperature')
return 25
output = output.strip()
if output.find("it 0, temperature ") > 0:
startindex = output.find('temperature') + len('temperature') + 1
endindex = output[startindex:].find(" ")
endindex = startindex + endindex
temp = output[startindex:endindex]
b = temp.find('.')
if b > 0:
temp=temp[:b]
temp = int(temp)
else:
misclogger.error("Failed to get temperature.")
temp = 0
return int(temp)
def system_monitor_temperature():
ctemp1, ctemp2, ctemp3 = system_get_coretemp()
btemp1, btemp2 = system_get_boardtemp()
ltemp = system_get_lswtemp()
fan_speed_str = system_cs6436_getfanexspeed()
fan_speed = int(fan_speed_str)
policy = 'stay'
pos = 0
#speed c1 c2 c3 b1 b2 lsw
fan_policy_up = ([30, 40000, 40000, 40000, 42000, 35000, 95],
[40, 44000, 44000, 44000, 44000, 39000, 96],
[50, 49000, 49000, 49000, 47000, 44000, 91],
[60, 52000, 52000, 52000, 51500, 47500, 92],
[70, 53000, 53000, 53000, 52000, 49000, 93],
[100,999999,999999,999999,999999,999999,999])
fan_policy_down=([30, 0, 0, 0, 0, 0, 0],
[40, 34000, 34000, 34000, 34000, 30000, 80],
[50, 38000, 38000, 38000, 37000, 33000, 81],
[60, 44000, 44000, 44000, 43000, 39000, 84],
[70, 44000, 44000, 44000, 43000, 40000, 84],
[100, 48000, 48000, 48000, 46000, 42000, 85],)
for policytable in fan_policy_up:
if fan_speed <= policytable[0]:
break
pos = pos + 1
fan_speed = policytable[0]
if (ctemp1 < policytable[1]) and (ctemp2 < policytable[2]) and (ctemp3 < policytable[3]) and (btemp1 < policytable[4]) and (btemp2 < policytable[5]) and (ltemp < policytable[6]):
policy = 'stay'
policytable = fan_policy_down[pos]
if (ctemp1 < policytable[1]) and (ctemp2 < policytable[2]) and (ctemp3 < policytable[3]) and (btemp1 < policytable[4]) and (btemp2 < policytable[5]) and (ltemp < policytable[6]):
policy = 'down'
else:
policy = 'up'
if policy == 'up':
misclogger.info("speed = %d." % fan_speed)
misclogger.info("core1 = %d, core2 = %d, core3 = %d." % (ctemp1, ctemp2, ctemp3))
misclogger.info("board1 = %d, board2 = %d." % (btemp1, btemp2))
misclogger.info("lsw = %d" % ltemp)
fan_speed = fan_policy_down[pos + 1][0]
misclogger.info("fan policy: up. speedexp = {}".format(fan_speed))
if policy == 'stay':
fan_speed = fan_policy_down[pos]
return
if policy == 'down':
misclogger.info("speed = %d." % fan_speed)
misclogger.info("core1 = %d, core2 = %d, core3 = %d." % (ctemp1, ctemp2, ctemp3))
misclogger.info("board1 = %d, board2 = %d." % (btemp1, btemp2))
misclogger.info("lsw = %d" % ltemp)
fan_speed = fan_policy_down[pos - 1][0]
misclogger.info("fan policy: down.speedexp = {}".format(fan_speed))
cmd = "echo %d > /sys/devices/platform/cs6436_56p_fan/fan_duty_cycle_percentage" % fan_speed
status, output = log_os_system(cmd, 1)
if status:
misclogger.error("set fan speed fault")
return
def system_cs6436_setfanexspeed(num):
fanspeednode = fans_prefix + 'fan_duty_cycle_percentage'
numstr = str(num)
with open(fanspeednode, 'w') as f:
f.write(numstr)
def system_cs6436_getfanexspeed():
fanspeednode = fans_prefix + 'fan_duty_cycle_percentage'
fanspeedstr = system_read_filestr(fanspeednode)
fanspeedexp = int(fanspeedstr)
return fanspeedexp
def system_cs6436_getdirection():
global cs6436_fanattrnodes
direction = 0
for fan in cs6436_fanattrnodes:
direction = direction + fan.direction
if direction > 2:
direction = 1
else:
direction = 0
return direction
def system_check_psusdirection():
global cs6436_psuattrnodes
cs6436totaldirct = system_cs6436_getdirection()
psutatus = 0
for psu in cs6436_psuattrnodes:
psu.updatedirection()
psu.checkstatus(cs6436totaldirct)
psutatus = psu.status + psutatus
return (psutatus != 0)
def system_check_psuspresent():
global cs6436_psuattrnodes
cs6436totaldirct = system_cs6436_getdirection()
psutatus = 0
for psu in cs6436_psuattrnodes:
psu.updatepresent()
psu.checkstatus(cs6436totaldirct)
psutatus = psu.status + psutatus
return (psutatus != 0)
def system_check_fansstate():
global cs6436_fanattrnodes
global cs6436_ledpath
cs6436totaldirct = system_cs6436_getdirection()
fanstatus = 0
fanexspeed = 0
fanexspeed = system_cs6436_getfanexspeed()
for fan in cs6436_fanattrnodes:
fan.updatedevice()
fan.checkstatus(fanexspeed, cs6436totaldirct)
fanstatus = fanstatus + fan.status
if fanstatus > 0:
misclogger.error(':fan error.set fans speed 100.')
system_cs6436_setfanexspeed(100)
system_bright_leds(cs6436_ledpath['fan'], 3)
else:
system_bright_leds(cs6436_ledpath['fan'], 1)
return (fanstatus != 0)
def system_misc_polling(threadName,delay):
for count in range(1,5):
if device_exist() == False:
@ -66,89 +529,46 @@ def system_misc_polling(threadName,delay):
status, output = log_os_system("echo 1 > /sys/devices/platform/cs6436_56p_led/leds/cs6436_56p_led::sys/brightness", 1)
status, output = log_os_system("hwconfig -cfp 1", 1)
global AGFlag
if os.access(ageing_controlfile, os.F_OK):
AGFlag = 1
else:
AGFlag = 0
os.system('csw_daemon &')
global cs6436_fanattrnodes
global cs6436_psuattrnodes
for num in range(1,6):
name = 'fan{}'.format(num)
fannode = cs6436_fanattr(name)
cs6436_fanattrnodes.append(fannode)
for num in range(1,3):
name = 'psu{}'.format(num)
psunode = cs6436_psuattr(name)
cs6436_psuattrnodes.append(psunode)
tempcontrol = system_init_coretemppath()
misclogger.info("%s: %s misc start." % ( threadName, time.ctime(time.time())))
count = 0
while 1:
status, output = log_os_system("cat /sys/bus/i2c/devices/5-005a/psu_present", 1)
if status:
print "failed to check status for 5-005a/psu_present"
continue
count = count + 1
ret = system_check_psuspresent()
ret = system_check_fansstate()
if output=='1':
log_os_system("echo 1 > /sys/devices/platform/cs6436_56p_led/leds/cs6436_56p_led::psu1/brightness", 1)
else:
log_os_system("echo 0 > /sys/devices/platform/cs6436_56p_led/leds/cs6436_56p_led::psu1/brightness", 1)
status, output = log_os_system("cat /sys/bus/i2c/devices/5-005b/psu_present", 1)
if status:
print "failed to check status for 5-005b/psu_present"
continue
if output=='1':
log_os_system("echo 1 > /sys/devices/platform/cs6436_56p_led/leds/cs6436_56p_led::psu2/brightness", 1)
else:
log_os_system("echo 0 > /sys/devices/platform/cs6436_56p_led/leds/cs6436_56p_led::psu2/brightness", 1)
status, fan1 = log_os_system(" cat /sys/devices/platform/cs6436_56p_fan/fan1_fault",1)
if status:
print "failed to check status for cs6436_56p_fan/fan1_fault"
continue
if fan1=='0':
log_os_system("echo 1 > /sys/devices/platform/cs6436_56p_led/leds/cs6436_56p_led::fan1/brightness", 1)
else:
log_os_system("echo 3 > /sys/devices/platform/cs6436_56p_led/leds/cs6436_56p_led::fan1/brightness", 1)
status, fan2 = log_os_system(" cat /sys/devices/platform/cs6436_56p_fan/fan2_fault",1)
if status:
print "failed to check status for cs6436_56p_fan/fan2_fault"
continue
if fan2=='0':
log_os_system("echo 1 > /sys/devices/platform/cs6436_56p_led/leds/cs6436_56p_led::fan2/brightness", 1)
else:
log_os_system("echo 3 > /sys/devices/platform/cs6436_56p_led/leds/cs6436_56p_led::fan2/brightness", 1)
status, fan3 = log_os_system(" cat /sys/devices/platform/cs6436_56p_fan/fan3_fault",1)
if status:
print "failed to check status for cs6436_56p_fan/fan3_fault"
continue
if fan3=='0':
log_os_system("echo 1 > /sys/devices/platform/cs6436_56p_led/leds/cs6436_56p_led::fan3/brightness", 1)
else:
log_os_system("echo 3 > /sys/devices/platform/cs6436_56p_led/leds/cs6436_56p_led::fan3/brightness", 1)
status, fan4 = log_os_system(" cat /sys/devices/platform/cs6436_56p_fan/fan4_fault",1)
if status:
print "failed to check status for cs6436_56p_fan/fan4_fault"
continue
if fan4=='0':
log_os_system("echo 1 > /sys/devices/platform/cs6436_56p_led/leds/cs6436_56p_led::fan4/brightness", 1)
else:
log_os_system("echo 3 > /sys/devices/platform/cs6436_56p_led/leds/cs6436_56p_led::fan4/brightness", 1)
status, fan5 = log_os_system(" cat /sys/devices/platform/cs6436_56p_fan/fan5_fault",1)
if status:
print "failed to check status for cs6436_56p_fan/fan5_fault"
continue
if fan5=='0':
log_os_system("echo 1 > /sys/devices/platform/cs6436_56p_led/leds/cs6436_56p_led::fan5/brightness", 1)
else:
log_os_system("echo 3 > /sys/devices/platform/cs6436_56p_led/leds/cs6436_56p_led::fan5/brightness", 1)
if fan1=='0' or fan2=='0' or fan3=='0' or fan4=='0' or fan5=='0':
log_os_system("echo 1 > /sys/devices/platform/cs6436_56p_led/leds/cs6436_56p_led::fan/brightness", 1)
else:
log_os_system("echo 3 > /sys/devices/platform/cs6436_56p_led/leds/cs6436_56p_led::fan/brightness", 1)
if count % 10 == 0:
misclogger.info(": adjust fans and check psu direction.")
system_check_psusdirection()
if tempcontrol == 0:
system_monitor_temperature()
count = 0
time.sleep(delay)
print "%s: %s" % ( threadName, time.ctime(time.time()))
return
if __name__ == '__main__':
target=system_misc_polling("Thread-misc",3)
target=system_misc_polling("Thread-misc",10)

View File

@ -42,13 +42,14 @@ from collections import namedtuple
PROJECT_NAME = 'cs6436_56p'
version = '0.1.0'
version = '0.1.1'
verbose = False
DEBUG = False
args = []
ALL_DEVICE = {}
DEVICE_NO = {'led':9, 'fan':5, 'thermal':4, 'psu':2, 'sfp':56}
FORCE = 0
CPU_TYPE = 'C3308'
if DEBUG == True:
print sys.argv[0]
@ -167,6 +168,7 @@ kos = [
'depmod',
'modprobe i2c_dev',
'modprobe i2c_mux_pca954x force_deselect_on_exit=1',
'modprobe x86-64-cig-cs6436-56p-sysfs ' ,
'modprobe x86-64-cig-cs6436-56p-cpld ' ,
'modprobe x86-64-cig-cs6436-56p-fan' ,
'modprobe x86-64-cig-cs6436-56p-psu' ,
@ -177,10 +179,13 @@ def driver_install():
global FORCE
for i in range(0,len(kos)):
if i == 3:
ret, board_type = log_os_system("cat /proc/cpuinfo | grep \"model name\" | cut -b 32-39 | head -n 1", 0)
if board_type=='i3-6100U':
if i == 4:
ret, CPU_TYPE = log_os_system("cat /proc/cpuinfo | grep \"model name\" | cut -b 32-39 | head -n 1", 0)
if CPU_TYPE=='i3-6100U':
kos[i] =kos[i] + 'board_id=1'
ret, CPU_TYPE = log_os_system("cat /proc/cpuinfo | grep \"model name\" | cut -b 36-40 | head -n 1", 0)
if CPU_TYPE=='C3758' or CPU_TYPE=='C3308':
kos[i] =kos[i] + 'board_id=2'
status, output = log_os_system(kos[i], 1)
if status:
@ -247,8 +252,7 @@ def device_install():
global FORCE
for i in range(0,len(mknod)):
#for pca954x need times to built new i2c buses
if mknod[i].find('pca954') != -1:
#all nodes need times to built new i2c buses
time.sleep(1)
status, output = log_os_system(mknod[i], 1)
@ -497,6 +501,16 @@ def get_value(input):
digit = re.findall('\d+', input)
return int(digit[0])
def get_ledname(ledx):
name_table={'led1':'SYS','led2':'FSTUS','led3':'FAN1','led4':'FAN2','led5':'FAN3','led6':'FAN4','led7':'FAN5','led8':'PSU1','led9':'PSU2'}
if name_table.has_key(ledx):
name = name_table[ledx]
else:
name = ledx
return name
def device_traversal():
if system_ready()==False:
print("System's not ready.")
@ -511,7 +525,11 @@ def device_traversal():
print("============================================")
for j in sorted(ALL_DEVICE[i].keys(), key=get_value):
nwnamex = get_ledname(j)
if nwnamex == j:
print " "+j+":",
else:
print " "+nwnamex+":",
for k in (ALL_DEVICE[i][j]):
ret, log = log_os_system("cat "+k, 0)
func = k.split("/")[-1].strip()

View File

View File

View File

@ -7,5 +7,15 @@ Standards-Version: 3.9.3
Package: sonic-platform-cig-cs6436-56p
Architecture: amd64
Depends: linux-image-4.9.0-9-amd64
Depends: linux-image-4.9.0-11-2-amd64
Description: kernel modules for platform devices such as fan, led, sfp
Package: sonic-platform-cig-cs6436-54p
Architecture: amd64
Depends: linux-image-4.9.0-11-2-amd64
Description: kernel modules for platform devices such as fan, led, sfp
Package: sonic-platform-cig-cs5435-54p
Architecture: amd64
Depends: linux-image-4.9.0-11-2-amd64
Description: kernel modules for platform devices such as fan, led, sfp

View File

@ -19,7 +19,7 @@ PACKAGE_PRE_NAME := sonic-platform-cig
KVERSION ?= $(shell uname -r)
KERNEL_SRC := /lib/modules/$(KVERSION)
MOD_SRC_DIR:= $(shell pwd)
MODULE_DIRS:= cs6436-56p
MODULE_DIRS:= cs6436-56p cs6436-54p cs5435-54p
MODULE_DIR := modules
UTILS_DIR := utils
SERVICE_DIR := service
@ -59,11 +59,12 @@ binary-indep:
# Custom package commands
(for mod in $(MODULE_DIRS); do \
dh_installdirs -p$(PACKAGE_PRE_NAME)-$${mod}/$(KERNEL_SRC)/$(INSTALL_MOD_DIR); \
dh_installdirs -p$(PACKAGE_PRE_NAME)-$${mod} /$(KERNEL_SRC)/$(INSTALL_MOD_DIR); \
dh_installdirs -p$(PACKAGE_PRE_NAME)-$${mod}/usr/local/bin; \
dh_installdirs -p$(PACKAGE_PRE_NAME)-$${mod}/lib/systemd/system; \
dh_installdirs -p$(PACKAGE_PRE_NAME)-$${mod}/etc/sonic; \
cp $(MOD_SRC_DIR)/$${mod}/$(MODULE_DIR)/*.ko debian/$(PACKAGE_PRE_NAME)-$${mod}/$(KERNEL_SRC)/$(INSTALL_MOD_DIR); \
cp $(MOD_SRC_DIR)/$${mod}/$(UTILS_DIR)/* debian/$(PACKAGE_PRE_NAME)-$${mod}/usr/local/bin/; \
cp $(MOD_SRC_DIR)/$${mod}/$(UTILS_DIR)/*.py debian/$(PACKAGE_PRE_NAME)-$${mod}/usr/local/bin/; \
cp $(MOD_SRC_DIR)/$${mod}/$(SERVICE_DIR)/*.service debian/$(PACKAGE_PRE_NAME)-$${mod}/lib/systemd/system/; \
$(PYTHON) $${mod}/setup.py install --root=$(MOD_SRC_DIR)/debian/$(PACKAGE_PRE_NAME)-$${mod} --install-layout=deb; \
done)