diff options
| author | Darrick J. Wong <djwong@us.ibm.com> | 2008-11-12 16:27:04 -0500 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2008-11-12 20:17:18 -0500 |
| commit | a412ae3fb90ab49072b82c8cfa1e3e60d2b27005 (patch) | |
| tree | a145d9346dc1a97eb21dc0c86bcaf62c7cd8c359 | |
| parent | c0b4e3ab0c769913438aeb078535ff117eeba5fb (diff) | |
ics932s401: new clock generator chip driver
The ics932s401 is a clock generator chip. This driver allows users to
read the current clock outputs.
Signed-off-by: Darrick J. Wong <djwong@us.ibm.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
| -rw-r--r-- | Documentation/ics932s401 | 31 | ||||
| -rw-r--r-- | drivers/misc/Kconfig | 10 | ||||
| -rw-r--r-- | drivers/misc/Makefile | 1 | ||||
| -rw-r--r-- | drivers/misc/ics932s401.c | 515 |
4 files changed, 557 insertions, 0 deletions
diff --git a/Documentation/ics932s401 b/Documentation/ics932s401 new file mode 100644 index 000000000000..07a739f406d8 --- /dev/null +++ b/Documentation/ics932s401 | |||
| @@ -0,0 +1,31 @@ | |||
| 1 | Kernel driver ics932s401 | ||
| 2 | ====================== | ||
| 3 | |||
| 4 | Supported chips: | ||
| 5 | * IDT ICS932S401 | ||
| 6 | Prefix: 'ics932s401' | ||
| 7 | Addresses scanned: I2C 0x69 | ||
| 8 | Datasheet: Publically available at the IDT website | ||
| 9 | |||
| 10 | Author: Darrick J. Wong | ||
| 11 | |||
| 12 | Description | ||
| 13 | ----------- | ||
| 14 | |||
| 15 | This driver implements support for the IDT ICS932S401 chip family. | ||
| 16 | |||
| 17 | This chip has 4 clock outputs--a base clock for the CPU (which is likely | ||
| 18 | multiplied to get the real CPU clock), a system clock, a PCI clock, a USB | ||
| 19 | clock, and a reference clock. The driver reports selected and actual | ||
| 20 | frequency. If spread spectrum mode is enabled, the driver also reports by what | ||
| 21 | percent the clock signal is being spread, which should be between 0 and -0.5%. | ||
| 22 | All frequencies are reported in KHz. | ||
| 23 | |||
| 24 | The ICS932S401 monitors all inputs continuously. The driver will not read | ||
| 25 | the registers more often than once every other second. | ||
| 26 | |||
| 27 | Special Features | ||
| 28 | ---------------- | ||
| 29 | |||
| 30 | The clocks could be reprogrammed to increase system speed. I will not help you | ||
| 31 | do this, as you risk damaging your system! | ||
diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig index 4494ad27cbf1..dcac7ca76937 100644 --- a/drivers/misc/Kconfig +++ b/drivers/misc/Kconfig | |||
| @@ -227,6 +227,16 @@ config HP_WMI | |||
| 227 | To compile this driver as a module, choose M here: the module will | 227 | To compile this driver as a module, choose M here: the module will |
| 228 | be called hp-wmi. | 228 | be called hp-wmi. |
| 229 | 229 | ||
| 230 | config ICS932S401 | ||
| 231 | tristate "Integrated Circuits ICS932S401" | ||
| 232 | depends on I2C && EXPERIMENTAL | ||
| 233 | help | ||
| 234 | If you say yes here you get support for the Integrated Circuits | ||
| 235 | ICS932S401 clock control chips. | ||
| 236 | |||
| 237 | This driver can also be built as a module. If so, the module | ||
| 238 | will be called ics932s401. | ||
| 239 | |||
| 230 | config MSI_LAPTOP | 240 | config MSI_LAPTOP |
| 231 | tristate "MSI Laptop Extras" | 241 | tristate "MSI Laptop Extras" |
| 232 | depends on X86 | 242 | depends on X86 |
diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile index 909e2468cdc9..bb14633d1362 100644 --- a/drivers/misc/Makefile +++ b/drivers/misc/Makefile | |||
| @@ -14,6 +14,7 @@ obj-$(CONFIG_ATMEL_PWM) += atmel_pwm.o | |||
| 14 | obj-$(CONFIG_ATMEL_SSC) += atmel-ssc.o | 14 | obj-$(CONFIG_ATMEL_SSC) += atmel-ssc.o |
| 15 | obj-$(CONFIG_ATMEL_TCLIB) += atmel_tclib.o | 15 | obj-$(CONFIG_ATMEL_TCLIB) += atmel_tclib.o |
| 16 | obj-$(CONFIG_HP_WMI) += hp-wmi.o | 16 | obj-$(CONFIG_HP_WMI) += hp-wmi.o |
| 17 | obj-$(CONFIG_ICS932S401) += ics932s401.o | ||
| 17 | obj-$(CONFIG_TC1100_WMI) += tc1100-wmi.o | 18 | obj-$(CONFIG_TC1100_WMI) += tc1100-wmi.o |
| 18 | obj-$(CONFIG_LKDTM) += lkdtm.o | 19 | obj-$(CONFIG_LKDTM) += lkdtm.o |
| 19 | obj-$(CONFIG_TIFM_CORE) += tifm_core.o | 20 | obj-$(CONFIG_TIFM_CORE) += tifm_core.o |
diff --git a/drivers/misc/ics932s401.c b/drivers/misc/ics932s401.c new file mode 100644 index 000000000000..6e43ab4231ae --- /dev/null +++ b/drivers/misc/ics932s401.c | |||
| @@ -0,0 +1,515 @@ | |||
| 1 | /* | ||
| 2 | * A driver for the Integrated Circuits ICS932S401 | ||
| 3 | * Copyright (C) 2008 IBM | ||
| 4 | * | ||
| 5 | * Author: Darrick J. Wong <djwong@us.ibm.com> | ||
| 6 | * | ||
| 7 | * This program is free software; you can redistribute it and/or modify | ||
| 8 | * it under the terms of the GNU General Public License as published by | ||
| 9 | * the Free Software Foundation; either version 2 of the License, or | ||
| 10 | * (at your option) any later version. | ||
| 11 | * | ||
| 12 | * This program is distributed in the hope that it will be useful, | ||
| 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 15 | * GNU General Public License for more details. | ||
| 16 | * | ||
| 17 | * You should have received a copy of the GNU General Public License | ||
| 18 | * along with this program; if not, write to the Free Software | ||
| 19 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
| 20 | */ | ||
| 21 | |||
| 22 | #include <linux/module.h> | ||
| 23 | #include <linux/jiffies.h> | ||
| 24 | #include <linux/i2c.h> | ||
| 25 | #include <linux/err.h> | ||
| 26 | #include <linux/mutex.h> | ||
| 27 | #include <linux/delay.h> | ||
| 28 | #include <linux/log2.h> | ||
| 29 | |||
| 30 | /* Addresses to scan */ | ||
| 31 | static const unsigned short normal_i2c[] = { 0x69, I2C_CLIENT_END }; | ||
| 32 | |||
| 33 | /* Insmod parameters */ | ||
| 34 | I2C_CLIENT_INSMOD_1(ics932s401); | ||
| 35 | |||
| 36 | /* ICS932S401 registers */ | ||
| 37 | #define ICS932S401_REG_CFG2 0x01 | ||
| 38 | #define ICS932S401_CFG1_SPREAD 0x01 | ||
| 39 | #define ICS932S401_REG_CFG7 0x06 | ||
| 40 | #define ICS932S401_FS_MASK 0x07 | ||
| 41 | #define ICS932S401_REG_VENDOR_REV 0x07 | ||
| 42 | #define ICS932S401_VENDOR 1 | ||
| 43 | #define ICS932S401_VENDOR_MASK 0x0F | ||
| 44 | #define ICS932S401_REV 4 | ||
| 45 | #define ICS932S401_REV_SHIFT 4 | ||
| 46 | #define ICS932S401_REG_DEVICE 0x09 | ||
| 47 | #define ICS932S401_DEVICE 11 | ||
| 48 | #define ICS932S401_REG_CTRL 0x0A | ||
| 49 | #define ICS932S401_MN_ENABLED 0x80 | ||
| 50 | #define ICS932S401_CPU_ALT 0x04 | ||
| 51 | #define ICS932S401_SRC_ALT 0x08 | ||
| 52 | #define ICS932S401_REG_CPU_M_CTRL 0x0B | ||
| 53 | #define ICS932S401_M_MASK 0x3F | ||
| 54 | #define ICS932S401_REG_CPU_N_CTRL 0x0C | ||
| 55 | #define ICS932S401_REG_CPU_SPREAD1 0x0D | ||
| 56 | #define ICS932S401_REG_CPU_SPREAD2 0x0E | ||
| 57 | #define ICS932S401_SPREAD_MASK 0x7FFF | ||
| 58 | #define ICS932S401_REG_SRC_M_CTRL 0x0F | ||
| 59 | #define ICS932S401_REG_SRC_N_CTRL 0x10 | ||
| 60 | #define ICS932S401_REG_SRC_SPREAD1 0x11 | ||
| 61 | #define ICS932S401_REG_SRC_SPREAD2 0x12 | ||
| 62 | #define ICS932S401_REG_CPU_DIVISOR 0x13 | ||
| 63 | #define ICS932S401_CPU_DIVISOR_SHIFT 4 | ||
| 64 | #define ICS932S401_REG_PCISRC_DIVISOR 0x14 | ||
| 65 | #define ICS932S401_SRC_DIVISOR_MASK 0x0F | ||
| 66 | #define ICS932S401_PCI_DIVISOR_SHIFT 4 | ||
| 67 | |||
| 68 | /* Base clock is 14.318MHz */ | ||
| 69 | #define BASE_CLOCK 14318 | ||
| 70 | |||
| 71 | #define NUM_REGS 21 | ||
| 72 | #define NUM_MIRRORED_REGS 15 | ||
| 73 | |||
| 74 | static int regs_to_copy[NUM_MIRRORED_REGS] = { | ||
| 75 | ICS932S401_REG_CFG2, | ||
| 76 | ICS932S401_REG_CFG7, | ||
| 77 | ICS932S401_REG_VENDOR_REV, | ||
| 78 | ICS932S401_REG_DEVICE, | ||
| 79 | ICS932S401_REG_CTRL, | ||
| 80 | ICS932S401_REG_CPU_M_CTRL, | ||
| 81 | ICS932S401_REG_CPU_N_CTRL, | ||
| 82 | ICS932S401_REG_CPU_SPREAD1, | ||
| 83 | ICS932S401_REG_CPU_SPREAD2, | ||
| 84 | ICS932S401_REG_SRC_M_CTRL, | ||
| 85 | ICS932S401_REG_SRC_N_CTRL, | ||
| 86 | ICS932S401_REG_SRC_SPREAD1, | ||
| 87 | ICS932S401_REG_SRC_SPREAD2, | ||
| 88 | ICS932S401_REG_CPU_DIVISOR, | ||
| 89 | ICS932S401_REG_PCISRC_DIVISOR, | ||
| 90 | }; | ||
| 91 | |||
| 92 | /* How often do we reread sensors values? (In jiffies) */ | ||
| 93 | #define SENSOR_REFRESH_INTERVAL (2 * HZ) | ||
| 94 | |||
| 95 | /* How often do we reread sensor limit values? (In jiffies) */ | ||
| 96 | #define LIMIT_REFRESH_INTERVAL (60 * HZ) | ||
| 97 | |||
| 98 | struct ics932s401_data { | ||
| 99 | struct attribute_group attrs; | ||
| 100 | struct mutex lock; | ||
| 101 | char sensors_valid; | ||
| 102 | unsigned long sensors_last_updated; /* In jiffies */ | ||
| 103 | |||
| 104 | u8 regs[NUM_REGS]; | ||
| 105 | }; | ||
| 106 | |||
| 107 | static int ics932s401_probe(struct i2c_client *client, | ||
| 108 | const struct i2c_device_id *id); | ||
| 109 | static int ics932s401_detect(struct i2c_client *client, int kind, | ||
| 110 | struct i2c_board_info *info); | ||
| 111 | static int ics932s401_remove(struct i2c_client *client); | ||
| 112 | |||
| 113 | static const struct i2c_device_id ics932s401_id[] = { | ||
| 114 | { "ics932s401", ics932s401 }, | ||
| 115 | { } | ||
| 116 | }; | ||
| 117 | MODULE_DEVICE_TABLE(i2c, ics932s401_id); | ||
| 118 | |||
| 119 | static struct i2c_driver ics932s401_driver = { | ||
| 120 | .class = I2C_CLASS_HWMON, | ||
| 121 | .driver = { | ||
| 122 | .name = "ics932s401", | ||
| 123 | }, | ||
| 124 | .probe = ics932s401_probe, | ||
| 125 | .remove = ics932s401_remove, | ||
