lpbb is the official Philips parallel I2C interface. lpbb.c contains only
basic i/o functions, bit-banging mechanism is implemented by dev/iicbus/iicbb.c immio.c: some bootverbose logs to watch zip+ connect/disconnect process
This commit is contained in:
parent
04f89a63cb
commit
f7ce69c963
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=40783
@ -23,7 +23,7 @@
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $Id: immio.c,v 1.2 1998/09/20 14:41:54 nsouch Exp $
|
||||
* $Id: immio.c,v 1.3 1998/10/02 20:44:58 nsouch Exp $
|
||||
*
|
||||
*/
|
||||
|
||||
@ -286,9 +286,13 @@ imm_disconnect(struct vpoio_data *vpo, int *connected, int release_bus)
|
||||
|
||||
ppb_MS_microseq(&vpo->vpo_dev, cpp_microseq, &ret);
|
||||
|
||||
if ((s1 != (char)0xb8 || s2 != (char)0x18 || s3 != (char)0x38) &&
|
||||
connected)
|
||||
*connected = VP0_ECONNECT;
|
||||
if ((s1 != (char)0xb8 || s2 != (char)0x18 || s3 != (char)0x38)) {
|
||||
if (bootverbose)
|
||||
printf("imm%d: (disconnect) s1=0x%x s2=0x%x, s3=0x%x\n",
|
||||
vpo->vpo_unit, s1 & 0xff, s2 & 0xff, s3 & 0xff);
|
||||
if (connected)
|
||||
*connected = VP0_ECONNECT;
|
||||
}
|
||||
|
||||
if (release_bus)
|
||||
return (ppb_release_bus(&vpo->vpo_dev));
|
||||
@ -334,9 +338,13 @@ imm_connect(struct vpoio_data *vpo, int how, int *disconnected, int request_bus)
|
||||
|
||||
ppb_MS_microseq(&vpo->vpo_dev, cpp_microseq, &ret);
|
||||
|
||||
if ((s1 != (char)0xb8 || s2 != (char)0x18 || s3 != (char)0x30)
|
||||
&& disconnected)
|
||||
*disconnected = VP0_ECONNECT;
|
||||
if ((s1 != (char)0xb8 || s2 != (char)0x18 || s3 != (char)0x30)) {
|
||||
if (bootverbose)
|
||||
printf("imm%d: (connect) s1=0x%x s2=0x%x, s3=0x%x\n",
|
||||
vpo->vpo_unit, s1 & 0xff, s2 & 0xff, s3 & 0xff);
|
||||
if (disconnected)
|
||||
*disconnected = VP0_ECONNECT;
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
325
sys/dev/ppbus/lpbb.c
Normal file
325
sys/dev/ppbus/lpbb.c
Normal file
@ -0,0 +1,325 @@
|
||||
/*-
|
||||
* Copyright (c) 1998 Nicolas Souchu, Marc Bouget
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $Id$
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* I2C Bit-Banging over parallel port
|
||||
*
|
||||
* See the Official Philips interface description in lpbb(4)
|
||||
*/
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/module.h>
|
||||
#include <sys/bus.h>
|
||||
#include <sys/conf.h>
|
||||
#include <sys/buf.h>
|
||||
#include <sys/uio.h>
|
||||
#include <sys/malloc.h>
|
||||
|
||||
#include <machine/clock.h>
|
||||
|
||||
#include <dev/ppbus/ppbconf.h>
|
||||
|
||||
#include <dev/iicbus/iiconf.h>
|
||||
#include <dev/iicbus/iicbus.h>
|
||||
|
||||
#include "iicbb_if.h"
|
||||
|
||||
/* iicbus softc */
|
||||
struct lpbb_softc {
|
||||
|
||||
struct ppb_device lpbb_dev;
|
||||
};
|
||||
|
||||
static int lpbb_detect(struct lpbb_softc *);
|
||||
|
||||
static int lpbb_probe(device_t);
|
||||
static int lpbb_attach(device_t);
|
||||
static void lpbb_print_child(device_t, device_t);
|
||||
|
||||
static int lpbb_callback(device_t, int, caddr_t *);
|
||||
static void lpbb_setlines(device_t, int, int);
|
||||
static int lpbb_getdataline(device_t);
|
||||
static int lpbb_reset(device_t, u_char, u_char, u_char *);
|
||||
|
||||
static devclass_t lpbb_devclass;
|
||||
|
||||
static device_method_t lpbb_methods[] = {
|
||||
/* device interface */
|
||||
DEVMETHOD(device_probe, lpbb_probe),
|
||||
DEVMETHOD(device_attach, lpbb_attach),
|
||||
|
||||
/* bus interface */
|
||||
DEVMETHOD(bus_print_child, lpbb_print_child),
|
||||
|
||||
/* iicbb interface */
|
||||
DEVMETHOD(iicbb_callback, lpbb_callback),
|
||||
DEVMETHOD(iicbb_setlines, lpbb_setlines),
|
||||
DEVMETHOD(iicbb_getdataline, lpbb_getdataline),
|
||||
DEVMETHOD(iicbb_reset, lpbb_reset),
|
||||
|
||||
{ 0, 0 }
|
||||
};
|
||||
|
||||
static driver_t lpbb_driver = {
|
||||
"lpbb",
|
||||
lpbb_methods,
|
||||
DRIVER_TYPE_MISC,
|
||||
sizeof(struct lpbb_softc),
|
||||
};
|
||||
|
||||
/*
|
||||
* Make ourselves visible as a ppbus driver
|
||||
*/
|
||||
static struct ppb_device *lpbb_ppb_probe(struct ppb_data *ppb);
|
||||
static int lpbb_ppb_attach(struct ppb_device *dev);
|
||||
|
||||
#define MAXLPBB 8 /* XXX not much better! */
|
||||
static struct lpbb_softc *lpbbdata[MAXLPBB];
|
||||
static int nlpbb = 0;
|
||||
|
||||
#ifdef KERNEL
|
||||
|
||||
static struct ppb_driver lpbbdriver = {
|
||||
lpbb_ppb_probe, lpbb_ppb_attach, "lpbb"
|
||||
};
|
||||
DATA_SET(ppbdriver_set, lpbbdriver);
|
||||
|
||||
#endif /* KERNEL */
|
||||
|
||||
static int
|
||||
lpbb_probe(device_t dev)
|
||||
{
|
||||
struct lpbb_softc *sc = lpbbdata[device_get_unit(dev)];
|
||||
struct lpbb_softc *scdst = (struct lpbb_softc *)device_get_softc(dev);
|
||||
|
||||
/* XXX copy softc. Yet, ppbus device is sc->lpbb_dev, but will be
|
||||
* dev->parent when ppbus will be ported to the new bus architecture */
|
||||
bcopy(sc, scdst, sizeof(struct lpbb_softc));
|
||||
|
||||
device_set_desc(dev, "parallel I2C bit-banging interface");
|
||||
|
||||
/* probe done by ppbus initialization */
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
lpbb_attach(device_t dev)
|
||||
{
|
||||
struct lpbb_softc *sc = (struct lpbb_softc *)device_get_softc(dev);
|
||||
device_t bitbang, iicbus;
|
||||
|
||||
/* add generic bit-banging code */
|
||||
bitbang = device_add_child(dev, "iicbb", -1, NULL);
|
||||
|
||||
/* add the iicbus to the tree */
|
||||
iicbus = iicbus_alloc_bus(bitbang);
|
||||
|
||||
device_probe_and_attach(bitbang);
|
||||
|
||||
/* XXX should be in iicbb_attach! */
|
||||
device_probe_and_attach(iicbus);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* lppbb_ppb_probe()
|
||||
*/
|
||||
static struct ppb_device *
|
||||
lpbb_ppb_probe(struct ppb_data *ppb)
|
||||
{
|
||||
struct lpbb_softc *sc;
|
||||
|
||||
sc = (struct lpbb_softc *) malloc(sizeof(struct lpbb_softc),
|
||||
M_TEMP, M_NOWAIT);
|
||||
if (!sc) {
|
||||
printf("lpbb: cannot malloc!\n");
|
||||
return (0);
|
||||
}
|
||||
bzero(sc, sizeof(struct lpbb_softc));
|
||||
|
||||
lpbbdata[nlpbb] = sc;
|
||||
|
||||
/*
|
||||
* ppbus dependent initialisation.
|
||||
*/
|
||||
sc->lpbb_dev.id_unit = nlpbb;
|
||||
sc->lpbb_dev.name = lpbbdriver.name;
|
||||
sc->lpbb_dev.ppb = ppb;
|
||||
sc->lpbb_dev.intr = 0;
|
||||
|
||||
if (!lpbb_detect(sc)) {
|
||||
free(sc, M_TEMP);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
/* Ok, go to next device on next probe */
|
||||
nlpbb ++;
|
||||
|
||||
/* XXX wrong according to new bus architecture. ppbus needs to be
|
||||
* ported
|
||||
*/
|
||||
return (&sc->lpbb_dev);
|
||||
}
|
||||
|
||||
static int
|
||||
lpbb_ppb_attach(struct ppb_device *dev)
|
||||
{
|
||||
/* add the parallel port I2C interface to the bus tree */
|
||||
if (!device_add_child(root_bus, "lpbb", dev->id_unit, NULL))
|
||||
return (0);
|
||||
|
||||
return (1);
|
||||
}
|
||||
|
||||
static int
|
||||
lpbb_callback(device_t dev, int index, caddr_t *data)
|
||||
{
|
||||
struct lpbb_softc *sc = (struct lpbb_softc *)device_get_softc(dev);
|
||||
int error = 0;
|
||||
int how;
|
||||
|
||||
switch (index) {
|
||||
case IIC_REQUEST_BUS:
|
||||
/* request the ppbus */
|
||||
how = *(int *)data;
|
||||
error = ppb_request_bus(&sc->lpbb_dev, how);
|
||||
break;
|
||||
|
||||
case IIC_RELEASE_BUS:
|
||||
/* release the ppbus */
|
||||
error = ppb_release_bus(&sc->lpbb_dev);
|
||||
break;
|
||||
|
||||
default:
|
||||
error = EINVAL;
|
||||
}
|
||||
|
||||
return (error);
|
||||
}
|
||||
|
||||
#define SDA_out 0x80
|
||||
#define SCL_out 0x08
|
||||
#define SDA_in 0x80
|
||||
#define SCL_in 0x08
|
||||
#define ALIM 0x20
|
||||
#define I2CKEY 0x50
|
||||
|
||||
static int getSDA(struct lpbb_softc *sc)
|
||||
{
|
||||
if((ppb_rstr(&sc->lpbb_dev)&SDA_in)==SDA_in)
|
||||
return 1;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int getSCL(struct lpbb_softc *sc)
|
||||
{
|
||||
if((ppb_rstr(&sc->lpbb_dev)&SCL_in)==SCL_in)
|
||||
return 1;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void setSDA(struct lpbb_softc *sc, char val)
|
||||
{
|
||||
if(val==0)
|
||||
ppb_wdtr(&sc->lpbb_dev, (u_char)SDA_out);
|
||||
else
|
||||
ppb_wdtr(&sc->lpbb_dev, (u_char)~SDA_out);
|
||||
}
|
||||
|
||||
static void setSCL(struct lpbb_softc *sc, unsigned char val)
|
||||
{
|
||||
if(val==0)
|
||||
ppb_wctr(&sc->lpbb_dev, (u_char)(ppb_rctr(&sc->lpbb_dev)&~SCL_out));
|
||||
else
|
||||
ppb_wctr(&sc->lpbb_dev, (u_char)(ppb_rctr(&sc->lpbb_dev)|SCL_out));
|
||||
}
|
||||
|
||||
static int lpbb_detect(struct lpbb_softc *sc)
|
||||
{
|
||||
if (ppb_request_bus(&sc->lpbb_dev, PPB_DONTWAIT)) {
|
||||
printf("lpbb: can't allocate ppbus\n");
|
||||
return (0);
|
||||
}
|
||||
|
||||
/* reset bus */
|
||||
setSDA(sc, 1);
|
||||
setSCL(sc, 1);
|
||||
|
||||
if ((ppb_rstr(&sc->lpbb_dev) & I2CKEY) ||
|
||||
((ppb_rstr(&sc->lpbb_dev) & ALIM) != ALIM))
|
||||
return (0);
|
||||
|
||||
ppb_release_bus(&sc->lpbb_dev);
|
||||
|
||||
return (1);
|
||||
}
|
||||
|
||||
static int
|
||||
lpbb_reset(device_t dev, u_char speed, u_char addr, u_char * oldaddr)
|
||||
{
|
||||
struct lpbb_softc *sc = (struct lpbb_softc *)device_get_softc(dev);
|
||||
|
||||
/* reset bus */
|
||||
setSDA(sc, 1);
|
||||
setSCL(sc, 1);
|
||||
|
||||
return (IIC_ENOADDR);
|
||||
}
|
||||
|
||||
static void
|
||||
lpbb_setlines(device_t dev, int ctrl, int data)
|
||||
{
|
||||
struct lpbb_softc *sc = (struct lpbb_softc *)device_get_softc(dev);
|
||||
|
||||
setSCL(sc, ctrl);
|
||||
setSDA(sc, data);
|
||||
}
|
||||
|
||||
static int
|
||||
lpbb_getdataline(device_t dev)
|
||||
{
|
||||
struct lpbb_softc *sc = (struct lpbb_softc *)device_get_softc(dev);
|
||||
|
||||
return (getSDA(sc));
|
||||
}
|
||||
|
||||
static void
|
||||
lpbb_print_child(device_t bus, device_t dev)
|
||||
{
|
||||
printf(" on %s%d", device_get_name(bus), device_get_unit(bus));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
DRIVER_MODULE(lpbb, root, lpbb_driver, lpbb_devclass, 0, 0);
|
Loading…
Reference in New Issue
Block a user