diff options
author | Guenter Roeck <linux@roeck-us.net> | 2015-03-28 11:03:10 -0400 |
---|---|---|
committer | Guenter Roeck <linux@roeck-us.net> | 2016-04-19 09:32:36 -0400 |
commit | 3c2e35126f2821be9b6f11dd5b772c68bcef4475 (patch) | |
tree | 8f4c476369fdc7a0b79f96de3f2499e1a8a41d97 | |
parent | 8e50e3c3f60c84b96956d37cbbf109b75569c6ba (diff) |
hwmon: (it87) Pass SIO base address as parameter to superio functions
This will let us support more than one chip on different SIO addresses
with the same driver.
Tested-by: Martin Blumenstingl <martin.blumenstingl@googlemail.com>
Signed-off-by: Guenter Roeck <linux@roeck-us.net>
-rw-r--r-- | drivers/hwmon/it87.c | 137 |
1 files changed, 72 insertions, 65 deletions
diff --git a/drivers/hwmon/it87.c b/drivers/hwmon/it87.c index 8f28f9b04150..4840f2d8c7b1 100644 --- a/drivers/hwmon/it87.c +++ b/drivers/hwmon/it87.c | |||
@@ -80,9 +80,9 @@ MODULE_PARM_DESC(force_id, "Override the detected device ID"); | |||
80 | 80 | ||
81 | static struct platform_device *it87_pdev; | 81 | static struct platform_device *it87_pdev; |
82 | 82 | ||
83 | #define REG 0x2e /* The register to read/write */ | 83 | #define REG_2E 0x2e /* The register to read/write */ |
84 | |||
84 | #define DEV 0x07 /* Register: Logical device select */ | 85 | #define DEV 0x07 /* Register: Logical device select */ |
85 | #define VAL 0x2f /* The value to read/write */ | ||
86 | #define PME 0x04 /* The device with the fan registers in it */ | 86 | #define PME 0x04 /* The device with the fan registers in it */ |
87 | 87 | ||
88 | /* The device with the IT8718F/IT8720F VID value in it */ | 88 | /* The device with the IT8718F/IT8720F VID value in it */ |
@@ -91,54 +91,54 @@ static struct platform_device *it87_pdev; | |||
91 | #define DEVID 0x20 /* Register: Device ID */ | 91 | #define DEVID 0x20 /* Register: Device ID */ |
92 | #define DEVREV 0x22 /* Register: Device Revision */ | 92 | #define DEVREV 0x22 /* Register: Device Revision */ |
93 | 93 | ||
94 | static inline int superio_inb(int reg) | 94 | static inline int superio_inb(int ioreg, int reg) |
95 | { | 95 | { |
96 | outb(reg, REG); | 96 | outb(reg, ioreg); |
97 | return inb(VAL); | 97 | return inb(ioreg + 1); |
98 | } | 98 | } |
99 | 99 | ||
100 | static inline void superio_outb(int reg, int val) | 100 | static inline void superio_outb(int ioreg, int reg, int val) |
101 | { | 101 | { |
102 | outb(reg, REG); | 102 | outb(reg, ioreg); |
103 | outb(val, VAL); | 103 | outb(val, ioreg + 1); |
104 | } | 104 | } |
105 | 105 | ||
106 | static int superio_inw(int reg) | 106 | static int superio_inw(int ioreg, int reg) |
107 | { | 107 | { |
108 | int val; | 108 | int val; |
109 | outb(reg++, REG); | 109 | outb(reg++, ioreg); |
110 | val = inb(VAL) << 8; | 110 | val = inb(ioreg + 1) << 8; |
111 | outb(reg, REG); | 111 | outb(reg, ioreg); |
112 | val |= inb(VAL); | 112 | val |= inb(ioreg + 1); |
113 | return val; | 113 | return val; |
114 | } | 114 | } |
115 | 115 | ||
116 | static inline void superio_select(int ldn) | 116 | static inline void superio_select(int ioreg, int ldn) |
117 | { | 117 | { |
118 | outb(DEV, REG); | 118 | outb(DEV, ioreg); |
119 | outb(ldn, VAL); | 119 | outb(ldn, ioreg + 1); |
120 | } | 120 | } |
121 | 121 | ||
122 | static inline int superio_enter(void) | 122 | static inline int superio_enter(int ioreg) |
123 | { | 123 | { |
124 | /* | 124 | /* |
125 | * Try to reserve REG and REG + 1 for exclusive access. | 125 | * Try to reserve ioreg and ioreg + 1 for exclusive access. |
126 | */ | 126 | */ |
127 | if (!request_muxed_region(REG, 2, DRVNAME)) | 127 | if (!request_muxed_region(ioreg, 2, DRVNAME)) |
128 | return -EBUSY; | 128 | return -EBUSY; |
129 | 129 | ||
130 | outb(0x87, REG); | 130 | outb(0x87, ioreg); |
131 | outb(0x01, REG); | 131 | outb(0x01, ioreg); |
132 | outb(0x55, REG); | 132 | outb(0x55, ioreg); |
133 | outb(0x55, REG); | 133 | outb(0x55, ioreg); |
134 | return 0; | 134 | return 0; |
135 | } | 135 | } |
136 | 136 | ||
137 | static inline void superio_exit(void) | 137 | static inline void superio_exit(int ioreg) |
138 | { | 138 | { |
139 | outb(0x02, REG); | 139 | outb(0x02, ioreg); |
140 | outb(0x02, VAL); | 140 | outb(0x02, ioreg + 1); |
141 | release_region(REG, 2); | 141 | release_region(ioreg, 2); |
142 | } | 142 | } |
143 | 143 | ||
144 | /* Logical device 4 registers */ | 144 | /* Logical device 4 registers */ |
@@ -1929,20 +1929,20 @@ static const struct attribute_group it87_group_label = { | |||
1929 | }; | 1929 | }; |
1930 | 1930 | ||
1931 | /* SuperIO detection - will change isa_address if a chip is found */ | 1931 | /* SuperIO detection - will change isa_address if a chip is found */ |
1932 | static int __init it87_find(unsigned short *address, | 1932 | static int __init it87_find(int sioaddr, unsigned short *address, |
1933 | struct it87_sio_data *sio_data) | 1933 | struct it87_sio_data *sio_data) |
1934 | { | 1934 | { |
1935 | int err; | 1935 | int err; |
1936 | u16 chip_type; | 1936 | u16 chip_type; |
1937 | const char *board_vendor, *board_name; | 1937 | const char *board_vendor, *board_name; |
1938 | const struct it87_devices *config; | 1938 | const struct it87_devices *config; |
1939 | 1939 | ||
1940 | err = superio_enter(); | 1940 | err = superio_enter(sioaddr); |
1941 | if (err) | 1941 | if (err) |
1942 | return err; | 1942 | return err; |
1943 | 1943 | ||
1944 | err = -ENODEV; | 1944 | err = -ENODEV; |
1945 | chip_type = force_id ? force_id : superio_inw(DEVID); | 1945 | chip_type = force_id ? force_id : superio_inw(sioaddr, DEVID); |
1946 | 1946 | ||
1947 | switch (chip_type) { | 1947 | switch (chip_type) { |
1948 | case IT8705F_DEVID: | 1948 | case IT8705F_DEVID: |
@@ -2005,20 +2005,20 @@ static int __init it87_find(unsigned short *address, | |||
2005 | goto exit; | 2005 | goto exit; |
2006 | } | 2006 | } |
2007 | 2007 | ||
2008 | superio_select(PME); | 2008 | superio_select(sioaddr, PME); |
2009 | if (!(superio_inb(IT87_ACT_REG) & 0x01)) { | 2009 | if (!(superio_inb(sioaddr, IT87_ACT_REG) & 0x01)) { |
2010 | pr_info("Device not activated, skipping\n"); | 2010 | pr_info("Device not activated, skipping\n"); |
2011 | goto exit; | 2011 | goto exit; |
2012 | } | 2012 | } |
2013 | 2013 | ||
2014 | *address = superio_inw(IT87_BASE_REG) & ~(IT87_EXTENT - 1); | 2014 | *address = superio_inw(sioaddr, IT87_BASE_REG) & ~(IT87_EXTENT - 1); |
2015 | if (*address == 0) { | 2015 | if (*address == 0) { |
2016 | pr_info("Base address not set, skipping\n"); | 2016 | pr_info("Base address not set, skipping\n"); |
2017 | goto exit; | 2017 | goto exit; |
2018 | } | 2018 | } |
2019 | 2019 | ||
2020 | err = 0; | 2020 | err = 0; |
2021 | sio_data->revision = superio_inb(DEVREV) & 0x0f; | 2021 | sio_data->revision = superio_inb(sioaddr, DEVREV) & 0x0f; |
2022 | pr_info("Found IT%04x%s chip at 0x%x, revision %d\n", chip_type, | 2022 | pr_info("Found IT%04x%s chip at 0x%x, revision %d\n", chip_type, |
2023 | it87_devices[sio_data->type].suffix, | 2023 | it87_devices[sio_data->type].suffix, |
2024 | *address, sio_data->revision); | 2024 | *address, sio_data->revision); |
@@ -2047,18 +2047,19 @@ static int __init it87_find(unsigned short *address, | |||
2047 | /* Read GPIO config and VID value from LDN 7 (GPIO) */ | 2047 | /* Read GPIO config and VID value from LDN 7 (GPIO) */ |
2048 | if (sio_data->type == it87) { | 2048 | if (sio_data->type == it87) { |
2049 | /* The IT8705F has a different LD number for GPIO */ | 2049 | /* The IT8705F has a different LD number for GPIO */ |
2050 | superio_select(5); | 2050 | superio_select(sioaddr, 5); |
2051 | sio_data->beep_pin = superio_inb(IT87_SIO_BEEP_PIN_REG) & 0x3f; | 2051 | sio_data->beep_pin = superio_inb(sioaddr, |
2052 | IT87_SIO_BEEP_PIN_REG) & 0x3f; | ||
2052 | } else if (sio_data->type == it8783) { | 2053 | } else if (sio_data->type == it8783) { |
2053 | int reg25, reg27, reg2a, reg2c, regef; | 2054 | int reg25, reg27, reg2a, reg2c, regef; |
2054 | 2055 | ||
2055 | superio_select(GPIO); | 2056 | superio_select(sioaddr, GPIO); |
2056 | 2057 | ||
2057 | reg25 = superio_inb(IT87_SIO_GPIO1_REG); | 2058 | reg25 = superio_inb(sioaddr, IT87_SIO_GPIO1_REG); |
2058 | reg27 = superio_inb(IT87_SIO_GPIO3_REG); | 2059 | reg27 = superio_inb(sioaddr, IT87_SIO_GPIO3_REG); |
2059 | reg2a = superio_inb(IT87_SIO_PINX1_REG); | 2060 | reg2a = superio_inb(sioaddr, IT87_SIO_PINX1_REG); |
2060 | reg2c = superio_inb(IT87_SIO_PINX2_REG); | 2061 | reg2c = superio_inb(sioaddr, IT87_SIO_PINX2_REG); |
2061 | regef = superio_inb(IT87_SIO_SPI_REG); | 2062 | regef = superio_inb(sioaddr, IT87_SIO_SPI_REG); |
2062 | 2063 | ||
2063 | /* Check if fan3 is there or not */ | 2064 | /* Check if fan3 is there or not */ |
2064 | if ((reg27 & (1 << 0)) || !(reg2c & (1 << 2))) | 2065 | if ((reg27 & (1 << 0)) || !(reg2c & (1 << 2))) |
@@ -2101,7 +2102,8 @@ static int __init it87_find(unsigned short *address, | |||
2101 | */ | 2102 | */ |
2102 | if (!(reg2c & (1 << 1))) { | 2103 | if (!(reg2c & (1 << 1))) { |
2103 | reg2c |= (1 << 1); | 2104 | reg2c |= (1 << 1); |
2104 | superio_outb(IT87_SIO_PINX2_REG, reg2c); | 2105 | superio_outb(sioaddr, IT87_SIO_PINX2_REG, |
2106 | reg2c); | ||
2105 | pr_notice("Routing internal VCCH5V to in7.\n"); | 2107 | pr_notice("Routing internal VCCH5V to in7.\n"); |
2106 | } | 2108 | } |
2107 | pr_notice("in7 routed to internal voltage divider, with external pin disabled.\n"); | 2109 | pr_notice("in7 routed to internal voltage divider, with external pin disabled.\n"); |
@@ -2113,13 +2115,14 @@ static int __init it87_find(unsigned short *address, | |||
2113 | if (reg2c & (1 << 1)) | 2115 | if (reg2c & (1 << 1)) |
2114 | sio_data->internal |= (1 << 1); | 2116 | sio_data->internal |= (1 << 1); |
2115 | 2117 | ||
2116 | sio_data->beep_pin = superio_inb(IT87_SIO_BEEP_PIN_REG) & 0x3f; | 2118 | sio_data->beep_pin = superio_inb(sioaddr, |
2119 | IT87_SIO_BEEP_PIN_REG) & 0x3f; | ||
2117 | } else if (sio_data->type == it8603) { | 2120 | } else if (sio_data->type == it8603) { |
2118 | int reg27, reg29; | 2121 | int reg27, reg29; |
2119 | 2122 | ||
2120 | superio_select(GPIO); | 2123 | superio_select(sioaddr, GPIO); |
2121 | 2124 | ||
2122 | reg27 = superio_inb(IT87_SIO_GPIO3_REG); | 2125 | reg27 = superio_inb(sioaddr, IT87_SIO_GPIO3_REG); |
2123 | 2126 | ||
2124 | /* Check if fan3 is there or not */ | 2127 | /* Check if fan3 is there or not */ |
2125 | if (reg27 & (1 << 6)) | 2128 | if (reg27 & (1 << 6)) |
@@ -2128,7 +2131,7 @@ static int __init it87_find(unsigned short *address, | |||
2128 | sio_data->skip_fan |= (1 << 2); | 2131 | sio_data->skip_fan |= (1 << 2); |
2129 | 2132 | ||
2130 | /* Check if fan2 is there or not */ | 2133 | /* Check if fan2 is there or not */ |
2131 | reg29 = superio_inb(IT87_SIO_GPIO5_REG); | 2134 | reg29 = superio_inb(sioaddr, IT87_SIO_GPIO5_REG); |
2132 | if (reg29 & (1 << 1)) | 2135 | if (reg29 & (1 << 1)) |
2133 | sio_data->skip_pwm |= (1 << 1); | 2136 | sio_data->skip_pwm |= (1 << 1); |
2134 | if (reg29 & (1 << 2)) | 2137 | if (reg29 & (1 << 2)) |
@@ -2137,38 +2140,39 @@ static int __init it87_find(unsigned short *address, | |||
2137 | sio_data->skip_in |= (1 << 5); /* No VIN5 */ | 2140 | sio_data->skip_in |= (1 << 5); /* No VIN5 */ |
2138 | sio_data->skip_in |= (1 << 6); /* No VIN6 */ | 2141 | sio_data->skip_in |= (1 << 6); /* No VIN6 */ |
2139 | 2142 | ||
2140 | sio_data->beep_pin = superio_inb(IT87_SIO_BEEP_PIN_REG) & 0x3f; | 2143 | sio_data->beep_pin = superio_inb(sioaddr, |
2144 | IT87_SIO_BEEP_PIN_REG) & 0x3f; | ||
2141 | } else if (sio_data->type == it8620) { | 2145 | } else if (sio_data->type == it8620) { |
2142 | int reg; | 2146 | int reg; |
2143 | 2147 | ||
2144 | superio_select(GPIO); | 2148 | superio_select(sioaddr, GPIO); |
2145 | 2149 | ||
2146 | /* Check for pwm5 */ | 2150 | /* Check for pwm5 */ |
2147 | reg = superio_inb(IT87_SIO_GPIO1_REG); | 2151 | reg = superio_inb(sioaddr, IT87_SIO_GPIO1_REG); |
2148 | if (reg & (1 << 6)) | 2152 | if (reg & (1 << 6)) |
2149 | sio_data->skip_pwm |= (1 << 4); | 2153 | sio_data->skip_pwm |= (1 << 4); |
2150 | 2154 | ||
2151 | /* Check for fan4, fan5 */ | 2155 | /* Check for fan4, fan5 */ |
2152 | reg = superio_inb(IT87_SIO_GPIO2_REG); | 2156 | reg = superio_inb(sioaddr, IT87_SIO_GPIO2_REG); |
2153 | if (!(reg & (1 << 5))) | 2157 | if (!(reg & (1 << 5))) |
2154 | sio_data->skip_fan |= (1 << 3); | 2158 | sio_data->skip_fan |= (1 << 3); |
2155 | if (!(reg & (1 << 4))) | 2159 | if (!(reg & (1 << 4))) |
2156 | sio_data->skip_fan |= (1 << 4); | 2160 | sio_data->skip_fan |= (1 << 4); |
2157 | 2161 | ||
2158 | /* Check for pwm3, fan3 */ | 2162 | /* Check for pwm3, fan3 */ |
2159 | reg = superio_inb(IT87_SIO_GPIO3_REG); | 2163 | reg = superio_inb(sioaddr, IT87_SIO_GPIO3_REG); |
2160 | if (reg & (1 << 6)) | 2164 | if (reg & (1 << 6)) |
2161 | sio_data->skip_pwm |= (1 << 2); | 2165 | sio_data->skip_pwm |= (1 << 2); |
2162 | if (reg & (1 << 7)) | 2166 | if (reg & (1 << 7)) |
2163 | sio_data->skip_fan |= (1 << 2); | 2167 | sio_data->skip_fan |= (1 << 2); |
2164 | 2168 | ||
2165 | /* Check for pwm4 */ | 2169 | /* Check for pwm4 */ |
2166 | reg = superio_inb(IT87_SIO_GPIO4_REG); | 2170 | reg = superio_inb(sioaddr, IT87_SIO_GPIO4_REG); |
2167 | if (!(reg & (1 << 2))) | 2171 | if (!(reg & (1 << 2))) |
2168 | sio_data->skip_pwm |= (1 << 3); | 2172 | sio_data->skip_pwm |= (1 << 3); |
2169 | 2173 | ||
2170 | /* Check for pwm2, fan2 */ | 2174 | /* Check for pwm2, fan2 */ |
2171 | reg = superio_inb(IT87_SIO_GPIO5_REG); | 2175 | reg = superio_inb(sioaddr, IT87_SIO_GPIO5_REG); |
2172 | if (reg & (1 << 1)) | 2176 | if (reg & (1 << 1)) |
2173 | sio_data->skip_pwm |= (1 << 1); | 2177 | sio_data->skip_pwm |= (1 << 1); |
2174 | if (reg & (1 << 2)) | 2178 | if (reg & (1 << 2)) |
@@ -2179,14 +2183,15 @@ static int __init it87_find(unsigned short *address, | |||
2179 | sio_data->skip_fan |= (1 << 5); | 2183 | sio_data->skip_fan |= (1 << 5); |
2180 | } | 2184 | } |
2181 | 2185 | ||
2182 | sio_data->beep_pin = superio_inb(IT87_SIO_BEEP_PIN_REG) & 0x3f; | 2186 | sio_data->beep_pin = superio_inb(sioaddr, |
2187 | IT87_SIO_BEEP_PIN_REG) & 0x3f; | ||
2183 | } else { | 2188 | } else { |
2184 | int reg; | 2189 | int reg; |
2185 | bool uart6; | 2190 | bool uart6; |
2186 | 2191 | ||
2187 | superio_select(GPIO); | 2192 | superio_select(sioaddr, GPIO); |
2188 | 2193 | ||
2189 | reg = superio_inb(IT87_SIO_GPIO3_REG); | 2194 | reg = superio_inb(sioaddr, IT87_SIO_GPIO3_REG); |
2190 | if (!sio_data->skip_vid) { | 2195 | if (!sio_data->skip_vid) { |
2191 | /* We need at least 4 VID pins */ | 2196 | /* We need at least 4 VID pins */ |
2192 | if (reg & 0x0f) { | 2197 | if (reg & 0x0f) { |
@@ -2202,7 +2207,7 @@ static int __init it87_find(unsigned short *address, | |||
2202 | sio_data->skip_fan |= (1 << 2); | 2207 | sio_data->skip_fan |= (1 << 2); |
2203 | 2208 | ||
2204 | /* Check if fan2 is there or not */ | 2209 | /* Check if fan2 is there or not */ |
2205 | reg = superio_inb(IT87_SIO_GPIO5_REG); | 2210 | reg = superio_inb(sioaddr, IT87_SIO_GPIO5_REG); |
2206 | if (reg & (1 << 1)) | 2211 | if (reg & (1 << 1)) |
2207 | sio_data->skip_pwm |= (1 << 1); | 2212 | sio_data->skip_pwm |= (1 << 1); |
2208 | if (reg & (1 << 2)) | 2213 | if (reg & (1 << 2)) |
@@ -2210,9 +2215,10 @@ static int __init it87_find(unsigned short *address, | |||
2210 | 2215 | ||
2211 | if ((sio_data->type == it8718 || sio_data->type == it8720) | 2216 | if ((sio_data->type == it8718 || sio_data->type == it8720) |
2212 | && !(sio_data->skip_vid)) | 2217 | && !(sio_data->skip_vid)) |
2213 | sio_data->vid_value = superio_inb(IT87_SIO_VID_REG); | 2218 | sio_data->vid_value = superio_inb(sioaddr, |
2219 | IT87_SIO_VID_REG); | ||
2214 | 2220 | ||
2215 | reg = superio_inb(IT87_SIO_PINX2_REG); | 2221 | reg = superio_inb(sioaddr, IT87_SIO_PINX2_REG); |
2216 | 2222 | ||
2217 | uart6 = sio_data->type == it8782 && (reg & (1 << 2)); | 2223 | uart6 = sio_data->type == it8782 && (reg & (1 << 2)); |
2218 | 2224 | ||
@@ -2232,7 +2238,7 @@ static int __init it87_find(unsigned short *address, | |||
2232 | */ | 2238 | */ |
2233 | if ((sio_data->type == it8720 || uart6) && !(reg & (1 << 1))) { | 2239 | if ((sio_data->type == it8720 || uart6) && !(reg & (1 << 1))) { |
2234 | reg |= (1 << 1); | 2240 | reg |= (1 << 1); |
2235 | superio_outb(IT87_SIO_PINX2_REG, reg); | 2241 | superio_outb(sioaddr, IT87_SIO_PINX2_REG, reg); |
2236 | pr_notice("Routing internal VCCH to in7\n"); | 2242 | pr_notice("Routing internal VCCH to in7\n"); |
2237 | } | 2243 | } |
2238 | if (reg & (1 << 0)) | 2244 | if (reg & (1 << 0)) |
@@ -2254,7 +2260,8 @@ static int __init it87_find(unsigned short *address, | |||
2254 | sio_data->skip_temp |= (1 << 2); | 2260 | sio_data->skip_temp |= (1 << 2); |
2255 | } | 2261 | } |
2256 | 2262 | ||
2257 | sio_data->beep_pin = superio_inb(IT87_SIO_BEEP_PIN_REG) & 0x3f; | 2263 | sio_data->beep_pin = superio_inb(sioaddr, |
2264 | IT87_SIO_BEEP_PIN_REG) & 0x3f; | ||
2258 | } | 2265 | } |
2259 | if (sio_data->beep_pin) | 2266 | if (sio_data->beep_pin) |
2260 | pr_info("Beeping is supported\n"); | 2267 | pr_info("Beeping is supported\n"); |
@@ -2279,7 +2286,7 @@ static int __init it87_find(unsigned short *address, | |||
2279 | } | 2286 | } |
2280 | 2287 | ||
2281 | exit: | 2288 | exit: |
2282 | superio_exit(); | 2289 | superio_exit(sioaddr); |
2283 | return err; | 2290 | return err; |
2284 | } | 2291 | } |
2285 | 2292 | ||
@@ -2939,7 +2946,7 @@ static int __init sm_it87_init(void) | |||
2939 | struct it87_sio_data sio_data; | 2946 | struct it87_sio_data sio_data; |
2940 | 2947 | ||
2941 | memset(&sio_data, 0, sizeof(struct it87_sio_data)); | 2948 | memset(&sio_data, 0, sizeof(struct it87_sio_data)); |
2942 | err = it87_find(&isa_address, &sio_data); | 2949 | err = it87_find(REG_2E, &isa_address, &sio_data); |
2943 | if (err) | 2950 | if (err) |
2944 | return err; | 2951 | return err; |
2945 | err = platform_driver_register(&it87_driver); | 2952 | err = platform_driver_register(&it87_driver); |