Subject: kern/36745: Add spdmem device for I2C
To: None <kern-bug-people@netbsd.org, gnats-admin@netbsd.org,>
From: None <paul@whooppee.com>
List: netbsd-bugs
Date: 08/07/2007 13:00:01
>Number: 36745
>Category: kern
>Synopsis: Add spdmem device for I2C
>Confidential: no
>Severity: non-critical
>Priority: low
>Responsible: kern-bug-people
>State: open
>Class: change-request
>Submitter-Id: net
>Arrival-Date: Tue Aug 07 13:00:01 +0000 2007
>Originator: Paul Goyette
>Release: NetBSD 4.99.26 sources as of 2007-08-01 12:42:27 UTC
>Organization:
>Environment:
System: NetBSD quicky.whooppee.com 4.99.26 NetBSD 4.99.26 (QUICKY (ASUS A8N5X) 2007-08-01 12:42:27 UTC) #185: Wed Aug 1 06:09:48 PDT 2007 paul@quicky.whooppee.com:/usr/obj/objdir/amd64/sys/arch/amd64/compile/QUICKY amd64
Architecture: x86_64
Machine: amd64
>Description:
Add spdmem device for I2C busses. Driver doesn't do much, other
than identify the type of memory.
>How-To-Repeat:
>Fix:
Code originally provided by Nicolas Joly...
Index: i2c/files.i2c
===================================================================
RCS file: /cvsroot/src/sys/dev/i2c/files.i2c,v
retrieving revision 1.14
diff -u -p -r1.14 files.i2c
--- i2c/files.i2c 17 Jan 2007 23:33:23 -0000 1.14
+++ i2c/files.i2c 7 Aug 2007 11:47:03 -0000
@@ -106,3 +106,8 @@ file dev/i2c/pic16lc.c pic16lc needs-fl
device xbseeprom
attach xbseeprom at iic
file dev/i2c/xbseeprom.c xbseeprom
+
+# Memory Serial Presence Detect
+device spdmem
+attach spdmem at iic
+file dev/i2c/spdmem.c spdmem
/* $NetBSD$ */
/*
* Copyright (c) 2007 Nicolas Joly
+ * 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.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* 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 FOUNDATION 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.
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD$");
#include <sys/param.h>
#include <sys/device.h>
#include <dev/i2c/i2cvar.h>
#define SPDMEM_MEMTYPE 0x02
#define SPDMEM_MEMTYPE_EDO 0x02
#define SPDMEM_MEMTYPE_SDRAM 0x04
#define SPDMEM_MEMTYPE_DDRSDRAM 0x07
#define SPDMEM_MEMTYPE_DDR2SDRAM 0x08
struct spdmem_softc {
struct device sc_dev;
i2c_tag_t sc_tag;
i2c_addr_t sc_addr;
};
static int spdmem_match(struct device *, struct cfdata *, void *);
static void spdmem_attach(struct device *, struct device *, void *);
static uint8_t spdmem_read(struct spdmem_softc *, uint8_t);
CFATTACH_DECL(spdmem, sizeof(struct spdmem_softc),
spdmem_match, spdmem_attach, NULL, NULL);
static int
spdmem_match(struct device *parent, struct cfdata *match, void *aux)
{
struct i2c_attach_args *ia = aux;
struct spdmem_softc sc;
int cksum = 0;
uint8_t i, val;
if (ia->ia_addr < 0x50)
return 0;
sc.sc_tag = ia->ia_tag;
sc.sc_addr = ia->ia_addr;
for (i = 0; i < 63; i++)
cksum += spdmem_read(&sc, i);
val = spdmem_read(&sc, 63);
if (cksum == 0 || (cksum & 0xff) != val)
return 0;
return 1;
}
static void
spdmem_attach(struct device *parent, struct device *self, void *aux)
{
struct spdmem_softc *sc = device_private(self);
struct i2c_attach_args *ia = aux;
uint8_t val;
const char *type;
sc->sc_tag = ia->ia_tag;
sc->sc_addr = ia->ia_addr;
val = spdmem_read(sc, SPDMEM_MEMTYPE);
switch (val) {
case SPDMEM_MEMTYPE_EDO:
type = "EDO";
break;
case SPDMEM_MEMTYPE_SDRAM:
type = "SDRAM";
break;
case SPDMEM_MEMTYPE_DDRSDRAM:
type = "DDR SDRAM";
break;
case SPDMEM_MEMTYPE_DDR2SDRAM:
type = "DDR2 SDRAM";
break;
default:
aprint_error(": unknown (0x%02x) memory type\n", val);
return;
}
aprint_normal(": %s memory module\n", type);
return;
}
static uint8_t
spdmem_read(struct spdmem_softc *sc, uint8_t reg)
{
uint8_t val;
iic_acquire_bus(sc->sc_tag,0);
iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP, sc->sc_addr, ®, 1,
&val, 1, 0);
iic_release_bus(sc->sc_tag, 0);
return val;
}