iicbus.c revision 129778
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 129778 2004-05-27 13:29:09Z 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 */ 143129289Sjoerg device_add_child(dev, "ic", -1); 144129289Sjoerg device_add_child(dev, "iic", -1); 145129289Sjoerg device_add_child(dev, "iicsmb", -1); 14640782Snsouch 14738774Snsouch bus_generic_attach(dev); 14838774Snsouch 14938774Snsouch return (0); 15038774Snsouch} 15193023Snsouch 15293023Snsouchstatic int 15393023Snsouchiicbus_detach(device_t dev) 15493023Snsouch{ 15593023Snsouch iicbus_reset(dev, IIC_FASTEST, 0, NULL); 15693023Snsouch 15793023Snsouch bus_generic_detach(dev); 15893023Snsouch 15993023Snsouch return (0); 16093023Snsouch} 16193023Snsouch 16293023Snsouchstatic int 16393023Snsouchiicbus_add_child(device_t dev, int order, const char *name, int unit) 16493023Snsouch{ 16593023Snsouch device_add_child_ordered(dev, order, name, unit); 16638774Snsouch 16793023Snsouch bus_generic_attach(dev); 16893023Snsouch 16993023Snsouch return (0); 17093023Snsouch} 17193023Snsouch 17238774Snsouchint 17338774Snsouchiicbus_generic_intr(device_t dev, int event, char *buf) 17438774Snsouch{ 17538774Snsouch return (0); 17638774Snsouch} 17738774Snsouch 17840782Snsouchint 17940782Snsouchiicbus_null_callback(device_t dev, int index, caddr_t data) 18040782Snsouch{ 18140782Snsouch return (0); 18240782Snsouch} 18340782Snsouch 18440782Snsouchint 18540782Snsouchiicbus_null_repeated_start(device_t dev, u_char addr) 18640782Snsouch{ 18740782Snsouch return (IIC_ENOTSUPP); 18840782Snsouch} 18940782Snsouch 19038774SnsouchDRIVER_MODULE(iicbus, pcf, iicbus_driver, iicbus_devclass, 0, 0); 191129778SjoergDRIVER_MODULE(iicbus, envctrl, iicbus_driver, iicbus_devclass, 0, 0); 19240782SnsouchDRIVER_MODULE(iicbus, iicbb, iicbus_driver, iicbus_devclass, 0, 0); 19340782SnsouchDRIVER_MODULE(iicbus, bti2c, iicbus_driver, iicbus_devclass, 0, 0); 19493023SnsouchMODULE_VERSION(iicbus, IICBUS_MODVER); 195