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

Cache object: 650b2e2778ed589527773cbe3add43b1


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