Skip to content

Commit

Permalink
ipq60xx: add kmod-gl-sdk4-fan support for GL.iNet GL-AXT1800
Browse files Browse the repository at this point in the history
  • Loading branch information
coolsnowwolf authored and sdf8057 committed Apr 1, 2023
1 parent c127280 commit f5028f2
Show file tree
Hide file tree
Showing 9 changed files with 563 additions and 1 deletion.
60 changes: 60 additions & 0 deletions package/kernel/gl-sdk4-fan/Makefile
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)))
4 changes: 4 additions & 0 deletions package/kernel/gl-sdk4-fan/files/etc/config/glfan
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@

config globals
option enabled '1'

39 changes: 39 additions & 0 deletions package/kernel/gl-sdk4-fan/files/etc/init.d/gl_fan
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
}
63 changes: 63 additions & 0 deletions package/kernel/gl-sdk4-fan/files/fan.lua
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
11 changes: 11 additions & 0 deletions package/kernel/gl-sdk4-fan/src/CMakeLists.txt
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
)
1 change: 1 addition & 0 deletions package/kernel/gl-sdk4-fan/src/driver/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
obj-m := gl_fan_driver.o
162 changes: 162 additions & 0 deletions package/kernel/gl-sdk4-fan/src/driver/gl_fan_driver.c
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");
Loading

0 comments on commit f5028f2

Please sign in to comment.