forked from lazyoop/ipq6000
-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
ipq60xx: add kmod-gl-sdk4-fan support for GL.iNet GL-AXT1800
- Loading branch information
1 parent
c127280
commit f5028f2
Showing
9 changed files
with
563 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
# | ||
# | ||
# Copyright (C) 2019 OpenWrt.org | ||
# | ||
# This is free software, licensed under the GNU General Public License v2. | ||
# See /LICENSE for more information. | ||
# | ||
include $(TOPDIR)/rules.mk | ||
include $(INCLUDE_DIR)/kernel.mk | ||
|
||
PKG_NAME:=gl-sdk4-fan | ||
PKG_VERSION:=axt1800 | ||
PKG_RELEASE:=1 | ||
|
||
include $(INCLUDE_DIR)/package.mk | ||
include $(INCLUDE_DIR)/cmake.mk | ||
|
||
define KernelPackage/$(PKG_NAME) | ||
CATEGORY:=gl-sdk4 | ||
SUBMENU:=Kernel modules | ||
DEPENDS:= +kmod-hwmon-pwmfan +libc | ||
TITLE:= glinet SDK4 fan module | ||
FILES:=$(PKG_BUILD_DIR)/driver/gl_fan_driver.ko | ||
AUTOLOAD:=$(call AutoLoad,81,gl_fan_driver,1) | ||
endef | ||
|
||
define Build/Prepare | ||
mkdir -p $(PKG_BUILD_DIR) | ||
$(CP) ./src/* $(PKG_BUILD_DIR) | ||
endef | ||
|
||
KERNEL_MAKE_FLAGS?= \ | ||
ARCH="$(LINUX_KARCH)" \ | ||
CROSS_COMPILE="$(TARGET_CROSS)" | ||
|
||
MAKE_OPTS:= \ | ||
$(KERNEL_MAKE_FLAGS) \ | ||
M="$(PKG_BUILD_DIR)/driver" | ||
|
||
define Build/Compile | ||
$(call Build/Compile/Default) | ||
$(MAKE) -C "$(LINUX_DIR)" \ | ||
$(MAKE_OPTS) \ | ||
modules | ||
endef | ||
|
||
define KernelPackage/$(PKG_NAME)/install | ||
$(INSTALL_DIR) $(1)/usr/bin/ | ||
$(INSTALL_BIN) $(PKG_BUILD_DIR)/gl_fan $(1)/usr/bin/ | ||
|
||
$(INSTALL_DIR) $(1)/etc/config | ||
$(INSTALL_DIR) $(1)/etc/init.d | ||
$(INSTALL_BIN) ./files/etc/config/glfan $(1)/etc/config/glfan | ||
$(INSTALL_BIN) ./files/etc/init.d/gl_fan $(1)/etc/init.d/gl_fan | ||
|
||
$(INSTALL_DIR) $(1)/usr/lib/oui-httpd/rpc | ||
$(CP) ./files/fan.lua $(1)/usr/lib/oui-httpd/rpc/fan | ||
endef | ||
|
||
$(eval $(call KernelPackage,$(PKG_NAME))) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
|
||
config globals | ||
option enabled '1' | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
#!/bin/sh /etc/rc.common | ||
|
||
START=99 | ||
|
||
USE_PROCD=1 | ||
|
||
PROG=/usr/bin/gl_fan | ||
|
||
get_fan_config() { | ||
config_get enabled $1 enabled | ||
config_get temperature $1 temperature | ||
config_get proportion $1 proportion | ||
config_get integration $1 integration | ||
config_get differential $1 differential | ||
config_get debug $1 debug | ||
} | ||
|
||
start_service() { | ||
config_load glfan | ||
config_foreach get_fan_config globals | ||
|
||
[ "$enabled" != "1" ] && exit | ||
[ -n "$temperature" ] && PROG="$PROG -t $temperature" | ||
[ -n "$proportion" ] && PROG="$PROG -p $proportion" | ||
[ -n "$integration" ] && PROG="$PROG -i $integration" | ||
[ -n "$differential" ] && PROG="$PROG -d $differential" | ||
[ "$debug" = "1" ] && PROG="$PROG -v" | ||
|
||
procd_open_instance | ||
procd_set_param respawn | ||
procd_set_param stderr 1 | ||
procd_set_param command $PROG | ||
procd_close_instance | ||
} | ||
|
||
stop_service() { | ||
kill -9 $(pgrep -f '/usr/bin/gl_fan') 2>/dev/null | ||
echo 0 > /sys/class/thermal/cooling_device0/cur_state | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
--[[ | ||
@object-name: fan | ||
@object-desc: This is the API related to fan Internet access. | ||
--]] | ||
|
||
local utils = require "oui.utils" | ||
|
||
local M = {} | ||
|
||
local function stop_test_fan() | ||
utils.writefile("/sys/class/thermal/cooling_device0/cur_state", "0") | ||
ngx.pipe.spawn({"/etc/init.d/gl_fan", "restart"}):wait() | ||
end | ||
|
||
--[[ | ||
@method-name: set_status | ||
@method-desc: Set led status. | ||
@in bool test_fan 测试风扇起转. | ||
@in number test_time 测试风扇起转时间s, 缺省为10s. | ||
@in-example: {\"jsonrpc\":\"2.0\",\"method\":\"call\",\"params\":[\"\",\"fan\",\"set_status\",{\"test_fan\":true,\"test_time\":5}],\"id\":1} | ||
@out-example: {\"jsonrpc\": \"2.0\", \"id\": 1, \"result\": {}} | ||
--]] | ||
|
||
M.set_status = function(params) | ||
|
||
local test_fan = params.test_fan | ||
if test_fan == true then | ||
local test_time = params.test_time or 10 | ||
ngx.pipe.spawn({"/etc/init.d/gl_fan", "stop"}):wait() | ||
utils.writefile("/sys/class/thermal/cooling_device0/cur_state", "255") | ||
ngx.timer.at(test_time, stop_test_fan) | ||
end | ||
|
||
end | ||
|
||
--[[ | ||
@method-name: get_status | ||
@method-desc: Get status of fan. | ||
@in bool get_speed 是否获取风扇转速,true:是 false 否. | ||
@out number fan_speed 风扇转速. | ||
@out bool fan_status 风扇状态,true:开启 false:关闭. | ||
@in-example: {\"jsonrpc\":\"2.0\",\"method\":\"call\",\"params\":[\"\",\"fan\",\"get_status\",{\"get_speed\":true}],\"id\":1} | ||
@out-example: {"id":1,"jsonrpc":"2.0","result":{"fan_speed":2000,"fan_status":true}} | ||
--]] | ||
M.get_status = function(params) | ||
|
||
local res = {} | ||
local get_speed = params.get_speed | ||
if get_speed == true then | ||
utils.writefile("/sys/class/fan/fan_speed", "refresh") | ||
ngx.sleep(1.5) | ||
res.fan_speed = tonumber(utils.readfile("/sys/class/fan/fan_speed"):match("(%d+)")) | ||
end | ||
|
||
res.status = tonumber(utils.readfile("/sys/class/thermal/cooling_device0/cur_state", 'n') or 0) ~= 0 and true or false | ||
|
||
return res | ||
end | ||
|
||
return M |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
cmake_minimum_required(VERSION 3.0) | ||
|
||
project(gl_fan C) | ||
|
||
aux_source_directory(. SRCS) | ||
add_executable(gl_fan ${SRCS}) | ||
|
||
install( | ||
TARGETS gl_fan | ||
DESTINATION gl_fan | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
obj-m := gl_fan_driver.o |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,162 @@ | ||
/* | ||
* gl_fan { | ||
* compatible = "gl-fan"; | ||
* interrupt-parent = <&pio>; | ||
* interrupts = <29 IRQ_TYPE_EDGE_RISING>; | ||
* }; | ||
*/ | ||
|
||
#include <linux/kernel.h> | ||
#include <linux/module.h> | ||
#include <linux/version.h> | ||
#include <linux/interrupt.h> | ||
#include <linux/of_irq.h> | ||
#include <linux/timer.h> | ||
#include <linux/of_platform.h> | ||
|
||
#define GL_FAN_DRV_NAME "gl-fan_v2.0" | ||
|
||
typedef struct { | ||
struct class *class; | ||
struct device *dev; | ||
unsigned int count; | ||
unsigned int irq; | ||
bool refresh; | ||
struct timer_list timer; | ||
} gl_fan_t; | ||
|
||
static gl_fan_t gl_fan; | ||
|
||
#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 4, 0) | ||
static void gl_fan_timer_callback(unsigned long arg) | ||
#else | ||
static void gl_fan_timer_callback(struct timer_list *t) | ||
#endif | ||
{ | ||
disable_irq(gl_fan.irq); | ||
gl_fan.refresh = false; | ||
} | ||
|
||
static irqreturn_t handle_gpio_irq(int irq, void *data) | ||
{ | ||
gl_fan.count++; | ||
return IRQ_HANDLED; | ||
} | ||
|
||
static ssize_t fan_speed_show(struct class *class, struct class_attribute *attr, char *buf) | ||
{ | ||
if (gl_fan.refresh) { | ||
return sprintf(buf, "refreshing...\n"); | ||
} else { | ||
if (gl_fan.count < 5) { | ||
return sprintf(buf, "0\n"); | ||
} else { | ||
return sprintf(buf, "%d\n", (int)(30 * gl_fan.count)); | ||
} | ||
} | ||
} | ||
|
||
static ssize_t fan_speed_store(struct class *class, struct class_attribute *attr, const char *buf, size_t count) | ||
{ | ||
if (!strstr(buf, "refresh")) { | ||
pr_err("please input 'refresh' %s\n", buf); | ||
return -EBADRQC; | ||
} | ||
|
||
if (gl_fan.refresh == true) { | ||
pr_err("gpio is busy\n"); | ||
return -EBADRQC; | ||
} | ||
|
||
gl_fan.refresh = true; | ||
gl_fan.count = 0 ; | ||
|
||
enable_irq(gl_fan.irq); | ||
mod_timer(&gl_fan.timer, jiffies + msecs_to_jiffies(1000)); | ||
|
||
return count; | ||
} | ||
|
||
#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 4, 0) | ||
static CLASS_ATTR(fan_speed, 0664, fan_speed_show, fan_speed_store); | ||
#else | ||
static const struct class_attribute class_attr_fan_speed = | ||
__ATTR(fan_speed, 0664, fan_speed_show, fan_speed_store); | ||
#endif | ||
|
||
static int gl_fan_probe(struct platform_device *pdev) | ||
{ | ||
struct device_node *np = pdev->dev.of_node; | ||
struct device *dev = &pdev->dev; | ||
int ret; | ||
|
||
gl_fan.irq = of_irq_get(np, 0); | ||
if (gl_fan.irq < 0) { | ||
dev_err(dev, "Failed to get IRQ\n"); | ||
return -ENXIO; | ||
} | ||
|
||
ret = devm_request_irq(dev, gl_fan.irq, handle_gpio_irq, 0, "fan speed", NULL); | ||
if (ret) { | ||
pr_err("request irq %d failed!\n", gl_fan.irq); | ||
return ret; | ||
} | ||
|
||
disable_irq(gl_fan.irq); | ||
|
||
#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 4, 0) | ||
setup_timer(&gl_fan.timer, gl_fan_timer_callback, 0); | ||
#else | ||
timer_setup(&gl_fan.timer, gl_fan_timer_callback, 0); | ||
#endif | ||
|
||
gl_fan.class = class_create(THIS_MODULE, "fan"); | ||
ret = class_create_file(gl_fan.class, &class_attr_fan_speed); | ||
if (ret) { | ||
dev_err(dev, "fail to creat class file\n"); | ||
return ret; | ||
} | ||
|
||
gl_fan.dev = dev; | ||
|
||
dev_info(dev, "install gl_fan\n"); | ||
|
||
return 0; | ||
} | ||
|
||
static int gl_fan_remove(struct platform_device *pdev) | ||
{ | ||
class_destroy(gl_fan.class); | ||
dev_info(&pdev->dev, "remove gl_fan\n"); | ||
return 0; | ||
} | ||
|
||
static const struct of_device_id gl_fan_match[] = { | ||
{ .compatible = "gl-fan" }, | ||
{} | ||
}; | ||
|
||
static struct platform_driver gl_fan_driver = { | ||
.probe = gl_fan_probe, | ||
.remove = gl_fan_remove, | ||
.driver = { | ||
.name = GL_FAN_DRV_NAME, | ||
.of_match_table = gl_fan_match, | ||
} | ||
}; | ||
|
||
static int __init gl_fan_init(void) | ||
{ | ||
return platform_driver_register(&gl_fan_driver); | ||
} | ||
|
||
static void __exit gl_fan_exit(void) | ||
{ | ||
platform_driver_unregister(&gl_fan_driver); | ||
} | ||
|
||
module_init(gl_fan_init); | ||
module_exit(gl_fan_exit); | ||
|
||
MODULE_AUTHOR("xinfa deng <[email protected]>"); | ||
MODULE_LICENSE("GPL"); |
Oops, something went wrong.