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

Cache object: 3602b821f2bcd01bea09e60f64879f89


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