.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-or-later |
---|
1 | 2 | /*************************************************************************** |
---|
2 | 3 | * Copyright (C) 2006 by Hans Edgington <hans@edgington.nl> * |
---|
3 | 4 | * Copyright (C) 2007-2009 Hans de Goede <hdegoede@redhat.com> * |
---|
4 | 5 | * Copyright (C) 2010 Giel van Schijndel <me@mortis.eu> * |
---|
5 | 6 | * * |
---|
6 | | - * This program is free software; you can redistribute it and/or modify * |
---|
7 | | - * it under the terms of the GNU General Public License as published by * |
---|
8 | | - * the Free Software Foundation; either version 2 of the License, or * |
---|
9 | | - * (at your option) any later version. * |
---|
10 | | - * * |
---|
11 | | - * This program is distributed in the hope that it will be useful, * |
---|
12 | | - * but WITHOUT ANY WARRANTY; without even the implied warranty of * |
---|
13 | | - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * |
---|
14 | | - * GNU General Public License for more details. * |
---|
15 | | - * * |
---|
16 | | - * You should have received a copy of the GNU General Public License * |
---|
17 | | - * along with this program; if not, write to the * |
---|
18 | | - * Free Software Foundation, Inc., * |
---|
19 | | - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * |
---|
20 | 7 | ***************************************************************************/ |
---|
21 | 8 | |
---|
22 | 9 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt |
---|
.. | .. |
---|
44 | 31 | #define SIO_REG_DEVID 0x20 /* Device ID (2 bytes) */ |
---|
45 | 32 | #define SIO_REG_DEVREV 0x22 /* Device revision */ |
---|
46 | 33 | #define SIO_REG_MANID 0x23 /* Fintek ID (2 bytes) */ |
---|
| 34 | +#define SIO_REG_CLOCK_SEL 0x26 /* Clock select */ |
---|
47 | 35 | #define SIO_REG_ROM_ADDR_SEL 0x27 /* ROM address select */ |
---|
48 | 36 | #define SIO_F81866_REG_PORT_SEL 0x27 /* F81866 Multi-Function Register */ |
---|
| 37 | +#define SIO_REG_TSI_LEVEL_SEL 0x28 /* TSI Level select */ |
---|
49 | 38 | #define SIO_REG_MFUNCT1 0x29 /* Multi function select 1 */ |
---|
50 | 39 | #define SIO_REG_MFUNCT2 0x2a /* Multi function select 2 */ |
---|
51 | 40 | #define SIO_REG_MFUNCT3 0x2b /* Multi function select 3 */ |
---|
.. | .. |
---|
62 | 51 | #define SIO_F71869A_ID 0x1007 /* Chipset ID */ |
---|
63 | 52 | #define SIO_F71882_ID 0x0541 /* Chipset ID */ |
---|
64 | 53 | #define SIO_F71889_ID 0x0723 /* Chipset ID */ |
---|
| 54 | +#define SIO_F81803_ID 0x1210 /* Chipset ID */ |
---|
65 | 55 | #define SIO_F81865_ID 0x0704 /* Chipset ID */ |
---|
66 | 56 | #define SIO_F81866_ID 0x1010 /* Chipset ID */ |
---|
67 | 57 | |
---|
.. | .. |
---|
121 | 111 | " given initial timeout. Zero (default) disables this feature."); |
---|
122 | 112 | |
---|
123 | 113 | enum chips { f71808fg, f71858fg, f71862fg, f71868, f71869, f71882fg, f71889fg, |
---|
124 | | - f81865, f81866}; |
---|
| 114 | + f81803, f81865, f81866}; |
---|
125 | 115 | |
---|
126 | 116 | static const char *f71808e_names[] = { |
---|
127 | 117 | "f71808fg", |
---|
.. | .. |
---|
131 | 121 | "f71869", |
---|
132 | 122 | "f71882fg", |
---|
133 | 123 | "f71889fg", |
---|
| 124 | + "f81803", |
---|
134 | 125 | "f81865", |
---|
135 | 126 | "f81866", |
---|
136 | 127 | }; |
---|
.. | .. |
---|
317 | 308 | return err; |
---|
318 | 309 | } |
---|
319 | 310 | |
---|
320 | | -static int f71862fg_pin_configure(unsigned short ioaddr) |
---|
321 | | -{ |
---|
322 | | - /* When ioaddr is non-zero the calling function has to take care of |
---|
323 | | - mutex handling and superio preparation! */ |
---|
324 | | - |
---|
325 | | - if (f71862fg_pin == 63) { |
---|
326 | | - if (ioaddr) { |
---|
327 | | - /* SPI must be disabled first to use this pin! */ |
---|
328 | | - superio_clear_bit(ioaddr, SIO_REG_ROM_ADDR_SEL, 6); |
---|
329 | | - superio_set_bit(ioaddr, SIO_REG_MFUNCT3, 4); |
---|
330 | | - } |
---|
331 | | - } else if (f71862fg_pin == 56) { |
---|
332 | | - if (ioaddr) |
---|
333 | | - superio_set_bit(ioaddr, SIO_REG_MFUNCT1, 1); |
---|
334 | | - } else { |
---|
335 | | - pr_err("Invalid argument f71862fg_pin=%d\n", f71862fg_pin); |
---|
336 | | - return -EINVAL; |
---|
337 | | - } |
---|
338 | | - return 0; |
---|
339 | | -} |
---|
340 | | - |
---|
341 | 311 | static int watchdog_start(void) |
---|
342 | 312 | { |
---|
| 313 | + int err; |
---|
| 314 | + u8 tmp; |
---|
| 315 | + |
---|
343 | 316 | /* Make sure we don't die as soon as the watchdog is enabled below */ |
---|
344 | | - int err = watchdog_keepalive(); |
---|
| 317 | + err = watchdog_keepalive(); |
---|
345 | 318 | if (err) |
---|
346 | 319 | return err; |
---|
347 | 320 | |
---|
.. | .. |
---|
360 | 333 | break; |
---|
361 | 334 | |
---|
362 | 335 | case f71862fg: |
---|
363 | | - err = f71862fg_pin_configure(watchdog.sioaddr); |
---|
364 | | - if (err) |
---|
365 | | - goto exit_superio; |
---|
| 336 | + if (f71862fg_pin == 63) { |
---|
| 337 | + /* SPI must be disabled first to use this pin! */ |
---|
| 338 | + superio_clear_bit(watchdog.sioaddr, SIO_REG_ROM_ADDR_SEL, 6); |
---|
| 339 | + superio_set_bit(watchdog.sioaddr, SIO_REG_MFUNCT3, 4); |
---|
| 340 | + } else if (f71862fg_pin == 56) { |
---|
| 341 | + superio_set_bit(watchdog.sioaddr, SIO_REG_MFUNCT1, 1); |
---|
| 342 | + } |
---|
366 | 343 | break; |
---|
367 | 344 | |
---|
368 | 345 | case f71868: |
---|
.. | .. |
---|
382 | 359 | superio_inb(watchdog.sioaddr, SIO_REG_MFUNCT3) & 0xcf); |
---|
383 | 360 | break; |
---|
384 | 361 | |
---|
| 362 | + case f81803: |
---|
| 363 | + /* Enable TSI Level register bank */ |
---|
| 364 | + superio_clear_bit(watchdog.sioaddr, SIO_REG_CLOCK_SEL, 3); |
---|
| 365 | + /* Set pin 27 to WDTRST# */ |
---|
| 366 | + superio_outb(watchdog.sioaddr, SIO_REG_TSI_LEVEL_SEL, 0x5f & |
---|
| 367 | + superio_inb(watchdog.sioaddr, SIO_REG_TSI_LEVEL_SEL)); |
---|
| 368 | + break; |
---|
| 369 | + |
---|
385 | 370 | case f81865: |
---|
386 | 371 | /* Set pin 70 to WDTRST# */ |
---|
387 | 372 | superio_clear_bit(watchdog.sioaddr, SIO_REG_MFUNCT3, 5); |
---|
388 | 373 | break; |
---|
389 | 374 | |
---|
390 | 375 | case f81866: |
---|
391 | | - /* Set pin 70 to WDTRST# */ |
---|
392 | | - superio_clear_bit(watchdog.sioaddr, SIO_F81866_REG_PORT_SEL, |
---|
393 | | - BIT(3) | BIT(0)); |
---|
394 | | - superio_set_bit(watchdog.sioaddr, SIO_F81866_REG_PORT_SEL, |
---|
395 | | - BIT(2)); |
---|
396 | 376 | /* |
---|
397 | 377 | * GPIO1 Control Register when 27h BIT3:2 = 01 & BIT0 = 0. |
---|
398 | 378 | * The PIN 70(GPIO15/WDTRST) is controlled by 2Ch: |
---|
399 | 379 | * BIT5: 0 -> WDTRST# |
---|
400 | 380 | * 1 -> GPIO15 |
---|
401 | 381 | */ |
---|
402 | | - superio_clear_bit(watchdog.sioaddr, SIO_F81866_REG_GPIO1, |
---|
403 | | - BIT(5)); |
---|
| 382 | + tmp = superio_inb(watchdog.sioaddr, SIO_F81866_REG_PORT_SEL); |
---|
| 383 | + tmp &= ~(BIT(3) | BIT(0)); |
---|
| 384 | + tmp |= BIT(2); |
---|
| 385 | + superio_outb(watchdog.sioaddr, SIO_F81866_REG_PORT_SEL, tmp); |
---|
| 386 | + |
---|
| 387 | + superio_clear_bit(watchdog.sioaddr, SIO_F81866_REG_GPIO1, 5); |
---|
404 | 388 | break; |
---|
405 | 389 | |
---|
406 | 390 | default: |
---|
.. | .. |
---|
527 | 511 | __module_get(THIS_MODULE); |
---|
528 | 512 | |
---|
529 | 513 | watchdog.expect_close = 0; |
---|
530 | | - return nonseekable_open(inode, file); |
---|
| 514 | + return stream_open(inode, file); |
---|
531 | 515 | } |
---|
532 | 516 | |
---|
533 | 517 | static int watchdog_release(struct inode *inode, struct file *file) |
---|
.. | .. |
---|
630 | 614 | |
---|
631 | 615 | if (new_options & WDIOS_ENABLECARD) |
---|
632 | 616 | return watchdog_start(); |
---|
633 | | - /* fall through */ |
---|
| 617 | + fallthrough; |
---|
634 | 618 | |
---|
635 | 619 | case WDIOC_KEEPALIVE: |
---|
636 | 620 | watchdog_keepalive(); |
---|
.. | .. |
---|
644 | 628 | return -EINVAL; |
---|
645 | 629 | |
---|
646 | 630 | watchdog_keepalive(); |
---|
647 | | - /* fall through */ |
---|
| 631 | + fallthrough; |
---|
648 | 632 | |
---|
649 | 633 | case WDIOC_GETTIMEOUT: |
---|
650 | 634 | return put_user(watchdog.timeout, uarg.i); |
---|
.. | .. |
---|
670 | 654 | .release = watchdog_release, |
---|
671 | 655 | .write = watchdog_write, |
---|
672 | 656 | .unlocked_ioctl = watchdog_ioctl, |
---|
| 657 | + .compat_ioctl = compat_ptr_ioctl, |
---|
673 | 658 | }; |
---|
674 | 659 | |
---|
675 | 660 | static struct miscdevice watchdog_miscdev = { |
---|
.. | .. |
---|
810 | 795 | break; |
---|
811 | 796 | case SIO_F71862_ID: |
---|
812 | 797 | watchdog.type = f71862fg; |
---|
813 | | - err = f71862fg_pin_configure(0); /* validate module parameter */ |
---|
814 | 798 | break; |
---|
815 | 799 | case SIO_F71868_ID: |
---|
816 | 800 | watchdog.type = f71868; |
---|
.. | .. |
---|
829 | 813 | /* Confirmed (by datasheet) not to have a watchdog. */ |
---|
830 | 814 | err = -ENODEV; |
---|
831 | 815 | goto exit; |
---|
| 816 | + case SIO_F81803_ID: |
---|
| 817 | + watchdog.type = f81803; |
---|
| 818 | + break; |
---|
832 | 819 | case SIO_F81865_ID: |
---|
833 | 820 | watchdog.type = f81865; |
---|
834 | 821 | break; |
---|
.. | .. |
---|
856 | 843 | int err = -ENODEV; |
---|
857 | 844 | int i; |
---|
858 | 845 | |
---|
| 846 | + if (f71862fg_pin != 63 && f71862fg_pin != 56) { |
---|
| 847 | + pr_err("Invalid argument f71862fg_pin=%d\n", f71862fg_pin); |
---|
| 848 | + return -EINVAL; |
---|
| 849 | + } |
---|
| 850 | + |
---|
859 | 851 | for (i = 0; i < ARRAY_SIZE(addrs); i++) { |
---|
860 | 852 | err = f71808e_find(addrs[i]); |
---|
861 | 853 | if (err == 0) |
---|