iicbus.c revision 129152
138774Snsouch/*-
293023Snsouch * Copyright (c) 1998, 2001 Nicolas Souchu
338774Snsouch * All rights reserved.
438774Snsouch *
538774Snsouch * Redistribution and use in source and binary forms, with or without
638774Snsouch * modification, are permitted provided that the following conditions
738774Snsouch * are met:
838774Snsouch * 1. Redistributions of source code must retain the above copyright
938774Snsouch *    notice, this list of conditions and the following disclaimer.
1038774Snsouch * 2. Redistributions in binary form must reproduce the above copyright
1138774Snsouch *    notice, this list of conditions and the following disclaimer in the
1238774Snsouch *    documentation and/or other materials provided with the distribution.
1338774Snsouch *
1438774Snsouch * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
1538774Snsouch * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1638774Snsouch * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1738774Snsouch * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
1838774Snsouch * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
1938774Snsouch * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2038774Snsouch * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2138774Snsouch * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2238774Snsouch * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2338774Snsouch * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2438774Snsouch * SUCH DAMAGE.
2538774Snsouch */
2638774Snsouch
27119418Sobrien#include <sys/cdefs.h>
28119418Sobrien__FBSDID("$FreeBSD: head/sys/dev/iicbus/iicbus.c 129152 2004-05-12 13:43:41Z joerg $");
29119418Sobrien
3038774Snsouch/*
3138774Snsouch * Autoconfiguration and support routines for the Philips serial I2C bus
3238774Snsouch */
3338774Snsouch
3438774Snsouch#include <sys/param.h>
3538774Snsouch#include <sys/systm.h>
3638774Snsouch#include <sys/kernel.h>
3738774Snsouch#include <sys/module.h>
3838774Snsouch#include <sys/bus.h>
3938774Snsouch
4038774Snsouch
4138774Snsouch#include <dev/iicbus/iiconf.h>
4238774Snsouch#include <dev/iicbus/iicbus.h>
4338774Snsouch
4438774Snsouch#include "iicbus_if.h"
4538774Snsouch
4638774Snsouch#define DEVTOIICBUS(dev) ((struct iicbus_device*)device_get_ivars(dev))
4738774Snsouch
4838774Snsouchstatic devclass_t iicbus_devclass;
4938774Snsouch
50129152Sjoerg/* See comments below for why auto-scanning is a bad idea. */
51129152Sjoerg#define SCAN_IICBUS 0
52129152Sjoerg
5338774Snsouch/*
5438774Snsouch * Device methods
5538774Snsouch */
5638774Snsouchstatic int iicbus_probe(device_t);
5738774Snsouchstatic int iicbus_attach(device_t);
5893023Snsouchstatic int iicbus_detach(device_t);
5993023Snsouchstatic int iicbus_add_child(device_t dev, int order, const char *name, int unit);
6038774Snsouch
6138774Snsouchstatic device_method_t iicbus_methods[] = {
6238774Snsouch        /* device interface */
6338774Snsouch        DEVMETHOD(device_probe,         iicbus_probe),
6438774Snsouch        DEVMETHOD(device_attach,        iicbus_attach),
6593023Snsouch        DEVMETHOD(device_detach,        iicbus_detach),
6638774Snsouch
6738774Snsouch        /* bus interface */
6893023Snsouch        DEVMETHOD(bus_add_child,	iicbus_add_child),
6993023Snsouch	DEVMETHOD(bus_driver_added,	bus_generic_driver_added),
7093023Snsouch        DEVMETHOD(bus_print_child,      bus_generic_print_child),
7138774Snsouch
7238774Snsouch        { 0, 0 }
7338774Snsouch};
7438774Snsouch
7538774Snsouchstatic driver_t iicbus_driver = {
7638774Snsouch        "iicbus",
7738774Snsouch        iicbus_methods,
7838774Snsouch        sizeof(struct iicbus_softc),
7938774Snsouch};
8038774Snsouch
8140782Snsouchstatic int
8240782Snsouchiicbus_probe(device_t dev)
8340782Snsouch{
8442442Snsouch	device_set_desc(dev, "Philips I2C bus");
8542442Snsouch
8640782Snsouch	return (0);
8740782Snsouch}
8840782Snsouch
89129152Sjoerg#if SCAN_IICBUS
9040782Snsouchstatic int
9140782Snsouchiic_probe_device(device_t dev, u_char addr)
9240782Snsouch{
9340782Snsouch	int count;
9440782Snsouch	char byte;
9540782Snsouch
9640782Snsouch	if ((addr & 1) == 0) {
9740782Snsouch		/* is device writable? */
9840782Snsouch		if (!iicbus_start(dev, (u_char)addr, 0)) {
9940782Snsouch			iicbus_stop(dev);
10040782Snsouch			return (1);
10140782Snsouch		}
10240782Snsouch	} else {
10340782Snsouch		/* is device readable? */
10440782Snsouch		if (!iicbus_block_read(dev, (u_char)addr, &byte, 1, &count))
10540782Snsouch			return (1);
10640782Snsouch	}
10740782Snsouch
10840782Snsouch	return (0);
10940782Snsouch}
11042442Snsouch#endif
11140782Snsouch
11238774Snsouch/*
11340782Snsouch * We add all the devices which we know about.
11440782Snsouch * The generic attach routine will attach them if they are alive.
11538774Snsouch */
11638774Snsouchstatic int
11740782Snsouchiicbus_attach(device_t dev)
11838774Snsouch{
119129152Sjoerg#if SCAN_IICBUS
120129152Sjoerg	unsigned char addr;
121129152Sjoerg#endif
122129152Sjoerg
12340782Snsouch	iicbus_reset(dev, IIC_FASTEST, 0, NULL);
12438774Snsouch
12542442Snsouch	/* device probing is meaningless since the bus is supposed to be
12642442Snsouch	 * hot-plug. Moreover, some I2C chips do not appreciate random
12742442Snsouch	 * accesses like stop after start to fast, reads for less than
12842442Snsouch	 * x bytes...
12942442Snsouch	 */
130129152Sjoerg#if SCAN_IICBUS
13140782Snsouch	printf("Probing for devices on iicbus%d:", device_get_unit(dev));
13238774Snsouch
13340782Snsouch	/* probe any devices */
134129152Sjoerg	for (addr = 16; addr < 240; addr++) {
13540782Snsouch		if (iic_probe_device(dev, (u_char)addr)) {
13640782Snsouch			printf(" <%x>", addr);
13740782Snsouch		}
13840782Snsouch	}
13940782Snsouch	printf("\n");
14042442Snsouch#endif
14193023Snsouch
14293023Snsouch	/* attach any known device */
14393023Snsouch	device_add_child(dev, NULL, -1);
14440782Snsouch
14538774Snsouch	bus_generic_attach(dev);
14638774Snsouch
14738774Snsouch        return (0);
14838774Snsouch}
14993023Snsouch
15093023Snsouchstatic int
15193023Snsouchiicbus_detach(device_t dev)
15293023Snsouch{
15393023Snsouch	iicbus_reset(dev, IIC_FASTEST, 0, NULL);
15493023Snsouch
15593023Snsouch	bus_generic_detach(dev);
15693023Snsouch
15793023Snsouch	return (0);
15893023Snsouch}
15993023Snsouch
16093023Snsouchstatic int
16193023Snsouchiicbus_add_child(device_t dev, int order, const char *name, int unit)
16293023Snsouch{
16393023Snsouch	device_add_child_ordered(dev, order, name, unit);
16438774Snsouch
16593023Snsouch	bus_generic_attach(dev);
16693023Snsouch
16793023Snsouch	return (0);
16893023Snsouch}
16993023Snsouch
17038774Snsouchint
17138774Snsouchiicbus_generic_intr(device_t dev, int event, char *buf)
17238774Snsouch{
17338774Snsouch	return (0);
17438774Snsouch}
17538774Snsouch
17640782Snsouchint
17740782Snsouchiicbus_null_callback(device_t dev, int index, caddr_t data)
17840782Snsouch{
17940782Snsouch	return (0);
18040782Snsouch}
18140782Snsouch
18240782Snsouchint
18340782Snsouchiicbus_null_repeated_start(device_t dev, u_char addr)
18440782Snsouch{
18540782Snsouch	return (IIC_ENOTSUPP);
18640782Snsouch}
18740782Snsouch
18838774SnsouchDRIVER_MODULE(iicbus, pcf, iicbus_driver, iicbus_devclass, 0, 0);
18940782SnsouchDRIVER_MODULE(iicbus, iicbb, iicbus_driver, iicbus_devclass, 0, 0);
19040782SnsouchDRIVER_MODULE(iicbus, bti2c, iicbus_driver, iicbus_devclass, 0, 0);
19193023SnsouchMODULE_VERSION(iicbus, IICBUS_MODVER);
192