1/*- 2 * Copyright (c) 2000 Matthew C. Forman 3 * 4 * Based (heavily) on alpm.c which is: 5 * 6 * Copyright (c) 1998, 1999 Nicolas Souchu 7 * All rights reserved. 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that the following conditions 11 * are met: 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 2. Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in the 16 * documentation and/or other materials provided with the distribution. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 19 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 22 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 24 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 26 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 27 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 28 * SUCH DAMAGE. 29 */ 30 31/* 32 * Power management function/SMBus function support for the AMD 756 chip. 33 */ 34 35#include <sys/cdefs.h>
| 1/*- 2 * Copyright (c) 2000 Matthew C. Forman 3 * 4 * Based (heavily) on alpm.c which is: 5 * 6 * Copyright (c) 1998, 1999 Nicolas Souchu 7 * All rights reserved. 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that the following conditions 11 * are met: 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 2. Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in the 16 * documentation and/or other materials provided with the distribution. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 19 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 22 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 24 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 26 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 27 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 28 * SUCH DAMAGE. 29 */ 30 31/* 32 * Power management function/SMBus function support for the AMD 756 chip. 33 */ 34 35#include <sys/cdefs.h>
|
36__FBSDID("$FreeBSD: head/sys/pci/amdpm.c 162234 2006-09-11 20:52:41Z jhb $");
| 36__FBSDID("$FreeBSD: head/sys/pci/amdpm.c 165951 2007-01-11 19:56:24Z jhb $");
|
37 38#include <sys/param.h>
| 37 38#include <sys/param.h>
|
| 39#include <sys/bus.h>
|
39#include <sys/kernel.h>
| 40#include <sys/kernel.h>
|
40#include <sys/systm.h>
| 41#include <sys/lock.h>
|
41#include <sys/module.h>
| 42#include <sys/module.h>
|
42#include <sys/bus.h> 43#include <sys/uio.h>
| 43#include <sys/mutex.h> 44#include <sys/systm.h>
|
44 45#include <machine/bus.h> 46#include <machine/resource.h> 47#include <sys/rman.h> 48 49#include <dev/pci/pcivar.h> 50#include <dev/pci/pcireg.h> 51
| 45 46#include <machine/bus.h> 47#include <machine/resource.h> 48#include <sys/rman.h> 49 50#include <dev/pci/pcivar.h> 51#include <dev/pci/pcireg.h> 52
|
52#include <dev/iicbus/iiconf.h>
| |
53#include <dev/smbus/smbconf.h> 54#include "smbus_if.h" 55 56#define AMDPM_DEBUG(x) if (amdpm_debug) (x) 57 58#ifdef DEBUG 59static int amdpm_debug = 1; 60#else 61static int amdpm_debug = 0; 62#endif 63 64#define AMDPM_VENDORID_AMD 0x1022 65#define AMDPM_DEVICEID_AMD756PM 0x740b 66#define AMDPM_DEVICEID_AMD766PM 0x7413 67#define AMDPM_DEVICEID_AMD768PM 0x7443 68#define AMDPM_DEVICEID_AMD8111PM 0x746B 69 70/* nVidia nForce chipset */ 71#define AMDPM_VENDORID_NVIDIA 0x10de 72#define AMDPM_DEVICEID_NF_SMB 0x01b4 73 74/* PCI Configuration space registers */ 75#define AMDPCI_PMBASE 0x58 76#define NFPCI_PMBASE 0x14 77 78#define AMDPCI_GEN_CONFIG_PM 0x41 79#define AMDPCI_PMIOEN (1<<7) 80 81#define AMDPCI_SCIINT_CONFIG_PM 0x42 82#define AMDPCI_SCISEL_IRQ11 11 83 84#define AMDPCI_REVID 0x08 85 86/* 87 * I/O registers. 88 * Base address programmed via AMDPCI_PMBASE. 89 */ 90 91#define AMDSMB_GLOBAL_STATUS (0x00) 92#define AMDSMB_GS_TO_STS (1<<5) 93#define AMDSMB_GS_HCYC_STS (1<<4) 94#define AMDSMB_GS_HST_STS (1<<3) 95#define AMDSMB_GS_PRERR_STS (1<<2) 96#define AMDSMB_GS_COL_STS (1<<1) 97#define AMDSMB_GS_ABRT_STS (1<<0) 98#define AMDSMB_GS_CLEAR_STS (AMDSMB_GS_TO_STS|AMDSMB_GS_HCYC_STS|AMDSMB_GS_PRERR_STS|AMDSMB_GS_COL_STS|AMDSMB_GS_ABRT_STS) 99 100#define AMDSMB_GLOBAL_ENABLE (0x02) 101#define AMDSMB_GE_ABORT (1<<5) 102#define AMDSMB_GE_HCYC_EN (1<<4) 103#define AMDSMB_GE_HOST_STC (1<<3) 104#define AMDSMB_GE_CYC_QUICK 0 105#define AMDSMB_GE_CYC_BYTE 1 106#define AMDSMB_GE_CYC_BDATA 2 107#define AMDSMB_GE_CYC_WDATA 3 108#define AMDSMB_GE_CYC_PROCCALL 4 109#define AMDSMB_GE_CYC_BLOCK 5 110
| 53#include <dev/smbus/smbconf.h> 54#include "smbus_if.h" 55 56#define AMDPM_DEBUG(x) if (amdpm_debug) (x) 57 58#ifdef DEBUG 59static int amdpm_debug = 1; 60#else 61static int amdpm_debug = 0; 62#endif 63 64#define AMDPM_VENDORID_AMD 0x1022 65#define AMDPM_DEVICEID_AMD756PM 0x740b 66#define AMDPM_DEVICEID_AMD766PM 0x7413 67#define AMDPM_DEVICEID_AMD768PM 0x7443 68#define AMDPM_DEVICEID_AMD8111PM 0x746B 69 70/* nVidia nForce chipset */ 71#define AMDPM_VENDORID_NVIDIA 0x10de 72#define AMDPM_DEVICEID_NF_SMB 0x01b4 73 74/* PCI Configuration space registers */ 75#define AMDPCI_PMBASE 0x58 76#define NFPCI_PMBASE 0x14 77 78#define AMDPCI_GEN_CONFIG_PM 0x41 79#define AMDPCI_PMIOEN (1<<7) 80 81#define AMDPCI_SCIINT_CONFIG_PM 0x42 82#define AMDPCI_SCISEL_IRQ11 11 83 84#define AMDPCI_REVID 0x08 85 86/* 87 * I/O registers. 88 * Base address programmed via AMDPCI_PMBASE. 89 */ 90 91#define AMDSMB_GLOBAL_STATUS (0x00) 92#define AMDSMB_GS_TO_STS (1<<5) 93#define AMDSMB_GS_HCYC_STS (1<<4) 94#define AMDSMB_GS_HST_STS (1<<3) 95#define AMDSMB_GS_PRERR_STS (1<<2) 96#define AMDSMB_GS_COL_STS (1<<1) 97#define AMDSMB_GS_ABRT_STS (1<<0) 98#define AMDSMB_GS_CLEAR_STS (AMDSMB_GS_TO_STS|AMDSMB_GS_HCYC_STS|AMDSMB_GS_PRERR_STS|AMDSMB_GS_COL_STS|AMDSMB_GS_ABRT_STS) 99 100#define AMDSMB_GLOBAL_ENABLE (0x02) 101#define AMDSMB_GE_ABORT (1<<5) 102#define AMDSMB_GE_HCYC_EN (1<<4) 103#define AMDSMB_GE_HOST_STC (1<<3) 104#define AMDSMB_GE_CYC_QUICK 0 105#define AMDSMB_GE_CYC_BYTE 1 106#define AMDSMB_GE_CYC_BDATA 2 107#define AMDSMB_GE_CYC_WDATA 3 108#define AMDSMB_GE_CYC_PROCCALL 4 109#define AMDSMB_GE_CYC_BLOCK 5 110
|
| 111#define LSB 0x1 /* XXX: Better name: Read/Write? */ 112
|
111#define AMDSMB_HSTADDR (0x04) 112#define AMDSMB_HSTDATA (0x06) 113#define AMDSMB_HSTCMD (0x08) 114#define AMDSMB_HSTDFIFO (0x09) 115#define AMDSMB_HSLVDATA (0x0A) 116#define AMDSMB_HSLVDA (0x0C) 117#define AMDSMB_HSLVDDR (0x0E) 118#define AMDSMB_SNPADDR (0x0F) 119 120struct amdpm_softc { 121 int base; 122 int rid; 123 struct resource *res; 124 bus_space_tag_t smbst; 125 bus_space_handle_t smbsh;
| 113#define AMDSMB_HSTADDR (0x04) 114#define AMDSMB_HSTDATA (0x06) 115#define AMDSMB_HSTCMD (0x08) 116#define AMDSMB_HSTDFIFO (0x09) 117#define AMDSMB_HSLVDATA (0x0A) 118#define AMDSMB_HSLVDA (0x0C) 119#define AMDSMB_HSLVDDR (0x0E) 120#define AMDSMB_SNPADDR (0x0F) 121 122struct amdpm_softc { 123 int base; 124 int rid; 125 struct resource *res; 126 bus_space_tag_t smbst; 127 bus_space_handle_t smbsh;
|
126
| |
127 device_t smbus;
| 128 device_t smbus;
|
| 129 struct mtx lock;
|
128}; 129
| 130}; 131
|
| 132#define AMDPM_LOCK(amdpm) mtx_lock(&(amdpm)->lock) 133#define AMDPM_UNLOCK(amdpm) mtx_unlock(&(amdpm)->lock) 134#define AMDPM_LOCK_ASSERT(amdpm) mtx_assert(&(amdpm)->lock, MA_OWNED) 135
|
130#define AMDPM_SMBINB(amdpm,register) \ 131 (bus_space_read_1(amdpm->smbst, amdpm->smbsh, register)) 132#define AMDPM_SMBOUTB(amdpm,register,value) \ 133 (bus_space_write_1(amdpm->smbst, amdpm->smbsh, register, value)) 134#define AMDPM_SMBINW(amdpm,register) \ 135 (bus_space_read_2(amdpm->smbst, amdpm->smbsh, register)) 136#define AMDPM_SMBOUTW(amdpm,register,value) \ 137 (bus_space_write_2(amdpm->smbst, amdpm->smbsh, register, value)) 138
| 136#define AMDPM_SMBINB(amdpm,register) \ 137 (bus_space_read_1(amdpm->smbst, amdpm->smbsh, register)) 138#define AMDPM_SMBOUTB(amdpm,register,value) \ 139 (bus_space_write_1(amdpm->smbst, amdpm->smbsh, register, value)) 140#define AMDPM_SMBINW(amdpm,register) \ 141 (bus_space_read_2(amdpm->smbst, amdpm->smbsh, register)) 142#define AMDPM_SMBOUTW(amdpm,register,value) \ 143 (bus_space_write_2(amdpm->smbst, amdpm->smbsh, register, value)) 144
|
| 145static int amdpm_detach(device_t dev); 146
|
139static int 140amdpm_probe(device_t dev) 141{ 142 u_long base; 143 u_int16_t vid; 144 u_int16_t did; 145 146 vid = pci_get_vendor(dev); 147 did = pci_get_device(dev); 148 if ((vid == AMDPM_VENDORID_AMD) && 149 ((did == AMDPM_DEVICEID_AMD756PM) || 150 (did == AMDPM_DEVICEID_AMD766PM) || 151 (did == AMDPM_DEVICEID_AMD768PM) || 152 (did == AMDPM_DEVICEID_AMD8111PM))) { 153 device_set_desc(dev, "AMD 756/766/768/8111 Power Management Controller"); 154 155 /* 156 * We have to do this, since the BIOS won't give us the 157 * resource info (not mine, anyway). 158 */ 159 base = pci_read_config(dev, AMDPCI_PMBASE, 4); 160 base &= 0xff00; 161 bus_set_resource(dev, SYS_RES_IOPORT, AMDPCI_PMBASE, 162 base+0xe0, 32); 163 return (BUS_PROBE_DEFAULT); 164 } 165 166 if ((vid == AMDPM_VENDORID_NVIDIA) && 167 (did == AMDPM_DEVICEID_NF_SMB)) { 168 device_set_desc(dev, "nForce SMBus Controller"); 169 170 /* 171 * We have to do this, since the BIOS won't give us the 172 * resource info (not mine, anyway). 173 */ 174 base = pci_read_config(dev, NFPCI_PMBASE, 4); 175 base &= 0xff00; 176 bus_set_resource(dev, SYS_RES_IOPORT, NFPCI_PMBASE, 177 base, 32); 178 179 return (BUS_PROBE_DEFAULT); 180 } 181 182 return ENXIO; 183} 184 185static int 186amdpm_attach(device_t dev) 187{ 188 struct amdpm_softc *amdpm_sc = device_get_softc(dev); 189 u_char val_b; 190 191 /* Enable I/O block access */ 192 val_b = pci_read_config(dev, AMDPCI_GEN_CONFIG_PM, 1); 193 pci_write_config(dev, AMDPCI_GEN_CONFIG_PM, val_b | AMDPCI_PMIOEN, 1); 194 195 /* Allocate I/O space */ 196 if (pci_get_vendor(dev) == AMDPM_VENDORID_AMD) 197 amdpm_sc->rid = AMDPCI_PMBASE; 198 else 199 amdpm_sc->rid = NFPCI_PMBASE; 200 amdpm_sc->res = bus_alloc_resource_any(dev, SYS_RES_IOPORT, 201 &amdpm_sc->rid, RF_ACTIVE); 202 203 if (amdpm_sc->res == NULL) { 204 device_printf(dev, "could not map i/o space\n"); 205 return (ENXIO); 206 } 207 208 amdpm_sc->smbst = rman_get_bustag(amdpm_sc->res); 209 amdpm_sc->smbsh = rman_get_bushandle(amdpm_sc->res);
| 147static int 148amdpm_probe(device_t dev) 149{ 150 u_long base; 151 u_int16_t vid; 152 u_int16_t did; 153 154 vid = pci_get_vendor(dev); 155 did = pci_get_device(dev); 156 if ((vid == AMDPM_VENDORID_AMD) && 157 ((did == AMDPM_DEVICEID_AMD756PM) || 158 (did == AMDPM_DEVICEID_AMD766PM) || 159 (did == AMDPM_DEVICEID_AMD768PM) || 160 (did == AMDPM_DEVICEID_AMD8111PM))) { 161 device_set_desc(dev, "AMD 756/766/768/8111 Power Management Controller"); 162 163 /* 164 * We have to do this, since the BIOS won't give us the 165 * resource info (not mine, anyway). 166 */ 167 base = pci_read_config(dev, AMDPCI_PMBASE, 4); 168 base &= 0xff00; 169 bus_set_resource(dev, SYS_RES_IOPORT, AMDPCI_PMBASE, 170 base+0xe0, 32); 171 return (BUS_PROBE_DEFAULT); 172 } 173 174 if ((vid == AMDPM_VENDORID_NVIDIA) && 175 (did == AMDPM_DEVICEID_NF_SMB)) { 176 device_set_desc(dev, "nForce SMBus Controller"); 177 178 /* 179 * We have to do this, since the BIOS won't give us the 180 * resource info (not mine, anyway). 181 */ 182 base = pci_read_config(dev, NFPCI_PMBASE, 4); 183 base &= 0xff00; 184 bus_set_resource(dev, SYS_RES_IOPORT, NFPCI_PMBASE, 185 base, 32); 186 187 return (BUS_PROBE_DEFAULT); 188 } 189 190 return ENXIO; 191} 192 193static int 194amdpm_attach(device_t dev) 195{ 196 struct amdpm_softc *amdpm_sc = device_get_softc(dev); 197 u_char val_b; 198 199 /* Enable I/O block access */ 200 val_b = pci_read_config(dev, AMDPCI_GEN_CONFIG_PM, 1); 201 pci_write_config(dev, AMDPCI_GEN_CONFIG_PM, val_b | AMDPCI_PMIOEN, 1); 202 203 /* Allocate I/O space */ 204 if (pci_get_vendor(dev) == AMDPM_VENDORID_AMD) 205 amdpm_sc->rid = AMDPCI_PMBASE; 206 else 207 amdpm_sc->rid = NFPCI_PMBASE; 208 amdpm_sc->res = bus_alloc_resource_any(dev, SYS_RES_IOPORT, 209 &amdpm_sc->rid, RF_ACTIVE); 210 211 if (amdpm_sc->res == NULL) { 212 device_printf(dev, "could not map i/o space\n"); 213 return (ENXIO); 214 } 215 216 amdpm_sc->smbst = rman_get_bustag(amdpm_sc->res); 217 amdpm_sc->smbsh = rman_get_bushandle(amdpm_sc->res);
|
| 218 mtx_init(&amdpm_sc->lock, device_get_nameunit(dev), "amdpm", MTX_DEF);
|
210 211 /* Allocate a new smbus device */ 212 amdpm_sc->smbus = device_add_child(dev, "smbus", -1);
| 219 220 /* Allocate a new smbus device */ 221 amdpm_sc->smbus = device_add_child(dev, "smbus", -1);
|
213 if (!amdpm_sc->smbus)
| 222 if (!amdpm_sc->smbus) { 223 amdpm_detach(dev);
|
214 return (EINVAL);
| 224 return (EINVAL);
|
| 225 }
|
215 216 bus_generic_attach(dev); 217 218 return (0); 219} 220 221static int 222amdpm_detach(device_t dev) 223{ 224 struct amdpm_softc *amdpm_sc = device_get_softc(dev); 225 226 if (amdpm_sc->smbus) { 227 device_delete_child(dev, amdpm_sc->smbus); 228 amdpm_sc->smbus = NULL; 229 } 230
| 226 227 bus_generic_attach(dev); 228 229 return (0); 230} 231 232static int 233amdpm_detach(device_t dev) 234{ 235 struct amdpm_softc *amdpm_sc = device_get_softc(dev); 236 237 if (amdpm_sc->smbus) { 238 device_delete_child(dev, amdpm_sc->smbus); 239 amdpm_sc->smbus = NULL; 240 } 241
|
| 242 mtx_destroy(&amdpm_sc->lock);
|
231 if (amdpm_sc->res) 232 bus_release_resource(dev, SYS_RES_IOPORT, amdpm_sc->rid, 233 amdpm_sc->res); 234 235 return (0); 236} 237 238static int 239amdpm_callback(device_t dev, int index, void *data) 240{ 241 int error = 0; 242 243 switch (index) { 244 case SMB_REQUEST_BUS: 245 case SMB_RELEASE_BUS: 246 break; 247 default: 248 error = EINVAL; 249 } 250 251 return (error); 252} 253 254static int 255amdpm_clear(struct amdpm_softc *sc) 256{
| 243 if (amdpm_sc->res) 244 bus_release_resource(dev, SYS_RES_IOPORT, amdpm_sc->rid, 245 amdpm_sc->res); 246 247 return (0); 248} 249 250static int 251amdpm_callback(device_t dev, int index, void *data) 252{ 253 int error = 0; 254 255 switch (index) { 256 case SMB_REQUEST_BUS: 257 case SMB_RELEASE_BUS: 258 break; 259 default: 260 error = EINVAL; 261 } 262 263 return (error); 264} 265 266static int 267amdpm_clear(struct amdpm_softc *sc) 268{
|
| 269 270 AMDPM_LOCK_ASSERT(sc);
|
257 AMDPM_SMBOUTW(sc, AMDSMB_GLOBAL_STATUS, AMDSMB_GS_CLEAR_STS); 258 DELAY(10); 259 260 return (0); 261} 262 263#if 0 264static int 265amdpm_abort(struct amdpm_softc *sc) 266{ 267 u_short l; 268 269 l = AMDPM_SMBINW(sc, AMDSMB_GLOBAL_ENABLE); 270 AMDPM_SMBOUTW(sc, AMDSMB_GLOBAL_ENABLE, l | AMDSMB_GE_ABORT); 271 272 return (0); 273} 274#endif 275 276static int 277amdpm_idle(struct amdpm_softc *sc) 278{ 279 u_short sts; 280
| 271 AMDPM_SMBOUTW(sc, AMDSMB_GLOBAL_STATUS, AMDSMB_GS_CLEAR_STS); 272 DELAY(10); 273 274 return (0); 275} 276 277#if 0 278static int 279amdpm_abort(struct amdpm_softc *sc) 280{ 281 u_short l; 282 283 l = AMDPM_SMBINW(sc, AMDSMB_GLOBAL_ENABLE); 284 AMDPM_SMBOUTW(sc, AMDSMB_GLOBAL_ENABLE, l | AMDSMB_GE_ABORT); 285 286 return (0); 287} 288#endif 289 290static int 291amdpm_idle(struct amdpm_softc *sc) 292{ 293 u_short sts; 294
|
| 295 AMDPM_LOCK_ASSERT(sc);
|
281 sts = AMDPM_SMBINW(sc, AMDSMB_GLOBAL_STATUS); 282 283 AMDPM_DEBUG(printf("amdpm: busy? STS=0x%x\n", sts)); 284 285 return (~(sts & AMDSMB_GS_HST_STS)); 286} 287 288/* 289 * Poll the SMBus controller 290 */ 291static int 292amdpm_wait(struct amdpm_softc *sc) 293{ 294 int count = 10000; 295 u_short sts = 0; 296 int error; 297
| 296 sts = AMDPM_SMBINW(sc, AMDSMB_GLOBAL_STATUS); 297 298 AMDPM_DEBUG(printf("amdpm: busy? STS=0x%x\n", sts)); 299 300 return (~(sts & AMDSMB_GS_HST_STS)); 301} 302 303/* 304 * Poll the SMBus controller 305 */ 306static int 307amdpm_wait(struct amdpm_softc *sc) 308{ 309 int count = 10000; 310 u_short sts = 0; 311 int error; 312
|
| 313 AMDPM_LOCK_ASSERT(sc);
|
298 /* Wait for command to complete (SMBus controller is idle) */ 299 while(count--) { 300 DELAY(10); 301 sts = AMDPM_SMBINW(sc, AMDSMB_GLOBAL_STATUS); 302 if (!(sts & AMDSMB_GS_HST_STS)) 303 break; 304 } 305 306 AMDPM_DEBUG(printf("amdpm: STS=0x%x (count=%d)\n", sts, count)); 307 308 error = SMB_ENOERR; 309 310 if (!count) 311 error |= SMB_ETIMEOUT; 312 313 if (sts & AMDSMB_GS_ABRT_STS) 314 error |= SMB_EABORT; 315 316 if (sts & AMDSMB_GS_COL_STS) 317 error |= SMB_ENOACK; 318 319 if (sts & AMDSMB_GS_PRERR_STS) 320 error |= SMB_EBUSERR; 321 322 if (error != SMB_ENOERR) 323 amdpm_clear(sc); 324 325 return (error); 326} 327 328static int 329amdpm_quick(device_t dev, u_char slave, int how) 330{ 331 struct amdpm_softc *sc = (struct amdpm_softc *)device_get_softc(dev); 332 int error; 333 u_short l; 334
| 314 /* Wait for command to complete (SMBus controller is idle) */ 315 while(count--) { 316 DELAY(10); 317 sts = AMDPM_SMBINW(sc, AMDSMB_GLOBAL_STATUS); 318 if (!(sts & AMDSMB_GS_HST_STS)) 319 break; 320 } 321 322 AMDPM_DEBUG(printf("amdpm: STS=0x%x (count=%d)\n", sts, count)); 323 324 error = SMB_ENOERR; 325 326 if (!count) 327 error |= SMB_ETIMEOUT; 328 329 if (sts & AMDSMB_GS_ABRT_STS) 330 error |= SMB_EABORT; 331 332 if (sts & AMDSMB_GS_COL_STS) 333 error |= SMB_ENOACK; 334 335 if (sts & AMDSMB_GS_PRERR_STS) 336 error |= SMB_EBUSERR; 337 338 if (error != SMB_ENOERR) 339 amdpm_clear(sc); 340 341 return (error); 342} 343 344static int 345amdpm_quick(device_t dev, u_char slave, int how) 346{ 347 struct amdpm_softc *sc = (struct amdpm_softc *)device_get_softc(dev); 348 int error; 349 u_short l; 350
|
| 351 AMDPM_LOCK(sc);
|
335 amdpm_clear(sc);
| 352 amdpm_clear(sc);
|
336 if (!amdpm_idle(sc))
| 353 if (!amdpm_idle(sc)) { 354 AMDPM_UNLOCK(sc);
|
337 return (EBUSY);
| 355 return (EBUSY);
|
| 356 }
|
338 339 switch (how) { 340 case SMB_QWRITE: 341 AMDPM_DEBUG(printf("amdpm: QWRITE to 0x%x", slave)); 342 AMDPM_SMBOUTW(sc, AMDSMB_HSTADDR, slave & ~LSB); 343 break; 344 case SMB_QREAD: 345 AMDPM_DEBUG(printf("amdpm: QREAD to 0x%x", slave)); 346 AMDPM_SMBOUTW(sc, AMDSMB_HSTADDR, slave | LSB); 347 break; 348 default: 349 panic("%s: unknown QUICK command (%x)!", __func__, how); 350 } 351 l = AMDPM_SMBINW(sc, AMDSMB_GLOBAL_ENABLE); 352 AMDPM_SMBOUTW(sc, AMDSMB_GLOBAL_ENABLE, (l & 0xfff8) | AMDSMB_GE_CYC_QUICK | AMDSMB_GE_HOST_STC); 353 354 error = amdpm_wait(sc); 355 356 AMDPM_DEBUG(printf(", error=0x%x\n", error));
| 357 358 switch (how) { 359 case SMB_QWRITE: 360 AMDPM_DEBUG(printf("amdpm: QWRITE to 0x%x", slave)); 361 AMDPM_SMBOUTW(sc, AMDSMB_HSTADDR, slave & ~LSB); 362 break; 363 case SMB_QREAD: 364 AMDPM_DEBUG(printf("amdpm: QREAD to 0x%x", slave)); 365 AMDPM_SMBOUTW(sc, AMDSMB_HSTADDR, slave | LSB); 366 break; 367 default: 368 panic("%s: unknown QUICK command (%x)!", __func__, how); 369 } 370 l = AMDPM_SMBINW(sc, AMDSMB_GLOBAL_ENABLE); 371 AMDPM_SMBOUTW(sc, AMDSMB_GLOBAL_ENABLE, (l & 0xfff8) | AMDSMB_GE_CYC_QUICK | AMDSMB_GE_HOST_STC); 372 373 error = amdpm_wait(sc); 374 375 AMDPM_DEBUG(printf(", error=0x%x\n", error));
|
| 376 AMDPM_UNLOCK(sc);
|
357 358 return (error); 359} 360 361static int 362amdpm_sendb(device_t dev, u_char slave, char byte) 363{ 364 struct amdpm_softc *sc = (struct amdpm_softc *)device_get_softc(dev); 365 int error; 366 u_short l; 367
| 377 378 return (error); 379} 380 381static int 382amdpm_sendb(device_t dev, u_char slave, char byte) 383{ 384 struct amdpm_softc *sc = (struct amdpm_softc *)device_get_softc(dev); 385 int error; 386 u_short l; 387
|
| 388 AMDPM_LOCK(sc);
|
368 amdpm_clear(sc);
| 389 amdpm_clear(sc);
|
369 if (!amdpm_idle(sc))
| 390 if (!amdpm_idle(sc)) { 391 AMDPM_UNLOCK(sc);
|
370 return (SMB_EBUSY);
| 392 return (SMB_EBUSY);
|
| 393 }
|
371 372 AMDPM_SMBOUTW(sc, AMDSMB_HSTADDR, slave & ~LSB); 373 AMDPM_SMBOUTW(sc, AMDSMB_HSTDATA, byte); 374 l = AMDPM_SMBINW(sc, AMDSMB_GLOBAL_ENABLE); 375 AMDPM_SMBOUTW(sc, AMDSMB_GLOBAL_ENABLE, (l & 0xfff8) | AMDSMB_GE_CYC_BYTE | AMDSMB_GE_HOST_STC); 376 377 error = amdpm_wait(sc); 378 379 AMDPM_DEBUG(printf("amdpm: SENDB to 0x%x, byte=0x%x, error=0x%x\n", slave, byte, error));
| 394 395 AMDPM_SMBOUTW(sc, AMDSMB_HSTADDR, slave & ~LSB); 396 AMDPM_SMBOUTW(sc, AMDSMB_HSTDATA, byte); 397 l = AMDPM_SMBINW(sc, AMDSMB_GLOBAL_ENABLE); 398 AMDPM_SMBOUTW(sc, AMDSMB_GLOBAL_ENABLE, (l & 0xfff8) | AMDSMB_GE_CYC_BYTE | AMDSMB_GE_HOST_STC); 399 400 error = amdpm_wait(sc); 401 402 AMDPM_DEBUG(printf("amdpm: SENDB to 0x%x, byte=0x%x, error=0x%x\n", slave, byte, error));
|
| 403 AMDPM_UNLOCK(sc);
|
380 381 return (error); 382} 383 384static int 385amdpm_recvb(device_t dev, u_char slave, char *byte) 386{ 387 struct amdpm_softc *sc = (struct amdpm_softc *)device_get_softc(dev); 388 int error; 389 u_short l; 390
| 404 405 return (error); 406} 407 408static int 409amdpm_recvb(device_t dev, u_char slave, char *byte) 410{ 411 struct amdpm_softc *sc = (struct amdpm_softc *)device_get_softc(dev); 412 int error; 413 u_short l; 414
|
| 415 AMDPM_LOCK(sc);
|
391 amdpm_clear(sc);
| 416 amdpm_clear(sc);
|
392 if (!amdpm_idle(sc))
| 417 if (!amdpm_idle(sc)) { 418 AMDPM_UNLOCK(sc);
|
393 return (SMB_EBUSY);
| 419 return (SMB_EBUSY);
|
| 420 }
|
394 395 AMDPM_SMBOUTW(sc, AMDSMB_HSTADDR, slave | LSB); 396 l = AMDPM_SMBINW(sc, AMDSMB_GLOBAL_ENABLE); 397 AMDPM_SMBOUTW(sc, AMDSMB_GLOBAL_ENABLE, (l & 0xfff8) | AMDSMB_GE_CYC_BYTE | AMDSMB_GE_HOST_STC); 398 399 if ((error = amdpm_wait(sc)) == SMB_ENOERR) 400 *byte = AMDPM_SMBINW(sc, AMDSMB_HSTDATA); 401 402 AMDPM_DEBUG(printf("amdpm: RECVB from 0x%x, byte=0x%x, error=0x%x\n", slave, *byte, error));
| 421 422 AMDPM_SMBOUTW(sc, AMDSMB_HSTADDR, slave | LSB); 423 l = AMDPM_SMBINW(sc, AMDSMB_GLOBAL_ENABLE); 424 AMDPM_SMBOUTW(sc, AMDSMB_GLOBAL_ENABLE, (l & 0xfff8) | AMDSMB_GE_CYC_BYTE | AMDSMB_GE_HOST_STC); 425 426 if ((error = amdpm_wait(sc)) == SMB_ENOERR) 427 *byte = AMDPM_SMBINW(sc, AMDSMB_HSTDATA); 428 429 AMDPM_DEBUG(printf("amdpm: RECVB from 0x%x, byte=0x%x, error=0x%x\n", slave, *byte, error));
|
| 430 AMDPM_UNLOCK(sc);
|
403 404 return (error); 405} 406 407static int 408amdpm_writeb(device_t dev, u_char slave, char cmd, char byte) 409{ 410 struct amdpm_softc *sc = (struct amdpm_softc *)device_get_softc(dev); 411 int error; 412 u_short l; 413
| 431 432 return (error); 433} 434 435static int 436amdpm_writeb(device_t dev, u_char slave, char cmd, char byte) 437{ 438 struct amdpm_softc *sc = (struct amdpm_softc *)device_get_softc(dev); 439 int error; 440 u_short l; 441
|
| 442 AMDPM_LOCK(sc);
|
414 amdpm_clear(sc);
| 443 amdpm_clear(sc);
|
415 if (!amdpm_idle(sc))
| 444 if (!amdpm_idle(sc)) { 445 AMDPM_UNLOCK(sc);
|
416 return (SMB_EBUSY);
| 446 return (SMB_EBUSY);
|
| 447 }
|
417 418 AMDPM_SMBOUTW(sc, AMDSMB_HSTADDR, slave & ~LSB); 419 AMDPM_SMBOUTW(sc, AMDSMB_HSTDATA, byte); 420 AMDPM_SMBOUTB(sc, AMDSMB_HSTCMD, cmd); 421 l = AMDPM_SMBINW(sc, AMDSMB_GLOBAL_ENABLE); 422 AMDPM_SMBOUTW(sc, AMDSMB_GLOBAL_ENABLE, (l & 0xfff8) | AMDSMB_GE_CYC_BDATA | AMDSMB_GE_HOST_STC); 423 424 error = amdpm_wait(sc); 425 426 AMDPM_DEBUG(printf("amdpm: WRITEB to 0x%x, cmd=0x%x, byte=0x%x, error=0x%x\n", slave, cmd, byte, error));
| 448 449 AMDPM_SMBOUTW(sc, AMDSMB_HSTADDR, slave & ~LSB); 450 AMDPM_SMBOUTW(sc, AMDSMB_HSTDATA, byte); 451 AMDPM_SMBOUTB(sc, AMDSMB_HSTCMD, cmd); 452 l = AMDPM_SMBINW(sc, AMDSMB_GLOBAL_ENABLE); 453 AMDPM_SMBOUTW(sc, AMDSMB_GLOBAL_ENABLE, (l & 0xfff8) | AMDSMB_GE_CYC_BDATA | AMDSMB_GE_HOST_STC); 454 455 error = amdpm_wait(sc); 456 457 AMDPM_DEBUG(printf("amdpm: WRITEB to 0x%x, cmd=0x%x, byte=0x%x, error=0x%x\n", slave, cmd, byte, error));
|
| 458 AMDPM_UNLOCK(sc);
|
427 428 return (error); 429} 430 431static int 432amdpm_readb(device_t dev, u_char slave, char cmd, char *byte) 433{ 434 struct amdpm_softc *sc = (struct amdpm_softc *)device_get_softc(dev); 435 int error; 436 u_short l; 437
| 459 460 return (error); 461} 462 463static int 464amdpm_readb(device_t dev, u_char slave, char cmd, char *byte) 465{ 466 struct amdpm_softc *sc = (struct amdpm_softc *)device_get_softc(dev); 467 int error; 468 u_short l; 469
|
| 470 AMDPM_LOCK(sc);
|
438 amdpm_clear(sc);
| 471 amdpm_clear(sc);
|
439 if (!amdpm_idle(sc))
| 472 if (!amdpm_idle(sc)) { 473 AMDPM_UNLOCK(sc);
|
440 return (SMB_EBUSY);
| 474 return (SMB_EBUSY);
|
| 475 }
|
441 442 AMDPM_SMBOUTW(sc, AMDSMB_HSTADDR, slave | LSB); 443 AMDPM_SMBOUTB(sc, AMDSMB_HSTCMD, cmd); 444 l = AMDPM_SMBINW(sc, AMDSMB_GLOBAL_ENABLE); 445 AMDPM_SMBOUTW(sc, AMDSMB_GLOBAL_ENABLE, (l & 0xfff8) | AMDSMB_GE_CYC_BDATA | AMDSMB_GE_HOST_STC); 446 447 if ((error = amdpm_wait(sc)) == SMB_ENOERR) 448 *byte = AMDPM_SMBINW(sc, AMDSMB_HSTDATA); 449 450 AMDPM_DEBUG(printf("amdpm: READB from 0x%x, cmd=0x%x, byte=0x%x, error=0x%x\n", slave, cmd, *byte, error));
| 476 477 AMDPM_SMBOUTW(sc, AMDSMB_HSTADDR, slave | LSB); 478 AMDPM_SMBOUTB(sc, AMDSMB_HSTCMD, cmd); 479 l = AMDPM_SMBINW(sc, AMDSMB_GLOBAL_ENABLE); 480 AMDPM_SMBOUTW(sc, AMDSMB_GLOBAL_ENABLE, (l & 0xfff8) | AMDSMB_GE_CYC_BDATA | AMDSMB_GE_HOST_STC); 481 482 if ((error = amdpm_wait(sc)) == SMB_ENOERR) 483 *byte = AMDPM_SMBINW(sc, AMDSMB_HSTDATA); 484 485 AMDPM_DEBUG(printf("amdpm: READB from 0x%x, cmd=0x%x, byte=0x%x, error=0x%x\n", slave, cmd, *byte, error));
|
| 486 AMDPM_UNLOCK(sc);
|
451 452 return (error); 453} 454 455static int 456amdpm_writew(device_t dev, u_char slave, char cmd, short word) 457{ 458 struct amdpm_softc *sc = (struct amdpm_softc *)device_get_softc(dev); 459 int error; 460 u_short l; 461
| 487 488 return (error); 489} 490 491static int 492amdpm_writew(device_t dev, u_char slave, char cmd, short word) 493{ 494 struct amdpm_softc *sc = (struct amdpm_softc *)device_get_softc(dev); 495 int error; 496 u_short l; 497
|
| 498 AMDPM_LOCK(sc);
|
462 amdpm_clear(sc);
| 499 amdpm_clear(sc);
|
463 if (!amdpm_idle(sc))
| 500 if (!amdpm_idle(sc)) { 501 AMDPM_UNLOCK(sc);
|
464 return (SMB_EBUSY);
| 502 return (SMB_EBUSY);
|
| 503 }
|
465 466 AMDPM_SMBOUTW(sc, AMDSMB_HSTADDR, slave & ~LSB); 467 AMDPM_SMBOUTW(sc, AMDSMB_HSTDATA, word); 468 AMDPM_SMBOUTB(sc, AMDSMB_HSTCMD, cmd); 469 l = AMDPM_SMBINW(sc, AMDSMB_GLOBAL_ENABLE); 470 AMDPM_SMBOUTW(sc, AMDSMB_GLOBAL_ENABLE, (l & 0xfff8) | AMDSMB_GE_CYC_WDATA | AMDSMB_GE_HOST_STC); 471 472 error = amdpm_wait(sc); 473 474 AMDPM_DEBUG(printf("amdpm: WRITEW to 0x%x, cmd=0x%x, word=0x%x, error=0x%x\n", slave, cmd, word, error));
| 504 505 AMDPM_SMBOUTW(sc, AMDSMB_HSTADDR, slave & ~LSB); 506 AMDPM_SMBOUTW(sc, AMDSMB_HSTDATA, word); 507 AMDPM_SMBOUTB(sc, AMDSMB_HSTCMD, cmd); 508 l = AMDPM_SMBINW(sc, AMDSMB_GLOBAL_ENABLE); 509 AMDPM_SMBOUTW(sc, AMDSMB_GLOBAL_ENABLE, (l & 0xfff8) | AMDSMB_GE_CYC_WDATA | AMDSMB_GE_HOST_STC); 510 511 error = amdpm_wait(sc); 512 513 AMDPM_DEBUG(printf("amdpm: WRITEW to 0x%x, cmd=0x%x, word=0x%x, error=0x%x\n", slave, cmd, word, error));
|
| 514 AMDPM_UNLOCK(sc);
|
475 476 return (error); 477} 478 479static int 480amdpm_readw(device_t dev, u_char slave, char cmd, short *word) 481{ 482 struct amdpm_softc *sc = (struct amdpm_softc *)device_get_softc(dev); 483 int error; 484 u_short l; 485
| 515 516 return (error); 517} 518 519static int 520amdpm_readw(device_t dev, u_char slave, char cmd, short *word) 521{ 522 struct amdpm_softc *sc = (struct amdpm_softc *)device_get_softc(dev); 523 int error; 524 u_short l; 525
|
| 526 AMDPM_LOCK(sc);
|
486 amdpm_clear(sc);
| 527 amdpm_clear(sc);
|
487 if (!amdpm_idle(sc))
| 528 if (!amdpm_idle(sc)) { 529 AMDPM_UNLOCK(sc);
|
488 return (SMB_EBUSY);
| 530 return (SMB_EBUSY);
|
| 531 }
|
489 490 AMDPM_SMBOUTW(sc, AMDSMB_HSTADDR, slave | LSB); 491 AMDPM_SMBOUTB(sc, AMDSMB_HSTCMD, cmd); 492 l = AMDPM_SMBINW(sc, AMDSMB_GLOBAL_ENABLE); 493 AMDPM_SMBOUTW(sc, AMDSMB_GLOBAL_ENABLE, (l & 0xfff8) | AMDSMB_GE_CYC_WDATA | AMDSMB_GE_HOST_STC); 494 495 if ((error = amdpm_wait(sc)) == SMB_ENOERR) 496 *word = AMDPM_SMBINW(sc, AMDSMB_HSTDATA); 497 498 AMDPM_DEBUG(printf("amdpm: READW from 0x%x, cmd=0x%x, word=0x%x, error=0x%x\n", slave, cmd, *word, error));
| 532 533 AMDPM_SMBOUTW(sc, AMDSMB_HSTADDR, slave | LSB); 534 AMDPM_SMBOUTB(sc, AMDSMB_HSTCMD, cmd); 535 l = AMDPM_SMBINW(sc, AMDSMB_GLOBAL_ENABLE); 536 AMDPM_SMBOUTW(sc, AMDSMB_GLOBAL_ENABLE, (l & 0xfff8) | AMDSMB_GE_CYC_WDATA | AMDSMB_GE_HOST_STC); 537 538 if ((error = amdpm_wait(sc)) == SMB_ENOERR) 539 *word = AMDPM_SMBINW(sc, AMDSMB_HSTDATA); 540 541 AMDPM_DEBUG(printf("amdpm: READW from 0x%x, cmd=0x%x, word=0x%x, error=0x%x\n", slave, cmd, *word, error));
|
| 542 AMDPM_UNLOCK(sc);
|
499 500 return (error); 501} 502 503static int 504amdpm_bwrite(device_t dev, u_char slave, char cmd, u_char count, char *buf) 505{ 506 struct amdpm_softc *sc = (struct amdpm_softc *)device_get_softc(dev); 507 u_char i; 508 int error; 509 u_short l; 510 511 if (count < 1 || count > 32) 512 return (SMB_EINVAL);
| 543 544 return (error); 545} 546 547static int 548amdpm_bwrite(device_t dev, u_char slave, char cmd, u_char count, char *buf) 549{ 550 struct amdpm_softc *sc = (struct amdpm_softc *)device_get_softc(dev); 551 u_char i; 552 int error; 553 u_short l; 554 555 if (count < 1 || count > 32) 556 return (SMB_EINVAL);
|
| 557 558 AMDPM_LOCK(sc);
|
513 amdpm_clear(sc);
| 559 amdpm_clear(sc);
|
514 if(!amdpm_idle(sc))
| 560 if (!amdpm_idle(sc)) { 561 AMDPM_UNLOCK(sc);
|
515 return (SMB_EBUSY);
| 562 return (SMB_EBUSY);
|
| 563 }
|
516 517 AMDPM_SMBOUTW(sc, AMDSMB_HSTADDR, slave & ~LSB); 518 519 /* 520 * Do we have to reset the internal 32-byte buffer? 521 * Can't see how to do this from the data sheet. 522 */ 523 AMDPM_SMBOUTW(sc, AMDSMB_HSTDATA, count); 524 525 /* Fill the 32-byte internal buffer */ 526 for (i = 0; i < count; i++) { 527 AMDPM_SMBOUTB(sc, AMDSMB_HSTDFIFO, buf[i]); 528 DELAY(2); 529 } 530 AMDPM_SMBOUTB(sc, AMDSMB_HSTCMD, cmd); 531 l = AMDPM_SMBINW(sc, AMDSMB_GLOBAL_ENABLE); 532 AMDPM_SMBOUTW(sc, AMDSMB_GLOBAL_ENABLE, 533 (l & 0xfff8) | AMDSMB_GE_CYC_BLOCK | AMDSMB_GE_HOST_STC); 534 535 error = amdpm_wait(sc); 536 537 AMDPM_DEBUG(printf("amdpm: WRITEBLK to 0x%x, count=0x%x, cmd=0x%x, error=0x%x", slave, count, cmd, error));
| 564 565 AMDPM_SMBOUTW(sc, AMDSMB_HSTADDR, slave & ~LSB); 566 567 /* 568 * Do we have to reset the internal 32-byte buffer? 569 * Can't see how to do this from the data sheet. 570 */ 571 AMDPM_SMBOUTW(sc, AMDSMB_HSTDATA, count); 572 573 /* Fill the 32-byte internal buffer */ 574 for (i = 0; i < count; i++) { 575 AMDPM_SMBOUTB(sc, AMDSMB_HSTDFIFO, buf[i]); 576 DELAY(2); 577 } 578 AMDPM_SMBOUTB(sc, AMDSMB_HSTCMD, cmd); 579 l = AMDPM_SMBINW(sc, AMDSMB_GLOBAL_ENABLE); 580 AMDPM_SMBOUTW(sc, AMDSMB_GLOBAL_ENABLE, 581 (l & 0xfff8) | AMDSMB_GE_CYC_BLOCK | AMDSMB_GE_HOST_STC); 582 583 error = amdpm_wait(sc); 584 585 AMDPM_DEBUG(printf("amdpm: WRITEBLK to 0x%x, count=0x%x, cmd=0x%x, error=0x%x", slave, count, cmd, error));
|
| 586 AMDPM_UNLOCK(sc);
|
538 539 return (error); 540} 541 542static int 543amdpm_bread(device_t dev, u_char slave, char cmd, u_char *count, char *buf) 544{ 545 struct amdpm_softc *sc = (struct amdpm_softc *)device_get_softc(dev); 546 u_char data, len, i; 547 int error; 548 u_short l; 549 550 if (*count < 1 || *count > 32) 551 return (SMB_EINVAL);
| 587 588 return (error); 589} 590 591static int 592amdpm_bread(device_t dev, u_char slave, char cmd, u_char *count, char *buf) 593{ 594 struct amdpm_softc *sc = (struct amdpm_softc *)device_get_softc(dev); 595 u_char data, len, i; 596 int error; 597 u_short l; 598 599 if (*count < 1 || *count > 32) 600 return (SMB_EINVAL);
|
| 601 602 AMDPM_LOCK(sc);
|
552 amdpm_clear(sc);
| 603 amdpm_clear(sc);
|
553 if (!amdpm_idle(sc))
| 604 if (!amdpm_idle(sc)) { 605 AMDPM_UNLOCK(sc);
|
554 return (SMB_EBUSY);
| 606 return (SMB_EBUSY);
|
| 607 }
|
555 556 AMDPM_SMBOUTW(sc, AMDSMB_HSTADDR, slave | LSB); 557 558 AMDPM_SMBOUTB(sc, AMDSMB_HSTCMD, cmd); 559 560 l = AMDPM_SMBINW(sc, AMDSMB_GLOBAL_ENABLE); 561 AMDPM_SMBOUTW(sc, AMDSMB_GLOBAL_ENABLE, 562 (l & 0xfff8) | AMDSMB_GE_CYC_BLOCK | AMDSMB_GE_HOST_STC); 563 564 if ((error = amdpm_wait(sc)) != SMB_ENOERR) 565 goto error; 566 567 len = AMDPM_SMBINW(sc, AMDSMB_HSTDATA); 568 569 /* Read the 32-byte internal buffer */ 570 for (i = 0; i < len; i++) { 571 data = AMDPM_SMBINB(sc, AMDSMB_HSTDFIFO); 572 if (i < *count) 573 buf[i] = data; 574 DELAY(2); 575 } 576 *count = len; 577 578error: 579 AMDPM_DEBUG(printf("amdpm: READBLK to 0x%x, count=0x%x, cmd=0x%x, error=0x%x", slave, *count, cmd, error));
| 608 609 AMDPM_SMBOUTW(sc, AMDSMB_HSTADDR, slave | LSB); 610 611 AMDPM_SMBOUTB(sc, AMDSMB_HSTCMD, cmd); 612 613 l = AMDPM_SMBINW(sc, AMDSMB_GLOBAL_ENABLE); 614 AMDPM_SMBOUTW(sc, AMDSMB_GLOBAL_ENABLE, 615 (l & 0xfff8) | AMDSMB_GE_CYC_BLOCK | AMDSMB_GE_HOST_STC); 616 617 if ((error = amdpm_wait(sc)) != SMB_ENOERR) 618 goto error; 619 620 len = AMDPM_SMBINW(sc, AMDSMB_HSTDATA); 621 622 /* Read the 32-byte internal buffer */ 623 for (i = 0; i < len; i++) { 624 data = AMDPM_SMBINB(sc, AMDSMB_HSTDFIFO); 625 if (i < *count) 626 buf[i] = data; 627 DELAY(2); 628 } 629 *count = len; 630 631error: 632 AMDPM_DEBUG(printf("amdpm: READBLK to 0x%x, count=0x%x, cmd=0x%x, error=0x%x", slave, *count, cmd, error));
|
| 633 AMDPM_UNLOCK(sc);
|
580 581 return (error); 582} 583 584static devclass_t amdpm_devclass; 585 586static device_method_t amdpm_methods[] = { 587 /* Device interface */ 588 DEVMETHOD(device_probe, amdpm_probe), 589 DEVMETHOD(device_attach, amdpm_attach), 590 DEVMETHOD(device_detach, amdpm_detach), 591 592 /* SMBus interface */ 593 DEVMETHOD(smbus_callback, amdpm_callback), 594 DEVMETHOD(smbus_quick, amdpm_quick), 595 DEVMETHOD(smbus_sendb, amdpm_sendb), 596 DEVMETHOD(smbus_recvb, amdpm_recvb), 597 DEVMETHOD(smbus_writeb, amdpm_writeb), 598 DEVMETHOD(smbus_readb, amdpm_readb), 599 DEVMETHOD(smbus_writew, amdpm_writew), 600 DEVMETHOD(smbus_readw, amdpm_readw), 601 DEVMETHOD(smbus_bwrite, amdpm_bwrite), 602 DEVMETHOD(smbus_bread, amdpm_bread), 603 604 { 0, 0 } 605}; 606 607static driver_t amdpm_driver = { 608 "amdpm", 609 amdpm_methods, 610 sizeof(struct amdpm_softc), 611}; 612 613DRIVER_MODULE(amdpm, pci, amdpm_driver, amdpm_devclass, 0, 0); 614DRIVER_MODULE(smbus, amdpm, smbus_driver, smbus_devclass, 0, 0); 615 616MODULE_DEPEND(amdpm, pci, 1, 1, 1); 617MODULE_DEPEND(amdpm, smbus, SMBUS_MINVER, SMBUS_PREFVER, SMBUS_MAXVER); 618MODULE_VERSION(amdpm, 1);
| 634 635 return (error); 636} 637 638static devclass_t amdpm_devclass; 639 640static device_method_t amdpm_methods[] = { 641 /* Device interface */ 642 DEVMETHOD(device_probe, amdpm_probe), 643 DEVMETHOD(device_attach, amdpm_attach), 644 DEVMETHOD(device_detach, amdpm_detach), 645 646 /* SMBus interface */ 647 DEVMETHOD(smbus_callback, amdpm_callback), 648 DEVMETHOD(smbus_quick, amdpm_quick), 649 DEVMETHOD(smbus_sendb, amdpm_sendb), 650 DEVMETHOD(smbus_recvb, amdpm_recvb), 651 DEVMETHOD(smbus_writeb, amdpm_writeb), 652 DEVMETHOD(smbus_readb, amdpm_readb), 653 DEVMETHOD(smbus_writew, amdpm_writew), 654 DEVMETHOD(smbus_readw, amdpm_readw), 655 DEVMETHOD(smbus_bwrite, amdpm_bwrite), 656 DEVMETHOD(smbus_bread, amdpm_bread), 657 658 { 0, 0 } 659}; 660 661static driver_t amdpm_driver = { 662 "amdpm", 663 amdpm_methods, 664 sizeof(struct amdpm_softc), 665}; 666 667DRIVER_MODULE(amdpm, pci, amdpm_driver, amdpm_devclass, 0, 0); 668DRIVER_MODULE(smbus, amdpm, smbus_driver, smbus_devclass, 0, 0); 669 670MODULE_DEPEND(amdpm, pci, 1, 1, 1); 671MODULE_DEPEND(amdpm, smbus, SMBUS_MINVER, SMBUS_PREFVER, SMBUS_MAXVER); 672MODULE_VERSION(amdpm, 1);
|