The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/pci/amdpm.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    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  * $FreeBSD$
   31  *
   32  */
   33 
   34 /*
   35  * Power management function/SMBus function support for the AMD 756 chip.
   36  */
   37 
   38 #include <sys/param.h>
   39 #include <sys/kernel.h>
   40 #include <sys/systm.h>
   41 #include <sys/module.h>
   42 #include <sys/bus.h>
   43 #include <sys/uio.h>
   44 
   45 #include <machine/bus_pio.h>
   46 #include <machine/bus_memio.h>
   47 #include <machine/bus.h>
   48 #include <machine/clock.h>
   49 #include <machine/resource.h>
   50 #include <sys/rman.h>
   51 
   52 #include <pci/pcivar.h>
   53 #include <pci/pcireg.h>
   54 
   55 #include <dev/iicbus/iiconf.h>
   56 #include <dev/smbus/smbconf.h>
   57 #include "smbus_if.h"
   58 
   59 #define AMDPM_DEBUG(x)  if (amdpm_debug) (x)
   60 
   61 #ifdef DEBUG
   62 static int amdpm_debug = 1;
   63 #else
   64 static int amdpm_debug = 0;
   65 #endif
   66 
   67 #define AMDPM_VENDORID_AMD 0x1022
   68 #define AMDPM_DEVICEID_AMD756PM 0x740b
   69 
   70 /* PCI Configuration space registers */
   71 #define AMDPCI_PMBASE 0x58
   72 
   73 #define AMDPCI_GEN_CONFIG_PM 0x41
   74 #define AMDPCI_PMIOEN (1<<7)
   75 
   76 #define AMDPCI_SCIINT_CONFIG_PM 0x42
   77 #define AMDPCI_SCISEL_IRQ11 11
   78 
   79 #define AMDPCI_REVID 0x08
   80 
   81 /*
   82  * I/O registers.
   83  * Base address programmed via AMDPCI_PMBASE.
   84  */
   85 #define AMDSMB_GLOBAL_STATUS 0xE0
   86 #define AMDSMB_GS_TO_STS (1<<5)
   87 #define AMDSMB_GS_HCYC_STS (1<<4)
   88 #define AMDSMB_GS_HST_STS (1<<3)
   89 #define AMDSMB_GS_PRERR_STS (1<<2)
   90 #define AMDSMB_GS_COL_STS (1<<1)
   91 #define AMDSMB_GS_ABRT_STS (1<<0)
   92 #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)
   93 
   94 #define AMDSMB_GLOBAL_ENABLE 0xE2
   95 #define AMDSMB_GE_ABORT (1<<5)
   96 #define AMDSMB_GE_HCYC_EN (1<<4)
   97 #define AMDSMB_GE_HOST_STC (1<<3)
   98 #define AMDSMB_GE_CYC_QUICK 0
   99 #define AMDSMB_GE_CYC_BYTE 1
  100 #define AMDSMB_GE_CYC_BDATA 2
  101 #define AMDSMB_GE_CYC_WDATA 3
  102 #define AMDSMB_GE_CYC_PROCCALL 4
  103 #define AMDSMB_GE_CYC_BLOCK 5
  104 
  105 #define AMDSMB_HSTADDR 0xE4
  106 #define AMDSMB_HSTDATA 0xE6
  107 #define AMDSMB_HSTCMD 0xE8
  108 #define AMDSMB_HSTDFIFO 0xE9
  109 #define AMDSMB_HSLVDATA 0xEA
  110 #define AMDSMB_HSLVDA 0xEC
  111 #define AMDSMB_HSLVDDR 0xEE
  112 #define AMDSMB_SNPADDR 0xEF
  113 
  114 struct amdpm_softc {
  115         int base;
  116         int rid;
  117         struct resource *res;
  118         bus_space_tag_t smbst;
  119         bus_space_handle_t smbsh;
  120 };
  121 
  122 struct amdsmb_softc {
  123         int base;
  124         device_t smbus;
  125         struct amdpm_softc *amdpm;
  126 };
  127 
  128 #define AMDPM_SMBINB(amdsmb,register) \
  129         (bus_space_read_1(amdsmb->amdpm->smbst, amdsmb->amdpm->smbsh, register))
  130 #define AMDPM_SMBOUTB(amdsmb,register,value) \
  131         (bus_space_write_1(amdsmb->amdpm->smbst, amdsmb->amdpm->smbsh, register, value))
  132 #define AMDPM_SMBINW(amdsmb,register) \
  133         (bus_space_read_2(amdsmb->amdpm->smbst, amdsmb->amdpm->smbsh, register))
  134 #define AMDPM_SMBOUTW(amdsmb,register,value) \
  135         (bus_space_write_2(amdsmb->amdpm->smbst, amdsmb->amdpm->smbsh, register, value))
  136 
  137 static int amdsmb_probe(device_t);
  138 static int amdsmb_attach(device_t);
  139 static int amdsmb_smb_callback(device_t, int, caddr_t *);
  140 static int amdsmb_smb_quick(device_t dev, u_char slave, int how);
  141 static int amdsmb_smb_sendb(device_t dev, u_char slave, char byte);
  142 static int amdsmb_smb_recvb(device_t dev, u_char slave, char *byte);
  143 static int amdsmb_smb_writeb(device_t dev, u_char slave, char cmd, char byte);
  144 static int amdsmb_smb_readb(device_t dev, u_char slave, char cmd, char *byte);
  145 static int amdsmb_smb_writew(device_t dev, u_char slave, char cmd, short word);
  146 static int amdsmb_smb_readw(device_t dev, u_char slave, char cmd, short *word);
  147 static int amdsmb_smb_bwrite(device_t dev, u_char slave, char cmd, u_char count, char *buf);
  148 static int amdsmb_smb_bread(device_t dev, u_char slave, char cmd, u_char count, char *byte);
  149 
  150 static int amdpm_probe(device_t);
  151 static int amdpm_attach(device_t);
  152 
  153 
  154 static int
  155 amdpm_probe(device_t dev)
  156 {
  157         u_long base;
  158         
  159         if ((pci_get_vendor(dev) == AMDPM_VENDORID_AMD) &&
  160             (pci_get_device(dev) == AMDPM_DEVICEID_AMD756PM)) {
  161               device_set_desc(dev, "AMD 756 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, base, 256);
  170               return (0);
  171         }
  172         return ENXIO;
  173 }
  174 
  175 static int
  176 amdpm_attach(device_t dev)
  177 {
  178         struct amdpm_softc *amdpm_sc = device_get_softc(dev);
  179         u_char val_b;
  180         int unit = device_get_unit(dev);
  181         device_t smbinterface;
  182         
  183         /* Enable I/O block access */
  184         val_b = pci_read_config(dev, AMDPCI_GEN_CONFIG_PM, 1);
  185         pci_write_config(dev, AMDPCI_GEN_CONFIG_PM, val_b | AMDPCI_PMIOEN, 1);
  186 
  187         /* Allocate I/O space */
  188         amdpm_sc->rid = AMDPCI_PMBASE;
  189         amdpm_sc->res = bus_alloc_resource(dev, SYS_RES_IOPORT, &amdpm_sc->rid, 0, ~0, 1, RF_ACTIVE);
  190         
  191         if (amdpm_sc->res == NULL) {
  192                 device_printf(dev, "could not map i/o space\n");
  193                 return (ENXIO);
  194         }            
  195 
  196         amdpm_sc->smbst = rman_get_bustag(amdpm_sc->res);
  197         amdpm_sc->smbsh = rman_get_bushandle(amdpm_sc->res);
  198         
  199         smbinterface = device_add_child(dev, "amdsmb", unit);
  200         if (!smbinterface)
  201                 device_printf(dev, "could not add SMBus device\n");
  202         else
  203                 device_probe_and_attach(smbinterface);
  204 
  205         return (0);
  206 }
  207 
  208 static int
  209 amdsmb_probe(device_t dev)
  210 {
  211         struct amdsmb_softc *amdsmb_sc = (struct amdsmb_softc *)device_get_softc(dev);
  212 
  213         /* Allocate a new smbus device */
  214         amdsmb_sc->smbus = smbus_alloc_bus(dev);
  215         if (!amdsmb_sc->smbus)
  216                 return (EINVAL);
  217 
  218         device_set_desc(dev, "AMD 756 SMBus interface");
  219         device_printf(dev, "AMD 756 SMBus interface\n");
  220 
  221         return (0);
  222 }
  223 
  224 static int
  225 amdsmb_attach(device_t dev)
  226 {
  227         struct amdsmb_softc *amdsmb_sc = (struct amdsmb_softc *)device_get_softc(dev);
  228 
  229         amdsmb_sc->amdpm = device_get_softc(device_get_parent(dev));
  230         
  231         /* Probe and attach the smbus */
  232         device_probe_and_attach(amdsmb_sc->smbus);
  233 
  234         return (0);
  235 }
  236 
  237 static int
  238 amdsmb_smb_callback(device_t dev, int index, caddr_t *data)
  239 {
  240         int error = 0;
  241 
  242         switch (index) {
  243         case SMB_REQUEST_BUS:
  244         case SMB_RELEASE_BUS:
  245                 break;
  246         default:
  247                 error = EINVAL;
  248         }
  249 
  250         return (error);
  251 }
  252 
  253 static int
  254 amdsmb_clear(struct amdsmb_softc *sc)
  255 {
  256         AMDPM_SMBOUTW(sc, AMDSMB_GLOBAL_STATUS, AMDSMB_GS_CLEAR_STS);
  257         DELAY(10);
  258 
  259         return (0);
  260 }
  261 
  262 static int
  263 amdsmb_abort(struct amdsmb_softc *sc)
  264 {
  265         u_short l;
  266         
  267         l = AMDPM_SMBINW(sc, AMDSMB_GLOBAL_ENABLE);
  268         AMDPM_SMBOUTW(sc, AMDSMB_GLOBAL_ENABLE, l | AMDSMB_GE_ABORT);
  269 
  270         return (0);
  271 }
  272 
  273 static int
  274 amdsmb_idle(struct amdsmb_softc *sc)
  275 {
  276         u_short sts;
  277 
  278         sts = AMDPM_SMBINW(sc, AMDSMB_GLOBAL_STATUS);
  279 
  280         AMDPM_DEBUG(printf("amdpm: busy? STS=0x%x\n", sts));
  281 
  282         return (~(sts & AMDSMB_GS_HST_STS));
  283 }
  284 
  285 /*
  286  * Poll the SMBus controller
  287  */
  288 static int
  289 amdsmb_wait(struct amdsmb_softc *sc)
  290 {
  291         int count = 10000;
  292         u_short sts = 0;
  293         int error;
  294 
  295         /* Wait for command to complete (SMBus controller is idle) */
  296         while(count--) {
  297                 DELAY(10);
  298                 sts = AMDPM_SMBINW(sc, AMDSMB_GLOBAL_STATUS);
  299                 if (!(sts & AMDSMB_GS_HST_STS))
  300                         break;
  301         }
  302 
  303         AMDPM_DEBUG(printf("amdpm: STS=0x%x (count=%d)\n", sts, count));
  304 
  305         error = SMB_ENOERR;
  306 
  307         if (!count)
  308                 error |= SMB_ETIMEOUT;
  309 
  310         if (sts & AMDSMB_GS_ABRT_STS)
  311                 error |= SMB_EABORT;
  312 
  313         if (sts & AMDSMB_GS_COL_STS)
  314                 error |= SMB_ENOACK;
  315 
  316         if (sts & AMDSMB_GS_PRERR_STS)
  317                 error |= SMB_EBUSERR;
  318 
  319         if (error != SMB_ENOERR)
  320                 amdsmb_clear(sc);
  321 
  322         return (error);
  323 }
  324 
  325 static int
  326 amdsmb_smb_quick(device_t dev, u_char slave, int how)
  327 {
  328         struct amdsmb_softc *sc = (struct amdsmb_softc *)device_get_softc(dev);
  329         int error;
  330         u_short l;
  331 
  332         amdsmb_clear(sc);
  333         if (!amdsmb_idle(sc))
  334                 return (EBUSY);
  335 
  336         switch (how) {
  337         case SMB_QWRITE:
  338                 AMDPM_DEBUG(printf("amdpm: QWRITE to 0x%x", slave));
  339                 AMDPM_SMBOUTW(sc, AMDSMB_HSTADDR, slave & ~LSB);
  340                 break;
  341         case SMB_QREAD:
  342                 AMDPM_DEBUG(printf("amdpm: QREAD to 0x%x", slave));
  343                 AMDPM_SMBOUTW(sc, AMDSMB_HSTADDR, slave | LSB);
  344                 break;
  345         default:
  346                 panic("%s: unknown QUICK command (%x)!", __FUNCTION__, how);
  347         }
  348         l = AMDPM_SMBINW(sc, AMDSMB_GLOBAL_ENABLE);
  349         AMDPM_SMBOUTW(sc, AMDSMB_GLOBAL_ENABLE, (l & 0xfff8) | AMDSMB_GE_CYC_QUICK | AMDSMB_GE_HOST_STC);
  350 
  351         error = amdsmb_wait(sc);
  352 
  353         AMDPM_DEBUG(printf(", error=0x%x\n", error));
  354 
  355         return (error);
  356 }
  357 
  358 static int
  359 amdsmb_smb_sendb(device_t dev, u_char slave, char byte)
  360 {
  361         struct amdsmb_softc *sc = (struct amdsmb_softc *)device_get_softc(dev);
  362         int error;
  363         u_short l;
  364 
  365         amdsmb_clear(sc);
  366         if (!amdsmb_idle(sc))
  367                 return (SMB_EBUSY);
  368 
  369         AMDPM_SMBOUTW(sc, AMDSMB_HSTADDR, slave & ~LSB);
  370         AMDPM_SMBOUTW(sc, AMDSMB_HSTDATA, byte);
  371         l = AMDPM_SMBINW(sc, AMDSMB_GLOBAL_ENABLE);
  372         AMDPM_SMBOUTW(sc, AMDSMB_GLOBAL_ENABLE, (l & 0xfff8) | AMDSMB_GE_CYC_BYTE | AMDSMB_GE_HOST_STC);
  373 
  374         error = amdsmb_wait(sc);
  375 
  376         AMDPM_DEBUG(printf("amdpm: SENDB to 0x%x, byte=0x%x, error=0x%x\n", slave, byte, error));
  377 
  378         return (error);
  379 }
  380 
  381 static int
  382 amdsmb_smb_recvb(device_t dev, u_char slave, char *byte)
  383 {
  384         struct amdsmb_softc *sc = (struct amdsmb_softc *)device_get_softc(dev);
  385         int error;
  386         u_short l;
  387 
  388         amdsmb_clear(sc);
  389         if (!amdsmb_idle(sc))
  390                 return (SMB_EBUSY);
  391 
  392         AMDPM_SMBOUTW(sc, AMDSMB_HSTADDR, slave | LSB);
  393         l = AMDPM_SMBINW(sc, AMDSMB_GLOBAL_ENABLE);
  394         AMDPM_SMBOUTW(sc, AMDSMB_GLOBAL_ENABLE, (l & 0xfff8) | AMDSMB_GE_CYC_BYTE | AMDSMB_GE_HOST_STC);
  395 
  396         if ((error = amdsmb_wait(sc)) == SMB_ENOERR)
  397                 *byte = AMDPM_SMBINW(sc, AMDSMB_HSTDATA);
  398 
  399         AMDPM_DEBUG(printf("amdpm: RECVB from 0x%x, byte=0x%x, error=0x%x\n", slave, *byte, error));
  400 
  401         return (error);
  402 }
  403 
  404 static int
  405 amdsmb_smb_writeb(device_t dev, u_char slave, char cmd, char byte)
  406 {
  407         struct amdsmb_softc *sc = (struct amdsmb_softc *)device_get_softc(dev);
  408         int error;
  409         u_short l;
  410 
  411         amdsmb_clear(sc);
  412         if (!amdsmb_idle(sc))
  413                 return (SMB_EBUSY);
  414 
  415         AMDPM_SMBOUTW(sc, AMDSMB_HSTADDR, slave & ~LSB);
  416         AMDPM_SMBOUTW(sc, AMDSMB_HSTDATA, byte);
  417         AMDPM_SMBOUTB(sc, AMDSMB_HSTCMD, cmd);
  418         l = AMDPM_SMBINW(sc, AMDSMB_GLOBAL_ENABLE);
  419         AMDPM_SMBOUTW(sc, AMDSMB_GLOBAL_ENABLE, (l & 0xfff8) | AMDSMB_GE_CYC_BDATA | AMDSMB_GE_HOST_STC);
  420 
  421         error = amdsmb_wait(sc);
  422 
  423         AMDPM_DEBUG(printf("amdpm: WRITEB to 0x%x, cmd=0x%x, byte=0x%x, error=0x%x\n", slave, cmd, byte, error));
  424 
  425         return (error);
  426 }
  427 
  428 static int
  429 amdsmb_smb_readb(device_t dev, u_char slave, char cmd, char *byte)
  430 {
  431         struct amdsmb_softc *sc = (struct amdsmb_softc *)device_get_softc(dev);
  432         int error;
  433         u_short l;
  434 
  435         amdsmb_clear(sc);
  436         if (!amdsmb_idle(sc))
  437                 return (SMB_EBUSY);
  438 
  439         AMDPM_SMBOUTW(sc, AMDSMB_HSTADDR, slave | LSB);
  440         AMDPM_SMBOUTB(sc, AMDSMB_HSTCMD, cmd);
  441         l = AMDPM_SMBINW(sc, AMDSMB_GLOBAL_ENABLE);
  442         AMDPM_SMBOUTW(sc, AMDSMB_GLOBAL_ENABLE, (l & 0xfff8) | AMDSMB_GE_CYC_BDATA | AMDSMB_GE_HOST_STC);
  443 
  444         if ((error = amdsmb_wait(sc)) == SMB_ENOERR)
  445                 *byte = AMDPM_SMBINW(sc, AMDSMB_HSTDATA);
  446 
  447         AMDPM_DEBUG(printf("amdpm: READB from 0x%x, cmd=0x%x, byte=0x%x, error=0x%x\n", slave, cmd, *byte, error));
  448 
  449         return (error);
  450 }
  451 
  452 static int
  453 amdsmb_smb_writew(device_t dev, u_char slave, char cmd, short word)
  454 {
  455         struct amdsmb_softc *sc = (struct amdsmb_softc *)device_get_softc(dev);
  456         int error;
  457         u_short l;
  458 
  459         amdsmb_clear(sc);
  460         if (!amdsmb_idle(sc))
  461                 return (SMB_EBUSY);
  462 
  463         AMDPM_SMBOUTW(sc, AMDSMB_HSTADDR, slave & ~LSB);
  464         AMDPM_SMBOUTW(sc, AMDSMB_HSTDATA, word);
  465         AMDPM_SMBOUTB(sc, AMDSMB_HSTCMD, cmd);
  466         l = AMDPM_SMBINW(sc, AMDSMB_GLOBAL_ENABLE);
  467         AMDPM_SMBOUTW(sc, AMDSMB_GLOBAL_ENABLE, (l & 0xfff8) | AMDSMB_GE_CYC_WDATA | AMDSMB_GE_HOST_STC);
  468 
  469         error = amdsmb_wait(sc);
  470 
  471         AMDPM_DEBUG(printf("amdpm: WRITEW to 0x%x, cmd=0x%x, word=0x%x, error=0x%x\n", slave, cmd, word, error));
  472 
  473         return (error);
  474 }
  475 
  476 static int
  477 amdsmb_smb_readw(device_t dev, u_char slave, char cmd, short *word)
  478 {
  479         struct amdsmb_softc *sc = (struct amdsmb_softc *)device_get_softc(dev);
  480         int error;
  481         u_short l;
  482 
  483         amdsmb_clear(sc);
  484         if (!amdsmb_idle(sc))
  485                 return (SMB_EBUSY);
  486 
  487         AMDPM_SMBOUTW(sc, AMDSMB_HSTADDR, slave | LSB);
  488         AMDPM_SMBOUTB(sc, AMDSMB_HSTCMD, cmd);
  489         l = AMDPM_SMBINW(sc, AMDSMB_GLOBAL_ENABLE);
  490         AMDPM_SMBOUTW(sc, AMDSMB_GLOBAL_ENABLE, (l & 0xfff8) | AMDSMB_GE_CYC_WDATA | AMDSMB_GE_HOST_STC);
  491 
  492         if ((error = amdsmb_wait(sc)) == SMB_ENOERR)
  493                 *word = AMDPM_SMBINW(sc, AMDSMB_HSTDATA);
  494 
  495         AMDPM_DEBUG(printf("amdpm: READW from 0x%x, cmd=0x%x, word=0x%x, error=0x%x\n", slave, cmd, *word, error));
  496 
  497         return (error);
  498 }
  499 
  500 static int
  501 amdsmb_smb_bwrite(device_t dev, u_char slave, char cmd, u_char count, char *buf)
  502 {
  503         struct amdsmb_softc *sc = (struct amdsmb_softc *)device_get_softc(dev);
  504         u_char remain, len, i;
  505         int error = SMB_ENOERR;
  506         u_short l;
  507 
  508         amdsmb_clear(sc);
  509         if(!amdsmb_idle(sc))
  510                 return (SMB_EBUSY);
  511 
  512         remain = count;
  513         while (remain) {
  514                 len = min(remain, 32);
  515 
  516                 AMDPM_SMBOUTW(sc, AMDSMB_HSTADDR, slave & ~LSB);
  517         
  518                 /*
  519                  * Do we have to reset the internal 32-byte buffer?
  520                  * Can't see how to do this from the data sheet.
  521                  */
  522 
  523                 AMDPM_SMBOUTW(sc, AMDSMB_HSTDATA, len);
  524 
  525                 /* Fill the 32-byte internal buffer */
  526                 for (i=0; i<len; i++) {
  527                         AMDPM_SMBOUTB(sc, AMDSMB_HSTDFIFO, buf[count-remain+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, (l & 0xfff8) | AMDSMB_GE_CYC_BLOCK | AMDSMB_GE_HOST_STC);
  533 
  534                 if ((error = amdsmb_wait(sc)) != SMB_ENOERR)
  535                         goto error;
  536 
  537                 remain -= len;
  538         }
  539 
  540 error:
  541         AMDPM_DEBUG(printf("amdpm: WRITEBLK to 0x%x, count=0x%x, cmd=0x%x, error=0x%x", slave, count, cmd, error));
  542 
  543         return (error);
  544 }
  545 
  546 static int
  547 amdsmb_smb_bread(device_t dev, u_char slave, char cmd, u_char count, char *buf)
  548 {
  549         struct amdsmb_softc *sc = (struct amdsmb_softc *)device_get_softc(dev);
  550         u_char remain, len, i;
  551         int error = SMB_ENOERR;
  552         u_short l;
  553 
  554         amdsmb_clear(sc);
  555         if (!amdsmb_idle(sc))
  556                 return (SMB_EBUSY);
  557 
  558         remain = count;
  559         while (remain) {
  560                 AMDPM_SMBOUTW(sc, AMDSMB_HSTADDR, slave | LSB);
  561         
  562                 AMDPM_SMBOUTB(sc, AMDSMB_HSTCMD, cmd);
  563 
  564                 l = AMDPM_SMBINW(sc, AMDSMB_GLOBAL_ENABLE);
  565                 AMDPM_SMBOUTW(sc, AMDSMB_GLOBAL_ENABLE, (l & 0xfff8) | AMDSMB_GE_CYC_BLOCK | AMDSMB_GE_HOST_STC);
  566                 
  567                 if ((error = amdsmb_wait(sc)) != SMB_ENOERR)
  568                         goto error;
  569 
  570                 len = AMDPM_SMBINW(sc, AMDSMB_HSTDATA);
  571 
  572                 /* Read the 32-byte internal buffer */
  573                 for (i=0; i<len; i++) {
  574                         buf[count-remain+i] = AMDPM_SMBINB(sc, AMDSMB_HSTDFIFO);
  575                         DELAY(2);
  576                 }
  577 
  578                 remain -= len;
  579         }
  580 error:
  581         AMDPM_DEBUG(printf("amdpm: READBLK to 0x%x, count=0x%x, cmd=0x%x, error=0x%x", slave, count, cmd, error));
  582 
  583         return (error);
  584 }
  585 
  586 static devclass_t amdpm_devclass;
  587 
  588 static device_method_t amdpm_methods[] = {
  589         /* Device interface */
  590         DEVMETHOD(device_probe,         amdpm_probe),
  591         DEVMETHOD(device_attach,        amdpm_attach),
  592         
  593         { 0, 0 }
  594 };
  595 
  596 static driver_t amdpm_driver = {
  597         "amdpm",
  598         amdpm_methods,
  599         sizeof(struct amdpm_softc),
  600 };
  601 
  602 static devclass_t amdsmb_devclass;
  603 
  604 static device_method_t amdsmb_methods[] = {
  605         /* Device interface */
  606         DEVMETHOD(device_probe,         amdsmb_probe),
  607         DEVMETHOD(device_attach,        amdsmb_attach),
  608 
  609         /* Bus interface */
  610         DEVMETHOD(bus_print_child,      bus_generic_print_child),
  611         
  612         /* SMBus interface */
  613         DEVMETHOD(smbus_callback,       amdsmb_smb_callback),
  614         DEVMETHOD(smbus_quick,          amdsmb_smb_quick),
  615         DEVMETHOD(smbus_sendb,          amdsmb_smb_sendb),
  616         DEVMETHOD(smbus_recvb,          amdsmb_smb_recvb),
  617         DEVMETHOD(smbus_writeb,         amdsmb_smb_writeb),
  618         DEVMETHOD(smbus_readb,          amdsmb_smb_readb),
  619         DEVMETHOD(smbus_writew,         amdsmb_smb_writew),
  620         DEVMETHOD(smbus_readw,          amdsmb_smb_readw),
  621         DEVMETHOD(smbus_bwrite,         amdsmb_smb_bwrite),
  622         DEVMETHOD(smbus_bread,          amdsmb_smb_bread),
  623         
  624         { 0, 0 }
  625 };
  626 
  627 static driver_t amdsmb_driver = {
  628         "amdsmb",
  629         amdsmb_methods,
  630         sizeof(struct amdsmb_softc),
  631 };
  632 
  633 DRIVER_MODULE(amdpm, pci, amdpm_driver, amdpm_devclass, 0, 0);
  634 DRIVER_MODULE(amdsmb, amdpm, amdsmb_driver, amdsmb_devclass, 0, 0);

Cache object: cd16e976759c7f29df9564fe4ec2c885


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.