Remove exsiting sonic-platform-modules-accton and apply submodule add… (#717)
* Remove exsiting sonic-platform-modules-accton and apply submodule adding on this folder. * Remove redundant commnet * Remove folder platform/broadcom/sonic-platform-modules-accton. * Add this dir for submodule.
This commit is contained in:
parent
c4133e166b
commit
66859385b6
3
.gitmodules
vendored
3
.gitmodules
vendored
@ -63,3 +63,6 @@
|
|||||||
[submodule "src/sonic-platform-daemons"]
|
[submodule "src/sonic-platform-daemons"]
|
||||||
path = src/sonic-platform-daemons
|
path = src/sonic-platform-daemons
|
||||||
url = https://github.com/Azure/sonic-platform-daemons
|
url = https://github.com/Azure/sonic-platform-daemons
|
||||||
|
[submodule "platform/broadcom/sonic-platform-modules-accton"]
|
||||||
|
path = platform/broadcom/sonic-platform-modules-accton
|
||||||
|
url = https://github.com/edge-core/sonic-platform-modules-accton.git
|
||||||
|
24
device/accton/x86_64-accton_as7712_32x-r0/plugins/eeprom.py
Normal file
24
device/accton/x86_64-accton_as7712_32x-r0/plugins/eeprom.py
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
#!/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/1-0057/eeprom"
|
||||||
|
#Two i2c buses might get flipped order, check them both.
|
||||||
|
if not os.path.exists(self.eeprom_path):
|
||||||
|
self.eeprom_path = "/sys/bus/i2c/devices/0-0057/eeprom"
|
||||||
|
super(board, self).__init__(self.eeprom_path, 0, '', True)
|
60
device/accton/x86_64-accton_as7712_32x-r0/plugins/sfputil.py
Normal file
60
device/accton/x86_64-accton_as7712_32x-r0/plugins/sfputil.py
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
|
||||||
|
try:
|
||||||
|
from sonic_sfp.sfputilbase import sfputilbase
|
||||||
|
except ImportError, e:
|
||||||
|
raise ImportError (str(e) + "- required module not found")
|
||||||
|
|
||||||
|
|
||||||
|
class sfputil(sfputilbase):
|
||||||
|
"""Platform specific sfputil class"""
|
||||||
|
|
||||||
|
port_start = 0
|
||||||
|
port_end = 31
|
||||||
|
ports_in_block = 32
|
||||||
|
|
||||||
|
port_to_eeprom_mapping = {}
|
||||||
|
port_to_i2c_mapping = {
|
||||||
|
9 : 18,
|
||||||
|
10 : 19,
|
||||||
|
11 : 20,
|
||||||
|
12 : 21,
|
||||||
|
1 : 22,
|
||||||
|
2 : 23,
|
||||||
|
3 : 24,
|
||||||
|
4 : 25,
|
||||||
|
6 : 26,
|
||||||
|
5 : 27,
|
||||||
|
8 : 28,
|
||||||
|
7 : 29,
|
||||||
|
13 : 30,
|
||||||
|
14 : 31,
|
||||||
|
15 : 32,
|
||||||
|
16 : 33,
|
||||||
|
17 : 34,
|
||||||
|
18 : 35,
|
||||||
|
19 : 36,
|
||||||
|
20 : 37,
|
||||||
|
25 : 38,
|
||||||
|
26 : 39,
|
||||||
|
27 : 40,
|
||||||
|
28 : 41,
|
||||||
|
29 : 42,
|
||||||
|
30 : 43,
|
||||||
|
31 : 44,
|
||||||
|
32 : 45,
|
||||||
|
21 : 46,
|
||||||
|
22 : 47,
|
||||||
|
23 : 48,
|
||||||
|
24 : 49,
|
||||||
|
}
|
||||||
|
|
||||||
|
_qsfp_ports = range(0, ports_in_block + 1)
|
||||||
|
|
||||||
|
def __init__(self, port_num):
|
||||||
|
# Override port_to_eeprom_mapping for class initialization
|
||||||
|
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+1])
|
||||||
|
self.port_to_eeprom_mapping[x] = port_eeprom_path
|
||||||
|
sfputilbase.__init__(self, port_num)
|
@ -4,11 +4,8 @@ ACCTON_AS7712_32X_PLATFORM_MODULE_VERSION = 1.0
|
|||||||
|
|
||||||
export ACCTON_AS7712_32X_PLATFORM_MODULE_VERSION
|
export ACCTON_AS7712_32X_PLATFORM_MODULE_VERSION
|
||||||
|
|
||||||
ACCTON_AS7712_32X_PLATFORM_MODULE = platform-modules-as7712-32x_$(ACCTON_AS7712_32X_PLATFORM_MODULE_VERSION)_amd64.deb
|
ACCTON_AS7712_32X_PLATFORM_MODULE = sonic-platform-accton-as7712-32x_$(ACCTON_AS7712_32X_PLATFORM_MODULE_VERSION)_amd64.deb
|
||||||
$(ACCTON_AS7712_32X_PLATFORM_MODULE)_SRC_PATH = $(PLATFORM_PATH)/sonic-platform-modules-accton
|
$(ACCTON_AS7712_32X_PLATFORM_MODULE)_SRC_PATH = $(PLATFORM_PATH)/sonic-platform-modules-accton
|
||||||
$(ACCTON_AS7712_32X_PLATFORM_MODULE)_DEPENDS += $(LINUX_HEADERS) $(LINUX_HEADERS_COMMON)
|
$(ACCTON_AS7712_32X_PLATFORM_MODULE)_DEPENDS += $(LINUX_HEADERS) $(LINUX_HEADERS_COMMON)
|
||||||
$(ACCTON_AS7712_32X_PLATFORM_MODULE)_PLATFORM = x86_64-accton_as7712_32x-r0
|
$(ACCTON_AS7712_32X_PLATFORM_MODULE)_PLATFORM = x86_64-accton_as7712_32x-r0
|
||||||
SONIC_DPKG_DEBS += $(ACCTON_AS7712_32X_PLATFORM_MODULE)
|
SONIC_DPKG_DEBS += $(ACCTON_AS7712_32X_PLATFORM_MODULE)
|
||||||
|
|
||||||
$(eval $(call add_extra_package,$(ACCTON_AS7712_32X_PLATFORM_MODULE)))
|
|
||||||
|
|
||||||
|
1
platform/broadcom/sonic-platform-modules-accton
Submodule
1
platform/broadcom/sonic-platform-modules-accton
Submodule
@ -0,0 +1 @@
|
|||||||
|
Subproject commit 99607d63220de336a61d81f6b4d1e64062761abe
|
@ -1,33 +0,0 @@
|
|||||||
# Object files
|
|
||||||
*.o
|
|
||||||
*.ko
|
|
||||||
*.obj
|
|
||||||
*.elf
|
|
||||||
|
|
||||||
# Precompiled Headers
|
|
||||||
*.gch
|
|
||||||
*.pch
|
|
||||||
|
|
||||||
# Libraries
|
|
||||||
*.lib
|
|
||||||
*.a
|
|
||||||
*.la
|
|
||||||
*.lo
|
|
||||||
|
|
||||||
# Shared objects (inc. Windows DLLs)
|
|
||||||
*.dll
|
|
||||||
*.so
|
|
||||||
*.so.*
|
|
||||||
*.dylib
|
|
||||||
|
|
||||||
# Executables
|
|
||||||
*.exe
|
|
||||||
*.out
|
|
||||||
*.app
|
|
||||||
*.i*86
|
|
||||||
*.x86_64
|
|
||||||
*.hex
|
|
||||||
|
|
||||||
# Debug files
|
|
||||||
*.dSYM/
|
|
||||||
*.su
|
|
@ -1,16 +0,0 @@
|
|||||||
Copyright (C) 2016 Microsoft, Inc
|
|
||||||
Copyright (C) 2017 Accton Technology Corporation
|
|
||||||
|
|
||||||
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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
@ -1 +0,0 @@
|
|||||||
platform drivers for AS7712_32X for the SONiC project
|
|
@ -1,13 +0,0 @@
|
|||||||
# /etc/modules: kernel modules to load at boot time.
|
|
||||||
#
|
|
||||||
# This file contains the names of kernel modules that should be loaded
|
|
||||||
# at boot time, one per line. Lines beginning with "#" are ignored.
|
|
||||||
|
|
||||||
i2c_dev
|
|
||||||
i2c_mux_pca954x
|
|
||||||
accton_i2c_cpld
|
|
||||||
accton_as7712_32x_fan
|
|
||||||
accton_as7712_32x_sfp
|
|
||||||
leds-accton_as7712_32x
|
|
||||||
accton_as7712_32x_psu
|
|
||||||
|
|
@ -1,2 +0,0 @@
|
|||||||
obj-m:=accton_as7712_32x_fan.o accton_as7712_32x_sfp.o leds-accton_as7712_32x.o \
|
|
||||||
accton_as7712_32x_psu.o accton_i2c_cpld.o ym2651y.o
|
|
@ -1,452 +0,0 @@
|
|||||||
/*
|
|
||||||
* A hwmon driver for the Accton as7712 32x fan
|
|
||||||
*
|
|
||||||
* Copyright (C) 2014 Accton Technology Corporation.
|
|
||||||
* Brandon Chuang <brandon_chuang@accton.com.tw>
|
|
||||||
*
|
|
||||||
* 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/dmi.h>
|
|
||||||
|
|
||||||
#define DRVNAME "as7712_32x_fan"
|
|
||||||
|
|
||||||
static struct as7712_32x_fan_data *as7712_32x_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);
|
|
||||||
extern int accton_i2c_cpld_read(unsigned short cpld_addr, u8 reg);
|
|
||||||
extern int accton_i2c_cpld_write(unsigned short cpld_addr, u8 reg, u8 value);
|
|
||||||
|
|
||||||
/* fan related data, the index should match sysfs_fan_attributes
|
|
||||||
*/
|
|
||||||
static const u8 fan_reg[] = {
|
|
||||||
0x0F, /* fan 1-6 present status */
|
|
||||||
0x11, /* fan PWM(for all fan) */
|
|
||||||
0x12, /* front fan 1 speed(rpm) */
|
|
||||||
0x13, /* front fan 2 speed(rpm) */
|
|
||||||
0x14, /* front fan 3 speed(rpm) */
|
|
||||||
0x15, /* front fan 4 speed(rpm) */
|
|
||||||
0x16, /* front fan 5 speed(rpm) */
|
|
||||||
0x17, /* front fan 6 speed(rpm) */
|
|
||||||
0x22, /* rear fan 1 speed(rpm) */
|
|
||||||
0x23, /* rear fan 2 speed(rpm) */
|
|
||||||
0x24, /* rear fan 3 speed(rpm) */
|
|
||||||
0x25, /* rear fan 4 speed(rpm) */
|
|
||||||
0x26, /* rear fan 5 speed(rpm) */
|
|
||||||
0x27, /* rear fan 6 speed(rpm) */
|
|
||||||
};
|
|
||||||
|
|
||||||
/* Each client has this additional data */
|
|
||||||
struct as7712_32x_fan_data {
|
|
||||||
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 */
|
|
||||||
};
|
|
||||||
|
|
||||||
enum fan_id {
|
|
||||||
FAN1_ID,
|
|
||||||
FAN2_ID,
|
|
||||||
FAN3_ID,
|
|
||||||
FAN4_ID,
|
|
||||||
FAN5_ID,
|
|
||||||
FAN6_ID
|
|
||||||
};
|
|
||||||
|
|
||||||
enum sysfs_fan_attributes {
|
|
||||||
FAN_PRESENT_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,
|
|
||||||
FAN6_FRONT_SPEED_RPM,
|
|
||||||
FAN1_REAR_SPEED_RPM,
|
|
||||||
FAN2_REAR_SPEED_RPM,
|
|
||||||
FAN3_REAR_SPEED_RPM,
|
|
||||||
FAN4_REAR_SPEED_RPM,
|
|
||||||
FAN5_REAR_SPEED_RPM,
|
|
||||||
FAN6_REAR_SPEED_RPM,
|
|
||||||
FAN1_PRESENT,
|
|
||||||
FAN2_PRESENT,
|
|
||||||
FAN3_PRESENT,
|
|
||||||
FAN4_PRESENT,
|
|
||||||
FAN5_PRESENT,
|
|
||||||
FAN6_PRESENT,
|
|
||||||
FAN1_FAULT,
|
|
||||||
FAN2_FAULT,
|
|
||||||
FAN3_FAULT,
|
|
||||||
FAN4_FAULT,
|
|
||||||
FAN5_FAULT,
|
|
||||||
FAN6_FAULT
|
|
||||||
};
|
|
||||||
|
|
||||||
/* Define attributes
|
|
||||||
*/
|
|
||||||
#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_DIRECTION_SENSOR_DEV_ATTR(index) \
|
|
||||||
static SENSOR_DEVICE_ATTR(fan##index##_direction, S_IRUGO, fan_show_value, NULL, FAN##index##_DIRECTION)
|
|
||||||
#define DECLARE_FAN_DIRECTION_ATTR(index) &sensor_dev_attr_fan##index##_direction.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_PRESENT_SENSOR_DEV_ATTR(index) \
|
|
||||||
static SENSOR_DEVICE_ATTR(fan##index##_present, S_IRUGO, fan_show_value, NULL, FAN##index##_PRESENT)
|
|
||||||
#define DECLARE_FAN_PRESENT_ATTR(index) &sensor_dev_attr_fan##index##_present.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
|
|
||||||
|
|
||||||
/* 6 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);
|
|
||||||
DECLARE_FAN_FAULT_SENSOR_DEV_ATTR(6);
|
|
||||||
/* 6 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);
|
|
||||||
DECLARE_FAN_SPEED_RPM_SENSOR_DEV_ATTR(6);
|
|
||||||
/* 6 fan present attributes in this platform */
|
|
||||||
DECLARE_FAN_PRESENT_SENSOR_DEV_ATTR(1);
|
|
||||||
DECLARE_FAN_PRESENT_SENSOR_DEV_ATTR(2);
|
|
||||||
DECLARE_FAN_PRESENT_SENSOR_DEV_ATTR(3);
|
|
||||||
DECLARE_FAN_PRESENT_SENSOR_DEV_ATTR(4);
|
|
||||||
DECLARE_FAN_PRESENT_SENSOR_DEV_ATTR(5);
|
|
||||||
DECLARE_FAN_PRESENT_SENSOR_DEV_ATTR(6);
|
|
||||||
/* 1 fan duty cycle attribute in this platform */
|
|
||||||
DECLARE_FAN_DUTY_CYCLE_SENSOR_DEV_ATTR();
|
|
||||||
|
|
||||||
static struct attribute *as7712_32x_fan_attributes[] = {
|
|
||||||
/* fan related attributes */
|
|
||||||
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_FAULT_ATTR(6),
|
|
||||||
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_SPEED_RPM_ATTR(6),
|
|
||||||
DECLARE_FAN_PRESENT_ATTR(1),
|
|
||||||
DECLARE_FAN_PRESENT_ATTR(2),
|
|
||||||
DECLARE_FAN_PRESENT_ATTR(3),
|
|
||||||
DECLARE_FAN_PRESENT_ATTR(4),
|
|
||||||
DECLARE_FAN_PRESENT_ATTR(5),
|
|
||||||
DECLARE_FAN_PRESENT_ATTR(6),
|
|
||||||
DECLARE_FAN_DUTY_CYCLE_ATTR(),
|
|
||||||
NULL
|
|
||||||
};
|
|
||||||
|
|
||||||
#define FAN_DUTY_CYCLE_REG_MASK 0xF
|
|
||||||
#define FAN_MAX_DUTY_CYCLE 100
|
|
||||||
#define FAN_REG_VAL_TO_SPEED_RPM_STEP 100
|
|
||||||
|
|
||||||
static int as7712_32x_fan_read_value(struct i2c_client *client, u8 reg)
|
|
||||||
{
|
|
||||||
return i2c_smbus_read_byte_data(client, reg);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int as7712_32x_fan_write_value(struct i2c_client *client, u8 reg, u8 value)
|
|
||||||
{
|
|
||||||
return i2c_smbus_write_byte_data(client, reg, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* fan utility functions
|
|
||||||
*/
|
|
||||||
static u32 reg_val_to_duty_cycle(u8 reg_val)
|
|
||||||
{
|
|
||||||
reg_val &= FAN_DUTY_CYCLE_REG_MASK;
|
|
||||||
return ((u32)(reg_val+1) * 625 + 75)/ 100;
|
|
||||||
}
|
|
||||||
|
|
||||||
static u8 duty_cycle_to_reg_val(u8 duty_cycle)
|
|
||||||
{
|
|
||||||
return ((u32)duty_cycle * 100 / 625) - 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
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_present(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 as7712_32x_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;
|
|
||||||
struct i2c_client *client = to_i2c_client(dev);
|
|
||||||
|
|
||||||
error = kstrtoint(buf, 10, &value);
|
|
||||||
if (error)
|
|
||||||
return error;
|
|
||||||
|
|
||||||
if (value < 0 || value > FAN_MAX_DUTY_CYCLE)
|
|
||||||
return -EINVAL;
|
|
||||||
|
|
||||||
as7712_32x_fan_write_value(client, 0x33, 0); /* Disable fan speed watch dog */
|
|
||||||
as7712_32x_fan_write_value(client, fan_reg[FAN_DUTY_CYCLE_PERCENTAGE], duty_cycle_to_reg_val(value));
|
|
||||||
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);
|
|
||||||
struct as7712_32x_fan_data *data = as7712_32x_fan_update_device(dev);
|
|
||||||
ssize_t ret = 0;
|
|
||||||
|
|
||||||
if (data->valid) {
|
|
||||||
switch (attr->index) {
|
|
||||||
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 FAN6_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:
|
|
||||||
case FAN6_REAR_SPEED_RPM:
|
|
||||||
ret = sprintf(buf, "%u\n", reg_val_to_speed_rpm(data->reg_val[attr->index]));
|
|
||||||
break;
|
|
||||||
case FAN1_PRESENT:
|
|
||||||
case FAN2_PRESENT:
|
|
||||||
case FAN3_PRESENT:
|
|
||||||
case FAN4_PRESENT:
|
|
||||||
case FAN5_PRESENT:
|
|
||||||
case FAN6_PRESENT:
|
|
||||||
ret = sprintf(buf, "%d\n",
|
|
||||||
reg_val_to_is_present(data->reg_val[FAN_PRESENT_REG],
|
|
||||||
attr->index - FAN1_PRESENT));
|
|
||||||
break;
|
|
||||||
case FAN1_FAULT:
|
|
||||||
case FAN2_FAULT:
|
|
||||||
case FAN3_FAULT:
|
|
||||||
case FAN4_FAULT:
|
|
||||||
case FAN5_FAULT:
|
|
||||||
case FAN6_FAULT:
|
|
||||||
ret = sprintf(buf, "%d\n", is_fan_fault(data, attr->index - FAN1_FAULT));
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
static const struct attribute_group as7712_32x_fan_group = {
|
|
||||||
.attrs = as7712_32x_fan_attributes,
|
|
||||||
};
|
|
||||||
|
|
||||||
static struct as7712_32x_fan_data *as7712_32x_fan_update_device(struct device *dev)
|
|
||||||
{
|
|
||||||
struct i2c_client *client = to_i2c_client(dev);
|
|
||||||
struct as7712_32x_fan_data *data = i2c_get_clientdata(client);
|
|
||||||
|
|
||||||
mutex_lock(&data->update_lock);
|
|
||||||
|
|
||||||
if (time_after(jiffies, data->last_updated + HZ + HZ / 2) ||
|
|
||||||
!data->valid) {
|
|
||||||
int i;
|
|
||||||
|
|
||||||
dev_dbg(&client->dev, "Starting as7712_32x_fan update\n");
|
|
||||||
data->valid = 0;
|
|
||||||
|
|
||||||
/* Update fan data
|
|
||||||
*/
|
|
||||||
for (i = 0; i < ARRAY_SIZE(data->reg_val); i++) {
|
|
||||||
int status = as7712_32x_fan_read_value(client, fan_reg[i]);
|
|
||||||
|
|
||||||
if (status < 0) {
|
|
||||||
data->valid = 0;
|
|
||||||
mutex_unlock(&data->update_lock);
|
|
||||||
dev_dbg(&client->dev, "reg %d, err %d\n", fan_reg[i], status);
|
|
||||||
return data;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
data->reg_val[i] = status;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
data->last_updated = jiffies;
|
|
||||||
data->valid = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
mutex_unlock(&data->update_lock);
|
|
||||||
|
|
||||||
return data;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int as7712_32x_fan_probe(struct i2c_client *client,
|
|
||||||
const struct i2c_device_id *dev_id)
|
|
||||||
{
|
|
||||||
struct as7712_32x_fan_data *data;
|
|
||||||
int status;
|
|
||||||
|
|
||||||
if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) {
|
|
||||||
status = -EIO;
|
|
||||||
goto exit;
|
|
||||||
}
|
|
||||||
|
|
||||||
data = kzalloc(sizeof(struct as7712_32x_fan_data), GFP_KERNEL);
|
|
||||||
if (!data) {
|
|
||||||
status = -ENOMEM;
|
|
||||||
goto exit;
|
|
||||||
}
|
|
||||||
|
|
||||||
i2c_set_clientdata(client, data);
|
|
||||||
data->valid = 0;
|
|
||||||
mutex_init(&data->update_lock);
|
|
||||||
|
|
||||||
dev_info(&client->dev, "chip found\n");
|
|
||||||
|
|
||||||
/* Register sysfs hooks */
|
|
||||||
status = sysfs_create_group(&client->dev.kobj, &as7712_32x_fan_group);
|
|
||||||
if (status) {
|
|
||||||
goto exit_free;
|
|
||||||
}
|
|
||||||
|
|
||||||
data->hwmon_dev = hwmon_device_register(&client->dev);
|
|
||||||
if (IS_ERR(data->hwmon_dev)) {
|
|
||||||
status = PTR_ERR(data->hwmon_dev);
|
|
||||||
goto exit_remove;
|
|
||||||
}
|
|
||||||
|
|
||||||
dev_info(&client->dev, "%s: fan '%s'\n",
|
|
||||||
dev_name(data->hwmon_dev), client->name);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
exit_remove:
|
|
||||||
sysfs_remove_group(&client->dev.kobj, &as7712_32x_fan_group);
|
|
||||||
exit_free:
|
|
||||||
kfree(data);
|
|
||||||
exit:
|
|
||||||
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int as7712_32x_fan_remove(struct i2c_client *client)
|
|
||||||
{
|
|
||||||
struct as7712_32x_fan_data *data = i2c_get_clientdata(client);
|
|
||||||
hwmon_device_unregister(data->hwmon_dev);
|
|
||||||
sysfs_remove_group(&client->dev.kobj, &as7712_32x_fan_group);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Addresses to scan */
|
|
||||||
static const unsigned short normal_i2c[] = { 0x66, I2C_CLIENT_END };
|
|
||||||
|
|
||||||
static const struct i2c_device_id as7712_32x_fan_id[] = {
|
|
||||||
{ "as7712_32x_fan", 0 },
|
|
||||||
{}
|
|
||||||
};
|
|
||||||
MODULE_DEVICE_TABLE(i2c, as7712_32x_fan_id);
|
|
||||||
|
|
||||||
static struct i2c_driver as7712_32x_fan_driver = {
|
|
||||||
.class = I2C_CLASS_HWMON,
|
|
||||||
.driver = {
|
|
||||||
.name = DRVNAME,
|
|
||||||
},
|
|
||||||
.probe = as7712_32x_fan_probe,
|
|
||||||
.remove = as7712_32x_fan_remove,
|
|
||||||
.id_table = as7712_32x_fan_id,
|
|
||||||
.address_list = normal_i2c,
|
|
||||||
};
|
|
||||||
|
|
||||||
static int __init as7712_32x_fan_init(void)
|
|
||||||
{
|
|
||||||
extern int platform_accton_as7712_32x(void);
|
|
||||||
if (!platform_accton_as7712_32x()) {
|
|
||||||
return -ENODEV;
|
|
||||||
}
|
|
||||||
|
|
||||||
return i2c_add_driver(&as7712_32x_fan_driver);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void __exit as7712_32x_fan_exit(void)
|
|
||||||
{
|
|
||||||
i2c_del_driver(&as7712_32x_fan_driver);
|
|
||||||
}
|
|
||||||
|
|
||||||
module_init(as7712_32x_fan_init);
|
|
||||||
module_exit(as7712_32x_fan_exit);
|
|
||||||
|
|
||||||
MODULE_AUTHOR("Brandon Chuang <brandon_chuang@accton.com.tw>");
|
|
||||||
MODULE_DESCRIPTION("as7712_32x_fan driver");
|
|
||||||
MODULE_LICENSE("GPL");
|
|
||||||
|
|
@ -1,293 +0,0 @@
|
|||||||
/*
|
|
||||||
* An hwmon driver for accton as7712_32x Power Module
|
|
||||||
*
|
|
||||||
* Copyright (C) 2014 Accton Technology Corporation.
|
|
||||||
* Brandon Chuang <brandon_chuang@accton.com.tw>
|
|
||||||
*
|
|
||||||
* Based on ad7414.c
|
|
||||||
* Copyright 2006 Stefan Roese <sr at denx.de>, DENX Software Engineering
|
|
||||||
*
|
|
||||||
* 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>
|
|
||||||
|
|
||||||
static ssize_t show_status(struct device *dev, struct device_attribute *da, char *buf);
|
|
||||||
static ssize_t show_model_name(struct device *dev, struct device_attribute *da, char *buf);
|
|
||||||
static int as7712_32x_psu_read_block(struct i2c_client *client, u8 command, u8 *data,int data_len);
|
|
||||||
extern int accton_i2c_cpld_read(unsigned short cpld_addr, u8 reg);
|
|
||||||
|
|
||||||
/* Addresses scanned
|
|
||||||
*/
|
|
||||||
static const unsigned short normal_i2c[] = { 0x50, 0x53, I2C_CLIENT_END };
|
|
||||||
|
|
||||||
/* Each client has this additional data
|
|
||||||
*/
|
|
||||||
struct as7712_32x_psu_data {
|
|
||||||
struct device *hwmon_dev;
|
|
||||||
struct mutex update_lock;
|
|
||||||
char valid; /* !=0 if registers are valid */
|
|
||||||
unsigned long last_updated; /* In jiffies */
|
|
||||||
u8 index; /* PSU index */
|
|
||||||
u8 status; /* Status(present/power_good) register read from CPLD */
|
|
||||||
char model_name[9]; /* Model name, read from eeprom */
|
|
||||||
};
|
|
||||||
|
|
||||||
static struct as7712_32x_psu_data *as7712_32x_psu_update_device(struct device *dev);
|
|
||||||
|
|
||||||
enum as7712_32x_psu_sysfs_attributes {
|
|
||||||
PSU_PRESENT,
|
|
||||||
PSU_MODEL_NAME,
|
|
||||||
PSU_POWER_GOOD
|
|
||||||
};
|
|
||||||
|
|
||||||
/* sysfs attributes for hwmon
|
|
||||||
*/
|
|
||||||
static SENSOR_DEVICE_ATTR(psu_present, S_IRUGO, show_status, NULL, PSU_PRESENT);
|
|
||||||
static SENSOR_DEVICE_ATTR(psu_model_name, S_IRUGO, show_model_name,NULL, PSU_MODEL_NAME);
|
|
||||||
static SENSOR_DEVICE_ATTR(psu_power_good, S_IRUGO, show_status, NULL, PSU_POWER_GOOD);
|
|
||||||
|
|
||||||
static struct attribute *as7712_32x_psu_attributes[] = {
|
|
||||||
&sensor_dev_attr_psu_present.dev_attr.attr,
|
|
||||||
&sensor_dev_attr_psu_model_name.dev_attr.attr,
|
|
||||||
&sensor_dev_attr_psu_power_good.dev_attr.attr,
|
|
||||||
NULL
|
|
||||||
};
|
|
||||||
|
|
||||||
static ssize_t show_status(struct device *dev, struct device_attribute *da,
|
|
||||||
char *buf)
|
|
||||||
{
|
|
||||||
struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
|
|
||||||
struct as7712_32x_psu_data *data = as7712_32x_psu_update_device(dev);
|
|
||||||
u8 status = 0;
|
|
||||||
|
|
||||||
if (attr->index == PSU_PRESENT) {
|
|
||||||
status = !(data->status >> (1-data->index) & 0x1);
|
|
||||||
}
|
|
||||||
else { /* PSU_POWER_GOOD */
|
|
||||||
status = (data->status >> (3-data->index) & 0x1);
|
|
||||||
}
|
|
||||||
|
|
||||||
return sprintf(buf, "%d\n", status);
|
|
||||||
}
|
|
||||||
|
|
||||||
static ssize_t show_model_name(struct device *dev, struct device_attribute *da,
|
|
||||||
char *buf)
|
|
||||||
{
|
|
||||||
struct as7712_32x_psu_data *data = as7712_32x_psu_update_device(dev);
|
|
||||||
|
|
||||||
return sprintf(buf, "%s\n", data->model_name);
|
|
||||||
}
|
|
||||||
|
|
||||||
static const struct attribute_group as7712_32x_psu_group = {
|
|
||||||
.attrs = as7712_32x_psu_attributes,
|
|
||||||
};
|
|
||||||
|
|
||||||
static int as7712_32x_psu_probe(struct i2c_client *client,
|
|
||||||
const struct i2c_device_id *dev_id)
|
|
||||||
{
|
|
||||||
struct as7712_32x_psu_data *data;
|
|
||||||
int status;
|
|
||||||
|
|
||||||
if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_I2C_BLOCK)) {
|
|
||||||
status = -EIO;
|
|
||||||
goto exit;
|
|
||||||
}
|
|
||||||
|
|
||||||
data = kzalloc(sizeof(struct as7712_32x_psu_data), GFP_KERNEL);
|
|
||||||
if (!data) {
|
|
||||||
status = -ENOMEM;
|
|
||||||
goto exit;
|
|
||||||
}
|
|
||||||
|
|
||||||
i2c_set_clientdata(client, data);
|
|
||||||
data->valid = 0;
|
|
||||||
data->index = dev_id->driver_data;
|
|
||||||
mutex_init(&data->update_lock);
|
|
||||||
|
|
||||||
dev_info(&client->dev, "chip found\n");
|
|
||||||
|
|
||||||
/* Register sysfs hooks */
|
|
||||||
status = sysfs_create_group(&client->dev.kobj, &as7712_32x_psu_group);
|
|
||||||
if (status) {
|
|
||||||
goto exit_free;
|
|
||||||
}
|
|
||||||
|
|
||||||
data->hwmon_dev = hwmon_device_register(&client->dev);
|
|
||||||
if (IS_ERR(data->hwmon_dev)) {
|
|
||||||
status = PTR_ERR(data->hwmon_dev);
|
|
||||||
goto exit_remove;
|
|
||||||
}
|
|
||||||
|
|
||||||
dev_info(&client->dev, "%s: psu '%s'\n",
|
|
||||||
dev_name(data->hwmon_dev), client->name);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
exit_remove:
|
|
||||||
sysfs_remove_group(&client->dev.kobj, &as7712_32x_psu_group);
|
|
||||||
exit_free:
|
|
||||||
kfree(data);
|
|
||||||
exit:
|
|
||||||
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int as7712_32x_psu_remove(struct i2c_client *client)
|
|
||||||
{
|
|
||||||
struct as7712_32x_psu_data *data = i2c_get_clientdata(client);
|
|
||||||
|
|
||||||
hwmon_device_unregister(data->hwmon_dev);
|
|
||||||
sysfs_remove_group(&client->dev.kobj, &as7712_32x_psu_group);
|
|
||||||
kfree(data);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
enum psu_index
|
|
||||||
{
|
|
||||||
as7712_32x_psu1,
|
|
||||||
as7712_32x_psu2
|
|
||||||
};
|
|
||||||
|
|
||||||
static const struct i2c_device_id as7712_32x_psu_id[] = {
|
|
||||||
{ "as7712_32x_psu1", as7712_32x_psu1 },
|
|
||||||
{ "as7712_32x_psu2", as7712_32x_psu2 },
|
|
||||||
{}
|
|
||||||
};
|
|
||||||
MODULE_DEVICE_TABLE(i2c, as7712_32x_psu_id);
|
|
||||||
|
|
||||||
static struct i2c_driver as7712_32x_psu_driver = {
|
|
||||||
.class = I2C_CLASS_HWMON,
|
|
||||||
.driver = {
|
|
||||||
.name = "as7712_32x_psu",
|
|
||||||
},
|
|
||||||
.probe = as7712_32x_psu_probe,
|
|
||||||
.remove = as7712_32x_psu_remove,
|
|
||||||
.id_table = as7712_32x_psu_id,
|
|
||||||
.address_list = normal_i2c,
|
|
||||||
};
|
|
||||||
|
|
||||||
static int as7712_32x_psu_read_block(struct i2c_client *client, u8 command, u8 *data,
|
|
||||||
int data_len)
|
|
||||||
{
|
|
||||||
int result = 0;
|
|
||||||
int retry_count = 5;
|
|
||||||
|
|
||||||
while (retry_count) {
|
|
||||||
retry_count--;
|
|
||||||
|
|
||||||
result = i2c_smbus_read_i2c_block_data(client, command, data_len, data);
|
|
||||||
|
|
||||||
if (unlikely(result < 0)) {
|
|
||||||
msleep(10);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (unlikely(result != data_len)) {
|
|
||||||
result = -EIO;
|
|
||||||
msleep(10);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
result = 0;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
static struct as7712_32x_psu_data *as7712_32x_psu_update_device(struct device *dev)
|
|
||||||
{
|
|
||||||
struct i2c_client *client = to_i2c_client(dev);
|
|
||||||
struct as7712_32x_psu_data *data = i2c_get_clientdata(client);
|
|
||||||
|
|
||||||
mutex_lock(&data->update_lock);
|
|
||||||
|
|
||||||
if (time_after(jiffies, data->last_updated + HZ + HZ / 2)
|
|
||||||
|| !data->valid) {
|
|
||||||
int status;
|
|
||||||
int power_good = 0;
|
|
||||||
|
|
||||||
dev_dbg(&client->dev, "Starting as7712_32x update\n");
|
|
||||||
|
|
||||||
/* Read psu status */
|
|
||||||
status = accton_i2c_cpld_read(0x60, 0x2);
|
|
||||||
|
|
||||||
if (status < 0) {
|
|
||||||
dev_dbg(&client->dev, "cpld reg 0x60 err %d\n", status);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
data->status = status;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Read model name */
|
|
||||||
memset(data->model_name, 0, sizeof(data->model_name));
|
|
||||||
power_good = (data->status >> (3-data->index) & 0x1);
|
|
||||||
|
|
||||||
if (power_good) {
|
|
||||||
status = as7712_32x_psu_read_block(client, 0x20, data->model_name,
|
|
||||||
ARRAY_SIZE(data->model_name)-1);
|
|
||||||
|
|
||||||
if (status < 0) {
|
|
||||||
data->model_name[0] = '\0';
|
|
||||||
dev_dbg(&client->dev, "unable to read model name from (0x%x)\n", client->addr);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
data->model_name[ARRAY_SIZE(data->model_name)-1] = '\0';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
data->last_updated = jiffies;
|
|
||||||
data->valid = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
mutex_unlock(&data->update_lock);
|
|
||||||
|
|
||||||
return data;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int __init as7712_32x_psu_init(void)
|
|
||||||
{
|
|
||||||
extern int platform_accton_as7712_32x(void);
|
|
||||||
if (!platform_accton_as7712_32x()) {
|
|
||||||
return -ENODEV;
|
|
||||||
}
|
|
||||||
|
|
||||||
return i2c_add_driver(&as7712_32x_psu_driver);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void __exit as7712_32x_psu_exit(void)
|
|
||||||
{
|
|
||||||
i2c_del_driver(&as7712_32x_psu_driver);
|
|
||||||
}
|
|
||||||
|
|
||||||
module_init(as7712_32x_psu_init);
|
|
||||||
module_exit(as7712_32x_psu_exit);
|
|
||||||
|
|
||||||
MODULE_AUTHOR("Brandon Chuang <brandon_chuang@accton.com.tw>");
|
|
||||||
MODULE_DESCRIPTION("as7712_32x_psu driver");
|
|
||||||
MODULE_LICENSE("GPL");
|
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
@ -1,259 +0,0 @@
|
|||||||
/*
|
|
||||||
* A hwmon driver for the accton_i2c_cpld
|
|
||||||
*
|
|
||||||
* Copyright (C) 2014 Accton Technology Corporation.
|
|
||||||
* Brandon Chuang <brandon_chuang@accton.com.tw>
|
|
||||||
*
|
|
||||||
* Based on ad7414.c
|
|
||||||
* Copyright 2006 Stefan Roese <sr at denx.de>, DENX Software Engineering
|
|
||||||
*
|
|
||||||
* 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/i2c.h>
|
|
||||||
#include <linux/slab.h>
|
|
||||||
#include <linux/list.h>
|
|
||||||
#include <linux/dmi.h>
|
|
||||||
#include <linux/hwmon.h>
|
|
||||||
#include <linux/hwmon-sysfs.h>
|
|
||||||
#include <linux/err.h>
|
|
||||||
#include <linux/mutex.h>
|
|
||||||
|
|
||||||
#define CPLD_VERSION_REG 0x1
|
|
||||||
|
|
||||||
enum as5712_54x_cpld_sysfs_attributes {
|
|
||||||
CPLD_READ_VERSION,
|
|
||||||
CPLD_BYTE_ACCESS,
|
|
||||||
CPLD_DUMP_ALL,
|
|
||||||
};
|
|
||||||
|
|
||||||
static ssize_t read_cpld_version(struct device *dev, struct device_attribute *da,
|
|
||||||
char *buf);
|
|
||||||
int accton_i2c_cpld_read(unsigned short cpld_addr, u8 reg);
|
|
||||||
|
|
||||||
|
|
||||||
static LIST_HEAD(cpld_client_list);
|
|
||||||
static struct mutex list_lock;
|
|
||||||
|
|
||||||
struct cpld_client_node {
|
|
||||||
struct i2c_client *client;
|
|
||||||
struct list_head list;
|
|
||||||
};
|
|
||||||
|
|
||||||
/* Addresses scanned for accton_i2c_cpld
|
|
||||||
*/
|
|
||||||
static const unsigned short normal_i2c[] = { 0x31, 0x35, 0x60, 0x61, 0x62, I2C_CLIENT_END };
|
|
||||||
|
|
||||||
static SENSOR_DEVICE_ATTR(cpld_get_version, S_IRUGO, read_cpld_version, NULL, CPLD_READ_VERSION);
|
|
||||||
|
|
||||||
static struct attribute *as5712_54x_cpld_attributes[] = {
|
|
||||||
&sensor_dev_attr_cpld_get_version.dev_attr.attr,
|
|
||||||
NULL
|
|
||||||
};
|
|
||||||
|
|
||||||
static const struct attribute_group as5712_54x_cpld_group = {
|
|
||||||
.attrs = as5712_54x_cpld_attributes,
|
|
||||||
};
|
|
||||||
|
|
||||||
static ssize_t read_cpld_version(struct device *dev, struct device_attribute *da,
|
|
||||||
char *buf)
|
|
||||||
{
|
|
||||||
struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
|
|
||||||
struct i2c_client *client = to_i2c_client(dev);
|
|
||||||
unsigned short cpld_reg = CPLD_VERSION_REG;
|
|
||||||
u8 reg;
|
|
||||||
|
|
||||||
if(attr->index == CPLD_READ_VERSION) {
|
|
||||||
reg = accton_i2c_cpld_read(client->addr, cpld_reg);
|
|
||||||
return sprintf(buf, "%02x\n",reg);
|
|
||||||
}
|
|
||||||
return -1 ;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static void accton_i2c_cpld_add_client(struct i2c_client *client)
|
|
||||||
{
|
|
||||||
struct cpld_client_node *node = kzalloc(sizeof(struct cpld_client_node), GFP_KERNEL);
|
|
||||||
|
|
||||||
if (!node) {
|
|
||||||
dev_dbg(&client->dev, "Can't allocate cpld_client_node (0x%x)\n", client->addr);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
node->client = client;
|
|
||||||
|
|
||||||
mutex_lock(&list_lock);
|
|
||||||
list_add(&node->list, &cpld_client_list);
|
|
||||||
mutex_unlock(&list_lock);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void accton_i2c_cpld_remove_client(struct i2c_client *client)
|
|
||||||
{
|
|
||||||
struct list_head *list_node = NULL;
|
|
||||||
struct cpld_client_node *cpld_node = NULL;
|
|
||||||
int found = 0;
|
|
||||||
|
|
||||||
mutex_lock(&list_lock);
|
|
||||||
|
|
||||||
list_for_each(list_node, &cpld_client_list)
|
|
||||||
{
|
|
||||||
cpld_node = list_entry(list_node, struct cpld_client_node, list);
|
|
||||||
|
|
||||||
if (cpld_node->client == client) {
|
|
||||||
found = 1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (found) {
|
|
||||||
list_del(list_node);
|
|
||||||
kfree(cpld_node);
|
|
||||||
}
|
|
||||||
|
|
||||||
mutex_unlock(&list_lock);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int accton_i2c_cpld_probe(struct i2c_client *client,
|
|
||||||
const struct i2c_device_id *dev_id)
|
|
||||||
{
|
|
||||||
int status;
|
|
||||||
|
|
||||||
if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) {
|
|
||||||
dev_dbg(&client->dev, "i2c_check_functionality failed (0x%x)\n", client->addr);
|
|
||||||
status = -EIO;
|
|
||||||
goto exit;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Register sysfs hooks */
|
|
||||||
status = sysfs_create_group(&client->dev.kobj, &as5712_54x_cpld_group);
|
|
||||||
if (status) {
|
|
||||||
goto exit;
|
|
||||||
}
|
|
||||||
|
|
||||||
dev_info(&client->dev, "chip found\n");
|
|
||||||
accton_i2c_cpld_add_client(client);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
exit:
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int accton_i2c_cpld_remove(struct i2c_client *client)
|
|
||||||
{
|
|
||||||
sysfs_remove_group(&client->dev.kobj, &as5712_54x_cpld_group);
|
|
||||||
|
|
||||||
accton_i2c_cpld_remove_client(client);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static const struct i2c_device_id accton_i2c_cpld_id[] = {
|
|
||||||
{ "accton_i2c_cpld", 0 },
|
|
||||||
{}
|
|
||||||
};
|
|
||||||
MODULE_DEVICE_TABLE(i2c, accton_i2c_cpld_id);
|
|
||||||
|
|
||||||
static struct i2c_driver accton_i2c_cpld_driver = {
|
|
||||||
.class = I2C_CLASS_HWMON,
|
|
||||||
.driver = {
|
|
||||||
.name = "accton_i2c_cpld",
|
|
||||||
},
|
|
||||||
.probe = accton_i2c_cpld_probe,
|
|
||||||
.remove = accton_i2c_cpld_remove,
|
|
||||||
.id_table = accton_i2c_cpld_id,
|
|
||||||
.address_list = normal_i2c,
|
|
||||||
};
|
|
||||||
|
|
||||||
int accton_i2c_cpld_read(unsigned short cpld_addr, u8 reg)
|
|
||||||
{
|
|
||||||
struct list_head *list_node = NULL;
|
|
||||||
struct cpld_client_node *cpld_node = NULL;
|
|
||||||
int ret = -EPERM;
|
|
||||||
|
|
||||||
mutex_lock(&list_lock);
|
|
||||||
|
|
||||||
list_for_each(list_node, &cpld_client_list)
|
|
||||||
{
|
|
||||||
cpld_node = list_entry(list_node, struct cpld_client_node, list);
|
|
||||||
|
|
||||||
if (cpld_node->client->addr == cpld_addr) {
|
|
||||||
ret = i2c_smbus_read_byte_data(cpld_node->client, reg);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
mutex_unlock(&list_lock);
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
EXPORT_SYMBOL(accton_i2c_cpld_read);
|
|
||||||
|
|
||||||
int accton_i2c_cpld_write(unsigned short cpld_addr, u8 reg, u8 value)
|
|
||||||
{
|
|
||||||
struct list_head *list_node = NULL;
|
|
||||||
struct cpld_client_node *cpld_node = NULL;
|
|
||||||
int ret = -EIO;
|
|
||||||
|
|
||||||
mutex_lock(&list_lock);
|
|
||||||
|
|
||||||
list_for_each(list_node, &cpld_client_list)
|
|
||||||
{
|
|
||||||
cpld_node = list_entry(list_node, struct cpld_client_node, list);
|
|
||||||
|
|
||||||
if (cpld_node->client->addr == cpld_addr) {
|
|
||||||
ret = i2c_smbus_write_byte_data(cpld_node->client, reg, value);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
mutex_unlock(&list_lock);
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
EXPORT_SYMBOL(accton_i2c_cpld_write);
|
|
||||||
|
|
||||||
static int __init accton_i2c_cpld_init(void)
|
|
||||||
{
|
|
||||||
mutex_init(&list_lock);
|
|
||||||
return i2c_add_driver(&accton_i2c_cpld_driver);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void __exit accton_i2c_cpld_exit(void)
|
|
||||||
{
|
|
||||||
i2c_del_driver(&accton_i2c_cpld_driver);
|
|
||||||
}
|
|
||||||
|
|
||||||
static struct dmi_system_id as7712_dmi_table[] = {
|
|
||||||
{
|
|
||||||
.ident = "Accton AS7712",
|
|
||||||
.matches = {
|
|
||||||
DMI_MATCH(DMI_SYS_VENDOR, "Accton"),
|
|
||||||
DMI_MATCH(DMI_PRODUCT_NAME, "AS7712"),
|
|
||||||
},
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
int platform_accton_as7712_32x(void)
|
|
||||||
{
|
|
||||||
return dmi_check_system(as7712_dmi_table);
|
|
||||||
}
|
|
||||||
EXPORT_SYMBOL(platform_accton_as7712_32x);
|
|
||||||
|
|
||||||
MODULE_AUTHOR("Brandon Chuang <brandon_chuang@accton.com.tw>");
|
|
||||||
MODULE_DESCRIPTION("accton_i2c_cpld driver");
|
|
||||||
MODULE_LICENSE("GPL");
|
|
||||||
|
|
||||||
module_init(accton_i2c_cpld_init);
|
|
||||||
module_exit(accton_i2c_cpld_exit);
|
|
@ -1,443 +0,0 @@
|
|||||||
/*
|
|
||||||
* A LED driver for the accton_as7712_32x_led
|
|
||||||
*
|
|
||||||
* Copyright (C) 2014 Accton Technology Corporation.
|
|
||||||
* Brandon Chuang <brandon_chuang@accton.com.tw>
|
|
||||||
*
|
|
||||||
* 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 accton_i2c_cpld_read (unsigned short cpld_addr, u8 reg);
|
|
||||||
extern int accton_i2c_cpld_write(unsigned short cpld_addr, u8 reg, u8 value);
|
|
||||||
|
|
||||||
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 "accton_as7712_32x_led"
|
|
||||||
|
|
||||||
struct accton_as7712_32x_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[1]; /* only 1 register*/
|
|
||||||
};
|
|
||||||
|
|
||||||
static struct accton_as7712_32x_led_data *ledctl = NULL;
|
|
||||||
|
|
||||||
/* LED related data
|
|
||||||
*/
|
|
||||||
|
|
||||||
#define LED_CNTRLER_I2C_ADDRESS (0x60)
|
|
||||||
|
|
||||||
#define LED_TYPE_DIAG_REG_MASK (0x3)
|
|
||||||
#define LED_MODE_DIAG_GREEN_VALUE (0x02)
|
|
||||||
#define LED_MODE_DIAG_RED_VALUE (0x01)
|
|
||||||
#define LED_MODE_DIAG_AMBER_VALUE (0x00) /*It's yellow actually. Green+Red=Yellow*/
|
|
||||||
#define LED_MODE_DIAG_OFF_VALUE (0x03)
|
|
||||||
|
|
||||||
|
|
||||||
#define LED_TYPE_LOC_REG_MASK (0x80)
|
|
||||||
#define LED_MODE_LOC_ON_VALUE (0)
|
|
||||||
#define LED_MODE_LOC_OFF_VALUE (0x80)
|
|
||||||
|
|
||||||
enum led_type {
|
|
||||||
LED_TYPE_DIAG,
|
|
||||||
LED_TYPE_LOC,
|
|
||||||
LED_TYPE_FAN,
|
|
||||||
LED_TYPE_PSU1,
|
|
||||||
LED_TYPE_PSU2
|
|
||||||
};
|
|
||||||
|
|
||||||
struct led_reg {
|
|
||||||
u32 types;
|
|
||||||
u8 reg_addr;
|
|
||||||
};
|
|
||||||
|
|
||||||
static const struct led_reg led_reg_map[] = {
|
|
||||||
{(1<<LED_TYPE_LOC) | (1<<LED_TYPE_DIAG), 0x41},
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
enum led_light_mode {
|
|
||||||
LED_MODE_OFF = 0,
|
|
||||||
LED_MODE_GREEN,
|
|
||||||
LED_MODE_AMBER,
|
|
||||||
LED_MODE_RED,
|
|
||||||
LED_MODE_BLUE,
|
|
||||||
LED_MODE_GREEN_BLINK,
|
|
||||||
LED_MODE_AMBER_BLINK,
|
|
||||||
LED_MODE_RED_BLINK,
|
|
||||||
LED_MODE_BLUE_BLINK,
|
|
||||||
LED_MODE_AUTO,
|
|
||||||
LED_MODE_UNKNOWN
|
|
||||||
};
|
|
||||||
|
|
||||||
struct led_type_mode {
|
|
||||||
enum led_type type;
|
|
||||||
enum led_light_mode mode;
|
|
||||||
int reg_bit_mask;
|
|
||||||
int mode_value;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct led_type_mode led_type_mode_data[] = {
|
|
||||||
{LED_TYPE_LOC, LED_MODE_OFF, LED_TYPE_LOC_REG_MASK, LED_MODE_LOC_OFF_VALUE},
|
|
||||||
{LED_TYPE_LOC, LED_MODE_BLUE, LED_TYPE_LOC_REG_MASK, LED_MODE_LOC_ON_VALUE},
|
|
||||||
{LED_TYPE_DIAG, LED_MODE_OFF, LED_TYPE_DIAG_REG_MASK, LED_MODE_DIAG_OFF_VALUE},
|
|
||||||
{LED_TYPE_DIAG, LED_MODE_GREEN, LED_TYPE_DIAG_REG_MASK, LED_MODE_DIAG_GREEN_VALUE},
|
|
||||||
{LED_TYPE_DIAG, LED_MODE_RED, LED_TYPE_DIAG_REG_MASK, LED_MODE_DIAG_RED_VALUE},
|
|
||||||
{LED_TYPE_DIAG, LED_MODE_AMBER, LED_TYPE_DIAG_REG_MASK, LED_MODE_DIAG_AMBER_VALUE},
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static void accton_as7712_32x_led_set(struct led_classdev *led_cdev,
|
|
||||||
enum led_brightness led_light_mode, enum led_type type);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static int accton_getLedReg(enum led_type type, u8 *reg)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
for (i = 0; i < ARRAY_SIZE(led_reg_map); i++) {
|
|
||||||
if(led_reg_map[i].types & (type<<1)){
|
|
||||||
*reg = led_reg_map[i].reg_addr;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
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].reg_bit_mask & reg_val) ==
|
|
||||||
led_type_mode_data[i].mode_value)
|
|
||||||
{
|
|
||||||
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_value |
|
|
||||||
(reg_val & (~led_type_mode_data[i].reg_bit_mask));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
return reg_val;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int accton_as7712_32x_led_read_value(u8 reg)
|
|
||||||
{
|
|
||||||
return accton_i2c_cpld_read(LED_CNTRLER_I2C_ADDRESS, reg);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int accton_as7712_32x_led_write_value(u8 reg, u8 value)
|
|
||||||
{
|
|
||||||
return accton_i2c_cpld_write(LED_CNTRLER_I2C_ADDRESS, reg, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void accton_as7712_32x_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 accton_as7712_32x_led update\n");
|
|
||||||
|
|
||||||
/* Update LED data
|
|
||||||
*/
|
|
||||||
for (i = 0; i < ARRAY_SIZE(ledctl->reg_val); i++) {
|
|
||||||
int status = accton_as7712_32x_led_read_value(led_reg_map[i].reg_addr);
|
|
||||||
|
|
||||||
if (status < 0) {
|
|
||||||
ledctl->valid = 0;
|
|
||||||
dev_dbg(&ledctl->pdev->dev, "reg %d, err %d\n", led_reg_map[i].reg_addr, status);
|
|
||||||
goto exit;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
ledctl->reg_val[i] = status;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ledctl->last_updated = jiffies;
|
|
||||||
ledctl->valid = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
exit:
|
|
||||||
mutex_unlock(&ledctl->update_lock);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void accton_as7712_32x_led_set(struct led_classdev *led_cdev,
|
|
||||||
enum led_brightness led_light_mode,
|
|
||||||
enum led_type type)
|
|
||||||
{
|
|
||||||
int reg_val;
|
|
||||||
u8 reg ;
|
|
||||||
mutex_lock(&ledctl->update_lock);
|
|
||||||
|
|
||||||
if( !accton_getLedReg(type, ®))
|
|
||||||
{
|
|
||||||
dev_dbg(&ledctl->pdev->dev, "Not match item for %d.\n", type);
|
|
||||||
}
|
|
||||||
|
|
||||||
reg_val = accton_as7712_32x_led_read_value(reg);
|
|
||||||
|
|
||||||
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);
|
|
||||||
accton_as7712_32x_led_write_value(reg, reg_val);
|
|
||||||
|
|
||||||
/* to prevent the slow-update issue */
|
|
||||||
ledctl->valid = 0;
|
|
||||||
|
|
||||||
exit:
|
|
||||||
mutex_unlock(&ledctl->update_lock);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static void accton_as7712_32x_led_diag_set(struct led_classdev *led_cdev,
|
|
||||||
enum led_brightness led_light_mode)
|
|
||||||
{
|
|
||||||
accton_as7712_32x_led_set(led_cdev, led_light_mode, LED_TYPE_DIAG);
|
|
||||||
}
|
|
||||||
|
|
||||||
static enum led_brightness accton_as7712_32x_led_diag_get(struct led_classdev *cdev)
|
|
||||||
{
|
|
||||||
accton_as7712_32x_led_update();
|
|
||||||
return led_reg_val_to_light_mode(LED_TYPE_DIAG, ledctl->reg_val[0]);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void accton_as7712_32x_led_loc_set(struct led_classdev *led_cdev,
|
|
||||||
enum led_brightness led_light_mode)
|
|
||||||
{
|
|
||||||
accton_as7712_32x_led_set(led_cdev, led_light_mode, LED_TYPE_LOC);
|
|
||||||
}
|
|
||||||
|
|
||||||
static enum led_brightness accton_as7712_32x_led_loc_get(struct led_classdev *cdev)
|
|
||||||
{
|
|
||||||
accton_as7712_32x_led_update();
|
|
||||||
return led_reg_val_to_light_mode(LED_TYPE_LOC, ledctl->reg_val[0]);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void accton_as7712_32x_led_auto_set(struct led_classdev *led_cdev,
|
|
||||||
enum led_brightness led_light_mode)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
static enum led_brightness accton_as7712_32x_led_auto_get(struct led_classdev *cdev)
|
|
||||||
{
|
|
||||||
return LED_MODE_AUTO;
|
|
||||||
}
|
|
||||||
|
|
||||||
static struct led_classdev accton_as7712_32x_leds[] = {
|
|
||||||
[LED_TYPE_DIAG] = {
|
|
||||||
.name = "accton_as7712_32x_led::diag",
|
|
||||||
.default_trigger = "unused",
|
|
||||||
.brightness_set = accton_as7712_32x_led_diag_set,
|
|
||||||
.brightness_get = accton_as7712_32x_led_diag_get,
|
|
||||||
.flags = LED_CORE_SUSPENDRESUME,
|
|
||||||
.max_brightness = LED_MODE_RED,
|
|
||||||
},
|
|
||||||
[LED_TYPE_LOC] = {
|
|
||||||
.name = "accton_as7712_32x_led::loc",
|
|
||||||
.default_trigger = "unused",
|
|
||||||
.brightness_set = accton_as7712_32x_led_loc_set,
|
|
||||||
.brightness_get = accton_as7712_32x_led_loc_get,
|
|
||||||
.flags = LED_CORE_SUSPENDRESUME,
|
|
||||||
.max_brightness = LED_MODE_BLUE,
|
|
||||||
},
|
|
||||||
[LED_TYPE_FAN] = {
|
|
||||||
.name = "accton_as7712_32x_led::fan",
|
|
||||||
.default_trigger = "unused",
|
|
||||||
.brightness_set = accton_as7712_32x_led_auto_set,
|
|
||||||
.brightness_get = accton_as7712_32x_led_auto_get,
|
|
||||||
.flags = LED_CORE_SUSPENDRESUME,
|
|
||||||
.max_brightness = LED_MODE_AUTO,
|
|
||||||
},
|
|
||||||
[LED_TYPE_PSU1] = {
|
|
||||||
.name = "accton_as7712_32x_led::psu1",
|
|
||||||
.default_trigger = "unused",
|
|
||||||
.brightness_set = accton_as7712_32x_led_auto_set,
|
|
||||||
.brightness_get = accton_as7712_32x_led_auto_get,
|
|
||||||
.flags = LED_CORE_SUSPENDRESUME,
|
|
||||||
.max_brightness = LED_MODE_AUTO,
|
|
||||||
},
|
|
||||||
[LED_TYPE_PSU2] = {
|
|
||||||
.name = "accton_as7712_32x_led::psu2",
|
|
||||||
.default_trigger = "unused",
|
|
||||||
.brightness_set = accton_as7712_32x_led_auto_set,
|
|
||||||
.brightness_get = accton_as7712_32x_led_auto_get,
|
|
||||||
.flags = LED_CORE_SUSPENDRESUME,
|
|
||||||
.max_brightness = LED_MODE_AUTO,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
static int accton_as7712_32x_led_suspend(struct platform_device *dev,
|
|
||||||
pm_message_t state)
|
|
||||||
{
|
|
||||||
int i = 0;
|
|
||||||
|
|
||||||
for (i = 0; i < ARRAY_SIZE(accton_as7712_32x_leds); i++) {
|
|
||||||
led_classdev_suspend(&accton_as7712_32x_leds[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int accton_as7712_32x_led_resume(struct platform_device *dev)
|
|
||||||
{
|
|
||||||
int i = 0;
|
|
||||||
|
|
||||||
for (i = 0; i < ARRAY_SIZE(accton_as7712_32x_leds); i++) {
|
|
||||||
led_classdev_resume(&accton_as7712_32x_leds[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int accton_as7712_32x_led_probe(struct platform_device *pdev)
|
|
||||||
{
|
|
||||||
int ret, i;
|
|
||||||
|
|
||||||
for (i = 0; i < ARRAY_SIZE(accton_as7712_32x_leds); i++) {
|
|
||||||
ret = led_classdev_register(&pdev->dev, &accton_as7712_32x_leds[i]);
|
|
||||||
|
|
||||||
if (ret < 0)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Check if all LEDs were successfully registered */
|
|
||||||
if (i != ARRAY_SIZE(accton_as7712_32x_leds)){
|
|
||||||
int j;
|
|
||||||
|
|
||||||
/* only unregister the LEDs that were successfully registered */
|
|
||||||
for (j = 0; j < i; j++) {
|
|
||||||
led_classdev_unregister(&accton_as7712_32x_leds[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int accton_as7712_32x_led_remove(struct platform_device *pdev)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
|
|
||||||
for (i = 0; i < ARRAY_SIZE(accton_as7712_32x_leds); i++) {
|
|
||||||
led_classdev_unregister(&accton_as7712_32x_leds[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static struct platform_driver accton_as7712_32x_led_driver = {
|
|
||||||
.probe = accton_as7712_32x_led_probe,
|
|
||||||
.remove = accton_as7712_32x_led_remove,
|
|
||||||
.suspend = accton_as7712_32x_led_suspend,
|
|
||||||
.resume = accton_as7712_32x_led_resume,
|
|
||||||
.driver = {
|
|
||||||
.name = DRVNAME,
|
|
||||||
.owner = THIS_MODULE,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
static int __init accton_as7712_32x_led_init(void)
|
|
||||||
{
|
|
||||||
int ret;
|
|
||||||
|
|
||||||
extern int platform_accton_as7712_32x(void);
|
|
||||||
if (!platform_accton_as7712_32x()) {
|
|
||||||
return -ENODEV;
|
|
||||||
}
|
|
||||||
|
|
||||||
ret = platform_driver_register(&accton_as7712_32x_led_driver);
|
|
||||||
if (ret < 0) {
|
|
||||||
goto exit;
|
|
||||||
}
|
|
||||||
|
|
||||||
ledctl = kzalloc(sizeof(struct accton_as7712_32x_led_data), GFP_KERNEL);
|
|
||||||
if (!ledctl) {
|
|
||||||
ret = -ENOMEM;
|
|
||||||
platform_driver_unregister(&accton_as7712_32x_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(&accton_as7712_32x_led_driver);
|
|
||||||
kfree(ledctl);
|
|
||||||
goto exit;
|
|
||||||
}
|
|
||||||
|
|
||||||
exit:
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void __exit accton_as7712_32x_led_exit(void)
|
|
||||||
{
|
|
||||||
platform_device_unregister(ledctl->pdev);
|
|
||||||
platform_driver_unregister(&accton_as7712_32x_led_driver);
|
|
||||||
kfree(ledctl);
|
|
||||||
}
|
|
||||||
|
|
||||||
module_init(accton_as7712_32x_led_init);
|
|
||||||
module_exit(accton_as7712_32x_led_exit);
|
|
||||||
|
|
||||||
MODULE_AUTHOR("Brandon Chuang <brandon_chuang@accton.com.tw>");
|
|
||||||
MODULE_DESCRIPTION("accton_as7712_32x_led driver");
|
|
||||||
MODULE_LICENSE("GPL");
|
|
@ -1,589 +0,0 @@
|
|||||||
/*
|
|
||||||
* An hwmon driver for the 3Y Power YM-2651Y Power Module
|
|
||||||
*
|
|
||||||
* Copyright (C) 2014 Accton Technology Corporation.
|
|
||||||
* Brandon Chuang <brandon_chuang@accton.com.tw>
|
|
||||||
*
|
|
||||||
* Based on ad7414.c
|
|
||||||
* Copyright 2006 Stefan Roese <sr at denx.de>, DENX Software Engineering
|
|
||||||
*
|
|
||||||
* 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>
|
|
||||||
|
|
||||||
#define MAX_FAN_DUTY_CYCLE 100
|
|
||||||
|
|
||||||
/* Addresses scanned
|
|
||||||
*/
|
|
||||||
static const unsigned short normal_i2c[] = { 0x58, 0x5b, I2C_CLIENT_END };
|
|
||||||
|
|
||||||
/* Each client has this additional data
|
|
||||||
*/
|
|
||||||
struct ym2651y_data {
|
|
||||||
struct device *hwmon_dev;
|
|
||||||
struct mutex update_lock;
|
|
||||||
char valid; /* !=0 if registers are valid */
|
|
||||||
unsigned long last_updated; /* In jiffies */
|
|
||||||
u8 capability; /* Register value */
|
|
||||||
u16 status_word; /* Register value */
|
|
||||||
u8 fan_fault; /* Register value */
|
|
||||||
u8 over_temp; /* Register value */
|
|
||||||
u16 v_out; /* Register value */
|
|
||||||
u16 i_out; /* Register value */
|
|
||||||
u16 p_out; /* Register value */
|
|
||||||
u16 temp; /* Register value */
|
|
||||||
u16 fan_speed; /* Register value */
|
|
||||||
u16 fan_duty_cycle[2]; /* Register value */
|
|
||||||
u8 fan_dir[4]; /* Register value */
|
|
||||||
u8 pmbus_revision; /* Register value */
|
|
||||||
u8 mfr_id[10]; /* Register value */
|
|
||||||
u8 mfr_model[10]; /* Register value */
|
|
||||||
u8 mfr_revsion[3]; /* Register value */
|
|
||||||
u16 mfr_vin_min; /* Register value */
|
|
||||||
u16 mfr_vin_max; /* Register value */
|
|
||||||
u16 mfr_iin_max; /* Register value */
|
|
||||||
u16 mfr_iout_max; /* Register value */
|
|
||||||
u16 mfr_pin_max; /* Register value */
|
|
||||||
u16 mfr_pout_max; /* Register value */
|
|
||||||
u16 mfr_vout_min; /* Register value */
|
|
||||||
u16 mfr_vout_max; /* Register value */
|
|
||||||
};
|
|
||||||
|
|
||||||
static ssize_t show_byte(struct device *dev, struct device_attribute *da,
|
|
||||||
char *buf);
|
|
||||||
static ssize_t show_word(struct device *dev, struct device_attribute *da,
|
|
||||||
char *buf);
|
|
||||||
static ssize_t show_linear(struct device *dev, struct device_attribute *da,
|
|
||||||
char *buf);
|
|
||||||
static ssize_t show_fan_fault(struct device *dev, struct device_attribute *da,
|
|
||||||
char *buf);
|
|
||||||
static ssize_t show_over_temp(struct device *dev, struct device_attribute *da,
|
|
||||||
char *buf);
|
|
||||||
static ssize_t show_ascii(struct device *dev, struct device_attribute *da,
|
|
||||||
char *buf);
|
|
||||||
static struct ym2651y_data *ym2651y_update_device(struct device *dev);
|
|
||||||
static ssize_t set_fan_duty_cycle(struct device *dev, struct device_attribute *da,
|
|
||||||
const char *buf, size_t count);
|
|
||||||
static int ym2651y_write_word(struct i2c_client *client, u8 reg, u16 value);
|
|
||||||
|
|
||||||
enum ym2651y_sysfs_attributes {
|
|
||||||
PSU_POWER_ON = 0,
|
|
||||||
PSU_TEMP_FAULT,
|
|
||||||
PSU_POWER_GOOD,
|
|
||||||
PSU_FAN1_FAULT,
|
|
||||||
PSU_FAN_DIRECTION,
|
|
||||||
PSU_OVER_TEMP,
|
|
||||||
PSU_V_OUT,
|
|
||||||
PSU_I_OUT,
|
|
||||||
PSU_P_OUT,
|
|
||||||
PSU_TEMP1_INPUT,
|
|
||||||
PSU_FAN1_SPEED,
|
|
||||||
PSU_FAN1_DUTY_CYCLE,
|
|
||||||
PSU_PMBUS_REVISION,
|
|
||||||
PSU_MFR_ID,
|
|
||||||
PSU_MFR_MODEL,
|
|
||||||
PSU_MFR_REVISION,
|
|
||||||
PSU_MFR_VIN_MIN,
|
|
||||||
PSU_MFR_VIN_MAX,
|
|
||||||
PSU_MFR_VOUT_MIN,
|
|
||||||
PSU_MFR_VOUT_MAX,
|
|
||||||
PSU_MFR_IIN_MAX,
|
|
||||||
PSU_MFR_IOUT_MAX,
|
|
||||||
PSU_MFR_PIN_MAX,
|
|
||||||
PSU_MFR_POUT_MAX
|
|
||||||
};
|
|
||||||
|
|
||||||
/* sysfs attributes for hwmon
|
|
||||||
*/
|
|
||||||
static SENSOR_DEVICE_ATTR(psu_power_on, S_IRUGO, show_word, NULL, PSU_POWER_ON);
|
|
||||||
static SENSOR_DEVICE_ATTR(psu_temp_fault, S_IRUGO, show_word, NULL, PSU_TEMP_FAULT);
|
|
||||||
static SENSOR_DEVICE_ATTR(psu_power_good, S_IRUGO, show_word, NULL, PSU_POWER_GOOD);
|
|
||||||
static SENSOR_DEVICE_ATTR(psu_fan1_fault, S_IRUGO, show_fan_fault, NULL, PSU_FAN1_FAULT);
|
|
||||||
static SENSOR_DEVICE_ATTR(psu_over_temp, S_IRUGO, show_over_temp, NULL, PSU_OVER_TEMP);
|
|
||||||
static SENSOR_DEVICE_ATTR(psu_v_out, S_IRUGO, show_linear, NULL, PSU_V_OUT);
|
|
||||||
static SENSOR_DEVICE_ATTR(psu_i_out, S_IRUGO, show_linear, NULL, PSU_I_OUT);
|
|
||||||
static SENSOR_DEVICE_ATTR(psu_p_out, S_IRUGO, show_linear, NULL, PSU_P_OUT);
|
|
||||||
static SENSOR_DEVICE_ATTR(psu_temp1_input, S_IRUGO, show_linear, NULL, PSU_TEMP1_INPUT);
|
|
||||||
static SENSOR_DEVICE_ATTR(psu_fan1_speed_rpm, S_IRUGO, show_linear, NULL, PSU_FAN1_SPEED);
|
|
||||||
static SENSOR_DEVICE_ATTR(psu_fan1_duty_cycle_percentage, S_IWUSR | S_IRUGO, show_linear, set_fan_duty_cycle, PSU_FAN1_DUTY_CYCLE);
|
|
||||||
static SENSOR_DEVICE_ATTR(psu_fan_dir, S_IRUGO, show_ascii, NULL, PSU_FAN_DIRECTION);
|
|
||||||
static SENSOR_DEVICE_ATTR(psu_pmbus_revision, S_IRUGO, show_byte, NULL, PSU_PMBUS_REVISION);
|
|
||||||
static SENSOR_DEVICE_ATTR(psu_mfr_id, S_IRUGO, show_ascii, NULL, PSU_MFR_ID);
|
|
||||||
static SENSOR_DEVICE_ATTR(psu_mfr_model, S_IRUGO, show_ascii, NULL, PSU_MFR_MODEL);
|
|
||||||
static SENSOR_DEVICE_ATTR(psu_mfr_revision, S_IRUGO, show_ascii, NULL, PSU_MFR_REVISION);
|
|
||||||
static SENSOR_DEVICE_ATTR(psu_mfr_vin_min, S_IRUGO, show_linear, NULL, PSU_MFR_VIN_MIN);
|
|
||||||
static SENSOR_DEVICE_ATTR(psu_mfr_vin_max, S_IRUGO, show_linear, NULL, PSU_MFR_VIN_MAX);
|
|
||||||
static SENSOR_DEVICE_ATTR(psu_mfr_vout_min, S_IRUGO, show_linear, NULL, PSU_MFR_VOUT_MIN);
|
|
||||||
static SENSOR_DEVICE_ATTR(psu_mfr_vout_max, S_IRUGO, show_linear, NULL, PSU_MFR_VOUT_MAX);
|
|
||||||
static SENSOR_DEVICE_ATTR(psu_mfr_iin_max, S_IRUGO, show_linear, NULL, PSU_MFR_IIN_MAX);
|
|
||||||
static SENSOR_DEVICE_ATTR(psu_mfr_iout_max, S_IRUGO, show_linear, NULL, PSU_MFR_IOUT_MAX);
|
|
||||||
static SENSOR_DEVICE_ATTR(psu_mfr_pin_max, S_IRUGO, show_linear, NULL, PSU_MFR_PIN_MAX);
|
|
||||||
static SENSOR_DEVICE_ATTR(psu_mfr_pout_max, S_IRUGO, show_linear, NULL, PSU_MFR_POUT_MAX);
|
|
||||||
|
|
||||||
static struct attribute *ym2651y_attributes[] = {
|
|
||||||
&sensor_dev_attr_psu_power_on.dev_attr.attr,
|
|
||||||
&sensor_dev_attr_psu_temp_fault.dev_attr.attr,
|
|
||||||
&sensor_dev_attr_psu_power_good.dev_attr.attr,
|
|
||||||
&sensor_dev_attr_psu_fan1_fault.dev_attr.attr,
|
|
||||||
&sensor_dev_attr_psu_over_temp.dev_attr.attr,
|
|
||||||
&sensor_dev_attr_psu_v_out.dev_attr.attr,
|
|
||||||
&sensor_dev_attr_psu_i_out.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_fan1_speed_rpm.dev_attr.attr,
|
|
||||||
&sensor_dev_attr_psu_fan1_duty_cycle_percentage.dev_attr.attr,
|
|
||||||
&sensor_dev_attr_psu_fan_dir.dev_attr.attr,
|
|
||||||
&sensor_dev_attr_psu_pmbus_revision.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_revision.dev_attr.attr,
|
|
||||||
&sensor_dev_attr_psu_mfr_vin_min.dev_attr.attr,
|
|
||||||
&sensor_dev_attr_psu_mfr_vin_max.dev_attr.attr,
|
|
||||||
&sensor_dev_attr_psu_mfr_pout_max.dev_attr.attr,
|
|
||||||
&sensor_dev_attr_psu_mfr_iin_max.dev_attr.attr,
|
|
||||||
&sensor_dev_attr_psu_mfr_pin_max.dev_attr.attr,
|
|
||||||
&sensor_dev_attr_psu_mfr_vout_min.dev_attr.attr,
|
|
||||||
&sensor_dev_attr_psu_mfr_vout_max.dev_attr.attr,
|
|
||||||
&sensor_dev_attr_psu_mfr_iout_max.dev_attr.attr,
|
|
||||||
NULL
|
|
||||||
};
|
|
||||||
|
|
||||||
static ssize_t show_byte(struct device *dev, struct device_attribute *da,
|
|
||||||
char *buf)
|
|
||||||
{
|
|
||||||
struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
|
|
||||||
struct ym2651y_data *data = ym2651y_update_device(dev);
|
|
||||||
|
|
||||||
return (attr->index == PSU_PMBUS_REVISION) ? sprintf(buf, "%d\n", data->pmbus_revision) :
|
|
||||||
sprintf(buf, "0\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
static ssize_t show_word(struct device *dev, struct device_attribute *da,
|
|
||||||
char *buf)
|
|
||||||
{
|
|
||||||
struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
|
|
||||||
struct ym2651y_data *data = ym2651y_update_device(dev);
|
|
||||||
u16 status = 0;
|
|
||||||
|
|
||||||
switch (attr->index) {
|
|
||||||
case PSU_POWER_ON: /* psu_power_on, low byte bit 6 of status_word, 0=>ON, 1=>OFF */
|
|
||||||
status = (data->status_word & 0x40) ? 0 : 1;
|
|
||||||
break;
|
|
||||||
case PSU_TEMP_FAULT: /* psu_temp_fault, low byte bit 2 of status_word, 0=>Normal, 1=>temp fault */
|
|
||||||
status = (data->status_word & 0x4) >> 2;
|
|
||||||
break;
|
|
||||||
case PSU_POWER_GOOD: /* psu_power_good, high byte bit 3 of status_word, 0=>OK, 1=>FAIL */
|
|
||||||
status = (data->status_word & 0x800) ? 0 : 1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
return sprintf(buf, "%d\n", status);
|
|
||||||
}
|
|
||||||
|
|
||||||
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 *da,
|
|
||||||
const char *buf, size_t count)
|
|
||||||
{
|
|
||||||
struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
|
|
||||||
struct i2c_client *client = to_i2c_client(dev);
|
|
||||||
struct ym2651y_data *data = i2c_get_clientdata(client);
|
|
||||||
int nr = (attr->index == PSU_FAN1_DUTY_CYCLE) ? 0 : 1;
|
|
||||||
long speed;
|
|
||||||
int error;
|
|
||||||
|
|
||||||
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;
|
|
||||||
ym2651y_write_word(client, 0x3B + nr, data->fan_duty_cycle[nr]);
|
|
||||||
mutex_unlock(&data->update_lock);
|
|
||||||
|
|
||||||
return count;
|
|
||||||
}
|
|
||||||
|
|
||||||
static ssize_t show_linear(struct device *dev, struct device_attribute *da,
|
|
||||||
char *buf)
|
|
||||||
{
|
|
||||||
struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
|
|
||||||
struct ym2651y_data *data = ym2651y_update_device(dev);
|
|
||||||
|
|
||||||
u16 value = 0;
|
|
||||||
int exponent, mantissa;
|
|
||||||
int multiplier = 1000;
|
|
||||||
|
|
||||||
switch (attr->index) {
|
|
||||||
case PSU_V_OUT:
|
|
||||||
value = data->v_out;
|
|
||||||
break;
|
|
||||||
case PSU_I_OUT:
|
|
||||||
value = data->i_out;
|
|
||||||
break;
|
|
||||||
case PSU_P_OUT:
|
|
||||||
value = data->p_out;
|
|
||||||
break;
|
|
||||||
case PSU_TEMP1_INPUT:
|
|
||||||
value = data->temp;
|
|
||||||
break;
|
|
||||||
case PSU_FAN1_SPEED:
|
|
||||||
value = data->fan_speed;
|
|
||||||
multiplier = 1;
|
|
||||||
break;
|
|
||||||
case PSU_FAN1_DUTY_CYCLE:
|
|
||||||
value = data->fan_duty_cycle[0];
|
|
||||||
multiplier = 1;
|
|
||||||
break;
|
|
||||||
case PSU_MFR_VIN_MIN:
|
|
||||||
value = data->mfr_vin_min;
|
|
||||||
break;
|
|
||||||
case PSU_MFR_VIN_MAX:
|
|
||||||
value = data->mfr_vin_max;
|
|
||||||
break;
|
|
||||||
case PSU_MFR_VOUT_MIN:
|
|
||||||
value = data->mfr_vout_min;
|
|
||||||
break;
|
|
||||||
case PSU_MFR_VOUT_MAX:
|
|
||||||
value = data->mfr_vout_max;
|
|
||||||
break;
|
|
||||||
case PSU_MFR_PIN_MAX:
|
|
||||||
value = data->mfr_pin_max;
|
|
||||||
break;
|
|
||||||
case PSU_MFR_POUT_MAX:
|
|
||||||
value = data->mfr_pout_max;
|
|
||||||
break;
|
|
||||||
case PSU_MFR_IOUT_MAX:
|
|
||||||
value = data->mfr_iout_max;
|
|
||||||
break;
|
|
||||||
case PSU_MFR_IIN_MAX:
|
|
||||||
value = data->mfr_iin_max;
|
|
||||||
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 show_fan_fault(struct device *dev, struct device_attribute *da,
|
|
||||||
char *buf)
|
|
||||||
{
|
|
||||||
struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
|
|
||||||
struct ym2651y_data *data = ym2651y_update_device(dev);
|
|
||||||
|
|
||||||
u8 shift = (attr->index == PSU_FAN1_FAULT) ? 7 : 6;
|
|
||||||
|
|
||||||
return sprintf(buf, "%d\n", data->fan_fault >> shift);
|
|
||||||
}
|
|
||||||
|
|
||||||
static ssize_t show_over_temp(struct device *dev, struct device_attribute *da,
|
|
||||||
char *buf)
|
|
||||||
{
|
|
||||||
struct ym2651y_data *data = ym2651y_update_device(dev);
|
|
||||||
|
|
||||||
return sprintf(buf, "%d\n", data->over_temp >> 7);
|
|
||||||
}
|
|
||||||
|
|
||||||
static ssize_t show_ascii(struct device *dev, struct device_attribute *da,
|
|
||||||
char *buf)
|
|
||||||
{
|
|
||||||
struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
|
|
||||||
struct ym2651y_data *data = ym2651y_update_device(dev);
|
|
||||||
u8 *ptr = NULL;
|
|
||||||
|
|
||||||
switch (attr->index) {
|
|
||||||
case PSU_FAN_DIRECTION: /* psu_fan_dir */
|
|
||||||
ptr = data->fan_dir;
|
|
||||||
break;
|
|
||||||
case PSU_MFR_ID: /* psu_mfr_id */
|
|
||||||
ptr = data->mfr_id;
|
|
||||||
break;
|
|
||||||
case PSU_MFR_MODEL: /* psu_mfr_model */
|
|
||||||
ptr = data->mfr_model;
|
|
||||||
break;
|
|
||||||
case PSU_MFR_REVISION: /* psu_mfr_revision */
|
|
||||||
ptr = data->mfr_revsion;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
return sprintf(buf, "%s\n", ptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
static const struct attribute_group ym2651y_group = {
|
|
||||||
.attrs = ym2651y_attributes,
|
|
||||||
};
|
|
||||||
|
|
||||||
static int ym2651y_probe(struct i2c_client *client,
|
|
||||||
const struct i2c_device_id *dev_id)
|
|
||||||
{
|
|
||||||
struct ym2651y_data *data;
|
|
||||||
int status;
|
|
||||||
|
|
||||||
if (!i2c_check_functionality(client->adapter,
|
|
||||||
I2C_FUNC_SMBUS_BYTE_DATA |
|
|
||||||
I2C_FUNC_SMBUS_WORD_DATA |
|
|
||||||
I2C_FUNC_SMBUS_I2C_BLOCK)) {
|
|
||||||
status = -EIO;
|
|
||||||
goto exit;
|
|
||||||
}
|
|
||||||
|
|
||||||
data = kzalloc(sizeof(struct ym2651y_data), GFP_KERNEL);
|
|
||||||
if (!data) {
|
|
||||||
status = -ENOMEM;
|
|
||||||
goto exit;
|
|
||||||
}
|
|
||||||
|
|
||||||
i2c_set_clientdata(client, data);
|
|
||||||
mutex_init(&data->update_lock);
|
|
||||||
|
|
||||||
dev_info(&client->dev, "chip found\n");
|
|
||||||
|
|
||||||
/* Register sysfs hooks */
|
|
||||||
status = sysfs_create_group(&client->dev.kobj, &ym2651y_group);
|
|
||||||
if (status) {
|
|
||||||
goto exit_free;
|
|
||||||
}
|
|
||||||
|
|
||||||
data->hwmon_dev = hwmon_device_register(&client->dev);
|
|
||||||
if (IS_ERR(data->hwmon_dev)) {
|
|
||||||
status = PTR_ERR(data->hwmon_dev);
|
|
||||||
goto exit_remove;
|
|
||||||
}
|
|
||||||
|
|
||||||
dev_info(&client->dev, "%s: psu '%s'\n",
|
|
||||||
dev_name(data->hwmon_dev), client->name);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
exit_remove:
|
|
||||||
sysfs_remove_group(&client->dev.kobj, &ym2651y_group);
|
|
||||||
exit_free:
|
|
||||||
kfree(data);
|
|
||||||
exit:
|
|
||||||
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int ym2651y_remove(struct i2c_client *client)
|
|
||||||
{
|
|
||||||
struct ym2651y_data *data = i2c_get_clientdata(client);
|
|
||||||
|
|
||||||
hwmon_device_unregister(data->hwmon_dev);
|
|
||||||
sysfs_remove_group(&client->dev.kobj, &ym2651y_group);
|
|
||||||
kfree(data);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static const struct i2c_device_id ym2651y_id[] = {
|
|
||||||
{ "ym2651", 0 },
|
|
||||||
{}
|
|
||||||
};
|
|
||||||
MODULE_DEVICE_TABLE(i2c, ym2651y_id);
|
|
||||||
|
|
||||||
static struct i2c_driver ym2651y_driver = {
|
|
||||||
.class = I2C_CLASS_HWMON,
|
|
||||||
.driver = {
|
|
||||||
.name = "ym2651",
|
|
||||||
},
|
|
||||||
.probe = ym2651y_probe,
|
|
||||||
.remove = ym2651y_remove,
|
|
||||||
.id_table = ym2651y_id,
|
|
||||||
.address_list = normal_i2c,
|
|
||||||
};
|
|
||||||
|
|
||||||
static int ym2651y_read_byte(struct i2c_client *client, u8 reg)
|
|
||||||
{
|
|
||||||
return i2c_smbus_read_byte_data(client, reg);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int ym2651y_read_word(struct i2c_client *client, u8 reg)
|
|
||||||
{
|
|
||||||
return i2c_smbus_read_word_data(client, reg);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int ym2651y_write_word(struct i2c_client *client, u8 reg, u16 value)
|
|
||||||
{
|
|
||||||
return i2c_smbus_write_word_data(client, reg, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int ym2651y_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;
|
|
||||||
};
|
|
||||||
|
|
||||||
static struct ym2651y_data *ym2651y_update_device(struct device *dev)
|
|
||||||
{
|
|
||||||
struct i2c_client *client = to_i2c_client(dev);
|
|
||||||
struct ym2651y_data *data = i2c_get_clientdata(client);
|
|
||||||
|
|
||||||
mutex_lock(&data->update_lock);
|
|
||||||
|
|
||||||
if (time_after(jiffies, data->last_updated + HZ + HZ / 2)
|
|
||||||
|| !data->valid) {
|
|
||||||
int i, status;
|
|
||||||
u8 command;
|
|
||||||
u8 fan_dir[5] = {0};
|
|
||||||
struct reg_data_byte regs_byte[] = { {0x19, &data->capability},
|
|
||||||
{0x7d, &data->over_temp},
|
|
||||||
{0x81, &data->fan_fault},
|
|
||||||
{0x98, &data->pmbus_revision}};
|
|
||||||
struct reg_data_word regs_word[] = { {0x79, &data->status_word},
|
|
||||||
{0x8b, &data->v_out},
|
|
||||||
{0x8c, &data->i_out},
|
|
||||||
{0x96, &data->p_out},
|
|
||||||
{0x8d, &data->temp},
|
|
||||||
{0x3b, &(data->fan_duty_cycle[0])},
|
|
||||||
{0x3c, &(data->fan_duty_cycle[1])},
|
|
||||||
{0x90, &data->fan_speed},
|
|
||||||
{0xa0, &data->mfr_vin_min},
|
|
||||||
{0xa1, &data->mfr_vin_max},
|
|
||||||
{0xa2, &data->mfr_iin_max},
|
|
||||||
{0xa3, &data->mfr_pin_max},
|
|
||||||
{0xa4, &data->mfr_vout_min},
|
|
||||||
{0xa5, &data->mfr_vout_max},
|
|
||||||
{0xa6, &data->mfr_iout_max},
|
|
||||||
{0xa7, &data->mfr_pout_max}};
|
|
||||||
|
|
||||||
dev_dbg(&client->dev, "Starting ym2651 update\n");
|
|
||||||
|
|
||||||
/* Read byte data */
|
|
||||||
for (i = 0; i < ARRAY_SIZE(regs_byte); i++) {
|
|
||||||
status = ym2651y_read_byte(client, regs_byte[i].reg);
|
|
||||||
|
|
||||||
if (status < 0)
|
|
||||||
{
|
|
||||||
dev_dbg(&client->dev, "reg %d, err %d\n",
|
|
||||||
regs_byte[i].reg, status);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
*(regs_byte[i].value) = status;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Read word data */
|
|
||||||
for (i = 0; i < ARRAY_SIZE(regs_word); i++) {
|
|
||||||
status = ym2651y_read_word(client, regs_word[i].reg);
|
|
||||||
|
|
||||||
if (status < 0)
|
|
||||||
{
|
|
||||||
dev_dbg(&client->dev, "reg %d, err %d\n",
|
|
||||||
regs_word[i].reg, status);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
*(regs_word[i].value) = status;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Read fan_direction */
|
|
||||||
command = 0xC3;
|
|
||||||
status = ym2651y_read_block(client, command, fan_dir, ARRAY_SIZE(fan_dir)-1);
|
|
||||||
|
|
||||||
if (status < 0) {
|
|
||||||
dev_dbg(&client->dev, "reg %d, err %d\n", command, status);
|
|
||||||
}
|
|
||||||
|
|
||||||
strncpy(data->fan_dir, fan_dir+1, ARRAY_SIZE(data->fan_dir)-1);
|
|
||||||
data->fan_dir[ARRAY_SIZE(data->fan_dir)-1] = '\0';
|
|
||||||
|
|
||||||
/* Read mfr_id */
|
|
||||||
command = 0x99;
|
|
||||||
status = ym2651y_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);
|
|
||||||
|
|
||||||
/* Read mfr_model */
|
|
||||||
command = 0x9a;
|
|
||||||
status = ym2651y_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);
|
|
||||||
|
|
||||||
/* Read mfr_revsion */
|
|
||||||
command = 0x9b;
|
|
||||||
status = ym2651y_read_block(client, command, data->mfr_revsion,
|
|
||||||
ARRAY_SIZE(data->mfr_revsion)-1);
|
|
||||||
data->mfr_revsion[ARRAY_SIZE(data->mfr_revsion)-1] = '\0';
|
|
||||||
|
|
||||||
if (status < 0)
|
|
||||||
dev_dbg(&client->dev, "reg %d, err %d\n", command, status);
|
|
||||||
|
|
||||||
data->last_updated = jiffies;
|
|
||||||
data->valid = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
mutex_unlock(&data->update_lock);
|
|
||||||
|
|
||||||
return data;
|
|
||||||
}
|
|
||||||
|
|
||||||
module_i2c_driver(ym2651y_driver);
|
|
||||||
|
|
||||||
MODULE_AUTHOR("Brandon Chuang <brandon_chuang@accton.com.tw>");
|
|
||||||
MODULE_DESCRIPTION("3Y Power YM-2651Y driver");
|
|
||||||
MODULE_LICENSE("GPL");
|
|
||||||
|
|
||||||
|
|
@ -1,3 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
|
|
||||||
echo "TO-DO: as7712-32x driver setting"
|
|
@ -1,5 +0,0 @@
|
|||||||
sonic-accton-platform-modules (1.0) unstable; urgency=low
|
|
||||||
|
|
||||||
* Initial release
|
|
||||||
|
|
||||||
-- Polly Hsu <polly_hsu@accton.com> Tue, 9 May 2017 17:54:11 -0800
|
|
@ -1 +0,0 @@
|
|||||||
9
|
|
@ -1,11 +0,0 @@
|
|||||||
Source: sonic-accton-platform-modules
|
|
||||||
Section: main
|
|
||||||
Priority: extra
|
|
||||||
Maintainer: polly_hsu <polly_hsu@accton.com>
|
|
||||||
Build-Depends: debhelper (>= 8.0.0), bzip2
|
|
||||||
Standards-Version: 3.9.3
|
|
||||||
|
|
||||||
Package: platform-modules-as7712-32x
|
|
||||||
Architecture: amd64
|
|
||||||
Depends: linux-image-3.16.0-4-amd64
|
|
||||||
Description: kernel modules for platform devices such as fan, led, sfp
|
|
@ -1,44 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
|
|
||||||
### BEGIN INIT INFO
|
|
||||||
# Provides: setup-board
|
|
||||||
# Required-Start:
|
|
||||||
# Required-Stop:
|
|
||||||
# Should-Start:
|
|
||||||
# Should-Stop:
|
|
||||||
# Default-Start: S
|
|
||||||
# Default-Stop: 0 6
|
|
||||||
# Short-Description: Setup AS7712-32X board.
|
|
||||||
### END INIT INFO
|
|
||||||
|
|
||||||
case "$1" in
|
|
||||||
start)
|
|
||||||
echo -n "Setting up board... "
|
|
||||||
|
|
||||||
modprobe i2c_dev
|
|
||||||
modprobe i2c_mux_pca954x
|
|
||||||
modprobe accton_i2c_cpld
|
|
||||||
modprobe accton_as7712_32x_fan
|
|
||||||
modprobe accton_as7712_32x_sfp
|
|
||||||
modprobe leds-accton_as7712_32x
|
|
||||||
modprobe accton_as7712_32x_psu
|
|
||||||
|
|
||||||
echo "done."
|
|
||||||
;;
|
|
||||||
|
|
||||||
stop)
|
|
||||||
echo "done."
|
|
||||||
|
|
||||||
;;
|
|
||||||
|
|
||||||
force-reload|restart)
|
|
||||||
echo "Not supported"
|
|
||||||
;;
|
|
||||||
|
|
||||||
*)
|
|
||||||
echo "Usage: /etc/init.d/platform-modules-as7712-32x.init {start|stop}"
|
|
||||||
exit 1
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
|
|
||||||
exit 0
|
|
@ -1,2 +0,0 @@
|
|||||||
as7712-32x/scripts/as7712_32x_platform_init.sh usr/local/bin
|
|
||||||
as7712-32x/cfg/as7712_32x-modules.conf etc/modules-load.d
|
|
@ -1,36 +0,0 @@
|
|||||||
#!/usr/bin/make -f
|
|
||||||
|
|
||||||
export INSTALL_MOD_DIR:=extra
|
|
||||||
|
|
||||||
KVERSION ?= $(shell uname -r)
|
|
||||||
KERNEL_SRC := /lib/modules/$(KVERSION)
|
|
||||||
MOD_SRC_DIR:= $(shell pwd)
|
|
||||||
MODULE_DIRS:= as7712-32x
|
|
||||||
|
|
||||||
%:
|
|
||||||
dh $@
|
|
||||||
|
|
||||||
override_dh_auto_build:
|
|
||||||
(for mod in $(MODULE_DIRS); do \
|
|
||||||
make -C $(KERNEL_SRC)/build M=$(MOD_SRC_DIR)/$${mod}/modules; \
|
|
||||||
done)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
override_dh_auto_install:
|
|
||||||
(for mod in $(MODULE_DIRS); do \
|
|
||||||
dh_installdirs -pplatform-modules-$${mod} \
|
|
||||||
$(KERNEL_SRC)/$(INSTALL_MOD_DIR); \
|
|
||||||
cp $(MOD_SRC_DIR)/$${mod}/modules/*.ko \
|
|
||||||
debian/platform-modules-$${mod}/$(KERNEL_SRC)/$(INSTALL_MOD_DIR); \
|
|
||||||
mkdir -p debian/platform-modules-$${mod}/etc/bcm; \
|
|
||||||
done)
|
|
||||||
|
|
||||||
override_dh_usrlocal:
|
|
||||||
|
|
||||||
override_dh_clean:
|
|
||||||
dh_clean
|
|
||||||
(for mod in $(MODULE_DIRS); do \
|
|
||||||
make -C $(KERNEL_SRC)/build M=$(MOD_SRC_DIR)/$${mod}/modules clean; \
|
|
||||||
done)
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user