svn commit: r273610 - head/sys/arm/broadcom/bcm2835

Luiz Otavio O Souza loos at FreeBSD.org
Fri Oct 24 22:06:23 UTC 2014


Author: loos
Date: Fri Oct 24 22:06:21 2014
New Revision: 273610
URL: https://svnweb.freebsd.org/changeset/base/273610

Log:
  Add an iicbus_reset() method to bcm2835_bsc.  While it is generally not
  used for kernel devices it is used by i2c(8).
  
  This fix the 'error: Device not configured' when i2c(8) tries to reset the
  controller, as an example:
  
  # i2c -r
  Resetting I2C controller on /dev/iic0: error: Device not configured
  
  For now use conservative settings for default i2c speeds.
  
  MFC after:	1 week

Modified:
  head/sys/arm/broadcom/bcm2835/bcm2835_bsc.c
  head/sys/arm/broadcom/bcm2835/bcm2835_bscvar.h

Modified: head/sys/arm/broadcom/bcm2835/bcm2835_bsc.c
==============================================================================
--- head/sys/arm/broadcom/bcm2835/bcm2835_bsc.c	Fri Oct 24 22:00:25 2014	(r273609)
+++ head/sys/arm/broadcom/bcm2835/bcm2835_bsc.c	Fri Oct 24 22:06:21 2014	(r273610)
@@ -210,6 +210,8 @@ static void
 bcm_bsc_reset(struct bcm_bsc_softc *sc)
 {
 
+	/* Enable the BSC Controller, disable interrupts. */
+	BCM_BSC_WRITE(sc, BCM_BSC_CTRL, BCM_BSC_CTRL_I2CEN);
 	/* Clear pending interrupts. */
 	BCM_BSC_WRITE(sc, BCM_BSC_STATUS, BCM_BSC_STATUS_CLKT |
 	    BCM_BSC_STATUS_ERR | BCM_BSC_STATUS_DONE);
@@ -302,7 +304,6 @@ bcm_bsc_attach(device_t dev)
 
 	/* Enable the BSC controller.  Flush the FIFO. */
 	BCM_BSC_LOCK(sc);
-	BCM_BSC_WRITE(sc, BCM_BSC_CTRL, BCM_BSC_CTRL_I2CEN);
 	bcm_bsc_reset(sc);
 	BCM_BSC_UNLOCK(sc);
 
@@ -351,9 +352,8 @@ bcm_bsc_intr(void *arg)
 	/* Check for errors. */
 	if (status & (BCM_BSC_STATUS_CLKT | BCM_BSC_STATUS_ERR)) {
 		/* Disable interrupts. */
-		BCM_BSC_WRITE(sc, BCM_BSC_CTRL, BCM_BSC_CTRL_I2CEN);
-		sc->sc_flags |= BCM_I2C_ERROR;
 		bcm_bsc_reset(sc);
+		sc->sc_flags |= BCM_I2C_ERROR;
 		wakeup(sc->sc_dev);
 		BCM_BSC_UNLOCK(sc);
 		return;
@@ -375,7 +375,6 @@ bcm_bsc_intr(void *arg)
 
 	if (status & BCM_BSC_STATUS_DONE) {
 		/* Disable interrupts. */
-		BCM_BSC_WRITE(sc, BCM_BSC_CTRL, BCM_BSC_CTRL_I2CEN);
 		bcm_bsc_reset(sc);
 		wakeup(sc->sc_dev);
 	}
@@ -459,6 +458,38 @@ bcm_bsc_transfer(device_t dev, struct ii
 	return (err);
 }
 
+static int
+bcm_bsc_iicbus_reset(device_t dev, u_char speed, u_char addr, u_char *oldaddr)
+{
+	struct bcm_bsc_softc *sc;
+	uint32_t freq;
+        
+	sc = device_get_softc(dev);
+	BCM_BSC_LOCK(sc);
+	bcm_bsc_reset(sc);
+	freq = 0;
+	switch (speed) {
+	case IIC_SLOW:
+		freq = BCM_BSC_SLOW;
+		break;
+	case IIC_FAST:
+		freq = BCM_BSC_FAST;
+		break;
+	case IIC_FASTEST:
+		freq = BCM_BSC_FASTEST;
+		break;
+	case IIC_UNKNOWN:
+	default:
+		/* Reuse last frequency. */
+		break;
+	}
+	if (freq != 0)
+		BCM_BSC_WRITE(sc, BCM_BSC_CLOCK, BCM_BSC_CORE_CLK / freq);
+	BCM_BSC_UNLOCK(sc);
+
+	return (IIC_ENOADDR);
+}
+
 static phandle_t
 bcm_bsc_get_node(device_t bus, device_t dev)
 {
@@ -474,6 +505,7 @@ static device_method_t bcm_bsc_methods[]
 	DEVMETHOD(device_detach,	bcm_bsc_detach),
 
 	/* iicbus interface */
+	DEVMETHOD(iicbus_reset,		bcm_bsc_iicbus_reset),
 	DEVMETHOD(iicbus_callback,	iicbus_null_callback),
 	DEVMETHOD(iicbus_transfer,	bcm_bsc_transfer),
 

Modified: head/sys/arm/broadcom/bcm2835/bcm2835_bscvar.h
==============================================================================
--- head/sys/arm/broadcom/bcm2835/bcm2835_bscvar.h	Fri Oct 24 22:00:25 2014	(r273609)
+++ head/sys/arm/broadcom/bcm2835/bcm2835_bscvar.h	Fri Oct 24 22:06:21 2014	(r273610)
@@ -56,6 +56,10 @@ struct bcm_bsc_softc {
 #define	BCM_I2C_READ		0x02
 #define	BCM_I2C_ERROR		0x04
 
+#define	BCM_BSC_SLOW		10000	/*  10 kHz. */
+#define	BCM_BSC_FAST		50000	/*  50 kHz. */
+#define	BCM_BSC_FASTEST		100000	/* 100 kHz. */
+
 #define	BCM_BSC_WRITE(_sc, _off, _val)		\
     bus_space_write_4(_sc->sc_bst, _sc->sc_bsh, _off, _val)
 #define	BCM_BSC_READ(_sc, _off)			\


More information about the svn-src-all mailing list