diff --git a/.tmp/nct6687d-1.0.62.tar.gz b/.tmp/nct6687d-1.0.62.tar.gz new file mode 100644 index 0000000..7e92180 Binary files /dev/null and b/.tmp/nct6687d-1.0.62.tar.gz differ diff --git a/.tmp/nct6687d-1.0.62/nct6687d/LICENSE b/.tmp/nct6687d-1.0.62/nct6687d/LICENSE new file mode 100644 index 0000000..d159169 --- /dev/null +++ b/.tmp/nct6687d-1.0.62/nct6687d/LICENSE @@ -0,0 +1,339 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Lesser General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. diff --git a/.tmp/nct6687d-1.0.62/nct6687d/Makefile b/.tmp/nct6687d-1.0.62/nct6687d/Makefile new file mode 100644 index 0000000..e90b60a --- /dev/null +++ b/.tmp/nct6687d-1.0.62/nct6687d/Makefile @@ -0,0 +1,78 @@ +obj-m += nct6687.o + +curpwd := $(shell pwd) +kver := $(shell uname -r) +commitcount := $(shell git rev-list --all --count) +commithash := $(shell git rev-parse --short HEAD) + + +build: + rm -rf ${curpwd}/${kver} + mkdir -p ${curpwd}/${kver} + cp ${curpwd}/Makefile ${curpwd}/nct6687.c ${curpwd}/${kver} + cd ${curpwd}/${kver} + make -C /lib/modules/${kver}/build M=${curpwd}/${kver} modules + +install: build + sudo cp ${curpwd}/${kver}/nct6687.ko /lib/modules/${kver}/kernel/drivers/hwmon/ + sudo depmod + sudo modprobe nct6687 + +clean: + [ -d "${curpwd}/${kver}" ] && make -C /lib/modules/${kver}/build M=${curpwd}/${kver} clean + + + + +akmod/build: + sudo dnf groupinstall -y "Development Tools" + sudo dnf install -y rpmdevtools kmodtool + mkdir -p ${curpwd}/.tmp/nct6687d-1.0.${commitcount}/nct6687d + cp LICENSE Makefile nct6687.c ${curpwd}/.tmp/nct6687d-1.0.${commitcount}/nct6687d + cd .tmp && tar -czvf nct6687d-1.0.${commitcount}.tar.gz nct6687d-1.0.${commitcount} && cd - + mkdir -p ${curpwd}/.tmp/rpmbuild/{BUILD,RPMS,SOURCES,SPECS,SRPMS} + cp ${curpwd}/.tmp/nct6687d-1.0.${commitcount}.tar.gz ${curpwd}/.tmp/rpmbuild/SOURCES/ + echo 'nct6687' | tee ${curpwd}/.tmp/rpmbuild/SOURCES/nct6687.conf + cp fedora/*.spec ${curpwd}/.tmp/rpmbuild/SPECS/ + sed -i "s/MAKEFILE_PKGVER/${commitcount}/g" ${curpwd}/.tmp/rpmbuild/SPECS/* + sed -i "s/MAKEFILE_COMMITHASH/${commithash}/g" ${curpwd}/.tmp/rpmbuild/SPECS/* + rpmbuild -ba --define "_topdir ${curpwd}/.tmp/rpmbuild" ${curpwd}/.tmp/rpmbuild/SPECS/nct6687d.spec + rpmbuild -ba --define "_topdir ${curpwd}/.tmp/rpmbuild" ${curpwd}/.tmp/rpmbuild/SPECS/nct6687d-kmod.spec + +akmod/install: akmod/build + sudo dnf install ${curpwd}/.tmp/rpmbuild/RPMS/*/*.rpm + +akmod/clean: + sudo dnf remove nct6687d + +akmod: akmod/install + + + +dkms/build: + make -C /lib/modules/${kver}/build M=${curpwd} modules + +dkms/install: + rm -rf ${curpwd}/dkms + mkdir -p ${curpwd}/dkms + cp ${curpwd}/dkms.conf ${curpwd}/Makefile ${curpwd}/nct6687.c ${curpwd}/dkms + sudo rm -rf /usr/src/nct6687d-1 + sudo cp -rT dkms /usr/src/nct6687d-1 + sudo dkms install nct6687d/1 + sudo modprobe nct6687 + +dkms/clean: + sudo dkms remove nct6687d/1 --all + make -C /lib/modules/${kver}/build M=${curpwd} clean + +debian/changelog: FORCE + git --no-pager log \ + --format='nct6687d-dkms (%ad) unstable; urgency=low%n%n * %s%n%n -- %aN <%aE> %aD%n' \ + --date='format:%Y%m%d-%H%M%S' \ + > $@ + +deb: debian/changelog + dpkg-buildpackage -b -rfakeroot -us -uc + +.PHONY: FORCE +FORCE: diff --git a/.tmp/nct6687d-1.0.62/nct6687d/nct6687.c b/.tmp/nct6687d-1.0.62/nct6687d/nct6687.c new file mode 100644 index 0000000..3a6385b --- /dev/null +++ b/.tmp/nct6687d-1.0.62/nct6687d/nct6687.c @@ -0,0 +1,1264 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * nct6687 - Driver for the hardware monitoring functionality of + * Nuvoton NCT6687 Super-I/O chips + * + * Copyright (C) 2020 Frederic Boltz + * + * Derived from nct6683 driver + * Copyright (C) 2013 Guenter Roeck + * + * Inspired of LibreHardwareMonitor + * https://github.com/LibreHardwareMonitor/LibreHardwareMonitor + * + * Supports the following chips: + * + * Chip #voltage #fan #pwm #temp chip ID + * nct6683 14(1) 8 8 7 0xc732 (partial support) + * nct6687 14(1) 8 8 7 0xd592 + * + * Notes: + * (1) Total number of voltage and 9 displayed. + */ +// #define DEBUG 1 +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define MIN(a,b) (((a)<(b))?(a):(b)) +#define MAX(a,b) (((a)>(b))?(a):(b)) + +enum kinds +{ + nct6683, + nct6687 +}; + +static bool force; +static bool manual; + +module_param(force, bool, 0); +MODULE_PARM_DESC(force, "Set to one to enable support for unknown vendors"); + +module_param(manual, bool, 0); +MODULE_PARM_DESC(manual, "Set voltage input and voltage label configured with external sensors file"); + +static const char *const nct6687_device_names[] = { + "nct6683", + "nct6687", +}; + +static const char *const nct6687_chip_names[] = { + "NCT6683D", + "NCT6687D", +}; + +#define DRVNAME "nct6687" + +/* + * Super-I/O constants and functions + */ + +#define NCT6687_LD_ACPI 0x0a +#define NCT6687_LD_HWM 0x0b +#define NCT6687_LD_VID 0x0d + +#define SIO_REG_LDSEL 0x07 /* Logical device select */ +#define SIO_REG_DEVID 0x20 /* Device ID (2 bytes) */ +#define SIO_REG_DEVREVISION 0x21 /* Device ID (2 bytes) */ +#define SIO_REG_ENABLE 0x30 /* Logical device enable */ +#define SIO_REG_ADDR 0x60 /* Logical device address (2 bytes) */ + +#define SIO_NCT6683D_ID 0xc732 +#define SIO_NCT6687_ID 0xd451 // 0xd592 +#define SIO_NCT6687D_ID 0xd592 + +static inline void superio_outb(int ioreg, int reg, int val) +{ + outb(reg, ioreg); + outb(val, ioreg + 1); +} + +static inline int superio_inb(int ioreg, int reg) +{ + outb(reg, ioreg); + + return inb(ioreg + 1); +} + +static inline void superio_select(int ioreg, int ld) +{ + outb(SIO_REG_LDSEL, ioreg); + outb(ld, ioreg + 1); +} + +static inline int superio_enter(int ioreg) +{ + /* + * Try to reserve and for exclusive access. + */ + if (!request_muxed_region(ioreg, 2, DRVNAME)) + return -EBUSY; + + outb(0x87, ioreg); + outb(0x87, ioreg); + + return 0; +} + +static inline void superio_exit(int ioreg) +{ + outb(0xaa, ioreg); + outb(0x02, ioreg); + outb(0x02, ioreg + 1); + + release_region(ioreg, 2); +} + +/* + * ISA constants + */ + +#define IOREGION_OFFSET 0 /* Use EC port 1 */ +#define IOREGION_LENGTH 4 + +/* Common and NCT6687 specific data */ + +#define NCT6687_NUM_REG_VOLTAGE (sizeof(nct6687_voltage_definition) / sizeof(struct voltage_reg)) +#define NCT6687_NUM_REG_TEMP 7 +#define NCT6687_NUM_REG_FAN 8 +#define NCT6687_NUM_REG_PWM 8 + +#define NCT6687_REG_TEMP(x) (0x100 + (x)*2) +#define NCT6687_REG_VOLTAGE(x) (0x120 + (x)*2) +#define NCT6687_REG_FAN_RPM(x) (0x140 + (x)*2) +#define NCT6687_REG_PWM(x) (0x160 + (x)) +#define NCT6687_REG_PWM_WRITE(x) (0xa28 + (x)) + +#define NCT6687_HWM_CFG 0x180 + +#define NCT6687_REG_MON_CFG(x) (0x1a0 + (x)) +#define NCT6687_REG_FANIN_CFG(x) (0xA00 + (x)) +#define NCT6687_REG_FANOUT_CFG(x) (0x1d0 + (x)) + +#define NCT6687_REG_TEMP_HYST(x) (0x330 + (x)) /* 8 bit */ +#define NCT6687_REG_TEMP_MAX(x) (0x350 + (x)) /* 8 bit */ +#define NCT6687_REG_MON_HIGH(x) (0x370 + (x)*2) /* 8 bit */ +#define NCT6687_REG_MON_LOW(x) (0x371 + (x)*2) /* 8 bit */ + +#define NCT6687_REG_FAN_MIN(x) (0x3b8 + (x)*2) /* 16 bit */ + +#define NCT6687_REG_FAN_CTRL_MODE(x) 0xA00 +#define NCT6687_REG_FAN_PWM_COMMAND(x) 0xA01 +#define NCT6687_FAN_CFG_REQ 0x80 +#define NCT6687_FAN_CFG_DONE 0x40 + +#define NCT6687_REG_BUILD_YEAR 0x604 +#define NCT6687_REG_BUILD_MONTH 0x605 +#define NCT6687_REG_BUILD_DAY 0x606 +#define NCT6687_REG_SERIAL 0x607 +#define NCT6687_REG_VERSION_HI 0x608 +#define NCT6687_REG_VERSION_LO 0x609 + +#define NCT6687_REG_CR_CASEOPEN 0xe8 +#define NCT6687_CR_CASEOPEN_MASK (1 << 7) + +#define NCT6687_REG_CR_BEEP 0xe0 +#define NCT6687_CR_BEEP_MASK (1 << 6) + +#define EC_SPACE_PAGE_REGISTER_OFFSET 0x04 +#define EC_SPACE_INDEX_REGISTER_OFFSET 0x05 +#define EC_SPACE_DATA_REGISTER_OFFSET 0x06 +#define EC_SPACE_PAGE_SELECT 0xFF + +struct voltage_reg +{ + u16 reg; + u16 multiplier; + const char *label; +}; + +static struct voltage_reg nct6687_voltage_definition[] = { + // +12V + { + .reg = 0, + .multiplier = 12, + .label = "+12V", + }, + // + 5V + { + .reg = 1, + .multiplier = 5, + .label = "+5V", + }, + // +3.3V + { + .reg = 11, + .multiplier = 1, + .label = "+3.3V", + }, + // CPU SOC + { + .reg = 2, + .multiplier = 1, + .label = "CPU Soc", + }, + // CPU Vcore + { + .reg = 4, + .multiplier = 1, + .label = "CPU Vcore", + }, + // CPU 1P8 + { + .reg = 9, + .multiplier = 1, + .label = "CPU 1P8", + }, + // CPU VDDP + { + .reg = 10, + .multiplier = 1, + .label = "CPU VDDP", + }, + // DRAM + { + .reg = 3, + .multiplier = 2, + .label = "DRAM", + }, + // Chipset + { + .reg = 5, + .multiplier = 1, + .label = "Chipset", + }, + + // CPU SA + { + .reg = 6, + .multiplier = 1, + .label = "CPU SA", + }, + // Voltage #2 + { + .reg = 7, + .multiplier = 1, + .label = "Voltage #2", + }, + // AVCC3 + { + .reg = 8, + .multiplier = 1, + .label = "AVCC3", + }, + // AVSB + { + .reg = 12, + .multiplier = 1, + .label = "AVSB", + }, + // VBAT + { + .reg = 13, + .multiplier = 1, + .label = "VBat", + }, + +}; + +static const char *const nct6687_temp_label[] = { + "CPU", + "System", + "VRM MOS", + "PCH", + "CPU Socket", + "PCIe x1", + "M2_1", + NULL, +}; + +static const char *const nct6687_fan_label[] = { + "CPU Fan", + "Pump Fan", + "System Fan #1", + "System Fan #2", + "System Fan #3", + "System Fan #4", + "System Fan #5", + "System Fan #6", + NULL, +}; + +/* ------------------------------------------------------- */ +struct nct6687_data +{ + int addr; /* IO base of EC space */ + int sioreg; /* SIO register */ + enum kinds kind; + + struct device *hwmon_dev; + const struct attribute_group *groups[6]; + + struct mutex update_lock; /* used to protect sensor updates */ + bool valid; /* true if following fields are valid */ + unsigned long last_updated; /* In jiffies */ + + /* Voltage values */ + s16 voltage[3][NCT6687_NUM_REG_VOLTAGE]; // 0 = current 1 = min 2 = max + + /* Temperature values */ + s32 temperature[3][NCT6687_NUM_REG_TEMP]; // 0 = current 1 = min 2 = max + + /* Fan attribute values */ + u16 rpm[3][NCT6687_NUM_REG_FAN]; // 0 = current 1 = min 2 = max + u8 _initialFanControlMode[NCT6687_NUM_REG_FAN]; + u8 _initialFanPwmCommand[NCT6687_NUM_REG_FAN]; + bool _restoreDefaultFanControlRequired[NCT6687_NUM_REG_FAN]; + + u8 pwm[NCT6687_NUM_REG_PWM]; + + /* Remember extra register values over suspend/resume */ + u8 hwm_cfg; +}; + +struct nct6687_sio_data +{ + int sioreg; + enum kinds kind; +}; + +struct sensor_device_template +{ + struct device_attribute dev_attr; + union + { + struct + { + u8 nr; + u8 index; + } s; + int index; + } u; + bool s2; /* true if both index and nr are used */ +}; + +struct sensor_device_attr_u +{ + union + { + struct sensor_device_attribute a1; + struct sensor_device_attribute_2 a2; + } u; + char name[32]; +}; + +#define __TEMPLATE_ATTR(_template, _mode, _show, _store) \ + { \ + .attr = {.name = _template, .mode = _mode}, \ + .show = _show, \ + .store = _store, \ + } + +#define SENSOR_DEVICE_TEMPLATE(_template, _mode, _show, _store, _index) \ + { \ + .dev_attr = __TEMPLATE_ATTR(_template, _mode, _show, _store), \ + .u.index = _index, \ + .s2 = false \ + } + +#define SENSOR_DEVICE_TEMPLATE_2(_template, _mode, _show, _store, \ + _nr, _index) \ + { \ + .dev_attr = __TEMPLATE_ATTR(_template, _mode, _show, _store), \ + .u.s.index = _index, \ + .u.s.nr = _nr, \ + .s2 = true \ + } + +#define SENSOR_TEMPLATE(_name, _template, _mode, _show, _store, _index) \ + static struct sensor_device_template sensor_dev_template_##_name = SENSOR_DEVICE_TEMPLATE(_template, _mode, _show, _store, \ + _index) + +#define SENSOR_TEMPLATE_2(_name, _template, _mode, _show, _store, \ + _nr, _index) \ + static struct sensor_device_template sensor_dev_template_##_name = SENSOR_DEVICE_TEMPLATE_2(_template, _mode, _show, _store, \ + _nr, _index) + +struct sensor_template_group +{ + struct sensor_device_template **templates; + umode_t (*is_visible)(struct kobject *, struct attribute *, int); + int base; +}; + +static void nct6687_save_fan_control(struct nct6687_data *data, int index); + +static const char* nct6687_voltage_label(char* buf, int index) +{ + if (manual) + sprintf(buf, "in%d", index); + else + strcpy(buf, nct6687_voltage_definition[index].label); + + return buf; +} + +static struct attribute_group *nct6687_create_attr_group(struct device *dev, const struct sensor_template_group *tg, int repeat) +{ + struct sensor_device_attribute_2 *a2; + struct sensor_device_attribute *a; + struct sensor_device_template **t; + struct sensor_device_attr_u *su; + struct attribute_group *group; + struct attribute **attrs; + int i, j, count; + + if (repeat <= 0) + return ERR_PTR(-EINVAL); + + t = tg->templates; + for (count = 0; *t; t++, count++) + ; + + if (count == 0) + return ERR_PTR(-EINVAL); + + group = devm_kzalloc(dev, sizeof(*group), GFP_KERNEL); + if (group == NULL) + return ERR_PTR(-ENOMEM); + + attrs = devm_kcalloc(dev, repeat * count + 1, sizeof(*attrs), GFP_KERNEL); + if (attrs == NULL) + return ERR_PTR(-ENOMEM); + + su = devm_kzalloc(dev, array3_size(repeat, count, sizeof(*su)), GFP_KERNEL); + if (su == NULL) + return ERR_PTR(-ENOMEM); + + group->attrs = attrs; + group->is_visible = tg->is_visible; + + for (i = 0; i < repeat; i++) + { + t = tg->templates; + + for (j = 0; *t != NULL; j++) + { + snprintf(su->name, sizeof(su->name), (*t)->dev_attr.attr.name, tg->base + i); + + if ((*t)->s2) + { + a2 = &su->u.a2; + sysfs_attr_init(&a2->dev_attr.attr); + a2->dev_attr.attr.name = su->name; + a2->nr = (*t)->u.s.nr + i; + a2->index = (*t)->u.s.index; + a2->dev_attr.attr.mode = (*t)->dev_attr.attr.mode; + a2->dev_attr.show = (*t)->dev_attr.show; + a2->dev_attr.store = (*t)->dev_attr.store; + *attrs = &a2->dev_attr.attr; + } + else + { + a = &su->u.a1; + sysfs_attr_init(&a->dev_attr.attr); + a->dev_attr.attr.name = su->name; + a->index = (*t)->u.index + i; + a->dev_attr.attr.mode = (*t)->dev_attr.attr.mode; + a->dev_attr.show = (*t)->dev_attr.show; + a->dev_attr.store = (*t)->dev_attr.store; + *attrs = &a->dev_attr.attr; + } + attrs++; + su++; + t++; + } + } + + return group; +} + +static u16 nct6687_read(struct nct6687_data *data, u16 address) +{ + u8 page = (u8)(address >> 8); + u8 index = (u8)(address & 0xFF); + int res; + + outb_p(EC_SPACE_PAGE_SELECT, data->addr + EC_SPACE_PAGE_REGISTER_OFFSET); + outb_p(page, data->addr + EC_SPACE_PAGE_REGISTER_OFFSET); + outb_p(index, data->addr + EC_SPACE_INDEX_REGISTER_OFFSET); + + res = inb_p(data->addr + EC_SPACE_DATA_REGISTER_OFFSET); + + return res; +} + +static u16 nct6687_read16(struct nct6687_data *data, u16 reg) +{ + return (nct6687_read(data, reg) << 8) | nct6687_read(data, reg + 1); +} + +static void nct6687_write(struct nct6687_data *data, u16 address, u16 value) +{ + u8 page = (u8)(address >> 8); + u8 index = (u8)(address & 0xFF); + + outb_p(EC_SPACE_PAGE_SELECT, data->addr + EC_SPACE_PAGE_REGISTER_OFFSET); + outb_p(page, data->addr + EC_SPACE_PAGE_REGISTER_OFFSET); + outb_p(index, data->addr + EC_SPACE_INDEX_REGISTER_OFFSET); + outb_p(value, data->addr + EC_SPACE_DATA_REGISTER_OFFSET); +} + +static void nct6687_update_temperatures(struct nct6687_data *data) +{ + int i; + + for (i = 0; i < NCT6687_NUM_REG_TEMP; i++) + { + s32 value = (char)nct6687_read(data, NCT6687_REG_TEMP(i)); + s32 half = (nct6687_read(data, NCT6687_REG_TEMP(i) + 1) >> 7) & 0x1; + s32 temperature = (value * 1000) + (500 * half); + + data->temperature[0][i] = temperature; + data->temperature[1][i] = MIN(temperature, data->temperature[1][i]); + data->temperature[2][i] = MAX(temperature, data->temperature[2][i]); + + pr_debug("nct6687_update_temperatures[%d]], addr=%04X, value=%d, half=%d, temperature=%d\n", i, NCT6687_REG_TEMP(i), value, half, temperature); + } +} + +static void nct6687_update_voltage(struct nct6687_data *data) +{ + int index; + char buf[128]; + + /* Measured voltages and limits */ + for (index = 0; index < NCT6687_NUM_REG_VOLTAGE; index++) + { + s16 reg = manual ? index : nct6687_voltage_definition[index].reg; + s16 high = nct6687_read(data, NCT6687_REG_VOLTAGE(reg)) * 16; + s16 low = ((u16)nct6687_read(data, NCT6687_REG_VOLTAGE(reg) + 1)) >> 4; + s16 value = low + high; + s16 voltage = manual ? value : value * nct6687_voltage_definition[index].multiplier; + + data->voltage[0][index] = voltage; + data->voltage[1][index] = MIN(voltage, data->voltage[1][index]); + data->voltage[2][index] = MAX(voltage, data->voltage[2][index]); + + pr_debug("nct6687_update_voltage[%d], %s, reg=%d, addr=0x%04x, value=%d, voltage=%d\n", index, nct6687_voltage_label(buf, index), reg, NCT6687_REG_VOLTAGE(index), value, voltage); + } + + pr_debug("nct6687_update_voltage\n"); +} + +static void nct6687_update_fans(struct nct6687_data *data) +{ + int i; + + for (i = 0; i < NCT6687_NUM_REG_FAN; i++) + { + s16 rmp = nct6687_read16(data, NCT6687_REG_FAN_RPM(i)); + + data->rpm[0][i] = rmp; + data->rpm[1][i] = MIN(rmp, data->rpm[1][i]); + data->rpm[2][i] = MAX(rmp, data->rpm[2][i]); + + pr_debug("nct6687_update_fans[%d], rpm=%d min=%d, max=%d", i, rmp, data->rpm[1][i], data->rpm[2][i]); + } + + for (i = 0; i < NCT6687_NUM_REG_PWM; i++) + { + data->pwm[i] = nct6687_read(data, NCT6687_REG_PWM(i)); + + pr_debug("nct6687_update_fans[%d], pwm=%d", i, data->pwm[i]); + } +} + +static struct nct6687_data *nct6687_update_device(struct device *dev) +{ + struct nct6687_data *data = dev_get_drvdata(dev); + + mutex_lock(&data->update_lock); + + if (time_after(jiffies, data->last_updated + HZ) || !data->valid) + { + /* Measured voltages and limits */ + nct6687_update_voltage(data); + + /* Measured temperatures and limits */ + nct6687_update_temperatures(data); + + /* Measured fan speeds and limits */ + nct6687_update_fans(data); + + data->last_updated = jiffies; + data->valid = true; + } + + mutex_unlock(&data->update_lock); + + return data; +} + +/* + * Sysfs callback functions + */ +static ssize_t show_voltage_label(struct device *dev, struct device_attribute *attr, char *buf) +{ + struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr); + + if (manual) + return sprintf(buf, "in%d\n", sattr->index); + else + return sprintf(buf, "%s\n", nct6687_voltage_definition[sattr->index].label); +} + +static ssize_t show_voltage_value(struct device *dev, struct device_attribute *attr, char *buf) +{ + struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr); + struct nct6687_data *data = nct6687_update_device(dev); + + return sprintf(buf, "%d\n", data->voltage[sattr->index][sattr->nr]); +} + +static umode_t nct6687_voltage_is_visible(struct kobject *kobj, struct attribute *attr, int index) +{ + pr_debug("nct6687_voltage_is_visible[%d], attr=0x%04X\n", index, attr->mode); + return attr->mode; +} + +SENSOR_TEMPLATE(voltage_label, "in%d_label", S_IRUGO, show_voltage_label, NULL, 0); +SENSOR_TEMPLATE_2(voltage_input, "in%d_input", S_IRUGO, show_voltage_value, NULL, 0, 0); +SENSOR_TEMPLATE_2(voltage_min, "in%d_min", S_IRUGO, show_voltage_value, NULL, 0, 1); +SENSOR_TEMPLATE_2(voltage_max, "in%d_max", S_IRUGO, show_voltage_value, NULL, 0, 2); + +static struct sensor_device_template *nct6687_attributes_voltage_template[] = { + &sensor_dev_template_voltage_label, + &sensor_dev_template_voltage_input, + &sensor_dev_template_voltage_min, + &sensor_dev_template_voltage_max, + NULL, +}; + +static const struct sensor_template_group nct6687_voltage_template_group = { + .templates = nct6687_attributes_voltage_template, + .is_visible = nct6687_voltage_is_visible, +}; + +static ssize_t show_fan_label(struct device *dev, struct device_attribute *attr, char *buf) +{ + struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr); + + return sprintf(buf, "%s\n", nct6687_fan_label[sattr->index]); +} + +static ssize_t show_fan_value(struct device *dev, struct device_attribute *attr, char *buf) +{ + struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr); + struct nct6687_data *data = nct6687_update_device(dev); + + return sprintf(buf, "%d\n", data->rpm[sattr->index][sattr->nr]); +} + +static umode_t nct6687_fan_is_visible(struct kobject *kobj, struct attribute *attr, int index) +{ + return attr->mode; +} + +SENSOR_TEMPLATE(fan_label, "fan%d_label", S_IRUGO, show_fan_label, NULL, 0); +SENSOR_TEMPLATE_2(fan_input, "fan%d_input", S_IRUGO, show_fan_value, NULL, 0, 0); +SENSOR_TEMPLATE_2(fan_min, "fan%d_min", S_IRUGO, show_fan_value, NULL, 0, 1); +SENSOR_TEMPLATE_2(fan_max, "fan%d_max", S_IRUGO, show_fan_value, NULL, 0, 2); + +/* + * nct6687_fan_is_visible uses the index into the following array + * to determine if attributes should be created or not. + * Any change in order or content must be matched. + */ +static struct sensor_device_template *nct6687_attributes_fan_template[] = { + &sensor_dev_template_fan_label, + &sensor_dev_template_fan_input, + &sensor_dev_template_fan_min, + &sensor_dev_template_fan_max, + NULL, +}; + +static const struct sensor_template_group nct6687_fan_template_group = { + .templates = nct6687_attributes_fan_template, + .is_visible = nct6687_fan_is_visible, + .base = 1, +}; + +static ssize_t show_temperature_label(struct device *dev, struct device_attribute *attr, char *buf) +{ + struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr); + + return sprintf(buf, "%s\n", nct6687_temp_label[sattr->index]); +} + +static ssize_t show_temperature_value(struct device *dev, struct device_attribute *attr, char *buf) +{ + struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr); + struct nct6687_data *data = nct6687_update_device(dev); + + return sprintf(buf, "%d\n", data->temperature[sattr->index][sattr->nr]); +} + +static umode_t nct6687_temp_is_visible(struct kobject *kobj, struct attribute *attr, int index) +{ + return attr->mode; +} + +SENSOR_TEMPLATE(temp_label, "temp%d_label", S_IRUGO, show_temperature_label, NULL, 0); +SENSOR_TEMPLATE_2(temp_input, "temp%d_input", S_IRUGO, show_temperature_value, NULL, 0, 0); +SENSOR_TEMPLATE_2(temp_min, "temp%d_min", S_IRUGO, show_temperature_value, NULL, 0, 1); +SENSOR_TEMPLATE_2(temp_max, "temp%d_max", S_IRUGO, show_temperature_value, NULL, 0, 2); + +/* + * nct6687_temp_is_visible uses the index into the following array + * to determine if attributes should be created or not. + * Any change in order or content must be matched. + */ +static struct sensor_device_template *nct6687_attributes_temp_template[] = { + &sensor_dev_template_temp_input, + &sensor_dev_template_temp_label, + &sensor_dev_template_temp_min, + &sensor_dev_template_temp_max, + NULL, +}; + +static const struct sensor_template_group nct6687_temp_template_group = { + .templates = nct6687_attributes_temp_template, + .is_visible = nct6687_temp_is_visible, + .base = 1, +}; + +static ssize_t show_pwm(struct device *dev, struct device_attribute *attr, char *buf) +{ + struct nct6687_data *data = nct6687_update_device(dev); + struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr); + int index = sattr->index; + + return sprintf(buf, "%d\n", data->pwm[index]); +} + +static ssize_t store_pwm(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) +{ + struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr); + struct nct6687_data *data = dev_get_drvdata(dev); + int index = sattr->index; + unsigned long val; + u16 mode; + u8 bitMask; + + if (kstrtoul(buf, 10, &val) || val > 255 || index >= NCT6687_NUM_REG_FAN) + return -EINVAL; + + mutex_lock(&data->update_lock); + + nct6687_save_fan_control(data, index); + + mode = nct6687_read(data, NCT6687_REG_FAN_CTRL_MODE(index)); + bitMask = (u8)(0x01 << index); + + mode = (u8)(mode | bitMask); + nct6687_write(data, NCT6687_REG_FAN_CTRL_MODE(index), mode); + + nct6687_write(data, NCT6687_REG_FAN_PWM_COMMAND(index), NCT6687_FAN_CFG_REQ); + msleep(50); + nct6687_write(data, NCT6687_REG_PWM_WRITE(index), val); + nct6687_write(data, NCT6687_REG_FAN_PWM_COMMAND(index), NCT6687_FAN_CFG_DONE); + msleep(50); + + mutex_unlock(&data->update_lock); + + return count; +} + +SENSOR_TEMPLATE(pwm, "pwm%d", S_IRUGO, show_pwm, store_pwm, 0); + +static void nct6687_save_fan_control(struct nct6687_data *data, int index) +{ + if (data->_restoreDefaultFanControlRequired[index] == false) + { + u16 reg = nct6687_read(data, NCT6687_REG_FAN_CTRL_MODE(index)); + u16 bitMask = 0x01 << index; + u8 pwm = nct6687_read(data, NCT6687_REG_FAN_PWM_COMMAND(index)); + + data->_initialFanControlMode[index] = (u8)(reg & bitMask); + data->_initialFanPwmCommand[index] = pwm; + + data->_restoreDefaultFanControlRequired[index] = true; + } +} + +static void nct6687_restore_fan_control(struct nct6687_data *data, int index) +{ + if (data->_restoreDefaultFanControlRequired[index]) + { + u8 mode = nct6687_read(data, NCT6687_REG_FAN_CTRL_MODE(index)); + mode = (u8)(mode & ~data->_initialFanControlMode[index]); + + nct6687_write(data, NCT6687_REG_FAN_CTRL_MODE(index), mode); + + nct6687_write(data, NCT6687_REG_FAN_PWM_COMMAND(index), NCT6687_FAN_CFG_REQ); + msleep(50); + nct6687_write(data, NCT6687_REG_PWM_WRITE(index), data->_initialFanPwmCommand[index]); + nct6687_write(data, NCT6687_REG_FAN_PWM_COMMAND(index), NCT6687_FAN_CFG_DONE); + msleep(50); + + data->_restoreDefaultFanControlRequired[index] = false; + + pr_debug("nct6687_restore_fan_control[%d], addr=%04X, ctrl=%04X, _initialFanPwmCommand=%d\n", index, NCT6687_REG_FAN_PWM_COMMAND(index), NCT6687_REG_PWM_WRITE(index), data->_initialFanPwmCommand[index]); + } +} + +static umode_t nct6687_pwm_is_visible(struct kobject *kobj, struct attribute *attr, int index) +{ + return attr->mode | S_IWUSR; +} + +static struct sensor_device_template *nct6687_attributes_pwm_template[] = { + &sensor_dev_template_pwm, + NULL, +}; + +static const struct sensor_template_group nct6687_pwm_template_group = { + .templates = nct6687_attributes_pwm_template, + .is_visible = nct6687_pwm_is_visible, + .base = 1, +}; + +/* Get the monitoring functions started */ +static inline void nct6687_init_device(struct nct6687_data *data) +{ + u8 tmp; + + pr_debug("nct6687_init_device\n"); + + /* Start hardware monitoring if needed */ + tmp = nct6687_read(data, NCT6687_HWM_CFG); + if (!(tmp & 0x80)) + { + pr_debug("nct6687_init_device: 0x%04x\n", tmp); + nct6687_write(data, NCT6687_HWM_CFG, tmp | 0x80); + } + + // enable SIO voltage + nct6687_write(data, 0x1BB, 0x61); + nct6687_write(data, 0x1BC, 0x62); + nct6687_write(data, 0x1BD, 0x63); + nct6687_write(data, 0x1BE, 0x64); + nct6687_write(data, 0x1BF, 0x65); +} + +/* + * There are a total of 8 fan inputs. + */ +static void nct6687_setup_fans(struct nct6687_data *data) +{ + int i; + + for (i = 0; i < NCT6687_NUM_REG_FAN; i++) + { + u16 reg = nct6687_read(data, NCT6687_REG_FAN_CTRL_MODE(i)); + u16 bitMask = 0x01 << i; + u16 rpm = nct6687_read16(data, NCT6687_REG_FAN_RPM(i)); + + data->rpm[0][i] = rpm; + data->rpm[1][i] = rpm; + data->rpm[2][i] = rpm; + data->_initialFanControlMode[i] = (u8)(reg & bitMask); + data->_restoreDefaultFanControlRequired[i] = false; + + pr_debug("nct6687_setup_fans[%d], %s - addr=%04X, ctrl=%04X, rpm=%d, _initialFanControlMode=%d\n", i, nct6687_fan_label[i], NCT6687_REG_FAN_CTRL_MODE(i), reg, rpm, data->_initialFanControlMode[i]); + } +} + +static void nct6687_setup_voltages(struct nct6687_data *data) +{ + int index; + char buf[64]; + + /* Measured voltages and limits */ + for (index = 0; index < NCT6687_NUM_REG_VOLTAGE; index++) + { + s16 reg = manual ? index : nct6687_voltage_definition[index].reg; + s16 high = nct6687_read(data, NCT6687_REG_VOLTAGE(reg)) * 16; + s16 low = ((u16)nct6687_read(data, NCT6687_REG_VOLTAGE(reg) + 1)) >> 4; + s16 value = low + high; + s16 voltage = manual ? value : value * nct6687_voltage_definition[index].multiplier; + + data->voltage[0][index] = voltage; + data->voltage[1][index] = voltage; + data->voltage[2][index] = voltage; + + pr_debug("nct6687_setup_voltages[%d], %s, addr=0x%04x, value=%d, voltage=%d\n", index, nct6687_voltage_label(buf, index), NCT6687_REG_VOLTAGE(index), value, voltage); + } +} + +static void nct6687_setup_temperatures(struct nct6687_data *data) +{ + int i; + + for (i = 0; i < NCT6687_NUM_REG_TEMP; i++) + { + s32 value = (char)nct6687_read(data, NCT6687_REG_TEMP(i)); + s32 half = (nct6687_read(data, NCT6687_REG_TEMP(i) + 1) >> 7) & 0x1; + s32 temperature = (value * 1000) + (5 * half); + + data->temperature[0][i] = temperature; + data->temperature[1][i] = temperature; + data->temperature[2][i] = temperature; + + pr_debug("nct6687_setup_temperatures[%d]], addr=%04X, value=%d, half=%d, temperature=%d\n", i, NCT6687_REG_TEMP(i), value, half, temperature); + } +} + +static void nct6687_setup_pwm(struct nct6687_data *data) +{ + int i; + + for (i = 0; i < NCT6687_NUM_REG_PWM; i++) + { + data->_initialFanPwmCommand[i] = nct6687_read(data, NCT6687_REG_FAN_PWM_COMMAND(i)); + data->pwm[i] = nct6687_read(data, NCT6687_REG_PWM(i)); + + pr_debug("nct6687_setup_pwm[%d], addr=%04X, pwm=%d, _initialFanPwmCommand=%d\n", i, NCT6687_REG_FAN_PWM_COMMAND(i), data->pwm[i], data->_initialFanPwmCommand[i]); + } +} + +static int nct6687_remove(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct nct6687_data *data = dev_get_drvdata(dev); + int i; + + mutex_lock(&data->update_lock); + + for (i = 0; i < NCT6687_NUM_REG_FAN; i++) + { + nct6687_restore_fan_control(data, i); + } + + mutex_unlock(&data->update_lock); + + return 0; +} + +static int nct6687_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct nct6687_sio_data *sio_data = dev->platform_data; + struct attribute_group *group; + struct nct6687_data *data; + struct device *hwmon_dev; + struct resource *res; + int groups = 0; + char build[16]; + + res = platform_get_resource(pdev, IORESOURCE_IO, 0); + if (!devm_request_region(dev, res->start, IOREGION_LENGTH, DRVNAME)) + return -EBUSY; + + data = devm_kzalloc(dev, sizeof(struct nct6687_data), GFP_KERNEL); + if (!data) + return -ENOMEM; + + data->kind = sio_data->kind; + data->sioreg = sio_data->sioreg; + data->addr = res->start; + + pr_debug("nct6687_probe addr=0x%04X, sioreg=0x%04X\n", data->addr, data->sioreg); + + mutex_init(&data->update_lock); + + platform_set_drvdata(pdev, data); + + nct6687_init_device(data); + nct6687_setup_fans(data); + nct6687_setup_pwm(data); + nct6687_setup_temperatures(data); + nct6687_setup_voltages(data); + + /* Register sysfs hooks */ + + group = nct6687_create_attr_group(dev, &nct6687_pwm_template_group, NCT6687_NUM_REG_FAN); + + if (IS_ERR(group)) + return PTR_ERR(group); + + data->groups[groups++] = group; + + group = nct6687_create_attr_group(dev, &nct6687_voltage_template_group, NCT6687_NUM_REG_VOLTAGE); + + if (IS_ERR(group)) + return PTR_ERR(group); + + data->groups[groups++] = group; + + group = nct6687_create_attr_group(dev, &nct6687_fan_template_group, NCT6687_NUM_REG_FAN); + + if (IS_ERR(group)) + return PTR_ERR(group); + + data->groups[groups++] = group; + + group = nct6687_create_attr_group(dev, &nct6687_temp_template_group, NCT6687_NUM_REG_TEMP); + + if (IS_ERR(group)) + return PTR_ERR(group); + + data->groups[groups++] = group; + + scnprintf(build, sizeof(build), "%02d/%02d/%02d", nct6687_read(data, NCT6687_REG_BUILD_MONTH), nct6687_read(data, NCT6687_REG_BUILD_DAY), nct6687_read(data, NCT6687_REG_BUILD_YEAR)); + + dev_info(dev, "%s EC firmware version %d.%d build %s\n", nct6687_chip_names[data->kind], nct6687_read(data, NCT6687_REG_VERSION_HI), nct6687_read(data, NCT6687_REG_VERSION_LO), build); + + hwmon_dev = devm_hwmon_device_register_with_groups(dev, nct6687_device_names[data->kind], data, data->groups); + + return PTR_ERR_OR_ZERO(hwmon_dev); +} + +static int nct6687_suspend(struct platform_device *pdev, pm_message_t state) +{ + struct nct6687_data *data = nct6687_update_device(&pdev->dev); + + mutex_lock(&data->update_lock); + data->hwm_cfg = nct6687_read(data, NCT6687_HWM_CFG); + mutex_unlock(&data->update_lock); + + return 0; +} + +static int nct6687_resume(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct nct6687_data *data = dev_get_drvdata(dev); + + mutex_lock(&data->update_lock); + + nct6687_write(data, NCT6687_HWM_CFG, data->hwm_cfg); + + /* Force re-reading all values */ + data->valid = false; + mutex_unlock(&data->update_lock); + + return 0; +} + +// static const struct dev_pm_ops nct6687_dev_pm_ops = { +// .suspend = nct6687_suspend, +// .resume = nct6687_resume, +// .freeze = nct6687_suspend, +// .restore = nct6687_resume, +// }; + +#define NCT6687_DEV_PM_OPS NULL + +static struct platform_driver nct6687_driver = { + .driver = { + .name = DRVNAME, + .pm = NCT6687_DEV_PM_OPS, + }, + .probe = nct6687_probe, + .remove = nct6687_remove, + .suspend = nct6687_suspend, + .resume = nct6687_resume, +}; + +static int __init nct6687_find(int sioaddr, struct nct6687_sio_data *sio_data) +{ + u16 address; + u16 verify; + u16 val; + int err; + + err = superio_enter(sioaddr); + if (err) + return err; + + val = (superio_inb(sioaddr, SIO_REG_DEVID) << 8) | superio_inb(sioaddr, SIO_REG_DEVREVISION); + + pr_debug("found chip ID: 0x%04x\n", val); + + if (val == SIO_NCT6683D_ID) { + sio_data->kind = nct6683; + } else if (val == SIO_NCT6687_ID || val == SIO_NCT6687D_ID || force) + { + sio_data->kind = nct6687; + } + else + { + if (val != 0xffff) + pr_debug("unsupported chip ID: 0x%04x\n", val); + goto fail; + } + + /* We have a known chip, find the HWM I/O address */ + superio_select(sioaddr, NCT6687_LD_HWM); + address = (superio_inb(sioaddr, SIO_REG_ADDR) << 8) | superio_inb(sioaddr, SIO_REG_ADDR + 1); + ssleep(1); + verify = (superio_inb(sioaddr, SIO_REG_ADDR) << 8) | superio_inb(sioaddr, SIO_REG_ADDR + 1); + + if (address == 0 || address != verify) + { + pr_err("EC base I/O port unconfigured\n"); + goto fail; + } + + if ((address & 0x07) == 0x05) + address &= 0xFFF8; + + if (address < 0x100 || (address & 0xF007) != 0) + { + pr_err("EC Invalid address: 0x%04X\n", address); + goto fail; + } + + /* Activate logical device if needed */ + val = superio_inb(sioaddr, SIO_REG_ENABLE); + if (!(val & 0x01)) + { + pr_warn("Forcibly enabling EC access. Data may be unusable.\n"); + superio_outb(sioaddr, SIO_REG_ENABLE, val | 0x01); + } + + superio_exit(sioaddr); + pr_info("Found %s or compatible chip at 0x%04x:0x%04x\n", nct6687_chip_names[sio_data->kind], sioaddr, address); + sio_data->sioreg = sioaddr; + + return address; + +fail: + superio_exit(sioaddr); + return -ENODEV; +} + +/* + * when Super-I/O functions move to a separate file, the Super-I/O + * bus will manage the lifetime of the device and this module will only keep + * track of the nct6687 driver. But since we use platform_device_alloc(), we + * must keep track of the device + */ +static struct platform_device *pdev[2]; + +static int __init sensors_nct6687_init(void) +{ + struct nct6687_sio_data sio_data; + int sioaddr[2] = {0x2e, 0x4e}; + struct resource res; + bool found = false; + int address; + int i, err; + + err = platform_driver_register(&nct6687_driver); + if (err) + return err; + + /* + * initialize sio_data->kind and sio_data->sioreg. + * + * when Super-I/O functions move to a separate file, the Super-I/O + * driver will probe 0x2e and 0x4e and auto-detect the presence of a + * nct6687 hardware monitor, and call probe() + */ + for (i = 0; i < ARRAY_SIZE(pdev); i++) + { + address = nct6687_find(sioaddr[i], &sio_data); + if (address <= 0) + continue; + + found = true; + + pdev[i] = platform_device_alloc(DRVNAME, address); + if (!pdev[i]) + { + err = -ENOMEM; + goto exit_device_unregister; + } + + err = platform_device_add_data(pdev[i], &sio_data, sizeof(struct nct6687_sio_data)); + if (err) + goto exit_device_put; + + memset(&res, 0, sizeof(res)); + + res.name = DRVNAME; + res.start = address + IOREGION_OFFSET; + res.end = address + IOREGION_OFFSET + IOREGION_LENGTH - 1; + res.flags = IORESOURCE_IO; + + err = acpi_check_resource_conflict(&res); + if (err) + { + platform_device_put(pdev[i]); + pdev[i] = NULL; + continue; + } + + err = platform_device_add_resources(pdev[i], &res, 1); + if (err) + goto exit_device_put; + + /* platform_device_add calls probe() */ + err = platform_device_add(pdev[i]); + if (err) + goto exit_device_put; + } + + if (!found) + { + err = -ENODEV; + goto exit_unregister; + } + + return 0; + +exit_device_put: + platform_device_put(pdev[i]); + +exit_device_unregister: + while (--i >= 0) + { + if (pdev[i]) + platform_device_unregister(pdev[i]); + } + +exit_unregister: + platform_driver_unregister(&nct6687_driver); + + return err; +} + +static void __exit sensors_nct6687_exit(void) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(pdev); i++) + { + if (pdev[i]) + platform_device_unregister(pdev[i]); + } + + platform_driver_unregister(&nct6687_driver); +} + +MODULE_AUTHOR("Frederic Boltz "); +MODULE_DESCRIPTION("Driver for NCT6687D"); +MODULE_LICENSE("GPL"); + +module_init(sensors_nct6687_init); +module_exit(sensors_nct6687_exit); diff --git a/.tmp/rpmbuild/RPMS/noarch/nct6687d-1.0.62-gitf59feef.noarch.rpm b/.tmp/rpmbuild/RPMS/noarch/nct6687d-1.0.62-gitf59feef.noarch.rpm new file mode 100644 index 0000000..f9605da Binary files /dev/null and b/.tmp/rpmbuild/RPMS/noarch/nct6687d-1.0.62-gitf59feef.noarch.rpm differ diff --git a/.tmp/rpmbuild/RPMS/x86_64/akmod-nct6687d-1.0.62-gitf59feef.x86_64.rpm b/.tmp/rpmbuild/RPMS/x86_64/akmod-nct6687d-1.0.62-gitf59feef.x86_64.rpm new file mode 100644 index 0000000..a7cf0f9 Binary files /dev/null and b/.tmp/rpmbuild/RPMS/x86_64/akmod-nct6687d-1.0.62-gitf59feef.x86_64.rpm differ diff --git a/.tmp/rpmbuild/RPMS/x86_64/kmod-nct6687d-1.0.62-gitf59feef.x86_64.rpm b/.tmp/rpmbuild/RPMS/x86_64/kmod-nct6687d-1.0.62-gitf59feef.x86_64.rpm new file mode 100644 index 0000000..947cc3b Binary files /dev/null and b/.tmp/rpmbuild/RPMS/x86_64/kmod-nct6687d-1.0.62-gitf59feef.x86_64.rpm differ diff --git a/.tmp/rpmbuild/SOURCES/nct6687.conf b/.tmp/rpmbuild/SOURCES/nct6687.conf new file mode 100644 index 0000000..164b458 --- /dev/null +++ b/.tmp/rpmbuild/SOURCES/nct6687.conf @@ -0,0 +1 @@ +nct6687 diff --git a/.tmp/rpmbuild/SOURCES/nct6687d-1.0.62.tar.gz b/.tmp/rpmbuild/SOURCES/nct6687d-1.0.62.tar.gz new file mode 100644 index 0000000..7e92180 Binary files /dev/null and b/.tmp/rpmbuild/SOURCES/nct6687d-1.0.62.tar.gz differ diff --git a/.tmp/rpmbuild/SPECS/nct6687d-kmod.spec b/.tmp/rpmbuild/SPECS/nct6687d-kmod.spec new file mode 100644 index 0000000..31d63bb --- /dev/null +++ b/.tmp/rpmbuild/SPECS/nct6687d-kmod.spec @@ -0,0 +1,57 @@ +%if 0%{?fedora} +%global buildforkernels akmod +%global debug_package %{nil} +%endif + +%global prjname nct6687d +%global pkgver 62 +%global commithash f59feef +%define buildforkernels akmod + +Name: %{prjname}-kmod +Version: 1.0.%{pkgver} +Release: git%{commithash} +Summary: Kernel module (kmod) for %{prjname} +License: GPL-2.0 +URL: https://github.com/Fred78290/nct6687d +Source0: nct6687d-%{version}.tar.gz +BuildRoot: %{_tmppath}/%{name}-%{version}-root-%(%{__id_u} -n) + + +BuildRequires: gcc +BuildRequires: make +BuildRequires: elfutils-libelf-devel +BuildRequires: kmodtool +Conflicts: nct6687d-kmod-common + +%{expand:%(kmodtool --target %{_target_cpu} --kmodname %{prjname} %{?buildforkernels:--%{buildforkernels}} %{?kernels:--for-kernels "%{?kernels}"} 2>/dev/null) } + +%description +%{prjname} kernel module + +%prep +kmodtool --target %{_target_cpu} --kmodname %{prjname} %{?buildforkernels:--%{buildforkernels}} %{?kernels:--for-kernels "%{?kernels}"} 2>/dev/null + +%autosetup -n nct6687d-%{version} + +for kernel_version in %{?kernel_versions} ; do + cp -a nct6687d _kmod_build_${kernel_version%%___*} +done + +%build +for kernel_version in %{?kernel_versions}; do + make V=0 %{?_smp_mflags} -C "${kernel_version##*___}" M=${PWD}/_kmod_build_${kernel_version%%___*} +done + +%install +for kernel_version in %{?kernel_versions}; do + mkdir -p %{buildroot}%{kmodinstdir_prefix}/${kernel_version%%___*}/%{kmodinstdir_postfix}/ + install -D -m 755 _kmod_build_${kernel_version%%___*}/*.ko %{buildroot}%{kmodinstdir_prefix}/${kernel_version%%___*}/%{kmodinstdir_postfix}/ + chmod a+x %{buildroot}%{kmodinstdir_prefix}/${kernel_version%%___*}/%{kmodinstdir_postfix}/*.ko +done +%{?akmod_install} + + +%changelog +* Wed Jan 04 2023 Frederic BOLTZ - %{version} +- Initial package diff --git a/.tmp/rpmbuild/SPECS/nct6687d.spec b/.tmp/rpmbuild/SPECS/nct6687d.spec new file mode 100644 index 0000000..dca2877 --- /dev/null +++ b/.tmp/rpmbuild/SPECS/nct6687d.spec @@ -0,0 +1,35 @@ +%global pkgver 62 +%global commithash f59feef + +Name: nct6687d +Version: 1.0.%{pkgver} +Release: git%{commithash} +Summary: Kernel module (kmod) for %{prjname} +License: GPL-2.0 +URL: https://github.com/Fred78290/nct6687d +Source0: nct6687.conf + +# For kmod package +Provides: %{name}-kmod-common = %{version}-%{release} +Requires: %{name}-kmod >= %{version} + +BuildArch: noarch + +%description +%{prjname} kernel module + +%prep + +%build +# Nothing to build + +%install + +install -D -m 0644 %{SOURCE0} %{buildroot}%{_modulesloaddir}/nct6687.conf + +%files +%{_modulesloaddir}/nct6687.conf + +%changelog +* Wed Jan 04 2023 Frederic BOLTZ - %{version} +- Initial package diff --git a/.tmp/rpmbuild/SRPMS/nct6687d-1.0.62-gitf59feef.src.rpm b/.tmp/rpmbuild/SRPMS/nct6687d-1.0.62-gitf59feef.src.rpm new file mode 100644 index 0000000..d00af29 Binary files /dev/null and b/.tmp/rpmbuild/SRPMS/nct6687d-1.0.62-gitf59feef.src.rpm differ diff --git a/.tmp/rpmbuild/SRPMS/nct6687d-kmod-1.0.62-gitf59feef.src.rpm b/.tmp/rpmbuild/SRPMS/nct6687d-kmod-1.0.62-gitf59feef.src.rpm new file mode 100644 index 0000000..f571d91 Binary files /dev/null and b/.tmp/rpmbuild/SRPMS/nct6687d-kmod-1.0.62-gitf59feef.src.rpm differ diff --git a/Makefile b/Makefile index cd9b23e..14de1b6 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,10 @@ obj-m += nct6687.o -curpwd := $(shell pwd) -kver := $(shell uname -r) +curpwd := $(shell pwd) +kver := $(shell uname -r) +commitcount := $(shell git rev-list --all --count) +commithash := $(shell git rev-parse --short HEAD) + build: rm -rf ${curpwd}/${kver} @@ -9,16 +12,35 @@ build: cp ${curpwd}/Makefile ${curpwd}/nct6687.c ${curpwd}/${kver} cd ${curpwd}/${kver} make -C /lib/modules/${kver}/build M=${curpwd}/${kver} modules - install: build sudo cp ${curpwd}/${kver}/nct6687.ko /lib/modules/${kver}/kernel/drivers/hwmon/ sudo depmod sudo modprobe nct6687 - clean: [ -d "${curpwd}/${kver}" ] && make -C /lib/modules/${kver}/build M=${curpwd}/${kver} clean +akmod/build: + sudo dnf groupinstall -y "Development Tools" + sudo dnf install -y rpmdevtools kmodtool + mkdir -p ${curpwd}/.tmp/nct6687d-1.0.${commitcount}/nct6687d + cp LICENSE Makefile nct6687.c ${curpwd}/.tmp/nct6687d-1.0.${commitcount}/nct6687d + cd .tmp && tar -czvf nct6687d-1.0.${commitcount}.tar.gz nct6687d-1.0.${commitcount} && cd - + mkdir -p ${curpwd}/.tmp/rpmbuild/{BUILD,RPMS,SOURCES,SPECS,SRPMS} + cp ${curpwd}/.tmp/nct6687d-1.0.${commitcount}.tar.gz ${curpwd}/.tmp/rpmbuild/SOURCES/ + echo 'nct6687' | tee ${curpwd}/.tmp/rpmbuild/SOURCES/nct6687.conf + cp fedora/*.spec ${curpwd}/.tmp/rpmbuild/SPECS/ + sed -i "s/MAKEFILE_PKGVER/${commitcount}/g" ${curpwd}/.tmp/rpmbuild/SPECS/* + sed -i "s/MAKEFILE_COMMITHASH/${commithash}/g" ${curpwd}/.tmp/rpmbuild/SPECS/* + rpmbuild -ba --define "_topdir ${curpwd}/.tmp/rpmbuild" ${curpwd}/.tmp/rpmbuild/SPECS/nct6687d.spec + rpmbuild -ba --define "_topdir ${curpwd}/.tmp/rpmbuild" ${curpwd}/.tmp/rpmbuild/SPECS/nct6687d-kmod.spec +akmod/install: akmod/build + sudo dnf install ${curpwd}/.tmp/rpmbuild/RPMS/*/*.rpm +akmod/clean: + sudo dnf remove nct6687d + rm -rf .tmp +akmod: akmod/install + dkms/build: make -C /lib/modules/${kver}/build M=${curpwd} modules @@ -36,8 +58,6 @@ dkms/clean: sudo dkms remove nct6687d/1 --all make -C /lib/modules/${kver}/build M=${curpwd} clean - - debian/changelog: FORCE git --no-pager log \ --format='nct6687d-dkms (%ad) unstable; urgency=low%n%n * %s%n%n -- %aN <%aE> %aD%n' \ @@ -45,6 +65,7 @@ debian/changelog: FORCE > $@ deb: debian/changelog + sudo apt install -y debhelper dkms dpkg-buildpackage -b -rfakeroot -us -uc .PHONY: FORCE diff --git a/README.md b/README.md index b5369fb..6723932 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,6 @@ ![https://valid.x86.fr/vsb4yv](https://valid.x86.fr/cache/banner/vsb4yv-6.png) ![https://valid.x86.fr/20aiek](https://valid.x86.fr/cache/banner/20aiek-6.png) -# README - -## NCT6687D Kernel module +# NCT6687D Kernel module This kernel module permit to recognize the chipset Nuvoton NCT6687-R in lm-sensors package. This sensor is present on some B550 motherboard such as MSI or ASUS. @@ -11,7 +9,36 @@ The implementation is minimalist and was done by reverse coding of Windows 10 so

## Installation -#### Dependencies: +### .deb package +- Clone this repository +```shell +~$ git clone https://github.com/Fred78290/nct6687d +~$ cd nct6687d +``` +- Build package +```shell +~$ make deb +``` +- Install package +```shell +~$ dpkg -i ../nct6687d-dkms_*.deb +``` +
+ +### .rpm package (akmod) +- Clone this repository +```shell +~$ git clone https://github.com/Fred78290/nct6687d +~$ cd nct6687d +``` +- Build & install package +```shell +~$ make akmod +``` +

+ +## Manual Install +### Dependencies: - Ubuntu/Debian: ```apt-get install build-essential linux-headers-$(uname -r) dkms``` - Fedora/CentOS/RHEL: @@ -38,26 +65,6 @@ The implementation is minimalist and was done by reverse coding of Windows 10 so ```
-### Deb package -- Prerequisites -```shell -~$ apt install -y debhelper dkms -``` -- Clone this repository -```shell -~$ git clone https://github.com/Fred78290/nct6687d -~$ cd nct6687d -``` -- Build package -```shell -make deb -``` -- Install package -```shell -dpkg -i ../nct6687d-dkms_*.deb -``` -

- ## Sensors By running the command sensors, you got this output @@ -176,4 +183,4 @@ chip "nct6687-*" ## VERIFIED **1. Fan speed control** -- Changing fan speed was tested succesfuly by users, see reported issue. \ No newline at end of file +- Changing fan speed was tested succesfuly by users, see reported issue. diff --git a/fedora/nct6687d-kmod.spec b/fedora/nct6687d-kmod.spec new file mode 100644 index 0000000..9740d6b --- /dev/null +++ b/fedora/nct6687d-kmod.spec @@ -0,0 +1,57 @@ +%if 0%{?fedora} +%global buildforkernels akmod +%global debug_package %{nil} +%endif + +%global prjname nct6687d +%global pkgver MAKEFILE_PKGVER +%global commithash MAKEFILE_COMMITHASH +%define buildforkernels akmod + +Name: %{prjname}-kmod +Version: 1.0.%{pkgver} +Release: git%{commithash} +Summary: Kernel module (kmod) for %{prjname} +License: GPL-2.0 +URL: https://github.com/Fred78290/nct6687d +Source0: nct6687d-%{version}.tar.gz +BuildRoot: %{_tmppath}/%{name}-%{version}-root-%(%{__id_u} -n) + + +BuildRequires: gcc +BuildRequires: make +BuildRequires: elfutils-libelf-devel +BuildRequires: kmodtool +Conflicts: nct6687d-kmod-common + +%{expand:%(kmodtool --target %{_target_cpu} --kmodname %{prjname} %{?buildforkernels:--%{buildforkernels}} %{?kernels:--for-kernels "%{?kernels}"} 2>/dev/null) } + +%description +%{prjname} kernel module + +%prep +kmodtool --target %{_target_cpu} --kmodname %{prjname} %{?buildforkernels:--%{buildforkernels}} %{?kernels:--for-kernels "%{?kernels}"} 2>/dev/null + +%autosetup -n nct6687d-%{version} + +for kernel_version in %{?kernel_versions} ; do + cp -a nct6687d _kmod_build_${kernel_version%%___*} +done + +%build +for kernel_version in %{?kernel_versions}; do + make V=0 %{?_smp_mflags} -C "${kernel_version##*___}" M=${PWD}/_kmod_build_${kernel_version%%___*} +done + +%install +for kernel_version in %{?kernel_versions}; do + mkdir -p %{buildroot}%{kmodinstdir_prefix}/${kernel_version%%___*}/%{kmodinstdir_postfix}/ + install -D -m 755 _kmod_build_${kernel_version%%___*}/*.ko %{buildroot}%{kmodinstdir_prefix}/${kernel_version%%___*}/%{kmodinstdir_postfix}/ + chmod a+x %{buildroot}%{kmodinstdir_prefix}/${kernel_version%%___*}/%{kmodinstdir_postfix}/*.ko +done +%{?akmod_install} + + +%changelog +* Wed Jan 04 2023 Frederic BOLTZ - %{version} +- Initial package diff --git a/fedora/nct6687d.spec b/fedora/nct6687d.spec new file mode 100644 index 0000000..72a0fda --- /dev/null +++ b/fedora/nct6687d.spec @@ -0,0 +1,35 @@ +%global pkgver MAKEFILE_PKGVER +%global commithash MAKEFILE_COMMITHASH + +Name: nct6687d +Version: 1.0.%{pkgver} +Release: git%{commithash} +Summary: Kernel module (kmod) for %{prjname} +License: GPL-2.0 +URL: https://github.com/Fred78290/nct6687d +Source0: nct6687.conf + +# For kmod package +Provides: %{name}-kmod-common = %{version}-%{release} +Requires: %{name}-kmod >= %{version} + +BuildArch: noarch + +%description +%{prjname} kernel module + +%prep + +%build +# Nothing to build + +%install + +install -D -m 0644 %{SOURCE0} %{buildroot}%{_modulesloaddir}/nct6687.conf + +%files +%{_modulesloaddir}/nct6687.conf + +%changelog +* Wed Jan 04 2023 Frederic BOLTZ - %{version} +- Initial package