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

Cache object: 633212887fa4f3663acc6c478c4c2704


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