Merge pull request #507 from jnealtowns/iproc-4.14-latest

ARM Kernel and Distribution Upgrades
This commit is contained in:
Jeffrey Townsend
2018-12-26 09:06:41 -08:00
committed by GitHub
71 changed files with 39145 additions and 78216 deletions

View File

@@ -26,7 +26,7 @@ $(foreach a,$(ALL_ARCHES),$(eval $(call build_arch_template,$(a))))
# Available build architectures based on the current suite
BUILD_ARCHES_wheezy := amd64 powerpc
BUILD_ARCHES_jessie := amd64 powerpc armel
BUILD_ARCHES_stretch := arm64 amd64
BUILD_ARCHES_stretch := arm64 amd64 armel
# Build available architectures by default.
.DEFAULT_GOAL := all

View File

@@ -19,6 +19,7 @@ if test "$ARCH" != "$IARCH"; then
# identify mappings between kernel arch and debian arch
case "$IARCH:$ARCH" in
armel:armv7l) ;;
armhf:armv7l) ;;
arm64:aarch64) ;;
powerpc:ppc) ;;
*)

View File

@@ -1 +1,2 @@
- u-boot-tools
- onl-kernel-4.14-lts-armel-iproc-all-modules

View File

@@ -1 +1,2 @@
- u-boot-tools
- onl-kernel-4.14-lts-armel-iproc-all-modules

View File

@@ -4,7 +4,9 @@ include $(ONL)/make/config.armel.mk
# Default to include all available powerpc platforms.
# You override this with you own list or yaml file.
#
ifndef PLATFORM_LIST
export PLATFORM_LIST=$(shell onlpm --list-platforms --arch armel --csv )
endif
RFS_CONFIG := $(ONL)/builds/any/rootfs/$(ONL_DEBIAN_SUITE)/standard/standard.yml
RFS_DIR := rootfs-armel.d

12
make/config.armhf.mk Normal file
View File

@@ -0,0 +1,12 @@
############################################################
#
# Open Network Linux
#
############################################################
include $(ONL)/make/config.mk
export TOOLCHAIN := arm-linux-gnueabihf
export CROSS_COMPILER := $(TOOLCHAIN)-
export ARCH := armhf
export UARCH := ARMHF
export ARCH_BOOT := uboot
export __$(ARCH)__ := 1

View File

@@ -13,14 +13,30 @@ ifndef DTB_LIST
DTB_LIST := $(patsubst %.dts,%.dtb,$(DTS_LIST))
endif
%.dtb: %.dts
$(ONL)/tools/dtc -I dts -O dtb -o $@ $<
ifndef DTC
ifdef KERNEL
DTC := $(shell $(ONLPM) --find-file $(KERNEL) dtc)
ifeq ($(DTC),)
$(error No device tree compiler.)
endif
else
DTC := $(ONL)/tools/dtc
endif
endif
.DEFAULT_GOAL := $(DTB_LIST)
%.dtb: %.dts
cpp -nostdinc -undef -x assembler-with-cpp $(foreach inc,$(INCLUDES),-I$(inc) ) $< > $(notdir $<).i
$(DTC) $(foreach inc,$(INCLUDES),-i$(inc) ) $(DTC_OPTIONS) -I dts -O dtb -o $@ $(notdir $<).i
rm $(notdir $<).i
.DEFAULT_GOAL := dtbs
dtbs: $(DTB_LIST)
echo $(DTB_LIST) $(VPATH)
$(MAKE) setup-clean
$(DTB_LIST): setup
clean::
rm -rf *.dtb
setup::
setup-clean::

View File

@@ -174,7 +174,7 @@ endif
MODSYNCLIST_DEFAULT := .config Module.symvers Makefile include scripts drivers \
arch/x86/include arch/x86/Makefile \
arch/powerpc/include arch/powerpc/Makefile arch/powerpc/lib arch/powerpc/boot/dts \
arch/arm/include arch/arm/Makefile arch/arm/lib arch/arm/boot/dts
arch/arm/include arch/arm/Makefile arch/arm/lib arch/arm/boot/dts arch/arm/kernel
MODSYNCLIST := $(MODSYNCLIST_DEFAULT) $(MODSYNCLIST_EXTRA) $(K_MODSYNCLIST)

View File

@@ -26,4 +26,4 @@ endif
modules:
rm -rf lib
ARCH=$(ARCH) $(ONL)/tools/scripts/kmodbuild.sh "$(KERNELS)" "$(KMODULES)" "$(SUBDIR)"
ARCH=$(ARCH) $(ONL)/tools/scripts/kmodbuild.sh "$(KERNELS)" "$(KMODULES)" "$(SUBDIR)" "$(KINCLUDES)"

View File

@@ -14,7 +14,7 @@ include $(ONL)/make/config.mk
# directory tree.
#
ifndef ARCHES
ARCHES := amd64 powerpc armel arm64 all
ARCHES := amd64 powerpc armel armhf arm64 all
endif
ONLPM_ENVIRONMENT = \

View File

@@ -138,7 +138,7 @@ case $(uname -m) in
ARCH_LIST="x86_64 amd64"
;;
armv7l)
ARCH_LIST="armel"
ARCH_LIST="armel armhf"
;;
aarch64)
ARCH_LIST="arm64"

View File

@@ -46,12 +46,12 @@ default:
=: kernel-3.2-lts-arm-iproc-all.bin.gz
<<: *arm-iproc-kernel-package
arm-iproc-kernel-4-4-package: &arm-iproc-kernel-4-4-package
package: onl-kernel-4.4-lts-arm-iproc-all:armel
armel-iproc-4-14-kernel-package: &armel-iproc-4-14-kernel-package
package: onl-kernel-4.14-lts-armel-iproc-all:armel
arm-iproc-kernel-4-4: &arm-iproc-kernel-4-4
=: kernel-4.4-lts-arm-iproc-all.bin.gz
<<: *arm-iproc-kernel-4-4-package
armel-iproc-4-14-kernel: &armel-iproc-4-14-kernel
=: kernel-4.14-lts-armel-iproc-all.bin.gz
<<: *armel-iproc-4-14-kernel-package
arm64-kernel-package: &arm64-kernel-package
package: onl-kernel-4.9-lts-arm64-all:arm64

View File

@@ -33,6 +33,7 @@ def baseconfig():
'i386-linux-gnu',
'x86_64-linux-gnu',
'arm-linux-gnueabi',
'arm-linux-gnueabihf',
'aarch64-linux-gnu',
]

View File

@@ -4,7 +4,7 @@ endif
.PHONY: onl-loader-fit.itb onl-loader-fit.its
onl-loader-fit.itb:
onl-loader-fit.itb: its
$(ONL)/tools/flat-image-tree.py --initrd onl-loader-initrd:$(ARCH),onl-loader-initrd-$(ARCH).cpio.gz --arch $(ARCH) --add-platform initrd --itb $@
$(ONLPM) --copy-file onl-loader-initrd:$(ARCH) manifest.json .

View File

@@ -868,7 +868,7 @@ CONFIG_EEPROM_AT25=y
# CONFIG_EEPROM_93CX6 is not set
# CONFIG_EEPROM_93XX46 is not set
# CONFIG_EEPROM_SFF_8436 is not set
CONFIG_EEPROM_OPTOE=y
CONFIG_EEPROM_ACCTON_AS4610_SFP=y
# CONFIG_CB710_CORE is not set
# CONFIG_IWMC3200TOP is not set
@@ -1497,7 +1497,7 @@ CONFIG_SENSORS_W83781D=y
# CONFIG_SENSORS_W83L786NG is not set
# CONFIG_SENSORS_W83627HF is not set
# CONFIG_SENSORS_W83627EHF is not set
CONFIG_SENSORS_ACCTON_AS4610_CPLD=y
CONFIG_SENSORS_ACCTON_I2C_CPLD=y
CONFIG_SENSORS_ACCTON_AS4610_FAN=y
CONFIG_SENSORS_ACCTON_AS4610_PSU=y
CONFIG_SENSORS_YM2651Y=y

View File

@@ -1,6 +1,6 @@
--- /dev/null
+++ b/arch/arm/boot/dts/accton_as4610_54.dts
@@ -0,0 +1,256 @@
@@ -0,0 +1,250 @@
+/*
+ * Accton AS4610 54 Device Tree Source
+ *
@@ -117,7 +117,7 @@
+ cpld@1,0 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "accton,as4610_54_cpld";
+ compatible = "accton,as4610-54-cpld";
+ label = "cpld";
+ reg = <0x30>;
+ };
@@ -142,8 +142,8 @@
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0>;
+ optoe@50 {
+ compatible = "optoe2";
+ sfp_eeprom@50 {
+ compatible = "at,24c04";
+ reg = <0x50>;
+ label = "port49";
+ };
@@ -154,8 +154,8 @@
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <1>;
+ optoe@50 {
+ compatible = "optoe2";
+ sfp_eeprom@50 {
+ compatible = "at,24c04";
+ reg = <0x50>;
+ label = "port50";
+ };
@@ -166,8 +166,8 @@
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <2>;
+ optoe@50 {
+ compatible = "optoe2";
+ sfp_eeprom@50 {
+ compatible = "at,24c04";
+ reg = <0x50>;
+ label = "port51";
+ };
@@ -178,8 +178,8 @@
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <3>;
+ optoe@50 {
+ compatible = "optoe2";
+ sfp_eeprom@50 {
+ compatible = "at,24c04";
+ reg = <0x50>;
+ label = "port52";
+ };
@@ -190,10 +190,9 @@
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <4>;
+ optoe@50 {
+ compatible = "optoe1";
+ sfp_eeprom@50 {
+ compatible = "at,24c04";
+ reg = <0x50>;
+ label = "port53";
+ };
+ };
+
@@ -202,10 +201,9 @@
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <5>;
+ optoe@50 {
+ compatible = "optoe1";
+ sfp_eeprom@50 {
+ compatible = "at,24c04";
+ reg = <0x50>;
+ label = "port54";
+ };
+ };
+
@@ -214,21 +212,17 @@
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <6>;
+ psu1_eeprom@50 {
+ compatible = "accton,as4610_psu1";
+ psu_eeprom@50 {
+ compatible = "at,24c02";
+ reg = <0x50>;
+ label = "psu1_eeprom";
+ read-only;
+ };
+ psu1_pmbus@58 {
+ compatible = "3y-power,ym1921";
+ reg = <0x58>;
+ };
+ psu2_eeprom@51 {
+ compatible = "accton,as4610_psu2";
+ psu_eeprom@51 {
+ compatible = "at,24c02";
+ reg = <0x51>;
+ };
+ psu2_pmbus@59 {
+ compatible = "3y-power,ym1921";
+ reg = <0x59>;
+ label = "psu2_eeprom";
+ read-only;
+ };
+ };
+

View File

@@ -0,0 +1,2 @@
linux-4.14*
kernel-4.14*

View File

@@ -1,4 +1,4 @@
############################################################
###########################################################
# <bsn.cl fy=2015 v=onl>
#
# Copyright 2015 Big Switch Networks, Inc.
@@ -29,13 +29,14 @@ endif
K_PATCH_DIR := $(THIS_DIR)/patches
include ../../kconfig.mk
K_CONFIG := arm-iproc-all.config
K_CONFIG := armel-iproc-all.config
K_BUILD_TARGET := Image
K_COPY_SRC := arch/arm/boot/Image
K_COPY_GZIP := 1
ifndef K_COPY_DST
K_COPY_DST := kernel-4.4-lts-arm-iproc-all.bin.gz
K_COPY_DST := kernel-4.14-lts-armel-iproc-all.bin.gz
endif
export ARCH=arm
include $(ONL)/make/kbuild.mk

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,86 @@
diff -urpN a/drivers/i2c/busses/xgs_iproc_smbus.c b/drivers/i2c/busses/xgs_iproc_smbus.c
--- a/drivers/i2c/busses/xgs_iproc_smbus.c 2018-12-17 15:00:29.412457650 +0000
+++ b/drivers/i2c/busses/xgs_iproc_smbus.c 2018-12-17 15:01:26.255275662 +0000
@@ -52,6 +52,8 @@
(regval & ~(mask)) | \
((fldval) << (startbit))
+//#define IPROC_SMB_DBG 1
+
typedef enum iproc_smb_clk_freq {
I2C_SPEED_100KHz = 0,
I2C_SPEED_400KHz = 1,
@@ -178,7 +180,7 @@ static int iproc_smb_set_clk_freq(void _
SETREGFLDVAL(regval, val, CCB_SMB_TIMGCFG_MODE400_MASK,
CCB_SMB_TIMGCFG_MODE400_SHIFT);
writel(regval, base_addr + CCB_SMB_TIMGCFG_REG);
-
+
return 0;
}
@@ -208,9 +210,20 @@ static int iproc_smbus_block_init(struct
udelay(100);
/* Set default clock frequency */
- if (of_property_read_u32(dn, "clock-frequency", &i2c_clk_freq))
- /*no property available, use default: 100KHz*/
- i2c_clk_freq = I2C_SPEED_100KHz;
+ if (of_property_read_u32(dn, "clock-frequency", &i2c_clk_freq)) {
+ /*no property available, use default: 100KHz*/
+ i2c_clk_freq = 100000;
+ }
+
+/* Edgecore patch */
+ if (i2c_clk_freq == 400000) {
+ dev_info(dev->dev, "bus set to %u Hz\n", i2c_clk_freq);
+ i2c_clk_freq = I2C_SPEED_400KHz;
+ } else {
+ dev_info(dev->dev, "bus set to %u Hz\n", 100000);
+ i2c_clk_freq = I2C_SPEED_100KHz;
+ }
+
iproc_smb_set_clk_freq(base_addr, i2c_clk_freq);
/* Disable intrs */
@@ -577,7 +590,9 @@ static int iproc_smb_data_send(struct i2
if (regval != MSTR_STS_XACT_SUCCESS) {
/* We can flush Tx FIFO here */
+#ifdef IPROC_SMB_DBG
dev_err(dev->dev, "Send: Error in transaction\n");
+#endif
return -EREMOTEIO;
}
}
@@ -662,7 +677,9 @@ static int iproc_smb_data_recv(struct i2
if (regval != MSTR_STS_XACT_SUCCESS) {
/* We can flush Tx FIFO here */
+#ifdef IPROC_SMB_DBG
dev_info(dev->dev, "Error in transaction\n");
+#endif
return -EREMOTEIO;
}
}
@@ -840,8 +857,10 @@ static int iproc_smb_xfer(struct i2c_ada
}
if (rc < 0) {
+#ifdef IPROC_SMB_DBG
dev_info(dev->dev, "%s error accessing\n",
(read_write == I2C_SMBUS_READ) ? "Read" : "Write");
+#endif
up(&dev->xfer_lock);
return -EREMOTEIO;
}
@@ -856,7 +875,8 @@ static int iproc_smb_xfer(struct i2c_ada
}
}
- msleep(1);
+ /* Edge-core comments out the sleep to speed up EEPROM dump */
+ //msleep(1);
up(&dev->xfer_lock);
return (rc);

View File

@@ -0,0 +1,26 @@
diff -urpN a/drivers/usb/phy/phy-xgs-iproc.c b/drivers/usb/phy/phy-xgs-iproc.c
--- a/drivers/usb/phy/phy-xgs-iproc.c 2018-12-17 14:49:55.121649311 +0000
+++ b/drivers/usb/phy/phy-xgs-iproc.c 2018-12-17 14:50:06.529412019 +0000
@@ -161,12 +161,22 @@ static int xgs_iproc_usb_phy_mode(struct
int usb_mode = IPROC_USB_MODE_HOST;
u32 __maybe_unused val;
int __maybe_unused gpio_pin, ret;
+ const char *phy_mode_str;
if (!wrap_base)
dev_warn(dev, "no wrap base addr");
if (of_device_is_compatible(dn, "brcm,usb-phy-hx4") ||
of_device_is_compatible(dn, "brcm,usb-phy-kt2")) {
+
+ /* Edge-core patch: use "usb-phy-mode" in dts to decide host/device mode */
+ if (!of_property_read_string(dn, "usb-phy-mode", &phy_mode_str)) {
+ if (!strcasecmp(phy_mode_str, "host"))
+ return IPROC_USB_MODE_HOST;
+ if (!strcasecmp(phy_mode_str, "device"))
+ return IPROC_USB_MODE_DEVICE;
+ }
+
/* gpio pin 4 to control host/device mode */
gpio_pin = of_get_named_gpio(dev->of_node, "usbdev-gpio", 0);

View File

@@ -1,3 +1,5 @@
brcm-iproc-4.14.patch
drivers-usb-phy-phy-xgs-iproc-usb-phy-mode.patch
drivers-i2c-busses-xgs_iproc_smbus-clk-freq.patch
0001-drivers-i2c-muxes-pca954x-deselect-on-exit.patch
0002-driver-support-intel-igb-bcm5461S-phy.patch

View File

@@ -1,3 +0,0 @@
kernel-*
linux-*
lib/

View File

@@ -1,26 +0,0 @@
############################################################
# <bsn.cl fy=2015 v=onl>
#
# Copyright 2015 Big Switch Networks, Inc.
#
# Licensed under the Eclipse Public License, Version 1.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.eclipse.org/legal/epl-v10.html
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
# either express or implied. See the License for the specific
# language governing permissions and limitations under the
# License.
#
# </bsn.cl>
############################################################
THIS_DIR := $(abspath $(dir $(lastword $(MAKEFILE_LIST))))
K_MAJOR_VERSION := 4
K_PATCH_LEVEL := 4
K_SUB_LEVEL := 39
K_SUFFIX :=
K_PATCH_DIR := $(THIS_DIR)/patches

View File

@@ -1 +0,0 @@
kernel-4.4-brcm-iproc.patch

File diff suppressed because it is too large Load Diff

View File

@@ -18,6 +18,7 @@ common:
maintainer: support@bigswitch.com
support: opennetworklinux@googlegroups.com
changelog: None
dists: $DISTS
packages:
- name: onl-platform-config-$PLATFORM

View File

@@ -5,6 +5,7 @@ common:
copyright: Copyright 2013, 2014, 2015 Big Switch Networks
maintainer: support@bigswitch.com
support: opennetworklinux@googlegroups.com
dists: jessie
packages:
- name: onl-kernel-3.2-lts-arm-iproc-all

View File

@@ -0,0 +1 @@
!include $ONL/packages/base/any/kernels/lts/APKG.yml VERSION=4.14 ARCH=armel CONFIG=armel-iproc-all

View File

@@ -0,0 +1,5 @@
KERNEL_BUILD_DIR := $(abspath $(dir $(lastword $(MAKEFILE_LIST))))
KERNEL_ARCH := arm
KERNEL_LTS_VERSION := 4.14
KERNEL_CONFIG := armel-iproc-all
include $(ONL)/packages/base/any/kernels/lts/builds/Makefile

View File

@@ -1,18 +0,0 @@
common:
arch: armel
version: 1.0.0
copyright: Copyright 2013, 2014, 2015 Big Switch Networks
maintainer: support@bigswitch.com
support: opennetworklinux@googlegroups.com
packages:
- name: onl-kernel-4.4-lts-arm-iproc-all
version: 1.0.0
summary: Open Network Linux Kernel 4.4-LTS for ARM Integrated Processor Platforms.
files:
builds/kernel-4.4-lts-arm-iproc-all.bin.gz : $$PKG_INSTALL/
builds/linux-4.4.*-mbuild : $$PKG_INSTALL/mbuilds
changelog: Change changes changes.,

View File

@@ -1,21 +0,0 @@
# -*- Makefile -*-
############################################################
# <bsn.cl fy=2013 v=none>
#
# Copyright 2013, 2014 BigSwitch Networks, Inc.
#
#
#
# </bsn.cl>
############################################################
THIS_DIR := $(abspath $(dir $(lastword $(MAKEFILE_LIST))))
include $(ONL)/make/config.mk
#export MODSYNCLIST_EXTRA := arch/arm/plat-iproc/include
kernel:
$(MAKE) -C $(ONL)/packages/base/any/kernels/4.4-lts/configs/arm-iproc-all K_TARGET_DIR=$(THIS_DIR) $(ONL_MAKE_PARALLEL)
clean:
rm -rf kernel-* linux-4.4.*

View File

@@ -1 +1 @@
!include $ONL_TEMPLATES/no-platform-modules.yml ARCH=armel VENDOR=accton BASENAME=arm-accton-as4610-30
!include $ONL_TEMPLATES/platform-modules.yml ARCH=armel VENDOR=accton BASENAME=arm-accton-as4610-30 KERNELS="onl-kernel-4.14-lts-armel-iproc-all:armel"

View File

@@ -0,0 +1,7 @@
KERNELS := onl-kernel-4.14-lts-armel-iproc-all:armel
KMODULES := $(wildcard $(ONL)/packages/platforms/accton/armel/arm-accton-as4610/src/modules/*.c)
KINCLUDES := $(wildcard $(ONL)/packages/platforms/accton/armel/arm-accton-as4610/src/modules/*.h)
VENDOR := accton
BASENAME := arm-accton-as4610-30
ARCH := arm
include $(ONL)/make/kmodule.mk

View File

@@ -1,10 +1,15 @@
INCLUDES=include .
KERNEL := onl-kernel-4.14-lts-armel-iproc-all:armel
DTS_LIST := arm-accton-as4610.dts
VPATH := ../../../../../src
include $(ONL)/make/dtbs.mk
#
# The 4610 DTS relies on the common arm devices tree includes. These are linked here from the kernel package.
#
setup::
onlpm --link-dir onl-kernel-3.2-lts-arm-iproc-all:armel /usr/share/onl/packages/armel/onl-kernel-3.2-lts-arm-iproc-all/mbuilds/arch/arm/boot/dts dts
onlpm --link-dir onl-kernel-4.14-lts-armel-iproc-all:armel /usr/share/onl/packages/armel/onl-kernel-4.14-lts-armel-iproc-all/mbuilds/arch/arm/boot/dts dts
onlpm --link-dir onl-kernel-4.14-lts-armel-iproc-all:armel /usr/share/onl/packages/armel/onl-kernel-4.14-lts-armel-iproc-all/mbuilds/include include
clean::
rm -rf fsl
setup-clean::
rm -f dts include

View File

@@ -139,8 +139,8 @@
#address-cells = <1>;
#size-cells = <0>;
reg = <0>;
optoe@50 {
compatible = "optoe2";
sfp_eeprom@50 {
compatible = "at,as4610_sfp1";
reg = <0x50>;
label = "port49";
};
@@ -151,8 +151,8 @@
#address-cells = <1>;
#size-cells = <0>;
reg = <1>;
optoe@50 {
compatible = "optoe2";
sfp_eeprom@50 {
compatible = "accton,as4610_sfp2";
reg = <0x50>;
label = "port50";
};
@@ -163,8 +163,8 @@
#address-cells = <1>;
#size-cells = <0>;
reg = <2>;
optoe@50 {
compatible = "optoe2";
sfp_eeprom@50 {
compatible = "accton,as4610_sfp3";
reg = <0x50>;
label = "port51";
};
@@ -175,8 +175,8 @@
#address-cells = <1>;
#size-cells = <0>;
reg = <3>;
optoe@50 {
compatible = "optoe2";
sfp_eeprom@50 {
compatible = "accton,as4610_sfp4";
reg = <0x50>;
label = "port52";
};
@@ -187,10 +187,9 @@
#address-cells = <1>;
#size-cells = <0>;
reg = <4>;
optoe@50 {
compatible = "optoe1";
sfp_eeprom@50 {
compatible = "accton,as4610_sfp5";
reg = <0x50>;
label = "port53";
};
};
@@ -199,10 +198,9 @@
#address-cells = <1>;
#size-cells = <0>;
reg = <5>;
optoe@50 {
compatible = "optoe1";
sfp_eeprom@50 {
compatible = "accton,as4610_sfp6";
reg = <0x50>;
label = "port54";
};
};

View File

@@ -9,9 +9,9 @@
arm-accton-as4610-30-r0:
flat_image_tree:
kernel:
<<: *arm-iproc-kernel
<<: *armel-iproc-4-14-kernel
dtb:
=: arm-accton-as4610-54-r0.dtb
=: arm-accton-as4610.dtb
package: onl-platform-build-arm-accton-as4610-30-r0:armel
itb:

View File

@@ -6,3 +6,13 @@ class OnlPlatform_arm_accton_as4610_30_r0(OnlPlatformAccton,
PLATFORM='arm-accton-as4610-30-r0'
MODEL="AS4610-30"
SYS_OBJECT_ID=".4610.30"
def baseconfig(self):
self.insmod("accton_i2c_cpld")
self.new_i2c_device("as4610_30_cpld", 0x30, 0)
self.insmod("accton_as4610_sfp")
self.insmod("accton_as4610_psu")
self.insmod("accton_as4610_fan")
self.insmod("accton_as4610_leds")
self.insmod("ym2651y")
return True

View File

@@ -1 +1 @@
!include $ONL_TEMPLATES/no-platform-modules.yml ARCH=armel VENDOR=accton BASENAME=arm-accton-as4610-54
!include $ONL_TEMPLATES/platform-modules.yml ARCH=armel VENDOR=accton BASENAME=arm-accton-as4610-54 KERNELS="onl-kernel-4.14-lts-armel-iproc-all:armel"

View File

@@ -0,0 +1,7 @@
KERNELS := onl-kernel-4.14-lts-armel-iproc-all:armel
KMODULES := $(wildcard $(ONL)/packages/platforms/accton/armel/arm-accton-as4610/src/modules/*.c)
KINCLUDES := $(wildcard $(ONL)/packages/platforms/accton/armel/arm-accton-as4610/src/modules/*.h)
VENDOR := accton
BASENAME := arm-accton-as4610-54
ARCH := arm
include $(ONL)/make/kmodule.mk

View File

@@ -1,10 +1,15 @@
INCLUDES=include .
KERNEL := onl-kernel-4.14-lts-armel-iproc-all:armel
DTS_LIST := arm-accton-as4610.dts
VPATH := ../../../../../src
include $(ONL)/make/dtbs.mk
#
# The 4610 DTS relies on the common arm devices tree includes. These are linked here from the kernel package.
#
setup::
onlpm --link-dir onl-kernel-3.2-lts-arm-iproc-all:armel /usr/share/onl/packages/armel/onl-kernel-3.2-lts-arm-iproc-all/mbuilds/arch/arm/boot/dts dts
onlpm --link-dir onl-kernel-4.14-lts-armel-iproc-all:armel /usr/share/onl/packages/armel/onl-kernel-4.14-lts-armel-iproc-all/mbuilds/arch/arm/boot/dts dts
onlpm --link-dir onl-kernel-4.14-lts-armel-iproc-all:armel /usr/share/onl/packages/armel/onl-kernel-4.14-lts-armel-iproc-all/mbuilds/include include
clean::
rm -rf fsl
setup-clean::
rm -f dts include

View File

@@ -139,8 +139,8 @@
#address-cells = <1>;
#size-cells = <0>;
reg = <0>;
optoe@50 {
compatible = "optoe2";
sfp_eeprom@50 {
compatible = "at,as4610_sfp1";
reg = <0x50>;
label = "port49";
};
@@ -151,8 +151,8 @@
#address-cells = <1>;
#size-cells = <0>;
reg = <1>;
optoe@50 {
compatible = "optoe2";
sfp_eeprom@50 {
compatible = "accton,as4610_sfp2";
reg = <0x50>;
label = "port50";
};
@@ -163,8 +163,8 @@
#address-cells = <1>;
#size-cells = <0>;
reg = <2>;
optoe@50 {
compatible = "optoe2";
sfp_eeprom@50 {
compatible = "accton,as4610_sfp3";
reg = <0x50>;
label = "port51";
};
@@ -175,8 +175,8 @@
#address-cells = <1>;
#size-cells = <0>;
reg = <3>;
optoe@50 {
compatible = "optoe2";
sfp_eeprom@50 {
compatible = "accton,as4610_sfp4";
reg = <0x50>;
label = "port52";
};
@@ -187,10 +187,9 @@
#address-cells = <1>;
#size-cells = <0>;
reg = <4>;
optoe@50 {
compatible = "optoe1";
sfp_eeprom@50 {
compatible = "accton,as4610_sfp5";
reg = <0x50>;
label = "port53";
};
};
@@ -199,10 +198,9 @@
#address-cells = <1>;
#size-cells = <0>;
reg = <5>;
optoe@50 {
compatible = "optoe1";
sfp_eeprom@50 {
compatible = "accton,as4610_sfp6";
reg = <0x50>;
label = "port54";
};
};

View File

@@ -2,16 +2,16 @@
######################################################################
#
# platform-config for AS4610
# platform-config for AS4610-54
#
######################################################################
arm-accton-as4610-54-r0:
flat_image_tree:
kernel:
<<: *arm-iproc-kernel
<<: *armel-iproc-4-14-kernel
dtb:
=: arm-accton-as4610-54-r0.dtb
=: arm-accton-as4610.dtb
package: onl-platform-build-arm-accton-as4610-54-r0:armel
itb:

View File

@@ -6,3 +6,31 @@ class OnlPlatform_arm_accton_as4610_54_r0(OnlPlatformAccton,
PLATFORM='arm-accton-as4610-54-r0'
MODEL="AS4610-54"
SYS_OBJECT_ID=".4610.54"
def baseconfig(self):
self.insmod("accton_i2c_cpld")
self.new_i2c_device("as4610_54_cpld", 0x30, 0)
self.insmod("accton_as4610_sfp")
self.insmod("accton_as4610_psu")
self.insmod("accton_as4610_fan")
self.insmod("accton_as4610_leds")
self.insmod("ym2651y")
# self.new_i2c_devices(
# [
# ("pca9548", 0x70, 1),
# ("as4610_sfp1", 0x50, 2),
# ("as4610_sfp2", 0x50, 3),
# ("as4610_sfp3", 0x50, 4),
# ("as4610_sfp4", 0x50, 5),
# ("as4610_sfp5", 0x50, 6),
# ("as4610_sfp6", 0x50, 7),
# ("as4610_psu1", 0x50, 8),
# ("as4610_psu2", 0x51, 8),
# ("ym1921", 0x58, 8),
# ("ym1921", 0x59, 8),
# ("lm77", 0x48, 9),
# ("ds1307", 0x68, 9),
# ("24c04", 0x50, 9),
# ]
# )
return True

View File

@@ -0,0 +1,286 @@
/*
* Accton AS4610 54 Device Tree Source
*
* Copyright 2015, Cumulus Networks, 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.
*
*/
/dts-v1/;
#include "dts/bcm-helix4.dtsi"
/ {
model = "accton,as4610_54";
compatible = "accton,as4610_54","brcm,helix4";
aliases {
serial0 = &uart1;
serial1 = &uart2;
ethernet0 = &gmac0;
i2c-controller0 = &i2c0;
i2c-controller1 = &i2c1;
};
/*
chosen {
bootargs = "console=ttyS0,115200n8 maxcpus=2 mem=2000M";
};
*/
memory {
reg = <0x61000000 0x7f000000>;
};
localbus@1c000000 {
#address-cells = <0x2>;
#size-cells = <0x1>;
/* NAND Flash */
ranges = <
0x0 0x0 0x0 0x1c000000 0x00120000
0x1 0x0 0x0 0x1c120000 0x00040000
>;
flash@0,0 {
#address-cells = <1>;
#size-cells = <1>;
compatible = "cfi-flash";
reg = <0x0 0x0 0x02000000>;
byteswap;
partition@0 {
/* uboot */
reg = <0x00000000 0x00100000>;
label = "uboot";
};
partition@1 {
/* uboot-env */
reg = <0x00100000 0x00100000>;
label = "uboot-env";
env_size = <0x2000>;
};
partition@2 {
/* board_eeprom */
reg = <0x00200000 0x00100000>;
label = "board_eeprom";
};
partition@3 {
/* shmoo */
reg = <0x00300000 0x00100000>;
label = "shmoo";
};
partition@4 {
/* onie */
reg = <0x00400000 0x00800000>;
label = "onie";
};
partition@5 {
/* open */
reg = <0x00c00000 0x03c00000>;
label = "open";
};
partition@6 {
/* open2 */
reg = <0x04800000 0x7d000000>;
label = "open2";
};
partition@7 {
/* diag */
reg = <0xfec00000 0x01000000>;
label = "diag";
};
};
};
};
&uart1 {
status = "okay";
};
&uart2 {
status = "okay";
};
&gmac0 {
status = "okay";
phy-mode = "sgmii"; /* "gmii-id", "gmii-rxid", "sgmii" */
};
&usbphy0 {
status = "okay";
usb-phy-mode = "host"; /* "host", "device" */
/* mdio-phy-handle = <&usb_phy>;
*/
};
&ehci0 {
status = "okay";
};
&gpio_cca {
status = "okay";
};
&i2c0 {
status = "okay";
clock-frequency = <400000>;
cpld@30 {
#address-cells = <1>;
#size-cells = <1>;
compatible = "accton,as4610_54_cpld";
label = "cpld";
reg = <0x30>;
};
};
&i2c1 {
status = "okay";
mux@70 {
compatible = "ti,pca9548";
reg = <0x70>;
#address-cells = <1>;
#size-cells = <0>;
deselect-on-exit;
// SFP+ 1
i2c@0 {
#address-cells = <1>;
#size-cells = <0>;
reg = <0>;
sfp_eeprom@50 {
compatible = "accton,as4610_sfp1";
reg = <0x50>;
label = "port49";
};
};
// SFP+ 2
i2c@1 {
#address-cells = <1>;
#size-cells = <0>;
reg = <1>;
sfp_eeprom@50 {
compatible = "accton,as4610_sfp2";
reg = <0x50>;
label = "port50";
};
};
// SFP+ 3
i2c@2 {
#address-cells = <1>;
#size-cells = <0>;
reg = <2>;
sfp_eeprom@50 {
compatible = "accton,as4610_sfp3";
reg = <0x50>;
label = "port51";
};
};
// SFP+ 4
i2c@3 {
#address-cells = <1>;
#size-cells = <0>;
reg = <3>;
sfp_eeprom@50 {
compatible = "accton,as4610_sfp4";
reg = <0x50>;
label = "port52";
};
};
// QSFP+ STK1
i2c@4 {
#address-cells = <1>;
#size-cells = <0>;
reg = <4>;
sfp_eeprom@50 {
compatible = "accton,as4610_sfp5";
reg = <0x50>;
};
};
// QSFP+ STK2
i2c@5 {
#address-cells = <1>;
#size-cells = <0>;
reg = <5>;
sfp_eeprom@50 {
compatible = "accton,as4610_sfp6";
reg = <0x50>;
};
};
// PSU EEPROM
i2c@6 {
#address-cells = <1>;
#size-cells = <0>;
reg = <6>;
psu1_eeprom@50 {
compatible = "accton,as4610_psu1";
reg = <0x50>;
};
psu1_pmbus@58 {
compatible = "3y-power,ym1921";
reg = <0x58>;
};
psu2_eeprom@51 {
compatible = "accton,as4610_psu2";
reg = <0x51>;
};
psu2_pmbus@59 {
compatible = "3y-power,ym1921";
reg = <0x59>;
};
};
i2c@7 {
#address-cells = <1>;
#size-cells = <0>;
reg = <7>;
temp@48 {
compatible = "nxp,lm77";
reg = <0x48>;
};
rtc@68 {
/* Actually M41T11 */
compatible = "dallas,ds1307";
reg = <0x68>;
};
board_eeprom@50 {
compatible = "at,24c04";
reg = <0x50>;
label = "board_eeprom";
};
};
};
};
/*
&mdio_int {
status = "okay";
usb_phy: usb_phy@0 {
reg = <6>;
};
};
*/
&hwrng {
status = "okay";
};
&iproc_wdt {
status = "okay";
};
&dmac0 {
status = "okay";
};
&iproc_cmicd {
status = "okay";
};

View File

@@ -28,8 +28,8 @@
#include "arm_accton_as4610_log.h"
#define CHASSIS_THERMAL_COUNT 1
#define CHASSIS_PSU_COUNT 2
#define CHASSIS_THERMAL_COUNT 1
#define CHASSIS_PSU_COUNT 2
#define PSU1_ID 1
#define PSU2_ID 2
@@ -46,7 +46,7 @@
#define PSU1_AC_EEPROM_NODE(node) PSU1_AC_EEPROM_PREFIX#node
#define PSU2_AC_EEPROM_NODE(node) PSU2_AC_EEPROM_PREFIX#node
#define IDPROM_PATH "/sys/devices/1803b000.i2c/i2c-1/i2c-9/9-0050/eeprom"
#define IDPROM_PATH "/sys/devices/platform/axi/1803b000.i2c/i2c-1/i2c-9/9-0050/eeprom"
int deviceNodeWriteInt(char *filename, int value, int data_len);
int deviceNodeReadBinary(char *filename, char *buffer, int buf_size, int data_len);
@@ -97,4 +97,3 @@ typedef enum platform_id_e {
extern platform_id_t platform_id;
#endif /* __PLATFORM_LIB_H__ */

View File

@@ -24,31 +24,50 @@
*
***********************************************************/
#include <onlp/platformi/sfpi.h>
#include <onlplib/file.h>
#include "platform_lib.h"
#include <arm_accton_as4610/arm_accton_as4610_config.h>
#include "arm_accton_as4610_log.h"
#define PORT_EEPROM_FORMAT "/sys/bus/i2c/devices/%d-0050/eeprom"
#define MODULE_PRESENT_FORMAT "/sys/bus/i2c/devices/0-0030/module_present_%d"
#define MODULE_RXLOS_FORMAT "/sys/bus/i2c/devices/0-0030/module_rx_los_%d"
#define MODULE_TXFAULT_FORMAT "/sys/bus/i2c/devices/0-0030/module_tx_fault_%d"
#define MODULE_PRESENT_ALL_ATTR_CPLD "/sys/bus/i2c/devices/0-0030/module_present_all"
#define MODULE_RXLOS_ALL_ATTR_CPLD "/sys/bus/i2c/devices/0-0030/module_rx_los_all"
#define MAX_SFP_PATH 64
static char sfp_node_path[MAX_SFP_PATH] = {0};
#define FRONT_PORT_MUX_INDEX(port) (port-46)
static int front_port_bus_index(int port)
static int
sfp_node_read_int(char *node_path, int *value, int data_len)
{
return (platform_id == PLATFORM_ID_POWERPC_ACCTON_AS4610_30_R0) ?
(port - 22) : /* PLATFORM_ID_POWERPC_ACCTON_AS4610_30_R0 */
(port - 46) ; /* PLATFORM_ID_POWERPC_ACCTON_AS4610_54_R0 */
int ret = 0;
char buf[8];
*value = 0;
ret = deviceNodeReadString(node_path, buf, sizeof(buf), data_len);
if (ret == 0) {
*value = atoi(buf);
}
return ret;
}
static int front_port_to_cpld_port(int port)
static char*
sfp_get_port_path_addr(int port, int addr, char *node_name)
{
return (platform_id == PLATFORM_ID_POWERPC_ACCTON_AS4610_30_R0) ?
(port - 23) : /* PLATFORM_ID_POWERPC_ACCTON_AS4610_30_R0 */
(port - 47) ; /* PLATFORM_ID_POWERPC_ACCTON_AS4610_54_R0 */
int front_port_mux_id;
if(platform_id == PLATFORM_ID_POWERPC_ACCTON_AS4610_30_R0)
front_port_mux_id = port - 22;
else /*PLATFORM_ID_POWERPC_ACCTON_AS4610_54_R0*/
front_port_mux_id = port - 46;
sprintf(sfp_node_path, "/sys/bus/i2c/devices/%d-00%d/%s",
front_port_mux_id, addr, node_name);
return sfp_node_path;
}
static char*
sfp_get_port_path(int port, char *node_name)
{
return sfp_get_port_path_addr(port, 50, node_name);
}
/************************************************************
@@ -96,9 +115,9 @@ onlp_sfpi_is_present(int port)
* Return < 0 if error.
*/
int present;
int cpld_port = front_port_to_cpld_port(port);
if (onlp_file_read_int(&present, MODULE_PRESENT_FORMAT, cpld_port) < 0) {
char* path = sfp_get_port_path(port, "sfp_is_present");
if (sfp_node_read_int(path, &present, 0) != 0) {
AIM_LOG_ERROR("Unable to read present status from port(%d)\r\n", port);
return ONLP_STATUS_E_INTERNAL;
}
@@ -110,6 +129,7 @@ int
onlp_sfpi_presence_bitmap_get(onlp_sfp_bitmap_t* dst)
{
uint32_t byte;
char* path;
FILE* fp;
int port;
@@ -120,18 +140,18 @@ onlp_sfpi_presence_bitmap_get(onlp_sfp_bitmap_t* dst)
else /*PLATFORM_ID_POWERPC_ACCTON_AS4610_54_R0*/
port = 48;
/* Read present status of each port */
fp = fopen(MODULE_PRESENT_ALL_ATTR_CPLD, "r");
path = sfp_get_port_path(port, "sfp_is_present_all");
fp = fopen(path, "r");
if(fp == NULL) {
AIM_LOG_ERROR("Unable to open the module_present_all device file of CPLD.");
AIM_LOG_ERROR("Unable to open the sfp_is_present_all device file.");
return ONLP_STATUS_E_INTERNAL;
}
int count = fscanf(fp, "%x", &byte);
fclose(fp);
if(count != 1) {
/* Likely a CPLD read timeout. */
AIM_LOG_ERROR("Unable to read all fields the module_present_all device file of CPLD.");
AIM_LOG_ERROR("Unable to read all fields from the sfp_is_present_all device file.");
return ONLP_STATUS_E_INTERNAL;
}
@@ -153,6 +173,7 @@ int
onlp_sfpi_rx_los_bitmap_get(onlp_sfp_bitmap_t* dst)
{
uint32_t byte;
char* path;
FILE* fp;
int port;
@@ -161,18 +182,16 @@ onlp_sfpi_rx_los_bitmap_get(onlp_sfp_bitmap_t* dst)
else /*PLATFORM_ID_POWERPC_ACCTON_AS4610_54_R0*/
port = 48;
/* Read present status of each port */
fp = fopen(MODULE_RXLOS_ALL_ATTR_CPLD, "r");
path = sfp_get_port_path(port, "sfp_rx_los_all");
fp = fopen(path, "r");
if(fp == NULL) {
AIM_LOG_ERROR("Unable to open the module_rx_los_all device file of CPLD.");
AIM_LOG_ERROR("Unable to open the sfp_rx_los_all device file.");
return ONLP_STATUS_E_INTERNAL;
}
int count = fscanf(fp, "%x", &byte);
fclose(fp);
if(count != 1) {
/* Likely a CPLD read timeout. */
AIM_LOG_ERROR("Unable to read all fields the module_rx_los_all device file of CPLD.");
AIM_LOG_ERROR("Unable to read all fields from the sfp_rx_los_all device file.");
return ONLP_STATUS_E_INTERNAL;
}
@@ -193,51 +212,32 @@ onlp_sfpi_rx_los_bitmap_get(onlp_sfp_bitmap_t* dst)
int
onlp_sfpi_eeprom_read(int port, uint8_t data[256])
{
char* path = sfp_get_port_path(port, "sfp_eeprom");
/*
* Read the SFP eeprom into data[]
*
* Return MISSING if SFP is missing.
* Return OK if eeprom is read
*/
int size = 0;
memset(data, 0, 256);
if(onlp_file_read(data, 256, &size, PORT_EEPROM_FORMAT, front_port_bus_index(port)) != ONLP_STATUS_OK) {
if (deviceNodeReadBinary(path, (char*)data, 256, 256) != 0) {
AIM_LOG_ERROR("Unable to read eeprom from port(%d)\r\n", port);
return ONLP_STATUS_E_INTERNAL;
}
if (size != 256) {
AIM_LOG_ERROR("Unable to read eeprom from port(%d), size is different!\r\n", port);
return ONLP_STATUS_E_INTERNAL;
}
return ONLP_STATUS_OK;
}
int
onlp_sfpi_dom_read(int port, uint8_t data[256])
{
FILE* fp;
char file[64] = {0};
sprintf(file, PORT_EEPROM_FORMAT, front_port_bus_index(port));
fp = fopen(file, "r");
if(fp == NULL) {
AIM_LOG_ERROR("Unable to open the eeprom device file of port(%d)", port);
return ONLP_STATUS_E_INTERNAL;
}
char* path = sfp_get_port_path_addr(port, 51, "sfp_eeprom");
memset(data, 0, 256);
if (fseek(fp, 256, SEEK_CUR) != 0) {
fclose(fp);
AIM_LOG_ERROR("Unable to set the file position indicator of port(%d)", port);
return ONLP_STATUS_E_INTERNAL;
}
int ret = fread(data, 1, 256, fp);
fclose(fp);
if (ret != 256) {
AIM_LOG_ERROR("Unable to read the module_eeprom device file of port(%d)", port);
if (deviceNodeReadBinary(path, (char*)data, 256, 256) != 0) {
AIM_LOG_INFO("Unable to read eeprom from port(%d)\r\n", port);
return ONLP_STATUS_E_INTERNAL;
}
@@ -247,24 +247,45 @@ onlp_sfpi_dom_read(int port, uint8_t data[256])
int
onlp_sfpi_control_set(int port, onlp_sfp_control_t control, int value)
{
return ONLP_STATUS_E_UNSUPPORTED;
int rv;
switch(control)
{
case ONLP_SFP_CONTROL_TX_DISABLE:
{
char* path = sfp_get_port_path(port, "sfp_tx_disable");
if (deviceNodeWriteInt(path, value, 0) != 0) {
AIM_LOG_ERROR("Unable to set tx_disable status to port(%d)\r\n", port);
rv = ONLP_STATUS_E_INTERNAL;
}
else {
rv = ONLP_STATUS_OK;
}
break;
}
default:
rv = ONLP_STATUS_E_UNSUPPORTED;
break;
}
return rv;
}
int
onlp_sfpi_control_get(int port, onlp_sfp_control_t control, int* value)
{
int rv;
int cpld_port = front_port_to_cpld_port(port);
if (cpld_port > 4) {
return ONLP_STATUS_E_UNSUPPORTED;
}
char* path = NULL;
switch(control)
{
case ONLP_SFP_CONTROL_RX_LOS:
{
if (onlp_file_read_int(value, MODULE_RXLOS_FORMAT, cpld_port) < 0) {
path = sfp_get_port_path(port, "sfp_rx_los");
if (sfp_node_read_int(path, value, 0) != 0) {
AIM_LOG_ERROR("Unable to read rx_los status from port(%d)\r\n", port);
rv = ONLP_STATUS_E_INTERNAL;
}
@@ -276,7 +297,9 @@ onlp_sfpi_control_get(int port, onlp_sfp_control_t control, int* value)
case ONLP_SFP_CONTROL_TX_FAULT:
{
if (onlp_file_read_int(value, MODULE_TXFAULT_FORMAT, cpld_port) < 0) {
path = sfp_get_port_path(port, "sfp_tx_fault");
if (sfp_node_read_int(path, value, 0) != 0) {
AIM_LOG_ERROR("Unable to read tx_fault status from port(%d)\r\n", port);
rv = ONLP_STATUS_E_INTERNAL;
}
@@ -286,6 +309,20 @@ onlp_sfpi_control_get(int port, onlp_sfp_control_t control, int* value)
break;
}
case ONLP_SFP_CONTROL_TX_DISABLE:
{
path = sfp_get_port_path(port, "sfp_tx_disable");
if (sfp_node_read_int(path, value, 0) != 0) {
AIM_LOG_ERROR("Unable to read tx_disabled status from port(%d)\r\n", port);
rv = ONLP_STATUS_E_INTERNAL;
}
else {
rv = ONLP_STATUS_OK;
}
break;
}
default:
rv = ONLP_STATUS_E_UNSUPPORTED;
}
@@ -293,9 +330,9 @@ onlp_sfpi_control_get(int port, onlp_sfp_control_t control, int* value)
return rv;
}
int
onlp_sfpi_denit(void)
{
return ONLP_STATUS_OK;
}

View File

@@ -63,11 +63,11 @@ enum onlp_thermal_id
static char* last_path[] = /* must map with onlp_thermal_id */
{
"reserved",
"9-0048/temp1_input",
"8-0058/psu_temp1_input",
"8-0059/psu_temp1_input",
"9-0048*temp1_input",
"8-0058*psu_temp1_input",
"8-0059*psu_temp1_input",
};
/* Static values */
static onlp_thermal_info_t linfo[] = {
{ }, /* Not used */
@@ -107,9 +107,7 @@ onlp_thermali_init(void)
int
onlp_thermali_info_get(onlp_oid_t id, onlp_thermal_info_t* info)
{
int fd, len, nbytes = 10, temp_base=1, local_id;
char r_data[10] = {0};
char fullpath[50] = {0};
int local_id;
VALIDATE(id);
local_id = ONLP_OID_ID_GET(id);
@@ -119,12 +117,12 @@ onlp_thermali_info_get(onlp_oid_t id, onlp_thermal_info_t* info)
*info = linfo[local_id];
/* get fullpath */
sprintf(fullpath, "%s%s", prefix_path, last_path[local_id]);
OPEN_READ_FILE(fd, fullpath, r_data, nbytes, len);
info->mcelsius = atoi(r_data) / temp_base;
onlp_file_read_int(&info->mcelsius, "%s%s", prefix_path, last_path[local_id]);
//sprintf(fullpath, "%s%s", prefix_path, last_path[local_id]);
//AIM_LOG_MSG("%s", fullpath);
//OPEN_READ_FILE(fd, fullpath, r_data, nbytes, len);
//info->mcelsius = atoi(r_data) / temp_base;
DEBUG_PRINT("\n[Debug][%s][%d][save data: %d]\n", __FUNCTION__, __LINE__, info->mcelsius);
return ONLP_STATUS_OK;
}

View File

@@ -0,0 +1,344 @@
/*
* A hwmon driver for the Accton as4610 fan
*
* Copyright (C) 2016 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/platform_device.h>
#include "accton_i2c_cpld.h"
#define DRVNAME "as4610_fan"
static struct as4610_fan_data *as4610_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);
/* fan related data, the index should match sysfs_fan_attributes
*/
static const u8 fan_reg[] = {
0x2B, /* fan PWM(for all fan) */
0x2D, /* fan 1 speed(rpm) */
0x2C, /* fan 2 speed(rpm) */
0x11, /* fan1-2 operating status */
};
static struct as4610_fan_data *fan_data = NULL;
/* Each client has this additional data */
struct as4610_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 */
};
enum fan_id {
FAN1_ID,
FAN2_ID
};
enum sysfs_fan_attributes {
FAN_DUTY_CYCLE_PERCENTAGE, /* Only one CPLD register to control duty cycle for all fans */
FAN1_SPEED_RPM,
FAN2_SPEED_RPM,
FAN_FAULT,
FAN1_FAULT,
FAN2_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_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##_speed_rpm, S_IRUGO, fan_show_value, NULL, FAN##index##_SPEED_RPM)
#define DECLARE_FAN_SPEED_RPM_ATTR(index) &sensor_dev_attr_fan##index##_speed_rpm.dev_attr.attr
/* fan fault attributes in this platform */
DECLARE_FAN_FAULT_SENSOR_DEV_ATTR(1);
DECLARE_FAN_FAULT_SENSOR_DEV_ATTR(2);
/* fan speed(rpm) attributes in this platform */
DECLARE_FAN_SPEED_RPM_SENSOR_DEV_ATTR(1);
DECLARE_FAN_SPEED_RPM_SENSOR_DEV_ATTR(2);
/* 1 fan duty cycle attribute in this platform */
DECLARE_FAN_DUTY_CYCLE_SENSOR_DEV_ATTR();
static struct attribute *as4610_fan_attributes[] = {
/* fan related attributes */
DECLARE_FAN_FAULT_ATTR(1),
DECLARE_FAN_FAULT_ATTR(2),
DECLARE_FAN_SPEED_RPM_ATTR(1),
DECLARE_FAN_SPEED_RPM_ATTR(2),
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 as4610_fan_read_value(u8 reg)
{
return accton_i2c_cpld_read(AS4610_CPLD_SLAVE_ADDR, reg);
}
static int as4610_fan_write_value(u8 reg, u8 value)
{
return accton_i2c_cpld_write(AS4610_CPLD_SLAVE_ADDR, 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 * 125 + 5)/10);
}
static u8 duty_cycle_to_reg_val(u8 duty_cycle)
{
return ((u32)duty_cycle * 10 / 125);
}
static u32 reg_val_to_speed_rpm(u8 reg_val)
{
/* Count Frequency is 1.515KHz= 0.66ms
* Count Period = 400 cycle = 400*0.66ms = 264ms
* R.P.M value = read value x3.79*60/2
* 3.79 = 1000ms/264ms
* 60 = 1min =60s
* 2 = 1 rotation of fan has two pulses.
*/
return (u32)reg_val * 379 * 60 / 2 / 100;
}
static u8 is_fan_fault(struct as4610_fan_data *data, enum fan_id id)
{
u8 mask = (id == FAN1_ID) ? 0x20 : 0x10;
return !(data->reg_val[FAN_FAULT] & mask);
}
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;
as4610_fan_write_value(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 as4610_fan_data *data = as4610_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[attr->index]);
ret = sprintf(buf, "%u\n", duty_cycle);
break;
}
case FAN1_SPEED_RPM:
case FAN2_SPEED_RPM:
ret = sprintf(buf, "%u\n", reg_val_to_speed_rpm(data->reg_val[attr->index]));
break;
case FAN1_FAULT:
case FAN2_FAULT:
ret = sprintf(buf, "%d\n", is_fan_fault(data, attr->index - FAN1_FAULT));
break;
default:
break;
}
}
return ret;
}
static const struct attribute_group as4610_fan_group = {
.attrs = as4610_fan_attributes,
};
static struct as4610_fan_data *as4610_fan_update_device(struct device *dev)
{
mutex_lock(&fan_data->update_lock);
if (time_after(jiffies, fan_data->last_updated + HZ + HZ / 2) ||
!fan_data->valid) {
int i;
dev_dbg(fan_data->hwmon_dev, "Starting as4610_fan update\n");
fan_data->valid = 0;
/* Update fan data
*/
for (i = 0; i < ARRAY_SIZE(fan_data->reg_val); i++) {
int status = as4610_fan_read_value(fan_reg[i]);
if (status < 0) {
fan_data->valid = 0;
mutex_unlock(&fan_data->update_lock);
dev_dbg(fan_data->hwmon_dev, "reg %d, err %d\n", fan_reg[i], status);
return fan_data;
}
else {
fan_data->reg_val[i] = status;
}
}
fan_data->last_updated = jiffies;
fan_data->valid = 1;
}
mutex_unlock(&fan_data->update_lock);
return fan_data;
}
static int as4610_fan_probe(struct platform_device *pdev)
{
int status = -1;
/* Register sysfs hooks */
status = sysfs_create_group(&pdev->dev.kobj, &as4610_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, "accton_as4610_fan\n");
return 0;
exit_remove:
sysfs_remove_group(&pdev->dev.kobj, &as4610_fan_group);
exit:
return status;
}
static int as4610_fan_remove(struct platform_device *pdev)
{
hwmon_device_unregister(fan_data->hwmon_dev);
sysfs_remove_group(&pdev->dev.kobj, &as4610_fan_group);
return 0;
}
static const struct i2c_device_id as4610_fan_id[] = {
{ "as4610_fan", 0 },
{}
};
MODULE_DEVICE_TABLE(i2c, as4610_fan_id);
static struct platform_driver as4610_fan_driver = {
.probe = as4610_fan_probe,
.remove = as4610_fan_remove,
.driver = {
.name = DRVNAME,
.owner = THIS_MODULE,
},
};
static int __init as4610_fan_init(void)
{
int ret;
if (as4610_number_of_system_fan() == 0) {
return -ENODEV;
}
ret = platform_driver_register(&as4610_fan_driver);
if (ret < 0) {
goto exit;
}
fan_data = kzalloc(sizeof(struct as4610_fan_data), GFP_KERNEL);
if (!fan_data) {
ret = -ENOMEM;
platform_driver_unregister(&as4610_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(&as4610_fan_driver);
kfree(fan_data);
goto exit;
}
exit:
return ret;
}
static void __exit as4610_fan_exit(void)
{
if (!fan_data) {
return;
}
platform_device_unregister(fan_data->pdev);
platform_driver_unregister(&as4610_fan_driver);
kfree(fan_data);
}
late_initcall(as4610_fan_init);
module_exit(as4610_fan_exit);
MODULE_AUTHOR("Brandon Chuang <brandon_chuang@accton.com.tw>");
MODULE_DESCRIPTION("as4610_fan driver");
MODULE_LICENSE("GPL");

View File

@@ -0,0 +1,674 @@
/*
* A LED driver for the accton_as4610_led
*
* Copyright (C) 2016 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/bitops.h>
#include "accton_i2c_cpld.h"
//extern void led_classdev_unregister(struct led_classdev *led_cdev);
//extern int led_classdev_register(struct device *parent, struct led_classdev *led_cdev);
#define DRVNAME "as4610_led"
struct as4610_led_data {
struct platform_device *pdev;
struct mutex update_lock;
char valid; /* != 0 if registers are valid */
unsigned long last_updated; /* In jiffies */
int led_map;
u8 reg_val[5]; /* Register value, 0 = (0x1A) Blinking function
1 = (0x30) 7-seg 2
2 = (0x31) 7-seg 1
3 = (0x32) SYS/PRI/PSU1-2 LED
4 = (0x33) STK1-2/Fan/PoE/Alarm LED */
};
static struct as4610_led_data *ledctl = NULL;
/* LED related data
*/
#define LED_7SEG_REG_MASK 0x0F
#define LED_7SEG_POINT_REG_MASK 0x10
#define LED_NORMAL_MASK 0x03
#define LED_NORMAL_GREEN_VALUE 0x02
#define LED_NORMAL_AMBER_VALUE 0x01
#define LED_NORMAL_OFF_VALUE 0x00
#define LED_TYPE_SYS_REG_MASK 0xC0
#define LED_MODE_SYS_BLINK_MASK 0x80
#define LED_TYPE_PRI_REG_MASK 0x30
#define LED_MODE_PRI_BLINK_MASK 0x40
#define LED_TYPE_PSU1_REG_MASK 0x0C
#define LED_MODE_PSU1_BLINK_MASK 0x20
#define LED_TYPE_PSU2_REG_MASK 0x03
#define LED_MODE_PSU2_BLINK_MASK 0x10
#define LED_TYPE_STK1_REG_MASK 0xC0
#define LED_MODE_STK1_BLINK_MASK 0x08
#define LED_TYPE_STK2_REG_MASK 0x30
#define LED_MODE_STK2_BLINK_MASK 0x04
#define LED_TYPE_FAN_REG_MASK 0x0C
#define LED_MODE_FAN_BLINK_MASK 0x02
#define LED_TYPE_POE_ALARM_REG_MASK 0x03
#define LED_MODE_POE_ALARM_BLINK_MASK 0x01
static const u8 led_reg[] = {
0x1A, /* Blinking function */
0x30, /* 7-seg 1 */
0x31, /* 7-seg 2 */
0x32, /* SYS/PRI/PSU1-2 LED */
0x33, /* STK1-2/Fan/PoE/Alarm LED */
};
enum led_type {
LED_TYPE_SYS,
LED_TYPE_PRI,
LED_TYPE_PSU1,
LED_TYPE_PSU2,
LED_TYPE_STK1,
LED_TYPE_STK2,
LED_TYPE_7SEG_TENS,
LED_TYPE_7SEG_TENS_POINT,
LED_TYPE_7SEG_DIGITS,
LED_TYPE_7SEG_DIGITS_POINT,
LED_TYPE_FAN,
LED_TYPE_POE,
LED_TYPE_ALARM,
NUM_OF_LED
};
#define AS4610_COMMON_LED_MAP (BIT(LED_TYPE_SYS) | BIT(LED_TYPE_PRI) | BIT(LED_TYPE_PSU1) | \
BIT(LED_TYPE_PSU2)| BIT(LED_TYPE_STK1)| BIT(LED_TYPE_STK2))
#define AS4610_NPOE_LED_MAP (AS4610_COMMON_LED_MAP | BIT(LED_TYPE_7SEG_TENS) | \
BIT(LED_TYPE_7SEG_TENS_POINT) | BIT(LED_TYPE_7SEG_DIGITS) | \
BIT(LED_TYPE_7SEG_DIGITS_POINT))
#define AS4610_POE_LED_MAP (AS4610_NPOE_LED_MAP | BIT(LED_TYPE_FAN) | BIT(LED_TYPE_POE))
#define AS4610_54T_B_LED_MAP (AS4610_COMMON_LED_MAP | BIT(LED_TYPE_FAN) | BIT(LED_TYPE_ALARM))
static int as4610_ledmaps[] = {
[PID_AS4610_30T] = AS4610_NPOE_LED_MAP,
[PID_AS4610_30P] = AS4610_POE_LED_MAP,
[PID_AS4610_54T] = AS4610_NPOE_LED_MAP,
[PID_AS4610_54P] = AS4610_POE_LED_MAP,
[PID_AS4610_54T_B] = AS4610_54T_B_LED_MAP,
[PID_RESERVED] = 0,
};
enum led_light_mode {
LED_MODE_OFF = 0,
LED_MODE_GREEN,
LED_MODE_GREEN_BLINK,
LED_MODE_AMBER,
LED_MODE_AMBER_BLINK,
LED_MODE_RED,
LED_MODE_RED_BLINK,
LED_MODE_BLUE,
LED_MODE_BLUE_BLINK,
LED_MODE_AUTO,
LED_MODE_AUTO_BLINKING,
LED_MODE_UNKNOWN,
LED_MODE_SEVEN_SEGMENT_MAX = 9,
};
static int as4610_led_read_value(u8 reg)
{
return accton_i2c_cpld_read(0x30, reg);
}
static int as4610_led_write_value(u8 reg, u8 value)
{
return accton_i2c_cpld_write(0x30, reg, value);
}
static void as4610_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 as4610_led update\n");
/* Update LED data
*/
for (i = 0; i < ARRAY_SIZE(ledctl->reg_val); i++) {
int status = as4610_led_read_value(led_reg[i]);
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 enum led_brightness seven_segment_get(struct led_classdev *cdev, u8 reg_id)
{
as4610_led_update();
return (ledctl->reg_val[reg_id] & LED_7SEG_REG_MASK);
}
static void seven_segment_set(struct led_classdev *cdev, enum led_brightness mode, u8 reg_id)
{
if (mode > cdev->max_brightness) {
return;
}
ledctl->reg_val[reg_id] &= 0xF0;
ledctl->reg_val[reg_id] |= mode;
as4610_led_write_value(led_reg[reg_id], ledctl->reg_val[reg_id]);
}
static enum led_brightness seven_segment_digits_get(struct led_classdev *cdev)
{
return seven_segment_get(cdev, 1);
}
static void seven_segment_digits_set(struct led_classdev *cdev, enum led_brightness mode)
{
seven_segment_set(cdev, mode, 1);
}
static enum led_brightness seven_segment_tens_get(struct led_classdev *cdev)
{
return seven_segment_get(cdev, 2);
}
static void seven_segment_tens_set(struct led_classdev *cdev, enum led_brightness mode)
{
seven_segment_set(cdev, mode, 2);
}
static enum led_brightness seven_segment_point_get(struct led_classdev *cdev, u8 reg_id)
{
as4610_led_update();
return (ledctl->reg_val[reg_id] & LED_7SEG_POINT_REG_MASK) ? LED_MODE_GREEN : LED_MODE_OFF;
}
static void seven_segment_point_set(struct led_classdev *cdev,
enum led_brightness mode, u8 reg_id)
{
/* Validate brightness */
if ((int)mode < LED_MODE_OFF || mode > cdev->max_brightness) {
return;
}
if ((int)mode == (int)LED_MODE_OFF) {
ledctl->reg_val[reg_id] &= ~LED_7SEG_POINT_REG_MASK;
}
else { /* LED_MODE_GREEN */
ledctl->reg_val[reg_id] |= LED_7SEG_POINT_REG_MASK;
}
as4610_led_write_value(led_reg[reg_id], ledctl->reg_val[reg_id]);
}
static enum led_brightness seven_segment_tens_point_get(struct led_classdev *cdev)
{
return seven_segment_point_get(cdev, 2);
}
static void seven_segment_tens_point_set(struct led_classdev *cdev,
enum led_brightness mode)
{
seven_segment_point_set(cdev, mode, 2);
}
static enum led_brightness seven_segment_digits_point_get(struct led_classdev *cdev)
{
return seven_segment_point_get(cdev, 1);
}
static void seven_segment_digits_point_set(struct led_classdev *cdev,
enum led_brightness mode)
{
seven_segment_point_set(cdev, mode, 1);
}
static u8 led_is_blinking_mode(enum led_brightness mode)
{
return ((int)mode == (int)LED_MODE_GREEN_BLINK ||
(int)mode == (int)LED_MODE_AMBER_BLINK ||
(int)mode == (int)LED_MODE_AUTO_BLINKING);
}
static enum led_brightness as4610_led_auto_get(u8 blink_mask)
{
as4610_led_update();
return (ledctl->reg_val[0] & blink_mask) ? LED_MODE_AUTO_BLINKING : LED_MODE_AUTO;
}
static void as4610_led_auto_set(struct led_classdev *cdev,
enum led_brightness mode, u8 blink_mask)
{
/* Validate brightness */
if ((int)mode < (int)LED_MODE_AUTO || mode > cdev->max_brightness) {
return;
}
/* Set blinking */
if (led_is_blinking_mode(mode)) {
ledctl->reg_val[0] |= blink_mask;
}
else {
ledctl->reg_val[0] &= ~blink_mask;
}
as4610_led_write_value(led_reg[0], ledctl->reg_val[0]);
}
static enum led_brightness as4610_led_psu1_get(struct led_classdev *cdev)
{
return as4610_led_auto_get(LED_MODE_PSU1_BLINK_MASK);
}
static void as4610_led_psu1_set(struct led_classdev *cdev,
enum led_brightness mode)
{
as4610_led_auto_set(cdev, mode, LED_MODE_PSU1_BLINK_MASK);
}
static enum led_brightness as4610_led_psu2_get(struct led_classdev *cdev)
{
return as4610_led_auto_get(LED_MODE_PSU2_BLINK_MASK);
}
static void as4610_led_psu2_set(struct led_classdev *led_cdev,
enum led_brightness mode)
{
as4610_led_auto_set(led_cdev, mode, LED_MODE_PSU2_BLINK_MASK);
}
static enum led_brightness as4610_led_fan_get(struct led_classdev *cdev)
{
return as4610_led_auto_get(LED_MODE_FAN_BLINK_MASK);
}
static void as4610_led_fan_set(struct led_classdev *cdev,
enum led_brightness mode)
{
as4610_led_auto_set(cdev, mode, LED_MODE_FAN_BLINK_MASK);
}
static u8 led_normal_light_mode_to_reg_val(enum led_brightness mode)
{
if (led_is_blinking_mode(mode)) {
mode -= 1; /* convert blinking mode to non-blinking mode */
}
if ((int)mode == (int)LED_MODE_GREEN) {
return LED_NORMAL_GREEN_VALUE;
}
else if ((int)mode == (int)LED_MODE_AMBER) {
return LED_NORMAL_AMBER_VALUE;
}
return LED_NORMAL_OFF_VALUE;
}
static enum led_brightness led_normal_reg_val_to_light_mode(u8 reg_val)
{
reg_val &= LED_NORMAL_MASK;
if (reg_val & LED_NORMAL_GREEN_VALUE) {
return LED_MODE_GREEN;
}
else if (reg_val & LED_NORMAL_AMBER_VALUE) {
return LED_MODE_AMBER;
}
return LED_MODE_OFF;
}
static void as4610_led_normal_set(struct led_classdev *cdev,
enum led_brightness mode, u8 blink_mask, u8 reg_id, u8 reg_mask, u8 shift)
{
/* Validate brightness */
if (mode > cdev->max_brightness) {
return;
}
/* Set blinking */
if (led_is_blinking_mode(mode)) {
ledctl->reg_val[0] |= blink_mask;
}
else {
ledctl->reg_val[0] &= ~blink_mask;
}
as4610_led_write_value(led_reg[0], ledctl->reg_val[0]);
/* Set color */
ledctl->reg_val[reg_id] &= ~reg_mask;
ledctl->reg_val[reg_id] |= (led_normal_light_mode_to_reg_val(mode) << shift);
as4610_led_write_value(led_reg[reg_id], ledctl->reg_val[reg_id]);
}
static enum led_brightness as4610_led_normal_get(u8 reg_id, u8 blink_mask, u8 shift)
{
u8 blinking = 0;
enum led_brightness mode;
as4610_led_update();
mode = led_normal_reg_val_to_light_mode(ledctl->reg_val[reg_id] >> shift);
if ((int)mode == (int)LED_MODE_OFF) {
return mode;
}
/* Checking blinking */
if (ledctl->reg_val[0] & blink_mask) {
blinking = 1;
}
return blinking ? (mode+1) : mode;
}
static void as4610_led_sys_set(struct led_classdev *cdev,
enum led_brightness mode)
{
as4610_led_normal_set(cdev, mode, LED_MODE_SYS_BLINK_MASK,
3, LED_TYPE_SYS_REG_MASK, 6);
}
static enum led_brightness as4610_led_sys_get(struct led_classdev *cdev)
{
return as4610_led_normal_get(3, LED_MODE_SYS_BLINK_MASK, 6);
}
static void as4610_led_pri_set(struct led_classdev *cdev,
enum led_brightness mode)
{
as4610_led_normal_set(cdev, mode, LED_MODE_PRI_BLINK_MASK,
3, LED_TYPE_PRI_REG_MASK, 4);
}
static enum led_brightness as4610_led_pri_get(struct led_classdev *cdev)
{
return as4610_led_normal_get(3, LED_MODE_PRI_BLINK_MASK, 4);
}
static void as4610_led_poe_alarm_set(struct led_classdev *cdev,
enum led_brightness mode)
{
as4610_led_normal_set(cdev, mode, LED_MODE_POE_ALARM_BLINK_MASK,
4, LED_TYPE_POE_ALARM_REG_MASK, 0);
}
static enum led_brightness as4610_led_poe_alarm_get(struct led_classdev *cdev)
{
return as4610_led_normal_get(4, LED_MODE_POE_ALARM_BLINK_MASK, 0);
}
static void as4610_led_stk1_set(struct led_classdev *cdev,
enum led_brightness mode)
{
as4610_led_normal_set(cdev, mode, LED_MODE_STK1_BLINK_MASK,
4, LED_TYPE_STK1_REG_MASK, 6);
}
static enum led_brightness as4610_led_stk1_get(struct led_classdev *cdev)
{
return as4610_led_normal_get(4, LED_MODE_STK1_BLINK_MASK, 6);
}
static void as4610_led_stk2_set(struct led_classdev *cdev,
enum led_brightness mode)
{
as4610_led_normal_set(cdev, mode, LED_MODE_STK2_BLINK_MASK,
4, LED_TYPE_STK2_REG_MASK, 4);
}
static enum led_brightness as4610_led_stk2_get(struct led_classdev *cdev)
{
return as4610_led_normal_get(4, LED_MODE_STK2_BLINK_MASK, 4);
}
static struct led_classdev as4610_leds[] = {
[LED_TYPE_SYS] = {
.name = "as4610::sys",
.default_trigger = "unused",
.brightness_set = as4610_led_sys_set,
.brightness_get = as4610_led_sys_get,
.max_brightness = LED_MODE_AMBER_BLINK,
},
[LED_TYPE_PRI] = {
.name = "as4610::pri",
.default_trigger = "unused",
.brightness_set = as4610_led_pri_set,
.brightness_get = as4610_led_pri_get,
.max_brightness = LED_MODE_AMBER_BLINK,
},
[LED_TYPE_PSU1] = {
.name = "as4610::psu1",
.default_trigger = "unused",
.brightness_set = as4610_led_psu1_set,
.brightness_get = as4610_led_psu1_get,
.max_brightness = LED_MODE_AUTO_BLINKING,
},
[LED_TYPE_PSU2] = {
.name = "as4610::psu2",
.default_trigger = "unused",
.brightness_set = as4610_led_psu2_set,
.brightness_get = as4610_led_psu2_get,
.max_brightness = LED_MODE_AUTO_BLINKING,
},
[LED_TYPE_STK1] = {
.name = "as4610::stk1",
.default_trigger = "unused",
.brightness_set = as4610_led_stk1_set,
.brightness_get = as4610_led_stk1_get,
.max_brightness = LED_MODE_AMBER_BLINK,
},
[LED_TYPE_STK2] = {
.name = "as4610::stk2",
.default_trigger = "unused",
.brightness_set = as4610_led_stk2_set,
.brightness_get = as4610_led_stk2_get,
.max_brightness = LED_MODE_AMBER_BLINK,
},
[LED_TYPE_7SEG_TENS] = {
.name = "as4610::7seg_tens",
.default_trigger = "unused",
.brightness_set = seven_segment_tens_set,
.brightness_get = seven_segment_tens_get,
.max_brightness = LED_MODE_SEVEN_SEGMENT_MAX,
},
[LED_TYPE_7SEG_TENS_POINT] = {
.name = "as4610::7seg_tens_point",
.default_trigger = "unused",
.brightness_set = seven_segment_tens_point_set,
.brightness_get = seven_segment_tens_point_get,
.max_brightness = LED_MODE_GREEN,
},
[LED_TYPE_7SEG_DIGITS] = {
.name = "as4610::7seg_digits",
.default_trigger = "unused",
.brightness_set = seven_segment_digits_set,
.brightness_get = seven_segment_digits_get,
.max_brightness = LED_MODE_SEVEN_SEGMENT_MAX,
},
[LED_TYPE_7SEG_DIGITS_POINT] = {
.name = "as4610::7seg_digits_point",
.default_trigger = "unused",
.brightness_set = seven_segment_digits_point_set,
.brightness_get = seven_segment_digits_point_get,
.max_brightness = LED_MODE_GREEN,
},
[LED_TYPE_FAN] = {
.name = "as4610::fan",
.default_trigger = "unused",
.brightness_set = as4610_led_fan_set,
.brightness_get = as4610_led_fan_get,
.max_brightness = LED_MODE_AUTO_BLINKING,
},
[LED_TYPE_POE] = {
.name = "as4610::poe",
.default_trigger = "unused",
.brightness_set = as4610_led_poe_alarm_set,
.brightness_get = as4610_led_poe_alarm_get,
.max_brightness = LED_MODE_AMBER_BLINK,
},
[LED_TYPE_ALARM] = {
.name = "as4610::alarm",
.default_trigger = "unused",
.brightness_set = as4610_led_poe_alarm_set,
.brightness_get = as4610_led_poe_alarm_get,
.max_brightness = LED_MODE_AMBER_BLINK,
},
};
static int as4610_led_probe(struct platform_device *pdev)
{
int ret = 0, i;
for (i = 0; i < NUM_OF_LED; i++) {
if (!(ledctl->led_map & BIT(i))) {
continue;
}
ret = led_classdev_register(&pdev->dev, &as4610_leds[i]);
if (ret < 0) {
goto error;
}
}
return 0;
error:
for (i = i-1; i >= 0; i--) {
/* only unregister the LEDs that were successfully registered */
if (!(ledctl->led_map & BIT(i))) {
continue;
}
led_classdev_unregister(&as4610_leds[i]);
}
return ret;
}
static int as4610_led_remove(struct platform_device *pdev)
{
int i;
for (i = 0; i < NUM_OF_LED; i++) {
if (!(ledctl->led_map & BIT(i))) {
continue;
}
led_classdev_unregister(&as4610_leds[i]);
}
return 0;
}
static struct platform_driver as4610_led_driver = {
.probe = as4610_led_probe,
.remove = as4610_led_remove,
.driver = {
.name = DRVNAME,
.owner = THIS_MODULE,
},
};
static int __init as4610_led_init(void)
{
int ret, pid;
if (as4610_product_id() == PID_UNKNOWN) {
return -ENODEV;
}
ret = platform_driver_register(&as4610_led_driver);
if (ret < 0) {
goto exit;
}
ledctl = kzalloc(sizeof(struct as4610_led_data), GFP_KERNEL);
if (!ledctl) {
ret = -ENOMEM;
platform_driver_unregister(&as4610_led_driver);
goto exit;
}
pid = as4610_product_id();
if (pid == PID_UNKNOWN) {
return -ENODEV;
}
ledctl->led_map = as4610_ledmaps[pid];
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(&as4610_led_driver);
kfree(ledctl);
goto exit;
}
exit:
return ret;
}
static void __exit as4610_led_exit(void)
{
if (!ledctl) {
return;
}
platform_device_unregister(ledctl->pdev);
platform_driver_unregister(&as4610_led_driver);
kfree(ledctl);
}
late_initcall(as4610_led_init);
module_exit(as4610_led_exit);
MODULE_AUTHOR("Brandon Chuang <brandon_chuang@accton.com.tw>");
MODULE_DESCRIPTION("as4610_led driver");
MODULE_LICENSE("GPL");

View File

@@ -0,0 +1,286 @@
/*
* An hwmon driver for accton as4610 Power Module
*
* Copyright (C) 2016 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 as4610_psu_read_data(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 as4610_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 as4610_psu_data *as4610_psu_update_device(struct device *dev);
enum as4610_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 *as4610_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 as4610_psu_data *data = as4610_psu_update_device(dev);
u8 status = 0;
if (attr->index == PSU_PRESENT) {
status = (data->status >> (data->index*2) & 0x1);
}
else { /* PSU_POWER_GOOD */
status = (data->status >> (data->index*2 + 1) & 0x1);
}
return sprintf(buf, "%d\n", status);
}
static ssize_t show_model_name(struct device *dev, struct device_attribute *da,
char *buf)
{
struct as4610_psu_data *data = as4610_psu_update_device(dev);
return sprintf(buf, "%s\n", data->model_name);
}
static const struct attribute_group as4610_psu_group = {
.attrs = as4610_psu_attributes,
};
static int as4610_psu_probe(struct i2c_client *client,
const struct i2c_device_id *dev_id)
{
struct as4610_psu_data *data;
int status;
if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) {
status = -EIO;
goto exit;
}
data = kzalloc(sizeof(struct as4610_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, &as4610_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, &as4610_psu_group);
exit_free:
kfree(data);
exit:
return status;
}
static int as4610_psu_remove(struct i2c_client *client)
{
struct as4610_psu_data *data = i2c_get_clientdata(client);
hwmon_device_unregister(data->hwmon_dev);
sysfs_remove_group(&client->dev.kobj, &as4610_psu_group);
kfree(data);
return 0;
}
enum psu_index
{
as4610_psu1,
as4610_psu2
};
static const struct i2c_device_id as4610_psu_id[] = {
{ "as4610_psu1", as4610_psu1 },
{ "as4610_psu2", as4610_psu2 },
{}
};
MODULE_DEVICE_TABLE(i2c, as4610_psu_id);
static struct i2c_driver as4610_psu_driver = {
.class = I2C_CLASS_HWMON,
.driver = {
.name = "as4610_psu",
},
.probe = as4610_psu_probe,
.remove = as4610_psu_remove,
.id_table = as4610_psu_id,
.address_list = normal_i2c,
};
static int as4610_psu_read_data(struct i2c_client *client, u8 command, u8 *data,
int count)
{
int status = 0;
while (count) {
status = i2c_smbus_read_byte_data(client, command);
if (unlikely(status < 0)) {
break;
}
*data = (u8)status;
data += 1;
command += 1;
count -= 1;
}
return status;
}
static struct as4610_psu_data *as4610_psu_update_device(struct device *dev)
{
struct i2c_client *client = to_i2c_client(dev);
struct as4610_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 present = 0;
data->valid = 0;
data->status = 0;
dev_dbg(&client->dev, "Starting as4610 update\n");
/* Read psu status */
status = accton_i2c_cpld_read(0x30, 0x11);
if (status < 0) {
dev_dbg(&client->dev, "cpld reg 0x30 err %d\n", status);
goto exit;
}
else {
data->status = status;
}
/* Read model name */
memset(data->model_name, 0, sizeof(data->model_name));
present = (data->status >> (data->index*2) & 0x1);
if (present) {
int len = ARRAY_SIZE(data->model_name)-1;
status = as4610_psu_read_data(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);
goto exit;
}
else {
data->model_name[ARRAY_SIZE(data->model_name)-1] = '\0';
}
}
data->last_updated = jiffies;
data->valid = 1;
}
exit:
mutex_unlock(&data->update_lock);
return data;
}
static int __init as4610_psu_init(void)
{
return i2c_add_driver(&as4610_psu_driver);
}
static void __exit as4610_psu_exit(void)
{
i2c_del_driver(&as4610_psu_driver);
}
module_init(as4610_psu_init);
module_exit(as4610_psu_exit);
MODULE_AUTHOR("Brandon Chuang <brandon_chuang@accton.com.tw>");
MODULE_DESCRIPTION("as4610_psu driver");
MODULE_LICENSE("GPL");

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,284 @@
/*
* A hwmon driver for the accton_i2c_cpld
*
* Copyright (C) 2013 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 "accton_i2c_cpld.h"
static LIST_HEAD(cpld_client_list);
static struct mutex list_lock;
enum cpld_device_id {
as4610_30_cpld,
as4610_54_cpld
};
struct cpld_data {
enum cpld_device_id id;
};
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 u8 cpld_product_id_offset(enum cpld_device_id id)
{
switch (id) {
case as4610_30_cpld:
case as4610_54_cpld:
return 0x1;
}
return 0;
}
static int cpld_has_product_id(const struct i2c_device_id *dev_id)
{
return (dev_id->driver_data == as4610_30_cpld) ||
(dev_id->driver_data == as4610_54_cpld);
}
static ssize_t show_cpld_product_id(struct device *dev, struct device_attribute *attr, char *buf)
{
int val = 0;
struct i2c_client *client = to_i2c_client(dev);
struct cpld_data *data = i2c_get_clientdata(client);
val = i2c_smbus_read_byte_data(client, cpld_product_id_offset(data->id));
if (val < 0) {
dev_dbg(&client->dev, "cpld(0x%x) reg(0x%x) err %d\n", client->addr, cpld_product_id_offset(data->id), val);
}
return sprintf(buf, "%d\n", (val & 0xF));
}
static u8 cpld_version_offset(enum cpld_device_id id)
{
switch (id) {
case as4610_30_cpld:
case as4610_54_cpld:
return 0xB;
}
return 0;
}
static ssize_t show_cpld_version(struct device *dev, struct device_attribute *attr, char *buf)
{
int val = 0;
struct i2c_client *client = to_i2c_client(dev);
struct cpld_data *data = i2c_get_clientdata(client);
val = i2c_smbus_read_byte_data(client, cpld_version_offset(data->id));
if (val < 0) {
dev_dbg(&client->dev, "cpld(0x%x) reg(0xB) err %d\n", client->addr, val);
}
return sprintf(buf, "%d\n", val);
}
static void accton_i2c_cpld_add_client(struct i2c_client *client, enum cpld_device_id id)
{
struct cpld_client_node *node = kzalloc(sizeof(struct cpld_client_node), GFP_KERNEL);
struct cpld_data *data = kzalloc(sizeof(struct cpld_data), GFP_KERNEL);
if (!node) {
dev_dbg(&client->dev, "Can't allocate cpld_client_node (0x%x)\n", client->addr);
return;
}
if (!data) {
dev_dbg(&client->dev, "Can't allocate cpld_client_data (0x%x)\n", client->addr);
return;
}
data->id = id;
i2c_set_clientdata(client, data);
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 struct device_attribute ver = __ATTR(version, 0600, show_cpld_version, NULL);
static struct device_attribute pid = __ATTR(product_id, 0600, show_cpld_product_id, NULL);
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;
}
status = sysfs_create_file(&client->dev.kobj, &ver.attr);
if (status) {
goto exit;
}
if (cpld_has_product_id(dev_id)) {
status = sysfs_create_file(&client->dev.kobj, &pid.attr);
if (status) {
goto exit;
}
}
dev_info(&client->dev, "chip found\n");
accton_i2c_cpld_add_client(client, (enum cpld_device_id)dev_id->driver_data);
return 0;
exit:
return status;
}
static int accton_i2c_cpld_remove(struct i2c_client *client)
{
sysfs_remove_file(&client->dev.kobj, &ver.attr);
accton_i2c_cpld_remove_client(client);
return 0;
}
static const struct i2c_device_id accton_i2c_cpld_id[] = {
{ "as4610_30_cpld", as4610_30_cpld },
{ "as4610_54_cpld", as4610_54_cpld },
{ /* LIST END */}
};
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);
}
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);

View File

@@ -0,0 +1,76 @@
/*
* A hwmon driver for the accton_i2c_cpld
*
* Copyright (C) 2016 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.
*/
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);
#define AS4610_CPLD_SLAVE_ADDR 0x30
#define AS4610_CPLD_PID_OFFSET 0x01 /* Product ID offset */
enum as4610_product_id_e {
PID_AS4610_30T,
PID_AS4610_30P,
PID_AS4610_54T,
PID_AS4610_54P,
PID_RESERVED,
PID_AS4610_54T_B,
PID_UNKNOWN
};
static inline int as4610_product_id(void)
{
int pid = accton_i2c_cpld_read(AS4610_CPLD_SLAVE_ADDR, AS4610_CPLD_PID_OFFSET);
pid &= 0xF;
if (pid < PID_AS4610_30T || pid > PID_AS4610_54T_B || pid == PID_RESERVED) {
return PID_UNKNOWN;
}
return pid;
}
static inline int as4610_is_poe_system(void)
{
int pid = as4610_product_id();
return (pid == PID_AS4610_30P || pid == PID_AS4610_54P);
}
static inline int as4610_number_of_system_fan(void)
{
int nFan = 0;
int pid = as4610_product_id();
switch (pid) {
case PID_AS4610_30P:
case PID_AS4610_54P:
nFan = 1;
break;
case PID_AS4610_54T_B:
nFan = 2;
break;
default:
nFan = 0;
break;
}
return nFan;
}

View File

@@ -1 +1 @@
!include $ONL_TEMPLATES/platform-config-platform.yml ARCH=armel VENDOR=delta BASENAME=arm-delta-ag6248c-poe REVISION=r0
!include $ONL_TEMPLATES/platform-config-platform.yml ARCH=armel VENDOR=delta BASENAME=arm-delta-ag6248c-poe REVISION=r0 DISTS=jessie

View File

@@ -1 +1 @@
!include $ONL_TEMPLATES/platform-config-platform.yml ARCH=armel VENDOR=delta BASENAME=arm-delta-ag6248c REVISION=r0
!include $ONL_TEMPLATES/platform-config-platform.yml ARCH=armel VENDOR=delta BASENAME=arm-delta-ag6248c REVISION=r0 DISTS=jessie

View File

@@ -1 +1 @@
!include $ONL_TEMPLATES/platform-config-platform.yml ARCH=armel VENDOR=qemu BASENAME=arm-qemu-armv7a REVISION=r0
!include $ONL_TEMPLATES/platform-config-platform.yml ARCH=armel VENDOR=qemu BASENAME=arm-qemu-armv7a REVISION=r0 DISTS=jessie

View File

@@ -66,7 +66,7 @@ class Image(object):
self.wl(""" description = "%s";""" % self.description)
self.wl(""" type = "%s";""" % self.type)
self.wl(""" data = /incbin/("%s");""" % self.data)
self.wl(""" arch = "%s";""" % ("arm" if ops.arch == 'armel' else ops.arch))
self.wl(""" arch = "%s";""" % ("arm" if ops.arch in [ 'armel', 'armhf' ] else ops.arch))
self.wl(""" compression = "%s";""" % self.compression)
if self.os:
self.wl(""" os = %s;""" % self.os)
@@ -95,7 +95,7 @@ class KernelImage(Image):
if arch == 'powerpc':
self.load = "<0x0>"
self.entry = "<0x0>"
elif arch == 'armel':
elif arch in [ 'armel', 'armhf' ]:
self.load = "<0x61008000>"
self.entry = "<0x61008000>"
elif arch == 'arm64':
@@ -117,7 +117,7 @@ class InitrdImage(Image):
if arch == 'powerpc':
self.load = "<0x1000000>"
self.entry ="<0x1000000>"
elif arch == 'armel':
elif arch in [ 'armel', 'armhf' ]:
self.load = "<0x0000000>"
self.entry ="<0x0000000>"
elif arch == 'arm64':
@@ -306,7 +306,7 @@ if __name__ == '__main__':
ap.add_argument("--desc", nargs=1, help="Flat Image Tree description", default="ONL Flat Image Tree.")
ap.add_argument("--itb", metavar='itb-file', help="Compile result to an image tree blob file.")
ap.add_argument("--its", metavar='its-file', help="Write result to an image tree source file.")
ap.add_argument("--arch", choices=['powerpc', 'armel', 'arm64'], required=True)
ap.add_argument("--arch", choices=['powerpc', 'armel', 'armhf', 'arm64'], required=True)
ops=ap.parse_args()
fit = FlatImageTree(ops.desc)

View File

@@ -175,7 +175,7 @@ if __name__ == '__main__':
ap = argparse.ArgumentParser(NAME)
ap.add_argument("--arch", help="Installer Architecture.", required=True,
choices = ['amd64', 'powerpc', 'armel', 'arm64'])
choices = ['amd64', 'powerpc', 'armel', 'armhf', 'arm64'])
ap.add_argument("--initrd", nargs=2, help="The system initrd.")
ap.add_argument("--fit", nargs=2, help="The system FIT image.")
ap.add_argument("--boot-config", help="The boot-config source.")

View File

@@ -136,8 +136,10 @@ class OnlPackage(object):
'BUILD_DIR' : 'BUILD/%s' % g_dist_codename,
# Default Templates Location
'ONL_TEMPLATES' : "%s/packages/base/any/templates" % os.getenv("ONL")
'ONL_TEMPLATES' : "%s/packages/base/any/templates" % os.getenv("ONL"),
# Default Distribution
'DISTS' : g_dist_codename,
}
############################################################
@@ -503,6 +505,13 @@ class OnlPackageGroup(object):
return False
return True
def distcheck(self):
for p in self.packages:
if p.pkg.get("dists", None):
if g_dist_codename not in p.pkg['dists'].split(','):
return False
return True
def prerequisite_packages(self):
rv = []
for e in list(onlu.sflatten(self._pkgs.get('prerequisites', {}).get('packages', []))):
@@ -863,7 +872,8 @@ class OnlPackageManager(object):
pg.filtered = True
if not pg.archcheck(arches):
pg.filtered = True
if not pg.distcheck():
pg.filtered = True
def load(self, basedir, usecache=True, rebuildcache=False):
pkgspec = [ 'PKG.yml', 'pkg.yml' ]
@@ -1089,6 +1099,8 @@ class OnlPackageManager(object):
def list_platforms(self, arch):
platforms = []
for pg in self.package_groups:
if not pg.distcheck():
continue
for p in pg.packages:
(name, pkgArch) = OnlPackage.idparse(p.id())
m = re.match(r'onl-platform-config-(?P<platform>.*)', name)
@@ -1103,7 +1115,7 @@ def defaultPm():
packagedirs = os.environ['ONLPM_OPTION_PACKAGEDIRS'].split(':')
repoPackageDir = os.environ.get('ONLPM_OPTION_REPO_PACKAGE_DIR', 'packages')
subdir = os.getcwd()
arches = ['amd64', 'powerpc', 'armel', 'arm64', 'all',]
arches = ['amd64', 'powerpc', 'armel', 'armhf', 'arm64', 'all',]
if envJson:
for j in envJson.split(':'):
@@ -1139,7 +1151,7 @@ if __name__ == '__main__':
ap.add_argument("--csv", action='store_true')
ap.add_argument("--show-group", action='store_true')
ap.add_argument("--arch")
ap.add_argument("--arches", nargs='+', default=['amd64', 'powerpc', 'armel', 'arm64', 'all']),
ap.add_argument("--arches", nargs='+', default=['amd64', 'powerpc', 'armel', 'armhf', 'arm64', 'all']),
ap.add_argument("--pmake", action='store_true')
ap.add_argument("--prereq-packages", action='store_true')
ap.add_argument("--lookup", metavar='PACKAGE')

View File

@@ -334,7 +334,7 @@ class OnlRfsBuilder(object):
if not os.path.exists(self.QEMU_PPC):
raise OnlRfsError("%s is missing." % self.QEMU_PPC)
if self.arch == 'armel':
if self.arch in [ 'armel', 'armhf' ]:
if not os.path.exists(self.QEMU_ARM):
raise OnlRfsError("%s is missing." % self.QEMU_ARM)
@@ -378,7 +378,7 @@ class OnlRfsBuilder(object):
def dpkg_configure(self, dir_):
if self.arch == 'powerpc':
onlu.execute('sudo cp %s %s' % (self.QEMU_PPC, os.path.join(dir_, 'usr/bin')))
if self.arch == 'armel':
if self.arch in [ 'armel', 'armhf' ]:
onlu.execute('sudo cp %s %s' % (self.QEMU_ARM, os.path.join(dir_, 'usr/bin')))
if self.arch == 'arm64':
onlu.execute('sudo cp %s %s' % (self.QEMU_ARM64, os.path.join(dir_, 'usr/bin')))

View File

@@ -38,6 +38,9 @@ function build_source
{
BUILD_DIR=`mktemp -d`
cp $2 $BUILD_DIR
if [ -n "$4" ]; then
cp $4 $BUILD_DIR
fi
src=$(basename $2)
obj=${src%.c}.o
echo "obj-m := $obj" >> $BUILD_DIR/Kbuild
@@ -49,7 +52,7 @@ for kernel in $1; do
if [ -d $module ]; then
build_directory $kernel $module $3
else
build_source $kernel $module $3
build_source $kernel $module $3 $4
fi
done
done