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/viapm.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) 2001 Alcove - Nicolas Souchu
    3  * All rights reserved.
    4  *
    5  * Redistribution and use in source and binary forms, with or without
    6  * modification, are permitted provided that the following conditions
    7  * are met:
    8  * 1. Redistributions of source code must retain the above copyright
    9  *    notice, this list of conditions and the following disclaimer.
   10  * 2. Redistributions in binary form must reproduce the above copyright
   11  *    notice, this list of conditions and the following disclaimer in the
   12  *    documentation and/or other materials provided with the distribution.
   13  *
   14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   15  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   17  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
   18  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   19  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   20  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   21  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   22  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   23  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   24  * SUCH DAMAGE.
   25  */
   26 
   27 #include <sys/cdefs.h>
   28 __FBSDID("$FreeBSD$");
   29 
   30 #include "opt_isa.h"
   31 
   32 #include <sys/param.h>
   33 #include <sys/bus.h>
   34 #include <sys/kernel.h>
   35 #include <sys/lock.h>
   36 #include <sys/module.h>
   37 #include <sys/mutex.h>
   38 #include <sys/systm.h>
   39 
   40 #include <machine/bus.h>
   41 #include <machine/resource.h>
   42 #include <sys/rman.h>
   43 
   44 #ifdef DEV_ISA
   45 #include <isa/isavar.h>
   46 #include <isa/isa_common.h>
   47 #endif
   48 #include <dev/pci/pcivar.h>
   49 #include <dev/pci/pcireg.h>
   50 
   51 #include <dev/iicbus/iiconf.h>
   52 
   53 #include <dev/smbus/smbconf.h>
   54 
   55 #include "iicbb_if.h"
   56 #include "smbus_if.h"
   57 
   58 #define VIAPM_DEBUG(x)  if (viapm_debug) (x)
   59 
   60 #ifdef DEBUG
   61 static int viapm_debug = 1;
   62 #else
   63 static int viapm_debug = 0;
   64 #endif
   65 
   66 #define VIA_586B_PMU_ID         0x30401106
   67 #define VIA_596A_PMU_ID         0x30501106
   68 #define VIA_596B_PMU_ID         0x30511106
   69 #define VIA_686A_PMU_ID         0x30571106
   70 #define VIA_8233_PMU_ID         0x30741106
   71 #define VIA_8233A_PMU_ID        0x31471106
   72 #define VIA_8235_PMU_ID         0x31771106
   73 #define VIA_8237_PMU_ID         0x32271106
   74 #define VIA_CX700_PMU_ID        0x83241106
   75 
   76 #define VIAPM_INB(port) \
   77         ((u_char)bus_space_read_1(viapm->st, viapm->sh, port))
   78 #define VIAPM_OUTB(port,val) \
   79         (bus_space_write_1(viapm->st, viapm->sh, port, (u_char)(val)))
   80 
   81 #define VIAPM_TYP_UNKNOWN       0
   82 #define VIAPM_TYP_586B_3040E    1
   83 #define VIAPM_TYP_586B_3040F    2
   84 #define VIAPM_TYP_596B          3
   85 #define VIAPM_TYP_686A          4
   86 #define VIAPM_TYP_8233          5
   87 
   88 #define VIAPM_LOCK(sc)          mtx_lock(&(sc)->lock)
   89 #define VIAPM_UNLOCK(sc)        mtx_unlock(&(sc)->lock)
   90 #define VIAPM_LOCK_ASSERT(sc)   mtx_assert(&(sc)->lock, MA_OWNED)
   91 
   92 struct viapm_softc {
   93         int type;
   94         u_int32_t base;
   95         bus_space_tag_t st;
   96         bus_space_handle_t sh;
   97         int iorid;
   98         int irqrid;
   99         struct resource *iores;
  100         struct resource *irqres;
  101         void *irqih;
  102         device_t iicbb;
  103         device_t smbus;
  104         struct mtx lock;
  105 };
  106 
  107 static devclass_t viapm_devclass;
  108 static devclass_t viapropm_devclass;
  109 
  110 /*
  111  * VT82C586B definitions
  112  */
  113 
  114 #define VIAPM_586B_REVID        0x08
  115 
  116 #define VIAPM_586B_3040E_BASE   0x20
  117 #define VIAPM_586B_3040E_ACTIV  0x4             /* 16 bits */
  118 
  119 #define VIAPM_586B_3040F_BASE   0x48
  120 #define VIAPM_586B_3040F_ACTIV  0x41            /* 8 bits */
  121 
  122 #define VIAPM_586B_OEM_REV_E    0x00
  123 #define VIAPM_586B_OEM_REV_F    0x01
  124 #define VIAPM_586B_PROD_REV_A   0x10
  125 
  126 #define VIAPM_586B_BA_MASK      0x0000ff00
  127 
  128 #define GPIO_DIR        0x40
  129 #define GPIO_VAL        0x42
  130 #define EXTSMI_VAL      0x44
  131 
  132 #define VIAPM_SCL       0x02                    /* GPIO1_VAL */
  133 #define VIAPM_SDA       0x04                    /* GPIO2_VAL */
  134 
  135 /*
  136  * VIAPRO common definitions
  137  */
  138 
  139 #define VIAPM_PRO_BA_MASK       0x0000fff0
  140 #define VIAPM_PRO_SMBCTRL       0xd2
  141 #define VIAPM_PRO_REVID         0xd6
  142 
  143 /*
  144  * VT82C686A definitions
  145  */
  146 
  147 #define VIAPM_PRO_BASE          0x90
  148 
  149 #define SMBHST                  0x0
  150 #define SMBHSL                  0x1
  151 #define SMBHCTRL                0x2
  152 #define SMBHCMD                 0x3
  153 #define SMBHADDR                0x4
  154 #define SMBHDATA0               0x5
  155 #define SMBHDATA1               0x6
  156 #define SMBHBLOCK               0x7
  157 
  158 #define SMBSST                  0x1
  159 #define SMBSCTRL                0x8
  160 #define SMBSSDWCMD              0x9
  161 #define SMBSEVENT               0xa
  162 #define SMBSDATA                0xc
  163 
  164 #define SMBHST_RESERVED         0xef    /* reserved bits */
  165 #define SMBHST_FAILED           0x10    /* failed bus transaction */
  166 #define SMBHST_COLLID           0x08    /* bus collision */
  167 #define SMBHST_ERROR            0x04    /* device error */
  168 #define SMBHST_INTR             0x02    /* command completed */
  169 #define SMBHST_BUSY             0x01    /* host busy */
  170 
  171 #define SMBHCTRL_START          0x40    /* start command */
  172 #define SMBHCTRL_PROTO          0x1c    /* command protocol mask */
  173 #define SMBHCTRL_QUICK          0x00
  174 #define SMBHCTRL_SENDRECV       0x04
  175 #define SMBHCTRL_BYTE           0x08
  176 #define SMBHCTRL_WORD           0x0c
  177 #define SMBHCTRL_BLOCK          0x14
  178 #define SMBHCTRL_KILL           0x02    /* stop the current transaction */
  179 #define SMBHCTRL_ENABLE         0x01    /* enable interrupts */
  180 
  181 #define SMBSCTRL_ENABLE         0x01    /* enable slave */
  182 
  183 
  184 /*
  185  * VIA8233 definitions
  186  */
  187 
  188 #define VIAPM_8233_BASE         0xD0
  189 
  190 static int
  191 viapm_586b_probe(device_t dev)
  192 {
  193         struct viapm_softc *viapm = (struct viapm_softc *)device_get_softc(dev);
  194         u_int32_t l;
  195         u_int16_t s;
  196         u_int8_t c;
  197 
  198         switch (pci_get_devid(dev)) {
  199         case VIA_586B_PMU_ID:
  200 
  201                 bzero(viapm, sizeof(struct viapm_softc));
  202 
  203                 l = pci_read_config(dev, VIAPM_586B_REVID, 1);
  204                 switch (l) {
  205                 case VIAPM_586B_OEM_REV_E:
  206                         viapm->type = VIAPM_TYP_586B_3040E;
  207                         viapm->iorid = VIAPM_586B_3040E_BASE;
  208 
  209                         /* Activate IO block access */
  210                         s = pci_read_config(dev, VIAPM_586B_3040E_ACTIV, 2);
  211                         pci_write_config(dev, VIAPM_586B_3040E_ACTIV, s | 0x1, 2);
  212                         break;
  213 
  214                 case VIAPM_586B_OEM_REV_F:
  215                 case VIAPM_586B_PROD_REV_A:
  216                 default:
  217                         viapm->type = VIAPM_TYP_586B_3040F;
  218                         viapm->iorid = VIAPM_586B_3040F_BASE;
  219 
  220                         /* Activate IO block access */
  221                         c = pci_read_config(dev, VIAPM_586B_3040F_ACTIV, 1);
  222                         pci_write_config(dev, VIAPM_586B_3040F_ACTIV, c | 0x80, 1);
  223                         break;
  224                 }
  225 
  226                 viapm->base = pci_read_config(dev, viapm->iorid, 4) &
  227                                 VIAPM_586B_BA_MASK;
  228 
  229                 /*
  230                  * We have to set the I/O resources by hand because it is
  231                  * described outside the viapmope of the traditional maps
  232                  */
  233                 if (bus_set_resource(dev, SYS_RES_IOPORT, viapm->iorid,
  234                                                         viapm->base, 256)) {
  235                         device_printf(dev, "could not set bus resource\n");
  236                         return ENXIO;
  237                 }
  238                 device_set_desc(dev, "VIA VT82C586B Power Management Unit");
  239                 return (BUS_PROBE_DEFAULT);
  240 
  241         default:
  242                 break;
  243         }
  244 
  245         return ENXIO;
  246 }
  247 
  248 
  249 static int
  250 viapm_pro_probe(device_t dev)
  251 {
  252         struct viapm_softc *viapm = (struct viapm_softc *)device_get_softc(dev);
  253 #ifdef VIAPM_BASE_ADDR
  254         u_int32_t l;
  255 #endif
  256         u_int32_t base_cfgreg;
  257         char *desc;
  258 
  259         switch (pci_get_devid(dev)) {
  260         case VIA_596A_PMU_ID:
  261                 desc = "VIA VT82C596A Power Management Unit";
  262                 viapm->type = VIAPM_TYP_596B;
  263                 base_cfgreg = VIAPM_PRO_BASE;
  264                 goto viapro;
  265 
  266         case VIA_596B_PMU_ID:
  267                 desc = "VIA VT82C596B Power Management Unit";
  268                 viapm->type = VIAPM_TYP_596B;
  269                 base_cfgreg = VIAPM_PRO_BASE;
  270                 goto viapro;
  271 
  272         case VIA_686A_PMU_ID:
  273                 desc = "VIA VT82C686A Power Management Unit";
  274                 viapm->type = VIAPM_TYP_686A;
  275                 base_cfgreg = VIAPM_PRO_BASE;
  276                 goto viapro;
  277 
  278         case VIA_8233_PMU_ID:
  279         case VIA_8233A_PMU_ID:
  280                 desc = "VIA VT8233 Power Management Unit";
  281                 viapm->type = VIAPM_TYP_UNKNOWN;
  282                 base_cfgreg = VIAPM_8233_BASE;
  283                 goto viapro;
  284 
  285         case VIA_8235_PMU_ID:
  286                 desc = "VIA VT8235 Power Management Unit";
  287                 viapm->type = VIAPM_TYP_UNKNOWN;
  288                 base_cfgreg = VIAPM_8233_BASE;
  289                 goto viapro;
  290 
  291         case VIA_8237_PMU_ID:
  292                 desc = "VIA VT8237 Power Management Unit";
  293                 viapm->type = VIAPM_TYP_UNKNOWN;
  294                 base_cfgreg = VIAPM_8233_BASE;
  295                 goto viapro;
  296 
  297         case VIA_CX700_PMU_ID:
  298                 desc = "VIA CX700 Power Management Unit";
  299                 viapm->type = VIAPM_TYP_UNKNOWN;
  300                 base_cfgreg = VIAPM_8233_BASE;
  301                 goto viapro;
  302 
  303         viapro:
  304 
  305 #ifdef VIAPM_BASE_ADDR
  306                 /* force VIAPM I/O base address */
  307 
  308                 /* enable the SMBus controller function */
  309                 l = pci_read_config(dev, VIAPM_PRO_SMBCTRL, 1);
  310                 pci_write_config(dev, VIAPM_PRO_SMBCTRL, l | 1, 1);
  311 
  312                 /* write the base address */
  313                 pci_write_config(dev, base_cfgreg,
  314                                  VIAPM_BASE_ADDR & VIAPM_PRO_BA_MASK, 4);
  315 #endif
  316 
  317                 viapm->base = pci_read_config(dev, base_cfgreg, 4) & VIAPM_PRO_BA_MASK;
  318 
  319                 /*
  320                  * We have to set the I/O resources by hand because it is
  321                  * described outside the viapmope of the traditional maps
  322                  */
  323                 viapm->iorid = base_cfgreg;
  324                 if (bus_set_resource(dev, SYS_RES_IOPORT, viapm->iorid,
  325                                      viapm->base, 16)) {
  326                         device_printf(dev, "could not set bus resource 0x%x\n",
  327                                         viapm->base);
  328                         return ENXIO;
  329                 }
  330 
  331                 if (bootverbose) {
  332                         device_printf(dev, "SMBus I/O base at 0x%x\n", viapm->base);
  333                 }
  334 
  335                 device_set_desc(dev, desc);
  336                 return (BUS_PROBE_DEFAULT);
  337 
  338         default:
  339                 break;
  340         }
  341 
  342         return ENXIO;
  343 }
  344 
  345 static int
  346 viapm_pro_attach(device_t dev)
  347 {
  348         struct viapm_softc *viapm = (struct viapm_softc *)device_get_softc(dev);
  349         u_int32_t l;
  350 
  351         mtx_init(&viapm->lock, device_get_nameunit(dev), "viapm", MTX_DEF);
  352         if (!(viapm->iores = bus_alloc_resource_any(dev, SYS_RES_IOPORT,
  353                 &viapm->iorid, RF_ACTIVE))) {
  354                 device_printf(dev, "could not allocate bus space\n");
  355                 goto error;
  356         }
  357         viapm->st = rman_get_bustag(viapm->iores);
  358         viapm->sh = rman_get_bushandle(viapm->iores);
  359 
  360 #ifdef notyet
  361         /* force irq 9 */
  362         l = pci_read_config(dev, VIAPM_PRO_SMBCTRL, 1);
  363         pci_write_config(dev, VIAPM_PRO_SMBCTRL, l | 0x80, 1);
  364 
  365         viapm->irqrid = 0;
  366         if (!(viapm->irqres = bus_alloc_resource(dev, SYS_RES_IRQ,
  367                                 &viapm->irqrid, 9, 9, 1,
  368                                 RF_SHAREABLE | RF_ACTIVE))) {
  369                 device_printf(dev, "could not allocate irq\n");
  370                 goto error;
  371         }
  372 
  373         if (bus_setup_intr(dev, viapm->irqres, INTR_TYPE_MISC,
  374                         (driver_intr_t *) viasmb_intr, viapm, &viapm->irqih)) {
  375                 device_printf(dev, "could not setup irq\n");
  376                 goto error;
  377         }
  378 #endif
  379 
  380         if (bootverbose) {
  381                 l = pci_read_config(dev, VIAPM_PRO_REVID, 1);
  382                 device_printf(dev, "SMBus revision code 0x%x\n", l);
  383         }
  384 
  385         viapm->smbus = device_add_child(dev, "smbus", -1);
  386 
  387         /* probe and attach the smbus */
  388         bus_generic_attach(dev);
  389 
  390         /* disable slave function */
  391         VIAPM_OUTB(SMBSCTRL, VIAPM_INB(SMBSCTRL) & ~SMBSCTRL_ENABLE);
  392 
  393         /* enable the SMBus controller function */
  394         l = pci_read_config(dev, VIAPM_PRO_SMBCTRL, 1);
  395         pci_write_config(dev, VIAPM_PRO_SMBCTRL, l | 1, 1);
  396 
  397 #ifdef notyet
  398         /* enable interrupts */
  399         VIAPM_OUTB(SMBHCTRL, VIAPM_INB(SMBHCTRL) | SMBHCTRL_ENABLE);
  400 #endif
  401 
  402 #ifdef DEV_ISA
  403         /* If this device is a PCI-ISA bridge, then attach an ISA bus. */
  404         if ((pci_get_class(dev) == PCIC_BRIDGE) &&
  405             (pci_get_subclass(dev) == PCIS_BRIDGE_ISA))
  406                 isab_attach(dev);
  407 #endif
  408         return 0;
  409 
  410 error:
  411         if (viapm->iores)
  412                 bus_release_resource(dev, SYS_RES_IOPORT, viapm->iorid, viapm->iores);
  413 #ifdef notyet
  414         if (viapm->irqres)
  415                 bus_release_resource(dev, SYS_RES_IRQ, viapm->irqrid, viapm->irqres);
  416 #endif
  417         mtx_destroy(&viapm->lock);
  418 
  419         return ENXIO;
  420 }
  421 
  422 static int
  423 viapm_586b_attach(device_t dev)
  424 {
  425         struct viapm_softc *viapm = (struct viapm_softc *)device_get_softc(dev);
  426 
  427         mtx_init(&viapm->lock, device_get_nameunit(dev), "viapm", MTX_DEF);
  428         if (!(viapm->iores = bus_alloc_resource_any(dev, SYS_RES_IOPORT,
  429                 &viapm->iorid, RF_ACTIVE | RF_SHAREABLE))) {
  430                 device_printf(dev, "could not allocate bus resource\n");
  431                 goto error;
  432         }
  433         viapm->st = rman_get_bustag(viapm->iores);
  434         viapm->sh = rman_get_bushandle(viapm->iores);
  435 
  436         VIAPM_OUTB(GPIO_DIR, VIAPM_INB(GPIO_DIR) | VIAPM_SCL | VIAPM_SDA);
  437 
  438         /* add generic bit-banging code */
  439         if (!(viapm->iicbb = device_add_child(dev, "iicbb", -1)))
  440                 goto error;
  441 
  442         bus_generic_attach(dev);
  443 
  444         return 0;
  445 
  446 error:
  447         if (viapm->iores)
  448                 bus_release_resource(dev, SYS_RES_IOPORT,
  449                                         viapm->iorid, viapm->iores);
  450         mtx_destroy(&viapm->lock);
  451         return ENXIO;
  452 }
  453 
  454 static int
  455 viapm_586b_detach(device_t dev)
  456 {
  457         struct viapm_softc *viapm = (struct viapm_softc *)device_get_softc(dev);
  458 
  459         bus_generic_detach(dev);
  460         if (viapm->iicbb) {
  461                 device_delete_child(dev, viapm->iicbb);
  462         }
  463 
  464         if (viapm->iores)
  465                 bus_release_resource(dev, SYS_RES_IOPORT, viapm->iorid,
  466                     viapm->iores);
  467         mtx_destroy(&viapm->lock);
  468 
  469         return 0;
  470 }
  471 
  472 static int
  473 viapm_pro_detach(device_t dev)
  474 {
  475         struct viapm_softc *viapm = (struct viapm_softc *)device_get_softc(dev);
  476 
  477         bus_generic_detach(dev);
  478         if (viapm->smbus) {
  479                 device_delete_child(dev, viapm->smbus);
  480         }
  481 
  482         bus_release_resource(dev, SYS_RES_IOPORT, viapm->iorid, viapm->iores);
  483 
  484 #ifdef notyet
  485         bus_release_resource(dev, SYS_RES_IRQ, viapm->irqrid, viapm->irqres);
  486 #endif
  487         mtx_destroy(&viapm->lock);
  488 
  489         return 0;
  490 }
  491 
  492 static int
  493 viabb_callback(device_t dev, int index, caddr_t *data)
  494 {
  495         return 0;
  496 }
  497 
  498 static void
  499 viabb_setscl(device_t dev, int ctrl)
  500 {
  501         struct viapm_softc *viapm = device_get_softc(dev);
  502         u_char val;
  503 
  504         VIAPM_LOCK(viapm);
  505         val = VIAPM_INB(GPIO_VAL);
  506 
  507         if (ctrl)
  508                 val |= VIAPM_SCL;
  509         else
  510                 val &= ~VIAPM_SCL;
  511 
  512         VIAPM_OUTB(GPIO_VAL, val);
  513         VIAPM_UNLOCK(viapm);
  514 
  515         return;
  516 }
  517 
  518 static void
  519 viabb_setsda(device_t dev, int data)
  520 {
  521         struct viapm_softc *viapm = device_get_softc(dev);
  522         u_char val;
  523 
  524         VIAPM_LOCK(viapm);
  525         val = VIAPM_INB(GPIO_VAL);
  526 
  527         if (data)
  528                 val |= VIAPM_SDA;
  529         else
  530                 val &= ~VIAPM_SDA;
  531 
  532         VIAPM_OUTB(GPIO_VAL, val);
  533         VIAPM_UNLOCK(viapm);
  534 
  535         return;
  536 }
  537         
  538 static int
  539 viabb_reset(device_t dev, u_char speed, u_char addr, u_char *oldaddr)
  540 {
  541         /* reset bus */
  542         viabb_setsda(dev, 1);
  543         viabb_setscl(dev, 1);
  544 
  545         return (IIC_ENOADDR);
  546 }
  547 
  548 static int
  549 viabb_getscl(device_t dev)
  550 {
  551         struct viapm_softc *viapm = device_get_softc(dev);
  552         u_char val;
  553 
  554         VIAPM_LOCK(viapm);
  555         val = VIAPM_INB(EXTSMI_VAL);
  556         VIAPM_UNLOCK(viapm);
  557         return ((val & VIAPM_SCL) != 0);
  558 }
  559 
  560 static int
  561 viabb_getsda(device_t dev)
  562 {
  563         struct viapm_softc *viapm = device_get_softc(dev);
  564         u_char val;
  565 
  566         VIAPM_LOCK(viapm);
  567         val = VIAPM_INB(EXTSMI_VAL);
  568         VIAPM_UNLOCK(viapm);
  569         return ((val & VIAPM_SDA) != 0);
  570 }
  571 
  572 static int
  573 viapm_abort(struct viapm_softc *viapm)
  574 {
  575         VIAPM_OUTB(SMBHCTRL, SMBHCTRL_KILL);
  576         DELAY(10);
  577 
  578         return (0);
  579 }
  580 
  581 static int
  582 viapm_clear(struct viapm_softc *viapm)
  583 {
  584         VIAPM_OUTB(SMBHST, SMBHST_FAILED | SMBHST_COLLID |
  585                 SMBHST_ERROR | SMBHST_INTR);
  586         DELAY(10);
  587 
  588         return (0);
  589 }
  590 
  591 static int
  592 viapm_busy(struct viapm_softc *viapm)
  593 {
  594         u_char sts;
  595 
  596         sts = VIAPM_INB(SMBHST);
  597 
  598         VIAPM_DEBUG(printf("viapm: idle? STS=0x%x\n", sts));
  599 
  600         return (sts & SMBHST_BUSY);
  601 }
  602 
  603 /*
  604  * Poll the SMBus controller
  605  */
  606 static int
  607 viapm_wait(struct viapm_softc *viapm)
  608 {
  609         int count = 10000;
  610         u_char sts = 0;
  611         int error;
  612 
  613         VIAPM_LOCK_ASSERT(viapm);
  614 
  615         /* wait for command to complete and SMBus controller is idle */
  616         while(count--) {
  617                 DELAY(10);
  618                 sts = VIAPM_INB(SMBHST);
  619 
  620                 /* check if the controller is processing a command */
  621                 if (!(sts & SMBHST_BUSY) && (sts & SMBHST_INTR))
  622                         break;
  623         }
  624 
  625         VIAPM_DEBUG(printf("viapm: SMBHST=0x%x\n", sts));
  626 
  627         error = SMB_ENOERR;
  628 
  629         if (!count)
  630                 error |= SMB_ETIMEOUT;
  631 
  632         if (sts & SMBHST_FAILED)
  633                 error |= SMB_EABORT;
  634 
  635         if (sts & SMBHST_COLLID)
  636                 error |= SMB_ENOACK;
  637 
  638         if (sts & SMBHST_ERROR)
  639                 error |= SMB_EBUSERR;
  640 
  641         if (error != SMB_ENOERR)
  642                 viapm_abort(viapm);
  643 
  644         viapm_clear(viapm);
  645 
  646         return (error);
  647 }
  648 
  649 static int
  650 viasmb_callback(device_t dev, int index, caddr_t *data)
  651 {
  652         int error = 0;
  653 
  654         switch (index) {
  655         case SMB_REQUEST_BUS:
  656         case SMB_RELEASE_BUS:
  657                 /* ok, bus allocation accepted */
  658                 break;
  659         default:
  660                 error = EINVAL;
  661         }
  662 
  663         return (error);
  664 }
  665 
  666 static int
  667 viasmb_quick(device_t dev, u_char slave, int how)
  668 {
  669         struct viapm_softc *viapm = (struct viapm_softc *)device_get_softc(dev);
  670         int error;
  671 
  672         VIAPM_LOCK(viapm);
  673         viapm_clear(viapm);
  674         if (viapm_busy(viapm)) {
  675                 VIAPM_UNLOCK(viapm);
  676                 return (SMB_EBUSY);
  677         }
  678 
  679         switch (how) {
  680         case SMB_QWRITE:
  681                 VIAPM_DEBUG(printf("viapm: QWRITE to 0x%x", slave));
  682                 VIAPM_OUTB(SMBHADDR, slave & ~LSB);
  683                 break;
  684         case SMB_QREAD:
  685                 VIAPM_DEBUG(printf("viapm: QREAD to 0x%x", slave));
  686                 VIAPM_OUTB(SMBHADDR, slave | LSB);
  687                 break;
  688         default:
  689                 panic("%s: unknown QUICK command (%x)!", __func__, how);
  690         }
  691 
  692         VIAPM_OUTB(SMBHCTRL, SMBHCTRL_START | SMBHCTRL_QUICK);
  693 
  694         error = viapm_wait(viapm);
  695         VIAPM_UNLOCK(viapm);
  696 
  697         return (error);
  698 }
  699 
  700 static int
  701 viasmb_sendb(device_t dev, u_char slave, char byte)
  702 {
  703         struct viapm_softc *viapm = (struct viapm_softc *)device_get_softc(dev);
  704         int error;
  705 
  706         VIAPM_LOCK(viapm);
  707         viapm_clear(viapm);
  708         if (viapm_busy(viapm)) {
  709                 VIAPM_UNLOCK(viapm);
  710                 return (SMB_EBUSY);
  711         }
  712 
  713         VIAPM_OUTB(SMBHADDR, slave & ~ LSB);
  714         VIAPM_OUTB(SMBHCMD, byte);
  715 
  716         VIAPM_OUTB(SMBHCTRL, SMBHCTRL_START | SMBHCTRL_SENDRECV);
  717 
  718         error = viapm_wait(viapm);
  719 
  720         VIAPM_DEBUG(printf("viapm: SENDB to 0x%x, byte=0x%x, error=0x%x\n", slave, byte, error));
  721         VIAPM_UNLOCK(viapm);
  722 
  723         return (error);
  724 }
  725 
  726 static int
  727 viasmb_recvb(device_t dev, u_char slave, char *byte)
  728 {
  729         struct viapm_softc *viapm = (struct viapm_softc *)device_get_softc(dev);
  730         int error;
  731 
  732         VIAPM_LOCK(viapm);
  733         viapm_clear(viapm);
  734         if (viapm_busy(viapm)) {
  735                 VIAPM_UNLOCK(viapm);
  736                 return (SMB_EBUSY);
  737         }
  738 
  739         VIAPM_OUTB(SMBHADDR, slave | LSB);
  740 
  741         VIAPM_OUTB(SMBHCTRL, SMBHCTRL_START | SMBHCTRL_SENDRECV);
  742 
  743         if ((error = viapm_wait(viapm)) == SMB_ENOERR)
  744                 *byte = VIAPM_INB(SMBHDATA0);
  745 
  746         VIAPM_DEBUG(printf("viapm: RECVB from 0x%x, byte=0x%x, error=0x%x\n", slave, *byte, error));
  747         VIAPM_UNLOCK(viapm);
  748 
  749         return (error);
  750 }
  751 
  752 static int
  753 viasmb_writeb(device_t dev, u_char slave, char cmd, char byte)
  754 {
  755         struct viapm_softc *viapm = (struct viapm_softc *)device_get_softc(dev);
  756         int error;
  757 
  758         VIAPM_LOCK(viapm);
  759         viapm_clear(viapm);
  760         if (viapm_busy(viapm)) {
  761                 VIAPM_UNLOCK(viapm);
  762                 return (SMB_EBUSY);
  763         }
  764 
  765         VIAPM_OUTB(SMBHADDR, slave & ~ LSB);
  766         VIAPM_OUTB(SMBHCMD, cmd);
  767         VIAPM_OUTB(SMBHDATA0, byte);
  768 
  769         VIAPM_OUTB(SMBHCTRL, SMBHCTRL_START | SMBHCTRL_BYTE);
  770 
  771         error = viapm_wait(viapm);
  772 
  773         VIAPM_DEBUG(printf("viapm: WRITEB to 0x%x, cmd=0x%x, byte=0x%x, error=0x%x\n", slave, cmd, byte, error));
  774         VIAPM_UNLOCK(viapm);
  775 
  776         return (error);
  777 }
  778 
  779 static int
  780 viasmb_readb(device_t dev, u_char slave, char cmd, char *byte)
  781 {
  782         struct viapm_softc *viapm = (struct viapm_softc *)device_get_softc(dev);
  783         int error;
  784 
  785         VIAPM_LOCK(viapm);
  786         viapm_clear(viapm);
  787         if (viapm_busy(viapm)) {
  788                 VIAPM_UNLOCK(viapm);
  789                 return (SMB_EBUSY);
  790         }
  791 
  792         VIAPM_OUTB(SMBHADDR, slave | LSB);
  793         VIAPM_OUTB(SMBHCMD, cmd);
  794 
  795         VIAPM_OUTB(SMBHCTRL, SMBHCTRL_START | SMBHCTRL_BYTE);
  796 
  797         if ((error = viapm_wait(viapm)) == SMB_ENOERR)
  798                 *byte = VIAPM_INB(SMBHDATA0);
  799 
  800         VIAPM_DEBUG(printf("viapm: READB from 0x%x, cmd=0x%x, byte=0x%x, error=0x%x\n", slave, cmd, *byte, error));
  801         VIAPM_UNLOCK(viapm);
  802 
  803         return (error);
  804 }
  805 
  806 static int
  807 viasmb_writew(device_t dev, u_char slave, char cmd, short word)
  808 {
  809         struct viapm_softc *viapm = (struct viapm_softc *)device_get_softc(dev);
  810         int error;
  811 
  812         VIAPM_LOCK(viapm);
  813         viapm_clear(viapm);
  814         if (viapm_busy(viapm)) {
  815                 VIAPM_UNLOCK(viapm);
  816                 return (SMB_EBUSY);
  817         }
  818 
  819         VIAPM_OUTB(SMBHADDR, slave & ~ LSB);
  820         VIAPM_OUTB(SMBHCMD, cmd);
  821         VIAPM_OUTB(SMBHDATA0, word & 0x00ff);
  822         VIAPM_OUTB(SMBHDATA1, (word & 0xff00) >> 8);
  823 
  824         VIAPM_OUTB(SMBHCTRL, SMBHCTRL_START | SMBHCTRL_WORD);
  825 
  826         error = viapm_wait(viapm);
  827 
  828         VIAPM_DEBUG(printf("viapm: WRITEW to 0x%x, cmd=0x%x, word=0x%x, error=0x%x\n", slave, cmd, word, error));
  829         VIAPM_UNLOCK(viapm);
  830 
  831         return (error);
  832 }
  833 
  834 static int
  835 viasmb_readw(device_t dev, u_char slave, char cmd, short *word)
  836 {
  837         struct viapm_softc *viapm = (struct viapm_softc *)device_get_softc(dev);
  838         int error;
  839         u_char high, low;
  840 
  841         VIAPM_LOCK(viapm);
  842         viapm_clear(viapm);
  843         if (viapm_busy(viapm)) {
  844                 VIAPM_UNLOCK(viapm);
  845                 return (SMB_EBUSY);
  846         }
  847 
  848         VIAPM_OUTB(SMBHADDR, slave | LSB);
  849         VIAPM_OUTB(SMBHCMD, cmd);
  850 
  851         VIAPM_OUTB(SMBHCTRL, SMBHCTRL_START | SMBHCTRL_WORD);
  852 
  853         if ((error = viapm_wait(viapm)) == SMB_ENOERR) {
  854                 low = VIAPM_INB(SMBHDATA0);
  855                 high = VIAPM_INB(SMBHDATA1);
  856 
  857                 *word = ((high & 0xff) << 8) | (low & 0xff);
  858         }
  859 
  860         VIAPM_DEBUG(printf("viapm: READW from 0x%x, cmd=0x%x, word=0x%x, error=0x%x\n", slave, cmd, *word, error));
  861         VIAPM_UNLOCK(viapm);
  862 
  863         return (error);
  864 }
  865 
  866 static int
  867 viasmb_bwrite(device_t dev, u_char slave, char cmd, u_char count, char *buf)
  868 {
  869         struct viapm_softc *viapm = (struct viapm_softc *)device_get_softc(dev);
  870         u_char i;
  871         int error;
  872 
  873         if (count < 1 || count > 32)
  874                 return (SMB_EINVAL);
  875 
  876         VIAPM_LOCK(viapm);
  877         viapm_clear(viapm);
  878         if (viapm_busy(viapm)) {
  879                 VIAPM_UNLOCK(viapm);
  880                 return (SMB_EBUSY);
  881         }
  882 
  883         VIAPM_OUTB(SMBHADDR, slave & ~LSB);
  884         VIAPM_OUTB(SMBHCMD, cmd);
  885         VIAPM_OUTB(SMBHDATA0, count);
  886         i = VIAPM_INB(SMBHCTRL);
  887 
  888         /* fill the 32-byte internal buffer */
  889         for (i = 0; i < count; i++) {
  890                 VIAPM_OUTB(SMBHBLOCK, buf[i]);
  891                 DELAY(2);
  892         }
  893         VIAPM_OUTB(SMBHCMD, cmd);
  894         VIAPM_OUTB(SMBHCTRL, SMBHCTRL_START | SMBHCTRL_BLOCK);
  895 
  896         error = viapm_wait(viapm);
  897 
  898         VIAPM_DEBUG(printf("viapm: WRITEBLK to 0x%x, count=0x%x, cmd=0x%x, error=0x%x", slave, count, cmd, error));
  899         VIAPM_UNLOCK(viapm);
  900 
  901         return (error);
  902 
  903 }
  904 
  905 static int
  906 viasmb_bread(device_t dev, u_char slave, char cmd, u_char *count, char *buf)
  907 {
  908         struct viapm_softc *viapm = (struct viapm_softc *)device_get_softc(dev);
  909         u_char data, len, i;
  910         int error;
  911 
  912         if (*count < 1 || *count > 32)
  913                 return (SMB_EINVAL);
  914 
  915         VIAPM_LOCK(viapm);
  916         viapm_clear(viapm);
  917         if (viapm_busy(viapm)) {
  918                 VIAPM_UNLOCK(viapm);
  919                 return (SMB_EBUSY);
  920         }
  921 
  922         VIAPM_OUTB(SMBHADDR, slave | LSB);
  923         VIAPM_OUTB(SMBHCMD, cmd);
  924         VIAPM_OUTB(SMBHCTRL, SMBHCTRL_START | SMBHCTRL_BLOCK);
  925 
  926         if ((error = viapm_wait(viapm)) != SMB_ENOERR)
  927                 goto error;
  928 
  929         len = VIAPM_INB(SMBHDATA0);
  930         i = VIAPM_INB(SMBHCTRL);                /* reset counter */
  931 
  932         /* read the 32-byte internal buffer */
  933         for (i = 0; i < len; i++) {
  934                 data = VIAPM_INB(SMBHBLOCK);
  935                 if (i < *count)
  936                         buf[i] = data;
  937                 DELAY(2);
  938         }
  939         *count = len;
  940 
  941 error:
  942         VIAPM_DEBUG(printf("viapm: READBLK to 0x%x, count=0x%x, cmd=0x%x, error=0x%x", slave, *count, cmd, error));
  943         VIAPM_UNLOCK(viapm);
  944 
  945         return (error);
  946 }
  947 
  948 static device_method_t viapm_methods[] = {
  949         /* device interface */
  950         DEVMETHOD(device_probe,         viapm_586b_probe),
  951         DEVMETHOD(device_attach,        viapm_586b_attach),
  952         DEVMETHOD(device_detach,        viapm_586b_detach),
  953 
  954         /* iicbb interface */
  955         DEVMETHOD(iicbb_callback,       viabb_callback),
  956         DEVMETHOD(iicbb_setscl,         viabb_setscl),
  957         DEVMETHOD(iicbb_setsda,         viabb_setsda),
  958         DEVMETHOD(iicbb_getscl,         viabb_getscl),
  959         DEVMETHOD(iicbb_getsda,         viabb_getsda),
  960         DEVMETHOD(iicbb_reset,          viabb_reset),
  961 
  962         /* Bus interface */
  963         DEVMETHOD(bus_print_child,      bus_generic_print_child),
  964         DEVMETHOD(bus_alloc_resource,   bus_generic_alloc_resource),
  965         DEVMETHOD(bus_release_resource, bus_generic_release_resource),
  966         DEVMETHOD(bus_activate_resource, bus_generic_activate_resource),
  967         DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource),
  968         DEVMETHOD(bus_setup_intr,       bus_generic_setup_intr),
  969         DEVMETHOD(bus_teardown_intr,    bus_generic_teardown_intr),
  970 
  971         { 0, 0 }
  972 };
  973 
  974 static driver_t viapm_driver = {
  975         "viapm",
  976         viapm_methods,
  977         sizeof(struct viapm_softc),
  978 };
  979 
  980 static device_method_t viapropm_methods[] = {
  981         /* device interface */
  982         DEVMETHOD(device_probe,         viapm_pro_probe),
  983         DEVMETHOD(device_attach,        viapm_pro_attach),
  984         DEVMETHOD(device_detach,        viapm_pro_detach),
  985 
  986         /* smbus interface */
  987         DEVMETHOD(smbus_callback,       viasmb_callback),
  988         DEVMETHOD(smbus_quick,          viasmb_quick),
  989         DEVMETHOD(smbus_sendb,          viasmb_sendb),
  990         DEVMETHOD(smbus_recvb,          viasmb_recvb),
  991         DEVMETHOD(smbus_writeb,         viasmb_writeb),
  992         DEVMETHOD(smbus_readb,          viasmb_readb),
  993         DEVMETHOD(smbus_writew,         viasmb_writew),
  994         DEVMETHOD(smbus_readw,          viasmb_readw),
  995         DEVMETHOD(smbus_bwrite,         viasmb_bwrite),
  996         DEVMETHOD(smbus_bread,          viasmb_bread),
  997         
  998         /* Bus interface */
  999         DEVMETHOD(bus_print_child,      bus_generic_print_child),
 1000         DEVMETHOD(bus_alloc_resource,   bus_generic_alloc_resource),
 1001         DEVMETHOD(bus_release_resource, bus_generic_release_resource),
 1002         DEVMETHOD(bus_activate_resource, bus_generic_activate_resource),
 1003         DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource),
 1004         DEVMETHOD(bus_setup_intr,       bus_generic_setup_intr),
 1005         DEVMETHOD(bus_teardown_intr,    bus_generic_teardown_intr),
 1006 
 1007         { 0, 0 }
 1008 };
 1009 
 1010 static driver_t viapropm_driver = {
 1011         "viapropm",
 1012         viapropm_methods,
 1013         sizeof(struct viapm_softc),
 1014 };
 1015 
 1016 DRIVER_MODULE(viapm, pci, viapm_driver, viapm_devclass, 0, 0);
 1017 DRIVER_MODULE(viapropm, pci, viapropm_driver, viapropm_devclass, 0, 0);
 1018 DRIVER_MODULE(smbus, viapropm, smbus_driver, smbus_devclass, 0, 0);
 1019 
 1020 MODULE_DEPEND(viapm, pci, 1, 1, 1);
 1021 MODULE_DEPEND(viapropm, pci, 1, 1, 1);
 1022 MODULE_DEPEND(viapm, iicbb, IICBB_MINVER, IICBB_PREFVER, IICBB_MAXVER);
 1023 MODULE_DEPEND(viapropm, smbus, SMBUS_MINVER, SMBUS_PREFVER, SMBUS_MAXVER);
 1024 MODULE_VERSION(viapm, 1);
 1025 
 1026 #ifdef DEV_ISA
 1027 DRIVER_MODULE(isa, viapm, isa_driver, isa_devclass, 0, 0);
 1028 DRIVER_MODULE(isa, viapropm, isa_driver, isa_devclass, 0, 0);
 1029 MODULE_DEPEND(viapm, isa, 1, 1, 1);
 1030 MODULE_DEPEND(viapropm, isa, 1, 1, 1);
 1031 #endif

Cache object: 6a6e745c1a33579eadea5e984a88a94d


[ 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.