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  * Copyright (c) 2002 Nicolas Souchu
    4  * All rights reserved.
    5  *
    6  * Redistribution and use in source and binary forms, with or without
    7  * modification, are permitted provided that the following conditions
    8  * are met:
    9  * 1. Redistributions of source code must retain the above copyright
   10  *    notice, this list of conditions and the following disclaimer.
   11  * 2. Redistributions in binary form must reproduce the above copyright
   12  *    notice, this list of conditions and the following disclaimer in the
   13  *    documentation and/or other materials provided with the distribution.
   14  *
   15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   16  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   18  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
   19  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   20  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   21  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   22  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   23  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   24  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   25  * SUCH DAMAGE.
   26  *
   27  * $FreeBSD$
   28  *
   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 <pci/pcivar.h>
   45 #include <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 #if 0
  512 static int
  513 viabb_getscl(device_t dev)
  514 {
  515         struct viapm_softc *viapm = device_get_softc(dev);
  516 
  517         return ((VIAPM_INB(EXTSMI_VAL) & VIAPM_SCL) != 0);
  518 }
  519 #endif
  520 
  521 static int
  522 viabb_getsda(device_t dev)
  523 {
  524         struct viapm_softc *viapm = device_get_softc(dev);
  525 
  526         return ((VIAPM_INB(EXTSMI_VAL) & VIAPM_SDA) != 0);
  527 }
  528 
  529 static void
  530 viabb_setlines(device_t dev, int ctrl, int data)
  531 {
  532         viabb_setscl(dev, ctrl);
  533         viabb_setsda(dev, data);
  534 
  535         return;
  536 }
  537 
  538 static int
  539 viapm_abort(struct viapm_softc *viapm)
  540 {
  541         VIAPM_OUTB(SMBHCTRL, SMBHCTRL_KILL);
  542         DELAY(10);
  543 
  544         return (0);
  545 }
  546 
  547 static int
  548 viapm_clear(struct viapm_softc *viapm)
  549 {
  550         VIAPM_OUTB(SMBHST, SMBHST_FAILED | SMBHST_COLLID |
  551                 SMBHST_ERROR | SMBHST_INTR);
  552         DELAY(10);
  553 
  554         return (0);
  555 }
  556 
  557 static int
  558 viapm_busy(struct viapm_softc *viapm)
  559 {
  560         u_char sts;
  561 
  562         sts = VIAPM_INB(SMBHST);
  563 
  564         VIAPM_DEBUG(printf("viapm: idle? STS=0x%x\n", sts));
  565 
  566         return (sts & SMBHST_BUSY);
  567 }
  568 
  569 /*
  570  * Poll the SMBus controller
  571  */
  572 static int
  573 viapm_wait(struct viapm_softc *viapm)
  574 {
  575         int count = 10000;
  576         u_char sts = 0;
  577         int error;
  578 
  579         /* wait for command to complete and SMBus controller is idle */
  580         while(count--) {
  581                 DELAY(10);
  582                 sts = VIAPM_INB(SMBHST);
  583 
  584                 /* check if the controller is processing a command */
  585                 if (!(sts & SMBHST_BUSY) && (sts & SMBHST_INTR))
  586                         break;
  587         }
  588 
  589         VIAPM_DEBUG(printf("viapm: SMBHST=0x%x\n", sts));
  590 
  591         error = SMB_ENOERR;
  592 
  593         if (!count)
  594                 error |= SMB_ETIMEOUT;
  595 
  596         if (sts & SMBHST_FAILED)
  597                 error |= SMB_EABORT;
  598 
  599         if (sts & SMBHST_COLLID)
  600                 error |= SMB_ENOACK;
  601 
  602         if (sts & SMBHST_ERROR)
  603                 error |= SMB_EBUSERR;
  604 
  605         if (error != SMB_ENOERR)
  606                 viapm_abort(viapm);
  607 
  608         viapm_clear(viapm);
  609 
  610         return (error);
  611 }
  612 
  613 static int
  614 viasmb_callback(device_t dev, int index, caddr_t *data)
  615 {
  616         int error = 0;
  617 
  618         switch (index) {
  619         case SMB_REQUEST_BUS:
  620         case SMB_RELEASE_BUS:
  621                 /* ok, bus allocation accepted */
  622                 break;
  623         default:
  624                 error = EINVAL;
  625         }
  626 
  627         return (error);
  628 }
  629 
  630 static int
  631 viasmb_quick(device_t dev, u_char slave, int how)
  632 {
  633         struct viapm_softc *viapm = (struct viapm_softc *)device_get_softc(dev);
  634         int error;
  635 
  636         viapm_clear(viapm);
  637         if (viapm_busy(viapm))
  638                 return (EBUSY);
  639 
  640         switch (how) {
  641         case SMB_QWRITE:
  642                 VIAPM_DEBUG(printf("viapm: QWRITE to 0x%x", slave));
  643                 VIAPM_OUTB(SMBHADDR, slave & ~LSB);
  644                 break;
  645         case SMB_QREAD:
  646                 VIAPM_DEBUG(printf("viapm: QREAD to 0x%x", slave));
  647                 VIAPM_OUTB(SMBHADDR, slave | LSB);
  648                 break;
  649         default:
  650                 panic("%s: unknown QUICK command (%x)!", __FUNCTION__,
  651                         how);
  652         }
  653 
  654         VIAPM_OUTB(SMBHCTRL, SMBHCTRL_START | SMBHCTRL_QUICK);
  655 
  656         error = viapm_wait(viapm);
  657 
  658         return (error);
  659 }
  660 
  661 static int
  662 viasmb_sendb(device_t dev, u_char slave, char byte)
  663 {
  664         struct viapm_softc *viapm = (struct viapm_softc *)device_get_softc(dev);
  665         int error;
  666 
  667         viapm_clear(viapm);
  668         if (viapm_busy(viapm))
  669                 return (EBUSY);
  670 
  671         VIAPM_OUTB(SMBHADDR, slave & ~ LSB);
  672         VIAPM_OUTB(SMBHCMD, byte);
  673 
  674         VIAPM_OUTB(SMBHCTRL, SMBHCTRL_START | SMBHCTRL_SENDRECV);
  675 
  676         error = viapm_wait(viapm);
  677 
  678         VIAPM_DEBUG(printf("viapm: SENDB to 0x%x, byte=0x%x, error=0x%x\n", slave, byte, error));
  679 
  680         return (error);
  681 }
  682 
  683 static int
  684 viasmb_recvb(device_t dev, u_char slave, char *byte)
  685 {
  686         struct viapm_softc *viapm = (struct viapm_softc *)device_get_softc(dev);
  687         int error;
  688 
  689         viapm_clear(viapm);
  690         if (viapm_busy(viapm))
  691                 return (EBUSY);
  692 
  693         VIAPM_OUTB(SMBHADDR, slave | LSB);
  694 
  695         VIAPM_OUTB(SMBHCTRL, SMBHCTRL_START | SMBHCTRL_SENDRECV);
  696 
  697         if ((error = viapm_wait(viapm)) == SMB_ENOERR)
  698                 *byte = VIAPM_INB(SMBHDATA0);
  699 
  700         VIAPM_DEBUG(printf("viapm: RECVB from 0x%x, byte=0x%x, error=0x%x\n", slave, *byte, error));
  701 
  702         return (error);
  703 }
  704 
  705 static int
  706 viasmb_writeb(device_t dev, u_char slave, char cmd, char byte)
  707 {
  708         struct viapm_softc *viapm = (struct viapm_softc *)device_get_softc(dev);
  709         int error;
  710 
  711         viapm_clear(viapm);
  712         if (viapm_busy(viapm))
  713                 return (EBUSY);
  714 
  715         VIAPM_OUTB(SMBHADDR, slave & ~ LSB);
  716         VIAPM_OUTB(SMBHCMD, cmd);
  717         VIAPM_OUTB(SMBHDATA0, byte);
  718 
  719         VIAPM_OUTB(SMBHCTRL, SMBHCTRL_START | SMBHCTRL_BYTE);
  720 
  721         error = viapm_wait(viapm);
  722 
  723         VIAPM_DEBUG(printf("viapm: WRITEB to 0x%x, cmd=0x%x, byte=0x%x, error=0x%x\n", slave, cmd, byte, error));
  724 
  725         return (error);
  726 }
  727 
  728 static int
  729 viasmb_readb(device_t dev, u_char slave, char cmd, char *byte)
  730 {
  731         struct viapm_softc *viapm = (struct viapm_softc *)device_get_softc(dev);
  732         int error;
  733 
  734         viapm_clear(viapm);
  735         if (viapm_busy(viapm))
  736                 return (EBUSY);
  737 
  738         VIAPM_OUTB(SMBHADDR, slave | LSB);
  739         VIAPM_OUTB(SMBHCMD, cmd);
  740 
  741         VIAPM_OUTB(SMBHCTRL, SMBHCTRL_START | SMBHCTRL_BYTE);
  742 
  743         if ((error = viapm_wait(viapm)) == SMB_ENOERR)
  744                 *byte = VIAPM_INB(SMBHDATA0);
  745 
  746         VIAPM_DEBUG(printf("viapm: READB from 0x%x, cmd=0x%x, byte=0x%x, error=0x%x\n", slave, cmd, *byte, error));
  747 
  748         return (error);
  749 }
  750 
  751 static int
  752 viasmb_writew(device_t dev, u_char slave, char cmd, short word)
  753 {
  754         struct viapm_softc *viapm = (struct viapm_softc *)device_get_softc(dev);
  755         int error;
  756 
  757         viapm_clear(viapm);
  758         if (viapm_busy(viapm))
  759                 return (EBUSY);
  760 
  761         VIAPM_OUTB(SMBHADDR, slave & ~ LSB);
  762         VIAPM_OUTB(SMBHCMD, cmd);
  763         VIAPM_OUTB(SMBHDATA0, word & 0x00ff);
  764         VIAPM_OUTB(SMBHDATA1, (word & 0xff00) >> 8);
  765 
  766         VIAPM_OUTB(SMBHCTRL, SMBHCTRL_START | SMBHCTRL_WORD);
  767 
  768         error = viapm_wait(viapm);
  769 
  770         VIAPM_DEBUG(printf("viapm: WRITEW to 0x%x, cmd=0x%x, word=0x%x, error=0x%x\n", slave, cmd, word, error));
  771 
  772         return (error);
  773 }
  774 
  775 static int
  776 viasmb_readw(device_t dev, u_char slave, char cmd, short *word)
  777 {
  778         struct viapm_softc *viapm = (struct viapm_softc *)device_get_softc(dev);
  779         int error;
  780         u_char high, low;
  781 
  782         viapm_clear(viapm);
  783         if (viapm_busy(viapm))
  784                 return (EBUSY);
  785 
  786         VIAPM_OUTB(SMBHADDR, slave | LSB);
  787         VIAPM_OUTB(SMBHCMD, cmd);
  788 
  789         VIAPM_OUTB(SMBHCTRL, SMBHCTRL_START | SMBHCTRL_WORD);
  790 
  791         if ((error = viapm_wait(viapm)) == SMB_ENOERR) {
  792                 low = VIAPM_INB(SMBHDATA0);
  793                 high = VIAPM_INB(SMBHDATA1);
  794 
  795                 *word = ((high & 0xff) << 8) | (low & 0xff);
  796         }
  797 
  798         VIAPM_DEBUG(printf("viapm: READW from 0x%x, cmd=0x%x, word=0x%x, error=0x%x\n", slave, cmd, *word, error));
  799 
  800         return (error);
  801 }
  802 
  803 static int
  804 viasmb_bwrite(device_t dev, u_char slave, char cmd, u_char count, char *buf)
  805 {
  806         struct viapm_softc *viapm = (struct viapm_softc *)device_get_softc(dev);
  807         u_char remain, len, i;
  808         int error = SMB_ENOERR;
  809 
  810         viapm_clear(viapm);
  811         if (viapm_busy(viapm))
  812                 return (EBUSY);
  813 
  814         remain = count;
  815         while (remain) {
  816                 len = min(remain, 32);
  817 
  818                 VIAPM_OUTB(SMBHADDR, slave & ~LSB);
  819                 VIAPM_OUTB(SMBHCMD, cmd);
  820                 VIAPM_OUTB(SMBHDATA0, len);
  821                 i = VIAPM_INB(SMBHCTRL);
  822 
  823                 /* fill the 32-byte internal buffer */
  824                 for (i=0; i<len; i++) {
  825                         VIAPM_OUTB(SMBHBLOCK, buf[count-remain+i]);
  826                         DELAY(2);
  827                 }
  828                 VIAPM_OUTB(SMBHCMD, cmd);
  829                 VIAPM_OUTB(SMBHCTRL, SMBHCTRL_START | SMBHCTRL_BLOCK);
  830 
  831                 if ((error = viapm_wait(viapm)) != SMB_ENOERR)
  832                         goto error;
  833 
  834                 remain -= len;
  835         }
  836 
  837 error:
  838         VIAPM_DEBUG(printf("viapm: WRITEBLK to 0x%x, count=0x%x, cmd=0x%x, error=0x%x", slave, count, cmd, error));
  839 
  840         return (error);
  841 
  842 }
  843 
  844 static int
  845 viasmb_bread(device_t dev, u_char slave, char cmd, u_char count, char *buf)
  846 {
  847         struct viapm_softc *viapm = (struct viapm_softc *)device_get_softc(dev);
  848         u_char remain, len, i;
  849         int error = SMB_ENOERR;
  850 
  851         viapm_clear(viapm);
  852         if (viapm_busy(viapm))
  853                 return (EBUSY);
  854 
  855         remain = count;
  856         while (remain) {
  857                 VIAPM_OUTB(SMBHADDR, slave | LSB);
  858                 VIAPM_OUTB(SMBHCMD, cmd);
  859                 VIAPM_OUTB(SMBHCTRL, SMBHCTRL_START | SMBHCTRL_BLOCK);
  860 
  861                 if ((error = viapm_wait(viapm)) != SMB_ENOERR)
  862                         goto error;
  863 
  864                 len = VIAPM_INB(SMBHDATA0);
  865                 i = VIAPM_INB(SMBHCTRL);                /* reset counter */
  866 
  867                 len = min(len, remain);
  868 
  869                 /* read the 32-byte internal buffer */
  870                 for (i=0; i<len; i++) {
  871                         buf[count-remain+i] = VIAPM_INB(SMBHBLOCK);
  872                         DELAY(2);
  873                 }
  874 
  875                 remain -= len;
  876         }
  877 error:
  878         VIAPM_DEBUG(printf("viapm: READBLK to 0x%x, count=0x%x, cmd=0x%x, error=0x%x", slave, count, cmd, error));
  879 
  880         return (error);
  881 }
  882 
  883 static device_method_t viapm_methods[] = {
  884         /* device interface */
  885         DEVMETHOD(device_probe,         viapm_586b_probe),
  886         DEVMETHOD(device_attach,        viapm_586b_attach),
  887         DEVMETHOD(device_detach,        viapm_586b_detach),
  888 
  889         /* iicbb interface */
  890         DEVMETHOD(iicbb_callback,       viabb_callback),
  891         DEVMETHOD(iicbb_setlines,       viabb_setlines),
  892         DEVMETHOD(iicbb_getdataline,    viabb_getsda),
  893         DEVMETHOD(iicbb_reset,          viabb_reset),
  894 
  895         { 0, 0 }
  896 };
  897 
  898 static driver_t viapm_driver = {
  899         "viapm",
  900         viapm_methods,
  901         sizeof(struct viapm_softc),
  902 };
  903 
  904 static device_method_t viapropm_methods[] = {
  905         /* device interface */
  906         DEVMETHOD(device_probe,         viapm_pro_probe),
  907         DEVMETHOD(device_attach,        viapm_pro_attach),
  908         DEVMETHOD(device_detach,        viapm_pro_detach),
  909 
  910         /* smbus interface */
  911         DEVMETHOD(smbus_callback,       viasmb_callback),
  912         DEVMETHOD(smbus_quick,          viasmb_quick),
  913         DEVMETHOD(smbus_sendb,          viasmb_sendb),
  914         DEVMETHOD(smbus_recvb,          viasmb_recvb),
  915         DEVMETHOD(smbus_writeb,         viasmb_writeb),
  916         DEVMETHOD(smbus_readb,          viasmb_readb),
  917         DEVMETHOD(smbus_writew,         viasmb_writew),
  918         DEVMETHOD(smbus_readw,          viasmb_readw),
  919         DEVMETHOD(smbus_bwrite,         viasmb_bwrite),
  920         DEVMETHOD(smbus_bread,          viasmb_bread),
  921         
  922         { 0, 0 }
  923 };
  924 
  925 static driver_t viapropm_driver = {
  926         "viapropm",
  927         viapropm_methods,
  928         sizeof(struct viapm_softc),
  929 };
  930 
  931 DRIVER_MODULE(viapm, pci, viapm_driver, viapm_devclass, 0, 0);
  932 DRIVER_MODULE(viapropm, pci, viapropm_driver, viapropm_devclass, 0, 0);
  933 
  934 MODULE_DEPEND(viapm, iicbb, IICBB_MINVER, IICBB_PREFVER, IICBB_MAXVER);
  935 MODULE_DEPEND(viapropm, smbus, SMBUS_MINVER, SMBUS_PREFVER, SMBUS_MAXVER);
  936 MODULE_VERSION(viapm, 1);

Cache object: 5709cddd74cbdd50ab3032c32c44999d


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